]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/chmod.c
libaml: fix gc bug, need to amltake()/amldrop() temporary buffer
[plan9front.git] / sys / src / cmd / chmod.c
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[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
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 }