📄 pgpmacfile.c
字号:
return PGPERR_OK;
macError:
result = pgpErrorFromMacError(macResult, PGPERR_FILE_OPFAIL);
error:
macSetError(file, result);
return result;
}
/*
* This routine is called after closing a MacBinary file for writing. It
* sets the finder information including type and creator.
*/
static PGPError
SetFileInfo(
PgpFile * file)
{
MacFile * mf = (MacFile *)file->priv;
FSSpec spec;
HFileParam pb;
if (!(mf->flags & kPGPMacWrite) || !(mf->flags & kPGPMacBinMode))
return PGPERR_OK;
if (pgpFSSpecFromFileRef(mf->fileRef, &spec) != PGPERR_OK)
goto error;
pb.ioNamePtr = spec.name;
pb.ioVRefNum = spec.vRefNum;
pb.ioDirID = spec.parID;
pb.ioFlCrDat = mf->macBinHeader.creation;
pb.ioFlMdDat = mf->macBinHeader.modification;
pgpCopyMemory(&mf->macBinHeader.info1, &pb.ioFlFndrInfo,
sizeof(pb.ioFlFndrInfo));
pb.ioFlFndrInfo.fdFlags &= 0xFF00;
pb.ioFlFndrInfo.fdFlags |= mf->macBinHeader.info2;
pb.ioFlFndrInfo.fdFlags &= ~NOMODIFY;
pb.ioFlFndrInfo.fdLocation.h = 0;
pb.ioFlFndrInfo.fdLocation.v = 0;
pb.ioFlFndrInfo.fdFldr = 0;
if (PBHSetFInfoSync((HParmBlkPtr)&pb) != noErr)
goto error;
return PGPERR_OK;
error:
/* XXX Improve error reporting */
macSetError(file, PGPERR_FILE_OPFAIL);
return PGPERR_FILE_OPFAIL;
}
/*
* It should be noted that writing to MacBinary files won't work if seeking
* is used in certain ways. The MacBinary header only interpreted the first
* time data is written past the first 128 bytes, and then the fork lengths
* and offsets are fixed and immutable. This could be fixed at some point,
* but there's no need for it now.
*
* The filename used to create the file is always the <fileRef> passed in,
* not the name in the MacBinary header.
*/
PgpFile *
pgpFileRefMacWriteOpen(
PGPFileRef const * fileRef,
PGPFileType fileType,
PGPFileOpenFlags flags,
PGPError * errorCode)
{
PgpFile * file = NULL;
MacFile * mf = NULL;
FSSpec spec;
PGPError result = PGPERR_OK;
if ((file = (PgpFile *)pgpAlloc(sizeof(*file))) == NULL)
{
result = PGPERR_NOMEM;
goto error;
}
if ((mf = (MacFile *)pgpAlloc(sizeof(*mf))) == NULL)
{
result = PGPERR_NOMEM;
goto error;
}
pgpClearMemory(mf, sizeof(*mf));
pgpClearMemory(file, sizeof(*file));
mf->fileRef = pgpCopyFileRef(fileRef);
if ((result = pgpFSSpecFromFileRef(mf->fileRef, &spec)) != PGPERR_OK)
goto error;
mf->fileType = fileType;
/* Try to delete the file first, in case it already exists */
/* XXX Maybe we should check the error, and/or truncate the file instead */
HDelete(spec.vRefNum, spec.parID, spec.name);
pgpAssert(sizeof(mf->macBinHeader) >= 129);
pgpAssert((flags & kPGPFileOpenLocalEncodeHashOnly) == 0);
mf->flags = kPGPMacWrite;
if (flags & (kPGPFileOpenMaybeLocalEncode | kPGPFileOpenForceLocalEncode))
{
mf->flags |= kPGPCheckMacBin;
if (flags & kPGPFileOpenNoMacBinCRCOkay)
mf->flags |= kPGPNoMacBinCRCOkay;
mf->dataOffset = mf->resOffset = 128;
}
else
mf->dataOffset = mf->resOffset = 0;
mf->dataRef = mf->resRef = 0;
mf->totalSize = 0;
mf->filePos = 0;
file->priv = mf;
file->read = macFileRead;
file->write = macFileWrite;
file->flush = macFileFlush;
file->close = macFileClose;
file->tell = macFileTell;
file->seek = macFileSeek;
file->eof = macFileEof;
file->sizeAdvise = macFileSizeAdvise;
file->error = macFileError;
file->clearError = macFileClearError;
file->write2read = macFileWrite2Read;
file->cfb = macFileCfb;
if (!(mf->flags & kPGPCheckMacBin))
if ((result = PrepareToWrite(file)) != PGPERR_OK)
goto error;
return file;
error:
if (mf != NULL)
{
if (mf->fileRef != NULL)
pgpFreeFileRef(mf->fileRef);
pgpFree(mf);
}
if (file != NULL)
pgpFree(file);
if (errorCode != NULL)
{
pgpAssertAddrValid(errorCode, PGPError);
*errorCode = result;
}
return NULL;
}
PgpFile *
pgpFileRefMacReadOpen(
PGPFileRef const * fileRef,
PGPFileOpenFlags flags,
PGPError * errorCode)
{
PgpFile * file = NULL;
MacFile * mf = NULL;
FSSpec spec;
HFileParam pb;
HParamBlockRec io;
ushort crc;
PGPError result = PGPERR_OK;
if ((file = (PgpFile *)pgpAlloc(sizeof(*file))) == NULL)
{
result = PGPERR_NOMEM;
goto error;
}
if ((mf = (MacFile *)pgpAlloc(sizeof(*mf))) == NULL)
{
result = PGPERR_NOMEM;
goto error;
}
pgpClearMemory(mf, sizeof(*mf));
pgpClearMemory(file, sizeof(*file));
mf->fileRef = pgpCopyFileRef(fileRef);
if ((result = pgpFSSpecFromFileRef(mf->fileRef, &spec)) != PGPERR_OK)
goto error;
mf->fileType = kPGPFileTypeNone;
pb.ioNamePtr = spec.name;
pb.ioVRefNum = spec.vRefNum;
pb.ioDirID = spec.parID;
pb.ioFDirIndex = 0;
if (PBHGetFInfoSync((HParmBlkPtr)&pb) != noErr)
{
result = pgpErrorFromMacError(pb.ioResult, PGPERR_NO_FILE);
goto error;
}
pgpAssert(sizeof(mf->macBinHeader) >= 129);
pgpClearMemory(&mf->macBinHeader, sizeof(mf->macBinHeader));
CopyPString(spec.name, mf->macBinHeader.name);
mf->macBinHeader.info2 = pb.ioFlFndrInfo.fdFlags & 0x00FF;
pb.ioFlFndrInfo.fdFlags &= 0xFF00;
pb.ioFlFndrInfo.fdLocation.h = 0;
pb.ioFlFndrInfo.fdLocation.v = 0;
pb.ioFlFndrInfo.fdFldr = 0;
mf->macBinHeader.info1 = pb.ioFlFndrInfo;
mf->macBinHeader.dLength = pb.ioFlLgLen;
mf->macBinHeader.rLength = pb.ioFlRLgLen;
mf->macBinHeader.creation = pb.ioFlCrDat;
mf->macBinHeader.modification = pb.ioFlMdDat;
mf->macBinHeader.newVersion = 129;
mf->macBinHeader.minimumVersion = 129;
crc = CalcCRC16((uchar *)&mf->macBinHeader + 1, 124);
pgpAssert(sizeof(crc) == 2);
pgpCopyMemory(&crc, &mf->macBinHeader.crc1, sizeof(crc));
mf->flags = kPGPMacRead;
if (flags & kPGPFileOpenMaybeLocalEncode)
{
int i;
mf->flags |= kPGPMacBinMode;
for (i = 0; nonMacBinaryTypes[i] != 0; i++)
if (pb.ioFlFndrInfo.fdType == nonMacBinaryTypes[i])
{
mf->flags &= ~kPGPMacBinMode;
break;
}
}
else if (flags & kPGPFileOpenForceLocalEncode)
mf->flags |= kPGPMacBinMode;
io.fileParam.ioNamePtr = spec.name;
io.fileParam.ioVRefNum = spec.vRefNum;
io.fileParam.ioDirID = spec.parID;
io.ioParam.ioPermssn = fsRdPerm;
if (PBHOpenDFSync(&io) != noErr)
{
result = pgpErrorFromMacError(io.ioParam.ioResult, PGPERR_NO_FILE);
goto error;
}
mf->dataRef = io.ioParam.ioRefNum;
if (mf->flags & kPGPMacBinMode)
{
io.fileParam.ioNamePtr = spec.name;
io.fileParam.ioVRefNum = spec.vRefNum;
io.fileParam.ioDirID = spec.parID;
io.ioParam.ioPermssn = fsRdPerm;
if (PBHOpenRFSync(&io) != noErr)
{
result = pgpErrorFromMacError(io.ioParam.ioResult, PGPERR_NO_FILE);
goto error;
}
mf->resRef = io.ioParam.ioRefNum;
mf->dataOffset = 128;
mf->resOffset = mf->dataOffset + (pb.ioFlLgLen + 127) & ~127L;
mf->totalSize = mf->resOffset + (pb.ioFlRLgLen + 127) & ~127L;
if (flags & kPGPFileOpenLocalEncodeHashOnly)
{
mf->flags |= kPGPMacBinHashOnly;
/* Clear the finder flags */
mf->macBinHeader.info1.fdFlags = 0;
mf->macBinHeader.info2 = 0;
/* Clear the creation and modification dates */
mf->macBinHeader.creation = 0;
mf->macBinHeader.modification = 0;
/* Clear the filename */
pgpClearMemory(mf->macBinHeader.name,
sizeof(mf->macBinHeader.name));
/*
* Clear the CRC so that if this output gets used to
* recreate a file (which it shouldn't), it won't work
* properly and someone will notice the problem.
*/
pgpClearMemory(&mf->macBinHeader.crc1, sizeof(crc));
}
}
else
{
mf->resRef = 0;
mf->dataOffset = 0;
mf->totalSize = mf->resOffset = pb.ioFlLgLen;
}
mf->filePos = 0;
file->priv = mf;
file->read = macFileRead;
file->write = macFileWrite;
file->flush = macFileFlush;
file->close = macFileClose;
file->tell = macFileTell;
file->seek = macFileSeek;
file->eof = macFileEof;
file->sizeAdvise = macFileSizeAdvise;
file->error = macFileError;
file->clearError = macFileClearError;
file->write2read = macFileWrite2Read;
file->cfb = macFileCfb;
return file;
error:
if (mf != NULL)
{
if (mf->fileRef != NULL)
pgpFreeFileRef(mf->fileRef);
pgpFree(mf);
}
if (file != NULL)
pgpFree(file);
if (errorCode != NULL)
{
pgpAssertAddrValid(errorCode, PGPError);
*errorCode = result;
}
return NULL;
}
PGPError
pgpMacCalcFileSize(
PGPFileRef const * fileRef,
PGPFileOpenFlags flags,
size_t * fileSize)
{
FSSpec spec;
HFileParam pb;
Boolean macBinMode;
PGPError result = PGPERR_OK;
*fileSize = 0; /* In case there's an error */
if ((result = pgpFSSpecFromFileRef(fileRef, &spec)) != PGPERR_OK)
return result;
pb.ioNamePtr = spec.name;
pb.ioVRefNum = spec.vRefNum;
pb.ioDirID = spec.parID;
pb.ioFDirIndex = 0;
if (PBHGetFInfoSync((HParmBlkPtr)&pb) != noErr)
return pgpErrorFromMacError(pb.ioResult, PGPERR_NO_FILE);
macBinMode = FALSE;
if (flags & kPGPFileOpenMaybeLocalEncode)
{
int i;
macBinMode = TRUE;
for (i = 0; nonMacBinaryTypes[i] != 0; i++)
if (pb.ioFlFndrInfo.fdType == nonMacBinaryTypes[i])
{
macBinMode = FALSE;
break;
}
}
else if (flags & kPGPFileOpenForceLocalEncode)
macBinMode = TRUE;
if (macBinMode)
{
*fileSize = 128 + /* MacBinary header */
((pb.ioFlLgLen + 127) & ~127L) + /* Data fork */
((pb.ioFlRLgLen + 127) & ~127L); /* Resource fork */
}
else
*fileSize = pb.ioFlLgLen;
return PGPERR_OK;
}
/*
* Local Variables:
* tab-width: 4
* End:
* vi: ts=4 sw=4
* vim: si
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -