LCOV - code coverage report
Current view: top level - src - wait.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 80 88 90.9 %
Date: 2016-11-29 15:07:43 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         582 : _gpgme_fd_table_init (fd_table_t fdt)
      45             : {
      46         582 :   fdt->fds = NULL;
      47         582 :   fdt->size = 0;
      48         582 : }
      49             : 
      50             : void
      51         574 : _gpgme_fd_table_deinit (fd_table_t fdt)
      52             : {
      53         574 :   if (fdt->fds)
      54         561 :     free (fdt->fds);
      55         574 : }
      56             : 
      57             : 
      58             : /* XXX We should keep a marker and roll over for speed.  */
      59             : static gpgme_error_t
      60        1737 : 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        3164 :   for (i = 0; i < fdt->size; i++)
      66             :     {
      67        2595 :       if (fdt->fds[i].fd == -1)
      68        1168 :         break;
      69             :     }
      70        1737 :   if (i == fdt->size)
      71             :     {
      72             : #define FDT_ALLOCSIZE 10
      73         569 :       new_fds = realloc (fdt->fds, (fdt->size + FDT_ALLOCSIZE)
      74             :                          * sizeof (*new_fds));
      75         569 :       if (!new_fds)
      76           0 :         return gpg_error_from_syserror ();
      77             : 
      78         569 :       fdt->fds = new_fds;
      79         569 :       fdt->size += FDT_ALLOCSIZE;
      80        6259 :       for (j = 0; j < FDT_ALLOCSIZE; j++)
      81        5690 :         fdt->fds[i + j].fd = -1;
      82             :     }
      83             : 
      84        1737 :   fdt->fds[i].fd = fd;
      85        1737 :   fdt->fds[i].for_read = (dir == 1);
      86        1737 :   fdt->fds[i].for_write = (dir == 0);
      87        1737 :   fdt->fds[i].signaled = 0;
      88        1737 :   fdt->fds[i].opaque = opaque;
      89        1737 :   *idx = i;
      90        1737 :   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        1737 : _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        1737 :   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        1737 :   assert (fnc);
     109        1737 :   assert (ctx);
     110             : 
     111        1737 :   fdt = &ctx->fdt;
     112        1737 :   assert (fdt);
     113             : 
     114        1737 :   tag = malloc (sizeof *tag);
     115        1737 :   if (!tag)
     116           0 :     return gpg_error_from_syserror ();
     117        1737 :   tag->ctx = ctx;
     118             : 
     119             :   /* Allocate a structure to hold information about the handler.  */
     120        1737 :   item = calloc (1, sizeof *item);
     121        1737 :   if (!item)
     122             :     {
     123           0 :       free (tag);
     124           0 :       return gpg_error_from_syserror ();
     125             :     }
     126        1737 :   item->ctx = ctx;
     127        1737 :   item->dir = dir;
     128        1737 :   item->handler = fnc;
     129        1737 :   item->handler_value = fnc_data;
     130             : 
     131        1737 :   err = fd_table_put (fdt, fd, dir, item, &tag->idx);
     132        1737 :   if (err)
     133             :     {
     134           0 :       free (tag);
     135           0 :       free (item);
     136           0 :       return err;
     137             :     }
     138             : 
     139        1737 :   TRACE3 (DEBUG_CTX, "_gpgme_add_io_cb", ctx,
     140             :           "fd %d, dir=%d -> tag=%p", fd, dir, tag);
     141             : 
     142        1737 :   *r_tag = tag;
     143        1737 :   return 0;
     144             : }
     145             : 
     146             : 
     147             : void
     148        1749 : _gpgme_remove_io_cb (void *data)
     149             : {
     150        1749 :   struct tag *tag = data;
     151             :   gpgme_ctx_t ctx;
     152             :   fd_table_t fdt;
     153             :   int idx;
     154             : 
     155        1749 :   assert (tag);
     156        1749 :   ctx = tag->ctx;
     157        1749 :   assert (ctx);
     158        1749 :   fdt = &ctx->fdt;
     159        1749 :   assert (fdt);
     160        1749 :   idx = tag->idx;
     161             : 
     162        1749 :   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        1749 :   free (fdt->fds[idx].opaque);
     167        1749 :   free (tag);
     168             : 
     169             :   /* Free the table entry.  */
     170        1749 :   fdt->fds[idx].fd = -1;
     171        1749 :   fdt->fds[idx].for_read = 0;
     172        1749 :   fdt->fds[idx].for_write = 0;
     173        1749 :   fdt->fds[idx].opaque = NULL;
     174        1749 : }
     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        8022 : _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        8022 :   item = (struct wait_item_s *) an_fds->opaque;
     192        8022 :   assert (item);
     193             : 
     194        8022 :   if (!checked)
     195             :     {
     196             :       int nr;
     197             :       struct io_select_fd_s fds;
     198             : 
     199        8022 :       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        8025 :       assert (nr <= 1);
     205        8025 :       if (nr < 0)
     206           1 :         return errno;
     207        8025 :       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        8025 :   TRACE2 (DEBUG_CTX, "_gpgme_run_io_cb", item, "handler (%p, %d)",
     214             :           item->handler_value, an_fds->fd);
     215             : 
     216        8027 :   iocb_data.handler_value = item->handler_value;
     217        8027 :   iocb_data.op_err = 0;
     218        8027 :   err = item->handler (&iocb_data, an_fds->fd);
     219             : 
     220        7942 :   *op_err = iocb_data.op_err;
     221        7942 :   return err;
     222             : }

Generated by: LCOV version 1.11