LTP GCOV extension - code coverage report
Current view: directory - and-httpd/src - ex_utils.h
Test: And-httpd coverage
Date: 2006-09-11 Instrumented lines: 97
Code covered: 56.7 % Executed lines: 55

       1                 : #ifndef EX_UTILS_H
       2                 : #define EX_UTILS_H 1
       3                 : 
       4                 : /* ************************************************************************** */
       5                 : /* headers: Vstr (and all supporting system headers), plus extra ones we need */
       6                 : /* ************************************************************************** */
       7                 : #define _GNU_SOURCE 1 /* for posix_fadvice etc. */
       8                 : #define VSTR_COMPILE_INCLUDE 1 /* make Vstr include it's system headers */
       9                 : #include <vstr.h>
      10                 : 
      11                 : #include <errno.h>
      12                 : 
      13                 : #include <err.h> /* BSD/Linux header see: man errx */
      14                 : 
      15                 : #include <poll.h>
      16                 : 
      17                 : #include <sys/types.h> /* stat + open + STDXXX_FILENO */
      18                 : #include <sys/stat.h>
      19                 : #include <unistd.h>
      20                 : #include <fcntl.h>
      21                 : 
      22                 : #include <string.h> /* strncmp() etc. in GETOPT macros */
      23                 : 
      24                 : #include "compiler.h" /* includes autoconf.h */
      25                 : 
      26                 : #undef NULL
      27                 : #define NULL ((void *)0) /* fix C++/old-C braindamage */
      28                 : 
      29                 : /* fix.h ? */
      30                 : #ifndef O_NOATIME
      31                 : #define O_NOATIME 0
      32                 : #endif
      33                 : 
      34                 : /* **************************************************************** */
      35                 : /* defines: TRUE/FALSE and assert(), Note that GETOPT is used later */
      36                 : /* **************************************************************** */
      37                 : 
      38                 : #ifndef FALSE
      39                 : # define FALSE 0
      40                 : #endif
      41                 : 
      42                 : #ifndef TRUE
      43                 : # define TRUE 1
      44                 : #endif
      45                 : 
      46                 : #ifndef SWAP_TYPE
      47                 : #define SWAP_TYPE(x, y, type) do {              \
      48                 :       type internal_local_tmp = (x);            \
      49                 :       (x) = (y);                                \
      50                 :       (y) = internal_local_tmp;                 \
      51                 :     } while (FALSE)
      52                 : #endif
      53                 : 
      54                 : /* help the programmers with the double negatives all the time */
      55                 : #define CSTREQ(x, y) (!strcmp(x, y))
      56                 : 
      57                 : /* values, values, values */
      58                 : #define min_t(T, a, b) ((((T)(a)) > ((T)(b))) ? (a) : (b))
      59                 : #define max_t(T, a, b) ((((T)(a)) < ((T)(b))) ? (a) : (b))
      60                 : 
      61                 : 
      62                 : /* Simple getopt code... */
      63                 : #define EX_UTILS_GETOPT_NUM(name, var) \
      64                 :     else if (!strncmp("--" name "=", argv[count], strlen("--" name "=")) || \
      65                 :              !strncmp("--" name, argv[count], strlen(argv[count])))     \
      66                 :     {                                                                   \
      67                 :       if (strncmp("--" name, argv[count], strlen(argv[count])))         \
      68                 :         (var) = strtol(argv[count] + strlen("--" name "="), NULL, 0);   \
      69                 :       else                                                              \
      70                 :       {                                                                 \
      71                 :         (var) = 0;                                                      \
      72                 :                                                                         \
      73                 :         ++count;                                                        \
      74                 :         if (count >= argc)                                              \
      75                 :           break;                                                        \
      76                 :                                                                         \
      77                 :         (var) = strtol(argv[count], NULL, 0);                           \
      78                 :       }                                                                 \
      79                 :     }                                                                   \
      80                 :     else if (0) ASSERT(FALSE)
      81                 : 
      82                 : #define EX_UTILS_GETOPT_CSTR(name, var) \
      83                 :     else if (!strncmp("--" name "=", argv[count], strlen("--" name "=")) || \
      84                 :              !strncmp("--" name, argv[count], strlen(argv[count])))     \
      85                 :     {                                                                   \
      86                 :       if (strncmp("--" name, argv[count], strlen(argv[count])))         \
      87                 :         (var) = argv[count] + strlen("--" name "=");                    \
      88                 :       else                                                              \
      89                 :       {                                                                 \
      90                 :         (var) = NULL;                                                   \
      91                 :                                                                         \
      92                 :         ++count;                                                        \
      93                 :         if (count >= argc)                                              \
      94                 :           break;                                                        \
      95                 :                                                                         \
      96                 :         (var) = argv[count];                                            \
      97                 :       }                                                                 \
      98                 :     }                                                                   \
      99                 :     else if (0) ASSERT(FALSE)
     100                 : 
     101                 : #define EX_UTILS_GETOPT_TOGGLE(name, var)                               \
     102                 :     else if (!strncmp("--" name, argv[count], strlen(argv[count])))     \
     103                 :       (var) = !(var);                                                   \
     104                 :     else if (0) ASSERT(FALSE)    
     105                 : 
     106                 : 
     107                 : #if COMPILE_DEBUG
     108                 : # define assert(x) do { if (x) {} else { warnx("assert(%s), FAILED at %s:%u", #x , __FILE__, __LINE__); abort(); } } while (FALSE)
     109                 : # define ASSERT(x) do { if (x) {} else { warnx("ASSERT(%s), FAILED at %s:%u", #x , __FILE__, __LINE__); abort(); } } while (FALSE)
     110                 : # define assert_ret(x, y) do { if (x) {} else { warnx("assert(%s), FAILED at %s:%u", #x , __FILE__, __LINE__); abort(); } } while (FALSE)
     111                 : # define ASSERT_RET(x, y) do { if (x) {} else { warnx("ASSERT(%s), FAILED at %s:%u", #x , __FILE__, __LINE__); abort(); } } while (FALSE)
     112                 : # define ASSERT_NO_SWITCH_DEF() break; default: ASSERT(!"default label")
     113                 : #else
     114                 : # define assert(x) do { } while (FALSE)
     115                 : # define ASSERT(x) do { } while (FALSE)
     116                 : # define assert_ret(x, y) do { if (x) {} else return y; } while (FALSE)
     117                 : # define ASSERT_RET(x, y) do { if (x) {} else return y; } while (FALSE)
     118                 : # define ASSERT_NO_SWITCH_DEF() break
     119                 : #endif
     120                 : #define ASSERT_NOT_REACHED() ASSERT(!"not reached")
     121                 : 
     122                 : 
     123                 : /* ********************************* */
     124                 : /* generic POSIX IO helper functions */
     125                 : /* ********************************* */
     126                 : 
     127                 : /* limits on amount of data we keep in core -- can be overridden */
     128                 : /* Note that EX_UTILS_NO_USE_INPUT should be defined if Input IO isn't needed */
     129                 : #ifndef EX_MAX_R_DATA_INCORE
     130                 : #define EX_MAX_R_DATA_INCORE (8 * 1024)
     131                 : #endif
     132                 : #ifndef EX_MAX_W_DATA_INCORE
     133                 : #define EX_MAX_W_DATA_INCORE (8 * 1024)
     134                 : #endif
     135                 : 
     136                 : #ifndef EX_UTILS_RET_FAIL
     137                 : #define EX_UTILS_RET_FAIL FALSE
     138                 : #endif
     139                 : 
     140                 : #define IO_OK    0
     141                 : #define IO_BLOCK 1
     142                 : #define IO_EOF   2
     143                 : #define IO_NONE  3
     144                 : #define IO_FAIL  4
     145                 : 
     146                 : #if !defined(EX_UTILS_NO_FUNCS) && !defined(EX_UTILS_NO_USE_BLOCK)
     147                 : /* block waiting for IO read, write or both... */
     148                 : static void io_block(int io_r_fd, int io_w_fd)
     149               0 : {
     150                 :   struct pollfd ios_beg[2];
     151               0 :   struct pollfd *ios = ios_beg;
     152               0 :   unsigned int num = 0;
     153                 :   
     154               0 :   ios[0].revents = ios[1].revents = 0;
     155                 :   
     156               0 :   if (io_r_fd == io_w_fd)
     157                 :   { /* block on both read and write, same fds */
     158               0 :     num = 1;
     159               0 :     ios[0].events = POLLIN | POLLOUT;
     160               0 :     ios[0].fd     = io_w_fd;
     161                 :   }
     162                 :   else
     163                 :   { /* block on read or write or both */
     164               0 :     if (io_r_fd != -1)
     165                 :     {
     166               0 :       ios->events = POLLIN;
     167               0 :       ios->fd     = io_r_fd;
     168               0 :       ++num; ++ios;
     169                 :     }
     170               0 :     if (io_w_fd != -1)
     171                 :     {
     172               0 :       ios->events = POLLOUT;
     173               0 :       ios->fd     = io_w_fd;
     174               0 :       ++num; ++ios;
     175                 :     }
     176                 :   }
     177                 :   
     178               0 :   while (poll(ios_beg, num, -1) == -1) /* can't timeout */
     179                 :   {
     180               0 :     if (errno != EINTR)
     181               0 :       err(EXIT_FAILURE, "poll");
     182                 :   }
     183               0 : }
     184                 : #endif
     185                 : 
     186                 : /* Try and move some data from Vstr string to fd */
     187                 : #if !defined(EX_UTILS_NO_FUNCS) && !defined(EX_UTILS_NO_USE_PUT)
     188                 : static int io_put(Vstr_base *io_w, int fd)
     189             208 : {
     190             208 :   if (!io_w->len)
     191             104 :     return (IO_NONE);
     192                 : 
     193             104 :   if (!vstr_sc_write_fd(io_w, 1, io_w->len, fd, NULL))
     194                 :   {
     195               0 :     if (errno == EAGAIN)
     196               0 :       return (IO_BLOCK);
     197                 : 
     198                 :     if (EX_UTILS_RET_FAIL)
     199               0 :       return (IO_FAIL);
     200                 :     
     201               0 :     err(EXIT_FAILURE, "write");
     202                 :   }
     203                 : 
     204             104 :   return (IO_OK);
     205                 : }
     206                 : #endif
     207                 : 
     208                 : #if !defined(EX_UTILS_NO_FUNCS) && !defined(EX_UTILS_NO_USE_BLOCK)
     209                 : #ifndef EX_UTILS_NO_USE_PUTALL
     210                 : /* loop outputting data until empty, blocking when needed */
     211                 : static int io_put_all(Vstr_base *io_w, int fd)
     212             104 : {
     213             104 :   int state = IO_NONE;
     214                 : 
     215             304 :   while ((state = io_put(io_w, fd)) != IO_NONE)
     216                 :   {
     217              96 :     if (state == IO_BLOCK)
     218               0 :       io_block(-1, fd);
     219                 :     
     220              24 :     if (EX_UTILS_RET_FAIL && (state == IO_FAIL))
     221               0 :       return (IO_FAIL);
     222                 :   }
     223                 : 
     224             104 :   return (state);
     225                 : }
     226                 : #endif
     227                 : #endif
     228                 : 
     229                 : #if !defined(EX_UTILS_NO_FUNCS) && !defined(EX_UTILS_NO_USE_INPUT)
     230                 : #ifndef EX_UTILS_NO_USE_GET
     231                 : /* Try and move some data from fd to Vstr string */
     232                 : static int io_get(Vstr_base *io_r, int fd)
     233            6462 : {
     234            6462 :   if (io_r->len < EX_MAX_R_DATA_INCORE)
     235                 :   {
     236            6462 :     unsigned int ern = 0;
     237                 : 
     238            6462 :     vstr_sc_read_iov_fd(io_r, io_r->len, fd, 56, 64, &ern);
     239                 :     
     240            6462 :     if (ern == VSTR_TYPE_SC_READ_FD_ERR_EOF)
     241              10 :       return (IO_EOF);
     242            6452 :     else if ((ern == VSTR_TYPE_SC_READ_FD_ERR_READ_ERRNO) && (errno == EAGAIN))
     243               0 :       return (IO_BLOCK);
     244                 :     else if (EX_UTILS_RET_FAIL && ern)
     245                 :       return (IO_FAIL);
     246            6452 :     else if (ern)
     247               0 :       err(EXIT_FAILURE, "read");
     248                 :   }
     249                 : 
     250            6452 :   return (IO_OK);
     251                 : }
     252                 : #endif
     253                 : 
     254                 : #if !defined(EX_UTILS_NO_FUNCS) && !defined(EX_UTILS_NO_USE_LIMIT)
     255                 : /* block read or writting, depending on limits */
     256                 : static void io_limit(int io_r_state, int io_r_fd,
     257                 :                      int io_w_state, int io_w_fd, Vstr_base *s_w)
     258               8 : {
     259               8 :   if (io_w_state == IO_BLOCK) /* maybe allow data to build up */
     260                 :   {
     261               0 :     if (io_r_state == IO_BLOCK) /* block to either get or put some data */
     262               0 :       io_block(io_r_fd, io_w_fd);
     263               0 :     else if (s_w->len > EX_MAX_W_DATA_INCORE)
     264               0 :       io_block(-1, io_w_fd); /* block to put more data */
     265                 :   }
     266               8 :   else if ((io_w_state == IO_NONE) && (io_r_state == IO_BLOCK))
     267               0 :     io_block(io_r_fd, -1); /* block to get more data */
     268               8 : }
     269                 : #endif
     270                 : #endif
     271                 : 
     272                 : /* generic POSIX IO functions that _don't_ call Vstr functions */
     273                 : 
     274                 : #if !defined(EX_UTILS_NO_FUNCS) && !defined(EX_UTILS_NO_USE_IO_FD)
     275                 : static int io_fd_set_o_nonblock(int fd)
     276              88 : {
     277              88 :   int flags = 0;
     278                 : 
     279                 :   /* see if the NONBLOCK flag is set... */
     280              88 :   if ((flags = fcntl(fd, F_GETFL)) == -1)
     281               0 :     return (FALSE);
     282                 : 
     283                 :   /* if it isn't try and add it to the current flags */
     284              88 :   if (!(flags & O_NONBLOCK) &&
     285                 :       (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1))
     286               0 :     return (FALSE);
     287                 : 
     288              88 :   return (TRUE);
     289                 : }
     290                 : #endif
     291                 : 
     292                 : 
     293                 : #ifdef VSTR_AUTOCONF_HAVE_OPEN64
     294                 : # define EX_UTILS_OPEN open64
     295                 : #else
     296                 : # define EX_UTILS_OPEN open
     297                 : #endif
     298                 : 
     299                 : /* This is inherited from open() on Linux, is it always? */
     300                 : #ifdef __linux__
     301                 : # define OS_INHERITS_NONBLOCK_FROM_OPEN 1
     302                 : #else
     303                 : # define OS_INHERITS_NONBLOCK_FROM_OPEN 0
     304                 : #endif
     305                 : 
     306                 : #if !defined(EX_UTILS_NO_FUNCS) && !defined(EX_UTILS_NO_USE_OPEN)
     307                 : # ifndef VSTR_AUTOCONF_HAVE_OPEN64
     308                 : #  define open64 open
     309                 : # endif
     310                 : static int io__open(const char *filename, int xflags)
     311           72441 : { /* do we alway6s want to do this for fifo's ? */
     312           72441 :   int flags = O_RDONLY | O_NOCTTY | xflags;
     313           72441 :   int fd = EX_UTILS_OPEN(filename, flags);
     314                 : 
     315           72433 :   if ((fd == -1) && EX_UTILS_RET_FAIL)
     316           39320 :     return (-1);
     317                 :   
     318           33121 :   if (fd == -1)
     319               0 :     err(EXIT_FAILURE, "open(%s)", filename);
     320                 : 
     321                 :   /* When doing IO, it should always be non-blocking -- doesn't work
     322                 :    * for files, but fd object might be a FIFO etc. */
     323           33121 :   if (!OS_INHERITS_NONBLOCK_FROM_OPEN || !(xflags & O_NONBLOCK))
     324               8 :     io_fd_set_o_nonblock(fd);
     325                 : 
     326           33121 :   return (fd);
     327                 : }
     328                 : #if !defined(EX_UTILS_NO_USE_BLOCK) && !defined(EX_UTILS_NO_USE_BLOCKING_OPEN)
     329                 : static int io_open(const char *filename)
     330               8 : {
     331               8 :   return (io__open(filename, 0));
     332                 : }
     333                 : #endif
     334                 : #ifdef EX_UTILS_USE_NONBLOCKING_OPEN
     335                 : static int io_open_nonblock(const char *filename)
     336                 : {
     337                 :   return (io__open(filename, O_NONBLOCK));
     338                 : }
     339                 : #endif
     340                 : #endif
     341                 : 
     342                 : /* ************************ */
     343                 : /* generic helper functions */
     344                 : /* ************************ */
     345                 : 
     346                 : #if !defined(EX_UTILS_NO_FUNCS) && !defined(EX_UTILS_NO_USE_INIT)
     347                 : /* Example init function */
     348                 : static Vstr_base *ex_init(Vstr_base **s2)
     349              80 : {
     350              80 :   Vstr_base *s1 = NULL;
     351                 :   struct stat64 stat_buf;
     352                 : 
     353              80 :   if (!vstr_init()) /* init the library */
     354               0 :     errno = ENOMEM, err(EXIT_FAILURE, "init");
     355                 : 
     356                 :   
     357                 :   /* alter the node buffer size to be whatever the stdout block size is */
     358              80 :   if (fstat64(1, &stat_buf) == -1)
     359                 :   {
     360               0 :     warn("fstat(STDOUT)");
     361               0 :     stat_buf.st_blksize = 0;
     362                 :   }
     363                 :   
     364              80 :   if (!stat_buf.st_blksize) /* this is allowed to be Zero -- *BSD proc */
     365               0 :     stat_buf.st_blksize = 4096;
     366                 :   
     367              80 :   if (!vstr_cntl_conf(NULL, VSTR_CNTL_CONF_SET_NUM_BUF_SZ,
     368                 :                       stat_buf.st_blksize / 32))
     369               0 :     warnx("Couldn't alter node size to match block size");
     370                 : 
     371                 :   /* create strings... */  
     372              80 :   if (!(s1 = vstr_make_base(NULL)) ||
     373                 :       (s2 && !(*s2 = vstr_make_base(NULL))))
     374               0 :     errno = ENOMEM, err(EXIT_FAILURE, "Create string");
     375                 : 
     376                 :   /* create some data storage for _both_ of the above strings */
     377              80 :   vstr_make_spare_nodes(NULL, VSTR_TYPE_NODE_BUF, 64);
     378                 :   
     379                 :   /* Try and make stdout non-blocking, if it is a file this won't do anything */
     380              80 :   io_fd_set_o_nonblock(STDOUT_FILENO);
     381                 : 
     382              80 :   return (s1);
     383                 : }
     384                 : #endif
     385                 : 
     386                 : #if !defined(EX_UTILS_NO_FUNCS) && !defined(EX_UTILS_NO_USE_EXIT)
     387                 : /* Example exit function */
     388                 : static int ex_exit(Vstr_base *s1, Vstr_base *s2)
     389              80 : {
     390                 :   /* These next calls are only really needed for debugging,
     391                 :    * in that when they are done any memory leaks can be seen in debugging mode.
     392                 :    */
     393                 : 
     394                 :   /* As with the system free() both of these are ok if passed NULL */
     395                 :   
     396                 :   /* free s1, our String object */
     397              80 :   vstr_free_base(s1);
     398                 :   /* free s2, our String object */
     399              80 :   vstr_free_base(s2);
     400                 : 
     401                 :   /* "exit" Vstr, this free's all internal data and no library calls apart from
     402                 :    * vstr_init() should be called after this.
     403                 :    */
     404              80 :   vstr_exit();
     405                 : 
     406              80 :   return (EXIT_SUCCESS);
     407                 : }
     408                 : #endif
     409                 : 
     410                 : #endif

Generated by: LTP GCOV extension version 1.4