435 lines
26 KiB
HTML
435 lines
26 KiB
HTML
|
|
<head>
|
||
|
|
<title>9p(3) - Plan 9 from User Space</title>
|
||
|
|
<meta content="text/html; charset=utf-8" http-equiv=Content-Type>
|
||
|
|
</head>
|
||
|
|
<body bgcolor=#ffffff>
|
||
|
|
<table border=0 cellpadding=0 cellspacing=0 width=100%>
|
||
|
|
<tr height=10><td>
|
||
|
|
<tr><td width=20><td>
|
||
|
|
<tr><td width=20><td><b>9P(3)</b><td align=right><b>9P(3)</b>
|
||
|
|
<tr><td width=20><td colspan=2>
|
||
|
|
<br>
|
||
|
|
<p><font size=+1><b>NAME </b></font><br>
|
||
|
|
|
||
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>
|
||
|
|
|
||
|
|
Srv, dirread9p, emalloc9p, erealloc9p, estrdup9p, postfd, postmountsrv,
|
||
|
|
readbuf, readstr, respond, srv, threadpostmountsrv, walkandclone
|
||
|
|
– 9P file service<br>
|
||
|
|
|
||
|
|
</table>
|
||
|
|
<p><font size=+1><b>SYNOPSIS </b></font><br>
|
||
|
|
|
||
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>
|
||
|
|
|
||
|
|
<tt><font size=+1>#include <u.h><br>
|
||
|
|
#include <libc.h><br>
|
||
|
|
#include <fcall.h><br>
|
||
|
|
#include <thread.h><br>
|
||
|
|
#include <9p.h><br>
|
||
|
|
|
||
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
|
||
|
|
|
||
|
|
typedef struct Srv {<br>
|
||
|
|
|
||
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>
|
||
|
|
|
||
|
|
Tree* tree;<br>
|
||
|
|
void (*attach)(Req *r);<br>
|
||
|
|
void (*auth)(Req *r);<br>
|
||
|
|
void (*open)(Req *r);<br>
|
||
|
|
void (*create)(Req *r);<br>
|
||
|
|
void (*read)(Req *r);<br>
|
||
|
|
void (*write)(Req *r);<br>
|
||
|
|
void (*remove)(Req *r);<br>
|
||
|
|
void (*flush)(Req *r);<br>
|
||
|
|
void (*stat)(Req *r);<br>
|
||
|
|
void (*wstat)(Req *r);<br>
|
||
|
|
void (*walk)(Req *r);<br>
|
||
|
|
char* (*walk1)(Fid *fid, char *name, Qid *qid);<br>
|
||
|
|
char* (*clone)(Fid *oldfid, Fid *newfid);<br>
|
||
|
|
void (*destroyfid)(Fid *fid);<br>
|
||
|
|
void (*destroyreq)(Req *r);<br>
|
||
|
|
void (*end)(Srv *s);<br>
|
||
|
|
void* aux;<br>
|
||
|
|
int infd;<br>
|
||
|
|
int outfd;<br>
|
||
|
|
int srvfd;<br>
|
||
|
|
int nopipe;<br>
|
||
|
|
|
||
|
|
</table>
|
||
|
|
} Srv;<br>
|
||
|
|
|
||
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
|
||
|
|
|
||
|
|
int srv(Srv *s)<br>
|
||
|
|
void postmountsrv(Srv *s, char *name, char *mtpt, int flag)<br>
|
||
|
|
void threadpostmountsrv(Srv *s, char *name, char *mtpt, int flag)<br>
|
||
|
|
int postfd(char *srvname, int fd)<br>
|
||
|
|
void respond(Req *r, char *error)<br>
|
||
|
|
ulong readstr(Req *r, char *src)<br>
|
||
|
|
ulong readbuf(Req *r, void *src, ulong nsrc)<br>
|
||
|
|
typedef int Dirgen(int n, Dir *dir, void *aux)<br>
|
||
|
|
void dirread9p(Req *r, Dirgen *gen, void *aux)<br>
|
||
|
|
void walkandclone(Req *r, char *(*walk1)(Fid *old, char *name,
|
||
|
|
void *v),<br>
|
||
|
|
|
||
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>
|
||
|
|
|
||
|
|
|
||
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>
|
||
|
|
|
||
|
|
char *(*clone)(Fid *old, Fid *new, void *v), void *v)<br>
|
||
|
|
|
||
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
|
||
|
|
|
||
|
|
|
||
|
|
</table>
|
||
|
|
|
||
|
|
</table>
|
||
|
|
void* emalloc9p(ulong n)<br>
|
||
|
|
void* erealloc9p(void *v, ulong n)<br>
|
||
|
|
char* estrdup9p(char *s)<br>
|
||
|
|
|
||
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
|
||
|
|
|
||
|
|
extern int chatty9p;<br>
|
||
|
|
</font></tt>
|
||
|
|
</table>
|
||
|
|
<p><font size=+1><b>DESCRIPTION </b></font><br>
|
||
|
|
|
||
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>
|
||
|
|
|
||
|
|
The function <i>srv</i> serves a 9P session by reading requests from
|
||
|
|
<tt><font size=+1>s−>infd</font></tt>, dispatching them to the function pointers kept in <tt><font size=+1>Srv</font></tt>,
|
||
|
|
and writing the responses to <tt><font size=+1>s−>outfd</font></tt>. (Typically, <i>postmountsrv</i>
|
||
|
|
or <i>threadpostmountsrv</i> initializes the <tt><font size=+1>infd</font></tt> and <tt><font size=+1>outfd</font></tt> structure
|
||
|
|
members. See the description below.)
|
||
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
|
||
|
|
|
||
|
|
<tt><font size=+1>Req</font></tt> and <tt><font size=+1>Fid</font></tt> structures are allocated one-to-one with uncompleted
|
||
|
|
requests and active fids, and are described in <a href="../man3/9p-fid.html"><i>9p-fid</i>(3)</a>.
|
||
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
|
||
|
|
|
||
|
|
The behavior of <i>srv</i> depends on whether there is a file tree (see
|
||
|
|
<a href="../man3/9p-file.html"><i>9p-file</i>(3)</a>) associated with the server, that is, whether the <tt><font size=+1>tree</font></tt>
|
||
|
|
element is nonzero. The differences are made explicit in the discussion
|
||
|
|
of the service loop below. The <tt><font size=+1>aux</font></tt> element is the client’s, to
|
||
|
|
do with as it pleases.
|
||
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
|
||
|
|
|
||
|
|
<i>Srv</i> does not return until the 9P conversation is finished. Since
|
||
|
|
it is usually run in a separate process so that the caller can
|
||
|
|
exit, the service loop has little chance to return gracefully
|
||
|
|
on out of memory errors. It calls <i>emalloc9p</i>, <i>erealloc9p</i>, and <i>estrdup9p</i>
|
||
|
|
to obtain its memory. The default implementations of these
|
||
|
|
functions act as <i>malloc</i>, <i>realloc</i>, and <i>strdup</i> but abort the program
|
||
|
|
if they run out of memory. If alternate behavior is desired, clients
|
||
|
|
can link against alternate implementations of these functions.
|
||
|
|
|
||
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
|
||
|
|
|
||
|
|
<i>Postmountsrv</i> and <i>threadpostmountsrv</i> are wrappers that create a
|
||
|
|
separate process in which to run <i>srv</i>. They do the following:<br>
|
||
|
|
|
||
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>
|
||
|
|
|
||
|
|
If <i>s</i><tt><font size=+1>−></font></tt><i>nopipe</i> is zero (the common case), initialize <i>s</i><tt><font size=+1>−></font></tt><i>infd</i> and <i>s</i><tt><font size=+1>−></font></tt><i>outfd</i>
|
||
|
|
to be one end of a freshly allocated pipe, with <i>s</i><tt><font size=+1>−></font></tt><i>srvfd</i> initialized
|
||
|
|
as the other end.<br>
|
||
|
|
If <tt><font size=+1>name</font></tt> is non-nil, call <tt><font size=+1>postfd(</font></tt><i>s</i><tt><font size=+1>−></font></tt><i>srvfd</i><tt><font size=+1>,</font></tt> <i>name</i><tt><font size=+1>)</font></tt> to post <i>s</i><tt><font size=+1>−></font></tt><i>srvfd</i>
|
||
|
|
as <tt><font size=+1>/srv/</font></tt><i>name</i><tt><font size=+1>.<br>
|
||
|
|
</font></tt>Fork a child process via <a href="../man3/rfork.html"><i>rfork</i>(3)</a> or <i>procrfork</i> (see <a href="../man3/thread.html"><i>thread</i>(3)</a>),
|
||
|
|
using the <tt><font size=+1>RFFDG</font></tt>, <tt><font size=+1>RFNAMEG</font></tt>, and <tt><font size=+1>RFMEM</font></tt> flags. The child process calls
|
||
|
|
<i>close(</i><tt><font size=+1>s</font></tt><i>-></i><tt><font size=+1>srvfd</font></tt><i>)</i> and then <i>srv(</i><tt><font size=+1>s</font></tt><i>)</i>; it will exit once <i>srv</i> returns.<br>
|
||
|
|
If <i>mtpt</i> is non-nil, call <tt><font size=+1>amount(</font></tt><i>s</i><tt><font size=+1>−></font></tt><i>srvfd, mtpt</i><tt><font size=+1>,</font></tt> <i>flag</i><tt><font size=+1>, </font></tt>""); otherwise,
|
||
|
|
close <i>s</i><tt><font size=+1>−></font></tt><i>srvfd</i>.<br>
|
||
|
|
The parent returns to the caller.
|
||
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
|
||
|
|
|
||
|
|
|
||
|
|
</table>
|
||
|
|
If any error occurs during this process, the entire process is
|
||
|
|
terminated by calling <a href="../man3/sysfatal.html"><i>sysfatal</i>(3)</a>.<br>
|
||
|
|
<p><font size=+1><b>Service functions </b></font><br>
|
||
|
|
The functions in a <tt><font size=+1>Srv</font></tt> structure named after 9P transactions are
|
||
|
|
called to satisfy requests as they arrive. If a function is provided,
|
||
|
|
it <i>must</i> arrange for <i>respond</i> to be called when the request is satisfied.
|
||
|
|
The only parameter of each service function is a <tt><font size=+1>Req*</font></tt> parameter
|
||
|
|
(say <i>r</i>). The incoming request parameters are
|
||
|
|
stored in <i>r</i><tt><font size=+1>−></font></tt><i>ifcall</i>; <i>r</i><tt><font size=+1>−></font></tt><i>fid</i> and <i>r</i><tt><font size=+1>−></font></tt><i>newfid</i> are pointers to <tt><font size=+1>Fid</font></tt> structures
|
||
|
|
corresponding to the numeric fids in <i>r</i><tt><font size=+1>−></font></tt><i>ifcall</i>; similarly, <i>r</i><tt><font size=+1>−></font></tt><i>oldreq</i>
|
||
|
|
is the <tt><font size=+1>Req</font></tt> structure corresponding to <i>r</i><tt><font size=+1>−></font></tt><i>ifcall.oldtag</i>. The outgoing
|
||
|
|
response data should be stored in <i>r</i><tt><font size=+1>−></font></tt><i>ofcall</i>. The one exception
|
||
|
|
to this rule is that <i>stat</i> should fill in
|
||
|
|
<i>r</i><tt><font size=+1>−></font></tt><i>d</i> rather than <i>r</i><tt><font size=+1>−></font></tt><i>ofcall.stat</i>: the library will convert the structure
|
||
|
|
into the machine-independent wire representation. Similarly, <i>wstat</i>
|
||
|
|
may consult <i>r</i><tt><font size=+1>−></font></tt><i>d</i> rather than decoding <i>r</i><tt><font size=+1>−></font></tt><i>ifcall</i><tt><font size=+1>.</font></tt><i>stat</i> itself. When
|
||
|
|
a request has been handled, <i>respond</i> should be called with <i>r</i> and
|
||
|
|
an error string. If the request was satisfied
|
||
|
|
successfully, the error string should be a nil pointer. Note that
|
||
|
|
it is permissible for a function to return without itself calling
|
||
|
|
<i>respond</i>, as long as it has arranged for <i>respond</i> to be called at
|
||
|
|
some point in the future by another proc sharing its address space,
|
||
|
|
but see the discussion of <i>flush</i> below. Once <i>respond</i> has been
|
||
|
|
called, the <tt><font size=+1>Req*</font></tt> as well as any pointers it once contained must
|
||
|
|
be considered freed and not referenced.
|
||
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
|
||
|
|
|
||
|
|
If the service loop detects an error in a request (e.g., an attempt
|
||
|
|
to reuse an extant fid, an open of an already open fid, a read
|
||
|
|
from a fid opened for write, etc.) it will reply with an error
|
||
|
|
without consulting the service functions.
|
||
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
|
||
|
|
|
||
|
|
The service loop provided by <i>srv</i> (and indirectly by <i>postmountsrv</i>
|
||
|
|
and <i>threadpostmountsrv</i>) is single-threaded. If it is expected
|
||
|
|
that some requests might block, arranging for alternate processes
|
||
|
|
to handle them is suggested.
|
||
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
|
||
|
|
|
||
|
|
The constraints on the service functions are as follows. These
|
||
|
|
constraints are checked while the server executes. If a service
|
||
|
|
function fails to do something it ought to have, <i>srv</i> will call
|
||
|
|
<i>endsrv</i> and then abort.<br>
|
||
|
|
<i>Auth</i> If authentication is desired, the <i>auth</i> function should record
|
||
|
|
that <i>afid</i> is the new authentication fid and set <i>afid->qid</i> and <i>ofcall.qid</i>.
|
||
|
|
<i>Auth</i> may be nil, in which case it will be treated as having responded
|
||
|
|
with the error “<i>argv0: authentication not required</i>,” where <i>argv0</i>
|
||
|
|
is the program name variable as set by
|
||
|
|
|
||
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>
|
||
|
|
|
||
|
|
<i>ARGBEGIN</i> (see <a href="../man3/arg.html"><i>arg</i>(3)</a>).<br>
|
||
|
|
|
||
|
|
</table>
|
||
|
|
<i>Attach</i>The <i>attach</i> function should check the authentication state
|
||
|
|
of <i>afid</i> if desired, and set <i>r</i><tt><font size=+1>−></font></tt><i>fid</i><tt><font size=+1>−></font></tt><i>qid</i> and <i>ofcall.qid</i> to the qid
|
||
|
|
of the file system root. <i>Attach</i> may be nil only if file trees
|
||
|
|
are in use; in this case, the qid will be filled from the root
|
||
|
|
of the tree, and no authentication will be done.
|
||
|
|
<i>Walk</i> If file trees are in use, <i>walk</i> is handled internally, and
|
||
|
|
<i>srv</i><tt><font size=+1>−></font></tt><i>walk</i> is never called.<br>
|
||
|
|
|
||
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>
|
||
|
|
|
||
|
|
If file trees are not in use, <i>walk</i> should consult <i>r</i><tt><font size=+1>−></font></tt><i>ifcall</i><tt><font size=+1>.</font></tt><i>wname</i>
|
||
|
|
and <i>r</i><tt><font size=+1>−></font></tt><i>ifcall</i><tt><font size=+1>.</font></tt><i>nwname</i>, filling in <i>ofcall</i><tt><font size=+1>.</font></tt><i>qid</i> and <i>ofcall</i><tt><font size=+1>.</font></tt><i>nqid</i>, and
|
||
|
|
also copying any necessary <i>aux</i> state from <i>r</i><tt><font size=+1>−></font></tt><i>fid</i> to <i>r</i><tt><font size=+1>−></font></tt><i>newfid</i> when
|
||
|
|
the two are different. As long as <i>walk</i> sets <i>ofcall</i><tt><font size=+1>.</font></tt><i>nqid</i> appropriately,
|
||
|
|
it can <i>respond</i> with a nil error string
|
||
|
|
even when 9P demands an error (<i>e.g.</i>, in the case of a short walk);
|
||
|
|
the library detects error conditions and handles them appropriately.<br>
|
||
|
|
Because implementing the full walk message is intricate and prone
|
||
|
|
to error, the helper routine <i>walkandclone</i> will handle the request
|
||
|
|
given pointers to two functions <i>walk1</i> and (optionally) <i>clone .
|
||
|
|
Clone</i>, if non-nil, is called to signal the creation of <i>newfid</i>
|
||
|
|
from <i>oldfid</i>. Typically a <i>clone</i> routine will copy or increment
|
||
|
|
a reference count in <i>oldfid</i>’s <i>aux</i> element. <i>Walk1</i> should walk <i>fid</i>
|
||
|
|
to <i>name</i>, initializing <i>fid</i><tt><font size=+1>−></font></tt><i>qid</i> to the new path’s qid. Both should
|
||
|
|
return nil on success or an error message on error. <i>Walkandclone</i>
|
||
|
|
will call <i>respond</i> after handling the request.<br>
|
||
|
|
|
||
|
|
</table>
|
||
|
|
<i>Walk1</i>, <i>Clone<br>
|
||
|
|
</i>
|
||
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>
|
||
|
|
|
||
|
|
If the client provides functions <i>srv</i><tt><font size=+1>−></font></tt><i>walk1</i> and (optionally) <i>srv</i><tt><font size=+1>−></font></tt><i>clone</i>,
|
||
|
|
the 9P service loop will call <i>walkandclone</i> with these functions
|
||
|
|
to handle the request. Unlike the <i>walk1</i> above, <i>srv</i><tt><font size=+1>−></font></tt><i>walk1</i> must
|
||
|
|
fill in both <i>fid</i><tt><font size=+1>−></font></tt><i>qid</i> and <tt><font size=+1>*</font></tt><i>qid</i> with the new qid on a successful
|
||
|
|
walk.<br>
|
||
|
|
|
||
|
|
</table>
|
||
|
|
<i>Open</i> If file trees are in use, the file metadata will be consulted
|
||
|
|
on open, create, remove, and wstat to see if the requester has
|
||
|
|
the appropriate permissions. If not, an error will be sent back
|
||
|
|
without consulting a service function.
|
||
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
|
||
|
|
|
||
|
|
If not using file trees or the user has the appropriate permissions,
|
||
|
|
<i>open</i> is called with <i>r</i><tt><font size=+1>−></font></tt><i>ofcall</i><tt><font size=+1>.</font></tt><i>qid</i> already initialized to the one
|
||
|
|
stored in the <tt><font size=+1>Fid</font></tt> structure (that is, the one returned in the
|
||
|
|
previous walk). If the qid changes, both should be updated.<br>
|
||
|
|
<i>Create</i>The <i>create</i> function must fill in both <i>r</i><tt><font size=+1>−></font></tt><i>fid</i><tt><font size=+1>−></font></tt><i>qid</i> and <i>r</i><tt><font size=+1>−></font></tt><i>ofcall</i><tt><font size=+1>.</font></tt><i>qid</i>
|
||
|
|
on success. When using file trees, <i>create</i> should allocate a new
|
||
|
|
<tt><font size=+1>File</font></tt> with <i>createfile</i>; note that <i>createfile</i> may return nil (because,
|
||
|
|
say, the file already exists). If the <i>create</i> function is nil,
|
||
|
|
<i>srv</i> behaves as though it were a function that always
|
||
|
|
|
||
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>
|
||
|
|
|
||
|
|
responded with the error “create prohibited”.<br>
|
||
|
|
|
||
|
|
</table>
|
||
|
|
<i>Remove<br>
|
||
|
|
|
||
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>
|
||
|
|
|
||
|
|
Remove
|
||
|
|
</table>
|
||
|
|
</i>
|
||
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>
|
||
|
|
|
||
|
|
should mark the file as removed, whether by calling <i>removefile</i>
|
||
|
|
when using file trees, or by updating an internal data structure.
|
||
|
|
In general it is not a good idea to clean up the <i>aux</i> information
|
||
|
|
associated with the corresponding <tt><font size=+1>File</font></tt> at this time, to avoid
|
||
|
|
memory errors if other fids have references to that
|
||
|
|
file. Instead, it is suggested that <i>remove</i> simply mark the file
|
||
|
|
as removed (so that further operations on it know to fail) and
|
||
|
|
wait until the file tree’s destroy function is called to reclaim
|
||
|
|
the <i>aux</i> pointer. If not using file trees, it is prudent to take
|
||
|
|
the analogous measures. If <i>remove</i> is not provided, all remove
|
||
|
|
requests will draw “remove prohibited” errors.<br>
|
||
|
|
|
||
|
|
</table>
|
||
|
|
<i>Read</i> The <i>read</i> function must be provided; it fills <i>r</i><tt><font size=+1>−></font></tt><i>ofcall</i><tt><font size=+1>.</font></tt><i>data</i>
|
||
|
|
with at most <i>r</i><tt><font size=+1>−></font></tt><i>ifcall</i><tt><font size=+1>.</font></tt><i>count</i> bytes of data from offset <i>r</i><tt><font size=+1>−></font></tt><i>ifcall</i><tt><font size=+1>.</font></tt><i>offset</i>
|
||
|
|
of the file. It also sets <i>r</i><tt><font size=+1>−></font></tt><i>ofcall</i><tt><font size=+1>.</font></tt><i>count</i> to the number of bytes
|
||
|
|
being returned. If using file trees, <i>srv</i> will handle reads of
|
||
|
|
directories internally, only calling <i>read</i> for requests on
|
||
|
|
|
||
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>
|
||
|
|
|
||
|
|
files. <i>Readstr</i> and <i>readbuf</i> are useful for satisfying read requests
|
||
|
|
on a string or buffer. Consulting the request in <i>r</i><tt><font size=+1>−></font></tt><i>ifcall</i>, they
|
||
|
|
fill <i>r</i><tt><font size=+1>−></font></tt><i>ofcall</i><tt><font size=+1>.</font></tt><i>data</i> and set <i>r</i><tt><font size=+1>−></font></tt><i>ofcall</i><tt><font size=+1>.</font></tt><i>count</i>; they do not call <i>respond</i><tt><font size=+1>.</font></tt>
|
||
|
|
Similarly, <i>dirread9p</i> can be used to handle directory reads in
|
||
|
|
servers not using file trees. The passed <i>gen
|
||
|
|
</i>function will be called as necessary to fill <i>dir</i> with information
|
||
|
|
for the <i>n</i>th entry in the directory. The string pointers placed
|
||
|
|
in <i>dir</i> should be fresh copies made with <i>estrdup9p</i>; they will be
|
||
|
|
freed by <i>dirread9p</i> after each successful call to <i>gen</i>. <i>Gen</i> should
|
||
|
|
return zero if it successfully filled <i>dir</i>, minus one on end of
|
||
|
|
directory.<br>
|
||
|
|
|
||
|
|
</table>
|
||
|
|
<i>Write</i>The <i>write</i> function is similar but need not be provided. If
|
||
|
|
it is not, all writes will draw “write prohibited” errors. Otherwise,
|
||
|
|
<i>write</i> should attempt to write the <i>r</i><tt><font size=+1>−></font></tt><i>ifcall</i><tt><font size=+1>.</font></tt><i>count</i> bytes of <i>r</i><tt><font size=+1>−></font></tt><i>ifcall</i><tt><font size=+1>.</font></tt><i>data</i>
|
||
|
|
to offset <i>r</i><tt><font size=+1>−></font></tt><i>ifcall</i><tt><font size=+1>.</font></tt><i>offset</i> of the file, setting <i>r</i><tt><font size=+1>−></font></tt><i>ofcall</i><tt><font size=+1>.</font></tt><i>count</i>
|
||
|
|
to the number of bytes actually written. Most
|
||
|
|
|
||
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>
|
||
|
|
|
||
|
|
programs consider it an error to write less than the requested
|
||
|
|
amount.<br>
|
||
|
|
|
||
|
|
</table>
|
||
|
|
<i>Stat Stat</i> should fill <i>r</i><tt><font size=+1>−></font></tt><i>d</i> with the stat information for <i>r</i><tt><font size=+1>−></font></tt><i>fid</i>.
|
||
|
|
If using file trees, <i>r</i><tt><font size=+1>−></font></tt><i>d</i> will have been initialized with the stat
|
||
|
|
info from the tree, and <i>stat</i> itself may be nil.<br>
|
||
|
|
<i>Wstat</i>The <i>wstat</i> consults <i>r</i><tt><font size=+1>−></font></tt><i>d</i> in changing the metadata for <i>r</i><tt><font size=+1>−></font></tt><i>fid</i>
|
||
|
|
as described in <i>stat</i>(9p). When using file trees, <i>srv</i> will take
|
||
|
|
care to check that the request satisfies the permissions outlined
|
||
|
|
in <i>stat</i>(9p). Otherwise <i>wstat</i> should take care to enforce permissions
|
||
|
|
where appropriate.<br>
|
||
|
|
<i>Flush</i> Single-threaded servers, which always call <i>respond</i> before
|
||
|
|
returning from the service functions, need not provide a <i>flush</i>
|
||
|
|
implementation: <i>flush</i> is only necessary in multithreaded programs,
|
||
|
|
which arrange for <i>respond</i> to be called asynchronously. <i>Flush</i> should
|
||
|
|
cause the request <i>r</i><tt><font size=+1>−></font></tt><i>oldreq</i> to be cancelled or
|
||
|
|
|
||
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>
|
||
|
|
|
||
|
|
hurried along. If <i>oldreq</i> is cancelled, this should be signalled
|
||
|
|
by calling <i>respond</i> on <i>oldreq</i> with error string ‘<tt><font size=+1>interrupted</font></tt>’.
|
||
|
|
<i>Flush</i> must respond to <i>r</i> with a nil error string. <i>Flush</i> may respond
|
||
|
|
to <i>r</i> before forcing a response to <i>r</i><tt><font size=+1>−></font></tt><i>oldreq</i>. In this case, the
|
||
|
|
library will delay sending the <i>Rflush</i> message until the
|
||
|
|
response to <i>r</i><tt><font size=+1>−></font></tt><i>oldreq</i> has been sent.
|
||
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
|
||
|
|
|
||
|
|
|
||
|
|
</table>
|
||
|
|
<i>Destroyfid</i>, <i>destroyreq</i>, and <i>end</i> are auxiliary functions, not called
|
||
|
|
in direct response to 9P requests.<br>
|
||
|
|
<i>Destroyfid<br>
|
||
|
|
</i>
|
||
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>
|
||
|
|
|
||
|
|
When a <tt><font size=+1>Fid</font></tt>’s reference count drops to zero (<i>i.e.,</i> it has been
|
||
|
|
clunked and there are no outstanding requests referring to it),
|
||
|
|
<i>destroyfid</i> is called to allow the program to dispose of the <i>fid</i><tt><font size=+1>−></font></tt><i>aux</i>
|
||
|
|
pointer.<br>
|
||
|
|
|
||
|
|
</table>
|
||
|
|
<i>Destroyreq<br>
|
||
|
|
</i>
|
||
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>
|
||
|
|
|
||
|
|
Similarly, when a <tt><font size=+1>Req</font></tt>’s reference count drops to zero (<i>i.e.</i>, it
|
||
|
|
has been handled via <i>respond</i> and other outstanding pointers to
|
||
|
|
it have been closed), <i>destroyreq</i> is called to allow the program
|
||
|
|
to dispose of the <i>r</i><tt><font size=+1>−></font></tt><i>aux</i> pointer.<br>
|
||
|
|
|
||
|
|
</table>
|
||
|
|
<i>End</i> Once the 9P service loop has finished (end of file been reached
|
||
|
|
on the service pipe or a bad message has been read), <i>end</i> is called
|
||
|
|
(if provided) to allow any final cleanup. For example, it was
|
||
|
|
used by the Palm Pilot synchronization file system (never finished)
|
||
|
|
to gracefully terminate the serial conversation once the
|
||
|
|
|
||
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>
|
||
|
|
|
||
|
|
file system had been unmounted. After calling <i>end</i>, the service
|
||
|
|
loop (which runs in a separate process from its caller) terminates
|
||
|
|
using <i>_exits</i> (see <a href="../man3/exits.html"><i>exits</i>(3)</a>).
|
||
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
|
||
|
|
|
||
|
|
|
||
|
|
</table>
|
||
|
|
If the <tt><font size=+1>chatty9p</font></tt> flag is at least one, a transcript of the 9P session
|
||
|
|
is printed on standard error. If the <tt><font size=+1>chatty9p</font></tt> flag is greater
|
||
|
|
than one, additional unspecified debugging output is generated.
|
||
|
|
By convention, servers written using this library accept the <tt><font size=+1>−D</font></tt>
|
||
|
|
option to increment <tt><font size=+1>chatty9p</font></tt>.
|
||
|
|
|
||
|
|
</table>
|
||
|
|
<p><font size=+1><b>EXAMPLES </b></font><br>
|
||
|
|
|
||
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>
|
||
|
|
|
||
|
|
<tt><font size=+1>/usr/local/plan9/src/lib9p/ramfs.c</font></tt> is an example of a simple single-threaded
|
||
|
|
file server. On Plan 9, see <i>archfs</i>, <i>cdfs</i>, <i>nntpfs</i>, <i>webfs</i>, and <i>sshnet</i>
|
||
|
|
for more examples.
|
||
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
|
||
|
|
|
||
|
|
In general, the <tt><font size=+1>File</font></tt> interface is appropriate for maintaining
|
||
|
|
arbitrary file trees (as in <i>ramfs</i>). The <tt><font size=+1>File</font></tt> interface is best
|
||
|
|
avoided when the tree structure is easily generated as necessary;
|
||
|
|
this is true when the tree is highly structured (as in <i>cdfs</i> and
|
||
|
|
<i>nntpfs</i>) or is maintained elsewhere.<br>
|
||
|
|
|
||
|
|
</table>
|
||
|
|
<p><font size=+1><b>SOURCE </b></font><br>
|
||
|
|
|
||
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>
|
||
|
|
|
||
|
|
<tt><font size=+1>/usr/local/plan9/src/lib9p<br>
|
||
|
|
</font></tt>
|
||
|
|
</table>
|
||
|
|
<p><font size=+1><b>SEE ALSO </b></font><br>
|
||
|
|
|
||
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>
|
||
|
|
|
||
|
|
<a href="../man3/9p-fid.html"><i>9p-fid</i>(3)</a>, <a href="../man3/9p-file.html"><i>9p-file</i>(3)</a>, <i>intro</i>(9p)<br>
|
||
|
|
|
||
|
|
</table>
|
||
|
|
|
||
|
|
<td width=20>
|
||
|
|
<tr height=20><td>
|
||
|
|
</table>
|
||
|
|
<!-- TRAILER -->
|
||
|
|
<table border=0 cellpadding=0 cellspacing=0 width=100%>
|
||
|
|
<tr height=15><td width=10><td><td width=10>
|
||
|
|
<tr><td><td>
|
||
|
|
<center>
|
||
|
|
<a href="../../"><img src="../../dist/spaceglenda100.png" alt="Space Glenda" border=1></a>
|
||
|
|
</center>
|
||
|
|
</table>
|
||
|
|
<!-- TRAILER -->
|
||
|
|
</body></html>
|