diff options
| author | Charles.Forsyth <devnull@localhost> | 2007-07-14 09:52:44 +0000 |
|---|---|---|
| committer | Charles.Forsyth <devnull@localhost> | 2007-07-14 09:52:44 +0000 |
| commit | ad88539715c50f30c4e8fca27338158dc33feaaa (patch) | |
| tree | 2423bd08dc7f3e7734b460c801a11e3c243c405d | |
| parent | 150ed664169adc7de05ac8c4fdcf87a0987bc372 (diff) | |
20070714-1052
| -rw-r--r-- | CHANGES | 5 | ||||
| -rw-r--r-- | appl/cmd/trfs.b | 213 | ||||
| -rw-r--r-- | dis/trfs.dis | bin | 0 -> 3045 bytes | |||
| -rw-r--r-- | emu/port/inferno.c | 29 | ||||
| -rw-r--r-- | include/version.h | 2 | ||||
| -rw-r--r-- | man/4/trfs | 22 | ||||
| -rw-r--r-- | module/sys.m | 1 | ||||
| -rw-r--r-- | os/port/inferno.c | 33 |
8 files changed, 303 insertions, 2 deletions
@@ -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 Binary files differnew file mode 100644 index 00000000..5e092428 --- /dev/null +++ b/dis/trfs.dis 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]; |
