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 >
C/C++ Source or Header  |  1991-02-10  |  10KB  |  404 lines

  1. /* v3.05 File related functions for unzip.c */
  2.  
  3. /*
  4.  * input file variables
  5.  *
  6.  */
  7.  
  8. #define INBUFSIZ BUFSIZ     /* same as stdio uses */
  9. byte *inbuf;            /* input file buffer - any size is legal */
  10. byte *inptr;
  11.  
  12. int incnt;
  13. UWORD bitbuf;
  14. int bits_left;
  15. boolean zipeof;
  16.  
  17. int zipfd;
  18. char __huge zipfn[STRSIZ];
  19. local_file_header lrec;
  20.  
  21. /* ----------------------------------------------------------- */
  22. /*
  23.  * output stream variables
  24.  *
  25.  */
  26.  
  27. byte *outbuf;                   /* buffer for rle look-back */
  28. byte *outptr;
  29. byte *outout;                 /* Scratch pad for ascebc trans v2.0g */
  30.  
  31. longint outpos;         /* absolute position in outfile */
  32. int outcnt;             /* current position in outbuf */
  33.  
  34. int outfd;
  35. char filename[STRSIZ];
  36. char extra[STRSIZ];
  37. char comment[STRSIZ];       /* v2.0b made it global for displays */
  38.  
  39.  
  40. void set_file_time()
  41.  /*
  42.   * set the output file date/time stamp according to information from the
  43.   * zipfile directory record for this file
  44.   */
  45. {
  46. #ifndef UNIX
  47. #ifndef AMIGA
  48.     union {
  49.         struct ftime ft;        /* system file time record */
  50.         struct {
  51.                 UWORD ztime;     /* date and time words */
  52.                 UWORD zdate;     /* .. same format as in .ZIP file */
  53.         } zt;
  54.     } td;
  55.  
  56.     /*
  57.      * set output file date and time - this is optional and can be
  58.      * deleted if your compiler does not easily support setftime()
  59.      */
  60.  
  61.     td.zt.ztime = lrec.last_mod_file_time;
  62.     td.zt.zdate = lrec.last_mod_file_date;
  63.  
  64.     setftime(outfd, &td.ft);
  65.  
  66. #endif    /* AMIGA */
  67. #else   /* UNIX */
  68.  
  69.     time_t times[2];
  70.     struct tm *tmbuf;
  71.     long m_time;
  72.     int yr, mo, dy, hh, mm, ss, leap, days = 0;
  73. #ifdef BSD
  74.     struct timeval tv;
  75.     struct timezone tz;
  76. #endif
  77.  
  78.     /*
  79.      * These date conversions look a little wierd, so I'll explain.
  80.      * UNIX bases all file modification times on the number of seconds
  81.      * elapsed since Jan 1, 1970, 00:00:00 GMT.  Therefore, to maintain
  82.      * compatibility with MS-DOS archives, which date from Jan 1, 1980,
  83.      * with NO relation to GMT, the following conversions must be made:
  84.      *      the Year (yr) must be incremented by 10;
  85.      *      the Date (dy) must be decremented by 1;
  86.      *      and the whole mess must be adjusted by TWO factors:
  87.      *          relationship to GMT (ie.,Pacific Time adds 8 hrs.),
  88.      *          and whether or not it is Daylight Savings Time.
  89.      * Also, the usual conversions must take place to account for leap years,
  90.      * etc.
  91.      *                                     C. Seaman
  92.      */
  93.  
  94.     yr = (((lrec.last_mod_file_date >> 9) & 0x7f) + 10);  /* dissect date */
  95.     mo = ((lrec.last_mod_file_date >> 5) & 0x0f);
  96.     dy = ((lrec.last_mod_file_date & 0x1f) - 1);
  97.  
  98.     hh = ((lrec.last_mod_file_time >> 11) & 0x1f);        /* dissect time */
  99.     mm = ((lrec.last_mod_file_time >> 5) & 0x3f);
  100.     ss = ((lrec.last_mod_file_time & 0x1f) * 2);
  101.  
  102.     /* leap = # of leap years from 1970 up to but not including
  103.        the current year */
  104.  
  105.     leap = ((yr+1969)/4);              /* Leap year base factor */
  106.  
  107.     /* How many days from 1970 to this year? */
  108.     days = (yr * 365) + (leap - 492);
  109.  
  110.     switch(mo)                 /* calculate expired days this year */
  111.     {
  112.     case 12:
  113.         days += 30;
  114.     case 11:
  115.         days += 31;
  116.     case 10:
  117.         days += 30;
  118.     case 9:
  119.         days += 31;
  120.     case 8:
  121.         days += 31;
  122.     case 7:
  123.         days += 30;
  124.     case 6:
  125.         days += 31;
  126.     case 5:
  127.         days += 30;
  128.     case 4:
  129.         days += 31;
  130.     case 3:
  131.         days += 28;                    /* account for leap years */
  132.         if (((yr+1970) % 4 == 0) && (yr+1970) != 2000)
  133.             ++days;
  134.     case 2:
  135.         days += 31;
  136.     }
  137.  
  138.     /* convert date & time to seconds relative to 00:00:00, 01/01/1970 */
  139.     m_time = ((days + dy) * 86400) + (hh * 3600) + (mm * 60) + ss;
  140.  
  141. #ifdef BSD
  142.     gettimeofday(&tv, &tz);
  143. /* This program is TOO smart about daylight savings time.
  144.  * Adjusting for it throws our file times off by one hour if it's true.
  145.  * Remming it out.
  146.  *
  147.  *  if (tz.tz_dsttime != 0)
  148.  *      m_time -= 3600;
  149.  */
  150.     m_time += tz.tz_minuteswest * 60;  /* account for timezone differences */
  151. #else   /* !BSD */
  152.     tmbuf = localtime(&m_time);
  153.     hh = tmbuf->tm_hour;
  154.     tmbuf = gmtime(&m_time);
  155.     hh = tmbuf->tm_hour - hh;
  156.     if (hh < 0)
  157.     hh += 24;
  158.     m_time += (hh * 3600);             /* account for timezone differences */
  159. #endif
  160.  
  161.     times[0] = m_time;             /* set the stamp on the file */
  162.     times[1] = m_time;
  163.     utime(filename, times);
  164. #endif  /* UNIX */
  165. }
  166.  
  167.  
  168. int create_output_file()
  169.  /* return non-0 if creat failed */
  170. {   /* create the output file with READ and WRITE permissions */
  171.     static int do_all = 0;
  172.     char answerbuf[10];
  173.     UWORD holder;
  174.  
  175.     if (cflag) {        /* output to stdout (a copy of it, really) */
  176. #ifdef    AMIGA
  177.     outfd = 1;
  178. #else
  179.         outfd = dup(1);
  180. #endif    /* AMIGA */
  181.         return 0;
  182.         }
  183.     CR_flag = 0;    /* Hack to get CR at end of buffer working. */
  184.  
  185.     /* 
  186.      * check if the file exists, unless do_all 
  187.      * ask before overwrite code by Bill Davidsen (davidsen@crdos1.crd.ge.com)
  188.      */
  189.     if (!do_all) {
  190.         outfd = open(filename, 0);
  191.     if (outfd >= 0) {
  192.         /* first close it, before you forget! */
  193.         close(outfd);
  194.  
  195.         /* ask the user before blowing it away */
  196.         fprintf(stderr, "replace %s, y-yes, n-no, a-all: ", filename);
  197.         fgets(answerbuf, 9, stdin);
  198.  
  199.         switch (answerbuf[0]) {
  200.           case 'y':
  201.           case 'Y':
  202.             break;
  203.           case 'a':
  204.           case 'A':
  205.             do_all = 1;
  206.         break;
  207.           case 'n':
  208.           case 'N':
  209.           default:
  210.             while(ReadByte(&holder));
  211.         return 1; /* it's done! */
  212.         }
  213.     }
  214.     }
  215.  
  216. #ifndef UNIX
  217.     outfd = creat(filename, S_IWRITE | S_IREAD);
  218. #else
  219.     outfd = creat(filename, 0666);  /* let umask strip unwanted perm's */
  220. #endif
  221.  
  222.     if (outfd < 1) {
  223.         fprintf(stderr, "Can't create output: %s\n", filename);
  224.         return 1;
  225.     }
  226.  
  227.     /*
  228.      * close the newly created file and reopen it in BINARY mode to
  229.      * disable all CR/LF translations
  230.      */
  231. #ifndef UNIX
  232. #ifndef AMIGA
  233.     close(outfd);
  234.     outfd = open(filename, O_RDWR | O_BINARY);
  235. #endif    /* AMIGA */
  236. #endif
  237.     return 0;
  238. }
  239.  
  240.  
  241. int open_input_file()
  242.  /* return non-0 if open failed */
  243. {
  244.     /*
  245.      * open the zipfile for reading and in BINARY mode to prevent cr/lf
  246.      * translation, which would corrupt the bitstreams
  247.      */
  248.  
  249. #ifdef    AMIGA
  250.     zipfd = open(zipfn, O_RDONLY);
  251. #else
  252. #ifndef UNIX
  253.     zipfd = open(zipfn, O_RDONLY | O_BINARY);
  254. #else
  255.     zipfd = open(zipfn, O_RDONLY);
  256. #endif
  257. #endif    /* AMIGA */
  258.     if (zipfd < 1) {
  259.         fprintf(stderr, "Can't open input file: %s\n", zipfn);
  260.         return (1);
  261.     }
  262.     return 0;
  263. }
  264.  
  265. /* ============================================================= */
  266.  
  267. int __regargs readbuf(fd, buf, size)
  268. int fd;
  269. char *buf;
  270. unsigned size;
  271. {
  272.     register int count;
  273.     int n;
  274.  
  275.     n = size;
  276.     while (size)  {
  277.         if (incnt == 0)  {
  278.             if ((incnt = read(fd, inbuf, INBUFSIZ)) <= 0)
  279.                 return(incnt);
  280.             inptr = inbuf;
  281.         }
  282.         count = min(size, incnt);
  283.         zmemcpy(buf, inptr, count);
  284.         buf += count;
  285.         inptr += count;
  286.         incnt -= count;
  287.         size -= count;
  288.     }
  289.     return(n);
  290. }
  291.  
  292. int ReadByte(x)
  293. UWORD *x;
  294.  /* read a byte; return 8 if byte available, 0 if not */
  295. {
  296.     if (csize-- <= 0)
  297.         return 0;
  298.     if (incnt == 0)  {
  299.         if ((incnt = read(zipfd, inbuf, INBUFSIZ)) <= 0)
  300.             return 0;
  301.         inptr = inbuf;
  302.     }
  303.     *x = *inptr++;
  304.     --incnt;
  305.     return 8;
  306. }
  307.  
  308.  
  309. /* ------------------------------------------------------------- */
  310. static UWORD mask_bits[] =
  311.         {0,     0x0001, 0x0003, 0x0007, 0x000f,
  312.                 0x001f, 0x003f, 0x007f, 0x00ff,
  313.                 0x01ff, 0x03ff, 0x07ff, 0x0fff,
  314.                 0x1fff, 0x3fff, 0x7fff, 0xffff
  315.         };
  316.  
  317.  
  318. int __regargs FillBitBuffer(bits)
  319. int bits;
  320. {
  321.     /* get the bits that are left and read the next UWORD */
  322.         register int result = bitbuf;
  323.     UWORD temp;
  324.     int sbits = bits_left;
  325.     bits -= bits_left;
  326.  
  327.     /* read next UWORD of input */
  328.     bits_left = ReadByte(&bitbuf);
  329.     bits_left += ReadByte(&temp);
  330.  
  331.     bitbuf |= (temp << 8);
  332.     if (bits_left == 0)
  333.         zipeof = 1;
  334.  
  335.     /* get the remaining bits */
  336.         result = result | (int) ((bitbuf & mask_bits[bits]) << sbits);
  337.         bitbuf >>= bits;
  338.         bits_left -= bits;
  339.         return result;
  340. }
  341.  
  342. /* ------------------------------------------------------------- */
  343.  
  344. int dos2unix (buf, len)
  345. unsigned char *buf;
  346. int len;
  347. {
  348.     int new_len;
  349.     int i;
  350.     unsigned char *walker;
  351.  
  352.     new_len = len;
  353.     walker = outout;
  354.     if (CR_flag && *buf != LF)
  355.         *walker++ = ascii_to_native(CR);
  356.     CR_flag = buf[len - 1] == CR;
  357.     for (i = 0; i < len; i += 1) {
  358.         *walker++ = *buf;
  359.         if (*buf++ == CR && *buf == LF) {
  360.             new_len--;
  361.             walker[-1] = ascii_to_native(*buf++);
  362.             i++;
  363.         }
  364.     }
  365.     /*
  366.      * If the last character is a CR, then "ignore it" for now...
  367.      */
  368.     if (walker[-1] == CR)
  369.         new_len--;
  370.     return new_len;
  371. }
  372.  
  373. void WriteBuffer(fd, buf, len)
  374. int fd;
  375. unsigned char *buf;
  376. int len;
  377. {
  378.      if (aflag)
  379.          len = dos2unix (buf, len);
  380.      if (write (fd, outout, len) != len) {
  381.          fprintf (stderr, "Fatal write error.\n");
  382.          exit (1);
  383.      }
  384. }
  385.  
  386.  
  387. /* ------------------------------------------------------------- */
  388.  
  389. void FlushOutput()
  390.  /* flush contents of output buffer */
  391. {
  392.     if (outcnt) {
  393.         UpdateCRC(outbuf, outcnt);
  394.  
  395.         if (!tflag)
  396.             WriteBuffer(outfd, outbuf, outcnt);
  397.  
  398.         outpos += outcnt;
  399.         outcnt = 0;
  400.         outptr = outbuf;
  401.     }
  402. }
  403.  
  404.