1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#define FOR_rm
23#include "toys.h"
24
25static int do_rm(struct dirtree *try)
26{
27 int fd = dirtree_parentfd(try), flags = toys.optflags;
28 int dir = S_ISDIR(try->st.st_mode), or = 0, using = 0;
29
30
31 if (isdotdot(try->name)) return 0;
32
33
34
35 if (dir && !(flags & (FLAG_r|FLAG_R))) goto skip;
36
37
38 if (!(flags & FLAG_f)
39 && (!S_ISLNK(try->st.st_mode) && faccessat(fd, try->name, W_OK, 0))) or++;
40 if (!(dir && try->again) && ((or && isatty(0)) || (flags & FLAG_i))) {
41 char *s = dirtree_path(try, 0);
42
43 fprintf(stderr, "rm %s%s%s", or ? "ro " : "", dir ? "dir " : "", s);
44 free(s);
45 or = yesno(0);
46 if (!or) goto nodelete;
47 }
48
49
50 if (dir) {
51 using = AT_REMOVEDIR;
52
53 if (faccessat(fd, try->name, R_OK, 0)) {
54 if (toys.optflags & FLAG_f) wfchmodat(fd, try->name, 0700);
55 else goto skip;
56 }
57 if (!try->again) return DIRTREE_COMEAGAIN;
58 if (try->symlink) goto skip;
59 if (flags & FLAG_i) {
60 char *s = dirtree_path(try, 0);
61
62
63 fprintf(stderr, "rmdir %s", s);
64 free(s);
65 or = yesno(0);
66 if (!or) goto nodelete;
67 }
68 }
69
70skip:
71 if (unlinkat(fd, try->name, using)) {
72 if (!dir || try->symlink != (char *)2) perror_msg_raw(try->name);
73nodelete:
74 if (try->parent) try->parent->symlink = (char *)2;
75 }
76
77 return 0;
78}
79
80void rm_main(void)
81{
82 char **s;
83
84
85 if (!toys.optc && !(toys.optflags & FLAG_f)) error_exit("Needs 1 argument");
86
87 for (s = toys.optargs; *s; s++) {
88 if (!strcmp(*s, "/")) {
89 error_msg("rm /. if you mean it");
90 continue;
91 }
92
93
94
95 if ((toys.optflags & FLAG_f) && (!unlink(*s) || errno == ENOENT))
96 continue;
97
98
99
100
101
102 dirtree_read(*s, do_rm);
103 }
104}
105