|  | 
 NAME     
 |  |  |  | Srv, dirread9p, emalloc9p, erealloc9p, estrdup9p, postfd, postmountsrv,
    readbuf, readstr, respond, srv, threadpostmountsrv, walkandclone
    – 9P file service 
 | 
 SYNOPSIS     
 |  |  |  | #include <u.h> #include <libc.h>
 #include <fcall.h>
 #include <thread.h>
 #include <9p.h>
 typedef struct Srv {
 
 } 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;
 
 | 
 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),
 
 void* emalloc9p(ulong n)|  |  |  | |  |  |  | char *(*clone)(Fid *old, Fid *new, void *v), void *v) 
 | 
 | 
 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
    requests and active fids, and are described in 9p-fid(3). 
    
    
    The behavior of srv depends on whether there is a file tree (see
    9p-file(3)) 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 functions. 
    
    
    Postmountsrv and threadpostmountsrv are wrappers that create a
    separate process in which to run srv. They do the following: 
 If any error occurs during this process, the entire process is
    terminated by calling sysfatal(3).|  |  |  | 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(3) or procrfork (see thread(3)),
        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, ""); otherwise,
        close s−>srvfd.
 The parent returns to the caller.
 | 
 
 Service functions    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
    constraints are checked while the server executes. If a service
    function fails to do something it ought to have, srv will call
    end and then abort.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 corresponding
    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 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 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 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.
 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 arg(3)).
    AttachThe 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.
 
 Walk1, Clone|  |  |  | 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 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 increment
        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.
 
 | 
 
 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.|  |  |  | 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. 
 | 
 CreateThe 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
    
    
    Remove
 
 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|  |  |  | should mark the file as removed, whether by calling removefile
        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. | 
 Write   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
    
    
    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.|  |  |  | 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 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. 
 | 
 WstatThe 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 outlined
    in stat(9p). Otherwise wstat should take care to enforce permissions
    where appropriate.
 Flush   Servers that always call respond before returning from the
    service 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
 Destroyfid, destroyreq, start, and end are auxiliary functions,
    not called in direct response to 9P requests.|  |  |  | respond on oldreq with error string ‘interrupted’. 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|  |  |  | 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. 
 | 
 
 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.|  |  |  | 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
 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.|  |  |  | unmounted. After calling end, the service loop (which runs in
        a separate process from its caller) terminates using _exits (see
        exits(3)). | 
 
 | 
 EXAMPLES     
 |  |  |  | /usr/lib/plan9/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 elsewhere. 
 | 
 SOURCE     
 SEE ALSO    
 |  |