diff --git a/common/ChangeLog b/common/ChangeLog index 1484ae0eb..3ce80cb1a 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,4 +1,12 @@ -2011-01-07 Werner Koch +2011-01-18 Werner Koch + + * iobuf.c (file_es_filter_ctx_t): New. + (file_es_filter): New. + (iobuf_esopen): New. + + * estream.c (es_func_mem_write): Fix computation of NEWSIZE. + + * membuf.c (clear_membuf, peek_membuf): New. * util.h (GPG_ERR_NO_KEYSERVER): New. @@ -10,6 +18,11 @@ * http.h (parsed_uri_s): Add field IS_HTTP. (http_parse_uri): Support NO_SCHEME_CHECK arg. +2011-01-10 Werner Koch + + * session-env.c (update_var): Fix same value detection. Fixes + bug#1311. + 2010-12-17 Werner Koch * asshelp.c (lock_spawning): Add arg VERBOSE. Improve timeout @@ -2263,7 +2276,7 @@ Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, - 2009, 2010, 2011 Free Software Foundation, Inc. + 2009, 2010 Free Software Foundation, Inc. This file is free software; as a special exception the author gives unlimited permission to copy and/or distribute it, with or without diff --git a/common/iobuf.c b/common/iobuf.c index b9bed3218..9813d3da6 100644 --- a/common/iobuf.c +++ b/common/iobuf.c @@ -1,6 +1,6 @@ /* iobuf.c - File Handling for OpenPGP. * Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2006, 2007, 2008, - * 2009, 2010 Free Software Foundation, Inc. + * 2009, 2010, 2011 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -78,6 +78,17 @@ typedef struct char fname[1]; /* Name of the file. */ } file_filter_ctx_t; +/* The context used by the estream filter. */ +typedef struct +{ + estream_t fp; /* Open estream handle. */ + int keep_open; + int no_cache; + int eof_seen; + int print_only_name; /* Flags indicating that fname is not a real file. */ + char fname[1]; /* Name of the file. */ +} file_es_filter_ctx_t; + /* Object to control the "close cache". */ struct close_cache_s @@ -577,6 +588,96 @@ file_filter (void *opaque, int control, iobuf_t chain, byte * buf, } +/* Similar to file_filter but using the estream system. */ +static int +file_es_filter (void *opaque, int control, iobuf_t chain, byte * buf, + size_t * ret_len) +{ + file_es_filter_ctx_t *a = opaque; + estream_t f = a->fp; + size_t size = *ret_len; + size_t nbytes = 0; + int rc = 0; + + (void)chain; /* Not used. */ + + if (control == IOBUFCTRL_UNDERFLOW) + { + assert (size); /* We need a buffer. */ + if (a->eof_seen) + { + rc = -1; + *ret_len = 0; + } + else + { + nbytes = 0; + rc = es_read (f, buf, size, &nbytes); + if (rc == -1) + { /* error */ + rc = gpg_error_from_syserror (); + log_error ("%s: read error: %s\n", a->fname, strerror (errno)); + } + else if (!nbytes) + { /* eof */ + a->eof_seen = 1; + rc = -1; + } + *ret_len = nbytes; + } + } + else if (control == IOBUFCTRL_FLUSH) + { + if (size) + { + byte *p = buf; + size_t nwritten; + + nbytes = size; + do + { + nwritten = 0; + if (es_write (f, p, nbytes, &nwritten)) + { + rc = gpg_error_from_syserror (); + log_error ("%s: write error: %s\n", + a->fname, strerror (errno)); + break; + } + p += nwritten; + nbytes -= nwritten; + } + while (nbytes); + nbytes = p - buf; + } + *ret_len = nbytes; + } + else if (control == IOBUFCTRL_INIT) + { + a->eof_seen = 0; + a->no_cache = 0; + } + else if (control == IOBUFCTRL_DESC) + { + *(char **) buf = "estream_filter"; + } + else if (control == IOBUFCTRL_FREE) + { + if (f != es_stdin && f != es_stdout) + { + if (DBG_IOBUF) + log_debug ("%s: es_fclose %p\n", a->fname, f); + if (!a->keep_open) + es_fclose (f); + } + f = NULL; + xfree (a); /* We can free our context now. */ + } + + return rc; +} + + #ifdef HAVE_W32_SYSTEM /* Because network sockets are special objects under Lose32 we have to use a dedicated filter for them. */ @@ -1257,6 +1358,30 @@ iobuf_fdopen_nc (int fd, const char *mode) } +iobuf_t +iobuf_esopen (estream_t estream, const char *mode, int keep_open) +{ + iobuf_t a; + file_es_filter_ctx_t *fcx; + size_t len; + + a = iobuf_alloc (strchr (mode, 'w') ? 2 : 1, IOBUF_BUFFER_SIZE); + fcx = xtrymalloc (sizeof *fcx + 30); + fcx->fp = estream; + fcx->print_only_name = 1; + fcx->keep_open = keep_open; + sprintf (fcx->fname, "[fd %p]", estream); + a->filter = file_es_filter; + a->filter_ov = fcx; + file_es_filter (fcx, IOBUFCTRL_DESC, NULL, (byte *) & a->desc, &len); + file_es_filter (fcx, IOBUFCTRL_INIT, NULL, NULL, &len); + if (DBG_IOBUF) + log_debug ("iobuf-%d.%d: esopen%s `%s'\n", + a->no, a->subno, keep_open? "_nc":"", fcx->fname); + return a; +} + + iobuf_t iobuf_sockopen (int fd, const char *mode) { diff --git a/common/iobuf.h b/common/iobuf.h index 1d863fdcd..3ac4fa061 100644 --- a/common/iobuf.h +++ b/common/iobuf.h @@ -23,6 +23,7 @@ #include "../include/types.h" /* fixme: should be moved elsewhere. */ #include "../common/sysutils.h" +#include "../common/estream.h" #define DBG_IOBUF iobuf_debug_mode @@ -102,6 +103,7 @@ iobuf_t iobuf_open_fd_or_name (gnupg_fd_t fd, const char *fname, iobuf_t iobuf_open (const char *fname); iobuf_t iobuf_fdopen (int fd, const char *mode); iobuf_t iobuf_fdopen_nc (int fd, const char *mode); +iobuf_t iobuf_esopen (estream_t estream, const char *mode, int keep_open); iobuf_t iobuf_sockopen (int fd, const char *mode); iobuf_t iobuf_create (const char *fname); iobuf_t iobuf_append (const char *fname); diff --git a/common/membuf.c b/common/membuf.c index f9f82d357..8648044a7 100644 --- a/common/membuf.c +++ b/common/membuf.c @@ -1,5 +1,5 @@ /* membuf.c - A simple implementation of a dynamic buffer. - * Copyright (C) 2001, 2003, 2009 Free Software Foundation, Inc. + * Copyright (C) 2001, 2003, 2009, 2011 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -56,6 +56,26 @@ init_membuf_secure (membuf_t *mb, int initiallen) } +/* Shift the the content of the membuf MB by AMOUNT bytes. The next + operation will then behave as if AMOUNT bytes had not been put into + the buffer. If AMOUNT is greater than the actual accumulated + bytes, the membuf is basically reset to its initial state. */ +void +clear_membuf (membuf_t *mb, size_t amount) +{ + /* No need to clear if we are already out of core. */ + if (mb->out_of_core) + return; + if (amount >= mb->len) + mb->len = 0; + else + { + mb->len -= amount; + memmove (mb->buf, mb->buf+amount, mb->len); + } +} + + void put_membuf (membuf_t *mb, const void *buf, size_t len) { @@ -116,3 +136,26 @@ get_membuf (membuf_t *mb, size_t *len) mb->out_of_core = ENOMEM; /* hack to make sure it won't get reused. */ return p; } + + +/* Peek at the membuf MB. On success a pointer to the buffer is + returned which is valid until the next operation on MB. If LEN is + not NULL the current LEN of the buffer is stored there. On error + NULL is returned and ERRNO is set. */ +const void * +peek_membuf (membuf_t *mb, size_t *len) +{ + const char *p; + + if (mb->out_of_core) + { + gpg_err_set_errno (mb->out_of_core); + return NULL; + } + + p = mb->buf; + if (len) + *len = mb->len; + return p; +} + diff --git a/common/membuf.h b/common/membuf.h index 75b506d5d..9f1a7a33b 100644 --- a/common/membuf.h +++ b/common/membuf.h @@ -39,9 +39,10 @@ typedef struct private_membuf_s membuf_t; void init_membuf (membuf_t *mb, int initiallen); void init_membuf_secure (membuf_t *mb, int initiallen); +void clear_membuf (membuf_t *mb, size_t amount); void put_membuf (membuf_t *mb, const void *buf, size_t len); void put_membuf_str (membuf_t *mb, const char *string); void *get_membuf (membuf_t *mb, size_t *len); - +const void *peek_membuf (membuf_t *mb, size_t *len); #endif /*GNUPG_COMMON_MEMBUF_H*/