skalibs

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

envdir_clamp.c (1966B)


      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/env.h>
      9 #include <skalibs/direntry.h>
     10 #include <skalibs/stralloc.h>
     11 #include <skalibs/djbunix.h>
     12 #include "envdir-internal.h"
     13 
     14 #define MAXVARSIZE 4095
     15 
     16 int envdir_internal_clamp (char const *path, stralloc *modifs, unsigned int options, char nullis)
     17 {
     18   char buf[MAXVARSIZE + 1] ;
     19   unsigned int n = 0 ;
     20   size_t pathlen = strlen(path) ;
     21   size_t modifbase = modifs->len ;
     22   int wasnull = !modifs->s ;
     23   DIR *dir = opendir(path) ;
     24   if (!dir) return -1 ;
     25   for (;;)
     26   {
     27     direntry *d ;
     28     size_t len ;
     29     ssize_t r ;
     30     errno = 0 ;
     31     d = readdir(dir) ;
     32     if (!d) break ;
     33     if (d->d_name[0] == '.') continue ;
     34     len = strlen(d->d_name) ;
     35     if (str_chr(d->d_name, '=') < len) continue ;
     36     {
     37       char tmp[pathlen + len + 2] ;
     38       memcpy(tmp, path, pathlen) ;
     39       tmp[pathlen] = '/' ;
     40       memcpy(tmp + pathlen + 1, d->d_name, len + 1) ;
     41       r = openreadnclose(tmp, buf, MAXVARSIZE) ;
     42     }
     43     if (r < 0)
     44     {
     45       if (errno == ENOENT) errno = EIDRM ;
     46       goto err ;
     47     }
     48     else if (r > 0)
     49     {
     50       if (options & SKALIBS_ENVDIR_VERBATIM)
     51       {
     52         if (!(options & SKALIBS_ENVDIR_NOCHOMP) && (buf[r-1] == '\n')) r-- ;
     53       }
     54       else
     55       {
     56         r = byte_chr(buf, r, '\n') ;
     57         if (!(options & SKALIBS_ENVDIR_NOCHOMP))
     58         {
     59           while (r--) if ((buf[r] != ' ') && (buf[r] != '\t') && (buf[r] != '\r')) break ;
     60           r++ ;
     61         }
     62       }
     63       {
     64         size_t i = 0 ;
     65         for (; i < (size_t)r ; i++) if (!buf[i]) buf[i] = nullis ;
     66       }
     67       buf[r++] = 0 ;
     68       if (!env_addmodif(modifs, d->d_name, buf)) goto err ;
     69     }
     70     else if (!env_addmodif(modifs, d->d_name, 0)) goto err ;
     71     n++ ;
     72   }
     73   if (errno) goto err ;
     74   dir_close(dir) ;
     75   return n ;
     76 
     77  err:
     78   dir_close(dir) ;
     79   if (wasnull) stralloc_free(modifs) ; else modifs->len = modifbase ;
     80   return -1 ;
     81 }