123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 |
- #include <config.h>
- #include <sys/file.h>
- #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
- # define WIN32_LEAN_AND_MEAN
- # include <windows.h>
- # include <errno.h>
- # include "msvc-nothrow.h"
- static BOOL
- file_size (HANDLE h, DWORD * lower, DWORD * upper)
- {
- *lower = GetFileSize (h, upper);
- return 1;
- }
- # ifndef LOCKFILE_FAIL_IMMEDIATELY
- # define LOCKFILE_FAIL_IMMEDIATELY 1
- # endif
- static BOOL
- do_lock (HANDLE h, int non_blocking, int exclusive)
- {
- BOOL res;
- DWORD size_lower, size_upper;
- OVERLAPPED ovlp;
- int flags = 0;
-
- res = file_size (h, &size_lower, &size_upper);
- if (!res)
- return 0;
-
- memset (&ovlp, 0, sizeof ovlp);
- if (non_blocking)
- flags |= LOCKFILE_FAIL_IMMEDIATELY;
- if (exclusive)
- flags |= LOCKFILE_EXCLUSIVE_LOCK;
- return LockFileEx (h, flags, 0, size_lower, size_upper, &ovlp);
- }
- static BOOL
- do_unlock (HANDLE h)
- {
- int res;
- DWORD size_lower, size_upper;
- res = file_size (h, &size_lower, &size_upper);
- if (!res)
- return 0;
- return UnlockFile (h, 0, 0, size_lower, size_upper);
- }
- int
- flock (int fd, int operation)
- {
- HANDLE h = (HANDLE) _get_osfhandle (fd);
- DWORD res;
- int non_blocking;
- if (h == INVALID_HANDLE_VALUE)
- {
- errno = EBADF;
- return -1;
- }
- non_blocking = operation & LOCK_NB;
- operation &= ~LOCK_NB;
- switch (operation)
- {
- case LOCK_SH:
- res = do_lock (h, non_blocking, 0);
- break;
- case LOCK_EX:
- res = do_lock (h, non_blocking, 1);
- break;
- case LOCK_UN:
- res = do_unlock (h);
- break;
- default:
- errno = EINVAL;
- return -1;
- }
-
- if (!res)
- {
- DWORD err = GetLastError ();
- switch (err)
- {
-
- case ERROR_LOCK_VIOLATION:
- errno = EAGAIN;
- break;
-
- case ERROR_NOT_ENOUGH_MEMORY:
- errno = ENOMEM;
- break;
- case ERROR_BAD_COMMAND:
- errno = EINVAL;
- break;
-
- default:
- errno = err;
- }
- return -1;
- }
- return 0;
- }
- #else
- # ifdef HAVE_STRUCT_FLOCK_L_TYPE
- # include <fcntl.h>
- # ifdef HAVE_UNISTD_H
- # include <unistd.h>
- # endif
- # include <errno.h>
- # include <string.h>
- int
- flock (int fd, int operation)
- {
- int cmd, r;
- struct flock fl;
- if (operation & LOCK_NB)
- cmd = F_SETLK;
- else
- cmd = F_SETLKW;
- operation &= ~LOCK_NB;
- memset (&fl, 0, sizeof fl);
- fl.l_whence = SEEK_SET;
-
- switch (operation)
- {
- case LOCK_SH:
- fl.l_type = F_RDLCK;
- break;
- case LOCK_EX:
- fl.l_type = F_WRLCK;
- break;
- case LOCK_UN:
- fl.l_type = F_UNLCK;
- break;
- default:
- errno = EINVAL;
- return -1;
- }
- r = fcntl (fd, cmd, &fl);
- if (r == -1 && errno == EACCES)
- errno = EAGAIN;
- return r;
- }
- # else
- # error "This platform lacks flock function, and Gnulib doesn't provide a replacement. This is a bug in Gnulib."
- # endif
- #endif
|