estream support for iobuf and new memuf functions.

This commit is contained in:
Werner Koch 2011-01-18 12:50:02 +01:00
parent 260c41851e
commit c2c5d30db8
5 changed files with 189 additions and 5 deletions

View File

@ -1,4 +1,12 @@
2011-01-07 Werner Koch <wk@g10code.com>
2011-01-18 Werner Koch <wk@g10code.com>
* 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 <wk@g10code.com>
* session-env.c (update_var): Fix same value detection. Fixes
bug#1311.
2010-12-17 Werner Koch <wk@g10code.com>
* 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

View File

@ -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)
{

View File

@ -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);

View File

@ -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;
}

View File

@ -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*/