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

📄 stream.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 5 页
字号:

int sread( STREAM *stream, void *buffer, int length )
	{
#if defined( __WIN32__ )
	DWORD bytesRead;
#elif defined( __MAC__ )
	long bytesRead = length;
#endif /* __WIN32__ */
	BYTE *bufPtr = buffer;

	assert( stream != NULL && stream->type != STREAM_TYPE_NULL );
	assert( buffer != NULL );
	assert( length > 0 );

	/* If there's a problem with the stream, don't try to do anything */
	if( stream->status != CRYPT_OK )
		return( stream->status );

	/* If we ungot a char, return this first */
	if( stream->ungetChar )
		{
		*bufPtr++ = stream->lastChar;
		stream->ungetChar = FALSE;
		if( !--length )
			return( CRYPT_OK );
		}

	/* If it's a memory stream, read the data from the buffer */
	if( stream->type == STREAM_TYPE_MEMORY )
		{
		if( stream->bufSize != STREAMSIZE_UNKNOWN && \
			stream->bufPos + length > stream->bufEnd )
			{
			memset( bufPtr, 0, length );	/* Clear the output buffer */
			stream->status = CRYPT_ERROR_UNDERFLOW;
			return( CRYPT_ERROR_UNDERFLOW );
			}
		memcpy( bufPtr, stream->buffer + stream->bufPos, length );
		stream->bufPos += length;

		return( CRYPT_OK );
		}

#ifdef NET_TCP
	/* If it's a network stream, read the data from the network */
	if( stream->type == STREAM_TYPE_NETWORK )
		{
		void *bufPtr = buffer;
		int localLength, status;

		assert( stream->isServer || stream->host != NULL );

		/* Some protocols require special handling for header data and
		   handshaking, which we have to handle before reading the actual
		   data */
		status = readProtocolHeader( stream, &bufPtr, &localLength, length, 
									 stream->isServer );
		if( cryptStatusError( status ) )
			{
			stream->status = status;
			return( status );
			}

		return( readSocket( stream, bufPtr, localLength ) );
		}
#endif /* NET_TCP */

#ifndef NO_STDIO
	/* It's a file stream, read the data from the file */
#ifdef __WIN32__
	if( !ReadFile( stream->hFile, bufPtr, length, &bytesRead, NULL ) || \
		( int ) bytesRead != length )
#elif defined( __MAC__ )
	if( FSRead( stream->refNum, &bytesRead, bufPtr ) != noErr || \
		( int ) bytesRead != length )
#else
	if( fread( bufPtr, 1, length, stream->filePtr ) != ( size_t ) length )
#endif /* __WIN32__ */
		{
		stream->status = CRYPT_ERROR_READ;
		return( CRYPT_ERROR_READ );
		}
#else
	assert( NOTREACHED );
#endif /* NO_STDIO */

	return( CRYPT_OK );
	}

/* Write a block of data to a stream */

