Blame src/data-compat.c

Packit Service 672cf4
/* data-compat.c - Compatibility interfaces for data objects.
Packit Service 6c01f9
   Copyright (C) 2002, 2003, 2004, 2007 g10 Code GmbH
Packit Service 6c01f9
Packit Service 6c01f9
   This file is part of GPGME.
Packit Service 6c01f9
Packit Service 6c01f9
   GPGME is free software; you can redistribute it and/or modify it
Packit Service 6c01f9
   under the terms of the GNU Lesser General Public License as
Packit Service 6c01f9
   published by the Free Software Foundation; either version 2.1 of
Packit Service 6c01f9
   the License, or (at your option) any later version.
Packit Service 6c01f9
Packit Service 6c01f9
   GPGME is distributed in the hope that it will be useful, but
Packit Service 6c01f9
   WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 6c01f9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 6c01f9
   Lesser General Public License for more details.
Packit Service 6c01f9
Packit Service 6c01f9
   You should have received a copy of the GNU Lesser General Public
Packit Service 6c01f9
   License along with this program; if not, write to the Free Software
Packit Service 6c01f9
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
Packit Service 6c01f9
   02111-1307, USA.  */
Packit Service 672cf4
Packit Service 672cf4
#if HAVE_CONFIG_H
Packit Service 672cf4
#include <config.h>
Packit Service 672cf4
#endif
Packit Service 672cf4
Packit Service 672cf4
#include <errno.h>
Packit Service 672cf4
#ifdef HAVE_SYS_TIME_H
Packit Service 672cf4
# include <sys/time.h>
Packit Service 672cf4
#endif
Packit Service 672cf4
#ifdef HAVE_SYS_STAT_H
Packit Service 672cf4
# include <sys/stat.h>
Packit Service 672cf4
#endif
Packit Service 672cf4
#include <stdlib.h>
Packit Service 672cf4
Packit Service 672cf4
#include "data.h"
Packit Service 672cf4
#include "util.h"
Packit Service 672cf4
#include "debug.h"
Packit Service 672cf4
Packit Service 672cf4

Packit Service 672cf4
/* Create a new data buffer filled with LENGTH bytes starting from
Packit Service 672cf4
   OFFSET within the file FNAME or stream STREAM (exactly one must be
Packit Service 672cf4
   non-zero).  */
Packit Service 672cf4
gpgme_error_t
Packit Service 672cf4
gpgme_data_new_from_filepart (gpgme_data_t *r_dh, const char *fname,
Packit Service 672cf4
			      FILE *stream, gpgme_off_t offset, size_t length)
Packit Service 672cf4
{
Packit Service 6c01f9
#if defined (HAVE_W32CE_SYSTEM) && defined (_MSC_VER)
Packit Service 6c01f9
  return gpgme_error (GPG_ERR_NOT_IMPLEMENTED);
Packit Service 6c01f9
#else
Packit Service 672cf4
  gpgme_error_t err;
Packit Service 672cf4
  char *buf = NULL;
Packit Service 672cf4
  int res;
Packit Service 672cf4
Packit Service 6c01f9
  TRACE_BEG4 (DEBUG_DATA, "gpgme_data_new_from_filepart", r_dh,
Packit Service 6c01f9
	      "file_name=%s, stream=%p, offset=%lli, length=%u",
Packit Service 6c01f9
	      fname, stream, offset, length);
Packit Service 672cf4
Packit Service 672cf4
  if (stream && fname)
Packit Service 672cf4
    return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
Packit Service 672cf4
Packit Service 672cf4
  if (fname)
Packit Service 672cf4
    stream = fopen (fname, "rb");
Packit Service 672cf4
  if (!stream)
Packit Service 672cf4
    return TRACE_ERR (gpg_error_from_syserror ());
Packit Service 672cf4
Packit Service 672cf4
#ifdef HAVE_FSEEKO
Packit Service 672cf4
  res = fseeko (stream, offset, SEEK_SET);
Packit Service 672cf4
#else
Packit Service 672cf4
  /* FIXME: Check for overflow, or at least bail at compilation.  */
Packit Service 672cf4
  res = fseek (stream, offset, SEEK_SET);
Packit Service 672cf4
#endif
Packit Service 672cf4
Packit Service 672cf4
  if (res)
Packit Service 672cf4
    {
Packit Service 672cf4
      int saved_err = gpg_error_from_syserror ();
Packit Service 672cf4
      if (fname)
Packit Service 672cf4
	fclose (stream);
Packit Service 672cf4
      return TRACE_ERR (saved_err);
Packit Service 672cf4
    }
Packit Service 672cf4
Packit Service 672cf4
  buf = malloc (length);
Packit Service 672cf4
  if (!buf)
Packit Service 672cf4
    {
Packit Service 672cf4
      int saved_err = gpg_error_from_syserror ();
Packit Service 672cf4
      if (fname)
Packit Service 672cf4
	fclose (stream);
Packit Service 672cf4
      return TRACE_ERR (saved_err);
Packit Service 672cf4
    }
Packit Service 672cf4
Packit Service 672cf4
  while (fread (buf, length, 1, stream) < 1
Packit Service 672cf4
	 && ferror (stream) && errno == EINTR);
Packit Service 672cf4
  if (ferror (stream))
Packit Service 672cf4
    {
Packit Service 672cf4
      int saved_err = gpg_error_from_syserror ();
Packit Service 672cf4
      if (buf)
Packit Service 672cf4
	free (buf);
Packit Service 672cf4
      if (fname)
Packit Service 672cf4
	fclose (stream);
Packit Service 672cf4
      return TRACE_ERR (saved_err);
Packit Service 672cf4
    }
Packit Service 672cf4
Packit Service 672cf4
  if (fname)
Packit Service 672cf4
    fclose (stream);
Packit Service 672cf4
Packit Service 672cf4
  err = gpgme_data_new (r_dh);
Packit Service 672cf4
  if (err)
Packit Service 672cf4
    {
Packit Service 672cf4
      if (buf)
Packit Service 672cf4
	free (buf);
Packit Service 672cf4
      return err;
Packit Service 672cf4
    }
Packit Service 672cf4
Packit Service 672cf4
  (*r_dh)->data.mem.buffer = buf;
Packit Service 672cf4
  (*r_dh)->data.mem.size = length;
Packit Service 672cf4
  (*r_dh)->data.mem.length = length;
Packit Service 672cf4
Packit Service 6c01f9
  return TRACE_SUC1 ("r_dh=%p", *r_dh);
Packit Service 6c01f9
#endif
Packit Service 672cf4
}
Packit Service 672cf4
Packit Service 672cf4

