⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pgpfilemac.c

📁 PGP8.0源码 请认真阅读您的文件包然后写出其具体功能
💻 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 + -