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