1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
Styxservers: module
{
PATH: con "/dis/lib/styxservers.dis";
Fid: adt {
fid: int; # client's fid
path: big; # file's 64-bit unique path
qtype: int; # file's qid type (eg, Sys->QTDIR if directory)
isopen: int; # non-zero if file is open
mode: int; # if open, the open mode
doffset: (int, int); # (internal) cache of directory offset
uname: string; # user name from original attach
param: string; # attach aname from original attach
data: array of byte; # application data
clone: fn(f: self ref Fid, nf: ref Fid): ref Fid;
open: fn(f: self ref Fid, mode: int, qid: Sys->Qid);
walk: fn(f: self ref Fid, qid: Sys->Qid);
};
Navigator: adt {
c: chan of ref Navop;
reply: chan of (ref Sys->Dir, string);
new: fn(c: chan of ref Navop): ref Navigator;
stat: fn(t: self ref Navigator, q: big): (ref Sys->Dir, string);
walk: fn(t: self ref Navigator, parentq: big, name: string): (ref Sys->Dir, string);
readdir: fn(t: self ref Navigator, q: big, offset, count: int): array of ref Sys->Dir;
};
Navop: adt {
reply: chan of (ref Sys->Dir, string); # channel for reply
path: big; # file or directory path
pick {
Stat =>
Walk =>
name: string;
Readdir =>
offset: int; # index (origin 0) of first directory entry to return
count: int; # number of directory entries requested
}
};
Styxserver: adt {
fd: ref Sys->FD; # file server end of connection
fids: array of list of ref Fid; # hash table of fids
fidlock: chan of int;
t: ref Navigator; # name space navigator for this server
rootpath: big; # Qid.path of root of its name space
msize: int; # negotiated Styx message size
replychan: chan of ref Styx->Rmsg;
new: fn(fd: ref Sys->FD, t: ref Navigator, rootpath: big): (chan of ref Styx->Tmsg, ref Styxserver);
reply: fn(srv: self ref Styxserver, m: ref Styx->Rmsg): int;
replydirect: fn(srv: self ref Styxserver, m: ref Styx->Rmsg): int;
error: fn(srv: self ref Styxserver, m: ref Styx->Tmsg, msg: string);
# protocol operations
attach: fn(srv: self ref Styxserver, m: ref Styx->Tmsg.Attach): ref Fid;
clunk: fn(srv: self ref Styxserver, m: ref Styx->Tmsg.Clunk): ref Fid;
walk: fn(srv: self ref Styxserver, m: ref Styx->Tmsg.Walk): ref Fid;
open: fn(srv: self ref Styxserver, m: ref Styx->Tmsg.Open): ref Fid;
read: fn(srv: self ref Styxserver, m: ref Styx->Tmsg.Read): ref Fid;
remove: fn(srv: self ref Styxserver, m: ref Styx->Tmsg.Remove): ref Fid;
stat: fn(srv: self ref Styxserver, m: ref Styx->Tmsg.Stat);
default: fn(srv: self ref Styxserver, gm: ref Styx->Tmsg);
# check validity but don't reply
cancreate: fn(srv: self ref Styxserver, m: ref Styx->Tmsg.Create): (ref Fid, int, ref Sys->Dir, string);
canopen: fn(srv: self ref Styxserver, m: ref Styx->Tmsg.Open): (ref Fid, int, ref Sys->Dir, string);
canremove: fn(srv: self ref Styxserver, m: ref Styx->Tmsg.Remove): (ref Fid, big, string);
canread: fn(srv: self ref Styxserver, m: ref Styx->Tmsg.Read): (ref Fid, string);
canwrite: fn(srv: self ref Styxserver, m: ref Styx->Tmsg.Write): (ref Fid, string);
# fid management
getfid: fn(srv: self ref Styxserver, fid: int): ref Fid;
newfid: fn(srv: self ref Styxserver, fid: int): ref Fid;
delfid: fn(srv: self ref Styxserver, c: ref Fid);
allfids: fn(srv: self ref Styxserver): list of ref Fid;
iounit: fn(srv: self ref Styxserver): int;
};
init: fn(styx: Styx);
traceset: fn(on: int);
readbytes: fn(m: ref Styx->Tmsg.Read, d: array of byte): ref Styx->Rmsg.Read;
readstr: fn(m: ref Styx->Tmsg.Read, s: string): ref Styx->Rmsg.Read;
openok: fn(uname: string, omode, perm: int, fuid, fgid: string): int;
openmode: fn(o: int): int;
Einuse: con "fid already in use";
Ebadfid: con "bad fid";
Eopen: con "fid already opened";
Enotfound: con "file does not exist";
Enotdir: con "not a directory";
Eperm: con "permission denied";
Ebadarg: con "bad argument";
Eexists: con "file already exists";
Emode: con "open/create -- unknown mode";
Eoffset: con "read/write -- bad offset";
Ecount: con "read/write -- count negative or exceeds msgsize";
Enotopen: con "read/write -- on non open fid";
Eaccess: con "read/write -- not open in suitable mode";
Ename: con "bad character in file name";
Edot: con ". and .. are illegal names";
};
Nametree: module {
PATH: con "/dis/lib/nametree.dis";
Tree: adt {
c: chan of ref Treeop;
reply: chan of string;
quit: fn(t: self ref Tree);
create: fn(t: self ref Tree, parent: big, d: Sys->Dir): string;
wstat: fn(t: self ref Tree, path: big, d: Sys->Dir): string;
remove: fn(t: self ref Tree, path: big): string;
getpath: fn(t: self ref Tree, path: big): string;
};
Treeop: adt {
reply: chan of string;
q: big;
pick {
Create or
Wstat =>
d: Sys->Dir;
Remove =>
Getpath =>
}
};
init: fn();
start: fn(): (ref Tree, chan of ref Styxservers->Navop);
};
|