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