aboutsummaryrefslogtreecommitdiffstats
path: root/common/estream.c
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2014-04-15 14:40:48 +0000
committerWerner Koch <[email protected]>2014-04-30 19:14:28 +0000
commit8416c875a729426eae05ed1ca9f1ebcb933c246a (patch)
tree1fcc94bb74e17505af4d27fe6dbbcc361d137044 /common/estream.c
parentestream: Fix deadlock in es_fileno. (diff)
downloadgnupg-8416c875a729426eae05ed1ca9f1ebcb933c246a.tar.gz
gnupg-8416c875a729426eae05ed1ca9f1ebcb933c246a.zip
estream: Implement "samethread" mode keyword.
* src/estream.c (estream_internal): Add field SAMETHREAD. (init_stream_lock, lock_stream, trylock_stream, unlock_stream): Use it. (parse_mode): Add arg SAMETHREAD and parse that keyword. (es_initialize): Rename to ... (init_stream_obj): this. Add arg SAMETHREAD. (es_create): Add arg SAMETHREAD. Call init_stream_lock after init_stream_obj. (doreadline): Call es_create with samethread flag. (es_fopen, es_mopen, es_fopenmem, es_fopencookie, do_fdopen) (do_fpopen, do_w32open): Implement "samethread" keyword. (es_freopen): Take samthread flag from old stream. (es_tmpfile): Call es)_create w/o samethread. -- Note: Unfortunately es_tmpfile has no mode arg so that we can't use samethread.
Diffstat (limited to 'common/estream.c')
-rw-r--r--common/estream.c161
1 files changed, 107 insertions, 54 deletions
diff --git a/common/estream.c b/common/estream.c
index a20d6d4e3..34726a3e4 100644
--- a/common/estream.c
+++ b/common/estream.c
@@ -1,5 +1,6 @@
/* estream.c - Extended Stream I/O Library
- * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010, 2011 g10 Code GmbH
+ * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010, 2011,
+ * 2014 g10 Code GmbH
*
* This file is part of Libestream.
*
@@ -221,6 +222,7 @@ struct estream_internal
unsigned int is_stdstream:1; /* This is a standard stream. */
unsigned int stdstream_fd:2; /* 0, 1 or 2 for a standard stream. */
unsigned int printable_fname_inuse: 1; /* es_fname_get has been used. */
+ unsigned int samethread: 1; /* The "samethread" mode keyword. */
size_t print_ntotal; /* Bytes written from in print_writer. */
notify_list_t onclose; /* On close notify function list. */
};
@@ -359,9 +361,14 @@ init_stream_lock (estream_t ES__RESTRICT stream)
#ifdef HAVE_NPTH
int rc;
- dbg_lock_1 ("enter init_stream_lock for %p\n", stream);
- rc = npth_mutex_init (&stream->intern->lock, NULL);
- dbg_lock_2 ("leave init_stream_lock for %p: rc=%d\n", stream, rc);
+ if (!stream->intern->samethread)
+ {
+ dbg_lock_1 ("enter init_stream_lock for %p\n", stream);
+ rc = npth_mutex_init (&stream->intern->lock, NULL);
+ dbg_lock_2 ("leave init_stream_lock for %p: rc=%d\n", stream, rc);
+ }
+ else
+ rc = 0;
return rc;
#else
(void)stream;
@@ -374,9 +381,12 @@ static void
lock_stream (estream_t ES__RESTRICT stream)
{
#ifdef HAVE_NPTH
- dbg_lock_1 ("enter lock_stream for %p\n", stream);
- npth_mutex_lock (&stream->intern->lock);
- dbg_lock_1 ("leave lock_stream for %p\n", stream);
+ if (!stream->intern->samethread)
+ {
+ dbg_lock_1 ("enter lock_stream for %p\n", stream);
+ npth_mutex_lock (&stream->intern->lock);
+ dbg_lock_1 ("leave lock_stream for %p\n", stream);
+ }
#else
(void)stream;
#endif
@@ -389,9 +399,14 @@ trylock_stream (estream_t ES__RESTRICT stream)
#ifdef HAVE_NPTH
int rc;
- dbg_lock_1 ("enter trylock_stream for %p\n", stream);
- rc = npth_mutex_trylock (&stream->intern->lock)? 0 : -1;
- dbg_lock_2 ("leave trylock_stream for %p: rc=%d\n", stream, rc);
+ if (!stream->intern->samethread)
+ {
+ dbg_lock_1 ("enter trylock_stream for %p\n", stream);
+ rc = npth_mutex_trylock (&stream->intern->lock)? 0 : -1;
+ dbg_lock_2 ("leave trylock_stream for %p: rc=%d\n", stream, rc);
+ }
+ else
+ rc = 0;
return rc;
#else
(void)stream;
@@ -404,9 +419,12 @@ static void
unlock_stream (estream_t ES__RESTRICT stream)
{
#ifdef HAVE_NPTH
- dbg_lock_1 ("enter unlock_stream for %p\n", stream);
- npth_mutex_unlock (&stream->intern->lock);
- dbg_lock_1 ("leave unlock_stream for %p\n", stream);
+ if (!stream->intern->samethread)
+ {
+ dbg_lock_1 ("enter unlock_stream for %p\n", stream);
+ npth_mutex_unlock (&stream->intern->lock);
+ dbg_lock_1 ("leave unlock_stream for %p\n", stream);
+ }
#else
(void)stream;
#endif
@@ -1478,29 +1496,40 @@ func_file_create (void **cookie, int *filedes,
defined mode flags keyword parameters are supported. These are
key/value pairs delimited by comma and optional white spaces.
Keywords and values may not contain a comma or white space; unknown
- keyword are skipped. The only supported keyword is mode; for
- example:
+ keywords are skipped. Supported keywords are:
+
+ mode=<string>
+
+ Creates a file and gives the new file read and write permissions
+ for the user and read permission for the group. The format of
+ the string is the same as shown by the -l option of the ls(1)
+ command. However the first letter must be a dash and it is
+ allowed to leave out trailing dashes. If this keyword parameter
+ is not given the default mode for creating files is "-rw-rw-r--"
+ (664). Note that the system still applies the current umask to
+ the mode when crating a file. Example:
+
+ "wb,mode=-rw-r--"
+
+ samethread
- "wb,mode=-rw-r--"
+ Assumes that the object is only used by the creating thread and
+ disables any internal locking. This keyword is also found on
+ IBM systems.
- Creates a file and gives the new file read and write permissions
- for the user and read permission for the group. The format of the
- string is the same as shown by the -l option of the ls(1) command.
- However the first letter must be a dash and it is allowed to leave
- out trailing dashes. If this keyword parameter is not given the
- default mode for creating files is "-rw-rw-r--" (664). Note that
- the system still applies the current umask to the mode when crating
- a file.
Note: R_CMODE is optional because is only required by functions
which are able to creat a file. */
static int
parse_mode (const char *modestr,
- unsigned int *modeflags, unsigned int *r_cmode)
+ unsigned int *modeflags, int *samethread,
+ unsigned int *r_cmode)
{
unsigned int omode, oflags, cmode;
int got_cmode = 0;
+ *samethread = 0;
+
switch (*modestr)
{
case 'r':
@@ -1573,6 +1602,16 @@ parse_mode (const char *modestr,
return -1;
}
}
+ else if (!strncmp (modestr, "samethread", 10))
+ {
+ modestr += 10;
+ if (*modestr && !strchr (" \t,", *modestr))
+ {
+ _set_errno (EINVAL);
+ return -1;
+ }
+ *samethread = 1;
+ }
}
if (!got_cmode)
cmode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
@@ -1712,10 +1751,10 @@ es_empty (estream_t stream)
/* Initialize STREAM. */
static void
-es_initialize (estream_t stream,
- void *cookie, es_syshd_t *syshd,
- es_cookie_io_functions_t functions,
- unsigned int modeflags)
+init_stream_obj (estream_t stream,
+ void *cookie, es_syshd_t *syshd,
+ es_cookie_io_functions_t functions,
+ unsigned int modeflags, int samethread)
{
stream->intern->cookie = cookie;
stream->intern->opaque = NULL;
@@ -1735,6 +1774,7 @@ es_initialize (estream_t stream,
stream->intern->deallocate_buffer = 0;
stream->intern->printable_fname = NULL;
stream->intern->printable_fname_inuse = 0;
+ stream->intern->samethread = !!samethread;
stream->intern->onclose = NULL;
stream->data_len = 0;
@@ -1784,7 +1824,7 @@ es_deinitialize (estream_t stream)
static int
es_create (estream_t *stream, void *cookie, es_syshd_t *syshd,
es_cookie_io_functions_t functions, unsigned int modeflags,
- int with_locked_list)
+ int samethread, int with_locked_list)
{
estream_internal_t stream_internal_new;
estream_t stream_new;
@@ -1813,8 +1853,8 @@ es_create (estream_t *stream, void *cookie, es_syshd_t *syshd,
stream_new->unread_buffer_size = sizeof (stream_internal_new->unread_buffer);
stream_new->intern = stream_internal_new;
+ init_stream_obj (stream_new, cookie, syshd, functions, modeflags, samethread);
init_stream_lock (stream_new);
- es_initialize (stream_new, cookie, syshd, functions, modeflags);
err = do_list_add (stream_new, with_locked_list);
if (err)
@@ -2406,7 +2446,7 @@ doreadline (estream_t ES__RESTRICT stream, size_t max_length,
memset (&syshd, 0, sizeof syshd);
err = es_create (&line_stream, line_stream_cookie, &syshd,
- estream_functions_mem, O_RDWR, 0);
+ estream_functions_mem, O_RDWR, 1, 0);
if (err)
goto out;
@@ -2667,7 +2707,7 @@ estream_t
es_fopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode)
{
unsigned int modeflags, cmode;
- int create_called;
+ int samethread, create_called;
estream_t stream;
void *cookie;
int err;
@@ -2678,7 +2718,7 @@ es_fopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode)
cookie = NULL;
create_called = 0;
- err = parse_mode (mode, &modeflags, &cmode);
+ err = parse_mode (mode, &modeflags, &samethread, &cmode);
if (err)
goto out;
@@ -2690,7 +2730,8 @@ es_fopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode)
syshd.u.fd = fd;
create_called = 1;
- err = es_create (&stream, cookie, &syshd, estream_functions_fd, modeflags, 0);
+ err = es_create (&stream, cookie, &syshd, estream_functions_fd, modeflags,
+ samethread, 0);
if (err)
goto out;
@@ -2731,10 +2772,11 @@ es_mopen (void *ES__RESTRICT data, size_t data_n, size_t data_len,
estream_t stream = NULL;
void *cookie = NULL;
unsigned int modeflags;
+ int samethread;
int err;
es_syshd_t syshd;
- err = parse_mode (mode, &modeflags, NULL);
+ err = parse_mode (mode, &modeflags, &samethread, NULL);
if (err)
goto out;
@@ -2747,7 +2789,7 @@ es_mopen (void *ES__RESTRICT data, size_t data_n, size_t data_len,
memset (&syshd, 0, sizeof syshd);
create_called = 1;
err = es_create (&stream, cookie, &syshd,
- estream_functions_mem, modeflags, 0);
+ estream_functions_mem, modeflags, samethread, 0);
out:
@@ -2763,13 +2805,14 @@ estream_t
es_fopenmem (size_t memlimit, const char *ES__RESTRICT mode)
{
unsigned int modeflags;
+ int samethread;
estream_t stream = NULL;
void *cookie = NULL;
es_syshd_t syshd;
/* Memory streams are always read/write. We use MODE only to get
the append flag. */
- if (parse_mode (mode, &modeflags, NULL))
+ if (parse_mode (mode, &modeflags, &samethread, NULL))
return NULL;
modeflags |= O_RDWR;
@@ -2780,7 +2823,8 @@ es_fopenmem (size_t memlimit, const char *ES__RESTRICT mode)
return NULL;
memset (&syshd, 0, sizeof syshd);
- if (es_create (&stream, cookie, &syshd, estream_functions_mem, modeflags, 0))
+ if (es_create (&stream, cookie, &syshd, estream_functions_mem, modeflags,
+ samethread, 0))
(*estream_functions_mem.func_close) (cookie);
if (stream)
@@ -2830,6 +2874,7 @@ es_fopencookie (void *ES__RESTRICT cookie,
es_cookie_io_functions_t functions)
{
unsigned int modeflags;
+ int samethread;
estream_t stream;
int err;
es_syshd_t syshd;
@@ -2837,12 +2882,13 @@ es_fopencookie (void *ES__RESTRICT cookie,
stream = NULL;
modeflags = 0;
- err = parse_mode (mode, &modeflags, NULL);
+ err = parse_mode (mode, &modeflags, &samethread, NULL);
if (err)
goto out;
memset (&syshd, 0, sizeof syshd);
- err = es_create (&stream, cookie, &syshd, functions, modeflags, 0);
+ err = es_create (&stream, cookie, &syshd, functions, modeflags,
+ samethread, 0);
if (err)
goto out;
@@ -2856,7 +2902,7 @@ estream_t
do_fdopen (int filedes, const char *mode, int no_close, int with_locked_list)
{
unsigned int modeflags;
- int create_called;
+ int samethread, create_called;
estream_t stream;
void *cookie;
int err;
@@ -2866,7 +2912,7 @@ do_fdopen (int filedes, const char *mode, int no_close, int with_locked_list)
cookie = NULL;
create_called = 0;
- err = parse_mode (mode, &modeflags, NULL);
+ err = parse_mode (mode, &modeflags, &samethread, NULL);
if (err)
goto out;
@@ -2878,7 +2924,7 @@ do_fdopen (int filedes, const char *mode, int no_close, int with_locked_list)
syshd.u.fd = filedes;
create_called = 1;
err = es_create (&stream, cookie, &syshd, estream_functions_fd,
- modeflags, with_locked_list);
+ modeflags, samethread, with_locked_list);
out:
if (err && create_called)
@@ -2906,7 +2952,7 @@ estream_t
do_fpopen (FILE *fp, const char *mode, int no_close, int with_locked_list)
{
unsigned int modeflags, cmode;
- int create_called;
+ int samethread, create_called;
estream_t stream;
void *cookie;
int err;
@@ -2916,7 +2962,7 @@ do_fpopen (FILE *fp, const char *mode, int no_close, int with_locked_list)
cookie = NULL;
create_called = 0;
- err = parse_mode (mode, &modeflags, &cmode);
+ err = parse_mode (mode, &modeflags, &samethread, &cmode);
if (err)
goto out;
@@ -2930,7 +2976,7 @@ do_fpopen (FILE *fp, const char *mode, int no_close, int with_locked_list)
syshd.u.fd = fp? fileno (fp): -1;
create_called = 1;
err = es_create (&stream, cookie, &syshd, estream_functions_fp,
- modeflags, with_locked_list);
+ modeflags, samethread, with_locked_list);
out:
@@ -2971,13 +3017,14 @@ do_w32open (HANDLE hd, const char *mode,
int no_close, int with_locked_list)
{
unsigned int modeflags, cmode;
+ int samethread;
int create_called = 0;
estream_t stream = NULL;
void *cookie = NULL;
int err;
es_syshd_t syshd;
- err = parse_mode (mode, &modeflags, &cmode);
+ err = parse_mode (mode, &modeflags, &samethread, &cmode);
if (err)
goto leave;
@@ -2989,7 +3036,7 @@ do_w32open (HANDLE hd, const char *mode,
syshd.u.handle = hd;
create_called = 1;
err = es_create (&stream, cookie, &syshd, estream_functions_w32,
- modeflags, with_locked_list);
+ modeflags, samethread, with_locked_list);
leave:
if (err && create_called)
@@ -3127,7 +3174,8 @@ _es_get_std_stream (int fd)
return stream;
}
-
+/* Note: A "samethread" keyword given in "mode" is ignored and the
+ value used by STREAM is used instead. */
estream_t
es_freopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode,
estream_t ES__RESTRICT stream)
@@ -3137,7 +3185,7 @@ es_freopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode,
if (path)
{
unsigned int modeflags, cmode;
- int create_called;
+ int dummy, samethread, create_called;
void *cookie;
int fd;
es_syshd_t syshd;
@@ -3145,13 +3193,16 @@ es_freopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode,
cookie = NULL;
create_called = 0;
+ samethread = stream->intern->samethread;
+
lock_stream (stream);
es_deinitialize (stream);
- err = parse_mode (mode, &modeflags, &cmode);
+ err = parse_mode (mode, &modeflags, &dummy, &cmode);
if (err)
goto leave;
+ (void)dummy;
err = func_file_create (&cookie, &fd, path, modeflags, cmode);
if (err)
@@ -3160,7 +3211,8 @@ es_freopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode,
syshd.type = ES_SYSHD_FD;
syshd.u.fd = fd;
create_called = 1;
- es_initialize (stream, cookie, &syshd, estream_functions_fd, modeflags);
+ init_stream_obj (stream, cookie, &syshd, estream_functions_fd,
+ modeflags, samethread);
leave:
@@ -4186,7 +4238,8 @@ es_tmpfile (void)
syshd.type = ES_SYSHD_FD;
syshd.u.fd = fd;
create_called = 1;
- err = es_create (&stream, cookie, &syshd, estream_functions_fd, modeflags, 0);
+ err = es_create (&stream, cookie, &syshd, estream_functions_fd, modeflags,
+ 0, 0);
out:
if (err)