📄 str_file.c
字号:
/* If we're doing a read, fetch the data into memory */
if( mode & FILE_READ )
{
FILE *filePtr;
fldata_t fileData;
char fileBuffer[ MAX_PATH_LENGTH ];
int count;
/* Open the file and determine how large it is */
filePtr = fopen( fileName, "rb" );
if( filePtr == NULL )
return( CRYPT_ERROR_OPEN );
status = fldata( filePtr, fileBuffer, &fileData );
if( status )
{
fclose( filePtr );
return( CRYPT_ERROR_OPEN );
}
length = fileData.__maxreclen;
/* Fetch the data into a buffer large enough to contain the entire
stream */
if( ( stream->buffer = clAlloc( "sFileOpen", length ) ) == NULL )
return( CRYPT_ERROR_MEMORY );
stream->bufSize = stream->bufEnd = length;
status = fread( stream->buffer, length, 1, filePtr );
fclose( filePtr );
return( ( status != 1 ) ? CRYPT_ERROR_READ : CRYPT_OK );
}
/* Allocate the initial I/O buffer for the data */
if( ( stream->buffer = clAlloc( "sFileOpen", STREAM_BUFSIZE ) ) == NULL )
return( CRYPT_ERROR_MEMORY );
stream->bufSize = STREAM_BUFSIZE;
return( CRYPT_OK );
#else
#error Need to add mechanism to connect stream to backing store
return( CRYPT_ERROR_OPEN );
#endif /* Nonstandard I/O enviroments */
}
int sFileClose( STREAM *stream )
{
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( stream->type != STREAM_TYPE_NULL );
#if defined( __IBM4758__ )
/* Close the file and clear the stream structure */
zeroise( stream->buffer, stream->bufSize );
clFree( "sFileClose", stream->buffer );
zeroise( stream, sizeof( STREAM ) );
return( CRYPT_OK );
#elif defined( __VMCMS__ )
/* Close the file and clear the stream structure */
zeroise( stream->buffer, stream->bufSize );
clFree( "sFileClose", stream->buffer );
zeroise( stream, sizeof( STREAM ) );
return( CRYPT_OK );
#else
#error Need to add mechanism to disconnect stream from backing store
zeroise( stream, sizeof( STREAM ) );
return( CRYPT_OK );
#endif /* Nonstandard I/O enviroments */
}
/* Read/write a block of data from/to a file stream */
int fileRead( STREAM *stream, void *buffer, const int length )
{
#if defined( __IBM4758__ ) || defined( __VMCMS__ )
/* These environments move all data into an in-memory buffer when the
file is opened, so there's never any need to read more data from the
stream */
return( CRYPT_ERROR_READ );
#else
#error Need to add mechanism to read data from backing store
return( CRYPT_ERROR_READ );
#endif /* Nonstandard I/O enviroments */
}
int fileWrite( STREAM *stream, const void *buffer, const int length )
{
#if defined( __IBM4758__ ) || defined( __VMCMS__ )
/* Expand the write buffer on demand when it fills up. If it's a small
buffer allocated when we initially read a file and it doesn't look
like we'll be overflowing a standard-size buffer, we first expand it
up to STREAM_BUFSIZE before increasing it in STREAM_BUFSIZE steps.
The following routine does a safe realloc() that wipes the original
buffer */
void *newBuffer;
const int newSize = ( stream->bufSize < STREAM_BUFSIZE && \
stream->bufPos + length < STREAM_BUFSIZE - 1024 ) ? \
STREAM_BUFSIZE : stream->bufSize + STREAM_BUFSIZE;
/* Allocate the buffer and copy the new data across. If the malloc
fails we return CRYPT_ERROR_OVERFLOW rather than CRYPT_ERROR_MEMORY
since the former is more appropriate for the emulated-I/O environment */
if( ( newBuffer = clDynAlloc( "expandBuffer", \
stream->bufSize + STREAM_BUFSIZE ) ) == NULL )
return( CRYPT_ERROR_OVERFLOW );
memcpy( newBuffer, stream->buffer, stream->bufSize );
zeroise( stream->buffer, stream->bufSize );
clFree( "expandBuffer", stream->buffer );
stream->buffer = newBuffer;
stream->bufSize = newSize;
return( CRYPT_OK );
#else
#error Need to add mechanism to write data to backing store
return( CRYPT_ERROR_WRITE );
#endif /* Nonstandard I/O enviroments */
}
/* Commit data in a file stream to backing storage */
int fileFlush( STREAM *stream )
{
#if defined( __IBM4758__ )
/* Write the data to flash or BB memory as appropriate */
if( sccSavePPD( stream->name, stream->buffer, stream->bufEnd,
( stream->isSensitive ? PPD_BBRAM : PPD_FLASH ) | PPD_TRIPLE ) != PPDGood )
return( CRYPT_ERROR_WRITE );
return( CRYPT_OK );
#elif defined( __VMCMS__ )
/* Under CMS, MVS, TSO, etc the only consistent way to handle writes is
to write a fixed-length single-record file containing all the data in
one record, so we can't really do anything until the data is flushed */
FILE *filePtr;
char formatBuffer[ 64 ];
int count;
sprintf( formatBuffer, "wb, recfm=F, lrecl=%d, noseek", stream->bufPos );
filePtr = fopen( stream->name, formatBuffer );
if( filePtr == NULL )
return( CRYPT_ERROR_WRITE );
count = fwrite( stream->buffer, stream->bufEnd, 1, filePtr );
fclose( filePtr );
return( ( count != 1 ) ? CRYPT_ERROR_WRITE : CRYPT_OK );
#else
#error Need to add mechanism to commit data to backing store
return( CRYPT_ERROR_WRITE );
#endif /* Nonstandard I/O enviroments */
}
/* Change the read/write position in a file */
int fileSeek( STREAM *stream, const long position )
{
#if defined( __IBM4758__ ) || defined( __VMCMS__ )
/* These environments move all data into an in-memory buffer when the
file is opened, so there's never any need to move around in the
stream */
return( CRYPT_ERROR_READ );
#else
#error Need to add mechanism to perform virtual seek on backing store
return( CRYPT_ERROR_READ );
#endif /* Nonstandard I/O enviroments */
}
/* Check whether a file is writeable */
BOOLEAN fileReadonly( const char *fileName )
{
/* Since there's no filesystem, there's no concept of a read-only
file - all data items are always accessible */
return( FALSE );
}
/* File deletion functions: Wipe a file from the current position to EOF,
and wipe and delete a file (although it's not terribly rigorous).
Vestigia nulla retrorsum */
void fileClearToEOF( const STREAM *stream )
{
#if defined( __IBM4758__ ) || defined( __VMCMS__ )
/* Data updates on these systems are atomic so there's no remaining data
left to clear */
UNUSED( stream );
#else
#error Need to add file clear-to-EOF function
#endif /* Nonstandard I/O enviroments */
}
void fileErase( const char *fileName )
{
#if defined( __IBM4758__ )
sccDeletePPD( ( char * ) fileName );
#elif defined( __VMCMS__ )
FILE *filePtr;
int length = CRYPT_ERROR, status;
assert( fileName != NULL );
/* Determine how large the file is */
filePtr = fopen( fileName, "rb+" );
if( filePtr != NULL )
{
fldata_t fileData;
char fileBuffer[ MAX_PATH_LENGTH ];
int status;
status = fldata( filePtr, fileBuffer, &fileData );
if( status == 0 )
length = fileData.__maxreclen;
}
/* If we got a length, overwrite the data. Since the file contains a
single record we can't perform the write-until-done overwrite used
on other OS'es, however since we're only going to be deleting short
private key files using the default stream buffer is OK for this */
if( length > 0 )
{
RESOURCE_DATA msgData;
BYTE buffer[ STREAM_BUFSIZE ];
length = max( length, STREAM_BUFSIZE );
setMessageData( &msgData, buffer, length );
krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );
fwrite( buffer, 1, length, filePtr );
}
if( filePtr != NULL )
{
fflush( filePtr );
fclose( filePtr );
}
remove( fileName );
#else
#error Need to add file erase function
#endif /* Nonstandard I/O enviroments */
}
/* Build the path to a file in the cryptlib directory */
void fileBuildCryptlibPath( char *path, const char *fileName,
const BOOLEAN createPath )
{
/* Make sure that the open fails if we can't build the path */
*path = '\0';
/* Build the path to the configuration file if necessary */
#if defined( __IBM4758__ )
strcpy( path, fileName );
#elif defined( __VMCMS__ )
strcpy( path, fileName );
strcat( path, " p15" );
#else
#error Need to add function to build the config file path
#endif /* OS-specific file path creation */
}
/****************************************************************************
* *
* Everything Else *
* *
****************************************************************************/
#else
/* BC++ 3.1 is rather anal-retentive about not allowing extensions when in
ANSI mode */
#if defined( __STDC__ ) && ( __BORLANDC__ == 0x410 )
#define fileno( filePtr ) ( ( filePtr )->fd )
#endif /* BC++ 3.1 in ANSI mode */
/* When checking whether a file is read-only we also have to check (via
errno) to make sure that the file actually exists since the access check
will return a false positive for a nonexistant file */
#if defined( __MSDOS16__ ) || defined( __OS2__ ) || defined( __WIN16__ )
#include <errno.h>
#endif /* __MSDOS16__ || __OS2__ || __WIN16__ */
/* Some OS'es don't define W_OK for the access check */
#ifndef W_OK
#define W_OK 2
#endif /* W_OK */
/* Symbolic defines for the stdio file access modes */
#define MODE_READ "rb"
#define MODE_WRITE "wb"
#define MODE_READWRITE "rb+"
/* Open/close a file stream */
int sFileOpen( STREAM *stream, const char *fileName, const int mode )
{
static const char *modes[] = { MODE_READ, MODE_READ,
MODE_WRITE, MODE_READWRITE };
const char *openMode;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( fileName != NULL );
assert( mode != 0 );
/* Initialise the stream structure */
memset( stream, 0, sizeof( STREAM ) );
stream->type = STREAM_TYPE_FILE;
if( ( mode & FILE_RW_MASK ) == FILE_READ )
stream->flags = STREAM_FLAG_READONLY;
openMode = modes[ mode & FILE_RW_MASK ];
/* If we're trying to write to the file, check whether we've got
permission to do so */
if( ( mode & FILE_WRITE ) && fileReadonly( fileName ) )
return( CRYPT_ERROR_PERMISSION );
#if defined( __MSDOS16__ ) || defined( __WIN16__ ) || defined( __OS2__ ) || \
defined( __SYMBIAN32__ )
/* Try and open the file */
stream->filePtr = fopen( fileName, openMode );
if( stream->filePtr == NULL )
/* The open failed, determine whether it was because the file doesn't
exist or because we can't use that access mode */
return( ( access( fileName, 0 ) == -1 ) ? CRYPT_ERROR_NOTFOUND : \
CRYPT_ERROR_OPEN );
#elif defined( __TANDEMNSK__ )
stream->filePtr = fopen( fileName, openMode );
if( stream->filePtr == NULL )
return( ( errno == ENOENT ) ? \
CRYPT_ERROR_NOTFOUND : CRYPT_ERROR_OPEN );
#else
#error Need to add file accessibility call
#endif /* OS-specific file accessibility check */
return( CRYPT_OK );
}
int sFileClose( STREAM *stream )
{
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( stream->type == STREAM_TYPE_FILE );
/* Close the file and clear the stream structure */
fclose( stream->filePtr );
zeroise( stream, sizeof( STREAM ) );
return( CRYPT_OK );
}
/* Read/write a block of data from/to a file stream */
int fileRead( STREAM *stream, void *buffer, const int length )
{
int bytesRead;
if( ( bytesRead = fread( buffer, 1, length, stream->filePtr ) ) < length && \
( bytesRead < 0 || ferror( stream->filePtr ) ) )
return( CRYPT_ERROR_READ );
return( bytesRead );
}
int fileWrite( STREAM *stream, const void *buffer, const int length )
{
if( fwrite( buffer, 1, length, stream->filePtr ) != length )
return( CRYPT_ERROR_WRITE );
return( CRYPT_OK );
}
/* Commit data in a file stream to backing storage */
int fileFlush( STREAM *stream )
{
fflush( stream->filePtr );
return( CRYPT_OK );
}
/* Change the read/write position in a file */
int fileSee
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -