|
|
1.1 ! root 1: /* ! 2: ! 3: Copyright (C) 1990-1992 Mark Adler, Richard B. Wales, Jean-loup Gailly, ! 4: Kai Uwe Rommel and Igor Mandrichenko. ! 5: Permission is granted to any individual or institution to use, copy, or ! 6: redistribute this software so long as all of the original files are included ! 7: unmodified, that it is not sold for profit, and that this copyright notice ! 8: is retained. ! 9: ! 10: */ ! 11: ! 12: /* ! 13: * zip.c by Mark Adler. ! 14: */ ! 15: ! 16: #include "revision.h" ! 17: #include "zip.h" ! 18: #ifdef VMS ! 19: # include "VMSmunch.h" ! 20: # define echon() echo(1) ! 21: #endif ! 22: #include <signal.h> ! 23: ! 24: #ifdef MACOS ! 25: # include <console.h> ! 26: #endif ! 27: ! 28: #define PWLEN 80 /* Input buffer size for reading encryption key */ ! 29: #define MAXCOM 256 /* Maximum one-line comment size */ ! 30: ! 31: ! 32: /* Local option flags */ ! 33: #define DELETE 0 ! 34: #define ADD 1 ! 35: #define UPDATE 2 ! 36: #define FRESHEN 3 ! 37: local int action = ADD; /* one of ADD, UPDATE, FRESHEN, or DELETE */ ! 38: local int comadd = 0; /* 1=add comments for new files */ ! 39: local int zipedit = 0; /* 1=edit zip comment and all file comments */ ! 40: local int dispose = 0; /* 1=remove files after put in zip file */ ! 41: local int latest = 0; /* 1=set zip file time to time of latest file */ ! 42: local ulg before = 0; /* 0=ignore, else exclude files before this time */ ! 43: ! 44: ! 45: /* Temporary zip file name and file pointer */ ! 46: local char *tempzip; ! 47: local FILE *tempzf; ! 48: ! 49: ! 50: /* Local functions */ ! 51: #ifdef PROTO ! 52: local void freeup(void); ! 53: local void leave(int); ! 54: local void handler(int); ! 55: local void license(void); ! 56: local void help(void); ! 57: local void zipstdout(void); ! 58: void main(int, char **); ! 59: local int count_args(char *s); ! 60: local void envargs(int *Pargc, char ***Pargv, char *envstr); ! 61: #endif /* PROTO */ ! 62: ! 63: ! 64: ! 65: local void freeup() ! 66: /* Free all allocations in the found list and the zfiles list */ ! 67: { ! 68: struct flist far *f; /* steps through found list */ ! 69: struct zlist far *z; /* pointer to next entry in zfiles list */ ! 70: ! 71: for (f = found; f != NULL; f = fexpel(f)) ! 72: ; ! 73: while (zfiles != NULL) ! 74: { ! 75: z = zfiles->nxt; ! 76: free((voidp *)(zfiles->name)); ! 77: free((voidp *)(zfiles->zname)); ! 78: if (zfiles->ext) ! 79: free((voidp *)(zfiles->extra)); ! 80: if (zfiles->cext && zfiles->cextra != zfiles->extra) ! 81: free((voidp *)(zfiles->cextra)); ! 82: if (zfiles->com) ! 83: free((voidp *)(zfiles->comment)); ! 84: farfree((voidp far *)zfiles); ! 85: zfiles = z; ! 86: zcount--; ! 87: } ! 88: } ! 89: ! 90: ! 91: local void leave(e) ! 92: int e; /* exit code */ ! 93: /* Process -o and -m options (if specified), free up malloc'ed stuff, and ! 94: exit with the code e. */ ! 95: { ! 96: int r; /* return value from trash() */ ! 97: ulg t; /* latest time in zip file */ ! 98: struct zlist far *z; /* pointer into zfile list */ ! 99: ! 100: /* If latest, set time to zip file to latest file in zip file */ ! 101: if (latest && strcmp(zipfile, "-")) ! 102: { ! 103: diag("changing time of zip file to time of latest file in it"); ! 104: /* find latest time in zip file */ ! 105: if (zfiles == NULL) ! 106: warn("zip file is empty, can't make it as old as latest entry", ""); ! 107: else { ! 108: t = zfiles->tim; ! 109: for (z = zfiles->nxt; z != NULL; z = z->nxt) ! 110: if (t < z->tim) ! 111: t = z->tim; ! 112: /* set modified time of zip file to that time */ ! 113: stamp(zipfile, t); ! 114: } ! 115: } ! 116: if (tempath != NULL) ! 117: { ! 118: free((voidp *)tempath); ! 119: tempath = NULL; ! 120: } ! 121: if (zipfile != NULL) ! 122: { ! 123: free((voidp *)zipfile); ! 124: zipfile = NULL; ! 125: } ! 126: ! 127: ! 128: /* If dispose, delete all files in the zfiles list that are marked */ ! 129: if (dispose) ! 130: { ! 131: diag("deleting files that were added to zip file"); ! 132: if ((r = trash()) != ZE_OK) ! 133: err(r, "was deleting moved files and directories"); ! 134: } ! 135: ! 136: ! 137: /* Done! */ ! 138: freeup(); ! 139: #ifdef VMS ! 140: exit(0); ! 141: #else /* !VMS */ ! 142: exit(e); ! 143: #endif /* ?VMS */ ! 144: } ! 145: ! 146: ! 147: void err(c, h) ! 148: int c; /* error code from the ZE_ class */ ! 149: char *h; /* message about how it happened */ ! 150: /* Issue a message for the error, clean up files and memory, and exit. */ ! 151: { ! 152: static int error_level; ! 153: if (error_level++ > 0) exit(0); /* avoid recursive err() */ ! 154: ! 155: if (PERR(c)) ! 156: perror("zip error"); ! 157: fprintf(stderr, "zip error: %s (%s)\n", errors[c-1], h); ! 158: if (tempzip != NULL) ! 159: { ! 160: if (tempzip != zipfile) { ! 161: if (tempzf != NULL) ! 162: fclose(tempzf); ! 163: #ifndef DEBUG ! 164: destroy(tempzip); ! 165: #endif ! 166: free((voidp *)tempzip); ! 167: } else { ! 168: /* -g option, attempt to restore the old file */ ! 169: int k = 0; /* keep count for end header */ ! 170: ulg cb = cenbeg; /* get start of central */ ! 171: struct zlist far *z; /* steps through zfiles linked list */ ! 172: ! 173: fprintf(stderr, "attempting to restore %s to its previous state\n", ! 174: zipfile); ! 175: fseek(tempzf, cenbeg, SEEK_SET); ! 176: tempzn = cenbeg; ! 177: for (z = zfiles; z != NULL; z = z->nxt) ! 178: { ! 179: putcentral(z, tempzf); ! 180: tempzn += 4 + CENHEAD + z->nam + z->cext + z->com; ! 181: k++; ! 182: } ! 183: putend(k, tempzn - cb, cb, zcomlen, zcomment, tempzf); ! 184: tempzf = NULL; ! 185: fclose(tempzf); ! 186: } ! 187: } ! 188: if (key != NULL) ! 189: free((voidp *)key); ! 190: if (tempath != NULL) ! 191: free((voidp *)tempath); ! 192: if (zipfile != NULL) ! 193: free((voidp *)zipfile); ! 194: freeup(); ! 195: #ifdef VMS ! 196: c = 0; ! 197: #endif ! 198: exit(c); ! 199: } ! 200: ! 201: ! 202: void error(h) ! 203: char *h; ! 204: /* Internal error, should never happen */ ! 205: { ! 206: err(ZE_LOGIC, h); ! 207: } ! 208: ! 209: local void handler(s) ! 210: int s; /* signal number (ignored) */ ! 211: /* Upon getting a user interrupt, turn echo back on for tty and abort ! 212: cleanly using err(). */ ! 213: { ! 214: #ifndef MSDOS ! 215: # ifdef CRYPT ! 216: echon(); ! 217: # endif ! 218: putc('\n', stderr); ! 219: #endif /* !MSDOS */ ! 220: err(ZE_ABORT, "aborting"); ! 221: s++; /* keep some compilers happy */ ! 222: } ! 223: ! 224: ! 225: void warn(a, b) ! 226: char *a, *b; /* message strings juxtaposed in output */ ! 227: /* Print a warning message to stderr and return. */ ! 228: { ! 229: fprintf(stderr, "zip warning: %s%s\n", a, b); ! 230: } ! 231: ! 232: ! 233: local void license() ! 234: /* Print license information to stdout. */ ! 235: { ! 236: extent i; /* counter for copyright array */ ! 237: ! 238: for (i = 0; i < sizeof(copyright)/sizeof(char *); i++) { ! 239: printf(copyright[i], "zip"); ! 240: putchar('\n'); ! 241: } ! 242: for (i = 0; i < sizeof(disclaimer)/sizeof(char *); i++) ! 243: puts(disclaimer[i]); ! 244: } ! 245: ! 246: ! 247: local void help() ! 248: /* Print help (along with license info) to stdout. */ ! 249: { ! 250: extent i; /* counter for help array */ ! 251: ! 252: /* help array */ ! 253: static char *text[] = { ! 254: "", ! 255: "Zip %d.%d (%s). Usage:", ! 256: "zip [-options] [-b path] [-t mmddyy] [-n suffixes] [zipfile list] [-x list]", ! 257: " The default action is to add or replace zipfile entries from list, which", ! 258: " can include the special name - to compress standard input.", ! 259: " If zipfile and list are ommitted, zip compresses stdin to stdout.", ! 260: " -f freshen: only changed files -u update: only changed or new files", ! 261: " -d delete entries in zipfile -m move into zipfile (delete files)", ! 262: " -k simulate PKZIP made zipfile -g allow growing existing zipfile", ! 263: " -h show this help -L show software license", ! 264: " -r recurse into directories -j junk (don't record) directory names", ! 265: " -0 store only -l translate end-of-line", ! 266: " -1 compress faster -9 compress better", ! 267: " -q quiet operation -n don't compress these suffixes", ! 268: " -c add one-line comments -z add zipfile comment", ! 269: " -b use \"path\" for temp files -t only do files after \"mmddyy\"", ! 270: " -@ read names from stdin -o make zipfile as old as latest entry", ! 271: #ifdef CRYPT ! 272: " -e encrypt (-ee verify key)", ! 273: #endif ! 274: #ifdef VMS ! 275: " -w append the VMS version number to the name stored in the zip file", ! 276: " -V save VMS file attributes", ! 277: #endif /* VMS */ ! 278: #ifdef OS2 ! 279: " -E use the .LONGNAME Extended attribute (if found) as filename", ! 280: #endif /* OS2 */ ! 281: #ifdef S_IFLNK ! 282: " -y store symbolic links as the link instead of the referenced file", ! 283: #endif /* !S_IFLNK */ ! 284: " -x exclude the names that follow from those operated on" ! 285: }; ! 286: ! 287: for (i = 0; i < sizeof(copyright)/sizeof(char *); i++) ! 288: { ! 289: printf(copyright[i], "zip"); ! 290: putchar('\n'); ! 291: } ! 292: for (i = 0; i < sizeof(text)/sizeof(char *); i++) ! 293: { ! 294: printf(text[i], REVISION / 10, REVISION % 10, REVDATE); ! 295: putchar('\n'); ! 296: } ! 297: } ! 298: ! 299: ! 300: /* Do command line expansion for MSDOS and VMS */ ! 301: #if defined(MSVMS) && !defined(__GO32__) ! 302: # define PROCNAME(n) (action==ADD||action==UPDATE?wild(n):procname(n)) ! 303: #else /* !MSVMS */ ! 304: # define PROCNAME(n) procname(n) ! 305: #endif /* ?MSVMS */ ! 306: ! 307: local void zipstdout() ! 308: /* setup for writing zip file on stdout */ ! 309: { ! 310: int r; ! 311: mesg = stderr; ! 312: if (isatty(1)) ! 313: err(ZE_PARMS, "no zip file provided"); ! 314: if ((zipfile = malloc(4)) == NULL) ! 315: err(ZE_MEM, "was processing arguments"); ! 316: strcpy(zipfile, "-"); ! 317: if ((r = readzipfile()) != ZE_OK) ! 318: err(r, zipfile); ! 319: } ! 320: ! 321: ! 322: void main(argc, argv) ! 323: int argc; /* number of tokens in command line */ ! 324: char **argv; /* command line tokens */ ! 325: /* Add, update, freshen, or delete zip entries in a zip file. See the ! 326: command help in help() above. */ ! 327: { ! 328: int a; /* attributes of zip file */ ! 329: ulg c; /* start of central directory */ ! 330: int d; /* true if just adding to a zip file */ ! 331: char *e; /* malloc'd comment buffer */ ! 332: struct flist far *f; /* steps through found linked list */ ! 333: int i; /* arg counter, root directory flag */ ! 334: int k; /* next argument type, marked counter, ! 335: comment size, entry count */ ! 336: ulg n; /* total of entry len's */ ! 337: int o; /* true if there were any ZE_OPEN errors */ ! 338: char *p; /* steps through option arguments */ ! 339: char *pp; /* temporary pointer */ ! 340: int r; /* temporary variable */ ! 341: ulg t; /* file time, length of central directory */ ! 342: struct zlist far *v; /* temporary variable */ ! 343: struct zlist far * far *w; /* pointer to last link in zfiles list */ ! 344: FILE *x, *y; /* input and output zip files */ ! 345: struct zlist far *z; /* steps through zfiles linked list */ ! 346: char *zipbuf; /* stdio buffer for the zip file */ ! 347: ! 348: mesg = (FILE *) stdout; /* cannot be made at link time for VMS */ ! 349: init_upper(); /* build case map table */ ! 350: ! 351: #ifdef MACOS ! 352: argc = ccommand(&argv); ! 353: #endif ! 354: ! 355: /* Process arguments */ ! 356: diag("processing arguments"); ! 357: if (argc == 1 && isatty(1)) ! 358: { ! 359: help(); ! 360: exit(0); ! 361: } ! 362: envargs(&argc, &argv, "ZIPOPT"); /* get options from environment */ ! 363: ! 364: zipfile = tempzip = NULL; ! 365: tempzf = NULL; ! 366: d = 0; /* disallow adding to a zip file */ ! 367: signal(SIGINT, handler); ! 368: signal(SIGTERM, handler); ! 369: k = 0; /* Next non-option argument type */ ! 370: for (i = 1; i < argc; i++) ! 371: { ! 372: if (argv[i][0] == '-') ! 373: if (argv[i][1]) ! 374: for (p = argv[i]+1; *p; p++) ! 375: switch(*p) ! 376: { ! 377: case '0': ! 378: method = STORE; level = 0; break; ! 379: case '1': case '2': case '3': case '4': ! 380: case '5': case '6': case '7': case '8': case '9': ! 381: /* Set the compression efficacy */ ! 382: level = *p - '0'; break; ! 383: case 'b': /* Specify path for temporary file */ ! 384: if (k != 0) ! 385: err(ZE_PARMS, "use -b before zip file name"); ! 386: else ! 387: k = 1; /* Next non-option is path */ ! 388: break; ! 389: case 'c': /* Add comments for new files in zip file */ ! 390: comadd = 1; break; ! 391: case 'd': /* Delete files from zip file */ ! 392: if (action != ADD) ! 393: err(ZE_PARMS, "specify just one action"); ! 394: action = DELETE; ! 395: break; ! 396: #ifdef CRYPT ! 397: case 'e': /* Encrypt */ ! 398: e = key == NULL ? (char *)NULL : key; ! 399: if ((key = malloc(PWLEN+1)) == NULL) ! 400: err(ZE_MEM, "was getting encryption password"); ! 401: if (getp(e == NULL ? "Enter password: " : "Verify password: ", ! 402: key, PWLEN+1) == NULL) ! 403: err(ZE_PARMS, "stderr is not a tty"); ! 404: if (e != NULL) ! 405: { ! 406: r = strcmp(key, e); ! 407: free((voidp *)e); ! 408: if (r) ! 409: err(ZE_PARMS, "password not verified"); ! 410: } ! 411: latest = 1; /* to make breaking the code harder */ ! 412: break; ! 413: #endif /* CRYPT */ ! 414: case 'f': /* Freshen zip file--overwrite only */ ! 415: if (action != ADD) ! 416: err(ZE_PARMS, "specify just one action"); ! 417: action = FRESHEN; ! 418: break; ! 419: case 'g': /* Allow appending to a zip file */ ! 420: d = 1; break; ! 421: case 'h': case 'H': case '?': /* Help */ ! 422: help(); ! 423: leave(ZE_OK); ! 424: case 'j': /* Junk directory names */ ! 425: pathput = 0; break; ! 426: case 'k': /* Make entries using DOS names (k for Katz) */ ! 427: dosify = 1; break; ! 428: case 'l': /* Translate end-of-line */ ! 429: translate_eol = 1; break; ! 430: case 'L': /* Show license, version */ ! 431: license(); ! 432: leave(ZE_OK); ! 433: case 'm': /* Delete files added or updated in zip file */ ! 434: dispose = 1; break; ! 435: case 'n': /* Don't compress files with a special suffix */ ! 436: special = NULL; ! 437: break; ! 438: case 'o': /* Set zip file time to time of latest file in it */ ! 439: latest = 1; break; ! 440: case 'p': /* Store path with name */ ! 441: break; /* (do nothing as annoyance avoidance) */ ! 442: case 'q': /* Quiet operation */ ! 443: noisy = 0; break; ! 444: case 'r': /* Recurse into subdirectories */ ! 445: recurse = 1; break; ! 446: case 't': /* Exclude files earlier than specified date */ ! 447: if (before) ! 448: err(ZE_PARMS, "can only have one -t"); ! 449: k = 2; break; ! 450: case 'u': /* Update zip file--overwrite only if newer */ ! 451: if (action != ADD) ! 452: err(ZE_PARMS, "specify just one action"); ! 453: action = UPDATE; ! 454: break; ! 455: case 'v': /* Mention oddities in zip file structure */ ! 456: verbose++; ! 457: break; ! 458: #ifdef VMS ! 459: case 'w': /* Append the VMS version number */ ! 460: vmsver = 1; break; ! 461: case 'V': /* Store in VMS format */ ! 462: vms_native = 1; break; ! 463: #endif /* VMS */ ! 464: case 'x': /* Exclude following files */ ! 465: if (k != 4 && ! 466: (k != 3 || (action != UPDATE && action != FRESHEN))) ! 467: err(ZE_PARMS, "nothing to exclude (-x) from"); ! 468: if (k == 3) /* must be -u or -f */ ! 469: for (z = zfiles; z != NULL; z = z->nxt) ! 470: z->mark = 1; /* mark all of them */ ! 471: k = 5; ! 472: if ((r = exclude()) != ZE_OK) ! 473: if (r == ZE_PARMS) ! 474: err(r, "cannot repeat names in zip file"); ! 475: else ! 476: err(r, "was processing list of files"); ! 477: break; ! 478: #ifdef S_IFLNK ! 479: case 'y': /* Store symbolic links as such */ ! 480: linkput = 1; break; ! 481: #endif /* S_IFLNK */ ! 482: case 'z': /* Edit zip file comment */ ! 483: zipedit = 1; break; ! 484: case '@': /* read file names from stdin */ ! 485: while ((pp = getnam(errbuf)) != NULL) ! 486: { ! 487: if ((r = PROCNAME(pp)) != ZE_OK) ! 488: if (r == ZE_MISS) ! 489: warn("name not matched: ", pp); ! 490: else ! 491: err(r, pp); ! 492: } ! 493: break; ! 494: #ifdef OS2 ! 495: case 'E': ! 496: /* use the .LONGNAME EA (if any) as the file's name. */ ! 497: use_longname_ea = 1; ! 498: break; ! 499: #endif ! 500: default: ! 501: { ! 502: sprintf(errbuf, "no such option: %c", *p); ! 503: err(ZE_PARMS, errbuf); ! 504: } ! 505: } ! 506: else /* just a dash */ ! 507: switch (k) ! 508: { ! 509: case 0: ! 510: zipstdout(); ! 511: k = 3; ! 512: break; ! 513: case 1: ! 514: err(ZE_PARMS, "invalid path"); ! 515: break; ! 516: case 2: ! 517: err(ZE_PARMS, "invalid time"); ! 518: break; ! 519: case 3: case 4: case 5: ! 520: if ((r = PROCNAME(argv[i])) != ZE_OK) ! 521: if (r == ZE_MISS) ! 522: warn("name not matched: ", argv[i]); ! 523: else ! 524: err(r, argv[i]); ! 525: if (k == 3) ! 526: k = 4; ! 527: } ! 528: else /* not an option */ ! 529: { ! 530: if (special == NULL) ! 531: special = argv[i]; ! 532: else ! 533: switch (k) ! 534: { ! 535: case 0: ! 536: if ((zipfile = ziptyp(argv[i])) == NULL) ! 537: err(ZE_MEM, "was processing arguments"); ! 538: if ((r = readzipfile()) != ZE_OK) ! 539: err(r, zipfile); ! 540: k = 3; ! 541: break; ! 542: case 1: ! 543: if ((tempath = malloc(strlen(argv[i]) + 1)) == NULL) ! 544: err(ZE_MEM, "was processing arguments"); ! 545: strcpy(tempath, argv[i]); ! 546: k = 0; ! 547: break; ! 548: case 2: ! 549: { ! 550: int yy, mm, dd; /* results of sscanf() */ ! 551: ! 552: if (sscanf(argv[i], "%2d%2d%2d", &mm, &dd, &yy) != 3 || ! 553: mm < 1 || mm > 12 || dd < 1 || dd > 31) ! 554: err(ZE_PARMS, "invalid date entered for -t option"); ! 555: before = dostime(yy + (yy < 80 ? 2000 : 1900), mm, dd, 0, 0, 0); ! 556: k = 0; ! 557: break; ! 558: } ! 559: case 3: case 4: case 5: ! 560: if ((r = PROCNAME(argv[i])) != ZE_OK) ! 561: if (r == ZE_MISS) ! 562: warn("name not matched: ", argv[i]); ! 563: else ! 564: err(r, argv[i]); ! 565: if (k == 3) ! 566: k = 4; ! 567: } ! 568: } ! 569: } ! 570: if (k < 3) { /* zip used as filter */ ! 571: zipstdout(); ! 572: if ((r = procname("-")) != ZE_OK) ! 573: if (r == ZE_MISS) ! 574: warn("name not matched: ", "-"); ! 575: else ! 576: err(r, "-"); ! 577: k = 4; ! 578: } ! 579: ! 580: if (k != 5) /* Clean up selections */ ! 581: { ! 582: if (k == 3 && (action == UPDATE || action == FRESHEN)) ! 583: for (z = zfiles; z != NULL; z = z->nxt) ! 584: z->mark = 1; /* if -u or -f with no args, do all */ ! 585: if ((r = exclude()) != ZE_OK) /* remove duplicates in found list */ ! 586: if (r == ZE_PARMS) ! 587: err(r, "cannot repeat names in zip file"); ! 588: else ! 589: err(r, "was processing list of files"); ! 590: } ! 591: if (zcount) ! 592: free((voidp *)zsort); ! 593: ! 594: /* Check option combinations */ ! 595: if (action == DELETE && (method != BEST || dispose || recurse || ! 596: key != NULL || comadd || zipedit)) ! 597: err(ZE_PARMS, "invalid option(s) used with -d"); ! 598: if (linkput && dosify) ! 599: err(ZE_PARMS, "can't use -y with -k"); ! 600: if ((action != ADD || d) && !strcmp(zipfile, "-")) ! 601: err(ZE_PARMS, "can't use -d,-f,-u or -g on standard output"); ! 602: #ifdef VMS ! 603: if (vms_native && translate_eol) ! 604: err(ZE_PARMS, "can't use -V with -l"); ! 605: #endif ! 606: if (zcount == 0 && (action != ADD || d)) ! 607: warn(zipfile, " not found or empty"); ! 608: ! 609: ! 610: /* If -b not specified, make temporary path the same as the zip file */ ! 611: #ifdef MSDOS ! 612: if (tempath == NULL && ((p = strrchr(zipfile, '/')) != NULL || ! 613: (p = strrchr(zipfile, '\\')) != NULL || ! 614: (p = strrchr(zipfile, ':')) != NULL)) ! 615: { ! 616: if (*p == ':') ! 617: p++; ! 618: #else /* !MSDOS */ ! 619: if (tempath == NULL && (p = strrchr(zipfile, '/')) != NULL) ! 620: { ! 621: #endif /* ?MSDOS */ ! 622: if ((tempath = malloc((int)(p - zipfile) + 1)) == NULL) ! 623: err(ZE_MEM, "was processing arguments"); ! 624: r = *p; *p = 0; ! 625: strcpy(tempath, zipfile); ! 626: *p = (char)r; ! 627: } ! 628: ! 629: /* For each marked entry, if not deleting, check if it exists, and if ! 630: updating or freshening, compare date with entry in old zip file. ! 631: Unmark if it doesn't exist or is too old, else update marked count. */ ! 632: diag("stating marked entries"); ! 633: k = 0; /* Initialize marked count */ ! 634: for (z = zfiles; z != NULL; z = z->nxt) ! 635: if (z->mark) ! 636: if (action != DELETE && ! 637: ((t = filetime(z->name, (ulg *)NULL, (long *)NULL)) == 0 || ! 638: t < before || ! 639: ((action == UPDATE || action == FRESHEN) && t <= z->tim))) ! 640: { ! 641: z->mark = 0; ! 642: z->trash = t && t >= before; /* delete if -um or -fm */ ! 643: if (verbose) ! 644: fprintf(mesg, "zip diagnostic: %s %s\n", z->name, ! 645: z->trash ? "up to date" : "missing or early"); ! 646: } ! 647: else ! 648: k++; ! 649: ! 650: ! 651: /* Remove entries from found list that do not exist or are too old */ ! 652: diag("stating new entries"); ! 653: for (f = found; f != NULL;) ! 654: if (action == DELETE || action == FRESHEN || ! 655: (t = filetime(f->name, (ulg *)NULL, (long *)NULL)) == 0 || ! 656: t < before || (namecmp(f->name, zipfile) == 0 && strcmp(zipfile, "-"))) ! 657: f = fexpel(f); ! 658: else ! 659: f = f->nxt; ! 660: ! 661: /* Make sure there's something left to do */ ! 662: if (k == 0 && found == NULL && !(zfiles != NULL && (latest || zipedit))) ! 663: if (action == UPDATE || action == FRESHEN) ! 664: leave(ZE_OK); ! 665: else if (zfiles == NULL && latest) ! 666: err(ZE_NAME, zipfile); ! 667: else ! 668: err(ZE_NONE, zipfile); ! 669: d = (d && k == 0 && (zipbeg || zfiles != NULL)); /* d true if appending */ ! 670: ! 671: ! 672: /* Before we get carried away, make sure zip file is writeable */ ! 673: if (strcmp(zipfile, "-")) ! 674: { ! 675: x = zfiles == NULL && zipbeg == 0 ? fopen(zipfile, FOPW) : ! 676: fopen(zipfile, FOPM); ! 677: /* Note: FOPW and FOPM expand to several parameters for VMS */ ! 678: if (x == NULL) ! 679: err(ZE_CREAT, zipfile); ! 680: fclose(x); ! 681: a = getfileattr(zipfile); ! 682: if (zfiles == NULL && zipbeg == 0) ! 683: destroy(zipfile); ! 684: } ! 685: else ! 686: a = 0; ! 687: ! 688: ! 689: /* Open zip file and temporary output file */ ! 690: diag("opening zip file and creating temporary zip file"); ! 691: x = NULL; ! 692: tempzn = 0; ! 693: if (strcmp(zipfile, "-") == 0) ! 694: { ! 695: #ifdef MSDOS ! 696: /* Set stdout mode to binary for MSDOS systems */ ! 697: setmode(fileno(stdout), O_BINARY); ! 698: tempzf = y = fdopen(fileno(stdout), FOPW); ! 699: #else ! 700: tempzf = y = stdout; ! 701: #endif ! 702: tempzip = "-"; ! 703: } ! 704: else if (d) /* d true if just appending (-g) */ ! 705: { ! 706: if ((y = fopen(zipfile, FOPM)) == NULL) ! 707: err(ZE_NAME, zipfile); ! 708: tempzip = zipfile; ! 709: tempzf = y; ! 710: if (fseek(y, cenbeg, SEEK_SET)) ! 711: err(ferror(y) ? ZE_READ : ZE_EOF, zipfile); ! 712: tempzn = cenbeg; ! 713: } ! 714: else ! 715: { ! 716: if ((zfiles != NULL || zipbeg) && (x = fopen(zipfile, FOPR_EX)) == NULL) ! 717: err(ZE_NAME, zipfile); ! 718: if ((tempzip = tempname(zipfile)) == NULL) ! 719: err(ZE_MEM, tempzip); ! 720: if ((tempzf = y = fopen(tempzip, FOPW)) == NULL) ! 721: err(ZE_TEMP, tempzip); ! 722: if (zipbeg && (r = fcopy(x, y, zipbeg)) != ZE_OK) ! 723: err(r, r == ZE_TEMP ? tempzip : zipfile); ! 724: tempzn = zipbeg; ! 725: } ! 726: #ifndef VMS ! 727: /* Use large buffer to speed up stdio: */ ! 728: zipbuf = (char *)malloc(ZBSZ); ! 729: if (zipbuf == NULL) ! 730: err(ZE_MEM, tempzip); ! 731: # ifdef _IOFBF ! 732: setvbuf(y, zipbuf, _IOFBF, ZBSZ); ! 733: # else ! 734: setbuf(y, zipbuf); ! 735: # endif /* _IOBUF */ ! 736: #endif /* VMS */ ! 737: o = 0; /* no ZE_OPEN errors yet */ ! 738: ! 739: ! 740: /* Process zip file, updating marked files */ ! 741: if (zfiles != NULL) ! 742: diag("going through old zip file"); ! 743: w = &zfiles; ! 744: while ((z = *w) != NULL) ! 745: if (z->mark) ! 746: { ! 747: /* if not deleting, zip it up */ ! 748: if (action != DELETE) ! 749: { ! 750: if (noisy) ! 751: { ! 752: fprintf(mesg, "updating %s", z->zname); ! 753: fflush(mesg); ! 754: } ! 755: if ((r = zipup(z, y)) != ZE_OK && r != ZE_OPEN) ! 756: { ! 757: if (noisy) ! 758: { ! 759: putc('\n', mesg); ! 760: fflush(mesg); ! 761: } ! 762: sprintf(errbuf, "was zipping %s", z->name); ! 763: err(r, errbuf); ! 764: } ! 765: if (r == ZE_OPEN) ! 766: { ! 767: o = 1; ! 768: if (noisy) ! 769: { ! 770: putc('\n', mesg); ! 771: fflush(mesg); ! 772: } ! 773: perror("zip warning"); ! 774: warn("could not open for reading: ", z->name); ! 775: warn("will just copy entry over: ", z->zname); ! 776: if ((r = zipcopy(z, x, y)) != ZE_OK) ! 777: { ! 778: sprintf(errbuf, "was copying %s", z->zname); ! 779: err(r, errbuf); ! 780: } ! 781: z->mark = 0; ! 782: } ! 783: w = &z->nxt; ! 784: } ! 785: else ! 786: { ! 787: if (noisy) ! 788: { ! 789: fprintf(mesg, "deleting %s\n", z->zname); ! 790: fflush(mesg); ! 791: } ! 792: v = z->nxt; /* delete entry from list */ ! 793: free((voidp *)(z->name)); ! 794: free((voidp *)(z->zname)); ! 795: if (z->ext) ! 796: free((voidp *)(z->extra)); ! 797: if (z->cext && z->cextra != z->extra) ! 798: free((voidp *)(z->cextra)); ! 799: if (z->com) ! 800: free((voidp *)(z->comment)); ! 801: farfree((voidp far *)z); ! 802: *w = v; ! 803: zcount--; ! 804: } ! 805: } ! 806: else ! 807: { ! 808: /* copy the original entry verbatim */ ! 809: if (!d && (r = zipcopy(z, x, y)) != ZE_OK) ! 810: { ! 811: sprintf(errbuf, "was copying %s", z->zname); ! 812: err(r, errbuf); ! 813: } ! 814: w = &z->nxt; ! 815: } ! 816: ! 817: ! 818: /* Process the edited found list, adding them to the zip file */ ! 819: diag("zipping up new entries, if any"); ! 820: for (f = found; f != NULL; f = fexpel(f)) ! 821: { ! 822: /* add a new zfiles entry and set the name */ ! 823: if ((z = (struct zlist far *)farmalloc(sizeof(struct zlist))) == NULL) ! 824: err(ZE_MEM, "was adding files to zip file"); ! 825: z->nxt = NULL; ! 826: z->name = f->name; ! 827: f->name = NULL; ! 828: z->zname = f->zname; ! 829: f->zname = NULL; ! 830: z->ext = z->cext = z->com = 0; ! 831: z->mark = 1; ! 832: z->dosflag = f->dosflag; ! 833: /* zip it up */ ! 834: if (noisy) ! 835: { ! 836: fprintf(mesg, "adding %s", z->zname); ! 837: fflush(mesg); ! 838: } ! 839: if ((r = zipup(z, y)) != ZE_OK && r != ZE_OPEN) ! 840: { ! 841: if (noisy) ! 842: { ! 843: putc('\n', mesg); ! 844: fflush(mesg); ! 845: } ! 846: sprintf(errbuf, "was zipping %s", z->name); ! 847: err(r, errbuf); ! 848: } ! 849: if (r == ZE_OPEN) ! 850: { ! 851: o = 1; ! 852: if (noisy) ! 853: { ! 854: putc('\n', mesg); ! 855: fflush(mesg); ! 856: } ! 857: perror("zip warning"); ! 858: warn("could not open for reading: ", z->name); ! 859: free((voidp *)(z->name)); ! 860: free((voidp *)(z->zname)); ! 861: farfree((voidp far *)z); ! 862: } ! 863: else ! 864: { ! 865: *w = z; ! 866: w = &z->nxt; ! 867: zcount++; ! 868: } ! 869: } ! 870: if (key != NULL) ! 871: { ! 872: free((voidp *)key); ! 873: key = NULL; ! 874: } ! 875: ! 876: ! 877: /* Get one line comment for each new entry */ ! 878: if (comadd) ! 879: { ! 880: if ((e = malloc(MAXCOM + 1)) == NULL) ! 881: err(ZE_MEM, "was reading comment lines"); ! 882: for (z = zfiles; z != NULL; z = z->nxt) ! 883: if (z->mark) ! 884: { ! 885: if (noisy) ! 886: fprintf(mesg, "Enter comment for %s:\n", z->name); ! 887: /* ??? reopen /dev/tty if one file was zipped from stdin ! 888: * or if file names were read from stdin. ! 889: */ ! 890: if (fgets(e, MAXCOM+1, stdin) != NULL) ! 891: { ! 892: if ((p = malloc((k = strlen(e))+1)) == NULL) ! 893: { ! 894: free((voidp *)e); ! 895: err(ZE_MEM, "was reading comment lines"); ! 896: } ! 897: strcpy(p, e); ! 898: if (p[k-1] == '\n') ! 899: p[--k] = 0; ! 900: z->comment = p; ! 901: z->com = k; ! 902: } ! 903: } ! 904: free((voidp *)e); ! 905: } ! 906: ! 907: /* Get multi-line comment for the zip file */ ! 908: if (zipedit) ! 909: { ! 910: if ((e = malloc(MAXCOM + 1)) == NULL) ! 911: err(ZE_MEM, "was reading comment lines"); ! 912: if (noisy && zcomlen) ! 913: { ! 914: fputs("current zip file comment is:\n", mesg); ! 915: fwrite(zcomment, 1, zcomlen, mesg); ! 916: if (zcomment[zcomlen-1] != '\n') ! 917: putc('\n', mesg); ! 918: free((voidp *)zcomment); ! 919: } ! 920: zcomment = malloc(1); ! 921: *zcomment = 0; ! 922: if (noisy) ! 923: fputs("enter new zip file comment (end with .):\n", mesg); ! 924: /* ??? reopen /dev/tty if one file was zipped from stdin ! 925: * or if file names were read from stdin. ! 926: */ ! 927: while (fgets(e, MAXCOM+1, stdin) != NULL && strcmp(e, ".\n")) ! 928: { ! 929: if (e[(r = strlen(e)) - 1] == '\n') ! 930: e[--r] = 0; ! 931: if ((p = malloc((*zcomment ? strlen(zcomment) + 3 : 1) + r)) == NULL) ! 932: { ! 933: free((voidp *)e); ! 934: err(ZE_MEM, "was reading comment lines"); ! 935: } ! 936: if (*zcomment) ! 937: strcat(strcat(strcpy(p, zcomment), "\r\n"), e); ! 938: else ! 939: strcpy(p, *e ? e : "\r\n"); ! 940: free((voidp *)zcomment); ! 941: zcomment = p; ! 942: } ! 943: zcomlen = strlen(zcomment); ! 944: free((voidp *)e); ! 945: } ! 946: ! 947: ! 948: /* Write central directory and end header to temporary zip */ ! 949: diag("writing central directory"); ! 950: k = 0; /* keep count for end header */ ! 951: c = tempzn; /* get start of central */ ! 952: n = t = 0; ! 953: for (z = zfiles; z != NULL; z = z->nxt) ! 954: { ! 955: if ((r = putcentral(z, y)) != ZE_OK) ! 956: err(r, tempzip); ! 957: tempzn += 4 + CENHEAD + z->nam + z->cext + z->com; ! 958: n += z->len; ! 959: t += z->siz; ! 960: k++; ! 961: } ! 962: if (k == 0) ! 963: warn("zip file empty", ""); ! 964: if (verbose) ! 965: fprintf(mesg, "total bytes=%lu, compressed=%lu -> %d%% savings\n", ! 966: n, t, percent(n, t)); ! 967: t = tempzn - c; /* compute length of central */ ! 968: diag("writing end of central directory"); ! 969: if ((r = putend(k, t, c, zcomlen, zcomment, y)) != ZE_OK) ! 970: err(r, tempzip); ! 971: tempzf = NULL; ! 972: if (fclose(y)) ! 973: err(d ? ZE_WRITE : ZE_TEMP, tempzip); ! 974: if (x != NULL) ! 975: fclose(x); ! 976: ! 977: ! 978: /* Replace old zip file with new zip file, leaving only the new one */ ! 979: if (strcmp(zipfile, "-") && !d) ! 980: { ! 981: diag("replacing old zip file with new zip file"); ! 982: if ((r = replace(zipfile, tempzip)) != ZE_OK) ! 983: { ! 984: warn("new zip file left as: ", tempzip); ! 985: free((voidp *)tempzip); ! 986: tempzip = NULL; ! 987: err(r, "was replacing the original zip file"); ! 988: } ! 989: free((voidp *)tempzip); ! 990: } ! 991: tempzip = NULL; ! 992: if (strcmp(zipfile, "-")) { ! 993: setfileattr(zipfile, a); ! 994: #ifdef VMS ! 995: /* If the zip file existed previously, restore its record format: */ ! 996: if (x != NULL) ! 997: VMSmunch(zipfile, RESTORE_RTYPE, NULL); ! 998: #endif ! 999: } ! 1000: ! 1001: /* Finish up (process -o, -m, clean up). Exit code depends on o. */ ! 1002: leave(o ? ZE_OPEN : ZE_OK); ! 1003: } ! 1004: ! 1005: /***************************************************************** ! 1006: | envargs - add default options from environment to command line ! 1007: |---------------------------------------------------------------- ! 1008: | Author: Bill Davidsen, original 10/13/91, revised 23 Oct 1991. ! 1009: | This program is in the public domain. ! 1010: |---------------------------------------------------------------- ! 1011: | Minor program notes: ! 1012: | 1. Yes, the indirection is a tad complex ! 1013: | 2. Parenthesis were added where not needed in some cases ! 1014: | to make the action of the code less obscure. ! 1015: ****************************************************************/ ! 1016: ! 1017: local void ! 1018: envargs(Pargc, Pargv, envstr) ! 1019: int *Pargc; ! 1020: char ***Pargv; ! 1021: char *envstr; ! 1022: { ! 1023: char *getenv(); ! 1024: char *envptr; /* value returned by getenv */ ! 1025: char *bufptr; /* copy of env info */ ! 1026: int argc = 0; /* internal arg count */ ! 1027: int ch; /* spare temp value */ ! 1028: char **argv; /* internal arg vector */ ! 1029: char **argvect; /* copy of vector address */ ! 1030: ! 1031: /* see if anything in the environment */ ! 1032: envptr = getenv(envstr); ! 1033: if (envptr == NULL || *envptr == 0) return; ! 1034: ! 1035: /* count the args so we can allocate room for them */ ! 1036: argc = count_args(envptr); ! 1037: bufptr = malloc(1+strlen(envptr)); ! 1038: if (bufptr == NULL) ! 1039: err(ZE_MEM, "Can't get memory for arguments"); ! 1040: ! 1041: strcpy(bufptr, envptr); ! 1042: ! 1043: /* allocate a vector large enough for all args */ ! 1044: argv = (char **)malloc((argc+*Pargc+1)*sizeof(char *)); ! 1045: if (argv == NULL) ! 1046: err(ZE_MEM, "Can't get memory for arguments"); ! 1047: argvect = argv; ! 1048: ! 1049: /* copy the program name first, that's always true */ ! 1050: *(argv++) = *((*Pargv)++); ! 1051: ! 1052: /* copy the environment args first, may be changed */ ! 1053: do { ! 1054: *(argv++) = bufptr; ! 1055: /* skip the arg and any trailing blanks */ ! 1056: while ((ch = *bufptr) != '\0' && ch != ' ') ++bufptr; ! 1057: if (ch == ' ') *(bufptr++) = '\0'; ! 1058: while ((ch = *bufptr) != '\0' && ch == ' ') ++bufptr; ! 1059: } while (ch); ! 1060: ! 1061: /* now save old argc and copy in the old args */ ! 1062: argc += *Pargc; ! 1063: while (--(*Pargc)) *(argv++) = *((*Pargv)++); ! 1064: ! 1065: /* finally, add a NULL after the last arg, like UNIX */ ! 1066: *argv = NULL; ! 1067: ! 1068: /* save the values and return */ ! 1069: *Pargv = argvect; ! 1070: *Pargc = argc; ! 1071: } ! 1072: ! 1073: static int ! 1074: count_args(s) ! 1075: char *s; ! 1076: { ! 1077: int count = 0; ! 1078: int ch; ! 1079: ! 1080: do { ! 1081: /* count and skip args */ ! 1082: ++count; ! 1083: while ((ch = *s) != '\0' && ch != ' ') ++s; ! 1084: while ((ch = *s) != '\0' && ch == ' ') ++s; ! 1085: } while (ch); ! 1086: ! 1087: return count; ! 1088: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.