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:
parent
0d40c4e83f
commit
1bfd1e4324
190
common/iobuf.c
190
common/iobuf.c
@ -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)
|
||||||
|
515
common/iobuf.h
515
common/iobuf.h
@ -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 )
|
||||||
|
Loading…
x
Reference in New Issue
Block a user