int swrite( STREAM *stream, const void *buffer, const int length )
	{
#ifdef __WIN32__
	DWORD bytesWritten;
#elif defined( __MAC__ )
	long bytesWritten = length;
#endif /* __WIN32__ */

	assert( stream != NULL );
	assert( buffer != NULL );
	assert( length > 0 );
	assert( !( stream->flags & STREAM_FLAG_READONLY ) );

	/* If there's a problem with the stream, don't try to do anything until
	   the error is cleared */
	if( stream->status != CRYPT_OK )
		return( stream->status );

	/* If it's a null stream, just record the write and return */
	if( stream->type == STREAM_TYPE_NULL )
		{
		stream->bufPos += length;
		return( CRYPT_OK );
		}

	/* If it's a memory stream, deposit the data in the buffer */
	if( stream->type == STREAM_TYPE_MEMORY )
		{
		if( stream->bufSize != STREAMSIZE_UNKNOWN && \
			stream->bufPos + length > stream->bufSize )
			{
#ifdef NO_STDIO
			/* If it's a non-sensitive pseudo-I/O stream, expand the buffer */
			if( stream->isIOStream && !stream->isSensitive )
				{
				const int status = expandBuffer( stream, length );
				if( cryptStatusError( status ) )
					return( status );
				}
			else
#endif /* NO_STDIO */
				{
				stream->status = CRYPT_ERROR_OVERFLOW;
				return( CRYPT_ERROR_OVERFLOW );
				}
			}
		memcpy( stream->buffer + stream->bufPos, buffer, length );
		stream->bufPos += length;
		if( stream->bufEnd < stream->bufPos )
			/* Move up the end-of-data pointer if necessary */
			stream->bufEnd = stream->bufPos;
		stream->flags |= STREAM_FLAG_DIRTY;

		return( CRYPT_OK );
		}

#ifdef NET_TCP
	/* If it's a network stream, write the data to the network */
	if( stream->type == STREAM_TYPE_NETWORK )
		{
		int status;

		assert( stream->isServer || stream->host != NULL );

		/* If it's a stateless protocol, connect to the remote server */
		if( stream->protocol == STREAM_PROTOCOL_HTTP_TRANSACTION )
			{
			char headerBuffer[ MAX_URL_SIZE + CRYPT_MAX_TEXTSIZE + 128 ];
			int headerPos;

			assert( stream->netSocket == CRYPT_ERROR );
			assert( stream->protocolState == STREAM_PROTOCOLSTATE_NONE );
			assert( strlen( stream->contentType ) );

			/* Open the connection to the remote host */
			status = connectStream( stream );
			if( cryptStatusError( status ) )
				return( status );

			/* Send the HTTP POST header */
			strcpy( headerBuffer, "POST " );
			strcat( headerBuffer, stream->path );
			strcat( headerBuffer, " HTTP/1.0\r\nContent-Type: " );
			strcat( headerBuffer, stream->contentType );
			strcat( headerBuffer, "\r\nContent-Transfer-Encoding: Binary\r\n"
					"Content-Length: " );
			headerPos = strlen( headerBuffer );
			sprintf( headerBuffer + headerPos, "%d\r\n"
					 "Cache-Control: no-cache\r\n\r\n", length );
			status = writeSocket( stream, headerBuffer, 
								  strlen( headerBuffer ) );
			if( cryptStatusError( status ) )
				{
				stream->status = status;
				return( status );
				}
			stream->protocolState = STREAM_PROTOCOLSTATE_FETCHSENT;
			}

		/* If it's an HTTP write, send the out-of-band header data to the 
		   client */
		if( stream->protocol == STREAM_PROTOCOL_HTTP )
			{
			char headerBuffer[ CRYPT_MAX_TEXTSIZE + 128 ];
			int headerPos;

			strcpy( headerBuffer, "HTTP/1.0 200 OK\r\nContent-Type: " );
			strcat( headerBuffer, stream->contentType );
			strcat( headerBuffer, "\r\nContent-Transfer-Encoding: Binary\r\n"
					"Content-Length: " );
			headerPos = strlen( headerBuffer );
			sprintf( headerBuffer + headerPos, "%d\r\n"
					 "Cache-Control: no-cache\r\n\r\n", length );
			status = writeSocket( stream, headerBuffer, 
								  strlen( headerBuffer ) );
			if( cryptStatusError( status ) )
				{
				stream->status = status;
				return( status );
				}
			}

		/* If it's a packet-based protocol, write the packet header */
		if( stream->protocol == STREAM_PROTOCOL_CMP )
			{
			BYTE headerBuffer[ 64 ];
			int headerLength, status;

			headerLength = writeCmpHeader( headerBuffer, length, 
										   stream->lastMessage );
			status = writeSocket( stream, headerBuffer, headerLength );
			if( cryptStatusError( status ) )
				{
				stream->status = status;
				return( status );
				}
			}

		/* Send the data to the server */
		status = writeSocket( stream, buffer, length );
		if( cryptStatusError( status ) )
			{
			stream->status = status;
			return( status );
			}

		return( CRYPT_OK );
		}
#endif /* NET_TCP */

#ifndef NO_STDIO
	/* It's a file stream, write the data to the file */
#if defined( __WIN32__ )
	if( !WriteFile( stream->hFile, buffer, length, &bytesWritten, NULL ) || \
		( int ) bytesWritten != length )
#elif defined( __MAC__ )
	if( FSWrite( stream->refNum, &bytesWritten, buffer ) != noErr || \
		( int ) bytesWritten != length )
#else
	if( fwrite( buffer, 1, length, stream->filePtr ) != ( size_t ) length )
#endif /* __WIN32__ */
		{
		stream->status = CRYPT_ERROR_WRITE;
		return( CRYPT_ERROR_WRITE );
		}
	stream->flags |= STREAM_FLAG_DIRTY;
#else
	assert( NOTREACHED );
#endif /* NO_STDIO */

	return( CRYPT_OK );
	}