Packit Service 672cf4
/* Create a new data buffer filled with the content of file FNAME.
Packit Service 672cf4
   COPY must be non-zero (delayed reads are not supported yet).  */
Packit Service 672cf4
gpgme_error_t
Packit Service 672cf4
gpgme_data_new_from_file (gpgme_data_t *r_dh, const char *fname, int copy)
Packit Service 672cf4
{
Packit Service 6c01f9
#if defined (HAVE_W32CE_SYSTEM) && defined (_MSC_VER)
Packit Service 6c01f9
  return gpgme_error (GPG_ERR_NOT_IMPLEMENTED);
Packit Service 6c01f9
#else
Packit Service 672cf4
  gpgme_error_t err;
Packit Service 672cf4
  struct stat statbuf;
Packit Service 6c01f9
  TRACE_BEG3 (DEBUG_DATA, "gpgme_data_new_from_file", r_dh,
Packit Service 672cf4
	      "file_name=%s, copy=%i (%s)", fname, copy, copy ? "yes" : "no");
Packit Service 672cf4
Packit Service 672cf4
  if (!fname || !copy)
Packit Service 672cf4
    return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
Packit Service 672cf4
Packit Service 672cf4
  if (stat (fname, &statbuf) < 0)
Packit Service 672cf4
    return TRACE_ERR (gpg_error_from_syserror ());
Packit Service 672cf4
Packit Service 672cf4
  err = gpgme_data_new_from_filepart (r_dh, fname, NULL, 0, statbuf.st_size);
Packit Service 672cf4
  return TRACE_ERR (err);
Packit Service 6c01f9
#endif
Packit Service 672cf4
}
Packit Service 672cf4
Packit Service 672cf4

