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 
env_dump(char const * dir,mode_t mode,char const * const * envp)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 }
55