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