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