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



NAME
       Srv,  dirread9p,  emalloc9p,  erealloc9p, estrdup9p, listensrv, postfd,
       postmountsrv, postsharesrv, readbuf,  readstr,  respond,  responderror,
       srvacquire,  srvrelease,  threadlistensrv,  threadpostmountsrv, thread‐
       postsharesrv, 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  (*start)(Srv *s);
           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  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)
       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  srvrelease(Srv *s)
       void  srvacquire(Srv *s)

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

       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  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 (see 9pqueue(2)).

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

       Start  This  gets called (from the forked service process) prior enter‐
              ing 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 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), 9pqueue(2), srv(3), shr(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)