summaryrefslogtreecommitdiff
path: root/src/basic/user-util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/basic/user-util.c')
-rw-r--r--src/basic/user-util.c49
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;
+}