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

📄 stream.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 3 页
字号:
		assert( NOTREACHED );
		return( CRYPT_ERROR_WRITE );
		}
	if( stream->type != STREAM_TYPE_NULL && \
		( stream->bufPos < 0 || stream->bufPos > stream->bufSize ) )
		{
		assert( NOTREACHED );
		return( sSetError( stream, CRYPT_ERROR_WRITE ) );
		}

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

	switch( stream->type )
		{
		case STREAM_TYPE_NULL:
			assert( !stream->flags );

			/* It's a null stream, just record the write and return */
			stream->bufPos++;
			if( stream->bufEnd < stream->bufPos )
				stream->bufEnd = stream->bufPos;
			return( CRYPT_OK );

		case STREAM_TYPE_MEMORY:
			assert( !( stream->flags & ~STREAM_FLAG_MASK ) );

			/* Write the data to the stream buffer */
			if( stream->bufPos >= stream->bufSize )
				{
				stream->status = CRYPT_ERROR_OVERFLOW;
				return( CRYPT_ERROR_OVERFLOW );
				}
			stream->buffer[ stream->bufPos++ ] = ch;
			if( stream->bufEnd < stream->bufPos )
				stream->bufEnd = stream->bufPos;

			return( CRYPT_OK );

		case STREAM_TYPE_FILE:
			assert( !( stream->flags & ~STREAM_FFLAG_MASK ) );

			/* Write the data to the file */
			if( stream->bufPos >= stream->bufSize )
				{
				int status;

				status = emptyStream( stream, FALSE );
				if( cryptStatusError( status ) )
					return( status );
				}
			stream->buffer[ stream->bufPos++ ] = ch;
			stream->flags |= STREAM_FFLAG_DIRTY;

			return( CRYPT_OK );
		}

	assert( NOTREACHED );
	return( CRYPT_ERROR_WRITE );	/* Get rid of compiler warning */
	}

