Blame


1 cfa37a7b 2004-04-10 devnull .TH 9P 3
2 cfa37a7b 2004-04-10 devnull .SH NAME
3 cfa37a7b 2004-04-10 devnull Srv,
4 cfa37a7b 2004-04-10 devnull dirread9p,
5 cfa37a7b 2004-04-10 devnull emalloc9p,
6 cfa37a7b 2004-04-10 devnull erealloc9p,
7 cfa37a7b 2004-04-10 devnull estrdup9p,
8 cfa37a7b 2004-04-10 devnull postfd,
9 cfa37a7b 2004-04-10 devnull postmountsrv,
10 cfa37a7b 2004-04-10 devnull readbuf,
11 cfa37a7b 2004-04-10 devnull readstr,
12 cfa37a7b 2004-04-10 devnull respond,
13 058b0118 2005-01-03 devnull srv,
14 cfa37a7b 2004-04-10 devnull threadpostmountsrv,
15 058b0118 2005-01-03 devnull walkandclone \- 9P file service
16 cfa37a7b 2004-04-10 devnull .SH SYNOPSIS
17 cfa37a7b 2004-04-10 devnull .ft L
18 cfa37a7b 2004-04-10 devnull .nf
19 cfa37a7b 2004-04-10 devnull #include <u.h>
20 cfa37a7b 2004-04-10 devnull #include <libc.h>
21 cfa37a7b 2004-04-10 devnull #include <fcall.h>
22 cfa37a7b 2004-04-10 devnull #include <thread.h>
23 cfa37a7b 2004-04-10 devnull #include <9p.h>
24 cfa37a7b 2004-04-10 devnull .fi
25 cfa37a7b 2004-04-10 devnull .PP
26 cfa37a7b 2004-04-10 devnull .ft L
27 cfa37a7b 2004-04-10 devnull .nf
28 cfa37a7b 2004-04-10 devnull .ta \w'\fL1234'u +\w'\fLTree* 'u
29 cfa37a7b 2004-04-10 devnull typedef struct Srv {
30 cfa37a7b 2004-04-10 devnull Tree* tree;
31 cfa37a7b 2004-04-10 devnull
32 cfa37a7b 2004-04-10 devnull void (*attach)(Req *r);
33 cfa37a7b 2004-04-10 devnull void (*auth)(Req *r);
34 cfa37a7b 2004-04-10 devnull void (*open)(Req *r);
35 cfa37a7b 2004-04-10 devnull void (*create)(Req *r);
36 cfa37a7b 2004-04-10 devnull void (*read)(Req *r);
37 cfa37a7b 2004-04-10 devnull void (*write)(Req *r);
38 cfa37a7b 2004-04-10 devnull void (*remove)(Req *r);
39 cfa37a7b 2004-04-10 devnull void (*flush)(Req *r);
40 cfa37a7b 2004-04-10 devnull void (*stat)(Req *r);
41 cfa37a7b 2004-04-10 devnull void (*wstat)(Req *r);
42 cfa37a7b 2004-04-10 devnull void (*walk)(Req *r);
43 cfa37a7b 2004-04-10 devnull
44 cfa37a7b 2004-04-10 devnull char* (*walk1)(Fid *fid, char *name, Qid *qid);
45 cfa37a7b 2004-04-10 devnull char* (*clone)(Fid *oldfid, Fid *newfid);
46 cfa37a7b 2004-04-10 devnull
47 cfa37a7b 2004-04-10 devnull void (*destroyfid)(Fid *fid);
48 cfa37a7b 2004-04-10 devnull void (*destroyreq)(Req *r);
49 cfa37a7b 2004-04-10 devnull void (*end)(Srv *s);
50 cfa37a7b 2004-04-10 devnull void* aux;
51 cfa37a7b 2004-04-10 devnull
52 cfa37a7b 2004-04-10 devnull int infd;
53 cfa37a7b 2004-04-10 devnull int outfd;
54 cfa37a7b 2004-04-10 devnull int srvfd;
55 cfa37a7b 2004-04-10 devnull int nopipe;
56 cfa37a7b 2004-04-10 devnull } Srv;
57 cfa37a7b 2004-04-10 devnull .fi
58 cfa37a7b 2004-04-10 devnull .PP
59 cfa37a7b 2004-04-10 devnull .nf
60 cfa37a7b 2004-04-10 devnull .ft L
61 cfa37a7b 2004-04-10 devnull .ta \w'\fLvoid* 'u
62 cfa37a7b 2004-04-10 devnull int srv(Srv *s)
63 cfa37a7b 2004-04-10 devnull void postmountsrv(Srv *s, char *name, char *mtpt, int flag)
64 cfa37a7b 2004-04-10 devnull void threadpostmountsrv(Srv *s, char *name, char *mtpt, int flag)
65 cfa37a7b 2004-04-10 devnull int postfd(char *srvname, int fd)
66 cfa37a7b 2004-04-10 devnull void respond(Req *r, char *error)
67 cfa37a7b 2004-04-10 devnull ulong readstr(Req *r, char *src)
68 cfa37a7b 2004-04-10 devnull ulong readbuf(Req *r, void *src, ulong nsrc)
69 cfa37a7b 2004-04-10 devnull typedef int Dirgen(int n, Dir *dir, void *aux)
70 cfa37a7b 2004-04-10 devnull void dirread9p(Req *r, Dirgen *gen, void *aux)
71 cfa37a7b 2004-04-10 devnull void walkandclone(Req *r, char *(*walk1)(Fid *old, char *name, void *v),
72 cfa37a7b 2004-04-10 devnull char *(*clone)(Fid *old, Fid *new, void *v), void *v)
73 cfa37a7b 2004-04-10 devnull .fi
74 cfa37a7b 2004-04-10 devnull .PP
75 cfa37a7b 2004-04-10 devnull .nf
76 cfa37a7b 2004-04-10 devnull .ft L
77 cfa37a7b 2004-04-10 devnull .ta \w'\fLvoid* 'u
78 cfa37a7b 2004-04-10 devnull void* emalloc9p(ulong n)
79 cfa37a7b 2004-04-10 devnull void* erealloc9p(void *v, ulong n)
80 cfa37a7b 2004-04-10 devnull char* estrdup9p(char *s)
81 cfa37a7b 2004-04-10 devnull .fi
82 cfa37a7b 2004-04-10 devnull .PP
83 cfa37a7b 2004-04-10 devnull .nf
84 cfa37a7b 2004-04-10 devnull .ft L
85 cfa37a7b 2004-04-10 devnull extern int chatty9p;
86 cfa37a7b 2004-04-10 devnull .fi
87 cfa37a7b 2004-04-10 devnull .SH DESCRIPTION
88 cfa37a7b 2004-04-10 devnull The function
89 cfa37a7b 2004-04-10 devnull .I srv
90 cfa37a7b 2004-04-10 devnull serves a 9P session by reading requests from
91 cfa37a7b 2004-04-10 devnull .BR s->infd ,
92 cfa37a7b 2004-04-10 devnull dispatching them to the function pointers kept in
93 cfa37a7b 2004-04-10 devnull .BR Srv ,
94 cfa37a7b 2004-04-10 devnull and
95 cfa37a7b 2004-04-10 devnull writing the responses to
96 cfa37a7b 2004-04-10 devnull .BR s->outfd .
97 cfa37a7b 2004-04-10 devnull (Typically,
98 cfa37a7b 2004-04-10 devnull .I postmountsrv
99 cfa37a7b 2004-04-10 devnull or
100 cfa37a7b 2004-04-10 devnull .I threadpostmountsrv
101 cfa37a7b 2004-04-10 devnull initializes the
102 cfa37a7b 2004-04-10 devnull .B infd
103 cfa37a7b 2004-04-10 devnull and
104 cfa37a7b 2004-04-10 devnull .B outfd
105 cfa37a7b 2004-04-10 devnull structure members. See the description below.)
106 cfa37a7b 2004-04-10 devnull .PP
107 cfa37a7b 2004-04-10 devnull .B Req
108 cfa37a7b 2004-04-10 devnull and
109 cfa37a7b 2004-04-10 devnull .B Fid
110 cfa37a7b 2004-04-10 devnull structures are allocated one-to-one with uncompleted
111 cfa37a7b 2004-04-10 devnull requests and active fids, and are described in
112 bf8a59fa 2004-04-11 devnull .IR 9pfid (3).
113 cfa37a7b 2004-04-10 devnull .PP
114 cfa37a7b 2004-04-10 devnull The behavior of
115 cfa37a7b 2004-04-10 devnull .I srv
116 cfa37a7b 2004-04-10 devnull depends on whether there is a file tree
117 cfa37a7b 2004-04-10 devnull (see
118 bf8a59fa 2004-04-11 devnull .IR 9pfile (3))
119 cfa37a7b 2004-04-10 devnull associated with the server, that is,
120 cfa37a7b 2004-04-10 devnull whether the
121 cfa37a7b 2004-04-10 devnull .B tree
122 cfa37a7b 2004-04-10 devnull element is nonzero.
123 cfa37a7b 2004-04-10 devnull The differences are made explicit in the
124 cfa37a7b 2004-04-10 devnull discussion of the service loop below.
125 cfa37a7b 2004-04-10 devnull The
126 cfa37a7b 2004-04-10 devnull .B aux
127 cfa37a7b 2004-04-10 devnull element is the client's, to do with as it pleases.
128 cfa37a7b 2004-04-10 devnull .PP
129 cfa37a7b 2004-04-10 devnull .I Srv
130 cfa37a7b 2004-04-10 devnull does not return until the 9P conversation is finished.
131 cfa37a7b 2004-04-10 devnull Since it is usually run in a separate process so that
132 cfa37a7b 2004-04-10 devnull the caller can exit, the service loop has little chance
133 cfa37a7b 2004-04-10 devnull to return gracefully on out of memory errors.
134 cfa37a7b 2004-04-10 devnull It calls
135 cfa37a7b 2004-04-10 devnull .IR emalloc9p ,
136 cfa37a7b 2004-04-10 devnull .IR erealloc9p ,
137 cfa37a7b 2004-04-10 devnull and
138 cfa37a7b 2004-04-10 devnull .I estrdup9p
139 cfa37a7b 2004-04-10 devnull to obtain its memory.
140 cfa37a7b 2004-04-10 devnull The default implementations of these functions
141 cfa37a7b 2004-04-10 devnull act as
142 cfa37a7b 2004-04-10 devnull .IR malloc ,
143 cfa37a7b 2004-04-10 devnull .IR realloc ,
144 cfa37a7b 2004-04-10 devnull and
145 cfa37a7b 2004-04-10 devnull .I strdup
146 cfa37a7b 2004-04-10 devnull but abort the program if they run out of memory.
147 cfa37a7b 2004-04-10 devnull If alternate behavior is desired, clients can link against
148 cfa37a7b 2004-04-10 devnull alternate implementations of these functions.
149 cfa37a7b 2004-04-10 devnull .PP
150 cfa37a7b 2004-04-10 devnull .I Postmountsrv
151 cfa37a7b 2004-04-10 devnull and
152 cfa37a7b 2004-04-10 devnull .I threadpostmountsrv
153 cfa37a7b 2004-04-10 devnull are wrappers that create a separate process in which to run
154 cfa37a7b 2004-04-10 devnull .IR srv .
155 cfa37a7b 2004-04-10 devnull They do the following:
156 cfa37a7b 2004-04-10 devnull .IP
157 cfa37a7b 2004-04-10 devnull If
158 cfa37a7b 2004-04-10 devnull .IB s -> nopipe
159 cfa37a7b 2004-04-10 devnull is zero (the common case),
160 cfa37a7b 2004-04-10 devnull initialize
161 cfa37a7b 2004-04-10 devnull .IB s -> infd
162 cfa37a7b 2004-04-10 devnull and
163 cfa37a7b 2004-04-10 devnull .IB s -> outfd
164 cfa37a7b 2004-04-10 devnull to be one end of a freshly allocated pipe,
165 cfa37a7b 2004-04-10 devnull with
166 cfa37a7b 2004-04-10 devnull .IB s -> srvfd
167 cfa37a7b 2004-04-10 devnull initialized as the other end.
168 cfa37a7b 2004-04-10 devnull .IP
169 cfa37a7b 2004-04-10 devnull If
170 cfa37a7b 2004-04-10 devnull .B name
171 cfa37a7b 2004-04-10 devnull is non-nil, call
172 cfa37a7b 2004-04-10 devnull .BI postfd( s -> srvfd ,
173 cfa37a7b 2004-04-10 devnull .IB name )
174 cfa37a7b 2004-04-10 devnull to post
175 cfa37a7b 2004-04-10 devnull .IB s -> srvfd
176 cfa37a7b 2004-04-10 devnull as
177 cfa37a7b 2004-04-10 devnull .BI /srv/ name .
178 cfa37a7b 2004-04-10 devnull .IP
179 cfa37a7b 2004-04-10 devnull Fork a child process via
180 058b0118 2005-01-03 devnull .IR rfork (3)
181 cfa37a7b 2004-04-10 devnull or
182 cfa37a7b 2004-04-10 devnull .I procrfork
183 cfa37a7b 2004-04-10 devnull (see
184 bf8a59fa 2004-04-11 devnull .IR thread (3)),
185 cfa37a7b 2004-04-10 devnull using the
186 cfa37a7b 2004-04-10 devnull .BR RFFDG ,
187 cfa37a7b 2004-04-10 devnull .RR RFNOTEG ,
188 cfa37a7b 2004-04-10 devnull .BR RFNAMEG ,
189 cfa37a7b 2004-04-10 devnull and
190 cfa37a7b 2004-04-10 devnull .BR RFMEM
191 cfa37a7b 2004-04-10 devnull flags.
192 cfa37a7b 2004-04-10 devnull The child process
193 cfa37a7b 2004-04-10 devnull calls
194 cfa37a7b 2004-04-10 devnull .IB close( s -> srvfd )
195 cfa37a7b 2004-04-10 devnull and then
196 cfa37a7b 2004-04-10 devnull .IB srv( s ) \fR;
197 cfa37a7b 2004-04-10 devnull it will exit once
198 cfa37a7b 2004-04-10 devnull .I srv
199 cfa37a7b 2004-04-10 devnull returns.
200 cfa37a7b 2004-04-10 devnull .IP
201 cfa37a7b 2004-04-10 devnull If
202 cfa37a7b 2004-04-10 devnull .I mtpt
203 cfa37a7b 2004-04-10 devnull is non-nil,
204 cfa37a7b 2004-04-10 devnull call
205 cfa37a7b 2004-04-10 devnull .BI amount( s -> srvfd,
206 cfa37a7b 2004-04-10 devnull .IB mtpt ,
207 cfa37a7b 2004-04-10 devnull .IB flag ,
208 cfa37a7b 2004-04-10 devnull \fB"")\fR;
209 cfa37a7b 2004-04-10 devnull otherwise, close
210 cfa37a7b 2004-04-10 devnull .IB s -> srvfd \fR.
211 cfa37a7b 2004-04-10 devnull .IP
212 cfa37a7b 2004-04-10 devnull The parent returns to the caller.
213 cfa37a7b 2004-04-10 devnull .LP
214 cfa37a7b 2004-04-10 devnull If any error occurs during
215 cfa37a7b 2004-04-10 devnull this process, the entire process is terminated by calling
216 058b0118 2005-01-03 devnull .IR sysfatal (3).
217 cfa37a7b 2004-04-10 devnull .SS Service functions
218 cfa37a7b 2004-04-10 devnull The functions in a
219 cfa37a7b 2004-04-10 devnull .B Srv
220 cfa37a7b 2004-04-10 devnull structure named after 9P transactions
221 cfa37a7b 2004-04-10 devnull are called to satisfy requests as they arrive.
222 cfa37a7b 2004-04-10 devnull If a function is provided, it
223 cfa37a7b 2004-04-10 devnull .I must
224 cfa37a7b 2004-04-10 devnull arrange for
225 cfa37a7b 2004-04-10 devnull .I respond
226 cfa37a7b 2004-04-10 devnull to be called when the request is satisfied.
227 cfa37a7b 2004-04-10 devnull The only parameter of each service function
228 cfa37a7b 2004-04-10 devnull is a
229 cfa37a7b 2004-04-10 devnull .B Req*
230 cfa37a7b 2004-04-10 devnull parameter (say
231 cfa37a7b 2004-04-10 devnull .IR r ).
232 cfa37a7b 2004-04-10 devnull The incoming request parameters are stored in
233 cfa37a7b 2004-04-10 devnull .IB r -> ifcall \fR;
234 cfa37a7b 2004-04-10 devnull .IB r -> fid
235 cfa37a7b 2004-04-10 devnull and
236 cfa37a7b 2004-04-10 devnull .IB r -> newfid
237 cfa37a7b 2004-04-10 devnull are pointers to
238 cfa37a7b 2004-04-10 devnull .B Fid
239 cfa37a7b 2004-04-10 devnull structures corresponding to the
240 cfa37a7b 2004-04-10 devnull numeric fids in
241 cfa37a7b 2004-04-10 devnull .IB r -> ifcall \fR;
242 cfa37a7b 2004-04-10 devnull similarly,
243 cfa37a7b 2004-04-10 devnull .IB r -> oldreq
244 cfa37a7b 2004-04-10 devnull is the
245 cfa37a7b 2004-04-10 devnull .B Req
246 cfa37a7b 2004-04-10 devnull structure corresponding to
247 cfa37a7b 2004-04-10 devnull .IB r -> ifcall.oldtag \fR.
248 cfa37a7b 2004-04-10 devnull The outgoing response data should be stored in
249 cfa37a7b 2004-04-10 devnull .IB r -> ofcall \fR.
250 cfa37a7b 2004-04-10 devnull The one exception to this rule is that
251 cfa37a7b 2004-04-10 devnull .I stat
252 cfa37a7b 2004-04-10 devnull should fill in
253 cfa37a7b 2004-04-10 devnull .IB r -> d
254 cfa37a7b 2004-04-10 devnull rather than
255 cfa37a7b 2004-04-10 devnull .IB r -> ofcall.stat \fR:
256 cfa37a7b 2004-04-10 devnull the library will convert the structure into the machine-independent
257 cfa37a7b 2004-04-10 devnull wire representation.
258 cfa37a7b 2004-04-10 devnull Similarly,
259 cfa37a7b 2004-04-10 devnull .I wstat
260 cfa37a7b 2004-04-10 devnull may consult
261 cfa37a7b 2004-04-10 devnull .IB r -> d
262 cfa37a7b 2004-04-10 devnull rather than decoding
263 cfa37a7b 2004-04-10 devnull .IB r -> ifcall . stat
264 cfa37a7b 2004-04-10 devnull itself.
265 cfa37a7b 2004-04-10 devnull When a request has been handled,
266 cfa37a7b 2004-04-10 devnull .I respond
267 cfa37a7b 2004-04-10 devnull should be called with
268 cfa37a7b 2004-04-10 devnull .I r
269 cfa37a7b 2004-04-10 devnull and an error string.
270 cfa37a7b 2004-04-10 devnull If the request was satisfied successfully, the error
271 cfa37a7b 2004-04-10 devnull string should be a nil pointer.
272 cfa37a7b 2004-04-10 devnull Note that it is permissible for a function to return
273 cfa37a7b 2004-04-10 devnull without itself calling
274 cfa37a7b 2004-04-10 devnull .IR respond ,
275 cfa37a7b 2004-04-10 devnull as long as it has arranged for
276 cfa37a7b 2004-04-10 devnull .I respond
277 cfa37a7b 2004-04-10 devnull to be called at some point in the future
278 cfa37a7b 2004-04-10 devnull by another proc sharing its address space,
279 cfa37a7b 2004-04-10 devnull but see the discussion of
280 cfa37a7b 2004-04-10 devnull .I flush
281 cfa37a7b 2004-04-10 devnull below.
282 cfa37a7b 2004-04-10 devnull Once
283 cfa37a7b 2004-04-10 devnull .I respond
284 cfa37a7b 2004-04-10 devnull has been called, the
285 cfa37a7b 2004-04-10 devnull .B Req*
286 cfa37a7b 2004-04-10 devnull as well as any pointers it once contained must
287 cfa37a7b 2004-04-10 devnull be considered freed and not referenced.
288 cfa37a7b 2004-04-10 devnull .PP
289 cfa37a7b 2004-04-10 devnull If the service loop detects an error in a request
290 cfa37a7b 2004-04-10 devnull (e.g., an attempt to reuse an extant fid, an open of
291 cfa37a7b 2004-04-10 devnull an already open fid, a read from a fid opened for write, etc.)
292 cfa37a7b 2004-04-10 devnull it will reply with an error without consulting
293 cfa37a7b 2004-04-10 devnull the service functions.
294 cfa37a7b 2004-04-10 devnull .PP
295 cfa37a7b 2004-04-10 devnull The service loop provided by
296 cfa37a7b 2004-04-10 devnull .I srv
297 cfa37a7b 2004-04-10 devnull (and indirectly by
298 cfa37a7b 2004-04-10 devnull .I postmountsrv
299 cfa37a7b 2004-04-10 devnull and
300 cfa37a7b 2004-04-10 devnull .IR threadpostmountsrv )
301 cfa37a7b 2004-04-10 devnull is single-threaded.
302 cfa37a7b 2004-04-10 devnull If it is expected that some requests might
303 cfa37a7b 2004-04-10 devnull block, arranging for alternate processes
304 cfa37a7b 2004-04-10 devnull to handle them is suggested.
305 cfa37a7b 2004-04-10 devnull .PP
306 cfa37a7b 2004-04-10 devnull The constraints on the service functions are as follows.
307 cfa37a7b 2004-04-10 devnull These constraints are checked while the server executes.
308 cfa37a7b 2004-04-10 devnull If a service function fails to do something it ought to have,
309 cfa37a7b 2004-04-10 devnull .I srv
310 cfa37a7b 2004-04-10 devnull will call
311 cfa37a7b 2004-04-10 devnull .I endsrv
312 cfa37a7b 2004-04-10 devnull and then abort.
313 cfa37a7b 2004-04-10 devnull .TP
314 cfa37a7b 2004-04-10 devnull .I Auth
315 cfa37a7b 2004-04-10 devnull If authentication is desired,
316 cfa37a7b 2004-04-10 devnull the
317 cfa37a7b 2004-04-10 devnull .I auth
318 cfa37a7b 2004-04-10 devnull function should record that
319 cfa37a7b 2004-04-10 devnull .I afid
320 cfa37a7b 2004-04-10 devnull is the new authentication fid and
321 cfa37a7b 2004-04-10 devnull set
322 cfa37a7b 2004-04-10 devnull .I afid->qid
323 cfa37a7b 2004-04-10 devnull and
324 cfa37a7b 2004-04-10 devnull .IR ofcall.qid .
325 cfa37a7b 2004-04-10 devnull .I Auth
326 cfa37a7b 2004-04-10 devnull may be nil, in which case it will be treated as having
327 cfa37a7b 2004-04-10 devnull responded with the error
328 cfa37a7b 2004-04-10 devnull .RI `` "argv0: authentication not required" ,''
329 cfa37a7b 2004-04-10 devnull where
330 cfa37a7b 2004-04-10 devnull .I argv0
331 cfa37a7b 2004-04-10 devnull is the program name variable as set by
332 cfa37a7b 2004-04-10 devnull .I ARGBEGIN
333 cfa37a7b 2004-04-10 devnull (see
334 bf8a59fa 2004-04-11 devnull .IR arg (3)).
335 cfa37a7b 2004-04-10 devnull .TP
336 cfa37a7b 2004-04-10 devnull .I Attach
337 cfa37a7b 2004-04-10 devnull The
338 cfa37a7b 2004-04-10 devnull .I attach
339 cfa37a7b 2004-04-10 devnull function should check the authentication state of
340 cfa37a7b 2004-04-10 devnull .I afid
341 cfa37a7b 2004-04-10 devnull if desired,
342 cfa37a7b 2004-04-10 devnull and set
343 cfa37a7b 2004-04-10 devnull .IB r -> fid -> qid
344 cfa37a7b 2004-04-10 devnull and
345 cfa37a7b 2004-04-10 devnull .I ofcall.qid
346 cfa37a7b 2004-04-10 devnull to the qid of the file system root.
347 cfa37a7b 2004-04-10 devnull .I Attach
348 cfa37a7b 2004-04-10 devnull may be nil only if file trees are in use;
349 cfa37a7b 2004-04-10 devnull in this case, the qid will be filled from the root
350 cfa37a7b 2004-04-10 devnull of the tree, and no authentication will be done.
351 cfa37a7b 2004-04-10 devnull .TP
352 cfa37a7b 2004-04-10 devnull .I Walk
353 cfa37a7b 2004-04-10 devnull If file trees are in use,
354 cfa37a7b 2004-04-10 devnull .I walk
355 cfa37a7b 2004-04-10 devnull is handled internally, and
356 cfa37a7b 2004-04-10 devnull .IB srv -> walk
357 cfa37a7b 2004-04-10 devnull is never called.
358 cfa37a7b 2004-04-10 devnull .IP
359 cfa37a7b 2004-04-10 devnull If file trees are not in use,
360 cfa37a7b 2004-04-10 devnull .I walk
361 cfa37a7b 2004-04-10 devnull should consult
362 cfa37a7b 2004-04-10 devnull .IB r -> ifcall . wname
363 cfa37a7b 2004-04-10 devnull and
364 cfa37a7b 2004-04-10 devnull .IB r -> ifcall . nwname \fR,
365 cfa37a7b 2004-04-10 devnull filling in
366 cfa37a7b 2004-04-10 devnull .IB ofcall . qid
367 cfa37a7b 2004-04-10 devnull and
368 cfa37a7b 2004-04-10 devnull .IB ofcall . nqid \fR,
369 cfa37a7b 2004-04-10 devnull and also copying any necessary
370 cfa37a7b 2004-04-10 devnull .I aux
371 cfa37a7b 2004-04-10 devnull state from
372 cfa37a7b 2004-04-10 devnull .IB r -> fid
373 cfa37a7b 2004-04-10 devnull to
374 cfa37a7b 2004-04-10 devnull .IB r -> newfid
375 cfa37a7b 2004-04-10 devnull when the two are different.
376 cfa37a7b 2004-04-10 devnull As long as
377 cfa37a7b 2004-04-10 devnull .I walk
378 cfa37a7b 2004-04-10 devnull sets
379 cfa37a7b 2004-04-10 devnull .IB ofcall . nqid
380 cfa37a7b 2004-04-10 devnull appropriately, it can
381 cfa37a7b 2004-04-10 devnull .I respond
382 cfa37a7b 2004-04-10 devnull with a nil error string even when 9P
383 cfa37a7b 2004-04-10 devnull demands an error
384 cfa37a7b 2004-04-10 devnull .RI ( e.g. ,
385 cfa37a7b 2004-04-10 devnull in the case of a short walk);
386 cfa37a7b 2004-04-10 devnull the library detects error conditions and handles them appropriately.
387 cfa37a7b 2004-04-10 devnull .IP
388 cfa37a7b 2004-04-10 devnull Because implementing the full walk message is intricate and
389 cfa37a7b 2004-04-10 devnull prone to error, the helper routine
390 cfa37a7b 2004-04-10 devnull .I walkandclone
391 cfa37a7b 2004-04-10 devnull will handle the request given pointers to two functions
392 cfa37a7b 2004-04-10 devnull .I walk1
393 cfa37a7b 2004-04-10 devnull and (optionally)
394 cfa37a7b 2004-04-10 devnull .I clone .
395 cfa37a7b 2004-04-10 devnull .IR Clone ,
396 cfa37a7b 2004-04-10 devnull if non-nil, is called to signal the creation of
397 cfa37a7b 2004-04-10 devnull .I newfid
398 cfa37a7b 2004-04-10 devnull from
399 cfa37a7b 2004-04-10 devnull .IR oldfid .
400 cfa37a7b 2004-04-10 devnull Typically a
401 cfa37a7b 2004-04-10 devnull .I clone
402 cfa37a7b 2004-04-10 devnull routine will copy or increment a reference count in
403 cfa37a7b 2004-04-10 devnull .IR oldfid 's
404 cfa37a7b 2004-04-10 devnull .I aux
405 cfa37a7b 2004-04-10 devnull element.
406 cfa37a7b 2004-04-10 devnull .I Walk1
407 cfa37a7b 2004-04-10 devnull should walk
408 cfa37a7b 2004-04-10 devnull .I fid
409 cfa37a7b 2004-04-10 devnull to
410 cfa37a7b 2004-04-10 devnull .IR name ,
411 cfa37a7b 2004-04-10 devnull initializing
412 cfa37a7b 2004-04-10 devnull .IB fid -> qid
413 cfa37a7b 2004-04-10 devnull to the new path's qid.
414 cfa37a7b 2004-04-10 devnull Both should return nil
415 cfa37a7b 2004-04-10 devnull on success or an error message on error.
416 cfa37a7b 2004-04-10 devnull .I Walkandclone
417 cfa37a7b 2004-04-10 devnull will call
418 cfa37a7b 2004-04-10 devnull .I respond
419 cfa37a7b 2004-04-10 devnull after handling the request.
420 cfa37a7b 2004-04-10 devnull .TP
421 cfa37a7b 2004-04-10 devnull .I Walk1\fR, \fPClone
422 cfa37a7b 2004-04-10 devnull If the client provides functions
423 cfa37a7b 2004-04-10 devnull .IB srv -> walk1
424 cfa37a7b 2004-04-10 devnull and (optionally)
425 cfa37a7b 2004-04-10 devnull .IB srv -> clone \fR,
426 cfa37a7b 2004-04-10 devnull the 9P service loop will call
427 cfa37a7b 2004-04-10 devnull .I walkandclone
428 cfa37a7b 2004-04-10 devnull with these functions to handle the request.
429 cfa37a7b 2004-04-10 devnull Unlike the
430 cfa37a7b 2004-04-10 devnull .I walk1
431 cfa37a7b 2004-04-10 devnull above,
432 cfa37a7b 2004-04-10 devnull .IB srv -> walk1
433 cfa37a7b 2004-04-10 devnull must fill in both
434 cfa37a7b 2004-04-10 devnull .IB fid -> qid
435 cfa37a7b 2004-04-10 devnull and
436 cfa37a7b 2004-04-10 devnull .BI * qid
437 cfa37a7b 2004-04-10 devnull with the new qid on a successful walk.
438 cfa37a7b 2004-04-10 devnull .TP
439 cfa37a7b 2004-04-10 devnull .I Open
440 cfa37a7b 2004-04-10 devnull If file trees are in use, the file
441 cfa37a7b 2004-04-10 devnull metadata will be consulted on open, create, remove, and wstat
442 cfa37a7b 2004-04-10 devnull to see if the requester has the appropriate permissions.
443 cfa37a7b 2004-04-10 devnull If not, an error will be sent back without consulting a service function.
444 cfa37a7b 2004-04-10 devnull .PP
445 cfa37a7b 2004-04-10 devnull If not using file trees or the user has the appropriate permissions,
446 cfa37a7b 2004-04-10 devnull .I open
447 cfa37a7b 2004-04-10 devnull is called with
448 cfa37a7b 2004-04-10 devnull .IB r -> ofcall . qid
449 cfa37a7b 2004-04-10 devnull already initialized to the one stored in the
450 cfa37a7b 2004-04-10 devnull .B Fid
451 cfa37a7b 2004-04-10 devnull structure (that is, the one returned in the previous walk).
452 cfa37a7b 2004-04-10 devnull If the qid changes, both should be updated.
453 cfa37a7b 2004-04-10 devnull .TP
454 cfa37a7b 2004-04-10 devnull .I Create
455 cfa37a7b 2004-04-10 devnull The
456 cfa37a7b 2004-04-10 devnull .I create
457 cfa37a7b 2004-04-10 devnull function must fill in
458 cfa37a7b 2004-04-10 devnull both
459 cfa37a7b 2004-04-10 devnull .IB r -> fid -> qid
460 cfa37a7b 2004-04-10 devnull and
461 cfa37a7b 2004-04-10 devnull .IB r -> ofcall . qid
462 cfa37a7b 2004-04-10 devnull on success.
463 cfa37a7b 2004-04-10 devnull When using file trees,
464 cfa37a7b 2004-04-10 devnull .I create
465 cfa37a7b 2004-04-10 devnull should allocate a new
466 cfa37a7b 2004-04-10 devnull .B File
467 cfa37a7b 2004-04-10 devnull with
468 cfa37a7b 2004-04-10 devnull .IR createfile ;
469 cfa37a7b 2004-04-10 devnull note that
470 cfa37a7b 2004-04-10 devnull .I createfile
471 cfa37a7b 2004-04-10 devnull may return nil (because, say, the file already exists).
472 cfa37a7b 2004-04-10 devnull If the
473 cfa37a7b 2004-04-10 devnull .I create
474 cfa37a7b 2004-04-10 devnull function is nil,
475 cfa37a7b 2004-04-10 devnull .I srv
476 cfa37a7b 2004-04-10 devnull behaves as though it were a function that always responded
477 cfa37a7b 2004-04-10 devnull with the error ``create prohibited''.
478 cfa37a7b 2004-04-10 devnull .TP
479 cfa37a7b 2004-04-10 devnull .I Remove
480 cfa37a7b 2004-04-10 devnull .I Remove
481 cfa37a7b 2004-04-10 devnull should mark the file as removed, whether
482 cfa37a7b 2004-04-10 devnull by calling
483 cfa37a7b 2004-04-10 devnull .I removefile
484 cfa37a7b 2004-04-10 devnull when using file trees, or by updating an internal data structure.
485 cfa37a7b 2004-04-10 devnull In general it is not a good idea to clean up the
486 cfa37a7b 2004-04-10 devnull .I aux
487 cfa37a7b 2004-04-10 devnull information associated with the corresponding
488 cfa37a7b 2004-04-10 devnull .B File
489 cfa37a7b 2004-04-10 devnull at this time, to avoid memory errors if other
490 cfa37a7b 2004-04-10 devnull fids have references to that file.
491 cfa37a7b 2004-04-10 devnull Instead, it is suggested that
492 cfa37a7b 2004-04-10 devnull .I remove
493 cfa37a7b 2004-04-10 devnull simply mark the file as removed (so that further
494 cfa37a7b 2004-04-10 devnull operations on it know to fail) and wait until the
495 cfa37a7b 2004-04-10 devnull file tree's destroy function is called to reclaim the
496 cfa37a7b 2004-04-10 devnull .I aux
497 cfa37a7b 2004-04-10 devnull pointer.
498 cfa37a7b 2004-04-10 devnull If not using file trees, it is prudent to take the
499 cfa37a7b 2004-04-10 devnull analogous measures.
500 cfa37a7b 2004-04-10 devnull If
501 cfa37a7b 2004-04-10 devnull .I remove
502 cfa37a7b 2004-04-10 devnull is not provided, all remove requests will draw
503 cfa37a7b 2004-04-10 devnull ``remove prohibited'' errors.
504 cfa37a7b 2004-04-10 devnull .TP
505 cfa37a7b 2004-04-10 devnull .I Read
506 cfa37a7b 2004-04-10 devnull The
507 cfa37a7b 2004-04-10 devnull .I read
508 cfa37a7b 2004-04-10 devnull function must be provided; it fills
509 cfa37a7b 2004-04-10 devnull .IB r -> ofcall . data
510 cfa37a7b 2004-04-10 devnull with at most
511 cfa37a7b 2004-04-10 devnull .IB r -> ifcall . count
512 cfa37a7b 2004-04-10 devnull bytes of data from offset
513 cfa37a7b 2004-04-10 devnull .IB r -> ifcall . offset
514 cfa37a7b 2004-04-10 devnull of the file.
515 cfa37a7b 2004-04-10 devnull It also sets
516 cfa37a7b 2004-04-10 devnull .IB r -> ofcall . count
517 cfa37a7b 2004-04-10 devnull to the number of bytes being returned.
518 cfa37a7b 2004-04-10 devnull If using file trees,
519 cfa37a7b 2004-04-10 devnull .I srv
520 cfa37a7b 2004-04-10 devnull will handle reads of directories internally, only
521 cfa37a7b 2004-04-10 devnull calling
522 cfa37a7b 2004-04-10 devnull .I read
523 cfa37a7b 2004-04-10 devnull for requests on files.
524 cfa37a7b 2004-04-10 devnull .I Readstr
525 cfa37a7b 2004-04-10 devnull and
526 cfa37a7b 2004-04-10 devnull .I readbuf
527 cfa37a7b 2004-04-10 devnull are useful for satisfying read requests on a string or buffer.
528 cfa37a7b 2004-04-10 devnull Consulting the request in
529 cfa37a7b 2004-04-10 devnull .IB r -> ifcall \fR,
530 cfa37a7b 2004-04-10 devnull they fill
531 cfa37a7b 2004-04-10 devnull .IB r -> ofcall . data
532 cfa37a7b 2004-04-10 devnull and set
533 cfa37a7b 2004-04-10 devnull .IB r -> ofcall . count \fR;
534 cfa37a7b 2004-04-10 devnull they do not call
535 cfa37a7b 2004-04-10 devnull .IB respond .
536 cfa37a7b 2004-04-10 devnull Similarly,
537 cfa37a7b 2004-04-10 devnull .I dirread9p
538 cfa37a7b 2004-04-10 devnull can be used to handle directory reads in servers
539 cfa37a7b 2004-04-10 devnull not using file trees.
540 cfa37a7b 2004-04-10 devnull The passed
541 cfa37a7b 2004-04-10 devnull .I gen
542 cfa37a7b 2004-04-10 devnull function will be called as necessary to
543 cfa37a7b 2004-04-10 devnull fill
544 cfa37a7b 2004-04-10 devnull .I dir
545 cfa37a7b 2004-04-10 devnull with information for the
546 cfa37a7b 2004-04-10 devnull .IR n th
547 cfa37a7b 2004-04-10 devnull entry in the directory.
548 cfa37a7b 2004-04-10 devnull The string pointers placed in
549 cfa37a7b 2004-04-10 devnull .I dir
550 cfa37a7b 2004-04-10 devnull should be fresh copies
551 cfa37a7b 2004-04-10 devnull made with
552 cfa37a7b 2004-04-10 devnull .IR estrdup9p ;
553 cfa37a7b 2004-04-10 devnull they will be freed by
554 cfa37a7b 2004-04-10 devnull .I dirread9p
555 cfa37a7b 2004-04-10 devnull after each successful call to
556 cfa37a7b 2004-04-10 devnull .IR gen .
557 cfa37a7b 2004-04-10 devnull .I Gen
558 cfa37a7b 2004-04-10 devnull should return zero if it successfully filled
559 cfa37a7b 2004-04-10 devnull .IR dir ,
560 cfa37a7b 2004-04-10 devnull minus one on end of directory.
561 cfa37a7b 2004-04-10 devnull .TP
562 cfa37a7b 2004-04-10 devnull .I Write
563 cfa37a7b 2004-04-10 devnull The
564 cfa37a7b 2004-04-10 devnull .I write
565 cfa37a7b 2004-04-10 devnull function is similar but need not be provided.
566 cfa37a7b 2004-04-10 devnull If it is not, all writes will draw
567 cfa37a7b 2004-04-10 devnull ``write prohibited'' errors.
568 cfa37a7b 2004-04-10 devnull Otherwise,
569 cfa37a7b 2004-04-10 devnull .I write
570 cfa37a7b 2004-04-10 devnull should attempt to write the
571 cfa37a7b 2004-04-10 devnull .IB r -> ifcall . count
572 cfa37a7b 2004-04-10 devnull bytes of
573 cfa37a7b 2004-04-10 devnull .IB r -> ifcall . data
574 cfa37a7b 2004-04-10 devnull to offset
575 cfa37a7b 2004-04-10 devnull .IB r -> ifcall . offset
576 cfa37a7b 2004-04-10 devnull of the file, setting
577 cfa37a7b 2004-04-10 devnull .IB r -> ofcall . count
578 cfa37a7b 2004-04-10 devnull to the number of bytes actually written.
579 cfa37a7b 2004-04-10 devnull Most programs consider it an error to
580 cfa37a7b 2004-04-10 devnull write less than the requested amount.
581 cfa37a7b 2004-04-10 devnull .TP
582 cfa37a7b 2004-04-10 devnull .I Stat
583 cfa37a7b 2004-04-10 devnull .I Stat
584 cfa37a7b 2004-04-10 devnull should fill
585 cfa37a7b 2004-04-10 devnull .IB r -> d
586 cfa37a7b 2004-04-10 devnull with the stat information for
587 cfa37a7b 2004-04-10 devnull .IB r -> fid \fR.
588 cfa37a7b 2004-04-10 devnull If using file trees,
589 cfa37a7b 2004-04-10 devnull .IB r -> d
590 cfa37a7b 2004-04-10 devnull will have been initialized with the stat info from
591 cfa37a7b 2004-04-10 devnull the tree, and
592 cfa37a7b 2004-04-10 devnull .I stat
593 cfa37a7b 2004-04-10 devnull itself may be nil.
594 cfa37a7b 2004-04-10 devnull .TP
595 cfa37a7b 2004-04-10 devnull .I Wstat
596 cfa37a7b 2004-04-10 devnull The
597 cfa37a7b 2004-04-10 devnull .I wstat
598 cfa37a7b 2004-04-10 devnull consults
599 cfa37a7b 2004-04-10 devnull .IB r -> d
600 cfa37a7b 2004-04-10 devnull in changing the metadata for
601 cfa37a7b 2004-04-10 devnull .IB r -> fid
602 cfa37a7b 2004-04-10 devnull as described in
603 058b0118 2005-01-03 devnull .IR stat (9p).
604 cfa37a7b 2004-04-10 devnull When using file trees,
605 cfa37a7b 2004-04-10 devnull .I srv
606 cfa37a7b 2004-04-10 devnull will take care to check that the request satisfies
607 cfa37a7b 2004-04-10 devnull the permissions outlined in
608 058b0118 2005-01-03 devnull .IR stat (9p).
609 cfa37a7b 2004-04-10 devnull Otherwise
610 cfa37a7b 2004-04-10 devnull .I wstat
611 cfa37a7b 2004-04-10 devnull should take care to enforce permissions
612 cfa37a7b 2004-04-10 devnull where appropriate.
613 cfa37a7b 2004-04-10 devnull .TP
614 cfa37a7b 2004-04-10 devnull .I Flush
615 cfa37a7b 2004-04-10 devnull Single-threaded servers, which always call
616 cfa37a7b 2004-04-10 devnull .I respond
617 cfa37a7b 2004-04-10 devnull before returning from the service functions,
618 cfa37a7b 2004-04-10 devnull need not provide a
619 cfa37a7b 2004-04-10 devnull .I flush
620 cfa37a7b 2004-04-10 devnull implementation:
621 cfa37a7b 2004-04-10 devnull .I flush
622 cfa37a7b 2004-04-10 devnull is only necessary in multithreaded programs,
623 cfa37a7b 2004-04-10 devnull which arrange for
624 cfa37a7b 2004-04-10 devnull .I respond
625 cfa37a7b 2004-04-10 devnull to be called asynchronously.
626 cfa37a7b 2004-04-10 devnull .I Flush
627 cfa37a7b 2004-04-10 devnull should cause the request
628 cfa37a7b 2004-04-10 devnull .IB r -> oldreq
629 cfa37a7b 2004-04-10 devnull to be cancelled or hurried along.
630 cfa37a7b 2004-04-10 devnull If
631 cfa37a7b 2004-04-10 devnull .I oldreq
632 cfa37a7b 2004-04-10 devnull is cancelled, this should be signalled by calling
633 cfa37a7b 2004-04-10 devnull .I respond
634 cfa37a7b 2004-04-10 devnull on
635 cfa37a7b 2004-04-10 devnull .I oldreq
636 cfa37a7b 2004-04-10 devnull with error string
637 cfa37a7b 2004-04-10 devnull .RB ` interrupted '.
638 cfa37a7b 2004-04-10 devnull .I Flush
639 cfa37a7b 2004-04-10 devnull must respond to
640 cfa37a7b 2004-04-10 devnull .I r
641 cfa37a7b 2004-04-10 devnull with a nil error string.
642 cfa37a7b 2004-04-10 devnull .I Flush
643 cfa37a7b 2004-04-10 devnull may respond to
644 cfa37a7b 2004-04-10 devnull .I r
645 cfa37a7b 2004-04-10 devnull before forcing a response to
646 cfa37a7b 2004-04-10 devnull .IB r -> oldreq \fR.
647 cfa37a7b 2004-04-10 devnull In this case, the library will delay sending
648 cfa37a7b 2004-04-10 devnull the
649 cfa37a7b 2004-04-10 devnull .I Rflush
650 cfa37a7b 2004-04-10 devnull message until the response to
651 cfa37a7b 2004-04-10 devnull .IB r -> oldreq
652 cfa37a7b 2004-04-10 devnull has been sent.
653 cfa37a7b 2004-04-10 devnull .PD
654 cfa37a7b 2004-04-10 devnull .PP
655 cfa37a7b 2004-04-10 devnull .IR Destroyfid ,
656 cfa37a7b 2004-04-10 devnull .IR destroyreq ,
657 cfa37a7b 2004-04-10 devnull and
658 cfa37a7b 2004-04-10 devnull .I end
659 cfa37a7b 2004-04-10 devnull are auxiliary functions, not called in direct response to 9P requests.
660 cfa37a7b 2004-04-10 devnull .TP
661 cfa37a7b 2004-04-10 devnull .I Destroyfid
662 cfa37a7b 2004-04-10 devnull When a
663 cfa37a7b 2004-04-10 devnull .BR Fid 's
664 cfa37a7b 2004-04-10 devnull reference count drops to zero
665 cfa37a7b 2004-04-10 devnull .RI ( i.e.,
666 cfa37a7b 2004-04-10 devnull it has been clunked and there are no outstanding
667 cfa37a7b 2004-04-10 devnull requests referring to it),
668 cfa37a7b 2004-04-10 devnull .I destroyfid
669 cfa37a7b 2004-04-10 devnull is called to allow the program to dispose
670 cfa37a7b 2004-04-10 devnull of the
671 cfa37a7b 2004-04-10 devnull .IB fid -> aux
672 cfa37a7b 2004-04-10 devnull pointer.
673 cfa37a7b 2004-04-10 devnull .TP
674 cfa37a7b 2004-04-10 devnull .I Destroyreq
675 cfa37a7b 2004-04-10 devnull Similarly, when a
676 cfa37a7b 2004-04-10 devnull .BR Req 's
677 cfa37a7b 2004-04-10 devnull reference count drops to zero
678 cfa37a7b 2004-04-10 devnull .RI ( i.e. ,
679 cfa37a7b 2004-04-10 devnull it has been handled via
680 cfa37a7b 2004-04-10 devnull .I respond
681 cfa37a7b 2004-04-10 devnull and other outstanding pointers to it have been closed),
682 cfa37a7b 2004-04-10 devnull .I destroyreq
683 cfa37a7b 2004-04-10 devnull is called to allow the program to dispose of the
684 cfa37a7b 2004-04-10 devnull .IB r -> aux
685 cfa37a7b 2004-04-10 devnull pointer.
686 cfa37a7b 2004-04-10 devnull .TP
687 cfa37a7b 2004-04-10 devnull .I End
688 cfa37a7b 2004-04-10 devnull Once the 9P service loop has finished
689 cfa37a7b 2004-04-10 devnull (end of file been reached on the service pipe
690 cfa37a7b 2004-04-10 devnull or a bad message has been read),
691 cfa37a7b 2004-04-10 devnull .I end
692 cfa37a7b 2004-04-10 devnull is called (if provided) to allow any final cleanup.
693 cfa37a7b 2004-04-10 devnull For example, it was used by the Palm Pilot synchronization
694 cfa37a7b 2004-04-10 devnull file system (never finished) to gracefully terminate the serial conversation once
695 cfa37a7b 2004-04-10 devnull the file system had been unmounted.
696 cfa37a7b 2004-04-10 devnull After calling
697 cfa37a7b 2004-04-10 devnull .IR end ,
698 cfa37a7b 2004-04-10 devnull the service loop (which runs in a separate process
699 cfa37a7b 2004-04-10 devnull from its caller) terminates using
700 cfa37a7b 2004-04-10 devnull .I _exits
701 cfa37a7b 2004-04-10 devnull (see
702 bf8a59fa 2004-04-11 devnull .IR exits (3)).
703 cfa37a7b 2004-04-10 devnull .PD
704 cfa37a7b 2004-04-10 devnull .PP
705 cfa37a7b 2004-04-10 devnull If the
706 cfa37a7b 2004-04-10 devnull .B chatty9p
707 cfa37a7b 2004-04-10 devnull flag is at least one,
708 cfa37a7b 2004-04-10 devnull a transcript of the 9P session is printed
709 cfa37a7b 2004-04-10 devnull on standard error.
710 cfa37a7b 2004-04-10 devnull If the
711 cfa37a7b 2004-04-10 devnull .B chatty9p
712 cfa37a7b 2004-04-10 devnull flag is greater than one,
713 cfa37a7b 2004-04-10 devnull additional unspecified debugging output is generated.
714 cfa37a7b 2004-04-10 devnull By convention, servers written using this library
715 cfa37a7b 2004-04-10 devnull accept the
716 cfa37a7b 2004-04-10 devnull .B -D
717 cfa37a7b 2004-04-10 devnull option to increment
718 cfa37a7b 2004-04-10 devnull .BR chatty9p .
719 cfa37a7b 2004-04-10 devnull .SH EXAMPLES
720 058b0118 2005-01-03 devnull /usr/local/plan9/src/lib9p/ramfs.c
721 058b0118 2005-01-03 devnull is an example of simple single-threaded file servers.
722 058b0118 2005-01-03 devnull On Plan 9, see
723 058b0118 2005-01-03 devnull .IR archfs ,
724 058b0118 2005-01-03 devnull .IR cdfs ,
725 058b0118 2005-01-03 devnull .IR nntpfs ,
726 058b0118 2005-01-03 devnull .IR webfs ,
727 cfa37a7b 2004-04-10 devnull and
728 cfa37a7b 2004-04-10 devnull .I sshnet
729 058b0118 2005-01-03 devnull for more examples.
730 cfa37a7b 2004-04-10 devnull .PP
731 cfa37a7b 2004-04-10 devnull In general, the
732 cfa37a7b 2004-04-10 devnull .B File
733 cfa37a7b 2004-04-10 devnull interface is appropriate for maintaining arbitrary file trees (as in
734 cfa37a7b 2004-04-10 devnull .IR ramfs ).
735 cfa37a7b 2004-04-10 devnull The
736 cfa37a7b 2004-04-10 devnull .B File
737 cfa37a7b 2004-04-10 devnull interface is best avoided when the
738 cfa37a7b 2004-04-10 devnull tree structure is easily generated as necessary;
739 cfa37a7b 2004-04-10 devnull this is true when the tree is highly structured (as in
740 cfa37a7b 2004-04-10 devnull .I cdfs
741 cfa37a7b 2004-04-10 devnull and
742 cfa37a7b 2004-04-10 devnull .IR nntpfs )
743 cfa37a7b 2004-04-10 devnull or is maintained elsewhere.
744 cfa37a7b 2004-04-10 devnull .SH SOURCE
745 b5fdffee 2004-04-19 devnull .B /usr/local/plan9/src/lib9p
746 cfa37a7b 2004-04-10 devnull .SH SEE ALSO
747 bf8a59fa 2004-04-11 devnull .IR 9pfid (3),
748 bf8a59fa 2004-04-11 devnull .IR 9pfile (3),
749 058b0118 2005-01-03 devnull .IR intro (9p)