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