1 #include <u.h> 2 #include <libc.h> 3 4 #define U(x) (x<<6) 5 #define G(x) (x<<3) 6 #define O(x) (x) 7 #define A(x) (U(x)|G(x)|O(x)) 8 9 #define DMRWE (DMREAD|DMWRITE|DMEXEC) 10 11 int parsemode(char *, ulong *, ulong *); 12 13 void 14 main(int argc, char *argv[]) 15 { 16 int i; 17 Dir *dir, ndir; 18 ulong mode, mask; 19 char *p; 20 21 if(argc < 3){ 22 fprint(2, "usage: chmod 0777 file ... or chmod [who]op[rwxal] file ...\n"); 23 exits("usage"); 24 } 25 mode = strtol(argv[1], &p, 8); 26 if(*p == 0) 27 mask = A(DMRWE); 28 else if(!parsemode(argv[1], &mask, &mode)){ 29 fprint(2, "chmod: bad mode: %s\n", argv[1]); 30 exits("mode"); 31 } 32 nulldir(&ndir); 33 for(i=2; i<argc; i++){ 34 dir = dirstat(argv[i]); 35 if(dir == nil){ 36 fprint(2, "chmod: can't stat %s: %r\n", argv[i]); 37 continue; 38 } 39 ndir.mode = (dir->mode & ~mask) | (mode & mask); 40 free(dir); 41 if(dirwstat(argv[i], &ndir)==-1){ 42 fprint(2, "chmod: can't wstat %s: %r\n", argv[i]); 43 continue; 44 } 45 } 46 exits(0); 47 } 48 49 int 50 parsemode(char *spec, ulong *pmask, ulong *pmode) 51 { 52 ulong mode, mask; 53 int done, op; 54 char *s; 55 56 s = spec; 57 mask = DMAPPEND | DMEXCL; 58 for(done=0; !done; ){ 59 switch(*s){ 60 case 'u': 61 mask |= U(DMRWE); break; 62 case 'g': 63 mask |= G(DMRWE); break; 64 case 'o': 65 mask |= O(DMRWE); break; 66 case 'a': 67 mask |= A(DMRWE); break; 68 case 0: 69 return 0; 70 default: 71 done = 1; 72 } 73 if(!done) 74 s++; 75 } 76 if(s == spec) 77 mask |= A(DMRWE); 78 op = *s++; 79 if(op != '+' && op != '-' && op != '=') 80 return 0; 81 mode = 0; 82 for(; *s ; s++){ 83 switch(*s){ 84 case 'r': 85 mode |= A(DMREAD); break; 86 case 'w': 87 mode |= A(DMWRITE); break; 88 case 'x': 89 mode |= A(DMEXEC); break; 90 case 'a': 91 mode |= DMAPPEND; break; 92 case 'l': 93 mode |= DMEXCL; break; 94 default: 95 return 0; 96 } 97 } 98 if(*s != 0) 99 return 0; 100 if(op == '+' || op == '-') 101 mask &= mode; 102 if(op == '-') 103 mode = ~mode; 104 *pmask = mask; 105 *pmode = mode; 106 return 1; 107 } 108