aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter <petershh@disroot.org>2022-08-03 15:09:47 +0300
committerGitHub <noreply@github.com>2022-08-03 15:09:47 +0300
commit5afaf8e6eef12f8b7109d4c12324ef9b505c2c4d (patch)
tree1d882b44767800552dce81bc2059204bc36e8c8d
parentaaf3b7a059f72375d09817d15758d92628990e65 (diff)
downloadshh-portable-utils-5afaf8e6eef12f8b7109d4c12324ef9b505c2c4d.tar.xz
Add mkdir
-rw-r--r--.gitignore1
-rw-r--r--package/deps.mak3
-rw-r--r--package/modes1
-rw-r--r--package/targets.mak1
-rw-r--r--src/shh-portable-utils/deps-exe/mkdir4
-rw-r--r--src/shh-portable-utils/mkdir.c104
6 files changed, 114 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index 8e345fe..71c3399 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,6 +15,7 @@ src/include/shh-portable-utils/config.h
/false
/link
/ln
+/mkdir
/mkfifo
/nice
/nohup
diff --git a/package/deps.mak b/package/deps.mak
index fc6cfd1..073500a 100644
--- a/package/deps.mak
+++ b/package/deps.mak
@@ -14,6 +14,7 @@ src/shh-portable-utils/dirname.o src/shh-portable-utils/dirname.lo: src/shh-port
src/shh-portable-utils/false.o src/shh-portable-utils/false.lo: src/shh-portable-utils/false.c
src/shh-portable-utils/link.o src/shh-portable-utils/link.lo: src/shh-portable-utils/link.c
src/shh-portable-utils/ln.o src/shh-portable-utils/ln.lo: src/shh-portable-utils/ln.c
+src/shh-portable-utils/mkdir.o src/shh-portable-utils/mkdir.lo: src/shh-portable-utils/mkdir.c
src/shh-portable-utils/mkfifo.o src/shh-portable-utils/mkfifo.lo: src/shh-portable-utils/mkfifo.c src/shh-portable-utils/shhfuncs.h
src/shh-portable-utils/nice.o src/shh-portable-utils/nice.lo: src/shh-portable-utils/nice.c
src/shh-portable-utils/nohup.o src/shh-portable-utils/nohup.lo: src/shh-portable-utils/nohup.c
@@ -50,6 +51,8 @@ link: EXTRA_LIBS := -lskarnet
link: src/shh-portable-utils/link.o
ln: EXTRA_LIBS := -lskarnet
ln: src/shh-portable-utils/ln.o
+mkdir: EXTRA_LIBS := -lskarnet
+mkdir: src/shh-portable-utils/mkdir.o src/shh-portable-utils/parse_mode_octal.o src/shh-portable-utils/parse_mode_symbolic.o src/shh-portable-utils/change_mode.o
mkfifo: EXTRA_LIBS := -lskarnet
mkfifo: src/shh-portable-utils/mkfifo.o src/shh-portable-utils/parse_mode_octal.o src/shh-portable-utils/parse_mode_symbolic.o src/shh-portable-utils/change_mode.o
nice: EXTRA_LIBS := -lskarnet
diff --git a/package/modes b/package/modes
index 3173407..12d0659 100644
--- a/package/modes
+++ b/package/modes
@@ -8,6 +8,7 @@ dirname 0755
false 0755
link 0755
ln 0755
+mkdir 0755
mkfifo 0755
nice 0755
nohup 0755
diff --git a/package/targets.mak b/package/targets.mak
index a7516ab..ff2bd8f 100644
--- a/package/targets.mak
+++ b/package/targets.mak
@@ -9,6 +9,7 @@ dirname \
false \
link \
ln \
+mkdir \
mkfifo \
nice \
nohup \
diff --git a/src/shh-portable-utils/deps-exe/mkdir b/src/shh-portable-utils/deps-exe/mkdir
new file mode 100644
index 0000000..e765767
--- /dev/null
+++ b/src/shh-portable-utils/deps-exe/mkdir
@@ -0,0 +1,4 @@
+parse_mode_octal.o
+parse_mode_symbolic.o
+change_mode.o
+-lskarnet
diff --git a/src/shh-portable-utils/mkdir.c b/src/shh-portable-utils/mkdir.c
new file mode 100644
index 0000000..ecd9119
--- /dev/null
+++ b/src/shh-portable-utils/mkdir.c
@@ -0,0 +1,104 @@
+#include <string.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <skalibs/strerr2.h>
+#include <skalibs/genalloc.h>
+#include <skalibs/sgetopt.h>
+
+#include "shhfuncs.h"
+
+#define USAGE "mkdir [-p] [-m mode] dir..."
+
+int main(int argc, char **argv)
+{
+ mode_t mask;
+ mode_t mode = 0777;
+ int failure = 0;
+ int mkparent = 0;
+ genalloc directives = GENALLOC_ZERO;
+ subgetopt l = SUBGETOPT_ZERO;
+ PROG = "mkdir";
+
+ mask = umask(0);
+ umask(mask);
+
+ for (;;) {
+ int opt = subgetopt_r(argc, (char const *const *)argv, "pm:", &l);
+ if (opt == -1)
+ break;
+ switch (opt) {
+ case 'p':
+ mkparent = 1;
+ break;
+ case 'm':
+ if ('0' <= l.arg[0] && l.arg[0] <= '7') {
+ if (parse_mode_octal(l.arg, &mode))
+ strerr_dief2x(100, "invalid mode: ", l.arg);
+ } else if (parse_mode_symbolic(l.arg, &directives)) {
+ if (errno == EINVAL)
+ strerr_dief2x(100, "invalid mode: ", l.arg);
+ else
+ strerr_diefu1sys(111, "parse mode");
+ } else
+ mode = change_mode(0777, genalloc_s(chmod_directive,
+ &directives),
+ genalloc_len(chmod_directive,
+ &directives),
+ mask);
+ break;
+ default:
+ strerr_dieusage(100, USAGE);
+ }
+ }
+ argc -= l.ind;
+ argv += l.ind;
+
+ if (!argc)
+ strerr_dieusage(100, USAGE);
+
+ for (char **path = argv; *path; path++) {
+ if (mkparent) {
+ char *afterslash = *path + 1;
+ char save;
+ for (;;) {
+ afterslash = strchr(afterslash, '/');
+ if (!afterslash) {
+ if (mkdir(*path, mode)) {
+ if (errno != EEXIST) {
+ strerr_warnwu2sys("mkdir ", *path);
+ failure = 1;
+ }
+ }
+ break;
+ }
+ afterslash++;
+ save = *afterslash;
+ *afterslash = '\0';
+ if (mkdir(*path, 0)) {
+ if (errno != EEXIST) {
+ strerr_warnwu2sys("mkdir ", *path);
+ failure = 1;
+ break;
+ }
+ *afterslash = save;
+ continue;
+ }
+ if (chmod(*path, (S_IWUSR | S_IXUSR | ~mask) & 0777)) {
+ strerr_warnwu2sys("chmod ", *path);
+ failure = 1;
+ break;
+ }
+ *afterslash = save;
+ }
+ } else {
+ if (mkdir(*path, mode)) {
+ strerr_warnwu2sys("mkdir ", *path);
+ failure = 1;
+ }
+ }
+ }
+ return failure ? 111 : 0;
+}