home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / developm / source / tarsrc30.sit / buffer.c next >
Encoding:
C/C++ Source or Header  |  1991-08-07  |  8.8 KB  |  392 lines

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