home *** CD-ROM | disk | FTP | other *** search
/ ftp.mactech.com 2010 / ftp.mactech.com.tar / ftp.mactech.com / online / source / c / compilers / Tickle-4.0.sit.hqx / Tickle-4.0 / src / tar_buffer.c < prev    next >
Text File  |  1993-11-07  |  8KB  |  374 lines

  1.  
  2. #pragma segment TAR
  3.  
  4. /*
  5.  * Macintosh Tar
  6.  *
  7.  * Modified by Craig Ruff for use on the Macintosh.
  8.  */
  9. /*
  10.  * Buffer management for public domain tar.
  11.  *
  12.  * Written by John Gilmore, ihnp4!hoptoad!gnu, on 25 August 1985.
  13.  *
  14.  * @(#) buffer.c 1.14 10/28/86 Public Domain - gnu
  15.  *
  16.  */
  17.  
  18. #include "tar.h"
  19.  
  20. Boolean        FlushArchive();
  21.  
  22. union record    *arBlock;    /* Start of block of archive */
  23. union record    *arRecord;    /* Current record of archive */
  24. union record    *arLast;    /* Last+1 record of archive block */
  25. char        arReading;    /* 0 writing, !0 reading archive */
  26.  
  27. /*
  28.  * The record pointed to by save_rec should not be overlaid
  29.  * when reading in a new tape block.  Copy it to record_save_area first, and
  30.  * change the pointer in *save_rec to point to record_save_area.
  31.  * Saved_recno records the record number at the time of the save.
  32.  * This is used by annofile() to print the record number of a file's
  33.  * header record.
  34.  */
  35. static union record **saveRec;
  36. static union record recordSaveArea;
  37. static int        savedRecno;
  38.  
  39. /*
  40.  * Record number of the start of this block of records
  41.  */
  42. static int    baseRec;
  43.  
  44. /*
  45.  * Return the location of the next available input or output record.
  46.  */
  47. union record *
  48. FindRec()
  49. {
  50.     if (arRecord == arLast) {
  51.         if (FlushArchive())
  52.             return((union record *) nil);
  53.             
  54.         if (arRecord == arLast)
  55.             return((union record *) nil);    /* EOF */
  56.     }
  57.  
  58.     return(arRecord);
  59. }
  60.  
  61. /*
  62.  * Indicate that we have used all records up thru the argument.
  63.  * (should the arg have an off-by-1? XXX FIXME)
  64.  */
  65. void
  66. UseRec(rec)
  67. union record *rec;
  68. {
  69.     while (rec >= arRecord)
  70.         arRecord++;
  71.     /*
  72.      * Do NOT flush the archive here.  If we do, the same
  73.      * argument to userec() could mean the next record (if the
  74.      * input block is exactly one record long), which is not what
  75.      * is intended.
  76.      */
  77.     if (arRecord > arLast) {
  78.         PgmAlert("\pUseRec", "\parRecord > arLast", nil);
  79.         return;
  80.     }
  81. }
  82.  
  83. /*
  84.  * Return a pointer to the end of the current records buffer.
  85.  * All the space between findrec() and endofrecs() is available
  86.  * for filling with data, or taking data from.
  87.  */
  88. union record *
  89. EndOfRecs()
  90. {
  91.     return(arLast);
  92. }
  93.  
  94. /*
  95.  * Open an archive file.  The argument specifies whether we are
  96.  * reading or writing.
  97.  */
  98. Boolean
  99. OpenArchive(read)
  100.     int    read;
  101.     {
  102.     OSErr            err;
  103.     char            *routine = "\pOpenArchive";
  104.     HParamBlockRec    hpb;
  105.     
  106.     /*
  107.      * Get a block buffer for use later
  108.      */
  109.     arBlock = (union record *) NewPtr((Size) blockSize);
  110.     if (arBlock == nil)
  111.         {
  112.         OSAlert(routine, "\pNewPtr", "\parBlock", MemError());
  113.         return(true);
  114.         }
  115.  
  116.     arRecord = arBlock;
  117.     arLast   = arBlock + blocking;
  118.  
  119.     /*
  120.      * Try and open the archive file.
  121.      */
  122.     hpb.ioParam.ioCompletion = 0;
  123.     hpb.ioParam.ioNamePtr = arName;
  124.     hpb.ioParam.ioVRefNum = arVRefNum;
  125.     hpb.fileParam.ioDirID = arDirID;    /* HIOParam is broke on this field! */
  126.     hpb.ioParam.ioMisc = 0;
  127.     
  128.     if (read)
  129.         {
  130.         hpb.ioParam.ioPermssn = fsRdPerm;
  131.         err = PBHOpen( &hpb, (Boolean)0 );
  132.         }
  133.     else
  134.         {
  135.         err = PBHCreate( &hpb, (Boolean)0 );
  136.         if ( (err == noErr) || (err == dupFNErr) )
  137.             {
  138.             hpb.fileParam.ioCompletion = 0;
  139.             hpb.fileParam.ioNamePtr = arName;
  140.             hpb.fileParam.ioVRefNum = arVRefNum;
  141.             hpb.fileParam.ioDirID = arDirID;
  142.             hpb.fileParam.ioFDirIndex = 0;
  143.             err = PBHGetFInfo( &hpb, (Boolean)0 );
  144.             if (err == noErr)
  145.                 {
  146.                 hpb.fileParam.ioCompletion = 0;
  147.                 hpb.fileParam.ioNamePtr = arName;
  148.                 hpb.fileParam.ioVRefNum = arVRefNum;
  149.                 hpb.fileParam.ioDirID = arDirID;
  150.                 hpb.fileParam.ioFDirIndex = 0;
  151.                 hpb.fileParam.ioFlFndrInfo.fdType = (OSType)'TARF';
  152.                 hpb.fileParam.ioFlFndrInfo.fdCreator = (OSType)APPL_TYPE;
  153.                 err = PBHSetFInfo( &hpb, (Boolean)0 );
  154.                 }
  155.             
  156.             hpb.ioParam.ioCompletion = 0;
  157.             hpb.ioParam.ioNamePtr = arName;
  158.             hpb.ioParam.ioVRefNum = arVRefNum;
  159.             hpb.ioParam.ioPermssn = fsRdWrPerm;
  160.             hpb.fileParam.ioDirID = arDirID;
  161.             hpb.ioParam.ioMisc = 0;
  162.             
  163.             err = PBHOpen( &hpb, (Boolean)0 );
  164.             }
  165.         }
  166.  
  167.     if (err != noErr)
  168.         {
  169.         OSAlert(routine, "\pFSOpen or FSCreate", arName, err);
  170.         DisposPtr((Ptr) arBlock);
  171.         archive = 0;
  172.         return(true);
  173.         }
  174.     else
  175.         {
  176.         archive = hpb.ioParam.ioRefNum;
  177.         }
  178.  
  179.     if (!read && ((err = SetEOF(archive, 0L)) != noErr)) {
  180.         OSAlert(routine, "\pSetEOF", arName, err);
  181.         DisposPtr((Ptr) arBlock);
  182.         archive = 0;
  183.         return(true);
  184.     }
  185.     
  186.     arReading = read;
  187.     if (read) {
  188.         arLast = arBlock;        /* Set up for 1st block = # 0 */
  189.         FlushArchive();
  190.     }
  191.  
  192.     return(false);
  193. }
  194.  
  195. /*
  196.  * Remember a union record * as pointing to something that we
  197.  * need to keep when reading onward in the file.  Only one such
  198.  * thing can be remembered at once, and it only works when reading
  199.  * an archive.
  200.  */
  201. SaveRec(pointer)
  202. union record    **pointer;
  203. {
  204.     saveRec = pointer;
  205.     savedRecno = baseRec + arRecord - arBlock;
  206. }
  207.  
  208. /*
  209.  * Perform a write to flush the buffer.
  210.  */
  211. Boolean
  212. FlWrite()
  213. {
  214.     OSErr    err;
  215.     long    count;
  216.  
  217.     count = blockSize;
  218.     err = FSWrite(archive, &count, arBlock->charptr);
  219.     if ((err == noErr) && (count == blockSize))
  220.         return(false);
  221.  
  222.     if ((count != blockSize) || (err == dskFulErr))
  223.         DFAlert();
  224.     else
  225.         OSAlert("\pFLWrite", "\pFSWrite", "\pArchive write", err);
  226.         
  227.     return(true);
  228. }
  229.  
  230. /*
  231.  * Perform a read to flush the buffer.
  232.  */
  233. Boolean
  234. FlRead()
  235. {
  236.     OSErr    err;        /* Result from system call */
  237.     long    count;
  238.     int    left;        /* Bytes left */
  239.     char    *more;        /* Pointer to next byte to read */
  240.     char    *routine = "\pFlRead";
  241.  
  242.     /*
  243.      * If we are about to wipe out a record that
  244.      * somebody needs to keep, copy it out to a holding
  245.      * area and adjust somebody's pointer to it.
  246.      */
  247.     if (saveRec &&
  248.         *saveRec >= arRecord &&
  249.         *saveRec < arLast) {
  250.         recordSaveArea = **saveRec;
  251.         *saveRec = &recordSaveArea;
  252.     }
  253.  
  254.     count = blockSize;
  255.     err = FSRead(archive, &count, arBlock->charptr);
  256.     if ((err == noErr) && (count == blockSize))
  257.         return(false);
  258.  
  259.     else if ((err != noErr) && (err != eofErr)) {
  260.         OSAlert("\pReadError", "\pFSRead", "\pArchive read", err);
  261.         return(true);
  262.     }
  263.  
  264.     more = arBlock->charptr + count;
  265.     left = blockSize - count;
  266.  
  267. again:
  268.     if (0 == (((unsigned)left) % RECORDSIZE)) {
  269.         /* FIXME, for size=0, multi vol support */
  270.         /* On the first block, warn about the problem */
  271.         if (!reblock && baseRec == 0) {
  272.             char    buf[80];
  273.  
  274.             sprintf(&buf[1], "Blocksize = %ld records",
  275.                     count / (long) RECORDSIZE);
  276.             buf[0] = strlen(&buf[1]);
  277.             PgmAlert(routine, buf, nil);
  278.         }
  279.  
  280.         arLast = arBlock + ((unsigned)(blockSize - left))/RECORDSIZE;
  281.         return(false);
  282.     }
  283.  
  284.     if (reblock) {
  285.         /*
  286.          * User warned us about this.  Fix up.
  287.          */
  288.         if (left > 0) {
  289.             count = left;
  290.             err = FSRead(archive, &count, more);
  291.             if ((err != noErr) && (err != eofErr)) {
  292.                 OSAlert("\pReadError", "\pFSRead",
  293.                         "\pArchive read 2", err);
  294.                 return(true);
  295.             }
  296.             
  297.             if ((count == 0) || (err = eofErr)) {
  298.                 PgmAlert(routine, "\pEof not on block boundary",
  299.                         nil);
  300.                 return(true);
  301.             }
  302.             
  303.             left -= count;
  304.             more += count;
  305.             goto again;
  306.         }
  307.     } else {
  308.         PgmAlert(routine, "\pDid not read blocksize bytes", nil);
  309.         return(true);
  310.     }
  311. }
  312.  
  313. /*
  314.  * Flush the current buffer to/from the archive.
  315.  */
  316. Boolean
  317. FlushArchive()
  318. {
  319.     baseRec += arLast - arBlock;/* Keep track of block #s */
  320.     arRecord = arBlock;        /* Restore pointer to start */
  321.     arLast = arBlock + blocking;    /* Restore pointer to end */
  322.  
  323.     if (!arReading) 
  324.         return(FlWrite());
  325.     else
  326.         return(FlRead());
  327. }
  328.  
  329. /*
  330.  * Close the archive file.
  331.  */
  332. CloseArchive()
  333. {
  334.     if (!arReading)
  335.         (void) FlushArchive();
  336.  
  337.     DisposPtr((Ptr) arBlock);
  338.     if (archive != 0)
  339.         (void) FSClose(archive);
  340.  
  341.     archive = 0;
  342. }
  343.  
  344. #ifdef NEVER_DEFINED
  345. /*
  346.  * bcopy and bzero compatability routines.
  347.  * These could (should) potentially be done with the Mac traps.
  348.  */
  349. char *
  350. bcopy(s1, s2, n)
  351. char *s1, *s2;
  352. register int n;
  353. {
  354.     register char *s = s1;
  355.     register char *d = s2;
  356.  
  357.     while (--n >= 0)
  358.         *d++ = *s++;
  359.  
  360.     return(s1);
  361. }
  362. #endif
  363.  
  364. #ifndef THINK_C
  365. void
  366. bzero (s1, n)
  367. register char *s1;
  368. register int n;
  369. {
  370.     while (--n >= 0)
  371.         *s1++ = 0;
  372. }
  373. #endif
  374.