aboutsummaryrefslogtreecommitdiff
path: root/man/man3/9p.3
diff options
context:
space:
mode:
Diffstat (limited to 'man/man3/9p.3')
-rw-r--r--man/man3/9p.3760
1 files changed, 760 insertions, 0 deletions
diff --git a/man/man3/9p.3 b/man/man3/9p.3
new file mode 100644
index 00000000..48d029ef
--- /dev/null
+++ b/man/man3/9p.3
@@ -0,0 +1,760 @@
+.TH 9P 3
+.SH NAME
+Srv,
+dirread9p,
+emalloc9p,
+erealloc9p,
+estrdup9p,
+postfd,
+postmountsrv,
+readbuf,
+readstr,
+respond,
+threadpostmountsrv,
+srv \- 9P file service
+.SH SYNOPSIS
+.ft L
+.nf
+#include <u.h>
+#include <libc.h>
+#include <fcall.h>
+#include <thread.h>
+#include <9p.h>
+.fi
+.PP
+.ft L
+.nf
+.ta \w'\fL1234'u +\w'\fLTree* 'u
+typedef struct Srv {
+ Tree* tree;
+
+ void (*attach)(Req *r);
+ void (*auth)(Req *r);
+ void (*open)(Req *r);
+ void (*create)(Req *r);
+ void (*read)(Req *r);
+ void (*write)(Req *r);
+ void (*remove)(Req *r);
+ void (*flush)(Req *r);
+ void (*stat)(Req *r);
+ void (*wstat)(Req *r);
+ void (*walk)(Req *r);
+
+ char* (*walk1)(Fid *fid, char *name, Qid *qid);
+ char* (*clone)(Fid *oldfid, Fid *newfid);
+
+ void (*destroyfid)(Fid *fid);
+ void (*destroyreq)(Req *r);
+ void (*end)(Srv *s);
+ void* aux;
+
+ int infd;
+ int outfd;
+ int srvfd;
+ int nopipe;
+} Srv;
+.fi
+.PP
+.nf
+.ft L
+.ta \w'\fLvoid* 'u
+int srv(Srv *s)
+void postmountsrv(Srv *s, char *name, char *mtpt, int flag)
+void threadpostmountsrv(Srv *s, char *name, char *mtpt, int flag)
+int postfd(char *srvname, int fd)
+void respond(Req *r, char *error)
+ulong readstr(Req *r, char *src)
+ulong readbuf(Req *r, void *src, ulong nsrc)
+typedef int Dirgen(int n, Dir *dir, void *aux)
+void dirread9p(Req *r, Dirgen *gen, void *aux)
+void walkandclone(Req *r, char *(*walk1)(Fid *old, char *name, void *v),
+ char *(*clone)(Fid *old, Fid *new, void *v), void *v)
+.fi
+.PP
+.nf
+.ft L
+.ta \w'\fLvoid* 'u
+void* emalloc9p(ulong n)
+void* erealloc9p(void *v, ulong n)
+char* estrdup9p(char *s)
+.fi
+.PP
+.nf
+.ft L
+extern int chatty9p;
+.fi
+.SH DESCRIPTION
+The function
+.I srv
+serves a 9P session by reading requests from
+.BR s->infd ,
+dispatching them to the function pointers kept in
+.BR Srv ,
+and
+writing the responses to
+.BR s->outfd .
+(Typically,
+.I postmountsrv
+or
+.I threadpostmountsrv
+initializes the
+.B infd
+and
+.B outfd
+structure members. See the description below.)
+.PP
+.B Req
+and
+.B Fid
+structures are allocated one-to-one with uncompleted
+requests and active fids, and are described in
+.IR 9pfid (2).
+.PP
+The behavior of
+.I srv
+depends on whether there is a file tree
+(see
+.IR 9pfile (2))
+associated with the server, that is,
+whether the
+.B tree
+element is nonzero.
+The differences are made explicit in the
+discussion of the service loop below.
+The
+.B aux
+element is the client's, to do with as it pleases.
+.PP
+.I Srv
+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
+.IR emalloc9p ,
+.IR erealloc9p ,
+and
+.I estrdup9p
+to obtain its memory.
+The default implementations of these functions
+act as
+.IR malloc ,
+.IR realloc ,
+and
+.I strdup
+but abort the program if they run out of memory.
+If alternate behavior is desired, clients can link against
+alternate implementations of these functions.
+.PP
+.I Postmountsrv
+and
+.I threadpostmountsrv
+are wrappers that create a separate process in which to run
+.IR srv .
+They do the following:
+.IP
+If
+.IB s -> nopipe
+is zero (the common case),
+initialize
+.IB s -> infd
+and
+.IB s -> outfd
+to be one end of a freshly allocated pipe,
+with
+.IB s -> srvfd
+initialized as the other end.
+.IP
+If
+.B name
+is non-nil, call
+.BI postfd( s -> srvfd ,
+.IB name )
+to post
+.IB s -> srvfd
+as
+.BI /srv/ name .
+.IP
+Fork a child process via
+.I rfork
+(see
+.IR fork (2))
+or
+.I procrfork
+(see
+.IR thread (2)),
+using the
+.BR RFFDG ,
+.RR RFNOTEG ,
+.BR RFNAMEG ,
+and
+.BR RFMEM
+flags.
+The child process
+calls
+.IB close( s -> srvfd )
+and then
+.IB srv( s ) \fR;
+it will exit once
+.I srv
+returns.
+.IP
+If
+.I mtpt
+is non-nil,
+call
+.BI amount( s -> srvfd,
+.IB mtpt ,
+.IB flag ,
+\fB"")\fR;
+otherwise, close
+.IB s -> srvfd \fR.
+.IP
+The parent returns to the caller.
+.LP
+If any error occurs during
+this process, the entire process is terminated by calling
+.I sysfatal
+(see
+.IR perror (2)).
+.SS Service functions
+The functions in a
+.B Srv
+structure named after 9P transactions
+are called to satisfy requests as they arrive.
+If a function is provided, it
+.I must
+arrange for
+.I respond
+to be called when the request is satisfied.
+The only parameter of each service function
+is a
+.B Req*
+parameter (say
+.IR r ).
+The incoming request parameters are stored in
+.IB r -> ifcall \fR;
+.IB r -> fid
+and
+.IB r -> newfid
+are pointers to
+.B Fid
+structures corresponding to the
+numeric fids in
+.IB r -> ifcall \fR;
+similarly,
+.IB r -> oldreq
+is the
+.B Req
+structure corresponding to
+.IB r -> ifcall.oldtag \fR.
+The outgoing response data should be stored in
+.IB r -> ofcall \fR.
+The one exception to this rule is that
+.I stat
+should fill in
+.IB r -> d
+rather than
+.IB r -> ofcall.stat \fR:
+the library will convert the structure into the machine-independent
+wire representation.
+Similarly,
+.I wstat
+may consult
+.IB r -> d
+rather than decoding
+.IB r -> ifcall . stat
+itself.
+When a request has been handled,
+.I respond
+should be called with
+.I r
+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
+.IR respond ,
+as long as it has arranged for
+.I respond
+to be called at some point in the future
+by another proc sharing its address space,
+but see the discussion of
+.I flush
+below.
+Once
+.I respond
+has been called, the
+.B Req*
+as well as any pointers it once contained must
+be considered freed and not referenced.
+.PP
+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.
+.PP
+The service loop provided by
+.I srv
+(and indirectly by
+.I postmountsrv
+and
+.IR threadpostmountsrv )
+is single-threaded.
+If it is expected that some requests might
+block, arranging for alternate processes
+to handle them is suggested.
+.PP
+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
+will call
+.I endsrv
+and then abort.
+.TP
+.I Auth
+If authentication is desired,
+the
+.I auth
+function should record that
+.I afid
+is the new authentication fid and
+set
+.I afid->qid
+and
+.IR ofcall.qid .
+.I Auth
+may be nil, in which case it will be treated as having
+responded with the error
+.RI `` "argv0: authentication not required" ,''
+where
+.I argv0
+is the program name variable as set by
+.I ARGBEGIN
+(see
+.IR arg (2)).
+.TP
+.I Attach
+The
+.I attach
+function should check the authentication state of
+.I afid
+if desired,
+and set
+.IB r -> fid -> qid
+and
+.I ofcall.qid
+to the qid of the file system root.
+.I Attach
+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.
+.TP
+.I Walk
+If file trees are in use,
+.I walk
+is handled internally, and
+.IB srv -> walk
+is never called.
+.IP
+If file trees are not in use,
+.I walk
+should consult
+.IB r -> ifcall . wname
+and
+.IB r -> ifcall . nwname \fR,
+filling in
+.IB ofcall . qid
+and
+.IB ofcall . nqid \fR,
+and also copying any necessary
+.I aux
+state from
+.IB r -> fid
+to
+.IB r -> newfid
+when the two are different.
+As long as
+.I walk
+sets
+.IB ofcall . nqid
+appropriately, it can
+.I respond
+with a nil error string even when 9P
+demands an error
+.RI ( e.g. ,
+in the case of a short walk);
+the library detects error conditions and handles them appropriately.
+.IP
+Because implementing the full walk message is intricate and
+prone to error, the helper routine
+.I walkandclone
+will handle the request given pointers to two functions
+.I walk1
+and (optionally)
+.I clone .
+.IR Clone ,
+if non-nil, is called to signal the creation of
+.I newfid
+from
+.IR oldfid .
+Typically a
+.I clone
+routine will copy or increment a reference count in
+.IR oldfid 's
+.I aux
+element.
+.I Walk1
+should walk
+.I fid
+to
+.IR name ,
+initializing
+.IB fid -> qid
+to the new path's qid.
+Both should return nil
+on success or an error message on error.
+.I Walkandclone
+will call
+.I respond
+after handling the request.
+.TP
+.I Walk1\fR, \fPClone
+If the client provides functions
+.IB srv -> walk1
+and (optionally)
+.IB srv -> clone \fR,
+the 9P service loop will call
+.I walkandclone
+with these functions to handle the request.
+Unlike the
+.I walk1
+above,
+.IB srv -> walk1
+must fill in both
+.IB fid -> qid
+and
+.BI * qid
+with the new qid on a successful walk.
+.TP
+.I Open
+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.
+.PP
+If not using file trees or the user has the appropriate permissions,
+.I open
+is called with
+.IB r -> ofcall . qid
+already initialized to the one stored in the
+.B Fid
+structure (that is, the one returned in the previous walk).
+If the qid changes, both should be updated.
+.TP
+.I Create
+The
+.I create
+function must fill in
+both
+.IB r -> fid -> qid
+and
+.IB r -> ofcall . qid
+on success.
+When using file trees,
+.I create
+should allocate a new
+.B File
+with
+.IR createfile ;
+note that
+.I createfile
+may return nil (because, say, the file already exists).
+If the
+.I create
+function is nil,
+.I srv
+behaves as though it were a function that always responded
+with the error ``create prohibited''.
+.TP
+.I Remove
+.I Remove
+should mark the file as removed, whether
+by calling
+.I removefile
+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
+information associated with the corresponding
+.B File
+at this time, to avoid memory errors if other
+fids have references to that file.
+Instead, it is suggested that
+.I remove
+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
+pointer.
+If not using file trees, it is prudent to take the
+analogous measures.
+If
+.I remove
+is not provided, all remove requests will draw
+``remove prohibited'' errors.
+.TP
+.I Read
+The
+.I read
+function must be provided; it fills
+.IB r -> ofcall . data
+with at most
+.IB r -> ifcall . count
+bytes of data from offset
+.IB r -> ifcall . offset
+of the file.
+It also sets
+.IB r -> ofcall . count
+to the number of bytes being returned.
+If using file trees,
+.I srv
+will handle reads of directories internally, only
+calling
+.I read
+for requests on files.
+.I Readstr
+and
+.I readbuf
+are useful for satisfying read requests on a string or buffer.
+Consulting the request in
+.IB r -> ifcall \fR,
+they fill
+.IB r -> ofcall . data
+and set
+.IB r -> ofcall . count \fR;
+they do not call
+.IB respond .
+Similarly,
+.I dirread9p
+can be used to handle directory reads in servers
+not using file trees.
+The passed
+.I gen
+function will be called as necessary to
+fill
+.I dir
+with information for the
+.IR n th
+entry in the directory.
+The string pointers placed in
+.I dir
+should be fresh copies
+made with
+.IR estrdup9p ;
+they will be freed by
+.I dirread9p
+after each successful call to
+.IR gen .
+.I Gen
+should return zero if it successfully filled
+.IR dir ,
+minus one on end of directory.
+.TP
+.I Write
+The
+.I write
+function is similar but need not be provided.
+If it is not, all writes will draw
+``write prohibited'' errors.
+Otherwise,
+.I write
+should attempt to write the
+.IB r -> ifcall . count
+bytes of
+.IB r -> ifcall . data
+to offset
+.IB r -> ifcall . offset
+of the file, setting
+.IB r -> ofcall . count
+to the number of bytes actually written.
+Most programs consider it an error to
+write less than the requested amount.
+.TP
+.I Stat
+.I Stat
+should fill
+.IB r -> d
+with the stat information for
+.IB r -> fid \fR.
+If using file trees,
+.IB r -> d
+will have been initialized with the stat info from
+the tree, and
+.I stat
+itself may be nil.
+.TP
+.I Wstat
+The
+.I wstat
+consults
+.IB r -> d
+in changing the metadata for
+.IB r -> fid
+as described in
+.IR stat (5).
+When using file trees,
+.I srv
+will take care to check that the request satisfies
+the permissions outlined in
+.IR stat (5).
+Otherwise
+.I wstat
+should take care to enforce permissions
+where appropriate.
+.TP
+.I Flush
+Single-threaded servers, which always call
+.I respond
+before returning from the service functions,
+need not provide a
+.I flush
+implementation:
+.I flush
+is only necessary in multithreaded programs,
+which arrange for
+.I respond
+to be called asynchronously.
+.I Flush
+should cause the request
+.IB r -> oldreq
+to be cancelled or hurried along.
+If
+.I oldreq
+is cancelled, this should be signalled by calling
+.I respond
+on
+.I oldreq
+with error string
+.RB ` interrupted '.
+.I Flush
+must respond to
+.I r
+with a nil error string.
+.I Flush
+may respond to
+.I r
+before forcing a response to
+.IB r -> oldreq \fR.
+In this case, the library will delay sending
+the
+.I Rflush
+message until the response to
+.IB r -> oldreq
+has been sent.
+.PD
+.PP
+.IR Destroyfid ,
+.IR destroyreq ,
+and
+.I end
+are auxiliary functions, not called in direct response to 9P requests.
+.TP
+.I Destroyfid
+When a
+.BR Fid 's
+reference count drops to zero
+.RI ( i.e.,
+it has been clunked and there are no outstanding
+requests referring to it),
+.I destroyfid
+is called to allow the program to dispose
+of the
+.IB fid -> aux
+pointer.
+.TP
+.I Destroyreq
+Similarly, when a
+.BR Req 's
+reference count drops to zero
+.RI ( i.e. ,
+it has been handled via
+.I respond
+and other outstanding pointers to it have been closed),
+.I destroyreq
+is called to allow the program to dispose of the
+.IB r -> aux
+pointer.
+.TP
+.I End
+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
+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 file system had been unmounted.
+After calling
+.IR end ,
+the service loop (which runs in a separate process
+from its caller) terminates using
+.I _exits
+(see
+.IR exits (2)).
+.PD
+.PP
+If the
+.B chatty9p
+flag is at least one,
+a transcript of the 9P session is printed
+on standard error.
+If the
+.B chatty9p
+flag is greater than one,
+additional unspecified debugging output is generated.
+By convention, servers written using this library
+accept the
+.B -D
+option to increment
+.BR chatty9p .
+.SH EXAMPLES
+.IR Archfs (4),
+.IR cdfs (4),
+.IR nntpfs (4),
+.IR snap (4),
+and
+.B /sys/src/lib9p/ramfs.c
+are good examples of simple single-threaded file servers.
+.IR Webfs (4)
+and
+.I sshnet
+(see
+.IR ssh (1))
+are good examples of multithreaded file servers.
+.PP
+In general, the
+.B File
+interface is appropriate for maintaining arbitrary file trees (as in
+.IR ramfs ).
+The
+.B File
+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
+and
+.IR nntpfs )
+or is maintained elsewhere.
+.SH SOURCE
+.B /sys/src/lib9p
+.SH SEE ALSO
+.IR 9pfid (2),
+.IR 9pfile (2),
+.IR srv (3),
+.IR intro (5)
+.SH BUGS
+The switch to 9P2000 was taken as an opportunity to tidy
+much of the interface; we promise to avoid such gratuitous change
+in the future.