1 #include <u.h>
2 #include <libc.h>
3
4 char errbuf[ERRMAX];
5 int ignerr = 0;
6
7 void
err(char * f)8 err(char *f)
9 {
10 if(!ignerr){
11 errbuf[0] = '\0';
12 errstr(errbuf, sizeof errbuf);
13 fprint(2, "rm: %s: %s\n", f, errbuf);
14 }
15 }
16
17 /*
18 * f is a non-empty directory. Remove its contents and then it.
19 */
20 void
rmdir(char * f)21 rmdir(char *f)
22 {
23 char *name;
24 int fd, i, j, n, ndir, nname;
25 Dir *dirbuf;
26
27 fd = open(f, OREAD);
28 if(fd < 0){
29 err(f);
30 return;
31 }
32 n = dirreadall(fd, &dirbuf);
33 close(fd);
34 if(n < 0){
35 err("dirreadall");
36 return;
37 }
38
39 nname = strlen(f)+1+STATMAX+1; /* plenty! */
40 name = malloc(nname);
41 if(name == 0){
42 err("memory allocation");
43 return;
44 }
45
46 ndir = 0;
47 for(i=0; i<n; i++){
48 snprint(name, nname, "%s/%s", f, dirbuf[i].name);
49 if(remove(name) != -1)
50 dirbuf[i].qid.type = QTFILE; /* so we won't recurse */
51 else{
52 if(dirbuf[i].qid.type & QTDIR)
53 ndir++;
54 else
55 err(name);
56 }
57 }
58 if(ndir)
59 for(j=0; j<n; j++)
60 if(dirbuf[j].qid.type & QTDIR){
61 snprint(name, nname, "%s/%s", f, dirbuf[j].name);
62 rmdir(name);
63 }
64 if(remove(f) == -1)
65 err(f);
66 free(name);
67 free(dirbuf);
68 }
69 void
main(int argc,char * argv[])70 main(int argc, char *argv[])
71 {
72 int i;
73 int recurse;
74 char *f;
75 Dir *db;
76
77 ignerr = 0;
78 recurse = 0;
79 ARGBEGIN{
80 case 'r':
81 recurse = 1;
82 break;
83 case 'f':
84 ignerr = 1;
85 break;
86 default:
87 fprint(2, "usage: rm [-fr] file ...\n");
88 exits("usage");
89 }ARGEND
90 for(i=0; i<argc; i++){
91 f = argv[i];
92 if(remove(f) != -1)
93 continue;
94 db = nil;
95 if(recurse && (db=dirstat(f))!=nil && (db->qid.type&QTDIR))
96 rmdir(f);
97 else
98 err(f);
99 free(db);
100 }
101 exits(errbuf);
102 }
103