mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-04 09:09:56 +00:00
PR: bin/3478
Have pwd_mkdb lock the source file while rebuilding the database. When called by programs such as vipw, the source file is a temporary file and this does not conflict with the lock on /etc/master.passwd already held by vipw. When run manually, however, master.passwd is typically specified as the argument and the locking prevents other programs from messing with master.passwd during the database rebuild. Also pwd_mkdb uses a blocking exclusive lock as it may be called from a script. The -N option was added to cause pwd_mkdb to get the lock non-blocking and exit with an error if the attempt fails, again useful for scripts.
This commit is contained in:
parent
0e31b6b580
commit
be648216c6
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=41712
@ -40,6 +40,7 @@
|
||||
.Sh SYNOPSIS
|
||||
.Nm pwd_mkdb
|
||||
.Op Fl C
|
||||
.Op Fl N
|
||||
.Op Fl p
|
||||
.Op Fl d Ar directory
|
||||
.Op Fl s Ar cachesize
|
||||
@ -67,6 +68,12 @@ The options are as follows:
|
||||
.It Fl C
|
||||
Check if the password file is in the correct format. Do not
|
||||
change, add, or remove any files.
|
||||
.It Fl N
|
||||
Tell
|
||||
.Nm Pwd_mkdb
|
||||
to exit with an error if it cannot obtain a lock on the file. By default,
|
||||
we block waiting for a lock on the source file. The lock is held through
|
||||
the rebuilding of the database.
|
||||
.It Fl p
|
||||
Create a Version 7 style password file and install it into
|
||||
.Pa /etc/passwd .
|
||||
|
@ -42,7 +42,7 @@ static const char copyright[] =
|
||||
static char sccsid[] = "@(#)pwd_mkdb.c 8.5 (Berkeley) 4/20/94";
|
||||
#endif
|
||||
static const char rcsid[] =
|
||||
"$Id: pwd_mkdb.c,v 1.27 1998/09/29 20:01:21 dt Exp $";
|
||||
"$Id: pwd_mkdb.c,v 1.28 1998/12/12 16:08:41 foxfair Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -109,6 +109,7 @@ main(argc, argv)
|
||||
char *username;
|
||||
u_int method, methoduid;
|
||||
int Cflag;
|
||||
int nblock = 0;
|
||||
|
||||
Cflag = 0;
|
||||
strcpy(prefix, _PATH_PWD);
|
||||
@ -133,6 +134,9 @@ main(argc, argv)
|
||||
break;
|
||||
case 'v': /* backward compatible */
|
||||
break;
|
||||
case 'N': /* do not wait for lock */
|
||||
nblock = LOCK_NB;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
@ -158,9 +162,30 @@ main(argc, argv)
|
||||
(void)umask(0);
|
||||
|
||||
pname = *argv;
|
||||
/* Open the original password file */
|
||||
if (!(fp = fopen(pname, "r")))
|
||||
error(pname);
|
||||
|
||||
/*
|
||||
* Open and lock the original password file. We have to check
|
||||
* the hardlink count after we get the lock to handle any potential
|
||||
* unlink/rename race.
|
||||
*
|
||||
* This lock is necessary when someone runs pwd_mkdb manually, directly
|
||||
* on master.passwd, to handle the case where a user might try to
|
||||
* change his password while pwd_mkdb is running.
|
||||
*/
|
||||
for (;;) {
|
||||
struct stat st;
|
||||
|
||||
if (!(fp = fopen(pname, "r")))
|
||||
error(pname);
|
||||
if (flock(fileno(fp), LOCK_EX|nblock) < 0)
|
||||
error("flock");
|
||||
if (fstat(fileno(fp), &st) < 0)
|
||||
error(pname);
|
||||
if (st.st_nlink != 0)
|
||||
break;
|
||||
fclose(fp);
|
||||
fp = NULL;
|
||||
}
|
||||
|
||||
/* check only if password database is valid */
|
||||
if (Cflag) {
|
||||
@ -431,8 +456,6 @@ main(argc, argv)
|
||||
|
||||
/* Set master.passwd permissions, in case caller forgot. */
|
||||
(void)fchmod(fileno(fp), S_IRUSR|S_IWUSR);
|
||||
if (fclose(fp) == EOF)
|
||||
error("close fp");
|
||||
|
||||
/* Install as the real password files. */
|
||||
(void)snprintf(buf, sizeof(buf), "%s/%s.tmp", prefix, _MP_DB);
|
||||
@ -454,6 +477,13 @@ main(argc, argv)
|
||||
*/
|
||||
(void)snprintf(buf, sizeof(buf), "%s/%s", prefix, _MASTERPASSWD);
|
||||
mv(pname, buf);
|
||||
|
||||
/*
|
||||
* Close locked password file after rename()
|
||||
*/
|
||||
if (fclose(fp) == EOF)
|
||||
error("close fp");
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user