Home | History | Annotate | Line # | Download | only in src
      1 /*
      2  * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
      3  *
      4  * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
      5  *                                  and others.
      6  *
      7  * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
      8  * Portions Copyright (C) 1989-1992, Brian Berliner
      9  *
     10  * You may distribute under the terms of the GNU General Public License as
     11  * specified in the README file that comes with the CVS source distribution.
     12  *
     13  * Set Lock
     14  *
     15  * Lock file support for CVS.
     16  */
     17 #include <sys/cdefs.h>
     18 __RCSID("$NetBSD: lock.c,v 1.5 2016/05/17 14:00:09 christos Exp $");
     19 
     20 /* The node Concurrency in doc/cvs.texinfo has a brief introduction to
     21    how CVS locks function, and some of the user-visible consequences of
     22    their existence.  Here is a summary of why they exist (and therefore,
     23    the consequences of hacking CVS to read a repository without creating
     24    locks):
     25 
     26    There are two uses.  One is the ability to prevent there from being
     27    two writers at the same time.  This is necessary for any number of
     28    reasons (fileattr code, probably others).  Commit needs to lock the
     29    whole tree so that nothing happens between the up-to-date check and
     30    the actual checkin.
     31 
     32    The second use is the ability to ensure that there is not a writer
     33    and a reader at the same time (several readers are allowed).  Reasons
     34    for this are:
     35 
     36    * Readlocks ensure that once CVS has found a collection of rcs
     37    files using Find_Names, the files will still exist when it reads
     38    them (they may have moved in or out of the attic).
     39 
     40    * Readlocks provide some modicum of consistency, although this is
     41    kind of limited--see the node Concurrency in cvs.texinfo.
     42 
     43    * Readlocks ensure that the RCS file does not change between
     44    RCS_parse and RCS_reparsercsfile time.  This one strikes me as
     45    important, although I haven't thought up what bad scenarios might
     46    be.
     47 
     48    * Readlocks ensure that we won't find the file in the state in
     49    which it is in between the calls to add_rcs_file and RCS_checkin in
     50    commit.c (when a file is being added).  This state is a state in
     51    which the RCS file parsing routines in rcs.c cannot parse the file.
     52 
     53    * Readlocks ensure that a reader won't try to look at a
     54    half-written fileattr file (fileattr is not updated atomically).
     55 
     56    (see also the description of anonymous read-only access in
     57    "Password authentication security" node in doc/cvs.texinfo).
     58 
     59    While I'm here, I'll try to summarize a few random suggestions
     60    which periodically get made about how locks might be different:
     61 
     62    1.  Check for EROFS.  Maybe useful, although in the presence of NFS
     63    EROFS does *not* mean that the file system is unchanging.
     64 
     65    2.  Provide an option to disable locks for operations which only
     66    read (see above for some of the consequences).
     67 
     68    3.  Have a server internally do the locking.  Probably a good
     69    long-term solution, and many people have been working hard on code
     70    changes which would eventually make it possible to have a server
     71    which can handle various connections in one process, but there is
     72    much, much work still to be done before this is feasible.  */
     73 
     74 #include "cvs.h"
     75 
     76 
     77 
     78 struct lock {
     79     /* This is the directory in which we may have a lock named by the
     80        readlock variable, a lock named by the writelock variable, and/or
     81        a lock named CVSLCK.  The storage is not allocated along with the
     82        struct lock; it is allocated by the Reader_Lock caller or in the
     83        case of promotablelocks, it is just a pointer to the storage allocated
     84        for the ->key field.  */
     85     const char *repository;
     86 
     87     /* The name of the lock files. */
     88     char *file1;
     89 #ifdef LOCK_COMPATIBILITY
     90     char *file2;
     91 #endif /* LOCK_COMPATIBILITY */
     92 
     93     /* The name of the master lock dir.  Usually CVSLCK.  */
     94     const char *lockdirname;
     95 
     96     /* The full path to the lock dir, if we are currently holding it.
     97      *
     98      * This will be LOCKDIRNAME catted onto REPOSITORY.  We waste a little
     99      * space by storing it, but save a later malloc/free.
    100      */
    101     char *lockdir;
    102 
    103     /* Note there is no way of knowing whether the readlock and writelock
    104        exist.  The code which sets the locks doesn't use SIG_beginCrSect
    105        to set a flag like we do for CVSLCK.  */
    106     bool free_repository;
    107 };
    108 
    109 static void remove_locks (void);
    110 static int set_lock (struct lock *lock, int will_wait);
    111 static void clear_lock (struct lock *lock);
    112 static void set_lockers_name (struct stat *statp);
    113 
    114 /* Malloc'd array containing the username of the whoever has the lock.
    115    Will always be non-NULL in the cases where it is needed.  */
    116 static char *lockers_name;
    117 /* Malloc'd array specifying name of a readlock within a directory.
    118    Or NULL if none.  */
    119 static char *readlock;
    120 /* Malloc'd array specifying name of a writelock within a directory.
    121    Or NULL if none.  */
    122 static char *writelock;
    123 /* Malloc'd array specifying name of a promotablelock within a directory.
    124    Or NULL if none.  */
    125 static char *promotablelock;
    126 static List *locklist;
    127 
    128 #define L_OK		0		/* success */
    129 #define L_ERROR		1		/* error condition */
    130 #define L_LOCKED	2		/* lock owned by someone else */
    131 
    132 /* This is the (single) readlock which is set by Reader_Lock.  The
    133    repository field is NULL if there is no such lock.  */
    134 #ifdef LOCK_COMPATIBILITY
    135 static struct lock global_readlock = {NULL, NULL, NULL, CVSLCK, NULL, false};
    136 static struct lock global_writelock = {NULL, NULL, NULL, CVSLCK, NULL, false};
    137 
    138 static struct lock global_history_lock = {NULL, NULL, NULL, CVSHISTORYLCK,
    139 					  NULL, false};
    140 static struct lock global_val_tags_lock = {NULL, NULL, NULL, CVSVALTAGSLCK,
    141 					   NULL, false};
    142 #else
    143 static struct lock global_readlock = {NULL, NULL, CVSLCK, NULL, false};
    144 static struct lock global_writelock = {NULL, NULL, CVSLCK, NULL, false};
    145 
    146 static struct lock global_history_lock = {NULL, NULL, CVSHISTORYLCK, NULL,
    147 					  false};
    148 static struct lock global_val_tags_lock = {NULL, NULL, CVSVALTAGSLCK, NULL,
    149 					   false};
    150 #endif /* LOCK_COMPATIBILITY */
    151 
    152 /* List of locks set by lock_tree_for_write.  This is redundant
    153    with locklist, sort of.  */
    154 static List *lock_tree_list;
    155 
    156 
    157 /*
    158  * Find the root directory in the repository directory
    159  */
    160 static int
    161 find_root (const char *repository, char *rootdir)
    162 {
    163     struct stat strep, stroot;
    164     char *p = NULL, *q = NULL;
    165     size_t len;
    166 
    167     if (stat (rootdir, &stroot) == -1)
    168 	return -1;
    169     len = strlen (repository);
    170     do {
    171 	if (p != NULL) {
    172 	    len = p - repository;
    173 	    *p = '\0';
    174 	}
    175 	if (q != NULL)
    176 	    *q = '/';
    177 	if (stat(repository, &strep) == -1) {
    178 	    if (p != NULL)
    179 		*p = '/';
    180 	    return -1;
    181 	}
    182 	if (strep.st_dev == stroot.st_dev && strep.st_ino == stroot.st_ino) {
    183 	    if (p != NULL)
    184 		*p = '/';
    185 	    if (q != NULL)
    186 		*q = '/';
    187 	    return len;
    188 	}
    189 	q = p;
    190     } while ((p = strrchr (repository, '/')) != NULL);
    191     return -1;
    192 }
    193 
    194 /* Return a newly malloc'd string containing the name of the lock for the
    195    repository REPOSITORY and the lock file name within that directory
    196    NAME.  Also create the directories in which to put the lock file
    197    if needed (if we need to, could save system call(s) by doing
    198    that only if the actual operation fails.  But for now we'll keep
    199    things simple).  */
    200 static char *
    201 lock_name (const char *repository, const char *name)
    202 {
    203     char *retval;
    204     const char *p;
    205     char *q;
    206     const char *short_repos;
    207     mode_t save_umask = 0000;
    208     int saved_umask = 0, len;
    209 
    210     TRACE (TRACE_FLOW, "lock_name (%s, %s)",
    211 	   repository  ? repository : "(null)", name ? name : "(null)");
    212 
    213     if (!config->lock_dir)
    214     {
    215 	/* This is the easy case.  Because the lock files go directly
    216 	   in the repository, no need to create directories or anything.  */
    217 	assert (name != NULL);
    218 	assert (repository != NULL);
    219 	retval = Xasprintf ("%s/%s", repository, name);
    220     }
    221     else
    222     {
    223 	struct stat sb;
    224 	mode_t new_mode = 0;
    225 
    226 	/* The interesting part of the repository is the part relative
    227 	   to CVSROOT.  */
    228 	assert (current_parsed_root != NULL);
    229 	assert (current_parsed_root->directory != NULL);
    230 	/*
    231 	 * Unfortunately, string comparisons are not enough because we
    232 	 * might have symlinks present
    233 	 */
    234 	len = find_root(repository, current_parsed_root->directory);
    235 	if (len == -1)
    236 	    error (1, 0, "%s not found in %s",
    237 		repository, current_parsed_root->directory);
    238 	short_repos = repository + len + 1;
    239 
    240 	if (strcmp (repository, current_parsed_root->directory) == 0)
    241 	    short_repos = ".";
    242 	else
    243 	    assert (short_repos[-1] == '/');
    244 
    245 	retval = xmalloc (strlen (config->lock_dir)
    246 			  + strlen (short_repos)
    247 			  + strlen (name)
    248 			  + 10);
    249 	strcpy (retval, config->lock_dir);
    250 	q = retval + strlen (retval);
    251 	*q++ = '/';
    252 
    253 	strcpy (q, short_repos);
    254 
    255 	/* In the common case, where the directory already exists, let's
    256 	   keep it to one system call.  */
    257 	if (stat (retval, &sb) < 0)
    258 	{
    259 	    /* If we need to be creating more than one directory, we'll
    260 	       get the existence_error here.  */
    261 	    if (!existence_error (errno))
    262 		error (1, errno, "cannot stat directory %s", retval);
    263 	}
    264 	else
    265 	{
    266 	    if (S_ISDIR (sb.st_mode))
    267 		goto created;
    268 	    else
    269 		error (1, 0, "%s is not a directory", retval);
    270 	}
    271 
    272 	/* Now add the directories one at a time, so we can create
    273 	   them if needed.
    274 
    275 	   The idea behind the new_mode stuff is that the directory we
    276 	   end up creating will inherit permissions from its parent
    277 	   directory (we re-set new_mode with each EEXIST).  CVSUMASK
    278 	   isn't right, because typically the reason for LockDir is to
    279 	   use a different set of permissions.  We probably want to
    280 	   inherit group ownership also (but we don't try to deal with
    281 	   that, some systems do it for us either always or when g+s is on).
    282 
    283 	   We don't try to do anything about the permissions on the lock
    284 	   files themselves.  The permissions don't really matter so much
    285 	   because the locks will generally be removed by the process
    286 	   which created them.  */
    287 
    288 	if (stat (config->lock_dir, &sb) < 0)
    289 	    error (1, errno, "cannot stat %s", config->lock_dir);
    290 	new_mode = sb.st_mode;
    291 	save_umask = umask (0000);
    292 	saved_umask = 1;
    293 
    294 	p = short_repos;
    295 	while (1)
    296 	{
    297 	    while (!ISSLASH (*p) && *p != '\0')
    298 		++p;
    299 	    if (ISSLASH (*p))
    300 	    {
    301 		strncpy (q, short_repos, p - short_repos);
    302 		q[p - short_repos] = '\0';
    303 		if (!ISSLASH (q[p - short_repos - 1])
    304 		    && CVS_MKDIR (retval, new_mode) < 0)
    305 		{
    306 		    int saved_errno = errno;
    307 		    if (saved_errno != EEXIST)
    308 			error (1, errno, "cannot make directory %s", retval);
    309 		    else
    310 		    {
    311 			if (stat (retval, &sb) < 0)
    312 			    error (1, errno, "cannot stat %s", retval);
    313 			new_mode = sb.st_mode;
    314 		    }
    315 		}
    316 		++p;
    317 	    }
    318 	    else
    319 	    {
    320 		strcpy (q, short_repos);
    321 		if (CVS_MKDIR (retval, new_mode) < 0
    322 		    && errno != EEXIST)
    323 		    error (1, errno, "cannot make directory %s", retval);
    324 		goto created;
    325 	    }
    326 	}
    327     created:;
    328 
    329 	strcat (retval, "/");
    330 	strcat (retval, name);
    331 
    332 	if (saved_umask)
    333 	{
    334 	    assert (umask (save_umask) == 0000);
    335 	    saved_umask = 0;
    336 	}
    337     }
    338     return retval;
    339 }
    340 
    341 
    342 
    343 /* Remove the lock files.  For interrupt purposes, it can be assumed that the
    344  * first thing this function does is set lock->repository to NULL.
    345  *
    346  * INPUTS
    347  *   lock	The lock to remove.
    348  *   free	True if this lock directory will not be reused (free
    349  *		lock->repository if necessary).
    350  */
    351 static void
    352 remove_lock_files (struct lock *lock, bool free_repository)
    353 {
    354     TRACE (TRACE_FLOW, "remove_lock_files (%s)", lock->repository);
    355 
    356     /* If lock->file is set, the lock *might* have been created, but since
    357      * Reader_Lock & lock_dir_for_write don't use SIG_beginCrSect the way that
    358      * set_lock does, we don't know that.  That is why we need to check for
    359      * existence_error here.
    360      */
    361     if (lock->file1)
    362     {
    363 	char *tmp = lock->file1;
    364 	lock->file1 = NULL;
    365 	if (CVS_UNLINK (tmp) < 0 && ! existence_error (errno))
    366 	    error (0, errno, "failed to remove lock %s", tmp);
    367 	free (tmp);
    368     }
    369 #ifdef LOCK_COMPATIBILITY
    370     if (lock->file2)
    371     {
    372 	char *tmp = lock->file2;
    373 	lock->file2 = NULL;
    374 	if (CVS_UNLINK (tmp) < 0 && ! existence_error (errno))
    375 	    error (0, errno, "failed to remove lock %s", tmp);
    376 	free (tmp);
    377     }
    378 #endif /* LOCK_COMPATIBILITY */
    379 
    380     clear_lock (lock);
    381 
    382     /* And free the repository string.  We don't really have to set the
    383      * repository string to NULL first since there is no harm in running any of
    384      * the above code twice.
    385      *
    386      * Use SIG_beginCrSect since otherwise we might be interrupted between
    387      * checking whether free_repository is set and freeing stuff.
    388      */
    389     if (free_repository)
    390     {
    391 	SIG_beginCrSect ();
    392 	if (lock->free_repository)
    393 	{
    394 	    free ((char *)lock->repository);
    395 	    lock->free_repository = false;
    396 	}
    397 	lock->repository = NULL;
    398 	SIG_endCrSect ();
    399     }
    400 }
    401 
    402 
    403 
    404 /*
    405  * Clean up outstanding read and write locks and free their storage.
    406  */
    407 void
    408 Simple_Lock_Cleanup (void)
    409 {
    410     TRACE (TRACE_FUNCTION, "Simple_Lock_Cleanup()");
    411 
    412     /* Avoid interrupts while accessing globals the interrupt handlers might
    413      * make use of.
    414      */
    415     SIG_beginCrSect();
    416 
    417     /* clean up simple read locks (if any) */
    418     if (global_readlock.repository != NULL)
    419 	remove_lock_files (&global_readlock, true);
    420     /* See note in Lock_Cleanup() below.  */
    421     SIG_endCrSect();
    422 
    423     SIG_beginCrSect();
    424 
    425     /* clean up simple write locks (if any) */
    426     if (global_writelock.repository != NULL)
    427 	remove_lock_files (&global_writelock, true);
    428     /* See note in Lock_Cleanup() below.  */
    429     SIG_endCrSect();
    430 
    431     SIG_beginCrSect();
    432 
    433     /* clean up simple write locks (if any) */
    434     if (global_history_lock.repository)
    435 	remove_lock_files (&global_history_lock, true);
    436     SIG_endCrSect();
    437 
    438     SIG_beginCrSect();
    439 
    440     if (global_val_tags_lock.repository)
    441 	remove_lock_files (&global_val_tags_lock, true);
    442     /* See note in Lock_Cleanup() below.  */
    443     SIG_endCrSect();
    444 }
    445 
    446 
    447 
    448 /*
    449  * Clean up all outstanding locks and free their storage.
    450  *
    451  * NOTES
    452  *   This function needs to be reentrant since a call to exit() can cause a
    453  *   call to this function, which can then be interrupted by a signal, which
    454  *   can cause a second call to this function.
    455  *
    456  * RETURNS
    457  *   Nothing.
    458  */
    459 void
    460 Lock_Cleanup (void)
    461 {
    462     TRACE (TRACE_FUNCTION, "Lock_Cleanup()");
    463 
    464     /* FIXME: Do not perform buffered I/O from an interrupt handler like
    465      * this (via error).  However, I'm leaving the error-calling code there
    466      * in the hope that on the rare occasion the error call is actually made
    467      * (e.g., a fluky I/O error or permissions problem prevents the deletion
    468      * of a just-created file) reentrancy won't be an issue.
    469      */
    470 
    471     remove_locks ();
    472 
    473     /* Avoid being interrupted during calls which set globals to NULL.  This
    474      * avoids having interrupt handlers attempt to use these global variables
    475      * in inconsistent states.
    476      *
    477      * This isn't always necessary, because sometimes we are called via exit()
    478      * or the interrupt handler, in which case signals will already be blocked,
    479      * but sometimes we might be called from elsewhere.
    480      */
    481     SIG_beginCrSect();
    482     dellist (&lock_tree_list);
    483     /*  Unblocking allows any signal to be processed as soon as possible.  This
    484      *  isn't really necessary, but since we know signals can cause us to be
    485      *  called, why not avoid having blocks of code run twice.
    486      */
    487     SIG_endCrSect();
    488 }
    489 
    490 
    491 
    492 /*
    493  * walklist proc for removing a list of locks
    494  */
    495 static int
    496 unlock_proc (Node *p, void *closure)
    497 {
    498     remove_lock_files (p->data, false);
    499     return 0;
    500 }
    501 
    502 
    503 
    504 /*
    505  * Remove locks without discarding the lock information.
    506  */
    507 static void
    508 remove_locks (void)
    509 {
    510     TRACE (TRACE_FLOW, "remove_locks()");
    511 
    512     Simple_Lock_Cleanup ();
    513 
    514     /* clean up promotable locks (if any) */
    515     SIG_beginCrSect();
    516     if (locklist != NULL)
    517     {
    518 	/* Use a tmp var since any of these functions could call exit, causing
    519 	 * us to be called a second time.
    520 	 */
    521 	List *tmp = locklist;
    522 	locklist = NULL;
    523 	walklist (tmp, unlock_proc, NULL);
    524     }
    525     SIG_endCrSect();
    526 }
    527 
    528 
    529 
    530 /*
    531  * Set the global readlock variable if it isn't already.
    532  */
    533 static void
    534 set_readlock_name (void)
    535 {
    536     if (readlock == NULL)
    537     {
    538 	readlock = Xasprintf (
    539 #ifdef HAVE_LONG_FILE_NAMES
    540 			      "%s.%s.%ld", CVSRFL, hostname,
    541 #else
    542 			      "%s.%ld", CVSRFL,
    543 #endif
    544 			      (long) getpid ());
    545     }
    546 }
    547 
    548 
    549 
    550 /*
    551  * Create a lock file for readers
    552  */
    553 int
    554 Reader_Lock (char *xrepository)
    555 {
    556     int err = 0;
    557     FILE *fp;
    558 
    559     if (nolock)
    560 	return (0);
    561 
    562     TRACE (TRACE_FUNCTION, "Reader_Lock(%s)", xrepository);
    563 
    564     if (noexec || readonlyfs)
    565 	return 0;
    566 
    567     /* we only do one directory at a time for read locks!  */
    568     if (global_readlock.repository != NULL)
    569     {
    570 	error (0, 0, "Reader_Lock called while read locks set - Help!");
    571 	return 1;
    572     }
    573 
    574     set_readlock_name ();
    575 
    576     /* remember what we're locking (for Lock_Cleanup) */
    577     global_readlock.repository = xstrdup (xrepository);
    578     global_readlock.free_repository = true;
    579 
    580     /* get the lock dir for our own */
    581     if (set_lock (&global_readlock, 1) != L_OK)
    582     {
    583 	error (0, 0, "failed to obtain dir lock in repository `%s'",
    584 	       xrepository);
    585 	if (readlock != NULL)
    586 	    free (readlock);
    587 	readlock = NULL;
    588 	/* We don't set global_readlock.repository to NULL.  I think this
    589 	   only works because recurse.c will give a fatal error if we return
    590 	   a nonzero value.  */
    591 	return 1;
    592     }
    593 
    594     /* write a read-lock */
    595     global_readlock.file1 = lock_name (xrepository, readlock);
    596     if ((fp = CVS_FOPEN (global_readlock.file1, "w+")) == NULL
    597 	|| fclose (fp) == EOF)
    598     {
    599 	error (0, errno, "cannot create read lock in repository `%s'",
    600 	       xrepository);
    601 	err = 1;
    602     }
    603 
    604     /* free the lock dir */
    605     clear_lock (&global_readlock);
    606 
    607     return err;
    608 }
    609 
    610 
    611 
    612 /*
    613  * lock_exists() returns 0 if there is no lock file matching FILEPAT in
    614  * the repository but not IGNORE; else 1 is returned, to indicate that the
    615  * caller should sleep a while and try again.
    616  *
    617  * INPUTS
    618  *   repository		The repository directory to search for locks.
    619  *   filepat		The file name pattern to search for.
    620  *   ignore		The name of a single file which can be ignored.
    621  *
    622  * GLOBALS
    623  *   lockdir		The lock dir external to the repository, if any.
    624  *
    625  * RETURNS
    626  *   0		No lock matching FILEPAT and not IGNORE exists.
    627  *   1		Otherwise and on error.
    628  *
    629  * ERRORS
    630  *  In the case where errors are encountered reading the directory, a warning
    631  *  message is printed, 1 is is returned and ERRNO is left set.
    632  */
    633 static int
    634 lock_exists (const char *repository, const char *filepat, const char *ignore)
    635 {
    636     char *lockdir;
    637     char *line;
    638     DIR *dirp;
    639     struct dirent *dp;
    640     struct stat sb;
    641     int ret;
    642 #ifdef CVS_FUDGELOCKS
    643     time_t now;
    644     (void)time (&now);
    645 #endif
    646 
    647     TRACE (TRACE_FLOW, "lock_exists (%s, %s, %s)",
    648 	   repository, filepat, ignore ? ignore : "(null)");
    649 
    650     lockdir = lock_name (repository, "");
    651     lockdir[strlen (lockdir) - 1] = '\0';   /* remove trailing slash */
    652 
    653     do {
    654 	if ((dirp = CVS_OPENDIR (lockdir)) == NULL)
    655 	    error (1, 0, "cannot open directory %s", lockdir);
    656 
    657 	ret = 0;
    658 	errno = 0;
    659 	while ((dp = CVS_READDIR (dirp)) != NULL)
    660 	{
    661 	    if (CVS_FNMATCH (filepat, dp->d_name, 0) == 0)
    662 	    {
    663 		/* FIXME: the basename conversion below should be replaced with
    664 		 * a call to the GNULIB basename function once it is imported.
    665 		 */
    666 		/* ignore our plock, if any */
    667 		if (ignore && !fncmp (ignore, dp->d_name))
    668 		    continue;
    669 
    670 		line = Xasprintf ("%s/%s", lockdir, dp->d_name);
    671 		if (stat (line, &sb) != -1)
    672 		{
    673 #ifdef CVS_FUDGELOCKS
    674 		    /*
    675 		     * If the create time of the file is more than CVSLCKAGE
    676 		     * seconds ago, try to clean-up the lock file, and if
    677 		     * successful, re-open the directory and try again.
    678 		     */
    679 		    if (now >= (sb.st_ctime + CVSLCKAGE) &&
    680                         CVS_UNLINK (line) != -1)
    681 		    {
    682 			free (line);
    683 			ret = -1;
    684 			break;
    685 		    }
    686 #endif
    687 		    set_lockers_name (&sb);
    688 		}
    689 		else
    690 		{
    691 		    /* If the file doesn't exist, it just means that it
    692 		     * disappeared between the time we did the readdir and the
    693 		     * time we did the stat.
    694 		     */
    695 		    if (!existence_error (errno))
    696 			error (0, errno, "cannot stat %s", line);
    697 		}
    698 		errno = 0;
    699 		free (line);
    700 		ret = 1;
    701 		break;
    702 	    }
    703 	    errno = 0;
    704 	}
    705 	if (errno != 0)
    706 	    error (0, errno, "error reading directory %s", repository);
    707 
    708 	CVS_CLOSEDIR (dirp);
    709     } while (ret < 0);
    710 
    711     if (lockdir != NULL)
    712 	free (lockdir);
    713     return ret;
    714 }
    715 
    716 
    717 
    718 /*
    719  * readers_exist() returns 0 if there are no reader lock files remaining in
    720  * the repository; else 1 is returned, to indicate that the caller should
    721  * sleep a while and try again.
    722  *
    723  * See lock_exists() for argument detail.
    724  */
    725 static int
    726 readers_exist (const char *repository)
    727 {
    728     TRACE (TRACE_FLOW, "readers_exist (%s)", repository);
    729 
    730     /* It is only safe to ignore a readlock set by our process if it was set as
    731      * a safety measure to prevent older CVS processes from ignoring our
    732      * promotable locks.  The code to ignore these readlocks can be removed
    733      * once it is deemed unlikely that anyone will be using CVS servers earlier
    734      * than version 1.12.4.
    735      */
    736     return lock_exists (repository, CVSRFLPAT,
    737 #ifdef LOCK_COMPATIBILITY
    738                          findnode (locklist, repository) ? readlock :
    739 #endif /* LOCK_COMPATIBILITY */
    740 			 NULL);
    741 }
    742 
    743 
    744 
    745 /*
    746  * promotable_exists() returns 0 if there is no promotable lock file in
    747  * the repository; else 1 is returned, to indicate that the caller should
    748  * sleep a while and try again.
    749  *
    750  * See lock_exists() for argument detail.
    751  */
    752 static int
    753 promotable_exists (const char *repository)
    754 {
    755     TRACE (TRACE_FLOW, "promotable_exists (%s)", repository);
    756     return lock_exists (repository, CVSPFLPAT, promotablelock);
    757 }
    758 
    759 
    760 
    761 /*
    762  * Lock a list of directories for writing
    763  */
    764 static char *lock_error_repos;
    765 static int lock_error;
    766 
    767 
    768 
    769 /*
    770  * Create a lock file for potential writers returns L_OK if lock set ok,
    771  * L_LOCKED if lock held by someone else or L_ERROR if an error occurred.
    772  */
    773 static int
    774 set_promotable_lock (struct lock *lock)
    775 {
    776     int status;
    777     FILE *fp;
    778 
    779     TRACE (TRACE_FUNCTION, "set_promotable_lock(%s)",
    780 	   lock->repository ? lock->repository : "(null)");
    781 
    782     if (promotablelock == NULL)
    783     {
    784 	promotablelock = Xasprintf (
    785 #ifdef HAVE_LONG_FILE_NAMES
    786 				    "%s.%s.%ld", CVSPFL, hostname,
    787 #else
    788 				    "%s.%ld", CVSPFL,
    789 #endif
    790 				    (long) getpid());
    791     }
    792 
    793     /* make sure the lock dir is ours (not necessarily unique to us!) */
    794     status = set_lock (lock, 0);
    795     if (status == L_OK)
    796     {
    797 	/* we now own a promotable lock - make sure there are no others */
    798 	if (promotable_exists (lock->repository))
    799 	{
    800 	    /* clean up the lock dir */
    801 	    clear_lock (lock);
    802 
    803 	    /* indicate we failed due to read locks instead of error */
    804 	    return L_LOCKED;
    805 	}
    806 
    807 	/* write the promotable-lock file */
    808 	lock->file1 = lock_name (lock->repository, promotablelock);
    809 	if ((fp = CVS_FOPEN (lock->file1, "w+")) == NULL || fclose (fp) == EOF)
    810 	{
    811 	    int xerrno = errno;
    812 
    813 	    if (CVS_UNLINK (lock->file1) < 0 && ! existence_error (errno))
    814 		error (0, errno, "failed to remove lock %s", lock->file1);
    815 
    816 	    /* free the lock dir */
    817 	    clear_lock (lock);
    818 
    819 	    /* return the error */
    820 	    error (0, xerrno,
    821 		   "cannot create promotable lock in repository `%s'",
    822 		   lock->repository);
    823 	    return L_ERROR;
    824 	}
    825 
    826 #ifdef LOCK_COMPATIBILITY
    827 	/* write the read-lock file.  We only do this so that older versions of
    828 	 * CVS will not think it is okay to create a write lock.  When it is
    829 	 * decided that versions of CVS earlier than 1.12.4 are not likely to
    830 	 * be used, this code can be removed.
    831 	 */
    832 	set_readlock_name ();
    833 	lock->file2 = lock_name (lock->repository, readlock);
    834 	if ((fp = CVS_FOPEN (lock->file2, "w+")) == NULL || fclose (fp) == EOF)
    835 	{
    836 	    int xerrno = errno;
    837 
    838 	    if ( CVS_UNLINK (lock->file2) < 0 && ! existence_error (errno))
    839 		error (0, errno, "failed to remove lock %s", lock->file2);
    840 
    841 	    /* free the lock dir */
    842 	    clear_lock (lock);
    843 
    844 	    /* Remove the promotable lock.  */
    845 	    lock->file2 = NULL;
    846 	    remove_lock_files (lock, false);
    847 
    848 	    /* return the error */
    849 	    error (0, xerrno,
    850 		   "cannot create read lock in repository `%s'",
    851 		   lock->repository);
    852 	    return L_ERROR;
    853 	}
    854 #endif /* LOCK_COMPATIBILITY */
    855 
    856 	clear_lock (lock);
    857 
    858 	return L_OK;
    859     }
    860     else
    861 	return status;
    862 }
    863 
    864 
    865 
    866 /*
    867  * walklist proc for setting write locks.  Mostly just a wrapper for the
    868  * set_promotable_lock function, which has a prettier API, but no other good
    869  * reason for existing separately.
    870  *
    871  * INPUTS
    872  *   p		The current node, as determined by walklist().
    873  *   closure	Not used.
    874  *
    875  * GLOBAL INPUTS
    876  *   lock_error		Any previous error encountered while attempting to get
    877  *                      a lock.
    878  *
    879  * GLOBAL OUTPUTS
    880  *   lock_error		Set if we encounter an error attempting to get axi
    881  *			promotable lock.
    882  *   lock_error_repos	Set so that if we set lock_error later functions will
    883  *			be able to report where the other process's lock was
    884  *			encountered.
    885  *
    886  * RETURNS
    887  *   0 for no error.
    888  */
    889 static int
    890 set_promotablelock_proc (Node *p, void *closure)
    891 {
    892     /* if some lock was not OK, just skip this one */
    893     if (lock_error != L_OK)
    894 	return 0;
    895 
    896     /* apply the write lock */
    897     lock_error_repos = p->key;
    898     lock_error = set_promotable_lock ((struct lock *)p->data);
    899     return 0;
    900 }
    901 
    902 
    903 
    904 /*
    905  * Print out a message that the lock is still held, then sleep a while.
    906  */
    907 static void
    908 lock_wait (const char *repos)
    909 {
    910     time_t now;
    911     char *msg;
    912     struct tm *tm_p;
    913 
    914     (void) time (&now);
    915     tm_p = gmtime (&now);
    916     msg = Xasprintf ("[%8.8s] waiting for %s's lock in %s",
    917 		     (tm_p ? asctime (tm_p) : ctime (&now)) + 11,
    918 		     lockers_name, repos);
    919     error (0, 0, "%s", msg);
    920     /* Call cvs_flusherr to ensure that the user sees this message as
    921        soon as possible.  */
    922     cvs_flusherr ();
    923     free (msg);
    924     (void)sleep (CVSLCKSLEEP);
    925 }
    926 
    927 
    928 
    929 /*
    930  * Print out a message when we obtain a lock.
    931  */
    932 static void
    933 lock_obtained (const char *repos)
    934 {
    935     time_t now;
    936     char *msg;
    937     struct tm *tm_p;
    938 
    939     (void) time (&now);
    940     tm_p = gmtime (&now);
    941     msg = Xasprintf ("[%8.8s] obtained lock in %s",
    942 		     (tm_p ? asctime (tm_p) : ctime (&now)) + 11, repos);
    943     error (0, 0, "%s", msg);
    944     /* Call cvs_flusherr to ensure that the user sees this message as
    945        soon as possible.  */
    946     cvs_flusherr ();
    947     free (msg);
    948 }
    949 
    950 
    951 
    952 static int
    953 lock_list_promotably (List *list)
    954 {
    955     char *wait_repos;
    956 
    957     TRACE (TRACE_FLOW, "lock_list_promotably ()");
    958 
    959     if (nolock)
    960 	return (0);
    961     if (noexec)
    962 	return 0;
    963 
    964     if (readonlyfs) {
    965 	error (0, 0,
    966 	       "promotable lock failed.\n\
    967 WARNING: Read-only repository access mode selected via `cvs -R'.\n\
    968 Attempting to write to a read-only filesystem is not allowed.");
    969 	return 1;
    970     }
    971 
    972     /* We only know how to do one list at a time */
    973     if (locklist != NULL)
    974     {
    975 	error (0, 0,
    976 	       "lock_list_promotably called while promotable locks set - Help!");
    977 	return 1;
    978     }
    979 
    980     wait_repos = NULL;
    981     for (;;)
    982     {
    983 	/* try to lock everything on the list */
    984 	lock_error = L_OK;		/* init for set_promotablelock_proc */
    985 	lock_error_repos = NULL;	/* init for set_promotablelock_proc */
    986 	locklist = list;		/* init for Lock_Cleanup */
    987 	if (lockers_name != NULL)
    988 	    free (lockers_name);
    989 	lockers_name = xstrdup ("unknown");
    990 
    991 	(void) walklist (list, set_promotablelock_proc, NULL);
    992 
    993 	switch (lock_error)
    994 	{
    995 	    case L_ERROR:		/* Real Error */
    996 		if (wait_repos != NULL)
    997 		    free (wait_repos);
    998 		Lock_Cleanup ();	/* clean up any locks we set */
    999 		error (0, 0, "lock failed - giving up");
   1000 		return 1;
   1001 
   1002 	    case L_LOCKED:		/* Someone already had a lock */
   1003 		remove_locks ();	/* clean up any locks we set */
   1004 		lock_wait (lock_error_repos); /* sleep a while and try again */
   1005 		wait_repos = xstrdup (lock_error_repos);
   1006 		continue;
   1007 
   1008 	    case L_OK:			/* we got the locks set */
   1009 	        if (wait_repos != NULL)
   1010 		{
   1011 		    lock_obtained (wait_repos);
   1012 		    free (wait_repos);
   1013 		}
   1014 		return 0;
   1015 
   1016 	    default:
   1017 		if (wait_repos != NULL)
   1018 		    free (wait_repos);
   1019 		error (0, 0, "unknown lock status %d in lock_list_promotably",
   1020 		       lock_error);
   1021 		return 1;
   1022 	}
   1023     }
   1024 }
   1025 
   1026 
   1027 
   1028 /*
   1029  * Set the static variable lockers_name appropriately, based on the stat
   1030  * structure passed in.
   1031  */
   1032 static void
   1033 set_lockers_name (struct stat *statp)
   1034 {
   1035     struct passwd *pw;
   1036 
   1037     if (lockers_name != NULL)
   1038 	free (lockers_name);
   1039     pw = (struct passwd *) getpwuid (statp->st_uid);
   1040     if (pw != NULL)
   1041 	lockers_name = xstrdup (pw->pw_name);
   1042     else
   1043 	lockers_name = Xasprintf ("uid%lu", (unsigned long) statp->st_uid);
   1044 }
   1045 
   1046 
   1047 
   1048 /*
   1049  * Persistently tries to make the directory "lckdir", which serves as a
   1050  * lock.
   1051  *
   1052  * #ifdef CVS_FUDGELOCKS
   1053  * If the create time on the directory is greater than CVSLCKAGE
   1054  * seconds old, just try to remove the directory.
   1055  * #endif
   1056  *
   1057  */
   1058 static int
   1059 set_lock (struct lock *lock, int will_wait)
   1060 {
   1061     int waited;
   1062     long us;
   1063     struct stat sb;
   1064     mode_t omask;
   1065     char *masterlock;
   1066     int status;
   1067 #ifdef CVS_FUDGELOCKS
   1068     time_t now;
   1069 #endif
   1070 
   1071     TRACE (TRACE_FLOW, "set_lock (%s, %d)",
   1072 	   lock->repository ? lock->repository : "(null)", will_wait);
   1073 
   1074     masterlock = lock_name (lock->repository, lock->lockdirname);
   1075 
   1076     /*
   1077      * Note that it is up to the callers of set_lock() to arrange for signal
   1078      * handlers that do the appropriate things, like remove the lock
   1079      * directory before they exit.
   1080      */
   1081     waited = 0;
   1082     us = 1;
   1083     for (;;)
   1084     {
   1085 	status = -1;
   1086 	omask = umask (cvsumask);
   1087 	SIG_beginCrSect ();
   1088 	if (CVS_MKDIR (masterlock, 0777) == 0)
   1089 	{
   1090 	    lock->lockdir = masterlock;
   1091 	    SIG_endCrSect ();
   1092 	    status = L_OK;
   1093 	    if (waited)
   1094 	        lock_obtained (lock->repository);
   1095 	    goto after_sig_unblock;
   1096 	}
   1097 	SIG_endCrSect ();
   1098     after_sig_unblock:
   1099 	(void) umask (omask);
   1100 	if (status != -1)
   1101 	    goto done;
   1102 
   1103 	if (errno != EEXIST)
   1104 	{
   1105 	    error (0, errno,
   1106 		   "failed to create lock directory for `%s' (%s)",
   1107 		   lock->repository, masterlock);
   1108 	    status = L_ERROR;
   1109 	    goto done;
   1110 	}
   1111 
   1112 	/* Find out who owns the lock.  If the lock directory is
   1113 	   non-existent, re-try the loop since someone probably just
   1114 	   removed it (thus releasing the lock).  */
   1115 	if (stat (masterlock, &sb) < 0)
   1116 	{
   1117 	    if (existence_error (errno))
   1118 		continue;
   1119 
   1120 	    error (0, errno, "couldn't stat lock directory `%s'", masterlock);
   1121 	    status = L_ERROR;
   1122 	    goto done;
   1123 	}
   1124 
   1125 #ifdef CVS_FUDGELOCKS
   1126 	/*
   1127 	 * If the create time of the directory is more than CVSLCKAGE seconds
   1128 	 * ago, try to clean-up the lock directory, and if successful, just
   1129 	 * quietly retry to make it.
   1130 	 */
   1131 	(void) time (&now);
   1132 	if (now >= (sb.st_ctime + CVSLCKAGE))
   1133 	{
   1134 	    if (CVS_RMDIR (masterlock) >= 0)
   1135 		continue;
   1136 	}
   1137 #endif
   1138 
   1139 	/* set the lockers name */
   1140 	set_lockers_name (&sb);
   1141 
   1142 	/* if he wasn't willing to wait, return an error */
   1143 	if (!will_wait)
   1144 	{
   1145 	    status = L_LOCKED;
   1146 	    goto done;
   1147 	}
   1148 
   1149 	/* if possible, try a very short sleep without a message */
   1150 	if (!waited && us < 1000)
   1151 	{
   1152 	    us += us;
   1153 	    {
   1154 		struct timespec ts;
   1155 		ts.tv_sec = 0;
   1156 		ts.tv_nsec = us * 1000;
   1157 		(void)nanosleep (&ts, NULL);
   1158 		continue;
   1159 	    }
   1160 	}
   1161 
   1162 	lock_wait (lock->repository);
   1163 	waited = 1;
   1164     }
   1165 
   1166 done:
   1167     if (!lock->lockdir)
   1168 	free (masterlock);
   1169     return status;
   1170 }
   1171 
   1172 
   1173 
   1174 /*
   1175  * Clear master lock.
   1176  *
   1177  * INPUTS
   1178  *   lock	The lock information.
   1179  *
   1180  * OUTPUTS
   1181  *   Sets LOCK->lockdir to NULL after removing the directory it names and
   1182  *   freeing the storage.
   1183  *
   1184  * ASSUMPTIONS
   1185  *   If we own the master lock directory, its name is stored in LOCK->lockdir.
   1186  *   We may free LOCK->lockdir.
   1187  */
   1188 static void
   1189 clear_lock (struct lock *lock)
   1190 {
   1191     SIG_beginCrSect ();
   1192     if (lock->lockdir)
   1193     {
   1194 	if (CVS_RMDIR (lock->lockdir) < 0)
   1195 	    error (0, errno, "failed to remove lock dir `%s'", lock->lockdir);
   1196 	free (lock->lockdir);
   1197 	lock->lockdir = NULL;
   1198     }
   1199     SIG_endCrSect ();
   1200 }
   1201 
   1202 
   1203 
   1204 /*
   1205  * Create a list of repositories to lock
   1206  */
   1207 /* ARGSUSED */
   1208 static int
   1209 lock_filesdoneproc (void *callerdat, int err, const char *repository,
   1210                     const char *update_dir, List *entries)
   1211 {
   1212     Node *p;
   1213 
   1214     p = getnode ();
   1215     p->type = LOCK;
   1216     p->key = xstrdup (repository);
   1217     p->data = xmalloc (sizeof (struct lock));
   1218     ((struct lock *)p->data)->repository = p->key;
   1219     ((struct lock *)p->data)->file1 = NULL;
   1220 #ifdef LOCK_COMPATIBILITY
   1221     ((struct lock *)p->data)->file2 = NULL;
   1222 #endif /* LOCK_COMPATIBILITY */
   1223     ((struct lock *)p->data)->lockdirname = CVSLCK;
   1224     ((struct lock *)p->data)->lockdir = NULL;
   1225     ((struct lock *)p->data)->free_repository = false;
   1226 
   1227     /* FIXME-KRP: this error condition should not simply be passed by. */
   1228     if (p->key == NULL || addnode (lock_tree_list, p) != 0)
   1229 	freenode (p);
   1230     return err;
   1231 }
   1232 
   1233 
   1234 
   1235 void
   1236 lock_tree_promotably (int argc, char **argv, int local, int which, int aflag)
   1237 {
   1238     TRACE (TRACE_FUNCTION, "lock_tree_promotably (%d, argv, %d, %d, %d)",
   1239 	   argc, local, which, aflag);
   1240 
   1241     /*
   1242      * Run the recursion processor to find all the dirs to lock and lock all
   1243      * the dirs
   1244      */
   1245     lock_tree_list = getlist ();
   1246     start_recursion
   1247 	(NULL, lock_filesdoneproc,
   1248 	 NULL, NULL, NULL, argc,
   1249 	 argv, local, which, aflag, CVS_LOCK_NONE,
   1250 	 NULL, 0, NULL );
   1251     sortlist (lock_tree_list, fsortcmp);
   1252     if (lock_list_promotably (lock_tree_list) != 0)
   1253 	error (1, 0, "lock failed - giving up");
   1254 }
   1255 
   1256 
   1257 
   1258 /* Lock a single directory in REPOSITORY.  It is OK to call this if
   1259  * a lock has been set with lock_dir_for_write; the new lock will replace
   1260  * the old one.  If REPOSITORY is NULL, don't do anything.
   1261  *
   1262  * We do not clear the dir lock after writing the lock file name since write
   1263  * locks are exclusive to all other locks.
   1264  */
   1265 void
   1266 lock_dir_for_write (const char *repository)
   1267 {
   1268     int waiting = 0;
   1269 
   1270     TRACE (TRACE_FLOW, "lock_dir_for_write (%s)", repository);
   1271 
   1272     if (repository != NULL
   1273 	&& (global_writelock.repository == NULL
   1274 	    || !strcmp (global_writelock.repository, repository)))
   1275     {
   1276 	if (writelock == NULL)
   1277 	{
   1278 	    writelock = Xasprintf (
   1279 #ifdef HAVE_LONG_FILE_NAMES
   1280 				   "%s.%s.%ld", CVSWFL, hostname,
   1281 #else
   1282 				   "%s.%ld", CVSWFL,
   1283 #endif
   1284 				   (long) getpid());
   1285 	}
   1286 
   1287 	if (global_writelock.repository != NULL)
   1288 	    remove_lock_files (&global_writelock, true);
   1289 
   1290 	global_writelock.repository = xstrdup (repository);
   1291 	global_writelock.free_repository = true;
   1292 
   1293 	for (;;)
   1294 	{
   1295 	    FILE *fp;
   1296 
   1297 	    if (set_lock (&global_writelock, 1) != L_OK)
   1298 		error (1, 0, "failed to obtain write lock in repository `%s'",
   1299 		       repository);
   1300 
   1301 	    /* check if readers exist */
   1302 	    if (readers_exist (repository)
   1303 		|| promotable_exists (repository))
   1304 	    {
   1305 		clear_lock (&global_writelock);
   1306 		lock_wait (repository); /* sleep a while and try again */
   1307 		waiting = 1;
   1308 		continue;
   1309 	    }
   1310 
   1311 	    if (waiting)
   1312 		lock_obtained (repository);
   1313 
   1314 	    /* write the write-lock file */
   1315 	    global_writelock.file1 = lock_name (global_writelock.repository,
   1316 	                                        writelock);
   1317 	    if ((fp = CVS_FOPEN (global_writelock.file1, "w+")) == NULL
   1318 		|| fclose (fp) == EOF)
   1319 	    {
   1320 		int xerrno = errno;
   1321 
   1322 		if (CVS_UNLINK (global_writelock.file1) < 0
   1323 		    && !existence_error (errno))
   1324 		{
   1325 		    error (0, errno, "failed to remove write lock %s",
   1326 			   global_writelock.file1);
   1327 		}
   1328 
   1329 		/* free the lock dir */
   1330 		clear_lock (&global_writelock);
   1331 
   1332 		/* return the error */
   1333 		error (1, xerrno,
   1334 		       "cannot create write lock in repository `%s'",
   1335 		       global_writelock.repository);
   1336 	    }
   1337 
   1338 	    /* If we upgraded from a promotable lock, remove it. */
   1339 	    if (locklist)
   1340 	    {
   1341 		Node *p = findnode (locklist, repository);
   1342 		if (p)
   1343 		{
   1344 		    remove_lock_files (p->data, true);
   1345 		    delnode (p);
   1346 		}
   1347 	    }
   1348 
   1349 	    break;
   1350 	}
   1351     }
   1352 }
   1353 
   1354 
   1355 
   1356 /* This is the internal implementation behind history_lock & val_tags_lock.  It
   1357  * gets a write lock for the history or val-tags file.
   1358  *
   1359  * RETURNS
   1360  *   true, on success
   1361  *   false, on error
   1362  */
   1363 static inline int
   1364 internal_lock (struct lock *lock, const char *xrepository)
   1365 {
   1366     /* remember what we're locking (for Lock_Cleanup) */
   1367     assert (!lock->repository);
   1368     lock->repository = Xasprintf ("%s/%s", xrepository, CVSROOTADM);
   1369     lock->free_repository = true;
   1370 
   1371     /* get the lock dir for our own */
   1372     if (set_lock (lock, 1) != L_OK)
   1373     {
   1374 	if (!really_quiet)
   1375 	    error (0, 0, "failed to obtain history lock in repository `%s'",
   1376 		   xrepository);
   1377 
   1378 	return 0;
   1379     }
   1380 
   1381     return 1;
   1382 }
   1383 
   1384 
   1385 
   1386 /* Lock the CVSROOT/history file for write.
   1387  */
   1388 int
   1389 history_lock (const char *xrepository)
   1390 {
   1391     return internal_lock (&global_history_lock, xrepository);
   1392 }
   1393 
   1394 
   1395 
   1396 /* Remove the CVSROOT/history lock, if it exists.
   1397  */
   1398 void
   1399 clear_history_lock ()
   1400 {
   1401     remove_lock_files (&global_history_lock, true);
   1402 }
   1403 
   1404 
   1405 
   1406 /* Lock the CVSROOT/val-tags file for write.
   1407  */
   1408 int
   1409 val_tags_lock (const char *xrepository)
   1410 {
   1411     return internal_lock (&global_val_tags_lock, xrepository);
   1412 }
   1413 
   1414 
   1415 
   1416 /* Remove the CVSROOT/val-tags lock, if it exists.
   1417  */
   1418 void
   1419 clear_val_tags_lock ()
   1420 {
   1421     remove_lock_files (&global_val_tags_lock, true);
   1422 }
   1423