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
main(int argc,char * argv[])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[rwxalt] 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
parsemode(char * spec,ulong * pmask,ulong * pmode)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 | DMTMP;
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 case 't':
95 mode |= DMTMP; break;
96 default:
97 return 0;
98 }
99 }
100 if(*s != 0)
101 return 0;
102 if(op == '+' || op == '-')
103 mask &= mode;
104 if(op == '-')
105 mode = ~mode;
106 *pmask = mask;
107 *pmode = mode;
108 return 1;
109 }
110