232 lines
5.7 KiB
Diff
232 lines
5.7 KiB
Diff
Based on:
|
|
https://github.com/shadow-maint/shadow/commit/65470e5c7ddbc2885ad35fbd0218b91a75626c2f
|
|
Index: shadow-4.8.1/lib/commonio.c
|
|
===================================================================
|
|
--- shadow-4.8.1.orig/lib/commonio.c
|
|
+++ shadow-4.8.1/lib/commonio.c
|
|
@@ -54,8 +54,6 @@
|
|
|
|
/* local function prototypes */
|
|
static int lrename (const char *, const char *);
|
|
-static int check_link_count (const char *file);
|
|
-static int do_lock_file (const char *file, const char *lock, bool log);
|
|
static /*@null@*/ /*@dependent@*/FILE *fopen_set_perms (
|
|
const char *name,
|
|
const char *mode,
|
|
@@ -117,140 +115,6 @@ int lrename (const char *old, const char
|
|
return res;
|
|
}
|
|
|
|
-static int check_link_count (const char *file)
|
|
-{
|
|
- struct stat sb;
|
|
-
|
|
- if (stat (file, &sb) != 0) {
|
|
- return 0;
|
|
- }
|
|
-
|
|
- if (sb.st_nlink != 2) {
|
|
- return 0;
|
|
- }
|
|
-
|
|
- return 1;
|
|
-}
|
|
-
|
|
-
|
|
-static int do_lock_file (const char *file, const char *lock, bool log)
|
|
-{
|
|
- int fd;
|
|
- pid_t pid;
|
|
- ssize_t len;
|
|
- int retval;
|
|
- char buf[32];
|
|
-
|
|
- fd = open (file, O_CREAT | O_TRUNC | O_WRONLY, 0600);
|
|
- if (-1 == fd) {
|
|
- if (log) {
|
|
- (void) fprintf (stderr,
|
|
- "%s: %s: %s\n",
|
|
- Prog, file, strerror (errno));
|
|
- }
|
|
- return 0;
|
|
- }
|
|
-
|
|
- pid = getpid ();
|
|
- snprintf (buf, sizeof buf, "%lu", (unsigned long) pid);
|
|
- len = (ssize_t) strlen (buf) + 1;
|
|
- if (write (fd, buf, (size_t) len) != len) {
|
|
- if (log) {
|
|
- (void) fprintf (stderr,
|
|
- "%s: %s: %s\n",
|
|
- Prog, file, strerror (errno));
|
|
- }
|
|
- (void) close (fd);
|
|
- unlink (file);
|
|
- return 0;
|
|
- }
|
|
- close (fd);
|
|
-
|
|
- if (link (file, lock) == 0) {
|
|
- retval = check_link_count (file);
|
|
- if ((0==retval) && log) {
|
|
- (void) fprintf (stderr,
|
|
- "%s: %s: lock file already used\n",
|
|
- Prog, file);
|
|
- }
|
|
- unlink (file);
|
|
- return retval;
|
|
- }
|
|
-
|
|
- fd = open (lock, O_RDWR);
|
|
- if (-1 == fd) {
|
|
- if (log) {
|
|
- (void) fprintf (stderr,
|
|
- "%s: %s: %s\n",
|
|
- Prog, lock, strerror (errno));
|
|
- }
|
|
- unlink (file);
|
|
- errno = EINVAL;
|
|
- return 0;
|
|
- }
|
|
- len = read (fd, buf, sizeof (buf) - 1);
|
|
- close (fd);
|
|
- if (len <= 0) {
|
|
- if (log) {
|
|
- (void) fprintf (stderr,
|
|
- "%s: existing lock file %s without a PID\n",
|
|
- Prog, lock);
|
|
- }
|
|
- unlink (file);
|
|
- errno = EINVAL;
|
|
- return 0;
|
|
- }
|
|
- buf[len] = '\0';
|
|
- if (get_pid (buf, &pid) == 0) {
|
|
- if (log) {
|
|
- (void) fprintf (stderr,
|
|
- "%s: existing lock file %s with an invalid PID '%s'\n",
|
|
- Prog, lock, buf);
|
|
- }
|
|
- unlink (file);
|
|
- errno = EINVAL;
|
|
- return 0;
|
|
- }
|
|
- if (kill (pid, 0) == 0) {
|
|
- if (log) {
|
|
- (void) fprintf (stderr,
|
|
- "%s: lock %s already used by PID %lu\n",
|
|
- Prog, lock, (unsigned long) pid);
|
|
- }
|
|
- unlink (file);
|
|
- errno = EEXIST;
|
|
- return 0;
|
|
- }
|
|
- if (unlink (lock) != 0) {
|
|
- if (log) {
|
|
- (void) fprintf (stderr,
|
|
- "%s: cannot get lock %s: %s\n",
|
|
- Prog, lock, strerror (errno));
|
|
- }
|
|
- unlink (file);
|
|
- return 0;
|
|
- }
|
|
-
|
|
- retval = 0;
|
|
- if (link (file, lock) == 0) {
|
|
- retval = check_link_count (file);
|
|
- if ((0==retval) && log) {
|
|
- (void) fprintf (stderr,
|
|
- "%s: %s: lock file already used\n",
|
|
- Prog, file);
|
|
- }
|
|
- } else {
|
|
- if (log) {
|
|
- (void) fprintf (stderr,
|
|
- "%s: cannot get lock %s: %s\n",
|
|
- Prog, lock, strerror (errno));
|
|
- }
|
|
- }
|
|
-
|
|
- unlink (file);
|
|
- return retval;
|
|
-}
|
|
-
|
|
|
|
static /*@null@*/ /*@dependent@*/FILE *fopen_set_perms (
|
|
const char *name,
|
|
@@ -374,6 +238,29 @@ bool commonio_present (const struct comm
|
|
return (access (db->filename, F_OK) == 0);
|
|
}
|
|
|
|
+int do_fcntl_lock (const char *file, bool log, short type)
|
|
+{
|
|
+ int fd;
|
|
+ struct flock lck = {
|
|
+ .l_type = type,
|
|
+ .l_whence = SEEK_SET,
|
|
+ .l_start = 0,
|
|
+ .l_len = 0,
|
|
+ };
|
|
+
|
|
+ fd = open (file, O_WRONLY, 0600);
|
|
+ if (-1 == fd) {
|
|
+ if (log) {
|
|
+ (void) fprintf (stderr, "%s: %s: %s\n",
|
|
+ Prog, file, strerror (errno));
|
|
+ }
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ fcntl (fd, F_OFD_SETLKW, &lck);
|
|
+ close(fd);
|
|
+ return(1);
|
|
+}
|
|
|
|
int commonio_lock_nowait (struct commonio_db *db, bool log)
|
|
{
|
|
@@ -398,8 +285,7 @@ int commonio_lock_nowait (struct commoni
|
|
}
|
|
snprintf (file, file_len, "%s.%lu",
|
|
db->filename, (unsigned long) getpid ());
|
|
- snprintf (lock, lock_file_len, "%s.lock", db->filename);
|
|
- if (do_lock_file (file, lock, log) != 0) {
|
|
+ if (do_fcntl_lock (db->filename, log, F_WRLCK | F_RDLCK) != 0) {
|
|
db->locked = true;
|
|
lock_count++;
|
|
err = 1;
|
|
@@ -499,8 +385,6 @@ static void dec_lock_count (void)
|
|
|
|
int commonio_unlock (struct commonio_db *db)
|
|
{
|
|
- char lock[1024];
|
|
-
|
|
if (db->isopen) {
|
|
db->readonly = true;
|
|
if (commonio_close (db) == 0) {
|
|
@@ -511,13 +395,8 @@ int commonio_unlock (struct commonio_db
|
|
}
|
|
}
|
|
if (db->locked) {
|
|
- /*
|
|
- * Unlock in reverse order: remove the lock file,
|
|
- * then call ulckpwdf() (if used) on last unlock.
|
|
- */
|
|
db->locked = false;
|
|
- snprintf (lock, sizeof lock, "%s.lock", db->filename);
|
|
- unlink (lock);
|
|
+ do_fcntl_lock (db->filename, false, F_UNLCK);
|
|
dec_lock_count ();
|
|
return 1;
|
|
}
|
|
Index: shadow-4.8.1/lib/commonio.h
|
|
===================================================================
|
|
--- shadow-4.8.1.orig/lib/commonio.h
|
|
+++ shadow-4.8.1/lib/commonio.h
|
|
@@ -150,6 +150,7 @@ extern int commonio_setname (struct comm
|
|
extern bool commonio_present (const struct commonio_db *db);
|
|
extern int commonio_lock (struct commonio_db *);
|
|
extern int commonio_lock_nowait (struct commonio_db *, bool log);
|
|
+extern int do_fcntl_lock (const char *file, bool log, short type);
|
|
extern int commonio_open (struct commonio_db *, int);
|
|
extern /*@observer@*/ /*@null@*/const void *commonio_locate (struct commonio_db *, const char *);
|
|
extern int commonio_update (struct commonio_db *, const void *);
|