📄 file.c
字号:
REQUIRES( pathMaxLen > 8 && pathMaxLen < MAX_INTLENGTH );
REQUIRES( fileNameLen > 0 && fileNameLen < MAX_INTLENGTH );
REQUIRES( ( ( option == BUILDPATH_CREATEPATH || \
option == BUILDPATH_GETPATH ) && fileName != NULL ) || \
( option == BUILDPATH_RNDSEEDFILE && fileName == NULL ) );
/* Make sure that the open fails if we can't build the path */
*path = '\0';
/* Make sure that the path buffer meets the minimum-length
requirements */
REQUIRES( pathMaxLen >= 64 );
/* Build the path to the configuration file if necessary. We assume that
we're on the correct drive */
strlcpy_s( path, pathMaxLen, "\\cryptlib\\" );
/* If we're being asked to create the cryptlib directory and it doesn't
already exist, create it now */
if( option == BUILDPATH_CREATEPATH && fjisdir( path ) == 0 )
{
/* The directory doesn't exist, try and create it */
if( fjmkdir( path ) < 0 )
return( CRYPT_ERROR_OPEN );
}
/* Add the filename to the path */
return( appendFilename( path, pathMaxLen, pathLen, fileName,
fileNameLen, option ) );
}
/****************************************************************************
* *
* uC/OS-II File Stream Functions *
* *
****************************************************************************/
#elif defined( __UCOSII__ )
/* Open/close a file stream */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int sFileOpen( INOUT STREAM *stream, IN_STRING const char *fileName,
IN_FLAGS( FILE ) 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 );
REQUIRES( mode != 0 );
/* Initialise the stream structure */
memset( stream, 0, sizeof( STREAM ) );
stream->type = STREAM_TYPE_FILE;
if( ( mode & FILE_FLAG_RW_MASK ) == FILE_FLAG_READ )
stream->flags = STREAM_FLAG_READONLY;
openMode = modes[ mode & FILE_FLAG_RW_MASK ];
/* If we're trying to write to the file, check whether we've got
permission to do so */
if( ( mode & FILE_FLAG_WRITE ) && fileReadonly( fileName ) )
return( CRYPT_ERROR_PERMISSION );
/* Try and open the file */
stream->pFile = FS_FOpen( fileName, openMode );
if( stream->pFile == NULL )
{
const FS_i16 errNo = FS_FError();
/* Return what we can in the way of an error message. Curiously
uC/FS doesn't provide an indicator for common errors like file
not found, although it does provide strange indicators like
FS_ERR_CLOSE, an error occurred while calling FS_FClose() */
return( ( errNo == FS_ERR_DISKFULL ) ? \
CRYPT_ERROR_OVEWFLOW : \
( errNo == FS_ERR_READONLY ) ? \
CRYPT_ERROR_PERMISSION : CRYPT_ERROR_OPEN );
}
return( CRYPT_OK );
}
RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int sFileClose( INOUT STREAM *stream )
{
assert( isWritePtr( stream, sizeof( STREAM ) ) );
REQUIRES( stream->type == STREAM_TYPE_FILE );
/* Close the file and clear the stream structure */
FS_FClose( stream->pFile );
zeroise( stream, sizeof( STREAM ) );
return( CRYPT_OK );
}
/* Read/write a block of data from/to a file stream */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \
int fileRead( INOUT STREAM *stream,
OUT_BUFFER( length, *bytesRead ) void *buffer,
IN_LENGTH const int length,
OUT_LENGTH_Z int *bytesRead )
{
int byteCount;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isWritePtr( buffer, length ) );
assert( isWritePtr( bytesRead, sizeof( int ) ) );
REQUIRES( stream->type == STREAM_TYPE_FILE );
REQUIRES( length > 0 && length < MAX_INTLENGTH );
/* Clear return value */
*bytesRead = 0;
if( ( byteCount = FS_Read( stream->pFile, buffer, length ) ) < 0 )
return( sSetError( stream, CRYPT_ERROR_READ ) );
*bytesRead = byteCount;
return( CRYPT_OK );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int fileWrite( INOUT STREAM *stream,
IN_BUFFER( length ) const void *buffer,
IN_LENGTH const int length )
{
int bytesWritten;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isReadPtr( buffer, length ) );
REQUIRES( stream->type == STREAM_TYPE_FILE );
REQUIRES( length > 0 && length < MAX_INTLENGTH );
if( ( bytesWritten = FS_Write( stream->pFile, buffer, length ) ) < 0 || \
bytesWritten != length )
return( sSetError( stream, CRYPT_ERROR_WRITE ) );
return( CRYPT_OK );
}
/* Commit data in a file stream to backing storage */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int fileFlush( INOUT STREAM *stream )
{
assert( isWritePtr( stream, sizeof( STREAM ) ) );
REQUIRES( stream->type == STREAM_TYPE_FILE );
/* There is an IOCTL to flush all buffers (for all files) to the backing
store, but it's no supported in all drivers and seems a bit excessive
for this case */
return( CRYPT_OK );
}
/* Change the read/write position in a file */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int fileSeek( INOUT STREAM *stream, IN_LENGTH_Z const long position )
{
assert( isWritePtr( stream, sizeof( STREAM ) ) );
REQUIRES( stream->type == STREAM_TYPE_FILE );
REQUIRES( position >= 0 && position < MAX_INTLENGTH );
if( FS_FSeek( stream->pFile, position, FS_SEEK_SET ) < 0 )
return( sSetError( stream, CRYPT_ERROR_READ ) );
return( CRYPT_OK );
}
/* Check whether a file is writeable */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
BOOLEAN fileReadonly( IN_STRING 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 )
{
assert( isReadPtr( stream, sizeof( STREAM ) ) );
REQUIRES_V( stream->type == STREAM_TYPE_FILE );
REQUIRES_V( position >= 0 && position < MAX_INTLENGTH );
REQUIRES_V( length > 0 && length < MAX_INTLENGTH );
/* Wipe everything past the current position in the file */
while( length > 0 )
{
MESSAGE_DATA msgData;
BYTE buffer[ ( BUFSIZ * 2 ) + 8 ];
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 );
}
STDC_NONNULL_ARG( ( 1 ) ) \
void fileClearToEOF( const STREAM *stream )
{
int length, position;
assert( isReadPtr( stream, sizeof( STREAM ) ) );
REQUIRES_V( 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 );
}
STDC_NONNULL_ARG( ( 1 ) ) \
void fileErase( IN_STRING 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_FLAG_READ | FILE_FLAG_WRITE | \
FILE_FLAG_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 */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \
int fileBuildCryptlibPath( OUT_BUFFER( pathMaxLen, pathLen ) char *path,
IN_LENGTH_SHORT const int pathMaxLen,
OUT_LENGTH_SHORT_Z int *pathLen,
IN_BUFFER( fileNameLen ) const char *fileName,
IN_LENGTH_SHORT const int fileNameLen,
IN_ENUM( BUILDPATH_OPTION ) \
const BUILDPATH_OPTION_TYPE option )
{
assert( isWritePtr( path, pathMaxLen ) );
assert( isWritePtr( pathLen, sizeof( int ) ) );
assert( isReadPtr( fileName, fileNameLen ) );
REQUIRES( pathMaxLen > 8 && pathMaxLen < MAX_INTLENGTH );
REQUIRES( fileNameLen > 0 && fileNameLen < MAX_INTLENGTH );
REQUIRES( ( ( option == BUILDPATH_CREATEPATH || \
option == BUILDPATH_GETPATH ) && fileName != NULL ) || \
( option == BUILDPATH_RNDSEEDFILE && fileName == NULL ) );
/* Make sure that the open fails if we can't build the path */
*path = '\0';
/* Make sure that the path buffer meets the minimum-length
requirements */
REQUIRES( pathMaxLen >= 64 );
/* Build the path to the configuration file if necessary. We assume that
we're on the correct drive */
strlcpy_s( path, pathMaxLen, "\\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 )
return( CRYPT_ERROR_OPEN );
}
}
/* Add the filename to the path */
return( appendFilename( path, pathMaxLen, pathLen, fileName,
fileNameLen, option ) );
}
/****************************************************************************
* *
* uITRON File Stream Functions *
* *
****************************************************************************/
/* See the comment in str_file.h for uITRON file handling */
#elif defined( __ITRON__ )
/* Open/close a file stream */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int sFileOpen( INOUT STREAM *stream, IN_STRING const char *fileName,
IN_FLAGS( FILE ) const int mode )
{
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( fileName != NULL );
REQUIRES( mode != 0 );
/* Initialise the stream structure */
memset( stream, 0, sizeof( STREAM ) );
stream->type = STREAM_TYPE_FILE;
if( ( mode & FILE_FLAG_RW_MASK ) == FILE_FLAG_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_FLAG_WRITE ) && fileReadonly( fileName ) )
return( CRYPT_ERROR_PERMISSION );
/* Try and open the file */
return( CRYPT_ERROR_OPEN );
}
RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int sFileClose( INOUT STREAM *stream )
{
assert( isWritePtr( stream, sizeof( STREAM ) ) );
REQUIRES( 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 */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \
int fileRead( INOUT STREAM *stream,
OUT_BUFFER( length, *bytesRead ) void *buffer,
IN_LENGTH const int length,
OUT_LENGTH_Z int *bytesRead )
{
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isWritePtr( buffer, length ) );
assert( isWritePtr( bytesRead, sizeof( int ) ) );
REQUIRES( stream->type == STREAM_TYPE_FILE );
REQUIRES( length > 0 && length < MAX_INTLENGTH );
/* Clear return value */
*bytesRead = 0;
return( sSetError( stream, CRYPT_ERROR_READ ) );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int fileWrite( INOUT STREAM *stream,
IN_BUFFER( length ) const void *buffer,
IN_LENGTH const int length )
{
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isReadPtr( buffer, length ) );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -