From ec79767e5f2c5fb5d43fae56771c67ac258f827a Mon Sep 17 00:00:00 2001 From: Mike Gelfand Date: Sat, 13 Jul 2019 22:53:04 +0300 Subject: [PATCH] Support OFD locks and missing flock --- CMakeLists.txt | 1 + libtransmission/file-posix.c | 53 ++++++++++++++++++++++++++++++++++-- 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a0f4048e2..2b35962b3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -453,6 +453,7 @@ set(NEEDED_FUNCTIONS canonicalize_file_name daemon fallocate64 + flock getmntent getpagesize htonll diff --git a/libtransmission/file-posix.c b/libtransmission/file-posix.c index 05840e7a5..f481a24c6 100644 --- a/libtransmission/file-posix.c +++ b/libtransmission/file-posix.c @@ -11,7 +11,7 @@ #include #include -#include /* O_LARGEFILE, posix_fadvise(), [posix_]fallocate() */ +#include /* O_LARGEFILE, posix_fadvise(), [posix_]fallocate(), fcntl() */ #include /* basename(), dirname() */ #include /* PATH_MAX */ #include @@ -985,6 +985,41 @@ bool tr_sys_file_lock(tr_sys_file_t handle, int operation, tr_error** error) !!(operation & TR_SYS_FILE_LOCK_UN) == 1); bool ret; + +#if defined(F_OFD_SETLK) + + struct flock fl = {0}; + + switch (operation & (TR_SYS_FILE_LOCK_SH | TR_SYS_FILE_LOCK_EX | TR_SYS_FILE_LOCK_UN)) + { + case TR_SYS_FILE_LOCK_SH: + fl.l_type = F_RDLCK; + break; + + case TR_SYS_FILE_LOCK_EX: + fl.l_type = F_WRLCK; + break; + + case TR_SYS_FILE_LOCK_UN: + fl.l_type = F_UNLCK; + break; + } + + fl.l_whence = SEEK_SET; + + do + { + ret = fcntl(handle, (operation & TR_SYS_FILE_LOCK_NB) != 0 ? F_OFD_SETLK : F_OFD_SETLKW, &fl) != -1; + } + while (!ret && errno == EINTR); + + if (!ret && errno == EAGAIN) + { + errno = EWOULDBLOCK; + } + +#elif defined(HAVE_FLOCK) + int native_operation = 0; if ((operation & TR_SYS_FILE_LOCK_SH) != 0) @@ -1007,7 +1042,21 @@ bool tr_sys_file_lock(tr_sys_file_t handle, int operation, tr_error** error) native_operation |= LOCK_UN; } - ret = flock(handle, native_operation) != -1; + do + { + ret = flock(handle, native_operation) != -1; + } + while (!ret && errno == EINTR); + +#else + + (void)handle; + (void)operation; + + errno = ENOSYS; + ret = false; + +#endif if (!ret) {