diff options
author | Marcus Brinkmann <[email protected]> | 2008-11-03 17:24:09 +0000 |
---|---|---|
committer | Marcus Brinkmann <[email protected]> | 2008-11-03 17:24:09 +0000 |
commit | 66d0fa1973e5e1a1bff619de8b595673d1b76cc5 (patch) | |
tree | 4b1f8e470fa455cbe3d9b5c4ab6fb4fa77f20ba3 /src/data-compat.c | |
parent | assuan/ (diff) | |
download | gpgme-66d0fa1973e5e1a1bff619de8b595673d1b76cc5.tar.gz gpgme-66d0fa1973e5e1a1bff619de8b595673d1b76cc5.zip |
008-11-03 Marcus Brinkmann <[email protected]>
* configure.ac: Replace gpgme paths with src.
* gpgme: Move to ...
* src: ... this new directory.
assuan/
2008-11-03 Marcus Brinkmann <[email protected]>
* Makefile.am (INCLUDES): Replace gpgme path with src.
tests/
2008-11-03 Marcus Brinkmann <[email protected]>
* gpgsm/Makefile.am (INCLUDES, LDADD): Replace gpgme path with src.
* gpg/Makefile.am (INCLUDES, LDADD, t_thread1_LDADD): Likewise.
* Makefile.am (LDADD): Likewise.
Diffstat (limited to 'src/data-compat.c')
-rw-r--r-- | src/data-compat.c | 242 |
1 files changed, 242 insertions, 0 deletions
diff --git a/src/data-compat.c b/src/data-compat.c new file mode 100644 index 00000000..cabe24e2 --- /dev/null +++ b/src/data-compat.c @@ -0,0 +1,242 @@ +/* data-compat.c - Compatibility interfaces for data objects. + Copyright (C) 2002, 2003, 2004, 2007 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + GPGME is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#if HAVE_CONFIG_H +#include <config.h> +#endif + +#include <errno.h> +#include <sys/time.h> +#include <sys/stat.h> +#include <stdlib.h> + +#include "data.h" +#include "util.h" +#include "debug.h" + + +/* Create a new data buffer filled with LENGTH bytes starting from + OFFSET within the file FNAME or stream STREAM (exactly one must be + non-zero). */ +gpgme_error_t +gpgme_data_new_from_filepart (gpgme_data_t *r_dh, const char *fname, + FILE *stream, off_t offset, size_t length) +{ + gpgme_error_t err; + char *buf = NULL; + int res; + + TRACE_BEG4 (DEBUG_DATA, "gpgme_data_new_from_filepart", r_dh, + "file_name=%s, stream=%p, offset=%lli, length=%u", + fname, stream, offset, length); + + if (stream && fname) + return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); + + if (fname) + stream = fopen (fname, "rb"); + if (!stream) + return TRACE_ERR (gpg_error_from_errno (errno)); + +#ifdef HAVE_FSEEKO + res = fseeko (stream, offset, SEEK_SET); +#else + /* FIXME: Check for overflow, or at least bail at compilation. */ + res = fseek (stream, offset, SEEK_SET); +#endif + + if (res) + { + int saved_errno = errno; + if (fname) + fclose (stream); + return TRACE_ERR (gpg_error_from_errno (saved_errno)); + } + + buf = malloc (length); + if (!buf) + { + int saved_errno = errno; + if (fname) + fclose (stream); + return TRACE_ERR (gpg_error_from_errno (saved_errno)); + } + + while (fread (buf, length, 1, stream) < 1 + && ferror (stream) && errno == EINTR); + if (ferror (stream)) + { + int saved_errno = errno; + if (buf) + free (buf); + if (fname) + fclose (stream); + return TRACE_ERR (gpg_error_from_errno (saved_errno)); + } + + if (fname) + fclose (stream); + + err = gpgme_data_new (r_dh); + if (err) + { + if (buf) + free (buf); + return err; + } + + (*r_dh)->data.mem.buffer = buf; + (*r_dh)->data.mem.size = length; + (*r_dh)->data.mem.length = length; + + return TRACE_SUC1 ("r_dh=%p", *r_dh); +} + + +/* Create a new data buffer filled with the content of file FNAME. + COPY must be non-zero (delayed reads are not supported yet). */ +gpgme_error_t +gpgme_data_new_from_file (gpgme_data_t *r_dh, const char *fname, int copy) +{ + gpgme_error_t err; + struct stat statbuf; + TRACE_BEG3 (DEBUG_DATA, "gpgme_data_new_from_filepart", r_dh, + "file_name=%s, copy=%i (%s)", fname, copy, copy ? "yes" : "no"); + + if (!fname || !copy) + return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); + + if (stat (fname, &statbuf) < 0) + return TRACE_ERR (gpg_error_from_errno (errno)); + + err = gpgme_data_new_from_filepart (r_dh, fname, NULL, 0, statbuf.st_size); + return TRACE_ERR (err); +} + + +static int +gpgme_error_to_errno (gpgme_error_t err) +{ + int res = gpg_err_code_to_errno (err); + + if (!err) + { + switch (gpg_err_code (err)) + { + case GPG_ERR_EOF: + res = 0; + break; + case GPG_ERR_INV_VALUE: + res = EINVAL; + break; + case GPG_ERR_NOT_SUPPORTED: + res = ENOSYS; + break; + default: + /* FIXME: Yeah, well. */ + res = EINVAL; + break; + } + } + TRACE3 (DEBUG_DATA, "gpgme:gpgme_error_to_errno", 0, + "mapping %s <%s> to: %s", gpgme_strerror (err), + gpgme_strsource (err), strerror (res)); + errno = res; + return res ? -1 : 0; +} + + +static ssize_t +old_user_read (gpgme_data_t dh, void *buffer, size_t size) +{ + gpgme_error_t err; + size_t amt; + TRACE_BEG2 (DEBUG_DATA, "gpgme:old_user_read", dh, + "buffer=%p, size=%u", buffer, size); + + err = (*dh->data.old_user.cb) (dh->data.old_user.handle, + buffer, size, &amt); + if (err) + return TRACE_SYSRES (gpgme_error_to_errno (err)); + return TRACE_SYSRES (amt); +} + + +static off_t +old_user_seek (gpgme_data_t dh, off_t offset, int whence) +{ + gpgme_error_t err; + TRACE_BEG2 (DEBUG_DATA, "gpgme:old_user_seek", dh, + "offset=%llu, whence=%i", offset, whence); + + if (whence != SEEK_SET || offset) + { + errno = EINVAL; + return TRACE_SYSRES (-1); + } + err = (*dh->data.old_user.cb) (dh->data.old_user.handle, NULL, 0, NULL); + if (err) + return TRACE_SYSRES (gpgme_error_to_errno (err)); + return TRACE_SYSRES (0); +} + + +static struct _gpgme_data_cbs old_user_cbs = + { + old_user_read, + NULL, + old_user_seek, + NULL + }; + + +/* Create a new data buffer which retrieves the data from the callback + function READ_CB. */ +gpgme_error_t +gpgme_data_new_with_read_cb (gpgme_data_t *r_dh, + int (*read_cb) (void *, char *, size_t, size_t *), + void *read_cb_value) +{ + gpgme_error_t err; + TRACE_BEG2 (DEBUG_DATA, "gpgme_data_new_with_read_cb", r_dh, + "read_cb=%p/%p", read_cb, read_cb_value); + + err = _gpgme_data_new (r_dh, &old_user_cbs); + + if (err) + return TRACE_ERR (err); + + (*r_dh)->data.old_user.cb = read_cb; + (*r_dh)->data.old_user.handle = read_cb_value; + return TRACE_ERR (0); +} + + +gpgme_error_t +gpgme_data_rewind (gpgme_data_t dh) +{ + gpgme_error_t err; + TRACE_BEG (DEBUG_DATA, "gpgme_data_rewind", dh); + + err = (gpgme_data_seek (dh, 0, SEEK_SET) == -1) + ? gpg_error_from_errno (errno) : 0; + + return TRACE_ERR (err); +} |