skalibs

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

env_dump.c (1252B)


      1 /* ISC license. */
      2 
      3 #include <skalibs/nonposix.h>
      4 #include <unistd.h>
      5 #include <sys/stat.h>
      6 #include <string.h>
      7 #include <errno.h>
      8 #include <stdlib.h>
      9 #include <stdio.h>
     10 
     11 #include <skalibs/bytestr.h>
     12 #include <skalibs/env.h>
     13 #include <skalibs/djbunix.h>
     14 
     15  /* XXX: breaks layering, but really openat() should be supported everywhere */
     16 #include <skalibs/unix-transactional.h>
     17 
     18 #define SUFFIX ":envdump:XXXXXX"
     19 
     20 int env_dump (char const *dir, mode_t mode, char const *const *envp)
     21 {
     22   int fd ;
     23   size_t dirlen = strlen(dir) ;
     24   char tmpdir[dirlen + sizeof(SUFFIX)] ;
     25   memcpy(tmpdir, dir, dirlen) ;
     26   memcpy(tmpdir + dirlen, SUFFIX, sizeof(SUFFIX)) ;
     27   if (!mkdtemp(tmpdir)) return 0 ;
     28   fd = open_read(tmpdir) ;
     29   if (fd == -1) goto err ;
     30   for (; *envp ; envp++)
     31   {
     32     size_t len = str_chr(*envp, '=') ;
     33     size_t vallen = strlen(*envp + len + 1) ;
     34     char fn[len + 1] ;
     35     memcpy(fn, *envp, len) ;
     36     fn[len] = 0 ;
     37     len = openwritenclose_at(fd, fn, *envp + len + 1, vallen) ;
     38     if (len < vallen) goto cerr ;
     39   }
     40   fd_close(fd) ;
     41   if (chmod(tmpdir, mode) == -1) goto err ;
     42   if (rename(tmpdir, dir) == -1) goto err ;
     43   return 1 ;
     44 
     45  cerr:
     46   fd_close(fd) ;
     47  err:
     48   {
     49     int e = errno ;
     50     rm_rf(tmpdir) ;
     51     errno = e ;
     52   }
     53   return 0 ;
     54 }