ref: d0ae2e369e0221e796f4b58255b21ce3592d80dc
dir: /sys/src/cmd/chmod.c/
#include <u.h> #include <libc.h> #define U(x) (x<<6) #define G(x) (x<<3) #define O(x) (x) #define A(x) (U(x)|G(x)|O(x)) #define DMRWE (DMREAD|DMWRITE|DMEXEC) int parsemode(char *, ulong *, ulong *); void main(int argc, char *argv[]) { int i; Dir *dir, ndir; ulong mode, mask; char *p; if(argc < 3){ fprint(2, "usage: chmod 0777 file ... or chmod [who]op[rwxalt] file ...\n"); exits("usage"); } mode = strtol(argv[1], &p, 8); if(*p == 0) mask = A(DMRWE); else if(!parsemode(argv[1], &mask, &mode)){ fprint(2, "chmod: bad mode: %s\n", argv[1]); exits("mode"); } nulldir(&ndir); for(i=2; i<argc; i++){ dir = dirstat(argv[i]); if(dir == nil){ fprint(2, "chmod: can't stat %s: %r\n", argv[i]); continue; } ndir.mode = (dir->mode & ~mask) | (mode & mask); free(dir); if(dirwstat(argv[i], &ndir)==-1){ fprint(2, "chmod: can't wstat %s: %r\n", argv[i]); continue; } } exits(0); } int parsemode(char *spec, ulong *pmask, ulong *pmode) { ulong mode, mask; int done, op; char *s; s = spec; mask = DMAPPEND | DMEXCL | DMTMP; for(done=0; !done; ){ switch(*s){ case 'u': mask |= U(DMRWE); break; case 'g': mask |= G(DMRWE); break; case 'o': mask |= O(DMRWE); break; case 'a': mask |= A(DMRWE); break; case 0: return 0; default: done = 1; } if(!done) s++; } if(s == spec) mask |= A(DMRWE); op = *s++; if(op != '+' && op != '-' && op != '=') return 0; mode = 0; for(; *s ; s++){ switch(*s){ case 'r': mode |= A(DMREAD); break; case 'w': mode |= A(DMWRITE); break; case 'x': mode |= A(DMEXEC); break; case 'a': mode |= DMAPPEND; break; case 'l': mode |= DMEXCL; break; case 't': mode |= DMTMP; break; default: return 0; } } if(*s != 0) return 0; if(op == '+' || op == '-') mask &= mode; if(op == '-') mode = ~mode; *pmask = mask; *pmode = mode; return 1; }