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