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

📄 str_file.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 5 页
字号:
									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 + -