Annotation of coherent/b/bin/zip/zipfile.c, revision 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.