aboutsummaryrefslogtreecommitdiffstats
path: root/util/iobuf.c
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>1998-10-16 16:00:17 +0000
committerWerner Koch <[email protected]>1998-10-16 16:00:17 +0000
commite81e0970f7ab6c815f3396168d47fc6ab57fdf30 (patch)
tree175aa8c360560b30cf500a91eb72b34e16bdedc4 /util/iobuf.c
parentbackup (diff)
downloadgnupg-e81e0970f7ab6c815f3396168d47fc6ab57fdf30.tar.gz
gnupg-e81e0970f7ab6c815f3396168d47fc6ab57fdf30.zip
last local commit
Diffstat (limited to '')
-rw-r--r--util/iobuf.c125
1 files changed, 114 insertions, 11 deletions
diff --git a/util/iobuf.c b/util/iobuf.c
index b7ccd1ecd..515a5f8a3 100644
--- a/util/iobuf.c
+++ b/util/iobuf.c
@@ -431,6 +431,13 @@ iobuf_close( IOBUF a )
size_t dummy_len;
int rc=0;
+ if( a->directfp ) {
+ fclose( a->directfp );
+ if( DBG_IOBUF )
+ log_debug("iobuf-close -> %p\n", a->directfp );
+ return 0;
+ }
+
for( ; a && !rc ; a = a2 ) {
a2 = a->chain;
if( a->usage == 2 && (rc=iobuf_flush(a)) )
@@ -602,6 +609,39 @@ iobuf_openrw( const char *fname )
return a;
}
+
+
+/****************
+ * You can overwrite the normal iobuf behaviour by using this function.
+ * If used, the crwated iobuf is a simple wrapper around stdio.
+ * NULL if an error occures and sets errno
+ */
+IOBUF
+iobuf_fopen( const char *fname, const char *mode )
+{
+ IOBUF a;
+ FILE *fp;
+ int print_only = 0;
+
+ if( !fname || (*fname=='-' && !fname[1]) ) {
+ fp = stdin; /* fixme: set binary mode for msdoze */
+ fname = "[stdin]";
+ print_only = 1;
+ }
+ else if( !(fp = fopen(fname, mode) ) )
+ return NULL;
+ a = iobuf_alloc(1, 8192 );
+ a->directfp = fp;
+
+ if( DBG_IOBUF )
+ log_debug("iobuf_fopen -> %p\n", a->directfp );
+
+ return a;
+}
+
+
+
+
/****************
* Register an i/o filter.
*/
@@ -614,6 +654,9 @@ iobuf_push_filter( IOBUF a,
size_t dummy_len=0;
int rc=0;
+ if( a->directfp )
+ BUG();
+
if( a->usage == 2 && (rc=iobuf_flush(a)) )
return rc;
/* make a copy of the current stream, so that
@@ -640,6 +683,7 @@ iobuf_push_filter( IOBUF a,
/* disable nlimit for the new stream */
a->ntotal = b->ntotal + b->nbytes;
a->nlimit = a->nbytes = 0;
+ a->nofast &= ~1;
/* make a link from the new stream to the original stream */
a->chain = b;
a->opaque = b->opaque;
@@ -675,6 +719,9 @@ iobuf_pop_filter( IOBUF a, int (*f)(void *opaque, int control,
size_t dummy_len=0;
int rc=0;
+ if( a->directfp )
+ BUG();
+
if( DBG_IOBUF )
log_debug("iobuf-%d.%d: pop '%s'\n", a->no, a->subno, a->desc );
if( !a->filter ) { /* this is simple */
@@ -744,6 +791,7 @@ underflow(IOBUF a)
assert( a->d.start == a->d.len );
if( a->usage == 3 )
return -1; /* EOF because a temp buffer can't do an underflow */
+
if( a->filter_eof ) {
if( DBG_IOBUF )
log_debug("iobuf-%d.%d: filter eof\n", a->no, a->subno );
@@ -755,6 +803,22 @@ underflow(IOBUF a)
return -1;
}
+ if( a->directfp ) {
+ FILE *fp = a->directfp;
+
+ len = fread( a->d.buf, 1, a->d.size, fp);
+ if( len < a->d.size ) {
+ if( ferror(fp) )
+ a->error = 1;
+ else if( feof( fp ) )
+ a->filter_eof = 1;
+ }
+ a->d.len = len;
+ a->d.start = 0;
+ return len? a->d.buf[a->d.start++] : -1;
+ }
+
+
if( a->filter ) {
len = a->d.size;
rc = a->filter( a->filter_ov, IOBUFCTRL_UNDERFLOW, a->chain,
@@ -790,6 +854,9 @@ underflow(IOBUF a)
void
iobuf_clear_eof(IOBUF a)
{
+ if( a->directfp )
+ return;
+
assert(a->usage == 1);
if( a->filter )
@@ -806,6 +873,9 @@ iobuf_flush(IOBUF a)
size_t len;
int rc;
+ if( a->directfp )
+ return 0;
+
/*log_debug("iobuf-%d.%d: flush\n", a->no, a->subno );*/
if( a->usage == 3 )
log_bug("temp buffer too short\n");
@@ -842,6 +912,7 @@ iobuf_readbyte(IOBUF a)
return a->unget.buf[a->unget.start++];
m_free(a->unget.buf);
a->unget.buf = NULL;
+ a->nofast &= ~2;
}
if( a->nlimit && a->nbytes >= a->nlimit )
@@ -924,6 +995,10 @@ iobuf_peek(IOBUF a, byte *buf, unsigned buflen )
int
iobuf_writebyte(IOBUF a, unsigned c)
{
+
+ if( a->directfp )
+ BUG();
+
if( a->d.len == a->d.size )
if( iobuf_flush(a) )
return -1;
@@ -937,6 +1012,10 @@ iobuf_writebyte(IOBUF a, unsigned c)
int
iobuf_write(IOBUF a, byte *buf, unsigned buflen )
{
+
+ if( a->directfp )
+ BUG();
+
do {
for( ; buflen && a->d.len < a->d.size; buflen--, buf++ )
a->d.buf[a->d.len++] = *buf;
@@ -996,9 +1075,11 @@ iobuf_unget_and_close_temp( IOBUF a, IOBUF temp )
/* not yet cleaned up; do it now */
m_free(a->unget.buf);
a->unget.buf = NULL;
+ a->nofast &= ~2;
}
a->unget.size = temp->d.len;
a->unget.buf = m_alloc( a->unget.size );
+ a->nofast |= 2;
a->unget.len = temp->d.len;
memcpy( a->unget.buf, temp->d.buf, a->unget.len );
iobuf_close(temp);
@@ -1012,6 +1093,10 @@ iobuf_unget_and_close_temp( IOBUF a, IOBUF temp )
void
iobuf_set_limit( IOBUF a, unsigned long nlimit )
{
+ if( nlimit )
+ a->nofast |= 1;
+ else
+ a->nofast &= ~1;
a->nlimit = nlimit;
a->ntotal += a->nbytes;
a->nbytes = 0;
@@ -1027,6 +1112,15 @@ iobuf_get_filelength( IOBUF a )
{
struct stat st;
+ if( a->directfp ) {
+ FILE *fp = a->directfp;
+
+ if( !fstat(fileno(fp), &st) )
+ return st.st_size;
+ log_error("fstat() failed: %s\n", strerror(errno) );
+ return 0;
+ }
+
for( ; a; a = a->chain )
if( !a->chain && a->filter == file_filter ) {
file_filter_ctx_t *b = a->filter_ov;
@@ -1061,30 +1155,39 @@ iobuf_seek( IOBUF a, ulong newpos )
{
file_filter_ctx_t *b = NULL;
- for( ; a; a = a->chain ) {
- if( !a->chain && a->filter == file_filter ) {
- b = a->filter_ov;
- break;
+ if( a->directfp ) {
+ FILE *fp = a->directfp;
+ if( fseek( fp, newpos, SEEK_SET ) ) {
+ log_error("can't seek to %lu: %s\n", newpos, strerror(errno) );
+ return -1;
}
+ clearerr(fp);
}
- if( !a )
- return -1;
-
- if( fseek( b->fp, newpos, SEEK_SET ) ) {
- log_error("can't seek to %lu: %s\n", newpos, strerror(errno) );
- return -1;
+ else {
+ for( ; a; a = a->chain ) {
+ if( !a->chain && a->filter == file_filter ) {
+ b = a->filter_ov;
+ break;
+ }
+ }
+ if( !a )
+ return -1;
+ if( fseek( b->fp, newpos, SEEK_SET ) ) {
+ log_error("can't seek to %lu: %s\n", newpos, strerror(errno) );
+ return -1;
+ }
}
a->d.len = 0; /* discard buffer */
a->d.start = 0;
a->nbytes = 0;
a->nlimit = 0;
+ a->nofast &= ~1;
a->ntotal = newpos;
a->error = 0;
/* remove filters, but the last */
while( a->chain )
iobuf_pop_filter( a, a->filter, NULL );
-
return 0;
}