glenda.party
term% ls -F
term% pwd
$home/manuals/plan9_4th/2/9p
term% cat index.txt
9P(2)                         System Calls Manual                        9P(2)



NAME
       Srv,  dirread9p,  emalloc9p,  erealloc9p, estrdup9p, listensrv, postfd,
       postmountsrv, readbuf, readstr, respond, responderror, threadlistensrv,
       threadpostmountsrv, srv - 9P file service

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

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

       int   srv(Srv *s)
       void  postmountsrv(Srv *s, char *name, char *mtpt, int flag)
       void  threadpostmountsrv(Srv *s, char *name, char *mtpt, int flag)
       void  listensrv(Srv *s, char *addr)
       void  threadlistensrv(Srv *s, char *addr)
       int   postfd(char *srvname, int fd)
       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* emalloc9p(ulong n)
       void* erealloc9p(void *v, ulong n)
       char* estrdup9p(char *s)

       extern int chatty9p;

DESCRIPTION
       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 uncompleted re‐
       quests and active fids, and are described in 9pfid(2).

       The behavior of srv depends on  whether  there  is  a  file  tree  (see
       9pfile(2))  associated  with the server, that is, whether the tree ele‐
       ment 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 ser‐
       vice loop has little chance to return gracefully on out of  memory  er‐
       rors.  It calls emalloc9p, erealloc9p, and estrdup9p to obtain its mem‐
       ory.  The default implementations of these functions act as malloc, re‐
       alloc,  and strdup but abort the program if they run out of memory.  If
       alternate behavior is desired, clients can link against  alternate  im‐
       plementations of these functions.

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

              If s->nopipe is zero (the common case), initialize  s->infd  and
              s->outfd  to  be  one  end  of  a  freshly  allocated pipe, with
              s->srvfd initialized as the other end.

              If name is non-nil, call postfd(s->srvfd, name) to post s->srvfd
              as /srv/name.

              Fork  a  child process via rfork (see fork(2)) or procrfork (see
              thread(2)), using the RFFDG,  RFNAMEG,  and  RFMEM  flags.   The
              child  process  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, "");  oth‐
              erwise, close s->srvfd.

              The parent returns to the caller.

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

       Listensrv and threadlistensrv create a separate process to announce  as
       addr.   The  process  listens  for incoming connections, 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 function 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 corre‐
       sponding to r->ifcall.oldtag.  The 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  con‐
       vert  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 function to return without itself calling respond, as long as it  has
       arranged  for  respond  to be called at some point in the future by an‐
       other 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
       errstr(2)).

       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.

       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.

       The  constraints  on  the service functions are as follows.  These con‐
       straints 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: authentica‐
              tion not required,'' where argv0 is the program name variable as
              set by ARGBEGIN (see arg(2)).

       Attach 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->if‐
              call.wname  and  r->ifcall.nwname, filling in ofcall.qid and of‐
              call.nqid, and also copying any necessary aux state from  r->fid
              to  r->newfid  when the two are different.  As long as walk sets
              ofcall.nqid appropriately, 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 in‐
              crement a reference 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 successful 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 function.

              If not using file trees or the user has the appropriate  permis‐
              sions,  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 up‐
              dated.

       Create The create function must fill in  both  r->fid->qid  and  r->of‐
              call.qid on success.  When using file trees, create should allo‐
              cate 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 Remove  should  mark the file as removed, whether by calling re‐
              movefile when using file trees, or by updating 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  memory  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 function 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.off‐
              set  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.   Consulting 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
              handle 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 es‐
              trdup9p; 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.

       Write  The write function is similar but need not be provided.   If  it
              is  not, all writes will draw ``write prohibited'' errors.  Oth‐
              erwise, write should attempt to write the r->ifcall.count  bytes
              of  r->ifcall.data  to offset r->ifcall.offset of the file, set‐
              ting r->ofcall.count to the number of  bytes  actually  written.
              Most  programs  consider  it an error to write less than the re‐
              quested amount.

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

       Wstat  The wstat consults r->d in changing the metadata 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 permis‐
              sions where appropriate.

       Flush  Servers that always call respond before returning from the  ser‐
              vice functions need not provide a flush implementation: 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 `in‐
              terrupted'.  Flush must respond to r with a  nil  error  string.
              Flush  may  respond to r before forcing 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, and end are auxiliary functions, not called in
       direct response to 9P requests.

       Destroyfid
              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.

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

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

EXAMPLES
       Archfs(4),  cdfs(4), nntpfs(4), snap(4), and /sys/src/lib9p/ramfs.c are
       good examples of simple single-threaded  file  servers.   Webfs(4)  and
       sshnet (see ssh(1)) are good examples of multithreaded file servers.

       In general, the File interface is appropriate for maintaining 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 structured (as in cdfs  and  nntpfs)  or  is  maintained
       elsewhere.

SOURCE
       /sys/src/lib9p

SEE ALSO
       9pfid(2), 9pfile(2), srv(3), intro(5)

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.



                                                                         9P(2)