s6

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

s6-accessrules-cdb-from-fs.c (4646B)


      1 /* ISC license. */
      2 
      3 #include <stdint.h>
      4 #include <unistd.h>
      5 #include <errno.h>
      6 #include <stdlib.h>
      7 #include <stdio.h>
      8 
      9 #include <skalibs/posixplz.h>
     10 #include <skalibs/types.h>
     11 #include <skalibs/cdbmake.h>
     12 #include <skalibs/strerr.h>
     13 #include <skalibs/stralloc.h>
     14 #include <skalibs/env.h>
     15 #include <skalibs/direntry.h>
     16 #include <skalibs/djbunix.h>
     17 #include <skalibs/skamisc.h>
     18 
     19 #define USAGE "s6-accessrules-cdb-from-fs cdbfile dir"
     20 #define SUFFIX ":s6-accessrules-cdb-from-fs:XXXXXX"
     21 
     22 static stralloc tmp = STRALLOC_ZERO ;
     23 
     24 static void cleanup (void)
     25 {
     26   unlink_void(tmp.s) ;
     27 }
     28 
     29 static void dienomem (void)
     30 {
     31   cleanup() ;
     32   strerr_diefu1sys(111, "stralloc_catb") ;
     33 }
     34 
     35 static void doit (cdbmaker *c, stralloc *sa, size_t start)
     36 {
     37   size_t tmpbase = tmp.len ;
     38   unsigned int k = sa->len ;
     39   if (!stralloc_readyplus(sa, 10)) dienomem() ;
     40   stralloc_catb(sa, "/allow", 7) ;
     41   tmp.s[tmpbase] = 0 ;
     42   if (access(sa->s, F_OK) < 0)
     43   {
     44     if ((errno != ENOENT) && (errno != EACCES))
     45     {
     46       cleanup() ;
     47       strerr_diefu2sys(111, "access ", sa->s) ;
     48     }
     49     sa->len = k+1 ;
     50     stralloc_catb(sa, "deny", 5) ;
     51     if (access(sa->s, F_OK) < 0)
     52       if ((errno != ENOENT) && (errno != EACCES))
     53       {
     54         cleanup() ;
     55         strerr_diefu2sys(111, "access ", sa->s) ;
     56       }
     57       else return ;
     58     else if (!cdbmake_add(c, sa->s + start, k - start, "D", 1))
     59     {
     60       cleanup() ;
     61       strerr_diefu1sys(111, "cdbmake_add") ;
     62     }
     63   }
     64   else
     65   {
     66     uint16_t envlen = 0 ;
     67     uint16_t execlen = 0 ;
     68     ssize_t r ;
     69     tmp.s[tmpbase] = 'A' ;
     70     sa->len = k+1 ;
     71     stralloc_catb(sa, "env", 4) ;
     72     tmp.len = tmpbase + 3 ;
     73     if ((envdir(sa->s, &tmp) < 0) && (errno != ENOENT))
     74     {
     75       cleanup() ;
     76       strerr_diefu2sys(111, "envdir ", sa->s) ;
     77     }
     78     if (tmp.len > tmpbase + 4103)
     79     {
     80       cleanup() ;
     81       strerr_dief2sys(100, sa->s, " too big") ;
     82     }
     83     envlen = tmp.len - tmpbase - 3 ;
     84     tmp.len = tmpbase ;
     85     uint16_pack_big(tmp.s + tmpbase + 1, envlen) ;
     86     sa->len = k+1 ;
     87     stralloc_catb(sa, "exec", 5) ;
     88     r = openreadnclose(sa->s, tmp.s + tmpbase + 5 + envlen, 4096) ;
     89     if ((r == -1) && (errno != ENOENT))
     90     {
     91       cleanup() ;
     92       strerr_diefu2sys(111, "openreadnclose ", sa->s) ;
     93     }
     94     if (r > 0) execlen = r ;
     95     if (execlen == 4096) strerr_warnw2x("possibly truncated file ", sa->s) ;
     96     uint16_pack_big(tmp.s + tmpbase + 3 + envlen, execlen) ;
     97     if (!cdbmake_add(c, sa->s + start, k - start, tmp.s + tmpbase, 5 + envlen + execlen))
     98     {
     99       cleanup() ;
    100       strerr_diefu1sys(111, "cdbmake_add") ;
    101     }
    102   }
    103 }
    104 
    105 int main (int argc, char const *const *argv)
    106 {
    107   stralloc sa = STRALLOC_ZERO ;
    108   cdbmaker c = CDBMAKER_ZERO ;
    109   DIR *dir ;
    110   size_t start ;
    111   int fd ;
    112   PROG = "s6-accessrules-cdb-from-fs" ;
    113   if (argc < 3) strerr_dieusage(100, USAGE) ;
    114   if (!stralloc_cats(&tmp, argv[1])) return 0 ;
    115   if (!stralloc_readyplus(&tmp, 8210))
    116     strerr_diefu1sys(111, "stralloc_catb") ;
    117   stralloc_catb(&tmp, SUFFIX, sizeof(SUFFIX)) ;
    118   fd = mkstemp(tmp.s) ;
    119   if (fd < 0) strerr_diefu2sys(111, "mkstemp ", tmp.s) ;
    120   if (!cdbmake_start(&c, fd))
    121   {
    122     cleanup() ;
    123     strerr_diefu1sys(111, "cdbmake_start") ;
    124   }
    125   dir = opendir(argv[2]) ;
    126   if (!dir)
    127   {
    128     cleanup() ;
    129     strerr_diefu2sys(111, "opendir ", argv[2]) ;
    130   }
    131   if (!stralloc_cats(&sa, argv[2]) || !stralloc_catb(&sa, "/", 1)) dienomem() ;
    132   start = sa.len ;
    133 
    134   for (;;)
    135   {
    136     DIR *subdir ;
    137     direntry *d ;
    138     size_t base ;
    139     errno = 0 ;
    140     d = readdir(dir) ;
    141     if (!d) break ;
    142     if (d->d_name[0] == '.') continue ;
    143     sa.len = start ;
    144     if (!stralloc_cats(&sa, d->d_name) || !stralloc_0(&sa)) dienomem() ;
    145     base = sa.len ;
    146     subdir = opendir(sa.s) ;
    147     if (!subdir)
    148     {
    149       cleanup() ;
    150       strerr_diefu2sys(111, "opendir ", sa.s) ;
    151     }
    152     sa.s[base-1] = '/' ;
    153     for (;;)
    154     {
    155       errno = 0 ;
    156       d = readdir(subdir) ;
    157       if (!d) break ;
    158       if (d->d_name[0] == '.') continue ;
    159       sa.len = base ;
    160       if (!stralloc_cats(&sa, d->d_name)) dienomem() ;
    161       doit(&c, &sa, start) ;
    162     }
    163     if (errno)
    164     {
    165       sa.s[base-1] = 0 ;
    166       cleanup() ;
    167       strerr_diefu2sys(111, "readdir ", sa.s) ;
    168     }
    169     dir_close(subdir) ;
    170   }
    171   if (errno)
    172   {
    173     cleanup() ;
    174     strerr_diefu2sys(111, "readdir ", argv[2]) ;
    175   }
    176   dir_close(dir) ;
    177   if (!cdbmake_finish(&c))
    178   {
    179     cleanup() ;
    180     strerr_diefu1sys(111, "cdb_make_finish") ;
    181   }
    182   if (fd_sync(fd) < 0)
    183   {
    184     cleanup() ;
    185     strerr_diefu1sys(111, "fd_sync") ;
    186   }
    187   fd_close(fd) ;
    188   if (rename(tmp.s, argv[1]) < 0)
    189   {
    190     cleanup() ;
    191     strerr_diefu4sys(111, "rename ", tmp.s, " to ", argv[1]) ;
    192   }
    193   return 0 ;
    194 }