From 661329653329949929b043f5fc45821aa314face Mon Sep 17 00:00:00 2001 From: Laurent Bercot Date: Wed, 14 Nov 2018 17:08:47 +0000 Subject: Add env_dump() --- src/include/skalibs/env.h | 1 + src/libstddjb/env_dump.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 src/libstddjb/env_dump.c (limited to 'src') 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 +#include +#include +#include +#include + +#include +#include +#include + + /* XXX: breaks layering, but really openat() should be supported everywhere */ +#include + +#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 ; +} -- cgit v1.2.3