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