man(1) Manual page archive


     9P(2)                                                       9P(2)

     NAME
          Fid, File, Req, Srv, Tree, allocmap, allocfid, allocfidpool,
          allocreq, allocreqpool, caninsertkey, closefid, deletekey,
          fcreate, freefid, freemap, freereq, fremove, fwalk, mktree,
          fdirread, insertkey, lookupfid, lookupkey, lookupreq, srv,
          postmountsrv, readbuf, readstr, respond, threadpostmountsrv,
          _lib9p_emalloc, _lib9p_erealloc, _lib9p_estrdup - 9P file
          server functions

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

          typedef struct Fid
          {
              ulong fid;
              char  omode;/* -1 if not open */
              char  uid[NAMELEN];
              Qid   qid;
              File  *file;
              Ref   ref;
              void  *aux;
              ...
          } Fid;

          typedef struct Req
          {
              ulong tag;
              Ref   ref;
              void  *aux;
              ...
          } Req;

          typedef struct File
          {
                   Dir;
                   File*parent;
                   Refref;
                   void*aux;
                   ...
          } File;

          typedef struct Tree
          {
                   File*root;
                   void(*rmaux)(File *file);

     9P(2)                                                       9P(2)

                   ...
          } Tree;

          Tree* mktree(char *uid, char *gid, ulong perm)
          File* fcreate(File *dir, char *name, char *uid, char *gid, ulong perm)
          int   fremove(File *file)
          void  fclose(File *file)
          File* fwalk(File *file, char *name)
          char* fdirread(File *dir, char *buf, long *n, vlong off)

          typedef struct Srv {
              Tree *tree;
              void (*session)(Req *req, char *id, char *dom, char *chal);
              void (*attach)(Req *req, Fid *fid, char *spec, Qid *qid);
              void (*clone) (Req *req, Fid *old, Fid *new);
              void (*walk)  (Req *req, Fid *fid, char *name, Qid *qid);
              void (*open)  (Req *req, Fid *fid, int omode, Qid *qid);
              void (*create)(Req *req, Fid *fid, char *name, int omode,
                                ulong perm, Qid *qid);
              void (*remove)(Req *req, Fid *fid);
              void (*read)  (Req *req, Fid *fid, void *buf,
                                long *count, vlong offset);
              void (*write) (Req *req, Fid *fid, void *buf,
                                long *count, vlong offset);
              void (*stat)  (Req *req, Fid *fid, Dir *d);
              void (*wstat) (Req *req, Fid *fid, Dir *d);
              void (*flush) (Req *req, Req *oldreq);
              void (*clunkaux)(Fid *fid);
          } Srv;

          void  srv(Srv *s, int fd)
          void  postmountsrv(Srv *s, char *srvname, char *mtpt, int flag)
          void  threadpostmountsrv(Srv *s, char *srvname, char *mtpt, int flag)
          void  respond(Req *req, char *error)
          void  readstr(vlong offset, void *dst, long *ndst, char *src)
          void  readbuf(vlong offset, void *dst, long *ndst, void *src, long nsrc)

          void* _lib9p_emalloc(ulong sz)
          void* _lib9p_erealloc(void *ptr, ulong newsz)
          char* _lib9p_estrdup(char *str)

          Intmap*  allocmap(void (*inc)(void*))
          void     freemap(Intmap *map)
          void*    lookupkey(Intmap *map, ulong key)
          void*    insertkey(Intmap *map, ulong key, void *val)
          int      caninsertkey(Intmap *map, ulong key, void *val)
          void*    deletekey(Intmap *map, ulong key)

          Fidpool* allocfidpool(void)
          void     freefidpool(Fidpool *p)
          Fid*     allocfid(Fidpool *p, ulong f)
          void     freefid(Fid *f)

     9P(2)                                                       9P(2)

          void     closefid(Fid *f)
          Fid*     lookupfid(Fidpool *p, ulong f)

          Reqpool* allocreqpool(void)
          void     freereqpool(Reqpool *p)
          Req*     allocreq(Reqpool *p, ulong tag)
          void     freereq(Req *r)
          void     closereq(Req *r)
          Req*     lookupreq(Reqpool *p, ulong tag)

     DESCRIPTION
          These routines provide a library for writing 9P file
          servers.

          Fid data structures are allocated one-to-one with active
          fids in the served 9P connection.  They are analogous to
          Chan structures in the Plan 9 kernel.  The fid element is
          the integer fid used in the 9P connection.  Omode is the
          mode under which the fid was opened, or -1 if this fid has
          not been opened yet.  Note that in addition to the values
          OREAD, OWRITE, and ORDWR, omode can contain the various
          flags permissible in an open call.  To ignore the flags, use
          omode&OMASK.  Omode should not be changed by the client.
          Uid contains the name of the user who has authenticated in
          order to obtain this fid.  Qid is set to the last qid
          returned by an attach, walk, or open function (q.v.).  The
          file element is explained below.  The aux element belongs to
          the client, and may be used to store a per-Fid data pointer.

          Req data structures are allocated one-to-one with outstand-
          ing 9P requests.  They contain the tag of the request as
          well as an aux element that may be used by the client to
          store a per-Req data pointer (often useful for multithreaded
          servers).

          The File and Tree structures provide an in-memory file hier-
          archy that can be used to handle stat, walk, and open
          requests.  If being used, the library will keep the Fid's
          file element pointing at the appropriate File structure as
          it is walked over the tree.  As with the other structures,
          the aux element may be used by the client to store a
          per-File data pointer.

          The Fid, File, and Req structures are garbage collected by
          reference counting, so that (for example) clunking a fid
          will not free it while another request using that fid is
          still pending.

          When creating a new reference by copying a pointer, the
          count should be incremented with incref. When a Fid is col-
          lected, the clunkaux function of the Srv structure
          (described below) is called to collect the pointer stored in

     9P(2)                                                       9P(2)

          aux.  Similarly, when a File is collected, the rmaux func-
          tion in the Tree structure is called to claim the aux
          pointer.  No such function is called when collecting a Req
          structure: the aux pointer should be removed before calling
          respond (described below).  To destroy a reference to a Fid,
          File, or Req, call closefid, fclose, or closereq, respec-
          tively.

          Mktree creates a new file tree whose root has owner uid,
          group gid, and permissions perm.  It returns a reference to
          that file.  Fcreate creates and returns a reference to a new
          file called name in the directory dir.  The file is owned by
          user uid, group gid, and has permissions perm.  If a file of
          the same name already exists in the directory, fcreate
          returns zero.  Otherwise it returns a pointer to the newly
          created File structure.  Fremove removes file from its
          directory.  If file is itself a directory that is not empty
          or is the root, it is not removed, and fremove returns -1.
          Otherwise fremove returns zero.  If removing the file from
          its directory causes the reference count to go to zero, the
          file is collected and rmaux is called.  Fwalk returns a new
          reference to the File named name in the directory dir.  If
          no such file exists, it returns zero.  It does not decrement
          dir's reference count.  Fdirread fills buf with at most n
          bytes of entries from the directory dir beginning at offset
          offset.  Note that the use of file trees is not required; it
          is provided as a convenience.

          To start a file server, one must fill in a Srv structure
          with pointers to the functions satisfying 9P requests.  As
          explained below, in almost all cases, using a nil function
          pointer results in sensible default behavior.  If the tree
          pointer is non-zero, that file tree is used as described
          below.  Calling srv with such a structure and a file
          descriptor causes it to serve 9P on that file descriptor.
          It does not return until the 9P conversation terminates.  In
          contrast, postmountsrv forks off a 9P server and returns.
          Before returning, if srvname is not zero, the service is
          posted in /srv/srvname (see srv(3)). If mtpt is not zero,
          the service is mounted at mtpt with mount flag flag.
          Threadpostmountsrv is similar but intended for use in pro-
          grams that use the thread(2) library for process creation.

          The functions registered in the Srv structure must conform
          to the following requirements.  The first argument of each
          function is a pointer to a Req that provides context to the
          library for responding to the request.  If a function is
          provided, it must arrange for respond to be called when the
          request is satisfied.  The first argument to respond should
          be the Req pointer; the second is an error string.  If the
          request was satisfied successfully, the error string should
          be a nil pointer.  Note that it is permissible for a

     9P(2)                                                       9P(2)

          function to return without calling respond, as long as it
          has arranged for respond to be called at some point in the
          future, perhaps by another proc sharing its address space,
          but see the discussion of flush below.  Once respond has
          been called, the function's pointer arguments must not be
          dereferenced, as they may point at freed memory.

          If the library 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), it will reply with
          an error without consulting any of the registered functions.

          The session function should fill id, dom, and chal with the
          authentication id and domain of the server, and a challenge,
          as described in attach(5). Before calling session, the
          library zeros these fields.  Leaving any or all of them zero
          is permissible.  Session may be nil, indicating no authenti-
          cation information.

          The attach function should check authentication information
          if desired, and fill in qid with the qid of the file system
          root.  Attach may be nil only if file trees are being used,
          in which case the qid will be filled in from the tree, and
          no authentication will be done.

          When a fid is cloned, the library simply copies the aux
          pointer from the old Fid to create the new one.  If further
          processing is desired, a non-nil clone function will be
          called after this copying has been done.  A typical use of
          this function might be to increment a reference count in the
          structure pointed at by aux.

          If file trees are being used, the 9P server will react to a
          walk message by attempting to walk the Fid's file.  If this
          fails, a ``file not found'' error is sent back.  Otherwise
          the Fid's file and qid elements are updated.  If file trees
          are in use, the walk function is never called.  If file
          trees are not in use, a walk function must be provided.

          Clwalk messages are translated by the library into a clone
          followed (when successful) by a walk; the library's client
          need not worry about them.

          If file trees are being used, the file metadata will be con-
          sulted on open, create, and remove to see if the requester
          has the appropriate permissions.  If not, an error will be
          sent back without calling a registered function.

          If file trees are not in use or the user has the appropriate
          permissions, open is called with the fid being opened, the
          open mode, and a pointer to a qid to be filled in.  The qid
          defaults to the one stored in the fid structure.  If file

     9P(2)                                                       9P(2)

          trees are not in use, an open function must be provided.

          The create function is passed the fid for the current direc-
          tory, as well as the name, mode, and permissions for the
          file to be created.  It must fill in the qid on success, and
          must allocate the new File with fcreate when file trees are
          in use.  Note that the create function must allow for the
          possibility of fcreate returning nil.  If create is nil, a
          ``creation disallowed'' error will be sent instead.

          The remove function is called on a request to remove the
          file associated with a Fid.  If using file trees, remove
          must call fremove itself.  If remove is nil, a ``remove dis-
          allowed'' error will be sent instead.  The library correctly
          detects 9P requests on removed files (via other fid refer-
          ences), and returns appropriate errors.

          The read function must be provided; it fills buf with at
          most *n bytes of data from offset offset of the file.  It
          also sets *n to the number of bytes being returned.  If
          using file trees, the library will handle reads of directo-
          ries: read will only be called for requests on files.
          Readstr and readbuf are useful for satisfying read requests
          on a string or buffer.

          The write function is similar, but need not be provided: a
          ``write disallowed'' message will be sent if write is nil.
          Otherwise, write should attempt to write the *n bytes of buf
          to offset offset of the file, leaving in *n the number of
          bytes actually written.

          The stat function should fill in dir with the stat info for
          fid.  If using file trees, dir will be initialized with the
          stat info from the tree, and stat itself may be nil.

          The wstat function takes a fid and a new Dir structure for
          it, as well as a bitmask specifying which fields to update.
          Other fields in the Dir structure should be ignored.  If
          using file trees and wstat is successful, the corresponding
          file's Dir structure will be updated.  It is permissible for
          wstat to be nil, in which case all wstats will fail with the
          error message ``wstat disallowed''.

          The flush function is called to cancel the outstanding
          request oldreq.  In single-threaded servers, it is safe to
          not supply such a function.  In multithreaded servers, the
          client must guarantee that once respond has been called for
          req, respond will not be called for oldreq.

          The actual 9P service loop provided by srv (and indirectly
          by postmountsrv and threadpostmountsrv) is a single thread
          of execution.  If it is expected that some requests might

     9P(2)                                                       9P(2)

          block, arranging for alternate processes is suggested.

        Implementation
          The rest of the text of this manual page describes the
          structures used to implement the library.  This is useful
          for some applications, but most users need not concern them-
          selves with it.

          The library uses internally the functions _lib9p_emalloc,
          _lib9p_erealloc, and _lib9p_estrdup, which are like malloc,
          realloc, and strdup, but call abort(2) rather than returning
          zero on error.  If alternate behavior is desired, one can
          link against replacements for all three.

          An Intmap is a arbitrary mapping from integers to pointers.
          Allocmap creates a new one, and freemap destroys it.  New
          entries are added to the map by calling insertkey, which
          will return the previous value associated with the given id,
          or zero if there was no previous value.  Before inserting
          the value, the inc function used when creating the map is
          called with the new value; typically this increments a ref-
          erence count to reflect the creation of the new reference
          held by the map.  Caninsertkey is similar, but only inserts
          the entry if no entry for id already exists.  It returns 1
          if the entry was inserted, and 0 otherwise.  Lookupkey
          returns the pointer associated with id, or zero if there is
          no such pointer.  As with the insertion routines, inc is
          called on the pointer before it is returned.  The reference
          count must be incremented by these routines rather than
          their callers to avoid the entry being deleted between func-
          tion return and reference increment.  Deletekey removes the
          entry for id from the map, returning the associated pointer,
          if any.

          Intmaps are used to implement Fidpools and Reqpools, which
          are allocation pools for Fids and Reqs.  Allocfidpool cre-
          ates a new fid pool, and freefidpool destroys one.  Allocfid
          returns a reference to a new Fid structure with identifier
          f.  If a structure with that identifier has already been
          allocated, allocfid returns zero.  Closefid destroys a ref-
          erence to a Fid but leaves it allocated.  Freefid deallo-
          cates a Fid and destroys the passed reference.  When the
          reference count goes to zero, clunkaux will be called on
          that particular Fid structure.  Lookupfid returns a refer-
          ence to the Fid structure identified with f, or zero if
          there is no such structure.

          Allocreqpool, freereqpool, allocreq, closereq, freereq, and
          lookupreq behave similarly, manipulating request pools.

     EXAMPLES
          The file servers archfs(4), cdfs(4), snap(4), and aux/olefs

     9P(2)                                                       9P(2)

          (see doc2txt(1)) are examples of simple single-threaded file
          servers written using this library.  Unlike the others, cdfs
          does not use the File interface but instead creates its
          directory entries on the fly.

     SOURCE
          /sys/src/lib9p

     SEE ALSO
          srv(3), intro(5)

     BUGS
          The library is new and not particularly well exercised; send
          bug reports to rsc@plan9.bell-labs.com.