coreutils

General Software Utilities
git clone http://git.omkov.net/coreutils
Log | Tree | Refs | README | LICENCE | Download

AuthorJamozed <[email protected]>
Date2020-09-25 12:40:39
Commit88802f3e8cf367bd602441cfe7e174597a20cd59
Parent02a966d641696b5992c93a07b9f4aa1b782f33f3

mkdir: Use mode library instead of own solution

Diffstat

M src/mkdir.c | 164 +++++++++++++++++++++++++++++++------------------------------------------------

1 files changed, 65 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");