static int Pstat(lua_State *L) /** stat(path,[selector]) */ { struct mystat s; const char *path=luaL_checkstring(L, 1); if (lstat(path,&s.s)==-1) return pusherror(L, path); s.type=filetype(s.s.st_mode); modechopper(s.s.st_mode, s.mode); return doselection(L, 2, Sstat, Fstat, &s); }
static int Pumask(lua_State *L) /** umask([mode]) */ { char m[10]; mode_t mode; umask(mode=umask(0)); mode=(~mode)&0777; if (!lua_isnone(L, 1)) { if (mode_munch(&mode, luaL_checkstring(L, 1))) { lua_pushnil(L); return 1; } mode&=0777; umask(~mode); } modechopper(mode, m); lua_pushstring(L, m); return 1; }
static int mode_munch(mode_t *mode, const char* p) { char op=0; mode_t affected_bits, ch_mode; int doneFlag = 0; #ifdef DEBUG char tmp[10]; #endif #ifdef DEBUG modechopper(*mode, tmp); printf("modemuncher: got base mode = %s\n", tmp); #endif while (!doneFlag) { /* step 0 -- clear temporary variables */ affected_bits=0; ch_mode=0; /* step 1 -- who's affected? */ #ifdef DEBUG printf("modemuncher step 1\n"); #endif /* mode string given in rwxrwxrwx format */ if (*p== 'r' || *p == '-') return rwxrwxrwx(mode, p); /* mode string given in ugoa+-=rwx format */ for ( ; ; p++) switch (*p) { case 'u': affected_bits |= 04700; break; case 'g': affected_bits |= 02070; break; case 'o': affected_bits |= 01007; break; case 'a': affected_bits |= 07777; break; /* ignore spaces */ case ' ': break; default: goto no_more_affected; } no_more_affected: /* If none specified, affect all bits. */ if (affected_bits == 0) affected_bits = 07777; /* step 2 -- how is it changed? */ #ifdef DEBUG printf("modemuncher step 2 (*p='%c')\n", *p); #endif switch (*p) { case '+': case '-': case '=': op = *p; break; /* ignore spaces */ case ' ': break; default: return -1; /* failed! -- bad operator */ } /* step 3 -- what are the changes? */ #ifdef DEBUG printf("modemuncher step 3\n"); #endif for (p++ ; *p!=0 ; p++) switch (*p) { case 'r': ch_mode |= 00444; break; case 'w': ch_mode |= 00222; break; case 'x': ch_mode |= 00111; break; case 's': /* Set the setuid/gid bits if `u' or `g' is selected. */ ch_mode |= 06000; break; /* ignore spaces */ case ' ': break; default: goto specs_done; } specs_done: /* step 4 -- apply the changes */ #ifdef DEBUG printf("modemuncher step 4\n"); #endif if (*p != ',') doneFlag = 1; if (*p != 0 && *p != ' ' && *p != ',') { #ifdef DEBUG printf("modemuncher: comma error!\n"); printf("modemuncher: doneflag = %u\n", doneFlag); #endif return -2; /* failed! -- bad mode change */ } p++; /*if (!ch_mode) return -2;*/ /* failed! -- bad mode change */ if (ch_mode) switch (op) { case '+': *mode |= ch_mode & affected_bits; break; case '-': *mode &= ~(ch_mode & affected_bits); break; case '=': *mode = ch_mode & affected_bits; break; default: return -3; /* failed! -- unknown error */ } } #ifdef DEBUG modechopper(*mode, tmp); printf("modemuncher: returning mode = %s\n", tmp); #endif return 0; /* successful call */ }