[Toybox] [PATCH] mode parser

Daniel Walter d.walter at 0x90.at
Thu Mar 8 00:40:47 PST 2012


Add string to mode_t parser

added new function string_to_mode(char *m_string, mode_t base) which
parses a given string and converts it to a mode_t.
If either + or - are part of m_string the permissions are either
added or removed from base.

Currently support for permision copy is missing (e.g. g=u),
but all other flags should work.

Format for m_string: either symbolic modes or octal representation.

symbolic modes:
[auog][[+-=][rwxst]*]

examples:
string_to_mode("u=rwx,g=rw,o=r", 0);
string_to_mode("a-x", 0777);
string_to_mode("0744", 0);

--
Also included: -m for mkfifo

regards, 
daniel

--
 lib/lib.c     |  144 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/lib.h     |    2 +
 toys/mkfifo.c |    9 +++-
 3 files changed, 153 insertions(+), 2 deletions(-)
--
diff -r a864aa8c6331 lib/lib.c
--- a/lib/lib.c	Wed Mar 07 20:05:36 2012 -0600
+++ b/lib/lib.c	Thu Mar 08 09:24:44 2012 +0100
@@ -892,3 +892,147 @@
 		if (signames[i].num == sig) return signames[i].name;
 	return NULL;
 }
+
+
+/* mode parsing */
+
+#define	USR_FLAGS	(S_IRWXU)
+#define	GRP_FLAGS	(S_IRWXG)
+#define	OTH_FLAGS	(S_IRWXO)
+#define SGT_FLAGS	(S_ISUID | S_ISGID | S_ISVTX)
+
+#define MODE_WHAT(v, w, x, y, z) { \
+	if (x & v) \
+		y |= S_I##w##z;\
+	}
+#define MODE_READ(x, y, z) MODE_WHAT(0x04, R, x, y, z)
+#define MODE_WRITE(x, y, z) MODE_WHAT(0x02, W, x, y, z)
+#define MODE_EXEC(x, y, z) MODE_WHAT(0x01, X, x, y, z)
+#define MODE_SUID(x, y) MODE_WHAT(0x08, S, x, y, UID)
+#define MODE_SGID(x, y) MODE_WHAT(0x08, S, x, y, GID)
+#define MODE_SVTX(x, y) MODE_WHAT(0x10, S, x, y, VTX)
+
+mode_t
+apply_mode(int who, int how, int what, mode_t base)
+{
+	mode_t new_mode = 0;
+	mode_t tmp_mode = 0;
+	mode_t tmp_mask = USR_FLAGS | GRP_FLAGS | OTH_FLAGS | SGT_FLAGS;
+	if (who & 0x01) {
+		/* u */
+		MODE_READ(what, tmp_mode, USR);
+		MODE_WRITE(what, tmp_mode, USR);
+		MODE_EXEC(what, tmp_mode, USR);
+		MODE_SUID(what, tmp_mode)
+		tmp_mask &= (GRP_FLAGS | OTH_FLAGS | SGT_FLAGS);
+	}
+	if (who & 0x02) {
+		/* g */
+		MODE_READ(what, tmp_mode, GRP);
+		MODE_WRITE(what, tmp_mode, GRP);
+		MODE_EXEC(what, tmp_mode, GRP);
+		MODE_SGID(what, tmp_mode)
+		tmp_mask &= (USR_FLAGS | OTH_FLAGS | SGT_FLAGS);
+	}
+	if (who & 0x04) {
+		/* o */
+		MODE_READ(what, tmp_mode, OTH);
+		MODE_WRITE(what, tmp_mode, OTH);
+		MODE_EXEC(what, tmp_mode, OTH);
+		tmp_mask &= (USR_FLAGS | GRP_FLAGS | SGT_FLAGS);
+	}
+	/* check sticky */
+	MODE_SVTX(what, tmp_mode);
+	switch (how){
+	case 1:
+		/* set */
+		new_mode = tmp_mode | (base & tmp_mask);
+		break;
+	case 2:
+		/* add */
+		new_mode = base | tmp_mode;
+		break;
+	case 3:
+		/* remove */
+		new_mode = base & ~(tmp_mode);
+		break;
+	}
+	return new_mode;
+}
+
+
+mode_t
+string_to_mode(char *mode_str, mode_t base)
+{
+	mode_t new_mode;
+	int what = 0;
+	int who = 0;
+	int how = 0;
+	char *p;
+	long tmp;
+	if (!mode_str)
+		return base;
+	if (isdigit(mode_str[0])) {
+		tmp = strtol(mode_str, &p, 8);
+		if (*p || tmp < 0 ||
+			(tmp & ~(OTH_FLAGS | SGT_FLAGS | GRP_FLAGS | USR_FLAGS)))
+			return base;
+		new_mode = (mode_t) tmp;
+		return new_mode;
+	}
+	new_mode = base;
+	while (*mode_str) {
+		/* TODO: add support for permission copying */
+		switch(*mode_str) {
+		case ',':
+			/* next command */
+			new_mode = apply_mode(who, how, what, new_mode);
+			who = 0;
+			how = 0;
+			what = 0;
+			break;
+		case 'a':
+			who = 0x01 | 0x02 | 0x04;
+			break;
+		case 'u':
+			who |= 0x01;
+			break;
+		case 'g':
+			who |= 0x02;
+			break;
+		case 'o':
+			who |= 0x04;
+			break;
+		case 'r':
+			what |= 0x04;
+			break;
+		case 'w':
+			what |= 0x02;
+			break;
+		case 'x':
+			what |= 0x01;
+			break;
+		case 't':
+			what |= 0x10;
+			break;
+		case 's':
+			what |= 0x08;
+			break;
+		case '=':
+			how = 1;
+			break;
+		case '+':
+			how = 2;
+			break;
+		case '-':
+			how = 3;
+			break;
+		default:
+			/* error case */
+			return base;
+		}
+		mode_str++;
+	}
+	new_mode = apply_mode(who, how, what, new_mode);
+	return new_mode;
+}
diff -r a864aa8c6331 lib/lib.h
--- a/lib/lib.h	Wed Mar 07 20:05:36 2012 -0600
+++ b/lib/lib.h	Thu Mar 08 09:24:44 2012 +0100
@@ -131,3 +131,5 @@
 
 int sig_to_num(char *pidstr);
 char *num_to_sig(int sig);
+
+mode_t string_to_mode(char *mode_str, mode_t base);
diff -r a864aa8c6331 toys/mkfifo.c
--- a/toys/mkfifo.c	Wed Mar 07 20:05:36 2012 -0600
+++ b/toys/mkfifo.c	Thu Mar 08 09:24:44 2012 +0100
@@ -8,7 +8,7 @@
  *
  * TODO: Add -m
 
-USE_MKFIFO(NEWTOY(mkfifo, "<1", TOYFLAG_BIN))
+USE_MKFIFO(NEWTOY(mkfifo, "<1m:", TOYFLAG_BIN))
 
 config MKFIFO
 	bool "mkfifo"
@@ -22,16 +22,21 @@
 #include "toys.h"
 
 DEFINE_GLOBALS(
-	long mode;
+	char *m_string;
+	mode_t mode;
 )
 
 #define TT this.mkfifo
+#define FLAG_m (1)
 
 void mkfifo_main(void)
 {
 	char **s;
 
 	TT.mode = 0666;
+	if (toys.optflags & FLAG_m) {
+		TT.mode = string_to_mode(TT.m_string, 0);
+	}
 
 	for (s = toys.optargs; *s; s++) {
 		if (mknod(*s, S_IFIFO | TT.mode, 0) < 0) {



More information about the Toybox mailing list