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