Author | Jamozed <[email protected]> |
Date | 2020-09-25 12:40:39 |
Commit | 88802f3e8cf367bd602441cfe7e174597a20cd59 |
Parent | 02a966d641696b5992c93a07b9f4aa1b782f33f3 |
mkdir: Use mode library instead of own solution
Diffstat
M | src/mkdir.c | | | 154 | ++++++++++++++++++++++++++++--------------------------------------------------- |
1 files changed, 55 insertions, 99 deletions
diff --git a/src/mkdir.c b/src/mkdir.c index ef2fb10..006da0e 100644 --- a/src/mkdir.c +++ b/src/mkdir.c @@ -1,4 +1,4 @@ -// mkdir.c, version 1.0.3 +// mkdir.c, version 1.0.4 // OMKOV coreutils implementation of POSIX mkdir // Copyright (C) 2020, Jakob Wakeling // All rights reserved. @@ -30,28 +30,22 @@ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. */ +/* + TODO Cleanup p flag handling + TODO Handle copying permissions +*/ + #include "lib/error.h" +#include "lib/mode.h" #include "lib/optget.h" #include <sys/stat.h> -#include <ctype.h> #include <errno.h> #include <stdbool.h> #include <stdio.h> -#define VERSION "1.0.3" - -#define USR 05700 -#define GRP 02070 -#define OTH 00007 -#define ALL 07777 - -#define RD 00444 -#define WR 00222 -#define EX 00111 -#define ID 06000 -#define ST 01000 +#define VERSION "1.0.4" static struct lop lops[] = { { "help", ARG_NUL, 256 }, @@ -59,16 +53,12 @@ static struct lop lops[] = { { NULL, 0, 0 } }; -static char *mopt; -static bool pflag; +static char *mopt; +static bool pflag; -static mode_t mode, mask; +static mode_t mask; -static inline mode_t newmode(char *mstr); -static inline mode_t strtom(char **nptr); -static inline mode_t getref(char **mstr); -static inline int getop(char **mstr); -static inline mode_t getmod(char **mstr); +static inline int makedir(const char *path, chmod_t *m); static void hlp(void); static void ver(void); @@ -85,98 +75,63 @@ int main(int ac, char *av[]) { A0 = av[0]; if (opt.ind == ac) { error(1, "missing operand"); } - if (mopt) { - mask = umask(0); mode = newmode(mopt); - if (mode == (mode_t)-1) { error(1, "%s: invalid mode", mopt); } - } else { mode = 0777; } + chmod_t *m = NULL; if (mopt) { + mask = umask(0); m = strmode(mopt); + if (!m) { error(1, "%s: invalid mode", mopt); } + } + + bool warned = false; - for (int i = opt.ind; i < ac; ++i) { - if (pflag) { - char *p = av[i]; - for (; *p == '/'; ++p) {} - for (; *p; ++p) { - if (*p != '/' || *(p + 1) == '/') { continue; } *p = 0; - if (mkdir(av[i], mode) && errno != EEXIST) { - warn("%s: %s", av[i], serr()); continue; - } *p = '/'; + for (char **p = &av[opt.ind]; *p; ++p) { + if (pflag) { // Create directory hierarchy if p flag is set + char *q = *p; for (; *q == '/'; ++q) {} + for (; *q; ++q) { + if (*q != '/' || *(q + 1) == '/') { continue; } *q = 0; + if (mkdir(*p, (S_IWUSR | S_IXUSR | ~mask) & 0777) && + errno != EEXIST) { + warn("%s: %s", *p, serr()); continue; + } *q = '/'; } } - if (mkdir(av[i], mode)) { warn("%s: %s", av[i], serr()); continue; } + + if (makedir(*p, m)) { warn("%s: %s", *p, serr()); warned = true; } } - return 0; + return warned; } -static inline mode_t newmode(char *mstr) { - for (; isspace(*mstr); ++mstr); - char *start = mstr; register mode_t nmode; +/* Make directory with specified permissions */ +static inline int makedir(const char *path, chmod_t *m) { + // If no chmod is given, use default mode + if (!m) { if (mkdir(path, 0777)) { return 1; } return 0; } - nmode = strtom(&mstr); - if (mstr == start) { nmode = 0; } - else if (*mstr) { return (mode_t)-1; } - else { return nmode; } + // Create directory with no permissions + if (mkdir(path, 0)) { return 1; } mode_t mode = 0777; - do { - register mode_t ref, mod; register int op; + // Handle each chmod_t + for (int i = 0;; ++i) switch (m[i].flag) { + case MF_NORM: case MF_XIFX: { + // If ref is null, use the file mode creation mask + if (!m[i].ref) { m[i].ref = M_ALL & ~mask; } - ref = getref(&mstr); - while ((op = getop(&mstr))) { - mod = getmod(&mstr); - switch (op) { - case '+': { nmode |= ref & mod; break; } - case '-': { nmode &= (~(ref & mod) & 07777); break; } - case '=': { nmode &= ~ref; nmode |= ref & mod; break; } - } + switch (m[i].op) { + case '+': { mode |= m[i].ref & m[i].mod; break; } + case '-': { mode &= (~(m[i].ref & m[i].mod) & 07777); break; } + case '=': { mode &= ~m[i].ref; mode |= m[i].ref & m[i].mod; break; } } - } while (*mstr++ == ',' && *mstr); - - if (*--mstr) { return (mode_t)-1; } - return nmode; -} - -static inline mode_t strtom(char **nptr) { - mode_t nmode = 0; register int d; - - for (; **nptr >= '0' && **nptr <= '7'; ++*nptr) { - d = **nptr - '0'; - if (nmode > (unsigned)(07777 - d) / 8) { break; } - nmode = nmode * 8 + (unsigned)d; - } - - return nmode; -} - -static inline mode_t getref(char **mstr) { - register mode_t nmode = 0; - - for (;;) switch (**mstr) { - case 'u': { nmode |= USR; ++*mstr; continue; } - case 'g': { nmode |= GRP; ++*mstr; continue; } - case 'o': { nmode |= OTH; ++*mstr; continue; } - case 'a': { nmode |= ALL; ++*mstr; continue; } - default: { if (!nmode) { nmode = ALL & ~mask; } return nmode; } + + // If the XIFX flag is set, set execute permission + if (m[i].flag == MF_XIFX) { mode |= m[i].ref & M_EX; } break; } -} - -static inline int getop(char **mstr) { - if (**mstr == '+' || **mstr == '-' || **mstr == '=') { return *(*mstr)++; } - switch (**mstr) { case '+': case '-': case '=': { return *(*mstr)++; }} - return 0; -} - -static inline mode_t getmod(char **mstr) { - register mode_t nmode = 0; + case MF_COPY: { /* TODO */ } + case MF_NULL: { goto end; } + } end:; - for (;;) switch (**mstr) { - case 'r': { nmode |= RD; ++*mstr; continue; } - case 'w': { nmode |= WR; ++*mstr; continue; } - case 'x': case 'X': { nmode |= EX; ++*mstr; continue; } - case 's': { nmode |= ID; ++*mstr; continue; } - case 't': { nmode |= ST; ++*mstr; continue; } - default: { return nmode; } - } + // Set permissions of directory to the calculated mode + if (chmod(path, mode)) { return 1; } return 0; } +/* Print help information */ static void hlp(void) { puts("mkdir - make directories\n"); puts("usage: mkdir [-p] [-m mode] dir...\n"); @@ -188,6 +143,7 @@ static void hlp(void) { return; } +/* Print version information */ static void ver(void) { puts("OMKOV coreutils mkdir, version " VERSION); puts("Copyright (C) 2020, Jakob Wakeling");