home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1992 June / SIMTEL_0692.cdr / msdos / zip / zipot11.arc / ZIPOT.C < prev    next >
Text File  |  1989-02-25  |  6KB  |  247 lines

  1. #include    <stdio.h>
  2. #include    <stdlib.h>
  3. #include    <io.h>
  4. #include    <fcntl.h>
  5. #include    <dos.h>
  6. #include    "zip.h"
  7.  
  8. /****************************************************************************
  9.  *                                        *
  10.  *  zipot - change time stamp of ZIP file to be same as its latest contents *
  11.  *                                        *
  12.  *  Initial release : Feb 19, 1989  Russ Herman                 *
  13.  *  Revision 1.1    : Feb 25, 1989                        *
  14.  *              Error in time calculation                 *
  15.  *                                        *
  16.  ****************************************************************************/
  17.  
  18. #define     BUFLEN     512
  19. char        buf[BUFLEN];        /* place to read in file         */
  20. long        buf0_off;            /* file offset corresponding to buf  */
  21. unsigned    buflen;            /* size of the buffer             */
  22. unsigned    bufgood;            /* amount of valid info in buffer    */
  23.  
  24. #ifdef DEBUG
  25. #define REG
  26. #else
  27. #define REG register
  28. #endif
  29.  
  30. /*  prototypes                                     */
  31. long        find_cdt(int);
  32. int        otzip(char *);
  33. void        main(int, char **);
  34.  
  35.  
  36. /* rummage backwards thru the file looking for the trailer signature         */
  37. long find_cdt(int zip_handle)
  38. {
  39.     REG char *p;
  40.     REG int i;
  41.     int front = 0;
  42.  
  43.     bufgood = buflen;
  44.     while (buf0_off >= 0 && !front)
  45.     {
  46.     front = (buf0_off == 0);
  47.     if (buf0_off < BUFLEN)
  48.     {   /* short block                             */
  49.         bufgood = (unsigned) buf0_off;  /* words to read             */
  50.         buf0_off = 0L;            /* position in file          */
  51.     }
  52.  
  53.     /* position to start of block                         */
  54.     if (lseek(zip_handle, buf0_off, 0) < 0L)
  55.     {
  56.         perror("cannot position ZIPfile");
  57.         return(-2l);
  58.     }
  59.  
  60.     /* read some                                 */
  61.     if (read(zip_handle, buf, bufgood) < 0)
  62.     {
  63.         perror("error reading ZIPfile");
  64.         return(-3L);
  65.     }
  66.  
  67.     /* step backwards thru what we just read                */
  68.     for(i=bufgood-4,p=&buf[bufgood-4]; i>=0; i--,p--)
  69.     {
  70.         if (*(unsigned long *)p == CDT_SIG)
  71.         return(buf0_off + i);    /* exit on signature match        */
  72.     }
  73.  
  74.     /* We reread the first 4 bytes of each block as a quick&dirty way of *
  75.      * handling the case where the signature splits our buffer block     */
  76.     buf0_off = buf0_off - bufgood + 4;
  77.    }
  78.    return(-1L);               /* Couldn't find signature         */
  79. }
  80.  
  81.  
  82. /* Process a single ZIPfile                             */
  83. int otzip(char *fname)
  84. {
  85.     int zip_handle;
  86.     int i, ret, later;
  87.     unsigned early_date, early_time;
  88.     long next_cdh;
  89.     long cdt_f_off;
  90.     long zip_fsize;
  91.     CDH *cdhp, cdh;
  92.     CDT *cdtp, cdt;
  93. #ifdef __TURBOC__
  94.     union REGS tregs;
  95. #endif
  96.  
  97.     early_date = 0;
  98.     early_time = 0;
  99.     /* open the file                                 */
  100.     if ((zip_handle=open(fname, O_RDONLY+O_BINARY)) < 1)
  101.     {
  102.     perror(fname);
  103.     return(97);
  104.     }
  105.  
  106.     /* go to EOF                                 */
  107.     if ((zip_fsize=lseek(zip_handle, 0l, 2)) < 0L)
  108.     {
  109.     perror("cannot get to ZIPfile EOF");
  110.     close(zip_handle);
  111.     return(98);
  112.     }
  113.     if (zip_fsize < (long) BUFLEN)
  114.     buf0_off = 0;
  115.     else
  116.     buf0_off = zip_fsize - buflen;
  117.  
  118.     /* look for an "end of central directory record" (cdt)                   */
  119.     if ((cdt_f_off=find_cdt(zip_handle)) < 0)
  120.     {
  121.     if (cdt_f_off == -1L)
  122.     {
  123.         fprintf(stderr, "%s: not a ZIPfile\n", fname);
  124.         close(zip_handle);
  125.         return(97);
  126.     }
  127.     else
  128.     {
  129.         fprintf(stderr, "find_cdt code %d finding ZIPfile central directory\n",
  130.             (int) -cdt_f_off);
  131.         close(zip_handle);
  132.         return(99);
  133.     }
  134.     }
  135.  
  136.     /* reread the cdt to make sure we get it all                 */
  137.     i = (lseek(zip_handle, cdt_f_off, 0) >= 0L);
  138.     if (i)
  139.     i = (read(zip_handle, (char *)&cdt, sizeof(cdt)-2) > 0);
  140.     if (!i)
  141.     {
  142.     perror("error rereading ZIPfile cdt");
  143.     close(zip_handle);
  144.     return(96);
  145.     }
  146.  
  147. #ifdef DEBUG
  148.     printf("%lx sig %08lx dno %u dno_cdh %u cnt_here %u cnt_all %u\n",
  149.         cdt_f_off, cdt.sig, cdt.dno, cdt.dno_cdh,
  150.         cdt.cnt_here, cdt.cnt_all);
  151.     printf("\tcd_size %lu cd_off %lu cmnt_len %u\n",
  152.         cdt.cd_size, cdt.cd_off, cdt.cmnt_len);
  153. #endif
  154.  
  155.     if (cdt.dno != 0 || cdt.dno_cdh != 0)
  156.     {
  157.     fprintf(stderr, "multivolume ZIPOT not yet implemented\n");
  158.     close(zip_handle);
  159.     return(95);
  160.     }
  161.  
  162.     /* point to the first file header in the central directory structure     */
  163.     ret = 0;
  164.     next_cdh = cdt.cd_off;
  165.     cdh.sig = 0L;
  166.  
  167.     /* process each file header in the central directory structure         */
  168.     for (i=cdt.cnt_all; i>0; i--)
  169.     {
  170.     /* position to and read a file header                     */
  171.     if (lseek(zip_handle, next_cdh, 0) < 0L)
  172.     {
  173.         perror("cannot position to ZIPfile header");
  174.         ret = 94;
  175.         break;
  176.     }
  177.     if (read(zip_handle, (char *)&cdh, sizeof(cdh)-2) <= 0)
  178.     {
  179.         perror("cannot read ZIPfile header");
  180.         ret = 93;
  181.         break;
  182.     }
  183. #ifdef DEBUG
  184.     printf("sig %lx comp_ver %u extr_ver %u bit_flag %04x method %u\n",
  185.         cdh.sig, cdh.comp_ver, cdh.extr_ver, cdh.bit_flag, cdh.method);
  186.     printf("\tftime %04x fdate %04x crc %08lx comp_size %lu ur_size %lu\n",
  187.         cdh.ftime, cdh.fdate, cdh.crc, cdh.comp_size, cdh.ur_size);
  188.     printf("\tfname_len %u extra_len %u cmnt_len %u dno %u\n",
  189.         cdh.fname_len, cdh.extra_len, cdh.cmnt_len, cdh.dno);
  190.     printf("\tint_attr %04x ext_attr %08lx lfh_off %08lx\n",
  191.         cdh.int_attr, cdh.ext_attr, cdh.lfh_off);
  192. #endif
  193.     /* is there really a header there ?                     */
  194.     if (cdh.sig != CDH_SIG)
  195.     {
  196.         fputs("ZIPfile header expected but not found\n", stderr);
  197.         ret = 92;
  198.         break;
  199.     }
  200.  
  201.     /* stash latest file timestamp of the ZIP                 */
  202.     if (!(later = (cdh.fdate>early_date)))
  203.         later = (cdh.fdate==early_date && cdh.ftime>early_time);
  204.     if (later)
  205.     {
  206.         early_date = cdh.fdate;
  207.         early_time = cdh.ftime;
  208.     }
  209.  
  210.     /* compute offset of next header                     */
  211.     next_cdh += sizeof(cdh) - 2 + cdh.fname_len + cdh.extra_len +
  212.             cdh.cmnt_len;
  213.     cdh.sig = 0L;
  214.     }
  215. #ifdef DEBUG
  216.     printf("early_date %04x, early_time %04x\n", early_date, early_time);
  217. #endif
  218.  
  219. #ifdef    __TURBOC__
  220.     tregs.h.ah = 0x57;
  221.     tregs.h.al = 0x01;
  222.     tregs.x.bx = zip_handle;
  223.     tregs.x.cx = early_time;
  224.     tregs.x.dx = early_date;
  225.     intdos(&tregs, &tregs);
  226. #else
  227.     _dos_setftime(zip_handle, early_date, early_time);
  228. #endif
  229.     close(zip_handle);
  230.     return(ret);
  231. }
  232.  
  233.  
  234. void main(int argc, char **argv)
  235. {
  236.     int i, ret;
  237.  
  238.     for (i=1; i<argc; i++)
  239.     {
  240.     buflen = BUFLEN;
  241.     ret = otzip(argv[i]);
  242.     if (ret != 0 && ret != 97)
  243.         fprintf(stderr, "    argument %s return code %d\n", argv[i], ret);
  244.     }
  245.     exit(0);
  246. }
  247.