rm.c - 9base - revived minimalist port of Plan 9 userland to Unix | |
git clone git://git.suckless.org/9base | |
Log | |
Files | |
Refs | |
README | |
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… | |
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[… | |
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&QTDI… | |
106 rmdir(f); | |
107 else | |
108 err(f); | |
109 free(db); | |
110 } | |
111 exits(errbuf); | |
112 } |