diff options
| author | Dennis Camera <skonfig@dtnr.ch> | 2022-08-21 10:34:13 +0200 |
|---|---|---|
| committer | Dennis Camera <skonfig@dtnr.ch> | 2022-08-21 10:34:13 +0200 |
| commit | 4c1347d2285aa7b6af772731adc417c816ac6112 (patch) | |
| tree | ed4b05505cd73bd1bb9ccd916d0b73981b6d7542 /src/util | |
| parent | 6ed18ee1677007b9870fad63b8ef11e7d9afe0d9 (diff) | |
| download | skonfig-c-4c1347d2285aa7b6af772731adc417c816ac6112.tar.gz skonfig-c-4c1347d2285aa7b6af772731adc417c816ac6112.zip | |
[src/run.c] Move creatfile, mktempdir, rmtree to util/fs.c
Diffstat (limited to 'src/util')
| -rw-r--r-- | src/util/fs.c | 101 | ||||
| -rw-r--r-- | src/util/fs.h | 28 |
2 files changed, 129 insertions, 0 deletions
diff --git a/src/util/fs.c b/src/util/fs.c index 6f787c0..72c87f3 100644 --- a/src/util/fs.c +++ b/src/util/fs.c @@ -1,5 +1,13 @@ #include "fs.h" +#include "../log.h" + +#include <stdio.h> +#include <errno.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <ftw.h> + bool is_dir(const char *restrict pathname) { #ifdef STAT_MACROS_BROKEN #error stat() macros are broken on this system. Cannot compile is_dir(). @@ -21,3 +29,96 @@ const char *myhome() { return (const char *)&home; } + +int creatfile(const char *path, mode_t mode) { + int fd = creat(path, mode); + if (0 < fd) { + (void)close(fd); + fd = 0; + } + return fd; +} + + +#if HAVE_MKDTEMP && !HAVE_DECL_MKDTEMP +extern char *mkdtemp(char *); +#endif +#if HAVE_MKTEMP && !HAVE_DECL_MKTEMP +extern char *mktemp(char *); +#endif +#if HAVE_TEMPNAM && !HAVE_DECL_TEMPNAM +extern char *tempnam(const char *, const char *); +#endif + +#ifndef P_tmpdir +/* fallback */ +#define P_tmpdir "/tmp" +#endif + +char *mktempdir(char *dest) { + static const char *pfx = "tmp"; + + for (size_t try = 1; try < TMP_MAX; ++try) { +#if HAVE_MKDTEMP || HAVE_MKTEMP + if (PATH_MAX < snprintf( + dest, PATH_MAX+1, "%s/%sXXXXXX", + (getenv("TMPDIR") ? getenv("TMPDIR") : P_tmpdir), + pfx)) { + goto fail; + } + +#if HAVE_MKDTEMP + if (NULL != mkdtemp(dest)) { + return dest; + } +#elif HAVE_MKTEMP + if (0 < strlen(mktemp(dest))) { + if (0 > mkdir(dest, S_IRWXU)) { + continue; + } + return dest; + } else if (errno = EINVAL) { + goto fail; + } +#endif /* HAVE_MKTEMP */ + +#elif HAVE_TEMPNAM + char *name = tempnam(NULL, pfx); + if (NULL == name) { + continue; + } + + dest[PATH_MAX] = '\0'; + (void)strncpy(dest, name, PATH_MAX); + free(name); + + if (dest[PATH_MAX]) { + continue; + } + + if (0 == mkdir(dest, S_IRWXU)) { + return dest; + } +#else +#error no implementation to create temporary directories +#endif + } + + goto fail; /* hack around error: label defined but not used */ + fail: + sk_error("mktempdir failed: %s", dest); + return NULL; +} + +static int __rmtree_fn( + const char *fpath, const struct stat *sb, int tflag, struct FTW *ftwbuf) { + sk_trace("removing %s", fpath); + if (-1 == remove(fpath)) { + sk_error("failed to remove %s: %s", fpath, strerror(errno)); + } + + return 0 /* FTW_CONTINUE */; +} +int rmtree(const char *dir) { + return nftw(dir, __rmtree_fn, 16, FTW_DEPTH | FTW_PHYS); +} diff --git a/src/util/fs.h b/src/util/fs.h index 7be8527..ad0a449 100644 --- a/src/util/fs.h +++ b/src/util/fs.h @@ -44,4 +44,32 @@ bool is_dir(const char *restrict pathname); */ const char *myhome(); +/** + * creatfile: + * create a file on the file system. + * + * @param path: pathname for the file to create + * @param mode: desired file mode (cf. creat(3p)) + * @return 0 on success, -1 otherwise (errno set) + */ +int creatfile(const char *path, mode_t mode); + +/** + * mktempdir: + * creates a temporary directory in a suitable location. + * + * @param dest: must be a pointer to a buffer of a least PATH_MAX+1 length. + * @return dest if a directory was created successfully, NULL otherwise. + */ +char *mktempdir(char *dest); + +/** + * rmtree: + * delete a directory on the file system and all its descendants. + * + * @param dir: the path to the directory to delete. + * @return 0 on success, -1 otherwise. + */ +int rmtree(const char *dir); + #endif |
