9P(2)                                                       9P(2)

          Srv, chatty9p, dirread9p, emalloc9p, erealloc9p, estrdup9p,
          listensrv, postmountsrv, postsharesrv, readbuf, readstr,
          respond, responderror, srvacquire, srvrelease,
          threadlistensrv, threadpostmountsrv, threadpostsharesrv, srv
          - 9P file service

          #include <u.h>
          #include <libc.h>
          #include <fcall.h>
          #include <thread.h>
          #include <9p.h>

          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  (*start)(Srv *s);
              void  (*end)(Srv *s);
              void* aux;

              int   infd;
              int   outfd;
              int   srvfd;
          } Srv;

          void  srv(Srv *s)
          void  postmountsrv(Srv *s, char *name, char *mtpt, int flag)
          void  postsharesrv(Srv *s, char *name, char *mtpt, char *desc)
          void  threadpostmountsrv(Srv *s, char *name, char *mtpt, int flag)
          void  threadpostsharesrv(Srv *s, char *name, char *mtpt, char *desc)
          void  listensrv(Srv *s, char *addr)
          void  threadlistensrv(Srv *s, char *addr)

     Page 1                       Plan 9             (printed 7/23/24)

     9P(2)                                                       9P(2)

          void  respond(Req *r, char *error)
          void  responderror(Req*)
          void  readstr(Req *r, char *src)
          void  readbuf(Req *r, void *src, long 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)

          void  srvrelease(Srv *s)
          void  srvacquire(Srv *s)

          void* emalloc9p(ulong n)
          void* erealloc9p(void *v, ulong n)
          char* estrdup9p(char *s)

          extern int chatty9p;

          The function srv serves a 9P session by reading requests
          from s->infd, dispatching them to the function pointers kept
          in Srv, and writing the responses to s->outfd.  (Typically,
          postmountsrv or threadpostmountsrv initializes the infd and
          outfd structure members.  See the description below.)

          Req and Fid structures are allocated one-to-one with uncom-
          pleted requests and active fids, and are described in

          The behavior of srv depends on whether there is a file tree
          (see 9pfile(2)) associated with the server, that is, whether
          the tree element is nonzero.  The differences are made
          explicit in the discussion of the service loop below.  The
          aux element is the client's, to do with as it pleases.

          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
          emalloc9p, erealloc9p, and estrdup9p to obtain its memory.
          The default implementations of these functions act as
          malloc, realloc, and strdup but abort the program if they
          run out of memory.  If alternate behavior is desired,
          clients can link against alternate implementations of these

          Postmountsrv and threadpostmountsrv are wrappers that create
          a separate process in which to run srv. They do the follow-

               Initialize s->infd and s->outfd to be one end of a
               freshly allocated pipe, with s->srvfd initialized as

     Page 2                       Plan 9             (printed 7/23/24)

     9P(2)                                                       9P(2)

               the other end.

               If name is non-nil, post the file descriptor s->srvfd
               under the name /srv/name.

               Fork a child process via rfork (see fork(2)) or
               procrfork (see thread(2)), using the RFPROC, RFNOWAIT,
               RFNAMEG, RFNOTEG and RFMEM flags. This isolates the
               service loop from the callers namespace and from notes
               posted to the callers note group but shares data and
               bss segments.

               The child process then waits for the parent to copy its
               file descriptor table via rfork using RFFDG flag. This
               way, the service loop will share the original file
               descriptor table with previously created child pro-
               cesses of the caller.

               The child process then calls close(s->srvfd) and then
               srv(s); it will exit once srv returns.

               If mtpt is non-nil, call amount(s->srvfd, mtpt, flag,
               ""); otherwise, close s->srvfd.

               The parent returns to the caller.

          If any error occurs during this process, the entire process
          is terminated by calling sysfatal (see perror(2)).

          Postsharesrv is similar to Postmountsrv but instead of
          mounting the service on a directory, it is put in a share
          (see shr(3)) where mtpt is the name of the share and desc is
          the name of the service channel.

          Listensrv and threadlistensrv create a separate process to
          announce as addr. The process listens for incoming connec-
          tions, creating a new process to serve each.  Using these
          functions results in srv and the service functions being run
          in multiple processes simultaneously.  The library locks its
          own data structures as necessary; the client may need to
          lock data it shares between the multiple connections.

        Service functions
          The functions in a Srv structure named after 9P transactions
          are called to satisfy requests as they arrive.  If a func-
          tion is provided, it must arrange for respond to be called
          when the request is satisfied.  The only parameter of each
          service function is a Req* parameter (say r). The incoming
          request parameters are stored in r->ifcall; r->fid and
          r->newfid are pointers to Fid structures corresponding to
          the numeric fids in r->ifcall; similarly, r->oldreq is the
          Req structure corresponding to r->ifcall.oldtag.  The

     Page 3                       Plan 9             (printed 7/23/24)

     9P(2)                                                       9P(2)

          outgoing response data should be stored in r->ofcall.  The
          one exception to this rule is that stat should fill in r->d
          rather than r->ofcall.stat: the library will convert the
          structure into the machine-independent wire representation.
          Similarly, wstat may consult r->d rather than decoding
          r->ifcall.stat itself.  When a request has been handled,
          respond should be called with 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 func-
          tion to return without itself calling respond, as long as it
          has arranged for respond to be called at some point in the
          future by another proc sharing its address space, but see
          the discussion of flush below.  Once respond has been
          called, the Req* as well as any pointers it once contained
          must be considered freed and not referenced.

          Responderror calls respond with the system error string (see

          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 func-

          The service loop provided by srv (and indirectly by
          postmountsrv and threadpostmountsrv) is single-threaded.  If
          it is expected that some requests might block, arranging for
          alternate processes to handle them is suggested (see

          Srvrelease temporarily releases the calling process from the
          server loop and if neccesary spawns a new process to handle
          9p requests. When released, the process can do blocking work
          that would otherwise halt processing of 9p requests.
          Srvacquire rejoins the calling process with the server loop
          after a srvrelease.

          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,
          srv will call endsrv and then abort.

          Auth If authentication is desired, the auth function should
               record that r->afid is the new authentication fid and
               set r->afid->qid and ofcall.qid. Auth may be nil, in
               which case it will be treated as having responded with
               the error ``argv0: authentication not required,'' where
               argv0 is the program name variable as set by ARGBEGIN
               (see arg(2)).


     Page 4                       Plan 9             (printed 7/23/24)

     9P(2)                                                       9P(2)

               The attach function should check the authentication
               state of afid if desired, and set r->fid->qid and
               ofcall.qid to the qid of the file system root.  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.

          Walk If file trees are in use, walk is handled internally,
               and srv->walk is never called.

               If file trees are not in use, walk should consult
               r->ifcall.wname and r->ifcall.nwname, filling in
               ofcall.qid and ofcall.nqid, and also copying any neces-
               sary aux state from r->fid to r->newfid when the two
               are different.  As long as walk sets ofcall.nqid appro-
               priately, it can respond with a nil error string even
               when 9P demands an error (e.g., in the case of a short
               walk); the library detects error conditions and handles
               them appropriately.

               Because implementing the full walk message is intricate
               and prone to error, the helper routine walkandclone
               will handle the request given pointers to two functions
               walk1 and (optionally) clone . Clone, if non-nil, is
               called to signal the creation of newfid from oldfid.
               Typically a clone routine will copy or increment a ref-
               erence count in oldfid's aux element.  Walk1 should
               walk fid to name, initializing fid->qid to the new
               path's qid.  Both should return nil on success or an
               error message on error.  Walkandclone will call respond
               after handling the request.

          Walk1, Clone
               If the client provides functions srv->walk1 and
               (optionally) srv->clone, the 9P service loop will call
               walkandclone with these functions to handle the
               request.  Unlike the walk1 above, srv->walk1 must fill
               in both fid->qid and *qid with the new qid on a suc-
               cessful walk.

          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

               If not using file trees or the user has the appropriate
               permissions, open is called with r->ofcall.qid already
               initialized to the one stored in the Fid structure
               (that is, the one returned in the previous walk).  If
               the qid changes, both should be updated.

     Page 5                       Plan 9             (printed 7/23/24)

     9P(2)                                                       9P(2)

               The create function must fill in both r->fid->qid and
               r->ofcall.qid on success.  When using file trees,
               create should allocate a new File with createfile; note
               that createfile may return nil (because, say, the file
               already exists).  If the create function is nil, srv
               behaves as though it were a function that always
               responded with the error ``create prohibited''.

               Remove should mark the file as removed, whether by
               calling removefile when using file trees, or by updat-
               ing an internal data structure.  In general it is not a
               good idea to clean up the aux information associated
               with the corresponding File at this time, to avoid mem-
               ory errors if other fids have references to that file.
               Instead, it is suggested that remove simply mark the
               file as removed (so that further operations on it know
               to fail) and wait until the file tree's destroy func-
               tion is called to reclaim the aux pointer.  If not
               using file trees, it is prudent to take the analogous
               measures.  If remove is not provided, all remove
               requests will draw ``remove prohibited'' errors.

          Read The read function must be provided; it fills
               r->ofcall.data with at most r->ifcall.count bytes of
               data from offset r->ifcall.offset of the file.  It also
               sets r->ofcall.count to the number of bytes being
               returned.  If using file trees, srv will handle reads
               of directories internally, only calling read for
               requests on files.  Readstr and readbuf are useful for
               satisfying read requests on a string or buffer.  Con-
               sulting the request in r->ifcall, they fill
               r->ofcall.data and set r->ofcall.count; they do not
               call respond.  Similarly, dirread9p can be used to han-
               dle directory reads in servers not using file trees.
               The passed gen function will be called as necessary to
               fill dir with information for the nth entry in the
               directory.  The string pointers placed in dir should be
               fresh copies made with estrdup9p; they will be freed by
               dirread9p after each successful call to gen. Gen should
               return zero if it successfully filled dir, minus one on
               end of directory.

               The write function is similar but need not be provided.
               If it is not, all writes will draw ``write prohibited''
               errors.  Otherwise, write should attempt to write the
               r->ifcall.count bytes of r->ifcall.data to offset
               r->ifcall.offset of the file, setting r->ofcall.count
               to the number of bytes actually written.  Most programs
               consider it an error to write less than the requested

     Page 6                       Plan 9             (printed 7/23/24)

     9P(2)                                                       9P(2)


          Stat Stat should fill r->d with the stat information for
               r->fid.  If using file trees, r->d will have been ini-
               tialized with the stat info from the tree, and stat
               itself may be nil.

               The wstat function consults r->d in changing the meta-
               data for r->fid as described in stat(5). When using
               file trees, srv will take care to check that the
               request satisfies the permissions outlined in stat(5).
               Otherwise wstat should take care to enforce permissions
               where appropriate.

               Servers that always call respond before returning from
               the service functions need not provide a flush imple-
               mentation: flush is only necessary in programs that
               arrange for respond to be called asynchronously.  Flush
               should cause the request r->oldreq to be cancelled or
               hurried along.  If oldreq is cancelled, this should be
               signalled by calling respond on oldreq with error
               string `interrupted'.  Flush must respond to r with a
               nil error string.  Flush may respond to r before forc-
               ing a response to r->oldreq.  In this case, the library
               will delay sending the Rflush message until the
               response to r->oldreq has been sent.

          Destroyfid, destroyreq, start, and end are auxiliary func-
          tions, not called in direct response to 9P requests.

               When a Fid's reference count drops to zero (i.e., it
               has been clunked and there are no outstanding requests
               referring to it), destroyfid is called to allow the
               program to dispose of the fid->aux pointer.

               Similarly, when a Req's reference count drops to zero
               (i.e., it has been handled via respond and other out-
               standing pointers to it have been closed), destroyreq
               is called to allow the program to dispose of the r->aux

               This gets called (from the forked service process)
               prior entering the 9P service loop.

          End  Once the 9P service loop has finished (end of file been
               reached on the service pipe or a bad message has been
               read), end is called (if provided) to allow any final

     Page 7                       Plan 9             (printed 7/23/24)

     9P(2)                                                       9P(2)

               cleanup.  For example, it was used by the Palm Pilot
               synchronization file system (never finished) to grace-
               fully terminate the serial conversation once the file
               system had been unmounted.  After calling end, the ser-
               vice loop (which runs in a separate process from its
               caller) terminates using _exits (see exits(2)).

          If the chatty9p flag is at least one, a transcript of the 9P
          session is printed on standard error.  If the chatty9p flag
          is greater than one, additional unspecified debugging output
          is generated.  By convention, servers written using this
          library accept the -D option to increment chatty9p.

          Archfs(4), cdfs(4), nntpfs(4), snap(4), and
          /sys/src/lib9p/ramfs.c are good examples of simple single-
          threaded file servers.

          In general, the File interface is appropriate for maintain-
          ing arbitrary file trees (as in ramfs). The File interface
          is best avoided when the tree structure is easily generated
          as necessary; this is true when the tree is highly struc-
          tured (as in cdfs and nntpfs) or is maintained elsewhere.


          9pfid(2), 9pfile(2), 9pqueue(2), srv(3), shr(3), intro(5)

          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.

     Page 8                       Plan 9             (printed 7/23/24)