Annotation of coherent/b/bin/zip/zip.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.