summaryrefslogtreecommitdiff
path: root/man/10/styxserver
diff options
context:
space:
mode:
Diffstat (limited to 'man/10/styxserver')
-rw-r--r--man/10/styxserver611
1 files changed, 611 insertions, 0 deletions
diff --git a/man/10/styxserver b/man/10/styxserver
new file mode 100644
index 00000000..d0a8d321
--- /dev/null
+++ b/man/10/styxserver
@@ -0,0 +1,611 @@
+.TH STYXSERVER 10.2
+.SH NAME
+Styxserver \- C Styx server library
+.SH SYNOPSIS
+.EX
+#define Qroot 0
+
+#define MSGMAX ((((8192+128)*2)+3) & ~3)
+
+extern char Enomem[]; /* out of memory */
+extern char Eperm[]; /* permission denied */
+extern char Enodev[]; /* no free devices */
+extern char Ehungup[]; /* i/o on hungup channel */
+extern char Eexist[]; /* file exists */
+extern char Enonexist[]; /* file does not exist */
+extern char Ebadcmd[]; /* bad command */
+extern char Ebadarg[]; /* bad arguments */
+
+typedef uvlong Path;
+typedef struct Styxserver Styxserver;
+typedef struct Styxops Styxops;
+typedef struct Styxfile Styxfile;
+typedef struct Client Client;
+
+struct Styxserver
+{
+ Styxops *ops;
+ Path qidgen;
+ int connfd;
+ Client *clients;
+ Client *curc;
+ Styxfile *root;
+ Styxfile **ftab;
+ void *priv; /* private */
+};
+
+struct Client
+{
+ Styxserver *server;
+ Client *next;
+ int fd;
+ char msg[MSGMAX];
+ uint nread; /* valid bytes in msg (including nc)*/
+ int nc; /* bytes consumed from front of msg by convM2S */
+ char data[MSGMAX]; /* Tread/Rread data */
+ int state;
+ Fid *fids;
+ char *uname; /* uid */
+ char *aname; /* attach name */
+ void *u;
+};
+
+struct Styxops
+{
+ char *(*newclient)(Client *c);
+ char *(*freeclient)(Client *c);
+
+ char *(*attach)(char *uname, char *aname);
+ char *(*walk)(Qid *qid, char *name);
+ char *(*open)(Qid *qid, int mode);
+ char *(*create)(Qid *qid, char *name, int perm, int mode);
+ char *(*read)(Qid qid, char *buf, ulong *n, vlong offset);
+ char *(*write)(Qid qid, char *buf, ulong *n, vlong offset);
+ char *(*close)(Qid qid, int mode);
+ char *(*remove)(Qid qid);
+ char *(*stat)(Qid qid, Dir *d);
+ char *(*wstat)(Qid qid, Dir *d);
+};
+
+struct Styxfile
+{
+ Dir d;
+ Styxfile *parent;
+ Styxfile *child;
+ Styxfile *sibling;
+ Styxfile *next;
+ int ref;
+ int open;
+ void *u;
+};
+
+char *styxinit(Styxserver *server, Styxops *ops, char *port, int perm, int needfile);
+char *styxwait(Styxserver *server);
+char *styxprocess(Styxserver *server);
+char *styxend(Styxserver *server);
+
+Client *styxclient(Styxserver *server);
+
+Styxfile *styxaddfile(Styxserver *server, Path pqid, Path qid, char *name,
+ int mode, char *owner);
+Styxfile *styxadddir(Styxserver *server, Path pqid, Path qid, char *name,
+ int mode, char *owner);
+int styxrmfile(Styxserver *server, Path qid);
+Styxfile *styxfindfile(Styxserver *server, Path qid);
+
+int styxperm(Styxfile *file, char *uid, int mode);
+long styxreadstr(ulong off, char *buf, ulong n, char *str);
+Qid styxqid(int path, int isdir);
+void *styxmalloc(int bytes);
+void styxfree(void *p);
+void styxdebug(void);
+.EE
+.SH DESCRIPTION
+The C Styx server library provides a small suite of functions to enable the
+production of a file server based on the Inferno Styx protocol. The following
+elements define the primary routines in the interface:
+.TP
+.BI styxinit(server\fP,\fP\ ops\fP,\fP\ port\fP,\fP\ perm\fP,\fP\ needfile )
+Initializes the interface given a pointer to a Styxserver structure
+.I server
+, a callback table of operations
+.I ops
+, a port number
+.I port
+to announce the file service on
+and the permissions
+.I perm
+on the root directory. The default permission is 0555 (read and execute for user,
+group and others) if the latter is specified as -1. If the last argument
+.I needfile
+is set to true, the styx library will check that each path number it deals with
+has a corresponding file associated with it and, if it hasn't, it will issue a
+"file does not exist" message automatically. In case of an error, the error message is
+returned, otherwise nil is returned to indicate success.
+.TP
+.BI styxwait(server )
+Waits for communication from a client. Return value as above.
+.TP
+.BI styxprocess(server )
+Processes the client message after a successful call to
+.I styxwait .
+This may result in calls to the functions in the table provided to
+.I styxinit .
+Return value as above.
+.TP
+.BI styxend(server )
+End all file service. Return value as above.
+.TP
+.BI styxclient(server )
+Returns the client whose request is currently being processed.
+.PP
+The next set of functions allow the creation of a file system structure based
+upon the
+.I Styxfile
+structure. This contains a Dir structure
+.I d
+describing the properties of the file
+(defined in lib9.h) and pointers to other files in the file tree:
+.I parent
+,
+.I child
+,
+.I sibling
+and
+.I next .
+The
+.I ref
+field
+counts current references to the file. The
+.I open
+field counts the current number of opens on the file. Finally the
+.I u
+field allows further fields to be tagged onto each file. It is not
+used by the Styx server library.
+.PP
+Each file must have a unique path number in the server. The root of
+the tree
+.I Qroot
+always has path number zero. It's corresponding file is created during library initialization
+and placed in the
+.I root
+field of the server structure. All other files must be supplied with a path number
+to identify them. Files are created/deleted as follows:
+.TP
+.BI styxaddfile(server\fP,\fP\ ppath\fP,\fP\ path\fP,\fP\ name\fP,\fP\ mode\fP,\fP\ owner )
+Add a new file (ie non-directory) with the given path
+.I path
+, name
+.I name
+, mode
+.I mode
+and owner
+.I owner
+to the directory identified by the path
+.I ppath .
+If
+.I path
+is -1 the library will generate a unique path number instead.
+Returns nil if the parent file with path
+.I ppath
+does not exist, if the parent is not a directory, if the path number
+.I path
+already is assigned to a file or if the parent already contains a file of name
+.I name .
+.TP
+.BI styxadddir(server\fP,\fP\ ppath\fP,\fP\ path\fP,\fP\ name\fP,\fP\ mode\fP,\fP\ owner )
+Add a new directory with the given path
+.I path
+, name
+.I name
+, mode
+.I mode
+and owner
+.I owner
+to the directory identified by the path
+.I ppath .
+Returns nil in the same circumstances as
+.I styxaddfile .
+.TP
+.BI styxrmfile(server\fP,\fP\ path )
+Remove the file or directory with path
+.I path
+from the file server tree. If the file is a directory, it's contents will be recursively
+removed. If the file does not exist, -1 is returned, otherwise 0 is returned for
+success.
+.TP
+.BI styxfindfile(server\fP,\fP\ path )
+Return the file structure corresponding to the file or directory with path
+.I path .
+Nil is returned if the file does not exist.
+.PP
+If the file system is created in this way the Styx library will check read/write/execute
+permissions, check for invalid uses of files and check that path numbers exist
+in the file system (see
+.I styxinit
+for the latter). If it's not feasible to do this (for instance if there is a more suitable
+way of describing the file system in question), then all file checking must be
+done as part of the callback functions below.
+.PP
+The library provides a callback mechanism so that the implementer of the
+file server can take corresponding action when a particular request is made
+of the server. All of these functions may return an error message which will
+be communicated back to the client. Otherwise they should return nil to
+indicate the success of the operation. Any of these functions may be nil in which case the library
+performs a default operation which will be described below. These routines use
+the
+.I Qid
+structure defined in lib9.h to describe files. This structure contains the path number(
+.I path
+), a version number(
+.I vers
+) typically zero and a type(
+.I type
+) which indicates whether the file is a directory, append-only etc.
+.TP
+.BI newclient(c )
+Called whenever a new client connects to the server. The Client structure
+.I c
+contains mainly private data but the
+.I uname
+field contains a user name and the
+.I aname
+field an attach name if required. The
+.I u
+field may be used to tag further data onto each client. It is not used by
+the Styx server library.
+.TP
+.BI freeclient(c )
+Called whenever a client disconnects from the server.
+.TP
+.BI attach(uname\fP,\fP\ aname )
+Called when a client user first mounts the file server. The
+.I uname
+is the user id and
+.I aname
+is typically the file tree to access if the server provides a choice.
+The default action is to allow the attach to the root of the file system.
+.TP
+.BI walk(qid\fP,\fP\ name )
+In a directory represented by
+.I qid
+, find a file member whose name is that given and place it's Qid in
+.I qid .
+The default action is to perform the walk using any directory structure provided.
+.TP
+.BI open(qid\fP,\fP\ mode )
+Open the file represented by
+.I qid
+with mode
+.I mode .
+The latter may be one of OREAD, OWRITE, ORDWR etc (see lib9.h). If the Qid
+of the newly opened file is different from that given (a file server may understand
+the opening of a file called "new" say to signify the creation of a directory whose
+Qid is returned instead) place it's Qid in
+.I qid .
+The default action is to nominally allow the open.
+.TP
+.BI create(qid\fP,\fP\ name\fP,\fP\ perm\fP,\fP\ mode )
+Create a file in the directory given by
+.I qid
+with name
+.I name
+, permissions
+.I perm
+and mode
+.I mode .
+Place the Qid of the newly created file in
+.I qid .
+The default action is to issue a permission denied message.
+.TP
+.BI read(qid\fP,\fP\ buf\fP,\fP\ n\fP,\fP\ offset )
+Read
+.I n
+bytes of the file represented by
+.I qid
+at offset
+.I offset
+and place the result in
+.I buf.
+ Place in
+.I n
+the actual number of bytes read.
+The default action is to read directories but to issue permission denied on ordinary
+files.
+.TP
+.BI write(qid\fP,\fP\ buf\fP,\fP\ n\fP,\fP\ offset )
+Write
+.I n
+bytes to the file represented by
+.I qid
+at offset
+.I offset
+from the buffer
+.I buf.
+ Place in
+.I n
+the actual number of bytes written.
+The default action is to issue permission denied.
+.TP
+.BI close(qid\fP,\fP\ mode )
+Close the file represented by
+.I qid .
+The mode it was originally opened with is given by
+.I mode .
+The default action is to allow the close.
+.TP
+.BI remove(qid )
+Remove the file represented by
+.I qid .
+The default action is to issue a permission denied message.
+.TP
+.BI stat(qid\fP,\fP\ d )
+Place the information for the file represented by
+.I qid
+in the Dir structure(see lib9.h)
+.I d .
+The default action is to allow the stat using any information in the file tree.
+.TP
+.BI wstat(qid\fP,\fP\ d )
+Update the information for the file represented by
+.I qid
+according to the Dir structure
+.I d .
+The default action is to disallow this with a permission denied message.
+.PP
+A small number of utility functions are provided:
+.TP
+.BI styxperm(file\fP,\fP\ uid\fP,\fP\ mode )
+Does the file/directory
+.I file
+allow the user
+.I uid
+the permission given by
+.I mode .
+For example use
+.I OREAD
+for read permission,
+.I OWRITE
+for write permission and
+.I ORDWR
+for both.
+.TP
+.BI styxreadstr(off\fP,\fP\ buf\fP,\fP\ n\fP,\fP\ str )
+Read
+.I n
+bytes of data from the string
+.I str
+at offset
+.I off
+and place the result in
+.I buf .
+Returns the actual number of bytes read.
+.TP
+.BI styxqid(path\fP,\fP\ isdir )
+Returns a typical Qid structure with the given path number
+.I path
+and whether the Qid is for a directory
+.I isdir .
+.TP
+.BI styxmalloc(n )
+Allocate
+.I n
+bytes of memory and return it.
+.TP
+.BI styxfree(p )
+Free the memory pointed to by
+.I p .
+.TP
+.BI styxdebug()
+Print out some of the actions of the server.
+.SH EXAMPLE
+.PP
+A very small file server example is illustrated. First the include files and globals.
+.PP
+.EX
+ #include <lib9.h>
+ #include "styxserver.h"
+
+ int nq;
+ Styxserver *server;
+.EE
+.PP
+The main processing loop:
+.PP
+.EX
+ main(int argc, char **argv)
+ {
+ Styxserver s;
+
+ server = &s;
+ styxinit(&s, &ops, "6701", 100, 0555, 0);
+ myinit(&s);
+ for(;;) {
+ styxwait(&s);
+ styxprocess(&s);
+ }
+ return 0;
+ }
+.EE
+.PP
+Here the port number is 6701 and the root file permissions are 0555 - no write
+permission for anyone which implies that files and directories cannot be
+created in the root directory.
+.PP
+The creation of the directory tree:
+.PP
+.EX
+ myinit(Styxserver *s)
+ {
+ styxaddfile(s, Qroot, 1, "fred", 0664, "inferno");
+ styxaddfile(s, Qroot, 2, "joe", 0664, "inferno");
+ styxadddir(s, Qroot, 3, "adir", 0775, "inferno");
+ styxaddfile(s, 3, 4, "bill", 0664, "inferno");
+ styxadddir(s, Qroot, 5, "new", 0775, "inferno");
+ styxadddir(s, 5, 6, "cdir", 0775, "inferno");
+ styxaddfile(s, 6, 7, "cfile", 0664, "inferno");
+ nq = 8;
+ }
+.EE
+.PP
+This creates two files
+.I fred
+and
+.I joe
+and two directories
+.I adir
+and
+.I new
+at the top level.
+.I adir
+contains a file called
+.I bill
+and
+.I new
+contains a directory called
+.I cdir
+which contains a file called
+.I cfile .
+Note that each new path number is unique.
+.PP
+The callback functions:
+.PP
+.EX
+ Styxops ops = {
+ nil, /* newclient */
+ nil, /* freeclient */
+
+ nil, /* attach */
+ nil, /* walk */
+ nil, /* open */
+ mycreate, /* create */
+ myread, /* read */
+ nil, /* write */
+ nil, /* close */
+ myremove, /* remove */
+ nil, /* stat */
+ nil, /* wstat */
+ };
+.EE
+.PP
+Here we choose the defaults most of the time.
+.PP
+The supplied callback routines:
+.PP
+.EX
+ char *
+ mycreate(Qid *qid, char *name, int perm, int mode)
+ {
+ int isdir;
+ Styxfile *f;
+
+ isdir = perm&DMDIR;
+ if(isdir)
+ f = styxadddir(server, qid->path, nq++, name , perm, "inferno");
+ else
+ f = styxaddfile(server, qid->path, nq++, name, perm, "inferno");
+ if(f == nil)
+ return Eexist;
+ *qid = f->d.qid;
+ return nil;
+ }
+
+ char *
+ myremove(Qid qid)
+ {
+ Styxfile *f;
+
+ f = styxfindfile(server, qid.path);
+ if(f != nil && (f->d.qid.type&QTDIR) && f->child != nil)
+ return "directory not empty";
+
+ if(styxrmfile(server, qid.path) < 0)
+ return Enonexist;
+ return nil;
+ }
+
+ char *
+ myread(Qid qid, char *d, ulong *n, vlong offset)
+ {
+ if(qid.path != 1){
+ *n = 0;
+ return nil;
+ }
+ *n = styxreadstr(offset, d, *n, "abcdeghijklmn");
+ return nil;
+ }
+.EE
+.PP
+Permission checking for walk (need execute permission on directory), open (the
+given mode must be compatible with the file permissions), create and remove (both of
+which need write permission on directory) is done automatically whenever
+possible. The functions
+.I mycreate
+and
+.I myremove
+below therefore can omit these checks.
+.PP
+The function
+.I mycreate
+simply creates a directory or file and
+if the file cannot be added to the directory tree it returns a 'file exists' error string.
+It sets the Qid for the newly created file before returning.
+.PP
+The function
+.I myremove
+first checks to see if the file represents a non-empty directory, in which case it
+disallows it's removal. Otherwise it
+removes the file if it can find it and returns a 'file does not exist' error string if it
+can't.
+.PP
+The function
+.I myread
+considers all files to be empty except for
+.I fred
+which notionally contains
+.I abcdefghijklmn .
+Note that the number of bytes read is returned in the argument
+.I n .
+.PP
+Once this file server is running, the root can be accessed by doing for example
+.PP
+.EX
+ mount -A tcp!<address>!6701 /n/remote
+.EE
+.PP
+under Inferno. Here
+.I <address>
+is the address of the machine running the file server (or the loopback address
+127.0.0.1 if it's all on one machine). The
+.I -A
+option is used to prevent authentication which is not supported at the moment.
+Then we can do
+.PP
+.EX
+ cd /n/remote
+ ls
+ adir
+ fred
+ joe
+ new
+ ...
+.EE
+.PP
+For a more complicated file server see /tools/styxtest/styxtest.c.
+.PP
+The file /tools/styxtest/mkfile shows how to compile and link the file server
+sources.
+.SH SOURCE
+.B /Nt/386/include/lib9.h
+.br
+.B /tools/libstyx/styxserver.h
+.br
+.B /tools/libstyx/styxserver.c
+.br
+.B /tools/styxtest/styxtest.c
+.br
+.B /tools/styxtest/styxtest0.c
+.SH BUGS
+Currently the library is available under Windows, Linux and Solaris only.
+.br
+Authentication is not supported.