diff options
Diffstat (limited to 'usr/src/lib/libast/common/string/strperm.c')
-rw-r--r-- | usr/src/lib/libast/common/string/strperm.c | 267 |
1 files changed, 267 insertions, 0 deletions
diff --git a/usr/src/lib/libast/common/string/strperm.c b/usr/src/lib/libast/common/string/strperm.c new file mode 100644 index 0000000000..b54b193186 --- /dev/null +++ b/usr/src/lib/libast/common/string/strperm.c @@ -0,0 +1,267 @@ +/*********************************************************************** +* * +* This software is part of the ast package * +* Copyright (c) 1985-2007 AT&T Knowledge Ventures * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Knowledge Ventures * +* * +* A copy of the License is available at * +* http://www.opensource.org/licenses/cpl1.0.txt * +* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * +* * +* Information and Software Systems Research * +* AT&T Research * +* Florham Park NJ * +* * +* Glenn Fowler <gsf@research.att.com> * +* David Korn <dgk@research.att.com> * +* Phong Vo <kpv@research.att.com> * +* * +***********************************************************************/ +#pragma prototyped +/* + * Glenn Fowler + * AT&T Research + * + * apply file permission expression expr to perm + * + * each expression term must match + * + * [ugoa]*[-&+|^=]?[rwxst0-7]* + * + * terms may be combined using , + * + * if non-null, e points to the first unrecognized char in expr + */ + +#include <ast.h> +#include <ls.h> +#include <modex.h> + +int +strperm(const char* aexpr, char** e, register int perm) +{ + register char* expr = (char*)aexpr; + register int c; + register int typ; + register int who; + int num; + int op; + int mask; + int masked; + + if (perm == -1) + { + perm = 0; + masked = 1; + mask = ~0; + } + else + masked = 0; + for (;;) + { + op = num = who = typ = 0; + for (;;) + { + switch (c = *expr++) + { + case 'u': + who |= S_ISVTX|S_ISUID|S_IRWXU; + continue; + case 'g': + who |= S_ISVTX|S_ISGID|S_IRWXG; + continue; + case 'o': + who |= S_ISVTX|S_IRWXO; + continue; + case 'a': + who = S_ISVTX|S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO; + continue; + default: + if (c >= '0' && c <= '7') + { + if (!who) + who = S_ISVTX|S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO; + c = '='; + } + expr--; + /*FALLTHROUGH*/ + case '=': + if (who) + perm &= ~who; + else + perm = 0; + /*FALLTHROUGH*/ + case '+': + case '|': + case '-': + case '&': + case '^': + op = c; + for (;;) + { + switch (c = *expr++) + { + case 'r': + typ |= S_IRUSR|S_IRGRP|S_IROTH; + continue; + case 'w': + typ |= S_IWUSR|S_IWGRP|S_IWOTH; + continue; + case 'X': + if (!S_ISDIR(perm) && !(perm & (S_IXUSR|S_IXGRP|S_IXOTH))) + continue; + /*FALLTHROUGH*/ + case 'x': + typ |= S_IXUSR|S_IXGRP|S_IXOTH; + continue; + case 's': + typ |= S_ISUID|S_ISGID; + continue; + case 't': + typ |= S_ISVTX; + continue; + case 'l': + if (perm & S_IXGRP) + { + if (e) + *e = expr - 1; + return perm & S_IPERM; + } + typ |= S_ISGID; + continue; + case '=': + case '+': + case '|': + case '-': + case '&': + case '^': + case ',': + case 0: + if (who) + typ &= who; + else + switch (op) + { + case '=': + case '+': + case '|': + case '-': + case '&': + if (!masked) + { + masked = 1; + umask(mask = umask(0)); + mask = ~mask; + } + typ &= mask; + break; + } + switch (op) + { + default: + if (who) + perm &= ~who; + else + perm = 0; + /*FALLTHROUGH*/ + case '+': + case '|': + perm |= typ; + typ = 0; + break; + case '-': + perm &= ~typ; + typ = 0; + break; + case '&': + perm &= typ; + typ = 0; + break; + case '^': + if (typ &= perm) + { + /* + * propagate least restrictive to most restrictive + */ + + if (typ & S_IXOTH) + perm |= who & (S_IXUSR|S_IXGRP); + if (typ & S_IWOTH) + perm |= who & (S_IWUSR|S_IWGRP); + if (typ & S_IROTH) + perm |= who & (S_IRUSR|S_IRGRP); + if (typ & S_IXGRP) + perm |= who & S_IXUSR; + if (typ & S_IWGRP) + perm |= who & S_IWUSR; + if (typ & S_IRGRP) + perm |= who & S_IRUSR; + + /* + * if any execute then read => execute + */ + + if ((typ |= perm) & (S_IXUSR|S_IXGRP|S_IXOTH)) + { + if (typ & S_IRUSR) + perm |= who & S_IXUSR; + if (typ & S_IRGRP) + perm |= who & S_IXGRP; + if (typ & S_IROTH) + perm |= who & S_IXOTH; + } + typ = 0; + } + break; + } + switch (c) + { + case '=': + case '+': + case '|': + case '-': + case '&': + case '^': + op = c; + typ = 0; + continue; + } + if (c) + break; + /*FALLTHROUGH*/ + default: + if (c < '0' || c > '7') + { + if (e) + *e = expr - 1; + if (typ) + { + if (who) + { + typ &= who; + perm &= ~who; + } + perm |= typ; + } + return perm & S_IPERM; + } + num = (num << 3) | (c - '0'); + if (!who && (op == '+' || op == '-')) + who = S_ISVTX|S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO; + if (*expr < '0' || *expr > '7') + { + typ |= modei(num); + num = 0; + } + continue; + } + break; + } + break; + } + break; + } + } +} |