sbase/libutil/mode.c

153 lines
2.7 KiB
C
Raw Normal View History

/* See LICENSE file for copyright and license details. */
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include "../util.h"
mode_t
getumask(void)
{
mode_t mask = umask(0);
umask(mask);
return mask;
}
mode_t
parsemode(const char *str, mode_t mode, mode_t mask)
{
char *end;
Fix symbolic mode parsing in parsemode I found quite a lot of bugs, so I ended up pretty much rewriting as I followed the spec¹. Now, it works as follows: - Determine a mask (who) of bits that can be modified for the subsequent operations. If none are specified, select all file mode bits. - In a loop, determine which operation (+, -, =) to apply. - If the next character is a permcopy (u, g, o), set the new permissions (perm) corresponding to the bits set in the user, group or other parts of the existing mode. - Otherwise, set the new permissions by looping through the next r, w, x, s, t characters. - Now, the set of bits we want to add or remove is (who & perm). Set or remove these bits according the the operation (first clearing the appropriate bits if the operation is =). - Continue from the top if the next character is a comma, otherwise, process the next operation. I tested this on some made up inputs, and I believe it is working correctly now: parsemode("g+w", 0644, 0), before: 0606, now: 0664, fixed parsemode("u+rx", 0222, 0), before: 0077, now: 0722, fixed parsemode("+x", 0644, 023), before: 0754, now: 0754, still works parsemode("+w", 0444, 022), before: 0644, now: 0644, still works parsemode("+w", 0444, 0), before: 0666, now: 0666, still works parsemode("+s", 0755, 0), before: 0755, now: 6755, fixed parsemode("u+s", 0755, 0), before: 0055, now: 4755, fixed parsemode("g+s", 0755, 0), before: 0705, now: 2755, fixed parsemode("g=u", 0700, 0), before: 0000, now: 0770, fixed parsemode("go=u-w", 0700, 0), before: 0000, now: 0755, fixed parsemode("o+u-g", 0641, 0), before: 0000, now: 0643, fixed parsemode("u=rx,o+w,g-r", 0654, 0) before: error, now: 0516, fixed parsemode(",", 0654, 0), before: error, now: error, still works ¹ http://pubs.opengroup.org/onlinepubs/9699919799/utilities/chmod.html
2014-11-02 17:24:52 -05:00
const char *p = str;
int octal, op;
mode_t who, perm, clear;
octal = strtol(str, &end, 8);
if (*end == '\0') {
if (octal < 0 || octal > 07777)
eprintf("%s: invalid mode\n", str);
return octal;
}
Fix symbolic mode parsing in parsemode I found quite a lot of bugs, so I ended up pretty much rewriting as I followed the spec¹. Now, it works as follows: - Determine a mask (who) of bits that can be modified for the subsequent operations. If none are specified, select all file mode bits. - In a loop, determine which operation (+, -, =) to apply. - If the next character is a permcopy (u, g, o), set the new permissions (perm) corresponding to the bits set in the user, group or other parts of the existing mode. - Otherwise, set the new permissions by looping through the next r, w, x, s, t characters. - Now, the set of bits we want to add or remove is (who & perm). Set or remove these bits according the the operation (first clearing the appropriate bits if the operation is =). - Continue from the top if the next character is a comma, otherwise, process the next operation. I tested this on some made up inputs, and I believe it is working correctly now: parsemode("g+w", 0644, 0), before: 0606, now: 0664, fixed parsemode("u+rx", 0222, 0), before: 0077, now: 0722, fixed parsemode("+x", 0644, 023), before: 0754, now: 0754, still works parsemode("+w", 0444, 022), before: 0644, now: 0644, still works parsemode("+w", 0444, 0), before: 0666, now: 0666, still works parsemode("+s", 0755, 0), before: 0755, now: 6755, fixed parsemode("u+s", 0755, 0), before: 0055, now: 4755, fixed parsemode("g+s", 0755, 0), before: 0705, now: 2755, fixed parsemode("g=u", 0700, 0), before: 0000, now: 0770, fixed parsemode("go=u-w", 0700, 0), before: 0000, now: 0755, fixed parsemode("o+u-g", 0641, 0), before: 0000, now: 0643, fixed parsemode("u=rx,o+w,g-r", 0654, 0) before: error, now: 0516, fixed parsemode(",", 0654, 0), before: error, now: error, still works ¹ http://pubs.opengroup.org/onlinepubs/9699919799/utilities/chmod.html
2014-11-02 17:24:52 -05:00
next:
/* first, determine which bits we will be modifying */
for (who = 0; *p; p++) {
switch (*p) {
/* masks */
case 'u':
Fix symbolic mode parsing in parsemode I found quite a lot of bugs, so I ended up pretty much rewriting as I followed the spec¹. Now, it works as follows: - Determine a mask (who) of bits that can be modified for the subsequent operations. If none are specified, select all file mode bits. - In a loop, determine which operation (+, -, =) to apply. - If the next character is a permcopy (u, g, o), set the new permissions (perm) corresponding to the bits set in the user, group or other parts of the existing mode. - Otherwise, set the new permissions by looping through the next r, w, x, s, t characters. - Now, the set of bits we want to add or remove is (who & perm). Set or remove these bits according the the operation (first clearing the appropriate bits if the operation is =). - Continue from the top if the next character is a comma, otherwise, process the next operation. I tested this on some made up inputs, and I believe it is working correctly now: parsemode("g+w", 0644, 0), before: 0606, now: 0664, fixed parsemode("u+rx", 0222, 0), before: 0077, now: 0722, fixed parsemode("+x", 0644, 023), before: 0754, now: 0754, still works parsemode("+w", 0444, 022), before: 0644, now: 0644, still works parsemode("+w", 0444, 0), before: 0666, now: 0666, still works parsemode("+s", 0755, 0), before: 0755, now: 6755, fixed parsemode("u+s", 0755, 0), before: 0055, now: 4755, fixed parsemode("g+s", 0755, 0), before: 0705, now: 2755, fixed parsemode("g=u", 0700, 0), before: 0000, now: 0770, fixed parsemode("go=u-w", 0700, 0), before: 0000, now: 0755, fixed parsemode("o+u-g", 0641, 0), before: 0000, now: 0643, fixed parsemode("u=rx,o+w,g-r", 0654, 0) before: error, now: 0516, fixed parsemode(",", 0654, 0), before: error, now: error, still works ¹ http://pubs.opengroup.org/onlinepubs/9699919799/utilities/chmod.html
2014-11-02 17:24:52 -05:00
who |= S_IRWXU|S_ISUID;
continue;
case 'g':
Fix symbolic mode parsing in parsemode I found quite a lot of bugs, so I ended up pretty much rewriting as I followed the spec¹. Now, it works as follows: - Determine a mask (who) of bits that can be modified for the subsequent operations. If none are specified, select all file mode bits. - In a loop, determine which operation (+, -, =) to apply. - If the next character is a permcopy (u, g, o), set the new permissions (perm) corresponding to the bits set in the user, group or other parts of the existing mode. - Otherwise, set the new permissions by looping through the next r, w, x, s, t characters. - Now, the set of bits we want to add or remove is (who & perm). Set or remove these bits according the the operation (first clearing the appropriate bits if the operation is =). - Continue from the top if the next character is a comma, otherwise, process the next operation. I tested this on some made up inputs, and I believe it is working correctly now: parsemode("g+w", 0644, 0), before: 0606, now: 0664, fixed parsemode("u+rx", 0222, 0), before: 0077, now: 0722, fixed parsemode("+x", 0644, 023), before: 0754, now: 0754, still works parsemode("+w", 0444, 022), before: 0644, now: 0644, still works parsemode("+w", 0444, 0), before: 0666, now: 0666, still works parsemode("+s", 0755, 0), before: 0755, now: 6755, fixed parsemode("u+s", 0755, 0), before: 0055, now: 4755, fixed parsemode("g+s", 0755, 0), before: 0705, now: 2755, fixed parsemode("g=u", 0700, 0), before: 0000, now: 0770, fixed parsemode("go=u-w", 0700, 0), before: 0000, now: 0755, fixed parsemode("o+u-g", 0641, 0), before: 0000, now: 0643, fixed parsemode("u=rx,o+w,g-r", 0654, 0) before: error, now: 0516, fixed parsemode(",", 0654, 0), before: error, now: error, still works ¹ http://pubs.opengroup.org/onlinepubs/9699919799/utilities/chmod.html
2014-11-02 17:24:52 -05:00
who |= S_IRWXG|S_ISGID;
continue;
case 'o':
Fix symbolic mode parsing in parsemode I found quite a lot of bugs, so I ended up pretty much rewriting as I followed the spec¹. Now, it works as follows: - Determine a mask (who) of bits that can be modified for the subsequent operations. If none are specified, select all file mode bits. - In a loop, determine which operation (+, -, =) to apply. - If the next character is a permcopy (u, g, o), set the new permissions (perm) corresponding to the bits set in the user, group or other parts of the existing mode. - Otherwise, set the new permissions by looping through the next r, w, x, s, t characters. - Now, the set of bits we want to add or remove is (who & perm). Set or remove these bits according the the operation (first clearing the appropriate bits if the operation is =). - Continue from the top if the next character is a comma, otherwise, process the next operation. I tested this on some made up inputs, and I believe it is working correctly now: parsemode("g+w", 0644, 0), before: 0606, now: 0664, fixed parsemode("u+rx", 0222, 0), before: 0077, now: 0722, fixed parsemode("+x", 0644, 023), before: 0754, now: 0754, still works parsemode("+w", 0444, 022), before: 0644, now: 0644, still works parsemode("+w", 0444, 0), before: 0666, now: 0666, still works parsemode("+s", 0755, 0), before: 0755, now: 6755, fixed parsemode("u+s", 0755, 0), before: 0055, now: 4755, fixed parsemode("g+s", 0755, 0), before: 0705, now: 2755, fixed parsemode("g=u", 0700, 0), before: 0000, now: 0770, fixed parsemode("go=u-w", 0700, 0), before: 0000, now: 0755, fixed parsemode("o+u-g", 0641, 0), before: 0000, now: 0643, fixed parsemode("u=rx,o+w,g-r", 0654, 0) before: error, now: 0516, fixed parsemode(",", 0654, 0), before: error, now: error, still works ¹ http://pubs.opengroup.org/onlinepubs/9699919799/utilities/chmod.html
2014-11-02 17:24:52 -05:00
who |= S_IRWXO;
continue;
case 'a':
Fix symbolic mode parsing in parsemode I found quite a lot of bugs, so I ended up pretty much rewriting as I followed the spec¹. Now, it works as follows: - Determine a mask (who) of bits that can be modified for the subsequent operations. If none are specified, select all file mode bits. - In a loop, determine which operation (+, -, =) to apply. - If the next character is a permcopy (u, g, o), set the new permissions (perm) corresponding to the bits set in the user, group or other parts of the existing mode. - Otherwise, set the new permissions by looping through the next r, w, x, s, t characters. - Now, the set of bits we want to add or remove is (who & perm). Set or remove these bits according the the operation (first clearing the appropriate bits if the operation is =). - Continue from the top if the next character is a comma, otherwise, process the next operation. I tested this on some made up inputs, and I believe it is working correctly now: parsemode("g+w", 0644, 0), before: 0606, now: 0664, fixed parsemode("u+rx", 0222, 0), before: 0077, now: 0722, fixed parsemode("+x", 0644, 023), before: 0754, now: 0754, still works parsemode("+w", 0444, 022), before: 0644, now: 0644, still works parsemode("+w", 0444, 0), before: 0666, now: 0666, still works parsemode("+s", 0755, 0), before: 0755, now: 6755, fixed parsemode("u+s", 0755, 0), before: 0055, now: 4755, fixed parsemode("g+s", 0755, 0), before: 0705, now: 2755, fixed parsemode("g=u", 0700, 0), before: 0000, now: 0770, fixed parsemode("go=u-w", 0700, 0), before: 0000, now: 0755, fixed parsemode("o+u-g", 0641, 0), before: 0000, now: 0643, fixed parsemode("u=rx,o+w,g-r", 0654, 0) before: error, now: 0516, fixed parsemode(",", 0654, 0), before: error, now: error, still works ¹ http://pubs.opengroup.org/onlinepubs/9699919799/utilities/chmod.html
2014-11-02 17:24:52 -05:00
who |= S_IRWXU|S_ISUID|S_IRWXG|S_ISGID|S_IRWXO;
continue;
}
break;
}
if (who) {
Fix symbolic mode parsing in parsemode I found quite a lot of bugs, so I ended up pretty much rewriting as I followed the spec¹. Now, it works as follows: - Determine a mask (who) of bits that can be modified for the subsequent operations. If none are specified, select all file mode bits. - In a loop, determine which operation (+, -, =) to apply. - If the next character is a permcopy (u, g, o), set the new permissions (perm) corresponding to the bits set in the user, group or other parts of the existing mode. - Otherwise, set the new permissions by looping through the next r, w, x, s, t characters. - Now, the set of bits we want to add or remove is (who & perm). Set or remove these bits according the the operation (first clearing the appropriate bits if the operation is =). - Continue from the top if the next character is a comma, otherwise, process the next operation. I tested this on some made up inputs, and I believe it is working correctly now: parsemode("g+w", 0644, 0), before: 0606, now: 0664, fixed parsemode("u+rx", 0222, 0), before: 0077, now: 0722, fixed parsemode("+x", 0644, 023), before: 0754, now: 0754, still works parsemode("+w", 0444, 022), before: 0644, now: 0644, still works parsemode("+w", 0444, 0), before: 0666, now: 0666, still works parsemode("+s", 0755, 0), before: 0755, now: 6755, fixed parsemode("u+s", 0755, 0), before: 0055, now: 4755, fixed parsemode("g+s", 0755, 0), before: 0705, now: 2755, fixed parsemode("g=u", 0700, 0), before: 0000, now: 0770, fixed parsemode("go=u-w", 0700, 0), before: 0000, now: 0755, fixed parsemode("o+u-g", 0641, 0), before: 0000, now: 0643, fixed parsemode("u=rx,o+w,g-r", 0654, 0) before: error, now: 0516, fixed parsemode(",", 0654, 0), before: error, now: error, still works ¹ http://pubs.opengroup.org/onlinepubs/9699919799/utilities/chmod.html
2014-11-02 17:24:52 -05:00
clear = who;
} else {
clear = S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO;
who = ~mask;
}
while (*p) {
switch (*p) {
/* opers */
case '=':
case '+':
case '-':
op = (int)*p;
break;
Fix symbolic mode parsing in parsemode I found quite a lot of bugs, so I ended up pretty much rewriting as I followed the spec¹. Now, it works as follows: - Determine a mask (who) of bits that can be modified for the subsequent operations. If none are specified, select all file mode bits. - In a loop, determine which operation (+, -, =) to apply. - If the next character is a permcopy (u, g, o), set the new permissions (perm) corresponding to the bits set in the user, group or other parts of the existing mode. - Otherwise, set the new permissions by looping through the next r, w, x, s, t characters. - Now, the set of bits we want to add or remove is (who & perm). Set or remove these bits according the the operation (first clearing the appropriate bits if the operation is =). - Continue from the top if the next character is a comma, otherwise, process the next operation. I tested this on some made up inputs, and I believe it is working correctly now: parsemode("g+w", 0644, 0), before: 0606, now: 0664, fixed parsemode("u+rx", 0222, 0), before: 0077, now: 0722, fixed parsemode("+x", 0644, 023), before: 0754, now: 0754, still works parsemode("+w", 0444, 022), before: 0644, now: 0644, still works parsemode("+w", 0444, 0), before: 0666, now: 0666, still works parsemode("+s", 0755, 0), before: 0755, now: 6755, fixed parsemode("u+s", 0755, 0), before: 0055, now: 4755, fixed parsemode("g+s", 0755, 0), before: 0705, now: 2755, fixed parsemode("g=u", 0700, 0), before: 0000, now: 0770, fixed parsemode("go=u-w", 0700, 0), before: 0000, now: 0755, fixed parsemode("o+u-g", 0641, 0), before: 0000, now: 0643, fixed parsemode("u=rx,o+w,g-r", 0654, 0) before: error, now: 0516, fixed parsemode(",", 0654, 0), before: error, now: error, still works ¹ http://pubs.opengroup.org/onlinepubs/9699919799/utilities/chmod.html
2014-11-02 17:24:52 -05:00
default:
eprintf("%s: invalid mode\n", str);
}
perm = 0;
switch (*++p) {
Fix symbolic mode parsing in parsemode I found quite a lot of bugs, so I ended up pretty much rewriting as I followed the spec¹. Now, it works as follows: - Determine a mask (who) of bits that can be modified for the subsequent operations. If none are specified, select all file mode bits. - In a loop, determine which operation (+, -, =) to apply. - If the next character is a permcopy (u, g, o), set the new permissions (perm) corresponding to the bits set in the user, group or other parts of the existing mode. - Otherwise, set the new permissions by looping through the next r, w, x, s, t characters. - Now, the set of bits we want to add or remove is (who & perm). Set or remove these bits according the the operation (first clearing the appropriate bits if the operation is =). - Continue from the top if the next character is a comma, otherwise, process the next operation. I tested this on some made up inputs, and I believe it is working correctly now: parsemode("g+w", 0644, 0), before: 0606, now: 0664, fixed parsemode("u+rx", 0222, 0), before: 0077, now: 0722, fixed parsemode("+x", 0644, 023), before: 0754, now: 0754, still works parsemode("+w", 0444, 022), before: 0644, now: 0644, still works parsemode("+w", 0444, 0), before: 0666, now: 0666, still works parsemode("+s", 0755, 0), before: 0755, now: 6755, fixed parsemode("u+s", 0755, 0), before: 0055, now: 4755, fixed parsemode("g+s", 0755, 0), before: 0705, now: 2755, fixed parsemode("g=u", 0700, 0), before: 0000, now: 0770, fixed parsemode("go=u-w", 0700, 0), before: 0000, now: 0755, fixed parsemode("o+u-g", 0641, 0), before: 0000, now: 0643, fixed parsemode("u=rx,o+w,g-r", 0654, 0) before: error, now: 0516, fixed parsemode(",", 0654, 0), before: error, now: error, still works ¹ http://pubs.opengroup.org/onlinepubs/9699919799/utilities/chmod.html
2014-11-02 17:24:52 -05:00
/* copy */
case 'u':
if (mode & S_IRUSR)
2014-11-09 14:22:49 -05:00
perm |= S_IRUSR|S_IRGRP|S_IROTH;
if (mode & S_IWUSR)
2014-11-09 14:22:49 -05:00
perm |= S_IWUSR|S_IWGRP|S_IWOTH;
if (mode & S_IXUSR)
2014-11-09 14:22:49 -05:00
perm |= S_IXUSR|S_IXGRP|S_IXOTH;
if (mode & S_ISUID)
2014-11-09 14:22:49 -05:00
perm |= S_ISUID|S_ISGID;
Fix symbolic mode parsing in parsemode I found quite a lot of bugs, so I ended up pretty much rewriting as I followed the spec¹. Now, it works as follows: - Determine a mask (who) of bits that can be modified for the subsequent operations. If none are specified, select all file mode bits. - In a loop, determine which operation (+, -, =) to apply. - If the next character is a permcopy (u, g, o), set the new permissions (perm) corresponding to the bits set in the user, group or other parts of the existing mode. - Otherwise, set the new permissions by looping through the next r, w, x, s, t characters. - Now, the set of bits we want to add or remove is (who & perm). Set or remove these bits according the the operation (first clearing the appropriate bits if the operation is =). - Continue from the top if the next character is a comma, otherwise, process the next operation. I tested this on some made up inputs, and I believe it is working correctly now: parsemode("g+w", 0644, 0), before: 0606, now: 0664, fixed parsemode("u+rx", 0222, 0), before: 0077, now: 0722, fixed parsemode("+x", 0644, 023), before: 0754, now: 0754, still works parsemode("+w", 0444, 022), before: 0644, now: 0644, still works parsemode("+w", 0444, 0), before: 0666, now: 0666, still works parsemode("+s", 0755, 0), before: 0755, now: 6755, fixed parsemode("u+s", 0755, 0), before: 0055, now: 4755, fixed parsemode("g+s", 0755, 0), before: 0705, now: 2755, fixed parsemode("g=u", 0700, 0), before: 0000, now: 0770, fixed parsemode("go=u-w", 0700, 0), before: 0000, now: 0755, fixed parsemode("o+u-g", 0641, 0), before: 0000, now: 0643, fixed parsemode("u=rx,o+w,g-r", 0654, 0) before: error, now: 0516, fixed parsemode(",", 0654, 0), before: error, now: error, still works ¹ http://pubs.opengroup.org/onlinepubs/9699919799/utilities/chmod.html
2014-11-02 17:24:52 -05:00
p++;
break;
Fix symbolic mode parsing in parsemode I found quite a lot of bugs, so I ended up pretty much rewriting as I followed the spec¹. Now, it works as follows: - Determine a mask (who) of bits that can be modified for the subsequent operations. If none are specified, select all file mode bits. - In a loop, determine which operation (+, -, =) to apply. - If the next character is a permcopy (u, g, o), set the new permissions (perm) corresponding to the bits set in the user, group or other parts of the existing mode. - Otherwise, set the new permissions by looping through the next r, w, x, s, t characters. - Now, the set of bits we want to add or remove is (who & perm). Set or remove these bits according the the operation (first clearing the appropriate bits if the operation is =). - Continue from the top if the next character is a comma, otherwise, process the next operation. I tested this on some made up inputs, and I believe it is working correctly now: parsemode("g+w", 0644, 0), before: 0606, now: 0664, fixed parsemode("u+rx", 0222, 0), before: 0077, now: 0722, fixed parsemode("+x", 0644, 023), before: 0754, now: 0754, still works parsemode("+w", 0444, 022), before: 0644, now: 0644, still works parsemode("+w", 0444, 0), before: 0666, now: 0666, still works parsemode("+s", 0755, 0), before: 0755, now: 6755, fixed parsemode("u+s", 0755, 0), before: 0055, now: 4755, fixed parsemode("g+s", 0755, 0), before: 0705, now: 2755, fixed parsemode("g=u", 0700, 0), before: 0000, now: 0770, fixed parsemode("go=u-w", 0700, 0), before: 0000, now: 0755, fixed parsemode("o+u-g", 0641, 0), before: 0000, now: 0643, fixed parsemode("u=rx,o+w,g-r", 0654, 0) before: error, now: 0516, fixed parsemode(",", 0654, 0), before: error, now: error, still works ¹ http://pubs.opengroup.org/onlinepubs/9699919799/utilities/chmod.html
2014-11-02 17:24:52 -05:00
case 'g':
if (mode & S_IRGRP)
2014-11-09 14:22:49 -05:00
perm |= S_IRUSR|S_IRGRP|S_IROTH;
if (mode & S_IWGRP)
2014-11-09 14:22:49 -05:00
perm |= S_IWUSR|S_IWGRP|S_IWOTH;
if (mode & S_IXGRP)
2014-11-09 14:22:49 -05:00
perm |= S_IXUSR|S_IXGRP|S_IXOTH;
if (mode & S_ISGID)
2014-11-09 14:22:49 -05:00
perm |= S_ISUID|S_ISGID;
Fix symbolic mode parsing in parsemode I found quite a lot of bugs, so I ended up pretty much rewriting as I followed the spec¹. Now, it works as follows: - Determine a mask (who) of bits that can be modified for the subsequent operations. If none are specified, select all file mode bits. - In a loop, determine which operation (+, -, =) to apply. - If the next character is a permcopy (u, g, o), set the new permissions (perm) corresponding to the bits set in the user, group or other parts of the existing mode. - Otherwise, set the new permissions by looping through the next r, w, x, s, t characters. - Now, the set of bits we want to add or remove is (who & perm). Set or remove these bits according the the operation (first clearing the appropriate bits if the operation is =). - Continue from the top if the next character is a comma, otherwise, process the next operation. I tested this on some made up inputs, and I believe it is working correctly now: parsemode("g+w", 0644, 0), before: 0606, now: 0664, fixed parsemode("u+rx", 0222, 0), before: 0077, now: 0722, fixed parsemode("+x", 0644, 023), before: 0754, now: 0754, still works parsemode("+w", 0444, 022), before: 0644, now: 0644, still works parsemode("+w", 0444, 0), before: 0666, now: 0666, still works parsemode("+s", 0755, 0), before: 0755, now: 6755, fixed parsemode("u+s", 0755, 0), before: 0055, now: 4755, fixed parsemode("g+s", 0755, 0), before: 0705, now: 2755, fixed parsemode("g=u", 0700, 0), before: 0000, now: 0770, fixed parsemode("go=u-w", 0700, 0), before: 0000, now: 0755, fixed parsemode("o+u-g", 0641, 0), before: 0000, now: 0643, fixed parsemode("u=rx,o+w,g-r", 0654, 0) before: error, now: 0516, fixed parsemode(",", 0654, 0), before: error, now: error, still works ¹ http://pubs.opengroup.org/onlinepubs/9699919799/utilities/chmod.html
2014-11-02 17:24:52 -05:00
p++;
break;
Fix symbolic mode parsing in parsemode I found quite a lot of bugs, so I ended up pretty much rewriting as I followed the spec¹. Now, it works as follows: - Determine a mask (who) of bits that can be modified for the subsequent operations. If none are specified, select all file mode bits. - In a loop, determine which operation (+, -, =) to apply. - If the next character is a permcopy (u, g, o), set the new permissions (perm) corresponding to the bits set in the user, group or other parts of the existing mode. - Otherwise, set the new permissions by looping through the next r, w, x, s, t characters. - Now, the set of bits we want to add or remove is (who & perm). Set or remove these bits according the the operation (first clearing the appropriate bits if the operation is =). - Continue from the top if the next character is a comma, otherwise, process the next operation. I tested this on some made up inputs, and I believe it is working correctly now: parsemode("g+w", 0644, 0), before: 0606, now: 0664, fixed parsemode("u+rx", 0222, 0), before: 0077, now: 0722, fixed parsemode("+x", 0644, 023), before: 0754, now: 0754, still works parsemode("+w", 0444, 022), before: 0644, now: 0644, still works parsemode("+w", 0444, 0), before: 0666, now: 0666, still works parsemode("+s", 0755, 0), before: 0755, now: 6755, fixed parsemode("u+s", 0755, 0), before: 0055, now: 4755, fixed parsemode("g+s", 0755, 0), before: 0705, now: 2755, fixed parsemode("g=u", 0700, 0), before: 0000, now: 0770, fixed parsemode("go=u-w", 0700, 0), before: 0000, now: 0755, fixed parsemode("o+u-g", 0641, 0), before: 0000, now: 0643, fixed parsemode("u=rx,o+w,g-r", 0654, 0) before: error, now: 0516, fixed parsemode(",", 0654, 0), before: error, now: error, still works ¹ http://pubs.opengroup.org/onlinepubs/9699919799/utilities/chmod.html
2014-11-02 17:24:52 -05:00
case 'o':
if (mode & S_IROTH)
2014-11-09 14:22:49 -05:00
perm |= S_IRUSR|S_IRGRP|S_IROTH;
if (mode & S_IWOTH)
2014-11-09 14:22:49 -05:00
perm |= S_IWUSR|S_IWGRP|S_IWOTH;
if (mode & S_IXOTH)
2014-11-09 14:22:49 -05:00
perm |= S_IXUSR|S_IXGRP|S_IXOTH;
Fix symbolic mode parsing in parsemode I found quite a lot of bugs, so I ended up pretty much rewriting as I followed the spec¹. Now, it works as follows: - Determine a mask (who) of bits that can be modified for the subsequent operations. If none are specified, select all file mode bits. - In a loop, determine which operation (+, -, =) to apply. - If the next character is a permcopy (u, g, o), set the new permissions (perm) corresponding to the bits set in the user, group or other parts of the existing mode. - Otherwise, set the new permissions by looping through the next r, w, x, s, t characters. - Now, the set of bits we want to add or remove is (who & perm). Set or remove these bits according the the operation (first clearing the appropriate bits if the operation is =). - Continue from the top if the next character is a comma, otherwise, process the next operation. I tested this on some made up inputs, and I believe it is working correctly now: parsemode("g+w", 0644, 0), before: 0606, now: 0664, fixed parsemode("u+rx", 0222, 0), before: 0077, now: 0722, fixed parsemode("+x", 0644, 023), before: 0754, now: 0754, still works parsemode("+w", 0444, 022), before: 0644, now: 0644, still works parsemode("+w", 0444, 0), before: 0666, now: 0666, still works parsemode("+s", 0755, 0), before: 0755, now: 6755, fixed parsemode("u+s", 0755, 0), before: 0055, now: 4755, fixed parsemode("g+s", 0755, 0), before: 0705, now: 2755, fixed parsemode("g=u", 0700, 0), before: 0000, now: 0770, fixed parsemode("go=u-w", 0700, 0), before: 0000, now: 0755, fixed parsemode("o+u-g", 0641, 0), before: 0000, now: 0643, fixed parsemode("u=rx,o+w,g-r", 0654, 0) before: error, now: 0516, fixed parsemode(",", 0654, 0), before: error, now: error, still works ¹ http://pubs.opengroup.org/onlinepubs/9699919799/utilities/chmod.html
2014-11-02 17:24:52 -05:00
p++;
break;
default:
for (; *p; p++) {
switch (*p) {
Fix symbolic mode parsing in parsemode I found quite a lot of bugs, so I ended up pretty much rewriting as I followed the spec¹. Now, it works as follows: - Determine a mask (who) of bits that can be modified for the subsequent operations. If none are specified, select all file mode bits. - In a loop, determine which operation (+, -, =) to apply. - If the next character is a permcopy (u, g, o), set the new permissions (perm) corresponding to the bits set in the user, group or other parts of the existing mode. - Otherwise, set the new permissions by looping through the next r, w, x, s, t characters. - Now, the set of bits we want to add or remove is (who & perm). Set or remove these bits according the the operation (first clearing the appropriate bits if the operation is =). - Continue from the top if the next character is a comma, otherwise, process the next operation. I tested this on some made up inputs, and I believe it is working correctly now: parsemode("g+w", 0644, 0), before: 0606, now: 0664, fixed parsemode("u+rx", 0222, 0), before: 0077, now: 0722, fixed parsemode("+x", 0644, 023), before: 0754, now: 0754, still works parsemode("+w", 0444, 022), before: 0644, now: 0644, still works parsemode("+w", 0444, 0), before: 0666, now: 0666, still works parsemode("+s", 0755, 0), before: 0755, now: 6755, fixed parsemode("u+s", 0755, 0), before: 0055, now: 4755, fixed parsemode("g+s", 0755, 0), before: 0705, now: 2755, fixed parsemode("g=u", 0700, 0), before: 0000, now: 0770, fixed parsemode("go=u-w", 0700, 0), before: 0000, now: 0755, fixed parsemode("o+u-g", 0641, 0), before: 0000, now: 0643, fixed parsemode("u=rx,o+w,g-r", 0654, 0) before: error, now: 0516, fixed parsemode(",", 0654, 0), before: error, now: error, still works ¹ http://pubs.opengroup.org/onlinepubs/9699919799/utilities/chmod.html
2014-11-02 17:24:52 -05:00
/* modes */
case 'r':
perm |= S_IRUSR|S_IRGRP|S_IROTH;
break;
case 'w':
perm |= S_IWUSR|S_IWGRP|S_IWOTH;
break;
case 'x':
perm |= S_IXUSR|S_IXGRP|S_IXOTH;
break;
case 'X':
if (S_ISDIR(mode) || mode & (S_IXUSR|S_IXGRP|S_IXOTH))
perm |= S_IXUSR|S_IXGRP|S_IXOTH;
break;
Fix symbolic mode parsing in parsemode I found quite a lot of bugs, so I ended up pretty much rewriting as I followed the spec¹. Now, it works as follows: - Determine a mask (who) of bits that can be modified for the subsequent operations. If none are specified, select all file mode bits. - In a loop, determine which operation (+, -, =) to apply. - If the next character is a permcopy (u, g, o), set the new permissions (perm) corresponding to the bits set in the user, group or other parts of the existing mode. - Otherwise, set the new permissions by looping through the next r, w, x, s, t characters. - Now, the set of bits we want to add or remove is (who & perm). Set or remove these bits according the the operation (first clearing the appropriate bits if the operation is =). - Continue from the top if the next character is a comma, otherwise, process the next operation. I tested this on some made up inputs, and I believe it is working correctly now: parsemode("g+w", 0644, 0), before: 0606, now: 0664, fixed parsemode("u+rx", 0222, 0), before: 0077, now: 0722, fixed parsemode("+x", 0644, 023), before: 0754, now: 0754, still works parsemode("+w", 0444, 022), before: 0644, now: 0644, still works parsemode("+w", 0444, 0), before: 0666, now: 0666, still works parsemode("+s", 0755, 0), before: 0755, now: 6755, fixed parsemode("u+s", 0755, 0), before: 0055, now: 4755, fixed parsemode("g+s", 0755, 0), before: 0705, now: 2755, fixed parsemode("g=u", 0700, 0), before: 0000, now: 0770, fixed parsemode("go=u-w", 0700, 0), before: 0000, now: 0755, fixed parsemode("o+u-g", 0641, 0), before: 0000, now: 0643, fixed parsemode("u=rx,o+w,g-r", 0654, 0) before: error, now: 0516, fixed parsemode(",", 0654, 0), before: error, now: error, still works ¹ http://pubs.opengroup.org/onlinepubs/9699919799/utilities/chmod.html
2014-11-02 17:24:52 -05:00
case 's':
perm |= S_ISUID|S_ISGID;
break;
case 't':
perm |= S_ISVTX;
break;
default:
goto apply;
}
}
}
Fix symbolic mode parsing in parsemode I found quite a lot of bugs, so I ended up pretty much rewriting as I followed the spec¹. Now, it works as follows: - Determine a mask (who) of bits that can be modified for the subsequent operations. If none are specified, select all file mode bits. - In a loop, determine which operation (+, -, =) to apply. - If the next character is a permcopy (u, g, o), set the new permissions (perm) corresponding to the bits set in the user, group or other parts of the existing mode. - Otherwise, set the new permissions by looping through the next r, w, x, s, t characters. - Now, the set of bits we want to add or remove is (who & perm). Set or remove these bits according the the operation (first clearing the appropriate bits if the operation is =). - Continue from the top if the next character is a comma, otherwise, process the next operation. I tested this on some made up inputs, and I believe it is working correctly now: parsemode("g+w", 0644, 0), before: 0606, now: 0664, fixed parsemode("u+rx", 0222, 0), before: 0077, now: 0722, fixed parsemode("+x", 0644, 023), before: 0754, now: 0754, still works parsemode("+w", 0444, 022), before: 0644, now: 0644, still works parsemode("+w", 0444, 0), before: 0666, now: 0666, still works parsemode("+s", 0755, 0), before: 0755, now: 6755, fixed parsemode("u+s", 0755, 0), before: 0055, now: 4755, fixed parsemode("g+s", 0755, 0), before: 0705, now: 2755, fixed parsemode("g=u", 0700, 0), before: 0000, now: 0770, fixed parsemode("go=u-w", 0700, 0), before: 0000, now: 0755, fixed parsemode("o+u-g", 0641, 0), before: 0000, now: 0643, fixed parsemode("u=rx,o+w,g-r", 0654, 0) before: error, now: 0516, fixed parsemode(",", 0654, 0), before: error, now: error, still works ¹ http://pubs.opengroup.org/onlinepubs/9699919799/utilities/chmod.html
2014-11-02 17:24:52 -05:00
2015-12-21 04:54:33 -05:00
apply:
/* apply */
switch (op) {
Fix symbolic mode parsing in parsemode I found quite a lot of bugs, so I ended up pretty much rewriting as I followed the spec¹. Now, it works as follows: - Determine a mask (who) of bits that can be modified for the subsequent operations. If none are specified, select all file mode bits. - In a loop, determine which operation (+, -, =) to apply. - If the next character is a permcopy (u, g, o), set the new permissions (perm) corresponding to the bits set in the user, group or other parts of the existing mode. - Otherwise, set the new permissions by looping through the next r, w, x, s, t characters. - Now, the set of bits we want to add or remove is (who & perm). Set or remove these bits according the the operation (first clearing the appropriate bits if the operation is =). - Continue from the top if the next character is a comma, otherwise, process the next operation. I tested this on some made up inputs, and I believe it is working correctly now: parsemode("g+w", 0644, 0), before: 0606, now: 0664, fixed parsemode("u+rx", 0222, 0), before: 0077, now: 0722, fixed parsemode("+x", 0644, 023), before: 0754, now: 0754, still works parsemode("+w", 0444, 022), before: 0644, now: 0644, still works parsemode("+w", 0444, 0), before: 0666, now: 0666, still works parsemode("+s", 0755, 0), before: 0755, now: 6755, fixed parsemode("u+s", 0755, 0), before: 0055, now: 4755, fixed parsemode("g+s", 0755, 0), before: 0705, now: 2755, fixed parsemode("g=u", 0700, 0), before: 0000, now: 0770, fixed parsemode("go=u-w", 0700, 0), before: 0000, now: 0755, fixed parsemode("o+u-g", 0641, 0), before: 0000, now: 0643, fixed parsemode("u=rx,o+w,g-r", 0654, 0) before: error, now: 0516, fixed parsemode(",", 0654, 0), before: error, now: error, still works ¹ http://pubs.opengroup.org/onlinepubs/9699919799/utilities/chmod.html
2014-11-02 17:24:52 -05:00
case '=':
mode &= ~clear;
/* fallthrough */
case '+':
Fix symbolic mode parsing in parsemode I found quite a lot of bugs, so I ended up pretty much rewriting as I followed the spec¹. Now, it works as follows: - Determine a mask (who) of bits that can be modified for the subsequent operations. If none are specified, select all file mode bits. - In a loop, determine which operation (+, -, =) to apply. - If the next character is a permcopy (u, g, o), set the new permissions (perm) corresponding to the bits set in the user, group or other parts of the existing mode. - Otherwise, set the new permissions by looping through the next r, w, x, s, t characters. - Now, the set of bits we want to add or remove is (who & perm). Set or remove these bits according the the operation (first clearing the appropriate bits if the operation is =). - Continue from the top if the next character is a comma, otherwise, process the next operation. I tested this on some made up inputs, and I believe it is working correctly now: parsemode("g+w", 0644, 0), before: 0606, now: 0664, fixed parsemode("u+rx", 0222, 0), before: 0077, now: 0722, fixed parsemode("+x", 0644, 023), before: 0754, now: 0754, still works parsemode("+w", 0444, 022), before: 0644, now: 0644, still works parsemode("+w", 0444, 0), before: 0666, now: 0666, still works parsemode("+s", 0755, 0), before: 0755, now: 6755, fixed parsemode("u+s", 0755, 0), before: 0055, now: 4755, fixed parsemode("g+s", 0755, 0), before: 0705, now: 2755, fixed parsemode("g=u", 0700, 0), before: 0000, now: 0770, fixed parsemode("go=u-w", 0700, 0), before: 0000, now: 0755, fixed parsemode("o+u-g", 0641, 0), before: 0000, now: 0643, fixed parsemode("u=rx,o+w,g-r", 0654, 0) before: error, now: 0516, fixed parsemode(",", 0654, 0), before: error, now: error, still works ¹ http://pubs.opengroup.org/onlinepubs/9699919799/utilities/chmod.html
2014-11-02 17:24:52 -05:00
mode |= perm & who;
break;
case '-':
Fix symbolic mode parsing in parsemode I found quite a lot of bugs, so I ended up pretty much rewriting as I followed the spec¹. Now, it works as follows: - Determine a mask (who) of bits that can be modified for the subsequent operations. If none are specified, select all file mode bits. - In a loop, determine which operation (+, -, =) to apply. - If the next character is a permcopy (u, g, o), set the new permissions (perm) corresponding to the bits set in the user, group or other parts of the existing mode. - Otherwise, set the new permissions by looping through the next r, w, x, s, t characters. - Now, the set of bits we want to add or remove is (who & perm). Set or remove these bits according the the operation (first clearing the appropriate bits if the operation is =). - Continue from the top if the next character is a comma, otherwise, process the next operation. I tested this on some made up inputs, and I believe it is working correctly now: parsemode("g+w", 0644, 0), before: 0606, now: 0664, fixed parsemode("u+rx", 0222, 0), before: 0077, now: 0722, fixed parsemode("+x", 0644, 023), before: 0754, now: 0754, still works parsemode("+w", 0444, 022), before: 0644, now: 0644, still works parsemode("+w", 0444, 0), before: 0666, now: 0666, still works parsemode("+s", 0755, 0), before: 0755, now: 6755, fixed parsemode("u+s", 0755, 0), before: 0055, now: 4755, fixed parsemode("g+s", 0755, 0), before: 0705, now: 2755, fixed parsemode("g=u", 0700, 0), before: 0000, now: 0770, fixed parsemode("go=u-w", 0700, 0), before: 0000, now: 0755, fixed parsemode("o+u-g", 0641, 0), before: 0000, now: 0643, fixed parsemode("u=rx,o+w,g-r", 0654, 0) before: error, now: 0516, fixed parsemode(",", 0654, 0), before: error, now: error, still works ¹ http://pubs.opengroup.org/onlinepubs/9699919799/utilities/chmod.html
2014-11-02 17:24:52 -05:00
mode &= ~(perm & who);
break;
}
Fix symbolic mode parsing in parsemode I found quite a lot of bugs, so I ended up pretty much rewriting as I followed the spec¹. Now, it works as follows: - Determine a mask (who) of bits that can be modified for the subsequent operations. If none are specified, select all file mode bits. - In a loop, determine which operation (+, -, =) to apply. - If the next character is a permcopy (u, g, o), set the new permissions (perm) corresponding to the bits set in the user, group or other parts of the existing mode. - Otherwise, set the new permissions by looping through the next r, w, x, s, t characters. - Now, the set of bits we want to add or remove is (who & perm). Set or remove these bits according the the operation (first clearing the appropriate bits if the operation is =). - Continue from the top if the next character is a comma, otherwise, process the next operation. I tested this on some made up inputs, and I believe it is working correctly now: parsemode("g+w", 0644, 0), before: 0606, now: 0664, fixed parsemode("u+rx", 0222, 0), before: 0077, now: 0722, fixed parsemode("+x", 0644, 023), before: 0754, now: 0754, still works parsemode("+w", 0444, 022), before: 0644, now: 0644, still works parsemode("+w", 0444, 0), before: 0666, now: 0666, still works parsemode("+s", 0755, 0), before: 0755, now: 6755, fixed parsemode("u+s", 0755, 0), before: 0055, now: 4755, fixed parsemode("g+s", 0755, 0), before: 0705, now: 2755, fixed parsemode("g=u", 0700, 0), before: 0000, now: 0770, fixed parsemode("go=u-w", 0700, 0), before: 0000, now: 0755, fixed parsemode("o+u-g", 0641, 0), before: 0000, now: 0643, fixed parsemode("u=rx,o+w,g-r", 0654, 0) before: error, now: 0516, fixed parsemode(",", 0654, 0), before: error, now: error, still works ¹ http://pubs.opengroup.org/onlinepubs/9699919799/utilities/chmod.html
2014-11-02 17:24:52 -05:00
/* if we hit a comma, move on to the next clause */
if (*p == ',') {
Fix symbolic mode parsing in parsemode I found quite a lot of bugs, so I ended up pretty much rewriting as I followed the spec¹. Now, it works as follows: - Determine a mask (who) of bits that can be modified for the subsequent operations. If none are specified, select all file mode bits. - In a loop, determine which operation (+, -, =) to apply. - If the next character is a permcopy (u, g, o), set the new permissions (perm) corresponding to the bits set in the user, group or other parts of the existing mode. - Otherwise, set the new permissions by looping through the next r, w, x, s, t characters. - Now, the set of bits we want to add or remove is (who & perm). Set or remove these bits according the the operation (first clearing the appropriate bits if the operation is =). - Continue from the top if the next character is a comma, otherwise, process the next operation. I tested this on some made up inputs, and I believe it is working correctly now: parsemode("g+w", 0644, 0), before: 0606, now: 0664, fixed parsemode("u+rx", 0222, 0), before: 0077, now: 0722, fixed parsemode("+x", 0644, 023), before: 0754, now: 0754, still works parsemode("+w", 0444, 022), before: 0644, now: 0644, still works parsemode("+w", 0444, 0), before: 0666, now: 0666, still works parsemode("+s", 0755, 0), before: 0755, now: 6755, fixed parsemode("u+s", 0755, 0), before: 0055, now: 4755, fixed parsemode("g+s", 0755, 0), before: 0705, now: 2755, fixed parsemode("g=u", 0700, 0), before: 0000, now: 0770, fixed parsemode("go=u-w", 0700, 0), before: 0000, now: 0755, fixed parsemode("o+u-g", 0641, 0), before: 0000, now: 0643, fixed parsemode("u=rx,o+w,g-r", 0654, 0) before: error, now: 0516, fixed parsemode(",", 0654, 0), before: error, now: error, still works ¹ http://pubs.opengroup.org/onlinepubs/9699919799/utilities/chmod.html
2014-11-02 17:24:52 -05:00
p++;
goto next;
}
}
return mode & ~S_IFMT;
}