summaryrefslogtreecommitdiff
path: root/lib/common
diff options
context:
space:
mode:
Diffstat (limited to 'lib/common')
-rw-r--r--lib/common/Makemodule.am1
-rw-r--r--lib/common/dirstack.c77
-rw-r--r--lib/common/mkdir_p.c45
3 files changed, 123 insertions, 0 deletions
diff --git a/lib/common/Makemodule.am b/lib/common/Makemodule.am
index 75f771d..db366af 100644
--- a/lib/common/Makemodule.am
+++ b/lib/common/Makemodule.am
@@ -5,5 +5,6 @@ libcommon_a_SOURCES += lib/common/compress.c lib/common/comp_opt.c
libcommon_a_SOURCES += lib/common/data_writer.c include/common.h
libcommon_a_SOURCES += lib/common/get_path.c lib/common/io_stdin.c
libcommon_a_SOURCES += lib/common/writer.c lib/common/perror.c
+libcommon_a_SOURCES += lib/common/dirstack.c lib/common/mkdir_p.c
noinst_LIBRARIES += libcommon.a
diff --git a/lib/common/dirstack.c b/lib/common/dirstack.c
new file mode 100644
index 0000000..8f73898
--- /dev/null
+++ b/lib/common/dirstack.c
@@ -0,0 +1,77 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later */
+/*
+ * dirstack.c
+ *
+ * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
+ */
+#include "common.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <stdio.h>
+
+#define STACK_DEPTH 128
+
+static int dirstack[STACK_DEPTH];
+static int stacktop = 0;
+
+int pushd(const char *path)
+{
+ int fd;
+
+ assert(stacktop < STACK_DEPTH);
+
+ fd = open(".", O_DIRECTORY | O_PATH | O_RDONLY | O_CLOEXEC);
+
+ if (fd < 0) {
+ perror("open ./");
+ return -1;
+ }
+
+ if (chdir(path)) {
+ perror(path);
+ close(fd);
+ return -1;
+ }
+
+ dirstack[stacktop++] = fd;
+ return 0;
+}
+
+int pushdn(const char *path, size_t len)
+{
+ char *temp;
+ int ret;
+
+ temp = strndup(path, len);
+ if (temp == NULL) {
+ perror("pushd");
+ return -1;
+ }
+
+ ret = pushd(temp);
+
+ free(temp);
+ return ret;
+}
+
+int popd(void)
+{
+ int fd;
+
+ assert(stacktop > 0);
+
+ fd = dirstack[stacktop - 1];
+
+ if (fchdir(fd)) {
+ perror("popd");
+ return -1;
+ }
+
+ --stacktop;
+ close(fd);
+ return 0;
+}
diff --git a/lib/common/mkdir_p.c b/lib/common/mkdir_p.c
new file mode 100644
index 0000000..cb433b3
--- /dev/null
+++ b/lib/common/mkdir_p.c
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later */
+/*
+ * mkdir_p.c
+ *
+ * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
+ */
+#include "common.h"
+
+#include <string.h>
+#include <alloca.h>
+#include <stdio.h>
+#include <errno.h>
+
+int mkdir_p(const char *path)
+{
+ size_t i, len;
+ char *buffer;
+
+ while (path[0] == '/' && path[1] == '/')
+ ++path;
+
+ if (*path == '\0' || (path[0] == '/' && path[1] == '\0'))
+ return 0;
+
+ len = strlen(path) + 1;
+ buffer = alloca(len);
+
+ for (i = 0; i < len; ++i) {
+ if (i > 0 && (path[i] == '/' || path[i] == '\0')) {
+ buffer[i] = '\0';
+
+ if (mkdir(buffer, 0755) != 0) {
+ if (errno != EEXIST) {
+ fprintf(stderr, "mkdir %s: %s\n",
+ buffer, strerror(errno));
+ return -1;
+ }
+ }
+ }
+
+ buffer[i] = path[i];
+ }
+
+ return 0;
+}