1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-01-23 15:07:03 +01:00

common/iobuf: Improve documentation and code comments.

common/iobuf.h: Improve documentation and code comments.
common/iobuf.c: Likewise.

--
Signed-off-by: Neal H. Walfield <neal@g10code.com>.
This commit is contained in:
Neal H. Walfield 2015-08-17 12:30:04 +02:00
parent 0d40c4e83f
commit 1bfd1e4324
2 changed files with 546 additions and 165 deletions

View File

@ -133,9 +133,9 @@ typedef struct
} sock_filter_ctx_t; } sock_filter_ctx_t;
#endif /*HAVE_W32_SYSTEM*/ #endif /*HAVE_W32_SYSTEM*/
/* The first partial length header block must be of size 512 /* The first partial length header block must be of size 512 to make
* to make it easier (and efficienter) we use a min. block size of 512 * it easier (and more efficient) we use a min. block size of 512 for
* for all chunks (but the last one) */ * all chunks (but the last one) */
#define OP_MIN_PARTIAL_CHUNK 512 #define OP_MIN_PARTIAL_CHUNK 512
#define OP_MIN_PARTIAL_CHUNK_2POW 9 #define OP_MIN_PARTIAL_CHUNK_2POW 9
@ -156,8 +156,8 @@ block_filter_ctx_t;
/* Global flag to tell whether special file names are enabled. See /* Global flag to tell whether special file names are enabled. See
gpg.c for an explanation of these file names. FIXME: it does not gpg.c for an explanation of these file names. FIXME: This does not
belong into the iobuf subsystem. */ belong in the iobuf subsystem. */
static int special_names_enabled; static int special_names_enabled;
/* Local prototypes. */ /* Local prototypes. */
@ -401,7 +401,7 @@ fd_cache_close (const char *fname, gnupg_fd_t fp)
} }
/* /*
* Do an direct_open on FNAME but first try to reuse one from the fd_cache * Do a direct_open on FNAME but first try to reuse one from the fd_cache
*/ */
static gnupg_fd_t static gnupg_fd_t
fd_cache_open (const char *fname, const char *mode) fd_cache_open (const char *fname, const char *mode)
@ -440,30 +440,6 @@ fd_cache_open (const char *fname, const char *mode)
} }
/****************
* Read data from a file into buf which has an allocated length of *LEN.
* return the number of read bytes in *LEN. OPAQUE is the FILE * of
* the stream. A is not used.
* control may be:
* IOBUFCTRL_INIT: called just before the function is linked into the
* list of function. This can be used to prepare internal
* data structures of the function.
* IOBUFCTRL_FREE: called just before the function is removed from the
* list of functions and can be used to release internal
* data structures or close a file etc.
* IOBUFCTRL_UNDERFLOW: called by iobuf_underflow to fill the buffer
* with new stuff. *RET_LEN is the available size of the
* buffer, and should be set to the number of bytes
* which were put into the buffer. The function
* returns 0 to indicate success, -1 on EOF and
* GPG_ERR_xxxxx for other errors.
*
* IOBUFCTRL_FLUSH: called by iobuf_flush() to write out the collected stuff.
* *RET_LAN is the number of bytes in BUF.
*
* IOBUFCTRL_CANCEL: send to all filters on behalf of iobuf_cancel. The
* filter may take appropriate action on this message.
*/
static int static int
file_filter (void *opaque, int control, iobuf_t chain, byte * buf, file_filter (void *opaque, int control, iobuf_t chain, byte * buf,
size_t * ret_len) size_t * ret_len)
@ -1117,13 +1093,6 @@ iobuf_print_chain (iobuf_t a)
return 0; return 0;
} }
/* Allocate a new io buffer, with no function assigned.
USE is the desired usage: IOBUF_INPUT for input, IOBUF_OUTPUT for
output, or IOBUF_TEMP for a temp buffer.
BUFSIZE is a suggested buffer size.
*/
iobuf_t iobuf_t
iobuf_alloc (int use, size_t bufsize) iobuf_alloc (int use, size_t bufsize)
{ {
@ -1233,19 +1202,10 @@ iobuf_cancel (iobuf_t a)
} }
/****************
* create a temporary iobuf, which can be used to collect stuff
* in an iobuf and later be written by iobuf_write_temp() to another
* iobuf.
*/
iobuf_t iobuf_t
iobuf_temp () iobuf_temp (void)
{ {
iobuf_t a; return iobuf_alloc (IOBUF_TEMP, IOBUF_BUFFER_SIZE);
a = iobuf_alloc (IOBUF_TEMP, IOBUF_BUFFER_SIZE);
return a;
} }
iobuf_t iobuf_t
@ -1290,8 +1250,6 @@ check_special_filename (const char *fname)
} }
/* This fucntion returns true if FNAME indicates a PIPE (stdout or
stderr) or a special file name if those are enabled. */
int int
iobuf_is_pipe_filename (const char *fname) iobuf_is_pipe_filename (const char *fname)
{ {
@ -1359,10 +1317,6 @@ do_open (const char *fname, int special_filenames,
return a; return a;
} }
/****************
* Create a head iobuf for reading from a file
* returns: NULL if an error occures and sets errno
*/
iobuf_t iobuf_t
iobuf_open (const char *fname) iobuf_open (const char *fname)
{ {
@ -1410,8 +1364,6 @@ do_iobuf_fdopen (int fd, const char *mode, int keep_open)
} }
/* Create a head iobuf for reading or writing from/to a file Returns:
* NULL and sets ERRNO if an error occured. */
iobuf_t iobuf_t
iobuf_fdopen (int fd, const char *mode) iobuf_fdopen (int fd, const char *mode)
{ {
@ -1587,11 +1539,51 @@ iobuf_push_filter2 (iobuf_t a,
return GPG_ERR_BAD_DATA; return GPG_ERR_BAD_DATA;
} }
/* make a copy of the current stream, so that /* We want to create a new filter and put it in front of A. A
* A is the new stream and B the original one. simple implementation would do:
* The contents of the buffers are transferred to the
* new stream. b = iobuf_alloc (...);
b->chain = a;
return a;
This is a bit problematic: A is the head of the pipeline and
there are potentially many pointers to it. Requiring the caller
to update all of these pointers is a burden.
An alternative implementation would add a level of indirection.
For instance, we could use a pipeline object, which contains a
pointer to the first filter in the pipeline. This is not what we
do either.
Instead, we allocate a new buffer (B) and copy the first filter's
state into that and use the initial buffer (A) for the new
filter. One limitation of this approach is that it is not
practical to maintain a pointer to a specific filter's state.
Before:
A
|
v 0x100 0x200
+----------+ +----------+
| filter x |--------->| filter y |---->....
+----------+ +----------+
After: B
|
v 0x300
+----------+
A | filter x |
| +----------+
v 0x100 ^ v 0x200
+----------+ +----------+
| filter w | | filter y |---->....
+----------+ +----------+
Note: filter x's address changed from 0x100 to 0x300, but A still
points to the head of the pipeline.
*/ */
b = xmalloc (sizeof *b); b = xmalloc (sizeof *b);
memcpy (b, a, sizeof *b); memcpy (b, a, sizeof *b);
/* fixme: it is stupid to keep a copy of the name at every level /* fixme: it is stupid to keep a copy of the name at every level
@ -1938,9 +1930,6 @@ filter_flush (iobuf_t a)
} }
/****************
* Read a byte from the iobuf; returns -1 on EOF
*/
int int
iobuf_readbyte (iobuf_t a) iobuf_readbyte (iobuf_t a)
{ {
@ -1956,6 +1945,9 @@ iobuf_readbyte (iobuf_t a)
else if ((c = underflow (a, 1)) == -1) else if ((c = underflow (a, 1)) == -1)
return -1; /* EOF */ return -1; /* EOF */
/* Note: if underflow doesn't return EOF, then it returns the first
byte that was read and advances a->d.start appropriately. */
a->nbytes++; a->nbytes++;
return c; return c;
} }
@ -1990,6 +1982,7 @@ iobuf_read (iobuf_t a, void *buffer, unsigned int buflen)
do do
{ {
if (n < buflen && a->d.start < a->d.len) if (n < buflen && a->d.start < a->d.len)
/* Drain the buffer. */
{ {
unsigned size = a->d.len - a->d.start; unsigned size = a->d.len - a->d.start;
if (size > buflen - n) if (size > buflen - n)
@ -2002,8 +1995,13 @@ iobuf_read (iobuf_t a, void *buffer, unsigned int buflen)
buf += size; buf += size;
} }
if (n < buflen) if (n < buflen)
/* Draining the internal buffer didn't fill BUFFER. Call
underflow to read more data into the filter's internal
buffer. */
{ {
if ((c = underflow (a, 1)) == -1) if ((c = underflow (a, 1)) == -1)
/* EOF. If we managed to read something, don't return EOF
now. */
{ {
a->nbytes += n; a->nbytes += n;
return n ? n : -1 /*EOF*/; return n ? n : -1 /*EOF*/;
@ -2120,9 +2118,6 @@ iobuf_writestr (iobuf_t a, const char *buf)
/****************
* copy the contents of TEMP to A.
*/
int int
iobuf_write_temp (iobuf_t a, iobuf_t temp) iobuf_write_temp (iobuf_t a, iobuf_t temp)
{ {
@ -2131,9 +2126,6 @@ iobuf_write_temp (iobuf_t a, iobuf_t temp)
return iobuf_write (a, temp->d.buf, temp->d.len); return iobuf_write (a, temp->d.buf, temp->d.len);
} }
/****************
* copy the contents of the temp io stream to BUFFER.
*/
size_t size_t
iobuf_temp_to_buffer (iobuf_t a, byte * buffer, size_t buflen) iobuf_temp_to_buffer (iobuf_t a, byte * buffer, size_t buflen)
{ {
@ -2158,12 +2150,6 @@ iobuf_temp_to_buffer (iobuf_t a, byte * buffer, size_t buflen)
} }
/****************
* Call this function to terminate processing of the temp stream
* without closing it. This removes all filters from the stream
* makes sure that iobuf_get_temp_{buffer,length}() returns correct
* values.
*/
void void
iobuf_flush_temp (iobuf_t temp) iobuf_flush_temp (iobuf_t temp)
{ {
@ -2172,10 +2158,6 @@ iobuf_flush_temp (iobuf_t temp)
} }
/****************
* Set a limit on how many bytes may be read from the input stream A.
* Setting the limit to 0 disables this feature.
*/
void void
iobuf_set_limit (iobuf_t a, off_t nlimit) iobuf_set_limit (iobuf_t a, off_t nlimit)
{ {
@ -2190,9 +2172,6 @@ iobuf_set_limit (iobuf_t a, off_t nlimit)
/* Return the length of an open file A. IF OVERFLOW is not NULL it
will be set to true if the file is larger than what off_t can cope
with. The function return 0 on error or on overflow condition. */
off_t off_t
iobuf_get_filelength (iobuf_t a, int *overflow) iobuf_get_filelength (iobuf_t a, int *overflow)
{ {
@ -2263,8 +2242,6 @@ iobuf_get_filelength (iobuf_t a, int *overflow)
} }
/* Return the file descriptor of the underlying file or -1 if it is
not available. */
int int
iobuf_get_fd (iobuf_t a) iobuf_get_fd (iobuf_t a)
{ {
@ -2281,10 +2258,6 @@ iobuf_get_fd (iobuf_t a)
} }
/****************
* Tell the file position, where the next read will take place
*/
off_t off_t
iobuf_tell (iobuf_t a) iobuf_tell (iobuf_t a)
{ {
@ -2322,10 +2295,6 @@ fseeko (FILE * stream, off_t newpos, int whence)
} }
#endif #endif
/****************
* This is a very limited implementation. It simply discards all internal
* buffering and removes all filters but the first one.
*/
int int
iobuf_seek (iobuf_t a, off_t newpos) iobuf_seek (iobuf_t a, off_t newpos)
{ {
@ -2367,6 +2336,16 @@ iobuf_seek (iobuf_t a, off_t newpos)
a->nofast = 0; a->nofast = 0;
a->ntotal = newpos; a->ntotal = newpos;
a->error = 0; a->error = 0;
/* It is impossible for A->CHAIN to be non-NULL. If A is an INPUT
or OUTPUT buffer, then we find the last filter, which is defined
as A->CHAIN being NULL. If A is a TEMP filter, then A must be
the only filter in the pipe: when iobuf_push_filter adds a filter
to the front of a pipeline, it sets the new filter to be an
OUTPUT filter if the pipeline is an OUTPUT or TEMP pipeline and
to be an INPUT filter if the pipeline is an INPUT pipeline.
Thus, only the last filter in a TEMP pipeline can be a */
/* remove filters, but the last */ /* remove filters, but the last */
if (a->chain) if (a->chain)
log_debug ("pop_filter called in iobuf_seek - please report\n"); log_debug ("pop_filter called in iobuf_seek - please report\n");
@ -2381,11 +2360,6 @@ iobuf_seek (iobuf_t a, off_t newpos)
/****************
* Retrieve the real filename. This is the filename actually used on
* disk and not a made up one. Returns NULL if no real filename is
* available.
*/
const char * const char *
iobuf_get_real_fname (iobuf_t a) iobuf_get_real_fname (iobuf_t a)
{ {
@ -2404,9 +2378,6 @@ iobuf_get_real_fname (iobuf_t a)
} }
/****************
* Retrieve the filename. This name should only be used in diagnostics.
*/
const char * const char *
iobuf_get_fname (iobuf_t a) iobuf_get_fname (iobuf_t a)
{ {
@ -2419,7 +2390,6 @@ iobuf_get_fname (iobuf_t a)
return NULL; return NULL;
} }
/* Same as iobuf_get_fname but never returns NULL. */
const char * const char *
iobuf_get_fname_nonnull (iobuf_t a) iobuf_get_fname_nonnull (iobuf_t a)
{ {
@ -2446,6 +2416,14 @@ iobuf_set_partial_block_mode (iobuf_t a, size_t len)
if (a->use == IOBUF_INPUT) if (a->use == IOBUF_INPUT)
log_debug ("pop_filter called in set_partial_block_mode" log_debug ("pop_filter called in set_partial_block_mode"
" - please report\n"); " - please report\n");
/* XXX: This pop_filter doesn't make sense. Since we haven't
actually added the filter to the pipeline yet, why are we
popping anything? Moreover, since we don't report an error,
the caller won't directly see an error. I think that it
would be better to push the filter and set a->error to
GPG_ERR_BAD_DATA, but Werner thinks it's impossible for len
to be 0 (but he doesn't want to remove the check just in
case). */
pop_filter (a, block_filter, NULL); pop_filter (a, block_filter, NULL);
} }
else else
@ -2459,16 +2437,6 @@ iobuf_set_partial_block_mode (iobuf_t a, size_t len)
/****************
* Same as fgets() but if the buffer is too short a larger one will
* be allocated up to some limit *max_length.
* A line is considered a byte stream ending in a LF.
* Returns the length of the line. EOF is indicated by a line of
* length zero. The last LF may be missing due to an EOF.
* is max_length is zero on return, the line has been truncated.
*
* Note: The buffer is allocated with enough space to append a CR,LF,EOL
*/
unsigned int unsigned int
iobuf_read_line (iobuf_t a, byte ** addr_of_buffer, iobuf_read_line (iobuf_t a, byte ** addr_of_buffer,
unsigned *length_of_buffer, unsigned *max_length) unsigned *length_of_buffer, unsigned *max_length)

View File

@ -31,6 +31,63 @@
#ifndef GNUPG_COMMON_IOBUF_H #ifndef GNUPG_COMMON_IOBUF_H
#define GNUPG_COMMON_IOBUF_H #define GNUPG_COMMON_IOBUF_H
/* An iobuf is basically a filter in a pipeline.
Consider the following command, which consists of three filters
that are chained together:
$ cat file | base64 --decode | gunzip
The first filter reads the file from the file system and sends that
data to the second filter. The second filter decodes
base64-encoded data and sends the data to the third and last
filter. The last filter decompresses the data and the result is
displayed on the terminal. The iobuf system works in the same way
where each iobuf is a filter and the individual iobufs can be
chained together.
There are number of predefined filters. iobuf_open(), for
instance, creates a filter that reads from a specified file. And,
iobuf_temp_with_content() creates a filter that returns some
specified contents. There are also filters for writing content.
iobuf_openrw opens a file for writing. iobuf_temp creates a filter
that writes data to a fixed-sized buffer.
To chain filters together, you use the iobuf_push_filter()
function. The filters are chained together using the chain field
in the iobuf_t.
A pipeline can only be used for reading (IOBUF_INPUT) or for
writing (IOBUF_OUTPUT / IOBUF_TEMP). When reading, data flows from
the last filter towards the first. That is, the user calls
iobuf_read(), the module reads from the first filter, which gets
its input from the second filter, etc. When writing, data flows
from the first filter towards the last. In this case, when the
user calls iobuf_write(), the data is written to the first filter,
which writes the transformed data to the second filter, etc.
An iobuf_t contains some state about the filter. For instance, it
indicates if the filter has already returned EOF (filter_eof) and
the next filter in the pipeline, if any (chain). It also contains
a function pointer, filter. This is a generic function. It is
called when input is needed or output is available. In this case
it is passed a pointer to some filter-specific persistent state
(filter_ov), the actual operation, the next filter in the chain, if
any, and a buffer that either contains the contents to write, if
the pipeline is setup to write data, or is the place to store data,
if the pipeline is setup to read data.
Unlike a Unix pipeline, an IOBUF pipeline can return EOF multiple
times. This is similar to the following:
{ cat file1; cat file2; } | grep foo
However, instead of grep seeing a single stream, grep would see
each byte stream followed by an EOF marker. (When a filter returns
EOF, the EOF is returned to the user exactly once and then the
filter is removed from the pipeline.) */
/* For estream_t. */ /* For estream_t. */
#include <gpg-error.h> #include <gpg-error.h>
@ -40,13 +97,16 @@
#define DBG_IOBUF iobuf_debug_mode #define DBG_IOBUF iobuf_debug_mode
/* Filter control modes. */ /* Filter control modes. */
#define IOBUFCTRL_INIT 1 enum
#define IOBUFCTRL_FREE 2 {
#define IOBUFCTRL_UNDERFLOW 3 IOBUFCTRL_INIT = 1,
#define IOBUFCTRL_FLUSH 4 IOBUFCTRL_FREE = 2,
#define IOBUFCTRL_DESC 5 IOBUFCTRL_UNDERFLOW = 3,
#define IOBUFCTRL_CANCEL 6 IOBUFCTRL_FLUSH = 4,
#define IOBUFCTRL_USER 16 IOBUFCTRL_DESC = 5,
IOBUFCTRL_CANCEL = 6,
IOBUFCTRL_USER = 16
};
/* Command codes for iobuf_ioctl. */ /* Command codes for iobuf_ioctl. */
@ -60,8 +120,17 @@ typedef enum
enum enum
{ {
/* Pipeline is in input mode. The data flows from the end to the
beginning. That is, when reading from the pipeline, the first
filter gets its input from the second filter, etc. */
IOBUF_INPUT=1, IOBUF_INPUT=1,
/* Pipeline is in output mode. The data flows from the beginning
to the end. That is, when writing to the pipeline, the user
writes to the first filter, which transforms the data and sends
it to the second filter, etc. */
IOBUF_OUTPUT=2, IOBUF_OUTPUT=2,
/* Pipeline is in output mode. The last filter in the pipeline is
a temporary buffer that grows as necessary. */
IOBUF_TEMP=3 IOBUF_TEMP=3
}; };
@ -75,33 +144,105 @@ struct iobuf_struct
/* The type of filter. Either IOBUF_INPUT, IOBUF_OUTPUT or /* The type of filter. Either IOBUF_INPUT, IOBUF_OUTPUT or
IOBUF_TEMP. */ IOBUF_TEMP. */
int use; int use;
/* nlimit can be changed using iobuf_set_limit. If non-zero, it is
the number of additional bytes that can be read from the filter
before EOF is forcefully returned. */
off_t nlimit; off_t nlimit;
off_t nbytes; /* Used together with nlimit. */ /* nbytes if the number of bytes that have been read (using
off_t ntotal; /* Total bytes read (position of stream). */ iobuf_get / iobuf_readbyte / iobuf_read) since the last call to
iobuf_set_limit. */
off_t nbytes;
/* The number of bytes read prior to the last call to
iobuf_set_limit. Thus, the total bytes read (i.e., the position
of stream) is ntotal + nbytes. */
off_t ntotal;
/* Whether we need to read from the filter one byte at a time or /* Whether we need to read from the filter one byte at a time or
whether we can do bulk reads. We need to read one byte at a time whether we can do bulk reads. We need to read one byte at a time
if a limit (set via iobuf_set_limit) is active. */ if a limit (set via iobuf_set_limit) is active. */
int nofast; int nofast;
/* A buffer for unread/unwritten data.
For an output pipeline (IOBUF_OUTPUT), this is the data that has
not yet been written to the filter. Consider a simple pipeline
consisting of a single stage, which writes to a file. When you
write to the pipeline (iobuf_writebyte or iobuf_write), the data
is first stored in this buffer. Only when the buffer is full or
you call iobuf_flush() is FILTER actually called and the data
written to the file.
For an input pipeline (IOBUF_INPUT), this is the data that has
been read from this filter, but not yet been read from the
preceding filter (or the user, if this filter is the head of the
pipeline). Again, consider a simple pipeline consisting of a
single stage. This stage reads from a file. If you read a
single byte (iobuf_get) and the buffer is empty, then FILTER is
called to fill the buffer. In this case, a single byte is not
requested, but the whole buffer is filled (if possible). */
struct struct
{ {
size_t size; /* Allocated size */ /* Size of the buffer. */
size_t start; /* Number of invalid bytes at the size_t size;
begin of the buffer */ /* Number of bytes at the beginning of the buffer that have
size_t len; /* Currently filled to this size */ already been consumed. (In other words: the index of the first
byte that hasn't been consumed.) This is only non-zero for
input filters. */
size_t start;
/* The number of bytes in the buffer including any bytes that have
been consumed. */
size_t len;
/* The buffer itself. */
byte *buf; byte *buf;
} d; } d;
/* When FILTER is called to read some data, it may read some data
and then return EOF. We can't return the EOF immediately.
Instead, we note that we observed the EOF and when the buffer is
finally empty, we return the EOF. */
int filter_eof; int filter_eof;
/* Like filter_eof, when FILTER is called to read some data, it may
read some data and then return an error. We can't return the
error (in the form of an EOF) immediately. Instead, we note that
we observed the error and when the buffer is finally empty, we
return the EOF. */
int error; int error;
/* The callback function to read data from the filter, etc. See
iobuf_filter_push for details. */
int (*filter) (void *opaque, int control, int (*filter) (void *opaque, int control,
iobuf_t chain, byte * buf, size_t * len); iobuf_t chain, byte * buf, size_t * len);
void *filter_ov; /* Value for opaque */ /* An opaque pointer that can be used for local filter state. This
is passed as the first parameter to FILTER. */
void *filter_ov;
/* Whether the iobuf code should free(filter_ov) when destroying the
filter. */
int filter_ov_owner; int filter_ov_owner;
/* When using iobuf_open, iobuf_create, iobuf_openrw to open a file,
the file's name is saved here. This is used to delete the file
when an output pipeline (IOBUF_OUPUT) is canceled
(iobuf_cancel). */
char *real_fname; char *real_fname;
iobuf_t chain; /* Next iobuf used for i/o if any
(passed to filter) */ /* The next filter in the pipeline. */
int no, subno; iobuf_t chain;
/* This field is for debugging. Each time a filter is allocated
(via iobuf_alloc()), a monotonically increasing counter is
incremented and this field is set to the new value. This field
should only be accessed via the iobuf_io macro. */
int no;
/* The number of filters in the pipeline following (not including)
this one. When you call iobuf_push_filter or iobuf_push_filter2,
this value is used to check the length of the pipeline if the
pipeline already contains 65 stages then these functions fail.
This amount of nesting typically indicates corrupted data or an
active denial of service attack. */
int subno;
}; };
#ifndef EXTERN_UNLESS_MAIN_MODULE #ifndef EXTERN_UNLESS_MAIN_MODULE
@ -113,78 +254,350 @@ struct iobuf_struct
#endif #endif
EXTERN_UNLESS_MAIN_MODULE int iobuf_debug_mode; EXTERN_UNLESS_MAIN_MODULE int iobuf_debug_mode;
/* Whether iobuf_open, iobuf_create and iobuf_is_pipefilename
recognize special filenames. Special filenames are of the form
"-&nnnn" where n is a positive integer. The integer corresponds to
a file descriptor. Note: these functions always recognize the
special filename '-', which corresponds to standard input. */
void iobuf_enable_special_filenames (int yes); void iobuf_enable_special_filenames (int yes);
/* Returns whether the specified filename corresponds to a pipe. In
particular, this function checks if FNAME is "-" and, if special
filenames are enabled (see iobuf_enable_special_filenames), whether
FNAME is a special filename. */
int iobuf_is_pipe_filename (const char *fname); int iobuf_is_pipe_filename (const char *fname);
/* Allocate a new filter. This filter doesn't have a function
assigned to it. Thus you need to manually set IOBUF->FILTER and
IOBUF->FILTER_OV, if required. This function is intended to help
create a new primary source or primary sink, i.e., the last filter
in the pipeline.
USE is IOBUF_INPUT, IOBUF_OUTPUT or IOBUF_TEMP.
BUFSIZE is the desired internal buffer size (that is, the size of
the typical read / write request). */
iobuf_t iobuf_alloc (int use, size_t bufsize); iobuf_t iobuf_alloc (int use, size_t bufsize);
/* Create an output filter that simply buffers data written to it.
This is useful for collecting data for later processing. The
buffer can be written to in the usual way (iobuf_write, etc.). The
data can later be extracted using iobuf_write_temp() or
iobuf_temp_to_buffer(). */
iobuf_t iobuf_temp (void); iobuf_t iobuf_temp (void);
/* Create an input filter that contains some data for reading. */
iobuf_t iobuf_temp_with_content (const char *buffer, size_t length); iobuf_t iobuf_temp_with_content (const char *buffer, size_t length);
/* Create an input file filter that reads from a file. If FNAME is
'-', reads from stdin. If special filenames are enabled
(iobuf_enable_special_filenames), then interprets special
filenames. */
iobuf_t iobuf_open (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); /* Create an output file filter that writes to a file. If FNAME is
iobuf_t iobuf_esopen (estream_t estream, const char *mode, int keep_open); NULL or '-', writes to stdout. If special filenames are enabled
iobuf_t iobuf_sockopen (int fd, const char *mode); (iobuf_enable_special_filenames), then interprets special
filenames. If FNAME is not NULL, '-' or a special filename, the
file is opened for writing. If the file exists, it is truncated.
If MODE700 is TRUE, the file is created with mode 600. Otherwise,
mode 666 is used. */
iobuf_t iobuf_create (const char *fname, int mode700); iobuf_t iobuf_create (const char *fname, int mode700);
/* Create an output file filter that writes to a specified file.
Neither '-' nor special file names are recognized. */
iobuf_t iobuf_openrw (const char *fname); iobuf_t iobuf_openrw (const char *fname);
/* Create a file filter using an existing file descriptor. If MODE
contains the letter 'w', creates an output filter. Otherwise,
creates an input filter. Note: MODE must reflect the file
descriptors actual mode! When the filter is destroyed, the file
descriptor is closed. */
iobuf_t iobuf_fdopen (int fd, const char *mode);
/* Like iobuf_fdopen, but doesn't close the file descriptor when the
filter is destroyed. */
iobuf_t iobuf_fdopen_nc (int fd, const char *mode);
/* Create a filter using an existing estream. If MODE contains the
letter 'w', creates an output filter. Otherwise, creates an input
filter. If KEEP_OPEN is TRUE, then the stream is not closed when
the filter is destroyed. Otherwise, the stream is closed when the
filter is destroyed. */
iobuf_t iobuf_esopen (estream_t estream, const char *mode, int keep_open);
/* Create a filter using an existing socket. On Windows creates a
special socket filter. On non-Windows systems simply, this simply
calls iobuf_fdopen. */
iobuf_t iobuf_sockopen (int fd, const char *mode);
/* Set various options / perform different actions on a PIPELINE. See
the IOBUF_IOCTL_* macros above. */
int iobuf_ioctl (iobuf_t a, iobuf_ioctl_t cmd, int intval, void *ptrval); int iobuf_ioctl (iobuf_t a, iobuf_ioctl_t cmd, int intval, void *ptrval);
/* Close a pipeline. The filters in the pipeline are first flushed
using iobuf_flush, if they are output filters, and then
IOBUFCTRL_FREE is called on each filter.
If any filter returns a non-zero value in response to the
IOBUFCTRL_FREE, that first such non-zero value is returned. Note:
processing is not aborted in this case. If all filters are freed
successfully, 0 is returned. */
int iobuf_close (iobuf_t iobuf); int iobuf_close (iobuf_t iobuf);
/* Calls IOBUFCTRL_CANCEL on each filter in the pipeline. Then calls
io_close() on the pipeline. Finally, if the pipeline is an output
pipeline, deletes the file. Returns the result of calling
iobuf_close on the pipeline. */
int iobuf_cancel (iobuf_t iobuf); int iobuf_cancel (iobuf_t iobuf);
/* Add a new filter to the front of a pipeline. A is the head of the
pipeline. F is the filter implementation. OV is an opaque pointer
that is passed to F and is normally used to hold any internal
state, such as a file pointer.
Note: you may only maintain a reference to an iobuf_t as a
reference to the head of the pipeline. That is, don't think about
setting a pointer in OV to point to the filter's iobuf_t. This is
because when we add a new filter to a pipeline, we memcpy the state
in A into new buffer. This has the advantage that there is no need
to update any references to the pipeline when a filter is added or
removed, but it also means that a filter's state moves around in
memory.
The behavior of the filter function is determined by the value of
the control parameter:
IOBUFCTRL_INIT: Called this value just before the filter is
linked into the pipeline. This can be used to initialize
internal data structures.
IOBUFCTRL_FREE: Called with this value just before the filter is
removed from the pipeline. Normally used to release internal
data structures, close a file handle, etc.
IOBUFCTRL_UNDERFLOW: Called with this value to fill the passed
buffer with more data. *LEN is the size of the buffer. Before
returning, it should be set to the number of bytes which were
written into the buffer. The function must return 0 to
indicate success, -1 on EOF and a GPG_ERR_xxxxx code for any
error.
Note: this function may both return data and indicate an error
or EOF. In this case, it simply writes the data to BUF, sets
*LEN and returns the appropriate return code. The implication
is that if an error occurs and no data has yet been written, it
is essential that *LEN be set to 0!
IOBUFCTRL_FLUSH: Called with this value to write out any
collected data. *LEN is the number of bytes in BUF that need
to be written out. Returns 0 on success and a GPG_ERR_* code
otherwise. *LEN must be set to the number of bytes that were
written out.
IOBUFCTRL_CANCEL: Called with this value when iobuf_cancel() is
called on the pipeline.
IOBUFCTRL_DESC: Called with this value to get a human-readable
description of the filter. * (char **) BUF should set to the
NUL-terminated string. Note: you need to keep track of this
value and, if necessary, free it when the filter function is
called with control set to IOBUFCTRL_FREE.
*/
int iobuf_push_filter (iobuf_t a, int (*f) (void *opaque, int control, int iobuf_push_filter (iobuf_t a, int (*f) (void *opaque, int control,
iobuf_t chain, byte * buf, iobuf_t chain, byte * buf,
size_t * len), void *ov); size_t * len), void *ov);
/* This variant of iobuf_push_filter allows the called to indicate
that OV should be freed when this filter is freed. That is, if
REL_OV is TRUE, then when the filter is popped or freed OV will be
freed after the filter function is called with control set to
IOBUFCTRL_FREE. */
int iobuf_push_filter2 (iobuf_t a, int iobuf_push_filter2 (iobuf_t a,
int (*f) (void *opaque, int control, iobuf_t chain, int (*f) (void *opaque, int control, iobuf_t chain,
byte * buf, size_t * len), void *ov, byte * buf, size_t * len), void *ov,
int rel_ov); int rel_ov);
/* Used for debugging. Prints out the chain using log_debug if
IOBUF_DEBUG_MODE is not 0. */
int iobuf_print_chain (iobuf_t a);
/* Indicate that some error occured on the specified filter. */
#define iobuf_set_error(a) do { (a)->error = 1; } while(0) #define iobuf_set_error(a) do { (a)->error = 1; } while(0)
/* Return any pending error on filter A. */
#define iobuf_error(a) ((a)->error) #define iobuf_error(a) ((a)->error)
/* Limit the amount of additional data that may be read from the
filter. That is, if you've already read 100 bytes from A and you
set the limit to 50, then you can read up to an additional 50 bytes
(i.e., a total of 150 bytes) before EOF is forcefully returned.
Setting NLIMIT to 0 removes any active limit.
Note: using iobuf_seek removes any currently enforced limit! */
void iobuf_set_limit (iobuf_t a, off_t nlimit); void iobuf_set_limit (iobuf_t a, off_t nlimit);
/* Returns the number of bytes that have been read from the pipeline.
Note: the result is undefined for IOBUF_OUTPUT and IOBUF_TEMP
pipelines! */
off_t iobuf_tell (iobuf_t a); off_t iobuf_tell (iobuf_t a);
/* There are two cases:
- If A is an INPUT or OUTPUT pipeline, then the last filter in the
pipeline is found. If that is not a file filter, -1 is returned.
Otherwise, an fseek(..., SEEK_SET) is performed on the file
descriptor.
- If A is a TEMP pipeline and the *first* (and thus only filter) is
a TEMP filter, then the "file position" is effectively unchanged.
That is, data is appended to the buffer and the seek does not
cause the size of the buffer to grow.
If no error occured, then any limit previous set by
iobuf_set_limit() is cleared. Further, any error on the filter
(the file filter or the temp filter) is cleared.
Returns 0 on success and -1 if an error occurs. */
int iobuf_seek (iobuf_t a, off_t newpos); int iobuf_seek (iobuf_t a, off_t newpos);
/* Read a single byte. If a filter has no more data, returns -1 to
indicate the EOF. Generally, you don't want to use this function,
but instead prefer the iobuf_get macro, which is faster if there is
data in the internal buffer. */
int iobuf_readbyte (iobuf_t a); int iobuf_readbyte (iobuf_t a);
int iobuf_read (iobuf_t a, void *buf, unsigned buflen);
unsigned iobuf_read_line (iobuf_t a, byte ** addr_of_buffer,
unsigned *length_of_buffer, unsigned *max_length);
int iobuf_peek (iobuf_t a, byte * buf, unsigned buflen);
int iobuf_writebyte (iobuf_t a, unsigned c);
int iobuf_write (iobuf_t a, const void *buf, unsigned buflen);
int iobuf_writestr (iobuf_t a, const char *buf);
void iobuf_flush_temp (iobuf_t temp);
int iobuf_write_temp (iobuf_t a, iobuf_t temp);
size_t iobuf_temp_to_buffer (iobuf_t a, byte * buffer, size_t buflen);
off_t iobuf_get_filelength (iobuf_t a, int *overflow);
#define IOBUF_FILELENGTH_LIMIT 0xffffffff
int iobuf_get_fd (iobuf_t a);
const char *iobuf_get_real_fname (iobuf_t a);
const char *iobuf_get_fname (iobuf_t a);
const char *iobuf_get_fname_nonnull (iobuf_t a);
void iobuf_set_partial_block_mode (iobuf_t a, size_t len);
void iobuf_skip_rest (iobuf_t a, unsigned long n, int partial);
/* Get a byte from the iobuf; must check for eof prior to this /* Get a byte from the iobuf; must check for eof prior to this
* function. This function returns values in the range 0 .. 255 or -1 function. This function returns values in the range 0 .. 255 or -1
* to indicate EOF. iobuf_get_noeof() does not return -1 to indicate to indicate EOF. iobuf_get_noeof() does not return -1 to indicate
* EOF, but masks the returned value to be in the range 0 .. 255. EOF, but masks the returned value to be in the range 0 .. 255. */
*/
#define iobuf_get(a) \ #define iobuf_get(a) \
( ((a)->nofast || (a)->d.start >= (a)->d.len )? \ ( ((a)->nofast || (a)->d.start >= (a)->d.len )? \
iobuf_readbyte((a)) : ( (a)->nbytes++, (a)->d.buf[(a)->d.start++] ) ) iobuf_readbyte((a)) : ( (a)->nbytes++, (a)->d.buf[(a)->d.start++] ) )
#define iobuf_get_noeof(a) (iobuf_get((a))&0xff) #define iobuf_get_noeof(a) (iobuf_get((a))&0xff)
/* write a byte to the iobuf and return true on write error /* Fill BUF with up to BUFLEN bytes. If a filter has no more data,
* This macro does only write the low order byte returns -1 to indicate the EOF. Otherwise returns the number of
*/ bytes read. */
int iobuf_read (iobuf_t a, void *buf, unsigned buflen);
/* Read a line of input (including the '\n') from the pipeline.
The semantics are the same as for fgets(), but if the buffer is too
short a larger one will be allocated up to *MAX_LENGTH and the end
of the line except the trailing '\n' discarded. (Thus,
*ADDR_OF_BUFFER must be allocated using malloc().) If the buffer
is enlarged, then *LENGTH_OF_BUFFER will be updated to reflect the
new size. If the line is truncated, then *MAX_LENGTH will be set
to 0. If *ADDR_OF_BUFFER is NULL, a buffer is allocated using
malloc().
A line is considered a byte stream ending in a '\n'. Returns the
number of characters written to the buffer (i.e., excluding any
discarded characters due to truncation). Thus, use this instead of
strlen(buffer) to determine the length of the string as this is
unreliable if the input contains NUL characters.
EOF is indicated by a line of length zero.
The last LF may be missing due to an EOF. */
unsigned iobuf_read_line (iobuf_t a, byte ** addr_of_buffer,
unsigned *length_of_buffer, unsigned *max_length);
/* Read up to BUFLEN bytes from pipeline A. Note: this function can't
return more than the pipeline's internal buffer size. The return
value is the number of bytes actually written to BUF. If the
filter returns EOF, then this function returns -1.
This function does not clear any pending EOF. That is, if the
pipeline consists of two filters and the first one returns EOF
during the peek, then the subsequent iobuf_read* will still return
EOF before returning the data from the second filter. */
int iobuf_peek (iobuf_t a, byte * buf, unsigned buflen);
/* Write a byte to the pipeline. Returns 0 on success and an error
code otherwise. */
int iobuf_writebyte (iobuf_t a, unsigned c);
/* Alias for iobuf_writebyte. */
#define iobuf_put(a,c) iobuf_writebyte(a,c) #define iobuf_put(a,c) iobuf_writebyte(a,c)
/* Write a sequence of bytes to the pipeline. Returns 0 on success
and an error code otherwise. */
int iobuf_write (iobuf_t a, const void *buf, unsigned buflen);
/* Write a string (not including the NUL terminator) to the pipeline.
Returns 0 on success and an error code otherwise. */
int iobuf_writestr (iobuf_t a, const char *buf);
/* Flushes the pipeline removing all filters but the sink (the last
filter) in the process. */
void iobuf_flush_temp (iobuf_t temp);
/* Flushes the pipeline SOURCE removing all filters but the sink (the
last filter) in the process (i.e., it calls
iobuf_flush_temp(source)) and then writes the data to the pipeline
DEST. Note: this doesn't free (iobuf_close()) SOURCE. Both SOURCE
and DEST must be output pipelines. */
int iobuf_write_temp (iobuf_t dest, iobuf_t source);
/* Flushes each filter in the pipeline (i.e., sends any buffered data
to the filter by calling IOBUFCTRL_FLUSH). Then, copies up to the
first BUFLEN bytes from the last filter's internal buffer (which
will only be non-empty if it is a temp filter) to the buffer
BUFFER. Returns the number of bytes actually copied. */
size_t iobuf_temp_to_buffer (iobuf_t a, byte * buffer, size_t buflen);
/* Return the size of any underlying file. This only works with
file_filter based pipelines.
On Win32, it is sometimes not possible to determine the size of
files larger than 4GB. In this case, *OVERFLOW (if not NULL) is
set to 1. Otherwise, *OVERFLOW is set to 0. */
off_t iobuf_get_filelength (iobuf_t a, int *overflow);
#define IOBUF_FILELENGTH_LIMIT 0xffffffff
/* Return the file descriptor designating the underlying file. This
only works with file_filter based pipelines. */
int iobuf_get_fd (iobuf_t a);
/* Return the real filename, if available. This only supports
pipelines that end in file filters. Returns NULL if not
available. */
const char *iobuf_get_real_fname (iobuf_t a);
/* Return the filename or a description thereof. For instance, for
iobuf_open("-"), this will return "[stdin]". This only supports
pipelines that end in file filters. Returns NULL if not
available. */
const char *iobuf_get_fname (iobuf_t a);
/* Like iobuf_getfname, but instead of returning NULL if no
description is available, return "[?]". */
const char *iobuf_get_fname_nonnull (iobuf_t a);
/* Pushes a filter on the pipeline that interprets the datastream as
an OpenPGP data block whose length is encoded using partial body
length headers (see Section 4.2.2.4 of RFC 4880). Concretely, it
just returns / writes the data and finishes the packet with an
EOF. */
void iobuf_set_partial_block_mode (iobuf_t a, size_t len);
/* If PARTIAL is set, then read from the pipeline until the first EOF
is returned.
If PARTIAL is 0, then read up to N bytes or until the first EOF is
returned.
Recall: a filter can return EOF. In this case, it and all
preceding filters are popped from the pipeline and the next read is
from the following filter (which may or may not return EOF). */
void iobuf_skip_rest (iobuf_t a, unsigned long n, int partial);
#define iobuf_where(a) "[don't know]" #define iobuf_where(a) "[don't know]"
/* Each time a filter is allocated (via iobuf_alloc()), a
monotonically increasing counter is incremented and this field is
set to the new value. This macro returns that number. */
#define iobuf_id(a) ((a)->no) #define iobuf_id(a) ((a)->no)
#define iobuf_get_temp_buffer(a) ( (a)->d.buf ) #define iobuf_get_temp_buffer(a) ( (a)->d.buf )