diff options
Diffstat (limited to 'src/libenvexec')
-rw-r--r-- | src/libenvexec/envdir-internal.h | 11 | ||||
-rw-r--r-- | src/libenvexec/envdir.c | 82 | ||||
-rw-r--r-- | src/libenvexec/envdir_clamp.c | 85 | ||||
-rw-r--r-- | src/libenvexec/envdir_noclamp.c | 103 |
4 files changed, 204 insertions, 77 deletions
diff --git a/src/libenvexec/envdir-internal.h b/src/libenvexec/envdir-internal.h new file mode 100644 index 0000000..7b86b1c --- /dev/null +++ b/src/libenvexec/envdir-internal.h @@ -0,0 +1,11 @@ +/* ISC license. */ + +#ifndef ENVDIR_INTERNAL_H +#define ENVDIR_INTERNAL_H + +#include <skalibs/stralloc.h> + +extern int envdir_internal_clamp (char const *, stralloc *, unsigned int, char) ; +extern int envdir_internal_noclamp (char const *, stralloc *, unsigned int, char) ; + +#endif diff --git a/src/libenvexec/envdir.c b/src/libenvexec/envdir.c index 6992654..be8867a 100644 --- a/src/libenvexec/envdir.c +++ b/src/libenvexec/envdir.c @@ -1,85 +1,13 @@ /* ISC license. */ -#include <unistd.h> -#include <string.h> #include <errno.h> -#include <skalibs/bytestr.h> -#include <skalibs/env.h> -#include <skalibs/direntry.h> -#include <skalibs/stralloc.h> -#include <skalibs/djbunix.h> -#define MAXVARSIZE 4095 +#include <skalibs/env.h> +#include "envdir-internal.h" int envdir_internal (char const *path, stralloc *modifs, unsigned int options, char nullis) { - char buf[MAXVARSIZE + 1] ; - unsigned int n = 0 ; - size_t pathlen = strlen(path) ; - size_t modifbase = modifs->len ; - int wasnull = !modifs->s ; - DIR *dir ; - if (!nullis) return (errno = EINVAL, -1) ; - dir = opendir(path) ; - if (!dir) return -1 ; - for (;;) - { - direntry *d ; - size_t len ; - ssize_t r ; - errno = 0 ; - d = readdir(dir) ; - if (!d) break ; - if (d->d_name[0] == '.') continue ; - len = strlen(d->d_name) ; - if (str_chr(d->d_name, '=') < len) continue ; - { - char tmp[pathlen + len + 2] ; - memcpy(tmp, path, pathlen) ; - tmp[pathlen] = '/' ; - memcpy(tmp + pathlen + 1, d->d_name, len + 1) ; - r = openreadnclose(tmp, buf, MAXVARSIZE) ; - } - if (r < 0) - { - if (errno == ENOENT) errno = EIDRM ; - goto err ; - } - else if (r > 0) - { - if (options & SKALIBS_ENVDIR_VERBATIM) - { - if (!(options & SKALIBS_ENVDIR_NOCHOMP) && (buf[r-1] == '\n')) r-- ; - } - else - { - r = byte_chr(buf, r, '\n') ; - if (!(options & SKALIBS_ENVDIR_NOCHOMP)) - { - while (r--) if ((buf[r] != ' ') && (buf[r] != '\t') && (buf[r] != '\r')) break ; - r++ ; - } - } - { - size_t i = 0 ; - for (; i < (size_t)r ; i++) if (!buf[i]) buf[i] = nullis ; - } - buf[r++] = 0 ; - if (!env_addmodif(modifs, d->d_name, buf)) goto err ; - } - else if (!env_addmodif(modifs, d->d_name, 0)) goto err ; - n++ ; - } - if (errno) goto err ; - dir_close(dir) ; - return n ; - - err: - { - int e = errno ; - dir_close(dir) ; - if (wasnull) stralloc_free(modifs) ; else modifs->len = modifbase ; - errno = e ; - return -1 ; - } + return nullis ? options & SKALIBS_ENVDIR_NOCLAMP ? + envdir_internal_noclamp(path, modifs, options & ~SKALIBS_ENVDIR_NOCLAMP, nullis) : + envdir_internal_clamp(path, modifs, options, nullis) : (errno = EINVAL, -1) ; } diff --git a/src/libenvexec/envdir_clamp.c b/src/libenvexec/envdir_clamp.c new file mode 100644 index 0000000..b63ed97 --- /dev/null +++ b/src/libenvexec/envdir_clamp.c @@ -0,0 +1,85 @@ +/* ISC license. */ + +#include <unistd.h> +#include <string.h> +#include <errno.h> + +#include <skalibs/bytestr.h> +#include <skalibs/env.h> +#include <skalibs/direntry.h> +#include <skalibs/stralloc.h> +#include <skalibs/djbunix.h> +#include "envdir-internal.h" + +#define MAXVARSIZE 4095 + +int envdir_internal_clamp (char const *path, stralloc *modifs, unsigned int options, char nullis) +{ + char buf[MAXVARSIZE + 1] ; + unsigned int n = 0 ; + size_t pathlen = strlen(path) ; + size_t modifbase = modifs->len ; + int wasnull = !modifs->s ; + DIR *dir = opendir(path) ; + if (!dir) return -1 ; + for (;;) + { + direntry *d ; + size_t len ; + ssize_t r ; + errno = 0 ; + d = readdir(dir) ; + if (!d) break ; + if (d->d_name[0] == '.') continue ; + len = strlen(d->d_name) ; + if (str_chr(d->d_name, '=') < len) continue ; + { + char tmp[pathlen + len + 2] ; + memcpy(tmp, path, pathlen) ; + tmp[pathlen] = '/' ; + memcpy(tmp + pathlen + 1, d->d_name, len + 1) ; + r = openreadnclose(tmp, buf, MAXVARSIZE) ; + } + if (r < 0) + { + if (errno == ENOENT) errno = EIDRM ; + goto err ; + } + else if (r > 0) + { + if (options & SKALIBS_ENVDIR_VERBATIM) + { + if (!(options & SKALIBS_ENVDIR_NOCHOMP) && (buf[r-1] == '\n')) r-- ; + } + else + { + r = byte_chr(buf, r, '\n') ; + if (!(options & SKALIBS_ENVDIR_NOCHOMP)) + { + while (r--) if ((buf[r] != ' ') && (buf[r] != '\t') && (buf[r] != '\r')) break ; + r++ ; + } + } + { + size_t i = 0 ; + for (; i < (size_t)r ; i++) if (!buf[i]) buf[i] = nullis ; + } + buf[r++] = 0 ; + if (!env_addmodif(modifs, d->d_name, buf)) goto err ; + } + else if (!env_addmodif(modifs, d->d_name, 0)) goto err ; + n++ ; + } + if (errno) goto err ; + dir_close(dir) ; + return n ; + + err: + { + int e = errno ; + dir_close(dir) ; + if (wasnull) stralloc_free(modifs) ; else modifs->len = modifbase ; + errno = e ; + return -1 ; + } +} diff --git a/src/libenvexec/envdir_noclamp.c b/src/libenvexec/envdir_noclamp.c new file mode 100644 index 0000000..b87291a --- /dev/null +++ b/src/libenvexec/envdir_noclamp.c @@ -0,0 +1,103 @@ +/* ISC license. */ + +#include <unistd.h> +#include <string.h> +#include <errno.h> + +#include <skalibs/bytestr.h> +#include <skalibs/buffer.h> +#include <skalibs/env.h> +#include <skalibs/direntry.h> +#include <skalibs/stralloc.h> +#include <skalibs/djbunix.h> +#include <skalibs/skamisc.h> +#include "envdir-internal.h" + +#define N 4096 + +int envdir_internal_noclamp (char const *path, stralloc *modifs, unsigned int options, char nullis) +{ + unsigned int n = 0 ; + size_t pathlen = strlen(path) ; + size_t modifbase = modifs->len ; + int wasnull = !modifs->s ; + int fd ; + DIR *dir = opendir(path) ; + if (!dir) return -1 ; + for (;;) + { + direntry *d ; + size_t len, pos ; + errno = 0 ; + d = readdir(dir) ; + if (!d) break ; + if (d->d_name[0] == '.') continue ; + len = strlen(d->d_name) ; + if (str_chr(d->d_name, '=') < len) continue ; + { + char tmp[pathlen + len + 2] ; + memcpy(tmp, path, pathlen) ; + tmp[pathlen] = '/' ; + memcpy(tmp + pathlen + 1, d->d_name, len + 1) ; + fd = openc_readb(tmp) ; + } + if (fd < 0) + { + if (errno == ENOENT) errno = EIDRM ; + goto err ; + } + if (!stralloc_catb(modifs, d->d_name, len) || !stralloc_catb(modifs, "=", 1)) goto errfd ; + pos = modifs->len ; + if (options & SKALIBS_ENVDIR_VERBATIM) + { + if (!slurp(modifs, fd)) goto errfd ; + if (modifs->len == pos) modifs->len = pos - 1 ; + if (!(options & SKALIBS_ENVDIR_NOCHOMP) && (modifs->s[modifs->len - 1] == '\n')) modifs->len-- ; + } + else + { + int r ; + char buf[N] ; + buffer b = BUFFER_INIT(&buffer_read, fd, buf, N) ; + r = skagetln(&b, modifs, '\n') ; + if (r == -1) + { + if (errno != EPIPE) goto errfd ; + if (!(options & SKALIBS_ENVDIR_NOCHOMP)) modifs->len = pos ; + if (!stralloc_catb(modifs, "\n", 1)) goto errfd ; + } + if (!r) modifs->len = pos - 1 ; + else + { + size_t i = pos ; + if (!(options & SKALIBS_ENVDIR_NOCHOMP)) + { + while (modifs->len-- > pos) + { + char c = modifs->s[modifs->len] ; + if ((c != ' ') && (c != '\t') && (c != '\r')) break ; + } + modifs->len++ ; + for (; i < modifs->len ; i++) if (!modifs->s[i]) modifs->s[i] = nullis ; + } + } + } + fd_close(fd) ; + if (!stralloc_0(modifs)) goto err ; + n++ ; + } + if (errno) goto err ; + dir_close(dir) ; + return n ; + + errfd: + fd_close(fd) ; + err: + { + int e = errno ; + dir_close(dir) ; + if (wasnull) stralloc_free(modifs) ; else modifs->len = modifbase ; + errno = e ; + return -1 ; + } +} |