|
|
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.