📄 pgpfilemac.c
字号:
/*____________________________________________________________________________
Copyright (C) 2002 PGP Corporation
All rights reserved.
$Id: pgpFileMac.c,v 1.2 2002/08/06 20:11:14 dallen Exp $
____________________________________________________________________________*/
#include "pgpConfig.h"
#include <errno.h>
#include <stdio.h>
#if ! PGP_MACINTOSH
#error use pgpFile.c
#endif
#if PGP_MACINTOSH
#include <Files.h>
#endif
#include "pgpDebug.h"
#include "pgpFileMac.h"
#include "pgpCFBPriv.h"
#include "pgpMem.h"
#include "pgpErrors.h"
#include "pgpContext.h"
struct File
{
PGPError (*doClose)(FSRef* file, SInt16 forkRefNum, void* arg);
void* closeArg;
PGPFileError err;
PGPCFBContext* cfb;
FSRef fRef;
SInt16 forkRefNum;
PGPError error;
int flags;
PGPFileOffset totalSize;
PGPFileOffset filePos;
PGPFileOffset maybeSize; /* Size or -1 if not a regular file, for sizeAdvise */
DEBUG_STRUCT_CONSTRUCTOR(File)
};
typedef struct File File;
/*
* These are the different flags, which define the various operations
* * * and types.
*/
#define FLAGS_READ 0x01
#define FLAGS_WRITE 0x02
#define FLAGS_FILE 0x04
#define FLAGS_PROC 0x08
#define FLAGS_DONTCLOSE 0x10
#define PGP_FILE_READ (FLAGS_FILE|FLAGS_READ)
#define PGP_FILE_WRITE (FLAGS_FILE|FLAGS_WRITE)
#define PGP_PROC_WRITE (FLAGS_PROC|FLAGS_WRITE)
/***************************************************/
/* Stdio Functions */
static void
setError(PGPFile* file, int code)
{
File* fp;
pgpAssertAddrValid(file, PGPFile);
fp = (File*) file->priv;
fp->err.f = file;
fp->err.syserrno = errno;
fp->err.error = (PGPError) code;
fp->error = (PGPError) code;
if (fp->error)
fp->err.fpos = fp->filePos;
}
static PGPSize
fsRead(void* buf, ByteCount count, PGPFile* file)
{
OSErr macErr;
File* fp;
ByteCount readCount = 0;
pgpAssertAddrValid(file, PGPFile);
fp = (File*) file->priv;
if (count)
{
pgpAssert(fp->filePos >= 0);
if (IsNull(buf))
{
setError(file, kPGPError_BadParams);
return 0;
}
if (!(fp->flags & FLAGS_READ))
{
setError(file, kPGPError_IllegalFileOp);
return 0;
}
macErr = FSReadFork(fp->forkRefNum,
fsAtMark, /* Use the current file position */
0, /* Ignored because of previous argument */
count,
buf,
&readCount); /* Actual number of bytes read */
if ((readCount != count) && (macErr != eofErr))
{
setError(file, kPGPError_ReadFailed);
return 0;
}
fp->filePos += readCount;
}
return readCount;
}
static PGPSize
fsWrite(const void* src, ByteCount count, PGPFile* file)
{
OSErr macErr;
File* fp;
ByteCount wroteCount = 0;
pgpAssertAddrValid(file, PGPFile);
fp = (File*) file->priv;
if (IsNull(src))
{
setError(file, kPGPError_BadParams);
return 0;
}
pgpAssert(fp->filePos >= 0);
if (!(fp->flags & FLAGS_WRITE))
{
setError(file, kPGPError_FileLocked);
return 0;
}
macErr = FSWriteFork(fp->forkRefNum,
fsAtMark, /* Use the current file position */
0, /* Ignored because of previous argument */
count,
(void*) src,
&wroteCount); /* Actual number of bytes written */
if (macErr != noErr)
{
setError(file, kPGPError_WriteFailed);
return 0;
}
fp->filePos += wroteCount;
/* Increase our file size marker */
if (fp->totalSize < fp->filePos)
fp->totalSize = fp->maybeSize = fp->filePos;
return wroteCount;
}
static PGPError
fsFlush(PGPFile* file)
{
OSErr macErr;
File* fp;
pgpAssertAddrValid(file, PGPFile);
fp = (File*) file->priv;
if (!(fp->flags & FLAGS_WRITE))
return kPGPError_FileLocked;
macErr = FSFlushFork(fp->forkRefNum);
if (macErr != noErr)
return kPGPError_FileOpFailed;
(void) file->tell(file); /* Tell will set the file position marker for us */
return kPGPError_NoErr;
}
static PGPFileOffset
fsTell(PGPFile* file)
{
OSErr macErr;
File* fp;
PGPFileOffset position;
pgpAssertAddrValid(file, PGPFile);
fp = (File*) file->priv;
macErr = FSGetForkPosition(fp->forkRefNum, &position);
if (macErr != noErr)
position = -1;
fp->filePos = position;
return position;
}
static PGPError
fsSeek(PGPFile* file, PGPFileOffset offset, int whence)
{
OSErr macErr;
File* fp;
PGPUInt32 positionMode;
pgpAssertAddrValid(file, PGPFile);
fp = (File*) file->priv;
if (!(fp->flags & FLAGS_READ))
return kPGPError_IllegalFileOp;
/* Translate whence into a Mac position mode */
switch (whence)
{
case SEEK_SET:
positionMode = fsFromStart;
break;
case SEEK_CUR:
positionMode = fsAtMark;
break;
case SEEK_END:
positionMode = fsFromLEOF;
break;
default:
pgpAssertMsg(0, "Must select one of SEEK_SET, SEEK_CUR, or SEEK_END");
return kPGPError_BadParams;
}
macErr = FSSetForkPosition(fp->forkRefNum, positionMode, offset);
if (macErr != noErr)
{
setError(file, kPGPError_FileOpFailed);
return kPGPError_FileOpFailed;
}
(void) file->tell(file); /* Tell will set the file position marker for us */
return kPGPError_NoErr;
}
/**********************************************************/
/* Non-specific functions (stdio or encrypted) */
static PGPError
fileClose(PGPFile* file)
{
OSErr macErr;
File* fp;
PGPError code = kPGPError_NoErr;
pgpAssertAddrValid(file, PGPFile);
fp = (File*) file->priv;
if ((fp->flags & FLAGS_FILE) && !(fp->flags & FLAGS_DONTCLOSE))
{
macErr = FSCloseFork(fp->forkRefNum);
if (macErr != noErr)
{
setError(file, kPGPError_FileOpFailed);
return kPGPError_FileOpFailed;
}
}
/* If we have some custom close procedure, use it. */
else if (fp->flags & FLAGS_PROC)
{
if (fp->doClose)
{
code = (PGPError) fp->doClose(&(fp->fRef), fp->forkRefNum, fp->closeArg);
if (code)
{
setError(file, kPGPError_FileOpFailed);
return kPGPError_FileOpFailed;
}
else
code = kPGPError_NoErr;
}
else
return kPGPError_FileOpFailed;
}
if (fp->cfb)
code = PGPFreeCFBContext(fp->cfb);
pgpClearMemory(fp, sizeof(*fp));
PGPFreeData(fp);
pgpClearMemory(file, sizeof(*file));
PGPFreeData(file);
return code;
}
static PGPBoolean
fileEof(PGPFile const* file)
{
File* fp;
pgpAssertAddrValid(file, PGPFile);
fp = (File*) file->priv;
/* Perhaps we should check for filePos == -1 as well */
return (fp->filePos >= fp->totalSize);
}
static PGPFileOffset
fileSizeAdvise(PGPFile const* file)
{
File* fp;
pgpAssertAddrValid(file, PGPFile);
fp = (File*) file->priv;
return fp->maybeSize;
}
static PGPFileError const*
fileError(PGPFile const* file)
{
File* fp;
pgpAssertAddrValid(file, PGPFile);
fp = (File*) file->priv;
if (fp->error)
return &(fp->err);
return NULL;
}
static void
fileClearError(PGPFile *file)
{
File* fp;
pgpAssertAddrValid(file, PGPFile);
fp = (File*) file->priv;
setError(file, kPGPError_NoErr);
}
/*
Converts a writing file to a reading file.
Note:
This function only modifies the flags associated with a PGPFile.
Therefore, fwrite( ( (File*)(file->priv) )->f, ...) would still work,
however pgpFileWrite(file) would fail because FLAGS_WRITE is disabled.
*/
static PGPError
fileWrite2read(PGPFile* file)
{
File* fp;
pgpAssertAddrValid(file, PGPFile);
fp = (File*) file->priv;
/* This may look strange, but remember that PGP_FILE_WRITE == (FLAGS_PROC | FLAGS_WRITE) */
if ((fp->flags & PGP_FILE_WRITE) != PGP_FILE_WRITE)
return kPGPError_FileLocked;
fp->flags &= ~FLAGS_READ;
fp->flags |= FLAGS_WRITE;
/* XXX -- should I rewind this file? */
/* return pgpFileSeek (file, 0, SEEK_SET); */
return kPGPError_NoErr;
}
/* Creates a new PGPCFBContext and returns it. Returns NULL otherwise */
static PGPCFBContextRef
fileCfb(PGPFile const* file)
{
File* fp;
pgpAssertAddrValid(file, PGPFile);
fp = (File*) file->priv;
if (IsntNull(fp->cfb))
{
PGPCFBContextRef newRef;
PGPError err;
err = PGPCopyCFBContext(fp->cfb, &newRef);
pgpAssertMsg(IsntPGPError(err), "Unable to copy CFB Context");
return(newRef);
}
return NULL;
}
/*************************************************************/
/* Open functions */
/* take a FILE* and convert it to a PGPFile* */
static PGPFile*
doOpen(PGPContextRef cdkContext, FSRef* file, SInt16 forkRefNum, int fflags)
{
PGPFile* pgpFilePtr;
File* FilePtr;
OSErr macErr;
FSRefParam filePB;
FSCatalogInfo fileCatInfo;
HFSUniStr255 fileUniName;
SInt32 gestaltResponse = 0;
PGPMemoryMgrRef memoryMgr = PGPPeekContextMemoryMgr(cdkContext);
if (!file)
return 0;
pgpFilePtr = (PGPFile*) PGPNewData(memoryMgr, sizeof (PGPFile), kPGPMemoryMgrFlags_Clear);
if (!pgpFilePtr)
return 0;
pgpFilePtr->context = cdkContext;
pgpFilePtr->dataType = kPGPFileDataType_Unknown;
FilePtr = (File*) PGPNewData(memoryMgr, sizeof (File), kPGPMemoryMgrFlags_Clear);
if (!FilePtr)
{
PGPFreeData(pgpFilePtr);
return 0;
}
/* We're only interested in getting the data fork sizes */
fileCatInfo.dataLogicalSize = 0;
fileCatInfo.dataPhysicalSize = 0;
filePB.ref = file;
filePB.whichInfo = kFSCatInfoDataSizes;
filePB.catInfo = &fileCatInfo;
filePB.spec = NULL;
filePB.parentRef = NULL;
filePB.outName = &fileUniName;
macErr = PBGetCatalogInfoSync(&filePB);
if (macErr != noErr)
{
PGPFreeData(FilePtr);
PGPFreeData(pgpFilePtr);
return 0;
}
FilePtr->maybeSize = fileCatInfo.dataLogicalSize; /* Should this be physical size? */
FilePtr->totalSize = fileCatInfo.dataLogicalSize;
FilePtr->filePos = 0;
/* Rewind the file offset to 0 */
macErr = FSSetForkPosition(forkRefNum, fsFromStart, 0);
if (macErr != noErr)
{
PGPFreeData(FilePtr);
PGPFreeData(pgpFilePtr);
return 0;
}
FilePtr->fRef = *file;
FilePtr->forkRefNum = forkRefNum;
FilePtr->flags = fflags;
pgpFilePtr->priv = FilePtr;
pgpFilePtr->read = fsRead;
pgpFilePtr->write = fsWrite;
pgpFilePtr->flush = fsFlush;
pgpFilePtr->tell = fsTell;
pgpFilePtr->seek = fsSeek;
pgpFilePtr->close = fileClose;
pgpFilePtr->eof = fileEof;
pgpFilePtr->sizeAdvise = fileSizeAdvise;
pgpFilePtr->error = fileError;
pgpFilePtr->clearError = fileClearError;
pgpFilePtr->write2read = fileWrite2read;
pgpFilePtr->cfb = fileCfb;
return pgpFilePtr;
}
/* Convert an FSRef* to PGPFile* in Write Mode */
PGPFile*
pgpFileWriteOpen(PGPContextRef cdkContext, FSRef* file, SInt16 forkRefNum, PGPCFBContext* cfbp)
{
pgpAssert(cfbp == NULL);
return doOpen(cdkContext, file, forkRefNum, PGP_FILE_WRITE);
}
/* Same as above, but don't close the fork automatically */
PGPFile*
pgpFileWriteOpenDontClose(PGPContextRef context, FSRef* file, SInt16 forkRefNum,
PGPCFBContext* cfbp)
{
pgpAssert (cfbp == NULL);
return doOpen(context, file, forkRefNum, PGP_FILE_WRITE | FLAGS_DONTCLOSE);
}
/* Convert an FSRef* to PGPFile* in Read Mode */
PGPFile*
pgpFileReadOpen(PGPContextRef context, FSRef* file, SInt16 forkRefNum, PGPUICb const* ui,
void* ui_arg)
{
(void) ui;
(void) ui_arg;
/*
* We still need to check the file for encryption and obtain
* the decryption key, somehow.
*/
return doOpen (context, file, forkRefNum, PGP_FILE_READ);
}
PGPFile*
pgpFileProcWriteOpen(PGPContextRef context, FSRef* file, SInt16 forkRefNum,
PGPError (*doClose) (FSRef* file, SInt16 forkRefNum, void* arg),
void* arg)
{
PGPFile* fp;
File* f;
fp = doOpen(context, file, forkRefNum, PGP_PROC_WRITE);
pgpAssert(fp);
f = (File*) fp->priv;
pgpAssert(f);
f->doClose = doClose;
f->closeArg = arg;
return fp;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -