diff options
author | Laurent Bercot <ska-skaware@skarnet.org> | 2018-11-14 17:08:47 +0000 |
---|---|---|
committer | Laurent Bercot <ska-skaware@skarnet.org> | 2018-11-14 17:08:47 +0000 |
commit | 661329653329949929b043f5fc45821aa314face (patch) | |
tree | b114775c7d8e0cf1d53f8b1fbc657d492f4bd444 /src | |
parent | 9575ac2abacc87c4167d419e5a1fa1d650dee11d (diff) | |
download | skalibs-661329653329949929b043f5fc45821aa314face.tar.xz |
Add env_dump()
Diffstat (limited to 'src')
-rw-r--r-- | src/include/skalibs/env.h | 1 | ||||
-rw-r--r-- | src/libstddjb/env_dump.c | 51 |
2 files changed, 52 insertions, 0 deletions
diff --git a/src/include/skalibs/env.h b/src/include/skalibs/env.h index c2569b4..bc8177b 100644 --- a/src/include/skalibs/env.h +++ b/src/include/skalibs/env.h @@ -23,5 +23,6 @@ extern int envdir_internal (char const *, stralloc *, unsigned int, char) ; #define envdir_chomp(path, sa) envdir_internal(path, (sa), SKALIBS_ENVDIR_NOCHOMP, '\n') #define envdir_verbatim_chomp(path, sa) envdir_internal(path, (sa), SKALIBS_ENVDIR_VERBATIM, '\n') #define envdir_verbatim(path, sa) envdir_internal(path, (sa), SKALIBS_ENVDIR_VERBATIM|SKALIBS_ENVDIR_NOCHOMP, '\n') +extern int env_dump (char const *, mode_t, char const *const *) ; #endif diff --git a/src/libstddjb/env_dump.c b/src/libstddjb/env_dump.c new file mode 100644 index 0000000..e15c6be --- /dev/null +++ b/src/libstddjb/env_dump.c @@ -0,0 +1,51 @@ +/* ISC license. */ + +#include <sys/stat.h> +#include <string.h> +#include <errno.h> +#include <stdlib.h> +#include <stdio.h> + +#include <skalibs/bytestr.h> +#include <skalibs/env.h> +#include <skalibs/djbunix.h> + + /* XXX: breaks layering, but really openat() should be supported everywhere */ +#include <skalibs/unix-transactional.h> + +#define SUFFIX ":envdump:XXXXXX" + +int env_dump (char const *dir, mode_t mode, char const *const *envp) +{ + int fd ; + size_t dirlen = strlen(dir) ; + char tmpdir[dirlen + sizeof(SUFFIX)] ; + memcpy(tmpdir, dir, dirlen) ; + memcpy(tmpdir + dirlen, SUFFIX, sizeof(SUFFIX)) ; + if (!mkdtemp(tmpdir)) return 0 ; + fd = open_read(tmpdir) ; + if (fd == -1) goto err ; + for (; *envp ; envp++) + { + size_t len = str_chr(*envp, '=') ; + size_t vallen = strlen(*envp + len + 1) ; + char fn[len + 1] ; + memcpy(fn, *envp, len + 1) ; + len = openwritenclose_at(fd, fn, *envp + len + 1, vallen) ; + if (len < vallen) goto cerr ; + } + fd_close(fd) ; + if (chmod(tmpdir, mode) == -1) goto err ; + if (rename(tmpdir, dir) == -1) goto err ; + return 1 ; + + cerr: + fd_close(fd) ; + err: + { + int e = errno ; + rm_rf(tmpdir) ; + errno = e ; + } + return 0 ; +} |