[Libsysio-commit] HEAD: libsysio/src fcntl.c lseek.c
Brought to you by:
lward
From: Lee W. <lw...@us...> - 2005-10-28 17:59:40
|
Update of /cvsroot/libsysio/libsysio/src In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv23911/src Modified Files: fcntl.c lseek.c Log Message: Fixed to properly support fcntl locking with relative offsets. Index: fcntl.c =================================================================== RCS file: /cvsroot/libsysio/libsysio/src/fcntl.c,v retrieving revision 1.22 retrieving revision 1.23 diff -u -w -b -B -p -r1.22 -r1.23 --- fcntl.c 14 Oct 2004 14:59:29 -0000 1.22 +++ fcntl.c 28 Oct 2005 17:59:31 -0000 1.23 @@ -9,7 +9,7 @@ * terms of the GNU Lesser General Public License * (see cit/LGPL or http://www.gnu.org/licenses/lgpl.html) * - * Cplant(TM) Copyright 1998-2003 Sandia Corporation. + * Cplant(TM) Copyright 1998-2005 Sandia Corporation. * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive * license for use of this work by or on behalf of the US Government. * Export of this program may require a license from the United States @@ -41,8 +41,11 @@ * le...@sa... */ +#include <string.h> #include <unistd.h> +#include <stdlib.h> #include <errno.h> +#include <assert.h> #include <sys/types.h> #include <fcntl.h> #include <sys/queue.h> @@ -56,9 +59,11 @@ #ifdef HAVE_LUSTRE_HACK #include <syscall.h> #include <native.h> +#endif +#ifdef HAVE_LUSTRE_HACK static int -_sysio_fcntl(int fd, int cmd, va_list ap, int *rtn) +_sysio_lustre_fcntl(int fd, int cmd, va_list ap, int *rtn) { long arg = va_arg(ap, long); @@ -67,13 +72,92 @@ _sysio_fcntl(int fd, int cmd, va_list ap } #endif -int -SYSIO_INTERFACE_NAME(fcntl)(int fd, int cmd, ...) +static int +_sysio_fcntl_raw_call(struct inode *ino, int *r, int cmd, ...) +{ + va_list ap; + int err; + + va_start(ap, cmd); + err = ino->i_ops.inop_fcntl(ino, cmd, ap, r); + va_end(ap); + return err; +} + +/* + * Convert offsets to absolute, when appropriate, and call appropriate driver + * to complete the fcntl lock function. If successful, convert + * returned values back to appropriate form. + */ +static int +_sysio_fcntl_lock(struct file *fil, int cmd, struct _SYSIO_FLOCK *fl) +{ + struct _SYSIO_FLOCK flock; + _SYSIO_OFF_T pos; + int err; + int rtn; + + /* + * The drivers will not have a clue as to the + * current position of the file pointer. We need to + * convert relative whence values to absolute + * file adresses for them, then. + */ + flock = *fl; + switch (flock.l_whence) { + case SEEK_SET: + /* + * At least parameter check this one, too. + */ + case SEEK_CUR: + case SEEK_END: + pos = + _sysio_lseek_prepare(fil, + flock.l_start, + flock.l_whence, + _SEEK_MAX(fil)); + if (pos < 0) + return (int )pos; + flock.l_start = pos; + flock.l_whence = SEEK_SET; + break; + default: + return -EINVAL; + } + err = + _sysio_fcntl_raw_call(fil->f_ino, &rtn, cmd, &flock); + if (err) + return err; + /* + * Ugh, convert back to relative form. + */ + switch (fl->l_whence) { + case SEEK_SET: + break; + case SEEK_CUR: + fl->l_start = flock.l_start; + fl->l_start -= fil->f_pos; + break; + case SEEK_END: + fl->l_start = flock.l_start; + fl->l_start -= + fil->f_ino->i_stbuf.st_size; + break; + default: + abort(); + } + /* + * Return success. + */ + return 0; +} + +static int +_sysio_vfcntl(int fd, int cmd, va_list ap) { int err; int rtn; struct file *fil; - va_list ap; SYSIO_INTERFACE_DISPLAY_BLOCK; SYSIO_INTERFACE_ENTER; @@ -81,12 +165,9 @@ SYSIO_INTERFACE_NAME(fcntl)(int fd, int fil = _sysio_fd_find(fd); if (!fil) { #ifdef HAVE_LUSTRE_HACK - va_start(ap, cmd); - err = _sysio_fcntl(fd, cmd, ap, &rtn); - va_end(ap); + err = _sysio_lustre_fcntl(fd, cmd, ap, &rtn); goto out; #else - rtn = -1; err = -EBADF; goto out; @@ -99,9 +180,7 @@ SYSIO_INTERFACE_NAME(fcntl)(int fd, int { long newfd; - va_start(ap, cmd); newfd = va_arg(ap, long); - va_end(ap); if (newfd != (int )newfd || newfd < 0) { rtn = -1; err = -EBADF; @@ -114,10 +193,77 @@ SYSIO_INTERFACE_NAME(fcntl)(int fd, int } } break; + case F_GETLK: + case F_SETLK: + case F_SETLKW: + { + struct intnl_stat buf; + struct flock *fl; +#if _LARGEFILE64_SOURCE + struct _SYSIO_FLOCK flock64; +#endif + + /* + * Refresh the cached attributes. + */ + err = + fil->f_ino->i_ops.inop_getattr(NULL, + fil->f_ino, + &buf); + if (err) { + rtn = -1; + break; + } + /* + * Copy args to a temp and normalize. + */ + fl = va_arg(ap, struct flock *); +#if _LARGEFILE64_SOURCE + flock64.l_type = fl->l_type; + flock64.l_whence = fl->l_whence; + flock64.l_start = fl->l_start; + flock64.l_len = fl->l_len; + flock64.l_pid = fl->l_pid; + err = _sysio_fcntl_lock(fil, cmd, &flock64); +#else + err = _sysio_fcntl_lock(fil, cmd, fl); +#endif + if (err < 0) { + rtn = -1; + break; + } +#if _LARGEFILE64_SOURCE + /* + * Copy back. Note that the fcntl_lock call + * should have ensured that no overflow was possible. + */ + fl->l_type = flock64.l_type; + fl->l_whence = flock64.l_whence; + fl->l_start = flock64.l_start; + assert(fl->l_start == flock64.l_start); + fl->l_len = flock64.l_len; + assert(fl->l_len == flock64.l_len); + fl->l_pid = flock64.l_pid; +#endif + rtn = 0; + } + break; +#if _LARGEFILE64_SOURCE + case F_GETLK64: + case F_SETLK64: + case F_SETLKW64: + { + struct flock64 *fl64; + + fl64 = va_arg(ap, struct flock64 *); + err = _sysio_fcntl_lock(fil, cmd, fl64); + if (err) + rtn = -1; + } + break; +#endif default: - va_start(ap, cmd); err = fil->f_ino->i_ops.inop_fcntl(fil->f_ino, cmd, ap, &rtn); - va_end(ap); break; } @@ -125,6 +271,21 @@ out: SYSIO_INTERFACE_RETURN(rtn, err); } +int +SYSIO_INTERFACE_NAME(fcntl)(int fd, int cmd, ...) +{ + va_list ap; + int err; + + va_start(ap, cmd); + err = _sysio_vfcntl(fd, cmd, ap); + va_end(ap); + return err; +} + +sysio_sym_weak_alias(SYSIO_INTERFACE_NAME(fcntl), + SYSIO_INTERFACE_NAME(fcntl64)) + #ifdef __GLIBC__ #undef __fcntl sysio_sym_weak_alias(SYSIO_INTERFACE_NAME(fcntl), Index: lseek.c =================================================================== RCS file: /cvsroot/libsysio/libsysio/src/lseek.c,v retrieving revision 1.26 retrieving revision 1.27 diff -u -w -b -B -p -r1.26 -r1.27 --- lseek.c 2 Aug 2005 21:57:09 -0000 1.26 +++ lseek.c 28 Oct 2005 17:59:31 -0000 1.27 @@ -9,7 +9,7 @@ * terms of the GNU Lesser General Public License * (see cit/LGPL or http://www.gnu.org/licenses/lgpl.html) * - * Cplant(TM) Copyright 1998-2003 Sandia Corporation. + * Cplant(TM) Copyright 1998-2005 Sandia Corporation. * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive * license for use of this work by or on behalf of the US Government. * Export of this program may require a license from the United States @@ -55,24 +55,8 @@ #include "sysio-symbols.h" -/* - * Test whether large file support on this file. - */ -#ifdef O_LARGEFILE -#define _SEEK_MAX_TEST(fil) \ - ((fil)->f_flags & O_LARGEFILE) -#else -#define _SEEK_MAX_TEST(fil) \ - (1) -#endif -/* - * Return max seek value for this file. - */ -#define _SEEK_MAX(fil) \ - (_SEEK_MAX_TEST(fil) ? _SYSIO_OFF_T_MAX : LONG_MAX) - -static _SYSIO_OFF_T -_sysio_lseek(struct file *fil, +_SYSIO_OFF_T +_sysio_lseek_prepare(struct file *fil, _SYSIO_OFF_T offset, int whence, _SYSIO_OFF_T max) @@ -116,6 +100,20 @@ _sysio_lseek(struct file *fil, return -EINVAL; if (pos >= max) return -EOVERFLOW; + return pos; +} + +static _SYSIO_OFF_T +_sysio_lseek(struct file *fil, + _SYSIO_OFF_T offset, + int whence, + _SYSIO_OFF_T max) +{ + _SYSIO_OFF_T pos; + + pos = _sysio_lseek_prepare(fil, offset, whence, max); + if (pos < 0) + return pos; pos = (fil->f_ino->i_ops.inop_pos)(fil->f_ino, pos); if (pos < 0) return pos; |