home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 28 / amigaformatcd28.iso / -seriously_amiga- / archivers / arcppc / src / arcio.c < prev    next >
C/C++ Source or Header  |  1998-04-23  |  7KB  |  290 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. #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, hdr->size=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, hdr->length=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.         if (ferror(t))
  182.             abort("Write failed");
  183. #else
  184.         if (fputc(c, t) == EOF)
  185.             abort("Write fail (disk full?)");
  186. #endif
  187.     }
  188. }
  189.  
  190. /*
  191.  * NOTE:  The filecopy() function is used to move large numbers of bytes from
  192.  * one file to another.  This particular version has been modified to improve
  193.  * performance in Computer Innovations C86 version 2.3 in the small memory
  194.  * model.  It may not work as expected with other compilers or libraries, or
  195.  * indeed with different versions of the CI-C86 compiler and library, or with
  196.  * the same version in a different memory model.
  197.  * 
  198.  * The following is a functional equivalent to the filecopy() routine that
  199.  * should work properly on any system using any compiler, albeit at the cost
  200.  * of reduced performance:
  201.  * 
  202.  * filecopy(f,t,size) 
  203.  *      FILE *f, *t; long size; 
  204.  * { 
  205.  *      while(size--)
  206.  *              putc_tst(fgetc(f),t); 
  207.  * }
  208.  */
  209. #if    MSDOS
  210. #include <fileio2.h>
  211.  
  212. filecopy(f, t, size)        /* bulk file copier */
  213.     FILE           *f, *t;    /* files from and to */
  214.     long            size;    /* bytes to copy */
  215. {
  216.     char           *buf;    /* buffer pointer */
  217.     char           *alloc();/* buffer allocator */
  218.     unsigned int    bufl;    /* buffer length */
  219.     unsigned int    coreleft();    /* space available reporter */
  220.     unsigned int    cpy;    /* bytes being copied */
  221.     long            floc, tloc, fseek();    /* file pointers, setter */
  222.     struct regval   reg;    /* registers for DOS calls */
  223.  
  224.     if ((bufl = coreleft()) < 1000)    /* see how much space we have */
  225.         abort("Out of memory");
  226.     bufl -= 1000;        /* fudge factor for overhead */
  227.     if (bufl > 60000)
  228.         bufl = 60000;    /* avoid choking alloc() */
  229.     if (bufl > size)
  230.         bufl = size;    /* avoid wasting space */
  231.     buf = alloc(bufl);    /* allocate our buffer */
  232.  
  233.     floc = fseek(f, 0L, 1);    /* reset I/O system */
  234.     tloc = fseek(t, 0L, 1);
  235.  
  236.     segread(®.si);    /* set segment registers for DOS */
  237.  
  238.     while (size > 0) {    /* while more to copy */
  239.         reg.ax = 0x3F00;/* read from handle */
  240.         reg.bx = filehand(f);
  241.         reg.cx = bufl < size ? bufl : size;    /* amount to read */
  242.         reg.dx = buf;
  243.         if (sysint21(®, ®) & 1)
  244.             abort("Read fail");
  245.  
  246.         cpy = reg.ax;    /* amount actually read */
  247.         reg.ax = 0x4000;/* write to handle */
  248.         reg.bx = filehand(t);
  249.         reg.cx = cpy;
  250.         reg.dx = buf;
  251.         sysint21(®, ®);
  252.  
  253.         if (reg.ax != cpy)
  254.             abort("Write fail (disk full?)");
  255.  
  256.         size -= (long) cpy;
  257.     }
  258.  
  259.     free(buf);        /* all done with buffer */
  260. }
  261. #else
  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 = 32760;
  274.     if (bufl > size)
  275.         bufl = size;    /* don't waste space */
  276.  
  277.     buf = malloc(bufl);
  278.  
  279.     while (size > 0) {
  280.         cpy = fread(buf, sizeof(char),
  281.             bufl < size ? bufl : (unsigned short) size, f);
  282.         if (fwrite(buf, sizeof(char), cpy, t) != cpy)
  283.             abort("Write fail (no space?)");
  284.         size -= cpy;
  285.     }
  286.  
  287.     free(buf);
  288. }
  289. #endif
  290.