home *** CD-ROM | disk | FTP | other *** search
- /*
- * Macintosh Tar
- *
- * Modified by Craig Ruff for use on the Macintosh.
- */
- /*
- * Buffer management for public domain tar.
- *
- * Written by John Gilmore, ihnp4!hoptoad!gnu, on 25 August 1985.
- *
- * @(#) buffer.c 1.14 10/28/86 Public Domain - gnu
- *
- */
-
- #include "tar.h"
- #include <Devices.h>
-
- Boolean FlushArchive();
-
- union record *arBlock; /* Start of block of archive */
- union record *arRecord; /* Current record of archive */
- union record *arLast; /* Last+1 record of archive block */
- char arReading; /* 0 writing, !0 reading archive */
-
- short archive;
- HParamBlockRec apb; /* Archive file PB */
-
- /*
- * The record pointed to by save_rec should not be overlaid
- * when reading in a new tape block. Copy it to record_save_area first, and
- * change the pointer in *save_rec to point to record_save_area.
- * Saved_recno records the record number at the time of the save.
- * This is used by annofile() to print the record number of a file's
- * header record.
- */
- static union record **saveRec;
- static union record recordSaveArea;
- static int savedRecno;
-
- /*
- * Record number of the start of this block of records
- */
- static int baseRec;
-
- /*
- * Return the location of the next available input or output record.
- */
- union record *
- FindRec()
- {
- if (arRecord == arLast) {
- if (FlushArchive())
- return((union record *) nil);
-
- if (arRecord == arLast)
- return((union record *) nil); /* EOF */
- }
-
- return(arRecord);
- }
-
- /*
- * Indicate that we have used all records up thru the argument.
- * (should the arg have an off-by-1? XXX FIXME)
- */
- void
- UseRec(rec)
- union record *rec;
- {
- while (rec >= arRecord)
- arRecord++;
- /*
- * Do NOT flush the archive here. If we do, the same
- * argument to userec() could mean the next record (if the
- * input block is exactly one record long), which is not what
- * is intended.
- */
- if (arRecord > arLast) {
- PgmAlert("\pUseRec", "\parRecord > arLast", nil);
- return;
- }
- }
-
- /*
- * Return a pointer to the end of the current records buffer.
- * All the space between findrec() and endofrecs() is available
- * for filling with data, or taking data from.
- */
- union record *
- EndOfRecs()
- {
- return(arLast);
- }
-
- /*
- * Open an archive file. The argument specifies whether we are
- * reading or writing.
- */
- Boolean
- OpenArchive(prompt, read)
- char *prompt;
- Boolean read;
- {
- OSErr err;
- char *routine = "\pOpenArchive";
- Point where;
- SFReply reply;
- Str255 name;
-
- archive = 0;
- memset(&apb, 0, sizeof(apb));
- if (pref.floppy) {
- /*
- * Open the floppy driver.
- */
- apb.fileParam.ioCompletion = nil;
- apb.fileParam.ioNamePtr = "\p.Sony";
- apb.fileParam.ioVRefNum = 0;
- apb.fileParam.ioFVersNum = 0;
- apb.fileParam.ioDirID = 0;
- apb.fileParam.ioFDirIndex = 0;
- apb.ioParam.ioPermssn = (read) ? fsRdPerm : fsWrPerm;
- apb.ioParam.ioMisc = nil;
- if ((err = PBHOpen(&apb, false)) != noErr) {
- OSAlert(routine, "\pPBHOpen or PBHCreate", reply.fName, err);
- return(true);
- }
-
- if ((apb.fileParam.ioVRefNum = DoInsertFloppy()) == 0)
- return(true);
-
- } else {
- /*
- * Put up a standard file dialog asking for the archive file name.
- */
- where.h = where.v = 75;
- name[0] = 0;
- if (read) {
- SFGetFile(where, prompt, nil, -1, nil, nil, &reply);
-
- } else {
- SFPutFile(where, prompt, name, nil, &reply);
- }
-
- if (!reply.good)
- return(true);
-
- /*
- * Try and open the archive file.
- */
- apb.fileParam.ioCompletion = nil;
- apb.fileParam.ioNamePtr = reply.fName;
- apb.fileParam.ioVRefNum = reply.vRefNum;
- apb.fileParam.ioFVersNum = 0;
- apb.fileParam.ioDirID = 0;
- apb.fileParam.ioFDirIndex = 0;
- if (read) {
- apb.ioParam.ioPermssn = fsRdPerm;
- apb.ioParam.ioMisc = nil;
- err = PBHOpen(&apb, false);
-
- } else {
- err = PBHCreate(&apb, false);
- if ((err == noErr) || (err == dupFNErr)){
- if (PBHGetFInfo(&apb, false)) {
- OSAlert(routine, "\pPBHGetFInfo", reply.fName,
- apb.fileParam.ioResult);
- return(true);
- }
-
- memcpy(&apb.fileParam.ioFlFndrInfo.fdCreator, "TAR ", 4);
- memcpy(&apb.fileParam.ioFlFndrInfo.fdType, "TARF", 4);
- apb.fileParam.ioNamePtr = reply.fName;
- apb.fileParam.ioDirID = 0;
- if (PBHSetFInfo(&apb, false)) {
- OSAlert(routine, "\pPBHSetFInfo", reply.fName,
- apb.fileParam.ioResult);
- return(true);
- }
-
- apb.ioParam.ioPermssn = fsWrPerm;
- apb.ioParam.ioMisc = nil;
- err = PBHOpen(&apb, false);
- }
- }
-
- if (err != noErr) {
- OSAlert(routine, "\pPBHOpen or PBHCreate", reply.fName, err);
- return(true);
- }
-
- if (!read) {
- apb.ioParam.ioMisc = 0;
- if ((err = PBSetEOF((ParmBlkPtr) &apb, false)) != noErr) {
- OSAlert(routine, "\pPBSetEOF", reply.fName, err);
- return(true);
- }
- }
- }
-
- apb.ioParam.ioPosMode = fsFromStart;
- apb.ioParam.ioPosOffset = 0;
- /*
- * Get a block buffer for use later
- */
- arBlock = (union record *) NewPtr((Size) pref.blockSize);
- if (arBlock == nil) {
- OSAlert(routine, "\pNewPtr", "\parBlock", MemError());
- if (!pref.floppy)
- PBClose((ParmBlkPtr) &apb, false);
-
- return(true);
- }
-
- arRecord = arBlock;
- arLast = arBlock + pref.blocking;
- archive = apb.ioParam.ioRefNum;
- arReading = read;
- if (read) {
- arLast = arBlock; /* Set up for 1st block = # 0 */
- FlushArchive();
- }
-
- return(false);
- }
-
- /*
- * Remember a union record * as pointing to something that we
- * need to keep when reading onward in the file. Only one such
- * thing can be remembered at once, and it only works when reading
- * an archive.
- */
- SaveRec(pointer)
- union record **pointer;
- {
- saveRec = pointer;
- savedRecno = baseRec + arRecord - arBlock;
- }
-
- /*
- * Perform a write to flush the buffer.
- */
- Boolean
- FlWrite()
- {
- OSErr err;
-
- apb.ioParam.ioBuffer = arBlock->charptr;
- apb.ioParam.ioReqCount = pref.blockSize;
- err = PBWrite((ParmBlkPtr) &apb, false);
- apb.ioParam.ioPosMode = fsAtMark;
- if ((err == noErr) && (apb.ioParam.ioActCount == pref.blockSize))
- return(false);
-
- if (
- (apb.ioParam.ioActCount != pref.blockSize) ||
- (err == dskFulErr)
- )
- DFAlert();
- else
- OSAlert("\pFLWrite", "\pPBWrite", "\pArchive write", err);
-
- return(true);
- }
-
- /*
- * Perform a read to flush the buffer.
- */
- Boolean
- FlRead()
- {
- OSErr err; /* Result from system call */
- int left; /* Bytes left */
- char *more; /* Pointer to next byte to read */
- char *routine = "\pFlRead";
-
- /*
- * If we are about to wipe out a record that
- * somebody needs to keep, copy it out to a holding
- * area and adjust somebody's pointer to it.
- */
- if (saveRec &&
- *saveRec >= arRecord &&
- *saveRec < arLast) {
- recordSaveArea = **saveRec;
- *saveRec = &recordSaveArea;
- }
-
- apb.ioParam.ioBuffer = arBlock->charptr;
- apb.ioParam.ioReqCount = pref.blockSize;
- err = PBRead((ParmBlkPtr) &apb, false);
- apb.ioParam.ioPosMode = fsAtMark;
- if ((err == noErr) && (apb.ioParam.ioActCount == pref.blockSize))
- return(false);
-
- else if ((err != noErr) && (err != eofErr)) {
- OSAlert("\pReadError", "\pPBRead", "\pArchive read", err);
- return(true);
- }
-
- more = arBlock->charptr + apb.ioParam.ioActCount;
- left = pref.blockSize - apb.ioParam.ioActCount;
-
- again:
- if (0 == (((unsigned)left) % RECORDSIZE)) {
- /* FIXME, for size=0, multi vol support */
- /* On the first block, warn about the problem */
- if (!reblock && baseRec == 0) {
- char buf[80];
-
- sprintf(&buf[1], "Blocksize = %ld records",
- apb.ioParam.ioActCount / (long) RECORDSIZE);
- buf[0] = strlen(&buf[1]);
- PgmAlert(routine, buf, nil);
- }
-
- arLast = arBlock + ((unsigned)(pref.blockSize - left))/RECORDSIZE;
- return(false);
- }
-
- if (reblock) {
- /*
- * User warned us about this. Fix up.
- */
- if (left > 0) {
- apb.ioParam.ioBuffer = more;
- apb.ioParam.ioReqCount = left;
- err = PBRead((ParmBlkPtr) &apb, false);
- if ((err != noErr) && (err != eofErr)) {
- OSAlert("\pReadError", "\pPBRead",
- "\pArchive read 2", err);
- return(true);
- }
-
- if ((apb.ioParam.ioActCount == 0) || (err == eofErr)) {
- PgmAlert(routine, "\pEof not on block boundary",
- nil);
- return(true);
- }
-
- left -= apb.ioParam.ioActCount;
- more += apb.ioParam.ioActCount;
- goto again;
- }
- } else {
- PgmAlert(routine, "\pDid not read blocksize bytes", nil);
- return(true);
- }
- }
-
- /*
- * Flush the current buffer to/from the archive.
- */
- Boolean
- FlushArchive()
- {
- baseRec += arLast - arBlock; /* Keep track of block #s */
- arRecord = arBlock; /* Restore pointer to start */
- arLast = arBlock + pref.blocking; /* Restore pointer to end */
-
- if (!arReading)
- return(FlWrite());
- else
- return(FlRead());
- }
-
- /*
- * Close the archive file.
- */
- CloseArchive()
- {
- ParamBlockRec ctlpb;
-
- if (!arReading)
- (void) FlushArchive();
-
- DisposPtr((Ptr) arBlock);
- if (pref.floppy) {
- /* Eject it! */
- memset(&ctlpb, 0, sizeof(ctlpb));
- ctlpb.cntrlParam.ioCompletion = nil;
- ctlpb.cntrlParam.ioVRefNum = apb.ioParam.ioVRefNum;
- ctlpb.cntrlParam.ioCRefNum = apb.ioParam.ioRefNum;
- ctlpb.cntrlParam.csCode = 7;
- (void) PBControl((ParmBlkPtr) &ctlpb, false);
-
- } else if (archive != 0)
- (void) PBClose((ParmBlkPtr) &apb, false);
-
- archive = 0;
- }
-