patch.c revision 54427
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 18static RETSIGTYPE patch_cleanup PROTO((void)); 19static Dtype patch_dirproc PROTO ((void *callerdat, char *dir, 20 char *repos, char *update_dir, 21 List *entries)); 22static int patch_fileproc PROTO ((void *callerdat, struct file_info *finfo)); 23static int patch_proc PROTO((int *pargc, char **argv, char *xwhere, 24 char *mwhere, char *mfile, int shorten, 25 int local_specified, char *mname, char *msg)); 26 27static int force_tag_match = 1; 28static int patch_short = 0; 29static int toptwo_diffs = 0; 30static int local = 0; 31static char *options = NULL; 32static char *rev1 = NULL; 33static int rev1_validated = 0; 34static char *rev2 = NULL; 35static int rev2_validated = 0; 36static char *date1 = NULL; 37static char *date2 = NULL; 38static char *tmpfile1 = NULL; 39static char *tmpfile2 = NULL; 40static char *tmpfile3 = NULL; 41static int unidiff = 0; 42 43static 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 61int 62patch (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 SIGHUP 234 (void) SIG_register (SIGHUP, patch_cleanup); 235#endif 236#ifdef SIGINT 237 (void) SIG_register (SIGINT, patch_cleanup); 238#endif 239#ifdef SIGQUIT 240 (void) SIG_register (SIGQUIT, patch_cleanup); 241#endif 242#ifdef SIGPIPE 243 (void) SIG_register (SIGPIPE, patch_cleanup); 244#endif 245#ifdef SIGTERM 246 (void) SIG_register (SIGTERM, patch_cleanup); 247#endif 248 249 db = open_module (); 250 for (i = 0; i < argc; i++) 251 err += do_module (db, argv[i], PATCH, "Patching", patch_proc, 252 (char *) NULL, 0, 0, 0, (char *) NULL); 253 close_module (db); 254 free (options); 255 patch_cleanup (); 256 return (err); 257} 258 259/* 260 * callback proc for doing the real work of patching 261 */ 262/* ARGSUSED */ 263static int 264patch_proc (pargc, argv, xwhere, mwhere, mfile, shorten, local_specified, 265 mname, msg) 266 int *pargc; 267 char **argv; 268 char *xwhere; 269 char *mwhere; 270 char *mfile; 271 int shorten; 272 int local_specified; 273 char *mname; 274 char *msg; 275{ 276 int err = 0; 277 int which; 278 char *repository; 279 char *where; 280 281 repository = xmalloc (strlen (CVSroot_directory) + strlen (argv[0]) 282 + (mfile == NULL ? 0 : strlen (mfile)) + 30); 283 (void) sprintf (repository, "%s/%s", CVSroot_directory, argv[0]); 284 where = xmalloc (strlen (argv[0]) + (mfile == NULL ? 0 : strlen (mfile)) 285 + 10); 286 (void) strcpy (where, argv[0]); 287 288 /* if mfile isn't null, we need to set up to do only part of the module */ 289 if (mfile != NULL) 290 { 291 char *cp; 292 char *path; 293 294 /* if the portion of the module is a path, put the dir part on repos */ 295 if ((cp = strrchr (mfile, '/')) != NULL) 296 { 297 *cp = '\0'; 298 (void) strcat (repository, "/"); 299 (void) strcat (repository, mfile); 300 (void) strcat (where, "/"); 301 (void) strcat (where, mfile); 302 mfile = cp + 1; 303 } 304 305 /* take care of the rest */ 306 path = xmalloc (strlen (repository) + strlen (mfile) + 5); 307 (void) sprintf (path, "%s/%s", repository, mfile); 308 if (isdir (path)) 309 { 310 /* directory means repository gets the dir tacked on */ 311 (void) strcpy (repository, path); 312 (void) strcat (where, "/"); 313 (void) strcat (where, mfile); 314 } 315 else 316 { 317 int i; 318 319 /* a file means muck argv */ 320 for (i = 1; i < *pargc; i++) 321 free (argv[i]); 322 argv[1] = xstrdup (mfile); 323 (*pargc) = 2; 324 } 325 free (path); 326 } 327 328 /* cd to the starting repository */ 329 if ( CVS_CHDIR (repository) < 0) 330 { 331 error (0, errno, "cannot chdir to %s", repository); 332 free (repository); 333 return (1); 334 } 335 free (repository); 336 337 if (force_tag_match) 338 which = W_REPOS | W_ATTIC; 339 else 340 which = W_REPOS; 341 342 if (rev1 != NULL && !rev1_validated) 343 { 344 tag_check_valid (rev1, *pargc - 1, argv + 1, local, 0, NULL); 345 rev1_validated = 1; 346 } 347 if (rev2 != NULL && !rev2_validated) 348 { 349 tag_check_valid (rev2, *pargc - 1, argv + 1, local, 0, NULL); 350 rev2_validated = 1; 351 } 352 353 /* start the recursion processor */ 354 err = start_recursion (patch_fileproc, (FILESDONEPROC) NULL, patch_dirproc, 355 (DIRLEAVEPROC) NULL, NULL, 356 *pargc - 1, argv + 1, local, 357 which, 0, 1, where, 1); 358 free (where); 359 360 return (err); 361} 362 363/* 364 * Called to examine a particular RCS file, as appropriate with the options 365 * that were set above. 366 */ 367/* ARGSUSED */ 368static int 369patch_fileproc (callerdat, finfo) 370 void *callerdat; 371 struct file_info *finfo; 372{ 373 struct utimbuf t; 374 char *vers_tag, *vers_head; 375 char *rcs = NULL; 376 RCSNode *rcsfile; 377 FILE *fp1, *fp2, *fp3; 378 int ret = 0; 379 int isattic = 0; 380 int retcode = 0; 381 char *file1; 382 char *file2; 383 char *strippath; 384 char *line1, *line2; 385 size_t line1_chars_allocated; 386 size_t line2_chars_allocated; 387 char *cp1, *cp2; 388 FILE *fp; 389 int line_length; 390 391 line1 = NULL; 392 line1_chars_allocated = 0; 393 line2 = NULL; 394 line2_chars_allocated = 0; 395 396 /* find the parsed rcs file */ 397 if ((rcsfile = finfo->rcs) == NULL) 398 { 399 ret = 1; 400 goto out2; 401 } 402 if ((rcsfile->flags & VALID) && (rcsfile->flags & INATTIC)) 403 isattic = 1; 404 405 rcs = xmalloc (strlen (finfo->file) + sizeof (RCSEXT) + 5); 406 (void) sprintf (rcs, "%s%s", finfo->file, RCSEXT); 407 408 /* if vers_head is NULL, may have been removed from the release */ 409 if (isattic && rev2 == NULL && date2 == NULL) 410 vers_head = NULL; 411 else 412 { 413 vers_head = RCS_getversion (rcsfile, rev2, date2, force_tag_match, 414 (int *) NULL); 415 if (vers_head != NULL && RCS_isdead (rcsfile, vers_head)) 416 { 417 free (vers_head); 418 vers_head = NULL; 419 } 420 } 421 422 if (toptwo_diffs) 423 { 424 if (vers_head == NULL) 425 { 426 ret = 1; 427 goto out2; 428 } 429 430 if (!date1) 431 date1 = xmalloc (MAXDATELEN); 432 *date1 = '\0'; 433 if (RCS_getrevtime (rcsfile, vers_head, date1, 1) == -1) 434 { 435 if (!really_quiet) 436 error (0, 0, "cannot find date in rcs file %s revision %s", 437 rcs, vers_head); 438 ret = 1; 439 goto out2; 440 } 441 } 442 vers_tag = RCS_getversion (rcsfile, rev1, date1, force_tag_match, 443 (int *) NULL); 444 if (vers_tag != NULL && RCS_isdead (rcsfile, vers_tag)) 445 { 446 free (vers_tag); 447 vers_tag = NULL; 448 } 449 450 if (vers_tag == NULL && vers_head == NULL) 451 { 452 /* Nothing known about specified revs. */ 453 ret = 0; 454 goto out2; 455 } 456 457 if (vers_tag && vers_head && strcmp (vers_head, vers_tag) == 0) 458 { 459 /* Not changed between releases. */ 460 ret = 0; 461 goto out2; 462 } 463 464 if (patch_short) 465 { 466 cvs_output ("File ", 0); 467 cvs_output (finfo->fullname, 0); 468 if (vers_tag == NULL) 469 { 470 cvs_output (" is new; current revision ", 0); 471 cvs_output (vers_head, 0); 472 cvs_output ("\n", 1); 473 } 474 else if (vers_head == NULL) 475 { 476 cvs_output (" is removed; not included in ", 0); 477 if (rev2 != NULL) 478 { 479 cvs_output ("release tag ", 0); 480 cvs_output (rev2, 0); 481 } 482 else if (date2 != NULL) 483 { 484 cvs_output ("release date ", 0); 485 cvs_output (date2, 0); 486 } 487 else 488 cvs_output ("current release", 0); 489 cvs_output ("\n", 1); 490 } 491 else 492 { 493 cvs_output (" changed from revision ", 0); 494 cvs_output (vers_tag, 0); 495 cvs_output (" to ", 0); 496 cvs_output (vers_head, 0); 497 cvs_output ("\n", 1); 498 } 499 ret = 0; 500 goto out2; 501 } 502 503 /* Create 3 empty files. I'm not really sure there is any advantage 504 to doing so now rather than just waiting until later. */ 505 tmpfile1 = cvs_temp_name (); 506 fp1 = CVS_FOPEN (tmpfile1, "w+"); 507 if (fp1 == NULL) 508 { 509 error (0, errno, "cannot create temporary file %s", tmpfile1); 510 ret = 1; 511 goto out; 512 } 513 else 514 if (fclose (fp1) < 0) 515 error (0, errno, "warning: cannot close %s", tmpfile1); 516 tmpfile2 = cvs_temp_name (); 517 fp2 = CVS_FOPEN (tmpfile2, "w+"); 518 if (fp2 == NULL) 519 { 520 error (0, errno, "cannot create temporary file %s", tmpfile2); 521 ret = 1; 522 goto out; 523 } 524 else 525 if (fclose (fp2) < 0) 526 error (0, errno, "warning: cannot close %s", tmpfile2); 527 tmpfile3 = cvs_temp_name (); 528 fp3 = CVS_FOPEN (tmpfile3, "w+"); 529 if (fp3 == NULL) 530 { 531 error (0, errno, "cannot create temporary file %s", tmpfile3); 532 ret = 1; 533 goto out; 534 } 535 else 536 if (fclose (fp3) < 0) 537 error (0, errno, "warning: cannot close %s", tmpfile3); 538 539 if (vers_tag != NULL) 540 { 541 retcode = RCS_checkout (rcsfile, (char *) NULL, vers_tag, 542 rev1, options, tmpfile1, 543 (RCSCHECKOUTPROC) NULL, (void *) NULL); 544 if (retcode != 0) 545 { 546 error (0, 0, 547 "cannot check out revision %s of %s", vers_tag, rcs); 548 ret = 1; 549 goto out; 550 } 551 memset ((char *) &t, 0, sizeof (t)); 552 if ((t.actime = t.modtime = RCS_getrevtime (rcsfile, vers_tag, 553 (char *) 0, 0)) != -1) 554 /* I believe this timestamp only affects the dates in our diffs, 555 and therefore should be on the server, not the client. */ 556 (void) utime (tmpfile1, &t); 557 } 558 else if (toptwo_diffs) 559 { 560 ret = 1; 561 goto out; 562 } 563 if (vers_head != NULL) 564 { 565 retcode = RCS_checkout (rcsfile, (char *) NULL, vers_head, 566 rev2, options, tmpfile2, 567 (RCSCHECKOUTPROC) NULL, (void *) NULL); 568 if (retcode != 0) 569 { 570 error (0, 0, 571 "cannot check out revision %s of %s", vers_head, rcs); 572 ret = 1; 573 goto out; 574 } 575 if ((t.actime = t.modtime = RCS_getrevtime (rcsfile, vers_head, 576 (char *) 0, 0)) != -1) 577 /* I believe this timestamp only affects the dates in our diffs, 578 and therefore should be on the server, not the client. */ 579 (void) utime (tmpfile2, &t); 580 } 581 582 switch (diff_exec (tmpfile1, tmpfile2, unidiff ? "-u" : "-c", tmpfile3)) 583 { 584 case -1: /* fork/wait failure */ 585 error (1, errno, "fork for diff failed on %s", rcs); 586 break; 587 case 0: /* nothing to do */ 588 break; 589 case 1: 590 /* 591 * The two revisions are really different, so read the first two 592 * lines of the diff output file, and munge them to include more 593 * reasonable file names that "patch" will understand. 594 */ 595 596 /* Output an "Index:" line for patch to use */ 597 cvs_output ("Index: ", 0); 598 cvs_output (finfo->fullname, 0); 599 cvs_output ("\n", 1); 600 601 fp = open_file (tmpfile3, "r"); 602 if (getline (&line1, &line1_chars_allocated, fp) < 0 || 603 getline (&line2, &line2_chars_allocated, fp) < 0) 604 { 605 if (feof (fp)) 606 error (0, 0, "\ 607failed to read diff file header %s for %s: end of file", tmpfile3, rcs); 608 else 609 error (0, errno, 610 "failed to read diff file header %s for %s", 611 tmpfile3, rcs); 612 ret = 1; 613 if (fclose (fp) < 0) 614 error (0, errno, "error closing %s", tmpfile3); 615 goto out; 616 } 617 if (!unidiff) 618 { 619 if (strncmp (line1, "*** ", 4) != 0 || 620 strncmp (line2, "--- ", 4) != 0 || 621 (cp1 = strchr (line1, '\t')) == NULL || 622 (cp2 = strchr (line2, '\t')) == NULL) 623 { 624 error (0, 0, "invalid diff header for %s", rcs); 625 ret = 1; 626 if (fclose (fp) < 0) 627 error (0, errno, "error closing %s", tmpfile3); 628 goto out; 629 } 630 } 631 else 632 { 633 if (strncmp (line1, "--- ", 4) != 0 || 634 strncmp (line2, "+++ ", 4) != 0 || 635 (cp1 = strchr (line1, '\t')) == NULL || 636 (cp2 = strchr (line2, '\t')) == NULL) 637 { 638 error (0, 0, "invalid unidiff header for %s", rcs); 639 ret = 1; 640 if (fclose (fp) < 0) 641 error (0, errno, "error closing %s", tmpfile3); 642 goto out; 643 } 644 } 645 if (CVSroot_directory != NULL) 646 { 647 strippath = xmalloc (strlen (CVSroot_directory) + 10); 648 (void) sprintf (strippath, "%s/", CVSroot_directory); 649 } 650 else 651 strippath = xstrdup (REPOS_STRIP); 652 if (strncmp (rcs, strippath, strlen (strippath)) == 0) 653 rcs += strlen (strippath); 654 free (strippath); 655 if (vers_tag != NULL) 656 { 657 file1 = xmalloc (strlen (finfo->fullname) 658 + strlen (vers_tag) 659 + 10); 660 (void) sprintf (file1, "%s:%s", finfo->fullname, vers_tag); 661 } 662 else 663 { 664 file1 = xstrdup (DEVNULL); 665 } 666 file2 = xmalloc (strlen (finfo->fullname) 667 + (vers_head != NULL ? strlen (vers_head) : 10) 668 + 10); 669 (void) sprintf (file2, "%s:%s", finfo->fullname, 670 vers_head ? vers_head : "removed"); 671 672 /* Note that the string "diff" is specified by POSIX (for -c) 673 and is part of the diff output format, not the name of a 674 program. */ 675 if (unidiff) 676 { 677 cvs_output ("diff -u ", 0); 678 cvs_output (file1, 0); 679 cvs_output (" ", 1); 680 cvs_output (file2, 0); 681 cvs_output ("\n", 1); 682 683 cvs_output ("--- ", 0); 684 cvs_output (file1, 0); 685 cvs_output (cp1, 0); 686 cvs_output ("+++ ", 0); 687 } 688 else 689 { 690 cvs_output ("diff -c ", 0); 691 cvs_output (file1, 0); 692 cvs_output (" ", 1); 693 cvs_output (file2, 0); 694 cvs_output ("\n", 1); 695 696 cvs_output ("*** ", 0); 697 cvs_output (file1, 0); 698 cvs_output (cp1, 0); 699 cvs_output ("--- ", 0); 700 } 701 702 cvs_output (finfo->fullname, 0); 703 cvs_output (cp2, 0); 704 705 /* spew the rest of the diff out */ 706 while ((line_length 707 = getline (&line1, &line1_chars_allocated, fp)) 708 >= 0) 709 cvs_output (line1, 0); 710 if (line_length < 0 && !feof (fp)) 711 error (0, errno, "cannot read %s", tmpfile3); 712 713 if (fclose (fp) < 0) 714 error (0, errno, "cannot close %s", tmpfile3); 715 free (file1); 716 free (file2); 717 break; 718 default: 719 error (0, 0, "diff failed for %s", finfo->fullname); 720 } 721 out: 722 if (line1) 723 free (line1); 724 if (line2) 725 free (line2); 726 if (CVS_UNLINK (tmpfile1) < 0) 727 error (0, errno, "cannot unlink %s", tmpfile1); 728 if (CVS_UNLINK (tmpfile2) < 0) 729 error (0, errno, "cannot unlink %s", tmpfile2); 730 if (CVS_UNLINK (tmpfile3) < 0) 731 error (0, errno, "cannot unlink %s", tmpfile3); 732 free (tmpfile1); 733 free (tmpfile2); 734 free (tmpfile3); 735 tmpfile1 = tmpfile2 = tmpfile3 = NULL; 736 737 out2: 738 if (rcs != NULL) 739 free (rcs); 740 return (ret); 741} 742 743/* 744 * Print a warm fuzzy message 745 */ 746/* ARGSUSED */ 747static Dtype 748patch_dirproc (callerdat, dir, repos, update_dir, entries) 749 void *callerdat; 750 char *dir; 751 char *repos; 752 char *update_dir; 753 List *entries; 754{ 755 if (!quiet) 756 error (0, 0, "Diffing %s", update_dir); 757 return (R_PROCESS); 758} 759 760/* 761 * Clean up temporary files 762 */ 763static RETSIGTYPE 764patch_cleanup () 765{ 766 /* Note that the checks for existence_error are because we are 767 called from a signal handler, without SIG_begincrsect, so 768 we don't know whether the files got created. */ 769 770 if (tmpfile1 != NULL) 771 { 772 if (unlink_file (tmpfile1) < 0 773 && !existence_error (errno)) 774 error (0, errno, "cannot remove %s", tmpfile1); 775 free (tmpfile1); 776 } 777 if (tmpfile2 != NULL) 778 { 779 if (unlink_file (tmpfile2) < 0 780 && !existence_error (errno)) 781 error (0, errno, "cannot remove %s", tmpfile2); 782 free (tmpfile2); 783 } 784 if (tmpfile3 != NULL) 785 { 786 if (unlink_file (tmpfile3) < 0 787 && !existence_error (errno)) 788 error (0, errno, "cannot remove %s", tmpfile3); 789 free (tmpfile3); 790 } 791 tmpfile1 = tmpfile2 = tmpfile3 = NULL; 792} 793