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