#ifndef _PARSE_MODE_H #define _PARSE_MODE_H #include #include #define U (S_ISUID | S_IRWXU) #define G (S_ISGID | S_IRWXG) #define O (S_IRWXO) #define A (U | G | O) #define WR_PERM (S_IWUSR | S_IWGRP | S_IWOTH) #define EX_PERM (S_IXUSR | S_IXGRP | S_IXOTH) #define RD_PERM (S_IRUSR | S_IRGRP | S_IROTH) #define SU_PERM (S_ISUID | S_ISGID | S_ISVTX) #define FULL_PERM (WR_PERM | EX_PERM | RD_PERM) static mode_t mu_parse_mode(const char *s, mode_t cur_mode) { char *p = NULL; mode_t mode = (mode_t)strtol(s, &p, 8); if (!*p && mode < 07777U) return mode; else if (mode > 07777U) return 0; mode = 0; /* Default + */ char append = 1; mode_t mask = 0; for (size_t i = 0; i < strlen(s); i++) { switch (s[i]) { case 'r': mode |= RD_PERM; break; case 'w': mode |= WR_PERM; break; case 'x': mode |= EX_PERM; break; case 's': mode |= SU_PERM; break; case '+': append = 1; break; case '-': append = 0; break; case '=': append = 2; break; case 'g': mask |= G; break; case 'u': mask |= U; break; case 'o': mask |= O; break; case 'a': mask |= A; break; default: return 0; } } if (mask == 0) mask = U; mask &= mode; if (append == 0) mode = ~mode; if (append == 2) return mode & mask; else return (cur_mode & ~mask) | (mode & mask); } #endif