2 |
- |
1 |
.HTML "Changes to the Programming Environment in the Fourth Release of Plan 9
|
|
|
2 |
.FP lucidasans
|
|
|
3 |
.TL
|
|
|
4 |
Changes to the Programming Environment
|
|
|
5 |
.br
|
|
|
6 |
in the
|
|
|
7 |
.br
|
|
|
8 |
Fourth Release of Plan 9
|
|
|
9 |
.AU
|
|
|
10 |
Rob Pike
|
|
|
11 |
.sp
|
|
|
12 |
rob@plan9.bell-labs.com
|
|
|
13 |
.SH
|
|
|
14 |
Introduction
|
|
|
15 |
.PP
|
|
|
16 |
The fourth release of Plan 9 includes changes at many levels of the system,
|
|
|
17 |
with repercussions in the libraries and program interfaces.
|
|
|
18 |
This document summarizes the changes and describes how
|
|
|
19 |
existing programs must be modified to run in the new release.
|
|
|
20 |
It is not exhaustive, of course; for further detail about any of the
|
|
|
21 |
topics refer to the manual pages, as always.
|
|
|
22 |
.PP
|
|
|
23 |
Programmers new to Plan 9 may find valuable tidbits here, but the
|
|
|
24 |
real audience for this paper is those with a need to update applications
|
|
|
25 |
and servers written in C for earlier releases of the Plan 9 operating system.
|
|
|
26 |
.SH
|
|
|
27 |
9P, NAMELEN, and strings
|
|
|
28 |
.PP
|
|
|
29 |
The underlying file service protocol for Plan 9, 9P, retains its basic form
|
|
|
30 |
but has had a number of adjustments to deal with longer file names and error strings,
|
|
|
31 |
new authentication mechanisms, and to make it more efficient at
|
|
|
32 |
evaluating file names.
|
|
|
33 |
The change to file names affects a number of system interfaces;
|
|
|
34 |
because file name elements are no longer of fixed size, they can
|
|
|
35 |
no longer be stored as arrays.
|
|
|
36 |
.PP
|
|
|
37 |
9P used to be a fixed-format protocol with
|
|
|
38 |
.CW NAMELEN -sized
|
|
|
39 |
byte arrays representing file name elements.
|
|
|
40 |
Now, it is a variable-format protocol, as described in
|
|
|
41 |
.I intro (5),
|
|
|
42 |
in which strings are represented by a count followed by that many bytes.
|
|
|
43 |
Thus, the string
|
|
|
44 |
.CW ken
|
|
|
45 |
would previously have occupied 28
|
|
|
46 |
.CW NAMELEN ) (
|
|
|
47 |
bytes in the message; now it occupies 5: a two-byte count followed by the three bytes of
|
|
|
48 |
.CW ken
|
|
|
49 |
and no terminal zero.
|
|
|
50 |
(And of course, a name could now be much longer.)
|
|
|
51 |
A similar format change has been made to
|
|
|
52 |
.CW stat
|
|
|
53 |
buffers: they are no longer
|
|
|
54 |
.CW DIRLEN
|
|
|
55 |
bytes long but instead have variable size prefixed by a two-byte count.
|
|
|
56 |
And in fact the entire 9P message syntax has changed: every message
|
|
|
57 |
now begins with a message length field that makes it trivial to break the
|
|
|
58 |
string into messages without parsing them, so
|
|
|
59 |
.CW aux/fcall
|
|
|
60 |
is gone.
|
|
|
61 |
A new library entry point,
|
|
|
62 |
.CW read9pmsg ,
|
|
|
63 |
makes it easy for user-level servers to break the client data stream into 9P messages.
|
|
|
64 |
All servers should switch from using
|
|
|
65 |
.CW read
|
|
|
66 |
(or the now gone
|
|
|
67 |
.CW getS)
|
|
|
68 |
to using
|
|
|
69 |
.CW read9pmsg .
|
|
|
70 |
.PP
|
|
|
71 |
This change to 9P affects the way strings are handled by the kernel and throughout
|
|
|
72 |
the system.
|
|
|
73 |
The consequences are primarily that fixed-size arrays have been replaced
|
|
|
74 |
by pointers and counts in a variety of system interfaces.
|
|
|
75 |
Most programs will need at least some adjustment to the new style.
|
|
|
76 |
In summary:
|
|
|
77 |
.CW NAMELEN
|
|
|
78 |
is gone, except as a vestige in the authentication libraries, where it has been
|
|
|
79 |
rechristened
|
|
|
80 |
.CW ANAMELEN .
|
|
|
81 |
.CW DIRLEN
|
|
|
82 |
and
|
|
|
83 |
.CW ERRLEN
|
|
|
84 |
are also gone.
|
|
|
85 |
All programs that mention
|
|
|
86 |
these constants
|
|
|
87 |
will need to be fixed.
|
|
|
88 |
.PP
|
|
|
89 |
The simplest place to see this change is in the
|
|
|
90 |
.CW errstr
|
|
|
91 |
system call, which no longer assumes a buffer of length
|
|
|
92 |
.CW ERRLEN
|
|
|
93 |
but now requires a byte-count argument:
|
|
|
94 |
.P1
|
|
|
95 |
char buf[...];
|
|
|
96 |
|
|
|
97 |
errstr(buf, sizeof buf);
|
|
|
98 |
.P2
|
|
|
99 |
The buffer can be any size you like.
|
|
|
100 |
For convenience, the kernel stores error strings internally as 256-byte arrays,
|
|
|
101 |
so if you like \(em but it's not required \(em you can use the defined constant
|
|
|
102 |
.CW ERRMAX= 256
|
|
|
103 |
as a good buffer size.
|
|
|
104 |
Unlike the old
|
|
|
105 |
.CW ERRLEN
|
|
|
106 |
(which had value 64),
|
|
|
107 |
.CW ERRMAX
|
|
|
108 |
is advisory, not mandatory, and is not part of the 9P specification.
|
|
|
109 |
.PP
|
|
|
110 |
With names, stat buffers, and directories, there isn't even an echo of a fixed-size array any more.
|
|
|
111 |
.SH
|
|
|
112 |
Directories and wait messages
|
|
|
113 |
.PP
|
|
|
114 |
With strings now variable-length, a number of system calls needed to change:
|
|
|
115 |
.CW errstr ,
|
|
|
116 |
.CW stat ,
|
|
|
117 |
.CW fstat ,
|
|
|
118 |
.CW wstat ,
|
|
|
119 |
.CW fwstat ,
|
|
|
120 |
and
|
|
|
121 |
.CW wait
|
|
|
122 |
are all affected, as is
|
|
|
123 |
.CW read
|
|
|
124 |
when applied to directories.
|
|
|
125 |
.PP
|
|
|
126 |
As far as directories are concerned, most programs don't use the system calls
|
|
|
127 |
directly anyway, since they operate on the machine-independent form, but
|
|
|
128 |
instead call the machine-dependent
|
|
|
129 |
.CW Dir
|
|
|
130 |
routines
|
|
|
131 |
.CW dirstat ,
|
|
|
132 |
.CW dirread ,
|
|
|
133 |
etc.
|
|
|
134 |
These used to fill user-provided fixed-size buffers; now they return objects allocated
|
|
|
135 |
by
|
|
|
136 |
.CW malloc
|
|
|
137 |
(which must therefore be freed after use).
|
|
|
138 |
To `stat' a file:
|
|
|
139 |
.P1
|
|
|
140 |
Dir *d;
|
|
|
141 |
|
|
|
142 |
d = dirstat(filename);
|
|
|
143 |
if(d == nil){
|
|
|
144 |
fprint(2, "can't stat %s: %r\en", filename);
|
|
|
145 |
exits("stat");
|
|
|
146 |
}
|
|
|
147 |
use(d);
|
|
|
148 |
free(d);
|
|
|
149 |
.P2
|
|
|
150 |
A common new bug is to forget to free a
|
|
|
151 |
.CW Dir
|
|
|
152 |
returned by
|
|
|
153 |
.CW dirstat .
|
|
|
154 |
.PP
|
|
|
155 |
.CW Dirfstat
|
|
|
156 |
and
|
|
|
157 |
.CW Dirfwstat
|
|
|
158 |
work pretty much as before, but changes to 9P make
|
|
|
159 |
it possible to exercise finer-grained control on what fields
|
|
|
160 |
of the
|
|
|
161 |
.CW Dir
|
|
|
162 |
are to be changed; see
|
|
|
163 |
.I stat (2)
|
|
|
164 |
and
|
|
|
165 |
.I stat (5)
|
|
|
166 |
for details.
|
|
|
167 |
.PP
|
|
|
168 |
Reading a directory works in a similar way to
|
|
|
169 |
.CW dirstat ,
|
|
|
170 |
with
|
|
|
171 |
.CW dirread
|
|
|
172 |
allocating and filling in an array of
|
|
|
173 |
.CW Dir
|
|
|
174 |
structures.
|
|
|
175 |
The return value is the number of elements of the array.
|
|
|
176 |
The arguments to
|
|
|
177 |
.CW dirread
|
|
|
178 |
now include a pointer to a
|
|
|
179 |
.CW Dir*
|
|
|
180 |
to be filled in with the address of the allocated array:
|
|
|
181 |
.P1
|
|
|
182 |
Dir *d;
|
|
|
183 |
int i, n;
|
|
|
184 |
|
|
|
185 |
while((n = dirread(fd, &d)) > 0){
|
|
|
186 |
for(i=0; i<n; i++)
|
|
|
187 |
use(&d[i]);
|
|
|
188 |
free(d);
|
|
|
189 |
}
|
|
|
190 |
.P2
|
|
|
191 |
A new library function,
|
|
|
192 |
.CW dirreadall ,
|
|
|
193 |
has the same form as
|
|
|
194 |
.CW dirread
|
|
|
195 |
but returns the entire directory in one call:
|
|
|
196 |
.P1
|
|
|
197 |
n = dirreadall(fd, &d)
|
|
|
198 |
for(i=0; i<n; i++)
|
|
|
199 |
use(&d[i]);
|
|
|
200 |
free(d);
|
|
|
201 |
.P2
|
|
|
202 |
If your program insists on using the underlying
|
|
|
203 |
.CW stat
|
|
|
204 |
system call or its relatives, or wants to operate directly on the
|
|
|
205 |
machine-independent format returned by
|
|
|
206 |
.CW stat
|
|
|
207 |
or
|
|
|
208 |
.CW read ,
|
|
|
209 |
it will need to be modified.
|
|
|
210 |
Such programs are rare enough that we'll not discuss them here beyond referring to
|
|
|
211 |
the man page
|
|
|
212 |
.I stat (2)
|
|
|
213 |
for details.
|
|
|
214 |
Be aware, though, that it used to be possible to regard the buffer returned by
|
|
|
215 |
.CW stat
|
|
|
216 |
as a byte array that began with the zero-terminated
|
|
|
217 |
name of the file; this is no longer true.
|
|
|
218 |
With very rare exceptions, programs that call
|
|
|
219 |
.CW stat
|
|
|
220 |
would be better recast to use the
|
|
|
221 |
.CW dir
|
|
|
222 |
routines or, if their goal is just to test the existence of a file,
|
|
|
223 |
.CW access .
|
|
|
224 |
.PP
|
|
|
225 |
Similar changes have affected the
|
|
|
226 |
.CW wait
|
|
|
227 |
system call. In fact,
|
|
|
228 |
.CW wait
|
|
|
229 |
is no longer a system call but a library routine that calls the new
|
|
|
230 |
.CW await
|
|
|
231 |
system call and returns a newly allocated machine-dependent
|
|
|
232 |
.CW Waitmsg
|
|
|
233 |
structure:
|
|
|
234 |
.P1
|
|
|
235 |
Waitmsg *w;
|
|
|
236 |
|
|
|
237 |
w = wait();
|
|
|
238 |
if(w == nil)
|
|
|
239 |
error("wait: %r");
|
|
|
240 |
print("pid is %d; exit string %s\en", w->pid, w->msg);
|
|
|
241 |
free(w);
|
|
|
242 |
.P2
|
|
|
243 |
The exit string
|
|
|
244 |
.CW w->msg
|
|
|
245 |
may be empty but it will never be a nil pointer.
|
|
|
246 |
Again, don't forget to free the structure returned by
|
|
|
247 |
.CW wait .
|
|
|
248 |
If all you need is the pid, you can call
|
|
|
249 |
.CW waitpid ,
|
|
|
250 |
which reports just the pid and doesn't return an allocated structure:
|
|
|
251 |
.P1
|
|
|
252 |
int pid;
|
|
|
253 |
|
|
|
254 |
pid = waitpid();
|
|
|
255 |
if(pid < 0)
|
|
|
256 |
error("wait: %r");
|
|
|
257 |
print("pid is %d\en", pid);
|
|
|
258 |
.P2
|
|
|
259 |
.SH
|
|
|
260 |
Quoted strings and tokenize
|
|
|
261 |
.PP
|
|
|
262 |
.CW Wait
|
|
|
263 |
gives us a good opportunity to describe how the system copes with all this
|
|
|
264 |
free-format data.
|
|
|
265 |
Consider the text returned by the
|
|
|
266 |
.CW await
|
|
|
267 |
system call, which includes a set of integers (pids and times) and a string (the exit status).
|
|
|
268 |
This information is formatted free-form; here is the statement in the kernel that
|
|
|
269 |
generates the message:
|
|
|
270 |
.P1
|
|
|
271 |
n = snprint(a, n, "%d %lud %lud %lud %q",
|
|
|
272 |
wq->w.pid,
|
|
|
273 |
wq->w.time[TUser], wq->w.time[TSys], wq->w.time[TReal],
|
|
|
274 |
wq->w.msg);
|
|
|
275 |
.P2
|
|
|
276 |
Note the use of
|
|
|
277 |
.CW %q
|
|
|
278 |
to produce a quoted-string representation of the exit status.
|
|
|
279 |
The
|
|
|
280 |
.CW %q
|
|
|
281 |
format is like %s but will wrap
|
|
|
282 |
.CW rc -style
|
|
|
283 |
single quotes around the string if it contains white space or is otherwise ambiguous.
|
|
|
284 |
The library routine
|
|
|
285 |
.CW tokenize
|
|
|
286 |
can be used to parse data formatted this way: it splits white-space-separated
|
|
|
287 |
fields but understands the
|
|
|
288 |
.CW %q
|
|
|
289 |
quoting conventions.
|
|
|
290 |
Here is how the
|
|
|
291 |
.CW wait
|
|
|
292 |
library routine builds its
|
|
|
293 |
.CW Waitmsg
|
|
|
294 |
from the data returned by
|
|
|
295 |
.CW await :
|
|
|
296 |
.P1
|
|
|
297 |
Waitmsg*
|
|
|
298 |
wait(void)
|
|
|
299 |
{
|
|
|
300 |
int n, l;
|
|
|
301 |
char buf[512], *fld[5];
|
|
|
302 |
Waitmsg *w;
|
|
|
303 |
|
|
|
304 |
n = await(buf, sizeof buf-1);
|
|
|
305 |
if(n < 0)
|
|
|
306 |
return nil;
|
|
|
307 |
buf[n] = '\0';
|
|
|
308 |
if(tokenize(buf, fld, nelem(fld)) != nelem(fld)){
|
|
|
309 |
werrstr("couldn't parse wait message");
|
|
|
310 |
return nil;
|
|
|
311 |
}
|
|
|
312 |
l = strlen(fld[4])+1;
|
|
|
313 |
w = malloc(sizeof(Waitmsg)+l);
|
|
|
314 |
if(w == nil)
|
|
|
315 |
return nil;
|
|
|
316 |
w->pid = atoi(fld[0]);
|
|
|
317 |
w->time[0] = atoi(fld[1]);
|
|
|
318 |
w->time[1] = atoi(fld[2]);
|
|
|
319 |
w->time[2] = atoi(fld[3]);
|
|
|
320 |
w->msg = (char*)&w[1];
|
|
|
321 |
memmove(w->msg, fld[4], l);
|
|
|
322 |
return w;
|
|
|
323 |
}
|
|
|
324 |
.P2
|
|
|
325 |
.PP
|
|
|
326 |
This style of quoted-string and
|
|
|
327 |
.CW tokenize
|
|
|
328 |
is used all through the system now.
|
|
|
329 |
In particular, devices now
|
|
|
330 |
.CW tokenize
|
|
|
331 |
the messages written to their
|
|
|
332 |
.CW ctl
|
|
|
333 |
files, which means that you can send messages that contain white space, by quoting them,
|
|
|
334 |
and that you no longer need to worry about whether or not the device accepts a newline.
|
|
|
335 |
In other words, you can say
|
|
|
336 |
.P1
|
|
|
337 |
echo message > /dev/xx/ctl
|
|
|
338 |
.P2
|
|
|
339 |
instead of
|
|
|
340 |
.CW echo
|
|
|
341 |
.CW -n
|
|
|
342 |
because
|
|
|
343 |
.CW tokenize
|
|
|
344 |
treats the newline character as white space and discards it.
|
|
|
345 |
.PP
|
|
|
346 |
While we're on the subject of quotes and strings, note that the implementation of
|
|
|
347 |
.CW await
|
|
|
348 |
used
|
|
|
349 |
.CW snprint
|
|
|
350 |
rather than
|
|
|
351 |
.CW sprint .
|
|
|
352 |
We now deprecate
|
|
|
353 |
.CW sprint
|
|
|
354 |
because it has no protection against buffer overflow.
|
|
|
355 |
We prefer
|
|
|
356 |
.CW snprint
|
|
|
357 |
or
|
|
|
358 |
.CW seprint ,
|
|
|
359 |
to constrain the output.
|
|
|
360 |
The
|
|
|
361 |
.CW %q
|
|
|
362 |
format is cleverer than most in this regard:
|
|
|
363 |
if the string is too long to be represented in full,
|
|
|
364 |
.CW %q
|
|
|
365 |
is smart enough to produce a truncated but correctly quoted
|
|
|
366 |
string within the available space.
|
|
|
367 |
.SH
|
|
|
368 |
Mount
|
|
|
369 |
.PP
|
|
|
370 |
Although strings in 9P are now variable-length and not zero-terminated,
|
|
|
371 |
this has little direct effect in most of the system interfaces.
|
|
|
372 |
File and user names are still zero-terminated strings as always;
|
|
|
373 |
the kernel does the work of translating them as necessary for
|
|
|
374 |
transport.
|
|
|
375 |
And of course, they are now free to be as long as you might want;
|
|
|
376 |
the only hard limit is that their length must be represented in 16 bits.
|
|
|
377 |
.PP
|
|
|
378 |
One example where this matters is that the file system specification in the
|
|
|
379 |
.CW mount
|
|
|
380 |
system call can now be much longer.
|
|
|
381 |
Programs like
|
|
|
382 |
.CW rio
|
|
|
383 |
that used the specification string in creative ways were limited by the
|
|
|
384 |
.CW NAMELEN
|
|
|
385 |
restriction; now they can use the string more freely.
|
|
|
386 |
.CW Rio
|
|
|
387 |
now accepts a simple but less cryptic specification language for the window
|
|
|
388 |
to be created by the
|
|
|
389 |
.CW mount
|
|
|
390 |
call, e.g.:
|
|
|
391 |
.P1
|
|
|
392 |
% mount $wsys /mnt/wsys 'new -dx 250 -dy 250 -pid 1234'
|
|
|
393 |
.P2
|
|
|
394 |
In the old system, this sort of control was impossible through the
|
|
|
395 |
.CW mount
|
|
|
396 |
interface.
|
|
|
397 |
.PP
|
|
|
398 |
While we're on the subject of
|
|
|
399 |
.CW mount ,
|
|
|
400 |
note that with the new security architecture
|
|
|
401 |
(see
|
|
|
402 |
.I factotum (4)),
|
|
|
403 |
9P has moved its authentication outside the protocol proper.
|
|
|
404 |
(For a full description of this change to 9P, see
|
|
|
405 |
.I fauth (2),
|
|
|
406 |
.I attach (5),
|
|
|
407 |
and the paper
|
|
|
408 |
.I "Security in Plan 9\f1.)
|
|
|
409 |
The most explicit effect of this change is that
|
|
|
410 |
.CW mount
|
|
|
411 |
now takes another argument,
|
|
|
412 |
.CW afd ,
|
|
|
413 |
a file descriptor for the
|
|
|
414 |
authentication file through which the authentication will be made.
|
|
|
415 |
For most user-level file servers, which do not require authentication, it is
|
|
|
416 |
sufficient to provide
|
|
|
417 |
.CW -1
|
|
|
418 |
as the value of
|
|
|
419 |
.CW afd:
|
|
|
420 |
.P1
|
|
|
421 |
if(mount(fd, -1, "/mnt/wsys", MREPL,
|
|
|
422 |
"new -dx 250 -dy 250 -pid 1234") < 0)
|
|
|
423 |
error("mount failed: %r");
|
|
|
424 |
.P2
|
|
|
425 |
To connect to servers that require authentication, use the new
|
|
|
426 |
.CW fauth
|
|
|
427 |
system call or the reimplemented
|
|
|
428 |
.CW amount
|
|
|
429 |
(authenticated mount) library call.
|
|
|
430 |
In fact, since
|
|
|
431 |
.CW amount
|
|
|
432 |
handles both authenticating and non-authenticating servers, it is often
|
|
|
433 |
easiest just to replace calls to
|
|
|
434 |
.CW mount
|
|
|
435 |
by calls to
|
|
|
436 |
.CW amount ;
|
|
|
437 |
see
|
|
|
438 |
.I auth (2)
|
|
|
439 |
for details.
|
|
|
440 |
.SH
|
|
|
441 |
Print
|
|
|
442 |
.PP
|
|
|
443 |
The C library has been heavily reworked in places.
|
|
|
444 |
Besides the changes mentioned above, it
|
|
|
445 |
now has a much more complete set of routines for handling
|
|
|
446 |
.CW Rune
|
|
|
447 |
strings (that is, zero-terminated arrays of 16-bit character values).
|
|
|
448 |
The most sweeping changes, however, are in the way formatted I/O is performed.
|
|
|
449 |
.PP
|
|
|
450 |
The
|
|
|
451 |
.CW print
|
|
|
452 |
routine and all its relatives have been reimplemented to offer a number
|
|
|
453 |
of improvements:
|
|
|
454 |
.IP (1)
|
|
|
455 |
Better buffer management, including the provision of an internal flush
|
|
|
456 |
routine, makes it unnecessary to provide large buffers.
|
|
|
457 |
For example,
|
|
|
458 |
.CW print
|
|
|
459 |
uses a much smaller buffer now (reducing stack load) while simultaneously
|
|
|
460 |
removing the need to truncate the output string if it doesn't fit in the buffer.
|
|
|
461 |
.IP (2)
|
|
|
462 |
Global variables have been eliminated so no locking is necessary.
|
|
|
463 |
.IP (3)
|
|
|
464 |
The combination of (1) and (2) means that the standard implementation of
|
|
|
465 |
.CW print
|
|
|
466 |
now works fine in threaded programs, and
|
|
|
467 |
.CW threadprint
|
|
|
468 |
is gone.
|
|
|
469 |
.IP (4)
|
|
|
470 |
The new routine
|
|
|
471 |
.CW smprint
|
|
|
472 |
prints into, and returns, storage allocated on demand by
|
|
|
473 |
.CW malloc .
|
|
|
474 |
.IP (5)
|
|
|
475 |
It is now possible to print into a
|
|
|
476 |
.CW Rune
|
|
|
477 |
string; for instance,
|
|
|
478 |
.CW runesmprint
|
|
|
479 |
is the
|
|
|
480 |
.CW Rune
|
|
|
481 |
analog of
|
|
|
482 |
.CW smprint .
|
|
|
483 |
.IP (6)
|
|
|
484 |
There is improved support for custom
|
|
|
485 |
print verbs and custom output routines such as error handlers.
|
|
|
486 |
The routine
|
|
|
487 |
.CW doprint
|
|
|
488 |
is gone, but
|
|
|
489 |
.CW vseprint
|
|
|
490 |
can always be used instead.
|
|
|
491 |
However, the new routines
|
|
|
492 |
.CW fmtfdinit ,
|
|
|
493 |
.CW fmtstrinit ,
|
|
|
494 |
.CW fmtprint ,
|
|
|
495 |
and friends
|
|
|
496 |
are often a better replacement.
|
|
|
497 |
The details are too long for exposition here;
|
|
|
498 |
.I fmtinstall (2)
|
|
|
499 |
explains the new interface and provides examples.
|
|
|
500 |
.IP (7)
|
|
|
501 |
Two new format flags, space and comma, close somewhat the gap between
|
|
|
502 |
Plan 9 and ANSI C.
|
|
|
503 |
.PP
|
|
|
504 |
Despite these changes, most programs will be unaffected;
|
|
|
505 |
.CW print
|
|
|
506 |
is still
|
|
|
507 |
.CW print .
|
|
|
508 |
Don't forget, though, that
|
|
|
509 |
you should eliminate calls to
|
|
|
510 |
.CW sprint
|
|
|
511 |
and use the
|
|
|
512 |
.CW %q
|
|
|
513 |
format when appropriate.
|
|
|
514 |
.SH
|
|
|
515 |
Binary compatibility
|
|
|
516 |
.PP
|
|
|
517 |
The discussion so far has been about changes at the source level.
|
|
|
518 |
Existing binaries will probably run without change in the new
|
|
|
519 |
environment, since the kernel provides backward-compatible
|
|
|
520 |
system calls for
|
|
|
521 |
.CW errstr ,
|
|
|
522 |
.CW stat ,
|
|
|
523 |
.CW wait ,
|
|
|
524 |
etc.
|
|
|
525 |
The only exceptions are programs that do either a
|
|
|
526 |
.CW mount
|
|
|
527 |
system call, because of the security changes and because
|
|
|
528 |
the file descriptor in
|
|
|
529 |
.CW mount
|
|
|
530 |
must point to a new 9P connection; or a
|
|
|
531 |
.CW read
|
|
|
532 |
system call on a directory, since the returned data will
|
|
|
533 |
be in the new format.
|
|
|
534 |
A moment's reflection will discover that this means old
|
|
|
535 |
user-level file servers will need to be fixed to run on the new system.
|
|
|
536 |
.SH
|
|
|
537 |
File servers
|
|
|
538 |
.PP
|
|
|
539 |
A full description of what user-level servers must do to provide service with
|
|
|
540 |
the new 9P is beyond the scope of this paper.
|
|
|
541 |
Your best source of information is section 5 of the manual,
|
|
|
542 |
combined with study of a few examples.
|
|
|
543 |
.CW /sys/src/cmd/ramfs.c
|
|
|
544 |
is a simple example; it has a counterpart
|
|
|
545 |
.CW /sys/src/lib9p/ramfs.c
|
|
|
546 |
that implements the same service using the new
|
|
|
547 |
.I 9p (2)
|
|
|
548 |
library.
|
|
|
549 |
.PP
|
|
|
550 |
That said, it's worth summarizing what to watch for when converting a file server.
|
|
|
551 |
The
|
|
|
552 |
.CW session
|
|
|
553 |
message is gone, and there is a now a
|
|
|
554 |
.CW version
|
|
|
555 |
message that is exchanged at the start of a connection to establish
|
|
|
556 |
the version of the protocol to use (there's only one at the moment, identified by
|
|
|
557 |
the string
|
|
|
558 |
.CW 9P2000 )
|
|
|
559 |
and what the maximum message size will be.
|
|
|
560 |
This negotiation makes it easier to handle 9P encapsulation, such as with
|
|
|
561 |
.CW exportfs ,
|
|
|
562 |
and also permits larger message sizes when appropriate.
|
|
|
563 |
.PP
|
|
|
564 |
If your server wants to authenticate, it will need to implement an authentication file
|
|
|
565 |
and implement the
|
|
|
566 |
.CW auth
|
|
|
567 |
message; otherwise it should return a helpful error string to the
|
|
|
568 |
.CW Tauth
|
|
|
569 |
request to signal that authentication is not required.
|
|
|
570 |
.PP
|
|
|
571 |
The handling of
|
|
|
572 |
.CW stat
|
|
|
573 |
and directory reads will require some changes but they should not be fundamental.
|
|
|
574 |
Be aware that seeking on directories is forbidden, so it is fine if you disregard the
|
|
|
575 |
file offset when implementing directory reads; this makes it a little easier to handle
|
|
|
576 |
the variable-length entries.
|
|
|
577 |
You should still never return a partial directory entry; if the I/O count is too small
|
|
|
578 |
to return even one entry, you should return two bytes containing the byte count
|
|
|
579 |
required to represent the next entry in the directory.
|
|
|
580 |
User code can use this value to formulate a retry if it desires.
|
|
|
581 |
See the
|
|
|
582 |
DIAGNOSTICS section of
|
|
|
583 |
.I stat (2)
|
|
|
584 |
for a description of this process.
|
|
|
585 |
.PP
|
|
|
586 |
The trickiest part of updating a file server is that the
|
|
|
587 |
.CW clone
|
|
|
588 |
and
|
|
|
589 |
.CW walk
|
|
|
590 |
messages have been merged into a single message, a sort of `clone-multiwalk'.
|
|
|
591 |
The new message, still called
|
|
|
592 |
.CW walk ,
|
|
|
593 |
proposes a sequence of file name elements to be evaluated using a possibly
|
|
|
594 |
cloned fid.
|
|
|
595 |
The return message contains the qids of the files reached by
|
|
|
596 |
walking to the sequential elements.
|
|
|
597 |
If all the elements can be walked, the fid will be cloned if requested.
|
|
|
598 |
If a non-zero number of elements are requested, but none
|
|
|
599 |
can be walked, an error should be returned.
|
|
|
600 |
If only some can be walked, the fid is not cloned, the original fid is left
|
|
|
601 |
where it was, and the returned
|
|
|
602 |
.CW Rwalk
|
|
|
603 |
message should contain the partial list of successfully reached qids.
|
|
|
604 |
See
|
|
|
605 |
.I walk (5)
|
|
|
606 |
for a full description.
|