[hackers] [sbase] symbolic chmod, thanks pancake || Connor Lane Smith

From: <hg_AT_suckless.org>
Date: Sat, 11 Jun 2011 01:30:14 +0200 (CEST)

changeset: 77:5306cfa4b08d
tag: tip
user: Connor Lane Smith <cls_AT_lubutu.com>
date: Sat Jun 11 00:30:07 2011 +0100
files: LICENSE chmod.1 chmod.c
description:
symbolic chmod, thanks pancake

diff -r ff08e2b697fe -r 5306cfa4b08d LICENSE
--- a/LICENSE Sat Jun 11 00:29:06 2011 +0100
+++ b/LICENSE Sat Jun 11 00:30:07 2011 +0100
@@ -5,6 +5,7 @@
 © 2011 stateless <stateless_AT_archlinux.us>
 © 2011 Rob Pilling <robpilling_AT_gmail.com>
 © 2011 Hiltjo Posthuma <hiltjo_AT_codemadness.org>
+© 2011 pancake <pancake_AT_youterm.com>
 
 Permission is hereby granted, free of charge, to any person obtaining a
 copy of this software and associated documentation files (the "Software"),
diff -r ff08e2b697fe -r 5306cfa4b08d chmod.1
--- a/chmod.1 Sat Jun 11 00:29:06 2011 +0100
+++ b/chmod.1 Sat Jun 11 00:30:07 2011 +0100
@@ -4,18 +4,65 @@
 .SH SYNOPSIS
 .B chmod
 .RB [ \-Rr ]
-.RI mode
+.I octal
+.RI [ file ...]
+.P
+.B chmod
+.RB [ \-Rr ]
+.RB [ ugoa ][ +-= ][ rwxs ]
 .RI [ file ...]
 .SH DESCRIPTION
 .B chmod
-changes the file mode for the given files. The
-.I mode
-is a four digit octal number derived from its comprising bits.
+changes the file mode for the given files.
 .P
-The first digit defines the setuid (4) and setgid (2) attributes. The second
-digit defines the owner's permissions: read (4), write (2), and execute (1); the
-third defines permissions for others in the file's group; and the fourth for all
-other users. Leading zeroes may be omitted.
+If the mode is an
+.I octal
+number, the modes are set according to that number's comprising bits. The first
+digit defines the setuid (4) and setgid (2) attributes. The second digit
+defines the owner's permissions: read (4), write (2), and execute (1); the third
+defines permissions for others in the file's group; and the fourth for all other
+users. Leading zeroes may be omitted.
+.P
+Alternatively the mode may be symbolic. The symbol meanings are:
+.TP
+.B u
+modifies owner permissions.
+.PD 0
+.TP
+.B g
+modifies group permissions.
+.TP
+.B o
+modifies other user permissions.
+.TP
+.B a
+modifies all user permissions.
+.PD
+.TP
+.B +
+adds the given permissions to the mode.
+.PD 0
+.TP
+.B -
+removes the given permissions from the mode.
+.TP
+.B =
+sets the mode to the given permissions.
+.PD
+.TP
+.B r
+read permissions.
+.PD 0
+.TP
+.B w
+write permissions.
+.TP
+.B x
+execute permissions.
+.TP
+.B s
+setuid and setgid attributes.
+.PD
 .SH OPTIONS
 .TP
 .B \-R, \-r
diff -r ff08e2b697fe -r 5306cfa4b08d chmod.c
--- a/chmod.c Sat Jun 11 00:29:06 2011 +0100
+++ b/chmod.c Sat Jun 11 00:30:07 2011 +0100
@@ -7,15 +7,16 @@
 #include "util.h"
 
 static void chmodr(const char *);
+static void parsemode(const char *);
 
 static bool rflag = false;
