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