Packit Service 672cf4
static int
Packit Service 672cf4
gpgme_error_to_errno (gpgme_error_t err)
Packit Service 672cf4
{
Packit Service 672cf4
  int res = gpg_err_code_to_errno (gpg_err_code (err));
Packit Service 672cf4
Packit Service 672cf4
  if (!err)
Packit Service 672cf4
    {
Packit Service 672cf4
      switch (gpg_err_code (err))
Packit Service 672cf4
	{
Packit Service 672cf4
	case GPG_ERR_EOF:
Packit Service 672cf4
	  res = 0;
Packit Service 672cf4
	  break;
Packit Service 672cf4
	case GPG_ERR_INV_VALUE:
Packit Service 672cf4
	  res = EINVAL;
Packit Service 672cf4
	  break;
Packit Service 672cf4
	case GPG_ERR_NOT_SUPPORTED:
Packit Service 672cf4
	  res = ENOSYS;
Packit Service 672cf4
	  break;
Packit Service 672cf4
	default:
Packit Service 672cf4
	  /* FIXME: Yeah, well.  */
Packit Service 672cf4
	  res = EINVAL;
Packit Service 672cf4
	  break;
Packit Service 672cf4
	}
Packit Service 672cf4
    }
Packit Service 6c01f9
  TRACE3 (DEBUG_DATA, "gpgme:gpgme_error_to_errno", 0,
Packit Service 672cf4
	  "mapping %s <%s> to: %s", gpgme_strerror (err),
Packit Service 672cf4
	  gpgme_strsource (err), strerror (res));
Packit Service 672cf4
  gpg_err_set_errno (res);
Packit Service 672cf4
  return res ? -1 : 0;
Packit Service 672cf4
}
Packit Service 672cf4
Packit Service 672cf4
Packit Service 672cf4
static gpgme_ssize_t
Packit Service 672cf4
old_user_read (gpgme_data_t dh, void *buffer, size_t size)
Packit Service 672cf4
{
Packit Service 672cf4
  gpgme_error_t err;
Packit Service 672cf4
  size_t amt;
Packit Service 6c01f9
  TRACE_BEG2 (DEBUG_DATA, "gpgme:old_user_read", dh,
Packit Service 6c01f9
	      "buffer=%p, size=%u", buffer, size);
Packit Service 672cf4
Packit Service 672cf4
  err = (*dh->data.old_user.cb) (dh->data.old_user.handle,
Packit Service 672cf4
				 buffer, size, &amt;;
Packit Service 672cf4
  if (err)
Packit Service 672cf4
    return TRACE_SYSRES (gpgme_error_to_errno (err));
Packit Service 6c01f9
  return TRACE_SYSRES ((gpgme_ssize_t)amt);
Packit Service 672cf4
}
Packit Service 672cf4
Packit Service 672cf4
Packit Service 672cf4
static gpgme_off_t
Packit Service 672cf4
old_user_seek (gpgme_data_t dh, gpgme_off_t offset, int whence)
Packit Service 672cf4
{
Packit Service 672cf4
  gpgme_error_t err;
Packit Service 6c01f9
  TRACE_BEG2 (DEBUG_DATA, "gpgme:old_user_seek", dh,
Packit Service 6c01f9
	      "offset=%llu, whence=%i", offset, whence);
Packit Service 672cf4
Packit Service 672cf4
  if (whence != SEEK_SET || offset)
Packit Service 672cf4
    {
Packit Service 672cf4
      gpg_err_set_errno (EINVAL);
Packit Service 672cf4
      return TRACE_SYSRES (-1);
Packit Service 672cf4
    }
Packit Service 672cf4
  err = (*dh->data.old_user.cb) (dh->data.old_user.handle, NULL, 0, NULL);
Packit Service 672cf4
  if (err)
Packit Service 672cf4
    return TRACE_SYSRES (gpgme_error_to_errno (err));
Packit Service 672cf4
  return TRACE_SYSRES (0);
Packit Service 672cf4
}
Packit Service 672cf4
Packit Service 672cf4
Packit Service 672cf4
static struct _gpgme_data_cbs old_user_cbs =
Packit Service 672cf4
  {
Packit Service 672cf4
    old_user_read,
Packit Service 672cf4
    NULL,
Packit Service 672cf4
    old_user_seek,
Packit Service 672cf4
    NULL
Packit Service 672cf4
  };
Packit Service 672cf4
Packit Service 672cf4
Packit Service 672cf4
/* Create a new data buffer which retrieves the data from the callback
Packit Service 672cf4
   function READ_CB.  */
Packit Service 672cf4
gpgme_error_t
Packit Service 672cf4
gpgme_data_new_with_read_cb (gpgme_data_t *r_dh,
Packit Service 672cf4
                             int (*read_cb) (void *, char *, size_t, size_t *),
Packit Service 672cf4
                             void *read_cb_value)
Packit Service 672cf4
{
Packit Service 672cf4
  gpgme_error_t err;
Packit Service 6c01f9
  TRACE_BEG2 (DEBUG_DATA, "gpgme_data_new_with_read_cb", r_dh,
Packit Service 672cf4
	      "read_cb=%p/%p", read_cb, read_cb_value);
Packit Service 672cf4
Packit Service 672cf4
  err = _gpgme_data_new (r_dh, &old_user_cbs);
Packit Service 672cf4
Packit Service 672cf4
  if (err)
Packit Service 672cf4
    return TRACE_ERR (err);
Packit Service 672cf4
Packit Service 672cf4
  (*r_dh)->data.old_user.cb = read_cb;
Packit Service 672cf4
  (*r_dh)->data.old_user.handle = read_cb_value;
Packit Service 672cf4
  return TRACE_ERR (0);
Packit Service 672cf4
}