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