* NEWS, lib/commonio.h, lib/commonio.c: Additional messages to

indicate why locking failed.
	* NEWS, lib/commonio.c: Fix the sort algorithm in case of NIS. NIS
	entries were dropped.
	* lib/commonio.c: NIS entries can start by '+' or '-'.
This commit is contained in:
nekral-guest 2011-07-14 13:58:17 +00:00
parent a7fee9db00
commit 39cecdab06
4 changed files with 86 additions and 10 deletions

View File

@ -1,3 +1,11 @@
2011-07-14 Nicolas François <nicolas.francois@centraliens.net>
* NEWS, lib/commonio.h, lib/commonio.c: Additional messages to
indicate why locking failed.
* NEWS, lib/commonio.c: Fix the sort algorithm in case of NIS. NIS
entries were dropped.
* lib/commonio.c: NIS entries can start by '+' or '-'.
2011-07-14 Nicolas François <nicolas.francois@centraliens.net> 2011-07-14 Nicolas François <nicolas.francois@centraliens.net>
* NEWS, src/groupmod.c: When the gshadow file exists but there are * NEWS, src/groupmod.c: When the gshadow file exists but there are

5
NEWS
View File

@ -14,6 +14,7 @@ shadow-4.1.4.3 -> shadow-4.1.5 UNRELEASED
* Added support for ACLs and Extended Attributes in useradd and usermod. * Added support for ACLs and Extended Attributes in useradd and usermod.
Support shall be enabled with the new --with-acl or --with-attr Support shall be enabled with the new --with-acl or --with-attr
configure options. configure options.
* Added diagnosis for lock failures.
-chpasswd -chpasswd
* PAM enabled versions: restore the -e option to allow restoring * PAM enabled versions: restore the -e option to allow restoring
@ -28,6 +29,8 @@ shadow-4.1.4.3 -> shadow-4.1.5 UNRELEASED
* When the gshadow file exists but there are no gshadow entries, an entry * When the gshadow file exists but there are no gshadow entries, an entry
is created if the password is changed and group requires a is created if the password is changed and group requires a
shadow entry. shadow entry.
- grpck
* NIS entries were dropped by -s (sort).
-login -login
* Fixed limits support (non PAM enabled versions only) * Fixed limits support (non PAM enabled versions only)
* Added support for infinite limits and group based limits (non PAM * Added support for infinite limits and group based limits (non PAM
@ -54,6 +57,8 @@ shadow-4.1.4.3 -> shadow-4.1.5 UNRELEASED
* Added support for PAM modules which change PAM_USER. * Added support for PAM modules which change PAM_USER.
- newgrp, sg, groupmems - newgrp, sg, groupmems
* Fix parsing of gshadow entries. * Fix parsing of gshadow entries.
- pwpck
* NIS entries were dropped by -s (sort).
- useradd - useradd
* If the skeleton directory contained hardlinked files, copies of the * If the skeleton directory contained hardlinked files, copies of the
hardlink were removed from the skeleton directory. hardlink were removed from the skeleton directory.

View File

@ -57,7 +57,7 @@
/* local function prototypes */ /* local function prototypes */
static int lrename (const char *, const char *); static int lrename (const char *, const char *);
static int check_link_count (const char *file); static int check_link_count (const char *file);
static int do_lock_file (const char *file, const char *lock); static int do_lock_file (const char *file, const char *lock, bool log);
static /*@null@*/ /*@dependent@*/FILE *fopen_set_perms ( static /*@null@*/ /*@dependent@*/FILE *fopen_set_perms (
const char *name, const char *name,
const char *mode, const char *mode,
@ -135,7 +135,7 @@ static int check_link_count (const char *file)
} }
static int do_lock_file (const char *file, const char *lock) static int do_lock_file (const char *file, const char *lock, bool log)
{ {
int fd; int fd;
pid_t pid; pid_t pid;
@ -145,6 +145,11 @@ static int do_lock_file (const char *file, const char *lock)
fd = open (file, O_CREAT | O_EXCL | O_WRONLY, 0600); fd = open (file, O_CREAT | O_EXCL | O_WRONLY, 0600);
if (-1 == fd) { if (-1 == fd) {
if (log) {
(void) fprintf (stderr,
"%s: %s: %s\n",
Prog, file, strerror (errno));
}
return 0; return 0;
} }
@ -152,6 +157,11 @@ static int do_lock_file (const char *file, const char *lock)
snprintf (buf, sizeof buf, "%lu", (unsigned long) pid); snprintf (buf, sizeof buf, "%lu", (unsigned long) pid);
len = (ssize_t) strlen (buf) + 1; len = (ssize_t) strlen (buf) + 1;
if (write (fd, buf, (size_t) len) != len) { if (write (fd, buf, (size_t) len) != len) {
if (log) {
(void) fprintf (stderr,
"%s: %s: %s\n",
Prog, file, strerror (errno));
}
(void) close (fd); (void) close (fd);
unlink (file); unlink (file);
return 0; return 0;
@ -160,12 +170,22 @@ static int do_lock_file (const char *file, const char *lock)
if (link (file, lock) == 0) { if (link (file, lock) == 0) {
retval = check_link_count (file); retval = check_link_count (file);
if ((0==retval) && log) {
(void) fprintf (stderr,
"%s: %s: lock file already used\n",
Prog, file);
}
unlink (file); unlink (file);
return retval; return retval;
} }
fd = open (lock, O_RDWR); fd = open (lock, O_RDWR);
if (-1 == fd) { if (-1 == fd) {
if (log) {
(void) fprintf (stderr,
"%s: %s: %s\n",
Prog, lock, strerror (errno));
}
unlink (file); unlink (file);
errno = EINVAL; errno = EINVAL;
return 0; return 0;
@ -173,29 +193,60 @@ static int do_lock_file (const char *file, const char *lock)
len = read (fd, buf, sizeof (buf) - 1); len = read (fd, buf, sizeof (buf) - 1);
close (fd); close (fd);
if (len <= 0) { if (len <= 0) {
if (log) {
(void) fprintf (stderr,
"%s: existing lock file %s without a PID\n",
Prog, lock);
}
unlink (file); unlink (file);
errno = EINVAL; errno = EINVAL;
return 0; return 0;
} }
buf[len] = '\0'; buf[len] = '\0';
if (get_pid (buf, &pid) == 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); unlink (file);
errno = EINVAL; errno = EINVAL;
return 0; return 0;
} }
if (kill (pid, 0) == 0) { if (kill (pid, 0) == 0) {
if (log) {
(void) fprintf (stderr,
"%s: lock %s already used by PID %d\n",
Prog, lock, pid);
}
unlink (file); unlink (file);
errno = EEXIST; errno = EEXIST;
return 0; return 0;
} }
if (unlink (lock) != 0) { if (unlink (lock) != 0) {
if (log) {
(void) fprintf (stderr,
"%s: cannot get lock %s: %s\n",
Prog, lock, strerror (errno));
}
unlink (file); unlink (file);
return 0; return 0;
} }
retval = 0; retval = 0;
if ((link (file, lock) == 0) && (check_link_count (file) != 0)) { if (link (file, lock) == 0) {
retval = 1; 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); unlink (file);
@ -328,7 +379,7 @@ bool commonio_present (const struct commonio_db *db)
} }
int commonio_lock_nowait (struct commonio_db *db) int commonio_lock_nowait (struct commonio_db *db, bool log)
{ {
char file[1024]; char file[1024];
char lock[1024]; char lock[1024];
@ -340,7 +391,7 @@ int commonio_lock_nowait (struct commonio_db *db)
snprintf (file, sizeof file, "%s.%lu", snprintf (file, sizeof file, "%s.%lu",
db->filename, (unsigned long) getpid ()); db->filename, (unsigned long) getpid ());
snprintf (lock, sizeof lock, "%s.lock", db->filename); snprintf (lock, sizeof lock, "%s.lock", db->filename);
if (do_lock_file (file, lock) != 0) { if (do_lock_file (file, lock, log) != 0) {
db->locked = true; db->locked = true;
lock_count++; lock_count++;
return 1; return 1;
@ -364,11 +415,16 @@ int commonio_lock (struct commonio_db *db)
*/ */
if (0 == lock_count) { if (0 == lock_count) {
if (lckpwdf () == -1) { if (lckpwdf () == -1) {
if (geteuid () != 0) {
(void) fprintf (stderr,
"%s: Permission denied.\n",
Prog);
}
return 0; /* failure */ return 0; /* failure */
} }
} }
if (commonio_lock_nowait (db) != 0) { if (commonio_lock_nowait (db, true) != 0) {
return 1; /* success */ return 1; /* success */
} }
@ -391,11 +447,13 @@ int commonio_lock (struct commonio_db *db)
if (i > 0) { if (i > 0) {
sleep (LOCK_SLEEP); /* delay between retries */ sleep (LOCK_SLEEP); /* delay between retries */
} }
if (commonio_lock_nowait (db) != 0) { if (commonio_lock_nowait (db, i==LOCK_TRIES-1) != 0) {
return 1; /* success */ return 1; /* success */
} }
/* no unnecessary retries on "permission denied" errors */ /* no unnecessary retries on "permission denied" errors */
if (geteuid () != 0) { if (geteuid () != 0) {
(void) fprintf (stderr, "%s: Permission denied.\n",
Prog);
return 0; return 0;
} }
} }
@ -714,7 +772,8 @@ commonio_sort (struct commonio_db *db, int (*cmp) (const void *, const void *))
(NULL != ptr) (NULL != ptr)
#if KEEP_NIS_AT_END #if KEEP_NIS_AT_END
&& (NULL != ptr->line) && (NULL != ptr->line)
&& ('+' != ptr->line[0]) && ( ('+' != ptr->line[0])
|| ('-' != ptr->line[0]))
#endif #endif
; ;
ptr = ptr->next) { ptr = ptr->next) {
@ -763,7 +822,11 @@ commonio_sort (struct commonio_db *db, int (*cmp) (const void *, const void *))
db->head->prev = NULL; db->head->prev = NULL;
db->head->next = entries[1]; db->head->next = entries[1];
entries[n]->prev = entries[n - 1]; entries[n]->prev = entries[n - 1];
#if KEEP_NIS_AT_END
entries[n]->next = nis;
#else
entries[n]->next = NULL; entries[n]->next = NULL;
#endif
/* Now other elements have prev and next entries */ /* Now other elements have prev and next entries */
for (i = 1; i < n; i++) { for (i = 1; i < n; i++) {

View File

@ -141,7 +141,7 @@ struct commonio_db {
extern int commonio_setname (struct commonio_db *, const char *); extern int commonio_setname (struct commonio_db *, const char *);
extern bool commonio_present (const struct commonio_db *db); extern bool commonio_present (const struct commonio_db *db);
extern int commonio_lock (struct commonio_db *); extern int commonio_lock (struct commonio_db *);
extern int commonio_lock_nowait (struct commonio_db *); extern int commonio_lock_nowait (struct commonio_db *, bool log);
extern int commonio_open (struct commonio_db *, int); extern int commonio_open (struct commonio_db *, int);
extern /*@observer@*/ /*@null@*/const void *commonio_locate (struct commonio_db *, const char *); extern /*@observer@*/ /*@null@*/const void *commonio_locate (struct commonio_db *, const char *);
extern int commonio_update (struct commonio_db *, const void *); extern int commonio_update (struct commonio_db *, const void *);