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