comparison toys/chgrp.c @ 582:b88bc7dcdb48

Update chgrp so -R works, tweaking DIRTREE_COMEAGAIN design along the way.
author Rob Landley <rob@landley.net>
date Sun, 27 May 2012 00:56:17 -0500
parents 4a91ede70548
children 9c2277b92b86
comparison
equal deleted inserted replaced
581:1e07220fd3b6 582:b88bc7dcdb48
13 13
14 USE_CHGRP(NEWTOY(chgrp, "<2Rfv", TOYFLAG_BIN)) 14 USE_CHGRP(NEWTOY(chgrp, "<2Rfv", TOYFLAG_BIN))
15 15
16 config CHGRP 16 config CHGRP
17 bool "chgrp" 17 bool "chgrp"
18 default n 18 default y
19 help 19 help
20 usage: chgrp [-R] [-f] [-v] group file... 20 usage: chgrp [-R] [-f] [-v] group file...
21 Change group ownership of one or more files. 21 Change group ownership of one or more files.
22 22
23 -R recurse into subdirectories. 23 -R recurse into subdirectories.
36 char *group_name; 36 char *group_name;
37 ) 37 )
38 38
39 #define TT this.chgrp 39 #define TT this.chgrp
40 40
41 static int do_chgrp(const char *path) { 41 static int do_chgrp(struct dirtree *node)
42 int ret = chown(path, -1, TT.group); 42 {
43 if (toys.optflags & FLAG_v) 43 int fd, ret = 1, flags = toys.optflags;
44 xprintf("chgrp(%s, %s)\n", TT.group_name, path); 44
45 if (ret == -1 && !(toys.optflags & FLAG_f)) 45 if (!dirtree_notdotdot(node)) return 0;
46 perror_msg("changing group of '%s' to '%s'", path, TT.group_name); 46
47 // Handle recursion, and make it depth first
48 if (S_ISDIR(node->st.st_mode)) {
49 if (!node->extra) node->extra = dup(node->data);
50 if ((flags & FLAG_R) && node->data != -1) return DIRTREE_COMEAGAIN;
51 fd = node->extra;
52 } else fd = openat(node->parent ? node->parent->data : AT_FDCWD,
53 node->name, 0);
54
55 if (fd != -1) ret = fchown(fd, -1, TT.group);
56
57 if (ret || (flags & FLAG_v)) {
58 char *path = dirtree_path(node, 0);
59 if (flags & FLAG_v)
60 xprintf("chgrp(%s, %s)\n", TT.group_name, path);
61 if (ret == -1 && !(toys.optflags & FLAG_f))
62 perror_msg("changing group of '%s' to '%s'", path, TT.group_name);
63 free(path);
64 }
65 close(fd);
47 toys.exitval |= ret; 66 toys.exitval |= ret;
48 return ret;
49 }
50
51 // Copied from toys/cp.c:cp_node()
52 int chgrp_node(char *path, struct dirtree *node)
53 {
54 char *s = path + strlen(path);
55 struct dirtree *n = node;
56
57 for ( ; ; n = n->parent) {
58 while (s!=path) {
59 if (*(--s) == '/') break;
60 }
61 if (!n) break;
62 }
63 if (s != path) s++;
64
65 do_chgrp(s);
66 67
67 return 0; 68 return 0;
68 } 69 }
69 70
70 void chgrp_main(void) 71 void chgrp_main(void)
72 char **s; 73 char **s;
73 struct group *group; 74 struct group *group;
74 75
75 TT.group_name = *toys.optargs; 76 TT.group_name = *toys.optargs;
76 group = getgrnam(TT.group_name); 77 group = getgrnam(TT.group_name);
77 if (!group) { 78 if (!group) error_exit("no group '%s'", TT.group_name);
78 error_msg("invalid group '%s'", TT.group_name);
79 toys.exitval = 1;
80 return;
81 }
82 TT.group = group->gr_gid; 79 TT.group = group->gr_gid;
83 80
84 if (toys.optflags & FLAG_R) { 81 for (s=toys.optargs+1; *s; s++) dirtree_read(*s, do_chgrp);
85 // Recurse into subdirectories
86 for (s=toys.optargs + 1; *s; s++) {
87 struct stat sb;
88 if (stat(*s, &sb) == -1) {
89 if (!(toys.optflags & FLAG_f))
90 perror_msg("stat '%s'", *s);
91 continue;
92 }
93 do_chgrp(*s);
94 if (S_ISDIR(sb.st_mode)) {
95 strncpy(toybuf, *s, sizeof(toybuf) - 1);
96 toybuf[sizeof(toybuf) - 1] = 0;
97 dirtree_read(toybuf, NULL, chgrp_node);
98 }
99 }
100 } else {
101 // Do not recurse
102 for (s=toys.optargs + 1; *s; s++) {
103 do_chgrp(*s);
104 }
105 }
106 } 82 }