# HG changeset patch # User Daniel Walter # Date 1332205076 18000 # Node ID 2548e6e590b23845df7b937a206197470cacdc02 # Parent b2194045c40e7dc793f382cd2c48920d9552b703 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); diff -r b2194045c40e -r 2548e6e590b2 lib/lib.c --- a/lib/lib.c Mon Mar 19 19:19:21 2012 -0500 +++ b/lib/lib.c Mon Mar 19 19:57:56 2012 -0500 @@ -895,3 +895,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 b2194045c40e -r 2548e6e590b2 lib/lib.h --- a/lib/lib.h Mon Mar 19 19:19:21 2012 -0500 +++ b/lib/lib.h Mon Mar 19 19:57:56 2012 -0500 @@ -132,3 +132,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 b2194045c40e -r 2548e6e590b2 toys/mkfifo.c --- a/toys/mkfifo.c Mon Mar 19 19:19:21 2012 -0500 +++ b/toys/mkfifo.c Mon Mar 19 19:57:56 2012 -0500 @@ -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) {