home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / ARC521-2.ZIP / ARCIO.C < prev    next >
C/C++ Source or Header  |  1989-12-30  |  8KB  |  292 lines

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