1/* chmod.c - Change file mode bits 2 * 3 * Copyright 2012 Rob Landley <rob@landley.net> 4 * 5 * See http://opengroup.org/onlinepubs/9699919799/utilities/chmod.html 6 7USE_CHMOD(NEWTOY(chmod, "<2?vfR[-vf]", TOYFLAG_BIN)) 8 9config CHMOD 10 bool "chmod" 11 default y 12 help 13 usage: chmod [-R] MODE FILE... 14 15 Change mode of listed file[s] (recursively with -R). 16 17 MODE can be (comma-separated) stanzas: [ugoa][+-=][rwxstXugo] 18 19 Stanzas are applied in order: For each category (u = user, 20 g = group, o = other, a = all three, if none specified default is a), 21 set (+), clear (-), or copy (=), r = read, w = write, x = execute. 22 s = u+s = suid, g+s = sgid, +t = sticky. (o+s ignored so a+s doesn't set +t) 23 suid/sgid: execute as the user/group who owns the file. 24 sticky: can't delete files you don't own out of this directory 25 X = x for directories or if any category already has x set. 26 27 Or MODE can be an octal value up to 7777 ug uuugggooo top + 28 bit 1 = o+x, bit 1<<8 = u+w, 1<<11 = g+1 sstrwxrwxrwx bottom 29 30 Examples: 31 chmod u+w file - allow owner of "file" to write to it. 32 chmod 744 file - user can read/write/execute, everyone else read only 33*/ 34 35#define FOR_chmod 36#include "toys.h" 37 38GLOBALS( 39 char *mode; 40) 41 42static int do_chmod(struct dirtree *try) 43{ 44 mode_t mode; 45 46 if (!dirtree_notdotdot(try)) return 0; 47 48 if (FLAG(R) && try->parent && S_ISLNK(try->st.st_mode)) { 49 // Ignore symlinks found during recursion. We'll only try to modify 50 // symlinks mentioned directly as arguments. We'll fail, of course, 51 // but that's what you asked for in that case. 52 } else { 53 mode = string_to_mode(TT.mode, try->st.st_mode) & ~S_IFMT; 54 if (FLAG(v)) { 55 char *s = dirtree_path(try, 0); 56 57 printf("chmod '%s' to %s\n", s, TT.mode); 58 free(s); 59 } 60 wfchmodat(dirtree_parentfd(try), try->name, mode); 61 } 62 63 return FLAG(R)*DIRTREE_RECURSE; 64} 65 66void chmod_main(void) 67{ 68 TT.mode = *toys.optargs; 69 char **file; 70 71 for (file = toys.optargs+1; *file; file++) dirtree_read(*file, do_chmod); 72} 73