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