Annotation of coherent/b/bin/zip/zipfile.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:  *  zipfile.c by Mark Adler.
                     14:  */
                     15: 
                     16: #include "zip.h"
                     17: 
                     18: #ifdef VMS
                     19: #  include "VMSmunch.h"
                     20: #  include <rms.h>
                     21: #endif
                     22: 
                     23: 
                     24: /* Macros for converting integers in little-endian to machine format */
                     25: #define SH(a) (((ush)(uch)(a)[0]) | (((ush)(uch)(a)[1]) << 8))
                     26: #define LG(a) ((ulg)SH(a) | ((ulg)SH((a)+2) << 16))
                     27: 
                     28: /* Macros for writing machine integers to little-endian format */
                     29: #define PUTSH(a,f) {putc((char)(a),(f)); putc((char)((a) >> 8),(f));}
                     30: #define PUTLG(a,f) {PUTSH(a,f) PUTSH((a) >> 16,f)}
                     31: 
                     32: 
                     33: /* -- Structure of a ZIP file -- */
                     34: 
                     35: /* Signatures for zip file information headers */
                     36: #define LOCSIG     0x04034b50L
                     37: #define CENSIG     0x02014b50L
                     38: #define ENDSIG     0x06054b50L
                     39: #define EXTLOCSIG  0x08074b50L
                     40: 
                     41: /* Offsets of values in headers */
                     42: #define LOCVER  0               /* version needed to extract */
                     43: #define LOCFLG  2               /* encrypt, deflate flags */
                     44: #define LOCHOW  4               /* compression method */
                     45: #define LOCTIM  6               /* last modified file time, DOS format */
                     46: #define LOCDAT  8               /* last modified file date, DOS format */
                     47: #define LOCCRC  10              /* uncompressed crc-32 for file */
                     48: #define LOCSIZ  14              /* compressed size in zip file */
                     49: #define LOCLEN  18              /* uncompressed size */
                     50: #define LOCNAM  22              /* length of filename */
                     51: #define LOCEXT  24              /* length of extra field */
                     52: 
                     53: #define CENVEM  0               /* version made by */
                     54: #define CENVER  2               /* version needed to extract */
                     55: #define CENFLG  4               /* encrypt, deflate flags */
                     56: #define CENHOW  6               /* compression method */
                     57: #define CENTIM  8               /* last modified file time, DOS format */
                     58: #define CENDAT  10              /* last modified file date, DOS format */
                     59: #define CENCRC  12              /* uncompressed crc-32 for file */
                     60: #define CENSIZ  16              /* compressed size in zip file */
                     61: #define CENLEN  20              /* uncompressed size */
                     62: #define CENNAM  24              /* length of filename */
                     63: #define CENEXT  26              /* length of extra field */
                     64: #define CENCOM  28              /* file comment length */
                     65: #define CENDSK  30              /* disk number start */
                     66: #define CENATT  32              /* internal file attributes */
                     67: #define CENATX  34              /* external file attributes */
                     68: #define CENOFF  38              /* relative offset of local header */
                     69: 
                     70: #define ENDDSK  0               /* number of this disk */
                     71: #define ENDBEG  2               /* number of the starting disk */
                     72: #define ENDSUB  4               /* entries on this disk */
                     73: #define ENDTOT  6               /* total number of entries */
                     74: #define ENDSIZ  8               /* size of entire central directory */
                     75: #define ENDOFF  12              /* offset of central on starting disk */
                     76: #define ENDCOM  16              /* length of zip file comment */
                     77: 
                     78: 
                     79: /* Local functions */
                     80: #ifdef PROTO
                     81:    local int zqcmp(voidp *, voidp *);
                     82: #  ifndef UTIL
                     83:      local int zbcmp(voidp *, voidp far *);
                     84:      local char *cutpath(char *);
                     85: #  endif /* !UTIL */
                     86: #endif /* PROTO */
                     87: 
                     88: 
                     89: local int zqcmp(a, b)
                     90: voidp *a, *b;           /* pointers to pointers to zip entries */
                     91: /* Used by qsort() to compare entries in the zfile list.  */
                     92: {
                     93:   return namecmp((*(struct zlist far **)a)->zname,
                     94:                 (*(struct zlist far **)b)->zname);
                     95: }
                     96: 
                     97: 
                     98: #ifndef UTIL
                     99: 
                    100: local int zbcmp(n, z)
                    101: voidp *n;               /* string to search for */
                    102: voidp far *z;           /* pointer to a pointer to a zip entry */
                    103: /* Used by search() to compare a target to an entry in the zfile list. */
                    104: {
                    105:   return namecmp((char *)n, ((struct zlist far *)z)->zname);
                    106: }
                    107: 
                    108: 
                    109: struct zlist far *zsearch(n)
                    110: char *n;                /* name to find */
                    111: /* Return a pointer to the entry in zfile with the name n, or NULL if
                    112:    not found. */
                    113: {
                    114:   voidp far **p;        /* result of search() */
                    115: 
                    116:   if (zcount && (p = search(n, (voidp far **)zsort, zcount, zbcmp)) != NULL)
                    117:     return *(struct zlist far **)p;
                    118:   else
                    119:     return NULL;
                    120: }
                    121: 
                    122: #endif /* !UTIL */
                    123: 
                    124: #ifndef VMS
                    125: #  define PATHCUT '/'
                    126: 
                    127: char *ziptyp(s)
                    128: char *s;                /* file name to force to zip */
                    129: /* If the file name *s has a dot (other than the first char), then return
                    130:    the name, otherwise append .zip to the name.  Allocate the space for
                    131:    the name in either case.  Return a pointer to the new name, or NULL
                    132:    if malloc() fails. */
                    133: {
                    134:   char *q;              /* temporary pointer */
                    135:   char *t;              /* pointer to malloc'ed string */
                    136: 
                    137:   if ((t = malloc(strlen(s) + 5)) == NULL)
                    138:     return NULL;
                    139:   strcpy(t, s);
                    140: #ifdef MSDOS
                    141:   for (q = t; *q; q++)
                    142:     if (*q == '\\')
                    143:       *q = '/';
                    144: #endif /* MSDOS */
                    145:   if (strrchr((q = strrchr(t, PATHCUT)) == NULL ? t : q + 1, '.') == NULL)
                    146:     strcat(t, ".zip");
                    147: #if defined(FORCE_UPPER) && defined(MSDOS) && !defined(OS2)
                    148:   strupr(t);
                    149: #endif
                    150:   return t;
                    151: }
                    152: 
                    153: #else /* VMS */
                    154: 
                    155: # define PATHCUT ']'
                    156: 
                    157: char *ziptyp(s)
                    158: char *s;
                    159: {   int status;
                    160:     struct FAB fab;
                    161:     struct NAM nam;
                    162:     static char zero=0;
                    163:     char result[NAM$C_MAXRSS+1],exp[NAM$C_MAXRSS+1];
                    164:     char *p;
                    165: 
                    166:     fab = cc$rms_fab;
                    167:     nam = cc$rms_nam;
                    168: 
                    169:     fab.fab$l_fna = s;
                    170:     fab.fab$b_fns = strlen(fab.fab$l_fna);
                    171: 
                    172:     fab.fab$l_dna = "sys$disk:[].zip";          /* Default fspec */
                    173:     fab.fab$b_dns = strlen(fab.fab$l_dna);
                    174: 
                    175:     fab.fab$l_nam = &nam;
                    176:     
                    177:     nam.nam$l_rsa = result;                     /* Put resultant name of */
                    178:     nam.nam$b_rss = sizeof(result)-1;           /* existing zipfile here */
                    179: 
                    180:     nam.nam$l_esa = exp;                        /* For full spec of */
                    181:     nam.nam$b_ess = sizeof(exp)-1;              /* file to create */
                    182: 
                    183:     status = sys$parse(&fab);
                    184:     if( (status & 1) == 0 )
                    185:         return &zero;
                    186: 
                    187:     status = sys$search(&fab);
                    188:     if( status & 1 )
                    189:     {               /* Existing ZIP file */
                    190:         int l;
                    191:         if( (p=malloc( (l=nam.nam$b_rsl) + 1 )) != NULL )
                    192:         {       result[l] = 0;
                    193:                 strcpy(p,result);
                    194:         }
                    195:     }
                    196:     else
                    197:     {               /* New ZIP file */
                    198:         int l;
                    199:         if( (p=malloc( (l=nam.nam$b_esl) + 1 )) != NULL )
                    200:         {       exp[l] = 0;
                    201:                 strcpy(p,exp);
                    202:         }
                    203:     }
                    204:     return p;
                    205: }
                    206: 
                    207: #endif  /* VMS */
                    208: 
                    209: 
                    210: int readzipfile()
                    211: /*
                    212:    Make first pass through zip file, reading information from local file
                    213:    headers and then verifying that information with the central file
                    214:    headers.  Any deviation from the expected zip file format returns an
                    215:    error.  At the end, a sorted list of file names in the zip file is made
                    216:    to facilitate searching by name.
                    217: 
                    218:    The name of the zip file is pointed to by the global "zipfile".  The
                    219:    globals zfiles, zcount, zcomlen, zcomment, and zsort are filled in.
                    220:    Return an error code in the ZE_ class.
                    221: */
                    222: {
                    223:   char b[CENHEAD];      /* buffer for central headers */
                    224:   FILE *f;              /* zip file */
                    225:   ush flg;              /* general purpose bit flag */
                    226:   int m;                /* mismatch flag */
                    227:   extent n;             /* length of name */
                    228:   ulg p;                /* current file offset */
                    229:   char r;               /* holds reserved bits during memcmp() */
                    230:   ulg s;                /* size of data, start of central */
                    231:   char *t;              /* temporary variable */
                    232:   char far *u;          /* temporary variable */
                    233:   struct zlist far * far *x;    /* pointer last entry's link */
                    234:   struct zlist far *z;  /* current zip entry structure */
                    235: 
                    236:   /* Initialize zip file info */
                    237:   zipbeg = 0;
                    238:   zfiles = NULL;                        /* Points to first header */
                    239:   zcomlen = 0;                          /* zip file comment length */
                    240: 
                    241:   /* If zip file exists, read headers and check structure */
                    242: #ifdef VMS
                    243:   if (zipfile == NULL || !(*zipfile) || !strcmp(zipfile, "-"))
                    244:     return ZE_OK;
                    245:   {
                    246:     int rtype;
                    247:     VMSmunch(zipfile, GET_RTYPE, (char *)&rtype);
                    248:     if (rtype == FAT$C_VARIABLE) {
                    249:       fprintf(stderr,
                    250:      "\n     Error:  zipfile is in variable-length record format.  Please\n\
                    251:      run \"bilf b %s\" to convert the zipfile to fixed-length\n\
                    252:      record format.  (Bilf.exe, bilf.c and make_bilf.com are included\n\
                    253:      in the VMS UnZip distribution.)\n\n", zipfile);
                    254:       return ZE_FORM;
                    255:     }
                    256:   }
                    257:   if ((f = fopen(zipfile, FOPR)) != NULL)
                    258: #else /* !VMS */
                    259:   if (zipfile != NULL && *zipfile && strcmp(zipfile, "-") &&
                    260:       (f = fopen(zipfile, FOPR)) != NULL)
                    261: #endif /* ?VMS */
                    262:   {
                    263:     x = &zfiles;                        /* first link */
                    264:     p = 0;                              /* starting file offset */
                    265:     zcount = 0;                         /* number of files */
                    266: 
                    267:     /* Find start of zip structures */
                    268:     for (;;) {
                    269:       while ((m = getc(f)) != EOF && m != 'P') p++;
                    270:       b[0] = (char) m;
                    271:       if (fread(b+1, 3, 1, f) != 1 || (s = LG(b)) == LOCSIG || s == ENDSIG)
                    272:         break;
                    273:       if (fseek(f, -3L, SEEK_CUR))
                    274:         return ferror(f) ? ZE_READ : ZE_EOF;
                    275:       p++;
                    276:     }
                    277:     zipbeg = p;
                    278: 
                    279:     /* Read local headers */
                    280:     while (LG(b) == LOCSIG)
                    281:     {
                    282:       /* Read local header raw to compare later with central header
                    283:          (this requires that the offest of ext in the zlist structure
                    284:          be greater than or equal to LOCHEAD) */
                    285:       if ((z = (struct zlist far *)farmalloc(sizeof(struct zlist))) == NULL)
                    286:         return ZE_MEM;
                    287:       if (fread(b, LOCHEAD, 1, f) != 1)
                    288:         return ferror(f) ? ZE_READ : ZE_EOF;
                    289:       t = b;  u = (char far *)z;  n = LOCHEAD;
                    290:       do {
                    291:         *u++ = *t++;
                    292:       } while (--n);
                    293: 
                    294:       /* Link into list */
                    295:       *x = z;
                    296:       z->nxt = NULL;
                    297:       x = &z->nxt;
                    298: 
                    299:       /* Read file name and extra field and skip data */
                    300:       n = SH(LOCNAM + (uch far *)z);
                    301:       z->ext = SH(LOCEXT + (uch far *)z);
                    302:       s = LG(LOCSIZ + (uch far *)z);
                    303:       if (n == 0)
                    304:       {
                    305:         sprintf(errbuf, "%d", zcount + 1);
                    306:         warn("zero-length name for entry #", errbuf);
                    307:         return ZE_FORM;
                    308:       }
                    309:       if ((z->zname = malloc(n+1)) ==  NULL ||
                    310:           (z->ext && (z->extra = malloc(z->ext)) == NULL))
                    311:         return ZE_MEM;
                    312:       if (fread(z->zname, n, 1, f) != 1 ||
                    313:           (z->ext && fread(z->extra, z->ext, 1, f) != 1) ||
                    314:           fseek(f, (long)s, SEEK_CUR))
                    315:         return ferror(f) ? ZE_READ : ZE_EOF;
                    316:       /* If there is an extended local header, s is either 0 or
                    317:        * the correct compressed size.
                    318:        */
                    319:       z->zname[n] = 0;                  /* terminate name */
                    320: #ifdef UTIL
                    321:       z->name = z->zname;
                    322: #else /* !UTIL */
                    323:       z->name = in2ex(z->zname);        /* convert to external name */
                    324:       if (z->name == NULL)
                    325:         return ZE_MEM;
                    326: #endif /* ?UTIL */
                    327: 
                    328:       /* Save offset, update for next header */
                    329:       z->off = p;
                    330:       p += 4 + LOCHEAD + n + z->ext + s;
                    331:       zcount++;
                    332: 
                    333:       /* Skip extended local header if there is one */
                    334:       flg = SH(b+LOCFLG);
                    335:       if ((flg & 8) != 0) {
                    336:         /* Skip the compressed data if compressed size is unknown.
                    337:          * For safety, we should use the central directory.
                    338:          */
                    339:         if (s == 0) {
                    340:           for (;;) {
                    341:             while ((m = getc(f)) != EOF && m != 'P') ;
                    342:             b[0] = (char) m;
                    343:             if (fread(b+1, 15, 1, f) != 1 || LG(b) == EXTLOCSIG)
                    344:               break;
                    345:             if (fseek(f, -15L, SEEK_CUR))
                    346:               return ferror(f) ? ZE_READ : ZE_EOF;
                    347:           }
                    348:           s = LG(b+8);
                    349:           p += s;
                    350:           if ((ulg) ftell(f) != p+16L) {
                    351:             warn("bad extended local header for ", z->zname);
                    352:             return ZE_FORM;
                    353:           }
                    354:         } else {
                    355:           /* compressed size non zero, assume that it is valid: */
                    356:           if (fseek(f, p, SEEK_SET) || fread(b, 16, 1, f) != 1)
                    357:             return ferror(f) ? ZE_READ : ZE_EOF;
                    358:           if (LG(b) != EXTLOCSIG) {
                    359:             warn("extended local header not found for ", z->zname);
                    360:             return ZE_FORM;
                    361:           }
                    362:         }
                    363:         /* overwrite the unknown values of the local header: */
                    364:         t = b+4;  u = (char far *)z+LOCCRC;  n = 12;
                    365:         do {
                    366:           *u++ = *t++;
                    367:         } while (--n);
                    368:         p += 16L;
                    369:       }
                    370:       /* Read next signature */
                    371:       if (fread(b, 4, 1, f) != 1)
                    372:         return ferror(f) ? ZE_READ : ZE_EOF;
                    373:     }
                    374: 
                    375:     /* Point to start of header list and read central headers */
                    376:     z = zfiles;
                    377:     s = p;                              /* save start of central */
                    378:     while (LG(b) == CENSIG)
                    379:     {
                    380:       if (z == NULL)
                    381:       {
                    382:         warn("extraneous central header signature", "");
                    383:         return ZE_FORM;
                    384:       }
                    385: 
                    386:       /* Read central header */
                    387:       if (fread(b, CENHEAD, 1, f) != 1)
                    388:         return ferror(f) ? ZE_READ : ZE_EOF;
                    389: 
                    390:       /* Compare local header with that part of central header (except
                    391:          for the reserved bits in the general purpose flags and except
                    392:          for length of extra fields--authentication can make these
                    393:          different in central and local headers) */
                    394:       z->lflg = SH(LOCFLG + (uch far *)z);      /* Save reserved bits */
                    395:       r = b[CENFLG+1];
                    396:       ((uch far *)z)[LOCFLG+1] &= 0x1f; /* Zero out reserved bits */
                    397:       b[CENFLG+1] &= 0x1f;
                    398:       for (m = 0, u = (char far *)z, n = 0; n < LOCHEAD - 2; n++)
                    399:         if (u[n] != b[n+2])
                    400:         {
                    401:           if (!m)
                    402:             warn("local and central headers differ for ", z->zname);
                    403:           m = 1;
                    404:           sprintf(errbuf, " offset %d--local = %02x, central = %02x",
                    405:                   n, (uch)u[n], (uch)b[n+2]);
                    406:           warn(errbuf, "");
                    407:         }
                    408:       if (m)
                    409:         return ZE_FORM;
                    410:       b[CENFLG+1] = r;                  /* Restore reserved bits */
                    411: 
                    412:       /* Overwrite local header with translated central header */
                    413:       z->vem = SH(CENVEM + b);
                    414:       z->ver = SH(CENVER + b);
                    415:       z->flg = SH(CENFLG + b);          /* may be different from z->lflg */
                    416:       z->how = SH(CENHOW + b);
                    417:       z->tim = LG(CENTIM + b);          /* time and date into one long */
                    418:       z->crc = LG(CENCRC + b);
                    419:       z->siz = LG(CENSIZ + b);
                    420:       z->len = LG(CENLEN + b);
                    421:       z->nam = SH(CENNAM + b);
                    422:       z->cext = SH(CENEXT + b);         /* may be different from z->ext */
                    423:       z->com = SH(CENCOM + b);
                    424:       z->dsk = SH(CENDSK + b);
                    425:       z->att = SH(CENATT + b);
                    426:       z->atx = LG(CENATX + b);
                    427:       if (z->off != LG(CENOFF + b))
                    428:       {
                    429:         warn("local offset in central header incorrect for ", z->zname);
                    430:         return ZE_FORM;
                    431:       }
                    432: 
                    433:       /* Compare name and extra fields and read comment field */
                    434:       if ((t = malloc(z->nam)) == NULL)
                    435:         return ZE_MEM;
                    436:       if (fread(t, z->nam, 1, f) != 1)
                    437:       {
                    438:         free((voidp *)t);
                    439:         return ferror(f) ? ZE_READ : ZE_EOF;
                    440:       }
                    441:       if (memcmp(t, z->zname, z->nam))
                    442:       {
                    443:         free((voidp *)t);
                    444:         warn("names in local and central differ for ", z->zname);
                    445:         return ZE_FORM;
                    446:       }
                    447:       free((voidp *)t);
                    448:       if (z->cext)
                    449:       {
                    450:         if ((z->cextra = malloc(z->cext)) == NULL)
                    451:           return ZE_MEM;
                    452:         if (fread(z->cextra, z->cext, 1, f) != 1)
                    453:         {
                    454:           free((voidp *)(z->cextra));
                    455:           return ferror(f) ? ZE_READ : ZE_EOF;
                    456:         }
                    457:         if (z->ext == z->cext && memcmp(z->extra, z->cextra, z->ext) == 0)
                    458:         {
                    459:           free((voidp *)(z->cextra));
                    460:           z->cextra = z->extra;
                    461:         }
                    462:       }
                    463:       if (z->com)
                    464:       {
                    465:         if ((z->comment = malloc(z->com)) == NULL)
                    466:           return ZE_MEM;
                    467:         if (fread(z->comment, z->com, 1, f) != 1)
                    468:         {
                    469:           free((voidp *)(z->comment));
                    470:           return ferror(f) ? ZE_READ : ZE_EOF;
                    471:         }
                    472:       }
                    473: 
                    474:       /* Note oddities */
                    475:       if (verbose)
                    476:       {
                    477:         if (z->vem != 10 && z->vem != 11 && z->vem != 20 &&
                    478:             (n = z->vem >> 8) != 3 && n != 2 && n != 6 && n != 0)
                    479:         {
                    480:           sprintf(errbuf, "made by version %d.%d on system type %d: ",
                    481:             (ush)(z->vem & 0xff) / (ush)10,
                    482:             (ush)(z->vem & 0xff) % (ush)10, z->vem >> 8);
                    483:           warn(errbuf, z->zname);
                    484:         }
                    485:         if (z->ver != 10 && z->ver != 11 && z->ver != 20)
                    486:         {
                    487:           sprintf(errbuf, "needs unzip %d.%d on system type %d: ",
                    488:             (ush)(z->ver & 0xff) / (ush)10,
                    489:             (ush)(z->ver & 0xff) % (ush)10, z->ver >> 8);
                    490:           warn(errbuf, z->zname);
                    491:         }
                    492:         if (z->flg != z->lflg)
                    493:         {
                    494:           sprintf(errbuf, "local flags = 0x%04x, central = 0x%04x: ",
                    495:                   z->lflg, z->flg);
                    496:           warn(errbuf, z->zname);
                    497:         }
                    498:         else if (z->flg & ~0xf)
                    499:         {
                    500:           sprintf(errbuf, "undefined bits used in flags = 0x%04x: ", z->flg);
                    501:           warn(errbuf, z->zname);
                    502:         }
                    503:         if (z->how > DEFLATE)
                    504:         {
                    505:           sprintf(errbuf, "unknown compression method %u: ", z->how);
                    506:           warn(errbuf, z->zname);
                    507:         }
                    508:         if (z->dsk)
                    509:         {
                    510:           sprintf(errbuf, "starts on disk %u: ", z->dsk);
                    511:           warn(errbuf, z->zname);
                    512:         }
                    513:         if (z->att & ~1)
                    514:         {
                    515:           sprintf(errbuf, "unknown internal attributes = 0x%04x: ", z->att);
                    516:           warn(errbuf, z->zname);
                    517:         }
                    518:         if (((n = z->vem >> 8) != 3) && n != 2 && z->atx & ~0xffL)
                    519:         {
                    520:           sprintf(errbuf, "unknown external attributes = 0x%08lx: ", z->atx);
                    521:           warn(errbuf, z->zname);
                    522:         }
                    523:         if (z->ext || z->cext)
                    524:           if (z->ext == z->cext && z->extra == z->cextra)
                    525:           {
                    526:             sprintf(errbuf, "has %d bytes of extra data: ", z->ext);
                    527:             warn(errbuf, z->zname);
                    528:           }
                    529:           else
                    530:           {
                    531:             sprintf(errbuf,
                    532:                     "local extra (%d bytes) != central extra (%d bytes): ",
                    533:                     z->ext, z->cext);
                    534:             warn(errbuf, z->zname);
                    535:           }
                    536:       }
                    537: 
                    538:       /* Clear actions */
                    539:       z->mark = 0;
                    540:       z->trash = 0;
                    541: 
                    542:       /* Update file offset */
                    543:       p += 4 + CENHEAD + z->nam + z->cext + z->com;
                    544: 
                    545:       /* Advance to next header structure */
                    546:       z = z->nxt;
                    547: 
                    548:       /* Read next signature */
                    549:       if (fread(b, 4, 1, f) != 1)
                    550:         return ferror(f) ? ZE_READ : ZE_EOF;
                    551:     }
                    552:     
                    553:     /* Read end header */
                    554:     if (z != NULL || LG(b) != ENDSIG)
                    555:     {
                    556:       warn("missing end signature--probably not a zip file (did you", "");
                    557:       warn("remember to use binary mode when you transferred it?)", "");
                    558:       return ZE_FORM;
                    559:     }
                    560:     if (fread(b, ENDHEAD, 1, f) != 1)
                    561:       return ferror(f) ? ZE_READ : ZE_EOF;
                    562:     if (SH(ENDDSK + b) || SH(ENDBEG + b) ||
                    563:         SH(ENDSUB + b) != SH(ENDTOT + b))
                    564:       warn("multiple disk information ignored", "");
                    565:     if (zcount != SH(ENDSUB + b))
                    566:     {
                    567:       warn("count in end of central directory incorrect", "");
                    568:       return ZE_FORM;
                    569:     }
                    570:     if (LG(ENDSIZ + b) != p - s)
                    571:     {
                    572:       warn("central directory size is incorrect (made by stzip?)", "");
                    573:       /* stzip 0.9 gets this wrong, so be tolerant */
                    574:       /* return ZE_FORM; */
                    575:     }
                    576:     if (LG(ENDOFF + b) != s)
                    577:     {
                    578:       warn("central directory start is incorrect", "");
                    579:       return ZE_FORM;
                    580:     }
                    581:     cenbeg = s;
                    582:     zcomlen = SH(ENDCOM + b);
                    583:     if (zcomlen)
                    584:     {
                    585:       if ((zcomment = malloc(zcomlen)) == NULL)
                    586:         return ZE_MEM;
                    587:       if (fread(zcomment, zcomlen, 1, f) != 1)
                    588:       {
                    589:         free((voidp *)zcomment);
                    590:         return ferror(f) ? ZE_READ : ZE_EOF;
                    591:       }
                    592:     }
                    593:     if (zipbeg)
                    594:     {
                    595:       sprintf(errbuf, " has a preamble of %ld bytes", zipbeg);
                    596:       warn(zipfile, errbuf);
                    597:     }
                    598:     if (getc(f) != EOF)
                    599:       warn("garbage at end of zip file ignored", "");
                    600: 
                    601:     /* Done with zip file for now */
                    602:     fclose(f);
                    603:     
                    604:     /* If one or more files, sort by name */
                    605:     if (zcount)
                    606:     {
                    607:       if ((x = zsort =
                    608:           (struct zlist far **)malloc(zcount * sizeof(struct zlist far *))) ==
                    609:           NULL)
                    610:         return ZE_MEM;
                    611:       for (z = zfiles; z != NULL; z = z->nxt)
                    612:         *x++ = z;
                    613:       qsort((char *)zsort, zcount, sizeof(struct zlist far *), zqcmp);
                    614:     }
                    615:   }
                    616:   return ZE_OK;
                    617: }
                    618: 
                    619: 
                    620: int putlocal(z, f)
                    621: struct zlist far *z;    /* zip entry to write local header for */
                    622: FILE *f;                /* file to write to */
                    623: /* Write a local header described by *z to file *f.  Return an error code
                    624:    in the ZE_ class. */
                    625: {
                    626:   PUTLG(LOCSIG, f);
                    627:   PUTSH(z->ver, f);
                    628:   PUTSH(z->lflg, f);
                    629:   PUTSH(z->how, f);
                    630:   PUTLG(z->tim, f);
                    631:   PUTLG(z->crc, f);
                    632:   PUTLG(z->siz, f);
                    633:   PUTLG(z->len, f);
                    634:   PUTSH(z->nam, f);
                    635:   PUTSH(z->ext, f);
                    636:   if (fwrite(z->zname, 1, z->nam, f) != z->nam ||
                    637:       (z->ext && fwrite(z->extra, 1, z->ext, f) != z->ext))
                    638:     return ZE_TEMP;
                    639:   return ZE_OK;
                    640: }
                    641: 
                    642: int putextended(z, f)
                    643: struct zlist far *z;    /* zip entry to write local header for */
                    644: FILE *f;                /* file to write to */
                    645: /* Write an extended local header described by *z to file *f.
                    646:  * Return an error code in the ZE_ class. */
                    647: {
                    648:   PUTLG(EXTLOCSIG, f);
                    649:   PUTLG(z->crc, f);
                    650:   PUTLG(z->siz, f);
                    651:   PUTLG(z->len, f);
                    652:   return ZE_OK;
                    653: }
                    654: 
                    655: int putcentral(z, f)
                    656: struct zlist far *z;    /* zip entry to write central header for */
                    657: FILE *f;                /* file to write to */
                    658: /* Write a central header described by *z to file *f.  Return an error code
                    659:    in the ZE_ class. */
                    660: {
                    661:   PUTLG(CENSIG, f);
                    662:   PUTSH(z->vem, f);
                    663:   PUTSH(z->ver, f);
                    664:   PUTSH(z->flg, f);
                    665:   PUTSH(z->how, f);
                    666:   PUTLG(z->tim, f);
                    667:   PUTLG(z->crc, f);
                    668:   PUTLG(z->siz, f);
                    669:   PUTLG(z->len, f);
                    670:   PUTSH(z->nam, f);
                    671:   PUTSH(z->cext, f);
                    672:   PUTSH(z->com, f);
                    673:   PUTSH(z->dsk, f);
                    674:   PUTSH(z->att, f);
                    675:   PUTLG(z->atx, f);
                    676:   PUTLG(z->off, f);
                    677:   if (fwrite(z->zname, 1, z->nam, f) != z->nam ||
                    678:       (z->cext && fwrite(z->cextra, 1, z->cext, f) != z->cext) ||
                    679:       (z->com && fwrite(z->comment, 1, z->com, f) != z->com))
                    680:     return ZE_TEMP;
                    681:   return ZE_OK;
                    682: }
                    683: 
                    684: 
                    685: int putend(n, s, c, m, z, f)
                    686: int n;                  /* number of entries in central directory */
                    687: ulg s, c;               /* size and offset of central directory */
                    688: extent m;               /* length of zip file comment (0 if none) */
                    689: char *z;                /* zip file comment if m != 0 */
                    690: FILE *f;                /* file to write to */
                    691: /* Write the end of central directory data to file *f.  Return an error code
                    692:    in the ZE_ class. */
                    693: {
                    694:   PUTLG(ENDSIG, f);
                    695:   PUTSH(0, f);
                    696:   PUTSH(0, f);
                    697:   PUTSH(n, f);
                    698:   PUTSH(n, f);
                    699:   PUTLG(s, f);
                    700:   PUTLG(c, f);
                    701:   PUTSH(m, f);
                    702:   if (m && fwrite(z, 1, m, f) != m)
                    703:     return ZE_TEMP;
                    704:   return ZE_OK;
                    705: }
                    706: 
                    707: 
                    708: #ifndef UTIL
                    709: 
                    710: local char *cutpath(p)
                    711: char *p;                /* path string */
                    712: /* Cut the last path component off the name *p in place.  Return p. */
                    713: {
                    714:   char *r;              /* pointer to last path delimiter */
                    715: 
                    716: #ifdef VMS                      /* change [w.x.y]z to [w.x]y.DIR */
                    717:   if ((r = strrchr(p, ']')) != NULL)
                    718:   {
                    719:     *r = 0;
                    720:     if ((r = strrchr(p, '.')) != NULL)
                    721:     {
                    722:       *r = ']';
                    723:       strcat(r, ".DIR");        /* this assumes a little padding--see PAD */
                    724:     }
                    725:     else
                    726:       *p = 0;
                    727:   }
                    728:   else
                    729:     *p = 0;
                    730: #else /* !VMS */                /* change w/x/y/z to w/x/y */
                    731:   if ((r = strrchr(p, '/')) != NULL)
                    732:     *r = 0;
                    733:   else
                    734:     *p = 0;
                    735: #endif /* ?VMS */
                    736:   return p;
                    737: }
                    738: 
                    739: 
                    740: int trash()
                    741: /* Delete the compressed files and the directories that contained the deleted
                    742:    files, if empty.  Return an error code in the ZE_ class.  Failure of
                    743:    destroy() or deletedir() is ignored. */
                    744: {
                    745:   extent i;             /* counter on deleted names */
                    746:   extent k;             /* number of deleted directories this pass */
                    747:   extent n;             /* number of deleted names left to handle */
                    748:   struct zlist far **s; /* table of zip entries to handle, sorted */
                    749:   struct zlist far *z;  /* current zip entry */
                    750: 
                    751:   /* Count and delete marked names */
                    752:   n = 0;
                    753:   for (z = zfiles; z != NULL; z = z->nxt)
                    754:     if (z->mark || z->trash)
                    755:     {
                    756:       if (z->zname[z->nam - 1] == '/') /* directory */
                    757:         z->mark = z->trash = 0;
                    758:       else {
                    759:         z->mark = 1;
                    760:         n++;
                    761:         if (verbose)
                    762:           printf("zip diagnostic: trashing file %s\n", z->name);
                    763:         destroy(z->name);
                    764:       }
                    765:     }
                    766: 
                    767:   /* Try to delete all paths that lead up to marked names */
                    768:   if (n)
                    769:   {
                    770:     if ((s = (struct zlist far **)malloc((n+1)*sizeof(struct zlist far *))) ==
                    771:         NULL ||
                    772:         (s[0] = (struct zlist far *)farmalloc(sizeof(struct zlist))) == NULL)
                    773:       return ZE_MEM;
                    774:     s[0]->name = "";
                    775:     s++;
                    776:     do {
                    777:       n = k = 0;
                    778:       for (z = zfiles; z != NULL; z = z->nxt)
                    779:         if (z->mark)
                    780:           s[n++] = z;
                    781:       qsort((char *)s, n, sizeof(struct zlist far *), zqcmp);
                    782:       for (i = 0; i < n; i++)
                    783:         if (*cutpath(s[i]->name) && strcmp(s[i]->name, s[i-1]->name))
                    784:         {
                    785:           if (verbose)
                    786:             printf("zip diagnostic: trashing directory %s (if empty)\n",
                    787:                    s[i]->name);
                    788:           deletedir(s[i]->name);
                    789:           k++;
                    790:         }
                    791:         else
                    792:           s[i]->mark = 0;
                    793:     } while (k);
                    794:     farfree((voidp far *)((--s)[0]));
                    795:     free((voidp *)s);
                    796:   }
                    797:   return ZE_OK;
                    798: }
                    799: 
                    800: #endif /* !UTIL */

unix.superglobalmegacorp.com

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