From ad88539715c50f30c4e8fca27338158dc33feaaa Mon Sep 17 00:00:00 2001 From: "Charles.Forsyth" Date: Sat, 14 Jul 2007 09:52:44 +0000 Subject: 20070714-1052 --- CHANGES | 5 ++ appl/cmd/trfs.b | 213 +++++++++++++++++++++++++++++++++++++++++++++++++++++ dis/trfs.dis | Bin 0 -> 3045 bytes emu/port/inferno.c | 29 ++++++++ include/version.h | 2 +- man/4/trfs | 22 ++++++ module/sys.m | 1 + os/port/inferno.c | 33 ++++++++- 8 files changed, 303 insertions(+), 2 deletions(-) create mode 100644 appl/cmd/trfs.b create mode 100644 dis/trfs.dis create mode 100644 man/4/trfs 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 + 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; ifprint(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 Binary files /dev/null and b/dis/trfs.dis 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 @@ -270,6 +270,35 @@ Sys_read(void *fp) acquire(); } +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) { 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(); } @@ -272,6 +273,35 @@ Sys_read(void *fp) acquire(); } +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) { @@ -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]; -- cgit v1.2.3