• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
usage()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 */
unlink_recursive(const char * name)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 
rm_main(int argc,char * argv[])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 
93