summaryrefslogtreecommitdiff
path: root/module/styxservers.m
blob: 28831bfa7085eec164c5c978321b6236d3a1ca9c (plain)
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);
};