1 #include <stdio.h>
2 #include <dirent.h>
3 #include <string.h>
4 #include <errno.h>
5 #include <unistd.h>
6 #include <sys/stat.h>
7 #include <aos/cli.h>
8 #include <stdbool.h>
9 #include <fcntl.h>
10 #include <stdlib.h>
11 #include <path_helper.h>
12 
show_help(void)13 static void show_help(void)
14 {
15     aos_cli_printf("Usage:\n"
16                "rm <file1> [<file2>...]\n"
17                "rm -r <dir>\n");
18 }
19 
rrmdir(const char * path)20 int rrmdir(const char *path)
21 {
22     struct stat s;
23     DIR *pdir = NULL;
24     struct dirent *entry = NULL;
25     int ret = -1;
26     char *dir, *p;
27 
28     if (!path)
29         return -EINVAL;
30 
31     dir = strdup(path);
32     p = dir + strlen(dir) - 1;
33     while ((*p == '/') && (p > dir)) {
34         *p = '\0';
35         p--;
36     }
37 
38     if (stat(dir, &s) || !S_ISDIR(s.st_mode)) {
39         aos_cli_printf("%s is neither existed nor a directory\n", dir);
40         goto out;
41     }
42 
43     pdir = opendir(dir);
44     if (!pdir) {
45         aos_cli_printf("opendir %s failed - %s\n", dir, strerror(errno));
46         goto out;
47     }
48 
49     ret = 0;
50     while ((ret == 0) && (entry = readdir(pdir))) {
51         char fpath[128];
52 
53         snprintf(fpath, 128, "%s/%s", dir, entry->d_name);
54 
55         ret = stat(fpath, &s);
56         if (ret) {
57             aos_cli_printf("stat %s failed\n", fpath);
58             break;
59         }
60 
61         if (!strcmp(entry->d_name, "."))
62             continue;
63         if (!strcmp(entry->d_name, ".."))
64             continue;
65 
66         if (S_ISDIR(s.st_mode))
67             ret = rrmdir(fpath);
68         else
69             ret = unlink(fpath);
70     }
71 
72     closedir(pdir);
73     if (ret == 0) {
74         ret = rmdir(dir);
75         if (ret)
76             aos_cli_printf("rmdir %s failed\n", dir);
77     }
78 out:
79     free(dir);
80     return ret;
81 }
82 
83 #define RM_FLAG_RECURSION (1 << 0)
rm_main(int argc,char ** argv)84 static int rm_main(int argc, char **argv)
85 {
86     int opts = 0, flags = 0, index, ret = 0;
87 
88     optind = 0;
89     while ((opts = getopt(argc, argv, ":r")) != EOF) {
90         switch (opts) {
91             case 'r':
92                 flags |= RM_FLAG_RECURSION;
93                 break;
94             case '?':
95                 aos_cli_printf("invalid option %c\n", optopt);
96                 return -1;
97             case ':':
98                 aos_cli_printf("option -%c requires an argument\n", optopt);
99                 show_help();
100                 return -1;
101         }
102     }
103 
104     argc -= optind;
105     argv += optind;
106 
107     if (argc < 1) {
108         show_help();
109         return -1;
110     }
111 
112     for (index = 0; index < argc; index++) {
113         struct stat s;
114         char *path = argv[index];
115         char abspath[256] = {0};
116 
117         path = get_realpath(path, abspath, sizeof(abspath));
118         if (!path) {
119             aos_cli_printf("Failed to get real path!\r\n");
120             return -1;
121         }
122 
123         if (!stat(path, &s) && S_ISREG(s.st_mode)) {
124             ret |= unlink(path);
125             aos_cli_printf("remove %s\n", path);
126             continue;
127         }
128 
129         if (flags & RM_FLAG_RECURSION) {
130             aos_cli_printf("remove dir %s\n", path);
131             ret |= rrmdir(path);
132             continue;
133         }
134 
135         ret |= -ENOENT;
136         aos_cli_printf("%s is neither existed nor a directory\n", path);
137     }
138 
139     return ret;
140 }
141 ALIOS_CLI_CMD_REGISTER(rm_main, rm, remove file);
142