/* Commit data in a stream to backing storage */

int sflush( STREAM *stream )
	{
#if defined( __MAC__ )
	FileParam paramBlock;
#endif /* __MAC__ */

	assert( stream != NULL && \
			( stream->type == STREAM_TYPE_MEMORY || \
			  stream->type == STREAM_TYPE_FILE ) );

	/* If there's a problem with the stream, don't try to do anything until
	   the error is cleared */
	if( stream->status != CRYPT_OK )
		return( stream->status );

	/* If there's no backing storage or the data is unchanged, there's
	   nothing to do */
#ifdef NO_STDIO
	if( !( stream->flags & STREAM_FLAG_DIRTY ) || \
		( stream->type == STREAM_TYPE_MEMORY && !stream->isIOStream ) )
#else
	if( !( stream->flags & STREAM_FLAG_DIRTY ) || \
		stream->type == STREAM_TYPE_MEMORY )
#endif /* NO_STDIO */
		return( CRYPT_OK );

	/* Commit the data as required by the system */
#if defined( __WIN32__ )
	FlushFileBuffers( stream->hFile );
#elif defined( __MAC__ )
	paramBlock.ioCompletion = NULL;
	paramBlock.ioFRefNum = stream->refNum;
	PBFlushFileSync(( union ParamBlockRec* ) &paramBlock );
#elif defined( NO_STDIO )
  #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 );
  #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[ 32 ];
	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 );
	if( count != 1 )
		return( CRYPT_ERROR_WRITE );
	}
  #else
	#error Need to add mechanism to save data to backing store
  #endif /* Nonstandard I/O enviroments */
#else
	fflush( stream->filePtr );
#endif /* OS-specific data commit */
	stream->flags &= ~STREAM_FLAG_DIRTY;

	return( CRYPT_OK );
	}

/* Move to an absolute position in a stream */

int sseek( STREAM *stream, const long position )
	{
	assert( stream != NULL && \
			( stream->type == STREAM_TYPE_NULL || \
			  stream->type == STREAM_TYPE_MEMORY || \
			  stream->type == STREAM_TYPE_FILE ) );
	assert( position >= 0 );

	/* If it's a memory or null stream, move to the position in the buffer */
	if( stream->type == STREAM_TYPE_NULL )
		{
		stream->bufPos = ( int ) position;
		return( CRYPT_OK );
		}
	if( stream->type == STREAM_TYPE_MEMORY )
		{
		stream->ungetChar = FALSE;
		if( stream->bufSize != STREAMSIZE_UNKNOWN && \
			( int ) position > stream->bufSize )
			{
			stream->bufPos = stream->bufSize;
			stream->status = CRYPT_ERROR_UNDERFLOW;
			return( CRYPT_ERROR_UNDERFLOW );
			}

		/* Set the new R/W position */
		stream->bufPos = ( int ) position;
		if( stream->bufPos > stream->bufEnd )
			/* If we've moved past the end of the valid data in the buffer,
			   move the end of data pointer to match the current position.
			   This mimics the behaviour of fseek(), which allows a seek past
			   the end of the file */
			stream->bufEnd = stream->bufPos;

		return( CRYPT_OK );
		}

#ifndef NO_STDIO
	/* It's a file stream, seek to the position in the file */
#if defined( __WIN32__ )
	if( SetFilePointer( stream->hFile, position, NULL,
						FILE_BEGIN ) == 0xFFFFFFFF )
#elif defined( __MAC__ )
	if( SetFPos( stream->refNum, fsFromStart, position) != noErr )
#else
	if( fseek( stream->filePtr, position, SEEK_SET ) )
#endif /* __WIN32__ */
		return( CRYPT_ERROR_WRITE );
#else
	assert( NOTREACHED );
#endif /* NO_STDIO */

	return( CRYPT_OK );
	}

/* Determine the position in a stream */

long stell( const STREAM *stream )
	{
	long position;

	assert( stream != NULL && \
			( stream->type == STREAM_TYPE_NULL || \
			  stream->type == STREAM_TYPE_MEMORY || \
			  stream->type == STREAM_TYPE_FILE ) );

	/* If it's a memory or null stream, return the position in the buffer */
	if( stream->type == STREAM_TYPE_MEMORY || \
		stream->type == STREAM_TYPE_NULL )
		return( ( stream )->bufPos - ( stream )->ungetChar );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -