xref: /plan9/sys/src/cmd/rm.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
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