#include #include "modern.h" #include "zalloc.h" #include "zippipe.h" #include "zipguts.h" #include "ziposcod.h" #include "crc32.h" #ifndef UNIX # ifdef M_XENIX # define UNIX # endif # ifdef unix # define UNIX # endif #endif #ifdef UNIX # include #endif #ifdef MSDOS # include # ifdef __TURBOC__ # include # endif #endif static unsigned long dostime __ARGS__((void)) { #ifdef MSDOS # ifdef __TURBOC__ union { struct date d; struct time t; } u; struct ftime f; getdate(&u.d); f.ft_year = u.d.da_year - 1980; f.ft_month = u.d.da_mon; f.ft_day = u.d.da_day; gettime(&u.t); f.ft_hour = u.t.ti_hour; f.ft_min = u.t.ti_min; f.ft_tsec = u.t.ti_sec; return *(unsigned long *)&f; # else uninon REGS r; unsigned d; r.h.ah = 0x2A; /* get date */ intdos(&r, &r); d = ((r.x.cx - 1980) << 9) | (r.h.dh << 5) | r.h.dl; r.h.ah = 0x2C; /* get time */ intdos(&r, &r); return ((unsigned long)d << 16) | (r.h.ch << 11) | (r.h.cl << 5) | (r.h.dh >> 1); # endif #else # ifdef UNIX extern long time(); struct tm *s; long t; (void)time(&t); s = localtime(&t); if (s->tm_year < 80) return 0L; return ((unsigned long)(s->tm_year - 80) << 25) | ((unsigned long)s->tm_mon << 21) | ((unsigned long)s->tm_mday << 16) | ((unsigned)s->tm_hour << 11) | (s->tm_min << 5) | (s->tm_sec >> 1); # else /* dummy time stamp */ return 0L; # endif #endif } #ifndef zalloc /* Turbo C malloc() does not allow dynamic allocation of 64K bytes * and farmalloc(64K) returns a pointer with nonzero offset, so we * must fix the pointer. Warning: the pointer must be saved in its * original form in order to free it, use farfree(). * For MSC, use halloc instead of this function. */ void far *zalloc(void far **p, unsigned n, unsigned s) { register unsigned long l; l = (unsigned long)(*p = farmalloc((unsigned long)n*s + 15)); return (void far *) ((0xffff0000L & l) + (0xffff0000L & (((0xffffL & l) + 15) << 12))); } #endif int zipalloc() { #ifdef DYN_ALLOC if (ct_alloc() != 0) return ZNOMEM; if (lm_alloc() != 0) { ct_free(); return ZNOMEM; } #endif return 0; } void zipfree() { #ifdef DYN_ALLOC lm_free(); ct_free(); #endif } static void putlong __ARGS__((ulg)); static void putlong(l) ulg l; { putword((ush)l); putword((ush)(l >> 16)); } static ulg inpsize; #ifdef DEBUG ulg isize; #endif static int ziptype; int deflate_level = 6; static ulg timestamp; static ush flags; /* speed options for the general purpose bit flag */ #define FAST 4 #define SLOW 2 int zipcreat(putb, ztype, dlevel) void (*putb)__ARGS__((int)); int ztype, dlevel; { register k; if (dlevel<1 || dlevel>9 || (ztype!=ZIP_PKW && ztype!=ZIP_GNU && ztype!=ZIP_RAW)) return (ziperror = ZUNSUP); deflate_level = dlevel; flags = dlevel <= 1 ? FAST : dlevel >= 9 ? SLOW : 0; ziptype = ztype; crcbegin(); bi_init(); if (ct_init() != 0) return (ziperror = ZNOMEM); if ((k=lm_init()) != 0) { #ifdef DYN_ALLOC ct_free(); #endif return (ziperror = k); } ziputbyte = putb; /* Write the header to the gzip file */ /* No extra field, file name or comment; no encryption */ if (ziptype == ZIP_GNU) { putword(GZIP_MAGIC);/* magic header */ putbyte(DEFLATED); /* compression method */ putbyte(0); /* general flags: nothing */ putlong(0L); /* dummy time stamp */ putbyte(flags); /* extra flags */ putbyte(OS_CODE); /* OS identifier */ } else if (ziptype == ZIP_PKW) { putlong(PKW_LOCAL); /* magic header */ putword(19); /* version to extract */ putword(flags|=8); putword(DEFLATED); /* compression method */ /* Who, the hell, needs in this time stamp? */ putlong(timestamp = dostime()); putlong(0L); /* dummy CRC */ putlong(0L); /* dummy compressed size */ putlong(0L); /* dummy original size */ putlong(0L); /* null file name & extra fields */ } inpsize = 0L; return 0; } int zipwrite(buffer, length) char *buffer; unsigned length; { if (!ziputbyte) return (ziperror=ZNOPEN, -1); if (length) { updcrc((unsigned char *)buffer, length); inpsize += length; } return deflate_level > 3 ? lazy_deflate(buffer, length) : fast_deflate(buffer, length); } long zipclose() { extern unsigned minlookahead; register long l = -1; ulg clen, crc; minlookahead = 0; /* indicate end of input */ /* Flush out any remaining bytes */ if (zipwrite(NULL,0) != 0) goto end; clen = (compressed_len >> 3); crc = getcrc(); if (ziptype == ZIP_GNU) { /* Write the crc. & uncompressed size */ putlong(crc); putlong(inpsize); } else if (ziptype == ZIP_PKW) { /* Write the /data descriptor/ extended locxal header */ putlong(PKW_EXT); /* signature */ putlong(crc); /* CRC */ putlong(clen); /* compressed size */ putlong(inpsize); /* uncompressed size */ /* Write the central directory entry */ putlong(PKW_CENTRAL); putword((OS_CODE<<8)|20); /* version made by */ putword(19); /* version to extract */ putword(flags); putword(DEFLATED);/* compression method */ putlong(timestamp); putlong(crc); /* CRC */ putlong(clen); /* compressed size */ putlong(inpsize); /* original size */ putlong(0L); /* filename & extra field length */ putword(0); /* file comment length */ putword(0); /* disk number start */ putword(0); /* internal file attributes */ putlong(0L); /* external file attributes */ putlong(0L); /* relative offset of local header */ /* Finish the central directory */ putlong(PKW_END); putword(0); /* number of this disk */ putword(0); /* number of the disk with the start of CD */ putword(1); /* total number of CD entries on this disk */ putword(1); /* total number of CD entries */ putlong(46L); /* size of the central directory */ putlong(30+clen+16); /* offset of start of CD */ putword(0); /* zipfile comment length */ } l = clen; end: ziputbyte = NULL; zipfree(); return l; }