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