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); +} | 
