📄 file.c
字号:
int fileSeek( STREAM *stream, const long position )
{
if( FS_FSeek( stream->pFile, position, FS_SEEK_SET ) < 0 )
return( CRYPT_ERROR_WRITE );
return( CRYPT_OK );
}
/* Check whether a file is writeable */
BOOLEAN fileReadonly( const char *fileName )
{
FS_U8 fileAttr;
assert( fileName != NULL );
if( ( fileAttr = FS_GetFileAttributes( fileName ) ) == 0xFF )
return( TRUE );
return( ( fileAttr & FS_ATTR_READONLY ) ? TRUE : 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 */
static void eraseFile( const STREAM *stream, long position, long length )
{
/* Wipe everything past the current position in the file */
while( length > 0 )
{
RESOURCE_DATA msgData;
BYTE buffer[ BUFSIZ * 2 ];
int bytesToWrite = min( length, BUFSIZ * 2 );
/* We need to make sure that we fill the buffer with random data for
each write, otherwise compressing filesystems will just compress
it to nothing */
setMessageData( &msgData, buffer, bytesToWrite );
krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );
if( FS_Write( stream->pFile, buffer, bytesToWrite ) < 0 )
break; /* An error occurred while writing, exit */
length -= bytesToWrite;
}
fjchsize( stream->pFile, position );
}
void fileClearToEOF( const STREAM *stream )
{
int length, position;
assert( isReadPtr( stream, sizeof( STREAM ) ) );
assert( stream->type == STREAM_TYPE_FILE );
/* Wipe everything past the current position in the file */
if( ( length = FS_GetFileSize( fileName ) ) < 0 )
return;
if( ( position = FS_FTell( stream->pFile ) ) < 0 )
return;
length -= position;
if( length <= 0 )
return; /* Nothing to do, exit */
eraseFile( stream, position, length );
}
void fileErase( const char *fileName )
{
STREAM stream;
int length, status;
assert( fileName != NULL );
if( ( length = FS_GetFileSize( fileName ) ) < 0 )
return;
/* Try and open the file so that we can erase it. If this fails, the
best that we can do is a straight unlink */
status = sFileOpen( &stream, fileName,
FILE_READ | FILE_WRITE | FILE_EXCLUSIVE_ACCESS );
if( cryptStatusError( status ) )
{
remove( fileName );
return;
}
/* Determine the size of the file and erase it */
eraseFile( &stream, 0, length );
/* Reset the file's attributes and delete it */
sFileClose( &stream );
FS_SetFileAttributes( stream.pFile, FS_ATTR_ARCHIVE );
FS_SetFileTime( stream.pFile, 0 );
FS_Remove( fileName );
}
/* Build the path to a file in the cryptlib directory */
void fileBuildCryptlibPath( char *path, const char *fileName,
const BUILDPATH_OPTION_TYPE option )
{
/* Make sure that the open fails if we can't build the path */
*path = '\0';
/* Build the path to the configuration file if necessary. We assume that
we're on the correct drive */
strcpy( path, "\\cryptlib\\" );
/* If we're being asked to create the cryptlib directory and it doesn't
already exist, create it now */
if( option == BUILDPATH_CREATEPATH )
{
FS_DIR dirInfo;
if( ( dirInfo = FS_OpenDir( path ) ) != NULL )
FSCloseDir( dirInfo );
else
{
/* The directory doesn't exist, try and create it */
if( FS_MkDir( path ) < 0 )
{
*path = '\0';
return;
}
}
}
/* Add the filename to the path */
if( option == BUILDPATH_RNDSEEDFILE )
strcat( path, "randseed.dat" );
else
{
strcat( path, fileName );
strcat( path, ".p15" );
}
}
/****************************************************************************
* *
* uITRON File Stream Functions *
* *
****************************************************************************/
/* See the comment in str_file.h for uITRON file handling */
#elif defined( __ITRON__ )
/* Open/close a file stream */
int sFileOpen( STREAM *stream, const char *fileName, const int mode )
{
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;
/* 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 );
/* Try and open the file */
return( CRYPT_ERROR_OPEN );
}
int sFileClose( STREAM *stream )
{
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( stream->type == STREAM_TYPE_FILE );
/* Close the file and clear the stream structure */
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;
return( CRYPT_ERROR_READ );
}
int fileWrite( STREAM *stream, const void *buffer, const int length )
{
return( CRYPT_ERROR_WRITE );
}
/* Commit data in a file stream to backing storage */
int fileFlush( STREAM *stream )
{
return( CRYPT_ERROR_WRITE );
}
/* Change the read/write position in a file */
int fileSeek( STREAM *stream, const long position )
{
return( CRYPT_ERROR_WRITE );
}
/* Check whether a file is writeable */
BOOLEAN fileReadonly( const char *fileName )
{
return( TRUE );
}
/* 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 */
static void eraseFile( const STREAM *stream, long position, long length )
{
BYTE buffer[ BUFSIZ * 2 ];
/* Wipe everything past the current position in the file */
while( length > 0 )
{
RESOURCE_DATA msgData;
int bytesToWrite = min( length, BUFSIZ * 2 );
/* We need to make sure that we fill the buffer with random data for
each write, otherwise compressing filesystems will just compress
it to nothing */
setMessageData( &msgData, buffer, bytesToWrite );
krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );
if( fwrite( buffer, 1, bytesToWrite, stream->filePtr ) == 0 )
break; /* An error occurred while writing, exit */
length -= bytesToWrite;
}
fflush( stream->filePtr );
/* Truncate the file and if we're erasing the entire file, reset the
timestamps. This is only possible through a file handle on some
systems, on others the caller has to do it via the filename */
chsize( fileHandle, position );
if( position <= 0 )
{
struct ftime fileTime;
memset( &fileTime, 0, sizeof( struct ftime ) );
setftime( fileHandle, &fileTime );
}
}
void fileClearToEOF( const STREAM *stream )
{
long position, length;
assert( isReadPtr( stream, sizeof( STREAM ) ) );
assert( stream->type == STREAM_TYPE_FILE );
/* Wipe everything past the current position in the file */
position = ftell( stream->filePtr );
fseek( stream->filePtr, 0, SEEK_END );
length = ftell( stream->filePtr ) - position;
fseek( stream->filePtr, position, SEEK_SET );
eraseFile( stream, position, length );
}
void fileErase( const char *fileName )
{
STREAM stream;
int fileHandle, length, status;
assert( fileName != NULL );
/* Try and open the file so that we can erase it. If this fails, the
best that we can do is a straight unlink */
status = sFileOpen( &stream, fileName,
FILE_READ | FILE_WRITE | FILE_EXCLUSIVE_ACCESS );
if( cryptStatusError( status ) )
{
remove( fileName );
return;
}
/* Determine the size of the file and erase it */
fileHandle = fileno( stream.filePtr );
fseek( stream.filePtr, 0, SEEK_END );
length = ( int ) ftell( stream.filePtr );
fseek( stream.filePtr, 0, SEEK_SET );
eraseFile( stream, 0, length );
/* Truncate the file to 0 bytes if we couldn't do it in eraseFile, reset
the time stamps, and delete it */
sFileClose( &stream );
/* Under Win16 we can't really do anything without resorting to MSDOS int
21h calls, the best we can do is truncate the file using _lcreat() */
hFile = _lcreat( fileName, 0 );
if( hFile != HFILE_ERROR )
_lclose( hFile );
/* Finally, delete the file */
remove( fileName );
}
/* Build the path to a file in the cryptlib directory */
void fileBuildCryptlibPath( char *path, const char *fileName,
const BUILDPATH_OPTION_TYPE option )
{
if( option == BUILDPATH_RNDSEEDFILE )
strcpy( path, "randseed.dat" );
else
{
strcpy( path, fileName );
strcat( path, ".p15" );
}
}
/****************************************************************************
* *
* Macintosh File Stream Functions *
* *
****************************************************************************/
#elif defined( __MAC__ )
/* Convert a C to a Pascal string */
static void CStringToPString( const char *cstring, StringPtr pstring )
{
short len = min( strlen( cstring ), 255 );
memmove( pstring + 1, cstring, len );
*pstring = len;
}
/* Open/close a file stream */
int sFileOpen( STREAM *stream, const char *fileName, const int mode )
{
Str255 pFileName;
OSErr err;
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;
CStringToPString( fileName, pFileName );
err = FSMakeFSSpec( 0, 0, pFileName, &stream->fsspec );
if( err == dirNFErr || err == nsvErr )
/* Volume or parent directory not found */
return( CRYPT_ERROR_NOTFOUND );
if( err != noErr && err != fnfErr )
/* fnfErr is OK since the fsspec is still valid */
return( CRYPT_ERROR_OPEN );
if( mode & FILE_WRITE )
{
/* Try and create the file, specifying its type and creator. The
wierd string-looking constants are Mac compiler-specific and
evaluate to 32-bit unsigned type and creator IDs */
err = FSpCreate( &stream->fsspec, '????', 'CLib', smSystemScript );
if( err == wPrErr || err == vLckdErr || err == afpAccessDenied )
return( CRYPT_ERROR_PERMISSION );
if( err != noErr && err != dupFNErr && err != afpObjectTypeErr )
return( CRYPT_ERROR_OPEN );
}
err = FSpOpenDF( &stream->fsspec, mode & FILE_RW_MASK, &stream->refNum );
if( err == nsvErr || err == dirNFErr || err == fnfErr )
return( CRYPT_ERROR_NOTFOUND );
if( err == opWrErr || err == permErr || err == afpAccessDenied )
return( CRYPT_ERROR_PERMISSION );
if( err != noErr )
return( CRYPT_ERROR_OPEN );
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 */
FSClose( stream->refNum );
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 )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -