home *** CD-ROM | disk | FTP | other *** search
/ Windows NT Super Tune-Up Kit / PIE-WindowsNTSuperTuneUpKit-1997.iso / COMPRESS / NT_PKZIP / ZIP.BAK < prev    next >
Text File  |  1992-03-26  |  26KB  |  873 lines

  1. /*
  2.  
  3.  Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup Gailly.
  4.  Permission is granted to any individual or institution to use, copy, or
  5.  redistribute this software so long as all of the original files are included
  6.  unmodified, that it is not sold for profit, and that this copyright notice
  7.  is retained.
  8.  
  9. */
  10.  
  11. /*
  12.  *  zip.c by Mark Adler.
  13.  */
  14.  
  15. #include "revision.h"
  16. #include "zip.h"
  17. #include <signal.h>
  18.  
  19. #define PWLEN 80        /* Input buffer size for reading encryption key */
  20. #define MAXCOM 256      /* Maximum one-line comment size */
  21.  
  22.  
  23. /* Local option flags */
  24. #define DELETE  0
  25. #define ADD     1
  26. #define UPDATE  2
  27. #define FRESHEN 3
  28. local int action = ADD; /* one of ADD, UPDATE, FRESHEN, or DELETE */
  29. local int comadd = 0;   /* 1=add comments for new files */
  30. local int zipedit = 0;  /* 1=edit zip comment and all file comments */
  31. local int dispose = 0;  /* 1=remove files after put in zip file */
  32. local int latest = 0;   /* 1=set zip file time to time of latest file */
  33. local ulg before = 0;   /* 0=ignore, else exclude files before this time */
  34.  
  35.  
  36. /* Temporary zip file name and file pointer */
  37. local char *tempzip;
  38. local FILE *tempzf;
  39.  
  40.  
  41. /* Local functions */
  42. #ifdef PROTO
  43.    local void freeup(void);
  44. #ifdef MIPS
  45. #  undef leave
  46. #else
  47.    local void leave(int);
  48. #endif
  49.    local void err(int, char *);
  50.    local void handler(int);
  51.    local void license(void);
  52.    local void help(void);
  53.    void main(int, char **);
  54. #endif /* MIPS */
  55. #endif /* PROTO */
  56.  
  57.  
  58.  
  59. local void freeup()
  60. /* Free all allocations in the found list and the zfiles list */
  61. {
  62.   struct flist far *f;  /* steps through found list */
  63.   struct zlist far *z;  /* pointer to next entry in zfiles list */
  64.  
  65.   for (f = found; f != NULL; f = fexpel(f))
  66.     ;
  67.   while (zfiles != NULL)
  68.   {
  69.     z = zfiles->nxt;
  70.     free((voidp *)(zfiles->name));
  71.     free((voidp *)(zfiles->zname));
  72.     if (zfiles->ext)
  73.       free((voidp *)(zfiles->extra));
  74.     if (zfiles->cext && zfiles->cextra != zfiles->extra)
  75.       free((voidp *)(zfiles->cextra));
  76.     if (zfiles->com)
  77.       free((voidp *)(zfiles->comment));
  78.     farfree((voidp far *)zfiles);
  79.     zfiles = z;
  80.     zcount--;
  81.   }
  82. }
  83.  
  84. local void leave(e)
  85. int e;                  /* exit code */
  86. /* Process -o and -m options (if specified), free up malloc'ed stuff, and
  87.    exit with the code e. */
  88. {
  89.   int r;                /* return value from trash() */
  90.   ulg t;                /* latest time in zip file */
  91.   struct zlist far *z;  /* pointer into zfile list */
  92.  
  93.   /* If latest, set time to zip file to latest file in zip file */
  94.   if (latest)
  95.   {
  96.     diag("changing time of zip file to time of latest file in it");
  97.     /* find latest time in zip file */
  98.     t = zfiles->tim;
  99.     for (z = zfiles->nxt; z != NULL; z = z->nxt)
  100.       if (t < z->tim)
  101.         t = z->tim;
  102.     /* set modified time of zip file to that time */
  103.     stamp(zipfile, t);
  104.   }
  105.   if (tempath != NULL)
  106.   {
  107.     free((voidp *)tempath);
  108.     tempath = NULL;
  109.   }
  110.   if (zipfile != NULL)
  111.   {
  112.     free((voidp *)zipfile);
  113.     zipfile = NULL;
  114.   }
  115.  
  116.  
  117.   /* If dispose, delete all files in the zfiles list that are marked */
  118.   if (dispose)
  119.   {
  120.     diag("deleting files that were added to zip file");
  121.     if ((r = trash()) != ZE_OK)
  122.       err(r, "was deleting moved files and directories");
  123.   }
  124.  
  125.  
  126.   /* Done! */
  127.   freeup();
  128. #ifdef VMS
  129.   exit(0);
  130. #else /* !VMS */
  131.   exit(e);
  132. #endif /* ?VMS */
  133. }
  134.  
  135.  
  136. local void err(c, h)
  137. int c;                  /* error code from the ZE_ class */
  138. char *h;                /* message about how it happened */
  139. /* Issue a message for the error, clean up files and memory, and exit. */
  140. {
  141.   if (PERR(c))
  142.     perror("zip error");
  143.   fprintf(stderr, "zip error: %s (%s)\n", errors[c-1], h);
  144.   if (shract)
  145.   {
  146.     shr_clear();
  147.     shract = 0;
  148.   }
  149. #ifndef NOIMPLODE
  150.   if (impact)
  151.   {
  152.     imp_clear();
  153.     impact = 0;
  154.   }
  155. #endif /* !NOIMPLODE */
  156.   if (tempzf != NULL)
  157.     fclose(tempzf);
  158.   if (tempzip != NULL)
  159.   {
  160.     destroy(tempzip);
  161.     if (tempzip != zipfile)
  162.       free((voidp *)tempzip);
  163.   }
  164.   if (key != NULL)
  165.     free((voidp *)key);
  166.   if (tempath != NULL)
  167.     free((voidp *)tempath);
  168.   if (zipfile != NULL)
  169.     free((voidp *)zipfile);
  170.   freeup();
  171. #ifdef VMS
  172.   exit(0);
  173. #else /* !VMS */
  174.   exit(c);
  175. #endif /* ?VMS */
  176. }
  177.  
  178.  
  179. local void handler(s)
  180. int s;                  /* signal number (ignored) */
  181. /* Upon getting a user interrupt, turn echo back on for tty and abort
  182.    cleanly using err(). */
  183. {
  184. #ifndef MSVMS
  185. #ifndef EXPORT
  186.   echon();
  187. #endif /* !EXPORT */
  188.   putc('\n', stderr);
  189. #endif /* !MSVMS */
  190.   err(ZE_ABORT, "aborting");
  191.   s++;                                  /* keep some compilers happy */
  192. }
  193.  
  194.  
  195. void warn(a, b)
  196. char *a, *b;            /* message strings juxtaposed in output */
  197. /* Print a warning message to stderr and return. */
  198. {
  199.   fprintf(stderr, "zip warning: %s%s\n", a, b);
  200. }
  201.  
  202.  
  203. local void license()
  204. /* Print license information to stdout. */
  205. {
  206.   extent i;             /* counter for copyright array */
  207.  
  208.   for (i = 0; i < sizeof(copyright)/sizeof(char *); i++)
  209.     puts(copyright[i]);
  210.   for (i = 0; i < sizeof(disclaimer)/sizeof(char *); i++)
  211.     puts(disclaimer[i]);
  212. }
  213.  
  214.  
  215. local void help()
  216. /* Print help (along with license info) to stdout. */
  217. {
  218.   extent i;             /* counter for help array */
  219.  
  220.   /* help array */
  221.   static char *text[] = {
  222. "",
  223. "Zip %d.%d (%s)",
  224. "Usage:  zip [-options] [-b path] [-t mmddyy] zipfile list [-x list]",
  225. "  the default action is to add or replace zipfile entries from list, which",
  226. "  can include the special name - to read names from stdin.",
  227. "  -f   freshen: only changed files  -u   update: only changed or new files",
  228. "  -d   delete entries in zipfile    -m   move into zipfile (delete files)",
  229. "  -k   simulate PKZIP made zipfile  -g   allow growing existing zipfile",
  230. "  -h   show this help               -l   show software license",
  231. "  -r   recurse into directories     -j   junk (don't record) directory names",
  232. "  -i   implode only                 -s   shrink only",
  233. "  -0   compress faster              -9   compress better",
  234. "  -q   quiet operation              -n   don't compress special suffixes",
  235. "  -c   add one-line comments        -z   add zipfile comment",
  236. "  -b   use \"path\" for temp files    -t   only do files after \"mmddyy\"",
  237. #ifdef EXPORT
  238. "  -o   make zipfile as old as latest entry",
  239. #else /* !EXPORT */
  240. "  -e   encrypt  (-ee verify key)    -o   make zipfile as old as latest entry",
  241. #endif /* ?EXPORT */
  242. #ifdef VMS
  243. "  -w   append the VMS version number to the name stored in the zip file",
  244. #endif /* VMS */
  245. #ifdef S_IFLNK
  246. "  -y   store symbolic links as the link instead of the referenced file",
  247. #endif /* !S_IFLNK */
  248. "  -x   exclude the names that follow from those operated on"
  249.   };
  250.  
  251.   for (i = 0; i < sizeof(copyright)/sizeof(char *); i++)
  252.     puts(copyright[i]);
  253.   for (i = 0; i < sizeof(text)/sizeof(char *); i++)
  254.   {
  255.     printf(text[i], REVISION / 10, REVISION % 10, REVDATE);
  256.     putchar('\n');
  257.   }
  258. }
  259.  
  260.  
  261. /* Do command line expansion for MSDOS and VMS */
  262. #ifdef MSVMS
  263. #  define PROCNAME(n) (action==ADD||action==UPDATE?wild(n):procname(n))
  264. #else /* !MSVMS */
  265. #  define PROCNAME(n) procname(n)
  266. #endif /* ?MSVMS */
  267.  
  268.  
  269. void main(argc, argv)
  270. int argc;               /* number of tokens in command line */
  271. char **argv;            /* command line tokens */
  272. /* Add, update, freshen, or delete zip entries in a zip file.  See the
  273.    command help in help() above. */
  274. {
  275.   int a;                /* attributes of zip file */
  276.   ulg c;                /* start of central directory */
  277.   int d;                /* true if just adding to a zip file */
  278.   char *e;              /* malloc'd comment buffer */
  279.   struct flist far *f;  /* steps through found linked list */
  280.   int i;                /* arg counter, root directory flag */
  281.   int k;                /* next argument type, marked counter,
  282.                            comment size, entry count */
  283.   ulg n;                /* total of entry len's */
  284.   int o;                /* true if there were any ZE_OPEN errors */
  285.   char *p;              /* steps through option arguments */
  286.   int r;                /* temporary variable */
  287.   ulg t;                /* file time, length of central directory */
  288.   struct zlist far *v;  /* temporary variable */
  289.   struct zlist far * far *w;    /* pointer to last link in zfiles list */
  290.   FILE *x, *y;          /* input and output zip files */
  291.   struct zlist far *z;  /* steps through zfiles linked list */
  292.  
  293.  
  294.   /* Process arguments */
  295.   diag("processing arguments");
  296.   if (argc == 1)
  297.   {
  298.     help();
  299.     exit(0);
  300.   }
  301.   zipfile = tempzip = NULL;
  302.   tempzf = NULL;
  303.   d = 0;                        /* disallow adding to a zip file */
  304. #ifndef WIN32
  305.   signal(SIGINT, handler);
  306.   signal(SIGTERM, handler);
  307. #endif
  308.   k = 0;                        /* Next non-option argument type */
  309.   for (i = 1; i < argc; i++)
  310.   {
  311.     if (argv[i][0] == '-')
  312.       if (argv[i][1])
  313.         for (p = argv[i]+1; *p; p++)
  314.           switch(*p)
  315.           {
  316.             case '0':  case '1':  case '2':  case '3':  case '4':
  317.             case '5':  case '6':  case '7':  case '8':  case '9':
  318.                         /* Set the compression efficacy */
  319.               level = *p - '0';  break;
  320.             case 'b':   /* Specify path for temporary file */
  321.               if (k != 0)
  322.                 err(ZE_PARMS, "use -b before zip file name");
  323.               else
  324.                 k = 1;          /* Next non-option is path */
  325.               break;
  326.             case 'c':   /* Add comments for new files in zip file */
  327.               comadd = 1;  break;
  328.             case 'd':   /* Delete files from zip file */
  329.               if (action != ADD)
  330.                 err(ZE_PARMS, "specify just one action");
  331.               action = DELETE;
  332.               break;
  333. #ifndef EXPORT
  334.             case 'e':   /* Encrypt */
  335.               e = key == NULL ? (char *)NULL : key;
  336.               if ((key = malloc(PWLEN+1)) == NULL)
  337.                 err(ZE_MEM, "was getting encryption password");
  338.               if (getp(e == NULL ? "Enter password: " : "Verify password: ",
  339.                        key, PWLEN+1) == NULL)
  340.                 err(ZE_PARMS, "stderr is not a tty");
  341.               if (e != NULL)
  342.               {
  343.                 r = strcmp(key, e);
  344.                 free((voidp *)e);
  345.                 if (r)
  346.                   err(ZE_PARMS, "password not verified");
  347.               }
  348.               break;
  349. #endif /* !EXPORT */
  350.             case 'f':   /* Freshen zip file--overwrite only */
  351.               if (action != ADD)
  352.                 err(ZE_PARMS, "specify just one action");
  353.               action = FRESHEN;
  354.               break;
  355.             case 'g':   /* Allow appending to a zip file */
  356.               d = 1;  break;
  357.             case 'h':   /* Help */
  358.               help();  break;
  359.             case 'i':   /* Implode only */
  360.               method = IMPLODE;  break;
  361.             case 'j':   /* Junk directory names */
  362.               pathput = 0;  break;
  363.             case 'k':   /* Make entries using DOS names (k for Katz) */
  364.               dosify = 2;  break;
  365.             case 'l':   /* Show license, version */
  366.               license();  break;
  367.             case 'm':   /* Delete files added or updated in zip file */
  368.               dispose = 1;  break;
  369.             case 'n':   /* Don't compress files with a special suffix */
  370.               if ((special = getenv("NOZIP")) == NULL)
  371.                 special = ".Z:.zip:.zoo:.arc";
  372. #if !defined (OS2) && !defined(WIN32)
  373. #ifdef MSDOS
  374.               strupr(special);
  375. #endif /* MSDOS */
  376. #endif /* !OS2 */
  377.               break;
  378.             case 'o':   /* Set zip file time to time of latest file in it */
  379.               latest = 1;  break;
  380.             case 'p':   /* Store path with name */
  381.               break;            /* (do nothing as annoyance avoidance) */
  382.             case 'q':   /* Quiet operation */
  383.               noisy = 0;  break;
  384.             case 'r':   /* Recurse into subdirectories */
  385.               recurse = 1;  break;
  386.             case 's':   /* Shrink only */
  387.               method = SHRINK;  break;
  388.             case 't':   /* Exclude files earlier than specified date */
  389.               if (before)
  390.                 err(ZE_PARMS, "can only have one -t");
  391.               k = 2;  break;
  392.             case 'u':   /* Update zip file--overwrite only if newer */
  393.               if (action != ADD)
  394.                 err(ZE_PARMS, "specify just one action");
  395.               action = UPDATE;
  396.               break;
  397.             case 'v':   /* Mention oddities in zip file structure */
  398.               verbose = 1;
  399.               break;
  400. #ifdef VMS
  401.             case 'w':   /* Append the VMS version number */
  402.               vmsver = 1;  break;
  403. #endif /* VMS */
  404.             case 'x':   /* Exclude following files */
  405.               if (k != 4 &&
  406.                   (k != 3 || (action != UPDATE && action != FRESHEN)))
  407.                 err(ZE_PARMS, "nothing to exclude (-x) from");
  408.               if (k == 3)       /* must be -u or -f */
  409.                 for (z = zfiles; z != NULL; z = z->nxt)
  410.                   z->mark = 1;  /* mark all of them */
  411.               k = 5;
  412.               if ((r = exclude()) != ZE_OK)
  413.                 if (r == ZE_PARMS)
  414.                   err(r, "cannot repeat names in zip file");
  415.                 else
  416.                   err(r, "was processing list of files");
  417.               break;
  418. #ifdef S_IFLNK
  419.             case 'y':   /* Store symbolic links as such */
  420.               linkput = 1;  break;
  421. #endif /* !S_IFLNK */
  422.             case 'z':   /* Edit zip file comment */
  423.               zipedit = 1;  break;
  424.             default:
  425.             {
  426.               sprintf(errbuf, "no such option: %c", *p);
  427.               err(ZE_PARMS, errbuf);
  428.             }
  429.           }
  430.       else              /* just a dash */
  431.         if (k < 3)
  432.           err(ZE_PARMS, "zip file cannot be stdin");
  433.         else            /* read names from stdin */
  434.           while ((p = getnam(errbuf)) != NULL)
  435.           {
  436.             if ((r = PROCNAME(p)) != ZE_OK)
  437.               if (r == ZE_MISS)
  438.                 warn("name not matched: ", p);
  439.               else
  440.                 err(r, p);
  441.           }
  442.     else                /* not an option */
  443.     {
  444.       switch (k)
  445.       {
  446.         case 0:
  447.           if ((zipfile = ziptyp(argv[i])) == NULL)
  448.             err(ZE_MEM, "was processing arguments");
  449.           if ((r = readzipfile()) != ZE_OK)
  450.             err(r, zipfile);
  451.           found = NULL;
  452.           fnxt = &found;
  453.           k = 3;
  454.           break;
  455.         case 1:
  456.           if ((tempath = malloc(strlen(argv[i]) + 1)) == NULL)
  457.             err(ZE_MEM, "was processing arguments");
  458.           strcpy(tempath, argv[i]);
  459.           k = 0;
  460.           break;
  461.         case 2:
  462.         {
  463.           int yy, mm, dd;       /* results of sscanf() */
  464.  
  465.           if (sscanf(argv[i], "%2d%2d%2d", &mm, &dd, &yy) != 3 ||
  466.               mm < 1 || mm > 12 || dd < 1 || dd > 31)
  467.             err(ZE_PARMS, "invalid date entered for -t option");
  468.           before = dostime(yy + (yy < 80 ? 2000 : 1900), mm, dd, 0, 0, 0);
  469.           k = 0;
  470.           break;
  471.         }
  472.         case 3:  case 4:  case 5:
  473.           if ((r = PROCNAME(argv[i])) != ZE_OK)
  474.             if (r == ZE_MISS)
  475.               warn("name not matched: ", argv[i]);
  476.             else
  477.               err(r, argv[i]);
  478.           if (k == 3)
  479.             k = 4;
  480.       }
  481.     }
  482.   }
  483.   if (k < 3)
  484.     exit(0);                    /* No zip file, don't complain */
  485.   if (k != 5)                   /* Clean up selections */
  486.   {
  487.     if (k == 3 && (action == UPDATE || action == FRESHEN))
  488.       for (z = zfiles; z != NULL; z = z->nxt)
  489.         z->mark = 1;                    /* if -u or -f with no args, do all */
  490.     if ((r = exclude()) != ZE_OK)       /* remove duplicates in found list */
  491.       if (r == ZE_PARMS)
  492.         err(r, "cannot repeat names in zip file");
  493.       else
  494.         err(r, "was processing list of files");
  495.   }
  496.   if (zcount)
  497.     free((voidp *)zsort);
  498.  
  499.  
  500.   /* Check option combinations */
  501.   if (action == DELETE && (method != BEST || dispose || recurse ||
  502.       dosify || key != NULL || comadd || zipedit))
  503.     err(ZE_PARMS, "invalid option(s) used with -d");
  504.   if (linkput && dosify)
  505.     err(ZE_PARMS, "can't use -y with -k");
  506.  
  507.   /* If -b not specified, make temporary path the same as the zip file */
  508. #ifdef MSDOS
  509.   if (tempath == NULL && ((p = strrchr(zipfile, '/')) != NULL ||
  510.                           (p = strrchr(zipfile, '\\')) != NULL ||
  511.                           (p = strrchr(zipfile, ':')) != NULL))
  512.   {
  513.     if (*p == ':')
  514.       p++;
  515. #else /* !MSDOS */
  516.   if (tempath == NULL && (p = strrchr(zipfile, '/')) != NULL)
  517.   {
  518. #endif /* ?MSDOS */
  519.     if ((tempath = malloc((int)(p - zipfile) + 1)) == NULL)
  520.       err(ZE_MEM, "was processing arguments");
  521.     r = *p;  *p = 0;
  522.     strcpy(tempath, zipfile);
  523.     *p = (char)r;
  524.   }
  525.  
  526.   /* If under MSDOS, force entries to look like made by PKZIP */
  527. #ifndef OS2
  528. #ifdef MSDOS
  529.   dosify = 1;
  530. #endif /* MSDOS */
  531. #endif /* !OS2 */
  532.  
  533.  
  534.   /* For each marked entry, if not deleting, check if it exists, and if
  535.      updating or freshening, compare date with entry in old zip file.
  536.      Unmark if it doesn't exist or is too old, else update marked count. */
  537.   diag("stating marked entries");
  538.   k = 0;                        /* Initialize marked count */
  539.   for (z = zfiles; z != NULL; z = z->nxt)
  540.     if (z->mark)
  541.       if (action != DELETE &&
  542.                 ((t = filetime(z->name, (ulg *)NULL, (long *)NULL)) == 0 ||
  543.                  t < before ||
  544.                  ((action == UPDATE || action == FRESHEN) && t <= z->tim)))
  545.       {
  546.         z->mark = 0;
  547.         z->trash = t && t >= before;    /* delete if -um or -fm */
  548.         if (verbose)
  549.           printf("zip diagnostic: %s %s\n", z->name,
  550.                  z->trash ? "up to date" : "missing or early");
  551.       }
  552.       else
  553.         k++;
  554.  
  555.  
  556.   /* Remove entries from found list that do not exist or are too old */
  557.   diag("stating new entries");
  558.   for (f = found; f != NULL;)
  559.     if (action == DELETE || action == FRESHEN ||
  560.         (t = filetime(f->name, (ulg *)NULL, (long *)NULL)) == 0 ||
  561.         t < before || strcmp(f->name, zipfile) == 0)
  562.       f = fexpel(f);
  563.     else
  564.       f = f->nxt;
  565.  
  566.  
  567.   /* Make sure there's something left to do */
  568.   if (k == 0 && found == NULL && !(zfiles != NULL && (latest || zipedit)))
  569.     if (action == UPDATE || action == FRESHEN)
  570.       leave(ZE_OK);
  571.     else
  572.       err(ZE_NONE, zipfile);
  573.   d = (d && k == 0 && zfiles != NULL);  /* d true if just appending */
  574.  
  575.  
  576.   /* Before we get carried away, make sure zip file is writeable */
  577.   if ((x = fopen(zipfile, zfiles == NULL ? FOPW : FOPM)) == NULL)
  578.     err(ZE_CREAT, zipfile);
  579.   fclose(x);
  580.   a = getfileattr(zipfile);
  581.   if (zfiles == NULL)
  582.     destroy(zipfile);
  583.  
  584.  
  585.   /* Open zip file and temporary output file */
  586.   diag("opening zip file and creating temporary zip file");
  587.   x = NULL;
  588.   if (d)
  589.   {
  590.     if ((y = fopen(zipfile, FOPM)) == NULL)
  591.       err(ZE_NAME, zipfile);
  592.     tempzip = zipfile;
  593.     tempzf = y;
  594. #ifdef MSDOS
  595.     {
  596.       char *zipbuf;
  597.  
  598.       zipbuf = (char *)malloc(BSZ);
  599.       if (zipbuf == NULL)
  600.         err(ZE_MEM, tempzip);
  601.       setbuf(y, zipbuf);
  602.     }
  603. #endif /* MSDOS */
  604.     if (fseek(y, cenbeg, SEEK_SET))
  605.       err(ferror(y) ? ZE_READ : ZE_EOF, zipfile);
  606.   }
  607.   else
  608.   {
  609.     if (zfiles != NULL && (x = fopen(zipfile, FOPR)) == NULL)
  610.       err(ZE_NAME, zipfile);
  611.     if ((tempzip = tempname('Z')) == NULL)
  612.       err(ZE_MEM, tempzip);
  613.     if ((tempzf = y = fopen(tempzip, FOPW)) == NULL)
  614.       err(ZE_TEMP, tempzip);
  615.     if (zipbeg && (r = fcopy(x, y, zipbeg)) != ZE_OK)
  616.       err(r, r == ZE_TEMP ? tempzip : zipfile);
  617.   }
  618.   o = 0;                                /* no ZE_OPEN errors yet */
  619.  
  620.  
  621.   /* Process zip file, updating marked files */
  622.   if (zfiles != NULL)
  623.     diag("going through old zip file");
  624.   w = &zfiles;
  625.   while ((z = *w) != NULL)
  626.     if (z->mark)
  627.     {
  628.       /* if not deleting, zip it up */
  629.       if (action != DELETE)
  630.       {
  631.         if (noisy)
  632.         {
  633.           printf("updating %s", z->zname);
  634.           fflush(stdout);
  635.         }
  636.         if ((r = zipup(z, y)) != ZE_OK && r != ZE_OPEN)
  637.         {
  638.           if (noisy)
  639.           {
  640.             putchar('\n');
  641.             fflush(stdout);
  642.           }
  643.           sprintf(errbuf, "was zipping %s", z->name);
  644.           err(r, errbuf);
  645.         }
  646.         if (r == ZE_OPEN)
  647.         {
  648.           o = 1;
  649.           if (noisy)
  650.           {
  651.             putchar('\n');
  652.             fflush(stdout);
  653.           }
  654.           perror("zip warning");
  655.           warn("could not open for reading: ", z->name);
  656.           warn("will just copy entry over: ", z->zname);
  657.           if ((r = zipcopy(z, x, y)) != ZE_OK)
  658.           {
  659.             sprintf(errbuf, "was copying %s", z->zname);
  660.             err(r, errbuf);
  661.           }
  662.           z->mark = 0;
  663.         }
  664.         w = &z->nxt;
  665.       }
  666.       else
  667.       {
  668.         if (noisy)
  669.         {
  670.           printf("deleting %s\n", z->zname);
  671.           fflush(stdout);
  672.         }
  673.         v = z->nxt;                     /* delete entry from list */
  674.         free((voidp *)(z->name));
  675.         free((voidp *)(z->zname));
  676.         if (z->ext)
  677.           free((voidp *)(z->extra));
  678.         if (z->cext && z->cextra != z->extra)
  679.           free((voidp *)(z->cextra));
  680.         if (z->com)
  681.           free((voidp *)(z->comment));
  682.         farfree((voidp far *)z);
  683.         *w = v;
  684.         zcount--;
  685.       }
  686.     }
  687.     else
  688.     {
  689.       /* copy the original entry verbatim */
  690.       if (!d && (r = zipcopy(z, x, y)) != ZE_OK)
  691.       {
  692.         sprintf(errbuf, "was copying %s", z->zname);
  693.         err(r, errbuf);
  694.       }
  695.       w = &z->nxt;
  696.     }
  697.   if (x != NULL)
  698.     fclose(x);
  699.  
  700.  
  701.   /* Process the edited found list, adding them to the zip file */
  702.   diag("zipping up new entries, if any");
  703.   for (f = found; f != NULL; f = fexpel(f))
  704.   {
  705.     /* add a new zfiles entry and set the name */
  706.     if ((z = (struct zlist far *)farmalloc(sizeof(struct zlist))) == NULL)
  707.       err(ZE_MEM, "was adding files to zip file");
  708.     z->nxt = NULL;
  709.     z->name = f->name;
  710.     f->name = NULL;
  711.     z->zname = f->zname;
  712.     f->zname = NULL;
  713.     z->ext = z->cext = z->com = 0;
  714.     z->mark = 1;
  715.     /* zip it up */
  716.     if (noisy)
  717.     {
  718.       printf("adding %s", z->zname);
  719.       fflush(stdout);
  720.     }
  721.     if ((r = zipup(z, y)) != ZE_OK  && r != ZE_OPEN)
  722.     {
  723.       if (noisy)
  724.       {
  725.         putchar('\n');
  726.         fflush(stdout);
  727.       }
  728.       sprintf(errbuf, "was zipping %s", z->name);
  729.       err(r, errbuf);
  730.     }
  731.     if (r == ZE_OPEN)
  732.     {
  733.       o = 1;
  734.       if (noisy)
  735.       {
  736.         putchar('\n');
  737.         fflush(stdout);
  738.       }
  739.       perror("zip warning");
  740.       warn("could not open for reading: ", z->name);
  741.       free((voidp *)(z->name));
  742.       free((voidp *)(z->zname));
  743.       farfree((voidp far *)z);
  744.     }
  745.     else
  746.     {
  747.       *w = z;
  748.       w = &z->nxt;
  749.       zcount++;
  750.     }
  751.   }
  752.   if (key != NULL)
  753.   {
  754.     free((voidp *)key);
  755.     key = NULL;
  756.   }
  757.  
  758.  
  759.   /* Get one line comment for each new entry */
  760.   if (comadd)
  761.   {
  762.     if ((e = malloc(MAXCOM + 1)) == NULL)
  763.       err(ZE_MEM, "was reading comment lines");
  764.     for (z = zfiles; z != NULL; z = z->nxt)
  765.       if (z->mark)
  766.       {
  767.         if (noisy)
  768.           printf("Enter comment for %s:\n", z->name);
  769.         if (fgets(e, MAXCOM+1, stdin) != NULL)
  770.         {
  771.           if ((p = malloc((k = strlen(e))+1)) == NULL)
  772.           {
  773.             free((voidp *)e);
  774.             err(ZE_MEM, "was reading comment lines");
  775.           }
  776.           strcpy(p, e);
  777.           if (p[k-1] == '\n')
  778.             p[--k] = 0;
  779.           z->comment = p;
  780.           z->com = k;
  781.         }
  782.       }
  783.     free((voidp *)e);
  784.   }
  785.  
  786.   /* Get multi-line comment for the zip file */
  787.   if (zipedit)
  788.   {
  789.     if ((e = malloc(MAXCOM + 1)) == NULL)
  790.       err(ZE_MEM, "was reading comment lines");
  791.     if (noisy && zcomlen)
  792.     {
  793.       puts("current zip file comment is:");
  794.       fwrite(zcomment, 1, zcomlen, stdout);
  795.       if (zcomment[zcomlen-1] != '\n')
  796.         putchar('\n');
  797.       free((voidp *)zcomment);
  798.     }
  799.     zcomment = malloc(1);
  800.     *zcomment = 0;
  801.     if (noisy)
  802.       puts("enter new zip file comment (end with .):");
  803.     while (fgets(e, MAXCOM+1, stdin) != NULL && strcmp(e, ".\n"))
  804.     {
  805.       if (e[(r = strlen(e)) - 1] == '\n')
  806.         e[--r] = 0;
  807.       if ((p = malloc((*zcomment ? strlen(zcomment) + 3 : 1) + r)) == NULL)
  808.       {
  809.         free((voidp *)e);
  810.         err(ZE_MEM, "was reading comment lines");
  811.       }
  812.       if (*zcomment)
  813.         strcat(strcat(strcpy(p, zcomment), "\r\n"), e);
  814.       else
  815.         strcpy(p, *e ? e : "\r\n");
  816.       free((voidp *)zcomment);
  817.       zcomment = p;
  818.     }
  819.     zcomlen = strlen(zcomment);
  820.     free((voidp *)e);
  821.   }
  822.  
  823.  
  824.   /* Write central directory and end header to temporary zip */
  825.   diag("writing central directory");
  826.   k = 0;                        /* keep count for end header */
  827.   if ((c = ftell(y)) == -1L)    /* get start of central */
  828.     err(d ? ZE_WRITE : ZE_TEMP, tempzip);
  829.   n = t = 0;
  830.   for (z = zfiles; z != NULL; z = z->nxt)
  831.   {
  832.     if ((r = putcentral(z, y)) != ZE_OK)
  833.       err(r, tempzip);
  834.     n += z->len;
  835.     t += z->siz;
  836.     k++;
  837.   }
  838.   if (k == 0)
  839.     warn("zip file empty", "");
  840.   if (verbose)
  841.     printf("total bytes=%lu, compressed=%lu -> %d%% savings\n",
  842.            n, t, percent(n, t));
  843.   if ((t = ftell(y)) == -1L)    /* get end of central */
  844.     err(d ? ZE_WRITE : ZE_TEMP, tempzip);
  845.   t -= c;                       /* compute length of central */
  846.   diag("writing end of central directory");
  847.   if ((r = putend(k, t, c, zcomlen, zcomment, y)) != ZE_OK)
  848.     err(r, tempzip);
  849.   tempzf = NULL;
  850.   if (fclose(y))
  851.     err(d ? ZE_WRITE : ZE_TEMP, tempzip);
  852.  
  853.  
  854.   /* Replace old zip file with new zip file, leaving only the new one */
  855.   if (!d)
  856.   {
  857.     diag("replacing old zip file with new zip file");
  858.     if ((r = replace(zipfile, tempzip)) != ZE_OK)
  859.     {
  860.       warn("new zip file left as: ", tempzip);
  861.       free((voidp *)tempzip);
  862.       tempzip = NULL;
  863.       err(r, "was replacing the original zip file");
  864.     }
  865.     free((voidp *)tempzip);
  866.   }
  867.   tempzip = NULL;
  868.   setfileattr(zipfile, a);
  869.  
  870.   /* Finish up (process -o, -m, clean up).  Exit code depends on o. */
  871.   leave(o ? ZE_OPEN : ZE_OK);
  872. }
  873.