diff options
Diffstat (limited to 'src/basic/user-util.c')
-rw-r--r-- | src/basic/user-util.c | 49 |
1 files changed, 46 insertions, 3 deletions
diff --git a/src/basic/user-util.c b/src/basic/user-util.c index 7e6c4c645d..d6c936db37 100644 --- a/src/basic/user-util.c +++ b/src/basic/user-util.c @@ -22,11 +22,14 @@ #include <pwd.h> #include <grp.h> -#include "user-util.h" +#include "alloc-util.h" +#include "fd-util.h" #include "macro.h" -#include "util.h" -#include "string-util.h" +#include "parse-util.h" #include "path-util.h" +#include "string-util.h" +#include "user-util.h" +#include "util.h" bool uid_is_valid(uid_t uid) { @@ -427,3 +430,43 @@ int reset_uid_gid(void) { return 0; } + +int take_etc_passwd_lock(const char *root) { + + struct flock flock = { + .l_type = F_WRLCK, + .l_whence = SEEK_SET, + .l_start = 0, + .l_len = 0, + }; + + const char *path; + int fd, r; + + /* This is roughly the same as lckpwdf(), but not as awful. We + * don't want to use alarm() and signals, hence we implement + * our own trivial version of this. + * + * Note that shadow-utils also takes per-database locks in + * addition to lckpwdf(). However, we don't given that they + * are redundant as they they invoke lckpwdf() first and keep + * it during everything they do. The per-database locks are + * awfully racy, and thus we just won't do them. */ + + if (root) + path = prefix_roota(root, "/etc/.pwd.lock"); + else + path = "/etc/.pwd.lock"; + + fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0600); + if (fd < 0) + return -errno; + + r = fcntl(fd, F_SETLKW, &flock); + if (r < 0) { + safe_close(fd); + return -errno; + } + + return fd; +} |