📄 pgpmacfile.c
字号:
/*____________________________________________________________________________
Copyright (C) 1997 Network Associates Inc. and affiliated companies.
All rights reserved.
$Id: pgpMacFile.c,v 1.59 1999/03/10 02:53:02 heller Exp $
____________________________________________________________________________*/
#include "pgpConfig.h"
#include <Devices.h>
#include <Files.h>
#include <Script.h>
#include <errno.h>
#include <stdio.h>
#if PGP_MACINTOSH /* [ */
#include <Errors.h>
#include "MacStrings.h"
#include "MacFiles.h"
#include "pgpTypes.h"
#include "pgpFile.h"
#include "pgpMacFile.h"
#include "pgpMacUtils.h"
#include "pgpFileRef.h"
#include "pgpFileSpec.h"
#include "pgpFileMod.h"
#include "pgpCFB.h"
#include "pgpMem.h"
#include "pgpErrors.h"
#include "pgpUsuals.h"
#include "pgpContext.h"
#include "pgpMacFileMapping.h"
/* XXX Is this stuff still necessary? */
#define CHANGED 0x0200 /* ---- --1- ---- ---- */
#define kFinderFlagsIgnore (kIsOnDesk | kHasBeenInited | CHANGED )
#if PRAGMA_ALIGN_SUPPORTED
#pragma options align=mac68k
#endif
typedef struct MacBinaryHeader
{
uchar filler;
uchar oldVersion; /* 000: Must be zero for compatibility */
uchar name[64]; /* 001: Pascal string */
FInfo info1; /* 065: Original Finder info: */
/* File type (long) */
/* File creator (long) */
/* Flags (word, low byte must be zero) */
/* File's location (Point) */
/* File's window (short) */
uchar protectedBit; /* 081: Low order bit */
uchar zero1; /* 082: Must be zero for compatibility */
long dLength; /* 083: Data fork length (in bytes) */
long rLength; /* 087: Resource fork length (in bytes) */
ulong creationDate; /* 091: Creation date */
ulong modificationDate; /* 095: Modification date */
short getInfoLength; /* 099: Get info length */
uchar info2; /* 101: Finder flags, low byte */
uchar dummy1;
uchar dummy2[18]; /* 103: Not used */
uchar dummy3;
uchar newVersion; /* 122: Uploading program version number */
uchar minimumVersion; /* 123: Minimum version number needed */
uchar crc1;
uchar crc2;
uchar endFiller[2]; /* To pad out to 128 bytes */
DEBUG_STRUCT_CONSTRUCTOR( MacBinaryHeader )
} MacBinaryHeader;
#if PRAGMA_ALIGN_SUPPORTED
#pragma options align=reset
#endif
/*____________________________________________________________________________
A MacFileTypeEntry maps a pgp file type to a mac creator/type pair.
____________________________________________________________________________*/
typedef struct MacFileTypeEntry
{
PGPFileType pgpFileType;
OSType creator;
OSType type;
} MacFileTypeEntry;
static MacFileTypeEntry sMacFileTypeTable[kPGPFileTypeNumTypes] =
{
{ kPGPFileTypePrefs,
kPGPMacFileCreator_Keys, kPGPMacFileType_Preferences },
{ kPGPFileTypePubRing,
kPGPMacFileCreator_Keys, kPGPMacFileType_PubRing },
{ kPGPFileTypePrivRing,
kPGPMacFileCreator_Keys, kPGPMacFileType_PrivRing },
{ kPGPFileTypeDetachedSig,
kPGPMacFileCreator_Tools, kPGPMacFileType_DetachedSig },
{ kPGPFileTypeRandomSeed,
kPGPMacFileCreator_Keys, kPGPMacFileType_RandomSeed },
{ kPGPFileTypeArmorFile,
kPGPMacFileCreator_Tools, kPGPMacFileType_ArmorFile },
{ kPGPFileTypeEncryptedData,
kPGPMacFileCreator_Tools, kPGPMacFileType_EncryptedData },
{ kPGPFileTypeGroups,
kPGPMacFileCreator_Keys, kPGPMacFileType_Groups },
/* XXX: The below should be user preferences */
/* but these are the defaults */
{ kPGPFileTypeDecryptedText,
kPGPMacFileCreator_DecryptedText, kPGPMacFileType_DecryptedText },
{ kPGPFileTypeDecryptedBin,
kPGPMacFileCreator_DecryptedBinary, kPGPMacFileType_DecryptedBinary },
{ kPGPFileTypeSignedData,
kPGPMacFileCreator_Tools, kPGPMacFileType_SignedData },
{ kPGPFileTypeExported509Keys,
kPGPMacFileCreator_Keys, kPGPMacFileType_Exported509Keys }
};
#define kNumMacFileTypeEntries \
( sizeof( sMacFileTypeTable ) / sizeof( sMacFileTypeTable[ 0 ] ) )
#define kPGPMacRead 0x01L
#define kPGPMacWrite 0x02L
#define kPGPMacBinMode 0x04L
/* For write mode only: whether we should check */
#define kPGPCheckMacBin 0x08L
/* Strip out volatile information for detached sig */
#define kPGPMacBinHashOnly 0x10L
/* CRC 0 in MacBin header is okay */
#define kPGPNoMacBinCRCOkay 0x20L
/* This is the private data for macfiles */
typedef struct MacFile
{
ulong flags;
short dataRef, resRef;
long dataOffset, resOffset, totalSize;
long filePos;
PGPFileError err;
PGPError error;
PFLFileSpecRef fileRef;
PGPFileType fileType;
MacBinaryHeader macBinHeader;
DEBUG_STRUCT_CONSTRUCTOR( MacFile )
} MacFile;
static PGPError PrepareToWrite(PGPFile *file, PGPBoolean autoMapMacTypes );
static PGPError SetFileInfo( PGPFile *file);
static void
macSetError(
PGPFile * file,
PGPError code)
{
MacFile * mf = (MacFile *)file->priv;
pgpAssert( pgpContextIsValid( file->context ) );
mf->err.f = file;
mf->err.fpos = mf->filePos;
mf->error = mf->err.error = code;
mf->err.syserrno = 0;
}
static OSErr
macFileReadFork(
PGPFile * file,
short refNum,
long forkOffset,
long forkEnd,
long * sizeLeftPtr,
void ** ptrPtr)
{
MacFile * mf = (MacFile *)file->priv;
long chunkSize;
OSErr err = noErr;
pgpAssert( pgpContextIsValid( file->context ) );
if (mf->filePos >= forkOffset &&
(chunkSize = pgpMin(*sizeLeftPtr, forkEnd - mf->filePos)) > 0)
{
UInt32 actualCount;
err = FSReadAtOffset( refNum, mf->filePos - forkOffset,
chunkSize, *ptrPtr, &actualCount, FALSE );
mf->filePos += actualCount;
*(Ptr *)ptrPtr += actualCount;
*sizeLeftPtr -= actualCount;
if ((mf->flags & kPGPMacBinMode) && err == eofErr)
{
/*
* Clear any memory which was beyond the EOF. This is expected
* in MacBinary because each fork is padded to a multiple of
* 128-bytes.
*/
chunkSize -= actualCount;
pgpClearMemory((uchar *)*ptrPtr, chunkSize);
mf->filePos += chunkSize;
*(Ptr *)ptrPtr += chunkSize;
*sizeLeftPtr -= chunkSize;
err = noErr;
}
else if (err != noErr)
macSetError(file, kPGPError_FileOpFailed);
}
return err;
}
static size_t
macFileRead(
void * ptr,
size_t size,
PGPFile * file)
{
MacFile * mf = (MacFile *)file->priv;
long sizeLeft = (long)size;
long chunkSize;
OSErr result = noErr;
pgpAssert(mf->filePos >= 0);
if (!(mf->flags & kPGPMacRead))
{
macSetError(file, kPGPError_IllegalFileOp);
return 0;
}
/* Handle portion in the MacBinary header, if any */
chunkSize = pgpMin(sizeLeft, mf->dataOffset - mf->filePos);
if ( chunkSize > 0 )
{
pgpCopyMemory( ((uchar *)&mf->macBinHeader) + 1 + mf->filePos,
ptr, chunkSize);
mf->filePos += chunkSize;
ptr = (void *)((Ptr)ptr + chunkSize);
sizeLeft -= chunkSize;
}
/* Handle portion in the data fork, if any */
if (result == noErr && sizeLeft > 0)
result = macFileReadFork(file, mf->dataRef, mf->dataOffset,
mf->resOffset, &sizeLeft, &ptr);
/*
* Handle zeroing the first 128 bytes of the resource fork,
* but only if kPGPMacBinHashOnly is set.
*/
chunkSize = pgpMin(sizeLeft,
pgpMin(mf->resOffset + 128, mf->totalSize) - mf->filePos);
if (result == noErr
&& (mf->flags & kPGPMacBinMode) && (mf->flags & kPGPMacBinHashOnly)
&& ( chunkSize > 0 ))
{
pgpClearMemory(ptr, chunkSize);
mf->filePos += chunkSize;
ptr = (void *)((Ptr)ptr + chunkSize);
sizeLeft -= chunkSize;
}
/* Handle portion in the resource fork, if any */
if (result == noErr && sizeLeft > 0 && (mf->flags & kPGPMacBinMode))
result = macFileReadFork(file, mf->resRef, mf->resOffset,
mf->totalSize, &sizeLeft, &ptr);
return (size_t)(size - sizeLeft);
}
static OSErr
macFileWriteFork(
PGPFile * file,
short refNum,
long forkOffset,
long forkEnd, /* Ignored unless kPGPMacBinMode flag set */
long forkLen, /* Ignored unless kPGPMacBinMode flag set */
long * sizeLeftPtr,
void const ** ptrPtr)
{
MacFile * mf = (MacFile *)file->priv;
long chunkSize;
OSErr result = noErr;
chunkSize = *sizeLeftPtr;
if (mf->flags & kPGPMacBinMode)
chunkSize = pgpMin(chunkSize, forkEnd - mf->filePos);
if (mf->filePos >= forkOffset && chunkSize > 0)
{
IOParam pb;
pb.ioRefNum = refNum;
pb.ioBuffer = (Ptr)*ptrPtr;
pb.ioPosMode = fsFromStart;
pb.ioPosOffset = mf->filePos - forkOffset;
pb.ioReqCount = chunkSize;
if (mf->flags & kPGPMacBinMode)
pb.ioReqCount = pgpMin(pb.ioReqCount, forkLen - pb.ioPosOffset);
result = PBWriteSync((ParmBlkPtr)&pb);
mf->filePos += chunkSize;
*(Ptr *)ptrPtr += chunkSize;
*sizeLeftPtr -= chunkSize;
if (result != noErr)
macSetError(file, kPGPError_FileOpFailed);
}
if (mf->totalSize < mf->filePos)
mf->totalSize = mf->filePos;
return result;
}
static size_t
macFileWrite(
void const * ptr,
size_t size,
PGPFile * file)
{
MacFile * mf = (MacFile *)file->priv;
long sizeLeft = (long)size;
long chunkSize;
OSErr macErr = noErr;
pgpAssert(mf->filePos >= 0);
pgpAssert( ( mf->flags & kPGPMacWrite) != 0 );
if (!(mf->flags & kPGPMacWrite))
{
macSetError(file, kPGPError_FileLocked);
return 0;
}
/* Handle portion in the MacBinary header, if any */
chunkSize = pgpMin(sizeLeft, mf->dataOffset - mf->filePos);
if ( chunkSize > 0)
{
pgpAssert(mf->filePos + chunkSize <= 128);
pgpCopyMemory(ptr, ((uchar *)&mf->macBinHeader) + 1 + mf->filePos,
chunkSize);
mf->filePos += chunkSize;
ptr = (void *)((Ptr)ptr + chunkSize);
sizeLeft -= chunkSize;
if (mf->totalSize < mf->filePos)
mf->totalSize = mf->filePos;
}
/* Handle portion in the data fork, if any */
if (macErr == noErr && sizeLeft > 0)
{
if ( IsPGPError( PrepareToWrite(file, TRUE ) ) )
return( 0 );
macErr = macFileWriteFork(file, mf->dataRef, mf->dataOffset,
mf->resOffset, mf->macBinHeader.dLength,
&sizeLeft, &ptr);
}
/* Handle portion in the resource fork, if any */
if (macErr == noErr &&
sizeLeft > 0 &&
(mf->flags & kPGPMacBinMode))
{
macErr = macFileWriteFork(file, mf->resRef, mf->resOffset,
mf->totalSize, mf->macBinHeader.rLength,
&sizeLeft, &ptr);
}
return (size_t)(size - sizeLeft);
}
static PGPError
macFileFlush(
PGPFile * file)
{
MacFile * mf = (MacFile *)file->priv;
IOParam pb;
pb.ioRefNum = mf->dataRef;
PBFlushFileSync((ParmBlkPtr)&pb);
pb.ioRefNum = mf->resRef;
PBFlushFileSync((ParmBlkPtr)&pb);
return kPGPError_NoErr;
}
static PGPError
macFileClose(
PGPFile * file)
{
MacFile * mf = (MacFile *)file->priv;
PGPContextRef cdkContext;
pgpAssertAddrValid( file, PGPFile );
cdkContext = file->context;
pgpAssert( pgpContextIsValid( cdkContext ) );
if ( ( mf->flags & kPGPMacWrite) != 0 )
{
PrepareToWrite(file, TRUE );
}
if (mf->dataRef > 0)
FSClose(mf->dataRef);
if (mf->resRef > 0)
FSClose(mf->resRef);
SetFileInfo(file);
PFLFreeFileSpec(mf->fileRef);
pgpClearMemory((void *)mf, sizeof(*mf));
pgpContextMemFree( cdkContext, mf);
pgpContextMemFree( cdkContext, file);
return kPGPError_NoErr;
}
static long
macFileTell(
PGPFile * file)
{
MacFile * mf = (MacFile *)file->priv;
return mf->filePos;
}
static PGPError
macFileSeek(
PGPFile * file,
long offset,
int whence)
{
MacFile * mf = (MacFile *)file->priv;
switch (whence)
{
case SEEK_SET:
/* offset is correct, as is */
break;
case SEEK_CUR:
offset += mf->filePos;
break;
case SEEK_END:
offset += mf->totalSize;
break;
}
if (offset < 0 || offset > mf->totalSize)
{
macSetError(file, kPGPError_FileOpFailed);
return kPGPError_FileOpFailed;
}
mf->filePos = offset;
return kPGPError_NoErr;
}
static PGPBoolean
macFileEof(
PGPFile const * file)
{
MacFile * mf = (MacFile *)file->priv;
/*
* XXX This will always return TRUE when writing files.
* Is that semantically correct?
*/
return mf->filePos >= mf->totalSize;
}
static long
macFileSizeAdvise(
PGPFile const * file)
{
MacFile * mf = (MacFile *)file->priv;
return mf->totalSize;
}
static PGPFileError const *
macFileError(
PGPFile const * file)
{
MacFile * mf = (MacFile *)file->priv;
if (mf->error != kPGPError_NoErr)
return &mf->err;
else
return NULL;
}
static void
macFileClearError(
PGPFile * file)
{
MacFile * mf = (MacFile *)file->priv;
mf->error = kPGPError_NoErr;
}
static PGPError
macFileWrite2Read(
PGPFile * file)
{
macSetError(file, kPGPError_IllegalFileOp);
return kPGPError_IllegalFileOp;
}
static PGPCFBContext *
macFileCfb(
PGPFile const * file)
{
(void)file; /* Quiet compiler warning */
/* XXX: I'm not really sure what should be done here */
return NULL;
}
#ifndef __powerc
static ushort asm CalcCRC16Contin(ushort start, const void *data, long len)
{
fralloc +
move.l D3, -(SP)
move.w #0x1021, D3
clr.l D0
move.w start, D0
move.l data, A0
move.l len, D2
bra Loop1
Loop0:
move.b (A0)+, D1
lsl.w #8, D1
eor.w D1, D0
moveq #7, D1
ShiftLoop0:
lsl.w #1, D0
bcc ShiftLoop1
eor.w D3, D0
ShiftLoop1:
dbra D1, ShiftLoop0
Loop1:
dbra D2, Loop0
move.l (SP)+, D3
frfree
#if GENERATINGCFM || defined(__CFM68K__)
rtd #12
#else
rts
#endif
}
static uchar asm CalcChecksum8Contin(uchar start, const void *data, long len)
{
FRALLOC +
CLR.L D0
MOVE.B start, D0
MOVE.L data, A0
MOVE.L len, D1
BRA Loop1
Loop0:
ADD.B (A0)+, D0
Loop1:
DBRA D1, Loop0
FRFREE
#if GENERATINGCFM || defined(__CFM68K__)
rtd #12
#else
rts
#endif
}
static ulong asm CalcCRC32(const void *data, long len)
{
fralloc +
move.l data, A0
clr.l D0
move.l len, D1
lsr.l #2, D1
bra Loop1
Loop0:
rol.l #1, D0
add.l (A0)+, D0
Loop1:
dbra D1, Loop0
moveq #3, D2
move.l len, D1
and.l D2, D1
lsl.w D2, D1
clr.l D2
not.l D2
lsr.l D1, D2
not.l D2
and.l (A0), D2
rol.l #1, D0
add.l D2, D0
frfree
#if GENERATINGCFM || defined(__CFM68K__)
rtd #8
#else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -