diff options
| author | vk210190 <none@none> | 2008-03-17 02:50:29 -0700 |
|---|---|---|
| committer | vk210190 <none@none> | 2008-03-17 02:50:29 -0700 |
| commit | 861d78e4c6cbc13ae7d45c5d1d2cb5acf0b408f7 (patch) | |
| tree | b755a077f6b726db3da613d82a542c7b6073fc22 /usr/src | |
| parent | 94cf82d0ee8fe71ca5efd060d6241bf36e66fee7 (diff) | |
| download | illumos-joyent-861d78e4c6cbc13ae7d45c5d1d2cb5acf0b408f7.tar.gz | |
6661506 LTP bug : pwrite04 fails because O_APPEND flag is not handled in similar way in Solaris and Linux
Diffstat (limited to 'usr/src')
| -rw-r--r-- | usr/src/lib/brand/lx/lx_brand/common/iovec.c | 37 | ||||
| -rw-r--r-- | usr/src/lib/brand/lx/lx_brand/common/lx_brand.c | 4 | ||||
| -rw-r--r-- | usr/src/lib/brand/lx/lx_brand/sys/lx_syscall.h | 3 |
3 files changed, 40 insertions, 4 deletions
diff --git a/usr/src/lib/brand/lx/lx_brand/common/iovec.c b/usr/src/lib/brand/lx/lx_brand/common/iovec.c index c9b48fb173..49af88d22e 100644 --- a/usr/src/lib/brand/lx/lx_brand/common/iovec.c +++ b/usr/src/lib/brand/lx/lx_brand/common/iovec.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -88,6 +88,41 @@ lx_pread64(uintptr_t p1, uintptr_t p2, uintptr_t p3, uintptr_t p4, uintptr_t p5) } /* + * On Linux, the pwrite(2) system call behaves identically to Solaris except + * in the case of the file being opened with O_APPEND. In that case Linux's + * pwrite(2) ignores the offset parameter and instead appends the data to the + * file without modifying the current seek pointer. + */ +int +lx_pwrite64(uintptr_t p1, uintptr_t p2, uintptr_t p3, uintptr_t p4, + uintptr_t p5) +{ + int fd = (int)p1; + void *buf = (void *)p2; + size_t nbyte = (size_t)p3; + uintptr_t off_lo = p4; + uintptr_t off_hi = p5; + ssize_t ret; + int rval; + struct stat64 statbuf; + + if ((rval = fcntl(fd, F_GETFL, 0)) < 0) + return (-errno); + + if (!(rval & O_APPEND)) { + ret = pwrite64(fd, buf, nbyte, + (off64_t)LX_32TO64(off_lo, off_hi)); + } else if ((ret = fstat64(fd, &statbuf)) == 0) { + ret = pwrite64(fd, buf, nbyte, statbuf.st_size); + } + + if (ret < 0) + return (-errno); + + return (ret); +} + +/* * Implementation of Linux readv() and writev() system calls. * * The Linux system calls differ from the Solaris system calls in a few key diff --git a/usr/src/lib/brand/lx/lx_brand/common/lx_brand.c b/usr/src/lib/brand/lx/lx_brand/common/lx_brand.c index 03eaff46bc..d9534848d5 100644 --- a/usr/src/lib/brand/lx/lx_brand/common/lx_brand.c +++ b/usr/src/lib/brand/lx/lx_brand/common/lx_brand.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -1158,7 +1158,7 @@ static struct lx_sysent sysents[] = { {"sigqueueinfo", NULL, NOSYS_UNDOC, 0}, /* 178 */ {"rt_sigsuspend", lx_rt_sigsuspend, 0, 2}, /* 179 */ {"pread64", lx_pread64, 0, 5}, /* 180 */ - {"pwrite64", pwrite64, SYS_PASSTHRU, 5}, /* 181 */ + {"pwrite64", lx_pwrite64, 0, 5}, /* 181 */ {"chown16", lx_chown16, 0, 3}, /* 182 */ {"getcwd", lx_getcwd, 0, 2}, /* 183 */ {"capget", NULL, NOSYS_NO_EQUIV, 0}, /* 184 */ diff --git a/usr/src/lib/brand/lx/lx_brand/sys/lx_syscall.h b/usr/src/lib/brand/lx/lx_brand/sys/lx_syscall.h index 5c52b1acec..fde32fe7bc 100644 --- a/usr/src/lib/brand/lx/lx_brand/sys/lx_syscall.h +++ b/usr/src/lib/brand/lx/lx_brand/sys/lx_syscall.h @@ -20,7 +20,7 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -62,6 +62,7 @@ extern int lx_read(uintptr_t, uintptr_t, uintptr_t); extern int lx_readv(uintptr_t, uintptr_t, uintptr_t); extern int lx_writev(uintptr_t, uintptr_t, uintptr_t); extern int lx_pread64(uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t); +extern int lx_pwrite64(uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t); extern int lx_socketcall(uintptr_t, uintptr_t); extern int lx_select(uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t); |
