* [PATCH] flock: add support for using fcntl() with open file description locks
@ 2024-04-17 10:09 Rasmus Villemoes
2024-04-17 17:33 ` Masatake YAMATO
2024-04-18 8:49 ` Rasmus Villemoes
0 siblings, 2 replies; 6+ messages in thread
From: Rasmus Villemoes @ 2024-04-17 10:09 UTC (permalink / raw)
To: util-linux; +Cc: Karel Zak, Rasmus Villemoes
Currently, there is no way for shell scripts to safely access
resources protected by POSIX locking (fcntl with the F_SETLK/F_SETLKW
commands). For example, the glibc function lckpwdf(), used to
protect access to the /etc/shadow database, works by taking a
F_SETLKW on /etc/.pwd.lock .
Due to the odd semantics of POSIX locking (e.g. released when any file
descriptor associated to the inode is closed), we cannot usefully
directly expose the POSIX F_SETLK/F_SETLKW commands. However, linux
3.15 introduced F_OFD_SETLK[W], with semantics wrt. ownership and
release better matching those of flock(2), and crucially they do
conflict with locks obtained via F_SETLK[W]. With this, a shell script
can do
exec 4> /etc/.pwd.lock
flock --fcntl-ofd 4
<access/modify /etc/shadow ...>
flock --fcntl-ofd --unlock 4 # or just exit
without conflicting with passwd(1) or other utilities that
access/modify /etc/shadow.
The option name is a bit verbose, and no single-letter shorthand is
defined, because this is somewhat low-level and the user really needs
to know what he is doing.
Signed-off-by: Rasmus Villemoes <rasmus.villemoes@prevas.dk>
---
Both my autotools and meson fu are weak to non-existing, so I don't
know if I've written the "test if the header exposes this macro"
correctly.
I'm not at all married to the option name. I also considered just
making it --fcntl, with the possiblity of making that grow an optional
argument (for example --fcntl=posix with plain --fcntl being an alias
for --fcntl=ofd) should anyone ever figure out a use for the plain
F_SETLK, perhaps just for testing.
configure.ac | 6 +++++
meson.build | 3 +++
sys-utils/flock.c | 60 +++++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 67 insertions(+), 2 deletions(-)
diff --git a/configure.ac b/configure.ac
index c302732e7..441b09440 100644
--- a/configure.ac
+++ b/configure.ac
@@ -434,6 +434,12 @@ AC_CHECK_DECLS([PR_REP_CAPACITY], [], [], [
#include <linux/pr.h>
])
+AC_CHECK_DECL([F_OFD_SETLK],
+ [AC_DEFINE([HAVE_FCNTL_OFD_LOCKS], [1],
+ [Define to 1 if fcntl.h defines F_OFD_ constants])], [], [
+#include <fcntl.h>
+])
+
AC_CHECK_HEADERS([security/openpam.h], [], [], [
#ifdef HAVE_SECURITY_PAM_APPL_H
#include <security/pam_appl.h>
diff --git a/meson.build b/meson.build
index 99126f7aa..004c849f1 100644
--- a/meson.build
+++ b/meson.build
@@ -704,6 +704,9 @@ conf.set('HAVE_DECL_BLK_ZONE_REP_CAPACITY', have ? 1 : false)
have = cc.has_header_symbol('linux/pr.h', 'PR_REP_CAPACITY')
conf.set('HAVE_DECL_PR_REP_CAPACITY', have ? 1 : false)
+have = cc.has_header_symbol('fcntl.h', 'F_OFD_SETLK', args: '-D_GNU_SOURCE')
+conf.set('HAVE_FCNTL_OFD_LOCKS', have ? 1 : false)
+
code = '''
#include <time.h>
#if !@0@
diff --git a/sys-utils/flock.c b/sys-utils/flock.c
index 7d878ff81..40751517d 100644
--- a/sys-utils/flock.c
+++ b/sys-utils/flock.c
@@ -70,6 +70,9 @@ static void __attribute__((__noreturn__)) usage(void)
fputs(_( " -o, --close close file descriptor before running command\n"), stdout);
fputs(_( " -c, --command <command> run a single command string through the shell\n"), stdout);
fputs(_( " -F, --no-fork execute command without forking\n"), stdout);
+#ifdef HAVE_FCNTL_OFD_LOCKS
+ fputs(_( " --fcntl-ofd use fcntl(F_OFD_SETLK) rather than flock()\n"), stdout);
+#endif
fputs(_( " --verbose increase verbosity\n"), stdout);
fputs(USAGE_SEPARATOR, stdout);
fprintf(stdout, USAGE_HELP_OPTIONS(26));
@@ -126,6 +129,38 @@ static void __attribute__((__noreturn__)) run_program(char **cmd_argv)
_exit((errno == ENOMEM) ? EX_OSERR : EX_UNAVAILABLE);
}
+static int flock_to_fcntl_type(int op)
+{
+ switch (op) {
+ case LOCK_EX:
+ return F_WRLCK;
+ case LOCK_SH:
+ return F_RDLCK;
+ case LOCK_UN:
+ return F_UNLCK;
+ default:
+ errx(EX_SOFTWARE, _("internal error, unknown operation %d"), op);
+ }
+}
+
+static int do_fcntl_lock(int fd, int op, int block)
+{
+#ifdef HAVE_FCNTL_OFD_LOCKS
+ struct flock arg = {
+ .l_type = flock_to_fcntl_type(op),
+ .l_whence = SEEK_SET,
+ .l_start = 0,
+ .l_len = 0,
+ };
+ int cmd = (block == LOCK_NB) ? F_OFD_SETLK : F_OFD_SETLKW;
+ return fcntl(fd, cmd, &arg);
+#else
+ /* Should never happen, nothing can ever set use_fcntl_ofd when !HAVE_FCNTL_OFD_LOCKS. */
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+
int main(int argc, char *argv[])
{
struct ul_timer timer;
@@ -140,6 +175,7 @@ int main(int argc, char *argv[])
int no_fork = 0;
int status;
int verbose = 0;
+ int use_fcntl_ofd = 0;
struct timeval time_start = { 0 }, time_done = { 0 };
/*
* The default exit code for lock conflict or timeout
@@ -149,7 +185,8 @@ int main(int argc, char *argv[])
char **cmd_argv = NULL, *sh_c_argv[4];
const char *filename = NULL;
enum {
- OPT_VERBOSE = CHAR_MAX + 1
+ OPT_VERBOSE = CHAR_MAX + 1,
+ OPT_FCNTL_OFD,
};
static const struct option long_options[] = {
{"shared", no_argument, NULL, 's'},
@@ -163,6 +200,7 @@ int main(int argc, char *argv[])
{"close", no_argument, NULL, 'o'},
{"no-fork", no_argument, NULL, 'F'},
{"verbose", no_argument, NULL, OPT_VERBOSE},
+ {"fcntl-ofd", no_argument, NULL, OPT_FCNTL_OFD},
{"help", no_argument, NULL, 'h'},
{"version", no_argument, NULL, 'V'},
{NULL, 0, NULL, 0}
@@ -217,6 +255,11 @@ int main(int argc, char *argv[])
if (conflict_exit_code < 0 || conflict_exit_code > 255)
errx(EX_USAGE, _("exit code out of range (expected 0 to 255)"));
break;
+#ifdef HAVE_FCNTL_OFD_LOCKS
+ case OPT_FCNTL_OFD:
+ use_fcntl_ofd = 1;
+ break;
+#endif
case OPT_VERBOSE:
verbose = 1;
break;
@@ -234,6 +277,13 @@ int main(int argc, char *argv[])
errx(EX_USAGE,
_("the --no-fork and --close options are incompatible"));
+ /*
+ * For fcntl(F_OFD_SETLK), an exclusive lock requires that the
+ * file is open for write.
+ */
+ if (use_fcntl_ofd && type == LOCK_EX)
+ open_flags = O_WRONLY;
+
if (argc > optind + 1) {
/* Run command */
if (!strcmp(argv[optind + 1], "-c") ||
@@ -280,9 +330,15 @@ int main(int argc, char *argv[])
if (verbose)
gettime_monotonic(&time_start);
- while (flock(fd, type | block)) {
+ while (use_fcntl_ofd ? do_fcntl_lock(fd, type, block) : flock(fd, type | block)) {
switch (errno) {
case EWOULDBLOCK:
+ /*
+ * Per the man page, for fcntl(), EACCES may
+ * be returned and means the same as
+ * EAGAIN/EWOULDBLOCK.
+ */
+ case EACCES:
/* -n option set and failed to lock. */
if (verbose)
warnx(_("failed to get lock"));
--
2.40.1.1.g1c60b9335d
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH] flock: add support for using fcntl() with open file description locks
2024-04-17 10:09 [PATCH] flock: add support for using fcntl() with open file description locks Rasmus Villemoes
@ 2024-04-17 17:33 ` Masatake YAMATO
2024-04-18 8:12 ` Rasmus Villemoes
2024-04-23 9:50 ` Karel Zak
2024-04-18 8:49 ` Rasmus Villemoes
1 sibling, 2 replies; 6+ messages in thread
From: Masatake YAMATO @ 2024-04-17 17:33 UTC (permalink / raw)
To: rasmus.villemoes; +Cc: util-linux, kzak
> Currently, there is no way for shell scripts to safely access
> resources protected by POSIX locking (fcntl with the F_SETLK/F_SETLKW
> commands). For example, the glibc function lckpwdf(), used to
> protect access to the /etc/shadow database, works by taking a
> F_SETLKW on /etc/.pwd.lock .
>
> Due to the odd semantics of POSIX locking (e.g. released when any file
> descriptor associated to the inode is closed), we cannot usefully
> directly expose the POSIX F_SETLK/F_SETLKW commands. However, linux
> 3.15 introduced F_OFD_SETLK[W], with semantics wrt. ownership and
> release better matching those of flock(2), and crucially they do
> conflict with locks obtained via F_SETLK[W]. With this, a shell script
> can do
>
> exec 4> /etc/.pwd.lock
> flock --fcntl-ofd 4
> <access/modify /etc/shadow ...>
> flock --fcntl-ofd --unlock 4 # or just exit
>
> without conflicting with passwd(1) or other utilities that
> access/modify /etc/shadow.
>
> The option name is a bit verbose, and no single-letter shorthand is
> defined, because this is somewhat low-level and the user really needs
> to know what he is doing.
>
> Signed-off-by: Rasmus Villemoes <rasmus.villemoes@prevas.dk>
>
> ---
>
> Both my autotools and meson fu are weak to non-existing, so I don't
> know if I've written the "test if the header exposes this macro"
> correctly.
>
> I'm not at all married to the option name. I also considered just
> making it --fcntl, with the possiblity of making that grow an optional
> argument (for example --fcntl=posix with plain --fcntl being an alias
> for --fcntl=ofd) should anyone ever figure out a use for the plain
> F_SETLK, perhaps just for testing.
>
>
> configure.ac | 6 +++++
> meson.build | 3 +++
> sys-utils/flock.c | 60 +++++++++++++++++++++++++++++++++++++++++++++--
> 3 files changed, 67 insertions(+), 2 deletions(-)
You may have to update sys-utils/flock.1.adoc and the completion rule bash-completion/flock
when adding a new optoin.
> diff --git a/configure.ac b/configure.ac
> index c302732e7..441b09440 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -434,6 +434,12 @@ AC_CHECK_DECLS([PR_REP_CAPACITY], [], [], [
> #include <linux/pr.h>
> ])
>
> +AC_CHECK_DECL([F_OFD_SETLK],
> + [AC_DEFINE([HAVE_FCNTL_OFD_LOCKS], [1],
> + [Define to 1 if fcntl.h defines F_OFD_ constants])], [], [
> +#include <fcntl.h>
> +])
> +
> AC_CHECK_HEADERS([security/openpam.h], [], [], [
> #ifdef HAVE_SECURITY_PAM_APPL_H
> #include <security/pam_appl.h>
> diff --git a/meson.build b/meson.build
> index 99126f7aa..004c849f1 100644
> --- a/meson.build
> +++ b/meson.build
> @@ -704,6 +704,9 @@ conf.set('HAVE_DECL_BLK_ZONE_REP_CAPACITY', have ? 1 : false)
> have = cc.has_header_symbol('linux/pr.h', 'PR_REP_CAPACITY')
> conf.set('HAVE_DECL_PR_REP_CAPACITY', have ? 1 : false)
>
> +have = cc.has_header_symbol('fcntl.h', 'F_OFD_SETLK', args: '-D_GNU_SOURCE')
> +conf.set('HAVE_FCNTL_OFD_LOCKS', have ? 1 : false)
> +
> code = '''
> #include <time.h>
> #if !@0@
> diff --git a/sys-utils/flock.c b/sys-utils/flock.c
> index 7d878ff81..40751517d 100644
> --- a/sys-utils/flock.c
> +++ b/sys-utils/flock.c
> @@ -70,6 +70,9 @@ static void __attribute__((__noreturn__)) usage(void)
> fputs(_( " -o, --close close file descriptor before running command\n"), stdout);
> fputs(_( " -c, --command <command> run a single command string through the shell\n"), stdout);
> fputs(_( " -F, --no-fork execute command without forking\n"), stdout);
> +#ifdef HAVE_FCNTL_OFD_LOCKS
> + fputs(_( " --fcntl-ofd use fcntl(F_OFD_SETLK) rather than flock()\n"), stdout);
> +#endif
> fputs(_( " --verbose increase verbosity\n"), stdout);
> fputs(USAGE_SEPARATOR, stdout);
> fprintf(stdout, USAGE_HELP_OPTIONS(26));
> @@ -126,6 +129,38 @@ static void __attribute__((__noreturn__)) run_program(char **cmd_argv)
> _exit((errno == ENOMEM) ? EX_OSERR : EX_UNAVAILABLE);
> }
>
> +static int flock_to_fcntl_type(int op)
> +{
> + switch (op) {
> + case LOCK_EX:
> + return F_WRLCK;
> + case LOCK_SH:
> + return F_RDLCK;
> + case LOCK_UN:
> + return F_UNLCK;
> + default:
> + errx(EX_SOFTWARE, _("internal error, unknown operation %d"), op);
> + }
> +}
Don't you need wrap flock_to_fcntl_type with #ifdef HAVE_FCNTL_OFD_LOCKS/#endif?
> +static int do_fcntl_lock(int fd, int op, int block)
> +{
> +#ifdef HAVE_FCNTL_OFD_LOCKS
> + struct flock arg = {
> + .l_type = flock_to_fcntl_type(op),
> + .l_whence = SEEK_SET,
> + .l_start = 0,
> + .l_len = 0,
> + };
> + int cmd = (block == LOCK_NB) ? F_OFD_SETLK : F_OFD_SETLKW;
> + return fcntl(fd, cmd, &arg);
> +#else
> + /* Should never happen, nothing can ever set use_fcntl_ofd when !HAVE_FCNTL_OFD_LOCKS. */
> + errno = ENOSYS;
> + return -1;
> +#endif
> +}
> +
> int main(int argc, char *argv[])
> {
> struct ul_timer timer;
> @@ -140,6 +175,7 @@ int main(int argc, char *argv[])
> int no_fork = 0;
> int status;
> int verbose = 0;
> + int use_fcntl_ofd = 0;
> struct timeval time_start = { 0 }, time_done = { 0 };
> /*
> * The default exit code for lock conflict or timeout
> @@ -149,7 +185,8 @@ int main(int argc, char *argv[])
> char **cmd_argv = NULL, *sh_c_argv[4];
> const char *filename = NULL;
> enum {
> - OPT_VERBOSE = CHAR_MAX + 1
> + OPT_VERBOSE = CHAR_MAX + 1,
> + OPT_FCNTL_OFD,
> };
> static const struct option long_options[] = {
> {"shared", no_argument, NULL, 's'},
> @@ -163,6 +200,7 @@ int main(int argc, char *argv[])
> {"close", no_argument, NULL, 'o'},
> {"no-fork", no_argument, NULL, 'F'},
> {"verbose", no_argument, NULL, OPT_VERBOSE},
> + {"fcntl-ofd", no_argument, NULL, OPT_FCNTL_OFD},
> {"help", no_argument, NULL, 'h'},
> {"version", no_argument, NULL, 'V'},
> {NULL, 0, NULL, 0}
> @@ -217,6 +255,11 @@ int main(int argc, char *argv[])
> if (conflict_exit_code < 0 || conflict_exit_code > 255)
> errx(EX_USAGE, _("exit code out of range (expected 0 to 255)"));
> break;
> +#ifdef HAVE_FCNTL_OFD_LOCKS
> + case OPT_FCNTL_OFD:
> + use_fcntl_ofd = 1;
> + break;
> +#endif
> case OPT_VERBOSE:
> verbose = 1;
> break;
> @@ -234,6 +277,13 @@ int main(int argc, char *argv[])
> errx(EX_USAGE,
> _("the --no-fork and --close options are incompatible"));
>
> + /*
> + * For fcntl(F_OFD_SETLK), an exclusive lock requires that the
> + * file is open for write.
> + */
> + if (use_fcntl_ofd && type == LOCK_EX)
> + open_flags = O_WRONLY;
> +
> if (argc > optind + 1) {
> /* Run command */
> if (!strcmp(argv[optind + 1], "-c") ||
> @@ -280,9 +330,15 @@ int main(int argc, char *argv[])
>
> if (verbose)
> gettime_monotonic(&time_start);
> - while (flock(fd, type | block)) {
> + while (use_fcntl_ofd ? do_fcntl_lock(fd, type, block) : flock(fd, type | block)) {
> switch (errno) {
> case EWOULDBLOCK:
> + /*
> + * Per the man page, for fcntl(), EACCES may
> + * be returned and means the same as
> + * EAGAIN/EWOULDBLOCK.
> + */
> + case EACCES:
> /* -n option set and failed to lock. */
> if (verbose)
> warnx(_("failed to get lock"));
> --
> 2.40.1.1.g1c60b9335d
>
>
Masatake YAMATO
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] flock: add support for using fcntl() with open file description locks
2024-04-17 17:33 ` Masatake YAMATO
@ 2024-04-18 8:12 ` Rasmus Villemoes
2024-04-23 9:50 ` Karel Zak
1 sibling, 0 replies; 6+ messages in thread
From: Rasmus Villemoes @ 2024-04-18 8:12 UTC (permalink / raw)
To: Masatake YAMATO; +Cc: util-linux, kzak
On 17/04/2024 19.33, Masatake YAMATO wrote:
>> Currently, there is no way for shell scripts to safely access
>> resources protected by POSIX locking (fcntl with the F_SETLK/F_SETLKW
>> commands). For example, the glibc function lckpwdf(), used to
>> protect access to the /etc/shadow database, works by taking a
>> F_SETLKW on /etc/.pwd.lock .
>>
>> Due to the odd semantics of POSIX locking (e.g. released when any file
>> descriptor associated to the inode is closed), we cannot usefully
>> directly expose the POSIX F_SETLK/F_SETLKW commands. However, linux
>> 3.15 introduced F_OFD_SETLK[W], with semantics wrt. ownership and
>> release better matching those of flock(2), and crucially they do
>> conflict with locks obtained via F_SETLK[W]. With this, a shell script
>> can do
>>
>> exec 4> /etc/.pwd.lock
>> flock --fcntl-ofd 4
>> <access/modify /etc/shadow ...>
>> flock --fcntl-ofd --unlock 4 # or just exit
>>
>> without conflicting with passwd(1) or other utilities that
>> access/modify /etc/shadow.
>>
>> The option name is a bit verbose, and no single-letter shorthand is
>> defined, because this is somewhat low-level and the user really needs
>> to know what he is doing.
>>
>> Signed-off-by: Rasmus Villemoes <rasmus.villemoes@prevas.dk>
>>
>> ---
>>
>> Both my autotools and meson fu are weak to non-existing, so I don't
>> know if I've written the "test if the header exposes this macro"
>> correctly.
>>
>> I'm not at all married to the option name. I also considered just
>> making it --fcntl, with the possiblity of making that grow an optional
>> argument (for example --fcntl=posix with plain --fcntl being an alias
>> for --fcntl=ofd) should anyone ever figure out a use for the plain
>> F_SETLK, perhaps just for testing.
>>
>>
>> configure.ac | 6 +++++
>> meson.build | 3 +++
>> sys-utils/flock.c | 60 +++++++++++++++++++++++++++++++++++++++++++++--
>> 3 files changed, 67 insertions(+), 2 deletions(-)
>
> You may have to update sys-utils/flock.1.adoc and the completion rule bash-completion/flock
> when adding a new optoin.
I will send a separate patch with that once the option naming is settled
and the concept itself is accepted (not necessarily applied to master).
>> code = '''
>> #include <time.h>
>> #if !@0@
>> diff --git a/sys-utils/flock.c b/sys-utils/flock.c
>> index 7d878ff81..40751517d 100644
>> --- a/sys-utils/flock.c
>> +++ b/sys-utils/flock.c
>> @@ -70,6 +70,9 @@ static void __attribute__((__noreturn__)) usage(void)
>> fputs(_( " -o, --close close file descriptor before running command\n"), stdout);
>> fputs(_( " -c, --command <command> run a single command string through the shell\n"), stdout);
>> fputs(_( " -F, --no-fork execute command without forking\n"), stdout);
>> +#ifdef HAVE_FCNTL_OFD_LOCKS
>> + fputs(_( " --fcntl-ofd use fcntl(F_OFD_SETLK) rather than flock()\n"), stdout);
>> +#endif
>> fputs(_( " --verbose increase verbosity\n"), stdout);
>> fputs(USAGE_SEPARATOR, stdout);
>> fprintf(stdout, USAGE_HELP_OPTIONS(26));
>> @@ -126,6 +129,38 @@ static void __attribute__((__noreturn__)) run_program(char **cmd_argv)
>> _exit((errno == ENOMEM) ? EX_OSERR : EX_UNAVAILABLE);
>> }
>>
>> +static int flock_to_fcntl_type(int op)
>> +{
>> + switch (op) {
>> + case LOCK_EX:
>> + return F_WRLCK;
>> + case LOCK_SH:
>> + return F_RDLCK;
>> + case LOCK_UN:
>> + return F_UNLCK;
>> + default:
>> + errx(EX_SOFTWARE, _("internal error, unknown operation %d"), op);
>> + }
>> +}
>
> Don't you need wrap flock_to_fcntl_type with #ifdef HAVE_FCNTL_OFD_LOCKS/#endif?
Well, the constants mentioned here are the same as used with posix
locking, and have been in glibc and kernel headers since forever. Only
the F_OFD_* ones are "newish". So I don't think this needs guarding due
to non-existence of the symbols. But I might need to guard the whole
function (or mark it maybe-unused) to avoid a defined-but-not-used warning.
I wasn't even sure if I actually needed a configure check and HAVE_*
guard at all; 3.15 is 10 years old by now, but I couldn't find any
mention of the oldest glibc/kernel that util-linux is supposed to build
against. Karel?
Rasmus
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] flock: add support for using fcntl() with open file description locks
2024-04-17 10:09 [PATCH] flock: add support for using fcntl() with open file description locks Rasmus Villemoes
2024-04-17 17:33 ` Masatake YAMATO
@ 2024-04-18 8:49 ` Rasmus Villemoes
1 sibling, 0 replies; 6+ messages in thread
From: Rasmus Villemoes @ 2024-04-18 8:49 UTC (permalink / raw)
To: util-linux; +Cc: Karel Zak, Masatake YAMATO
On 17/04/2024 12.09, Rasmus Villemoes wrote:
> I'm not at all married to the option name. I also considered just
> making it --fcntl,
Thinking more about it, I think I prefer this slightly shorter name.
with the possiblity of making that grow an optional
> argument (for example --fcntl=posix with plain --fcntl being an alias
> for --fcntl=ofd)
Not that I'm gonna implement this part immediately, but I do like that
it leaves the door open for it.
If no other comments appear in a day or two, I'll resend with that
change and the fix for guarding the maybe-unused helper function.
Rasmus
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] flock: add support for using fcntl() with open file description locks
2024-04-17 17:33 ` Masatake YAMATO
2024-04-18 8:12 ` Rasmus Villemoes
@ 2024-04-23 9:50 ` Karel Zak
2024-04-23 9:53 ` Karel Zak
1 sibling, 1 reply; 6+ messages in thread
From: Karel Zak @ 2024-04-23 9:50 UTC (permalink / raw)
To: Masatake YAMATO; +Cc: rasmus.villemoes, util-linux
On Thu, Apr 18, 2024 at 02:33:54AM +0900, Masatake YAMATO wrote:
> > int main(int argc, char *argv[])
> > {
> > struct ul_timer timer;
> > @@ -140,6 +175,7 @@ int main(int argc, char *argv[])
> > int no_fork = 0;
> > int status;
> > int verbose = 0;
> > + int use_fcntl_ofd = 0;
What about to introduce "lock_method" variable and define
enum {
LOCK_BY_FLOCK
LOCK_BY_FCNTL_OFD
};
later you can easily extend it by LOCK_BY_FCNTL_POSIX. IMHO the code
will be more readable.
> > struct timeval time_start = { 0 }, time_done = { 0 };
> > /*
> > * The default exit code for lock conflict or timeout
> > @@ -149,7 +185,8 @@ int main(int argc, char *argv[])
> > char **cmd_argv = NULL, *sh_c_argv[4];
> > const char *filename = NULL;
> > enum {
> > - OPT_VERBOSE = CHAR_MAX + 1
> > + OPT_VERBOSE = CHAR_MAX + 1,
> > + OPT_FCNTL_OFD,
> > };
> > static const struct option long_options[] = {
> > {"shared", no_argument, NULL, 's'},
> > @@ -163,6 +200,7 @@ int main(int argc, char *argv[])
> > {"close", no_argument, NULL, 'o'},
> > {"no-fork", no_argument, NULL, 'F'},
> > {"verbose", no_argument, NULL, OPT_VERBOSE},
> > + {"fcntl-ofd", no_argument, NULL, OPT_FCNTL_OFD},
I agree that the sort name --fcntl sounds better and it's extendable.
> > {"help", no_argument, NULL, 'h'},
> > {"version", no_argument, NULL, 'V'},
> > {NULL, 0, NULL, 0}
> > @@ -217,6 +255,11 @@ int main(int argc, char *argv[])
> > if (conflict_exit_code < 0 || conflict_exit_code > 255)
> > errx(EX_USAGE, _("exit code out of range (expected 0 to 255)"));
> > break;
> > +#ifdef HAVE_FCNTL_OFD_LOCKS
> > + case OPT_FCNTL_OFD:
> > + use_fcntl_ofd = 1;
> > + break;
> > +#endif
> > case OPT_VERBOSE:
> > verbose = 1;
> > break;
> > @@ -234,6 +277,13 @@ int main(int argc, char *argv[])
> > errx(EX_USAGE,
> > _("the --no-fork and --close options are incompatible"));
> >
> > + /*
> > + * For fcntl(F_OFD_SETLK), an exclusive lock requires that the
> > + * file is open for write.
> > + */
> > + if (use_fcntl_ofd && type == LOCK_EX)
> > + open_flags = O_WRONLY;
> > +
> > if (argc > optind + 1) {
> > /* Run command */
> > if (!strcmp(argv[optind + 1], "-c") ||
> > @@ -280,9 +330,15 @@ int main(int argc, char *argv[])
> >
> > if (verbose)
> > gettime_monotonic(&time_start);
> > - while (flock(fd, type | block)) {
> > + while (use_fcntl_ofd ? do_fcntl_lock(fd, type, block) : flock(fd, type | block)) {
Maybe we can move the locking to a function
do_lock(fd, method, type, block)
and hide the necessary flock and fcntl details there, instead of
trying to do it in main().
Karel
--
Karel Zak <kzak@redhat.com>
http://karelzak.blogspot.com
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] flock: add support for using fcntl() with open file description locks
2024-04-23 9:50 ` Karel Zak
@ 2024-04-23 9:53 ` Karel Zak
0 siblings, 0 replies; 6+ messages in thread
From: Karel Zak @ 2024-04-23 9:53 UTC (permalink / raw)
To: rasmus.villemoes; +Cc: util-linux, Masatake YAMATO
On Tue, Apr 23, 2024 at 11:50:05AM +0200, Karel Zak wrote:
> On Thu, Apr 18, 2024 at 02:33:54AM +0900, Masatake YAMATO wrote:
Oh, sorry, I replied to Masatake's email instead of Rasmus's. My notes
are for the original patch :-)
Karel
--
Karel Zak <kzak@redhat.com>
http://karelzak.blogspot.com
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2024-04-23 9:53 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-04-17 10:09 [PATCH] flock: add support for using fcntl() with open file description locks Rasmus Villemoes
2024-04-17 17:33 ` Masatake YAMATO
2024-04-18 8:12 ` Rasmus Villemoes
2024-04-23 9:50 ` Karel Zak
2024-04-23 9:53 ` Karel Zak
2024-04-18 8:49 ` Rasmus Villemoes
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.