skalibs

Mirror/fork of https://skarnet.org/software/skalibs/
git clone https://ccx.te2000.cz/git/skalibs
Log | Files | Refs | README | LICENSE

envdir_noclamp.c (2532B)


      1 /* ISC license. */
      2 
      3 #include <unistd.h>
      4 #include <string.h>
      5 #include <errno.h>
      6 
      7 #include <skalibs/bytestr.h>
      8 #include <skalibs/buffer.h>
      9 #include <skalibs/env.h>
     10 #include <skalibs/direntry.h>
     11 #include <skalibs/stralloc.h>
     12 #include <skalibs/djbunix.h>
     13 #include <skalibs/skamisc.h>
     14 #include "envdir-internal.h"
     15 
     16 #define N 4096
     17 
     18 int envdir_internal_noclamp (char const *path, stralloc *modifs, unsigned int options, char nullis)
     19 {
     20   unsigned int n = 0 ;
     21   size_t pathlen = strlen(path) ;
     22   size_t modifbase = modifs->len ;
     23   int wasnull = !modifs->s ;
     24   int fd ;
     25   DIR *dir = opendir(path) ;
     26   if (!dir) return -1 ;
     27   for (;;)
     28   {
     29     direntry *d ;
     30     size_t len, pos ;
     31     errno = 0 ;
     32     d = readdir(dir) ;
     33     if (!d) break ;
     34     if (d->d_name[0] == '.') continue ;
     35     len = strlen(d->d_name) ;
     36     if (str_chr(d->d_name, '=') < len) continue ;
     37     {
     38       char tmp[pathlen + len + 2] ;
     39       memcpy(tmp, path, pathlen) ;
     40       tmp[pathlen] = '/' ;
     41       memcpy(tmp + pathlen + 1, d->d_name, len + 1) ;
     42       fd = openc_readb(tmp) ;
     43     }
     44     if (fd < 0)
     45     {
     46       if (errno == ENOENT) errno = EIDRM ;
     47       goto err ;
     48     }
     49     if (!stralloc_catb(modifs, d->d_name, len) || !stralloc_catb(modifs, "=", 1)) goto errfd ;
     50     pos = modifs->len ;
     51     if (options & SKALIBS_ENVDIR_VERBATIM)
     52     {
     53       if (!slurp(modifs, fd)) goto errfd ;
     54       if (modifs->len == pos) modifs->len = pos - 1 ;
     55       if (!(options & SKALIBS_ENVDIR_NOCHOMP) && (modifs->s[modifs->len - 1] == '\n')) modifs->len-- ;
     56     }
     57     else
     58     {
     59       int r ;
     60       char buf[N] ;
     61       buffer b = BUFFER_INIT(&buffer_read, fd, buf, N) ;
     62       r = skagetln(&b, modifs, '\n') ;
     63       if (r == -1)
     64       {
     65         if (errno != EPIPE) goto errfd ;
     66         if (!(options & SKALIBS_ENVDIR_NOCHOMP)) modifs->len = pos ;
     67         modifs->len++ ;
     68       }
     69       if (!r) modifs->len = pos - 1 ;
     70       else
     71       {
     72         modifs->len-- ;
     73         if (!(options & SKALIBS_ENVDIR_NOCHOMP))
     74         {
     75           while (modifs->len-- > pos)
     76           {
     77             char c = modifs->s[modifs->len] ;
     78             if ((c != ' ') && (c != '\t') && (c != '\r')) break ;
     79           }
     80           modifs->len++ ;
     81         }
     82       }
     83     }
     84     fd_close(fd) ;
     85     for (; pos < modifs->len ; pos++) if (!modifs->s[pos]) modifs->s[pos] = nullis ;
     86     if (!stralloc_0(modifs)) goto err ;
     87     n++ ;
     88   }
     89   if (errno) goto err ;
     90   dir_close(dir) ;
     91   return n ;
     92 
     93  errfd:
     94   fd_close(fd) ;
     95  err:
     96   dir_close(dir) ;
     97   if (wasnull) stralloc_free(modifs) ; else modifs->len = modifbase ;
     98   return -1 ;
     99 }