~ubuntu-branches/ubuntu/dapper/gnupg2/dapper

« back to all changes in this revision

Viewing changes to util/iobuf.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Mueller
  • Date: 2005-03-29 10:30:32 UTC
  • Revision ID: james.westby@ubuntu.com-20050329103032-sj42n2ain3ipx310
Tags: upstream-1.9.15
ImportĀ upstreamĀ versionĀ 1.9.15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
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
}