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