summaryrefslogtreecommitdiff
path: root/appl/cmd/rm.b
diff options
context:
space:
mode:
Diffstat (limited to 'appl/cmd/rm.b')
-rw-r--r--appl/cmd/rm.b99
1 files changed, 99 insertions, 0 deletions
diff --git a/appl/cmd/rm.b b/appl/cmd/rm.b
new file mode 100644
index 00000000..af8236be
--- /dev/null
+++ b/appl/cmd/rm.b
@@ -0,0 +1,99 @@
+implement Rm;
+
+include "sys.m";
+ sys: Sys;
+include "draw.m";
+
+include "readdir.m";
+ readdir: Readdir;
+
+include "arg.m";
+
+Rm: module
+{
+ init: fn(ctxt: ref Draw->Context, argv: list of string);
+};
+
+stderr: ref Sys->FD;
+quiet := 0;
+force := 0;
+errcount := 0;
+
+usage()
+{
+ sys->fprint(stderr, "Usage: rm [-fr] file ...\n");
+ raise "fail: usage";
+}
+allwrite := Sys->nulldir;
+
+init(nil: ref Draw->Context, args: list of string)
+{
+ sys = load Sys Sys->PATH;
+ stderr = sys->fildes(2);
+ allwrite.mode = 8r777 | Sys->DMDIR;
+
+ arg := load Arg Arg->PATH;
+ if(arg == nil){
+ sys->fprint(stderr, "rm: can't load %s: %r\n", Arg->PATH);
+ raise "fail:load";
+ }
+ arg->init(args);
+ while((o := arg->opt()) != 0)
+ case o {
+ 'r' =>
+ readdir = load Readdir Readdir->PATH;
+ if(readdir == nil)
+ sys->fprint(stderr, "rm: can't load Readdir: %r\n"); # -r is regarded as optional
+ 'f' =>
+ quiet = 1;
+ 'F' =>
+ force = 1;
+ * =>
+ usage();
+ }
+ args = arg->argv();
+ arg = nil;
+ sys->pctl(Sys->FORKNS, nil);
+ for(; args != nil; args = tl args) {
+ name := hd args;
+ if(sys->remove(name) < 0) {
+ e := sys->sprint("%r");
+ (ok, d) := sys->stat(name);
+ if(readdir != nil && ok >= 0 && (d.mode & Sys->DMDIR) != 0)
+ rmdir(name);
+ else
+ err(name, e);
+ }
+ }
+ if(errcount > 0)
+ raise "fail:errors";
+}
+
+rmdir(name: string)
+{
+ if(force)
+ sys->wstat(name, allwrite);
+ (d, n) := readdir->init(name, Readdir->NONE|Readdir->COMPACT);
+ for(i := 0; i < n; i++){
+ path := name+"/"+d[i].name;
+ if(d[i].mode & Sys->DMDIR)
+ rmdir(path);
+ else
+ remove(path);
+ }
+ remove(name);
+}
+
+remove(name: string)
+{
+ if(sys->remove(name) < 0)
+ err(name, sys->sprint("%r"));
+}
+
+err(name, e: string)
+{
+ if(!quiet) {
+ sys->fprint(stderr, "rm: %s: %s\n", name, e);
+ errcount++;
+ }
+}