[inferno-npe] 5 new revisions pushed by extrudedaluminiu on 2010-02-21 14:25 GMT

1 view
Skip to first unread message

infer...@googlecode.com

unread,
Feb 21, 2010, 9:26:09 AM2/21/10
to inferno-n...@googlegroups.com
5 new revisions:

Revision: 0d6c060f8a
Author: for...@vitanuova.com
Date: Tue Feb 9 12:25:28 2010
Log: 20100209-2025
http://code.google.com/p/inferno-npe/source/detail?r=0d6c060f8a

Revision: da33526f10
Author: for...@vitanuova.com
Date: Wed Feb 10 08:58:28 2010
Log: 20100210-1658
http://code.google.com/p/inferno-npe/source/detail?r=da33526f10

Revision: 47bd0f44e7
Author: for...@vitanuova.com
Date: Sat Feb 13 13:14:07 2010
Log: 20100213-2114
http://code.google.com/p/inferno-npe/source/detail?r=47bd0f44e7

Revision: 416eb2c905
Author: for...@vitanuova.com
Date: Sun Feb 21 04:11:43 2010
Log: 20100221-1211
http://code.google.com/p/inferno-npe/source/detail?r=416eb2c905

Revision: 62d7bd2f90
Author: me@challenger
Date: Sun Feb 21 06:23:46 2010
Log: Merge with inferno-os 20100220.
http://code.google.com/p/inferno-npe/source/detail?r=62d7bd2f90

==============================================================================
Revision: 0d6c060f8a
Author: for...@vitanuova.com
Date: Tue Feb 9 12:25:28 2010
Log: 20100209-2025
http://code.google.com/p/inferno-npe/source/detail?r=0d6c060f8a

Modified:
/appl/cmd/limbo/stubs.b
/dis/limbo.dis
/include/version.h
/limbo/stubs.c

=======================================
--- /appl/cmd/limbo/stubs.b Tue Feb 17 03:18:45 2009
+++ /appl/cmd/limbo/stubs.b Tue Feb 9 12:25:28 2010
@@ -20,12 +20,8 @@
}
}
if(emitstub){
- print("#pragma hjdicks x4\n");
- print("#pragma pack x4\n");
adtstub(globals);
modstub(globals);
- print("#pragma pack off\n");
- print("#pragma hjdicks off\n");
}
if(emittab != nil)
modtab(globals);
=======================================
--- /dis/limbo.dis Wed Apr 1 15:46:59 2009
+++ /dis/limbo.dis Tue Feb 9 12:25:28 2010
Binary file, no diff available.
=======================================
--- /include/version.h Fri Feb 5 03:01:55 2010
+++ /include/version.h Tue Feb 9 12:25:28 2010
@@ -1,1 +1,1 @@
-#define VERSION "Fourth Edition (20100205)"
+#define VERSION "Fourth Edition (20100209)"
=======================================
--- /limbo/stubs.c Tue Feb 17 03:18:45 2009
+++ /limbo/stubs.c Tue Feb 9 12:25:28 2010
@@ -25,12 +25,8 @@
}
}
if(emitstub){
- print("#pragma hjdicks x4\n");
- print("#pragma pack x4\n");
adtstub(globals);
modstub(globals);
- print("#pragma pack off\n");
- print("#pragma hjdicks off\n");
}
if(emittab != nil)
modtab(globals);

==============================================================================
Revision: da33526f10
Author: for...@vitanuova.com
Date: Wed Feb 10 08:58:28 2010
Log: 20100210-1658
http://code.google.com/p/inferno-npe/source/detail?r=da33526f10

Modified:
/libinterp/runt.h

=======================================
--- /libinterp/runt.h Wed Feb 3 12:48:47 2010
+++ /libinterp/runt.h Wed Feb 10 08:58:28 2010
@@ -1,5 +1,3 @@
-#pragma hjdicks x4
-#pragma pack x4
typedef struct Sys_Qid Sys_Qid;
typedef struct Sys_Dir Sys_Dir;
typedef struct Sys_FD Sys_FD;
@@ -4264,5 +4262,3 @@
#define Freetype_PATH "$Freetype"
#define Freetype_STYLE_ITALIC 1
#define Freetype_STYLE_BOLD 2
-#pragma pack off
-#pragma hjdicks off

==============================================================================
Revision: 47bd0f44e7
Author: for...@vitanuova.com
Date: Sat Feb 13 13:14:07 2010
Log: 20100213-2114
http://code.google.com/p/inferno-npe/source/detail?r=47bd0f44e7

Added:
/libkern/div-thumb.s
Modified:
/CHANGES
/emu/port/devfs-posix.c
/include/version.h
/libkern/mkfile-thumb
/mkfiles/mkfile-os-thumb
/os/port/portmkfile
/utils/5l/span.c

=======================================
--- /dev/null
+++ /libkern/div-thumb.s Sat Feb 13 13:14:07 2010
@@ -0,0 +1,119 @@
+Q = 0
+N = 1
+D = 2
+CC = 3
+TMP = 11
+
+TEXT save<>(SB), 1, $0
+ MOVW R(Q), 0(FP)
+ MOVW R(N), 4(FP)
+ MOVW R(D), 8(FP)
+ MOVW R(CC), 12(FP)
+
+ MOVW R(TMP), R(Q) /* numerator */
+ MOVW 20(FP), R(D) /* denominator */
+ CMP $0, R(D)
+ BNE s1
+ SWI 0
+/* MOVW -1(R(D)), R(TMP) /* divide by zero fault */
+s1: RET
+
+TEXT rest<>(SB), 1, $0
+ MOVW 0(FP), R(Q)
+ MOVW 4(FP), R(N)
+ MOVW 8(FP), R(D)
+ MOVW 12(FP), R(CC)
+/*
+ * return to caller
+ * of rest<>
+ */
+ MOVW 0(R13), R14
+ ADD $20, R13
+ B (R14)
+
+TEXT div<>(SB), 1, $0
+ MOVW $32, R(CC)
+/*
+ * skip zeros 8-at-a-time
+ */
+e1:
+ AND.S $(0xff<<24),R(Q), R(N)
+ BNE e2
+ SLL $8, R(Q)
+ SUB.S $8, R(CC)
+ BNE e1
+ RET
+e2:
+ MOVW $0, R(N)
+
+loop:
+/*
+ * shift R(N||Q) left one
+ */
+ SLL $1, R(N)
+ CMP $0, R(Q)
+ ORR.LT $1, R(N)
+ SLL $1, R(Q)
+
+/*
+ * compare numerator to denominator
+ * if less, subtract and set quotent bit
+ */
+ CMP R(D), R(N)
+ ORR.HS $1, R(Q)
+ SUB.HS R(D), R(N)
+ SUB.S $1, R(CC)
+ BNE loop
+ RET
+
+TEXT _div(SB), 1, $16
+ BL save<>(SB)
+ CMP $0, R(Q)
+ BGE d1
+ RSB $0, R(Q), R(Q)
+ CMP $0, R(D)
+ BGE d2
+ RSB $0, R(D), R(D)
+d0:
+ BL div<>(SB) /* none/both neg */
+ MOVW R(Q), R(TMP)
+ B out
+d1:
+ CMP $0, R(D)
+ BGE d0
+ RSB $0, R(D), R(D)
+d2:
+ BL div<>(SB) /* one neg */
+ RSB $0, R(Q), R(TMP)
+ B out
+
+TEXT _mod(SB), 1, $16
+ BL save<>(SB)
+ CMP $0, R(D)
+ RSB.LT $0, R(D), R(D)
+ CMP $0, R(Q)
+ BGE m1
+ RSB $0, R(Q), R(Q)
+ BL div<>(SB) /* neg numerator */
+ RSB $0, R(N), R(TMP)
+ B out
+m1:
+ BL div<>(SB) /* pos numerator */
+ MOVW R(N), R(TMP)
+ B out
+
+TEXT _divu(SB), 1, $16
+ BL save<>(SB)
+ BL div<>(SB)
+ MOVW R(Q), R(TMP)
+ B out
+
+TEXT _modu(SB), 1, $16
+ BL save<>(SB)
+ BL div<>(SB)
+ MOVW R(N), R(TMP)
+ B out
+
+out:
+ BL rest<>(SB)
+ B out
=======================================
--- /CHANGES Fri Feb 5 07:56:39 2010
+++ /CHANGES Sat Feb 13 13:14:07 2010
@@ -1,3 +1,5 @@
+20100213
+ apply saoret.one's changes for thumb [issue 155]
20100205
update man pages to replace most references to Styx by 9P
update man pages to replace references to sys-dial(2) by dial(2)
=======================================
--- /emu/port/devfs-posix.c Thu Nov 19 09:08:00 2009
+++ /emu/port/devfs-posix.c Sat Feb 13 13:14:07 2010
@@ -750,7 +750,7 @@
struct stat stbuf;
char path[MAXPATH], *ep;
struct dirent *de;
- static char slop[8192];
+ static uchar slop[8192];

