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