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