From 5afaf8e6eef12f8b7109d4c12324ef9b505c2c4d Mon Sep 17 00:00:00 2001 From: Peter Date: Wed, 3 Aug 2022 15:09:47 +0300 Subject: Add mkdir --- .gitignore | 1 + package/deps.mak | 3 + package/modes | 1 + package/targets.mak | 1 + src/shh-portable-utils/deps-exe/mkdir | 4 ++ src/shh-portable-utils/mkdir.c | 104 ++++++++++++++++++++++++++++++++++ 6 files changed, 114 insertions(+) create mode 100644 src/shh-portable-utils/deps-exe/mkdir create mode 100644 src/shh-portable-utils/mkdir.c 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 +#include + +#include +#include + +#include +#include +#include + +#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; +} -- cgit v1.2.3