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