home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
479a.lha
/
Unzip
/
file_io.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-02-10
|
10KB
|
404 lines
/* v3.05 File related functions for unzip.c */
/*
* input file variables
*
*/
#define INBUFSIZ BUFSIZ /* same as stdio uses */
byte *inbuf; /* input file buffer - any size is legal */
byte *inptr;
int incnt;
UWORD bitbuf;
int bits_left;
boolean zipeof;
int zipfd;
char __huge zipfn[STRSIZ];
local_file_header lrec;
/* ----------------------------------------------------------- */
/*
* output stream variables
*
*/
byte *outbuf; /* buffer for rle look-back */
byte *outptr;
byte *outout; /* Scratch pad for ascebc trans v2.0g */
longint outpos; /* absolute position in outfile */
int outcnt; /* current position in outbuf */
int outfd;
char filename[STRSIZ];
char extra[STRSIZ];
char comment[STRSIZ]; /* v2.0b made it global for displays */
void set_file_time()
/*
* set the output file date/time stamp according to information from the
* zipfile directory record for this file
*/
{
#ifndef UNIX
#ifndef AMIGA
union {
struct ftime ft; /* system file time record */
struct {
UWORD ztime; /* date and time words */
UWORD zdate; /* .. same format as in .ZIP file */
} zt;
} td;
/*
* set output file date and time - this is optional and can be
* deleted if your compiler does not easily support setftime()
*/
td.zt.ztime = lrec.last_mod_file_time;
td.zt.zdate = lrec.last_mod_file_date;
setftime(outfd, &td.ft);
#endif /* AMIGA */
#else /* UNIX */
time_t times[2];
struct tm *tmbuf;
long m_time;
int yr, mo, dy, hh, mm, ss, leap, days = 0;
#ifdef BSD
struct timeval tv;
struct timezone tz;
#endif
/*
* These date conversions look a little wierd, so I'll explain.
* UNIX bases all file modification times on the number of seconds
* elapsed since Jan 1, 1970, 00:00:00 GMT. Therefore, to maintain
* compatibility with MS-DOS archives, which date from Jan 1, 1980,
* with NO relation to GMT, the following conversions must be made:
* the Year (yr) must be incremented by 10;
* the Date (dy) must be decremented by 1;
* and the whole mess must be adjusted by TWO factors:
* relationship to GMT (ie.,Pacific Time adds 8 hrs.),
* and whether or not it is Daylight Savings Time.
* Also, the usual conversions must take place to account for leap years,
* etc.
* C. Seaman
*/
yr = (((lrec.last_mod_file_date >> 9) & 0x7f) + 10); /* dissect date */
mo = ((lrec.last_mod_file_date >> 5) & 0x0f);
dy = ((lrec.last_mod_file_date & 0x1f) - 1);
hh = ((lrec.last_mod_file_time >> 11) & 0x1f); /* dissect time */
mm = ((lrec.last_mod_file_time >> 5) & 0x3f);
ss = ((lrec.last_mod_file_time & 0x1f) * 2);
/* leap = # of leap years from 1970 up to but not including
the current year */
leap = ((yr+1969)/4); /* Leap year base factor */
/* How many days from 1970 to this year? */
days = (yr * 365) + (leap - 492);
switch(mo) /* calculate expired days this year */
{
case 12:
days += 30;
case 11:
days += 31;
case 10:
days += 30;
case 9:
days += 31;
case 8:
days += 31;
case 7:
days += 30;
case 6:
days += 31;
case 5:
days += 30;
case 4:
days += 31;
case 3:
days += 28; /* account for leap years */
if (((yr+1970) % 4 == 0) && (yr+1970) != 2000)
++days;
case 2:
days += 31;
}
/* convert date & time to seconds relative to 00:00:00, 01/01/1970 */
m_time = ((days + dy) * 86400) + (hh * 3600) + (mm * 60) + ss;
#ifdef BSD
gettimeofday(&tv, &tz);
/* This program is TOO smart about daylight savings time.
* Adjusting for it throws our file times off by one hour if it's true.
* Remming it out.
*
* if (tz.tz_dsttime != 0)
* m_time -= 3600;
*/
m_time += tz.tz_minuteswest * 60; /* account for timezone differences */
#else /* !BSD */
tmbuf = localtime(&m_time);
hh = tmbuf->tm_hour;
tmbuf = gmtime(&m_time);
hh = tmbuf->tm_hour - hh;
if (hh < 0)
hh += 24;
m_time += (hh * 3600); /* account for timezone differences */
#endif
times[0] = m_time; /* set the stamp on the file */
times[1] = m_time;
utime(filename, times);
#endif /* UNIX */
}
int create_output_file()
/* return non-0 if creat failed */
{ /* create the output file with READ and WRITE permissions */
static int do_all = 0;
char answerbuf[10];
UWORD holder;
if (cflag) { /* output to stdout (a copy of it, really) */
#ifdef AMIGA
outfd = 1;
#else
outfd = dup(1);
#endif /* AMIGA */
return 0;
}
CR_flag = 0; /* Hack to get CR at end of buffer working. */
/*
* check if the file exists, unless do_all
* ask before overwrite code by Bill Davidsen (davidsen@crdos1.crd.ge.com)
*/
if (!do_all) {
outfd = open(filename, 0);
if (outfd >= 0) {
/* first close it, before you forget! */
close(outfd);
/* ask the user before blowing it away */
fprintf(stderr, "replace %s, y-yes, n-no, a-all: ", filename);
fgets(answerbuf, 9, stdin);
switch (answerbuf[0]) {
case 'y':
case 'Y':
break;
case 'a':
case 'A':
do_all = 1;
break;
case 'n':
case 'N':
default:
while(ReadByte(&holder));
return 1; /* it's done! */
}
}
}
#ifndef UNIX
outfd = creat(filename, S_IWRITE | S_IREAD);
#else
outfd = creat(filename, 0666); /* let umask strip unwanted perm's */
#endif
if (outfd < 1) {
fprintf(stderr, "Can't create output: %s\n", filename);
return 1;
}
/*
* close the newly created file and reopen it in BINARY mode to
* disable all CR/LF translations
*/
#ifndef UNIX
#ifndef AMIGA
close(outfd);
outfd = open(filename, O_RDWR | O_BINARY);
#endif /* AMIGA */
#endif
return 0;
}
int open_input_file()
/* return non-0 if open failed */
{
/*
* open the zipfile for reading and in BINARY mode to prevent cr/lf
* translation, which would corrupt the bitstreams
*/
#ifdef AMIGA
zipfd = open(zipfn, O_RDONLY);
#else
#ifndef UNIX
zipfd = open(zipfn, O_RDONLY | O_BINARY);
#else
zipfd = open(zipfn, O_RDONLY);
#endif
#endif /* AMIGA */
if (zipfd < 1) {
fprintf(stderr, "Can't open input file: %s\n", zipfn);
return (1);
}
return 0;
}
/* ============================================================= */
int __regargs readbuf(fd, buf, size)
int fd;
char *buf;
unsigned size;
{
register int count;
int n;
n = size;
while (size) {
if (incnt == 0) {
if ((incnt = read(fd, inbuf, INBUFSIZ)) <= 0)
return(incnt);
inptr = inbuf;
}
count = min(size, incnt);
zmemcpy(buf, inptr, count);
buf += count;
inptr += count;
incnt -= count;
size -= count;
}
return(n);
}
int ReadByte(x)
UWORD *x;
/* read a byte; return 8 if byte available, 0 if not */
{
if (csize-- <= 0)
return 0;
if (incnt == 0) {
if ((incnt = read(zipfd, inbuf, INBUFSIZ)) <= 0)
return 0;
inptr = inbuf;
}
*x = *inptr++;
--incnt;
return 8;
}
/* ------------------------------------------------------------- */
static UWORD mask_bits[] =
{0, 0x0001, 0x0003, 0x0007, 0x000f,
0x001f, 0x003f, 0x007f, 0x00ff,
0x01ff, 0x03ff, 0x07ff, 0x0fff,
0x1fff, 0x3fff, 0x7fff, 0xffff
};
int __regargs FillBitBuffer(bits)
int bits;
{
/* get the bits that are left and read the next UWORD */
register int result = bitbuf;
UWORD temp;
int sbits = bits_left;
bits -= bits_left;
/* read next UWORD of input */
bits_left = ReadByte(&bitbuf);
bits_left += ReadByte(&temp);
bitbuf |= (temp << 8);
if (bits_left == 0)
zipeof = 1;
/* get the remaining bits */
result = result | (int) ((bitbuf & mask_bits[bits]) << sbits);
bitbuf >>= bits;
bits_left -= bits;
return result;
}
/* ------------------------------------------------------------- */
int dos2unix (buf, len)
unsigned char *buf;
int len;
{
int new_len;
int i;
unsigned char *walker;
new_len = len;
walker = outout;
if (CR_flag && *buf != LF)
*walker++ = ascii_to_native(CR);
CR_flag = buf[len - 1] == CR;
for (i = 0; i < len; i += 1) {
*walker++ = *buf;
if (*buf++ == CR && *buf == LF) {
new_len--;
walker[-1] = ascii_to_native(*buf++);
i++;
}
}
/*
* If the last character is a CR, then "ignore it" for now...
*/
if (walker[-1] == CR)
new_len--;
return new_len;
}
void WriteBuffer(fd, buf, len)
int fd;
unsigned char *buf;
int len;
{
if (aflag)
len = dos2unix (buf, len);
if (write (fd, outout, len) != len) {
fprintf (stderr, "Fatal write error.\n");
exit (1);
}
}
/* ------------------------------------------------------------- */
void FlushOutput()
/* flush contents of output buffer */
{
if (outcnt) {
UpdateCRC(outbuf, outcnt);
if (!tflag)
WriteBuffer(outfd, outbuf, outcnt);
outpos += outcnt;
outcnt = 0;
outptr = outbuf;
}
}