i = 0;
fspath(FS(c)->name, "", path);
@@ -951,7 +951,6 @@
newuname(char *name)
{
struct passwd *p;
- User *u;

p = getpwnam(name);
if(p == nil)
@@ -963,7 +962,6 @@
newuid(int id)
{
struct passwd *p;
- User *u;

p = getpwuid(id);
if(p == nil)
@@ -1010,7 +1008,6 @@
static User*
id2user(User **tab, int id, User* (*get)(int))
{
- int i;
User *u, **h;

h = hashuser(tab, id);
=======================================
--- /include/version.h Tue Feb 9 12:25:28 2010
+++ /include/version.h Sat Feb 13 13:14:07 2010
@@ -1,1 +1,1 @@
-#define VERSION "Fourth Edition (20100209)"
+#define VERSION "Fourth Edition (20100213)"
=======================================
--- /libkern/mkfile-thumb Fri Dec 22 09:07:39 2006
+++ /libkern/mkfile-thumb Sat Feb 13 13:14:07 2010
@@ -10,3 +10,4 @@
strchr-thumb.$O\
vlop-thumb.$O\
vlrt-thumb.$O\
+ div-thumb.$O\
=======================================
--- /mkfiles/mkfile-os-thumb Wed Jul 23 12:37:49 2008
+++ /mkfiles/mkfile-os-thumb Sat Feb 13 13:14:07 2010
@@ -1,7 +1,7 @@
TARGMODEL= Inferno
TARGSHTYPE= sh
CPUS= arm
-OBJDIR= Inferno/arm #force everything to point to inferno directory
+OBJDIR= Inferno/thumb #force everything to point to inferno directory

O= t
OS= 5t
@@ -11,10 +11,10 @@
ARPREFIX=

AS= 5a
-ASFLAGS=
+ASFLAGS= -t

CC= tc
-CFLAGS= -wFV -I$ROOT/Inferno/arm/include -I$ROOT/include
+CFLAGS= -wFV -I$ROOT/Inferno/thumb/include -I$ROOT/include
ANSICPP= -p

LD= 5l
=======================================
--- /os/port/portmkfile Fri Dec 22 16:30:12 2006
+++ /os/port/portmkfile Sat Feb 13 13:14:07 2010
@@ -9,7 +9,7 @@
CLEANEXTRA=

%.$O: %.s
- $AS $stem.s
+ $AS $ASFLAGS $stem.s

%.$O: %.c
$CC $CFLAGS $stem.c
=======================================
--- /utils/5l/span.c Fri Dec 22 13:39:35 2006
+++ /utils/5l/span.c Sat Feb 13 13:14:07 2010
@@ -266,7 +266,7 @@

loop:
passes++;
- if(passes > 100){
+ if(passes > 150){
diag("span looping !");
errorexit();
}

==============================================================================
Revision: 416eb2c905
Author: for...@vitanuova.com
Date: Sun Feb 21 04:11:43 2010
Log: 20100221-1211
http://code.google.com/p/inferno-npe/source/detail?r=416eb2c905

Added:
/appl/lib/ninep.b
/dis/lib/ninep.dis
/man/2/9p-ninep
/module/9p.m
Modified:
/CHANGES
/appl/cmd/9660srv.b
/appl/cmd/auth/keyfs.b
/appl/cmd/dossrv.b
/appl/cmd/ftpfs.b
/appl/lib/styx.b
/dis/9660srv.dis
/dis/auth/keyfs.dis
/dis/dossrv.dis
/dis/ftpfs.dis
/dis/lib/styx.dis
/include/version.h

=======================================
--- /dev/null
+++ /appl/lib/ninep.b Sun Feb 21 04:11:43 2010
@@ -0,0 +1,914 @@
+implement Ninep;
+
+include "sys.m";
+ sys: Sys;
+
+include "9p.m";
+
+STR: con BIT16SZ; # string length
+TAG: con BIT16SZ;
+FID: con BIT32SZ;
+QID: con BIT8SZ+BIT32SZ+BIT64SZ;
+LEN: con BIT16SZ; # stat and qid array lengths
+COUNT: con BIT32SZ;
+OFFSET: con BIT64SZ;
+
+H: con BIT32SZ+BIT8SZ+BIT16SZ; # minimum header length: size[4] type tag[2]
+
+#
+# the following array could be shorter if it were indexed by
(type-Tversion)
+#
+hdrlen := array[Tmax] of
+{
+Tversion => H+COUNT+STR, # size[4] Tversion tag[2] msize[4] version[s]
+Rversion => H+COUNT+STR, # size[4] Rversion tag[2] msize[4] version[s]
+
+Tauth => H+FID+STR+STR, # size[4] Tauth tag[2] afid[4] uname[s] aname[s]
+Rauth => H+QID, # size[4] Rauth tag[2] aqid[13]
+
+Rerror => H+STR, # size[4] Rerror tag[2] ename[s]
+
+Tflush => H+TAG, # size[4] Tflush tag[2] oldtag[2]
+Rflush => H, # size[4] Rflush tag[2]
+
+Tattach => H+FID+FID+STR+STR, # size[4] Tattach tag[2] fid[4] afid[4]
uname[s] aname[s]
+Rattach => H+QID, # size[4] Rattach tag[2] qid[13]
+
+Twalk => H+FID+FID+LEN, # size[4] Twalk tag[2] fid[4] newfid[4] nwname[2]
nwname*(wname[s])
+Rwalk => H+LEN, # size[4] Rwalk tag[2] nwqid[2] nwqid*(wqid[13])
+
+Topen => H+FID+BIT8SZ, # size[4] Topen tag[2] fid[4] mode[1]
+Ropen => H+QID+COUNT, # size[4] Ropen tag[2] qid[13] iounit[4]
+
+Tcreate => H+FID+STR+BIT32SZ+BIT8SZ, # size[4] Tcreate tag[2] fid[4]
name[s] perm[4] mode[1]
+Rcreate => H+QID+COUNT, # size[4] Rcreate tag[2] qid[13] iounit[4]
+
+Tread => H+FID+OFFSET+COUNT, # size[4] Tread tag[2] fid[4] offset[8]
count[4]
+Rread => H+COUNT, # size[4] Rread tag[2] count[4] data[count]
+
+Twrite => H+FID+OFFSET+COUNT, # size[4] Twrite tag[2] fid[4] offset[8]
count[4] data[count]
+Rwrite => H+COUNT, # size[4] Rwrite tag[2] count[4]
+
+Tclunk => H+FID, # size[4] Tclunk tag[2] fid[4]
+Rclunk => H, # size[4] Rclunk tag[2]
+
+Tremove => H+FID, # size[4] Tremove tag[2] fid[4]
+Rremove => H, # size[4] Rremove tag[2]
+
+Tstat => H+FID, # size[4] Tstat tag[2] fid[4]
+Rstat => H+LEN, # size[4] Rstat tag[2] stat[n]
+
+Twstat => H+FID+LEN, # size[4] Twstat tag[2] fid[4] stat[n]
+Rwstat => H, # size[4] Rwstat tag[2]
+};
+
+init()
+{
+ sys = load Sys Sys->PATH;
+}
+
+utflen(s: string): int
+{
+ # the domain is 16-bit unicode only, which is all that Inferno now
implements
+ n := l := len s;
+ for(i:=0; i<l; i++)
+ if((c := s[i]) > 16r7F){
+ n++;
+ if(c > 16r7FF)
+ n++;
+ }
+ return n;
+}
+
+packdirsize(d: Sys->Dir): int
+{
+ return
STATFIXLEN+utflen(d.name)+utflen(d.uid)+utflen(d.gid)+utflen(d.muid);
+}
+
+packdir(f: Sys->Dir): array of byte
+{
+ ds := packdirsize(f);
+ a := array[ds] of byte;
+ # size[2]
+ a[0] = byte (ds-LEN);
+ a[1] = byte ((ds-LEN)>>8);
+ # type[2]
+ a[2] = byte f.dtype;
+ a[3] = byte (f.dtype>>8);
+ # dev[4]
+ a[4] = byte f.dev;
+ a[5] = byte (f.dev>>8);
+ a[6] = byte (f.dev>>16);
+ a[7] = byte (f.dev>>24);
+ # qid.type[1]
+ # qid.vers[4]
+ # qid.path[8]
+ pqid(a, 8, f.qid);
+ # mode[4]
+ a[21] = byte f.mode;
+ a[22] = byte (f.mode>>8);
+ a[23] = byte (f.mode>>16);
+ a[24] = byte (f.mode>>24);
+ # atime[4]
+ a[25] = byte f.atime;
+ a[26] = byte (f.atime>>8);
+ a[27] = byte (f.atime>>16);
+ a[28] = byte (f.atime>>24);
+ # mtime[4]
+ a[29] = byte f.mtime;
+ a[30] = byte (f.mtime>>8);
+ a[31] = byte (f.mtime>>16);
+ a[32] = byte (f.mtime>>24);
+ # length[8]
+ p64(a, 33, big f.length);
+ # name[s]
+ i := pstring(a, 33+BIT64SZ, f.name);
+ i = pstring(a, i, f.uid);
+ i = pstring(a, i, f.gid);
+ i = pstring(a, i, f.muid);
+ if(i != len a)
+ raise "assertion: Ninep->packdir: bad count"; # can't happen unless
packedsize is wrong
+ return a;
+}
+
+pqid(a: array of byte, o: int, q: Sys->Qid): int
+{
+ a[o] = byte q.qtype;
+ v := q.vers;
+ a[o+1] = byte v;
+ a[o+2] = byte (v>>8);
+ a[o+3] = byte (v>>16);
+ a[o+4] = byte (v>>24);
+ v = int q.path;
+ a[o+5] = byte v;
+ a[o+6] = byte (v>>8);
+ a[o+7] = byte (v>>16);
+ a[o+8] = byte (v>>24);
+ v = int (q.path >> 32);
+ a[o+9] = byte v;
+ a[o+10] = byte (v>>8);
+ a[o+11] = byte (v>>16);
+ a[o+12] = byte (v>>24);
+ return o+QID;
+}
+
+pstring(a: array of byte, o: int, s: string): int
+{
+ sa := array of byte s; # could do conversion ourselves
+ n := len sa;
+ a[o] = byte n;
+ a[o+1] = byte (n>>8);
+ a[o+2:] = sa;
+ return o+LEN+n;
+}
+
+p32(a: array of byte, o: int, v: int): int
+{
+ a[o] = byte v;
+ a[o+1] = byte (v>>8);
+ a[o+2] = byte (v>>16);
+ a[o+3] = byte (v>>24);
+ return o+BIT32SZ;
+}
+
+p64(a: array of byte, o: int, b: big): int
+{
+ i := int b;
+ a[o] = byte i;
+ a[o+1] = byte (i>>8);
+ a[o+2] = byte (i>>16);
+ a[o+3] = byte (i>>24);
+ i = int (b>>32);
+ a[o+4] = byte i;
+ a[o+5] = byte (i>>8);
+ a[o+6] = byte (i>>16);
+ a[o+7] = byte (i>>24);
+ return o+BIT64SZ;
+}
+
+unpackdir(a: array of byte): (int, Sys->Dir)
+{
+ dir: Sys->Dir;
+
+ if(len a < STATFIXLEN)
+ return (0, dir);
+ # size[2]
+ sz := ((int a[1] << 8) | int a[0])+LEN; # bytes this packed dir should
occupy
+ if(len a < sz)
+ return (0, dir);
+ # type[2]
+ dir.dtype = (int a[3]<<8) | int a[2];
+ # dev[4]
+ dir.dev = (((((int a[7] << 8) | int a[6]) << 8) | int a[5]) << 8) | int
a[4];
+ # qid.type[1]
+ # qid.vers[4]
+ # qid.path[8]
+ dir.qid = gqid(a, 8);
+ # mode[4]
+ dir.mode = (((((int a[24] << 8) | int a[23]) << 8) | int a[22]) << 8) |
int a[21];
+ # atime[4]
+ dir.atime = (((((int a[28] << 8) | int a[27]) << 8) | int a[26]) << 8) |
int a[25];
+ # mtime[4]
+ dir.mtime = (((((int a[32] << 8) | int a[31]) << 8) | int a[30]) << 8) |
int a[29];
+ # length[8]
+ v0 := (((((int a[36] << 8) | int a[35]) << 8) | int a[34]) << 8) | int
a[33];
+ v1 := (((((int a[40] << 8) | int a[39]) << 8) | int a[38]) << 8) | int
a[37];
+ dir.length = (big v1 << 32) | (big v0 & 16rFFFFFFFF);
+ # name[s], uid[s], gid[s], muid[s]
+ i: int;
+ (dir.name, i) = gstring(a, 41);
+ (dir.uid, i) = gstring(a, i);
+ (dir.gid, i) = gstring(a, i);
+ (dir.muid, i) = gstring(a, i);
+ if(i != sz)
+ return (0, dir);
+ return (i, dir);
+}
+
+gqid(f: array of byte, i: int): Sys->Qid
+{
+ qtype := int f[i];
+ vers := (((((int f[i+4] << 8) | int f[i+3]) << 8) | int f[i+2]) << 8) |
int f[i+1];
+ i += BIT8SZ+BIT32SZ;
+ path0 := (((((int f[i+3] << 8) | int f[i+2]) << 8) | int f[i+1]) << 8) |
int f[i];
+ i += BIT32SZ;
+ path1 := (((((int f[i+3] << 8) | int f[i+2]) << 8) | int f[i+1]) << 8) |
int f[i];
+ path := (big path1 << 32) | (big path0 & 16rFFFFFFFF);
+ return (path, vers, qtype);
+}
+
+g32(f: array of byte, i: int): int
+{
+ return (((((int f[i+3] << 8) | int f[i+2]) << 8) | int f[i+1]) << 8) |
int f[i];
+}
+
+g64(f: array of byte, i: int): big
+{
+ b0 := (((((int f[i+3] << 8) | int f[i+2]) << 8) | int f[i+1]) << 8) | int
f[i];
+ b1 := (((((int f[i+7] << 8) | int f[i+6]) << 8) | int f[i+5]) << 8) | int
f[i+4];
+ return (big b1 << 32) | (big b0 & 16rFFFFFFFF);
+}
+
+gstring(a: array of byte, o: int): (string, int)
+{
+ if(o < 0 || o+STR > len a)
+ return (nil, -1);
+ l := (int a[o+1] << 8) | int a[o];
+ o += STR;
+ e := o+l;
+ if(e > len a)
+ return (nil, -1);
+ return (string a[o:e], e);
+}
+
+ttag2type := array[] of {
+tagof Tmsg.Readerror => 0,
+tagof Tmsg.Version => Tversion,
+tagof Tmsg.Auth => Tauth,
+tagof Tmsg.Attach => Tattach,
+tagof Tmsg.Flush => Tflush,
+tagof Tmsg.Walk => Twalk,
+tagof Tmsg.Open => Topen,
+tagof Tmsg.Create => Tcreate,
+tagof Tmsg.Read => Tread,
+tagof Tmsg.Write => Twrite,
+tagof Tmsg.Clunk => Tclunk,
+tagof Tmsg.Stat => Tstat,
+tagof Tmsg.Remove => Tremove,
+tagof Tmsg.Wstat => Twstat,
+};
+
+Tmsg.mtype(t: self ref Tmsg): int
+{
+ return ttag2type[tagof t];
+}
+
+Tmsg.packedsize(t: self ref Tmsg): int
+{
+ mtype := ttag2type[tagof t];
+ if(mtype <= 0)
+ return 0;
+ ml := hdrlen[mtype];
+ pick m := t {
+ Version =>
+ ml += utflen(m.version);
+ Auth =>
+ ml += utflen(m.uname)+utflen(m.aname);
+ Attach =>
+ ml += utflen(m.uname)+utflen(m.aname);
+ Walk =>
+ for(i:=0; i<len m.names; i++)
+ ml += STR+utflen(m.names[i]);
+ Create =>
+ ml += utflen(m.name);
+ Write =>
+ ml += len m.data;
+ Wstat =>
+ ml += packdirsize(m.stat);
+ }
+ return ml;
+}
+
+Tmsg.pack(t: self ref Tmsg): array of byte
+{
+ if(t == nil)
+ return nil;
+ ds := t.packedsize();
+ if(ds <= 0)
+ return nil;
+ d := array[ds] of byte;
+ d[0] = byte ds;
+ d[1] = byte (ds>>8);
+ d[2] = byte (ds>>16);
+ d[3] = byte (ds>>24);
+ d[4] = byte ttag2type[tagof t];
+ d[5] = byte t.tag;
+ d[6] = byte (t.tag >> 8);
+ pick m := t {
+ Version =>
+ p32(d, H, m.msize);
+ pstring(d, H+COUNT, m.version);
+ Auth =>
+ p32(d, H, m.afid);
+ o := pstring(d, H+FID, m.uname);
+ pstring(d, o, m.aname);
+ Flush =>
+ v := m.oldtag;
+ d[H] = byte v;
+ d[H+1] = byte (v>>8);
+ Attach =>
+ p32(d, H, m.fid);
+ p32(d, H+FID, m.afid);
+ o := pstring(d, H+2*FID, m.uname);
+ pstring(d, o, m.aname);
+ Walk =>
+ d[H] = byte m.fid;
+ d[H+1] = byte (m.fid>>8);
+ d[H+2] = byte (m.fid>>16);
+ d[H+3] = byte (m.fid>>24);
+ d[H+FID] = byte m.newfid;
+ d[H+FID+1] = byte (m.newfid>>8);
+ d[H+FID+2] = byte (m.newfid>>16);
+ d[H+FID+3] = byte (m.newfid>>24);
+ n := len m.names;
+ d[H+2*FID] = byte n;
+ d[H+2*FID+1] = byte (n>>8);
+ o := H+2*FID+LEN;
+ for(i := 0; i < n; i++)
+ o = pstring(d, o, m.names[i]);
+ Open =>
+ p32(d, H, m.fid);
+ d[H+FID] = byte m.mode;
+ Create =>
+ p32(d, H, m.fid);
+ o := pstring(d, H+FID, m.name);
+ p32(d, o, m.perm);
+ d[o+BIT32SZ] = byte m.mode;
+ Read =>
+ p32(d, H, m.fid);
+ p64(d, H+FID, m.offset);
+ p32(d, H+FID+OFFSET, m.count);
+ Write =>
+ p32(d, H, m.fid);
+ p64(d, H+FID, m.offset);
+ n := len m.data;
+ p32(d, H+FID+OFFSET, n);
+ d[H+FID+OFFSET+COUNT:] = m.data;
+ Clunk or Remove or Stat =>
+ p32(d, H, m.fid);
+ Wstat =>
+ p32(d, H, m.fid);
+ stat := packdir(m.stat);
+ n := len stat;
+ d[H+FID] = byte n;
+ d[H+FID+1] = byte (n>>8);
+ d[H+FID+LEN:] = stat;
+ * =>
+ raise sys->sprint("assertion: Ninep->Tmsg.pack: bad tag: %d", tagof t);
+ }
+ return d;
+}
+
+Tmsg.unpack(f: array of byte): (int, ref Tmsg)
+{
+ if(len f < H)
+ return (0, nil);
+ size := (int f[1] << 8) | int f[0];
+ size |= ((int f[3] << 8) | int f[2]) << 16;
+ if(len f != size){
+ if(len f < size)
+ return (0, nil); # need more data
+ f = f[0:size]; # trim to exact length
+ }
+ mtype := int f[4];
+ if(mtype >= len hdrlen || (mtype&1) != 0 || size < hdrlen[mtype])
+ return (-1, nil);
+
+ tag := (int f[6] << 8) | int f[5];
+ fid := 0;
+ if(hdrlen[mtype] >= H+FID)
+ fid = g32(f, H); # fid is always in same place: extract it once for all
if there
+
+ # return out of each case body for a legal message;
+ # break out of the case for an illegal one
+
+Decode:
+ case mtype {
+ * =>
+ sys->print("styx: Tmsg.unpack: bad type %d\n", mtype);
+ Tversion =>
+ msize := fid;
+ (version, o) := gstring(f, H+COUNT);
+ if(o <= 0)
+ break;
+ return (o, ref Tmsg.Version(tag, msize, version));
+ Tauth =>
+ (uname, o1) := gstring(f, H+FID);
+ (aname, o2) := gstring(f, o1);
+ if(o2 <= 0)
+ break;
+ return (o2, ref Tmsg.Auth(tag, fid, uname, aname));
+ Tflush =>
+ oldtag := (int f[H+1] << 8) | int f[H];
+ return (H+TAG, ref Tmsg.Flush(tag, oldtag));
+ Tattach =>
+ afid := g32(f, H+FID);
+ (uname, o1) := gstring(f, H+2*FID);
+ (aname, o2) := gstring(f, o1);
+ if(o2 <= 0)
+ break;
+ return (o2, ref Tmsg.Attach(tag, fid, afid, uname, aname));
+ Twalk =>
+ newfid := g32(f, H+FID);
+ n := (int f[H+2*FID+1] << 8) | int f[H+2*FID];
+ if(n > MAXWELEM)
+ break;
+ o := H+2*FID+LEN;
+ names: array of string = nil;
+ if(n > 0){
+ names = array[n] of string;
+ for(i:=0; i<n; i++){
+ (names[i], o) = gstring(f, o);
+ if(o <= 0)
+ break Decode;
+ }
+ }
+ return (o, ref Tmsg.Walk(tag, fid, newfid, names));
+ Topen =>
+ return (H+FID+BIT8SZ, ref Tmsg.Open(tag, fid, int f[H+FID]));
+ Tcreate =>
+ (name, o) := gstring(f, H+FID);
+ if(o <= 0 || o+BIT32SZ+BIT8SZ > len f)
+ break;
+ perm := g32(f, o);
+ o += BIT32SZ;
+ mode := int f[o++];
+ return (o, ref Tmsg.Create(tag, fid, name, perm, mode));
+ Tread =>
+ offset := g64(f, H+FID);
+ count := g32(f, H+FID+OFFSET);
+ return (H+FID+OFFSET+COUNT, ref Tmsg.Read(tag, fid, offset, count));
+ Twrite =>
+ offset := g64(f, H+FID);
+ count := g32(f, H+FID+OFFSET);
+ O: con H+FID+OFFSET+COUNT;
+ if(count > len f-O)
+ break;
+ data := f[O:O+count];
+ return (O+count, ref Tmsg.Write(tag, fid, offset, data));
+ Tclunk =>
+ return (H+FID, ref Tmsg.Clunk(tag, fid));
+ Tremove =>
+ return (H+FID, ref Tmsg.Remove(tag, fid));
+ Tstat =>
+ return (H+FID, ref Tmsg.Stat(tag, fid));
+ Twstat =>
+ n := int (f[H+FID+1]<<8) | int f[H+FID];
+ if(len f < H+FID+LEN+n)
+ break;
+ (ds, stat) := unpackdir(f[H+FID+LEN:]);
+ if(ds != n){
+ sys->print("Ninep->Tmsg.unpack: wstat count: %d/%d\n", ds, n); #
temporary
+ break;
+ }
+ return (H+FID+LEN+n, ref Tmsg.Wstat(tag, fid, stat));
+ }
+ return (-1, nil); # illegal
+}
+
+tmsgname := array[] of {
+tagof Tmsg.Readerror => "Readerror",
+tagof Tmsg.Version => "Version",
+tagof Tmsg.Auth => "Auth",
+tagof Tmsg.Attach => "Attach",
+tagof Tmsg.Flush => "Flush",
+tagof Tmsg.Walk => "Walk",
+tagof Tmsg.Open => "Open",
+tagof Tmsg.Create => "Create",
+tagof Tmsg.Read => "Read",
+tagof Tmsg.Write => "Write",
+tagof Tmsg.Clunk => "Clunk",
+tagof Tmsg.Stat => "Stat",
+tagof Tmsg.Remove => "Remove",
+tagof Tmsg.Wstat => "Wstat",
+};
+
+Tmsg.text(t: self ref Tmsg): string
+{
+ if(t == nil)
+ return "nil";
+ s := sys->sprint("Tmsg.%s(%ud", tmsgname[tagof t], t.tag);
+ pick m:= t {
+ * =>
+ return s + ",ILLEGAL)";
+ Readerror =>
+ return s + sys->sprint(",\"%s\")", m.error);
+ Version =>
+ return s + sys->sprint(",%d,\"%s\")", m.msize, m.version);
+ Auth =>
+ return s + sys->sprint(",%ud,\"%s\",\"%s\")", m.afid, m.uname, m.aname);
+ Flush =>
+ return s + sys->sprint(",%ud)", m.oldtag);
+ Attach =>
+ return s + sys->sprint(",%ud,%ud,\"%s\",\"%s\")", m.fid, m.afid,
m.uname, m.aname);
+ Walk =>
+ s += sys->sprint(",%ud,%ud", m.fid, m.newfid);
+ if(len m.names != 0){
+ s += ",array[] of {";
+ for(i := 0; i < len m.names; i++){
+ c := ",";
+ if(i == 0)
+ c = "";
+ s += sys->sprint("%s\"%s\"", c, m.names[i]);
+ }
+ s += "}";
+ }else
+ s += ",nil";
+ return s + ")";
+ Open =>
+ return s + sys->sprint(",%ud,%d)", m.fid, m.mode);
+ Create =>
+ return s + sys->sprint(",%ud,\"%s\",8r%uo,%d)", m.fid, m.name, m.perm,
m.mode);
+ Read =>
+ return s + sys->sprint(",%ud,%bd,%ud)", m.fid, m.offset, m.count);
+ Write =>
+ return s + sys->sprint(",%ud,%bd,array[%d] of byte)", m.fid, m.offset,
len m.data);
+ Clunk or
+ Remove or
+ Stat =>
+ return s + sys->sprint(",%ud)", m.fid);
+ Wstat =>
+ return s + sys->sprint(",%ud,%s)", m.fid, dir2text(m.stat));
+ }
+}
+
+Tmsg.read(fd: ref Sys->FD, msglim: int): ref Tmsg
+{
+ (msg, err) := readmsg(fd, msglim);
+ if(err != nil)
+ return ref Tmsg.Readerror(0, err);
+ if(msg == nil)
+ return nil;
+ (nil, m) := Tmsg.unpack(msg);
+ if(m == nil)
+ return ref Tmsg.Readerror(0, "bad 9P T-message format");
+ return m;
+}
+
+rtag2type := array[] of {
+tagof Rmsg.Version => Rversion,
+tagof Rmsg.Auth => Rauth,
+tagof Rmsg.Error => Rerror,
+tagof Rmsg.Flush => Rflush,
+tagof Rmsg.Attach => Rattach,
+tagof Rmsg.Walk => Rwalk,
+tagof Rmsg.Open => Ropen,
+tagof Rmsg.Create => Rcreate,
+tagof Rmsg.Read => Rread,
+tagof Rmsg.Write => Rwrite,
+tagof Rmsg.Clunk => Rclunk,
+tagof Rmsg.Remove => Rremove,
+tagof Rmsg.Stat => Rstat,
+tagof Rmsg.Wstat => Rwstat,
+};
+
+Rmsg.mtype(r: self ref Rmsg): int
+{
+ return rtag2type[tagof r];
+}
+
+Rmsg.packedsize(r: self ref Rmsg): int
+{
+ mtype := rtag2type[tagof r];
+ if(mtype <= 0)
+ return 0;
+ ml := hdrlen[mtype];
+ pick m := r {
+ Version =>
+ ml += utflen(m.version);
+ Error =>
+ ml += utflen(m.ename);
+ Walk =>
+ ml += QID*len m.qids;
+ Read =>
+ ml += len m.data;
+ Stat =>
+ ml += packdirsize(m.stat);
+ }
+ return ml;
+}
+
+Rmsg.pack(r: self ref Rmsg): array of byte
+{
+ if(r == nil)
+ return nil;
+ ps := r.packedsize();
+ if(ps <= 0)
+ return nil;
+ d := array[ps] of byte;
+ d[0] = byte ps;
+ d[1] = byte (ps>>8);
+ d[2] = byte (ps>>16);
+ d[3] = byte (ps>>24);
+ d[4] = byte rtag2type[tagof r];
+ d[5] = byte r.tag;
+ d[6] = byte (r.tag >> 8);
+ pick m := r {
+ Version =>
+ p32(d, H, m.msize);
+ pstring(d, H+BIT32SZ, m.version);
+ Auth =>
+ pqid(d, H, m.aqid);
+ Flush or
+ Clunk or
+ Remove or
+ Wstat =>
+ ; # nothing more required
+ Error =>
+ pstring(d, H, m.ename);
+ Attach =>
+ pqid(d, H, m.qid);
+ Walk =>
+ n := len m.qids;
+ d[H] = byte n;
+ d[H+1] = byte (n>>8);
+ o := H+LEN;
+ for(i:=0; i<n; i++){
+ pqid(d, o, m.qids[i]);
+ o += QID;
+ }
+ Create or
+ Open =>
+ pqid(d, H, m.qid);
+ p32(d, H+QID, m.iounit);
+ Read =>
+ v := len m.data;
+ d[H] = byte v;
+ d[H+1] = byte (v>>8);
+ d[H+2] = byte (v>>16);
+ d[H+3] = byte (v>>24);
+ d[H+4:] = m.data;
+ Write =>
+ v := m.count;
+ d[H] = byte v;
+ d[H+1] = byte (v>>8);
+ d[H+2] = byte (v>>16);
+ d[H+3] = byte (v>>24);
+ Stat =>
+ stat := packdir(m.stat);
+ v := len stat;
+ d[H] = byte v;
+ d[H+1] = byte (v>>8);
+ d[H+2:] = stat; # should avoid copy?
+ * =>
+ raise sys->sprint("assertion: Ninep->Rmsg.pack: missed case: tag %d",
tagof r);
+ }
+ return d;
+}
+
+Rmsg.unpack(f: array of byte): (int, ref Rmsg)
+{
+ if(len f < H)
+ return (0, nil);
+ size := (int f[1] << 8) | int f[0];
+ size |= ((int f[3] << 8) | int f[2]) << 16; # size includes itself
+ if(len f != size){
+ if(len f < size)
+ return (0, nil); # need more data
+ f = f[0:size]; # trim to exact length
+ }
+ mtype := int f[4];
+ if(mtype >= len hdrlen || (mtype&1) == 0 || size < hdrlen[mtype])
+ return (-1, nil);
+
+ tag := (int f[6] << 8) | int f[5];
+
+ # return out of each case body for a legal message;
+ # break out of the case for an illegal one
+
+ case mtype {
+ * =>
+ sys->print("Ninep->Rmsg.unpack: bad type %d\n", mtype); # temporary
+ Rversion =>
+ msize := g32(f, H);
+ (version, o) := gstring(f, H+BIT32SZ);
+ if(o <= 0)
+ break;
+ return (o, ref Rmsg.Version(tag, msize, version));
+ Rauth =>
+ return (H+QID, ref Rmsg.Auth(tag, gqid(f, H)));
+ Rflush =>
+ return (H, ref Rmsg.Flush(tag));
+ Rerror =>
+ (ename, o) := gstring(f, H);
+ if(o <= 0)
+ break;
+ return (o, ref Rmsg.Error(tag, ename));
+ Rclunk =>
+ return (H, ref Rmsg.Clunk(tag));
+ Rremove =>
+ return (H, ref Rmsg.Remove(tag));
+ Rwstat=>
+ return (H, ref Rmsg.Wstat(tag));
+ Rattach =>
+ return (H+QID, ref Rmsg.Attach(tag, gqid(f, H)));
+ Rwalk =>
+ nqid := (int f[H+1] << 8) | int f[H];
+ if(len f < H+LEN+nqid*QID)
+ break;
+ o := H+LEN;
+ qids := array[nqid] of Sys->Qid;
+ for(i:=0; i<nqid; i++){
+ qids[i] = gqid(f, o);
+ o += QID;
+ }
+ return (o, ref Rmsg.Walk(tag, qids));
+ Ropen =>
+ return (H+QID+COUNT, ref Rmsg.Open(tag, gqid(f, H), g32(f, H+QID)));
+ Rcreate=>
+ return (H+QID+COUNT, ref Rmsg.Create(tag, gqid(f, H), g32(f, H+QID)));
+ Rread =>
+ count := g32(f, H);
+ if(len f < H+COUNT+count)
+ break;
+ data := f[H+COUNT:H+COUNT+count];
+ return (H+COUNT+count, ref Rmsg.Read(tag, data));
+ Rwrite =>
+ return (H+COUNT, ref Rmsg.Write(tag, g32(f, H)));
+ Rstat =>
+ n := (int f[H+1] << 8) | int f[H];
+ if(len f < H+LEN+n)
+ break;
+ (ds, d) := unpackdir(f[H+LEN:]);
+ if(ds <= 0)
+ break;
+ if(ds != n){
+ sys->print("Ninep->Rmsg.unpack: stat count: %d/%d\n", ds, n); #
temporary
+ break;
+ }
+ return (H+LEN+n, ref Rmsg.Stat(tag, d));
+ }
+ return (-1, nil); # illegal
+}
+
+rmsgname := array[] of {
+tagof Rmsg.Version => "Version",
+tagof Rmsg.Auth => "Auth",
+tagof Rmsg.Attach => "Attach",
+tagof Rmsg.Error => "Error",
+tagof Rmsg.Flush => "Flush",
+tagof Rmsg.Walk => "Walk",
+tagof Rmsg.Create => "Create",
+tagof Rmsg.Open => "Open",
+tagof Rmsg.Read => "Read",
+tagof Rmsg.Write => "Write",
+tagof Rmsg.Clunk => "Clunk",
+tagof Rmsg.Remove => "Remove",
+tagof Rmsg.Stat => "Stat",
+tagof Rmsg.Wstat => "Wstat",
+};
+
+Rmsg.text(r: self ref Rmsg): string
+{
+ if(sys == nil)
+ sys = load Sys Sys->PATH;
+ if(r == nil)
+ return "nil";
+ s := sys->sprint("Rmsg.%s(%ud", rmsgname[tagof r], r.tag);
+ pick m := r {
+ * =>
+ return s + "ERROR)";
+ Readerror =>
+ return s + sys->sprint(",\"%s\")", m.error);
+ Version =>
+ return s + sys->sprint(",%d,\"%s\")", m.msize, m.version);
+ Auth =>
+ return s+sys->sprint(",%s)", qid2text(m.aqid));
+ Error =>
+ return s+sys->sprint(",\"%s\")", m.ename);
+ Flush or
+ Clunk or
+ Remove or
+ Wstat =>
+ return s+")";
+ Attach =>
+ return s+sys->sprint(",%s)", qid2text(m.qid));
+ Walk =>
+ s += ",array[] of {";
+ for(i := 0; i < len m.qids; i++){
+ c := "";
+ if(i != 0)
+ c = ",";
+ s += sys->sprint("%s%s", c, qid2text(m.qids[i]));
+ }
+ return s+"})";
+ Create or
+ Open =>
+ return s+sys->sprint(",%s,%d)", qid2text(m.qid), m.iounit);
+ Read =>
+ return s+sys->sprint(",array[%d] of byte)", len m.data);
+ Write =>
+ return s+sys->sprint(",%d)", m.count);
+ Stat =>
+ return s+sys->sprint(",%s)", dir2text(m.stat));
+ }
+}
+
+Rmsg.read(fd: ref Sys->FD, msglim: int): ref Rmsg
+{
+ (msg, err) := readmsg(fd, msglim);
+ if(err != nil)
+ return ref Rmsg.Readerror(0, err);
+ if(msg == nil)
+ return nil;
+ (nil, m) := Rmsg.unpack(msg);
+ if(m == nil)
+ return ref Rmsg.Readerror(0, "bad 9P R-message format");
+ return m;
+}
+
+dir2text(d: Sys->Dir): string
+{
+ return
sys->sprint("Dir(\"%s\",\"%s\",\"%s\",%s,8r%uo,%d,%d,%bd,16r%ux,%d)",
+ d.name, d.uid, d.gid, qid2text(d.qid), d.mode, d.atime, d.mtime,
d.length, d.dtype, d.dev);
+}
+
+qid2text(q: Sys->Qid): string
+{
+ return sys->sprint("Qid(16r%ubx,%d,16r%.2ux)", q.path, q.vers, q.qtype);
+}
+
+readmsg(fd: ref Sys->FD, msglim: int): (array of byte, string)
+{
+ if(msglim <= 0)
+ msglim = DEFMSIZE;
+ sbuf := array[BIT32SZ] of byte;
+ if((n := sys->readn(fd, sbuf, BIT32SZ)) != BIT32SZ){
+ if(n == 0)
+ return (nil, nil);
+ return (nil, sys->sprint("%r"));
+ }
+ ml := (int sbuf[1] << 8) | int sbuf[0];
+ ml |= ((int sbuf[3] << 8) | int sbuf[2]) << 16;
+ if(ml <= BIT32SZ)
+ return (nil, "invalid 9P message size");
+ if(ml > msglim)
+ return (nil, "9P message longer than agreed");
+ buf := array[ml] of byte;
+ buf[0:] = sbuf;
+ if((n = sys->readn(fd, buf[BIT32SZ:], ml-BIT32SZ)) != ml-BIT32SZ){
+ if(n == 0)
+ return (nil, "9P message truncated");
+ return (nil, sys->sprint("%r"));
+ }
+ return (buf, nil);
+}
+
+istmsg(f: array of byte): int
+{
+ if(len f < H)
+ return -1;
+ return (int f[BIT32SZ] & 1) == 0;
+}
+
+compatible(t: ref Tmsg.Version, msize: int, version: string): (int, string)
+{
+ if(version == nil)
+ version = VERSION;
+ if(t.msize < msize)
+ msize = t.msize;
+ v := t.version;
+ if(len v < 2 || v[0:2] != "9P")
+ return (msize, "unknown");
+ for(i:=2; i<len v; i++)
+ if((c := v[i]) == '.'){
+ v = v[0:i];
+ break;
+ }else if(!(c >= '0' && c <= '9'))
+ return (msize, "unknown"); # fussier than Plan 9
+ if(v < VERSION)
+ return (msize, "unknown");
+ if(v < version)
+ version = v;
+ return (msize, version);
+}
=======================================
--- /dev/null
+++ /dis/lib/ninep.dis Sun Feb 21 04:11:43 2010
Binary file, no diff available.
=======================================
--- /dev/null
+++ /man/2/9p-ninep Sun Feb 21 04:11:43 2010
@@ -0,0 +1,416 @@
+.TH 9P-NINEP 2
+.SH NAME
+Ninep: Rmsg, Tmsg, dir2text, istmsg, packdir, packdirsize, readmsg,
qid2text, unpackdir \- interface to 9P file protocol
+.SH SYNOPSIS
+.EX
+include "9p.m";
+ninep := load Ninep Ninep->PATH;
+
+Tmsg: adt {
+ tag: int;
+ pick {
+ Readerror =>
+ error: string; # tag is unused in this case
+ Version =>
+ msize: int;
+ version: string;
+ Auth =>
+ afid: int;
+ uname, aname: string;
+ Attach =>
+ fid, afid: int;
+ uname, aname: string;
+ Flush =>
+ oldtag: int;
+ Walk =>
+ fid, newfid: int;
+ names: array of string;
+ Open =>
+ fid, mode: int;
+ Create =>
+ fid: int;
+ name: string;
+ perm, mode: int;
+ Read =>
+ fid: int;
+ offset: big;
+ count: int;
+ Write =>
+ fid: int;
+ offset: big;
+ data: array of byte;
+ Clunk or
+ Stat or
+ Remove =>
+ fid: int;
+ Wstat =>
+ fid: int;
+ stat: Sys->Dir;
+ }
+
+ read: fn(fd: ref Sys->FD, msize: int): ref Tmsg;
+ unpack: fn(a: array of byte): (int, ref Tmsg);
+ pack: fn(nil: self ref Tmsg): array of byte;
+ packedsize: fn(nil: self ref Tmsg): int;
+ text: fn(nil: self ref Tmsg): string;
+ mtype: fn(nil: self ref Tmsg): int;
+};
+
+Rmsg: adt {
+ tag: int;
+ pick {
+ Readerror =>
+ error: string; # tag is unused in this case
+ Version =>
+ msize: int;
+ version: string;
+ Auth =>
+ aqid: Sys->Qid;
+ Attach =>
+ qid: Sys->Qid;
+ Flush =>
+ Error =>
+ ename: string;
+ Clunk or
+ Remove or
+ Wstat =>
+ Walk =>
+ qids: array of Sys->Qid;
+ Create or
+ Open =>
+ qid: Sys->Qid;
+ iounit: int;
+ Read =>
+ data: array of byte;
+ Write =>
+ count: int;
+ Stat =>
+ stat: Sys->Dir;
+ }
+
+ read: fn(fd: ref Sys->FD, msize: int): ref Rmsg;
+ unpack: fn(a: array of byte): (int, ref Rmsg);
+ pack: fn(nil: self ref Rmsg): array of byte;
+ packedsize: fn(nil: self ref Rmsg): int;
+ text: fn(nil: self ref Rmsg): string;
+ mtype: fn(nil: self ref Rmsg): int;
+};
+
+init: fn();
+
+readmsg: fn(fd: ref Sys->FD, msize: int): (array of byte, string);
+istmsg: fn(f: array of byte): int;
+
+compatible: fn(t: ref Tmsg.Version, msize: int, version: string): (int,
string);
+
+packdirsize: fn(d: Sys->Dir): int;
+packdir: fn(d: Sys->Dir): array of byte;
+unpackdir: fn(f: array of byte): (int, Sys->Dir);
+dir2text: fn(d: Sys->Dir): string;
+qid2text: fn(q: Sys->Qid): string;
+
+VERSION: con "9P2000";
+MAXWELEM: con 16;
+NOTAG: con 16rFFFF;
+NOFID: con ~0;
+IOHDRSZ: con \fIimplementation-defined\f5;
+DEFMSIZE: con \fIimplementation-defined\f5;
+.EE
+.SH DESCRIPTION
+.B Ninep
+provides a Limbo interface to send and receive messages of the 9P file
service protocol,
+described by Section 5 of this manual, a thorough reading of which
+is advised before using this module.
+.B Init
+must be called before using any other function in the module.
+.PP
+A 9P client transmits requests to a server as `T-messages'
+and receives replies in matching `R-messages'.
+A T-message is here represented by values of the type
+.BR Tmsg ,
+and an R-message by values of type
+.BR Rmsg .
+Every message has a
+.B tag
+value, and the alternatives of the pick adt represent the possible
operation types of a T-message,
+generally with parameter names and types corresponding to those described
in section 5.
+The exceptions are:
+.B Tmsg.Write
+and
+.B Rmsg.Read
+contain an array of byte,
+.BR data ,
+to hold the data for the corresponding message, and the `count' parameter
of the message is simply the length of that array;
+and there is an alternative labelled
+.B Readerror
+that does not appear in the protocol but is used to represent input errors
as described below.
+Also note that values that are `unsigned' integers in the protocol are
typically given signed integer
+types in the Limbo representation (in particular, fids, qid paths, counts
and offsets), and applications
+should take appropriate care when manipulating them.
+.PP
+The following functions are provided by
+.BR Tmsg:
+.TP
+.BI read( fd\fP,\fP\ msize )
+Read file descriptor
+.I fd
+to obtain exactly one T-message and return (a reference to) the
corresponding
+.BR Tmsg .
+A nil value is returned on end of file.
+Otherwise, if the read fails or the data read does not form a valid
T-message,
+the value returned will be a
+.B Tmsg.Readerror
+value in which the
+.B error
+member describes the error.
+.I Msize
+gives the maximum number of bytes in any acceptable T-message,
+and should be the value negotiated in the exchange of
+.B version
+messages;
+any incoming message larger than that will result in a diagnostic as a
+.B Tmsg.Readerror
+value.
+An
+.I msize
+of 0 means `no limit negotiated' and should (only) be used until a message
size
+has been negotiated by exchange of
+.IR version (5)
+messages.
+.TP
+.IB t .pack()
+Return an array of bytes containing the value of
+.I t
+in the machine-independent format described in Section 5.
+It can return nil only if the message
+.I t
+is itself nil or has an invalid type.
+.TP
+.BI unpack( a )
+The array
+.I a
+is assumed to contain zero or more T-messages.
+.B Unpack
+attempts to unpack the first message, and returns a tuple of the form
+.RI ( n , v ).
+If successful,
+.I n
+is the number of bytes at the start of
+.I a
+used by the message, and
+.I v
+is the corresponding
+.B Tmsg
+value.
+If
+.I a
+contains the prefix of a valid message but more data is required to
complete it,
+.I n
+is zero (and
+.I v
+is nil); the caller will typically read more data, append it to
+.IR a ,
+and try again.
+If the message is invalid,
+.I n
+is -1
+and
+.I v
+is nil.
+.TP
+.IB t .packedsize()
+Return the number of bytes required for the value of
+.I t
+when packed in its machine-independent format.
+(Zero is returned if
+.I t
+is invalid.)
+.TP
+.IB t .text()
+Return a printable string showing the contents of
+.IR t ,
+for tracing or debugging.
+.TP
+.IB t .mtype()
+Return the 9P message type of the message.
+.PP
+An R-message is represented by
+.BR Rmsg .
+Its member functions behave exactly as those for
+.BR Tmsg ,
+except that they operate on R-messages not T-messages.
+.PP
+When a client reads a directory, the data returned in the reply must be
formatted
+as described in
+.IR read (5):
+an array of directory entries, one per file, with each entry formatted in
+a machine-independent format.
+An appropriate array value can be produced by
+.B packdir
+from a
+.B Sys->Dir
+structure, as used by
+.IR sys-stat (2).
+The space that packed representation will take can be calculated
beforehand by
+.BR packdirsize .
+The server will usually fill the buffer for the reply to the read
+with as many entries as will fit,
+checking the space remaining against the result of
+.B packdirsize
+and if the value will fit, storing the result of
+.BR packdir .
+Given an array
+.I a
+containing at most one packed directory value (as produced by
+.BR packdir ),
+.B unpackdir
+returns a tuple
+.RI ( n,\ d )
+where
+.I n
+is \-1 if
+.I a
+is illegally formatted;
+.I n
+is zero if
+.I a
+does not contain a complete directory entry value;
+and otherwise
+.I n
+is the number of bytes of
+.I a
+used to produce the unpacked
+.B Dir
+value
+.I d .
+.PP
+The functions
+.B dir2text
+and
+.B qid2text
+produce printable strings showing the contents of the corresponding data
structures,
+for use when tracing or debugging.
+.PP
+Applications that acts as file servers will read T-messages and
+reply with R-messages.
+They can use
+.B Tmsg.read
+to read each T-message, build an
+.B Rmsg
+reply value
+.IR r ,
+and use
+.IB r .pack
+to produce an array of bytes to be written in reply by
+.B Sys->write
+(see
+.IR sys-read (2)).
+.PP
+A few specialised programs might need the lower-level function
+.B readmsg
+that underlies
+.B Tmsg.read
+and
+.BR Rmsg.read .
+It reads a single message, which can be either a T-message or R-message,
+and returns it as an array of bytes,
+which can then be unpacked using
+.B Tmsg.unpack
+or
+.BR Rmsg.unpack .
+.I Msize
+is the negotiated message size, or 0 meaning `no limit'.
+The predicate
+.B istmsg
+returns true if the contents of array
+.I f
+looks like a packed representation of a T-message,
+judging only by its
+.I type
+byte.
+.PP
+When generating the
+.B version
+message (see
+.IR version (5)),
+the constant
+.B NOTAG
+can be used in
+.B Tmsg.tag
+and
+.B Rmsg.tag
+to represent `no tag value'.
+The constant
+.B VERSION
+names the current version of the protocol, and can be
+used as the value of
+.BR Tmsg.version .
+.PP
+.B Compatible
+can be used by a server to
+compare its
+.I msize
+and
+.I version
+(which is typically
+.BR VERSION )
+to those in the
+.B Tmsg.Version
+message received from a client, to decide its reply,
+following the rules in
+.IR version (5).
+It returns a tuple
+.RI ( m ", " v )
+with values for use in the
+.B Rmsg.Version
+reply.
+.I M
+is the lesser of
+.I msize
+and
+.IB t .msize ,
+and
+.I v
+is the negotiated protocol version, or the value \f5"unknown"\f1
+if no version could be agreed.
+The constant
+.B DEFMSIZE
+is a reasonable value for
+.I msize
+on current systems.
+The resulting value
+.I m
+can subsequently be given to the various read functions as the limit
+.IR msize .
+The constant
+.B IOHDRSZ
+gives the amount to allow for protocol overhead, when limiting data size
for
+.B Tmsg.Write
+and
+.BR Rmsg.Read .
+.PP
+The constant
+.B NOFID
+can be used as the value of
+.B afid
+of the
+.B attach
+message when authentication is not required (see
+.IR attach (5)).
+.PP
+The constant
+.B MAXWELEM
+gives the protocol-defined limit on the length of the arrays
+.B Tmsg.names
+and
+.BR Rmsg.qids .
+For specialised applications, the module defines constants
+.BR Tversion ,
+.BR Rversion ,
+etc. for the message types of the protocol, and the
+other constants mentioned in Section 5.
+.SH SOURCE
+.B /appl/lib/ninep.b
+.SH SEE ALSO
+.IR styxservers (2),
+.IR intro (5)
=======================================
--- /dev/null
+++ /module/9p.m Sun Feb 21 04:11:43 2010
@@ -0,0 +1,178 @@
+Ninep: module
+{
+ PATH: con "/dis/lib/ninep.dis";
+
+ VERSION: con "9P2000";
+ MAXWELEM: con 16;
+
+ NOTAG: con 16rFFFF;
+ NOFID: con int ~0; # 32 bits in this version of 9P
+
+ BIT8SZ: con 1;
+ BIT16SZ: con 2;
+ BIT32SZ: con 4;
+ BIT64SZ: con 8;
+ QIDSZ: con BIT8SZ+BIT32SZ+BIT64SZ;
+
+ STATFIXLEN: con BIT16SZ+QIDSZ+5*BIT16SZ+4*BIT32SZ+BIT64SZ; # amount of
fixed length data in a stat buffer
+ IOHDRSZ: con 24; # room for Twrite/Rread header
+ DEFIOUNIT: con 8192; # `reasonable' iounit
+ DEFMSIZE: con IOHDRSZ+DEFIOUNIT; # usable default for fversion and iounit
+
+ Tversion, # 100
+ Rversion,
+ Tauth, # 102
+ Rauth,
+ Tattach, # 104
+ Rattach,
+ Terror, # 106, illegal
+ Rerror,
+ Tflush, #108
+ Rflush,
+ Twalk, # 110
+ Rwalk,
+ Topen, # 112
+ Ropen,
+ Tcreate, # 114
+ Rcreate,
+ Tread, # 116
+ Rread,
+ Twrite, # 118
+ Rwrite,
+ Tclunk, # 120
+ Rclunk,
+ Tremove, # 122
+ Rremove,
+ Tstat, # 124
+ Rstat,
+ Twstat, #126
+ Rwstat,
+ Tmax: con 100+iota;
+
+ ERRMAX: con 128;
+
+ OREAD: con 0; # open for read
+ OWRITE: con 1; # write
+ ORDWR: con 2; # read and write
+ OEXEC: con 3; # execute, == read but check execute permission
+ OTRUNC: con 16; # or'ed in (except for exec), truncate file first
+ ORCLOSE: con 64; # or'ed in, remove on close
+
+ # mode bits in Dir.mode used by the protocol
+ DMDIR: con int 1<<31; # mode bit for directory
+ DMAPPEND: con int 1<<30; # mode bit for append-only files
+ DMEXCL: con int 1<<29; # mode bit for exclusive use files
+ DMAUTH: con int 1<<27; # mode bit for authentication files
+
+ # Qid.qtype
+ QTDIR: con 16r80;
+ QTAPPEND: con 16r40;
+ QTEXCL: con 16r20;
+ QTAUTH: con 16r08;
+ QTFILE: con 16r00;
+
+ Tmsg: adt {
+ tag: int;
+ pick {
+ Readerror =>
+ error: string; # tag is unused in this case
+ Version =>
+ msize: int;
+ version: string;
+ Auth =>
+ afid: int;
+ uname, aname: string;
+ Attach =>
+ fid, afid: int;
+ uname, aname: string;
+ Flush =>
+ oldtag: int;
+ Walk =>
+ fid, newfid: int;
+ names: array of string;
+ Open =>
+ fid, mode: int;
+ Create =>
+ fid: int;
+ name: string;
+ perm, mode: int;
+ Read =>
+ fid: int;
+ offset: big;
+ count: int;
+ Write =>
+ fid: int;
+ offset: big;
+ data: array of byte;
+ Clunk or
+ Stat or
+ Remove =>
+ fid: int;
+ Wstat =>
+ fid: int;
+ stat: Sys->Dir;
+ }
+
+ read: fn(fd: ref Sys->FD, msize: int): ref Tmsg;
+ unpack: fn(a: array of byte): (int, ref Tmsg);
+ pack: fn(nil: self ref Tmsg): array of byte;
+ packedsize: fn(nil: self ref Tmsg): int;
+ text: fn(nil: self ref Tmsg): string;
+ mtype: fn(nil: self ref Tmsg): int;
+ };
+
+ Rmsg: adt {
+ tag: int;
+ pick {
+ Readerror =>
+ error: string; # tag is unused in this case
+ Version =>
+ msize: int;
+ version: string;
+ Auth =>
+ aqid: Sys->Qid;
+ Attach =>
+ qid: Sys->Qid;
+ Flush =>
+ Error =>
+ ename: string;
+ Clunk or
+ Remove or
+ Wstat =>
+ Walk =>
+ qids: array of Sys->Qid;
+ Create or
+ Open =>
+ qid: Sys->Qid;
+ iounit: int;
+ Read =>
+ data: array of byte;
+ Write =>
+ count: int;
+ Stat =>
+ stat: Sys->Dir;
+ }
+
+ read: fn(fd: ref Sys->FD, msize: int): ref Rmsg;
+ unpack: fn(a: array of byte): (int, ref Rmsg);
+ pack: fn(nil: self ref Rmsg): array of byte;
+ packedsize: fn(nil: self ref Rmsg): int;
+ text: fn(nil: self ref Rmsg): string;
+ mtype: fn(nil: self ref Rmsg): int;
+ };
+
+ init: fn();
+
+ readmsg: fn(fd: ref Sys->FD, msize: int): (array of byte, string);
+ istmsg: fn(f: array of byte): int;
+
+ compatible: fn(t: ref Tmsg.Version, msize: int, version: string): (int,
string);
+
+ packdirsize: fn(d: Sys->Dir): int;
+ packdir: fn(d: Sys->Dir): array of byte;
+ unpackdir: fn(f: array of byte): (int, Sys->Dir);
+ dir2text: fn(d: Sys->Dir): string;
+ qid2text: fn(q: Sys->Qid): string;
+
+ utflen: fn(s: string): int;
+};
=======================================
--- /CHANGES Sat Feb 13 13:14:07 2010
+++ /CHANGES Sun Feb 21 04:11:43 2010
@@ -1,3 +1,5 @@
+20100220
+ appl/cmd/keyfs.b wasn't clunking fids on error in remove [issue 225]
20100213
apply saoret.one's changes for thumb [issue 155]
20100205
=======================================
--- /appl/cmd/9660srv.b Fri Dec 22 09:07:39 2006
+++ /appl/cmd/9660srv.b Sun Feb 21 04:11:43 2010
@@ -185,7 +185,7 @@
error("bad R-message conversion");
if(showstyx)
chat(r.text()+"\n");
- if(styx->write(rfd, rbuf, len rbuf) != len rbuf)
+ if(sys->write(rfd, rbuf, len rbuf) != len rbuf)
error(sys->sprint("connection write error: %r"));
}

=======================================
--- /appl/cmd/auth/keyfs.b Fri Dec 22 09:07:39 2006
+++ /appl/cmd/auth/keyfs.b Sun Feb 21 04:11:43 2010
@@ -415,6 +415,7 @@
}
case TYPE(c.path) {
Quser =>
+ srv.delfid(c);
u := finduserpath(c.path);
if(u == nil){
srv.reply(ref Rmsg.Error(m.tag, Eremoved));
@@ -422,9 +423,9 @@
}
removeuser(u);
writekeys(keyfile);
- srv.delfid(c);
srv.reply(ref Rmsg.Remove(m.tag));
Qsecret =>
+ srv.delfid(c);
u := finduserpath(c.path);
if(u == nil){
srv.reply(ref Rmsg.Error(m.tag, Eremoved));
@@ -432,7 +433,6 @@
}
u.secret = nil;
writekeys(keyfile);
- srv.delfid(c);
srv.reply(ref Rmsg.Remove(m.tag));
* =>
srv.remove(m); # let it reject it
=======================================
--- /appl/cmd/dossrv.b Fri Dec 22 09:07:39 2006
+++ /appl/cmd/dossrv.b Sun Feb 21 04:11:43 2010
@@ -195,7 +195,6 @@
{
sys->pctl(Sys->NEWFD, rfd.fd :: 2 :: nil);
rfd = sys->fildes(rfd.fd);
- data := array[Styx->MAXRPC] of byte;
while((t := Tmsg.read(rfd, 0)) != nil){
if(debug & STYX_MESS)
chat(sys->sprint("%s...", t.text()));
@@ -242,7 +241,7 @@
panic("Rmsg.pack");
if(debug & STYX_MESS)
chat(sys->sprint("%s\n", r.text()));
- if(styx->write(rfd, rbuf, len rbuf) != len rbuf)
+ if(sys->write(rfd, rbuf, len rbuf) != len rbuf)
panic("mount write");
}

@@ -967,7 +966,7 @@
oaddr := dp.addr;
ooffset := dp.offset;
d := dpd;
- od := *d;
+# od := *d;
# start := getstart(f.xf, d);
start := d.start;
length := d.length;
@@ -1395,7 +1394,7 @@
fileclust(f: ref Xfile, iclust: int, cflag: int): int
{

- bp := f.xf.ptr;
+# bp := f.xf.ptr;
dp := f.ptr;
if(isroot(dp.addr))
return -1; # root directory for old FAT format does not start on a
cluster boundary
@@ -2067,7 +2066,7 @@
truncfile(f: ref Xfile): int
{
xf := f.xf;
- bp := xf.ptr;
+# bp := xf.ptr;
dp := f.ptr;
d := Dosdir.arr2Dd(dp.p.iobuf[dp.offset:dp.offset+DOSDIRSIZE]);

=======================================
--- /appl/cmd/ftpfs.b Tue Aug 25 12:05:21 2009
+++ /appl/cmd/ftpfs.b Sun Feb 21 04:11:43 2010
@@ -280,7 +280,7 @@
if (debug)
sys->print("> %s\n", r.text());
a := r.pack();
- if(styx->write(styxfd, a, len a) != len a)
+ if(sys->write(styxfd, a, len a) != len a)
sys->print("ftpfs: error replying: %r\n");
}

=======================================
--- /appl/lib/styx.b Fri Dec 22 09:07:39 2006
+++ /appl/lib/styx.b Sun Feb 21 04:11:43 2010
@@ -571,7 +571,7 @@
return nil;
(nil, m) := Tmsg.unpack(msg);
if(m == nil)
- return ref Tmsg.Readerror(0, "bad Styx T-message format");
+ return ref Tmsg.Readerror(0, "bad 9P T-message format");
return m;
}

@@ -843,7 +843,7 @@
return nil;
(nil, m) := Rmsg.unpack(msg);
if(m == nil)
- return ref Rmsg.Readerror(0, "bad Styx R-message format");
+ return ref Rmsg.Readerror(0, "bad 9P R-message format");
return m;
}

@@ -863,7 +863,7 @@
if(msglim <= 0)
msglim = MAXRPC;
sbuf := array[BIT32SZ] of byte;
- if((n := readn(fd, sbuf, BIT32SZ)) != BIT32SZ){
+ if((n := sys->readn(fd, sbuf, BIT32SZ)) != BIT32SZ){
if(n == 0)
return (nil, nil);
return (nil, sys->sprint("%r"));
@@ -871,32 +871,18 @@
ml := (int sbuf[1] << 8) | int sbuf[0];
ml |= ((int sbuf[3] << 8) | int sbuf[2]) << 16;
if(ml <= BIT32SZ)
- return (nil, "invalid Styx message size");
+ return (nil, "invalid 9P message size");
if(ml > msglim)
- return (nil, "Styx message longer than agreed");
+ return (nil, "9P message longer than agreed");
buf := array[ml] of byte;
buf[0:] = sbuf;
- if((n = readn(fd, buf[BIT32SZ:], ml-BIT32SZ)) != ml-BIT32SZ){
+ if((n = sys->readn(fd, buf[BIT32SZ:], ml-BIT32SZ)) != ml-BIT32SZ){
if(n == 0)
- return (nil, "Styx message truncated");
+ return (nil, "9P message truncated");
return (nil, sys->sprint("%r"));
}
return (buf, nil);
}
-
-readn(fd: ref Sys->FD, buf: array of byte, nb: int): int
-{
- for(nr := 0; nr < nb;){
- n := sys->read(fd, buf[nr:], nb-nr);
- if(n <= 0){
- if(nr == 0)
- return n;
- break;
- }
- nr += n;
- }
- return nr;
-}

istmsg(f: array of byte): int
{
=======================================
--- /dis/9660srv.dis Fri Dec 22 12:52:35 2006
+++ /dis/9660srv.dis Sun Feb 21 04:11:43 2010
Binary file, no diff available.
=======================================
--- /dis/auth/keyfs.dis Fri Dec 22 12:52:35 2006
+++ /dis/auth/keyfs.dis Sun Feb 21 04:11:43 2010
Binary file, no diff available.
=======================================
--- /dis/dossrv.dis Fri Dec 22 12:52:35 2006
+++ /dis/dossrv.dis Sun Feb 21 04:11:43 2010
Binary file, no diff available.
=======================================
--- /dis/ftpfs.dis Tue Aug 25 12:05:21 2009
+++ /dis/ftpfs.dis Sun Feb 21 04:11:43 2010
Binary file, no diff available.
=======================================
--- /dis/lib/styx.dis Fri Dec 22 12:52:35 2006
+++ /dis/lib/styx.dis Sun Feb 21 04:11:43 2010
Binary file, no diff available.
=======================================
--- /include/version.h Sat Feb 13 13:14:07 2010
+++ /include/version.h Sun Feb 21 04:11:43 2010
@@ -1,1 +1,1 @@
-#define VERSION "Fourth Edition (20100213)"
+#define VERSION "Fourth Edition (20100221)"

==============================================================================
Revision: 62d7bd2f90
Author: me@challenger
Date: Sun Feb 21 06:23:46 2010
Log: Merge with inferno-os 20100220.
http://code.google.com/p/inferno-npe/source/detail?r=62d7bd2f90

Modified:
/CHANGES
/emu/port/devfs-posix.c
/include/version.h

=======================================
--- /CHANGES Sun Feb 7 07:49:54 2010
+++ /CHANGES Sun Feb 21 06:23:46 2010
@@ -1,3 +1,7 @@
+20100220
+ appl/cmd/keyfs.b wasn't clunking fids on error in remove [issue 225]
+20100213
+ apply saoret.one's changes for thumb [issue 155]
20100205
update man pages to replace most references to Styx by 9P
update man pages to replace references to sys-dial(2) by dial(2)
=======================================
--- /emu/port/devfs-posix.c Thu Jan 14 06:36:32 2010
+++ /emu/port/devfs-posix.c Sun Feb 21 06:23:46 2010
@@ -750,7 +750,7 @@
struct stat stbuf;
char path[MAXPATH], *ep;
struct dirent *de;
- static char slop[8192];
+ static uchar slop[8192];

i = 0;
fspath(FS(c)->name, "", path);
@@ -951,7 +951,6 @@
newuname(char *name)
{
struct passwd *p;
- User *u;

p = getpwnam(name);
if(p == nil)
@@ -963,7 +962,6 @@
newuid(int id)
{
struct passwd *p;
- User *u;

p = getpwuid(id);
if(p == nil)
@@ -1010,7 +1008,6 @@
static User*
id2user(User **tab, int id, User* (*get)(int))
{
- int i;
User *u, **h;

h = hashuser(tab, id);
=======================================
--- /include/version.h Sun Feb 7 07:49:54 2010
+++ /include/version.h Sun Feb 21 06:23:46 2010
@@ -1,1 +1,1 @@
-#define VERSION "Fourth Edition (20100205)"
+#define VERSION "Fourth Edition (20100221)"

Reply all
Reply to author
Forward
0 new messages