summaryrefslogtreecommitdiff
path: root/sys/src/cmd/chmod.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/chmod.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/chmod.c')
-rwxr-xr-xsys/src/cmd/chmod.c109
1 files changed, 109 insertions, 0 deletions
diff --git a/sys/src/cmd/chmod.c b/sys/src/cmd/chmod.c
new file mode 100755
index 000000000..425f8efce
--- /dev/null
+++ b/sys/src/cmd/chmod.c
@@ -0,0 +1,109 @@
+#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;
+}