📄 stream.c
字号:
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 + -