1 /*
2   unix/unix.c - Zip 3
3 
4   Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.
5 
6   See the accompanying file LICENSE, version 2007-Mar-4 or later
7   (the contents of which are also included in zip.h) for terms of use.
8   If, for some reason, all these files are missing, the Info-ZIP license
9   also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
10 */
11 #include "zip.h"
12 
13 #ifndef UTIL    /* the companion #endif is a bit of ways down ... */
14 
15 #include <time.h>
16 
17 #if defined(MINIX) || defined(__mpexl)
18 #  ifdef S_IWRITE
19 #    undef S_IWRITE
20 #  endif /* S_IWRITE */
21 #  define S_IWRITE S_IWUSR
22 #endif /* MINIX */
23 
24 #if (!defined(S_IWRITE) && defined(S_IWUSR))
25 #  define S_IWRITE S_IWUSR
26 #endif
27 
28 #if defined(HAVE_DIRENT_H) || defined(_POSIX_VERSION)
29 #  include <dirent.h>
30 #else /* !HAVE_DIRENT_H */
31 #  ifdef HAVE_NDIR_H
32 #    include <ndir.h>
33 #  endif /* HAVE_NDIR_H */
34 #  ifdef HAVE_SYS_NDIR_H
35 #    include <sys/ndir.h>
36 #  endif /* HAVE_SYS_NDIR_H */
37 #  ifdef HAVE_SYS_DIR_H
38 #    include <sys/dir.h>
39 #  endif /* HAVE_SYS_DIR_H */
40 #  ifndef dirent
41 #    define dirent direct
42 #  endif
43 #endif /* HAVE_DIRENT_H || _POSIX_VERSION */
44 
45 #define PAD 0
46 #define PATH_END '/'
47 
48 /* Library functions not in (most) header files */
49 
50 #ifdef _POSIX_VERSION
51 #  include <utime.h>
52 #else
53    int utime OF((char *, time_t *));
54 #endif
55 
56 extern char *label;
57 local ulg label_time = 0;
58 local ulg label_mode = 0;
59 local time_t label_utim = 0;
60 
61 /* Local functions */
62 local char *readd OF((DIR *));
63 
64 
65 #ifdef NO_DIR                    /* for AT&T 3B1 */
66 #include <sys/dir.h>
67 #ifndef dirent
68 #  define dirent direct
69 #endif
70 typedef FILE DIR;
71 /*
72 **  Apparently originally by Rich Salz.
73 **  Cleaned up and modified by James W. Birdsall.
74 */
75 
76 #define opendir(path) fopen(path, "r")
77 
readdir(dirp)78 struct dirent *readdir(dirp)
79 DIR *dirp;
80 {
81   static struct dirent entry;
82 
83   if (dirp == NULL)
84     return NULL;
85   for (;;)
86     if (fread (&entry, sizeof (struct dirent), 1, dirp) == 0)
87       return NULL;
88     else if (entry.d_ino)
89       return (&entry);
90 } /* end of readdir() */
91 
92 #define closedir(dirp) fclose(dirp)
93 #endif /* NO_DIR */
94 
95 
readd(d)96 local char *readd(d)
97 DIR *d;                 /* directory stream to read from */
98 /* Return a pointer to the next name in the directory stream d, or NULL if
99    no more entries or an error occurs. */
100 {
101   struct dirent *e;
102 
103   e = readdir(d);
104   return e == NULL ? (char *) NULL : e->d_name;
105 }
106 
procname(n,caseflag)107 int procname(n, caseflag)
108 char *n;                /* name to process */
109 int caseflag;           /* true to force case-sensitive match */
110 /* Process a name or sh expression to operate on (or exclude).  Return
111    an error code in the ZE_ class. */
112 {
113   char *a;              /* path and name for recursion */
114   DIR *d;               /* directory stream from opendir() */
115   char *e;              /* pointer to name from readd() */
116   int m;                /* matched flag */
117   char *p;              /* path for recursion */
118   z_stat s;             /* result of stat() */
119   struct zlist far *z;  /* steps through zfiles list */
120 
121   if (strcmp(n, "-") == 0)   /* if compressing stdin */
122     return newname(n, 0, caseflag);
123   else if (LSSTAT(n, &s))
124   {
125     /* Not a file or directory--search for shell expression in zip file */
126     p = ex2in(n, 0, (int *)NULL);       /* shouldn't affect matching chars */
127     m = 1;
128     for (z = zfiles; z != NULL; z = z->nxt) {
129       if (MATCH(p, z->iname, caseflag))
130       {
131         z->mark = pcount ? filter(z->zname, caseflag) : 1;
132         if (verbose)
133             fprintf(mesg, "zip diagnostic: %scluding %s\n",
134                z->mark ? "in" : "ex", z->name);
135         m = 0;
136       }
137     }
138     free((zvoid *)p);
139     return m ? ZE_MISS : ZE_OK;
140   }
141 
142   /* Live name--use if file, recurse if directory */
143 #ifdef OS390
144   if (S_ISREG(s.st_mode) || S_ISLNK(s.st_mode))
145 #else
146 #  ifdef S_IFLNK
147   if ((s.st_mode & S_IFREG) == S_IFREG || (s.st_mode & S_IFLNK) == S_IFLNK)
148 #  else
149   if ((s.st_mode & S_IFREG) == S_IFREG)
150 #  endif
151 #endif
152   {
153     /* add or remove name of file */
154     if ((m = newname(n, 0, caseflag)) != ZE_OK)
155       return m;
156   }
157 #ifdef OS390
158   else if (S_ISDIR(s.st_mode))
159 #else
160   else if ((s.st_mode & S_IFDIR) == S_IFDIR)
161 #endif
162   {
163     /* Add trailing / to the directory name */
164     if ((p = malloc(strlen(n)+2)) == NULL)
165       return ZE_MEM;
166     if (strcmp(n, ".") == 0) {
167       *p = '\0';  /* avoid "./" prefix and do not create zip entry */
168     } else {
169       strcpy(p, n);
170       a = p + strlen(p);
171       if (a[-1] != '/')
172         strcpy(a, "/");
173       if (dirnames && (m = newname(p, 1, caseflag)) != ZE_OK) {
174         free((zvoid *)p);
175         return m;
176       }
177     }
178     /* recurse into directory */
179     if (recurse && (d = opendir(n)) != NULL)
180     {
181       while ((e = readd(d)) != NULL) {
182         if (strcmp(e, ".") && strcmp(e, ".."))
183         {
184           if ((a = malloc(strlen(p) + strlen(e) + 1)) == NULL)
185           {
186             closedir(d);
187             free((zvoid *)p);
188             return ZE_MEM;
189           }
190           strcat(strcpy(a, p), e);
191           if ((m = procname(a, caseflag)) != ZE_OK)   /* recurse on name */
192           {
193             if (m == ZE_MISS)
194               zipwarn("name not matched: ", a);
195             else
196               ziperr(m, a);
197           }
198           free((zvoid *)a);
199         }
200       }
201       closedir(d);
202     }
203     free((zvoid *)p);
204   } /* (s.st_mode & S_IFDIR) */
205 #ifdef OS390
206   else if (S_ISFIFO(s.st_mode))
207 #else
208   else if ((s.st_mode & S_IFIFO) == S_IFIFO)
209 #endif
210   {
211     if (allow_fifo) {
212       /* FIFO (Named Pipe) - handle as normal file */
213       /* add or remove name of FIFO */
214       /* zip will stop if FIFO is open and wait for pipe to be fed and closed */
215       if (noisy) zipwarn("Reading FIFO (Named Pipe): ", n);
216       if ((m = newname(n, 0, caseflag)) != ZE_OK)
217         return m;
218     } else {
219       zipwarn("ignoring FIFO (Named Pipe) - use -FI to read: ", n);
220       return ZE_OK;
221     }
222   } /* S_IFIFO */
223   else
224     zipwarn("ignoring special file: ", n);
225   return ZE_OK;
226 }
227 
ex2in(x,isdir,pdosflag)228 char *ex2in(x, isdir, pdosflag)
229 char *x;                /* external file name */
230 int isdir;              /* input: x is a directory */
231 int *pdosflag;          /* output: force MSDOS file attributes? */
232 /* Convert the external file name to a zip file name, returning the malloc'ed
233    string or NULL if not enough memory. */
234 {
235   char *n;              /* internal file name (malloc'ed) */
236   char *t = NULL;       /* shortened name */
237   int dosflag;
238 
239   dosflag = dosify;     /* default for non-DOS and non-OS/2 */
240 
241   /* Find starting point in name before doing malloc */
242   /* Strip "//host/share/" part of a UNC name */
243   if (!strncmp(x,"//",2) && (x[2] != '\0' && x[2] != '/')) {
244     n = x + 2;
245     while (*n != '\0' && *n != '/')
246       n++;              /* strip host name */
247     if (*n != '\0') {
248       n++;
249       while (*n != '\0' && *n != '/')
250         n++;            /* strip `share' name */
251     }
252     if (*n != '\0')
253       t = n + 1;
254   } else
255       t = x;
256   while (*t == '/')
257     t++;                /* strip leading '/' chars to get a relative path */
258   while (*t == '.' && t[1] == '/')
259     t += 2;             /* strip redundant leading "./" sections */
260 
261   /* Make changes, if any, to the copied name (leave original intact) */
262   if (!pathput)
263     t = last(t, PATH_END);
264 
265   /* Malloc space for internal name and copy it */
266   if ((n = malloc(strlen(t) + 1)) == NULL)
267     return NULL;
268   strcpy(n, t);
269 
270   if (dosify)
271     msname(n);
272 
273 #ifdef EBCDIC
274   strtoasc(n, n);       /* here because msname() needs native coding */
275 #endif
276 
277   /* Returned malloc'ed name */
278   if (pdosflag)
279     *pdosflag = dosflag;
280 
281   if (isdir) return n;  /* avoid warning on unused variable */
282   return n;
283 }
284 
in2ex(n)285 char *in2ex(n)
286 char *n;                /* internal file name */
287 /* Convert the zip file name to an external file name, returning the malloc'ed
288    string or NULL if not enough memory. */
289 {
290   char *x;              /* external file name */
291 
292   if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)
293     return NULL;
294 #ifdef EBCDIC
295   strtoebc(x, n);
296 #else
297   strcpy(x, n);
298 #endif
299   return x;
300 }
301 
302 /*
303  * XXX use ztimbuf in both POSIX and non POSIX cases ?
304  */
stamp(f,d)305 void stamp(f, d)
306 char *f;                /* name of file to change */
307 ulg d;                  /* dos-style time to change it to */
308 /* Set last updated and accessed time of file f to the DOS time d. */
309 {
310 #ifdef _POSIX_VERSION
311   struct utimbuf u;     /* argument for utime()  const ?? */
312 #else
313   time_t u[2];          /* argument for utime() */
314 #endif
315 
316   /* Convert DOS time to time_t format in u */
317 #ifdef _POSIX_VERSION
318   u.actime = u.modtime = dos2unixtime(d);
319   utime(f, &u);
320 #else
321   u[0] = u[1] = dos2unixtime(d);
322   utime(f, u);
323 #endif
324 
325 }
326 
filetime(f,a,n,t)327 ulg filetime(f, a, n, t)
328   char *f;                /* name of file to get info on */
329   ulg *a;                 /* return value: file attributes */
330   zoff_t *n;              /* return value: file size */
331   iztimes *t;             /* return value: access, modific. and creation times */
332 /* If file *f does not exist, return 0.  Else, return the file's last
333    modified date and time as an MSDOS date and time.  The date and
334    time is returned in a long with the date most significant to allow
335    unsigned integer comparison of absolute times.  Also, if a is not
336    a NULL pointer, store the file attributes there, with the high two
337    bytes being the Unix attributes, and the low byte being a mapping
338    of that to DOS attributes.  If n is not NULL, store the file size
339    there.  If t is not NULL, the file's access, modification and creation
340    times are stored there as UNIX time_t values.
341    If f is "-", use standard input as the file. If f is a device, return
342    a file size of -1 */
343 {
344   z_stat s;         /* results of stat() */
345   /* converted to pointer from using FNMAX - 11/8/04 EG */
346   char *name;
347   int len = strlen(f);
348 
349   if (f == label) {
350     if (a != NULL)
351       *a = label_mode;
352     if (n != NULL)
353       *n = -2L; /* convention for a label name */
354     if (t != NULL)
355       t->atime = t->mtime = t->ctime = label_utim;
356     return label_time;
357   }
358   if ((name = malloc(len + 1)) == NULL) {
359     ZIPERR(ZE_MEM, "filetime");
360   }
361   strcpy(name, f);
362   if (name[len - 1] == '/')
363     name[len - 1] = '\0';
364   /* not all systems allow stat'ing a file with / appended */
365   if (strcmp(f, "-") == 0) {
366     if (zfstat(fileno(stdin), &s) != 0) {
367       free(name);
368       error("fstat(stdin)");
369     }
370   }
371   else if (LSSTAT(name, &s) != 0) {
372     /* Accept about any file kind including directories
373      * (stored with trailing / with -r option)
374      */
375     free(name);
376     return 0;
377   }
378   free(name);
379 
380   if (a != NULL) {
381 #ifndef OS390
382     *a = ((ulg)s.st_mode << 16) | !(s.st_mode & S_IWRITE);
383 #else
384 /*
385 **  The following defines are copied from the unizip source and represent the
386 **  legacy Unix mode flags.  These fixed bit masks are no longer required
387 **  by XOPEN standards - the S_IS### macros being the new recommended method.
388 **  The approach here of setting the legacy flags by testing the macros should
389 **  work under any _XOPEN_SOURCE environment (and will just rebuild the same bit
390 **  mask), but is required if the legacy bit flags differ from legacy Unix.
391 */
392 #define UNX_IFDIR      0040000     /* Unix directory */
393 #define UNX_IFREG      0100000     /* Unix regular file */
394 #define UNX_IFSOCK     0140000     /* Unix socket (BSD, not SysV or Amiga) */
395 #define UNX_IFLNK      0120000     /* Unix symbolic link (not SysV, Amiga) */
396 #define UNX_IFBLK      0060000     /* Unix block special       (not Amiga) */
397 #define UNX_IFCHR      0020000     /* Unix character special   (not Amiga) */
398 #define UNX_IFIFO      0010000     /* Unix fifo    (BCC, not MSC or Amiga) */
399     {
400     mode_t legacy_modes;
401 
402     /* Initialize with permission bits--which are not implementation-optional */
403     legacy_modes = s.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX);
404     if (S_ISDIR(s.st_mode))
405       legacy_modes |= UNX_IFDIR;
406     if (S_ISREG(s.st_mode))
407       legacy_modes |= UNX_IFREG;
408     if (S_ISLNK(s.st_mode))
409       legacy_modes |= UNX_IFLNK;
410     if (S_ISBLK(s.st_mode))
411       legacy_modes |= UNX_IFBLK;
412     if (S_ISCHR(s.st_mode))
413       legacy_modes |= UNX_IFCHR;
414     if (S_ISFIFO(s.st_mode))
415       legacy_modes |= UNX_IFIFO;
416     if (S_ISSOCK(s.st_mode))
417       legacy_modes |= UNX_IFSOCK;
418     *a = ((ulg)legacy_modes << 16) | !(s.st_mode & S_IWRITE);
419     }
420 #endif
421     if ((s.st_mode & S_IFMT) == S_IFDIR) {
422       *a |= MSDOS_DIR_ATTR;
423     }
424   }
425   if (n != NULL)
426     *n = (s.st_mode & S_IFMT) == S_IFREG ? s.st_size : -1L;
427   if (t != NULL) {
428     t->atime = s.st_atime;
429     t->mtime = s.st_mtime;
430     t->ctime = t->mtime;   /* best guess, (s.st_ctime: last status change!!) */
431   }
432   return unix2dostime(&s.st_mtime);
433 }
434 
435 
436 #ifndef QLZIP /* QLZIP Unix2QDOS cross-Zip supplies an extended variant */
437 
set_new_unix_extra_field(z,s)438 int set_new_unix_extra_field(z, s)
439   struct zlist far *z;
440   z_stat *s;
441   /* New unix extra field.
442      Currently only UIDs and GIDs are stored. */
443 {
444   int uid_size;
445   int gid_size;
446   int ef_data_size;
447   char *extra;
448   char *cextra;
449   ulg id;
450   int b;
451 
452   uid_size = sizeof(s->st_uid);
453   gid_size = sizeof(s->st_gid);
454 
455 /* New extra field
456    tag       (2 bytes)
457    size      (2 bytes)
458    version   (1 byte)
459    uid_size  (1 byte - size in bytes)
460    uid       (variable)
461    gid_size  (1 byte - size in bytes)
462    gid       (variable)
463  */
464 
465   ef_data_size = 1 + 1 + uid_size + 1 + gid_size;
466 
467   if ((extra = (char *)malloc(z->ext + 4 + ef_data_size)) == NULL)
468     return ZE_MEM;
469   if ((cextra = (char *)malloc(z->ext + 4 + ef_data_size)) == NULL)
470     return ZE_MEM;
471 
472   if (z->ext)
473     memcpy(extra, z->extra, z->ext);
474   if (z->cext)
475     memcpy(cextra, z->cextra, z->cext);
476 
477   free(z->extra);
478   z->extra = extra;
479   free(z->cextra);
480   z->cextra = cextra;
481 
482   z->extra[z->ext + 0] = 'u';
483   z->extra[z->ext + 1] = 'x';
484   z->extra[z->ext + 2] = (char)ef_data_size;     /* length of data part */
485   z->extra[z->ext + 3] = 0;
486   z->extra[z->ext + 4] = 1;                      /* version */
487 
488   /* UID */
489   z->extra[z->ext + 5] = (char)(uid_size);       /* uid size in bytes */
490   b = 6;
491   id = (ulg)(s->st_uid);
492   z->extra[z->ext + b] = (char)(id & 0xFF);
493   if (uid_size > 1) {
494     b++;
495     id = id >> 8;
496     z->extra[z->ext + b] = (char)(id & 0xFF);
497     if (uid_size > 2) {
498       b++;
499       id = id >> 8;
500       z->extra[z->ext + b] = (char)(id & 0xFF);
501       b++;
502       id = id >> 8;
503       z->extra[z->ext + b] = (char)(id & 0xFF);
504       if (uid_size == 8) {
505         b++;
506         id = id >> 8;
507         z->extra[z->ext + b] = (char)(id & 0xFF);
508         b++;
509         id = id >> 8;
510         z->extra[z->ext + b] = (char)(id & 0xFF);
511         b++;
512         id = id >> 8;
513         z->extra[z->ext + b] = (char)(id & 0xFF);
514         b++;
515         id = id >> 8;
516         z->extra[z->ext + b] = (char)(id & 0xFF);
517       }
518     }
519   }
520 
521   /* GID */
522   b++;
523   z->extra[z->ext + b] = (char)(gid_size);       /* gid size in bytes */
524   b++;
525   id = (ulg)(s->st_gid);
526   z->extra[z->ext + b] = (char)(id & 0xFF);
527   if (gid_size > 1) {
528     b++;
529     id = id >> 8;
530     z->extra[z->ext + b] = (char)(id & 0xFF);
531     if (gid_size > 2) {
532       b++;
533       id = id >> 8;
534       z->extra[z->ext + b] = (char)(id & 0xFF);
535       b++;
536       id = id >> 8;
537       z->extra[z->ext + b] = (char)(id & 0xFF);
538       if (gid_size == 8) {
539         b++;
540         id = id >> 8;
541         z->extra[z->ext + b] = (char)(id & 0xFF);
542         b++;
543         id = id >> 8;
544         z->extra[z->ext + b] = (char)(id & 0xFF);
545         b++;
546         id = id >> 8;
547         z->extra[z->ext + b] = (char)(id & 0xFF);
548         b++;
549         id = id >> 8;
550         z->extra[z->ext + b] = (char)(id & 0xFF);
551       }
552     }
553   }
554 
555   /* copy local extra field to central directory extra field */
556   memcpy((z->cextra) + z->cext, (z->extra) + z->ext, 4 + ef_data_size);
557 
558   z->ext = z->ext + 4 + ef_data_size;
559   z->cext = z->cext + 4 + ef_data_size;
560 
561   return ZE_OK;
562 }
563 
564 
set_extra_field(z,z_utim)565 int set_extra_field(z, z_utim)
566   struct zlist far *z;
567   iztimes *z_utim;
568   /* store full data in local header but just modification time stamp info
569      in central header */
570 {
571   z_stat s;
572   char *name;
573   int len = strlen(z->name);
574 
575   /* For the full sized UT local field including the UID/GID fields, we
576    * have to stat the file again. */
577 
578   if ((name = malloc(len + 1)) == NULL) {
579     ZIPERR(ZE_MEM, "set_extra_field");
580   }
581   strcpy(name, z->name);
582   if (name[len - 1] == '/')
583     name[len - 1] = '\0';
584   /* not all systems allow stat'ing a file with / appended */
585   if (LSSTAT(name, &s)) {
586     free(name);
587     return ZE_OPEN;
588   }
589   free(name);
590 
591 #define EB_L_UT_SIZE    (EB_HEADSIZE + EB_UT_LEN(2))
592 #define EB_C_UT_SIZE    (EB_HEADSIZE + EB_UT_LEN(1))
593 
594 /* The flag UIDGID_NOT_16BIT should be set by the pre-compile configuration
595    script when it detects st_uid or st_gid sizes differing from 16-bit.
596  */
597 #ifndef UIDGID_NOT_16BIT
598   /* The following "second-level" check for st_uid and st_gid members being
599      16-bit wide is only added as a safety precaution in case the "first-level"
600      check failed to define the UIDGID_NOT_16BIT symbol.
601      The first-level check should have been implemented in the automatic
602      compile configuration process.
603    */
604 # ifdef UIDGID_ARE_16B
605 #  undef UIDGID_ARE_16B
606 # endif
607   /* The following expression is a compile-time constant and should (hopefully)
608      get optimized away by any sufficiently intelligent compiler!
609    */
610 # define UIDGID_ARE_16B  (sizeof(s.st_uid) == 2 && sizeof(s.st_gid) == 2)
611 
612 # define EB_L_UX2_SIZE   (EB_HEADSIZE + EB_UX2_MINLEN)
613 # define EB_C_UX2_SIZE   EB_HEADSIZE
614 # define EF_L_UNIX_SIZE  (EB_L_UT_SIZE + (UIDGID_ARE_16B ? EB_L_UX2_SIZE : 0))
615 # define EF_C_UNIX_SIZE  (EB_C_UT_SIZE + (UIDGID_ARE_16B ? EB_C_UX2_SIZE : 0))
616 #else
617 # define EF_L_UNIX_SIZE EB_L_UT_SIZE
618 # define EF_C_UNIX_SIZE EB_C_UT_SIZE
619 #endif /* !UIDGID_NOT_16BIT */
620 
621   if ((z->extra = (char *)malloc(EF_L_UNIX_SIZE)) == NULL)
622     return ZE_MEM;
623   if ((z->cextra = (char *)malloc(EF_C_UNIX_SIZE)) == NULL)
624     return ZE_MEM;
625 
626   z->extra[0]  = 'U';
627   z->extra[1]  = 'T';
628   z->extra[2]  = (char)EB_UT_LEN(2);    /* length of data part of local e.f. */
629   z->extra[3]  = 0;
630   z->extra[4]  = EB_UT_FL_MTIME | EB_UT_FL_ATIME;    /* st_ctime != creation */
631   z->extra[5]  = (char)(s.st_mtime);
632   z->extra[6]  = (char)(s.st_mtime >> 8);
633   z->extra[7]  = (char)(s.st_mtime >> 16);
634   z->extra[8]  = (char)(s.st_mtime >> 24);
635   z->extra[9]  = (char)(s.st_atime);
636   z->extra[10] = (char)(s.st_atime >> 8);
637   z->extra[11] = (char)(s.st_atime >> 16);
638   z->extra[12] = (char)(s.st_atime >> 24);
639 
640 #ifndef UIDGID_NOT_16BIT
641   /* Only store the UID and GID in the old Ux extra field if the runtime
642      system provides them in 16-bit wide variables.  */
643   if (UIDGID_ARE_16B) {
644     z->extra[13] = 'U';
645     z->extra[14] = 'x';
646     z->extra[15] = (char)EB_UX2_MINLEN; /* length of data part of local e.f. */
647     z->extra[16] = 0;
648     z->extra[17] = (char)(s.st_uid);
649     z->extra[18] = (char)(s.st_uid >> 8);
650     z->extra[19] = (char)(s.st_gid);
651     z->extra[20] = (char)(s.st_gid >> 8);
652   }
653 #endif /* !UIDGID_NOT_16BIT */
654 
655   z->ext = EF_L_UNIX_SIZE;
656 
657   memcpy(z->cextra, z->extra, EB_C_UT_SIZE);
658   z->cextra[EB_LEN] = (char)EB_UT_LEN(1);
659 #ifndef UIDGID_NOT_16BIT
660   if (UIDGID_ARE_16B) {
661     /* Copy header of Ux extra field from local to central */
662     memcpy(z->cextra+EB_C_UT_SIZE, z->extra+EB_L_UT_SIZE, EB_C_UX2_SIZE);
663     z->cextra[EB_LEN+EB_C_UT_SIZE] = 0;
664   }
665 #endif
666   z->cext = EF_C_UNIX_SIZE;
667 
668 #if 0  /* UID/GID presence is now signaled by central EF_IZUNIX2 field ! */
669   /* lower-middle external-attribute byte (unused until now):
670    *   high bit        => (have GMT mod/acc times) >>> NO LONGER USED! <<<
671    *   second-high bit => have Unix UID/GID info
672    * NOTE: The high bit was NEVER used in any official Info-ZIP release,
673    *       but its future use should be avoided (if possible), since it
674    *       was used as "GMT mod/acc times local extra field" flags in Zip beta
675    *       versions 2.0j up to 2.0v, for about 1.5 years.
676    */
677   z->atx |= 0x4000;
678 #endif /* never */
679 
680   /* new unix extra field */
681   set_new_unix_extra_field(z, &s);
682 
683   return ZE_OK;
684 }
685 
686 #endif /* !QLZIP */
687 
688 
deletedir(d)689 int deletedir(d)
690 char *d;                /* directory to delete */
691 /* Delete the directory *d if it is empty, do nothing otherwise.
692    Return the result of rmdir(), delete(), or system().
693    For VMS, d must be in format [x.y]z.dir;1  (not [x.y.z]).
694  */
695 {
696 # ifdef NO_RMDIR
697     /* code from Greg Roelofs, who horked it from Mark Edwards (unzip) */
698     int r, len;
699     char *s;              /* malloc'd string for system command */
700 
701     len = strlen(d);
702     if ((s = malloc(len + 34)) == NULL)
703       return 127;
704 
705     sprintf(s, "IFS=\" \t\n\" /bin/rmdir %s 2>/dev/null", d);
706     r = system(s);
707     free(s);
708     return r;
709 # else /* !NO_RMDIR */
710     return rmdir(d);
711 # endif /* ?NO_RMDIR */
712 }
713 
714 #endif /* !UTIL */
715 
716 
717 /******************************/
718 /*  Function version_local()  */
719 /******************************/
720 
721 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__386BSD__) || \
722     defined(__OpenBSD__) || defined(__bsdi__)
723 #include <sys/param.h> /* for the BSD define */
724 /* if we have something newer than NET/2 we'll use uname(3) */
725 #if (BSD > 199103)
726 #include <sys/utsname.h>
727 #endif /* BSD > 199103 */
728 #endif /* __{Net,Free,Open,386}BSD__ || __bsdi__ */
729 
version_local()730 void version_local()
731 {
732 #ifdef __GNUC__
733 #  ifdef NX_CURRENT_COMPILER_RELEASE
734     char compiler_name[80];
735 #  endif
736 #else
737 #  if (defined( __SUNPRO_C))
738     char compiler_name[33];
739 #  else
740 #    if (defined( __HP_cc) || defined( __IBMC__))
741     char compiler_name[33];
742 #    else
743 #      if (defined( __DECC_VER))
744     char compiler_name[33];
745     int compiler_typ;
746 #      else
747 #        if ((defined(CRAY) || defined(cray)) && defined(_RELEASE))
748     char compiler_name[40];
749 #        endif
750 #      endif
751 #    endif
752 #  endif
753 #endif
754 
755 #ifdef BSD
756 # if (BSD > 199103)
757     struct utsname u;
758     char os_name[40];
759 # else
760 # if defined(__NETBSD__))
761     static ZCONST char *netbsd[] = { "_ALPHA", "", "A", "B" };
762     char os_name[40];
763 # endif /* __NETBSD__ */
764 # endif /* BSD > 199103 */
765 #else /* !BSD */
766 #if ((defined(CRAY) || defined(cray)) && defined(_UNICOS))
767     char os_name[40];
768 #endif /* (CRAY && defined(_UNICOS)) */
769 #endif /* ?BSD */
770 
771 /* Define the compiler name and version string */
772 #ifdef __GNUC__
773 #  ifdef NX_CURRENT_COMPILER_RELEASE
774     sprintf(compiler_name, "NeXT DevKit %d.%02d (gcc " __VERSION__ ")",
775      NX_CURRENT_COMPILER_RELEASE/100, NX_CURRENT_COMPILER_RELEASE%100);
776 #    define COMPILER_NAME compiler_name
777 #  else
778 #    define COMPILER_NAME "gcc " __VERSION__
779 #  endif
780 #else /* !__GNUC__ */
781 #  if defined(__SUNPRO_C)
782     sprintf( compiler_name, "Sun C version %x", __SUNPRO_C);
783 #    define COMPILER_NAME compiler_name
784 #  else
785 #    if (defined( __HP_cc))
786     if ((__HP_cc% 100) == 0)
787     {
788       sprintf( compiler_name, "HP C version A.%02d.%02d",
789        (__HP_cc/ 10000), ((__HP_cc% 10000)/ 100));
790     }
791     else
792     {
793       sprintf( compiler_name, "HP C version A.%02d.%02d.%02d",
794        (__HP_cc/ 10000), ((__HP_cc% 10000)/ 100), (__HP_cc% 100));
795     }
796 #      define COMPILER_NAME compiler_name
797 #    else
798 #      if (defined( __DECC_VER))
799     sprintf( compiler_name, "DEC C version %c%d.%d-%03d",
800      ((compiler_typ = (__DECC_VER / 10000) % 10) == 6 ? 'T' :
801      (compiler_typ == 8 ? 'S' : 'V')),
802      __DECC_VER / 10000000,
803      (__DECC_VER % 10000000) / 100000, __DECC_VER % 1000);
804 #        define COMPILER_NAME compiler_name
805 #      else
806 #        if ((defined(CRAY) || defined(cray)) && defined(_RELEASE))
807     sprintf(compiler_name, "cc version %d", _RELEASE);
808 #          define COMPILER_NAME compiler_name
809 #        else
810 #          ifdef __IBMC__
811     sprintf( compiler_name, "IBM C version %d.%d.%d",
812      (__IBMC__/ 100), ((__IBMC__/ 10)% 10), (__IBMC__% 10));
813 #            define COMPILER_NAME compiler_name
814 #          else
815 #            ifdef __VERSION__
816 #              define COMPILER_NAME "cc " __VERSION__
817 #            else
818 #              define COMPILER_NAME "cc "
819 #            endif
820 #          endif
821 #        endif
822 #      endif
823 #    endif
824 #  endif
825 #endif /* ?__GNUC__ */
826 
827 
828 /* Define the name to use for the OS we're compiling on */
829 #if defined(sgi) || defined(__sgi)
830 #  define OS_NAME "Silicon Graphics IRIX"
831 #else
832 #ifdef sun
833 #  ifdef sparc
834 #    ifdef __SVR4
835 #      define OS_NAME "Sun SPARC/Solaris"
836 #    else /* may or may not be SunOS */
837 #      define OS_NAME "Sun SPARC"
838 #    endif
839 #  else
840 #  if defined(sun386) || defined(i386)
841 #    define OS_NAME "Sun 386i"
842 #  else
843 #  if defined(mc68020) || defined(__mc68020__)
844 #    define OS_NAME "Sun 3"
845 #  else /* mc68010 or mc68000:  Sun 2 or earlier */
846 #    define OS_NAME "Sun 2"
847 #  endif
848 #  endif
849 #  endif
850 #else
851 #ifdef __hpux
852 #  define OS_NAME "HP-UX"
853 #else
854 #ifdef __osf__
855 #  define OS_NAME "DEC OSF/1"
856 #else
857 #ifdef _AIX
858 #  define OS_NAME "IBM AIX"
859 #else
860 #ifdef aiws
861 #  define OS_NAME "IBM RT/AIX"
862 #else
863 #if defined(CRAY) || defined(cray)
864 #  ifdef _UNICOS
865     sprintf(os_name, "Cray UNICOS release %d", _UNICOS);
866 #    define OS_NAME os_name
867 #  else
868 #    define OS_NAME "Cray UNICOS"
869 #  endif
870 #else
871 #if defined(uts) || defined(UTS)
872 #  define OS_NAME "Amdahl UTS"
873 #else
874 #ifdef NeXT
875 #  ifdef mc68000
876 #    define OS_NAME "NeXTStep/black"
877 #  else
878 #    define OS_NAME "NeXTStep for Intel"
879 #  endif
880 #else
881 #if defined(linux) || defined(__linux__)
882 #  ifdef __ELF__
883 #    define OS_NAME "Linux ELF"
884 #  else
885 #    define OS_NAME "Linux a.out"
886 #  endif
887 #else
888 #ifdef MINIX
889 #  define OS_NAME "Minix"
890 #else
891 #ifdef M_UNIX
892 #  define OS_NAME "SCO Unix"
893 #else
894 #ifdef M_XENIX
895 #  define OS_NAME "SCO Xenix"
896 #else
897 #ifdef BSD
898 # if (BSD > 199103)
899 #    define OS_NAME os_name
900     uname(&u);
901     sprintf(os_name, "%s %s", u.sysname, u.release);
902 # else
903 # ifdef __NetBSD__
904 #   define OS_NAME os_name
905 #   ifdef NetBSD0_8
906       sprintf(os_name, "NetBSD 0.8%s", netbsd[NetBSD0_8]);
907 #   else
908 #   ifdef NetBSD0_9
909       sprintf(os_name, "NetBSD 0.9%s", netbsd[NetBSD0_9]);
910 #   else
911 #   ifdef NetBSD1_0
912       sprintf(os_name, "NetBSD 1.0%s", netbsd[NetBSD1_0]);
913 #   endif /* NetBSD1_0 */
914 #   endif /* NetBSD0_9 */
915 #   endif /* NetBSD0_8 */
916 # else
917 # ifdef __FreeBSD__
918 #    define OS_NAME "FreeBSD 1.x"
919 # else
920 # ifdef __bsdi__
921 #    define OS_NAME "BSD/386 1.0"
922 # else
923 # ifdef __386BSD__
924 #    define OS_NAME "386BSD"
925 # else
926 #    define OS_NAME "Unknown BSD"
927 # endif /* __386BSD__ */
928 # endif /* __bsdi__ */
929 # endif /* FreeBSD */
930 # endif /* NetBSD */
931 # endif /* BSD > 199103 */
932 #else
933 #ifdef __CYGWIN__
934 #  define OS_NAME "Cygwin"
935 #else
936 #if defined(i686) || defined(__i686) || defined(__i686__)
937 #  define OS_NAME "Intel 686"
938 #else
939 #if defined(i586) || defined(__i586) || defined(__i586__)
940 #  define OS_NAME "Intel 586"
941 #else
942 #if defined(i486) || defined(__i486) || defined(__i486__)
943 #  define OS_NAME "Intel 486"
944 #else
945 #if defined(i386) || defined(__i386) || defined(__i386__)
946 #  define OS_NAME "Intel 386"
947 #else
948 #ifdef pyr
949 #  define OS_NAME "Pyramid"
950 #else
951 #if defined(ultrix) || defined(__ultrix)
952 #  if defined(mips) || defined(__mips)
953 #    define OS_NAME "DEC/MIPS"
954 #  else
955 #  if defined(vax) || defined(__vax)
956 #    define OS_NAME "DEC/VAX"
957 #  else /* __alpha? */
958 #    define OS_NAME "DEC/Alpha"
959 #  endif
960 #  endif
961 #else
962 #ifdef gould
963 #  define OS_NAME "Gould"
964 #else
965 #ifdef MTS
966 #  define OS_NAME "MTS"
967 #else
968 #ifdef __convexc__
969 #  define OS_NAME "Convex"
970 #else
971 #ifdef __QNX__
972 #  define OS_NAME "QNX 4"
973 #else
974 #ifdef __QNXNTO__
975 #  define OS_NAME "QNX Neutrino"
976 #else
977 #ifdef __APPLE__
978 #  ifdef __i386__
979 #    define OS_NAME "Mac OS X Intel"
980 #  else /* __i386__ */
981 #    ifdef __ppc__
982 #      define OS_NAME "Mac OS X PowerPC"
983 #    else /* __ppc__ */
984 #      ifdef __ppc64__
985 #        define OS_NAME "Mac OS X PowerPC64"
986 #      else /* __ppc64__ */
987 #        define OS_NAME "Mac OS X"
988 #      endif /* __ppc64__ */
989 #    endif /* __ppc__ */
990 #  endif /* __i386__ */
991 #else
992 #  define OS_NAME "Unknown"
993 #endif /* Apple */
994 #endif /* QNX Neutrino */
995 #endif /* QNX 4 */
996 #endif /* Convex */
997 #endif /* MTS */
998 #endif /* Gould */
999 #endif /* DEC */
1000 #endif /* Pyramid */
1001 #endif /* 386 */
1002 #endif /* 486 */
1003 #endif /* 586 */
1004 #endif /* 686 */
1005 #endif /* Cygwin */
1006 #endif /* BSD */
1007 #endif /* SCO Xenix */
1008 #endif /* SCO Unix */
1009 #endif /* Minix */
1010 #endif /* Linux */
1011 #endif /* NeXT */
1012 #endif /* Amdahl */
1013 #endif /* Cray */
1014 #endif /* RT/AIX */
1015 #endif /* AIX */
1016 #endif /* OSF/1 */
1017 #endif /* HP-UX */
1018 #endif /* Sun */
1019 #endif /* SGI */
1020 
1021 
1022 /* Define the compile date string */
1023 #ifdef __DATE__
1024 #  define COMPILE_DATE " on " __DATE__
1025 #else
1026 #  define COMPILE_DATE ""
1027 #endif
1028 
1029     printf("Compiled with %s for Unix (%s)%s.\n\n",
1030            COMPILER_NAME, OS_NAME, COMPILE_DATE);
1031 
1032 } /* end function version_local() */
1033 
1034 
1035 /* 2006-03-23 SMS.
1036  * Emergency replacement for strerror().  (Useful on SunOS 4.*.)
1037  * Enable by specifying "LOCAL_UNZIP=-DNEED_STRERROR=1" on the "make"
1038  * command line.
1039  */
1040 
1041 #ifdef NEED_STRERROR
1042 
strerror(err)1043 char *strerror( err)
1044   int err;
1045 {
1046     extern char *sys_errlist[];
1047     extern int sys_nerr;
1048 
1049     static char no_msg[ 64];
1050 
1051     if ((err >= 0) && (err < sys_nerr))
1052     {
1053         return sys_errlist[ err];
1054     }
1055     else
1056     {
1057         sprintf( no_msg, "(no message, code = %d.)", err);
1058         return no_msg;
1059     }
1060 }
1061 
1062 #endif /* def NEED_STRERROR */
1063 
1064 
1065 /* 2006-03-23 SMS.
1066  * Emergency replacement for memmove().  (Useful on SunOS 4.*.)
1067  * Enable by specifying "LOCAL_UNZIP=-DNEED_MEMMOVE=1" on the "make"
1068  * command line.
1069  */
1070 
1071 #ifdef NEED_MEMMOVE
1072 
1073 /* memmove.c -- copy memory.
1074    Copy LENGTH bytes from SOURCE to DEST.  Does not null-terminate.
1075    In the public domain.
1076    By David MacKenzie <djm@gnu.ai.mit.edu>.
1077    Adjusted by SMS.
1078 */
1079 
memmove(dest0,source0,length)1080 void *memmove(dest0, source0, length)
1081   void *dest0;
1082   void const *source0;
1083   size_t length;
1084 {
1085     char *dest = dest0;
1086     char const *source = source0;
1087     if (source < dest)
1088         /* Moving from low mem to hi mem; start at end.  */
1089         for (source += length, dest += length; length; --length)
1090             *--dest = *--source;
1091     else if (source != dest)
1092     {
1093         /* Moving from hi mem to low mem; start at beginning.  */
1094         for (; length; --length)
1095             *dest++ = *source++;
1096     }
1097     return dest0;
1098 }
1099 
1100 #endif /* def NEED_MEMMOVE */
1101