1 /* 2 * Copyright (c) 1992, Brian Berliner and Jeff Polk 3 * Copyright (c) 1989-1992, Brian Berliner 4 * 5 * You may distribute under the terms of the GNU General Public License as 6 * specified in the README file that comes with the CVS source distribution. 7 * 8 * "update" updates the version in the present directory with respect to the RCS 9 * repository. The present version must have been created by "checkout". The 10 * user can keep up-to-date by calling "update" whenever he feels like it. 11 * 12 * The present version can be committed by "commit", but this keeps the version 13 * in tact. 14 * 15 * Arguments following the options are taken to be file names to be updated, 16 * rather than updating the entire directory. 17 * 18 * Modified or non-existent RCS files are checked out and reported as U 19 * <user_file> 20 * 21 * Modified user files are reported as M <user_file>. If both the RCS file and 22 * the user file have been modified, the user file is replaced by the result 23 * of rcsmerge, and a backup file is written for the user in .#file.version. 24 * If this throws up irreconcilable differences, the file is reported as C 25 * <user_file>, and as M <user_file> otherwise. 26 * 27 * Files added but not yet committed are reported as A <user_file>. Files 28 * removed but not yet committed are reported as R <user_file>. 29 * 30 * If the current directory contains subdirectories that hold concurrent 31 * versions, these are updated too. If the -d option was specified, new 32 * directories added to the repository are automatically created and updated 33 * as well. 34 */ 35 36 #include "cvs.h" 37 #include "savecwd.h" 38 #ifdef SERVER_SUPPORT 39 #include "md5.h" 40 #endif 41 #include "watch.h" 42 #include "fileattr.h" 43 #include "edit.h" 44 #include "getline.h" 45 #include "buffer.h" 46 #include "hardlink.h" 47 48 static int checkout_file PROTO ((struct file_info *finfo, Vers_TS *vers_ts, 49 int adding, int merging, int update_server)); 50 #ifdef SERVER_SUPPORT 51 static void checkout_to_buffer PROTO ((void *, const char *, size_t)); 52 #endif 53 #ifdef SERVER_SUPPORT 54 static int patch_file PROTO ((struct file_info *finfo, 55 Vers_TS *vers_ts, 56 int *docheckout, struct stat *file_info, 57 unsigned char *checksum)); 58 static void patch_file_write PROTO ((void *, const char *, size_t)); 59 #endif 60 static int merge_file PROTO ((struct file_info *finfo, Vers_TS *vers)); 61 static int scratch_file PROTO((struct file_info *finfo)); 62 static Dtype update_dirent_proc PROTO ((void *callerdat, char *dir, 63 char *repository, char *update_dir, 64 List *entries)); 65 static int update_dirleave_proc PROTO ((void *callerdat, char *dir, 66 int err, char *update_dir, 67 List *entries)); 68 static int update_fileproc PROTO ((void *callerdat, struct file_info *)); 69 static int update_filesdone_proc PROTO ((void *callerdat, int err, 70 char *repository, char *update_dir, 71 List *entries)); 72 #ifdef PRESERVE_PERMISSIONS_SUPPORT 73 static int get_linkinfo_proc PROTO ((void *callerdat, struct file_info *)); 74 #endif 75 static void write_letter PROTO ((struct file_info *finfo, int letter)); 76 static void join_file PROTO ((struct file_info *finfo, Vers_TS *vers_ts)); 77 78 static char *options = NULL; 79 static char *tag = NULL; 80 static char *date = NULL; 81 /* This is a bit of a kludge. We call WriteTag at the beginning 82 before we know whether nonbranch is set or not. And then at the 83 end, once we have the right value for nonbranch, we call WriteTag 84 again. I don't know whether the first call is necessary or not. 85 rewrite_tag is nonzero if we are going to have to make that second 86 call. */ 87 static int rewrite_tag; 88 static int nonbranch; 89 90 /* If we set the tag or date for a subdirectory, we use this to undo 91 the setting. See update_dirent_proc. */ 92 static char *tag_update_dir; 93 94 static char *join_rev1, *date_rev1; 95 static char *join_rev2, *date_rev2; 96 static int aflag = 0; 97 static int toss_local_changes = 0; 98 static int force_tag_match = 1; 99 static int update_build_dirs = 0; 100 static int update_prune_dirs = 0; 101 static int pipeout = 0; 102 #ifdef SERVER_SUPPORT 103 static int patches = 0; 104 static int rcs_diff_patches = 0; 105 #endif 106 static List *ignlist = (List *) NULL; 107 static time_t last_register_time; 108 static const char *const update_usage[] = 109 { 110 "Usage: %s %s [-APdflRp] [-k kopt] [-r rev|-D date] [-j rev]\n", 111 " [-I ign] [-W spec] [files...]\n", 112 "\t-A\tReset any sticky tags/date/kopts.\n", 113 "\t-P\tPrune empty directories.\n", 114 "\t-C\tOverwrite locally modified files with clean repository copies.\n", 115 "\t-d\tBuild directories, like checkout does.\n", 116 "\t-f\tForce a head revision match if tag/date not found.\n", 117 "\t-l\tLocal directory only, no recursion.\n", 118 "\t-R\tProcess directories recursively.\n", 119 "\t-p\tSend updates to standard output (avoids stickiness).\n", 120 "\t-k kopt\tUse RCS kopt -k option on checkout.\n", 121 "\t-r rev\tUpdate using specified revision/tag (is sticky).\n", 122 "\t-D date\tSet date to update from (is sticky).\n", 123 "\t-j rev\tMerge in changes made between current revision and rev.\n", 124 "\t-I ign\tMore files to ignore (! to reset).\n", 125 "\t-W spec\tWrappers specification line.\n", 126 "(Specify the --help global option for a list of other help options)\n", 127 NULL 128 }; 129 130 /* 131 * update is the argv,argc based front end for arg parsing 132 */ 133 int 134 update (argc, argv) 135 int argc; 136 char **argv; 137 { 138 int c, err; 139 int local = 0; /* recursive by default */ 140 int which; /* where to look for files and dirs */ 141 142 if (argc == -1) 143 usage (update_usage); 144 145 ign_setup (); 146 wrap_setup (); 147 148 /* parse the args */ 149 optind = 0; 150 while ((c = getopt (argc, argv, "+ApCPflRQqduk:r:D:j:I:W:")) != -1) 151 { 152 switch (c) 153 { 154 case 'A': 155 aflag = 1; 156 break; 157 case 'C': 158 toss_local_changes = 1; 159 break; 160 case 'I': 161 ign_add (optarg, 0); 162 break; 163 case 'W': 164 wrap_add (optarg, 0); 165 break; 166 case 'k': 167 if (options) 168 free (options); 169 options = RCS_check_kflag (optarg); 170 break; 171 case 'l': 172 local = 1; 173 break; 174 case 'R': 175 local = 0; 176 break; 177 case 'Q': 178 case 'q': 179 #ifdef SERVER_SUPPORT 180 /* The CVS 1.5 client sends these options (in addition to 181 Global_option requests), so we must ignore them. */ 182 if (!server_active) 183 #endif 184 error (1, 0, 185 "-q or -Q must be specified before \"%s\"", 186 command_name); 187 break; 188 case 'd': 189 update_build_dirs = 1; 190 break; 191 case 'f': 192 force_tag_match = 0; 193 break; 194 case 'r': 195 tag = optarg; 196 break; 197 case 'D': 198 date = Make_Date (optarg); 199 break; 200 case 'P': 201 update_prune_dirs = 1; 202 break; 203 case 'p': 204 pipeout = 1; 205 noexec = 1; /* so no locks will be created */ 206 break; 207 case 'j': 208 if (join_rev2) 209 error (1, 0, "only two -j options can be specified"); 210 if (join_rev1) 211 join_rev2 = optarg; 212 else 213 join_rev1 = optarg; 214 break; 215 case 'u': 216 #ifdef SERVER_SUPPORT 217 if (server_active) 218 { 219 patches = 1; 220 rcs_diff_patches = server_use_rcs_diff (); 221 } 222 else 223 #endif 224 usage (update_usage); 225 break; 226 case '?': 227 default: 228 usage (update_usage); 229 break; 230 } 231 } 232 argc -= optind; 233 argv += optind; 234 235 #ifdef CLIENT_SUPPORT 236 if (client_active) 237 { 238 int pass; 239 240 /* The first pass does the regular update. If we receive at least 241 one patch which failed, we do a second pass and just fetch 242 those files whose patches failed. */ 243 pass = 1; 244 do 245 { 246 int status; 247 248 start_server (); 249 250 if (local) 251 send_arg("-l"); 252 if (update_build_dirs) 253 send_arg("-d"); 254 if (pipeout) 255 send_arg("-p"); 256 if (!force_tag_match) 257 send_arg("-f"); 258 if (aflag) 259 send_arg("-A"); 260 if (toss_local_changes) 261 send_arg("-C"); 262 if (update_prune_dirs) 263 send_arg("-P"); 264 client_prune_dirs = update_prune_dirs; 265 option_with_arg ("-r", tag); 266 if (options && options[0] != '\0') 267 send_arg (options); 268 if (date) 269 client_senddate (date); 270 if (join_rev1) 271 option_with_arg ("-j", join_rev1); 272 if (join_rev2) 273 option_with_arg ("-j", join_rev2); 274 wrap_send (); 275 276 if (failed_patches_count == 0) 277 { 278 unsigned int flags = 0; 279 280 /* If the server supports the command "update-patches", that 281 means that it knows how to handle the -u argument to update, 282 which means to send patches instead of complete files. 283 284 We don't send -u if failed_patches != NULL, so that the 285 server doesn't try to send patches which will just fail 286 again. At least currently, the client also clobbers the 287 file and tells the server it is lost, which also will get 288 a full file instead of a patch, but it seems clean to omit 289 -u. */ 290 if (supported_request ("update-patches")) 291 send_arg ("-u"); 292 293 if (update_build_dirs) 294 flags |= SEND_BUILD_DIRS; 295 296 if (toss_local_changes) { 297 flags |= SEND_NO_CONTENTS; 298 flags |= BACKUP_MODIFIED_FILES; 299 } 300 301 /* If noexec, probably could be setting SEND_NO_CONTENTS. 302 Same caveats as for "cvs status" apply. */ 303 304 send_files (argc, argv, local, aflag, flags); 305 send_file_names (argc, argv, SEND_EXPAND_WILD); 306 } 307 else 308 { 309 int i; 310 311 (void) printf ("%s client: refetching unpatchable files\n", 312 program_name); 313 314 if (toplevel_wd != NULL 315 && CVS_CHDIR (toplevel_wd) < 0) 316 { 317 error (1, errno, "could not chdir to %s", toplevel_wd); 318 } 319 320 for (i = 0; i < failed_patches_count; i++) 321 if (unlink_file (failed_patches[i]) < 0 322 && !existence_error (errno)) 323 error (0, errno, "cannot remove %s", 324 failed_patches[i]); 325 send_files (failed_patches_count, failed_patches, local, 326 aflag, update_build_dirs ? SEND_BUILD_DIRS : 0); 327 send_file_names (failed_patches_count, failed_patches, 0); 328 free_names (&failed_patches_count, failed_patches); 329 } 330 331 send_to_server ("update\012", 0); 332 333 status = get_responses_and_close (); 334 335 /* If there are any conflicts, the server will return a 336 non-zero exit status. If any patches failed, we still 337 want to run the update again. We use a pass count to 338 avoid an endless loop. */ 339 340 /* Notes: (1) assuming that status != 0 implies a 341 potential conflict is the best we can cleanly do given 342 the current protocol. I suppose that trying to 343 re-fetch in cases where there was a more serious error 344 is probably more or less harmless, but it isn't really 345 ideal. (2) it would be nice to have a testsuite case for the 346 conflict-and-patch-failed case. */ 347 348 if (status != 0 349 && (failed_patches_count == 0 || pass > 1)) 350 { 351 if (failed_patches_count > 0) 352 free_names (&failed_patches_count, failed_patches); 353 return status; 354 } 355 356 ++pass; 357 } while (failed_patches_count > 0); 358 359 return 0; 360 } 361 #endif 362 363 if (tag != NULL) 364 tag_check_valid (tag, argc, argv, local, aflag, ""); 365 if (join_rev1 != NULL) 366 tag_check_valid_join (join_rev1, argc, argv, local, aflag, ""); 367 if (join_rev2 != NULL) 368 tag_check_valid_join (join_rev2, argc, argv, local, aflag, ""); 369 370 /* 371 * If we are updating the entire directory (for real) and building dirs 372 * as we go, we make sure there is no static entries file and write the 373 * tag file as appropriate 374 */ 375 if (argc <= 0 && !pipeout) 376 { 377 if (update_build_dirs) 378 { 379 if (unlink_file (CVSADM_ENTSTAT) < 0 && ! existence_error (errno)) 380 error (1, errno, "cannot remove file %s", CVSADM_ENTSTAT); 381 #ifdef SERVER_SUPPORT 382 if (server_active) 383 { 384 char *repos = Name_Repository (NULL, NULL); 385 server_clear_entstat (".", repos); 386 free (repos); 387 } 388 #endif 389 } 390 391 /* keep the CVS/Tag file current with the specified arguments */ 392 if (aflag || tag || date) 393 { 394 char *repos = Name_Repository (NULL, NULL); 395 WriteTag ((char *) NULL, tag, date, 0, ".", repos); 396 free (repos); 397 rewrite_tag = 1; 398 nonbranch = 0; 399 } 400 } 401 402 /* look for files/dirs locally and in the repository */ 403 which = W_LOCAL | W_REPOS; 404 405 /* look in the attic too if a tag or date is specified */ 406 if (tag != NULL || date != NULL || joining()) 407 which |= W_ATTIC; 408 409 /* call the command line interface */ 410 err = do_update (argc, argv, options, tag, date, force_tag_match, 411 local, update_build_dirs, aflag, update_prune_dirs, 412 pipeout, which, join_rev1, join_rev2, (char *) NULL); 413 414 /* free the space Make_Date allocated if necessary */ 415 if (date != NULL) 416 free (date); 417 418 return (err); 419 } 420 421 /* 422 * Command line interface to update (used by checkout) 423 */ 424 int 425 do_update (argc, argv, xoptions, xtag, xdate, xforce, local, xbuild, xaflag, 426 xprune, xpipeout, which, xjoin_rev1, xjoin_rev2, preload_update_dir) 427 int argc; 428 char **argv; 429 char *xoptions; 430 char *xtag; 431 char *xdate; 432 int xforce; 433 int local; 434 int xbuild; 435 int xaflag; 436 int xprune; 437 int xpipeout; 438 int which; 439 char *xjoin_rev1; 440 char *xjoin_rev2; 441 char *preload_update_dir; 442 { 443 int err = 0; 444 char *cp; 445 446 /* fill in the statics */ 447 options = xoptions; 448 tag = xtag; 449 date = xdate; 450 force_tag_match = xforce; 451 update_build_dirs = xbuild; 452 aflag = xaflag; 453 update_prune_dirs = xprune; 454 pipeout = xpipeout; 455 456 /* setup the join support */ 457 join_rev1 = xjoin_rev1; 458 join_rev2 = xjoin_rev2; 459 if (join_rev1 && (cp = strchr (join_rev1, ':')) != NULL) 460 { 461 *cp++ = '\0'; 462 date_rev1 = Make_Date (cp); 463 } 464 else 465 date_rev1 = (char *) NULL; 466 if (join_rev2 && (cp = strchr (join_rev2, ':')) != NULL) 467 { 468 *cp++ = '\0'; 469 date_rev2 = Make_Date (cp); 470 } 471 else 472 date_rev2 = (char *) NULL; 473 474 #ifdef PRESERVE_PERMISSIONS_SUPPORT 475 if (preserve_perms) 476 { 477 /* We need to do an extra recursion, bleah. It's to make sure 478 that we know as much as possible about file linkage. */ 479 hardlist = getlist(); 480 working_dir = xgetwd(); /* save top-level working dir */ 481 482 /* FIXME-twp: the arguments to start_recursion make me dizzy. This 483 function call was copied from the update_fileproc call that 484 follows it; someone should make sure that I did it right. */ 485 err = start_recursion (get_linkinfo_proc, (FILESDONEPROC) NULL, 486 (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, NULL, 487 argc, argv, local, which, aflag, 1, 488 preload_update_dir, 1); 489 if (err) 490 return (err); 491 492 /* FIXME-twp: at this point we should walk the hardlist 493 and update the `links' field of each hardlink_info struct 494 to list the files that are linked on dist. That would make 495 it easier & more efficient to compare the disk linkage with 496 the repository linkage (a simple strcmp). */ 497 } 498 #endif 499 500 /* call the recursion processor */ 501 err = start_recursion (update_fileproc, update_filesdone_proc, 502 update_dirent_proc, update_dirleave_proc, NULL, 503 argc, argv, local, which, aflag, 1, 504 preload_update_dir, 1); 505 506 /* see if we need to sleep before returning to avoid time-stamp races */ 507 if (last_register_time) 508 { 509 while (time ((time_t *) NULL) == last_register_time) 510 sleep (1); 511 } 512 513 return (err); 514 } 515 516 #ifdef PRESERVE_PERMISSIONS_SUPPORT 517 /* 518 * The get_linkinfo_proc callback adds each file to the hardlist 519 * (see hardlink.c). 520 */ 521 522 static int 523 get_linkinfo_proc (callerdat, finfo) 524 void *callerdat; 525 struct file_info *finfo; 526 { 527 char *fullpath; 528 Node *linkp; 529 struct hardlink_info *hlinfo; 530 531 /* Get the full pathname of the current file. */ 532 fullpath = xmalloc (strlen(working_dir) + 533 strlen(finfo->fullname) + 2); 534 sprintf (fullpath, "%s/%s", working_dir, finfo->fullname); 535 536 /* To permit recursing into subdirectories, files 537 are keyed on the full pathname and not on the basename. */ 538 linkp = lookup_file_by_inode (fullpath); 539 if (linkp == NULL) 540 { 541 /* The file isn't on disk; we are probably restoring 542 a file that was removed. */ 543 return 0; 544 } 545 546 /* Create a new, empty hardlink_info node. */ 547 hlinfo = (struct hardlink_info *) 548 xmalloc (sizeof (struct hardlink_info)); 549 550 hlinfo->status = (Ctype) 0; /* is this dumb? */ 551 hlinfo->checked_out = 0; 552 553 linkp->data = (char *) hlinfo; 554 555 return 0; 556 } 557 #endif 558 559 /* 560 * This is the callback proc for update. It is called for each file in each 561 * directory by the recursion code. The current directory is the local 562 * instantiation. file is the file name we are to operate on. update_dir is 563 * set to the path relative to where we started (for pretty printing). 564 * repository is the repository. entries and srcfiles are the pre-parsed 565 * entries and source control files. 566 * 567 * This routine decides what needs to be done for each file and does the 568 * appropriate magic for checkout 569 */ 570 static int 571 update_fileproc (callerdat, finfo) 572 void *callerdat; 573 struct file_info *finfo; 574 { 575 int retval; 576 Ctype status; 577 Vers_TS *vers; 578 int resurrecting; 579 580 resurrecting = 0; 581 582 status = Classify_File (finfo, tag, date, options, force_tag_match, 583 aflag, &vers, pipeout); 584 585 /* Keep track of whether TAG is a branch tag. 586 Note that if it is a branch tag in some files and a nonbranch tag 587 in others, treat it as a nonbranch tag. It is possible that case 588 should elicit a warning or an error. */ 589 if (rewrite_tag 590 && tag != NULL 591 && finfo->rcs != NULL) 592 { 593 char *rev = RCS_getversion (finfo->rcs, tag, NULL, 1, NULL); 594 if (rev != NULL 595 && !RCS_nodeisbranch (finfo->rcs, tag)) 596 nonbranch = 1; 597 if (rev != NULL) 598 free (rev); 599 } 600 601 if (pipeout) 602 { 603 /* 604 * We just return success without doing anything if any of the really 605 * funky cases occur 606 * 607 * If there is still a valid RCS file, do a regular checkout type 608 * operation 609 */ 610 switch (status) 611 { 612 case T_UNKNOWN: /* unknown file was explicitly asked 613 * about */ 614 case T_REMOVE_ENTRY: /* needs to be un-registered */ 615 case T_ADDED: /* added but not committed */ 616 retval = 0; 617 break; 618 case T_CONFLICT: /* old punt-type errors */ 619 retval = 1; 620 break; 621 case T_UPTODATE: /* file was already up-to-date */ 622 case T_NEEDS_MERGE: /* needs merging */ 623 case T_MODIFIED: /* locally modified */ 624 case T_REMOVED: /* removed but not committed */ 625 case T_CHECKOUT: /* needs checkout */ 626 #ifdef SERVER_SUPPORT 627 case T_PATCH: /* needs patch */ 628 #endif 629 retval = checkout_file (finfo, vers, 0, 0, 0); 630 break; 631 632 default: /* can't ever happen :-) */ 633 error (0, 0, 634 "unknown file status %d for file %s", status, finfo->file); 635 retval = 0; 636 break; 637 } 638 } 639 else 640 { 641 switch (status) 642 { 643 case T_UNKNOWN: /* unknown file was explicitly asked 644 * about */ 645 case T_UPTODATE: /* file was already up-to-date */ 646 retval = 0; 647 break; 648 case T_CONFLICT: /* old punt-type errors */ 649 retval = 1; 650 write_letter (finfo, 'C'); 651 break; 652 case T_NEEDS_MERGE: /* needs merging */ 653 retval = merge_file (finfo, vers); 654 break; 655 case T_MODIFIED: /* locally modified */ 656 retval = 0; 657 if (toss_local_changes) 658 { 659 char *bakname; 660 bakname = backup_file (finfo->file, vers->vn_user); 661 /* This behavior is sufficiently unexpected to 662 justify overinformativeness, I think. */ 663 #ifdef SERVER_SUPPORT 664 if ((! really_quiet) && (! server_active)) 665 #else /* ! SERVER_SUPPORT */ 666 if (! really_quiet) 667 #endif /* SERVER_SUPPORT */ 668 (void) printf ("(Locally modified %s moved to %s)\n", 669 finfo->file, bakname); 670 free (bakname); 671 672 /* The locally modified file is still present, but 673 it will be overwritten by the repository copy 674 after this. */ 675 status = T_CHECKOUT; 676 retval = checkout_file (finfo, vers, 0, 0, 1); 677 } 678 else 679 { 680 if (vers->ts_conflict) 681 { 682 char *filestamp; 683 int retcode; 684 685 /* 686 * If the timestamp has changed and no 687 * conflict indicators are found, it isn't a 688 * 'C' any more. 689 */ 690 691 #ifdef SERVER_SUPPORT 692 if (server_active) 693 retcode = vers->ts_conflict[0] != '='; 694 else 695 { 696 filestamp = time_stamp (finfo->file); 697 retcode = strcmp (vers->ts_conflict, filestamp); 698 free (filestamp); 699 } 700 #else 701 filestamp = time_stamp (finfo->file); 702 retcode = strcmp (vers->ts_conflict, filestamp); 703 free (filestamp); 704 #endif 705 706 if (retcode) 707 { 708 /* The timestamps differ. But if there 709 are conflict markers print 'C' anyway. */ 710 retcode = !file_has_markers (finfo); 711 } 712 713 if (!retcode) 714 { 715 write_letter (finfo, 'C'); 716 retval = 1; 717 } 718 else 719 { 720 /* Reregister to clear conflict flag. */ 721 Register (finfo->entries, finfo->file, 722 vers->vn_rcs, vers->ts_rcs, 723 vers->options, vers->tag, 724 vers->date, (char *)0); 725 } 726 } 727 if (!retval) 728 { 729 write_letter (finfo, 'M'); 730 retval = 0; 731 } 732 } 733 break; 734 #ifdef SERVER_SUPPORT 735 case T_PATCH: /* needs patch */ 736 if (patches) 737 { 738 int docheckout; 739 struct stat file_info; 740 unsigned char checksum[16]; 741 742 retval = patch_file (finfo, 743 vers, &docheckout, 744 &file_info, checksum); 745 if (! docheckout) 746 { 747 if (server_active && retval == 0) 748 server_updated (finfo, vers, 749 (rcs_diff_patches 750 ? SERVER_RCS_DIFF 751 : SERVER_PATCHED), 752 file_info.st_mode, checksum, 753 (struct buffer *) NULL); 754 break; 755 } 756 } 757 /* If we're not running as a server, just check the 758 file out. It's simpler and faster than producing 759 and applying patches. */ 760 /* Fall through. */ 761 #endif 762 case T_CHECKOUT: /* needs checkout */ 763 retval = checkout_file (finfo, vers, 0, 0, 1); 764 break; 765 case T_ADDED: /* added but not committed */ 766 write_letter (finfo, 'A'); 767 retval = 0; 768 break; 769 case T_REMOVED: /* removed but not committed */ 770 write_letter (finfo, 'R'); 771 retval = 0; 772 break; 773 case T_REMOVE_ENTRY: /* needs to be un-registered */ 774 retval = scratch_file (finfo); 775 #ifdef SERVER_SUPPORT 776 if (server_active && retval == 0) 777 { 778 if (vers->ts_user == NULL) 779 server_scratch_entry_only (); 780 server_updated (finfo, vers, 781 SERVER_UPDATED, (mode_t) -1, 782 (unsigned char *) NULL, 783 (struct buffer *) NULL); 784 } 785 #endif 786 break; 787 default: /* can't ever happen :-) */ 788 error (0, 0, 789 "unknown file status %d for file %s", status, finfo->file); 790 retval = 0; 791 break; 792 } 793 } 794 795 /* only try to join if things have gone well thus far */ 796 if (retval == 0 && join_rev1) 797 join_file (finfo, vers); 798 799 /* if this directory has an ignore list, add this file to it */ 800 if (ignlist) 801 { 802 Node *p; 803 804 p = getnode (); 805 p->type = FILES; 806 p->key = xstrdup (finfo->file); 807 if (addnode (ignlist, p) != 0) 808 freenode (p); 809 } 810 811 freevers_ts (&vers); 812 return (retval); 813 } 814 815 static void update_ignproc PROTO ((char *, char *)); 816 817 static void 818 update_ignproc (file, dir) 819 char *file; 820 char *dir; 821 { 822 struct file_info finfo; 823 824 memset (&finfo, 0, sizeof (finfo)); 825 finfo.file = file; 826 finfo.update_dir = dir; 827 if (dir[0] == '\0') 828 finfo.fullname = xstrdup (file); 829 else 830 { 831 finfo.fullname = xmalloc (strlen (file) + strlen (dir) + 10); 832 strcpy (finfo.fullname, dir); 833 strcat (finfo.fullname, "/"); 834 strcat (finfo.fullname, file); 835 } 836 837 write_letter (&finfo, '?'); 838 free (finfo.fullname); 839 } 840 841 /* ARGSUSED */ 842 static int 843 update_filesdone_proc (callerdat, err, repository, update_dir, entries) 844 void *callerdat; 845 int err; 846 char *repository; 847 char *update_dir; 848 List *entries; 849 { 850 if (rewrite_tag) 851 { 852 WriteTag (NULL, tag, date, nonbranch, update_dir, repository); 853 rewrite_tag = 0; 854 } 855 856 /* if this directory has an ignore list, process it then free it */ 857 if (ignlist) 858 { 859 ignore_files (ignlist, entries, update_dir, update_ignproc); 860 dellist (&ignlist); 861 } 862 863 /* Clean up CVS admin dirs if we are export */ 864 if (strcmp (command_name, "export") == 0) 865 { 866 /* I'm not sure the existence_error is actually possible (except 867 in cases where we really should print a message), but since 868 this code used to ignore all errors, I'll play it safe. */ 869 if (unlink_file_dir (CVSADM) < 0 && !existence_error (errno)) 870 error (0, errno, "cannot remove %s directory", CVSADM); 871 } 872 #ifdef SERVER_SUPPORT 873 else if (!server_active && !pipeout) 874 #else 875 else if (!pipeout) 876 #endif /* SERVER_SUPPORT */ 877 { 878 /* If there is no CVS/Root file, add one */ 879 if (!isfile (CVSADM_ROOT)) 880 Create_Root ((char *) NULL, CVSroot_original); 881 } 882 883 return (err); 884 } 885 886 /* 887 * update_dirent_proc () is called back by the recursion processor before a 888 * sub-directory is processed for update. In this case, update_dirent proc 889 * will probably create the directory unless -d isn't specified and this is a 890 * new directory. A return code of 0 indicates the directory should be 891 * processed by the recursion code. A return of non-zero indicates the 892 * recursion code should skip this directory. 893 */ 894 static Dtype 895 update_dirent_proc (callerdat, dir, repository, update_dir, entries) 896 void *callerdat; 897 char *dir; 898 char *repository; 899 char *update_dir; 900 List *entries; 901 { 902 if (ignore_directory (update_dir)) 903 { 904 /* print the warm fuzzy message */ 905 if (!quiet) 906 error (0, 0, "Ignoring %s", update_dir); 907 return R_SKIP_ALL; 908 } 909 910 if (!isdir (dir)) 911 { 912 /* if we aren't building dirs, blow it off */ 913 if (!update_build_dirs) 914 return (R_SKIP_ALL); 915 916 /* Various CVS administrators are in the habit of removing 917 the repository directory for things they don't want any 918 more. I've even been known to do it myself (on rare 919 occasions). Not the usual recommended practice, but we 920 want to try to come up with some kind of 921 reasonable/documented/sensible behavior. Generally 922 the behavior is to just skip over that directory (see 923 dirs test in sanity.sh; the case which reaches here 924 is when update -d is specified, and the working directory 925 is gone but the subdirectory is still mentioned in 926 CVS/Entries). */ 927 if (1 928 #ifdef SERVER_SUPPORT 929 /* In the remote case, the client should refrain from 930 sending us the directory in the first place. So we 931 want to continue to give an error, so clients make 932 sure to do this. */ 933 && !server_active 934 #endif 935 && !isdir (repository)) 936 return R_SKIP_ALL; 937 938 if (noexec) 939 { 940 /* ignore the missing dir if -n is specified */ 941 error (0, 0, "New directory `%s' -- ignored", update_dir); 942 return (R_SKIP_ALL); 943 } 944 else 945 { 946 /* otherwise, create the dir and appropriate adm files */ 947 948 /* If no tag or date were specified on the command line, 949 and we're not using -A, we want the subdirectory to use 950 the tag and date, if any, of the current directory. 951 That way, update -d will work correctly when working on 952 a branch. 953 954 We use TAG_UPDATE_DIR to undo the tag setting in 955 update_dirleave_proc. If we did not do this, we would 956 not correctly handle a working directory with multiple 957 tags (and maybe we should prohibit such working 958 directories, but they work now and we shouldn't make 959 them stop working without more thought). */ 960 if ((tag == NULL && date == NULL) && ! aflag) 961 { 962 ParseTag (&tag, &date, &nonbranch); 963 if (tag != NULL || date != NULL) 964 tag_update_dir = xstrdup (update_dir); 965 } 966 967 make_directory (dir); 968 Create_Admin (dir, update_dir, repository, tag, date, 969 /* This is a guess. We will rewrite it later 970 via WriteTag. */ 971 0, 972 0, 973 1); 974 rewrite_tag = 1; 975 nonbranch = 0; 976 Subdir_Register (entries, (char *) NULL, dir); 977 } 978 } 979 /* Do we need to check noexec here? */ 980 else if (!pipeout) 981 { 982 char *cvsadmdir; 983 984 /* The directory exists. Check to see if it has a CVS 985 subdirectory. */ 986 987 cvsadmdir = xmalloc (strlen (dir) + 80); 988 strcpy (cvsadmdir, dir); 989 strcat (cvsadmdir, "/"); 990 strcat (cvsadmdir, CVSADM); 991 992 if (!isdir (cvsadmdir)) 993 { 994 /* We cannot successfully recurse into a directory without a CVS 995 subdirectory. Generally we will have already printed 996 "? foo". */ 997 free (cvsadmdir); 998 return R_SKIP_ALL; 999 } 1000 free (cvsadmdir); 1001 } 1002 1003 /* 1004 * If we are building dirs and not going to stdout, we make sure there is 1005 * no static entries file and write the tag file as appropriate 1006 */ 1007 if (!pipeout) 1008 { 1009 if (update_build_dirs) 1010 { 1011 char *tmp; 1012 1013 tmp = xmalloc (strlen (dir) + sizeof (CVSADM_ENTSTAT) + 10); 1014 (void) sprintf (tmp, "%s/%s", dir, CVSADM_ENTSTAT); 1015 if (unlink_file (tmp) < 0 && ! existence_error (errno)) 1016 error (1, errno, "cannot remove file %s", tmp); 1017 #ifdef SERVER_SUPPORT 1018 if (server_active) 1019 server_clear_entstat (update_dir, repository); 1020 #endif 1021 free (tmp); 1022 } 1023 1024 /* keep the CVS/Tag file current with the specified arguments */ 1025 if (aflag || tag || date) 1026 { 1027 WriteTag (dir, tag, date, 0, update_dir, repository); 1028 rewrite_tag = 1; 1029 nonbranch = 0; 1030 } 1031 1032 /* initialize the ignore list for this directory */ 1033 ignlist = getlist (); 1034 } 1035 1036 /* print the warm fuzzy message */ 1037 if (!quiet) 1038 error (0, 0, "Updating %s", update_dir); 1039 1040 return (R_PROCESS); 1041 } 1042 1043 /* 1044 * update_dirleave_proc () is called back by the recursion code upon leaving 1045 * a directory. It will prune empty directories if needed and will execute 1046 * any appropriate update programs. 1047 */ 1048 /* ARGSUSED */ 1049 static int 1050 update_dirleave_proc (callerdat, dir, err, update_dir, entries) 1051 void *callerdat; 1052 char *dir; 1053 int err; 1054 char *update_dir; 1055 List *entries; 1056 { 1057 FILE *fp; 1058 1059 /* Delete the ignore list if it hasn't already been done. */ 1060 if (ignlist) 1061 dellist (&ignlist); 1062 1063 /* If we set the tag or date for a new subdirectory in 1064 update_dirent_proc, and we're now done with that subdirectory, 1065 undo the tag/date setting. Note that we know that the tag and 1066 date were both originally NULL in this case. */ 1067 if (tag_update_dir != NULL && strcmp (update_dir, tag_update_dir) == 0) 1068 { 1069 if (tag != NULL) 1070 { 1071 free (tag); 1072 tag = NULL; 1073 } 1074 if (date != NULL) 1075 { 1076 free (date); 1077 date = NULL; 1078 } 1079 nonbranch = 0; 1080 free (tag_update_dir); 1081 tag_update_dir = NULL; 1082 } 1083 1084 /* run the update_prog if there is one */ 1085 /* FIXME: should be checking for errors from CVS_FOPEN and printing 1086 them if not existence_error. */ 1087 if (err == 0 && !pipeout && !noexec && 1088 (fp = CVS_FOPEN (CVSADM_UPROG, "r")) != NULL) 1089 { 1090 char *cp; 1091 char *repository; 1092 char *line = NULL; 1093 size_t line_allocated = 0; 1094 1095 repository = Name_Repository ((char *) NULL, update_dir); 1096 if (getline (&line, &line_allocated, fp) >= 0) 1097 { 1098 if ((cp = strrchr (line, '\n')) != NULL) 1099 *cp = '\0'; 1100 run_setup (line); 1101 run_arg (repository); 1102 cvs_output (program_name, 0); 1103 cvs_output (" ", 1); 1104 cvs_output (command_name, 0); 1105 cvs_output (": Executing '", 0); 1106 run_print (stdout); 1107 cvs_output ("'\n", 0); 1108 cvs_flushout (); 1109 (void) run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL); 1110 } 1111 else if (ferror (fp)) 1112 error (0, errno, "cannot read %s", CVSADM_UPROG); 1113 else 1114 error (0, 0, "unexpected end of file on %s", CVSADM_UPROG); 1115 1116 if (fclose (fp) < 0) 1117 error (0, errno, "cannot close %s", CVSADM_UPROG); 1118 if (line != NULL) 1119 free (line); 1120 free (repository); 1121 } 1122 1123 if (strchr (dir, '/') == NULL) 1124 { 1125 /* FIXME: chdir ("..") loses with symlinks. */ 1126 /* Prune empty dirs on the way out - if necessary */ 1127 (void) CVS_CHDIR (".."); 1128 if (update_prune_dirs && isemptydir (dir, 0)) 1129 { 1130 /* I'm not sure the existence_error is actually possible (except 1131 in cases where we really should print a message), but since 1132 this code used to ignore all errors, I'll play it safe. */ 1133 if (unlink_file_dir (dir) < 0 && !existence_error (errno)) 1134 error (0, errno, "cannot remove %s directory", dir); 1135 Subdir_Deregister (entries, (char *) NULL, dir); 1136 } 1137 } 1138 1139 return (err); 1140 } 1141 1142 static int isremoved PROTO ((Node *, void *)); 1143 1144 /* Returns 1 if the file indicated by node has been removed. */ 1145 static int 1146 isremoved (node, closure) 1147 Node *node; 1148 void *closure; 1149 { 1150 Entnode *entdata = (Entnode*) node->data; 1151 1152 /* If the first character of the version is a '-', the file has been 1153 removed. */ 1154 return (entdata->version && entdata->version[0] == '-') ? 1 : 0; 1155 } 1156 1157 /* Returns 1 if the argument directory is completely empty, other than the 1158 existence of the CVS directory entry. Zero otherwise. If MIGHT_NOT_EXIST 1159 and the directory doesn't exist, then just return 0. */ 1160 int 1161 isemptydir (dir, might_not_exist) 1162 char *dir; 1163 int might_not_exist; 1164 { 1165 DIR *dirp; 1166 struct dirent *dp; 1167 1168 if ((dirp = CVS_OPENDIR (dir)) == NULL) 1169 { 1170 if (might_not_exist && existence_error (errno)) 1171 return 0; 1172 error (0, errno, "cannot open directory %s for empty check", dir); 1173 return (0); 1174 } 1175 errno = 0; 1176 while ((dp = readdir (dirp)) != NULL) 1177 { 1178 if (strcmp (dp->d_name, ".") != 0 1179 && strcmp (dp->d_name, "..") != 0) 1180 { 1181 if (strcmp (dp->d_name, CVSADM) != 0) 1182 { 1183 /* An entry other than the CVS directory. The directory 1184 is certainly not empty. */ 1185 (void) closedir (dirp); 1186 return (0); 1187 } 1188 else 1189 { 1190 /* The CVS directory entry. We don't have to worry about 1191 this unless the Entries file indicates that files have 1192 been removed, but not committed, in this directory. 1193 (Removing the directory would prevent people from 1194 comitting the fact that they removed the files!) */ 1195 List *l; 1196 int files_removed; 1197 struct saved_cwd cwd; 1198 1199 if (save_cwd (&cwd)) 1200 error_exit (); 1201 1202 if (CVS_CHDIR (dir) < 0) 1203 error (1, errno, "cannot change directory to %s", dir); 1204 l = Entries_Open (0, NULL); 1205 files_removed = walklist (l, isremoved, 0); 1206 Entries_Close (l); 1207 1208 if (restore_cwd (&cwd, NULL)) 1209 error_exit (); 1210 free_cwd (&cwd); 1211 1212 if (files_removed != 0) 1213 { 1214 /* There are files that have been removed, but not 1215 committed! Do not consider the directory empty. */ 1216 (void) closedir (dirp); 1217 return (0); 1218 } 1219 } 1220 } 1221 errno = 0; 1222 } 1223 if (errno != 0) 1224 { 1225 error (0, errno, "cannot read directory %s", dir); 1226 (void) closedir (dirp); 1227 return (0); 1228 } 1229 (void) closedir (dirp); 1230 return (1); 1231 } 1232 1233 /* 1234 * scratch the Entries file entry associated with a file 1235 */ 1236 static int 1237 scratch_file (finfo) 1238 struct file_info *finfo; 1239 { 1240 history_write ('W', finfo->update_dir, "", finfo->file, finfo->repository); 1241 Scratch_Entry (finfo->entries, finfo->file); 1242 if (unlink_file (finfo->file) < 0 && ! existence_error (errno)) 1243 error (0, errno, "unable to remove %s", finfo->fullname); 1244 return (0); 1245 } 1246 1247 /* 1248 * Check out a file. 1249 */ 1250 static int 1251 checkout_file (finfo, vers_ts, adding, merging, update_server) 1252 struct file_info *finfo; 1253 Vers_TS *vers_ts; 1254 int adding; 1255 int merging; 1256 int update_server; 1257 { 1258 char *backup; 1259 int set_time, retval = 0; 1260 int status; 1261 int file_is_dead; 1262 struct buffer *revbuf; 1263 1264 backup = NULL; 1265 revbuf = NULL; 1266 1267 /* Don't screw with backup files if we're going to stdout, or if 1268 we are the server. */ 1269 if (!pipeout 1270 #ifdef SERVER_SUPPORT 1271 && ! server_active 1272 #endif 1273 ) 1274 { 1275 backup = xmalloc (strlen (finfo->file) 1276 + sizeof (CVSADM) 1277 + sizeof (CVSPREFIX) 1278 + 10); 1279 (void) sprintf (backup, "%s/%s%s", CVSADM, CVSPREFIX, finfo->file); 1280 if (isfile (finfo->file)) 1281 rename_file (finfo->file, backup); 1282 else 1283 { 1284 /* If -f/-t wrappers are being used to wrap up a directory, 1285 then backup might be a directory instead of just a file. */ 1286 if (unlink_file_dir (backup) < 0) 1287 { 1288 /* Not sure if the existence_error check is needed here. */ 1289 if (!existence_error (errno)) 1290 /* FIXME: should include update_dir in message. */ 1291 error (0, errno, "error removing %s", backup); 1292 } 1293 free (backup); 1294 backup = NULL; 1295 } 1296 } 1297 1298 file_is_dead = RCS_isdead (vers_ts->srcfile, vers_ts->vn_rcs); 1299 1300 if (!file_is_dead) 1301 { 1302 /* 1303 * if we are checking out to stdout, print a nice message to 1304 * stderr, and add the -p flag to the command */ 1305 if (pipeout) 1306 { 1307 if (!quiet) 1308 { 1309 cvs_outerr ("\ 1310 ===================================================================\n\ 1311 Checking out ", 0); 1312 cvs_outerr (finfo->fullname, 0); 1313 cvs_outerr ("\n\ 1314 RCS: ", 0); 1315 cvs_outerr (vers_ts->srcfile->path, 0); 1316 cvs_outerr ("\n\ 1317 VERS: ", 0); 1318 cvs_outerr (vers_ts->vn_rcs, 0); 1319 cvs_outerr ("\n***************\n", 0); 1320 } 1321 } 1322 1323 #ifdef SERVER_SUPPORT 1324 if (update_server 1325 && server_active 1326 && ! pipeout 1327 && ! file_gzip_level 1328 && ! joining () 1329 && ! wrap_name_has (finfo->file, WRAP_FROMCVS)) 1330 { 1331 revbuf = buf_nonio_initialize ((BUFMEMERRPROC) NULL); 1332 status = RCS_checkout (vers_ts->srcfile, (char *) NULL, 1333 vers_ts->vn_rcs, vers_ts->vn_tag, 1334 vers_ts->options, RUN_TTY, 1335 checkout_to_buffer, revbuf); 1336 } 1337 else 1338 #endif 1339 status = RCS_checkout (vers_ts->srcfile, 1340 pipeout ? NULL : finfo->file, 1341 vers_ts->vn_rcs, vers_ts->vn_tag, 1342 vers_ts->options, RUN_TTY, 1343 (RCSCHECKOUTPROC) NULL, (void *) NULL); 1344 } 1345 if (file_is_dead || status == 0) 1346 { 1347 mode_t mode; 1348 1349 mode = (mode_t) -1; 1350 1351 if (!pipeout) 1352 { 1353 Vers_TS *xvers_ts; 1354 1355 if (revbuf != NULL && !noexec) 1356 { 1357 struct stat sb; 1358 1359 /* FIXME: We should have RCS_checkout return the mode. 1360 That would also fix the kludge with noexec, above, which 1361 is here only because noexec doesn't write srcfile->path 1362 for us to stat. */ 1363 if (stat (vers_ts->srcfile->path, &sb) < 0) 1364 error (1, errno, "cannot stat %s", 1365 vers_ts->srcfile->path); 1366 mode = sb.st_mode &~ (S_IWRITE | S_IWGRP | S_IWOTH); 1367 } 1368 1369 if (cvswrite 1370 && !file_is_dead 1371 && !fileattr_get (finfo->file, "_watched")) 1372 { 1373 if (revbuf == NULL) 1374 xchmod (finfo->file, 1); 1375 else 1376 { 1377 /* We know that we are the server here, so 1378 although xchmod checks umask, we don't bother. */ 1379 mode |= (((mode & S_IRUSR) ? S_IWUSR : 0) 1380 | ((mode & S_IRGRP) ? S_IWGRP : 0) 1381 | ((mode & S_IROTH) ? S_IWOTH : 0)); 1382 } 1383 } 1384 1385 { 1386 /* A newly checked out file is never under the spell 1387 of "cvs edit". If we think we were editing it 1388 from a previous life, clean up. Would be better to 1389 check for same the working directory instead of 1390 same user, but that is hairy. */ 1391 1392 struct addremove_args args; 1393 1394 editor_set (finfo->file, getcaller (), NULL); 1395 1396 memset (&args, 0, sizeof args); 1397 args.remove_temp = 1; 1398 watch_modify_watchers (finfo->file, &args); 1399 } 1400 1401 /* set the time from the RCS file iff it was unknown before */ 1402 set_time = 1403 (!noexec 1404 && (vers_ts->vn_user == NULL || 1405 strncmp (vers_ts->ts_rcs, "Initial", 7) == 0) 1406 && !file_is_dead); 1407 1408 wrap_fromcvs_process_file (finfo->file); 1409 1410 xvers_ts = Version_TS (finfo, options, tag, date, 1411 force_tag_match, set_time); 1412 if (strcmp (xvers_ts->options, "-V4") == 0) 1413 xvers_ts->options[0] = '\0'; 1414 1415 if (revbuf != NULL) 1416 { 1417 /* If we stored the file data into a buffer, then we 1418 didn't create a file at all, so xvers_ts->ts_user 1419 is wrong. The correct value is to have it be the 1420 same as xvers_ts->ts_rcs, meaning that the working 1421 file is unchanged from the RCS file. 1422 1423 FIXME: We should tell Version_TS not to waste time 1424 statting the nonexistent file. 1425 1426 FIXME: Actually, I don't think the ts_user value 1427 matters at all here. The only use I know of is 1428 that it is printed in a trace message by 1429 Server_Register. */ 1430 1431 if (xvers_ts->ts_user != NULL) 1432 free (xvers_ts->ts_user); 1433 xvers_ts->ts_user = xstrdup (xvers_ts->ts_rcs); 1434 } 1435 1436 (void) time (&last_register_time); 1437 1438 if (file_is_dead) 1439 { 1440 if (xvers_ts->vn_user != NULL) 1441 { 1442 error (0, 0, 1443 "warning: %s is not (any longer) pertinent", 1444 finfo->fullname); 1445 } 1446 Scratch_Entry (finfo->entries, finfo->file); 1447 #ifdef SERVER_SUPPORT 1448 if (server_active && xvers_ts->ts_user == NULL) 1449 server_scratch_entry_only (); 1450 #endif 1451 /* FIXME: Rather than always unlink'ing, and ignoring the 1452 existence_error, we should do the unlink only if 1453 vers_ts->ts_user is non-NULL. Then there would be no 1454 need to ignore an existence_error (for example, if the 1455 user removes the file while we are running). */ 1456 if (unlink_file (finfo->file) < 0 && ! existence_error (errno)) 1457 { 1458 error (0, errno, "cannot remove %s", finfo->fullname); 1459 } 1460 } 1461 else 1462 Register (finfo->entries, finfo->file, 1463 adding ? "0" : xvers_ts->vn_rcs, 1464 xvers_ts->ts_user, xvers_ts->options, 1465 xvers_ts->tag, xvers_ts->date, 1466 (char *)0); /* Clear conflict flag on fresh checkout */ 1467 1468 /* fix up the vers structure, in case it is used by join */ 1469 if (join_rev1) 1470 { 1471 if (vers_ts->vn_user != NULL) 1472 free (vers_ts->vn_user); 1473 if (vers_ts->vn_rcs != NULL) 1474 free (vers_ts->vn_rcs); 1475 vers_ts->vn_user = xstrdup (xvers_ts->vn_rcs); 1476 vers_ts->vn_rcs = xstrdup (xvers_ts->vn_rcs); 1477 } 1478 1479 /* If this is really Update and not Checkout, recode history */ 1480 if (strcmp (command_name, "update") == 0) 1481 history_write ('U', finfo->update_dir, xvers_ts->vn_rcs, finfo->file, 1482 finfo->repository); 1483 1484 freevers_ts (&xvers_ts); 1485 1486 if (!really_quiet && !file_is_dead) 1487 { 1488 write_letter (finfo, 'U'); 1489 } 1490 } 1491 1492 #ifdef SERVER_SUPPORT 1493 if (update_server && server_active) 1494 server_updated (finfo, vers_ts, 1495 merging ? SERVER_MERGED : SERVER_UPDATED, 1496 mode, (unsigned char *) NULL, revbuf); 1497 #endif 1498 } 1499 else 1500 { 1501 if (backup != NULL) 1502 { 1503 rename_file (backup, finfo->file); 1504 free (backup); 1505 backup = NULL; 1506 } 1507 1508 error (0, 0, "could not check out %s", finfo->fullname); 1509 1510 retval = status; 1511 } 1512 1513 if (backup != NULL) 1514 { 1515 /* If -f/-t wrappers are being used to wrap up a directory, 1516 then backup might be a directory instead of just a file. */ 1517 if (unlink_file_dir (backup) < 0) 1518 { 1519 /* Not sure if the existence_error check is needed here. */ 1520 if (!existence_error (errno)) 1521 /* FIXME: should include update_dir in message. */ 1522 error (0, errno, "error removing %s", backup); 1523 } 1524 free (backup); 1525 } 1526 1527 return (retval); 1528 } 1529 1530 #ifdef SERVER_SUPPORT 1531 1532 /* This function is used to write data from a file being checked out 1533 into a buffer. */ 1534 1535 static void 1536 checkout_to_buffer (callerdat, data, len) 1537 void *callerdat; 1538 const char *data; 1539 size_t len; 1540 { 1541 struct buffer *buf = (struct buffer *) callerdat; 1542 1543 buf_output (buf, data, len); 1544 } 1545 1546 #endif /* SERVER_SUPPORT */ 1547 1548 #ifdef SERVER_SUPPORT 1549 1550 /* This structure is used to pass information between patch_file and 1551 patch_file_write. */ 1552 1553 struct patch_file_data 1554 { 1555 /* File name, for error messages. */ 1556 const char *filename; 1557 /* File to which to write. */ 1558 FILE *fp; 1559 /* Whether to compute the MD5 checksum. */ 1560 int compute_checksum; 1561 /* Data structure for computing the MD5 checksum. */ 1562 struct cvs_MD5Context context; 1563 /* Set if the file has a final newline. */ 1564 int final_nl; 1565 }; 1566 1567 /* Patch a file. Runs diff. This is only done when running as the 1568 * server. The hope is that the diff will be smaller than the file 1569 * itself. 1570 */ 1571 static int 1572 patch_file (finfo, vers_ts, docheckout, file_info, checksum) 1573 struct file_info *finfo; 1574 Vers_TS *vers_ts; 1575 int *docheckout; 1576 struct stat *file_info; 1577 unsigned char *checksum; 1578 { 1579 char *backup; 1580 char *file1; 1581 char *file2; 1582 int retval = 0; 1583 int retcode = 0; 1584 int fail; 1585 long file_size; 1586 FILE *e; 1587 struct patch_file_data data; 1588 1589 *docheckout = 0; 1590 1591 if (noexec || pipeout || joining ()) 1592 { 1593 *docheckout = 1; 1594 return 0; 1595 } 1596 1597 /* If this file has been marked as being binary, then never send a 1598 patch. */ 1599 if (strcmp (vers_ts->options, "-kb") == 0) 1600 { 1601 *docheckout = 1; 1602 return 0; 1603 } 1604 1605 /* First check that the first revision exists. If it has been nuked 1606 by cvs admin -o, then just fall back to checking out entire 1607 revisions. In some sense maybe we don't have to do this; after 1608 all cvs.texinfo says "Make sure that no-one has checked out a 1609 copy of the revision you outdate" but then again, that advice 1610 doesn't really make complete sense, because "cvs admin" operates 1611 on a working directory and so _someone_ will almost always have 1612 _some_ revision checked out. */ 1613 { 1614 char *rev; 1615 1616 rev = RCS_gettag (finfo->rcs, vers_ts->vn_user, 1, NULL); 1617 if (rev == NULL) 1618 { 1619 *docheckout = 1; 1620 return 0; 1621 } 1622 else 1623 free (rev); 1624 } 1625 1626 /* If the revision is dead, let checkout_file handle it rather 1627 than duplicating the processing here. */ 1628 if (RCS_isdead (vers_ts->srcfile, vers_ts->vn_rcs)) 1629 { 1630 *docheckout = 1; 1631 return 0; 1632 } 1633 1634 backup = xmalloc (strlen (finfo->file) 1635 + sizeof (CVSADM) 1636 + sizeof (CVSPREFIX) 1637 + 10); 1638 (void) sprintf (backup, "%s/%s%s", CVSADM, CVSPREFIX, finfo->file); 1639 if (isfile (finfo->file)) 1640 rename_file (finfo->file, backup); 1641 else 1642 { 1643 if (unlink_file (backup) < 0 1644 && !existence_error (errno)) 1645 error (0, errno, "cannot remove %s", backup); 1646 } 1647 1648 file1 = xmalloc (strlen (finfo->file) 1649 + sizeof (CVSADM) 1650 + sizeof (CVSPREFIX) 1651 + 10); 1652 (void) sprintf (file1, "%s/%s%s-1", CVSADM, CVSPREFIX, finfo->file); 1653 file2 = xmalloc (strlen (finfo->file) 1654 + sizeof (CVSADM) 1655 + sizeof (CVSPREFIX) 1656 + 10); 1657 (void) sprintf (file2, "%s/%s%s-2", CVSADM, CVSPREFIX, finfo->file); 1658 1659 fail = 0; 1660 1661 /* We need to check out both revisions first, to see if either one 1662 has a trailing newline. Because of this, we don't use rcsdiff, 1663 but just use diff. */ 1664 1665 e = CVS_FOPEN (file1, "w"); 1666 if (e == NULL) 1667 error (1, errno, "cannot open %s", file1); 1668 1669 data.filename = file1; 1670 data.fp = e; 1671 data.final_nl = 0; 1672 data.compute_checksum = 0; 1673 1674 retcode = RCS_checkout (vers_ts->srcfile, (char *) NULL, 1675 vers_ts->vn_user, (char *) NULL, 1676 vers_ts->options, RUN_TTY, 1677 patch_file_write, (void *) &data); 1678 1679 if (fclose (e) < 0) 1680 error (1, errno, "cannot close %s", file1); 1681 1682 if (retcode != 0 || ! data.final_nl) 1683 fail = 1; 1684 1685 if (! fail) 1686 { 1687 e = CVS_FOPEN (file2, "w"); 1688 if (e == NULL) 1689 error (1, errno, "cannot open %s", file2); 1690 1691 data.filename = file2; 1692 data.fp = e; 1693 data.final_nl = 0; 1694 data.compute_checksum = 1; 1695 cvs_MD5Init (&data.context); 1696 1697 retcode = RCS_checkout (vers_ts->srcfile, (char *) NULL, 1698 vers_ts->vn_rcs, vers_ts->vn_tag, 1699 vers_ts->options, RUN_TTY, 1700 patch_file_write, (void *) &data); 1701 1702 fseek(e, 0L, SEEK_END); 1703 file_size = ftell(e); 1704 1705 if (fclose (e) < 0) 1706 error (1, errno, "cannot close %s", file2); 1707 1708 if (retcode != 0 || ! data.final_nl) 1709 fail = 1; 1710 else 1711 cvs_MD5Final (checksum, &data.context); 1712 } 1713 1714 retcode = 0; 1715 if (! fail) 1716 { 1717 char *diff_options; 1718 1719 /* If the client does not support the Rcs-diff command, we 1720 send a context diff, and the client must invoke patch. 1721 That approach was problematical for various reasons. The 1722 new approach only requires running diff in the server; the 1723 client can handle everything without invoking an external 1724 program. */ 1725 if (! rcs_diff_patches) 1726 { 1727 /* We use -c, not -u, because that is what CVS has 1728 traditionally used. Kind of a moot point, now that 1729 Rcs-diff is preferred, so there is no point in making 1730 the compatibility issues worse. */ 1731 diff_options = "-c"; 1732 } 1733 else 1734 { 1735 /* Now that diff is librarified, we could be passing -a if 1736 we wanted to. However, it is unclear to me whether we 1737 would want to. Does diff -a, in any significant 1738 percentage of cases, produce patches which are smaller 1739 than the files it is patching? I guess maybe text 1740 files with character sets which diff regards as 1741 'binary'. Conversely, do they tend to be much larger 1742 in the bad cases? This needs some more 1743 thought/investigation, I suspect. */ 1744 1745 diff_options = "-n"; 1746 } 1747 retcode = diff_exec (file1, file2, diff_options, finfo->file); 1748 1749 /* A retcode of 0 means no differences. 1 means some differences. */ 1750 if (retcode != 0 1751 && retcode != 1) 1752 { 1753 fail = 1; 1754 } 1755 else 1756 { 1757 #define BINARY "Binary" 1758 char buf[sizeof BINARY]; 1759 unsigned int c; 1760 1761 /* Stat the original RCS file, and then adjust it the way 1762 that RCS_checkout would. FIXME: This is an abstraction 1763 violation. */ 1764 if (CVS_STAT (vers_ts->srcfile->path, file_info) < 0) 1765 error (1, errno, "could not stat %s", vers_ts->srcfile->path); 1766 if (chmod (finfo->file, 1767 file_info->st_mode & ~(S_IWRITE | S_IWGRP | S_IWOTH)) 1768 < 0) 1769 error (0, errno, "cannot change mode of file %s", finfo->file); 1770 if (cvswrite 1771 && !fileattr_get (finfo->file, "_watched")) 1772 xchmod (finfo->file, 1); 1773 1774 /* Check the diff output to make sure patch will be handle it. */ 1775 e = CVS_FOPEN (finfo->file, "r"); 1776 if (e == NULL) 1777 error (1, errno, "could not open diff output file %s", 1778 finfo->fullname); 1779 c = fread (buf, 1, sizeof BINARY - 1, e); 1780 buf[c] = '\0'; 1781 if (strcmp (buf, BINARY) == 0) 1782 { 1783 /* These are binary files. We could use diff -a, but 1784 patch can't handle that. */ 1785 fail = 1; 1786 } 1787 else { 1788 /* 1789 * Don't send a diff if just sending the entire file 1790 * would be smaller 1791 */ 1792 fseek(e, 0L, SEEK_END); 1793 if (file_size < ftell(e)) 1794 fail = 1; 1795 } 1796 1797 fclose (e); 1798 } 1799 } 1800 1801 if (! fail) 1802 { 1803 Vers_TS *xvers_ts; 1804 1805 /* This stuff is just copied blindly from checkout_file. I 1806 don't really know what it does. */ 1807 xvers_ts = Version_TS (finfo, options, tag, date, 1808 force_tag_match, 0); 1809 if (strcmp (xvers_ts->options, "-V4") == 0) 1810 xvers_ts->options[0] = '\0'; 1811 1812 Register (finfo->entries, finfo->file, xvers_ts->vn_rcs, 1813 xvers_ts->ts_user, xvers_ts->options, 1814 xvers_ts->tag, xvers_ts->date, NULL); 1815 1816 if (CVS_STAT (finfo->file, file_info) < 0) 1817 error (1, errno, "could not stat %s", finfo->file); 1818 1819 /* If this is really Update and not Checkout, recode history */ 1820 if (strcmp (command_name, "update") == 0) 1821 history_write ('P', finfo->update_dir, xvers_ts->vn_rcs, finfo->file, 1822 finfo->repository); 1823 1824 freevers_ts (&xvers_ts); 1825 1826 if (!really_quiet) 1827 { 1828 write_letter (finfo, 'P'); 1829 } 1830 } 1831 else 1832 { 1833 int old_errno = errno; /* save errno value over the rename */ 1834 1835 if (isfile (backup)) 1836 rename_file (backup, finfo->file); 1837 1838 if (retcode != 0 && retcode != 1) 1839 error (retcode == -1 ? 1 : 0, retcode == -1 ? old_errno : 0, 1840 "could not diff %s", finfo->fullname); 1841 1842 *docheckout = 1; 1843 retval = retcode; 1844 } 1845 1846 if (unlink_file (backup) < 0 1847 && !existence_error (errno)) 1848 error (0, errno, "cannot remove %s", backup); 1849 if (unlink_file (file1) < 0 1850 && !existence_error (errno)) 1851 error (0, errno, "cannot remove %s", file1); 1852 if (unlink_file (file2) < 0 1853 && !existence_error (errno)) 1854 error (0, errno, "cannot remove %s", file2); 1855 1856 free (backup); 1857 free (file1); 1858 free (file2); 1859 return (retval); 1860 } 1861 1862 /* Write data to a file. Record whether the last byte written was a 1863 newline. Optionally compute a checksum. This is called by 1864 patch_file via RCS_checkout. */ 1865 1866 static void 1867 patch_file_write (callerdat, buffer, len) 1868 void *callerdat; 1869 const char *buffer; 1870 size_t len; 1871 { 1872 struct patch_file_data *data = (struct patch_file_data *) callerdat; 1873 1874 if (fwrite (buffer, 1, len, data->fp) != len) 1875 error (1, errno, "cannot write %s", data->filename); 1876 1877 data->final_nl = (buffer[len - 1] == '\n'); 1878 1879 if (data->compute_checksum) 1880 cvs_MD5Update (&data->context, (unsigned char *) buffer, len); 1881 } 1882 1883 #endif /* SERVER_SUPPORT */ 1884 1885 /* 1886 * Several of the types we process only print a bit of information consisting 1887 * of a single letter and the name. 1888 */ 1889 static void 1890 write_letter (finfo, letter) 1891 struct file_info *finfo; 1892 int letter; 1893 { 1894 if (!really_quiet) 1895 { 1896 char *tag = NULL; 1897 /* Big enough for "+updated" or any of its ilk. */ 1898 char buf[80]; 1899 1900 switch (letter) 1901 { 1902 case 'U': 1903 tag = "updated"; 1904 break; 1905 default: 1906 /* We don't yet support tagged output except for "U". */ 1907 break; 1908 } 1909 1910 if (tag != NULL) 1911 { 1912 sprintf (buf, "+%s", tag); 1913 cvs_output_tagged (buf, NULL); 1914 } 1915 buf[0] = letter; 1916 buf[1] = ' '; 1917 buf[2] = '\0'; 1918 cvs_output_tagged ("text", buf); 1919 cvs_output_tagged ("fname", finfo->fullname); 1920 cvs_output_tagged ("newline", NULL); 1921 if (tag != NULL) 1922 { 1923 sprintf (buf, "-%s", tag); 1924 cvs_output_tagged (buf, NULL); 1925 } 1926 } 1927 return; 1928 } 1929 1930 /* 1931 * Do all the magic associated with a file which needs to be merged 1932 */ 1933 static int 1934 merge_file (finfo, vers) 1935 struct file_info *finfo; 1936 Vers_TS *vers; 1937 { 1938 char *backup; 1939 int status; 1940 int retcode = 0; 1941 int retval; 1942 1943 /* 1944 * The users currently modified file is moved to a backup file name 1945 * ".#filename.version", so that it will stay around for a few days 1946 * before being automatically removed by some cron daemon. The "version" 1947 * is the version of the file that the user was most up-to-date with 1948 * before the merge. 1949 */ 1950 backup = xmalloc (strlen (finfo->file) 1951 + strlen (vers->vn_user) 1952 + sizeof (BAKPREFIX) 1953 + 10); 1954 (void) sprintf (backup, "%s%s.%s", BAKPREFIX, finfo->file, vers->vn_user); 1955 1956 if (unlink_file (backup) && !existence_error (errno)) 1957 error (0, errno, "unable to remove %s", backup); 1958 copy_file (finfo->file, backup); 1959 xchmod (finfo->file, 1); 1960 1961 if (strcmp (vers->options, "-kb") == 0 1962 || wrap_merge_is_copy (finfo->file) 1963 || special_file_mismatch (finfo, NULL, vers->vn_rcs)) 1964 { 1965 /* For binary files, a merge is always a conflict. Same for 1966 files whose permissions or linkage do not match. We give the 1967 user the two files, and let them resolve it. It is possible 1968 that we should require a "touch foo" or similar step before 1969 we allow a checkin. */ 1970 1971 /* TODO: it may not always be necessary to regard a permission 1972 mismatch as a conflict. The working file and the RCS file 1973 have a common ancestor `A'; if the working file's permissions 1974 match A's, then it's probably safe to overwrite them with the 1975 RCS permissions. Only if the working file, the RCS file, and 1976 A all disagree should this be considered a conflict. But more 1977 thought needs to go into this, and in the meantime it is safe 1978 to treat any such mismatch as an automatic conflict. -twp */ 1979 1980 #ifdef SERVER_SUPPORT 1981 if (server_active) 1982 server_copy_file (finfo->file, finfo->update_dir, 1983 finfo->repository, backup); 1984 #endif 1985 1986 status = checkout_file (finfo, vers, 0, 1, 1); 1987 1988 /* Is there a better term than "nonmergeable file"? What we 1989 really mean is, not something that CVS cannot or does not 1990 want to merge (there might be an external manual or 1991 automatic merge process). */ 1992 error (0, 0, "nonmergeable file needs merge"); 1993 error (0, 0, "revision %s from repository is now in %s", 1994 vers->vn_rcs, finfo->fullname); 1995 error (0, 0, "file from working directory is now in %s", backup); 1996 write_letter (finfo, 'C'); 1997 1998 history_write ('C', finfo->update_dir, vers->vn_rcs, finfo->file, 1999 finfo->repository); 2000 retval = 0; 2001 goto out; 2002 } 2003 2004 status = RCS_merge(finfo->rcs, vers->srcfile->path, finfo->file, 2005 vers->options, vers->vn_user, vers->vn_rcs); 2006 if (status != 0 && status != 1) 2007 { 2008 error (0, status == -1 ? errno : 0, 2009 "could not merge revision %s of %s", vers->vn_user, finfo->fullname); 2010 error (status == -1 ? 1 : 0, 0, "restoring %s from backup file %s", 2011 finfo->fullname, backup); 2012 rename_file (backup, finfo->file); 2013 retval = 1; 2014 goto out; 2015 } 2016 2017 if (strcmp (vers->options, "-V4") == 0) 2018 vers->options[0] = '\0'; 2019 2020 /* This file is the result of a merge, which means that it has 2021 been modified. We use a special timestamp string which will 2022 not compare equal to any actual timestamp. */ 2023 { 2024 char *cp = 0; 2025 2026 if (status) 2027 { 2028 (void) time (&last_register_time); 2029 cp = time_stamp (finfo->file); 2030 } 2031 Register (finfo->entries, finfo->file, vers->vn_rcs, 2032 "Result of merge", vers->options, vers->tag, 2033 vers->date, cp); 2034 if (cp) 2035 free (cp); 2036 } 2037 2038 /* fix up the vers structure, in case it is used by join */ 2039 if (join_rev1) 2040 { 2041 if (vers->vn_user != NULL) 2042 free (vers->vn_user); 2043 vers->vn_user = xstrdup (vers->vn_rcs); 2044 } 2045 2046 #ifdef SERVER_SUPPORT 2047 /* Send the new contents of the file before the message. If we 2048 wanted to be totally correct, we would have the client write 2049 the message only after the file has safely been written. */ 2050 if (server_active) 2051 { 2052 server_copy_file (finfo->file, finfo->update_dir, finfo->repository, 2053 backup); 2054 server_updated (finfo, vers, SERVER_MERGED, 2055 (mode_t) -1, (unsigned char *) NULL, 2056 (struct buffer *) NULL); 2057 } 2058 #endif 2059 2060 /* FIXME: the noexec case is broken. RCS_merge could be doing the 2061 xcmp on the temporary files without much hassle, I think. */ 2062 if (!noexec && !xcmp (backup, finfo->file)) 2063 { 2064 cvs_output (finfo->fullname, 0); 2065 cvs_output (" already contains the differences between ", 0); 2066 cvs_output (vers->vn_user, 0); 2067 cvs_output (" and ", 0); 2068 cvs_output (vers->vn_rcs, 0); 2069 cvs_output ("\n", 1); 2070 2071 history_write ('G', finfo->update_dir, vers->vn_rcs, finfo->file, 2072 finfo->repository); 2073 retval = 0; 2074 goto out; 2075 } 2076 2077 if (status == 1) 2078 { 2079 error (0, 0, "conflicts found in %s", finfo->fullname); 2080 2081 write_letter (finfo, 'C'); 2082 2083 history_write ('C', finfo->update_dir, vers->vn_rcs, finfo->file, finfo->repository); 2084 2085 } 2086 else if (retcode == -1) 2087 { 2088 error (1, errno, "fork failed while examining update of %s", 2089 finfo->fullname); 2090 } 2091 else 2092 { 2093 write_letter (finfo, 'M'); 2094 history_write ('G', finfo->update_dir, vers->vn_rcs, finfo->file, 2095 finfo->repository); 2096 } 2097 retval = 0; 2098 out: 2099 free (backup); 2100 return retval; 2101 } 2102 2103 /* 2104 * Do all the magic associated with a file which needs to be joined 2105 * (-j option) 2106 */ 2107 static void 2108 join_file (finfo, vers) 2109 struct file_info *finfo; 2110 Vers_TS *vers; 2111 { 2112 char *backup; 2113 char *t_options; 2114 int status; 2115 2116 char *rev1; 2117 char *rev2; 2118 char *jrev1; 2119 char *jrev2; 2120 char *jdate1; 2121 char *jdate2; 2122 2123 jrev1 = join_rev1; 2124 jrev2 = join_rev2; 2125 jdate1 = date_rev1; 2126 jdate2 = date_rev2; 2127 2128 /* Determine if we need to do anything at all. */ 2129 if (vers->srcfile == NULL || 2130 vers->srcfile->path == NULL) 2131 { 2132 return; 2133 } 2134 2135 /* If only one join revision is specified, it becomes the second 2136 revision. */ 2137 if (jrev2 == NULL) 2138 { 2139 jrev2 = jrev1; 2140 jrev1 = NULL; 2141 jdate2 = jdate1; 2142 jdate1 = NULL; 2143 } 2144 2145 /* Convert the second revision, walking branches and dates. */ 2146 rev2 = RCS_getversion (vers->srcfile, jrev2, jdate2, 1, (int *) NULL); 2147 2148 /* If this is a merge of two revisions, get the first revision. 2149 If only one join tag was specified, then the first revision is 2150 the greatest common ancestor of the second revision and the 2151 working file. */ 2152 if (jrev1 != NULL) 2153 rev1 = RCS_getversion (vers->srcfile, jrev1, jdate1, 1, (int *) NULL); 2154 else 2155 { 2156 /* Note that we use vn_rcs here, since vn_user may contain a 2157 special string such as "-nn". */ 2158 if (vers->vn_rcs == NULL) 2159 rev1 = NULL; 2160 else if (rev2 == NULL) 2161 { 2162 /* This means that the file never existed on the branch. 2163 It does not mean that the file was removed on the 2164 branch: that case is represented by a dead rev2. If 2165 the file never existed on the branch, then we have 2166 nothing to merge, so we just return. */ 2167 return; 2168 } 2169 else 2170 rev1 = gca (vers->vn_rcs, rev2); 2171 } 2172 2173 /* Handle a nonexistent or dead merge target. */ 2174 if (rev2 == NULL || RCS_isdead (vers->srcfile, rev2)) 2175 { 2176 char *mrev; 2177 2178 if (rev2 != NULL) 2179 free (rev2); 2180 2181 /* If the first revision doesn't exist either, then there is 2182 no change between the two revisions, so we don't do 2183 anything. */ 2184 if (rev1 == NULL || RCS_isdead (vers->srcfile, rev1)) 2185 { 2186 if (rev1 != NULL) 2187 free (rev1); 2188 return; 2189 } 2190 2191 /* If we are merging two revisions, then the file was removed 2192 between the first revision and the second one. In this 2193 case we want to mark the file for removal. 2194 2195 If we are merging one revision, then the file has been 2196 removed between the greatest common ancestor and the merge 2197 revision. From the perspective of the branch on to which 2198 we ar emerging, which may be the trunk, either 1) the file 2199 does not currently exist on the target, or 2) the file has 2200 not been modified on the target branch since the greatest 2201 common ancestor, or 3) the file has been modified on the 2202 target branch since the greatest common ancestor. In case 2203 1 there is nothing to do. In case 2 we mark the file for 2204 removal. In case 3 we have a conflict. 2205 2206 Note that the handling is slightly different depending upon 2207 whether one or two join targets were specified. If two 2208 join targets were specified, we don't check whether the 2209 file was modified since a given point. My reasoning is 2210 that if you ask for an explicit merge between two tags, 2211 then you want to merge in whatever was changed between 2212 those two tags. If a file was removed between the two 2213 tags, then you want it to be removed. However, if you ask 2214 for a merge of a branch, then you want to merge in all 2215 changes which were made on the branch. If a file was 2216 removed on the branch, that is a change to the file. If 2217 the file was also changed on the main line, then that is 2218 also a change. These two changes--the file removal and the 2219 modification--must be merged. This is a conflict. */ 2220 2221 /* If the user file is dead, or does not exist, or has been 2222 marked for removal, then there is nothing to do. */ 2223 if (vers->vn_user == NULL 2224 || vers->vn_user[0] == '-' 2225 || RCS_isdead (vers->srcfile, vers->vn_user)) 2226 { 2227 if (rev1 != NULL) 2228 free (rev1); 2229 return; 2230 } 2231 2232 /* If the user file has been marked for addition, or has been 2233 locally modified, then we have a conflict which we can not 2234 resolve. No_Difference will already have been called in 2235 this case, so comparing the timestamps is sufficient to 2236 determine whether the file is locally modified. */ 2237 if (strcmp (vers->vn_user, "0") == 0 2238 || (vers->ts_user != NULL 2239 && strcmp (vers->ts_user, vers->ts_rcs) != 0)) 2240 { 2241 if (jdate2 != NULL) 2242 error (0, 0, 2243 "file %s is locally modified, but has been removed in revision %s as of %s", 2244 finfo->fullname, jrev2, jdate2); 2245 else 2246 error (0, 0, 2247 "file %s is locally modified, but has been removed in revision %s", 2248 finfo->fullname, jrev2); 2249 2250 /* FIXME: Should we arrange to return a non-zero exit 2251 status? */ 2252 2253 if (rev1 != NULL) 2254 free (rev1); 2255 2256 return; 2257 } 2258 2259 /* If only one join tag was specified, and the user file has 2260 been changed since the greatest common ancestor (rev1), 2261 then there is a conflict we can not resolve. See above for 2262 the rationale. */ 2263 if (join_rev2 == NULL 2264 && strcmp (rev1, vers->vn_user) != 0) 2265 { 2266 if (jdate2 != NULL) 2267 error (0, 0, 2268 "file %s has been modified, but has been removed in revision %s as of %s", 2269 finfo->fullname, jrev2, jdate2); 2270 else 2271 error (0, 0, 2272 "file %s has been modified, but has been removed in revision %s", 2273 finfo->fullname, jrev2); 2274 2275 /* FIXME: Should we arrange to return a non-zero exit 2276 status? */ 2277 2278 if (rev1 != NULL) 2279 free (rev1); 2280 2281 return; 2282 } 2283 2284 if (rev1 != NULL) 2285 free (rev1); 2286 2287 /* The user file exists and has not been modified. Mark it 2288 for removal. FIXME: If we are doing a checkout, this has 2289 the effect of first checking out the file, and then 2290 removing it. It would be better to just register the 2291 removal. */ 2292 #ifdef SERVER_SUPPORT 2293 if (server_active) 2294 { 2295 server_scratch (finfo->file); 2296 server_updated (finfo, vers, SERVER_UPDATED, (mode_t) -1, 2297 (unsigned char *) NULL, (struct buffer *) NULL); 2298 } 2299 #endif 2300 mrev = xmalloc (strlen (vers->vn_user) + 2); 2301 sprintf (mrev, "-%s", vers->vn_user); 2302 Register (finfo->entries, finfo->file, mrev, vers->ts_rcs, 2303 vers->options, vers->tag, vers->date, vers->ts_conflict); 2304 free (mrev); 2305 /* We need to check existence_error here because if we are 2306 running as the server, and the file is up to date in the 2307 working directory, the client will not have sent us a copy. */ 2308 if (unlink_file (finfo->file) < 0 && ! existence_error (errno)) 2309 error (0, errno, "cannot remove file %s", finfo->fullname); 2310 #ifdef SERVER_SUPPORT 2311 if (server_active) 2312 server_checked_in (finfo->file, finfo->update_dir, 2313 finfo->repository); 2314 #endif 2315 if (! really_quiet) 2316 error (0, 0, "scheduling %s for removal", finfo->fullname); 2317 2318 return; 2319 } 2320 2321 /* If the target of the merge is the same as the working file 2322 revision, then there is nothing to do. */ 2323 if (vers->vn_user != NULL && strcmp (rev2, vers->vn_user) == 0) 2324 { 2325 if (rev1 != NULL) 2326 free (rev1); 2327 free (rev2); 2328 return; 2329 } 2330 2331 /* If rev1 is dead or does not exist, then the file was added 2332 between rev1 and rev2. */ 2333 if (rev1 == NULL || RCS_isdead (vers->srcfile, rev1)) 2334 { 2335 if (rev1 != NULL) 2336 free (rev1); 2337 free (rev2); 2338 2339 /* If the file does not exist in the working directory, then 2340 we can just check out the new revision and mark it for 2341 addition. */ 2342 if (vers->vn_user == NULL) 2343 { 2344 Vers_TS *xvers; 2345 2346 xvers = Version_TS (finfo, vers->options, jrev2, jdate2, 1, 0); 2347 2348 /* Reset any keyword expansion option. Otherwise, when a 2349 command like `cvs update -kk -jT1 -jT2' creates a new file 2350 (because a file had the T2 tag, but not T1), the subsequent 2351 commit of that just-added file effectively would set the 2352 admin `-kk' option for that file in the repository. */ 2353 options = NULL; 2354 2355 /* FIXME: If checkout_file fails, we should arrange to 2356 return a non-zero exit status. */ 2357 status = checkout_file (finfo, xvers, 1, 0, 1); 2358 2359 freevers_ts (&xvers); 2360 2361 return; 2362 } 2363 2364 /* The file currently exists in the working directory, so we 2365 have a conflict which we can not resolve. Note that this 2366 is true even if the file is marked for addition or removal. */ 2367 2368 if (jdate2 != NULL) 2369 error (0, 0, 2370 "file %s exists, but has been added in revision %s as of %s", 2371 finfo->fullname, jrev2, jdate2); 2372 else 2373 error (0, 0, 2374 "file %s exists, but has been added in revision %s", 2375 finfo->fullname, jrev2); 2376 2377 return; 2378 } 2379 2380 /* If the two merge revisions are the same, then there is nothing 2381 to do. */ 2382 if (strcmp (rev1, rev2) == 0) 2383 { 2384 free (rev1); 2385 free (rev2); 2386 return; 2387 } 2388 2389 /* If there is no working file, then we can't do the merge. */ 2390 if (vers->vn_user == NULL) 2391 { 2392 free (rev1); 2393 free (rev2); 2394 2395 if (jdate2 != NULL) 2396 error (0, 0, 2397 "file %s does not exist, but is present in revision %s as of %s", 2398 finfo->fullname, jrev2, jdate2); 2399 else 2400 error (0, 0, 2401 "file %s does not exist, but is present in revision %s", 2402 finfo->fullname, jrev2); 2403 2404 /* FIXME: Should we arrange to return a non-zero exit status? */ 2405 2406 return; 2407 } 2408 2409 #ifdef SERVER_SUPPORT 2410 if (server_active && !isreadable (finfo->file)) 2411 { 2412 int retcode; 2413 /* The file is up to date. Need to check out the current contents. */ 2414 retcode = RCS_checkout (vers->srcfile, finfo->file, 2415 vers->vn_user, (char *) NULL, 2416 (char *) NULL, RUN_TTY, 2417 (RCSCHECKOUTPROC) NULL, (void *) NULL); 2418 if (retcode != 0) 2419 error (1, 0, 2420 "failed to check out %s file", finfo->fullname); 2421 } 2422 #endif 2423 2424 /* 2425 * The users currently modified file is moved to a backup file name 2426 * ".#filename.version", so that it will stay around for a few days 2427 * before being automatically removed by some cron daemon. The "version" 2428 * is the version of the file that the user was most up-to-date with 2429 * before the merge. 2430 */ 2431 backup = xmalloc (strlen (finfo->file) 2432 + strlen (vers->vn_user) 2433 + sizeof (BAKPREFIX) 2434 + 10); 2435 (void) sprintf (backup, "%s%s.%s", BAKPREFIX, finfo->file, vers->vn_user); 2436 2437 if (unlink_file (backup) < 0 2438 && !existence_error (errno)) 2439 error (0, errno, "cannot remove %s", backup); 2440 copy_file (finfo->file, backup); 2441 xchmod (finfo->file, 1); 2442 2443 t_options = vers->options; 2444 #if 0 2445 if (*t_options == '\0') 2446 t_options = "-kk"; /* to ignore keyword expansions */ 2447 #endif 2448 2449 /* If the source of the merge is the same as the working file 2450 revision, then we can just RCS_checkout the target (no merging 2451 as such). In the text file case, this is probably quite 2452 similar to the RCS_merge, but in the binary file case, 2453 RCS_merge gives all kinds of trouble. */ 2454 if (vers->vn_user != NULL 2455 && strcmp (rev1, vers->vn_user) == 0 2456 /* See comments above about how No_Difference has already been 2457 called. */ 2458 && vers->ts_user != NULL 2459 && strcmp (vers->ts_user, vers->ts_rcs) == 0 2460 2461 /* This is because of the worry below about $Name. If that 2462 isn't a problem, I suspect this code probably works for 2463 text files too. */ 2464 && (strcmp (t_options, "-kb") == 0 2465 || wrap_merge_is_copy (finfo->file))) 2466 { 2467 /* FIXME: what about nametag? What does RCS_merge do with 2468 $Name? */ 2469 if (RCS_checkout (finfo->rcs, finfo->file, rev2, NULL, t_options, 2470 RUN_TTY, (RCSCHECKOUTPROC)0, NULL) != 0) 2471 status = 2; 2472 else 2473 status = 0; 2474 2475 /* OK, this is really stupid. RCS_checkout carefully removes 2476 write permissions, and we carefully put them back. But 2477 until someone gets around to fixing it, that seems like the 2478 easiest way to get what would seem to be the right mode. 2479 I don't check CVSWRITE or _watched; I haven't thought about 2480 that in great detail, but it seems like a watched file should 2481 be checked out (writable) after a merge. */ 2482 xchmod (finfo->file, 1); 2483 2484 /* Traditionally, the text file case prints a whole bunch of 2485 scary looking and verbose output which fails to tell the user 2486 what is really going on (it gives them rev1 and rev2 but doesn't 2487 indicate in any way that rev1 == vn_user). I think just a 2488 simple "U foo" is good here; it seems analogous to the case in 2489 which the file was added on the branch in terms of what to 2490 print. */ 2491 write_letter (finfo, 'U'); 2492 } 2493 else if (strcmp (t_options, "-kb") == 0 2494 || wrap_merge_is_copy (finfo->file) 2495 || special_file_mismatch (finfo, rev1, rev2)) 2496 { 2497 /* We are dealing with binary files, or files with a 2498 permission/linkage mismatch, and real merging would 2499 need to take place. This is a conflict. We give the user 2500 the two files, and let them resolve it. It is possible 2501 that we should require a "touch foo" or similar step before 2502 we allow a checkin. */ 2503 if (RCS_checkout (finfo->rcs, finfo->file, rev2, NULL, t_options, 2504 RUN_TTY, (RCSCHECKOUTPROC)0, NULL) != 0) 2505 status = 2; 2506 else 2507 status = 0; 2508 2509 /* OK, this is really stupid. RCS_checkout carefully removes 2510 write permissions, and we carefully put them back. But 2511 until someone gets around to fixing it, that seems like the 2512 easiest way to get what would seem to be the right mode. 2513 I don't check CVSWRITE or _watched; I haven't thought about 2514 that in great detail, but it seems like a watched file should 2515 be checked out (writable) after a merge. */ 2516 xchmod (finfo->file, 1); 2517 2518 /* Hmm. We don't give them REV1 anywhere. I guess most people 2519 probably don't have a 3-way merge tool for the file type in 2520 question, and might just get confused if we tried to either 2521 provide them with a copy of the file from REV1, or even just 2522 told them what REV1 is so they can get it themself, but it 2523 might be worth thinking about. */ 2524 /* See comment in merge_file about the "nonmergeable file" 2525 terminology. */ 2526 error (0, 0, "nonmergeable file needs merge"); 2527 error (0, 0, "revision %s from repository is now in %s", 2528 rev2, finfo->fullname); 2529 error (0, 0, "file from working directory is now in %s", backup); 2530 write_letter (finfo, 'C'); 2531 } 2532 else 2533 status = RCS_merge (finfo->rcs, vers->srcfile->path, finfo->file, 2534 t_options, rev1, rev2); 2535 2536 if (status != 0 && status != 1) 2537 { 2538 error (0, status == -1 ? errno : 0, 2539 "could not merge revision %s of %s", rev2, finfo->fullname); 2540 error (status == -1 ? 1 : 0, 0, "restoring %s from backup file %s", 2541 finfo->fullname, backup); 2542 rename_file (backup, finfo->file); 2543 } 2544 free (rev1); 2545 free (rev2); 2546 2547 /* The file has changed, but if we just checked it out it may 2548 still have the same timestamp it did when it was first 2549 registered above in checkout_file. We register it again with a 2550 dummy timestamp to make sure that later runs of CVS will 2551 recognize that it has changed. 2552 2553 We don't actually need to register again if we called 2554 RCS_checkout above, and we aren't running as the server. 2555 However, that is not the normal case, and calling Register 2556 again won't cost much in that case. */ 2557 { 2558 char *cp = 0; 2559 2560 if (status) 2561 { 2562 (void) time (&last_register_time); 2563 cp = time_stamp (finfo->file); 2564 } 2565 Register (finfo->entries, finfo->file, 2566 vers->vn_rcs ? vers->vn_rcs : "0", "Result of merge", 2567 vers->options, vers->tag, vers->date, cp); 2568 if (cp) 2569 free(cp); 2570 } 2571 2572 #ifdef SERVER_SUPPORT 2573 if (server_active) 2574 { 2575 server_copy_file (finfo->file, finfo->update_dir, finfo->repository, 2576 backup); 2577 server_updated (finfo, vers, SERVER_MERGED, 2578 (mode_t) -1, (unsigned char *) NULL, 2579 (struct buffer *) NULL); 2580 } 2581 #endif 2582 free (backup); 2583 } 2584 2585 /* 2586 * Report whether revisions REV1 and REV2 of FINFO agree on: 2587 * . file ownership 2588 * . permissions 2589 * . major and minor device numbers 2590 * . symbolic links 2591 * . hard links 2592 * 2593 * If either REV1 or REV2 is NULL, the working copy is used instead. 2594 * 2595 * Return 1 if the files differ on these data. 2596 */ 2597 2598 int 2599 special_file_mismatch (finfo, rev1, rev2) 2600 struct file_info *finfo; 2601 char *rev1; 2602 char *rev2; 2603 { 2604 #ifdef PRESERVE_PERMISSIONS_SUPPORT 2605 struct stat sb; 2606 RCSVers *vp; 2607 Node *n; 2608 uid_t rev1_uid, rev2_uid; 2609 gid_t rev1_gid, rev2_gid; 2610 mode_t rev1_mode, rev2_mode; 2611 unsigned long dev_long; 2612 dev_t rev1_dev, rev2_dev; 2613 char *rev1_symlink = NULL; 2614 char *rev2_symlink = NULL; 2615 List *rev1_hardlinks = NULL; 2616 List *rev2_hardlinks = NULL; 2617 int check_uids, check_gids, check_modes; 2618 int result; 2619 2620 /* If we don't care about special file info, then 2621 don't report a mismatch in any case. */ 2622 if (!preserve_perms) 2623 return 0; 2624 2625 /* When special_file_mismatch is called from No_Difference, the 2626 RCS file has been only partially parsed. We must read the 2627 delta tree in order to compare special file info recorded in 2628 the delta nodes. (I think this is safe. -twp) */ 2629 if (finfo->rcs->flags & PARTIAL) 2630 RCS_reparsercsfile (finfo->rcs, NULL, NULL); 2631 2632 check_uids = check_gids = check_modes = 1; 2633 2634 /* Obtain file information for REV1. If this is null, then stat 2635 finfo->file and use that info. */ 2636 /* If a revision does not know anything about its status, 2637 then presumably it doesn't matter, and indicates no conflict. */ 2638 2639 if (rev1 == NULL) 2640 { 2641 if (islink (finfo->file)) 2642 rev1_symlink = xreadlink (finfo->file); 2643 else 2644 { 2645 #ifdef HAVE_ST_RDEV 2646 if (CVS_LSTAT (finfo->file, &sb) < 0) 2647 error (1, errno, "could not get file information for %s", 2648 finfo->file); 2649 rev1_uid = sb.st_uid; 2650 rev1_gid = sb.st_gid; 2651 rev1_mode = sb.st_mode; 2652 if (S_ISBLK (rev1_mode) || S_ISCHR (rev1_mode)) 2653 rev1_dev = sb.st_rdev; 2654 #else 2655 error (1, 0, "cannot handle device files on this system (%s)", 2656 finfo->file); 2657 #endif 2658 } 2659 rev1_hardlinks = list_linked_files_on_disk (finfo->file); 2660 } 2661 else 2662 { 2663 n = findnode (finfo->rcs->versions, rev1); 2664 vp = (RCSVers *) n->data; 2665 2666 n = findnode (vp->other_delta, "symlink"); 2667 if (n != NULL) 2668 rev1_symlink = xstrdup (n->data); 2669 else 2670 { 2671 n = findnode (vp->other_delta, "owner"); 2672 if (n == NULL) 2673 check_uids = 0; /* don't care */ 2674 else 2675 rev1_uid = strtoul (n->data, NULL, 10); 2676 2677 n = findnode (vp->other_delta, "group"); 2678 if (n == NULL) 2679 check_gids = 0; /* don't care */ 2680 else 2681 rev1_gid = strtoul (n->data, NULL, 10); 2682 2683 n = findnode (vp->other_delta, "permissions"); 2684 if (n == NULL) 2685 check_modes = 0; /* don't care */ 2686 else 2687 rev1_mode = strtoul (n->data, NULL, 8); 2688 2689 n = findnode (vp->other_delta, "special"); 2690 if (n == NULL) 2691 rev1_mode |= S_IFREG; 2692 else 2693 { 2694 /* If the size of `ftype' changes, fix the sscanf call also */ 2695 char ftype[16+1]; 2696 if (sscanf (n->data, "%16s %lu", ftype, 2697 &dev_long) < 2) 2698 error (1, 0, "%s:%s has bad `special' newphrase %s", 2699 finfo->file, rev1, n->data); 2700 rev1_dev = dev_long; 2701 if (strcmp (ftype, "character") == 0) 2702 rev1_mode |= S_IFCHR; 2703 else if (strcmp (ftype, "block") == 0) 2704 rev1_mode |= S_IFBLK; 2705 else 2706 error (0, 0, "%s:%s unknown file type `%s'", 2707 finfo->file, rev1, ftype); 2708 } 2709 2710 rev1_hardlinks = vp->hardlinks; 2711 if (rev1_hardlinks == NULL) 2712 rev1_hardlinks = getlist(); 2713 } 2714 } 2715 2716 /* Obtain file information for REV2. */ 2717 if (rev2 == NULL) 2718 { 2719 if (islink (finfo->file)) 2720 rev2_symlink = xreadlink (finfo->file); 2721 else 2722 { 2723 #ifdef HAVE_ST_RDEV 2724 if (CVS_LSTAT (finfo->file, &sb) < 0) 2725 error (1, errno, "could not get file information for %s", 2726 finfo->file); 2727 rev2_uid = sb.st_uid; 2728 rev2_gid = sb.st_gid; 2729 rev2_mode = sb.st_mode; 2730 if (S_ISBLK (rev2_mode) || S_ISCHR (rev2_mode)) 2731 rev2_dev = sb.st_rdev; 2732 #else 2733 error (1, 0, "cannot handle device files on this system (%s)", 2734 finfo->file); 2735 #endif 2736 } 2737 rev2_hardlinks = list_linked_files_on_disk (finfo->file); 2738 } 2739 else 2740 { 2741 n = findnode (finfo->rcs->versions, rev2); 2742 vp = (RCSVers *) n->data; 2743 2744 n = findnode (vp->other_delta, "symlink"); 2745 if (n != NULL) 2746 rev2_symlink = xstrdup (n->data); 2747 else 2748 { 2749 n = findnode (vp->other_delta, "owner"); 2750 if (n == NULL) 2751 check_uids = 0; /* don't care */ 2752 else 2753 rev2_uid = strtoul (n->data, NULL, 10); 2754 2755 n = findnode (vp->other_delta, "group"); 2756 if (n == NULL) 2757 check_gids = 0; /* don't care */ 2758 else 2759 rev2_gid = strtoul (n->data, NULL, 10); 2760 2761 n = findnode (vp->other_delta, "permissions"); 2762 if (n == NULL) 2763 check_modes = 0; /* don't care */ 2764 else 2765 rev2_mode = strtoul (n->data, NULL, 8); 2766 2767 n = findnode (vp->other_delta, "special"); 2768 if (n == NULL) 2769 rev2_mode |= S_IFREG; 2770 else 2771 { 2772 /* If the size of `ftype' changes, fix the sscanf call also */ 2773 char ftype[16+1]; 2774 if (sscanf (n->data, "%16s %lu", ftype, 2775 &dev_long) < 2) 2776 error (1, 0, "%s:%s has bad `special' newphrase %s", 2777 finfo->file, rev2, n->data); 2778 rev2_dev = dev_long; 2779 if (strcmp (ftype, "character") == 0) 2780 rev2_mode |= S_IFCHR; 2781 else if (strcmp (ftype, "block") == 0) 2782 rev2_mode |= S_IFBLK; 2783 else 2784 error (0, 0, "%s:%s unknown file type `%s'", 2785 finfo->file, rev2, ftype); 2786 } 2787 2788 rev2_hardlinks = vp->hardlinks; 2789 if (rev2_hardlinks == NULL) 2790 rev2_hardlinks = getlist(); 2791 } 2792 } 2793 2794 /* Check the user/group ownerships and file permissions, printing 2795 an error for each mismatch found. Return 0 if all characteristics 2796 matched, and 1 otherwise. */ 2797 2798 result = 0; 2799 2800 /* Compare symlinks first, since symlinks are simpler (don't have 2801 any other characteristics). */ 2802 if (rev1_symlink != NULL && rev2_symlink == NULL) 2803 { 2804 error (0, 0, "%s is a symbolic link", 2805 (rev1 == NULL ? "working file" : rev1)); 2806 result = 1; 2807 } 2808 else if (rev1_symlink == NULL && rev2_symlink != NULL) 2809 { 2810 error (0, 0, "%s is a symbolic link", 2811 (rev2 == NULL ? "working file" : rev2)); 2812 result = 1; 2813 } 2814 else if (rev1_symlink != NULL) 2815 result = (strcmp (rev1_symlink, rev2_symlink) == 0); 2816 else 2817 { 2818 /* Compare user ownership. */ 2819 if (check_uids && rev1_uid != rev2_uid) 2820 { 2821 error (0, 0, "%s: owner mismatch between %s and %s", 2822 finfo->file, 2823 (rev1 == NULL ? "working file" : rev1), 2824 (rev2 == NULL ? "working file" : rev2)); 2825 result = 1; 2826 } 2827 2828 /* Compare group ownership. */ 2829 if (check_gids && rev1_gid != rev2_gid) 2830 { 2831 error (0, 0, "%s: group mismatch between %s and %s", 2832 finfo->file, 2833 (rev1 == NULL ? "working file" : rev1), 2834 (rev2 == NULL ? "working file" : rev2)); 2835 result = 1; 2836 } 2837 2838 /* Compare permissions. */ 2839 if (check_modes && 2840 (rev1_mode & 07777) != (rev2_mode & 07777)) 2841 { 2842 error (0, 0, "%s: permission mismatch between %s and %s", 2843 finfo->file, 2844 (rev1 == NULL ? "working file" : rev1), 2845 (rev2 == NULL ? "working file" : rev2)); 2846 result = 1; 2847 } 2848 2849 /* Compare device file characteristics. */ 2850 if ((rev1_mode & S_IFMT) != (rev2_mode & S_IFMT)) 2851 { 2852 error (0, 0, "%s: %s and %s are different file types", 2853 finfo->file, 2854 (rev1 == NULL ? "working file" : rev1), 2855 (rev2 == NULL ? "working file" : rev2)); 2856 result = 1; 2857 } 2858 else if (S_ISBLK (rev1_mode)) 2859 { 2860 if (rev1_dev != rev2_dev) 2861 { 2862 error (0, 0, "%s: device numbers of %s and %s do not match", 2863 finfo->file, 2864 (rev1 == NULL ? "working file" : rev1), 2865 (rev2 == NULL ? "working file" : rev2)); 2866 result = 1; 2867 } 2868 } 2869 2870 /* Compare hard links. */ 2871 if (compare_linkage_lists (rev1_hardlinks, rev2_hardlinks) == 0) 2872 { 2873 error (0, 0, "%s: hard linkage of %s and %s do not match", 2874 finfo->file, 2875 (rev1 == NULL ? "working file" : rev1), 2876 (rev2 == NULL ? "working file" : rev2)); 2877 result = 1; 2878 } 2879 } 2880 2881 if (rev1_symlink != NULL) 2882 free (rev1_symlink); 2883 if (rev2_symlink != NULL) 2884 free (rev2_symlink); 2885 if (rev1_hardlinks != NULL) 2886 dellist (&rev1_hardlinks); 2887 if (rev2_hardlinks != NULL) 2888 dellist (&rev2_hardlinks); 2889 2890 return result; 2891 #else 2892 return 0; 2893 #endif 2894 } 2895 2896 int 2897 joining () 2898 { 2899 return (join_rev1 != NULL); 2900 } 2901