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