From ba506d93e0954f02f13dbba742c83387b3bbd077 Mon Sep 17 00:00:00 2001 From: petershh Date: Sun, 31 Jul 2022 15:35:39 +0300 Subject: Move parse_octal, parse_symbolic and change_mode to their own files --- package/deps.mak | 7 +- src/shh-portable-utils/change_mode.c | 82 +++++++++++ src/shh-portable-utils/chmod.c | 234 -------------------------------- src/shh-portable-utils/deps-exe/chmod | 3 + src/shh-portable-utils/parse_octal.c | 39 ++++++ src/shh-portable-utils/parse_symbolic.c | 127 +++++++++++++++++ 6 files changed, 256 insertions(+), 236 deletions(-) create mode 100644 src/shh-portable-utils/change_mode.c create mode 100644 src/shh-portable-utils/parse_octal.c create mode 100644 src/shh-portable-utils/parse_symbolic.c diff --git a/package/deps.mak b/package/deps.mak index d078b77..d84009e 100644 --- a/package/deps.mak +++ b/package/deps.mak @@ -5,8 +5,9 @@ src/shh-portable-utils/basename.o src/shh-portable-utils/basename.lo: src/shh-portable-utils/basename.c src/shh-portable-utils/byte_notin.o src/shh-portable-utils/byte_notin.lo: src/shh-portable-utils/byte_notin.c src/shh-portable-utils/shhfuncs.h src/shh-portable-utils/cat.o src/shh-portable-utils/cat.lo: src/shh-portable-utils/cat.c +src/shh-portable-utils/change_mode.o src/shh-portable-utils/change_mode.lo: src/shh-portable-utils/change_mode.c src/shh-portable-utils/shhfuncs.h src/shh-portable-utils/chgrp.o src/shh-portable-utils/chgrp.lo: src/shh-portable-utils/chgrp.c src/shh-portable-utils/shhfuncs.h -src/shh-portable-utils/chmod.o src/shh-portable-utils/chmod.lo: src/shh-portable-utils/chmod.c +src/shh-portable-utils/chmod.o src/shh-portable-utils/chmod.lo: src/shh-portable-utils/chmod.c src/shh-portable-utils/shhfuncs.h src/shh-portable-utils/chown.o src/shh-portable-utils/chown.lo: src/shh-portable-utils/chown.c src/shh-portable-utils/shhfuncs.h src/shh-portable-utils/cut.o src/shh-portable-utils/cut.lo: src/shh-portable-utils/cut.c src/shh-portable-utils/shhfuncs.h src/shh-portable-utils/dirname.o src/shh-portable-utils/dirname.lo: src/shh-portable-utils/dirname.c @@ -16,6 +17,8 @@ src/shh-portable-utils/ln.o src/shh-portable-utils/ln.lo: src/shh-portable-utils src/shh-portable-utils/nice.o src/shh-portable-utils/nice.lo: src/shh-portable-utils/nice.c src/shh-portable-utils/nohup.o src/shh-portable-utils/nohup.lo: src/shh-portable-utils/nohup.c src/shh-portable-utils/parse_group.o src/shh-portable-utils/parse_group.lo: src/shh-portable-utils/parse_group.c +src/shh-portable-utils/parse_octal.o src/shh-portable-utils/parse_octal.lo: src/shh-portable-utils/parse_octal.c src/shh-portable-utils/shhfuncs.h +src/shh-portable-utils/parse_symbolic.o src/shh-portable-utils/parse_symbolic.lo: src/shh-portable-utils/parse_symbolic.c src/shh-portable-utils/parse_user.o src/shh-portable-utils/parse_user.lo: src/shh-portable-utils/parse_user.c src/shh-portable-utils/shhfuncs.h src/shh-portable-utils/renice.o src/shh-portable-utils/renice.lo: src/shh-portable-utils/renice.c src/shh-portable-utils/shhfuncs.h src/shh-portable-utils/shhgetln.o src/shh-portable-utils/shhgetln.lo: src/shh-portable-utils/shhgetln.c src/shh-portable-utils/shhfuncs.h @@ -33,7 +36,7 @@ cat: src/shh-portable-utils/cat.o chgrp: EXTRA_LIBS := ${SOCKET_LIB} -lskarnet chgrp: src/shh-portable-utils/chgrp.o src/shh-portable-utils/parse_group.o ${LIBNSSS} chmod: EXTRA_LIBS := -lskarnet -chmod: src/shh-portable-utils/chmod.o +chmod: src/shh-portable-utils/chmod.o src/shh-portable-utils/parse_octal.o src/shh-portable-utils/parse_symbolic.o src/shh-portable-utils/change_mode.o chown: EXTRA_LIBS := ${SOCKET_LIB} -lskarnet chown: src/shh-portable-utils/chown.o src/shh-portable-utils/parse_user.o src/shh-portable-utils/parse_group.o ${LIBNSSS} cut: EXTRA_LIBS := -lskarnet diff --git a/src/shh-portable-utils/change_mode.c b/src/shh-portable-utils/change_mode.c new file mode 100644 index 0000000..611981c --- /dev/null +++ b/src/shh-portable-utils/change_mode.c @@ -0,0 +1,82 @@ +#include + +#include +#include + +#include "shhfuncs.h" + +int change_mode(char const *file, mode_t mode, genalloc *directives, + mode_t mask) +{ + mode_t cur_mode; + if (!genalloc_len(chmod_directive, directives)) + cur_mode = mode; + else { + struct stat st; + mode_t who, perm, clear; + chmod_directive const *s = genalloc_s(chmod_directive, directives); + size_t len = genalloc_len(chmod_directive, directives); + + if (stat(file, &st) == -1) { + strerr_warnwu2sys("stat ", file); + return 1; + } + cur_mode = st.st_mode; + + for (size_t i = 0; i < len; i++) { + if (s[i].who) { + who = s[i].who; + clear = s[i].who; + } + else { + who = ~mask; + clear = S_ISALL; + } + perm = s[i].perm; + + if (s[i].permcopy & 1) { + if (cur_mode & S_IRUSR) + perm |= S_IRUSR | S_IRGRP | S_IROTH; + if (cur_mode & S_IWUSR) + perm |= S_IWUSR | S_IWGRP | S_IWOTH; + if (cur_mode & S_IXUSR) + perm |= S_IXUSR | S_IXGRP | S_IXOTH; + } + if (s[i].permcopy & 2) { + if (cur_mode & S_IRGRP) + perm |= S_IRUSR | S_IRGRP | S_IROTH; + if (cur_mode & S_IWGRP) + perm |= S_IWUSR | S_IWGRP | S_IWOTH; + if (cur_mode & S_IXGRP) + perm |= S_IXUSR | S_IXGRP | S_IXOTH; + } + if (s[i].permcopy & 4) { + if (cur_mode & S_IROTH) + perm |= S_IRUSR | S_IRGRP | S_IROTH; + if (cur_mode & S_IWOTH) + perm |= S_IWUSR | S_IWGRP | S_IWOTH; + if (cur_mode & S_IXOTH) + perm |= S_IXUSR | S_IXGRP | S_IXOTH; + } + + if (s[i].dir_x && (S_ISDIR(cur_mode) + || (cur_mode & (S_IXUSR | S_IXGRP | S_IXOTH)))) + perm |= S_IXUSR | S_IXGRP | S_IXOTH; + + switch (s[i].action) { + case '=': + cur_mode &= ~clear; + case '+': + cur_mode |= (who & perm); + break; + case '-': + cur_mode &= ~(who & perm); + } + } + } + if (chmod(file, cur_mode) == -1) { + strerr_warnwu2sys("change mode of ", file); + return 1; + } + return 0; +} diff --git a/src/shh-portable-utils/chmod.c b/src/shh-portable-utils/chmod.c index 40091e6..9518730 100644 --- a/src/shh-portable-utils/chmod.c +++ b/src/shh-portable-utils/chmod.c @@ -79,240 +79,6 @@ int main(int argc, char const *const *argv) return failure ? 111 : 0; } - -mode_t parse_octal(char const *raw_mode) -{ - mode_t mode = 0; - unsigned int m; - if (!uint0_oscan(raw_mode, &m)) - strerr_dief2x(100, "invalid mode: ", raw_mode); - - if (m & 0001) - mode |= S_IXOTH; - if (m & 0002) - mode |= S_IWOTH; - if (m & 0004) - mode |= S_IROTH; - if (m & 0010) - mode |= S_IXGRP; - if (m & 0020) - mode |= S_IWGRP; - if (m & 0040) - mode |= S_IRGRP; - if (m & 0100) - mode |= S_IXUSR; - if (m & 0200) - mode |= S_IWUSR; - if (m & 0400) - mode |= S_IRUSR; - if (m & 01000) - mode |= S_ISVTX; - if (m & 02000) - mode |= S_ISGID; - if (m & 04000) - mode |= S_ISUID; - - return mode; -} - -void parse_symbolic(char const *raw, genalloc *directives) -{ - char const *p = raw; - for (;;) { - chmod_directive d = CHMOD_DIRECTIVE_ZERO; - /* stage 1: parse 'who' list */ - for (;;) { - if (*p == 'u') - d.who |= S_IRWXU | S_ISUID; - else if (*p == 'g') - d.who |= S_IRWXG | S_ISGID; - else if (*p == 'o') - d.who |= S_IRWXO; - else if (*p == 'a') - d.who |= S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID; - else - break; - p++; - } - /* stage 2: actions. First cycle is out of the loop. */ - switch(*p) { - case '+': - case '-': - case '=': - d.action = *p; - break; - default: - strerr_dief2x(100, "invalid mode: ", raw); - } - p++; - for (;;) { - if (*p == 'u') - d.permcopy |= 1; - else if (*p == 'g') - d.permcopy |= 2; - else if (*p == 'o') - d.permcopy |= 4; - else if (*p == 'r') - d.perm |= S_IRUSR | S_IRGRP | S_IROTH; - else if (*p == 'w') - d.perm |= S_IWUSR | S_IWGRP | S_IWOTH; - else if (*p == 'x') - d.perm |= S_IXUSR | S_IXGRP | S_IXOTH; - else if (*p == 'X') - d.dir_x = 1; - else if (*p == 's') - d.perm |= S_ISUID | S_ISGID; - else if (*p == 't') - d.perm |= S_ISVTX; - else if (*p == ',') { - p++; - break; - } - else if (*p == '\0') { - if (d.perm && d.permcopy) - strerr_dief2x(100, "invalid mode: ", raw); - if (!genalloc_append(chmod_directive, directives, &d)) - strerr_diefu1sys(111, "parse mode"); - return; - } - p++; - } - - if (d.perm && d.permcopy) - strerr_dief2x(100, "invalid mode: ", raw); - if (!genalloc_append(chmod_directive, directives, &d)) - strerr_diefu1sys(111, "parse mode"); - - for (;;) { - d.action = d.perm = d.permcopy = d.dir_x = 0; - if (*p == '+' || *p == '-' || *p == '=') - d.action = *p; - else if (*p == ',') - break; - else if (*p == '\0') - return; - else - strerr_dief2x(100, "invalid mode: ", raw); - - p++; - - for (;;) { - if (*p == 'u') - d.permcopy |= 1; - else if (*p == 'g') - d.permcopy |= 2; - else if (*p == 'o') - d.permcopy |= 4; - else if (*p == 'r') - d.perm |= S_IRUSR | S_IRGRP | S_IROTH; - else if (*p == 'w') - d.perm |= S_IWUSR | S_IWGRP | S_IWOTH; - else if (*p == 'x') - d.perm |= S_IXUSR | S_IXGRP | S_IXOTH; - else if (*p == 'X') - d.dir_x = 1; - else if (*p == 's') - d.perm |= S_ISUID | S_ISGID; - else if (*p == 't') - d.perm |= S_ISVTX; - else if (*p == ',') { - p++; - break; - } - else if (*p == '\0') { - if (d.perm && d.permcopy) - strerr_dief2x(100, "invalid mode: ", raw); - if (!genalloc_append(chmod_directive, directives, &d)) - strerr_diefu1sys(111, "parse mode"); - return; - } - p++; - } - - if (d.perm && d.permcopy) - strerr_dief2x(100, "invalid mode: ", raw); - if (!genalloc_append(chmod_directive, directives, &d)) - strerr_diefu1sys(111, "parse mode"); - } - } -} - -int change_mode(char const *file, mode_t mode, genalloc *directives, - mode_t mask) -{ - mode_t cur_mode; - if (!genalloc_len(chmod_directive, directives)) - cur_mode = mode; - else { - struct stat st; - mode_t who, perm, clear; - chmod_directive const *s = genalloc_s(chmod_directive, directives); - size_t len = genalloc_len(chmod_directive, directives); - - if (stat(file, &st) == -1) { - strerr_warnwu2sys("stat ", file); - return 1; - } - cur_mode = st.st_mode; - - for (size_t i = 0; i < len; i++) { - if (s[i].who) { - who = s[i].who; - clear = s[i].who; - } - else { - who = ~mask; - clear = S_ISALL; - } - perm = s[i].perm; - - if (s[i].permcopy & 1) { - if (cur_mode & S_IRUSR) - perm |= S_IRUSR | S_IRGRP | S_IROTH; - if (cur_mode & S_IWUSR) - perm |= S_IWUSR | S_IWGRP | S_IWOTH; - if (cur_mode & S_IXUSR) - perm |= S_IXUSR | S_IXGRP | S_IXOTH; - } - if (s[i].permcopy & 2) { - if (cur_mode & S_IRGRP) - perm |= S_IRUSR | S_IRGRP | S_IROTH; - if (cur_mode & S_IWGRP) - perm |= S_IWUSR | S_IWGRP | S_IWOTH; - if (cur_mode & S_IXGRP) - perm |= S_IXUSR | S_IXGRP | S_IXOTH; - } - if (s[i].permcopy & 4) { - if (cur_mode & S_IROTH) - perm |= S_IRUSR | S_IRGRP | S_IROTH; - if (cur_mode & S_IWOTH) - perm |= S_IWUSR | S_IWGRP | S_IWOTH; - if (cur_mode & S_IXOTH) - perm |= S_IXUSR | S_IXGRP | S_IXOTH; - } - - if (s[i].dir_x && (S_ISDIR(cur_mode) - || (cur_mode & (S_IXUSR | S_IXGRP | S_IXOTH)))) - perm |= S_IXUSR | S_IXGRP | S_IXOTH; - - switch (s[i].action) { - case '=': - cur_mode &= ~clear; - case '+': - cur_mode |= (who & perm); - break; - case '-': - cur_mode &= ~(who & perm); - } - } - } - if (chmod(file, cur_mode) == -1) { - strerr_warnwu2sys("change mode of ", file); - return 1; - } - return 0; -} - int traverse_dir(stralloc *dirname, mode_t mode, genalloc *directives, mode_t mask) { diff --git a/src/shh-portable-utils/deps-exe/chmod b/src/shh-portable-utils/deps-exe/chmod index e7187fe..939c605 100644 --- a/src/shh-portable-utils/deps-exe/chmod +++ b/src/shh-portable-utils/deps-exe/chmod @@ -1 +1,4 @@ +parse_octal.o +parse_symbolic.o +change_mode.o -lskarnet diff --git a/src/shh-portable-utils/parse_octal.c b/src/shh-portable-utils/parse_octal.c new file mode 100644 index 0000000..c969f5f --- /dev/null +++ b/src/shh-portable-utils/parse_octal.c @@ -0,0 +1,39 @@ +#include +#include + +#include "shhfuncs.h" + +mode_t parse_octal(char const *raw_mode) +{ + mode_t mode = 0; + unsigned int m; + if (!uint0_oscan(raw_mode, &m)) + strerr_dief2x(100, "invalid mode: ", raw_mode); + + if (m & 0001) + mode |= S_IXOTH; + if (m & 0002) + mode |= S_IWOTH; + if (m & 0004) + mode |= S_IROTH; + if (m & 0010) + mode |= S_IXGRP; + if (m & 0020) + mode |= S_IWGRP; + if (m & 0040) + mode |= S_IRGRP; + if (m & 0100) + mode |= S_IXUSR; + if (m & 0200) + mode |= S_IWUSR; + if (m & 0400) + mode |= S_IRUSR; + if (m & 01000) + mode |= S_ISVTX; + if (m & 02000) + mode |= S_ISGID; + if (m & 04000) + mode |= S_ISUID; + + return mode; +} diff --git a/src/shh-portable-utils/parse_symbolic.c b/src/shh-portable-utils/parse_symbolic.c new file mode 100644 index 0000000..3c2ea94 --- /dev/null +++ b/src/shh-portable-utils/parse_symbolic.c @@ -0,0 +1,127 @@ +#include +#include + +#include "shhfuncs.h" + +void parse_symbolic(char const *raw, genalloc *directives) +{ + char const *p = raw; + for (;;) { + chmod_directive d = CHMOD_DIRECTIVE_ZERO; + /* stage 1: parse 'who' list */ + for (;;) { + if (*p == 'u') + d.who |= S_IRWXU | S_ISUID; + else if (*p == 'g') + d.who |= S_IRWXG | S_ISGID; + else if (*p == 'o') + d.who |= S_IRWXO; + else if (*p == 'a') + d.who |= S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID; + else + break; + p++; + } + /* stage 2: actions. First cycle is out of the loop. */ + switch(*p) { + case '+': + case '-': + case '=': + d.action = *p; + break; + default: + strerr_dief2x(100, "invalid mode: ", raw); + } + p++; + for (;;) { + if (*p == 'u') + d.permcopy |= 1; + else if (*p == 'g') + d.permcopy |= 2; + else if (*p == 'o') + d.permcopy |= 4; + else if (*p == 'r') + d.perm |= S_IRUSR | S_IRGRP | S_IROTH; + else if (*p == 'w') + d.perm |= S_IWUSR | S_IWGRP | S_IWOTH; + else if (*p == 'x') + d.perm |= S_IXUSR | S_IXGRP | S_IXOTH; + else if (*p == 'X') + d.dir_x = 1; + else if (*p == 's') + d.perm |= S_ISUID | S_ISGID; + else if (*p == 't') + d.perm |= S_ISVTX; + else if (*p == ',') { + p++; + break; + } + else if (*p == '\0') { + if (d.perm && d.permcopy) + strerr_dief2x(100, "invalid mode: ", raw); + if (!genalloc_append(chmod_directive, directives, &d)) + strerr_diefu1sys(111, "parse mode"); + return; + } + p++; + } + + if (d.perm && d.permcopy) + strerr_dief2x(100, "invalid mode: ", raw); + if (!genalloc_append(chmod_directive, directives, &d)) + strerr_diefu1sys(111, "parse mode"); + + for (;;) { + d.action = d.perm = d.permcopy = d.dir_x = 0; + if (*p == '+' || *p == '-' || *p == '=') + d.action = *p; + else if (*p == ',') + break; + else if (*p == '\0') + return; + else + strerr_dief2x(100, "invalid mode: ", raw); + + p++; + + for (;;) { + if (*p == 'u') + d.permcopy |= 1; + else if (*p == 'g') + d.permcopy |= 2; + else if (*p == 'o') + d.permcopy |= 4; + else if (*p == 'r') + d.perm |= S_IRUSR | S_IRGRP | S_IROTH; + else if (*p == 'w') + d.perm |= S_IWUSR | S_IWGRP | S_IWOTH; + else if (*p == 'x') + d.perm |= S_IXUSR | S_IXGRP | S_IXOTH; + else if (*p == 'X') + d.dir_x = 1; + else if (*p == 's') + d.perm |= S_ISUID | S_ISGID; + else if (*p == 't') + d.perm |= S_ISVTX; + else if (*p == ',') { + p++; + break; + } + else if (*p == '\0') { + if (d.perm && d.permcopy) + strerr_dief2x(100, "invalid mode: ", raw); + if (!genalloc_append(chmod_directive, directives, &d)) + strerr_diefu1sys(111, "parse mode"); + return; + } + p++; + } + + if (d.perm && d.permcopy) + strerr_dief2x(100, "invalid mode: ", raw); + if (!genalloc_append(chmod_directive, directives, &d)) + strerr_diefu1sys(111, "parse mode"); + } + } +} + -- cgit v1.2.3