LCOV - code coverage report
Current view: top level - src - wait.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 79 88 89.8 %
Date: 2016-12-01 18:45:36 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /* wait.c
       2             :    Copyright (C) 2000 Werner Koch (dd9jn)
       3             :    Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007 g10 Code GmbH
       4             : 
       5             :    This file is part of GPGME.
       6             : 
       7             :    GPGME is free software; you can redistribute it and/or modify it
       8             :    under the terms of the GNU Lesser General Public License as
       9             :    published by the Free Software Foundation; either version 2.1 of
      10             :    the License, or (at your option) any later version.
      11             : 
      12             :    GPGME is distributed in the hope that it will be useful, but
      13             :    WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :    Lesser General Public License for more details.
      16             : 
      17             :    You should have received a copy of the GNU Lesser General Public
      18             :    License along with this program; if not, write to the Free Software
      19             :    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
      20             :    02111-1307, USA.  */
      21             : 
      22             : #if HAVE_CONFIG_H
      23             : #include <config.h>
      24             : #endif
      25             : #include <stdlib.h>
      26             : #include <string.h>
      27             : #include <assert.h>
      28             : #include <errno.h>
      29             : #ifdef HAVE_SYS_TYPES_H
      30             : # include <sys/types.h>
      31             : #endif
      32             : 
      33             : #include "util.h"
      34             : #include "context.h"
      35             : #include "ops.h"
      36             : #include "wait.h"
      37             : #include "sema.h"
      38             : #include "priv-io.h"
      39             : #include "engine.h"
      40             : #include "debug.h"
      41             : 
      42             : 
      43             : void
      44         581 : _gpgme_fd_table_init (fd_table_t fdt)
      45             : {
      46         581 :   fdt->fds = NULL;
      47         581 :   fdt->size = 0;
      48         581 : }
      49             : 
      50             : void
      51         570 : _gpgme_fd_table_deinit (fd_table_t fdt)
      52             : {
      53         570 :   if (fdt->fds)
      54         558 :     free (fdt->fds);
      55         570 : }
      56             : 
      57             : 
      58             : /* XXX We should keep a marker and roll over for speed.  */
      59             : static gpgme_error_t
      60        1767 : fd_table_put (fd_table_t fdt, int fd, int dir, void *opaque, int *idx)
      61             : {
      62             :   unsigned int i, j;
      63             :   struct io_select_fd_s *new_fds;
      64             : 
      65        3211 :   for (i = 0; i < fdt->size; i++)
      66             :     {
      67        2628 :       if (fdt->fds[i].fd == -1)
      68        1184 :         break;
      69             :     }
      70        1767 :   if (i == fdt->size)
      71             :     {
      72             : #define FDT_ALLOCSIZE 10
      73         583 :       new_fds = realloc (fdt->fds, (fdt->size + FDT_ALLOCSIZE)
      74             :                          * sizeof (*new_fds));
      75         583 :       if (!new_fds)
      76           0 :         return gpg_error_from_syserror ();
      77             : 
      78         583 :       fdt->fds = new_fds;
      79         583 :       fdt->size += FDT_ALLOCSIZE;
      80        6413 :       for (j = 0; j < FDT_ALLOCSIZE; j++)
      81        5830 :         fdt->fds[i + j].fd = -1;
      82             :     }
      83             : 
      84        1767 :   fdt->fds[i].fd = fd;
      85        1767 :   fdt->fds[i].for_read = (dir == 1);
      86        1767 :   fdt->fds[i].for_write = (dir == 0);
      87        1767 :   fdt->fds[i].signaled = 0;
      88        1767 :   fdt->fds[i].opaque = opaque;
      89        1767 :   *idx = i;
      90        1767 :   return 0;
      91             : }
      92             : 
      93             : 
      94             : /* Register the file descriptor FD with the handler FNC (which gets
      95             :    FNC_DATA as its first argument) for the direction DIR.  DATA should
      96             :    be the context for which the fd is added.  R_TAG will hold the tag
      97             :    that can be used to remove the fd.  */
      98             : gpgme_error_t
      99        1766 : _gpgme_add_io_cb (void *data, int fd, int dir, gpgme_io_cb_t fnc,
     100             :                   void *fnc_data, void **r_tag)
     101             : {
     102             :   gpgme_error_t err;
     103        1766 :   gpgme_ctx_t ctx = (gpgme_ctx_t) data;
     104             :   fd_table_t fdt;
     105             :   struct wait_item_s *item;
     106             :   struct tag *tag;
     107             : 
     108        1766 :   assert (fnc);
     109        1766 :   assert (ctx);
     110             : 
     111        1766 :   fdt = &ctx->fdt;
     112        1766 :   assert (fdt);
     113             : 
     114        1766 :   tag = malloc (sizeof *tag);
     115        1766 :   if (!tag)
     116           0 :     return gpg_error_from_syserror ();
     117        1766 :   tag->ctx = ctx;
     118             : 
     119             :   /* Allocate a structure to hold information about the handler.  */
     120        1766 :   item = calloc (1, sizeof *item);
     121        1766 :   if (!item)
     122             :     {
     123           0 :       free (tag);
     124           0 :       return gpg_error_from_syserror ();
     125             :     }
     126        1766 :   item->ctx = ctx;
     127        1766 :   item->dir = dir;
     128        1766 :   item->handler = fnc;
     129        1766 :   item->handler_value = fnc_data;
     130             : 
     131        1766 :   err = fd_table_put (fdt, fd, dir, item, &tag->idx);
     132        1767 :   if (err)
     133             :     {
     134           0 :       free (tag);
     135           0 :       free (item);
     136           0 :       return err;
     137             :     }
     138             : 
     139        1767 :   TRACE3 (DEBUG_CTX, "_gpgme_add_io_cb", ctx,
     140             :           "fd %d, dir=%d -> tag=%p", fd, dir, tag);
     141             : 
     142        1767 :   *r_tag = tag;
     143        1767 :   return 0;
     144             : }
     145             : 
     146             : 
     147             : void
     148        1753 : _gpgme_remove_io_cb (void *data)
     149             : {
     150        1753 :   struct tag *tag = data;
     151             :   gpgme_ctx_t ctx;
     152             :   fd_table_t fdt;
     153             :   int idx;
     154             : 
     155        1753 :   assert (tag);
     156        1753 :   ctx = tag->ctx;
     157        1753 :   assert (ctx);
     158        1753 :   fdt = &ctx->fdt;
     159        1753 :   assert (fdt);
     160        1753 :   idx = tag->idx;
     161             : 
     162        1753 :   TRACE2 (DEBUG_CTX, "_gpgme_remove_io_cb", data,
     163             :           "setting fd 0x%x (item=%p) done", fdt->fds[idx].fd,
     164             :           fdt->fds[idx].opaque);
     165             : 
     166        1753 :   free (fdt->fds[idx].opaque);
     167        1753 :   free (tag);
     168             : 
     169             :   /* Free the table entry.  */
     170        1753 :   fdt->fds[idx].fd = -1;
     171        1753 :   fdt->fds[idx].for_read = 0;
     172        1753 :   fdt->fds[idx].for_write = 0;
     173        1753 :   fdt->fds[idx].opaque = NULL;
     174        1753 : }
     175             : 
     176             : 
     177             : /* This is slightly embarrassing.  The problem is that running an I/O
     178             :    callback _may_ influence the status of other file descriptors.  Our
     179             :    own event loops could compensate for that, but the external event
     180             :    loops cannot.  FIXME: We may still want to optimize this a bit when
     181             :    we are called from our own event loops.  So if CHECKED is 1, the
     182             :    check is skipped.  */
     183             : gpgme_error_t
     184        8019 : _gpgme_run_io_cb (struct io_select_fd_s *an_fds, int checked,
     185             :                   gpgme_error_t *op_err)
     186             : {
     187             :   struct wait_item_s *item;
     188             :   struct io_cb_data iocb_data;
     189             :   gpgme_error_t err;
     190             : 
     191        8019 :   item = (struct wait_item_s *) an_fds->opaque;
     192        8019 :   assert (item);
     193             : 
     194        8019 :   if (!checked)
     195             :     {
     196             :       int nr;
     197             :       struct io_select_fd_s fds;
     198             : 
     199        8021 :       TRACE0 (DEBUG_CTX, "_gpgme_run_io_cb", item, "need to check");
     200        8020 :       fds = *an_fds;
     201        8020 :       fds.signaled = 0;
     202             :       /* Just give it a quick poll.  */
     203        8020 :       nr = _gpgme_io_select (&fds, 1, 1);
     204        8024 :       assert (nr <= 1);
     205        8024 :       if (nr < 0)
     206           0 :         return errno;
     207        8024 :       else if (nr == 0)
     208             :         /* The status changed in the meantime, there is nothing left
     209             :            to do.  */
     210           0 :         return 0;
     211             :     }
     212             : 
     213        8022 :   TRACE2 (DEBUG_CTX, "_gpgme_run_io_cb", item, "handler (%p, %d)",
     214             :           item->handler_value, an_fds->fd);
     215             : 
     216        8026 :   iocb_data.handler_value = item->handler_value;
     217        8026 :   iocb_data.op_err = 0;
     218        8026 :   err = item->handler (&iocb_data, an_fds->fd);
     219             : 
     220       16147 :   *op_err = iocb_data.op_err;
     221       16147 :   return err;
     222             : }

Generated by: LCOV version 1.11