📄 str_file.c
字号:
FILE_ATTRIBUTES | FILE_FLAGS, NULL );
if( stream->hFile != INVALID_HANDLE_VALUE && \
GetLastError() == ERROR_ALREADY_EXISTS )
{
/* There was already something there that wasn't hit by the
delete, we can't be sure that the file has the required
semantics */
CloseHandle( stream->hFile );
DeleteFile( fileName );
stream->hFile = INVALID_HANDLE_VALUE;
}
}
else
{
const int openMode = ( ( mode & FILE_RW_MASK ) == FILE_READ ) ? \
GENERIC_READ : GENERIC_READ | GENERIC_WRITE;
const int shareMode = ( mode & FILE_EXCLUSIVE_ACCESS ) ? \
0 : FILE_SHARE_READ;
stream->hFile = CreateFile( fileName, openMode, shareMode, NULL,
OPEN_EXISTING, FILE_FLAGS, NULL );
}
SetErrorMode( uErrorMode );
if( stream->hFile == INVALID_HANDLE_VALUE )
{
/* Translate the Win32 error code into an equivalent cryptlib error
code */
switch( GetLastError() )
{
case ERROR_FILE_NOT_FOUND:
case ERROR_PATH_NOT_FOUND:
status = CRYPT_ERROR_NOTFOUND;
break;
case ERROR_ACCESS_DENIED:
status = CRYPT_ERROR_PERMISSION;
break;
case ERROR_BUSY:
status = CRYPT_ERROR_TIMEOUT;
break;
default:
status = CRYPT_ERROR_OPEN;
}
}
/* Clean up */
freeACLInfo( aclInfo );
return( status );
}
int sFileClose( STREAM *stream )
{
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( stream->type == STREAM_TYPE_FILE );
/* Close the file and clear the stream structure */
CloseHandle( stream->hFile );
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 )
{
DWORD bytesRead;
if( !ReadFile( stream->hFile, buffer, length, &bytesRead, NULL ) )
return( CRYPT_ERROR_READ );
return( bytesRead );
}
int fileWrite( STREAM *stream, const void *buffer, const int length )
{
DWORD bytesWritten;
if( !WriteFile( stream->hFile, buffer, length, &bytesWritten, NULL ) || \
( int ) bytesWritten != length )
return( CRYPT_ERROR_WRITE );
return( CRYPT_OK );
}
/* Commit data in a file stream to backing storage */
int fileFlush( STREAM *stream )
{
FlushFileBuffers( stream->hFile );
return( CRYPT_OK );
}
/* Change the read/write position in a file */
int fileSeek( STREAM *stream, const long position )
{
if( SetFilePointer( stream->hFile, position, NULL,
FILE_BEGIN ) == 0xFFFFFFFF )
return( CRYPT_ERROR_WRITE );
return( CRYPT_OK );
}
/* Check whether a file is writeable */
BOOLEAN fileReadonly( const char *fileName )
{
HANDLE hFile;
assert( fileName != NULL );
/* The only way to tell whether a file is writeable is to try to open it
for writing. An access()-based check is pointless because it just
calls GetFileAttributes() and checks for the read-only bit being set.
Even if we wanted to check for this basic level of access, it
wouldn't work because writes can still be blocked if it's a read-only
file system or a network share */
hFile = CreateFile( fileName, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL );
if( hFile == INVALID_HANDLE_VALUE )
/* Translate the Win32 error code into an equivalent cryptlib error
code */
return( ( GetLastError() == ERROR_ACCESS_DENIED ) ? TRUE : FALSE );
CloseHandle( hFile );
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 */
static void eraseFile( const STREAM *stream, long position, long length )
{
/* Wipe the file */
while( length > 0 )
{
RESOURCE_DATA msgData;
BYTE buffer[ 1024 ];
DWORD bytesWritten;
int bytesToWrite = min( length, 1024 );
/* 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 );
WriteFile( stream->hFile, buffer, bytesToWrite, &bytesWritten, NULL );
length -= bytesToWrite;
}
/* Truncate the file and if we're erasing the entire file, reset the
timestamps. The delete just marks the file as deleted rather than
actually deleting it, but there's not much information that can be
recovered without a magnetic force microscope. The call to
FlushFileBuffers() ensures that the changed data gets committed
before the delete call comes along. If we didn't do this then the OS
would drop all changes once DeleteFile() was called, leaving the
original more or less intact on disk */
SetFilePointer( stream->hFile, position, NULL, FILE_BEGIN );
SetEndOfFile( stream->hFile );
if( position <= 0 )
SetFileTime( stream->hFile, 0, 0, 0 );
FlushFileBuffers( stream->hFile );
}
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 */
if( ( position = SetFilePointer( stream->hFile, 0, NULL,
FILE_CURRENT ) ) == 0xFFFFFFFF )
return;
length = GetFileSize( stream->hFile, NULL ) - position;
if( length <= 0 )
return; /* Nothing to do, exit */
eraseFile( stream, position, length );
}
void fileErase( const char *fileName )
{
STREAM stream;
int 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 ) )
{
DeleteFile( fileName );
return;
}
eraseFile( &stream, 0, GetFileSize( stream.hFile, NULL ) );
sFileClose( &stream );
DeleteFile( fileName );
}
/* Build the path to a file in the cryptlib directory */
void fileBuildCryptlibPath( char *path, const char *fileName,
const BOOLEAN createPath )
{
typedef HRESULT ( WINAPI *SHGETFOLDERPATH )( HWND hwndOwner,
int nFolder, HANDLE hToken,
DWORD dwFlags, LPTSTR lpszPath );
SHGETFOLDERPATH pSHGetFolderPath;
OSVERSIONINFO osvi = { sizeof( OSVERSIONINFO ) };
HINSTANCE hShell32;
BOOLEAN loadedShell = FALSE, gotPath = FALSE;
/* Make sure that the open fails if we can't build the path */
*path = '\0';
#if !( defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x500 ) )
/* Build the path to the configuration file if necessary */
if( ( hShell32 = GetModuleHandle( "Shell32.dll" ) ) == NULL )
{
hShell32 = LoadLibrary( "Shell32.dll" );
loadedShell = TRUE;
}
GetVersionEx( &osvi );
if( osvi.dwMajorVersion <= 4 )
{
HINSTANCE hComCtl32, hSHFolder;
BOOLEAN loadedComCtl = FALSE;
/* Try and find the location of the closest thing that Windows has
to a home directory. This is a bit of a problem function in that
both the function name and parameters have changed over time, and
it's only included in pre-Win2K versions of the OS via a kludge
DLL that takes the call and redirects it to the appropriate
function anderswhere. Under certain (very unusual) circumstances
this kludge can fail if shell32.dll and comctl32.dll aren't
mapped into the process' address space yet, so we have to check
for the presence of these DLLs in memory as well as for the
successful load of the kludge DLL */
if( ( hComCtl32 = GetModuleHandle( "ComCtl32.dll" ) ) == NULL )
{
hComCtl32 = LoadLibrary( "ComCtl32.dll" );
loadedComCtl = TRUE;
}
if( ( hSHFolder = LoadLibrary( "SHFolder.dll" ) ) != NULL )
{
pSHGetFolderPath = ( SHGETFOLDERPATH ) \
GetProcAddress( hSHFolder, "SHGetFolderPathA" );
if( pSHGetFolderPath != NULL && \
pSHGetFolderPath( NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE,
NULL, SHGFP_TYPE_CURRENT, path ) == S_OK )
gotPath = TRUE;
FreeLibrary( hSHFolder );
}
if( loadedComCtl )
FreeLibrary( hComCtl32 );
}
else
{
/* Try and find the location of the closest thing that Windows has
to a home directory */
pSHGetFolderPath = ( SHGETFOLDERPATH ) \
GetProcAddress( hShell32, "SHGetFolderPathA" );
if( pSHGetFolderPath != NULL && \
pSHGetFolderPath( NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE,
NULL, SHGFP_TYPE_CURRENT, path ) == S_OK )
gotPath = TRUE;
}
if( loadedShell )
FreeLibrary( hShell32 );
#endif /* Old Borland compiler */
if( !gotPath )
GetWindowsDirectory( path, _MAX_PATH - 32 );
strcat( path, "\\cryptlib" );
/* If we're being asked to create the cryptlib directory and it doesn't
already exist, create it now */
if( createPath && GetFileAttributes( path ) == 0xFFFFFFFFUL )
{
void *aclInfo = NULL;
BOOLEAN retVal = TRUE;
if( !isWin95 && \
( aclInfo = initACLInfo( FILE_ALL_ACCESS ) ) == NULL )
retVal = FALSE;
else
retVal = CreateDirectory( path, getACLInfo( aclInfo ) );
freeACLInfo( aclInfo );
if( !retVal )
{
*path = '\0';
return;
}
}
/* Add the filename to the path */
strcat( path, "\\" );
strcat( path, fileName );
strcat( path, ".p15" );
}
/****************************************************************************
* *
* Unix/BeOS File Stream Functions *
* *
****************************************************************************/
#elif defined( __UNIX__ ) || defined( __BEOS__ )
/* Open/close a file stream */
#ifdef DDNAME_IO
/* DDNAME I/O can be used under MVS. Low-level POSIX I/O APIs can't be
used at this level, only stream I/O functions can be used. For
sFileOpen:
- File permissions are controlled by RACF (or SAF compatable product)
and should not be set by the program.
- No locking mechanism is implemented */
#define MODE_READ "rb,byteseek"
#define MODE_WRITE "wb,byteseek,recfm=*"
#define MODE_READWRITE "rb+,byteseek,recfm=*"
int sFileOpen( STREAM *stream, const char *fileName, const int mode )
{
#pragma convlit( suspend )
static const char *modes[] = { MODE_READ, MODE_READ,
MODE_WRITE, MODE_READWRITE };
#pragma convlit( resume )
const char *openMode;
char fileNameBuffer[ MAX_PATH_LENGTH ];
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 ];
/* Try and open the file */
fileName = bufferToEbcdic( fileNameBuffer, fileName );
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. An errno value
of ENOENT results from a ddname not found, and 67 (no mnemonic
name defined by IBM for DYNALLOC return codes) is member not
found, and 49 is data set not found */
return( ( errno == ENOENT || errno == 67 || errno == 49 ) ? \
CRYPT_ERROR_NOTFOUND : CRYPT_ERROR_OPEN );
return( CRYPT_OK );
}
#else
int sFileOpen( STREAM *stream, const char *fileName, const int mode )
{
#if defined( EBCDIC_CHARS )
#pragma convlit( suspend )
#endif /* EBCDIC_CHARS */
static const int modes[] = { O_RDONLY, O_RDONLY, O_WRONLY, O_RDWR };
#if defined( EBCDIC_CHARS )
#pragma convlit( resume )
#endif /* EBCDIC_CHARS */
int openMode = modes[ mode & FILE_RW_MASK ];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -