bb_parse_mode: do not do umask() needlessly.
This commit is contained in:
		@@ -9,49 +9,40 @@
 | 
			
		||||
 | 
			
		||||
/* http://www.opengroup.org/onlinepubs/007904975/utilities/chmod.html */
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include "libbb.h"
 | 
			
		||||
 | 
			
		||||
#define FILEMODEBITS    (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO)
 | 
			
		||||
#define FILEMODEBITS (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO)
 | 
			
		||||
 | 
			
		||||
int bb_parse_mode(const char *s, mode_t *current_mode)
 | 
			
		||||
{
 | 
			
		||||
	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 */
 | 
			
		||||
		S_ISUID | S_IRWXU,           /* u */
 | 
			
		||||
		S_ISGID | S_IRWXG,           /* g */
 | 
			
		||||
		S_IRWXO                      /* o */
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	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_IXUSR | S_IXGRP | S_IXOTH, /* X -- special -- see below */
 | 
			
		||||
		S_ISUID | S_ISGID,		/* s */
 | 
			
		||||
		S_ISVTX					/* t */
 | 
			
		||||
		S_ISUID | S_ISGID,           /* s */
 | 
			
		||||
		S_ISVTX                      /* t */
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	static const char who_chars[] = "augo";
 | 
			
		||||
	static const char perm_chars[] = "rwxXst";
 | 
			
		||||
 | 
			
		||||
	const char *p;
 | 
			
		||||
 | 
			
		||||
	mode_t wholist;
 | 
			
		||||
	mode_t permlist;
 | 
			
		||||
	mode_t mask;
 | 
			
		||||
	mode_t new_mode;
 | 
			
		||||
	char op;
 | 
			
		||||
 | 
			
		||||
	assert(s);
 | 
			
		||||
 | 
			
		||||
	if (((unsigned int)(*s - '0')) < 8) {
 | 
			
		||||
		unsigned long tmp;
 | 
			
		||||
		char *e;
 | 
			
		||||
 | 
			
		||||
		tmp = strtol(s, &e, 8);
 | 
			
		||||
		tmp = strtoul(s, &e, 8);
 | 
			
		||||
		if (*e || (tmp > 07777U)) { /* Check range and trailing chars. */
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
@@ -59,16 +50,12 @@ int bb_parse_mode(const char *s, mode_t *current_mode)
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	mask = umask(0);
 | 
			
		||||
	umask(mask);
 | 
			
		||||
 | 
			
		||||
	new_mode = *current_mode;
 | 
			
		||||
 | 
			
		||||
	/* Note: We allow empty clauses, and hence empty modes.
 | 
			
		||||
	/* 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;
 | 
			
		||||
@@ -76,8 +63,7 @@ int bb_parse_mode(const char *s, mode_t *current_mode)
 | 
			
		||||
 | 
			
		||||
		/* Get a wholist. */
 | 
			
		||||
		wholist = 0;
 | 
			
		||||
 | 
			
		||||
	WHO_LIST:
 | 
			
		||||
 WHO_LIST:
 | 
			
		||||
		p = who_chars;
 | 
			
		||||
		do {
 | 
			
		||||
			if (*p == *s) {
 | 
			
		||||
@@ -95,7 +81,7 @@ int bb_parse_mode(const char *s, mode_t *current_mode)
 | 
			
		||||
					return 0;
 | 
			
		||||
				}
 | 
			
		||||
				/* Since op is '=', clear all bits corresponding to the
 | 
			
		||||
				 * wholist, of all file bits if wholist is empty. */
 | 
			
		||||
				 * wholist, or all file bits if wholist is empty. */
 | 
			
		||||
				permlist = ~FILEMODEBITS;
 | 
			
		||||
				if (wholist) {
 | 
			
		||||
					permlist = ~wholist;
 | 
			
		||||
@@ -124,13 +110,12 @@ int bb_parse_mode(const char *s, mode_t *current_mode)
 | 
			
		||||
 | 
			
		||||
			/* It was not a permcopy, so get a permlist. */
 | 
			
		||||
			permlist = 0;
 | 
			
		||||
 | 
			
		||||
		PERM_LIST:
 | 
			
		||||
 PERM_LIST:
 | 
			
		||||
			p = perm_chars;
 | 
			
		||||
			do {
 | 
			
		||||
				if (*p == *s) {
 | 
			
		||||
					if ((*p != 'X')
 | 
			
		||||
						|| (new_mode & (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH))
 | 
			
		||||
					 || (new_mode & (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH))
 | 
			
		||||
					) {
 | 
			
		||||
						permlist |= perm_mask[(int)(p-perm_chars)];
 | 
			
		||||
					}
 | 
			
		||||
@@ -140,15 +125,15 @@ int bb_parse_mode(const char *s, mode_t *current_mode)
 | 
			
		||||
					goto PERM_LIST;
 | 
			
		||||
				}
 | 
			
		||||
			} while (*++p);
 | 
			
		||||
 | 
			
		||||
		GOT_ACTION:
 | 
			
		||||
 GOT_ACTION:
 | 
			
		||||
			if (permlist) {	/* The permlist was nonempty. */
 | 
			
		||||
				mode_t tmp = ~mask;
 | 
			
		||||
				if (wholist) {
 | 
			
		||||
					tmp = wholist;
 | 
			
		||||
				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 {
 | 
			
		||||
@@ -159,6 +144,5 @@ int bb_parse_mode(const char *s, mode_t *current_mode)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*current_mode = new_mode;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user