OSDN Git Service

Add string to mode_t parser
authorDaniel Walter <d.walter@0x90.at>
Tue, 20 Mar 2012 00:57:56 +0000 (19:57 -0500)
committerDaniel Walter <d.walter@0x90.at>
Tue, 20 Mar 2012 00:57:56 +0000 (19:57 -0500)
added new function string_to_mode(char *m_string, mode_t base) which
parses a given string and converts it to a mode_t.
If either + or - are part of m_string the permissions are either
added or removed from base.

Currently support for permision copy is missing (e.g. g=u),
but all other flags should work.

Format for m_string: either symbolic modes or octal representation.

symbolic modes:
[auog][[+-=][rwxst]*]

examples:
string_to_mode("u=rwx,g=rw,o=r", 0);
string_to_mode("a-x", 0777);
string_to_mode("0744", 0);

lib/lib.c
lib/lib.h
toys/mkfifo.c

index 6a2e7d9..4665beb 100644 (file)
--- a/lib/lib.c
+++ b/lib/lib.c
@@ -895,3 +895,147 @@ char *num_to_sig(int sig)
                if (signames[i].num == sig) return signames[i].name;
        return NULL;
 }
+
+
+/* mode parsing */
+
+#define        USR_FLAGS       (S_IRWXU)
+#define        GRP_FLAGS       (S_IRWXG)
+#define        OTH_FLAGS       (S_IRWXO)
+#define SGT_FLAGS      (S_ISUID | S_ISGID | S_ISVTX)
+
+#define MODE_WHAT(v, w, x, y, z) { \
+       if (x & v) \
+               y |= S_I##w##z;\
+       }
+#define MODE_READ(x, y, z) MODE_WHAT(0x04, R, x, y, z)
+#define MODE_WRITE(x, y, z) MODE_WHAT(0x02, W, x, y, z)
+#define MODE_EXEC(x, y, z) MODE_WHAT(0x01, X, x, y, z)
+#define MODE_SUID(x, y) MODE_WHAT(0x08, S, x, y, UID)
+#define MODE_SGID(x, y) MODE_WHAT(0x08, S, x, y, GID)
+#define MODE_SVTX(x, y) MODE_WHAT(0x10, S, x, y, VTX)
+
+mode_t
+apply_mode(int who, int how, int what, mode_t base)
+{
+       mode_t new_mode = 0;
+       mode_t tmp_mode = 0;
+       mode_t tmp_mask = USR_FLAGS | GRP_FLAGS | OTH_FLAGS | SGT_FLAGS;
+       if (who & 0x01) {
+               /* u */
+               MODE_READ(what, tmp_mode, USR);
+               MODE_WRITE(what, tmp_mode, USR);
+               MODE_EXEC(what, tmp_mode, USR);
+               MODE_SUID(what, tmp_mode)
+               tmp_mask &= (GRP_FLAGS | OTH_FLAGS | SGT_FLAGS);
+       }
+       if (who & 0x02) {
+               /* g */
+               MODE_READ(what, tmp_mode, GRP);
+               MODE_WRITE(what, tmp_mode, GRP);
+               MODE_EXEC(what, tmp_mode, GRP);
+               MODE_SGID(what, tmp_mode)
+               tmp_mask &= (USR_FLAGS | OTH_FLAGS | SGT_FLAGS);
+       }
+       if (who & 0x04) {
+               /* o */
+               MODE_READ(what, tmp_mode, OTH);
+               MODE_WRITE(what, tmp_mode, OTH);
+               MODE_EXEC(what, tmp_mode, OTH);
+               tmp_mask &= (USR_FLAGS | GRP_FLAGS | SGT_FLAGS);
+       }
+       /* check sticky */
+       MODE_SVTX(what, tmp_mode);
+       switch (how){
+       case 1:
+               /* set */
+               new_mode = tmp_mode | (base & tmp_mask);
+               break;
+       case 2:
+               /* add */
+               new_mode = base | tmp_mode;
+               break;
+       case 3:
+               /* remove */
+               new_mode = base & ~(tmp_mode);
+               break;
+       }
+       return new_mode;
+}
+
+
+mode_t
+string_to_mode(char *mode_str, mode_t base)
+{
+       mode_t new_mode;
+       int what = 0;
+       int who = 0;
+       int how = 0;
+       char *p;
+       long tmp;
+       if (!mode_str)
+               return base;
+       if (isdigit(mode_str[0])) {
+               tmp = strtol(mode_str, &p, 8);
+               if (*p || tmp < 0 ||
+                       (tmp & ~(OTH_FLAGS | SGT_FLAGS | GRP_FLAGS | USR_FLAGS)))
+                       return base;
+               new_mode = (mode_t) tmp;
+               return new_mode;
+       }
+       new_mode = base;
+       while (*mode_str) {
+               /* TODO: add support for permission copying */
+               switch(*mode_str) {
+               case ',':
+                       /* next command */
+                       new_mode = apply_mode(who, how, what, new_mode);
+                       who = 0;
+                       how = 0;
+                       what = 0;
+                       break;
+               case 'a':
+                       who = 0x01 | 0x02 | 0x04;
+                       break;
+               case 'u':
+                       who |= 0x01;
+                       break;
+               case 'g':
+                       who |= 0x02;
+                       break;
+               case 'o':
+                       who |= 0x04;
+                       break;
+               case 'r':
+                       what |= 0x04;
+                       break;
+               case 'w':
+                       what |= 0x02;
+                       break;
+               case 'x':
+                       what |= 0x01;
+                       break;
+               case 't':
+                       what |= 0x10;
+                       break;
+               case 's':
+                       what |= 0x08;
+                       break;
+               case '=':
+                       how = 1;
+                       break;
+               case '+':
+                       how = 2;
+                       break;
+               case '-':
+                       how = 3;
+                       break;
+               default:
+                       /* error case */
+                       return base;
+               }
+               mode_str++;
+       }
+       new_mode = apply_mode(who, how, what, new_mode);
+       return new_mode;
+}
index c219039..2f33236 100644 (file)
--- a/lib/lib.h
+++ b/lib/lib.h
@@ -132,3 +132,5 @@ void bunzipStream(int src_fd, int dst_fd);
 
 int sig_to_num(char *pidstr);
 char *num_to_sig(int sig);
+
+mode_t string_to_mode(char *mode_str, mode_t base);
index 17d9c2c..ab466fc 100644 (file)
@@ -8,7 +8,7 @@
  *
  * TODO: Add -m
 
-USE_MKFIFO(NEWTOY(mkfifo, "<1", TOYFLAG_BIN))
+USE_MKFIFO(NEWTOY(mkfifo, "<1m:", TOYFLAG_BIN))
 
 config MKFIFO
        bool "mkfifo"
@@ -22,16 +22,21 @@ config MKFIFO
 #include "toys.h"
 
 DEFINE_GLOBALS(
-       long mode;
+       char *m_string;
+       mode_t mode;
 )
 
 #define TT this.mkfifo
+#define FLAG_m (1)
 
 void mkfifo_main(void)
 {
        char **s;
 
        TT.mode = 0666;
+       if (toys.optflags & FLAG_m) {
+               TT.mode = string_to_mode(TT.m_string, 0);
+       }
 
        for (s = toys.optargs; *s; s++) {
                if (mknod(*s, S_IFIFO | TT.mode, 0) < 0) {