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 <stdio.h> |
22 |
#include <stdlib.h> |
23 |
#include <string.h> |
24 |
#include <errno.h> |
25 |
#include <ctype.h> |
26 |
#include <assert.h> |
27 |
#include <sys/types.h> |
28 |
#include <sys/stat.h> |
29 |
#include <fcntl.h> |
30 |
#include <io.h> |
31 |
#include <windows.h> |
32 |
|
33 |
#include "openpgp.h" |
34 |
|
35 |
#define my_fileno(a) (a) |
36 |
#define my_fopen_ro(a,b) fd_cache_open ((a),(b)) |
37 |
#define my_fopen(a,b) direct_open ((a),(b)) |
38 |
typedef HANDLE FILEP_OR_FD; |
39 |
#define INVALID_FP ((HANDLE)-1) |
40 |
#define FILEP_OR_FD_FOR_STDIN (GetStdHandle (STD_INPUT_HANDLE)) |
41 |
#define FILEP_OR_FD_FOR_STDOUT (GetStdHandle (STD_OUTPUT_HANDLE)) |
42 |
#undef USE_SETMODE |
43 |
typedef struct { |
44 |
FILEP_OR_FD fp; /* open file handle */ |
45 |
int keep_open; |
46 |
int no_cache; |
47 |
int eof_seen; |
48 |
int print_only_name; /* flags indicating that fname is not a real file*/ |
49 |
char fname[1]; /* name of the file */ |
50 |
} file_filter_ctx_t ; |
51 |
|
52 |
struct close_cache_s { |
53 |
struct close_cache_s *next; |
54 |
FILEP_OR_FD fp; |
55 |
char fname[1]; |
56 |
}; |
57 |
typedef struct close_cache_s *CLOSE_CACHE; |
58 |
static CLOSE_CACHE close_cache; |
59 |
|
60 |
/* The first partial length header block must be of size 512 |
61 |
* to make it easier (and efficienter) we use a min. block size of 512 |
62 |
* for all chunks (but the last one) */ |
63 |
#define OP_MIN_PARTIAL_CHUNK 512 |
64 |
#define OP_MIN_PARTIAL_CHUNK_2POW 9 |
65 |
|
66 |
typedef struct { |
67 |
int use; |
68 |
size_t size; |
69 |
size_t count; |
70 |
int partial; /* 1 = partial header, 2 in last partial packet */ |
71 |
char *buffer; /* used for partial header */ |
72 |
size_t buflen; /* used size of buffer */ |
73 |
int first_c; /* of partial header (which is > 0)*/ |
74 |
int eof; |
75 |
} block_filter_ctx_t; |
76 |
|
77 |
static int special_names_enabled; |
78 |
|
79 |
static int underflow(gpg_iobuf_t a); |
80 |
static int translate_file_handle ( int fd, int for_write ); |
81 |
|
82 |
/* |
83 |
* Invalidate (i.e. close) a cached iobuf |
84 |
*/ |
85 |
static void |
86 |
fd_cache_invalidate (const char *fname) |
87 |
{ |
88 |
CLOSE_CACHE cc; |
89 |
|
90 |
assert (fname); |
91 |
|
92 |
for (cc=close_cache; cc; cc = cc->next ) { |
93 |
if ( cc->fp != INVALID_FP && !strcmp (cc->fname, fname) ) { |
94 |
CloseHandle (cc->fp); |
95 |
cc->fp = INVALID_FP; |
96 |
} |
97 |
} |
98 |
} |
99 |
|
100 |
static FILEP_OR_FD |
101 |
direct_open (const char *fname, const char *mode) |
102 |
{ |
103 |
unsigned long da, cd, sm; |
104 |
HANDLE hfile; |
105 |
|
106 |
/* Note, that we do not handle all mode combinations */ |
107 |
|
108 |
/* According to the ReactOS source it seems that open() of the |
109 |
* standard MSW32 crt does open the file in share mode which is |
110 |
* something new for MS applications ;-) |
111 |
*/ |
112 |
if ( strchr (mode, '+') ) { |
113 |
fd_cache_invalidate (fname); |
114 |
da = GENERIC_READ|GENERIC_WRITE; |
115 |
cd = OPEN_EXISTING; |
116 |
sm = FILE_SHARE_READ | FILE_SHARE_WRITE; |
117 |
} |
118 |
else if ( strchr (mode, 'w') ) { |
119 |
fd_cache_invalidate (fname); |
120 |
da = GENERIC_WRITE; |
121 |
cd = CREATE_ALWAYS; |
122 |
sm = FILE_SHARE_WRITE; |
123 |
} |
124 |
else { |
125 |
da = GENERIC_READ; |
126 |
cd = OPEN_EXISTING; |
127 |
sm = FILE_SHARE_READ; |
128 |
} |
129 |
|
130 |
hfile = CreateFile (fname, da, sm, NULL, cd, FILE_ATTRIBUTE_NORMAL, NULL); |
131 |
return hfile; |
132 |
} |
133 |
|
134 |
|
135 |
/* |
136 |
* Instead of closing an FD we keep it open and cache it for later reuse |
137 |
* Note that this caching strategy only works if the process does not chdir. |
138 |
*/ |
139 |
static void |
140 |
fd_cache_close (const char *fname, FILEP_OR_FD fp) |
141 |
{ |
142 |
CLOSE_CACHE cc; |
143 |
|
144 |
assert (fp); |
145 |
if ( !fname || !*fname ) { |
146 |
CloseHandle (fp); |
147 |
return; |
148 |
} |
149 |
/* try to reuse a slot */ |
150 |
for (cc=close_cache; cc; cc = cc->next ) { |
151 |
if ( cc->fp == INVALID_FP && !strcmp (cc->fname, fname) ) { |
152 |
cc->fp = fp; |
153 |
return; |
154 |
} |
155 |
} |
156 |
/* add a new one */ |
157 |
cc = calloc (1, sizeof *cc + strlen (fname)); |
158 |
strcpy (cc->fname, fname); |
159 |
cc->fp = fp; |
160 |
cc->next = close_cache; |
161 |
close_cache = cc; |
162 |
} |
163 |
|
164 |
/* |
165 |
* Do an direct_open on FNAME but first try to reuse one from the fd_cache |
166 |
*/ |
167 |
static FILEP_OR_FD |
168 |
fd_cache_open (const char *fname, const char *mode) |
169 |
{ |
170 |
CLOSE_CACHE cc; |
171 |
|
172 |
assert (fname); |
173 |
for (cc=close_cache; cc; cc = cc->next ) { |
174 |
if ( cc->fp != INVALID_FP && !strcmp (cc->fname, fname) ) { |
175 |
FILEP_OR_FD fp = cc->fp; |
176 |
cc->fp = INVALID_FP; |
177 |
if (SetFilePointer (fp, 0, NULL, FILE_BEGIN) == 0xffffffff ) { |
178 |
printf ("rewind file failed on handle %p: ec=%d\n", |
179 |
fp, (int)GetLastError () ); |
180 |
fp = INVALID_FP; |
181 |
} |
182 |
return fp; |
183 |
} |
184 |
} |
185 |
return direct_open (fname, mode); |
186 |
} |
187 |
|
188 |
|
189 |
/**************** |
190 |
* Read data from a file into buf which has an allocated length of *LEN. |
191 |
* return the number of read bytes in *LEN. OPAQUE is the FILE * of |
192 |
* the stream. A is not used. |
193 |
* control may be: |
194 |
* IOBUFCTRL_INIT: called just before the function is linked into the |
195 |
* list of function. This can be used to prepare internal |
196 |
* data structures of the function. |
197 |
* IOBUFCTRL_FREE: called just before the function is removed from the |
198 |
* list of functions and can be used to release internal |
199 |
* data structures or close a file etc. |
200 |
* IOBUFCTRL_UNDERFLOW: called by iobuf_underflow to fill the buffer |
201 |
* with new stuff. *RET_LEN is the available size of the |
202 |
* buffer, and should be set to the number of bytes |
203 |
* which were put into the buffer. The function |
204 |
* returns 0 to indicate success, -1 on EOF and |
205 |
* G10ERR_xxxxx for other errors. |
206 |
* |
207 |
* IOBUFCTRL_FLUSH: called by iobuf_flush() to write out the collected stuff. |
208 |
* *RET_LAN is the number of bytes in BUF. |
209 |
* |
210 |
* IOBUFCTRL_CANCEL: send to all filters on behalf of iobuf_cancel. The |
211 |
* filter may take appropriate action on this message. |
212 |
*/ |
213 |
static int |
214 |
file_filter(void *opaque, int control, gpg_iobuf_t chain, byte *buf, size_t *ret_len) |
215 |
{ |
216 |
file_filter_ctx_t *a = opaque; |
217 |
FILEP_OR_FD f = a->fp; |
218 |
size_t size = *ret_len; |
219 |
size_t nbytes = 0; |
220 |
int rc = 0; |
221 |
|
222 |
if( control == IOBUFCTRL_UNDERFLOW ) { |
223 |
assert( size ); /* need a buffer */ |
224 |
if ( a->eof_seen) { |
225 |
rc = -1; |
226 |
*ret_len = 0; |
227 |
} |
228 |
else { |
229 |
unsigned long nread; |
230 |
|
231 |
nbytes = 0; |
232 |
if ( !ReadFile ( f, buf, size, &nread, NULL ) ) { |
233 |
int ec = (int)GetLastError (); |
234 |
if ( ec != ERROR_BROKEN_PIPE ) { |
235 |
printf("%s: read error: ec=%d\n", a->fname, ec); |
236 |
rc = G10ERR_READ_FILE; |
237 |
} |
238 |
} |
239 |
else if ( !nread ) { |
240 |
a->eof_seen = 1; |
241 |
rc = -1; |
242 |
} |
243 |
else { |
244 |
nbytes = nread; |
245 |
} |
246 |
*ret_len = nbytes; |
247 |
} |
248 |
} |
249 |
else if( control == IOBUFCTRL_FLUSH ) { |
250 |
if( size ) { |
251 |
byte *p = buf; |
252 |
unsigned long n; |
253 |
|
254 |
nbytes = size; |
255 |
do { |
256 |
if ( size && !WriteFile ( f, p, nbytes, &n, NULL) ) { |
257 |
int ec = (int)GetLastError (); |
258 |
printf("%s: write error: ec=%d\n", a->fname, ec); |
259 |
rc = G10ERR_WRITE_FILE; |
260 |
break; |
261 |
} |
262 |
p += n; |
263 |
nbytes -= n; |
264 |
} while ( nbytes ); |
265 |
nbytes = p - buf; |
266 |
} |
267 |
*ret_len = nbytes; |
268 |
} |
269 |
else if ( control == IOBUFCTRL_INIT ) { |
270 |
a->eof_seen = 0; |
271 |
a->keep_open = 0; |
272 |
a->no_cache = 0; |
273 |
} |
274 |
else if ( control == IOBUFCTRL_DESC ) { |
275 |
*(char**)buf = "file_filter(fd)"; |
276 |
} |
277 |
else if ( control == IOBUFCTRL_FREE ) { |
278 |
if ( f != FILEP_OR_FD_FOR_STDIN && f != FILEP_OR_FD_FOR_STDOUT ) { |
279 |
if (!a->keep_open) |
280 |
fd_cache_close (a->no_cache?NULL:a->fname, f); |
281 |
} |
282 |
safe_free (a); /* we can free our context now */ |
283 |
} |
284 |
return rc; |
285 |
} |
286 |
|
287 |
/**************** |
288 |
* This is used to implement the block write mode. |
289 |
* Block reading is done on a byte by byte basis in readbyte(), |
290 |
* without a filter |
291 |
*/ |
292 |
static int |
293 |
block_filter(void *opaque, int control, gpg_iobuf_t chain, byte *buf, size_t *ret_len) |
294 |
{ |
295 |
block_filter_ctx_t *a = opaque; |
296 |
size_t size = *ret_len; |
297 |
int c, needed, rc = 0; |
298 |
char *p; |
299 |
|
300 |
if( control == IOBUFCTRL_UNDERFLOW ) { |
301 |
size_t n=0; |
302 |
|
303 |
p = buf; |
304 |
assert( size ); /* need a buffer */ |
305 |
if( a->eof ) /* don't read any further */ |
306 |
rc = -1; |
307 |
while( !rc && size ) { |
308 |
if( !a->size ) { /* get the length bytes */ |
309 |
if( a->partial == 2 ) { |
310 |
a->eof = 1; |
311 |
if( !n ) |
312 |
rc = -1; |
313 |
break; |
314 |
} |
315 |
else if( a->partial ) { |
316 |
/* These OpenPGP introduced huffman like encoded length |
317 |
* bytes are really a mess :-( */ |
318 |
if( a->first_c ) { |
319 |
c = a->first_c; |
320 |
a->first_c = 0; |
321 |
} |
322 |
else if( (c = gpg_iobuf_get(chain)) == -1 ) { |
323 |
printf("block_filter: 1st length byte missing\n"); |
324 |
rc = G10ERR_READ_FILE; |
325 |
break; |
326 |
} |
327 |
if( c < 192 ) { |
328 |
a->size = c; |
329 |
a->partial = 2; |
330 |
if( !a->size ) { |
331 |
a->eof = 1; |
332 |
if( !n ) |
333 |
rc = -1; |
334 |
break; |
335 |
} |
336 |
} |
337 |
else if( c < 224 ) { |
338 |
a->size = (c - 192) * 256; |
339 |
if( (c = gpg_iobuf_get(chain)) == -1 ) { |
340 |
printf("block_filter: 2nd length byte missing\n"); |
341 |
rc = G10ERR_READ_FILE; |
342 |
break; |
343 |
} |
344 |
a->size += c + 192; |
345 |
a->partial = 2; |
346 |
if( !a->size ) { |
347 |
a->eof = 1; |
348 |
if( !n ) |
349 |
rc = -1; |
350 |
break; |
351 |
} |
352 |
} |
353 |
else if( c == 255 ) { |
354 |
a->size = gpg_iobuf_get(chain) << 24; |
355 |
a->size |= gpg_iobuf_get(chain) << 16; |
356 |
a->size |= gpg_iobuf_get(chain) << 8; |
357 |
if( (c = gpg_iobuf_get(chain)) == -1 ) { |
358 |
printf("block_filter: invalid 4 byte length\n"); |
359 |
rc = G10ERR_READ_FILE; |
360 |
break; |
361 |
} |
362 |
a->size |= c; |
363 |
} |
364 |
else { /* next partial body length */ |
365 |
a->size = 1 << (c & 0x1f); |
366 |
} |
367 |
/* printf("partial: ctx=%p c=%02x size=%u\n", a, c, a->size);*/ |
368 |
} |
369 |
else { /* the gnupg partial length scheme - much better :-) */ |
370 |
c = gpg_iobuf_get(chain); |
371 |
a->size = c << 8; |
372 |
c = gpg_iobuf_get(chain); |
373 |
a->size |= c; |
374 |
if( c == -1 ) { |
375 |
printf("block_filter: error reading length info\n"); |
376 |
rc = G10ERR_READ_FILE; |
377 |
} |
378 |
if( !a->size ) { |
379 |
a->eof = 1; |
380 |
if( !n ) |
381 |
rc = -1; |
382 |
break; |
383 |
} |
384 |
} |
385 |
} |
386 |
|
387 |
while( !rc && size && a->size ) { |
388 |
needed = size < a->size ? size : a->size; |
389 |
c = gpg_iobuf_read( chain, p, needed ); |
390 |
if( c < needed ) { |
391 |
if( c == -1 ) c = 0; |
392 |
printf("block_filter %p: read error (size=%lu,a->size=%lu)\n", |
393 |
a, (ulong)size+c, (ulong)a->size+c); |
394 |
rc = G10ERR_READ_FILE; |
395 |
} |
396 |
else { |
397 |
size -= c; |
398 |
a->size -= c; |
399 |
p += c; |
400 |
n += c; |
401 |
} |
402 |
} |
403 |
} |
404 |
*ret_len = n; |
405 |
} |
406 |
else if( control == IOBUFCTRL_FLUSH ) { |
407 |
if( a->partial ) { /* the complicated openpgp scheme */ |
408 |
size_t blen, n, nbytes = size + a->buflen; |
409 |
|
410 |
assert( a->buflen <= OP_MIN_PARTIAL_CHUNK ); |
411 |
if( nbytes < OP_MIN_PARTIAL_CHUNK ) { |
412 |
/* not enough to write a partial block out; so we store it*/ |
413 |
if( !a->buffer ) |
414 |
a->buffer = malloc( OP_MIN_PARTIAL_CHUNK ); |
415 |
memcpy( a->buffer + a->buflen, buf, size ); |
416 |
a->buflen += size; |
417 |
} |
418 |
else { /* okay, we can write out something */ |
419 |
/* do this in a loop to use the most efficient block lengths */ |
420 |
p = buf; |
421 |
do { |
422 |
/* find the best matching block length - this is limited |
423 |
* by the size of the internal buffering */ |
424 |
for( blen=OP_MIN_PARTIAL_CHUNK*2, |
425 |
c=OP_MIN_PARTIAL_CHUNK_2POW+1; blen <= nbytes; |
426 |
blen *=2, c++ ) |
427 |
; |
428 |
blen /= 2; c--; |
429 |
/* write the partial length header */ |
430 |
assert( c <= 0x1f ); /*;-)*/ |
431 |
c |= 0xe0; |
432 |
gpg_iobuf_put( chain, c ); |
433 |
if( (n=a->buflen) ) { /* write stuff from the buffer */ |
434 |
assert( n == OP_MIN_PARTIAL_CHUNK); |
435 |
if( gpg_iobuf_write(chain, a->buffer, n ) ) |
436 |
rc = G10ERR_WRITE_FILE; |
437 |
a->buflen = 0; |
438 |
nbytes -= n; |
439 |
} |
440 |
if( (n = nbytes) > blen ) |
441 |
n = blen; |
442 |
if( n && gpg_iobuf_write(chain, p, n ) ) |
443 |
rc = G10ERR_WRITE_FILE; |
444 |
p += n; |
445 |
nbytes -= n; |
446 |
} while( !rc && nbytes >= OP_MIN_PARTIAL_CHUNK ); |
447 |
/* store the rest in the buffer */ |
448 |
if( !rc && nbytes ) { |
449 |
assert( !a->buflen ); |
450 |
assert( nbytes < OP_MIN_PARTIAL_CHUNK ); |
451 |
if( !a->buffer ) |
452 |
a->buffer = malloc( OP_MIN_PARTIAL_CHUNK ); |
453 |
memcpy( a->buffer, p, nbytes ); |
454 |
a->buflen = nbytes; |
455 |
} |
456 |
} |
457 |
} |
458 |
else { /* the gnupg scheme (which is not openpgp compliant) */ |
459 |
size_t avail, n; |
460 |
|
461 |
for(p=buf; !rc && size; ) { |
462 |
n = size; |
463 |
avail = a->size - a->count; |
464 |
if( !avail ) { |
465 |
if( n > a->size ) { |
466 |
gpg_iobuf_put( chain, (a->size >> 8) & 0xff ); |
467 |
gpg_iobuf_put( chain, a->size & 0xff ); |
468 |
avail = a->size; |
469 |
a->count = 0; |
470 |
} |
471 |
else { |
472 |
gpg_iobuf_put( chain, (n >> 8) & 0xff ); |
473 |
gpg_iobuf_put( chain, n & 0xff ); |
474 |
avail = n; |
475 |
a->count = a->size - n; |
476 |
} |
477 |
} |
478 |
if( n > avail ) |
479 |
n = avail; |
480 |
if( gpg_iobuf_write(chain, p, n ) ) |
481 |
rc = G10ERR_WRITE_FILE; |
482 |
a->count += n; |
483 |
p += n; |
484 |
size -= n; |
485 |
} |
486 |
} |
487 |
} |
488 |
else if( control == IOBUFCTRL_INIT ) { |
489 |
if( a->partial ) |
490 |
a->count = 0; |
491 |
else if( a->use == 1 ) |
492 |
a->count = a->size = 0; |
493 |
else |
494 |
a->count = a->size; /* force first length bytes */ |
495 |
a->eof = 0; |
496 |
a->buffer = NULL; |
497 |
a->buflen = 0; |
498 |
} |
499 |
else if( control == IOBUFCTRL_DESC ) { |
500 |
*(char**)buf = "block_filter"; |
501 |
} |
502 |
else if( control == IOBUFCTRL_FREE ) { |
503 |
if( a->use == 2 ) { /* write the end markers */ |
504 |
if( a->partial ) { |
505 |
u32 len; |
506 |
/* write out the remaining bytes without a partial header |
507 |
* the length of this header may be 0 - but if it is |
508 |
* the first block we are not allowed to use a partial header |
509 |
* and frankly we can't do so, because this length must be |
510 |
* a power of 2. This is _really_ complicated because we |
511 |
* have to check the possible length of a packet prior |
512 |
* to it's creation: a chain of filters becomes complicated |
513 |
* and we need a lot of code to handle compressed packets etc. |
514 |
* :-((((((( |
515 |
*/ |
516 |
/* construct header */ |
517 |
len = a->buflen; |
518 |
/*printf("partial: remaining length=%u\n", len );*/ |
519 |
if( len < 192 ) |
520 |
rc = gpg_iobuf_put(chain, len ); |
521 |
else if( len < 8384 ) { |
522 |
if( !(rc=gpg_iobuf_put( chain, ((len-192) / 256) + 192)) ) |
523 |
rc = gpg_iobuf_put( chain, ((len-192) % 256)); |
524 |
} |
525 |
else { /* use a 4 byte header */ |
526 |
if( !(rc=gpg_iobuf_put( chain, 0xff )) ) |
527 |
if( !(rc=gpg_iobuf_put( chain, (len >> 24)&0xff )) ) |
528 |
if( !(rc=gpg_iobuf_put( chain, (len >> 16)&0xff )) ) |
529 |
if( !(rc=gpg_iobuf_put( chain, (len >> 8)&0xff ))) |
530 |
rc=gpg_iobuf_put( chain, len & 0xff ); |
531 |
} |
532 |
if( !rc && len ) |
533 |
rc = gpg_iobuf_write(chain, a->buffer, len ); |
534 |
if( rc ) { |
535 |
printf("block_filter: write error: %s\n",strerror(errno)); |
536 |
rc = G10ERR_WRITE_FILE; |
537 |
} |
538 |
safe_free( a->buffer ); a->buffer = NULL; a->buflen = 0; |
539 |
} |
540 |
else { |
541 |
gpg_iobuf_writebyte(chain, 0); |
542 |
gpg_iobuf_writebyte(chain, 0); |
543 |
} |
544 |
} |
545 |
else if( a->size ) { |
546 |
printf("block_filter: pending bytes!\n"); |
547 |
} |
548 |
safe_free(a); /* we can free our context now */ |
549 |
} |
550 |
|
551 |
return rc; |
552 |
} |
553 |
|
554 |
/**************** |
555 |
* Allocate a new io buffer, with no function assigned. |
556 |
* Use is the desired usage: 1 for input, 2 for output, 3 for temp buffer |
557 |
* BUFSIZE is a suggested buffer size. |
558 |
*/ |
559 |
gpg_iobuf_t |
560 |
gpg_iobuf_alloc(int use, size_t bufsize) |
561 |
{ |
562 |
gpg_iobuf_t a; |
563 |
static int number=0; |
564 |
|
565 |
a = calloc(1, sizeof *a); |
566 |
a->use = use; |
567 |
a->d.buf = malloc( bufsize ); |
568 |
a->d.size = bufsize; |
569 |
a->no = ++number; |
570 |
a->subno = 0; |
571 |
a->opaque = NULL; |
572 |
a->real_fname = NULL; |
573 |
return a; |
574 |
} |
575 |
|
576 |
int |
577 |
gpg_iobuf_close( gpg_iobuf_t a ) |
578 |
{ |
579 |
gpg_iobuf_t a2; |
580 |
size_t dummy_len=0; |
581 |
int rc=0; |
582 |
|
583 |
if( a && a->directfp ) { |
584 |
fclose( a->directfp ); |
585 |
safe_free( a->real_fname ); |
586 |
return 0; |
587 |
} |
588 |
|
589 |
for( ; a && !rc ; a = a2 ) { |
590 |
a2 = a->chain; |
591 |
if( a->use == 2 && (rc=gpg_iobuf_flush(a)) ) |
592 |
printf("iobuf_flush failed on close\n"); |
593 |
if( a->filter && (rc = a->filter(a->filter_ov, IOBUFCTRL_FREE, |
594 |
a->chain, NULL, &dummy_len)) ) |
595 |
printf("IOBUFCTRL_FREE failed on close\n"); |
596 |
safe_free(a->real_fname); |
597 |
if (a->d.buf) { |
598 |
memset (a->d.buf, 0, a->d.size); /* erase the buffer */ |
599 |
safe_free(a->d.buf); |
600 |
} |
601 |
safe_free(a); |
602 |
} |
603 |
|
604 |
return rc; |
605 |
} |
606 |
|
607 |
int |
608 |
gpg_iobuf_cancel( gpg_iobuf_t a ) |
609 |
{ |
610 |
const char *s; |
611 |
gpg_iobuf_t a2; |
612 |
int rc; |
613 |
char *remove_name = NULL; |
614 |
|
615 |
if( a && a->use == 2 ) { |
616 |
s = gpg_iobuf_get_real_fname(a); |
617 |
if( s && *s ) { |
618 |
remove_name = strdup ( s ); |
619 |
} |
620 |
} |
621 |
|
622 |
/* send a cancel message to all filters */ |
623 |
for( a2 = a; a2 ; a2 = a2->chain ) { |
624 |
size_t dummy; |
625 |
if( a2->filter ) |
626 |
a2->filter( a2->filter_ov, IOBUFCTRL_CANCEL, a2->chain, |
627 |
NULL, &dummy ); |
628 |
} |
629 |
|
630 |
rc = gpg_iobuf_close(a); |
631 |
if ( remove_name ) { |
632 |
/* Argg, MSDOS does not allow to remove open files. So |
633 |
* we have to do it here */ |
634 |
remove ( remove_name ); |
635 |
safe_free ( remove_name ); |
636 |
} |
637 |
return rc; |
638 |
} |
639 |
|
640 |
|
641 |
/**************** |
642 |
* create a temporary iobuf, which can be used to collect stuff |
643 |
* in an iobuf and later be written by iobuf_write_temp() to another |
644 |
* iobuf. |
645 |
*/ |
646 |
gpg_iobuf_t |
647 |
gpg_iobuf_temp( void ) |
648 |
{ |
649 |
gpg_iobuf_t a; |
650 |
|
651 |
a = gpg_iobuf_alloc(3, 8192 ); |
652 |
|
653 |
return a; |
654 |
} |
655 |
|
656 |
gpg_iobuf_t |
657 |
gpg_iobuf_temp_with_content( const char *buffer, size_t length ) |
658 |
{ |
659 |
gpg_iobuf_t a; |
660 |
|
661 |
a = gpg_iobuf_alloc(3, length ); |
662 |
memcpy( a->d.buf, buffer, length ); |
663 |
a->d.len = length; |
664 |
|
665 |
return a; |
666 |
} |
667 |
|
668 |
void |
669 |
gpg_iobuf_enable_special_filenames ( int yes ) |
670 |
{ |
671 |
special_names_enabled = yes; |
672 |
} |
673 |
|
674 |
/* |
675 |
* see whether the filename has the for "-&nnnn", where n is a |
676 |
* non-zero number. |
677 |
* Returns this number or -1 if it is not the case. |
678 |
*/ |
679 |
static int |
680 |
check_special_filename ( const char *fname ) |
681 |
{ |
682 |
if ( special_names_enabled |
683 |
&& fname && *fname == '-' && fname[1] == '&' ) { |
684 |
int i; |
685 |
|
686 |
fname += 2; |
687 |
for (i=0; isdigit (fname[i]); i++ ) |
688 |
; |
689 |
if ( !fname[i] ) |
690 |
return atoi (fname); |
691 |
} |
692 |
return -1; |
693 |
} |
694 |
|
695 |
/**************** |
696 |
* Create a head iobuf for reading from a file |
697 |
* returns: NULL if an error occures and sets errno |
698 |
*/ |
699 |
gpg_iobuf_t |
700 |
gpg_iobuf_open( const char *fname ) |
701 |
{ |
702 |
gpg_iobuf_t a; |
703 |
FILEP_OR_FD fp; |
704 |
file_filter_ctx_t *fcx; |
705 |
size_t len; |
706 |
int print_only = 0; |
707 |
int fd; |
708 |
|
709 |
if( !fname || (*fname=='-' && !fname[1]) ) { |
710 |
fp = FILEP_OR_FD_FOR_STDIN; |
711 |
//setmode ( my_fileno(fp) , O_BINARY ); |
712 |
fname = "[stdin]"; |
713 |
print_only = 1; |
714 |
} |
715 |
else if ( (fd = check_special_filename ( fname )) != -1 ) |
716 |
return gpg_iobuf_fdopen ( translate_file_handle (fd,0), "rb" ); |
717 |
else if( (fp = my_fopen_ro(fname, "rb")) == INVALID_FP ) |
718 |
return NULL; |
719 |
a = gpg_iobuf_alloc(1, 8192 ); |
720 |
fcx = malloc( sizeof *fcx + strlen(fname) ); |
721 |
fcx->fp = fp; |
722 |
fcx->print_only_name = print_only; |
723 |
strcpy(fcx->fname, fname ); |
724 |
if( !print_only ) |
725 |
a->real_fname = strdup( fname ); |
726 |
a->filter = file_filter; |
727 |
a->filter_ov = fcx; |
728 |
file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len ); |
729 |
file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len ); |
730 |
|
731 |
return a; |
732 |
} |
733 |
|
734 |
/**************** |
735 |
* Create a head iobuf for reading from a file |
736 |
* returns: NULL if an error occures and sets errno |
737 |
*/ |
738 |
gpg_iobuf_t |
739 |
gpg_iobuf_fdopen( int fd, const char *mode ) |
740 |
{ |
741 |
gpg_iobuf_t a; |
742 |
FILEP_OR_FD fp; |
743 |
file_filter_ctx_t *fcx; |
744 |
size_t len; |
745 |
|
746 |
fp = (FILEP_OR_FD)fd; |
747 |
a = gpg_iobuf_alloc( strchr( mode, 'w')? 2:1, 8192 ); |
748 |
fcx = malloc( sizeof *fcx + 20 ); |
749 |
fcx->fp = fp; |
750 |
fcx->print_only_name = 1; |
751 |
sprintf(fcx->fname, "[fd %d]", fd ); |
752 |
a->filter = file_filter; |
753 |
a->filter_ov = fcx; |
754 |
file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len ); |
755 |
file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len ); |
756 |
gpg_iobuf_ioctl (a,3,1,NULL); /* disable fd caching */ |
757 |
return a; |
758 |
} |
759 |
|
760 |
/**************** |
761 |
* create an iobuf for writing to a file; the file will be created. |
762 |
*/ |
763 |
gpg_iobuf_t |
764 |
gpg_iobuf_create( const char *fname ) |
765 |
{ |
766 |
gpg_iobuf_t a; |
767 |
FILEP_OR_FD fp; |
768 |
file_filter_ctx_t *fcx; |
769 |
size_t len; |
770 |
int print_only = 0; |
771 |
int fd; |
772 |
|
773 |
if( !fname || (*fname=='-' && !fname[1]) ) { |
774 |
fp = FILEP_OR_FD_FOR_STDOUT; |
775 |
fname = "[stdout]"; |
776 |
print_only = 1; |
777 |
} |
778 |
else if ( (fd = check_special_filename ( fname )) != -1 ) |
779 |
return gpg_iobuf_fdopen ( translate_file_handle (fd, 1), "wb" ); |
780 |
else if( (fp = my_fopen(fname, "wb")) == INVALID_FP ) |
781 |
return NULL; |
782 |
a = gpg_iobuf_alloc(2, 8192 ); |
783 |
fcx = malloc( sizeof *fcx + strlen(fname) ); |
784 |
fcx->fp = fp; |
785 |
fcx->print_only_name = print_only; |
786 |
strcpy(fcx->fname, fname ); |
787 |
if( !print_only ) |
788 |
a->real_fname = strdup( fname ); |
789 |
a->filter = file_filter; |
790 |
a->filter_ov = fcx; |
791 |
file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len ); |
792 |
file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len ); |
793 |
|
794 |
return a; |
795 |
} |
796 |
|
797 |
gpg_iobuf_t |
798 |
gpg_iobuf_openrw( const char *fname ) |
799 |
{ |
800 |
gpg_iobuf_t a; |
801 |
FILEP_OR_FD fp; |
802 |
file_filter_ctx_t *fcx; |
803 |
size_t len; |
804 |
|
805 |
if( !fname ) |
806 |
return NULL; |
807 |
else if( (fp = my_fopen(fname, "r+b")) == INVALID_FP ) |
808 |
return NULL; |
809 |
a = gpg_iobuf_alloc(2, 8192 ); |
810 |
fcx = malloc( sizeof *fcx + strlen(fname) ); |
811 |
fcx->fp = fp; |
812 |
strcpy(fcx->fname, fname ); |
813 |
a->real_fname = strdup( fname ); |
814 |
a->filter = file_filter; |
815 |
a->filter_ov = fcx; |
816 |
file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len ); |
817 |
file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len ); |
818 |
|
819 |
return a; |
820 |
} |
821 |
|
822 |
|
823 |
int |
824 |
gpg_iobuf_ioctl ( gpg_iobuf_t a, int cmd, int intval, void *ptrval ) |
825 |
{ |
826 |
if ( cmd == 1 ) { /* keep system filepointer/descriptor open */ |
827 |
for( ; a; a = a->chain ) |
828 |
if( !a->chain && a->filter == file_filter ) { |
829 |
file_filter_ctx_t *b = a->filter_ov; |
830 |
b->keep_open = intval; |
831 |
return 0; |
832 |
} |
833 |
} |
834 |
else if ( cmd == 2 ) { /* invalidate cache */ |
835 |
if ( !a && !intval && ptrval ) { |
836 |
fd_cache_invalidate (ptrval); |
837 |
return 0; |
838 |
} |
839 |
} |
840 |
else if ( cmd == 3 ) { /* disallow/allow caching */ |
841 |
for( ; a; a = a->chain ) |
842 |
if( !a->chain && a->filter == file_filter ) { |
843 |
file_filter_ctx_t *b = a->filter_ov; |
844 |
b->no_cache = intval; |
845 |
return 0; |
846 |
} |
847 |
} |
848 |
|
849 |
return -1; |
850 |
} |
851 |
|
852 |
|
853 |
/**************** |
854 |
* Register an i/o filter. |
855 |
*/ |
856 |
int |
857 |
gpg_iobuf_push_filter( gpg_iobuf_t a, |
858 |
int (*f)(void *opaque, int control, |
859 |
gpg_iobuf_t chain, byte *buf, size_t *len), void *ov ) |
860 |
{ |
861 |
return gpg_iobuf_push_filter2( a, f, ov, 0 ); |
862 |
} |
863 |
|
864 |
int |
865 |
gpg_iobuf_push_filter2( gpg_iobuf_t a, |
866 |
int (*f)(void *opaque, int control, |
867 |
gpg_iobuf_t chain, byte *buf, size_t *len), |
868 |
void *ov, int rel_ov ) |
869 |
{ |
870 |
gpg_iobuf_t b; |
871 |
size_t dummy_len=0; |
872 |
int rc=0; |
873 |
|
874 |
if( a->directfp ) { |
875 |
printf( "This is a BUG.\n%s:%d\n", __FILE__, __LINE__ ); |
876 |
exit( -1 ); |
877 |
} |
878 |
|
879 |
if( a->use == 2 && (rc=gpg_iobuf_flush(a)) ) |
880 |
return rc; |
881 |
/* make a copy of the current stream, so that |
882 |
* A is the new stream and B the original one. |
883 |
* The contents of the buffers are transferred to the |
884 |
* new stream. |
885 |
*/ |
886 |
b = malloc(sizeof *b); |
887 |
memcpy(b, a, sizeof *b ); |
888 |
/* fixme: it is stupid to keep a copy of the name at every level |
889 |
* but we need the name somewhere because the name known by file_filter |
890 |
* may have been released when we need the name of the file */ |
891 |
b->real_fname = a->real_fname? strdup(a->real_fname):NULL; |
892 |
/* remove the filter stuff from the new stream */ |
893 |
a->filter = NULL; |
894 |
a->filter_ov = NULL; |
895 |
a->filter_ov_owner = 0; |
896 |
a->filter_eof = 0; |
897 |
if( a->use == 3 ) |
898 |
a->use = 2; /* make a write stream from a temp stream */ |
899 |
|
900 |
if( a->use == 2 ) { /* allocate a fresh buffer for the original stream */ |
901 |
b->d.buf = malloc( a->d.size ); |
902 |
b->d.len = 0; |
903 |
b->d.start = 0; |
904 |
} |
905 |
else { /* allocate a fresh buffer for the new stream */ |
906 |
a->d.buf = malloc( a->d.size ); |
907 |
a->d.len = 0; |
908 |
a->d.start = 0; |
909 |
} |
910 |
/* disable nlimit for the new stream */ |
911 |
a->ntotal = b->ntotal + b->nbytes; |
912 |
a->nlimit = a->nbytes = 0; |
913 |
a->nofast &= ~1; |
914 |
/* make a link from the new stream to the original stream */ |
915 |
a->chain = b; |
916 |
a->opaque = b->opaque; |
917 |
|
918 |
/* setup the function on the new stream */ |
919 |
a->filter = f; |
920 |
a->filter_ov = ov; |
921 |
a->filter_ov_owner = rel_ov; |
922 |
|
923 |
a->subno = b->subno + 1; |
924 |
f( ov, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &dummy_len ); |
925 |
|
926 |
/* now we can initialize the new function if we have one */ |
927 |
if( a->filter && (rc = a->filter(a->filter_ov, IOBUFCTRL_INIT, a->chain, |
928 |
NULL, &dummy_len)) ) |
929 |
printf("IOBUFCTRL_INIT failed\n"); |
930 |
return rc; |
931 |
} |
932 |
|
933 |
/**************** |
934 |
* Remove an i/o filter. |
935 |
*/ |
936 |
int |
937 |
pop_filter( gpg_iobuf_t a, int (*f)(void *opaque, int control, |
938 |
gpg_iobuf_t chain, byte *buf, size_t *len), void *ov ) |
939 |
{ |
940 |
gpg_iobuf_t b; |
941 |
size_t dummy_len=0; |
942 |
int rc=0; |
943 |
|
944 |
if( a->directfp ) { |
945 |
printf( "This is a BUG.\n%s:%d\n", __FILE__, __LINE__ ); |
946 |
exit( -1 ); |
947 |
} |
948 |
|
949 |
if( !a->filter ) { /* this is simple */ |
950 |
b = a->chain; |
951 |
assert(b); |
952 |
safe_free(a->d.buf); |
953 |
safe_free(a->real_fname); |
954 |
memcpy(a,b, sizeof *a); |
955 |
safe_free(b); |
956 |
return 0; |
957 |
} |
958 |
for(b=a ; b; b = b->chain ) |
959 |
if( b->filter == f && (!ov || b->filter_ov == ov) ) |
960 |
break; |
961 |
if( !b ) |
962 |
printf("pop_filter(): filter function not found\n"); |
963 |
|
964 |
/* flush this stream if it is an output stream */ |
965 |
if( a->use == 2 && (rc=gpg_iobuf_flush(b)) ) { |
966 |
printf("iobuf_flush failed in pop_filter\n"); |
967 |
return rc; |
968 |
} |
969 |
/* and tell the filter to free it self */ |
970 |
if( b->filter && (rc = b->filter(b->filter_ov, IOBUFCTRL_FREE, b->chain, |
971 |
NULL, &dummy_len)) ) { |
972 |
printf("IOBUFCTRL_FREE failed\n"); |
973 |
return rc; |
974 |
} |
975 |
if( b->filter_ov && b->filter_ov_owner ) { |
976 |
safe_free( b->filter_ov ); |
977 |
b->filter_ov = NULL; |
978 |
} |
979 |
|
980 |
|
981 |
/* and see how to remove it */ |
982 |
if( a == b && !b->chain ) |
983 |
printf("can't remove the last filter from the chain\n"); |
984 |
else if( a == b ) { /* remove the first iobuf from the chain */ |
985 |
/* everything from b is copied to a. This is save because |
986 |
* a flush has been done on the to be removed entry |
987 |
*/ |
988 |
b = a->chain; |
989 |
safe_free(a->d.buf); |
990 |
safe_free(a->real_fname); |
991 |
memcpy(a,b, sizeof *a); |
992 |
safe_free(b); |
993 |
} |
994 |
else if( !b->chain ) { /* remove the last iobuf from the chain */ |
995 |
printf("Ohh jeee, trying to remove a head filter\n"); |
996 |
} |
997 |
else { /* remove an intermediate iobuf from the chain */ |
998 |
printf("Ohh jeee, trying to remove an intermediate filter\n"); |
999 |
} |
1000 |
|
1001 |
return rc; |
1002 |
} |
1003 |
|
1004 |
|
1005 |
/**************** |
1006 |
* read underflow: read more bytes into the buffer and return |
1007 |
* the first byte or -1 on EOF. |
1008 |
*/ |
1009 |
static int |
1010 |
underflow(gpg_iobuf_t a) |
1011 |
{ |
1012 |
size_t len; |
1013 |
int rc; |
1014 |
|
1015 |
assert( a->d.start == a->d.len ); |
1016 |
if( a->use == 3 ) |
1017 |
return -1; /* EOF because a temp buffer can't do an underflow */ |
1018 |
|
1019 |
if( a->filter_eof ) { |
1020 |
if( a->chain ) { |
1021 |
gpg_iobuf_t b = a->chain; |
1022 |
safe_free(a->d.buf); |
1023 |
safe_free(a->real_fname); |
1024 |
memcpy(a, b, sizeof *a); |
1025 |
safe_free(b); |
1026 |
} |
1027 |
else |
1028 |
a->filter_eof = 0; /* for the top level filter */ |
1029 |
return -1; /* return one(!) EOF */ |
1030 |
} |
1031 |
if( a->error ) { |
1032 |
return -1; |
1033 |
} |
1034 |
|
1035 |
if( a->directfp ) { |
1036 |
FILE *fp = a->directfp; |
1037 |
|
1038 |
len = fread( a->d.buf, 1, a->d.size, fp); |
1039 |
if( len < a->d.size ) { |
1040 |
if( ferror(fp) ) |
1041 |
a->error = 1; |
1042 |
} |
1043 |
a->d.len = len; |
1044 |
a->d.start = 0; |
1045 |
return len? a->d.buf[a->d.start++] : -1; |
1046 |
} |
1047 |
|
1048 |
|
1049 |
if( a->filter ) { |
1050 |
len = a->d.size; |
1051 |
rc = a->filter( a->filter_ov, IOBUFCTRL_UNDERFLOW, a->chain, |
1052 |
a->d.buf, &len ); |
1053 |
if( a->use == 1 && rc == -1 ) { /* EOF: we can remove the filter */ |
1054 |
size_t dummy_len=0; |
1055 |
|
1056 |
/* and tell the filter to free itself */ |
1057 |
if( (rc = a->filter(a->filter_ov, IOBUFCTRL_FREE, a->chain, |
1058 |
NULL, &dummy_len)) ) |
1059 |
printf("IOBUFCTRL_FREE failed\n"); |
1060 |
if( a->filter_ov && a->filter_ov_owner ) { |
1061 |
safe_free( a->filter_ov ); |
1062 |
a->filter_ov = NULL; |
1063 |
} |
1064 |
a->filter = NULL; |
1065 |
a->desc = NULL; |
1066 |
a->filter_ov = NULL; |
1067 |
a->filter_eof = 1; |
1068 |
if( !len && a->chain ) { |
1069 |
gpg_iobuf_t b = a->chain; |
1070 |
safe_free(a->d.buf); |
1071 |
safe_free(a->real_fname); |
1072 |
memcpy(a,b, sizeof *a); |
1073 |
safe_free(b); |
1074 |
} |
1075 |
} |
1076 |
else if( rc ) |
1077 |
a->error = 1; |
1078 |
|
1079 |
if( !len ) { |
1080 |
return -1; |
1081 |
} |
1082 |
a->d.len = len; |
1083 |
a->d.start = 0; |
1084 |
return a->d.buf[a->d.start++]; |
1085 |
} |
1086 |
else { |
1087 |
return -1; /* no filter; return EOF */ |
1088 |
} |
1089 |
} |
1090 |
|
1091 |
|
1092 |
int |
1093 |
gpg_iobuf_flush(gpg_iobuf_t a) |
1094 |
{ |
1095 |
size_t len; |
1096 |
int rc; |
1097 |
|
1098 |
if( a->directfp ) |
1099 |
return 0; |
1100 |
|
1101 |
if( a->use == 3 ) { /* increase the temp buffer */ |
1102 |
char *newbuf; |
1103 |
size_t newsize = a->d.size + 8192; |
1104 |
|
1105 |
printf("increasing temp iobuf from %lu to %lu\n", |
1106 |
(ulong)a->d.size, (ulong)newsize ); |
1107 |
newbuf = malloc( newsize ); |
1108 |
memcpy( newbuf, a->d.buf, a->d.len ); |
1109 |
safe_free(a->d.buf); |
1110 |
a->d.buf = newbuf; |
1111 |
a->d.size = newsize; |
1112 |
return 0; |
1113 |
} |
1114 |
else if( a->use != 2 ) |
1115 |
printf("flush on non-output iobuf\n"); |
1116 |
else if( !a->filter ) |
1117 |
printf("iobuf_flush: no filter\n"); |
1118 |
len = a->d.len; |
1119 |
rc = a->filter( a->filter_ov, IOBUFCTRL_FLUSH, a->chain, a->d.buf, &len ); |
1120 |
if( !rc && len != a->d.len ) { |
1121 |
printf("iobuf_flush did not write all!\n"); |
1122 |
rc = G10ERR_WRITE_FILE; |
1123 |
} |
1124 |
else if( rc ) |
1125 |
a->error = 1; |
1126 |
a->d.len = 0; |
1127 |
|
1128 |
return rc; |
1129 |
} |
1130 |
|
1131 |
|
1132 |
/**************** |
1133 |
* Read a byte from the iobuf; returns -1 on EOF |
1134 |
*/ |
1135 |
int |
1136 |
gpg_iobuf_readbyte(gpg_iobuf_t a) |
1137 |
{ |
1138 |
int c; |
1139 |
|
1140 |
/* nlimit does not work together with unget */ |
1141 |
/* nbytes is also not valid! */ |
1142 |
if( a->unget.buf ) { |
1143 |
if( a->unget.start < a->unget.len ) |
1144 |
return a->unget.buf[a->unget.start++]; |
1145 |
safe_free(a->unget.buf); |
1146 |
a->unget.buf = NULL; |
1147 |
a->nofast &= ~2; |
1148 |
} |
1149 |
|
1150 |
if( a->nlimit && a->nbytes >= a->nlimit ) |
1151 |
return -1; /* forced EOF */ |
1152 |
|
1153 |
if( a->d.start < a->d.len ) { |
1154 |
c = a->d.buf[a->d.start++]; |
1155 |
} |
1156 |
else if( (c=underflow(a)) == -1 ) |
1157 |
return -1; /* EOF */ |
1158 |
|
1159 |
a->nbytes++; |
1160 |
return c; |
1161 |
} |
1162 |
|
1163 |
|
1164 |
int |
1165 |
gpg_iobuf_read(gpg_iobuf_t a, byte *buf, unsigned buflen ) |
1166 |
{ |
1167 |
int c, n; |
1168 |
|
1169 |
if( a->unget.buf || a->nlimit ) { |
1170 |
/* handle special cases */ |
1171 |
for(n=0 ; n < buflen; n++ ) { |
1172 |
if( (c = gpg_iobuf_readbyte(a)) == -1 ) { |
1173 |
if( !n ) |
1174 |
return -1; /* eof */ |
1175 |
break; |
1176 |
} |
1177 |
else |
1178 |
if( buf ) *buf = c; |
1179 |
if( buf ) buf++; |
1180 |
} |
1181 |
return n; |
1182 |
} |
1183 |
|
1184 |
n = 0; |
1185 |
do { |
1186 |
if( n < buflen && a->d.start < a->d.len ) { |
1187 |
unsigned size = a->d.len - a->d.start; |
1188 |
if( size > buflen - n ) |
1189 |
size = buflen - n; |
1190 |
if( buf ) |
1191 |
memcpy( buf, a->d.buf + a->d.start, size ); |
1192 |
n += size; |
1193 |
a->d.start += size; |
1194 |
if( buf ) |
1195 |
buf += size; |
1196 |
} |
1197 |
if( n < buflen ) { |
1198 |
if( (c=underflow(a)) == -1 ) { |
1199 |
a->nbytes += n; |
1200 |
return n? n : -1/*EOF*/; |
1201 |
} |
1202 |
if( buf ) |
1203 |
*buf++ = c; |
1204 |
n++; |
1205 |
} |
1206 |
} while( n < buflen ); |
1207 |
a->nbytes += n; |
1208 |
return n; |
1209 |
} |
1210 |
|
1211 |
|
1212 |
/**************** |
1213 |
* Have a look at the iobuf. |
1214 |
* NOTE: This only works in special cases. |
1215 |
*/ |
1216 |
int |
1217 |
gpg_iobuf_peek(gpg_iobuf_t a, byte *buf, unsigned buflen ) |
1218 |
{ |
1219 |
int n=0; |
1220 |
|
1221 |
if( a->filter_eof ) |
1222 |
return -1; |
1223 |
|
1224 |
if( !(a->d.start < a->d.len) ) { |
1225 |
if( underflow(a) == -1 ) |
1226 |
return -1; |
1227 |
/* and unget this character */ |
1228 |
assert(a->d.start == 1); |
1229 |
a->d.start = 0; |
1230 |
} |
1231 |
|
1232 |
for(n=0 ; n < buflen && (a->d.start+n) < a->d.len ; n++, buf++ ) |
1233 |
*buf = a->d.buf[n]; |
1234 |
return n; |
1235 |
} |
1236 |
|
1237 |
|
1238 |
|
1239 |
|
1240 |
int |
1241 |
gpg_iobuf_writebyte(gpg_iobuf_t a, unsigned c) |
1242 |
{ |
1243 |
|
1244 |
if( a->directfp ) { |
1245 |
printf( "This is a BUG.\n%s:%d\n", __FILE__, __LINE__ ); |
1246 |
exit( -1 ); |
1247 |
} |
1248 |
|
1249 |
if( a->d.len == a->d.size ) |
1250 |
if( gpg_iobuf_flush(a) ) |
1251 |
return -1; |
1252 |
|
1253 |
assert( a->d.len < a->d.size ); |
1254 |
a->d.buf[a->d.len++] = c; |
1255 |
return 0; |
1256 |
} |
1257 |
|
1258 |
|
1259 |
int |
1260 |
gpg_iobuf_write(gpg_iobuf_t a, byte *buf, unsigned buflen ) |
1261 |
{ |
1262 |
|
1263 |
if( a->directfp ) { |
1264 |
printf( "This is a BUG.\n%s:%d\n", __FILE__, __LINE__ ); |
1265 |
exit( -1 ); |
1266 |
} |
1267 |
|
1268 |
do { |
1269 |
if( buflen && a->d.len < a->d.size ) { |
1270 |
unsigned size = a->d.size - a->d.len; |
1271 |
if( size > buflen ) size = buflen; |
1272 |
memcpy( a->d.buf + a->d.len, buf, size ); |
1273 |
buflen -= size; |
1274 |
buf += size; |
1275 |
a->d.len += size; |
1276 |
} |
1277 |
if( buflen ) { |
1278 |
if( gpg_iobuf_flush(a) ) |
1279 |
return -1; |
1280 |
} |
1281 |
} while( buflen ); |
1282 |
return 0; |
1283 |
} |
1284 |
|
1285 |
|
1286 |
int |
1287 |
gpg_iobuf_writestr(gpg_iobuf_t a, const char *buf ) |
1288 |
{ |
1289 |
for( ; *buf; buf++ ) |
1290 |
if( gpg_iobuf_writebyte(a, *buf) ) |
1291 |
return -1; |
1292 |
return 0; |
1293 |
} |
1294 |
|
1295 |
|
1296 |
|
1297 |
/**************** |
1298 |
* copy the contents of TEMP to A. |
1299 |
*/ |
1300 |
int |
1301 |
gpg_iobuf_write_temp( gpg_iobuf_t a, gpg_iobuf_t temp ) |
1302 |
{ |
1303 |
while( temp->chain ) |
1304 |
pop_filter( temp, temp->filter, NULL ); |
1305 |
return gpg_iobuf_write(a, temp->d.buf, temp->d.len ); |
1306 |
} |
1307 |
|
1308 |
/**************** |
1309 |
* copy the contents of the temp io stream to BUFFER. |
1310 |
*/ |
1311 |
size_t |
1312 |
gpg_iobuf_temp_to_buffer( gpg_iobuf_t a, byte *buffer, size_t buflen ) |
1313 |
{ |
1314 |
size_t n = a->d.len; |
1315 |
|
1316 |
if( n > buflen ) |
1317 |
n = buflen; |
1318 |
memcpy( buffer, a->d.buf, n ); |
1319 |
return n; |
1320 |
} |
1321 |
|
1322 |
|
1323 |
/**************** |
1324 |
* Call this function to terminate processing of the temp stream |
1325 |
* without closing it. This removes all filters from the stream |
1326 |
* makes sure that iobuf_get_temp_{buffer,length}() returns correct |
1327 |
* values. |
1328 |
*/ |
1329 |
void |
1330 |
gpg_iobuf_flush_temp( gpg_iobuf_t temp ) |
1331 |
{ |
1332 |
while( temp->chain ) |
1333 |
pop_filter( temp, temp->filter, NULL ); |
1334 |
} |
1335 |
|
1336 |
|
1337 |
/**************** |
1338 |
* Set a limit on how many bytes may be read from the input stream A. |
1339 |
* Setting the limit to 0 disables this feature. |
1340 |
*/ |
1341 |
void |
1342 |
gpg_iobuf_set_limit( gpg_iobuf_t a, _off_t nlimit ) |
1343 |
{ |
1344 |
if( nlimit ) |
1345 |
a->nofast |= 1; |
1346 |
else |
1347 |
a->nofast &= ~1; |
1348 |
a->nlimit = nlimit; |
1349 |
a->ntotal += a->nbytes; |
1350 |
a->nbytes = 0; |
1351 |
} |
1352 |
|
1353 |
|
1354 |
|
1355 |
/**************** |
1356 |
* Return the length of an open file |
1357 |
*/ |
1358 |
_off_t |
1359 |
gpg_iobuf_get_filelength( gpg_iobuf_t a ) |
1360 |
{ |
1361 |
struct stat st; |
1362 |
|
1363 |
if( a->directfp ) { |
1364 |
FILE *fp = a->directfp; |
1365 |
|
1366 |
if( !fstat(fileno(fp), &st) ) |
1367 |
return st.st_size; |
1368 |
printf("fstat() failed: %s\n", strerror(errno) ); |
1369 |
return 0; |
1370 |
} |
1371 |
|
1372 |
/* Hmmm: file_filter may have already been removed */ |
1373 |
for( ; a; a = a->chain ) |
1374 |
if( !a->chain && a->filter == file_filter ) { |
1375 |
file_filter_ctx_t *b = a->filter_ov; |
1376 |
FILEP_OR_FD fp = b->fp; |
1377 |
|
1378 |
ulong size; |
1379 |
|
1380 |
if ( (size=GetFileSize (fp, NULL)) != 0xffffffff ) |
1381 |
return size; |
1382 |
printf ("GetFileSize for handle %p failed: ec=%d\n", |
1383 |
fp, (int)GetLastError () ); |
1384 |
break; |
1385 |
} |
1386 |
|
1387 |
return 0; |
1388 |
} |
1389 |
|
1390 |
/**************** |
1391 |
* Tell the file position, where the next read will take place |
1392 |
*/ |
1393 |
_off_t |
1394 |
gpg_iobuf_tell( gpg_iobuf_t a ) |
1395 |
{ |
1396 |
return a->ntotal + a->nbytes; |
1397 |
} |
1398 |
|
1399 |
|
1400 |
#if !defined(HAVE_FSEEKO) && !defined(fseeko) |
1401 |
|
1402 |
#ifdef HAVE_LIMITS_H |
1403 |
# include <limits.h> |
1404 |
#endif |
1405 |
#ifndef LONG_MAX |
1406 |
# define LONG_MAX ((long) ((unsigned long) -1 >> 1)) |
1407 |
#endif |
1408 |
#ifndef LONG_MIN |
1409 |
# define LONG_MIN (-1 - LONG_MAX) |
1410 |
#endif |
1411 |
|
1412 |
/**************** |
1413 |
* A substitute for fseeko, for hosts that don't have it. |
1414 |
*/ |
1415 |
static int |
1416 |
fseeko( FILE *stream, _off_t newpos, int whence ) |
1417 |
{ |
1418 |
while( newpos != (long) newpos ) { |
1419 |
long pos = newpos < 0 ? LONG_MIN : LONG_MAX; |
1420 |
if( fseek( stream, pos, whence ) != 0 ) |
1421 |
return -1; |
1422 |
newpos -= pos; |
1423 |
whence = SEEK_CUR; |
1424 |
} |
1425 |
return fseek( stream, (long)newpos, whence ); |
1426 |
} |
1427 |
#endif |
1428 |
|
1429 |
/**************** |
1430 |
* This is a very limited implementation. It simply discards all internal |
1431 |
* buffering and removes all filters but the first one. |
1432 |
*/ |
1433 |
int |
1434 |
gpg_iobuf_seek( gpg_iobuf_t a, _off_t newpos ) |
1435 |
{ |
1436 |
file_filter_ctx_t *b = NULL; |
1437 |
|
1438 |
if( a->directfp ) { |
1439 |
FILE *fp = a->directfp; |
1440 |
if( fseeko( fp, newpos, SEEK_SET ) ) { |
1441 |
printf("can't seek: %s\n", strerror(errno) ); |
1442 |
return -1; |
1443 |
} |
1444 |
clearerr(fp); |
1445 |
} |
1446 |
else { |
1447 |
for( ; a; a = a->chain ) { |
1448 |
if( !a->chain && a->filter == file_filter ) { |
1449 |
b = a->filter_ov; |
1450 |
break; |
1451 |
} |
1452 |
} |
1453 |
if( !a ) |
1454 |
return -1; |
1455 |
if (SetFilePointer (b->fp, newpos, NULL, FILE_BEGIN) == 0xffffffff ) { |
1456 |
printf ("SetFilePointer failed on handle %p: ec=%d\n", |
1457 |
b->fp, (int)GetLastError () ); |
1458 |
return -1; |
1459 |
} |
1460 |
} |
1461 |
a->d.len = 0; /* discard buffer */ |
1462 |
a->d.start = 0; |
1463 |
a->nbytes = 0; |
1464 |
a->nlimit = 0; |
1465 |
a->nofast &= ~1; |
1466 |
a->ntotal = newpos; |
1467 |
a->error = 0; |
1468 |
/* remove filters, but the last */ |
1469 |
if( a->chain ) |
1470 |
printf("pop_filter called in iobuf_seek - please report\n"); |
1471 |
while( a->chain ) |
1472 |
pop_filter( a, a->filter, NULL ); |
1473 |
|
1474 |
return 0; |
1475 |
} |
1476 |
|
1477 |
|
1478 |
|
1479 |
|
1480 |
|
1481 |
|
1482 |
/**************** |
1483 |
* Retrieve the real filename |
1484 |
*/ |
1485 |
const char * |
1486 |
gpg_iobuf_get_real_fname( gpg_iobuf_t a ) |
1487 |
{ |
1488 |
if( a->real_fname ) |
1489 |
return a->real_fname; |
1490 |
|
1491 |
/* the old solution */ |
1492 |
for( ; a; a = a->chain ) |
1493 |
if( !a->chain && a->filter == file_filter ) { |
1494 |
file_filter_ctx_t *b = a->filter_ov; |
1495 |
return b->print_only_name? NULL : b->fname; |
1496 |
} |
1497 |
|
1498 |
return NULL; |
1499 |
} |
1500 |
|
1501 |
|
1502 |
/**************** |
1503 |
* Retrieve the filename |
1504 |
*/ |
1505 |
const char * |
1506 |
gpg_iobuf_get_fname( gpg_iobuf_t a ) |
1507 |
{ |
1508 |
for( ; a; a = a->chain ) |
1509 |
if( !a->chain && a->filter == file_filter ) { |
1510 |
file_filter_ctx_t *b = a->filter_ov; |
1511 |
return b->fname; |
1512 |
} |
1513 |
|
1514 |
return NULL; |
1515 |
} |
1516 |
|
1517 |
/**************** |
1518 |
* Start the block write mode, see rfc1991.new for details. |
1519 |
* A value of 0 for N stops this mode (flushes and writes |
1520 |
* the end marker) |
1521 |
*/ |
1522 |
void |
1523 |
gpg_iobuf_set_block_mode( gpg_iobuf_t a, size_t n ) |
1524 |
{ |
1525 |
block_filter_ctx_t *ctx = calloc( 1, sizeof *ctx ); |
1526 |
|
1527 |
assert( a->use == 1 || a->use == 2 ); |
1528 |
ctx->use = a->use; |
1529 |
if( !n ) { |
1530 |
if( a->use == 1 ) |
1531 |
printf("pop_filter called in set_block_mode - please report\n"); |
1532 |
pop_filter(a, block_filter, NULL ); |
1533 |
} |
1534 |
else { |
1535 |
ctx->size = n; /* only needed for use 2 */ |
1536 |
gpg_iobuf_push_filter(a, block_filter, ctx ); |
1537 |
} |
1538 |
} |
1539 |
|
1540 |
/**************** |
1541 |
* enable partial block mode as described in the OpenPGP draft. |
1542 |
* LEN is the first length byte on read, but ignored on writes. |
1543 |
*/ |
1544 |
void |
1545 |
gpg_iobuf_set_partial_block_mode( gpg_iobuf_t a, size_t len ) |
1546 |
{ |
1547 |
block_filter_ctx_t *ctx = calloc( 1, sizeof *ctx ); |
1548 |
|
1549 |
assert( a->use == 1 || a->use == 2 ); |
1550 |
ctx->use = a->use; |
1551 |
if( !len ) { |
1552 |
if( a->use == 1 ) |
1553 |
printf("pop_filter called in set_partial_block_mode" |
1554 |
" - please report\n"); |
1555 |
pop_filter(a, block_filter, NULL ); |
1556 |
} |
1557 |
else { |
1558 |
ctx->partial = 1; |
1559 |
ctx->size = 0; |
1560 |
ctx->first_c = len; |
1561 |
gpg_iobuf_push_filter(a, block_filter, ctx ); |
1562 |
} |
1563 |
} |
1564 |
|
1565 |
|
1566 |
/**************** |
1567 |
* Checks whether the stream is in block mode |
1568 |
* Note: This does not work if other filters are pushed on the stream. |
1569 |
*/ |
1570 |
int |
1571 |
gpg_iobuf_in_block_mode( gpg_iobuf_t a ) |
1572 |
{ |
1573 |
if( a && a->filter == block_filter ) |
1574 |
return 1; /* yes */ |
1575 |
return 0; /* no */ |
1576 |
} |
1577 |
|
1578 |
|
1579 |
/**************** |
1580 |
* Same as fgets() but if the buffer is too short a larger one will |
1581 |
* be allocated up to some limit *max_length. |
1582 |
* A line is considered a byte stream ending in a LF. |
1583 |
* Returns the length of the line. EOF is indicated by a line of |
1584 |
* length zero. The last LF may be missing due to an EOF. |
1585 |
* is max_length is zero on return, the line has been truncated. |
1586 |
* |
1587 |
* Note: The buffer is allocated with enough space to append a CR,LF,EOL |
1588 |
*/ |
1589 |
unsigned |
1590 |
gpg_iobuf_read_line( gpg_iobuf_t a, byte **addr_of_buffer, |
1591 |
unsigned *length_of_buffer, unsigned *max_length ) |
1592 |
{ |
1593 |
int c; |
1594 |
char *buffer = *addr_of_buffer; |
1595 |
unsigned length = *length_of_buffer; |
1596 |
unsigned nbytes = 0; |
1597 |
unsigned maxlen = *max_length; |
1598 |
char *p; |
1599 |
|
1600 |
if( !buffer ) { /* must allocate a new buffer */ |
1601 |
length = 256; |
1602 |
buffer = (char *)malloc( length ); |
1603 |
*addr_of_buffer = buffer; |
1604 |
*length_of_buffer = length; |
1605 |
} |
1606 |
|
1607 |
length -= 3; /* reserve 3 bytes (cr,lf,eol) */ |
1608 |
p = buffer; |
1609 |
while( (c=gpg_iobuf_get(a)) != -1 ) { |
1610 |
if( nbytes == length ) { /* increase the buffer */ |
1611 |
if( length > maxlen ) { /* this is out limit */ |
1612 |
/* skip the rest of the line */ |
1613 |
while( c != '\n' && (c=gpg_iobuf_get(a)) != -1 ) |
1614 |
; |
1615 |
*p++ = '\n'; /* always append a LF (we have reserved space) */ |
1616 |
nbytes++; |
1617 |
*max_length = 0; /* indicate truncation */ |
1618 |
break; |
1619 |
} |
1620 |
length += 3; /* correct for the reserved byte */ |
1621 |
length += length < 1024? 256 : 1024; |
1622 |
buffer = realloc( buffer, length ); |
1623 |
*addr_of_buffer = buffer; |
1624 |
*length_of_buffer = length; |
1625 |
length -= 3; /* and reserve again */ |
1626 |
p = buffer + nbytes; |
1627 |
} |
1628 |
*p++ = c; |
1629 |
nbytes++; |
1630 |
if( c == '\n' ) |
1631 |
break; |
1632 |
} |
1633 |
*p = 0; /* make sure the line is a string */ |
1634 |
|
1635 |
return nbytes; |
1636 |
} |
1637 |
|
1638 |
/* This is the non iobuf specific function */ |
1639 |
int |
1640 |
gpg_iobuf_translate_file_handle ( int fd, int for_write ) |
1641 |
{ |
1642 |
{ |
1643 |
int x; |
1644 |
|
1645 |
if ( fd <= 2 ) |
1646 |
return fd; /* do not do this for error, stdin, stdout, stderr */ |
1647 |
|
1648 |
x = _open_osfhandle ( fd, for_write? 1:0 ); |
1649 |
if (x==-1 ) |
1650 |
printf ("failed to translate osfhandle %p\n", (void*)fd ); |
1651 |
else { |
1652 |
/*log_info ("_open_osfhandle %p yields %d%s\n", |
1653 |
(void*)fd, x, for_write? " for writing":"" );*/ |
1654 |
fd = x; |
1655 |
} |
1656 |
} |
1657 |
return fd; |
1658 |
} |
1659 |
|
1660 |
static int |
1661 |
translate_file_handle ( int fd, int for_write ) |
1662 |
{ |
1663 |
{ |
1664 |
int x; |
1665 |
|
1666 |
if ( fd == 0 ) |
1667 |
x = (int)GetStdHandle (STD_INPUT_HANDLE); |
1668 |
else if (fd == 1) |
1669 |
x = (int)GetStdHandle (STD_OUTPUT_HANDLE); |
1670 |
else if (fd == 2) |
1671 |
x = (int)GetStdHandle (STD_ERROR_HANDLE); |
1672 |
else |
1673 |
x = fd; |
1674 |
|
1675 |
if (x == -1) |
1676 |
printf ("GetStdHandle(%d) failed: ec=%d\n", |
1677 |
fd, (int)GetLastError () ); |
1678 |
|
1679 |
fd = x; |
1680 |
} |
1681 |
return fd; |
1682 |
} |
1683 |
|
1684 |
|