summaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
authorDennis Camera <skonfig@dtnr.ch>2022-08-21 10:34:13 +0200
committerDennis Camera <skonfig@dtnr.ch>2022-08-21 10:34:13 +0200
commit4c1347d2285aa7b6af772731adc417c816ac6112 (patch)
treeed4b05505cd73bd1bb9ccd916d0b73981b6d7542 /src/util
parent6ed18ee1677007b9870fad63b8ef11e7d9afe0d9 (diff)
downloadskonfig-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.c101
-rw-r--r--src/util/fs.h28
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