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 * Patch 9 * 10 * Create a Larry Wall format "patch" file between a previous release and the 11 * current head of a module, or between two releases. Can specify the 12 * release as either a date or a revision number. 13 */ 14 15 #include <assert.h> 16 #include "cvs.h" 17 #include "getline.h" 18 19 static RETSIGTYPE patch_cleanup PROTO((void)); 20 static Dtype patch_dirproc PROTO ((void *callerdat, char *dir, 21 char *repos, char *update_dir, 22 List *entries)); 23 static int patch_fileproc PROTO ((void *callerdat, struct file_info *finfo)); 24 static int patch_proc PROTO((int argc, char **argv, char *xwhere, 25 char *mwhere, char *mfile, int shorten, 26 int local_specified, char *mname, char *msg)); 27 28 static int force_tag_match = 1; 29 static int patch_short = 0; 30 static int toptwo_diffs = 0; 31 static int local = 0; 32 static char *options = NULL; 33 static char *rev1 = NULL; 34 static int rev1_validated = 0; 35 static char *rev2 = NULL; 36 static int rev2_validated = 0; 37 static char *date1 = NULL; 38 static char *date2 = NULL; 39 static char *tmpfile1 = NULL; 40 static char *tmpfile2 = NULL; 41 static char *tmpfile3 = NULL; 42 static int unidiff = 0; 43 44 static const char *const patch_usage[] = 45 { 46 "Usage: %s %s [-flR] [-c|-u] [-s|-t] [-V %%d]\n", 47 " -r rev|-D date [-r rev2 | -D date2] modules...\n", 48 "\t-f\tForce a head revision match if tag/date not found.\n", 49 "\t-l\tLocal directory only, not recursive\n", 50 "\t-R\tProcess directories recursively.\n", 51 "\t-c\tContext diffs (default)\n", 52 "\t-u\tUnidiff format.\n", 53 "\t-s\tShort patch - one liner per file.\n", 54 "\t-t\tTop two diffs - last change made to the file.\n", 55 "\t-D date\tDate.\n", 56 "\t-r rev\tRevision - symbolic or numeric.\n", 57 "\t-V vers\tUse RCS Version \"vers\" for keyword expansion.\n", 58 "(Specify the --help global option for a list of other help options)\n", 59 NULL 60 }; 61 62 int 63 patch (argc, argv) 64 int argc; 65 char **argv; 66 { 67 register int i; 68 int c; 69 int err = 0; 70 DBM *db; 71 72 if (argc == -1) 73 usage (patch_usage); 74 75 optind = 0; 76 while ((c = getopt (argc, argv, "+V:k:cuftsQqlRD:r:")) != -1) 77 { 78 switch (c) 79 { 80 case 'Q': 81 case 'q': 82 #ifdef SERVER_SUPPORT 83 /* The CVS 1.5 client sends these options (in addition to 84 Global_option requests), so we must ignore them. */ 85 if (!server_active) 86 #endif 87 error (1, 0, 88 "-q or -Q must be specified before \"%s\"", 89 command_name); 90 break; 91 case 'f': 92 force_tag_match = 0; 93 break; 94 case 'l': 95 local = 1; 96 break; 97 case 'R': 98 local = 0; 99 break; 100 case 't': 101 toptwo_diffs = 1; 102 break; 103 case 's': 104 patch_short = 1; 105 break; 106 case 'D': 107 if (rev2 != NULL || date2 != NULL) 108 error (1, 0, 109 "no more than two revisions/dates can be specified"); 110 if (rev1 != NULL || date1 != NULL) 111 date2 = Make_Date (optarg); 112 else 113 date1 = Make_Date (optarg); 114 break; 115 case 'r': 116 if (rev2 != NULL || date2 != NULL) 117 error (1, 0, 118 "no more than two revisions/dates can be specified"); 119 if (rev1 != NULL || date1 != NULL) 120 rev2 = optarg; 121 else 122 rev1 = optarg; 123 break; 124 case 'k': 125 if (options) 126 free (options); 127 options = RCS_check_kflag (optarg); 128 break; 129 case 'V': 130 /* This option is pretty seriously broken: 131 1. It is not clear what it does (does it change keyword 132 expansion behavior? If so, how? Or does it have 133 something to do with what version of RCS we are using? 134 Or the format we write RCS files in?). 135 2. Because both it and -k use the options variable, 136 specifying both -V and -k doesn't work. 137 3. At least as of CVS 1.9, it doesn't work (failed 138 assertion in RCS_checkout where it asserts that options 139 starts with -k). Few people seem to be complaining. 140 In the future (perhaps the near future), I have in mind 141 removing it entirely, and updating NEWS and cvs.texinfo, 142 but in case it is a good idea to give people more time 143 to complain if they would miss it, I'll just add this 144 quick and dirty error message for now. */ 145 error (1, 0, 146 "the -V option is obsolete and should not be used"); 147 #if 0 148 if (atoi (optarg) <= 0) 149 error (1, 0, "must specify a version number to -V"); 150 if (options) 151 free (options); 152 options = xmalloc (strlen (optarg) + 1 + 2); /* for the -V */ 153 (void) sprintf (options, "-V%s", optarg); 154 #endif 155 break; 156 case 'u': 157 unidiff = 1; /* Unidiff */ 158 break; 159 case 'c': /* Context diff */ 160 unidiff = 0; 161 break; 162 case '?': 163 default: 164 usage (patch_usage); 165 break; 166 } 167 } 168 argc -= optind; 169 argv += optind; 170 171 /* Sanity checks */ 172 if (argc < 1) 173 usage (patch_usage); 174 175 if (toptwo_diffs && patch_short) 176 error (1, 0, "-t and -s options are mutually exclusive"); 177 if (toptwo_diffs && (date1 != NULL || date2 != NULL || 178 rev1 != NULL || rev2 != NULL)) 179 error (1, 0, "must not specify revisions/dates with -t option!"); 180 181 if (!toptwo_diffs && (date1 == NULL && date2 == NULL && 182 rev1 == NULL && rev2 == NULL)) 183 error (1, 0, "must specify at least one revision/date!"); 184 if (date1 != NULL && date2 != NULL) 185 if (RCS_datecmp (date1, date2) >= 0) 186 error (1, 0, "second date must come after first date!"); 187 188 /* if options is NULL, make it a NULL string */ 189 if (options == NULL) 190 options = xstrdup (""); 191 192 #ifdef CLIENT_SUPPORT 193 if (current_parsed_root->isremote) 194 { 195 /* We're the client side. Fire up the remote server. */ 196 start_server (); 197 198 ign_setup (); 199 200 if (local) 201 send_arg("-l"); 202 if (!force_tag_match) 203 send_arg("-f"); 204 if (toptwo_diffs) 205 send_arg("-t"); 206 if (patch_short) 207 send_arg("-s"); 208 if (unidiff) 209 send_arg("-u"); 210 211 if (rev1) 212 option_with_arg ("-r", rev1); 213 if (date1) 214 client_senddate (date1); 215 if (rev2) 216 option_with_arg ("-r", rev2); 217 if (date2) 218 client_senddate (date2); 219 if (options[0] != '\0') 220 send_arg (options); 221 222 { 223 int i; 224 for (i = 0; i < argc; ++i) 225 send_arg (argv[i]); 226 } 227 228 send_to_server ("rdiff\012", 0); 229 return get_responses_and_close (); 230 } 231 #endif 232 233 /* clean up if we get a signal */ 234 #ifdef SIGABRT 235 (void) SIG_register (SIGABRT, patch_cleanup); 236 #endif 237 #ifdef SIGHUP 238 (void) SIG_register (SIGHUP, patch_cleanup); 239 #endif 240 #ifdef SIGINT 241 (void) SIG_register (SIGINT, patch_cleanup); 242 #endif 243 #ifdef SIGQUIT 244 (void) SIG_register (SIGQUIT, patch_cleanup); 245 #endif 246 #ifdef SIGPIPE 247 (void) SIG_register (SIGPIPE, patch_cleanup); 248 #endif 249 #ifdef SIGTERM 250 (void) SIG_register (SIGTERM, patch_cleanup); 251 #endif 252 253 db = open_module (); 254 for (i = 0; i < argc; i++) 255 err += do_module (db, argv[i], PATCH, "Patching", patch_proc, 256 (char *) NULL, 0, 0, 0, 0, (char *) NULL); 257 close_module (db); 258 free (options); 259 patch_cleanup (); 260 return (err); 261 } 262 263 /* 264 * callback proc for doing the real work of patching 265 */ 266 /* ARGSUSED */ 267 static int 268 patch_proc (argc, argv, xwhere, mwhere, mfile, shorten, local_specified, 269 mname, msg) 270 int argc; 271 char **argv; 272 char *xwhere; 273 char *mwhere; 274 char *mfile; 275 int shorten; 276 int local_specified; 277 char *mname; 278 char *msg; 279 { 280 char *myargv[2]; 281 int err = 0; 282 int which; 283 char *repository; 284 char *where; 285 286 repository = xmalloc (strlen (current_parsed_root->directory) + strlen (argv[0]) 287 + (mfile == NULL ? 0 : strlen (mfile) + 1) + 2); 288 (void) sprintf (repository, "%s/%s", current_parsed_root->directory, argv[0]); 289 where = xmalloc (strlen (argv[0]) + (mfile == NULL ? 0 : strlen (mfile) + 1) 290 + 1); 291 (void) strcpy (where, argv[0]); 292 293 /* if mfile isn't null, we need to set up to do only part of the module */ 294 if (mfile != NULL) 295 { 296 char *cp; 297 char *path; 298 299 /* if the portion of the module is a path, put the dir part on repos */ 300 if ((cp = strrchr (mfile, '/')) != NULL) 301 { 302 *cp = '\0'; 303 (void) strcat (repository, "/"); 304 (void) strcat (repository, mfile); 305 (void) strcat (where, "/"); 306 (void) strcat (where, mfile); 307 mfile = cp + 1; 308 } 309 310 /* take care of the rest */ 311 path = xmalloc (strlen (repository) + strlen (mfile) + 2); 312 (void) sprintf (path, "%s/%s", repository, mfile); 313 if (isdir (path)) 314 { 315 /* directory means repository gets the dir tacked on */ 316 (void) strcpy (repository, path); 317 (void) strcat (where, "/"); 318 (void) strcat (where, mfile); 319 } 320 else 321 { 322 myargv[0] = argv[0]; 323 myargv[1] = mfile; 324 argc = 2; 325 argv = myargv; 326 } 327 free (path); 328 } 329 330 /* cd to the starting repository */ 331 if ( CVS_CHDIR (repository) < 0) 332 { 333 error (0, errno, "cannot chdir to %s", repository); 334 free (repository); 335 return (1); 336 } 337 free (repository); 338 339 if (force_tag_match) 340 which = W_REPOS | W_ATTIC; 341 else 342 which = W_REPOS; 343 344 if (rev1 != NULL && !rev1_validated) 345 { 346 tag_check_valid (rev1, argc - 1, argv + 1, local, 0, NULL); 347 rev1_validated = 1; 348 } 349 if (rev2 != NULL && !rev2_validated) 350 { 351 tag_check_valid (rev2, argc - 1, argv + 1, local, 0, NULL); 352 rev2_validated = 1; 353 } 354 355 /* start the recursion processor */ 356 err = start_recursion (patch_fileproc, (FILESDONEPROC) NULL, patch_dirproc, 357 (DIRLEAVEPROC) NULL, NULL, 358 argc - 1, argv + 1, local, 359 which, 0, 1, where, 1); 360 free (where); 361 362 return (err); 363 } 364 365 /* 366 * Called to examine a particular RCS file, as appropriate with the options 367 * that were set above. 368 */ 369 /* ARGSUSED */ 370 static int 371 patch_fileproc (callerdat, finfo) 372 void *callerdat; 373 struct file_info *finfo; 374 { 375 struct utimbuf t; 376 char *vers_tag, *vers_head; 377 char *rcs = NULL; 378 RCSNode *rcsfile; 379 FILE *fp1, *fp2, *fp3; 380 int ret = 0; 381 int isattic = 0; 382 int retcode = 0; 383 char *file1; 384 char *file2; 385 char *strippath; 386 char *line1, *line2; 387 size_t line1_chars_allocated; 388 size_t line2_chars_allocated; 389 char *cp1, *cp2; 390 FILE *fp; 391 int line_length; 392 393 line1 = NULL; 394 line1_chars_allocated = 0; 395 line2 = NULL; 396 line2_chars_allocated = 0; 397 398 /* find the parsed rcs file */ 399 if ((rcsfile = finfo->rcs) == NULL) 400 { 401 ret = 1; 402 goto out2; 403 } 404 if ((rcsfile->flags & VALID) && (rcsfile->flags & INATTIC)) 405 isattic = 1; 406 407 rcs = xmalloc (strlen (finfo->file) + sizeof (RCSEXT) + 5); 408 (void) sprintf (rcs, "%s%s", finfo->file, RCSEXT); 409 410 /* if vers_head is NULL, may have been removed from the release */ 411 if (isattic && rev2 == NULL && date2 == NULL) 412 vers_head = NULL; 413 else 414 { 415 vers_head = RCS_getversion (rcsfile, rev2, date2, force_tag_match, 416 (int *) NULL); 417 if (vers_head != NULL && RCS_isdead (rcsfile, vers_head)) 418 { 419 free (vers_head); 420 vers_head = NULL; 421 } 422 } 423 424 if (toptwo_diffs) 425 { 426 if (vers_head == NULL) 427 { 428 ret = 1; 429 goto out2; 430 } 431 432 if (!date1) 433 date1 = xmalloc (MAXDATELEN); 434 *date1 = '\0'; 435 if (RCS_getrevtime (rcsfile, vers_head, date1, 1) == -1) 436 { 437 if (!really_quiet) 438 error (0, 0, "cannot find date in rcs file %s revision %s", 439 rcs, vers_head); 440 ret = 1; 441 goto out2; 442 } 443 } 444 vers_tag = RCS_getversion (rcsfile, rev1, date1, force_tag_match, 445 (int *) NULL); 446 if (vers_tag != NULL && RCS_isdead (rcsfile, vers_tag)) 447 { 448 free (vers_tag); 449 vers_tag = NULL; 450 } 451 452 if (vers_tag == NULL && vers_head == NULL) 453 { 454 /* Nothing known about specified revs. */ 455 ret = 0; 456 goto out2; 457 } 458 459 if (vers_tag && vers_head && strcmp (vers_head, vers_tag) == 0) 460 { 461 /* Not changed between releases. */ 462 ret = 0; 463 goto out2; 464 } 465 466 if (patch_short) 467 { 468 cvs_output ("File ", 0); 469 cvs_output (finfo->fullname, 0); 470 if (vers_tag == NULL) 471 { 472 cvs_output (" is new; current revision ", 0); 473 cvs_output (vers_head, 0); 474 cvs_output ("\n", 1); 475 } 476 else if (vers_head == NULL) 477 { 478 cvs_output (" is removed; not included in ", 0); 479 if (rev2 != NULL) 480 { 481 cvs_output ("release tag ", 0); 482 cvs_output (rev2, 0); 483 } 484 else if (date2 != NULL) 485 { 486 cvs_output ("release date ", 0); 487 cvs_output (date2, 0); 488 } 489 else 490 cvs_output ("current release", 0); 491 cvs_output ("\n", 1); 492 } 493 else 494 { 495 cvs_output (" changed from revision ", 0); 496 cvs_output (vers_tag, 0); 497 cvs_output (" to ", 0); 498 cvs_output (vers_head, 0); 499 cvs_output ("\n", 1); 500 } 501 ret = 0; 502 goto out2; 503 } 504 505 /* Create 3 empty files. I'm not really sure there is any advantage 506 * to doing so now rather than just waiting until later. 507 * 508 * There is - cvs_temp_file opens the file so that it can guarantee that 509 * we have exclusive write access to the file. Unfortunately we spoil that 510 * by closing it and reopening it again. Of course any better solution 511 * requires that the RCS functions accept open file pointers rather than 512 * simple file names. 513 */ 514 if ((fp1 = cvs_temp_file (&tmpfile1)) == NULL) 515 { 516 error (0, errno, "cannot create temporary file %s", tmpfile1); 517 ret = 1; 518 goto out; 519 } 520 else 521 if (fclose (fp1) < 0) 522 error (0, errno, "warning: cannot close %s", tmpfile1); 523 if ((fp2 = cvs_temp_file (&tmpfile2)) == NULL) 524 { 525 error (0, errno, "cannot create temporary file %s", tmpfile2); 526 ret = 1; 527 goto out; 528 } 529 else 530 if (fclose (fp2) < 0) 531 error (0, errno, "warning: cannot close %s", tmpfile2); 532 if ((fp3 = cvs_temp_file (&tmpfile3)) == NULL) 533 { 534 error (0, errno, "cannot create temporary file %s", tmpfile3); 535 ret = 1; 536 goto out; 537 } 538 else 539 if (fclose (fp3) < 0) 540 error (0, errno, "warning: cannot close %s", tmpfile3); 541 542 if (vers_tag != NULL) 543 { 544 retcode = RCS_checkout (rcsfile, (char *) NULL, vers_tag, 545 rev1, options, tmpfile1, 546 (RCSCHECKOUTPROC) NULL, (void *) NULL); 547 if (retcode != 0) 548 { 549 error (0, 0, 550 "cannot check out revision %s of %s", vers_tag, rcs); 551 ret = 1; 552 goto out; 553 } 554 memset ((char *) &t, 0, sizeof (t)); 555 if ((t.actime = t.modtime = RCS_getrevtime (rcsfile, vers_tag, 556 (char *) 0, 0)) != -1) 557 /* I believe this timestamp only affects the dates in our diffs, 558 and therefore should be on the server, not the client. */ 559 (void) utime (tmpfile1, &t); 560 } 561 else if (toptwo_diffs) 562 { 563 ret = 1; 564 goto out; 565 } 566 if (vers_head != NULL) 567 { 568 retcode = RCS_checkout (rcsfile, (char *) NULL, vers_head, 569 rev2, options, tmpfile2, 570 (RCSCHECKOUTPROC) NULL, (void *) NULL); 571 if (retcode != 0) 572 { 573 error (0, 0, 574 "cannot check out revision %s of %s", vers_head, rcs); 575 ret = 1; 576 goto out; 577 } 578 if ((t.actime = t.modtime = RCS_getrevtime (rcsfile, vers_head, 579 (char *) 0, 0)) != -1) 580 /* I believe this timestamp only affects the dates in our diffs, 581 and therefore should be on the server, not the client. */ 582 (void) utime (tmpfile2, &t); 583 } 584 585 switch (diff_exec (tmpfile1, tmpfile2, NULL, NULL, unidiff ? "-u" : "-c", tmpfile3)) 586 { 587 case -1: /* fork/wait failure */ 588 error (1, errno, "fork for diff failed on %s", rcs); 589 break; 590 case 0: /* nothing to do */ 591 break; 592 case 1: 593 /* 594 * The two revisions are really different, so read the first two 595 * lines of the diff output file, and munge them to include more 596 * reasonable file names that "patch" will understand. 597 */ 598 599 /* Output an "Index:" line for patch to use */ 600 cvs_output ("Index: ", 0); 601 cvs_output (finfo->fullname, 0); 602 cvs_output ("\n", 1); 603 604 fp = open_file (tmpfile3, "r"); 605 if (getline (&line1, &line1_chars_allocated, fp) < 0 || 606 getline (&line2, &line2_chars_allocated, fp) < 0) 607 { 608 if (feof (fp)) 609 error (0, 0, "\ 610 failed to read diff file header %s for %s: end of file", tmpfile3, rcs); 611 else 612 error (0, errno, 613 "failed to read diff file header %s for %s", 614 tmpfile3, rcs); 615 ret = 1; 616 if (fclose (fp) < 0) 617 error (0, errno, "error closing %s", tmpfile3); 618 goto out; 619 } 620 if (!unidiff) 621 { 622 if (strncmp (line1, "*** ", 4) != 0 || 623 strncmp (line2, "--- ", 4) != 0 || 624 (cp1 = strchr (line1, '\t')) == NULL || 625 (cp2 = strchr (line2, '\t')) == NULL) 626 { 627 error (0, 0, "invalid diff header for %s", rcs); 628 ret = 1; 629 if (fclose (fp) < 0) 630 error (0, errno, "error closing %s", tmpfile3); 631 goto out; 632 } 633 } 634 else 635 { 636 if (strncmp (line1, "--- ", 4) != 0 || 637 strncmp (line2, "+++ ", 4) != 0 || 638 (cp1 = strchr (line1, '\t')) == NULL || 639 (cp2 = strchr (line2, '\t')) == NULL) 640 { 641 error (0, 0, "invalid unidiff header for %s", rcs); 642 ret = 1; 643 if (fclose (fp) < 0) 644 error (0, errno, "error closing %s", tmpfile3); 645 goto out; 646 } 647 } 648 assert (current_parsed_root != NULL); 649 assert (current_parsed_root->directory != NULL); 650 { 651 strippath = xmalloc (strlen (current_parsed_root->directory) + 2); 652 (void) sprintf (strippath, "%s/", current_parsed_root->directory); 653 } 654 /*else 655 strippath = xstrdup (REPOS_STRIP); */ 656 if (strncmp (rcs, strippath, strlen (strippath)) == 0) 657 rcs += strlen (strippath); 658 free (strippath); 659 if (vers_tag != NULL) 660 { 661 file1 = xmalloc (strlen (finfo->fullname) 662 + strlen (vers_tag) 663 + 10); 664 (void) sprintf (file1, "%s:%s", finfo->fullname, vers_tag); 665 } 666 else 667 { 668 file1 = xstrdup (DEVNULL); 669 } 670 file2 = xmalloc (strlen (finfo->fullname) 671 + (vers_head != NULL ? strlen (vers_head) : 10) 672 + 10); 673 (void) sprintf (file2, "%s:%s", finfo->fullname, 674 vers_head ? vers_head : "removed"); 675 676 /* Note that the string "diff" is specified by POSIX (for -c) 677 and is part of the diff output format, not the name of a 678 program. */ 679 if (unidiff) 680 { 681 cvs_output ("diff -u ", 0); 682 cvs_output (file1, 0); 683 cvs_output (" ", 1); 684 cvs_output (file2, 0); 685 cvs_output ("\n", 1); 686 687 cvs_output ("--- ", 0); 688 cvs_output (file1, 0); 689 cvs_output (cp1, 0); 690 cvs_output ("+++ ", 0); 691 } 692 else 693 { 694 cvs_output ("diff -c ", 0); 695 cvs_output (file1, 0); 696 cvs_output (" ", 1); 697 cvs_output (file2, 0); 698 cvs_output ("\n", 1); 699 700 cvs_output ("*** ", 0); 701 cvs_output (file1, 0); 702 cvs_output (cp1, 0); 703 cvs_output ("--- ", 0); 704 } 705 706 cvs_output (finfo->fullname, 0); 707 cvs_output (cp2, 0); 708 709 /* spew the rest of the diff out */ 710 while ((line_length 711 = getline (&line1, &line1_chars_allocated, fp)) 712 >= 0) 713 cvs_output (line1, 0); 714 if (line_length < 0 && !feof (fp)) 715 error (0, errno, "cannot read %s", tmpfile3); 716 717 if (fclose (fp) < 0) 718 error (0, errno, "cannot close %s", tmpfile3); 719 free (file1); 720 free (file2); 721 break; 722 default: 723 error (0, 0, "diff failed for %s", finfo->fullname); 724 } 725 out: 726 if (line1) 727 free (line1); 728 if (line2) 729 free (line2); 730 if (CVS_UNLINK (tmpfile1) < 0) 731 error (0, errno, "cannot unlink %s", tmpfile1); 732 if (CVS_UNLINK (tmpfile2) < 0) 733 error (0, errno, "cannot unlink %s", tmpfile2); 734 if (CVS_UNLINK (tmpfile3) < 0) 735 error (0, errno, "cannot unlink %s", tmpfile3); 736 free (tmpfile1); 737 free (tmpfile2); 738 free (tmpfile3); 739 tmpfile1 = tmpfile2 = tmpfile3 = NULL; 740 741 out2: 742 if (vers_tag != NULL) 743 free (vers_tag); 744 if (vers_head != NULL) 745 free (vers_head); 746 if (rcs != NULL) 747 free (rcs); 748 return (ret); 749 } 750 751 /* 752 * Print a warm fuzzy message 753 */ 754 /* ARGSUSED */ 755 static Dtype 756 patch_dirproc (callerdat, dir, repos, update_dir, entries) 757 void *callerdat; 758 char *dir; 759 char *repos; 760 char *update_dir; 761 List *entries; 762 { 763 if (!quiet) 764 error (0, 0, "Diffing %s", update_dir); 765 return (R_PROCESS); 766 } 767 768 /* 769 * Clean up temporary files 770 */ 771 static RETSIGTYPE 772 patch_cleanup () 773 { 774 /* Note that the checks for existence_error are because we are 775 called from a signal handler, without SIG_begincrsect, so 776 we don't know whether the files got created. */ 777 778 if (tmpfile1 != NULL) 779 { 780 if (unlink_file (tmpfile1) < 0 781 && !existence_error (errno)) 782 error (0, errno, "cannot remove %s", tmpfile1); 783 free (tmpfile1); 784 } 785 if (tmpfile2 != NULL) 786 { 787 if (unlink_file (tmpfile2) < 0 788 && !existence_error (errno)) 789 error (0, errno, "cannot remove %s", tmpfile2); 790 free (tmpfile2); 791 } 792 if (tmpfile3 != NULL) 793 { 794 if (unlink_file (tmpfile3) < 0 795 && !existence_error (errno)) 796 error (0, errno, "cannot remove %s", tmpfile3); 797 free (tmpfile3); 798 } 799 tmpfile1 = tmpfile2 = tmpfile3 = NULL; 800 } 801