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 CHRWE (CHREAD|CHWRITE|CHEXEC) 10 11 int parsemode(char *, ulong *, ulong *); 12 13 void 14 main(int argc, char *argv[]) 15 { 16 int i; 17 Dir dir; 18 ulong mode, mask; 19 char *p; 20 char err[ERRLEN]; 21 22 if(argc < 2){ 23 fprint(2, "usage: chmod 0777 file ... or chmod [who]op[rwxal] file ...\n"); 24 exits("usage"); 25 } 26 mode = strtol(argv[1], &p, 8); 27 if(*p == 0) 28 mask = A(CHRWE); 29 else if(!parsemode(argv[1], &mask, &mode)){ 30 fprint(2, "chmod: bad mode: %s\n", argv[1]); 31 exits("mode"); 32 } 33 for(i=2; i<argc; i++){ 34 if(dirstat(argv[i], &dir)==-1){ 35 errstr(err); 36 fprint(2, "chmod: can't stat %s: %s\n", argv[i], err); 37 continue; 38 } 39 dir.mode = (dir.mode & ~mask) | (mode & mask); 40 if(dirwstat(argv[i], &dir)==-1){ 41 errstr(err); 42 fprint(2, "chmod: can't wstat %s: %s\n", argv[i], err); 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 = CHAPPEND | CHEXCL; 58 for(done=0; !done; ){ 59 switch(*s){ 60 case 'u': 61 mask |= U(CHRWE); break; 62 case 'g': 63 mask |= G(CHRWE); break; 64 case 'o': 65 mask |= O(CHRWE); break; 66 case 'a': 67 mask |= A(CHRWE); 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(CHRWE); 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(CHREAD); break; 86 case 'w': 87 mode |= A(CHWRITE); break; 88 case 'x': 89 mode |= A(CHEXEC); break; 90 case 'a': 91 mode |= CHAPPEND; break; 92 case 'l': 93 mode |= CHEXCL; 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