+static char oper = '=';
 static mode_t mode = 0;
 
 int
 main(int argc, char *argv[])
 {
         char c;
- int octal;
 
         while((c = getopt(argc, argv, "Rr")) != -1)
                 switch(c) {
@@ -28,21 +29,8 @@
                 }
         if(optind == argc)
                 eprintf("usage: %s [-Rr] mode [file...]\n", argv[0]);
- octal = estrtol(argv[optind++], 8);
 
- /* posix doesn't specify modal bits */
- if(octal & 04000) mode |= S_ISUID;
- if(octal & 02000) mode |= S_ISGID;
- if(octal & 00400) mode |= S_IRUSR;
- if(octal & 00200) mode |= S_IWUSR;
- if(octal & 00100) mode |= S_IXUSR;
- if(octal & 00040) mode |= S_IRGRP;
- if(octal & 00020) mode |= S_IWGRP;
- if(octal & 00010) mode |= S_IXGRP;
- if(octal & 00004) mode |= S_IROTH;
- if(octal & 00002) mode |= S_IWOTH;
- if(octal & 00001) mode |= S_IXOTH;
-
+ parsemode(argv[optind++]);
         for(; optind < argc; optind++)
                 chmodr(argv[optind]);
         return EXIT_SUCCESS;
@@ -51,8 +39,86 @@
 void
 chmodr(const char *path)
 {
- if(chmod(path, mode) == -1)
+ struct stat st;
+
+ if(stat(path, &st) == -1)
+ eprintf("stat %s:", path);
+
+ switch(oper) {
+ case '+':
+ st.st_mode |= mode;
+ break;
+ case '-':
+ st.st_mode &= ~mode;
+ break;
+ }
+ if(chmod(path, st.st_mode) == -1)
                 eprintf("chmod %s:", path);
         if(rflag)
                 recurse(path, chmodr);
 }
+
+void
+parsemode(const char *str)
+{
+ char *end;
+ const char *p;
+ int octal;
+ mode_t mask = 0;
+
+ octal = strtol(str, &end, 8);
+ if(*end == '\0') {
+ if(octal & 04000) mode |= S_ISUID;
+ if(octal & 02000) mode |= S_ISGID;
+ if(octal & 00400) mode |= S_IRUSR;
+ if(octal & 00200) mode |= S_IWUSR;
+ if(octal & 00100) mode |= S_IXUSR;
+ if(octal & 00040) mode |= S_IRGRP;
+ if(octal & 00020) mode |= S_IWGRP;
+ if(octal & 00010) mode |= S_IXGRP;
+ if(octal & 00004) mode |= S_IROTH;
+ if(octal & 00002) mode |= S_IWOTH;
+ if(octal & 00001) mode |= S_IXOTH;
+ return;
+ }
+ for(p = str; *p; p++)
+ switch(*p) {
+ /* masks */
+ case 'u':
+ mask |= S_IRWXU;
+ break;
+ case 'g':
+ mask |= S_IRWXG;
+ break;
+ case 'o':
+ mask |= S_IRWXO;
+ break;
+ case 'a':
+ mask |= S_IRWXU|S_IRWXG|S_IRWXO;
+ break;
+ /* opers */
+ case '+':
+ case '-':
+ case '=':
+ oper = *p;
+ break;
+ /* modes */
+ case 'r':
+ mode |= S_IRUSR|S_IRGRP|S_IROTH;
+ break;
+ case 'w':
+ mode |= S_IWUSR|S_IWGRP|S_IWOTH;
+ break;
+ case 'x':
+ mode |= S_IXUSR|S_IXGRP|S_IXOTH;
+ break;
+ case 's':
+ mode |= S_ISUID|S_ISGID;
+ break;
+ /* error */
+ default:
+ eprintf("%s: invalid mode\n", str);
+ }
+ if(mask)
+ mode &= mask;
+}
Received on Sat Jun 11 2011 - 01:30:14 CEST

This archive was generated by hypermail 2.2.0 : Sat Jun 11 2011 - 01:36:05 CEST