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