LCOV - code coverage report
Current view: top level - src - data.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 105 144 72.9 %
Date: 2016-09-12 13:07:23 Functions: 14 15 93.3 %

          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         358 : _gpgme_data_new (gpgme_data_t *r_dh, struct _gpgme_data_cbs *cbs)
      42             : {
      43             :   gpgme_data_t dh;
      44             : 
      45         358 :   if (!r_dh)
      46           1 :     return gpg_error (GPG_ERR_INV_VALUE);
      47             : 
      48         357 :   *r_dh = NULL;
      49         357 :   dh = calloc (1, sizeof (*dh));
      50         357 :   if (!dh)
      51           0 :     return gpg_error_from_syserror ();
      52             : 
      53         357 :   dh->cbs = cbs;
      54             : 
      55         357 :   *r_dh = dh;
      56         357 :   return 0;
      57             : }
      58             : 
      59             : 
      60             : void
      61         346 : _gpgme_data_release (gpgme_data_t dh)
      62             : {
      63         346 :   if (!dh)
      64         346 :     return;
      65             : 
      66         346 :   if (dh->file_name)
      67           3 :     free (dh->file_name);
      68         346 :   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        1046 : gpgme_data_read (gpgme_data_t dh, void *buffer, size_t size)
      77             : {
      78             :   gpgme_ssize_t res;
      79        1046 :   TRACE_BEG2 (DEBUG_DATA, "gpgme_data_read", dh,
      80             :               "buffer=%p, size=%u", buffer, size);
      81             : 
      82        1046 :   if (!dh)
      83             :     {
      84           0 :       gpg_err_set_errno (EINVAL);
      85           0 :       return TRACE_SYSRES (-1);
      86             :     }
      87        1046 :   if (!dh->cbs->read)
      88             :     {
      89           0 :       gpg_err_set_errno (ENOSYS);
      90           0 :       return TRACE_SYSRES (-1);
      91             :     }
      92             :   do
      93        1046 :     res = (*dh->cbs->read) (dh, buffer, size);
      94        1046 :   while (res < 0 && errno == EINTR);
      95             : 
      96        1046 :   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         238 : gpgme_data_write (gpgme_data_t dh, const void *buffer, size_t size)
     105             : {
     106             :   gpgme_ssize_t res;
     107         238 :   TRACE_BEG2 (DEBUG_DATA, "gpgme_data_write", dh,
     108             :               "buffer=%p, size=%u", buffer, size);
     109             : 
     110         238 :   if (!dh)
     111             :     {
     112           0 :       gpg_err_set_errno (EINVAL);
     113           0 :       return TRACE_SYSRES (-1);
     114             :     }
     115         238 :   if (!dh->cbs->write)
     116             :     {
     117           0 :       gpg_err_set_errno (ENOSYS);
     118           0 :       return TRACE_SYSRES (-1);
     119             :     }
     120             :   do
     121         238 :     res = (*dh->cbs->write) (dh, buffer, size);
     122         238 :   while (res < 0 && errno == EINTR);
     123             : 
     124         238 :   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         231 : gpgme_data_seek (gpgme_data_t dh, gpgme_off_t offset, int whence)
     133             : {
     134         231 :   TRACE_BEG2 (DEBUG_DATA, "gpgme_data_seek", dh,
     135             :               "offset=%lli, whence=%i", offset, whence);
     136             : 
     137         231 :   if (!dh)
     138             :     {
     139           0 :       gpg_err_set_errno (EINVAL);
     140           0 :       return TRACE_SYSRES (-1);
     141             :     }
     142         231 :   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         231 :   if (whence == SEEK_CUR)
     151           0 :     offset -= dh->pending_len;
     152             : 
     153         231 :   offset = (*dh->cbs->seek) (dh, offset, whence);
     154         231 :   if (offset >= 0)
     155         229 :     dh->pending_len = 0;
     156             : 
     157         231 :   return TRACE_SYSRES (offset);
     158             : }
     159             : 
     160             : 
     161             : /* Release the data object with the handle DH.  */
     162             : void
     163         346 : gpgme_data_release (gpgme_data_t dh)
     164             : {
     165         346 :   TRACE (DEBUG_DATA, "gpgme_data_release", dh);
     166             : 
     167         346 :   if (!dh)
     168         346 :     return;
     169             : 
     170         346 :   if (dh->cbs->release)
     171         336 :     (*dh->cbs->release) (dh);
     172         346 :   _gpgme_data_release (dh);
     173             : }
     174             : 
     175             : 
     176             : /* Get the current encoding meta information for the data object with
     177             :    handle DH.  */
     178             : gpgme_data_encoding_t
     179          93 : gpgme_data_get_encoding (gpgme_data_t dh)
     180             : {
     181          93 :   TRACE1 (DEBUG_DATA, "gpgme_data_get_encoding", dh,
     182             :           "dh->encoding=%i", dh ? dh->encoding : GPGME_DATA_ENCODING_NONE);
     183          93 :   return dh ? dh->encoding : GPGME_DATA_ENCODING_NONE;
     184             : }
     185             : 
     186             : 
     187             : /* Set the encoding meta information for the data object with handle
     188             :    DH to ENC.  */
     189             : gpgme_error_t
     190           0 : gpgme_data_set_encoding (gpgme_data_t dh, gpgme_data_encoding_t enc)
     191             : {
     192           0 :   TRACE_BEG1 (DEBUG_DATA, "gpgme_data_set_encoding", dh,
     193             :               "encoding=%i", enc);
     194           0 :   if (!dh)
     195           0 :     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
     196           0 :   if (enc < 0 || enc > GPGME_DATA_ENCODING_MIME)
     197           0 :     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
     198           0 :   dh->encoding = enc;
     199           0 :   return TRACE_ERR (0);
     200             : }
     201             : 
     202             : 
     203             : /* Set the file name associated with the data object with handle DH to
     204             :    FILE_NAME.  */
     205             : gpgme_error_t
     206           3 : gpgme_data_set_file_name (gpgme_data_t dh, const char *file_name)
     207             : {
     208           3 :   TRACE_BEG1 (DEBUG_DATA, "gpgme_data_set_file_name", dh,
     209             :               "file_name=%s", file_name);
     210             : 
     211           3 :   if (!dh)
     212           0 :     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
     213             : 
     214           3 :   if (dh->file_name)
     215           0 :     free (dh->file_name);
     216             : 
     217           3 :   if (file_name)
     218             :     {
     219           3 :       dh->file_name = strdup (file_name);
     220           3 :       if (!dh->file_name)
     221           0 :         return TRACE_ERR (gpg_error_from_syserror ());
     222             :     }
     223             :   else
     224           0 :     dh->file_name = 0;
     225             : 
     226           3 :   return TRACE_ERR (0);
     227             : }
     228             : 
     229             : 
     230             : /* Get the file name associated with the data object with handle DH,
     231             :    or NULL if there is none.  */
     232             : char *
     233          86 : gpgme_data_get_file_name (gpgme_data_t dh)
     234             : {
     235          86 :   if (!dh)
     236             :     {
     237           0 :       TRACE (DEBUG_DATA, "gpgme_data_get_file_name", dh);
     238           0 :       return NULL;
     239             :     }
     240             : 
     241          86 :   TRACE1 (DEBUG_DATA, "gpgme_data_get_file_name", dh,
     242             :           "dh->file_name=%s", dh->file_name);
     243          86 :   return dh->file_name;
     244             : }
     245             : 
     246             : 
     247             : /* Set a flag for the data object DH.  See the manual for details.  */
     248             : gpg_error_t
     249          64 : gpgme_data_set_flag (gpgme_data_t dh, const char *name, const char *value)
     250             : {
     251          64 :   TRACE_BEG2 (DEBUG_DATA, "gpgme_data_set_flag", dh,
     252             :               "%s=%s", name, value);
     253             : 
     254          64 :   if (!dh)
     255           0 :     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
     256             : 
     257          64 :   if (!strcmp (name, "size-hint"))
     258             :     {
     259          64 :       dh->size_hint= value? _gpgme_string_to_off (value) : 0;
     260             :     }
     261             :   else
     262           0 :     return gpg_error (GPG_ERR_UNKNOWN_NAME);
     263             : 
     264          64 :   return 0;
     265             : }
     266             : 
     267             : 
     268             : 
     269             : /* Functions to support the wait interface.  */
     270             : 
     271             : gpgme_error_t
     272         369 : _gpgme_data_inbound_handler (void *opaque, int fd)
     273             : {
     274         369 :   struct io_cb_data *data = (struct io_cb_data *) opaque;
     275         369 :   gpgme_data_t dh = (gpgme_data_t) data->handler_value;
     276             :   char buffer[BUFFER_SIZE];
     277         369 :   char *bufp = buffer;
     278             :   gpgme_ssize_t buflen;
     279         369 :   TRACE_BEG1 (DEBUG_CTX, "_gpgme_data_inbound_handler", dh,
     280             :               "fd=0x%x", fd);
     281             : 
     282         369 :   buflen = _gpgme_io_read (fd, buffer, BUFFER_SIZE);
     283         369 :   if (buflen < 0)
     284           0 :     return gpg_error_from_syserror ();
     285         369 :   if (buflen == 0)
     286             :     {
     287         145 :       _gpgme_io_close (fd);
     288         145 :       return TRACE_ERR (0);
     289             :     }
     290             : 
     291             :   do
     292             :     {
     293         224 :       gpgme_ssize_t amt = gpgme_data_write (dh, bufp, buflen);
     294         224 :       if (amt == 0 || (amt < 0 && errno != EINTR))
     295           0 :         return TRACE_ERR (gpg_error_from_syserror ());
     296         224 :       bufp += amt;
     297         224 :       buflen -= amt;
     298             :     }
     299         224 :   while (buflen > 0);
     300         224 :   return TRACE_ERR (0);
     301             : }
     302             : 
     303             : 
     304             : gpgme_error_t
     305         649 : _gpgme_data_outbound_handler (void *opaque, int fd)
     306             : {
     307         649 :   struct io_cb_data *data = (struct io_cb_data *) opaque;
     308         649 :   gpgme_data_t dh = (gpgme_data_t) data->handler_value;
     309             :   gpgme_ssize_t nwritten;
     310         649 :   TRACE_BEG1 (DEBUG_CTX, "_gpgme_data_outbound_handler", dh,
     311             :               "fd=0x%x", fd);
     312             : 
     313         649 :   if (!dh->pending_len)
     314             :     {
     315         649 :       gpgme_ssize_t amt = gpgme_data_read (dh, dh->pending, BUFFER_SIZE);
     316         649 :       if (amt < 0)
     317           0 :         return TRACE_ERR (gpg_error_from_syserror ());
     318         649 :       if (amt == 0)
     319             :         {
     320         175 :           _gpgme_io_close (fd);
     321         175 :           return TRACE_ERR (0);
     322             :         }
     323         474 :       dh->pending_len = amt;
     324             :     }
     325             : 
     326         474 :   nwritten = _gpgme_io_write (fd, dh->pending, dh->pending_len);
     327         474 :   if (nwritten == -1 && errno == EAGAIN)
     328           0 :     return TRACE_ERR (0);
     329             : 
     330         474 :   if (nwritten == -1 && errno == EPIPE)
     331             :     {
     332             :       /* Not much we can do.  The other end closed the pipe, but we
     333             :          still have data.  This should only ever happen if the other
     334             :          end is going to tell us what happened on some other channel.
     335             :          Silently close our end.  */
     336           0 :       _gpgme_io_close (fd);
     337           0 :       return TRACE_ERR (0);
     338             :     }
     339             : 
     340         474 :   if (nwritten <= 0)
     341           0 :     return TRACE_ERR (gpg_error_from_syserror ());
     342             : 
     343         474 :   if (nwritten < dh->pending_len)
     344           0 :     memmove (dh->pending, dh->pending + nwritten, dh->pending_len - nwritten);
     345         474 :   dh->pending_len -= nwritten;
     346         474 :   return TRACE_ERR (0);
     347             : }
     348             : 
     349             : 
     350             : /* Get the file descriptor associated with DH, if possible.  Otherwise
     351             :    return -1.  */
     352             : int
     353          18 : _gpgme_data_get_fd (gpgme_data_t dh)
     354             : {
     355          18 :   if (!dh || !dh->cbs->get_fd)
     356          18 :     return -1;
     357           0 :   return (*dh->cbs->get_fd) (dh);
     358             : }
     359             : 
     360             : 
     361             : /* Get the size-hint value for DH or 0 if not available.  */
     362             : gpgme_off_t
     363         148 : _gpgme_data_get_size_hint (gpgme_data_t dh)
     364             : {
     365         148 :   return dh ? dh->size_hint : 0;
     366             : }

Generated by: LCOV version 1.11