|
|
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: * zipup.c by Mark Adler. Includes modifications by Jean-loup Gailly. ! 14: */ ! 15: ! 16: #define NOCPYRT /* this is not a main module */ ! 17: #include <ctype.h> ! 18: #include "zip.h" ! 19: #include "revision.h" ! 20: #ifdef OS2 ! 21: # include "os2zip.h" ! 22: #endif ! 23: ! 24: /* Use the raw functions for MSDOS and Unix to save on buffer space. ! 25: They're not used for VMS since it doesn't work (raw is weird on VMS). ! 26: (This sort of stuff belongs in fileio.c, but oh well.) */ ! 27: #ifdef VMS ! 28: # define fhow "r" ! 29: # define fbad NULL ! 30: typedef void *ftype; ! 31: # define zopen(n,p) (vms_native?vms_open(n) :(ftype)fopen((n),(p))) ! 32: # define zread(f,b,n) (vms_native?vms_read(f,b,n):fread((b),1,(n),(FILE*)(f))) ! 33: # define zclose(f) (vms_native?vms_close(f) :fclose((FILE*)(f))) ! 34: # define zerr(f) (vms_native?vms_error(f) :ferror((FILE*)(f))) ! 35: # define zstdin stdin ! 36: ftype vms_open OF((char *)); ! 37: int vms_read OF((ftype, char *, int)); ! 38: int vms_close OF((ftype)); ! 39: int vms_error OF((ftype)); ! 40: #else /* !VMS */ ! 41: # if defined(MSDOS) && !defined(ATARI_ST) ! 42: # include <io.h> ! 43: # include <fcntl.h> ! 44: # define fhow (O_RDONLY|O_BINARY) ! 45: # else /* !MSDOS */ ! 46: int open OF((char *, int)); ! 47: int read OF((int, char *, int)); ! 48: int close OF((int)); ! 49: int lseek OF((int, long, int)); ! 50: # define fhow 0 ! 51: # endif /* ?MSDOS */ ! 52: typedef int ftype; ! 53: # define fbad (-1) ! 54: # define zopen(n,p) open(n,p) ! 55: # define zread(f,b,n) read(f,b,n) ! 56: # define zclose(f) close(f) ! 57: # define zerr(f) (k==(extent)(-1L)) ! 58: # define zstdin 0 ! 59: #endif /* ?VMS */ ! 60: ! 61: ! 62: /* Local data */ ! 63: ! 64: #ifndef UTIL ! 65: local ulg crc; /* crc on uncompressed file data */ ! 66: local ftype ifile; /* file to compress */ ! 67: #endif ! 68: ulg isize; /* input file size. global only for debugging */ ! 69: ! 70: /* Local functions */ ! 71: #if defined(PROTO) && !defined(UTIL) ! 72: local int suffixes(char *, char *); ! 73: #endif ! 74: ! 75: ! 76: /* Note: a zip "entry" includes a local header (which includes the file ! 77: name), an encryption header if encrypting, the compressed data ! 78: and possibly an extended local header. */ ! 79: ! 80: int zipcopy(z, x, y) ! 81: struct zlist far *z; /* zip entry to copy */ ! 82: FILE *x, *y; /* source and destination files */ ! 83: /* Copy the zip entry described by *z from file *x to file *y. Return an ! 84: error code in the ZE_ class. Also update tempzn by the number of bytes ! 85: copied. */ ! 86: { ! 87: ulg n; /* holds local header offset */ ! 88: ! 89: if (fseek(x, z->off, SEEK_SET)) ! 90: return ferror(x) ? ZE_READ : ZE_EOF; ! 91: z->off = tempzn; ! 92: n = 4 + LOCHEAD + (long)z->nam + (long)z->ext + z->siz; ! 93: /* copy the extended local header if there is one */ ! 94: if (z->lflg & 8) n += 16; ! 95: tempzn += n; ! 96: return fcopy(x, y, n); ! 97: } ! 98: ! 99: ! 100: #ifndef UTIL ! 101: ! 102: int percent(n, m) ! 103: long n, m; /* n is the original size, m is the new size */ ! 104: /* Return the percentage compression from n to m using only integer ! 105: operations */ ! 106: { ! 107: if (n > 0xffffffL) /* If n >= 16M */ ! 108: { /* then divide n and m by 256 */ ! 109: n += 0x80; n >>= 8; ! 110: m += 0x80; m >>= 8; ! 111: } ! 112: return n ? (int)(1 + (200 * (n - m)/n)) / 2 : 0; ! 113: } ! 114: ! 115: local int suffixes(a, s) ! 116: char *a; /* name to check suffix of */ ! 117: char *s; /* list of suffixes separated by : or ; */ ! 118: /* Return true if a ends in any of the suffixes in the list s. */ ! 119: { ! 120: int m; /* true if suffix matches so far */ ! 121: char *p; /* pointer into special */ ! 122: char *q; /* pointer into name a */ ! 123: ! 124: m = 1; ! 125: #ifdef VMS ! 126: if( (q = strrchr(a,';')) != NULL ) /* Cut out VMS file version */ ! 127: --q; ! 128: else ! 129: q = a + strlen(a) - 1; ! 130: #else ! 131: q = a + strlen(a) - 1; ! 132: #endif ! 133: for (p = s + strlen(s) - 1; p >= s; p--) ! 134: if (*p == ':' || *p == ';') ! 135: if (m) ! 136: return 1; ! 137: else ! 138: { ! 139: m = 1; ! 140: #ifdef VMS ! 141: if( (q = strrchr(a,';')) != NULL ) /* Cut out VMS file version */ ! 142: --q; ! 143: else ! 144: q = a + strlen(a) - 1; ! 145: #else ! 146: q = a + strlen(a) - 1; ! 147: #endif ! 148: } ! 149: else ! 150: { ! 151: m = m && q >= a && case_map(*p) == case_map(*q); ! 152: q--; ! 153: } ! 154: return m; ! 155: } ! 156: ! 157: int zipup(z, y) ! 158: struct zlist far *z; /* zip entry to compress */ ! 159: FILE *y; /* output file */ ! 160: /* Compress the file z->name into the zip entry described by *z and write ! 161: it to the file *y. Encrypt if requested. Return an error code in the ! 162: ZE_ class. Also, update tempzn by the number of bytes written. */ ! 163: { ! 164: ulg a = 0L; /* attributes returned by filetime() */ ! 165: char *b; /* malloc'ed file buffer */ ! 166: extent k = 0; /* result of zread */ ! 167: int l = 0; /* true if this file is a symbolic link */ ! 168: int m; /* method for this entry */ ! 169: ulg o, p; /* offsets in zip file */ ! 170: long q = -2L; /* size returned by filetime */ ! 171: int r; /* temporary variable */ ! 172: ulg s = 0L; /* size of compressed data */ ! 173: int isdir; /* set for a directory name */ ! 174: ! 175: isdir = z->name[strlen(z->name)-1] == '/'; ! 176: ! 177: if ((z->tim = filetime(z->name, &a, &q)) == 0 || q < -1L) ! 178: return ZE_OPEN; ! 179: /* q is set to -1 if the input file is a device */ ! 180: ! 181: z->nam = strlen(z->zname); ! 182: ! 183: /* Select method based on the suffix and the global method */ ! 184: m = special != NULL && suffixes(z->name, special) ? STORE : method; ! 185: ! 186: /* Open file to zip up unless it is stdin */ ! 187: if (strcmp(z->name, "-") == 0) ! 188: { ! 189: ifile = (ftype)zstdin; ! 190: #ifdef MSDOS ! 191: setmode(zstdin, O_BINARY); ! 192: #endif ! 193: } ! 194: else ! 195: { ! 196: #ifdef VMS ! 197: if (vms_native) ! 198: get_vms_attributes(z); ! 199: #endif ! 200: #ifdef OS2 ! 201: GetEAs(z->name, &z->extra, &z->ext, &z->cextra, &z->cext); ! 202: /* store data in local header, and size only in central headers */ ! 203: #endif ! 204: l = issymlnk(a); ! 205: if (l) ! 206: ifile = fbad; ! 207: else if (isdir) { /* directory */ ! 208: ifile = fbad; ! 209: m = STORE; ! 210: } ! 211: else if ((ifile = zopen(z->name, fhow)) == fbad) ! 212: return ZE_OPEN; ! 213: } ! 214: ! 215: if (l || q == 0) ! 216: m = STORE; ! 217: if (m == BEST) ! 218: m = DEFLATE; ! 219: ! 220: /* Do not create STORED files with extended local headers if the ! 221: * input size is not known, because such files could not be extracted. ! 222: * So if the zip file is not seekable and the input file is not ! 223: * on disk, obey the -0 option by forcing deflation with stored block. ! 224: * Note however that using "zip -0" as filter is not very useful... ! 225: * ??? to be done. ! 226: */ ! 227: ! 228: /* Fill in header information and write local header to zip file. ! 229: * This header will later be re-written since compressed length and ! 230: * crc are not yet known. ! 231: */ ! 232: ! 233: /* (Assume ext, cext, com, and zname already filled in.) */ ! 234: #ifdef OS2 ! 235: z->vem = z->dosflag ? 20 : /* Made under MSDOS by PKZIP 2.0 */ ! 236: /* We for a FAT file system, we must cheat and pretend that the ! 237: * file was not made on OS2 but under DOS. unzip is confused otherwise. ! 238: */ ! 239: #else ! 240: z->vem = dosify ? 20 : /* Made under MSDOS by PKZIP 2.0 */ ! 241: #endif ! 242: #ifdef VMS ! 243: 0x200 + REVISION; /* Made under VMS by this Zip */ ! 244: #else /* !VMS */ ! 245: # ifdef OS2 ! 246: 0x600 + REVISION; /* Made under OS/2 by this Zip */ ! 247: # else /* !OS2 */ ! 248: # ifdef MSDOS ! 249: 0 + REVISION; /* Made under MSDOS by this Zip */ ! 250: # else ! 251: 0x300 + REVISION; /* Made under Unix by this Zip */ ! 252: # endif /* MSDOS */ ! 253: # endif /* ?OS2 */ ! 254: #endif /* ?VMS */ ! 255: ! 256: z->ver = 20; /* Need PKUNZIP 2.0 */ ! 257: z->crc = 0; /* to be updated later */ ! 258: /* Assume first that we will need an extended local header: */ ! 259: z->flg = 8; /* to be updated later */ ! 260: #ifdef CRYPT ! 261: if (key != NULL) { ! 262: z->flg |= 1; ! 263: /* Since we do not yet know the crc here, we pretend that the crc ! 264: * is the modification time: ! 265: */ ! 266: z->crc = z->tim << 16; ! 267: } ! 268: #endif ! 269: z->lflg = z->flg; ! 270: z->how = m; /* may be changed later */ ! 271: z->siz = m == STORE && q >= 0 ? q : 0; /* will be changed later */ ! 272: z->len = q >= 0 ? q : 0; /* may be changed later */ ! 273: z->dsk = 0; ! 274: z->att = BINARY; /* may be changed later */ ! 275: z->atx = z->dosflag ? a & 0xff : a; /* Attributes from filetime() */ ! 276: z->off = tempzn; ! 277: if ((r = putlocal(z, y)) != ZE_OK) ! 278: return r; ! 279: tempzn += 4 + LOCHEAD + z->nam + z->ext; ! 280: ! 281: #ifdef CRYPT ! 282: if (key != NULL) { ! 283: crypthead(key, z->crc, y); ! 284: z->siz += 12; /* to be updated later */ ! 285: tempzn += 12; ! 286: } ! 287: #endif ! 288: o = ftell(y); /* for debugging only */ ! 289: ! 290: /* Write stored or deflated file to zip file */ ! 291: isize = 0L; ! 292: crc = updcrc((char *)NULL, 0); ! 293: ! 294: if (m == DEFLATE) { ! 295: bi_init(y); ! 296: z->att = (ush)UNKNOWN; ! 297: ct_init(&z->att, &m); ! 298: lm_init(level, &z->flg); ! 299: s = deflate(); ! 300: } ! 301: else ! 302: { ! 303: if ((b = malloc(CBSZ)) == NULL) ! 304: return ZE_MEM; ! 305: ! 306: if (!isdir) /* no read for directories */ ! 307: while ((k = l ? rdsymlnk(z->name, b, CBSZ) : zread(ifile, b, CBSZ)) > 0) ! 308: { ! 309: isize += k; ! 310: crc = updcrc(b, k); ! 311: if (zfwrite(b, 1, k, y) != k) ! 312: { ! 313: free((voidp *)b); ! 314: return ZE_TEMP; ! 315: } ! 316: #ifdef MINIX ! 317: if (l) ! 318: q = k; ! 319: #endif /* MINIX */ ! 320: if (l) ! 321: break; ! 322: } ! 323: free((voidp *)b); ! 324: s = isize; ! 325: } ! 326: if (ifile != fbad && zerr(ifile)) ! 327: return ZE_READ; ! 328: if (ifile != fbad) ! 329: zclose(ifile); ! 330: ! 331: tempzn += s; ! 332: p = tempzn; /* save for future fseek() */ ! 333: ! 334: #ifndef VMS ! 335: /* Check input size (but not in VMS--variable record lengths mess it up) */ ! 336: if (q >= 0 && isize != (ulg)q && !translate_eol) ! 337: { ! 338: fprintf(mesg, " i=%ld, q=%ld ", isize, q); ! 339: error("incorrect input size"); ! 340: } ! 341: #endif /* !VMS */ ! 342: ! 343: /* Try to rewrite the local header with correct information */ ! 344: z->crc = crc; ! 345: z->siz = s; ! 346: #ifdef CRYPT ! 347: if (key != NULL) ! 348: z->siz += 12; ! 349: #endif ! 350: z->len = isize; ! 351: if (fseek(y, z->off, SEEK_SET)) { ! 352: if (z->how != (ush) m) ! 353: error("can't rewrite method"); ! 354: if (m == STORE && q < 0) ! 355: error("zip -0 not allowed for input/output from/to pipe or device"); ! 356: if ((r = putextended(z, y)) != ZE_OK) ! 357: return r; ! 358: tempzn += 16L; ! 359: z->flg = z->lflg; /* if flg modified by inflate */ ! 360: } else { ! 361: /* seek ok, ftell() should work, check compressed size */ ! 362: #ifndef VMS ! 363: if (p - o != s) { ! 364: fprintf(mesg, " s=%ld, actual=%ld ", s, p-o); ! 365: error("incorrect compressed size"); ! 366: } ! 367: #endif ! 368: z->how = m; ! 369: if ((z->flg & 1) == 0) ! 370: z->flg &= ~8; /* clear the extended local header flag */ ! 371: z->lflg = z->flg; ! 372: /* rewrite the local header: */ ! 373: if ((r = putlocal(z, y)) != ZE_OK) ! 374: return r; ! 375: if (fseek(y, p, SEEK_SET)) ! 376: return ZE_READ; ! 377: if ((z->flg & 1) != 0) { ! 378: /* encrypted file, extended header still required */ ! 379: if ((r = putextended(z, y)) != ZE_OK) ! 380: return r; ! 381: tempzn += 16L; ! 382: } ! 383: } ! 384: ! 385: /* Display statistics */ ! 386: if (noisy) ! 387: { ! 388: if (verbose) ! 389: fprintf(mesg, " (in=%lu) (out=%lu)", isize, s); ! 390: if (m == DEFLATE) ! 391: fprintf(mesg, " (deflated %d%%)\n", percent(isize, s)); ! 392: else ! 393: fprintf(mesg, " (stored 0%%)\n"); ! 394: fflush(mesg); ! 395: } ! 396: return ZE_OK; ! 397: } ! 398: ! 399: ! 400: int file_read(buf, size) ! 401: char *buf; ! 402: unsigned size; ! 403: /* Read a new buffer from the current input file, and update the crc and ! 404: * input file size. ! 405: * IN assertion: size >= 2 (for end-of-line translation) ! 406: */ ! 407: { ! 408: unsigned len; ! 409: char far *b; ! 410: if (translate_eol) { ! 411: size >>= 1; ! 412: b = buf+size; ! 413: size = len = zread(ifile, b, size); ! 414: if (len == (unsigned)EOF || len == 0) return len; ! 415: do { ! 416: if ((*buf++ = *b++) == '\n') *(buf-1) = '\r', *buf++ = '\n', len++; ! 417: } while (--size != 0); ! 418: buf -= len; ! 419: } else { ! 420: len = zread(ifile, buf, size); ! 421: if (len == (unsigned)EOF || len == 0) return len; ! 422: } ! 423: crc = updcrc(buf, len); ! 424: isize += (ulg)len; ! 425: return len; ! 426: } ! 427: #endif /* !UTIL */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.