110 lines
1.9 KiB
C
110 lines
1.9 KiB
C
#include <u.h>
|
|
#include <libc.h>
|
|
|
|
#define U(x) (x<<6)
|
|
#define G(x) (x<<3)
|
|
#define O(x) (x)
|
|
#define A(x) (U(x)|G(x)|O(x))
|
|
|
|
#define DMRWE (DMREAD|DMWRITE|DMEXEC)
|
|
|
|
int parsemode(char *, ulong *, ulong *);
|
|
|
|
void
|
|
main(int argc, char *argv[])
|
|
{
|
|
int i;
|
|
Dir *dir, ndir;
|
|
ulong mode, mask;
|
|
char *p;
|
|
|
|
if(argc < 3){
|
|
fprint(2, "usage: chmod 0777 file ... or chmod [who]op[rwxalt] file ...\n");
|
|
exits("usage");
|
|
}
|
|
mode = strtol(argv[1], &p, 8);
|
|
if(*p == 0)
|
|
mask = A(DMRWE);
|
|
else if(!parsemode(argv[1], &mask, &mode)){
|
|
fprint(2, "chmod: bad mode: %s\n", argv[1]);
|
|
exits("mode");
|
|
}
|
|
nulldir(&ndir);
|
|
for(i=2; i<argc; i++){
|
|
dir = dirstat(argv[i]);
|
|
if(dir == nil){
|
|
fprint(2, "chmod: can't stat %s: %r\n", argv[i]);
|
|
continue;
|
|
}
|
|
ndir.mode = (dir->mode & ~mask) | (mode & mask);
|
|
free(dir);
|
|
if(dirwstat(argv[i], &ndir)==-1){
|
|
fprint(2, "chmod: can't wstat %s: %r\n", argv[i]);
|
|
continue;
|
|
}
|
|
}
|
|
exits(0);
|
|
}
|
|
|
|
int
|
|
parsemode(char *spec, ulong *pmask, ulong *pmode)
|
|
{
|
|
ulong mode, mask;
|
|
int done, op;
|
|
char *s;
|
|
|
|
s = spec;
|
|
mask = DMAPPEND | DMEXCL | DMTMP;
|
|
for(done=0; !done; ){
|
|
switch(*s){
|
|
case 'u':
|
|
mask |= U(DMRWE); break;
|
|
case 'g':
|
|
mask |= G(DMRWE); break;
|
|
case 'o':
|
|
mask |= O(DMRWE); break;
|
|
case 'a':
|
|
mask |= A(DMRWE); break;
|
|
case 0:
|
|
return 0;
|
|
default:
|
|
done = 1;
|
|
}
|
|
if(!done)
|
|
s++;
|
|
}
|
|
if(s == spec)
|
|
mask |= A(DMRWE);
|
|
op = *s++;
|
|
if(op != '+' && op != '-' && op != '=')
|
|
return 0;
|
|
mode = 0;
|
|
for(; *s ; s++){
|
|
switch(*s){
|
|
case 'r':
|
|
mode |= A(DMREAD); break;
|
|
case 'w':
|
|
mode |= A(DMWRITE); break;
|
|
case 'x':
|
|
mode |= A(DMEXEC); break;
|
|
case 'a':
|
|
mode |= DMAPPEND; break;
|
|
case 'l':
|
|
mode |= DMEXCL; break;
|
|
case 't':
|
|
mode |= DMTMP; break;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
if(*s != 0)
|
|
return 0;
|
|
if(op == '+' || op == '-')
|
|
mask &= mode;
|
|
if(op == '-')
|
|
mode = ~mode;
|
|
*pmask = mask;
|
|
*pmode = mode;
|
|
return 1;
|
|
}
|