summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES5
-rw-r--r--appl/cmd/trfs.b213
-rw-r--r--dis/trfs.disbin0 -> 3045 bytes
-rw-r--r--emu/port/inferno.c29
-rw-r--r--include/version.h2
-rw-r--r--man/4/trfs22
-rw-r--r--module/sys.m1
-rw-r--r--os/port/inferno.c33
8 files changed, 303 insertions, 2 deletions
diff --git a/CHANGES b/CHANGES
index c0e478e4..5cebc86a 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,8 @@
+20070714
+ add Sys->readn
+ copy two repairs from emu/port/inferno.c to os/port/inferno.c
+20070619
+ remembered to include /appl/cmd/trfs.b /dis/trfs.dis
20070614
/appl/lib/venti.b bug fixes, a few more errstrs, remove prints to stderr
add initial module/vac.m appl/lib/vac.b from mjl (gsoc project ventivac)
diff --git a/appl/cmd/trfs.b b/appl/cmd/trfs.b
new file mode 100644
index 00000000..1ccd0639
--- /dev/null
+++ b/appl/cmd/trfs.b
@@ -0,0 +1,213 @@
+implement Trfs;
+
+include "sys.m";
+ sys: Sys;
+
+include "draw.m";
+
+include "styx.m";
+ styx: Styx;
+ Rmsg, Tmsg: import styx;
+
+Trfs: module
+{
+ init: fn(nil: ref Draw->Context, nil: list of string);
+};
+
+Fid: adt {
+ fid: int;
+ isdir: int;
+ aux: int;
+};
+
+Table: adt[T] {
+ items: array of list of (int, T);
+ nilval: T;
+
+ new: fn(nslots: int, nilval: T): ref Table[T];
+ add: fn(t: self ref Table, id: int, x: T): int;
+ del: fn(t: self ref Table, id: int): T;
+ find: fn(t: self ref Table, id: int): T;
+};
+
+NBspace: con 16r00A0; # Unicode `no-break' space (looks like a faint box in some fonts)
+NBspacelen: con 2; # length of it in utf-8
+
+msize: int;
+lock: chan of int;
+fids: ref Table[ref Fid];
+tfids: ref Table[ref Fid];
+
+init(nil: ref Draw->Context, args: list of string)
+{
+ sys = load Sys Sys->PATH;
+ styx = load Styx Styx->PATH;
+
+ if(len args != 3){
+ sys->fprint(sys->fildes(2), "usage: trfs dir mountpoint\n");
+ raise "fail:usage";
+ }
+ dir := hd tl args;
+ mntpt := hd tl tl args;
+ p := array[2] of ref Sys->FD;
+ q := array[2] of ref Sys->FD;
+ fids = Table[ref Fid].new(11, nil);
+ tfids = Table[ref Fid].new(11, nil);
+ lock = chan[1] of int;
+
+ styx->init();
+ sys->pipe(p);
+ sys->pipe(q);
+ if(sys->export(q[0], dir, Sys->EXPASYNC) < 0)
+ fatal("can't export " + dir);
+ spawn trfsin(p[1], q[1]);
+ spawn trfsout(p[1], q[1]);
+ if(sys->mount(p[0], nil, mntpt, Sys->MREPL|Sys->MCREATE, nil) < 0)
+ fatal("can't mount on " + mntpt);
+}
+
+trfsin(cfd, sfd: ref Sys->FD)
+{
+ while((t:=Tmsg.read(cfd, msize)) != nil){
+ pick m := t {
+ Clunk or
+ Remove =>
+ fids.del(m.fid);
+ Create =>
+ fid := ref Fid(m.fid, 0, 0);
+ fids.add(m.fid, fid);
+ addtfid(m.tag, fid);
+ m.name = tr(m.name, NBspace, ' ');
+ Open =>
+ fid := ref Fid(m.fid, 0, 0);
+ fids.add(m.fid, fid);
+ addtfid(m.tag, fid);
+ Read =>
+ fid := fids.find(m.fid);
+ addtfid(m.tag, fid);
+ if(fid.isdir){
+ m.count /= NBspacelen; # translated strings might grow by this much
+ if(m.offset == big 0)
+ fid.aux = 0;
+ m.offset -= big fid.aux;
+ }
+ Walk =>
+ for(i:=0; i<len m.names; i++)
+ m.names[i] = tr(m.names[i], NBspace, ' ');
+ Wstat =>
+ m.stat.name = tr(m.stat.name, NBspace, ' ');
+ }
+ sys->write(sfd, t.pack(), t.packedsize());
+ }
+}
+
+trfsout(cfd, sfd: ref Sys->FD)
+{
+ b := array[Styx->MAXFDATA] of byte;
+ while((r := Rmsg.read(sfd, msize)) != nil){
+ pick m := r {
+ Version =>
+ msize = m.msize;
+ if(msize > len b)
+ b = array[msize] of byte; # a bit more than needed but doesn't matter
+ Create or
+ Open =>
+ fid := deltfid(m.tag);
+ fid.isdir = m.qid.qtype & Sys->QTDIR;
+ Read =>
+ fid := deltfid(m.tag);
+ if(fid.isdir){
+ bs := 0;
+ for(n := 0; n < len m.data; ){
+ (ds, d) := styx->unpackdir(m.data[n:]);
+ if(ds <= 0)
+ break;
+ d.name = tr(d.name, ' ', NBspace);
+ b[bs:] = styx->packdir(d);
+ bs += styx->packdirsize(d);
+ n += ds;
+ }
+ fid.aux += bs-n;
+ m.data = b[0:bs];
+ }
+ Stat =>
+ m.stat.name = tr(m.stat.name, ' ', NBspace);
+ }
+ sys->write(cfd, r.pack(), r.packedsize());
+ }
+}
+
+tr(name: string, c1, c2: int): string
+{
+ for(i:=0; i<len name; i++)
+ if(name[i] == c1)
+ name[i] = c2;
+ return name;
+}
+
+Table[T].new(nslots: int, nilval: T): ref Table[T]
+{
+ if(nslots == 0)
+ nslots = 13;
+ return ref Table[T](array[nslots] of list of (int, T), nilval);
+}
+
+Table[T].add(t: self ref Table[T], id: int, x: T): int
+{
+ slot := id % len t.items;
+ for(q := t.items[slot]; q != nil; q = tl q)
+ if((hd q).t0 == id)
+ return 0;
+ t.items[slot] = (id, x) :: t.items[slot];
+ return 1;
+}
+
+Table[T].del(t: self ref Table[T], id: int): T
+{
+ p: list of (int, T);
+ slot := id % len t.items;
+ for(q := t.items[slot]; q != nil; q = tl q){
+ if((hd q).t0 == id){
+ t.items[slot] = join(p, tl q);
+ return (hd q).t1;
+ }
+ p = hd q :: p;
+ }
+ return t.nilval;
+}
+
+Table[T].find(t: self ref Table[T], id: int): T
+{
+ for(p := t.items[id % len t.items]; p != nil; p = tl p)
+ if((hd p).t0 == id)
+ return (hd p).t1;
+ return t.nilval;
+}
+
+join[T](x, y: list of (int, T)): list of (int, T)
+{
+ for(; x != nil; x = tl x)
+ y = hd x :: y;
+ return y;
+}
+
+addtfid(t: int, fid: ref Fid)
+{
+ lock <-= 1;
+ tfids.add(t, fid);
+ <- lock;
+}
+
+deltfid(t: int): ref Fid
+{
+ lock <-= 1;
+ r := tfids.del(t);
+ <- lock;
+ return r;
+}
+
+fatal(s: string)
+{
+ sys->fprint(sys->fildes(2), "trfs: %s: %r\n", s);
+ raise "fail:error";
+}
diff --git a/dis/trfs.dis b/dis/trfs.dis
new file mode 100644
index 00000000..5e092428
--- /dev/null
+++ b/dis/trfs.dis
Binary files differ
diff --git a/emu/port/inferno.c b/emu/port/inferno.c
index 1149d623..b568f9fa 100644
--- a/emu/port/inferno.c
+++ b/emu/port/inferno.c
@@ -271,6 +271,35 @@ Sys_read(void *fp)
}
void
+Sys_readn(void *fp)
+{
+ int fd, m, n, t;
+ F_Sys_readn *f;
+
+ f = fp;
+ n = f->n;
+ if(f->buf == (Array*)H || n < 0) {
+ *f->ret = 0;
+ return;
+ }
+ if(n > f->buf->len)
+ n = f->buf->len;
+ fd = fdchk(f->fd);
+
+ release();
+ for(t = 0; t < n; t += m){
+ m = kread(fd, (char*)f->buf->data+t, n-t);
+ if(m <= 0){
+ if(t == 0)
+ t = m;
+ break;
+ }
+ }
+ *f->ret = t;
+ acquire();
+}
+
+void
Sys_pread(void *fp)
{
int n;
diff --git a/include/version.h b/include/version.h
index 2bf1eba1..d651e3c6 100644
--- a/include/version.h
+++ b/include/version.h
@@ -1 +1 @@
-#define VERSION "Fourth Edition (20070614)"
+#define VERSION "Fourth Edition (20070714)"
diff --git a/man/4/trfs b/man/4/trfs
new file mode 100644
index 00000000..cc7ecdb5
--- /dev/null
+++ b/man/4/trfs
@@ -0,0 +1,22 @@
+.TH TRFS 4
+.SH NAME
+trfs \- translate spaces and other runes in names in a file system
+.SH SYNOPSIS
+.B trfs
+.I olddir
+.I mountdir
+.SH DESCRIPTION
+.I Trfs
+makes the contents of directory
+.I olddir
+appear on the directory
+.IR mountdir ,
+but every space character in file and directory names viewed through
+.I mountdir
+is made visible as a special `no-break space' character (U+00A0).
+Other Inferno applications will not mistake it for the end of a file name,
+and it has some visible representation in most fonts.
+.SH SOURCE
+.B /appl/cmd/trfs.b
+.SH BUGS
+There can be error or ambiguity if the existing tree also uses no-break space in its names.
diff --git a/module/sys.m b/module/sys.m
index 1fed789f..0852bb18 100644
--- a/module/sys.m
+++ b/module/sys.m
@@ -145,6 +145,7 @@ Sys: module
pread: fn(fd: ref FD, buf: array of byte, n: int, off: big): int;
pwrite: fn(fd: ref FD, buf: array of byte, n: int, off: big): int;
read: fn(fd: ref FD, buf: array of byte, n: int): int;
+ readn: fn(fd: ref FD, buf: array of byte, n: int): int;
remove: fn(s: string): int;
seek: fn(fd: ref FD, off: big, start: int): big;
sleep: fn(period: int): int;
diff --git a/os/port/inferno.c b/os/port/inferno.c
index 82de83d6..8858ec1e 100644
--- a/os/port/inferno.c
+++ b/os/port/inferno.c
@@ -62,7 +62,8 @@ freeFD(Heap *h, int swept)
handle = H2D(FD*, h);
release();
- kfgrpclose(handle->grp, handle->fd.fd);
+ if(handle->fd.fd >= 0)
+ kfgrpclose(handle->grp, handle->fd.fd);
closefgrp(handle->grp);
acquire();
}
@@ -273,6 +274,35 @@ Sys_read(void *fp)
}
void
+Sys_readn(void *fp)
+{
+ int fd, m, n, t;
+ F_Sys_readn *f;
+
+ f = fp;
+ n = f->n;
+ if(f->buf == (Array*)H || n < 0) {
+ *f->ret = 0;
+ return;
+ }
+ if(n > f->buf->len)
+ n = f->buf->len;
+ fd = fdchk(f->fd);
+
+ release();
+ for(t = 0; t < n; t += m){
+ m = kread(fd, (char*)f->buf->data+t, n-t);
+ if(m <= 0){
+ if(t == 0)
+ t = m;
+ break;
+ }
+ }
+ *f->ret = t;
+ acquire();
+}
+
+void
Sys_pread(void *fp)
{
int n;
@@ -380,6 +410,7 @@ packdir(Sys_Dir *sd)
for(i=0; i<4; i++){
n = strlen(nm[i])+1;
memmove(p, nm[i], n);
+ nm[i] = p;
p += n;
}
d->name = nm[0];