LCOV - code coverage report
Current view: top level - src - data.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 97 134 72.4 %
Date: 2015-11-05 17:14:26 Functions: 12 13 92.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         148 : _gpgme_data_new (gpgme_data_t *r_dh, struct _gpgme_data_cbs *cbs)
      42             : {
      43             :   gpgme_data_t dh;
      44             : 
      45         148 :   if (!r_dh)
      46           1 :     return gpg_error (GPG_ERR_INV_VALUE);
      47             : 
      48         147 :   *r_dh = NULL;
      49         147 :   dh = calloc (1, sizeof (*dh));
      50         147 :   if (!dh)
      51           0 :     return gpg_error_from_syserror ();
      52             : 
      53         147 :   dh->cbs = cbs;
      54             : 
      55         147 :   *r_dh = dh;
      56         147 :   return 0;
      57             : }
      58             : 
      59             : 
      60             : void
      61         147 : _gpgme_data_release (gpgme_data_t dh)
      62             : {
      63         147 :   if (!dh)
      64         147 :     return;
      65             : 
      66         147 :   if (dh->file_name)
      67           1 :     free (dh->file_name);
      68         147 :   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         499 : gpgme_data_read (gpgme_data_t dh, void *buffer, size_t size)
      77             : {
      78             :   gpgme_ssize_t res;
      79         499 :   TRACE_BEG2 (DEBUG_DATA, "gpgme_data_read", dh,
      80             :               "buffer=%p, size=%u", buffer, size);
      81             : 
      82         499 :   if (!dh)
      83             :     {
      84           0 :       gpg_err_set_errno (EINVAL);
      85           0 :       return TRACE_SYSRES (-1);
      86             :     }
      87         499 :   if (!dh->cbs->read)
      88             :     {
      89           0 :       gpg_err_set_errno (ENOSYS);
      90           0 :       return TRACE_SYSRES (-1);
      91             :     }
      92             :   do
      93         499 :     res = (*dh->cbs->read) (dh, buffer, size);
      94         499 :   while (res < 0 && errno == EINTR);
      95             : 
      96         499 :   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         108 : gpgme_data_write (gpgme_data_t dh, const void *buffer, size_t size)
     105             : {
     106             :   gpgme_ssize_t res;
     107         108 :   TRACE_BEG2 (DEBUG_DATA, "gpgme_data_write", dh,
     108             :               "buffer=%p, size=%u", buffer, size);
     109             : 
     110         108 :   if (!dh)
     111             :     {
     112           0 :       gpg_err_set_errno (EINVAL);
     113           0 :       return TRACE_SYSRES (-1);
     114             :     }
     115         108 :   if (!dh->cbs->write)
     116             :     {
     117           0 :       gpg_err_set_errno (ENOSYS);
     118           0 :       return TRACE_SYSRES (-1);
     119             :     }
     120             :   do
     121         108 :     res = (*dh->cbs->write) (dh, buffer, size);
     122         108 :   while (res < 0 && errno == EINTR);
     123             : 
     124         108 :   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          62 : gpgme_data_seek (gpgme_data_t dh, gpgme_off_t offset, int whence)
     133             : {
     134          62 :   TRACE_BEG2 (DEBUG_DATA, "gpgme_data_seek", dh,
     135             :               "offset=%lli, whence=%i", offset, whence);
     136             : 
     137          62 :   if (!dh)
     138             :     {
     139           0 :       gpg_err_set_errno (EINVAL);
     140           0 :       return TRACE_SYSRES (-1);
     141             :     }
     142          62 :   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          62 :   if (whence == SEEK_CUR)
     151           0 :     offset -= dh->pending_len;
     152             : 
     153          62 :   offset = (*dh->cbs->seek) (dh, offset, whence);
     154          62 :   if (offset >= 0)
     155          62 :     dh->pending_len = 0;
     156             : 
     157          62 :   return TRACE_SYSRES (offset);
     158             : }
     159             : 
     160             : 
     161             : /* Release the data object with the handle DH.  */
     162             : void
     163         147 : gpgme_data_release (gpgme_data_t dh)
     164             : {
     165         147 :   TRACE (DEBUG_DATA, "gpgme_data_release", dh);
     166             : 
     167         147 :   if (!dh)
     168         147 :     return;
     169             : 
     170         147 :   if (dh->cbs->release)
     171         147 :     (*dh->cbs->release) (dh);
     172         147 :   _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          12 : gpgme_data_get_encoding (gpgme_data_t dh)
     180             : {
     181          12 :   TRACE1 (DEBUG_DATA, "gpgme_data_get_encoding", dh,
     182             :           "dh->encoding=%i", dh ? dh->encoding : GPGME_DATA_ENCODING_NONE);
     183          12 :   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_URL0)
     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           1 : gpgme_data_set_file_name (gpgme_data_t dh, const char *file_name)
     207             : {
     208           1 :   TRACE_BEG1 (DEBUG_DATA, "gpgme_data_set_file_name", dh,
     209             :               "file_name=%s", file_name);
     210             : 
     211           1 :   if (!dh)
     212           0 :     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
     213             : 
     214           1 :   if (dh->file_name)
     215           0 :     free (dh->file_name);
     216             : 
     217           1 :   if (file_name)
     218             :     {
     219           1 :       dh->file_name = strdup (file_name);
     220           1 :       if (!dh->file_name)
     221           0 :         return TRACE_ERR (gpg_error_from_syserror ());
     222             :     }
     223             :   else
     224           0 :     dh->file_name = 0;
     225             : 
     226           1 :   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          35 : gpgme_data_get_file_name (gpgme_data_t dh)
     234             : {
     235          35 :   if (!dh)
     236             :     {
     237           0 :       TRACE (DEBUG_DATA, "gpgme_data_get_file_name", dh);
     238           0 :       return NULL;
     239             :     }
     240             : 
     241          35 :   TRACE1 (DEBUG_DATA, "gpgme_data_get_file_name", dh,
     242             :           "dh->file_name=%s", dh->file_name);
     243          35 :   return dh->file_name;
     244             : }
     245             : 
     246             : 
     247             : /* Functions to support the wait interface.  */
     248             : 
     249             : gpgme_error_t
     250         173 : _gpgme_data_inbound_handler (void *opaque, int fd)
     251             : {
     252         173 :   struct io_cb_data *data = (struct io_cb_data *) opaque;
     253         173 :   gpgme_data_t dh = (gpgme_data_t) data->handler_value;
     254             :   char buffer[BUFFER_SIZE];
     255         173 :   char *bufp = buffer;
     256             :   gpgme_ssize_t buflen;
     257         173 :   TRACE_BEG1 (DEBUG_CTX, "_gpgme_data_inbound_handler", dh,
     258             :               "fd=0x%x", fd);
     259             : 
     260         173 :   buflen = _gpgme_io_read (fd, buffer, BUFFER_SIZE);
     261         173 :   if (buflen < 0)
     262           0 :     return gpg_error_from_syserror ();
     263         173 :   if (buflen == 0)
     264             :     {
     265          71 :       _gpgme_io_close (fd);
     266          71 :       return TRACE_ERR (0);
     267             :     }
     268             : 
     269             :   do
     270             :     {
     271         102 :       gpgme_ssize_t amt = gpgme_data_write (dh, bufp, buflen);
     272         102 :       if (amt == 0 || (amt < 0 && errno != EINTR))
     273           0 :         return TRACE_ERR (gpg_error_from_syserror ());
     274         102 :       bufp += amt;
     275         102 :       buflen -= amt;
     276             :     }
     277         102 :   while (buflen > 0);
     278         102 :   return TRACE_ERR (0);
     279             : }
     280             : 
     281             : 
     282             : gpgme_error_t
     283         180 : _gpgme_data_outbound_handler (void *opaque, int fd)
     284             : {
     285         180 :   struct io_cb_data *data = (struct io_cb_data *) opaque;
     286         180 :   gpgme_data_t dh = (gpgme_data_t) data->handler_value;
     287             :   gpgme_ssize_t nwritten;
     288         180 :   TRACE_BEG1 (DEBUG_CTX, "_gpgme_data_outbound_handler", dh,
     289             :               "fd=0x%x", fd);
     290             : 
     291         180 :   if (!dh->pending_len)
     292             :     {
     293         180 :       gpgme_ssize_t amt = gpgme_data_read (dh, dh->pending, BUFFER_SIZE);
     294         180 :       if (amt < 0)
     295           0 :         return TRACE_ERR (gpg_error_from_syserror ());
     296         180 :       if (amt == 0)
     297             :         {
     298          78 :           _gpgme_io_close (fd);
     299          78 :           return TRACE_ERR (0);
     300             :         }
     301         102 :       dh->pending_len = amt;
     302             :     }
     303             : 
     304         102 :   nwritten = _gpgme_io_write (fd, dh->pending, dh->pending_len);
     305         102 :   if (nwritten == -1 && errno == EAGAIN)
     306           0 :     return TRACE_ERR (0);
     307             : 
     308         102 :   if (nwritten == -1 && errno == EPIPE)
     309             :     {
     310             :       /* Not much we can do.  The other end closed the pipe, but we
     311             :          still have data.  This should only ever happen if the other
     312             :          end is going to tell us what happened on some other channel.
     313             :          Silently close our end.  */
     314           0 :       _gpgme_io_close (fd);
     315           0 :       return TRACE_ERR (0);
     316             :     }
     317             : 
     318         102 :   if (nwritten <= 0)
     319           0 :     return TRACE_ERR (gpg_error_from_syserror ());
     320             : 
     321         102 :   if (nwritten < dh->pending_len)
     322           0 :     memmove (dh->pending, dh->pending + nwritten, dh->pending_len - nwritten);
     323         102 :   dh->pending_len -= nwritten;
     324         102 :   return TRACE_ERR (0);
     325             : }
     326             : 
     327             : 
     328             : /* Get the file descriptor associated with DH, if possible.  Otherwise
     329             :    return -1.  */
     330             : int
     331          18 : _gpgme_data_get_fd (gpgme_data_t dh)
     332             : {
     333          18 :   if (!dh || !dh->cbs->get_fd)
     334          18 :     return -1;
     335           0 :   return (*dh->cbs->get_fd) (dh);
     336             : }

Generated by: LCOV version 1.11