aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/rm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/rm.c')
-rw-r--r--src/cmd/rm.c104
1 files changed, 104 insertions, 0 deletions
diff --git a/src/cmd/rm.c b/src/cmd/rm.c
new file mode 100644
index 00000000..6066543e
--- /dev/null
+++ b/src/cmd/rm.c
@@ -0,0 +1,104 @@
+#include <u.h>
+#include <libc.h>
+
+#define rmdir p9rmdir
+
+char errbuf[ERRMAX];
+int ignerr = 0;
+
+void
+err(char *f)
+{
+ if(!ignerr){
+ errbuf[0] = '\0';
+ errstr(errbuf, sizeof errbuf);
+ fprint(2, "rm: %s: %s\n", f, errbuf);
+ }
+}
+
+/*
+ * f is a non-empty directory. Remove its contents and then it.
+ */
+void
+rmdir(char *f)
+{
+ char *name;
+ int fd, i, j, n, ndir, nname;
+ Dir *dirbuf;
+
+ fd = open(f, OREAD);
+ if(fd < 0){
+ err(f);
+ return;
+ }
+ n = dirreadall(fd, &dirbuf);
+ close(fd);
+ if(n < 0){
+ err("dirreadall");
+ return;
+ }
+
+ nname = strlen(f)+1+STATMAX+1; /* plenty! */
+ name = malloc(nname);
+ if(name == 0){
+ err("memory allocation");
+ return;
+ }
+
+ ndir = 0;
+ for(i=0; i<n; i++){
+ snprint(name, nname, "%s/%s", f, dirbuf[i].name);
+ if(remove(name) != -1)
+ dirbuf[i].qid.type = QTFILE; /* so we won't recurse */
+ else{
+ if(dirbuf[i].qid.type & QTDIR)
+ ndir++;
+ else
+ err(name);
+ }
+ }
+ if(ndir)
+ for(j=0; j<n; j++)
+ if(dirbuf[j].qid.type & QTDIR){
+ snprint(name, nname, "%s/%s", f, dirbuf[j].name);
+ rmdir(name);
+ }
+ if(remove(f) == -1)
+ err(f);
+ free(name);
+ free(dirbuf);
+}
+void
+main(int argc, char *argv[])
+{
+ int i;
+ int recurse;
+ char *f;
+ Dir *db;
+
+ ignerr = 0;
+ recurse = 0;
+ ARGBEGIN{
+ case 'r':
+ recurse = 1;
+ break;
+ case 'f':
+ ignerr = 1;
+ break;
+ default:
+ fprint(2, "usage: rm [-fr] file ...\n");
+ exits("usage");
+ }ARGEND
+ for(i=0; i<argc; i++){
+ f = argv[i];
+ if(remove(f) != -1)
+ continue;
+ db = nil;
+ if(recurse && (db=dirstat(f))!=nil && (db->qid.type&QTDIR))
+ rmdir(f);
+ else
+ err(f);
+ free(db);
+ }
+ exits(errbuf);
+}