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 }