diff options
author | Daniel Walter <d.walter@0x90.at> | 2012-03-19 19:57:56 -0500 |
---|---|---|
committer | Daniel Walter <d.walter@0x90.at> | 2012-03-19 19:57:56 -0500 |
commit | 05744b3176828c25f6e2cc2d663615252b4cd02f (patch) | |
tree | 0877fb5acc60b3a23485bdbff1b63d39666ff789 /lib/lib.c | |
parent | ee00a7f4587c1b75dedb71b5aa3d12608fb7b54c (diff) | |
download | toybox-05744b3176828c25f6e2cc2d663615252b4cd02f.tar.gz |
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);
Diffstat (limited to 'lib/lib.c')
-rw-r--r-- | lib/lib.c | 144 |
1 files changed, 144 insertions, 0 deletions
@@ -895,3 +895,147 @@ char *num_to_sig(int sig) 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; +} |