diff options
Diffstat (limited to 'toolbox/rm.c')
-rw-r--r-- | toolbox/rm.c | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/toolbox/rm.c b/toolbox/rm.c new file mode 100644 index 000000000..bd6631181 --- /dev/null +++ b/toolbox/rm.c | |||
@@ -0,0 +1,92 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <unistd.h> | ||
3 | #include <string.h> | ||
4 | #include <errno.h> | ||
5 | #include <dirent.h> | ||
6 | #include <limits.h> | ||
7 | #include <sys/stat.h> | ||
8 | #include <sys/types.h> | ||
9 | |||
10 | static int usage() | ||
11 | { | ||
12 | fprintf(stderr,"rm [-rR] <target>\n"); | ||
13 | return -1; | ||
14 | } | ||
15 | |||
16 | /* return -1 on failure, with errno set to the first error */ | ||
17 | static int unlink_recursive(const char* name) | ||
18 | { | ||
19 | struct stat st; | ||
20 | DIR *dir; | ||
21 | struct dirent *de; | ||
22 | int fail = 0; | ||
23 | |||
24 | /* is it a file or directory? */ | ||
25 | if (lstat(name, &st) < 0) | ||
26 | return -1; | ||
27 | |||
28 | /* a file, so unlink it */ | ||
29 | if (!S_ISDIR(st.st_mode)) | ||
30 | return unlink(name); | ||
31 | |||
32 | /* a directory, so open handle */ | ||
33 | dir = opendir(name); | ||
34 | if (dir == NULL) | ||
35 | return -1; | ||
36 | |||
37 | /* recurse over components */ | ||
38 | errno = 0; | ||
39 | while ((de = readdir(dir)) != NULL) { | ||
40 | char dn[PATH_MAX]; | ||
41 | if (!strcmp(de->d_name, "..") || !strcmp(de->d_name, ".")) | ||
42 | continue; | ||
43 | sprintf(dn, "%s/%s", name, de->d_name); | ||
44 | if (unlink_recursive(dn) < 0) { | ||
45 | fail = 1; | ||
46 | break; | ||
47 | } | ||
48 | errno = 0; | ||
49 | } | ||
50 | /* in case readdir or unlink_recursive failed */ | ||
51 | if (fail || errno < 0) { | ||
52 | int save = errno; | ||
53 | closedir(dir); | ||
54 | errno = save; | ||
55 | return -1; | ||
56 | } | ||
57 | |||
58 | /* close directory handle */ | ||
59 | if (closedir(dir) < 0) | ||
60 | return -1; | ||
61 | |||
62 | /* delete target directory */ | ||
63 | return rmdir(name); | ||
64 | } | ||
65 | |||
66 | int rm_main(int argc, char *argv[]) | ||
67 | { | ||
68 | int ret; | ||
69 | int i = 1; | ||
70 | int recursive = 0; | ||
71 | |||
72 | if (argc < 2) | ||
73 | return usage(); | ||
74 | |||
75 | /* check if recursive */ | ||
76 | if (argc >=2 && (!strcmp(argv[1], "-r") || !strcmp(argv[1], "-R"))) { | ||
77 | recursive = 1; | ||
78 | i = 2; | ||
79 | } | ||
80 | |||
81 | /* loop over the file/directory args */ | ||
82 | for (; i < argc; i++) { | ||
83 | int ret = recursive ? unlink_recursive(argv[i]) : unlink(argv[i]); | ||
84 | if (ret < 0) { | ||
85 | fprintf(stderr, "rm failed for %s, %s\n", argv[i], strerror(errno)); | ||
86 | return -1; | ||
87 | } | ||
88 | } | ||
89 | |||
90 | return 0; | ||
91 | } | ||
92 | |||