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