home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c019 / 1.ddi / ARC521_C / ARCIO.C < prev    next >
Encoding:
C/C++ Source or Header  |  1988-08-01  |  7.2 KB  |  287 lines

  1. /*
  2.  * $Header: arcio.c,v 1.7 88/06/02 16:27:32 hyc Locked $
  3.  */
  4.  
  5. /*  ARC - Archive utility - ARCIO
  6.  
  7.     Version 2.50, created on 04/22/87 at 13:25:20
  8.  
  9. (C) COPYRIGHT 1985,86 by System Enhancement Associates; ALL RIGHTS RESERVED
  10.  
  11.     By:     Thom Henderson
  12.  
  13.     Description:
  14.      This file contains the file I/O routines used to manipulate
  15.      an archive.
  16.  
  17.     Language:
  18.      Computer Innovations Optimizing C86
  19. */
  20. #include <stdio.h>
  21. #include "arc.h"
  22. #if    MTS
  23. #include <ctype.h>
  24. #endif
  25.  
  26. void    abort();
  27. int    strlen(), free();
  28.  
  29. int
  30. readhdr(hdr, f)            /* read a header from an archive */
  31.     struct heads   *hdr;    /* storage for header */
  32.     FILE           *f;    /* archive to read header from */
  33. {
  34. #if    !MSDOS
  35.     unsigned char   dummy[28];
  36.     int             i;
  37. #endif
  38.     char            name[FNLEN];    /* filename buffer */
  39.     int             try = 0;/* retry counter */
  40.     static int      first = 1;    /* true only on first read */
  41.  
  42.     if (!f)            /* if archive didn't open */
  43.         return 0;    /* then pretend it's the end */
  44.     if (feof(f))        /* if no more data */
  45.         return 0;    /* then signal end of archive */
  46.  
  47.     if (fgetc(f) != ARCMARK) {    /* check archive validity */
  48.         if (warn) {
  49.             printf("An entry in %s has a bad header.", arcname);
  50.             nerrs++;
  51.         }
  52.         while (!feof(f)) {
  53.             try++;
  54.             if (fgetc(f) == ARCMARK) {
  55.                 ungetc(hdrver = fgetc(f), f);
  56.                 if (!(hdrver & 0x80) && hdrver <= ARCVER)
  57.                     break;
  58.             }
  59.         }
  60.  
  61.         if (feof(f) && first)
  62.             abort("%s is not an archive", arcname);
  63.  
  64.         if (changing && warn)
  65.             abort("%s is corrupted -- changes disallowed", arcname);
  66.  
  67.         if (warn)
  68.             printf("  %d bytes skipped.\n", try);
  69.  
  70.         if (feof(f))
  71.             return 0;
  72.     }
  73.     hdrver = fgetc(f);    /* get header version */
  74.     if (hdrver & 0x80)    /* sign bit? negative? */
  75.         abort("Invalid header in archive %s", arcname);
  76.     if (hdrver == 0)
  77.         return 0;    /* note our end of archive marker */
  78.     if (hdrver > ARCVER) {
  79.         fread(name, sizeof(char), FNLEN, f);
  80. #if    MTS
  81.         atoe(name, strlen(name));
  82. #endif
  83.         printf("I don't know how to handle file %s in archive %s\n",
  84.                name, arcname);
  85.         printf("I think you need a newer version of ARC.\n");
  86.         exit(1);
  87.     }
  88.     /* amount to read depends on header type */
  89.  
  90.     if (hdrver == 1) {    /* old style is shorter */
  91.         fread(hdr, sizeof(struct heads) - sizeof(long int), 1, f);
  92.         hdrver = 2;    /* convert header to new format */
  93.         hdr->length = hdr->size;    /* size is same when not
  94.                          * packed */
  95.     } else
  96. #if    MSDOS
  97.         fread(hdr, sizeof(struct heads), 1, f);
  98. #else
  99.         fread(dummy, 27, 1, f);
  100.  
  101.     for (i = 0; i < FNLEN; hdr->name[i] = dummy[i], i++);
  102. #if    MTS
  103.     (void) atoe(hdr->name, strlen(hdr->name));
  104. #endif
  105.     for (i = 0; i<4; hdr->size<<=8, hdr->size += dummy[16-i], i++);
  106.     hdr->date = (short) ((dummy[18] << 8) + dummy[17]);
  107.     hdr->time = (short) ((dummy[20] << 8) + dummy[19]);
  108.     hdr->crc = (short) ((dummy[22] << 8) + dummy[21]);
  109.     for (i = 0; i<4; hdr->length<<=8, hdr->length += dummy[26-i], i++);
  110. #endif
  111.  
  112.     if (hdr->date > olddate
  113.         || (hdr->date == olddate && hdr->time > oldtime)) {
  114.         olddate = hdr->date;
  115.         oldtime = hdr->time;
  116.     }
  117.     first = 0;
  118.     return 1;        /* we read something */
  119. }
  120.  
  121. void
  122. put_int(number, f)        /* write a 2 byte integer */
  123.     short           number;
  124.     FILE           *f;
  125. {
  126.     fputc((char) (number & 255), f);
  127.     fputc((char) (number >> 8), f);
  128. }
  129.  
  130. void
  131. put_long(number, f)        /* write a 4 byte integer */
  132.     long            number;
  133.     FILE           *f;
  134. {
  135.     put_int((short) (number & 0xFFFF), f);
  136.     put_int((short) (number >> 16), f);
  137. }
  138.  
  139. void
  140. writehdr(hdr, f)        /* write a header to an archive */
  141.     struct heads   *hdr;    /* header to write */
  142.     FILE           *f;    /* archive to write to */
  143. {
  144.     fputc(ARCMARK, f);        /* write out the mark of ARC */
  145.     fputc(hdrver, f);    /* write out the header version */
  146.     if (!hdrver)        /* if that's the end */
  147.         return;        /* then write no more */
  148. #if    MSDOS
  149.     fwrite(hdr, sizeof(struct heads), 1, f);
  150. #else
  151.     /* byte/word ordering hassles... */
  152. #if    MTS
  153.     etoa(hdr->name, strlen(hdr->name));
  154. #endif
  155.     fwrite(hdr->name, 1, FNLEN, f);
  156.     put_long(hdr->size, f);
  157.     put_int(hdr->date, f);
  158.     put_int(hdr->time, f);
  159.     put_int(hdr->crc, f);
  160.     put_long(hdr->length, f);
  161. #endif
  162.  
  163.     /* note the newest file for updating the archive timestamp */
  164.  
  165.     if (hdr->date > arcdate
  166.         || (hdr->date == arcdate && hdr->time > arctime)) {
  167.         arcdate = hdr->date;
  168.         arctime = hdr->time;
  169.     }
  170. }
  171.  
  172. void
  173. putc_tst(c, t)            /* put a character, with tests */
  174.     char            c;    /* character to output */
  175.     FILE           *t;    /* file to write to */
  176. {
  177.     c &= 0xff;
  178.     if (t)
  179. #if    UNIX
  180.         fputc(c, t);
  181. #else
  182.         if (fputc(c, t) == EOF)
  183.             abort("Write fail (disk full?)");
  184. #endif
  185. }
  186.  
  187. /*
  188.  * NOTE:  The filecopy() function is used to move large numbers of bytes from
  189.  * one file to another.  This particular version has been modified to improve
  190.  * performance in Computer Innovations C86 version 2.3 in the small memory
  191.  * model.  It may not work as expected with other compilers or libraries, or
  192.  * indeed with different versions of the CI-C86 compiler and library, or with
  193.  * the same version in a different memory model.
  194.  * 
  195.  * The following is a functional equivalent to the filecopy() routine that
  196.  * should work properly on any system using any compiler, albeit at the cost
  197.  * of reduced performance:
  198.  * 
  199.  * filecopy(f,t,size) 
  200.  *      FILE *f, *t; long size; 
  201.  * { 
  202.  *      while(size--)
  203.  *              putc_tst(fgetc(f),t); 
  204.  * }
  205.  */
  206. #if    MSDOS
  207. #include <fileio2.h>
  208.  
  209. filecopy(f, t, size)        /* bulk file copier */
  210.     FILE           *f, *t;    /* files from and to */
  211.     long            size;    /* bytes to copy */
  212. {
  213.     char           *buf;    /* buffer pointer */
  214.     char           *alloc();/* buffer allocator */
  215.     unsigned int    bufl;    /* buffer length */
  216.     unsigned int    coreleft();    /* space available reporter */
  217.     unsigned int    cpy;    /* bytes being copied */
  218.     long            floc, tloc, fseek();    /* file pointers, setter */
  219.     struct regval   reg;    /* registers for DOS calls */
  220.  
  221.     if ((bufl = coreleft()) < 1000)    /* see how much space we have */
  222.         abort("Out of memory");
  223.     bufl -= 1000;        /* fudge factor for overhead */
  224.     if (bufl > 60000)
  225.         bufl = 60000;    /* avoid choking alloc() */
  226.     if (bufl > size)
  227.         bufl = size;    /* avoid wasting space */
  228.     buf = alloc(bufl);    /* allocate our buffer */
  229.  
  230.     floc = fseek(f, 0L, 1);    /* reset I/O system */
  231.     tloc = fseek(t, 0L, 1);
  232.  
  233.     segread(®.si);    /* set segment registers for DOS */
  234.  
  235.     while (size > 0) {    /* while more to copy */
  236.         reg.ax = 0x3F00;/* read from handle */
  237.         reg.bx = filehand(f);
  238.         reg.cx = bufl < size ? bufl : size;    /* amount to read */
  239.         reg.dx = buf;
  240.         if (sysint21(®, ®) & 1)
  241.             abort("Read fail");
  242.  
  243.         cpy = reg.ax;    /* amount actually read */
  244.         reg.ax = 0x4000;/* write to handle */
  245.         reg.bx = filehand(t);
  246.         reg.cx = cpy;
  247.         reg.dx = buf;
  248.         sysint21(®, ®);
  249.  
  250.         if (reg.ax != cpy)
  251.             abort("Write fail (disk full?)");
  252.  
  253.         size -= (long) cpy;
  254.     }
  255.  
  256.     free(buf);        /* all done with buffer */
  257. }
  258. #else
  259.  
  260. void
  261. filecopy(f, t, size)        /* bulk file copier */
  262.     FILE           *f, *t;    /* files from and to */
  263.     long            size;    /* bytes to copy */
  264. {
  265.     char           *buf;    /* buffer pointer */
  266.     char           *malloc();    /* buffer allocator */
  267.     unsigned int    bufl;    /* buffer length */
  268.     unsigned int    cpy;    /* bytes being copied */
  269.  
  270.     bufl = 32760;
  271.     if (bufl > size)
  272.         bufl = size;    /* don't waste space */
  273.  
  274.     buf = malloc(bufl);
  275.  
  276.     while (size > 0) {
  277.         cpy = fread(buf, sizeof(char),
  278.             bufl < size ? bufl : (unsigned short) size, f);
  279.         if (fwrite(buf, sizeof(char), cpy, t) != cpy)
  280.             abort("Write fail (no space?)");
  281.         size -= cpy;
  282.     }
  283.  
  284.     free(buf);
  285. }
  286. #endif
  287.