/** * cdk_stream_mmap: * @s: the stream * @ret_buf: the buffer to store the content * @ret_count: length of the buffer * * Map the data of the given stream into a memory section. @ret_count * contains the length of the buffer. **/ cdk_error_t cdk_stream_mmap( cdk_stream_t s, byte ** ret_buf, size_t * ret_count ) { const u32 max_filesize = 16777216; u32 len, oldpos; int n, rc; char * p; if( !s || !ret_buf || !ret_count ) return CDK_Inv_Value; *ret_count = 0; *ret_buf = NULL; oldpos = cdk_stream_tell( s ); rc = cdk_stream_flush( s ); if( !rc ) rc = cdk_stream_seek( s, 0 ); if( rc ) return rc; len = cdk_stream_get_length( s ); if( !len || len > max_filesize ) return 0; p = *ret_buf = cdk_calloc( 1, len+1 ); if( !p ) return 0; *ret_count = len; n = cdk_stream_read( s, p, len ); if( n != len ) *ret_count = n; rc = cdk_stream_seek( s, oldpos ); return rc; }
/** * cdk_stream_close: Close a stream and flush all buffers. * @s: The STREAM object. * * This function work different for read or write streams. When the * stream is for reading, the filtering is already done and we can * simply close the file and all buffers. * But for the case it's a write stream, we need to apply all registered * filters now. The file is closed in the filter function and not here. **/ cdk_error_t cdk_stream_close( cdk_stream_t s ) { struct stream_filter_s * f, * f2; int rc = 0; if( !s ) return CDK_Inv_Value; _cdk_log_debug( "close stream `%s'\n", s->fname? s->fname : "[temp]" ); if( !s->flags.filtrated && !s->error ) rc = cdk_stream_flush( s ); if( s->fname || s->flags.temp ) { rc = fclose( s->fp ); s->fp = NULL; if( rc ) rc = CDK_File_Error; } f = s->filters; while( f ) { f2 = f->next; if( f->fnct ) f->fnct( f->opaque, STREAMCTL_FREE, NULL, NULL ); cdk_free( f ); f = f2; } if( s->fname ) { cdk_free( s->fname ); s->fname = NULL; } cdk_free( s ); return rc; }
cdk_error_t cdk_stream_mmap (cdk_stream_t inp, byte ** buf, size_t * buflen) { off_t len; /* We need to make sure all data is flushed before we retrieve the size. */ cdk_stream_flush (inp); len = cdk_stream_get_length (inp); return cdk_stream_mmap_part (inp, 0, len, buf, buflen); }
/** * cdk_stream_close: Close a stream and flush all buffers. * @s: The STREAM object. * * This function work different for read or write streams. When the * stream is for reading, the filtering is already done and we can * simply close the file and all buffers. * But for the case it's a write stream, we need to apply all registered * filters now. The file is closed in the filter function and not here. **/ cdk_error_t cdk_stream_close (cdk_stream_t s) { struct stream_filter_s *f, *f2; cdk_error_t rc; if (!s) { gnutls_assert (); return CDK_Inv_Value; } _cdk_log_debug ("close stream ref=%d `%s'\n", s->fp_ref, s->fname ? s->fname : "[temp]"); /* In the user callback mode, we call the release cb if possible and just free the stream. */ if (s->cbs_hd) { if (s->cbs.release) rc = s->cbs.release (s->cbs_hd); else rc = 0; cdk_free (s); gnutls_assert (); return rc; } rc = 0; if (!s->flags.filtrated && !s->error) rc = cdk_stream_flush (s); if (!s->fp_ref && (s->fname || s->flags.temp)) { int err; _cdk_log_debug ("close stream fd=%d\n", fileno (s->fp)); err = fclose (s->fp); s->fp = NULL; if (err) rc = CDK_File_Error; } /* Iterate over the filter list and use the cleanup flag to free the allocated internal structures. */ f = s->filters; while (f) { f2 = f->next; if (f->fnct) f->fnct (f->opaque, STREAMCTL_FREE, NULL, NULL); cdk_free (f); f = f2; } if (s->fname) { cdk_free (s->fname); s->fname = NULL; } cdk_free (s->cache.buf); s->cache.alloced = 0; cdk_free (s); gnutls_assert (); return rc; }
/** * cdk_stream_mmap_part: * @s: the stream * @off: the offset where to start * @len: how much bytes shall be mapped * @ret_buf: the buffer to store the content * @ret_buflen: length of the buffer * * Maps the data of the given stream into a memory section. @ret_count * contains the length of the buffer. **/ cdk_error_t cdk_stream_mmap_part (cdk_stream_t s, off_t off, size_t len, byte ** ret_buf, size_t * ret_buflen) { cdk_error_t rc; off_t oldpos; unsigned int n; if (!ret_buf || !ret_buflen) { gnutls_assert (); return CDK_Inv_Value; } *ret_buf = NULL; *ret_buflen = 0; if (!s) { gnutls_assert (); return CDK_Inv_Value; } /* Memory mapping is not supported on custom I/O objects. */ if (s->cbs_hd) { _cdk_log_debug ("cdk_stream_mmap_part: not supported on callbacks\n"); gnutls_assert (); return CDK_Inv_Mode; } oldpos = cdk_stream_tell (s); rc = cdk_stream_flush (s); if (rc) { gnutls_assert (); return rc; } rc = cdk_stream_seek (s, off); if (rc) { gnutls_assert (); return rc; } if (!len) len = cdk_stream_get_length (s); if (!len) { _cdk_log_debug ("cdk_stream_mmap_part: invalid file size %lu\n", len); gnutls_assert (); return s->error; } if (len > MAX_MAP_SIZE) { gnutls_assert (); return CDK_Too_Short; } *ret_buf = cdk_calloc (1, len + 1); *ret_buflen = len; n = cdk_stream_read (s, *ret_buf, len); if (n != len) *ret_buflen = n; rc = cdk_stream_seek (s, oldpos); if (rc) gnutls_assert (); return rc; }