Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
}