From 4aca87515a5083ae0e31ce3177189fd43b6d05ac Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sat, 3 Jan 2015 13:58:15 +0100 Subject: patch to Vanilla Tomato 1.28 --- release/src/router/busybox/libbb/parse_mode.c | 228 ++++++++++++++------------ 1 file changed, 120 insertions(+), 108 deletions(-) (limited to 'release/src/router/busybox/libbb/parse_mode.c') diff --git a/release/src/router/busybox/libbb/parse_mode.c b/release/src/router/busybox/libbb/parse_mode.c index 30d2f21c..40105dd3 100644 --- a/release/src/router/busybox/libbb/parse_mode.c +++ b/release/src/router/busybox/libbb/parse_mode.c @@ -1,138 +1,150 @@ /* vi: set sw=4 ts=4: */ /* - * Utility routines. + * parse_mode implementation for busybox * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. + * Copyright (C) 2003 Manuel Novoa III * + * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. */ -#include -#include +/* http://www.opengroup.org/onlinepubs/007904975/utilities/chmod.html */ + #include "libbb.h" +/* This function is used from NOFORK applets. It must not allocate anything */ + +#define FILEMODEBITS (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO) -/* This function parses the sort of string you might pass - * to chmod (i.e., [ugoa]{+|-|=}[rwxst] ) and returns the - * correct mode described by the string. */ -extern int parse_mode(const char *s, mode_t * theMode) +int FAST_FUNC bb_parse_mode(const char *s, mode_t *current_mode) { - static const mode_t group_set[] = { - S_ISUID | S_IRWXU, /* u */ - S_ISGID | S_IRWXG, /* g */ - S_IRWXO, /* o */ - S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO /* a */ + static const mode_t who_mask[] = { + S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO, /* a */ + S_ISUID | S_IRWXU, /* u */ + S_ISGID | S_IRWXG, /* g */ + S_IRWXO /* o */ }; - - static const mode_t mode_set[] = { + static const mode_t perm_mask[] = { S_IRUSR | S_IRGRP | S_IROTH, /* r */ S_IWUSR | S_IWGRP | S_IWOTH, /* w */ S_IXUSR | S_IXGRP | S_IXOTH, /* x */ - S_ISUID | S_ISGID, /* s */ - S_ISVTX /* t */ + S_IXUSR | S_IXGRP | S_IXOTH, /* X -- special -- see below */ + S_ISUID | S_ISGID, /* s */ + S_ISVTX /* t */ }; - - static const char group_chars[] = "ugoa"; - static const char mode_chars[] = "rwxst"; + static const char who_chars[] ALIGN1 = "augo"; + static const char perm_chars[] ALIGN1 = "rwxXst"; const char *p; + mode_t wholist; + mode_t permlist; + mode_t new_mode; + char op; - mode_t andMode = - S_ISVTX | S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO; - mode_t orMode = 0; - mode_t mode; - mode_t groups; - char type; - char c; + if (((unsigned int)(*s - '0')) < 8) { + unsigned long tmp; + char *e; - if (s==NULL) { - return (FALSE); + tmp = strtoul(s, &e, 8); + if (*e || (tmp > 07777U)) { /* Check range and trailing chars. */ + return 0; + } + *current_mode = tmp; + return 1; } - do { - mode = 0; - groups = 0; - NEXT_GROUP: - if ((c = *s++) == '\0') { - return -1; + new_mode = *current_mode; + + /* Note: we allow empty clauses, and hence empty modes. + * We treat an empty mode as no change to perms. */ + + while (*s) { /* Process clauses. */ + if (*s == ',') { /* We allow empty clauses. */ + ++s; + continue; } - for (p=group_chars ; *p ; p++) { - if (*p == c) { - groups |= group_set[(int)(p-group_chars)]; - goto NEXT_GROUP; + + /* Get a wholist. */ + wholist = 0; + WHO_LIST: + p = who_chars; + do { + if (*p == *s) { + wholist |= who_mask[(int)(p-who_chars)]; + if (!*++s) { + return 0; + } + goto WHO_LIST; } - } - switch (c) { - case '=': - case '+': - case '-': - type = c; - if (groups == 0) { /* The default is "all" */ - groups |= S_ISUID | S_ISGID | S_ISVTX - | S_IRWXU | S_IRWXG | S_IRWXO; + } while (*++p); + + do { /* Process action list. */ + if ((*s != '+') && (*s != '-')) { + if (*s != '=') { + return 0; } - break; - default: - if ((c < '0') || (c > '7') || (mode | groups)) { - return (FALSE); - } else { - *theMode = strtol(--s, NULL, 8); - return (TRUE); + /* Since op is '=', clear all bits corresponding to the + * wholist, or all file bits if wholist is empty. */ + permlist = ~FILEMODEBITS; + if (wholist) { + permlist = ~wholist; } - } + new_mode &= permlist; + } + op = *s++; - NEXT_MODE: - if (((c = *s++) != '\0') && (c != ',')) { - for (p=mode_chars ; *p ; p++) { - if (*p == c) { - mode |= mode_set[(int)(p-mode_chars)]; - goto NEXT_MODE; + /* Check for permcopy. */ + p = who_chars + 1; /* Skip 'a' entry. */ + do { + if (*p == *s) { + int i = 0; + permlist = who_mask[(int)(p-who_chars)] + & (S_IRWXU | S_IRWXG | S_IRWXO) + & new_mode; + do { + if (permlist & perm_mask[i]) { + permlist |= perm_mask[i]; + } + } while (++i < 3); + ++s; + goto GOT_ACTION; } - } - break; /* We're done so break out of loop.*/ - } - switch (type) { - case '=': - andMode &= ~(groups); /* Now fall through. */ - case '+': - orMode |= mode & groups; - break; - case '-': - andMode &= ~(mode & groups); - orMode &= ~(mode & groups); - break; - } - } while (c == ','); + } while (*++p); - *theMode &= andMode; - *theMode |= orMode; + /* It was not a permcopy, so get a permlist. */ + permlist = 0; + PERM_LIST: + p = perm_chars; + do { + if (*p == *s) { + if ((*p != 'X') + || (new_mode & (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH)) + ) { + permlist |= perm_mask[(int)(p-perm_chars)]; + } + if (!*++s) { + break; + } + goto PERM_LIST; + } + } while (*++p); + GOT_ACTION: + if (permlist) { /* The permlist was nonempty. */ + mode_t tmp = wholist; + if (!wholist) { + mode_t u_mask = umask(0); + umask(u_mask); + tmp = ~u_mask; + } + permlist &= tmp; + if (op == '-') { + new_mode &= ~permlist; + } else { + new_mode |= permlist; + } + } + } while (*s && (*s != ',')); + } - return TRUE; + *current_mode = new_mode; + return 1; } - -/* END CODE */ -/* -Local Variables: -c-file-style: "linux" -c-basic-offset: 4 -tab-width: 4 -End: -*/ -- cgit v1.2.3-54-g00ecf