LCOV - code coverage report
Current view: top level - src - data.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 104 149 69.8 %
Date: 2017-03-02 17:11:10 Functions: 14 16 87.5 %

          Line data    Source code
       1             : /* data.c - An abstraction for data objects.
       2             :    Copyright (C) 2002, 2003, 2004, 2005, 2007 g10 Code GmbH
       3             : 
       4             :    This file is part of GPGME.
       5             : 
       6             :    GPGME is free software; you can redistribute it and/or modify it
       7             :    under the terms of the GNU Lesser General Public License as
       8             :    published by the Free Software Foundation; either version 2.1 of
       9             :    the License, or (at your option) any later version.
      10             : 
      11             :    GPGME is distributed in the hope that it will be useful, but
      12             :    WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             :    Lesser General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU Lesser General Public
      17             :    License along with this program; if not, write to the Free Software
      18             :    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
      19             :    02111-1307, USA.  */
      20             : 
      21             : #if HAVE_CONFIG_H
      22             : #include <config.h>
      23             : #endif
      24             : 
      25             : #include <stdlib.h>
      26             : #ifdef HAVE_UNISTD_H
      27             : # include <unistd.h>
      28             : #endif
      29             : #include <errno.h>
      30             : #include <string.h>
      31             : 
      32             : #include "gpgme.h"
      33             : #include "data.h"
      34             : #include "util.h"
      35             : #include "ops.h"
      36             : #include "priv-io.h"
      37             : #include "debug.h"
      38             : 
      39             : 
      40             : gpgme_error_t
      41         684 : _gpgme_data_new (gpgme_data_t *r_dh, struct _gpgme_data_cbs *cbs)
      42             : {
      43             :   gpgme_data_t dh;
      44             : 
      45         684 :   if (!r_dh)
      46           1 :     return gpg_error (GPG_ERR_INV_VALUE);
      47             : 
      48         683 :   *r_dh = NULL;
      49         683 :   dh = calloc (1, sizeof (*dh));
      50         683 :   if (!dh)
      51           0 :     return gpg_error_from_syserror ();
      52             : 
      53         683 :   dh->cbs = cbs;
      54             : 
      55         683 :   *r_dh = dh;
      56         683 :   return 0;
      57             : }
      58             : 
      59             : 
      60             : void
      61         645 : _gpgme_data_release (gpgme_data_t dh)
      62             : {
      63         645 :   if (!dh)
      64           0 :     return;
      65             : 
      66         645 :   if (dh->file_name)
      67           5 :     free (dh->file_name);
      68         645 :   free (dh);
      69             : }
      70             : 
      71             : 
      72             : /* Read up to SIZE bytes into buffer BUFFER from the data object with
      73             :    the handle DH.  Return the number of characters read, 0 on EOF and
      74             :    -1 on error.  If an error occurs, errno is set.  */
      75             : gpgme_ssize_t
      76        1434 : gpgme_data_read (gpgme_data_t dh, void *buffer, size_t size)
      77             : {
      78             :   gpgme_ssize_t res;
      79        1434 :   TRACE_BEG2 (DEBUG_DATA, "gpgme_data_read", dh,
      80             :               "buffer=%p, size=%u", buffer, size);
      81             : 
      82        1434 :   if (!dh)
      83             :     {
      84           0 :       gpg_err_set_errno (EINVAL);
      85           0 :       return TRACE_SYSRES (-1);
      86             :     }
      87        1434 :   if (!dh->cbs->read)
      88             :     {
      89           0 :       gpg_err_set_errno (ENOSYS);
      90           0 :       return TRACE_SYSRES (-1);
      91             :     }
      92             :   do
      93        1434 :     res = (*dh->cbs->read) (dh, buffer, size);
      94        1434 :   while (res < 0 && errno == EINTR);
      95             : 
      96        1434 :   return TRACE_SYSRES (res);
      97             : }
      98             : 
      99             : 
     100             : /* Write up to SIZE bytes from buffer BUFFER to the data object with
     101             :    the handle DH.  Return the number of characters written, or -1 on
     102             :    error.  If an error occurs, errno is set.  */
     103             : gpgme_ssize_t
     104         885 : gpgme_data_write (gpgme_data_t dh, const void *buffer, size_t size)
     105             : {
     106             :   gpgme_ssize_t res;
     107         885 :   TRACE_BEG2 (DEBUG_DATA, "gpgme_data_write", dh,
     108             :               "buffer=%p, size=%u", buffer, size);
     109             : 
     110         885 :   if (!dh)
     111             :     {
     112           0 :       gpg_err_set_errno (EINVAL);
     113           0 :       return TRACE_SYSRES (-1);
     114             :     }
     115         885 :   if (!dh->cbs->write)
     116             :     {
     117           0 :       gpg_err_set_errno (ENOSYS);
     118           0 :       return TRACE_SYSRES (-1);
     119             :     }
     120             :   do
     121         885 :     res = (*dh->cbs->write) (dh, buffer, size);
     122         885 :   while (res < 0 && errno == EINTR);
     123             : 
     124         885 :   return TRACE_SYSRES (res);
     125             : }
     126             : 
     127             : 
     128             : /* Set the current position from where the next read or write starts
     129             :    in the data object with the handle DH to OFFSET, relativ to
     130             :    WHENCE.  */
     131             : gpgme_off_t
     132         318 : gpgme_data_seek (gpgme_data_t dh, gpgme_off_t offset, int whence)
     133             : {
     134         318 :   TRACE_BEG2 (DEBUG_DATA, "gpgme_data_seek", dh,
     135             :               "offset=%lli, whence=%i", offset, whence);
     136             : 
     137         318 :   if (!dh)
     138             :     {
     139           0 :       gpg_err_set_errno (EINVAL);
     140           0 :       return TRACE_SYSRES (-1);
     141             :     }
     142         318 :   if (!dh->cbs->seek)
     143             :     {
     144           0 :       gpg_err_set_errno (ENOSYS);
     145           0 :       return TRACE_SYSRES (-1);
     146             :     }
     147             : 
     148             :   /* For relative movement, we must take into account the actual
     149             :      position of the read counter.  */
     150         318 :   if (whence == SEEK_CUR)
     151           0 :     offset -= dh->pending_len;
     152             : 
     153         318 :   offset = (*dh->cbs->seek) (dh, offset, whence);
     154         318 :   if (offset >= 0)
     155         314 :     dh->pending_len = 0;
     156             : 
     157         318 :   return TRACE_SYSRES (offset);
     158             : }
     159             : 
     160             : 
     161             : /* Convenience function to do a gpgme_data_seek (dh, 0, SEEK_SET).  */
     162             : gpgme_error_t
     163           0 : gpgme_data_rewind (gpgme_data_t dh)
     164             : {
     165             :   gpgme_error_t err;
     166           0 :   TRACE_BEG (DEBUG_DATA, "gpgme_data_rewind", dh);
     167             : 
     168           0 :   err = ((gpgme_data_seek (dh, 0, SEEK_SET) == -1)
     169           0 :          ? gpg_error_from_syserror () : 0);
     170             : 
     171           0 :   return TRACE_ERR (err);
     172             : }
     173             : 
     174             : 
     175             : /* Release the data object with the handle DH.  */
     176             : void
     177        1289 : gpgme_data_release (gpgme_data_t dh)
     178             : {
     179        1289 :   TRACE (DEBUG_DATA, "gpgme_data_release", dh);
     180             : 
     181        1289 :   if (!dh)
     182         644 :     return;
     183             : 
     184         645 :   if (dh->cbs->release)
     185         625 :     (*dh->cbs->release) (dh);
     186         645 :   _gpgme_data_release (dh);
     187             : }
     188             : 
     189             : 
     190             : /* Get the current encoding meta information for the data object with
     191             :    handle DH.  */
     192             : gpgme_data_encoding_t
     193         135 : gpgme_data_get_encoding (gpgme_data_t dh)
     194             : {
     195         135 :   TRACE1 (DEBUG_DATA, "gpgme_data_get_encoding", dh,
     196             :           "dh->encoding=%i", dh ? dh->encoding : GPGME_DATA_ENCODING_NONE);
     197         135 :   return dh ? dh->encoding : GPGME_DATA_ENCODING_NONE;
     198             : }
     199             : 
     200             : 
     201             : /* Set the encoding meta information for the data object with handle
     202             :    DH to ENC.  */
     203             : gpgme_error_t
     204           0 : gpgme_data_set_encoding (gpgme_data_t dh, gpgme_data_encoding_t enc)
     205             : {
     206           0 :   TRACE_BEG1 (DEBUG_DATA, "gpgme_data_set_encoding", dh,
     207             :               "encoding=%i", enc);
     208           0 :   if (!dh)
     209           0 :     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
     210           0 :   if (enc < 0 || enc > GPGME_DATA_ENCODING_MIME)
     211           0 :     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
     212           0 :   dh->encoding = enc;
     213           0 :   return TRACE_ERR (0);
     214             : }
     215             : 
     216             : 
     217             : /* Set the file name associated with the data object with handle DH to
     218             :    FILE_NAME.  */
     219             : gpgme_error_t
     220           5 : gpgme_data_set_file_name (gpgme_data_t dh, const char *file_name)
     221             : {
     222           5 :   TRACE_BEG1 (DEBUG_DATA, "gpgme_data_set_file_name", dh,
     223             :               "file_name=%s", file_name);
     224             : 
     225           5 :   if (!dh)
     226           0 :     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
     227             : 
     228           5 :   if (dh->file_name)
     229           0 :     free (dh->file_name);
     230             : 
     231           5 :   if (file_name)
     232             :     {
     233           5 :       dh->file_name = strdup (file_name);
     234           5 :       if (!dh->file_name)
     235           0 :         return TRACE_ERR (gpg_error_from_syserror ());
     236             :     }
     237             :   else
     238           0 :     dh->file_name = 0;
     239             : 
     240           5 :   return TRACE_ERR (0);
     241             : }
     242             : 
     243             : 
     244             : /* Get the file name associated with the data object with handle DH,
     245             :    or NULL if there is none.  */
     246             : char *
     247         130 : gpgme_data_get_file_name (gpgme_data_t dh)
     248             : {
     249         130 :   if (!dh)
     250             :     {
     251           0 :       TRACE (DEBUG_DATA, "gpgme_data_get_file_name", dh);
     252           0 :       return NULL;
     253             :     }
     254             : 
     255         130 :   TRACE1 (DEBUG_DATA, "gpgme_data_get_file_name", dh,
     256             :           "dh->file_name=%s", dh->file_name);
     257         130 :   return dh->file_name;
     258             : }
     259             : 
     260             : 
     261             : /* Set a flag for the data object DH.  See the manual for details.  */
     262             : gpg_error_t
     263          67 : gpgme_data_set_flag (gpgme_data_t dh, const char *name, const char *value)
     264             : {
     265          67 :   TRACE_BEG2 (DEBUG_DATA, "gpgme_data_set_flag", dh,
     266             :               "%s=%s", name, value);
     267             : 
     268          67 :   if (!dh)
     269           0 :     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
     270             : 
     271          67 :   if (!strcmp (name, "size-hint"))
     272             :     {
     273          67 :       dh->size_hint= value? _gpgme_string_to_off (value) : 0;
     274             :     }
     275             :   else
     276           0 :     return gpg_error (GPG_ERR_UNKNOWN_NAME);
     277             : 
     278          67 :   return 0;
     279             : }
     280             : 
     281             : 
     282             : 
     283             : /* Functions to support the wait interface.  */
     284             : 
     285             : gpgme_error_t
     286         537 : _gpgme_data_inbound_handler (void *opaque, int fd)
     287             : {
     288         537 :   struct io_cb_data *data = (struct io_cb_data *) opaque;
     289         537 :   gpgme_data_t dh = (gpgme_data_t) data->handler_value;
     290             :   char buffer[BUFFER_SIZE];
     291         537 :   char *bufp = buffer;
     292             :   gpgme_ssize_t buflen;
     293         537 :   TRACE_BEG1 (DEBUG_CTX, "_gpgme_data_inbound_handler", dh,
     294             :               "fd=0x%x", fd);
     295             : 
     296         537 :   buflen = _gpgme_io_read (fd, buffer, BUFFER_SIZE);
     297         537 :   if (buflen < 0)
     298           0 :     return gpg_error_from_syserror ();
     299         537 :   if (buflen == 0)
     300             :     {
     301         209 :       _gpgme_io_close (fd);
     302         209 :       return TRACE_ERR (0);
     303             :     }
     304             : 
     305             :   do
     306             :     {
     307         328 :       gpgme_ssize_t amt = gpgme_data_write (dh, bufp, buflen);
     308         328 :       if (amt == 0 || (amt < 0 && errno != EINTR))
     309           0 :         return TRACE_ERR (gpg_error_from_syserror ());
     310         328 :       bufp += amt;
     311         328 :       buflen -= amt;
     312             :     }
     313         328 :   while (buflen > 0);
     314         328 :   return TRACE_ERR (0);
     315             : }
     316             : 
     317             : 
     318             : gpgme_error_t
     319         873 : _gpgme_data_outbound_handler (void *opaque, int fd)
     320             : {
     321         873 :   struct io_cb_data *data = (struct io_cb_data *) opaque;
     322         873 :   gpgme_data_t dh = (gpgme_data_t) data->handler_value;
     323             :   gpgme_ssize_t nwritten;
     324         873 :   TRACE_BEG1 (DEBUG_CTX, "_gpgme_data_outbound_handler", dh,
     325             :               "fd=0x%x", fd);
     326             : 
     327         873 :   if (!dh->pending_len)
     328             :     {
     329         873 :       gpgme_ssize_t amt = gpgme_data_read (dh, dh->pending, BUFFER_SIZE);
     330         873 :       if (amt < 0)
     331           0 :         return TRACE_ERR (gpg_error_from_syserror ());
     332         873 :       if (amt == 0)
     333             :         {
     334         277 :           _gpgme_io_close (fd);
     335         277 :           return TRACE_ERR (0);
     336             :         }
     337         596 :       dh->pending_len = amt;
     338             :     }
     339             : 
     340         596 :   nwritten = _gpgme_io_write (fd, dh->pending, dh->pending_len);
     341         596 :   if (nwritten == -1 && errno == EAGAIN)
     342           0 :     return TRACE_ERR (0);
     343             : 
     344         596 :   if (nwritten == -1 && errno == EPIPE)
     345             :     {
     346             :       /* Not much we can do.  The other end closed the pipe, but we
     347             :          still have data.  This should only ever happen if the other
     348             :          end is going to tell us what happened on some other channel.
     349             :          Silently close our end.  */
     350           0 :       _gpgme_io_close (fd);
     351           0 :       return TRACE_ERR (0);
     352             :     }
     353             : 
     354         596 :   if (nwritten <= 0)
     355           0 :     return TRACE_ERR (gpg_error_from_syserror ());
     356             : 
     357         596 :   if (nwritten < dh->pending_len)
     358           0 :     memmove (dh->pending, dh->pending + nwritten, dh->pending_len - nwritten);
     359         596 :   dh->pending_len -= nwritten;
     360         596 :   return TRACE_ERR (0);
     361             : }
     362             : 
     363             : 
     364             : /* Get the file descriptor associated with DH, if possible.  Otherwise
     365             :    return -1.  */
     366             : int
     367          18 : _gpgme_data_get_fd (gpgme_data_t dh)
     368             : {
     369          18 :   if (!dh || !dh->cbs->get_fd)
     370          18 :     return -1;
     371           0 :   return (*dh->cbs->get_fd) (dh);
     372             : }
     373             : 
     374             : 
     375             : /* Get the size-hint value for DH or 0 if not available.  */
     376             : gpgme_off_t
     377         229 : _gpgme_data_get_size_hint (gpgme_data_t dh)
     378             : {
     379         229 :   return dh ? dh->size_hint : 0;
     380             : }

Generated by: LCOV version 1.13