micro-utils/libmu/parse_mode.h

84 lines
1.1 KiB
C
Raw Normal View History

2023-11-01 14:17:25 +03:00
#ifndef _PARSE_MODE_H
#define _PARSE_MODE_H
#include <sys/stat.h>
2023-11-01 15:33:16 +03:00
#define U(x) (x << 6)
#define G(x) (x << 3)
#define O(x) (x)
#define A(x) (U(x) | G(x) | O(x))
2023-11-02 02:51:11 +03:00
#define WR_PERM (2)
#define EX_PERM (1)
#define RD_PERM (4)
#define FULL_PERM (7)
2023-11-02 12:51:20 +03:00
mode_t mu_parse_mode(const char *s, mode_t cur_mode) {
2023-11-01 14:17:25 +03:00
char *p = NULL;
2023-11-02 02:51:11 +03:00
2023-11-01 15:33:16 +03:00
mode_t mode = (mode_t)strtol(s, &p, 8);
2023-11-02 02:51:11 +03:00
if (!*p && mode < 07777U)
2023-11-01 14:17:25 +03:00
return mode;
2023-11-02 12:32:35 +03:00
else if (mode > 07777U)
return 0;
2023-11-02 12:08:06 +03:00
2023-11-02 12:32:35 +03:00
mode = 0;
int append = 1;
2023-11-02 12:08:06 +03:00
mode_t mask = 0;
for (size_t i = 0; i < strlen(s); i++) {
switch (s[i]) {
case 'r':
mode |= A(RD_PERM);
break;
case 'w':
mode |= A(WR_PERM);
break;
case 'x':
mode |= A(EX_PERM);
break;
case '+':
2023-11-02 12:32:35 +03:00
append = 1;
2023-11-02 12:08:06 +03:00
break;
case '-':
2023-11-02 12:32:35 +03:00
append = 0;
2023-11-02 12:08:06 +03:00
break;
case 'g':
mask |= G(FULL_PERM);
break;
case 'u':
mask |= U(FULL_PERM);
break;
case 'o':
mask |= O(FULL_PERM);
break;
case 'a':
mask |= A(FULL_PERM);
break;
default:
2023-11-02 12:32:35 +03:00
return 0;
2023-11-02 12:08:06 +03:00
}
}
2023-11-02 12:32:35 +03:00
if (mask == 0)
mask = U(FULL_PERM);
2023-11-02 12:51:20 +03:00
mask = mask & mode;
if (!append)
mode = ~mode;
2023-11-02 12:08:06 +03:00
2023-11-02 12:51:20 +03:00
return (cur_mode & ~mask) | (mode & mask);
2023-11-01 14:17:25 +03:00
}
#endif