int swrite( STREAM *stream, const void *buffer, const int length )
	{
	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( stream->type == STREAM_TYPE_NULL || \
			stream->type == STREAM_TYPE_MEMORY || \
			stream->type == STREAM_TYPE_FILE || \
			stream->type == STREAM_TYPE_NETWORK );
	assert( stream->type == STREAM_TYPE_NULL || \
			stream->type == STREAM_TYPE_NETWORK || \
			isWritePtr( stream->buffer, stream->bufSize ) );
	assert( stream->type == STREAM_TYPE_NULL || \
			stream->type == STREAM_TYPE_NETWORK || \
			( stream->bufPos >= 0 && stream->bufPos <= stream->bufSize ) );
	assert( isReadPtr( buffer, length ) );
	assert( length > 0 );
	assert( !( stream->flags & STREAM_FLAG_READONLY ) );

	/* Check that the input parameters are in order */
	if( !isWritePtr( stream, sizeof( STREAM ) ) )
		{
		assert( NOTREACHED );
		return( CRYPT_ERROR_WRITE );
		}
	if( ( stream->type != STREAM_TYPE_NULL && \
		  stream->type != STREAM_TYPE_NETWORK && \
		  ( stream->bufPos < 0 || stream->bufPos > stream->bufSize ) ) || \
		!isReadPtr( buffer, length ) )
		{
		assert( NOTREACHED );
		return( sSetError( stream, CRYPT_ERROR_WRITE ) );
		}

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

	switch( stream->type )
		{
		case STREAM_TYPE_NULL:
			assert( !stream->flags );

			/* It's a null stream, just record the write and return */
			stream->bufPos += length;
			if( stream->bufEnd < stream->bufPos )
				stream->bufEnd = stream->bufPos;
			return( CRYPT_OK );

		case STREAM_TYPE_MEMORY:
			assert( !( stream->flags & ~STREAM_FLAG_MASK ) );

			/* Write the data to the stream buffer */
			if( stream->bufPos + length > stream->bufSize )
				{
				stream->status = CRYPT_ERROR_OVERFLOW;
				return( CRYPT_ERROR_OVERFLOW );
				}
			memcpy( stream->buffer + stream->bufPos, buffer, length );
			stream->bufPos += length;
			if( stream->bufEnd < stream->bufPos )
				stream->bufEnd = stream->bufPos;

			return( CRYPT_OK );

		case STREAM_TYPE_FILE:
			{
			const BYTE *bufPtr = buffer;
			int dataLength = length;

			assert( !( stream->flags & ~STREAM_FFLAG_MASK ) );

			/* Write the data to the file */
			while( dataLength > 0 )
				{
				const int bytesToCopy = \
						min( dataLength, stream->bufSize - stream->bufPos );

				if( bytesToCopy > 0 )
					{
					memcpy( stream->buffer + stream->bufPos, bufPtr, 
							bytesToCopy );
					stream->bufPos += bytesToCopy;
					bufPtr += bytesToCopy;
					dataLength -= bytesToCopy;
					}
				if( stream->bufPos >= stream->bufSize )
					{
					int status;

					status = emptyStream( stream, FALSE );
					if( cryptStatusError( status ) )
						return( status );
					}
				}
			stream->flags |= STREAM_FFLAG_DIRTY;

			return( CRYPT_OK );
			}

#ifdef USE_TCP
		case STREAM_TYPE_NETWORK:
			{
			int status;

			assert( !( stream->flags & ~STREAM_NFLAG_MASK ) );
			assert( stream->writeFunction != NULL );
			assert( ( stream->flags & STREAM_NFLAG_ISSERVER ) || \
					stream->host != NULL || \
					stream->netSocket != CRYPT_ERROR );
			assert( stream->timeout >= 0 && stream->timeout <= 300 );

			/* Write the data to the network.  Writes are normally atomic, 
			   but when doing bulk data transfers can be restarted after
			   a timeout */
			status = stream->writeFunction( stream, buffer, length );
			if( cryptStatusError( status ) )
				return( status );
			if( status < length && \
				!( stream->flags & STREAM_FLAG_PARTIALWRITE ) )
				{
				/* If we didn't write all of the data and partial writes 
				   aren't allowed, report a write timeout */
				retExtStream( stream, CRYPT_ERROR_TIMEOUT,
							  "Write timed out with %d of %d bytes written",
							  status, length );
				}
			return( status );
			}
#endif /* USE_TCP */
		}

	assert( NOTREACHED );
	return( CRYPT_ERROR_WRITE );	/* Get rid of compiler warning */
	}

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

int sflush( STREAM *stream )
	{
	int status = CRYPT_OK, flushStatus;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( stream->type == STREAM_TYPE_FILE );
	assert( isReadPtr( stream->buffer, stream->bufSize ) );
	assert( !( stream->flags & STREAM_FLAG_READONLY ) );

	/* Check that the input parameters are in order */
	if( !isWritePtr( stream, sizeof( STREAM ) ) )
		{
		assert( NOTREACHED );
		return( CRYPT_ERROR_WRITE );
		}
	if( !isReadPtr( stream->buffer, stream->bufSize ) )
		{
		assert( NOTREACHED );
		return( sSetError( stream, CRYPT_ERROR_WRITE ) );
		}

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

	/* If the data is unchanged, there's nothing to do */
	if( !( stream->flags & STREAM_FFLAG_DIRTY ) )
		return( CRYPT_OK );

	/* If there's data still in the stream buffer, write it to disk */
	if( stream->bufPos > 0 )
		status = emptyStream( stream, TRUE );

	/* Commit the data */
	flushStatus = fileFlush( stream );
	stream->flags &= ~STREAM_FFLAG_DIRTY;

	return( cryptStatusOK( status ) ? flushStatus : status );
	}

