sbase

suckless unix tools
git clone git://git.2f30.org/sbase.git
Log | Files | Refs | README | LICENSE

commit bd99b92e9107dd4af44d57e6a31da153d64df99c
parent a1b62b2282a632374cab442e6e8311846b857f56
Author: Hiltjo Posthuma <hiltjo@codemadness.org>
Date:   Wed Apr 23 21:28:59 +0200

parsemode: rework

- for octal input: reset mode to 0.
- take umask into account.
- make '=rwx' etc work.
- we wont support crazy but valid modes like "a+rw,g=x,o=g"
- uudecode: use parsemode, mask is 0.

Signed-off-by: Hiltjo Posthuma <hiltjo@codemadness.org>

Diffstat:
chmod.c | 22+++++++---------------
util.h | 3++-
util/mode.c | 92++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
uudecode.c | 2+-
4 files changed, 68 insertions(+), 51 deletions(-)
diff --git a/chmod.c b/chmod.c @@ -9,8 +9,8 @@ static void chmodr(const char *); static bool rflag = false; -static int oper = '='; -static mode_t mode = 0; +static char *modestr = ""; +static mode_t mask = 0; static void usage(void) @@ -45,7 +45,8 @@ main(int argc, char *argv[]) } done: - parsemode(argv[0], &mode, &oper); + mask = getumask(); + modestr = argv[0]; argv++; argc--; @@ -61,22 +62,13 @@ void chmodr(const char *path) { struct stat st; + mode_t m; if(stat(path, &st) == -1) eprintf("stat %s:", path); - switch(oper) { - case '+': - st.st_mode |= mode; - break; - case '-': - st.st_mode &= ~mode; - break; - case '=': - st.st_mode = mode; - break; - } - if(chmod(path, st.st_mode) == -1) + m = parsemode(modestr, st.st_mode, mask); + if(chmod(path, m) == -1) weprintf("chmod %s:", path); if(rflag) recurse(path, chmodr); diff --git a/util.h b/util.h @@ -27,4 +27,5 @@ size_t strlcat(char *, const char *, size_t); size_t strlcpy(char *, const char *, size_t); void weprintf(const char *, ...); -void parsemode(const char *, mode_t *, int *); +mode_t getumask(void); +mode_t parsemode(const char *, mode_t, mode_t); diff --git a/util/mode.c b/util/mode.c @@ -4,74 +4,98 @@ #include <sys/stat.h> #include "../util.h" -void -parsemode(const char *str, mode_t *mode, int *oper) +mode_t +getumask(void) +{ + mode_t mask = umask(0); + umask(mask); + return mask; +} + +mode_t +parsemode(const char *str, mode_t mode, mode_t mask) { char *end; const char *p; - int octal; - mode_t mask = 0; + int octal, op = '+'; + mode_t gmask = 0, m = 0; octal = strtol(str, &end, 8); if(*end == '\0') { - if(octal < 0 || octal > 07777) + if(octal < 0 || octal > 07777) { eprintf("%s: invalid mode\n", str); - if(octal & 04000) *mode |= S_ISUID; - if(octal & 02000) *mode |= S_ISGID; - if(octal & 01000) *mode |= S_ISVTX; - if(octal & 00400) *mode |= S_IRUSR; - if(octal & 00200) *mode |= S_IWUSR; - if(octal & 00100) *mode |= S_IXUSR; - if(octal & 00040) *mode |= S_IRGRP; - if(octal & 00020) *mode |= S_IWGRP; - if(octal & 00010) *mode |= S_IXGRP; - if(octal & 00004) *mode |= S_IROTH; - if(octal & 00002) *mode |= S_IWOTH; - if(octal & 00001) *mode |= S_IXOTH; - return; + return -1; + } + mode = 0; + if(octal & 04000) mode |= S_ISUID; + if(octal & 02000) mode |= S_ISGID; + if(octal & 01000) mode |= S_ISVTX; + if(octal & 00400) mode |= S_IRUSR; + if(octal & 00200) mode |= S_IWUSR; + if(octal & 00100) mode |= S_IXUSR; + if(octal & 00040) mode |= S_IRGRP; + if(octal & 00020) mode |= S_IWGRP; + if(octal & 00010) mode |= S_IXGRP; + if(octal & 00004) mode |= S_IROTH; + if(octal & 00002) mode |= S_IWOTH; + if(octal & 00001) mode |= S_IXOTH; + return mode; } - for(p = str; *p; p++) + for(p = str; *p; p++) { switch(*p) { /* masks */ case 'u': - mask |= S_IRWXU; + gmask |= S_IRWXU; break; case 'g': - mask |= S_IRWXG; + gmask |= S_IRWXG; break; case 'o': - mask |= S_IRWXO; + gmask |= S_IRWXO; break; case 'a': - mask |= S_IRWXU|S_IRWXG|S_IRWXO; + gmask |= S_IRWXU|S_IRWXG|S_IRWXO; break; /* opers */ + case '=': case '+': case '-': - case '=': - if(oper) - *oper = (int)*p; + op = (int)*p; break; /* modes */ case 'r': - *mode |= S_IRUSR|S_IRGRP|S_IROTH; + m |= S_IRUSR|S_IRGRP|S_IROTH; break; case 'w': - *mode |= S_IWUSR|S_IWGRP|S_IWOTH; + m |= S_IWUSR|S_IWGRP|S_IWOTH; break; case 'x': - *mode |= S_IXUSR|S_IXGRP|S_IXOTH; + m |= S_IXUSR|S_IXGRP|S_IXOTH; break; case 's': - *mode |= S_ISUID|S_ISGID; + m |= S_ISUID|S_ISGID; break; case 't': - *mode |= S_ISVTX; + m |= S_ISVTX; break; - /* error */ default: eprintf("%s: invalid mode\n", str); + return -1; + } + /* apply */ + switch(op) { + case '+': + mode |= (m & ((~mask) & 0777)); + break; + case '-': + mode &= (~(m & ((~mask) & 0777))); + break; + case '=': + mode = (m & ((~mask) & 0777)); + break; } - if(mask) - *mode &= mask; + } + if(gmask && op != '=') + mode &= ~gmask; + return mode; } diff --git a/uudecode.c b/uudecode.c @@ -107,7 +107,7 @@ parseheader(FILE *fp, const char *s, const char *header, mode_t *mode, char **fn eprintf("malformed mode string in header\n"); *q++ = '\0'; /* now mode should be null terminated, q points to fname */ - parsemode(p, mode, NULL); + *mode = parsemode(p, *mode, 0); n = strlen(q); while (n > 0 && (q[n - 1] == '\n' || q[n - 1] == '\r')) q[--n] = '\0';