b4b9c195e16753e39812fcb647ff408ab340cfc6
[gnupg.git] / util / iobuf.c
1 /* iobuf.c  -  file handling
2  *      Copyright (c) 1997 by Werner Koch (dd9jn)
3  *
4  * This file is part of G10.
5  *
6  * G10 is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * G10 is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <assert.h>
27 #include <sys/stat.h>
28 #include <unistd.h>
29
30 #include "memory.h"
31 #include "util.h"
32 #include "iobuf.h"
33
34 typedef struct {
35     FILE *fp;      /* open file handle */
36     char fname[1]; /* name of the file */
37 } file_filter_ctx_t ;
38
39 typedef struct {
40     int usage;
41     size_t size;
42     size_t count;
43     int eof;
44 } block_filter_ctx_t;
45
46 static int underflow(IOBUF a);
47
48 /****************
49  * Read data from a file into buf which has an allocated length of *LEN.
50  * return the number of read bytes in *LEN. OPAQUE is the FILE * of
51  * the stream. A is not used.
52  * control maybe:
53  * IOBUFCTRL_INIT: called just before the function is linked into the
54  *                 list of function. This can be used to prepare internal
55  *                 data structures of the function.
56  * IOBUFCTRL_FREE: called just before the function is removed from the
57  *                  list of functions and can be used to release internal
58  *                  data structures or close a file etc.
59  * IOBUFCTRL_UNDERFLOW: called by iobuf_underflow to fill the buffer
60  *                  with new stuff. *RET_LEN is the available size of the
61  *                  buffer, and should be set to the number of bytes
62  *                  which were put into the buffer. The function
63  *                  returns 0 to indicate success, -1 on EOF and
64  *                  G10ERR_xxxxx for other errors.
65  *
66  * IOBUFCTRL_FLUSH: called by iobuf_flush() to write out the collected stuff.
67  *                  *RET_LAN is the number of bytes in BUF.
68  *
69  */
70 static int
71 file_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
72 {
73     file_filter_ctx_t *a = opaque;
74     FILE *fp = a->fp;
75     size_t size = *ret_len;
76     size_t nbytes = 0;
77     int c, rc = 0;
78     char *p;
79
80     if( control == IOBUFCTRL_UNDERFLOW ) {
81         assert( size ); /* need a buffer */
82         for(; size; size-- ) {
83             if( (c=getc(fp)) == EOF ) {
84                 if( ferror(fp) ) {
85                     log_error("%s: read error: %s\n",
86                                         a->fname, strerror(errno));
87                     rc = G10ERR_READ_FILE;
88                 }
89                 else if( !nbytes )
90                     rc = -1; /* okay: we can return EOF now. */
91                 break;
92             }
93             buf[nbytes++] = c & 0xff;
94         }
95         *ret_len = nbytes;
96     }
97     else if( control == IOBUFCTRL_FLUSH ) {
98         for(p=buf; nbytes < size; nbytes++, p++ ) {
99             if( putc(*p, fp) == EOF ) {
100                 log_error("%s: write error: %s\n",
101                                     a->fname, strerror(errno));
102                 rc = G10ERR_WRITE_FILE;
103                 break;
104             }
105         }
106         *ret_len = nbytes;
107     }
108     else if( control == IOBUFCTRL_INIT ) {
109     }
110     else if( control == IOBUFCTRL_DESC ) {
111         *(char**)buf = "file_filter";
112     }
113     else if( control == IOBUFCTRL_FREE ) {
114         if( fp != stdin && fp != stdout )
115             fclose(fp);
116         fp = NULL;
117         m_free(a); /* we can free our context now */
118     }
119
120     return rc;
121 }
122
123
124 /****************
125  * This is used to implement the block write mode.
126  * Block reading is done on a byte by byte basis in readbyte(),
127  * without a filter
128  */
129 static int
130 block_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
131 {
132     block_filter_ctx_t *a = opaque;
133     size_t size = *ret_len;
134     int c, rc = 0;
135     char *p;
136
137     if( control == IOBUFCTRL_UNDERFLOW ) {
138         size_t n=0;
139
140         p = buf;
141         assert( size ); /* need a buffer */
142         if( a->eof ) /* don't read any further */
143             rc = -1;
144         while( !rc && size ) {
145             if( !a->size ) { /* get the length bytes */
146                 c = iobuf_get(chain);
147                 a->size = c << 8;
148                 c = iobuf_get(chain);
149                 a->size |= c;
150                 if( c == -1 ) {
151                     log_error("block_filter: error reading length info\n");
152                     rc = G10ERR_READ_FILE;
153                 }
154                 if( !a->size ) {
155                     a->eof = 1;
156                     if( !n )
157                         rc = -1;
158                     break;
159                 }
160             }
161
162             for(; !rc && size && a->size; size--, a->size-- ) {
163                 if( (c=iobuf_get(chain)) == -1 ) {
164                     log_error("block_filter %p: read error (size=%lu,a->size=%lu)\n",
165                                 a,  (ulong)size, (ulong)a->size);
166                     rc = G10ERR_READ_FILE;
167                 }
168                 else {
169                     *p++ = c;
170                     n++;
171                 }
172             }
173         }
174         *ret_len = n;
175     }
176     else if( control == IOBUFCTRL_FLUSH ) {
177         size_t avail, n;
178
179         for(p=buf; !rc && size; ) {
180             n = size;
181             avail = a->size - a->count;
182             if( !avail ) {
183                 if( n > a->size ) {
184                     iobuf_put( chain, (a->size >> 8) & 0xff );
185                     iobuf_put( chain, a->size & 0xff );
186                     avail = a->size;
187                     a->count = 0;
188                 }
189                 else {
190                     iobuf_put( chain, (n >> 8) & 0xff );
191                     iobuf_put( chain, n & 0xff );
192                     avail = n;
193                     a->count = a->size - n;
194                 }
195             }
196             if( n > avail )
197                 n = avail;
198             if( iobuf_write(chain, p, n ) )
199                 rc = G10ERR_WRITE_FILE;
200             a->count += n;
201             p += n;
202             size -= n;
203         }
204     }
205     else if( control == IOBUFCTRL_INIT ) {
206         if( DBG_IOBUF )
207             log_debug("init block_filter %p\n", a );
208         if( a->usage == 1 )
209             a->count = a->size = 0;
210         else
211             a->count = a->size; /* force first length bytes */
212         a->eof = 0;
213     }
214     else if( control == IOBUFCTRL_DESC ) {
215         *(char**)buf = "block_filter";
216     }
217     else if( control == IOBUFCTRL_FREE ) {
218         if( a->usage == 2 ) { /* write the end markers */
219             iobuf_writebyte(chain, 0);
220             iobuf_writebyte(chain, 0);
221         }
222         else if( a->size ) {
223             log_error("block_filter: pending bytes!\n");
224         }
225         if( DBG_IOBUF )
226             log_debug("free block_filter %p\n", a );
227         m_free(a); /* we can free our context now */
228     }
229
230     return rc;
231 }
232
233
234
235 /****************
236  * Allocate a new io buffer, with no function assigned.
237  * Usage is the desired usage: 1 for input, 2 for output, 3 for temp buffer
238  * BUFSIZE is a suggested buffer size.
239  */
240 IOBUF
241 iobuf_alloc(int usage, size_t bufsize)
242 {
243     IOBUF a;
244     static int number=0;
245
246     a = m_alloc_clear(sizeof *a);
247     a->usage = usage;
248     a->d.buf = m_alloc( bufsize );
249     a->d.size = bufsize;
250     a->no = ++number;
251     a->subno = 0;
252     a->opaque = NULL;
253     return a;
254 }
255
256
257 int
258 iobuf_close( IOBUF a )
259 {
260     IOBUF a2;
261     size_t dummy_len;
262     int rc=0;
263
264     for( ; a; a = a2 ) {
265         a2 = a->chain;
266         if( a->usage == 2 && (rc=iobuf_flush(a)) )
267             log_error("iobuf_flush failed on close: %s\n", g10_errstr(rc));
268
269         if( DBG_IOBUF )
270             log_debug("iobuf-%d.%d: close '%s'\n", a->no, a->subno, a->desc );
271         if( a->filter && (rc = a->filter(a->filter_ov, IOBUFCTRL_FREE,
272                                          a->chain, NULL, &dummy_len)) )
273             log_error("IOBUFCTRL_FREE failed on close: %s\n", g10_errstr(rc) );
274         m_free(a->d.buf);
275         m_free(a);
276     }
277     return rc;
278 }
279
280 int
281 iobuf_cancel( IOBUF a )
282 {
283     const char *s;
284
285     if( a && a->usage == 2 ) {
286         s = iobuf_get_fname(a);
287         if( s && *s )
288             remove(s);  /* remove the file. Fixme: this will fail for MSDOZE*/
289     }                   /* because the file is still open */
290     return iobuf_close(a);
291 }
292
293
294 /****************
295  * create a temporary iobuf, which can be used to collect stuff
296  * in an iobuf and later be written by iobuf_write_temp() to another
297  * iobuf.
298  */
299 IOBUF
300 iobuf_temp()
301 {
302     IOBUF a;
303
304     a = iobuf_alloc(3, 8192 );
305
306     return a;
307 }
308
309
310 /****************
311  * Create a head iobuf for reading from a file
312  * returns: NULL if an error occures and sets errno
313  */
314 IOBUF
315 iobuf_open( const char *fname )
316 {
317     IOBUF a;
318     FILE *fp;
319     file_filter_ctx_t *fcx;
320     size_t len;
321
322     if( !fname ) {
323         fp = stdin; /* fixme: set binary mode for msdoze */
324         fname = "[stdin]";
325     }
326     else if( !(fp = fopen(fname, "rb")) )
327         return NULL;
328     a = iobuf_alloc(1, 8192 );
329     fcx = m_alloc( sizeof *fcx + strlen(fname) );
330     fcx->fp = fp;
331     strcpy(fcx->fname, fname );
332     a->filter = file_filter;
333     a->filter_ov = fcx;
334     file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
335     file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
336     if( DBG_IOBUF )
337         log_debug("iobuf-%d.%d: open '%s'\n", a->no, a->subno, fname );
338
339     return a;
340 }
341
342 /****************
343  * create a iobuf for writing to a file; the file will be created.
344  */
345 IOBUF
346 iobuf_create( const char *fname )
347 {
348     IOBUF a;
349     FILE *fp;
350     file_filter_ctx_t *fcx;
351     size_t len;
352
353     if( !fname ) {
354         fp = stdout;
355         fname = "[stdout]";
356     }
357     else if( !(fp = fopen(fname, "wb")) )
358         return NULL;
359     a = iobuf_alloc(2, 8192 );
360     fcx = m_alloc( sizeof *fcx + strlen(fname) );
361     fcx->fp = fp;
362     strcpy(fcx->fname, fname );
363     a->filter = file_filter;
364     a->filter_ov = fcx;
365     file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
366     file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
367     if( DBG_IOBUF )
368         log_debug("iobuf-%d.%d: create '%s'\n", a->no, a->subno, a->desc );
369
370     return a;
371 }
372
373 /****************
374  * append to a iobuf if the file does not exits; create it.
375  * cannont be used for stdout.
376  */
377 IOBUF
378 iobuf_append( const char *fname )
379 {
380     IOBUF a;
381     FILE *fp;
382     file_filter_ctx_t *fcx;
383     size_t len;
384
385     if( !fname )
386         return NULL;
387     else if( !(fp = fopen(fname, "ab")) )
388         return NULL;
389     a = iobuf_alloc(2, 8192 );
390     fcx = m_alloc( sizeof *fcx + strlen(fname) );
391     fcx->fp = fp;
392     strcpy(fcx->fname, fname );
393     a->filter = file_filter;
394     a->filter_ov = fcx;
395     file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
396     file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
397     if( DBG_IOBUF )
398         log_debug("iobuf-%d.%d: append '%s'\n", a->no, a->subno, a->desc );
399
400     return a;
401 }
402
403 IOBUF
404 iobuf_openrw( const char *fname )
405 {
406     IOBUF a;
407     FILE *fp;
408     file_filter_ctx_t *fcx;
409     size_t len;
410
411     if( !fname )
412         return NULL;
413     else if( !(fp = fopen(fname, "r+b")) )
414         return NULL;
415     a = iobuf_alloc(2, 8192 );
416     fcx = m_alloc( sizeof *fcx + strlen(fname) );
417     fcx->fp = fp;
418     strcpy(fcx->fname, fname );
419     a->filter = file_filter;
420     a->filter_ov = fcx;
421     file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
422     file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
423     if( DBG_IOBUF )
424         log_debug("iobuf-%d.%d: openrw '%s'\n", a->no, a->subno, a->desc );
425
426     return a;
427 }
428
429 /****************
430  * Register an i/o filter.
431  */
432 int
433 iobuf_push_filter( IOBUF a,
434                    int (*f)(void *opaque, int control,
435                    IOBUF chain, byte *buf, size_t *len), void *ov )
436 {
437     IOBUF b;
438     size_t dummy_len=0;
439     int rc=0;
440
441     if( a->usage == 2 && (rc=iobuf_flush(a)) )
442         return rc;
443     /* make a copy of the current stream, so that
444      * A is the new stream and B the original one.
445      * The contents of the buffers are transferred to the
446      * new stream.
447      */
448     b = m_alloc(sizeof *b);
449     memcpy(b, a, sizeof *b );
450     /* remove the filter stuff from the new stream */
451     a->filter = NULL;
452     a->filter_ov = NULL;
453     if( a->usage == 2 ) { /* allocate a fresh buffer for the original stream */
454         b->d.buf = m_alloc( a->d.size );
455         b->d.len = 0;
456         b->d.start = 0;
457     }
458     else { /* allocate a fresh buffer for the new stream */
459         a->d.buf = m_alloc( a->d.size );
460         a->d.len = 0;
461         a->d.start = 0;
462     }
463     /* disable nlimit for the new stream */
464     a->ntotal = b->ntotal + b->nbytes;
465     a->nlimit = a->nbytes = 0;
466     /* make a link from the new stream to the original stream */
467     a->chain = b;
468     a->opaque = b->opaque;
469
470     /* setup the function on the new stream */
471     a->filter = f;
472     a->filter_ov = ov;
473
474     a->subno = b->subno + 1;
475     f( ov, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &dummy_len );
476
477     if( DBG_IOBUF ) {
478         log_debug("iobuf-%d.%d: push '%s'\n", a->no, a->subno, a->desc );
479         for(b=a; b; b = b->chain )
480             log_debug("\tchain: %d.%d '%s'\n", b->no, b->subno, b->desc );
481     }
482
483     /* now we can initialize the new function if we have one */
484     if( a->filter && (rc = a->filter(a->filter_ov, IOBUFCTRL_INIT, a->chain,
485                        NULL, &dummy_len)) )
486         log_error("IOBUFCTRL_INIT failed: %s\n", g10_errstr(rc) );
487     return rc;
488 }
489
490 /****************
491  * Remove an i/o filter.
492  */
493 int
494 iobuf_pop_filter( IOBUF a, int (*f)(void *opaque, int control,
495                       IOBUF chain, byte *buf, size_t *len), void *ov )
496 {
497     IOBUF b;
498     size_t dummy_len=0;
499     int rc=0;
500
501     if( DBG_IOBUF )
502         log_debug("iobuf-%d.%d: pop '%s'\n", a->no, a->subno, a->desc );
503     if( !a->filter ) { /* this is simple */
504         b = a->chain;
505         assert(b);
506         m_free(a->d.buf);
507         memcpy(a,b, sizeof *a);
508         m_free(b);
509         return 0;
510     }
511     for(b=a ; b; b = b->chain )
512         if( b->filter == f && (!ov || b->filter_ov == ov) )
513             break;
514     if( !b )
515         log_bug("iobuf_pop_filter(): filter function not found\n");
516
517     /* flush this stream if it is an output stream */
518     if( a->usage == 2 && (rc=iobuf_flush(b)) ) {
519         log_error("iobuf_flush failed in pop_filter: %s\n", g10_errstr(rc));
520         return rc;
521     }
522     /* and tell the filter to free it self */
523     if( (rc = b->filter(b->filter_ov, IOBUFCTRL_FREE, b->chain,
524                        NULL, &dummy_len)) ) {
525         log_error("IOBUFCTRL_FREE failed: %s\n", g10_errstr(rc) );
526         return rc;
527     }
528
529     /* and look how to remove it */
530     if( a == b && !b->chain )
531         log_bug("can't remove the last filter from the chain\n");
532     else if( a == b ) { /* remove the first iobuf from the chain */
533         /* everything from b is copied to a. This is save because
534          * a flush has been done on the to be removed entry
535          */
536         b = a->chain;
537         m_free(a->d.buf);
538         memcpy(a,b, sizeof *a);
539         m_free(b);
540     }
541     else if( !b->chain ) { /* remove the last iobuf from the chain */
542         log_bug("Ohh jeee, trying to a head filter\n");
543     }
544     else {  /* remove an intermediate iobuf from the chain */
545         log_bug("Ohh jeee, trying to remove an intermediate filter\n");
546     }
547
548     return rc;
549 }
550
551
552
553 /****************
554  * read underflow: read more bytes into the buffer and return
555  * the first byte or -1 on EOF.
556  */
557 static int
558 underflow(IOBUF a)
559 {
560     size_t len;
561     int rc;
562
563   /*log_debug("iobuf-%d.%d: underflow: start=%lu len=%lu\n",
564                 a->no, a->subno, (ulong)a->d.start, (ulong)a->d.len );*/
565     assert( a->d.start == a->d.len );
566     if( a->usage == 3 )
567         return -1; /* EOF because a temp buffer can't do an underflow */
568     if( a->filter_eof ) {
569         if( DBG_IOBUF )
570             log_debug("iobuf-%d.%d: filter eof\n", a->no, a->subno );
571         return -1;
572     }
573
574     if( a->filter ) {
575         len = a->d.size;
576         rc = a->filter( a->filter_ov, IOBUFCTRL_UNDERFLOW, a->chain,
577                         a->d.buf, &len );
578         if( a->usage == 1 && rc == -1 ) { /* EOF: we can remove the filter */
579             size_t dummy_len;
580
581             /* and tell the filter to free it self */
582             if( (rc = a->filter(a->filter_ov, IOBUFCTRL_FREE, a->chain,
583                                NULL, &dummy_len)) )
584                 log_error("IOBUFCTRL_FREE failed: %s\n", g10_errstr(rc) );
585             a->filter = NULL;
586             a->desc = NULL;
587             a->filter_ov = NULL;
588             a->filter_eof = 1;
589         }
590
591         if( !len )
592             return -1;
593         a->d.len = len;
594         a->d.start = 0;
595         return a->d.buf[a->d.start++];
596     }
597     else
598         return -1;  /* no filter; return EOF */
599 }
600
601
602 void
603 iobuf_clear_eof(IOBUF a)
604 {
605     assert(a->usage == 1);
606
607     if( a->filter )
608         log_info("iobuf-%d.%d: clear_eof '%s' with enabled filter\n", a->no, a->subno, a->desc );
609     if( !a->filter_eof )
610         log_info("iobuf-%d.%d: clear_eof '%s' with no EOF pending\n", a->no, a->subno, a->desc );
611     iobuf_pop_filter(a, NULL, NULL);
612 }
613
614
615 int
616 iobuf_flush(IOBUF a)
617 {
618     size_t len;
619     int rc;
620
621     /*log_debug("iobuf-%d.%d: flush\n", a->no, a->subno );*/
622     if( a->usage == 3 )
623         log_bug("temp buffer too short\n");
624     else if( a->usage != 2 )
625         log_bug("flush on non-output iobuf\n");
626     else if( !a->filter )
627         log_bug("iobuf_flush: no filter\n");
628     len = a->d.len;
629     rc = a->filter( a->filter_ov, IOBUFCTRL_FLUSH, a->chain, a->d.buf, &len );
630     if( !rc && len != a->d.len ) {
631         log_info("iobuf_flush did not write all!\n");
632         rc = G10ERR_WRITE_FILE;
633     }
634     a->d.len = 0;
635
636     return rc;
637 }
638
639
640 /****************
641  * Read a byte from the iobuf; returns -1 on EOF
642  */
643 int
644 iobuf_readbyte(IOBUF a)
645 {
646     int c;
647
648     if( a->nlimit && a->nbytes >= a->nlimit )
649         return -1; /* forced EOF */
650
651     if( a->d.start < a->d.len ) {
652         c = a->d.buf[a->d.start++];
653     }
654     else if( (c=underflow(a)) == -1 )
655         return -1; /* EOF */
656
657     a->nbytes++;
658     return c;
659 }
660
661
662 int
663 iobuf_writebyte(IOBUF a, unsigned c)
664 {
665     if( a->d.len == a->d.size )
666         if( iobuf_flush(a) )
667             return -1;
668
669     assert( a->d.len < a->d.size );
670     a->d.buf[a->d.len++] = c;
671     return 0;
672 }
673
674
675 int
676 iobuf_write(IOBUF a, byte *buf, unsigned buflen )
677 {
678     for( ; buflen; buflen--, buf++ )
679         if( iobuf_writebyte(a, *buf) )
680             return -1;
681     return 0;
682 }
683
684 int
685 iobuf_writestr(IOBUF a, const char *buf )
686 {
687     for( ; *buf; buf++ )
688         if( iobuf_writebyte(a, *buf) )
689             return -1;
690     return 0;
691 }
692
693
694
695 /****************
696  * copy the contents of TEMP to A.
697  */
698 int
699 iobuf_write_temp( IOBUF a, IOBUF temp )
700 {
701     return iobuf_write(a, temp->d.buf, temp->d.len );
702 }
703
704 /****************
705  * copy the contents of the temp io stream to BUFFER.
706  */
707 size_t
708 iobuf_temp_to_buffer( IOBUF a, byte *buffer, size_t buflen )
709 {
710     size_t n = a->d.len;
711
712     if( n > buflen )
713         n = buflen;
714     memcpy( buffer, a->d.buf, n );
715     return n;
716 }
717
718
719 /****************
720  * Set a limit, how much bytes may be read from the input stream A.
721  * Setting the limit to 0 disables this feature.
722  */
723 void
724 iobuf_set_limit( IOBUF a, unsigned long nlimit )
725 {
726     a->nlimit = nlimit;
727     a->ntotal += a->nbytes;
728     a->nbytes = 0;
729 }
730
731
732
733 /****************
734  * Return the length of an open file
735  */
736 u32
737 iobuf_get_filelength( IOBUF a )
738 {
739     struct stat st;
740
741     for( ; a; a = a->chain )
742         if( !a->chain && a->filter == file_filter ) {
743             file_filter_ctx_t *b = a->filter_ov;
744             FILE *fp = b->fp;
745
746             if( !fstat(fileno(fp), &st) )
747                 return st.st_size;
748             log_error("fstat() failed: %s\n", strerror(errno) );
749             break;
750         }
751
752     return 0;
753 }
754
755 /****************
756  * Tell the file position, where the next read will take place
757  */
758 ulong
759 iobuf_tell( IOBUF a )
760 {
761     return a->ntotal + a->nbytes;
762 }
763
764
765 int
766 iobuf_seek( IOBUF a, ulong newpos )
767 {
768     file_filter_ctx_t *b = NULL;
769
770     for( ; a; a = a->chain ) {
771         if( !a->chain && a->filter == file_filter ) {
772             b = a->filter_ov;
773             break;
774         }
775     }
776     if( !a )
777         return -1;
778
779     if( fseek( b->fp, newpos, SEEK_SET ) ) {
780         log_error("can't seek to %lu: %s\n", newpos, strerror(errno) );
781         return -1;
782     }
783     a->ntotal = newpos;
784     /* FIXME: flush all buffers (and remove filters?)*/
785
786     return 0;
787 }
788
789
790
791
792
793
794 /****************
795  * Retrieve the filename
796  */
797 const char *
798 iobuf_get_fname( IOBUF a )
799 {
800     struct stat st;
801
802     for( ; a; a = a->chain )
803         if( !a->chain && a->filter == file_filter ) {
804             file_filter_ctx_t *b = a->filter_ov;
805             return b->fname;
806         }
807
808     return NULL;
809 }
810
811 /****************
812  * Start the block write mode, see rfc1991.new for details.
813  * A value of 0 for N stops this mode (flushes and writes
814  * the end marker)
815  */
816 void
817 iobuf_set_block_mode( IOBUF a, size_t n )
818 {
819     block_filter_ctx_t *ctx = m_alloc_clear( sizeof *ctx );
820
821     assert( a->usage == 1 || a->usage == 2 );
822     ctx->usage = a->usage;
823     if( !n ) {
824         iobuf_pop_filter(a, block_filter, NULL );
825     }
826     else {
827         ctx->size = n; /* only needed for usage 2 */
828         iobuf_push_filter(a, block_filter, ctx );
829     }
830 }
831
832
833 /****************
834  * checks wether the stream is in block mode
835  */
836 int
837 iobuf_in_block_mode( IOBUF a )
838 {
839     for(; a; a = a->chain )
840         if( a->filter == block_filter )
841             return 1; /* yes */
842     return 0; /* no */
843 }
844
845
846