/****************************************************************************
*																			*
*								Meta-data Functions							*
*																			*
****************************************************************************/

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

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

	/* Check that the input parameters are in order */
	if( !isWritePtr( stream, sizeof( STREAM ) ) )
		{
		assert( NOTREACHED );
		return( CRYPT_ERROR_READ );
		}
	if( position < 0 )
		{
		assert( NOTREACHED );
		return( sSetError( stream, CRYPT_ERROR_READ ) );
		}

	switch( stream->type )
		{
		case STREAM_TYPE_NULL:
			assert( !stream->flags );

			/* Move to the position in the stream buffer.  We never get 
			   called directly with an sseek on a memory stream, but end up 
			   here via a translated sSkip() call */
			stream->bufPos = ( int ) position;
			if( stream->bufEnd < stream->bufPos )
				stream->bufEnd = stream->bufPos;
			return( CRYPT_OK );

		case STREAM_TYPE_MEMORY:
			assert( !( stream->flags & ~STREAM_FLAG_MASK ) );

			/* Move to the position in the stream buffer */
			if( ( int ) position > stream->bufSize )
				{
				stream->bufPos = stream->bufSize;
				stream->status = CRYPT_ERROR_UNDERFLOW;
				return( CRYPT_ERROR_UNDERFLOW );
				}
			stream->bufPos = ( int ) position;
			if( stream->bufEnd < stream->bufPos )
				stream->bufEnd = stream->bufPos;
			return( CRYPT_OK );

		case STREAM_TYPE_FILE:
			{
			int newBufCount;

			assert( !( stream->flags & ~STREAM_FFLAG_MASK ) );

			/* If it's a currently-disconnected file stream, all that we can 
			   do is rewind the stream.  This occurs when we're doing an 
			   atomic flush of data to disk and we rewind the stream prior 
			   to writing the new/updated data.  The next buffer-connect 
			   operation will reset the stream state, so there's nothing to 
			   do at this point */
			if( stream->bufSize <= 0 )
				{
				assert( position == 0 );
				return( CRYPT_OK );
				}

			/* It's a file stream, remember the new position in the file */
			newBufCount = position / stream->bufSize;
			if( newBufCount != stream->bufCount )
				{
				/* We're not within the current buffer any more, remember 
				   that we have to explicitly update the file position on
				   the next read */
				stream->flags |= STREAM_FFLAG_POSCHANGED;

				/* If we're already positioned to read the next bufferful 
				   of data, we don't have to explicitly skip ahead to it */
				if( newBufCount == stream->bufCount + 1 ) 
					stream->flags |= STREAM_FFLAG_POSCHANGED_NOSKIP ;

				stream->bufCount = newBufCount;
				}
			stream->bufPos = position % stream->bufSize;
			return( CRYPT_OK );
			}
		}

	assert( NOTREACHED );
	return( CRYPT_ERROR_WRITE );	/* Get rid of compiler warning */
	}

/* Skip a number of bytes in a stream */

int sSkip( STREAM *stream, const long offset )
	{
	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( stream->type == STREAM_TYPE_NULL || \
			stream->type == STREAM_TYPE_MEMORY || \
			stream->type == STREAM_TYPE_FILE );
	assert( offset > 0 );

	/* Check that the input parameters are in order */
	if( !isWritePtr( stream, sizeof( STREAM ) ) )
		{
		assert( NOTREACHED );
		return( CRYPT_ERROR_READ );
		}
	if( offset <= 0 )
		{
		assert( NOTREACHED );
		return( sSetError( stream, CRYPT_ERROR_READ ) );
		}

	return( sseek( stream, stream->bufPos + offset ) );
	}

/* Peek at the next data value in a stream */

int sPeek( STREAM *stream )
	{
	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( stream->type == STREAM_TYPE_MEMORY || \
			stream->type == STREAM_TYPE_FILE );
	assert( stream->bufPos >= 0 && stream->bufPos <= stream->bufEnd );
	assert( isReadPtr( stream->buffer, stream->bufSize ) );

	/* Check that the input parameters are in order */
	if( !isWritePtr( stream, sizeof( STREAM ) ) )
		{
		assert( NOTREACHED );
		return( CRYPT_ERROR_READ );
		}
	if( stream->bufPos < 0 || stream->bufPos > stream->bufEnd || \
		!isReadPtr( stream->buffer, stream->bufSize ) )

⌨️ 快捷键说明

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