From 26fb537f9cf011eaeaf975adcad5e8e9154d04fd Mon Sep 17 00:00:00 2001 From: Anas Nashif Date: Tue, 19 Feb 2013 08:22:18 -0800 Subject: Imported Upstream version 1.3.2 --- src/data-compat.c | 254 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 254 insertions(+) create mode 100644 src/data-compat.c (limited to 'src/data-compat.c') diff --git a/src/data-compat.c b/src/data-compat.c new file mode 100644 index 0000000..39c743e --- /dev/null +++ b/src/data-compat.c @@ -0,0 +1,254 @@ +/* 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 +#endif + +#include +#ifdef HAVE_SYS_TIME_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#include + +#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) +{ +#if defined (HAVE_W32CE_SYSTEM) && defined (_MSC_VER) + return gpgme_error (GPG_ERR_NOT_IMPLEMENTED); +#else + 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); +#endif +} + + +/* 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) +{ +#if defined (HAVE_W32CE_SYSTEM) && defined (_MSC_VER) + return gpgme_error (GPG_ERR_NOT_IMPLEMENTED); +#else + 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); +#endif +} + + +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)); + gpg_err_set_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) + { + gpg_err_set_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); +} -- cgit v1.2.3