diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 1e67bc4e6..dbeae5a47 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,19 @@ +2008-04-01 Corinna Vinschen + + Throughout, call fcntl64 instead of fcntl or fcntl_worker. + * fcntl.cc (fcntl_worker): Remove. + (fcntl64): Add fault handler. Move fcntl_worker stuff here. Add case + for locking and call fhandler's lock method directly. Make sure that + F_FLOCK flag isn't set in lock call. + (_fcntl): Add fault handler. + * fhandler.cc (fhandler_base::fcntl): Drop lock cases. + * flock.cc (flock): Add fault handler. Simplify code. Call fhandlers + lock method directly instead of fcntl_worker. Add debug output. + (lockf): Add fault handler. Call fhandlers lock method directly + instead of fcntl_worker. Add debug output. + * winsup.h (fcntl_worker): Drop declaration. + (fcntl64): Declare. + 2008-03-31 Corinna Vinschen * smallprint.cc (__small_vswprintf): Fix uninitialized usage of `w'. diff --git a/winsup/cygwin/fcntl.cc b/winsup/cygwin/fcntl.cc index f9a023ec4..7c2a218ff 100644 --- a/winsup/cygwin/fcntl.cc +++ b/winsup/cygwin/fcntl.cc @@ -20,10 +20,12 @@ details. */ #include "thread.h" #include "cygtls.h" -int -fcntl_worker (int fd, int cmd, void *arg) +extern "C" int +fcntl64 (int fd, int cmd, ...) { - int res; + int res = -1; + void *arg = NULL; + va_list args; myfault efault; if (efault.faulted (EFAULT)) @@ -31,29 +33,33 @@ fcntl_worker (int fd, int cmd, void *arg) cygheap_fdget cfd (fd, true); if (cfd < 0) - { - res = -1; - goto done; - } - if (cmd != F_DUPFD) - res = cfd->fcntl (cmd, arg); - else - res = dup2 (fd, cygheap_fdnew (((int) arg) - 1)); -done: - syscall_printf ("%d = fcntl (%d, %d, %p)", res, fd, cmd, arg); - return res; -} - -extern "C" int -fcntl64 (int fd, int cmd, ...) -{ - void *arg = NULL; - va_list args; + goto done; va_start (args, cmd); arg = va_arg (args, void *); va_end (args); - return fcntl_worker (fd, cmd, arg); + + switch (cmd) + { + case F_DUPFD: + res = dup2 (fd, cygheap_fdnew (((int) arg) - 1)); + break; + case F_GETLK: + case F_SETLK: + case F_SETLKW: + { + struct __flock64 *fl = (struct __flock64 *) arg; + fl->l_type &= F_RDLCK | F_WRLCK | F_UNLCK; + res = cfd->lock (cmd, fl); + } + break; + default: + res = cfd->fcntl (cmd, arg); + break; + } +done: + syscall_printf ("%d = fcntl (%d, %d, %p)", res, fd, cmd, arg); + return res; } extern "C" int @@ -64,6 +70,10 @@ _fcntl (int fd, int cmd, ...) struct __flock32 *src = NULL; struct __flock64 dst; + myfault efault; + if (efault.faulted (EFAULT)) + return -1; + va_start (args, cmd); arg = va_arg (args, void *); va_end (args); @@ -77,7 +87,7 @@ _fcntl (int fd, int cmd, ...) dst.l_pid = src->l_pid; arg = &dst; } - int res = fcntl_worker (fd, cmd, arg); + int res = fcntl64 (fd, cmd, arg); if (cmd == F_GETLK) { src->l_type = dst.l_type; diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc index 8513ab347..b3f347749 100644 --- a/winsup/cygwin/fhandler.cc +++ b/winsup/cygwin/fhandler.cc @@ -1178,11 +1178,6 @@ int fhandler_base::fcntl (int cmd, void *arg) } res = 0; break; - case F_GETLK: - case F_SETLK: - case F_SETLKW: - res = lock (cmd, (struct __flock64 *) arg); - break; default: set_errno (EINVAL); res = -1; diff --git a/winsup/cygwin/flock.cc b/winsup/cygwin/flock.cc index e09be2ed5..407400812 100644 --- a/winsup/cygwin/flock.cc +++ b/winsup/cygwin/flock.cc @@ -58,7 +58,7 @@ * $RH: flock.c,v 1.2 2000/08/23 17:07:00 nalin Exp $ */ -/* The lockf function has been taken from FreeBSD with the following +/* The lockf function is based upon FreeBSD sources with the following * copyright. * * Copyright (c) 1997 The NetBSD Foundation, Inc. @@ -835,8 +835,8 @@ fhandler_disk_file::lock (int a_op, struct __flock64 *fl) } need_fork_fixup (true); - /* Unlock the fd table which has been locked in fcntl_worker, otherwise - a blocking F_SETLKW never wakes up on a signal. */ + /* Unlock the fd table which has been locked in fcntl_worker/lock_worker, + otherwise a blocking F_SETLKW never wakes up on a signal. */ cygheap->fdtab.unlock (); lockf_t **head = &node->i_lockf; @@ -1495,68 +1495,59 @@ lf_wakelock (lockf_t *listhead, HANDLE fhdl) listhead->del_lock_obj (fhdl, true); } -int +extern "C" int flock (int fd, int operation) { - int i, cmd; - struct __flock64 l = { 0, 0, 0, 0, 0 }; - if (operation & LOCK_NB) - { - cmd = F_SETLK; - } - else - { - cmd = F_SETLKW; - } - l.l_whence = SEEK_SET; + int res = -1; + int cmd; + struct __flock64 fl = { 0, SEEK_SET, 0, 0, 0 }; + + myfault efault; + if (efault.faulted (EFAULT)) + return -1; + + cygheap_fdget cfd (fd, true); + if (cfd < 0) + goto done; + + cmd = (operation & LOCK_NB) ? F_SETLK : F_SETLKW; switch (operation & (~LOCK_NB)) { case LOCK_EX: - l.l_type = F_WRLCK | F_FLOCK; - i = fcntl_worker (fd, cmd, &l); - if (i == -1) - { - if ((get_errno () == EAGAIN) || (get_errno () == EACCES)) - { - set_errno (EWOULDBLOCK); - } - } + fl.l_type = F_WRLCK | F_FLOCK; break; case LOCK_SH: - l.l_type = F_RDLCK | F_FLOCK; - i = fcntl_worker (fd, cmd, &l); - if (i == -1) - { - if ((get_errno () == EAGAIN) || (get_errno () == EACCES)) - { - set_errno (EWOULDBLOCK); - } - } + fl.l_type = F_RDLCK | F_FLOCK; break; case LOCK_UN: - l.l_type = F_UNLCK | F_FLOCK; - i = fcntl_worker (fd, cmd, &l); - if (i == -1) - { - if ((get_errno () == EAGAIN) || (get_errno () == EACCES)) - { - set_errno (EWOULDBLOCK); - } - } + fl.l_type = F_UNLCK | F_FLOCK; break; default: - i = -1; set_errno (EINVAL); - break; + goto done; } - return i; + res = cfd->lock (cmd, &fl); + if (res == -1 && (get_errno () == EAGAIN) || (get_errno () == EACCES)) + set_errno (EWOULDBLOCK); +done: + syscall_printf ("%d = flock (%d, %d)", res, fd, operation); + return res; } extern "C" int lockf (int filedes, int function, _off64_t size) { - struct flock fl; + int res = -1; int cmd; + struct __flock64 fl; + + myfault efault; + if (efault.faulted (EFAULT)) + return -1; + + cygheap_fdget cfd (filedes, true); + if (cfd < 0) + goto done; fl.l_start = 0; fl.l_len = size; @@ -1578,18 +1569,21 @@ lockf (int filedes, int function, _off64_t size) break; case F_TEST: fl.l_type = F_WRLCK; - if (fcntl_worker (filedes, F_GETLK, &fl) == -1) - return -1; + if (cfd->lock (F_GETLK, &fl) == -1) + goto done; if (fl.l_type == F_UNLCK || fl.l_pid == getpid ()) - return 0; - errno = EAGAIN; - return -1; + res = 0; + else + errno = EAGAIN; + goto done; /* NOTREACHED */ default: errno = EINVAL; - return -1; + goto done; /* NOTREACHED */ } - - return fcntl_worker (filedes, cmd, &fl); + res = cfd->lock (cmd, &fl); +done: + syscall_printf ("%d = lockf (%d, %d, %D)", res, filedes, function, size); + return res; } diff --git a/winsup/cygwin/libc/minires.c b/winsup/cygwin/libc/minires.c index f11ff418b..7d0a6ab06 100644 --- a/winsup/cygwin/libc/minires.c +++ b/winsup/cygwin/libc/minires.c @@ -427,7 +427,7 @@ int res_nsend( res_state statp, const unsigned char * MsgPtr, return -1; } /* Set close on exec flag */ - if (fcntl(statp->sockfd, F_SETFD, 1) == -1) { + if (fcntl64(statp->sockfd, F_SETFD, 1) == -1) { DPRINTF(debug, "fcntl: %s\n", strerror(errno)); statp->res_h_errno = NETDB_INTERNAL; diff --git a/winsup/cygwin/libc/rcmd.cc b/winsup/cygwin/libc/rcmd.cc index 0e484c515..843a21af7 100644 --- a/winsup/cygwin/libc/rcmd.cc +++ b/winsup/cygwin/libc/rcmd.cc @@ -203,7 +203,7 @@ cygwin_rcmd_af(char **ahost, in_port_t rport, const char *locuser, NULL); return (-1); } - fcntl(s, F_SETOWN, pid); + fcntl64(s, F_SETOWN, pid); if (cygwin_connect(s, ai->ai_addr, ai->ai_addrlen) >= 0) break; (void)close(s); diff --git a/winsup/cygwin/posix_ipc.cc b/winsup/cygwin/posix_ipc.cc index 2ed38fb23..7bcc38087 100644 --- a/winsup/cygwin/posix_ipc.cc +++ b/winsup/cygwin/posix_ipc.cc @@ -209,14 +209,14 @@ public: fl.l_whence = SEEK_SET; fl.l_start = 0; fl.l_len = size; - return fcntl (fd, F_SETLKW, &fl); + return fcntl64 (fd, F_SETLKW, &fl); } int unlock (int fd) { if (!fl.l_len) return 0; fl.l_type = F_UNLCK; - return fcntl (fd, F_SETLKW, &fl); + return fcntl64 (fd, F_SETLKW, &fl); } }; diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index f7122dcb9..06c74a209 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -2940,12 +2940,12 @@ locked_append (int fd, const void * buf, size_t size) do if ((lock_buffer.l_start = lseek64 (fd, 0, SEEK_END)) != (_off64_t) -1 - && fcntl_worker (fd, F_SETLKW, &lock_buffer) != -1) + && fcntl64 (fd, F_SETLKW, &lock_buffer) != -1) { if (lseek64 (fd, 0, SEEK_END) != (_off64_t) -1) write (fd, buf, size); lock_buffer.l_type = F_UNLCK; - fcntl_worker (fd, F_SETLK, &lock_buffer); + fcntl64 (fd, F_SETLK, &lock_buffer); break; } while (count++ < 1000 @@ -3452,7 +3452,7 @@ popen (const char *command, const char *in_type) } FILE *fp = fdopen (fd, in_type); - fcntl (fd, F_SETFD, fcntl (fd, F_GETFD, 0) | FD_CLOEXEC); + fcntl64 (fd, F_SETFD, fcntl64 (fd, F_GETFD, 0) | FD_CLOEXEC); if (!fp) goto err; @@ -3467,11 +3467,11 @@ popen (const char *command, const char *in_type) { lock_process now; - int state = fcntl (stdwhat, F_GETFD, 0); - fcntl (stdwhat, F_SETFD, state | FD_CLOEXEC); + int state = fcntl64 (stdwhat, F_GETFD, 0); + fcntl64 (stdwhat, F_SETFD, state | FD_CLOEXEC); pid = spawn_guts ("/bin/sh", argv, cur_environ (), _P_NOWAIT, __stdin, __stdout); - fcntl (stdwhat, F_SETFD, state); + fcntl64 (stdwhat, F_SETFD, state); } if (pid < 0) diff --git a/winsup/cygwin/syslog.cc b/winsup/cygwin/syslog.cc index 383cc244f..88313b2c2 100644 --- a/winsup/cygwin/syslog.cc +++ b/winsup/cygwin/syslog.cc @@ -217,7 +217,7 @@ connect_syslogd () else syslogd_inited = inited_dgram; syslogd_sock = fd; - fcntl (syslogd_sock, F_SETFD, FD_CLOEXEC); + fcntl64 (syslogd_sock, F_SETFD, FD_CLOEXEC); return; } diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h index 33cdba39d..9a722778b 100644 --- a/winsup/cygwin/winsup.h +++ b/winsup/cygwin/winsup.h @@ -54,7 +54,7 @@ extern struct passwd *getpwnam (const char *); extern struct __sFILE64 *fopen64 (const char *, const char *); extern struct hostent *cygwin_gethostbyname (const char *name); extern unsigned long cygwin_inet_addr (const char *cp); - +extern int fcntl64 (int fd, int cmd, ...); #ifdef __cplusplus } #endif @@ -324,7 +324,6 @@ int symlink_worker (const char *, const char *, bool, bool) class path_conv; -int fcntl_worker (int fd, int cmd, void *arg); int __stdcall stat_worker (path_conv &pc, struct __stat64 *buf) __attribute__ ((regparm (2))); __ino64_t __stdcall readdir_get_ino (const char *path, bool dot_dot) __attribute__ ((regparm (2)));