LTP GCOV extension - code coverage report
Current view: directory - src - vstr_sc_posix.c
Test: Vstr coverage
Date: 2005-01-10 Instrumented lines: 404
Code covered: 100.0 % Executed lines: 404

       1                 : #define VSTR_SC_POSIX_C
       2                 : /*
       3                 :  *  Copyright (C) 2002, 2003, 2004  James Antill
       4                 :  *
       5                 :  *  This library is free software; you can redistribute it and/or
       6                 :  *  modify it under the terms of the GNU Lesser General Public
       7                 :  *  License as published by the Free Software Foundation; either
       8                 :  *  version 2 of the License, or (at your option) any later version.
       9                 :  *
      10                 :  *  This library is distributed in the hope that it will be useful,
      11                 :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      12                 :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13                 :  *  Lesser General Public License for more details.
      14                 :  *
      15                 :  *  You should have received a copy of the GNU Lesser General Public
      16                 :  *  License along with this library; if not, write to the Free Software
      17                 :  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      18                 :  *
      19                 :  *  email: james@and.org
      20                 :  */
      21                 : /* functions which are shortcuts */
      22                 : #include "main.h"
      23                 : 
      24                 : #if !(USE_FD_CLOSE_CHECK) /* hack to test code path on close error */
      25                 : # define VSTR__POSIX_OPEN3(x, y, z) open64(x, y, z)
      26                 : # define VSTR__POSIX_CLOSE(x) close(x)
      27                 : #else
      28                 :  /* this is all non threadsafe ... */
      29                 : # define VSTR__POSIX_OPEN3(x, y, z)  vstr__sc_posix_open(x, y, z)
      30                 : # define VSTR__POSIX_CLOSE(x) vstr__sc_posix_close(x)
      31                 : static int vstr__sc_posix_open(const char *pathname, int flags,
      32                 :                                VSTR_AUTOCONF_mode_t mode)
      33           15527 : {
      34           15527 :   int ret = open64(pathname, flags, mode);
      35                 :   
      36           15527 :   ASSERT((ret == -1) || ++vstr__options.fd_count);
      37                 : 
      38           15527 :   return (ret);
      39                 : }
      40                 : 
      41                 : static int vstr__sc_posix_close(int fd)
      42           15522 : {
      43           15522 :   int ret = close(fd);
      44                 : 
      45           15522 :   ASSERT(vstr__options.fd_count-- > 0);
      46                 :   
      47           15522 :   if ((ret != -1) &&
      48                 :       vstr__options.fd_close_fail_num && !--vstr__options.fd_close_fail_num)
      49                 :   {
      50               4 :     errno = EIO;
      51               4 :     return (-1);
      52                 :   }
      53                 : 
      54           15518 :   return (ret);
      55                 : }
      56                 : #endif
      57                 : 
      58                 : #define VSTR__POSIX_OPEN1(x)                                    \
      59                 :     VSTR__POSIX_OPEN3(x, O_RDONLY | O_NOCTTY | O_NONBLOCK, 0)
      60                 : 
      61                 : #ifndef HAVE_MMAP
      62                 : # define VSTR__SC_ENOSYS(x) \
      63                 :   if (err) \
      64                 :   { \
      65                 :     errno = ENOSYS; \
      66                 :     *err = (x); \
      67                 :   } \
      68                 :   \
      69                 :   return (FALSE)
      70                 : #else
      71                 : static void vstr__sc_ref_munmap(Vstr_ref *passed_ref)
      72            1841 : { /* debugging is all non threadsafe ... */
      73            1841 :   Vstr__sc_mmap_ref *mmap_ref = (Vstr__sc_mmap_ref *)passed_ref;
      74                 : 
      75            1841 :   munmap(mmap_ref->ref.ptr, mmap_ref->mmap_len); /* this _can't_ be -1 */
      76                 : 
      77            1841 :   VSTR__F(mmap_ref);
      78                 : 
      79             461 :   ASSERT(vstr__options.mmap_count-- > 0);
      80                 : }
      81                 : #endif
      82                 : 
      83                 : static int vstr__sc_get_size(size_t base_len,
      84                 :                              int fd, size_t *len, VSTR_AUTOCONF_off64_t off,
      85                 :                              unsigned int *err,
      86                 :                              unsigned int err_fstat, unsigned int err_size)
      87                 :     VSTR__COMPILE_ATTR_NONNULL_A();
      88                 : static int vstr__sc_get_size(size_t base_len,
      89                 :                              int fd, size_t *len, VSTR_AUTOCONF_off64_t off,
      90                 :                              unsigned int *err,
      91                 :                              unsigned int err_fstat, unsigned int err_size)
      92           80452 : {
      93           80452 :   struct stat64 stat_buf;
      94                 : 
      95           80452 :   ASSERT(len && err);
      96                 : 
      97           80452 :   if (*len)
      98           18526 :     return (TRUE);
      99                 : 
     100           61926 :   if (fstat64(fd, &stat_buf) == -1)
     101                 :   {
     102              12 :     *err = err_fstat;
     103              12 :     return (FALSE);
     104                 :   }
     105                 : 
     106           61914 :   if (stat_buf.st_size <= off)
     107                 :   {
     108               4 :     *err = err_fstat;
     109               4 :     errno = ENOSPC;
     110               4 :     return (FALSE);
     111                 :   }
     112                 : 
     113           61910 :   *len = (stat_buf.st_size - off);
     114           61910 :   if (*len > (SIZE_MAX - base_len))
     115                 :   {
     116           61728 :     *err = err_size;
     117           61728 :     errno = EFBIG;
     118           61728 :     return (FALSE);
     119                 :   }
     120                 : 
     121             182 :   return (TRUE);
     122                 : }
     123                 : 
     124                 : 
     125                 : #ifndef HAVE_MMAP
     126                 : int vstr_sc_mmap_fd(Vstr_base *VSTR__ATTR_UNUSED(base),
     127                 :                     size_t VSTR__ATTR_UNUSED(pos),
     128                 :                     int VSTR__ATTR_UNUSED(fd),
     129                 :                     VSTR_AUTOCONF_off64_t VSTR__ATTR_UNUSED(off),
     130                 :                     size_t VSTR__ATTR_UNUSED(len),
     131                 :                     unsigned int *err)
     132                 : { VSTR__SC_ENOSYS(VSTR_TYPE_SC_MMAP_FD_ERR_MMAP_ERRNO); }
     133                 : #else
     134                 : int vstr_sc_mmap_fd(Vstr_base *base, size_t pos, int fd,
     135                 :                     VSTR_AUTOCONF_off64_t off, size_t len, unsigned int *err)
     136           32727 : {
     137           32727 :   unsigned int dummy_err;
     138           32727 :   void *addr = NULL;
     139           32727 :   Vstr__sc_mmap_ref *mmap_ref = NULL;
     140                 : 
     141           32727 :   assert(off >= 0); /* off is offset from the start of the file,
     142                 :                      * not as in seek */
     143                 : 
     144           32727 :   if (!err)
     145            1704 :     err = &dummy_err;
     146           32727 :   *err = 0;
     147                 : 
     148           32727 :   ASSERT_GOTO(base && (pos <= base->len), inval_args);
     149                 :   
     150           32727 :   if (!vstr__sc_get_size(base->len, fd, &len, off, err,
     151                 :                          VSTR_TYPE_SC_MMAP_FD_ERR_FSTAT_ERRNO,
     152                 :                          VSTR_TYPE_SC_MMAP_FD_ERR_TOO_LARGE))
     153           30872 :     return (FALSE);
     154                 : 
     155            1855 :   addr = mmap64(NULL, len, PROT_READ, MAP_PRIVATE, fd, off);
     156            1855 :   if (addr == MAP_FAILED)
     157                 :   {
     158              12 :     *err = VSTR_TYPE_SC_MMAP_FD_ERR_MMAP_ERRNO;
     159              12 :     return (FALSE);
     160                 :   }
     161                 : 
     162            1843 :   if (!(mmap_ref = VSTR__MK(sizeof(Vstr__sc_mmap_ref))))
     163               1 :     goto malloc_mmap_ref_failed;
     164            1842 :   mmap_ref->mmap_len = len;
     165            1842 :   mmap_ref->ref.func = vstr__sc_ref_munmap;
     166            1842 :   mmap_ref->ref.ptr = (void *)addr;
     167            1842 :   mmap_ref->ref.ref = 0;
     168                 : 
     169            1842 :   if (!vstr_add_ref(base, pos, &mmap_ref->ref, 0, len))
     170               1 :     goto add_ref_failed;
     171                 : 
     172            1841 :   ASSERT(++vstr__options.mmap_count);
     173                 : 
     174            1841 :   return (TRUE);
     175                 : 
     176                 :  add_ref_failed:
     177               1 :   VSTR__F(mmap_ref);
     178                 :  malloc_mmap_ref_failed:
     179               2 :   munmap(addr, len);
     180               2 :   *err = VSTR_TYPE_SC_MMAP_FILE_ERR_MEM;
     181               2 :   errno = ENOMEM;
     182               2 :   base->conf->malloc_bad = TRUE;
     183                 : 
     184               2 :   return (FALSE);
     185                 :   
     186                 :  inval_args:
     187            8184 :   *err = VSTR_TYPE_SC_MMAP_FD_ERR_MMAP_ERRNO;
     188            8184 :   errno = EINVAL;
     189            8184 :   return (FALSE);
     190                 : }
     191                 : #endif
     192                 : 
     193                 : #ifndef HAVE_MMAP
     194                 : int vstr_sc_mmap_file(Vstr_base *VSTR__ATTR_UNUSED(base),
     195                 :                       size_t VSTR__ATTR_UNUSED(pos),
     196                 :                       const char *VSTR__ATTR_UNUSED(filename),
     197                 :                       VSTR_AUTOCONF_off64_t VSTR__ATTR_UNUSED(off),
     198                 :                       size_t VSTR__ATTR_UNUSED(len),
     199                 :                       unsigned int *err)
     200                 : { VSTR__SC_ENOSYS(VSTR_TYPE_SC_MMAP_FD_ERR_MMAP_ERRNO); }
     201                 : #else
     202                 : int vstr_sc_mmap_file(Vstr_base *base, size_t pos, const char *filename,
     203                 :                       VSTR_AUTOCONF_off64_t off, size_t len,
     204                 :                       unsigned int *err)
     205           31019 : {
     206           31019 :   int fd = -1;
     207           31019 :   unsigned int dummy_err;
     208           31019 :   int ret = 0;
     209           31019 :   int saved_errno = 0;
     210                 : 
     211           31019 :   if (!err)
     212              12 :     err = &dummy_err;
     213           31019 :   *err = 0;
     214                 : 
     215           31019 :   if ((fd = VSTR__POSIX_OPEN1(filename)) == -1)
     216                 :   {
     217               4 :     *err = VSTR_TYPE_SC_MMAP_FILE_ERR_OPEN_ERRNO;
     218               4 :     return (FALSE);
     219                 :   }
     220                 : 
     221           31015 :   ret = vstr_sc_mmap_fd(base, pos, fd, off, len, err);
     222                 : 
     223           31015 :   if (*err)
     224           30870 :     saved_errno = errno;
     225                 : 
     226           31015 :   if ((VSTR__POSIX_CLOSE(fd) == -1) && !*err)
     227                 :   {
     228               1 :     *err = VSTR_TYPE_SC_MMAP_FILE_ERR_CLOSE_ERRNO;
     229               1 :     return (FALSE);
     230                 :   }
     231                 :   
     232           31014 :   if (*err)
     233           30870 :     errno = saved_errno;
     234                 : 
     235           31014 :   return (ret);
     236                 : }
     237                 : #endif
     238                 : 
     239                 : static int vstr__sc_read_slow_len_fd(Vstr_base *base, size_t pos, int fd,
     240                 :                                      size_t len, unsigned int *err)
     241              32 : {
     242              32 :   size_t orig_pos = pos;
     243              32 :   ssize_t bytes = -1;
     244              32 :   unsigned int num = 0;
     245              32 :   Vstr_ref *ref = NULL;
     246                 : 
     247              32 :   ASSERT_GOTO(base && (pos <= base->len), inval_args);
     248                 : 
     249              32 :   if (pos && !vstr__add_setup_pos(base, &pos, &num, NULL))
     250               1 :     goto mem_fail;
     251              31 :   pos = orig_pos;
     252                 : 
     253              31 :   if (!(ref = vstr_ref_make_malloc(len)))
     254               2 :     goto mem_fail;
     255                 : 
     256              29 :   if (!vstr_cntl_conf(base->conf, VSTR_CNTL_CONF_SET_NUM_RANGE_SPARE_REF,
     257                 :                       1, UINT_MAX))
     258               1 :     goto mem_ref_fail;
     259                 : 
     260              28 :   do
     261                 :   {
     262              28 :     bytes = read(fd, ref->ptr, len);
     263              28 :   } while ((bytes == -1) && (errno == EINTR));
     264                 : 
     265              28 :   if (bytes == -1)
     266                 :   {
     267               4 :     *err = VSTR_TYPE_SC_READ_FD_ERR_READ_ERRNO;
     268               4 :     goto mem_ref_fail;
     269                 :   }
     270              24 :   if (!bytes)
     271                 :   {
     272               4 :     *err = VSTR_TYPE_SC_READ_FD_ERR_EOF;
     273               4 :     errno = ENOSPC;
     274               4 :     goto mem_ref_fail;
     275                 :   }
     276                 : 
     277              20 :   num = vstr_add_ref(base, pos, ref, 0, bytes); /* must work */
     278              20 :   ASSERT(num);
     279                 :   
     280              20 :   vstr_ref_del(ref);
     281                 : 
     282              20 :   return (TRUE);
     283                 : 
     284                 :  mem_ref_fail:
     285               9 :   assert(ref);
     286               9 :   vstr_ref_del(ref);
     287                 :   
     288                 :  mem_fail:
     289              12 :   if (!*err)
     290                 :   {
     291               4 :     *err = VSTR_TYPE_SC_READ_FD_ERR_MEM;
     292               4 :     errno = ENOMEM;
     293                 :   }
     294                 :   
     295              12 :   return (FALSE);
     296                 : 
     297                 :  inval_args:
     298              11 :   *err = VSTR_TYPE_SC_READ_FD_ERR_READ_ERRNO;
     299              11 :   errno = EINVAL;
     300              11 :   return (FALSE);
     301                 : }
     302                 : 
     303                 : static int vstr__sc_read_fast_iov_fd(Vstr_base *base, size_t pos, int fd,
     304                 :                                      struct iovec *iovs, unsigned int num,
     305                 :                                      unsigned int *err)
     306           70786 : {
     307           70786 :   ssize_t bytes = -1;
     308                 : 
     309           70786 :   if (num > UIO_MAXIOV)
     310               4 :     num = UIO_MAXIOV;
     311                 : 
     312           70786 :   do
     313                 :   {
     314           70786 :     bytes = readv(fd, iovs, num);
     315           70786 :   } while ((bytes == -1) && (errno == EINTR));
     316                 : 
     317           70786 :   if (bytes == -1)
     318                 :   {
     319            6828 :     vstr_add_iovec_buf_end(base, pos, 0);
     320            6828 :     *err = VSTR_TYPE_SC_READ_FD_ERR_READ_ERRNO;
     321            6828 :     return (FALSE);
     322                 :   }
     323                 : 
     324           63958 :   vstr_add_iovec_buf_end(base, pos, (size_t)bytes);
     325                 : 
     326           63958 :   if (!bytes)
     327                 :   {
     328            2155 :     *err = VSTR_TYPE_SC_READ_FD_ERR_EOF;
     329            2155 :     errno = ENOSPC;
     330            2155 :     return (FALSE);
     331                 :   }
     332                 : 
     333           61803 :   return (TRUE);
     334                 : }
     335                 : 
     336                 : int vstr_sc_read_iov_fd(Vstr_base *base, size_t pos, int fd,
     337                 :                         unsigned int min, unsigned int max,
     338                 :                         unsigned int *err)
     339           53976 : {
     340           53976 :   struct iovec *iovs = NULL;
     341           53976 :   unsigned int num = 0;
     342           53976 :   unsigned int dummy_err;
     343                 : 
     344           53976 :   if (!err)
     345               8 :     err = &dummy_err;
     346           53976 :   *err = 0;
     347                 : 
     348           53976 :   assert(max >= min);
     349                 : 
     350           53976 :   ASSERT_GOTO(base && (pos <= base->len), inval_args);
     351                 :   
     352           53976 :   if (!min)
     353               4 :     return (TRUE);
     354                 : 
     355           53972 :   if (!base->cache_available)
     356              18 :     return (vstr__sc_read_slow_len_fd(base, pos, fd,
     357                 :                                       min * base->conf->buf_sz, err));
     358                 : 
     359                 :   /* use iovec internal add -- much quicker, one syscall no double copy  */
     360           53954 :   if (!vstr_add_iovec_buf_beg(base, pos, min, max, &iovs, &num))
     361                 :   {
     362               1 :     *err = VSTR_TYPE_SC_READ_FD_ERR_MEM;
     363               1 :     errno = ENOMEM;
     364               1 :     return (FALSE);
     365                 :   }
     366                 : 
     367           53953 :   return (vstr__sc_read_fast_iov_fd(base, pos, fd, iovs, num, err));
     368                 :   
     369                 :  inval_args:
     370           19292 :   *err = VSTR_TYPE_SC_READ_FD_ERR_READ_ERRNO;
     371           19292 :   errno = EINVAL;
     372           19292 :   return (FALSE);
     373                 : }
     374                 : 
     375                 : #define IOV_SZ(iovs, num) \
     376                 :  (iovs[0].iov_len + ((num > 1) ? iovs[num - 1].iov_len : 0) + \
     377                 :                     ((num > 2) ? ((num - 2) * base->conf->buf_sz) : 0))
     378                 : 
     379                 : static int vstr__sc_read_len_fd(Vstr_base *base, size_t pos, int fd,
     380                 :                                 size_t len, unsigned int *err)
     381           16849 : {
     382           16849 :   struct iovec *iovs = NULL;
     383           16849 :   unsigned int num = 0;
     384           16849 :   unsigned int ios = 0;
     385                 : 
     386           16849 :   if (!base->cache_available)
     387              14 :     return (vstr__sc_read_slow_len_fd(base, pos, fd, len, err));
     388                 : 
     389                 :   /* guess at 2 over size, as we usually lose some in the division
     390                 :    * and we can lose a lot on iovs[0] */
     391           16835 :   ios = len / base->conf->buf_sz;
     392           16835 :   ios += 2;
     393           16835 :   if (!vstr_add_iovec_buf_beg(base, pos, ios, ios, &iovs, &num))
     394                 :   {
     395               2 :     *err = VSTR_TYPE_SC_READ_FD_ERR_MEM;
     396               2 :     errno = ENOMEM;
     397               2 :     return (FALSE);
     398                 :   }
     399                 : 
     400                 :   /* fixup iovs for exact size of len, if bigger */
     401           42077 :   assert(num && ((num == 1) || (iovs[num - 1].iov_len == base->conf->buf_sz)));
     402                 : 
     403           42077 :   assert(IOV_SZ(iovs, num) >= len);
     404           50499 :   while (IOV_SZ(iovs, num) >  len)
     405                 :   {
     406           33666 :     size_t tmp = 0;
     407                 : 
     408           33666 :     tmp = (IOV_SZ(iovs, num) -  len);
     409           33666 :     if (tmp >= iovs[num - 1].iov_len)
     410                 :     {
     411           16833 :       --num;
     412           16833 :       continue;
     413                 :     }
     414                 : 
     415           16833 :     iovs[num - 1].iov_len  -= tmp;
     416           16833 :     assert(IOV_SZ(iovs, num) == len);
     417                 :   }
     418           16833 :   assert(IOV_SZ(iovs, num) == len);
     419                 : 
     420           16833 :   return (vstr__sc_read_fast_iov_fd(base, pos, fd, iovs, num, err));
     421                 : }
     422                 : #undef IOV_SZ
     423                 : 
     424                 : int vstr_sc_read_len_fd(Vstr_base *base, size_t pos, int fd,
     425                 :                         size_t len, unsigned int *err)
     426           16758 : {
     427           16758 :   unsigned int dummy_err;
     428           16758 :   const size_t off = 0;
     429                 : 
     430           16758 :   if (!err)
     431               8 :     err = &dummy_err;
     432           16758 :   *err = 0;
     433                 : 
     434           16758 :   ASSERT_GOTO(base && (pos <= base->len), inval_args);
     435                 :   
     436           16758 :   if (!vstr__sc_get_size(base->len, fd, &len, off, err,
     437                 :                          VSTR_TYPE_SC_READ_FD_ERR_FSTAT_ERRNO,
     438                 :                          VSTR_TYPE_SC_READ_FD_ERR_TOO_LARGE))
     439               4 :     return (FALSE);
     440                 : 
     441           16754 :   return (vstr__sc_read_len_fd(base, pos, fd, len, err));
     442                 :   
     443                 :  inval_args:
     444            4193 :   *err = VSTR_TYPE_SC_READ_FD_ERR_READ_ERRNO;
     445            4193 :   errno = EINVAL;
     446            4193 :   return (FALSE);
     447                 : }
     448                 : 
     449                 : int vstr_sc_read_iov_file(Vstr_base *base, size_t pos,
     450                 :                           const char *filename, VSTR_AUTOCONF_off64_t off,
     451                 :                           unsigned int min, unsigned int max,
     452                 :                           unsigned int *err)
     453              50 : {
     454              50 :   int fd = -1;
     455              50 :   unsigned int dummy_err;
     456              50 :   int ret = 0;
     457              50 :   int saved_errno = 0;
     458                 : 
     459              50 :   if (!err)
     460              17 :     err = &dummy_err;
     461              50 :   *err = 0;
     462                 :   
     463              50 :   ASSERT_GOTO(base && (pos <= base->len), inval_args);
     464                 : 
     465              32 :   if ((fd = VSTR__POSIX_OPEN1(filename)) == -1)
     466                 :   {
     467               4 :     *err = VSTR_TYPE_SC_READ_FILE_ERR_OPEN_ERRNO;
     468               4 :     return (FALSE);
     469                 :   }
     470                 : 
     471              28 :   if (off && (lseek64(fd, off, SEEK_SET) == -1))
     472               4 :     *err = VSTR_TYPE_SC_READ_FILE_ERR_SEEK_ERRNO;
     473                 : 
     474              28 :   if (!*err)
     475                 :   {
     476              24 :     size_t orig_pos = pos;
     477              24 :     size_t orig_len = base->len;
     478                 : 
     479              60 :     while (!*err && min)
     480                 :     {
     481              36 :       unsigned int num = base->num;
     482              36 :       size_t tmp = base->len;
     483                 :       
     484              36 :       ret = vstr_sc_read_iov_fd(base, pos, fd, min, max, err);
     485                 :       
     486              36 :       num = base->num - num;
     487              36 :       if (num > min) num = min;
     488                 :       
     489              36 :       min -= num;
     490              36 :       max -= num;
     491              36 :       pos += base->len - tmp;
     492                 :     }
     493              24 :     if (*err) /* shouldn't change errno */
     494                 :     {
     495               3 :       ASSERT((saved_errno =  errno));
     496               3 :       vstr_del(base, orig_pos, base->len - orig_len);
     497              21 :       ASSERT( saved_errno == errno);
     498                 :     }
     499                 :   }
     500                 : 
     501              28 :   if (*err)
     502               7 :     saved_errno = errno;
     503                 : 
     504              28 :   if ((VSTR__POSIX_CLOSE(fd) == -1) && !*err)
     505                 :   {
     506               1 :     *err = VSTR_TYPE_SC_READ_FILE_ERR_CLOSE_ERRNO;
     507               1 :     return (FALSE);
     508                 :   }
     509                 :   
     510              27 :   if (*err)
     511               7 :     errno = saved_errno;
     512                 : 
     513              27 :   return (ret);
     514                 :   
     515                 :  inval_args:
     516              29 :   *err = VSTR_TYPE_SC_READ_FD_ERR_READ_ERRNO;
     517              29 :   errno = EINVAL;
     518              29 :   return (FALSE);
     519                 : }
     520                 : 
     521                 : int vstr_sc_read_len_file(Vstr_base *base, size_t pos,
     522                 :                           const char *filename,
     523                 :                           VSTR_AUTOCONF_off64_t off, size_t len,
     524                 :                           unsigned int *err)
     525           30993 : {
     526           30993 :   int fd = -1;
     527           30993 :   unsigned int dummy_err;
     528           30993 :   int ret = FALSE;
     529           30993 :   int saved_errno = 0;
     530                 : 
     531           30993 :   if (!err)
     532              83 :     err = &dummy_err;
     533           30993 :   *err = 0;
     534                 : 
     535           30993 :   ASSERT_GOTO(base && (pos <= base->len), inval_args);
     536                 :   
     537           30975 :   if ((fd = VSTR__POSIX_OPEN1(filename)) == -1)
     538                 :   {
     539               8 :     *err = VSTR_TYPE_SC_READ_FILE_ERR_OPEN_ERRNO;
     540               8 :     return (FALSE);
     541                 :   }
     542                 : 
     543           30967 :   if (vstr__sc_get_size(base->len, fd, &len, off, err,
     544                 :                         VSTR_TYPE_SC_READ_FILE_ERR_FSTAT_ERRNO,
     545                 :                         VSTR_TYPE_SC_READ_FILE_ERR_TOO_LARGE))
     546                 :   {
     547              99 :     if (off && (lseek64(fd, off, SEEK_SET) == -1))
     548               4 :       *err = VSTR_TYPE_SC_READ_FILE_ERR_SEEK_ERRNO;
     549                 :   }
     550                 : 
     551           30967 :   if (!*err)
     552                 :   {
     553              95 :     size_t orig_pos = pos;
     554              95 :     size_t orig_len = base->len;
     555                 :     
     556             190 :     while (!*err && len)
     557                 :     {
     558              95 :       size_t tmp = base->len;
     559                 :       
     560              95 :       ret = vstr__sc_read_len_fd(base, pos, fd, len, err);
     561              95 :       len -= base->len - tmp;
     562              95 :       pos += base->len - tmp;
     563                 :     }
     564                 :     
     565              95 :     if (*err)
     566                 :     {
     567               4 :       ASSERT((saved_errno =  errno));
     568               4 :       vstr_del(base, orig_pos, base->len - orig_len);
     569           23227 :       ASSERT( saved_errno == errno);
     570                 :     }
     571                 :   }
     572                 :   
     573           30967 :   if (*err)
     574           30876 :     saved_errno = errno;
     575                 : 
     576           30967 :   if ((VSTR__POSIX_CLOSE(fd) == -1) && !*err)
     577                 :   {
     578               1 :     *err = VSTR_TYPE_SC_READ_FILE_ERR_CLOSE_ERRNO;
     579               1 :     return (FALSE);
     580                 :   }
     581                 :   
     582           30966 :   if (*err)
     583           30876 :     errno = saved_errno;
     584                 : 
     585           30966 :   return (ret);
     586                 :   
     587                 :  inval_args:
     588            7764 :   *err = VSTR_TYPE_SC_READ_FD_ERR_READ_ERRNO;
     589            7764 :   errno = EINVAL;
     590            7764 :   return (FALSE);
     591                 : }
     592                 : 
     593                 : int vstr_sc_write_fd(Vstr_base *base, size_t pos, size_t len, int fd,
     594                 :                      unsigned int *err)
     595           97092 : {
     596           97092 :   unsigned int dummy_err;
     597                 : 
     598           97092 :   if (!err)
     599           56556 :     err = &dummy_err;
     600           97092 :   *err = 0;
     601                 : 
     602           97092 :   ASSERT_GOTO(base && pos && (((pos <= base->len) &&
     603                 :                                (vstr_sc_poslast(pos, len) <= base->len)) ||
     604                 :                               !len), inval_args);
     605                 :   
     606           97083 :   if (!len)
     607             934 :     return (TRUE);
     608                 : 
     609          176223 :   while (len)
     610                 :   {
     611           96194 :     struct iovec cpy_vec[VSTR__SC_VEC_SZ];
     612           96194 :     size_t sz = VSTR__SC_VEC_SZ;
     613           96194 :     struct iovec *vec;
     614           96194 :     unsigned int num = 0;
     615           96194 :     size_t  clen  = 0;
     616           96194 :     ssize_t bytes = 0;
     617                 : 
     618           96194 :     if ((pos == 1) && (len == base->len) && base->cache_available)
     619                 :     {
     620           96169 :       if (!(clen = vstr_export_iovec_ptr_all(base, &vec, &num)))
     621                 :       {
     622               1 :         *err = VSTR_TYPE_SC_WRITE_FD_ERR_MEM;
     623               1 :         errno = ENOMEM;
     624               1 :         return (FALSE);
     625                 :       }
     626                 :     }
     627                 :     else
     628                 :     { /* could opt. anything with cache_avail ... but probably not worth it */
     629              25 :       vec = cpy_vec;
     630              25 :       clen = vstr_export_iovec_cpy_ptr(base, pos, len, vec, sz, &num);
     631                 :     }
     632                 : 
     633           96193 :     if (num > UIO_MAXIOV)
     634                 :     {
     635              28 :       unsigned int scan = num;
     636                 : 
     637             404 :       while (scan-- > UIO_MAXIOV)
     638             376 :         clen -= vec[scan].iov_len;
     639              28 :       num = UIO_MAXIOV;
     640                 :     }
     641                 : 
     642                 :     /* Linux just gives EINVAL on size > SSIZE_MAX */
     643           96193 :     if (clen > SSIZE_MAX)
     644                 :     {
     645               4 :       unsigned int scan = num;
     646                 : 
     647               7 :       ASSERT(VSTR_MAX_NODE_ALL <= SSIZE_MAX);
     648                 :       
     649               8 :       while (clen > SSIZE_MAX)
     650                 :       {
     651               4 :         ASSERT(scan >= 1);
     652               4 :         clen -= vec[--scan].iov_len;
     653                 :       }
     654                 :       
     655               4 :       num = scan;
     656                 :     }
     657                 :     
     658           96193 :     do
     659                 :     {
     660           96193 :       bytes = writev(fd, vec, num);
     661           96193 :     } while ((bytes == -1) && (errno == EINTR));
     662                 : 
     663           96193 :     if (bytes == -1)
     664                 :     {
     665           15564 :       *err = VSTR_TYPE_SC_WRITE_FD_ERR_WRITE_ERRNO;
     666           15564 :       return (FALSE);
     667                 :     }
     668                 : 
     669           80629 :     ASSERT((size_t)bytes <= len);
     670                 : 
     671           80629 :     vstr_del(base, pos, bytes);
     672                 :     
     673           80629 :     ASSERT((size_t)bytes <= clen);
     674           80629 :     if (clen != (size_t)bytes)
     675             555 :       break;
     676                 :     
     677           80074 :     len -= bytes;
     678                 :   }
     679                 : 
     680           80584 :   return (TRUE);
     681                 : 
     682                 :  inval_args:
     683           25252 :   *err = VSTR_TYPE_SC_WRITE_FD_ERR_WRITE_ERRNO;
     684           25252 :   errno = EINVAL;
     685           25252 :   return (FALSE);
     686                 : }
     687                 : 
     688                 : int vstr_sc_write_file(Vstr_base *base, size_t pos, size_t len,
     689                 :                        const char *filename, int open_flags,
     690                 :                        VSTR_AUTOCONF_mode_t mode,
     691                 :                        VSTR_AUTOCONF_off64_t off, unsigned int *err)
     692              53 : {
     693              53 :   int fd = -1;
     694              53 :   unsigned int dummy_err;
     695              53 :   int ret = 0;
     696              53 :   int saved_errno = 0;
     697                 : 
     698              53 :   if (!err)
     699              36 :     err = &dummy_err;
     700              53 :   *err = 0;
     701                 :   
     702              53 :   ASSERT_GOTO(base && pos && (((pos <= base->len) &&
     703                 :                                (vstr_sc_poslast(pos, len) <= base->len)) ||
     704                 :                               !len), inval_args);
     705                 :   
     706              53 :   if (!len)
     707               4 :     return (TRUE);
     708                 : 
     709              49 :   if (!open_flags) /* O_RDONLY isn't valid, for obvious reasons */
     710               5 :     open_flags = (O_WRONLY | O_CREAT | O_EXCL | O_NONBLOCK);
     711                 : 
     712              49 :   if ((fd = VSTR__POSIX_OPEN3(filename, open_flags, mode)) == -1)
     713                 :   {
     714               4 :     *err = VSTR_TYPE_SC_WRITE_FILE_ERR_OPEN_ERRNO;
     715               4 :     return (FALSE);
     716                 :   }
     717                 : 
     718              45 :   if (off && (lseek64(fd, off, SEEK_SET) == -1))
     719               4 :     *err = VSTR_TYPE_SC_WRITE_FILE_ERR_SEEK_ERRNO;
     720                 : 
     721              86 :   while (!*err && len)
     722                 :   {
     723              41 :     size_t tmp = base->len;
     724                 :     
     725              41 :     ret = vstr_sc_write_fd(base, pos, len, fd, err);
     726              41 :     len -= tmp - base->len;
     727                 :   }
     728                 : 
     729              45 :   if (*err)
     730               9 :     saved_errno = errno;
     731                 : 
     732              45 :   if ((VSTR__POSIX_CLOSE(fd) == -1) && !*err)
     733                 :   {
     734               1 :     *err = VSTR_TYPE_SC_WRITE_FILE_ERR_CLOSE_ERRNO;
     735               1 :     return (FALSE);
     736                 :   }
     737                 :   
     738              44 :   if (*err)
     739               9 :     errno = saved_errno;
     740                 : 
     741              44 :   return (ret);
     742                 :   
     743                 :  inval_args:
     744              14 :   *err = VSTR_TYPE_SC_WRITE_FD_ERR_WRITE_ERRNO;
     745              14 :   errno = EINVAL;
     746              14 :   return (FALSE);
     747                 : }
     748                 : 
     749                 : static int vstr__sc_fmt_add_cb_ipv4_ptr(Vstr_base *base, size_t pos,
     750                 :                                         Vstr_fmt_spec *spec)
     751             129 : {
     752             129 :   struct in_addr *ipv4 = VSTR_FMT_CB_ARG_PTR(spec, 0);
     753             129 :   size_t obj_len = 0;
     754             129 :   char buf[1024];
     755             129 :   const char *ptr = NULL;
     756                 : 
     757             129 :   assert(ipv4);
     758             129 :   assert(sizeof(buf) >= INET_ADDRSTRLEN);
     759                 : 
     760             129 :   ptr = inet_ntop(AF_INET, ipv4, buf, sizeof(buf));
     761             129 :   if (!ptr) ptr = "0.0.0.0";
     762                 : 
     763             129 :   obj_len = strlen(ptr);
     764                 : 
     765             129 :   if (!vstr_sc_fmt_cb_beg(base, &pos, spec, &obj_len,
     766                 :                           VSTR_FLAG_SC_FMT_CB_BEG_OBJ_STR))
     767              29 :     return (FALSE);
     768                 : 
     769             100 :   if (!vstr_add_buf(base, pos, ptr, obj_len))
     770               6 :     return (FALSE);
     771                 : 
     772              94 :   if (!vstr_sc_fmt_cb_end(base, pos, spec, obj_len))
     773              30 :     return (FALSE);
     774                 : 
     775              64 :   return (TRUE);
     776                 : }
     777                 : 
     778                 : static int vstr__sc_fmt_add_cb_ipv6_ptr(Vstr_base *base, size_t pos,
     779                 :                                         Vstr_fmt_spec *spec)
     780             129 : {
     781             129 :   struct in6_addr *ipv6 = VSTR_FMT_CB_ARG_PTR(spec, 0);
     782             129 :   size_t obj_len = 0;
     783             129 :   char buf[1024];
     784             129 :   const char *ptr = NULL;
     785                 : 
     786             129 :   assert(ipv6);
     787             129 :   assert(sizeof(buf) >= INET6_ADDRSTRLEN);
     788                 : 
     789             129 :   ptr = inet_ntop(AF_INET6, ipv6, buf, sizeof(buf));
     790             129 :   if (!ptr) ptr = "::";
     791                 : 
     792             129 :   obj_len = strlen(ptr);
     793                 : 
     794             129 :   if (!vstr_sc_fmt_cb_beg(base, &pos, spec, &obj_len,
     795                 :                           VSTR_FLAG_SC_FMT_CB_BEG_OBJ_STR))
     796              22 :     return (FALSE);
     797                 : 
     798             107 :   if (!vstr_add_buf(base, pos, ptr, obj_len))
     799              13 :     return (FALSE);
     800                 : 
     801              94 :   if (!vstr_sc_fmt_cb_end(base, pos, spec, obj_len))
     802              30 :     return (FALSE);
     803                 : 
     804              64 :   return (TRUE);
     805                 : }
     806                 : 
     807                 : int vstr_sc_fmt_add_ipv4_ptr(Vstr_conf *conf, const char *name)
     808            4169 : {
     809            4169 :   return (vstr_fmt_add(conf, name, vstr__sc_fmt_add_cb_ipv4_ptr,
     810                 :                        VSTR_TYPE_FMT_PTR_VOID,
     811                 :                        VSTR_TYPE_FMT_END));
     812                 : }
     813                 : 
     814                 : int vstr_sc_fmt_add_ipv6_ptr(Vstr_conf *conf, const char *name)
     815            4071 : {
     816            4071 :   return (vstr_fmt_add(conf, name, vstr__sc_fmt_add_cb_ipv6_ptr,
     817                 :                        VSTR_TYPE_FMT_PTR_VOID,
     818                 :                        VSTR_TYPE_FMT_END));
     819                 : }
     820                 : 
     821                 : #define VSTR__SC_FMT_ADD(x, n, nchk)                                    \
     822                 :     if (ret &&                                                          \
     823                 :         !VSTR_SC_FMT_ADD(conf, vstr_sc_fmt_add_ ## x, "{" n, nchk, "}")) \
     824                 :       ret = FALSE
     825                 : 
     826                 : int vstr__sc_fmt_add_posix(Vstr_conf *conf)
     827             601 : {
     828             601 :   int ret = TRUE;
     829                 :   
     830             601 :   VSTR__SC_FMT_ADD(ipv4_ptr, "ipv4.p", "p");
     831             601 :   VSTR__SC_FMT_ADD(ipv6_ptr, "ipv6.p", "p");
     832                 : 
     833             601 :   return (ret);
     834                 : }

Generated by: LTP GCOV extension version 1.1