Fix possible NULL argument to printf
[gnupg.git] / util / iobuf.c
1 /* iobuf.c  -  file handling
2  * Copyright (C) 1998, 1999, 2000, 2001, 2003,
3  *               2004, 2008 Free Software Foundation, Inc.
4  *
5  * This file is part of GnuPG.
6  *
7  * GnuPG is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * GnuPG is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <ctype.h>
27 #include <assert.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <fcntl.h> 
31 #include <unistd.h>
32 #ifdef HAVE_DOSISH_SYSTEM
33 #include <windows.h>
34 #endif
35 #ifdef __riscos__
36 #include <kernel.h>
37 #include <swis.h>
38 #endif /* __riscos__ */
39
40 #include "memory.h"
41 #include "util.h"
42 #include "dynload.h"
43 #include "iobuf.h"
44
45 /* The size of the internal buffers. 
46    NOTE: If you change this value you MUST also adjust the regression
47    test "armored_key_8192" in armor.test! */
48 #define IOBUF_BUFFER_SIZE  8192
49
50
51 #undef FILE_FILTER_USES_STDIO
52
53 #ifdef HAVE_DOSISH_SYSTEM
54 #define USE_SETMODE 1
55 #endif
56
57 #ifdef FILE_FILTER_USES_STDIO
58 #define my_fileno(a)  fileno ((a))
59 #define my_fopen_ro(a,b) fopen ((a),(b))
60 #define my_fopen(a,b)    fopen ((a),(b))
61 typedef FILE *FILEP_OR_FD;
62 #define INVALID_FP    NULL
63 #define FILEP_OR_FD_FOR_STDIN  (stdin)
64 #define FILEP_OR_FD_FOR_STDOUT  (stdout)
65 typedef struct {
66      FILE *fp;     /* open file handle */
67      int keep_open;
68      int no_cache;
69      int  print_only_name; /* flags indicating that fname is not a real file*/
70      char fname[1]; /* name of the file */
71  } file_filter_ctx_t ;
72 #else
73 #define my_fileno(a)  (a)
74 #define my_fopen_ro(a,b) fd_cache_open ((a),(b)) 
75 #define my_fopen(a,b) direct_open ((a),(b)) 
76 #ifdef HAVE_DOSISH_SYSTEM
77 typedef HANDLE FILEP_OR_FD;
78 #define INVALID_FP  ((HANDLE)-1)
79 #define FILEP_OR_FD_FOR_STDIN  (GetStdHandle (STD_INPUT_HANDLE))
80 #define FILEP_OR_FD_FOR_STDOUT (GetStdHandle (STD_OUTPUT_HANDLE))
81 #undef USE_SETMODE
82 #else
83 typedef int FILEP_OR_FD;
84 #define INVALID_FP  (-1)
85 #define FILEP_OR_FD_FOR_STDIN  (0)
86 #define FILEP_OR_FD_FOR_STDOUT (1)
87 #endif
88 typedef struct {
89      FILEP_OR_FD  fp;      /* open file handle */
90      int keep_open;
91      int no_cache;
92      int eof_seen;
93      int  print_only_name; /* flags indicating that fname is not a real file*/
94      char fname[1]; /* name of the file */
95  } file_filter_ctx_t ;
96
97  struct close_cache_s { 
98     struct close_cache_s *next;
99     FILEP_OR_FD fp;
100     char fname[1];
101  };
102  typedef struct close_cache_s *CLOSE_CACHE;
103  static CLOSE_CACHE close_cache;
104 #endif
105
106 #ifdef _WIN32
107 typedef struct {
108     int sock;
109     int keep_open;
110     int no_cache;
111     int eof_seen;
112     int  print_only_name; /* flags indicating that fname is not a real file*/
113     char fname[1]; /* name of the file */
114 } sock_filter_ctx_t ;
115 #endif /*_WIN32*/
116
117 /* The first partial length header block must be of size 512
118  * to make it easier (and efficienter) we use a min. block size of 512
119  * for all chunks (but the last one) */
120 #define OP_MIN_PARTIAL_CHUNK      512
121 #define OP_MIN_PARTIAL_CHUNK_2POW 9
122
123 typedef struct {
124     int use;
125     size_t size;
126     size_t count;
127     int partial;  /* 1 = partial header, 2 in last partial packet */
128     char *buffer;    /* used for partial header */
129     size_t buflen;   /* used size of buffer */
130     int first_c;     /* of partial header (which is > 0)*/
131     int eof;
132 } block_filter_ctx_t;
133
134 static int special_names_enabled;
135
136 static int underflow(IOBUF a);
137 static int translate_file_handle ( int fd, int for_write );
138
139
140 \f
141 #ifndef FILE_FILTER_USES_STDIO
142
143 /* This is a replacement for strcmp.  Under W32 it does not
144    distinguish between backslash and slash.  */
145 static int
146 fd_cache_strcmp (const char *a, const char *b)
147 {
148 #ifdef HAVE_DOSISH_SYSTEM
149   for (; *a && *b; a++, b++)
150     {
151       if (*a != *b && !((*a == '/' && *b == '\\') 
152                         || (*a == '\\' && *b == '/')) )
153         break;
154     }
155   return *(const unsigned char *)a - *(const unsigned char *)b;
156 #else
157   return strcmp (a, b);
158 #endif
159 }
160
161 /*
162  * Invalidate (i.e. close) a cached iobuf or all iobufs if NULL is
163  * used for FNAME.
164  */
165 static void
166 fd_cache_invalidate (const char *fname)
167 {
168     CLOSE_CACHE cc;
169
170     if (!fname) {
171         if( DBG_IOBUF )
172             log_debug ("fd_cache_invalidate (all)\n");
173
174         for (cc=close_cache; cc; cc = cc->next ) {
175             if ( cc->fp != INVALID_FP ) {
176 #ifdef HAVE_DOSISH_SYSTEM
177                 CloseHandle (cc->fp);
178 #else
179                 close(cc->fp);
180 #endif
181                 cc->fp = INVALID_FP;
182             }
183         }
184         return;
185     }
186
187     if( DBG_IOBUF )
188         log_debug ("fd_cache_invalidate (%s)\n", fname);
189
190     for (cc=close_cache; cc; cc = cc->next ) {
191         if ( cc->fp != INVALID_FP && !fd_cache_strcmp (cc->fname, fname) ) {
192             if( DBG_IOBUF )
193                 log_debug ("                did (%s)\n", cc->fname);
194 #ifdef HAVE_DOSISH_SYSTEM
195             CloseHandle (cc->fp);
196 #else
197             close(cc->fp);
198 #endif
199             cc->fp = INVALID_FP;
200         }
201     }
202 }
203
204
205
206 static FILEP_OR_FD
207 direct_open (const char *fname, const char *mode)
208 {
209 #ifdef HAVE_DOSISH_SYSTEM
210     unsigned long da, cd, sm;
211     HANDLE hfile;
212
213     /* Note, that we do not handle all mode combinations */
214
215     /* According to the ReactOS source it seems that open() of the
216      * standard MSW32 crt does open the file in share mode which is
217      * something new for MS applications ;-)
218      */
219     if ( strchr (mode, '+') ) {
220         fd_cache_invalidate (fname);
221         da = GENERIC_READ|GENERIC_WRITE;
222         cd = OPEN_EXISTING;
223         sm = FILE_SHARE_READ | FILE_SHARE_WRITE;
224     }
225     else if ( strchr (mode, 'w') ) {
226         fd_cache_invalidate (fname);
227         da = GENERIC_WRITE;
228         cd = CREATE_ALWAYS;
229         sm = FILE_SHARE_WRITE;
230     }
231     else {
232         da = GENERIC_READ;
233         cd = OPEN_EXISTING;
234         sm = FILE_SHARE_READ;
235     }
236
237     hfile = CreateFile (fname, da, sm, NULL, cd, FILE_ATTRIBUTE_NORMAL, NULL);
238     return hfile;
239 #else
240     int oflag;
241     int cflag = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;
242
243     /* Note, that we do not handle all mode combinations */
244     if ( strchr (mode, '+') ) {
245         fd_cache_invalidate (fname);
246         oflag = O_RDWR;
247     }
248     else if ( strchr (mode, 'w') ) {
249         fd_cache_invalidate (fname);
250         oflag = O_WRONLY | O_CREAT | O_TRUNC;
251     }
252     else {
253         oflag = O_RDONLY;
254     }
255 #ifdef O_BINARY
256     if (strchr (mode, 'b'))
257       oflag |= O_BINARY;
258 #endif
259 #ifndef __riscos__
260     return open (fname, oflag, cflag );
261 #else
262     {
263         struct stat buf;
264         int rc = stat( fname, &buf );
265         
266         /* Don't allow iobufs on directories */
267         if( !rc && S_ISDIR(buf.st_mode) && !S_ISREG(buf.st_mode) )
268             return __set_errno( EISDIR );
269         else
270             return open( fname, oflag, cflag );
271     }
272 #endif
273 #endif
274 }
275
276
277 /*
278  * Instead of closing an FD we keep it open and cache it for later reuse 
279  * Note that this caching strategy only works if the process does not chdir.
280  */
281 static void
282 fd_cache_close (const char *fname, FILEP_OR_FD fp)
283 {
284     CLOSE_CACHE cc;
285
286     assert (fp);
287     if ( !fname || !*fname ) {
288 #ifdef HAVE_DOSISH_SYSTEM
289         CloseHandle (fp);
290 #else
291         close(fp);
292 #endif
293         if( DBG_IOBUF )
294             log_debug ("fd_cache_close (%p) real\n", (void*)fp);
295         return;
296     }
297     /* try to reuse a slot */
298     for (cc=close_cache; cc; cc = cc->next ) {
299         if ( cc->fp == INVALID_FP && !fd_cache_strcmp (cc->fname, fname) ) {
300             cc->fp = fp;
301             if( DBG_IOBUF )
302                 log_debug ("fd_cache_close (%s) used existing slot\n", fname);
303             return;
304         }
305     }
306     /* add a new one */
307     if( DBG_IOBUF )
308         log_debug ("fd_cache_close (%s) new slot created\n", fname);
309     cc = xmalloc_clear (sizeof *cc + strlen (fname));
310     strcpy (cc->fname, fname);
311     cc->fp = fp;
312     cc->next = close_cache;
313     close_cache = cc;
314 }
315
316 /*
317  * Do an direct_open on FNAME but first try to reuse one from the fd_cache
318  */
319 static FILEP_OR_FD
320 fd_cache_open (const char *fname, const char *mode)
321 {
322     CLOSE_CACHE cc;
323
324     assert (fname);
325     for (cc=close_cache; cc; cc = cc->next ) {
326         if ( cc->fp != INVALID_FP && !fd_cache_strcmp (cc->fname, fname) ) {
327             FILEP_OR_FD fp = cc->fp;
328             cc->fp = INVALID_FP;
329             if( DBG_IOBUF )
330                 log_debug ("fd_cache_open (%s) using cached fp\n", fname);
331 #ifdef HAVE_DOSISH_SYSTEM
332             if (SetFilePointer (fp, 0, NULL, FILE_BEGIN) == 0xffffffff ) {
333                 log_error ("rewind file failed on handle %p: %s\n",
334                            fp, w32_strerror (errno));
335                 fp = INVALID_FP;
336             }
337 #else
338             if ( lseek (fp, 0, SEEK_SET) == (off_t)-1 ) {
339                 log_error("can't rewind fd %d: %s\n", fp, strerror(errno) );
340                 fp = INVALID_FP;
341             }
342 #endif
343             return fp;
344         }
345     }
346     if( DBG_IOBUF )
347         log_debug ("fd_cache_open (%s) not cached\n", fname);
348     return direct_open (fname, mode);
349 }
350
351
352 #endif /*FILE_FILTER_USES_STDIO*/
353
354
355 /****************
356  * Read data from a file into buf which has an allocated length of *LEN.
357  * return the number of read bytes in *LEN. OPAQUE is the FILE * of
358  * the stream. A is not used.
359  * control may be:
360  * IOBUFCTRL_INIT: called just before the function is linked into the
361  *                 list of function. This can be used to prepare internal
362  *                 data structures of the function.
363  * IOBUFCTRL_FREE: called just before the function is removed from the
364  *                  list of functions and can be used to release internal
365  *                  data structures or close a file etc.
366  * IOBUFCTRL_UNDERFLOW: called by iobuf_underflow to fill the buffer
367  *                  with new stuff. *RET_LEN is the available size of the
368  *                  buffer, and should be set to the number of bytes
369  *                  which were put into the buffer. The function
370  *                  returns 0 to indicate success, -1 on EOF and
371  *                  G10ERR_xxxxx for other errors.
372  *
373  * IOBUFCTRL_FLUSH: called by iobuf_flush() to write out the collected stuff.
374  *                  *RET_LAN is the number of bytes in BUF.
375  *
376  * IOBUFCTRL_CANCEL: send to all filters on behalf of iobuf_cancel.  The
377  *                  filter may take appropriate action on this message.
378  */
379 static int
380 file_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
381 {
382     file_filter_ctx_t *a = opaque;
383     FILEP_OR_FD f = a->fp;
384     size_t size = *ret_len;
385     size_t nbytes = 0;
386     int rc = 0;
387
388 #ifdef FILE_FILTER_USES_STDIO
389     if( control == IOBUFCTRL_UNDERFLOW ) {
390         assert( size ); /* need a buffer */
391         if ( feof(f)) { /* On terminals you could easiely read as many EOFs as you call         */
392             rc = -1;            /* fread() or fgetc() repeatly. Every call will block until you press   */
393             *ret_len = 0;       /* CTRL-D. So we catch this case before we call fread() again.          */
394         }
395         else {
396             clearerr( f );
397             nbytes = fread( buf, 1, size, f );
398             if( feof(f) && !nbytes ) {
399                 rc = -1; /* okay: we can return EOF now. */
400             }
401             else if( ferror(f) && errno != EPIPE  ) {
402                 log_error("%s: read error: %s\n",
403                           a->fname, strerror(errno));
404                 rc = G10ERR_READ_FILE;
405             }
406             *ret_len = nbytes;
407         }
408     }
409     else if( control == IOBUFCTRL_FLUSH ) {
410         if( size ) {
411             clearerr( f );
412             nbytes = fwrite( buf, 1, size, f );
413             if( ferror(f) ) {
414                 log_error("%s: write error: %s\n", a->fname, strerror(errno));
415                 rc = G10ERR_WRITE_FILE;
416             }
417         }
418         *ret_len = nbytes;
419     }
420     else if( control == IOBUFCTRL_INIT ) {
421         a->keep_open = a->no_cache = 0;
422     }
423     else if( control == IOBUFCTRL_DESC ) {
424         *(char**)buf = "file_filter";
425     }
426     else if( control == IOBUFCTRL_FREE ) {
427         if( f != stdin && f != stdout ) {
428             if( DBG_IOBUF )
429                 log_debug("%s: close fd %d\n", a->fname, fileno(f) );
430             if (!a->keep_open)
431                 fclose(f);
432         }
433         f = NULL;
434         xfree(a); /* we can free our context now */
435     }
436 #else /* !stdio implementation */
437
438     if( control == IOBUFCTRL_UNDERFLOW ) {
439         assert( size ); /* need a buffer */
440         if ( a->eof_seen) {
441             rc = -1;            
442             *ret_len = 0;       
443         }
444         else {
445 #ifdef HAVE_DOSISH_SYSTEM
446             unsigned long nread;
447
448             nbytes = 0;
449             if ( !ReadFile ( f, buf, size, &nread, NULL ) ) {
450                 if ((int)GetLastError () != ERROR_BROKEN_PIPE) {
451                     log_error ("%s: read error: %s\n", a->fname,
452                                w32_strerror (0));
453                     rc = G10ERR_READ_FILE;
454                 }
455             }
456             else if ( !nread ) {
457                 a->eof_seen = 1;
458                 rc = -1;
459             }
460             else {
461                 nbytes = nread;
462             }
463
464 #else
465
466             int n;
467
468             nbytes = 0;
469             do {
470                 n = read ( f, buf, size );
471             } while (n == -1 && errno == EINTR );
472             if ( n == -1 ) { /* error */
473                 if (errno != EPIPE) {
474                     log_error("%s: read error: %s\n",
475                               a->fname, strerror(errno));
476                     rc = G10ERR_READ_FILE;
477                 }
478             }
479             else if ( !n ) { /* eof */
480                 a->eof_seen = 1;
481                 rc = -1;
482             }
483             else {
484                 nbytes = n;
485             }
486 #endif
487             *ret_len = nbytes;
488         }
489     }
490     else if( control == IOBUFCTRL_FLUSH ) {
491         if( size ) {
492 #ifdef HAVE_DOSISH_SYSTEM
493             byte *p = buf;
494             unsigned long n;
495
496             nbytes = size;
497             do {
498                 if (size && !WriteFile (f,  p, nbytes, &n, NULL)) {
499                     log_error ("%s: write error: %s\n", a->fname,
500                                w32_strerror (0));
501                     rc = G10ERR_WRITE_FILE;
502                     break;
503                 }
504                 p += n;
505                 nbytes -= n;
506             } while ( nbytes );
507             nbytes = p - buf;
508 #else
509             byte *p = buf;
510             int n;
511
512             nbytes = size;
513             do {
514                 do {
515                     n = write ( f, p, nbytes );
516                 } while ( n == -1 && errno == EINTR );
517                 if ( n > 0 ) {
518                     p += n;
519                     nbytes -= n;
520                 }
521             } while ( n != -1 && nbytes );
522             if( n == -1 ) {
523                 log_error("%s: write error: %s\n", a->fname, strerror(errno));
524                 rc = G10ERR_WRITE_FILE;
525             }
526             nbytes = p - buf;
527 #endif
528         }
529         *ret_len = nbytes;
530     }
531     else if ( control == IOBUFCTRL_INIT ) {
532         a->eof_seen = 0;
533         a->keep_open = 0;
534         a->no_cache = 0;
535     }
536     else if ( control == IOBUFCTRL_DESC ) {
537         *(char**)buf = "file_filter(fd)";
538     }
539     else if ( control == IOBUFCTRL_FREE ) {
540 #ifdef HAVE_DOSISH_SYSTEM
541         if ( f != FILEP_OR_FD_FOR_STDIN && f != FILEP_OR_FD_FOR_STDOUT ) {
542             if( DBG_IOBUF )
543                 log_debug("%s: close handle %p\n", a->fname, f );
544             if (!a->keep_open)
545                 fd_cache_close (a->no_cache?NULL:a->fname, f);
546         }
547 #else
548         if ( (int)f != 0 && (int)f != 1 ) {
549             if( DBG_IOBUF )
550                 log_debug("%s: close fd %d\n", a->fname, f );
551             if (!a->keep_open)
552                 fd_cache_close (a->no_cache?NULL:a->fname, f);
553         }
554         f = INVALID_FP;
555 #endif
556         xfree (a); /* we can free our context now */
557     }
558 #endif /* !stdio implementation */
559     return rc;
560 }
561
562 #ifdef _WIN32
563 /* Becuase sockets are an special object under Lose32 we have to
564  * use a special filter */
565 static int
566 sock_filter (void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
567 {
568     sock_filter_ctx_t *a = opaque;
569     size_t size = *ret_len;
570     size_t nbytes = 0;
571     int rc = 0;
572
573     if( control == IOBUFCTRL_UNDERFLOW ) {
574         assert( size ); /* need a buffer */
575         if ( a->eof_seen) {
576             rc = -1;            
577             *ret_len = 0;       
578         }
579         else {
580             int nread;
581
582             nread = recv ( a->sock, buf, size, 0 );
583             if ( nread == SOCKET_ERROR ) {
584                 int ec = (int)WSAGetLastError ();
585                 log_error("socket read error: ec=%d\n", ec);
586                 rc = G10ERR_READ_FILE;
587             }
588             else if ( !nread ) {
589                 a->eof_seen = 1;
590                 rc = -1;
591             }
592             else {
593                 nbytes = nread;
594             }
595             *ret_len = nbytes;
596         }
597     }
598     else if( control == IOBUFCTRL_FLUSH ) {
599         if( size ) {
600             byte *p = buf;
601             int n;
602
603             nbytes = size;
604             do {
605                 n = send (a->sock, p, nbytes, 0);
606                 if ( n == SOCKET_ERROR ) {
607                     int ec = (int)WSAGetLastError ();
608                     log_error("socket write error: ec=%d\n", ec);
609                     rc = G10ERR_WRITE_FILE;
610                     break;
611                 }
612                 p += n;
613                 nbytes -= n;
614             } while ( nbytes );
615             nbytes = p - buf;
616         }
617         *ret_len = nbytes;
618     }
619     else if ( control == IOBUFCTRL_INIT ) {
620         a->eof_seen = 0;
621         a->keep_open = 0;
622         a->no_cache = 0;
623     }
624     else if ( control == IOBUFCTRL_DESC ) {
625         *(char**)buf = "sock_filter";
626     }
627     else if ( control == IOBUFCTRL_FREE ) {
628         if (!a->keep_open)
629             closesocket (a->sock);
630         xfree (a); /* we can free our context now */
631     }
632     return rc;
633 }
634 #endif /*_WIN32*/
635
636 /****************
637  * This is used to implement the block write mode.
638  * Block reading is done on a byte by byte basis in readbyte(),
639  * without a filter
640  */
641 static int
642 block_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
643 {
644     block_filter_ctx_t *a = opaque;
645     size_t size = *ret_len;
646     int c, needed, rc = 0;
647     char *p;
648
649     if( control == IOBUFCTRL_UNDERFLOW ) {
650         size_t n=0;
651
652         p = buf;
653         assert( size ); /* need a buffer */
654         if( a->eof ) /* don't read any further */
655             rc = -1;
656         while( !rc && size ) {
657             if( !a->size ) { /* get the length bytes */
658                 if( a->partial == 2 ) {
659                     a->eof = 1;
660                     if( !n )
661                         rc = -1;
662                     break;
663                 }
664                 else if( a->partial ) {
665                     /* These OpenPGP introduced huffman like encoded length
666                      * bytes are really a mess :-( */
667                     if( a->first_c ) {
668                         c = a->first_c;
669                         a->first_c = 0;
670                     }
671                     else if( (c = iobuf_get(chain)) == -1 ) {
672                         log_error("block_filter: 1st length byte missing\n");
673                         rc = G10ERR_READ_FILE;
674                         break;
675                     }
676                     if( c < 192 ) {
677                         a->size = c;
678                         a->partial = 2;
679                         if( !a->size ) {
680                             a->eof = 1;
681                             if( !n )
682                                 rc = -1;
683                             break;
684                         }
685                     }
686                     else if( c < 224 ) {
687                         a->size = (c - 192) * 256;
688                         if( (c = iobuf_get(chain)) == -1 ) {
689                             log_error("block_filter: 2nd length byte missing\n");
690                             rc = G10ERR_READ_FILE;
691                             break;
692                         }
693                         a->size += c + 192;
694                         a->partial = 2;
695                         if( !a->size ) {
696                             a->eof = 1;
697                             if( !n )
698                                 rc = -1;
699                             break;
700                         }
701                     }
702                     else if( c == 255 ) {
703                         a->size  = iobuf_get(chain) << 24;
704                         a->size |= iobuf_get(chain) << 16;
705                         a->size |= iobuf_get(chain) << 8;
706                         if( (c = iobuf_get(chain)) == -1 ) {
707                             log_error("block_filter: invalid 4 byte length\n");
708                             rc = G10ERR_READ_FILE;
709                             break;
710                         }
711                         a->size |= c;
712                         a->partial = 2;
713                         if( !a->size ) {
714                             a->eof = 1;
715                             if( !n )
716                                 rc = -1;
717                             break;
718                         }
719                     }
720                     else { /* next partial body length */
721                         a->size = 1 << (c & 0x1f);
722                     }
723             /*  log_debug("partial: ctx=%p c=%02x size=%u\n", a, c, a->size);*/
724                 }
725                 else
726                   BUG();
727             }
728
729             while( !rc && size && a->size ) {
730                 needed = size < a->size ? size : a->size;
731                 c = iobuf_read( chain, p, needed );
732                 if( c < needed ) {
733                     if( c == -1 ) c = 0;
734                     log_error("block_filter %p: read error (size=%lu,a->size=%lu)\n",
735                               a,  (ulong)size+c, (ulong)a->size+c);
736                     rc = G10ERR_READ_FILE;
737                 }
738                 else {
739                     size -= c;
740                     a->size -= c;
741                     p += c;
742                     n += c;
743                 }
744             }
745         }
746         *ret_len = n;
747     }
748     else if( control == IOBUFCTRL_FLUSH ) {
749         if( a->partial ) { /* the complicated openpgp scheme */
750             size_t blen, n, nbytes = size + a->buflen;
751
752             assert( a->buflen <= OP_MIN_PARTIAL_CHUNK );
753             if( nbytes < OP_MIN_PARTIAL_CHUNK ) {
754                 /* not enough to write a partial block out; so we store it*/
755                 if( !a->buffer )
756                     a->buffer = xmalloc( OP_MIN_PARTIAL_CHUNK );
757                 memcpy( a->buffer + a->buflen, buf, size );
758                 a->buflen += size;
759             }
760             else { /* okay, we can write out something */
761                 /* do this in a loop to use the most efficient block lengths */
762                 p = buf;
763                 do {
764                     /* find the best matching block length - this is limited
765                      * by the size of the internal buffering */
766                     for( blen=OP_MIN_PARTIAL_CHUNK*2,
767                             c=OP_MIN_PARTIAL_CHUNK_2POW+1; blen <= nbytes;
768                                                             blen *=2, c++ )
769                         ;
770                     blen /= 2; c--;
771                     /* write the partial length header */
772                     assert( c <= 0x1f ); /*;-)*/
773                     c |= 0xe0;
774                     iobuf_put( chain, c );
775                     if( (n=a->buflen) ) { /* write stuff from the buffer */
776                         assert( n == OP_MIN_PARTIAL_CHUNK);
777                         if( iobuf_write(chain, a->buffer, n ) )
778                             rc = G10ERR_WRITE_FILE;
779                         a->buflen = 0;
780                         nbytes -= n;
781                     }
782                     if( (n = nbytes) > blen )
783                         n = blen;
784                     if( n && iobuf_write(chain, p, n ) )
785                         rc = G10ERR_WRITE_FILE;
786                     p += n;
787                     nbytes -= n;
788                 } while( !rc && nbytes >= OP_MIN_PARTIAL_CHUNK );
789                 /* store the rest in the buffer */
790                 if( !rc && nbytes ) {
791                     assert( !a->buflen );
792                     assert( nbytes < OP_MIN_PARTIAL_CHUNK );
793                     if( !a->buffer )
794                         a->buffer = xmalloc( OP_MIN_PARTIAL_CHUNK );
795                     memcpy( a->buffer, p, nbytes );
796                     a->buflen = nbytes;
797                 }
798             }
799         }
800         else
801           BUG();
802     }
803     else if( control == IOBUFCTRL_INIT ) {
804         if( DBG_IOBUF )
805             log_debug("init block_filter %p\n", a );
806         if( a->partial )
807             a->count = 0;
808         else if( a->use == 1 )
809             a->count = a->size = 0;
810         else
811             a->count = a->size; /* force first length bytes */
812         a->eof = 0;
813         a->buffer = NULL;
814         a->buflen = 0;
815     }
816     else if( control == IOBUFCTRL_DESC ) {
817         *(char**)buf = "block_filter";
818     }
819     else if( control == IOBUFCTRL_FREE ) {
820         if( a->use == 2 ) { /* write the end markers */
821             if( a->partial ) {
822                 u32 len;
823                 /* write out the remaining bytes without a partial header
824                  * the length of this header may be 0 - but if it is
825                  * the first block we are not allowed to use a partial header
826                  * and frankly we can't do so, because this length must be
827                  * a power of 2. This is _really_ complicated because we
828                  * have to check the possible length of a packet prior
829                  * to it's creation: a chain of filters becomes complicated
830                  * and we need a lot of code to handle compressed packets etc.
831                  *   :-(((((((
832                  */
833                 /* construct header */
834                 len = a->buflen;
835                 /*log_debug("partial: remaining length=%u\n", len );*/
836                 if( len < 192 )
837                     rc = iobuf_put(chain, len );
838                 else if( len < 8384 ) {
839                     if( !(rc=iobuf_put( chain, ((len-192) / 256) + 192)) )
840                         rc = iobuf_put( chain, ((len-192) % 256));
841                 }
842                 else { /* use a 4 byte header */
843                     if( !(rc=iobuf_put( chain, 0xff )) )
844                         if( !(rc=iobuf_put( chain, (len >> 24)&0xff )) )
845                             if( !(rc=iobuf_put( chain, (len >> 16)&0xff )) )
846                                 if( !(rc=iobuf_put( chain, (len >> 8)&0xff )))
847                                     rc=iobuf_put( chain, len & 0xff );
848                 }
849                 if( !rc && len )
850                     rc = iobuf_write(chain, a->buffer, len );
851                 if( rc ) {
852                     log_error("block_filter: write error: %s\n",strerror(errno));
853                     rc = G10ERR_WRITE_FILE;
854                 }
855                 xfree( a->buffer ); a->buffer = NULL; a->buflen = 0;
856             }
857             else
858               BUG();
859         }
860         else if( a->size ) {
861             log_error("block_filter: pending bytes!\n");
862         }
863         if( DBG_IOBUF )
864             log_debug("free block_filter %p\n", a );
865         xfree(a); /* we can free our context now */
866     }
867
868     return rc;
869 }
870
871
872 static void
873 print_chain( IOBUF a )
874 {
875     if( !DBG_IOBUF )
876         return;
877     for(; a; a = a->chain ) {
878         size_t dummy_len = 0;
879         const char *desc = "[none]";
880
881         if( a->filter )
882             a->filter( a->filter_ov, IOBUFCTRL_DESC, NULL,
883                                                 (byte*)&desc, &dummy_len );
884
885         log_debug("iobuf chain: %d.%d `%s' filter_eof=%d start=%d len=%d\n",
886                    a->no, a->subno, desc?desc:"?", a->filter_eof,
887                    (int)a->d.start, (int)a->d.len );
888     }
889 }
890
891 int
892 iobuf_print_chain( IOBUF a )
893 {
894     print_chain(a);
895     return 0;
896 }
897
898 /****************
899  * Allocate a new io buffer, with no function assigned.
900  * Use is the desired usage: 1 for input, 2 for output, 3 for temp buffer
901  * BUFSIZE is a suggested buffer size.
902  */
903 IOBUF
904 iobuf_alloc(int use, size_t bufsize)
905 {
906     IOBUF a;
907     static int number=0;
908
909     a = xmalloc_clear(sizeof *a);
910     a->use = use;
911     a->d.buf = xmalloc( bufsize );
912     a->d.size = bufsize;
913     a->no = ++number;
914     a->subno = 0;
915     a->opaque = NULL;
916     a->real_fname = NULL;
917     return a;
918 }
919
920 int
921 iobuf_close ( IOBUF a )
922 {
923     IOBUF a2;
924     size_t dummy_len=0;
925     int rc=0;
926
927     if( a && a->directfp ) {
928         fclose( a->directfp );
929         xfree( a->real_fname );
930         if( DBG_IOBUF )
931             log_debug("iobuf_close -> %p\n", a->directfp );
932         return 0;
933     }
934
935     for( ; a && !rc ; a = a2 ) {
936         a2 = a->chain;
937         if( a->use == 2 && (rc=iobuf_flush(a)) )
938             log_error("iobuf_flush failed on close: %s\n", g10_errstr(rc));
939
940         if( DBG_IOBUF )
941             log_debug("iobuf-%d.%d: close `%s'\n", a->no, a->subno,
942                       a->desc?a->desc:"?");
943         if( a->filter && (rc = a->filter(a->filter_ov, IOBUFCTRL_FREE,
944                                          a->chain, NULL, &dummy_len)) )
945             log_error("IOBUFCTRL_FREE failed on close: %s\n", g10_errstr(rc) );
946         xfree(a->real_fname);
947         if (a->d.buf) {
948             memset (a->d.buf, 0, a->d.size); /* erase the buffer */
949             xfree(a->d.buf);
950         }
951         xfree(a);
952     }
953     return rc;
954 }
955
956 int
957 iobuf_cancel( IOBUF a )
958 {
959     const char *s;
960     IOBUF a2;
961     int rc;
962 #if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
963     char *remove_name = NULL;
964 #endif
965
966     if( a && a->use == 2 ) {
967         s = iobuf_get_real_fname(a);
968         if( s && *s ) {
969 #if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
970             remove_name = xstrdup ( s );
971 #else
972             remove(s);
973 #endif
974         }
975     }
976
977     /* send a cancel message to all filters */
978     for( a2 = a; a2 ; a2 = a2->chain ) {
979         size_t dummy;
980         if( a2->filter )
981             a2->filter( a2->filter_ov, IOBUFCTRL_CANCEL, a2->chain,
982                                                          NULL, &dummy );
983     }
984
985     rc = iobuf_close(a);
986 #if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
987     if ( remove_name ) {
988         /* Argg, MSDOS does not allow to remove open files.  So
989          * we have to do it here */
990         remove ( remove_name );
991         xfree ( remove_name );
992     }
993 #endif
994     return rc;
995 }
996
997
998 /****************
999  * create a temporary iobuf, which can be used to collect stuff
1000  * in an iobuf and later be written by iobuf_write_temp() to another
1001  * iobuf.
1002  */
1003 IOBUF
1004 iobuf_temp()
1005 {
1006     IOBUF a;
1007
1008     a = iobuf_alloc(3, IOBUF_BUFFER_SIZE );
1009
1010     return a;
1011 }
1012
1013 IOBUF
1014 iobuf_temp_with_content( const char *buffer, size_t length )
1015 {
1016     IOBUF a;
1017
1018     a = iobuf_alloc(3, length );
1019     memcpy( a->d.buf, buffer, length );
1020     a->d.len = length;
1021
1022     return a;
1023 }
1024
1025 void
1026 iobuf_enable_special_filenames ( int yes )
1027 {
1028     special_names_enabled = yes;
1029 }
1030
1031 /*
1032  * see whether the filename has the for "-&nnnn", where n is a
1033  * non-zero number.
1034  * Returns this number or -1 if it is not the case.
1035  */
1036 static int
1037 check_special_filename ( const char *fname )
1038 {
1039     if ( special_names_enabled
1040          && fname && *fname == '-' && fname[1] == '&' ) {
1041         int i;
1042
1043         fname += 2;
1044         for (i=0; digitp (fname+i); i++ )
1045             ;
1046         if ( !fname[i] ) 
1047             return atoi (fname);
1048     }
1049     return -1;
1050 }
1051
1052 /* This fucntion returns true if FNAME indicates a PIPE (stdout or
1053    stderr) or a special file name if those are enabled. */
1054 int
1055 iobuf_is_pipe_filename (const char *fname)
1056 {
1057   if (!fname || (*fname=='-' && !fname[1]) )
1058     return 1;
1059   return check_special_filename (fname) != -1;
1060 }
1061
1062 /****************
1063  * Create a head iobuf for reading from a file
1064  * returns: NULL if an error occures and sets errno
1065  */
1066 IOBUF
1067 iobuf_open( const char *fname )
1068 {
1069     IOBUF a;
1070     FILEP_OR_FD fp;
1071     file_filter_ctx_t *fcx;
1072     size_t len;
1073     int print_only = 0;
1074     int fd;
1075
1076     if( !fname || (*fname=='-' && !fname[1])  ) {
1077         fp = FILEP_OR_FD_FOR_STDIN;
1078 #ifdef USE_SETMODE
1079         setmode ( my_fileno(fp) , O_BINARY );
1080 #endif
1081         fname = "[stdin]";
1082         print_only = 1;
1083     }
1084     else if ( (fd = check_special_filename ( fname )) != -1 )
1085         return iobuf_fdopen ( translate_file_handle (fd,0), "rb" );
1086     else if( (fp = my_fopen_ro(fname, "rb")) == INVALID_FP )
1087         return NULL;
1088     a = iobuf_alloc(1, IOBUF_BUFFER_SIZE );
1089     fcx = xmalloc( sizeof *fcx + strlen(fname) );
1090     fcx->fp = fp;
1091     fcx->print_only_name = print_only;
1092     strcpy(fcx->fname, fname );
1093     if( !print_only )
1094         a->real_fname = xstrdup( fname );
1095     a->filter = file_filter;
1096     a->filter_ov = fcx;
1097     file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
1098     file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
1099     if( DBG_IOBUF )
1100         log_debug("iobuf-%d.%d: open `%s' fd=%d\n",
1101                    a->no, a->subno, fname, (int)my_fileno(fcx->fp) );
1102
1103     return a;
1104 }
1105
1106 /****************
1107  * Create a head iobuf for reading from a file
1108  * returns: NULL if an error occures and sets errno
1109  */
1110 IOBUF
1111 iobuf_fdopen( int fd, const char *mode )
1112 {
1113     IOBUF a;
1114     FILEP_OR_FD fp;
1115     file_filter_ctx_t *fcx;
1116     size_t len;
1117
1118 #ifdef FILE_FILTER_USES_STDIO
1119     if( !(fp = fdopen(fd, mode)) )
1120         return NULL;
1121 #else
1122     fp = (FILEP_OR_FD)fd;
1123 #endif
1124     a = iobuf_alloc( strchr( mode, 'w')? 2:1, IOBUF_BUFFER_SIZE );
1125     fcx = xmalloc( sizeof *fcx + 20 );
1126     fcx->fp = fp;
1127     fcx->print_only_name = 1;
1128     sprintf(fcx->fname, "[fd %d]", fd );
1129     a->filter = file_filter;
1130     a->filter_ov = fcx;
1131     file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
1132     file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
1133     if( DBG_IOBUF )
1134         log_debug("iobuf-%d.%d: fdopen `%s'\n", a->no, a->subno, fcx->fname );
1135     iobuf_ioctl (a,3,1,NULL); /* disable fd caching */
1136     return a;
1137 }
1138
1139
1140 IOBUF
1141 iobuf_sockopen ( int fd, const char *mode )
1142 {
1143     IOBUF a;
1144 #ifdef _WIN32
1145     sock_filter_ctx_t *scx;
1146     size_t len;
1147
1148     a = iobuf_alloc( strchr( mode, 'w')? 2:1, IOBUF_BUFFER_SIZE );
1149     scx = xmalloc( sizeof *scx + 25 );
1150     scx->sock = fd;
1151     scx->print_only_name = 1;
1152     sprintf(scx->fname, "[sock %d]", fd );
1153     a->filter = sock_filter;
1154     a->filter_ov = scx;
1155     sock_filter( scx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
1156     sock_filter( scx, IOBUFCTRL_INIT, NULL, NULL, &len );
1157     if( DBG_IOBUF )
1158         log_debug("iobuf-%d.%d: sockopen `%s'\n", a->no, a->subno, scx->fname);
1159     iobuf_ioctl (a,3,1,NULL); /* disable fd caching */ 
1160 #else
1161     a = iobuf_fdopen (fd, mode);
1162 #endif
1163     return a;
1164 }
1165
1166 /****************
1167  * create an iobuf for writing to a file; the file will be created.
1168  */
1169 IOBUF
1170 iobuf_create( const char *fname )
1171 {
1172     IOBUF a;
1173     FILEP_OR_FD fp;
1174     file_filter_ctx_t *fcx;
1175     size_t len;
1176     int print_only = 0;
1177     int fd;
1178
1179     if( !fname || (*fname=='-' && !fname[1]) ) {
1180         fp = FILEP_OR_FD_FOR_STDOUT;
1181 #ifdef USE_SETMODE
1182         setmode ( my_fileno(fp) , O_BINARY );
1183 #endif
1184         fname = "[stdout]";
1185         print_only = 1;
1186     }
1187     else if ( (fd = check_special_filename ( fname )) != -1 )
1188         return iobuf_fdopen ( translate_file_handle (fd, 1), "wb" );
1189     else if( (fp = my_fopen(fname, "wb")) == INVALID_FP )
1190         return NULL;
1191     a = iobuf_alloc(2, IOBUF_BUFFER_SIZE );
1192     fcx = xmalloc( sizeof *fcx + strlen(fname) );
1193     fcx->fp = fp;
1194     fcx->print_only_name = print_only;
1195     strcpy(fcx->fname, fname );
1196     if( !print_only )
1197         a->real_fname = xstrdup( fname );
1198     a->filter = file_filter;
1199     a->filter_ov = fcx;
1200     file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
1201     file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
1202     if( DBG_IOBUF )
1203         log_debug("iobuf-%d.%d: create `%s'\n", a->no, a->subno, 
1204                   a->desc?a->desc:"?" );
1205
1206     return a;
1207 }
1208
1209 /****************
1210  * append to an iobuf; if the file does not exist, create it.
1211  * cannot be used for stdout.
1212  * Note: This is not used.
1213  */
1214 #if 0 /* not used */
1215 IOBUF
1216 iobuf_append( const char *fname )
1217 {
1218     IOBUF a;
1219     FILE *fp;
1220     file_filter_ctx_t *fcx;
1221     size_t len;
1222
1223     if( !fname )
1224         return NULL;
1225     else if( !(fp = my_fopen(fname, "ab")) )
1226         return NULL;
1227     a = iobuf_alloc(2, IOBUF_BUFFER_SIZE );
1228     fcx = xmalloc( sizeof *fcx + strlen(fname) );
1229     fcx->fp = fp;
1230     strcpy(fcx->fname, fname );
1231     a->real_fname = xstrdup( fname );
1232     a->filter = file_filter;
1233     a->filter_ov = fcx;
1234     file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
1235     file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
1236     if( DBG_IOBUF )
1237         log_debug("iobuf-%d.%d: append `%s'\n", a->no, a->subno, 
1238                   a->desc?a->desc:"?" );
1239
1240     return a;
1241 }
1242 #endif
1243
1244 IOBUF
1245 iobuf_openrw( const char *fname )
1246 {
1247     IOBUF a;
1248     FILEP_OR_FD fp;
1249     file_filter_ctx_t *fcx;
1250     size_t len;
1251
1252     if( !fname )
1253         return NULL;
1254     else if( (fp = my_fopen(fname, "r+b")) == INVALID_FP )
1255         return NULL;
1256     a = iobuf_alloc(2, IOBUF_BUFFER_SIZE );
1257     fcx = xmalloc( sizeof *fcx + strlen(fname) );
1258     fcx->fp = fp;
1259     strcpy(fcx->fname, fname );
1260     a->real_fname = xstrdup( fname );
1261     a->filter = file_filter;
1262     a->filter_ov = fcx;
1263     file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
1264     file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
1265     if( DBG_IOBUF )
1266         log_debug("iobuf-%d.%d: openrw `%s'\n", a->no, a->subno, 
1267                   a->desc?a->desc:"?");
1268
1269     return a;
1270 }
1271
1272
1273 int
1274 iobuf_ioctl ( IOBUF a, int cmd, int intval, void *ptrval )
1275 {
1276     if ( cmd == 1 ) {  /* keep system filepointer/descriptor open */
1277         if( DBG_IOBUF )
1278             log_debug("iobuf-%d.%d: ioctl `%s' keep=%d\n",
1279                       a? a->no:-1, a?a->subno:-1, 
1280                       a&&a->desc?a->desc:"?", intval );
1281         for( ; a; a = a->chain )
1282             if( !a->chain && a->filter == file_filter ) {
1283                 file_filter_ctx_t *b = a->filter_ov;
1284                 b->keep_open = intval;
1285                 return 0;
1286             }
1287 #ifdef _WIN32
1288             else if( !a->chain && a->filter == sock_filter ) {
1289                 sock_filter_ctx_t *b = a->filter_ov;
1290                 b->keep_open = intval;
1291                 return 0;
1292             }
1293 #endif
1294     }
1295     else if ( cmd == 2 ) {  /* invalidate cache */
1296         if( DBG_IOBUF )
1297             log_debug("iobuf-*.*: ioctl `%s' invalidate\n",
1298                       ptrval? (char*)ptrval:"[all]");
1299         if ( !a && !intval ) {
1300 #ifndef FILE_FILTER_USES_STDIO
1301             fd_cache_invalidate (ptrval);
1302 #endif
1303             return 0;
1304         }
1305     }
1306     else if ( cmd == 3 ) {  /* disallow/allow caching */
1307         if( DBG_IOBUF )
1308             log_debug("iobuf-%d.%d: ioctl `%s' no_cache=%d\n",
1309                       a? a->no:-1, a?a->subno:-1, 
1310                       a&&a->desc?a->desc:"?", intval );
1311         for( ; a; a = a->chain )
1312             if( !a->chain && a->filter == file_filter ) {
1313                 file_filter_ctx_t *b = a->filter_ov;
1314                 b->no_cache = intval;
1315                 return 0;
1316             }
1317 #ifdef _WIN32
1318             else if( !a->chain && a->filter == sock_filter ) {
1319                 sock_filter_ctx_t *b = a->filter_ov;
1320                 b->no_cache = intval;
1321                 return 0;
1322             }
1323 #endif
1324     }
1325
1326     return -1;
1327 }
1328
1329
1330 /****************
1331  * Register an i/o filter.
1332  */
1333 int
1334 iobuf_push_filter( IOBUF a,
1335                    int (*f)(void *opaque, int control,
1336                    IOBUF chain, byte *buf, size_t *len), void *ov )
1337 {
1338     return iobuf_push_filter2( a, f, ov, 0 );
1339 }
1340
1341 int
1342 iobuf_push_filter2( IOBUF a,
1343                     int (*f)(void *opaque, int control,
1344                     IOBUF chain, byte *buf, size_t *len),
1345                     void *ov, int rel_ov )
1346 {
1347     IOBUF b;
1348     size_t dummy_len=0;
1349     int rc=0;
1350
1351     if( a->directfp )
1352         BUG();
1353
1354     if( a->use == 2 && (rc=iobuf_flush(a)) )
1355         return rc;
1356     /* make a copy of the current stream, so that
1357      * A is the new stream and B the original one.
1358      * The contents of the buffers are transferred to the
1359      * new stream.
1360      */
1361     b = xmalloc(sizeof *b);
1362     memcpy(b, a, sizeof *b );
1363     /* fixme: it is stupid to keep a copy of the name at every level
1364      * but we need the name somewhere because the name known by file_filter
1365      * may have been released when we need the name of the file */
1366     b->real_fname = a->real_fname? xstrdup(a->real_fname):NULL;
1367     /* remove the filter stuff from the new stream */
1368     a->filter = NULL;
1369     a->filter_ov = NULL;
1370     a->filter_ov_owner = 0;
1371     a->filter_eof = 0;
1372     if( a->use == 3 )
1373         a->use = 2;  /* make a write stream from a temp stream */
1374
1375     if( a->use == 2 ) { /* allocate a fresh buffer for the original stream */
1376         b->d.buf = xmalloc( a->d.size );
1377         b->d.len = 0;
1378         b->d.start = 0;
1379     }
1380     else { /* allocate a fresh buffer for the new stream */
1381         a->d.buf = xmalloc( a->d.size );
1382         a->d.len = 0;
1383         a->d.start = 0;
1384     }
1385     /* disable nlimit for the new stream */
1386     a->ntotal = b->ntotal + b->nbytes;
1387     a->nlimit = a->nbytes = 0;
1388     a->nofast &= ~1;
1389     /* make a link from the new stream to the original stream */
1390     a->chain = b;
1391     a->opaque = b->opaque;
1392
1393     /* setup the function on the new stream */
1394     a->filter = f;
1395     a->filter_ov = ov;
1396     a->filter_ov_owner = rel_ov;
1397
1398     a->subno = b->subno + 1;
1399     f( ov, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &dummy_len );
1400
1401     if( DBG_IOBUF ) {
1402         log_debug("iobuf-%d.%d: push `%s'\n", a->no, a->subno, 
1403                   a->desc?a->desc:"?" );
1404         print_chain( a );
1405     }
1406
1407     /* now we can initialize the new function if we have one */
1408     if( a->filter && (rc = a->filter(a->filter_ov, IOBUFCTRL_INIT, a->chain,
1409                        NULL, &dummy_len)) )
1410         log_error("IOBUFCTRL_INIT failed: %s\n", g10_errstr(rc) );
1411     return rc;
1412 }
1413
1414 /****************
1415  * Remove an i/o filter.
1416  */
1417 static int
1418 pop_filter( IOBUF a, int (*f)(void *opaque, int control,
1419                       IOBUF chain, byte *buf, size_t *len), void *ov )
1420 {
1421     IOBUF b;
1422     size_t dummy_len=0;
1423     int rc=0;
1424
1425     if( a->directfp )
1426         BUG();
1427
1428     if( DBG_IOBUF )
1429         log_debug("iobuf-%d.%d: pop `%s'\n", a->no, a->subno,
1430                   a->desc?a->desc:"?" );
1431     if( !a->filter ) { /* this is simple */
1432         b = a->chain;
1433         assert(b);
1434         xfree(a->d.buf);
1435         xfree(a->real_fname);
1436         memcpy(a,b, sizeof *a);
1437         xfree(b);
1438         return 0;
1439     }
1440     for(b=a ; b; b = b->chain )
1441         if( b->filter == f && (!ov || b->filter_ov == ov) )
1442             break;
1443     if( !b )
1444         log_bug("pop_filter(): filter function not found\n");
1445
1446     /* flush this stream if it is an output stream */
1447     if( a->use == 2 && (rc=iobuf_flush(b)) ) {
1448         log_error("iobuf_flush failed in pop_filter: %s\n", g10_errstr(rc));
1449         return rc;
1450     }
1451     /* and tell the filter to free it self */
1452     if( b->filter && (rc = b->filter(b->filter_ov, IOBUFCTRL_FREE, b->chain,
1453                        NULL, &dummy_len)) ) {
1454         log_error("IOBUFCTRL_FREE failed: %s\n", g10_errstr(rc) );
1455         return rc;
1456     }
1457     if( b->filter_ov && b->filter_ov_owner ) {
1458         xfree( b->filter_ov );
1459         b->filter_ov = NULL;
1460     }
1461
1462
1463     /* and see how to remove it */
1464     if( a == b && !b->chain )
1465         log_bug("can't remove the last filter from the chain\n");
1466     else if( a == b ) { /* remove the first iobuf from the chain */
1467         /* everything from b is copied to a. This is save because
1468          * a flush has been done on the to be removed entry
1469          */
1470         b = a->chain;
1471         xfree(a->d.buf);
1472         xfree(a->real_fname);
1473         memcpy(a,b, sizeof *a);
1474         xfree(b);
1475         if( DBG_IOBUF )
1476            log_debug("iobuf-%d.%d: popped filter\n", a->no, a->subno );
1477     }
1478     else if( !b->chain ) { /* remove the last iobuf from the chain */
1479         log_bug("Ohh jeee, trying to remove a head filter\n");
1480     }
1481     else {  /* remove an intermediate iobuf from the chain */
1482         log_bug("Ohh jeee, trying to remove an intermediate filter\n");
1483     }
1484
1485     return rc;
1486 }
1487
1488
1489 /****************
1490  * read underflow: read more bytes into the buffer and return
1491  * the first byte or -1 on EOF.
1492  */
1493 static int
1494 underflow(IOBUF a)
1495 {
1496     size_t len;
1497     int rc;
1498
1499     assert( a->d.start == a->d.len );
1500     if( a->use == 3 )
1501         return -1; /* EOF because a temp buffer can't do an underflow */
1502
1503     if( a->filter_eof ) {
1504         if( a->chain ) {
1505             IOBUF b = a->chain;
1506             if( DBG_IOBUF )
1507                 log_debug("iobuf-%d.%d: pop `%s' in underflow\n",
1508                           a->no, a->subno, a->desc?a->desc:"?" );
1509             xfree(a->d.buf);
1510             xfree(a->real_fname);
1511             memcpy(a, b, sizeof *a);
1512             xfree(b);
1513             print_chain(a);
1514         }
1515         else
1516              a->filter_eof = 0;  /* for the top level filter */
1517         if( DBG_IOBUF )
1518             log_debug("iobuf-%d.%d: underflow: eof (due to filter eof)\n",
1519                                                     a->no, a->subno );
1520         return -1; /* return one(!) EOF */
1521     }
1522     if( a->error ) {
1523         if( DBG_IOBUF )
1524             log_debug("iobuf-%d.%d: error\n", a->no, a->subno );
1525         return -1;
1526     }
1527
1528     if( a->directfp ) {
1529         FILE *fp = a->directfp;
1530
1531         len = fread( a->d.buf, 1, a->d.size, fp);
1532         if( len < a->d.size ) {
1533             if( ferror(fp) )
1534                 a->error = 1;
1535         }
1536         a->d.len = len;
1537         a->d.start = 0;
1538         return len? a->d.buf[a->d.start++] : -1;
1539     }
1540
1541
1542     if( a->filter ) {
1543         len = a->d.size;
1544         if( DBG_IOBUF )
1545             log_debug("iobuf-%d.%d: underflow: req=%lu\n",
1546                       a->no, a->subno, (ulong)len );
1547         rc = a->filter( a->filter_ov, IOBUFCTRL_UNDERFLOW, a->chain,
1548                         a->d.buf, &len );
1549         if( DBG_IOBUF ) {
1550             log_debug("iobuf-%d.%d: underflow: got=%lu rc=%d\n",
1551                     a->no, a->subno, (ulong)len, rc );
1552 /*          if( a->no == 1 ) */
1553 /*                   log_hexdump ("     data:", a->d.buf, len); */
1554         }
1555         if( a->use == 1 && rc == -1 ) { /* EOF: we can remove the filter */
1556             size_t dummy_len=0;
1557
1558             /* and tell the filter to free itself */
1559             if( (rc = a->filter(a->filter_ov, IOBUFCTRL_FREE, a->chain,
1560                                NULL, &dummy_len)) )
1561                 log_error("IOBUFCTRL_FREE failed: %s\n", g10_errstr(rc) );
1562             if( a->filter_ov && a->filter_ov_owner ) {
1563                 xfree( a->filter_ov );
1564                 a->filter_ov = NULL;
1565             }
1566             a->filter = NULL;
1567             a->desc = NULL;
1568             a->filter_ov = NULL;
1569             a->filter_eof = 1;
1570             if( !len && a->chain ) {
1571                 IOBUF b = a->chain;
1572                 if( DBG_IOBUF )
1573                     log_debug("iobuf-%d.%d: pop in underflow (!len)\n",
1574                               a->no, a->subno);
1575                 xfree(a->d.buf);
1576                 xfree(a->real_fname);
1577                 memcpy(a,b, sizeof *a);
1578                 xfree(b);
1579                 print_chain(a);
1580             }
1581         }
1582         else if( rc )
1583             a->error = 1;
1584
1585         if( !len ) {
1586             if( DBG_IOBUF )
1587                 log_debug("iobuf-%d.%d: underflow: eof\n", a->no, a->subno );
1588             return -1;
1589         }
1590         a->d.len = len;
1591         a->d.start = 0;
1592         return a->d.buf[a->d.start++];
1593     }
1594     else {
1595         if( DBG_IOBUF )
1596             log_debug("iobuf-%d.%d: underflow: eof (no filter)\n",
1597                                                     a->no, a->subno );
1598         return -1;  /* no filter; return EOF */
1599     }
1600 }
1601
1602
1603 int
1604 iobuf_flush(IOBUF a)
1605 {
1606     size_t len;
1607     int rc;
1608
1609     if( a->directfp )
1610         return 0;
1611
1612     if( a->use == 3 ) { /* increase the temp buffer */
1613         char *newbuf;
1614         size_t newsize = a->d.size + IOBUF_BUFFER_SIZE;
1615
1616         if( DBG_IOBUF )
1617           log_debug("increasing temp iobuf from %lu to %lu\n",
1618                     (ulong)a->d.size, (ulong)newsize );
1619         newbuf = xmalloc( newsize );
1620         memcpy( newbuf, a->d.buf, a->d.len );
1621         xfree(a->d.buf);
1622         a->d.buf = newbuf;
1623         a->d.size = newsize;
1624         return 0;
1625     }
1626     else if( a->use != 2 )
1627         log_bug("flush on non-output iobuf\n");
1628     else if( !a->filter )
1629         log_bug("iobuf_flush: no filter\n");
1630     len = a->d.len;
1631     rc = a->filter( a->filter_ov, IOBUFCTRL_FLUSH, a->chain, a->d.buf, &len );
1632     if( !rc && len != a->d.len ) {
1633         log_info("iobuf_flush did not write all!\n");
1634         rc = G10ERR_WRITE_FILE;
1635     }
1636     else if( rc )
1637         a->error = 1;
1638     a->d.len = 0;
1639
1640     return rc;
1641 }
1642
1643
1644 /****************
1645  * Read a byte from the iobuf; returns -1 on EOF
1646  */
1647 int
1648 iobuf_readbyte(IOBUF a)
1649 {
1650     int c;
1651
1652     /* nlimit does not work together with unget */
1653     /* nbytes is also not valid! */
1654     if( a->unget.buf ) {
1655         if( a->unget.start < a->unget.len )
1656             return a->unget.buf[a->unget.start++];
1657         xfree(a->unget.buf);
1658         a->unget.buf = NULL;
1659         a->nofast &= ~2;
1660     }
1661
1662     if( a->nlimit && a->nbytes >= a->nlimit )
1663         return -1; /* forced EOF */
1664
1665     if( a->d.start < a->d.len ) {
1666         c = a->d.buf[a->d.start++];
1667     }
1668     else if( (c=underflow(a)) == -1 )
1669         return -1; /* EOF */
1670
1671     a->nbytes++;
1672     return c;
1673 }
1674
1675
1676 int
1677 iobuf_read(IOBUF a, byte *buf, unsigned buflen )
1678 {
1679     int c, n;
1680
1681     if( a->unget.buf || a->nlimit ) {
1682         /* handle special cases */
1683         for(n=0 ; n < buflen; n++ ) {
1684             if( (c = iobuf_readbyte(a)) == -1 ) {
1685                 if( !n )
1686                     return -1; /* eof */
1687                 break;
1688             }
1689             else
1690                 if( buf ) *buf = c;
1691             if( buf ) buf++;
1692         }
1693         return n;
1694     }
1695
1696     n = 0;
1697     do {
1698         if( n < buflen && a->d.start < a->d.len ) {
1699             unsigned size = a->d.len - a->d.start;
1700             if( size > buflen - n )
1701                 size = buflen - n;
1702             if( buf )
1703                 memcpy( buf, a->d.buf + a->d.start, size );
1704             n += size;
1705             a->d.start += size;
1706             if( buf )
1707                 buf += size;
1708         }
1709         if( n < buflen ) {
1710             if( (c=underflow(a)) == -1 ) {
1711                 a->nbytes += n;
1712                 return n? n : -1/*EOF*/;
1713             }
1714             if( buf )
1715                 *buf++ = c;
1716             n++;
1717         }
1718     } while( n < buflen );
1719     a->nbytes += n;
1720     return n;
1721 }
1722
1723
1724 /****************
1725  * Have a look at the iobuf.
1726  * NOTE: This only works in special cases.
1727  */
1728 int
1729 iobuf_peek(IOBUF a, byte *buf, unsigned buflen )
1730 {
1731     int n=0;
1732
1733     if( a->filter_eof )
1734         return -1;
1735
1736     if( !(a->d.start < a->d.len) ) {
1737         if( underflow(a) == -1 )
1738             return -1;
1739         /* and unget this character */
1740         assert(a->d.start == 1);
1741         a->d.start = 0;
1742     }
1743
1744     for(n=0 ; n < buflen && (a->d.start+n) < a->d.len ; n++, buf++ )
1745         *buf = a->d.buf[n];
1746     return n;
1747 }
1748
1749
1750
1751
1752 int
1753 iobuf_writebyte(IOBUF a, unsigned c)
1754 {
1755
1756     if( a->directfp )
1757         BUG();
1758
1759     if( a->d.len == a->d.size )
1760         if( iobuf_flush(a) )
1761             return -1;
1762
1763     assert( a->d.len < a->d.size );
1764     a->d.buf[a->d.len++] = c;
1765     return 0;
1766 }
1767
1768
1769 int
1770 iobuf_write(IOBUF a, byte *buf, unsigned buflen )
1771 {
1772
1773     if( a->directfp )
1774         BUG();
1775
1776     do {
1777         if( buflen && a->d.len < a->d.size ) {
1778             unsigned size = a->d.size - a->d.len;
1779             if( size > buflen ) size = buflen;
1780             memcpy( a->d.buf + a->d.len, buf, size );
1781             buflen -= size;
1782             buf += size;
1783             a->d.len += size;
1784         }
1785         if( buflen ) {
1786             if( iobuf_flush(a) )
1787                 return -1;
1788         }
1789     } while( buflen );
1790     return 0;
1791 }
1792
1793
1794 int
1795 iobuf_writestr(IOBUF a, const char *buf )
1796 {
1797     for( ; *buf; buf++ )
1798         if( iobuf_writebyte(a, *buf) )
1799             return -1;
1800     return 0;
1801 }
1802
1803
1804
1805 /****************
1806  * copy the contents of TEMP to A.
1807  */
1808 int
1809 iobuf_write_temp( IOBUF a, IOBUF temp )
1810 {
1811     while( temp->chain )
1812         pop_filter( temp, temp->filter, NULL );
1813     return iobuf_write(a, temp->d.buf, temp->d.len );
1814 }
1815
1816 /****************
1817  * copy the contents of the temp io stream to BUFFER.
1818  */
1819 size_t
1820 iobuf_temp_to_buffer( IOBUF a, byte *buffer, size_t buflen )
1821 {
1822     size_t n = a->d.len;
1823
1824     if( n > buflen )
1825         n = buflen;
1826     memcpy( buffer, a->d.buf, n );
1827     return n;
1828 }
1829
1830
1831 /****************
1832  * Call this function to terminate processing of the temp stream
1833  * without closing it.  This removes all filters from the stream
1834  * makes sure that iobuf_get_temp_{buffer,length}() returns correct
1835  * values.
1836  */
1837 void
1838 iobuf_flush_temp( IOBUF temp )
1839 {
1840     while( temp->chain )
1841         pop_filter( temp, temp->filter, NULL );
1842 }
1843
1844
1845 /****************
1846  * Set a limit on how many bytes may be read from the input stream A.
1847  * Setting the limit to 0 disables this feature.
1848  */
1849 void
1850 iobuf_set_limit( IOBUF a, off_t nlimit )
1851 {
1852     if( nlimit )
1853         a->nofast |= 1;
1854     else
1855         a->nofast &= ~1;
1856     a->nlimit = nlimit;
1857     a->ntotal += a->nbytes;
1858     a->nbytes = 0;
1859 }
1860
1861
1862
1863 /* Return the length of an open file A.  IF OVERFLOW is not NULL it
1864    will be set to true if the file is larger than what off_t can cope
1865    with.  The function return 0 on error or on overflow condition.  */
1866 off_t
1867 iobuf_get_filelength (IOBUF a, int *overflow )
1868 {
1869     struct stat st;
1870
1871     if (overflow)
1872       *overflow = 0;
1873
1874     if( a->directfp )  {
1875         FILE *fp = a->directfp;
1876
1877        if( !fstat(fileno(fp), &st) )
1878            return st.st_size;
1879         log_error("fstat() failed: %s\n", strerror(errno) );
1880         return 0;
1881     }
1882
1883     /* Hmmm: file_filter may have already been removed */
1884     for( ; a; a = a->chain )
1885         if( !a->chain && a->filter == file_filter ) {
1886             file_filter_ctx_t *b = a->filter_ov;
1887             FILEP_OR_FD fp = b->fp;
1888
1889 #if defined(HAVE_DOSISH_SYSTEM) && !defined(FILE_FILTER_USES_STDIO)
1890             ulong size;
1891             static int (* __stdcall get_file_size_ex) 
1892               (void *handle, LARGE_INTEGER *size);
1893             static int get_file_size_ex_initialized;
1894
1895             if (!get_file_size_ex_initialized)
1896               {
1897                 void *handle;
1898                 
1899                 handle = dlopen ("kernel32.dll", RTLD_LAZY);
1900                 if (handle)
1901                   {
1902                     get_file_size_ex = dlsym (handle, "GetFileSizeEx");
1903                     if (!get_file_size_ex)
1904                     dlclose (handle);
1905                   }
1906                 get_file_size_ex_initialized = 1;
1907               }
1908
1909             if (get_file_size_ex)
1910               {
1911                 /* This is a newer system with GetFileSizeEx; we use
1912                    this then becuase it seem that GetFileSize won't
1913                    return a proper error in case a file is larger than
1914                    4GB. */
1915                 LARGE_INTEGER size;
1916                 
1917                 if (get_file_size_ex (fp, &size))
1918                   {
1919                     if (!size.u.HighPart)
1920                       return size.u.LowPart;
1921                     if (overflow)
1922                       *overflow = 1;
1923                     return 0; 
1924                   }
1925               }
1926             else
1927               {
1928                 if  ((size=GetFileSize (fp, NULL)) != 0xffffffff)
1929                   return size;
1930               }
1931             log_error ("GetFileSize for handle %p failed: %s\n",
1932                        fp, w32_strerror (0));
1933 #else
1934             if( !fstat(my_fileno(fp), &st) )
1935                 return st.st_size;
1936             log_error("fstat() failed: %s\n", strerror(errno) );
1937 #endif
1938             break;
1939         }
1940
1941     return 0;
1942 }
1943
1944
1945 /* Return the file descriptor of the underlying file or -1 if it is
1946    not available.  */
1947 int 
1948 iobuf_get_fd (IOBUF a)
1949 {
1950   if (a->directfp)
1951     return fileno ( (FILE*)a->directfp );
1952
1953   for ( ; a; a = a->chain )
1954     if (!a->chain && a->filter == file_filter)
1955       {
1956         file_filter_ctx_t *b = a->filter_ov;
1957         FILEP_OR_FD fp = b->fp;
1958
1959         return my_fileno (fp);
1960       }
1961
1962   return -1;
1963 }
1964
1965
1966 /****************
1967  * Tell the file position, where the next read will take place
1968  */
1969 off_t
1970 iobuf_tell( IOBUF a )
1971 {
1972     return a->ntotal + a->nbytes;
1973 }
1974
1975
1976 #if !defined(HAVE_FSEEKO) && !defined(fseeko)
1977
1978 #ifdef HAVE_LIMITS_H
1979 # include <limits.h>
1980 #endif
1981 #ifndef LONG_MAX
1982 # define LONG_MAX ((long) ((unsigned long) -1 >> 1))
1983 #endif
1984 #ifndef LONG_MIN
1985 # define LONG_MIN (-1 - LONG_MAX)
1986 #endif
1987
1988 /****************
1989  * A substitute for fseeko, for hosts that don't have it.
1990  */
1991 static int
1992 fseeko( FILE *stream, off_t newpos, int whence )
1993 {
1994     while( newpos != (long) newpos ) {
1995        long pos = newpos < 0 ? LONG_MIN : LONG_MAX;
1996        if( fseek( stream, pos, whence ) != 0 )
1997            return -1;
1998        newpos -= pos;
1999        whence = SEEK_CUR;
2000     }
2001     return fseek( stream, (long)newpos, whence );
2002 }
2003 #endif
2004
2005 /****************
2006  * This is a very limited implementation. It simply discards all internal
2007  * buffering and removes all filters but the first one.
2008  */
2009 int
2010 iobuf_seek( IOBUF a, off_t newpos )
2011 {
2012     file_filter_ctx_t *b = NULL;
2013
2014     if( a->directfp ) {
2015         FILE *fp = a->directfp;
2016         if( fseeko( fp, newpos, SEEK_SET ) ) {
2017             log_error("can't seek: %s\n", strerror(errno) );
2018             return -1;
2019         }
2020         clearerr(fp);
2021     }
2022     else {
2023         for( ; a; a = a->chain ) {
2024             if( !a->chain && a->filter == file_filter ) {
2025                 b = a->filter_ov;
2026                 break;
2027             }
2028         }
2029         if( !a )
2030             return -1;
2031 #ifdef FILE_FILTER_USES_STDIO
2032        if( fseeko( b->fp, newpos, SEEK_SET ) ) {
2033            log_error("can't fseek: %s\n", strerror(errno) );
2034            return -1;
2035        }
2036 #else
2037 #ifdef HAVE_DOSISH_SYSTEM
2038        if (SetFilePointer (b->fp, newpos, NULL, FILE_BEGIN) == 0xffffffff ) {
2039            log_error ("SetFilePointer failed on handle %p: %s\n",
2040                       b->fp, w32_strerror (0));
2041            return -1;
2042        }
2043 #else
2044        if ( lseek (b->fp, newpos, SEEK_SET) == (off_t)-1 ) {
2045            log_error("can't lseek: %s\n", strerror(errno) );
2046            return -1;
2047        }
2048 #endif
2049 #endif
2050     }
2051     a->d.len = 0;   /* discard buffer */
2052     a->d.start = 0;
2053     a->nbytes = 0;
2054     a->nlimit = 0;
2055     a->nofast &= ~1;
2056     a->ntotal = newpos;
2057     a->error = 0;
2058     /* remove filters, but the last */
2059     if( a->chain )
2060         log_debug("pop_filter called in iobuf_seek - please report\n");
2061     while( a->chain )
2062        pop_filter( a, a->filter, NULL );
2063
2064     return 0;
2065 }
2066
2067
2068
2069
2070
2071
2072 /****************
2073  * Retrieve the real filename
2074  */
2075 const char *
2076 iobuf_get_real_fname( IOBUF a )
2077 {
2078     if( a->real_fname )
2079         return a->real_fname;
2080
2081     /* the old solution */
2082     for( ; a; a = a->chain )
2083         if( !a->chain && a->filter == file_filter ) {
2084             file_filter_ctx_t *b = a->filter_ov;
2085             return b->print_only_name? NULL : b->fname;
2086         }
2087
2088     return NULL;
2089 }
2090
2091
2092 /****************
2093  * Retrieve the filename
2094  */
2095 const char *
2096 iobuf_get_fname( IOBUF a )
2097 {
2098     for( ; a; a = a->chain )
2099         if( !a->chain && a->filter == file_filter ) {
2100             file_filter_ctx_t *b = a->filter_ov;
2101             return b->fname;
2102         }
2103
2104     return NULL;
2105 }
2106
2107
2108 /****************
2109  * enable partial block mode as described in the OpenPGP draft.
2110  * LEN is the first length byte on read, but ignored on writes.
2111  */
2112 void
2113 iobuf_set_partial_block_mode( IOBUF a, size_t len )
2114 {
2115     block_filter_ctx_t *ctx = xmalloc_clear( sizeof *ctx );
2116
2117     assert( a->use == 1 || a->use == 2 );
2118     ctx->use = a->use;
2119     if( !len ) {
2120         if( a->use == 1 )
2121             log_debug("pop_filter called in set_partial_block_mode"
2122                                                     " - please report\n");
2123         pop_filter(a, block_filter, NULL );
2124     }
2125     else {
2126         ctx->partial = 1;
2127         ctx->size = 0;
2128         ctx->first_c = len;
2129         iobuf_push_filter(a, block_filter, ctx );
2130     }
2131 }
2132
2133
2134 /****************
2135  * Same as fgets() but if the buffer is too short a larger one will
2136  * be allocated up to some limit *max_length.
2137  * A line is considered a byte stream ending in a LF.
2138  * Returns the length of the line. EOF is indicated by a line of
2139  * length zero. The last LF may be missing due to an EOF.
2140  * is max_length is zero on return, the line has been truncated.
2141  *
2142  * Note: The buffer is allocated with enough space to append a CR,LF,EOL
2143  */
2144 unsigned
2145 iobuf_read_line( IOBUF a, byte **addr_of_buffer,
2146                           unsigned *length_of_buffer, unsigned *max_length )
2147 {
2148     int c;
2149     char *buffer = *addr_of_buffer;
2150     unsigned length = *length_of_buffer;
2151     unsigned nbytes = 0;
2152     unsigned maxlen = *max_length;
2153     char *p;
2154
2155     if( !buffer ) { /* must allocate a new buffer */
2156         length = 256;
2157         buffer = xmalloc( length );
2158         *addr_of_buffer = buffer;
2159         *length_of_buffer = length;
2160     }
2161
2162     length -= 3; /* reserve 3 bytes (cr,lf,eol) */
2163     p = buffer;
2164     while( (c=iobuf_get(a)) != -1 ) {
2165         if( nbytes == length ) { /* increase the buffer */
2166             if( length > maxlen  ) { /* this is out limit */
2167                 /* skip the rest of the line */
2168                 while( c != '\n' && (c=iobuf_get(a)) != -1 )
2169                     ;
2170                 *p++ = '\n'; /* always append a LF (we have reserved space) */
2171                 nbytes++;
2172                 *max_length = 0; /* indicate truncation */
2173                 break;
2174             }
2175             length += 3; /* correct for the reserved byte */
2176             length += length < 1024? 256 : 1024;
2177             buffer = xrealloc( buffer, length );
2178             *addr_of_buffer = buffer;
2179             *length_of_buffer = length;
2180             length -= 3; /* and reserve again */
2181             p = buffer + nbytes;
2182         }
2183         *p++ = c;
2184         nbytes++;
2185         if( c == '\n' )
2186             break;
2187     }
2188     *p = 0; /* make sure the line is a string */
2189
2190     return nbytes;
2191 }
2192
2193 /* This is the non iobuf specific function */
2194 int
2195 iobuf_translate_file_handle ( int fd, int for_write )
2196 {
2197 #ifdef _WIN32
2198     {
2199         int x;
2200             
2201         if  ( fd <= 2 )
2202             return fd; /* do not do this for error, stdin, stdout, stderr */
2203
2204         x = _open_osfhandle ( fd, for_write? 1:0 );
2205         if (x==-1 )
2206             log_error ("failed to translate osfhandle %p\n", (void*)fd );
2207         else {
2208             /*log_info ("_open_osfhandle %p yields %d%s\n",
2209               (void*)fd, x, for_write? " for writing":"" );*/
2210             fd = x;
2211         }
2212     }
2213 #endif
2214     return fd;
2215 }
2216
2217 static int
2218 translate_file_handle ( int fd, int for_write )
2219 {
2220 #ifdef _WIN32
2221 #ifdef FILE_FILTER_USES_STDIO  
2222     fd = iobuf_translate_file_handle (fd, for_write);
2223 #else
2224     {
2225         int x;
2226
2227         if  ( fd == 0 ) 
2228             x = (int)GetStdHandle (STD_INPUT_HANDLE);
2229         else if (fd == 1)    
2230             x = (int)GetStdHandle (STD_OUTPUT_HANDLE);
2231         else if (fd == 2)    
2232             x = (int)GetStdHandle (STD_ERROR_HANDLE);
2233         else
2234             x = fd;
2235
2236         if (x == -1)
2237             log_debug ("GetStdHandle(%d) failed: %s\n",
2238                        fd, w32_strerror (0));
2239
2240         fd = x;
2241     }
2242 #endif
2243 #endif
2244     return fd;
2245 }
2246
2247
2248 void
2249 iobuf_skip_rest(IOBUF a, unsigned long n, int partial)
2250 {
2251     if ( partial ) {
2252         for (;;) {
2253             if (a->nofast || a->d.start >= a->d.len) {
2254                 if (iobuf_readbyte (a) == -1) {
2255                     break;
2256                 }
2257             } else {
2258                 unsigned long count = a->d.len - a->d.start;
2259                 a->nbytes += count;
2260                 a->d.start = a->d.len;
2261             }
2262         }
2263     } else {
2264         unsigned long remaining = n;
2265         while (remaining > 0) {
2266             if (a->nofast || a->d.start >= a->d.len) {
2267                 if (iobuf_readbyte (a) == -1) {
2268                     break;
2269                 }
2270                 --remaining;
2271             } else {
2272                 unsigned long count = a->d.len - a->d.start;
2273                 if (count > remaining) {
2274                     count = remaining;
2275                 }
2276                 a->nbytes += count;
2277                 a->d.start += count;
2278                 remaining -= count;
2279             }
2280         }
2281     }
2282 }