Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages


home | help
9P(3)			   Library Functions Manual			 9P(3)

       Srv, dirread9p, emalloc9p, erealloc9p, estrdup9p, postfd, postmountsrv,
       readbuf,	readstr, respond, srv, threadpostmountsrv, walkandclone	 -  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;
	   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)
       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)

       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

       Req  and	 Fid  structures are allocated one-to-one with uncompleted re-
       quests and active fids, and are described in

       The behavior of srv depends on whether there is a file tree (see	 asso-
       ciated  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 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 or procrfork (see using the RFFDG,  RF-
	      NAMEG, 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

   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.

       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 end and then

       Auth   If authentication	is desired, the	auth  function	should	record
	      that  afid  is  the new authentication fid and set 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

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

       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-> with
	      at most r->ifcall.count bytes of data from offset	r->
	      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->  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->	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(9p).  When using file  trees,  srv  will  take
	      care  to	check  that the	request	satisfies the permissions out-
	      lined in stat(9p).  Otherwise wstat should take care to  enforce
	      permissions 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.

	      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 outstanding pointers to
	      it have been closed), destroyreq is called to allow the  program
	      to dispose of the	r->aux pointer.

       Start  Before  the 9P service loop begins, the service proc calls start
	      so that the server can run any initialization that must be  done
	      from inside the service proc.

       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

       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

       /src/lib9p/ramfs.c is an	 example  of  a	 simple	 single-threaded  file
       server.	 On  Plan  9,  see archfs, cdfs, nntpfs, webfs,	and sshnet for
       more examples.

       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





Want to link to this manual page? Use this URL:

home | help