2 * Copyright (c) 1992, Brian Berliner and Jeff Polk
3 * Copyright (c) 1989-1992, Brian Berliner
5 * You may distribute under the terms of the GNU General Public License as
6 * specified in the README file that comes with the CVS source distribution.
10 * Lock file support for CVS.
15 /* The node Concurrency in doc/cvs.texinfo has a brief introduction to
16 how CVS locks function, and some of the user-visible consequences of
17 their existence. Here is a summary of why they exist (and therefore,
18 the consequences of hacking CVS to read a repository without creating
21 There are two uses. One is the ability to prevent there from being
22 two writers at the same time. This is necessary for any number of
23 reasons (fileattr code, probably others). Commit needs to lock the
24 whole tree so that nothing happens between the up-to-date check and
27 The second use is the ability to ensure that there is not a writer
28 and a reader at the same time (several readers are allowed). Reasons
31 * Readlocks ensure that once CVS has found a collection of rcs
32 files using Find_Names, the files will still exist when it reads
33 them (they may have moved in or out of the attic).
35 * Readlocks provide some modicum of consistency, although this is
36 kind of limited--see the node Concurrency in cvs.texinfo.
38 * Readlocks ensure that the RCS file does not change between
39 RCS_parse and RCS_reparsercsfile time. This one strikes me as
40 important, although I haven't thought up what bad scenarios might
43 * Readlocks ensure that we won't find the file in the state in
44 which it is in between the calls to add_rcs_file and RCS_checkin in
45 commit.c (when a file is being added). This state is a state in
46 which the RCS file parsing routines in rcs.c cannot parse the file.
48 * Readlocks ensure that a reader won't try to look at a
49 half-written fileattr file (fileattr is not updated atomically).
51 (see also the description of anonymous read-only access in
52 "Password authentication security" node in doc/cvs.texinfo).
54 While I'm here, I'll try to summarize a few random suggestions
55 which periodically get made about how locks might be different:
57 1. Check for EROFS. Maybe useful, although in the presence of NFS
58 EROFS does *not* mean that the file system is unchanging.
60 2. Provide an option to disable locks for operations which only
61 read (see above for some of the consequences).
63 3. Have a server internally do the locking. Probably a good
64 long-term solution, and many people have been working hard on code
65 changes which would eventually make it possible to have a server
66 which can handle various connections in one process, but there is
67 much, much work still to be done before this is feasible. */
74 #else /* HAVE_NANOSLEEP */
75 # if !defined HAVE_USLEEP && defined HAVE_SELECT
76 /* use select as a workaround */
78 # endif /* !defined HAVE_USLEEP && defined HAVE_SELECT */
79 #endif /* !HAVE_NANOSLEEP */
83 /* This is the directory in which we may have a lock named by the
84 readlock variable, a lock named by the writelock variable, and/or
85 a lock named CVSLCK. The storage is not allocated along with the
86 struct lock; it is allocated by the Reader_Lock caller or in the
87 case of writelocks, it is just a pointer to the storage allocated
88 for the ->key field. */
90 /* Do we have a lock named CVSLCK? */
92 /* Note there is no way of knowing whether the readlock and writelock
93 exist. The code which sets the locks doesn't use SIG_beginCrSect
94 to set a flag like we do for CVSLCK. */
97 static void remove_locks PROTO((void));
98 static int readers_exist PROTO((char *repository));
99 static int set_lock PROTO ((struct lock *lock, int will_wait));
100 static void clear_lock PROTO ((struct lock *lock));
101 static void set_lockers_name PROTO((struct stat *statp));
102 static int set_writelock_proc PROTO((Node * p, void *closure));
103 static int unlock_proc PROTO((Node * p, void *closure));
104 static int write_lock PROTO ((struct lock *lock));
105 static void lock_simple_remove PROTO ((struct lock *lock));
106 static void lock_wait PROTO((char *repository));
107 static void lock_obtained PROTO((char *repository));
109 /* Malloc'd array containing the username of the whoever has the lock.
110 Will always be non-NULL in the cases where it is needed. */
111 static char *lockers_name;
112 /* Malloc'd array specifying name of a readlock within a directory.
114 static char *readlock;
115 /* Malloc'd array specifying name of a writelock within a directory.
117 static char *writelock;
118 /* Malloc'd array specifying the name of a CVSLCK file (absolute pathname).
119 Will always be non-NULL in the cases where it is used. */
120 static char *masterlock;
121 static List *locklist;
123 #define L_OK 0 /* success */
124 #define L_ERROR 1 /* error condition */
125 #define L_LOCKED 2 /* lock owned by someone else */
127 /* This is the (single) readlock which is set by Reader_Lock. The
128 repository field is NULL if there is no such lock. */
129 static struct lock global_readlock;
131 /* List of locks set by lock_tree_for_write. This is redundant
132 with locklist, sort of. */
133 static List *lock_tree_list;
135 /* If we set locks with lock_dir_for_write, then locked_dir contains
136 the malloc'd name of the repository directory which we have locked.
137 locked_list is the same thing packaged into a list and is redundant
138 with locklist the same way that lock_tree_list is. */
139 static char *locked_dir;
140 static List *locked_list;
142 /* LockDir from CVSROOT/config. */
145 static char *lock_name PROTO ((char *repository, char *name));
147 /* Return a newly malloc'd string containing the name of the lock for the
148 repository REPOSITORY and the lock file name within that directory
149 NAME. Also create the directories in which to put the lock file
150 if needed (if we need to, could save system call(s) by doing
151 that only if the actual operation fails. But for now we'll keep
154 lock_name (repository, name)
165 if (lock_dir == NULL)
167 /* This is the easy case. Because the lock files go directly
168 in the repository, no need to create directories or anything. */
169 retval = xmalloc (strlen (repository) + strlen (name) + 10);
170 (void) sprintf (retval, "%s/%s", repository, name);
177 /* The interesting part of the repository is the part relative
179 assert (current_parsed_root != NULL);
180 assert (current_parsed_root->directory != NULL);
181 assert (strncmp (repository, current_parsed_root->directory,
182 strlen (current_parsed_root->directory)) == 0);
183 short_repos = repository + strlen (current_parsed_root->directory) + 1;
185 if (strcmp (repository, current_parsed_root->directory) == 0)
188 assert (short_repos[-1] == '/');
190 retval = xmalloc (strlen (lock_dir)
191 + strlen (short_repos)
194 strcpy (retval, lock_dir);
195 q = retval + strlen (retval);
198 strcpy (q, short_repos);
200 /* In the common case, where the directory already exists, let's
201 keep it to one system call. */
202 if (CVS_STAT (retval, &sb) < 0)
204 /* If we need to be creating more than one directory, we'll
205 get the existence_error here. */
206 if (!existence_error (errno))
207 error (1, errno, "cannot stat directory %s", retval);
211 if (S_ISDIR (sb.st_mode))
214 error (1, 0, "%s is not a directory", retval);
217 /* Now add the directories one at a time, so we can create
220 The idea behind the new_mode stuff is that the directory we
221 end up creating will inherit permissions from its parent
222 directory (we re-set new_mode with each EEXIST). CVSUMASK
223 isn't right, because typically the reason for LockDir is to
224 use a different set of permissions. We probably want to
225 inherit group ownership also (but we don't try to deal with
226 that, some systems do it for us either always or when g+s is on).
228 We don't try to do anything about the permissions on the lock
229 files themselves. The permissions don't really matter so much
230 because the locks will generally be removed by the process
231 which created them. */
233 if (CVS_STAT (lock_dir, &sb) < 0)
234 error (1, errno, "cannot stat %s", lock_dir);
235 new_mode = sb.st_mode;
236 save_umask = umask (0000);
242 while (!ISDIRSEP (*p) && *p != '\0')
246 strncpy (q, short_repos, p - short_repos);
247 q[p - short_repos] = '\0';
248 if (!ISDIRSEP (q[p - short_repos - 1])
249 && CVS_MKDIR (retval, new_mode) < 0)
251 int saved_errno = errno;
252 if (saved_errno != EEXIST)
253 error (1, errno, "cannot make directory %s", retval);
256 if (CVS_STAT (retval, &sb) < 0)
257 error (1, errno, "cannot stat %s", retval);
258 new_mode = sb.st_mode;
265 strcpy (q, short_repos);
266 if (CVS_MKDIR (retval, new_mode) < 0
268 error (1, errno, "cannot make directory %s", retval);
274 strcat (retval, "/");
275 strcat (retval, name);
279 assert (umask (save_umask) == 0000);
287 * Clean up all outstanding locks
292 /* FIXME: error handling here is kind of bogus; we sometimes will call
293 error, which in turn can call us again. For the moment work around
294 this by refusing to reenter this function (this is a kludge). */
295 /* FIXME-reentrancy: the workaround isn't reentrant. */
296 static int in_lock_cleanup = 0;
299 (void) fprintf (stderr, "%s-> Lock_Cleanup()\n", CLIENT_SERVER_STR);
307 dellist (&lock_tree_list);
309 if (locked_dir != NULL)
311 dellist (&locked_list);
320 * Remove locks without discarding the lock information
325 /* clean up simple locks (if any) */
326 if (global_readlock.repository != NULL)
328 lock_simple_remove (&global_readlock);
329 global_readlock.repository = NULL;
332 /* clean up multiple locks (if any) */
333 if (locklist != (List *) NULL)
335 (void) walklist (locklist, unlock_proc, NULL);
336 locklist = (List *) NULL;
341 * walklist proc for removing a list of locks
344 unlock_proc (p, closure)
348 lock_simple_remove (p->data);
352 /* Remove the lock files. */
354 lock_simple_remove (lock)
359 /* If readlock is set, the lock directory *might* have been created, but
360 since Reader_Lock doesn't use SIG_beginCrSect the way that set_lock
361 does, we don't know that. That is why we need to check for
362 existence_error here. */
363 if (readlock != NULL)
365 tmp = lock_name (lock->repository, readlock);
366 if ( CVS_UNLINK (tmp) < 0 && ! existence_error (errno))
367 error (0, errno, "failed to remove lock %s", tmp);
371 /* If writelock is set, the lock directory *might* have been created, but
372 since write_lock doesn't use SIG_beginCrSect the way that set_lock
373 does, we don't know that. That is why we need to check for
374 existence_error here. */
375 if (writelock != NULL)
377 tmp = lock_name (lock->repository, writelock);
378 if ( CVS_UNLINK (tmp) < 0 && ! existence_error (errno))
379 error (0, errno, "failed to remove lock %s", tmp);
383 if (lock->have_lckdir)
385 tmp = lock_name (lock->repository, CVSLCK);
387 if (CVS_RMDIR (tmp) < 0)
388 error (0, errno, "failed to remove lock dir %s", tmp);
389 lock->have_lckdir = 0;
398 * Create a lock file for readers
401 Reader_Lock (xrepository)
409 (void) fprintf (stderr, "%s-> Reader_Lock(%s)\n", CLIENT_SERVER_STR,
412 if (noexec || readonlyfs)
415 /* we only do one directory at a time for read locks! */
416 if (global_readlock.repository != NULL)
418 error (0, 0, "Reader_Lock called while read locks set - Help!");
422 if (readlock == NULL)
424 readlock = xmalloc (strlen (hostname) + sizeof (CVSRFL) + 40);
425 (void) sprintf (readlock,
426 #ifdef HAVE_LONG_FILE_NAMES
427 "%s.%s.%ld", CVSRFL, hostname,
434 /* remember what we're locking (for Lock_Cleanup) */
435 global_readlock.repository = xrepository;
437 /* get the lock dir for our own */
438 if (set_lock (&global_readlock, 1) != L_OK)
440 error (0, 0, "failed to obtain dir lock in repository `%s'",
442 if (readlock != NULL)
445 /* We don't set global_readlock.repository to NULL. I think this
446 only works because recurse.c will give a fatal error if we return
451 /* write a read-lock */
452 tmp = lock_name (xrepository, readlock);
453 if ((fp = CVS_FOPEN (tmp, "w+")) == NULL || fclose (fp) == EOF)
455 error (0, errno, "cannot create read lock in repository `%s'",
457 if (readlock != NULL)
464 /* free the lock dir */
465 clear_lock (&global_readlock);
473 * Lock a list of directories for writing
475 static char *lock_error_repos;
476 static int lock_error;
478 static int Writer_Lock PROTO ((List * list));
490 error (0, 0, "write lock failed - read-only repository");
494 /* We only know how to do one list at a time */
495 if (locklist != (List *) NULL)
497 error (0, 0, "Writer_Lock called while write locks set - Help!");
504 /* try to lock everything on the list */
505 lock_error = L_OK; /* init for set_writelock_proc */
506 lock_error_repos = (char *) NULL; /* init for set_writelock_proc */
507 locklist = list; /* init for Lock_Cleanup */
508 if (lockers_name != NULL)
510 lockers_name = xstrdup ("unknown");
512 (void) walklist (list, set_writelock_proc, NULL);
516 case L_ERROR: /* Real Error */
517 if (wait_repos != NULL)
519 Lock_Cleanup (); /* clean up any locks we set */
520 error (0, 0, "lock failed - giving up");
523 case L_LOCKED: /* Someone already had a lock */
524 remove_locks (); /* clean up any locks we set */
525 lock_wait (lock_error_repos); /* sleep a while and try again */
526 wait_repos = xstrdup (lock_error_repos);
529 case L_OK: /* we got the locks set */
530 if (wait_repos != NULL)
532 lock_obtained (wait_repos);
538 if (wait_repos != NULL)
540 error (0, 0, "unknown lock status %d in Writer_Lock",
550 * walklist proc for setting write locks
553 set_writelock_proc (p, closure)
557 /* if some lock was not OK, just skip this one */
558 if (lock_error != L_OK)
561 /* apply the write lock */
562 lock_error_repos = p->key;
563 lock_error = write_lock (p->data);
570 * Create a lock file for writers returns L_OK if lock set ok, L_LOCKED if
571 * lock held by someone else or L_ERROR if an error occurred
582 (void) fprintf (stderr, "%s-> write_lock(%s)\n",
583 CLIENT_SERVER_STR, lock->repository);
585 if (writelock == NULL)
587 writelock = xmalloc (strlen (hostname) + sizeof (CVSWFL) + 40);
588 (void) sprintf (writelock,
589 #ifdef HAVE_LONG_FILE_NAMES
590 "%s.%s.%ld", CVSWFL, hostname,
597 /* make sure the lock dir is ours (not necessarily unique to us!) */
598 status = set_lock (lock, 0);
601 /* we now own a writer - make sure there are no readers */
602 if (readers_exist (lock->repository))
604 /* clean up the lock dir if we created it */
610 /* indicate we failed due to read locks instead of error */
614 /* write the write-lock file */
615 tmp = lock_name (lock->repository, writelock);
616 if ((fp = CVS_FOPEN (tmp, "w+")) == NULL || fclose (fp) == EOF)
620 if ( CVS_UNLINK (tmp) < 0 && ! existence_error (errno))
621 error (0, errno, "failed to remove lock %s", tmp);
623 /* free the lock dir if we created it */
629 /* return the error */
630 error (0, xerrno, "cannot create write lock in repository `%s'",
645 * readers_exist() returns 0 if there are no reader lock files remaining in
646 * the repository; else 1 is returned, to indicate that the caller should
647 * sleep a while and try again.
650 readers_exist (repository)
659 #ifdef CVS_FUDGELOCKS
664 lockdir = lock_name (repository, "");
665 lockdir[strlen (lockdir) - 1] = '\0'; /* remove trailing slash */
668 if ((dirp = CVS_OPENDIR (lockdir)) == NULL)
669 error (1, 0, "cannot open directory %s", lockdir);
673 while ((dp = CVS_READDIR (dirp)) != NULL)
675 if (CVS_FNMATCH (CVSRFLPAT, dp->d_name, 0) == 0)
677 line = xmalloc (strlen (lockdir) + 1 + strlen (dp->d_name) + 1);
678 (void)sprintf (line, "%s/%s", lockdir, dp->d_name);
679 if (CVS_STAT (line, &sb) != -1)
681 #ifdef CVS_FUDGELOCKS
683 * If the create time of the file is more than CVSLCKAGE
684 * seconds ago, try to clean-up the lock file, and if
685 * successful, re-open the directory and try again.
687 if (now >= (sb.st_ctime + CVSLCKAGE) &&
688 CVS_UNLINK (line) != -1)
695 set_lockers_name (&sb);
699 /* If the file doesn't exist, it just means that it
700 * disappeared between the time we did the readdir and the
701 * time we did the stat.
703 if (!existence_error (errno))
704 error (0, errno, "cannot stat %s", line);
714 error (0, errno, "error reading directory %s", repository);
727 * Set the static variable lockers_name appropriately, based on the stat
728 * structure passed in.
731 set_lockers_name (statp)
736 if (lockers_name != NULL)
738 if ((pw = (struct passwd *)getpwuid (statp->st_uid)) !=
739 (struct passwd *)NULL)
741 lockers_name = xstrdup (pw->pw_name);
745 lockers_name = xmalloc (20);
746 (void)sprintf (lockers_name, "uid%lu", (unsigned long) statp->st_uid);
753 * Persistently tries to make the directory "lckdir", which serves as a
756 * #ifdef CVS_FUDGELOCKS
757 * If the create time on the directory is greater than CVSLCKAGE
758 * seconds old, just try to remove the directory.
763 set_lock (lock, will_wait)
771 #ifdef CVS_FUDGELOCKS
775 if (masterlock != NULL)
777 masterlock = lock_name (lock->repository, CVSLCK);
780 * Note that it is up to the callers of set_lock() to arrange for signal
781 * handlers that do the appropriate things, like remove the lock
782 * directory before they exit.
786 lock->have_lckdir = 0;
790 omask = umask (cvsumask);
792 if (CVS_MKDIR (masterlock, 0777) == 0)
794 lock->have_lckdir = 1;
798 lock_obtained (lock->repository);
803 (void) umask (omask);
810 "failed to create lock directory for `%s' (%s)",
811 lock->repository, masterlock);
815 /* Find out who owns the lock. If the lock directory is
816 non-existent, re-try the loop since someone probably just
817 removed it (thus releasing the lock). */
818 if (CVS_STAT (masterlock, &sb) < 0)
820 if (existence_error (errno))
823 error (0, errno, "couldn't stat lock directory `%s'", masterlock);
827 #ifdef CVS_FUDGELOCKS
829 * If the create time of the directory is more than CVSLCKAGE seconds
830 * ago, try to clean-up the lock directory, and if successful, just
831 * quietly retry to make it.
834 if (now >= (sb.st_ctime + CVSLCKAGE))
836 if (CVS_RMDIR (masterlock) >= 0)
841 /* set the lockers name */
842 set_lockers_name (&sb);
844 /* if he wasn't willing to wait, return an error */
848 /* if possible, try a very short sleep without a message */
849 if (!waited && us < 1000)
852 #if defined HAVE_NANOSLEEP
856 ts.tv_nsec = us * 1000;
857 (void)nanosleep (&ts, NULL);
860 #elif defined HAVE_USLEEP
863 #elif defined HAVE_SELECT
868 (void)select (0, (fd_set *)NULL, (fd_set *)NULL, (fd_set *)NULL, &tv);
874 lock_wait (lock->repository);
880 * Clear master lock. We don't have to recompute the lock name since
881 * clear_lock is never called except after a successful set_lock().
888 if (CVS_RMDIR (masterlock) < 0)
889 error (0, errno, "failed to remove lock dir `%s'", masterlock);
890 lock->have_lckdir = 0;
895 * Print out a message that the lock is still held, then sleep a while.
906 tm_p = gmtime (&now);
907 msg = xmalloc (100 + strlen (lockers_name) + strlen (repos));
908 sprintf (msg, "[%8.8s] waiting for %s's lock in %s",
909 (tm_p ? asctime (tm_p) : ctime (&now)) + 11,
910 lockers_name, repos);
911 error (0, 0, "%s", msg);
912 /* Call cvs_flusherr to ensure that the user sees this message as
916 (void) sleep (CVSLCKSLEEP);
920 * Print out a message when we obtain a lock.
923 lock_obtained (repos)
931 tm_p = gmtime (&now);
932 msg = xmalloc (100 + strlen (repos));
933 sprintf (msg, "[%8.8s] obtained lock in %s",
934 (tm_p ? asctime (tm_p) : ctime (&now)) + 11, repos);
935 error (0, 0, "%s", msg);
936 /* Call cvs_flusherr to ensure that the user sees this message as
944 static int lock_filesdoneproc PROTO ((void *callerdat, int err,
945 const char *repository,
946 const char *update_dir,
950 * Create a list of repositories to lock
954 lock_filesdoneproc (callerdat, err, repository, update_dir, entries)
957 const char *repository;
958 const char *update_dir;
965 p->key = xstrdup (repository);
966 p->data = xmalloc (sizeof (struct lock));
967 ((struct lock *)p->data)->repository = p->key;
968 ((struct lock *)p->data)->have_lckdir = 0;
970 /* FIXME-KRP: this error condition should not simply be passed by. */
971 if (p->key == NULL || addnode (lock_tree_list, p) != 0)
977 lock_tree_for_write (argc, argv, local, which, aflag)
985 * Run the recursion processor to find all the dirs to lock and lock all
988 lock_tree_list = getlist ();
989 start_recursion ((FILEPROC) NULL, lock_filesdoneproc,
990 (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, NULL, argc,
991 argv, local, which, aflag, CVS_LOCK_NONE,
992 (char *) NULL, 0, (char *) NULL);
993 sortlist (lock_tree_list, fsortcmp);
994 if (Writer_Lock (lock_tree_list) != 0)
995 error (1, 0, "lock failed - giving up");
998 /* Lock a single directory in REPOSITORY. It is OK to call this if
999 a lock has been set with lock_dir_for_write; the new lock will replace
1000 the old one. If REPOSITORY is NULL, don't do anything. */
1002 lock_dir_for_write (repository)
1005 if (repository != NULL
1006 && (locked_dir == NULL
1007 || strcmp (locked_dir, repository) != 0))
1011 if (locked_dir != NULL)
1014 locked_dir = xstrdup (repository);
1015 locked_list = getlist ();
1018 node->key = xstrdup (repository);
1019 node->data = xmalloc (sizeof (struct lock));
1020 ((struct lock *)node->data)->repository = node->key;
1021 ((struct lock *)node->data)->have_lckdir = 0;
1023 (void) addnode (locked_list, node);
1024 Writer_Lock (locked_list);