[Userfs-commits]
rev 2 - in trunk: . kernel kernel/linux kernel/src kernel/src/linux
genser utils br lib filesystems filesystems/tarfs filesystems/yfs
filesystems/ftpfs filesystems/intfs filesystems/cvsfs
filesystems/gvfs filesystems/homer filesystems/mailfs
filesystems/example filesystems/arcfs
manish at oss.oracle.com
manish at oss.oracle.com
Thu May 29 10:40:47 CDT 2003
Author: manish
Date: 2003-05-29 04:40:42 -0500 (Thu, 29 May 2003)
New Revision: 2
Added:
trunk/ANNOUNCE
trunk/COPYING
trunk/Changelog
trunk/Makefile
trunk/README.gnome-vfs
trunk/README.mjm
trunk/README.mm
trunk/README.ps
trunk/TODO
trunk/br/
trunk/br/br.c
trunk/filesystems/
trunk/filesystems/README
trunk/filesystems/arcfs/
trunk/filesystems/arcfs/Makefile
trunk/filesystems/arcfs/README
trunk/filesystems/arcfs/arcfs.c
trunk/filesystems/arcfs/arcfs.h
trunk/filesystems/arcfs/arcvfs.c
trunk/filesystems/arcfs/arcvfs.h
trunk/filesystems/arcfs/tgz.c
trunk/filesystems/arcfs/zip.c
trunk/filesystems/cvsfs/
trunk/filesystems/cvsfs/Makefile
trunk/filesystems/cvsfs/README
trunk/filesystems/cvsfs/cvs.c
trunk/filesystems/cvsfs/cvs.h
trunk/filesystems/cvsfs/cvsdir.c
trunk/filesystems/cvsfs/cvsdir.h
trunk/filesystems/cvsfs/cvsfs.c
trunk/filesystems/cvsfs/cvstree.c
trunk/filesystems/cvsfs/cvstree.h
trunk/filesystems/example/
trunk/filesystems/example/Makefile
trunk/filesystems/example/egdir.cc
trunk/filesystems/example/egdir.h
trunk/filesystems/example/egfile.cc
trunk/filesystems/example/egfile.h
trunk/filesystems/example/egfs.cc
trunk/filesystems/example/egfs.h
trunk/filesystems/ftpfs/
trunk/filesystems/ftpfs/ConfFile.cc
trunk/filesystems/ftpfs/ConfFile.h
trunk/filesystems/ftpfs/Makefile
trunk/filesystems/ftpfs/Path.cc
trunk/filesystems/ftpfs/Path.h
trunk/filesystems/ftpfs/README
trunk/filesystems/ftpfs/conninfo.cc
trunk/filesystems/ftpfs/conninfo.h
trunk/filesystems/ftpfs/dir.cc
trunk/filesystems/ftpfs/dir.h
trunk/filesystems/ftpfs/dos_host.cc
trunk/filesystems/ftpfs/dos_host.h
trunk/filesystems/ftpfs/ftpconn.cc
trunk/filesystems/ftpfs/ftpconn.h
trunk/filesystems/ftpfs/ftpdir.cc
trunk/filesystems/ftpfs/ftpdir.h
trunk/filesystems/ftpfs/ftpfile.cc
trunk/filesystems/ftpfs/ftpfile.h
trunk/filesystems/ftpfs/ftpfs.cc
trunk/filesystems/ftpfs/ftpfs.h
trunk/filesystems/ftpfs/ftplink.cc
trunk/filesystems/ftpfs/ftplink.h
trunk/filesystems/ftpfs/getdate.h
trunk/filesystems/ftpfs/getdate.y
trunk/filesystems/ftpfs/host.cc
trunk/filesystems/ftpfs/host.h
trunk/filesystems/ftpfs/ino.cc
trunk/filesystems/ftpfs/ino.h
trunk/filesystems/ftpfs/netsys.h
trunk/filesystems/ftpfs/nonblk_io.cc
trunk/filesystems/ftpfs/pushd.cc
trunk/filesystems/ftpfs/pushd.h
trunk/filesystems/ftpfs/reap.pl
trunk/filesystems/ftpfs/serv_port.cc
trunk/filesystems/ftpfs/serv_port.h
trunk/filesystems/ftpfs/sitetopdir.cc
trunk/filesystems/ftpfs/sitetopdir.h
trunk/filesystems/ftpfs/topdir.cc
trunk/filesystems/ftpfs/topdir.h
trunk/filesystems/ftpfs/unix_host.cc
trunk/filesystems/ftpfs/unix_host.h
trunk/filesystems/ftpfs/vms_host.h
trunk/filesystems/gvfs/
trunk/filesystems/gvfs/Makefile
trunk/filesystems/gvfs/gvfs.h
trunk/filesystems/gvfs/gvfsops.c
trunk/filesystems/gvfs/vfsbase.c
trunk/filesystems/gvfs/vfsbase.h
trunk/filesystems/homer/
trunk/filesystems/homer/Makefile
trunk/filesystems/homer/homer.cc
trunk/filesystems/homer/homer.h
trunk/filesystems/homer/password.cc
trunk/filesystems/intfs/
trunk/filesystems/intfs/Makefile
trunk/filesystems/intfs/README
trunk/filesystems/intfs/intfs.cc
trunk/filesystems/intfs/intfs.h
trunk/filesystems/intfs/intfsDirIno.cc
trunk/filesystems/intfs/intfsDirIno.h
trunk/filesystems/intfs/intfsFifoDir.cc
trunk/filesystems/intfs/intfsFifoDir.h
trunk/filesystems/intfs/intfsFifoIno.cc
trunk/filesystems/intfs/intfsFifoIno.h
trunk/filesystems/intfs/intfsIno.cc
trunk/filesystems/intfs/intfsIno.h
trunk/filesystems/intfs/intfsLinkIno.cc
trunk/filesystems/intfs/intfsLinkIno.h
trunk/filesystems/intfs/pushd.cc
trunk/filesystems/intfs/pushd.h
trunk/filesystems/mailfs/
trunk/filesystems/mailfs/Makefile
trunk/filesystems/mailfs/README
trunk/filesystems/mailfs/TODO
trunk/filesystems/mailfs/mail.cc
trunk/filesystems/mailfs/mail.h
trunk/filesystems/mailfs/maildir.cc
trunk/filesystems/mailfs/maildir.h
trunk/filesystems/mailfs/mailfile.cc
trunk/filesystems/mailfs/mailfile.h
trunk/filesystems/mailfs/mailfs.1
trunk/filesystems/mailfs/mailfs.cc
trunk/filesystems/mailfs/mailfs.h
trunk/filesystems/mailfs/maillink.cc
trunk/filesystems/mailfs/maillink.h
trunk/filesystems/tarfs/
trunk/filesystems/tarfs/Makefile
trunk/filesystems/tarfs/README
trunk/filesystems/tarfs/rt.c
trunk/filesystems/tarfs/tarfs.c
trunk/filesystems/tarfs/tarfs.h
trunk/filesystems/tarfs/tarvfs.c
trunk/filesystems/tarfs/tarvfs.h
trunk/filesystems/yfs/
trunk/filesystems/yfs/Makefile
trunk/filesystems/yfs/yfs.c
trunk/genser/
trunk/genser/Makefile
trunk/genser/README
trunk/genser/coder.h
trunk/genser/com.h
trunk/genser/format.c
trunk/genser/format.h
trunk/genser/gencode.c
trunk/genser/genhdr.c
trunk/genser/lexer.l
trunk/genser/misc.c
trunk/genser/misc.h
trunk/genser/parser.y
trunk/genser/symtab.c
trunk/genser/symtab.h
trunk/kernel/
trunk/kernel/Makefile
trunk/kernel/linux/
trunk/kernel/linux/Makefile
trunk/kernel/linux/assert.h
trunk/kernel/linux/coder.h
trunk/kernel/linux/userfs_fs.h
trunk/kernel/linux/userfs_fs_f.h
trunk/kernel/linux/userfs_fs_i.h
trunk/kernel/linux/userfs_fs_sb.h
trunk/kernel/linux/userfs_mount.h
trunk/kernel/linux/userfs_types.c
trunk/kernel/linux/userfs_types.h
trunk/kernel/src/
trunk/kernel/src/Makefile
trunk/kernel/src/file.c
trunk/kernel/src/inode.c
trunk/kernel/src/linux/
trunk/kernel/src/linux/userfs_fs.h
trunk/kernel/src/linux/userfs_fs_f.h
trunk/kernel/src/linux/userfs_fs_i.h
trunk/kernel/src/linux/userfs_fs_sb.h
trunk/kernel/src/linux/userfs_mount.h
trunk/kernel/src/linux/userfs_types.c
trunk/kernel/src/linux/userfs_types.h
trunk/kernel/src/module.c
trunk/kernel/src/super.c
trunk/kernel/src/uio.c
trunk/kernel/src/userfs.h
trunk/kernel/src/userfs_types.c
trunk/kernel/src/userfs_types.h
trunk/kernel/src/userfs_types.ty
trunk/kernel/types.h
trunk/lib/
trunk/lib/Comm.cc
trunk/lib/Comm.h
trunk/lib/CommBase.cc
trunk/lib/CommBase.h
trunk/lib/DeferComm.cc
trunk/lib/DeferComm.h
trunk/lib/DeferFilesys.cc
trunk/lib/DeferFilesys.h
trunk/lib/DirInode.cc
trunk/lib/DirInode.h
trunk/lib/Filesystem.h
trunk/lib/Filesystem.p
trunk/lib/Inode.cc
trunk/lib/Inode.p
trunk/lib/Makefile
trunk/lib/README
trunk/lib/SimpleInode.h
trunk/lib/ThreadComm.cc
trunk/lib/ThreadComm.h
trunk/lib/coder.h
trunk/lib/dbg.h
trunk/lib/operations.h
trunk/rules
trunk/rules.sub
trunk/utils/
trunk/utils/Makefile
trunk/utils/io.c
trunk/utils/io.h
trunk/utils/muserfs.c
trunk/utils/opnames.h
trunk/utils/um.c
trunk/utils/userfs_types.c
Log:
initial import
Added: trunk/README.mjm
==============================================================================
--- trunk/README.mjm 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/README.mjm 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,181 @@
+Mon 3 May 1999
+
+cvsfs: Added ability to delete checked out versions properly, so that the
+repository version won't show up in it's place.
+
+cvsfs: need to find a way to checkout files in place.
+
+userfs: added lib and contrib directories back into the package.
+Modified Inode.cc so that is doesn't include fs.h with __KERNEL__
+Modified genser to parse the function prototype that was upsetting
+it in posix_types.h. Removed lwp and its C++ wrapper.
+Moved all the filesystem programs into the same directory.
+
+Mike
+
+Sat 1 May 1999
+
+Fixed bug in cvsfs.c - the truncate code was incorrect.
+Implemented do_notify_change() function.
+
+Fixed a bug in the original code that was causing the module
+to crash when the userfs_sleep function was used. This was generally
+when more than one process was using the user file system at
+a time. eg.
+
+$ cd test
+$ cp /zImage-990430 . & cp /zImage-990421 .
+
+To solve this, in uio.c#kissone(), the line lp->bed=NULL was commented out.
+
+Other bugs (fixed other days):
+* included cache update when writing to files
+* fixed append mode when writing to files
+* notify_change should must truncate to the requied size if the file
+ size is changed.
+
+TODO List:
+* make cvsfs more efficient. This could envolve tighter integration with the
+ filesystem... perhaps enter the real inodes from the checkout directory
+ into the directory entries for the cvsfs file system, so that accesses to
+ real files go directly to the underlying filesystem instead of through
+ cvsfs.
+
+Mike
+
+-------------------------------------------------------------
+
+Wed 28 April 1999
+
+Well, Jeremy was right, the port to 2.6.6 has turned out to
+take alot of effort. Today i've almost got cvsfs working, but
+am still having trouble reading/writing files after renaming.
+This is the same problems as i was having below, but it is fixed
+for the case of creation of new files now.
+
+CVSfs will be cool if i can get it to work :-)
+
+Mike
+
+------------------------------------------------------------
+
+Monday 26 April 1999
+
+Hello! Silly me, i forgot to set the userfs file handle in create also.
+Why do we need to keep two copies of the handle anyhow? Still trying to
+figure out why create doesn't work.
+
+Found out why create doesn't work. In lookup, you must create a dentry
+and add it to the parent directory even if the lookup is unsuccessful.
+This is necessary for the kernel to be able to create the file.
+
+Similarly for mkdir. i have changed around the userfs_create
+userfs_mknod and userfs_mkdir functions to all user the do_create fn.
+
+Now the write function doesn't seem to be working, but i'm tired so i'm
+going to bed.
+
+Mike
+
+--------------------------------------------------------------
+
+Sunday 25 April 1999
+
+Fixed a couple of major bugs, and changed the way things work a little.
+I had forgotted to malloc memory for userfs_inode_info, and the code
+was using who-knows-what memory to store the inode information. Every so
+often, this would make the kernel cause an exception... notably after running
+"du" on a userfs filesystem a couple of times.
+
+So... because mallocs make me uneasy (especially in the kernel) i have updated
+the userfs code to store its extra inode info in the end of the inode struct,
+in the space reserved for filesystem code to store its information. This is
+good, but we've got be sure that there's enough room there for our data. To
+make sure, i've added a check in the install_module code. (It should really
+be done at compile time though.)
+
+For some reason i haven't figured yet, i can't create files in my userfs
+filesystems. (or directories either.)
+
+-------------------------------------------------------------
+
+Hello,
+
+i forgot to mention that to compile userfs you may need to comment
+out the following line in /usr/include/linux/posis_types.h:
+
+/* typedef void (*__kernel_sighandler_t)(int); */
+
+This is because the genser program cannot deal with function pointers.
+(i think). Anyway, it hasn't cause any trouble since i've commented it
+out, so i'm going to leave it that way until i could be bothered to
+modify the code to genser to handle it. (or somebody beats me to it.)
+
+I've added a few userfs file systems to the tar:
+
+tarfs: reads a tar file (not through a process) and creates a filesystem
+ from the contents
+yfs: a simple mirror file system (read only)
+cvsfs: display the contents of a CVS repositry in a filesystem. Hopefully
+ after a bit of work i can make it so that you can compile in place
+ without checking out the source tree... sound familiar to anybody ;-)
+
+Fixed the following bugs with the 2.2.6 version:
+* when writing to a file, use the "off" pointer
+* in do_userfs_write, use copy_from_user, not copy_to_user
+* when deleting an inode, d_delete entry must be called.
+
+24 April 1999
+
+Mike
+
+--------------------------------------------------------------------
+Hello Again,
+
+enough work for tonight!
+
+i've found (and hopefully corrected) the following problems:
+
+1) need to check both tokern and fromkern (struct file *) are not NULL
+ in uio.c in userfs_close_channel. The new kernel must be doing something
+ different with the pipe handles.
+2) tgz.c was not compatable with the tar on my system and wouldn't
+ read the tar file index properly. Adjusted the fields in index reader.
+ (i've got GNU tar 1.12)
+
+Now userfs/Linux 2.2.6 seems to work with arcfs for read access to zip and
+tar files.
+
+Things still to do:
+* check that the other functions work (eg. writing, links, etc)
+* go through with a fine tooth comb and check if there's any SMP or
+ other danger spots, memory leaks or other nasties.
+
+Mike
+
+23 Apr 1999
+
+btw. i forgot to mention that you should define __SMP__ in the makefile if
+you have a SMP system, and only if you have a SMP system. (that one took
+me a while to figure out ;-)
+
+--------------------------------------------------------------------------
+Hi,
+
+currently this code doesn't work! i am half way through modifying the userfs
+module to work with the linux 2.2.6 kernel. It compiles, but don't be
+deceived by this... it will crash your system if you use it as it stands!
+
+Things to do:
+* use the handles in the correct manner, including correct use of dput
+* lock kernel/file handles in appropriate spots
+
+Please send any updates to
+Michael.McCormack at alcatel.com.au or mccormack at ozemail.com.au
+
+regards
+
+Mike McCormack
+
+Shanghai, China 22 Apr 1999 (yes i read my mail in Australia from here)
+
Added: trunk/kernel/linux/userfs_mount.h
==============================================================================
--- trunk/kernel/linux/userfs_mount.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/kernel/linux/userfs_mount.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,30 @@
+/*
+ * Information passed from user process to the kernel as the
+ * 3rd argument to mount(2).
+ */
+
+#ifndef _LINUX_USERFS_MOUNT
+#define _LINUX_USERFS_MOUNT
+
+/*
+ * WARNING! Do not delete or change the order of these fields. If
+ * a new field is required then add it to the end. The version field
+ * tracks which fields are present. This will ensure some measure of
+ * mount-to-kernel version compatibilty. Some of these aren't used yet
+ * but here they are anyway.
+ */
+
+/* Change this if things are added to the structure below */
+#define USERFS_VERSION 3
+
+
+struct userfs_mount
+{
+ int version; /* v1 - version of structure */
+ int tokern; /* v1 - fd of stream into the kernel */
+ int fromkern; /* v1 - from kernel */
+ int magic; /* v2 - magic */
+ int seq; /* v3 - initial sequence number */
+};
+
+#endif /* _LINUX_USERFS_MOUNT */
Added: trunk/kernel/linux/userfs_types.h
==============================================================================
--- trunk/kernel/linux/userfs_types.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/kernel/linux/userfs_types.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,894 @@
+/* -*- C -*-
+ * DO NOT EDIT BY HAND!
+ *
+ * This was automatically generated from "userfs_types.ty" by genhdr.
+ */
+#ifndef __USERFS_TYPES_H_SEEN__
+#define __USERFS_TYPES_H_SEEN__
+
+#ifndef __KERNEL__
+#include <asm/posix_types.h>
+#include <asm/types.h>
+typedef __kernel_suseconds_t suseconds_t;
+typedef __u8 uint8_t;
+typedef __u16 uint16_t;
+typedef __u32 uint32_t;
+#undef __FD_ZERO
+#undef __FD_SET
+#undef __FD_CLR
+#undef __FD_ISSET
+#endif
+#if !defined(ALLOC)
+# if defined(__KERNEL__)
+# include <linux/slab.h>
+# include <linux/mm.h>
+# include <linux/assert.h>
+# define ALLOC(x) kmalloc(x, GFP_KERNEL)
+# define FREE(x) kfree(x)
+# else
+# define ALLOC ALLOC
+# include <assert.h>
+# include <stdlib.h>
+#ifdef __GLIBC__
+#include <time.h>
+#include <malloc.h>
+typedef unsigned char unchar;
+#endif
+static __inline__ void *ALLOC(int alloc)
+{
+ void *mem = malloc(alloc);
+
+ assert(mem != 0);
+ return mem;
+}
+#define FREE(x) free(x)
+# endif /* __KERNEL__ */
+#endif /* ALLOC */
+#include <linux/types.h>
+#include <linux/userfs_fs_i.h>
+#include <linux/userfs_fs_f.h>
+#define UP_REPL 0 /* Is a reply */
+#define UP_REQ 1 /* Is a request */
+#define UP_ENQ 2 /* Is capability enquiry */
+#ifndef _NO_CODER_H_
+/* Type encode/decode routines */
+#include "coder.h" /* Standard routines */
+#endif /* _NO_CODER_H_ */
+/* Encoded types */
+
+typedef Ulong _userfs_types_001[32];
+typedef long _userfs_types_002[2];
+typedef Ulong _userfs_types_003[32];
+typedef ushort uf_uid_t;
+typedef ushort uf_gid_t;
+typedef ushort uf_nlink_t;
+typedef ushort uf_dev_t;
+typedef struct
+{
+ Ulong nelem;
+ long* elems;
+} _userfs_types_004;
+typedef struct
+{
+ uf_uid_t uid;
+ uf_uid_t euid;
+ uf_uid_t suid;
+ uf_uid_t gid;
+ uf_uid_t egid;
+ uf_uid_t sgid;
+ uf_uid_t umask;
+ _userfs_types_004 groups;
+} up_cred;
+typedef struct
+{
+ Ulong ia_valid;
+ umode_t ia_mode;
+ uf_uid_t ia_uid;
+ uf_gid_t ia_gid;
+ off_t ia_size;
+ time_t ia_atime;
+ time_t ia_mtime;
+ time_t ia_ctime;
+} up_iattr;
+typedef struct
+{
+ __s16 version;
+ long seq;
+ Uchar op;
+ Uchar isreq;
+ Ulong size;
+} up_preamble;
+typedef struct
+{
+ __s16 version;
+ long seq;
+ Uchar op;
+ Uchar isreq;
+ Ulong size;
+ long err_no;
+} upp_repl;
+typedef struct
+{
+ umode_t mode;
+ uf_nlink_t nlink;
+ uf_uid_t uid;
+ uf_gid_t gid;
+ off_t size;
+ time_t atime;
+ time_t mtime;
+ time_t ctime;
+ uf_dev_t rdev;
+ Ulong blksize;
+ Ulong blocks;
+} up_inode;
+typedef struct
+{
+ Ulong nelem;
+ __s8* elems;
+} up_name;
+typedef struct
+{
+ up_inode ino;
+ up_handle handle;
+} upp_iwrite_s;
+typedef struct
+{
+ up_handle handle;
+} upp_iread_s;
+typedef struct
+{
+ up_handle handle;
+ up_inode ino;
+} upp_iread_r;
+typedef struct
+{
+ up_handle dir;
+ up_name name;
+} upp_unlink_s;
+typedef struct
+{
+ up_handle link;
+} upp_readlink_s;
+typedef struct
+{
+ up_name name;
+} upp_readlink_r;
+typedef struct
+{
+ up_handle dir;
+ up_handle link;
+ long flag;
+ long mode;
+} upp_followlink_s;
+typedef struct
+{
+ up_name path;
+} upp_followlink_r;
+typedef struct
+{
+ Ulong nelem;
+ long* elems;
+} _userfs_types_005;
+typedef struct
+{
+ long mode;
+ up_handle dir;
+ up_cred cred;
+ long rdev;
+ up_name name;
+} upp_create_s;
+typedef struct
+{
+ up_handle file;
+} upp_create_r;
+typedef struct
+{
+ up_handle dir;
+ up_name name;
+} upp_lookup_s;
+typedef struct
+{
+ up_handle handle;
+} upp_lookup_r;
+typedef struct
+{
+ up_handle file;
+ off_t off;
+ off_t size;
+ up_credtok ctok;
+} upp_read_s;
+typedef struct
+{
+ Ulong nelem;
+ Uchar* elems;
+} _userfs_types_006;
+typedef struct
+{
+ _userfs_types_006 data;
+} upp_read_r;
+typedef struct
+{
+ Ulong nelem;
+ Uchar* elems;
+} _userfs_types_007;
+typedef struct
+{
+ up_handle file;
+ off_t off;
+ up_credtok ctok;
+ _userfs_types_007 data;
+} upp_write_s;
+typedef struct
+{
+ off_t wrote;
+} upp_write_r;
+typedef struct
+{
+ up_handle dir;
+ off_t off;
+ up_credtok ctok;
+} upp_readdir_s;
+typedef struct
+{
+ up_handle file;
+ off_t off;
+ up_name name;
+} upp_readdir_r;
+typedef upp_readdir_s upp_multireaddir_s;
+typedef struct
+{
+ Ulong nelem;
+ upp_readdir_r* elems;
+} upp_multireaddir_r;
+typedef struct
+{
+ up_handle root;
+} upp_mount_r;
+typedef struct
+{
+ up_handle handle;
+} upp_iput_s;
+typedef struct
+{
+ Ulong nelem;
+ long* elems;
+} _userfs_types_008;
+typedef struct
+{
+ up_cred cred;
+ up_handle file;
+} upp_open_s;
+typedef struct
+{
+ up_credtok ctok;
+} upp_open_r;
+typedef struct
+{
+ up_handle file;
+ up_credtok ctok;
+} upp_close_s;
+typedef struct
+{
+ Ulong nelem;
+ long* elems;
+} _userfs_types_009;
+typedef struct
+{
+ up_cred cred;
+ up_handle file;
+ long mask;
+} upp_permission_s;
+typedef struct
+{
+ up_handle odir;
+ up_name oname;
+ up_handle ndir;
+ up_name nname;
+} upp_rename_s;
+typedef struct
+{
+ up_handle ofile;
+ up_handle dir;
+ up_name name;
+} upp_link_s;
+typedef struct
+{
+ Ulong nelem;
+ long* elems;
+} _userfs_types_010;
+typedef struct
+{
+ up_handle dir;
+ up_name name;
+ up_name symname;
+ up_cred cred;
+} upp_symlink_s;
+typedef long _userfs_types_011[2];
+typedef struct
+{
+ __kernel_off_t bsize;
+ __kernel_off_t blocks;
+ __kernel_off_t bfree;
+ __kernel_off_t bavail;
+ __kernel_off_t files;
+ __kernel_off_t ffree;
+ _userfs_types_011 fsid;
+ __kernel_off_t namelen;
+} upp_statfs_r;
+typedef struct
+{
+ up_handle file;
+ off_t size;
+} upp_truncate_s;
+typedef struct
+{
+ up_handle handle;
+ up_iattr iattr;
+} upp_notify_change_s;
+typedef struct
+{
+ up_handle handle;
+ up_version version;
+} upp_inode_valid_s;
+typedef struct
+{
+ up_version version;
+ __s8 valid;
+} upp_inode_valid_r;
+static unsigned char *encode_char(const char *, unsigned char *);
+static unsigned char *decode_char(char *, unsigned char *);
+static unsigned int sizeof_char(const char *);
+
+static unsigned char *encode_short(const short *, unsigned char *);
+static unsigned char *decode_short(short *, unsigned char *);
+static unsigned int sizeof_short(const short *);
+
+static unsigned char *encode_long(const long *, unsigned char *);
+static unsigned char *decode_long(long *, unsigned char *);
+static unsigned int sizeof_long(const long *);
+
+static unsigned char *encode_longlong(const longlong *, unsigned char *);
+static unsigned char *decode_longlong(longlong *, unsigned char *);
+static unsigned int sizeof_longlong(const longlong *);
+
+static unsigned char *encode_float(const float *, unsigned char *);
+static unsigned char *decode_float(float *, unsigned char *);
+static unsigned int sizeof_float(const float *);
+
+static unsigned char *encode_double(const double *, unsigned char *);
+static unsigned char *decode_double(double *, unsigned char *);
+static unsigned int sizeof_double(const double *);
+
+static unsigned char *encode_void(const void *, unsigned char *);
+static unsigned char *decode_void(void *, unsigned char *);
+static unsigned int sizeof_void(const void *);
+
+static unsigned char *encode_Uchar(const Uchar *, unsigned char *);
+static unsigned char *decode_Uchar(Uchar *, unsigned char *);
+static unsigned int sizeof_Uchar(const Uchar *);
+
+static unsigned char *encode_Ushort(const Ushort *, unsigned char *);
+static unsigned char *decode_Ushort(Ushort *, unsigned char *);
+static unsigned int sizeof_Ushort(const Ushort *);
+
+static unsigned char *encode_Ulong(const Ulong *, unsigned char *);
+static unsigned char *decode_Ulong(Ulong *, unsigned char *);
+static unsigned int sizeof_Ulong(const Ulong *);
+
+static unsigned char *encode_Ulonglong(const Ulonglong *, unsigned char *);
+static unsigned char *decode_Ulonglong(Ulonglong *, unsigned char *);
+static unsigned int sizeof_Ulonglong(const Ulonglong *);
+
+unsigned char *encode_Uint(const Uint *, unsigned char *);
+unsigned char *decode_Uint(Uint *, unsigned char *);
+unsigned int sizeof_Uint(const Uint *);
+
+unsigned char *encode_int(const int *, unsigned char *);
+unsigned char *decode_int(int *, unsigned char *);
+unsigned int sizeof_int(const int *);
+
+unsigned char *encode__userfs_types_001(const _userfs_types_001 *, unsigned char *);
+unsigned char *decode__userfs_types_001(_userfs_types_001 *, unsigned char *);
+unsigned int sizeof__userfs_types_001(const _userfs_types_001 *);
+
+unsigned char *encode___kernel_fd_set(const __kernel_fd_set *, unsigned char *);
+unsigned char *decode___kernel_fd_set(__kernel_fd_set *, unsigned char *);
+unsigned int sizeof___kernel_fd_set(const __kernel_fd_set *);
+
+unsigned char *encode___kernel_key_t(const __kernel_key_t *, unsigned char *);
+unsigned char *decode___kernel_key_t(__kernel_key_t *, unsigned char *);
+unsigned int sizeof___kernel_key_t(const __kernel_key_t *);
+
+unsigned char *encode___kernel_dev_t(const __kernel_dev_t *, unsigned char *);
+unsigned char *decode___kernel_dev_t(__kernel_dev_t *, unsigned char *);
+unsigned int sizeof___kernel_dev_t(const __kernel_dev_t *);
+
+unsigned char *encode___kernel_ino_t(const __kernel_ino_t *, unsigned char *);
+unsigned char *decode___kernel_ino_t(__kernel_ino_t *, unsigned char *);
+unsigned int sizeof___kernel_ino_t(const __kernel_ino_t *);
+
+unsigned char *encode___kernel_mode_t(const __kernel_mode_t *, unsigned char *);
+unsigned char *decode___kernel_mode_t(__kernel_mode_t *, unsigned char *);
+unsigned int sizeof___kernel_mode_t(const __kernel_mode_t *);
+
+unsigned char *encode___kernel_nlink_t(const __kernel_nlink_t *, unsigned char *);
+unsigned char *decode___kernel_nlink_t(__kernel_nlink_t *, unsigned char *);
+unsigned int sizeof___kernel_nlink_t(const __kernel_nlink_t *);
+
+unsigned char *encode___kernel_off_t(const __kernel_off_t *, unsigned char *);
+unsigned char *decode___kernel_off_t(__kernel_off_t *, unsigned char *);
+unsigned int sizeof___kernel_off_t(const __kernel_off_t *);
+
+unsigned char *encode___kernel_pid_t(const __kernel_pid_t *, unsigned char *);
+unsigned char *decode___kernel_pid_t(__kernel_pid_t *, unsigned char *);
+unsigned int sizeof___kernel_pid_t(const __kernel_pid_t *);
+
+unsigned char *encode___kernel_ipc_pid_t(const __kernel_ipc_pid_t *, unsigned char *);
+unsigned char *decode___kernel_ipc_pid_t(__kernel_ipc_pid_t *, unsigned char *);
+unsigned int sizeof___kernel_ipc_pid_t(const __kernel_ipc_pid_t *);
+
+unsigned char *encode___kernel_uid_t(const __kernel_uid_t *, unsigned char *);
+unsigned char *decode___kernel_uid_t(__kernel_uid_t *, unsigned char *);
+unsigned int sizeof___kernel_uid_t(const __kernel_uid_t *);
+
+unsigned char *encode___kernel_gid_t(const __kernel_gid_t *, unsigned char *);
+unsigned char *decode___kernel_gid_t(__kernel_gid_t *, unsigned char *);
+unsigned int sizeof___kernel_gid_t(const __kernel_gid_t *);
+
+unsigned char *encode___kernel_size_t(const __kernel_size_t *, unsigned char *);
+unsigned char *decode___kernel_size_t(__kernel_size_t *, unsigned char *);
+unsigned int sizeof___kernel_size_t(const __kernel_size_t *);
+
+unsigned char *encode___kernel_ssize_t(const __kernel_ssize_t *, unsigned char *);
+unsigned char *decode___kernel_ssize_t(__kernel_ssize_t *, unsigned char *);
+unsigned int sizeof___kernel_ssize_t(const __kernel_ssize_t *);
+
+unsigned char *encode___kernel_ptrdiff_t(const __kernel_ptrdiff_t *, unsigned char *);
+unsigned char *decode___kernel_ptrdiff_t(__kernel_ptrdiff_t *, unsigned char *);
+unsigned int sizeof___kernel_ptrdiff_t(const __kernel_ptrdiff_t *);
+
+unsigned char *encode___kernel_time_t(const __kernel_time_t *, unsigned char *);
+unsigned char *decode___kernel_time_t(__kernel_time_t *, unsigned char *);
+unsigned int sizeof___kernel_time_t(const __kernel_time_t *);
+
+unsigned char *encode___kernel_suseconds_t(const __kernel_suseconds_t *, unsigned char *);
+unsigned char *decode___kernel_suseconds_t(__kernel_suseconds_t *, unsigned char *);
+unsigned int sizeof___kernel_suseconds_t(const __kernel_suseconds_t *);
+
+unsigned char *encode___kernel_clock_t(const __kernel_clock_t *, unsigned char *);
+unsigned char *decode___kernel_clock_t(__kernel_clock_t *, unsigned char *);
+unsigned int sizeof___kernel_clock_t(const __kernel_clock_t *);
+
+unsigned char *encode___kernel_daddr_t(const __kernel_daddr_t *, unsigned char *);
+unsigned char *decode___kernel_daddr_t(__kernel_daddr_t *, unsigned char *);
+unsigned int sizeof___kernel_daddr_t(const __kernel_daddr_t *);
+
+unsigned char *encode___kernel_caddr_t(const __kernel_caddr_t *, unsigned char *);
+unsigned char *decode___kernel_caddr_t(__kernel_caddr_t *, unsigned char *);
+unsigned int sizeof___kernel_caddr_t(const __kernel_caddr_t *);
+
+unsigned char *encode___kernel_uid16_t(const __kernel_uid16_t *, unsigned char *);
+unsigned char *decode___kernel_uid16_t(__kernel_uid16_t *, unsigned char *);
+unsigned int sizeof___kernel_uid16_t(const __kernel_uid16_t *);
+
+unsigned char *encode___kernel_gid16_t(const __kernel_gid16_t *, unsigned char *);
+unsigned char *decode___kernel_gid16_t(__kernel_gid16_t *, unsigned char *);
+unsigned int sizeof___kernel_gid16_t(const __kernel_gid16_t *);
+
+unsigned char *encode___kernel_uid32_t(const __kernel_uid32_t *, unsigned char *);
+unsigned char *decode___kernel_uid32_t(__kernel_uid32_t *, unsigned char *);
+unsigned int sizeof___kernel_uid32_t(const __kernel_uid32_t *);
+
+unsigned char *encode___kernel_gid32_t(const __kernel_gid32_t *, unsigned char *);
+unsigned char *decode___kernel_gid32_t(__kernel_gid32_t *, unsigned char *);
+unsigned int sizeof___kernel_gid32_t(const __kernel_gid32_t *);
+
+unsigned char *encode___kernel_old_uid_t(const __kernel_old_uid_t *, unsigned char *);
+unsigned char *decode___kernel_old_uid_t(__kernel_old_uid_t *, unsigned char *);
+unsigned int sizeof___kernel_old_uid_t(const __kernel_old_uid_t *);
+
+unsigned char *encode___kernel_old_gid_t(const __kernel_old_gid_t *, unsigned char *);
+unsigned char *decode___kernel_old_gid_t(__kernel_old_gid_t *, unsigned char *);
+unsigned int sizeof___kernel_old_gid_t(const __kernel_old_gid_t *);
+
+unsigned char *encode__userfs_types_002(const _userfs_types_002 *, unsigned char *);
+unsigned char *decode__userfs_types_002(_userfs_types_002 *, unsigned char *);
+unsigned int sizeof__userfs_types_002(const _userfs_types_002 *);
+
+unsigned char *encode___kernel_fsid_t(const __kernel_fsid_t *, unsigned char *);
+unsigned char *decode___kernel_fsid_t(__kernel_fsid_t *, unsigned char *);
+unsigned int sizeof___kernel_fsid_t(const __kernel_fsid_t *);
+
+unsigned char *encode_umode_t(const umode_t *, unsigned char *);
+unsigned char *decode_umode_t(umode_t *, unsigned char *);
+unsigned int sizeof_umode_t(const umode_t *);
+
+unsigned char *encode___s8(const __s8 *, unsigned char *);
+unsigned char *decode___s8(__s8 *, unsigned char *);
+unsigned int sizeof___s8(const __s8 *);
+
+unsigned char *encode___u8(const __u8 *, unsigned char *);
+unsigned char *decode___u8(__u8 *, unsigned char *);
+unsigned int sizeof___u8(const __u8 *);
+
+unsigned char *encode___s16(const __s16 *, unsigned char *);
+unsigned char *decode___s16(__s16 *, unsigned char *);
+unsigned int sizeof___s16(const __s16 *);
+
+unsigned char *encode___u16(const __u16 *, unsigned char *);
+unsigned char *decode___u16(__u16 *, unsigned char *);
+unsigned int sizeof___u16(const __u16 *);
+
+unsigned char *encode___s32(const __s32 *, unsigned char *);
+unsigned char *decode___s32(__s32 *, unsigned char *);
+unsigned int sizeof___s32(const __s32 *);
+
+unsigned char *encode___u32(const __u32 *, unsigned char *);
+unsigned char *decode___u32(__u32 *, unsigned char *);
+unsigned int sizeof___u32(const __u32 *);
+
+unsigned char *encode__userfs_types_003(const _userfs_types_003 *, unsigned char *);
+unsigned char *decode__userfs_types_003(_userfs_types_003 *, unsigned char *);
+unsigned int sizeof__userfs_types_003(const _userfs_types_003 *);
+
+unsigned char *encode_fd_set(const fd_set *, unsigned char *);
+unsigned char *decode_fd_set(fd_set *, unsigned char *);
+unsigned int sizeof_fd_set(const fd_set *);
+
+unsigned char *encode_dev_t(const dev_t *, unsigned char *);
+unsigned char *decode_dev_t(dev_t *, unsigned char *);
+unsigned int sizeof_dev_t(const dev_t *);
+
+unsigned char *encode_ino_t(const ino_t *, unsigned char *);
+unsigned char *decode_ino_t(ino_t *, unsigned char *);
+unsigned int sizeof_ino_t(const ino_t *);
+
+unsigned char *encode_mode_t(const mode_t *, unsigned char *);
+unsigned char *decode_mode_t(mode_t *, unsigned char *);
+unsigned int sizeof_mode_t(const mode_t *);
+
+unsigned char *encode_nlink_t(const nlink_t *, unsigned char *);
+unsigned char *decode_nlink_t(nlink_t *, unsigned char *);
+unsigned int sizeof_nlink_t(const nlink_t *);
+
+unsigned char *encode_off_t(const off_t *, unsigned char *);
+unsigned char *decode_off_t(off_t *, unsigned char *);
+unsigned int sizeof_off_t(const off_t *);
+
+unsigned char *encode_pid_t(const pid_t *, unsigned char *);
+unsigned char *decode_pid_t(pid_t *, unsigned char *);
+unsigned int sizeof_pid_t(const pid_t *);
+
+unsigned char *encode_daddr_t(const daddr_t *, unsigned char *);
+unsigned char *decode_daddr_t(daddr_t *, unsigned char *);
+unsigned int sizeof_daddr_t(const daddr_t *);
+
+unsigned char *encode_key_t(const key_t *, unsigned char *);
+unsigned char *decode_key_t(key_t *, unsigned char *);
+unsigned int sizeof_key_t(const key_t *);
+
+unsigned char *encode_suseconds_t(const suseconds_t *, unsigned char *);
+unsigned char *decode_suseconds_t(suseconds_t *, unsigned char *);
+unsigned int sizeof_suseconds_t(const suseconds_t *);
+
+unsigned char *encode_uid_t(const uid_t *, unsigned char *);
+unsigned char *decode_uid_t(uid_t *, unsigned char *);
+unsigned int sizeof_uid_t(const uid_t *);
+
+unsigned char *encode_gid_t(const gid_t *, unsigned char *);
+unsigned char *decode_gid_t(gid_t *, unsigned char *);
+unsigned int sizeof_gid_t(const gid_t *);
+
+unsigned char *encode_size_t(const size_t *, unsigned char *);
+unsigned char *decode_size_t(size_t *, unsigned char *);
+unsigned int sizeof_size_t(const size_t *);
+
+unsigned char *encode_ssize_t(const ssize_t *, unsigned char *);
+unsigned char *decode_ssize_t(ssize_t *, unsigned char *);
+unsigned int sizeof_ssize_t(const ssize_t *);
+
+unsigned char *encode_ptrdiff_t(const ptrdiff_t *, unsigned char *);
+unsigned char *decode_ptrdiff_t(ptrdiff_t *, unsigned char *);
+unsigned int sizeof_ptrdiff_t(const ptrdiff_t *);
+
+unsigned char *encode_time_t(const time_t *, unsigned char *);
+unsigned char *decode_time_t(time_t *, unsigned char *);
+unsigned int sizeof_time_t(const time_t *);
+
+unsigned char *encode_clock_t(const clock_t *, unsigned char *);
+unsigned char *decode_clock_t(clock_t *, unsigned char *);
+unsigned int sizeof_clock_t(const clock_t *);
+
+unsigned char *encode_caddr_t(const caddr_t *, unsigned char *);
+unsigned char *decode_caddr_t(caddr_t *, unsigned char *);
+unsigned int sizeof_caddr_t(const caddr_t *);
+
+unsigned char *encode_u_char(const u_char *, unsigned char *);
+unsigned char *decode_u_char(u_char *, unsigned char *);
+unsigned int sizeof_u_char(const u_char *);
+
+unsigned char *encode_u_short(const u_short *, unsigned char *);
+unsigned char *decode_u_short(u_short *, unsigned char *);
+unsigned int sizeof_u_short(const u_short *);
+
+unsigned char *encode_u_int(const u_int *, unsigned char *);
+unsigned char *decode_u_int(u_int *, unsigned char *);
+unsigned int sizeof_u_int(const u_int *);
+
+unsigned char *encode_u_long(const u_long *, unsigned char *);
+unsigned char *decode_u_long(u_long *, unsigned char *);
+unsigned int sizeof_u_long(const u_long *);
+
+unsigned char *encode_unchar(const unchar *, unsigned char *);
+unsigned char *decode_unchar(unchar *, unsigned char *);
+unsigned int sizeof_unchar(const unchar *);
+
+unsigned char *encode_ushort(const ushort *, unsigned char *);
+unsigned char *decode_ushort(ushort *, unsigned char *);
+unsigned int sizeof_ushort(const ushort *);
+
+unsigned char *encode_uint(const uint *, unsigned char *);
+unsigned char *decode_uint(uint *, unsigned char *);
+unsigned int sizeof_uint(const uint *);
+
+unsigned char *encode_ulong(const ulong *, unsigned char *);
+unsigned char *decode_ulong(ulong *, unsigned char *);
+unsigned int sizeof_ulong(const ulong *);
+
+unsigned char *encode_u_int8_t(const u_int8_t *, unsigned char *);
+unsigned char *decode_u_int8_t(u_int8_t *, unsigned char *);
+unsigned int sizeof_u_int8_t(const u_int8_t *);
+
+unsigned char *encode_int8_t(const int8_t *, unsigned char *);
+unsigned char *decode_int8_t(int8_t *, unsigned char *);
+unsigned int sizeof_int8_t(const int8_t *);
+
+unsigned char *encode_u_int16_t(const u_int16_t *, unsigned char *);
+unsigned char *decode_u_int16_t(u_int16_t *, unsigned char *);
+unsigned int sizeof_u_int16_t(const u_int16_t *);
+
+unsigned char *encode_int16_t(const int16_t *, unsigned char *);
+unsigned char *decode_int16_t(int16_t *, unsigned char *);
+unsigned int sizeof_int16_t(const int16_t *);
+
+unsigned char *encode_u_int32_t(const u_int32_t *, unsigned char *);
+unsigned char *decode_u_int32_t(u_int32_t *, unsigned char *);
+unsigned int sizeof_u_int32_t(const u_int32_t *);
+
+unsigned char *encode_int32_t(const int32_t *, unsigned char *);
+unsigned char *decode_int32_t(int32_t *, unsigned char *);
+unsigned int sizeof_int32_t(const int32_t *);
+
+unsigned char *encode_uint8_t(const uint8_t *, unsigned char *);
+unsigned char *decode_uint8_t(uint8_t *, unsigned char *);
+unsigned int sizeof_uint8_t(const uint8_t *);
+
+unsigned char *encode_uint16_t(const uint16_t *, unsigned char *);
+unsigned char *decode_uint16_t(uint16_t *, unsigned char *);
+unsigned int sizeof_uint16_t(const uint16_t *);
+
+unsigned char *encode_uint32_t(const uint32_t *, unsigned char *);
+unsigned char *decode_uint32_t(uint32_t *, unsigned char *);
+unsigned int sizeof_uint32_t(const uint32_t *);
+
+unsigned char *encode_up_handle(const up_handle *, unsigned char *);
+unsigned char *decode_up_handle(up_handle *, unsigned char *);
+unsigned int sizeof_up_handle(const up_handle *);
+
+unsigned char *encode_up_version(const up_version *, unsigned char *);
+unsigned char *decode_up_version(up_version *, unsigned char *);
+unsigned int sizeof_up_version(const up_version *);
+
+unsigned char *encode_up_credtok(const up_credtok *, unsigned char *);
+unsigned char *decode_up_credtok(up_credtok *, unsigned char *);
+unsigned int sizeof_up_credtok(const up_credtok *);
+
+unsigned char *encode_uf_uid_t(const uf_uid_t *, unsigned char *);
+unsigned char *decode_uf_uid_t(uf_uid_t *, unsigned char *);
+unsigned int sizeof_uf_uid_t(const uf_uid_t *);
+
+unsigned char *encode_uf_gid_t(const uf_gid_t *, unsigned char *);
+unsigned char *decode_uf_gid_t(uf_gid_t *, unsigned char *);
+unsigned int sizeof_uf_gid_t(const uf_gid_t *);
+
+unsigned char *encode_uf_nlink_t(const uf_nlink_t *, unsigned char *);
+unsigned char *decode_uf_nlink_t(uf_nlink_t *, unsigned char *);
+unsigned int sizeof_uf_nlink_t(const uf_nlink_t *);
+
+unsigned char *encode_uf_dev_t(const uf_dev_t *, unsigned char *);
+unsigned char *decode_uf_dev_t(uf_dev_t *, unsigned char *);
+unsigned int sizeof_uf_dev_t(const uf_dev_t *);
+
+unsigned char *encode__userfs_types_004(const _userfs_types_004 *, unsigned char *);
+unsigned char *decode__userfs_types_004(_userfs_types_004 *, unsigned char *);
+unsigned int sizeof__userfs_types_004(const _userfs_types_004 *);
+
+unsigned char *encode_up_cred(const up_cred *, unsigned char *);
+unsigned char *decode_up_cred(up_cred *, unsigned char *);
+unsigned int sizeof_up_cred(const up_cred *);
+
+unsigned char *encode_up_iattr(const up_iattr *, unsigned char *);
+unsigned char *decode_up_iattr(up_iattr *, unsigned char *);
+unsigned int sizeof_up_iattr(const up_iattr *);
+
+unsigned char *encode_up_preamble(const up_preamble *, unsigned char *);
+unsigned char *decode_up_preamble(up_preamble *, unsigned char *);
+unsigned int sizeof_up_preamble(const up_preamble *);
+
+unsigned char *encode_upp_repl(const upp_repl *, unsigned char *);
+unsigned char *decode_upp_repl(upp_repl *, unsigned char *);
+unsigned int sizeof_upp_repl(const upp_repl *);
+
+unsigned char *encode_up_inode(const up_inode *, unsigned char *);
+unsigned char *decode_up_inode(up_inode *, unsigned char *);
+unsigned int sizeof_up_inode(const up_inode *);
+
+unsigned char *encode_up_name(const up_name *, unsigned char *);
+unsigned char *decode_up_name(up_name *, unsigned char *);
+unsigned int sizeof_up_name(const up_name *);
+
+unsigned char *encode_upp_iwrite_s(const upp_iwrite_s *, unsigned char *);
+unsigned char *decode_upp_iwrite_s(upp_iwrite_s *, unsigned char *);
+unsigned int sizeof_upp_iwrite_s(const upp_iwrite_s *);
+
+unsigned char *encode_upp_iread_s(const upp_iread_s *, unsigned char *);
+unsigned char *decode_upp_iread_s(upp_iread_s *, unsigned char *);
+unsigned int sizeof_upp_iread_s(const upp_iread_s *);
+
+unsigned char *encode_upp_iread_r(const upp_iread_r *, unsigned char *);
+unsigned char *decode_upp_iread_r(upp_iread_r *, unsigned char *);
+unsigned int sizeof_upp_iread_r(const upp_iread_r *);
+
+unsigned char *encode_upp_unlink_s(const upp_unlink_s *, unsigned char *);
+unsigned char *decode_upp_unlink_s(upp_unlink_s *, unsigned char *);
+unsigned int sizeof_upp_unlink_s(const upp_unlink_s *);
+
+unsigned char *encode_upp_readlink_s(const upp_readlink_s *, unsigned char *);
+unsigned char *decode_upp_readlink_s(upp_readlink_s *, unsigned char *);
+unsigned int sizeof_upp_readlink_s(const upp_readlink_s *);
+
+unsigned char *encode_upp_readlink_r(const upp_readlink_r *, unsigned char *);
+unsigned char *decode_upp_readlink_r(upp_readlink_r *, unsigned char *);
+unsigned int sizeof_upp_readlink_r(const upp_readlink_r *);
+
+unsigned char *encode_upp_followlink_s(const upp_followlink_s *, unsigned char *);
+unsigned char *decode_upp_followlink_s(upp_followlink_s *, unsigned char *);
+unsigned int sizeof_upp_followlink_s(const upp_followlink_s *);
+
+unsigned char *encode_upp_followlink_r(const upp_followlink_r *, unsigned char *);
+unsigned char *decode_upp_followlink_r(upp_followlink_r *, unsigned char *);
+unsigned int sizeof_upp_followlink_r(const upp_followlink_r *);
+
+unsigned char *encode__userfs_types_005(const _userfs_types_005 *, unsigned char *);
+unsigned char *decode__userfs_types_005(_userfs_types_005 *, unsigned char *);
+unsigned int sizeof__userfs_types_005(const _userfs_types_005 *);
+
+unsigned char *encode_upp_create_s(const upp_create_s *, unsigned char *);
+unsigned char *decode_upp_create_s(upp_create_s *, unsigned char *);
+unsigned int sizeof_upp_create_s(const upp_create_s *);
+
+unsigned char *encode_upp_create_r(const upp_create_r *, unsigned char *);
+unsigned char *decode_upp_create_r(upp_create_r *, unsigned char *);
+unsigned int sizeof_upp_create_r(const upp_create_r *);
+
+unsigned char *encode_upp_lookup_s(const upp_lookup_s *, unsigned char *);
+unsigned char *decode_upp_lookup_s(upp_lookup_s *, unsigned char *);
+unsigned int sizeof_upp_lookup_s(const upp_lookup_s *);
+
+unsigned char *encode_upp_lookup_r(const upp_lookup_r *, unsigned char *);
+unsigned char *decode_upp_lookup_r(upp_lookup_r *, unsigned char *);
+unsigned int sizeof_upp_lookup_r(const upp_lookup_r *);
+
+unsigned char *encode_upp_read_s(const upp_read_s *, unsigned char *);
+unsigned char *decode_upp_read_s(upp_read_s *, unsigned char *);
+unsigned int sizeof_upp_read_s(const upp_read_s *);
+
+unsigned char *encode__userfs_types_006(const _userfs_types_006 *, unsigned char *);
+unsigned char *decode__userfs_types_006(_userfs_types_006 *, unsigned char *);
+unsigned int sizeof__userfs_types_006(const _userfs_types_006 *);
+
+unsigned char *encode_upp_read_r(const upp_read_r *, unsigned char *);
+unsigned char *decode_upp_read_r(upp_read_r *, unsigned char *);
+unsigned int sizeof_upp_read_r(const upp_read_r *);
+
+unsigned char *encode__userfs_types_007(const _userfs_types_007 *, unsigned char *);
+unsigned char *decode__userfs_types_007(_userfs_types_007 *, unsigned char *);
+unsigned int sizeof__userfs_types_007(const _userfs_types_007 *);
+
+unsigned char *encode_upp_write_s(const upp_write_s *, unsigned char *);
+unsigned char *decode_upp_write_s(upp_write_s *, unsigned char *);
+unsigned int sizeof_upp_write_s(const upp_write_s *);
+
+unsigned char *encode_upp_write_r(const upp_write_r *, unsigned char *);
+unsigned char *decode_upp_write_r(upp_write_r *, unsigned char *);
+unsigned int sizeof_upp_write_r(const upp_write_r *);
+
+unsigned char *encode_upp_readdir_s(const upp_readdir_s *, unsigned char *);
+unsigned char *decode_upp_readdir_s(upp_readdir_s *, unsigned char *);
+unsigned int sizeof_upp_readdir_s(const upp_readdir_s *);
+
+unsigned char *encode_upp_readdir_r(const upp_readdir_r *, unsigned char *);
+unsigned char *decode_upp_readdir_r(upp_readdir_r *, unsigned char *);
+unsigned int sizeof_upp_readdir_r(const upp_readdir_r *);
+
+unsigned char *encode_upp_multireaddir_s(const upp_multireaddir_s *, unsigned char *);
+unsigned char *decode_upp_multireaddir_s(upp_multireaddir_s *, unsigned char *);
+unsigned int sizeof_upp_multireaddir_s(const upp_multireaddir_s *);
+
+unsigned char *encode_upp_multireaddir_r(const upp_multireaddir_r *, unsigned char *);
+unsigned char *decode_upp_multireaddir_r(upp_multireaddir_r *, unsigned char *);
+unsigned int sizeof_upp_multireaddir_r(const upp_multireaddir_r *);
+
+unsigned char *encode_upp_mount_r(const upp_mount_r *, unsigned char *);
+unsigned char *decode_upp_mount_r(upp_mount_r *, unsigned char *);
+unsigned int sizeof_upp_mount_r(const upp_mount_r *);
+
+unsigned char *encode_upp_iput_s(const upp_iput_s *, unsigned char *);
+unsigned char *decode_upp_iput_s(upp_iput_s *, unsigned char *);
+unsigned int sizeof_upp_iput_s(const upp_iput_s *);
+
+unsigned char *encode__userfs_types_008(const _userfs_types_008 *, unsigned char *);
+unsigned char *decode__userfs_types_008(_userfs_types_008 *, unsigned char *);
+unsigned int sizeof__userfs_types_008(const _userfs_types_008 *);
+
+unsigned char *encode_upp_open_s(const upp_open_s *, unsigned char *);
+unsigned char *decode_upp_open_s(upp_open_s *, unsigned char *);
+unsigned int sizeof_upp_open_s(const upp_open_s *);
+
+unsigned char *encode_upp_open_r(const upp_open_r *, unsigned char *);
+unsigned char *decode_upp_open_r(upp_open_r *, unsigned char *);
+unsigned int sizeof_upp_open_r(const upp_open_r *);
+
+unsigned char *encode_upp_close_s(const upp_close_s *, unsigned char *);
+unsigned char *decode_upp_close_s(upp_close_s *, unsigned char *);
+unsigned int sizeof_upp_close_s(const upp_close_s *);
+
+unsigned char *encode__userfs_types_009(const _userfs_types_009 *, unsigned char *);
+unsigned char *decode__userfs_types_009(_userfs_types_009 *, unsigned char *);
+unsigned int sizeof__userfs_types_009(const _userfs_types_009 *);
+
+unsigned char *encode_upp_permission_s(const upp_permission_s *, unsigned char *);
+unsigned char *decode_upp_permission_s(upp_permission_s *, unsigned char *);
+unsigned int sizeof_upp_permission_s(const upp_permission_s *);
+
+unsigned char *encode_upp_rename_s(const upp_rename_s *, unsigned char *);
+unsigned char *decode_upp_rename_s(upp_rename_s *, unsigned char *);
+unsigned int sizeof_upp_rename_s(const upp_rename_s *);
+
+unsigned char *encode_upp_link_s(const upp_link_s *, unsigned char *);
+unsigned char *decode_upp_link_s(upp_link_s *, unsigned char *);
+unsigned int sizeof_upp_link_s(const upp_link_s *);
+
+unsigned char *encode__userfs_types_010(const _userfs_types_010 *, unsigned char *);
+unsigned char *decode__userfs_types_010(_userfs_types_010 *, unsigned char *);
+unsigned int sizeof__userfs_types_010(const _userfs_types_010 *);
+
+unsigned char *encode_upp_symlink_s(const upp_symlink_s *, unsigned char *);
+unsigned char *decode_upp_symlink_s(upp_symlink_s *, unsigned char *);
+unsigned int sizeof_upp_symlink_s(const upp_symlink_s *);
+
+unsigned char *encode__userfs_types_011(const _userfs_types_011 *, unsigned char *);
+unsigned char *decode__userfs_types_011(_userfs_types_011 *, unsigned char *);
+unsigned int sizeof__userfs_types_011(const _userfs_types_011 *);
+
+unsigned char *encode_upp_statfs_r(const upp_statfs_r *, unsigned char *);
+unsigned char *decode_upp_statfs_r(upp_statfs_r *, unsigned char *);
+unsigned int sizeof_upp_statfs_r(const upp_statfs_r *);
+
+unsigned char *encode_upp_truncate_s(const upp_truncate_s *, unsigned char *);
+unsigned char *decode_upp_truncate_s(upp_truncate_s *, unsigned char *);
+unsigned int sizeof_upp_truncate_s(const upp_truncate_s *);
+
+unsigned char *encode_upp_notify_change_s(const upp_notify_change_s *, unsigned char *);
+unsigned char *decode_upp_notify_change_s(upp_notify_change_s *, unsigned char *);
+unsigned int sizeof_upp_notify_change_s(const upp_notify_change_s *);
+
+unsigned char *encode_upp_inode_valid_s(const upp_inode_valid_s *, unsigned char *);
+unsigned char *decode_upp_inode_valid_s(upp_inode_valid_s *, unsigned char *);
+unsigned int sizeof_upp_inode_valid_s(const upp_inode_valid_s *);
+
+unsigned char *encode_upp_inode_valid_r(const upp_inode_valid_r *, unsigned char *);
+unsigned char *decode_upp_inode_valid_r(upp_inode_valid_r *, unsigned char *);
+unsigned int sizeof_upp_inode_valid_r(const upp_inode_valid_r *);
+
+#endif /* __USERFS_TYPES_H_SEEN__ */
Added: trunk/kernel/linux/coder.h
==============================================================================
--- trunk/kernel/linux/coder.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/kernel/linux/coder.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,283 @@
+/* Base type primitives */
+
+#ifndef __CODER_H_SEEN__
+#define __CODER_H_SEEN__
+
+#ifndef __GNUC__
+#define __inline__ /* */
+#endif
+
+#ifndef __cplusplus
+#ifndef ALLOC
+extern void *malloc(unsigned long);
+extern void free(void *);
+#define ALLOC(s) malloc(s)
+#define FREE(s) free(s)
+#endif /* ALLOC */
+#endif __cplusplus
+
+/* Types we use */
+typedef unsigned char Uchar;
+typedef unsigned short Ushort;
+typedef unsigned long Ulong;
+typedef unsigned long Uint;
+typedef unsigned long long Ulonglong;
+typedef long long longlong;
+
+/** char **/
+__inline__ static unsigned char *encode_char(const char *ch, unsigned char *buf)
+{
+ *buf = *ch;
+ return buf+1;
+}
+
+__inline__ static unsigned char *decode_char(char *ch, unsigned char *buf)
+{
+ *ch = *buf;
+ return buf+1;
+}
+
+__inline__ static unsigned int sizeof_char(const char *c)
+{
+ (void)c;
+ return 1;
+}
+
+/** unsigned char **/
+__inline__ static unsigned char *encode_Uchar(const Uchar *ch, unsigned char *buf)
+{
+ *buf = *ch;
+ return buf+1;
+}
+
+__inline__ static unsigned char *decode_Uchar(Uchar *ch, unsigned char *buf)
+{
+ *ch = *buf;
+ return buf+1;
+}
+
+__inline__ static unsigned int sizeof_Uchar(const Uchar *c)
+{
+ (void)c;
+ return 1;
+}
+
+/** short **/
+__inline__ static unsigned char *encode_short(const short *sh, unsigned char *buf)
+{
+ register short sv = *sh;
+
+ buf[0] = (sv >> 8)& 0xff;
+ buf[1] = sv & 0xff;
+ return buf+2;
+}
+
+__inline__ static unsigned char *decode_short(short *sh, unsigned char *buf)
+{
+ *sh = (buf[0] << 8) | buf[1];
+ return buf+2;
+}
+
+__inline__ static unsigned int sizeof_short(const short *c)
+{
+ (void)c;
+ return 2;
+}
+
+/** unsigned short **/
+__inline__ static unsigned char *encode_Ushort(const Ushort *sh, unsigned char *buf)
+{
+ register Ushort sv = *sh;
+
+ buf[0] = (sv >> 8)& 0xff;
+ buf[1] = sv & 0xff;
+ return buf+2;
+}
+
+__inline__ static unsigned char *decode_Ushort(Ushort *sh, unsigned char *buf)
+{
+ *sh = (buf[0] << 8) | buf[1];
+ return buf+2;
+}
+
+__inline__ static unsigned int sizeof_Ushort(const Ushort *c)
+{
+ (void)c;
+ return 2;
+}
+
+/** long **/
+__inline__ static unsigned char *encode_long(const long *l, unsigned char *buf)
+{
+ register long lv = *l;
+
+ buf[0] = (lv >> 24) & 0xff;
+ buf[1] = (lv >> 16) & 0xff;
+ buf[2] = (lv >> 8) & 0xff;
+ buf[3] = lv & 0xff;
+ return buf+4;
+}
+
+__inline__ static unsigned char *decode_long(long *l, unsigned char *buf)
+{
+ *l = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
+ return buf+4;
+}
+
+__inline__ static unsigned int sizeof_long(const long *c)
+{
+ (void)c;
+ return 4;
+}
+
+/** unsigned long **/
+__inline__ static unsigned char *encode_Ulong(const Ulong *l, unsigned char *buf)
+{
+ register Ulong lv = *l;
+
+ buf[0] = (lv >> 24) & 0xff;
+ buf[1] = (lv >> 16) & 0xff;
+ buf[2] = (lv >> 8) & 0xff;
+ buf[3] = lv & 0xff;
+ return buf+4;
+}
+
+__inline__ static unsigned char *decode_Ulong(Ulong *l, unsigned char *buf)
+{
+ *l = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
+ return buf+4;
+}
+
+__inline__ static unsigned int sizeof_Ulong(const Ulong *c)
+{
+ (void)c;
+ return 4;
+}
+
+/** long long */
+__inline__ static unsigned char *encode_longlong(const long long *l,
+ unsigned char *buf)
+{
+ register long long lv = *l;
+
+ buf[0] = (lv >> 56) & 0xff;
+ buf[1] = (lv >> 48) & 0xff;
+ buf[2] = (lv >> 40) & 0xff;
+ buf[3] = (lv >> 32) & 0xff;
+ buf[4] = (lv >> 24) & 0xff;
+ buf[5] = (lv >> 16) & 0xff;
+ buf[6] = (lv >> 8) & 0xff;
+ buf[7] = lv & 0xff;
+
+ return buf+8;
+}
+
+__inline__ static unsigned char *decode_longlong(long long *l,
+ unsigned char *buf)
+{
+#define BUF(x) ((long long)(buf[x]))
+ *l = (BUF(0) << 56)|(BUF(1) << 48)|(BUF(2) << 40)|(BUF(3) << 32)|
+ (BUF(4) << 24)|(BUF(5) << 16)|(BUF(6) << 8)|BUF(7);
+#undef BUF
+ return buf+8;
+}
+
+__inline__ static unsigned int sizeof_longlong(const long long *c)
+{
+ (void)c;
+ return 8;
+}
+
+/** unsigned long long */
+__inline__ static unsigned char *encode_Ulonglong(const unsigned long long *l,
+ unsigned char *buf)
+{
+ register unsigned long long lv = *l;
+
+ buf[0] = (lv >> 56) & 0xff;
+ buf[1] = (lv >> 48) & 0xff;
+ buf[2] = (lv >> 40) & 0xff;
+ buf[3] = (lv >> 32) & 0xff;
+ buf[4] = (lv >> 24) & 0xff;
+ buf[5] = (lv >> 16) & 0xff;
+ buf[6] = (lv >> 8) & 0xff;
+ buf[7] = lv & 0xff;
+
+ return buf+8;
+}
+
+__inline__ static unsigned char *decode_Ulonglong(unsigned long long *l,
+ unsigned char *buf)
+{
+#define BUF(x) ((unsigned long long)(buf[x]))
+ *l = (BUF(0) << 56)|(BUF(1) << 48)|(BUF(2) << 40)|(BUF(3) << 32)|
+ (BUF(4) << 24)|(BUF(5) << 16)|(BUF(6) << 8)|BUF(7);
+#undef BUF
+ return buf+8;
+}
+
+__inline__ static unsigned int sizeof_Ulonglong(const unsigned long long *c)
+{
+ (void)c;
+ return 8;
+}
+
+/** void **/
+__inline__ static unsigned char *encode_void(const void *v, unsigned char *buf)
+{
+ (void)v;
+ return buf;
+}
+
+__inline__ static unsigned char *decode_void(void *v, unsigned char *buf)
+{
+ (void)v;
+ return buf;
+}
+
+__inline__ static unsigned int sizeof_void(const void *c)
+{
+ (void)c;
+ return 0;
+}
+
+/* Assuming this host has IEEE 754 floats, this is all OK */
+/** float **/
+__inline__ static unsigned char *encode_float(const float *f, unsigned char *buf)
+{
+ *(float *)buf = *f;
+ return buf + sizeof(float);
+}
+
+__inline__ static unsigned char *decode_float(float *f, unsigned char *buf)
+{
+ *f = *(float *)buf;
+ return buf + sizeof(float);
+}
+
+__inline__ static unsigned int sizeof_float(const float *c)
+{
+ (void)c;
+ return sizeof(float);
+}
+
+/** double **/
+__inline__ static unsigned char *encode_double(const double *d, unsigned char *buf)
+{
+ *(double *)buf = *d;
+ return buf + sizeof(double);
+}
+
+__inline__ static unsigned char *decode_double(double *d, unsigned char *buf)
+{
+ *d = *(double *)buf;
+ return buf + sizeof(double);
+}
+
+__inline__ static unsigned int sizeof_double(const double *c)
+{
+ (void)c;
+ return sizeof(double);
+}
+
+#endif /* __CODER_H_SEEN__ */
Added: trunk/kernel/linux/userfs_fs.h
==============================================================================
--- trunk/kernel/linux/userfs_fs.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/kernel/linux/userfs_fs.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,102 @@
+/*
+ * Filesystem stub for filesystems implemented with user-level
+ * programs.
+ *
+ * This file forms the definition of the protocol between the
+ * kernel and the user process through the file descriptors.
+ *
+ * There are two file descriptors passed to the kernel as part
+ * of the args to mount(). One is for data from the kernel
+ * to the filesystem, the other from the filesystem to the
+ * kernel. Control and data information are encoded along
+ * the same path.
+ *
+ * The filesystem process never initiates any transaction - they
+ * are all generated by the kernel on the behalf of the other
+ * user processes using the filesystem.
+ *
+ * The connction between the user process and the kernel is
+ * stateful, so if the connection breaks, Something Bad happens -
+ * I suppose it should be considered a umount - but what about
+ * outstanding writes?
+ *
+ * For much the same reasons as nfs and dosfs, there can be no
+ * direct mapping from files, making exec() less memory and time
+ * efficient. I don't see this as a big problem.
+ *
+ * Jeremy Fitzhardinge 1993
+ */
+
+#ifndef _LINUX_USERFS_FS
+#define _LINUX_USERFS_FS
+
+/*
+ * These operations map closely with the elements in the various
+ * operations structures.
+ *
+ * Things are missing here, or overloaded. Open does create, mknod and
+ * mkdir. Unlink can also do a rmdir.
+ */
+typedef enum
+{
+ userfs_up_create, /* 0 create files, devices, dirs */
+ userfs_up_lookup, /* 1 path->file handle */
+ userfs_up_close, /* 2 close on fh */
+ userfs_up_read, /* 3 read from file */
+ userfs_up_write, /* 4 write to file */
+ userfs_up_truncate, /* 5 set file length */
+ userfs_up_fsync, /* 6 sync file */
+ userfs_up_readdir, /* 7 read dir entries */
+ userfs_up_link, /* 8 link files */
+ userfs_up_unlink, /* 9 unlink file */
+ userfs_up_symlink, /* 10 create symlink */
+ userfs_up_readlink, /* 11 read link contents */
+ userfs_up_followlink, /* 12 resolve path through link */
+ userfs_up_mount, /* 13 mount request */
+ userfs_up_umount, /* 14 unmount request */
+ userfs_up_iread, /* 15 get contents of inode for file */
+ userfs_up_iwrite, /* 16 set inode contents */
+ userfs_up_statfs, /* 17 stat filesystem wide things */
+ userfs_up_iput, /* 18 put an inode after finished */
+ userfs_up_open, /* 19 open of a file */
+ userfs_up_permission, /* 20 check file permissions */
+ userfs_up_rename, /* 21 rename file */
+ userfs_up_multireaddir, /* 22 read multiple dir entries */
+ userfs_up_notify_change, /* 23 notify inode changes */
+ userfs_up_inode_valid, /* 24 ask filesystem whether an inode is valid */
+} up_ops;
+
+/* increment this when the structure shapes change */
+#define UP_VERSION 16
+
+/*
+ * Max transfer size currently limited to largest allocatable
+ * block. There's also not much need to make it bigger.
+ */
+#define USERFS_MAX_XFER (4080)
+
+#ifdef __KERNEL__
+#include <linux/param.h> /* For NGROUPS */
+#include <linux/userfs_types.h>
+
+typedef unsigned char *(*encode_func)(const void *, unsigned char *);
+typedef unsigned char *(*decode_func)(void *, unsigned char *);
+typedef unsigned int (*sizeof_func)(const void *);
+
+#define GEN_ENC(var) (encode_func)(var)
+#define GEN_DEC(var) (decode_func)(var)
+#define GEN_SIZ(var) (sizeof_func)(var)
+
+void userfs_genpkt(struct super_block *, up_preamble *, up_ops);
+
+/* Encode and send request, receive and decode reply */
+#define userfs_doop(sb, pre, repl, st, ss, rt, rs)\
+ __userfs_doop(sb, pre, repl, \
+ GEN_ENC(encode_##st), (void *)ss, \
+ GEN_DEC(decode_##rt), (void *)rs, \
+ GEN_SIZ(sizeof_##st), GEN_SIZ(sizeof_##rt))
+
+int __userfs_doop(struct super_block *, up_preamble *pre, upp_repl *repl, encode_func, void *, decode_func, void *, sizeof_func, sizeof_func);
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_USERFS_FS */
Added: trunk/kernel/linux/assert.h
==============================================================================
--- trunk/kernel/linux/assert.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/kernel/linux/assert.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,28 @@
+/*
+ * Kernel assertions
+ */
+
+#ifndef __LINUX_ASSERT_H_
+#define __LINUX_ASSERT_H_
+
+#ifdef NO_ASSERT
+#define assert(x)
+#else
+#ifdef __cplusplus
+#define assert(x) \
+ if(!(x)) \
+ { \
+ printk("Assertion failed in %s:%d: %s\n", \
+ __FILE__, __LINE__, #x); \
+ }
+#else
+#define assert(x) \
+ if(!(x)) \
+ { \
+ printk("Assertion failed in %s:%d (%s): %s\n", \
+ __FILE__, __LINE__, __FUNCTION__, #x); \
+ }
+#endif /* __cplusplus */
+#endif /* NO_ASSERT */
+
+#endif /* __LINUX_ASSERT_H_ */
Added: trunk/kernel/linux/userfs_fs_sb.h
==============================================================================
--- trunk/kernel/linux/userfs_fs_sb.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/kernel/linux/userfs_fs_sb.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,31 @@
+/*
+ * Super-block structure for user-level filesystem support.
+ */
+
+#ifndef _LINUX_USERFS_FS_SB
+#define _LINUX_USERFS_FS_SB
+
+#include <linux/fs.h>
+
+#define USERFS_SUPER_MAGIC 0x73757265
+
+struct userfs_sb_info
+{
+ struct file *s_toproc; /* To user process */
+ struct file *s_fromproc; /* From user process */
+ int s_seq; /* Sequence number */
+ up_handle s_root; /* root of mounted fs */
+ struct inode_operations *s_iops; /* inode ops for this fs */
+
+ /* These are for serialising access to pipe */
+ spinlock_t s_lock;
+
+ /* This is for multiple outstanding operations */
+ int s_canread; /* there is something reading */
+ int s_nwproc; /* number of processes waiting */
+ struct pwlist *s_wlist; /* list of waiting processes */
+};
+
+extern struct super_block *userfs_read_super(struct super_block *, void *, int);
+
+#endif /* _LINUX_USERFS_FS_SB */
Added: trunk/kernel/linux/userfs_fs_f.h
==============================================================================
--- trunk/kernel/linux/userfs_fs_f.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/kernel/linux/userfs_fs_f.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,14 @@
+/*
+ * Per file open information for userfs
+ */
+
+#ifndef __LINUX_USERFS_FS_F_H_SEEN__
+#define __LINUX_USERFS_FS_F_H_SEEN__
+
+typedef unsigned long up_credtok;
+
+struct userfs_file_info {
+ up_credtok cred_tok; /* credentials token */
+};
+
+#endif /* __LINUX_USERFS_FS_F_H_SEEN__ */
Added: trunk/kernel/linux/userfs_types.c
==============================================================================
--- trunk/kernel/linux/userfs_types.c 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/kernel/linux/userfs_types.c 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,1436 @@
+/* -*- C -*-
+ * DO NOT EDIT BY HAND!
+ *
+ * This was automatically generated by gencode.
+ */
+#include "userfs_types.h"
+
+
+unsigned char *encode__userfs_types_001(const _userfs_types_001 *sp, unsigned char *buf)
+{
+ {
+ unsigned i;
+
+ for(i = 0; i < 32; i++) {
+ buf = encode_Ulong(&(*sp)[i], buf);
+ }
+ }
+ return buf;
+}
+
+
+unsigned char *encode__userfs_types_002(const _userfs_types_002 *sp, unsigned char *buf)
+{
+ {
+ unsigned i;
+
+ for(i = 0; i < 2; i++) {
+ buf = encode_long(&(*sp)[i], buf);
+ }
+ }
+ return buf;
+}
+
+
+unsigned char *encode_up_handle(const up_handle *sp, unsigned char *buf)
+{
+ buf = encode_Ulong(&sp->handle, buf);
+ return buf;
+}
+
+
+unsigned char *encode_uf_uid_t(const uf_uid_t *sp, unsigned char *buf)
+{
+ buf = encode_Ushort(sp, buf);
+ return buf;
+}
+
+
+unsigned char *encode__userfs_types_004(const _userfs_types_004 *sp, unsigned char *buf)
+{
+ {
+ unsigned i;
+
+ buf = encode_Ulong(&sp->nelem, buf);
+ for(i = 0; i < sp->nelem; i++) {
+ buf = encode_long(&sp->elems[i], buf);
+ }
+ }
+ return buf;
+}
+
+
+unsigned char *encode_up_cred(const up_cred *sp, unsigned char *buf)
+{
+ buf = encode_Ushort(&sp->uid, buf);
+ buf = encode_Ushort(&sp->euid, buf);
+ buf = encode_Ushort(&sp->suid, buf);
+ buf = encode_Ushort(&sp->gid, buf);
+ buf = encode_Ushort(&sp->egid, buf);
+ buf = encode_Ushort(&sp->sgid, buf);
+ buf = encode_Ushort(&sp->umask, buf);
+ buf = encode__userfs_types_004(&sp->groups, buf);
+ return buf;
+}
+
+
+unsigned char *encode_up_iattr(const up_iattr *sp, unsigned char *buf)
+{
+ buf = encode_Ulong(&sp->ia_valid, buf);
+ buf = encode_Ushort(&sp->ia_mode, buf);
+ buf = encode_Ushort(&sp->ia_uid, buf);
+ buf = encode_Ushort(&sp->ia_gid, buf);
+ buf = encode_long(&sp->ia_size, buf);
+ buf = encode_long(&sp->ia_atime, buf);
+ buf = encode_long(&sp->ia_mtime, buf);
+ buf = encode_long(&sp->ia_ctime, buf);
+ return buf;
+}
+
+
+unsigned char *encode_up_preamble(const up_preamble *sp, unsigned char *buf)
+{
+ buf = encode_short(&sp->version, buf);
+ buf = encode_long(&sp->seq, buf);
+ buf = encode_Uchar(&sp->op, buf);
+ buf = encode_Uchar(&sp->isreq, buf);
+ buf = encode_Ulong(&sp->size, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_repl(const upp_repl *sp, unsigned char *buf)
+{
+ buf = encode_short(&sp->version, buf);
+ buf = encode_long(&sp->seq, buf);
+ buf = encode_Uchar(&sp->op, buf);
+ buf = encode_Uchar(&sp->isreq, buf);
+ buf = encode_Ulong(&sp->size, buf);
+ buf = encode_long(&sp->err_no, buf);
+ return buf;
+}
+
+
+unsigned char *encode_up_inode(const up_inode *sp, unsigned char *buf)
+{
+ buf = encode_Ushort(&sp->mode, buf);
+ buf = encode_Ushort(&sp->nlink, buf);
+ buf = encode_Ushort(&sp->uid, buf);
+ buf = encode_Ushort(&sp->gid, buf);
+ buf = encode_long(&sp->size, buf);
+ buf = encode_long(&sp->atime, buf);
+ buf = encode_long(&sp->mtime, buf);
+ buf = encode_long(&sp->ctime, buf);
+ buf = encode_Ushort(&sp->rdev, buf);
+ buf = encode_Ulong(&sp->blksize, buf);
+ buf = encode_Ulong(&sp->blocks, buf);
+ return buf;
+}
+
+
+unsigned char *encode_up_name(const up_name *sp, unsigned char *buf)
+{
+ {
+ unsigned i;
+
+ buf = encode_Ulong(&sp->nelem, buf);
+ for(i = 0; i < sp->nelem; i++) {
+ buf = encode_char(&sp->elems[i], buf);
+ }
+ }
+ return buf;
+}
+
+
+unsigned char *encode_upp_iwrite_s(const upp_iwrite_s *sp, unsigned char *buf)
+{
+ buf = encode_up_inode(&sp->ino, buf);
+ buf = encode_up_handle(&sp->handle, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_iread_s(const upp_iread_s *sp, unsigned char *buf)
+{
+ buf = encode_up_handle(&sp->handle, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_iread_r(const upp_iread_r *sp, unsigned char *buf)
+{
+ buf = encode_up_handle(&sp->handle, buf);
+ buf = encode_up_inode(&sp->ino, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_unlink_s(const upp_unlink_s *sp, unsigned char *buf)
+{
+ buf = encode_up_handle(&sp->dir, buf);
+ buf = encode_up_name(&sp->name, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_readlink_s(const upp_readlink_s *sp, unsigned char *buf)
+{
+ buf = encode_up_handle(&sp->link, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_readlink_r(const upp_readlink_r *sp, unsigned char *buf)
+{
+ buf = encode_up_name(&sp->name, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_followlink_s(const upp_followlink_s *sp, unsigned char *buf)
+{
+ buf = encode_up_handle(&sp->dir, buf);
+ buf = encode_up_handle(&sp->link, buf);
+ buf = encode_long(&sp->flag, buf);
+ buf = encode_long(&sp->mode, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_followlink_r(const upp_followlink_r *sp, unsigned char *buf)
+{
+ buf = encode_up_name(&sp->path, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_create_s(const upp_create_s *sp, unsigned char *buf)
+{
+ buf = encode_long(&sp->mode, buf);
+ buf = encode_up_handle(&sp->dir, buf);
+ buf = encode_up_cred(&sp->cred, buf);
+ buf = encode_long(&sp->rdev, buf);
+ buf = encode_up_name(&sp->name, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_create_r(const upp_create_r *sp, unsigned char *buf)
+{
+ buf = encode_up_handle(&sp->file, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_lookup_s(const upp_lookup_s *sp, unsigned char *buf)
+{
+ buf = encode_up_handle(&sp->dir, buf);
+ buf = encode_up_name(&sp->name, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_lookup_r(const upp_lookup_r *sp, unsigned char *buf)
+{
+ buf = encode_up_handle(&sp->handle, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_read_s(const upp_read_s *sp, unsigned char *buf)
+{
+ buf = encode_up_handle(&sp->file, buf);
+ buf = encode_long(&sp->off, buf);
+ buf = encode_long(&sp->size, buf);
+ buf = encode_Ulong(&sp->ctok, buf);
+ return buf;
+}
+
+
+unsigned char *encode__userfs_types_006(const _userfs_types_006 *sp, unsigned char *buf)
+{
+ {
+ unsigned i;
+
+ buf = encode_Ulong(&sp->nelem, buf);
+ for(i = 0; i < sp->nelem; i++) {
+ buf = encode_Uchar(&sp->elems[i], buf);
+ }
+ }
+ return buf;
+}
+
+
+unsigned char *encode_upp_read_r(const upp_read_r *sp, unsigned char *buf)
+{
+ buf = encode__userfs_types_006(&sp->data, buf);
+ return buf;
+}
+
+
+unsigned char *encode__userfs_types_007(const _userfs_types_007 *sp, unsigned char *buf)
+{
+ {
+ unsigned i;
+
+ buf = encode_Ulong(&sp->nelem, buf);
+ for(i = 0; i < sp->nelem; i++) {
+ buf = encode_Uchar(&sp->elems[i], buf);
+ }
+ }
+ return buf;
+}
+
+
+unsigned char *encode_upp_write_s(const upp_write_s *sp, unsigned char *buf)
+{
+ buf = encode_up_handle(&sp->file, buf);
+ buf = encode_long(&sp->off, buf);
+ buf = encode_Ulong(&sp->ctok, buf);
+ buf = encode__userfs_types_007(&sp->data, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_write_r(const upp_write_r *sp, unsigned char *buf)
+{
+ buf = encode_long(&sp->wrote, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_readdir_s(const upp_readdir_s *sp, unsigned char *buf)
+{
+ buf = encode_up_handle(&sp->dir, buf);
+ buf = encode_long(&sp->off, buf);
+ buf = encode_Ulong(&sp->ctok, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_readdir_r(const upp_readdir_r *sp, unsigned char *buf)
+{
+ buf = encode_up_handle(&sp->file, buf);
+ buf = encode_long(&sp->off, buf);
+ buf = encode_up_name(&sp->name, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_multireaddir_s(const upp_multireaddir_s *sp, unsigned char *buf)
+{
+ buf = encode_upp_readdir_s(sp, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_multireaddir_r(const upp_multireaddir_r *sp, unsigned char *buf)
+{
+ {
+ unsigned i;
+
+ buf = encode_Ulong(&sp->nelem, buf);
+ for(i = 0; i < sp->nelem; i++) {
+ buf = encode_upp_readdir_r(&sp->elems[i], buf);
+ }
+ }
+ return buf;
+}
+
+
+unsigned char *encode_upp_mount_r(const upp_mount_r *sp, unsigned char *buf)
+{
+ buf = encode_up_handle(&sp->root, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_iput_s(const upp_iput_s *sp, unsigned char *buf)
+{
+ buf = encode_up_handle(&sp->handle, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_open_s(const upp_open_s *sp, unsigned char *buf)
+{
+ buf = encode_up_cred(&sp->cred, buf);
+ buf = encode_up_handle(&sp->file, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_open_r(const upp_open_r *sp, unsigned char *buf)
+{
+ buf = encode_Ulong(&sp->ctok, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_close_s(const upp_close_s *sp, unsigned char *buf)
+{
+ buf = encode_up_handle(&sp->file, buf);
+ buf = encode_Ulong(&sp->ctok, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_permission_s(const upp_permission_s *sp, unsigned char *buf)
+{
+ buf = encode_up_cred(&sp->cred, buf);
+ buf = encode_up_handle(&sp->file, buf);
+ buf = encode_long(&sp->mask, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_rename_s(const upp_rename_s *sp, unsigned char *buf)
+{
+ buf = encode_up_handle(&sp->odir, buf);
+ buf = encode_up_name(&sp->oname, buf);
+ buf = encode_up_handle(&sp->ndir, buf);
+ buf = encode_up_name(&sp->nname, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_link_s(const upp_link_s *sp, unsigned char *buf)
+{
+ buf = encode_up_handle(&sp->ofile, buf);
+ buf = encode_up_handle(&sp->dir, buf);
+ buf = encode_up_name(&sp->name, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_symlink_s(const upp_symlink_s *sp, unsigned char *buf)
+{
+ buf = encode_up_handle(&sp->dir, buf);
+ buf = encode_up_name(&sp->name, buf);
+ buf = encode_up_name(&sp->symname, buf);
+ buf = encode_up_cred(&sp->cred, buf);
+ return buf;
+}
+
+
+unsigned char *encode__userfs_types_011(const _userfs_types_011 *sp, unsigned char *buf)
+{
+ {
+ unsigned i;
+
+ for(i = 0; i < 2; i++) {
+ buf = encode_long(&(*sp)[i], buf);
+ }
+ }
+ return buf;
+}
+
+
+unsigned char *encode_upp_statfs_r(const upp_statfs_r *sp, unsigned char *buf)
+{
+ buf = encode_long(&sp->bsize, buf);
+ buf = encode_long(&sp->blocks, buf);
+ buf = encode_long(&sp->bfree, buf);
+ buf = encode_long(&sp->bavail, buf);
+ buf = encode_long(&sp->files, buf);
+ buf = encode_long(&sp->ffree, buf);
+ buf = encode__userfs_types_011(&sp->fsid, buf);
+ buf = encode_long(&sp->namelen, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_truncate_s(const upp_truncate_s *sp, unsigned char *buf)
+{
+ buf = encode_up_handle(&sp->file, buf);
+ buf = encode_long(&sp->size, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_notify_change_s(const upp_notify_change_s *sp, unsigned char *buf)
+{
+ buf = encode_up_handle(&sp->handle, buf);
+ buf = encode_up_iattr(&sp->iattr, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_inode_valid_s(const upp_inode_valid_s *sp, unsigned char *buf)
+{
+ buf = encode_up_handle(&sp->handle, buf);
+ buf = encode_Ulong(&sp->version, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_inode_valid_r(const upp_inode_valid_r *sp, unsigned char *buf)
+{
+ buf = encode_Ulong(&sp->version, buf);
+ buf = encode_char(&sp->valid, buf);
+ return buf;
+}
+
+
+unsigned char *decode__userfs_types_001(_userfs_types_001 *sp, unsigned char *buf)
+{
+ {
+ unsigned i;
+
+ for(i = 0; i < 32; i++) {
+ buf = decode_Ulong(sp[i], buf);
+ }
+ }
+ return buf;
+}
+
+
+unsigned char *decode__userfs_types_002(_userfs_types_002 *sp, unsigned char *buf)
+{
+ {
+ unsigned i;
+
+ for(i = 0; i < 2; i++) {
+ buf = decode_long(sp[i], buf);
+ }
+ }
+ return buf;
+}
+
+
+unsigned char *decode_up_handle(up_handle *sp, unsigned char *buf)
+{
+ buf = decode_Ulong(&sp->handle, buf);
+ return buf;
+}
+
+
+unsigned char *decode_uf_uid_t(uf_uid_t *sp, unsigned char *buf)
+{
+ buf = decode_Ushort(sp, buf);
+ return buf;
+}
+
+
+unsigned char *decode__userfs_types_004(_userfs_types_004 *sp, unsigned char *buf)
+{
+ {
+ unsigned i;
+ buf = decode_Ulong(&sp->nelem, buf);
+ if (sp->nelem == 0)
+ {
+ sp->elems = 0;
+ return buf;
+ }
+ sp->elems = (long *)ALLOC(sizeof(long) * sp->nelem);
+ if (sp->elems == 0) {
+ return buf;
+ }
+ for(i = 0; i < sp->nelem; i++) {
+ buf = decode_long(&sp->elems[i], buf);
+ }
+ }
+ return buf;
+}
+
+
+unsigned char *decode_up_cred(up_cred *sp, unsigned char *buf)
+{
+ buf = decode_Ushort(&sp->uid, buf);
+ buf = decode_Ushort(&sp->euid, buf);
+ buf = decode_Ushort(&sp->suid, buf);
+ buf = decode_Ushort(&sp->gid, buf);
+ buf = decode_Ushort(&sp->egid, buf);
+ buf = decode_Ushort(&sp->sgid, buf);
+ buf = decode_Ushort(&sp->umask, buf);
+ buf = decode__userfs_types_004(&sp->groups, buf);
+ return buf;
+}
+
+
+unsigned char *decode_up_iattr(up_iattr *sp, unsigned char *buf)
+{
+ buf = decode_Ulong(&sp->ia_valid, buf);
+ buf = decode_Ushort(&sp->ia_mode, buf);
+ buf = decode_Ushort(&sp->ia_uid, buf);
+ buf = decode_Ushort(&sp->ia_gid, buf);
+ buf = decode_long(&sp->ia_size, buf);
+ buf = decode_long(&sp->ia_atime, buf);
+ buf = decode_long(&sp->ia_mtime, buf);
+ buf = decode_long(&sp->ia_ctime, buf);
+ return buf;
+}
+
+
+unsigned char *decode_up_preamble(up_preamble *sp, unsigned char *buf)
+{
+ buf = decode_short(&sp->version, buf);
+ buf = decode_long(&sp->seq, buf);
+ buf = decode_Uchar(&sp->op, buf);
+ buf = decode_Uchar(&sp->isreq, buf);
+ buf = decode_Ulong(&sp->size, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_repl(upp_repl *sp, unsigned char *buf)
+{
+ buf = decode_short(&sp->version, buf);
+ buf = decode_long(&sp->seq, buf);
+ buf = decode_Uchar(&sp->op, buf);
+ buf = decode_Uchar(&sp->isreq, buf);
+ buf = decode_Ulong(&sp->size, buf);
+ buf = decode_long(&sp->err_no, buf);
+ return buf;
+}
+
+
+unsigned char *decode_up_inode(up_inode *sp, unsigned char *buf)
+{
+ buf = decode_Ushort(&sp->mode, buf);
+ buf = decode_Ushort(&sp->nlink, buf);
+ buf = decode_Ushort(&sp->uid, buf);
+ buf = decode_Ushort(&sp->gid, buf);
+ buf = decode_long(&sp->size, buf);
+ buf = decode_long(&sp->atime, buf);
+ buf = decode_long(&sp->mtime, buf);
+ buf = decode_long(&sp->ctime, buf);
+ buf = decode_Ushort(&sp->rdev, buf);
+ buf = decode_Ulong(&sp->blksize, buf);
+ buf = decode_Ulong(&sp->blocks, buf);
+ return buf;
+}
+
+
+unsigned char *decode_up_name(up_name *sp, unsigned char *buf)
+{
+ {
+ unsigned i;
+ buf = decode_Ulong(&sp->nelem, buf);
+ if (sp->nelem == 0)
+ {
+ sp->elems = 0;
+ return buf;
+ }
+ sp->elems = (char *)ALLOC(sizeof(char) * sp->nelem);
+ if (sp->elems == 0) {
+ return buf;
+ }
+ for(i = 0; i < sp->nelem; i++) {
+ buf = decode_char(&sp->elems[i], buf);
+ }
+ }
+ return buf;
+}
+
+
+unsigned char *decode_upp_iwrite_s(upp_iwrite_s *sp, unsigned char *buf)
+{
+ buf = decode_up_inode(&sp->ino, buf);
+ buf = decode_up_handle(&sp->handle, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_iread_s(upp_iread_s *sp, unsigned char *buf)
+{
+ buf = decode_up_handle(&sp->handle, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_iread_r(upp_iread_r *sp, unsigned char *buf)
+{
+ buf = decode_up_handle(&sp->handle, buf);
+ buf = decode_up_inode(&sp->ino, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_unlink_s(upp_unlink_s *sp, unsigned char *buf)
+{
+ buf = decode_up_handle(&sp->dir, buf);
+ buf = decode_up_name(&sp->name, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_readlink_s(upp_readlink_s *sp, unsigned char *buf)
+{
+ buf = decode_up_handle(&sp->link, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_readlink_r(upp_readlink_r *sp, unsigned char *buf)
+{
+ buf = decode_up_name(&sp->name, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_followlink_s(upp_followlink_s *sp, unsigned char *buf)
+{
+ buf = decode_up_handle(&sp->dir, buf);
+ buf = decode_up_handle(&sp->link, buf);
+ buf = decode_long(&sp->flag, buf);
+ buf = decode_long(&sp->mode, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_followlink_r(upp_followlink_r *sp, unsigned char *buf)
+{
+ buf = decode_up_name(&sp->path, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_create_s(upp_create_s *sp, unsigned char *buf)
+{
+ buf = decode_long(&sp->mode, buf);
+ buf = decode_up_handle(&sp->dir, buf);
+ buf = decode_up_cred(&sp->cred, buf);
+ buf = decode_long(&sp->rdev, buf);
+ buf = decode_up_name(&sp->name, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_create_r(upp_create_r *sp, unsigned char *buf)
+{
+ buf = decode_up_handle(&sp->file, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_lookup_s(upp_lookup_s *sp, unsigned char *buf)
+{
+ buf = decode_up_handle(&sp->dir, buf);
+ buf = decode_up_name(&sp->name, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_lookup_r(upp_lookup_r *sp, unsigned char *buf)
+{
+ buf = decode_up_handle(&sp->handle, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_read_s(upp_read_s *sp, unsigned char *buf)
+{
+ buf = decode_up_handle(&sp->file, buf);
+ buf = decode_long(&sp->off, buf);
+ buf = decode_long(&sp->size, buf);
+ buf = decode_Ulong(&sp->ctok, buf);
+ return buf;
+}
+
+
+unsigned char *decode__userfs_types_006(_userfs_types_006 *sp, unsigned char *buf)
+{
+ {
+ unsigned i;
+ buf = decode_Ulong(&sp->nelem, buf);
+ if (sp->nelem == 0)
+ {
+ sp->elems = 0;
+ return buf;
+ }
+ sp->elems = (Uchar *)ALLOC(sizeof(Uchar) * sp->nelem);
+ if (sp->elems == 0) {
+ return buf;
+ }
+ for(i = 0; i < sp->nelem; i++) {
+ buf = decode_Uchar(&sp->elems[i], buf);
+ }
+ }
+ return buf;
+}
+
+
+unsigned char *decode_upp_read_r(upp_read_r *sp, unsigned char *buf)
+{
+ buf = decode__userfs_types_006(&sp->data, buf);
+ return buf;
+}
+
+
+unsigned char *decode__userfs_types_007(_userfs_types_007 *sp, unsigned char *buf)
+{
+ {
+ unsigned i;
+ buf = decode_Ulong(&sp->nelem, buf);
+ if (sp->nelem == 0)
+ {
+ sp->elems = 0;
+ return buf;
+ }
+ sp->elems = (Uchar *)ALLOC(sizeof(Uchar) * sp->nelem);
+ if (sp->elems == 0) {
+ return buf;
+ }
+ for(i = 0; i < sp->nelem; i++) {
+ buf = decode_Uchar(&sp->elems[i], buf);
+ }
+ }
+ return buf;
+}
+
+
+unsigned char *decode_upp_write_s(upp_write_s *sp, unsigned char *buf)
+{
+ buf = decode_up_handle(&sp->file, buf);
+ buf = decode_long(&sp->off, buf);
+ buf = decode_Ulong(&sp->ctok, buf);
+ buf = decode__userfs_types_007(&sp->data, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_write_r(upp_write_r *sp, unsigned char *buf)
+{
+ buf = decode_long(&sp->wrote, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_readdir_s(upp_readdir_s *sp, unsigned char *buf)
+{
+ buf = decode_up_handle(&sp->dir, buf);
+ buf = decode_long(&sp->off, buf);
+ buf = decode_Ulong(&sp->ctok, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_readdir_r(upp_readdir_r *sp, unsigned char *buf)
+{
+ buf = decode_up_handle(&sp->file, buf);
+ buf = decode_long(&sp->off, buf);
+ buf = decode_up_name(&sp->name, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_multireaddir_s(upp_multireaddir_s *sp, unsigned char *buf)
+{
+ buf = decode_upp_readdir_s(sp, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_multireaddir_r(upp_multireaddir_r *sp, unsigned char *buf)
+{
+ {
+ unsigned i;
+ buf = decode_Ulong(&sp->nelem, buf);
+ if (sp->nelem == 0)
+ {
+ sp->elems = 0;
+ return buf;
+ }
+ sp->elems = (upp_readdir_r *)ALLOC(sizeof(upp_readdir_r) * sp->nelem);
+ if (sp->elems == 0) {
+ return buf;
+ }
+ for(i = 0; i < sp->nelem; i++) {
+ buf = decode_upp_readdir_r(&sp->elems[i], buf);
+ }
+ }
+ return buf;
+}
+
+
+unsigned char *decode_upp_mount_r(upp_mount_r *sp, unsigned char *buf)
+{
+ buf = decode_up_handle(&sp->root, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_iput_s(upp_iput_s *sp, unsigned char *buf)
+{
+ buf = decode_up_handle(&sp->handle, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_open_s(upp_open_s *sp, unsigned char *buf)
+{
+ buf = decode_up_cred(&sp->cred, buf);
+ buf = decode_up_handle(&sp->file, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_open_r(upp_open_r *sp, unsigned char *buf)
+{
+ buf = decode_Ulong(&sp->ctok, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_close_s(upp_close_s *sp, unsigned char *buf)
+{
+ buf = decode_up_handle(&sp->file, buf);
+ buf = decode_Ulong(&sp->ctok, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_permission_s(upp_permission_s *sp, unsigned char *buf)
+{
+ buf = decode_up_cred(&sp->cred, buf);
+ buf = decode_up_handle(&sp->file, buf);
+ buf = decode_long(&sp->mask, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_rename_s(upp_rename_s *sp, unsigned char *buf)
+{
+ buf = decode_up_handle(&sp->odir, buf);
+ buf = decode_up_name(&sp->oname, buf);
+ buf = decode_up_handle(&sp->ndir, buf);
+ buf = decode_up_name(&sp->nname, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_link_s(upp_link_s *sp, unsigned char *buf)
+{
+ buf = decode_up_handle(&sp->ofile, buf);
+ buf = decode_up_handle(&sp->dir, buf);
+ buf = decode_up_name(&sp->name, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_symlink_s(upp_symlink_s *sp, unsigned char *buf)
+{
+ buf = decode_up_handle(&sp->dir, buf);
+ buf = decode_up_name(&sp->name, buf);
+ buf = decode_up_name(&sp->symname, buf);
+ buf = decode_up_cred(&sp->cred, buf);
+ return buf;
+}
+
+
+unsigned char *decode__userfs_types_011(_userfs_types_011 *sp, unsigned char *buf)
+{
+ {
+ unsigned i;
+
+ for(i = 0; i < 2; i++) {
+ buf = decode_long(sp[i], buf);
+ }
+ }
+ return buf;
+}
+
+
+unsigned char *decode_upp_statfs_r(upp_statfs_r *sp, unsigned char *buf)
+{
+ buf = decode_long(&sp->bsize, buf);
+ buf = decode_long(&sp->blocks, buf);
+ buf = decode_long(&sp->bfree, buf);
+ buf = decode_long(&sp->bavail, buf);
+ buf = decode_long(&sp->files, buf);
+ buf = decode_long(&sp->ffree, buf);
+ buf = decode__userfs_types_011(&sp->fsid, buf);
+ buf = decode_long(&sp->namelen, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_truncate_s(upp_truncate_s *sp, unsigned char *buf)
+{
+ buf = decode_up_handle(&sp->file, buf);
+ buf = decode_long(&sp->size, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_notify_change_s(upp_notify_change_s *sp, unsigned char *buf)
+{
+ buf = decode_up_handle(&sp->handle, buf);
+ buf = decode_up_iattr(&sp->iattr, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_inode_valid_s(upp_inode_valid_s *sp, unsigned char *buf)
+{
+ buf = decode_up_handle(&sp->handle, buf);
+ buf = decode_Ulong(&sp->version, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_inode_valid_r(upp_inode_valid_r *sp, unsigned char *buf)
+{
+ buf = decode_Ulong(&sp->version, buf);
+ buf = decode_char(&sp->valid, buf);
+ return buf;
+}
+unsigned int sizeof__userfs_types_001(const _userfs_types_001 *sp)
+{
+ unsigned int sz=0;
+
+ {
+ unsigned i;
+ for(i = 0; i < 32; i++) {
+ sz += sizeof_Ulong(sp[i]);
+ }
+ }
+ return sz;
+}
+unsigned int sizeof__userfs_types_002(const _userfs_types_002 *sp)
+{
+ unsigned int sz=0;
+
+ {
+ unsigned i;
+ for(i = 0; i < 2; i++) {
+ sz += sizeof_long(sp[i]);
+ }
+ }
+ return sz;
+}
+unsigned int sizeof_up_handle(const up_handle *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_Ulong(&sp->handle);
+ return sz;
+}
+unsigned int sizeof_uf_uid_t(const uf_uid_t *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_Ushort(sp);
+ return sz;
+}
+unsigned int sizeof__userfs_types_004(const _userfs_types_004 *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_Ulong(&sp->nelem);
+ {
+ unsigned i;
+ for(i = 0; i < sp->nelem; i++) {
+ sz += sizeof_long(&sp->elems[i]);
+ }
+ }
+ return sz;
+}
+unsigned int sizeof_up_cred(const up_cred *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_Ushort(&sp->uid);
+ sz += sizeof_Ushort(&sp->euid);
+ sz += sizeof_Ushort(&sp->suid);
+ sz += sizeof_Ushort(&sp->gid);
+ sz += sizeof_Ushort(&sp->egid);
+ sz += sizeof_Ushort(&sp->sgid);
+ sz += sizeof_Ushort(&sp->umask);
+ sz += sizeof__userfs_types_004(&sp->groups);
+ return sz;
+}
+unsigned int sizeof_up_iattr(const up_iattr *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_Ulong(&sp->ia_valid);
+ sz += sizeof_Ushort(&sp->ia_mode);
+ sz += sizeof_Ushort(&sp->ia_uid);
+ sz += sizeof_Ushort(&sp->ia_gid);
+ sz += sizeof_long(&sp->ia_size);
+ sz += sizeof_long(&sp->ia_atime);
+ sz += sizeof_long(&sp->ia_mtime);
+ sz += sizeof_long(&sp->ia_ctime);
+ return sz;
+}
+unsigned int sizeof_up_preamble(const up_preamble *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_short(&sp->version);
+ sz += sizeof_long(&sp->seq);
+ sz += sizeof_Uchar(&sp->op);
+ sz += sizeof_Uchar(&sp->isreq);
+ sz += sizeof_Ulong(&sp->size);
+ return sz;
+}
+unsigned int sizeof_upp_repl(const upp_repl *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_short(&sp->version);
+ sz += sizeof_long(&sp->seq);
+ sz += sizeof_Uchar(&sp->op);
+ sz += sizeof_Uchar(&sp->isreq);
+ sz += sizeof_Ulong(&sp->size);
+ sz += sizeof_long(&sp->err_no);
+ return sz;
+}
+unsigned int sizeof_up_inode(const up_inode *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_Ushort(&sp->mode);
+ sz += sizeof_Ushort(&sp->nlink);
+ sz += sizeof_Ushort(&sp->uid);
+ sz += sizeof_Ushort(&sp->gid);
+ sz += sizeof_long(&sp->size);
+ sz += sizeof_long(&sp->atime);
+ sz += sizeof_long(&sp->mtime);
+ sz += sizeof_long(&sp->ctime);
+ sz += sizeof_Ushort(&sp->rdev);
+ sz += sizeof_Ulong(&sp->blksize);
+ sz += sizeof_Ulong(&sp->blocks);
+ return sz;
+}
+unsigned int sizeof_up_name(const up_name *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_Ulong(&sp->nelem);
+ {
+ unsigned i;
+ for(i = 0; i < sp->nelem; i++) {
+ sz += sizeof_char(&sp->elems[i]);
+ }
+ }
+ return sz;
+}
+unsigned int sizeof_upp_iwrite_s(const upp_iwrite_s *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_inode(&sp->ino);
+ sz += sizeof_up_handle(&sp->handle);
+ return sz;
+}
+unsigned int sizeof_upp_iread_s(const upp_iread_s *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_handle(&sp->handle);
+ return sz;
+}
+unsigned int sizeof_upp_iread_r(const upp_iread_r *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_handle(&sp->handle);
+ sz += sizeof_up_inode(&sp->ino);
+ return sz;
+}
+unsigned int sizeof_upp_unlink_s(const upp_unlink_s *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_handle(&sp->dir);
+ sz += sizeof_up_name(&sp->name);
+ return sz;
+}
+unsigned int sizeof_upp_readlink_s(const upp_readlink_s *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_handle(&sp->link);
+ return sz;
+}
+unsigned int sizeof_upp_readlink_r(const upp_readlink_r *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_name(&sp->name);
+ return sz;
+}
+unsigned int sizeof_upp_followlink_s(const upp_followlink_s *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_handle(&sp->dir);
+ sz += sizeof_up_handle(&sp->link);
+ sz += sizeof_long(&sp->flag);
+ sz += sizeof_long(&sp->mode);
+ return sz;
+}
+unsigned int sizeof_upp_followlink_r(const upp_followlink_r *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_name(&sp->path);
+ return sz;
+}
+unsigned int sizeof_upp_create_s(const upp_create_s *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_long(&sp->mode);
+ sz += sizeof_up_handle(&sp->dir);
+ sz += sizeof_up_cred(&sp->cred);
+ sz += sizeof_long(&sp->rdev);
+ sz += sizeof_up_name(&sp->name);
+ return sz;
+}
+unsigned int sizeof_upp_create_r(const upp_create_r *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_handle(&sp->file);
+ return sz;
+}
+unsigned int sizeof_upp_lookup_s(const upp_lookup_s *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_handle(&sp->dir);
+ sz += sizeof_up_name(&sp->name);
+ return sz;
+}
+unsigned int sizeof_upp_lookup_r(const upp_lookup_r *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_handle(&sp->handle);
+ return sz;
+}
+unsigned int sizeof_upp_read_s(const upp_read_s *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_handle(&sp->file);
+ sz += sizeof_long(&sp->off);
+ sz += sizeof_long(&sp->size);
+ sz += sizeof_Ulong(&sp->ctok);
+ return sz;
+}
+unsigned int sizeof__userfs_types_006(const _userfs_types_006 *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_Ulong(&sp->nelem);
+ {
+ unsigned i;
+ for(i = 0; i < sp->nelem; i++) {
+ sz += sizeof_Uchar(&sp->elems[i]);
+ }
+ }
+ return sz;
+}
+unsigned int sizeof_upp_read_r(const upp_read_r *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof__userfs_types_006(&sp->data);
+ return sz;
+}
+unsigned int sizeof__userfs_types_007(const _userfs_types_007 *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_Ulong(&sp->nelem);
+ {
+ unsigned i;
+ for(i = 0; i < sp->nelem; i++) {
+ sz += sizeof_Uchar(&sp->elems[i]);
+ }
+ }
+ return sz;
+}
+unsigned int sizeof_upp_write_s(const upp_write_s *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_handle(&sp->file);
+ sz += sizeof_long(&sp->off);
+ sz += sizeof_Ulong(&sp->ctok);
+ sz += sizeof__userfs_types_007(&sp->data);
+ return sz;
+}
+unsigned int sizeof_upp_write_r(const upp_write_r *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_long(&sp->wrote);
+ return sz;
+}
+unsigned int sizeof_upp_readdir_s(const upp_readdir_s *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_handle(&sp->dir);
+ sz += sizeof_long(&sp->off);
+ sz += sizeof_Ulong(&sp->ctok);
+ return sz;
+}
+unsigned int sizeof_upp_readdir_r(const upp_readdir_r *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_handle(&sp->file);
+ sz += sizeof_long(&sp->off);
+ sz += sizeof_up_name(&sp->name);
+ return sz;
+}
+unsigned int sizeof_upp_multireaddir_s(const upp_multireaddir_s *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_upp_readdir_s(sp);
+ return sz;
+}
+unsigned int sizeof_upp_multireaddir_r(const upp_multireaddir_r *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_Ulong(&sp->nelem);
+ {
+ unsigned i;
+ for(i = 0; i < sp->nelem; i++) {
+ sz += sizeof_upp_readdir_r(&sp->elems[i]);
+ }
+ }
+ return sz;
+}
+unsigned int sizeof_upp_mount_r(const upp_mount_r *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_handle(&sp->root);
+ return sz;
+}
+unsigned int sizeof_upp_iput_s(const upp_iput_s *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_handle(&sp->handle);
+ return sz;
+}
+unsigned int sizeof_upp_open_s(const upp_open_s *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_cred(&sp->cred);
+ sz += sizeof_up_handle(&sp->file);
+ return sz;
+}
+unsigned int sizeof_upp_open_r(const upp_open_r *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_Ulong(&sp->ctok);
+ return sz;
+}
+unsigned int sizeof_upp_close_s(const upp_close_s *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_handle(&sp->file);
+ sz += sizeof_Ulong(&sp->ctok);
+ return sz;
+}
+unsigned int sizeof_upp_permission_s(const upp_permission_s *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_cred(&sp->cred);
+ sz += sizeof_up_handle(&sp->file);
+ sz += sizeof_long(&sp->mask);
+ return sz;
+}
+unsigned int sizeof_upp_rename_s(const upp_rename_s *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_handle(&sp->odir);
+ sz += sizeof_up_name(&sp->oname);
+ sz += sizeof_up_handle(&sp->ndir);
+ sz += sizeof_up_name(&sp->nname);
+ return sz;
+}
+unsigned int sizeof_upp_link_s(const upp_link_s *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_handle(&sp->ofile);
+ sz += sizeof_up_handle(&sp->dir);
+ sz += sizeof_up_name(&sp->name);
+ return sz;
+}
+unsigned int sizeof_upp_symlink_s(const upp_symlink_s *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_handle(&sp->dir);
+ sz += sizeof_up_name(&sp->name);
+ sz += sizeof_up_name(&sp->symname);
+ sz += sizeof_up_cred(&sp->cred);
+ return sz;
+}
+unsigned int sizeof__userfs_types_011(const _userfs_types_011 *sp)
+{
+ unsigned int sz=0;
+
+ {
+ unsigned i;
+ for(i = 0; i < 2; i++) {
+ sz += sizeof_long(sp[i]);
+ }
+ }
+ return sz;
+}
+unsigned int sizeof_upp_statfs_r(const upp_statfs_r *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_long(&sp->bsize);
+ sz += sizeof_long(&sp->blocks);
+ sz += sizeof_long(&sp->bfree);
+ sz += sizeof_long(&sp->bavail);
+ sz += sizeof_long(&sp->files);
+ sz += sizeof_long(&sp->ffree);
+ sz += sizeof__userfs_types_011(&sp->fsid);
+ sz += sizeof_long(&sp->namelen);
+ return sz;
+}
+unsigned int sizeof_upp_truncate_s(const upp_truncate_s *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_handle(&sp->file);
+ sz += sizeof_long(&sp->size);
+ return sz;
+}
+unsigned int sizeof_upp_notify_change_s(const upp_notify_change_s *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_handle(&sp->handle);
+ sz += sizeof_up_iattr(&sp->iattr);
+ return sz;
+}
+unsigned int sizeof_upp_inode_valid_s(const upp_inode_valid_s *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_handle(&sp->handle);
+ sz += sizeof_Ulong(&sp->version);
+ return sz;
+}
+unsigned int sizeof_upp_inode_valid_r(const upp_inode_valid_r *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_Ulong(&sp->version);
+ sz += sizeof_char(&sp->valid);
+ return sz;
+}
Added: trunk/kernel/linux/userfs_fs_i.h
==============================================================================
--- trunk/kernel/linux/userfs_fs_i.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/kernel/linux/userfs_fs_i.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,25 @@
+/*
+ * Inode data for userfs
+ */
+
+#ifndef _LINUX_USERFS_FS_I
+#define _LINUX_USERFS_FS_I
+
+/*
+ * What a handle looks like
+ */
+typedef struct
+{
+ unsigned long handle;
+} up_handle;
+
+typedef unsigned long up_version;
+
+struct userfs_inode_info
+{
+ up_handle handle;
+ struct userfs_dir_ra *dir_ra;
+ up_version version;
+};
+
+#endif /* _LINUX_USERFS_FS_I */
Added: trunk/kernel/linux/Makefile
==============================================================================
--- trunk/kernel/linux/Makefile 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/kernel/linux/Makefile 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,25 @@
+# Generate some "headers"
+
+TOP=../..
+CPPFLAGS=-I..
+
+include $(TOP)/rules
+
+.SUFFIXES: .ty
+
+.ty.c:
+ $(GENCODE) $(CPPFLAGS) -sed $< > $@
+
+.ty.h:
+ $(GENHDR) $(CPPFLAGS) $< > $@
+
+dep depend all:: userfs_types.c userfs_types.h coder.h
+
+userfs_types.c: userfs_types.ty $(GENCODE)
+userfs_types.h: userfs_types.ty $(GENHDR)
+
+coder.h:
+ ln -s $(GENDIR)/coder.h .
+
+clean::
+ rm -f userfs_types.[ch] coder.h *~
Added: trunk/kernel/src/linux/userfs_mount.h
==============================================================================
--- trunk/kernel/src/linux/userfs_mount.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/kernel/src/linux/userfs_mount.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,30 @@
+/*
+ * Information passed from user process to the kernel as the
+ * 3rd argument to mount(2).
+ */
+
+#ifndef _LINUX_USERFS_MOUNT
+#define _LINUX_USERFS_MOUNT
+
+/*
+ * WARNING! Do not delete or change the order of these fields. If
+ * a new field is required then add it to the end. The version field
+ * tracks which fields are present. This will ensure some measure of
+ * mount-to-kernel version compatibilty. Some of these aren't used yet
+ * but here they are anyway.
+ */
+
+/* Change this if things are added to the structure below */
+#define USERFS_VERSION 3
+
+
+struct userfs_mount
+{
+ int version; /* v1 - version of structure */
+ int tokern; /* v1 - fd of stream into the kernel */
+ int fromkern; /* v1 - from kernel */
+ int magic; /* v2 - magic */
+ int seq; /* v3 - initial sequence number */
+};
+
+#endif /* _LINUX_USERFS_MOUNT */
Added: trunk/kernel/src/linux/userfs_types.h
==============================================================================
--- trunk/kernel/src/linux/userfs_types.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/kernel/src/linux/userfs_types.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,895 @@
+/* -*- C -*-
+ * DO NOT EDIT BY HAND!
+ *
+ * This was automatically generated from "userfs_types.ty" by genhdr.
+ */
+
+#ifndef __USERFS_TYPES_H_SEEN__
+#define __USERFS_TYPES_H_SEEN__
+
+#ifndef __KERNEL__
+#include <asm/posix_types.h>
+#include <asm/types.h>
+typedef __kernel_suseconds_t suseconds_t;
+typedef __u8 uint8_t;
+typedef __u16 uint16_t;
+typedef __u32 uint32_t;
+#undef __FD_ZERO
+#undef __FD_SET
+#undef __FD_CLR
+#undef __FD_ISSET
+#endif
+#if !defined(ALLOC)
+# if defined(__KERNEL__)
+# include <linux/slab.h>
+# include <linux/mm.h>
+# include <linux/assert.h>
+# define ALLOC(x) kmalloc(x, GFP_KERNEL)
+# define FREE(x) kfree(x)
+# else
+# define ALLOC ALLOC
+# include <assert.h>
+# include <stdlib.h>
+#ifdef __GLIBC__
+#include <time.h>
+#include <malloc.h>
+typedef unsigned char unchar;
+#endif
+static __inline__ void *ALLOC(int alloc)
+{
+ void *mem = malloc(alloc);
+
+ assert(mem != 0);
+ return mem;
+}
+#define FREE(x) free(x)
+# endif /* __KERNEL__ */
+#endif /* ALLOC */
+#include <linux/types.h>
+#include <linux/userfs_fs_i.h>
+#include <linux/userfs_fs_f.h>
+#define UP_REPL 0 /* Is a reply */
+#define UP_REQ 1 /* Is a request */
+#define UP_ENQ 2 /* Is capability enquiry */
+#ifndef _NO_CODER_H_
+/* Type encode/decode routines */
+#include "coder.h" /* Standard routines */
+#endif /* _NO_CODER_H_ */
+/* Encoded types */
+
+typedef Ulong _userfs_types_001[32];
+typedef long _userfs_types_002[2];
+typedef Ulong _userfs_types_003[32];
+typedef ushort uf_uid_t;
+typedef ushort uf_gid_t;
+typedef ushort uf_nlink_t;
+typedef ushort uf_dev_t;
+typedef struct
+{
+ Ulong nelem;
+ long* elems;
+} _userfs_types_004;
+typedef struct
+{
+ uf_uid_t uid;
+ uf_uid_t euid;
+ uf_uid_t suid;
+ uf_uid_t gid;
+ uf_uid_t egid;
+ uf_uid_t sgid;
+ uf_uid_t umask;
+ _userfs_types_004 groups;
+} up_cred;
+typedef struct
+{
+ Ulong ia_valid;
+ umode_t ia_mode;
+ uf_uid_t ia_uid;
+ uf_gid_t ia_gid;
+ off_t ia_size;
+ time_t ia_atime;
+ time_t ia_mtime;
+ time_t ia_ctime;
+} up_iattr;
+typedef struct
+{
+ __s16 version;
+ long seq;
+ Uchar op;
+ Uchar isreq;
+ Ulong size;
+} up_preamble;
+typedef struct
+{
+ __s16 version;
+ long seq;
+ Uchar op;
+ Uchar isreq;
+ Ulong size;
+ long err_no;
+} upp_repl;
+typedef struct
+{
+ umode_t mode;
+ uf_nlink_t nlink;
+ uf_uid_t uid;
+ uf_gid_t gid;
+ off_t size;
+ time_t atime;
+ time_t mtime;
+ time_t ctime;
+ uf_dev_t rdev;
+ Ulong blksize;
+ Ulong blocks;
+} up_inode;
+typedef struct
+{
+ Ulong nelem;
+ __s8* elems;
+} up_name;
+typedef struct
+{
+ up_inode ino;
+ up_handle handle;
+} upp_iwrite_s;
+typedef struct
+{
+ up_handle handle;
+} upp_iread_s;
+typedef struct
+{
+ up_handle handle;
+ up_inode ino;
+} upp_iread_r;
+typedef struct
+{
+ up_handle dir;
+ up_name name;
+} upp_unlink_s;
+typedef struct
+{
+ up_handle link;
+} upp_readlink_s;
+typedef struct
+{
+ up_name name;
+} upp_readlink_r;
+typedef struct
+{
+ up_handle dir;
+ up_handle link;
+ long flag;
+ long mode;
+} upp_followlink_s;
+typedef struct
+{
+ up_name path;
+} upp_followlink_r;
+typedef struct
+{
+ Ulong nelem;
+ long* elems;
+} _userfs_types_005;
+typedef struct
+{
+ long mode;
+ up_handle dir;
+ up_cred cred;
+ long rdev;
+ up_name name;
+} upp_create_s;
+typedef struct
+{
+ up_handle file;
+} upp_create_r;
+typedef struct
+{
+ up_handle dir;
+ up_name name;
+} upp_lookup_s;
+typedef struct
+{
+ up_handle handle;
+} upp_lookup_r;
+typedef struct
+{
+ up_handle file;
+ off_t off;
+ off_t size;
+ up_credtok ctok;
+} upp_read_s;
+typedef struct
+{
+ Ulong nelem;
+ Uchar* elems;
+} _userfs_types_006;
+typedef struct
+{
+ _userfs_types_006 data;
+} upp_read_r;
+typedef struct
+{
+ Ulong nelem;
+ Uchar* elems;
+} _userfs_types_007;
+typedef struct
+{
+ up_handle file;
+ off_t off;
+ up_credtok ctok;
+ _userfs_types_007 data;
+} upp_write_s;
+typedef struct
+{
+ off_t wrote;
+} upp_write_r;
+typedef struct
+{
+ up_handle dir;
+ off_t off;
+ up_credtok ctok;
+} upp_readdir_s;
+typedef struct
+{
+ up_handle file;
+ off_t off;
+ up_name name;
+} upp_readdir_r;
+typedef upp_readdir_s upp_multireaddir_s;
+typedef struct
+{
+ Ulong nelem;
+ upp_readdir_r* elems;
+} upp_multireaddir_r;
+typedef struct
+{
+ up_handle root;
+} upp_mount_r;
+typedef struct
+{
+ up_handle handle;
+} upp_iput_s;
+typedef struct
+{
+ Ulong nelem;
+ long* elems;
+} _userfs_types_008;
+typedef struct
+{
+ up_cred cred;
+ up_handle file;
+} upp_open_s;
+typedef struct
+{
+ up_credtok ctok;
+} upp_open_r;
+typedef struct
+{
+ up_handle file;
+ up_credtok ctok;
+} upp_close_s;
+typedef struct
+{
+ Ulong nelem;
+ long* elems;
+} _userfs_types_009;
+typedef struct
+{
+ up_cred cred;
+ up_handle file;
+ long mask;
+} upp_permission_s;
+typedef struct
+{
+ up_handle odir;
+ up_name oname;
+ up_handle ndir;
+ up_name nname;
+} upp_rename_s;
+typedef struct
+{
+ up_handle ofile;
+ up_handle dir;
+ up_name name;
+} upp_link_s;
+typedef struct
+{
+ Ulong nelem;
+ long* elems;
+} _userfs_types_010;
+typedef struct
+{
+ up_handle dir;
+ up_name name;
+ up_name symname;
+ up_cred cred;
+} upp_symlink_s;
+typedef long _userfs_types_011[2];
+typedef struct
+{
+ __kernel_off_t bsize;
+ __kernel_off_t blocks;
+ __kernel_off_t bfree;
+ __kernel_off_t bavail;
+ __kernel_off_t files;
+ __kernel_off_t ffree;
+ _userfs_types_011 fsid;
+ __kernel_off_t namelen;
+} upp_statfs_r;
+typedef struct
+{
+ up_handle file;
+ off_t size;
+} upp_truncate_s;
+typedef struct
+{
+ up_handle handle;
+ up_iattr iattr;
+} upp_notify_change_s;
+typedef struct
+{
+ up_handle handle;
+ up_version version;
+} upp_inode_valid_s;
+typedef struct
+{
+ up_version version;
+ __s8 valid;
+} upp_inode_valid_r;
+static unsigned char *encode_char(const char *, unsigned char *);
+static unsigned char *decode_char(char *, unsigned char *);
+static unsigned int sizeof_char(const char *);
+
+static unsigned char *encode_short(const short *, unsigned char *);
+static unsigned char *decode_short(short *, unsigned char *);
+static unsigned int sizeof_short(const short *);
+
+static unsigned char *encode_long(const long *, unsigned char *);
+static unsigned char *decode_long(long *, unsigned char *);
+static unsigned int sizeof_long(const long *);
+
+static unsigned char *encode_longlong(const longlong *, unsigned char *);
+static unsigned char *decode_longlong(longlong *, unsigned char *);
+static unsigned int sizeof_longlong(const longlong *);
+
+static unsigned char *encode_float(const float *, unsigned char *);
+static unsigned char *decode_float(float *, unsigned char *);
+static unsigned int sizeof_float(const float *);
+
+static unsigned char *encode_double(const double *, unsigned char *);
+static unsigned char *decode_double(double *, unsigned char *);
+static unsigned int sizeof_double(const double *);
+
+static unsigned char *encode_void(const void *, unsigned char *);
+static unsigned char *decode_void(void *, unsigned char *);
+static unsigned int sizeof_void(const void *);
+
+static unsigned char *encode_Uchar(const Uchar *, unsigned char *);
+static unsigned char *decode_Uchar(Uchar *, unsigned char *);
+static unsigned int sizeof_Uchar(const Uchar *);
+
+static unsigned char *encode_Ushort(const Ushort *, unsigned char *);
+static unsigned char *decode_Ushort(Ushort *, unsigned char *);
+static unsigned int sizeof_Ushort(const Ushort *);
+
+static unsigned char *encode_Ulong(const Ulong *, unsigned char *);
+static unsigned char *decode_Ulong(Ulong *, unsigned char *);
+static unsigned int sizeof_Ulong(const Ulong *);
+
+static unsigned char *encode_Ulonglong(const Ulonglong *, unsigned char *);
+static unsigned char *decode_Ulonglong(Ulonglong *, unsigned char *);
+static unsigned int sizeof_Ulonglong(const Ulonglong *);
+
+unsigned char *encode_Uint(const Uint *, unsigned char *);
+unsigned char *decode_Uint(Uint *, unsigned char *);
+unsigned int sizeof_Uint(const Uint *);
+
+unsigned char *encode_int(const int *, unsigned char *);
+unsigned char *decode_int(int *, unsigned char *);
+unsigned int sizeof_int(const int *);
+
+unsigned char *encode__userfs_types_001(const _userfs_types_001 *, unsigned char *);
+unsigned char *decode__userfs_types_001(_userfs_types_001 *, unsigned char *);
+unsigned int sizeof__userfs_types_001(const _userfs_types_001 *);
+
+unsigned char *encode___kernel_fd_set(const __kernel_fd_set *, unsigned char *);
+unsigned char *decode___kernel_fd_set(__kernel_fd_set *, unsigned char *);
+unsigned int sizeof___kernel_fd_set(const __kernel_fd_set *);
+
+unsigned char *encode___kernel_key_t(const __kernel_key_t *, unsigned char *);
+unsigned char *decode___kernel_key_t(__kernel_key_t *, unsigned char *);
+unsigned int sizeof___kernel_key_t(const __kernel_key_t *);
+
+unsigned char *encode___kernel_dev_t(const __kernel_dev_t *, unsigned char *);
+unsigned char *decode___kernel_dev_t(__kernel_dev_t *, unsigned char *);
+unsigned int sizeof___kernel_dev_t(const __kernel_dev_t *);
+
+unsigned char *encode___kernel_ino_t(const __kernel_ino_t *, unsigned char *);
+unsigned char *decode___kernel_ino_t(__kernel_ino_t *, unsigned char *);
+unsigned int sizeof___kernel_ino_t(const __kernel_ino_t *);
+
+unsigned char *encode___kernel_mode_t(const __kernel_mode_t *, unsigned char *);
+unsigned char *decode___kernel_mode_t(__kernel_mode_t *, unsigned char *);
+unsigned int sizeof___kernel_mode_t(const __kernel_mode_t *);
+
+unsigned char *encode___kernel_nlink_t(const __kernel_nlink_t *, unsigned char *);
+unsigned char *decode___kernel_nlink_t(__kernel_nlink_t *, unsigned char *);
+unsigned int sizeof___kernel_nlink_t(const __kernel_nlink_t *);
+
+unsigned char *encode___kernel_off_t(const __kernel_off_t *, unsigned char *);
+unsigned char *decode___kernel_off_t(__kernel_off_t *, unsigned char *);
+unsigned int sizeof___kernel_off_t(const __kernel_off_t *);
+
+unsigned char *encode___kernel_pid_t(const __kernel_pid_t *, unsigned char *);
+unsigned char *decode___kernel_pid_t(__kernel_pid_t *, unsigned char *);
+unsigned int sizeof___kernel_pid_t(const __kernel_pid_t *);
+
+unsigned char *encode___kernel_ipc_pid_t(const __kernel_ipc_pid_t *, unsigned char *);
+unsigned char *decode___kernel_ipc_pid_t(__kernel_ipc_pid_t *, unsigned char *);
+unsigned int sizeof___kernel_ipc_pid_t(const __kernel_ipc_pid_t *);
+
+unsigned char *encode___kernel_uid_t(const __kernel_uid_t *, unsigned char *);
+unsigned char *decode___kernel_uid_t(__kernel_uid_t *, unsigned char *);
+unsigned int sizeof___kernel_uid_t(const __kernel_uid_t *);
+
+unsigned char *encode___kernel_gid_t(const __kernel_gid_t *, unsigned char *);
+unsigned char *decode___kernel_gid_t(__kernel_gid_t *, unsigned char *);
+unsigned int sizeof___kernel_gid_t(const __kernel_gid_t *);
+
+unsigned char *encode___kernel_size_t(const __kernel_size_t *, unsigned char *);
+unsigned char *decode___kernel_size_t(__kernel_size_t *, unsigned char *);
+unsigned int sizeof___kernel_size_t(const __kernel_size_t *);
+
+unsigned char *encode___kernel_ssize_t(const __kernel_ssize_t *, unsigned char *);
+unsigned char *decode___kernel_ssize_t(__kernel_ssize_t *, unsigned char *);
+unsigned int sizeof___kernel_ssize_t(const __kernel_ssize_t *);
+
+unsigned char *encode___kernel_ptrdiff_t(const __kernel_ptrdiff_t *, unsigned char *);
+unsigned char *decode___kernel_ptrdiff_t(__kernel_ptrdiff_t *, unsigned char *);
+unsigned int sizeof___kernel_ptrdiff_t(const __kernel_ptrdiff_t *);
+
+unsigned char *encode___kernel_time_t(const __kernel_time_t *, unsigned char *);
+unsigned char *decode___kernel_time_t(__kernel_time_t *, unsigned char *);
+unsigned int sizeof___kernel_time_t(const __kernel_time_t *);
+
+unsigned char *encode___kernel_suseconds_t(const __kernel_suseconds_t *, unsigned char *);
+unsigned char *decode___kernel_suseconds_t(__kernel_suseconds_t *, unsigned char *);
+unsigned int sizeof___kernel_suseconds_t(const __kernel_suseconds_t *);
+
+unsigned char *encode___kernel_clock_t(const __kernel_clock_t *, unsigned char *);
+unsigned char *decode___kernel_clock_t(__kernel_clock_t *, unsigned char *);
+unsigned int sizeof___kernel_clock_t(const __kernel_clock_t *);
+
+unsigned char *encode___kernel_daddr_t(const __kernel_daddr_t *, unsigned char *);
+unsigned char *decode___kernel_daddr_t(__kernel_daddr_t *, unsigned char *);
+unsigned int sizeof___kernel_daddr_t(const __kernel_daddr_t *);
+
+unsigned char *encode___kernel_caddr_t(const __kernel_caddr_t *, unsigned char *);
+unsigned char *decode___kernel_caddr_t(__kernel_caddr_t *, unsigned char *);
+unsigned int sizeof___kernel_caddr_t(const __kernel_caddr_t *);
+
+unsigned char *encode___kernel_uid16_t(const /* __kernel_uid16_t */ unsigned short *, unsigned char *);
+unsigned char *decode___kernel_uid16_t(/* __kernel_uid16_t */ unsigned short *, unsigned char *);
+unsigned int sizeof___kernel_uid16_t(const /* __kernel_uid16_t */ unsigned short *);
+
+unsigned char *encode___kernel_gid16_t(const /* __kernel_gid16_t */ unsigned short *, unsigned char *);
+unsigned char *decode___kernel_gid16_t(/* __kernel_gid16_t */ unsigned short *, unsigned char *);
+unsigned int sizeof___kernel_gid16_t(const /* __kernel_gid16_t */ unsigned short *);
+
+unsigned char *encode___kernel_uid32_t(const /*__kernel_uid32_t */ unsigned int *, unsigned char *);
+unsigned char *decode___kernel_uid32_t(/*__kernel_uid32_t */ unsigned int *, unsigned char *);
+unsigned int sizeof___kernel_uid32_t(const /*__kernel_uid32_t */ unsigned int *);
+
+unsigned char *encode___kernel_gid32_t(const /*__kernel_gid32_t */ unsigned int *, unsigned char *);
+unsigned char *decode___kernel_gid32_t(/*__kernel_gid32_t */ unsigned int *, unsigned char *);
+unsigned int sizeof___kernel_gid32_t(const /*__kernel_gid32_t */ unsigned int *);
+
+unsigned char *encode___kernel_old_uid_t(const /*__kernel_old_uid_t */ unsigned short *, unsigned char *);
+unsigned char *decode___kernel_old_uid_t(/*__kernel_old_uid_t */ unsigned short *, unsigned char *);
+unsigned int sizeof___kernel_old_uid_t(const /*__kernel_old_uid_t */ unsigned short *);
+
+unsigned char *encode___kernel_old_gid_t(const /*__kernel_old_gid_t */ unsigned short *, unsigned char *);
+unsigned char *decode___kernel_old_gid_t(/*__kernel_old_gid_t */ unsigned short *, unsigned char *);
+unsigned int sizeof___kernel_old_gid_t(const /*__kernel_old_gid_t */ unsigned short *);
+
+unsigned char *encode__userfs_types_002(const _userfs_types_002 *, unsigned char *);
+unsigned char *decode__userfs_types_002(_userfs_types_002 *, unsigned char *);
+unsigned int sizeof__userfs_types_002(const _userfs_types_002 *);
+
+unsigned char *encode___kernel_fsid_t(const __kernel_fsid_t *, unsigned char *);
+unsigned char *decode___kernel_fsid_t(__kernel_fsid_t *, unsigned char *);
+unsigned int sizeof___kernel_fsid_t(const __kernel_fsid_t *);
+
+unsigned char *encode_umode_t(const umode_t *, unsigned char *);
+unsigned char *decode_umode_t(umode_t *, unsigned char *);
+unsigned int sizeof_umode_t(const umode_t *);
+
+unsigned char *encode___s8(const __s8 *, unsigned char *);
+unsigned char *decode___s8(__s8 *, unsigned char *);
+unsigned int sizeof___s8(const __s8 *);
+
+unsigned char *encode___u8(const __u8 *, unsigned char *);
+unsigned char *decode___u8(__u8 *, unsigned char *);
+unsigned int sizeof___u8(const __u8 *);
+
+unsigned char *encode___s16(const __s16 *, unsigned char *);
+unsigned char *decode___s16(__s16 *, unsigned char *);
+unsigned int sizeof___s16(const __s16 *);
+
+unsigned char *encode___u16(const __u16 *, unsigned char *);
+unsigned char *decode___u16(__u16 *, unsigned char *);
+unsigned int sizeof___u16(const __u16 *);
+
+unsigned char *encode___s32(const __s32 *, unsigned char *);
+unsigned char *decode___s32(__s32 *, unsigned char *);
+unsigned int sizeof___s32(const __s32 *);
+
+unsigned char *encode___u32(const __u32 *, unsigned char *);
+unsigned char *decode___u32(__u32 *, unsigned char *);
+unsigned int sizeof___u32(const __u32 *);
+
+unsigned char *encode__userfs_types_003(const _userfs_types_003 *, unsigned char *);
+unsigned char *decode__userfs_types_003(_userfs_types_003 *, unsigned char *);
+unsigned int sizeof__userfs_types_003(const _userfs_types_003 *);
+
+unsigned char *encode_fd_set(const fd_set *, unsigned char *);
+unsigned char *decode_fd_set(fd_set *, unsigned char *);
+unsigned int sizeof_fd_set(const fd_set *);
+
+unsigned char *encode_dev_t(const dev_t *, unsigned char *);
+unsigned char *decode_dev_t(dev_t *, unsigned char *);
+unsigned int sizeof_dev_t(const dev_t *);
+
+unsigned char *encode_ino_t(const ino_t *, unsigned char *);
+unsigned char *decode_ino_t(ino_t *, unsigned char *);
+unsigned int sizeof_ino_t(const ino_t *);
+
+unsigned char *encode_mode_t(const mode_t *, unsigned char *);
+unsigned char *decode_mode_t(mode_t *, unsigned char *);
+unsigned int sizeof_mode_t(const mode_t *);
+
+unsigned char *encode_nlink_t(const nlink_t *, unsigned char *);
+unsigned char *decode_nlink_t(nlink_t *, unsigned char *);
+unsigned int sizeof_nlink_t(const nlink_t *);
+
+unsigned char *encode_off_t(const off_t *, unsigned char *);
+unsigned char *decode_off_t(off_t *, unsigned char *);
+unsigned int sizeof_off_t(const off_t *);
+
+unsigned char *encode_pid_t(const pid_t *, unsigned char *);
+unsigned char *decode_pid_t(pid_t *, unsigned char *);
+unsigned int sizeof_pid_t(const pid_t *);
+
+unsigned char *encode_daddr_t(const daddr_t *, unsigned char *);
+unsigned char *decode_daddr_t(daddr_t *, unsigned char *);
+unsigned int sizeof_daddr_t(const daddr_t *);
+
+unsigned char *encode_key_t(const key_t *, unsigned char *);
+unsigned char *decode_key_t(key_t *, unsigned char *);
+unsigned int sizeof_key_t(const key_t *);
+
+unsigned char *encode_suseconds_t(const suseconds_t *, unsigned char *);
+unsigned char *decode_suseconds_t(suseconds_t *, unsigned char *);
+unsigned int sizeof_suseconds_t(const suseconds_t *);
+
+unsigned char *encode_uid_t(const uid_t *, unsigned char *);
+unsigned char *decode_uid_t(uid_t *, unsigned char *);
+unsigned int sizeof_uid_t(const uid_t *);
+
+unsigned char *encode_gid_t(const gid_t *, unsigned char *);
+unsigned char *decode_gid_t(gid_t *, unsigned char *);
+unsigned int sizeof_gid_t(const gid_t *);
+
+unsigned char *encode_size_t(const size_t *, unsigned char *);
+unsigned char *decode_size_t(size_t *, unsigned char *);
+unsigned int sizeof_size_t(const size_t *);
+
+unsigned char *encode_ssize_t(const ssize_t *, unsigned char *);
+unsigned char *decode_ssize_t(ssize_t *, unsigned char *);
+unsigned int sizeof_ssize_t(const ssize_t *);
+
+unsigned char *encode_ptrdiff_t(const ptrdiff_t *, unsigned char *);
+unsigned char *decode_ptrdiff_t(ptrdiff_t *, unsigned char *);
+unsigned int sizeof_ptrdiff_t(const ptrdiff_t *);
+
+unsigned char *encode_time_t(const time_t *, unsigned char *);
+unsigned char *decode_time_t(time_t *, unsigned char *);
+unsigned int sizeof_time_t(const time_t *);
+
+unsigned char *encode_clock_t(const clock_t *, unsigned char *);
+unsigned char *decode_clock_t(clock_t *, unsigned char *);
+unsigned int sizeof_clock_t(const clock_t *);
+
+unsigned char *encode_caddr_t(const caddr_t *, unsigned char *);
+unsigned char *decode_caddr_t(caddr_t *, unsigned char *);
+unsigned int sizeof_caddr_t(const caddr_t *);
+
+unsigned char *encode_u_char(const u_char *, unsigned char *);
+unsigned char *decode_u_char(u_char *, unsigned char *);
+unsigned int sizeof_u_char(const u_char *);
+
+unsigned char *encode_u_short(const u_short *, unsigned char *);
+unsigned char *decode_u_short(u_short *, unsigned char *);
+unsigned int sizeof_u_short(const u_short *);
+
+unsigned char *encode_u_int(const u_int *, unsigned char *);
+unsigned char *decode_u_int(u_int *, unsigned char *);
+unsigned int sizeof_u_int(const u_int *);
+
+unsigned char *encode_u_long(const u_long *, unsigned char *);
+unsigned char *decode_u_long(u_long *, unsigned char *);
+unsigned int sizeof_u_long(const u_long *);
+
+unsigned char *encode_unchar(const unchar *, unsigned char *);
+unsigned char *decode_unchar(unchar *, unsigned char *);
+unsigned int sizeof_unchar(const unchar *);
+
+unsigned char *encode_ushort(const ushort *, unsigned char *);
+unsigned char *decode_ushort(ushort *, unsigned char *);
+unsigned int sizeof_ushort(const ushort *);
+
+unsigned char *encode_uint(const uint *, unsigned char *);
+unsigned char *decode_uint(uint *, unsigned char *);
+unsigned int sizeof_uint(const uint *);
+
+unsigned char *encode_ulong(const ulong *, unsigned char *);
+unsigned char *decode_ulong(ulong *, unsigned char *);
+unsigned int sizeof_ulong(const ulong *);
+
+unsigned char *encode_u_int8_t(const u_int8_t *, unsigned char *);
+unsigned char *decode_u_int8_t(u_int8_t *, unsigned char *);
+unsigned int sizeof_u_int8_t(const u_int8_t *);
+
+unsigned char *encode_int8_t(const int8_t *, unsigned char *);
+unsigned char *decode_int8_t(int8_t *, unsigned char *);
+unsigned int sizeof_int8_t(const int8_t *);
+
+unsigned char *encode_u_int16_t(const u_int16_t *, unsigned char *);
+unsigned char *decode_u_int16_t(u_int16_t *, unsigned char *);
+unsigned int sizeof_u_int16_t(const u_int16_t *);
+
+unsigned char *encode_int16_t(const int16_t *, unsigned char *);
+unsigned char *decode_int16_t(int16_t *, unsigned char *);
+unsigned int sizeof_int16_t(const int16_t *);
+
+unsigned char *encode_u_int32_t(const u_int32_t *, unsigned char *);
+unsigned char *decode_u_int32_t(u_int32_t *, unsigned char *);
+unsigned int sizeof_u_int32_t(const u_int32_t *);
+
+unsigned char *encode_int32_t(const int32_t *, unsigned char *);
+unsigned char *decode_int32_t(int32_t *, unsigned char *);
+unsigned int sizeof_int32_t(const int32_t *);
+
+unsigned char *encode_uint8_t(const uint8_t *, unsigned char *);
+unsigned char *decode_uint8_t(uint8_t *, unsigned char *);
+unsigned int sizeof_uint8_t(const uint8_t *);
+
+unsigned char *encode_uint16_t(const uint16_t *, unsigned char *);
+unsigned char *decode_uint16_t(uint16_t *, unsigned char *);
+unsigned int sizeof_uint16_t(const uint16_t *);
+
+unsigned char *encode_uint32_t(const uint32_t *, unsigned char *);
+unsigned char *decode_uint32_t(uint32_t *, unsigned char *);
+unsigned int sizeof_uint32_t(const uint32_t *);
+
+unsigned char *encode_up_handle(const up_handle *, unsigned char *);
+unsigned char *decode_up_handle(up_handle *, unsigned char *);
+unsigned int sizeof_up_handle(const up_handle *);
+
+unsigned char *encode_up_version(const up_version *, unsigned char *);
+unsigned char *decode_up_version(up_version *, unsigned char *);
+unsigned int sizeof_up_version(const up_version *);
+
+unsigned char *encode_up_credtok(const up_credtok *, unsigned char *);
+unsigned char *decode_up_credtok(up_credtok *, unsigned char *);
+unsigned int sizeof_up_credtok(const up_credtok *);
+
+unsigned char *encode_uf_uid_t(const uf_uid_t *, unsigned char *);
+unsigned char *decode_uf_uid_t(uf_uid_t *, unsigned char *);
+unsigned int sizeof_uf_uid_t(const uf_uid_t *);
+
+unsigned char *encode_uf_gid_t(const uf_gid_t *, unsigned char *);
+unsigned char *decode_uf_gid_t(uf_gid_t *, unsigned char *);
+unsigned int sizeof_uf_gid_t(const uf_gid_t *);
+
+unsigned char *encode_uf_nlink_t(const uf_nlink_t *, unsigned char *);
+unsigned char *decode_uf_nlink_t(uf_nlink_t *, unsigned char *);
+unsigned int sizeof_uf_nlink_t(const uf_nlink_t *);
+
+unsigned char *encode_uf_dev_t(const uf_dev_t *, unsigned char *);
+unsigned char *decode_uf_dev_t(uf_dev_t *, unsigned char *);
+unsigned int sizeof_uf_dev_t(const uf_dev_t *);
+
+unsigned char *encode__userfs_types_004(const _userfs_types_004 *, unsigned char *);
+unsigned char *decode__userfs_types_004(_userfs_types_004 *, unsigned char *);
+unsigned int sizeof__userfs_types_004(const _userfs_types_004 *);
+
+unsigned char *encode_up_cred(const up_cred *, unsigned char *);
+unsigned char *decode_up_cred(up_cred *, unsigned char *);
+unsigned int sizeof_up_cred(const up_cred *);
+
+unsigned char *encode_up_iattr(const up_iattr *, unsigned char *);
+unsigned char *decode_up_iattr(up_iattr *, unsigned char *);
+unsigned int sizeof_up_iattr(const up_iattr *);
+
+unsigned char *encode_up_preamble(const up_preamble *, unsigned char *);
+unsigned char *decode_up_preamble(up_preamble *, unsigned char *);
+unsigned int sizeof_up_preamble(const up_preamble *);
+
+unsigned char *encode_upp_repl(const upp_repl *, unsigned char *);
+unsigned char *decode_upp_repl(upp_repl *, unsigned char *);
+unsigned int sizeof_upp_repl(const upp_repl *);
+
+unsigned char *encode_up_inode(const up_inode *, unsigned char *);
+unsigned char *decode_up_inode(up_inode *, unsigned char *);
+unsigned int sizeof_up_inode(const up_inode *);
+
+unsigned char *encode_up_name(const up_name *, unsigned char *);
+unsigned char *decode_up_name(up_name *, unsigned char *);
+unsigned int sizeof_up_name(const up_name *);
+
+unsigned char *encode_upp_iwrite_s(const upp_iwrite_s *, unsigned char *);
+unsigned char *decode_upp_iwrite_s(upp_iwrite_s *, unsigned char *);
+unsigned int sizeof_upp_iwrite_s(const upp_iwrite_s *);
+
+unsigned char *encode_upp_iread_s(const upp_iread_s *, unsigned char *);
+unsigned char *decode_upp_iread_s(upp_iread_s *, unsigned char *);
+unsigned int sizeof_upp_iread_s(const upp_iread_s *);
+
+unsigned char *encode_upp_iread_r(const upp_iread_r *, unsigned char *);
+unsigned char *decode_upp_iread_r(upp_iread_r *, unsigned char *);
+unsigned int sizeof_upp_iread_r(const upp_iread_r *);
+
+unsigned char *encode_upp_unlink_s(const upp_unlink_s *, unsigned char *);
+unsigned char *decode_upp_unlink_s(upp_unlink_s *, unsigned char *);
+unsigned int sizeof_upp_unlink_s(const upp_unlink_s *);
+
+unsigned char *encode_upp_readlink_s(const upp_readlink_s *, unsigned char *);
+unsigned char *decode_upp_readlink_s(upp_readlink_s *, unsigned char *);
+unsigned int sizeof_upp_readlink_s(const upp_readlink_s *);
+
+unsigned char *encode_upp_readlink_r(const upp_readlink_r *, unsigned char *);
+unsigned char *decode_upp_readlink_r(upp_readlink_r *, unsigned char *);
+unsigned int sizeof_upp_readlink_r(const upp_readlink_r *);
+
+unsigned char *encode_upp_followlink_s(const upp_followlink_s *, unsigned char *);
+unsigned char *decode_upp_followlink_s(upp_followlink_s *, unsigned char *);
+unsigned int sizeof_upp_followlink_s(const upp_followlink_s *);
+
+unsigned char *encode_upp_followlink_r(const upp_followlink_r *, unsigned char *);
+unsigned char *decode_upp_followlink_r(upp_followlink_r *, unsigned char *);
+unsigned int sizeof_upp_followlink_r(const upp_followlink_r *);
+
+unsigned char *encode__userfs_types_005(const _userfs_types_005 *, unsigned char *);
+unsigned char *decode__userfs_types_005(_userfs_types_005 *, unsigned char *);
+unsigned int sizeof__userfs_types_005(const _userfs_types_005 *);
+
+unsigned char *encode_upp_create_s(const upp_create_s *, unsigned char *);
+unsigned char *decode_upp_create_s(upp_create_s *, unsigned char *);
+unsigned int sizeof_upp_create_s(const upp_create_s *);
+
+unsigned char *encode_upp_create_r(const upp_create_r *, unsigned char *);
+unsigned char *decode_upp_create_r(upp_create_r *, unsigned char *);
+unsigned int sizeof_upp_create_r(const upp_create_r *);
+
+unsigned char *encode_upp_lookup_s(const upp_lookup_s *, unsigned char *);
+unsigned char *decode_upp_lookup_s(upp_lookup_s *, unsigned char *);
+unsigned int sizeof_upp_lookup_s(const upp_lookup_s *);
+
+unsigned char *encode_upp_lookup_r(const upp_lookup_r *, unsigned char *);
+unsigned char *decode_upp_lookup_r(upp_lookup_r *, unsigned char *);
+unsigned int sizeof_upp_lookup_r(const upp_lookup_r *);
+
+unsigned char *encode_upp_read_s(const upp_read_s *, unsigned char *);
+unsigned char *decode_upp_read_s(upp_read_s *, unsigned char *);
+unsigned int sizeof_upp_read_s(const upp_read_s *);
+
+unsigned char *encode__userfs_types_006(const _userfs_types_006 *, unsigned char *);
+unsigned char *decode__userfs_types_006(_userfs_types_006 *, unsigned char *);
+unsigned int sizeof__userfs_types_006(const _userfs_types_006 *);
+
+unsigned char *encode_upp_read_r(const upp_read_r *, unsigned char *);
+unsigned char *decode_upp_read_r(upp_read_r *, unsigned char *);
+unsigned int sizeof_upp_read_r(const upp_read_r *);
+
+unsigned char *encode__userfs_types_007(const _userfs_types_007 *, unsigned char *);
+unsigned char *decode__userfs_types_007(_userfs_types_007 *, unsigned char *);
+unsigned int sizeof__userfs_types_007(const _userfs_types_007 *);
+
+unsigned char *encode_upp_write_s(const upp_write_s *, unsigned char *);
+unsigned char *decode_upp_write_s(upp_write_s *, unsigned char *);
+unsigned int sizeof_upp_write_s(const upp_write_s *);
+
+unsigned char *encode_upp_write_r(const upp_write_r *, unsigned char *);
+unsigned char *decode_upp_write_r(upp_write_r *, unsigned char *);
+unsigned int sizeof_upp_write_r(const upp_write_r *);
+
+unsigned char *encode_upp_readdir_s(const upp_readdir_s *, unsigned char *);
+unsigned char *decode_upp_readdir_s(upp_readdir_s *, unsigned char *);
+unsigned int sizeof_upp_readdir_s(const upp_readdir_s *);
+
+unsigned char *encode_upp_readdir_r(const upp_readdir_r *, unsigned char *);
+unsigned char *decode_upp_readdir_r(upp_readdir_r *, unsigned char *);
+unsigned int sizeof_upp_readdir_r(const upp_readdir_r *);
+
+unsigned char *encode_upp_multireaddir_s(const upp_multireaddir_s *, unsigned char *);
+unsigned char *decode_upp_multireaddir_s(upp_multireaddir_s *, unsigned char *);
+unsigned int sizeof_upp_multireaddir_s(const upp_multireaddir_s *);
+
+unsigned char *encode_upp_multireaddir_r(const upp_multireaddir_r *, unsigned char *);
+unsigned char *decode_upp_multireaddir_r(upp_multireaddir_r *, unsigned char *);
+unsigned int sizeof_upp_multireaddir_r(const upp_multireaddir_r *);
+
+unsigned char *encode_upp_mount_r(const upp_mount_r *, unsigned char *);
+unsigned char *decode_upp_mount_r(upp_mount_r *, unsigned char *);
+unsigned int sizeof_upp_mount_r(const upp_mount_r *);
+
+unsigned char *encode_upp_iput_s(const upp_iput_s *, unsigned char *);
+unsigned char *decode_upp_iput_s(upp_iput_s *, unsigned char *);
+unsigned int sizeof_upp_iput_s(const upp_iput_s *);
+
+unsigned char *encode__userfs_types_008(const _userfs_types_008 *, unsigned char *);
+unsigned char *decode__userfs_types_008(_userfs_types_008 *, unsigned char *);
+unsigned int sizeof__userfs_types_008(const _userfs_types_008 *);
+
+unsigned char *encode_upp_open_s(const upp_open_s *, unsigned char *);
+unsigned char *decode_upp_open_s(upp_open_s *, unsigned char *);
+unsigned int sizeof_upp_open_s(const upp_open_s *);
+
+unsigned char *encode_upp_open_r(const upp_open_r *, unsigned char *);
+unsigned char *decode_upp_open_r(upp_open_r *, unsigned char *);
+unsigned int sizeof_upp_open_r(const upp_open_r *);
+
+unsigned char *encode_upp_close_s(const upp_close_s *, unsigned char *);
+unsigned char *decode_upp_close_s(upp_close_s *, unsigned char *);
+unsigned int sizeof_upp_close_s(const upp_close_s *);
+
+unsigned char *encode__userfs_types_009(const _userfs_types_009 *, unsigned char *);
+unsigned char *decode__userfs_types_009(_userfs_types_009 *, unsigned char *);
+unsigned int sizeof__userfs_types_009(const _userfs_types_009 *);
+
+unsigned char *encode_upp_permission_s(const upp_permission_s *, unsigned char *);
+unsigned char *decode_upp_permission_s(upp_permission_s *, unsigned char *);
+unsigned int sizeof_upp_permission_s(const upp_permission_s *);
+
+unsigned char *encode_upp_rename_s(const upp_rename_s *, unsigned char *);
+unsigned char *decode_upp_rename_s(upp_rename_s *, unsigned char *);
+unsigned int sizeof_upp_rename_s(const upp_rename_s *);
+
+unsigned char *encode_upp_link_s(const upp_link_s *, unsigned char *);
+unsigned char *decode_upp_link_s(upp_link_s *, unsigned char *);
+unsigned int sizeof_upp_link_s(const upp_link_s *);
+
+unsigned char *encode__userfs_types_010(const _userfs_types_010 *, unsigned char *);
+unsigned char *decode__userfs_types_010(_userfs_types_010 *, unsigned char *);
+unsigned int sizeof__userfs_types_010(const _userfs_types_010 *);
+
+unsigned char *encode_upp_symlink_s(const upp_symlink_s *, unsigned char *);
+unsigned char *decode_upp_symlink_s(upp_symlink_s *, unsigned char *);
+unsigned int sizeof_upp_symlink_s(const upp_symlink_s *);
+
+unsigned char *encode__userfs_types_011(const _userfs_types_011 *, unsigned char *);
+unsigned char *decode__userfs_types_011(_userfs_types_011 *, unsigned char *);
+unsigned int sizeof__userfs_types_011(const _userfs_types_011 *);
+
+unsigned char *encode_upp_statfs_r(const upp_statfs_r *, unsigned char *);
+unsigned char *decode_upp_statfs_r(upp_statfs_r *, unsigned char *);
+unsigned int sizeof_upp_statfs_r(const upp_statfs_r *);
+
+unsigned char *encode_upp_truncate_s(const upp_truncate_s *, unsigned char *);
+unsigned char *decode_upp_truncate_s(upp_truncate_s *, unsigned char *);
+unsigned int sizeof_upp_truncate_s(const upp_truncate_s *);
+
+unsigned char *encode_upp_notify_change_s(const upp_notify_change_s *, unsigned char *);
+unsigned char *decode_upp_notify_change_s(upp_notify_change_s *, unsigned char *);
+unsigned int sizeof_upp_notify_change_s(const upp_notify_change_s *);
+
+unsigned char *encode_upp_inode_valid_s(const upp_inode_valid_s *, unsigned char *);
+unsigned char *decode_upp_inode_valid_s(upp_inode_valid_s *, unsigned char *);
+unsigned int sizeof_upp_inode_valid_s(const upp_inode_valid_s *);
+
+unsigned char *encode_upp_inode_valid_r(const upp_inode_valid_r *, unsigned char *);
+unsigned char *decode_upp_inode_valid_r(upp_inode_valid_r *, unsigned char *);
+unsigned int sizeof_upp_inode_valid_r(const upp_inode_valid_r *);
+
+#endif /* __USERFS_TYPES_H_SEEN__ */
Added: trunk/kernel/src/linux/userfs_fs.h
==============================================================================
--- trunk/kernel/src/linux/userfs_fs.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/kernel/src/linux/userfs_fs.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,102 @@
+/*
+ * Filesystem stub for filesystems implemented with user-level
+ * programs.
+ *
+ * This file forms the definition of the protocol between the
+ * kernel and the user process through the file descriptors.
+ *
+ * There are two file descriptors passed to the kernel as part
+ * of the args to mount(). One is for data from the kernel
+ * to the filesystem, the other from the filesystem to the
+ * kernel. Control and data information are encoded along
+ * the same path.
+ *
+ * The filesystem process never initiates any transaction - they
+ * are all generated by the kernel on the behalf of the other
+ * user processes using the filesystem.
+ *
+ * The connction between the user process and the kernel is
+ * stateful, so if the connection breaks, Something Bad happens -
+ * I suppose it should be considered a umount - but what about
+ * outstanding writes?
+ *
+ * For much the same reasons as nfs and dosfs, there can be no
+ * direct mapping from files, making exec() less memory and time
+ * efficient. I don't see this as a big problem.
+ *
+ * Jeremy Fitzhardinge 1993
+ */
+
+#ifndef _LINUX_USERFS_FS
+#define _LINUX_USERFS_FS
+
+/*
+ * These operations map closely with the elements in the various
+ * operations structures.
+ *
+ * Things are missing here, or overloaded. Open does create, mknod and
+ * mkdir. Unlink can also do a rmdir.
+ */
+typedef enum
+{
+ userfs_up_create, /* 0 create files, devices, dirs */
+ userfs_up_lookup, /* 1 path->file handle */
+ userfs_up_close, /* 2 close on fh */
+ userfs_up_read, /* 3 read from file */
+ userfs_up_write, /* 4 write to file */
+ userfs_up_truncate, /* 5 set file length */
+ userfs_up_fsync, /* 6 sync file */
+ userfs_up_readdir, /* 7 read dir entries */
+ userfs_up_link, /* 8 link files */
+ userfs_up_unlink, /* 9 unlink file */
+ userfs_up_symlink, /* 10 create symlink */
+ userfs_up_readlink, /* 11 read link contents */
+ userfs_up_followlink, /* 12 resolve path through link */
+ userfs_up_mount, /* 13 mount request */
+ userfs_up_umount, /* 14 unmount request */
+ userfs_up_iread, /* 15 get contents of inode for file */
+ userfs_up_iwrite, /* 16 set inode contents */
+ userfs_up_statfs, /* 17 stat filesystem wide things */
+ userfs_up_iput, /* 18 put an inode after finished */
+ userfs_up_open, /* 19 open of a file */
+ userfs_up_permission, /* 20 check file permissions */
+ userfs_up_rename, /* 21 rename file */
+ userfs_up_multireaddir, /* 22 read multiple dir entries */
+ userfs_up_notify_change, /* 23 notify inode changes */
+ userfs_up_inode_valid, /* 24 ask filesystem whether an inode is valid */
+} up_ops;
+
+/* increment this when the structure shapes change */
+#define UP_VERSION 16
+
+/*
+ * Max transfer size currently limited to largest allocatable
+ * block. There's also not much need to make it bigger.
+ */
+#define USERFS_MAX_XFER (4080)
+
+#ifdef __KERNEL__
+#include <linux/param.h> /* For NGROUPS */
+#include <linux/userfs_types.h>
+
+typedef unsigned char *(*encode_func)(const void *, unsigned char *);
+typedef unsigned char *(*decode_func)(void *, unsigned char *);
+typedef unsigned int (*sizeof_func)(const void *);
+
+#define GEN_ENC(var) (encode_func)(var)
+#define GEN_DEC(var) (decode_func)(var)
+#define GEN_SIZ(var) (sizeof_func)(var)
+
+void userfs_genpkt(struct super_block *, up_preamble *, up_ops);
+
+/* Encode and send request, receive and decode reply */
+#define userfs_doop(sb, pre, repl, st, ss, rt, rs)\
+ __userfs_doop(sb, pre, repl, \
+ GEN_ENC(encode_##st), (void *)ss, \
+ GEN_DEC(decode_##rt), (void *)rs, \
+ GEN_SIZ(sizeof_##st), GEN_SIZ(sizeof_##rt))
+
+int __userfs_doop(struct super_block *, up_preamble *pre, upp_repl *repl, encode_func, void *, decode_func, void *, sizeof_func, sizeof_func);
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_USERFS_FS */
Added: trunk/kernel/src/linux/userfs_fs_sb.h
==============================================================================
--- trunk/kernel/src/linux/userfs_fs_sb.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/kernel/src/linux/userfs_fs_sb.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,32 @@
+/*
+ * Super-block structure for user-level filesystem support.
+ */
+
+#ifndef _LINUX_USERFS_FS_SB
+#define _LINUX_USERFS_FS_SB
+
+#include <linux/fs.h>
+
+#define USERFS_SUPER_MAGIC 0x73757265
+
+struct userfs_sb_info
+{
+ struct file *s_toproc; /* To user process */
+ struct file *s_fromproc; /* From user process */
+ int s_seq; /* Sequence number */
+ up_handle s_root; /* root of mounted fs */
+ struct inode_operations *s_iops; /* inode ops for this fs */
+
+ /* These are for serialising access to pipe */
+ spinlock_t s_lock;
+ wait_queue_t s_wait;
+
+ /* This is for multiple outstanding operations */
+ int s_canread; /* there is something reading */
+ int s_nwproc; /* number of processes waiting */
+ struct pwlist *s_wlist; /* list of waiting processes */
+};
+
+extern struct super_block *userfs_read_super(struct super_block *, void *, int);
+
+#endif /* _LINUX_USERFS_FS_SB */
Added: trunk/kernel/src/linux/userfs_fs_f.h
==============================================================================
--- trunk/kernel/src/linux/userfs_fs_f.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/kernel/src/linux/userfs_fs_f.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,14 @@
+/*
+ * Per file open information for userfs
+ */
+
+#ifndef __LINUX_USERFS_FS_F_H_SEEN__
+#define __LINUX_USERFS_FS_F_H_SEEN__
+
+typedef unsigned long up_credtok;
+
+struct userfs_file_info {
+ up_credtok cred_tok; /* credentials token */
+};
+
+#endif /* __LINUX_USERFS_FS_F_H_SEEN__ */
Added: trunk/kernel/src/linux/userfs_types.c
==============================================================================
--- trunk/kernel/src/linux/userfs_types.c 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/kernel/src/linux/userfs_types.c 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,1436 @@
+/* -*- C -*-
+ * DO NOT EDIT BY HAND!
+ *
+ * This was automatically generated by gencode.
+ */
+#include "userfs_types.h"
+
+
+unsigned char *encode__userfs_types_001(const _userfs_types_001 *sp, unsigned char *buf)
+{
+ {
+ unsigned i;
+
+ for(i = 0; i < 32; i++) {
+ buf = encode_Ulong(&(*sp)[i], buf);
+ }
+ }
+ return buf;
+}
+
+
+unsigned char *encode__userfs_types_002(const _userfs_types_002 *sp, unsigned char *buf)
+{
+ {
+ unsigned i;
+
+ for(i = 0; i < 2; i++) {
+ buf = encode_long(&(*sp)[i], buf);
+ }
+ }
+ return buf;
+}
+
+
+unsigned char *encode_up_handle(const up_handle *sp, unsigned char *buf)
+{
+ buf = encode_Ulong(&sp->handle, buf);
+ return buf;
+}
+
+
+unsigned char *encode_uf_uid_t(const uf_uid_t *sp, unsigned char *buf)
+{
+ buf = encode_Ushort(sp, buf);
+ return buf;
+}
+
+
+unsigned char *encode__userfs_types_004(const _userfs_types_004 *sp, unsigned char *buf)
+{
+ {
+ unsigned i;
+
+ buf = encode_Ulong(&sp->nelem, buf);
+ for(i = 0; i < sp->nelem; i++) {
+ buf = encode_long(&sp->elems[i], buf);
+ }
+ }
+ return buf;
+}
+
+
+unsigned char *encode_up_cred(const up_cred *sp, unsigned char *buf)
+{
+ buf = encode_Ushort(&sp->uid, buf);
+ buf = encode_Ushort(&sp->euid, buf);
+ buf = encode_Ushort(&sp->suid, buf);
+ buf = encode_Ushort(&sp->gid, buf);
+ buf = encode_Ushort(&sp->egid, buf);
+ buf = encode_Ushort(&sp->sgid, buf);
+ buf = encode_Ushort(&sp->umask, buf);
+ buf = encode__userfs_types_004(&sp->groups, buf);
+ return buf;
+}
+
+
+unsigned char *encode_up_iattr(const up_iattr *sp, unsigned char *buf)
+{
+ buf = encode_Ulong(&sp->ia_valid, buf);
+ buf = encode_Ushort(&sp->ia_mode, buf);
+ buf = encode_Ushort(&sp->ia_uid, buf);
+ buf = encode_Ushort(&sp->ia_gid, buf);
+ buf = encode_long(&sp->ia_size, buf);
+ buf = encode_long(&sp->ia_atime, buf);
+ buf = encode_long(&sp->ia_mtime, buf);
+ buf = encode_long(&sp->ia_ctime, buf);
+ return buf;
+}
+
+
+unsigned char *encode_up_preamble(const up_preamble *sp, unsigned char *buf)
+{
+ buf = encode_short(&sp->version, buf);
+ buf = encode_long(&sp->seq, buf);
+ buf = encode_Uchar(&sp->op, buf);
+ buf = encode_Uchar(&sp->isreq, buf);
+ buf = encode_Ulong(&sp->size, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_repl(const upp_repl *sp, unsigned char *buf)
+{
+ buf = encode_short(&sp->version, buf);
+ buf = encode_long(&sp->seq, buf);
+ buf = encode_Uchar(&sp->op, buf);
+ buf = encode_Uchar(&sp->isreq, buf);
+ buf = encode_Ulong(&sp->size, buf);
+ buf = encode_long(&sp->err_no, buf);
+ return buf;
+}
+
+
+unsigned char *encode_up_inode(const up_inode *sp, unsigned char *buf)
+{
+ buf = encode_Ushort(&sp->mode, buf);
+ buf = encode_Ushort(&sp->nlink, buf);
+ buf = encode_Ushort(&sp->uid, buf);
+ buf = encode_Ushort(&sp->gid, buf);
+ buf = encode_long(&sp->size, buf);
+ buf = encode_long(&sp->atime, buf);
+ buf = encode_long(&sp->mtime, buf);
+ buf = encode_long(&sp->ctime, buf);
+ buf = encode_Ushort(&sp->rdev, buf);
+ buf = encode_Ulong(&sp->blksize, buf);
+ buf = encode_Ulong(&sp->blocks, buf);
+ return buf;
+}
+
+
+unsigned char *encode_up_name(const up_name *sp, unsigned char *buf)
+{
+ {
+ unsigned i;
+
+ buf = encode_Ulong(&sp->nelem, buf);
+ for(i = 0; i < sp->nelem; i++) {
+ buf = encode_char(&sp->elems[i], buf);
+ }
+ }
+ return buf;
+}
+
+
+unsigned char *encode_upp_iwrite_s(const upp_iwrite_s *sp, unsigned char *buf)
+{
+ buf = encode_up_inode(&sp->ino, buf);
+ buf = encode_up_handle(&sp->handle, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_iread_s(const upp_iread_s *sp, unsigned char *buf)
+{
+ buf = encode_up_handle(&sp->handle, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_iread_r(const upp_iread_r *sp, unsigned char *buf)
+{
+ buf = encode_up_handle(&sp->handle, buf);
+ buf = encode_up_inode(&sp->ino, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_unlink_s(const upp_unlink_s *sp, unsigned char *buf)
+{
+ buf = encode_up_handle(&sp->dir, buf);
+ buf = encode_up_name(&sp->name, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_readlink_s(const upp_readlink_s *sp, unsigned char *buf)
+{
+ buf = encode_up_handle(&sp->link, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_readlink_r(const upp_readlink_r *sp, unsigned char *buf)
+{
+ buf = encode_up_name(&sp->name, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_followlink_s(const upp_followlink_s *sp, unsigned char *buf)
+{
+ buf = encode_up_handle(&sp->dir, buf);
+ buf = encode_up_handle(&sp->link, buf);
+ buf = encode_long(&sp->flag, buf);
+ buf = encode_long(&sp->mode, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_followlink_r(const upp_followlink_r *sp, unsigned char *buf)
+{
+ buf = encode_up_name(&sp->path, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_create_s(const upp_create_s *sp, unsigned char *buf)
+{
+ buf = encode_long(&sp->mode, buf);
+ buf = encode_up_handle(&sp->dir, buf);
+ buf = encode_up_cred(&sp->cred, buf);
+ buf = encode_long(&sp->rdev, buf);
+ buf = encode_up_name(&sp->name, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_create_r(const upp_create_r *sp, unsigned char *buf)
+{
+ buf = encode_up_handle(&sp->file, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_lookup_s(const upp_lookup_s *sp, unsigned char *buf)
+{
+ buf = encode_up_handle(&sp->dir, buf);
+ buf = encode_up_name(&sp->name, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_lookup_r(const upp_lookup_r *sp, unsigned char *buf)
+{
+ buf = encode_up_handle(&sp->handle, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_read_s(const upp_read_s *sp, unsigned char *buf)
+{
+ buf = encode_up_handle(&sp->file, buf);
+ buf = encode_long(&sp->off, buf);
+ buf = encode_long(&sp->size, buf);
+ buf = encode_Ulong(&sp->ctok, buf);
+ return buf;
+}
+
+
+unsigned char *encode__userfs_types_006(const _userfs_types_006 *sp, unsigned char *buf)
+{
+ {
+ unsigned i;
+
+ buf = encode_Ulong(&sp->nelem, buf);
+ for(i = 0; i < sp->nelem; i++) {
+ buf = encode_Uchar(&sp->elems[i], buf);
+ }
+ }
+ return buf;
+}
+
+
+unsigned char *encode_upp_read_r(const upp_read_r *sp, unsigned char *buf)
+{
+ buf = encode__userfs_types_006(&sp->data, buf);
+ return buf;
+}
+
+
+unsigned char *encode__userfs_types_007(const _userfs_types_007 *sp, unsigned char *buf)
+{
+ {
+ unsigned i;
+
+ buf = encode_Ulong(&sp->nelem, buf);
+ for(i = 0; i < sp->nelem; i++) {
+ buf = encode_Uchar(&sp->elems[i], buf);
+ }
+ }
+ return buf;
+}
+
+
+unsigned char *encode_upp_write_s(const upp_write_s *sp, unsigned char *buf)
+{
+ buf = encode_up_handle(&sp->file, buf);
+ buf = encode_long(&sp->off, buf);
+ buf = encode_Ulong(&sp->ctok, buf);
+ buf = encode__userfs_types_007(&sp->data, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_write_r(const upp_write_r *sp, unsigned char *buf)
+{
+ buf = encode_long(&sp->wrote, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_readdir_s(const upp_readdir_s *sp, unsigned char *buf)
+{
+ buf = encode_up_handle(&sp->dir, buf);
+ buf = encode_long(&sp->off, buf);
+ buf = encode_Ulong(&sp->ctok, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_readdir_r(const upp_readdir_r *sp, unsigned char *buf)
+{
+ buf = encode_up_handle(&sp->file, buf);
+ buf = encode_long(&sp->off, buf);
+ buf = encode_up_name(&sp->name, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_multireaddir_s(const upp_multireaddir_s *sp, unsigned char *buf)
+{
+ buf = encode_upp_readdir_s(sp, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_multireaddir_r(const upp_multireaddir_r *sp, unsigned char *buf)
+{
+ {
+ unsigned i;
+
+ buf = encode_Ulong(&sp->nelem, buf);
+ for(i = 0; i < sp->nelem; i++) {
+ buf = encode_upp_readdir_r(&sp->elems[i], buf);
+ }
+ }
+ return buf;
+}
+
+
+unsigned char *encode_upp_mount_r(const upp_mount_r *sp, unsigned char *buf)
+{
+ buf = encode_up_handle(&sp->root, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_iput_s(const upp_iput_s *sp, unsigned char *buf)
+{
+ buf = encode_up_handle(&sp->handle, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_open_s(const upp_open_s *sp, unsigned char *buf)
+{
+ buf = encode_up_cred(&sp->cred, buf);
+ buf = encode_up_handle(&sp->file, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_open_r(const upp_open_r *sp, unsigned char *buf)
+{
+ buf = encode_Ulong(&sp->ctok, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_close_s(const upp_close_s *sp, unsigned char *buf)
+{
+ buf = encode_up_handle(&sp->file, buf);
+ buf = encode_Ulong(&sp->ctok, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_permission_s(const upp_permission_s *sp, unsigned char *buf)
+{
+ buf = encode_up_cred(&sp->cred, buf);
+ buf = encode_up_handle(&sp->file, buf);
+ buf = encode_long(&sp->mask, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_rename_s(const upp_rename_s *sp, unsigned char *buf)
+{
+ buf = encode_up_handle(&sp->odir, buf);
+ buf = encode_up_name(&sp->oname, buf);
+ buf = encode_up_handle(&sp->ndir, buf);
+ buf = encode_up_name(&sp->nname, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_link_s(const upp_link_s *sp, unsigned char *buf)
+{
+ buf = encode_up_handle(&sp->ofile, buf);
+ buf = encode_up_handle(&sp->dir, buf);
+ buf = encode_up_name(&sp->name, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_symlink_s(const upp_symlink_s *sp, unsigned char *buf)
+{
+ buf = encode_up_handle(&sp->dir, buf);
+ buf = encode_up_name(&sp->name, buf);
+ buf = encode_up_name(&sp->symname, buf);
+ buf = encode_up_cred(&sp->cred, buf);
+ return buf;
+}
+
+
+unsigned char *encode__userfs_types_011(const _userfs_types_011 *sp, unsigned char *buf)
+{
+ {
+ unsigned i;
+
+ for(i = 0; i < 2; i++) {
+ buf = encode_long(&(*sp)[i], buf);
+ }
+ }
+ return buf;
+}
+
+
+unsigned char *encode_upp_statfs_r(const upp_statfs_r *sp, unsigned char *buf)
+{
+ buf = encode_long(&sp->bsize, buf);
+ buf = encode_long(&sp->blocks, buf);
+ buf = encode_long(&sp->bfree, buf);
+ buf = encode_long(&sp->bavail, buf);
+ buf = encode_long(&sp->files, buf);
+ buf = encode_long(&sp->ffree, buf);
+ buf = encode__userfs_types_011(&sp->fsid, buf);
+ buf = encode_long(&sp->namelen, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_truncate_s(const upp_truncate_s *sp, unsigned char *buf)
+{
+ buf = encode_up_handle(&sp->file, buf);
+ buf = encode_long(&sp->size, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_notify_change_s(const upp_notify_change_s *sp, unsigned char *buf)
+{
+ buf = encode_up_handle(&sp->handle, buf);
+ buf = encode_up_iattr(&sp->iattr, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_inode_valid_s(const upp_inode_valid_s *sp, unsigned char *buf)
+{
+ buf = encode_up_handle(&sp->handle, buf);
+ buf = encode_Ulong(&sp->version, buf);
+ return buf;
+}
+
+
+unsigned char *encode_upp_inode_valid_r(const upp_inode_valid_r *sp, unsigned char *buf)
+{
+ buf = encode_Ulong(&sp->version, buf);
+ buf = encode_char(&sp->valid, buf);
+ return buf;
+}
+
+
+unsigned char *decode__userfs_types_001(_userfs_types_001 *sp, unsigned char *buf)
+{
+ {
+ unsigned i;
+
+ for(i = 0; i < 32; i++) {
+ buf = decode_Ulong(sp[i], buf);
+ }
+ }
+ return buf;
+}
+
+
+unsigned char *decode__userfs_types_002(_userfs_types_002 *sp, unsigned char *buf)
+{
+ {
+ unsigned i;
+
+ for(i = 0; i < 2; i++) {
+ buf = decode_long(sp[i], buf);
+ }
+ }
+ return buf;
+}
+
+
+unsigned char *decode_up_handle(up_handle *sp, unsigned char *buf)
+{
+ buf = decode_Ulong(&sp->handle, buf);
+ return buf;
+}
+
+
+unsigned char *decode_uf_uid_t(uf_uid_t *sp, unsigned char *buf)
+{
+ buf = decode_Ushort(sp, buf);
+ return buf;
+}
+
+
+unsigned char *decode__userfs_types_004(_userfs_types_004 *sp, unsigned char *buf)
+{
+ {
+ unsigned i;
+ buf = decode_Ulong(&sp->nelem, buf);
+ if (sp->nelem == 0)
+ {
+ sp->elems = 0;
+ return buf;
+ }
+ sp->elems = (long *)ALLOC(sizeof(long) * sp->nelem);
+ if (sp->elems == 0) {
+ return buf;
+ }
+ for(i = 0; i < sp->nelem; i++) {
+ buf = decode_long(&sp->elems[i], buf);
+ }
+ }
+ return buf;
+}
+
+
+unsigned char *decode_up_cred(up_cred *sp, unsigned char *buf)
+{
+ buf = decode_Ushort(&sp->uid, buf);
+ buf = decode_Ushort(&sp->euid, buf);
+ buf = decode_Ushort(&sp->suid, buf);
+ buf = decode_Ushort(&sp->gid, buf);
+ buf = decode_Ushort(&sp->egid, buf);
+ buf = decode_Ushort(&sp->sgid, buf);
+ buf = decode_Ushort(&sp->umask, buf);
+ buf = decode__userfs_types_004(&sp->groups, buf);
+ return buf;
+}
+
+
+unsigned char *decode_up_iattr(up_iattr *sp, unsigned char *buf)
+{
+ buf = decode_Ulong(&sp->ia_valid, buf);
+ buf = decode_Ushort(&sp->ia_mode, buf);
+ buf = decode_Ushort(&sp->ia_uid, buf);
+ buf = decode_Ushort(&sp->ia_gid, buf);
+ buf = decode_long(&sp->ia_size, buf);
+ buf = decode_long(&sp->ia_atime, buf);
+ buf = decode_long(&sp->ia_mtime, buf);
+ buf = decode_long(&sp->ia_ctime, buf);
+ return buf;
+}
+
+
+unsigned char *decode_up_preamble(up_preamble *sp, unsigned char *buf)
+{
+ buf = decode_short(&sp->version, buf);
+ buf = decode_long(&sp->seq, buf);
+ buf = decode_Uchar(&sp->op, buf);
+ buf = decode_Uchar(&sp->isreq, buf);
+ buf = decode_Ulong(&sp->size, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_repl(upp_repl *sp, unsigned char *buf)
+{
+ buf = decode_short(&sp->version, buf);
+ buf = decode_long(&sp->seq, buf);
+ buf = decode_Uchar(&sp->op, buf);
+ buf = decode_Uchar(&sp->isreq, buf);
+ buf = decode_Ulong(&sp->size, buf);
+ buf = decode_long(&sp->err_no, buf);
+ return buf;
+}
+
+
+unsigned char *decode_up_inode(up_inode *sp, unsigned char *buf)
+{
+ buf = decode_Ushort(&sp->mode, buf);
+ buf = decode_Ushort(&sp->nlink, buf);
+ buf = decode_Ushort(&sp->uid, buf);
+ buf = decode_Ushort(&sp->gid, buf);
+ buf = decode_long(&sp->size, buf);
+ buf = decode_long(&sp->atime, buf);
+ buf = decode_long(&sp->mtime, buf);
+ buf = decode_long(&sp->ctime, buf);
+ buf = decode_Ushort(&sp->rdev, buf);
+ buf = decode_Ulong(&sp->blksize, buf);
+ buf = decode_Ulong(&sp->blocks, buf);
+ return buf;
+}
+
+
+unsigned char *decode_up_name(up_name *sp, unsigned char *buf)
+{
+ {
+ unsigned i;
+ buf = decode_Ulong(&sp->nelem, buf);
+ if (sp->nelem == 0)
+ {
+ sp->elems = 0;
+ return buf;
+ }
+ sp->elems = (char *)ALLOC(sizeof(char) * sp->nelem);
+ if (sp->elems == 0) {
+ return buf;
+ }
+ for(i = 0; i < sp->nelem; i++) {
+ buf = decode_char(&sp->elems[i], buf);
+ }
+ }
+ return buf;
+}
+
+
+unsigned char *decode_upp_iwrite_s(upp_iwrite_s *sp, unsigned char *buf)
+{
+ buf = decode_up_inode(&sp->ino, buf);
+ buf = decode_up_handle(&sp->handle, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_iread_s(upp_iread_s *sp, unsigned char *buf)
+{
+ buf = decode_up_handle(&sp->handle, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_iread_r(upp_iread_r *sp, unsigned char *buf)
+{
+ buf = decode_up_handle(&sp->handle, buf);
+ buf = decode_up_inode(&sp->ino, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_unlink_s(upp_unlink_s *sp, unsigned char *buf)
+{
+ buf = decode_up_handle(&sp->dir, buf);
+ buf = decode_up_name(&sp->name, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_readlink_s(upp_readlink_s *sp, unsigned char *buf)
+{
+ buf = decode_up_handle(&sp->link, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_readlink_r(upp_readlink_r *sp, unsigned char *buf)
+{
+ buf = decode_up_name(&sp->name, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_followlink_s(upp_followlink_s *sp, unsigned char *buf)
+{
+ buf = decode_up_handle(&sp->dir, buf);
+ buf = decode_up_handle(&sp->link, buf);
+ buf = decode_long(&sp->flag, buf);
+ buf = decode_long(&sp->mode, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_followlink_r(upp_followlink_r *sp, unsigned char *buf)
+{
+ buf = decode_up_name(&sp->path, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_create_s(upp_create_s *sp, unsigned char *buf)
+{
+ buf = decode_long(&sp->mode, buf);
+ buf = decode_up_handle(&sp->dir, buf);
+ buf = decode_up_cred(&sp->cred, buf);
+ buf = decode_long(&sp->rdev, buf);
+ buf = decode_up_name(&sp->name, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_create_r(upp_create_r *sp, unsigned char *buf)
+{
+ buf = decode_up_handle(&sp->file, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_lookup_s(upp_lookup_s *sp, unsigned char *buf)
+{
+ buf = decode_up_handle(&sp->dir, buf);
+ buf = decode_up_name(&sp->name, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_lookup_r(upp_lookup_r *sp, unsigned char *buf)
+{
+ buf = decode_up_handle(&sp->handle, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_read_s(upp_read_s *sp, unsigned char *buf)
+{
+ buf = decode_up_handle(&sp->file, buf);
+ buf = decode_long(&sp->off, buf);
+ buf = decode_long(&sp->size, buf);
+ buf = decode_Ulong(&sp->ctok, buf);
+ return buf;
+}
+
+
+unsigned char *decode__userfs_types_006(_userfs_types_006 *sp, unsigned char *buf)
+{
+ {
+ unsigned i;
+ buf = decode_Ulong(&sp->nelem, buf);
+ if (sp->nelem == 0)
+ {
+ sp->elems = 0;
+ return buf;
+ }
+ sp->elems = (Uchar *)ALLOC(sizeof(Uchar) * sp->nelem);
+ if (sp->elems == 0) {
+ return buf;
+ }
+ for(i = 0; i < sp->nelem; i++) {
+ buf = decode_Uchar(&sp->elems[i], buf);
+ }
+ }
+ return buf;
+}
+
+
+unsigned char *decode_upp_read_r(upp_read_r *sp, unsigned char *buf)
+{
+ buf = decode__userfs_types_006(&sp->data, buf);
+ return buf;
+}
+
+
+unsigned char *decode__userfs_types_007(_userfs_types_007 *sp, unsigned char *buf)
+{
+ {
+ unsigned i;
+ buf = decode_Ulong(&sp->nelem, buf);
+ if (sp->nelem == 0)
+ {
+ sp->elems = 0;
+ return buf;
+ }
+ sp->elems = (Uchar *)ALLOC(sizeof(Uchar) * sp->nelem);
+ if (sp->elems == 0) {
+ return buf;
+ }
+ for(i = 0; i < sp->nelem; i++) {
+ buf = decode_Uchar(&sp->elems[i], buf);
+ }
+ }
+ return buf;
+}
+
+
+unsigned char *decode_upp_write_s(upp_write_s *sp, unsigned char *buf)
+{
+ buf = decode_up_handle(&sp->file, buf);
+ buf = decode_long(&sp->off, buf);
+ buf = decode_Ulong(&sp->ctok, buf);
+ buf = decode__userfs_types_007(&sp->data, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_write_r(upp_write_r *sp, unsigned char *buf)
+{
+ buf = decode_long(&sp->wrote, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_readdir_s(upp_readdir_s *sp, unsigned char *buf)
+{
+ buf = decode_up_handle(&sp->dir, buf);
+ buf = decode_long(&sp->off, buf);
+ buf = decode_Ulong(&sp->ctok, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_readdir_r(upp_readdir_r *sp, unsigned char *buf)
+{
+ buf = decode_up_handle(&sp->file, buf);
+ buf = decode_long(&sp->off, buf);
+ buf = decode_up_name(&sp->name, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_multireaddir_s(upp_multireaddir_s *sp, unsigned char *buf)
+{
+ buf = decode_upp_readdir_s(sp, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_multireaddir_r(upp_multireaddir_r *sp, unsigned char *buf)
+{
+ {
+ unsigned i;
+ buf = decode_Ulong(&sp->nelem, buf);
+ if (sp->nelem == 0)
+ {
+ sp->elems = 0;
+ return buf;
+ }
+ sp->elems = (upp_readdir_r *)ALLOC(sizeof(upp_readdir_r) * sp->nelem);
+ if (sp->elems == 0) {
+ return buf;
+ }
+ for(i = 0; i < sp->nelem; i++) {
+ buf = decode_upp_readdir_r(&sp->elems[i], buf);
+ }
+ }
+ return buf;
+}
+
+
+unsigned char *decode_upp_mount_r(upp_mount_r *sp, unsigned char *buf)
+{
+ buf = decode_up_handle(&sp->root, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_iput_s(upp_iput_s *sp, unsigned char *buf)
+{
+ buf = decode_up_handle(&sp->handle, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_open_s(upp_open_s *sp, unsigned char *buf)
+{
+ buf = decode_up_cred(&sp->cred, buf);
+ buf = decode_up_handle(&sp->file, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_open_r(upp_open_r *sp, unsigned char *buf)
+{
+ buf = decode_Ulong(&sp->ctok, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_close_s(upp_close_s *sp, unsigned char *buf)
+{
+ buf = decode_up_handle(&sp->file, buf);
+ buf = decode_Ulong(&sp->ctok, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_permission_s(upp_permission_s *sp, unsigned char *buf)
+{
+ buf = decode_up_cred(&sp->cred, buf);
+ buf = decode_up_handle(&sp->file, buf);
+ buf = decode_long(&sp->mask, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_rename_s(upp_rename_s *sp, unsigned char *buf)
+{
+ buf = decode_up_handle(&sp->odir, buf);
+ buf = decode_up_name(&sp->oname, buf);
+ buf = decode_up_handle(&sp->ndir, buf);
+ buf = decode_up_name(&sp->nname, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_link_s(upp_link_s *sp, unsigned char *buf)
+{
+ buf = decode_up_handle(&sp->ofile, buf);
+ buf = decode_up_handle(&sp->dir, buf);
+ buf = decode_up_name(&sp->name, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_symlink_s(upp_symlink_s *sp, unsigned char *buf)
+{
+ buf = decode_up_handle(&sp->dir, buf);
+ buf = decode_up_name(&sp->name, buf);
+ buf = decode_up_name(&sp->symname, buf);
+ buf = decode_up_cred(&sp->cred, buf);
+ return buf;
+}
+
+
+unsigned char *decode__userfs_types_011(_userfs_types_011 *sp, unsigned char *buf)
+{
+ {
+ unsigned i;
+
+ for(i = 0; i < 2; i++) {
+ buf = decode_long(sp[i], buf);
+ }
+ }
+ return buf;
+}
+
+
+unsigned char *decode_upp_statfs_r(upp_statfs_r *sp, unsigned char *buf)
+{
+ buf = decode_long(&sp->bsize, buf);
+ buf = decode_long(&sp->blocks, buf);
+ buf = decode_long(&sp->bfree, buf);
+ buf = decode_long(&sp->bavail, buf);
+ buf = decode_long(&sp->files, buf);
+ buf = decode_long(&sp->ffree, buf);
+ buf = decode__userfs_types_011(&sp->fsid, buf);
+ buf = decode_long(&sp->namelen, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_truncate_s(upp_truncate_s *sp, unsigned char *buf)
+{
+ buf = decode_up_handle(&sp->file, buf);
+ buf = decode_long(&sp->size, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_notify_change_s(upp_notify_change_s *sp, unsigned char *buf)
+{
+ buf = decode_up_handle(&sp->handle, buf);
+ buf = decode_up_iattr(&sp->iattr, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_inode_valid_s(upp_inode_valid_s *sp, unsigned char *buf)
+{
+ buf = decode_up_handle(&sp->handle, buf);
+ buf = decode_Ulong(&sp->version, buf);
+ return buf;
+}
+
+
+unsigned char *decode_upp_inode_valid_r(upp_inode_valid_r *sp, unsigned char *buf)
+{
+ buf = decode_Ulong(&sp->version, buf);
+ buf = decode_char(&sp->valid, buf);
+ return buf;
+}
+unsigned int sizeof__userfs_types_001(const _userfs_types_001 *sp)
+{
+ unsigned int sz=0;
+
+ {
+ unsigned i;
+ for(i = 0; i < 32; i++) {
+ sz += sizeof_Ulong(sp[i]);
+ }
+ }
+ return sz;
+}
+unsigned int sizeof__userfs_types_002(const _userfs_types_002 *sp)
+{
+ unsigned int sz=0;
+
+ {
+ unsigned i;
+ for(i = 0; i < 2; i++) {
+ sz += sizeof_long(sp[i]);
+ }
+ }
+ return sz;
+}
+unsigned int sizeof_up_handle(const up_handle *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_Ulong(&sp->handle);
+ return sz;
+}
+unsigned int sizeof_uf_uid_t(const uf_uid_t *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_Ushort(sp);
+ return sz;
+}
+unsigned int sizeof__userfs_types_004(const _userfs_types_004 *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_Ulong(&sp->nelem);
+ {
+ unsigned i;
+ for(i = 0; i < sp->nelem; i++) {
+ sz += sizeof_long(&sp->elems[i]);
+ }
+ }
+ return sz;
+}
+unsigned int sizeof_up_cred(const up_cred *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_Ushort(&sp->uid);
+ sz += sizeof_Ushort(&sp->euid);
+ sz += sizeof_Ushort(&sp->suid);
+ sz += sizeof_Ushort(&sp->gid);
+ sz += sizeof_Ushort(&sp->egid);
+ sz += sizeof_Ushort(&sp->sgid);
+ sz += sizeof_Ushort(&sp->umask);
+ sz += sizeof__userfs_types_004(&sp->groups);
+ return sz;
+}
+unsigned int sizeof_up_iattr(const up_iattr *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_Ulong(&sp->ia_valid);
+ sz += sizeof_Ushort(&sp->ia_mode);
+ sz += sizeof_Ushort(&sp->ia_uid);
+ sz += sizeof_Ushort(&sp->ia_gid);
+ sz += sizeof_long(&sp->ia_size);
+ sz += sizeof_long(&sp->ia_atime);
+ sz += sizeof_long(&sp->ia_mtime);
+ sz += sizeof_long(&sp->ia_ctime);
+ return sz;
+}
+unsigned int sizeof_up_preamble(const up_preamble *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_short(&sp->version);
+ sz += sizeof_long(&sp->seq);
+ sz += sizeof_Uchar(&sp->op);
+ sz += sizeof_Uchar(&sp->isreq);
+ sz += sizeof_Ulong(&sp->size);
+ return sz;
+}
+unsigned int sizeof_upp_repl(const upp_repl *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_short(&sp->version);
+ sz += sizeof_long(&sp->seq);
+ sz += sizeof_Uchar(&sp->op);
+ sz += sizeof_Uchar(&sp->isreq);
+ sz += sizeof_Ulong(&sp->size);
+ sz += sizeof_long(&sp->err_no);
+ return sz;
+}
+unsigned int sizeof_up_inode(const up_inode *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_Ushort(&sp->mode);
+ sz += sizeof_Ushort(&sp->nlink);
+ sz += sizeof_Ushort(&sp->uid);
+ sz += sizeof_Ushort(&sp->gid);
+ sz += sizeof_long(&sp->size);
+ sz += sizeof_long(&sp->atime);
+ sz += sizeof_long(&sp->mtime);
+ sz += sizeof_long(&sp->ctime);
+ sz += sizeof_Ushort(&sp->rdev);
+ sz += sizeof_Ulong(&sp->blksize);
+ sz += sizeof_Ulong(&sp->blocks);
+ return sz;
+}
+unsigned int sizeof_up_name(const up_name *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_Ulong(&sp->nelem);
+ {
+ unsigned i;
+ for(i = 0; i < sp->nelem; i++) {
+ sz += sizeof_char(&sp->elems[i]);
+ }
+ }
+ return sz;
+}
+unsigned int sizeof_upp_iwrite_s(const upp_iwrite_s *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_inode(&sp->ino);
+ sz += sizeof_up_handle(&sp->handle);
+ return sz;
+}
+unsigned int sizeof_upp_iread_s(const upp_iread_s *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_handle(&sp->handle);
+ return sz;
+}
+unsigned int sizeof_upp_iread_r(const upp_iread_r *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_handle(&sp->handle);
+ sz += sizeof_up_inode(&sp->ino);
+ return sz;
+}
+unsigned int sizeof_upp_unlink_s(const upp_unlink_s *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_handle(&sp->dir);
+ sz += sizeof_up_name(&sp->name);
+ return sz;
+}
+unsigned int sizeof_upp_readlink_s(const upp_readlink_s *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_handle(&sp->link);
+ return sz;
+}
+unsigned int sizeof_upp_readlink_r(const upp_readlink_r *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_name(&sp->name);
+ return sz;
+}
+unsigned int sizeof_upp_followlink_s(const upp_followlink_s *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_handle(&sp->dir);
+ sz += sizeof_up_handle(&sp->link);
+ sz += sizeof_long(&sp->flag);
+ sz += sizeof_long(&sp->mode);
+ return sz;
+}
+unsigned int sizeof_upp_followlink_r(const upp_followlink_r *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_name(&sp->path);
+ return sz;
+}
+unsigned int sizeof_upp_create_s(const upp_create_s *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_long(&sp->mode);
+ sz += sizeof_up_handle(&sp->dir);
+ sz += sizeof_up_cred(&sp->cred);
+ sz += sizeof_long(&sp->rdev);
+ sz += sizeof_up_name(&sp->name);
+ return sz;
+}
+unsigned int sizeof_upp_create_r(const upp_create_r *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_handle(&sp->file);
+ return sz;
+}
+unsigned int sizeof_upp_lookup_s(const upp_lookup_s *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_handle(&sp->dir);
+ sz += sizeof_up_name(&sp->name);
+ return sz;
+}
+unsigned int sizeof_upp_lookup_r(const upp_lookup_r *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_handle(&sp->handle);
+ return sz;
+}
+unsigned int sizeof_upp_read_s(const upp_read_s *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_handle(&sp->file);
+ sz += sizeof_long(&sp->off);
+ sz += sizeof_long(&sp->size);
+ sz += sizeof_Ulong(&sp->ctok);
+ return sz;
+}
+unsigned int sizeof__userfs_types_006(const _userfs_types_006 *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_Ulong(&sp->nelem);
+ {
+ unsigned i;
+ for(i = 0; i < sp->nelem; i++) {
+ sz += sizeof_Uchar(&sp->elems[i]);
+ }
+ }
+ return sz;
+}
+unsigned int sizeof_upp_read_r(const upp_read_r *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof__userfs_types_006(&sp->data);
+ return sz;
+}
+unsigned int sizeof__userfs_types_007(const _userfs_types_007 *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_Ulong(&sp->nelem);
+ {
+ unsigned i;
+ for(i = 0; i < sp->nelem; i++) {
+ sz += sizeof_Uchar(&sp->elems[i]);
+ }
+ }
+ return sz;
+}
+unsigned int sizeof_upp_write_s(const upp_write_s *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_handle(&sp->file);
+ sz += sizeof_long(&sp->off);
+ sz += sizeof_Ulong(&sp->ctok);
+ sz += sizeof__userfs_types_007(&sp->data);
+ return sz;
+}
+unsigned int sizeof_upp_write_r(const upp_write_r *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_long(&sp->wrote);
+ return sz;
+}
+unsigned int sizeof_upp_readdir_s(const upp_readdir_s *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_handle(&sp->dir);
+ sz += sizeof_long(&sp->off);
+ sz += sizeof_Ulong(&sp->ctok);
+ return sz;
+}
+unsigned int sizeof_upp_readdir_r(const upp_readdir_r *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_handle(&sp->file);
+ sz += sizeof_long(&sp->off);
+ sz += sizeof_up_name(&sp->name);
+ return sz;
+}
+unsigned int sizeof_upp_multireaddir_s(const upp_multireaddir_s *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_upp_readdir_s(sp);
+ return sz;
+}
+unsigned int sizeof_upp_multireaddir_r(const upp_multireaddir_r *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_Ulong(&sp->nelem);
+ {
+ unsigned i;
+ for(i = 0; i < sp->nelem; i++) {
+ sz += sizeof_upp_readdir_r(&sp->elems[i]);
+ }
+ }
+ return sz;
+}
+unsigned int sizeof_upp_mount_r(const upp_mount_r *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_handle(&sp->root);
+ return sz;
+}
+unsigned int sizeof_upp_iput_s(const upp_iput_s *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_handle(&sp->handle);
+ return sz;
+}
+unsigned int sizeof_upp_open_s(const upp_open_s *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_cred(&sp->cred);
+ sz += sizeof_up_handle(&sp->file);
+ return sz;
+}
+unsigned int sizeof_upp_open_r(const upp_open_r *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_Ulong(&sp->ctok);
+ return sz;
+}
+unsigned int sizeof_upp_close_s(const upp_close_s *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_handle(&sp->file);
+ sz += sizeof_Ulong(&sp->ctok);
+ return sz;
+}
+unsigned int sizeof_upp_permission_s(const upp_permission_s *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_cred(&sp->cred);
+ sz += sizeof_up_handle(&sp->file);
+ sz += sizeof_long(&sp->mask);
+ return sz;
+}
+unsigned int sizeof_upp_rename_s(const upp_rename_s *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_handle(&sp->odir);
+ sz += sizeof_up_name(&sp->oname);
+ sz += sizeof_up_handle(&sp->ndir);
+ sz += sizeof_up_name(&sp->nname);
+ return sz;
+}
+unsigned int sizeof_upp_link_s(const upp_link_s *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_handle(&sp->ofile);
+ sz += sizeof_up_handle(&sp->dir);
+ sz += sizeof_up_name(&sp->name);
+ return sz;
+}
+unsigned int sizeof_upp_symlink_s(const upp_symlink_s *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_handle(&sp->dir);
+ sz += sizeof_up_name(&sp->name);
+ sz += sizeof_up_name(&sp->symname);
+ sz += sizeof_up_cred(&sp->cred);
+ return sz;
+}
+unsigned int sizeof__userfs_types_011(const _userfs_types_011 *sp)
+{
+ unsigned int sz=0;
+
+ {
+ unsigned i;
+ for(i = 0; i < 2; i++) {
+ sz += sizeof_long(sp[i]);
+ }
+ }
+ return sz;
+}
+unsigned int sizeof_upp_statfs_r(const upp_statfs_r *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_long(&sp->bsize);
+ sz += sizeof_long(&sp->blocks);
+ sz += sizeof_long(&sp->bfree);
+ sz += sizeof_long(&sp->bavail);
+ sz += sizeof_long(&sp->files);
+ sz += sizeof_long(&sp->ffree);
+ sz += sizeof__userfs_types_011(&sp->fsid);
+ sz += sizeof_long(&sp->namelen);
+ return sz;
+}
+unsigned int sizeof_upp_truncate_s(const upp_truncate_s *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_handle(&sp->file);
+ sz += sizeof_long(&sp->size);
+ return sz;
+}
+unsigned int sizeof_upp_notify_change_s(const upp_notify_change_s *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_handle(&sp->handle);
+ sz += sizeof_up_iattr(&sp->iattr);
+ return sz;
+}
+unsigned int sizeof_upp_inode_valid_s(const upp_inode_valid_s *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_up_handle(&sp->handle);
+ sz += sizeof_Ulong(&sp->version);
+ return sz;
+}
+unsigned int sizeof_upp_inode_valid_r(const upp_inode_valid_r *sp)
+{
+ unsigned int sz=0;
+
+ sz += sizeof_Ulong(&sp->version);
+ sz += sizeof_char(&sp->valid);
+ return sz;
+}
Added: trunk/kernel/src/linux/userfs_fs_i.h
==============================================================================
--- trunk/kernel/src/linux/userfs_fs_i.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/kernel/src/linux/userfs_fs_i.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,25 @@
+/*
+ * Inode data for userfs
+ */
+
+#ifndef _LINUX_USERFS_FS_I
+#define _LINUX_USERFS_FS_I
+
+/*
+ * What a handle looks like
+ */
+typedef struct
+{
+ unsigned long handle;
+} up_handle;
+
+typedef unsigned long up_version;
+
+struct userfs_inode_info
+{
+ up_handle handle;
+ struct userfs_dir_ra *dir_ra;
+ up_version version;
+};
+
+#endif /* _LINUX_USERFS_FS_I */
Added: trunk/kernel/src/inode.c
==============================================================================
--- trunk/kernel/src/inode.c 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/kernel/src/inode.c 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,785 @@
+/*
+ * General inody operations for user process filesystem implmentation
+ *
+ * Jeremy Fitzhardinge <jeremy at sw.oz.au>, 1993-1996
+ */
+
+#include "userfs.h"
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/stat.h>
+#include <linux/errno.h>
+#include <linux/locks.h>
+#include <linux/userfs_fs.h>
+#include <linux/userfs_fs_sb.h>
+#include <linux/assert.h>
+#include <asm/segment.h>
+#include <linux/string.h>
+#include <asm/uaccess.h>
+
+/* this following code relies on the kernel being locked with SMP */
+
+/* see linux/fs/inode.c */
+void __wait_on_inode(struct inode * inode)
+{
+ DECLARE_WAITQUEUE(wait, current);
+
+ add_wait_queue(&inode->i_wait, &wait);
+repeat:
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ if (inode->i_state & I_LOCK) {
+ schedule();
+ goto repeat;
+ }
+ remove_wait_queue(&inode->i_wait, &wait);
+ current->state = TASK_RUNNING;
+}
+
+/* see linux/fs/inode.c */
+void wait_on_inode(struct inode * inode)
+{
+ if(inode->i_state & I_LOCK)
+ __wait_on_inode(inode);
+}
+
+void userfs_lock_inode(struct inode * inode)
+{
+ wait_on_inode(inode);
+ inode->i_state |= I_LOCK;
+}
+
+void userfs_unlock_inode(struct inode * inode)
+{
+ inode->i_state &= ~I_LOCK;
+ wake_up(&inode->i_wait);
+}
+
+k_static struct dentry *userfs_lookup(struct inode *dir, struct dentry *de)
+{
+ int ret = -ENOENT;
+ up_preamble pre;
+ upp_repl repl;
+ upp_lookup_s snd;
+ upp_lookup_r rcv;
+ struct inode *result = NULL;
+
+#ifdef DEBUG
+ printk("userfs_lookup(%p,%p)\n",dir,de);
+#endif
+
+ if (!dir)
+ return ERR_PTR(-ENOENT);
+
+ if (!S_ISDIR(dir->i_mode))
+ {
+ return ERR_PTR(-ENOTDIR);
+ }
+
+ userfs_genpkt(dir->i_sb, &pre, userfs_up_lookup);
+
+ snd.name.nelem = de->d_name.len;
+ snd.name.elems = (char *)de->d_name.name;
+ snd.dir = U_INOP(dir)->handle;
+
+ if ((ret = userfs_doop(dir->i_sb, &pre, &repl,
+ upp_lookup_s, &snd,
+ upp_lookup_r, &rcv)) != 0)
+ printk("userfs_lookup: userfs_doop failed %d\n", ret);
+
+ if (ret != 0)
+ return ERR_PTR(ret);
+
+ if (repl.err_no == 0)
+ {
+ result = iget(dir->i_sb, rcv.handle.handle);
+ if(result)
+ {
+ U_INOP(result)->handle.handle = rcv.handle.handle;
+ }
+ else
+ {
+ return ERR_PTR(-EACCES);
+ }
+ }
+
+ /*
+ * Must add the directory entry even if we can't find one
+ * so that the kernel can create new entries.
+ */
+ d_add(de,result);
+
+ return NULL;
+}
+
+void userfs_setcred(up_cred *cr)
+{
+ cr->uid = current->uid;
+ cr->suid = current->suid;
+ cr->euid = current->euid;
+ cr->gid = current->gid;
+ cr->sgid = current->sgid;
+ cr->egid = current->egid;
+ cr->umask = current->fs->umask;
+
+ cr->groups.elems = (long *)current->groups;
+ cr->groups.nelem = current->ngroups;
+}
+
+/*
+ * This code is common to create, mkdir and mknod
+ */
+k_static int do_create(struct inode *dir, struct dentry *de,
+ int mode, dev_t rdev)
+{
+ struct inode *ino = NULL;
+ int ret = 0;
+ up_preamble pre;
+ upp_repl repl;
+ upp_create_s snd;
+ upp_create_r rcv;
+
+#ifdef DEBUG
+ printk("do_create(...)\n");
+#endif
+
+ if (!dir || !S_ISDIR(dir->i_mode))
+ {
+ return -ENOTDIR;
+ }
+
+ userfs_lock_inode(dir);
+
+ dir->i_version = ++event;
+ userfs_genpkt(dir->i_sb, &pre, userfs_up_create);
+
+ snd.mode = mode;
+ snd.dir = U_INOP(dir)->handle;
+ userfs_setcred(&snd.cred);
+ snd.name.elems = (char *)de->d_name.name;
+ snd.name.nelem = de->d_name.len;
+ snd.rdev = rdev;
+
+ if ((ret = userfs_doop(dir->i_sb, &pre, &repl,
+ upp_create_s, &snd, upp_create_r, &rcv)) != 0)
+ {
+ printk("do_create(userfs): userfs_doop failed: %d\n", ret);
+ if (ret==-ERESTARTSYS)
+ printk("do_create(userfs): userfs_doop will be restarted\n");
+ goto out;
+ }
+
+ if(repl.err_no)
+ {
+ ret = -repl.err_no;
+ goto out;
+ }
+
+ assert(dir->i_sb != NULL);
+ ino = get_empty_inode();
+ if (ino == NULL)
+ {
+ printk("userfs_create: iget failed for %lx\n", rcv.file.handle);
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ U_INOP(ino)->handle.handle = rcv.file.handle;
+ ino->i_ino = rcv.file.handle;
+ ino->i_sb = dir->i_sb;
+
+ userfs_read_inode(ino);
+
+ insert_inode_hash(ino);
+
+ d_instantiate(de,ino);
+
+out:
+ userfs_unlock_inode(dir);
+
+ return ret;
+}
+
+k_static int userfs_create(struct inode *dir, struct dentry *de, int mode)
+{
+ return do_create(dir, de, S_IFREG | mode, 0);
+}
+
+k_static int userfs_mknod(struct inode *dir, struct dentry *de,
+ int mode, int rdev)
+{
+ return do_create(dir, de, mode, rdev);
+}
+
+k_static int userfs_mkdir(struct inode *dir, struct dentry *de, int mode)
+{
+ return do_create(dir, de, S_IFDIR | mode, 0);
+}
+
+/* Actually do the readlink - doesn't eat ino */
+k_static int do_readlink(struct inode *ino, up_name *res)
+{
+ int ret;
+ upp_readlink_s snd;
+ upp_readlink_r rcv;
+ up_preamble pre;
+ upp_repl repl;
+
+ rcv.name.elems = NULL;
+ rcv.name.nelem = 0;
+
+ if (!S_ISLNK(ino->i_mode))
+ return -EINVAL;
+
+ userfs_genpkt(ino->i_sb, &pre, userfs_up_readlink);
+
+ snd.link = U_INOP(ino)->handle;
+
+ if ((ret = userfs_doop(ino->i_sb, &pre, &repl,
+ upp_readlink_s, &snd,
+ upp_readlink_r, &rcv)) != 0)
+ {
+ printk("do_readlink(userfs): userfs_doop failed %d\n", ret);
+ return ret;
+ }
+
+ if (repl.err_no != 0)
+ return -repl.err_no;
+
+ *res = rcv.name;
+
+ return 0;
+}
+
+k_static int userfs_readlink(struct dentry *de, char *name, int nlen)
+{
+ int ret;
+ up_name path;
+
+#ifdef DEBUG
+ printk("userfs_readlink(%p,%s,%d)\n",de,name,nlen);
+#endif
+ path.elems = NULL;
+
+ ret = do_readlink(de->d_inode, &path);
+
+ if (ret != 0)
+ goto out;
+
+ ret = MIN(nlen, path.nelem);
+
+ if (ret > 0)
+ if(copy_to_user(name, path.elems, ret))
+ ret = -EPERM;
+
+out:
+ if (path.elems != NULL)
+ FREE(path.elems);
+
+ iput(de->d_inode);
+ return ret;
+}
+
+int do_followlink(struct inode *dir, struct dentry *base, int follow, int useread)
+{
+ up_name path;
+ char *fpath;
+ int fplen;
+ int ret;
+ struct dentry *result = NULL;
+ struct nameidata nd;
+
+ nd.dentry=base;
+ nd.flags=follow;
+
+#ifdef DEBUG
+ printk("do_followlink(%p,%p,...)\n",dir,base);
+#endif
+ if (dir == NULL)
+ {
+ dir = current->fs->root->d_inode;
+ dir->i_count.counter++;
+ }
+
+ if (!base || !base->d_inode)
+ {
+ iput(dir);
+ return -ENOENT;
+ }
+
+ if (!S_ISLNK(base->d_inode->i_mode))
+ {
+ iput(dir);
+ return 0;
+ }
+
+ path.elems = NULL;
+
+ if (current->link_count > 5)
+ {
+ result = ERR_PTR(-ELOOP);
+ goto out;
+ }
+
+ if (useread)
+ {
+ ret = do_readlink(base->d_inode, &path);
+ if (ret != 0) {
+ result = ERR_PTR(ret);
+ goto out;
+ }
+ }
+ else
+ {
+ up_preamble pre;
+ upp_repl repl;
+ upp_followlink_s snd;
+ upp_followlink_r rcv;
+
+ rcv.path.nelem = 0;
+
+ userfs_genpkt(dir->i_sb, &pre, userfs_up_followlink);
+
+ snd.dir = U_INOP(dir)->handle;
+ snd.link = U_INOP(base->d_inode)->handle;
+ snd.flag = 0; /* flag */
+ snd.mode = 0; /* mode */
+
+ ret = userfs_doop(dir->i_sb, &pre, &repl,
+ upp_followlink_s, &snd,
+ upp_followlink_r, &rcv);
+ if(ret != 0)
+ {
+ printk("userfs_followlink: userfs_doop failed %d\n",
+ ret);
+ result = ERR_PTR(ret);
+ goto out;
+ }
+
+ if (repl.err_no != 0)
+ {
+ result = ERR_PTR(-repl.err_no);
+ goto out;
+ }
+ path = rcv.path;
+ }
+
+ fplen = path.nelem;
+ fpath = (char *)kmalloc(fplen+1, GFP_KERNEL);
+ memcpy(fpath, (char *)path.elems, fplen);
+ fpath[fplen] = '\0';
+
+ current->link_count++;
+ /* result = lookup_dentry(fpath, base, follow);
+ * struct nameidata {
+ * struct dentry *dentry;
+ * struct vfsmount *mnt;
+ * struct qstr last;
+ * unsigned int flags;
+ * int last_type;
+ *};
+ */
+
+ path_walk(fpath, &nd);
+ current->link_count--;
+
+ kfree(fpath); /* , fplen+1); */
+
+ out:
+ if (path.elems != NULL)
+ FREE(path.elems);
+
+ dput(base);
+ iput(dir);
+
+ return 0; /* nd.dentry; */
+}
+
+/* Do a followlink, using the followlink operation */
+int userfs_followlink(struct dentry *dir, struct nameidata *nd)
+{
+ return do_followlink(dir->d_inode, nd->dentry, nd->flags, 0);
+}
+
+/* Do a followlink, using readlink to get the info */
+int userfs_followlink2(struct dentry *dir, struct nameidata *nd)
+{
+ return do_followlink(dir->d_inode, nd->dentry, nd->flags, 1);
+}
+
+k_static int userfs_symlink(struct inode *dir, struct dentry *de,
+ const char *symname)
+{
+ int ret;
+ up_preamble pre;
+ upp_repl repl;
+ upp_symlink_s snd;
+
+#ifdef DEBUG
+ printk("userfs_symlink(%p,%p,%s)\n",dir,de,symname);
+#endif
+ if (!dir || !S_ISDIR(dir->i_mode))
+ return -ENOTDIR;
+
+ userfs_genpkt(dir->i_sb, &pre, userfs_up_symlink);
+
+ snd.dir = U_INOP(dir)->handle;
+ snd.name.elems = (char *)de->d_name.name;
+ snd.name.nelem = de->d_name.len;
+ snd.symname.elems = (char *)symname;
+ snd.symname.nelem = strlen(symname);
+ userfs_setcred(&snd.cred);
+
+ if ((ret = userfs_doop(dir->i_sb, &pre, &repl,
+ upp_symlink_s, &snd, void, NULL)) != 0)
+ printk("userfs_symlink: userfs_doop failed: %d\n", ret);
+ else
+ ret = -repl.err_no;
+
+ return ret;
+}
+
+k_static int userfs_unlink(struct inode *dir, struct dentry *de)
+{
+ up_preamble pre;
+ upp_unlink_s snd;
+ upp_repl rcv;
+ int ret;
+
+#ifdef DEBUG
+ printk("userfs_unlink(%p,%p)\n",dir,de);
+#endif
+ if (!dir || !S_ISDIR(dir->i_mode))
+ return -ENOTDIR;
+
+ userfs_genpkt(dir->i_sb, &pre, userfs_up_unlink);
+
+ snd.dir = U_INOP(dir)->handle;
+ snd.name.nelem = de->d_name.len;
+ snd.name.elems = (char *)de->d_name.name;
+
+ if ((ret = userfs_doop(dir->i_sb, &pre, &rcv, upp_unlink_s, &snd, void, NULL)) != 0)
+ printk("userfs_unlink: userfs_doop failed %d\n", ret);
+ else
+ ret = -rcv.err_no;
+
+ if(!ret)
+ d_delete(de);
+
+ return ret;
+}
+
+int userfs_link(struct dentry * old, struct inode * dir, struct dentry *new)
+{
+ int ret;
+ up_preamble pre;
+ upp_repl repl;
+ upp_link_s snd;
+
+#ifdef DEBUG
+ printk("userfs_link(%p,%p,%p)\n",old,dir,new);
+#endif
+ if (!dir || !S_ISDIR(dir->i_mode))
+ return -EBADF;
+
+ if (!old || !old->d_inode)
+ {
+ ret = -ENOENT;
+ goto out;
+ }
+
+ userfs_genpkt(dir->i_sb, &pre, userfs_up_link);
+
+ snd.ofile = U_INOP(old->d_inode)->handle;
+ snd.dir = U_INOP(dir)->handle;
+ snd.name.elems = (char *)new->d_name.name;
+ snd.name.nelem = new->d_name.len;
+
+ if ((ret = userfs_doop(dir->i_sb, &pre, &repl,
+ upp_link_s, &snd, void, NULL)) != 0)
+ printk("userfs_link: userfs_doop failed: %d\n", ret);
+ else
+ ret = -repl.err_no;
+
+ out:
+ iput(dir);
+
+ if (old)
+ dput(old);
+
+ return ret;
+}
+
+k_static void userfs_truncate(struct inode *ino)
+{
+ up_preamble pre;
+ upp_truncate_s snd;
+ upp_repl repl;
+ int ret;
+
+#ifdef DEBUG
+ printk("userfs_truncate(%p)\n",ino);
+#endif
+ userfs_genpkt(ino->i_sb, &pre, userfs_up_truncate);
+
+ snd.file = U_INOP(ino)->handle;
+ snd.size = ino->i_size;
+
+ if ((ret = userfs_doop(ino->i_sb, &pre, &repl, upp_truncate_s, &snd, void, NULL)) != 0)
+ printk("userfs_truncate: userfs_doop failed %d\n", ret);
+ else
+ ret = repl.err_no;
+}
+
+k_static int userfs_permission(struct inode *ino, int mask)
+{
+ up_preamble pre;
+ upp_permission_s snd;
+ upp_repl repl;
+ int ret;
+
+#ifdef DEBUG
+ printk("userfs_permission(%p,%d)\n",ino,mask);
+#endif
+ userfs_genpkt(ino->i_sb, &pre, userfs_up_permission);
+
+ userfs_setcred(&snd.cred);
+ snd.mask = mask;
+ snd.file = U_INOP(ino)->handle;
+
+ if ((ret = userfs_doop(ino->i_sb, &pre, &repl, upp_permission_s, &snd, void, NULL)) != 0)
+ printk("userfs_permission: userfs_doop failed %d\n", ret);
+ else
+ ret = repl.err_no;
+
+ return ret == 0;
+}
+
+k_static int userfs_rename(struct inode *odir, struct dentry *ode,
+ struct inode *ndir, struct dentry *nde)
+{
+ up_preamble pre;
+ upp_rename_s snd;
+ upp_repl repl;
+ int ret;
+
+#ifdef DEBUG
+ printk("userfs_rename(...)\n");
+#endif
+ if (!odir || !S_ISDIR(odir->i_mode) ||
+ !ndir || !S_ISDIR(ndir->i_mode))
+ return -ENOTDIR;
+
+ assert(odir->i_sb == ndir->i_sb);
+
+ userfs_genpkt(odir->i_sb, &pre, userfs_up_rename);
+
+ snd.odir = U_INOP(odir)->handle;
+ snd.oname.elems = (char *)ode->d_name.name;
+ snd.oname.nelem = ode->d_name.len;
+
+ snd.ndir = U_INOP(ndir)->handle;
+ snd.nname.elems = (char *)nde->d_name.name;
+ snd.nname.nelem = nde->d_name.len;
+
+ if ((ret = userfs_doop(odir->i_sb, &pre, &repl, upp_rename_s, &snd, void, NULL)) != 0)
+ {
+ printk("userfs_rename: userfs_doop failed %d\n", ret);
+ return ret;
+ }
+ if(repl.err_no)
+ return -repl.err_no;
+
+ return 0;
+}
+
+/* Ask process if operation is supported */
+int userfs_probe(struct super_block *sb, up_ops op)
+{
+ up_preamble pre;
+ upp_repl repl;
+ int ret;
+
+#ifdef DEBUG
+ printk("userfs_probe()\n");
+#endif
+ userfs_genpkt(sb, &pre, op);
+
+ pre.isreq = UP_ENQ;
+
+ if ((ret = userfs_doop(sb, &pre, &repl, void, NULL, void, NULL)) != 0)
+ {
+ printk("userfs_probe: userfs_doop failed: %d\n", ret);
+ return 0;
+ }
+
+ return repl.err_no == 0;
+}
+
+/* disable things that process won't cope with */
+struct inode_operations *userfs_probe_iops(struct super_block *sb)
+{
+ struct inode_operations *iops;
+
+#ifdef DEBUG
+ printk("userfs_probe_iops(%p)\n",sb);
+#endif
+ iops = (struct inode_operations *)kmalloc(sizeof(*iops), GFP_KERNEL);
+
+ *iops = userfs_inode_operations;
+
+ /* iops->default_file_ops = userfs_probe_fops(sb); */
+
+ if (!userfs_probe(sb, userfs_up_lookup))
+ iops->lookup = NULL;
+ if (!userfs_probe(sb, userfs_up_create))
+ {
+ printk("Sorry, you can't create stuff.\n");
+ iops->create = NULL;
+ iops->mkdir = NULL;
+ iops->mknod = NULL;
+ }
+ if (!userfs_probe(sb, userfs_up_link))
+ iops->link = NULL;
+ if (!userfs_probe(sb, userfs_up_unlink))
+ {
+ iops->unlink = NULL;
+ iops->rmdir = NULL;
+ }
+ if (!userfs_probe(sb, userfs_up_rename))
+ iops->rename = NULL;
+ if (!userfs_probe(sb, userfs_up_readlink))
+ iops->readlink = NULL;
+ if (!userfs_probe(sb, userfs_up_symlink))
+ iops->symlink = NULL;
+
+ /*
+ * If the proc supports readlink but not followlink,
+ * implement followlink in terms of readlink.
+ * Is this really the Right Thing?
+ */
+ if (!userfs_probe(sb, userfs_up_followlink))
+ {
+ if (iops->readlink)
+ iops->follow_link = userfs_followlink2;
+ else
+ iops->follow_link = NULL;
+ }
+ if (!userfs_probe(sb, userfs_up_permission))
+ iops->permission = NULL;
+ if (!userfs_probe(sb, userfs_up_truncate))
+ iops->truncate = NULL;
+
+ return iops;
+}
+
+#define PG_LOCK(page) set_bit(PG_locked, &(page)->flags)
+#define PG_UNLOCK(page) clear_bit(PG_locked, &(page)->flags)
+#define PG_CLRERROR(page) clear_bit(PG_error, &(page)->flags)
+#define PG_UPTODATE(page) set_bit(PG_uptodate, &(page)->flags)
+#define PG_ISUPTODATE(page) (Page_Uptodate((page)))
+
+k_static int userfs_readpage(struct file *file, struct page *page)
+{
+ unsigned long address;
+ off_t off;
+ struct inode *inode = file -> f_dentry -> d_inode;
+
+ address = (unsigned long) page_address(page);
+ atomic_inc(&page->count);
+ if (PG_ISUPTODATE(page)) {
+ free_page(address);
+ return 0;
+ }
+
+ PG_LOCK(page);
+ PG_CLRERROR(page);
+
+ /*
+ * Unfortunately we don't get the file pointer passed here, so
+ * we can't get the credentials token. It wouldn't really make
+ * sense anyway.
+ */
+ printk("userfs_readpaqge: calling do_userfs_read: off=%ld\n", page->index*PAGE_SIZE);
+/* off = do_userfs_read(inode, 0, page->index,
+ (char *)address, PAGE_SIZE, 0); */
+ off = do_userfs_read(inode, 0, page->index*PAGE_SIZE,
+ (char *)address, PAGE_SIZE, 0);
+ printk("userfs_readpaqge: do_userfs_read returned %ld\n", off);
+ if (off < PAGE_SIZE)
+ {
+ off_t fix = off < 0 ? 0 : off;
+ printk("userfs_readpaqge: off=%ld < PAGE_SIZE=%ld, fix=%ld\n", off, PAGE_SIZE, fix);
+
+ memset((char *)address+fix, 0, PAGE_SIZE-fix);
+ }
+
+ PG_UPTODATE(page);
+ PG_UNLOCK(page);
+
+ wake_up(&page->wait);
+ free_page(address);
+ return 0;
+}
+/*
+struct inode_operations {
+ int (*create) (struct inode *,struct dentry *,int);
+ struct dentry * (*lookup) (struct inode *,struct dentry *);
+ int (*link) (struct dentry *,struct inode *,struct dentry *);
+ int (*unlink) (struct inode *,struct dentry *);
+ int (*symlink) (struct inode *,struct dentry *,const char *);
+ int (*mkdir) (struct inode *,struct dentry *,int);
+ int (*rmdir) (struct inode *,struct dentry *);
+ int (*mknod) (struct inode *,struct dentry *,int,int);
+ int (*rename) (struct inode *, struct dentry *,
+ struct inode *, struct dentry *);
+ int (*readlink) (struct dentry *, char *,int);
+ int (*follow_link) (struct dentry *, struct nameidata *);
+ void (*truncate) (struct inode *);
+ int (*permission) (struct inode *, int);
+ int (*revalidate) (struct dentry *);
+ int (*setattr) (struct dentry *, struct iattr *);
+ int (*getattr) (struct dentry *, struct iattr *);
+};
+*/
+
+struct inode_operations userfs_inode_operations =
+{
+/* &userfs_file_operations, */
+ userfs_create, /* create */
+ userfs_lookup, /* lookup */
+ userfs_link, /* link */
+ userfs_unlink, /* unlink */
+ userfs_symlink, /* symlink */
+ userfs_mkdir, /* mkdir */
+ userfs_unlink, /* rmdir */
+ userfs_mknod, /* mknod */
+ userfs_rename, /* rename */
+ userfs_readlink, /* readlink */
+ userfs_followlink, /* follow_link */
+/* userfs_readpage,*/ /* readpage */
+/* NULL, */ /* writepage */
+/* NULL, */ /* bmap */
+ userfs_truncate, /* truncate */
+ userfs_permission, /* permission */
+/* NULL, */ /* smap */
+/* NULL, */ /* updatepage */
+ NULL, /* revalidate */
+ NULL, /* setattr */
+ NULL, /* getattr */
+};
+
+struct address_space_operations userfs_aops =
+{
+/* readpage: ext2_readpage,
+ writepage: ext2_writepage,
+ sync_page: block_sync_page,
+ prepare_write: ext2_prepare_write,
+ commit_write: generic_commit_write,
+ bmap: ext2_bmap
+*/
+ readpage: userfs_readpage,
+};
+
Added: trunk/kernel/src/super.c
==============================================================================
--- trunk/kernel/src/super.c 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/kernel/src/super.c 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,609 @@
+/*
+ * Super block/filesystem wide operations
+ *
+ * Jeremy Fitzhardinge <jeremy at softway.oz.au>, May 1993
+ */
+
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/stat.h>
+#include <linux/errno.h>
+#include <linux/locks.h>
+#include <linux/assert.h>
+#include <linux/string.h>
+#include <linux/file.h>
+#include <asm/segment.h>
+#include <asm/uaccess.h>
+
+#define __NO_VERSION__
+#include <linux/module.h>
+
+#include <linux/userfs_fs.h>
+#include <linux/userfs_fs_sb.h>
+#include <linux/userfs_mount.h>
+
+#include "userfs.h"
+
+static void userfs_free_super(struct super_block *sb)
+{
+#ifdef DEBUG
+ printk("userfs_free_super()\n");
+#endif
+
+ if(!sb)
+ {
+ printk("warning: sb was NULL!\n");
+ return;
+ }
+
+ userfs_close_chan(sb);
+
+ if (sb->s_op != &userfs_super_operations)
+ kfree(sb->s_op); /*, sizeof(struct super_operations)); */
+
+/* kfree_s(U_SBP(sb)->s_iops->default_file_ops,
+ sizeof(struct file_operations)); */
+ kfree(U_SBP(sb)->s_iops); /*, sizeof(struct inode_operations)); */
+
+ sb->s_dev = 0;
+
+ if (U_SBP(sb)->s_nwproc != 0)
+ {
+#ifdef DEBUG
+ printk("kissing process... ");
+#endif
+ assert(U_SBP(sb)->s_wlist != NULL);
+ userfs_kiss(sb, UP_WALL, UP_FINISH);
+#ifdef DEBUG
+ printk("ok\n");
+#endif
+ }
+
+ assert(U_SBP(sb)->s_nwproc == 0);
+ assert(U_SBP(sb)->s_wlist == NULL);
+
+ MOD_DEC_USE_COUNT;
+#ifdef DEBUG
+ printk("bye.\n");
+#endif
+
+}
+
+static void userfs_put_super(struct super_block *sb)
+{
+ up_preamble snd;
+ upp_repl repl;
+ int ret;
+
+ userfs_genpkt(sb, &snd, userfs_up_umount);
+
+ /* lock_super(sb); - we get this lock for free now in 2.4 */
+ if ((ret = userfs_doop(sb, &snd, &repl, void, NULL, void, NULL)) != 0)
+ printk("userfs_put_super: userfs_doop returns %d\n", ret);
+
+ /* unlock_super(sb); */
+
+ if (repl.err_no != 0)
+ printk("userfs_put_super: up_umount failed with %ld\n", repl.err_no);
+ userfs_free_super(sb);
+}
+
+static void userfs_free_inode(struct inode *ino)
+{
+ if (! (ino->i_state&I_FREEING) )
+ ino->i_state |= I_FREEING;
+ if (ino->i_data.nrpages)
+ truncate_inode_pages(&ino->i_data, 0);
+ if (ino->i_count.counter > 1)
+ return;
+
+#ifdef USE_MULTIDIRREAD
+ userfs_free_dirra(ino);
+#endif
+
+ /* Make sure the inode isn't cached */
+ clear_inode(ino);
+}
+
+static void userfs_put_inode(struct inode *ino)
+{
+ up_preamble pre;
+ upp_iput_s pkt;
+ upp_repl repl;
+ int ret;
+
+#ifdef DEBUG
+ printk("userfs_put_inode(%lX)\n",U_INOP(ino)->handle.handle);
+#endif
+ userfs_genpkt(ino->i_sb, &pre, userfs_up_iput);
+ pkt.handle = U_INOP(ino)->handle;
+
+ userfs_lock_inode(ino);
+
+ if ((ret = userfs_doop(ino->i_sb, &pre, &repl, upp_iput_s, &pkt, void, NULL)) != 0)
+ printk("userfs_put_inode: userfs_doop failed %d\n", ret);
+ else
+ {
+ if (repl.err_no != 0)
+ printk("userfs_put_inode: operation failed with %ld\n",
+ repl.err_no);
+ }
+ userfs_unlock_inode(ino);
+ userfs_free_inode(ino);
+}
+static int userfs_statfs_stub(struct super_block *sb, struct statfs *buf)
+/* static int userfs_statfs_stub(struct super_block *sb, struct statfs *buf, int bufsz) */
+{
+ struct statfs sfs;
+
+ memset(&sfs, 0, sizeof(sfs));
+
+ sfs.f_type = USERFS_SUPER_MAGIC;
+ sfs.f_bsize = 1024;
+ sfs.f_blocks = 0;
+ sfs.f_bfree = 0;
+ sfs.f_bavail = 0;
+ sfs.f_files = 0;
+ sfs.f_ffree = 0;
+ sfs.f_namelen = NAME_MAX;
+
+ copy_to_user(buf, &sfs, sizeof(sfs));
+
+ return 0;
+}
+
+static int userfs_statfs(struct super_block *sb, struct statfs *buf)
+/* static int userfs_statfs(struct super_block *sb, struct statfs *buf, int bufsz) */
+{
+ up_preamble pre;
+ upp_repl repl;
+ upp_statfs_r rcv;
+ int ret;
+ struct statfs sfs;
+
+ userfs_genpkt(sb, &pre, userfs_up_statfs);
+
+ if ((ret = userfs_doop(sb, &pre, &repl,
+ void, NULL, upp_statfs_r, &rcv)) != 0)
+ {
+ printk("userfs_statfs: userfs_doop failed: %d\n", ret);
+ memset(&sfs, 0, sizeof(struct statfs));
+
+ return EBADF;
+ }
+ else
+ {
+ int i;
+
+ sfs.f_type = USERFS_SUPER_MAGIC;
+ sfs.f_bsize = rcv.bsize;
+ sfs.f_blocks = rcv.blocks;
+ sfs.f_bfree = rcv.bfree;
+ sfs.f_bavail = rcv.bavail;
+ sfs.f_files = rcv.files;
+ sfs.f_ffree = rcv.ffree;
+ for(i = 0; i < sizeof(sfs.f_fsid.val)/sizeof(*sfs.f_fsid.val); i++)
+ sfs.f_fsid.val[i] = rcv.fsid[i];
+ sfs.f_namelen = rcv.namelen;
+ }
+
+ copy_to_user(buf, &sfs, sizeof(sfs));
+
+ return 0;
+}
+
+struct super_block *
+userfs_read_super(struct super_block *sb, void *raw_data, int flag)
+{
+ struct file *toproc;
+ struct file *fromproc;
+ struct userfs_mount *mntinfo = (struct userfs_mount *)raw_data;
+ up_preamble snd;
+ upp_mount_r rcv;
+ upp_repl repl;
+ int ret;
+ struct inode *root=NULL;
+ struct files_struct *files;
+
+#ifdef DEBUG
+ printk("userfs_read_super entered infd=%X outfd=%X\n",
+ mntinfo->fromkern,
+ mntinfo->tokern);
+#endif
+
+ MOD_INC_USE_COUNT;
+
+ /* don't alloc - it's in the superblock struct already */
+ memset(U_SBP(sb), 0, sizeof(*U_SBP(sb)));
+
+ toproc = fromproc = NULL;
+
+ U_SBP(sb)->s_toproc = toproc;
+ U_SBP(sb)->s_fromproc = fromproc;
+
+ if (raw_data == NULL)
+ {
+ printk("userfs_read_super: extra mount data missing\n");
+ goto fail;
+ }
+
+ if (mntinfo->version != USERFS_VERSION)
+ {
+ printk("userfs_read_super: mount data version %d, kernel is %d\n",
+ mntinfo->version, USERFS_VERSION);
+ goto fail;
+ }
+
+ if (mntinfo->magic != USERFS_SUPER_MAGIC)
+ {
+ printk("userfs: client tried to mount with incorrect magic number in parameter block\n");
+ goto fail;
+ }
+
+ spin_lock_init(&(U_SBP(sb)->s_lock));
+
+#ifdef DEBUG
+ if(!current->files)
+ printk("userfs_read_super current->files is null\n");
+#endif
+
+#ifdef DEBUG
+ printk("userfs_read_super getting from kern fd\n");
+#endif
+ task_lock(current);
+ files = current->files;
+ if (files) /* do we want to do this!? */
+ atomic_inc(&files->count);
+ task_unlock(current);
+ if ((toproc = fcheck_files(files, mntinfo->fromkern)) == NULL )
+ {
+ printk("userfs_read_super: bad fromkern fd %d\n",
+ mntinfo->fromkern);
+ goto fail;
+ }
+
+#ifdef DEBUG
+ printk("userfs_read_super checking fd is writeable\n");
+#endif
+
+ if( !(toproc->f_mode&FMODE_WRITE) )
+ {
+ printk("userfs_read_super: bad fromkern fd %d\n",
+ mntinfo->fromkern);
+ goto fail;
+ }
+
+ U_SBP(sb)->s_toproc = toproc;
+
+#ifdef DEBUG
+ printk("userfs_read_super getting to kernel fd\n");
+#endif
+ task_lock(current);
+ files = current->files;
+ if (files)
+ atomic_inc(&files->count);
+ task_unlock(current);
+ if ((fromproc = fcheck_files(files, mntinfo->tokern)) == NULL )
+ {
+ printk("userfs_read_super: bad tokern fd %d\n",
+ mntinfo->tokern);
+ goto fail;
+ }
+
+#ifdef DEBUG
+ printk("userfs_read_super checking fd is readable\n");
+#endif
+
+ if ( !(fromproc->f_mode&FMODE_READ))
+ {
+ printk("userfs_read_super: bad tokern fd %d\n",
+ mntinfo->tokern);
+ goto fail;
+ }
+
+ U_SBP(sb)->s_fromproc = fromproc;
+
+ toproc->f_count.counter++;
+ fromproc->f_count.counter++;
+
+ sb->s_magic = USERFS_SUPER_MAGIC;
+ sb->s_blocksize = 1024;
+ sb->s_op = &userfs_super_operations;
+ sb->s_flags = 0;
+
+ U_SBP(sb)->s_seq = mntinfo->seq;
+ U_SBP(sb)->s_iops = &userfs_inode_operations;
+
+ U_SBP(sb)->s_nwproc = 0;
+ U_SBP(sb)->s_canread = 0;
+ U_SBP(sb)->s_wlist = NULL;
+
+#ifdef DEBUG
+ printk("userfs_read_super requesting superblock mount\n");
+#endif
+
+ userfs_genpkt(sb, &snd, userfs_up_mount);
+
+ ret = userfs_doop(sb, &snd, &repl, void, NULL, upp_mount_r, &rcv);
+
+ if (ret != 0)
+ {
+ printk("userfs_read_super: userfs_doop failed with %d\n", ret);
+ goto fail;
+ }
+
+ if (repl.err_no != 0)
+ {
+ printk("userfs_read_super: mount failed with %ld\n",
+ repl.err_no);
+ goto fail;
+ }
+
+ U_SBP(sb)->s_root = rcv.root;
+
+#ifdef DEBUG
+ printk("userfs_read_super requesting process capabilities\n");
+#endif
+
+ sb->s_op = userfs_probe_sops(sb);
+ U_SBP(sb)->s_iops = userfs_probe_iops(sb);
+
+#ifdef DEBUG
+ printk("userfs_read_super allocating root dirent\n");
+#endif
+
+ root = iget(sb,U_SBP(sb)->s_root.handle);
+ if(!root)
+ goto fail;
+
+ U_INOP(root)->handle.handle = U_SBP(sb)->s_root.handle;
+
+ if (!(sb->s_root = d_alloc_root(root)))
+ {
+ printk("userfs_read_super: get root inode %ld failed\n",
+ U_SBP(sb)->s_root.handle);
+ goto fail;
+ }
+
+#ifdef DEBUG
+ printk("read superblock %lX\n",U_INOP(root)->handle.handle);
+#endif
+
+ return sb;
+
+fail:
+ printk("userfs_read_super"": failed\n");
+
+ if (sb != NULL)
+ {
+ sb->s_dev = 0;
+ sb->s_op = NULL;
+ sb->s_magic = 0;
+ userfs_close_chan(sb);
+ }
+
+ MOD_DEC_USE_COUNT;
+
+ return NULL;
+}
+
+extern struct inode_operations userfs_inode_operations;
+
+void userfs_set_inode(struct inode *inode, const up_inode *rcv)
+{
+ inode->i_mode = rcv->mode;
+ inode->i_nlink = rcv->nlink;
+ inode->i_uid = rcv->uid;
+ inode->i_gid = rcv->gid;
+ inode->i_size = rcv->size;
+ inode->i_atime = rcv->atime;
+ inode->i_mtime = rcv->mtime;
+ inode->i_ctime = rcv->ctime;
+ inode->i_blksize = rcv->blksize;
+ inode->i_blocks = rcv->blocks;
+ inode->i_rdev = rcv->rdev;
+
+ /* these things seem to be new to kernel 2.2.6 */
+ inode->i_version = ++event; /* something unique, i guess */
+ inode->i_attr_flags = 0; /* also set to zero in ext2 */
+ inode->i_flags = 0; /* don't know the meaning */
+}
+
+extern struct address_space_operations userfs_aops;
+extern struct inode_operations userfs_inode_operations;
+extern struct file_operations userfs_file_operations;
+
+void userfs_read_inode(struct inode *inode)
+{
+ up_preamble pre;
+ upp_repl repl;
+ upp_iread_s snd;
+ upp_iread_r rcv;
+ int ret;
+
+ if(!inode)
+ {
+ printk("inode pointer NULL!");
+ return;
+ }
+
+#ifdef DEBUG
+ printk("Reading inode %lX\n",inode->i_ino);
+#endif
+
+ inode->i_op = NULL;
+ inode->i_mode = 0;
+ inode->i_flags = 0;
+ inode->i_mapping->a_ops = NULL;
+ inode->i_fop = NULL;
+
+ userfs_genpkt(inode->i_sb, &pre, userfs_up_iread);
+
+ snd.handle.handle = inode->i_ino;
+
+ if ((ret = userfs_doop(inode->i_sb, &pre, &repl, upp_iread_s, &snd, upp_iread_r, &rcv)) != 0)
+ {
+ printk("userfs_read_inode: failed to do upp_iread: %d\n", ret);
+ return;
+ }
+
+ if (repl.err_no != 0)
+ {
+ printk("userfs_read_inode: inode read failed: ino=%ld, errno = %ld\n",
+ inode->i_ino, repl.err_no);
+ memset(&rcv, 0, sizeof(rcv));
+ }
+ else
+ {
+ assert(rcv.handle.handle == inode->i_ino);
+ assert(inode->i_nlink != 0);
+
+ if ((rcv.handle.handle == inode->i_ino) && (inode->i_nlink != 0))
+ {
+ inode->i_op = U_SBP(inode->i_sb)->s_iops;
+ inode->i_mapping->a_ops = &userfs_aops;
+ inode->i_fop = &userfs_file_operations;
+ }
+ else
+ {
+ printk("Bad: different inode handle returned.\n");
+ memset(&rcv, 0, sizeof(rcv));
+ }
+ }
+
+ U_INOP(inode)->handle = rcv.handle;
+ U_INOP(inode)->dir_ra = NULL;
+ U_INOP(inode)->version = 0;
+
+ userfs_set_inode(inode, &rcv.ino);
+}
+
+k_static void userfs_pack_iattr(up_iattr *target, const struct iattr *source)
+{
+ target->ia_valid = source->ia_valid;
+ target->ia_mode = source->ia_mode;
+ target->ia_uid = source->ia_uid;
+ target->ia_gid = source->ia_gid;
+ target->ia_size = source->ia_size;
+ target->ia_atime = source->ia_atime;
+ target->ia_mtime = source->ia_mtime;
+ target->ia_ctime = source->ia_ctime;
+}
+
+k_static int userfs_notify_change(struct dentry *dentry, struct iattr *iattr)
+{
+ up_preamble pre;
+ upp_notify_change_s snd;
+ upp_repl rcv;
+ int ret;
+ struct inode *inode = dentry->d_inode;
+
+ userfs_genpkt(inode->i_sb, &pre, userfs_up_notify_change);
+
+ snd.handle = U_INOP(inode)->handle;
+ userfs_pack_iattr(&snd.iattr, iattr);
+
+ if ((ret = userfs_doop(inode->i_sb, &pre, &rcv,
+ upp_notify_change_s, &snd,
+ void, NULL)) != 0)
+ {
+ printk("userfs_notify_change: transaction failed: %d\n", ret);
+ return ret;
+ }
+
+ userfs_read_inode(inode);
+
+ return -rcv.err_no;
+}
+
+k_static void userfs_pack_inode(up_inode *ino, const struct inode *inode)
+{
+ ino->mode = inode->i_mode;
+ ino->nlink = inode->i_nlink;
+ ino->uid = inode->i_uid;
+ ino->gid = inode->i_gid;
+ ino->size = inode->i_size;
+ ino->atime = inode->i_atime;
+ ino->mtime = inode->i_mtime;
+ ino->ctime = inode->i_ctime;
+ ino->blksize = inode->i_blksize;
+ ino->blocks = inode->i_blocks;
+}
+
+k_static int userfs_write_change(int flags, struct inode *inode)
+{
+ up_preamble pre;
+ upp_iwrite_s snd;
+ upp_repl rcv;
+ int ret;
+
+ userfs_genpkt(inode->i_sb, &pre, userfs_up_iwrite);
+
+ snd.handle = U_INOP(inode)->handle;
+ userfs_pack_inode(&snd.ino, inode);
+
+ if ((ret = userfs_doop(inode->i_sb, &pre, &rcv,
+ upp_iwrite_s, &snd, void, NULL)) != 0)
+ {
+ printk("userfs_write_change: transaction failed: %d\n", ret);
+ return ret;
+ }
+
+ return rcv.err_no;
+}
+
+k_static void userfs_write_inode(struct inode *inode, int just_showed_up_in_2_4)
+/* k_static void userfs_write_inode(struct inode *inode) */
+{
+ int ret;
+
+ /*
+ * We arn't allowed to fail, so if the IO below doesn't work,
+ * tough.
+ */
+ inode->i_state &= ~I_DIRTY;
+
+ if ((ret = userfs_write_change(0, inode)) != 0)
+ printk("userfs_write_inode: inode write failed: %d\n", ret);
+}
+
+struct super_operations *userfs_probe_sops(struct super_block *sb)
+{
+ struct super_operations *sops;
+
+ sops = (struct super_operations *)kmalloc(sizeof(*sops), GFP_KERNEL);
+ *sops = userfs_super_operations;
+
+ if (!userfs_probe(sb, userfs_up_iread))
+ sops->read_inode = NULL;
+ if (!userfs_probe(sb, userfs_up_iwrite))
+ sops->write_inode = NULL;
+ if (!userfs_probe(sb, userfs_up_iput))
+ sops->put_inode = NULL; /* userfs_free_inode; */
+ if (!userfs_probe(sb, userfs_up_umount))
+ sops->put_super = userfs_free_super;
+ if (!userfs_probe(sb, userfs_up_statfs))
+ sops->statfs = userfs_statfs_stub;
+
+ return sops;
+}
+
+struct super_operations userfs_super_operations =
+{
+ userfs_read_inode, /* read_inode */
+ NULL, /* read_inode2 */
+ NULL, /* dirty_inode */
+ userfs_write_inode, /* write_inode */
+ userfs_put_inode, /* put_inode */
+ NULL, /* delete inode */
+ userfs_put_super, /* put_super */
+ NULL, /* write_super */
+ NULL, /* write_super_lockfs */
+ NULL, /* unlockfs */
+ userfs_statfs, /* statfs */
+ NULL, /* remount_fs */
+ NULL, /* clear inode */
+ NULL, /* unmount begin */
+};
+
Added: trunk/kernel/src/file.c
==============================================================================
--- trunk/kernel/src/file.c 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/kernel/src/file.c 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,649 @@
+/*
+ * Deal with file operations
+ *
+ * Jeremy Fitzhardinge <jeremy at softway.oz.au>, 1993-1995
+ */
+
+#include "userfs.h"
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/stat.h>
+#include <linux/errno.h>
+#include <linux/fcntl.h>
+#include <linux/locks.h>
+#include <linux/userfs_fs.h>
+#include <linux/userfs_fs_sb.h>
+#include <linux/userfs_fs_f.h>
+#include <linux/userfs_mount.h>
+#include <linux/assert.h>
+#include <asm/segment.h>
+#include <asm/uaccess.h>
+
+int do_userfs_read(struct inode *inode,
+ up_credtok tok, off_t offset,
+ char *buf, int size, int userspace)
+{
+ unsigned int max_size;
+ up_preamble pre;
+ upp_repl repl;
+ upp_read_s snd;
+ upp_read_r rcv;
+ int rd = 0;
+ int sz;
+ int ret;
+
+#ifdef DEBUG
+ printk("do_userfs_read()\n");
+#endif
+
+ if (inode == NULL)
+ {
+ printk("userfs_read: inode is NULL\n");
+ return -EINVAL;
+ }
+
+ rcv.data.nelem = 0;
+ max_size = MAX_KMALLOC - sizeof_upp_read_r(&rcv);
+
+ snd.file = U_INOP(inode)->handle;
+ snd.ctok = tok;
+
+ while(size > 0)
+ {
+ userfs_genpkt(inode->i_sb, &pre, userfs_up_read);
+
+ snd.off = offset;
+ snd.size = MIN(max_size, size);
+
+ if ((ret = userfs_doop(inode->i_sb, &pre, &repl,
+ upp_read_s, &snd,
+ upp_read_r, &rcv)) != 0)
+ {
+ printk("userfs_read: userfs_doop failed %d\n",
+ ret);
+ if (rd == 0)
+ rd = ret;
+ break;
+ }
+
+ if (repl.err_no != 0)
+ {
+ if (rd == 0)
+ {
+ rd = -repl.err_no;
+ printk("userfs_read: repl.err.no!=0 : %d\n", rd);
+ }
+
+ break;
+ }
+
+ if (rcv.data.nelem == 0)
+ break;
+
+ sz = MIN(size, rcv.data.nelem);
+
+ if (rcv.data.nelem > max_size)
+ {
+ printk("userfs_read: more than %d bytes in data (!!!) (%ld)\n",
+ max_size, rcv.data.nelem);
+ sz = MIN(sz, max_size);
+ }
+
+ if (userspace)
+ copy_to_user(buf, rcv.data.elems, sz);
+ else
+ /* this looks bad... */
+ memcpy(buf, rcv.data.elems, sz);
+
+ offset += sz;
+ size -= sz;
+ rd += sz;
+ buf += sz;
+
+ FREE(rcv.data.elems);
+ }
+ return rd;
+}
+
+k_static ssize_t userfs_read(struct file *file,
+ char *buf, size_t size, loff_t *offset)
+{
+ /*
+ * If we have a unified VM/buffer cache, then we just use
+ * the generic read function. This will end up calling our
+ * userfs_readpage function to perform the actual IO if necessary.
+ */
+ return generic_file_read(file, buf, size, offset);
+}
+
+k_static ssize_t userfs_write(struct file *file,
+ const char *buf, size_t size, loff_t *ofs)
+{
+ up_preamble pre;
+ upp_repl repl;
+ upp_write_s snd;
+ upp_write_r rcv;
+ int wr = 0;
+ int sz;
+ int ret;
+ unsigned char *mbuf = NULL;
+ int bufsz = 0;
+ unsigned int max_size;
+ struct inode *inode = file->f_dentry->d_inode;
+
+ if (inode == NULL)
+ {
+ printk("userfs_write: inode is NULL\n");
+ return -EINVAL;
+ }
+
+ snd.data.nelem = 0;
+ max_size = MAX_KMALLOC - sizeof_upp_write_s(&snd);
+
+ snd.file = U_INOP(inode)->handle;
+ if(U_FILEP(file))
+ snd.ctok = U_FILEP(file)->cred_tok;
+ else
+ memset(&snd.ctok, 0, sizeof snd.ctok);
+
+ if(!ofs)
+ {
+ printk("userfs_write: offset pointer was NULL.\n");
+ return -EINVAL;
+ }
+
+ sz = MIN(max_size, size);
+
+ mbuf = (unsigned char *)kmalloc(sz, GFP_KERNEL);
+ bufsz = sz;
+
+ while(size > 0)
+ {
+ sz = MIN(max_size, size);
+
+ copy_from_user(mbuf, buf, sz);
+
+ userfs_genpkt(inode->i_sb, &pre, userfs_up_write);
+
+ if (file->f_flags & O_APPEND)
+ snd.off = inode->i_size;
+ else
+ snd.off = *ofs;
+
+ snd.data.elems = mbuf;
+ snd.data.nelem = sz;
+
+ if ((ret = userfs_doop(inode->i_sb, &pre, &repl,
+ upp_write_s, &snd,
+ upp_write_r, &rcv)) != 0)
+ {
+ printk("userfs_write: userfs_doop failed %d\n",
+ ret);
+ if (wr == 0)
+ wr = ret;
+ break;
+ }
+
+ if (repl.err_no != 0)
+ {
+ printk("userfs_write: error %lX occured\n",repl.err_no);
+ if (wr == 0)
+ wr = -repl.err_no;
+ break;
+ }
+
+ sz = rcv.wrote;
+
+ if (sz == 0)
+ {
+ printk("userfs_write: write op returned 0\n");
+ break;
+ }
+
+ /* update_vm_cache(inode, snd.off, buf, sz); */
+
+ /* update the size */
+ if(file->f_flags&O_APPEND)
+ {
+ inode->i_size += sz;
+ mark_inode_dirty(inode);
+ }
+ else
+ {
+ (*ofs) += sz;
+ if(inode->i_size < (*ofs))
+ {
+ inode->i_size = *ofs;
+ mark_inode_dirty(inode);
+ }
+ }
+ size -= sz;
+ wr += sz;
+ buf += sz;
+ }
+
+ inode->i_version = ++event;
+ inode->i_ctime = inode->i_mtime = CURRENT_TIME;
+
+ if (mbuf != NULL)
+ {
+ kfree(mbuf);
+ mbuf = NULL;
+ bufsz = 0;
+ }
+ return wr;
+}
+
+#ifdef USE_MULTIREADDIR
+
+/* i suspect this is broken and unnecessary for the 2.2.x kernel ! */
+
+/* Free all read-ahead dir entries */
+void userfs_free_dirra(struct inode *ino)
+{
+ struct userfs_dir_ra *ra;
+ int i;
+
+#ifndef DEBUG
+ printk("userfs_free_dirra()\n");
+#endif
+
+ if (ino == NULL)
+ return;
+
+ if (U_INOP(ino)->dir_ra == NULL)
+ return;
+
+ ra = U_INOP(ino)->dir_ra;
+ U_INOP(ino)->dir_ra = NULL;
+
+ for(i = 0; i < ra->nent; i++)
+ {
+ if (ra->ents[i].name != NULL)
+ kfree(ra->ents[i].name); /*, ra->ents[i].nlen); */
+ }
+
+ kfree(ra->ents); /* , sizeof(*ra->ents)*ra->nent); */
+ kfree(ra); /* , sizeof(*ra)); */
+}
+
+/*
+ * Look up dir entry given offset for inode
+ * Returns pointer to entry on success, NULL on failure
+ */
+k_static struct userfs_dent *lookup_ra_dent(struct inode *dir, off_t off)
+{
+ struct userfs_dir_ra *ra;
+ int i;
+
+#ifdef DEBUG
+ printk("lookup_ra_dent()\n");
+#endif
+
+ if (dir == NULL || U_INOP(dir)->dir_ra == NULL)
+ return NULL;
+
+ ra = U_INOP(dir)->dir_ra;
+
+ for(i = 0; i < ra->nent; i++)
+ if (ra->ents[i].roff == off)
+ return &ra->ents[i];
+ return NULL;
+}
+
+k_static int userfs_multireaddir(struct file *file,
+ void *dirent, filldir_t filldir)
+{
+ up_preamble pre;
+ upp_repl repl;
+ upp_multireaddir_s snd;
+ upp_multireaddir_r rcv;
+ struct userfs_dent *dent;
+ struct userfs_dir_ra *ra;
+ long ret = 0, err;
+ int i;
+ off_t off;
+ struct inode *dir = file->f_dentry->d_inode;
+
+#ifdef DEBUG
+ printk("userfs_multireaddir()\n");
+#endif
+
+ if (!dir || !S_ISDIR(dir->i_mode))
+ return -ENOTDIR;
+
+ /* Try for read-ahead entries first */
+ while((dent = lookup_ra_dent(dir, file->f_pos)) != NULL)
+ {
+ int len;
+
+ len = MIN(NAME_MAX, dent->nlen);
+ if ((*filldir)(dirent, dent->name, len,
+ file->f_pos, dent->inum) != 0)
+ return ret;
+ ret += dent->offset;
+ file->f_pos += dent->offset;
+ }
+
+ /* Flush the read-ahead and get something new */
+ userfs_free_dirra(dir);
+
+ userfs_genpkt(dir->i_sb, &pre, userfs_up_multireaddir);
+
+ snd.off = file->f_pos;
+ snd.dir = U_INOP(dir)->handle;
+ if(U_FILEP(file))
+ snd.ctok = U_FILEP(file)->cred_tok;
+ else
+ memset(&snd.ctok, 0, sizeof snd.ctok);
+
+ rcv.nelem = 0;
+ rcv.elems = NULL;
+
+ userfs_lock_inode(dir);
+
+ if ((err = userfs_doop(dir->i_sb, &pre, &repl, upp_multireaddir_s,
+ &snd, upp_multireaddir_r, &rcv)) != 0)
+ {
+ printk("userfs_multireaddir: userfs_doop failed %ld\n", err);
+ ret = err;
+ goto out;
+ }
+
+ if (repl.err_no != 0)
+ {
+ ret = -repl.err_no;
+ goto out;
+ }
+
+ if (rcv.nelem == 0)
+ goto out;
+
+ ra = kmalloc(sizeof(*ra), GFP_KERNEL);
+ ra->nent = rcv.nelem;
+ ra->ents = kmalloc(sizeof(struct userfs_dent)*rcv.nelem, GFP_KERNEL);
+
+ off = file->f_pos;
+ for(i = 0; i < rcv.nelem; i++)
+ {
+ ra->ents[i].roff = off;
+ off += ra->ents[i].offset = rcv.elems[i].off;
+ ra->ents[i].name = rcv.elems[i].name.elems;
+ ra->ents[i].nlen = rcv.elems[i].name.nelem;
+ ra->ents[i].inum = rcv.elems[i].file.handle;
+ }
+ U_INOP(dir)->dir_ra = ra;
+
+ if (rcv.elems != NULL)
+ FREE(rcv.elems);
+
+ while((dent = lookup_ra_dent(dir, file->f_pos)) != NULL)
+ {
+ int len;
+
+ len = MIN(NAME_MAX, dent->nlen);
+ if ((*filldir)(dirent, dent->name, len,
+ file->f_pos, dent->inum , DT_UNKNOWN ) != 0)
+ break;
+ ret += dent->offset;
+ file->f_pos += dent->offset;
+ }
+
+out:
+ userfs_unlock_inode(dir);
+ return ret;
+}
+#endif
+
+k_static int userfs_readdir(struct file *file,
+ void *dirent, filldir_t filldir)
+{
+ up_preamble pre;
+ upp_repl repl;
+ upp_readdir_s snd;
+ upp_readdir_r rcv;
+ long ret;
+ struct inode *dir = NULL;
+
+ if(!file)
+ {
+ printk("file pointer was null\n");
+ return 0;
+ }
+
+ if(!file->f_dentry)
+ {
+ printk("d_entry pointer was null\n");
+ return 0;
+ }
+
+ dir = file->f_dentry->d_inode;
+
+#ifdef DEBUG
+ printk("userfs_readdir()\n");
+#endif
+
+ if (!dir || !S_ISDIR(dir->i_mode))
+ return -ENOTDIR;
+
+ if(!dir->i_sb)
+ {
+ printk("superblock ptr was null\n");
+ return 0;
+ }
+ userfs_genpkt(dir->i_sb, &pre, userfs_up_readdir);
+
+ snd.off = file->f_pos;
+ snd.dir = U_INOP(dir)->handle;
+
+ if(U_FILEP(file))
+ snd.ctok = U_FILEP(file)->cred_tok;
+ else {
+ memset(&snd.ctok, 0, sizeof snd.ctok);
+ }
+
+ rcv.name.nelem = 0;
+
+ userfs_lock_inode(dir);
+
+ ret = userfs_doop(dir->i_sb, &pre, &repl,
+ upp_readdir_s, &snd,
+ upp_readdir_r, &rcv);
+
+ userfs_unlock_inode(dir);
+
+ if (ret != 0)
+ {
+ printk("userfs_readdir: userfs_doop failed %ld\n", ret);
+ return ret;
+ }
+
+ if (repl.err_no != 0)
+ {
+ ret = -repl.err_no;
+ goto out;
+ }
+
+ if (rcv.off != 0)
+ {
+ ret = MIN(NAME_MAX, rcv.name.nelem);
+
+ if(filldir)
+ (*filldir)(dirent, rcv.name.elems, ret,
+ file->f_pos, rcv.file.handle, DT_UNKNOWN);
+ else
+ printk("filldir was null\n");
+ file->f_pos += rcv.off;
+ }
+
+ ret = rcv.off;
+
+out:
+ if (rcv.name.nelem != 0)
+ FREE(rcv.name.elems);
+
+ return ret;
+}
+
+k_static int userfs_open(struct inode *ino, struct file *file)
+{
+ upp_open_s snd;
+ upp_open_r rcv;
+ up_preamble pre;
+ upp_repl repl;
+ int ret = 0;
+
+#ifdef DEBUG
+ printk("userfs_open()\n");
+#endif
+
+ if(!ino)
+ {
+ printk("Null inode.\n");
+ return -EINVAL;
+ }
+
+ userfs_genpkt(ino->i_sb, &pre, userfs_up_open);
+
+ userfs_setcred(&snd.cred);
+
+ if(!ino)
+ printk("userfs_open() ino null!\n");
+
+ snd.file = U_INOP(ino)->handle;
+
+ if ((ret = userfs_doop(ino->i_sb, &pre, &repl,
+ upp_open_s, &snd, upp_open_r, &rcv)) != 0)
+ {
+ printk("userfs_open: userfs_doop failed %d\n", ret);
+ goto out;
+ }
+
+ if ((ret = -repl.err_no) == 0)
+ {
+ /* gotta malloc this one */
+ U_FILEP(file) = kmalloc(sizeof(struct userfs_file_info), GFP_KERNEL);
+ U_FILEP(file)->cred_tok = rcv.ctok;
+ }
+
+ out:
+ return ret;
+}
+
+k_static int userfs_stub_open(struct inode *ino, struct file *file)
+{
+ printk("userfs_STUB_open\n");
+ U_FILEP(file)=NULL;
+ return 0;
+}
+
+k_static int free_file(struct inode *ino, struct file *file)
+{
+ if (U_FILEP(file) != NULL)
+ {
+ kfree(U_FILEP(file)); /*, sizeof(*U_FILEP(file))); */
+ return 0;
+ }
+ return -EBADF;
+}
+
+k_static int userfs_close(struct inode *ino, struct file *file)
+{
+ upp_close_s snd;
+ up_preamble pre;
+ upp_repl repl;
+ int ret = 0;
+
+#ifdef DEBUG
+ printk("userfs_close()\n");
+#endif
+
+ userfs_genpkt(ino->i_sb, &pre, userfs_up_close);
+
+ snd.file = U_INOP(ino)->handle;
+ if(U_FILEP(file))
+ snd.ctok = U_FILEP(file)->cred_tok;
+ else
+ memset(&snd.ctok,0,sizeof snd.ctok);
+
+ if ((ret = userfs_doop(ino->i_sb, &pre, &repl,
+ upp_close_s, &snd, void, NULL)) != 0)
+ {
+ printk("userfs_close: userfs_doop failed %d\n", ret);
+ return -EBUSY;
+ }
+
+ free_file(ino, file);
+
+ return ret;
+}
+
+/* disable things that process won't cope with */
+struct file_operations *userfs_probe_fops(struct super_block *sb)
+{
+ struct file_operations *fops;
+
+#ifdef DEBUG
+ printk("userfs_probe_fops()\n");
+#endif
+
+ fops = (struct file_operations *)kmalloc(sizeof(*fops), GFP_KERNEL);
+
+ *fops = userfs_file_operations;
+
+ if (!userfs_probe(sb, userfs_up_read))
+ fops->read = NULL;
+ if (!userfs_probe(sb, userfs_up_write))
+ fops->write = NULL;
+#ifdef USE_MULTIREADDIR
+ if (!userfs_probe(sb, userfs_up_multireaddir))
+ {
+ if (userfs_probe(sb, userfs_up_readdir))
+ fops->readdir = userfs_readdir;
+ else
+ fops->readdir = NULL;
+ }
+#else
+ if (!userfs_probe(sb, userfs_up_readdir))
+ fops->readdir = NULL;
+#endif
+ if (!userfs_probe(sb, userfs_up_open))
+ fops->open = userfs_stub_open;
+ if (!userfs_probe(sb, userfs_up_close))
+ fops->release = free_file;
+
+ return fops;
+}
+
+k_static int userfs_mmap(struct file *file, struct vm_area_struct *vma)
+{
+#ifdef DEBUG
+ printk("userfs_mmap()\n");
+#endif
+
+ /* Check uptodate here */
+ return generic_file_mmap(file, vma);
+}
+
+struct file_operations userfs_file_operations =
+{
+ NULL, /* struct module owner */
+ NULL, /* userfs_lseek */
+ userfs_read,
+ userfs_write,
+ userfs_readdir,
+ NULL, /* userfs_poll */
+ NULL, /* userfs_ioctl */
+ userfs_mmap,
+ userfs_open, /* open */
+ NULL, /* flush */
+ userfs_close, /* release */
+ NULL, /* can't fsync */
+ NULL, /* can't fasync */
+ NULL, /* lock */
+ NULL, /* readv */
+ NULL, /* writev */
+};
Added: trunk/kernel/src/userfs_types.h
==============================================================================
--- trunk/kernel/src/userfs_types.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/kernel/src/userfs_types.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,2 @@
+/* Get the kernel ones */
+#include <linux/userfs_types.h>
Added: trunk/kernel/src/userfs_types.ty
==============================================================================
--- trunk/kernel/src/userfs_types.ty 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/kernel/src/userfs_types.ty 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,2 @@
+/* Just include main userfs_types.ty */
+#include <linux/userfs_types.ty>
Added: trunk/kernel/src/module.c
==============================================================================
--- trunk/kernel/src/module.c 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/kernel/src/module.c 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,73 @@
+/*
+ * Handling for loadable module
+ */
+
+#include <linux/kernel.h>
+#include <linux/autoconf.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/userfs_fs.h>
+#include <linux/userfs_fs_sb.h>
+#include "userfs.h"
+
+DECLARE_FSTYPE(ufst,"userfs",userfs_read_super,0);
+/*
+static struct file_system_type ufst =
+{
+ "userfs2",
+ 0,
+ userfs_read_super,
+ NULL
+};
+*/
+
+int init_module(void)
+{
+ int err;
+ struct super_block super_test;
+ struct inode inode_test;
+
+ /*
+ * This is a sanity check. The code is going to assume
+ * that the userfs superblock info will fit into the
+ * standard superblock's misc data union. If it doesn't
+ * you will have to change some stuff in userfs to
+ * allocate extra memory and store a pointer there instead.
+ * Alternative you could recompile your kernel with enough
+ * space for the userfs_sb structure in struct super.
+ */
+ if ( ( sizeof super_test.u < sizeof(struct userfs_sb_info)) ||
+ ( sizeof inode_test.u < sizeof(struct userfs_inode_info)) )
+ {
+ printk("%s:%d A bad assumption was made\n",__FILE__,__LINE__);
+ printk("Userfs will not be installed.\n");
+ return -1;
+ }
+
+ err = register_filesystem(&ufst);
+
+ if (err)
+ {
+ printk("userfs: failed to register filesystem\n");
+ return err;
+ }
+
+ return 0;
+}
+
+void cleanup_module(void)
+{
+ int err;
+ if (MOD_IN_USE)
+ printk("userfs: filesystem in use, removal delayed\n");
+
+
+ if ( (err = unregister_filesystem(&ufst)) )
+ {
+ printk("userfs: failed to unregister filesystem\n");
+ return;
+ }
+}
+
+
Added: trunk/kernel/src/userfs_types.c
==============================================================================
--- trunk/kernel/src/userfs_types.c 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/kernel/src/userfs_types.c 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,5 @@
+/*
+ * Just include the generated userfs_types.c
+ */
+#include "userfs.h"
+#include <linux/userfs_types.c>
Added: trunk/kernel/src/uio.c
==============================================================================
--- trunk/kernel/src/uio.c 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/kernel/src/uio.c 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,727 @@
+/*
+ * IO to user process
+ *
+ * Jeremy Fitzhardinge <jeremy at softway.oz.au>, May 1993
+ */
+
+#include "userfs.h"
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/userfs_fs.h>
+#include <linux/userfs_fs_sb.h>
+#include <linux/locks.h>
+#include <linux/slab.h>
+#include <asm/segment.h>
+#include <asm/uaccess.h>
+
+#define DB(x) x
+
+#include <linux/assert.h>
+
+
+/* Close channels, make everything fail later */
+void userfs_close_chan(struct super_block *sb)
+{
+ struct file *file;
+
+ /* this is not really possible, but test it anyhow */
+ if (U_SBP(sb) == NULL)
+ return;
+
+ /* Wake up all sleepers before killing connection */
+ userfs_kiss(sb, UP_WALL, UP_FINISH);
+
+ if (U_SBP(sb)->s_toproc)
+ {
+ file = U_SBP(sb)->s_toproc;
+ if(file)
+ {
+#ifdef DEBUG
+ printk("freeing toproc handle %p\n",file);
+#endif
+ file->f_op->release(file->f_dentry->d_inode, file);
+ U_SBP(sb)->s_toproc = NULL;
+ }
+#ifdef DEBUG
+ else
+ {
+ printk("toproc handle was null\n");
+ }
+#endif
+ }
+
+ if (U_SBP(sb)->s_fromproc)
+ {
+ file = U_SBP(sb)->s_fromproc;
+
+ if(file)
+ {
+#ifdef DEBUG
+ printk("freeing fromproc handle %p\n",file);
+#endif
+ file->f_op->release(file->f_dentry->d_inode, file);
+ U_SBP(sb)->s_fromproc = NULL;
+ }
+#ifdef DEBUG
+ else
+ {
+ printk("fromproc handle was null\n");
+ }
+#endif
+ }
+}
+
+/*
+ * Write to a file descriptor, like the sys_write
+ *
+ * The data buffer passed in is in kernel space.
+ * The tricky part is that f_op->write needs a buffer in
+ * current's user space, so we remap "fs" to the kernel data space,
+ * so that kernel space appears as user space.
+ *
+ * This will keep writing until everything is done, unless there's
+ * EOF or an error.
+ */
+k_static int userfs_send(struct file *file, char *data, unsigned int count)
+{
+ int ret;
+ int wrote = 0;
+ mm_segment_t fs;
+ sigset_t blocked;
+
+ if (!file)
+ return -EBADF;
+
+ if (!(file->f_mode & 2))
+ return -EBADF;
+ if (!file->f_op || !file->f_op->write)
+ return -EINVAL;
+ if (!count)
+ return 0;
+
+ if (count == 0)
+ return 0;
+
+ /* inode = file->f_dentry->d_inode; */
+
+ fs = get_fs();
+ set_fs(get_ds());
+
+ /* Filesystems are supposed to be uninterruptible */
+ spin_lock(current->sigmask_lock);
+ blocked = current->blocked;
+ /* current->blocked = ~0L; */
+ sigaddset(¤t->blocked,SIGKILL);
+ spin_unlock(current->sigmask_lock);
+
+ while(count > 0)
+ {
+ assert(file != NULL);
+ assert(file->f_op != NULL);
+ assert(file->f_op->write != NULL);
+
+ /* FIXME: need to initialise ofs */
+
+ ret = file->f_op->write(file,(char *)data,count,&file->f_pos);
+
+ if (ret <= 0)
+ goto bad;
+
+ count -= ret;
+ data += ret;
+ wrote += ret;
+ }
+
+ ret = wrote;
+ bad:
+ spin_lock(current->sigmask_lock);
+ current->blocked = blocked;
+ spin_unlock(current->sigmask_lock);
+
+ set_fs(fs);
+ if (ret == 0)
+ printk("userfs_send: f_op->write wrote 0 bytes, %d total\n",
+ wrote);
+
+ return ret;
+}
+
+/*
+ * As above, except for reading into kernel space.
+ *
+ * Note that this is unlike a normal read() syscall, since it will
+ * keep reading until count bytes are read, unless the read returns
+ * error or EOF.
+ */
+k_static int userfs_recv(struct file *file, char *data, unsigned int count)
+{
+ int ret, read = 0;
+ mm_segment_t fs;
+ sigset_t blocked;
+
+ if (!file)
+ return -EBADF;
+
+ if (!(file->f_mode & 1))
+ return -EBADF;
+ if (!file->f_op || !file->f_op->read)
+ return -EBADF;
+ if (!count)
+ return 0;
+
+ fs = get_fs();
+ set_fs(get_ds());
+
+ /* Filesystems are supposed to be uninterruptible */
+ spin_lock(current->sigmask_lock);
+ blocked = current->blocked;
+/* sigaddset(¤t->blocked,SIGKILL);
+ sigaddset(¤t->blocked,SIGALRM); */
+ sigfillset(¤t->blocked);
+ spin_unlock(current->sigmask_lock);
+
+ while(count > 0)
+ {
+ assert(file != NULL);
+ assert(file->f_op != NULL);
+ assert(file->f_op->read != NULL);
+
+ /* FIXME: what was this for? */
+ /* current->blocked = (unsigned long)-1; */
+
+ ret = file->f_op->read(file,(char *)data,count,&file->f_pos);
+
+ if (ret < 0)
+ {
+ printk("userfs_recv barfed: %s : %d\n", (char *)file->f_dentry->d_name.name, ret);
+ goto bad;
+ }
+
+ if (ret == 0)
+ break;
+
+ data += ret;
+ count -= ret;
+ read += ret;
+ }
+
+ ret = read;
+bad:
+ spin_lock(current->sigmask_lock);
+ current->blocked = blocked;
+ spin_unlock(current->sigmask_lock);
+
+ set_fs(fs);
+ return ret;
+}
+
+/*
+ * Generate a normal request packet for sending, including managing
+ * seqence numbers, etc
+ */
+void userfs_genpkt(struct super_block *sb, up_preamble *pre, up_ops op)
+{
+ pre->op = op;
+ pre->version = UP_VERSION;
+ pre->isreq = UP_REQ;
+ pre->seq = U_SBP(sb)->s_seq++;
+ pre->size = 0;
+}
+
+/*
+ * Set lock on the userfs part of super block
+ */
+
+k_static void userfs_lock(struct super_block *sb)
+{
+ spin_lock(&(U_SBP(sb)->s_lock));
+}
+
+/*
+ * Release lock on userfs part of super block
+ */
+k_static void userfs_unlock(struct super_block *sb)
+{
+ spin_unlock(&(U_SBP(sb)->s_lock));
+}
+
+/*
+ * Add entry to list of waiting processes
+ */
+k_static void addwlist(struct userfs_sb_info *sbi, struct pwlist *ent)
+{
+printk("addwlist\n");
+ assert(ent != NULL);
+ if (ent == NULL)
+ return;
+
+ init_waitqueue_head(&ent->bed);
+
+ ent->next = sbi->s_wlist;
+ if (ent->next)
+ ent->next->prev = ent;
+
+ ent->prev = NULL;
+ sbi->s_wlist = ent;
+
+ sbi->s_nwproc++;
+
+ /* Assert postconditions */
+ assert(sbi->s_wlist == ent);
+ assert(ent->prev == NULL);
+ assert(ent->next == NULL || (ent->next->prev == ent));
+ assert(sbi->s_nwproc != 0);
+ assert((ent->next == NULL && sbi->s_nwproc == 1) || (ent->next != NULL && sbi->s_nwproc > 1));
+}
+
+/*
+ * Remove from list of waiting processes
+ */
+k_static void remwlist(struct userfs_sb_info *sbi, struct pwlist *ent)
+{
+printk("remwlist\n");
+ assert(ent != NULL);
+ if (ent == NULL)
+ return;
+
+ if (ent->next)
+ {
+ assert(ent->next != ent);
+ ent->next->prev = ent->prev;
+ }
+
+ if (ent->prev)
+ {
+ assert(ent->prev != ent);
+ ent->prev->next = ent->next;
+ }
+ else
+ {
+ assert(sbi->s_wlist == ent);
+ sbi->s_wlist = ent->next;
+ }
+
+ ent->next = ent->prev = NULL;
+
+ sbi->s_nwproc--;
+
+ /* Assert some postconditions */
+ assert(sbi->s_nwproc >= 0);
+ assert((sbi->s_wlist == NULL && sbi->s_nwproc == 0) || (sbi->s_wlist != NULL && sbi->s_nwproc >= 1));
+ assert(sbi->s_wlist == NULL || (sbi->s_wlist->prev == NULL));
+}
+
+#ifdef DEBUG
+k_static void dumplist(struct userfs_sb_info *sbi)
+{
+ struct pwlist *lp;
+ int i;
+printk("dumplist\n");
+
+ for(lp = sbi->s_wlist, i = 0; lp != NULL; lp = lp->next, i++)
+ printk("%d: seq %d pid=%d why=%d more=%p repl.seq=%ld\n",
+ i, lp->seq, lp->pid, lp->why, lp->more, lp->repl.seq);
+
+ assert(i == sbi->s_nwproc);
+}
+#endif
+
+/*
+ * Find waiting entry, given sequence number
+ */
+k_static struct pwlist *findwent(struct userfs_sb_info *sbi, int seq)
+{
+ struct pwlist *lp;
+printk("findwent\n");
+
+ for(lp = sbi->s_wlist; lp != NULL; lp = lp->next)
+ if (lp->seq == seq)
+ return lp;
+
+#ifdef DEBUG
+ printk("findwent: seq=%d not found, %d things on list\n",
+ seq, sbi->s_nwproc);
+ dumplist(sbi);
+#endif
+ return NULL;
+}
+
+/*
+ * Kiss one process awake. Sets up the reason, the reply header
+ * and the reply body in the list entry and wakes it up.
+ */
+k_static struct pwlist *kissone(struct super_block *sb, int seq, int why,
+ upp_repl *repl, char *more)
+{
+ struct pwlist *lp;
+ struct userfs_sb_info *sbi = U_SBP(sb);
+
+ if (seq == UP_WFIRST)
+ lp = sbi->s_wlist;
+ else
+ lp = findwent(sbi, seq);
+
+ if (lp == NULL)
+ {
+ DB(printk("kissone: nothing done for seq=%d\n",
+ seq));
+ return lp;
+ }
+
+ lp->why = why;
+
+ remwlist(sbi, lp);
+
+ if (repl != NULL)
+ {
+ lp->more = more;
+ lp->repl = *repl;
+ }
+ else
+ {
+ assert(why != UP_REPL);
+ lp->repl.size = 0;
+ lp->repl.seq = -1;
+ lp->more = NULL;
+ }
+
+ DB(printk("kissone: pid %d: kissing seq=%d, why=%d\n",
+ current->pid, seq, why));
+
+ assert(lp->pid == -1);
+
+ lp->pid = current->pid;
+ wake_up(&lp->bed);
+
+ return lp;
+}
+
+/*
+ * Wake up one or all sleeping processes
+ * If seq == UP_WFIRST, then the first process is woken. Typically
+ * this would be why==UP_BATON, meaning that the process thus woken
+ * should take resposibility for reading the pipe
+ * If seq == UP_WALL then all processes are woken. It is not
+ * meaningful to have why anything but UP_FINISH.
+ * This shouldn't be called if a specific process needs awakening
+ */
+struct pwlist *userfs_kiss(struct super_block *sb, int seq, int why)
+{
+ struct userfs_sb_info *sbi;
+ struct pwlist *lp, *nxt;
+
+ sbi = U_SBP(sb);
+
+ if (seq == UP_WFIRST)
+ {
+ return kissone(sb, seq, why, NULL, NULL);
+ }
+
+ assert(why == UP_FINISH);
+ assert(seq == UP_WALL);
+
+ for(lp = sbi->s_wlist; lp != NULL; lp = nxt)
+ {
+ nxt = lp->next;
+
+ kissone(sb, UP_WFIRST, why, NULL, NULL);
+ }
+
+ assert(sbi->s_wlist == NULL);
+ assert(sbi->s_nwproc == 0);
+
+ return NULL;
+}
+
+/*
+ * Suck stuff from the process until we get what we want,
+ * then hand responsibilty over.
+ *
+ * This will either return when this process's reply comes, or
+ * on error.
+ */
+k_static int suckin(struct super_block *sb, struct pwlist *ent)
+{
+ upp_repl repl;
+ int replsz = sizeof_upp_repl(&repl);
+ char *more;
+ size_t more_sz;
+ struct userfs_sb_info *sbi = U_SBP(sb);
+ struct file *from = sbi->s_fromproc;
+ int ret;
+ unsigned char *p0, *p;
+
+ p0 = (unsigned char *)get_free_page(GFP_KERNEL);
+
+ ret = -1; /* general failure assumed */
+
+ assert(sbi->s_canread == 1);
+
+ for(;;)
+ {
+ more = NULL;
+ more_sz = 0;
+
+ if ((ret = userfs_recv(from, (char *)p0, replsz)) != replsz)
+ {
+ printk("suckin: %d: header recv failed: replsz=%d rcv=%d\n",
+ current->pid, replsz, ret);
+ if (ret==-ERESTARTSYS)
+ {
+ printk("suckin(header): needs to restart, trying to back-out\n");
+ break;
+ }
+ userfs_close_chan(sb);
+ break;
+ }
+
+ p = decode_upp_repl(&repl, p0);
+
+ DB(printk("suckin: pid %d, seq %d got packet seq %ld, sz=%ld\n",
+ current->pid, ent->seq, repl.seq, repl.size));
+
+ assert(repl.size <= MAX_KMALLOC);
+ assert(repl.isreq == UP_REPL);
+
+ if (repl.err_no == 0 && repl.size != 0)
+ {
+ more = (char *)kmalloc(repl.size, GFP_KERNEL);
+ more_sz = repl.size;
+
+ if ((ret = userfs_recv(from, more, more_sz)) != repl.size)
+ {
+ printk("suckin: body recv failed: %d\n", ret);
+ if (ret==-ERESTARTSYS)
+ {
+ printk("suckin(body): needs to restart, trying to back-out\n");
+ break;
+ }
+ userfs_close_chan(sb);
+ break;
+ }
+ }
+
+ assert((repl.size == 0 && more == NULL) || (repl.size > 0 && more != NULL));
+
+ if (repl.seq == ent->seq)
+ {
+ /* For us! */
+
+ if (sbi->s_nwproc != 0)
+ userfs_kiss(sb, UP_WFIRST, UP_BATON);
+ else
+ sbi->s_canread = 0;
+
+ ent->more = more;
+ ent->why = UP_REPL;
+ ent->repl = repl;
+ ret = 0;
+ more = NULL;
+
+ DB(printk("suckin: sucker found its own (seq=%d), more=%p\n",
+ ent->seq, ent->more));
+ break;
+ }
+ else
+ {
+ DB(printk("suckin: %d kissing seq %ld\n",
+ ent->seq, repl.seq));
+ kissone(sb, repl.seq, UP_REPL, &repl, more);
+ }
+ }
+
+ if (more != NULL)
+ kfree(more); /* , more_sz); */
+
+ free_page((unsigned long)p0);
+
+ return ret;
+}
+
+/*
+ * Wait for the reply to return, mostly sleeping.
+ *
+ * There are two cases:
+ * 1. We wait on the pipe for incoming packets.
+ * If a packet arrives that's not for us, then
+ * we wake up the process that is responsible
+ * for it.
+ * If its for us, then we accept it and pass
+ * responsibility on to another process to cope
+ * with the incoming. If there are no other
+ * waiting processes, then there should be
+ * no outstanding replies.
+ * 2. We wait on the list for something to happen.
+ * There are 3 reasons we can get woken:
+ * - Our reply arrvies.
+ * - We become resposible for reading
+ * - We unmount, and the reply is dropped
+ * If we get a reply or umount then remove ourselves
+ * from the list
+ * We return 0 on success, 1 if we were woken with UP_FINISHED
+ */
+k_static int userfs_sleep(struct super_block *sb, int seq, upp_repl *repl,
+ char **data)
+{
+ struct pwlist ent;
+ struct userfs_sb_info *sbi;
+ int ret = 0;
+
+ sbi = U_SBP(sb);
+
+ ent.seq = seq;
+ ent.more = NULL;
+ ent.why = 0;
+ ent.pid = -1;
+ ent.repl.size = 0;
+ ent.repl.seq = -1;
+
+ if (sbi->s_canread == 0)
+ {
+ DB(printk("userfs_sleep: reading, pid=%d seq=%d\n",
+ current->pid, seq));
+
+ sbi->s_canread = 1;
+
+ ret = suckin(sb, &ent);
+
+ /* for restart, reset our state */
+ if (ret==-ERESTARTSYS)
+ sbi->s_canread = 0;
+ }
+ else
+ {
+ addwlist(sbi, &ent);
+
+ DB(printk("userfs_sleep: sleeping on list, pid=%d seq=%d\n",
+ current->pid, ent.seq));
+
+ ent.repl.seq = -1;
+
+ sleep_on(&ent.bed);
+ DB(printk("userfs_sleep: pid %d, seq %d woken by pid %d\n",
+ current->pid, ent.seq, ent.pid));
+
+ assert(ent.pid != -1);
+ assert(ent.pid != current->pid);
+
+ switch(ent.why)
+ {
+ case UP_BATON: /* We were woken to be reader */
+ assert(sbi->s_canread == 1);
+ DB(printk("userfs_sleep: pid %d, seq %d taking on reader job\n",
+ current->pid, ent.seq));
+
+ ret = suckin(sb, &ent);
+ break;
+
+ case UP_REPL: /* Our prince arrived */
+ DB(printk("userfs_sleep: pid %d woken with %ld bytes in %p\n",
+ current->pid, ent.repl.size, ent.more));
+ break;
+
+ case UP_FINISH: /* We were sleeping and the connection failed */
+ printk("userfs_sleep: got UP_FINISH from %d\n",
+ ent.pid);
+ ret = -EPROTO;
+ break;
+
+ default: /* Bad reason for waking */
+ printk("userfs_sleep: woke with bad why=%d from pid %d\n",
+ ent.why, ent.pid);
+ ret = -EPROTO;
+ break;
+ }
+ }
+
+ if (ret != 0)
+ printk("userfs_sleep: failed with %d\n", ret);
+ else
+ {
+ *data = ent.more;
+ *repl = ent.repl;
+ }
+
+ return ret;
+}
+
+/*
+ * Deal with a normal send/reply transaction.
+ *
+ * This writes out the request in two parts. This locks the super
+ * block to prevent other operations from going out at the same
+ * time. After that we sleep until the reply comes in.
+ * Decode it and return.
+ */
+int __userfs_doop(struct super_block *sb,
+ up_preamble *pre, upp_repl *repl,
+ encode_func se, void *send,
+ decode_func rd, void *recv,
+ sizeof_func sso, sizeof_func rso)
+{
+ int ret;
+ unsigned char *p, *p0;
+ char *more = NULL;
+ struct file *to = U_SBP(sb)->s_toproc;
+
+ p = p0 = (unsigned char *)get_free_page(GFP_KERNEL);
+
+ assert(pre->version == UP_VERSION);
+ assert(pre->size <= MAX_KMALLOC);
+ assert(pre->isreq == UP_REQ || pre->isreq == UP_ENQ);
+
+ pre->size = (*sso)(send);
+ assert(pre->size <= MAX_KMALLOC);
+
+ /* Atomically send the packet */
+ userfs_lock(sb);
+ p = encode_up_preamble(pre, p0);
+ if ((ret = userfs_send(to, (char *)p0, p-p0)) <= 0)
+ {
+ printk("userfs_doop: header send failed: %d\n", ret);
+ userfs_close_chan(sb);
+ free_page((long)p0);
+ userfs_unlock(sb);
+ return ret;
+ }
+
+ if (pre->size > 0)
+ {
+ p = (*se)(send, p0);
+ if ((ret = userfs_send(to, (char *)p0, p-p0)) <= 0)
+ {
+ printk("userfs_doop: body send failed: %d\n", ret);
+ userfs_close_chan(sb);
+ free_page((long)p0);
+ userfs_unlock(sb);
+ return ret;
+ }
+ assert(p - p0 == pre->size);
+ }
+
+ /* Sleep until a prince comes */
+ if ((ret = userfs_sleep(sb, pre->seq, repl, &more)) == 0)
+ {
+ if (more != NULL)
+ {
+ (*rd)(recv, (unsigned char *)more);
+ assert(repl->size == (*rso)(recv));
+ DB(printk("userfs_doop: more=%p\n", more));
+ kfree(more); /*, repl->size); */
+ }
+ }
+ else if (ret==-ERESTARTSYS)
+ printk("userfs_doop: userfs_sleep interrupted by signal in %d\n", current->pid);
+ else
+ printk("userfs_doop: userfs_sleep failed with %d\n", ret);
+
+ userfs_unlock(sb);
+
+ free_page((long)p0);
+
+ return ret;
+}
Added: trunk/kernel/src/Makefile
==============================================================================
--- trunk/kernel/src/Makefile 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/kernel/src/Makefile 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,46 @@
+#
+# Makefile for the Linux userfs-filesystem routines.
+#
+# Edit DEFINES below depending on your kernel version
+#
+
+TOP=../..
+include $(TOP)/rules
+
+CC=$(KERNCC)
+
+#define __SMP__ if you use smp... otherwise bad things will happen
+#DEFINES= -DMODULE -DMODVERSIONS -DDEBUG
+DEFINES= -DMODULE -DDEBUG
+CFLAGS=-nostdinc -I/usr/lib/gcc-lib/i386-linux/2.95.4/include -I/usr/src/linux/include -I.. -O2 -fomit-frame-pointer $(DEFINES) -D__KERNEL__ -Wall
+XCFLAGS=
+INCL=../linux
+
+all:: userfs.o
+
+typedir: userfs_types.ty types
+ rm -f types/*
+ $(GENCODE) -sedl types userfs_types.ty
+ rm -f types/encode*_r.c types/decode*_s.c
+ cd types; for i in *.c ; do echo $$i: ; $(CC) -I.. $(CFLAGS) -c $$i; done
+ touch typedir
+
+OBJS= inode.o file.o super.o uio.o userfs_types.o module.o
+
+types: dummy
+ mkdir types
+
+userfs.o: $(OBJS)
+ $(LD) -r -o $@ $(OBJS)
+
+types.a: typedir
+ rm -f types.a
+ $(AR) r types.a types/*.o
+ ranlib types.a
+
+clean::
+ rm -f core *.o *.a *.s *~
+ rm -f types/* typedir types.a
+
+depend dep:: $(INCL)/userfs_types.h
+ $(CPP) $(CFLAGS) -M *.c > .depend
Added: trunk/kernel/src/userfs.h
==============================================================================
--- trunk/kernel/src/userfs.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/kernel/src/userfs.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,167 @@
+/*
+ * local defs of useful things
+ */
+
+#ifndef __FS_USERFS_USERFS_H_SEEN__
+#define __FS_USERFS_USERFS_H_SEEN__
+
+/* Versioning */
+#include <linux/version.h>
+#define KVERS(maj,min,pat) ((maj)<<16|(min)<<8|(pat))
+
+#if !defined(LINUX_VERSION_CODE) || (LINUX_VERSION_CODE < KVERS(2,2,0))
+#error "This version of Userfs is only supported on 2.2.6"
+#endif /* LINUX_VERSION_CODE */
+
+/* Module support */
+#ifndef MODULE
+#error "This version of Userfs must be compiled as a module."
+#endif /* MODULE */
+
+/* #include <linux/autoconf.h> */
+/* #include <linux/module.h> */
+
+#ifdef MODVERSIONS
+#include <linux/modversions.h>
+#endif /* MODVERSIONS */
+
+#if __cplusplus
+#define __FUNCTION__ "__FUNCTION__:"__FILE__":(function/line unknown)"
+#endif
+
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+#define MAX(a,b) (((a) > (b)) ? (a) : (b))
+
+extern struct file_operations userfs_file_operations;
+extern struct inode_operations userfs_inode_operations;
+extern struct super_operations userfs_super_operations;
+
+#include <linux/userfs_fs.h>
+
+struct super_block;
+struct inode;
+
+extern void userfs_close_chan(struct super_block *);
+extern void userfs_setcred(up_cred *);
+
+extern struct super_operations *userfs_probe_sops(struct super_block *);
+extern struct inode_operations *userfs_probe_iops(struct super_block *);
+extern struct file_operations *userfs_probe_fops(struct super_block *);
+
+extern int userfs_probe(struct super_block *, up_ops);
+extern void userfs_set_inode(struct inode *, const up_inode *);
+extern void userfs_read_inode(struct inode *);
+
+extern int do_userfs_read(struct inode *, up_credtok, off_t, char *, int, int);
+
+/* Access macros for union members */
+
+/*
+** Get a ptr to the userfs sb info struct from a ptr to a sb struct
+**
+** This assumes that union in the superblock is large enough to
+** fit the userfs_fs_info structure. This is reasonable, because the
+** union includes the proprietary information of many other fs's.
+*/
+#define U_SBP(sb) ((struct userfs_sb_info *)&((sb)->u.generic_sbp))
+
+/*
+** Get a ptr to the userfs inode info struct from a ptr to an inode
+**
+** Comment similar to that for the superblock.
+*/
+#define U_INOP(ino) ((struct userfs_inode_info *)&((ino)->u.generic_ip))
+
+/*
+** Get a ptr to the userfs file info struct from a ptr to a file.
+**
+** Aye ah. This one is different. You must malloc it first, because
+** there isn't enough space in the struct to store all our info :-(
+*/
+#define U_FILEP(file) ((struct userfs_file_info *)((file)->private_data))
+
+/*
+** old defined from when we used to malloc these things
+**
+** #define U_SB(sb) (*(struct userfs_sb_info *)(sb)->u.generic_sbp)
+** #define U_INO(ino) (*(struct userfs_inode_info *)(ino)->u.generic_ip)
+** #define U_SBP(sb) ((struct userfs_sb_info *)(sb)->u.generic_sbp)
+** #define U_INOP(ino) ((struct userfs_inode_info *)(ino)->u.generic_ip)
+** #define U_FILEP(file) ((struct userfs_file_info *)(file)->private_data)
+** #define U_FILE(file) (*(struct userfs_file_info *)(file)->private_data)
+*/
+
+/*
+** old defines from when we were in the kernel
+**
+** #define U_SB(sb) ((sb)->u.userfs_sb)
+** #define U_INO(ino) ((ino)->u.userfs_i)
+** #define U_FILE(file) ((file)->u.userfs_f)
+*/
+
+/* A kiss to end a sleep */
+extern struct pwlist *userfs_kiss(struct super_block *, int seq, int why);
+
+/* reasons why */
+#define UP_FINISH 1 /* Finish up - your prince will never come */
+#define UP_RECV 2 /* Your prince has arrived */
+#define UP_BATON 3 /* You take over */
+
+/* for matching entries */
+#define UP_WFIRST (-1) /* wake first */
+#define UP_WALL (-2) /* wake all entries */
+
+/* Element on list of sleeping processes */
+struct pwlist
+{
+ wait_queue_head_t bed; /* where we sleep */
+ int why; /* filled on wake - why we woke */
+ int seq; /* reply seqence */
+ upp_repl repl; /* reply header */
+ char *more; /* extra data */
+ int pid; /* prince id */
+
+ struct pwlist *next; /* there are other beauties */
+ struct pwlist *prev;
+};
+
+/*
+ * kmalloc is much less restricted than it used to be, but I'm still not
+ * allocating more than 4k, because there's little need.
+ */
+#define MAX_KMALLOC USERFS_MAX_XFER
+#include <linux/slab.h>
+
+/* Directory readahead things */
+void userfs_free_dirra(struct inode *ino);
+
+struct userfs_dir_ra
+{
+ int nent; /* Number of entries */
+ struct userfs_dent *ents; /* Entries */
+};
+
+struct userfs_dent
+{
+ off_t offset; /* Dir offset */
+ off_t roff; /* Returned offset */
+ ino_t inum; /* Inode number */
+ char *name; /* Name, not \0 terminated */
+ unsigned nlen; /* Name length */
+};
+
+extern void userfs_lock_inode(struct inode *);
+extern void userfs_unlock_inode(struct inode *);
+
+/*
+ * If we are debugging, bare all. If we generate an exception,
+ * we can lookup /proc/ksyms to see round about where things stuffed up.
+ */
+#ifdef DEBUG
+#define k_static
+#else
+#define k_static static
+#endif
+
+#endif /* __FS_USERFS_USERFS_H_SEEN__ */
+
Added: trunk/kernel/types.h
==============================================================================
--- trunk/kernel/types.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/kernel/types.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,130 @@
+#ifndef _LINUX_TYPES_H
+#define _LINUX_TYPES_H
+
+#ifdef __KERNEL__
+#include <linux/config.h>
+#endif
+
+#include <linux/posix_types.h>
+#include <asm/types.h>
+
+#ifndef __KERNEL_STRICT_NAMES
+
+typedef __kernel_fd_set fd_set;
+typedef __kernel_dev_t dev_t;
+typedef __kernel_ino_t ino_t;
+typedef __kernel_mode_t mode_t;
+typedef __kernel_nlink_t nlink_t;
+typedef __kernel_off_t off_t;
+typedef __kernel_pid_t pid_t;
+typedef __kernel_daddr_t daddr_t;
+typedef __kernel_key_t key_t;
+typedef __kernel_suseconds_t suseconds_t;
+
+#ifdef __KERNEL__
+typedef __kernel_uid32_t uid_t;
+typedef __kernel_gid32_t gid_t;
+typedef __kernel_uid16_t uid16_t;
+typedef __kernel_gid16_t gid16_t;
+
+#ifdef CONFIG_UID16
+/* This is defined by include/asm-{arch}/posix_types.h */
+typedef __kernel_old_uid_t old_uid_t;
+typedef __kernel_old_gid_t old_gid_t;
+#endif /* CONFIG_UID16 */
+
+/* libc5 includes this file to define uid_t, thus uid_t can never change
+ * when it is included by non-kernel code
+ */
+#else
+typedef __kernel_uid_t uid_t;
+typedef __kernel_gid_t gid_t;
+#endif /* __KERNEL__ */
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+typedef __kernel_loff_t loff_t;
+#endif
+
+/*
+ * The following typedefs are also protected by individual ifdefs for
+ * historical reasons:
+ */
+#ifndef _SIZE_T
+#define _SIZE_T
+typedef __kernel_size_t size_t;
+#endif
+
+#ifndef _SSIZE_T
+#define _SSIZE_T
+typedef __kernel_ssize_t ssize_t;
+#endif
+
+#ifndef _PTRDIFF_T
+#define _PTRDIFF_T
+typedef __kernel_ptrdiff_t ptrdiff_t;
+#endif
+
+#ifndef _TIME_T
+#define _TIME_T
+typedef __kernel_time_t time_t;
+#endif
+
+#ifndef _CLOCK_T
+#define _CLOCK_T
+typedef __kernel_clock_t clock_t;
+#endif
+
+#ifndef _CADDR_T
+#define _CADDR_T
+typedef __kernel_caddr_t caddr_t;
+#endif
+
+/* bsd */
+typedef unsigned char u_char;
+typedef unsigned short u_short;
+typedef unsigned int u_int;
+typedef unsigned long u_long;
+
+/* sysv */
+typedef unsigned char unchar;
+typedef unsigned short ushort;
+typedef unsigned int uint;
+typedef unsigned long ulong;
+
+#ifndef __BIT_TYPES_DEFINED__
+#define __BIT_TYPES_DEFINED__
+
+typedef __u8 u_int8_t;
+typedef __s8 int8_t;
+typedef __u16 u_int16_t;
+typedef __s16 int16_t;
+typedef __u32 u_int32_t;
+typedef __s32 int32_t;
+
+#endif /* !(__BIT_TYPES_DEFINED__) */
+
+typedef __u8 uint8_t;
+typedef __u16 uint16_t;
+typedef __u32 uint32_t;
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+typedef __u64 uint64_t;
+typedef __u64 u_int64_t;
+typedef __s64 int64_t;
+#endif
+
+#endif /* __KERNEL_STRICT_NAMES */
+
+/*
+ * Below are truly Linux-specific types that should never collide with
+ * any application/library that wants linux/types.h.
+ */
+
+struct ustat {
+ __kernel_daddr_t f_tfree;
+ __kernel_ino_t f_tinode;
+ char f_fname[6];
+ char f_fpack[6];
+};
+
+#endif /* _LINUX_TYPES_H */
Added: trunk/kernel/Makefile
==============================================================================
--- trunk/kernel/Makefile 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/kernel/Makefile 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,7 @@
+# Userfs kernel top Makefile
+TOP=..
+SUBDIRS=linux src
+all:: subdirs
+
+include ../rules.sub
+include ../rules
Added: trunk/rules.sub
==============================================================================
--- trunk/rules.sub 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/rules.sub 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,8 @@
+subdirs::
+ set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i; done
+
+#dep depend::
+# set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i dep; done
+
+#clean::
+# set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i clean; done
Added: trunk/genser/symtab.c
==============================================================================
--- trunk/genser/symtab.c 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/genser/symtab.c 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,384 @@
+/* Symbol table handling */
+
+#include "com.h"
+#include "symtab.h"
+
+/* Global symbol/type table */
+Var *global;
+
+/* Table for dealing with structures */
+Var *structures;
+
+Var *lookup(Var *table, const char *sym)
+{
+ for(; table != NULL; table = table->next)
+ if (strcmp(sym, table->name) == 0)
+ return table;
+
+ return NULL;
+}
+
+Var *mkvar(Type *type, char *name)
+{
+ Var *var = (Var *)malloc(sizeof(*var));
+
+ var->name = name;
+ var->next = NULL;
+ var->prev = NULL;
+ var->type = type;
+
+ return var;
+}
+
+Var *add(Var *table, Var *var)
+{
+ assert(var != NULL);
+
+ var->next = var->prev = NULL;
+
+ if (table != NULL)
+ {
+ Var *tp = table;
+
+ while(tp->next != NULL)
+ tp = tp->next;
+
+ tp->next = var;
+ var->prev = tp;
+ }
+ else
+ table = var;
+
+ return table;
+}
+
+Var *addl(Var *table, Var *l)
+{
+ Var *n;
+
+ assert(l != NULL);
+
+ for(; l != NULL; l = n)
+ {
+ n = l->next;
+ table = add(table, l);
+ }
+
+ return table;
+}
+
+Var *preadd(Var *table, Var *var)
+{
+ var->next = table;
+ if (table)
+ table->prev = var;
+
+ return var;
+}
+
+int type_sizeof(const Type *ty)
+{
+ int sz = 0;
+
+ switch(ty->tclass)
+ {
+ case Scalar:
+ switch(ty->i.scalar_i.size)
+ {
+ case NoType: sz = 0; break;
+ case Char: sz = 1; break;
+ case Short: sz = 2; break;
+ case Long: sz = 4; break;
+ case LongLong: sz = 8; break;
+ case Float: sz = 4; break;
+ case Double: sz = 8; break;
+ }
+ break;
+
+ case Pointer:
+ sz = 4; /* XXX */
+ break;
+
+ case Void:
+ sz = 0;
+ break;
+
+ case CArray:
+ sz = ty->i.carray_i.size * type_sizeof(ty->i.carray_i.type);
+ break;
+
+ default:
+ sz = 0; /* XXX */
+ break;
+ }
+
+ return sz;
+}
+
+Type *mktype(void)
+{
+ Type *tp = (Type *)malloc(sizeof(Type));
+
+ tp->tclass = NoType;
+ tp->anon = 1;
+ tp->nocode = 0;
+ tp->nohdr = 0;
+ tp->demand = 0;
+ tp->norep = 0;
+ tp->coded = 0;
+ tp->name = NULL;
+
+ return tp;
+}
+
+Var *mktypedef(Type *type, char *name)
+{
+ Type *td = mktype();
+ Var *tv = mkvar(td, name);
+
+ td->tclass = Typedef;
+ td->i.typedef_i.t = type;
+ td->i.typedef_i.n = name;
+ type->anon = 0;
+
+ if (type->name == NULL)
+ type->name = td;
+
+ td->anon = 0;
+ td->norep = type->norep;
+
+ return tv;
+}
+
+Type *mkstruct(Var *vars)
+{
+ Type *st = mktype();
+
+ st->tclass = Struct;
+ st->i.struct_i = vars;
+
+ return st;
+}
+
+Type *mkpointer(Type *type)
+{
+ Type *pt = mktype();
+
+ pt->tclass = Pointer;
+ pt->i.pointer_i = type;
+
+ return pt;
+}
+
+Type *mkvoid(void)
+{
+ Type *v = mktype();
+
+ v->tclass = Void;
+ return v;
+}
+
+Type *mkarray(Type *type)
+{
+ Type *at = mktype();
+
+ at->tclass = Array;
+ at->i.array_i = type;
+
+ return at;
+}
+
+Type *mkcarray(Type *type, unsigned int size)
+{
+ Type *at = mktype();
+
+ at->tclass = CArray;
+ at->i.carray_i.type = type;
+ at->i.carray_i.size = size;
+
+ return at;
+}
+
+Type *mkscalar(enum sc_size sz, int sgn)
+{
+ Type *st = mktype();
+
+ st->tclass = Scalar;
+ st->i.scalar_i.size = sz;
+ st->i.scalar_i.Unsigned = sgn;
+
+ return st;
+}
+
+Type *realtype(Type *t)
+{
+ while(t && t->tclass == Typedef)
+ t = t->i.typedef_i.t;
+
+ return t;
+}
+
+Type *Ulonglong_type;
+Type *Ulong_type;
+Type *Ushort_type;
+Type *Uchar_type;
+Type *longlong_type;
+Type *long_type;
+Type *short_type;
+Type *char_type;
+Type *void_type;
+Type *float_type;
+Type *double_type;
+
+/*
+ * Carefully set up symbol table types. Most of the fiddling here
+ * is to cover the slight differences between our type system and
+ * C's
+ */
+void init_symtab(void)
+{
+ Var *v;
+ Type *t;
+
+ global = NULL;
+ structures = NULL;
+
+ t = char_type = mkscalar(Char, 0);
+ t->nocode = t->nohdr = 1;
+ t = Uchar_type = mkscalar(Char, 1);
+ t->nocode = 1;
+
+ t = short_type = mkscalar(Short, 0);
+ t->nocode = t->nohdr = 1;
+ t = Ushort_type = mkscalar(Short, 1);
+ t->nocode = 1;
+
+ t = long_type = mkscalar(Long, 0);
+ t->nocode = t->nohdr = 1;
+ t = Ulong_type = mkscalar(Long, 1);
+ t->nocode = 1;
+
+ t = longlong_type = mkscalar(LongLong, 0);
+ t->nocode = t->nohdr = 1;
+ t = Ulonglong_type = mkscalar(LongLong, 1);
+ t->nocode = 1;
+
+ t = float_type = mkscalar(Float, 0);
+ t->nocode = t->nohdr = 1;
+ t = double_type = mkscalar(Double, 1);
+ t->nocode = 1;
+
+ t = void_type = mkvoid();
+ t->nohdr = t->nocode = t->norep = 1;
+
+ global = add(global, v = mktypedef(char_type, "char"));
+ v->type->nocode = v->type->nohdr = 1;
+ global = add(global, v = mktypedef(short_type, "short"));
+ v->type->nocode = v->type->nohdr = 1;
+ global = add(global, v = mktypedef(long_type, "long"));
+ v->type->nocode = v->type->nohdr = 1;
+ global = add(global, v = mktypedef(longlong_type, "longlong"));
+ v->type->nocode = v->type->nohdr = 1;
+
+ global = add(global, v = mktypedef(float_type, "float"));
+ v->type->nocode = v->type->nohdr = 1;
+ global = add(global, v = mktypedef(double_type, "double"));
+ v->type->nocode = v->type->nohdr = 1;
+
+ global = add(global, v = mktypedef(void_type, "void"));
+ v->type->nohdr = v->type->nocode = v->type->norep = 1;
+
+ global = add(global, v = mktypedef(Uchar_type, "Uchar"));
+ v->type->nocode = v->type->nohdr = 1;
+ global = add(global, v = mktypedef(Ushort_type, "Ushort"));
+ v->type->nocode = v->type->nohdr = 1;
+ global = add(global, v = mktypedef(Ulong_type, "Ulong"));
+ v->type->nocode = v->type->nohdr = 1;
+ global = add(global, v = mktypedef(Ulonglong_type, "Ulonglong"));
+ v->type->nocode = v->type->nohdr = 1;
+ global = add(global, v=mktypedef(Ulong_type, "Uint"));
+ v->type->demand = v->type->nohdr = v->type->indir = 1;
+
+ global = add(global, v=mktypedef(long_type, "int"));
+ v->type->demand = v->type->nohdr = v->type->indir = 1;
+}
+
+extern char *prefix;
+
+static Var *name_type(Type *type, Var *var)
+{
+ Var *vp;
+ static int typecnt = 1;
+
+ if (type->tclass != Typedef && type->anon == 1)
+ {
+ char buf[20];
+ Var *nv;
+
+ sprintf(buf, "_%s_%03d", prefix, typecnt++);
+
+ nv = mktypedef(type, strdup(buf));
+ type->anon = 1;
+
+ var = preadd(var, nv);
+ }
+
+ switch(type->tclass)
+ {
+ case Array:
+ var = name_type(type->i.array_i, var);
+ break;
+
+ case CArray:
+ var = name_type(type->i.carray_i.type, var);
+ break;
+
+ case Pointer:
+ var = name_type(type->i.pointer_i, var);
+ break;
+
+ case Struct:
+ for(vp = type->i.struct_i; vp != NULL; vp = vp->next)
+ var = name_type(vp->type, var);
+ break;
+
+ case Typedef:
+ var = name_type(type->i.typedef_i.t, var);
+ break;
+
+ default:
+ break;
+ }
+
+ return var;
+}
+
+Var *name_types(Var *table)
+{
+ Var *vp, *sc;
+ Var *tab;
+
+ for(tab = table; tab != NULL; tab = tab->next)
+ {
+ if (tab->type->nocode)
+ continue;
+ vp = name_type(tab->type, NULL);
+
+ if (vp == NULL)
+ continue;
+
+ for(sc = vp; sc->next != NULL; sc = sc->next)
+ ;
+
+ vp->prev = tab->prev;
+ if (tab->prev)
+ tab->prev->next = vp;
+ else
+ table = vp;
+
+ sc->next = tab;
+ tab->prev = sc;
+ }
+
+ return table;
+}
Added: trunk/genser/misc.h
==============================================================================
--- trunk/genser/misc.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/genser/misc.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,13 @@
+#ifndef _MISC_H_SEEN_
+#define _MISC_H_SEEN_
+
+struct cmdarg
+{
+ char *str;
+ struct cmdarg *n;
+};
+
+struct cmdarg *add_cmdarg(struct cmdarg *, const char *str);
+char *cat_args(struct cmdarg *);
+
+#endif /* _MISC_H_SEEN_ */
Added: trunk/genser/coder.h
==============================================================================
--- trunk/genser/coder.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/genser/coder.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,283 @@
+/* Base type primitives */
+
+#ifndef __CODER_H_SEEN__
+#define __CODER_H_SEEN__
+
+#ifndef __GNUC__
+#define __inline__ /* */
+#endif
+
+#ifndef __cplusplus
+#ifndef ALLOC
+extern void *malloc(unsigned long);
+extern void free(void *);
+#define ALLOC(s) malloc(s)
+#define FREE(s) free(s)
+#endif /* ALLOC */
+#endif __cplusplus
+
+/* Types we use */
+typedef unsigned char Uchar;
+typedef unsigned short Ushort;
+typedef unsigned long Ulong;
+typedef unsigned long Uint;
+typedef unsigned long long Ulonglong;
+typedef long long longlong;
+
+/** char **/
+__inline__ static unsigned char *encode_char(const char *ch, unsigned char *buf)
+{
+ *buf = *ch;
+ return buf+1;
+}
+
+__inline__ static unsigned char *decode_char(char *ch, unsigned char *buf)
+{
+ *ch = *buf;
+ return buf+1;
+}
+
+__inline__ static unsigned int sizeof_char(const char *c)
+{
+ (void)c;
+ return 1;
+}
+
+/** unsigned char **/
+__inline__ static unsigned char *encode_Uchar(const Uchar *ch, unsigned char *buf)
+{
+ *buf = *ch;
+ return buf+1;
+}
+
+__inline__ static unsigned char *decode_Uchar(Uchar *ch, unsigned char *buf)
+{
+ *ch = *buf;
+ return buf+1;
+}
+
+__inline__ static unsigned int sizeof_Uchar(const Uchar *c)
+{
+ (void)c;
+ return 1;
+}
+
+/** short **/
+__inline__ static unsigned char *encode_short(const short *sh, unsigned char *buf)
+{
+ register short sv = *sh;
+
+ buf[0] = (sv >> 8)& 0xff;
+ buf[1] = sv & 0xff;
+ return buf+2;
+}
+
+__inline__ static unsigned char *decode_short(short *sh, unsigned char *buf)
+{
+ *sh = (buf[0] << 8) | buf[1];
+ return buf+2;
+}
+
+__inline__ static unsigned int sizeof_short(const short *c)
+{
+ (void)c;
+ return 2;
+}
+
+/** unsigned short **/
+__inline__ static unsigned char *encode_Ushort(const Ushort *sh, unsigned char *buf)
+{
+ register Ushort sv = *sh;
+
+ buf[0] = (sv >> 8)& 0xff;
+ buf[1] = sv & 0xff;
+ return buf+2;
+}
+
+__inline__ static unsigned char *decode_Ushort(Ushort *sh, unsigned char *buf)
+{
+ *sh = (buf[0] << 8) | buf[1];
+ return buf+2;
+}
+
+__inline__ static unsigned int sizeof_Ushort(const Ushort *c)
+{
+ (void)c;
+ return 2;
+}
+
+/** long **/
+__inline__ static unsigned char *encode_long(const long *l, unsigned char *buf)
+{
+ register long lv = *l;
+
+ buf[0] = (lv >> 24) & 0xff;
+ buf[1] = (lv >> 16) & 0xff;
+ buf[2] = (lv >> 8) & 0xff;
+ buf[3] = lv & 0xff;
+ return buf+4;
+}
+
+__inline__ static unsigned char *decode_long(long *l, unsigned char *buf)
+{
+ *l = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
+ return buf+4;
+}
+
+__inline__ static unsigned int sizeof_long(const long *c)
+{
+ (void)c;
+ return 4;
+}
+
+/** unsigned long **/
+__inline__ static unsigned char *encode_Ulong(const Ulong *l, unsigned char *buf)
+{
+ register Ulong lv = *l;
+
+ buf[0] = (lv >> 24) & 0xff;
+ buf[1] = (lv >> 16) & 0xff;
+ buf[2] = (lv >> 8) & 0xff;
+ buf[3] = lv & 0xff;
+ return buf+4;
+}
+
+__inline__ static unsigned char *decode_Ulong(Ulong *l, unsigned char *buf)
+{
+ *l = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
+ return buf+4;
+}
+
+__inline__ static unsigned int sizeof_Ulong(const Ulong *c)
+{
+ (void)c;
+ return 4;
+}
+
+/** long long */
+__inline__ static unsigned char *encode_longlong(const long long *l,
+ unsigned char *buf)
+{
+ register long long lv = *l;
+
+ buf[0] = (lv >> 56) & 0xff;
+ buf[1] = (lv >> 48) & 0xff;
+ buf[2] = (lv >> 40) & 0xff;
+ buf[3] = (lv >> 32) & 0xff;
+ buf[4] = (lv >> 24) & 0xff;
+ buf[5] = (lv >> 16) & 0xff;
+ buf[6] = (lv >> 8) & 0xff;
+ buf[7] = lv & 0xff;
+
+ return buf+8;
+}
+
+__inline__ static unsigned char *decode_longlong(long long *l,
+ unsigned char *buf)
+{
+#define BUF(x) ((long long)(buf[x]))
+ *l = (BUF(0) << 56)|(BUF(1) << 48)|(BUF(2) << 40)|(BUF(3) << 32)|
+ (BUF(4) << 24)|(BUF(5) << 16)|(BUF(6) << 8)|BUF(7);
+#undef BUF
+ return buf+8;
+}
+
+__inline__ static unsigned int sizeof_longlong(const long long *c)
+{
+ (void)c;
+ return 8;
+}
+
+/** unsigned long long */
+__inline__ static unsigned char *encode_Ulonglong(const unsigned long long *l,
+ unsigned char *buf)
+{
+ register unsigned long long lv = *l;
+
+ buf[0] = (lv >> 56) & 0xff;
+ buf[1] = (lv >> 48) & 0xff;
+ buf[2] = (lv >> 40) & 0xff;
+ buf[3] = (lv >> 32) & 0xff;
+ buf[4] = (lv >> 24) & 0xff;
+ buf[5] = (lv >> 16) & 0xff;
+ buf[6] = (lv >> 8) & 0xff;
+ buf[7] = lv & 0xff;
+
+ return buf+8;
+}
+
+__inline__ static unsigned char *decode_Ulonglong(unsigned long long *l,
+ unsigned char *buf)
+{
+#define BUF(x) ((unsigned long long)(buf[x]))
+ *l = (BUF(0) << 56)|(BUF(1) << 48)|(BUF(2) << 40)|(BUF(3) << 32)|
+ (BUF(4) << 24)|(BUF(5) << 16)|(BUF(6) << 8)|BUF(7);
+#undef BUF
+ return buf+8;
+}
+
+__inline__ static unsigned int sizeof_Ulonglong(const unsigned long long *c)
+{
+ (void)c;
+ return 8;
+}
+
+/** void **/
+__inline__ static unsigned char *encode_void(const void *v, unsigned char *buf)
+{
+ (void)v;
+ return buf;
+}
+
+__inline__ static unsigned char *decode_void(void *v, unsigned char *buf)
+{
+ (void)v;
+ return buf;
+}
+
+__inline__ static unsigned int sizeof_void(const void *c)
+{
+ (void)c;
+ return 0;
+}
+
+/* Assuming this host has IEEE 754 floats, this is all OK */
+/** float **/
+__inline__ static unsigned char *encode_float(const float *f, unsigned char *buf)
+{
+ *(float *)buf = *f;
+ return buf + sizeof(float);
+}
+
+__inline__ static unsigned char *decode_float(float *f, unsigned char *buf)
+{
+ *f = *(float *)buf;
+ return buf + sizeof(float);
+}
+
+__inline__ static unsigned int sizeof_float(const float *c)
+{
+ (void)c;
+ return sizeof(float);
+}
+
+/** double **/
+__inline__ static unsigned char *encode_double(const double *d, unsigned char *buf)
+{
+ *(double *)buf = *d;
+ return buf + sizeof(double);
+}
+
+__inline__ static unsigned char *decode_double(double *d, unsigned char *buf)
+{
+ *d = *(double *)buf;
+ return buf + sizeof(double);
+}
+
+__inline__ static unsigned int sizeof_double(const double *c)
+{
+ (void)c;
+ return sizeof(double);
+}
+
+#endif /* __CODER_H_SEEN__ */
Added: trunk/genser/parser.y
==============================================================================
--- trunk/genser/parser.y 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/genser/parser.y 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,338 @@
+/* -*- fundamental -*- */
+
+%{
+#include "com.h"
+#include "symtab.h"
+
+#define YYERROR_VERBOSE
+
+static int nohdr = 0;
+
+static Type *set_type(Type *, Type *);
+void yyerror(const char *, ...);
+int yylex(void);
+%}
+
+%union
+{
+ Var *var;
+ Type *type;
+ char *name;
+ int num;
+}
+
+%token STRUCT TYPEDEF SIGNED UNSIGNED NOTHDR GENERATE VOID
+%token STATIC CONST EXTERN ELLIPSIS VOLATILE SIZEOF
+%token <name> IDENT
+%token <type> TYPE
+%token <num> NUM
+%token <name> STRING
+
+%left '-' '+'
+%left '*' '/'
+
+%type <type> type struct qual_type unsigned signed
+%type <var> type_name varlist typedef c_ident c_id_list type_list
+%type <name> op_ident
+%type <num> const sizeof
+
+%%
+
+sfile : /* */
+ | sfile actions
+ ;
+
+actions : nothdr
+ | header_thing
+ | generate
+ ;
+
+nothdr : NOTHDR '{' { nohdr++; } header_things { nohdr--; } '}'
+ ;
+
+type_list: STRING { $$ = mkvar(NULL, $1); }
+ | type_list ',' STRING { $$ = add($1, mkvar(NULL, $3)); }
+ ;
+
+/* Cause code to be generated for types */
+generate: GENERATE type_list ';'
+ {
+ Var *v = $2;
+ for(; v != NULL; v = v->next)
+ {
+ Var *tv = lookup(global, v->name);
+ if (tv)
+ tv->type->demand = 0;
+ else
+ yyerror("Type %s unknown", v->name);
+ }
+ }
+ ;
+
+/* things we're likely to find in a header file */
+header_thing: typedefs
+ | prototype
+ | vars
+ ;
+
+header_things: header_thing
+ | header_things header_thing
+ ;
+
+/* List of typedef statements */
+typedefs: typedef { if ($1 != NULL) global = addl(global, $1); }
+ | typedefs typedef
+ {
+ if ($2 != NULL)
+ global = addl(global, $2);
+ }
+ ;
+
+/* A single typedef */
+typedef : TYPEDEF type c_id_list ';'
+ {
+ Var *v, *l = NULL;
+ for(v = $3; v != NULL; v = v->next)
+ {
+ Var *td;
+ v->type = set_type(v->type, $2);
+ td = mktypedef(v->type, v->name);
+ td->type->nohdr = nohdr;
+ td->type->demand = nohdr;
+ l = add(l, td);
+ }
+ $$ = l;
+ }
+ | struct ';' { $$ = NULL; }
+
+
+ | TYPEDEF type '(' c_ident ')' '(' comma_proto_list ')' ';'
+ {
+ $$ = NULL;
+ }
+ ;
+
+/* A list of type-ident pairs */
+varlist: /* */ { $$ = NULL; }
+ | varlist type_name { $$ = $2 == NULL ? NULL : addl($1, $2); }
+ ;
+
+/* A type with a list of names */
+type_name: type c_id_list ';'
+ {
+ Var *v, *n, *l = NULL;
+ for(v = $2; v != NULL; v = n) {
+ n = v->next;
+ v->type = set_type(v->type, $1);
+ l = add(l, v);
+ }
+ $$ = l;
+ }
+ ;
+
+const : NUM { $$ = $1; }
+ | sizeof { $$ = $1; }
+ | const '+' const { $$ = $1 + $3; }
+ | const '-' const { $$ = $1 - $3; }
+ | const '*' const { $$ = $1 * $3; }
+ | const '/' const { $$ = $1 / $3; }
+ | '(' const ')' { $$ = $2; }
+ ;
+
+sizeof : SIZEOF '(' type ')' { $$ = type_sizeof($3); }
+ ;
+
+/*
+ * A comma-separated list of C idents
+ * The hacks in here are for things like "int foo, bar[10];" and
+ * "char goop, **poot;"
+ */
+c_ident : IDENT { $$ = mkvar(NULL, $1); }
+ | '*' c_ident { $$ = mkvar(mkpointer($2->type), $2->name); }
+ | c_ident '[' const ']' { $$ = mkvar(mkcarray($1->type, $3), $1->name); }
+ | c_ident '[' ']' { $$ = mkvar(mkarray($1->type), $1->name); }
+ ;
+
+c_id_list: c_ident { $$ = $1; }
+ | c_id_list ',' c_ident { $$ = add($1, $3); }
+ ;
+
+/* Optional ident for C struct syntax */
+op_ident: /* */ { $$ = NULL; }
+ | IDENT { $$ = $1; }
+ ;
+
+/* Cope with C structure syntax */
+struct : STRUCT op_ident '{' varlist '}'
+ {
+ $$ = mkstruct($4);
+ if ($2 != NULL)
+ {
+ Var *v = mkvar($$, $2);
+ structures = add(structures, v);
+ }
+ }
+ | STRUCT IDENT
+ {
+ Var *v = lookup(structures, $2);
+
+ if (v != NULL)
+ $$ = v->type;
+ else
+ {
+ $$ = mkstruct(NULL);
+ $$->norep = 1;
+ }
+ }
+ ;
+
+/* Cruftyness to handle "long int" and "long double" */
+qual_type: TYPE TYPE
+ {
+ Type *t1 = realtype($1);
+ Type *t2 = realtype($2);
+ $$ = NULL;
+
+ if (t1 != long_type && t1 != short_type)
+ {
+ yyerror("Can only qualify with \"long\" or \"short\"");
+ YYERROR;
+ }
+ else if (t2->tclass != Scalar)
+ {
+ yyerror("Can only qualify scalar types");
+ YYERROR;
+ }
+ else
+ {
+ switch(t2->i.scalar_i.size)
+ {
+ case Float:
+ if (t1 == long_type)
+ {
+ $$ = double_type;
+ break;
+ }
+ case Long:
+ if (t1 == short_type)
+ {
+ $$ = short_type;
+ break;
+ }
+ if (t1 == long_type)
+ {
+ $$ = longlong_type;
+ break;
+ }
+
+ default: $$ = $2;
+ }
+ }
+ }
+ ;
+
+/* Cope with "unsigned int" */
+unsigned: UNSIGNED TYPE { $$ = $2; }
+ | UNSIGNED qual_type { $$ = $2; }
+ | UNSIGNED { $$ = Ulong_type; }
+ ;
+
+signed : SIGNED TYPE { $$ = $2; }
+ | SIGNED qual_type { $$ = $2; }
+ | SIGNED { $$ = long_type; }
+ ;
+
+/* Main rule for all types */
+type : TYPE { $$ = $1; }
+ | qual_type
+ | signed { $$ = $1; }
+ | unsigned
+ {
+ Type *t, *rt;
+
+ rt = realtype($1);
+ if (rt->tclass != Scalar)
+ {
+ yyerror("only scalars can be unsigned");
+ YYERROR;
+ t = $1;
+ }
+ else
+ {
+ switch(rt->i.scalar_i.size)
+ {
+ case Char: t = Uchar_type; break;
+ case Short: t = Ushort_type; break;
+ case Long: t = Ulong_type; break;
+ case LongLong: t = Ulonglong_type; break;
+ default:
+ yyerror("only integral types can be unsigned");
+ YYERROR;
+ break;
+ }
+ }
+ $$ = t;
+ }
+ | struct { $$ = $1; }
+ | VOID { $$ = NULL; }
+ ;
+
+/* Parse prototypes, without semantic action */
+
+/* Storage class for functions. We're an accepting lot */
+sclass : /* */
+ | sclass EXTERN
+ | sclass CONST
+ | sclass VOLATILE
+ | sclass STATIC
+ ;
+
+prototype: sclass type IDENT '(' comma_proto_list ')' ';'
+ ;
+
+/* Variables */
+vars : sclass type_name /* ';' -- type_name expects it */
+
+/* Optional constant */
+opconst: /* */
+ | CONST
+ ;
+
+/* A prototype argument */
+proto : opconst type
+ | opconst type IDENT
+ | ELLIPSIS
+ ;
+
+/* A list of parameters */
+comma_proto_list: /* */
+ | proto
+ | comma_proto_list ',' proto
+ ;
+%%
+
+static Type *set_type(Type *tt, Type *to)
+{
+ if (tt == NULL)
+ return to;
+
+ switch(tt->tclass)
+ {
+ case Array:
+ tt->i.array_i = set_type(tt->i.array_i, to);
+ break;
+
+ case CArray:
+ tt->i.carray_i.type = set_type(tt->i.carray_i.type, to);
+ break;
+
+ case Pointer:
+ tt->i.pointer_i = set_type(tt->i.pointer_i, to);
+ break;
+
+ default:
+ abort();
+ }
+
+ return tt;
+}
Added: trunk/genser/com.h
==============================================================================
--- trunk/genser/com.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/genser/com.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,12 @@
+/* Common headers and defns */
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <assert.h>
+
+#ifdef __cplusplus
+#define EXTERNC extern "C"
+#endif
Added: trunk/genser/symtab.h
==============================================================================
--- trunk/genser/symtab.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/genser/symtab.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,111 @@
+/*
+ * Symbol table structures
+ */
+
+typedef struct var_t Var;
+typedef struct type_t Type;
+
+enum typeclass
+{
+ Struct,
+ Typedef,
+ Scalar,
+ Array,
+ CArray,
+ Pointer,
+ Void
+};
+
+enum sc_size
+{
+ NoType = -1,
+ Char,
+ Short,
+ Long,
+ LongLong,
+ Float,
+ Double
+};
+
+struct type_t
+{
+ enum typeclass tclass;
+ union
+ {
+ Var *struct_i;
+ struct
+ {
+ Type *t;
+ char *n;
+ } typedef_i;
+ struct
+ {
+ enum sc_size size;
+ int Unsigned;
+ } scalar_i;
+ Type *array_i;
+ Type *pointer_i;
+ struct
+ {
+ Type *type;
+ unsigned size;
+ } carray_i;
+ } i;
+ Type *name; /* Pointer to nameing typedef */
+ unsigned anon:1; /* Had no defined name */
+ unsigned nocode:1; /* No code to be generated */
+ unsigned nohdr:1; /* No header generated */
+ unsigned demand:1; /* Generate code as needed */
+ unsigned norep:1; /* No serial representation */
+ unsigned indir:1; /* Use a level of indirection */
+ unsigned coded:3; /* En/Decode func generated */
+};
+
+struct var_t
+{
+ char *name;
+ Type *type;
+ Var *next;
+ Var *prev;
+};
+
+extern Var *global; /* Global symbol table */
+extern Var *structures; /* Global structure table */
+
+void init_symtab(void);
+
+int type_sizeof(const Type *);
+
+Var *lookup(Var *, const char *);
+Var *add(Var *, Var *);
+Var *addl(Var *, Var *);
+Var *preadd(Var *, Var *);
+
+Type *mktype(void);
+Type *mkstruct(Var *);
+Type *mkpointer(Type *);
+Type *mkarray(Type *);
+Type *mkcarray(Type *, unsigned int);
+Type *mkscalar(enum sc_size, int);
+Type *mkvoid(void);
+
+Var *mkvar(Type *, char *);
+Var *mktypedef(Type *, char *);
+Var *mkincl(const char *);
+
+Var *name_types(Var *);
+
+Type *realtype(Type *);
+
+/* Standard types */
+extern Type *Ulonglong_type;
+extern Type *Ulong_type;
+extern Type *Ushort_type;
+extern Type *Uchar_type;
+extern Type *longlong_type;
+extern Type *long_type;
+extern Type *short_type;
+extern Type *char_type;
+extern Type *void_type;
+extern Type *float_type;
+extern Type *double_type;
Added: trunk/genser/gencode.c
==============================================================================
--- trunk/genser/gencode.c 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/genser/gencode.c 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,591 @@
+#include <errno.h>
+#include "com.h"
+#include "symtab.h"
+#include "format.h"
+#include "misc.h"
+#include <getopt.h>
+
+extern int yyparse();
+
+char *prefix = "";
+
+int copythrough = 0;
+
+static int do_oneperfile = 0;
+static int do_cplusplus = 0;
+static const char *filedir = NULL;
+static const char *srcext = ".c";
+
+static void file_preamble(void)
+{
+ format("/* -*- %s -*-\n * DO NOT EDIT BY HAND!\n *\n",
+ do_cplusplus ? "C++" : "C");
+ format(" * This was automatically generated by gencode.\n */\n");
+ if (do_cplusplus)
+ {
+ format("#ifdef __cplusplus\n");
+ format("#if __GNUC__ == 2\n");
+ format("#pragma implementation \"%s\"\n", prefix);
+ format("#endif /* __GNUC__ */\n");
+ format("#endif /* __cplusplus */\n");
+ }
+ format("#include \"%s.h\"\n", prefix);
+}
+
+static void preamble(Type *type, const char *op, int co, const char *name)
+{
+ if (do_oneperfile)
+ {
+ char buf[256];
+
+ sprintf(buf, "%s_%s%s", op, name, srcext);
+
+ if ((form_out = fopen(buf, "w")) == NULL)
+ {
+ fprintf(stderr, "Failed to create %s: %s\n",
+ buf, strerror(errno));
+ exit(1);
+ }
+ file_preamble();
+ }
+
+ format("\n");
+#if 0
+ if (!do_oneperfile && (type->anon || type->demand))
+ format("__inline__ static ");
+#endif
+ format("\nunsigned char *%s_%s(%s%s *sp, unsigned char *buf)\n{\n",
+ op, name, co ? "const " : "", name);
+}
+
+static void postamble()
+{
+ format("return buf;\n}\n");
+
+ if (do_oneperfile)
+ fclose(form_out);
+}
+
+#define NAMEOF(t) ((t)->name->i.typedef_i.n)
+
+void encode_type(Type *type, const char *typename)
+{
+ Var *var;
+
+ assert(type != NULL);
+
+ if (type->nocode || type->coded == 1)
+ return;
+
+ type->coded = 1;
+
+ switch(type->tclass)
+ {
+ Type *tt;
+
+#define PRE() preamble(type, "encode", 1, typename)
+#define POST() postamble()
+
+ case Typedef:
+ tt = realtype(type);
+ encode_type(tt, NAMEOF(tt));
+ PRE();
+ format("buf = encode_%s(sp, buf);\n", NAMEOF(tt));
+ POST();
+ break;
+
+ case Scalar:
+ PRE();
+ format("buf = encode_%s(sp, buf);\n", NAMEOF(type));
+ POST();
+ break;
+
+ case Array:
+ if (type->norep)
+ {
+ PRE();
+ format("/* No representation */\n");
+ POST();
+ break;
+ }
+ tt = realtype(type->i.array_i);
+
+ encode_type(tt, NAMEOF(tt));
+ PRE();
+ format("{\nunsigned i;\n\n");
+ format("buf = encode_Ulong(&sp->nelem, buf);\n");
+ format("for(i = 0; i < sp->nelem; i++) {\n");
+ format("buf = encode_%s(&sp->elems[i], buf);\n",
+ NAMEOF(tt));
+ format("}\n}\n");
+ POST();
+ break;
+
+ case CArray:
+ tt = realtype(type->i.carray_i.type);
+ encode_type(tt, NAMEOF(tt));
+ PRE();
+ format("{\nunsigned i;\n\n");
+ format("for(i = 0; i < %d; i++) {\n", type->i.carray_i.size);
+ format("buf = encode_%s(&(*sp)[i], buf);\n",
+ NAMEOF(tt));
+ format("}\n}\n");
+ POST();
+ break;
+
+ case Struct:
+ for(var = type->i.struct_i; var != NULL; var = var->next)
+ {
+ tt = realtype(var->type);
+ encode_type(tt, NAMEOF(tt));
+ }
+
+ PRE();
+ for(var = type->i.struct_i; var != NULL; var = var->next)
+ {
+ if (var->type->norep)
+ {
+ format("/* Unrepresentable type */\n");
+ continue;
+ }
+
+ tt = realtype(var->type);
+
+ format("buf = encode_%s(&sp->%s, buf);\n",
+ NAMEOF(tt), var->name);
+ }
+ POST();
+ break;
+
+ case Pointer:
+ tt = realtype(type->i.pointer_i);
+ encode_type(tt, NAMEOF(tt));
+ PRE();
+ format("buf = encode_%s(*sp, buf);\n",
+ NAMEOF(tt));
+ POST();
+ break;
+
+ default:
+ printf("#error \"undealt-with type %d\"\n", type->tclass);
+ break;
+#undef PRE
+#undef POST
+ }
+}
+
+void decode_type(Type *type, const char *typename)
+{
+ Var *var;
+
+ assert(type != NULL);
+
+ if (type->nocode || type->coded == 2)
+ return;
+
+ type->coded = 2;
+
+ switch(type->tclass)
+ {
+ Type *tt;
+
+#define PRE() preamble(type, "decode", 0, typename)
+#define POST() postamble()
+
+ case Typedef:
+ tt = realtype(type);
+ decode_type(tt, NAMEOF(tt));
+ PRE();
+ format("buf = decode_%s(sp, buf);\n",
+ NAMEOF(tt));
+ POST();
+ break;
+
+ case Scalar:
+ PRE();
+ format("buf = decode_%s(sp, buf);\n", NAMEOF(type));
+ POST();
+ break;
+
+ case Array:
+ if (type->norep)
+ {
+ PRE();
+ format("/* No representation */\n");
+ POST();
+ break;
+ }
+
+ tt = realtype(type->i.array_i);
+ decode_type(tt, NAMEOF(tt));
+ PRE();
+ format("{\nunsigned i;\n");
+ format("buf = decode_Ulong(&sp->nelem, buf);\n");
+ format("if (sp->nelem == 0)\n");
+ format("{\nsp->elems = 0;\nreturn buf;\n}\n");
+ if (do_cplusplus)
+ {
+ format("#ifdef __cplusplus\n");
+ format("sp->alloc(sp->nelem);\n");
+ format("#else\n");
+ }
+ format("sp->elems = (%s *)ALLOC(sizeof(%s) * sp->nelem);\n",
+ NAMEOF(tt), NAMEOF(tt));
+ if (do_cplusplus)
+ format("#endif /* __cplusplus */\n");
+ format("if (sp->elems == 0) {\nreturn buf;\n}\n");
+
+ format("for(i = 0; i < sp->nelem; i++) {\n");
+ format("buf = decode_%s(&sp->elems[i], buf);\n",
+ NAMEOF(tt));
+ format("}\n}\n");
+ POST();
+ break;
+
+ case CArray:
+ tt = realtype(type->i.carray_i.type);
+ decode_type(tt, NAMEOF(tt));
+ PRE();
+ format("{\nunsigned i;\n\n");
+ format("for(i = 0; i < %d; i++) {\n", type->i.carray_i.size);
+ format("buf = decode_%s(sp[i], buf);\n",
+ NAMEOF(tt));
+ format("}\n}\n");
+ POST();
+ break;
+
+ case Struct:
+ for(var = type->i.struct_i; var != NULL; var = var->next)
+ {
+ tt = realtype(var->type);
+ decode_type(tt, NAMEOF(tt));
+ }
+ PRE();
+ for(var = type->i.struct_i; var != NULL; var = var->next)
+ {
+ if (var->type->norep)
+ {
+ format("/* Unrepresentable type */\n");
+ continue;
+ }
+ tt = realtype(var->type);
+ format("buf = decode_%s(&sp->%s, buf);\n",
+ NAMEOF(tt), var->name);
+ }
+ POST();
+ break;
+
+ case Pointer:
+ tt = realtype(type->i.pointer_i);
+ decode_type(tt, NAMEOF(tt));
+ PRE();
+ format("*sp = (%s *)ALLOC(sizeof(%s));\n",
+ NAMEOF(tt), NAMEOF(tt));
+ format("if (*sp == NULL) {\nreturn buf;\n}\n");
+ format("buf = decode_%s(*sp, buf);\n",
+ NAMEOF(tt));
+ POST();
+ break;
+
+#undef PRE
+#undef POST
+ default:
+ printf("#error \"undealt-with type %d\"\n", type->tclass);
+ break;
+ }
+}
+
+static void s_preamble(const Type *type, const char *name)
+{
+ if (do_oneperfile)
+ {
+ char buf[256];
+
+ sprintf(buf, "sizeof_%s%s", name, srcext);
+
+ if ((form_out = fopen(buf, "w")) == NULL)
+ {
+ fprintf(stderr, "Failed to create %s: %s\n",
+ buf, strerror(errno));
+ exit(1);
+ }
+ file_preamble();
+ }
+#if 0
+ if (!do_oneperfile && (type->nocode || type->anon || type->demand))
+ format("static __inline__ ");
+#endif
+ format("unsigned int sizeof_%s(const %s *sp)\n{\n", name, name);
+ format("unsigned int sz=0;\n\n");
+}
+
+static void s_postamble(void)
+{
+ format("return sz;\n}\n");
+
+ if (do_oneperfile)
+ fclose(form_out);
+}
+
+void sizeof_type(Type *type, const char *typename)
+{
+ Var *var;
+
+ assert(type != NULL);
+
+ if (type->nocode || type->coded == 3)
+ return;
+
+ type->coded = 3;
+
+ switch(type->tclass)
+ {
+ Type *tt;
+
+#define PRE() s_preamble(type, typename)
+#define POST() s_postamble()
+
+ case Typedef:
+ tt = realtype(type);
+ sizeof_type(tt, NAMEOF(tt));
+ PRE();
+ format("sz += sizeof_%s(sp);\n",
+ NAMEOF(tt));
+ POST();
+ break;
+
+ case Scalar:
+ PRE();
+ format("sz += sizeof(%s);\n",
+ NAMEOF(type));
+ POST();
+ break;
+
+ case Array:
+ if (type->norep)
+ {
+ PRE();
+ format("/* No representation */\n");
+ POST();
+ break;
+ }
+ tt = realtype(type->i.array_i);
+
+ sizeof_type(tt, NAMEOF(tt));
+ PRE();
+ format("sz += sizeof_Ulong(&sp->nelem);\n");
+ format("{\nunsigned i;\n");
+ format("for(i = 0; i < sp->nelem; i++) {\n");
+ format("sz += sizeof_%s(&sp->elems[i]);\n", NAMEOF(tt));
+ format("}\n}\n");
+ POST();
+ break;
+
+ case CArray:
+ tt = realtype(type->i.carray_i.type);
+ sizeof_type(tt, NAMEOF(tt));
+ PRE();
+ format("{\nunsigned i;\n");
+ format("for(i = 0; i < %d; i++) {\n",
+ type->i.carray_i.size);
+ format("sz += sizeof_%s(sp[i]);\n}\n}\n", NAMEOF(tt));
+ POST();
+ break;
+
+ case Struct:
+ for(var = type->i.struct_i; var != NULL; var = var->next)
+ {
+ tt = realtype(var->type);
+ sizeof_type(tt, NAMEOF(tt));
+ }
+
+ PRE();
+ for(var = type->i.struct_i; var != NULL; var = var->next)
+ {
+ if (var->type->norep)
+ {
+ format("/* Unrepresentable type */\n");
+ continue;
+ }
+ tt = realtype(var->type);
+ format("sz += sizeof_%s(&sp->%s);\n",
+ NAMEOF(tt),
+ var->name);
+ }
+ POST();
+ break;
+
+ case Pointer:
+ tt = realtype(type->i.pointer_i);
+ sizeof_type(tt, NAMEOF(tt));
+ PRE();
+ format("sz += sizeof_%s(*sp);\n",
+ NAMEOF(tt));
+ POST();
+ break;
+
+ case Void:
+ PRE();
+ POST();
+ break;
+
+ default:
+ printf("#error \"undealt-with type %d\"\n", type->tclass);
+ break;
+#undef PRE
+ }
+}
+
+
+typedef void (*Genfunc)(Type *, const char *);
+
+static void gen_code(Var *table, Genfunc func)
+{
+ for(; table != NULL; table = table->next)
+ {
+ Type *type;
+
+ type = table->type;
+
+ assert(table->type->tclass == Typedef);
+
+ if (type->demand)
+ continue;
+
+ (*func)(type->i.typedef_i.t, type->i.typedef_i.n);
+ }
+}
+
+extern FILE *yyin;
+char *file;
+
+extern int yydebug;
+
+int
+main(int argc, char *argv[])
+{
+ char *cp;
+ int och, err = 0;
+ int do_encode = 0, do_decode = 0, do_sizeof = 0;
+ char buf[1024];
+ struct cmdarg *cppargs = NULL;
+
+ form_out = stdout;
+ cppargs = add_cmdarg(cppargs, CPP);
+
+ while((och = getopt(argc, argv, "sedCD:I:U:l:E:Y")) != EOF)
+ {
+ switch(och)
+ {
+ case 'D':
+ case 'I':
+ case 'U':
+ sprintf(buf, "-%c%s", och, optarg);
+ cppargs = add_cmdarg(cppargs, buf);
+ break;
+
+ case 'd':
+ do_decode = 1;
+ break;
+
+ case 'e':
+ do_encode = 1;
+ break;
+
+ case 's':
+ do_sizeof = 1;
+ break;
+
+ case 'l':
+ filedir = optarg;
+ do_oneperfile = 1;
+ break;
+
+ case 'E':
+ srcext = optarg;
+ break;
+
+ case 'C':
+ do_cplusplus = 1;
+ srcext = ".cc";
+ break;
+
+ case 'Y':
+ yydebug = 1;
+ break;
+
+ default:
+ err++;
+ break;
+ }
+ }
+
+ if (err || optind >= argc)
+ {
+ fprintf(stderr, "Usage: %s [-des] [-l dir] [-E ext] [cpp-opts] types-file\n",
+ argv[0]);
+ fprintf(stderr, "\t-d\tGenerate decode functions\n");
+ fprintf(stderr, "\t-e\tGenerate encode functions\n");
+ fprintf(stderr, "\t-s\tGenerate sizeof functions\n");
+ fprintf(stderr, "\t-l dir\tGenerate one function per file in directory `dir'\n");
+ fprintf(stderr, "\t-E ext\tUse extention `ext' on files (-l only)\n");
+ fprintf(stderr, "\tcpp-opts\tPass -I, -D and -U options to cpp\n");
+ exit(1);
+ }
+
+ if (!(do_encode || do_decode || do_sizeof))
+ fprintf(stderr, "Warning: no functions will be generated\n");
+
+ file = strdup(argv[optind]);
+
+ cppargs = add_cmdarg(cppargs, file);
+
+ if ((yyin = popen(cat_args(cppargs), "r")) == NULL)
+ {
+ perror("file open failed");
+ exit(1);
+ }
+
+ if ((cp = strrchr(argv[optind], '/')) == NULL)
+ cp = argv[optind];
+ else
+ cp++;
+
+ prefix = strdup(cp);
+ cp = strrchr(prefix, '.');
+ if (cp)
+ *cp = 0;
+
+ init_symtab();
+
+ if (yyparse())
+ {
+ fprintf(stderr, "Bad input file\n");
+ exit(1);
+
+ }
+
+ global = name_types(global);
+
+ if (!do_oneperfile)
+ file_preamble();
+ else
+ {
+ if (chdir(filedir) == -1)
+ {
+ perror("Couldn't change to output directory");
+ exit(1);
+ }
+ }
+
+ if (do_encode)
+ gen_code(global, encode_type);
+
+ if (do_decode)
+ gen_code(global, decode_type);
+
+ if (do_sizeof)
+ gen_code(global, sizeof_type);
+
+ exit(0);
+}
Added: trunk/genser/genhdr.c
==============================================================================
--- trunk/genser/genhdr.c 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/genser/genhdr.c 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,270 @@
+#include "com.h"
+#include "symtab.h"
+#include "format.h"
+#include "misc.h"
+#include <getopt.h>
+#include <ctype.h>
+
+extern int yyparse();
+
+int copythrough = 1;
+
+static int do_cplusplus = 0;
+
+char *prefix;
+
+static inline Type *symb(Type *t)
+{
+ if (t->name != NULL)
+ return t->name;
+ assert(t->tclass == Typedef);
+ return t;
+}
+
+void dumptype(Type *type, const char *name)
+{
+ char *str;
+ Var *var;
+ int ret = 1;
+
+ assert(type != NULL);
+
+ switch(type->tclass)
+ {
+ case Typedef:
+ format(type->i.typedef_i.n);
+ break;
+
+ case Scalar:
+ if (type->i.scalar_i.Unsigned)
+ format("unsigned ");
+ switch(type->i.scalar_i.size)
+ {
+ case Char: str = "char"; break;
+ case Short: str = "short"; break;
+ case Long: str = "long"; break;
+ case LongLong: str = "long long"; break;
+ case Float: str = "float"; break;
+ case Double: str = "double"; break;
+ default: str = "???"; break;
+ }
+
+ format(str);
+ break;
+
+ case Array:
+ if (do_cplusplus)
+ {
+ static int scount = 1;
+ char n[128];
+
+ sprintf(n, "_%s_S%03d", prefix, scount++);
+
+ format("struct %s {\n", n);
+ format("Ulong nelem;\n");
+ dumptype(mkpointer(type->i.array_i), "elems");
+ format(";\n");
+ format("#ifdef __cplusplus\n");
+ format("int alloced;\n");
+ format("void %s::alloc(unsigned size)\t{elems = new ", n);
+ dumptype(symb(type->i.array_i),"");
+ format("[size]; alloced = 1; }\n");
+ format("%s::%s()\t{ alloced = 0; }\n", n, n);
+ format("%s::~%s()\t{\n", n, n);
+ format("if (alloced) {\n");
+ format("delete [] elems; alloced = 0;\n}\n}\n");
+ format("#endif /* __cplusplus */\n}");
+ }
+ else
+ {
+ format("struct\n{\n");
+ format("Ulong nelem;\n");
+ dumptype(mkpointer(type->i.array_i), "elems");
+ format(";\n}");
+ }
+ break;
+
+ case CArray:
+ dumptype(symb(type->i.carray_i.type), name);
+ format("[%d]", type->i.carray_i.size);
+ ret = 0;
+ break;
+
+ case Struct:
+ format("struct\n{\n");
+ for(var = type->i.struct_i; var != NULL; var = var->next)
+ {
+ if (var->type->norep)
+ {
+ format("/* No representation */\n");
+ continue;
+ }
+ dumptype(symb(var->type), var->name);
+ format(";\n");
+ }
+ format("}");
+ break;
+
+ case Pointer:
+ dumptype(symb(type->i.pointer_i), NULL);
+ format("*");
+ break;
+
+ default:
+ printf("undealt-with type %d", type->tclass);
+ break;
+ }
+ if (name != NULL && ret)
+ format(" %s", name);
+}
+
+void gen_hdr(Var *table)
+{
+ format("/* Encoded types */\n\n");
+ for(; table != NULL; table = table->next)
+ {
+ Type *type = table->type;
+
+ assert(type->tclass == Typedef);
+
+ if (type->nohdr)
+ continue;
+
+ format("typedef ");
+ dumptype(type->i.typedef_i.t, table->name);
+ format(";\n");
+ }
+}
+
+void gen_proto(Var *table)
+{
+ for(; table != NULL; table = table->next)
+ {
+ Type *type;
+ const char *name = table->name;
+ const char *st = table->type->nocode ? "static " : "";
+
+ assert(table->type->tclass == Typedef);
+
+ type = table->type->i.typedef_i.t;
+
+ format("%sunsigned char *encode_%s(const %s *, unsigned char *);\n",
+ st, name, name);
+ format("%sunsigned char *decode_%s(%s *, unsigned char *);\n",
+ st, name, name);
+ format("%sunsigned int sizeof_%s(const %s *);\n\n",
+ st, name, name);
+
+ }
+}
+
+extern FILE *yyin;
+char *file;
+
+extern int yydebug;
+
+int
+main(int argc, char *argv[])
+{
+ char *upname, *cp;
+ int c, err = 0;
+ char buf[1024];
+ struct cmdarg *cppargs = NULL;
+
+ form_out = stdout;
+ cppargs = add_cmdarg(cppargs, CPP);
+
+ while((c = getopt(argc, argv, "U:I:D:YC")) != EOF)
+ switch(c)
+ {
+ case 'D':
+ case 'I':
+ case 'U':
+ sprintf(buf, "-%c%s", c, optarg);
+ cppargs = add_cmdarg(cppargs, buf);
+ break;
+
+ case 'Y':
+ yydebug = 1;
+ break;
+
+ case 'C':
+ do_cplusplus = 1;
+ break;
+
+ default:
+ err++;
+ break;
+ }
+
+ if (err || optind >= argc)
+ {
+ fprintf(stderr, "Usage: %s [-C] [cpp-opts...] typedef-file\n", argv[0]);
+ fprintf(stderr, "\t-C\tGenerate C++ classes rather than C\n");
+ fprintf(stderr, "\tcpp-opts\tPass -I, -D and -U options to cpp\n");
+ exit(1);
+ }
+
+ file = strdup(argv[optind]);
+
+ cppargs = add_cmdarg(cppargs, file);
+
+ if ((yyin = popen(cat_args(cppargs), "r")) == NULL)
+ {
+ perror("file open failed");
+ exit(1);
+ }
+
+ if ((cp = strrchr(file, '/')) == NULL)
+ cp = file;
+ else
+ cp++;
+
+ prefix = strdup(cp);
+ cp = strrchr(prefix, '.');
+ if (cp)
+ *cp = 0;
+
+ init_symtab();
+
+ upname = cp = strdup(prefix);
+
+ for(; *cp; cp++)
+ if (islower(*cp))
+ *cp = toupper(*cp);
+
+ format("/* -*- %s -*-\n * DO NOT EDIT BY HAND!\n *\n",
+ do_cplusplus ? "C++" : "C");
+ format(" * This was automatically generated from \"%s\"",
+ argv[optind]);
+ format(" by genhdr.\n */\n");
+ format("#ifndef __%s_H_SEEN__\n", upname);
+ format("#define __%s_H_SEEN__\n\n", upname);
+
+ if (do_cplusplus)
+ {
+ format("#ifdef __cplusplus\n");
+ format("#if __GNUC__ == 2\n");
+ format("#pragma interface \"%s\"\n", prefix);
+ format("#endif /* __GNUC__ */\n");
+ format("#endif /* __cplusplus */\n");
+ }
+ if (yyparse())
+ {
+ fprintf(stderr, "Bad input file\n");
+ exit(1);
+ }
+
+ format("#ifndef _NO_CODER_H_\n");
+ format("/* Type encode/decode routines */\n");
+ format("#include \"coder.h\"\t/* Standard routines */\n");
+ format("#endif /* _NO_CODER_H_ */\n");
+ global = name_types(global);
+
+ gen_hdr(global);
+ gen_proto(global);
+
+ format("#endif /* __%s_H_SEEN__ */\n", upname);
+
+ exit(0);
+}
Added: trunk/genser/format.c
==============================================================================
--- trunk/genser/format.c 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/genser/format.c 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,87 @@
+/* C output formatting */
+#include "com.h"
+#include "format.h"
+#include <stdarg.h>
+
+static int lvl;
+static int lastnl = 0;
+static int col;
+
+FILE *form_out;
+
+static void out_ch(char ch)
+{
+ if (ch == '\n')
+ {
+ fputc(ch, form_out);
+ col = 0;
+ lastnl = 1;
+ return;
+ }
+
+ if (lastnl && ch != '#')
+ {
+ int cnt;
+
+ col += lvl * 4;
+ for(cnt = 0; cnt < lvl; cnt++)
+ fputs(" ", form_out);
+ }
+ lastnl = 0;
+
+ col++;
+ fputc(ch, form_out);
+
+#if 0
+ if (col >= 65 && (ch == ';' || ch == ','))
+ out_ch('\n');
+#endif
+}
+
+static void out_str(const char *str)
+{
+ for(; *str; str++)
+ out_ch(*str);
+}
+
+static void out_num(int n)
+{
+ char buf[20];
+
+ sprintf(buf, "%d", n);
+ out_str(buf);
+}
+
+void format(const char *str, ...)
+{
+ va_list va;
+
+ va_start(va, str);
+
+ for(; *str; str++)
+ {
+ switch(*str)
+ {
+ case '(':
+ case '{': out_ch(*str); lvl++; break;
+
+ case ')':
+ case '}': lvl--; out_ch(*str); break;
+
+ case '%':
+ switch(*++str)
+ {
+ case 's': out_str(va_arg(va, char *)); break;
+ case 'd': out_num(va_arg(va, int)); break;
+ default:
+ out_ch('%');
+ out_ch(*str);
+ break;
+ }
+ break;
+
+ default:
+ out_ch(*str);
+ }
+ }
+}
Added: trunk/genser/lexer.l
==============================================================================
--- trunk/genser/lexer.l 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/genser/lexer.l 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,99 @@
+/* -*- fundamental -*- */
+%{
+#include "com.h"
+#include "symtab.h"
+#include "y.tab.h"
+
+extern char *file;
+extern int copythrough;
+static int line = 1;
+static char strbuf[1024];
+static char *strptr;
+%}
+
+%x comment
+%x string
+
+%%
+struct return STRUCT;
+typedef return TYPEDEF;
+unsigned return UNSIGNED;
+(__)?signed(__)? return SIGNED;
+notypedef return NOTHDR;
+generate return GENERATE;
+sizeof return SIZEOF;
+
+ /* Purely C keywords */
+static return STATIC;
+void return VOID;
+extern return EXTERN;
+(__)?const return CONST;
+(__)?volatile return VOLATILE;
+"..." return ELLIPSIS;
+
+[_a-zA-Z][_a-zA-Z0-9]* {
+ Var *v = lookup(global, yytext);
+ if (v != NULL && v->type->tclass == Typedef)
+ {
+ Type *t = v->type;
+ if (t->indir == 1)
+ t = t->i.typedef_i.t;
+
+ yylval.type = t;
+ return TYPE;
+ }
+ yylval.name = strdup(yytext);
+ return IDENT;
+ }
+[0-9]+ { yylval.num = atoi(yytext); return NUM; }
+[+-/{}[\]*;,()] return *yytext;
+"/*" BEGIN(comment);
+^#\ [0-9]+\ \"[a-zA-Z_.0-9/]+\".*$ {
+ char *cp;
+
+ line = strtol(&yytext[2], &cp, 10);
+ free(file);
+ file = cp+2;
+ for(cp = file; *cp && *cp != '"'; cp++)
+ ;
+ *cp = 0;
+ file = strdup(file);
+ }
+\" strptr = strbuf; BEGIN(string);
+^#.*$ ;
+[ \t] ;
+\n line++;
+^"%".* if (copythrough) { fputs(&yytext[1], stdout); fputc('\n', stdout); }
+. fprintf(stderr, "Uncaught char '%c'\n", *yytext);
+
+<comment>[^*\n]+ /* eat up anything up to '*' */
+<comment>"*"+[^*/\n]* /* eat up rows of '*' not followed by '/' */
+<comment>\n line++;
+<comment>"*"+"/" BEGIN(INITIAL);
+
+<string>\\. *strptr++ = yytext[1];
+<string>\" *strptr=0; yylval.name = strdup(strbuf); BEGIN(INITIAL); return STRING;
+<string>[^\\\"]+ {char *cp = yytext; while(*cp) *strptr++ = *cp++; }
+
+%%
+
+#include <stdio.h>
+#include <stdarg.h>
+
+void
+yyerror(const char *msg, ...)
+{
+ va_list va;
+
+ fprintf(stderr, "%s:%d:", file, line, msg);
+
+ va_start(va, msg);
+ vfprintf(stderr, msg, va);
+ va_end(va);
+ fputc('\n', stderr);
+}
+
+int yywrap(void)
+{
+ return 1;
+}
Added: trunk/genser/misc.c
==============================================================================
--- trunk/genser/misc.c 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/genser/misc.c 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,45 @@
+/*
+ * Misc functions, for command execution and so on
+ */
+#include <stdlib.h>
+#include <string.h>
+#include "misc.h"
+
+struct cmdarg *add_cmdarg(struct cmdarg *l, const char *str)
+{
+ struct cmdarg *lp, *new;
+
+ new = malloc(sizeof(*new));
+ new->n = NULL;
+ new->str = strdup(str);
+
+ if (l == NULL)
+ return new;
+
+ for(lp = l; lp->n != NULL; lp = lp->n)
+ ;
+ lp->n = new;
+
+ return l;
+}
+
+char *cat_args(struct cmdarg *l)
+{
+ int len;
+ struct cmdarg *lp;
+ char *str, *cp;
+
+ for(len = 0, lp = l; lp != NULL; len += strlen(l->str)+1, lp = lp->n)
+ ;
+
+ str = malloc(len);
+
+ for(cp = str, lp = l; lp != NULL; lp = lp->n, *cp++ = ' ')
+ {
+ strcpy(cp, lp->str);
+ cp += strlen(lp->str);
+ }
+
+ cp[-1] = 0;
+ return str;
+}
Added: trunk/genser/README
==============================================================================
--- trunk/genser/README 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/genser/README 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,113 @@
+genser - generate serialising code
+
+This is a pair of programs which generate code to serialise and
+deserialise data structures, given a description of them. I wrote
+them for the protocol used by userfs, but they are quite general. One
+program generates code for encoding, decoding and finding the size of
+the encoded representation, and the other generates prototypes for
+them, and emits the types in ansi C.
+
+GENHDR
+
+Usage: genhdr [-C] input.ty
+
+This emits all the datatypes and function prototypes in ansi C to
+standard output. If -C is specified then array structures are
+generated with destructors which free memory allocated by decoding.
+
+GENCODE
+
+Usage: gencode [-sedC] [-l dir] [-s suff] input.ty [> output.c]
+
+Gencode generates C code for the encode/decode/sizeof functions
+(generated with the -e, -d, and -s options respectively). -l dir will
+generate one function per file into directory "dir" for the generation
+of archive libraries so that programs don't have to link everything
+in. -s sets the suffix of the output files (.c by default). -C
+generates code to work with the destuctors generated with genhdr -C,
+and sets the suffix to .cc when used with -l.
+
+INPUT FILE FORMAT
+
+The input file is essentially C type definitions, with a few
+exceptions. By default, code is generated for any type named with
+typedef, and any anonymous type used in a typedef.
+
+Arrays are defined as follows:
+
+ typedef int foo[];
+
+This defines a type "foo", which is an unbounded array of ints (signed
+32 bit words). This generates a structure of the form:
+
+ struct {
+ int *elems;
+ long nelem;
+ };
+
+which is a pointer to the base of the array, and the number of
+elements.
+
+This, and the complete exclusion of functions from the type system,
+are the main differences from pure C syntax. A number of parsing
+hacks have been put in place so that C syntax can be parsed without
+semantic content for genser.
+
+Structures may be named with the "struct foo {...};" syntax, but they
+are ignored until they are used in a named type.
+
+Often you want to include a system include file for a couple of types,
+but it defines dozens. Typedefs can be marked as "generate on demand"
+(when used in other types) by enclosing them in a notypedef block:
+
+notypedef {
+#include <sys/types.h>
+}
+
+This will only generate code and definitions for the types in
+<sys/types.h> if another type uses them.
+
+The input file is run through cpp ("/lib/cpp -Ulinux -C").
+
+It is possible to quote parts of the input file directly into the
+output file, by putting '%' at the beginning of the line. These lines
+are completely uninterpreted and are copied through with the '%'
+stripped off. The order in the output of these lines is maintained,
+but the order in relation to genser output corresponding to input
+surrounding the quoted lines is not specified, but generally they will
+be before any generated output. Quoted lines are not copies through
+by gencode, only genhdr, so they are only in the header lines.
+
+%/* Copy into output file */
+%#include <sys/types.h>
+
+When decoding arrays of variable size and pointers to objects, the
+decode routine calls a function or macro void *ALLOC(size_t size) to
+allocate memory. It expects this function will always return a valid
+pointer to free memory. By default, it is defined as malloc(), but it
+can be redefined in the quoted section to something appropriate to
+local conditions. The memory allocated in the decode function must be
+manually freed when you've finished. If one generates C++ code (-C
+option to gen(code|hdr)) then destructors which call FREE() are
+generated for arrays. They will only attempt to free memory if it was
+allocated by a decode function.
+
+coder.h is a file that must always be included. It contains the
+definitions of the encode/decode/sizeof functions for the base types
+used by genser. It is normally included as "coder.h", but if one
+defines _NO_CODER_H_ in the output file (with a quoted define), it
+will not be automatically included. One can then include it in a more
+appropriate way, or replace it altogether.
+
+There are no known actual *bugs*, but there are a few limitations and
+desireable features. Most importantly, C++ support could be much
+better. Each type could be a class with encode/decode/sizeof methods,
+and memory can be allocated with new and delete if required. Also it
+should have a better grasp of C so it will always be able to parse
+Linux header files.
+
+Also, this readme file could be turned into a real man page or texinfo
+page.
+
+Bug reports and comments to
+ Jeremy Fitzhardinge <jeremy at sw.oz.au>
Added: trunk/genser/Makefile
==============================================================================
--- trunk/genser/Makefile 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/genser/Makefile 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,51 @@
+#
+# Makefile for genser
+#
+LEX=flex -s
+YACC=bison -yvt
+TOP=..
+include $(TOP)/rules
+
+CFLAGS = $(CPP)
+CPP='-DCPP="/lib/cpp -Ulinux -C"'
+LDFLAGS=-s
+LIBS= #-lfl
+
+ALLSRC=gencode.c genhdr.c $(SRC)
+ALLOBJ=$(ALLSRC:%.c=%.o)
+
+SRC=symtab.c lex.yy.c y.tab.c format.c misc.c
+HDR=symtab.h y.tab.h
+OBJ=$(SRC:%.c=%.o)
+
+.SUFFIXES: .ty
+
+.ty.c: gencode
+ gencode -dse $< > $@
+
+.ty.h: genhdr
+ genhdr $< > $@
+
+all:: genhdr gencode
+
+genhdr: genhdr.o $(OBJ)
+ $(CC) $(LDFLAGS) -o $@ genhdr.o $(OBJ) $(LIBS)
+
+gencode: gencode.o $(OBJ)
+ $(CC) $(LDFLAGS) -o $@ gencode.o $(OBJ) $(LIBS)
+
+lex.yy.c: lexer.l y.tab.h
+ $(LEX) $<
+
+lex.yy.o: lex.yy.c y.tab.h
+ $(CC) $(XCFLAGS) $(CFLAGS) -w -c $<
+
+y.tab.c y.tab.h: parser.y
+ $(YACC) -d $<
+
+dep depend:: $(ALLSRC) $(HDR)
+ $(CC) -M $(ALLSRC) > .depend
+
+clean::
+ rm -f *.o lex.yy.c y.output y.tab.[ch] *~ genhdr gencode core
+
Added: trunk/genser/format.h
==============================================================================
--- trunk/genser/format.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/genser/format.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,5 @@
+/* Output formatting routines */
+
+void format(const char *, ...) __attribute((format (printf, 1, 2)));
+
+extern FILE *form_out;
Added: trunk/Changelog
==============================================================================
--- trunk/Changelog 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/Changelog 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,25 @@
+--------------------------------------------------------------------------
+userfs-0.9.7-pre3
+ The listed example filesystems now compile well:
+
+ arcfs
+ cvsfs
+ egfs
+ homer
+ tarfs
+
+--------------------------------------------------------------------------
+20 June 1999 Jan Jirmasek
+
+ Merged the Mike's patch for 2.2.x kernels and my glibc patches
+ into the latest version of userfs-0.9.6.
+ Getting ready to compile genser part, kernel part, utils, c++ lib.
+
+
+5 May 1999 Michael McCormack
+
+ Userfs now compiles with the Linux 2.2.7 kernel
+ Added a couple of extra file systems.
+ Modified genser to parse and discard function typedefs.
+ Removed some compile warnings.
+
Added: trunk/rules
==============================================================================
--- trunk/rules 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/rules 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,64 @@
+# Global rules and definitions
+# This is included near the top of every Makefile (after TOP is set)
+
+CC=gcc
+KERNCC=gcc # Do not define this as $(CC)
+CPP=$(CC)
+CXX=g++
+
+# Debugging/optimisation
+DEBUG=-O2 -m486
+
+# profiling flags
+PROF=
+
+# Warnings
+WARN=-Wall -Wno-unused
+
+#Extra ld flags
+XLDFLAGS=
+
+# Extra C and C++ flags
+# Individual makefiles can change CFLAGS and CXXFLAGS, but
+# global additions can be made here
+XCFLAGS=$(PROF) $(DEBUG) $(WARN)
+XCXXFLAGS=$(PROF) $(DEBUG) $(WARN) #-fno-for-scope
+
+.cc.o:
+ $(CXX) -c $(CXXFLAGS) $(XCXXFLAGS) $<
+
+.c.o:
+ $(CC) -c $(CFLAGS) $(XCFLAGS) $<
+
+.cc.s:
+ $(CXX) -S $(CXXFLAGS) $(XCXXFLAGS) $<
+
+.c.s:
+ $(CC) -S $(CFLAGS) $(XCFLAGS) $<
+
+all::
+
+# Specific targets
+DEPLIBUSERFS=$(TOP)/lib/libuserfs.a
+LIBUSERFS=-L$(TOP)/lib -luserfs
+
+DEPLIBLWP=$(TOP)/lwp/liblwp.a
+LIBLWP=-L$(TOP)/lwp -llwp
+
+GENDIR=$(TOP)/genser
+GENHDR=$(GENDIR)/genhdr
+GENCODE=$(GENDIR)/gencode
+
+$(GENHDR) $(GENCODE) $(DEPLIBUSERFS) $(DEPLIBLWP): dummy
+ $(MAKE) -C $(@D) $(@F)
+
+
+#
+# include a dependency file if one exists
+#
+ifeq (.depend,$(wildcard .depend))
+include .depend
+endif
+
+dummy:
+
Added: trunk/README.gnome-vfs
==============================================================================
--- trunk/README.gnome-vfs 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/README.gnome-vfs 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,53 @@
+The additional work done here on top of userfs-0.9.7-pre3 is designed to allow
+access to gnome-vfs URIs from non-Gnome projects. For the purposes of getting
+gnome-vfs as a filesystem, here are the files we care about:
+
+ kernel/src/userfs.o - build this (hopefully) by doing a make in kernel/
+ filesystems/gvfs - cd here and do a "make gvfs"
+ utils/muserfs - do a "make muserfs" from utils/
+
+You could do a make from the toplevel, but be prepared to get a boatload of
+errors about the c++ class library. The "filesystems" were first written against
+libg++ and I began to bring them forward before realizing that I could just
+write the user-side module in C (by changing the arcfs module slightly).
+Forget the c++ stuff for now.
+
+Once you have a working userfs.o, just "insmod userfs.o" as root. If it
+bitches, you'll have to figure out what changed in the kernel from 2.4.3.
+
+If that worked, cd over to filesystems/gvfs, and try:
+ $ ../../utils/muserfs ./gvfs /mnt/0 ftp://user:pass@host/path
+for an existing path /mnt/0 that you have full privileges on.
+
+If all goes well, you may now poke around on your ftp server.
+
+REQUIREMENTS:
+ * kernel 2.4.3 is known to work, 2.4.0-test2 is known NOT to work
+ * gnome-vfs requires the NIC patch (the no-gconf stuff)
+ * my /usr/include/linux and /usr/include/asm happened to be the 2.4.3
+ include/linux and include/asm directories, so either change the makefile
+ or change your setup to match when building the kernel module
+
+NOTES:
+ * open up two terminals, start reading a big file in one, then start reading
+ the same file in the second. BARF! most likely a bug in kernel/src/uio.c
+ related to my /* commenting out the superblock locking.. */ or maybe not.
+ * it currently even works with webdav over a proxy, but the proxy string
+ is screwy. I think it needs to be HTTP_PROXY=host:port as opposed to
+ the usual HTTP_PROXY=http://host:port. ?? anyhoo, it has been tested
+ successfully against http://www.mydocsonline.com
+ * read, write, open, close, readdir, lookup, create are all implemented.
+ haven't done remove, move, and symlink ops yet, but they shouldn't be
+ hard.
+ * read specifically works around any gnome-vfs pseudo-seek stuff. this is
+ solely because the NIC project has no hard drive so I cannot afford to
+ use temp space. thusly, if you are going to do non-sequential reads,
+ your performance will _suck_, but hey, it works.
+ * writes can currently only be sequential.
+ * though it's weird, you can even mount a file (as opposed to a directory).
+ a phony parent directory will be created for it. though this is strange,
+ you may need this if, for example, you can access a file via ftp but have
+ no permissions to the directory which contains it.
+
+Have fun!
+-kurt
Added: trunk/utils/um.c
==============================================================================
--- trunk/utils/um.c 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/utils/um.c 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,27 @@
+/*
+ * Force an unmount, ignoring everything
+ *
+ * This is useful for getting rid of runaway filesystems
+ * when muserfs gets confused and leaves the mtab in an
+ * inconsistent state.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/mount.h>
+
+int
+main(int argc, char *argv[])
+{
+ if (argc == 2)
+ {
+ if (umount(argv[1]) == -1)
+ perror("umount");
+ else
+ exit(0);
+ }
+ else
+ fprintf(stderr, "Usage: %s mount-point\n", argv[0]);
+ exit(1);
+}
Added: trunk/utils/muserfs.c
==============================================================================
--- trunk/utils/muserfs.c 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/utils/muserfs.c 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,622 @@
+/*
+ * Simple mount interface for userfs. This does permissions checking
+ * and allows non-suid processes to be mounted.
+ *
+ * It checks the proposed mount dir, does the mount and starts up
+ * the filesystem program attached to the kernel with pipes to
+ * deal with the filesystem operations. The filesystem process
+ * runs as the invoking user.
+ *
+ * Muserfs expects the child to only ever exit properly when it
+ * gets an EOF from the kernel. Muserfs takes signals and umounts
+ * the filesystem when it gets normal termination signals.
+ * muserfs will also attempt to unmount the filesystem if the child
+ * exists unexpectedly. If this happens, muserfs will exit regardless
+ * of whether it was successful.
+ *
+ * The /etc/mtab file is also updated correctly, so that umount should
+ * be able to unmount the filesystem.
+ *
+ * The input and output fds are inhereted by the filesystem process
+ * and are passed on the command-line with the -i fd (kernel to process)
+ * and -o fd (process to kernel) options.
+ *
+ * Usage: muserfs [-a] program mount-point [args...]
+ *
+ * This program is distributed under the terms of the
+ * Free Software Foundation General Public Licence.
+ * Copyright Jeremy Fitzhardinge 1993
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <stdarg.h>
+#include <mntent.h>
+#include <pwd.h>
+#include <getopt.h>
+#include <signal.h>
+#include <fcntl.h>
+
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+
+#define FILESYSTEM_NAME "userfs"
+
+#ifdef __GLIBC__
+
+#undef WNOHANG /* due sys/wait.h -x- linux/fs.h conflict */
+#undef WUNTRACED
+
+#undef BLOCK_SIZE /* due sys/mount.h -x- linux/fs.h conflict */
+#undef MS_RDONLY
+#undef MS_NOSUID
+#undef MS_NODEV
+#undef MS_NOEXEC
+#undef MS_SYNCHRONOUS
+#undef MS_REMOUNT
+#undef MS_MANDLOCK
+#undef S_WRITE
+#undef S_APPEND
+#undef S_IMMUTABLE
+#undef MS_NOATIME
+#undef MS_NODIRATIME
+#undef MS_RMT_MASK
+#undef MS_MGC_VAL
+#undef BLKROSET
+#undef BLKROGET
+#undef BLKRRPART
+#undef BLKGETSIZE
+#undef BLKFLSBUF
+#undef BLKRASET
+#undef BLKRAGET
+
+#endif
+
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/userfs_fs.h>
+#include <linux/userfs_mount.h>
+#include <linux/userfs_types.h>
+#include <linux/userfs_fs_sb.h>
+
+#include "io.h"
+
+char *progname = NULL;
+
+const char *mount_point = NULL;
+
+int doumount(const char *);
+int mounted = 0;
+
+void sighandler(int sig)
+{
+fprintf(stderr, "%s: in sighandler\n", progname);
+ switch (sig)
+ {
+ case SIGINT:
+ case SIGTERM:
+ case SIGHUP:
+ case SIGQUIT:
+ case SIGCHLD:
+ fprintf(stderr, "%s: signal in (INT,TERM,HUP,QUIT,CHLD)\n", progname);
+ if (!mounted)
+ break;
+
+ if (!doumount(mount_point))
+ fprintf(stderr, "%s: failed to unmount \"%s\"\n",
+ progname, mount_point);
+
+ default:
+ return;
+ }
+}
+
+static void sysfatal(const char *str, ...)
+{
+ va_list va;
+ int er = errno;
+
+ va_start(va, str);
+ fprintf(stderr, "%s: ", progname);
+ vfprintf(stderr, str, va);
+ fprintf(stderr, ": %s\n", strerror(er));
+ va_end(va);
+ exit(1);
+}
+
+static void syserror(const char *str, ...)
+{
+ va_list va;
+ int er = errno;
+
+ va_start(va, str);
+ fprintf(stderr, "%s: ", progname);
+ vfprintf(stderr, str, va);
+ fprintf(stderr, ": %s\n", strerror(er));
+ va_end(va);
+}
+
+void *xmalloc(size_t s)
+{
+ void *m = malloc(s);
+
+ if (m == NULL)
+ sysfatal("memory allocation failure");
+
+ return m;
+}
+
+char *fullpath(const char *p)
+{
+ char path[MAXPATHLEN];
+ int dl;
+ char *np;
+
+ if (realpath(p, path) == NULL)
+ return strdup(p);
+ else
+ return strdup(path);
+}
+
+char *makeopts(char **av, int narg, const char *name, int pid)
+{
+ int i, j, nblen;
+ char *op, *cp;
+ char nbuf[100];
+
+ sprintf(nbuf, "username=%s,user,pid=%d,exec,nodev,nosuid,", name, pid);
+ nblen = j = strlen(nbuf);
+
+ for(i = 0; i < narg; i++)
+ j += strlen(av[i]) + 1;
+
+ op = xmalloc(j + 1);
+
+ strcpy(op, nbuf);
+ cp = &op[nblen];
+
+ for(i = 0; i < narg; i++)
+ {
+ strcpy(cp, av[i]);
+ cp += strlen(av[i]);
+ *cp++ = ',';
+ }
+
+ cp[-1] = 0;
+
+ return op;
+}
+
+int doumount(const char *mpoint)
+{
+ int kid;
+ int wstat;
+ int i;
+ static volatile int interlock;
+ static const char *umounts[] =
+ {
+ "/sbin/umount",
+ "/etc/umount",
+ "/usr/sbin/umount",
+ "/bin/umount",
+ };
+
+ if (++interlock != 1)
+ return 0;
+ if (mpoint == NULL)
+ return 0;
+
+ switch(kid = fork())
+ {
+ case -1:
+ perror("umount fork failed");
+ return 1;
+ case 0:
+ setuid(geteuid());
+ for(i = 0; i < sizeof(umounts)/sizeof(*umount); i++)
+ execl(umounts[i], "umount", mpoint, NULL);
+ sysfatal("exec of \"umount %s\" failed", mpoint);
+ exit(1);
+ }
+
+ if (wait4(kid, &wstat, 0, NULL) == -1)
+ sysfatal("Wait for umount failed");
+
+ interlock--;
+
+ if (WEXITSTATUS(wstat) != 0)
+ return 0;
+ mounted = 0;
+ return 1;
+}
+
+static int prot_seq = 0;
+
+void genhdr(up_preamble *pre, up_ops op)
+{
+ pre->version = UP_VERSION;
+ pre->op = op;
+ pre->isreq = UP_REQ;
+ pre->seq = prot_seq++;
+ pre->size = 0;
+}
+
+typedef unsigned char *(*encode_func)(const void *, unsigned char *);
+typedef unsigned char *(*decode_func)(void *, unsigned char *);
+typedef unsigned int (*sizeof_func)(const void *);
+
+#define GEN_ENC(var) (encode_func)(var)
+#define GEN_DEC(var) (decode_func)(var)
+#define GEN_SIZ(var) (sizeof_func)(var)
+
+void userfs_genpkt(struct super_block *, up_preamble *, up_ops);
+
+/* Encode and send request, receive and decode reply */
+#define doop(from, to, pre, repl, st, ss, rt, rs)\
+ _userfs_doop(from, to, pre, repl, \
+ GEN_ENC(encode_##st), (void *)ss, \
+ GEN_DEC(decode_##rt), (void *)rs, \
+ GEN_SIZ(sizeof_##st), GEN_SIZ(sizeof_##rt))
+
+int _userfs_doop(int from, int to,
+ up_preamble *pre, upp_repl *repl,
+ encode_func se, void *send,
+ decode_func rd, void *recv,
+ sizeof_func sso, sizeof_func rso)
+{
+ int ret;
+ unsigned char *p, *p0;
+ int replsz = sizeof_upp_repl(repl);
+
+ pre->size = (*sso)(send);
+
+ p = p0 = xmalloc(USERFS_MAX_XFER);
+
+ p = encode_up_preamble(pre, p0);
+ if ((ret = fullwrite(to, p0, p-p0)) != p-p0)
+ {
+ free(p0);
+ return -1;
+ }
+
+ if (pre->size > 0)
+ {
+ p = (*se)(send, p0);
+ if ((ret = fullwrite(to, p0, p-p0)) != p-p0)
+ {
+ free(p0);
+ return -1;
+ }
+ }
+
+ if (fullread(from, p0, replsz) != replsz)
+ {
+ free(p0);
+ return -1;
+ }
+
+ decode_upp_repl(repl, p0);
+
+ if (repl->size != 0)
+ {
+ if (fullread(from, p0, repl->size) != repl->size)
+ {
+ free(p0);
+ return -1;
+ }
+ (*rd)(recv, p0);
+ }
+ free(p0);
+
+ return 0;
+}
+
+/*
+ * Get mount flags from the filesystem
+ */
+int getflags(int in, int out)
+{
+ return 0;
+}
+
+/*
+ * Check filesystem process is there and functioning by asking if
+ * it supports the upp_mount operation. If it doesn't or fails to
+ * respond then the mount is aborted.
+ */
+int checkfs(int in, int out)
+{
+ up_preamble pre;
+ upp_repl repl;
+ int sz;
+
+ genhdr(&pre, userfs_up_mount);
+ pre.isreq = UP_ENQ;
+
+ if (doop(in, out, &pre, &repl, void, NULL, void, NULL) != 0)
+ return 0;
+
+ if (repl.version != UP_VERSION || repl.op != userfs_up_mount ||
+ repl.seq != 0 || repl.isreq != UP_REPL ||
+ repl.size != 0 || repl.err_no != 0)
+ return 0;
+
+ return 1;
+}
+
+int domount(int infd, int outfd, const char *mpoint, char *prog,
+ char **args, int nargs, int kid, int flags)
+{
+ struct userfs_mount mnt;
+ struct mntent ment;
+ FILE *mtab;
+ struct passwd *pwd;
+ char *mdev;
+ int fd,r;
+
+ if ((pwd = getpwuid(getuid())) == NULL)
+ sysfatal("can't get password file entry for uid %d",
+ getuid());
+
+ mnt.tokern = infd;
+ mnt.fromkern = outfd;
+ mnt.version = USERFS_VERSION;
+ mnt.magic = USERFS_SUPER_MAGIC;
+ mnt.seq = prot_seq;
+
+ r = mount(NULL, mpoint, FILESYSTEM_NAME,
+ MS_MGC_VAL|MS_NODEV|MS_NOSUID|flags, &mnt);
+
+ if (r == -1)
+ {
+ syserror("mount of %s on %s failed",
+ prog, mpoint);
+ if(0>close(infd))
+ fprintf(stderr,"close infd returned err\n");
+ if(0>close(outfd))
+ fprintf(stderr,"close outfd returned err\n");
+ return 1;
+ }
+
+ close(infd);
+ close(outfd);
+
+ mdev = xmalloc(strlen(prog) + 7);
+ sprintf(mdev, "%s-%d", prog, kid);
+
+ ment.mnt_fsname = mdev;
+ ment.mnt_dir = fullpath(mpoint);
+ ment.mnt_type = FILESYSTEM_NAME;
+ ment.mnt_opts = makeopts(args, nargs, pwd->pw_name, kid);
+ ment.mnt_freq = 0;
+ ment.mnt_passno= 0;
+
+ mount_point = ment.mnt_dir;
+
+ if ((fd = open(MOUNTED"~", O_RDWR|O_CREAT|O_EXCL, 0600)) == -1)
+ {
+ syserror("Can't get "MOUNTED"~ lock file");
+ return 1;
+ }
+ close(fd);
+
+ if ((mtab = setmntent(MOUNTED, "a+")) == NULL)
+ {
+ syserror("Can't open " MOUNTED);
+ return 1;
+ }
+
+ if (addmntent(mtab, &ment) == 1)
+ {
+ syserror("Can't write mount entry");
+ return 1;
+ }
+ if (fchmod(fileno(mtab), 0644) == -1)
+ {
+ syserror("Can't set perms on "MOUNTED);
+ return 1;
+ }
+ endmntent(mtab);
+
+ if (unlink(MOUNTED"~") == -1)
+ {
+ syserror("Can't remove "MOUNTED"~");
+ return 1;
+ }
+ free(mdev);
+ mounted = 1;
+ return 0;
+}
+
+int mountok(struct stat *st)
+{
+ if (!S_ISDIR(st->st_mode))
+ {
+ errno = ENOTDIR;
+ return -1;
+ }
+
+ if (getuid() != 0 &&
+ (getuid() != st->st_uid ||
+ (st->st_mode & S_IRWXU) != S_IRWXU)
+ )
+ {
+ errno = EPERM;
+ return -1;
+ }
+
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ struct stat st;
+ int kid, i, ch;
+ int p1[2], p2[2];
+ char **args;
+ char b1[10], b2[10];
+ int async = 0;
+ int ret = 0;
+ int euid, egid, gid;
+
+ progname = argv[0];
+ euid = geteuid();
+ egid = getegid();
+ gid = getgid();
+#if 0
+ if (euid != 0 || egid != gid)
+ {
+ fprintf(stderr, "%s: must be installed suid root: euid=%d egid=%d gid=%d\n",
+ progname,
+ euid, egid, gid);
+ exit(1);
+ }
+#endif
+
+ for(i = 0; (ch = getopt(argc, argv, "a")) != EOF;)
+ switch(ch)
+ {
+ case 'a':
+ async = 1;
+ break;
+ default:
+ i++;
+ }
+
+ argc -= optind;
+ argv = &argv[optind];
+
+ if (i != 0 || argc < 2)
+ {
+ fprintf(stderr,
+ "Usage: %s [-a] program mount-point [args...]\n",
+ progname);
+ exit(1);
+ }
+
+ if (async && getuid() != 0)
+ {
+ fprintf(stderr, "%s: async (-a) ignored: you can't unmount if you arn't root\n",
+ progname);
+ async = 0;
+ }
+
+ if (stat(argv[1], &st) < 0)
+ sysfatal("Stat of %s failed", argv[1]);
+
+ if (mountok(&st) < 0)
+ sysfatal("can't mount on %s", argv[1]);
+
+ if (pipe(p1) < 0 || pipe(p2) < 0)
+ sysfatal("can't create pipe");
+
+ for(i = 1; i < NSIG; i++)
+ {
+ struct sigaction sa;
+ sigset_t ss;
+
+ sigemptyset(&ss);
+
+ sa.sa_handler = sighandler;
+ sa.sa_flags = SA_NOMASK|SA_RESTART;
+ sa.sa_mask = ss;
+
+ if (i != SIGKILL && i != SIGSTOP)
+ sigaction(i, &sa, NULL);
+ }
+ signal(SIGCHLD, SIG_DFL);
+
+ switch(kid = fork())
+ {
+ case -1: /* fail */
+ sysfatal("fork failed");
+
+ case 0: /* child */
+ break;
+
+ default: /* parent */
+ close(p1[1]);
+ close(p2[0]);
+
+ mounted = 0;
+
+ if (checkfs(p1[0], p2[1]))
+ {
+ int flags = getflags(p1[0], p2[1]);
+
+ ret = domount(p1[0], p2[1], argv[1], argv[0],
+ &argv[2], argc-2, kid, flags);
+ }
+ else
+ fprintf(stderr,
+ "%s: filesystem failed to respond correctly.\n",
+ progname);
+
+ while (!async)
+ {
+ int wstat;
+
+ if (wait4(kid, &wstat, 0, NULL) < 0)
+ fprintf(stderr, "%s: wait for pid %d failed: %s\n",
+ progname, kid, strerror(errno));
+ else
+ if (!WIFEXITED(wstat))
+ continue;
+
+ if (mounted && !doumount(mount_point) != 0)
+ fprintf(stderr, "%s: Failed to umount filesystem\n",
+ progname);
+ break;
+ }
+ exit(ret);
+ }
+
+ /* child */
+ close(p1[0]);
+ close(p2[1]);
+
+ if (setreuid(-1, getuid()) < 0)
+ sysfatal("Can't drop suid permissions");
+
+ {
+ static int isigs[] = { SIGKILL, SIGTERM, SIGINT };
+ for(i = 0; i < sizeof(isigs)/sizeof(*isigs); i++)
+ {
+ struct sigaction sa;
+ sigset_t ss;
+
+ sigemptyset(&ss);
+
+ sa.sa_handler = SIG_IGN;
+ sa.sa_flags = SA_NOMASK|SA_RESTART;
+ sa.sa_mask = ss;
+
+ sigaction(isigs[i], &sa, NULL);
+ }
+ }
+ args = (char **)xmalloc(sizeof(char *)* (argc + 3));
+
+ sprintf(b1, "-i%d", p2[0]);
+ sprintf(b2, "-o%d", p1[1]);
+
+ args[0] = argv[0];
+ args[1] = b1;
+ args[2] = b2;
+ args[3] = "-m";
+ args[4] = fullpath(argv[1]);
+
+ for(i = 0; i <= argc-3; i++)
+ args[i+5] = argv[i+2];
+ args[i+5] = NULL;
+
+ execvp(args[0], args);
+
+ sysfatal("exec of %s failed", args[0]);
+ exit(1);
+}
Added: trunk/utils/opnames.h
==============================================================================
--- trunk/utils/opnames.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/utils/opnames.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,27 @@
+
+const char *opnames[] =
+{
+ "up_create",
+ "up_lookup",
+ "up_close",
+ "up_read",
+ "up_write",
+ "up_truncate",
+ "up_fsync",
+ "up_readdir",
+ "up_link",
+ "up_unlink",
+ "up_symlink",
+ "up_readlink",
+ "up_followlink",
+ "up_mount",
+ "up_umount",
+ "up_iread",
+ "up_iwrite",
+ "up_statfs",
+ "up_iput",
+ "up_open",
+ "up_permission",
+ "up_rename",
+};
+
Added: trunk/utils/io.c
==============================================================================
--- trunk/utils/io.c 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/utils/io.c 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,81 @@
+/*
+ * Simple IO functions
+ *
+ * These are just like read() and write(), except they will try
+ * to process all the requested data, unless there's an error or
+ * EOF. They also cope with EINTR.
+ *
+ * Copyright (C) 1995 Jeremy Fitzhardinge <jeremy at sw.oz.au>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/types.h>
+
+#include "io.h"
+
+size_t
+fullread(int from, unsigned char *buf, size_t sz)
+{
+ size_t rd = 0;
+ size_t ret;
+
+ while(sz > 0)
+ {
+ ret = read(from, buf, sz);
+
+ if (ret == (size_t)-1)
+ {
+ if (errno == EINTR)
+ continue;
+
+ return -1;
+ }
+
+ if (ret == 0)
+ break;
+
+ sz -= ret;
+ buf += ret;
+ rd += ret;
+ }
+
+ return rd;
+}
+
+size_t
+fullwrite(int tofd, const unsigned char *buf, size_t sz)
+{
+ size_t wr = 0;
+ size_t ret;
+
+ while(sz > 0)
+ {
+ ret = write(tofd, buf, sz);
+
+ if (ret == (size_t)-1)
+ {
+ if (errno == EINTR)
+ continue;
+ return -1;
+ }
+
+ if (ret == 0)
+ {
+ fprintf(stderr, "fullwrite wrote 0 bytes\n");
+ break;
+ }
+
+ sz -= ret;
+ buf += ret;
+ wr += ret;
+ }
+
+ return wr;
+}
Added: trunk/utils/userfs_types.c
==============================================================================
--- trunk/utils/userfs_types.c 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/utils/userfs_types.c 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1 @@
+#include <linux/userfs_types.c>
Added: trunk/utils/io.h
==============================================================================
--- trunk/utils/io.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/utils/io.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,23 @@
+/* -*- C -*- */
+
+#ifndef _LIB_IO_H_
+#define _LIB_IO_H_
+
+/*
+ * Simple IO functions
+ */
+
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+size_t fullread(int fd, unsigned char *, size_t);
+size_t fullwrite(int fd, const unsigned char *, size_t);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIB_IO_H_ */
Added: trunk/utils/Makefile
==============================================================================
--- trunk/utils/Makefile 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/utils/Makefile 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,33 @@
+# Client toplevel makefile
+
+TOP=..
+FLAGS=-I$(TOP)/kernel -I$(TOP)/lib -I$(TOP)/genser #-DDEBUG -S
+CXXFLAGS = $(FLAGS)
+CFLAGS = $(FLAGS) -g
+
+#include $(TOP)/rules
+
+LDFLAGS = $(PROF)
+
+MUSERFSOBJ = muserfs.o userfs_types.o io.o
+
+PROGS=muserfs um
+
+all: $(PROGS)
+
+install: muserfs
+ install -m 4755 -o root -g root -sc muserfs /usr/local/bin
+
+muserfs: $(MUSERFSOBJ) #$(DEPLIBUSERFS)
+ $(CC) $(LDFLAGS) -o $@ $(MUSERFSOBJ) $(LIBUSERFS)
+
+muserfs.cat: muserfs.1
+ groff -Tascii -man $< > $@ || rm -f $@
+
+clean:
+ rm -f *.o *~ core $(PROGS)
+
+dep depend:
+ $(CXX) $(CXXFLAGS) -M *.c > .depend
+
+include $(TOP)/rules.sub
Added: trunk/br/br.c
==============================================================================
--- trunk/br/br.c 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/br/br.c 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,9 @@
+#include <linux/unistd.h>
+
+_syscall0(void,unbreak)
+_syscall0(void,doabreak)
+
+int main()
+{
+ unbreak();
+}
Added: trunk/README.mm
==============================================================================
--- trunk/README.mm 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/README.mm 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,910 @@
+.\" mm, I guess
+.ds d "\&\s-1\f(CW
+.ds p "\&\s+1\fP
+.de CC
+.DS I
+.ft CW
+.S -1
+.nr == \w'~~~~~~~~'u
+.ta \\n(==u +\\n(==u +\\n(==u +\\n(==u +\\n(==u +\\n(==u +\\n(==u +\\n(==u +\\n(==u +\\n(==u
+..
+.de EE
+.ft P
+.S +1
+.DE \\$1
+..
+.nr Hb 10
+.nr Hs 10
+.TL
+\fB Userfs\fP \- Filesystems Implemented as User Processes
+.AU "Jeremy Fitzhardinge <jeremy at sw.oz.au>
+.AF "Softway Pty. Ltd."
+.MT 4
+.H 1 "Introduction"
+Userfs is a mechanism by which normal user processes can
+be a Linux filesystem.
+There are many uses for this, including:
+.BL
+.LI "Prototype filesystems"
+.P
+Prototype new block allocation algorithms in a user process and
+debug with gdb
+before going into the compile-crash-reboot cycle of kernel
+development.
+.LI "Infrequent use filesystems"
+.P
+You want to mount "FooBaz 0X" filesystems under Linux, but
+you don't want it that often, and you don't need it to be
+maximum speed. Rather than trying to get the kernel itself
+to understand, or write specialised tools, write a filesystem
+program.
+.LI "Add capabilities to existing filesystems"
+.P
+Want compression, encryption, ACLs? Have a process to mirror
+an existing file tree, but with your own extentions and semantics.
+.LI "Completely virtual filesystems and new interfaces"
+.P
+Add a filesystem-type interface to an existing mechanism, or
+a filesystem interface as a new way of representing data.
+Sick of FTP? How about
+.CC
+$ mkdir /ftp/tsx-11.mit.edu
+$ cd /ftp/tsx-11.mit.edu/pub/linux
+$ cp README $HOME
+.EE
+Or mail?
+.CC
+$ cd /mail
+$ ls
+001.sbg at socs.uts.edu.au
+002.Leroy
+003.tlukka at vinkku.hut.fi
+004.Davor_Jadrijevic
+$ cat */From
+From: sbg at socs.uts.edu.au
+From: leroy at socs.uts.edu.au (Leroy)
+From: tlukka at vinkku.hut.fi
+From: davor%emard.uucp at ds5000.irb.hr (Davor Jadrijevic)
+$ cat */Subject
+Subject: More things
+Subject: (none)
+Subject: That userfs thing
+Subject: mailfs again
+$
+.EE
+.LE
+You get the idea.
+.H 1 "Installation"
+.H 2 "Kernel"
+First of all, if you have installed userfs before,
+remove traces of previous versions of userfs: make sure
+there are no userfs header files in
+.I "linux/include/linux"
+and no userfs patches to any of the kernel source.
+.P
+Otherwise, the kernel module should just compile with the rest of
+the build process. Userfs is currently supported for 2.0.x
+(tested up to 2.0.0), and for 1.3.x.
+It should work out the kernel version you're compiling for and configure itself
+appropriately.
+There are no kernel patches and
+compiling userfs into the kernel is not supported.
+.P
+To install the module you need the
+.B modutils
+package, which should be available from your local
+Linux ftp archive. It should be clear from its
+documentation what you need to do with
+.I "userfs.o"
+to get it into the kernel. If you get some warnings about multiply
+defined symbols, ignore them: only undefined symbols are a problem.
+You can compile the kernel and module with either ELF or a.out compilers;
+I used ELF.
+.P
+The kernel module supports modverions, so it generally won't be necessary
+to recompile it for every kernel version;
+.I insmod
+will let you know if you need to recompile the userfs module (with luck - otherwise
+Linux will helpfully let you know with obscure behaviour or kernel panics...).
+.H 2 "Non-kernel Code"
+.P
+Building the rest of the code should be a matter of typing "make" at
+the top userfs directory. This will generate dependencies and build
+the utilities needed (genser), the library, the clients using the
+library and the kernel module. There will be some warnings; ignore them.
+.P
+I used gcc 2.7.0; you probably need to use the latest compiler and
+libraries (libg++ 2.7.0.1) for the C++ (though I've avoided templates
+and exceptions; g++ has enough problems with simple things).
+.H 2 "Mailing list"
+The old USERFS channel on the Linux Activists list server is now
+defunct.
+There is a new list:
+\f(CWlinux-userfs at vger.rutgers.edu\fP.
+To subscribe, send mail to \f(CWmajordomo at vger.rutgers.edu\fP
+with the contents
+.CC
+subscribe linux-userfs [your email address]
+.EE
+.H 2 "Bugs, comments, etc"
+When you find a bug, tell me. Please send me the code you're using,
+the kernel version, whatever changes you've made to userfs kernel
+code, and instructions or a script to reproduce the bug. Don't just
+tell me "it broke."
+.P
+If you've made changes to the kernel code, please send it to me rather
+than sending it out to the world. Please send me comments, ideas for
+new kernel features, or things that you think would make good
+filesystems but you can't do right now. Also feel free to ask
+questions about either the implementation of my code, how to write
+your own userfs clients, or even just to tell me you got it working.
+.P
+Send mail to either me (Jeremy Fitzhardinge <jeremy at sw.oz.au>) or to
+the mailing list (see above).
+.H 1 "Using clients"
+Clients are generally mounted with the
+.B muserfs
+command. It's quite simple \- it's a program which makes sure the
+mount point is legal for the user to mount on, and mounts the given
+process with the user's permissions. Note that any user can mount a
+process, so more checking is done on the mount point than for a normal
+mount. Unless the user is root, the mount point must be owned by the
+user and writable.
+.B muserfs
+has a man page, which is even up to date.
+.P
+There are a few useful or semi-useful clients:
+.B homer ", " ftpfs ", " mailfs " and " arcfs.
+.BL
+.LI Homer
+is written in C++, and uses the C++ library in the lib directory to do
+most of its work. All it does is set up a single directory under its
+mount point which contains symbolic links named after each user name
+in the password file, which points to the associated home directory.
+Mounted on /u it makes a passible replacement for ~ expansion in a
+shell (but it works for any program).
+.LI Ftpfs
+is an experimental filesystem which allows readonly access to FTP
+sites, maintaining a long-term disk cache. Its intended primarily for
+anonymous FTP, but can also be used for authenticated FTP sessions.
+.LI Mailfs
+is by Davor Jadrijevic. It is for reading mail. Currently its
+read-only and does not track mailbox changes, and is no longer being
+actively developed. Pester Davor (or fix it yourself).
+.LI Arcfs
+was written by David Gymer. It allows you to mount
+a compressed tar file as a read-only filesystem, and inspect
+it with normal tools. It's pretty neat, but not recommended for
+heavy "production" use, or for very large files.
+.H 1 "Theory of operation"
+The kernel module registers a new filesystem type with the
+kernel ("userfs"). The filesystem itself is very simple; all it does
+it takes the normal kernel filesystem requests, wraps them up into
+well-defined packets and squirts them down a file descriptor
+(presumeably connected to a process) and waits for the reply on
+another file descriptor.
+.P
+If the filesystem process is on the same machine, then the file
+descriptors are probably ordinary pipes. However, userfs just reads
+and writes on the file descriptors, so they could be anything; files,
+sockets, devices \- userfs doesn't care.
+.P
+The following is not a comprehensive tutorial on writing filesystems,
+or a detailed "how it works" or specification of the existing code.
+It is intended to give some idea of what I was thinking, and basic
+concepts to bear in mind while poking about in my kernel or user code.
+.H 2 "Priorities"
+I had a number of goals which I wanted satisfied by this thing (from
+most to least important):
+.BL
+.LI Flexibility
+.P
+I want the process to have as much power as a kernel-resident
+filesystem as possible. I wanted to keep the interfaces as generic
+and flexible. This has been mostly achieved.
+.LI Robustness
+.P
+Since I see prototyping and development a major use for userfs, it
+seems important to make sure that the kernel code can't (at worst)
+crash or lock up if the user code fails. As it stands, it should be
+impossible for a user process to crash the kernel, but it is possible
+for a bad user process to lock up processes trying to use the
+filesystem.
+.P
+It is also possible for a process to go strange while it is being
+mounted, leaving a half-mounted filesystem. The mountpoint becomes a
+nulled out inode, but the kernel refuses to unmount it (because it
+isn't mounted), and refuses to mount on it (because it's busy).
+This happens much less often than it used to, because muserfs does a
+simple check to see if the filesystem process is at all viable.
+.LI "Availability to users and Security"
+.P
+I'd like any user to be able to write a filesystem process.
+Traditionally, filesystems are things that embody the security of
+Unix, and are therefore very much superuser-only things. However,
+there are only a couple of really sensitive features that shouldn't be
+able to be controlled by any user: suid executables and device nodes.
+Since a trusted superuser process is still required to call the mount
+system call, and that process can set the no-suid and no-device flags,
+the filesystem code can't use these as security holes. I can't think
+of anything else that needs special care from a security point of
+view. However, since the filesystem is completely under the control
+of the process, one can make no assumptions about its contents. For
+example "." and ".." may not do expected things, symlinks may point to
+places other than what readlink returns. This makes navigating such
+filesystems a new and interesting experience.
+.LI "Efficiency"
+.P
+Efficiency is my lowest priority, but it is still important.
+Unfortunately the other requirements (as usual) make things less
+efficient. The most significant inefficiency is the context switches
+between the kernel and the process. I think the most benefits can be
+gained by reducing the number of these. There are several approaches
+to this:
+.BL
+.LI
+If the process wants a default behaviour for an operation, then
+it can be done in the kernel. The best example of this is
+permission checking - if the process wants normal unix permission
+checking then it doesn't need to do it itself. Otherwise it can take
+all the permission requests from the kernel, and implement other
+permission policies. This is currently implemented. When the
+filesystem is first mounted, the kernel asks the process what requests
+it will accept. From that point the kernel will do sensible default
+actions for requests that the process doesn't want to handle rather
+than sending them down the connection.
+.LI
+Group requests commonly issued together into one. This is hard, since
+the main kernel tells the filesystem code very little about what it is
+doing, so it is hard to know what to do next. However, there are a
+couple of single kernel requests that are implemented in the protocol
+as two or more transactions. This could be fixed in future.
+.LI
+Data can be cached in the kernel. This is the most tricky, since
+kernel caching or read-ahead limits the amount of control the process
+can have over the data once read. I think this could be optionally
+implemented, depending on whether the process says it is OK to do
+caching, and if so what kinds.
+.P
+Currently directory readahead is implemented with the
+.B upp_multireaddir
+operation. This allows the filesystem process to return as many
+directory entries as it likes, which are then saved in a readahead
+buffer. If there's a future request which can be satisfied by this
+buffer it is, rather than sending another message to the filesystem.
+In 1.3.x kernels, userfs can transfer the whole lot to the process
+reading the directory in one syscall (assuming the process has enough
+space allocated for it).
+This is a win if there
+are lots of linear directory searches (such as shell globbing, ls or
+pwd).
+.LI
+A larger than 4k maximum packet size can be used, now that the kernel
+memory allocator allows larger than 4k memory allocations. However,
+since pipes are the most common connection beween filesystems and
+kernels, and pipes can hold at most 4k of data, there would still be a
+context switch between filesystem code and kernel every 4k, so there
+wouldn't be much gain.
+.LE
+.P
+A number of people have suggested adding shared memory between the
+kernel and the filesystem process. This would be quite limiting and
+least likely option to improve things. At the moment, the filesystem
+makes no assumptions about the nature of the file descriptors for
+talking to the process. To implement shared memory between the kernel
+and the process would require some way of finding the process on the
+other end of the file descriptors (if any), and playing around with
+memory maps. This still wouldn't cut down on the number of context
+switches at all (it may even increase the number of switches because
+of syncronisation).
+.LE
+.H 2 "Protocol"
+The protocol used is machine independent, using network
+byte order and defined type sizes. The code to do the
+packetisation and depacketisation is generated automatically
+by a program, given the description of each packet.
+This is not fully portable, but it avoids byte order and
+structure alignment problems.
+.P
+A packet to or from the kernel has two parts. The first is a header
+that contains a sequence number, an operation type, a packet type,
+size of the following data, and a protocol version number. The packet
+type can either be a request, a reply or an enquiry. Requests and
+enquiries are always from the kernel to the process, and the process
+only ever sends replies to the kernel. A reply's header has one extra
+field - an error field, containing an error number. Replies always
+have the same sequence number as their corresponding request or
+enquiry. If there was an error performing the operation the error
+field is set to the error number and there is no additional data
+returned. If there is no error the error field is set to 0.
+.P
+Following a request or reply packet is the optional operation-specific
+data. This is passed through the protocol for interpretation by the
+operation routines at each end.
+.P
+The kernel may have multiple outstanding requests. In other words,
+the kernel may send a new request before receiving a reply to a
+previous one. This allows the filesystem to block one process for a
+slow operation while other processes can use the filesystem for
+shorter operations. This improves performance on, for example, an ftp
+filesystem, where one process may be using a fast local link, and
+another may be using a slow international one, and each has to wait
+for its own requests to be satisfied. Of course this requires the
+filesystem process to be written with some form of multi-threading.
+If the filesystem just reads requests, acts on them and replies then it
+can do so and ignore any kernel requests until it is ready to deal
+with them.
+.H 2 "Handles"
+The base element of a filesystem is an
+.I inode .
+There is an exact one to one relationship between inodes and files
+(where a
+.I file
+in this case can be any filesystem object, like a normal file, a
+directory and so on). The kernel needs to be able to uniquely
+identify inodes. Inodes are uniquely numbered within a
+filesystem, but each mounted filesystem has its own numbering.
+Therefore an inode is completely identified by an inode number and a
+filesystem identifier (or
+.I device ,
+though it doesn't mean much for a filesystem which has no
+physical hardware associated with it).
+.P
+A device is what distinguishes mounted filesystems from one another,
+and an inode is what distinguishes files within a filesystem from each
+other. Inode numbers are generated by each filesystem, and are used
+by the kernel to refer to specific files to the filesystem specific
+code. User process filesystems are no exception: between the kernel
+and the filesystem process, files are refered to by using
+.I handles ,
+which are essentially 32 bit unsigned numbers. When a filesystem first
+mentions a file to the kernel, it gives it a handle, which the kernel
+uses for all later operations on the file. It the the handle which
+identifies the file, rather than the name, so it is important to use
+distinct handles for distinct files, and never change the handle of a
+file once it has been given to the kernel.
+.H 2 "Random operation specific advice and blurb"
+This may eventually accurately describe the whole protocol, but for
+now its a list of interesting points and things that have bitten me.
+.P
+Normally when writing a filesystem you should use the library
+.I libuserfs
+(see below), and use the advice in this section as a guide on what
+kind of things should be put in your userfs operation functions,
+or for idle curiosity.
+.H 3 "Mounting"
+The mount is initiated by a user process calling the mount system
+call, with the "userfs" filesystem type. In the filesystem specific
+data, the process passes two file descriptor numbers for the kernel to
+read and write to. These can by any kind of file descriptor at all.
+Most commonly they would be pipes or sockets, but there is no
+restriction. All the kernel requires that the one it talks to the
+process with is writable, and the one it gets replies from is
+readable.
+.P
+The most important request is mounting. Most important, because it is
+one of the two requests that the process has to implement (of course,
+not implementing anything else would be completely useless). The request
+itself is not that complex. All it does is return a handle of the inode
+at the root of the filesystem. Most commonly, this will be a directory.
+Userfs does not enforce this, but the kernel itself may.
+.P
+After the process returns the root handle, the kernel will probe the
+process to see what operations it is willing to support. This is done
+by sending a series of enquire packets to the process. The process
+should reply with normal reply packets, with the errno field either
+set to 0 if it is supported or ENOSYS if it isn't. No real operation
+should be done, and no additional information should be sent in the
+reply. If the process replies ENOSYS to an operation, it will never
+recieve it again, and the kernel will use a sensible default for it
+(typically what the kernel would normally do for an in-kernel
+filesystem if it doesn't support the operation). Conversely, if the
+filesystem process doesn't get an enquiry about a particular operation
+from the kernel, it will never see that operation from the kernel.
+The filesystem process should send 0 for the operations it explicitly
+supports, and ENOSYS for everything else, so the protocol can be
+extended without having to modify existing clients.
+
+.H 3 "Reading Inodes"
+The most common thing for a filesystem to be asked to do is to read
+inodes. For the process, this involves filling out a structure much
+like the kernel's inode structure and the stat structure. It's
+important is to make sure the nlinks field is non-zero. This
+field is the number of names the inode has, that is, the number of
+directory entries in the filesystem which refer to this inode. In
+theory, this can never be 0 when the kernel asks for the inode,
+because that means that the kernel asked for the inode without ever
+seeing a name referring to it, implying that the filesystem never told
+the kernel about the file. If it is 0 then the kernel will never
+"put" the inode, and it will make the filesystem un-umountable.
+.P
+When the kernel wants an inode from the filesystem, it uses the
+.B upp_iread
+protocol request to fetch it. This happens if something in the kernel
+asks for the inode, but it isn't already in the kernel inode table.
+Therefore, once the kernel has asked the filesystem for an inode, it
+will not ask for it again while anything in the kernel is using it.
+.P
+Once nothing in the kernel is using the inode, the kernel will
+issue an
+.B upp_iput
+operation, which may be preceded by an
+.B upp_iwrite
+if the inode was modified in use. A filesystem need not implement
+these operations if there is no need to do so.
+.H 3 "Open and Close"
+Reading and putting inodes are the basic operations: regardless of
+what an inode is being used for it will be read and put. The
+.B upp_open " and " upp_close
+operations specifically correspond to the
+.BR open (2)
+and
+.BR close (2)
+system calls. Normally a filesystem doesn't need to perform any
+special handling for these operations, and would not normally
+implement them, except if it wants to know the identity of the process
+doing the operations. When a program issues an open system call for a
+file on the user filesystem, the kernel will send a
+.I upp_open
+operation for the file, which includes complete identifcation for the
+process which issued the open. When the filesystem replies it returns
+a
+.I "credentials token."
+From then on, that credentials token is sent to the filesystem in all
+operations which correspond to a system call which takes a file
+descriptor as an argument, such as
+.B read , write , readdir , lseek
+and so on.
+.P
+This may seem a bit complex: why not just send the uid of the process
+with the operations? Well, the credentials of a process are quite
+complex, since they include the real, saved and effective uids and
+gids of the process, and all the auxillary groups. Sending this with
+each request would be quite an overhead. The idea is that all the
+info is sent on a open, and the filesystem process can associate it
+with a token internally, and only use the token in correspondance with
+the kernel.
+.P
+Also note that the credentials are associated with an open file
+descriptor, not the process performing the operation. Mostly a
+process will deal with file descriptors it has created itself, but its
+quite possible that it can inherit file descriptors from another
+process with a different set of credentials. In this case the
+filesystem knows the original process's credentials, but not for the
+process which is performing the operation.
+.H 3 "Handle Management"
+The handle of an inode is only way the kernel and the filesystem can
+talk about a file. An inode may have more than one name, or no names
+at all, so file names are not a good way of keeping track of a file.
+Use inodes in your filesystem code to keep track of files, even if you
+have a simple 1:1 name to file mapping.
+.P
+Handles must also be consistent. Of course you must always keep the
+handles of files currently in use consistent, but you must also keep
+them consistent between uses. If a process opens a file once, closes
+it and then reopens it, then it will expect it to have the same inode
+number if it is supposed to be the same file (which is how processes
+using a user filesystem will see the file handles).
+.P
+Also, if you ever refer to a handle in communication with the kernel,
+you must be prepared for the kernel to ask about it. For example, if
+the kernel reads a directory with the
+.B upp_readdir " or " upp_multireaddir
+operations, each entry in the reply will have a name and a handle.
+Each of those handles must be the handle of the file if the kernel
+looks at the file more closely. If you make them all the same, for
+example, then a program would be entitled to believe that all the
+names in the directory refer to one actual file.
+.H 3 "Dealing with muserfs"
+Writing a client which can be handled by muserfs is very easy. The
+important thing to remember is that the filesystem process can
+basically ignore muserfs, and ignore issues like how to quit and so
+on.
+.P
+A userfs filesystem process should only terminate under one condition:
+it gets an EOF (a read of 0 bytes) from the kernel on the file
+descriptor its reading operation requests from. Muserfs will execute
+it so that most signals are ignored, so it can handle them itself.
+When the muserfs process is sent a SIGINT or SIGTERM it unmounts the
+filesystem mount point with the
+.BR umount (8)
+command (used so that /etc/mtab is updated properly). This causes the
+kernel to send the filesystem process a
+.B upp_umount
+operation. The kernel will close its end of the file descriptors, and
+the process is expected to do the same, even if only by exiting.
+Therefore, when trying to unmount a userfs filesystem, do not kill the
+filesystem process directly, and do not kill muserfs with SIGKILL.
+Either way you should be able to unmount with
+.B umount
+as root.
+.H 1 "Using libuserfs"
+.I libuserfs
+is a C++ library designed to make writing filesystem clients easier.
+It is designed so all the work common to almost all filesystems is
+encapsulated into a few generic classes, which can be used as base
+classes for specific filesystem functions.
+.H 2 "Basic Classes"
+The most basic classes,
+.B Comm ", " Filesystem " and " Inode
+implement the basic communication with the kernel and stub methods for
+each operation.
+.P
+The Comm class reads from the kernel and decodes the headers of the
+operation packets, and passes the remainder to the Filesystem class.
+The Filesystem performs the operation and returns an unencoded return
+header and the encoded body of the reply, if any. All this is not
+exposed to the code using the library.
+.P
+Filesystem takes each operation and dispatches it to the appropriate
+place. The Filesystem class directly handles the operations which are
+global to the whole filesystem, such as mounting or unmounting.
+For operation which pertain to a particular Inode (such as reading,
+or looking up a name in a directory), Filesystem looks
+up the Inode in its table and dispatches the operation to it.
+.P
+The Inode class has all its methods implemented as stubs which fail
+with the "not implemented" error code. It also has members for the
+standard inode properties of mode, type, size, ownership, links,
+timestamps and so on.
+.P
+These classes are completely useless on their own, so they must be
+used as base classes for other classes with actually do something.
+.I libuserfs
+has more specific, but still generally useful classes.
+.P
+.B SimpleInode
+implements a simple inode with some normally expected behaviour.
+It has a constructor which initializes the inode properties to
+sensible values, and methods which implement simple defaults for
+the open, close and permissions check operations.
+.P
+.B DirInode,
+derived from SimpleInode, implements all the operations needed for
+a directory, including linking and unlinking inodes to/from names,
+rename, and directory scanning and lookup. It takes very little
+extra code to implemement simple directory behaviour.
+.H 2 "Writing your own filesystem classes"
+A complete filesystem has two parts: a collection of inodes, one for
+each file, and the filesystem structure itself, which holds all the
+inodes together. Each inode represents a file in the filesystem,
+regardless of type. There is only one inode per file in the
+filesystem, even if the file appears multiple times under different
+names.
+.H 3 "Arguments and return values of operation methods"
+Each method with the name
+.B do_something
+in the Filesystem and Inode classes corresponds to an operation
+in the userfs protocol. As a result, they all have similar
+argument structures. All such methods have
+.B "const up_preamble &pre" " and " "upp_repl &repl"
+which are references to the operation reqest and reply packet
+headers. Mostly there is no reason for operation methods to
+use them, because their contents are dealt with in lower
+levels of the library, but they are there if you want them.
+.P
+Each userfs protocol operation may have arguments, return values,
+both or neither, and the method for that operation will have
+corresponding arguments. For an operation named
+.I x
+the method argument with the operation arguments will have the
+type \fBconst upp_\fIx\fP_s\fR,
+and the return values argument will have the type
+\fBupp_\fIx\fP_r\fR,
+For example, the up_read operation will correspond to the Inode
+method
+.CC
+int Inode::do_read(const up_preamble &pre, upp_repl &repl,
+ const upp_read_s &args, upp_read_r &ret);
+.EE
+.P
+The contents of the structures, along with encoding and decoding
+functions, are machine generated, and therefore have a consistent
+set of rules. Mostly its quite simple, with normal base types
+directly corresponding to C and C++ types. However, variable
+sized types need to have both a pointer to the data and the
+size of the data encoded into them. Memory for the data is allocated
+with the C++ new and delete operators, with the
+.B alloc
+method of a variable sized object. The memory is automatically freed
+by the method's caller. For example, if a return value of a method
+contains an member called
+.B name
+representing a filename, it would be set with the following sequence
+(assuming
+.B ourname
+is a normal 0 terminated string):
+.CC
+int namelen = strlen(ourname);
+ret.name.alloc(namelen); // Allocate memory
+ret.name.nelem = namelen; // Set name length
+memcpy(&ret.name.elems, ourname, namelen); // Set name contents
+// ...
+.EE
+(alternatively, you could just point
+.I "ret.name.elems
+directly at
+.I ourname ,
+because it won't try and free the string if it was never allocated).
+.P
+Note that strings are never zero terminated; the length of the
+returned string is exactly the number of characters in the string.
+.P
+If the operation the method is performing fails, it should return the
+appropriate error code, or 0 if it succeeds. Don't return -1 unless
+you mean to \- it has special meaning (see below, in "Deferring
+Replies").
+.H 3 "Deriving from Filesystem"
+Filesystem class must implement a number of methods to make the
+filesystem viable:
+.BL
+.LI "\fIEnquire\fP"
+is called when the kernel wants to find what operations your
+filesystem supports. For all the operations that any inode will
+implement, return 0 and return ENOSYS for the rest.
+.LI "\fIdo_mount\fP"
+takes no arguments and returns the handle for the inode for the
+root directory (that is, the top directory of your filesystem).
+The kernel immediately does a
+.B do_iread
+operation using this handle.
+.LE
+You can also implement
+.I do_statfs
+which allows the kernel to get space and inode usage statistics,
+such as when "df" is executed, and
+.I do_umount
+so the filesystem is formally informed when it is unmounted (normally
+it just gets an EOF from the kernel, and Comm::Run returns).
+.H 3 "Deriving from Inode"
+Most of the work of the filesystem is done in the inodes.
+All inode classes must be derived from Inode, and generally
+there will be a number of different Inode based classes.
+.P
+It is probably better to use SimpleInode as a base rather than
+plain Inode, because it implements simple defaults for some
+methods, which would otherwise fail. If Filesystem::Enquire
+says that the filesystem supports a particular operation, then
+any inode should be prepared to get that operation from the
+kernel.
+.P
+Similarly, unless you are doing something special, deriving
+directories from DirInode saves a lot of work.
+.P
+Only
+.I do_iread
+need be implemented, but obviously the filesystem will do nothing
+interesting unless other operations are implemented. do_iread returns
+the details of the inode. Note that the Filesystem class calls the
+do_iread of the Inode when the operation comes from the kernel, so the
+inode must exist by the time the kernel asks for it. The constructor
+for Inode automatically registers the inode in the Filesystem's inode
+table; conversely, the destructor removes it.
+.P
+Here are some other useful methods for an Inode; the descriptions
+are brief and general, and don't necessarily refer to all the arguments
+and return values, which means they can be ignored.
+.BL
+.LI "\fIdo_iwrite\fP"
+is, obviously, the opposite of do_iread. It simply sets the various
+Inode values.
+.LI "\fIdo_iput\fP"
+is called when the kernel is no longer using the inode. That is,
+the inode is no longer open, the current or root directory of a
+process, being executed from or being mapped from. If an inode
+is iput and has no names (has no name to inode mapping in any
+directory) it can be destroyed.
+.LI "\fIdo_read\fP"
+allows data to be read from the file. The arguments are the offset in
+the file to start reading from, and the number of bytes desiried. The
+method may return as many bytes up to that number as it likes,
+including 0, which means EOF.
+.LI "\fIdo_write\fP"
+does the converse; a block of data and an offset is passed in, and
+the method returns the number of bytes actually written.
+.LI "\fIdo_lookup\fP"
+translates a name into an inode reference. This is typically
+implemented for directories; if the name exists in the directory
+the method should return the handle of the inode, or fail with
+ENOENT.
+.LI "\fIdo_dirread\fP"
+returns the next directory entry at the passed offset. It returns
+the name and inode of the next file in the directory, and the
+size of the entry returned. This is added by the kernel to the
+current offset in the directory to form the offset of the next
+directory entry for the next call. Since the directory entries
+don't correspond to real file storage as in other, more conventional
+filesystems, a directory entry can be regarded as having an
+offset of 1.
+.P
+If the end of the directory has been reached, it should return a new
+offset of 0.
+.LI "\fIdo_multireaddir\fP"
+is similar to do_readdir, but can return any number of directory
+entries, which are cached in a readahead buffer in the kernel. If a
+program asks for a directory entry for an inode which has a cached
+directory entry then the entry will come from within the kernel rather
+than asking the filesystem process. This operation can return only
+one entry (and so is like do_readdir), or as many as will fit in a
+return packet (up to 4k or so of entries). Returning no entries means
+the end of the directory has been reached. Returning multiple entries
+improves the performance of directory scans, most frequently done by
+ls, pwd and shell globbing.
+.P
+Look at the implementation of DirInode::do_multireaddir for details
+of how this should be dealt with.
+.LI "\fIdo_create\fP"
+does all file creation, whether it be a normal file, a directory,
+a fifo file or a device node. The mode contains the type of the
+file in same way as the stat structure member
+.B st_mode.
+.LI "\fIdo_unlink\fP"
+is the opposite, and is used for unlinking (removing a name to inode
+mapping) files and directories. If an inode is not in use and
+has no links then it can be destroyed and its handle can be reused.
+.LI "\fIdo_symlink\fP"
+is used to create new symlink inodes. It returns the handle
+of the new inode.
+.LI "\fIdo_readlink\fP"
+returns the pathname which a symbolic link is pointing to.
+.LI "\fIdo_followlink\fP"
+returns the pathname of the file a symbolic link is really referring
+to. If Filesystem::Enquire says the filesystem does not support
+this operation, the readlink operation is used instead.
+.LI "\fIdo_open\fP"
+is called when a file is actually opened. It is only necessary
+to implement this if it is important to know whether a file is
+being opened as opposed to being used in any other way. This
+operation passes the filesystem the complete authentication
+credentials of the process doing the open, so that the filesystem
+can do extended security checking or change the behaviour of the
+file depending on the user.
+.P
+This method can return a credential token, which is a magic number
+used by the filesystem process to refer to the set of credentials
+passed by the kernel. The kernel attaches this credentials token to
+each each operation generated by system calls on the file descriptor
+generated by the open (read(), write(), readdir() and close()). The
+credentials token is part of the file descriptor, so is inhereited
+unchanged if the descriptor is passed to another process, even if it
+has different credentials.
+.P
+When a file is opened, a new file table entry for the inode is
+created. That file table entry has a single file descriptor
+referring to it. More file descriptors can be made to refer to
+the file table entry with the
+.BR dup (2)
+system call, and can be removed with
+.BR close (2).
+.LI "\fIdo_close\fP"
+is called when the last file descriptor for a file table entry
+is closed. The only argument for this is the credentials token
+for that file table entry, so that the filesystem can free all
+references to it.
+.LI "\fIdo_permission\fP"
+is called when the filesystem says it wants to do permissions
+checking. This is called a lot, and can cause many more operations
+to pass between the kernel and filesystem process. If the filesystem
+does not implement it the normal unix user/group/others checking
+is performed.
+.LI "\fIdo_rename\fP"
+moves a file from one directory to a new one (though it may be the
+same).
+.H 3 "Deriving from DirInode"
+DirInode implements a number of userfs operation methods for
+directories, such as readdir, multireaddir and lookup. It
+also automatically constructs directories with "." and ".."
+entries pointing to the appropriate places.
+.P
+DirInode deals with strings a lot, and rather than using the
+normal
+.B "char *"
+it uses the libg++
+.B String
+class for all string arguments to its own methods (but not,
+of course, for the userfs protocol operation methods).
+.P
+DirInode expects a pointer to the parent directory,
+which is also a class derived from DirInode. If the directory
+is at the top of the filesystem's tree, it should be a NULL
+pointer. The protected member
+.B parent
+points the the parent inode, or
+.B this
+for the top one. It should never be NULL.
+.P
+DirInode keeps a list of files in the directory, but does not
+allow that list to be directly visible. The only operations
+for manipulating the directory contents for a derived class
+are:
+.BL
+.LI "\fBint link(const String name, Inode *)\fP"
+which links a new name into the directory, updating all the reference
+and link counts;
+.LI "\fBint unlink(const String name)\fP"
+which does the opposite;
+.LI "\fBDirEntry *lookup(const String name)\fP"
+which returns a directory entry if it finds the file, or NULL
+otherwise; and
+.LI "\fBDirEntry *scan(DirEntry * &pos)\fP"
+which returns the directory entry at
+.I pos,
+updating it in the process, or NULL if there are no more entries.
+.LI "\fBDirEntry *scan(int &pos)\fP"
+is the same, except it uses an integer offset, which is less
+efficient.
+.LE
+.H 2 "Communications classes"
+.P
+There are a number of communications classes in the library,
+which provide different ways of multiplexing replies.
+.P
+The most simple is the Comm class, which simply takes each request,
+passes it to the filesystem and sends back the reply. There are more
+complex comms classes though.
+.H 3 "File Descriptor Dispatcher"
+.P
+The
+.B CommBase
+class (base of all comms classes) provides a dispatcher which allows
+classes to register interest in activity on file descriptors.
+This is used internally to get input from the kernel, but can be used
+by a filesystem to monitor any file descriptor for any reason.
+To do it, simply derive a dispatcher class from
+.B DispatchFD
+and call
+.B "struct disp_fd CommBase::addDispatch(int fd, DispatchFD *, int what)" ,
+where what can be one or more of
+.I DISP_R ", " DISP_W " or " DISP_E ,
+for interest in read ready, write ready or exceptions.
+When an event occurs, the
+.B "DispatchFD::dispatch(int fd, int what)"
+method is called of the registered class. If it returns 0 then
+it is removed from the dispatch list. If it returns -1 it indicates
+an error; it is removed, and
+.B "CommBase::Run()"
+returns. Returning 1 is a normal return.
+.P
+.B "CommBase::Run()"
+returns normally when there are no more entries on the dispatch list.
+.H 3 "Deferring Replies"
+.P
+In normal operation, the filesystem processes one request at a time,
+so each operation is replied to before the next is looked at. This is
+a convention of the way the user code works, and not something the
+kernel enforces. It just sends requsts as processes using the
+filesystem need them, and they block until the reply for their
+particular request is replied to. Therefore, it is possible for
+multiple processes to use the filesystem at once.
+.P
+The
+.B DeferComm " and " DeferFilesys
+classes have a method called
+.B DeferReply
+(the DeferFilesys once just calls the DeferComm one to make it
+accessable to things within the filesystem). DeferReply forks the
+filesystem; on the child side it returns 0 and in the parent it
+returns the pid of the child. If the operation method returns -1 then
+the Filesystem just goes on to processing the next request from the
+kernel. When the child is ready to reply, it can just return in the
+normal way. The call to DeferReply sets up the DeferComm class in the
+child process to reply though the parent rather than going straight to
+the kernel, in order to make sure the replies from multiple processes
+don't get jumbled up. When the reply has been sent back, the child
+process just exits.
+.P
+Because the child is really a child process, you have to do all the
+changes in filesystem state before calling DeferReply, or arrange for
+some other mechanism for the parent and children to talk.
+.H 3 "Multi-threaded filesystems"
+.P
+The
+.B ThreadComm
+class creates a new lightweight thread for each request, using the Rex
+lwp library (in the lwp directory). This allows multiple requests to
+be handled within the one process, so long as one thread does not
+block the whole process in a system call. The file descriptor
+dispatcher in CommBase is useful for preventing this: see
+.B ftpfs
+for a
+complete example of a multithreaded filesystem.
Added: trunk/TODO
==============================================================================
--- trunk/TODO 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/TODO 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,8 @@
+TODO list
+=========
+
+1. Any C++ hacker should try to compile the sample filesystems - ftpfs, intfs,
+ homer, etc. There has to be done some work around the String class sure.
+
+2. Remove useless warnings during compilation of the c++ lib.
+
Added: trunk/lib/Comm.cc
==============================================================================
--- trunk/lib/Comm.cc 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/lib/Comm.cc 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,84 @@
+// -*- C++ -*-
+
+// Basic communications
+
+// (C) Copyright 1993, 1994 Jeremy Fitzhardinge <jeremy at sw.oz.au>
+// This code is distributed under the terms of the
+// GNU General Public Licence. See COPYING for more details.
+
+#pragma implementation
+
+#include <Filesystem.h>
+#include <Comm.h>
+#include <io.h>
+#include <stdio.h>
+
+Comm::Comm(Filesystem &fs, unsigned int to, unsigned int from)
+ :CommBase(fs, to, from)
+{
+ req = new Comm_doreq(this, filesys);
+ addDispatch(from, req);
+}
+
+Comm_doreq::Comm_doreq(const CommBase *comm, Filesystem &fs)
+ : DispToKern(comm), filesys(fs)
+{
+}
+
+int
+Comm_doreq::dispatch(int fd, int)
+{
+ up_preamble pre;
+ size_t presize = sizeof_up_preamble(&pre);
+ Uchar hbuf[256];
+ Uchar buf[4096];
+ int ret;
+
+ ret = fullread(fd, hbuf, presize);
+ if (ret == 0)
+ return 0;
+
+ if (ret != (int)presize)
+ {
+ fprintf(stderr, "Comm_doreq::dispatch failed to get whole header (%d wanted, %d got)\n",
+ presize, ret);
+ return -1;
+ }
+
+ upp_repl repl;
+ size_t replsize = sizeof_upp_repl(&repl);
+
+ assert(sizeof(hbuf) > replsize);
+
+ decode_up_preamble(&pre, hbuf);
+
+ if (pre.size != 0 && (ret = fullread(fd, buf, pre.size)) != (int)pre.size)
+ {
+ fprintf(stderr, "Comm_doreq::dispatch: failed to get whole body (%ld wanted, %d got)\n",
+ pre.size, ret);
+ return -1;
+ }
+
+ ret = filesys.DoOp(pre, repl, buf);
+
+ if (!ret)
+ return -1;
+
+#ifdef DEBUG
+ if (repl.errno != 0)
+ {
+ fprintf(stderr, "Request %d failing with %d %s\n",
+ pre.op, repl.errno, strerror(repl.errno));
+ }
+#endif
+
+ encode_upp_repl(&repl, hbuf);
+
+ if (fullwrite(tokern, hbuf, replsize) != replsize)
+ return -1;
+
+ if (repl.size != 0 && fullwrite(tokern, buf, repl.size) != repl.size)
+ return -1;
+
+ return 1;
+}
Added: trunk/lib/Comm.h
==============================================================================
--- trunk/lib/Comm.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/lib/Comm.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,32 @@
+// -*- C++ -*-
+
+// Basic communications - simple 1 in 1 out
+
+// This program is distributed under the terms of the
+// Free Software Foundation General Public Licence.
+// Copyright Jeremy Fitzhardinge <jeremy at sw.oz.au> 1993
+
+#ifndef __COMM_H_SEEN__
+#define __COMM_H_SEEN__
+
+#pragma interface
+
+#include <CommBase.h>
+
+class Comm: public CommBase
+{
+public:
+ Comm(Filesystem &, unsigned int to, unsigned int from);
+};
+
+class Comm_doreq: public DispToKern
+{
+protected:
+ Filesystem &filesys;
+public:
+ Comm_doreq(const CommBase *comm, Filesystem &filesys);
+
+ int dispatch(int fd, int);
+};
+
+#endif /* __COMM_H_SEEN__ */
Added: trunk/lib/DirInode.cc
==============================================================================
--- trunk/lib/DirInode.cc 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/lib/DirInode.cc 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,325 @@
+// -*- C++ -*-
+
+// Generic directory inode by Jeremy Fitzhardinge
+// This program is distributed under the terms of the
+// Free Software Foundation General Public Licence.
+// See COPYING for details
+
+// A directory
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <unistd.h>
+#include <assert.h>
+#include <sys/time.h>
+
+#pragma implementation
+
+#include "Filesystem.h"
+#include "SimpleInode.h"
+#include "DirInode.h"
+#include "string"
+#include "dbg.h"
+
+DirInode::DirInode(Filesystem &fs, Handle h, Inode *p, int mm)
+ :SimpleInode(fs, h), max_multird(mm)
+{
+ LOG("DirInode::DirInode");
+
+ mode = S_IFDIR;
+
+ parent = p == NULL ? this : p;
+
+ size = 0;
+
+ entries = end = NULL;
+ link(".", this);
+ link("..", parent);
+}
+
+DirInode::~DirInode()
+{
+ DirEntry *next;
+
+ for(; entries; entries = next)
+ {
+ next = entries->next;
+ delete entries;
+ }
+
+ entries = end = NULL;
+}
+
+int
+DirInode::link(const string &name, Inode *ino)
+{
+ if (lookup(name) != NULL)
+ return EEXIST;
+
+ DirEntry *de = new DirEntry(name, ino);
+
+ de->prev = end;
+ de->next = NULL;
+ if (de->prev)
+ de->prev->next = de;
+ else
+ entries = de;
+ end = de;
+
+ ino->incref();
+
+ size++;
+
+ return 0;
+}
+
+int
+DirInode::unlink(const string &name)
+{
+ DirEntry *de = lookup(name);
+
+ if (de == NULL)
+ return ENOENT;
+
+ de->geti()->decref();
+
+ if (de->next)
+ de->next->prev = de->prev;
+ else
+ end = de->prev;
+
+ if (de->prev)
+ de->prev->next = de->next;
+ else
+ entries = de->next;
+
+ delete de;
+
+ size--;
+
+ return 0;
+}
+
+DirEntry *
+DirInode::lookup(const string &name) const
+{
+ for(DirEntry *de = entries; de != NULL; de = de->next)
+ if (de->name == name)
+ return de;
+
+ return NULL;
+}
+
+DirEntry *
+DirInode::scan(DirEntry * &de) const
+{
+ if (de == NULL)
+ de = entries;
+
+ if (de == NULL)
+ return NULL;
+
+ DirEntry *ret = de;
+ de = de->next;
+
+ return ret;
+}
+
+DirEntry *
+DirInode::scan(int &ind) const
+{
+ if (ind >= size)
+ return NULL;
+
+ int i;
+ DirEntry *de;
+
+ for(de = entries, i = 0; de != NULL && i < ind; de = de->next, i++)
+ ;
+
+ if (de == NULL)
+ return de;
+
+ ind++;
+ return de;
+}
+
+// Implementations of userfs operations
+int
+DirInode::do_unlink(const up_preamble &, upp_repl &,
+ const upp_unlink_s &arg)
+{
+ update();
+
+ return unlink(string((char *)arg.name.elems, (int)arg.name.nelem));
+}
+
+int
+DirInode::do_link(const up_preamble &, upp_repl &,
+ const upp_link_s &args)
+{
+ update();
+
+ Inode *ino = findino(args.ofile.handle);
+
+ if (!ino)
+ return EINVAL;
+
+ return link(string((char *)args.name.elems, (int)args.name.nelem), ino);
+}
+
+int
+DirInode::do_rename(const up_preamble &, upp_repl &,
+ const upp_rename_s &arg)
+{
+ Inode *ndir = findino(arg.ndir.handle);
+
+ if (ndir == NULL || !S_ISDIR(ndir->mode))
+ return ENOTDIR;
+
+ update();
+
+ string oname((char *)arg.oname.elems, (int)arg.oname.nelem);
+
+ DirEntry *fde = lookup(oname);
+
+ if (!fde)
+ return ENOENT;
+
+ Inode *file = fde->geti();
+
+ if (file == NULL)
+ return EINVAL;
+
+ int ret = ndir->link((char *)arg.nname.elems, arg.nname.nelem, file);
+ if (ret)
+ return ret;
+ ret = unlink(oname);
+
+ ndir->mtime = mtime = time(0);
+
+ return ret;
+}
+
+int
+DirInode::do_lookup(const up_preamble &pre, upp_repl &rep,
+ const upp_lookup_s &arg, upp_lookup_r &res)
+{
+ update();
+
+ DirEntry *de = lookup(string((char *)arg.name.elems, (int)arg.name.nelem));
+
+ atime = time(0);
+
+ if (de != NULL)
+ {
+ res.handle.handle = de->geti()->gethandle();
+ return 0;
+ }
+ return ENOENT;
+}
+
+int
+DirInode::do_readdir(const up_preamble &pre, upp_repl &repl,
+ const upp_readdir_s &arg, upp_readdir_r &res)
+{
+ LOG("readdir");
+
+ update();
+
+ res.off=1;
+
+ int ind = arg.off;
+
+ DirEntry *de = scan(ind);
+
+ if(de == NULL)
+ {
+ res.off=0;
+ res.name.nelem=0;
+ return 0;
+ }
+
+ atime = time(0);
+
+ res.name.nelem = strlen((de->name).c_str());
+ res.name.elems = (__s8 *) (de->name).c_str();
+ res.file.handle = de->ino->gethandle();
+
+ DB(printf("Readdir:'%s',%d,%d\n",res.name.elems,res.name.nelem,res.file.handle));
+ return 0;
+}
+
+int
+DirInode::do_read(const up_preamble &, upp_repl &,
+ const upp_read_s &, upp_read_r &)
+{
+ return EISDIR;
+}
+
+int
+DirInode::do_write(const up_preamble &, upp_repl &,
+ const upp_write_s &, upp_write_r &)
+{
+ return EISDIR;
+}
+
+int
+DirInode::do_multireaddir(const up_preamble &pre, upp_repl &repl,
+ const upp_multireaddir_s &arg,
+ upp_multireaddir_r &res)
+{
+ update();
+
+ LOG("multireaddir");
+
+ int ind = arg.off;
+ DirEntry *de = scan(ind);
+
+ if (de == NULL)
+ {
+ res.nelem = 0;
+ return 0;
+ }
+
+ atime = time(0);
+
+ res.nelem = 0;
+ res.alloc(max_multird);
+ upp_readdir_r *ents = res.elems;
+
+ int i;
+ for(i = 0;
+ de != NULL && i < max_multird &&
+ sizeof_upp_multireaddir_r(&res) < USERFS_MAX_XFER;
+ i++, scan(de))
+ {
+ int len = de->name.length();
+ ents[i].off = 1;
+ ents[i].name.nelem = len;
+ ents[i].name.alloc(len);
+ memcpy(ents[i].name.elems, (de->name).c_str(), len);
+ ents[i].file.handle = de->ino->gethandle();
+ DB(printf("Multireaddir:%d '%s',nlen=%d,ino=%d,off=%d\n",
+ i, (const char *)de->name,
+ len, ents[i].file.handle, off));
+ res.nelem = i+1;
+ }
+ res.nelem = i;
+
+ while(sizeof_upp_multireaddir_r(&res) >= USERFS_MAX_XFER)
+ res.nelem--;
+
+ return 0;
+}
+
+DirEntry::DirEntry(const string name, Inode *i)
+ : name(name), ino(i)
+{
+}
+
+DirEntry::~DirEntry()
+{
+}
Added: trunk/lib/Filesystem.p
==============================================================================
--- trunk/lib/Filesystem.p 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/lib/Filesystem.p 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,9584 @@
+
+
+
+
+
+
+
+
+#pragma implementation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern "C" {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern int errno;
+
+
+extern int *__errno_location (void) throw () __attribute__ ((__const__));
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#pragma interface "userfs_types"
+
+
+
+
+
+
+
+
+
+
+
+
+typedef unsigned short __kernel_dev_t;
+typedef unsigned long __kernel_ino_t;
+typedef unsigned short __kernel_mode_t;
+typedef unsigned short __kernel_nlink_t;
+typedef long __kernel_off_t;
+typedef int __kernel_pid_t;
+typedef unsigned short __kernel_ipc_pid_t;
+typedef unsigned short __kernel_uid_t;
+typedef unsigned short __kernel_gid_t;
+typedef unsigned int __kernel_size_t;
+typedef int __kernel_ssize_t;
+typedef int __kernel_ptrdiff_t;
+typedef long __kernel_time_t;
+typedef long __kernel_suseconds_t;
+typedef long __kernel_clock_t;
+typedef int __kernel_daddr_t;
+typedef char * __kernel_caddr_t;
+typedef unsigned short __kernel_uid16_t;
+typedef unsigned short __kernel_gid16_t;
+typedef unsigned int __kernel_uid32_t;
+typedef unsigned int __kernel_gid32_t;
+
+typedef unsigned short __kernel_old_uid_t;
+typedef unsigned short __kernel_old_gid_t;
+
+
+typedef long long __kernel_loff_t;
+
+
+typedef struct {
+
+ int __val[2];
+
+} __kernel_fsid_t;
+
+
+
+
+
+
+
+
+typedef unsigned short umode_t;
+
+
+
+
+
+
+typedef __signed__ char __s8;
+typedef unsigned char __u8;
+
+typedef __signed__ short __s16;
+typedef unsigned short __u16;
+
+typedef __signed__ int __s32;
+typedef unsigned int __u32;
+
+
+typedef __signed__ long long __s64;
+typedef unsigned long long __u64;
+
+
+
+
+
+
+
+
+
+typedef __kernel_suseconds_t suseconds_t;
+typedef __u8 uint8_t;
+typedef __u16 uint16_t;
+typedef __u32 uint32_t;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern "C" {
+
+
+extern void __assert_fail (__const char *__assertion, __const char *__file,
+ unsigned int __line, __const char *__function)
+ throw () __attribute__ ((__noreturn__));
+
+
+extern void __assert_perror_fail (int __errnum, __const char *__file,
+ unsigned int __line,
+ __const char *__function)
+ throw () __attribute__ ((__noreturn__));
+
+
+
+
+extern void __assert (const char *__assertion, const char *__file, int __line)
+ throw () __attribute__ ((__noreturn__));
+
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef unsigned int size_t;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern "C" {
+
+
+
+
+
+
+
+typedef struct
+ {
+ int quot;
+ int rem;
+ } div_t;
+
+
+
+typedef struct
+ {
+ long int quot;
+ long int rem;
+ } ldiv_t;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern size_t __ctype_get_mb_cur_max (void) throw () ;
+
+
+
+extern double atof (__const char *__nptr) throw () ;
+
+extern int atoi (__const char *__nptr) throw () ;
+
+extern long int atol (__const char *__nptr) throw () ;
+
+
+
+__extension__ extern long long int atoll (__const char *__nptr)
+ throw () ;
+
+
+
+extern double strtod (__const char *__restrict __nptr,
+ char **__restrict __endptr) throw () ;
+
+
+
+
+extern long int strtol (__const char *__restrict __nptr,
+ char **__restrict __endptr, int __base) throw () ;
+
+extern unsigned long int strtoul (__const char *__restrict __nptr,
+ char **__restrict __endptr, int __base)
+ throw () ;
+
+
+
+__extension__
+extern long long int strtoq (__const char *__restrict __nptr,
+ char **__restrict __endptr, int __base) throw () ;
+
+__extension__
+extern unsigned long long int strtouq (__const char *__restrict __nptr,
+ char **__restrict __endptr, int __base)
+ throw () ;
+
+
+
+
+
+
+__extension__
+extern long long int strtoll (__const char *__restrict __nptr,
+ char **__restrict __endptr, int __base) throw () ;
+
+__extension__
+extern unsigned long long int strtoull (__const char *__restrict __nptr,
+ char **__restrict __endptr, int __base)
+ throw () ;
+
+
+
+
+
+
+
+
+
+extern double __strtod_internal (__const char *__restrict __nptr,
+ char **__restrict __endptr, int __group)
+ throw () ;
+extern float __strtof_internal (__const char *__restrict __nptr,
+ char **__restrict __endptr, int __group)
+ throw () ;
+extern long double __strtold_internal (__const char *__restrict __nptr,
+ char **__restrict __endptr,
+ int __group) throw () ;
+
+extern long int __strtol_internal (__const char *__restrict __nptr,
+ char **__restrict __endptr,
+ int __base, int __group) throw () ;
+
+
+
+extern unsigned long int __strtoul_internal (__const char *__restrict __nptr,
+ char **__restrict __endptr,
+ int __base, int __group) throw () ;
+
+
+
+
+__extension__
+extern long long int __strtoll_internal (__const char *__restrict __nptr,
+ char **__restrict __endptr,
+ int __base, int __group) throw () ;
+
+
+
+__extension__
+extern unsigned long long int __strtoull_internal (__const char *
+ __restrict __nptr,
+ char **__restrict __endptr,
+ int __base, int __group)
+ throw () ;
+
+
+
+
+
+
+
+extern __inline double
+strtod (__const char *__restrict __nptr, char **__restrict __endptr) throw ()
+{
+ return __strtod_internal (__nptr, __endptr, 0);
+}
+extern __inline long int
+strtol (__const char *__restrict __nptr, char **__restrict __endptr,
+ int __base) throw ()
+{
+ return __strtol_internal (__nptr, __endptr, __base, 0);
+}
+extern __inline unsigned long int
+strtoul (__const char *__restrict __nptr, char **__restrict __endptr,
+ int __base) throw ()
+{
+ return __strtoul_internal (__nptr, __endptr, __base, 0);
+}
+
+
+
+
+__extension__ extern __inline long long int
+strtoq (__const char *__restrict __nptr, char **__restrict __endptr,
+ int __base) throw ()
+{
+ return __strtoll_internal (__nptr, __endptr, __base, 0);
+}
+__extension__ extern __inline unsigned long long int
+strtouq (__const char *__restrict __nptr, char **__restrict __endptr,
+ int __base) throw ()
+{
+ return __strtoull_internal (__nptr, __endptr, __base, 0);
+}
+
+
+
+__extension__ extern __inline long long int
+strtoll (__const char *__restrict __nptr, char **__restrict __endptr,
+ int __base) throw ()
+{
+ return __strtoll_internal (__nptr, __endptr, __base, 0);
+}
+__extension__ extern __inline unsigned long long int
+strtoull (__const char * __restrict __nptr, char **__restrict __endptr,
+ int __base) throw ()
+{
+ return __strtoull_internal (__nptr, __endptr, __base, 0);
+}
+
+
+extern __inline double
+atof (__const char *__nptr) throw ()
+{
+ return strtod (__nptr, (char **) __null );
+}
+extern __inline int
+atoi (__const char *__nptr) throw ()
+{
+ return (int) strtol (__nptr, (char **) __null , 10);
+}
+extern __inline long int
+atol (__const char *__nptr) throw ()
+{
+ return strtol (__nptr, (char **) __null , 10);
+}
+
+
+__extension__ extern __inline long long int
+atoll (__const char *__nptr) throw ()
+{
+ return strtoll (__nptr, (char **) __null , 10);
+}
+
+
+
+
+
+
+
+
+extern char *l64a (long int __n) throw () ;
+
+
+extern long int a64l (__const char *__s) throw () ;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern "C" {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef unsigned char __u_char;
+typedef unsigned short __u_short;
+typedef unsigned int __u_int;
+typedef unsigned long __u_long;
+
+__extension__ typedef unsigned long long int __u_quad_t;
+__extension__ typedef long long int __quad_t;
+
+typedef signed char __int8_t;
+typedef unsigned char __uint8_t;
+typedef signed short int __int16_t;
+typedef unsigned short int __uint16_t;
+typedef signed int __int32_t;
+typedef unsigned int __uint32_t;
+
+__extension__ typedef signed long long int __int64_t;
+__extension__ typedef unsigned long long int __uint64_t;
+
+typedef __quad_t *__qaddr_t;
+
+typedef __u_quad_t __dev_t;
+typedef __u_int __uid_t;
+typedef __u_int __gid_t;
+typedef __u_long __ino_t;
+typedef __u_int __mode_t;
+typedef __u_int __nlink_t;
+typedef long int __off_t;
+typedef __quad_t __loff_t;
+typedef int __pid_t;
+typedef int __ssize_t;
+typedef __u_long __rlim_t;
+typedef __u_quad_t __rlim64_t;
+typedef __u_int __id_t;
+
+typedef struct
+ {
+ int __val[2];
+ } __fsid_t;
+
+
+typedef int __daddr_t;
+typedef char *__caddr_t;
+typedef long int __time_t;
+typedef unsigned int __useconds_t;
+typedef long int __suseconds_t;
+typedef long int __swblk_t;
+
+typedef long int __clock_t;
+
+
+typedef int __clockid_t;
+
+
+typedef int __timer_t;
+
+
+
+
+
+
+typedef int __key_t;
+
+
+typedef unsigned short int __ipc_pid_t;
+
+
+
+typedef long int __blksize_t;
+
+
+
+
+typedef long int __blkcnt_t;
+typedef __quad_t __blkcnt64_t;
+
+
+typedef __u_long __fsblkcnt_t;
+typedef __u_quad_t __fsblkcnt64_t;
+
+
+typedef __u_long __fsfilcnt_t;
+typedef __u_quad_t __fsfilcnt64_t;
+
+
+typedef __u_quad_t __ino64_t;
+
+
+typedef __loff_t __off64_t;
+
+
+typedef long int __t_scalar_t;
+typedef unsigned long int __t_uscalar_t;
+
+
+typedef int __intptr_t;
+
+
+typedef unsigned int __socklen_t;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+struct __sched_param
+ {
+ int __sched_priority;
+ };
+
+
+
+
+typedef int _lt_spinlock_t;
+
+
+struct _pthread_fastlock
+{
+ long int __status;
+ _lt_spinlock_t __spinlock;
+
+};
+
+
+
+typedef struct _pthread_descr_struct *_pthread_descr;
+
+
+
+
+
+typedef struct __pthread_attr_s
+{
+ int __detachstate;
+ int __schedpolicy;
+ struct __sched_param __schedparam;
+ int __inheritsched;
+ int __scope;
+ size_t __guardsize;
+ int __stackaddr_set;
+ void *__stackaddr;
+ size_t __stacksize;
+} pthread_attr_t;
+
+
+
+typedef struct
+{
+ struct _pthread_fastlock __c_lock;
+ _pthread_descr __c_waiting;
+} pthread_cond_t;
+
+
+
+typedef struct
+{
+ int __dummy;
+} pthread_condattr_t;
+
+
+typedef unsigned int pthread_key_t;
+
+
+
+
+
+typedef struct
+{
+ int __m_reserved;
+ int __m_count;
+ _pthread_descr __m_owner;
+ int __m_kind;
+ struct _pthread_fastlock __m_lock;
+} pthread_mutex_t;
+
+
+
+typedef struct
+{
+ int __mutexkind;
+} pthread_mutexattr_t;
+
+
+
+typedef int pthread_once_t;
+
+
+
+
+
+
+
+
+typedef unsigned long int pthread_t;
+
+
+
+
+
+
+
+
+
+typedef __u_char u_char;
+typedef __u_short u_short;
+typedef __u_int u_int;
+typedef __u_long u_long;
+typedef __quad_t quad_t;
+typedef __u_quad_t u_quad_t;
+typedef __fsid_t fsid_t;
+
+
+typedef __loff_t loff_t;
+
+
+
+typedef __ino_t ino_t;
+
+
+
+
+
+
+typedef __dev_t dev_t;
+
+
+
+
+typedef __gid_t gid_t;
+
+
+
+
+typedef __mode_t mode_t;
+
+
+
+
+typedef __nlink_t nlink_t;
+
+
+
+
+typedef __uid_t uid_t;
+
+
+
+
+
+typedef __off_t off_t;
+
+
+
+
+
+
+typedef __pid_t pid_t;
+
+
+
+
+typedef __id_t id_t;
+
+
+
+
+typedef __ssize_t ssize_t;
+
+
+
+
+typedef __daddr_t daddr_t;
+typedef __caddr_t caddr_t;
+
+
+
+typedef __key_t key_t;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef __time_t time_t;
+
+
+
+
+
+
+
+
+
+
+typedef __clockid_t clockid_t;
+
+
+
+
+
+
+
+
+
+
+typedef __timer_t timer_t;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef unsigned long int ulong;
+typedef unsigned short int ushort;
+typedef unsigned int uint;
+
+
+
+
+
+
+
+
+
+
+
+
+typedef int int8_t __attribute__ ((__mode__ ( __QI__ ))) ;
+typedef int int16_t __attribute__ ((__mode__ ( __HI__ ))) ;
+typedef int int32_t __attribute__ ((__mode__ ( __SI__ ))) ;
+typedef int int64_t __attribute__ ((__mode__ ( __DI__ ))) ;
+
+
+typedef unsigned int u_int8_t __attribute__ ((__mode__ ( __QI__ ))) ;
+typedef unsigned int u_int16_t __attribute__ ((__mode__ ( __HI__ ))) ;
+typedef unsigned int u_int32_t __attribute__ ((__mode__ ( __SI__ ))) ;
+typedef unsigned int u_int64_t __attribute__ ((__mode__ ( __DI__ ))) ;
+
+typedef int register_t __attribute__ ((__mode__ (__word__)));
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef int __sig_atomic_t;
+
+
+
+
+typedef struct
+ {
+ unsigned long int __val[(1024 / (8 * sizeof (unsigned long int))) ];
+ } __sigset_t;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef __sigset_t sigset_t;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+struct timespec
+ {
+ long int tv_sec;
+ long int tv_nsec;
+ };
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+struct timeval
+ {
+ __time_t tv_sec;
+ __suseconds_t tv_usec;
+ };
+
+
+
+
+
+
+typedef long int __fd_mask;
+
+
+
+
+
+
+
+typedef struct
+ {
+
+
+
+ __fd_mask __fds_bits[1024 / (8 * sizeof (__fd_mask)) ];
+
+
+ } fd_set;
+
+
+
+
+
+
+typedef __fd_mask fd_mask;
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern "C" {
+
+
+
+
+
+
+extern int select (int __nfds, fd_set *__restrict __readfds,
+ fd_set *__restrict __writefds,
+ fd_set *__restrict __exceptfds,
+ struct timeval *__restrict __timeout) throw () ;
+
+
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef __blkcnt_t blkcnt_t;
+
+
+
+typedef __fsblkcnt_t fsblkcnt_t;
+
+
+
+typedef __fsfilcnt_t fsfilcnt_t;
+
+
+
+
+
+
+}
+
+
+
+
+
+
+
+
+
+extern long int random (void) throw () ;
+
+
+extern void srandom (unsigned int __seed) throw () ;
+
+
+
+
+
+extern char *initstate (unsigned int __seed, char *__statebuf,
+ size_t __statelen) throw () ;
+
+
+
+extern char *setstate (char *__statebuf) throw () ;
+
+
+
+
+
+
+
+struct random_data
+ {
+ int32_t *fptr;
+ int32_t *rptr;
+ int32_t *state;
+ int rand_type;
+ int rand_deg;
+ int rand_sep;
+ int32_t *end_ptr;
+ };
+
+extern int random_r (struct random_data *__restrict __buf,
+ int32_t *__restrict __result) throw () ;
+
+extern int srandom_r (unsigned int __seed, struct random_data *__buf) throw () ;
+
+extern int initstate_r (unsigned int __seed, char *__restrict __statebuf,
+ size_t __statelen,
+ struct random_data *__restrict __buf) throw () ;
+
+extern int setstate_r (char *__restrict __statebuf,
+ struct random_data *__restrict __buf) throw () ;
+
+
+
+
+
+extern int rand (void) throw () ;
+
+extern void srand (unsigned int __seed) throw () ;
+
+
+
+extern int rand_r (unsigned int *__seed) throw () ;
+
+
+
+
+
+
+
+extern double drand48 (void) throw () ;
+extern double erand48 (unsigned short int __xsubi[3]) throw () ;
+
+
+extern long int lrand48 (void) throw () ;
+extern long int nrand48 (unsigned short int __xsubi[3]) throw () ;
+
+
+extern long int mrand48 (void) throw () ;
+extern long int jrand48 (unsigned short int __xsubi[3]) throw () ;
+
+
+extern void srand48 (long int __seedval) throw () ;
+extern unsigned short int *seed48 (unsigned short int __seed16v[3]) throw () ;
+extern void lcong48 (unsigned short int __param[7]) throw () ;
+
+
+
+
+
+struct drand48_data
+ {
+ unsigned short int __x[3];
+ unsigned short int __old_x[3];
+ unsigned short int __c;
+ unsigned short int __init;
+ unsigned long long int __a;
+ };
+
+
+extern int drand48_r (struct drand48_data *__restrict __buffer,
+ double *__restrict __result) throw () ;
+extern int erand48_r (unsigned short int __xsubi[3],
+ struct drand48_data *__restrict __buffer,
+ double *__restrict __result) throw () ;
+
+
+extern int lrand48_r (struct drand48_data *__restrict __buffer,
+ long int *__restrict __result) throw () ;
+extern int nrand48_r (unsigned short int __xsubi[3],
+ struct drand48_data *__restrict __buffer,
+ long int *__restrict __result) throw () ;
+
+
+extern int mrand48_r (struct drand48_data *__restrict __buffer,
+ long int *__restrict __result) throw () ;
+extern int jrand48_r (unsigned short int __xsubi[3],
+ struct drand48_data *__restrict __buffer,
+ long int *__restrict __result) throw () ;
+
+
+extern int srand48_r (long int __seedval, struct drand48_data *__buffer)
+ throw () ;
+
+extern int seed48_r (unsigned short int __seed16v[3],
+ struct drand48_data *__buffer) throw () ;
+
+extern int lcong48_r (unsigned short int __param[7],
+ struct drand48_data *__buffer) throw () ;
+
+
+
+
+
+
+
+
+extern void *malloc (size_t __size) throw () ;
+
+extern void *calloc (size_t __nmemb, size_t __size)
+ throw () ;
+
+
+
+
+
+extern void *realloc (void *__ptr, size_t __size) throw () ;
+
+extern void free (void *__ptr) throw () ;
+
+
+
+extern void cfree (void *__ptr) throw () ;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern "C" {
+
+
+
+
+
+extern void *alloca (size_t __size) throw () ;
+
+
+
+
+
+}
+
+
+
+
+
+
+
+extern void *valloc (size_t __size) throw () ;
+
+
+
+
+
+extern void abort (void) throw () __attribute__ ((__noreturn__));
+
+
+
+extern int atexit (void (*__func) (void)) throw () ;
+
+
+
+
+extern int on_exit (void (*__func) (int __status, void *__arg), void *__arg)
+ throw () ;
+
+
+
+
+
+extern void exit (int __status) throw () __attribute__ ((__noreturn__));
+
+
+
+
+
+extern char *getenv (__const char *__name) throw () ;
+
+
+
+extern char *__secure_getenv (__const char *__name) throw () ;
+
+
+
+
+
+extern int putenv (char *__string) throw () ;
+
+
+
+
+
+extern int setenv (__const char *__name, __const char *__value, int __replace)
+ throw () ;
+
+
+extern int unsetenv (__const char *__name) throw () ;
+
+
+
+
+
+
+extern int clearenv (void) throw () ;
+
+
+
+
+
+
+
+
+extern char *mktemp (char *__template) throw () ;
+
+
+
+
+
+
+
+extern int mkstemp (char *__template) throw () ;
+
+
+
+
+
+
+
+
+
+
+extern char *mkdtemp (char *__template) throw () ;
+
+
+
+
+extern int system (__const char *__command) throw () ;
+
+
+
+
+
+
+
+
+
+
+
+extern char *realpath (__const char *__restrict __name,
+ char *__restrict __resolved) throw () ;
+
+
+
+
+
+
+typedef int (*__compar_fn_t) (__const void *, __const void *);
+
+
+
+
+
+
+extern void *bsearch (__const void *__key, __const void *__base,
+ size_t __nmemb, size_t __size, __compar_fn_t __compar);
+
+
+
+extern void qsort (void *__base, size_t __nmemb, size_t __size,
+ __compar_fn_t __compar);
+
+
+
+extern int abs (int __x) throw () __attribute__ ((__const__));
+extern long int labs (long int __x) throw () __attribute__ ((__const__));
+
+
+
+
+
+
+extern div_t div (int __numer, int __denom)
+ throw () __attribute__ ((__const__));
+extern ldiv_t ldiv (long int __numer, long int __denom)
+ throw () __attribute__ ((__const__));
+
+
+
+
+
+
+
+
+
+
+extern char *ecvt (double __value, int __ndigit, int *__restrict __decpt,
+ int *__restrict __sign) throw () ;
+
+
+
+
+extern char *fcvt (double __value, int __ndigit, int *__restrict __decpt,
+ int *__restrict __sign) throw () ;
+
+
+
+
+extern char *gcvt (double __value, int __ndigit, char *__buf) throw () ;
+
+
+
+
+extern char *qecvt (long double __value, int __ndigit,
+ int *__restrict __decpt, int *__restrict __sign) throw () ;
+extern char *qfcvt (long double __value, int __ndigit,
+ int *__restrict __decpt, int *__restrict __sign) throw () ;
+extern char *qgcvt (long double __value, int __ndigit, char *__buf) throw () ;
+
+
+
+
+extern int ecvt_r (double __value, int __ndigit, int *__restrict __decpt,
+ int *__restrict __sign, char *__restrict __buf,
+ size_t __len) throw () ;
+extern int fcvt_r (double __value, int __ndigit, int *__restrict __decpt,
+ int *__restrict __sign, char *__restrict __buf,
+ size_t __len) throw () ;
+
+extern int qecvt_r (long double __value, int __ndigit,
+ int *__restrict __decpt, int *__restrict __sign,
+ char *__restrict __buf, size_t __len) throw () ;
+extern int qfcvt_r (long double __value, int __ndigit,
+ int *__restrict __decpt, int *__restrict __sign,
+ char *__restrict __buf, size_t __len) throw () ;
+
+
+
+
+
+
+extern int mblen (__const char *__s, size_t __n) throw () ;
+
+
+extern int mbtowc (wchar_t *__restrict __pwc,
+ __const char *__restrict __s, size_t __n) throw () ;
+
+
+extern int wctomb (char *__s, wchar_t __wchar) throw () ;
+
+
+
+extern size_t mbstowcs (wchar_t *__restrict __pwcs,
+ __const char *__restrict __s, size_t __n) throw () ;
+
+extern size_t wcstombs (char *__restrict __s,
+ __const wchar_t *__restrict __pwcs, size_t __n)
+ throw () ;
+
+
+
+
+
+
+
+extern int rpmatch (__const char *__response) throw () ;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern int getloadavg (double __loadavg[], int __nelem) throw () ;
+
+
+
+
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern "C" {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern long int __sysconf (int);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef __clock_t clock_t;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+struct tm
+{
+ int tm_sec;
+ int tm_min;
+ int tm_hour;
+ int tm_mday;
+ int tm_mon;
+ int tm_year;
+ int tm_wday;
+ int tm_yday;
+ int tm_isdst;
+
+
+ long int tm_gmtoff;
+ __const char *tm_zone;
+
+};
+
+
+
+
+struct itimerspec
+ {
+ struct timespec it_interval;
+ struct timespec it_value;
+ };
+
+
+struct sigevent;
+
+
+
+
+
+
+
+
+extern clock_t clock (void) throw () ;
+
+
+extern time_t time (time_t *__timer) throw () ;
+
+
+extern double difftime (time_t __time1, time_t __time0)
+ throw () __attribute__ ((__const__));
+
+
+extern time_t mktime (struct tm *__tp) throw () ;
+
+
+
+
+
+extern size_t strftime (char *__restrict __s, size_t __maxsize,
+ __const char *__restrict __format,
+ __const struct tm *__restrict __tp) throw () ;
+
+
+
+
+
+
+extern struct tm *gmtime (__const time_t *__timer) throw () ;
+
+
+
+extern struct tm *localtime (__const time_t *__timer) throw () ;
+
+
+
+
+extern struct tm *gmtime_r (__const time_t *__restrict __timer,
+ struct tm *__restrict __tp) throw () ;
+
+
+
+extern struct tm *localtime_r (__const time_t *__restrict __timer,
+ struct tm *__restrict __tp) throw () ;
+
+
+
+
+extern char *asctime (__const struct tm *__tp) throw () ;
+
+
+extern char *ctime (__const time_t *__timer) throw () ;
+
+
+
+
+
+
+extern char *asctime_r (__const struct tm *__restrict __tp,
+ char *__restrict __buf) throw () ;
+
+
+extern char *ctime_r (__const time_t *__restrict __timer,
+ char *__restrict __buf) throw () ;
+
+
+
+
+extern char *__tzname[2];
+extern int __daylight;
+extern long int __timezone;
+
+
+
+
+extern char *tzname[2];
+
+
+
+extern void tzset (void) throw () ;
+
+
+
+extern int daylight;
+extern long int timezone;
+
+
+
+
+
+extern int stime (__const time_t *__when) throw () ;
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern time_t timegm (struct tm *__tp) throw () ;
+
+
+extern time_t timelocal (struct tm *__tp) throw () ;
+
+
+extern int dysize (int __year) throw () __attribute__ ((__const__));
+
+
+
+
+
+extern int nanosleep (__const struct timespec *__requested_time,
+ struct timespec *__remaining) throw () ;
+
+
+
+extern int clock_getres (clockid_t __clock_id, struct timespec *__res) throw () ;
+
+
+extern int clock_gettime (clockid_t __clock_id, struct timespec *__tp) throw () ;
+
+
+extern int clock_settime (clockid_t __clock_id, __const struct timespec *__tp)
+ throw () ;
+
+
+
+
+
+extern int timer_create (clockid_t __clock_id,
+ struct sigevent *__restrict __evp,
+ timer_t *__restrict __timerid) throw () ;
+
+
+extern int timer_delete (timer_t __timerid) throw () ;
+
+
+extern int timer_settime (timer_t __timerid, int __flags,
+ __const struct itimerspec *__restrict __value,
+ struct itimerspec *__restrict __ovalue) throw () ;
+
+
+extern int timer_gettime (timer_t __timerid, struct itimerspec *__value)
+ throw () ;
+
+
+extern int timer_getoverrun (timer_t __timerid) throw () ;
+
+
+
+
+
+
+
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef int ptrdiff_t;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef unsigned int wint_t;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern "C" {
+
+
+
+
+extern int __malloc_initialized;
+
+
+
+
+
+extern void * malloc (size_t __size) throw () ;
+
+
+extern void * calloc (size_t __nmemb, size_t __size) throw ()
+ ;
+
+
+
+extern void * realloc (void * __ptr,
+ size_t __size) throw ()
+ ;
+
+
+extern void free (void * __ptr) throw () ;
+
+
+extern void cfree (void * __ptr) throw () ;
+
+
+extern void * memalign (size_t __alignment, size_t __size) throw () ;
+
+
+extern void * valloc (size_t __size) throw () ;
+
+
+
+extern void * pvalloc (size_t __size) throw ()
+ ;
+
+
+
+extern void * (*__morecore) (ptrdiff_t __size) ;
+
+
+extern void * __default_morecore (ptrdiff_t __size) throw ()
+ ;
+
+
+struct mallinfo {
+ int arena;
+ int ordblks;
+ int smblks;
+ int hblks;
+ int hblkhd;
+ int usmblks;
+ int fsmblks;
+ int uordblks;
+ int fordblks;
+ int keepcost;
+};
+
+
+extern struct mallinfo mallinfo (void) throw () ;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern int mallopt (int __param, int __val) throw () ;
+
+
+
+extern int malloc_trim (size_t __pad) throw () ;
+
+
+
+extern size_t malloc_usable_size (void * __ptr) throw () ;
+
+
+extern void malloc_stats (void) throw () ;
+
+
+extern void * malloc_get_state (void) throw () ;
+
+
+
+extern int malloc_set_state (void * __ptr) throw () ;
+
+
+
+
+
+extern void (*__malloc_initialize_hook) (void) ;
+
+extern void (*__free_hook) (void * __ptr,
+ __const void * ) ;
+extern void * (*__malloc_hook) (size_t __size,
+ __const void * ) ;
+extern void * (*__realloc_hook) (void * __ptr,
+ size_t __size,
+ __const void * ) ;
+extern void * (*__memalign_hook) (size_t __alignment,
+ size_t __size,
+ __const void * ) ;
+extern void (*__after_morecore_hook) (void) ;
+
+
+extern void __malloc_check_init (void) throw () ;
+
+
+
+};
+
+
+
+
+typedef unsigned char unchar;
+
+static __inline__ void * ALLOC (int alloc)
+{
+ void *mem = malloc(alloc);
+
+ (static_cast<void> (( mem != 0 ) ? 0 : (__assert_fail ("mem != 0" , "userfs_types.h", 46, __PRETTY_FUNCTION__ ), 0))) ;
+ return mem;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef struct {
+ unsigned long fds_bits [(1024 / (8 * sizeof(unsigned long)) ) ];
+} __kernel_fd_set;
+
+
+typedef void (*__kernel_sighandler_t)(int);
+
+
+typedef int __kernel_key_t;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+struct ustat {
+ __kernel_daddr_t f_tfree;
+ __kernel_ino_t f_tinode;
+ char f_fname[6];
+ char f_fpack[6];
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef struct
+{
+ unsigned long handle;
+} up_handle;
+
+typedef unsigned long up_version;
+
+struct userfs_inode_info
+{
+ up_handle handle;
+ struct userfs_dir_ra *dir_ra;
+ up_version version;
+};
+
+
+
+
+
+
+
+
+
+
+typedef unsigned long up_credtok;
+
+struct userfs_file_info {
+ up_credtok cred_tok;
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef unsigned char Uchar;
+typedef unsigned short Ushort;
+typedef unsigned long Ulong;
+typedef unsigned long Uint;
+typedef unsigned long long Ulonglong;
+typedef long long longlong;
+
+
+__inline__ static unsigned char *encode_char(const char *ch, unsigned char *buf)
+{
+ *buf = *ch;
+ return buf+1;
+}
+
+__inline__ static unsigned char *decode_char(char *ch, unsigned char *buf)
+{
+ *ch = *buf;
+ return buf+1;
+}
+
+__inline__ static unsigned int sizeof_char(const char *c)
+{
+ (void)c;
+ return 1;
+}
+
+
+__inline__ static unsigned char *encode_Uchar(const Uchar *ch, unsigned char *buf)
+{
+ *buf = *ch;
+ return buf+1;
+}
+
+__inline__ static unsigned char *decode_Uchar(Uchar *ch, unsigned char *buf)
+{
+ *ch = *buf;
+ return buf+1;
+}
+
+__inline__ static unsigned int sizeof_Uchar(const Uchar *c)
+{
+ (void)c;
+ return 1;
+}
+
+
+__inline__ static unsigned char *encode_short(const short *sh, unsigned char *buf)
+{
+ register short sv = *sh;
+
+ buf[0] = (sv >> 8)& 0xff;
+ buf[1] = sv & 0xff;
+ return buf+2;
+}
+
+__inline__ static unsigned char *decode_short(short *sh, unsigned char *buf)
+{
+ *sh = (buf[0] << 8) | buf[1];
+ return buf+2;
+}
+
+__inline__ static unsigned int sizeof_short(const short *c)
+{
+ (void)c;
+ return 2;
+}
+
+
+__inline__ static unsigned char *encode_Ushort(const Ushort *sh, unsigned char *buf)
+{
+ register Ushort sv = *sh;
+
+ buf[0] = (sv >> 8)& 0xff;
+ buf[1] = sv & 0xff;
+ return buf+2;
+}
+
+__inline__ static unsigned char *decode_Ushort(Ushort *sh, unsigned char *buf)
+{
+ *sh = (buf[0] << 8) | buf[1];
+ return buf+2;
+}
+
+__inline__ static unsigned int sizeof_Ushort(const Ushort *c)
+{
+ (void)c;
+ return 2;
+}
+
+
+__inline__ static unsigned char *encode_long(const long *l, unsigned char *buf)
+{
+ register long lv = *l;
+
+ buf[0] = (lv >> 24) & 0xff;
+ buf[1] = (lv >> 16) & 0xff;
+ buf[2] = (lv >> 8) & 0xff;
+ buf[3] = lv & 0xff;
+ return buf+4;
+}
+
+__inline__ static unsigned char *decode_long(long *l, unsigned char *buf)
+{
+ *l = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
+ return buf+4;
+}
+
+__inline__ static unsigned int sizeof_long(const long *c)
+{
+ (void)c;
+ return 4;
+}
+
+
+__inline__ static unsigned char *encode_Ulong(const Ulong *l, unsigned char *buf)
+{
+ register Ulong lv = *l;
+
+ buf[0] = (lv >> 24) & 0xff;
+ buf[1] = (lv >> 16) & 0xff;
+ buf[2] = (lv >> 8) & 0xff;
+ buf[3] = lv & 0xff;
+ return buf+4;
+}
+
+__inline__ static unsigned char *decode_Ulong(Ulong *l, unsigned char *buf)
+{
+ *l = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
+ return buf+4;
+}
+
+__inline__ static unsigned int sizeof_Ulong(const Ulong *c)
+{
+ (void)c;
+ return 4;
+}
+
+
+__inline__ static unsigned char *encode_longlong(const long long *l,
+ unsigned char *buf)
+{
+ register long long lv = *l;
+
+ buf[0] = (lv >> 56) & 0xff;
+ buf[1] = (lv >> 48) & 0xff;
+ buf[2] = (lv >> 40) & 0xff;
+ buf[3] = (lv >> 32) & 0xff;
+ buf[4] = (lv >> 24) & 0xff;
+ buf[5] = (lv >> 16) & 0xff;
+ buf[6] = (lv >> 8) & 0xff;
+ buf[7] = lv & 0xff;
+
+ return buf+8;
+}
+
+__inline__ static unsigned char *decode_longlong(long long *l,
+ unsigned char *buf)
+{
+
+ *l = (((long long)(buf[ 0 ])) << 56)|(((long long)(buf[ 1 ])) << 48)|(((long long)(buf[ 2 ])) << 40)|(((long long)(buf[ 3 ])) << 32)|
+ (((long long)(buf[ 4 ])) << 24)|(((long long)(buf[ 5 ])) << 16)|(((long long)(buf[ 6 ])) << 8)| ((long long)(buf[ 7 ])) ;
+
+ return buf+8;
+}
+
+__inline__ static unsigned int sizeof_longlong(const long long *c)
+{
+ (void)c;
+ return 8;
+}
+
+
+__inline__ static unsigned char *encode_Ulonglong(const unsigned long long *l,
+ unsigned char *buf)
+{
+ register unsigned long long lv = *l;
+
+ buf[0] = (lv >> 56) & 0xff;
+ buf[1] = (lv >> 48) & 0xff;
+ buf[2] = (lv >> 40) & 0xff;
+ buf[3] = (lv >> 32) & 0xff;
+ buf[4] = (lv >> 24) & 0xff;
+ buf[5] = (lv >> 16) & 0xff;
+ buf[6] = (lv >> 8) & 0xff;
+ buf[7] = lv & 0xff;
+
+ return buf+8;
+}
+
+__inline__ static unsigned char *decode_Ulonglong(unsigned long long *l,
+ unsigned char *buf)
+{
+
+ *l = (((unsigned long long)(buf[ 0 ])) << 56)|(((unsigned long long)(buf[ 1 ])) << 48)|(((unsigned long long)(buf[ 2 ])) << 40)|(((unsigned long long)(buf[ 3 ])) << 32)|
+ (((unsigned long long)(buf[ 4 ])) << 24)|(((unsigned long long)(buf[ 5 ])) << 16)|(((unsigned long long)(buf[ 6 ])) << 8)| ((unsigned long long)(buf[ 7 ])) ;
+
+ return buf+8;
+}
+
+__inline__ static unsigned int sizeof_Ulonglong(const unsigned long long *c)
+{
+ (void)c;
+ return 8;
+}
+
+
+__inline__ static unsigned char *encode_void(const void *v, unsigned char *buf)
+{
+ (void)v;
+ return buf;
+}
+
+__inline__ static unsigned char *decode_void(void *v, unsigned char *buf)
+{
+ (void)v;
+ return buf;
+}
+
+__inline__ static unsigned int sizeof_void(const void *c)
+{
+ (void)c;
+ return 0;
+}
+
+
+
+__inline__ static unsigned char *encode_float(const float *f, unsigned char *buf)
+{
+ *(float *)buf = *f;
+ return buf + sizeof(float);
+}
+
+__inline__ static unsigned char *decode_float(float *f, unsigned char *buf)
+{
+ *f = *(float *)buf;
+ return buf + sizeof(float);
+}
+
+__inline__ static unsigned int sizeof_float(const float *c)
+{
+ (void)c;
+ return sizeof(float);
+}
+
+
+__inline__ static unsigned char *encode_double(const double *d, unsigned char *buf)
+{
+ *(double *)buf = *d;
+ return buf + sizeof(double);
+}
+
+__inline__ static unsigned char *decode_double(double *d, unsigned char *buf)
+{
+ *d = *(double *)buf;
+ return buf + sizeof(double);
+}
+
+__inline__ static unsigned int sizeof_double(const double *c)
+{
+ (void)c;
+ return sizeof(double);
+}
+
+
+
+
+
+
+typedef Ulong _userfs_types_001[32];
+typedef long _userfs_types_002[2];
+typedef Ulong _userfs_types_003[32];
+typedef ushort uf_uid_t;
+typedef ushort uf_gid_t;
+typedef ushort uf_nlink_t;
+typedef ushort uf_dev_t;
+typedef struct _userfs_types_S001 {
+ Ulong nelem;
+ long* elems;
+
+ int alloced;
+ void _userfs_types_S001::alloc(unsigned size) {elems = new long [size]; alloced = 1; }
+ _userfs_types_S001::_userfs_types_S001() { alloced = 0; }
+ _userfs_types_S001::~_userfs_types_S001() {
+ if (alloced) {
+ delete [] elems; alloced = 0;
+ }
+ }
+
+} _userfs_types_004;
+typedef struct
+{
+ uf_uid_t uid;
+ uf_uid_t euid;
+ uf_uid_t suid;
+ uf_uid_t gid;
+ uf_uid_t egid;
+ uf_uid_t sgid;
+ uf_uid_t umask;
+ _userfs_types_004 groups;
+} up_cred;
+typedef struct
+{
+ Ulong ia_valid;
+ umode_t ia_mode;
+ uf_uid_t ia_uid;
+ uf_gid_t ia_gid;
+ off_t ia_size;
+ time_t ia_atime;
+ time_t ia_mtime;
+ time_t ia_ctime;
+} up_iattr;
+typedef struct
+{
+ __s16 version;
+ long seq;
+ Uchar op;
+ Uchar isreq;
+ Ulong size;
+} up_preamble;
+typedef struct
+{
+ __s16 version;
+ long seq;
+ Uchar op;
+ Uchar isreq;
+ Ulong size;
+ long err_no;
+} upp_repl;
+typedef struct
+{
+ umode_t mode;
+ uf_nlink_t nlink;
+ uf_uid_t uid;
+ uf_gid_t gid;
+ off_t size;
+ time_t atime;
+ time_t mtime;
+ time_t ctime;
+ uf_dev_t rdev;
+ Ulong blksize;
+ Ulong blocks;
+} up_inode;
+typedef struct _userfs_types_S002 {
+ Ulong nelem;
+ __s8* elems;
+
+ int alloced;
+ void _userfs_types_S002::alloc(unsigned size) {elems = new __s8 [size]; alloced = 1; }
+ _userfs_types_S002::_userfs_types_S002() { alloced = 0; }
+ _userfs_types_S002::~_userfs_types_S002() {
+ if (alloced) {
+ delete [] elems; alloced = 0;
+ }
+ }
+
+} up_name;
+typedef struct
+{
+ up_inode ino;
+ up_handle handle;
+} upp_iwrite_s;
+typedef struct
+{
+ up_handle handle;
+} upp_iread_s;
+typedef struct
+{
+ up_handle handle;
+ up_inode ino;
+} upp_iread_r;
+typedef struct
+{
+ up_handle dir;
+ up_name name;
+} upp_unlink_s;
+typedef struct
+{
+ up_handle link;
+} upp_readlink_s;
+typedef struct
+{
+ up_name name;
+} upp_readlink_r;
+typedef struct
+{
+ up_handle dir;
+ up_handle link;
+ long flag;
+ long mode;
+} upp_followlink_s;
+typedef struct
+{
+ up_name path;
+} upp_followlink_r;
+typedef struct _userfs_types_S003 {
+ Ulong nelem;
+ long* elems;
+
+ int alloced;
+ void _userfs_types_S003::alloc(unsigned size) {elems = new long [size]; alloced = 1; }
+ _userfs_types_S003::_userfs_types_S003() { alloced = 0; }
+ _userfs_types_S003::~_userfs_types_S003() {
+ if (alloced) {
+ delete [] elems; alloced = 0;
+ }
+ }
+
+} _userfs_types_005;
+typedef struct
+{
+ long mode;
+ up_handle dir;
+ up_cred cred;
+ long rdev;
+ up_name name;
+} upp_create_s;
+typedef struct
+{
+ up_handle file;
+} upp_create_r;
+typedef struct
+{
+ up_handle dir;
+ up_name name;
+} upp_lookup_s;
+typedef struct
+{
+ up_handle handle;
+} upp_lookup_r;
+typedef struct
+{
+ up_handle file;
+ off_t off;
+ off_t size;
+ up_credtok ctok;
+} upp_read_s;
+typedef struct _userfs_types_S004 {
+ Ulong nelem;
+ Uchar* elems;
+
+ int alloced;
+ void _userfs_types_S004::alloc(unsigned size) {elems = new Uchar [size]; alloced = 1; }
+ _userfs_types_S004::_userfs_types_S004() { alloced = 0; }
+ _userfs_types_S004::~_userfs_types_S004() {
+ if (alloced) {
+ delete [] elems; alloced = 0;
+ }
+ }
+
+} _userfs_types_006;
+typedef struct
+{
+ _userfs_types_006 data;
+} upp_read_r;
+typedef struct _userfs_types_S005 {
+ Ulong nelem;
+ Uchar* elems;
+
+ int alloced;
+ void _userfs_types_S005::alloc(unsigned size) {elems = new Uchar [size]; alloced = 1; }
+ _userfs_types_S005::_userfs_types_S005() { alloced = 0; }
+ _userfs_types_S005::~_userfs_types_S005() {
+ if (alloced) {
+ delete [] elems; alloced = 0;
+ }
+ }
+
+} _userfs_types_007;
+typedef struct
+{
+ up_handle file;
+ off_t off;
+ up_credtok ctok;
+ _userfs_types_007 data;
+} upp_write_s;
+typedef struct
+{
+ off_t wrote;
+} upp_write_r;
+typedef struct
+{
+ up_handle dir;
+ off_t off;
+ up_credtok ctok;
+} upp_readdir_s;
+typedef struct
+{
+ up_handle file;
+ off_t off;
+ up_name name;
+} upp_readdir_r;
+typedef upp_readdir_s upp_multireaddir_s;
+typedef struct _userfs_types_S006 {
+ Ulong nelem;
+ upp_readdir_r* elems;
+
+ int alloced;
+ void _userfs_types_S006::alloc(unsigned size) {elems = new upp_readdir_r [size]; alloced = 1; }
+ _userfs_types_S006::_userfs_types_S006() { alloced = 0; }
+ _userfs_types_S006::~_userfs_types_S006() {
+ if (alloced) {
+ delete [] elems; alloced = 0;
+ }
+ }
+
+} upp_multireaddir_r;
+typedef struct
+{
+ up_handle root;
+} upp_mount_r;
+typedef struct
+{
+ up_handle handle;
+} upp_iput_s;
+typedef struct _userfs_types_S007 {
+ Ulong nelem;
+ long* elems;
+
+ int alloced;
+ void _userfs_types_S007::alloc(unsigned size) {elems = new long [size]; alloced = 1; }
+ _userfs_types_S007::_userfs_types_S007() { alloced = 0; }
+ _userfs_types_S007::~_userfs_types_S007() {
+ if (alloced) {
+ delete [] elems; alloced = 0;
+ }
+ }
+
+} _userfs_types_008;
+typedef struct
+{
+ up_cred cred;
+ up_handle file;
+} upp_open_s;
+typedef struct
+{
+ up_credtok ctok;
+} upp_open_r;
+typedef struct
+{
+ up_handle file;
+ up_credtok ctok;
+} upp_close_s;
+typedef struct _userfs_types_S008 {
+ Ulong nelem;
+ long* elems;
+
+ int alloced;
+ void _userfs_types_S008::alloc(unsigned size) {elems = new long [size]; alloced = 1; }
+ _userfs_types_S008::_userfs_types_S008() { alloced = 0; }
+ _userfs_types_S008::~_userfs_types_S008() {
+ if (alloced) {
+ delete [] elems; alloced = 0;
+ }
+ }
+
+} _userfs_types_009;
+typedef struct
+{
+ up_cred cred;
+ up_handle file;
+ long mask;
+} upp_permission_s;
+typedef struct
+{
+ up_handle odir;
+ up_name oname;
+ up_handle ndir;
+ up_name nname;
+} upp_rename_s;
+typedef struct
+{
+ up_handle ofile;
+ up_handle dir;
+ up_name name;
+} upp_link_s;
+typedef struct _userfs_types_S009 {
+ Ulong nelem;
+ long* elems;
+
+ int alloced;
+ void _userfs_types_S009::alloc(unsigned size) {elems = new long [size]; alloced = 1; }
+ _userfs_types_S009::_userfs_types_S009() { alloced = 0; }
+ _userfs_types_S009::~_userfs_types_S009() {
+ if (alloced) {
+ delete [] elems; alloced = 0;
+ }
+ }
+
+} _userfs_types_010;
+typedef struct
+{
+ up_handle dir;
+ up_name name;
+ up_name symname;
+ up_cred cred;
+} upp_symlink_s;
+typedef long _userfs_types_011[2];
+typedef struct
+{
+ __kernel_off_t bsize;
+ __kernel_off_t blocks;
+ __kernel_off_t bfree;
+ __kernel_off_t bavail;
+ __kernel_off_t files;
+ __kernel_off_t ffree;
+ _userfs_types_011 fsid;
+ __kernel_off_t namelen;
+} upp_statfs_r;
+typedef struct
+{
+ up_handle file;
+ off_t size;
+} upp_truncate_s;
+typedef struct
+{
+ up_handle handle;
+ up_iattr iattr;
+} upp_notify_change_s;
+typedef struct
+{
+ up_handle handle;
+ up_version version;
+} upp_inode_valid_s;
+typedef struct
+{
+ up_version version;
+ __s8 valid;
+} upp_inode_valid_r;
+static unsigned char *encode_char(const char *, unsigned char *);
+static unsigned char *decode_char(char *, unsigned char *);
+static unsigned int sizeof_char(const char *);
+
+static unsigned char *encode_short(const short *, unsigned char *);
+static unsigned char *decode_short(short *, unsigned char *);
+static unsigned int sizeof_short(const short *);
+
+static unsigned char *encode_long(const long *, unsigned char *);
+static unsigned char *decode_long(long *, unsigned char *);
+static unsigned int sizeof_long(const long *);
+
+static unsigned char *encode_longlong(const longlong *, unsigned char *);
+static unsigned char *decode_longlong(longlong *, unsigned char *);
+static unsigned int sizeof_longlong(const longlong *);
+
+static unsigned char *encode_float(const float *, unsigned char *);
+static unsigned char *decode_float(float *, unsigned char *);
+static unsigned int sizeof_float(const float *);
+
+static unsigned char *encode_double(const double *, unsigned char *);
+static unsigned char *decode_double(double *, unsigned char *);
+static unsigned int sizeof_double(const double *);
+
+static unsigned char *encode_void(const void *, unsigned char *);
+static unsigned char *decode_void(void *, unsigned char *);
+static unsigned int sizeof_void(const void *);
+
+static unsigned char *encode_Uchar(const Uchar *, unsigned char *);
+static unsigned char *decode_Uchar(Uchar *, unsigned char *);
+static unsigned int sizeof_Uchar(const Uchar *);
+
+static unsigned char *encode_Ushort(const Ushort *, unsigned char *);
+static unsigned char *decode_Ushort(Ushort *, unsigned char *);
+static unsigned int sizeof_Ushort(const Ushort *);
+
+static unsigned char *encode_Ulong(const Ulong *, unsigned char *);
+static unsigned char *decode_Ulong(Ulong *, unsigned char *);
+static unsigned int sizeof_Ulong(const Ulong *);
+
+static unsigned char *encode_Ulonglong(const Ulonglong *, unsigned char *);
+static unsigned char *decode_Ulonglong(Ulonglong *, unsigned char *);
+static unsigned int sizeof_Ulonglong(const Ulonglong *);
+
+unsigned char *encode_Uint(const Uint *, unsigned char *);
+unsigned char *decode_Uint(Uint *, unsigned char *);
+unsigned int sizeof_Uint(const Uint *);
+
+unsigned char *encode_int(const int *, unsigned char *);
+unsigned char *decode_int(int *, unsigned char *);
+unsigned int sizeof_int(const int *);
+
+unsigned char *encode__userfs_types_001(const _userfs_types_001 *, unsigned char *);
+unsigned char *decode__userfs_types_001(_userfs_types_001 *, unsigned char *);
+unsigned int sizeof__userfs_types_001(const _userfs_types_001 *);
+
+unsigned char *encode___kernel_fd_set(const __kernel_fd_set *, unsigned char *);
+unsigned char *decode___kernel_fd_set(__kernel_fd_set *, unsigned char *);
+unsigned int sizeof___kernel_fd_set(const __kernel_fd_set *);
+
+unsigned char *encode___kernel_key_t(const __kernel_key_t *, unsigned char *);
+unsigned char *decode___kernel_key_t(__kernel_key_t *, unsigned char *);
+unsigned int sizeof___kernel_key_t(const __kernel_key_t *);
+
+unsigned char *encode___kernel_dev_t(const __kernel_dev_t *, unsigned char *);
+unsigned char *decode___kernel_dev_t(__kernel_dev_t *, unsigned char *);
+unsigned int sizeof___kernel_dev_t(const __kernel_dev_t *);
+
+unsigned char *encode___kernel_ino_t(const __kernel_ino_t *, unsigned char *);
+unsigned char *decode___kernel_ino_t(__kernel_ino_t *, unsigned char *);
+unsigned int sizeof___kernel_ino_t(const __kernel_ino_t *);
+
+unsigned char *encode___kernel_mode_t(const __kernel_mode_t *, unsigned char *);
+unsigned char *decode___kernel_mode_t(__kernel_mode_t *, unsigned char *);
+unsigned int sizeof___kernel_mode_t(const __kernel_mode_t *);
+
+unsigned char *encode___kernel_nlink_t(const __kernel_nlink_t *, unsigned char *);
+unsigned char *decode___kernel_nlink_t(__kernel_nlink_t *, unsigned char *);
+unsigned int sizeof___kernel_nlink_t(const __kernel_nlink_t *);
+
+unsigned char *encode___kernel_off_t(const __kernel_off_t *, unsigned char *);
+unsigned char *decode___kernel_off_t(__kernel_off_t *, unsigned char *);
+unsigned int sizeof___kernel_off_t(const __kernel_off_t *);
+
+unsigned char *encode___kernel_pid_t(const __kernel_pid_t *, unsigned char *);
+unsigned char *decode___kernel_pid_t(__kernel_pid_t *, unsigned char *);
+unsigned int sizeof___kernel_pid_t(const __kernel_pid_t *);
+
+unsigned char *encode___kernel_ipc_pid_t(const __kernel_ipc_pid_t *, unsigned char *);
+unsigned char *decode___kernel_ipc_pid_t(__kernel_ipc_pid_t *, unsigned char *);
+unsigned int sizeof___kernel_ipc_pid_t(const __kernel_ipc_pid_t *);
+
+unsigned char *encode___kernel_uid_t(const __kernel_uid_t *, unsigned char *);
+unsigned char *decode___kernel_uid_t(__kernel_uid_t *, unsigned char *);
+unsigned int sizeof___kernel_uid_t(const __kernel_uid_t *);
+
+unsigned char *encode___kernel_gid_t(const __kernel_gid_t *, unsigned char *);
+unsigned char *decode___kernel_gid_t(__kernel_gid_t *, unsigned char *);
+unsigned int sizeof___kernel_gid_t(const __kernel_gid_t *);
+
+unsigned char *encode___kernel_size_t(const __kernel_size_t *, unsigned char *);
+unsigned char *decode___kernel_size_t(__kernel_size_t *, unsigned char *);
+unsigned int sizeof___kernel_size_t(const __kernel_size_t *);
+
+unsigned char *encode___kernel_ssize_t(const __kernel_ssize_t *, unsigned char *);
+unsigned char *decode___kernel_ssize_t(__kernel_ssize_t *, unsigned char *);
+unsigned int sizeof___kernel_ssize_t(const __kernel_ssize_t *);
+
+unsigned char *encode___kernel_ptrdiff_t(const __kernel_ptrdiff_t *, unsigned char *);
+unsigned char *decode___kernel_ptrdiff_t(__kernel_ptrdiff_t *, unsigned char *);
+unsigned int sizeof___kernel_ptrdiff_t(const __kernel_ptrdiff_t *);
+
+unsigned char *encode___kernel_time_t(const __kernel_time_t *, unsigned char *);
+unsigned char *decode___kernel_time_t(__kernel_time_t *, unsigned char *);
+unsigned int sizeof___kernel_time_t(const __kernel_time_t *);
+
+unsigned char *encode___kernel_suseconds_t(const __kernel_suseconds_t *, unsigned char *);
+unsigned char *decode___kernel_suseconds_t(__kernel_suseconds_t *, unsigned char *);
+unsigned int sizeof___kernel_suseconds_t(const __kernel_suseconds_t *);
+
+unsigned char *encode___kernel_clock_t(const __kernel_clock_t *, unsigned char *);
+unsigned char *decode___kernel_clock_t(__kernel_clock_t *, unsigned char *);
+unsigned int sizeof___kernel_clock_t(const __kernel_clock_t *);
+
+unsigned char *encode___kernel_daddr_t(const __kernel_daddr_t *, unsigned char *);
+unsigned char *decode___kernel_daddr_t(__kernel_daddr_t *, unsigned char *);
+unsigned int sizeof___kernel_daddr_t(const __kernel_daddr_t *);
+
+unsigned char *encode___kernel_caddr_t(const __kernel_caddr_t *, unsigned char *);
+unsigned char *decode___kernel_caddr_t(__kernel_caddr_t *, unsigned char *);
+unsigned int sizeof___kernel_caddr_t(const __kernel_caddr_t *);
+
+unsigned char *encode___kernel_uid16_t(const __kernel_uid16_t *, unsigned char *);
+unsigned char *decode___kernel_uid16_t(__kernel_uid16_t *, unsigned char *);
+unsigned int sizeof___kernel_uid16_t(const __kernel_uid16_t *);
+
+unsigned char *encode___kernel_gid16_t(const __kernel_gid16_t *, unsigned char *);
+unsigned char *decode___kernel_gid16_t(__kernel_gid16_t *, unsigned char *);
+unsigned int sizeof___kernel_gid16_t(const __kernel_gid16_t *);
+
+unsigned char *encode___kernel_uid32_t(const __kernel_uid32_t *, unsigned char *);
+unsigned char *decode___kernel_uid32_t(__kernel_uid32_t *, unsigned char *);
+unsigned int sizeof___kernel_uid32_t(const __kernel_uid32_t *);
+
+unsigned char *encode___kernel_gid32_t(const __kernel_gid32_t *, unsigned char *);
+unsigned char *decode___kernel_gid32_t(__kernel_gid32_t *, unsigned char *);
+unsigned int sizeof___kernel_gid32_t(const __kernel_gid32_t *);
+
+unsigned char *encode___kernel_old_uid_t(const __kernel_old_uid_t *, unsigned char *);
+unsigned char *decode___kernel_old_uid_t(__kernel_old_uid_t *, unsigned char *);
+unsigned int sizeof___kernel_old_uid_t(const __kernel_old_uid_t *);
+
+unsigned char *encode___kernel_old_gid_t(const __kernel_old_gid_t *, unsigned char *);
+unsigned char *decode___kernel_old_gid_t(__kernel_old_gid_t *, unsigned char *);
+unsigned int sizeof___kernel_old_gid_t(const __kernel_old_gid_t *);
+
+unsigned char *encode__userfs_types_002(const _userfs_types_002 *, unsigned char *);
+unsigned char *decode__userfs_types_002(_userfs_types_002 *, unsigned char *);
+unsigned int sizeof__userfs_types_002(const _userfs_types_002 *);
+
+unsigned char *encode___kernel_fsid_t(const __kernel_fsid_t *, unsigned char *);
+unsigned char *decode___kernel_fsid_t(__kernel_fsid_t *, unsigned char *);
+unsigned int sizeof___kernel_fsid_t(const __kernel_fsid_t *);
+
+unsigned char *encode_umode_t(const umode_t *, unsigned char *);
+unsigned char *decode_umode_t(umode_t *, unsigned char *);
+unsigned int sizeof_umode_t(const umode_t *);
+
+unsigned char *encode___s8(const __s8 *, unsigned char *);
+unsigned char *decode___s8(__s8 *, unsigned char *);
+unsigned int sizeof___s8(const __s8 *);
+
+unsigned char *encode___u8(const __u8 *, unsigned char *);
+unsigned char *decode___u8(__u8 *, unsigned char *);
+unsigned int sizeof___u8(const __u8 *);
+
+unsigned char *encode___s16(const __s16 *, unsigned char *);
+unsigned char *decode___s16(__s16 *, unsigned char *);
+unsigned int sizeof___s16(const __s16 *);
+
+unsigned char *encode___u16(const __u16 *, unsigned char *);
+unsigned char *decode___u16(__u16 *, unsigned char *);
+unsigned int sizeof___u16(const __u16 *);
+
+unsigned char *encode___s32(const __s32 *, unsigned char *);
+unsigned char *decode___s32(__s32 *, unsigned char *);
+unsigned int sizeof___s32(const __s32 *);
+
+unsigned char *encode___u32(const __u32 *, unsigned char *);
+unsigned char *decode___u32(__u32 *, unsigned char *);
+unsigned int sizeof___u32(const __u32 *);
+
+unsigned char *encode__userfs_types_003(const _userfs_types_003 *, unsigned char *);
+unsigned char *decode__userfs_types_003(_userfs_types_003 *, unsigned char *);
+unsigned int sizeof__userfs_types_003(const _userfs_types_003 *);
+
+unsigned char *encode_fd_set(const fd_set *, unsigned char *);
+unsigned char *decode_fd_set(fd_set *, unsigned char *);
+unsigned int sizeof_fd_set(const fd_set *);
+
+unsigned char *encode_dev_t(const dev_t *, unsigned char *);
+unsigned char *decode_dev_t(dev_t *, unsigned char *);
+unsigned int sizeof_dev_t(const dev_t *);
+
+unsigned char *encode_ino_t(const ino_t *, unsigned char *);
+unsigned char *decode_ino_t(ino_t *, unsigned char *);
+unsigned int sizeof_ino_t(const ino_t *);
+
+unsigned char *encode_mode_t(const mode_t *, unsigned char *);
+unsigned char *decode_mode_t(mode_t *, unsigned char *);
+unsigned int sizeof_mode_t(const mode_t *);
+
+unsigned char *encode_nlink_t(const nlink_t *, unsigned char *);
+unsigned char *decode_nlink_t(nlink_t *, unsigned char *);
+unsigned int sizeof_nlink_t(const nlink_t *);
+
+unsigned char *encode_off_t(const off_t *, unsigned char *);
+unsigned char *decode_off_t(off_t *, unsigned char *);
+unsigned int sizeof_off_t(const off_t *);
+
+unsigned char *encode_pid_t(const pid_t *, unsigned char *);
+unsigned char *decode_pid_t(pid_t *, unsigned char *);
+unsigned int sizeof_pid_t(const pid_t *);
+
+unsigned char *encode_daddr_t(const daddr_t *, unsigned char *);
+unsigned char *decode_daddr_t(daddr_t *, unsigned char *);
+unsigned int sizeof_daddr_t(const daddr_t *);
+
+unsigned char *encode_key_t(const key_t *, unsigned char *);
+unsigned char *decode_key_t(key_t *, unsigned char *);
+unsigned int sizeof_key_t(const key_t *);
+
+unsigned char *encode_suseconds_t(const suseconds_t *, unsigned char *);
+unsigned char *decode_suseconds_t(suseconds_t *, unsigned char *);
+unsigned int sizeof_suseconds_t(const suseconds_t *);
+
+unsigned char *encode_uid_t(const uid_t *, unsigned char *);
+unsigned char *decode_uid_t(uid_t *, unsigned char *);
+unsigned int sizeof_uid_t(const uid_t *);
+
+unsigned char *encode_gid_t(const gid_t *, unsigned char *);
+unsigned char *decode_gid_t(gid_t *, unsigned char *);
+unsigned int sizeof_gid_t(const gid_t *);
+
+unsigned char *encode_size_t(const size_t *, unsigned char *);
+unsigned char *decode_size_t(size_t *, unsigned char *);
+unsigned int sizeof_size_t(const size_t *);
+
+unsigned char *encode_ssize_t(const ssize_t *, unsigned char *);
+unsigned char *decode_ssize_t(ssize_t *, unsigned char *);
+unsigned int sizeof_ssize_t(const ssize_t *);
+
+unsigned char *encode_ptrdiff_t(const ptrdiff_t *, unsigned char *);
+unsigned char *decode_ptrdiff_t(ptrdiff_t *, unsigned char *);
+unsigned int sizeof_ptrdiff_t(const ptrdiff_t *);
+
+unsigned char *encode_time_t(const time_t *, unsigned char *);
+unsigned char *decode_time_t(time_t *, unsigned char *);
+unsigned int sizeof_time_t(const time_t *);
+
+unsigned char *encode_clock_t(const clock_t *, unsigned char *);
+unsigned char *decode_clock_t(clock_t *, unsigned char *);
+unsigned int sizeof_clock_t(const clock_t *);
+
+unsigned char *encode_caddr_t(const caddr_t *, unsigned char *);
+unsigned char *decode_caddr_t(caddr_t *, unsigned char *);
+unsigned int sizeof_caddr_t(const caddr_t *);
+
+unsigned char *encode_u_char(const u_char *, unsigned char *);
+unsigned char *decode_u_char(u_char *, unsigned char *);
+unsigned int sizeof_u_char(const u_char *);
+
+unsigned char *encode_u_short(const u_short *, unsigned char *);
+unsigned char *decode_u_short(u_short *, unsigned char *);
+unsigned int sizeof_u_short(const u_short *);
+
+unsigned char *encode_u_int(const u_int *, unsigned char *);
+unsigned char *decode_u_int(u_int *, unsigned char *);
+unsigned int sizeof_u_int(const u_int *);
+
+unsigned char *encode_u_long(const u_long *, unsigned char *);
+unsigned char *decode_u_long(u_long *, unsigned char *);
+unsigned int sizeof_u_long(const u_long *);
+
+unsigned char *encode_unchar(const unchar *, unsigned char *);
+unsigned char *decode_unchar(unchar *, unsigned char *);
+unsigned int sizeof_unchar(const unchar *);
+
+unsigned char *encode_ushort(const ushort *, unsigned char *);
+unsigned char *decode_ushort(ushort *, unsigned char *);
+unsigned int sizeof_ushort(const ushort *);
+
+unsigned char *encode_uint(const uint *, unsigned char *);
+unsigned char *decode_uint(uint *, unsigned char *);
+unsigned int sizeof_uint(const uint *);
+
+unsigned char *encode_ulong(const ulong *, unsigned char *);
+unsigned char *decode_ulong(ulong *, unsigned char *);
+unsigned int sizeof_ulong(const ulong *);
+
+unsigned char *encode_u_int8_t(const u_int8_t *, unsigned char *);
+unsigned char *decode_u_int8_t(u_int8_t *, unsigned char *);
+unsigned int sizeof_u_int8_t(const u_int8_t *);
+
+unsigned char *encode_int8_t(const int8_t *, unsigned char *);
+unsigned char *decode_int8_t(int8_t *, unsigned char *);
+unsigned int sizeof_int8_t(const int8_t *);
+
+unsigned char *encode_u_int16_t(const u_int16_t *, unsigned char *);
+unsigned char *decode_u_int16_t(u_int16_t *, unsigned char *);
+unsigned int sizeof_u_int16_t(const u_int16_t *);
+
+unsigned char *encode_int16_t(const int16_t *, unsigned char *);
+unsigned char *decode_int16_t(int16_t *, unsigned char *);
+unsigned int sizeof_int16_t(const int16_t *);
+
+unsigned char *encode_u_int32_t(const u_int32_t *, unsigned char *);
+unsigned char *decode_u_int32_t(u_int32_t *, unsigned char *);
+unsigned int sizeof_u_int32_t(const u_int32_t *);
+
+unsigned char *encode_int32_t(const int32_t *, unsigned char *);
+unsigned char *decode_int32_t(int32_t *, unsigned char *);
+unsigned int sizeof_int32_t(const int32_t *);
+
+unsigned char *encode_uint8_t(const uint8_t *, unsigned char *);
+unsigned char *decode_uint8_t(uint8_t *, unsigned char *);
+unsigned int sizeof_uint8_t(const uint8_t *);
+
+unsigned char *encode_uint16_t(const uint16_t *, unsigned char *);
+unsigned char *decode_uint16_t(uint16_t *, unsigned char *);
+unsigned int sizeof_uint16_t(const uint16_t *);
+
+unsigned char *encode_uint32_t(const uint32_t *, unsigned char *);
+unsigned char *decode_uint32_t(uint32_t *, unsigned char *);
+unsigned int sizeof_uint32_t(const uint32_t *);
+
+unsigned char *encode_up_handle(const up_handle *, unsigned char *);
+unsigned char *decode_up_handle(up_handle *, unsigned char *);
+unsigned int sizeof_up_handle(const up_handle *);
+
+unsigned char *encode_up_version(const up_version *, unsigned char *);
+unsigned char *decode_up_version(up_version *, unsigned char *);
+unsigned int sizeof_up_version(const up_version *);
+
+unsigned char *encode_up_credtok(const up_credtok *, unsigned char *);
+unsigned char *decode_up_credtok(up_credtok *, unsigned char *);
+unsigned int sizeof_up_credtok(const up_credtok *);
+
+unsigned char *encode_uf_uid_t(const uf_uid_t *, unsigned char *);
+unsigned char *decode_uf_uid_t(uf_uid_t *, unsigned char *);
+unsigned int sizeof_uf_uid_t(const uf_uid_t *);
+
+unsigned char *encode_uf_gid_t(const uf_gid_t *, unsigned char *);
+unsigned char *decode_uf_gid_t(uf_gid_t *, unsigned char *);
+unsigned int sizeof_uf_gid_t(const uf_gid_t *);
+
+unsigned char *encode_uf_nlink_t(const uf_nlink_t *, unsigned char *);
+unsigned char *decode_uf_nlink_t(uf_nlink_t *, unsigned char *);
+unsigned int sizeof_uf_nlink_t(const uf_nlink_t *);
+
+unsigned char *encode_uf_dev_t(const uf_dev_t *, unsigned char *);
+unsigned char *decode_uf_dev_t(uf_dev_t *, unsigned char *);
+unsigned int sizeof_uf_dev_t(const uf_dev_t *);
+
+unsigned char *encode__userfs_types_004(const _userfs_types_004 *, unsigned char *);
+unsigned char *decode__userfs_types_004(_userfs_types_004 *, unsigned char *);
+unsigned int sizeof__userfs_types_004(const _userfs_types_004 *);
+
+unsigned char *encode_up_cred(const up_cred *, unsigned char *);
+unsigned char *decode_up_cred(up_cred *, unsigned char *);
+unsigned int sizeof_up_cred(const up_cred *);
+
+unsigned char *encode_up_iattr(const up_iattr *, unsigned char *);
+unsigned char *decode_up_iattr(up_iattr *, unsigned char *);
+unsigned int sizeof_up_iattr(const up_iattr *);
+
+unsigned char *encode_up_preamble(const up_preamble *, unsigned char *);
+unsigned char *decode_up_preamble(up_preamble *, unsigned char *);
+unsigned int sizeof_up_preamble(const up_preamble *);
+
+unsigned char *encode_upp_repl(const upp_repl *, unsigned char *);
+unsigned char *decode_upp_repl(upp_repl *, unsigned char *);
+unsigned int sizeof_upp_repl(const upp_repl *);
+
+unsigned char *encode_up_inode(const up_inode *, unsigned char *);
+unsigned char *decode_up_inode(up_inode *, unsigned char *);
+unsigned int sizeof_up_inode(const up_inode *);
+
+unsigned char *encode_up_name(const up_name *, unsigned char *);
+unsigned char *decode_up_name(up_name *, unsigned char *);
+unsigned int sizeof_up_name(const up_name *);
+
+unsigned char *encode_upp_iwrite_s(const upp_iwrite_s *, unsigned char *);
+unsigned char *decode_upp_iwrite_s(upp_iwrite_s *, unsigned char *);
+unsigned int sizeof_upp_iwrite_s(const upp_iwrite_s *);
+
+unsigned char *encode_upp_iread_s(const upp_iread_s *, unsigned char *);
+unsigned char *decode_upp_iread_s(upp_iread_s *, unsigned char *);
+unsigned int sizeof_upp_iread_s(const upp_iread_s *);
+
+unsigned char *encode_upp_iread_r(const upp_iread_r *, unsigned char *);
+unsigned char *decode_upp_iread_r(upp_iread_r *, unsigned char *);
+unsigned int sizeof_upp_iread_r(const upp_iread_r *);
+
+unsigned char *encode_upp_unlink_s(const upp_unlink_s *, unsigned char *);
+unsigned char *decode_upp_unlink_s(upp_unlink_s *, unsigned char *);
+unsigned int sizeof_upp_unlink_s(const upp_unlink_s *);
+
+unsigned char *encode_upp_readlink_s(const upp_readlink_s *, unsigned char *);
+unsigned char *decode_upp_readlink_s(upp_readlink_s *, unsigned char *);
+unsigned int sizeof_upp_readlink_s(const upp_readlink_s *);
+
+unsigned char *encode_upp_readlink_r(const upp_readlink_r *, unsigned char *);
+unsigned char *decode_upp_readlink_r(upp_readlink_r *, unsigned char *);
+unsigned int sizeof_upp_readlink_r(const upp_readlink_r *);
+
+unsigned char *encode_upp_followlink_s(const upp_followlink_s *, unsigned char *);
+unsigned char *decode_upp_followlink_s(upp_followlink_s *, unsigned char *);
+unsigned int sizeof_upp_followlink_s(const upp_followlink_s *);
+
+unsigned char *encode_upp_followlink_r(const upp_followlink_r *, unsigned char *);
+unsigned char *decode_upp_followlink_r(upp_followlink_r *, unsigned char *);
+unsigned int sizeof_upp_followlink_r(const upp_followlink_r *);
+
+unsigned char *encode__userfs_types_005(const _userfs_types_005 *, unsigned char *);
+unsigned char *decode__userfs_types_005(_userfs_types_005 *, unsigned char *);
+unsigned int sizeof__userfs_types_005(const _userfs_types_005 *);
+
+unsigned char *encode_upp_create_s(const upp_create_s *, unsigned char *);
+unsigned char *decode_upp_create_s(upp_create_s *, unsigned char *);
+unsigned int sizeof_upp_create_s(const upp_create_s *);
+
+unsigned char *encode_upp_create_r(const upp_create_r *, unsigned char *);
+unsigned char *decode_upp_create_r(upp_create_r *, unsigned char *);
+unsigned int sizeof_upp_create_r(const upp_create_r *);
+
+unsigned char *encode_upp_lookup_s(const upp_lookup_s *, unsigned char *);
+unsigned char *decode_upp_lookup_s(upp_lookup_s *, unsigned char *);
+unsigned int sizeof_upp_lookup_s(const upp_lookup_s *);
+
+unsigned char *encode_upp_lookup_r(const upp_lookup_r *, unsigned char *);
+unsigned char *decode_upp_lookup_r(upp_lookup_r *, unsigned char *);
+unsigned int sizeof_upp_lookup_r(const upp_lookup_r *);
+
+unsigned char *encode_upp_read_s(const upp_read_s *, unsigned char *);
+unsigned char *decode_upp_read_s(upp_read_s *, unsigned char *);
+unsigned int sizeof_upp_read_s(const upp_read_s *);
+
+unsigned char *encode__userfs_types_006(const _userfs_types_006 *, unsigned char *);
+unsigned char *decode__userfs_types_006(_userfs_types_006 *, unsigned char *);
+unsigned int sizeof__userfs_types_006(const _userfs_types_006 *);
+
+unsigned char *encode_upp_read_r(const upp_read_r *, unsigned char *);
+unsigned char *decode_upp_read_r(upp_read_r *, unsigned char *);
+unsigned int sizeof_upp_read_r(const upp_read_r *);
+
+unsigned char *encode__userfs_types_007(const _userfs_types_007 *, unsigned char *);
+unsigned char *decode__userfs_types_007(_userfs_types_007 *, unsigned char *);
+unsigned int sizeof__userfs_types_007(const _userfs_types_007 *);
+
+unsigned char *encode_upp_write_s(const upp_write_s *, unsigned char *);
+unsigned char *decode_upp_write_s(upp_write_s *, unsigned char *);
+unsigned int sizeof_upp_write_s(const upp_write_s *);
+
+unsigned char *encode_upp_write_r(const upp_write_r *, unsigned char *);
+unsigned char *decode_upp_write_r(upp_write_r *, unsigned char *);
+unsigned int sizeof_upp_write_r(const upp_write_r *);
+
+unsigned char *encode_upp_readdir_s(const upp_readdir_s *, unsigned char *);
+unsigned char *decode_upp_readdir_s(upp_readdir_s *, unsigned char *);
+unsigned int sizeof_upp_readdir_s(const upp_readdir_s *);
+
+unsigned char *encode_upp_readdir_r(const upp_readdir_r *, unsigned char *);
+unsigned char *decode_upp_readdir_r(upp_readdir_r *, unsigned char *);
+unsigned int sizeof_upp_readdir_r(const upp_readdir_r *);
+
+unsigned char *encode_upp_multireaddir_s(const upp_multireaddir_s *, unsigned char *);
+unsigned char *decode_upp_multireaddir_s(upp_multireaddir_s *, unsigned char *);
+unsigned int sizeof_upp_multireaddir_s(const upp_multireaddir_s *);
+
+unsigned char *encode_upp_multireaddir_r(const upp_multireaddir_r *, unsigned char *);
+unsigned char *decode_upp_multireaddir_r(upp_multireaddir_r *, unsigned char *);
+unsigned int sizeof_upp_multireaddir_r(const upp_multireaddir_r *);
+
+unsigned char *encode_upp_mount_r(const upp_mount_r *, unsigned char *);
+unsigned char *decode_upp_mount_r(upp_mount_r *, unsigned char *);
+unsigned int sizeof_upp_mount_r(const upp_mount_r *);
+
+unsigned char *encode_upp_iput_s(const upp_iput_s *, unsigned char *);
+unsigned char *decode_upp_iput_s(upp_iput_s *, unsigned char *);
+unsigned int sizeof_upp_iput_s(const upp_iput_s *);
+
+unsigned char *encode__userfs_types_008(const _userfs_types_008 *, unsigned char *);
+unsigned char *decode__userfs_types_008(_userfs_types_008 *, unsigned char *);
+unsigned int sizeof__userfs_types_008(const _userfs_types_008 *);
+
+unsigned char *encode_upp_open_s(const upp_open_s *, unsigned char *);
+unsigned char *decode_upp_open_s(upp_open_s *, unsigned char *);
+unsigned int sizeof_upp_open_s(const upp_open_s *);
+
+unsigned char *encode_upp_open_r(const upp_open_r *, unsigned char *);
+unsigned char *decode_upp_open_r(upp_open_r *, unsigned char *);
+unsigned int sizeof_upp_open_r(const upp_open_r *);
+
+unsigned char *encode_upp_close_s(const upp_close_s *, unsigned char *);
+unsigned char *decode_upp_close_s(upp_close_s *, unsigned char *);
+unsigned int sizeof_upp_close_s(const upp_close_s *);
+
+unsigned char *encode__userfs_types_009(const _userfs_types_009 *, unsigned char *);
+unsigned char *decode__userfs_types_009(_userfs_types_009 *, unsigned char *);
+unsigned int sizeof__userfs_types_009(const _userfs_types_009 *);
+
+unsigned char *encode_upp_permission_s(const upp_permission_s *, unsigned char *);
+unsigned char *decode_upp_permission_s(upp_permission_s *, unsigned char *);
+unsigned int sizeof_upp_permission_s(const upp_permission_s *);
+
+unsigned char *encode_upp_rename_s(const upp_rename_s *, unsigned char *);
+unsigned char *decode_upp_rename_s(upp_rename_s *, unsigned char *);
+unsigned int sizeof_upp_rename_s(const upp_rename_s *);
+
+unsigned char *encode_upp_link_s(const upp_link_s *, unsigned char *);
+unsigned char *decode_upp_link_s(upp_link_s *, unsigned char *);
+unsigned int sizeof_upp_link_s(const upp_link_s *);
+
+unsigned char *encode__userfs_types_010(const _userfs_types_010 *, unsigned char *);
+unsigned char *decode__userfs_types_010(_userfs_types_010 *, unsigned char *);
+unsigned int sizeof__userfs_types_010(const _userfs_types_010 *);
+
+unsigned char *encode_upp_symlink_s(const upp_symlink_s *, unsigned char *);
+unsigned char *decode_upp_symlink_s(upp_symlink_s *, unsigned char *);
+unsigned int sizeof_upp_symlink_s(const upp_symlink_s *);
+
+unsigned char *encode__userfs_types_011(const _userfs_types_011 *, unsigned char *);
+unsigned char *decode__userfs_types_011(_userfs_types_011 *, unsigned char *);
+unsigned int sizeof__userfs_types_011(const _userfs_types_011 *);
+
+unsigned char *encode_upp_statfs_r(const upp_statfs_r *, unsigned char *);
+unsigned char *decode_upp_statfs_r(upp_statfs_r *, unsigned char *);
+unsigned int sizeof_upp_statfs_r(const upp_statfs_r *);
+
+unsigned char *encode_upp_truncate_s(const upp_truncate_s *, unsigned char *);
+unsigned char *decode_upp_truncate_s(upp_truncate_s *, unsigned char *);
+unsigned int sizeof_upp_truncate_s(const upp_truncate_s *);
+
+unsigned char *encode_upp_notify_change_s(const upp_notify_change_s *, unsigned char *);
+unsigned char *decode_upp_notify_change_s(upp_notify_change_s *, unsigned char *);
+unsigned int sizeof_upp_notify_change_s(const upp_notify_change_s *);
+
+unsigned char *encode_upp_inode_valid_s(const upp_inode_valid_s *, unsigned char *);
+unsigned char *decode_upp_inode_valid_s(upp_inode_valid_s *, unsigned char *);
+unsigned int sizeof_upp_inode_valid_s(const upp_inode_valid_s *);
+
+unsigned char *encode_upp_inode_valid_r(const upp_inode_valid_r *, unsigned char *);
+unsigned char *decode_upp_inode_valid_r(upp_inode_valid_r *, unsigned char *);
+unsigned int sizeof_upp_inode_valid_r(const upp_inode_valid_r *);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef enum
+{
+ userfs_up_create,
+ userfs_up_lookup,
+ userfs_up_close,
+ userfs_up_read,
+ userfs_up_write,
+ userfs_up_truncate,
+ userfs_up_fsync,
+ userfs_up_readdir,
+ userfs_up_link,
+ userfs_up_unlink,
+ userfs_up_symlink,
+ userfs_up_readlink,
+ userfs_up_followlink,
+ userfs_up_mount,
+ userfs_up_umount,
+ userfs_up_iread,
+ userfs_up_iwrite,
+ userfs_up_statfs,
+ userfs_up_iput,
+ userfs_up_open,
+ userfs_up_permission,
+ userfs_up_rename,
+ userfs_up_multireaddir,
+ userfs_up_notify_change,
+ userfs_up_inode_valid,
+} up_ops;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern "C" {
+
+
+extern void __assert_fail (__const char *__assertion, __const char *__file,
+ unsigned int __line, __const char *__function)
+ throw () __attribute__ ((__noreturn__));
+
+
+extern void __assert_perror_fail (int __errnum, __const char *__file,
+ unsigned int __line,
+ __const char *__function)
+ throw () __attribute__ ((__noreturn__));
+
+
+
+
+extern void __assert (const char *__assertion, const char *__file, int __line)
+ throw () __attribute__ ((__noreturn__));
+
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#pragma interface
+
+typedef unsigned long Handle;
+class Filesystem;
+
+class InodeList;
+class DirInode;
+
+class Inode
+{
+ friend InodeList;
+ friend DirInode;
+
+private:
+ Inode *next, *prev;
+ short alive, onlist;
+
+protected:
+
+ uid_t uid;
+ gid_t gid;
+ umode_t mode;
+ nlink_t nlink;
+ off_t size;
+ time_t atime;
+ time_t mtime;
+ time_t ctime;
+ dev_t rdev;
+
+
+ Handle handle;
+
+
+ Filesystem &filesys;
+
+ Inode *findino(Handle h);
+
+
+
+ virtual void update() {}
+
+ virtual void cleanup() {}
+public:
+ Inode(Filesystem &, Handle);
+ virtual ~Inode();
+
+ Handle gethandle() { return handle; }
+ Filesystem &getfilesys() { return filesys; }
+
+ virtual void incref() { nlink++; }
+ virtual void decref() { nlink--; }
+
+ virtual void beforeop(enum up_ops) { }
+ virtual void afterop(enum up_ops) { }
+
+ virtual int link(const char *, int, Inode *) { return 38 ; }
+ virtual int unlink(const char *, int) { return 38 ; }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+virtual int do_create (const up_preamble &, upp_repl &, const upp_create_s &, upp_create_r &) ;
+virtual int do_lookup (const up_preamble &, upp_repl &, const upp_lookup_s &, upp_lookup_r &) ;
+virtual int do_link (const up_preamble &, upp_repl &, const upp_link_s &) ;
+virtual int do_unlink (const up_preamble &, upp_repl &, const upp_unlink_s &) ;
+virtual int do_symlink (const up_preamble &, upp_repl &, const upp_symlink_s &) ;
+virtual int do_rename (const up_preamble &, upp_repl &, const upp_rename_s &) ;
+virtual int do_readlink (const up_preamble &, upp_repl &, const upp_readlink_s &, upp_readlink_r &) ;
+virtual int do_followlink (const up_preamble &, upp_repl &, const upp_followlink_s &, upp_followlink_r &) ;
+virtual int do_permission (const up_preamble &, upp_repl &, const upp_permission_s &) ;
+virtual int do_iwrite (const up_preamble &, upp_repl &, const upp_iwrite_s &) ;
+virtual int do_iread (const up_preamble &, upp_repl &, const upp_iread_s &, upp_iread_r &) ;
+virtual int do_iput (const up_preamble &, upp_repl &, const upp_iput_s &) ;
+virtual int do_notify_change (const up_preamble &, upp_repl &, const upp_notify_change_s &) ;
+virtual int do_truncate (const up_preamble &, upp_repl &, const upp_truncate_s &) ;
+virtual int do_inode_valid (const up_preamble &, upp_repl &, const upp_inode_valid_s &, upp_inode_valid_r &) ;
+
+
+
+
+
+
+
+virtual int do_read (const up_preamble &, upp_repl &, const upp_read_s &, upp_read_r &) ;
+virtual int do_write (const up_preamble &, upp_repl &, const upp_write_s &, upp_write_r &) ;
+virtual int do_readdir (const up_preamble &, upp_repl &, const upp_readdir_s &, upp_readdir_r &) ;
+virtual int do_multireaddir (const up_preamble &, upp_repl &, const upp_multireaddir_s &, upp_multireaddir_r &) ;
+virtual int do_open (const up_preamble &, upp_repl &, const upp_open_s &, upp_open_r &) ;
+virtual int do_close (const up_preamble &, upp_repl &, const upp_close_s &) ;
+
+
+
+
+
+
+
+
+
+
+};
+
+
+
+
+class InodeList
+{
+private:
+ Inode *list;
+
+public:
+ InodeList();
+ ~InodeList();
+ Inode *find(Handle);
+ void add(Inode *);
+ void del(Inode *);
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef __suseconds_t suseconds_t;
+
+
+
+
+extern "C" {
+
+
+
+
+
+
+
+struct timezone
+ {
+ int tz_minuteswest;
+ int tz_dsttime;
+ };
+
+typedef struct timezone *__restrict __timezone_ptr_t;
+
+
+
+
+
+
+
+extern int gettimeofday (struct timeval *__restrict __tv,
+ __timezone_ptr_t __tz) throw () ;
+
+
+
+
+extern int settimeofday (__const struct timeval *__tv,
+ __const struct timezone *__tz) throw () ;
+
+
+
+
+
+extern int adjtime (__const struct timeval *__delta,
+ struct timeval *__olddelta) throw () ;
+
+
+
+
+enum __itimer_which
+ {
+
+ ITIMER_REAL = 0,
+
+
+ ITIMER_VIRTUAL = 1,
+
+
+
+ ITIMER_PROF = 2
+
+ };
+
+
+
+struct itimerval
+ {
+
+ struct timeval it_interval;
+
+ struct timeval it_value;
+ };
+
+
+typedef int __itimer_which_t;
+
+
+
+
+extern int getitimer (__itimer_which_t __which,
+ struct itimerval *__value) throw () ;
+
+
+
+
+extern int setitimer (__itimer_which_t __which,
+ __const struct itimerval *__restrict __new,
+ struct itimerval *__restrict __old) throw () ;
+
+
+
+extern int utimes (__const char *__file, __const struct timeval __tvp[2])
+ throw () ;
+
+
+
+
+
+
+
+
+
+
+
+
+}
+
+
+
+
+#pragma interface
+
+class Filesystem;
+class DispatchFD;
+class DispToKern;
+
+
+
+
+
+
+
+
+
+
+class CommBase
+{
+ friend Filesystem;
+ friend DispToKern;
+
+
+ struct dispq_t
+ {
+ struct disp_fd *h, *t;
+ } dispqs[4 ];
+ int dispatches;
+
+
+ unsigned int tokern;
+
+protected:
+
+ Filesystem &filesys;
+
+ DispatchFD *req;
+
+public:
+ CommBase(Filesystem &, unsigned int to, unsigned int from);
+ virtual ~CommBase();
+
+ struct disp_fd *addDispatch(int fd, DispatchFD *dfd, int what= 1 , int pri = 2);
+ void delDispatch(struct disp_fd *);
+
+
+ int Run();
+
+
+ int DeferRepl();
+
+
+
+ void CloseFDs(int all = 0);
+};
+
+
+class DispatchFD
+{
+public:
+ virtual int dispatch(int fd, int what) = 0;
+ virtual ~DispatchFD();
+};
+
+
+class DispToKern : public DispatchFD
+{
+protected:
+ int tokern;
+public:
+ DispToKern(const CommBase *);
+};
+
+
+
+
+#pragma interface
+
+typedef unsigned char Data;
+class Comm;
+
+class Filesystem
+{
+ friend CommBase;
+ friend Inode;
+
+ const char *mpoint;
+
+ CommBase *comm_p;
+ void setcomm(CommBase *c) { comm_p = c; }
+
+protected:
+ InodeList inodes;
+ virtual int Enquire(up_ops op);
+
+ Handle rootdir;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+virtual int do_mount (const up_preamble &, upp_repl &, upp_mount_r &) ;
+virtual int do_umount (const up_preamble &, upp_repl &) ;
+virtual int do_statfs (const up_preamble &, upp_repl &, upp_statfs_r &) ;
+
+
+
+
+
+
+
+virtual int do_create (const up_preamble &, upp_repl &, const upp_create_s &, upp_create_r &) ;
+virtual int do_lookup (const up_preamble &, upp_repl &, const upp_lookup_s &, upp_lookup_r &) ;
+virtual int do_link (const up_preamble &, upp_repl &, const upp_link_s &) ;
+virtual int do_unlink (const up_preamble &, upp_repl &, const upp_unlink_s &) ;
+virtual int do_symlink (const up_preamble &, upp_repl &, const upp_symlink_s &) ;
+virtual int do_rename (const up_preamble &, upp_repl &, const upp_rename_s &) ;
+virtual int do_readlink (const up_preamble &, upp_repl &, const upp_readlink_s &, upp_readlink_r &) ;
+virtual int do_followlink (const up_preamble &, upp_repl &, const upp_followlink_s &, upp_followlink_r &) ;
+virtual int do_permission (const up_preamble &, upp_repl &, const upp_permission_s &) ;
+virtual int do_iwrite (const up_preamble &, upp_repl &, const upp_iwrite_s &) ;
+virtual int do_iread (const up_preamble &, upp_repl &, const upp_iread_s &, upp_iread_r &) ;
+virtual int do_iput (const up_preamble &, upp_repl &, const upp_iput_s &) ;
+virtual int do_notify_change (const up_preamble &, upp_repl &, const upp_notify_change_s &) ;
+virtual int do_truncate (const up_preamble &, upp_repl &, const upp_truncate_s &) ;
+virtual int do_inode_valid (const up_preamble &, upp_repl &, const upp_inode_valid_s &, upp_inode_valid_r &) ;
+
+
+
+
+
+
+
+virtual int do_read (const up_preamble &, upp_repl &, const upp_read_s &, upp_read_r &) ;
+virtual int do_write (const up_preamble &, upp_repl &, const upp_write_s &, upp_write_r &) ;
+virtual int do_readdir (const up_preamble &, upp_repl &, const upp_readdir_s &, upp_readdir_r &) ;
+virtual int do_multireaddir (const up_preamble &, upp_repl &, const upp_multireaddir_s &, upp_multireaddir_r &) ;
+virtual int do_open (const up_preamble &, upp_repl &, const upp_open_s &, upp_open_r &) ;
+virtual int do_close (const up_preamble &, upp_repl &, const upp_close_s &) ;
+
+
+
+
+
+
+
+
+
+
+
+public:
+ Filesystem(const char *mpoint);
+ virtual ~Filesystem();
+
+ Inode *findino(Handle h) { return inodes.find(h); }
+
+
+
+ int DoOp(const up_preamble &, upp_repl &, Data *data);
+
+ CommBase *comm() const { return comm_p; }
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern "C" {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef __intptr_t intptr_t;
+
+
+
+
+
+
+typedef __socklen_t socklen_t;
+
+
+
+
+
+
+
+
+
+
+
+
+extern int access (__const char *__name, int __type) throw () ;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern __off_t lseek (int __fd, __off_t __offset, int __whence) throw () ;
+
+
+
+
+extern int close (int __fd) throw () ;
+
+
+
+extern ssize_t read (int __fd, void *__buf, size_t __nbytes) throw () ;
+
+
+extern ssize_t write (int __fd, __const void *__buf, size_t __n) throw () ;
+
+
+
+
+
+
+
+extern int pipe (int __pipedes[2]) throw () ;
+
+
+
+
+
+
+
+
+extern unsigned int alarm (unsigned int __seconds) throw () ;
+
+
+
+
+
+
+
+
+extern unsigned int sleep (unsigned int __seconds) throw () ;
+
+
+
+
+
+
+extern __useconds_t ualarm (__useconds_t __value, __useconds_t __interval)
+ throw () ;
+
+
+
+extern int usleep (__useconds_t __useconds) throw () ;
+
+
+
+
+
+extern int pause (void) throw () ;
+
+
+
+extern int chown (__const char *__file, __uid_t __owner, __gid_t __group)
+ throw () ;
+
+
+
+extern int fchown (int __fd, __uid_t __owner, __gid_t __group) throw () ;
+
+
+
+
+extern int lchown (__const char *__file, __uid_t __owner, __gid_t __group)
+ throw () ;
+
+
+
+
+extern int chdir (__const char *__path) throw () ;
+
+
+
+extern int fchdir (int __fd) throw () ;
+
+
+
+
+
+
+
+
+
+extern char *getcwd (char *__buf, size_t __size) throw () ;
+
+
+
+
+
+
+
+extern char *getwd (char *__buf) throw () ;
+
+
+
+
+extern int dup (int __fd) throw () ;
+
+
+extern int dup2 (int __fd, int __fd2) throw () ;
+
+
+extern char **__environ;
+
+
+
+
+
+extern int execve (__const char *__path, char *__const __argv[],
+ char *__const __envp[]) throw () ;
+
+
+
+
+
+extern int execv (__const char *__path, char *__const __argv[]) throw () ;
+
+
+
+extern int execle (__const char *__path, __const char *__arg, ...) throw () ;
+
+
+
+extern int execl (__const char *__path, __const char *__arg, ...) throw () ;
+
+
+
+extern int execvp (__const char *__file, char *__const __argv[]) throw () ;
+
+
+
+
+extern int execlp (__const char *__file, __const char *__arg, ...) throw () ;
+
+
+
+
+extern int nice (int __inc) throw () ;
+
+
+
+
+extern void _exit (int __status) __attribute__ ((__noreturn__));
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+enum
+ {
+ _PC_LINK_MAX,
+
+ _PC_MAX_CANON,
+
+ _PC_MAX_INPUT,
+
+ _PC_NAME_MAX,
+
+ _PC_PATH_MAX,
+
+ _PC_PIPE_BUF,
+
+ _PC_CHOWN_RESTRICTED,
+
+ _PC_NO_TRUNC,
+
+ _PC_VDISABLE,
+
+ _PC_SYNC_IO,
+
+ _PC_ASYNC_IO,
+
+ _PC_PRIO_IO,
+
+ _PC_SOCK_MAXBUF,
+
+ _PC_FILESIZEBITS,
+
+ _PC_REC_INCR_XFER_SIZE,
+
+ _PC_REC_MAX_XFER_SIZE,
+
+ _PC_REC_MIN_XFER_SIZE,
+
+ _PC_REC_XFER_ALIGN
+
+ };
+
+
+enum
+ {
+ _SC_ARG_MAX,
+
+ _SC_CHILD_MAX,
+
+ _SC_CLK_TCK,
+
+ _SC_NGROUPS_MAX,
+
+ _SC_OPEN_MAX,
+
+ _SC_STREAM_MAX,
+
+ _SC_TZNAME_MAX,
+
+ _SC_JOB_CONTROL,
+
+ _SC_SAVED_IDS,
+
+ _SC_REALTIME_SIGNALS,
+
+ _SC_PRIORITY_SCHEDULING,
+
+ _SC_TIMERS,
+
+ _SC_ASYNCHRONOUS_IO,
+
+ _SC_PRIORITIZED_IO,
+
+ _SC_SYNCHRONIZED_IO,
+
+ _SC_FSYNC,
+
+ _SC_MAPPED_FILES,
+
+ _SC_MEMLOCK,
+
+ _SC_MEMLOCK_RANGE,
+
+ _SC_MEMORY_PROTECTION,
+
+ _SC_MESSAGE_PASSING,
+
+ _SC_SEMAPHORES,
+
+ _SC_SHARED_MEMORY_OBJECTS,
+
+ _SC_AIO_LISTIO_MAX,
+
+ _SC_AIO_MAX,
+
+ _SC_AIO_PRIO_DELTA_MAX,
+
+ _SC_DELAYTIMER_MAX,
+
+ _SC_MQ_OPEN_MAX,
+
+ _SC_MQ_PRIO_MAX,
+
+ _SC_VERSION,
+
+ _SC_PAGESIZE,
+
+
+ _SC_RTSIG_MAX,
+
+ _SC_SEM_NSEMS_MAX,
+
+ _SC_SEM_VALUE_MAX,
+
+ _SC_SIGQUEUE_MAX,
+
+ _SC_TIMER_MAX,
+
+
+
+
+ _SC_BC_BASE_MAX,
+
+ _SC_BC_DIM_MAX,
+
+ _SC_BC_SCALE_MAX,
+
+ _SC_BC_STRING_MAX,
+
+ _SC_COLL_WEIGHTS_MAX,
+
+ _SC_EQUIV_CLASS_MAX,
+
+ _SC_EXPR_NEST_MAX,
+
+ _SC_LINE_MAX,
+
+ _SC_RE_DUP_MAX,
+
+ _SC_CHARCLASS_NAME_MAX,
+
+
+ _SC_2_VERSION,
+
+ _SC_2_C_BIND,
+
+ _SC_2_C_DEV,
+
+ _SC_2_FORT_DEV,
+
+ _SC_2_FORT_RUN,
+
+ _SC_2_SW_DEV,
+
+ _SC_2_LOCALEDEF,
+
+
+ _SC_PII,
+
+ _SC_PII_XTI,
+
+ _SC_PII_SOCKET,
+
+ _SC_PII_INTERNET,
+
+ _SC_PII_OSI,
+
+ _SC_POLL,
+
+ _SC_SELECT,
+
+ _SC_UIO_MAXIOV,
+
+ _SC_IOV_MAX = _SC_UIO_MAXIOV ,
+
+ _SC_PII_INTERNET_STREAM,
+
+ _SC_PII_INTERNET_DGRAM,
+
+ _SC_PII_OSI_COTS,
+
+ _SC_PII_OSI_CLTS,
+
+ _SC_PII_OSI_M,
+
+ _SC_T_IOV_MAX,
+
+
+
+ _SC_THREADS,
+
+ _SC_THREAD_SAFE_FUNCTIONS,
+
+ _SC_GETGR_R_SIZE_MAX,
+
+ _SC_GETPW_R_SIZE_MAX,
+
+ _SC_LOGIN_NAME_MAX,
+
+ _SC_TTY_NAME_MAX,
+
+ _SC_THREAD_DESTRUCTOR_ITERATIONS,
+
+ _SC_THREAD_KEYS_MAX,
+
+ _SC_THREAD_STACK_MIN,
+
+ _SC_THREAD_THREADS_MAX,
+
+ _SC_THREAD_ATTR_STACKADDR,
+
+ _SC_THREAD_ATTR_STACKSIZE,
+
+ _SC_THREAD_PRIORITY_SCHEDULING,
+
+ _SC_THREAD_PRIO_INHERIT,
+
+ _SC_THREAD_PRIO_PROTECT,
+
+ _SC_THREAD_PROCESS_SHARED,
+
+
+ _SC_NPROCESSORS_CONF,
+
+ _SC_NPROCESSORS_ONLN,
+
+ _SC_PHYS_PAGES,
+
+ _SC_AVPHYS_PAGES,
+
+ _SC_ATEXIT_MAX,
+
+ _SC_PASS_MAX,
+
+
+ _SC_XOPEN_VERSION,
+
+ _SC_XOPEN_XCU_VERSION,
+
+ _SC_XOPEN_UNIX,
+
+ _SC_XOPEN_CRYPT,
+
+ _SC_XOPEN_ENH_I18N,
+
+ _SC_XOPEN_SHM,
+
+
+ _SC_2_CHAR_TERM,
+
+ _SC_2_C_VERSION,
+
+ _SC_2_UPE,
+
+
+ _SC_XOPEN_XPG2,
+
+ _SC_XOPEN_XPG3,
+
+ _SC_XOPEN_XPG4,
+
+
+ _SC_CHAR_BIT,
+
+ _SC_CHAR_MAX,
+
+ _SC_CHAR_MIN,
+
+ _SC_INT_MAX,
+
+ _SC_INT_MIN,
+
+ _SC_LONG_BIT,
+
+ _SC_WORD_BIT,
+
+ _SC_MB_LEN_MAX,
+
+ _SC_NZERO,
+
+ _SC_SSIZE_MAX,
+
+ _SC_SCHAR_MAX,
+
+ _SC_SCHAR_MIN,
+
+ _SC_SHRT_MAX,
+
+ _SC_SHRT_MIN,
+
+ _SC_UCHAR_MAX,
+
+ _SC_UINT_MAX,
+
+ _SC_ULONG_MAX,
+
+ _SC_USHRT_MAX,
+
+
+ _SC_NL_ARGMAX,
+
+ _SC_NL_LANGMAX,
+
+ _SC_NL_MSGMAX,
+
+ _SC_NL_NMAX,
+
+ _SC_NL_SETMAX,
+
+ _SC_NL_TEXTMAX,
+
+
+ _SC_XBS5_ILP32_OFF32,
+
+ _SC_XBS5_ILP32_OFFBIG,
+
+ _SC_XBS5_LP64_OFF64,
+
+ _SC_XBS5_LPBIG_OFFBIG,
+
+
+ _SC_XOPEN_LEGACY,
+
+ _SC_XOPEN_REALTIME,
+
+ _SC_XOPEN_REALTIME_THREADS,
+
+
+ _SC_ADVISORY_INFO,
+
+ _SC_BARRIERS,
+
+ _SC_BASE,
+
+ _SC_C_LANG_SUPPORT,
+
+ _SC_C_LANG_SUPPORT_R,
+
+ _SC_CLOCK_SELECTION,
+
+ _SC_CPUTIME,
+
+ _SC_THREAD_CPUTIME,
+
+ _SC_DEVICE_IO,
+
+ _SC_DEVICE_SPECIFIC,
+
+ _SC_DEVICE_SPECIFIC_R,
+
+ _SC_FD_MGMT,
+
+ _SC_FIFO,
+
+ _SC_PIPE,
+
+ _SC_FILE_ATTRIBUTES,
+
+ _SC_FILE_LOCKING,
+
+ _SC_FILE_SYSTEM,
+
+ _SC_MONOTONIC_CLOCK,
+
+ _SC_MULTIPLE_PROCESS,
+
+ _SC_SINGLE_PROCESS,
+
+ _SC_NETWORKING,
+
+ _SC_READER_WRITER_LOCKS,
+
+ _SC_SPIN_LOCKS,
+
+ _SC_REGEXP,
+
+ _SC_REGEX_VERSION,
+
+ _SC_SHELL,
+
+ _SC_SIGNALS,
+
+ _SC_SPAWN,
+
+ _SC_SPORADIC_SERVER,
+
+ _SC_THREAD_SPORADIC_SERVER,
+
+ _SC_SYSTEM_DATABASE,
+
+ _SC_SYSTEM_DATABASE_R,
+
+ _SC_TIMEOUTS,
+
+ _SC_TYPED_MEMORY_OBJECTS,
+
+ _SC_USER_GROUPS,
+
+ _SC_USER_GROUPS_R,
+
+ _SC_2_PBS,
+
+ _SC_2_PBS_ACCOUNTING,
+
+ _SC_2_PBS_LOCATE,
+
+ _SC_2_PBS_MESSAGE,
+
+ _SC_2_PBS_TRACK,
+
+ _SC_SYMLOOP,
+
+ _SC_STREAMS,
+
+ _SC_2_PBS_CHECKPOINT
+
+ };
+
+
+
+enum
+ {
+ _CS_PATH
+
+
+
+
+
+ };
+
+
+
+
+extern long int pathconf (__const char *__path, int __name) throw () ;
+
+
+extern long int fpathconf (int __fd, int __name) throw () ;
+
+
+extern long int sysconf (int __name) throw () __attribute__ ((__const__));
+
+
+
+extern size_t confstr (int __name, char *__buf, size_t __len) throw () ;
+
+
+
+
+extern __pid_t getpid (void) throw () ;
+
+
+extern __pid_t getppid (void) throw () ;
+
+
+
+
+extern __pid_t getpgrp (void) throw () ;
+
+
+
+extern __pid_t __getpgid (__pid_t __pid) throw () ;
+
+
+
+
+
+
+extern int setpgid (__pid_t __pid, __pid_t __pgid) throw () ;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern int setpgrp (void) throw () ;
+
+
+
+
+
+
+
+extern __pid_t setsid (void) throw () ;
+
+
+
+
+extern __uid_t getuid (void) throw () ;
+
+
+extern __uid_t geteuid (void) throw () ;
+
+
+extern __gid_t getgid (void) throw () ;
+
+
+extern __gid_t getegid (void) throw () ;
+
+
+
+
+extern int getgroups (int __size, __gid_t __list[]) throw () ;
+
+
+
+
+
+
+
+extern int setuid (__uid_t __uid) throw () ;
+
+
+
+
+extern int setreuid (__uid_t __ruid, __uid_t __euid) throw () ;
+
+
+
+
+extern int seteuid (__uid_t __uid) throw () ;
+
+
+
+
+
+
+extern int setgid (__gid_t __gid) throw () ;
+
+
+
+
+extern int setregid (__gid_t __rgid, __gid_t __egid) throw () ;
+
+
+
+
+extern int setegid (__gid_t __gid) throw () ;
+
+
+
+
+
+
+extern __pid_t fork (void) throw () ;
+
+
+
+
+
+
+extern __pid_t vfork (void) throw () ;
+
+
+
+
+
+extern char *ttyname (int __fd) throw () ;
+
+
+
+extern int ttyname_r (int __fd, char *__buf, size_t __buflen) throw () ;
+
+
+
+extern int isatty (int __fd) throw () ;
+
+
+
+
+extern int ttyslot (void) throw () ;
+
+
+
+
+extern int link (__const char *__from, __const char *__to) throw () ;
+
+
+
+extern int symlink (__const char *__from, __const char *__to) throw () ;
+
+
+
+
+extern int readlink (__const char *__restrict __path, char *__restrict __buf,
+ size_t __len) throw () ;
+
+
+
+extern int unlink (__const char *__name) throw () ;
+
+
+extern int rmdir (__const char *__path) throw () ;
+
+
+
+extern __pid_t tcgetpgrp (int __fd) throw () ;
+
+
+extern int tcsetpgrp (int __fd, __pid_t __pgrp_id) throw () ;
+
+
+
+extern char *getlogin (void) throw () ;
+
+
+
+
+extern int setlogin (__const char *__name) throw () ;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern "C" {
+
+
+
+
+
+
+
+
+extern char *optarg;
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern int optind;
+
+
+
+
+extern int opterr;
+
+
+
+extern int optopt;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern int getopt (int __argc, char *const *__argv, const char *__shortopts);
+
+
+
+
+
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern int gethostname (char *__name, size_t __len) throw () ;
+
+
+
+
+
+
+extern int sethostname (__const char *__name, size_t __len) throw () ;
+
+
+
+extern int sethostid (long int __id) throw () ;
+
+
+
+
+
+extern int getdomainname (char *__name, size_t __len) throw () ;
+extern int setdomainname (__const char *__name, size_t __len) throw () ;
+
+
+
+
+
+extern int vhangup (void) throw () ;
+
+
+extern int revoke (__const char *__file) throw () ;
+
+
+
+
+
+
+
+extern int profil (unsigned short int *__sample_buffer, size_t __size,
+ size_t __offset, unsigned int __scale) throw () ;
+
+
+
+
+
+extern int acct (__const char *__name) throw () ;
+
+
+
+extern char *getusershell (void) throw () ;
+extern void endusershell (void) throw () ;
+extern void setusershell (void) throw () ;
+
+
+
+
+
+extern int daemon (int __nochdir, int __noclose) throw () ;
+
+
+
+
+
+
+extern int chroot (__const char *__path) throw () ;
+
+
+
+extern char *getpass (__const char *__prompt) throw () ;
+
+
+
+
+
+extern int fsync (int __fd) throw () ;
+
+
+
+
+
+
+extern long int gethostid (void) throw () ;
+
+
+extern void sync (void) throw () ;
+
+
+
+
+extern int getpagesize (void) throw () __attribute__ ((__const__));
+
+
+
+
+extern int truncate (__const char *__file, __off_t __length) throw () ;
+
+
+
+
+
+extern int ftruncate (int __fd, __off_t __length) throw () ;
+
+
+
+
+
+
+extern int getdtablesize (void) throw () ;
+
+
+
+
+
+
+
+
+extern int brk (void *__addr) throw () ;
+
+
+
+
+
+extern void *sbrk (intptr_t __delta) throw () ;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern long int syscall (long int __sysno, ...) throw () ;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern int lockf (int __fd, int __cmd, __off_t __len) throw () ;
+
+
+
+
+
+
+
+
+
+
+extern int fdatasync (int __fildes) throw () ;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern int pthread_atfork (void (*__prepare) (void),
+ void (*__parent) (void),
+ void (*__child) (void)) throw () ;
+
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+Filesystem::Filesystem(const char *mp)
+{
+ mpoint = mp;
+ rootdir = (Handle)-1;
+}
+
+Filesystem::~Filesystem()
+{
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern "C" {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef struct _IO_FILE FILE;
+
+
+
+
+
+
+
+
+
+typedef struct _IO_FILE __FILE;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef struct
+{
+ int __count;
+ union
+ {
+ wint_t __wch;
+ char __wchb[4];
+ } __value;
+} __mbstate_t;
+
+
+
+
+
+
+
+
+
+
+
+typedef struct
+{
+ __off_t __pos;
+ __mbstate_t __state;
+} _G_fpos_t;
+typedef struct
+{
+ __off64_t __pos;
+ __mbstate_t __state;
+} _G_fpos64_t;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+enum
+{
+ __GCONV_OK = 0,
+ __GCONV_NOCONV,
+ __GCONV_NODB,
+ __GCONV_NOMEM,
+
+ __GCONV_EMPTY_INPUT,
+ __GCONV_FULL_OUTPUT,
+ __GCONV_ILLEGAL_INPUT,
+ __GCONV_INCOMPLETE_INPUT,
+
+ __GCONV_ILLEGAL_DESCRIPTOR,
+ __GCONV_INTERNAL_ERROR
+};
+
+
+
+enum
+{
+ __GCONV_IS_LAST = 0x0001,
+ __GCONV_IGNORE_ERRORS = 0x0002
+};
+
+
+
+struct __gconv_step;
+struct __gconv_step_data;
+struct __gconv_loaded_object;
+struct __gconv_trans_data;
+
+
+
+typedef int (*__gconv_fct) (struct __gconv_step *, struct __gconv_step_data *,
+ __const unsigned char **, __const unsigned char *,
+ unsigned char **, size_t *, int, int);
+
+
+typedef int (*__gconv_init_fct) (struct __gconv_step *);
+typedef void (*__gconv_end_fct) (struct __gconv_step *);
+
+
+
+typedef int (*__gconv_trans_fct) (struct __gconv_step *,
+ struct __gconv_step_data *, void *,
+ __const unsigned char *,
+ __const unsigned char **,
+ __const unsigned char *, unsigned char **,
+ size_t *);
+
+
+typedef int (*__gconv_trans_context_fct) (void *, __const unsigned char *,
+ __const unsigned char *,
+ unsigned char *, unsigned char *);
+
+
+typedef int (*__gconv_trans_query_fct) (__const char *, __const char ***,
+ size_t *);
+
+
+typedef int (*__gconv_trans_init_fct) (void **, const char *);
+typedef void (*__gconv_trans_end_fct) (void *);
+
+struct __gconv_trans_data
+{
+
+ __gconv_trans_fct __trans_fct;
+ __gconv_trans_context_fct __trans_context_fct;
+ __gconv_trans_end_fct __trans_end_fct;
+ void *__data;
+ struct __gconv_trans_data *__next;
+};
+
+
+
+struct __gconv_step
+{
+ struct __gconv_loaded_object *__shlib_handle;
+ __const char *__modname;
+
+ int __counter;
+
+ char *__from_name;
+ char *__to_name;
+
+ __gconv_fct __fct;
+ __gconv_init_fct __init_fct;
+ __gconv_end_fct __end_fct;
+
+
+
+ int __min_needed_from;
+ int __max_needed_from;
+ int __min_needed_to;
+ int __max_needed_to;
+
+
+ int __stateful;
+
+ void *__data;
+};
+
+
+
+struct __gconv_step_data
+{
+ unsigned char *__outbuf;
+ unsigned char *__outbufend;
+
+
+
+ int __flags;
+
+
+
+ int __invocation_counter;
+
+
+
+ int __internal_use;
+
+ __mbstate_t *__statep;
+ __mbstate_t __state;
+
+
+
+ struct __gconv_trans_data *__trans;
+};
+
+
+
+typedef struct __gconv_info
+{
+ size_t __nsteps;
+ struct __gconv_step *__steps;
+ __extension__ struct __gconv_step_data __data [0] ;
+} *__gconv_t;
+
+
+
+typedef union
+{
+ struct __gconv_info __cd;
+ struct
+ {
+ struct __gconv_info __cd;
+ struct __gconv_step_data __data;
+ } __combined;
+} _G_iconv_t;
+
+typedef int _G_int16_t __attribute__ ((__mode__ (__HI__)));
+typedef int _G_int32_t __attribute__ ((__mode__ (__SI__)));
+typedef unsigned int _G_uint16_t __attribute__ ((__mode__ (__HI__)));
+typedef unsigned int _G_uint32_t __attribute__ ((__mode__ (__SI__)));
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef void *__gnuc_va_list;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+struct _IO_jump_t; struct _IO_FILE;
+
+
+
+typedef void _IO_lock_t;
+
+
+
+
+
+struct _IO_marker {
+ struct _IO_marker *_next;
+ struct _IO_FILE *_sbuf;
+
+
+
+ int _pos;
+
+};
+
+
+enum __codecvt_result
+{
+ __codecvt_ok,
+ __codecvt_partial,
+ __codecvt_error,
+ __codecvt_noconv
+};
+
+
+
+struct _IO_FILE {
+ int _flags;
+
+
+
+
+ char* _IO_read_ptr;
+ char* _IO_read_end;
+ char* _IO_read_base;
+ char* _IO_write_base;
+ char* _IO_write_ptr;
+ char* _IO_write_end;
+ char* _IO_buf_base;
+ char* _IO_buf_end;
+
+ char *_IO_save_base;
+ char *_IO_backup_base;
+ char *_IO_save_end;
+
+ struct _IO_marker *_markers;
+
+ struct _IO_FILE *_chain;
+
+ int _fileno;
+ int _blksize;
+ __off_t _old_offset;
+
+
+
+ unsigned short _cur_column;
+ signed char _vtable_offset;
+ char _shortbuf[1];
+
+
+
+ _IO_lock_t *_lock;
+
+
+ __off64_t _offset;
+
+ void *__pad1;
+ void *__pad2;
+
+ int _mode;
+
+ char _unused2[15 * sizeof (int) - 2 * sizeof (void *)];
+
+};
+
+
+
+struct _IO_FILE_plus;
+
+extern struct _IO_FILE_plus _IO_2_1_stdin_;
+extern struct _IO_FILE_plus _IO_2_1_stdout_;
+extern struct _IO_FILE_plus _IO_2_1_stderr_;
+
+
+
+
+
+
+
+
+
+
+
+typedef __ssize_t __io_read_fn (void *__cookie, char *__buf, size_t __nbytes);
+
+
+
+
+
+
+
+typedef __ssize_t __io_write_fn (void *__cookie, __const char *__buf,
+ size_t __n);
+
+
+
+
+
+
+
+typedef int __io_seek_fn (void *__cookie, __off64_t *__pos, int __w);
+
+
+typedef int __io_close_fn (void *__cookie);
+
+
+
+
+
+
+extern "C" {
+
+
+extern int __underflow (_IO_FILE *) throw () ;
+extern int __uflow (_IO_FILE *) throw () ;
+extern int __overflow (_IO_FILE *, int) throw () ;
+extern wint_t __wunderflow (_IO_FILE *) throw () ;
+extern wint_t __wuflow (_IO_FILE *) throw () ;
+extern wint_t __woverflow (_IO_FILE *, wint_t ) throw () ;
+
+
+
+
+
+
+
+
+
+
+
+extern int _IO_getc (_IO_FILE *__fp) throw () ;
+extern int _IO_putc (int __c, _IO_FILE *__fp) throw () ;
+extern int _IO_feof (_IO_FILE *__fp) throw () ;
+extern int _IO_ferror (_IO_FILE *__fp) throw () ;
+
+extern int _IO_peekc_locked (_IO_FILE *__fp) throw () ;
+
+
+
+
+extern void _IO_flockfile (_IO_FILE *) throw () ;
+extern void _IO_funlockfile (_IO_FILE *) throw () ;
+extern int _IO_ftrylockfile (_IO_FILE *) throw () ;
+
+
+
+
+
+
+
+
+
+
+extern int _IO_vfscanf (_IO_FILE * __restrict, const char * __restrict,
+ __gnuc_va_list , int *__restrict) throw () ;
+extern int _IO_vfprintf (_IO_FILE *__restrict, const char *__restrict,
+ __gnuc_va_list ) throw () ;
+extern __ssize_t _IO_padn (_IO_FILE *, int, __ssize_t ) throw () ;
+extern size_t _IO_sgetn (_IO_FILE *, void *, size_t ) throw () ;
+
+extern __off64_t _IO_seekoff (_IO_FILE *, __off64_t , int, int) throw () ;
+extern __off64_t _IO_seekpos (_IO_FILE *, __off64_t , int) throw () ;
+
+extern void _IO_free_backup_area (_IO_FILE *) throw () ;
+
+
+
+
+}
+
+
+
+
+
+
+
+
+
+typedef _G_fpos_t fpos_t;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern FILE *stdin;
+extern FILE *stdout;
+extern FILE *stderr;
+
+
+
+
+
+
+extern int remove (__const char *__filename) throw () ;
+
+extern int rename (__const char *__old, __const char *__new) throw () ;
+
+
+
+
+extern FILE *tmpfile (void) throw () ;
+
+
+
+extern char *tmpnam (char *__s) throw () ;
+
+
+
+
+extern char *tmpnam_r (char *__s) throw () ;
+
+
+
+
+
+
+
+
+
+
+
+extern char *tempnam (__const char *__dir, __const char *__pfx)
+ throw () ;
+
+
+
+
+extern int fclose (FILE *__stream) throw () ;
+
+extern int fflush (FILE *__stream) throw () ;
+
+
+
+extern int fflush_unlocked (FILE *__stream) throw () ;
+
+
+
+
+
+
+
+extern FILE *fopen (__const char *__restrict __filename,
+ __const char *__restrict __modes) throw () ;
+
+extern FILE *freopen (__const char *__restrict __filename,
+ __const char *__restrict __modes,
+ FILE *__restrict __stream) throw () ;
+
+
+
+
+
+extern FILE *fdopen (int __fd, __const char *__modes) throw () ;
+
+
+
+
+
+
+
+extern void setbuf (FILE *__restrict __stream, char *__restrict __buf) throw () ;
+
+
+
+extern int setvbuf (FILE *__restrict __stream, char *__restrict __buf,
+ int __modes, size_t __n) throw () ;
+
+
+
+
+extern void setbuffer (FILE *__restrict __stream, char *__restrict __buf,
+ size_t __size) throw () ;
+
+
+extern void setlinebuf (FILE *__stream) throw () ;
+
+
+
+
+extern int fprintf (FILE *__restrict __stream,
+ __const char *__restrict __format, ...) throw () ;
+
+extern int printf (__const char *__restrict __format, ...) throw () ;
+
+extern int sprintf (char *__restrict __s,
+ __const char *__restrict __format, ...) throw () ;
+
+
+extern int vfprintf (FILE *__restrict __s, __const char *__restrict __format,
+ __gnuc_va_list __arg) throw () ;
+
+extern int vprintf (__const char *__restrict __format, __gnuc_va_list __arg)
+ throw () ;
+
+extern int vsprintf (char *__restrict __s, __const char *__restrict __format,
+ __gnuc_va_list __arg) throw () ;
+
+
+
+extern int snprintf (char *__restrict __s, size_t __maxlen,
+ __const char *__restrict __format, ...)
+ throw () __attribute__ ((__format__ (__printf__, 3, 4)));
+
+extern int vsnprintf (char *__restrict __s, size_t __maxlen,
+ __const char *__restrict __format, __gnuc_va_list __arg)
+ throw () __attribute__ ((__format__ (__printf__, 3, 0)));
+
+
+
+
+
+
+extern int fscanf (FILE *__restrict __stream,
+ __const char *__restrict __format, ...) throw () ;
+
+extern int scanf (__const char *__restrict __format, ...) throw () ;
+
+extern int sscanf (__const char *__restrict __s,
+ __const char *__restrict __format, ...) throw () ;
+
+
+
+
+
+extern int fgetc (FILE *__stream) throw () ;
+extern int getc (FILE *__stream) throw () ;
+
+
+extern int getchar (void) throw () ;
+
+
+
+
+
+
+
+extern int getc_unlocked (FILE *__stream) throw () ;
+extern int getchar_unlocked (void) throw () ;
+
+
+
+
+extern int fgetc_unlocked (FILE *__stream) throw () ;
+
+
+
+
+extern int fputc (int __c, FILE *__stream) throw () ;
+extern int putc (int __c, FILE *__stream) throw () ;
+
+
+extern int putchar (int __c) throw () ;
+
+
+
+
+
+
+
+extern int fputc_unlocked (int __c, FILE *__stream) throw () ;
+
+
+
+
+extern int putc_unlocked (int __c, FILE *__stream) throw () ;
+extern int putchar_unlocked (int __c) throw () ;
+
+
+
+
+
+extern int getw (FILE *__stream) throw () ;
+
+
+extern int putw (int __w, FILE *__stream) throw () ;
+
+
+
+
+extern char *fgets (char *__restrict __s, int __n, FILE *__restrict __stream)
+ throw () ;
+
+
+
+
+
+extern char *gets (char *__s) throw () ;
+
+
+
+
+
+
+extern int fputs (__const char *__restrict __s, FILE *__restrict __stream)
+ throw () ;
+
+
+
+
+extern int puts (__const char *__s) throw () ;
+
+
+
+extern int ungetc (int __c, FILE *__stream) throw () ;
+
+
+
+extern size_t fread (void *__restrict __ptr, size_t __size,
+ size_t __n, FILE *__restrict __stream) throw () ;
+
+extern size_t fwrite (__const void *__restrict __ptr, size_t __size,
+ size_t __n, FILE *__restrict __s) throw () ;
+
+
+
+extern size_t fread_unlocked (void *__restrict __ptr, size_t __size,
+ size_t __n, FILE *__restrict __stream) throw () ;
+extern size_t fwrite_unlocked (__const void *__restrict __ptr, size_t __size,
+ size_t __n, FILE *__restrict __stream) throw () ;
+
+
+
+
+extern int fseek (FILE *__stream, long int __off, int __whence) throw () ;
+
+extern long int ftell (FILE *__stream) throw () ;
+
+extern void rewind (FILE *__stream) throw () ;
+
+
+
+
+
+
+
+
+
+
+extern int fgetpos (FILE *__restrict __stream, fpos_t *__restrict __pos)
+ throw () ;
+
+extern int fsetpos (FILE *__stream, __const fpos_t *__pos) throw () ;
+
+
+
+
+
+extern void clearerr (FILE *__stream) throw () ;
+
+extern int feof (FILE *__stream) throw () ;
+
+extern int ferror (FILE *__stream) throw () ;
+
+
+
+extern void clearerr_unlocked (FILE *__stream) throw () ;
+extern int feof_unlocked (FILE *__stream) throw () ;
+extern int ferror_unlocked (FILE *__stream) throw () ;
+
+
+
+
+extern void perror (__const char *__s) throw () ;
+
+
+
+
+extern int sys_nerr;
+extern __const char *__const sys_errlist[];
+
+
+
+
+
+
+extern int fileno (FILE *__stream) throw () ;
+
+
+
+
+extern int fileno_unlocked (FILE *__stream) throw () ;
+
+
+
+
+
+extern FILE *popen (__const char *__command, __const char *__modes) throw () ;
+
+
+extern int pclose (FILE *__stream) throw () ;
+
+
+
+
+
+extern char *ctermid (char *__s) throw () ;
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern void flockfile (FILE *__stream) throw () ;
+
+
+
+extern int ftrylockfile (FILE *__stream) throw () ;
+
+
+extern void funlockfile (FILE *__stream) throw () ;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+inline int
+vprintf (__const char *__restrict __fmt, __gnuc_va_list __arg) throw ()
+{
+ return vfprintf (stdout , __fmt, __arg);
+}
+
+
+inline int
+getchar (void) throw ()
+{
+ return _IO_getc (stdin );
+}
+
+
+
+
+inline int
+getc_unlocked (FILE *__fp) throw ()
+{
+ return (( __fp )->_IO_read_ptr >= ( __fp )->_IO_read_end ? __uflow ( __fp ) : *(unsigned char *) ( __fp )->_IO_read_ptr++) ;
+}
+
+
+inline int
+getchar_unlocked (void) throw ()
+{
+ return (( stdin )->_IO_read_ptr >= ( stdin )->_IO_read_end ? __uflow ( stdin ) : *(unsigned char *) ( stdin )->_IO_read_ptr++) ;
+}
+
+
+
+
+inline int
+putchar (int __c) throw ()
+{
+ return _IO_putc (__c, stdout );
+}
+
+
+
+
+inline int
+fputc_unlocked (int __c, FILE *__stream) throw ()
+{
+ return ((( __stream )->_IO_write_ptr >= ( __stream )->_IO_write_end) ? __overflow ( __stream , (unsigned char) ( __c )) : (unsigned char) (*( __stream )->_IO_write_ptr++ = ( __c ))) ;
+}
+
+
+
+
+
+inline int
+putc_unlocked (int __c, FILE *__stream) throw ()
+{
+ return ((( __stream )->_IO_write_ptr >= ( __stream )->_IO_write_end) ? __overflow ( __stream , (unsigned char) ( __c )) : (unsigned char) (*( __stream )->_IO_write_ptr++ = ( __c ))) ;
+}
+
+
+inline int
+putchar_unlocked (int __c) throw ()
+{
+ return ((( stdout )->_IO_write_ptr >= ( stdout )->_IO_write_end) ? __overflow ( stdout , (unsigned char) ( __c )) : (unsigned char) (*( stdout )->_IO_write_ptr++ = ( __c ))) ;
+}
+
+
+
+
+
+
+
+
+inline int
+feof_unlocked (FILE *__stream) throw ()
+{
+ return ((( __stream )->_flags & 0x10 ) != 0) ;
+}
+
+
+inline int
+ferror_unlocked (FILE *__stream) throw ()
+{
+ return ((( __stream )->_flags & 0x20 ) != 0) ;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
+
+
+
+
+
+
+
+static void genrepl(const up_preamble &pre, upp_repl &repl)
+{
+ repl.size = 0;
+ repl.err_no = 0;
+ repl.isreq = 0 ;
+ repl.seq = pre.seq;
+ repl.op = pre.op;
+ repl.version = 16 ;
+}
+
+int
+Filesystem::DoOp(const up_preamble &pre, upp_repl &repl, Data *data)
+{
+ int err;
+
+ ;
+ { int eq_ = (( pre.isreq == 2 ) || ( pre.isreq == 1 )); if (!eq_) { fprintf(stderr , "Check failed :""pre.isreq == UP_ENQ""(%d)""||""pre.isreq == UP_REQ""(%d)\n", ( pre.isreq == 2 ), ( pre.isreq == 1 )); } } ;
+ { int eq_ = (( pre.version ) == ( 16 )); if (!eq_) { fprintf(stderr , "Check failed :""pre.version""(%d)""==""UP_VERSION""(%d)\n", ( pre.version ), ( 16 )); } } ;
+
+ genrepl(pre, repl);
+
+ if (pre.isreq == 2 )
+ {
+ repl.err_no = Enquire((up_ops)pre.op);
+ return 1;
+ }
+
+ switch(pre.op)
+ {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+case up_mount : { ; upp_mount_r ret; err = do_mount (pre, repl, ret); if (!err) repl.size = encode_upp_mount_r(&ret, data) - data; break; } ;
+case up_umount : ; err = do_umount (pre, repl); break; ;
+case up_statfs : { ; upp_statfs_r ret; err = do_statfs (pre, repl, ret); if (!err) repl.size = encode_upp_statfs_r(&ret, data) - data; break; } ;
+
+
+
+
+
+
+
+case up_create : { ; upp_create_s arg; upp_create_r ret; decode_upp_create_s(&arg, data); err = do_create (pre, repl, arg, ret); if (!err) repl.size = encode_upp_create_r(&ret, data) - data; break; } ;
+case up_lookup : { ; upp_lookup_s arg; upp_lookup_r ret; decode_upp_lookup_s(&arg, data); err = do_lookup (pre, repl, arg, ret); if (!err) repl.size = encode_upp_lookup_r(&ret, data) - data; break; } ;
+case up_link : { ; upp_link_s arg; decode_upp_link_s(&arg, data); err = do_link (pre, repl, arg); break; } ;
+case up_unlink : { ; upp_unlink_s arg; decode_upp_unlink_s(&arg, data); err = do_unlink (pre, repl, arg); break; } ;
+case up_symlink : { ; upp_symlink_s arg; decode_upp_symlink_s(&arg, data); err = do_symlink (pre, repl, arg); break; } ;
+case up_rename : { ; upp_rename_s arg; decode_upp_rename_s(&arg, data); err = do_rename (pre, repl, arg); break; } ;
+case up_readlink : { ; upp_readlink_s arg; upp_readlink_r ret; decode_upp_readlink_s(&arg, data); err = do_readlink (pre, repl, arg, ret); if (!err) repl.size = encode_upp_readlink_r(&ret, data) - data; break; } ;
+case up_followlink : { ; upp_followlink_s arg; upp_followlink_r ret; decode_upp_followlink_s(&arg, data); err = do_followlink (pre, repl, arg, ret); if (!err) repl.size = encode_upp_followlink_r(&ret, data) - data; break; } ;
+case up_permission : { ; upp_permission_s arg; decode_upp_permission_s(&arg, data); err = do_permission (pre, repl, arg); break; } ;
+case up_iwrite : { ; upp_iwrite_s arg; decode_upp_iwrite_s(&arg, data); err = do_iwrite (pre, repl, arg); break; } ;
+case up_iread : { ; upp_iread_s arg; upp_iread_r ret; decode_upp_iread_s(&arg, data); err = do_iread (pre, repl, arg, ret); if (!err) repl.size = encode_upp_iread_r(&ret, data) - data; break; } ;
+case up_iput : { ; upp_iput_s arg; decode_upp_iput_s(&arg, data); err = do_iput (pre, repl, arg); break; } ;
+case up_notify_change : { ; upp_notify_change_s arg; decode_upp_notify_change_s(&arg, data); err = do_notify_change (pre, repl, arg); break; } ;
+case up_truncate : { ; upp_truncate_s arg; decode_upp_truncate_s(&arg, data); err = do_truncate (pre, repl, arg); break; } ;
+case up_inode_valid : { ; upp_inode_valid_s arg; upp_inode_valid_r ret; decode_upp_inode_valid_s(&arg, data); err = do_inode_valid (pre, repl, arg, ret); if (!err) repl.size = encode_upp_inode_valid_r(&ret, data) - data; break; } ;
+
+
+
+
+
+
+
+case up_read : { ; upp_read_s arg; upp_read_r ret; decode_upp_read_s(&arg, data); err = do_read (pre, repl, arg, ret); if (!err) repl.size = encode_upp_read_r(&ret, data) - data; break; } ;
+case up_write : { ; upp_write_s arg; upp_write_r ret; decode_upp_write_s(&arg, data); err = do_write (pre, repl, arg, ret); if (!err) repl.size = encode_upp_write_r(&ret, data) - data; break; } ;
+case up_readdir : { ; upp_readdir_s arg; upp_readdir_r ret; decode_upp_readdir_s(&arg, data); err = do_readdir (pre, repl, arg, ret); if (!err) repl.size = encode_upp_readdir_r(&ret, data) - data; break; } ;
+case up_multireaddir : { ; upp_multireaddir_s arg; upp_multireaddir_r ret; decode_upp_multireaddir_s(&arg, data); err = do_multireaddir (pre, repl, arg, ret); if (!err) repl.size = encode_upp_multireaddir_r(&ret, data) - data; break; } ;
+case up_open : { ; upp_open_s arg; upp_open_r ret; decode_upp_open_s(&arg, data); err = do_open (pre, repl, arg, ret); if (!err) repl.size = encode_upp_open_r(&ret, data) - data; break; } ;
+case up_close : { ; upp_close_s arg; decode_upp_close_s(&arg, data); err = do_close (pre, repl, arg); break; } ;
+
+
+
+
+
+
+
+
+
+
+
+ default:
+ err = 38 ;
+ break;
+ }
+
+ if (err == -1)
+ return -1;
+
+ if (err != 0)
+ {
+ { int eq_ = (( (int)repl.size ) == ( 0 )); if (!eq_) { fprintf(stderr , "Check failed :""(int)repl.size""(%d)""==""0""(%d)\n", ( (int)repl.size ), ( 0 )); } } ;
+ repl.size = 0;
+ repl.err_no = err;
+ }
+
+ return 1;
+}
+
+int
+Filesystem::Enquire(up_ops)
+{
+ return 38 ;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+int Filesystem::do_mount (const up_preamble &, upp_repl &, upp_mount_r &) { return 38 ; } ;
+int Filesystem::do_umount (const up_preamble &, upp_repl &) { return 38 ; } ;
+int Filesystem::do_statfs (const up_preamble &, upp_repl &, upp_statfs_r &) { return 38 ; } ;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+int Filesystem::do_create (const up_preamble &pre, upp_repl &repl, const upp_create_s &arg, upp_create_r &ret) { ; Inode *ino = inodes.find(arg. dir .handle); if (ino == __null ) return 22 ; ino->beforeop(up_create ); int r = ino->do_create (pre, repl, arg, ret); ino->afterop(up_create ); return r; } ;
+int Filesystem::do_lookup (const up_preamble &pre, upp_repl &repl, const upp_lookup_s &arg, upp_lookup_r &ret) { ; Inode *ino = inodes.find(arg. dir .handle); if (ino == __null ) return 22 ; ino->beforeop(up_lookup ); int r = ino->do_lookup (pre, repl, arg, ret); ino->afterop(up_lookup ); return r; } ;
+int Filesystem::do_link (const up_preamble &pre, upp_repl &repl, const upp_link_s &arg) { ; Inode *ino = inodes.find(arg. dir .handle); if (ino == __null ) return 22 ; ino->beforeop(up_link ); int ret = ino->do_link (pre, repl, arg); ino->afterop(up_link ); return ret; } ;
+int Filesystem::do_unlink (const up_preamble &pre, upp_repl &repl, const upp_unlink_s &arg) { ; Inode *ino = inodes.find(arg. dir .handle); if (ino == __null ) return 22 ; ino->beforeop(up_unlink ); int ret = ino->do_unlink (pre, repl, arg); ino->afterop(up_unlink ); return ret; } ;
+int Filesystem::do_symlink (const up_preamble &pre, upp_repl &repl, const upp_symlink_s &arg) { ; Inode *ino = inodes.find(arg. dir .handle); if (ino == __null ) return 22 ; ino->beforeop(up_symlink ); int ret = ino->do_symlink (pre, repl, arg); ino->afterop(up_symlink ); return ret; } ;
+int Filesystem::do_rename (const up_preamble &pre, upp_repl &repl, const upp_rename_s &arg) { ; Inode *ino = inodes.find(arg. odir .handle); if (ino == __null ) return 22 ; ino->beforeop(up_rename ); int ret = ino->do_rename (pre, repl, arg); ino->afterop(up_rename ); return ret; } ;
+int Filesystem::do_readlink (const up_preamble &pre, upp_repl &repl, const upp_readlink_s &arg, upp_readlink_r &ret) { ; Inode *ino = inodes.find(arg. link .handle); if (ino == __null ) return 22 ; ino->beforeop(up_readlink ); int r = ino->do_readlink (pre, repl, arg, ret); ino->afterop(up_readlink ); return r; } ;
+int Filesystem::do_followlink (const up_preamble &pre, upp_repl &repl, const upp_followlink_s &arg, upp_followlink_r &ret) { ; Inode *ino = inodes.find(arg. link .handle); if (ino == __null ) return 22 ; ino->beforeop(up_followlink ); int r = ino->do_followlink (pre, repl, arg, ret); ino->afterop(up_followlink ); return r; } ;
+int Filesystem::do_permission (const up_preamble &pre, upp_repl &repl, const upp_permission_s &arg) { ; Inode *ino = inodes.find(arg. file .handle); if (ino == __null ) return 22 ; ino->beforeop(up_permission ); int ret = ino->do_permission (pre, repl, arg); ino->afterop(up_permission ); return ret; } ;
+int Filesystem::do_iwrite (const up_preamble &pre, upp_repl &repl, const upp_iwrite_s &arg) { ; Inode *ino = inodes.find(arg. handle .handle); if (ino == __null ) return 22 ; ino->beforeop(up_iwrite ); int ret = ino->do_iwrite (pre, repl, arg); ino->afterop(up_iwrite ); return ret; } ;
+int Filesystem::do_iread (const up_preamble &pre, upp_repl &repl, const upp_iread_s &arg, upp_iread_r &ret) { ; Inode *ino = inodes.find(arg. handle .handle); if (ino == __null ) return 22 ; ino->beforeop(up_iread ); int r = ino->do_iread (pre, repl, arg, ret); ino->afterop(up_iread ); return r; } ;
+int Filesystem::do_notify_change (const up_preamble &pre, upp_repl &repl, const upp_notify_change_s &arg) { ; Inode *ino = inodes.find(arg. handle .handle); if (ino == __null ) return 22 ; ino->beforeop(up_notify_change ); int ret = ino->do_notify_change (pre, repl, arg); ino->afterop(up_notify_change ); return ret; } ;
+int Filesystem::do_iput (const up_preamble &pre, upp_repl &repl, const upp_iput_s &arg) { ; Inode *ino = inodes.find(arg. handle .handle); if (ino == __null ) return 22 ; ino->beforeop(up_iput ); int ret = ino->do_iput (pre, repl, arg); ino->afterop(up_iput ); return ret; } ;
+
+int Filesystem::do_read (const up_preamble &pre, upp_repl &repl, const upp_read_s &arg, upp_read_r &ret) { ; Inode *ino = inodes.find(arg. file .handle); if (ino == __null ) return 22 ; ino->beforeop(up_read ); int r = ino->do_read (pre, repl, arg, ret); ino->afterop(up_read ); return r; } ;
+int Filesystem::do_write (const up_preamble &pre, upp_repl &repl, const upp_write_s &arg, upp_write_r &ret) { ; Inode *ino = inodes.find(arg. file .handle); if (ino == __null ) return 22 ; ino->beforeop(up_write ); int r = ino->do_write (pre, repl, arg, ret); ino->afterop(up_write ); return r; } ;
+int Filesystem::do_readdir (const up_preamble &pre, upp_repl &repl, const upp_readdir_s &arg, upp_readdir_r &ret) { ; Inode *ino = inodes.find(arg. dir .handle); if (ino == __null ) return 22 ; ino->beforeop(up_readdir ); int r = ino->do_readdir (pre, repl, arg, ret); ino->afterop(up_readdir ); return r; } ;
+int Filesystem::do_multireaddir (const up_preamble &pre, upp_repl &repl, const upp_multireaddir_s &arg, upp_multireaddir_r &ret) { ; Inode *ino = inodes.find(arg. dir .handle); if (ino == __null ) return 22 ; ino->beforeop(up_multireaddir ); int r = ino->do_multireaddir (pre, repl, arg, ret); ino->afterop(up_multireaddir ); return r; } ;
+int Filesystem::do_open (const up_preamble &pre, upp_repl &repl, const upp_open_s &arg, upp_open_r &ret) { ; Inode *ino = inodes.find(arg. file .handle); if (ino == __null ) return 22 ; ino->beforeop(up_open ); int r = ino->do_open (pre, repl, arg, ret); ino->afterop(up_open ); return r; } ;
+int Filesystem::do_close (const up_preamble &pre, upp_repl &repl, const upp_close_s &arg) { ; Inode *ino = inodes.find(arg. file .handle); if (ino == __null ) return 22 ; ino->beforeop(up_close ); int ret = ino->do_close (pre, repl, arg); ino->afterop(up_close ); return ret; } ;
+int Filesystem::do_truncate (const up_preamble &pre, upp_repl &repl, const upp_truncate_s &arg) { ; Inode *ino = inodes.find(arg. file .handle); if (ino == __null ) return 22 ; ino->beforeop(up_truncate ); int ret = ino->do_truncate (pre, repl, arg); ino->afterop(up_truncate ); return ret; } ;
+int Filesystem::do_inode_valid (const up_preamble &pre, upp_repl &repl, const upp_inode_valid_s &arg, upp_inode_valid_r &ret) { ; Inode *ino = inodes.find(arg. handle .handle); if (ino == __null ) return 22 ; ino->beforeop(up_inode_valid ); int r = ino->do_inode_valid (pre, repl, arg, ret); ino->afterop(up_inode_valid ); return r; } ;
Added: trunk/lib/dbg.h
==============================================================================
--- trunk/lib/dbg.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/lib/dbg.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,11 @@
+// -*- C++ -*-
+// Just a stub
+
+#ifdef DEBUG
+#include <stdio.h>
+#define LOG(x) fprintf(stderr, __FILE__":%d: %s\n", __LINE__, x)
+#define DB(x) x
+#else
+#define LOG(x)
+#define DB(x)
+#endif
Added: trunk/lib/coder.h
==============================================================================
--- trunk/lib/coder.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/lib/coder.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,283 @@
+/* Base type primitives */
+
+#ifndef __CODER_H_SEEN__
+#define __CODER_H_SEEN__
+
+#ifndef __GNUC__
+#define __inline__ /* */
+#endif
+
+#ifndef __cplusplus
+#ifndef ALLOC
+extern void *malloc(unsigned long);
+extern void free(void *);
+#define ALLOC(s) malloc(s)
+#define FREE(s) free(s)
+#endif /* ALLOC */
+#endif __cplusplus
+
+/* Types we use */
+typedef unsigned char Uchar;
+typedef unsigned short Ushort;
+typedef unsigned long Ulong;
+typedef unsigned long Uint;
+typedef unsigned long long Ulonglong;
+typedef long long longlong;
+
+/** char **/
+__inline__ static unsigned char *encode_char(const char *ch, unsigned char *buf)
+{
+ *buf = *ch;
+ return buf+1;
+}
+
+__inline__ static unsigned char *decode_char(char *ch, unsigned char *buf)
+{
+ *ch = *buf;
+ return buf+1;
+}
+
+__inline__ static unsigned int sizeof_char(const char *c)
+{
+ (void)c;
+ return 1;
+}
+
+/** unsigned char **/
+__inline__ static unsigned char *encode_Uchar(const Uchar *ch, unsigned char *buf)
+{
+ *buf = *ch;
+ return buf+1;
+}
+
+__inline__ static unsigned char *decode_Uchar(Uchar *ch, unsigned char *buf)
+{
+ *ch = *buf;
+ return buf+1;
+}
+
+__inline__ static unsigned int sizeof_Uchar(const Uchar *c)
+{
+ (void)c;
+ return 1;
+}
+
+/** short **/
+__inline__ static unsigned char *encode_short(const short *sh, unsigned char *buf)
+{
+ register short sv = *sh;
+
+ buf[0] = (sv >> 8)& 0xff;
+ buf[1] = sv & 0xff;
+ return buf+2;
+}
+
+__inline__ static unsigned char *decode_short(short *sh, unsigned char *buf)
+{
+ *sh = (buf[0] << 8) | buf[1];
+ return buf+2;
+}
+
+__inline__ static unsigned int sizeof_short(const short *c)
+{
+ (void)c;
+ return 2;
+}
+
+/** unsigned short **/
+__inline__ static unsigned char *encode_Ushort(const Ushort *sh, unsigned char *buf)
+{
+ register Ushort sv = *sh;
+
+ buf[0] = (sv >> 8)& 0xff;
+ buf[1] = sv & 0xff;
+ return buf+2;
+}
+
+__inline__ static unsigned char *decode_Ushort(Ushort *sh, unsigned char *buf)
+{
+ *sh = (buf[0] << 8) | buf[1];
+ return buf+2;
+}
+
+__inline__ static unsigned int sizeof_Ushort(const Ushort *c)
+{
+ (void)c;
+ return 2;
+}
+
+/** long **/
+__inline__ static unsigned char *encode_long(const long *l, unsigned char *buf)
+{
+ register long lv = *l;
+
+ buf[0] = (lv >> 24) & 0xff;
+ buf[1] = (lv >> 16) & 0xff;
+ buf[2] = (lv >> 8) & 0xff;
+ buf[3] = lv & 0xff;
+ return buf+4;
+}
+
+__inline__ static unsigned char *decode_long(long *l, unsigned char *buf)
+{
+ *l = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
+ return buf+4;
+}
+
+__inline__ static unsigned int sizeof_long(const long *c)
+{
+ (void)c;
+ return 4;
+}
+
+/** unsigned long **/
+__inline__ static unsigned char *encode_Ulong(const Ulong *l, unsigned char *buf)
+{
+ register Ulong lv = *l;
+
+ buf[0] = (lv >> 24) & 0xff;
+ buf[1] = (lv >> 16) & 0xff;
+ buf[2] = (lv >> 8) & 0xff;
+ buf[3] = lv & 0xff;
+ return buf+4;
+}
+
+__inline__ static unsigned char *decode_Ulong(Ulong *l, unsigned char *buf)
+{
+ *l = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
+ return buf+4;
+}
+
+__inline__ static unsigned int sizeof_Ulong(const Ulong *c)
+{
+ (void)c;
+ return 4;
+}
+
+/** long long */
+__inline__ static unsigned char *encode_longlong(const long long *l,
+ unsigned char *buf)
+{
+ register long long lv = *l;
+
+ buf[0] = (lv >> 56) & 0xff;
+ buf[1] = (lv >> 48) & 0xff;
+ buf[2] = (lv >> 40) & 0xff;
+ buf[3] = (lv >> 32) & 0xff;
+ buf[4] = (lv >> 24) & 0xff;
+ buf[5] = (lv >> 16) & 0xff;
+ buf[6] = (lv >> 8) & 0xff;
+ buf[7] = lv & 0xff;
+
+ return buf+8;
+}
+
+__inline__ static unsigned char *decode_longlong(long long *l,
+ unsigned char *buf)
+{
+#define BUF(x) ((long long)(buf[x]))
+ *l = (BUF(0) << 56)|(BUF(1) << 48)|(BUF(2) << 40)|(BUF(3) << 32)|
+ (BUF(4) << 24)|(BUF(5) << 16)|(BUF(6) << 8)|BUF(7);
+#undef BUF
+ return buf+8;
+}
+
+__inline__ static unsigned int sizeof_longlong(const long long *c)
+{
+ (void)c;
+ return 8;
+}
+
+/** unsigned long long */
+__inline__ static unsigned char *encode_Ulonglong(const unsigned long long *l,
+ unsigned char *buf)
+{
+ register unsigned long long lv = *l;
+
+ buf[0] = (lv >> 56) & 0xff;
+ buf[1] = (lv >> 48) & 0xff;
+ buf[2] = (lv >> 40) & 0xff;
+ buf[3] = (lv >> 32) & 0xff;
+ buf[4] = (lv >> 24) & 0xff;
+ buf[5] = (lv >> 16) & 0xff;
+ buf[6] = (lv >> 8) & 0xff;
+ buf[7] = lv & 0xff;
+
+ return buf+8;
+}
+
+__inline__ static unsigned char *decode_Ulonglong(unsigned long long *l,
+ unsigned char *buf)
+{
+#define BUF(x) ((unsigned long long)(buf[x]))
+ *l = (BUF(0) << 56)|(BUF(1) << 48)|(BUF(2) << 40)|(BUF(3) << 32)|
+ (BUF(4) << 24)|(BUF(5) << 16)|(BUF(6) << 8)|BUF(7);
+#undef BUF
+ return buf+8;
+}
+
+__inline__ static unsigned int sizeof_Ulonglong(const unsigned long long *c)
+{
+ (void)c;
+ return 8;
+}
+
+/** void **/
+__inline__ static unsigned char *encode_void(const void *v, unsigned char *buf)
+{
+ (void)v;
+ return buf;
+}
+
+__inline__ static unsigned char *decode_void(void *v, unsigned char *buf)
+{
+ (void)v;
+ return buf;
+}
+
+__inline__ static unsigned int sizeof_void(const void *c)
+{
+ (void)c;
+ return 0;
+}
+
+/* Assuming this host has IEEE 754 floats, this is all OK */
+/** float **/
+__inline__ static unsigned char *encode_float(const float *f, unsigned char *buf)
+{
+ *(float *)buf = *f;
+ return buf + sizeof(float);
+}
+
+__inline__ static unsigned char *decode_float(float *f, unsigned char *buf)
+{
+ *f = *(float *)buf;
+ return buf + sizeof(float);
+}
+
+__inline__ static unsigned int sizeof_float(const float *c)
+{
+ (void)c;
+ return sizeof(float);
+}
+
+/** double **/
+__inline__ static unsigned char *encode_double(const double *d, unsigned char *buf)
+{
+ *(double *)buf = *d;
+ return buf + sizeof(double);
+}
+
+__inline__ static unsigned char *decode_double(double *d, unsigned char *buf)
+{
+ *d = *(double *)buf;
+ return buf + sizeof(double);
+}
+
+__inline__ static unsigned int sizeof_double(const double *c)
+{
+ (void)c;
+ return sizeof(double);
+}
+
+#endif /* __CODER_H_SEEN__ */
Added: trunk/lib/Inode.cc
==============================================================================
--- trunk/lib/Inode.cc 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/lib/Inode.cc 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,127 @@
+// -*- C++ -*-
+// Inode handling class
+//
+// This program is distributed under the terms of the
+// Free Software Foundation General Public Licence.
+// Copyright Jeremy Fitzhardinge <jeremy at sw.oz.au> 1993
+
+#pragma implementation
+
+#include "Inode.h"
+#include "Filesystem.h"
+
+#include <stdio.h>
+
+InodeList::InodeList()
+{
+ list = NULL;
+}
+
+InodeList::~InodeList()
+{
+ Inode *next;
+
+ for(next = list; next != NULL; next = next->next)
+ next->cleanup();
+
+ for(; list != NULL; list = next)
+ {
+ next = list->next;
+ delete list;
+ }
+}
+
+void
+InodeList::add(Inode *ino)
+{
+ if (ino->onlist)
+ {
+ fprintf(stderr, "Adding %p onto list again\n", ino);
+ return;
+ }
+ ino->next = list;
+ ino->prev = NULL;
+ if (ino->next)
+ ino->next->prev = ino;
+ list = ino;
+ ino->onlist = 1;
+}
+
+void
+InodeList::del(Inode *ino)
+{
+ if (!ino->onlist)
+ return;
+ if (ino->prev)
+ ino->prev->next = ino->next;
+ else
+ list = ino->next;
+ if (ino->next)
+ ino->next->prev = ino->prev;
+ ino->onlist = 0;
+}
+
+Inode *
+InodeList::find(Handle hand)
+{
+ Inode *ino;
+
+ for(ino = list; ino != NULL; ino = ino->next)
+ if (ino->handle == hand)
+ break;
+
+ if (ino == NULL)
+ return NULL;
+
+ // Move to head of list
+ del(ino);
+ add(ino);
+
+ return ino;
+}
+
+Inode::Inode(Filesystem &fs, Handle hand)
+ :next(NULL),prev(NULL),nlink(0),handle(hand),filesys(fs)
+{
+ alive = 1;
+ onlist = 0;
+ filesys.inodes.add(this);
+}
+
+Inode::~Inode()
+{
+ if (!alive)
+ fprintf(stderr, "Inode %p already dead!\n", this);
+ filesys.inodes.del(this);
+ alive = 0;
+}
+
+Inode *
+Inode::findino(Handle h)
+{
+ return filesys.inodes.find(h);
+}
+
+#if 0
+void
+Inode::iread(up_inode &ino)
+{
+ ino.uid = uid;
+ ino.gid = gid;
+ ino.mode = mode;
+ ino.nlink = nlink;
+ ino.mtime = mtime;
+ ino.ctime = ctime;
+ ino.atime = atime;
+ ino.size = size;
+}
+#endif
+
+#define DO(op) int Inode::do_##op(const up_preamble &, upp_repl &) { return ENOSYS; }
+#define DOa(op) int Inode::do_##op(const up_preamble &, upp_repl &, const upp_##op##_s &) { return ENOSYS; }
+#define DOr(op) int Inode::do_##op(const up_preamble &, upp_repl &, upp_##op##_r &) { return ENOSYS; }
+#define DOar(op) int Inode::do_##op(const up_preamble &, upp_repl &, const upp_##op##_s &, upp_##op##_r &) { return ENOSYS; }
+#define opFILE
+#define opINODE
+#include "operations.h"
+
Added: trunk/lib/DirInode.h
==============================================================================
--- trunk/lib/DirInode.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/lib/DirInode.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,81 @@
+// -*- C++ -*-
+
+/* Copyright (C) 1993 Tuomas J. Lukka, based on Jeremy Fitzhardinge's work */
+// Further modified by Jeremy as a general Directory Inode.
+// This program is distributed under the terms of the
+// Free Software Foundation General Public Licence.
+// See COPYING for details
+
+// A directory inode
+
+#ifndef __DIRINODE_H_SEEN__
+#define __DIRINODE_H_SEEN__
+
+#include <SimpleInode.h>
+
+#include <sys/types.h>
+#include <string>
+
+#pragma interface
+
+class Filesystem;
+class DirInode;
+
+class DirEntry
+{
+ friend DirInode;
+ string name;
+ Inode *ino; // NULL if none
+
+ DirEntry *prev, *next;
+
+public:
+ DirEntry(const string, Inode *);
+ DirEntry() { ino = NULL; }
+ ~DirEntry();
+
+ const string getname() const { return name; }
+ Inode *geti() const { return ino; }
+};
+
+class DirInode : public SimpleInode
+{
+private:
+ int max_multird;
+ DirEntry *entries, *end;
+
+protected:
+ Inode *parent;
+
+public:
+ DirInode(Filesystem &fs, Handle h, Inode *parent, int mm = 100);
+ ~DirInode();
+
+ // Userfs operations
+ int do_lookup(const up_preamble &, upp_repl &,
+ const upp_lookup_s &, upp_lookup_r &);
+ int do_readdir(const up_preamble &, upp_repl &,
+ const upp_readdir_s &, upp_readdir_r &);
+ int do_multireaddir(const up_preamble &, upp_repl &,
+ const upp_multireaddir_s &, upp_multireaddir_r &);
+ int do_rename(const up_preamble &, upp_repl &,
+ const upp_rename_s &);
+ int do_unlink(const up_preamble &, upp_repl &,
+ const upp_unlink_s &arg);
+ int do_link(const up_preamble &, upp_repl &,
+ const upp_link_s &);
+ int do_read(const up_preamble &, upp_repl &,
+ const upp_read_s &, upp_read_r &);
+ int do_write(const up_preamble &, upp_repl &,
+ const upp_write_s &, upp_write_r &);
+
+ // Inode operations
+ int link(const string &, Inode *);
+ DirEntry *lookup(const string &) const;
+ int unlink(const string &);
+ DirEntry *scan(int &pos) const;
+ DirEntry *scan(DirEntry *&pos) const;
+ int link(const char *n, int l, Inode *i) { return link(string(n, l), i); }
+ int unlink(const char *n, int l) { return unlink(string(n, l)); }
+};
+#endif
Added: trunk/lib/DeferComm.cc
==============================================================================
--- trunk/lib/DeferComm.cc 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/lib/DeferComm.cc 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,205 @@
+// -*- C++ -*-
+
+// Cope with deferred replies in the form of sub-processes
+
+#pragma implementation
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#include "DeferComm.h"
+#include "DeferFilesys.h"
+#include "io.h"
+
+class Defer_doreq: public Comm_doreq
+{
+ int deferred;
+
+ int dispatch(int fd, int flag);
+public:
+ Defer_doreq(const CommBase *, Filesystem &);
+ void defer(int fd);
+};
+
+class copy : public DispToKern
+{
+public:
+ copy(const CommBase *);
+ int dispatch(int fd, int);
+};
+
+copy::copy(const CommBase *c)
+ :DispToKern(c)
+{
+}
+
+int
+copy::dispatch(int from, int)
+{
+ int rd;
+ char buf[1024];
+
+ again:
+ while((rd = read(from, buf, sizeof(buf))) > 0)
+ {
+ char *wrp = buf;
+
+ while(rd > 0)
+ {
+ int wr = write(tokern, wrp, rd);
+
+ if (wr == -1 && errno == EINTR)
+ continue;
+
+ if (wr == -1 || wr == 0)
+ return -1;
+ wrp += wr;
+ rd -= wr;
+ }
+ }
+
+ if (rd == -1)
+ {
+ if (errno == EINTR)
+ goto again;
+ return -1;
+ }
+
+ return 0;
+}
+
+DeferComm::DeferComm(DeferFilesys &fs, unsigned int to, unsigned int from)
+ :CommBase(fs, to, from),filesys(fs)
+{
+ req = ourreq = new Defer_doreq(this, filesys);
+ addDispatch(from, req);
+ fs.setcomm(this);
+}
+
+// This can be (indirectly) called by filesystem methods so they
+// can defer replying until later, allowing the filesystem to be
+// used by other processes in the meantime. This would happen,
+// for example, if a read takes a long time to generate and the
+// filesystem should be available for directory scans and name
+// lookups.
+// The function uses fork(); the parent returns so the main
+// filesystem process can keep accepting requests. The child
+// works away and sends the reply when its ready. This goes
+// through a pipe from the child to the parent for copying
+// to the kernel in one piece. Everything is set up so the
+// Comm class in the child knows what to do, and exits when
+// done.
+int
+DeferComm::DeferRepl()
+{
+ int p[2];
+ int pid;
+
+ if (pipe(p) == -1)
+ {
+ perror("DeferComm::DeferRepl pipe() failed");
+ return -1;
+ }
+
+ switch(pid = fork())
+ {
+ case -1:
+ perror("DeferComm::DeferRepl fork() failed");
+ return -1;
+ case 0:
+ CloseFDs(0);
+ ourreq->defer(p[1]);
+ ::close(p[0]);
+ break;
+ default:
+ ::close(p[1]);
+ addDispatch(p[0], new copy(this));
+ break;
+ }
+
+ return pid;
+}
+
+DispatchFD *
+DeferComm::kern_disp()
+{
+ return req;
+}
+
+Defer_doreq::Defer_doreq(const CommBase *comm, Filesystem &fs)
+ : Comm_doreq(comm, fs)
+{
+ deferred = 0;
+}
+
+// Process a request from the kernel
+// Returns 0 on EOF, -1 on error and 1 for OK
+int
+Defer_doreq::dispatch(int fd, int)
+{
+ up_preamble pre;
+ size_t presize = sizeof_up_preamble(&pre);
+ Uchar hbuf[256];
+ Uchar buf[4096];
+ int ret;
+
+ ret = fullread(fd, hbuf, presize);
+ if (ret == 0)
+ return 0;
+
+ if (ret != (int)presize)
+ {
+ fprintf(stderr, "Defer_doreq::dispatch failed to get whole header (%d wanted, %d got)\n",
+ presize, ret);
+ return -1;
+ }
+
+ upp_repl repl;
+ size_t replsize = sizeof_upp_repl(&repl);
+
+ assert(sizeof(hbuf) > replsize);
+
+ decode_up_preamble(&pre, hbuf);
+
+ if (pre.size != 0 && (ret = fullread(fd, buf, pre.size)) != (int)pre.size)
+ {
+ fprintf(stderr, "Defer_doreq::dispatch: failed to get whole body (%li wanted, %d got)\n",
+ pre.size, ret);
+ return -1;
+ }
+
+ ret = filesys.DoOp(pre, repl, buf);
+
+ if (ret == -1 && !deferred)
+ return 1;
+
+ if (!ret)
+ return -1;
+
+#ifdef DEBUG
+ if (repl.errno != 0)
+ {
+ fprintf(stderr, "Request %d failing with %d %s\n",
+ pre.op, repl.errno, strerror(repl.errno));
+ }
+#endif
+
+ encode_upp_repl(&repl, hbuf);
+
+ if (fullwrite(tokern, hbuf, replsize) != replsize)
+ return -1;
+
+ if (repl.size != 0 && fullwrite(tokern, buf, repl.size) != repl.size)
+ return -1;
+
+ return deferred ? 0 : 1;
+}
+
+void
+Defer_doreq::defer(int fd)
+{
+ ::close(tokern);
+ tokern = fd;
+ deferred = 1;
+}
Added: trunk/lib/DeferComm.h
==============================================================================
--- trunk/lib/DeferComm.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/lib/DeferComm.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,24 @@
+// -*- C++ -*-
+
+// Deferred reply Comm class
+
+#ifndef _DEFERCOMM_H_
+#define _DEFERCOMM_H_
+
+#pragma interface
+
+#include "Comm.h"
+
+class DeferComm : public CommBase
+{
+ class Defer_doreq *ourreq;
+ DispatchFD *kern_disp();
+
+ class DeferFilesys &filesys;
+
+public:
+ DeferComm(class DeferFilesys &, unsigned int to, unsigned int from);
+ int DeferRepl();
+};
+
+#endif /* _DEFERCOMM_H_ */
Added: trunk/lib/Inode.p
==============================================================================
--- trunk/lib/Inode.p 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/lib/Inode.p 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,7911 @@
+
+
+
+
+
+
+
+#pragma implementation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef enum
+{
+ userfs_up_create,
+ userfs_up_lookup,
+ userfs_up_close,
+ userfs_up_read,
+ userfs_up_write,
+ userfs_up_truncate,
+ userfs_up_fsync,
+ userfs_up_readdir,
+ userfs_up_link,
+ userfs_up_unlink,
+ userfs_up_symlink,
+ userfs_up_readlink,
+ userfs_up_followlink,
+ userfs_up_mount,
+ userfs_up_umount,
+ userfs_up_iread,
+ userfs_up_iwrite,
+ userfs_up_statfs,
+ userfs_up_iput,
+ userfs_up_open,
+ userfs_up_permission,
+ userfs_up_rename,
+ userfs_up_multireaddir,
+ userfs_up_notify_change,
+ userfs_up_inode_valid,
+} up_ops;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#pragma interface "userfs_types"
+
+
+
+
+
+
+
+
+
+
+
+
+typedef unsigned short __kernel_dev_t;
+typedef unsigned long __kernel_ino_t;
+typedef unsigned short __kernel_mode_t;
+typedef unsigned short __kernel_nlink_t;
+typedef long __kernel_off_t;
+typedef int __kernel_pid_t;
+typedef unsigned short __kernel_ipc_pid_t;
+typedef unsigned short __kernel_uid_t;
+typedef unsigned short __kernel_gid_t;
+typedef unsigned int __kernel_size_t;
+typedef int __kernel_ssize_t;
+typedef int __kernel_ptrdiff_t;
+typedef long __kernel_time_t;
+typedef long __kernel_suseconds_t;
+typedef long __kernel_clock_t;
+typedef int __kernel_daddr_t;
+typedef char * __kernel_caddr_t;
+typedef unsigned short __kernel_uid16_t;
+typedef unsigned short __kernel_gid16_t;
+typedef unsigned int __kernel_uid32_t;
+typedef unsigned int __kernel_gid32_t;
+
+typedef unsigned short __kernel_old_uid_t;
+typedef unsigned short __kernel_old_gid_t;
+
+
+typedef long long __kernel_loff_t;
+
+
+typedef struct {
+
+ int __val[2];
+
+} __kernel_fsid_t;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef unsigned short umode_t;
+
+
+
+
+
+
+typedef __signed__ char __s8;
+typedef unsigned char __u8;
+
+typedef __signed__ short __s16;
+typedef unsigned short __u16;
+
+typedef __signed__ int __s32;
+typedef unsigned int __u32;
+
+
+typedef __signed__ long long __s64;
+typedef unsigned long long __u64;
+
+
+
+
+
+
+
+
+
+typedef __kernel_suseconds_t suseconds_t;
+typedef __u8 uint8_t;
+typedef __u16 uint16_t;
+typedef __u32 uint32_t;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern "C" {
+
+
+extern void __assert_fail (__const char *__assertion, __const char *__file,
+ unsigned int __line, __const char *__function)
+ throw () __attribute__ ((__noreturn__));
+
+
+extern void __assert_perror_fail (int __errnum, __const char *__file,
+ unsigned int __line,
+ __const char *__function)
+ throw () __attribute__ ((__noreturn__));
+
+
+
+
+extern void __assert (const char *__assertion, const char *__file, int __line)
+ throw () __attribute__ ((__noreturn__));
+
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef unsigned int size_t;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern "C" {
+
+
+
+
+
+
+
+typedef struct
+ {
+ int quot;
+ int rem;
+ } div_t;
+
+
+
+typedef struct
+ {
+ long int quot;
+ long int rem;
+ } ldiv_t;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern size_t __ctype_get_mb_cur_max (void) throw () ;
+
+
+
+extern double atof (__const char *__nptr) throw () ;
+
+extern int atoi (__const char *__nptr) throw () ;
+
+extern long int atol (__const char *__nptr) throw () ;
+
+
+
+__extension__ extern long long int atoll (__const char *__nptr)
+ throw () ;
+
+
+
+extern double strtod (__const char *__restrict __nptr,
+ char **__restrict __endptr) throw () ;
+
+
+
+
+extern long int strtol (__const char *__restrict __nptr,
+ char **__restrict __endptr, int __base) throw () ;
+
+extern unsigned long int strtoul (__const char *__restrict __nptr,
+ char **__restrict __endptr, int __base)
+ throw () ;
+
+
+
+__extension__
+extern long long int strtoq (__const char *__restrict __nptr,
+ char **__restrict __endptr, int __base) throw () ;
+
+__extension__
+extern unsigned long long int strtouq (__const char *__restrict __nptr,
+ char **__restrict __endptr, int __base)
+ throw () ;
+
+
+
+
+
+
+__extension__
+extern long long int strtoll (__const char *__restrict __nptr,
+ char **__restrict __endptr, int __base) throw () ;
+
+__extension__
+extern unsigned long long int strtoull (__const char *__restrict __nptr,
+ char **__restrict __endptr, int __base)
+ throw () ;
+
+
+
+
+
+
+
+
+
+extern double __strtod_internal (__const char *__restrict __nptr,
+ char **__restrict __endptr, int __group)
+ throw () ;
+extern float __strtof_internal (__const char *__restrict __nptr,
+ char **__restrict __endptr, int __group)
+ throw () ;
+extern long double __strtold_internal (__const char *__restrict __nptr,
+ char **__restrict __endptr,
+ int __group) throw () ;
+
+extern long int __strtol_internal (__const char *__restrict __nptr,
+ char **__restrict __endptr,
+ int __base, int __group) throw () ;
+
+
+
+extern unsigned long int __strtoul_internal (__const char *__restrict __nptr,
+ char **__restrict __endptr,
+ int __base, int __group) throw () ;
+
+
+
+
+__extension__
+extern long long int __strtoll_internal (__const char *__restrict __nptr,
+ char **__restrict __endptr,
+ int __base, int __group) throw () ;
+
+
+
+__extension__
+extern unsigned long long int __strtoull_internal (__const char *
+ __restrict __nptr,
+ char **__restrict __endptr,
+ int __base, int __group)
+ throw () ;
+
+
+
+
+
+
+
+extern __inline double
+strtod (__const char *__restrict __nptr, char **__restrict __endptr) throw ()
+{
+ return __strtod_internal (__nptr, __endptr, 0);
+}
+extern __inline long int
+strtol (__const char *__restrict __nptr, char **__restrict __endptr,
+ int __base) throw ()
+{
+ return __strtol_internal (__nptr, __endptr, __base, 0);
+}
+extern __inline unsigned long int
+strtoul (__const char *__restrict __nptr, char **__restrict __endptr,
+ int __base) throw ()
+{
+ return __strtoul_internal (__nptr, __endptr, __base, 0);
+}
+
+
+
+
+__extension__ extern __inline long long int
+strtoq (__const char *__restrict __nptr, char **__restrict __endptr,
+ int __base) throw ()
+{
+ return __strtoll_internal (__nptr, __endptr, __base, 0);
+}
+__extension__ extern __inline unsigned long long int
+strtouq (__const char *__restrict __nptr, char **__restrict __endptr,
+ int __base) throw ()
+{
+ return __strtoull_internal (__nptr, __endptr, __base, 0);
+}
+
+
+
+__extension__ extern __inline long long int
+strtoll (__const char *__restrict __nptr, char **__restrict __endptr,
+ int __base) throw ()
+{
+ return __strtoll_internal (__nptr, __endptr, __base, 0);
+}
+__extension__ extern __inline unsigned long long int
+strtoull (__const char * __restrict __nptr, char **__restrict __endptr,
+ int __base) throw ()
+{
+ return __strtoull_internal (__nptr, __endptr, __base, 0);
+}
+
+
+extern __inline double
+atof (__const char *__nptr) throw ()
+{
+ return strtod (__nptr, (char **) __null );
+}
+extern __inline int
+atoi (__const char *__nptr) throw ()
+{
+ return (int) strtol (__nptr, (char **) __null , 10);
+}
+extern __inline long int
+atol (__const char *__nptr) throw ()
+{
+ return strtol (__nptr, (char **) __null , 10);
+}
+
+
+__extension__ extern __inline long long int
+atoll (__const char *__nptr) throw ()
+{
+ return strtoll (__nptr, (char **) __null , 10);
+}
+
+
+
+
+
+
+
+
+extern char *l64a (long int __n) throw () ;
+
+
+extern long int a64l (__const char *__s) throw () ;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern "C" {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef unsigned char __u_char;
+typedef unsigned short __u_short;
+typedef unsigned int __u_int;
+typedef unsigned long __u_long;
+
+__extension__ typedef unsigned long long int __u_quad_t;
+__extension__ typedef long long int __quad_t;
+
+typedef signed char __int8_t;
+typedef unsigned char __uint8_t;
+typedef signed short int __int16_t;
+typedef unsigned short int __uint16_t;
+typedef signed int __int32_t;
+typedef unsigned int __uint32_t;
+
+__extension__ typedef signed long long int __int64_t;
+__extension__ typedef unsigned long long int __uint64_t;
+
+typedef __quad_t *__qaddr_t;
+
+typedef __u_quad_t __dev_t;
+typedef __u_int __uid_t;
+typedef __u_int __gid_t;
+typedef __u_long __ino_t;
+typedef __u_int __mode_t;
+typedef __u_int __nlink_t;
+typedef long int __off_t;
+typedef __quad_t __loff_t;
+typedef int __pid_t;
+typedef int __ssize_t;
+typedef __u_long __rlim_t;
+typedef __u_quad_t __rlim64_t;
+typedef __u_int __id_t;
+
+typedef struct
+ {
+ int __val[2];
+ } __fsid_t;
+
+
+typedef int __daddr_t;
+typedef char *__caddr_t;
+typedef long int __time_t;
+typedef unsigned int __useconds_t;
+typedef long int __suseconds_t;
+typedef long int __swblk_t;
+
+typedef long int __clock_t;
+
+
+typedef int __clockid_t;
+
+
+typedef int __timer_t;
+
+
+
+
+
+
+typedef int __key_t;
+
+
+typedef unsigned short int __ipc_pid_t;
+
+
+
+typedef long int __blksize_t;
+
+
+
+
+typedef long int __blkcnt_t;
+typedef __quad_t __blkcnt64_t;
+
+
+typedef __u_long __fsblkcnt_t;
+typedef __u_quad_t __fsblkcnt64_t;
+
+
+typedef __u_long __fsfilcnt_t;
+typedef __u_quad_t __fsfilcnt64_t;
+
+
+typedef __u_quad_t __ino64_t;
+
+
+typedef __loff_t __off64_t;
+
+
+typedef long int __t_scalar_t;
+typedef unsigned long int __t_uscalar_t;
+
+
+typedef int __intptr_t;
+
+
+typedef unsigned int __socklen_t;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+struct __sched_param
+ {
+ int __sched_priority;
+ };
+
+
+
+
+typedef int _lt_spinlock_t;
+
+
+struct _pthread_fastlock
+{
+ long int __status;
+ _lt_spinlock_t __spinlock;
+
+};
+
+
+
+typedef struct _pthread_descr_struct *_pthread_descr;
+
+
+
+
+
+typedef struct __pthread_attr_s
+{
+ int __detachstate;
+ int __schedpolicy;
+ struct __sched_param __schedparam;
+ int __inheritsched;
+ int __scope;
+ size_t __guardsize;
+ int __stackaddr_set;
+ void *__stackaddr;
+ size_t __stacksize;
+} pthread_attr_t;
+
+
+
+typedef struct
+{
+ struct _pthread_fastlock __c_lock;
+ _pthread_descr __c_waiting;
+} pthread_cond_t;
+
+
+
+typedef struct
+{
+ int __dummy;
+} pthread_condattr_t;
+
+
+typedef unsigned int pthread_key_t;
+
+
+
+
+
+typedef struct
+{
+ int __m_reserved;
+ int __m_count;
+ _pthread_descr __m_owner;
+ int __m_kind;
+ struct _pthread_fastlock __m_lock;
+} pthread_mutex_t;
+
+
+
+typedef struct
+{
+ int __mutexkind;
+} pthread_mutexattr_t;
+
+
+
+typedef int pthread_once_t;
+
+
+
+
+
+
+
+
+typedef unsigned long int pthread_t;
+
+
+
+
+
+
+
+
+
+typedef __u_char u_char;
+typedef __u_short u_short;
+typedef __u_int u_int;
+typedef __u_long u_long;
+typedef __quad_t quad_t;
+typedef __u_quad_t u_quad_t;
+typedef __fsid_t fsid_t;
+
+
+typedef __loff_t loff_t;
+
+
+
+typedef __ino_t ino_t;
+
+
+
+
+
+
+typedef __dev_t dev_t;
+
+
+
+
+typedef __gid_t gid_t;
+
+
+
+
+typedef __mode_t mode_t;
+
+
+
+
+typedef __nlink_t nlink_t;
+
+
+
+
+typedef __uid_t uid_t;
+
+
+
+
+
+typedef __off_t off_t;
+
+
+
+
+
+
+typedef __pid_t pid_t;
+
+
+
+
+typedef __id_t id_t;
+
+
+
+
+typedef __ssize_t ssize_t;
+
+
+
+
+typedef __daddr_t daddr_t;
+typedef __caddr_t caddr_t;
+
+
+
+typedef __key_t key_t;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef __time_t time_t;
+
+
+
+
+
+
+
+
+
+
+typedef __clockid_t clockid_t;
+
+
+
+
+
+
+
+
+
+
+typedef __timer_t timer_t;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef unsigned long int ulong;
+typedef unsigned short int ushort;
+typedef unsigned int uint;
+
+
+
+
+
+
+
+
+
+
+
+
+typedef int int8_t __attribute__ ((__mode__ ( __QI__ ))) ;
+typedef int int16_t __attribute__ ((__mode__ ( __HI__ ))) ;
+typedef int int32_t __attribute__ ((__mode__ ( __SI__ ))) ;
+typedef int int64_t __attribute__ ((__mode__ ( __DI__ ))) ;
+
+
+typedef unsigned int u_int8_t __attribute__ ((__mode__ ( __QI__ ))) ;
+typedef unsigned int u_int16_t __attribute__ ((__mode__ ( __HI__ ))) ;
+typedef unsigned int u_int32_t __attribute__ ((__mode__ ( __SI__ ))) ;
+typedef unsigned int u_int64_t __attribute__ ((__mode__ ( __DI__ ))) ;
+
+typedef int register_t __attribute__ ((__mode__ (__word__)));
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef int __sig_atomic_t;
+
+
+
+
+typedef struct
+ {
+ unsigned long int __val[(1024 / (8 * sizeof (unsigned long int))) ];
+ } __sigset_t;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef __sigset_t sigset_t;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+struct timespec
+ {
+ long int tv_sec;
+ long int tv_nsec;
+ };
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+struct timeval
+ {
+ __time_t tv_sec;
+ __suseconds_t tv_usec;
+ };
+
+
+
+
+
+
+typedef long int __fd_mask;
+
+
+
+
+
+
+
+typedef struct
+ {
+
+
+
+ __fd_mask __fds_bits[1024 / (8 * sizeof (__fd_mask)) ];
+
+
+ } fd_set;
+
+
+
+
+
+
+typedef __fd_mask fd_mask;
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern "C" {
+
+
+
+
+
+
+extern int select (int __nfds, fd_set *__restrict __readfds,
+ fd_set *__restrict __writefds,
+ fd_set *__restrict __exceptfds,
+ struct timeval *__restrict __timeout) throw () ;
+
+
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef __blkcnt_t blkcnt_t;
+
+
+
+typedef __fsblkcnt_t fsblkcnt_t;
+
+
+
+typedef __fsfilcnt_t fsfilcnt_t;
+
+
+
+
+
+
+}
+
+
+
+
+
+
+
+
+
+extern long int random (void) throw () ;
+
+
+extern void srandom (unsigned int __seed) throw () ;
+
+
+
+
+
+extern char *initstate (unsigned int __seed, char *__statebuf,
+ size_t __statelen) throw () ;
+
+
+
+extern char *setstate (char *__statebuf) throw () ;
+
+
+
+
+
+
+
+struct random_data
+ {
+ int32_t *fptr;
+ int32_t *rptr;
+ int32_t *state;
+ int rand_type;
+ int rand_deg;
+ int rand_sep;
+ int32_t *end_ptr;
+ };
+
+extern int random_r (struct random_data *__restrict __buf,
+ int32_t *__restrict __result) throw () ;
+
+extern int srandom_r (unsigned int __seed, struct random_data *__buf) throw () ;
+
+extern int initstate_r (unsigned int __seed, char *__restrict __statebuf,
+ size_t __statelen,
+ struct random_data *__restrict __buf) throw () ;
+
+extern int setstate_r (char *__restrict __statebuf,
+ struct random_data *__restrict __buf) throw () ;
+
+
+
+
+
+extern int rand (void) throw () ;
+
+extern void srand (unsigned int __seed) throw () ;
+
+
+
+extern int rand_r (unsigned int *__seed) throw () ;
+
+
+
+
+
+
+
+extern double drand48 (void) throw () ;
+extern double erand48 (unsigned short int __xsubi[3]) throw () ;
+
+
+extern long int lrand48 (void) throw () ;
+extern long int nrand48 (unsigned short int __xsubi[3]) throw () ;
+
+
+extern long int mrand48 (void) throw () ;
+extern long int jrand48 (unsigned short int __xsubi[3]) throw () ;
+
+
+extern void srand48 (long int __seedval) throw () ;
+extern unsigned short int *seed48 (unsigned short int __seed16v[3]) throw () ;
+extern void lcong48 (unsigned short int __param[7]) throw () ;
+
+
+
+
+
+struct drand48_data
+ {
+ unsigned short int __x[3];
+ unsigned short int __old_x[3];
+ unsigned short int __c;
+ unsigned short int __init;
+ unsigned long long int __a;
+ };
+
+
+extern int drand48_r (struct drand48_data *__restrict __buffer,
+ double *__restrict __result) throw () ;
+extern int erand48_r (unsigned short int __xsubi[3],
+ struct drand48_data *__restrict __buffer,
+ double *__restrict __result) throw () ;
+
+
+extern int lrand48_r (struct drand48_data *__restrict __buffer,
+ long int *__restrict __result) throw () ;
+extern int nrand48_r (unsigned short int __xsubi[3],
+ struct drand48_data *__restrict __buffer,
+ long int *__restrict __result) throw () ;
+
+
+extern int mrand48_r (struct drand48_data *__restrict __buffer,
+ long int *__restrict __result) throw () ;
+extern int jrand48_r (unsigned short int __xsubi[3],
+ struct drand48_data *__restrict __buffer,
+ long int *__restrict __result) throw () ;
+
+
+extern int srand48_r (long int __seedval, struct drand48_data *__buffer)
+ throw () ;
+
+extern int seed48_r (unsigned short int __seed16v[3],
+ struct drand48_data *__buffer) throw () ;
+
+extern int lcong48_r (unsigned short int __param[7],
+ struct drand48_data *__buffer) throw () ;
+
+
+
+
+
+
+
+
+extern void *malloc (size_t __size) throw () ;
+
+extern void *calloc (size_t __nmemb, size_t __size)
+ throw () ;
+
+
+
+
+
+extern void *realloc (void *__ptr, size_t __size) throw () ;
+
+extern void free (void *__ptr) throw () ;
+
+
+
+extern void cfree (void *__ptr) throw () ;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern "C" {
+
+
+
+
+
+extern void *alloca (size_t __size) throw () ;
+
+
+
+
+
+}
+
+
+
+
+
+
+
+extern void *valloc (size_t __size) throw () ;
+
+
+
+
+
+extern void abort (void) throw () __attribute__ ((__noreturn__));
+
+
+
+extern int atexit (void (*__func) (void)) throw () ;
+
+
+
+
+extern int on_exit (void (*__func) (int __status, void *__arg), void *__arg)
+ throw () ;
+
+
+
+
+
+extern void exit (int __status) throw () __attribute__ ((__noreturn__));
+
+
+
+
+
+extern char *getenv (__const char *__name) throw () ;
+
+
+
+extern char *__secure_getenv (__const char *__name) throw () ;
+
+
+
+
+
+extern int putenv (char *__string) throw () ;
+
+
+
+
+
+extern int setenv (__const char *__name, __const char *__value, int __replace)
+ throw () ;
+
+
+extern int unsetenv (__const char *__name) throw () ;
+
+
+
+
+
+
+extern int clearenv (void) throw () ;
+
+
+
+
+
+
+
+
+extern char *mktemp (char *__template) throw () ;
+
+
+
+
+
+
+
+extern int mkstemp (char *__template) throw () ;
+
+
+
+
+
+
+
+
+
+
+extern char *mkdtemp (char *__template) throw () ;
+
+
+
+
+extern int system (__const char *__command) throw () ;
+
+
+
+
+
+
+
+
+
+
+
+extern char *realpath (__const char *__restrict __name,
+ char *__restrict __resolved) throw () ;
+
+
+
+
+
+
+typedef int (*__compar_fn_t) (__const void *, __const void *);
+
+
+
+
+
+
+extern void *bsearch (__const void *__key, __const void *__base,
+ size_t __nmemb, size_t __size, __compar_fn_t __compar);
+
+
+
+extern void qsort (void *__base, size_t __nmemb, size_t __size,
+ __compar_fn_t __compar);
+
+
+
+extern int abs (int __x) throw () __attribute__ ((__const__));
+extern long int labs (long int __x) throw () __attribute__ ((__const__));
+
+
+
+
+
+
+extern div_t div (int __numer, int __denom)
+ throw () __attribute__ ((__const__));
+extern ldiv_t ldiv (long int __numer, long int __denom)
+ throw () __attribute__ ((__const__));
+
+
+
+
+
+
+
+
+
+
+extern char *ecvt (double __value, int __ndigit, int *__restrict __decpt,
+ int *__restrict __sign) throw () ;
+
+
+
+
+extern char *fcvt (double __value, int __ndigit, int *__restrict __decpt,
+ int *__restrict __sign) throw () ;
+
+
+
+
+extern char *gcvt (double __value, int __ndigit, char *__buf) throw () ;
+
+
+
+
+extern char *qecvt (long double __value, int __ndigit,
+ int *__restrict __decpt, int *__restrict __sign) throw () ;
+extern char *qfcvt (long double __value, int __ndigit,
+ int *__restrict __decpt, int *__restrict __sign) throw () ;
+extern char *qgcvt (long double __value, int __ndigit, char *__buf) throw () ;
+
+
+
+
+extern int ecvt_r (double __value, int __ndigit, int *__restrict __decpt,
+ int *__restrict __sign, char *__restrict __buf,
+ size_t __len) throw () ;
+extern int fcvt_r (double __value, int __ndigit, int *__restrict __decpt,
+ int *__restrict __sign, char *__restrict __buf,
+ size_t __len) throw () ;
+
+extern int qecvt_r (long double __value, int __ndigit,
+ int *__restrict __decpt, int *__restrict __sign,
+ char *__restrict __buf, size_t __len) throw () ;
+extern int qfcvt_r (long double __value, int __ndigit,
+ int *__restrict __decpt, int *__restrict __sign,
+ char *__restrict __buf, size_t __len) throw () ;
+
+
+
+
+
+
+extern int mblen (__const char *__s, size_t __n) throw () ;
+
+
+extern int mbtowc (wchar_t *__restrict __pwc,
+ __const char *__restrict __s, size_t __n) throw () ;
+
+
+extern int wctomb (char *__s, wchar_t __wchar) throw () ;
+
+
+
+extern size_t mbstowcs (wchar_t *__restrict __pwcs,
+ __const char *__restrict __s, size_t __n) throw () ;
+
+extern size_t wcstombs (char *__restrict __s,
+ __const wchar_t *__restrict __pwcs, size_t __n)
+ throw () ;
+
+
+
+
+
+
+
+extern int rpmatch (__const char *__response) throw () ;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern int getloadavg (double __loadavg[], int __nelem) throw () ;
+
+
+
+
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern "C" {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern long int __sysconf (int);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef __clock_t clock_t;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+struct tm
+{
+ int tm_sec;
+ int tm_min;
+ int tm_hour;
+ int tm_mday;
+ int tm_mon;
+ int tm_year;
+ int tm_wday;
+ int tm_yday;
+ int tm_isdst;
+
+
+ long int tm_gmtoff;
+ __const char *tm_zone;
+
+};
+
+
+
+
+struct itimerspec
+ {
+ struct timespec it_interval;
+ struct timespec it_value;
+ };
+
+
+struct sigevent;
+
+
+
+
+
+
+
+
+extern clock_t clock (void) throw () ;
+
+
+extern time_t time (time_t *__timer) throw () ;
+
+
+extern double difftime (time_t __time1, time_t __time0)
+ throw () __attribute__ ((__const__));
+
+
+extern time_t mktime (struct tm *__tp) throw () ;
+
+
+
+
+
+extern size_t strftime (char *__restrict __s, size_t __maxsize,
+ __const char *__restrict __format,
+ __const struct tm *__restrict __tp) throw () ;
+
+
+
+
+
+
+extern struct tm *gmtime (__const time_t *__timer) throw () ;
+
+
+
+extern struct tm *localtime (__const time_t *__timer) throw () ;
+
+
+
+
+extern struct tm *gmtime_r (__const time_t *__restrict __timer,
+ struct tm *__restrict __tp) throw () ;
+
+
+
+extern struct tm *localtime_r (__const time_t *__restrict __timer,
+ struct tm *__restrict __tp) throw () ;
+
+
+
+
+extern char *asctime (__const struct tm *__tp) throw () ;
+
+
+extern char *ctime (__const time_t *__timer) throw () ;
+
+
+
+
+
+
+extern char *asctime_r (__const struct tm *__restrict __tp,
+ char *__restrict __buf) throw () ;
+
+
+extern char *ctime_r (__const time_t *__restrict __timer,
+ char *__restrict __buf) throw () ;
+
+
+
+
+extern char *__tzname[2];
+extern int __daylight;
+extern long int __timezone;
+
+
+
+
+extern char *tzname[2];
+
+
+
+extern void tzset (void) throw () ;
+
+
+
+extern int daylight;
+extern long int timezone;
+
+
+
+
+
+extern int stime (__const time_t *__when) throw () ;
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern time_t timegm (struct tm *__tp) throw () ;
+
+
+extern time_t timelocal (struct tm *__tp) throw () ;
+
+
+extern int dysize (int __year) throw () __attribute__ ((__const__));
+
+
+
+
+
+extern int nanosleep (__const struct timespec *__requested_time,
+ struct timespec *__remaining) throw () ;
+
+
+
+extern int clock_getres (clockid_t __clock_id, struct timespec *__res) throw () ;
+
+
+extern int clock_gettime (clockid_t __clock_id, struct timespec *__tp) throw () ;
+
+
+extern int clock_settime (clockid_t __clock_id, __const struct timespec *__tp)
+ throw () ;
+
+
+
+
+
+extern int timer_create (clockid_t __clock_id,
+ struct sigevent *__restrict __evp,
+ timer_t *__restrict __timerid) throw () ;
+
+
+extern int timer_delete (timer_t __timerid) throw () ;
+
+
+extern int timer_settime (timer_t __timerid, int __flags,
+ __const struct itimerspec *__restrict __value,
+ struct itimerspec *__restrict __ovalue) throw () ;
+
+
+extern int timer_gettime (timer_t __timerid, struct itimerspec *__value)
+ throw () ;
+
+
+extern int timer_getoverrun (timer_t __timerid) throw () ;
+
+
+
+
+
+
+
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef int ptrdiff_t;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef unsigned int wint_t;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern "C" {
+
+
+
+
+extern int __malloc_initialized;
+
+
+
+
+
+extern void * malloc (size_t __size) throw () ;
+
+
+extern void * calloc (size_t __nmemb, size_t __size) throw ()
+ ;
+
+
+
+extern void * realloc (void * __ptr,
+ size_t __size) throw ()
+ ;
+
+
+extern void free (void * __ptr) throw () ;
+
+
+extern void cfree (void * __ptr) throw () ;
+
+
+extern void * memalign (size_t __alignment, size_t __size) throw () ;
+
+
+extern void * valloc (size_t __size) throw () ;
+
+
+
+extern void * pvalloc (size_t __size) throw ()
+ ;
+
+
+
+extern void * (*__morecore) (ptrdiff_t __size) ;
+
+
+extern void * __default_morecore (ptrdiff_t __size) throw ()
+ ;
+
+
+struct mallinfo {
+ int arena;
+ int ordblks;
+ int smblks;
+ int hblks;
+ int hblkhd;
+ int usmblks;
+ int fsmblks;
+ int uordblks;
+ int fordblks;
+ int keepcost;
+};
+
+
+extern struct mallinfo mallinfo (void) throw () ;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern int mallopt (int __param, int __val) throw () ;
+
+
+
+extern int malloc_trim (size_t __pad) throw () ;
+
+
+
+extern size_t malloc_usable_size (void * __ptr) throw () ;
+
+
+extern void malloc_stats (void) throw () ;
+
+
+extern void * malloc_get_state (void) throw () ;
+
+
+
+extern int malloc_set_state (void * __ptr) throw () ;
+
+
+
+
+
+extern void (*__malloc_initialize_hook) (void) ;
+
+extern void (*__free_hook) (void * __ptr,
+ __const void * ) ;
+extern void * (*__malloc_hook) (size_t __size,
+ __const void * ) ;
+extern void * (*__realloc_hook) (void * __ptr,
+ size_t __size,
+ __const void * ) ;
+extern void * (*__memalign_hook) (size_t __alignment,
+ size_t __size,
+ __const void * ) ;
+extern void (*__after_morecore_hook) (void) ;
+
+
+extern void __malloc_check_init (void) throw () ;
+
+
+
+};
+
+
+
+
+typedef unsigned char unchar;
+
+static __inline__ void * ALLOC (int alloc)
+{
+ void *mem = malloc(alloc);
+
+ (static_cast<void> (( mem != 0 ) ? 0 : (__assert_fail ("mem != 0" , "userfs_types.h", 46, __PRETTY_FUNCTION__ ), 0))) ;
+ return mem;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef struct {
+ unsigned long fds_bits [(1024 / (8 * sizeof(unsigned long)) ) ];
+} __kernel_fd_set;
+
+
+typedef void (*__kernel_sighandler_t)(int);
+
+
+typedef int __kernel_key_t;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+struct ustat {
+ __kernel_daddr_t f_tfree;
+ __kernel_ino_t f_tinode;
+ char f_fname[6];
+ char f_fpack[6];
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef struct
+{
+ unsigned long handle;
+} up_handle;
+
+typedef unsigned long up_version;
+
+struct userfs_inode_info
+{
+ up_handle handle;
+ struct userfs_dir_ra *dir_ra;
+ up_version version;
+};
+
+
+
+
+
+
+
+
+
+
+typedef unsigned long up_credtok;
+
+struct userfs_file_info {
+ up_credtok cred_tok;
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef unsigned char Uchar;
+typedef unsigned short Ushort;
+typedef unsigned long Ulong;
+typedef unsigned long Uint;
+typedef unsigned long long Ulonglong;
+typedef long long longlong;
+
+
+__inline__ static unsigned char *encode_char(const char *ch, unsigned char *buf)
+{
+ *buf = *ch;
+ return buf+1;
+}
+
+__inline__ static unsigned char *decode_char(char *ch, unsigned char *buf)
+{
+ *ch = *buf;
+ return buf+1;
+}
+
+__inline__ static unsigned int sizeof_char(const char *c)
+{
+ (void)c;
+ return 1;
+}
+
+
+__inline__ static unsigned char *encode_Uchar(const Uchar *ch, unsigned char *buf)
+{
+ *buf = *ch;
+ return buf+1;
+}
+
+__inline__ static unsigned char *decode_Uchar(Uchar *ch, unsigned char *buf)
+{
+ *ch = *buf;
+ return buf+1;
+}
+
+__inline__ static unsigned int sizeof_Uchar(const Uchar *c)
+{
+ (void)c;
+ return 1;
+}
+
+
+__inline__ static unsigned char *encode_short(const short *sh, unsigned char *buf)
+{
+ register short sv = *sh;
+
+ buf[0] = (sv >> 8)& 0xff;
+ buf[1] = sv & 0xff;
+ return buf+2;
+}
+
+__inline__ static unsigned char *decode_short(short *sh, unsigned char *buf)
+{
+ *sh = (buf[0] << 8) | buf[1];
+ return buf+2;
+}
+
+__inline__ static unsigned int sizeof_short(const short *c)
+{
+ (void)c;
+ return 2;
+}
+
+
+__inline__ static unsigned char *encode_Ushort(const Ushort *sh, unsigned char *buf)
+{
+ register Ushort sv = *sh;
+
+ buf[0] = (sv >> 8)& 0xff;
+ buf[1] = sv & 0xff;
+ return buf+2;
+}
+
+__inline__ static unsigned char *decode_Ushort(Ushort *sh, unsigned char *buf)
+{
+ *sh = (buf[0] << 8) | buf[1];
+ return buf+2;
+}
+
+__inline__ static unsigned int sizeof_Ushort(const Ushort *c)
+{
+ (void)c;
+ return 2;
+}
+
+
+__inline__ static unsigned char *encode_long(const long *l, unsigned char *buf)
+{
+ register long lv = *l;
+
+ buf[0] = (lv >> 24) & 0xff;
+ buf[1] = (lv >> 16) & 0xff;
+ buf[2] = (lv >> 8) & 0xff;
+ buf[3] = lv & 0xff;
+ return buf+4;
+}
+
+__inline__ static unsigned char *decode_long(long *l, unsigned char *buf)
+{
+ *l = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
+ return buf+4;
+}
+
+__inline__ static unsigned int sizeof_long(const long *c)
+{
+ (void)c;
+ return 4;
+}
+
+
+__inline__ static unsigned char *encode_Ulong(const Ulong *l, unsigned char *buf)
+{
+ register Ulong lv = *l;
+
+ buf[0] = (lv >> 24) & 0xff;
+ buf[1] = (lv >> 16) & 0xff;
+ buf[2] = (lv >> 8) & 0xff;
+ buf[3] = lv & 0xff;
+ return buf+4;
+}
+
+__inline__ static unsigned char *decode_Ulong(Ulong *l, unsigned char *buf)
+{
+ *l = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
+ return buf+4;
+}
+
+__inline__ static unsigned int sizeof_Ulong(const Ulong *c)
+{
+ (void)c;
+ return 4;
+}
+
+
+__inline__ static unsigned char *encode_longlong(const long long *l,
+ unsigned char *buf)
+{
+ register long long lv = *l;
+
+ buf[0] = (lv >> 56) & 0xff;
+ buf[1] = (lv >> 48) & 0xff;
+ buf[2] = (lv >> 40) & 0xff;
+ buf[3] = (lv >> 32) & 0xff;
+ buf[4] = (lv >> 24) & 0xff;
+ buf[5] = (lv >> 16) & 0xff;
+ buf[6] = (lv >> 8) & 0xff;
+ buf[7] = lv & 0xff;
+
+ return buf+8;
+}
+
+__inline__ static unsigned char *decode_longlong(long long *l,
+ unsigned char *buf)
+{
+
+ *l = (((long long)(buf[ 0 ])) << 56)|(((long long)(buf[ 1 ])) << 48)|(((long long)(buf[ 2 ])) << 40)|(((long long)(buf[ 3 ])) << 32)|
+ (((long long)(buf[ 4 ])) << 24)|(((long long)(buf[ 5 ])) << 16)|(((long long)(buf[ 6 ])) << 8)| ((long long)(buf[ 7 ])) ;
+
+ return buf+8;
+}
+
+__inline__ static unsigned int sizeof_longlong(const long long *c)
+{
+ (void)c;
+ return 8;
+}
+
+
+__inline__ static unsigned char *encode_Ulonglong(const unsigned long long *l,
+ unsigned char *buf)
+{
+ register unsigned long long lv = *l;
+
+ buf[0] = (lv >> 56) & 0xff;
+ buf[1] = (lv >> 48) & 0xff;
+ buf[2] = (lv >> 40) & 0xff;
+ buf[3] = (lv >> 32) & 0xff;
+ buf[4] = (lv >> 24) & 0xff;
+ buf[5] = (lv >> 16) & 0xff;
+ buf[6] = (lv >> 8) & 0xff;
+ buf[7] = lv & 0xff;
+
+ return buf+8;
+}
+
+__inline__ static unsigned char *decode_Ulonglong(unsigned long long *l,
+ unsigned char *buf)
+{
+
+ *l = (((unsigned long long)(buf[ 0 ])) << 56)|(((unsigned long long)(buf[ 1 ])) << 48)|(((unsigned long long)(buf[ 2 ])) << 40)|(((unsigned long long)(buf[ 3 ])) << 32)|
+ (((unsigned long long)(buf[ 4 ])) << 24)|(((unsigned long long)(buf[ 5 ])) << 16)|(((unsigned long long)(buf[ 6 ])) << 8)| ((unsigned long long)(buf[ 7 ])) ;
+
+ return buf+8;
+}
+
+__inline__ static unsigned int sizeof_Ulonglong(const unsigned long long *c)
+{
+ (void)c;
+ return 8;
+}
+
+
+__inline__ static unsigned char *encode_void(const void *v, unsigned char *buf)
+{
+ (void)v;
+ return buf;
+}
+
+__inline__ static unsigned char *decode_void(void *v, unsigned char *buf)
+{
+ (void)v;
+ return buf;
+}
+
+__inline__ static unsigned int sizeof_void(const void *c)
+{
+ (void)c;
+ return 0;
+}
+
+
+
+__inline__ static unsigned char *encode_float(const float *f, unsigned char *buf)
+{
+ *(float *)buf = *f;
+ return buf + sizeof(float);
+}
+
+__inline__ static unsigned char *decode_float(float *f, unsigned char *buf)
+{
+ *f = *(float *)buf;
+ return buf + sizeof(float);
+}
+
+__inline__ static unsigned int sizeof_float(const float *c)
+{
+ (void)c;
+ return sizeof(float);
+}
+
+
+__inline__ static unsigned char *encode_double(const double *d, unsigned char *buf)
+{
+ *(double *)buf = *d;
+ return buf + sizeof(double);
+}
+
+__inline__ static unsigned char *decode_double(double *d, unsigned char *buf)
+{
+ *d = *(double *)buf;
+ return buf + sizeof(double);
+}
+
+__inline__ static unsigned int sizeof_double(const double *c)
+{
+ (void)c;
+ return sizeof(double);
+}
+
+
+
+
+
+
+typedef Ulong _userfs_types_001[32];
+typedef long _userfs_types_002[2];
+typedef Ulong _userfs_types_003[32];
+typedef ushort uf_uid_t;
+typedef ushort uf_gid_t;
+typedef ushort uf_nlink_t;
+typedef ushort uf_dev_t;
+typedef struct _userfs_types_S001 {
+ Ulong nelem;
+ long* elems;
+
+ int alloced;
+ void _userfs_types_S001::alloc(unsigned size) {elems = new long [size]; alloced = 1; }
+ _userfs_types_S001::_userfs_types_S001() { alloced = 0; }
+ _userfs_types_S001::~_userfs_types_S001() {
+ if (alloced) {
+ delete [] elems; alloced = 0;
+ }
+ }
+
+} _userfs_types_004;
+typedef struct
+{
+ uf_uid_t uid;
+ uf_uid_t euid;
+ uf_uid_t suid;
+ uf_uid_t gid;
+ uf_uid_t egid;
+ uf_uid_t sgid;
+ uf_uid_t umask;
+ _userfs_types_004 groups;
+} up_cred;
+typedef struct
+{
+ Ulong ia_valid;
+ umode_t ia_mode;
+ uf_uid_t ia_uid;
+ uf_gid_t ia_gid;
+ off_t ia_size;
+ time_t ia_atime;
+ time_t ia_mtime;
+ time_t ia_ctime;
+} up_iattr;
+typedef struct
+{
+ __s16 version;
+ long seq;
+ Uchar op;
+ Uchar isreq;
+ Ulong size;
+} up_preamble;
+typedef struct
+{
+ __s16 version;
+ long seq;
+ Uchar op;
+ Uchar isreq;
+ Ulong size;
+ long err_no;
+} upp_repl;
+typedef struct
+{
+ umode_t mode;
+ uf_nlink_t nlink;
+ uf_uid_t uid;
+ uf_gid_t gid;
+ off_t size;
+ time_t atime;
+ time_t mtime;
+ time_t ctime;
+ uf_dev_t rdev;
+ Ulong blksize;
+ Ulong blocks;
+} up_inode;
+typedef struct _userfs_types_S002 {
+ Ulong nelem;
+ __s8* elems;
+
+ int alloced;
+ void _userfs_types_S002::alloc(unsigned size) {elems = new __s8 [size]; alloced = 1; }
+ _userfs_types_S002::_userfs_types_S002() { alloced = 0; }
+ _userfs_types_S002::~_userfs_types_S002() {
+ if (alloced) {
+ delete [] elems; alloced = 0;
+ }
+ }
+
+} up_name;
+typedef struct
+{
+ up_inode ino;
+ up_handle handle;
+} upp_iwrite_s;
+typedef struct
+{
+ up_handle handle;
+} upp_iread_s;
+typedef struct
+{
+ up_handle handle;
+ up_inode ino;
+} upp_iread_r;
+typedef struct
+{
+ up_handle dir;
+ up_name name;
+} upp_unlink_s;
+typedef struct
+{
+ up_handle link;
+} upp_readlink_s;
+typedef struct
+{
+ up_name name;
+} upp_readlink_r;
+typedef struct
+{
+ up_handle dir;
+ up_handle link;
+ long flag;
+ long mode;
+} upp_followlink_s;
+typedef struct
+{
+ up_name path;
+} upp_followlink_r;
+typedef struct _userfs_types_S003 {
+ Ulong nelem;
+ long* elems;
+
+ int alloced;
+ void _userfs_types_S003::alloc(unsigned size) {elems = new long [size]; alloced = 1; }
+ _userfs_types_S003::_userfs_types_S003() { alloced = 0; }
+ _userfs_types_S003::~_userfs_types_S003() {
+ if (alloced) {
+ delete [] elems; alloced = 0;
+ }
+ }
+
+} _userfs_types_005;
+typedef struct
+{
+ long mode;
+ up_handle dir;
+ up_cred cred;
+ long rdev;
+ up_name name;
+} upp_create_s;
+typedef struct
+{
+ up_handle file;
+} upp_create_r;
+typedef struct
+{
+ up_handle dir;
+ up_name name;
+} upp_lookup_s;
+typedef struct
+{
+ up_handle handle;
+} upp_lookup_r;
+typedef struct
+{
+ up_handle file;
+ off_t off;
+ off_t size;
+ up_credtok ctok;
+} upp_read_s;
+typedef struct _userfs_types_S004 {
+ Ulong nelem;
+ Uchar* elems;
+
+ int alloced;
+ void _userfs_types_S004::alloc(unsigned size) {elems = new Uchar [size]; alloced = 1; }
+ _userfs_types_S004::_userfs_types_S004() { alloced = 0; }
+ _userfs_types_S004::~_userfs_types_S004() {
+ if (alloced) {
+ delete [] elems; alloced = 0;
+ }
+ }
+
+} _userfs_types_006;
+typedef struct
+{
+ _userfs_types_006 data;
+} upp_read_r;
+typedef struct _userfs_types_S005 {
+ Ulong nelem;
+ Uchar* elems;
+
+ int alloced;
+ void _userfs_types_S005::alloc(unsigned size) {elems = new Uchar [size]; alloced = 1; }
+ _userfs_types_S005::_userfs_types_S005() { alloced = 0; }
+ _userfs_types_S005::~_userfs_types_S005() {
+ if (alloced) {
+ delete [] elems; alloced = 0;
+ }
+ }
+
+} _userfs_types_007;
+typedef struct
+{
+ up_handle file;
+ off_t off;
+ up_credtok ctok;
+ _userfs_types_007 data;
+} upp_write_s;
+typedef struct
+{
+ off_t wrote;
+} upp_write_r;
+typedef struct
+{
+ up_handle dir;
+ off_t off;
+ up_credtok ctok;
+} upp_readdir_s;
+typedef struct
+{
+ up_handle file;
+ off_t off;
+ up_name name;
+} upp_readdir_r;
+typedef upp_readdir_s upp_multireaddir_s;
+typedef struct _userfs_types_S006 {
+ Ulong nelem;
+ upp_readdir_r* elems;
+
+ int alloced;
+ void _userfs_types_S006::alloc(unsigned size) {elems = new upp_readdir_r [size]; alloced = 1; }
+ _userfs_types_S006::_userfs_types_S006() { alloced = 0; }
+ _userfs_types_S006::~_userfs_types_S006() {
+ if (alloced) {
+ delete [] elems; alloced = 0;
+ }
+ }
+
+} upp_multireaddir_r;
+typedef struct
+{
+ up_handle root;
+} upp_mount_r;
+typedef struct
+{
+ up_handle handle;
+} upp_iput_s;
+typedef struct _userfs_types_S007 {
+ Ulong nelem;
+ long* elems;
+
+ int alloced;
+ void _userfs_types_S007::alloc(unsigned size) {elems = new long [size]; alloced = 1; }
+ _userfs_types_S007::_userfs_types_S007() { alloced = 0; }
+ _userfs_types_S007::~_userfs_types_S007() {
+ if (alloced) {
+ delete [] elems; alloced = 0;
+ }
+ }
+
+} _userfs_types_008;
+typedef struct
+{
+ up_cred cred;
+ up_handle file;
+} upp_open_s;
+typedef struct
+{
+ up_credtok ctok;
+} upp_open_r;
+typedef struct
+{
+ up_handle file;
+ up_credtok ctok;
+} upp_close_s;
+typedef struct _userfs_types_S008 {
+ Ulong nelem;
+ long* elems;
+
+ int alloced;
+ void _userfs_types_S008::alloc(unsigned size) {elems = new long [size]; alloced = 1; }
+ _userfs_types_S008::_userfs_types_S008() { alloced = 0; }
+ _userfs_types_S008::~_userfs_types_S008() {
+ if (alloced) {
+ delete [] elems; alloced = 0;
+ }
+ }
+
+} _userfs_types_009;
+typedef struct
+{
+ up_cred cred;
+ up_handle file;
+ long mask;
+} upp_permission_s;
+typedef struct
+{
+ up_handle odir;
+ up_name oname;
+ up_handle ndir;
+ up_name nname;
+} upp_rename_s;
+typedef struct
+{
+ up_handle ofile;
+ up_handle dir;
+ up_name name;
+} upp_link_s;
+typedef struct _userfs_types_S009 {
+ Ulong nelem;
+ long* elems;
+
+ int alloced;
+ void _userfs_types_S009::alloc(unsigned size) {elems = new long [size]; alloced = 1; }
+ _userfs_types_S009::_userfs_types_S009() { alloced = 0; }
+ _userfs_types_S009::~_userfs_types_S009() {
+ if (alloced) {
+ delete [] elems; alloced = 0;
+ }
+ }
+
+} _userfs_types_010;
+typedef struct
+{
+ up_handle dir;
+ up_name name;
+ up_name symname;
+ up_cred cred;
+} upp_symlink_s;
+typedef long _userfs_types_011[2];
+typedef struct
+{
+ __kernel_off_t bsize;
+ __kernel_off_t blocks;
+ __kernel_off_t bfree;
+ __kernel_off_t bavail;
+ __kernel_off_t files;
+ __kernel_off_t ffree;
+ _userfs_types_011 fsid;
+ __kernel_off_t namelen;
+} upp_statfs_r;
+typedef struct
+{
+ up_handle file;
+ off_t size;
+} upp_truncate_s;
+typedef struct
+{
+ up_handle handle;
+ up_iattr iattr;
+} upp_notify_change_s;
+typedef struct
+{
+ up_handle handle;
+ up_version version;
+} upp_inode_valid_s;
+typedef struct
+{
+ up_version version;
+ __s8 valid;
+} upp_inode_valid_r;
+static unsigned char *encode_char(const char *, unsigned char *);
+static unsigned char *decode_char(char *, unsigned char *);
+static unsigned int sizeof_char(const char *);
+
+static unsigned char *encode_short(const short *, unsigned char *);
+static unsigned char *decode_short(short *, unsigned char *);
+static unsigned int sizeof_short(const short *);
+
+static unsigned char *encode_long(const long *, unsigned char *);
+static unsigned char *decode_long(long *, unsigned char *);
+static unsigned int sizeof_long(const long *);
+
+static unsigned char *encode_longlong(const longlong *, unsigned char *);
+static unsigned char *decode_longlong(longlong *, unsigned char *);
+static unsigned int sizeof_longlong(const longlong *);
+
+static unsigned char *encode_float(const float *, unsigned char *);
+static unsigned char *decode_float(float *, unsigned char *);
+static unsigned int sizeof_float(const float *);
+
+static unsigned char *encode_double(const double *, unsigned char *);
+static unsigned char *decode_double(double *, unsigned char *);
+static unsigned int sizeof_double(const double *);
+
+static unsigned char *encode_void(const void *, unsigned char *);
+static unsigned char *decode_void(void *, unsigned char *);
+static unsigned int sizeof_void(const void *);
+
+static unsigned char *encode_Uchar(const Uchar *, unsigned char *);
+static unsigned char *decode_Uchar(Uchar *, unsigned char *);
+static unsigned int sizeof_Uchar(const Uchar *);
+
+static unsigned char *encode_Ushort(const Ushort *, unsigned char *);
+static unsigned char *decode_Ushort(Ushort *, unsigned char *);
+static unsigned int sizeof_Ushort(const Ushort *);
+
+static unsigned char *encode_Ulong(const Ulong *, unsigned char *);
+static unsigned char *decode_Ulong(Ulong *, unsigned char *);
+static unsigned int sizeof_Ulong(const Ulong *);
+
+static unsigned char *encode_Ulonglong(const Ulonglong *, unsigned char *);
+static unsigned char *decode_Ulonglong(Ulonglong *, unsigned char *);
+static unsigned int sizeof_Ulonglong(const Ulonglong *);
+
+unsigned char *encode_Uint(const Uint *, unsigned char *);
+unsigned char *decode_Uint(Uint *, unsigned char *);
+unsigned int sizeof_Uint(const Uint *);
+
+unsigned char *encode_int(const int *, unsigned char *);
+unsigned char *decode_int(int *, unsigned char *);
+unsigned int sizeof_int(const int *);
+
+unsigned char *encode__userfs_types_001(const _userfs_types_001 *, unsigned char *);
+unsigned char *decode__userfs_types_001(_userfs_types_001 *, unsigned char *);
+unsigned int sizeof__userfs_types_001(const _userfs_types_001 *);
+
+unsigned char *encode___kernel_fd_set(const __kernel_fd_set *, unsigned char *);
+unsigned char *decode___kernel_fd_set(__kernel_fd_set *, unsigned char *);
+unsigned int sizeof___kernel_fd_set(const __kernel_fd_set *);
+
+unsigned char *encode___kernel_key_t(const __kernel_key_t *, unsigned char *);
+unsigned char *decode___kernel_key_t(__kernel_key_t *, unsigned char *);
+unsigned int sizeof___kernel_key_t(const __kernel_key_t *);
+
+unsigned char *encode___kernel_dev_t(const __kernel_dev_t *, unsigned char *);
+unsigned char *decode___kernel_dev_t(__kernel_dev_t *, unsigned char *);
+unsigned int sizeof___kernel_dev_t(const __kernel_dev_t *);
+
+unsigned char *encode___kernel_ino_t(const __kernel_ino_t *, unsigned char *);
+unsigned char *decode___kernel_ino_t(__kernel_ino_t *, unsigned char *);
+unsigned int sizeof___kernel_ino_t(const __kernel_ino_t *);
+
+unsigned char *encode___kernel_mode_t(const __kernel_mode_t *, unsigned char *);
+unsigned char *decode___kernel_mode_t(__kernel_mode_t *, unsigned char *);
+unsigned int sizeof___kernel_mode_t(const __kernel_mode_t *);
+
+unsigned char *encode___kernel_nlink_t(const __kernel_nlink_t *, unsigned char *);
+unsigned char *decode___kernel_nlink_t(__kernel_nlink_t *, unsigned char *);
+unsigned int sizeof___kernel_nlink_t(const __kernel_nlink_t *);
+
+unsigned char *encode___kernel_off_t(const __kernel_off_t *, unsigned char *);
+unsigned char *decode___kernel_off_t(__kernel_off_t *, unsigned char *);
+unsigned int sizeof___kernel_off_t(const __kernel_off_t *);
+
+unsigned char *encode___kernel_pid_t(const __kernel_pid_t *, unsigned char *);
+unsigned char *decode___kernel_pid_t(__kernel_pid_t *, unsigned char *);
+unsigned int sizeof___kernel_pid_t(const __kernel_pid_t *);
+
+unsigned char *encode___kernel_ipc_pid_t(const __kernel_ipc_pid_t *, unsigned char *);
+unsigned char *decode___kernel_ipc_pid_t(__kernel_ipc_pid_t *, unsigned char *);
+unsigned int sizeof___kernel_ipc_pid_t(const __kernel_ipc_pid_t *);
+
+unsigned char *encode___kernel_uid_t(const __kernel_uid_t *, unsigned char *);
+unsigned char *decode___kernel_uid_t(__kernel_uid_t *, unsigned char *);
+unsigned int sizeof___kernel_uid_t(const __kernel_uid_t *);
+
+unsigned char *encode___kernel_gid_t(const __kernel_gid_t *, unsigned char *);
+unsigned char *decode___kernel_gid_t(__kernel_gid_t *, unsigned char *);
+unsigned int sizeof___kernel_gid_t(const __kernel_gid_t *);
+
+unsigned char *encode___kernel_size_t(const __kernel_size_t *, unsigned char *);
+unsigned char *decode___kernel_size_t(__kernel_size_t *, unsigned char *);
+unsigned int sizeof___kernel_size_t(const __kernel_size_t *);
+
+unsigned char *encode___kernel_ssize_t(const __kernel_ssize_t *, unsigned char *);
+unsigned char *decode___kernel_ssize_t(__kernel_ssize_t *, unsigned char *);
+unsigned int sizeof___kernel_ssize_t(const __kernel_ssize_t *);
+
+unsigned char *encode___kernel_ptrdiff_t(const __kernel_ptrdiff_t *, unsigned char *);
+unsigned char *decode___kernel_ptrdiff_t(__kernel_ptrdiff_t *, unsigned char *);
+unsigned int sizeof___kernel_ptrdiff_t(const __kernel_ptrdiff_t *);
+
+unsigned char *encode___kernel_time_t(const __kernel_time_t *, unsigned char *);
+unsigned char *decode___kernel_time_t(__kernel_time_t *, unsigned char *);
+unsigned int sizeof___kernel_time_t(const __kernel_time_t *);
+
+unsigned char *encode___kernel_suseconds_t(const __kernel_suseconds_t *, unsigned char *);
+unsigned char *decode___kernel_suseconds_t(__kernel_suseconds_t *, unsigned char *);
+unsigned int sizeof___kernel_suseconds_t(const __kernel_suseconds_t *);
+
+unsigned char *encode___kernel_clock_t(const __kernel_clock_t *, unsigned char *);
+unsigned char *decode___kernel_clock_t(__kernel_clock_t *, unsigned char *);
+unsigned int sizeof___kernel_clock_t(const __kernel_clock_t *);
+
+unsigned char *encode___kernel_daddr_t(const __kernel_daddr_t *, unsigned char *);
+unsigned char *decode___kernel_daddr_t(__kernel_daddr_t *, unsigned char *);
+unsigned int sizeof___kernel_daddr_t(const __kernel_daddr_t *);
+
+unsigned char *encode___kernel_caddr_t(const __kernel_caddr_t *, unsigned char *);
+unsigned char *decode___kernel_caddr_t(__kernel_caddr_t *, unsigned char *);
+unsigned int sizeof___kernel_caddr_t(const __kernel_caddr_t *);
+
+unsigned char *encode___kernel_uid16_t(const __kernel_uid16_t *, unsigned char *);
+unsigned char *decode___kernel_uid16_t(__kernel_uid16_t *, unsigned char *);
+unsigned int sizeof___kernel_uid16_t(const __kernel_uid16_t *);
+
+unsigned char *encode___kernel_gid16_t(const __kernel_gid16_t *, unsigned char *);
+unsigned char *decode___kernel_gid16_t(__kernel_gid16_t *, unsigned char *);
+unsigned int sizeof___kernel_gid16_t(const __kernel_gid16_t *);
+
+unsigned char *encode___kernel_uid32_t(const __kernel_uid32_t *, unsigned char *);
+unsigned char *decode___kernel_uid32_t(__kernel_uid32_t *, unsigned char *);
+unsigned int sizeof___kernel_uid32_t(const __kernel_uid32_t *);
+
+unsigned char *encode___kernel_gid32_t(const __kernel_gid32_t *, unsigned char *);
+unsigned char *decode___kernel_gid32_t(__kernel_gid32_t *, unsigned char *);
+unsigned int sizeof___kernel_gid32_t(const __kernel_gid32_t *);
+
+unsigned char *encode___kernel_old_uid_t(const __kernel_old_uid_t *, unsigned char *);
+unsigned char *decode___kernel_old_uid_t(__kernel_old_uid_t *, unsigned char *);
+unsigned int sizeof___kernel_old_uid_t(const __kernel_old_uid_t *);
+
+unsigned char *encode___kernel_old_gid_t(const __kernel_old_gid_t *, unsigned char *);
+unsigned char *decode___kernel_old_gid_t(__kernel_old_gid_t *, unsigned char *);
+unsigned int sizeof___kernel_old_gid_t(const __kernel_old_gid_t *);
+
+unsigned char *encode__userfs_types_002(const _userfs_types_002 *, unsigned char *);
+unsigned char *decode__userfs_types_002(_userfs_types_002 *, unsigned char *);
+unsigned int sizeof__userfs_types_002(const _userfs_types_002 *);
+
+unsigned char *encode___kernel_fsid_t(const __kernel_fsid_t *, unsigned char *);
+unsigned char *decode___kernel_fsid_t(__kernel_fsid_t *, unsigned char *);
+unsigned int sizeof___kernel_fsid_t(const __kernel_fsid_t *);
+
+unsigned char *encode_umode_t(const umode_t *, unsigned char *);
+unsigned char *decode_umode_t(umode_t *, unsigned char *);
+unsigned int sizeof_umode_t(const umode_t *);
+
+unsigned char *encode___s8(const __s8 *, unsigned char *);
+unsigned char *decode___s8(__s8 *, unsigned char *);
+unsigned int sizeof___s8(const __s8 *);
+
+unsigned char *encode___u8(const __u8 *, unsigned char *);
+unsigned char *decode___u8(__u8 *, unsigned char *);
+unsigned int sizeof___u8(const __u8 *);
+
+unsigned char *encode___s16(const __s16 *, unsigned char *);
+unsigned char *decode___s16(__s16 *, unsigned char *);
+unsigned int sizeof___s16(const __s16 *);
+
+unsigned char *encode___u16(const __u16 *, unsigned char *);
+unsigned char *decode___u16(__u16 *, unsigned char *);
+unsigned int sizeof___u16(const __u16 *);
+
+unsigned char *encode___s32(const __s32 *, unsigned char *);
+unsigned char *decode___s32(__s32 *, unsigned char *);
+unsigned int sizeof___s32(const __s32 *);
+
+unsigned char *encode___u32(const __u32 *, unsigned char *);
+unsigned char *decode___u32(__u32 *, unsigned char *);
+unsigned int sizeof___u32(const __u32 *);
+
+unsigned char *encode__userfs_types_003(const _userfs_types_003 *, unsigned char *);
+unsigned char *decode__userfs_types_003(_userfs_types_003 *, unsigned char *);
+unsigned int sizeof__userfs_types_003(const _userfs_types_003 *);
+
+unsigned char *encode_fd_set(const fd_set *, unsigned char *);
+unsigned char *decode_fd_set(fd_set *, unsigned char *);
+unsigned int sizeof_fd_set(const fd_set *);
+
+unsigned char *encode_dev_t(const dev_t *, unsigned char *);
+unsigned char *decode_dev_t(dev_t *, unsigned char *);
+unsigned int sizeof_dev_t(const dev_t *);
+
+unsigned char *encode_ino_t(const ino_t *, unsigned char *);
+unsigned char *decode_ino_t(ino_t *, unsigned char *);
+unsigned int sizeof_ino_t(const ino_t *);
+
+unsigned char *encode_mode_t(const mode_t *, unsigned char *);
+unsigned char *decode_mode_t(mode_t *, unsigned char *);
+unsigned int sizeof_mode_t(const mode_t *);
+
+unsigned char *encode_nlink_t(const nlink_t *, unsigned char *);
+unsigned char *decode_nlink_t(nlink_t *, unsigned char *);
+unsigned int sizeof_nlink_t(const nlink_t *);
+
+unsigned char *encode_off_t(const off_t *, unsigned char *);
+unsigned char *decode_off_t(off_t *, unsigned char *);
+unsigned int sizeof_off_t(const off_t *);
+
+unsigned char *encode_pid_t(const pid_t *, unsigned char *);
+unsigned char *decode_pid_t(pid_t *, unsigned char *);
+unsigned int sizeof_pid_t(const pid_t *);
+
+unsigned char *encode_daddr_t(const daddr_t *, unsigned char *);
+unsigned char *decode_daddr_t(daddr_t *, unsigned char *);
+unsigned int sizeof_daddr_t(const daddr_t *);
+
+unsigned char *encode_key_t(const key_t *, unsigned char *);
+unsigned char *decode_key_t(key_t *, unsigned char *);
+unsigned int sizeof_key_t(const key_t *);
+
+unsigned char *encode_suseconds_t(const suseconds_t *, unsigned char *);
+unsigned char *decode_suseconds_t(suseconds_t *, unsigned char *);
+unsigned int sizeof_suseconds_t(const suseconds_t *);
+
+unsigned char *encode_uid_t(const uid_t *, unsigned char *);
+unsigned char *decode_uid_t(uid_t *, unsigned char *);
+unsigned int sizeof_uid_t(const uid_t *);
+
+unsigned char *encode_gid_t(const gid_t *, unsigned char *);
+unsigned char *decode_gid_t(gid_t *, unsigned char *);
+unsigned int sizeof_gid_t(const gid_t *);
+
+unsigned char *encode_size_t(const size_t *, unsigned char *);
+unsigned char *decode_size_t(size_t *, unsigned char *);
+unsigned int sizeof_size_t(const size_t *);
+
+unsigned char *encode_ssize_t(const ssize_t *, unsigned char *);
+unsigned char *decode_ssize_t(ssize_t *, unsigned char *);
+unsigned int sizeof_ssize_t(const ssize_t *);
+
+unsigned char *encode_ptrdiff_t(const ptrdiff_t *, unsigned char *);
+unsigned char *decode_ptrdiff_t(ptrdiff_t *, unsigned char *);
+unsigned int sizeof_ptrdiff_t(const ptrdiff_t *);
+
+unsigned char *encode_time_t(const time_t *, unsigned char *);
+unsigned char *decode_time_t(time_t *, unsigned char *);
+unsigned int sizeof_time_t(const time_t *);
+
+unsigned char *encode_clock_t(const clock_t *, unsigned char *);
+unsigned char *decode_clock_t(clock_t *, unsigned char *);
+unsigned int sizeof_clock_t(const clock_t *);
+
+unsigned char *encode_caddr_t(const caddr_t *, unsigned char *);
+unsigned char *decode_caddr_t(caddr_t *, unsigned char *);
+unsigned int sizeof_caddr_t(const caddr_t *);
+
+unsigned char *encode_u_char(const u_char *, unsigned char *);
+unsigned char *decode_u_char(u_char *, unsigned char *);
+unsigned int sizeof_u_char(const u_char *);
+
+unsigned char *encode_u_short(const u_short *, unsigned char *);
+unsigned char *decode_u_short(u_short *, unsigned char *);
+unsigned int sizeof_u_short(const u_short *);
+
+unsigned char *encode_u_int(const u_int *, unsigned char *);
+unsigned char *decode_u_int(u_int *, unsigned char *);
+unsigned int sizeof_u_int(const u_int *);
+
+unsigned char *encode_u_long(const u_long *, unsigned char *);
+unsigned char *decode_u_long(u_long *, unsigned char *);
+unsigned int sizeof_u_long(const u_long *);
+
+unsigned char *encode_unchar(const unchar *, unsigned char *);
+unsigned char *decode_unchar(unchar *, unsigned char *);
+unsigned int sizeof_unchar(const unchar *);
+
+unsigned char *encode_ushort(const ushort *, unsigned char *);
+unsigned char *decode_ushort(ushort *, unsigned char *);
+unsigned int sizeof_ushort(const ushort *);
+
+unsigned char *encode_uint(const uint *, unsigned char *);
+unsigned char *decode_uint(uint *, unsigned char *);
+unsigned int sizeof_uint(const uint *);
+
+unsigned char *encode_ulong(const ulong *, unsigned char *);
+unsigned char *decode_ulong(ulong *, unsigned char *);
+unsigned int sizeof_ulong(const ulong *);
+
+unsigned char *encode_u_int8_t(const u_int8_t *, unsigned char *);
+unsigned char *decode_u_int8_t(u_int8_t *, unsigned char *);
+unsigned int sizeof_u_int8_t(const u_int8_t *);
+
+unsigned char *encode_int8_t(const int8_t *, unsigned char *);
+unsigned char *decode_int8_t(int8_t *, unsigned char *);
+unsigned int sizeof_int8_t(const int8_t *);
+
+unsigned char *encode_u_int16_t(const u_int16_t *, unsigned char *);
+unsigned char *decode_u_int16_t(u_int16_t *, unsigned char *);
+unsigned int sizeof_u_int16_t(const u_int16_t *);
+
+unsigned char *encode_int16_t(const int16_t *, unsigned char *);
+unsigned char *decode_int16_t(int16_t *, unsigned char *);
+unsigned int sizeof_int16_t(const int16_t *);
+
+unsigned char *encode_u_int32_t(const u_int32_t *, unsigned char *);
+unsigned char *decode_u_int32_t(u_int32_t *, unsigned char *);
+unsigned int sizeof_u_int32_t(const u_int32_t *);
+
+unsigned char *encode_int32_t(const int32_t *, unsigned char *);
+unsigned char *decode_int32_t(int32_t *, unsigned char *);
+unsigned int sizeof_int32_t(const int32_t *);
+
+unsigned char *encode_uint8_t(const uint8_t *, unsigned char *);
+unsigned char *decode_uint8_t(uint8_t *, unsigned char *);
+unsigned int sizeof_uint8_t(const uint8_t *);
+
+unsigned char *encode_uint16_t(const uint16_t *, unsigned char *);
+unsigned char *decode_uint16_t(uint16_t *, unsigned char *);
+unsigned int sizeof_uint16_t(const uint16_t *);
+
+unsigned char *encode_uint32_t(const uint32_t *, unsigned char *);
+unsigned char *decode_uint32_t(uint32_t *, unsigned char *);
+unsigned int sizeof_uint32_t(const uint32_t *);
+
+unsigned char *encode_up_handle(const up_handle *, unsigned char *);
+unsigned char *decode_up_handle(up_handle *, unsigned char *);
+unsigned int sizeof_up_handle(const up_handle *);
+
+unsigned char *encode_up_version(const up_version *, unsigned char *);
+unsigned char *decode_up_version(up_version *, unsigned char *);
+unsigned int sizeof_up_version(const up_version *);
+
+unsigned char *encode_up_credtok(const up_credtok *, unsigned char *);
+unsigned char *decode_up_credtok(up_credtok *, unsigned char *);
+unsigned int sizeof_up_credtok(const up_credtok *);
+
+unsigned char *encode_uf_uid_t(const uf_uid_t *, unsigned char *);
+unsigned char *decode_uf_uid_t(uf_uid_t *, unsigned char *);
+unsigned int sizeof_uf_uid_t(const uf_uid_t *);
+
+unsigned char *encode_uf_gid_t(const uf_gid_t *, unsigned char *);
+unsigned char *decode_uf_gid_t(uf_gid_t *, unsigned char *);
+unsigned int sizeof_uf_gid_t(const uf_gid_t *);
+
+unsigned char *encode_uf_nlink_t(const uf_nlink_t *, unsigned char *);
+unsigned char *decode_uf_nlink_t(uf_nlink_t *, unsigned char *);
+unsigned int sizeof_uf_nlink_t(const uf_nlink_t *);
+
+unsigned char *encode_uf_dev_t(const uf_dev_t *, unsigned char *);
+unsigned char *decode_uf_dev_t(uf_dev_t *, unsigned char *);
+unsigned int sizeof_uf_dev_t(const uf_dev_t *);
+
+unsigned char *encode__userfs_types_004(const _userfs_types_004 *, unsigned char *);
+unsigned char *decode__userfs_types_004(_userfs_types_004 *, unsigned char *);
+unsigned int sizeof__userfs_types_004(const _userfs_types_004 *);
+
+unsigned char *encode_up_cred(const up_cred *, unsigned char *);
+unsigned char *decode_up_cred(up_cred *, unsigned char *);
+unsigned int sizeof_up_cred(const up_cred *);
+
+unsigned char *encode_up_iattr(const up_iattr *, unsigned char *);
+unsigned char *decode_up_iattr(up_iattr *, unsigned char *);
+unsigned int sizeof_up_iattr(const up_iattr *);
+
+unsigned char *encode_up_preamble(const up_preamble *, unsigned char *);
+unsigned char *decode_up_preamble(up_preamble *, unsigned char *);
+unsigned int sizeof_up_preamble(const up_preamble *);
+
+unsigned char *encode_upp_repl(const upp_repl *, unsigned char *);
+unsigned char *decode_upp_repl(upp_repl *, unsigned char *);
+unsigned int sizeof_upp_repl(const upp_repl *);
+
+unsigned char *encode_up_inode(const up_inode *, unsigned char *);
+unsigned char *decode_up_inode(up_inode *, unsigned char *);
+unsigned int sizeof_up_inode(const up_inode *);
+
+unsigned char *encode_up_name(const up_name *, unsigned char *);
+unsigned char *decode_up_name(up_name *, unsigned char *);
+unsigned int sizeof_up_name(const up_name *);
+
+unsigned char *encode_upp_iwrite_s(const upp_iwrite_s *, unsigned char *);
+unsigned char *decode_upp_iwrite_s(upp_iwrite_s *, unsigned char *);
+unsigned int sizeof_upp_iwrite_s(const upp_iwrite_s *);
+
+unsigned char *encode_upp_iread_s(const upp_iread_s *, unsigned char *);
+unsigned char *decode_upp_iread_s(upp_iread_s *, unsigned char *);
+unsigned int sizeof_upp_iread_s(const upp_iread_s *);
+
+unsigned char *encode_upp_iread_r(const upp_iread_r *, unsigned char *);
+unsigned char *decode_upp_iread_r(upp_iread_r *, unsigned char *);
+unsigned int sizeof_upp_iread_r(const upp_iread_r *);
+
+unsigned char *encode_upp_unlink_s(const upp_unlink_s *, unsigned char *);
+unsigned char *decode_upp_unlink_s(upp_unlink_s *, unsigned char *);
+unsigned int sizeof_upp_unlink_s(const upp_unlink_s *);
+
+unsigned char *encode_upp_readlink_s(const upp_readlink_s *, unsigned char *);
+unsigned char *decode_upp_readlink_s(upp_readlink_s *, unsigned char *);
+unsigned int sizeof_upp_readlink_s(const upp_readlink_s *);
+
+unsigned char *encode_upp_readlink_r(const upp_readlink_r *, unsigned char *);
+unsigned char *decode_upp_readlink_r(upp_readlink_r *, unsigned char *);
+unsigned int sizeof_upp_readlink_r(const upp_readlink_r *);
+
+unsigned char *encode_upp_followlink_s(const upp_followlink_s *, unsigned char *);
+unsigned char *decode_upp_followlink_s(upp_followlink_s *, unsigned char *);
+unsigned int sizeof_upp_followlink_s(const upp_followlink_s *);
+
+unsigned char *encode_upp_followlink_r(const upp_followlink_r *, unsigned char *);
+unsigned char *decode_upp_followlink_r(upp_followlink_r *, unsigned char *);
+unsigned int sizeof_upp_followlink_r(const upp_followlink_r *);
+
+unsigned char *encode__userfs_types_005(const _userfs_types_005 *, unsigned char *);
+unsigned char *decode__userfs_types_005(_userfs_types_005 *, unsigned char *);
+unsigned int sizeof__userfs_types_005(const _userfs_types_005 *);
+
+unsigned char *encode_upp_create_s(const upp_create_s *, unsigned char *);
+unsigned char *decode_upp_create_s(upp_create_s *, unsigned char *);
+unsigned int sizeof_upp_create_s(const upp_create_s *);
+
+unsigned char *encode_upp_create_r(const upp_create_r *, unsigned char *);
+unsigned char *decode_upp_create_r(upp_create_r *, unsigned char *);
+unsigned int sizeof_upp_create_r(const upp_create_r *);
+
+unsigned char *encode_upp_lookup_s(const upp_lookup_s *, unsigned char *);
+unsigned char *decode_upp_lookup_s(upp_lookup_s *, unsigned char *);
+unsigned int sizeof_upp_lookup_s(const upp_lookup_s *);
+
+unsigned char *encode_upp_lookup_r(const upp_lookup_r *, unsigned char *);
+unsigned char *decode_upp_lookup_r(upp_lookup_r *, unsigned char *);
+unsigned int sizeof_upp_lookup_r(const upp_lookup_r *);
+
+unsigned char *encode_upp_read_s(const upp_read_s *, unsigned char *);
+unsigned char *decode_upp_read_s(upp_read_s *, unsigned char *);
+unsigned int sizeof_upp_read_s(const upp_read_s *);
+
+unsigned char *encode__userfs_types_006(const _userfs_types_006 *, unsigned char *);
+unsigned char *decode__userfs_types_006(_userfs_types_006 *, unsigned char *);
+unsigned int sizeof__userfs_types_006(const _userfs_types_006 *);
+
+unsigned char *encode_upp_read_r(const upp_read_r *, unsigned char *);
+unsigned char *decode_upp_read_r(upp_read_r *, unsigned char *);
+unsigned int sizeof_upp_read_r(const upp_read_r *);
+
+unsigned char *encode__userfs_types_007(const _userfs_types_007 *, unsigned char *);
+unsigned char *decode__userfs_types_007(_userfs_types_007 *, unsigned char *);
+unsigned int sizeof__userfs_types_007(const _userfs_types_007 *);
+
+unsigned char *encode_upp_write_s(const upp_write_s *, unsigned char *);
+unsigned char *decode_upp_write_s(upp_write_s *, unsigned char *);
+unsigned int sizeof_upp_write_s(const upp_write_s *);
+
+unsigned char *encode_upp_write_r(const upp_write_r *, unsigned char *);
+unsigned char *decode_upp_write_r(upp_write_r *, unsigned char *);
+unsigned int sizeof_upp_write_r(const upp_write_r *);
+
+unsigned char *encode_upp_readdir_s(const upp_readdir_s *, unsigned char *);
+unsigned char *decode_upp_readdir_s(upp_readdir_s *, unsigned char *);
+unsigned int sizeof_upp_readdir_s(const upp_readdir_s *);
+
+unsigned char *encode_upp_readdir_r(const upp_readdir_r *, unsigned char *);
+unsigned char *decode_upp_readdir_r(upp_readdir_r *, unsigned char *);
+unsigned int sizeof_upp_readdir_r(const upp_readdir_r *);
+
+unsigned char *encode_upp_multireaddir_s(const upp_multireaddir_s *, unsigned char *);
+unsigned char *decode_upp_multireaddir_s(upp_multireaddir_s *, unsigned char *);
+unsigned int sizeof_upp_multireaddir_s(const upp_multireaddir_s *);
+
+unsigned char *encode_upp_multireaddir_r(const upp_multireaddir_r *, unsigned char *);
+unsigned char *decode_upp_multireaddir_r(upp_multireaddir_r *, unsigned char *);
+unsigned int sizeof_upp_multireaddir_r(const upp_multireaddir_r *);
+
+unsigned char *encode_upp_mount_r(const upp_mount_r *, unsigned char *);
+unsigned char *decode_upp_mount_r(upp_mount_r *, unsigned char *);
+unsigned int sizeof_upp_mount_r(const upp_mount_r *);
+
+unsigned char *encode_upp_iput_s(const upp_iput_s *, unsigned char *);
+unsigned char *decode_upp_iput_s(upp_iput_s *, unsigned char *);
+unsigned int sizeof_upp_iput_s(const upp_iput_s *);
+
+unsigned char *encode__userfs_types_008(const _userfs_types_008 *, unsigned char *);
+unsigned char *decode__userfs_types_008(_userfs_types_008 *, unsigned char *);
+unsigned int sizeof__userfs_types_008(const _userfs_types_008 *);
+
+unsigned char *encode_upp_open_s(const upp_open_s *, unsigned char *);
+unsigned char *decode_upp_open_s(upp_open_s *, unsigned char *);
+unsigned int sizeof_upp_open_s(const upp_open_s *);
+
+unsigned char *encode_upp_open_r(const upp_open_r *, unsigned char *);
+unsigned char *decode_upp_open_r(upp_open_r *, unsigned char *);
+unsigned int sizeof_upp_open_r(const upp_open_r *);
+
+unsigned char *encode_upp_close_s(const upp_close_s *, unsigned char *);
+unsigned char *decode_upp_close_s(upp_close_s *, unsigned char *);
+unsigned int sizeof_upp_close_s(const upp_close_s *);
+
+unsigned char *encode__userfs_types_009(const _userfs_types_009 *, unsigned char *);
+unsigned char *decode__userfs_types_009(_userfs_types_009 *, unsigned char *);
+unsigned int sizeof__userfs_types_009(const _userfs_types_009 *);
+
+unsigned char *encode_upp_permission_s(const upp_permission_s *, unsigned char *);
+unsigned char *decode_upp_permission_s(upp_permission_s *, unsigned char *);
+unsigned int sizeof_upp_permission_s(const upp_permission_s *);
+
+unsigned char *encode_upp_rename_s(const upp_rename_s *, unsigned char *);
+unsigned char *decode_upp_rename_s(upp_rename_s *, unsigned char *);
+unsigned int sizeof_upp_rename_s(const upp_rename_s *);
+
+unsigned char *encode_upp_link_s(const upp_link_s *, unsigned char *);
+unsigned char *decode_upp_link_s(upp_link_s *, unsigned char *);
+unsigned int sizeof_upp_link_s(const upp_link_s *);
+
+unsigned char *encode__userfs_types_010(const _userfs_types_010 *, unsigned char *);
+unsigned char *decode__userfs_types_010(_userfs_types_010 *, unsigned char *);
+unsigned int sizeof__userfs_types_010(const _userfs_types_010 *);
+
+unsigned char *encode_upp_symlink_s(const upp_symlink_s *, unsigned char *);
+unsigned char *decode_upp_symlink_s(upp_symlink_s *, unsigned char *);
+unsigned int sizeof_upp_symlink_s(const upp_symlink_s *);
+
+unsigned char *encode__userfs_types_011(const _userfs_types_011 *, unsigned char *);
+unsigned char *decode__userfs_types_011(_userfs_types_011 *, unsigned char *);
+unsigned int sizeof__userfs_types_011(const _userfs_types_011 *);
+
+unsigned char *encode_upp_statfs_r(const upp_statfs_r *, unsigned char *);
+unsigned char *decode_upp_statfs_r(upp_statfs_r *, unsigned char *);
+unsigned int sizeof_upp_statfs_r(const upp_statfs_r *);
+
+unsigned char *encode_upp_truncate_s(const upp_truncate_s *, unsigned char *);
+unsigned char *decode_upp_truncate_s(upp_truncate_s *, unsigned char *);
+unsigned int sizeof_upp_truncate_s(const upp_truncate_s *);
+
+unsigned char *encode_upp_notify_change_s(const upp_notify_change_s *, unsigned char *);
+unsigned char *decode_upp_notify_change_s(upp_notify_change_s *, unsigned char *);
+unsigned int sizeof_upp_notify_change_s(const upp_notify_change_s *);
+
+unsigned char *encode_upp_inode_valid_s(const upp_inode_valid_s *, unsigned char *);
+unsigned char *decode_upp_inode_valid_s(upp_inode_valid_s *, unsigned char *);
+unsigned int sizeof_upp_inode_valid_s(const upp_inode_valid_s *);
+
+unsigned char *encode_upp_inode_valid_r(const upp_inode_valid_r *, unsigned char *);
+unsigned char *decode_upp_inode_valid_r(upp_inode_valid_r *, unsigned char *);
+unsigned int sizeof_upp_inode_valid_r(const upp_inode_valid_r *);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern "C" {
+
+
+extern void __assert_fail (__const char *__assertion, __const char *__file,
+ unsigned int __line, __const char *__function)
+ throw () __attribute__ ((__noreturn__));
+
+
+extern void __assert_perror_fail (int __errnum, __const char *__file,
+ unsigned int __line,
+ __const char *__function)
+ throw () __attribute__ ((__noreturn__));
+
+
+
+
+extern void __assert (const char *__assertion, const char *__file, int __line)
+ throw () __attribute__ ((__noreturn__));
+
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern "C" {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern int errno;
+
+
+extern int *__errno_location (void) throw () __attribute__ ((__const__));
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
+
+
+
+
+
+
+
+
+
+
+
+#pragma interface
+
+typedef unsigned long Handle;
+class Filesystem;
+
+class InodeList;
+class DirInode;
+
+class Inode
+{
+ friend InodeList;
+ friend DirInode;
+
+private:
+ Inode *next, *prev;
+ short alive, onlist;
+
+protected:
+
+ uid_t uid;
+ gid_t gid;
+ umode_t mode;
+ nlink_t nlink;
+ off_t size;
+ time_t atime;
+ time_t mtime;
+ time_t ctime;
+ dev_t rdev;
+
+
+ Handle handle;
+
+
+ Filesystem &filesys;
+
+ Inode *findino(Handle h);
+
+
+
+ virtual void update() {}
+
+ virtual void cleanup() {}
+public:
+ Inode(Filesystem &, Handle);
+ virtual ~Inode();
+
+ Handle gethandle() { return handle; }
+ Filesystem &getfilesys() { return filesys; }
+
+ virtual void incref() { nlink++; }
+ virtual void decref() { nlink--; }
+
+ virtual void beforeop(enum up_ops) { }
+ virtual void afterop(enum up_ops) { }
+
+ virtual int link(const char *, int, Inode *) { return 38 ; }
+ virtual int unlink(const char *, int) { return 38 ; }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+virtual int do_create (const up_preamble &, upp_repl &, const upp_create_s &, upp_create_r &) ;
+virtual int do_lookup (const up_preamble &, upp_repl &, const upp_lookup_s &, upp_lookup_r &) ;
+virtual int do_link (const up_preamble &, upp_repl &, const upp_link_s &) ;
+virtual int do_unlink (const up_preamble &, upp_repl &, const upp_unlink_s &) ;
+virtual int do_symlink (const up_preamble &, upp_repl &, const upp_symlink_s &) ;
+virtual int do_rename (const up_preamble &, upp_repl &, const upp_rename_s &) ;
+virtual int do_readlink (const up_preamble &, upp_repl &, const upp_readlink_s &, upp_readlink_r &) ;
+virtual int do_followlink (const up_preamble &, upp_repl &, const upp_followlink_s &, upp_followlink_r &) ;
+virtual int do_permission (const up_preamble &, upp_repl &, const upp_permission_s &) ;
+virtual int do_iwrite (const up_preamble &, upp_repl &, const upp_iwrite_s &) ;
+virtual int do_iread (const up_preamble &, upp_repl &, const upp_iread_s &, upp_iread_r &) ;
+virtual int do_iput (const up_preamble &, upp_repl &, const upp_iput_s &) ;
+virtual int do_notify_change (const up_preamble &, upp_repl &, const upp_notify_change_s &) ;
+virtual int do_truncate (const up_preamble &, upp_repl &, const upp_truncate_s &) ;
+virtual int do_inode_valid (const up_preamble &, upp_repl &, const upp_inode_valid_s &, upp_inode_valid_r &) ;
+
+
+
+
+
+
+
+virtual int do_read (const up_preamble &, upp_repl &, const upp_read_s &, upp_read_r &) ;
+virtual int do_write (const up_preamble &, upp_repl &, const upp_write_s &, upp_write_r &) ;
+virtual int do_readdir (const up_preamble &, upp_repl &, const upp_readdir_s &, upp_readdir_r &) ;
+virtual int do_multireaddir (const up_preamble &, upp_repl &, const upp_multireaddir_s &, upp_multireaddir_r &) ;
+virtual int do_open (const up_preamble &, upp_repl &, const upp_open_s &, upp_open_r &) ;
+virtual int do_close (const up_preamble &, upp_repl &, const upp_close_s &) ;
+
+
+
+
+
+
+
+
+
+
+};
+
+
+
+
+class InodeList
+{
+private:
+ Inode *list;
+
+public:
+ InodeList();
+ ~InodeList();
+ Inode *find(Handle);
+ void add(Inode *);
+ void del(Inode *);
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef __suseconds_t suseconds_t;
+
+
+
+
+extern "C" {
+
+
+
+
+
+
+
+struct timezone
+ {
+ int tz_minuteswest;
+ int tz_dsttime;
+ };
+
+typedef struct timezone *__restrict __timezone_ptr_t;
+
+
+
+
+
+
+
+extern int gettimeofday (struct timeval *__restrict __tv,
+ __timezone_ptr_t __tz) throw () ;
+
+
+
+
+extern int settimeofday (__const struct timeval *__tv,
+ __const struct timezone *__tz) throw () ;
+
+
+
+
+
+extern int adjtime (__const struct timeval *__delta,
+ struct timeval *__olddelta) throw () ;
+
+
+
+
+enum __itimer_which
+ {
+
+ ITIMER_REAL = 0,
+
+
+ ITIMER_VIRTUAL = 1,
+
+
+
+ ITIMER_PROF = 2
+
+ };
+
+
+
+struct itimerval
+ {
+
+ struct timeval it_interval;
+
+ struct timeval it_value;
+ };
+
+
+typedef int __itimer_which_t;
+
+
+
+
+extern int getitimer (__itimer_which_t __which,
+ struct itimerval *__value) throw () ;
+
+
+
+
+extern int setitimer (__itimer_which_t __which,
+ __const struct itimerval *__restrict __new,
+ struct itimerval *__restrict __old) throw () ;
+
+
+
+extern int utimes (__const char *__file, __const struct timeval __tvp[2])
+ throw () ;
+
+
+
+
+
+
+
+
+
+
+
+
+}
+
+
+
+
+#pragma interface
+
+class Filesystem;
+class DispatchFD;
+class DispToKern;
+
+
+
+
+
+
+
+
+
+
+class CommBase
+{
+ friend Filesystem;
+ friend DispToKern;
+
+
+ struct dispq_t
+ {
+ struct disp_fd *h, *t;
+ } dispqs[4 ];
+ int dispatches;
+
+
+ unsigned int tokern;
+
+protected:
+
+ Filesystem &filesys;
+
+ DispatchFD *req;
+
+public:
+ CommBase(Filesystem &, unsigned int to, unsigned int from);
+ virtual ~CommBase();
+
+ struct disp_fd *addDispatch(int fd, DispatchFD *dfd, int what= 1 , int pri = 2);
+ void delDispatch(struct disp_fd *);
+
+
+ int Run();
+
+
+ int DeferRepl();
+
+
+
+ void CloseFDs(int all = 0);
+};
+
+
+class DispatchFD
+{
+public:
+ virtual int dispatch(int fd, int what) = 0;
+ virtual ~DispatchFD();
+};
+
+
+class DispToKern : public DispatchFD
+{
+protected:
+ int tokern;
+public:
+ DispToKern(const CommBase *);
+};
+
+
+
+
+#pragma interface
+
+typedef unsigned char Data;
+class Comm;
+
+class Filesystem
+{
+ friend CommBase;
+ friend Inode;
+
+ const char *mpoint;
+
+ CommBase *comm_p;
+ void setcomm(CommBase *c) { comm_p = c; }
+
+protected:
+ InodeList inodes;
+ virtual int Enquire(up_ops op);
+
+ Handle rootdir;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+virtual int do_mount (const up_preamble &, upp_repl &, upp_mount_r &) ;
+virtual int do_umount (const up_preamble &, upp_repl &) ;
+virtual int do_statfs (const up_preamble &, upp_repl &, upp_statfs_r &) ;
+
+
+
+
+
+
+
+virtual int do_create (const up_preamble &, upp_repl &, const upp_create_s &, upp_create_r &) ;
+virtual int do_lookup (const up_preamble &, upp_repl &, const upp_lookup_s &, upp_lookup_r &) ;
+virtual int do_link (const up_preamble &, upp_repl &, const upp_link_s &) ;
+virtual int do_unlink (const up_preamble &, upp_repl &, const upp_unlink_s &) ;
+virtual int do_symlink (const up_preamble &, upp_repl &, const upp_symlink_s &) ;
+virtual int do_rename (const up_preamble &, upp_repl &, const upp_rename_s &) ;
+virtual int do_readlink (const up_preamble &, upp_repl &, const upp_readlink_s &, upp_readlink_r &) ;
+virtual int do_followlink (const up_preamble &, upp_repl &, const upp_followlink_s &, upp_followlink_r &) ;
+virtual int do_permission (const up_preamble &, upp_repl &, const upp_permission_s &) ;
+virtual int do_iwrite (const up_preamble &, upp_repl &, const upp_iwrite_s &) ;
+virtual int do_iread (const up_preamble &, upp_repl &, const upp_iread_s &, upp_iread_r &) ;
+virtual int do_iput (const up_preamble &, upp_repl &, const upp_iput_s &) ;
+virtual int do_notify_change (const up_preamble &, upp_repl &, const upp_notify_change_s &) ;
+virtual int do_truncate (const up_preamble &, upp_repl &, const upp_truncate_s &) ;
+virtual int do_inode_valid (const up_preamble &, upp_repl &, const upp_inode_valid_s &, upp_inode_valid_r &) ;
+
+
+
+
+
+
+
+virtual int do_read (const up_preamble &, upp_repl &, const upp_read_s &, upp_read_r &) ;
+virtual int do_write (const up_preamble &, upp_repl &, const upp_write_s &, upp_write_r &) ;
+virtual int do_readdir (const up_preamble &, upp_repl &, const upp_readdir_s &, upp_readdir_r &) ;
+virtual int do_multireaddir (const up_preamble &, upp_repl &, const upp_multireaddir_s &, upp_multireaddir_r &) ;
+virtual int do_open (const up_preamble &, upp_repl &, const upp_open_s &, upp_open_r &) ;
+virtual int do_close (const up_preamble &, upp_repl &, const upp_close_s &) ;
+
+
+
+
+
+
+
+
+
+
+
+public:
+ Filesystem(const char *mpoint);
+ virtual ~Filesystem();
+
+ Inode *findino(Handle h) { return inodes.find(h); }
+
+
+
+ int DoOp(const up_preamble &, upp_repl &, Data *data);
+
+ CommBase *comm() const { return comm_p; }
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern "C" {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef struct _IO_FILE FILE;
+
+
+
+
+
+
+
+
+
+typedef struct _IO_FILE __FILE;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef struct
+{
+ int __count;
+ union
+ {
+ wint_t __wch;
+ char __wchb[4];
+ } __value;
+} __mbstate_t;
+
+
+
+
+
+
+
+
+
+
+
+typedef struct
+{
+ __off_t __pos;
+ __mbstate_t __state;
+} _G_fpos_t;
+typedef struct
+{
+ __off64_t __pos;
+ __mbstate_t __state;
+} _G_fpos64_t;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+enum
+{
+ __GCONV_OK = 0,
+ __GCONV_NOCONV,
+ __GCONV_NODB,
+ __GCONV_NOMEM,
+
+ __GCONV_EMPTY_INPUT,
+ __GCONV_FULL_OUTPUT,
+ __GCONV_ILLEGAL_INPUT,
+ __GCONV_INCOMPLETE_INPUT,
+
+ __GCONV_ILLEGAL_DESCRIPTOR,
+ __GCONV_INTERNAL_ERROR
+};
+
+
+
+enum
+{
+ __GCONV_IS_LAST = 0x0001,
+ __GCONV_IGNORE_ERRORS = 0x0002
+};
+
+
+
+struct __gconv_step;
+struct __gconv_step_data;
+struct __gconv_loaded_object;
+struct __gconv_trans_data;
+
+
+
+typedef int (*__gconv_fct) (struct __gconv_step *, struct __gconv_step_data *,
+ __const unsigned char **, __const unsigned char *,
+ unsigned char **, size_t *, int, int);
+
+
+typedef int (*__gconv_init_fct) (struct __gconv_step *);
+typedef void (*__gconv_end_fct) (struct __gconv_step *);
+
+
+
+typedef int (*__gconv_trans_fct) (struct __gconv_step *,
+ struct __gconv_step_data *, void *,
+ __const unsigned char *,
+ __const unsigned char **,
+ __const unsigned char *, unsigned char **,
+ size_t *);
+
+
+typedef int (*__gconv_trans_context_fct) (void *, __const unsigned char *,
+ __const unsigned char *,
+ unsigned char *, unsigned char *);
+
+
+typedef int (*__gconv_trans_query_fct) (__const char *, __const char ***,
+ size_t *);
+
+
+typedef int (*__gconv_trans_init_fct) (void **, const char *);
+typedef void (*__gconv_trans_end_fct) (void *);
+
+struct __gconv_trans_data
+{
+
+ __gconv_trans_fct __trans_fct;
+ __gconv_trans_context_fct __trans_context_fct;
+ __gconv_trans_end_fct __trans_end_fct;
+ void *__data;
+ struct __gconv_trans_data *__next;
+};
+
+
+
+struct __gconv_step
+{
+ struct __gconv_loaded_object *__shlib_handle;
+ __const char *__modname;
+
+ int __counter;
+
+ char *__from_name;
+ char *__to_name;
+
+ __gconv_fct __fct;
+ __gconv_init_fct __init_fct;
+ __gconv_end_fct __end_fct;
+
+
+
+ int __min_needed_from;
+ int __max_needed_from;
+ int __min_needed_to;
+ int __max_needed_to;
+
+
+ int __stateful;
+
+ void *__data;
+};
+
+
+
+struct __gconv_step_data
+{
+ unsigned char *__outbuf;
+ unsigned char *__outbufend;
+
+
+
+ int __flags;
+
+
+
+ int __invocation_counter;
+
+
+
+ int __internal_use;
+
+ __mbstate_t *__statep;
+ __mbstate_t __state;
+
+
+
+ struct __gconv_trans_data *__trans;
+};
+
+
+
+typedef struct __gconv_info
+{
+ size_t __nsteps;
+ struct __gconv_step *__steps;
+ __extension__ struct __gconv_step_data __data [0] ;
+} *__gconv_t;
+
+
+
+typedef union
+{
+ struct __gconv_info __cd;
+ struct
+ {
+ struct __gconv_info __cd;
+ struct __gconv_step_data __data;
+ } __combined;
+} _G_iconv_t;
+
+typedef int _G_int16_t __attribute__ ((__mode__ (__HI__)));
+typedef int _G_int32_t __attribute__ ((__mode__ (__SI__)));
+typedef unsigned int _G_uint16_t __attribute__ ((__mode__ (__HI__)));
+typedef unsigned int _G_uint32_t __attribute__ ((__mode__ (__SI__)));
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef void *__gnuc_va_list;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+struct _IO_jump_t; struct _IO_FILE;
+
+
+
+typedef void _IO_lock_t;
+
+
+
+
+
+struct _IO_marker {
+ struct _IO_marker *_next;
+ struct _IO_FILE *_sbuf;
+
+
+
+ int _pos;
+
+};
+
+
+enum __codecvt_result
+{
+ __codecvt_ok,
+ __codecvt_partial,
+ __codecvt_error,
+ __codecvt_noconv
+};
+
+
+
+struct _IO_FILE {
+ int _flags;
+
+
+
+
+ char* _IO_read_ptr;
+ char* _IO_read_end;
+ char* _IO_read_base;
+ char* _IO_write_base;
+ char* _IO_write_ptr;
+ char* _IO_write_end;
+ char* _IO_buf_base;
+ char* _IO_buf_end;
+
+ char *_IO_save_base;
+ char *_IO_backup_base;
+ char *_IO_save_end;
+
+ struct _IO_marker *_markers;
+
+ struct _IO_FILE *_chain;
+
+ int _fileno;
+ int _blksize;
+ __off_t _old_offset;
+
+
+
+ unsigned short _cur_column;
+ signed char _vtable_offset;
+ char _shortbuf[1];
+
+
+
+ _IO_lock_t *_lock;
+
+
+ __off64_t _offset;
+
+ void *__pad1;
+ void *__pad2;
+
+ int _mode;
+
+ char _unused2[15 * sizeof (int) - 2 * sizeof (void *)];
+
+};
+
+
+
+struct _IO_FILE_plus;
+
+extern struct _IO_FILE_plus _IO_2_1_stdin_;
+extern struct _IO_FILE_plus _IO_2_1_stdout_;
+extern struct _IO_FILE_plus _IO_2_1_stderr_;
+
+
+
+
+
+
+
+
+
+
+
+typedef __ssize_t __io_read_fn (void *__cookie, char *__buf, size_t __nbytes);
+
+
+
+
+
+
+
+typedef __ssize_t __io_write_fn (void *__cookie, __const char *__buf,
+ size_t __n);
+
+
+
+
+
+
+
+typedef int __io_seek_fn (void *__cookie, __off64_t *__pos, int __w);
+
+
+typedef int __io_close_fn (void *__cookie);
+
+
+
+
+
+
+extern "C" {
+
+
+extern int __underflow (_IO_FILE *) throw () ;
+extern int __uflow (_IO_FILE *) throw () ;
+extern int __overflow (_IO_FILE *, int) throw () ;
+extern wint_t __wunderflow (_IO_FILE *) throw () ;
+extern wint_t __wuflow (_IO_FILE *) throw () ;
+extern wint_t __woverflow (_IO_FILE *, wint_t ) throw () ;
+
+
+
+
+
+
+
+
+
+
+
+extern int _IO_getc (_IO_FILE *__fp) throw () ;
+extern int _IO_putc (int __c, _IO_FILE *__fp) throw () ;
+extern int _IO_feof (_IO_FILE *__fp) throw () ;
+extern int _IO_ferror (_IO_FILE *__fp) throw () ;
+
+extern int _IO_peekc_locked (_IO_FILE *__fp) throw () ;
+
+
+
+
+extern void _IO_flockfile (_IO_FILE *) throw () ;
+extern void _IO_funlockfile (_IO_FILE *) throw () ;
+extern int _IO_ftrylockfile (_IO_FILE *) throw () ;
+
+
+
+
+
+
+
+
+
+
+extern int _IO_vfscanf (_IO_FILE * __restrict, const char * __restrict,
+ __gnuc_va_list , int *__restrict) throw () ;
+extern int _IO_vfprintf (_IO_FILE *__restrict, const char *__restrict,
+ __gnuc_va_list ) throw () ;
+extern __ssize_t _IO_padn (_IO_FILE *, int, __ssize_t ) throw () ;
+extern size_t _IO_sgetn (_IO_FILE *, void *, size_t ) throw () ;
+
+extern __off64_t _IO_seekoff (_IO_FILE *, __off64_t , int, int) throw () ;
+extern __off64_t _IO_seekpos (_IO_FILE *, __off64_t , int) throw () ;
+
+extern void _IO_free_backup_area (_IO_FILE *) throw () ;
+
+
+
+
+}
+
+
+
+
+
+
+
+
+
+typedef _G_fpos_t fpos_t;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern FILE *stdin;
+extern FILE *stdout;
+extern FILE *stderr;
+
+
+
+
+
+
+extern int remove (__const char *__filename) throw () ;
+
+extern int rename (__const char *__old, __const char *__new) throw () ;
+
+
+
+
+extern FILE *tmpfile (void) throw () ;
+
+
+
+extern char *tmpnam (char *__s) throw () ;
+
+
+
+
+extern char *tmpnam_r (char *__s) throw () ;
+
+
+
+
+
+
+
+
+
+
+
+extern char *tempnam (__const char *__dir, __const char *__pfx)
+ throw () ;
+
+
+
+
+extern int fclose (FILE *__stream) throw () ;
+
+extern int fflush (FILE *__stream) throw () ;
+
+
+
+extern int fflush_unlocked (FILE *__stream) throw () ;
+
+
+
+
+
+
+
+extern FILE *fopen (__const char *__restrict __filename,
+ __const char *__restrict __modes) throw () ;
+
+extern FILE *freopen (__const char *__restrict __filename,
+ __const char *__restrict __modes,
+ FILE *__restrict __stream) throw () ;
+
+
+
+
+
+extern FILE *fdopen (int __fd, __const char *__modes) throw () ;
+
+
+
+
+
+
+
+extern void setbuf (FILE *__restrict __stream, char *__restrict __buf) throw () ;
+
+
+
+extern int setvbuf (FILE *__restrict __stream, char *__restrict __buf,
+ int __modes, size_t __n) throw () ;
+
+
+
+
+extern void setbuffer (FILE *__restrict __stream, char *__restrict __buf,
+ size_t __size) throw () ;
+
+
+extern void setlinebuf (FILE *__stream) throw () ;
+
+
+
+
+extern int fprintf (FILE *__restrict __stream,
+ __const char *__restrict __format, ...) throw () ;
+
+extern int printf (__const char *__restrict __format, ...) throw () ;
+
+extern int sprintf (char *__restrict __s,
+ __const char *__restrict __format, ...) throw () ;
+
+
+extern int vfprintf (FILE *__restrict __s, __const char *__restrict __format,
+ __gnuc_va_list __arg) throw () ;
+
+extern int vprintf (__const char *__restrict __format, __gnuc_va_list __arg)
+ throw () ;
+
+extern int vsprintf (char *__restrict __s, __const char *__restrict __format,
+ __gnuc_va_list __arg) throw () ;
+
+
+
+extern int snprintf (char *__restrict __s, size_t __maxlen,
+ __const char *__restrict __format, ...)
+ throw () __attribute__ ((__format__ (__printf__, 3, 4)));
+
+extern int vsnprintf (char *__restrict __s, size_t __maxlen,
+ __const char *__restrict __format, __gnuc_va_list __arg)
+ throw () __attribute__ ((__format__ (__printf__, 3, 0)));
+
+
+
+
+
+
+extern int fscanf (FILE *__restrict __stream,
+ __const char *__restrict __format, ...) throw () ;
+
+extern int scanf (__const char *__restrict __format, ...) throw () ;
+
+extern int sscanf (__const char *__restrict __s,
+ __const char *__restrict __format, ...) throw () ;
+
+
+
+
+
+extern int fgetc (FILE *__stream) throw () ;
+extern int getc (FILE *__stream) throw () ;
+
+
+extern int getchar (void) throw () ;
+
+
+
+
+
+
+
+extern int getc_unlocked (FILE *__stream) throw () ;
+extern int getchar_unlocked (void) throw () ;
+
+
+
+
+extern int fgetc_unlocked (FILE *__stream) throw () ;
+
+
+
+
+extern int fputc (int __c, FILE *__stream) throw () ;
+extern int putc (int __c, FILE *__stream) throw () ;
+
+
+extern int putchar (int __c) throw () ;
+
+
+
+
+
+
+
+extern int fputc_unlocked (int __c, FILE *__stream) throw () ;
+
+
+
+
+extern int putc_unlocked (int __c, FILE *__stream) throw () ;
+extern int putchar_unlocked (int __c) throw () ;
+
+
+
+
+
+extern int getw (FILE *__stream) throw () ;
+
+
+extern int putw (int __w, FILE *__stream) throw () ;
+
+
+
+
+extern char *fgets (char *__restrict __s, int __n, FILE *__restrict __stream)
+ throw () ;
+
+
+
+
+
+extern char *gets (char *__s) throw () ;
+
+
+
+
+
+
+extern int fputs (__const char *__restrict __s, FILE *__restrict __stream)
+ throw () ;
+
+
+
+
+extern int puts (__const char *__s) throw () ;
+
+
+
+extern int ungetc (int __c, FILE *__stream) throw () ;
+
+
+
+extern size_t fread (void *__restrict __ptr, size_t __size,
+ size_t __n, FILE *__restrict __stream) throw () ;
+
+extern size_t fwrite (__const void *__restrict __ptr, size_t __size,
+ size_t __n, FILE *__restrict __s) throw () ;
+
+
+
+extern size_t fread_unlocked (void *__restrict __ptr, size_t __size,
+ size_t __n, FILE *__restrict __stream) throw () ;
+extern size_t fwrite_unlocked (__const void *__restrict __ptr, size_t __size,
+ size_t __n, FILE *__restrict __stream) throw () ;
+
+
+
+
+extern int fseek (FILE *__stream, long int __off, int __whence) throw () ;
+
+extern long int ftell (FILE *__stream) throw () ;
+
+extern void rewind (FILE *__stream) throw () ;
+
+
+
+
+
+
+
+
+
+
+extern int fgetpos (FILE *__restrict __stream, fpos_t *__restrict __pos)
+ throw () ;
+
+extern int fsetpos (FILE *__stream, __const fpos_t *__pos) throw () ;
+
+
+
+
+
+extern void clearerr (FILE *__stream) throw () ;
+
+extern int feof (FILE *__stream) throw () ;
+
+extern int ferror (FILE *__stream) throw () ;
+
+
+
+extern void clearerr_unlocked (FILE *__stream) throw () ;
+extern int feof_unlocked (FILE *__stream) throw () ;
+extern int ferror_unlocked (FILE *__stream) throw () ;
+
+
+
+
+extern void perror (__const char *__s) throw () ;
+
+
+
+
+extern int sys_nerr;
+extern __const char *__const sys_errlist[];
+
+
+
+
+
+
+extern int fileno (FILE *__stream) throw () ;
+
+
+
+
+extern int fileno_unlocked (FILE *__stream) throw () ;
+
+
+
+
+
+extern FILE *popen (__const char *__command, __const char *__modes) throw () ;
+
+
+extern int pclose (FILE *__stream) throw () ;
+
+
+
+
+
+extern char *ctermid (char *__s) throw () ;
+
+
+
+
+
+
+
+
+
+
+
+
+
+extern void flockfile (FILE *__stream) throw () ;
+
+
+
+extern int ftrylockfile (FILE *__stream) throw () ;
+
+
+extern void funlockfile (FILE *__stream) throw () ;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+inline int
+vprintf (__const char *__restrict __fmt, __gnuc_va_list __arg) throw ()
+{
+ return vfprintf (stdout , __fmt, __arg);
+}
+
+
+inline int
+getchar (void) throw ()
+{
+ return _IO_getc (stdin );
+}
+
+
+
+
+inline int
+getc_unlocked (FILE *__fp) throw ()
+{
+ return (( __fp )->_IO_read_ptr >= ( __fp )->_IO_read_end ? __uflow ( __fp ) : *(unsigned char *) ( __fp )->_IO_read_ptr++) ;
+}
+
+
+inline int
+getchar_unlocked (void) throw ()
+{
+ return (( stdin )->_IO_read_ptr >= ( stdin )->_IO_read_end ? __uflow ( stdin ) : *(unsigned char *) ( stdin )->_IO_read_ptr++) ;
+}
+
+
+
+
+inline int
+putchar (int __c) throw ()
+{
+ return _IO_putc (__c, stdout );
+}
+
+
+
+
+inline int
+fputc_unlocked (int __c, FILE *__stream) throw ()
+{
+ return ((( __stream )->_IO_write_ptr >= ( __stream )->_IO_write_end) ? __overflow ( __stream , (unsigned char) ( __c )) : (unsigned char) (*( __stream )->_IO_write_ptr++ = ( __c ))) ;
+}
+
+
+
+
+
+inline int
+putc_unlocked (int __c, FILE *__stream) throw ()
+{
+ return ((( __stream )->_IO_write_ptr >= ( __stream )->_IO_write_end) ? __overflow ( __stream , (unsigned char) ( __c )) : (unsigned char) (*( __stream )->_IO_write_ptr++ = ( __c ))) ;
+}
+
+
+inline int
+putchar_unlocked (int __c) throw ()
+{
+ return ((( stdout )->_IO_write_ptr >= ( stdout )->_IO_write_end) ? __overflow ( stdout , (unsigned char) ( __c )) : (unsigned char) (*( stdout )->_IO_write_ptr++ = ( __c ))) ;
+}
+
+
+
+
+
+
+
+
+inline int
+feof_unlocked (FILE *__stream) throw ()
+{
+ return ((( __stream )->_flags & 0x10 ) != 0) ;
+}
+
+
+inline int
+ferror_unlocked (FILE *__stream) throw ()
+{
+ return ((( __stream )->_flags & 0x20 ) != 0) ;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
+
+
+
+
+
+
+InodeList::InodeList()
+{
+ list = __null ;
+}
+
+InodeList::~InodeList()
+{
+ Inode *next;
+
+ for(next = list; next != __null ; next = next->next)
+ next->cleanup();
+
+ for(; list != __null ; list = next)
+ {
+ next = list->next;
+ delete list;
+ }
+}
+
+void
+InodeList::add(Inode *ino)
+{
+ if (ino->onlist)
+ {
+ fprintf(stderr , "Adding %p onto list again\n", ino);
+ return;
+ }
+ ino->next = list;
+ ino->prev = __null ;
+ if (ino->next)
+ ino->next->prev = ino;
+ list = ino;
+ ino->onlist = 1;
+}
+
+void
+InodeList::del(Inode *ino)
+{
+ if (!ino->onlist)
+ return;
+ if (ino->prev)
+ ino->prev->next = ino->next;
+ else
+ list = ino->next;
+ if (ino->next)
+ ino->next->prev = ino->prev;
+ ino->onlist = 0;
+}
+
+Inode *
+InodeList::find(Handle hand)
+{
+ Inode *ino;
+
+ for(ino = list; ino != __null ; ino = ino->next)
+ if (ino->handle == hand)
+ break;
+
+ if (ino == __null )
+ return __null ;
+
+
+ del(ino);
+ add(ino);
+
+ return ino;
+}
+
+Inode::Inode(Filesystem &fs, Handle hand)
+ :next(__null ),prev(__null ),nlink(0),handle(hand),filesys(fs)
+{
+ alive = 1;
+ onlist = 0;
+ filesys.inodes.add(this);
+}
+
+Inode::~Inode()
+{
+ if (!alive)
+ fprintf(stderr , "Inode %p already dead!\n", this);
+ filesys.inodes.del(this);
+ alive = 0;
+}
+
+Inode *
+Inode::findino(Handle h)
+{
+ return filesys.inodes.find(h);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+int Inode::do_create (const up_preamble &, upp_repl &, const upp_create_s &, upp_create_r &) { return 38 ; } ;
+int Inode::do_lookup (const up_preamble &, upp_repl &, const upp_lookup_s &, upp_lookup_r &) { return 38 ; } ;
+int Inode::do_link (const up_preamble &, upp_repl &, const upp_link_s &) { return 38 ; } ;
+int Inode::do_unlink (const up_preamble &, upp_repl &, const upp_unlink_s &) { return 38 ; } ;
+int Inode::do_symlink (const up_preamble &, upp_repl &, const upp_symlink_s &) { return 38 ; } ;
+int Inode::do_rename (const up_preamble &, upp_repl &, const upp_rename_s &) { return 38 ; } ;
+int Inode::do_readlink (const up_preamble &, upp_repl &, const upp_readlink_s &, upp_readlink_r &) { return 38 ; } ;
+int Inode::do_followlink (const up_preamble &, upp_repl &, const upp_followlink_s &, upp_followlink_r &) { return 38 ; } ;
+int Inode::do_permission (const up_preamble &, upp_repl &, const upp_permission_s &) { return 38 ; } ;
+int Inode::do_iwrite (const up_preamble &, upp_repl &, const upp_iwrite_s &) { return 38 ; } ;
+int Inode::do_iread (const up_preamble &, upp_repl &, const upp_iread_s &, upp_iread_r &) { return 38 ; } ;
+int Inode::do_iput (const up_preamble &, upp_repl &, const upp_iput_s &) { return 38 ; } ;
+int Inode::do_notify_change (const up_preamble &, upp_repl &, const upp_notify_change_s &) { return 38 ; } ;
+int Inode::do_truncate (const up_preamble &, upp_repl &, const upp_truncate_s &) { return 38 ; } ;
+int Inode::do_inode_valid (const up_preamble &, upp_repl &, const upp_inode_valid_s &, upp_inode_valid_r &) { return 38 ; } ;
+
+
+
+
+
+
+
+int Inode::do_read (const up_preamble &, upp_repl &, const upp_read_s &, upp_read_r &) { return 38 ; } ;
+int Inode::do_write (const up_preamble &, upp_repl &, const upp_write_s &, upp_write_r &) { return 38 ; } ;
+int Inode::do_readdir (const up_preamble &, upp_repl &, const upp_readdir_s &, upp_readdir_r &) { return 38 ; } ;
+int Inode::do_multireaddir (const up_preamble &, upp_repl &, const upp_multireaddir_s &, upp_multireaddir_r &) { return 38 ; } ;
+int Inode::do_open (const up_preamble &, upp_repl &, const upp_open_s &, upp_open_r &) { return 38 ; } ;
+int Inode::do_close (const up_preamble &, upp_repl &, const upp_close_s &) { return 38 ; } ;
+
+
+
+
+
+
+
+
+
+
+
Added: trunk/lib/README
==============================================================================
--- trunk/lib/README 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/lib/README 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,54 @@
+This library is still very rudimentary. It handles the basic
+filesystem operations, but still lacks most higher-level
+functionality. The basic classes are:
+
+Filesystem A whole filesystem, consisting of a collection
+ of Inodes. This class is passed a block of data
+ repesenting a request and decodes it. There is a
+ method for each userfs protocol operation. For
+ operations involving inodes it finds the appropriate
+ inode (if any) and dispatches it.
+
+Inode A generic inode base class, with methods for
+ each operation.
+
+SimpleInode A simple class derived from Inode which implements
+ a simple constructor, and default behaviour for
+ upp_permission, upp_iread, upp_open, upp_close
+ and so on.
+
+DirInode Derived from SimpleInode: this implements most of the
+ functionality needed for a directory. For
+ simple cases all a class derived from this
+ needs is a special constructor: see homer.cc
+
+Comm This performs the comms between the kernel
+ streams and the filesystem itself.
+
+DeferComm This is like Comm, except it allows some replies
+ to be deferred - that is, the filesystem goes on
+ to process more input while a separate process
+ handles the outstanding requests.
+
+ThreadComm This creates a new light-weight process for each
+ request (using the library in ../lwp), and
+ terminates the thread when the request is done.
+ The LWP library is not pre-emptive, so care
+ must be taken with blocking system calls.
+ The filedescriptor dispatch service in CommBase
+ is useful for this.
+
+CommBase The base comms class. This is not useful by itself,
+ but it does provide some useful services to derived
+ classes, through the DispatchFD table. Its main
+ method is Run(), which does a select() syscall on
+ the set of fds in the dispatch table, and calls the
+ dispatch() method of each class in the table when its
+ filedescriptor event arrives. This is used for waiting
+ for kernel input, but arbitary fds can be selected on,
+ for reads, writes or exceptions. FD dispatch table
+ entries can be added and removed with addDispatch()
+ and delDispatch().
+
+
+ Jeremy Fitzhardinge <jeremy at sw.oz.au>
Added: trunk/lib/SimpleInode.h
==============================================================================
--- trunk/lib/SimpleInode.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/lib/SimpleInode.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,36 @@
+// -*- C++ -*-
+
+// A simple inode with some very basic operations implemented
+
+#ifndef _SIMPLEINODE_H_
+#define _SIMPLEINODE_H_
+
+#pragma interface
+
+#include <Inode.h>
+
+class SimpleInode: public Inode
+{
+public:
+ virtual void iread(up_inode &);
+ virtual void iwrite(const up_inode &);
+
+ int do_iwrite(const up_preamble &, upp_repl &,
+ const upp_iwrite_s &arg);
+ int do_iread(const up_preamble &, upp_repl &,
+ const upp_iread_s &, upp_iread_r &);
+ int do_notify_change(const up_preamble &, upp_repl &,
+ const upp_notify_change_s &);
+ int do_open(const up_preamble &, upp_repl &,
+ const upp_open_s &, upp_open_r &);
+ int do_close(const up_preamble &, upp_repl &,
+ const upp_close_s &);
+ int do_permission(const up_preamble &, upp_repl &,
+ const upp_permission_s &);
+ int do_iput(const up_preamble &, upp_repl &,
+ const upp_iput_s &);
+
+ SimpleInode(Filesystem &, Handle);
+};
+
+#endif /* _SIMPLEINODE_H_ */
Added: trunk/lib/ThreadComm.cc
==============================================================================
--- trunk/lib/ThreadComm.cc 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/lib/ThreadComm.cc 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,173 @@
+// -*- C++ -*-
+
+// Threaded Comms class
+
+// This class sets up a LWP for each request
+
+// (C) Copyright 1994 Jeremy Fitzhardinge <jeremy at sw.oz.au>
+// This code is distributed under the terms of the
+// GNU General Public Licence. See COPYING for more details.
+
+#include <Filesystem.h>
+#include <ThreadComm.h>
+#include <LWP.h>
+#include <io.h>
+#include <linux/userfs_fs.h>
+#include <stdio.h>
+
+class Thread_doreq: public Comm_doreq
+{
+ friend void op_proc(int, char **, void *);
+ friend class ThreadComm;
+
+ // Argument for thread
+ int fd;
+ int stksz, threadpri;
+
+ // Associated dispatch list and comm struct pointers
+ struct disp_fd *disp;
+ ThreadComm *comm;
+
+ // Do the read work in a thread
+ void doop();
+
+ // Virtual from Comm_doreq
+ int dispatch(int fd, int flags);
+
+ void remself() { comm->delDispatch(disp); }
+
+public:
+ Thread_doreq(ThreadComm *, Filesystem &, int pri, int stk);
+};
+
+class EOF_handler: public DispatchFD
+{
+ int dispatch(int fd, int flags);
+};
+
+int
+EOF_handler::dispatch(int fd, int)
+{
+ return 0;
+}
+
+ThreadComm::ThreadComm(Filesystem &fs, unsigned to, unsigned from,
+ int stk, int pri, int tpri)
+ : CommBase(fs, to, from)
+{
+ main = new LWP(pri);
+
+ Thread_doreq *tdr = new Thread_doreq(this, filesys, stk, tpri);
+ req = tdr;
+
+ tdr->disp = addDispatch(from, tdr, DISP_R, NDISP_PRI);
+ EOF_handler *eof = new EOF_handler();
+ addDispatch(from, eof, DISP_E);
+}
+
+ThreadComm::~ThreadComm()
+{
+ delete main;
+}
+
+Thread_doreq::Thread_doreq(ThreadComm *tc, Filesystem &fs, int stk, int pri)
+ : Comm_doreq(tc, fs), stksz(stk), threadpri(pri), comm(tc)
+{
+}
+
+// Hop-through funtion to do casting
+void op_proc(int, char **, void *p)
+{
+ ((Thread_doreq *)p)->doop();
+ suicide();
+ abort(); // NOTREACHED
+
+}
+
+// Process a request from the kernel
+// Returns 0 on EOF, -1 on error and 1 for OK
+int
+Thread_doreq::dispatch(int infd, int)
+{
+ fd = infd;
+ LWP *lwp = new LWP(threadpri, op_proc, stksz, 0, NULL, this);
+
+ return 1; // Always OK (no way of returning error)
+}
+
+void
+Thread_doreq::doop()
+{
+ up_preamble pre;
+ size_t presize = sizeof_up_preamble(&pre);
+ Uchar hbuf[256];
+ int ret;
+
+ ret = fullread(fd, hbuf, presize);
+ if (ret == 0)
+ {
+ remself();
+ return;
+ }
+
+ if (ret != (int)presize)
+ {
+ fprintf(stderr, "Thread_doreq::dispatch failed to get whole header (%d wanted, %d got)\n",
+ presize, ret);
+ remself();
+ return;
+ }
+
+ upp_repl repl;
+ size_t replsize = sizeof_upp_repl(&repl);
+
+ assert(sizeof(hbuf) > replsize);
+
+ decode_up_preamble(&pre, hbuf);
+
+ Data *buf = new Data[USERFS_MAX_XFER];
+
+ if (pre.size != 0 && (ret = fullread(fd, buf, pre.size)) != (int)pre.size)
+ {
+ fprintf(stderr, "Thread_doreq::dispatch: failed to get whole body (%li wanted, %d got)\n",
+ pre.size, ret);
+ remself();
+ delete buf;
+ return;
+ }
+
+ ret = filesys.DoOp(pre, repl, buf);
+
+ if (ret != 1)
+ {
+ remself();
+ delete buf;
+ return; // -1
+ }
+
+#ifdef DEBUG
+ if (repl.errno != 0)
+ {
+ fprintf(stderr, "Request %d failing with %d %s\n",
+ pre.op, repl.errno, strerror(repl.errno));
+ }
+#endif
+
+ encode_upp_repl(&repl, hbuf);
+
+ int err = 0;
+
+ if (fullwrite(tokern, hbuf, replsize) != replsize)
+ err = 1;
+ else
+ if (repl.size != 0 &&
+ fullwrite(tokern, buf, repl.size) != repl.size)
+ err = 1;
+
+ if (err)
+ remself();
+
+ delete buf;
+ return;
+}
+
Added: trunk/lib/DeferFilesys.cc
==============================================================================
--- trunk/lib/DeferFilesys.cc 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/lib/DeferFilesys.cc 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,7 @@
+// -*- C++ -*-
+
+// Implementation file for DeferFilesys
+
+#pragma implementation
+
+#include <DeferFilesys.h>
Added: trunk/lib/ThreadComm.h
==============================================================================
--- trunk/lib/ThreadComm.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/lib/ThreadComm.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,25 @@
+// -*- C++ -*-
+
+// Threaded Comm class
+
+// (C) Copyright 1994 Jeremy Fitzhardinge <jeremy at sw.oz.au>
+// This code is distributed under the terms of the
+// GNU General Public Licence. See COPYING for more details.
+
+
+#ifndef _THREADCOMM_H_
+#define _THREADCOMM_H_
+
+#include "Comm.h"
+
+class ThreadComm : public CommBase
+{
+ class LWP *main;
+ const int stksize, threadpri;
+
+public:
+ ThreadComm(Filesystem &, unsigned int, unsigned int, int stk, int mpri, int tpri);
+ ~ThreadComm();
+};
+
+#endif /* _THREADCOMM_H_ */
Added: trunk/lib/operations.h
==============================================================================
--- trunk/lib/operations.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/lib/operations.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,81 @@
+/*
+ * This contains references to all the userfs protocol operations this
+ * library supports. For each operation there is a macro which says
+ * whether it is a filesystem, inode or file operation, and whether it
+ * has arguments or return values.
+ *
+ * This is used for automatically generating prototypes in class
+ * definitions, and implementations of stub versions of these functions.
+ *
+ * For inode and file operations it also should really have macros for
+ * extracting the handle from the arguments.
+ *
+ * Copyright (C) 1995 Jeremy Fitzhardinge <jeremy at sw.oz.au>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#if !defined(DO) || !defined(DOa) || !defined(DOr) || !defined(DOar)
+#error "Need DOxx macros defined"
+#endif
+
+#if !defined(opSUPER) && !defined(opINODE) && !defined(opFILE)
+#define opSUPER
+#define opINODE
+#define opFILE
+#endif
+
+/* Super operations */
+#ifdef opSUPER
+#undef opSUPER
+
+DOr(mount);
+DO(umount);
+DOr(statfs);
+
+#endif /* opSUPER */
+
+/* Inode operations */
+#ifdef opINODE
+#undef opINODE
+
+DOar(create);
+DOar(lookup);
+DOa(link);
+DOa(unlink);
+DOa(symlink);
+DOa(rename);
+DOar(readlink);
+DOar(followlink);
+DOa(permission);
+DOa(iwrite);
+DOar(iread);
+DOa(iput);
+DOa(notify_change);
+DOa(truncate);
+DOar(inode_valid);
+
+#endif /* opINODE */
+
+/* File operations */
+#ifdef opFILE
+#undef opFILE
+
+DOar(read);
+DOar(write);
+DOar(readdir);
+DOar(multireaddir);
+DOar(open);
+DOa(close);
+
+#endif /* opFILE */
+
+#undef DO
+#undef DOa
+#undef DOr
+#undef DOar
+
+
Added: trunk/lib/DeferFilesys.h
==============================================================================
--- trunk/lib/DeferFilesys.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/lib/DeferFilesys.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,23 @@
+// -*- C++ -*-
+
+// Filesystem which knows about DeferComm
+
+#ifndef _DEFERFILESYS_H_
+#define _DEFERFILESYS_H_
+
+#pragma interface
+
+#include <Filesystem.h>
+
+class DeferFilesys: public Filesystem
+{
+ friend class DeferComm;
+
+ DeferComm *comm_p;
+ void setcomm(DeferComm *c) { comm_p = c; }
+public:
+ DeferFilesys(const char *mpoint):Filesystem(mpoint) {}
+ DeferComm *comm() const { return comm_p; }
+};
+
+#endif /* _DEFERFILESYS_H_ */
Added: trunk/lib/CommBase.cc
==============================================================================
--- trunk/lib/CommBase.cc 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/lib/CommBase.cc 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,217 @@
+// -*- C++ -*-
+// Communications class
+//
+// This class copes with all the communication to and from the
+// kernel for a userfs filesystem.
+// The implementation of the base class is purely synchronous.
+//
+// This program is distributed under the terms of the
+// Free Software Foundation General Public Licence.
+// Copyright Jeremy Fitzhardinge <jeremy at sw.oz.au> 1993
+
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+#include <unistd.h>
+
+#pragma implementation
+
+#include "CommBase.h"
+#include "Filesystem.h"
+
+#define _SYS_SELECT_H 1
+#include <bits/select.h>
+
+CommBase::CommBase(Filesystem &fs, unsigned int to, unsigned int from)
+ :tokern(to),filesys(fs)
+{
+ req = NULL;
+ for(int i=0; i < NDISP_PRI; i++)
+ dispqs[i].h = dispqs[i].t = NULL;
+ dispatches = 0;
+ fs.setcomm(this);
+}
+
+CommBase::~CommBase()
+{
+ close(tokern);
+ tokern = (unsigned)-1;
+ CloseFDs(1);
+}
+
+struct disp_fd
+{
+ disp_fd *next, *prev;
+ int fd;
+ DispatchFD *dfd;
+ int what;
+ int pri;
+
+ ~disp_fd();
+};
+
+disp_fd::~disp_fd()
+{
+ delete dfd;
+}
+
+DispatchFD::~DispatchFD()
+{
+}
+
+// Queue things on the end of the list to get round-robin type scheduling
+// In a multithreaded filesystem this is important to allow multiple access
+// to the filesystem
+disp_fd *
+CommBase::addDispatch(int fd, DispatchFD *dfd, int what, int pri)
+{
+ disp_fd *fdl = new disp_fd;
+
+ if (pri >= NDISP_PRI)
+ pri = NDISP_PRI-1;
+
+ fdl->prev = dispqs[pri].t;
+ fdl->next = NULL;
+ if (fdl->prev != NULL)
+ fdl->prev->next = fdl;
+
+ dispqs[pri].t = fdl;
+ if (dispqs[pri].h == NULL)
+ dispqs[pri].h = fdl;
+
+ fdl->fd = fd;
+ fdl->dfd = dfd;
+ fdl->what = what;
+ fdl->pri = pri;
+
+ dispatches++;
+ return fdl;
+}
+
+void
+CommBase::delDispatch(disp_fd *fdl)
+{
+ if (fdl->dfd == req)
+ req = NULL;
+
+ if (fdl->next != NULL)
+ fdl->next->prev = fdl->prev;
+ else
+ dispqs[fdl->pri].t = fdl->prev;
+
+ if (fdl->prev != NULL)
+ fdl->prev->next = fdl->next;
+ else
+ dispqs[fdl->pri].h = fdl->next;
+
+ fdl->next = fdl->prev = NULL;
+
+ dispatches--;
+ delete fdl;
+}
+
+// Wait on input filedescriptors for something to happen.
+// Things which want to know about file descriptors (for read only)
+// can register themselves. When select() returns, each
+// matching dispatch routine is called so it can do what it likes.
+// If a dispatch routine returns 0, it means it wants to be removed
+// from the list; -1 indicates error and 1 means OK. If there
+// are no routines on the list then CommBase::Run returns.
+int
+CommBase::Run()
+{
+ int ret;
+
+ while(dispatches > 0)
+ {
+ int i;
+
+ fd_set r_set, w_set, e_set;
+ FD_ZERO(&r_set);
+ FD_ZERO(&w_set);
+ FD_ZERO(&e_set);
+
+ disp_fd *dfd;
+ int topfd = 0;
+
+ for(i = NDISP_PRI-1; i >= 0; i--)
+ for(dfd = dispqs[i].h; dfd != NULL; dfd = dfd->next)
+ {
+ if (dfd->what & DISP_R)
+ FD_SET(dfd->fd, &r_set);
+ if (dfd->what & DISP_W)
+ FD_SET(dfd->fd, &w_set);
+ if (dfd->what & DISP_E)
+ FD_SET(dfd->fd, &e_set);
+ if (dfd->fd > topfd)
+ topfd = dfd->fd;
+ }
+
+ ret = select(topfd+1, &r_set, &w_set, &e_set, NULL);
+
+ if (ret == -1)
+ {
+ if (errno == EINTR)
+ continue;
+ else
+ {
+ perror("select failed");
+ return ret;
+ }
+ }
+ if (ret == 0)
+ {
+ fprintf(stderr, "Comm::Run ret == 0\n");
+ continue;
+ }
+
+ disp_fd *next;
+ for (i = NDISP_PRI-1; i >= 0; i--)
+ for(dfd = dispqs[i].h; dfd != NULL; dfd = next)
+ {
+ int what = 0;
+
+ next = dfd->next;
+ if (dfd->what & DISP_R && FD_ISSET(dfd->fd, &r_set))
+ what |= DISP_R;
+ if (dfd->what & DISP_W && FD_ISSET(dfd->fd, &w_set))
+ what |= DISP_W;
+ if (dfd->what & DISP_E && FD_ISSET(dfd->fd, &e_set))
+ what |= DISP_E;
+
+ if (what == 0)
+ continue;
+
+ ret = dfd->dfd->dispatch(dfd->fd, what);
+
+ if (ret == 1)
+ continue;
+ delDispatch(dfd);
+ if (ret != 0)
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+// Close filedescriptors we really don't need
+void
+CommBase::CloseFDs(int all)
+{
+ disp_fd *fdlp, *next;
+
+ for(int i = 0; i < NDISP_PRI; i++)
+ for(fdlp = dispqs[i].h; fdlp != NULL; fdlp = next)
+ {
+ next = fdlp->next;
+
+ if (all || fdlp->dfd != req)
+ delDispatch(fdlp);
+ }
+}
+
+DispToKern::DispToKern(const CommBase *comm)
+{
+ tokern = comm->tokern;
+}
Added: trunk/lib/Filesystem.h
==============================================================================
--- trunk/lib/Filesystem.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/lib/Filesystem.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,61 @@
+// -*- c++ -*-
+//
+// C++ classes for making user level filesystems easier
+//
+// This program is distributed under the terms of the
+// Free Software Foundation General Public Licence.
+// Copyright Jeremy Fitzhardinge <jeremy at sw.oz.au> 1993
+
+#ifndef __FILESYSTEM_H_SEEN__
+#define __FILESYSTEM_H_SEEN__
+
+#include <errno.h>
+
+#include <userfs_types.h>
+#include <linux/userfs_fs.h>
+
+#include <Inode.h>
+#include <CommBase.h>
+
+#pragma interface
+
+typedef unsigned char Data;
+class Comm;
+
+class Filesystem
+{
+ friend CommBase;
+ friend Inode;
+
+ const char *mpoint;
+
+ CommBase *comm_p;
+ void setcomm(CommBase *c) { comm_p = c; }
+
+protected:
+ InodeList inodes;
+ virtual int Enquire(up_ops op);
+
+ Handle rootdir;
+
+ // generate prototypes for operations methods
+#define DO(op) virtual int do_##op(const up_preamble &, upp_repl &)
+#define DOa(op) virtual int do_##op(const up_preamble &, upp_repl &, const upp_##op##_s &)
+#define DOr(op) virtual int do_##op(const up_preamble &, upp_repl &, upp_##op##_r &)
+#define DOar(op) virtual int do_##op(const up_preamble &, upp_repl &, const upp_##op##_s &, upp_##op##_r &)
+#include "operations.h"
+
+public:
+ Filesystem(const char *mpoint);
+ virtual ~Filesystem();
+
+ Inode *findino(Handle h) { return inodes.find(h); }
+
+ // Data contains the encoded reply on non-error return
+ // It should point to at least 4k of data.
+ int DoOp(const up_preamble &, upp_repl &, Data *data);
+
+ CommBase *comm() const { return comm_p; }
+};
+
+#endif // __FILESYSTEM_H_SEEN__
Added: trunk/lib/CommBase.h
==============================================================================
--- trunk/lib/CommBase.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/lib/CommBase.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,86 @@
+// -*- C++ -*-
+//
+// Class for kernel to process communications
+//
+// This program is distributed under the terms of the
+// Free Software Foundation General Public Licence.
+// Copyright Jeremy Fitzhardinge <jeremy at sw.oz.au> 1993
+
+#ifndef __COMMBASE_H_SEEN__
+#define __COMMBASE_H_SEEN__
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#pragma interface
+
+class Filesystem;
+class DispatchFD;
+class DispToKern;
+
+// Flags for selecting type of select
+#define DISP_R 1
+#define DISP_W 2
+#define DISP_E 4
+
+// Number select dispatch priorities
+#define NDISP_PRI 4
+
+// Filesystem communications
+class CommBase
+{
+ friend Filesystem;
+ friend DispToKern;
+
+ // List of fd dispatch handers
+ struct dispq_t
+ {
+ struct disp_fd *h, *t;
+ } dispqs[NDISP_PRI];
+ int dispatches;
+
+ // fd to kernel
+ unsigned int tokern;
+
+protected:
+ // The filesystem we're part of.
+ Filesystem &filesys;
+ // Set up kernel fd dispatch handler
+ DispatchFD *req;
+
+public:
+ CommBase(Filesystem &, unsigned int to, unsigned int from);
+ virtual ~CommBase();
+
+ struct disp_fd *addDispatch(int fd, DispatchFD *dfd, int what=DISP_R, int pri = 2);
+ void delDispatch(struct disp_fd *);
+
+ // This doesn't return until there is an IO error or EOF
+ int Run();
+
+ // Defer a reply for a child process to do
+ int DeferRepl();
+
+ // Close all fds we have open, and remove handlers
+ // all==1 means even the kernel connection
+ void CloseFDs(int all = 0);
+};
+
+// Dispatch class for FDs
+class DispatchFD
+{
+public:
+ virtual int dispatch(int fd, int what) = 0;
+ virtual ~DispatchFD();
+};
+
+// A dispatcher which sends needs to send to the kernel
+class DispToKern : public DispatchFD
+{
+protected:
+ int tokern;
+public:
+ DispToKern(const CommBase *);
+};
+
+#endif /* __COMMBASE_H_SEEN__ */
Added: trunk/lib/Makefile
==============================================================================
--- trunk/lib/Makefile 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/lib/Makefile 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,58 @@
+# Makefile for library
+TOP=..
+CPP=$(CC)
+CPPFLAGS=-I. -I$(TOP)/lwp -I$(TOP)/utils -I$(TOP)/kernel -I$(TOP)/genser #-DDEBUG
+CFLAGS=$(CPPFLAGS)
+CXXFLAGS=$(CFLAGS)
+LIB=libuserfs.a
+
+include $(TOP)/rules
+
+LIBOBJ = userfs_types.o Filesystem.o Inode.o SimpleInode.o DirInode.o \
+ DeferFilesys.o CommBase.o Comm.o DeferComm.o ThreadComm.o \
+ $(TOP)/utils/io.o
+
+all $(LIB):: $(LIB)($(LIBOBJ))
+
+.SUFFIXES: .ty
+
+.ty.cc: $(GENCODE)
+ $(GENCODE) $(CPPFLAGS) -Csed $< > $@ || rm -f $@
+
+.ty.h: $(GENHDR)
+ $(GENHDR) $(CPPFLAGS) -C $< > $@ || rm -f $@
+
+TYPEFILE=$(TOP)/kernel/linux/userfs_types.ty
+
+userfs_types.o: userfs_types.cc userfs_types.h
+
+userfs_types.h: $(TYPEFILE) $(GENHDR)
+ $(GENHDR) $(CPPFLAGS) -C $< > $@ || rm -f $@
+
+#userfs_types.cc: $(TYPEFILE) $(GENCODE)
+# $(GENCODE) $(CPPFLAGS) -Csed $< > $@
+
+# Generate only code we want
+userfs_types.cc: $(TYPEFILE) $(GENCODE)
+ rm -rf types
+ mkdir types
+ $(GENCODE) $(CPPFLAGS) -Csed -l types $<
+ rm -f types/encode_*_s.cc types/decode_*_r.cc
+ cat types/* | awk ' \
+ /^#(include.*)|pragma implementation/ { \
+ if (!($$0 in seen)) { \
+ seen[$$0] = 1; \
+ } else next \
+ } \
+ { print $$0; }' > $@
+ rm -fr types
+
+depend dep:: userfs_types.h coder.h
+ $(CPP) $(CPPFLAGS) -M *.cc *.c> .depend
+
+coder.h:
+ @-ln -s $(GENDIR)/coder.h .
+
+clean::
+ rm -f *.[ao] *~ userfs_types.cc userfs_types.h
+
Added: trunk/ANNOUNCE
==============================================================================
--- trunk/ANNOUNCE 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/ANNOUNCE 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,83 @@
+ Announcing: userfs ALPHA version 0.9
+
+Userfs is a mechanism by which normal user processes can be a Linux
+filesystem, similar to Plan 9 filesystems or The Hurd's translators.
+There are many uses for this, including:
+
+* Completely virtual filesystems and new interfaces *
+
+Add a filesystem-type interface to an existing mechanism, or a
+filesystem interface as a new way of representing data. Sick of FTP?
+How about:
+
+ $ mkdir /ftp/tsx-11.mit.edu
+ $ cd /ftp/tsx-11.mit.edu/pub/Linux
+ $ cp README $HOME
+
+* Prototype filesystems *
+
+Prototype new block allocation algorithms in a user process and debug
+with gdb before going into the compile-crash-reboot cycle of kernel
+development.
+
+* Infrequent use filesystems *
+
+You want to mount "FooBaz 0X" filesystems under Linux, but you don't
+want it that often, and you don't need it to be maximum speed. Rather
+than trying to get the kernel itself to understand, or write
+specialised tools, write a filesystem program.
+
+This release has some actual implementations of filesystems doing
+things that I've been promising for the last few versions. It will
+probably be much more interesting for non-programmers.
+
+This version is a loadable kernel module. There is no need to patch
+the kernel source.
+
+There are no significant functional changes. The kernel code has been
+updated to work in 1.2 and 1.3 kernels (tested only in 1.3.10).
+There are a few minor bug fixes in the demo filesystems, but no
+new functionality. I haven't tested the contrib stuff lately, so
+it probably doesn't work.
+
+The release comes with six complete filesystems:
+ - ftpfs, a filesystem for FTP access. This allows multilple FTP
+ sites to be accessed as a filesystem, with a persistent cache of
+ data.
+ - homer, which simply creates a directory containing symlinks
+ to every user's home directory. Mounted on /u, it makes a
+ passible replacement for '~' expansion in your shell which
+ works for everything.
+ - intfs, an experimental filesystem in which file contents can
+ be generated by arbitary shell scripts on the fly as they are
+ read.
+ - egfs, a very simple example/tutorial filesystem
+
+And the contributed filesystems:
+ - arcfs which allows a compressed tar
+ file to be mounted readonly and browsed as a filesystem.
+ (Dave Gymer)
+ - mailfs, a simple mail-reading filesystem
+ (Davor Jadrijevic)
+
+Thanks also to Ulrich Dessauer for his C library interface and various
+filesystems using it, including an OS/9 filesystem.
+
+This release is available from:
+ sunsite.unc.edu:pub/Linux/ALPHA/userfs/userfs-0.9.tar.gz
+ tsx-11.mit.edu:pub/linux/ALPHA/userfs/userfs-0.9.tar.gz
+(as a last resort, since we have a slow link)
+ ftp.softway.com.au:pub/jeremy/linux/userfs-0.9.tar.gz
+
+* Mailing List *
+
+There is a USERFS channel on the linux activists list server.
+To subscribe, send mail with
+ X-Mn-Admin: join USERFS
+as the first line to linux-activists-request at niksula.hut.fi
+(I'm not sure what the status of the linux-activist list manager
+is, so I may set up a new mailing list)
+
+Please send bugs and comments to Jeremy Fitzhardinge <jeremy at sw.oz.au>
+or to the mailing list. Send me mail if you find userfs interesting
+and intend doing something with it.
Added: trunk/filesystems/tarfs/tarfs.c
==============================================================================
--- trunk/filesystems/tarfs/tarfs.c 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/tarfs/tarfs.c 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,477 @@
+/* (Read-only) archive filesystem. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <utime.h>
+#include <dirent.h>
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include <getopt.h>
+#include <assert.h>
+
+#include <time.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/fcntl.h>
+
+#include <linux/fs.h>
+#include <linux/userfs_fs.h>
+
+#include <assert.h>
+
+#include "tarfs.h"
+
+static char *mpoint;
+static TAR_DIRENT *root;
+
+/* No point in this being in a seperate file. */
+#include <linux/userfs_types.c>
+
+static int
+myread (int fd, void *buf, int sz)
+{
+ int rd = 0;
+ int ret;
+
+ while (sz > 0)
+ {
+ ret = read (fd, buf, sz);
+
+ if (ret == -1)
+ {
+ if (errno == EINTR)
+ continue;
+
+ perror ("myread");
+ exit (1);
+ }
+
+ if (ret == 0)
+ break;
+
+ sz -= ret;
+ buf += ret;
+ rd += ret;
+ }
+
+ return rd;
+}
+
+static int
+mywrite (int fd, const void *buf, int sz)
+{
+ int wr = 0;
+ int ret;
+
+ while (sz > 0)
+ {
+ ret = write (fd, buf, sz);
+
+ if (ret == -1)
+ {
+ if (errno == EINTR)
+ continue;
+ FAIL ("write");
+ exit (1);
+ }
+
+ if (ret == 0)
+ {
+ fprintf (stderr, "write wrote 0 bytes\n");
+ break;
+ }
+
+ sz -= ret;
+ buf += ret;
+ wr += ret;
+ }
+
+ return wr;
+}
+
+static int
+readpkt (int fd, up_preamble *pre, unsigned char *buf)
+{
+ int presz = sizeof_up_preamble (pre);
+ unsigned int rd;
+ unsigned char pbuf[presz];
+
+ memset (pbuf, 0, sizeof (pbuf));
+
+ rd = myread (fd, pbuf, presz);
+ if (rd != presz)
+ {
+ if (rd == 0)
+ return 0;
+ if (rd > 0)
+ fprintf (stderr, "readpkt, incomplete read (%d, not %d)\n",
+ rd, presz);
+ perror ("readpkt, header read");
+ return -1;
+ }
+
+ decode_up_preamble (pre, pbuf);
+
+ if (pre->isreq != UP_ENQ && pre->isreq != UP_REQ)
+ fprintf (stderr, "pre->isreq = %d\n", pre->isreq);
+
+ if (pre->version != UP_VERSION)
+ {
+ fprintf (stderr, "Version mismatch: us=%d them=%d\n",
+ UP_VERSION, pre->version);
+ return -1;
+ }
+
+ if (pre->size != 0)
+ {
+ if (myread (fd, buf, pre->size) != pre->size)
+ {
+ perror ("readpkt, body read");
+ return -1;
+ }
+ }
+
+ return 1;
+}
+
+static int
+writepkt (int fd, upp_repl *repl, const unsigned char *buf)
+{
+ int replsz = sizeof_upp_repl (repl);
+ unsigned char pbuf[replsz];
+ unsigned int wr;
+ unsigned char *p;
+
+ assert (repl->version == UP_VERSION);
+ assert (repl->isreq == UP_REPL);
+
+ p = encode_upp_repl (repl, pbuf);
+
+ assert (replsz == p - pbuf);
+
+ wr = mywrite (fd, pbuf, replsz);
+ if (wr != replsz)
+ {
+ perror ("writepkt, header write");
+ return -1;
+ }
+
+ if (repl->size > 0 && repl->err_no == 0)
+ {
+ if ( mywrite(fd, buf, repl->size) != repl->size)
+ {
+ perror ("writepkt, body write");
+ return -1;
+ }
+ }
+
+ return 1;
+}
+
+static void
+genpkt (upp_repl *repl, int seq, up_ops op)
+{
+ repl->version = UP_VERSION;
+ repl->seq = seq;
+ repl->op = op;
+ repl->isreq = 0;
+ repl->size = 0;
+ repl->err_no = 0;
+}
+
+#define DIRINO 1
+
+static int
+do_iread (unsigned char *buf, upp_repl *repl)
+{
+ upp_iread_s rcv;
+ upp_iread_r snd;
+
+ decode_upp_iread_s(&rcv, buf);
+
+ memset(&snd, 0, sizeof(snd));
+
+ snd.ino.mode = 0444;
+ snd.handle = rcv.handle;
+ snd.ino.nlink = 1;
+
+ if (rcv.handle.handle == DIRINO)
+ {
+ snd.ino.mode |= S_IFDIR | 0111;
+ snd.ino.mtime = 0;
+ snd.ino.ctime = 0;
+ snd.ino.atime = 0;
+ }
+ else
+ {
+ TAR_DIRENT *ent = (TAR_DIRENT *) rcv.handle.handle;
+
+ if (ent->size != -1)
+ {
+ snd.ino.mode = ent->attr;
+ snd.ino.size = ent->size;
+ /* These numbers seem to be magic for Linux. */
+ snd.ino.blksize = 512;
+ snd.ino.blocks = (ent->size + 511) / 512;
+ }
+ else
+ {
+ snd.ino.mode |= S_IFDIR | 0111;
+ snd.ino.size = 0;
+ }
+ snd.ino.gid = ent->gid;
+ snd.ino.uid = ent->uid;
+ snd.ino.mtime = ent->time;
+ snd.ino.ctime = ent->time;
+ snd.ino.atime = ent->time;
+ }
+
+
+ repl->size = encode_upp_iread_r(&snd, buf) - buf;
+
+ return 0;
+}
+
+static int
+do_lookup (unsigned char *buf, upp_repl *repl)
+{
+ upp_lookup_s rcv;
+ upp_lookup_r snd;
+ TAR_DIRENT *ent;
+
+ decode_upp_lookup_s(&rcv, buf);
+
+ ent = (TAR_DIRENT *) rcv.dir.handle;
+ if (ent->size != -1)
+ return ENOTDIR;
+
+ if (rcv.name.nelem == 2
+ && rcv.name.elems[0] == '.' && rcv.name.elems[1] == '.')
+ {
+ ent = ent->pdir;
+ }
+ else if (rcv.name.nelem != 1 || rcv.name.elems[0] != '.')
+ {
+ ent = ent->data.dir.first;
+ while (ent)
+ {
+ /* Probably bombs out on prefixes... */
+ if (!strncmp(ent->name, rcv.name.elems, rcv.name.nelem))
+ break;
+ ent = ent->next;
+ }
+ }
+ FREE(rcv.name.elems);
+ if (!ent)
+ return ENOENT;
+ snd.handle.handle = (Ulong) ent;
+
+ repl->size = encode_upp_lookup_r (&snd, buf) - buf;
+
+ return 0;
+}
+
+static int
+do_readdir (unsigned char *buf, upp_repl *repl)
+{
+ upp_readdir_s rcv;
+ upp_readdir_r snd;
+ TAR_DIRENT *ent;
+
+ decode_upp_readdir_s(&rcv, buf);
+
+ ent = (TAR_DIRENT *) rcv.dir.handle;
+ if (ent->size != -1)
+ return ENOTDIR;
+
+ snd.off = 0;
+ snd.name.nelem = 0;
+
+ if (!rcv.off--)
+ {
+ snd.name.elems = ".";
+ }
+ else if (!rcv.off--)
+ {
+ snd.name.elems = "..";
+ ent = ent->pdir;
+ }
+ else
+ {
+ ent = ent->data.dir.first;
+ while (ent && rcv.off--)
+ ent = ent->next;
+ if (ent)
+ {
+ snd.name.elems = ent->name;
+ }
+ }
+
+ if (ent)
+ {
+ snd.off = 1;
+ snd.name.nelem = strlen (snd.name.elems);
+ snd.file.handle = (Ulong) ent;
+ }
+
+ repl->size = encode_upp_readdir_r(&snd, buf) - buf;
+
+ return 0;
+}
+
+static int
+do_open (unsigned char *buf, upp_repl *repl)
+{
+ upp_open_s rcv;
+ TAR_DIRENT *ent;
+
+ decode_upp_open_s (&rcv, buf);
+
+ ent = (TAR_DIRENT *) rcv.file.handle;
+ /* Directories are opened here, but read using _readdir instead of _read,
+ so all we do is return success! */
+ if (ent->size == -1)
+ return 0;
+
+ return a_open (ent);
+}
+
+static int
+do_close (unsigned char *buf, upp_repl *repl)
+{
+ upp_close_s rcv;
+ TAR_DIRENT *ent;
+
+ decode_upp_close_s (&rcv, buf);
+
+ ent = (TAR_DIRENT *) rcv.file.handle;
+ if (ent->size == -1)
+ return 0;
+
+ return a_close (ent);
+}
+
+static int
+do_read (unsigned char *mbuf, upp_repl *repl)
+{
+ upp_read_s rcv;
+ upp_read_r snd;
+ TAR_DIRENT *ent;
+ int rc;
+
+ snd.data.nelem = 0;
+
+ decode_upp_read_s (&rcv, mbuf);
+
+ ent = (TAR_DIRENT *) rcv.file.handle;
+ if (ent->size == -1)
+ return EISDIR;
+
+ /* a_read will allocate its own buffer, so remember to free it */
+ snd.data.elems = NULL;
+ rc = a_read (ent, rcv.off, rcv.size, &snd.data.nelem, &snd.data.elems);
+ if (rc)
+ return rc;
+ repl->size = encode_upp_read_r (&snd, mbuf) - mbuf;
+
+ /* if(snd.data.elems)
+ free(snd.data.elems); */
+
+ return 0;
+}
+
+static int
+do_mount (unsigned char *buf, upp_repl *repl)
+{
+ upp_mount_r snd;
+
+ snd.root.handle = (Ulong) root;
+ repl->size = encode_upp_mount_r(&snd, buf) - buf;
+ /* INIT */
+ repl->size = encode_upp_mount_r(&snd, buf) - buf;
+ return 0;
+}
+
+static void
+run (int wr, int rd)
+{
+ up_preamble pre;
+ upp_repl repl;
+ /* Ah! The bogey man's a-coming to get me! */
+ unsigned char buf[4096];
+ int error;
+
+ while(readpkt(rd, &pre, buf) == 1)
+ {
+ genpkt(&repl, pre.seq, pre.op);
+
+ switch(pre.op)
+ {
+#define DO(op, b, r) case userfs_up_##op: \
+ error = (pre.isreq == UP_ENQ ? 0 : do_##op(b, r)); \
+ break;
+ DO(mount, buf, &repl);
+ DO(iread, buf, &repl);
+ DO(lookup, buf, &repl);
+ DO(readdir, buf, &repl);
+ DO(open, buf, &repl);
+ DO(close, buf, &repl);
+ DO(read, buf, &repl);
+#undef DO
+ default:
+ error = ENOSYS;
+ break;
+ }
+
+ repl.err_no = error;
+ if (error != 0)
+ repl.size = 0;
+
+ if (writepkt(wr, &repl, buf) != 1)
+ break;
+ }
+}
+
+int
+main (int argc, char **argv)
+{
+ int infd = 0;
+ int outfd = 1;
+ int c;
+
+ while ((c = getopt (argc, argv, "i:o:m:")) != EOF)
+ switch(c)
+ {
+ case 'i':
+ infd = atoi(optarg);
+ break;
+ case 'o':
+ outfd = atoi(optarg);
+ break;
+ case 'm':
+ mpoint = optarg;
+ break;
+ default:
+ fprintf (stderr, "%s: bad option\n", argv[0]);
+ return 1;
+ }
+
+ if (optind != argc - 1)
+ {
+ fprintf (stderr, "%s: no zipfile named\n", argv[0]);
+ return 1;
+ }
+
+ root = arc_read (argv[optind++]);
+ if (!root)
+ return 1;
+
+ signal (SIGCHLD, SIG_IGN);
+
+ run(outfd, infd);
+
+ return 0;
+}
Added: trunk/filesystems/tarfs/tarfs.h
==============================================================================
--- trunk/filesystems/tarfs/tarfs.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/tarfs/tarfs.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,47 @@
+#ifndef _TARFS_H
+#define _TARFS_H
+
+#define FAIL(str) fprintf(stderr, "%s:%d %s failed with errno = %s (%d)\n", __FILE__, __LINE__, str, strerror(errno), errno)
+#ifdef DEBUG
+#include <stdio.h>
+#include <stdlib.h>
+#define DB(x) {x;}
+#else
+#define DB(x) /**/
+#endif
+
+typedef struct tagDIRENT TAR_DIRENT;
+
+struct tagDIRENT {
+ TAR_DIRENT *next;
+ /* The directory to which this belongs (or itself if this is the root
+ directory). */
+ TAR_DIRENT *pdir;
+ /* -1 for a directory. */
+ long size;
+ int attr;
+ time_t time;
+ gid_t gid;
+ uid_t uid;
+ union {
+ struct {
+ /* long csize; */
+ unsigned long offset;
+ unsigned int refc; /* PRIVATE to `unzip.c'. */
+ } file;
+ struct {
+ TAR_DIRENT *first;
+ FILE *fd;
+ } dir;
+ } data;
+ char *name;
+ /* Structure is then expanded to whatever... */
+ char fullname[1]; /* PRIVATE to `zip.c'. */
+};
+
+int a_open (TAR_DIRENT *);
+int a_close (TAR_DIRENT *);
+int a_read (TAR_DIRENT *, long, long, unsigned long *, unsigned char **);
+TAR_DIRENT *arc_read (const char *);
+
+#endif /* _TARFS_H */
Added: trunk/filesystems/tarfs/rt.c
==============================================================================
--- trunk/filesystems/tarfs/rt.c 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/tarfs/rt.c 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,94 @@
+#include<stdio.h>
+#include<stdlib.h>
+
+#define TARBLOCK 512
+
+#define TARLEN(x) (((x)+TARBLOCK-1)&~(TARBLOCK-1))
+
+typedef struct _tarinfo
+{
+ long offset;
+ char *filename;
+ int attr;
+ int uid;
+ int gid;
+ int length;
+ int time;
+ int date;
+} tarinfo;
+
+char *savestring(unsigned char **p)
+{
+ char *str ;
+ int len = strlen(*p)+1;
+
+ str = (char *)malloc(len);
+ strcpy(str,*p);
+ (*p) += len;
+
+ return str;
+}
+
+int read_octal(unsigned char **p)
+{
+ int x=0;
+
+ while((**p==0) || (**p==' ')) (*p)++;
+
+ while(('0' <= (**p)) && ('7' >= (**p)))
+ {
+ x<<=3;
+ x+=(**p-'0');
+ (*p)++;
+ }
+
+ return x;
+}
+
+int read_tarindex(FILE *tar, tarinfo *head)
+{
+ static unsigned char tmp[TARBLOCK];
+ unsigned char *p = tmp;
+
+ head->offset = ftell(tar);
+ if(1 != fread(tmp, TARBLOCK, 1, tar))
+ return 1;
+
+ if(!p[0])
+ return 1;
+
+ head->filename = savestring(&p);
+ head->attr = read_octal(&p);
+ head->uid = read_octal(&p);
+ head->gid = read_octal(&p);
+ head->length = read_octal(&p);
+ head->time = read_octal(&p);
+ head->date = read_octal(&p);
+
+ return 0;
+}
+
+main(int argc, char ** argv)
+{
+ FILE *tar = fopen(argv[1],"rb");
+ tarinfo tar_entry;
+
+ if(!tar)
+ {
+ fprintf(stderr,"Can't open tar file\n");
+ return 1;
+ }
+
+ while(0==read_tarindex(tar,&tar_entry))
+ {
+ printf("%s\n",tar_entry.filename);
+ printf("attr\t= %x\n",tar_entry.attr);
+ printf("len\t= %x\n",tar_entry.length);
+ if(0>fseek(tar,TARLEN(tar_entry.length),SEEK_CUR))
+ break;
+ }
+
+ fclose(tar);
+
+ return 0;
+}
Added: trunk/filesystems/tarfs/tarvfs.c
==============================================================================
--- trunk/filesystems/tarfs/tarvfs.c 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/tarfs/tarvfs.c 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,288 @@
+/* TAR Archive VFS layer. */
+
+/*
+** Derived from arcvfs.c originally by David P. Gymer
+** Modified by Michael McCormack to read tar files directly.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "tarvfs.h"
+
+#define TARBLOCK 512
+#define TARDIR 0x400
+
+#define TARLEN(x) (((x)+TARBLOCK-1)&~(TARBLOCK-1))
+
+typedef struct _tarinfo
+{
+ long offset;
+ char *filename;
+ int attr;
+ int uid;
+ int gid;
+ int length;
+ int time;
+ int date;
+} tarinfo;
+
+TAR_DIRENT *
+create_entry (const char *fname, const char *name, TAR_DIRENT *dir)
+{
+ TAR_DIRENT *ent;
+
+ ent = malloc (sizeof (TAR_DIRENT) + strlen (fname));
+ if (ent)
+ {
+ strcpy (ent->fullname, fname);
+ ent->name = ent->fullname + (name - fname);
+ ent->pdir = dir;
+ ent->next = 0;
+ }
+ return ent;
+}
+
+TAR_DIRENT *
+create_dirent (char *fname, char *name, TAR_DIRENT **p_ent, TAR_DIRENT *dir)
+{
+ char *s;
+
+ if (!p_ent)
+ return 0;
+
+ while ((s = strchr (name, '/')) != 0)
+ {
+ *s = '\0';
+ while (*p_ent && strcmp (name, (*p_ent)->name))
+ p_ent = &(*p_ent)->next;
+ if (!*p_ent)
+ {
+ *p_ent = create_entry (fname, name, dir);
+ if (!*p_ent)
+ return 0;
+ (*p_ent)->size = -1;
+ (*p_ent)->data.dir.first = 0;
+ }
+ /* Check for directory/file clash. */
+ if ((*p_ent)->size != -1)
+ return 0;
+ dir = *p_ent;
+ p_ent = &(*p_ent)->data.dir.first;
+ *s++ = '/';
+ name = s;
+ }
+
+ while (*p_ent)
+ p_ent = &(*p_ent)->next;
+
+ *p_ent = create_entry (fname, name, dir);
+ return *p_ent;
+}
+
+static TAR_DIRENT *
+root_ent (TAR_DIRENT *ent)
+{
+ while (ent->pdir != ent)
+ ent = ent->pdir;
+ return ent;
+}
+
+/* The generic read/write code. */
+
+int
+a_open (TAR_DIRENT *ent)
+{
+ if(ent->size == -1)
+ return EIO;
+ ++ent->data.file.refc;
+ return 0;
+}
+
+int
+a_close (TAR_DIRENT *ent)
+{
+ if (!ent->data.file.refc)
+ return EBADF;
+ --ent->data.file.refc;
+ return 0;
+}
+
+/*
+** This function needs to read data into a buffer of some
+** arbitary size, which is not provided. Make sure the calling
+** function frees the data in *elems when it is done with it.
+*/
+int a_read (TAR_DIRENT *ent, long off, long size,
+ unsigned long *nelem, unsigned char **elems)
+{
+ TAR_DIRENT *root = root_ent (ent);
+
+ if(!root)
+ {
+ fprintf(stderr,"couldn't get the root directory\n");
+ return EINVAL;
+ }
+
+ if (!ent->data.file.refc)
+ {
+ fprintf(stderr,"tried to read an unopened file\n");
+ return EINVAL;
+ }
+
+ if (ent->size == -1)
+ {
+ fprintf(stderr,"tried to read a directory\n");
+ return EINVAL;
+ }
+
+ *elems = NULL;
+ *nelem = 0;
+
+ if(size > (ent->size - off))
+ size = ent->size - off;
+
+ if(size)
+ *elems = (unsigned char *) malloc(size);
+
+ if(*elems)
+ {
+ fseek(root->data.dir.fd, ent->data.file.offset, SEEK_SET);
+ *nelem = fread(*elems, 1, size, root->data.dir.fd);
+ if(*nelem < 0)
+ return EIO;
+ if(*nelem != size)
+ fprintf(stderr,"couldn't read all the data.\n");
+ }
+
+ return 0;
+}
+
+char *savestring(unsigned char **p)
+{
+ char *str ;
+ int len = strlen(*p)+1;
+
+ str = (char *)malloc(len);
+ strcpy(str,*p);
+ (*p) += len;
+
+ return str;
+}
+
+int read_octal(unsigned char **p)
+{
+ int x=0;
+
+ while((**p==0) || (**p==' ')) (*p)++;
+
+ while(('0' <= (**p)) && ('7' >= (**p)))
+ {
+ x<<=3;
+ x+=(**p-'0');
+ (*p)++;
+ }
+
+ return x;
+}
+
+int read_tarindex(FILE *tar, tarinfo *head)
+{
+ static unsigned char tmp[TARBLOCK];
+ unsigned char *p = tmp;
+
+ head->offset = ftell(tar);
+ if(1 != fread(tmp, TARBLOCK, 1, tar))
+ return 1;
+
+ if(!p[0])
+ return 1;
+
+ head->filename = savestring(&p);
+ head->attr = read_octal(&p);
+ head->uid = read_octal(&p);
+ head->gid = read_octal(&p);
+ head->length = read_octal(&p);
+ head->time = read_octal(&p);
+ head->date = read_octal(&p);
+
+ return 0;
+}
+
+/* The VFS code itself. */
+
+TAR_DIRENT *
+arc_read (const char *tarfile)
+{
+ TAR_DIRENT *first = NULL, *ent = NULL;
+ FILE *tar = fopen(tarfile,"rb");
+ tarinfo tar_entry;
+ struct stat st;
+
+ if(!tar)
+ {
+ fprintf(stderr,"Can't open tar file\n");
+ return NULL;
+ }
+
+ stat(tarfile,&st);
+
+ first = create_entry (tarfile, tarfile, 0);
+ if (!first)
+ return NULL;
+
+ first->pdir = first;
+ first->size = -1;
+ first->data.dir.first = 0;
+ first->name = NULL;
+ first->data.dir.fd = tar;
+ first->gid = st.st_gid;
+ first->uid = st.st_uid;
+ first->time = st.st_mtime;
+
+ while(0==read_tarindex(tar,&tar_entry))
+ {
+ ent = create_dirent (tar_entry.filename,
+ tar_entry.filename,
+ &first->data.dir.first,
+ first);
+ if(!ent)
+ break;
+
+ if(tar_entry.attr & TARDIR)
+ {
+ /* create dirent */
+ ent->size = -1;
+ ent->data.dir.first = 0;
+ }
+ else
+ {
+ /* create normal file */
+ ent->size = tar_entry.length;
+ ent->data.file.refc = 0;
+ ent->data.file.offset = tar_entry.offset + TARBLOCK;
+ }
+ ent->gid = tar_entry.gid;
+ ent->uid = tar_entry.uid;
+ ent->attr = tar_entry.attr;
+ ent->time = tar_entry.time;
+ ent->next = NULL;
+ if(0>fseek(tar,TARLEN(tar_entry.length),SEEK_CUR))
+ break;
+ }
+
+ if(!ent)
+ {
+ free(first);
+ first=NULL;
+ fclose(tar);
+ fprintf (stderr, "%s: not a tar archive!\n", tarfile);
+ }
+
+ return first;
+}
+
Added: trunk/filesystems/tarfs/tarvfs.h
==============================================================================
--- trunk/filesystems/tarfs/tarvfs.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/tarfs/tarvfs.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,9 @@
+#ifndef _TARVFS_H
+#define _TARVFS_H
+
+#include "tarfs.h"
+
+TAR_DIRENT *create_entry (const char *, const char *, TAR_DIRENT *);
+TAR_DIRENT *create_dirent (char *, char *, TAR_DIRENT **, TAR_DIRENT *);
+
+#endif /* _TARVFS_H */
Added: trunk/filesystems/tarfs/Makefile
==============================================================================
--- trunk/filesystems/tarfs/Makefile 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/tarfs/Makefile 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,37 @@
+CC = gcc
+CFLAGS = -O2 -Wall -I../../kernel
+CPPFLAGS = #-DDEBUG
+LDFLAGS = -s
+
+NAME = tarfs
+SRCS = tarfs.c tarvfs.c
+INC = tarvfs.h tarfs.h
+DISTS = $(SRCS) $(INC) README Makefile
+
+$(NAME) : $(SRCS:%.o=%.c)
+
+.PHONY : dist dep clean realclean spotless
+
+dep : .depend
+.depend : $(SRCS) $(INC)
+ $(CC) $(CFLAGS) -MM *.c > .depend
+
+dist : $(DISTS)
+ rm -rf /tmp/$(NAME)
+ mkdir /tmp/$(NAME)
+ cp -a $(DISTS) /tmp/$(NAME)
+ (cd /tmp; tar cfvz - $(NAME)) > $(NAME).tar.gz
+ rm -rf /tmp/$(NAME)
+
+clean :
+ rm -f *.o core *~ *.orig *.rej tarfs
+
+realclean : clean
+ rm -rf $(NAME)
+
+spotless : realclean
+ rm -f .depend
+
+ifeq (.depend,$(wildcard .depend))
+include .depend
+endif
Added: trunk/filesystems/tarfs/README
==============================================================================
--- trunk/filesystems/tarfs/README 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/tarfs/README 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,12 @@
+TARFS - transparent read-only TAR file access for Linux
+
+Copyright (C) 1999 Michael J McCormack
+
+Derived in part from code written by Jeremy Fitzhardinge
+<jeremy at sw.oz.au> and David P Gymer
+
+The idea of using a command line to read the tar file's data irked me a little
+and for some practice in userfs, i decided to rewrite the arcfs code to
+access a tar file directly. This code will only access a tar file, not a
+gzipped tar file! (might try to do that a little later...)
+
Added: trunk/filesystems/yfs/yfs.c
==============================================================================
--- trunk/filesystems/yfs/yfs.c 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/yfs/yfs.c 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,705 @@
+/* (Read-only) archive filesystem. */
+
+#define CVS
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <utime.h>
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include <getopt.h>
+#include <assert.h>
+
+#include <time.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/fcntl.h>
+
+#include <linux/fs.h>
+#include <linux/userfs_fs.h>
+
+#include <unistd.h>
+#include <linux/dirent.h>
+#include <linux/unistd.h>
+
+#include <assert.h>
+
+#define Y_MAGIC 0x005D595D
+
+typedef struct Y_DIRENT {
+ int magic;
+ int fd;
+ int ref_count;
+ struct Y_DIRENT *parent;
+ struct Y_DIRENT *next;
+ struct Y_DIRENT *child;
+ char name[1];
+} Y_DIRENT;
+
+static char *mpoint;
+static Y_DIRENT *root;
+
+unsigned char *delete_me = NULL;
+
+/* No point in this being in a seperate file. */
+#include <linux/userfs_types.c>
+
+#define FAIL(str) fprintf(stderr, "%s:%d %s failed with errno = %s (%d)\n", \
+ __FILE__, __LINE__, str, strerror(errno), errno)
+
+static int
+myread (int fd, void *buf, int sz)
+{
+ int rd = 0;
+ int ret;
+
+ while (sz > 0)
+ {
+ ret = read (fd, buf, sz);
+
+ if (ret == -1)
+ {
+ if (errno == EINTR)
+ continue;
+
+ perror ("myread");
+ exit (1);
+ }
+
+ if (ret == 0)
+ break;
+
+ sz -= ret;
+ buf += ret;
+ rd += ret;
+ }
+
+ return rd;
+}
+
+static int
+mywrite (int fd, const void *buf, int sz)
+{
+ int wr = 0;
+ int ret;
+
+ while (sz > 0)
+ {
+ ret = write (fd, buf, sz);
+
+ if (ret == -1)
+ {
+ if (errno == EINTR)
+ continue;
+ FAIL ("write");
+ exit (1);
+ }
+
+ if (ret == 0)
+ {
+ fprintf (stderr, "write wrote 0 bytes\n");
+ break;
+ }
+
+ sz -= ret;
+ buf += ret;
+ wr += ret;
+ }
+
+ return wr;
+}
+
+static int
+readpkt (int fd, up_preamble *pre, unsigned char *buf)
+{
+ int presz = sizeof_up_preamble (pre);
+ unsigned int rd;
+ unsigned char pbuf[presz];
+
+ memset (pbuf, 0, sizeof (pbuf));
+
+ rd = myread (fd, pbuf, presz);
+ if (rd != presz)
+ {
+ if (rd == 0)
+ return 0;
+ if (rd > 0)
+ fprintf (stderr, "readpkt, incomplete read (%d, not %d)\n",
+ rd, presz);
+ perror ("readpkt, header read");
+ return -1;
+ }
+
+ decode_up_preamble (pre, pbuf);
+
+ if (pre->isreq != UP_ENQ && pre->isreq != UP_REQ)
+ fprintf (stderr, "pre->isreq = %d\n", pre->isreq);
+
+ if (pre->version != UP_VERSION)
+ {
+ fprintf (stderr, "Version mismatch: us=%d them=%d\n",
+ UP_VERSION, pre->version);
+ return -1;
+ }
+
+ if (pre->size != 0)
+ {
+ if (myread (fd, buf, pre->size) != pre->size)
+ {
+ perror ("readpkt, body read");
+ return -1;
+ }
+ }
+
+ return 1;
+}
+
+static int
+writepkt (int fd, upp_repl *repl, const unsigned char *buf)
+{
+ int replsz = sizeof_upp_repl (repl);
+ unsigned char pbuf[replsz];
+ unsigned int wr;
+ unsigned char *p;
+
+ assert (repl->version == UP_VERSION);
+ assert (repl->isreq == UP_REPL);
+
+ p = encode_upp_repl (repl, pbuf);
+
+ assert (replsz == p - pbuf);
+
+ wr = mywrite (fd, pbuf, replsz);
+ if (wr != replsz)
+ {
+ perror ("writepkt, header write");
+ return -1;
+ }
+
+ if (repl->size > 0 && repl->err_no == 0)
+ {
+ if ( mywrite(fd, buf, repl->size) != repl->size)
+ {
+ perror ("writepkt, body write");
+ return -1;
+ }
+ }
+
+ return 1;
+}
+
+static void
+genpkt (upp_repl *repl, int seq, up_ops op)
+{
+ repl->version = UP_VERSION;
+ repl->seq = seq;
+ repl->op = op;
+ repl->isreq = 0;
+ repl->size = 0;
+ repl->err_no = 0;
+}
+
+/* construct path name without trailing slash */
+static int
+get_path(char *name, int size, Y_DIRENT *t)
+{
+ int len,plen;
+
+ if(!t)
+ return ENOENT;
+ len = strlen(t->name)+1; /* include trailing zero byte */
+ if(len>size)
+ return ENOENT;
+ if(t->parent != t) {
+ len++; /* include slash */
+ if(0>(plen=get_path(name, size - len, t->parent)))
+ return ENOENT;
+ strcat(name,"/");
+ strcat(name,t->name);
+ }
+ else
+ {
+ plen=0;
+ strcpy(name,t->name);
+ }
+ return plen+len;
+}
+
+int ReadChildren(Y_DIRENT *ent)
+{
+ /* read the directory into memory */
+ Y_DIRENT *t;
+ char buffer[1024],filename[1024],*p;
+ struct dirent *de=(struct dirent *)buffer;
+ int len,n,fd;
+
+ if(0>get_path(filename, sizeof filename, ent))
+ return ENOTDIR;
+
+ fprintf(stderr,"reading dir: %s\n",buffer);
+
+ fd = open(filename,O_RDONLY);
+ if(!fd)
+ return ENOTDIR;
+
+#ifdef CVS
+ /* ok, now prepare to stat each file by adding it to the buffer */
+ p = &filename[strlen(filename)];
+ *p++ = '/';
+#endif
+
+ while(1) {
+ de=(struct dirent *)&buffer[0];
+ n=0;
+ len=getdents(fd, de, sizeof buffer);
+ if(!len)
+ break;
+ while(n<len)
+ {
+ if(strcmp(de->d_name,".") && strcmp(de->d_name,".."))
+ {
+ int add_file = 1;
+
+#ifdef CVS
+ /* check that the file is a CVS version or a directory */
+ if(strcmp(&de->d_name[strlen(de->d_name)-2],",v"))
+ {
+ struct stat st;
+
+ /* stat the file */
+ strcpy(p,de->d_name);
+ if(0>stat(filename,&st))
+ add_file = 0;
+ if(!S_ISDIR(st.st_mode))
+ add_file = 0;
+ }
+ else
+ {
+ /* remove the ,v */
+ de->d_name[strlen(de->d_name)-2]=0;
+ add_file = 1;
+ }
+#endif
+
+ if(add_file)
+ {
+ t = malloc(sizeof (Y_DIRENT) + strlen(de->d_name));
+ strcpy(t->name,de->d_name);
+ t->magic = Y_MAGIC;
+ t->fd = 0;
+ t->ref_count=0;
+ t->parent = ent;
+ t->child = NULL;
+
+ fprintf(stderr,"adding entry: %s\n",t->name);
+
+ /* add this to the head of the parent's child list */
+ t->next = ent->child;
+ ent->child = t;
+ }
+ }
+ n+=de->d_reclen;
+ de = (struct dirent *)&buffer[n];
+ }
+ }
+ close(fd);
+
+ return 0;
+}
+
+#define DIRINO 1
+
+static int
+do_iread (unsigned char *buf, upp_repl *repl)
+{
+ upp_iread_s rcv;
+ upp_iread_r snd;
+ struct stat st;
+ Y_DIRENT *ent ;
+ char name[1024];
+
+ decode_upp_iread_s(&rcv, buf);
+
+ memset(&snd, 0, sizeof(snd));
+
+ ent = (Y_DIRENT *) rcv.handle.handle;
+ snd.handle = rcv.handle;
+
+ if(0 > get_path(name,sizeof name, ent))
+ return ENOENT;
+
+ fprintf(stderr,"stat on file: %s\n",name);
+
+ /* if the file exists, add it to our tree */
+ if(0>lstat(name,&st))
+ {
+#ifdef CVS
+ strcat(name,",v");
+ if(0>lstat(name,&st))
+#endif
+ return ENOENT;
+ }
+
+ /* copy from one filesystem to the other */
+ snd.ino.mode = st.st_mode;
+ snd.ino.size = st.st_size;
+ snd.ino.uid = st.st_uid;
+ snd.ino.gid = st.st_gid;
+ snd.ino.nlink = st.st_nlink;
+ snd.ino.blksize = st.st_blksize;
+ snd.ino.blocks = st.st_blocks;
+ snd.ino.mtime = st.st_mtime;
+ snd.ino.atime = st.st_atime;
+ snd.ino.ctime = st.st_ctime;
+ snd.ino.rdev = st.st_rdev;
+
+ repl->size = encode_upp_iread_r(&snd, buf) - buf;
+
+ return 0;
+}
+
+static int
+do_lookup (unsigned char *buf, upp_repl *repl)
+{
+ upp_lookup_s rcv;
+ upp_lookup_r snd;
+ Y_DIRENT *ent;
+ Y_DIRENT *t;
+
+ decode_upp_lookup_s(&rcv, buf);
+
+ ent = (Y_DIRENT *) rcv.dir.handle;
+
+ if (rcv.name.nelem == 2
+ && rcv.name.elems[0] == '.' && rcv.name.elems[1] == '.')
+ {
+ t = ent->parent;
+ }
+ else if (rcv.name.nelem == 1 && rcv.name.elems[0] == '.')
+ {
+ t = ent;
+ }
+ else
+ {
+ if(!ent->child)
+ ReadChildren(ent);
+ for(t = ent->child; t; t=t->next)
+ {
+ /* check the length */
+ if(t->name[rcv.name.nelem])
+ continue;
+ if (!strncmp(t->name, rcv.name.elems, rcv.name.nelem))
+ break;
+ }
+ if(!t)
+ {
+ char name[1024];
+ struct stat st;
+ int len;
+
+ /* construct a path name to the file */
+ len = get_path(name,sizeof name, ent);
+ if((len+rcv.name.nelem+1) > sizeof name)
+ return ENOENT;
+ strcat(name,"/");
+ strncat(name,rcv.name.elems,rcv.name.nelem);
+ name[len+rcv.name.nelem]=0;
+
+ fprintf(stderr,"looking up: %s\n",name);
+
+ /* if the file exists, add it to our tree */
+ if(0>stat(name,&st))
+ return ENOENT;
+
+ /* make the new entry */
+ t = (Y_DIRENT *) malloc(sizeof(Y_DIRENT)+rcv.name.nelem);
+ strncpy(t->name,rcv.name.elems,rcv.name.nelem);
+ name[rcv.name.nelem]=0;
+ t->magic = Y_MAGIC;
+ t->fd = 0;
+ t->ref_count=0;
+ t->parent = ent;
+ t->child = NULL;
+
+ /* add it to the head of the child list */
+ t->next = ent->child;
+ ent->child = t;
+ }
+ }
+ FREE(rcv.name.elems);
+ if (!t)
+ return ENOENT;
+ snd.handle.handle = (Ulong) t;
+
+ repl->size = encode_upp_lookup_r (&snd, buf) - buf;
+
+ return 0;
+}
+
+/* read the elements in a directory */
+static int
+do_readdir (unsigned char *buf, upp_repl *repl)
+{
+ upp_readdir_s rcv;
+ upp_readdir_r snd;
+ Y_DIRENT *ent;
+ Y_DIRENT *t;
+
+ decode_upp_readdir_s(&rcv, buf);
+
+ ent = (Y_DIRENT *) rcv.dir.handle;
+
+ snd.off = 0;
+ snd.name.nelem = 0;
+
+ /* if there are no children, try and read some */
+ if(!ent->child)
+ ReadChildren(ent);
+
+ /* now just look up the appropriate offset */
+ switch(rcv.off) {
+ case 0:
+ snd.name.elems = ".";
+ t = ent;
+ break;
+ case 1:
+ snd.name.elems = "..";
+ t = ent->parent;
+ break;
+ default:
+ rcv.off-=2;
+ for(t=ent->child; t && rcv.off--; t=t->next);
+ if (t)
+ snd.name.elems = t->name;
+ }
+
+ if(t) {
+ snd.off = 1;
+ snd.name.nelem = strlen (snd.name.elems);
+ snd.file.handle = (Ulong) t;
+ }
+
+ repl->size = encode_upp_readdir_r(&snd, buf) - buf;
+
+ return 0;
+}
+
+static int
+do_open (unsigned char *buf, upp_repl *repl)
+{
+ upp_open_s rcv;
+ Y_DIRENT *ent;
+ char filename[1024];
+
+ decode_upp_open_s (&rcv, buf);
+
+ ent = (Y_DIRENT *) rcv.file.handle;
+
+ if(ent->magic != Y_MAGIC)
+ return EPERM;
+
+ if(!ent->ref_count)
+ {
+ if(0>get_path(filename,sizeof filename,ent))
+ return EPERM;
+ ent->fd = open ( filename, O_RDONLY);
+ if(ent->fd<0)
+ return -ent->fd;
+ }
+ ent->ref_count++;
+
+ return 0;
+}
+
+static int
+do_close (unsigned char *buf, upp_repl *repl)
+{
+ upp_close_s rcv;
+ Y_DIRENT *ent;
+
+ decode_upp_close_s (&rcv, buf);
+
+ ent = (Y_DIRENT *) rcv.file.handle;
+
+ if(!ent->ref_count)
+ return EPERM;
+
+ ent->ref_count--;
+ if(!ent->ref_count)
+ {
+ close(ent->fd);
+ ent->fd = 0;
+ }
+
+ return 0;
+}
+
+static int
+do_read (unsigned char *mbuf, upp_repl *repl)
+{
+ upp_read_s rcv;
+ upp_read_r snd;
+ Y_DIRENT *ent;
+ int rc;
+ long size;
+
+ snd.data.nelem = 0;
+ snd.data.elems = NULL;
+
+ decode_upp_read_s (&rcv, mbuf);
+
+ ent = (Y_DIRENT *) rcv.file.handle;
+
+ /* check that the file is actually open */
+ if(!ent->ref_count)
+ return EPERM;
+
+ size = lseek(ent->fd,0,SEEK_END);
+ if(0>lseek(ent->fd,rcv.off,SEEK_SET))
+ return EPERM;
+
+ if( (size - rcv.off) < rcv.size )
+ size = (size - rcv.off);
+ else
+ size = rcv.size;
+
+ /* where is this going to be free'd ? */
+ if(size)
+ snd.data.elems = (unsigned char *)malloc(size);
+
+ if(snd.data.elems)
+ {
+ rc = read(ent->fd,snd.data.elems,size);
+ if(rc < 0)
+ return rc;
+ snd.data.nelem = rc;
+ }
+
+ repl->size = encode_upp_read_r (&snd, mbuf) - mbuf;
+
+ /* hack alert! */
+ delete_me = snd.data.elems;
+
+ return 0;
+}
+
+static int
+do_mount (unsigned char *buf, upp_repl *repl)
+{
+ upp_mount_r snd;
+
+ snd.root.handle = (Ulong) root;
+ repl->size = encode_upp_mount_r(&snd, buf) - buf;
+ /* INIT */
+ repl->size = encode_upp_mount_r(&snd, buf) - buf;
+ return 0;
+}
+
+static void
+run (int wr, int rd)
+{
+ up_preamble pre;
+ upp_repl repl;
+ /* Ah! The bogey man's a-coming to get me! */
+ unsigned char buf[4096];
+ int error;
+
+ while(readpkt(rd, &pre, buf) == 1)
+ {
+ genpkt(&repl, pre.seq, pre.op);
+
+ switch(pre.op)
+ {
+#define DO(op, b, r) case up_##op: \
+ error = (pre.isreq == UP_ENQ ? 0 : do_##op(b, r)); \
+ break;
+ DO(mount, buf, &repl);
+ DO(iread, buf, &repl);
+ DO(lookup, buf, &repl);
+ DO(readdir, buf, &repl);
+ DO(open, buf, &repl);
+ DO(close, buf, &repl);
+ DO(read, buf, &repl);
+#undef DO
+ default:
+ error = ENOSYS;
+ break;
+ }
+
+ repl.err_no = error;
+ if (error != 0)
+ repl.size = 0;
+
+ if (writepkt(wr, &repl, buf) != 1)
+ break;
+
+ /* this is a terrible hack! */
+ if(delete_me)
+ {
+ free(delete_me);
+ delete_me = NULL;
+ }
+ }
+}
+
+Y_DIRENT *y_read(char *rootname)
+{
+ Y_DIRENT *root;
+
+ root = (Y_DIRENT*)malloc(sizeof(Y_DIRENT)+strlen(rootname));
+
+ root->magic = Y_MAGIC;
+ root->fd = 0;
+ root->ref_count = 1;
+ root->parent = root;
+ root->next = NULL;
+ root->child = NULL;
+ strcpy(root->name,rootname);
+
+ fprintf(stderr,"mounting mirror file system of %s\n",root->name);
+
+ return root;
+}
+
+int
+main (int argc, char **argv)
+{
+ int infd = 0;
+ int outfd = 1;
+ int c;
+
+ while ((c = getopt (argc, argv, "i:o:m:")) != EOF)
+ switch(c)
+ {
+ case 'i':
+ infd = atoi(optarg);
+ break;
+ case 'o':
+ outfd = atoi(optarg);
+ break;
+ case 'm':
+ mpoint = optarg;
+ break;
+ default:
+ fprintf (stderr, "%s: bad option\n", argv[0]);
+ return 1;
+ }
+
+ if (optind != argc - 1)
+ {
+ fprintf (stderr, "%s: no zipfile named\n", argv[0]);
+ return 1;
+ }
+
+ root = y_read (argv[optind++]);
+ if (!root)
+ return 1;
+
+ signal (SIGCHLD, SIG_IGN);
+
+ run(outfd, infd);
+
+ return 0;
+}
Added: trunk/filesystems/yfs/Makefile
==============================================================================
--- trunk/filesystems/yfs/Makefile 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/yfs/Makefile 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,35 @@
+CC = gcc
+CFLAGS = -O2 -Wall -I../../kernel
+CPPFLAGS = #-DDEBUG
+LDFLAGS = -s
+
+SRCS = yfs.c
+DISTS = $(SRCS) README Makefile
+
+yfs : yfs.o
+
+.PHONY : dist dep clean realclean spotless
+
+dep : .depend
+.depend : $(SRCS)
+ $(CC) $(CFLAGS) -MM *.c > .depend
+
+dist : $(DISTS)
+ rm -rf /tmp/yfs
+ mkdir /tmp/yfs
+ cp -a $(DISTS) /tmp/yfs
+ (cd /tmp; tar cfvz - yfs) >yfs.tar.gz
+ rm -rf /tmp/yfs
+
+clean :
+ rm -f *.o core *~ *.orig *.rej
+
+realclean : clean
+ rm -rf yfs
+
+spotless : realclean
+ rm -f .depend
+
+ifeq (.depend,$(wildcard .depend))
+include .depend
+endif
Added: trunk/filesystems/ftpfs/ftpfile.h
==============================================================================
--- trunk/filesystems/ftpfs/ftpfile.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/ftpfs/ftpfile.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,53 @@
+// -*- C++ -*-
+
+#ifndef _FTPFILE_H_
+#define _FTPFILE_H_
+
+#pragma interface
+
+#include "ino.h"
+#include <string>
+#include <sys/types.h>
+#include <time.h>
+
+class ftpfile : public ino
+{
+ friend class docopy;
+
+ class ftpdir *dir;
+ class ftpconn *conn;
+ string name;
+
+ int do_read(const up_preamble &, upp_repl &,
+ const upp_read_s &, upp_read_r &);
+ int do_iput(const up_preamble &, upp_repl &,
+ const upp_iput_s &);
+
+ int updatefile();
+ int updating;
+ class LWP *upd_thread;
+
+ struct waiting *wlist;
+ struct waiting *addwlist(off_t off);
+ void delwlist(struct waiting *);
+
+ int open(int=0,int=0666); // Open cache file
+ void close(); // Close it
+ int fd; // fd of cache file
+
+ void decref();
+
+ int read(unsigned char *, size_t, off_t);
+public:
+ ftpfile(class ftpfs &, const string &name, class ftpdir *dir, class ftpconn *conn);
+ ~ftpfile();
+
+ int is_uptodate() const;
+ void setstats(size_t size, time_t time);
+ void getstats(size_t &sz, time_t &time) const
+ {
+ sz = size;
+ time = mtime;
+ }
+};
+#endif /* _FTPFILE_H_ */
Added: trunk/filesystems/ftpfs/Path.cc
==============================================================================
--- trunk/filesystems/ftpfs/Path.cc 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/ftpfs/Path.cc 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,76 @@
+// -*- C++ -*-
+
+// Pathname handling
+
+// (C) Copyright 1994 Jeremy Fitzhardinge <jeremy at sw.oz.au>
+// This code is distributed under the terms of the
+// GNU General Public Licence. See COPYING for more details.
+
+#pragma implementation
+
+#include "Path.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/param.h>
+#include <assert.h>
+#include <string>
+
+Path::Path(const string &elem, const Path *parent)
+ :_parent(parent)
+{
+ p_rep = new _PathRep(elem, parent ? parent->p_rep : (const _PathRep *)NULL);
+}
+
+Path::Path(const Path &p)
+{
+ memcpy(this, &p, sizeof(*this));
+ p_rep->incref();
+}
+
+Path &
+Path::operator = (const Path &p)
+{
+ if (this != &p)
+ {
+ p_rep->decref();
+ *this = p;
+ p_rep->incref();
+ }
+ return *this;
+}
+
+Path::~Path()
+{
+ p_rep->decref();
+}
+
+_PathRep::_PathRep(const string &elem, const _PathRep *p)
+ :_path(elem), _parent(p)
+{
+ count = 1;
+ if (p)
+ ((_PathRep *)p)->incref(); // XXX
+}
+
+_PathRep::~_PathRep()
+{
+ assert(count == 0);
+ if (_parent != NULL)
+ ((_PathRep *)_parent)->decref(); // XXX
+}
+
+string
+_PathRep::path() const
+{
+ string p;
+
+ if (_parent != NULL)
+ {
+ p = _parent->path();
+ cat(p, "/", _path, p);
+ }
+ else
+ p = _path;
+
+ return p;
+}
Added: trunk/filesystems/ftpfs/topdir.cc
==============================================================================
--- trunk/filesystems/ftpfs/topdir.cc 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/ftpfs/topdir.cc 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,188 @@
+// -*- C++ -*-
+
+// Top directory
+// This is initialized from the cache directory, but users can
+// create directories with the names of hostnames. Directories
+// are always created with the official hostname of a machine,
+// with all the alises appearing as symlinks.
+
+// (C) Copyright 1994 Jeremy Fitzhardinge <jeremy at sw.oz.au>
+// This code is distributed under the terms of the
+// GNU General Public Licence. See COPYING for more details.
+
+#pragma implementation
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string>
+
+#include <unistd.h>
+#include <netdb.h>
+#include <stdio.h>
+
+#include "ftpfs.h"
+#include "topdir.h"
+#include "sitetopdir.h"
+#include "ftpconn.h"
+#include "ftplink.h"
+
+int
+topdir::do_create(const up_preamble &, upp_repl &,
+ const upp_create_s &arg, upp_create_r &ret)
+{
+ if (!S_ISDIR(arg.mode))
+ return EPERM;
+
+ string name((char *)arg.name.elems, (int)arg.name.nelem);
+
+ return create(name, ret.file);
+}
+
+int
+topdir::create(const string &name, up_handle &handle)
+{
+ struct hostent *he = gethostbyname((const char *)name.data());
+
+ if (!he)
+ {
+ cerr << "Hostname lookup for " << name << " failed:",
+ herror("");
+ return ENOENT;
+ }
+
+ struct hostent *rhe = NULL;
+ string hostname = he->h_name; // First guess
+
+ if (!he->h_addr_list[0] || he->h_addrtype != AF_INET)
+ {
+ cerr << name << ": no address associated with name\n";
+ return ENOENT;
+ }
+
+ cout << "IP for " << name << " is "
+ << (unsigned)(unsigned char)(he->h_addr_list[0][0]) << '.'
+ << (unsigned)(unsigned char)(he->h_addr_list[0][1]) << '.'
+ << (unsigned)(unsigned char)(he->h_addr_list[0][2]) << '.'
+ << (unsigned)(unsigned char)(he->h_addr_list[0][3]) << ".\n";
+
+ char *xaddr = new char[he->h_length];
+ if (xaddr)
+ {
+ // Avoid stepping on buffers
+
+ memcpy(xaddr, he->h_addr_list[0], he->h_length);
+
+ rhe = gethostbyaddr(xaddr, he->h_length, he->h_addrtype);
+ delete xaddr;
+ }
+
+ cout << "Reverse lookup " << (rhe ? "succeeded\n" : "failed\n");
+
+ if (rhe)
+ hostname = rhe->h_name; // Reverse lookup is better
+
+ cout << "Official name of " << name << " is " << hostname << '\n';
+
+ if (lookup(name)) // Already exists?
+ return EEXIST;
+ else
+ {
+ DirEntry *de = lookup(hostname);
+
+ if (!de)
+ {
+ Inode *ino = new sitetopdir(filesys, hostname, this);
+ link(hostname, ino);
+ handle.handle = ino->gethandle();
+ }
+ if (name != hostname)
+ {
+ Inode *ino = new ftplink(filesys, hostname, this, name);
+ if (link(name, ino))
+ delete ino;
+ }
+ if (de)
+ return EEXIST; // We just needed a new link
+ }
+
+ for (char **aliaspp = he->h_aliases; aliaspp && *aliaspp; aliaspp++)
+ {
+ string alias(*aliaspp);
+
+ cout << "aliasing to " << *aliaspp << '\n';
+
+ Inode *ino = new ftplink(filesys, hostname, this, alias);
+ if (link(alias, ino))
+ delete ino;
+ }
+
+ return 0;
+}
+
+topdir::topdir(ftpfs &fs, const string &cache)
+ :dir(fs, cache, NULL)
+{
+ mode = S_IFDIR | 0777;
+ init();
+}
+
+Inode *
+topdir::newinode(dir *d, const struct stat *st, const string &name)
+{
+ Inode *ino = NULL;
+
+ if (S_ISDIR(st->st_mode))
+ {
+ if (name == "." || name == "..")
+ return NULL;
+ ino = new sitetopdir(filesys, name, this);
+ }
+ else if (S_ISLNK(st->st_mode))
+ {
+ char buf[1024];
+ int len = readlink(name.data(), buf, sizeof(buf));
+ if (len == -1)
+ return NULL;
+
+ ino = new ftplink(filesys, string(buf, len), this, name);
+ }
+
+ return ino;
+}
+
+//
+// hpa 951118: topdir::do_lookup is overloaded in order to provide an
+// "automounter" effect -- if we are looking for a specific
+// filename, and it doesn't exist, attempt to create it
+//
+// Curious note: the obvious way to do this would be to re-define
+// topdir::lookup (it would save a lot of duplicate work), but the
+// lookup function is not virtual, so do_lookup would call
+// DirInode::lookup and not topdir::lookup. Having a non-virtual
+// lookup seems to defeat the purpose, somehow...
+//
+int
+topdir::do_lookup(const up_preamble &pre, upp_repl &rep,
+ const upp_lookup_s &arg, upp_lookup_r &ret)
+{
+ string name((char *)arg.name.elems, (int)arg.name.nelem);
+
+ // First check if we have already come across this site...
+ if ( !dir::lookup(name) )
+ {
+ // Not found. Attempt to create.
+
+ cout << name << " not found, attempting to connect to site.\n";
+
+ up_handle bogus; // We don't really need this information
+ create(name, bogus); // (at least not right now)
+
+ // We don't check the result of "create", since if it failed,
+ // dir::do_lookup will fail and handle all the paperwork for us.
+ }
+
+ return dir::do_lookup(pre,rep,arg,ret);
+}
+
+
Added: trunk/filesystems/ftpfs/topdir.h
==============================================================================
--- trunk/filesystems/ftpfs/topdir.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/ftpfs/topdir.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,34 @@
+// -*- C++ -*-
+
+// This is the top directory in the filesystem
+// Each entry in this directory is a hostname of a machine
+// for which either cached information exists or an open
+// connection exists.
+
+// (C) Copyright 1994 Jeremy Fitzhardinge <jeremy at sw.oz.au>
+// This code is distributed under the terms of the
+// GNU General Public Licence. See COPYING for more details.
+
+#ifndef _TOPDIR_H_
+#define _TOPDIR_H_
+
+#pragma interface
+
+#include "dir.h"
+#include <string>
+
+class topdir : public dir
+{
+ Inode *newinode(dir *, const struct stat *, const string &);
+
+ int do_create(const up_preamble &, upp_repl &,
+ const upp_create_s &, upp_create_r &);
+ int create(const string &, up_handle &);
+ int do_lookup(const up_preamble &, upp_repl &,
+ const upp_lookup_s &, upp_lookup_r &);
+
+public:
+ topdir(ftpfs &fs, const string &);
+};
+
+#endif /* _TOPDIR_H_ */
Added: trunk/filesystems/ftpfs/vms_host.h
==============================================================================
--- trunk/filesystems/ftpfs/vms_host.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/ftpfs/vms_host.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,23 @@
+// -*- C++ -*-
+
+// VMS host specific information. Not implemented
+
+// (C) Copyright 1994 Jeremy Fitzhardinge <jeremy at sw.oz.au>
+// This code is distributed under the terms of the
+// GNU General Public Licence. See COPYING for more details.
+
+/*
+ Pathname format: drive:[dir.dir.dir]file;ver
+ ^^^^^^ ^^^^ optional
+ Dir listing:
+ FTP_SERVER.LOG;1824 %RMS-E-PRV, insufficient privilege or file protection violation
+ KERMIT.DIR;1 1 16-JUL-1993 13:39 [1,1] (RWE,RWE,RE,RE)
+ MITCHELL.DIR;1 1 20-MAY-1994 08:32 [1,1] (RWE,RWE,RE,RE)
+ RISKS_V12.LIS;1 %RMS-E-PRV, insufficient privilege or file protection violation
+ MSKERMIT.INI_ALTPS;1
+ %RMS-E-PRV, insufficient privilege or file protection violation
+
+ Result from daytime service:
+ Tuesday, June 7, 1994 7:32:48PM-EDT
+
+ */
Added: trunk/filesystems/ftpfs/ftplink.cc
==============================================================================
--- trunk/filesystems/ftpfs/ftplink.cc 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/ftpfs/ftplink.cc 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,80 @@
+// -*- C++ -*-
+
+// (C) Copyright 1994 Jeremy Fitzhardinge <jeremy at sw.oz.au>
+// This code is distributed under the terms of the
+// GNU General Public Licence. See COPYING for more details.
+
+#pragma implementation
+
+#include "ftplink.h"
+#include "ftpfs.h"
+#include "pushd.h"
+#include "dir.h"
+
+#include <sys/stat.h>
+#include <time.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <stdio.h>
+#include <errno.h>
+#include <string>
+
+ftplink::ftplink(ftpfs &fs, string lnk, dir *d, string name)
+ : ino(fs), link(lnk), d(d), name(name)
+{
+ if (link[0] == '/')
+ {
+ int dp = d->depth();
+ string pre = "./";
+
+ if (dp > 0)
+ {
+ pre = "";
+ for ( ; dp>0; dp--)
+ pre += "../";
+ }
+
+ link = link.substr(1,link.length()-1);
+ link.insert(0, pre);
+ }
+
+ int fd = d->open();
+
+ if (fd != -1)
+ {
+ pushd here(fd);
+ symlink(link.data(), name.data());
+ }
+
+ ctime = mtime = time(0);
+ mode = S_IFLNK | 0777;
+ size = link.length();
+}
+
+void
+ftplink::decref()
+{
+ if (nlink-- > 0)
+ return;
+
+ int fd = d->open();
+
+ if (fd != -1)
+ {
+ pushd here(fd);
+ ::unlink(name.data());
+ }
+ delete this;
+}
+
+int
+ftplink::do_readlink(const up_preamble &, upp_repl &,
+ const upp_readlink_s &arg, upp_readlink_r &ret)
+{
+ ret.name.nelem = link.length();
+ link.copy((char *)ret.name.elems, ret.name.nelem, 0);
+/* ret.name.elems = (signed char *)link.chars(); */
+
+ return 0;
+}
Added: trunk/filesystems/ftpfs/ftplink.h
==============================================================================
--- trunk/filesystems/ftpfs/ftplink.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/ftpfs/ftplink.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,32 @@
+// -*- C++ -*-
+
+// (C) Copyright 1994 Jeremy Fitzhardinge <jeremy at sw.oz.au>
+// This code is distributed under the terms of the
+// GNU General Public Licence. See COPYING for more details.
+
+#ifndef _FTPLINK_H_
+#define _FTPLINK_H_
+
+#pragma interface
+
+#include <string>
+#include "ino.h"
+
+class ftpfs;
+
+class ftplink: public ino
+{
+ string link;
+ class dir *d;
+ string name;
+
+ int do_readlink(const up_preamble &, upp_repl &,
+ const upp_readlink_s &, upp_readlink_r &);
+ void decref();
+public:
+ ftplink(ftpfs &fs, string link, class dir *, string name);
+
+ const string &getlink() const { return link; }
+};
+
+#endif /* _FTPDIR_H_ */
Added: trunk/filesystems/ftpfs/nonblk_io.cc
==============================================================================
--- trunk/filesystems/ftpfs/nonblk_io.cc 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/ftpfs/nonblk_io.cc 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,369 @@
+// -*- C++ -*-
+
+// Non-blocking threaded IO
+// This sets the fd for the operation into nonblocking mode.
+// If the IO would have blocked, it's put onto the dispatch
+// list and another thread is scheduled. When the fd is ready
+// for IO, this thread is rescheduled and the IO is completed.
+
+// (C) Copyright 1994 Jeremy Fitzhardinge <jeremy at sw.oz.au>
+// This code is distributed under the terms of the
+// GNU General Public Licence. See COPYING for more details.
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <assert.h>
+
+#include <ThreadComm.h>
+#include <LWP.h>
+
+CommBase *selector = NULL;
+int do_nonblock = 0;
+
+class reio : public DispatchFD
+{
+ int dispatch(int, int);
+
+ Semaphore sem;
+
+ CommBase *comm;
+
+public:
+ reio();
+
+ void wait(int fd, int what);
+
+};
+
+reio::reio()
+ : sem(0), comm(selector)
+{
+ assert(selector != NULL);
+}
+
+void
+reio::wait(int fd, int what)
+{
+ comm->addDispatch(fd, this, what);
+ sem.wait();
+}
+
+int
+reio::dispatch(int, int)
+{
+ sem.signal();
+ return 0;
+}
+
+extern "C"
+ssize_t read(int fd, void *buf, size_t sz)
+{
+ int flags;
+ ssize_t ret;
+
+ if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
+ return -1;
+
+ again:
+ if (do_nonblock && fcntl(fd, F_SETFL, flags|O_NONBLOCK) == -1)
+ return -1;
+
+ if ((ret = __read(fd, buf, sz)) == -1)
+ {
+ int err = errno;
+
+ fcntl(fd, F_SETFL, flags);
+
+ if (err == EINTR)
+ goto again;
+
+ if (err == EAGAIN)
+ {
+ reio *rio = new reio();
+
+ rio->wait(fd, DISP_R);
+ goto again;
+ }
+ errno = err;
+ return ret;
+ }
+ fcntl(fd, F_SETFL, flags);
+
+ return ret;
+}
+
+extern "C"
+ssize_t write(int fd, const void *buf, size_t sz)
+{
+ int flags;
+ ssize_t ret;
+
+ if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
+ return -1;
+
+ again:
+ if (do_nonblock && fcntl(fd, F_SETFL, flags|O_NONBLOCK) == -1)
+ return -1;
+
+ if ((ret = __write(fd, buf, sz)) == -1)
+ {
+ int err = errno;
+
+ fcntl(fd, F_SETFL, flags);
+
+ if (err == EINTR)
+ goto again;
+
+ if (err == EAGAIN)
+ {
+ reio *rio = new reio();
+ rio->wait(fd, DISP_W);
+ goto again;
+ }
+ errno = err;
+ return ret;
+ }
+ fcntl(fd, F_SETFL, flags);
+
+ return ret;
+}
+
+#if 0
+extern "C"
+int select(int width, fd_set *read_fd, fd_set *write_fd, fd_set *except_fd,
+ struct timeval *timeout)
+{
+ int i;
+
+ for(i = 0; i < width; i++)
+ {
+ int what = 0;
+ if (FD_ISSET(i, read_fd))
+ what |= DISP_R;
+ if (FD_ISSET(i, write_fd))
+ what |= DISP_W;
+ if (FD_ISSET(i, execpt_fd))
+ what |= DISP_E;
+ if (what != 0)
+ {
+ }
+ }
+}
+#endif
+
+#include "netsys.h"
+
+extern "C"
+int send(int fd, const void *buf, int len, unsigned sndfl)
+{
+ int flags;
+ int ret;
+
+ if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
+ return -1;
+
+ again:
+ if (do_nonblock && fcntl(fd, F_SETFL, flags|O_NONBLOCK) == -1)
+ return -1;
+
+ if ((ret = __send(fd, buf, len, sndfl)) == -1)
+ {
+ int err = errno;
+ fcntl(fd, F_SETFL, flags);
+
+ if (err == EAGAIN)
+ {
+ reio *rio = new reio();
+
+ rio->wait(fd, DISP_W);
+ goto again;
+ }
+ errno = err;
+ return ret;
+ }
+ fcntl(fd, F_SETFL, flags);
+
+ return ret;
+}
+
+extern "C"
+int sendto(int fd, const void *buf, int len, unsigned sndfl,
+ const struct sockaddr *to, int tolen)
+{
+ int flags;
+ int ret;
+
+ if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
+ return -1;
+
+ again:
+ if (do_nonblock && fcntl(fd, F_SETFL, flags|O_NONBLOCK) == -1)
+ return -1;
+
+ if ((ret = __sendto(fd, buf, len, sndfl, to, tolen)) == -1)
+ {
+ int err = errno;
+
+ fcntl(fd, F_SETFL, flags);
+
+ if (err == EAGAIN)
+ {
+ reio *rio = new reio();
+
+ rio->wait(fd, DISP_W);
+ goto again;
+ }
+ errno = err;
+ return ret;
+ }
+ fcntl(fd, F_SETFL, flags);
+
+ return ret;
+}
+
+extern "C"
+int recv(int fd, void *buf, int len, unsigned rcvfl)
+{
+ int flags;
+ ssize_t ret;
+
+ if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
+ return -1;
+
+ again:
+ if (do_nonblock && fcntl(fd, F_SETFL, flags|O_NONBLOCK) == -1)
+ return -1;
+
+ if ((ret = __recv(fd, buf, len, rcvfl)) == -1)
+ {
+ int err = errno;
+
+ fcntl(fd, F_SETFL, flags);
+
+ if (err == EAGAIN)
+ {
+ reio *rio = new reio();
+
+ rio->wait(fd, DISP_R);
+ goto again;
+ }
+ errno = err;
+ return ret;
+ }
+ fcntl(fd, F_SETFL, flags);
+ return ret;
+}
+
+extern "C"
+int recvfrom(int fd, void *buf, int len, unsigned rcvfl,
+ struct sockaddr *from, int *fromlen)
+{
+ int flags;
+ ssize_t ret;
+
+ if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
+ return -1;
+
+ again:
+ if (do_nonblock && fcntl(fd, F_SETFL, flags|O_NONBLOCK) == -1)
+ return -1;
+
+ if ((ret = __recvfrom(fd, buf, len, rcvfl, from, fromlen)) == -1)
+ {
+ int err = errno;
+
+ fcntl(fd, F_SETFL, flags);
+
+ if (err == EAGAIN)
+ {
+ reio *rio = new reio();
+
+ rio->wait(fd, DISP_R);
+ goto again;
+ }
+ errno = err;
+ return ret;
+ }
+ fcntl(fd, F_SETFL, flags);
+
+ return ret;
+}
+
+extern "C"
+int connect(int fd, struct sockaddr *addr, int addrlen)
+{
+ int flags;
+ ssize_t ret;
+
+ if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
+ return -1;
+
+ again:
+ if (do_nonblock && fcntl(fd, F_SETFL, flags|O_NONBLOCK) == -1)
+ return -1;
+
+ if ((ret = __connect(fd, addr, addrlen)) == -1)
+ {
+ int err = errno;
+
+ fcntl(fd, F_SETFL, flags);
+
+#if 0
+ // Hack around Linux kernel bug
+ // If we get EALREADY back, it means we have connected,
+ // are in the process of disconnecting again. There is
+ // received data ready for us to read
+ if (err == EALREADY)
+ return 0;
+#endif
+ if (err == EALREADY || err == EINPROGRESS)
+ {
+ reio *rio = new reio();
+
+ rio->wait(fd, DISP_R);
+ goto again;
+ }
+ errno = err;
+ return ret;
+ }
+ fcntl(fd, F_SETFL, flags);
+
+ return ret;
+}
+
+extern "C"
+int accept(int fd, struct sockaddr *addr, int *addrlen)
+{
+ int flags;
+ ssize_t ret;
+
+ if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
+ return -1;
+
+ again:
+ if (do_nonblock && fcntl(fd, F_SETFL, flags|O_NONBLOCK) == -1)
+ return -1;
+
+ if ((ret = __accept(fd, addr, addrlen)) == -1)
+ {
+ int err = errno;
+
+ fcntl(fd, F_SETFL, flags);
+
+ if (err == EAGAIN)
+ {
+ reio *rio = new reio();
+
+ rio->wait(fd, DISP_R);
+ goto again;
+ }
+ errno = err;
+ return ret;
+ }
+
+ fcntl(fd, F_SETFL, flags);
+ return ret;
+}
Added: trunk/filesystems/ftpfs/reap.pl
==============================================================================
--- trunk/filesystems/ftpfs/reap.pl 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/ftpfs/reap.pl 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,60 @@
+#!/usr/bin/perl --
+#
+# Cache reaper. This script keeps the cache size at or below
+# a set point, keeping files most reciently used.
+#
+# (C) Copyright 1994 Jeremy Fitzhardinge <jeremy at sw.oz.au>
+# This code is distributed under the terms of the
+# GNU General Public Licence. See COPYING for more details.
+
+eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
+ if $running_under_some_shell;
+
+$#ARGV == 1 || die("Usage: $0 cache-dir max-size\n");
+
+require "find.pl";
+
+# Traverse desired filesystems
+
+&find($ARGV[0]);
+
+$ARGV[1] =~ tr/KMG/kmg/;
+$ARGV[1] =~ /^([0-9]+)([kmg]?)$/;
+
+$scale{"k"} = 1024;
+$scale{"m"} = 1024*1024;
+$scale{"g"} = 1024*1024*1024;
+
+die("$0: $ARGV[1]: Bad scale factor\n")
+ if (!defined($1) || ($2 != "" && !defined($scale{$2})));
+
+$max = $1*$scale{$2};
+$total = 0;
+$delsz = 0;
+$delfiles = 0;
+
+foreach $key (reverse sort keys %sizes) {
+ $sz = $sizes{$key};
+ $total += $sz;
+
+ if ($total > $max) {
+ ($atime, $name) = split(" ", $key, 2);
+ unlink($name);
+ $delsz += $sz;
+ $delfiles++;
+ }
+}
+
+print "$delsz bytes in $delfiles deleted\n";
+
+exit;
+
+sub wanted {
+ if ((($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$sizemm,$atime) = lstat($_)) &&
+ -f _ && $_ !~ /\.ftpfs_.*/)
+ {
+ $key = "$atime $name";
+ $sizes{$key} = $sizemm;
+ }
+}
+
Added: trunk/filesystems/ftpfs/dir.cc
==============================================================================
--- trunk/filesystems/ftpfs/dir.cc 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/ftpfs/dir.cc 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,113 @@
+// -*- C++ -*-
+
+// Base directory class
+
+// (C) Copyright 1994 Jeremy Fitzhardinge <jeremy at sw.oz.au>
+// This code is distributed under the terms of the
+// GNU General Public Licence. See COPYING for more details.
+
+#pragma implementation
+
+#include "dir.h"
+#include "ftpfs.h"
+#include "ftpdir.h"
+#include "ftplink.h"
+#include "ftpconn.h"
+#include "pushd.h"
+
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <string>
+
+dir::dir(ftpfs &fs, const string &name, dir *up)
+ :DirInode(fs, fs.genhand(), up), sem(1),
+ name(name, up ? &up->name : (Path *)NULL), filesys(fs), parent(up)
+{
+ mode = S_IFDIR | 0555;
+ atime = ctime = mtime = time(0);
+ uid = fs.uid;
+ gid = fs.gid;
+}
+
+void
+dir::init()
+{
+ int dfd = open();
+
+ if (dfd == -1)
+ return;
+
+ pushd here(dfd);
+
+ DIR *dir;
+ if ((dir = opendir(".")) == NULL)
+ {
+ perror("topdir::topdir opendir of cache failed");
+ return;
+ }
+
+ struct dirent *de;
+
+ while((de = readdir(dir)) != NULL)
+ {
+ struct stat st;
+
+ if (lstat(de->d_name, &st) == -1)
+ {
+ fprintf(stderr, "stat of %s failed: %s\n",
+ de->d_name, strerror(errno));
+ continue;
+ }
+
+ Inode *ino;
+ string name(de->d_name);
+
+ if ((ino = newinode(this, &st, name)) == NULL)
+ continue;
+
+ link(name, ino);
+ }
+ closedir(dir);
+}
+
+int
+dir::open()
+{
+ string p = path();
+
+ int ret = ::open(p.data(), O_RDONLY);
+
+ if (ret == -1)
+ {
+ int err = errno;
+ fprintf(stderr, "open of %s failed: %s\n",
+ (const char *)p.data(), strerror(errno));
+ errno = err;
+ }
+ return ret;
+}
+
+int
+dir::do_iput(const up_preamble &, upp_repl &, const upp_iput_s &)
+{
+ if (nlink == 0)
+ delete this;
+ return 0;
+}
+
+void
+dir::beforeop(up_ops)
+{
+ sem.wait();
+}
+
+void
+dir::afterop(up_ops)
+{
+ sem.signal();
+}
Added: trunk/filesystems/ftpfs/getdate.h
==============================================================================
--- trunk/filesystems/ftpfs/getdate.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/ftpfs/getdate.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,39 @@
+/* -*- C -*- */
+
+#ifndef _GETDATE_H_
+#define _GETDATE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <time.h>
+#include <sys/timeb.h>
+
+/*
+** Daylight-savings mode: on, off, or not yet known.
+*/
+typedef enum _DSTMODE {
+ DSTon, DSToff, DSTmaybe
+} DSTMODE;
+
+/*
+** Meridian: am, pm, or 24-hour style.
+*/
+typedef enum _MERIDIAN {
+ MERam, MERpm, MER24
+} MERIDIAN;
+
+
+time_t get_date(char *p, struct timeb *now);
+time_t
+Convert(time_t Month, time_t Day, time_t Year,
+ time_t Hours, time_t Minutes, time_t Seconds,
+ MERIDIAN Meridian, DSTMODE DSTmode,
+ time_t timezone);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GETDATE_H_ */
Added: trunk/filesystems/ftpfs/ftpfs.cc
==============================================================================
--- trunk/filesystems/ftpfs/ftpfs.cc 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/ftpfs/ftpfs.cc 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,118 @@
+// -*- C++ -*-
+
+// FTP filesystem
+
+// (C) Copyright 1994 Jeremy Fitzhardinge <jeremy at sw.oz.au>
+// This code is distributed under the terms of the
+// GNU General Public Licence. See COPYING for more details.
+
+#pragma implementation
+
+#include <getopt.h>
+#include <stdio.h>
+
+#include <ThreadComm.h>
+#include "ftpfs.h"
+#include "topdir.h"
+
+#include <sys/param.h>
+#include <unistd.h>
+
+ftpfs::ftpfs(const char *mpoint, const string &cache)
+ : cache(cache), Filesystem(mpoint), uid(0), gid(0)
+{
+ hcount = 0;
+ root = new topdir(*this, cache);
+}
+
+int
+ftpfs::do_mount(const up_preamble &, upp_repl &,
+ upp_mount_r &ret)
+{
+ ret.root.handle = root->gethandle();
+ return 0;
+}
+
+ftpfs::~ftpfs()
+{
+}
+
+int
+ftpfs::Enquire(up_ops op)
+{
+ switch(op)
+ {
+ case up_mount:
+ case up_iread:
+ case up_multireaddir:
+ case up_lookup:
+ case up_notify_change:
+ case up_readlink:
+ case up_create:
+ case up_read:
+ case up_iput:
+ return 0;
+ default:
+ break;
+ }
+
+ return Filesystem::Enquire(op);
+}
+
+// Globals for controlling nonblocking IO (nonblk_io.cc)
+extern CommBase *selector;
+extern int do_nonblock;
+
+// Parse the arguments from muserfs and construct the filesystem
+// and communications.
+int
+main(int argc, char **argv)
+{
+ int optch, err = 0;
+ int infd, outfd;
+ const char *mpoint = "";
+
+ extern char *optarg;
+ extern int optind, opterr, optopt;
+
+
+ infd = outfd = -1;
+ while((optch = getopt(argc, argv, "i:o:m:c:")) != EOF)
+ switch(optch)
+ {
+ case 'i':
+ infd = atoi(optarg);
+ break;
+ case 'o':
+ outfd = atoi(optarg);
+ break;
+ case 'm':
+ mpoint = optarg;
+ break;
+ default:
+ err++;
+ }
+
+ if (err || infd == -1 || outfd == -1 || optind == argc)
+ {
+ cerr << "Usage: " << argv[0] << " -i infd -o outfd -m mpoint cachedir\n";
+ exit(1);
+ }
+
+ char path[MAXPATHLEN];
+ char *full = realpath(argv[optind], path);
+ string cache(full ? full : argv[optind]);
+
+#if 0 && DEBUG
+ printf("pid=%d, return to cont\n", getpid());
+ getchar();
+#endif
+ ftpfs ftp(mpoint, cache);
+ ThreadComm comm(ftp, outfd, infd, 32*1024, COM_TPRI, OPS_TPRI);
+ selector = &comm;
+ do_nonblock = 1;
+ if (comm.Run() == -1)
+ cerr << argv[0] << ": Comm.Run() failed!\n";
+ do_nonblock = 0;
+ return 0;
+}
Added: trunk/filesystems/ftpfs/dos_host.cc
==============================================================================
--- trunk/filesystems/ftpfs/dos_host.cc 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/ftpfs/dos_host.cc 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,170 @@
+// -*- C++ -*-
+
+// (C) Copyright 1994 Jeremy Fitzhardinge <jeremy at sw.oz.au>
+// This code is distributed under the terms of the
+// GNU General Public Licence. See COPYING for more details.
+
+// Dos ftp server support by marcus at ee.pdx.edu (Marcus Daniels)
+
+#pragma implementation
+
+#include "dos_host.h"
+#include "serv_port.h"
+#include "ftpconn.h"
+#include "getdate.h"
+#include <io.h>
+
+#include <unistd.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <string>
+#include <stdio.h>
+#include <netinet/in.h>
+#include <stdlib.h>
+
+int
+dos_host::pathsteps(const string &path, string *ret[])
+{
+ static const Regex deldot("\\(^\\./\\)\\|\\(/\\.\\/\\)\\|\\(/\\.$\\)\\|\\(//\\)\\|\\(^\\.$\\)");
+ static const Regex deldotdot("\\(^|/\\)[^/]+/\\.\\./");
+
+ *ret = new string[1];
+ (*ret)[0] = path;
+ (*ret)[0].gsub(deldot, "");
+ (*ret)[0].gsub(deldotdot, "/");
+
+ if ((*ret)[0] == "")
+ return 0;
+
+ return 1;
+}
+
+// Get local time at remote machine with the "time" service
+time_t
+dos_host::localtime(struct sockaddr_in addr)
+{
+ return time(0);
+}
+
+#define EPOCH 1970
+#define HOUR(x) ((time_t)(x) * 60)
+#define SECSPERDAY (24L * 60L * 60L)
+
+// Parse a date from "dir"
+static time_t
+parsedate(const string &date, time_t timezone)
+{
+ string parts[2];
+ static const Regex rx_date_time_delim(" +");
+ string date_parts[3];
+ static const Regex rx_date_delim("-");
+
+ if (split(date, parts, 2, rx_date_time_delim) != 2)
+ return -1;
+ if (split(parts[0], date_parts, 3, rx_date_delim) != 3)
+ return -1;
+
+ static const Regex rx_time("[012]?[0-9]:[0-5][0-9]");
+ static const Regex rx_year("[0-9][0-9]");
+ static const Regex rx_month("[0-1][0-9]");
+ static const Regex rx_day("[0-9][0-9]");
+
+ int month = -1;
+ int day = -1;
+ int year = -1;
+ int hours = -1;
+ int mins = -1;
+
+ if (!date_parts[0].matches(rx_month))
+ return 0;
+ month = atoi(date_parts[0]);
+ if (!date_parts[1].matches(rx_day))
+ return 0;
+ day = atoi(date_parts[1]);
+ if (!date_parts[2].matches(rx_year))
+ return 0;
+ year = atoi(date_parts[2]);
+
+ {
+ string hm[2];
+ if (!parts[1].matches(rx_time))
+ return 0;
+ if (split(parts[1], hm, 2, string(":")) != 2)
+ return 0;
+ hours = atoi(hm[0]);
+ mins = atoi(hm[1]);
+ }
+ return Convert(month, day,
+ year,hours,mins,0,MER24,DSToff,timezone);
+}
+
+struct ftp_filelist *
+dos_host::parse_filelist(const string &ro_line, time_t timezone)
+{
+ string line = ro_line;
+
+ // Match a line of "dir" output
+ static const Regex dir_line_1("^\\([^ /]+\\) *\\([<DIR>0-9]+\\) \\([0-1][0-9]-[0-3][0-9]-[0-9][0-9] [012][0-9]:[0-5][0-9]\\).*");
+ static const Regex dir_line_2("^.*/\\([^ /]+\\) *\\([<DIR>0-9]+\\) \\([0-1][0-9]-[0-3][0-9]-[0-9][0-9] [012][0-9]:[0-5][0-9]\\).*");
+
+ const Regex *dir_rx = &dir_line_1;
+
+ if (!line.matches(dir_line_1))
+ {
+ if (!line.matches(dir_line_2))
+ {
+ cout << "Failed to match dir line [" << line << "]\n";
+ return NULL;
+ }
+ dir_rx=&dir_line_2;
+ }
+
+ int start, len;
+
+ ftp_filelist *nf = new ftp_filelist;
+ dir_rx->match_info(start, len, 1);
+ nf->name = string(line.at(start,len));
+
+ dir_rx->match_info(start, len, 2);
+
+ string sz_str(line.at(start, len));
+ nf->size = strtol(sz_str, NULL, 10);
+ switch(sz_str[0])
+ {
+ case '<':
+ nf->type = FT_Directory;
+ break;
+ default:
+ nf->type = FT_File;
+ break;
+ }
+
+ dir_rx->match_info(start, len, 3);
+ string date_str(line.at(start, len));
+ cout << "Date_str:[" << date_str << "]\n";
+ nf->time = parsedate(date_str, timezone);
+ nf->next = NULL;
+
+ struct tm *tm = gmtime(&nf->time);
+ cout << "Name " << nf->name << " size " << nf->size <<
+ " date " << asctime(tm);
+
+ return nf;
+}
+
+const string &
+dos_host::hosttype() const
+{
+ static const string dos("dos");
+
+ return dos;
+}
+
+const string &
+dos_host::wildcard() const
+{
+ static const string wild("/*");
+
+ return wild;
+}
Added: trunk/filesystems/ftpfs/unix_host.h
==============================================================================
--- trunk/filesystems/ftpfs/unix_host.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/ftpfs/unix_host.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,27 @@
+// -*- C++ -*-
+
+// Unix host information
+
+// (C) Copyright 1994 Jeremy Fitzhardinge <jeremy at sw.oz.au>
+// This code is distributed under the terms of the
+// GNU General Public Licence. See COPYING for more details.
+
+#ifndef _UNIX_HOST_H_
+#define _UNIX_HOST_H_
+
+#pragma interface
+
+#include "host.h"
+#include <sys/socket.h>
+#include <string>
+#include <netinet/in.h>
+
+class unix_host: public host
+{
+ int pathsteps(const string &, string *steps[]);
+ time_t localtime(struct sockaddr_in);
+ struct ftp_filelist *parse_filelist(const string &, time_t);
+ const string &hosttype() const;
+};
+
+#endif /* _UNIX_HOST_H_ */
Added: trunk/filesystems/ftpfs/pushd.cc
==============================================================================
--- trunk/filesystems/ftpfs/pushd.cc 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/ftpfs/pushd.cc 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,37 @@
+// -*- C++ -*-
+
+// PushD/PopD operations
+
+// (C) Copyright 1994 Jeremy Fitzhardinge <jeremy at sw.oz.au>
+// This code is distributed under the terms of the
+// GNU General Public Licence. See COPYING for more details.
+
+#include "pushd.h"
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+
+pushd::pushd(int dir)
+ :dir(dir)
+{
+ int fd = open(".", O_RDONLY);
+
+ if (fd == -1 || fchdir(dir) == -1)
+ {
+ perror("pushd::pushd() open or fchdir failed");
+ return;
+ }
+
+ old = fd;
+}
+
+pushd::~pushd()
+{
+ fchdir(old);
+ close(old);
+ close(dir);
+}
+
+
Added: trunk/filesystems/ftpfs/serv_port.cc
==============================================================================
--- trunk/filesystems/ftpfs/serv_port.cc 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/ftpfs/serv_port.cc 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,24 @@
+// -*- C++ -*-
+
+// Service port things
+
+#pragma implementation
+
+#include "serv_port.h"
+
+#include <netdb.h>
+#include <stdio.h>
+
+serv_port::serv_port(const char *srv, const char *trans)
+{
+ struct servent *se = getservbyname(srv, trans);
+
+ if (se == NULL)
+ {
+ fprintf(stderr, "Can't find service %s/%s\n",
+ srv, trans);
+ return;
+ }
+
+ port = se->s_port;
+}
Added: trunk/filesystems/ftpfs/serv_port.h
==============================================================================
--- trunk/filesystems/ftpfs/serv_port.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/ftpfs/serv_port.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,17 @@
+// -*- C++ -*-
+
+// Little utility struct for getting service ports
+
+#ifndef _SERV_PORT_H_
+#define _SERV_PORT_H_
+
+#pragma interface
+
+struct serv_port
+{
+ int port;
+
+ serv_port(const char *, const char *);
+};
+
+#endif /* _SERV_PORT_H_ */
Added: trunk/filesystems/ftpfs/ino.cc
==============================================================================
--- trunk/filesystems/ftpfs/ino.cc 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/ftpfs/ino.cc 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,47 @@
+// -*- C++ -*-
+
+// Base inode class (apart from directories)
+
+// (C) Copyright 1994 Jeremy Fitzhardinge <jeremy at sw.oz.au>
+// This code is distributed under the terms of the
+// GNU General Public Licence. See COPYING for more details.
+
+#pragma implementation
+
+#include "ftpfs.h"
+#include "ino.h"
+
+ino::ino(ftpfs &fs)
+ :SimpleInode(fs, fs.genhand()), sem(1)
+{
+ uid = fs.uid;
+ gid = fs.gid;
+}
+
+void
+ino::beforeop(up_ops)
+{
+ sem.wait();
+}
+
+void
+ino::afterop(up_ops)
+{
+ sem.signal();
+}
+
+int
+ino::do_iput(const up_preamble &, upp_repl &, const upp_iput_s &)
+{
+ if (nlink == 0)
+ delete this;
+ return 0;
+}
+
+void
+ino::decref()
+{
+ nlink--;
+ if (nlink == 0)
+ delete this;
+}
Added: trunk/filesystems/ftpfs/pushd.h
==============================================================================
--- trunk/filesystems/ftpfs/pushd.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/ftpfs/pushd.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,20 @@
+// -*- C++ -*-
+
+// (C) Copyright 1994 Jeremy Fitzhardinge <jeremy at sw.oz.au>
+// This code is distributed under the terms of the
+// GNU General Public Licence. See COPYING for more details.
+
+#ifndef _PUSHD_H_
+#define _PUSHD_H_
+
+class pushd
+{
+ int old;
+ int dir;
+
+public:
+ pushd(int fd);
+ ~pushd();
+};
+
+#endif /* _PUSHD_H_ */
Added: trunk/filesystems/ftpfs/ino.h
==============================================================================
--- trunk/filesystems/ftpfs/ino.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/ftpfs/ino.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,34 @@
+// -*- C++ -*-
+
+// Base non-dir inode
+// This just exists to serialize thread access to an inode
+
+// (C) Copyright 1994 Jeremy Fitzhardinge <jeremy at sw.oz.au>
+// This code is distributed under the terms of the
+// GNU General Public Licence. See COPYING for more details.
+
+#ifndef _INO_H_
+#define _INO_H_
+
+#pragma interface
+
+#include <SimpleInode.h>
+#include <LWP.h>
+
+class ftpfs;
+
+class ino : public SimpleInode
+{
+ Semaphore sem;
+
+ void beforeop(up_ops);
+ void afterop(up_ops);
+
+ int do_iput(const up_preamble &, upp_repl &, const upp_iput_s &);
+
+ void decref();
+public:
+ ino(ftpfs &);
+};
+
+#endif /* _INO_H_ */
Added: trunk/filesystems/ftpfs/netsys.h
==============================================================================
--- trunk/filesystems/ftpfs/netsys.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/ftpfs/netsys.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,29 @@
+/* -*- C -*- */
+
+/* Hooks to get in before the library functions */
+/*
+ * (C) Copyright 1994 Jeremy Fitzhardinge <jeremy at sw.oz.au>
+ * This code is distributed under the terms of the
+ * GNU General Public Licence. See COPYING for more details.
+ */
+
+#ifndef _NETSYS_H_
+#define _NETSYS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+int __recv(int fd, void *buf, int len, unsigned flags);
+int __recvfrom(int fd, void *buf, int len, unsigned flags,
+ struct sockaddr *from, int *fromlen);
+int __send(int fd, const void *buf, int len, unsigned flags);
+int __sendto(int sockfd, const void *buffer, int len, unsigned flags,
+ const struct sockaddr *to, int tolen);
+int __connect(int sockfd, struct sockaddr *saddr, int addrlen);
+int __accept(int sockfd, struct sockaddr *peer, int *paddrlen);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _NETSYS_H_ */
Added: trunk/filesystems/ftpfs/sitetopdir.h
==============================================================================
--- trunk/filesystems/ftpfs/sitetopdir.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/ftpfs/sitetopdir.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,21 @@
+// -*- C++ -*-
+
+// (C) Copyright 1994 Jeremy Fitzhardinge <jeremy at sw.oz.au>
+// This code is distributed under the terms of the
+// GNU General Public Licence. See COPYING for more details.
+
+#ifndef _SITETOPDIR_H_
+#define _SITETOPDIR_H_
+
+#pragma interface
+
+#include "ftpdir.h"
+
+class sitetopdir: public ftpdir
+{
+ int depth() const { return 0; }
+public:
+ sitetopdir(ftpfs &fs, string name, dir *up);
+};
+
+#endif /* _SITETOPDIR_H_ */
Added: trunk/filesystems/ftpfs/ftpdir.cc
==============================================================================
--- trunk/filesystems/ftpfs/ftpdir.cc 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/ftpfs/ftpdir.cc 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,435 @@
+// -*- C++ -*-
+
+// Directories cached from an ftp site
+
+// (C) Copyright 1994 Jeremy Fitzhardinge <jeremy at sw.oz.au>
+// This code is distributed under the terms of the
+// GNU General Public Licence. See COPYING for more details.
+
+#pragma implementation
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <errno.h>
+
+#include <string>
+#include <iostream.h>
+#include <fstream.h>
+
+#include "ftpdir.h"
+#include "ftpconn.h"
+#include "ftplink.h"
+#include "ftpfile.h"
+#include "pushd.h"
+#include "ConfFile.h"
+#include <regex.h>
+
+static regex_t ignore_pat;
+static regmatch_t matches[2];
+
+
+ftpdir::ftpdir(ftpfs &fs, const string &elem, dir *up,
+ ftpdir *ftpup, const string &cfname)
+ : dir(fs, elem, up), ftpup(ftpup)
+{
+ conn = new ftpconn(Path(cfname, &name), elem);
+ construct();
+}
+
+ftpdir::ftpdir(ftpfs &fs, const string &name, dir *up,
+ ftpdir *ftpup, ftpconn *conn)
+ : dir(fs, name, up), ftpup(ftpup), conn(conn)
+{
+ construct();
+}
+
+void
+ftpdir::construct()
+{
+
+ regcomp(&ignore_pat, "^\\.ftpfs_.*$", 0);
+
+
+ int fd = parent->open();
+
+ conf = NULL;
+
+ if (fd != -1)
+ {
+ pushd here(fd);
+ string dir=name.path();
+ mkdir(dir.data(), mode|0700);
+ conf = new ConfFile(Path(".ftpfs_dir", &name));
+ }
+ else
+ cout << "name=" << name.elem() <<
+ " failed to open parent " <<
+ parent->getname().path() << "\n";
+
+ mode |= 0777;
+
+ getparams();
+ init_done = 0;
+ conn->incref();
+}
+
+void
+ftpdir::init()
+{
+ dir::init();
+
+ int dfd = open();
+ pushd here(dfd);
+
+ ifstream dinfo(".ftpfs_dirinfo");
+
+ if (!dinfo.bad())
+ {
+ mode_t mode;
+ size_t size;
+ time_t time;
+ string name;
+ string symlink;
+
+ for(;;)
+ {
+ dinfo >> mode;
+ dinfo >> size;
+ dinfo >> time;
+ dinfo >> name;
+ if (S_ISLNK(mode))
+ dinfo >> symlink;
+
+ if (dinfo.eof() || dinfo.fail())
+ break;
+
+ if (lookup(name) != NULL)
+ continue;
+
+ Inode *ino = NULL;
+
+ if (S_ISREG(mode))
+ {
+ ftpfile *f = new ftpfile(filesys, name,
+ this, conn);
+ f->setstats(size, time);
+ ino = f;
+ }
+ else if (S_ISDIR(mode))
+ {
+ ftpdir *d = new ftpdir(filesys, name, this,
+ this, conn);
+ d->mtime = time;
+ ino = d;
+ }
+ else if (S_ISLNK(mode))
+ ino = new ftplink(filesys, symlink, this, name);
+
+ if (ino == NULL)
+ continue;
+ link(name, ino);
+ }
+ }
+}
+
+void
+ftpdir::cleanup()
+{
+ int fd = open();
+ pushd here(fd);
+
+
+ ::unlink(".ftpfs_dirinfo");
+ ofstream dinfo(".ftpfs_dirinfo", ios::out|ios::trunc, 0444);
+
+ if (!dinfo.bad())
+ {
+ DirEntry *de=NULL;
+
+ for(de = scan(de); de != NULL; scan(de))
+ {
+ string name = de->getname();
+
+ if (name == "." || name == ".." ||
+ regexec(&ignore_pat, name.data(), 2, matches, 0)==REG_NOMATCH)
+ continue;
+
+ up_inode ino;
+
+ ((SimpleInode *)de->geti())->iread(ino); // XXX
+
+ dinfo << oct << ' ' << ino.mode << ' '
+ << dec << ' ' << ino.size << ' '
+ << ino.mtime << ' ' << name;
+ if (S_ISLNK(ino.mode))
+ dinfo << ' ' <<
+ ((ftplink *)de->geti())->getlink(); // XXX
+ dinfo << '\n';
+ }
+ }
+}
+
+ftpdir::~ftpdir()
+{
+ regfree(&ignore_pat);
+ setparams();
+ conn->decref();
+ if (conf)
+ delete conf;
+}
+
+void
+ftpdir::getparams()
+{
+ if (conf == NULL)
+ return;
+
+ if (!conf->getnum("last_update", last_upd))
+ last_upd = 0;
+ if (!conf->getnum("last_failure", last_failure))
+ last_failure = 0;
+}
+
+void
+ftpdir::setparams()
+{
+ if (conf == NULL)
+ return;
+ conf->setnum("last_update", last_upd);
+ conf->setnum("last_failure", last_failure);
+}
+
+Inode *
+ftpdir::newinode(dir *d, const struct stat *st, const string &name)
+{
+ Inode *ino = NULL;
+
+ if (S_ISDIR(st->st_mode))
+ {
+ if (name == "." || name == "..")
+ return NULL;
+ ino = new ftpdir(filesys, name, this, this, conn);
+ }
+ else if (S_ISLNK(st->st_mode))
+ {
+ char buf[1024];
+ int len = readlink(name.data(), buf, sizeof(buf));
+ if (len == -1)
+ return NULL;
+
+ ino = new ftplink(filesys, string(buf, len), this, name);
+ }
+ else if (S_ISREG(st->st_mode) &&
+ regexec(&ignore_pat, name.data(), 2, matches, 0)==REG_NOMATCH)
+ ino = new ftpfile(filesys, name, this, conn);
+
+ return ino;
+}
+
+int
+ftpdir::updatedir(int force)
+{
+ time_t now = time(0);
+ if (!init_done)
+ {
+ init_done = 1;
+ init();
+ }
+
+ if (!force)
+ {
+ if (last_upd > (now - conn->get_upd_timeout()))
+ return 0;
+ if ((last_failure > last_upd) &&
+ last_failure > (now - conn->get_fail_timeout()))
+ return 0;
+ }
+ string p = ftppath();
+
+ cout << "Updating directory at path \"" << p << "\"\n";
+
+ ftp_filelist *fl, *flist;
+
+ fl = flist = conn->getfilelist(p);
+
+ if (fl == NULL)
+ {
+ last_failure = now;
+ return ENOENT;
+ }
+
+ // Check to see if a file has changed type
+ for(; fl != NULL; fl = fl->next)
+ {
+ DirEntry *de;
+
+ if ((de = lookup(fl->name)) != NULL)
+ {
+ int bad = 0;
+ up_inode i;
+
+ ((SimpleInode *)de->geti())->iread(i); // XXX
+
+ switch(fl->type)
+ {
+ case FT_Directory:
+ if (!S_ISDIR(i.mode))
+ bad = 1;
+ break;
+ case FT_File:
+ if (!S_ISREG(i.mode))
+ bad = 1;
+ else
+ ((ftpfile *)de->geti())->setstats(fl->size, fl->time); // XXX
+ break;
+ case FT_Link:
+ if (!S_ISLNK(i.mode))
+ bad = 1;
+ break;
+ default:
+ break;
+ }
+
+ if (!bad)
+ continue;
+ unlink(fl->name);
+ }
+
+ Inode *ino = NULL;
+
+ switch(fl->type)
+ {
+ case FT_Directory:
+ ino = new ftpdir(filesys, fl->name, this, this, conn);
+ break;
+ case FT_File:
+ {
+ ftpfile *file = new ftpfile(filesys, fl->name, this, conn);
+ file->setstats(fl->size, fl->time);
+ ino = file;
+ break;
+ }
+ case FT_Link:
+ ino = new ftplink(filesys, fl->link, this, fl->name);
+ break;
+ default:
+ break;
+ }
+
+ if (ino != NULL && link(fl->name, ino))
+ delete ino;
+ }
+
+ DirEntry *de=NULL;
+ pushd here(open());
+
+ for(de = scan(de); de != NULL; scan(de))
+ {
+ string name = de->getname();
+
+ if (name == "." || name == ".." ||
+ regexec(&ignore_pat, name.data(), 2, matches, 0)==REG_NOMATCH)
+ continue;
+
+ int match = 0;
+ for(fl = flist; fl != NULL; fl = fl->next)
+ if (fl->name == name)
+ {
+ match = 1;
+ break;
+ }
+ if (!match)
+ {
+ unlink(name);
+ ::unlink(name.data());
+ }
+ }
+
+ for(; flist != NULL; flist = fl)
+ {
+ fl = flist->next;
+ delete flist;
+ }
+
+ last_upd = now;
+ return 0;
+}
+
+int
+ftpdir::do_readdir(const up_preamble &pre, upp_repl &rep,
+ const upp_readdir_s &arg, upp_readdir_r &ret)
+{
+ updatedir();
+
+ return dir::do_readdir(pre, rep, arg, ret);
+}
+
+int
+ftpdir::do_multireaddir(const up_preamble &pre, upp_repl &rep,
+ const upp_multireaddir_s &arg, upp_multireaddir_r &ret)
+{
+ updatedir();
+
+ return dir::do_multireaddir(pre, rep, arg, ret);
+}
+
+int
+ftpdir::do_lookup(const up_preamble &pre, upp_repl &rep,
+ const upp_lookup_s &arg, upp_lookup_r &ret)
+{
+ string name((char *)arg.name.elems, (int)arg.name.nelem);
+ if (name == ".ftpfs_update")
+ {
+ updatedir(1);
+ return ENOENT;
+ }
+
+ int r = dir::do_lookup(pre, rep, arg, ret);
+
+ if (r == ENOENT)
+ {
+ updatedir();
+ r = dir::do_lookup(pre, rep, arg, ret);
+ }
+
+ return r;
+}
+
+int
+ftpdir::do_create(const up_preamble &, upp_repl &,
+ const upp_create_s &arg, upp_create_r &ret)
+{
+ if (!S_ISDIR(arg.mode))
+ return EPERM;
+
+ string name((char *)arg.name.elems, (int)arg.name.nelem);
+ string fullname(ftppath());
+ fullname += "/";
+ fullname += name;
+
+ if (conn->makedir(fullname))
+ return EPERM;
+
+ Inode *ino = new ftpdir(filesys, name, this, this, conn);
+ link(name, ino);
+
+ return 0;
+}
+
+string
+ftpdir::ftppath() const
+{
+ string p;
+
+ if (ftpup)
+ {
+ p = string(ftpup->ftppath());
+ p += "/";
+ p += name.elem();
+ }
+ else
+ p = ".";
+ return p;
+}
Added: trunk/filesystems/ftpfs/Makefile
==============================================================================
--- trunk/filesystems/ftpfs/Makefile 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/ftpfs/Makefile 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,33 @@
+TOP=../..
+include $(TOP)/rules
+
+DEBUG=-ggdb3 -DDEBUG -O
+FLAGS=-I$(TOP)/lwp -I$(TOP)/kernel -I$(TOP)/lib -I$(TOP)/genser -I${TOP}/utils -I/usr/include/g++
+CXXFLAGS = $(FLAGS)
+CFLAGS = $(FLAGS)
+
+LDFLAGS = $(DEBUG) $(PROF)
+
+DEPLIBS= $(DEPLIBUSERFS) $(DEPLIBLWP)
+LIBS= $(LIBUSERFS) $(LIBLWP) #-lmcheck
+
+PROGS=ftpfs
+
+OBJ=ftpfs.o ino.o dir.o topdir.o sitetopdir.o ftpdir.o ftplink.o \
+ ftpfile.o ftpconn.o nonblk_io.o pushd.o netsys.o \
+ ConfFile.o serv_port.o host.o dos_host.o unix_host.o \
+ getdate.o Path.o conninfo.o
+
+all:: $(PROGS)
+
+ftpfs: $(OBJ) $(DEPLIBS)
+ $(CXX) $(LDFLAGS) -o $@ $(OBJ) $(LIBS)
+
+getdate.c: getdate.y
+
+clean:: dummy
+ rm -f getdate.c *.o *~ core $(PROGS)
+
+dep depend:: getdate.c
+ $(CC) $(FLAGS) -M *.c *.cc > .depend
+
Added: trunk/filesystems/ftpfs/Path.h
==============================================================================
--- trunk/filesystems/ftpfs/Path.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/ftpfs/Path.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,49 @@
+// -*- C++ -*-
+
+// Pathnames
+
+// (C) Copyright 1994 Jeremy Fitzhardinge <jeremy at sw.oz.au>
+// This code is distributed under the terms of the
+// GNU General Public Licence. See COPYING for more details.
+
+#ifndef _PATH_H_
+#define _PATH_H_
+
+#pragma interface
+
+#include <string>
+
+class _PathRep
+{
+ friend class Path;
+
+ string _path;
+ const _PathRep *_parent;
+ int count;
+
+ void decref() { if (--count == 0) delete this; }
+ void incref() { count++; }
+
+ string path() const;
+ _PathRep(const string &, const _PathRep *parent);
+ ~_PathRep();
+};
+
+class Path
+{
+ _PathRep *p_rep;
+ const Path *_parent;
+
+public:
+ Path(const string &elem, const Path *parent=NULL);
+ Path(const Path &);
+ ~Path();
+
+ Path &operator =(const Path &);
+
+ const string &elem() const { return p_rep->_path; }
+ string path() const { return p_rep->path(); }
+ const Path *parent() const { return _parent; }
+};
+
+#endif /* _PATH_H_ */
Added: trunk/filesystems/ftpfs/getdate.y
==============================================================================
--- trunk/filesystems/ftpfs/getdate.y 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/ftpfs/getdate.y 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,842 @@
+%{
+/* 1.8
+** @(#)getdate.y 1.8 92/03/03
+**
+** Originally written by Steven M. Bellovin <smb at research.att.com> while
+** at the University of North Carolina at Chapel Hill. Later tweaked by
+** a couple of people on Usenet. Completely overhauled by Rich $alz
+** <rsalz at bbn.com> and Jim Berets <jberets at bbn.com> in August, 1990;
+** send any email to Rich.
+**
+** This grammar has eight shift/reduce conflicts.
+**
+** This code is in the public domain and has no copyright.
+*/
+/* SUPPRESS 287 on yaccpar_sccsid *//* Unused static variable */
+/* SUPPRESS 288 on yyerrlab *//* Label unused */
+
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/timeb.h>
+#include <ctype.h>
+#include "getdate.h"
+
+#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__)
+#ifdef __GNUC__
+#undef alloca /* might get redefined below */
+#endif
+#endif
+
+#define yyparse getdate_yyparse
+#define yylex getdate_yylex
+#define yyerror getdate_yyerror
+
+#if !defined(lint) && !defined(SABER)
+static char RCS[] = "@(#)getdate.y 1.8 92/03/03";
+#endif /* !defined(lint) && !defined(SABER) */
+
+
+#define EPOCH 1970
+#define HOUR(x) ((time_t)(x) * 60)
+#define SECSPERDAY (24L * 60L * 60L)
+
+
+/*
+** An entry in the lexical lookup table.
+*/
+typedef struct _TABLE {
+ char *name;
+ int type;
+ time_t value;
+} TABLE;
+
+
+
+/*
+** Global variables. We could get rid of most of these by using a good
+** union as the yacc stack. (This routine was originally written before
+** yacc had the %union construct.) Maybe someday; right now we only use
+** the %union very rarely.
+*/
+static char *yyInput;
+static DSTMODE yyDSTmode;
+static time_t yyDayOrdinal;
+static time_t yyDayNumber;
+static int yyHaveDate;
+static int yyHaveDay;
+static int yyHaveRel;
+static int yyHaveTime;
+static int yyHaveZone;
+static time_t yyTimezone;
+static time_t yyDay;
+static time_t yyHour;
+static time_t yyMinutes;
+static time_t yyMonth;
+static time_t yySeconds;
+static time_t yyYear;
+static MERIDIAN yyMeridian;
+static time_t yyRelMonth;
+static time_t yyRelSeconds;
+
+%}
+
+%union {
+ time_t Number;
+ enum _MERIDIAN Meridian;
+}
+
+%token tAGO tDAY tDAYZONE tID tMERIDIAN tMINUTE_UNIT tMONTH tMONTH_UNIT
+%token tSEC_UNIT tSNUMBER tUNUMBER tZONE tDST
+
+%type <Number> tDAY tDAYZONE tMINUTE_UNIT tMONTH tMONTH_UNIT
+%type <Number> tSEC_UNIT tSNUMBER tUNUMBER tZONE
+%type <Meridian> tMERIDIAN o_merid
+
+%%
+
+spec : /* NULL */
+ | spec item
+ ;
+
+item : time {
+ yyHaveTime++;
+ }
+ | zone {
+ yyHaveZone++;
+ }
+ | date {
+ yyHaveDate++;
+ }
+ | day {
+ yyHaveDay++;
+ }
+ | rel {
+ yyHaveRel++;
+ }
+ | number
+ ;
+
+time : tUNUMBER tMERIDIAN {
+ yyHour = $1;
+ yyMinutes = 0;
+ yySeconds = 0;
+ yyMeridian = $2;
+ }
+ | tUNUMBER ':' tUNUMBER o_merid {
+ yyHour = $1;
+ yyMinutes = $3;
+ yySeconds = 0;
+ yyMeridian = $4;
+ }
+ | tUNUMBER ':' tUNUMBER tSNUMBER {
+ yyHour = $1;
+ yyMinutes = $3;
+ yyMeridian = MER24;
+ yyDSTmode = DSToff;
+ yyTimezone = - ($4 % 100 + ($4 / 100) * 60);
+ }
+ | tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid {
+ yyHour = $1;
+ yyMinutes = $3;
+ yySeconds = $5;
+ yyMeridian = $6;
+ }
+ | tUNUMBER ':' tUNUMBER ':' tUNUMBER tSNUMBER {
+ yyHour = $1;
+ yyMinutes = $3;
+ yySeconds = $5;
+ yyMeridian = MER24;
+ yyDSTmode = DSToff;
+ yyTimezone = - ($6 % 100 + ($6 / 100) * 60);
+ }
+ ;
+
+zone : tZONE {
+ yyTimezone = $1;
+ yyDSTmode = DSToff;
+ }
+ | tDAYZONE {
+ yyTimezone = $1;
+ yyDSTmode = DSTon;
+ }
+ |
+ tZONE tDST {
+ yyTimezone = $1;
+ yyDSTmode = DSTon;
+ }
+ ;
+
+day : tDAY {
+ yyDayOrdinal = 1;
+ yyDayNumber = $1;
+ }
+ | tDAY ',' {
+ yyDayOrdinal = 1;
+ yyDayNumber = $1;
+ }
+ | tUNUMBER tDAY {
+ yyDayOrdinal = $1;
+ yyDayNumber = $2;
+ }
+ ;
+
+date : tUNUMBER '/' tUNUMBER {
+ yyMonth = $1;
+ yyDay = $3;
+ }
+ | tUNUMBER '/' tUNUMBER '/' tUNUMBER {
+ yyMonth = $1;
+ yyDay = $3;
+ yyYear = $5;
+ }
+ | tMONTH tUNUMBER {
+ yyMonth = $1;
+ yyDay = $2;
+ }
+ | tMONTH tUNUMBER ',' tUNUMBER {
+ yyMonth = $1;
+ yyDay = $2;
+ yyYear = $4;
+ }
+ | tUNUMBER tMONTH {
+ yyMonth = $2;
+ yyDay = $1;
+ }
+ | tUNUMBER tMONTH tUNUMBER {
+ yyMonth = $2;
+ yyDay = $1;
+ yyYear = $3;
+ }
+ | tUNUMBER '-' tMONTH '-' tUNUMBER {
+ yyMonth = $3;
+ yyDay = $1;
+ yyYear = $5;
+ }
+ ;
+
+rel : relunit tAGO {
+ yyRelSeconds = -yyRelSeconds;
+ yyRelMonth = -yyRelMonth;
+ }
+ | relunit
+ ;
+
+relunit : tUNUMBER tMINUTE_UNIT {
+ yyRelSeconds += $1 * $2 * 60L;
+ }
+ | tSNUMBER tMINUTE_UNIT {
+ yyRelSeconds += $1 * $2 * 60L;
+ }
+ | tMINUTE_UNIT {
+ yyRelSeconds += $1 * 60L;
+ }
+ | tSNUMBER tSEC_UNIT {
+ yyRelSeconds += $1;
+ }
+ | tUNUMBER tSEC_UNIT {
+ yyRelSeconds += $1;
+ }
+ | tSEC_UNIT {
+ yyRelSeconds++;
+ }
+ | tSNUMBER tMONTH_UNIT {
+ yyRelMonth += $1 * $2;
+ }
+ | tUNUMBER tMONTH_UNIT {
+ yyRelMonth += $1 * $2;
+ }
+ | tMONTH_UNIT {
+ yyRelMonth += $1;
+ }
+ ;
+
+number : tUNUMBER {
+ if (yyHaveTime && yyHaveDate && !yyHaveRel)
+ yyYear = $1;
+ else {
+ if($1>10000) {
+ time_t date_part;
+
+ date_part= $1/10000;
+ yyHaveDate++;
+ yyDay= (date_part)%100;
+ yyMonth= (date_part/100)%100;
+ yyYear = date_part/10000;
+ }
+ yyHaveTime++;
+ if ($1 < 100) {
+ yyHour = $1;
+ yyMinutes = 0;
+ }
+ else {
+ yyHour = $1 / 100;
+ yyMinutes = $1 % 100;
+ }
+ yySeconds = 0;
+ yyMeridian = MER24;
+ }
+ }
+ ;
+
+o_merid : /* NULL */ {
+ $$ = MER24;
+ }
+ | tMERIDIAN {
+ $$ = $1;
+ }
+ ;
+
+%%
+
+/* Month and day table. */
+static TABLE MonthDayTable[] = {
+ { "january", tMONTH, 1 },
+ { "february", tMONTH, 2 },
+ { "march", tMONTH, 3 },
+ { "april", tMONTH, 4 },
+ { "may", tMONTH, 5 },
+ { "june", tMONTH, 6 },
+ { "july", tMONTH, 7 },
+ { "august", tMONTH, 8 },
+ { "september", tMONTH, 9 },
+ { "sept", tMONTH, 9 },
+ { "october", tMONTH, 10 },
+ { "november", tMONTH, 11 },
+ { "december", tMONTH, 12 },
+ { "sunday", tDAY, 0 },
+ { "monday", tDAY, 1 },
+ { "tuesday", tDAY, 2 },
+ { "tues", tDAY, 2 },
+ { "wednesday", tDAY, 3 },
+ { "wednes", tDAY, 3 },
+ { "thursday", tDAY, 4 },
+ { "thur", tDAY, 4 },
+ { "thurs", tDAY, 4 },
+ { "friday", tDAY, 5 },
+ { "saturday", tDAY, 6 },
+ { NULL }
+};
+
+/* Time units table. */
+static TABLE UnitsTable[] = {
+ { "year", tMONTH_UNIT, 12 },
+ { "month", tMONTH_UNIT, 1 },
+ { "fortnight", tMINUTE_UNIT, 14 * 24 * 60 },
+ { "week", tMINUTE_UNIT, 7 * 24 * 60 },
+ { "day", tMINUTE_UNIT, 1 * 24 * 60 },
+ { "hour", tMINUTE_UNIT, 60 },
+ { "minute", tMINUTE_UNIT, 1 },
+ { "min", tMINUTE_UNIT, 1 },
+ { "second", tSEC_UNIT, 1 },
+ { "sec", tSEC_UNIT, 1 },
+ { NULL }
+};
+
+/* Assorted relative-time words. */
+static TABLE OtherTable[] = {
+ { "tomorrow", tMINUTE_UNIT, 1 * 24 * 60 },
+ { "yesterday", tMINUTE_UNIT, -1 * 24 * 60 },
+ { "today", tMINUTE_UNIT, 0 },
+ { "now", tMINUTE_UNIT, 0 },
+ { "last", tUNUMBER, -1 },
+ { "this", tMINUTE_UNIT, 0 },
+ { "next", tUNUMBER, 2 },
+ { "first", tUNUMBER, 1 },
+/* { "second", tUNUMBER, 2 }, */
+ { "third", tUNUMBER, 3 },
+ { "fourth", tUNUMBER, 4 },
+ { "fifth", tUNUMBER, 5 },
+ { "sixth", tUNUMBER, 6 },
+ { "seventh", tUNUMBER, 7 },
+ { "eighth", tUNUMBER, 8 },
+ { "ninth", tUNUMBER, 9 },
+ { "tenth", tUNUMBER, 10 },
+ { "eleventh", tUNUMBER, 11 },
+ { "twelfth", tUNUMBER, 12 },
+ { "ago", tAGO, 1 },
+ { NULL }
+};
+
+/* The timezone table. */
+/* Some of these are commented out because a time_t can't store a float. */
+static TABLE TimezoneTable[] = {
+ { "gmt", tZONE, HOUR( 0) }, /* Greenwich Mean */
+ { "ut", tZONE, HOUR( 0) }, /* Universal (Coordinated) */
+ { "utc", tZONE, HOUR( 0) },
+ { "wet", tZONE, HOUR( 0) }, /* Western European */
+ { "bst", tDAYZONE, HOUR( 0) }, /* British Summer */
+ { "wat", tZONE, HOUR( 1) }, /* West Africa */
+ { "at", tZONE, HOUR( 2) }, /* Azores */
+#if 0
+ /* For completeness. BST is also British Summer, and GST is
+ * also Guam Standard. */
+ { "bst", tZONE, HOUR( 3) }, /* Brazil Standard */
+ { "gst", tZONE, HOUR( 3) }, /* Greenland Standard */
+#endif
+#if 0
+ { "nft", tZONE, HOUR(3.5) }, /* Newfoundland */
+ { "nst", tZONE, HOUR(3.5) }, /* Newfoundland Standard */
+ { "ndt", tDAYZONE, HOUR(3.5) }, /* Newfoundland Daylight */
+#endif
+ { "ast", tZONE, HOUR( 4) }, /* Atlantic Standard */
+ { "adt", tDAYZONE, HOUR( 4) }, /* Atlantic Daylight */
+ { "est", tZONE, HOUR( 5) }, /* Eastern Standard */
+ { "edt", tDAYZONE, HOUR( 5) }, /* Eastern Daylight */
+ { "cst", tZONE, HOUR( 6) }, /* Central Standard */
+ { "cdt", tDAYZONE, HOUR( 6) }, /* Central Daylight */
+ { "mst", tZONE, HOUR( 7) }, /* Mountain Standard */
+ { "mdt", tDAYZONE, HOUR( 7) }, /* Mountain Daylight */
+ { "pst", tZONE, HOUR( 8) }, /* Pacific Standard */
+ { "pdt", tDAYZONE, HOUR( 8) }, /* Pacific Daylight */
+ { "yst", tZONE, HOUR( 9) }, /* Yukon Standard */
+ { "ydt", tDAYZONE, HOUR( 9) }, /* Yukon Daylight */
+ { "hst", tZONE, HOUR(10) }, /* Hawaii Standard */
+ { "hdt", tDAYZONE, HOUR(10) }, /* Hawaii Daylight */
+ { "cat", tZONE, HOUR(10) }, /* Central Alaska */
+ { "ahst", tZONE, HOUR(10) }, /* Alaska-Hawaii Standard */
+ { "nt", tZONE, HOUR(11) }, /* Nome */
+ { "idlw", tZONE, HOUR(12) }, /* International Date Line West */
+ { "cet", tZONE, -HOUR(1) }, /* Central European */
+ { "met", tZONE, -HOUR(1) }, /* Middle European */
+ { "mewt", tZONE, -HOUR(1) }, /* Middle European Winter */
+ { "mest", tDAYZONE, -HOUR(1) }, /* Middle European Summer */
+ { "swt", tZONE, -HOUR(1) }, /* Swedish Winter */
+ { "sst", tDAYZONE, -HOUR(1) }, /* Swedish Summer */
+ { "fwt", tZONE, -HOUR(1) }, /* French Winter */
+ { "fst", tDAYZONE, -HOUR(1) }, /* French Summer */
+ { "eet", tZONE, -HOUR(2) }, /* Eastern Europe, USSR Zone 1 */
+ { "bt", tZONE, -HOUR(3) }, /* Baghdad, USSR Zone 2 */
+#if 0
+ { "it", tZONE, -HOUR(3.5) },/* Iran */
+#endif
+ { "zp4", tZONE, -HOUR(4) }, /* USSR Zone 3 */
+ { "zp5", tZONE, -HOUR(5) }, /* USSR Zone 4 */
+#if 0
+ { "ist", tZONE, -HOUR(5.5) },/* Indian Standard */
+#endif
+ { "zp6", tZONE, -HOUR(6) }, /* USSR Zone 5 */
+#if 0
+ /* For completeness. NST is also Newfoundland Stanard, and SST is
+ * also Swedish Summer. */
+ { "nst", tZONE, -HOUR(6.5) },/* North Sumatra */
+ { "sst", tZONE, -HOUR(7) }, /* South Sumatra, USSR Zone 6 */
+#endif /* 0 */
+ { "wast", tZONE, -HOUR(7) }, /* West Australian Standard */
+ { "wadt", tDAYZONE, -HOUR(7) }, /* West Australian Daylight */
+#if 0
+ { "jt", tZONE, -HOUR(7.5) },/* Java (3pm in Cronusland!) */
+#endif
+ { "cct", tZONE, -HOUR(8) }, /* China Coast, USSR Zone 7 */
+ { "jst", tZONE, -HOUR(9) }, /* Japan Standard, USSR Zone 8 */
+#if 0
+ { "cast", tZONE, -HOUR(9.5) },/* Central Australian Standard */
+ { "cadt", tDAYZONE, -HOUR(9.5) },/* Central Australian Daylight */
+#endif
+ { "east", tZONE, -HOUR(10) }, /* Eastern Australian Standard */
+ { "eadt", tDAYZONE, -HOUR(10) }, /* Eastern Australian Daylight */
+ { "gst", tZONE, -HOUR(10) }, /* Guam Standard, USSR Zone 9 */
+ { "nzt", tZONE, -HOUR(12) }, /* New Zealand */
+ { "nzst", tZONE, -HOUR(12) }, /* New Zealand Standard */
+ { "nzdt", tDAYZONE, -HOUR(12) }, /* New Zealand Daylight */
+ { "idle", tZONE, -HOUR(12) }, /* International Date Line East */
+ { NULL }
+};
+
+/* Military timezone table. */
+static TABLE MilitaryTable[] = {
+ { "a", tZONE, HOUR( 1) },
+ { "b", tZONE, HOUR( 2) },
+ { "c", tZONE, HOUR( 3) },
+ { "d", tZONE, HOUR( 4) },
+ { "e", tZONE, HOUR( 5) },
+ { "f", tZONE, HOUR( 6) },
+ { "g", tZONE, HOUR( 7) },
+ { "h", tZONE, HOUR( 8) },
+ { "i", tZONE, HOUR( 9) },
+ { "k", tZONE, HOUR( 10) },
+ { "l", tZONE, HOUR( 11) },
+ { "m", tZONE, HOUR( 12) },
+ { "n", tZONE, HOUR(- 1) },
+ { "o", tZONE, HOUR(- 2) },
+ { "p", tZONE, HOUR(- 3) },
+ { "q", tZONE, HOUR(- 4) },
+ { "r", tZONE, HOUR(- 5) },
+ { "s", tZONE, HOUR(- 6) },
+ { "t", tZONE, HOUR(- 7) },
+ { "u", tZONE, HOUR(- 8) },
+ { "v", tZONE, HOUR(- 9) },
+ { "w", tZONE, HOUR(-10) },
+ { "x", tZONE, HOUR(-11) },
+ { "y", tZONE, HOUR(-12) },
+ { "z", tZONE, HOUR( 0) },
+ { NULL }
+};
+
+
+
+
+/* ARGSUSED */
+int
+yyerror(s)
+ char *s;
+{
+ return 0;
+}
+
+
+static time_t
+ToSeconds(time_t Hours, time_t Minutes, time_t Seconds, MERIDIAN Meridian)
+{
+ time_t ret = -1;
+
+ if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59)
+ return -1;
+ switch (Meridian) {
+ case MER24:
+ if (Hours < 0 || Hours > 23)
+ return -1;
+ ret = (Hours * 60L + Minutes) * 60L + Seconds;
+ break;
+ case MERam:
+ if (Hours < 1 || Hours > 12)
+ return -1;
+ ret = (Hours * 60L + Minutes) * 60L + Seconds;
+ break;
+ case MERpm:
+ if (Hours < 1 || Hours > 12)
+ return -1;
+ ret = ((Hours + 12) * 60L + Minutes) * 60L + Seconds;
+ break;
+ }
+ return ret;
+}
+
+time_t
+Convert(time_t Month, time_t Day, time_t Year,
+ time_t Hours, time_t Minutes, time_t Seconds,
+ MERIDIAN Meridian, DSTMODE DSTmode,
+ time_t timezone)
+{
+ time_t now = time(0);
+ struct tm *tm = localtime(&now);
+ time_t timeval;
+
+ if (Year >= 1900)
+ Year -= 1900;
+
+ tm->tm_year = Year;
+ tm->tm_mon = Month-1;
+ tm->tm_mday = Day;
+ tm->tm_hour = Hours;
+ tm->tm_min = Minutes;
+ tm->tm_sec = Seconds;
+
+ timeval = mktime(tm);
+
+ timeval += timezone * 60L;
+ if (DSTmode == DSTon ||
+ (DSTmode == DSTmaybe && localtime(&now)->tm_isdst))
+ timeval -= 60*60;
+
+ return timeval;
+}
+
+static time_t
+DSTcorrect(time_t Start, time_t Future)
+{
+ time_t StartDay;
+ time_t FutureDay;
+
+ StartDay = (localtime(&Start)->tm_hour + 1) % 24;
+ FutureDay = (localtime(&Future)->tm_hour + 1) % 24;
+ return (Future - Start) + (StartDay - FutureDay) * 60L * 60L;
+}
+
+
+static time_t
+RelativeDate(time_t Start, time_t DayOrdinal, time_t DayNumber)
+{
+ struct tm *tm;
+ time_t now;
+
+ now = Start;
+ tm = localtime(&now);
+ now += SECSPERDAY * ((DayNumber - tm->tm_wday + 7) % 7);
+ now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1);
+ return DSTcorrect(Start, now);
+}
+
+
+static time_t
+RelativeMonth(time_t Start, time_t RelMonth)
+{
+ struct tm *tm;
+ time_t Month;
+ time_t Year;
+
+ if (RelMonth == 0)
+ return 0;
+ tm = localtime(&Start);
+ Month = 12 * tm->tm_year + tm->tm_mon + RelMonth;
+ Year = Month / 12;
+ Month = Month % 12 + 1;
+ return DSTcorrect(Start,
+ Convert(Month, (time_t)tm->tm_mday, Year,
+ (time_t)tm->tm_hour, (time_t)tm->tm_min, (time_t)tm->tm_sec,
+ MER24, DSTmaybe, yyTimezone));
+}
+
+
+static int
+LookupWord(char *buff)
+{
+ register char *p;
+ register char *q;
+ register TABLE *tp;
+ int i;
+ int abbrev;
+
+ /* Make it lowercase. */
+ for (p = buff; *p; p++)
+ if (isupper(*p))
+ *p = tolower(*p);
+
+ if (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0) {
+ yylval.Meridian = MERam;
+ return tMERIDIAN;
+ }
+ if (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0) {
+ yylval.Meridian = MERpm;
+ return tMERIDIAN;
+ }
+
+ /* See if we have an abbreviation for a month. */
+ if (strlen(buff) == 3)
+ abbrev = 1;
+ else if (strlen(buff) == 4 && buff[3] == '.') {
+ abbrev = 1;
+ buff[3] = '\0';
+ }
+ else
+ abbrev = 0;
+
+ for (tp = MonthDayTable; tp->name; tp++) {
+ if (abbrev) {
+ if (strncmp(buff, tp->name, 3) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+ }
+ else if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+ }
+
+ for (tp = TimezoneTable; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+
+ if (strcmp(buff, "dst") == 0)
+ return tDST;
+
+ for (tp = UnitsTable; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+
+ /* Strip off any plural and try the units table again. */
+ i = strlen(buff) - 1;
+ if (buff[i] == 's') {
+ buff[i] = '\0';
+ for (tp = UnitsTable; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+ buff[i] = 's'; /* Put back for "this" in OtherTable. */
+ }
+
+ for (tp = OtherTable; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+
+ /* Military timezones. */
+ if (buff[1] == '\0' && isalpha(*buff)) {
+ for (tp = MilitaryTable; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+ }
+
+ /* Drop out any periods and try the timezone table again. */
+ for (i = 0, p = q = buff; *q; q++)
+ if (*q != '.')
+ *p++ = *q;
+ else
+ i++;
+ *p = '\0';
+ if (i)
+ for (tp = TimezoneTable; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+
+ return tID;
+}
+
+
+int
+yylex()
+{
+ register char c;
+ register char *p;
+ char buff[20];
+ int Count;
+ int sign;
+
+ for ( ; ; ) {
+ while (isspace(*yyInput))
+ yyInput++;
+
+ if (isdigit(c = *yyInput) || c == '-' || c == '+') {
+ if (c == '-' || c == '+') {
+ sign = c == '-' ? -1 : 1;
+ if (!isdigit(*++yyInput))
+ /* skip the '-' sign */
+ continue;
+ }
+ else
+ sign = 0;
+ for (yylval.Number = 0; isdigit(c = *yyInput++); )
+ yylval.Number = 10 * yylval.Number + c - '0';
+ yyInput--;
+ if (sign < 0)
+ yylval.Number = -yylval.Number;
+ return sign ? tSNUMBER : tUNUMBER;
+ }
+ if (isalpha(c)) {
+ for (p = buff; isalpha(c = *yyInput++) || c == '.'; )
+ if (p < &buff[sizeof buff - 1])
+ *p++ = c;
+ *p = '\0';
+ yyInput--;
+ return LookupWord(buff);
+ }
+ if (c != '(')
+ return *yyInput++;
+ Count = 0;
+ do {
+ c = *yyInput++;
+ if (c == '\0')
+ return c;
+ if (c == '(')
+ Count++;
+ else if (c == ')')
+ Count--;
+ } while (Count > 0);
+ }
+}
+
+
+time_t
+get_date(char *p, struct timeb *now)
+{
+ struct tm *tm;
+ struct timeb ftz;
+ time_t Start;
+ time_t tod;
+
+ yyInput = p;
+ if (now == NULL) {
+ now = &ftz;
+ (void)ftime(&ftz);
+ }
+
+ tm = gmtime(&now->time);
+ yyYear = tm->tm_year;
+ yyMonth = tm->tm_mon + 1;
+ yyDay = tm->tm_mday;
+#if defined(timezone)
+ yyTimezone = now->tzone;
+#else
+ yyTimezone = now->timezone;
+#endif /* defined(timezone) */
+ yyDSTmode = DSTmaybe;
+ yyHour = 0;
+ yyMinutes = 0;
+ yySeconds = 0;
+ yyMeridian = MER24;
+ yyRelSeconds = 0;
+ yyRelMonth = 0;
+ yyHaveDate = 0;
+ yyHaveDay = 0;
+ yyHaveRel = 0;
+ yyHaveTime = 0;
+ yyHaveZone = 0;
+
+ if (yyparse()
+ || yyHaveTime > 1 || yyHaveZone > 1 || yyHaveDate > 1 || yyHaveDay > 1)
+ return -1;
+
+ if (yyHaveDate || yyHaveTime || yyHaveDay) {
+ Start = Convert(yyMonth, yyDay, yyYear, yyHour, yyMinutes, yySeconds,
+ yyMeridian, yyDSTmode, yyTimezone);
+ if (Start < 0)
+ return -1;
+ }
+ else {
+ Start = now->time;
+ if (!yyHaveRel)
+ Start -= ((tm->tm_hour * 60L + tm->tm_min) * 60L) + tm->tm_sec;
+ }
+
+ Start += yyRelSeconds;
+ Start += RelativeMonth(Start, yyRelMonth);
+
+ if (yyHaveDay && !yyHaveDate) {
+ tod = RelativeDate(Start, yyDayOrdinal, yyDayNumber);
+ Start += tod;
+ }
+
+ /* Have to do *something* with a legitimate -1 so it's distinguishable
+ * from the error return value. (Alternately could set errno on error.) */
+ return Start == -1 ? 0 : Start;
+}
+
+
+#if defined(TEST)
+
+#include <stdio.h>
+/* ARGSUSED */
+main(ac, av)
+ int ac;
+ char *av[];
+{
+ char buff[128];
+ time_t d;
+
+ (void)printf("Enter date, or blank line to exit.\n\t> ");
+ (void)fflush(stdout);
+ while (gets(buff) && buff[0]) {
+ d = get_date(buff, (struct timeb *)NULL);
+ if (d == -1)
+ (void)printf("Bad format - couldn't convert.\n");
+ else
+ (void)printf("%s", ctime(&d));
+ (void)printf("\t> ");
+ (void)fflush(stdout);
+ }
+ exit(0);
+ /* NOTREACHED */
+}
+#endif /* defined(TEST) */
Added: trunk/filesystems/ftpfs/ftpconn.cc
==============================================================================
--- trunk/filesystems/ftpfs/ftpconn.cc 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/ftpfs/ftpconn.cc 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,923 @@
+// -*- C++ -*-
+
+// Handle FTP connections
+
+// (C) Copyright 1994 Jeremy Fitzhardinge <jeremy at sw.oz.au>
+// This code is distributed under the terms of the
+// GNU General Public Licence. See COPYING for more details.
+
+#pragma implementation
+
+#include "ftpconn.h"
+#include "LWP.h"
+#include "ConfFile.h"
+#include "serv_port.h"
+#include "io.h"
+
+// Host types
+#include "unix_host.h"
+#include "dos_host.h"
+
+#include <netdb.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string>
+#include <ctype.h>
+#include <arpa/telnet.h>
+#include <arpa/inet.h>
+#include <assert.h>
+
+#include <fstream.h>
+#include <obstack.h>
+
+#define obstack_chunk_alloc malloc
+#define obstack_chunk_free free
+
+static const serv_port ftp_port("ftp", "tcp");
+
+class semlock
+{
+ Semaphore &sem;
+public:
+ semlock(Semaphore &sem):sem(sem) { sem.wait(); }
+ ~semlock() { sem.signal(); }
+};
+
+ftpconn::ftpconn(const Path &conffile, const string &host)
+ :hostname(host), conf(conffile), sem(1)
+{
+ struct hostent *he = gethostbyname((const char *)hostname.data());
+
+ if (he == NULL)
+ {
+ cerr << "Hostname lookup for " << host << " failed: " << flush;
+ herror("");
+ }
+
+ init(he);
+}
+
+ftpconn::ftpconn(const Path &conffile, const string &host,
+ const struct hostent *he)
+ :hostname(host), conf(conffile), sem(1)
+{
+ init(he);
+}
+
+void
+ftpconn::init(const struct hostent *he)
+{
+ lastreply = NULL;
+ ref = 0;
+ need_tz = 1;
+ need_siteroot = 1;
+ timezone = 0;
+ ctlsock = datasock = -1;
+ inbuf = NULL;
+ memset(&addr, 0, sizeof(addr));
+ memset(&myaddr, 0, sizeof(myaddr));
+ state = Unresolved;
+
+ getparams();
+
+ if (state == Unresolved)
+ {
+ if (resolve_name(he) != 0)
+ return;
+
+ state = Resolved;
+ }
+}
+
+static unix_host unix_host_type;
+static dos_host dos_host_type;
+
+host *host_types[] =
+{
+ &unix_host_type,
+ &dos_host_type,
+};
+
+// Various parameters for this site/connection
+void
+ftpconn::getparams()
+{
+ if (!conf.get("username", username))
+ username="anonymous";
+ if (!conf.get("password", passwd))
+ passwd="ftpfs@"; // '@' makes some sites more agreeable
+ if (!conf.getnum("update_timeout", upd_timeout))
+ upd_timeout = 60*60;
+ if (!conf.getnum("fail_timeout", fail_timeout))
+ fail_timeout = 120;
+ if (conf.get("site_root", site_root))
+ need_siteroot = 0;
+
+ if (conf.getnum("timezone", timezone))
+ need_tz = 0;
+
+ string hosttype;
+ site_host = NULL;
+ if (conf.get("hosttype", hosttype))
+ {
+ for (unsigned i = 0;
+ i < sizeof(host_types)/sizeof(*host_types);
+ i++)
+ if (hosttype == host_types[i]->hosttype())
+ site_host = host_types[i];
+ }
+ if (site_host == NULL)
+ site_host = &unix_host_type;
+
+ string dotaddr;
+ if (conf.get("ip_address", dotaddr))
+ if ((addr.sin_addr.s_addr = inet_addr(dotaddr.data())) != -1)
+ {
+ addr.sin_port = ftp_port.port;
+ addr.sin_family = AF_INET;
+ state = Resolved;
+ }
+}
+
+void
+ftpconn::setparams()
+{
+ if (state >= Resolved)
+ {
+ string dotaddr(inet_ntoa(addr.sin_addr));
+
+ conf.set("ip_address", dotaddr);
+ }
+ if (!need_tz)
+ conf.setnum("timezone", timezone);
+ if (!need_siteroot)
+ conf.set("site_root", site_root);
+
+ conf.set("hosttype", site_host->hosttype());
+}
+
+ftpconn::~ftpconn()
+{
+ setparams();
+ if (state > Resolved)
+ goto_state(Resolved);
+ if (inbuf)
+ delete inbuf;
+ cout << "FTP connection to " << hostname << " closed\n";
+}
+
+ftpstate_t
+ftpconn::resolve(ftpstate_t)
+{
+ assert(state == Unresolved);
+
+ struct hostent *he = gethostbyname(hostname.data());
+
+ if (resolve_name(he))
+ return Bad;
+ return Resolved;
+}
+
+int
+ftpconn::resolve_name(const struct hostent *he)
+{
+ if (he == NULL)
+ return -1;
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = he->h_addrtype;
+ memcpy(&addr.sin_addr, he->h_addr_list[0], sizeof(he->h_length));
+ addr.sin_port = ftp_port.port;
+
+ return 0;
+}
+
+ftpstate_t
+ftpconn::connect(ftpstate_t)
+{
+ if (need_tz)
+ {
+ time_t now = time(0); // UTC
+ time_t there = site_host->localtime(addr);
+
+ if (there == (time_t)-1)
+ there = now; // Fake it
+
+ time_t diff = (now-there)/60;
+
+ time_t d = diff;
+ cout << "Time diff = "<<d/60<<"hr "<<d%60<<"min\n";
+ timezone = diff;
+ need_tz = 0;
+ }
+
+ if ((ctlsock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
+ {
+ perror("ftpconn::connect socket() failed");
+ return Bad;
+ }
+
+ if (::connect(ctlsock, (struct sockaddr *)&addr, sizeof(addr)) == -1)
+ {
+ perror("ftpconn::connect connect() failed");
+ ::close(ctlsock);
+ return Bad;
+ }
+
+ int len = sizeof (myaddr);
+ if (getsockname(ctlsock, (struct sockaddr *)&myaddr, (socklen_t *)&len) < 0)
+ {
+ perror("ftpconn::connect getsockname() failed");
+ ::close(ctlsock);
+ return Bad;
+ }
+
+ inbuf = new ifstream(ctlsock);
+ inbuf->unsetf(ios::skipws);
+
+ if (getreply() != 220)
+ {
+ cerr << "Failed to connect properly\n";
+ ::close(ctlsock);
+ delete inbuf;
+ inbuf = NULL;
+ return Bad;
+ }
+
+ cout << "Connected OK to " << hostname << '\n';
+
+ return Connected;
+}
+
+ftpstate_t
+ftpconn::close(ftpstate_t)
+{
+ ::close(ctlsock);
+ ::close(datasock);
+
+ ctlsock = datasock = -1;
+
+ return Resolved;
+}
+
+ftpstate_t
+ftpconn::login(ftpstate_t)
+{
+ int ret = 0;
+
+ if (sendcmd("USER "+username) != 331)
+ return Bad;
+
+ if (sendcmd("PASS "+passwd) != 230)
+ return Bad;
+
+ if (need_siteroot && ftpcwd(site_root)/100 != 2)
+ {
+ cout << "Failed to get CWD\n";
+ site_root = ".";
+ }
+ else
+ need_siteroot = 0;
+
+ if (ftpsetcwd(site_root) != 250)
+ {
+ goto_state(Resolved);
+ return Bad;
+ }
+
+ if (ret != 0)
+ cout << "Login as " << username <<
+ ", passwd " << passwd << " failed\n";
+ else
+ {
+ sendcmd("SYST");
+ sendcmd("STAT");
+ }
+
+ return LoggedIn;
+}
+
+ftpstate_t
+ftpconn::logout(ftpstate_t)
+{
+ sendcmd("QUIT");
+ return Connected;
+}
+
+ftpstate_t
+ftpconn::listen(ftpstate_t)
+{
+ dataaddr = myaddr; // Our address
+ dataaddr.sin_port = 0; // System port
+
+ closedata(LoggedIn);
+
+ if ((datasock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
+ {
+ perror("creation of data socket failed");
+ return Bad;
+ }
+
+ if (::bind(datasock, (struct sockaddr *)&dataaddr, sizeof(dataaddr)) == -1)
+ {
+ perror("bind of data socket");
+ closedata(LoggedIn);
+ return Bad;
+ }
+
+ int len = sizeof (dataaddr);
+ if (getsockname(datasock, (struct sockaddr *)&dataaddr, (socklen_t *)&len) == -1)
+ {
+ perror("data socket getsockname");
+ closedata(LoggedIn);
+ return Bad;
+ }
+
+ if (::listen(datasock, 1) == -1)
+ {
+ perror("listen on data socket");
+ closedata(LoggedIn);
+ return Bad;
+ }
+
+ char *addr = (char *)&dataaddr.sin_addr;
+ char *port = (char *)&dataaddr.sin_port;
+ char buf[128];
+
+#define UC(b) (((int)b)&0xff)
+ sprintf(buf, "PORT %d,%d,%d,%d,%d,%d",
+ UC(addr[0]), UC(addr[1]), UC(addr[2]), UC(addr[3]),
+ UC(port[0]), UC(port[1]));
+#undef UC
+ if (sendcmd(buf)/100 != 2)
+ {
+ cerr << "Send of \"" << buf << "\" failed\n";
+ return Bad;
+ }
+
+ return Listening;
+}
+
+ftpstate_t
+ftpconn::closedata(ftpstate_t nst)
+{
+ ::close(datasock);
+ datasock = -1;
+ return nst;
+}
+
+
+ftpstate_t
+ftpconn::abort(ftpstate_t nst)
+{
+ if (state == Transfer)
+ sendcmd("ABOR");
+ return nst;
+}
+
+static const char *st_name[] =
+{
+ "Unresolved",
+ "Resolved",
+ "Connected",
+ "LoggedIn",
+ "Listening",
+ "Transfer",
+ "Bad"
+};
+
+int
+ftpconn::goto_state(ftpstate_t newstate)
+{
+ typedef enum
+ {
+ tr_NONE, tr_RESOLVE, tr_CONNECT,
+ tr_CLOSE, tr_LOGIN, tr_LOGOUT,
+ tr_LISTEN, tr_CLOSEDATA, tr_ABORT
+ } trfunc;
+
+ static trfunc trtab[6][6] =
+ {
+ { tr_NONE, tr_RESOLVE, tr_RESOLVE, tr_RESOLVE, tr_RESOLVE, tr_NONE },
+ { tr_NONE, tr_NONE, tr_CONNECT, tr_CONNECT, tr_CONNECT, tr_NONE },
+ { tr_NONE, tr_CLOSE, tr_NONE, tr_LOGIN, tr_LOGIN, tr_NONE },
+ { tr_NONE, tr_LOGOUT, tr_LOGOUT, tr_NONE, tr_LISTEN, tr_NONE },
+ { tr_NONE, tr_CLOSEDATA, tr_CLOSEDATA, tr_CLOSEDATA, tr_NONE, tr_CLOSEDATA },
+ { tr_NONE, tr_ABORT, tr_ABORT, tr_ABORT, tr_ABORT, tr_NONE },
+ };
+
+ while(state != newstate)
+ {
+ ftpstate_t next;
+ assert(state < Bad);
+ assert(newstate < Bad);
+ trfunc tr = trtab[state][newstate];
+ switch (tr)
+ {
+ case tr_RESOLVE:
+ next = ftpconn::resolve(newstate);
+ break;
+ case tr_CONNECT:
+ next = ftpconn::connect(newstate);
+ break;
+ case tr_CLOSE:
+ next = ftpconn::close(newstate);
+ break;
+ case tr_LOGIN:
+ next = ftpconn::login(newstate);
+ break;
+ case tr_LOGOUT:
+ next = ftpconn::logout(newstate);
+ break;
+ case tr_LISTEN:
+ next = ftpconn::listen(newstate);
+ break;
+ case tr_CLOSEDATA:
+ next = ftpconn::closedata(newstate);
+ break;
+ case tr_ABORT:
+ next = ftpconn::abort(newstate);
+ break;
+ case tr_NONE:
+ default:
+ cerr << "No transition from " << st_name[state]
+ << " to " << st_name[newstate] << '\n';
+ return -1;
+ break;
+ }
+
+
+ if (next == Bad)
+ {
+ cerr << "Transition from " << st_name[state]
+ << " to " << st_name[newstate] << " failed\n";
+ return -1;
+ }
+ state = next;
+ }
+
+ return 0;
+}
+
+/*
+ * Send a command to the ftp server.
+ *
+ * All we do is pack the command off to the other server, and call getreply()
+ * to deal with the response. We just return the code from getreply().
+ *
+ * It returns either the code from getreply() or return with -1 and errno
+ * set if there is a syscall failure.
+ */
+int
+ftpconn::sendcmd(string command, string *repl)
+{
+ int ret;
+ int retry = 0;
+
+ cout << "Sending command \"" << command << "\"\n";
+ command += "\r\n";
+
+ if (fullwrite(ctlsock, (const unsigned char *)command.data(),
+ command.length()) != command.length())
+ {
+ perror("fullwrite of command failed");
+ return -1;
+ }
+
+ ret = getreply(repl);
+
+ return ret;
+}
+
+/*
+ * Get a reply from the ftp daemon, and deal with it.
+ *
+ * This is all dealing with the FTP protocol - see Internet RFC 959
+ * to find out what all this really means.
+ *
+ * These are the RFC 959 return codes, attached to the beginning of each
+ * reply from the remote machine.
+ *
+ * FTP Code Meaning
+ * 1xx success (positive preliminary reply)
+ * 2xx success (positive completion reply)
+ * 3xx success (positive intermediate reply)
+ * 4xx failure (transiant negative completion reply)
+ * 5xx failure (permanent negative completion reply)
+ *
+ *
+ * The code returned is either '-1' if some system call failure happens,
+ * or the code number attached to the reply.
+ */
+int
+ftpconn::getreply(string *str)
+{
+ unsigned char ch;
+ int digit; // Which digit we're processing
+ int code; // Numeric code
+ static struct obstack reply;
+// Obstack reply; // Reply in string form
+
+ obstack_init (&reply);
+ digit = 0;
+ code = 0;
+
+ while((*inbuf >> ch) && ch != '\n')
+ {
+ if (ch == IAC)
+ {
+ char telcode[4];
+
+ /*
+ * Deal with telnet protocol commands by ignoring them
+ */
+ *inbuf >> ch;
+ switch (ch)
+ {
+ case WILL:
+ case WONT:
+ *inbuf >> ch;
+ sprintf(telcode, "%c%c%c", IAC, DONT, ch);
+ fullwrite(ctlsock, (unsigned char *)telcode, 3);
+ break;
+ case DO:
+ case DONT:
+ *inbuf >> ch;
+ sprintf(telcode, "%c%c%c", IAC, WONT, ch);
+ fullwrite(ctlsock, (unsigned char *)telcode, 3);
+ break;
+ default:
+ break;
+ }
+ continue;
+ }
+
+ if (ch == '\r')
+ continue;
+
+ obstack_1grow(&reply, ch);
+
+ if (digit < 3 && isdigit(ch))
+ code = code*10 + ch-'0';
+
+ /*
+ * Handle multi-line messages
+ * These have the form:
+ * xyz-message
+ * message contents
+ * multiple lines
+ * xyz end message
+ */
+ if (digit == 3 && ch == '-')
+ {
+ string line;
+ char codebuf[5]; /* string at end of message */
+ char dat[200];
+ unsigned int pos;
+
+ sprintf(codebuf, "%3.03d ", code);
+ do
+ {
+ inbuf->getline(dat, 200);
+ line = dat;
+ if ((pos=line.find('\r', 0)) != string::npos)
+ line = line.substr(0, pos);
+ obstack_grow(&reply, (void *)line.data(), line.length());
+ obstack_1grow(&reply, '\n');
+ }
+ while(inbuf->good() && codebuf != line.substr(0,4));
+
+ if (!inbuf->good())
+ {
+ perror("inbuf->readline failed");
+ state = Resolved;
+ close(Resolved);
+ return -1;
+ }
+ break;
+ }
+ else if (digit == 3 && ch != ' ')
+ fprintf(stderr, "RFC 959 violation: Unexpected character after digits - 0x%02x, not ' '\n", ch);
+ digit++;
+ }
+
+ if (inbuf->eof() || inbuf->bad())
+ {
+ // If we get an EOF, then just go straight to Resolved state
+ close(Resolved);
+ state = Resolved;
+ return -1;
+ }
+ char *buf = (char *)obstack_finish(&reply);
+ if (str != NULL)
+ *str = string(buf);
+
+ if (lastreply)
+ delete lastreply;
+ lastreply = new string(buf);
+
+ cout << "Message \"" << *lastreply << "\"\n" <<
+ "getreply() returning " << code << '\n';
+
+ return code;
+}
+
+class ftp_return
+{
+ const string &p;
+ ftpconn &ftp;
+
+ public:
+ ftp_return(ftpconn &ftp, const string &p)
+ :p(p),ftp(ftp)
+ {
+ }
+ ~ftp_return()
+ {
+ ftp.ftpsetcwd(p, 1);
+ }
+};
+
+// Get a file list from an ftp server
+// Calls host-specific code to parse the directory listing
+ftp_filelist *
+ftpconn::getfilelist(const string &dname)
+{
+ string dirname = dname;
+ unsigned int l;
+
+ string path,dir;
+ string
+ const string &wildcard = site_host->wildcard();
+ path = dirname.substr(0,
+ dir = dirname.after('/', -1);
+ l=dirname.rfind('/',0);
+ if (dir == "")
+ dir = dname;
+
+ semlock lock(sem);
+
+ cout << "ftpconn::getfilelist getting dir on host " << hostname
+ << ", dirname=" << dirname << ", basedir=" << path
+ << ", subdir=" << dir << "\n";
+
+ if (goto_state(LoggedIn))
+ {
+ fprintf(stderr, "Failed to log in\n");
+ return NULL;
+ }
+
+ if (sendcmd("TYPE A") != 200)
+ {
+ fprintf(stderr, "Failed to set TYPE A\n");
+ return NULL;
+ }
+
+ ftp_return ftp_here(*this, site_root);
+ if (path != "" && ftpsetcwd(path) != 250)
+ {
+ cerr << "Failed to change to \"" << path << "\"\n";
+ return NULL;
+ }
+
+ if (goto_state(Listening))
+ {
+ fprintf(stderr, "Failed to listen\n");
+ return NULL;
+ }
+
+ if (sendcmd("LIST "+dir+wildcard)/100 != 1)
+ {
+ fprintf(stderr, "Failed to send LIST\n");
+ return NULL;
+ }
+
+ struct sockaddr_in from;
+ int fromlen = sizeof(from);
+ int sfd;
+
+ if ((sfd = ::accept(datasock, (struct sockaddr *)&from, &fromlen)) == -1)
+ {
+ perror("Failed to accept()");
+ goto_state(LoggedIn);
+ return NULL;
+ }
+ closedata(LoggedIn);
+
+ ifstream in(sfd);
+ string line;
+ ftp_filelist *fl = NULL;
+
+ int ret;
+ while((ret = readline(in, line)) > 0)
+ {
+ if (line.contains('\r'))
+ line = line.before('\r');
+
+ ftp_filelist *nfl = site_host->parse_filelist(line, timezone);
+
+ if (nfl == NULL)
+ continue;
+ nfl->next = fl;
+ fl = nfl;
+ }
+
+ ::close(sfd);
+ getreply();
+ goto_state(LoggedIn);
+
+ return fl;
+}
+
+int
+ftpconn::getfile(const string &fname, int fd, ftpxfer *xfer)
+{
+ string filename = fname;
+ string path = filename.before('/', -1);
+ string file = filename.after('/', -1);
+ if (file == "")
+ file = fname;
+
+ semlock lock(sem);
+
+ cout << "ftpconn::getfile getting file on host " << hostname
+ << ", dir " << path << ", file " << file << "\n";
+
+ if (goto_state(LoggedIn))
+ {
+ fprintf(stderr, "Failed to log in\n");
+ if (xfer != NULL)
+ xfer->error(EPERM);
+ return -1;
+ }
+
+ ftp_return ftp_here(*this, site_root);
+ if (path != "" && ftpsetcwd(path) != 250)
+ {
+ cerr << "Failed to change to \"" << path << "\n";
+ return -1;
+ }
+
+
+ if (sendcmd("TYPE I") != 200)
+ {
+ fprintf(stderr, "Failed to set TYPE I\n");
+ if (xfer != NULL)
+ xfer->error(EIO);
+ return -1;
+ }
+
+ if (goto_state(Listening))
+ {
+ fprintf(stderr, "Failed to listen\n");
+ if (xfer != NULL)
+ xfer->error(EIO);
+ return -1;
+ }
+
+ if (sendcmd("RETR "+file)/100 != 1)
+ {
+ fprintf(stderr, "Failed to send RETR\n");
+ if (xfer != NULL)
+ xfer->error(EIO);
+ return -1;
+ }
+
+ struct sockaddr_in from;
+ int fromlen = sizeof(from);
+ int sfd;
+
+ if ((sfd = ::accept(datasock, (struct sockaddr *)&from, &fromlen)) == -1)
+ {
+ perror("Failed to accept()");
+ if (xfer != NULL)
+ xfer->error(errno);
+ goto_state(LoggedIn);
+ return -1;
+ }
+
+ goto_state(Transfer);
+
+ unsigned char buf[2048];
+ int ret;
+
+ cout << "Fetching " << file << " from " << hostname << ':' << path << '\n';
+ while((ret = fullread(sfd, buf, sizeof(buf))) > 0)
+ {
+ putchar('#'); fflush(stdout);
+ if (fullwrite(fd, buf, ret) == -1)
+ {
+ ret = -1;
+ break;
+ }
+
+ if (xfer)
+ xfer->notify(sfd);
+ }
+ if (ret == -1)
+ {
+ perror("file xfer failed");
+ if (xfer != NULL)
+ xfer->error(errno);
+ ::close(sfd);
+ goto_state(LoggedIn);
+ return -1;
+ }
+
+ cout << file << " done\n";
+
+ getreply();
+ ::close(sfd);
+
+ state = LoggedIn; // Go directly, avoid unneeded ABOR
+
+ return 0;
+}
+
+int
+ftpconn::ftpcwd(string &cwd)
+{
+ string repl;
+ int ret;
+
+ if ((ret = sendcmd("PWD", &repl)) != 257)
+ return ret;
+
+ static const Regex bqrx("^[^\"]*\"");
+ static const Regex aqrx("\"[^\"]*$");
+ static const Regex rmqrx("\"\"");
+ static const string nil;
+
+ repl.gsub(bqrx, nil);
+ repl.gsub(aqrx, nil);
+ repl.gsub(rmqrx, nil);
+
+ cwd = repl;
+ return ret;
+}
+
+int
+ftpconn::ftpsetcwd(const string &dir, int nostep)
+{
+ int ret;
+ static const string cwd("CWD ");
+
+ if (nostep)
+ ret = sendcmd(cwd+dir);
+ else
+ {
+ string *steps;
+ int nelem = site_host->pathsteps(dir, &steps);
+ int i;
+
+ ret = 250;
+
+ for(i = 0; i < nelem; i++)
+ {
+ ret = sendcmd(cwd+steps[i]);
+ if (ret / 100 != 2)
+ break;
+ }
+
+ delete [] steps;
+ }
+ return ret;
+}
+
+int
+ftpconn::makedir(const string &dname)
+{
+ string dirname = dname;
+ string path = dirname.before('/', -1);
+ string dir = dirname.after('/', -1);
+ if (dir == "")
+ dir = dname;
+
+ semlock lock(sem);
+
+ cout << "ftpconn::makedir making dir on host " << hostname
+ << ", dirname=" << dirname << ", basedir=" << path
+ << ", subdir=" << dir << "\n";
+
+ if (goto_state(LoggedIn))
+ {
+ fprintf(stderr, "Failed to log in\n");
+ return -1;
+ }
+
+ ftp_return ftp_here(*this, site_root);
+ if (path != "" && ftpsetcwd(path) != 250)
+ {
+ cerr << "Failed to change to \"" << path << "\"\n";
+ return -1;
+ }
+
+ int ret = sendcmd("MKD "+dir);
+
+ if (ret/100 != 2)
+ return -1;
+ return 0;
+}
Added: trunk/filesystems/ftpfs/conninfo.cc
==============================================================================
--- trunk/filesystems/ftpfs/conninfo.cc 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/ftpfs/conninfo.cc 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,70 @@
+// -*- C++ -*-
+
+// Get/set info about connection
+
+// (C) Copyright 1994 Jeremy Fitzhardinge <jeremy at sw.oz.au>
+// This code is distributed under the terms of the
+// GNU General Public Licence. See COPYING for more details.
+
+#pragma implementation
+
+#include <fstream.h>
+
+#include "conninfo.h"
+#include "ftpconn.h"
+
+#include <sys/stat.h>
+
+conninfo::conninfo(ftpfs &fs, ftpconn *c)
+ :ino(fs), conn(c)
+{
+ // Use our invoker's ID rather than the person doing the syscall.
+ uid = getuid();
+ gid = getgid();
+ mode = S_IFREG | 0444;
+ size = 0;
+}
+
+conninfo::~conninfo()
+{
+}
+
+int
+conninfo::do_read(const up_preamble &, upp_repl &,
+ const upp_read_s &arg, upp_read_r &ret)
+{
+ string s;
+
+ conn->setparams();
+ conn->conf.unparsestr(s);
+
+ if (conn->lastreply != NULL)
+ {
+ s += "Last reply: ";
+ s += *conn->lastreply + "\n";
+ }
+
+ cout << "arg.off="<<arg.off<<" arg.size="<<arg.size<<" str="<<s<<"\n";
+
+ int sz = s.length() - arg.off;
+
+ if (sz <= 0)
+ sz = 0;
+
+ sz = sz > arg.size ? arg.size : sz;
+
+ ret.data.alloc(sz);
+ ret.data.nelem = sz;
+ memcpy(ret.data.elems, s.chars() + arg.off, sz);
+
+ return 0;
+}
+
+int
+conninfo::do_write(const up_preamble &, upp_repl &,
+ const upp_write_s &arg, upp_write_r &ret)
+{
+ ret.wrote = arg.data.nelem;
+
+ return 0;
+}
Added: trunk/filesystems/ftpfs/README
==============================================================================
--- trunk/filesystems/ftpfs/README 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/ftpfs/README 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,79 @@
+ ftpfs - FTP filesystem
+
+ *** BEWARE ***
+This is a new experimental filesystem. It has never been tested on
+the open Internet. If something goes wrong, it can quite easily
+saturate an FTP site and generate a lot of network bandwidth.
+ **************
+
+This filesystem allows FTP sites to be accessed in a filesystem-like
+way. Normally they will be anonymous FTP sites, but non-anonymous
+ones can be set up.
+
+It should be mounted like so:
+ muserfs ftpfs mount-point cache-dir
+
+The cache dir contains a long-term cache of the ftp'd data to minimize
+network use. The filesystem shape and the cache dir have the same
+shape: there is a directory for each site in the top directory, with
+the tree for that site underneath.
+
+To connect to a new site, type "mkdir sitename" (where sitename is a
+hostname, fully qualified if necessary) in the top filesystem
+directory. This will resolve the name and create a new cache
+directory. After that, you can just cd into the site and look around.
+Inaccessable directories appear to be empty, but otherwise the
+filesystem looks just like the ftp site. Files which are out of date
+or not present in the cache are transferred as required; otherwise
+they are just fetched from the local cache.
+
+There are a number of config and parameter files about. They all have
+the same format: one parameter per line in the form "name: value".
+
+Each site dir in the cache tree has a file called ".ftpfs_site" which
+has site-related parameters. "username" and "password" are supported,
+because any user can mount the filesystem, users can have private
+cache directories with secret usernames and passwords (so long as the
+cache has 700 permissions). Also there are also "failure_timeout"
+(time before retying after an error) and "update_timeout" (time to
+update after the last update, without any other reason). Both are in
+seconds. "timezone" is for timezone correction of times from the
+remote site, measured in number of minutes needed to be added to the
+time to make it UTC (GMT). ftpfs makes an attempt to find the local
+time at target machines to determine this automatically, but anonymous
+FTP sites often give times and dates in UTC anyway.
+
+Also, if you touch the file ".ftpfs_update" in any directory in the
+filesystem (which never exists), it causes the directory its in to be
+updated.
+
+Each directory in the cache (apart from the very top one) has a
+".ftpfs_dir" file containing per-directory information. There are a
+couple of valid parameters it uses: "last_update", which is the time
+the directory was last looked at on the ftp site (0 if it hasn't), and
+"last_failure" which is the last time this dir failed to be updated.
+Each directory also has a ".ftpfs_dirinfo" file, which contains
+information about files in the directory, even if they have not been
+transferred yet.
+
+Also, the filesystem only copes with unix ftp sites. Parsers for
+different pathname syntaxes and LIST outputs have to be written for
+other OS types.
+
+This filesystem uses a threads library to maintain multiple threads of
+execution. This allows more than one process to use the filesystem at
+once. For example, even if one process is reading from a long FTP
+transfer, other processes can use other FTP sites, or even the same
+one without being affected much (response time is slower, but its
+better than nothing). Unfortunately, since the filesystem only
+maintains one FTP connection per site, only one file at a time can be
+read from an FTP site. I may fix this in future to allow more than
+one FTP connection per site.
+
+There is a perl script "reap.pl" which prunes ftpfs cache trees of
+old files to keep the total cache size below some preset size.
+At present this needs to be invoked from a cron job or some similar
+mechanism, though in future ftpfs may invoke it itself if the cache
+is full.
+
+ J
Added: trunk/filesystems/ftpfs/ftpconn.h
==============================================================================
--- trunk/filesystems/ftpfs/ftpconn.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/ftpfs/ftpconn.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,145 @@
+// -*- C++ -*-
+
+// FTP connection class
+
+// (C) Copyright 1994 Jeremy Fitzhardinge <jeremy at sw.oz.au>
+// This code is distributed under the terms of the
+// GNU General Public Licence. See COPYING for more details.
+
+#ifndef _FTPCONN_H_
+#define _FTPCONN_H_
+
+#pragma interface
+
+#include <string>
+#include <netinet/in.h>
+
+#include "LWP.h"
+#include "ConfFile.h"
+
+enum ftpstate_t {
+ Unresolved,
+ Resolved,
+ Connected,
+ LoggedIn,
+ Listening,
+ Transfer,
+ Bad
+};
+
+#include <sys/types.h>
+#include <time.h>
+
+enum ftp_filetype
+{
+ FT_Unknown,
+ FT_File,
+ FT_Directory,
+ FT_Link
+};
+
+struct ftp_filelist
+{
+ string name;
+ string link;
+ ftp_filetype type;
+ time_t time;
+ size_t size;
+
+ ftp_filelist *next;
+};
+
+class ftpconn
+{
+ friend class conninfo;
+
+ // Reference count
+ int ref;
+
+ // Connection state
+ ftpstate_t state;
+ const string hostname;
+
+ // Parameters
+ string username; // Username (default "anonymous")
+ string passwd; // Password
+ string site_root; // Dir to cd to
+ short need_siteroot;
+ time_t timezone; // Seconds from GMT
+ short need_tz;
+ time_t upd_timeout; // Time before an update times out
+ time_t fail_timeout; // Time before retrying after failure
+ void getparams();
+ void setparams();
+
+ class host *site_host; // Site's host-specific operations
+
+ // Config file
+ ConfFile conf;
+ conninfo *infoino;
+
+ // Control connection
+ struct sockaddr_in addr;
+ struct sockaddr_in myaddr;
+ int ctlsock;
+
+ class ifstream *inbuf;
+
+ // Data connection
+ struct sockaddr_in dataaddr;
+ int datasock;
+
+ void init(const struct hostent *);
+ int resolve_name(const struct hostent *);
+
+ // Transition functions
+ ftpstate_t resolve(ftpstate_t);
+ ftpstate_t connect(ftpstate_t);
+ ftpstate_t close(ftpstate_t);
+ ftpstate_t login(ftpstate_t);
+ ftpstate_t logout(ftpstate_t);
+ ftpstate_t listen(ftpstate_t);
+ ftpstate_t closedata(ftpstate_t);
+ ftpstate_t abort(ftpstate_t);
+
+ int goto_state(ftpstate_t);
+
+ int sendcmd(string cmd, string * = NULL);
+ int getreply(string * = NULL);
+ string *lastreply;
+
+ Semaphore sem;
+
+public:
+ ftpconn(const Path &conffile, const string &host);
+ ftpconn(const Path &conffile, const string &host,
+ const struct hostent *);
+ ~ftpconn();
+
+ ftp_filelist *getfilelist(const string &path);
+ int getfile(const string &path, int fd, class ftpxfer *);
+ int ftpcwd(string &cwd);
+ int ftpsetcwd(const string &cwd, int =0);
+ int makedir(const string &dir);
+
+ void incref() { ref++; }
+ void decref()
+ {
+ if (--ref == 0)
+ delete this;
+ }
+
+ int get_upd_timeout() const { return upd_timeout; }
+ int get_fail_timeout() const { return fail_timeout; }
+};
+
+class ftpxfer
+{
+public:
+ virtual ~ftpxfer() {}
+
+ virtual void notify(int) = 0;
+ virtual void error(int) {}
+};
+
+#endif /* _FTPCONN_H_ */
Added: trunk/filesystems/ftpfs/conninfo.h
==============================================================================
--- trunk/filesystems/ftpfs/conninfo.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/ftpfs/conninfo.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,30 @@
+// -*- C++ -*-
+
+// Get/set connection info
+
+// (C) Copyright 1994 Jeremy Fitzhardinge <jeremy at sw.oz.au>
+// This code is distributed under the terms of the
+// GNU General Public Licence. See COPYING for more details.
+
+#ifndef _CONNINFO_H_
+#define _CONNINFO_H_
+
+#pragma interface
+
+#include "ino.h"
+#include <string>
+
+class conninfo : public ino
+{
+ class ftpconn *conn;
+
+ int do_write(const up_preamble &, upp_repl &,
+ const upp_write_s &, upp_write_r &);
+ int do_read(const up_preamble &, upp_repl &,
+ const upp_read_s &, upp_read_r &);
+
+public:
+ conninfo(class ftpfs &, class ftpconn *conn);
+ ~conninfo();
+};
+#endif /* _CONNINFO_H_ */
Added: trunk/filesystems/ftpfs/host.cc
==============================================================================
--- trunk/filesystems/ftpfs/host.cc 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/ftpfs/host.cc 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,18 @@
+// -*- C++ -*-
+
+// Simple implementation file for class host
+
+#pragma implementation
+
+#include "host.h"
+
+host::~host()
+{
+}
+
+const string &
+host::wildcard() const
+{
+ static const string nil;
+ return nil;
+}
Added: trunk/filesystems/ftpfs/host.h
==============================================================================
--- trunk/filesystems/ftpfs/host.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/ftpfs/host.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,36 @@
+// -*- C++ -*-
+
+// Host-type specific information
+
+// (C) Copyright 1994 Jeremy Fitzhardinge <jeremy at sw.oz.au>
+// This code is distributed under the terms of the
+// GNU General Public Licence. See COPYING for more details.
+
+#ifndef _HOST_H_
+#define _HOST_H_
+
+#pragma interface
+
+#include <sys/types.h>
+#include <string>
+#include <netinet/in.h>
+
+class host
+{
+public:
+ virtual ~host();
+
+ // Return steps to get to required directory
+ virtual int pathsteps(const string &path, string *steps[]) = 0;
+
+ // Get local time
+ virtual time_t localtime(struct sockaddr_in) = 0;
+
+ // Parse a line of file listing
+ virtual struct ftp_filelist *parse_filelist(const string &, time_t) = 0;
+ // Return host type identifier
+ virtual const string &hosttype() const = 0;
+ virtual const string &wildcard() const;
+};
+
+#endif /* _HOST_H_ */
Added: trunk/filesystems/ftpfs/unix_host.cc
==============================================================================
--- trunk/filesystems/ftpfs/unix_host.cc 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/ftpfs/unix_host.cc 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,238 @@
+// -*- C++ -*-
+
+// (C) Copyright 1994 Jeremy Fitzhardinge <jeremy at sw.oz.au>
+// This code is distributed under the terms of the
+// GNU General Public Licence. See COPYING for more details.
+
+#pragma implementation
+
+#include "unix_host.h"
+#include "serv_port.h"
+#include "ftpconn.h"
+#include "getdate.h"
+#include <io.h>
+
+#include <unistd.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <string>
+#include <stdio.h>
+#include <netinet/in.h>
+#include <stdlib.h>
+
+static const serv_port daytime_port("daytime", "tcp");
+
+int
+unix_host::pathsteps(const string &path, string *ret[])
+{
+ static const Regex deldot("\\(^\\./\\)\\|\\(/\\.\\/\\)\\|\\(/\\.$\\)\\|\\(//\\)\\|\\(^\\.$\\)");
+ static const Regex deldotdot("\\(^|/\\)[^/]+/\\.\\./");
+
+ *ret = new string[1];
+ (*ret)[0] = path;
+ (*ret)[0].gsub(deldot, "");
+ (*ret)[0].gsub(deldotdot, "/");
+
+ if ((*ret)[0] == "")
+ return 0;
+
+ return 1;
+}
+
+// Get local time at remote machine with the "time" service
+time_t
+unix_host::localtime(struct sockaddr_in addr)
+{
+ int fd;
+ unsigned char rawtime[512];
+ int size;
+
+ addr.sin_port = daytime_port.port;
+ if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
+ {
+ perror("Time service socket");
+ return -1;
+ }
+
+ if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
+ {
+ perror("Time service connect");
+ close(fd);
+ return -1;
+ }
+
+ if ((size = fullread(fd, rawtime, sizeof(rawtime)-1)) == -1)
+ {
+ perror("Time service read");
+ close(fd);
+ return -1;
+ }
+ close(fd);
+
+ rawtime[size] = 0;
+
+ time_t rtime = get_date(rawtime, NULL);
+
+ struct tm *tm = ::gmtime(&rtime);
+ cout << "Remote time "<<asctime(tm);
+ return rtime;
+}
+
+// Parse a date from "ls" - its about the only thing getdate won't handle
+static time_t
+parsedate(const string &date, time_t timezone)
+{
+ string parts[3];
+
+ if (split(date, parts, 3, RXwhite) != 3)
+ return -1;
+
+ static const string months[13] = { "xxx",
+ "Jan", "Feb", "Mar",
+ "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep",
+ "Oct", "Nov", "Dec"
+ };
+
+ static const Regex rx_time("[012]?[0-9]:[0-5][0-9]");
+ static const Regex rx_year("[0-9][0-9][0-9][0-9]");
+ static const Regex rx_day("[0-9]?[0-9]");
+
+ int month = -1;
+ int day = -1;
+ int year = -1;
+ int hours = -1;
+ int mins = -1;
+
+ for(int i = 1; i < 13; i++)
+ if (parts[0] == months[i])
+ {
+ month = i;
+ break;
+ }
+ if (month == -1)
+ return 0;
+
+ if (!parts[1].matches(rx_day))
+ return 0;
+ day = atoi(parts[1]);
+
+ if (parts[2].matches(rx_year))
+ year = atoi(parts[2]);
+ else
+ {
+ string hm[2];
+ if (!parts[2].matches(rx_time))
+ return 0;
+ if (split(parts[2], hm, 2, string(":")) != 2)
+ return 0;
+ hours = atoi(hm[0]);
+ mins = atoi(hm[1]);
+ }
+
+ time_t now = time(0);
+
+ struct tm *tm = gmtime(&now);
+
+ return Convert(month, day,
+ year == -1 ? tm->tm_year : year,
+ hours == -1 ? 0 : hours,
+ mins == -1 ? 0 : mins, 0,
+ MER24, DSToff, timezone);
+}
+
+struct ftp_filelist *
+unix_host::parse_filelist(const string &ro_line, time_t timezone)
+{
+ string line = ro_line;
+
+ // Match a line of "ls" output
+ static const Regex ls_line(
+ "^\\([-dl][r-][w-][xsS-][r-][w-][xs-][r-][w-][xTt-]\\) *"// perms
+ "[0-9]+ +" // links
+ "[0-9a-zA-Z_-]+ +" // uid
+ "[0-9a-zA-Z_-]+ +" // gid
+ "\\([0-9]+\\) +" // size
+ "\\(\\(Jan\\|Feb\\|Mar\\|Apr\\|May\\|Jun\\|Jul\\|Aug\\|Sep\\|Oct\\|Nov\\|Dec\\) \\( \\|[0-9]\\)[0-9] \\([012][0-9]:[0-5][0-9]\\| [0-9][0-9][0-9][0-9]\\)\\) " // date
+ "\\(.+\\)$" // name
+ );
+ static const Regex bsd_ls_line(
+ "^\\([-dl][r-][w-][xsS-][r-][w-][xs-][r-][w-][xTt-]\\) *"// perms
+ "[0-9]+ +" // links
+ "[0-9a-zA-Z_-]+ +" // uid
+ "\\([0-9]+\\) +" // size
+ "\\(\\(Jan\\|Feb\\|Mar\\|Apr\\|May\\|Jun\\|Jul\\|Aug\\|Sep\\|Oct\\|Nov\\|Dec\\) \\( \\|[0-9]\\)[0-9] \\([012][0-9]:[0-5][0-9]\\| [0-9][0-9][0-9][0-9]\\)\\) " // date
+ "\\(.+\\)$" // name
+ );
+
+ const Regex *ls_rx = &ls_line;
+
+ if (!line.matches(ls_line))
+ {
+ if (!line.matches(bsd_ls_line))
+ {
+ cout << "Failed to match ls line " << line << '\n';
+ return NULL;
+ }
+ ls_rx = &bsd_ls_line;
+ }
+
+ int start, len;
+
+ ftp_filelist *nf = new ftp_filelist;
+ ls_rx->match_info(start, len, 7);
+ nf->name = string(line.at(start,len));
+
+ switch(line[0])
+ {
+ case 'd':
+ nf->type = FT_Directory;
+ break;
+ case '-':
+ nf->type = FT_File;
+ break;
+ case 'l':
+ {
+ string name = nf->name;
+ static const Regex sym_rx("^\\([^ ]+\\) -> \\(.*\\)$");
+ if (!name.matches(sym_rx))
+ {
+ nf->type = FT_Unknown;
+ break;
+ }
+
+ nf->type = FT_Link;
+ sym_rx.match_info(start, len, 1);
+ nf->name = string(name.at(start, len));
+ sym_rx.match_info(start, len, 2);
+ nf->link = string(name.at(start, len));
+ }
+ break;
+ default:
+ nf->type = FT_Unknown;
+ }
+
+ ls_rx->match_info(start, len, 2);
+ string sz_str(line.at(start, len));
+ nf->size = strtol(sz_str, NULL, 10);
+
+ ls_rx->match_info(start, len, 3);
+ string date_str(line.at(start, len));
+ nf->time = parsedate(date_str, timezone);
+ nf->next = NULL;
+
+ struct tm *tm = gmtime(&nf->time);
+ cout << "Name " << nf->name << " size " << nf->size <<
+ " date " << asctime(tm);
+
+ return nf;
+}
+
+const string &
+unix_host::hosttype() const
+{
+ static const string ux("unix");
+
+ return ux;
+}
Added: trunk/filesystems/ftpfs/dir.h
==============================================================================
--- trunk/filesystems/ftpfs/dir.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/ftpfs/dir.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,57 @@
+// -*- C++ -*-
+
+// Directory inodes
+// This contains the basic sync mechanisms for priming from a disk
+// filesystem, and for serializing access to a single inode
+
+// (C) Copyright 1994 Jeremy Fitzhardinge <jeremy at sw.oz.au>
+// This code is distributed under the terms of the
+// GNU General Public Licence. See COPYING for more details.
+
+#ifndef _DIR_H_
+#define _DIR_H_
+
+#pragma interface
+
+#include <DirInode.h>
+#include <string>
+#include <LWP.h>
+#include "Path.h"
+
+class ftpfs;
+class ftpconn;
+
+class dir: public DirInode
+{
+ int do_iput(const up_preamble &, upp_repl &, const upp_iput_s &);
+
+ void beforeop(up_ops);
+ void afterop(up_ops);
+
+ Semaphore sem;
+
+protected:
+ Path name;
+
+ virtual Inode *newinode(dir *, const struct stat *, const string &) = 0;
+
+ ftpfs &filesys;
+ dir *parent;
+public:
+ dir(ftpfs &fs, const string &name, dir *up);
+
+ string path() const { return name.path(); }
+
+ virtual int depth() const
+ {
+ if (parent && parent != this)
+ return parent->depth() + 1;
+ return 0;
+ }
+
+ int open();
+ const Path &getname() const { return name; }
+ void init();
+};
+
+#endif /* _FTPDIR_H_ */
Added: trunk/filesystems/ftpfs/dos_host.h
==============================================================================
--- trunk/filesystems/ftpfs/dos_host.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/ftpfs/dos_host.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,30 @@
+// -*- C++ -*-
+
+// DOS host information
+
+// (C) Copyright 1994 Jeremy Fitzhardinge <jeremy at sw.oz.au>
+// This code is distributed under the terms of the
+// GNU General Public Licence. See COPYING for more details.
+
+// Dos ftp server support by marcus at ee.pdx.edu (Marcus Daniels)
+
+#ifndef _DOS_HOST_H_
+#define _DOS_HOST_H_
+
+#pragma interface
+
+#include "host.h"
+#include <sys/socket.h>
+#include <string>
+#include <netinet/in.h>
+
+class dos_host: public host
+{
+ int pathsteps(const string &, string *steps[]);
+ time_t localtime(struct sockaddr_in);
+ struct ftp_filelist *parse_filelist(const string &, time_t);
+ const string &hosttype() const;
+ const string &wildcard() const;
+};
+
+#endif /* _DOS_HOST_H_ */
Added: trunk/filesystems/ftpfs/ftpfs.h
==============================================================================
--- trunk/filesystems/ftpfs/ftpfs.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/ftpfs/ftpfs.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,46 @@
+// -*- C++ -*-
+
+// (C) Copyright 1994 Jeremy Fitzhardinge <jeremy at sw.oz.au>
+// This code is distributed under the terms of the
+// GNU General Public Licence. See COPYING for more details.
+
+#ifndef _FTPFS_H_
+#define _FTPFS_H_
+
+#pragma interface
+
+#include <Filesystem.h>
+#include <string>
+
+// Thread priorities for different classes of threads
+// Operations should be quick, so they get timely response.
+// UPD_TPRI is higher than COM_TPRI, but it blocks itself to be
+// woken by the comm thread, so its really lower priority...
+#define OPS_TPRI 7 // Doing operations
+#define UPD_TPRI 5 // Updating a file (bulk FTP transfer)
+#define COM_TPRI 4 // Waiting for select input
+
+class ftpfs : public Filesystem
+{
+ string cache;
+
+ Handle hcount;
+
+ Inode *root;
+
+public:
+ ftpfs(const char *mpoint, const string &cache);
+ ~ftpfs();
+
+ const uid_t uid;
+ const gid_t gid;
+
+ int do_mount(const up_preamble &, upp_repl &,
+ upp_mount_r &ret);
+
+ int Enquire(up_ops);
+
+ Handle genhand() { return hcount++; }
+};
+
+#endif /* _FTPFS_H_ */
Added: trunk/filesystems/ftpfs/ConfFile.cc
==============================================================================
--- trunk/filesystems/ftpfs/ConfFile.cc 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/ftpfs/ConfFile.cc 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,185 @@
+// -*- C++ -*-
+
+// Config file handling
+
+// (C) Copyright 1994 Jeremy Fitzhardinge <jeremy at sw.oz.au>
+// This code is distributed under the terms of the
+// GNU General Public Licence. See COPYING for more details.
+
+#pragma implementation
+
+#include "ConfFile.h"
+#include "pushd.h"
+
+#include <string>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include <fstream.h>
+#include <strstream.h>
+
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <regex.h>
+
+ConfFile::ConfFile(const Path &path)
+ :name(path)
+{
+ list = NULL;
+
+ parse();
+ changed = 0;
+}
+
+ConfFile::~ConfFile()
+{
+ unparse();
+ for(list_t *next; list; list = next)
+ {
+ next = list->next;
+ delete list;
+ }
+}
+
+void
+ConfFile::unparsestr(string &s) const
+{
+ for(const list_t *p = list; p != NULL; p = p->next)
+ s += p->name + ": " + p->val + "\n";
+}
+
+void
+ConfFile::unparse()
+{
+ if (!changed)
+ return;
+
+ string path = name.path();
+ ofstream out(path.data(), ios::out|ios::trunc, 0644);
+
+ if (out.bad())
+ {
+ cout << "Failed to open config file " << path << "\n";
+ return;
+ }
+
+ string s;
+ unparsestr(s);
+ out << s;
+
+ changed = 0;
+}
+
+void
+ConfFile::parseline(const string &line)
+{
+ string &mline = (string &)line;
+
+ if (line[0] == '#')
+ return;
+
+regex_t regex;
+regmatch_t matches[2];
+
+if (regcomp(®ex, "^\\([a-zA-Z_]+\\):[ \t]*\\(.*\\)$", 0)==0)
+{
+ if (regexec(®ex, line.data(), 2, matches,0)!=REG_NOMATCH)
+ {
+ if (matches[0].rm_so!=-1 && matches[1].rm_so!=-1)
+ {
+ string n(mline.substr(matches[0].rm_so, matches[0].rm_eo+1));
+ string v(mline.substr(matches[1].rm_so, matches[1].rm_eo+1));
+ set(n, v);
+ }
+ }
+ regfree(®ex);
+}
+
+}
+
+void
+ConfFile::parse()
+{
+ char *dat;
+ int ret;
+ string path = name.path();
+ ifstream in(path.data(), ios::in, 0664);
+
+ if (in.bad())
+ return;
+ dat = (char *)malloc(200);
+ while(!in.eof())
+ {
+ in.getline(dat, 200);
+ const string line(dat);
+ parseline(line);
+ }
+ free(dat);
+}
+
+ConfFile::list_t *
+ConfFile::find(const string &name) const
+{
+ list_t *p;
+
+ for(p = list; p != NULL; p = p->next)
+ if (name == p->name)
+ return p;
+ return NULL;
+}
+
+int
+ConfFile::get(const string &name, string &val) const
+{
+ list_t *p;
+
+ if ((p = find(name)) == NULL)
+ return 0;
+ val = p->val;
+ return 1;
+}
+
+void
+ConfFile::set(const string &name, const string &val)
+{
+ list_t *p;
+
+ p = find(name);
+
+ if (p == NULL)
+ {
+ p = new list_t;
+ p->name = name;
+ p->next = list;
+ list = p;
+ }
+ p->val = val;
+
+ changed = 1;
+}
+
+void
+ConfFile::setnum(const string &name, long val)
+{
+ char buf[32];
+ ostrstream str(buf, sizeof(buf));
+
+ str << val << '\0';
+
+ set(name, string(buf));
+}
+
+int
+ConfFile::getnum(const string &name, long &val) const
+{
+ string v;
+
+ if (!get(name, v))
+ return 0;
+
+ val = atol(v.data());
+
+ return 1;
+}
Added: trunk/filesystems/ftpfs/sitetopdir.cc
==============================================================================
--- trunk/filesystems/ftpfs/sitetopdir.cc 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/ftpfs/sitetopdir.cc 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,22 @@
+// -*- C++ -*-
+
+// Top directory of an FTP site
+
+// (C) Copyright 1994 Jeremy Fitzhardinge <jeremy at sw.oz.au>
+// This code is distributed under the terms of the
+// GNU General Public Licence. See COPYING for more details.
+
+#pragma implementation
+
+#include "sitetopdir.h"
+#include "ftpconn.h"
+#include "ConfFile.h"
+#include "Path.h"
+#include "conninfo.h"
+
+sitetopdir::sitetopdir(ftpfs &fs, string dname, dir *up)
+ :ftpdir(fs, dname, up, NULL, ".ftpfs_site")
+{
+ link(".ftpfs_info", new conninfo(fs, conn));
+}
+
Added: trunk/filesystems/ftpfs/ConfFile.h
==============================================================================
--- trunk/filesystems/ftpfs/ConfFile.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/ftpfs/ConfFile.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,52 @@
+// -*- C++ -*-
+
+// Configuration file handling
+// This class handles reading and writing config files
+// with simple name-value pairs.
+
+// (C) Copyright 1994 Jeremy Fitzhardinge <jeremy at sw.oz.au>
+// This code is distributed under the terms of the
+// GNU General Public Licence. See COPYING for more details.
+
+#ifndef _CONFFILE_H_
+#define _CONFFILE_H_
+
+#pragma interface
+
+#include <string>
+#include <unistd.h>
+#include "Path.h"
+
+class ConfFile
+{
+ int changed;
+
+ void parse();
+ void unparse();
+
+ Path name;
+
+ struct list_t
+ {
+ list_t *next;
+ string name;
+ string val;
+ } *list;
+
+ list_t *find(const string &name) const;
+
+public:
+ ConfFile(const Path &);
+ ~ConfFile();
+
+ void parseline(const string &name);
+ void unparsestr(string &) const;
+
+ void set(const string &name, const string &val);
+ int get(const string &name, string &val) const;
+
+ void setnum(const string &name, long);
+ int getnum(const string &name, long &) const;
+};
+
+#endif /* _CONFFILE_H_ */
Added: trunk/filesystems/ftpfs/ftpfile.cc
==============================================================================
--- trunk/filesystems/ftpfs/ftpfile.cc 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/ftpfs/ftpfile.cc 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,357 @@
+// -*- C++ -*-
+
+// Deal with keeping files up to date and transferring them.
+// Also copes with ordinary FS reads of files. The complexity
+// is in allowing a file to be read as it's being updated without
+// getting problems.
+
+// (C) Copyright 1994 Jeremy Fitzhardinge
+// This code is distributed under the terms of the
+// GNU General Public Licence. See COPYING for more details.
+
+#pragma implementation
+
+#include "ftpfile.h"
+#include "ftpconn.h"
+#include "ftpdir.h"
+#include "ftpfs.h"
+
+#include <LWP.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <utime.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string>
+#include <assert.h>
+#include <stdio.h>
+
+#include <iostream.h>
+
+ftpfile::ftpfile(ftpfs &fs, const string &name, ftpdir *dir, ftpconn *conn)
+ : dir(dir), ino(fs), conn(conn), name(name)
+{
+ fd = -1;
+ updating = 0;
+ wlist = NULL;
+ mode = S_IFREG | 0444;
+ conn->incref();
+ upd_thread = NULL;
+
+ open();
+ if (fd != -1)
+ {
+ struct stat st;
+
+ if (fstat(fd, &st) == 0)
+ {
+ size = st.st_size;
+ mtime = st.st_mtime;
+ }
+ close();
+ }
+}
+
+ftpfile::~ftpfile()
+{
+ if (upd_thread != NULL)
+ delete upd_thread;
+ close();
+ conn->decref();
+}
+
+struct waiting
+{
+ off_t off;
+ Semaphore sem;
+ int err;
+ waiting *next, *prev;
+
+ waiting(off_t, waiting *next);
+};
+
+waiting *
+ftpfile::addwlist(off_t off)
+{
+ waiting *w = new waiting(off, wlist);
+
+ wlist = w;
+
+ return w;
+}
+
+void
+ftpfile::delwlist(waiting *w)
+{
+ if (w->next)
+ w->next->prev = w->prev;
+ if (w->prev)
+ w->prev->next = w->next;
+ else
+ wlist = w->next;
+}
+
+waiting::waiting(off_t off, waiting *n)
+ :off(off), sem(0), next(n)
+{
+ err = 0;
+ next = prev = NULL;
+}
+
+// This class is passed as a callback to the ftpconn method for
+// getting a file
+class docopy: public ftpxfer
+{
+ ftpfile &ftp;
+ off_t last_off;
+ int err;
+
+public:
+ docopy(string path, int cfd, ftpfile &, ftpconn *);
+ ~docopy();
+
+ void notify(int);
+ void error(int e) { err = e; }
+ // Things for passing through the thread args
+ int cfd;
+ string path;
+ ftpconn *conn;
+};
+
+static void
+copy_cache(int, char **, void *v)
+{
+ cout << "update thread starting\n";
+ docopy *dc = (docopy *)v;
+ dc->conn->getfile(dc->path, dc->cfd, dc);
+ delete dc;
+ cout << "update thread finishing\n";
+ suicide();
+ abort();
+}
+
+docopy::docopy(string path, int cfd, ftpfile &f, ftpconn *conn)
+ : ftp(f), cfd(cfd), path(path), conn(conn)
+{
+ assert(ftp.updating == 0);
+ ftp.updating = 1;
+ last_off = 0;
+ err = 0;
+}
+
+docopy::~docopy()
+{
+ assert(ftp.updating == 1);
+ // Wake up everything outstanding
+ for(waiting *w = ftp.wlist; w != NULL; w = w->next)
+ {
+ ftp.delwlist(w);
+ w->err = err;
+ w->sem.signal();
+ delete w;
+ }
+
+ string nm = ftp.dir->path() + "/" + ftp.name;
+ struct utimbuf ut;
+ ut.actime = ftp.atime;
+ ut.modtime = ftp.mtime;
+ utime(nm.data(), &ut);
+
+ ftp.updating = 0;
+ ftp.close();
+}
+
+void
+docopy::notify(int infd)
+{
+ off_t size = lseek(cfd, 0, SEEK_CUR);
+
+ // Force thread change if it wouldn't otherwise.
+ // If we're doing this we re-queue it with a low select
+ // dispatch priority.
+ // If it's yielding a lot because of blocking reads anyhow,
+ // it means other threads get good response
+
+ if (size >= (last_off + 8*1024))
+ {
+ class copyyield: public DispatchFD
+ {
+ Semaphore sem;
+ public:
+ copyyield(): sem(0) {}
+
+ int dispatch(int,int) { sem.signal(); return 0; }
+ void wait() { sem.wait(); }
+ };
+
+ copyyield *cy = new copyyield();
+ ftp.filesys.comm()->addDispatch(infd, cy, DISP_R, 0);
+ cy->wait();
+ last_off = size;
+ }
+ for(waiting *w = ftp.wlist; w != NULL; w = w->next)
+ if (w->off < size)
+ {
+ cout << "passing offset " << w->off <<
+ " at " << size << "\n";
+ ftp.delwlist(w);
+ w->sem.signal();
+ delete w;
+ }
+ ftp.size = size;
+}
+
+void
+ftpfile::decref()
+{
+ if (nlink-- == 0)
+ {
+ string cn = dir->path() + "/" + name;
+ ::unlink(cn.data());
+ delete this;
+ }
+}
+
+int
+ftpfile::is_uptodate() const
+{
+ struct stat st;
+ string cn = dir->path() + "/" + name;
+
+ if (stat((const char *)cn.data(), &st) == 0 &&
+ size == st.st_size &&
+ size != 0)
+ return 1;
+ return 0;
+}
+
+// Start updating file if needed
+// This starts an update thread. Things wanting to read the file should
+// use ftpfile::read, which checks to see if the cache file is being updated.
+// If so, it puts an entry on the waiting list. If the update thread passes
+// a point being waited for by a reading thread, it is woken.
+int
+ftpfile::updatefile()
+{
+ if (updating)
+ return 0;
+
+ if (is_uptodate())
+ return 0;
+
+ string cn = dir->path() + "/" + name;
+ string fn = dir->ftppath() + "/" + name;
+
+ ::unlink(cn.data());
+ close();
+ if (open(1, 0444))
+ return -1;
+
+ // Start cache update thread
+ docopy *dc = new docopy(fn, fd, *this, conn);
+ new LWP(UPD_TPRI, copy_cache, 16*1024, 0, NULL, dc);
+
+ return 0;
+}
+
+/* Open the cache file */
+int
+ftpfile::open(int create, int mode)
+{
+ string cp;
+
+ close();
+ cp = dir->path() + "/" + name;
+ fd = ::open(cp.data(), create ? O_RDWR|O_TRUNC|O_CREAT|O_APPEND : O_RDONLY, mode);
+// cout << "ftpfile::open(" << create << ", " << mode << ") opened " << cp << " fd="<< fd << '\n';
+
+ return fd == -1 ? -1 : 0;
+}
+
+void
+ftpfile::close()
+{
+ ::close(fd);
+ fd = -1;
+}
+
+// Read from the file
+// If the file is being updated from the ftp site, we wait until
+// the update thread says some data we want has arrived. Otherwise,
+// just go direct to the file
+int
+ftpfile::read(unsigned char *buf, size_t sz, off_t off)
+{
+ struct stat st;
+
+ if (fd == -1 && open() == -1)
+ return -1;
+
+ int cfd = dup(fd);
+ if (cfd == -1)
+ ::perror("dup failed");
+ if (fstat(cfd, &st) == -1)
+ {
+ ::perror("fstat failed");
+ return -1;
+ }
+
+ if (updating && off >= st.st_size)
+ {
+ waiting *w = addwlist(off);
+ w->sem.wait();
+ if (w->err != 0)
+ {
+ cout << "read failed in wait: " << strerror(w->err)
+ << '\n';
+ ftruncate(cfd, 0);
+ close();
+ errno = w->err;
+ return -1;
+ }
+ }
+
+ lseek(cfd, off, SEEK_SET);
+ int ret = ::read(cfd, buf, sz);
+ if (ret == -1)
+ perror("read failed");
+ ::close(cfd);
+
+ return ret;
+}
+
+int
+ftpfile::do_iput(const up_preamble &, upp_repl &,
+ const upp_iput_s &arg)
+{
+ if (!updating)
+ close();
+ return 0;
+}
+
+int
+ftpfile::do_read(const up_preamble &, upp_repl &,
+ const upp_read_s &arg, upp_read_r &ret)
+{
+ updatefile();
+
+ unsigned char buf[arg.size];
+ int rd = read(buf, arg.size, arg.off);
+
+ if (rd == -1)
+ return errno;
+
+ ret.data.alloc(rd);
+ ret.data.nelem = rd;
+ memcpy(ret.data.elems, buf, rd);
+
+ return 0;
+}
+
+void
+ftpfile::setstats(size_t sz, time_t time)
+{
+ size = sz;
+ mtime = time;
+}
Added: trunk/filesystems/ftpfs/ftpdir.h
==============================================================================
--- trunk/filesystems/ftpfs/ftpdir.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/ftpfs/ftpdir.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,68 @@
+// -*- C++ -*-
+
+// (C) Copyright 1994 Jeremy Fitzhardinge <jeremy at sw.oz.au>
+// This code is distributed under the terms of the
+// GNU General Public Licence. See COPYING for more details.
+
+#ifndef _FTPDIR_H_
+#define _FTPDIR_H_
+
+#pragma interface
+
+#include "dir.h"
+
+#include <sys/time.h>
+
+class ftpconn;
+
+class ftpdir: public dir
+{
+ void construct();
+ void init();
+
+ void cleanup();
+
+ // Parent dir in ftp site
+ ftpdir *ftpup;
+
+ // Parameters about this dir
+ class ConfFile *conf;
+ time_t last_upd;
+ time_t last_failure;
+
+ // Inode creation
+ Inode *newinode(dir *, const struct stat *, const string &);
+
+ // Resync with FTP site
+ int updatedir(int force = 0);
+ int init_done;
+
+ // Config parameters
+ void getparams();
+ void setparams();
+
+ // Operations
+ int do_readdir(const up_preamble &, upp_repl &,
+ const upp_readdir_s &, upp_readdir_r &);
+ int do_multireaddir(const up_preamble &, upp_repl &,
+ const upp_multireaddir_s &, upp_multireaddir_r &);
+ int do_lookup(const up_preamble &pre, upp_repl &rep,
+ const upp_lookup_s &arg, upp_lookup_r &ret);
+ int do_create(const up_preamble &, upp_repl &,
+ const upp_create_s &, upp_create_r &);
+
+protected:
+ // FTP connection
+ ftpconn *conn;
+
+public:
+ ftpdir(ftpfs &fs, const string &name, dir *up,
+ ftpdir *ftpup, ftpconn *conn);
+ ftpdir(ftpfs &fs, const string &name, dir *up, ftpdir *ftpup,
+ const string &cfname);
+ ~ftpdir();
+
+ string ftppath() const;
+};
+
+#endif /* _FTPDIR_H_ */
Added: trunk/filesystems/intfs/intfsIno.h
==============================================================================
--- trunk/filesystems/intfs/intfsIno.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/intfs/intfsIno.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,40 @@
+// -*- C++ -*-
+
+#ifndef _INTFSINO_H_
+#define _INTFSINO_H_
+
+#pragma interface
+
+#include <SimpleInode.h>
+#include <string>
+
+class intfs;
+class ifsDirIno;
+
+class ifsIno: public SimpleInode
+{
+protected:
+ intfs &filesys;
+
+ const string name;
+ string link;
+ ifsDirIno *dir;
+
+ int do_readlink(const up_preamble &, upp_repl &,
+ const upp_readlink_s &, upp_readlink_r &);
+ int do_followlink(const up_preamble &, upp_repl &,
+ const upp_followlink_s &, upp_followlink_r &);
+ int do_write(const up_preamble &, upp_repl &,
+ const upp_write_s &, upp_write_r &);
+
+ void update();
+
+ int open(int mode);
+
+public:
+ string path();
+ ifsIno(intfs &fs, Handle hand, ifsDirIno *, string name, string link);
+ ~ifsIno();
+};
+
+#endif /* _INTFSINO_H_ */
Added: trunk/filesystems/intfs/intfsFifoIno.cc
==============================================================================
--- trunk/filesystems/intfs/intfsFifoIno.cc 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/intfs/intfsFifoIno.cc 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,165 @@
+// -*- C++ -*-
+
+// An inode with a command behind it
+// These are transient, and only exist long enough to be opened.
+// They go away once they have been put, never to be seen again.
+// The contents are only generated if they are actually read.
+
+#pragma implementation
+
+#include "intfsFifoIno.h"
+#include "intfsFifoDir.h"
+#include "intfsDirIno.h"
+#include "intfs.h"
+
+#include "dbg.h"
+
+#include <DeferComm.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <time.h>
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+
+ifsFifoIno::ifsFifoIno(intfs &fs, string command, ifsDirIno *dir)
+ : SimpleInode(fs, fs.genhand()),
+ command(command), dir(dir), filesys(fs)
+{
+ atime = ctime = mtime = time(0);
+ mode = S_IFIFO | 0444;
+ pid = -1;
+ readfd = -1;
+
+ name = filesys.getfifod()->create(this);
+ named = 1;
+
+ DB(printf("ifsFifoIno::ifsFifoIno, linked into fifod name=%s, command=%s\n",
+ (const char *)name, (const char *)command));
+}
+
+ifsFifoIno::~ifsFifoIno()
+{
+ unname();
+ ::close(readfd);
+ readfd = -1;
+// if (pid > 0)
+// ::kill(pid, SIGTERM);
+// pid = -1;
+}
+
+void
+ifsFifoIno::unname()
+{
+ if (named)
+ filesys.getfifod()->unlink(name);
+ named = 0;
+}
+
+int
+ifsFifoIno::do_open(const up_preamble &, upp_repl &,
+ const upp_open_s &arg, upp_open_r &ret)
+{
+ LOG("ifsFifoIno::do_open");
+ unname();
+
+ uid = arg.cred.uid;
+ euid = arg.cred.euid;
+ gid = arg.cred.gid;
+ egid = arg.cred.egid;
+
+ return 0;
+}
+
+int
+ifsFifoIno::do_iput(const up_preamble &, upp_repl &,
+ const upp_iput_s &)
+{
+ LOG("ifsFifoIno::do_iput");
+
+ delete this;
+ return 0;
+}
+
+int
+ifsFifoIno::start()
+{
+ int pfd[2];
+
+ if (pipe(pfd) == -1)
+ return errno;
+
+ signal(SIGCHLD, SIG_IGN);
+
+ switch(pid = fork())
+ {
+ case -1:
+ return errno;
+ case 0:
+ close(0);
+ close(1);
+ close(2);
+ close(pfd[0]);
+ filesys.comm()->CloseFDs(1);
+
+ open("/dev/null", O_RDWR);
+ dup(pfd[1]);
+ dup(pfd[1]);
+ close(pfd[1]);
+
+ int dfd = dir->dupfd();
+ fchdir(dfd);
+ close(dfd);
+
+ setreuid(uid, euid);
+ setregid(gid, egid);
+
+ signal(SIGTERM, SIG_DFL);
+
+ execlp("/bin/sh", "/bin/sh", "-c", (const char *)command, 0);
+ fprintf(stderr, "exec of /bin/sh -c %s failed: %s\n",
+ (const char *)command, strerror(errno));
+ exit(1);
+ }
+
+ close(pfd[1]);
+ readfd = pfd[0];
+
+ return 0;
+}
+
+int
+ifsFifoIno::do_read(const up_preamble &, upp_repl &,
+ const upp_read_s &arg, upp_read_r &data)
+{
+ int ret;
+
+ LOG("ifsFifoIno::do_read");
+
+ if (pid == -1 && (ret = start()) != 0)
+ return ret;
+
+ int dpid = filesys.comm()->DeferRepl();
+
+ if (dpid != -1 && dpid != 0)
+ return -1;
+
+ char buf[1024];
+ off_t sz = arg.size > sizeof(buf) ? sizeof(buf) : arg.size;
+
+ while((ret = read(readfd, buf, sz)) == -1)
+ if (errno != EINTR)
+ return errno;
+
+ if (ret > 0)
+ {
+ data.data.alloc(ret);
+ memcpy(data.data.elems, buf, ret);
+ }
+ data.data.nelem = ret;
+
+ return 0;
+}
Added: trunk/filesystems/intfs/intfsFifoIno.h
==============================================================================
--- trunk/filesystems/intfs/intfsFifoIno.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/intfs/intfsFifoIno.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,48 @@
+// -*- C++ -*-
+
+#ifndef _INTFSFIFOINO_H_
+#define _INTFSFIFOINO_H_
+
+#pragma interface
+
+#include <string>
+#include <SimpleInode.h>
+
+#include <sys/types.h>
+
+class intfs;
+class ifsDirIno;
+
+class ifsFifoIno: public SimpleInode
+{
+ string command;
+ ifsDirIno *dir;
+ string name;
+
+ pid_t pid;
+ int readfd;
+ int named;
+
+ int start();
+ void unname();
+
+ uid_t uid, euid;
+ gid_t gid, egid;
+
+protected:
+ intfs &filesys;
+
+ int do_open(const up_preamble &, upp_repl &,
+ const upp_open_s &, upp_open_r &);
+ int do_iput(const up_preamble &, upp_repl &,
+ const upp_iput_s &);
+ int do_read(const up_preamble &, upp_repl &,
+ const upp_read_s &, upp_read_r &);
+public:
+ ifsFifoIno(intfs &, string command, ifsDirIno *dir);
+ ~ifsFifoIno();
+
+ string getname() const { return name; }
+};
+
+#endif /* _INTFSFIFOINO_H_ */
Added: trunk/filesystems/intfs/intfsLinkIno.cc
==============================================================================
--- trunk/filesystems/intfs/intfsLinkIno.cc 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/intfs/intfsLinkIno.cc 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,46 @@
+// -*- C++ -*-
+
+// Inode for symbolic links in intfs filesystem
+
+#pragma implementation
+
+#include "intfsLinkIno.h"
+#include "intfsFifoIno.h"
+#include "intfsDirIno.h"
+
+#include "dbg.h"
+
+ifsLinkIno::ifsLinkIno(intfs &fs, Handle hand, ifsDirIno *dir, string name, string link)
+ : ifsIno(fs, hand, dir, name, link)
+{
+}
+
+ifsLinkIno::~ifsLinkIno()
+{
+}
+
+int
+ifsLinkIno::do_followlink(const up_preamble &pre, upp_repl &rep,
+ const upp_followlink_s &arg, upp_followlink_r &ret)
+{
+ LOG("ifsLinkIno::do_followlink");
+
+ if (link(NULL,2) != "#!")
+ return ifsIno::do_followlink(pre, rep, arg, ret);
+
+ ifsFifoIno *ino = new ifsFifoIno(filesys, link.after(1), dir);
+
+ string p;
+
+ cat(dir->toppath(), "/.fifo/", ino->getname(), p);
+ int len = p.length();
+
+ DB(printf("ifsLinkIno::do_followlink returning link to %s\n",
+ (const char *)p.data()));
+
+ ret.path.alloc(len);
+ ret.path.nelem = len;
+ memcpy(ret.path.elems, (const char *)p.data(), len);
+
+ return 0;
+}
Added: trunk/filesystems/intfs/README
==============================================================================
--- trunk/filesystems/intfs/README 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/intfs/README 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,85 @@
+intfs - filesystem for intensional files.
+
+This filesystem allows file contents to be expressed in terms of
+programs to generate the contents. It allows simple user space
+filesystems to be constructed without the effort of having
+to write a full userfs filesystem.
+
+To mount, use
+ muserfs intfs <mount-point> <base-dir>
+
+The <base-dir> is a directory tree which is to be mirrored. The intfs
+filesystem will appear as a tree of directories in the same shape as
+the base directory, except containing symlinks to the original files
+rather than images of them. Symlinks in the base directory tree appear
+unchanged in the mirrored tree (that is, the link contents point to the
+same place).
+
+Normally a symlink contains a pathname to another file or symlink,
+relative to the directory containing the symlink. In this case, if
+the symlink points to a path starting with "#!", the rest of the path
+is treated as a script for /bin/sh. When the file is read, the
+command is actually executed, and the stdout and stderr is read as the
+file contents. If you do a fstat on the open file descriptor, it
+appears to be a pipe or fifo file.
+
+For example (commands typed in a mounted intfs filesystem):
+$ ls -l
+lrwxrwxrwx 1 jeremy users 16 May 13 19:58 file.gz -> /usr/tmp/file.gz
+lrwxrwxrwx 1 jeremy users 14 May 13 19:58 file -> #!zcat file.gz
+$ cat file
+This is a compressed file
+
+So, as you see, file contents can be generated on demand.
+
+HOW IT WORKS
+
+This works by having different code for the up_readlink and
+up_followlink operations. Normally, reading the link gives you the
+literal path of the file which is being referred to. However, it is
+possible to have a symlink which goes to a different place when
+followed than would appear from reading it.
+
+A userfs filesystem still has to return a pathname for a file as a
+result of a up_followlink operation, so intfs has a special directory
+".fifo" in the mount directory which contains transient FIFO files.
+When a normal link is followed, intfs just returns the link contents
+as read by readlink. For intensional links (those starting with
+'#!'), it returns a relative path to a fifo file in .fifo. The fifo
+file only exists in the directory for a very short time: it is removed
+when that path is opened or when the inode is "iput", which ever comes
+first. Therefore, if the link is being followed for opening, it can
+be opened once before the name disappears. If the link is followed
+for something else, like a stat, it will be "iput" immediately,
+without ever being read.
+
+There is a race-condition: if an intensional file is being stat'd,
+then it does appear in .fifo, so something else could open it and
+read it.
+
+If intfs can (if its running as root), it tries to execute the command
+with the permissions of the program reading the file. It gets these
+permissions from the credentials passed when the file is opened.
+Because the filename is removed from .fifos as soon as it is opened,
+nothing else can open the file and get the output of the program
+executing for another user. The program is run with the same
+environment as intfs, with a current directory in the corresponding
+place in the base filesystem.
+
+This is an experimental filesystem, and so has some problems. In
+paritcular, it doesn't keep track of the underlying filesystem changes
+very well, so its best to do all the file rename/deletion/ creation
+through the intfs filesystem.
+
+THe basic idea for intfs came from Paul Eggert and D. Stott Parker's
+paper in the 1992 Usenix File Systems Workshop Proceedings, which
+presented IFS0, a filesystem having properties similar to intfs, but
+implemented in SunOS shared libraries. They followed this work up
+with the IFS1 filesystem, presented in the Usenix Winter 1993
+Technical Conference proceedings. The library approach is probably
+more suited for this filesystem than using userfs, but I had userfs
+and haven't found out how to make Linux shared libraries, so here it
+is.
+
+ Jeremy Fitzhardinge
+ jeremy at sw.oz.au
Added: trunk/filesystems/intfs/intfsLinkIno.h
==============================================================================
--- trunk/filesystems/intfs/intfsLinkIno.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/intfs/intfsLinkIno.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,23 @@
+// -*- C++ -*-
+
+#ifndef _INTFSLINKINO_H_
+#define _INTFSLINKINO_H_
+
+#pragma interface
+
+#include <string>
+#include "intfsIno.h"
+
+class ifsLinkIno: public ifsIno
+{
+protected:
+ int do_followlink(const up_preamble &, upp_repl &,
+ const upp_followlink_s &, upp_followlink_r &);
+public:
+ ifsLinkIno(intfs &fs, Handle hand, ifsDirIno *,
+ string name, string link);
+ ~ifsLinkIno();
+
+};
+
+#endif /* _INTFSLINKINO_H_ */
Added: trunk/filesystems/intfs/pushd.cc
==============================================================================
--- trunk/filesystems/intfs/pushd.cc 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/intfs/pushd.cc 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,31 @@
+// -*- C++ -*-
+
+// PushD/PopD operations
+
+#include "pushd.h"
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+
+pushd::pushd(int dir)
+{
+ int fd = open(".", O_RDONLY);
+
+ if (fd == -1 || fchdir(dir) == -1)
+ {
+ fprintf(stderr, "pushd::pushd() open or fchdir failed");
+ return;
+ }
+
+ old = fd;
+}
+
+pushd::~pushd()
+{
+ fchdir(old);
+ close(old);
+}
+
+
Added: trunk/filesystems/intfs/intfs.cc
==============================================================================
--- trunk/filesystems/intfs/intfs.cc 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/intfs/intfs.cc 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,130 @@
+// -*- C++ -*-
+
+// Intensive filesystem - the opposite of an extensive filesystem.
+
+// The basic idea is that rather than having file which literally
+// describe their contents, we have files which can describe how their
+// contents are built.
+
+// This is done by having symbolic links which contain strings of
+// shell commands rather than literal file names. Such links are
+// identified by having the 1st 2 characters "#!".
+
+// The filesystem is a layer over another filesystem to provide this
+// functionality. For each normal file in the base filesystem there
+// is a symbolic link in the intfs filesystem. Symbolic links in
+// the base filesystem appear literally in the intfs. Normal
+// symlinks are treated normally, but ones with command syntax are
+// interpreted to generate the contents of the file. In such cases
+// the readlink operation returns the command, but followlink returns
+// the name of the temp file or named pipe with the actual contents
+// of the file.
+
+#pragma implementation
+
+#include <DeferComm.h>
+#include <GetOpt.h>
+#include <stdio.h>
+
+#include "intfs.h"
+#include "intfsDirIno.h"
+#include "intfsFifoDir.h"
+
+#include "dbg.h"
+
+int
+intfs::Enquire(up_ops op)
+{
+ switch(op)
+ {
+ case up_mount:
+ case up_iread:
+ case up_readdir:
+ case up_multireaddir:
+ case up_lookup:
+ case up_readlink:
+ case up_followlink:
+ case up_unlink:
+ case up_rename:
+ case up_create:
+ case up_symlink:
+ case up_iput:
+// case up_iwrite:
+ case up_read:
+ case up_write:
+ case up_open:
+ case up_close:
+ return 0;
+
+ default:
+ return DeferFilesys::Enquire(op);
+ }
+}
+
+intfs::intfs(const char *mpoint, string base)
+ : DeferFilesys(mpoint), base(base)
+{
+ inocnt = 2;
+ root = new ifsDirIno(*this, genhand(), NULL, base);
+ fifod = new ifsFifoDir(*this, genhand(), root);
+ root->link(".fifo", fifod);
+}
+
+intfs::~intfs()
+{
+}
+
+int
+intfs::do_mount(const up_preamble &, upp_repl &, upp_mount_r &ret)
+{
+ ret.root.handle = root->gethandle();
+ return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+ GetOpt getopt(argc, argv, "i:o:m:");
+ int optch, err = 0;
+ int infd, outfd;
+ const char *mpoint = "";
+ const char *base;
+
+ infd = outfd = -1;
+ while((optch = getopt()) != EOF)
+ switch(optch)
+ {
+ case 'i':
+ infd = atoi(getopt.optarg);
+ break;
+ case 'o':
+ outfd = atoi(getopt.optarg);
+ break;
+ case 'm':
+ mpoint = getopt.optarg;
+ break;
+ default:
+ err++;
+ }
+
+ if (err || infd == -1 || outfd == -1 || getopt.optind == argc)
+ {
+ fprintf(stderr, "Usage: %s -i infd -o outfd -m mpoint basedir\n",
+ argv[0]);
+ exit(1);
+ }
+
+ base = argv[getopt.optind];
+
+#if 0 && DEBUG
+ printf("pid=%d, return to cont\n", getpid());
+ getchar();
+#endif
+ intfs ifs(mpoint, base);
+ DeferComm comm(ifs, outfd, infd);
+
+ if (comm.Run() == -1)
+ fprintf(stderr, "%s: Comm.Run() failed!\n", argv[0]);
+
+ return 0;
+}
Added: trunk/filesystems/intfs/intfs.h
==============================================================================
--- trunk/filesystems/intfs/intfs.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/intfs/intfs.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,34 @@
+// -*- C++ -*-
+
+#ifndef _INTFS_H_
+#define _INTFS_H_
+
+#pragma interface
+
+#include <DeferFilesys.h>
+#include <string>
+
+class ifsDirIno;
+class ifsFifoDir;
+
+class intfs : public DeferFilesys
+{
+ const string base;
+ ifsDirIno *root;
+ ifsFifoDir *fifod;
+
+ Handle inocnt;
+
+protected:
+ int Enquire(up_ops);
+
+ int do_mount(const up_preamble &, upp_repl &, upp_mount_r &);
+public:
+ Handle genhand() { return inocnt++; }
+ intfs(const char *mpoint, string base);
+ ~intfs();
+
+ ifsFifoDir *getfifod() const { return fifod; }
+};
+
+#endif /* _INTFS_H_ */
Added: trunk/filesystems/intfs/pushd.h
==============================================================================
--- trunk/filesystems/intfs/pushd.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/intfs/pushd.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,15 @@
+// -*- C++ -*-
+
+#ifndef _PUSHD_H_
+#define _PUSHD_H_
+
+class pushd
+{
+ int old;
+
+public:
+ pushd(int fd);
+ ~pushd();
+};
+
+#endif /* _PUSHD_H_ */
Added: trunk/filesystems/intfs/intfsFifoDir.cc
==============================================================================
--- trunk/filesystems/intfs/intfsFifoDir.cc 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/intfs/intfsFifoDir.cc 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,65 @@
+// -*- C++ -*-
+
+#pragma implementation
+
+#include "intfs.h"
+#include "intfsFifoDir.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <errno.h>
+#include <stdio.h>
+
+#include "dbg.h"
+
+ifsFifoDir::ifsFifoDir(intfs &fs, Handle hand, DirInode *parent)
+ :DirInode(fs, hand, parent, 30)
+{
+ count = 0;
+
+ uid = 0;
+ gid = 0;
+ mode = S_IFDIR | S_ISVTX | 0555;
+ mtime = ctime = time(0);
+}
+
+ifsFifoDir::~ifsFifoDir()
+{
+}
+
+string
+ifsFifoDir::create(Inode *ino)
+{
+ char buf[20];
+
+ sprintf(buf, "C%d", count++);
+
+ string n(buf);
+
+ link(n, ino);
+
+ DB(printf("ifsFifoDir::create linked inode to %s\n", (const char *)n));
+ return n;
+}
+
+int
+ifsFifoDir::do_unlink(const up_preamble &, upp_repl &,
+ const upp_unlink_s &)
+{
+ return EPERM;
+}
+
+int
+ifsFifoDir::do_link(const up_preamble &, upp_repl &,
+ const upp_link_s &)
+{
+ return EPERM;
+}
+
+int
+ifsFifoDir::do_rename(const up_preamble &, upp_repl &,
+ const upp_rename_s &)
+{
+ return EPERM;
+}
Added: trunk/filesystems/intfs/intfsDirIno.cc
==============================================================================
--- trunk/filesystems/intfs/intfsDirIno.cc 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/intfs/intfsDirIno.cc 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,318 @@
+// -*- C++ -*-
+
+// Cope with directories in an intfs filesystem
+
+#pragma implementation
+
+#include "intfsDirIno.h"
+#include "intfsLinkIno.h"
+#include "intfsIno.h"
+#include "intfs.h"
+
+#include "pushd.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "readdir.h"
+
+#include "dbg.h"
+
+ifsDirIno::ifsDirIno(intfs &fs, Handle hand,
+ ifsDirIno *parent, string dirname)
+ :DirInode(fs, hand, parent == NULL ? this : parent, 30),
+ name(dirname), dotdot(parent == NULL ? this : parent),
+ filesys(fs)
+{
+ fd = -1;
+ mtime = atime = ctime = 0;
+ updating = 0;
+
+ open();
+ struct stat st;
+
+ if (fstat(fd, &st) != -1)
+ {
+ mode = st.st_mode;
+ uid = st.st_uid;
+ gid = st.st_gid;
+ }
+ close();
+}
+
+ifsDirIno::~ifsDirIno()
+{
+ close();
+}
+
+string ifsDirIno::toppath()
+{
+ ifsDirIno *p;
+ string ret = ".";
+
+ for(p = this; p != NULL && p->dotdot != p; p = p->dotdot)
+ {
+ string n;
+ cat("../", ret, n);
+ ret = n;
+ }
+
+ return ret;
+}
+
+string ifsDirIno::path()
+{
+ string p = name;
+
+ if (dotdot && dotdot != this)
+ cat(dotdot->path(), "/", p, p);
+
+ return p;
+}
+
+void ifsDirIno::update()
+{
+ struct dirent de;
+ int ret;
+
+ if (updating)
+ return;
+ updating = 1;
+
+ if ((ret = open()))
+ {
+ DB(fprintf(stderr, "ifsDirIno::update open failed: %s\n", strerror(ret)));
+ updating = 0;
+ return;
+ }
+
+ struct stat st;
+
+ if (fstat(fd, &st) == -1)
+ {
+ DB(perror("ifsDirIno::update stat failed"));
+ close();
+ updating = 0;
+ return;
+ }
+
+ atime = st.st_atime;
+ ctime = st.st_ctime;
+ uid = st.st_uid;
+ gid = st.st_gid;
+ mode = st.st_mode;
+
+ if (st.st_mtime == mtime)
+ {
+ close();
+ updating = 0;
+ return;
+ }
+
+ mtime = st.st_mtime;
+
+ pushd here(fd);
+
+ while((ret = readdir(fd, &de, 1)) > 0)
+ {
+ if (lstat(de.d_name, &st) == -1)
+ continue;
+
+ string entname(de.d_name, de.d_reclen);
+
+ DirEntry *dent = lookup(entname);
+
+ if (dent == NULL)
+ {
+ Inode *ino;
+
+ if (S_ISLNK(st.st_mode))
+ {
+ char buf[256];
+ int len;
+
+ DB(printf("%s is a link\n",
+ (const char *)entname.data()));
+ if ((len = readlink((const char *)entname.data(),
+ buf, sizeof(buf))) == -1)
+ continue;
+ ino = new ifsLinkIno(filesys,
+ filesys.genhand(),
+ this, entname,
+ string(buf, len));
+ }
+ else if (S_ISDIR(st.st_mode))
+ {
+ DB(printf("%s is a directory\n",
+ (const char *)entname.data()));
+ ino = new ifsDirIno(filesys, filesys.genhand(),
+ this, entname);
+ }
+ else
+ {
+ string str;
+// DB(printf("%s is a file\n",
+// (const char *)entname));
+ cat(path(), "/", entname, str);
+ ino = new ifsIno(filesys,
+ filesys.genhand(),
+ this, entname, str);
+ }
+ link(entname, ino);
+ }
+ else
+ ((ifsDirIno *)dent->geti())->update();
+ }
+ if (ret != 0)
+ DB(perror("ifsDirIno::update, readdir failed"));
+ updating = 0;
+ close();
+}
+
+int
+ifsDirIno::open()
+{
+ string p = path();
+
+ fd = ::open(p.data(), O_RDONLY);
+ int err = errno;
+
+ return (fd == -1) ? err : 0;
+}
+
+void
+ifsDirIno::close()
+{
+ ::close(fd);
+ fd = -1;
+}
+
+int
+ifsDirIno::dupfd()
+{
+ int fl = 0;
+
+ if (fd == -1)
+ {
+ fl = 1;
+ open();
+ }
+
+ int ret = dup(fd);
+
+ if (fl)
+ close();
+ return ret;
+}
+
+int
+ifsDirIno::do_unlink(const up_preamble &, upp_repl &,
+ const upp_unlink_s &arg)
+{
+ LOG("ifsDirIno::do_unlink");
+ int ret;
+
+ if (ret = open())
+ return ret;
+
+ pushd here(fd);
+ close();
+
+ string file((const char *)arg.name.elems, (int)arg.name.nelem);
+ DirEntry *de = lookup(file);
+
+ if (S_ISDIR(((ifsDirIno *)de->geti())->mode))
+ {
+ if (::rmdir((const char *)file.data()) == -1)
+ ret = errno;
+ }
+ else
+ {
+ if (::unlink((const char *)file.data()) == -1)
+ ret = errno;
+ }
+
+ if (ret == 0 || ret == ENOENT)
+ ret = unlink(string((const char *)arg.name.elems,
+ (int)arg.name.nelem));
+ return ret;
+}
+
+int ifsDirIno::do_symlink(const up_preamble &, upp_repl &, const upp_symlink_s &arg)
+{
+ open();
+ pushd here(fd);
+ string name((const char *)arg.name.elems, (int)arg.name.nelem);
+ string link((const char *)arg.symname.elems, (int)arg.symname.nelem);
+
+ if (::symlink((const char *)link.data(), (const char *)name.data()) == -1)
+ return errno;
+ return 0;
+}
+
+int ifsDirIno::do_create(const up_preamble &, upp_repl &,
+ const upp_create_s &arg, upp_create_r &ret)
+{
+ open();
+ pushd here(fd);
+ close();
+ string name((const char *)arg.name.elems, (int)arg.name.nelem);
+ Inode *ino;
+ string str;
+ Handle hand = filesys.genhand();
+
+ cat(path(), "/", name, str);
+
+ if (S_ISREG(arg.mode))
+ {
+ int fd = ::open((const char *)name.data(),
+ O_TRUNC|O_CREAT|O_RDONLY, arg.mode);
+ if (fd == -1)
+ return errno;
+ ::close(fd);
+ ino = new ifsIno(filesys, hand, this, name, str);
+ }
+ else if (S_ISDIR(arg.mode))
+ {
+ if (::mkdir((const char *)name.data(), arg.mode) == -1)
+ return errno;
+ ino = new ifsDirIno(filesys, hand, this, name);
+ }
+ else
+ {
+ if (::mknod((const char *)name.data(), arg.mode, arg.rdev) == -1)
+ return errno;
+ ino = new ifsIno(filesys, hand, this, name, str);
+ }
+
+ link(name, ino);
+
+ ret.file.handle = ino->gethandle();
+ return 0;
+}
+
+int
+ifsDirIno::do_rename(const up_preamble &pre, upp_repl &rep,
+ const upp_rename_s &arg)
+{
+ open();
+ pushd here(fd);
+ close();
+
+ string oname((const char *)arg.oname.elems, (int)arg.oname.nelem);
+ string nname((const char *)arg.nname.elems, (int)arg.nname.nelem);
+ ifsDirIno *ndir = (ifsDirIno *)findino(arg.ndir.handle);
+ string npath;
+
+ cat(ndir->path(), "/", nname, npath);
+
+ DB(printf("renaming from %s to %s\n",
+ (const char *)oname.data(), (const char *)npath.data()));
+
+ if (::rename((const char *)oname.data(), (const char *)npath.data()) == -1)
+ return errno;
+
+ return DirInode::do_rename(pre, rep, arg);
+}
+
Added: trunk/filesystems/intfs/intfsFifoDir.h
==============================================================================
--- trunk/filesystems/intfs/intfsFifoDir.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/intfs/intfsFifoDir.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,32 @@
+// -*- C++ -*-
+
+#ifndef _INTFSFIFODIR_H_
+#define _INTFSFIFODIR_H_
+
+#pragma interface
+
+#include <string>
+#include <DirInode.h>
+
+class intfs;
+
+class ifsFifoDir: public DirInode
+{
+ int count;
+
+protected:
+ int do_rename(const up_preamble &, upp_repl &,
+ const upp_rename_s &);
+ int do_unlink(const up_preamble &, upp_repl &,
+ const upp_unlink_s &arg);
+ int do_link(const up_preamble &, upp_repl &,
+ const upp_link_s &);
+
+public:
+ ifsFifoDir(intfs &, Handle, DirInode *parent);
+ ~ifsFifoDir();
+
+ string create(Inode *);
+};
+
+#endif /* _INTFSFIFODIR_H_ */
Added: trunk/filesystems/intfs/intfsIno.cc
==============================================================================
--- trunk/filesystems/intfs/intfsIno.cc 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/intfs/intfsIno.cc 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,114 @@
+// -*- C++ -*-
+
+// General base class for non-directory inodes in intfs
+
+#pragma implementation
+
+#include "intfsIno.h"
+#include "intfs.h"
+#include "intfsDirIno.h"
+
+#include "dbg.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+ifsIno::ifsIno(intfs &fs, Handle hand, ifsDirIno *dir, string name, string link)
+ : SimpleInode(fs, hand),
+ filesys(fs), name(name), link(link), dir(dir)
+{
+ size = link.length();
+ mode = S_IFLNK|0777;
+}
+
+ifsIno::~ifsIno()
+{
+}
+
+int ifsIno::do_readlink(const up_preamble &, upp_repl &,
+ const upp_readlink_s &, upp_readlink_r &ret)
+{
+ int len;
+ ret.name.alloc(len = link.length());
+ memcpy(ret.name.elems, (const char *)link.data(), len);
+ ret.name.nelem = len;
+
+ return 0;
+}
+
+int ifsIno::do_followlink(const up_preamble &, upp_repl &,
+ const upp_followlink_s &, upp_followlink_r &ret)
+{
+ int len;
+ ret.path.alloc(len = link.length());
+ memcpy(ret.path.elems, (const char *)link.data(), len);
+ ret.path.nelem = len;
+
+ return 0;
+}
+
+int ifsIno::do_write(const up_preamble &, upp_repl &,
+ const upp_write_s &arg, upp_write_r &ret)
+{
+ LOG("ifsIno::do_write");
+ int fd = open(O_WRONLY);
+ int r;
+
+ if (fd < 0)
+ return -fd;
+ if (::lseek(fd, arg.off, SEEK_SET) == -1)
+ {
+ int er = errno;
+ ::close(fd);
+ return er;
+ }
+ if ((r = ::write(fd, arg.data.elems, arg.data.nelem)) == -1)
+ {
+ int er = errno;
+ ::close(fd);
+ return er;
+ }
+ ret.wrote = r;
+ ::close(fd);
+ return 0;
+}
+
+string ifsIno::path()
+{
+ string n;
+
+ cat(dir->path(), "/", name, n);
+
+ return n;
+}
+
+void ifsIno::update()
+{
+ struct stat st;
+ string p = path();
+
+ if (::lstat((const char *)p.data(), &st) == -1)
+ {
+ DB(printf("ifsIno::update stat of %s failed: %s\n",
+ (const char *)p.data(), strerror(errno)));
+ return;
+ }
+ atime = st.st_atime;
+ ctime = st.st_ctime;
+ mtime = st.st_mtime;
+ uid = st.st_uid;
+ gid = st.st_gid;
+}
+
+int ifsIno::open(int mode)
+{
+ string p;
+ int fd;
+
+ cat(dir->path(), "/", name, p);
+ if ((fd = ::open((const char *)p.data(), mode)) == -1)
+ return -errno;
+ return fd;
+}
Added: trunk/filesystems/intfs/Makefile
==============================================================================
--- trunk/filesystems/intfs/Makefile 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/intfs/Makefile 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,24 @@
+TOP=../..
+include $(TOP)/rules
+LIBDIR=$(TOP)/lib
+KERNDIR=$(TOP)/kernel
+
+CXXFLAGS = -DDEBUG -I$(LIBDIR) -I$(KERNDIR) -I$(TOP)/genser -I/usr/include/g++
+LDFLAGS = $(PROF) -L$(LIBDIR) -g
+
+OBJ = intfs.o intfsIno.o intfsDirIno.o intfsLinkIno.o intfsFifoDir.o \
+ intfsFifoIno.o readdir.o pushd.o
+
+PROGS = intfs
+
+all:: $(PROGS)
+
+intfs: $(OBJ) $(DEPLIBUSERFS)
+ $(CXX) $(LDFLAGS) -o intfs $(OBJ) $(LIBUSERFS)
+
+clean:: dummy
+ rm -f *.o *~ core $(PROGS)
+
+dep depend:: dummy
+ $(CXX) $(CXXFLAGS) -M *.cc> .depend
+
Added: trunk/filesystems/intfs/intfsDirIno.h
==============================================================================
--- trunk/filesystems/intfs/intfsDirIno.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/intfs/intfsDirIno.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,46 @@
+// -*- C++ -*-
+
+#ifndef _INTFSDIRINO_H_
+#define _INTFSDIRINO_H_
+
+#pragma interface
+
+#include <DirInode.h>
+#include <string>
+
+class intfs;
+
+class ifsDirIno: public DirInode
+{
+ const string name;
+ ifsDirIno *dotdot;
+ int fd;
+ intfs &filesys;
+
+ int open();
+ void close();
+
+ int updating;
+
+protected:
+ void update();
+ int do_unlink(const up_preamble &, upp_repl &,
+ const upp_unlink_s &);
+ int do_symlink(const up_preamble &, upp_repl &,
+ const upp_symlink_s &arg);
+ int do_create(const up_preamble &, upp_repl &,
+ const upp_create_s &, upp_create_r &);
+ int do_rename(const up_preamble &, upp_repl &,
+ const upp_rename_s &);
+public:
+ string path();
+ string toppath();
+
+ ifsDirIno(intfs &fs, Handle hand, ifsDirIno *parent,
+ string dirname);
+ ~ifsDirIno();
+
+ int dupfd();
+};
+
+#endif /* _INTFSDIRINO_H_ */
Added: trunk/filesystems/cvsfs/cvsdir.h
==============================================================================
--- trunk/filesystems/cvsfs/cvsdir.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/cvsfs/cvsdir.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,6 @@
+/*
+ * Functions to read a CVS checkout directory
+ */
+
+int ReadCVSDir (CVS_DIRENT *dir);
+
Added: trunk/filesystems/cvsfs/cvstree.h
==============================================================================
--- trunk/filesystems/cvsfs/cvstree.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/cvsfs/cvstree.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,10 @@
+/*
+ * cvstree.h - declarations of fns for filesystem tree manipulation
+ */
+
+int get_path(char *name, int size, CVS_DIRENT *t, int type);
+int RemoveChild(CVS_DIRENT *dir, CVS_DIRENT *ent);
+CVS_DIRENT *FindChild(CVS_DIRENT *ent, char *name, int namelen);
+CVS_DIRENT *CreateChild(char *name, int type);
+int ReadChildren(CVS_DIRENT *ent, int type);
+
Added: trunk/filesystems/cvsfs/cvs.h
==============================================================================
--- trunk/filesystems/cvsfs/cvs.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/cvsfs/cvs.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,56 @@
+
+#ifndef __CVS_H__
+#define __CVS_H__
+
+typedef struct _ChunkInfo
+{
+ int *offsets;
+ int size;
+ int first_line; /* for the future */
+ int last_line; /* for the future */
+ struct _ChunkInfo *next;/* for the future */
+} ChunkInfo;
+
+int ReadChunkInfo(int fd, ChunkInfo **ci);
+int ReadChunkedData(int fd, ChunkInfo *ci, size_t offset,
+ size_t count, unsigned char *buf);
+size_t ChunkSize(const ChunkInfo *ci);
+size_t GetVersionLength(int fd);
+
+#define Y_MAGIC 0x005D595D
+
+/* some file types */
+#define NO_TYPE 0x00 /* bad or unknown file type */
+#define VER_FILE 0x10 /* repository version file */
+#define STD_FILE 0x11 /* normal file in checked out dir */
+#define REP_DIR 0x12 /* repository directory */
+#define STD_DIR 0x13 /* normal directory in checked out dir */
+#define CHECKOUT_FILE 0x14 /* checked out and existing file */
+#define CHECKOUT_DIR 0x15 /* checked out and existing directory */
+#define DELETED_FILE 0x16 /* directory checked out but deleted */
+#define DELETED_DIR 0x17 /* directory checked out but deleted */
+
+#define IS_DELETED(type) (((type)==DELETED_FILE)||((type)==DELETED_DIR))
+
+/* maximum length of a filename */
+#define MAXCVSFILE 1024
+
+/*
+ * malloc allocs us around 0x100 bytes per alloc anyhow, so
+ * we might as well use it.
+ */
+typedef struct CVS_DIRENT {
+ int magic;
+ int file_type; /* this is true if the file is in the repository */
+ int fd;
+ int ref_count;
+ struct CVS_DIRENT *parent;
+ struct CVS_DIRENT *next;
+ struct CVS_DIRENT *child;
+ ChunkInfo *info;
+ char *cvsdir,*codir; /* name of the repositry and checkout dir */
+ char strings[MAXCVSFILE]; /* because i'm lazy */
+} CVS_DIRENT;
+
+#endif
+
Added: trunk/filesystems/cvsfs/cvsfs.c
==============================================================================
--- trunk/filesystems/cvsfs/cvsfs.c 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/cvsfs/cvsfs.c 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,1133 @@
+/* cvs access archive filesystem. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <utime.h>
+#include <dirent.h>
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include <getopt.h>
+#include <assert.h>
+
+#include <time.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/fcntl.h>
+
+#include <linux/fs.h>
+
+#include <linux/userfs_fs.h>
+#include <linux/unistd.h>
+
+#include <assert.h>
+#include "cvs.h"
+#include "cvstree.h"
+#include "cvsdir.h"
+
+static char *mpoint;
+static CVS_DIRENT *root;
+
+unsigned char *delete_me = NULL;
+
+/* No point in this being in a seperate file. */
+#include <linux/userfs_types.c>
+
+#define FAIL(str) fprintf(stderr, "%s:%d %s failed with errno = %s (%d)\n", \
+ __FILE__, __LINE__, str, strerror(errno), errno)
+
+static int myread (int fd, void *buf, int sz)
+{
+ int rd = 0;
+ int ret;
+
+ while (sz > 0)
+ {
+ ret = read (fd, buf, sz);
+
+ if (ret == -1)
+ {
+ if (errno == EINTR)
+ continue;
+
+ perror ("myread");
+ exit (1);
+ }
+
+ if (ret == 0)
+ break;
+
+ sz -= ret;
+ buf += ret;
+ rd += ret;
+ }
+
+ return rd;
+}
+
+static int mywrite (int fd, const void *buf, int sz)
+{
+ int wr = 0;
+ int ret;
+
+ while (sz > 0)
+ {
+ ret = write (fd, buf, sz);
+
+ if (ret == -1)
+ {
+ if (errno == EINTR)
+ continue;
+ FAIL ("write");
+ exit (1);
+ }
+
+ if (ret == 0)
+ {
+ fprintf (stderr, "write wrote 0 bytes\n");
+ break;
+ }
+
+ sz -= ret;
+ buf += ret;
+ wr += ret;
+ }
+
+ return wr;
+}
+
+static int readpkt (int fd, up_preamble *pre, unsigned char *buf)
+{
+ int presz = sizeof_up_preamble (pre);
+ unsigned int rd;
+ unsigned char pbuf[presz];
+
+ memset (pbuf, 0, sizeof (pbuf));
+
+ rd = myread (fd, pbuf, presz);
+ if (rd != presz)
+ {
+ if (rd == 0)
+ return 0;
+ if (rd > 0)
+ fprintf (stderr, "readpkt, incomplete read (%d, not %d)\n",
+ rd, presz);
+ perror ("readpkt, header read");
+ return -1;
+ }
+
+ decode_up_preamble (pre, pbuf);
+
+ if (pre->isreq != UP_ENQ && pre->isreq != UP_REQ)
+ fprintf (stderr, "pre->isreq = %d\n", pre->isreq);
+
+ if (pre->version != UP_VERSION)
+ {
+ fprintf (stderr, "Version mismatch: us=%d them=%d\n",
+ UP_VERSION, pre->version);
+ return -1;
+ }
+
+ if (pre->size != 0)
+ {
+ if (myread (fd, buf, pre->size) != pre->size)
+ {
+ perror ("readpkt, body read");
+ return -1;
+ }
+ }
+
+ return 1;
+}
+
+static int writepkt (int fd, upp_repl *repl, const unsigned char *buf)
+{
+ int replsz = sizeof_upp_repl (repl);
+ unsigned char pbuf[replsz];
+ unsigned int wr;
+ unsigned char *p;
+
+ assert (repl->version == UP_VERSION);
+ assert (repl->isreq == UP_REPL);
+
+ p = encode_upp_repl (repl, pbuf);
+
+ assert (replsz == p - pbuf);
+
+ wr = mywrite (fd, pbuf, replsz);
+ if (wr != replsz)
+ {
+ perror ("writepkt, header write");
+ return -1;
+ }
+
+ if (repl->size > 0 && repl->err_no == 0)
+ {
+ if ( mywrite(fd, buf, repl->size) != repl->size)
+ {
+ perror ("writepkt, body write");
+ return -1;
+ }
+ }
+
+ return 1;
+}
+
+static void genpkt (upp_repl *repl, int seq, up_ops op)
+{
+ repl->version = UP_VERSION;
+ repl->seq = seq;
+ repl->op = op;
+ repl->isreq = 0;
+ repl->size = 0;
+ repl->err_no = 0;
+}
+
+static int do_iread (unsigned char *buf, upp_repl *repl)
+{
+ upp_iread_s rcv;
+ upp_iread_r snd;
+ struct stat st;
+ CVS_DIRENT *ent ;
+ char name[1024];
+
+ decode_upp_iread_s(&rcv, buf);
+
+ memset(&snd, 0, sizeof(snd));
+
+ ent = (CVS_DIRENT *) rcv.handle.handle;
+ snd.handle = rcv.handle;
+
+ if( IS_DELETED(ent->file_type))
+ return ENOENT;
+
+ if(0 > get_path(name,sizeof name-2, ent, ent->file_type))
+ {
+ fprintf(stderr,"Filename too long.\n");
+ return ENAMETOOLONG;
+ }
+
+ /* fprintf(stderr,"stat on file: %s\n",name); */
+
+ if(ent->file_type==VER_FILE)
+ strcat(name,",v");
+
+ /* if the file exists, add it to our tree */
+ if(0>lstat(name,&st))
+ {
+ return ENOENT;
+ }
+
+ /* this is slow, but if we don't do it, reading is wrong */
+ if(ent->file_type == VER_FILE)
+ {
+ int fd = open(name,O_RDONLY);
+ /* fprintf(stderr,"Checking length %s ...",name); */
+ snd.ino.size = GetVersionLength(fd);
+ /* fprintf(stderr,"OK\n"); */
+ close(fd);
+ }
+ else
+ snd.ino.size = st.st_size;
+
+ /* clear the writable bits for repository files */
+ if(ent->file_type == VER_FILE)
+ snd.ino.mode = st.st_mode&~(S_IWUSR|S_IWGRP|S_IWOTH);
+ else if(ent->file_type == STD_DIR || ent->file_type == REP_DIR)
+ snd.ino.mode = S_IFDIR | st.st_mode;
+ else
+ snd.ino.mode = st.st_mode;
+
+ /* copy from one filesystem to the other */
+ snd.ino.uid = st.st_uid;
+ snd.ino.gid = st.st_gid;
+ snd.ino.nlink = st.st_nlink;
+ snd.ino.blksize = st.st_blksize;
+ snd.ino.blocks = st.st_blocks;
+ snd.ino.mtime = st.st_mtime;
+ snd.ino.atime = st.st_atime;
+ snd.ino.ctime = st.st_ctime;
+ snd.ino.rdev = st.st_rdev;
+
+ repl->size = encode_upp_iread_r(&snd, buf) - buf;
+
+ return 0;
+}
+
+static int do_lookup (unsigned char *buf, upp_repl *repl)
+{
+ upp_lookup_s rcv;
+ upp_lookup_r snd;
+ CVS_DIRENT *ent;
+ CVS_DIRENT *t;
+
+ decode_upp_lookup_s(&rcv, buf);
+
+ ent = (CVS_DIRENT *) rcv.dir.handle;
+
+ if (rcv.name.nelem == 2
+ && rcv.name.elems[0] == '.' && rcv.name.elems[1] == '.')
+ {
+ t = ent->parent;
+ }
+ else if (rcv.name.nelem == 1 && rcv.name.elems[0] == '.')
+ {
+ t = ent;
+ }
+ else
+ {
+ if(!ent->child)
+ {
+ /* files in the checked out filesystem shadow those in the repositry */
+ ReadCVSDir(ent);
+ ReadChildren(ent,STD_DIR);
+ ReadChildren(ent,REP_DIR);
+ }
+ t = FindChild(ent, rcv.name.elems, rcv.name.nelem);
+ if(t && IS_DELETED(t->file_type))
+ return ENOENT;
+ }
+ FREE(rcv.name.elems);
+ if (!t)
+ {
+ return ENOENT;
+ }
+ snd.handle.handle = (Ulong) t;
+
+ repl->size = encode_upp_lookup_r (&snd, buf) - buf;
+
+ return 0;
+}
+
+/* read the elements in a directory */
+static int do_readdir (unsigned char *buf, upp_repl *repl)
+{
+ upp_readdir_s rcv;
+ upp_readdir_r snd;
+ CVS_DIRENT *ent;
+ CVS_DIRENT *t;
+
+ decode_upp_readdir_s(&rcv, buf);
+
+ ent = (CVS_DIRENT *) rcv.dir.handle;
+
+ snd.off = 0;
+ snd.name.nelem = 0;
+
+ /* if there are no children, try and read some */
+ if(!ent->child)
+ {
+ /* files in the checked out filesystem shadow those in the repositry */
+ ReadCVSDir(ent);
+ ReadChildren(ent,STD_DIR);
+ ReadChildren(ent,REP_DIR);
+ }
+
+ /* now just look up the appropriate offset */
+ switch(rcv.off) {
+ case 0:
+ snd.name.elems = ".";
+ t = ent;
+ break;
+ case 1:
+ snd.name.elems = "..";
+ t = ent->parent;
+ break;
+ default:
+ rcv.off-=2;
+ for(t=ent->child; t && rcv.off--; )
+ {
+ do {
+ t = t->next;
+ } while(t && IS_DELETED(t->file_type));
+ }
+ if (t)
+ snd.name.elems = t->strings;
+ }
+
+ if(t) {
+ snd.off = 1;
+ snd.name.nelem = strlen (snd.name.elems);
+ snd.file.handle = (Ulong) t;
+ }
+
+ repl->size = encode_upp_readdir_r(&snd, buf) - buf;
+
+ return 0;
+}
+
+/* 0 is success, nonzero failure */
+static int MakeCheckoutDir(CVS_DIRENT *dir)
+{
+ char name[MAXCVSFILE];
+ int r;
+
+ /* if we're already a standard directory, return */
+ if(dir->file_type == STD_DIR)
+ return 0;
+
+ /* if we're not a repository directory, bail */
+ if(dir->file_type != REP_DIR)
+ return EPERM;
+
+ /* if we're at the root directory, then it should already exist... */
+ if(dir->parent == dir)
+ return 0;
+
+ r = MakeCheckoutDir(dir->parent);
+
+ if(r != 0)
+ return r;
+
+ /* force the name to be in the checkout area */
+ if(0>get_path(name,sizeof name,dir,STD_DIR))
+ return ENAMETOOLONG;
+
+ fprintf(stderr,"Making checkout directory %s\n",name);
+ /* TODO: this mask should be read from the repository directory */
+ if(0>mkdir(name,0755))
+ return errno;
+
+ /* update the directory entry to be a checkout directory */
+ dir->file_type = STD_DIR;
+
+ return 0;
+}
+
+static int do_rename (unsigned char *buf, upp_repl *repl)
+{
+ upp_rename_s rcv;
+ CVS_DIRENT *olddir;
+ CVS_DIRENT *newdir;
+ CVS_DIRENT *ent;
+ CVS_DIRENT *target;
+ char oldfile[1024];
+ char newfile[1024];
+
+ decode_upp_rename_s (&rcv, buf);
+
+ fprintf(stderr,"do_rename: ");
+
+ olddir = (CVS_DIRENT *) rcv.odir.handle;
+ newdir = (CVS_DIRENT *) rcv.ndir.handle;
+
+ ent = FindChild(olddir, rcv.oname.elems, rcv.oname.nelem);
+ if(!ent)
+ {
+ fprintf(stderr,"no child found.\n");
+ return ENOENT;
+ }
+
+ if(ent->file_type != STD_FILE)
+ {
+ fprintf(stderr,"not a standard file.\n");
+ return EPERM;
+ }
+
+ /*
+ * If the directory is not a checkout directory
+ * then a new mirror directory will be created in the checkout area.
+ */
+ if(MakeCheckoutDir(newdir))
+ {
+ fprintf(stderr,"couldn't make a checkout directory\n");
+ return EPERM;
+ }
+
+ /*
+ * Check if there is already a directory entry by this name
+ * and whether or not we can overwrite it.
+ */
+ if((target = FindChild(newdir,rcv.nname.elems,rcv.nname.nelem)))
+ if((target->file_type == REP_DIR) || (target->file_type == VER_FILE))
+ return EPERM;
+
+ if(0>get_path(oldfile,sizeof oldfile,ent,ent->file_type))
+ {
+ fprintf(stderr,"old path too long.\n");
+ return ENAMETOOLONG;
+ }
+
+ /* TODO: need to check whether we will overwrite a deleted checkout file */
+
+ strncpy(ent->strings,rcv.nname.elems,rcv.nname.nelem);
+ ent->strings[rcv.nname.nelem]=0;
+
+ if(0>get_path(newfile,sizeof newfile,ent,ent->file_type))
+ {
+ fprintf(stderr,"new path too long.\n");
+ return ENAMETOOLONG;
+ }
+ if(0>rename(oldfile,newfile))
+ {
+ /* copy the old name back */
+ strncpy(ent->strings,rcv.oname.elems,rcv.oname.nelem);
+ ent->strings[rcv.oname.nelem]=0;
+
+ return errno;
+ }
+
+ /* if there was a file overwritten by the rename, remove it */
+ if(target)
+ RemoveChild(newdir,target);
+
+ fprintf(stderr,"%s -> %s rename OK.\n",oldfile,newfile);
+
+ return 0;
+}
+
+static int do_unlink (unsigned char *buf, upp_repl *repl)
+{
+ upp_unlink_s rcv;
+ CVS_DIRENT *dir;
+ CVS_DIRENT *ent;
+ char filename[1024];
+
+ decode_upp_unlink_s (&rcv, buf);
+
+ dir = (CVS_DIRENT *) rcv.dir.handle;
+
+ if(dir->magic != Y_MAGIC)
+ return EPERM;
+
+ ent = FindChild(dir, rcv.name.elems, rcv.name.nelem);
+
+ if(0>get_path(filename,sizeof filename,ent,ent->file_type))
+ return ENAMETOOLONG;
+
+ if(ent->ref_count)
+ fprintf(stderr,"Unlinking an open file. Maybe not so good...\n");
+
+ switch(ent->file_type)
+ {
+ case VER_FILE:
+ case REP_DIR:
+ return EPERM;
+ case STD_FILE:
+ if(0>unlink(filename))
+ return errno;
+ RemoveChild(dir,ent);
+ break;
+ case STD_DIR:
+ if(0>rmdir(filename))
+ return errno;
+ RemoveChild(dir,ent);
+ break;
+ case DELETED_FILE:
+ case DELETED_DIR:
+ return ENOENT;
+ case CHECKOUT_FILE:
+ if(0>unlink(filename))
+ return errno;
+ ent->file_type = DELETED_FILE;
+ break;
+ case CHECKOUT_DIR:
+ if(0>rmdir(filename))
+ return errno;
+ ent->file_type = DELETED_DIR;
+ break;
+ default:
+ fprintf(stderr,"File type %X. What's that?\n",ent->file_type);
+ return EPERM;
+ }
+
+ return 0;
+}
+
+static int do_create (unsigned char *buf, upp_repl *repl)
+{
+ upp_create_s rcv;
+ upp_create_r snd;
+ CVS_DIRENT *dir;
+ CVS_DIRENT *ent;
+ char filename[1024];
+
+ decode_upp_create_s (&rcv, buf);
+ dir = (CVS_DIRENT *) rcv.dir.handle;
+
+ if(dir->magic != Y_MAGIC)
+ return EPERM;
+
+ if( (ent = FindChild(dir,rcv.name.elems,rcv.name.nelem)) )
+ {
+ if(!IS_DELETED(ent->file_type))
+ return EPERM;
+ if(0>get_path(filename,sizeof filename,ent,ent->file_type))
+ return ENAMETOOLONG;
+ }
+ else
+ {
+ if(MakeCheckoutDir(dir))
+ {
+ fprintf(stderr,"create: couldn't make checkout directory\n");
+ return EPERM;
+ }
+
+ strncpy(filename,rcv.name.elems,rcv.name.nelem);
+ filename[rcv.name.nelem]=0;
+
+ ent = CreateChild(filename,(rcv.mode&S_IFDIR)?STD_DIR:STD_FILE);
+ if(0>get_path(filename,sizeof filename,ent,ent->file_type))
+ {
+ free(ent);
+ return ENAMETOOLONG;
+ }
+ }
+
+ /* new files must be created on the RW filesystem */
+ switch(ent->file_type)
+ {
+ case STD_FILE:
+ ent->fd = creat ( filename, rcv.mode);
+ if(ent->fd<0)
+ {
+ free(ent);
+ return errno;
+ }
+ close(ent->fd);
+ ent->fd = 0;
+ /* OK, now add it to its parent's child list (at the beginning) */
+ ent->next = dir->child;
+ dir->child = ent;
+ break;
+
+ case STD_DIR:
+ if(0>mkdir(filename,rcv.mode))
+ return errno;
+ /* OK, now add it to its parent's child list (at the beginning) */
+ ent->next = dir->child;
+ dir->child = ent;
+ break;
+
+ case DELETED_DIR:
+ if(0>mkdir(filename,rcv.mode))
+ return errno;
+ ent->file_type = CHECKOUT_DIR;
+ break;
+
+ case DELETED_FILE:
+ ent->fd = creat ( filename, rcv.mode);
+ if(ent->fd<0)
+ return errno;
+ close(ent->fd);
+ ent->file_type = CHECKOUT_FILE;
+ break;
+ default:
+ fprintf(stderr,"cvs: Somebody tried to create a wierd file.\n");
+ return EPERM;
+ }
+
+ /* now return the handle to the new file */
+ snd.file.handle = (Ulong) ent;
+ repl->size = encode_upp_create_r (&snd, buf) - buf;
+
+ return 0;
+}
+
+static int do_open (unsigned char *buf, upp_repl *repl)
+{
+ upp_open_s rcv;
+ CVS_DIRENT *ent;
+ char filename[1024];
+
+ decode_upp_open_s (&rcv, buf);
+
+ ent = (CVS_DIRENT *) rcv.file.handle;
+
+ if(ent->magic != Y_MAGIC)
+ return EPERM;
+
+ if(!ent->ref_count)
+ {
+ if(0>get_path(filename,sizeof filename,ent,ent->file_type))
+ return EPERM;
+
+ switch(ent->file_type)
+ {
+ case VER_FILE:
+ strcat(filename,",v");
+ ent->fd = open ( filename, O_RDONLY);
+ if(ent->fd<0)
+ return EPERM;
+ /* maybe we should re-read the chunk info? */
+ if(!ent->info)
+ if(ReadChunkInfo(ent->fd, &ent->info))
+ return EPERM;
+ break;
+
+ case STD_DIR: /* nothing to do when opening directories */
+ case CHECKOUT_DIR:
+ break;
+
+ case DELETED_FILE:
+ case DELETED_DIR:
+ return ENOENT;
+
+ case STD_FILE:
+ case CHECKOUT_FILE:
+ ent->fd = open ( filename, O_RDWR);
+ if(ent->fd<0)
+ {
+ fprintf(stderr,"Open %s failed\n",filename);
+ return EPERM;
+ }
+ break;
+ }
+ }
+ ent->ref_count++;
+
+ return 0;
+}
+
+/*
+ * free handles if nobody left using the file
+ */
+static int do_close (unsigned char *buf, upp_repl *repl)
+{
+ upp_close_s rcv;
+ CVS_DIRENT *ent;
+
+ decode_upp_close_s (&rcv, buf);
+
+ ent = (CVS_DIRENT *) rcv.file.handle;
+
+ if(!ent->ref_count)
+ return EPERM;
+
+ ent->ref_count--;
+ if(!ent->ref_count)
+ {
+ switch(ent->file_type)
+ {
+ case VER_FILE:
+ if(ent->info)
+ {
+ if(ent->info->offsets)
+ free(ent->info->offsets);
+ ent->info->offsets=NULL;
+ free(ent->info);
+ ent->info = NULL;
+ }
+ /* fall through */
+ case CHECKOUT_FILE:
+ case STD_FILE:
+ close(ent->fd);
+ ent->fd = 0;
+ /* fall through */
+ case CHECKOUT_DIR:
+ case STD_DIR:
+ case REP_DIR:
+ default:
+ /* still falling... */
+ }
+ }
+
+ return 0;
+}
+
+static int do_truncate (unsigned char *mbuf, upp_repl *repl)
+{
+ upp_truncate_s rcv;
+ CVS_DIRENT *ent;
+ char filename[1024];
+
+ decode_upp_truncate_s (&rcv, mbuf);
+
+ ent = (CVS_DIRENT *) rcv.file.handle;
+
+ if(ent->magic != Y_MAGIC)
+ return EPERM;
+
+ switch(ent->file_type)
+ {
+ case VER_FILE:
+ case REP_DIR:
+ case STD_DIR:
+ case CHECKOUT_DIR:
+ case DELETED_DIR:
+ case DELETED_FILE:
+ return EPERM;
+
+ case STD_FILE:
+ case CHECKOUT_FILE:
+ if(ent->ref_count)
+ {
+ if(0>ftruncate(ent->fd,rcv.size))
+ return errno;
+ }
+ else
+ {
+ if(0>get_path(filename,sizeof filename,ent,ent->file_type))
+ return ENAMETOOLONG;
+
+ if(0>truncate(filename,rcv.size))
+ return errno;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+/*
+ * We can only write to files in the checkout directory.
+ */
+static int do_write (unsigned char *mbuf, upp_repl *repl)
+{
+ upp_write_s rcv;
+ upp_write_r snd;
+ CVS_DIRENT *ent;
+ int rc;
+
+ decode_upp_write_s (&rcv, mbuf);
+
+ ent = (CVS_DIRENT *) rcv.file.handle;
+
+ /* check that the file is actually open */
+ if(!ent->ref_count)
+ return EPERM;
+
+ /* make doublely sure we don't write to repository files */
+ switch(ent->file_type)
+ {
+ case VER_FILE:
+ case STD_DIR:
+ case REP_DIR:
+ case CHECKOUT_DIR:
+ case DELETED_DIR:
+ case DELETED_FILE:
+ return EPERM;
+ case CHECKOUT_FILE:
+ case STD_FILE:
+ lseek(ent->fd, rcv.off, SEEK_SET);
+ rc = write(ent->fd, rcv.data.elems, rcv.data.nelem);
+ if(rc < 0)
+ return errno;
+ break;
+ default:
+ fprintf(stderr,"Wierdo file write. Blah!\n");
+ return EPERM;
+ }
+
+ snd.wrote = rc;
+
+ repl->size = encode_upp_write_r (&snd, mbuf) - mbuf;
+
+ return 0;
+}
+
+/*
+ * two cases: read from a normal file or read from the repository
+ */
+static int do_read (unsigned char *mbuf, upp_repl *repl)
+{
+ upp_read_s rcv;
+ upp_read_r snd;
+ CVS_DIRENT *ent;
+ int rc;
+ long size;
+
+ snd.data.nelem = 0;
+ snd.data.elems = NULL;
+
+ decode_upp_read_s (&rcv, mbuf);
+
+ ent = (CVS_DIRENT *) rcv.file.handle;
+
+ /* check that the file is actually open */
+ if(!ent->ref_count)
+ return EPERM;
+
+ switch(ent->file_type)
+ {
+ case VER_FILE:
+ if(!ent->info)
+ return EIO;
+ size = ChunkSize(ent->info);
+ break;
+
+ case CHECKOUT_FILE:
+ case STD_FILE:
+ size = lseek(ent->fd,0,SEEK_END);
+ if(0>lseek(ent->fd,rcv.off,SEEK_SET))
+ return EPERM;
+ break;
+
+ default:
+ return EPERM;
+ }
+
+ if( (size - rcv.off) < rcv.size )
+ size = (size - rcv.off);
+ else
+ size = rcv.size;
+
+ /* where is this going to be free'd ? */
+ if(size)
+ snd.data.elems = (unsigned char *)malloc(size);
+
+ if(snd.data.elems)
+ {
+ if(ent->file_type == VER_FILE)
+ rc = ReadChunkedData(ent->fd, ent->info, rcv.off, size, snd.data.elems);
+ else
+ rc = read(ent->fd,snd.data.elems,size);
+
+ if(rc < 0)
+ return rc;
+ snd.data.nelem = rc;
+ }
+
+ repl->size = encode_upp_read_r (&snd, mbuf) - mbuf;
+
+ /* hack alert! */
+ delete_me = snd.data.elems;
+
+ return 0;
+}
+
+/* these must line up with the values defined for the kernel in linux/fs.h */
+#define ATTR_MODE 1
+#define ATTR_UID 2
+#define ATTR_GID 4
+#define ATTR_SIZE 8
+#define ATTR_ATIME 16
+#define ATTR_MTIME 32
+#define ATTR_CTIME 64
+
+/*
+ * make a change to an inode's mode, size, time, ownership, etc.
+ */
+static int do_notify_change(unsigned char *mbuf, upp_repl *repl)
+{
+ upp_notify_change_s rcv;
+ CVS_DIRENT *ent;
+ char name[1024];
+ struct stat st;
+ struct utimbuf ut;
+
+ decode_upp_notify_change_s (&rcv, mbuf);
+ ent = (CVS_DIRENT *)rcv.handle.handle;
+
+ switch(ent->file_type)
+ {
+ case VER_FILE:
+ case REP_DIR:
+ case DELETED_DIR:
+ case DELETED_FILE:
+ return EPERM;
+ case STD_FILE:
+ case STD_DIR:
+ case CHECKOUT_FILE:
+ case CHECKOUT_DIR:
+ break;
+ default:
+ return EPERM;
+ }
+
+ if(0>get_path(name, sizeof name, ent, ent->file_type))
+ return ENAMETOOLONG;
+
+ /* read the old values */
+ if(0>lstat(name,&st))
+ return errno;
+
+ if(rcv.iattr.ia_valid & ATTR_MODE )
+ if(0>chmod(name,rcv.iattr.ia_mode))
+ return errno;
+
+ if(rcv.iattr.ia_valid & (ATTR_UID|ATTR_GID))
+ {
+ if(rcv.iattr.ia_valid & ATTR_UID )
+ st.st_uid = rcv.iattr.ia_uid;
+ if(rcv.iattr.ia_valid & ATTR_GID )
+ st.st_gid = rcv.iattr.ia_gid;
+ if(0>chown(name,st.st_uid,st.st_gid))
+ return errno;
+ }
+
+ if(rcv.iattr.ia_valid & ATTR_SIZE )
+ {
+ if(0>truncate(name, rcv.iattr.ia_size))
+ return errno;
+ }
+
+ if(rcv.iattr.ia_valid & (ATTR_ATIME|ATTR_MTIME|ATTR_CTIME) )
+ {
+ if(rcv.iattr.ia_valid & ATTR_ATIME )
+ st.st_atime = rcv.iattr.ia_atime;
+ if(rcv.iattr.ia_valid & ATTR_MTIME )
+ st.st_mtime = rcv.iattr.ia_mtime;
+ if(rcv.iattr.ia_valid & ATTR_CTIME ) /* this is not used */
+ st.st_ctime = rcv.iattr.ia_ctime;
+ }
+
+ if(rcv.iattr.ia_valid & (ATTR_ATIME|ATTR_MTIME) )
+ {
+ ut.actime = st.st_atime;
+ ut.modtime = st.st_mtime;
+ if(0>utime(name,&ut))
+ return errno;
+ }
+
+ return 0;
+}
+
+static int do_mount (unsigned char *buf, upp_repl *repl)
+{
+ upp_mount_r snd;
+
+ snd.root.handle = (Ulong) root;
+ repl->size = encode_upp_mount_r(&snd, buf) - buf;
+ /* INIT */
+ repl->size = encode_upp_mount_r(&snd, buf) - buf;
+ return 0;
+}
+
+static void run (int wr, int rd)
+{
+ up_preamble pre;
+ upp_repl repl;
+ /* Ah! The bogey man's a-coming to get me! */
+ unsigned char buf[4096];
+ int error;
+
+ while(readpkt(rd, &pre, buf) == 1)
+ {
+ genpkt(&repl, pre.seq, pre.op);
+
+ switch(pre.op)
+ {
+#define DO(op, b, r) case up_##op: \
+ error = (pre.isreq == UP_ENQ ? 0 : do_##op(b, r)); \
+ break;
+ DO(mount, buf, &repl);
+ DO(iread, buf, &repl);
+ /* DO(iput, buf, &repl); */
+ DO(lookup, buf, &repl);
+ DO(readdir, buf, &repl);
+ DO(unlink, buf, &repl);
+ DO(open, buf, &repl);
+ DO(close, buf, &repl);
+ DO(read, buf, &repl);
+ DO(write, buf, &repl);
+ DO(create, buf, &repl);
+ DO(truncate, buf, &repl);
+ DO(notify_change, buf, &repl);
+ DO(rename, buf, &repl);
+#undef DO
+ default:
+ error = ENOSYS;
+ break;
+ }
+
+ repl.err_no = error;
+ if (error != 0)
+ repl.size = 0;
+
+ if (writepkt(wr, &repl, buf) != 1)
+ break;
+
+ /* this is a terrible hack! */
+ if(delete_me)
+ {
+ free(delete_me);
+ delete_me = NULL;
+ }
+ }
+}
+
+CVS_DIRENT *y_read(char *cvsdir, char *codir)
+{
+ CVS_DIRENT *root;
+
+ if(!cvsdir || !codir)
+ return NULL;
+
+ root = (CVS_DIRENT*)malloc(sizeof(CVS_DIRENT)
+ /*+strlen(cvsdir)+strlen(codir)+1*/);
+
+ root->magic = Y_MAGIC;
+ root->file_type = REP_DIR;
+ root->info = NULL;
+ root->fd = 0;
+ root->ref_count = 1;
+ root->parent = root;
+ root->next = NULL;
+ root->child = NULL;
+
+ /* pointers are to memory at the end of the CVS_DIRENT structure */
+ root->cvsdir = &root->strings[0];
+ strcpy(root->cvsdir,cvsdir);
+ root->codir = &root->strings[strlen(root->strings)+1];
+ strcpy(root->codir,codir);
+
+ fprintf(stderr,"mounting mirror file system of %s\n",root->strings);
+
+ return root;
+}
+
+int main (int argc, char **argv)
+{
+ int infd = 0;
+ int outfd = 1;
+ int c;
+ char *cvsroot = NULL;
+
+ while ((c = getopt (argc, argv, "i:o:m:r:")) != EOF)
+ {
+ switch(c)
+ {
+ case 'i':
+ infd = atoi(optarg);
+ break;
+ case 'o':
+ outfd = atoi(optarg);
+ break;
+ case 'm':
+ mpoint = optarg;
+ break;
+ case 'r':
+ cvsroot = optarg;
+ break;
+ default:
+ fprintf (stderr, "%s: bad option\n", argv[0]);
+ return 1;
+ }
+ }
+
+#ifdef FUTURE
+ /*
+ * check that we have a CVS repository to work with.
+ */
+ if(cvsroot == NULL)
+ {
+ cvsroot = getenv("CVSROOT");
+ if(cvsroot == NULL)
+ {
+ fprintf(stderr,"neither CVSROOT environment variable nor -r option specified.\n");
+ fprintf(stderr,"Where is your CVS repository?\n");
+ return 1;
+ }
+ }
+#endif
+
+ if (optind != argc - 2 )
+ {
+ fprintf (stderr, "%s: cvs directory and checkout dir not named\n", argv[0]);
+ return 1;
+ }
+
+ root = y_read (argv[optind], argv[optind+1]);
+ if (!root)
+ return 1;
+
+ signal (SIGCHLD, SIG_IGN);
+
+ run(outfd, infd);
+
+ return 0;
+}
+
Added: trunk/filesystems/cvsfs/cvsdir.c
==============================================================================
--- trunk/filesystems/cvsfs/cvsdir.c 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/cvsfs/cvsdir.c 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,180 @@
+/*
+ * CVS directory reader
+ *
+ * Functions in this file read the contents of a CVS directory
+ * (the checked out files) and add them to the directory's child
+ * list. Files are initially named checked out but deleted, and
+ * are updated to CHECKEDOUT if they are found in the directory.
+ * That is done elsewhere. We need to keep a record of which files
+ * are checked out and deleted otherwise we will add the original
+ * from the repository over the top of it, and it won't be deleted!
+ */
+
+#include<stdio.h>
+#include<linux/errno.h>
+#include<sys/stat.h>
+#include<sys/types.h>
+#include<fcntl.h>
+#include<unistd.h>
+#include<string.h>
+
+#include"cvs.h"
+#include"cvsdir.h"
+#include "cvstree.h"
+
+/*
+ * This function will check whether the checkout root for the
+ * named directory matches that specified on the command line.
+ *
+ * Returns 0 for success
+ * Returns errno for failure
+ */
+int CheckRoot(CVS_DIRENT *dir, char *name)
+{
+ return 0;
+}
+
+/*
+ * This function will check whether the repository for the
+ * named directory matches that specified on the command line.
+ *
+ * Returns 0 for success
+ * Returns errno for failure
+ */
+int CheckRepository(CVS_DIRENT *dir, char *name)
+{
+ return 0;
+}
+
+int MarkEOL(char *data, int max)
+{
+ int i=0;
+
+ /* find end of line */
+ while( (i<max) && (data[i]!='\n') && (data[i]!=0) )
+ i++;
+
+ if(i>=max)
+ return 0;
+
+ if(data[i]==0)
+ return 0;
+
+ data[i++]=0;
+
+ return i;
+}
+
+/*
+ * Read the names of all the checked out files in this directory
+ * and make them into dirents for this directory.
+ *
+ * The format of the lines in the Entries file is as follows:
+ * /ANNOUNCE/1.16/Sun Mar 28 15:38:32 1999//
+ * D/console////
+ *
+ * leading D means a directory. The filename is the second field.
+ */
+int ReadCheckedoutFiles(CVS_DIRENT *dir, char *name)
+{
+ char buffer[MAXCVSFILE];
+ int fd,n,pos;
+
+ fd = open(name, O_RDONLY);
+ if(fd<0)
+ return 1;
+
+ do
+ {
+ pos = 0;
+
+ n = read(fd, buffer, sizeof buffer);
+ if(n<0)
+ break;
+
+ do
+ {
+ char *token,*line=&buffer[pos];
+ int file_type=NO_TYPE;
+ CVS_DIRENT *ent;
+
+ /* make a string */
+ pos = MarkEOL(line,n);
+ if(pos == 0)
+ break;
+
+ fprintf(stderr,"Read line %s\n",line);
+ /* determine the type of file */
+ token = strsep(&line,"/");
+ if(!token)
+ continue;
+ if(!strcmp(token,"D"))
+ file_type = DELETED_DIR;
+ if(!strcmp(token,""))
+ file_type = DELETED_FILE;
+ if(file_type==NO_TYPE)
+ continue;
+
+ /* get the file's name */
+ token = strsep(&line,"/");
+ if(!token)
+ continue;
+ ent = CreateChild(token,file_type);
+ if(!ent)
+ continue;
+
+ fprintf(stderr,"added checked out file: %s\n",token);
+
+ /* add the child to the parent */
+ ent->parent = dir;
+ ent->next = dir->child;
+ dir->child = ent;
+ } while (pos);
+ } while (n && pos);
+
+ return 0;
+}
+
+/*
+ * Read in all the files that have been checked out.
+ */
+int ReadCVSDir (CVS_DIRENT *dir)
+{
+ char name[MAXCVSFILE];
+ char *p;
+ struct stat st;
+
+ if(0>get_path(name, sizeof name-4,dir, STD_DIR))
+ return ENAMETOOLONG;
+
+ /* first check that there is a CVS subdirectory */
+ p = &name[strlen(name)];
+
+ strcpy(p,"/CVS");
+
+ fprintf(stderr,"Reading %s\n",name);
+
+ if(0>lstat(name,&st))
+ return ENOTDIR;
+
+ if(!S_ISDIR(st.st_mode))
+ return ENOTDIR;
+
+ if(CheckRepository(dir,name))
+ return ENOTDIR;
+
+ if(CheckRoot(dir,name))
+ return ENOTDIR;
+
+ strcat(p,"/Entries");
+
+ fprintf(stderr,"Reading %s\n",name);
+
+ if(ReadCheckedoutFiles(dir, name))
+ return ENOTDIR;
+
+ dir->file_type = CHECKOUT_DIR;
+
+ return 0;
+}
+
Added: trunk/filesystems/cvsfs/cvs.c
==============================================================================
--- trunk/filesystems/cvsfs/cvs.c 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/cvsfs/cvs.c 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,315 @@
+/*
+ * cvs version file reader
+ *
+ * Eventually plan to be able to read all the versions
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "cvs.h"
+
+#define CVSBLOCK 1024
+
+/*
+ * count the characters in an rcs string eg. @......@@.....@
+ */
+static int ParseString(int fd)
+{
+ char line[1000];
+ int i,n,count=0;
+ int saw_esc = 0;
+ int end = 0;
+
+ while(!end)
+ {
+ n = read(fd,line,sizeof line);
+ if(n<=0)
+ end=1;
+ for(i=0; (i<n) && !end; i++)
+ {
+ if(saw_esc)
+ {
+ if(line[i]!='@')
+ end = 1;
+ else
+ count++;
+ saw_esc = 0;
+ }
+ else
+ {
+ if(line[i]=='@')
+ saw_esc = 1;
+ else
+ count++;
+ }
+ }
+ }
+ return count;
+}
+
+/*
+ * Read a single line into the buffer
+ * if the line is longer than the buffer, only the end will be read
+ */
+int ReadLine(int fd, unsigned char *buffer, int bsize)
+{
+ int n,i;
+
+ /* keep reading until we find a cr then go back */
+ do {
+ n = read(fd,buffer,bsize);
+ if(n<=0)
+ return 1;
+ for(i=0; i<n; i++)
+ if(buffer[i]=='\n')
+ break;
+ }
+ while (i>=n);
+ lseek(fd,i - n + 1, SEEK_CUR); /* go back */
+ buffer[i]=0;
+
+ return 0;
+}
+
+/*
+ * Read information about the location of data in the file
+ * Offsets are not one to one because of RCS escape characters(@).
+ */
+size_t *ReadOffsetInfo(int fd, size_t start, size_t size)
+{
+ size_t *offsets;
+ char line[CVSBLOCK];
+ int i,n,count=0;
+ size_t total=0;
+ int saw_esc = 0;
+ int end = 0;
+
+ lseek(fd,start,SEEK_SET);
+
+ /* allocate data for the offset info */
+ offsets = (size_t *)malloc(sizeof(size_t)*((size+CVSBLOCK-1)/CVSBLOCK));
+ if(!offsets)
+ return NULL;
+
+ while(!end)
+ {
+ n = read(fd,line,sizeof line);
+ if(n<=0)
+ end=1;
+ for(i=0; (i<n) && !end; i++,total++)
+ {
+ if(!saw_esc && ((count%CVSBLOCK)==0))
+ {
+ offsets[count/CVSBLOCK]=start+total;
+ /* printf("%x -> %x\n",count,start+total); */
+ }
+ if(saw_esc)
+ {
+ if(line[i]!='@')
+ end = 1;
+ else
+ count++;
+ saw_esc = 0;
+ }
+ else
+ {
+ if(line[i]=='@')
+ saw_esc = 1;
+ else
+ count++;
+ }
+ }
+ }
+ return offsets;
+}
+
+/*
+ * this is not going to be very efficient or correct for now
+ * It would be best to use yacc to generate a parser for the rcs file,
+ * but this is only proof of concept.
+ */
+int ReadChunkInfo(int fd, ChunkInfo **ci)
+{
+ char line[80];
+ size_t start_data;
+
+ while(!ReadLine(fd,line,sizeof line))
+ {
+ line[sizeof line -1]=0;
+ if(!strcmp(line,"text"))
+ {
+ /* fprintf(stderr,"Found start of last version\n"); */
+ break;
+ }
+ }
+ read(fd,line,1);
+ if('@' != line[0])
+ return 1;
+ *ci = (ChunkInfo*)malloc(sizeof (ChunkInfo));
+ if(!*ci)
+ return 1;
+
+ start_data= lseek(fd, 0, SEEK_CUR);
+ (*ci)->size = ParseString(fd);
+ (*ci)->first_line = 0;
+ (*ci)->last_line = 0;
+ (*ci)->next = NULL;
+
+ /* allocate data for the offset info */
+ (*ci)->offsets = ReadOffsetInfo(fd, start_data, (*ci)->size);
+
+ return 0;
+}
+
+/*
+ * This function is called every time a directory is read.
+ * If the length in the directory is incorrect, then programs want
+ * to read too much data from the file.
+ *
+ * That's not good because it makes reading directories very
+ * slow, but unless the length can be determined without parsing
+ * the whole file, tough.
+ */
+size_t GetVersionLength(int fd)
+{
+ char line[80];
+
+ while(!ReadLine(fd,line,sizeof line))
+ {
+ line[sizeof line -1]=0;
+ if(!strcmp(line,"text"))
+ {
+ /* fprintf(stderr,"Found start of last version\n"); */
+ break;
+ }
+ }
+ read(fd,line,1);
+ if('@' != line[0])
+ return 0;
+
+ return ParseString(fd);
+}
+
+/*
+ * This could be made a lot more efficient with the use of
+ * memcpy. You can't use strchr, as there may be zero bytes in the data.
+ *
+ * The idea is the read one block, removing any escape
+ * characters from the data.
+ */
+int ReadChunk(int fd, ChunkInfo *ci, int blockno, unsigned char *buf)
+{
+ int i,j,n,saw_esc,jnow;
+ size_t count = CVSBLOCK;
+
+ lseek(fd,ci->offsets[blockno], SEEK_SET);
+ /* printf("Reading at %X\n",ci->offsets[blockno]); */
+
+ j=0;
+ saw_esc = 0;
+ while(count > j)
+ {
+ n = read(fd, &buf[j], count-j);
+ if(n<=0)
+ break;
+ jnow = j;
+ for(i=jnow; i<(jnow+n); i++)
+ {
+ if(saw_esc)
+ {
+ buf[j++]=buf[i];
+ saw_esc=0;
+ }
+ else
+ {
+ if(buf[i]=='@')
+ saw_esc = 1;
+ else
+ buf[j++]=buf[i];
+ }
+ }
+ }
+
+ return j;
+}
+
+/*
+ * Read data from the file in blocks of CVSBLOCK
+ * Need to keep a list of offsets because we don't know
+ * how many escape characters there are.
+ */
+int ReadChunkedData(int fd, ChunkInfo *ci, size_t offset,
+ size_t count, unsigned char *buf)
+{
+ unsigned char block[CVSBLOCK];
+ int total, blockno, size;
+
+ if( (offset+count) > ci->size)
+ count = ci->size - offset;
+
+ total = 0;
+ for(blockno = offset/CVSBLOCK; blockno<=((offset+count)/CVSBLOCK); blockno++)
+ {
+
+ /* printf("reading chunk %d\n",blockno); */
+
+ ReadChunk(fd, ci, blockno, block);
+
+ /* set size to count to transfer as much as possible */
+ size = count;
+
+ /* then check we don't overrun the end of the read block */
+ if( ((offset%CVSBLOCK)+size) > CVSBLOCK)
+ size = CVSBLOCK - offset%CVSBLOCK;
+
+ memcpy(buf,&block[offset%CVSBLOCK],size);
+ count -= size;
+ offset += size;
+ buf += size;
+ total += size;
+ }
+
+ return total;
+}
+
+size_t ChunkSize(const ChunkInfo *ci)
+{
+ if(ci == NULL)
+ return 0;
+ return ci->size;
+}
+
+#ifdef TEST
+
+int main()
+{
+ int fd = open("/usr/src/wine/cvs/wine/wine.ini,v",O_RDONLY);
+ int n;
+ ChunkInfo *ci = NULL;
+ unsigned char *data;
+
+ if(!fd)
+ {
+ fprintf(stderr,"Open failed\n");
+ return 1;
+ }
+
+ if(0!=ReadChunkInfo(fd,&ci))
+ {
+ fprintf(stderr,"ReadChunkInfo failed\n");
+ return 1;
+ }
+
+ fprintf(stderr,"Size is %d, offset is %d\n",ci->size,ci->offset);
+ n = ChunkSize(ci);
+ data = (unsigned char *)malloc(n);
+ ReadChunkedData(fd,ci,0,n,data);
+ write(1,data,n);
+ return 0;
+}
+
+#endif
Added: trunk/filesystems/cvsfs/cvstree.c
==============================================================================
--- trunk/filesystems/cvsfs/cvstree.c 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/cvsfs/cvstree.c 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,284 @@
+/* cvs access archive filesystem. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <utime.h>
+#include <dirent.h>
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include <getopt.h>
+#include <assert.h>
+
+#include <time.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/fcntl.h>
+
+#include <linux/fs.h>
+
+#include <linux/userfs_fs.h>
+#include <linux/unistd.h>
+
+#include <assert.h>
+#include "cvs.h"
+
+/*
+ * Construct a real path name without trailing slash
+ * This will be used to access the existing file system.
+ *
+ * type indicates whether we are accessing the RO or RW
+ * base file system.
+ */
+int get_path(char *name, int size, CVS_DIRENT *t, int type)
+{
+ int len,plen;
+
+ if(!t)
+ return -ENOENT;
+ if(t->parent != t)
+ {
+ len = strlen(t->strings)+1; /* include trailing zero byte */
+ if(len>size)
+ return -ENOENT;
+ len++; /* include slash */
+ if(0>(plen=get_path(name, size - len, t->parent, type)))
+ return -ENOENT;
+ strcat(name,"/");
+ strcat(name,t->strings);
+ }
+ else
+ {
+ /* we're at the root inode */
+ plen=0;
+ switch(type)
+ {
+ case VER_FILE:
+ case REP_DIR:
+ len = strlen(t->cvsdir)+1; /* include trailing zero byte */
+ if(len>size)
+ return -ENOENT;
+ strcpy(name,t->cvsdir);
+ break;
+ case STD_FILE:
+ case STD_DIR:
+ case DELETED_DIR:
+ case DELETED_FILE:
+ case CHECKOUT_FILE:
+ case CHECKOUT_DIR:
+ len = strlen(t->codir)+1; /* include trailing zero byte */
+ if(len>size)
+ return -ENOENT;
+ strcpy(name,t->codir);
+ break;
+ default:
+ strcpy(name,"");
+ return -ENOENT;
+ }
+ }
+ return plen+len;
+}
+
+/*
+ * Remove a child entry from a directory.
+ */
+int RemoveChild(CVS_DIRENT *dir, CVS_DIRENT *ent)
+{
+ CVS_DIRENT **t;
+
+ if(!dir || !ent)
+ return 1;
+
+ for(t = &dir->child; *t; t = &((*t)->next))
+ {
+ if(*t == ent)
+ break;
+ }
+ if(*t)
+ {
+ CVS_DIRENT *freeme = *t;
+ *t = (*t)->next;
+ free(freeme);
+ }
+ else
+ return 1;
+
+ return 0;
+}
+
+/*
+ * Return a dirent with the name specified or NULL.
+ * This is the essence of the lookup function.
+ */
+CVS_DIRENT *FindChild(CVS_DIRENT *ent, char *name, int namelen)
+{
+ CVS_DIRENT *t;
+ int i=0;
+
+ for(t = ent->child; t; t=t->next)
+ {
+ if(i++>1000)
+ {
+ fprintf(stderr,"Wow. Something's wrong here\n");
+ return NULL;
+ }
+ /* check the length */
+ if(t->strings[namelen])
+ continue;
+ if (!strncmp(t->strings, name, namelen))
+ break;
+ }
+ return t;
+}
+
+/* create a blank entry */
+CVS_DIRENT *CreateChild(char *name, int type)
+{
+ CVS_DIRENT *ent;
+
+ ent = (CVS_DIRENT *) malloc(sizeof (CVS_DIRENT));
+ if(!ent)
+ return ent;
+
+ strcpy(ent->strings,name);
+ ent->magic = Y_MAGIC;
+ ent->file_type = type;
+ ent->info = NULL;
+ ent->fd = 0;
+ ent->ref_count=0;
+ ent->parent = NULL;
+ ent->child = NULL;
+ ent->cvsdir = NULL;
+ ent->next = NULL;
+
+ return ent;
+}
+
+int getdents(unsigned int fd, struct dirent *dirp, unsigned int count)
+{
+ _syscall3(int, getdents, uint, fd, struct dirent *, dirp, uint, count);
+ return(0);
+}
+
+/*
+ * type can be VER_FILE or STD_FILE
+ */
+int ReadChildren(CVS_DIRENT *ent, int type)
+{
+ /* read the directory into memory */
+ CVS_DIRENT *t;
+ char buffer[1024],filename[1024],*p;
+ struct dirent *de=(struct dirent *)buffer;
+ int len,n,fd;
+ struct stat st;
+
+ if(0>get_path(filename, sizeof filename, ent, type))
+ return ENOTDIR;
+
+ fprintf(stderr,"reading dir: %s\n",filename);
+
+ fd = open(filename,O_RDONLY);
+ if(fd<0)
+ return ENOTDIR;
+
+ /* ok, now prepare to stat each file by adding it to the buffer */
+ p = &filename[strlen(filename)];
+ *p++ = '/';
+
+ while(1)
+ {
+ de=(struct dirent *)&buffer[0];
+ n=0;
+ len=getdents(fd, de, sizeof buffer);
+ if(!len)
+ break;
+ while(n<len)
+ {
+ if(strcmp(de->d_name,".") && strcmp(de->d_name,".."))
+ {
+ int add_file = 1;
+ int file_type = NO_TYPE;
+
+ switch(type)
+ {
+ case REP_DIR:
+ case VER_FILE:
+ /* check that the file is a CVS version or a directory */
+ if(strcmp(&de->d_name[strlen(de->d_name)-2],",v"))
+ {
+ /* stat the file */
+ strcpy(p,de->d_name);
+ if(0>stat(filename,&st))
+ add_file = 0;
+ if(!S_ISDIR(st.st_mode))
+ add_file = 0;
+ else
+ file_type = REP_DIR;
+ }
+ else
+ {
+ /* remove the ,v */
+ de->d_name[strlen(de->d_name)-2]=0;
+ add_file = 1;
+ file_type = VER_FILE;
+ }
+ break;
+ case STD_DIR:
+ case STD_FILE:
+ /* stat the file */
+ strcpy(p,de->d_name);
+ if(0>stat(filename,&st))
+ add_file = 0;
+ else
+ if(S_ISDIR(st.st_mode))
+ file_type = STD_DIR;
+ else
+ file_type = STD_FILE;
+ break;
+ default:
+ fprintf(stderr,"Unknown file type.\n");
+ }
+
+ /* if there is already a child with this name, don't add this one */
+ if(FindChild(ent, de->d_name, strlen(de->d_name)))
+ {
+ add_file = 0;
+ switch(ent->file_type)
+ {
+ case DELETED_DIR:
+ if(file_type==STD_DIR)
+ ent->file_type = CHECKOUT_DIR;
+ break;
+ case DELETED_FILE:
+ if(file_type==STD_DIR)
+ ent->file_type = CHECKOUT_FILE;
+ ent->file_type = CHECKOUT_FILE;
+ break;
+ }
+ }
+
+ if(add_file)
+ {
+ fprintf(stderr,"Adding %s\n",de->d_name);
+ t = CreateChild(de->d_name,file_type);
+
+ if(t)
+ {
+ /* add this to the head of the parent's child list */
+ t->parent = ent;
+ t->next = ent->child;
+ ent->child = t;
+ }
+ }
+ }
+ n+=de->d_reclen;
+ de = (struct dirent *)&buffer[n];
+ }
+ }
+ close(fd);
+
+ return 0;
+}
+
Added: trunk/filesystems/cvsfs/Makefile
==============================================================================
--- trunk/filesystems/cvsfs/Makefile 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/cvsfs/Makefile 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,38 @@
+CC = gcc
+CFLAGS = -O2 -Wall -I../../kernel
+CPPFLAGS = #-DDEBUG
+LDFLAGS = -s
+
+SRCS = cvsfs.c cvs.c cvsdir.c cvstree.c
+DISTS = $(SRCS) README Makefile
+
+cvsfs : cvsfs.o cvs.o cvsdir.o cvstree.o
+
+test: cvs.o
+ $(CC) $(CFLAGS) cvs.c -DTEST -o cvscat
+
+.PHONY : dist dep clean realclean spotless
+
+dep : .depend
+.depend : $(SRCS)
+ $(CC) $(CFLAGS) -MM *.c > .depend
+
+dist : $(DISTS)
+ rm -rf /tmp/cvsfs
+ mkdir /tmp/cvsfs
+ cp -a $(DISTS) /tmp/cvsfs
+ (cd /tmp; tar cfvz - cvsfs) >cvsfs.tar.gz
+ rm -rf /tmp/cvsfs
+
+clean :
+ rm -f *.o core *~ *.orig *.rej cvsfs
+
+realclean : clean
+ rm -rf cvsfs
+
+spotless : realclean
+ rm -f .depend
+
+ifeq (.depend,$(wildcard .depend))
+include .depend
+endif
Added: trunk/filesystems/cvsfs/README
==============================================================================
--- trunk/filesystems/cvsfs/README 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/cvsfs/README 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,42 @@
+Hello,
+
+cvsfs was derived from arcfs by David P Gymer.
+
+This code allows read only access to the latest versions in a CVS repositry.
+Reading is done on the fly. i have tested this by building "wine"
+
+This filesystem allows you to build a CVS module without checking it out of
+the repository.
+
+usage:
+ insmod kernel/src/userfs.o
+ utils/muserfs contrib/cvsfs/cvsfs /usr/src/mnt /usr/src/wine/cvs/wine \
+ /usr/src/wine/wine
+
+(/usr/src/wine/cvs/wine is the wine directory in my cvs repository)
+(/usr/src/wine/wine is the checkout directory)
+
+Normally, instead of using cvsfs you would type:
+ setenv CVSROOT /usr/src/wine/cvs
+ cd /usr/src/wine
+ cvs checkout wine
+ cd wine
+ configure
+ make depend
+ make
+
+After installing cvsfs, you can do the following:
+ setenv CVSROOT /usr/src/wine/cvs
+ cd /usr/src/wine
+ mkdir wine
+ mkdir mnt
+ <the install userfs and start cvsfs>
+ cd mnt
+ configure
+ make depend
+ make
+
+This way, you don't have to checkout the wine module to compile it...
+
+Mike McCormack 24 April 1999
+
Added: trunk/filesystems/gvfs/vfsbase.h
==============================================================================
--- trunk/filesystems/gvfs/vfsbase.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/gvfs/vfsbase.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,68 @@
+/*
+ * Portions of this work Copyright (C) 2001 Oracle Corporation
+ *
+ * This is free software. you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef _VFSBASE_H
+#define _VFSBASE_H
+
+#include <linux/userfs_types.h>
+
+#define FAIL(str) fprintf(stderr, "%s:%d %s failed with errno = %s (%d)\n", __FILE__, __LINE__, str, strerror(errno), errno)
+#ifdef DEBUG
+#include <stdio.h>
+#include <stdlib.h>
+#define DB(x) {x;}
+#else
+#define DB(x) /**/
+#endif
+#define DIRINO 1
+#define DIRECTORY_SIZE -1
+#define VFS_OPTAB_SIZE 25
+typedef int (*VfsOperation) (unsigned char *, upp_repl *);
+
+/* {
+ VfsOperation create;
+ VfsOperation lookup;
+ VfsOperation close;
+ VfsOperation read;
+ VfsOperation write;
+ VfsOperation truncate;
+ VfsOperation fsync;
+ VfsOperation readdir;
+ VfsOperation link;
+ VfsOperation unlink;
+ VfsOperation symlink;
+ VfsOperation readlink;
+ VfsOperation followlink;
+ VfsOperation mount;
+ VfsOperation umount;
+ VfsOperation iread;
+ VfsOperation iwrite;
+ VfsOperation statfs;
+ VfsOperation iput;
+ VfsOperation open;
+ VfsOperation permission;
+ VfsOperation rename;
+ VfsOperation multireaddir;
+ VfsOperation notify_change;
+ VfsOperation inode_valid;
+} VfsOptab; */
+
+
+#endif /* _VFSBASE_H */
Added: trunk/filesystems/gvfs/gvfsops.c
==============================================================================
--- trunk/filesystems/gvfs/gvfsops.c 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/gvfs/gvfsops.c 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,820 @@
+/*
+ * Portions of this work Copyright (C) 2001 Oracle Corporation
+ *
+ * This is free software. you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <utime.h>
+#include <dirent.h>
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include <getopt.h>
+#include <assert.h>
+
+#include <time.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/fcntl.h>
+
+#include <linux/fs.h>
+#include <linux/userfs_fs.h>
+
+#include <assert.h>
+
+/* #include <gnome.h> */
+#include <libgnomevfs/gnome-vfs.h>
+
+#include "vfsbase.h"
+#include "gvfs.h"
+
+
+static char *mpoint;
+static GVFS_DIRENT *root;
+
+static int do_gnome_vfs_readdir (GVFS_DIRENT * dir);
+static int make_root_inode (char *uri, GnomeVFSFileInfo * info);
+
+#ifdef DEBUG
+#define MESSAGE(x) fprintf(stderr, "%s\n", (x))
+#else
+#define MESSAGE(x)
+#endif
+
+
+static GVFS_DIRENT *
+make_gvfs_dirent (GVFS_DIRENT * dir, GnomeVFSFileInfo * info)
+{
+ GVFS_DIRENT *ent;
+ char *dirname;
+
+ dirname = dir->fullname;
+ ent = malloc (sizeof (GVFS_DIRENT) + strlen (dirname) + strlen (info->name) + 2);
+ if (!ent)
+ return NULL;
+
+ strcpy (ent->fullname, dirname);
+ strcat (ent->fullname, "/");
+ strcat (ent->fullname, info->name);
+ ent->name = ent->fullname + strlen (dirname) + 1;
+ ent->pdir = dir;
+ ent->next = 0;
+ ent->vfs_handle = 0;
+
+#define SET_FIELD(x, yup, nope) ( info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_##x ? (yup) : (nope) )
+ /* size better be a valid field!!!! */
+ ent->ino.size = SET_FIELD (SIZE, info->size, 0);
+ ent->ino.nlink = SET_FIELD (LINK_COUNT, info->link_count, 1);
+ ent->ino.mode = SET_FIELD (PERMISSIONS, info->permissions, 0777);
+ ent->ino.atime = SET_FIELD (ATIME, info->atime, time (0));
+ ent->ino.mtime = SET_FIELD (MTIME, info->mtime, time (0));
+ ent->ino.ctime = SET_FIELD (CTIME, info->ctime, time (0));
+ ent->ino.blksize = SET_FIELD (IO_BLOCK_SIZE, info->io_block_size, 512);
+ ent->ino.blocks =
+ SET_FIELD (BLOCK_COUNT, info->block_count, (ent->ino.size + 511) / 512);
+#undef SET_FIELD
+
+ /* hackola - user web is 100 */
+ ent->ino.uid = 100;
+ ent->ino.gid = 100;
+
+ if (info->type == GNOME_VFS_FILE_TYPE_DIRECTORY)
+ {
+ ent->ino.mode |= S_IFDIR;
+ ent->ino.size = -1; /* FIXME: this is redundant with S_IFDIR */
+ ent->data.dir.first = 0;
+ ent->data.dir.state = DIR_NEEDS_LOOKUP;
+ }
+ else
+ {
+ ent->ino.mode |= S_IFREG;
+ ent->data.file.vfs_pos = 0;
+ }
+ return ent;
+}
+
+
+static GVFS_DIRENT *
+root_ent (GVFS_DIRENT * ent)
+{
+ MESSAGE("root_ent");
+ while (ent->pdir != ent)
+ ent = ent->pdir;
+ return ent;
+}
+
+static GVFS_DIRENT *
+find_gvfs_dirent (GVFS_DIRENT * dir, char *name, int namelen)
+{
+ GVFS_DIRENT *ent;
+ MESSAGE("find_gvfs_dirent");
+ ent = NULL;
+ if (dir->data.dir.state == DIR_NEEDS_LOOKUP)
+ do_gnome_vfs_readdir (dir);
+ ent = dir->data.dir.first;
+ while (ent)
+ {
+ if (strncmp (ent->name, name, namelen) == 0 &&
+ strlen (ent->name) == namelen)
+ break;
+ ent = ent->next;
+ }
+ return ent;
+}
+
+
+static int
+do_iread (unsigned char *buf, upp_repl * repl)
+{
+ upp_iread_s rcv;
+ upp_iread_r snd;
+ MESSAGE("do_iread");
+
+ decode_upp_iread_s (&rcv, buf);
+
+ memset (&snd, 0, sizeof (snd));
+ snd.handle = rcv.handle;
+
+ if (rcv.handle.handle == DIRINO)
+ {
+ snd.ino.mode = 0444;
+ snd.ino.mode |= S_IFDIR | 0111;
+ snd.ino.mtime = snd.ino.ctime = snd.ino.atime = time (0);
+ snd.ino.nlink = 1;
+ }
+ else
+ {
+ GVFS_DIRENT *ent = (GVFS_DIRENT *) rcv.handle.handle;
+ memcpy (&snd.ino, &ent->ino, sizeof (up_inode));
+ if (snd.ino.size == -1)
+ snd.ino.size = 0;
+ }
+
+ repl->size = encode_upp_iread_r (&snd, buf) - buf;
+ MESSAGE("do_iread: done");
+ return 0;
+}
+
+static int
+do_gnome_vfs_readdir (GVFS_DIRENT * dir)
+{
+ GnomeVFSFileInfo *info;
+ GList *list, *tmp;
+ gchar *root_uri, *uri;
+ GVFS_DIRENT **ent;
+ MESSAGE("do_gnome_vfs_readdir");
+
+ uri = strdup (dir->fullname);
+ list = NULL;
+ signal (SIGCHLD, SIG_DFL);
+ if (gnome_vfs_directory_list_load (&list, uri,
+ (GNOME_VFS_FILE_INFO_GET_MIME_TYPE |
+ GNOME_VFS_FILE_INFO_FORCE_FAST_MIME_TYPE
+ | GNOME_VFS_FILE_INFO_FOLLOW_LINKS),
+ NULL) == GNOME_VFS_OK && list != NULL)
+ {
+ tmp = list;
+ ent = &(dir->data.dir.first);
+ while (tmp != NULL)
+ {
+ info = (GnomeVFSFileInfo *) (tmp->data);
+ if (info->type != GNOME_VFS_FILE_TYPE_DIRECTORY &&
+ info->type != GNOME_VFS_FILE_TYPE_REGULAR)
+ {
+ tmp = tmp->next;
+ continue;
+ }
+ if (strcmp (info->name, ".") == 0 || strcmp (info->name, "..") == 0)
+ {
+ tmp = tmp->next;
+ continue;
+ }
+ *ent = make_gvfs_dirent (dir, info);
+
+ tmp = tmp->next;
+ ent = &((*ent)->next);
+ }
+ gnome_vfs_file_info_list_free (list);
+ }
+ else
+ fprintf (stderr, "do_gnome_vfs_readdir: list_load FAILED for %s\n", uri);
+
+ signal (SIGCHLD, SIG_IGN);
+ free (uri);
+ dir->data.dir.state = DIR_OK;
+}
+
+static int
+do_lookup (unsigned char *buf, upp_repl * repl)
+{
+ upp_lookup_s rcv;
+ upp_lookup_r snd;
+ GVFS_DIRENT *ent;
+ MESSAGE("do_lookup");
+
+ decode_upp_lookup_s (&rcv, buf);
+
+ ent = (GVFS_DIRENT *) rcv.dir.handle;
+ if (ent->ino.size != -1)
+ return ENOTDIR;
+
+ if (rcv.name.nelem == 2
+ && rcv.name.elems[0] == '.' && rcv.name.elems[1] == '.')
+ {
+ ent = ent->pdir;
+ }
+ else if (rcv.name.nelem != 1 || rcv.name.elems[0] != '.')
+ {
+ ent = find_gvfs_dirent (ent, rcv.name.elems, rcv.name.nelem);
+ }
+ FREE (rcv.name.elems);
+ if (!ent)
+ return ENOENT;
+ snd.handle.handle = (Ulong) ent;
+
+ repl->size = encode_upp_lookup_r (&snd, buf) - buf;
+
+ return 0;
+}
+
+static int
+do_readdir (unsigned char *buf, upp_repl * repl)
+{
+ upp_readdir_s rcv;
+ upp_readdir_r snd;
+ GVFS_DIRENT *ent;
+ MESSAGE("do_readdir");
+
+ decode_upp_readdir_s (&rcv, buf);
+
+ ent = (GVFS_DIRENT *) rcv.dir.handle;
+ if (ent->ino.size != -1)
+ return ENOTDIR;
+
+ snd.off = 0;
+ snd.name.nelem = 0;
+
+ if (!rcv.off--)
+ {
+ snd.name.elems = ".";
+ }
+ else if (!rcv.off--)
+ {
+ snd.name.elems = "..";
+ ent = ent->pdir;
+ }
+ else
+ {
+ if (ent->data.dir.state == DIR_NEEDS_LOOKUP)
+ do_gnome_vfs_readdir (ent);
+ ent = ent->data.dir.first;
+ while (ent && rcv.off--)
+ ent = ent->next;
+ if (ent)
+ snd.name.elems = ent->name;
+ }
+
+ if (ent)
+ {
+ snd.off = 1;
+ snd.name.nelem = strlen (snd.name.elems);
+ snd.file.handle = (Ulong) ent;
+ }
+
+ repl->size = encode_upp_readdir_r (&snd, buf) - buf;
+
+ return 0;
+}
+
+static int
+gnome_vfs_handle_check (GnomeVFSHandle ** handle)
+{
+ GnomeVFSFileInfo info;
+
+ MESSAGE("gnome_vfs_handle_check: top");
+
+ if (!handle || !*handle)
+ {
+ MESSAGE("gnome_vfs_handle_check: NULL handle");
+ return 0;
+ }
+
+ return 1;
+
+#if 0
+ /* do not check the handle for now */
+ /* probably a bad idea anyway */
+ if (gnome_vfs_get_file_info_from_handle (*handle, &info,
+ GNOME_VFS_FILE_INFO_DEFAULT) ==
+ GNOME_VFS_OK)
+ {
+ MESSAGE("gnome_vfs_handle_check: good handle");
+ return 1;
+ }
+
+ MESSAGE("gnome_vfs_handle_check: BAD handle, clearing it!");
+ gnome_vfs_close (*handle);
+ *handle = 0;
+ return 0;
+#endif
+}
+
+static int
+do_open (unsigned char *buf, upp_repl * repl)
+{
+ upp_open_s rcv;
+ GVFS_DIRENT *ent;
+ gchar *root_uri, *uri;
+ int ret;
+
+ MESSAGE("do_open");
+ decode_upp_open_s (&rcv, buf);
+
+ ent = (GVFS_DIRENT *) rcv.file.handle;
+ MESSAGE(ent->fullname);
+ /* Directories are opened here, but read using _readdir instead of _read,
+ so all we do is return success! */
+ if (ent->ino.size == -1)
+ return 0;
+
+ /* is the vfs_handle already open and alive? */
+ if (gnome_vfs_handle_check (&ent->vfs_handle))
+ return 0;
+
+ MESSAGE("do_open: handle is OK");
+ uri = strdup (ent->fullname);
+
+ if (uri == NULL)
+ return EFBIG; /* ????? what to return here? */
+
+ ret = EINVAL;
+ ent->data.file.vfs_pos = 0;
+ signal (SIGCHLD, SIG_DFL);
+ MESSAGE("do_open: now doing the gnome_vfs_open");
+ if (gnome_vfs_open (&(ent->vfs_handle), uri, GNOME_VFS_OPEN_READ) == GNOME_VFS_OK)
+ {
+ ret = 0;
+ MESSAGE("do_open: FAILED in gnome_vfs_open");
+ }
+ signal (SIGCHLD, SIG_IGN);
+ free (uri);
+ MESSAGE("do_open: ok");
+ return ret;
+}
+
+static int
+do_close (unsigned char *buf, upp_repl * repl)
+{
+ upp_close_s rcv;
+ GVFS_DIRENT *ent;
+ MESSAGE("do_close");
+
+ decode_upp_close_s (&rcv, buf);
+
+ ent = (GVFS_DIRENT *) rcv.file.handle;
+ if (ent->ino.size == -1)
+ return 0;
+
+ if (ent->vfs_handle == 0)
+ return 0;
+
+ gnome_vfs_close (ent->vfs_handle);
+ ent->vfs_handle = 0;
+ ent->data.file.vfs_pos = 0;
+ return 0;
+
+}
+
+static int
+reopen_gnome_vfs (GVFS_DIRENT * ent, GnomeVFSOpenMode mode)
+{
+ fprintf(stderr, "reopen_gnome_vfs: %s : mode=%d\n", ent->fullname, (int)mode);
+ gnome_vfs_close (ent->vfs_handle);
+ signal (SIGCHLD, SIG_DFL);
+ if (gnome_vfs_open (&(ent->vfs_handle), ent->fullname, mode) != GNOME_VFS_OK)
+ {
+ signal (SIGCHLD, SIG_IGN);
+ return EPERM;
+ }
+ signal (SIGCHLD, SIG_IGN);
+ ent->data.file.vfs_pos = 0;
+ return 0;
+}
+
+static int
+fake_o_seek (GVFS_DIRENT * ent, GnomeVFSFileSize seekTo)
+{
+#define SEEK_BUF_SIZE 65536
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+#define MAX(a,b) (((a) > (b)) ? (a) : (b))
+ GnomeVFSFileSize seekActual;
+ int seekNum;
+ char *seekBuf = malloc (SEEK_BUF_SIZE);
+ MESSAGE("fake_o_seek");
+
+ while (ent->data.file.vfs_pos < seekTo)
+ {
+ seekNum = MIN (SEEK_BUF_SIZE, seekTo - ent->data.file.vfs_pos);
+ if (gnome_vfs_read (ent->vfs_handle, seekBuf, seekNum,
+ &seekActual) != GNOME_VFS_OK)
+ {
+ free (seekBuf);
+ return EPERM;
+ }
+ ent->data.file.vfs_pos += seekActual;
+ }
+ free (seekBuf);
+ return 0;
+#undef SEEK_BUF_SIZE
+#undef MIN
+#undef MAX
+}
+
+static int
+do_create (unsigned char *buf, upp_repl * repl)
+{
+ upp_create_s rcv;
+ upp_create_r snd;
+ GVFS_DIRENT *dir;
+ GVFS_DIRENT *ent;
+ char *newuri;
+ GnomeVFSHandle *handle;
+ int ret;
+ MESSAGE("do_create");
+
+ decode_upp_create_s (&rcv, buf);
+ dir = (GVFS_DIRENT *) rcv.dir.handle;
+
+ ent = find_gvfs_dirent (dir, rcv.name.elems, rcv.name.nelem);
+ if (ent)
+ {
+ snd.file.handle = (Ulong) ent;
+ repl->size = encode_upp_create_r (&snd, buf) - buf;
+ return 0;
+ }
+
+ newuri = malloc (rcv.name.nelem + strlen (dir->fullname) + 2);
+ strcpy (newuri, dir->fullname);
+ strcat (newuri, "/");
+ strncat (newuri, rcv.name.elems, rcv.name.nelem);
+ newuri[rcv.name.nelem + strlen (dir->fullname) + 1] = 0;
+
+ if (rcv.mode & S_IFDIR)
+ {
+ fprintf(stderr, "do_create: gnome_vfs_make_directory\n");
+ ret = gnome_vfs_make_directory (newuri, 0777);
+ if (ret != GNOME_VFS_OK)
+ {
+ fprintf(stderr, "gnome_vfs_make_directory failed for %s\n", newuri);
+ free (newuri);
+ return EPERM;
+ }
+ }
+ else
+ {
+ fprintf(stderr, "do_create: gnome_vfs_create\n");
+ ret = gnome_vfs_create (&handle, newuri, GNOME_VFS_OPEN_WRITE, 1, 0666);
+ if (ret != GNOME_VFS_OK)
+ {
+ fprintf(stderr, "gnome_vfs_create failed for %s\n", newuri);
+ free (newuri);
+ return EPERM;
+ }
+ }
+ free (newuri);
+
+ dir->data.dir.state = DIR_NEEDS_LOOKUP;
+ ent = find_gvfs_dirent (dir, rcv.name.elems, rcv.name.nelem);
+ if (ent == NULL)
+ return ENOENT;
+ if (handle)
+ ent->vfs_handle = handle;
+ snd.file.handle = (Ulong) ent;
+ repl->size = encode_upp_create_r (&snd, buf) - buf;
+ return 0;
+}
+
+static int
+do_read (unsigned char *mbuf, upp_repl * repl)
+{
+ upp_read_s rcv;
+ upp_read_r snd;
+ GVFS_DIRENT *ent;
+ int rc;
+ GnomeVFSFileSize fsize;
+ char *tmpbuf;
+ int ret;
+ MESSAGE("do_read");
+
+ snd.data.nelem = 0;
+
+ decode_upp_read_s (&rcv, mbuf);
+
+ ent = (GVFS_DIRENT *) rcv.file.handle;
+ if (ent->ino.size == -1)
+ return EISDIR;
+
+ if (!gnome_vfs_handle_check (&ent->vfs_handle))
+ return EBADF;
+
+ if ((unsigned long long) rcv.off < ent->data.file.vfs_pos)
+ {
+ ret = reopen_gnome_vfs (ent, GNOME_VFS_OPEN_READ);
+ if (ret)
+ return ret;
+ }
+
+ if ((unsigned long long) rcv.off > ent->data.file.vfs_pos)
+ {
+ ret = fake_o_seek (ent, (unsigned long long) rcv.off);
+ if (ret)
+ return ret;
+ }
+
+ tmpbuf = malloc (rcv.size);
+ gnome_vfs_read (ent->vfs_handle, tmpbuf, rcv.size,
+ (GnomeVFSFileSize *) & (snd.data.nelem));
+ snd.data.elems = tmpbuf;
+ ent->data.file.vfs_pos += snd.data.nelem;
+
+ repl->size = encode_upp_read_r (&snd, mbuf) - mbuf;
+ free (tmpbuf);
+
+ return 0;
+}
+
+static int
+do_write (unsigned char *mbuf, upp_repl * repl)
+{
+ upp_write_s rcv;
+ upp_write_r snd;
+ GVFS_DIRENT *ent;
+ int ret;
+ MESSAGE("do_write");
+
+ decode_upp_write_s (&rcv, mbuf);
+
+ ent = (GVFS_DIRENT *) rcv.file.handle;
+
+ if (ent->ino.size == -1)
+ return EISDIR;
+
+ if (!gnome_vfs_handle_check (&ent->vfs_handle))
+ return EBADF;
+ if (gnome_vfs_handle_get_open_mode (ent->vfs_handle) !=
+ GNOME_VFS_OPEN_WRITE)
+ {
+ fprintf(stderr, "do_write: mode!=GNOME_VFS_OPEN_WRITE, reopening\n");
+ ret = reopen_gnome_vfs (ent, GNOME_VFS_OPEN_WRITE);
+ if (ret)
+ return ret;
+ }
+
+ if ((unsigned long long) rcv.off != ent->data.file.vfs_pos)
+ {
+ fprintf (stderr,
+ "do_write: only SEQUENTIAL writes allowed for now!!!\n");
+ return EPERM;
+ }
+#if 0
+ if ((unsigned long long) rcv.off > ent->data.file.vfs_pos)
+ {
+ fprintf (stderr, "do_write: need to seek ahead: %ld -> %d\n",
+ ent->data.file.vfs_pos, rcv.off);
+ ret = fake_o_seek (ent, (unsigned long long) rcv.off);
+ if (ret)
+ return ret;
+ }
+#endif
+
+ if (gnome_vfs_write (ent->vfs_handle,
+ rcv.data.elems,
+ rcv.data.nelem,
+ (GnomeVFSFileSize *) & snd.wrote) != GNOME_VFS_OK)
+ {
+ fprintf (stderr, "error on gnome_vfs_write: pos=%d amt=%d wrote=%d\n",
+ ent->data.file.vfs_pos, rcv.data.nelem, snd.wrote);
+ return EPERM;
+ }
+ ent->data.file.vfs_pos += snd.wrote;
+
+ repl->size = encode_upp_write_r (&snd, mbuf) - mbuf;
+ return 0;
+}
+
+static int
+do_mount (unsigned char *buf, upp_repl * repl)
+{
+ upp_mount_r snd;
+ MESSAGE("do_mount");
+
+ snd.root.handle = (Ulong) root;
+ repl->size = encode_upp_mount_r (&snd, buf) - buf;
+ /* INIT */
+ /* kch: has no fucking clue why this is done 2x */
+ repl->size = encode_upp_mount_r (&snd, buf) - buf;
+ return 0;
+}
+
+static int
+do_truncate (unsigned char *buf, upp_repl * repl)
+{
+ upp_truncate_s rcv;
+ GVFS_DIRENT *ent;
+ MESSAGE("do_truncate");
+
+ decode_upp_truncate_s(&rcv, buf);
+ ent = (GVFS_DIRENT *)rcv.file.handle;
+
+ fprintf(stderr, "truncate called for file: %s\n", ent->fullname);
+ if (gnome_vfs_truncate(ent->fullname, rcv.size)!= GNOME_VFS_OK)
+ {
+ /* for our purposes, truncate never necessary */
+ /* famous last werdz */
+ return 0;
+ }
+
+ return 0;
+}
+
+static int
+do_unlink (unsigned char *buf, upp_repl *repl)
+{
+ upp_unlink_s rcv;
+ GVFS_DIRENT *dir, *ent;
+
+ decode_upp_unlink_s (&rcv, buf);
+ dir = (GVFS_DIRENT *) rcv.dir.handle;
+ ent = find_gvfs_dirent (ent, rcv.name.elems, rcv.name.nelem);
+ fprintf(stderr, "for now, I am IGNORING unlink for file: %s\n", ent->fullname);
+ return 0;
+}
+
+
+static VfsOperation gvfs_optab[] = {
+ do_create, /* create */
+ do_lookup, /* lookup */
+ do_close, /* close */
+ do_read, /* read */
+ do_write, /* write */
+ do_truncate, /* truncate */
+ NULL, /* fsync */
+ do_readdir, /* readdir */
+ NULL, /* link */
+ do_unlink, /* unlink */
+ NULL, /* symlink */
+ NULL, /* readlink */
+ NULL, /* followlink */
+ do_mount, /* mount */
+ NULL, /* umount */
+ do_iread, /* iread */
+ NULL, /* iwrite */
+ NULL, /* statfs */
+ NULL, /* iput */
+ do_open, /* open */
+ NULL, /* permission */
+ NULL, /* rename */
+ NULL, /* multireaddir */
+ NULL, /* notify_change */
+ NULL /* inode_valid */
+};
+
+
+int
+main (int argc, char **argv)
+{
+ int infd = 0;
+ int outfd = 1;
+ int c;
+ char *uri;
+ GnomeVFSFileInfo info;
+ MESSAGE("main");
+
+ gnome_vfs_init ();
+ while ((c = getopt (argc, argv, "i:o:m:")) != EOF)
+ switch (c)
+ {
+ case 'i':
+ infd = atoi (optarg);
+ break;
+ case 'o':
+ outfd = atoi (optarg);
+ break;
+ case 'm':
+ mpoint = optarg;
+ break;
+ default:
+ fprintf (stderr, "%s: bad option\n", argv[0]);
+ return 1;
+ }
+
+ if (optind != argc - 1)
+ {
+ fprintf (stderr, "%s: no URI given\n", argv[0]);
+ return 1;
+ }
+
+ uri = malloc (strlen (argv[optind]) + 2);
+ strcpy (uri, argv[optind]);
+#if 0
+ if (*(uri + strlen (uri) - 1) != '/')
+ strcat (uri, "/");
+#endif
+
+ memset (&info, 0, sizeof (info));
+ if (gnome_vfs_get_file_info (uri, &info, GNOME_VFS_FILE_INFO_DEFAULT) !=
+ GNOME_VFS_OK)
+ {
+ fprintf (stderr, "%s: bad URI given: %s\n", argv[0], uri);
+ free (uri);
+ return 1;
+ }
+ if (make_root_inode (uri, &info))
+ {
+ free (uri);
+ return 1;
+ }
+ free (uri);
+ signal (SIGCHLD, SIG_IGN);
+ run (gvfs_optab, outfd, infd);
+ gnome_vfs_shutdown ();
+ return 0;
+}
+
+static int
+make_root_inode (char *uri, GnomeVFSFileInfo * info)
+{
+ MESSAGE("make_root_inode");
+ root = malloc (sizeof (GVFS_DIRENT) + strlen (uri) + 1);
+ if (!root)
+ {
+ fprintf (stderr, "not enough memory to create root inode... LATER!\n");
+ return 1;
+ }
+
+ root->next = 0;
+ root->vfs_handle = 0;
+ root->ino.size = -1;
+ root->ino.nlink = 1; /* 2? */
+ root->ino.mode = S_IFDIR | 0777;
+ root->ino.atime = time (0);
+ root->ino.mtime = time (0);
+ root->ino.ctime = time (0);
+ root->ino.blksize = 512;
+ root->ino.blocks = 0;
+ root->ino.uid = 100;
+ root->ino.gid = 100;
+ root->pdir = root;
+ root->data.dir.first = 0;
+ root->data.dir.state = DIR_NEEDS_LOOKUP;
+
+ if (info->type & GNOME_VFS_FILE_TYPE_DIRECTORY)
+ {
+ strcpy (root->fullname, uri);
+ root->name = root->fullname;
+ fprintf (stderr, "normal URI\n");
+ }
+ else if (info->type & GNOME_VFS_FILE_TYPE_REGULAR)
+ {
+ GVFS_DIRENT *ent;
+ char *tmp;
+
+ fprintf (stderr, "file URI (doing some funky shit)\n");
+ tmp = strrchr (uri, '/');
+ if (tmp == NULL)
+ {
+ free (root);
+ return 1;
+ }
+ tmp++;
+ *tmp = 0;
+ strcpy (root->fullname, uri);
+ root->name = root->fullname;
+ ent = make_gvfs_dirent (root, info);
+ if (ent)
+ {
+ root->data.dir.first = ent;
+ root->data.dir.state = DIR_OK;
+ }
+ }
+
+ return 0;
+}
Added: trunk/filesystems/gvfs/vfsbase.c
==============================================================================
--- trunk/filesystems/gvfs/vfsbase.c 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/gvfs/vfsbase.c 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,242 @@
+/*
+ * Portions of this work Copyright (C) 2001 Oracle Corporation
+ *
+ * This is free software. you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <utime.h>
+#include <dirent.h>
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include <getopt.h>
+#include <assert.h>
+
+#include <time.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/fcntl.h>
+
+#include <linux/fs.h>
+#include <linux/userfs_fs.h>
+
+#include <assert.h>
+
+#include "vfsbase.h"
+
+/* No point in this being in a seperate file. */
+#include <linux/userfs_types.c>
+
+int
+myread (int fd, void *buf, int sz)
+{
+ int rd = 0;
+ int ret;
+
+ while (sz > 0)
+ {
+ ret = read (fd, buf, sz);
+
+ if (ret == -1)
+ {
+ if (errno == EINTR)
+ continue;
+
+ perror ("myread");
+ exit (1);
+ }
+
+ if (ret == 0)
+ break;
+
+ sz -= ret;
+ buf += ret;
+ rd += ret;
+ }
+
+ return rd;
+}
+
+int
+mywrite (int fd, const void *buf, int sz)
+{
+ int wr = 0;
+ int ret;
+
+ while (sz > 0)
+ {
+ ret = write (fd, buf, sz);
+
+ if (ret == -1)
+ {
+ if (errno == EINTR)
+ continue;
+ if (errno == EPIPE)
+ {
+ fprintf (stderr, "Eeeeek! A broken pipe on write! ");
+ fprintf (stderr, "wrote: %d/%d bytes\n", wr, sz);
+ return -1;
+ }
+ FAIL ("write");
+ exit (1);
+ }
+
+ if (ret == 0)
+ {
+ fprintf (stderr, "write wrote 0 bytes\n");
+ break;
+ }
+
+ sz -= ret;
+ buf += ret;
+ wr += ret;
+ }
+
+ return wr;
+}
+
+int
+readpkt (int fd, up_preamble * pre, unsigned char *buf)
+{
+ int presz = sizeof_up_preamble (pre);
+ unsigned int rd;
+ unsigned char pbuf[presz];
+
+ memset (pbuf, 0, sizeof (pbuf));
+
+ rd = myread (fd, pbuf, presz);
+ if (rd != presz)
+ {
+ if (rd == 0)
+ return 0;
+ if (rd > 0)
+ fprintf (stderr, "readpkt, incomplete read (%d, not %d)\n",
+ rd, presz);
+ perror ("readpkt, header read");
+ return -1;
+ }
+
+ decode_up_preamble (pre, pbuf);
+
+ if (pre->isreq != UP_ENQ && pre->isreq != UP_REQ)
+ fprintf (stderr, "pre->isreq = %d\n", pre->isreq);
+
+ if (pre->version != UP_VERSION)
+ {
+ fprintf (stderr, "Version mismatch: us=%d them=%d\n",
+ UP_VERSION, pre->version);
+ return -1;
+ }
+
+ if (pre->size != 0)
+ {
+ if (myread (fd, buf, pre->size) != pre->size)
+ {
+ perror ("readpkt, body read");
+ return -1;
+ }
+ }
+
+ return 1;
+}
+
+int
+writepkt (int fd, upp_repl * repl, const unsigned char *buf)
+{
+ int replsz = sizeof_upp_repl (repl);
+ unsigned char pbuf[replsz];
+ unsigned int wr;
+ unsigned char *p;
+
+ assert (repl->version == UP_VERSION);
+ assert (repl->isreq == UP_REPL);
+
+ p = encode_upp_repl (repl, pbuf);
+
+ assert (replsz == p - pbuf);
+
+ wr = mywrite (fd, pbuf, replsz);
+ if (wr != replsz)
+ {
+ perror ("writepkt, header write");
+ return -1;
+ }
+
+ if (repl->size > 0 && repl->err_no == 0)
+ {
+ if (mywrite (fd, buf, repl->size) != repl->size)
+ {
+ perror ("writepkt, body write");
+ return -1;
+ }
+ }
+
+ return 1;
+}
+
+void
+genpkt (upp_repl * repl, int seq, up_ops op)
+{
+ repl->version = UP_VERSION;
+ repl->seq = seq;
+ repl->op = op;
+ repl->isreq = 0;
+ repl->size = 0;
+ repl->err_no = 0;
+}
+
+void
+run (VfsOperation optab[], int wr, int rd)
+{
+ up_preamble pre;
+ upp_repl repl;
+ unsigned char buf[4096];
+ int error, ret1, ret2;
+
+ while ((ret1=readpkt (rd, &pre, buf)) == 1)
+ {
+ genpkt (&repl, pre.seq, pre.op);
+
+ if ((unsigned int) pre.op >= VFS_OPTAB_SIZE ||
+ optab[(unsigned int) pre.op] == NULL)
+ {
+ fprintf(stderr, "run: some op i don't handle: %d\n", pre.op);
+ error = ENOSYS;
+ }
+ else
+ {
+ VfsOperation op = optab[pre.op];
+ error = (pre.isreq == UP_ENQ ? 0 : (*op) (buf, &repl));
+ }
+
+ repl.err_no = error;
+ if (error != 0)
+ repl.size = 0;
+
+ if ((ret2=writepkt (wr, &repl, buf)) != 1)
+ {
+ fprintf(stderr, "run: writepkt returned %d exiting\n", ret2);
+ break;
+ }
+ }
+ if (ret1!=1)
+ fprintf(stderr, "run: readpkt returned %d exiting\n", ret1);
+}
Added: trunk/filesystems/gvfs/gvfs.h
==============================================================================
--- trunk/filesystems/gvfs/gvfs.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/gvfs/gvfs.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,69 @@
+/*
+ * Portions of this work Copyright (C) 2001 Oracle Corporation
+ *
+ * This is free software. you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef GVFS_H
+#define GVFS_H
+
+#include "vfsbase.h"
+
+/* static VfsOperation do_mount, do_iread, do_lookup, do_readdir;
+static VfsOperation do_open, do_close, do_read; */
+
+typedef enum
+{
+ DIR_NEEDS_LOOKUP,
+ DIR_OK
+}
+gvfs_dir_state;
+
+typedef struct tagDIRENT GVFS_DIRENT;
+struct tagDIRENT
+{
+ GVFS_DIRENT *next;
+ GVFS_DIRENT *pdir; /* The directory to which this belongs, or self for root */
+ up_inode ino;
+ GnomeVFSHandle *vfs_handle;
+ union
+ {
+ struct
+ {
+ GnomeVFSFileSize vfs_pos;
+ }
+ file;
+ struct
+ {
+ gvfs_dir_state state;
+ GVFS_DIRENT *first;
+ }
+ dir;
+ }
+ data;
+ char *name;
+ char fullname[1];
+};
+
+/*
+int a_open (ARC_DIRENT *);
+int a_close (ARC_DIRENT *);
+int a_read (ARC_DIRENT *, long, long, unsigned long *, unsigned char **);
+ARC_DIRENT *arc_read (const char *);
+*/
+
+#endif /* GVFS_H */
Added: trunk/filesystems/gvfs/Makefile
==============================================================================
--- trunk/filesystems/gvfs/Makefile 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/gvfs/Makefile 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,40 @@
+CC = gcc
+CFLAGS = -DDEBUG -g -I../../kernel -I/usr/local/userfs/include -I/usr/local/userfs/lib/vfs/include -D_REENTRANT -I/home/manish/nicstuff/gnome-vfs-1.0.1 `pkg-config glib-2.0 --cflags`
+CPPFLAGS = #-DDEBUG
+LDFLAGS = -g -s -L/usr/local/userfs/lib -lgnomevfs -lpthread -L/usr/lib -L/usr/X11R6/lib -rdynamic `pkg-config glib-2.0 --libs`
+
+NAME = gvfs
+SRCS = gvfsops.c vfsbase.c
+INC = gvfs.h vfsbase.h
+DISTS = $(SRCS) $(INC) README Makefile
+
+$(NAME) : $(SRCS:%.o=%.c)
+
+gvfs : gvfsops.o vfsbase.o
+ gcc -DDEBUG $(CFLAGS) $(LDFLAGS) vfsbase.o gvfsops.o -o gvfs
+
+.PHONY : dist dep clean realclean spotless
+
+dep : .depend
+.depend : $(SRCS) $(INC)
+ $(CC) $(CFLAGS) -MM *.c > .depend
+
+dist : $(DISTS)
+ rm -rf /tmp/$(NAME)
+ mkdir /tmp/$(NAME)
+ cp -a $(DISTS) /tmp/$(NAME)
+ (cd /tmp; tar cfvz - $(NAME)) >$(NAME).tar.gz
+ rm -rf /tmp/$(NAME)
+
+clean :
+ rm -f *.o core *~ *.orig *.rej gvfs
+
+realclean : clean
+ rm -rf gvfs
+
+spotless : realclean
+ rm -f .depend
+
+ifeq (.depend,$(wildcard .depend))
+include .depend
+endif
Added: trunk/filesystems/homer/homer.h
==============================================================================
--- trunk/filesystems/homer/homer.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/homer/homer.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,16 @@
+// -*- C++ -*-
+
+#include "Filesystem.h"
+
+class password;
+
+class homer:public Filesystem
+{
+protected:
+ int Enquire(up_ops op);
+
+ int do_mount(const up_preamble &, upp_repl &, upp_mount_r &);
+
+public:
+ homer(const char *, password *);
+};
Added: trunk/filesystems/homer/password.cc
==============================================================================
--- trunk/filesystems/homer/password.cc 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/homer/password.cc 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,76 @@
+// -*- C++ -*-
+// Passwords, specifically for ``homer''
+
+#include "password.h"
+#include <stdlib.h>
+#include <string.h>
+
+const pwent *
+password::entry(int ino)
+{
+ pwent *pwe;
+
+ for(pwe = pwlist; pwe != NULL; pwe = pwe->next)
+ if (pwe->ino == ino)
+ return pwe;
+ return NULL;
+}
+
+const pwent *
+password::entry(const char *name)
+{
+ pwent *pwe;
+
+ for(pwe = pwlist; pwe != NULL; pwe = pwe->next)
+ if (strcmp(name, pwe->name) == 0)
+ return pwe;
+ return NULL;
+}
+
+const pwent *
+password::entry(const char *name, int len)
+{
+ pwent *pwe;
+
+ for(pwe = pwlist; pwe != NULL; pwe = pwe->next)
+ if (strncmp(name, pwe->name, len) == 0)
+ return pwe;
+ return NULL;
+}
+
+password::password()
+{
+ passwd *pw;
+ pwent *pwe;
+
+ update = time(0);
+ pwlist = NULL;
+ ino = 0;
+ while((pw = getpwent()) != NULL)
+ {
+ pwe = new pwent;
+
+ pwe->dir = strdup(pw->pw_dir);
+ pwe->name = strdup(pw->pw_name);
+ pwe->uid = pw->pw_uid;
+ pwe->gid = pw->pw_gid;
+ pwe->ino = ino++;
+ pwe->next = pwlist;
+ pwlist = pwe;
+ }
+ endpwent();
+}
+
+password::~password()
+{
+ pwent *next;
+
+ for(; pwlist != NULL; pwlist = next)
+ {
+ next = pwlist->next;
+ free(pwlist->dir);
+ free(pwlist->name);
+ delete pwlist;
+ }
+}
+
Added: trunk/filesystems/homer/Makefile
==============================================================================
--- trunk/filesystems/homer/Makefile 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/homer/Makefile 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,22 @@
+TOP=../..
+include $(TOP)/rules
+FLAGS=-I$(TOP)/kernel -I$(TOP)/lib -I$(TOP)/genser
+CXXFLAGS = $(FLAGS)
+CFLAGS = $(FLAGS)
+
+LDFLAGS = $(PROF)
+PROGS=homer
+
+HOMEOBJ = homer.o password.o
+
+all:: $(PROGS)
+
+homer: $(HOMEOBJ) $(DEPLIBUSERFS)
+ $(CXX) $(LDFLAGS) -o $@ $(HOMEOBJ) $(LIBUSERFS)
+
+clean:: dummy
+ rm -f *.o *~ core $(PROGS)
+
+dep depend::
+ $(CXX) $(CXXFLAGS) -M *.cc > .depend
+
Added: trunk/filesystems/homer/homer.cc
==============================================================================
--- trunk/filesystems/homer/homer.cc 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/homer/homer.cc 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,206 @@
+// -*- C++ -*-
+// Find home
+// A simple user process filesystem. This one sets up a dir full
+// of symlinks pointing to everyone in /etc/passwd's home dirs.
+//
+// This program is distributed under the terms of the
+// Free Software Foundation General Public Licence.
+// Copyright Jeremy Fitzhardinge 1993
+
+#include <Comm.h>
+#include <Filesystem.h>
+#include <DirInode.h>
+#include <SimpleInode.h>
+#include "homer.h"
+#include "password.h"
+#include <sys/stat.h>
+#include <getopt.h>
+#include <signal.h>
+#include "dbg.h"
+
+// Choose an inode number for the filesystem. We use the line
+// number in /etc/passwd as the inode, starting from zero, so have
+// something high to avoid it. This can be bigger, but it gets
+// unwieldy.
+const Handle DIRINO = 65534;
+
+// This is all the operations the filesystem as a whole will accept
+// from the kernel. This is done this way so that if the kernel
+// asks about completely new operations we can still say "no".
+int
+homer::Enquire(up_ops op)
+{
+ LOG("enq");
+ switch(op)
+ {
+ case userfs_up_mount:
+ case userfs_up_iread:
+ case userfs_up_readdir:
+ case userfs_up_multireaddir:
+ case userfs_up_lookup:
+ case userfs_up_readlink:
+// case userfs_up_unlink:
+ return 0;
+
+ default:
+ // Rather than just failing, ask our base class
+ return Filesystem::Enquire(op);
+ }
+}
+
+// Just another constructor for the generic directory inode
+// After construction everything is handled by the base class
+class dirino:public DirInode
+{
+public:
+ dirino::dirino(Filesystem &, Handle, password *);
+};
+
+// A symlink to the home dir
+// This has most of the work in it, but there isn't very much
+// to do.
+class nameino:public SimpleInode
+{
+ char *dir;
+ int dirlen;
+
+protected:
+ int do_readlink(const up_preamble &, upp_repl &,
+ const upp_readlink_s &, upp_readlink_r &);
+public:
+ nameino(Filesystem &, Handle, uid_t, gid_t, char *);
+ virtual ~nameino();
+};
+
+nameino::nameino(Filesystem &fs, Handle hand,
+ uid_t u, gid_t g, char *d)
+ : SimpleInode(fs, hand)
+{
+ uid = u;
+ gid = g;
+ dir = strdup(d);
+ size = dirlen = strlen(d);
+ mode = S_IFLNK | 0777;
+ atime = ctime = mtime = time(0);
+}
+
+nameino::~nameino()
+{
+ free(dir);
+}
+
+// Make a dir entry for each line in the passwd file, and init our
+// own inode values.
+dirino::dirino(Filesystem &fs, Handle h, password *pw)
+ :DirInode(fs, h, this)
+{
+ const pwent *pwe;
+
+ pwe = pw->getlist();
+
+ for (; pwe != NULL; pwe = pwe->next)
+ {
+ Inode *ino = findino(pwe->ino);
+ link(pwe->name, ino);
+ }
+
+ uid = getuid();
+ gid = getgid();
+ mode = S_IFDIR | 0555;
+ mtime = ctime = atime = time(0);
+}
+
+// Constructor for the filesystem.
+// This creates all the filesystem's inodes from the password file,
+// then creates a single directory to give them names.
+homer::homer(const char *mpoint, password *pw) : Filesystem(mpoint)
+{
+ const pwent *pwe = pw->getlist();
+
+ for(; pwe != NULL; pwe = pwe->next)
+ new nameino(*this, pwe->ino, pwe->uid, pwe->gid, pwe->dir);
+
+ new dirino(*this, DIRINO, pw);
+}
+
+int
+homer::do_mount(const up_preamble &pre, upp_repl &repl,
+ upp_mount_r &ret)
+{
+ ret.root.handle = DIRINO;
+ return 0;
+}
+
+int
+nameino::do_readlink(const up_preamble &pre, upp_repl &repl,
+ const upp_readlink_s &arg, upp_readlink_r &ret)
+{
+ LOG("readlink");
+
+ atime = time(0);
+ ret.name.elems = (__s8 *)dir;
+ ret.name.nelem = dirlen;
+
+ return 0;
+}
+
+const char *mpoint = NULL;
+
+int
+main(int argc, char *argv[])
+{
+ int infd = 0;
+ int outfd = 1;
+ int c;
+
+ LOG("Starting");
+
+#ifdef DEBUG
+ printf("pid=%d\n", getpid());
+ getchar();
+#endif
+
+ // Parse the command line options from muserfs
+ while((c = getopt(argc, argv, "i:o:m:")) != EOF)
+ switch(c)
+ {
+ case 'i':
+ infd = atoi(optarg);
+ break;
+
+ case 'o':
+ outfd = atoi(optarg);
+ break;
+
+ case 'm':
+ mpoint = optarg;
+ break;
+
+ default:
+ fprintf(stderr, "%s: bad option\n", argv[0]);
+ exit(1);
+ }
+
+ signal(SIGCHLD, SIG_IGN);
+
+ LOG("GOING to run");
+
+ // Create password file class
+ password pwfile;
+
+ // Create filesystem
+ homer homefs(mpoint, &pwfile);
+
+ // Create communications with kernel
+ Comm comm(homefs, outfd, infd);
+
+ fprintf(stderr, "now communicating with kernel\n");
+
+ // Run -- doesn't return until EOF or error
+ if (comm.Run() == -1)
+ fprintf(stderr, "Something went wrong!\n");
+
+ LOG("Stop");
+
+ return 0;
+}
Added: trunk/filesystems/mailfs/mailfs.cc
==============================================================================
--- trunk/filesystems/mailfs/mailfs.cc 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/mailfs/mailfs.cc 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,119 @@
+// -*- C++ -*-
+
+// Example filesystem
+
+#pragma implementation
+
+// Misc headers
+#include <GetOpt.h>
+
+// Filesystem related headers
+#include <Comm.h>
+#include "mailfs.h"
+//#include "mailfile.h"
+#include "maildir.h"
+
+// A simple constructor for the filesystem
+// All this does is pass the arguments to the base class
+// and initialize the inode handle counter.
+// The counter is for generating unique handles as required.
+// The mechanism used is very simple, because there is a bounded
+// number of inodes.
+mailfs::mailfs(const char *mpoint, const char *mail)
+ : Filesystem(mpoint)
+{
+ hcount=2;
+ mail_file = mail;
+ ifile = new ifstream(mail);
+}
+
+mailfs::~mailfs()
+{
+ if(ifile)
+ delete ifile;
+}
+
+// Declare to the kernel which operations we will support.
+int
+mailfs::Enquire(up_ops op)
+{
+ switch(op)
+ {
+ case up_mount:
+ case up_iread:
+ case up_readdir:
+ case up_multireaddir:
+ case up_lookup:
+ case up_read:
+ case up_readlink:
+ case up_rename:
+ case up_unlink:
+ return 0;
+ default:
+ break;
+ }
+ return Filesystem::Enquire(op);
+}
+
+// Do the mount. This simply returns the handle of the root
+// directory and creates the directory.
+int
+mailfs::do_mount(const up_preamble &, upp_repl &,
+ upp_mount_r &ret)
+{
+ Inode *root = new mailtopdir(*this, genhand(), NULL);
+ ret.root.handle = root->gethandle();
+ return 0;
+}
+
+// Parse the arguments from muserfs and construct the filesystem
+// and communications.
+int
+main(int argc, char **argv)
+{
+ GetOpt getopt(argc, argv, "i:o:m:f:");
+ int optch, err = 0;
+ int infd, outfd;
+ const char *mpoint = "";
+ const char *mfile;
+
+ mfile = getenv("MAIL");
+ infd = outfd = -1;
+ while((optch = getopt()) != EOF)
+ switch(optch)
+ {
+ case 'i':
+ infd = atoi(getopt.optarg);
+ break;
+ case 'o':
+ outfd = atoi(getopt.optarg);
+ break;
+ case 'm':
+ mpoint = getopt.optarg;
+ break;
+ case 'f':
+ mfile = getopt.optarg;
+ break;
+ default:
+ err++;
+ }
+
+ if (err)
+ {
+ fprintf(stderr, "Usage: %s -i infd -o outfd -m mpoint -f mailfile\n",
+ argv[0]);
+ exit(1);
+ }
+
+#if 0 && DEBUG
+ printf("pid=%d, return to cont\n", getpid());
+ getchar();
+#endif
+ mailfs efs(mpoint, mfile);
+ Comm comm(efs, outfd, infd);
+
+ if (comm.Run() == -1)
+ fprintf(stderr, "%s: Comm.Run() failed!\n", argv[0]);
+
+ return 0;
+}
Added: trunk/filesystems/mailfs/mailfs.h
==============================================================================
--- trunk/filesystems/mailfs/mailfs.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/mailfs/mailfs.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,33 @@
+// -*- C++ -*-
+
+// Example filesystem
+
+#ifndef _MAILFS_H_
+#define _MAILFS_H_
+
+#include <Filesystem.h>
+#include <String.h>
+#include <fstream.h>
+
+#pragma interface
+
+class mailfs:public Filesystem
+{
+ Handle hcount;
+ String mail_file;
+ ifstream *ifile;
+
+ int Enquire(up_ops);
+
+ int do_mount(const up_preamble &, upp_repl &, upp_mount_r &);
+
+public:
+ mailfs(const char *, const char *);
+ ~mailfs();
+
+ Handle genhand() { return hcount++; }
+ String mail() { return mail_file; };
+ ifstream *file() { return ifile; };
+};
+
+#endif /* _MAILFS_H_ */
Added: trunk/filesystems/mailfs/maillink.cc
==============================================================================
--- trunk/filesystems/mailfs/maillink.cc 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/mailfs/maillink.cc 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,29 @@
+// -*- C++ -*-
+
+#pragma implementation
+
+#include "maillink.h"
+
+#include <unistd.h>
+#include <sys/stat.h>
+
+maillink::maillink(Filesystem &fs, Handle h, String str)
+ : SimpleInode(fs, h), str(str)
+{
+ uid = getuid();
+ gid = getgid();
+ mode = S_IFLNK | 0777;
+ size = str.length();
+// atime = ctime = mtime = time(0);
+}
+
+int
+maillink::do_readlink(const up_preamble &, upp_repl &,
+ const upp_readlink_s &arg, upp_readlink_r &ret)
+{
+// atime = time(0);
+
+ ret.name.elems = (char *)str.chars();
+ ret.name.nelem = str.length();
+ return 0;
+}
Added: trunk/filesystems/mailfs/maildir.cc
==============================================================================
--- trunk/filesystems/mailfs/maildir.cc 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/mailfs/maildir.cc 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,139 @@
+// -*- C++ -*-
+
+#pragma implementation
+
+#include "maildir.h"
+#include "mailfile.h"
+#include "maillink.h"
+#include "mailfs.h"
+#include "mail.h"
+
+#include <sys/stat.h>
+#include <unistd.h>
+
+maildir::maildir(mailfs &fs, Handle h, Inode *p, time_t t)
+ : DirInode(fs, h, p)
+{
+ uid = getuid();
+ gid = getgid();
+ mode = S_IFDIR | 0555;
+ ifile = NULL;
+ atime = ctime = mtime = t;
+}
+
+maildir::maildir(mailfs &fs, Handle h, Inode *p, ifstream *ifile, streampos start, int l, time_t t)
+ : DirInode(fs, h, p), start(start), ifile(ifile)
+{
+ uid = getuid();
+ gid = getgid();
+ mode = S_IFDIR | 0555;
+ length = l;
+ atime = ctime = mtime = t;
+}
+
+// This constructs the entire directory heirachy for this
+// filesystem.
+mailtopdir::mailtopdir(mailfs &fs, Handle h, Inode *p)
+ : maildir(fs, h, p, time(NULL))
+{
+// String mailfn = getenv("MAIL");
+ puts("Parsing... ");
+ mail nmail(fs.file());
+ puts("done");
+ int i, iform = 0;
+ Pix a, b;
+ String name;
+ char num[16], form[16];
+// DLList<message> &m;
+// DLList<header> &hdr;
+ DirInode *d;
+ Inode *f;
+ ifstream *file;
+ streampos offset;
+ int len, body;
+ time_t tm;
+
+ if(iform > 0)
+ sprintf(form, "%%0%d.", iform);
+ else
+ strcpy(form, "%d.");
+// nmail.disp();
+ DLList<message> &m = nmail.contents();
+ for(i = 1, a = m.first(); a != NULL; m.next(a), i++)
+ {
+ sprintf(num, form, i);
+ name = num + m(a).name();
+
+ m(a).report(file, offset, len, body, tm);
+ d = new maildir(fs, fs.genhand(), this, file, offset, len, tm);
+ link(name, d);
+ f = new mailfile(fs, fs.genhand(), file, offset + body, len - body, tm);
+ d->link("body.txt", f);
+ f = new mailfile(fs, fs.genhand(), file, offset, len, tm);
+ d->link(".complete.txt", f);
+
+ DLList<header> &hdr = *(m(a).headers());
+ for(b = hdr.first(); b != NULL; hdr.next(b))
+ {
+ hdr(b).report(file, offset, len);
+ f = new mailfile(fs, fs.genhand(), file, offset, len, tm);
+ d->link(hdr(b).name(), f);
+ }
+ }
+ puts("MAILFS ready");
+
+/*
+ link("test1", new mailfile(fs, fs.genhand(), "Hello, world!\n"));
+ link("test2", new mailfile(fs, fs.genhand(), "Wooba wooba...\n"));
+
+ link("link1", new maillink(fs, fs.genhand(), "/usr/bin"));
+
+ DirInode *d1 = new maildir(fs, fs.genhand(), this);
+ DirInode *d2 = new maildir(fs, fs.genhand(), this);
+
+ link("dir1", d1);
+ link("dir2", d2);
+
+ Inode *f1 = new mailfile(fs, fs.genhand(), "File with multiple names\n");
+ d1->link("linked-file", f1);
+ d2->link("another-link", f1);
+
+ Inode *f2 = new mailfile(fs, fs.genhand(), "Piffle woodle.\n");
+ d2->link("strange", f2);
+*/
+}
+
+int
+maildir::do_read(const up_preamble &pre, upp_repl &repl,
+ const upp_read_s &arg, upp_read_r &ret)
+{
+ int sz, off; // legth of returned bunch
+ // Bunch is requested by kernel. Kernel asks for bunch of
+ // arg.size bytes starting from arg.off
+
+ if(!ifile)
+ return EISDIR;
+
+// ret.data.nelem = 0;
+// return 0;
+
+ // i = arg.file;
+ off = arg.off;
+ sz = arg.size;
+ // l = arg.ctok;
+
+ if(off >= length)
+ {
+ ret.data.nelem = 0; // send EOF
+ }
+ else
+ {
+ if(off + sz > length)
+ sz = length - off;
+ ret.data.alloc(ret.data.nelem = sz);
+ ifile->seekg(start + off);
+ ifile->read(ret.data.elems, sz);
+ }
+ return 0;
+}
+
Added: trunk/filesystems/mailfs/TODO
==============================================================================
--- trunk/filesystems/mailfs/TODO 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/mailfs/TODO 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,15 @@
+[x] 1. cut down RAM usage
+[x] 2. Date -> mtime
+[x] 3. Replace trouble chars with _
+[x] 4. use zero leading numbers.
+[x] 5. Take "From:" name with more sense - care: no "/"!
+[x] 6. Use Content-Length to determine how much is in body.txt
+[x] 7. Use Lines to determine number of lines in the body.txt
+[ ] 8. highlighted file without .txt
+[ ] 9. Option for zero-leading numbers.
+[x] 10. Update man page
+[ ] 11. Safe error if mailfile doesn't exist
+[x] 12. Speed up the parser
+[ ] 13. Track mail changes
+[ ] 14. Send mail
+[ ] 15. Read RFC822
Added: trunk/filesystems/mailfs/maillink.h
==============================================================================
--- trunk/filesystems/mailfs/maillink.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/mailfs/maillink.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,22 @@
+// -*- C++ -*-
+
+#ifndef _MAILLINK_H_
+#define _MAILLINK_H_
+
+#include <SimpleInode.h>
+#include <String.h>
+#include <time.h>
+
+#pragma interface
+
+class maillink:public SimpleInode
+{
+ String str;
+
+ public:
+ maillink(Filesystem &fs, Handle h, String str);
+ do_readlink(const up_preamble &, upp_repl &,
+ const upp_readlink_s &, upp_readlink_r &);
+};
+
+#endif /* _MAILLINK_H_ */
Added: trunk/filesystems/mailfs/mailfile.cc
==============================================================================
--- trunk/filesystems/mailfs/mailfile.cc 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/mailfs/mailfile.cc 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,47 @@
+// -*- C++ -*-
+
+#pragma implementation
+
+#include "mailfile.h"
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fstream.h>
+
+mailfile::mailfile(Filesystem &fs, Handle h,
+ ifstream *ifile, streampos start, int l, time_t t)
+ : SimpleInode(fs, h), start(start), ifile(ifile)
+{
+ uid = getuid();
+ gid = getgid();
+ mode = S_IFREG | 0444;
+ size = l;
+ atime = ctime = mtime = t;
+}
+
+int
+mailfile::do_read(const up_preamble &pre, upp_repl &repl,
+ const upp_read_s &arg, upp_read_r &ret)
+{
+ int sz, off; // legth of returned bunch
+ // Bunch is requested by kernel. Kernel asks for bunch of
+ // arg.size bytes starting from arg.off
+
+ // i = arg.file;
+ off = arg.off;
+ sz = arg.size;
+ // l = arg.ctok;
+
+ if(off >= size)
+ {
+ ret.data.nelem = 0; // send EOF
+ }
+ else
+ {
+ if(off + sz > size)
+ sz = size - off;
+ ret.data.alloc(ret.data.nelem = sz);
+ ifile->seekg(start + off);
+ ifile->read(ret.data.elems, sz);
+ }
+ return 0;
+}
Added: trunk/filesystems/mailfs/mail.cc
==============================================================================
--- trunk/filesystems/mailfs/mail.cc 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/mailfs/mail.cc 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,455 @@
+// -*- C++ -*-
+
+#pragma implementation
+
+#include "mail.h"
+
+header::header(ifstream *f, String name, streampos begin, int l = 0)
+{
+ file = f;
+ n = name;
+ start = begin;
+ len = l;
+// printf("HEADER STARTED AT %d\n", start);
+}
+
+String
+header::full()
+{
+ if(!file)
+ puts("FILE NULL POINTER!!!");
+ char x[len + 1];
+ file->seekg(start);
+ file->read(x, len);
+ x[len] = 0;
+ return x;
+};
+
+// tests in fact is the ifstream OK
+void
+header::test()
+{
+ char staf[200];
+ streampos p = file->tellg();
+ file->seekg(0);
+ file->getline(staf, 35);
+ puts("HEADER TEST");
+ puts(staf);
+ file->seekg(p);
+}
+
+message::message(ifstream *f, streampos begin, int l = 0)
+{
+ file = f;
+ start = begin;
+ len = l;
+}
+
+static Regex
+ from_left_rx(":.*<"),
+ alpha_rx("[A-Za-z]"),
+ rubout_leftsc_rx("^: *"),
+ rubout_rightless_rx(" *<$"),
+ inparen_rx("(.*)"),
+ whitespc_rx("[ \n\t]"),
+ easyshell_rx("[ /!&@'\"]"),
+ rubout_leftpar_rx("^.*("),
+ rubout_rightpar_rx(").*$");
+
+void
+message::setname(String m)
+{
+ from_name = m.at(from_left_rx);
+ if(from_name.index(alpha_rx) >= 0)
+ {
+ from_name.del(rubout_leftsc_rx);
+ from_name.del(rubout_rightless_rx);
+ m = from_name;
+ int j = 0;
+ int i = m.length();
+ if(m.at(j, 1) == "\"")
+ j++;
+ if(m.at(i-1, 1) == "\"")
+ i--;
+ from_name = m.at(j, i - j); // extract name out of "From " header
+ }
+ else
+ {
+ from_name = m.at(inparen_rx);
+ if(from_name.index(alpha_rx) >= 0)
+ {
+ from_name.del(rubout_leftpar_rx);
+ from_name.del(rubout_rightpar_rx);
+ }
+ else
+ {
+ int j = m.index(" ") + 1;
+ int i = m.index(whitespc_rx, j);
+ if(i < 0)
+ i = m.length();
+ if(i > j)
+ {
+// from_name = m.at(Regex("<.*>"), j);
+ for(; m.at(j, 1) == "<" || m.at(j, 1) == "\""; )
+ j++;
+ for(; m.at(i-1, 1) == ">" || m.at(i-1, 1) == "\""; )
+ i--;
+ from_name = m.at(j, i - j); // extract name out of "From " header
+ }
+ }
+ }
+ from_name.gsub(easyshell_rx, "_"); // it's easier for shells
+}
+
+static Regex num_rx("[0-9]"), capit_rx("[A-Z]");
+
+void
+message::setdate(String date)
+{
+ struct tm tms;
+ char month[8];
+
+ char *months[] =
+ {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+ };
+
+// puts((char *)date);
+ String dt = date.from(num_rx);
+ tms.tm_mday = atoi((char *)dt);
+ dt = dt.from(capit_rx);
+ int i;
+ for(i = 11; i >= 0; i--)
+ if(dt.index(months[i]) >= 0)
+ break;
+ tms.tm_mon = i;
+ dt = dt.from(num_rx);
+ tms.tm_year = atoi((char *)dt);
+ if(tms.tm_year >= 1900)
+ tms.tm_year -= 1900;
+ dt = dt.after(" ");
+ tms.tm_hour = atoi((char *)dt);
+ dt = dt.after(":");
+ tms.tm_min = atoi((char *)dt);
+ dt = dt.after(":");
+ tms.tm_sec = atoi((char *)dt);
+ dt = dt.after(" ");
+ tms.tm_isdst = -1;
+ int plus = atoi((char *)dt);
+ long int pz = (plus % 100) * 60 + (plus / 100) * 3600;
+ d = mktime(&tms);
+ d += - pz - timezone;
+ if(daylight)
+ d += 3600;
+}
+
+/*
+message::message(String msg = "")
+{
+ int i, j, k, p, r;
+ Pix a;
+
+ m = msg;
+
+ j = m.index(" ") + 1;
+ i = m.index(Regex("[ \n\t]"), j);
+ if(i > j)
+ {
+// from_name = m.at(Regex("<.*>"), j);
+ if(m.at(j, 1) == "<")
+ j++;
+ if(m.at(i-1, 1) == ">")
+ i--;
+ from_name = m.at(j, i - j); // extract name out of "From " header
+ from_name.gsub(Regex("[ /!&@']"), "_"); // it's easier for shells
+ }
+ for(k = 0, p = i = m.index("\n") + 1; i < m.length(); i = j + 1, k++ )
+ {
+ j = m.index("\n", i);
+ if(j < 0)
+ j = m.length(); // if newline is not found, skip to END of message
+
+ if(m.at(i, 1) != "\t" && m.at(i, 1) != 32)
+ { // test if line doesn't begin with TAB/SPC
+ if(i > p) // p is the start of previous header line
+ {
+ // Take care - we are adding PREVIOUS line here
+ // once we get sure current line doesn't begin with TAB
+ header h = m.at(p, i - p);
+ for(r = 0, a = hdrs.first(); a != NULL; hdrs.next(a))
+ {
+ if(hdrs(a).name() == h.name())
+ {
+ r++;
+ hdrs(a).append(h.full());
+ break;
+ }
+ }
+ if(!r)
+ hdrs.append(h);
+ }
+ p = i;
+ }
+ if(j - i < 1)
+ break; // this is empty lin
+ }
+ b = i;
+}
+*/
+
+String
+message::full()
+{
+ if(!file)
+ return "FILE: NULL POINTER!!!";
+ char x[len + 1];
+ file->seekg(start);
+ file->read(x, len);
+ x[len] = 0;
+ return x;
+};
+
+String
+message::body()
+{
+ if(!file)
+ return "FILE: NULL POINTER!!!";
+ int l = len - b;
+ char x[l + 1];
+ file->seekg(start + b);
+ file->read(x, l);
+ x[l] = 0;
+ return x;
+};
+
+
+void
+message::disp()
+{
+ int i;
+ Pix a;
+ String b;
+
+ cout << "----- headers:\n";
+ for(i = 0, a = hdrs.first(); a != NULL; hdrs.next(a), i++)
+ {
+// hdrs(a).test();
+ cout << i << " " << hdrs(a).full();
+ }
+ b = body();
+ cout << "----- body (len = " << b.length() << "):\n" << body() << "-----\n";
+}
+
+void
+message::test()
+{
+ char staf[200];
+ streampos p = file->tellg();
+ file->seekg(0);
+ file->getline(staf, 35);
+ puts("MESSAGE TEST");
+ if(file->eof())
+ puts("FILE EOF");
+ puts(staf);
+ file->seekg(p);
+}
+
+mail::mail(ifstream *f)
+{
+ file = f;
+ char line[MAX_LINE_LEN + 1];
+ String msg, temp;
+ int i = 0, ic, cont_len = -1, line_num = -1, lines = 0;
+ streampos st, sp = -1, sn, bm = -1, em, hs = -1;
+ int state = FSM_NOTHING;
+ message *m = NULL;
+ header *h = NULL;
+ String hname = "", tname;
+
+ if(!file)
+ return;
+ for(st = sn = 0; !file->eof(); )
+ {
+ sp = sn;
+ file->getline(line, MAX_LINE_LEN);
+ temp = line;
+// sn = file->tellg();
+// I gave off on tellg() because it's SLOW and people hate it.
+// here's a faster hack, but expect BIG trobles if line is
+// longer than MAX_LINE_LEN!!!
+ sn += temp.length() + 1;
+ switch(state)
+ {
+ case FSM_NOTHING:
+ if(!memcmp(line, "From ", 5))
+ {
+ if(bm >= 0) // soome message has to exist before we append.
+ {
+ m->setlen(sp - bm);
+ messages.append(*m);
+ }
+ state = FSM_HEADERS;
+ i++; // increment message number
+ bm = sp; // begin of the message
+ hs = cont_len = line_num = -1; // clear header start and Contents-Length
+ m = new message(file, bm);
+ m->setname(temp);
+ hname = "";
+ }
+ break;
+ case FSM_HEADERS:
+ {
+// take care, for the last header to be appended,
+// a final header addition shall be done when
+// the empty line is seen.
+ char c = *line;
+ if(c != '\t' && c != ' ')
+ { // test if line doesn't begin with TAB/SPC
+ ic = 0;
+ int it = temp.index(Regex("[: ]"));
+ tname = temp.before(it); // establish possible header's name
+ if(!memcmp(line, "Content-Length:", 15))
+ {
+ cont_len = atoi(line + it + 1);
+ }
+ else
+ if(!memcmp(line, "Lines:", 6))
+ {
+ line_num = atoi(line + it + 1);
+ }
+ else
+ if(!memcmp(line, "From:", 5))
+ {
+ m->setname(temp);
+ }
+ else
+ if(!memcmp(line, "Date:", 5))
+ {
+ m->setdate(temp);
+ }
+ if(hs < 0) // header hasn't begun
+ {
+ hs = sp; // start the header
+ if(tname.length() > 0)
+ {
+ ic++; // signal - create new header
+ hname = tname;
+ }
+ }
+ else
+ {
+// potential BUG location: if we have multiple headers with same name,
+// but not coming in succession, one after another, we are having a problem.
+// we cannot represent header contents file with single offset/length
+// because header's contents is split in parts.
+ if(tname != hname) // just test if the previous isn't the same
+ {
+ h->setlen(sp - hs); // header length
+ m->headers()->append(*h); // append this header, since
+ // since it probably has a different name
+ hs = sp;
+ if(tname.length() > 0)
+ {
+ ic++; // signal - create new header
+ hname = tname;
+ }
+ }
+ }
+ if(ic)
+ { // create new header
+ h = new header(file, hname, hs);
+ }
+ }
+ if( temp.length() < 2)
+ {
+ m->setbody(sn - bm);
+ if(cont_len >= 0)
+ {
+ sp += cont_len;
+ sn += cont_len;
+ file->seekg(sn);
+ m->setlen(sn - bm);
+ messages.append(*m);
+ state = FSM_NOTHING;
+ bm = -1; // begin of the message
+ hs = cont_len = line_num = -1; // clear header start and Contents-Length
+ i++; // increment message number
+ }
+ else
+ {
+ state = FSM_BODY; // empty line - start body reading
+ lines = 0;
+ }
+ break;
+ }
+ break;
+ }
+ case FSM_BODY:
+ int nxtmsg = 0;
+ if(!memcmp(line, "From ", 5))
+ {
+ if(bm >= 0) // at least one message has to exist before we append.
+ {
+ m->setlen(sp - bm);
+ messages.append(*m);
+ }
+ state = FSM_HEADERS;
+ bm = sp; // begin of the message
+ nxtmsg++;
+ }
+ else
+ {
+ if(line_num >= 0 && ++lines > line_num)
+ {
+ if(bm >= 0) // append.
+ {
+ m->setlen(sp - bm);
+ messages.append(*m);
+ }
+ state = FSM_NOTHING;
+ bm = -1; // begin of the message
+ nxtmsg++;
+ }
+ }
+ if(nxtmsg)
+ {
+ hs = cont_len = line_num = -1; // clear header start and Contents-Length
+ i++; // increment message number
+ m = new message(file, bm);
+ m->setname(temp);
+ hname = "";
+ break;
+ }
+ break;
+ }
+ conta1:;
+ }
+ file->clear(); // wipe out eof thing
+ if(bm >= 0 && bm < sp)
+ {
+ m->setlen(sp - bm);
+ messages.append(*m); // it has to be one message more!
+ }
+}
+
+void
+mail::disp()
+{
+ int i;
+ Pix a;
+
+ cout << "----- MAIL messages:\n";
+ for(i = 0, a = messages.first(); a != NULL; messages.next(a), i++)
+ messages(a).disp();
+}
+
+/*
+int main()
+{
+ ifstream f("davor");
+ mail a(&f);
+ a.disp();
+ return 0;
+}
+*/
Added: trunk/filesystems/mailfs/maildir.h
==============================================================================
--- trunk/filesystems/mailfs/maildir.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/mailfs/maildir.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,34 @@
+// -*- C++ -*-
+
+// Example directory
+
+#ifndef _MAILDIR_H_
+#define _MAILDIR_H_
+
+#pragma interface
+
+#include <DirInode.h>
+#include <time.h>
+#include <fstream.h>
+
+class mailfs;
+
+class maildir : public DirInode
+{
+ streampos start;
+ ifstream *ifile;
+ int length;
+public:
+ maildir(mailfs &, Handle, Inode *, ifstream *, streampos, int, time_t);
+ maildir(mailfs &, Handle, Inode *, time_t);
+ int do_read(const up_preamble &, upp_repl &,
+ const upp_read_s &arg, upp_read_r &ret);
+};
+
+class mailtopdir : public maildir
+{
+public:
+ mailtopdir(mailfs &, Handle, Inode *);
+};
+
+#endif /* _MAILDIR_H_ */
Added: trunk/filesystems/mailfs/mail.h
==============================================================================
--- trunk/filesystems/mailfs/mail.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/mailfs/mail.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,80 @@
+// -*- C++ -*-
+
+#ifndef _MAIL_H_
+#define _MAIL_H_
+
+#pragma interface
+
+// Header line management
+
+#include <stdio.h>
+#include <unistd.h>
+#include <String.h>
+#include <DLList.h>
+#include <sys/file.h>
+#include <stdlib.h>
+#include <fstream.h>
+#include <time.h>
+
+#define MAX_LINE_LEN 256
+#define MAX_MSG_LEN 32767
+
+enum { ACT_DATE, ACT_FROM, ACT_CONTENTS_LENGTH, ACT_LINES, ACT_N };
+enum { FSM_NOTHING, FSM_HEADERS, FSM_BODY };
+
+class header
+{
+ String n;
+ ifstream *file;
+ streampos start;
+ int len;
+public:
+ header(ifstream *, String, streampos, int);
+ header() { file = NULL; start = len = 0; };
+ String name() { return n; };
+ void setlen(int l) { len = l; };
+ void test();
+ String full();
+ void report(ifstream* &rf, streampos &rs, int &rl)
+ { rf = file; rs = start; rl = len; };
+};
+
+class message
+{
+ DLList<header> hdrs;
+ String from_name;
+ streampos start;
+ ifstream *file;
+ time_t d;
+ int len;
+ int b;
+public:
+ message() { file = NULL; start = len = 0; };
+ message(ifstream *, streampos, int);
+ void disp();
+ String name() { return from_name; };
+ String body();
+ String full();
+ DLList<header> *headers() { return &hdrs; };
+ void clear(streampos p) { hdrs.clear(); start = p; };
+ void test();
+ void setlen(int l) { len = l; };
+ void setbody(int bb) { b = bb; };
+ void setname(String);
+ void report(ifstream* &rf, streampos &rs, int &rl, int &rb, time_t &rt)
+ { rf = file; rs = start; rl = len; rb = b; rt = d; };
+ void setdate(String);
+};
+
+class mail
+{
+ DLList<message> messages;
+ ifstream *file;
+public:
+ mail(ifstream *);
+ ~mail() { };
+ void disp();
+ DLList<message> contents() { return messages; };
+};
+
+#endif /* _MAIL_H_ */
Added: trunk/filesystems/mailfs/mailfile.h
==============================================================================
--- trunk/filesystems/mailfs/mailfile.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/mailfs/mailfile.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,24 @@
+// -*- C++ -*-
+
+#ifndef _MAILFILE_H_
+#define _MAILFILE_H_
+
+#include <SimpleInode.h>
+#include <String.h>
+#include <fstream.h>
+#include <time.h>
+
+#pragma interface
+
+class mailfile:public SimpleInode
+{
+ streampos start;
+ ifstream *ifile;
+
+ public:
+ mailfile(Filesystem &, Handle, ifstream *, streampos, int, time_t);
+ do_read(const up_preamble &, upp_repl &,
+ const upp_read_s &arg, upp_read_r &ret);
+};
+
+#endif /* _MAILFILE_H_ */
Added: trunk/filesystems/mailfs/mailfs.1
==============================================================================
--- trunk/filesystems/mailfs/mailfs.1 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/mailfs/mailfs.1 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,165 @@
+.\" Copyright 1994 Davor Jadrijevic <davor%emard.uucp at ds5000.irb.hr>
+.\" May be distributed under the GNU General Public License
+.\" See section COPYING for conditions for redistribution
+.TH mailfs 1 "15 May 1994" Mailfs "Linux Manual"
+.SH NAME
+mailfs \- userfs client to display contents of a mail file
+in form of a directory
+.SH SYNOPSIS
+.RI muserfs
+.B mailfs
+.I "mount\-point"
+.RI \-\-
+.I "[options...]"
+.SH DESCRIPTION
+.B mailfs
+is a userfs client which allows to mount messages from mail file
+arranged in form of directory.
+.PP
+.B mailfs
+will operate in the directory to where it is mounted. There it will
+create one directory for every mail message. Name of the directory
+consists from number of the message (lower numbers - recently arrived
+messages), and the username in a)
+.B From:
+header, between
+.B :
+and
+.B <
+b)
+.B From:
+header, between
+.B (
+and
+.B )
+c)
+.B From:
+header between two spaces
+d)
+.B From
+header between two spaces. That can
+looks like
+.B 001.user_name
+( problematic characters like
+.B !, @
+etc. will be replaced with
+.B _
+). In this directory, there will be files. For each header, a file
+will be created, named same as the header, and containing full
+header text (with name too). Message text is in file
+.B body.txt
+and full mail message (together with headers) is in file
+.B .complete.txt
+.PP
+Time stamp of files will be calculated from
+.B Date:
+header, and should represent
+the time when message was sent in terms of local time. This is done
+by converting
+.B Date:
+to GMT, and then adding local timezone and 1 hour in case of daylight
+saving.
+.SH OPTIONS
+.TP
+.I "\-o n"
+Where
+.I n
+is the file descriptor number the process should write to the kernel on.
+.TP
+.I "\-i n"
+Where
+.I n
+is the file descriptor to read kernel requests from.
+.TP
+.I "\-m mpoint"
+Where
+.I mpoint
+is the path of the mountpoint.
+.TP
+.I "\-f mail-file"
+Where
+.I mail-file
+is the file in which mail messages reside. If you omit this option, then
+.B MAIL
+environment variable content will be used. This variable shall contain
+something like /usr/spool/mail/username
+.P
+User is not required to invoke any of the options for ordinary operation.
+.SH EXAMPLES
+
+ $ muserfs bin/mailfs mnt &
+ [1] 352
+ $ cd mnt
+ $ ls
+ 001.sbg_socs.uts.edu.au
+ 002.Leroy
+ 003.tlukka_vinkku.hut.fi
+ $ cat */From
+ From: sbg at socs.uts.edu.au
+ From: leroy at socs.uts.edu.au (Leroy)
+ From: tlukka at vinkku.hut.fi
+ $ cat */Subject
+ More things
+ (none)
+ That userfs thing
+.SH METHOD
+.B mailfs
+divides the mail file into linked list of messages,
+every message is then divided into linked list of headers and body.
+A tree-like structure formed that way is used to fill userfs with
+representation of the mail in directory.
+.PP
+Division is made on follwing conditions: In mail file, each message
+begins with a line having
+.B From
+at its beginning, following with space. In message, each header
+follows with a line which in turn begins with any character except
+whitespace
+.B TAB
+or
+.B SPACE.
+Whitespace
+at the beginning is used as continuation character for the previous
+header. Header's name is string from beginning of the line to the
+semicolon (
+.B \:
+) character. Headers are divided from message body with empty line.
+In case
+.B Contents-Length:
+is defined, the message body is assumed to be of that length, regardless
+of the contents there.
+Otherwise, message body is the rest of the message until
+.B From
+appears.
+or until
+.B Lines:
+number of lines is read (if this header exists).
+.SH BUGS
+There might be problems if message contains headers of the same
+name at random places, i.e. same header names, but not appearing
+strictly one after another.
+.PP
+Also, problems if any line in the mail file exceeds
+.B MAX_LINE_LEN
+having default value
+.B 256
+defined in
+.B mail.h
+.PP
+On
+.B longer
+mail files, userfs will take some
+.B time
+to parse the file.
+If you enter mounted userfs directory before mailfs is ready, file
+operations there will produce
+.B No such file or directory
+errors after mailfs gets up.
+Exiting and reentering userfs directory will solve the problem.
+.SH AUTHOR
+Davor Jadrijevic <davor%emard.uucp at ds5000.irb.hr>
+.SH SEE ALSO
+.BR muserfs (2),
+.BR mount (8),
+.BR umount (8),
+.BR mail (1)
Added: trunk/filesystems/mailfs/README
==============================================================================
--- trunk/filesystems/mailfs/README 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/mailfs/README 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,71 @@
+
+ * * * ** ** ******** ********
+ ** ** *** ** ** ******** *********
+ *** *** ***** ** ** ****
+ **** **** ******* ** ** ******** ******
+ ***** ***** ********* ** ** ******** ****
+ *********** *********** ** ******** ** *********
+ *********** *********** ** ******** ** ********
+
+ ,
+ BY DAVOR JADRIJEVIC
+
+
+ MAILFS is a client for userfs file system. MAILFS will read
+the mail file and arrange it in form of a directory. Each message
+is represented by its number, and name of the person From whom
+the message arrived. Directory itself behaves as a file; it can
+be read, giving message with headers. It can be entered, as a normal
+directory, inside of which are files representing headers (each
+header in separated file) and message body.
+
+ Message dates are converted to local time, so the time-stamp of
+files representing mail is set appropriately. This can be used
+for comparing the time (in local units) when messages are written;
+useful for time-basis sorting etc.
+
+Please refer to man page mailfs.1 with e.g.
+$ groff -man mailfs.1 | more
+for more details.
+
+--- STATUS OF MAILFS ---
+ (alpha testing)
+
+Things to be done:
+
+1. Dynamics.
+
+Dynamically read the mail as it arrives in the mailbox.
+Possible solutions are under consideration.
+For now, MAILFS is static - mail file can be mounted, but
+once it's mounted it's not supposed to change (anomalies
+are expected if it does).
+
+2. Speeded-up parser.
+
+It has been reported that long mail files take very long
+time to be parsed.
+
+3. Proper rfc822 implementation
+
+It has been implemented a subset of rfc822 recommendation
+in a rather simple way, in order to get a useful mailfs
+behaviour with rather quick and simple solutions.
+
+4. Sending mail
+
+If I get a good idea, maybe I can implemend replying and
+sending mail messages, so mailfs will serve as fully qualified
+mailer, which can be mounted all the time.
+
+--- * * * ---
+
+I wish to thank Jeremy Fitzhardinge for making userfs,
+his idea and collaborating on mailfs.
+
+Mailfs can be handled under the terms of GNU public licence.
+
+Enjoy it.
+-- ,
+Davor Jadrijevic <davj at ds5000.irb.hr>
+Lastovska 5, 41000 Zagreb, Croatia.
Added: trunk/filesystems/mailfs/Makefile
==============================================================================
--- trunk/filesystems/mailfs/Makefile 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/mailfs/Makefile 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,23 @@
+TOP=../..
+include $(TOP)/rules
+FLAGS=-I$(TOP)/kernel -I$(TOP)/lib -I$(TOP)/genser -I/usr/include/g++
+CFLAGS=$(FLAGS)
+CXXFLAGS=$(FLAGS)
+DEBUG=-O -g -DDEBUG
+
+LDFLAGS =
+PROGS=mailfs
+
+OBJ=mailfs.o maildir.o mailfile.o maillink.o mail.o
+
+all:: $(PROGS)
+
+mailfs: $(OBJ) $(DEPLIBUSERFS)
+ $(CXX) $(LDFLAGS) -o $@ $(OBJ) $(LIBUSERFS)
+
+clean:: dummy
+ rm -f *.o *~ $(PROGS)
+
+dep depend::
+ $(CXX) $(CXXFLAGS) -M *.cc > .depend
+
Added: trunk/filesystems/example/egfile.cc
==============================================================================
--- trunk/filesystems/example/egfile.cc 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/example/egfile.cc 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,96 @@
+// -*- C++ -*-
+//
+// Files in egfs
+//
+// This program is distributed under the terms of the
+// Free Software Foundation General Public Licence.
+// See COPYING for details
+// Copyright Jeremy Fitzhardinge <jeremy at sw.oz.au> 1994,1995
+
+#pragma implementation
+
+#include "egfile.h"
+
+#include <unistd.h>
+#include <sys/stat.h>
+
+// Create a file with some initial content
+egfile::egfile(Filesystem &fs, Handle h, char *b, int sz)
+ : SimpleInode(fs, h)
+{
+ // Use our invoker's ID rather than the person doing the syscall.
+ uid = getuid();
+ gid = getgid();
+ mode = S_IFREG | 0644;
+ if (sz == -1)
+ sz = strlen(b);
+ buf = new char [sz];
+ size = sz;
+ memcpy(buf, b, sz);
+}
+
+// Set the length of the file. Very naive: it just frees the old buffer
+// and allocates the new one, without trying to optimise at all.
+void
+egfile::truncate(off_t off)
+{
+ char *nb = new char[off];
+
+ memset(nb, 0, off);
+ memcpy(nb, buf, off > size ? size : off);
+ delete buf;
+ buf = nb;
+ size = off;
+}
+
+// Not much to reading
+int
+egfile::do_read(const up_preamble &, upp_repl &,
+ const upp_read_s &arg, upp_read_r &ret)
+{
+ size_t sz = size - arg.off;
+
+ // Reads beyond EOF always get 0 bytes
+ if (sz <= 0)
+ {
+ ret.data.nelem = 0;
+ return 0;
+ }
+
+ // Read either the amount wanted or to the end of the file.
+ sz = sz > arg.size ? arg.size : sz;
+
+ // Just point the return to the data
+ ret.data.nelem = sz;
+ ret.data.elems = (Uchar *)&buf[arg.off];
+ return 0;
+}
+
+// Writing files could be much more efficient. As it is, each write
+// which grows the file will cause truncate() to alloc, copy and free
+// the buffer with the file contents.
+int
+egfile::do_write(const up_preamble &, upp_repl &,
+ const upp_write_s &arg, upp_write_r &ret)
+{
+ // Writing off the end of the file means we grow it
+ if (arg.off + arg.data.nelem > size)
+ truncate(arg.off + arg.data.nelem);
+
+ // Copy the data into place
+ memcpy(buf+arg.off, arg.data.elems, arg.data.nelem);
+
+ // We can never do partial writes
+ ret.wrote = arg.data.nelem;
+ return 0;
+}
+
+// Set the size of the file (truncate is historical; it can also grow
+// files)
+int
+egfile::do_truncate(const up_preamble &, upp_repl &,
+ const upp_truncate_s &arg)
+{
+ truncate(arg.size);
+ return 0;
+}
Added: trunk/filesystems/example/egdir.h
==============================================================================
--- trunk/filesystems/example/egdir.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/example/egdir.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,32 @@
+// -*- C++ -*-
+
+// Example directory
+
+#ifndef _EGDIR_H_
+#define _EGDIR_H_
+
+#pragma interface
+
+#include <string>
+#include <DirInode.h>
+
+class egfs;
+
+class egdir : public DirInode
+{
+ egfs &filesys;
+
+public:
+ egdir(egfs &, Handle, Inode *);
+
+ int do_create(const up_preamble &, upp_repl &,
+ const upp_create_s &arg, upp_create_r &ret);
+};
+
+class egtopdir : public egdir
+{
+public:
+ egtopdir(egfs &, Handle, Inode *);
+};
+
+#endif /* _EGDIR_H_ */
Added: trunk/filesystems/example/egfile.h
==============================================================================
--- trunk/filesystems/example/egfile.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/example/egfile.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,26 @@
+// -*- C++ -*-
+
+#ifndef _EGFILE_H_
+#define _EGFILE_H_
+
+#include <SimpleInode.h>
+#include <string.h>
+
+#pragma interface
+
+class egfile:public SimpleInode
+{
+ char *buf;
+
+ public:
+ egfile(Filesystem &fs, Handle h, char *b, int sz = -1);
+ int do_read(const up_preamble &, upp_repl &,
+ const upp_read_s &arg, upp_read_r &ret);
+ int do_write(const up_preamble &, upp_repl &,
+ const upp_write_s &arg, upp_write_r &ret);
+ int do_truncate(const up_preamble &, upp_repl &,
+ const upp_truncate_s &arg);
+ void truncate(off_t off);
+};
+
+#endif /* _EGFILE_H_ */
Added: trunk/filesystems/example/egfs.cc
==============================================================================
--- trunk/filesystems/example/egfs.cc 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/example/egfs.cc 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,125 @@
+// -*- C++ -*-
+//
+// Example filesystem
+//
+// This program is distributed under the terms of the
+// Free Software Foundation General Public Licence.
+// See COPYING for details
+// Copyright Jeremy Fitzhardinge <jeremy at sw.oz.au> 1994,1995
+
+#pragma implementation
+
+// Misc headers
+#include <getopt.h>
+#include <stdio.h>
+
+// Filesystem related headers
+#include <Comm.h>
+
+#include "egfs.h"
+#include "egdir.h"
+
+// A simple constructor for the filesystem
+// All this does is pass the arguments to the base class
+// and initialize the inode handle counter.
+// The counter is for generating unique handles as required.
+// The mechanism used is very simple, because there is a bounded
+// number of inodes.
+egfs::egfs(const char *mpoint)
+ : Filesystem(mpoint)
+{
+ hcount=2;
+}
+
+egfs::~egfs()
+{
+}
+
+// Declare to the kernel which operations we will support. Lots of
+// this is entirely done by the base classes in libuserfs (for example,
+// up_link is done by DirInode; we don't have to do anything explicitly).
+int
+egfs::Enquire(up_ops op)
+{
+ switch(op)
+ {
+ case userfs_up_mount:
+ case userfs_up_iread:
+ case userfs_up_notify_change:
+ case userfs_up_readdir:
+ case userfs_up_multireaddir:
+ case userfs_up_lookup:
+ case userfs_up_create:
+ case userfs_up_unlink:
+ case userfs_up_link:
+ case userfs_up_rename:
+ case userfs_up_truncate:
+ case userfs_up_read:
+ case userfs_up_write:
+ return 0;
+ default:
+ break;
+ }
+ return Filesystem::Enquire(op);
+}
+
+// Do the mount. This simply returns the handle of the root
+// directory and creates the directory.
+int
+egfs::do_mount(const up_preamble &, upp_repl &,
+ upp_mount_r &ret)
+{
+ Inode *root = new egtopdir(*this, genhand(), NULL);
+ ret.root.handle = root->gethandle();
+ return 0;
+}
+
+// Parse the arguments from muserfs and construct the filesystem
+// and communications.
+int
+main(int argc, char **argv)
+{
+ int optch, err = 0;
+ int infd, outfd;
+ const char *mpoint = "";
+
+ extern char *optarg;
+ extern int optind, opterr, optopt;
+
+
+ infd = outfd = -1;
+ while((optch = getopt(argc, argv, "i:o:m:")) != EOF)
+ switch(optch)
+ {
+ case 'i':
+ infd = atoi(optarg);
+ break;
+ case 'o':
+ outfd = atoi(optarg);
+ break;
+ case 'm':
+ mpoint = optarg;
+ break;
+ default:
+ err++;
+ }
+
+ if (err)
+ {
+ fprintf(stderr, "Usage: %s -i infd -o outfd -m mpoint\n",
+ argv[0]);
+ exit(1);
+ }
+
+#if 0 && DEBUG
+ printf("pid=%d, return to cont\n", getpid());
+ getchar();
+#endif
+ egfs efs(mpoint);
+ Comm comm(efs, outfd, infd);
+
+ if (comm.Run() == -1)
+ fprintf(stderr, "%s: Comm.Run() failed!\n", argv[0]);
+
+ return 0;
+}
Added: trunk/filesystems/example/egfs.h
==============================================================================
--- trunk/filesystems/example/egfs.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/example/egfs.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,27 @@
+// -*- C++ -*-
+
+// Example filesystem
+
+#ifndef _EGFS_H_
+#define _EGFS_H_
+
+#include <Filesystem.h>
+
+#pragma interface
+
+class egfs:public Filesystem
+{
+ Handle hcount;
+
+ int Enquire(up_ops);
+
+ int do_mount(const up_preamble &, upp_repl &, upp_mount_r &);
+
+public:
+ egfs(const char *);
+ ~egfs();
+
+ Handle genhand() { return hcount++; }
+};
+
+#endif /* _EGFS_H_ */
Added: trunk/filesystems/example/Makefile
==============================================================================
--- trunk/filesystems/example/Makefile 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/example/Makefile 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,23 @@
+TOP=../..
+FLAGS=-I$(TOP)/kernel -I$(TOP)/lib -I$(TOP)/genser -I/usr/include/g++ \
+ -DDEBUG -Wall
+CXXFLAGS = $(FLAGS)
+
+include $(TOP)/rules
+
+LDFLAGS = -g $(PROF)
+
+PROGS=egfs
+
+OBJ=egfs.o egdir.o egfile.o $(TOP)/lib/libuserfs.a -lg++
+
+all:: $(PROGS)
+
+egfs: $(OBJ) $(DEPLIBUSERFS)
+ $(CXX) $(LDFLAGS) -o $@ $(OBJ) $(LIBUSERFS)
+
+clean:: dummy
+ rm -f *.o *~ core $(PROGS)
+
+dep depend::
+ $(CXX) $(CXXFLAGS) -M *.cc > .depend
Added: trunk/filesystems/example/egdir.cc
==============================================================================
--- trunk/filesystems/example/egdir.cc 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/example/egdir.cc 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,84 @@
+// -*- C++ -*-
+
+// Directories in egfs
+//
+// This program is distributed under the terms of the
+// Free Software Foundation General Public Licence.
+// See COPYING for details
+// Copyright Jeremy Fitzhardinge <jeremy at sw.oz.au> 1994,1995
+
+#pragma implementation
+
+#include "egdir.h"
+#include "egfile.h"
+#include "egfs.h"
+
+#include <sys/stat.h>
+#include <unistd.h>
+
+// Directories are *easy*
+egdir::egdir(egfs &fs, Handle h, Inode *p)
+ : DirInode(fs, h, p), filesys(fs)
+{
+ uid = getuid();
+ gid = getgid();
+ mode = S_IFDIR | 0755;
+}
+
+// This constructs the entire directory hierachy for this
+// filesystem (i.e. prime it with silly files)
+egtopdir::egtopdir(egfs &fs, Handle h, Inode *p)
+ : egdir(fs, h, p)
+{
+ link("test1", new egfile(fs, fs.genhand(), "Hello, world!\n"));
+ link("test2", new egfile(fs, fs.genhand(), "Wooba wooba...\n"));
+
+ DirInode *d1 = new egdir(fs, fs.genhand(), this);
+ DirInode *d2 = new egdir(fs, fs.genhand(), this);
+
+ link("dir1", d1);
+ link("dir2", d2);
+
+ Inode *f1 = new egfile(fs, fs.genhand(), "File with multiple names\n");
+ d1->link("linked-file", f1);
+ d2->link("another-link", f1);
+
+ Inode *f2 = new egfile(fs, fs.genhand(), "Piffle woodle.\n");
+ d2->link("strange", f2);
+}
+
+// Handle file creation. We only support files and directories (no links,
+// devices, etc)
+int
+egdir::do_create(const up_preamble &, upp_repl &,
+ const upp_create_s &arg, upp_create_r &ret)
+{
+ Inode *ino;
+ Handle h = filesys.genhand();
+ char* buf;
+ int n;
+
+ if (S_ISREG(arg.mode))
+ {
+ ino = new egfile(filesys, h, NULL, 0);
+ }
+ else if (S_ISDIR(arg.mode))
+ {
+ ino = new egdir(filesys, h, this);
+ }
+ else
+ return EINVAL;
+
+ ret.file.handle = ino->gethandle();
+ // link(String((char *)arg.name.elems, (int)arg.name.nelem), ino);
+
+ n = (int)arg.name.nelem;
+ buf = (char *)malloc(n + 1);
+ strncpy(buf, (char *)arg.name.elems, n);
+ buf[n] = '\0';
+ link(buf, ino);
+ free(buf);
+
+ return 0;
+}
+
Added: trunk/filesystems/README
==============================================================================
--- trunk/filesystems/README 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/README 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,12 @@
+This directory contains contributed work. Briefly, the contents are:
+
+arcfs - mount compressed tar files and browse them as filesystems
+mailfs - a mailreading filesystem
+ulrich-dessauer - a C userfs interface library and various filesystems
+ including a read-only OS/9 filesystem.
+
+I don't guarentee that things under here work or even compile. Use them
+at your own risk. Please report bugs in programs in this directory to
+both me and their original authors.
+
+ Jeremy Fitzhardinge
Added: trunk/filesystems/arcfs/arcfs.c
==============================================================================
--- trunk/filesystems/arcfs/arcfs.c 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/arcfs/arcfs.c 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,561 @@
+/* (Read-only) archive filesystem. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <utime.h>
+#include <dirent.h>
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include <getopt.h>
+#include <assert.h>
+
+#include <time.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/fcntl.h>
+
+#include <linux/fs.h>
+#include <linux/userfs_fs.h>
+
+#include <assert.h>
+
+#include "arcfs.h"
+
+static char *mpoint;
+static ARC_DIRENT *root;
+
+/* No point in this being in a seperate file. */
+#include <linux/userfs_types.c>
+
+static int
+myread (int fd, void *buf, int sz)
+{
+ int rd = 0;
+ int ret;
+
+ while (sz > 0)
+ {
+ ret = read (fd, buf, sz);
+
+ if (ret == -1)
+ {
+ if (errno == EINTR)
+ continue;
+
+ perror ("myread");
+ exit (1);
+ }
+
+ if (ret == 0)
+ break;
+
+ sz -= ret;
+ buf += ret;
+ rd += ret;
+ }
+
+ return rd;
+}
+
+static int
+mywrite (int fd, const void *buf, int sz)
+{
+ int wr = 0;
+ int ret;
+
+ while (sz > 0)
+ {
+ ret = write (fd, buf, sz);
+
+ if (ret == -1)
+ {
+ if (errno == EINTR)
+ continue;
+ FAIL ("write");
+ exit (1);
+ }
+
+ if (ret == 0)
+ {
+ fprintf (stderr, "write wrote 0 bytes\n");
+ break;
+ }
+
+ sz -= ret;
+ buf += ret;
+ wr += ret;
+ }
+
+ return wr;
+}
+
+static int
+readpkt (int fd, up_preamble *pre, unsigned char *buf)
+{
+ int presz = sizeof_up_preamble (pre);
+ unsigned int rd;
+ unsigned char pbuf[presz];
+
+ memset (pbuf, 0, sizeof (pbuf));
+
+ rd = myread (fd, pbuf, presz);
+ if (rd != presz)
+ {
+ if (rd == 0)
+ return 0;
+ if (rd > 0)
+ fprintf (stderr, "readpkt, incomplete read (%d, not %d)\n",
+ rd, presz);
+ perror ("readpkt, header read");
+ return -1;
+ }
+
+ decode_up_preamble (pre, pbuf);
+
+ if (pre->isreq != UP_ENQ && pre->isreq != UP_REQ)
+ fprintf (stderr, "pre->isreq = %d\n", pre->isreq);
+
+ if (pre->version != UP_VERSION)
+ {
+ fprintf (stderr, "Version mismatch: us=%d them=%d\n",
+ UP_VERSION, pre->version);
+ return -1;
+ }
+
+ if (pre->size != 0)
+ {
+ if (myread (fd, buf, pre->size) != pre->size)
+ {
+ perror ("readpkt, body read");
+ return -1;
+ }
+ }
+
+ return 1;
+}
+
+static int
+writepkt (int fd, upp_repl *repl, const unsigned char *buf)
+{
+ int replsz = sizeof_upp_repl (repl);
+ unsigned char pbuf[replsz];
+ unsigned int wr;
+ unsigned char *p;
+
+ assert (repl->version == UP_VERSION);
+ assert (repl->isreq == UP_REPL);
+
+ p = encode_upp_repl (repl, pbuf);
+
+ assert (replsz == p - pbuf);
+
+ wr = mywrite (fd, pbuf, replsz);
+ if (wr != replsz)
+ {
+ perror ("writepkt, header write");
+ return -1;
+ }
+
+ if (repl->size > 0 && repl->err_no == 0)
+ {
+ if ( mywrite(fd, buf, repl->size) != repl->size)
+ {
+ perror ("writepkt, body write");
+ return -1;
+ }
+ }
+
+ return 1;
+}
+
+static void
+genpkt (upp_repl *repl, int seq, up_ops op)
+{
+ repl->version = UP_VERSION;
+ repl->seq = seq;
+ repl->op = op;
+ repl->isreq = 0;
+ repl->size = 0;
+ repl->err_no = 0;
+}
+
+#define DIRINO 1
+
+static int
+do_iread (unsigned char *buf, upp_repl *repl)
+{
+ upp_iread_s rcv;
+ upp_iread_r snd;
+ time_t t;
+
+ decode_upp_iread_s(&rcv, buf);
+
+ memset(&snd, 0, sizeof(snd));
+
+ snd.ino.mode = 0444;
+ snd.handle = rcv.handle;
+ snd.ino.nlink = 1;
+
+ fprintf(stderr, "do_iread: handle=%ld\n", rcv.handle.handle);
+
+ if (rcv.handle.handle == DIRINO)
+ {
+ snd.ino.mode |= S_IFDIR | 0111;
+ t = time (0);
+ }
+ else
+ {
+ ARC_DIRENT *ent = (ARC_DIRENT *) rcv.handle.handle;
+
+ if (ent->size != -1)
+ {
+ snd.ino.mode |= S_IFREG;
+ snd.ino.size = ent->size;
+ /* These numbers seem to be magic for Linux. */
+ snd.ino.blksize = 512;
+ snd.ino.blocks = (ent->data.file.csize + 511) / 512;
+ }
+ else
+ {
+ snd.ino.mode |= S_IFDIR | 0111;
+ snd.ino.size = 0;
+ }
+ t = 0;
+ }
+
+ snd.ino.mtime = snd.ino.ctime = t;
+ snd.ino.atime = time (0);
+
+ repl->size = encode_upp_iread_r(&snd, buf) - buf;
+
+ return 0;
+}
+
+static int
+do_lookup (unsigned char *buf, upp_repl *repl)
+{
+ upp_lookup_s rcv;
+ upp_lookup_r snd;
+ ARC_DIRENT *ent;
+
+ decode_upp_lookup_s(&rcv, buf);
+
+ ent = (ARC_DIRENT *) rcv.dir.handle;
+ if (ent->size != -1)
+ return ENOTDIR;
+
+ if (rcv.name.nelem == 2
+ && rcv.name.elems[0] == '.' && rcv.name.elems[1] == '.')
+ {
+ ent = ent->pdir;
+ }
+ else if (rcv.name.nelem != 1 || rcv.name.elems[0] != '.')
+ {
+ ent = ent->data.dir.first;
+ while (ent)
+ {
+ /* Probably bombs out on prefixes... */
+ if (!strncmp(ent->name, rcv.name.elems, rcv.name.nelem))
+ break;
+ ent = ent->next;
+ }
+ }
+ FREE(rcv.name.elems);
+ if (!ent)
+ return ENOENT;
+
+ fprintf(stderr, "do_lookup: found %s\n", ent->name);
+ snd.handle.handle = (Ulong) ent;
+
+ repl->size = encode_upp_lookup_r (&snd, buf) - buf;
+
+ return 0;
+}
+
+static int
+do_readdir (unsigned char *buf, upp_repl *repl)
+{
+ upp_readdir_s rcv;
+ upp_readdir_r snd;
+ ARC_DIRENT *ent;
+
+ decode_upp_readdir_s(&rcv, buf);
+fprintf(stderr, "do_readdir: dirhandle=%ld off=%d\n", rcv.dir.handle, rcv.off);
+
+ ent = (ARC_DIRENT *) rcv.dir.handle;
+ if (ent->size != -1)
+ return ENOTDIR;
+
+ snd.off = 0;
+ snd.name.nelem = 0;
+
+ if (!rcv.off--)
+ {
+ snd.name.elems = ".";
+ }
+ else if (!rcv.off--)
+ {
+ snd.name.elems = "..";
+ ent = ent->pdir;
+ }
+ else
+ {
+ ent = ent->data.dir.first;
+ while (ent && rcv.off--)
+ ent = ent->next;
+ if (ent)
+ snd.name.elems = ent->name;
+ }
+
+ if (ent)
+ {
+ snd.off = 1;
+ snd.name.nelem = strlen (snd.name.elems);
+ snd.file.handle = (Ulong) ent;
+ }
+
+ repl->size = encode_upp_readdir_r(&snd, buf) - buf;
+
+ return 0;
+}
+
+static int
+do_open (unsigned char *buf, upp_repl *repl)
+{
+ upp_open_s rcv;
+ ARC_DIRENT *ent;
+
+ decode_upp_open_s (&rcv, buf);
+
+ ent = (ARC_DIRENT *) rcv.file.handle;
+ /* Directories are opened here, but read using _readdir instead of _read,
+ so all we do is return success! */
+ if (ent->size == -1)
+ return 0;
+
+ return a_open (ent);
+}
+
+static int
+do_close (unsigned char *buf, upp_repl *repl)
+{
+ upp_close_s rcv;
+ ARC_DIRENT *ent;
+
+ decode_upp_close_s (&rcv, buf);
+
+ ent = (ARC_DIRENT *) rcv.file.handle;
+ if (ent->size == -1)
+ return 0;
+
+ return a_close (ent);
+}
+
+static int
+do_read (unsigned char *mbuf, upp_repl *repl)
+{
+ upp_read_s rcv;
+ upp_read_r snd;
+ ARC_DIRENT *ent;
+ int rc;
+
+ snd.data.nelem = 0;
+
+ decode_upp_read_s (&rcv, mbuf);
+
+ ent = (ARC_DIRENT *) rcv.file.handle;
+ if (ent->size == -1)
+ return EISDIR;
+
+ rc = a_read (ent, rcv.off, rcv.size, &snd.data.nelem, &snd.data.elems);
+ if (rc)
+ return rc;
+ repl->size = encode_upp_read_r (&snd, mbuf) - mbuf;
+ return 0;
+}
+
+static int
+do_mount (unsigned char *buf, upp_repl *repl)
+{
+ upp_mount_r snd;
+
+ snd.root.handle = (Ulong) root;
+ repl->size = encode_upp_mount_r(&snd, buf) - buf;
+ /* INIT */
+ repl->size = encode_upp_mount_r(&snd, buf) - buf;
+ return 0;
+}
+
+static void
+run (int wr, int rd)
+{
+ up_preamble pre;
+ upp_repl repl;
+ /* Ah! The bogey man's a-coming to get me! */
+ unsigned char buf[4096];
+ int error;
+
+ while(readpkt(rd, &pre, buf) == 1)
+ {
+ genpkt(&repl, pre.seq, pre.op);
+
+ switch(pre.op)
+ {
+/*
+#define DO(op, b, r) case userfs_up_##op: \
+ error = (pre.isreq == UP_ENQ ? 0 : do_##op(b, r)); \
+ break;
+ DO(mount, buf, &repl);
+ DO(iread, buf, &repl);
+ DO(lookup, buf, &repl);
+ DO(readdir, buf, &repl);
+ DO(open, buf, &repl);
+ DO(close, buf, &repl);
+ DO(read, buf, &repl);
+#undef DO
+*/
+ case userfs_up_mount:
+ error = (pre.isreq == UP_ENQ ? 0 : do_mount(buf, &repl));
+ break;
+ case userfs_up_iread:
+ error = (pre.isreq == UP_ENQ ? 0 : do_iread(buf, &repl));
+ break;
+ case userfs_up_lookup:
+ error = (pre.isreq == UP_ENQ ? 0 : do_lookup(buf, &repl));
+ break;
+ case userfs_up_readdir:
+ error = (pre.isreq == UP_ENQ ? 0 : do_readdir(buf, &repl));
+ break;
+ case userfs_up_open:
+ error = (pre.isreq == UP_ENQ ? 0 : do_open(buf, &repl));
+ break;
+ case userfs_up_close:
+ error = (pre.isreq == UP_ENQ ? 0 : do_close(buf, &repl));
+ break;
+ case userfs_up_read:
+ error = (pre.isreq == UP_ENQ ? 0 : do_read(buf, &repl));
+ break;
+
+ case userfs_up_write:
+ fprintf(stderr, "userfs_up_write: some op i don't handle: %d\n", pre.op);
+ error = ENOSYS;
+ break;
+ case userfs_up_create:
+ fprintf(stderr, "userfs_up_create: some op i don't handle: %d\n", pre.op);
+ error = ENOSYS;
+ break;
+ case userfs_up_followlink:
+ fprintf(stderr, "userfs_up_followlink: some op i don't handle: %d\n", pre.op);
+ error = ENOSYS;
+ break;
+ case userfs_up_iput:
+ fprintf(stderr, "userfs_up_iput: some op i don't handle: %d\n", pre.op);
+ error = ENOSYS;
+ break;
+ case userfs_up_iwrite:
+ fprintf(stderr, "userfs_up_iwrite: some op i don't handle: %d\n", pre.op);
+ error = ENOSYS;
+ break;
+ case userfs_up_link:
+ fprintf(stderr, "userfs_up_link: some op i don't handle: %d\n", pre.op);
+ error = ENOSYS;
+ break;
+ case userfs_up_multireaddir:
+ fprintf(stderr, "userfs_up_multireaddir: some op i don't handle: %d\n", pre.op);
+ error = ENOSYS;
+ break;
+ case userfs_up_notify_change:
+ fprintf(stderr, "userfs_up_notify_change: some op i don't handle: %d\n", pre.op);
+ error = ENOSYS;
+ break;
+ case userfs_up_permission:
+ fprintf(stderr, "userfs_up_permission: some op i don't handle: %d\n", pre.op);
+ error = ENOSYS;
+ break;
+ case userfs_up_readlink:
+ fprintf(stderr, "userfs_up_readlink: some op i don't handle: %d\n", pre.op);
+ error = ENOSYS;
+ break;
+ case userfs_up_rename:
+ fprintf(stderr, "userfs_up_rename: some op i don't handle: %d\n", pre.op);
+ error = ENOSYS;
+ break;
+ case userfs_up_statfs:
+ fprintf(stderr, "userfs_up_statfs: some op i don't handle: %d\n", pre.op);
+ error = ENOSYS;
+ break;
+ case userfs_up_symlink:
+ fprintf(stderr, "userfs_up_symlink: some op i don't handle: %d\n", pre.op);
+ error = ENOSYS;
+ break;
+ case userfs_up_truncate:
+ fprintf(stderr, "userfs_up_truncate: some op i don't handle: %d\n", pre.op);
+ error = ENOSYS;
+ break;
+ case userfs_up_umount:
+ fprintf(stderr, "userfs_up_umount: some op i don't handle: %d\n", pre.op);
+ error = ENOSYS;
+ break;
+ case userfs_up_unlink:
+ fprintf(stderr, "userfs_up_unlink: some op i don't handle: %d\n", pre.op);
+ error = ENOSYS;
+ break;
+
+ default:
+ fprintf(stderr, "run: some op i don't handle: %d\n", pre.op);
+ error = ENOSYS;
+ break;
+ }
+
+ repl.err_no = error;
+ if (error != 0)
+ repl.size = 0;
+
+ if (writepkt(wr, &repl, buf) != 1)
+ break;
+ }
+}
+
+int
+main (int argc, char **argv)
+{
+ int infd = 0;
+ int outfd = 1;
+ int c;
+
+ while ((c = getopt (argc, argv, "i:o:m:")) != EOF)
+ switch(c)
+ {
+ case 'i':
+ infd = atoi(optarg);
+ break;
+ case 'o':
+ outfd = atoi(optarg);
+ break;
+ case 'm':
+ mpoint = optarg;
+ break;
+ default:
+ fprintf (stderr, "%s: bad option\n", argv[0]);
+ return 1;
+ }
+
+ if (optind != argc - 1)
+ {
+ fprintf (stderr, "%s: no zipfile named\n", argv[0]);
+ return 1;
+ }
+
+ root = arc_read (argv[optind++]);
+ if (!root)
+ return 1;
+
+ signal (SIGCHLD, SIG_IGN);
+
+ run(outfd, infd);
+
+ return 0;
+}
Added: trunk/filesystems/arcfs/zip.c
==============================================================================
--- trunk/filesystems/arcfs/zip.c 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/arcfs/zip.c 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,94 @@
+/* Access ZIP archives. */
+
+#include "arcvfs.h"
+
+#ifdef ARCFMT_ZIP
+
+/* This is a very quick and dirty hack. It works by simply snarfing the whole
+ of a file into core and keeping it there until all FDs refering to it are
+ closed. This is fine for small archived files, tho. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static const char excmd[] = "unzip -p -qq %s %s";
+
+ARC_DIRENT *
+arc_read_zip (const char *zipfile)
+{
+ FILE *fp;
+ char buf[4096];
+ ARC_DIRENT *first = 0;
+ char *name;
+ long csize;
+
+ csize = strlen (zipfile);
+ if (csize < 4 || strcmp (zipfile + csize - 4, ".zip"))
+ return 0;
+
+ first = create_entry (zipfile, zipfile, 0);
+ if (!first)
+ return 0;
+ first->pdir = first;
+ first->size = -1;
+ first->data.dir.first = 0;
+ first->name = (char *) excmd;
+
+ /* USIZE METHOD CSIZE CF% MM-DD-YY HH:MM CRC NAME */
+ sprintf (buf, "unzip -v -qq %s", zipfile);
+ fp = popen (buf, "r");
+ if (!fp)
+ {
+ perror (buf);
+ return 0;
+ }
+ while (fgets (buf, sizeof (buf), fp))
+ {
+ long usize;
+ ARC_DIRENT *ent;
+ int dir_p;
+
+ name = buf + strlen (buf);
+ if (name > buf && name[-1] == '\n')
+ *--name = '\0';
+ if (name > buf && name[-1] == '/')
+ {
+ *--name = '\0';
+ dir_p = 1;
+ }
+ else
+ dir_p = 0;
+
+ usize = strtol (buf, &name, 10);
+ name = skip_field (name); /* METHOD */
+ csize = strtol (name, &name, 10);
+ name = skip_field (name); /* CF% */
+ name = skip_field (name); /* DATE */
+ name = skip_field (name); /* TIME */
+ name = skip_field (name); /* CRC */
+ while (*name == ' ')
+ ++name;
+
+ ent = create_dirent (name, name, &first->data.dir.first, first);
+ if (ent)
+ {
+ if (dir_p)
+ {
+ ent->size = -1;
+ ent->data.dir.first = 0;
+ }
+ else
+ {
+ ent->size = usize;
+ ent->data.file.csize = csize;
+ ent->data.file.refc = 0;
+ }
+ ent->next = 0;
+ }
+ }
+ fclose (fp);
+ return first;
+}
+
+#endif
Added: trunk/filesystems/arcfs/arcfs.h
==============================================================================
--- trunk/filesystems/arcfs/arcfs.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/arcfs/arcfs.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,42 @@
+#ifndef _ARCFS_H
+#define _ARCFS_H
+
+#define FAIL(str) fprintf(stderr, "%s:%d %s failed with errno = %s (%d)\n", __FILE__, __LINE__, str, strerror(errno), errno)
+#ifdef DEBUG
+#include <stdio.h>
+#include <stdlib.h>
+#define DB(x) {x;}
+#else
+#define DB(x) /**/
+#endif
+
+typedef struct tagDIRENT ARC_DIRENT;
+
+struct tagDIRENT {
+ ARC_DIRENT *next;
+ /* The directory to which this belongs (or itself if this is the root
+ directory). */
+ ARC_DIRENT *pdir;
+ /* -1 for a directory. */
+ long size;
+ union {
+ struct {
+ long csize;
+ unsigned char *buf;
+ unsigned int refc; /* PRIVATE to `unzip.c'. */
+ } file;
+ struct {
+ ARC_DIRENT *first;
+ } dir;
+ } data;
+ char *name;
+ /* Structure is then expanded to whatever... */
+ char fullname[1]; /* PRIVATE to `zip.c'. */
+};
+
+int a_open (ARC_DIRENT *);
+int a_close (ARC_DIRENT *);
+int a_read (ARC_DIRENT *, long, long, unsigned long *, unsigned char **);
+ARC_DIRENT *arc_read (const char *);
+
+#endif /* _ARCFS_H */
Added: trunk/filesystems/arcfs/arcvfs.c
==============================================================================
--- trunk/filesystems/arcfs/arcvfs.c 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/arcfs/arcvfs.c 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,178 @@
+/* Archive VFS layer. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "arcvfs.h"
+
+ARC_DIRENT *
+create_entry (const char *fname, const char *name, ARC_DIRENT *dir)
+{
+ ARC_DIRENT *ent;
+
+ ent = malloc (sizeof (ARC_DIRENT) + strlen (fname));
+ if (ent)
+ {
+ strcpy (ent->fullname, fname);
+ ent->name = ent->fullname + (name - fname);
+ ent->pdir = dir;
+ ent->next = 0;
+fprintf(stderr, "create_entry(%s, %s)\n", ent->fullname, ent->name);
+ }
+ return ent;
+}
+
+ARC_DIRENT *
+create_dirent (char *fname, char *name, ARC_DIRENT **p_ent, ARC_DIRENT *dir)
+{
+ char *s;
+fprintf(stderr, "create_dirent(%s, %s)\n", fname, name);
+
+ if (!p_ent)
+ return 0;
+
+ while ((s = strchr (name, '/')) != 0)
+ {
+ *s = '\0';
+ while (*p_ent && strcmp (name, (*p_ent)->name))
+ p_ent = &(*p_ent)->next;
+ if (!*p_ent)
+ {
+ *p_ent = create_entry (fname, name, dir);
+ if (!*p_ent)
+ return 0;
+ (*p_ent)->size = -1;
+ (*p_ent)->data.dir.first = 0;
+ }
+ /* Check for directory/file clash. */
+ if ((*p_ent)->size != -1)
+ return 0;
+ dir = *p_ent;
+ p_ent = &(*p_ent)->data.dir.first;
+ *s++ = '/';
+ name = s;
+ }
+
+ while (*p_ent)
+ p_ent = &(*p_ent)->next;
+
+ *p_ent = create_entry (fname, name, dir);
+
+ return *p_ent;
+}
+
+char *
+skip_field (char *s)
+{
+ while (*s == ' ')
+ ++s;
+ while (*s != ' ')
+ ++s;
+ return s;
+}
+
+static ARC_DIRENT *
+root_ent (ARC_DIRENT *ent)
+{
+ while (ent->pdir != ent)
+ ent = ent->pdir;
+ return ent;
+}
+
+/* The generic read/write code. */
+
+int
+a_open (ARC_DIRENT *ent)
+{
+ FILE *fp;
+ char buf[4096];
+ ARC_DIRENT *root = root_ent (ent);
+
+ sprintf (buf, root->name, root->fullname, ent->fullname);
+ fp = popen (buf, "r");
+ if (!fp)
+ return EIO;
+ ent->data.file.buf = malloc (ent->size);
+ if (ent->data.file.buf)
+ {
+ fread (ent->data.file.buf, ent->size, 1, fp);
+ fclose (fp);
+ ++ent->data.file.refc;
+ return 0;
+ }
+ return EFBIG;
+}
+
+int
+a_close (ARC_DIRENT *ent)
+{
+ if (!ent->data.file.refc)
+ return EBADF;
+ if (!--ent->data.file.refc)
+ free (ent->data.file.buf);
+ return 0;
+}
+
+int
+a_read (ARC_DIRENT *ent, long off, long size,
+ unsigned long *nelem, unsigned char **elems)
+{
+ char *s;
+ long n;
+
+ if (!ent->data.file.refc)
+ return EINVAL;
+
+ s = ent->data.file.buf;
+ n = ent->size;
+
+ if (off > n)
+ off = n;
+ if (size > n - off)
+ size = n - off;
+ *elems = s + off;
+ *nelem = size;
+
+ return 0;
+}
+
+/* The VFS code itself. */
+
+struct vfsfn {
+ ARC_DIRENT *(*fn) (const char *);
+} ents[] = {
+#ifdef ARCFMT_ZIP
+ { arc_read_zip },
+#endif
+#ifdef ARCFMT_HPACK
+ { arc_read_hpack },
+#endif
+#ifdef ARCFMT_ZOO
+ { arc_read_zoo },
+#endif
+#ifdef ARCFMT_TGZ
+ { arc_read_tgz },
+#endif
+ { 0 }
+};
+
+ARC_DIRENT *
+arc_read (const char *zipfile)
+{
+ int i;
+
+ i = 0;
+ while (ents[i].fn)
+ {
+ ARC_DIRENT *root = ents[i].fn (zipfile);
+
+ if (root)
+ return root;
+ ++i;
+ }
+
+ fprintf (stderr, "%s: not a recognized archive type!\n", zipfile);
+ return 0;
+}
Added: trunk/filesystems/arcfs/tgz.c
==============================================================================
--- trunk/filesystems/arcfs/tgz.c 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/arcfs/tgz.c 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,95 @@
+/* Access Gzip'd and Compresse'd TARs. */
+
+#include "arcvfs.h"
+
+#ifdef ARCFMT_TGZ
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static const char excmd[] = "tar xOfz %s %s";
+
+ARC_DIRENT *
+arc_read_tgz (const char *zipfile)
+{
+ FILE *fp;
+ char buf[4096];
+ ARC_DIRENT *first = 0;
+ char *name;
+ long csize;
+
+ csize = strlen (zipfile);
+ if (! ( (csize > 4 && !strcmp (zipfile + csize - 4, ".tgz") )
+ || (csize > 7 && !strcmp (zipfile + csize - 7, ".tar.gz") )
+ || (csize > 6 && !strcmp (zipfile + csize - 6, ".tar.z") )
+ || (csize > 6 && !strcmp (zipfile + csize - 6, ".tar.Z") )
+ )
+ )
+ return 0;
+
+ first = create_entry (zipfile, zipfile, 0);
+ if (!first)
+ return 0;
+ first->pdir = first;
+ first->size = -1;
+ first->data.dir.first = 0;
+ first->name = (char *) excmd;
+
+ /* MODE USER/GROUP USIZE MON DD HH:MM YYYY NAME */
+ sprintf (buf, "tar tvfz %s", zipfile);
+ fp = popen (buf, "r");
+ if (!fp)
+ {
+ perror (buf);
+ return 0;
+ }
+ while (fgets (buf, sizeof (buf), fp))
+ {
+ long usize;
+ ARC_DIRENT *ent;
+ int dir_p;
+
+ name = buf + strlen (buf);
+ if (name > buf && name[-1] == '\n')
+ *--name = '\0';
+ if (name > buf && name[-1] == '/')
+ {
+ *--name = '\0';
+ dir_p = 1;
+ }
+ else
+ dir_p = 0;
+
+ name = skip_field (buf); /* MODE */
+ name = skip_field (name); /* OWNER/GROUP */
+ usize = csize = strtol (name, &name, 10);
+ name = skip_field (name); /* MMM */
+ /* name = skip_field (name); */ /* DD */
+ name = skip_field (name); /* HH:MM */
+ /* name = skip_field (name); */ /* YYYY */
+ while (*name == ' ')
+ ++name;
+
+ ent = create_dirent (name, name, &first->data.dir.first, first);
+ if (ent)
+ {
+ if (dir_p)
+ {
+ ent->size = -1;
+ ent->data.dir.first = 0;
+ }
+ else
+ {
+ ent->size = usize;
+ ent->data.file.csize = csize;
+ ent->data.file.refc = 0;
+ }
+ ent->next = 0;
+ }
+ }
+ fclose (fp);
+ return first;
+}
+
+#endif
Added: trunk/filesystems/arcfs/arcvfs.h
==============================================================================
--- trunk/filesystems/arcfs/arcvfs.h 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/arcfs/arcvfs.h 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,28 @@
+#ifndef _ARCVFS_H
+#define _ARCVFS_H
+
+#include "arcfs.h"
+
+#define ARCFMT_ZIP
+#undef ARCFMT_HPACK
+#undef ARCFMT_ZOO
+#define ARCFMT_TGZ
+
+#ifdef ARCFMT_ZIP
+ARC_DIRENT *arc_read_zip (const char *);
+#endif
+#ifdef ARCFMT_HPACK
+ARC_DIRENT *arc_read_hpack (const char *);
+#endif
+#ifdef ARCFMT_ZOO
+ARC_DIRENT *arc_read_zoo (const char *);
+#endif
+#ifdef ARCFMT_TGZ
+ARC_DIRENT *arc_read_tgz (const char *);
+#endif
+
+ARC_DIRENT *create_entry (const char *, const char *, ARC_DIRENT *);
+ARC_DIRENT *create_dirent (char *, char *, ARC_DIRENT **, ARC_DIRENT *);
+char *skip_field (char *);
+
+#endif /* _ARCVFS_H */
Added: trunk/filesystems/arcfs/README
==============================================================================
--- trunk/filesystems/arcfs/README 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/arcfs/README 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,38 @@
+ArcFS - transparent read-only archive access for Linux
+
+Copyright (C) 1994 David P Gymer
+
+Derived in part from code written by Jeremy Fitzhardinge
+<jeremy at sw.oz.au>.
+
+
+This code represents a simple user-level filesystem for Linux using
+Jeremy Fitzhardinge's userfs (which must be gotten and installed into
+the kernel separately) which presents a zip or tar.gz archive as a
+read-only filesystem, allowing one to cd into the archive, use less or
+emacs to view files, and ls to view the archive contents.
+
+It should be easy for even fairly inexperienced C programmers to
+extend to other types of archives.
+
+This code is a quick and dirty hack. It's not meant as anything else;
+it works, but it ain't pretty, and it's certainly not bulletproof
+(heck, it's not even paper-dart proof!).
+
+Basic use goes something like this,
+ "muserfs ./arcfs /mnt/0 ./test.tar.gz"
+then you can do
+ "find /mnt/0 -ls"
+and see what's in the archive. After you've finished, make sure no
+process has anything in the arhive open (including as it's current
+directory; ie. if you did "cd /mnt/0/a.directory", be sure to cd out)
+and then hit ^C or send a SIGINT to "arcfs" to kill it and unmount the
+archive.
+
+[I just upgrdaded my copy of umount, and I have to do
+ "/sbin/umount /mnt/0"
+by hand to kill it off completely.]
+
+-- Dave
+dpg at cs.nott.ac.uk (but only til June or July this year :-[ ).
+Just Another Linux Hacker
Added: trunk/filesystems/arcfs/Makefile
==============================================================================
--- trunk/filesystems/arcfs/Makefile 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/filesystems/arcfs/Makefile 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,35 @@
+CC = gcc
+CFLAGS = -g -I../../kernel
+CPPFLAGS = #-DDEBUG
+LDFLAGS = -s
+
+SRCS = arcfs.c arcvfs.c zip.c tgz.c arcvfs.h arcfs.h
+DISTS = $(SRCS) README Makefile
+
+arcfs : arcfs.o arcvfs.o zip.o tgz.o
+
+.PHONY : dist dep clean realclean spotless
+
+dep : .depend
+.depend : $(SRCS)
+ $(CC) $(CFLAGS) -MM *.c > .depend
+
+dist : $(DISTS)
+ rm -rf /tmp/arcfs
+ mkdir /tmp/arcfs
+ cp -a $(DISTS) /tmp/arcfs
+ (cd /tmp; tar cfvz - arcfs) >arcfs.tar.gz
+ rm -rf /tmp/arcfs
+
+clean :
+ rm -f *.o core *~ *.orig *.rej arcfs
+
+realclean : clean
+ rm -rf arcfs
+
+spotless : realclean
+ rm -f .depend
+
+ifeq (.depend,$(wildcard .depend))
+include .depend
+endif
Added: trunk/COPYING
==============================================================================
--- trunk/COPYING 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/COPYING 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
Added: trunk/Makefile
==============================================================================
--- trunk/Makefile 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/Makefile 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,30 @@
+TOP=.
+SUBDIRS=genser lwp kernel utils lib
+
+include rules
+
+all:: subdirs readmes
+
+subdirs:: $(DEPEND)
+
+.depend: depend
+ touch .depend
+
+clobber:: clean
+ find . \( -name .depend -o -name '*~' \) -print | xargs rm -f
+
+clean::
+ rm -f *~
+
+install:
+ insmod kernel/src/userfs.o
+
+readmes: README README.ps
+
+README: README.mm
+ groff -Tascii -mgm $< > $@ || rm -f $@
+
+README.ps: README.mm
+ groff -Tps -mgm $< > $@ || rm -f $@
+
+include rules.sub
Added: trunk/README.ps
==============================================================================
--- trunk/README.ps 2003-05-23 23:51:35 UTC (rev 1)
+++ trunk/README.ps 2003-05-29 09:40:42 UTC (rev 2)
@@ -0,0 +1,1315 @@
+%!PS-Adobe-3.0
+%%Creator: groff version 1.10
+%%CreationDate: Sat May 24 22:23:42 1997
+%%DocumentNeededResources: font Times-Bold
+%%+ font Times-Italic
+%%+ font Times-Roman
+%%+ font Courier
+%%DocumentSuppliedResources: procset grops 1.10 0
+%%Pages: 11
+%%PageOrder: Ascend
+%%Orientation: Portrait
+%%EndComments
+%%BeginProlog
+%%BeginResource: procset grops 1.10 0
+/setpacking where{
+pop
+currentpacking
+true setpacking
+}if
+/grops 120 dict dup begin
+/SC 32 def
+/A/show load def
+/B{0 SC 3 -1 roll widthshow}bind def
+/C{0 exch ashow}bind def
+/D{0 exch 0 SC 5 2 roll awidthshow}bind def
+/E{0 rmoveto show}bind def
+/F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def
+/G{0 rmoveto 0 exch ashow}bind def
+/H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/I{0 exch rmoveto show}bind def
+/J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def
+/K{0 exch rmoveto 0 exch ashow}bind def
+/L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/M{rmoveto show}bind def
+/N{rmoveto 0 SC 3 -1 roll widthshow}bind def
+/O{rmoveto 0 exch ashow}bind def
+/P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/Q{moveto show}bind def
+/R{moveto 0 SC 3 -1 roll widthshow}bind def
+/S{moveto 0 exch ashow}bind def
+/T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/SF{
+findfont exch
+[exch dup 0 exch 0 exch neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/MF{
+findfont
+[5 2 roll
+0 3 1 roll
+neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/level0 0 def
+/RES 0 def
+/PL 0 def
+/LS 0 def
+/MANUAL{
+statusdict begin/manualfeed true store end
+}bind def
+/PLG{
+gsave newpath clippath pathbbox grestore
+exch pop add exch pop
+}bind def
+/BP{
+/level0 save def
+1 setlinecap
+1 setlinejoin
+72 RES div dup scale
+LS{
+90 rotate
+}{
+0 PL translate
+}ifelse
+1 -1 scale
+}bind def
+/EP{
+level0 restore
+showpage
+}bind def
+/DA{
+newpath arcn stroke
+}bind def
+/SN{
+transform
+.25 sub exch .25 sub exch
+round .25 add exch round .25 add exch
+itransform
+}bind def
+/DL{
+SN
+moveto
+SN
+lineto stroke
+}bind def
+/DC{
+newpath 0 360 arc closepath
+}bind def
+/TM matrix def
+/DE{
+TM currentmatrix pop
+translate scale newpath 0 0 .5 0 360 arc closepath
+TM setmatrix
+}bind def
+/RC/rcurveto load def
+/RL/rlineto load def
+/ST/stroke load def
+/MT/moveto load def
+/CL/closepath load def
+/FL{
+currentgray exch setgray fill setgray
+}bind def
+/BL/fill load def
+/LW/setlinewidth load def
+/RE{
+findfont
+dup maxlength 1 index/FontName known not{1 add}if dict begin
+{
+1 index/FID ne{def}{pop pop}ifelse
+}forall
+/Encoding exch def
+dup/FontName exch def
+currentdict end definefont pop
+}bind def
+/DEFS 0 def
+/EBEGIN{
+moveto
+DEFS begin
+}bind def
+/EEND/end load def
+/CNT 0 def
+/level1 0 def
+/PBEGIN{
+/level1 save def
+translate
+div 3 1 roll div exch scale
+neg exch neg exch translate
+0 setgray
+0 setlinecap
+1 setlinewidth
+0 setlinejoin
+10 setmiterlimit
+[]0 setdash
+/setstrokeadjust where{
+pop
+false setstrokeadjust
+}if
+/setoverprint where{
+pop
+false setoverprint
+}if
+newpath
+/CNT countdictstack def
+userdict begin
+/showpage{}def
+}bind def
+/PEND{
+clear
+countdictstack CNT sub{end}repeat
+level1 restore
+}bind def
+end def
+/setpacking where{
+pop
+setpacking
+}if
+%%EndResource
+%%IncludeResource: font Times-Bold
+%%IncludeResource: font Times-Italic
+%%IncludeResource: font Times-Roman
+%%IncludeResource: font Courier
+grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72
+def/PL 792 def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron
+/scaron/zcaron/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/space/exclam/quotedbl/numbersign/dollar/percent
+/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen
+/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon
+/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O
+/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/circumflex
+/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y
+/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase/guillemotleft
+/guillemotright/bullet/florin/fraction/perthousand/dagger/daggerdbl
+/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut
+/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash
+/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen
+/brokenbar/section/dieresis/copyright/ordfeminine/guilsinglleft
+/logicalnot/minus/registered/macron/degree/plusminus/twosuperior
+/threesuperior/acute/mu/paragraph/periodcentered/cedilla/onesuperior
+/ordmasculine/guilsinglright/onequarter/onehalf/threequarters
+/questiondown/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE
+/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex
+/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis
+/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn
+/germandbls/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla
+/egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis
+/eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide/oslash
+/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis]def
+/Courier at 0 ENC0/Courier RE/Times-Roman at 0 ENC0/Times-Roman RE
+/Times-Italic at 0 ENC0/Times-Italic RE/Times-Bold at 0 ENC0/Times-Bold RE
+%%EndProlog
+%%Page: 1 1
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 12/Times-Bold at 0 SF(Userfs \255 Filesystems Implemented as User Pr)
+155.886 82.031 Q(ocesses)-.216 E/F1 10/Times-Italic at 0 SF -.25(Je)204.375
+100.031 S -.37(re).25 G(my F).37 E(itzhar)-.45 E(ding)-.37 E 2.5(e<)-.1
+G(jer)-2.5 E(emy at sw)-.37 E(.oz.au>)-.74 E/F2 10/Times-Roman at 0 SF(Softw)
+253.095 118.031 Q(ay Pty)-.1 E 2.5(.L)-.65 G(td.)-2.5 E F1 2.5(1. Intr)
+72 166.031 R(oduction)-.45 E F2 .156(Userfs is a mechanism by which nor\
+mal user processes can be a Linux \214lesystem.)72 184.031 R .155
+(There are man)5.155 F 2.655(yu)-.15 G .155(ses for)-2.655 F
+(this, including:)72 196.031 Q(Prototype \214lesystems)72 214.031 Q .051
+(Prototype ne)97 232.031 R 2.551(wb)-.25 G .052
+(lock allocation algorithms in a user process and deb)-2.551 F .052
+(ug with gdb before going into the)-.2 F(compile-crash-reboot c)97
+244.031 Q(ycle of k)-.15 E(ernel de)-.1 E -.15(ve)-.25 G(lopment.).15 E
+(Infrequent use \214lesystems)72 262.031 Q -1.1(Yo)97 280.031 S 3.08(uw)
+1.1 G .58(ant to mount "F)-3.18 F .58
+(ooBaz 0X" \214lesystems under Linux, b)-.15 F .579(ut you don')-.2 F
+3.079(tw)-.18 G .579(ant it that often, and you)-3.179 F(don')97 292.031
+Q 2.675(tn)-.18 G .175(eed it to be maximum speed.)-2.675 F .176
+(Rather than trying to get the k)5.175 F .176
+(ernel itself to understand, or write)-.1 F
+(specialised tools, write a \214lesystem program.)97 304.031 Q
+(Add capabilities to e)72 322.031 Q(xisting \214lesystems)-.15 E -.8(Wa)
+97 340.031 S .764(nt compression, encryption, A).8 F 3.264(CLs? Ha)-.4 F
+1.064 -.15(ve a p)-.2 H .764(rocess to mirror an e).15 F .764
+(xisting \214le tree, b)-.15 F .764(ut with your)-.2 F -.25(ow)97
+352.031 S 2.5(ne).25 G(xtentions and semantics.)-2.65 E
+(Completely virtual \214lesystems and ne)72 370.031 Q 2.5(wi)-.25 G
+(nterf)-2.5 E(aces)-.1 E .642(Add a \214lesystem-type interf)97 388.031
+R .642(ace to an e)-.1 F .643
+(xisting mechanism, or a \214lesystem interf)-.15 F .643(ace as a ne)-.1
+F 3.143(ww)-.25 G .643(ay of)-3.243 F(representing data.)97 400.031 Q
+(Sick of FTP?)5 E(Ho)5 E 2.5(wa)-.25 G(bout)-2.5 E/F3 9/Courier at 0 SF 5.4
+($m)122 417.031 S(kdir /ftp/tsx-11.mit.edu)-5.4 E 5.4($c)122 428.031 S
+5.4(d/)-5.4 G(ftp/tsx-11.mit.edu/pub/linux)-5.4 E 5.4($c)122 439.031 S
+5.4(pR)-5.4 G(EADME $HOME)-5.4 E F2(Or mail?)97 457.031 Q F3 5.4($c)122
+474.031 S 5.4(d/)-5.4 G(mail)-5.4 E 5.4($l)122 485.031 S(s)-5.4 E
+(001.sbg at socs.uts.edu.au)122 496.031 Q(002.Leroy)122 507.031 Q
+(003.tlukka at vinkku.hut.fi)122 518.031 Q(004.Davor_Jadrijevic)122 529.031
+Q 5.4($c)122 540.031 S(at */From)-5.4 E(From: sbg at socs.uts.edu.au)122
+551.031 Q(From: leroy at socs.uts.edu.au \(Leroy\))122 562.031 Q
+(From: tlukka at vinkku.hut.fi)122 573.031 Q
+(From: davor%emard.uucp at ds5000.irb.hr \(Davor Jadrijevic\))122 584.031 Q
+5.4($c)122 595.031 S(at */Subject)-5.4 E(Subject: More things)122
+606.031 Q(Subject: \(none\))122 617.031 Q(Subject: That userfs thing)122
+628.031 Q(Subject: mailfs again)122 639.031 Q($)122 650.031 Q F2 -1.1
+(Yo)72 668.031 S 2.5(ug)1.1 G(et the idea.)-2.5 E F1 2.5
+(2. Installation)72 692.031 R EP
+%%Page: 2 2
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman at 0 SF 2.5(-2-)279.67 48 S/F1 10/Times-Italic at 0 SF 2.5
+(2.1 K)72 96 R(ernel)-.35 E F0 .026(First of all, if you ha)72 114 R
+.326 -.15(ve i)-.2 H .026(nstalled userfs before, remo).15 F .326 -.15
+(ve t)-.15 H .026(races of pre).15 F .026(vious v)-.25 F .026
+(ersions of userfs: mak)-.15 F 2.526(es)-.1 G .026(ure there)-2.526 F
+(are no userfs header \214les in)72 126 Q F1(linux/include/linux)2.5 E
+F0(and no userfs patches to an)2.5 E 2.5(yo)-.15 G 2.5(ft)-2.5 G(he k)
+-2.5 E(ernel source.)-.1 E 1.171(Otherwise, the k)72 144 R 1.171
+(ernel module should just compile with the rest of the b)-.1 F 1.172
+(uild process.)-.2 F 1.172(Userfs is currently)6.172 F 2.296
+(supported for 2.0.x \(tested up to 2.0.0\), and for 1.3.x.)72 156 R
+2.295(It should w)7.295 F 2.295(ork out the k)-.1 F 2.295(ernel v)-.1 F
+2.295(ersion you')-.15 F(re)-.5 E .355
+(compiling for and con\214gure itself appropriately)72 168 R 5.355(.T)
+-.65 G .355(here are no k)-5.355 F .356
+(ernel patches and compiling userfs into the)-.1 F -.1(ke)72 180 S
+(rnel is not supported.).1 E 1.925 -.8(To i)72 198 T .325
+(nstall the module you need the).8 F/F2 10/Times-Bold at 0 SF(modutils)
+2.825 E F0 .325(package, which should be a)2.825 F -.25(va)-.2 G .324
+(ilable from your local Linux ftp).25 F(archi)72 210 Q -.15(ve)-.25 G
+6.414(.I).15 G 3.914(ts)-6.414 G 1.415
+(hould be clear from its documentation what you need to do with)-3.914 F
+F1(userfs.o)3.915 E F0 1.415(to get it into the)3.915 F -.1(ke)72 222 S
+3.413(rnel. If).1 F .912(you get some w)3.413 F .912
+(arnings about multiply de\214ned symbols, ignore them:)-.1 F .912
+(only unde\214ned symbols)5.912 F(are a problem.)72 234 Q -1.1(Yo)5 G
+2.5(uc)1.1 G(an compile the k)-2.5 E
+(ernel and module with either ELF or a.out compilers; I used ELF)-.1 E
+(.)-.8 E .211(The k)72 252 R .212(ernel module supports modv)-.1 F .212
+(erions, so it generally w)-.15 F(on')-.1 E 2.712(tb)-.18 G 2.712(en)
+-2.712 G .212(ecessary to recompile it for e)-2.712 F -.15(ve)-.25 G
+.212(ry k).15 F(ernel)-.1 E -.15(ve)72 264 S(rsion;).15 E F1(insmod)2.79
+E F0 .29(will let you kno)2.79 F 2.79(wi)-.25 G 2.79(fy)-2.79 G .29
+(ou need to recompile the userfs module \(with luck - otherwise Linux)
+-2.79 F(will helpfully let you kno)72 276 Q 2.5(ww)-.25 G
+(ith obscure beha)-2.5 E(viour or k)-.2 E(ernel panics...\).)-.1 E F1
+2.5(2.2 Non-k)72 294 R(ernel Code)-.1 E F0 1.384
+(Building the rest of the code should be a matter of typing "mak)72 312
+R 1.384(e" at the top userfs directory)-.1 F 3.885(.T)-.65 G 1.385
+(his will)-3.885 F .807(generate dependencies and b)72 324 R .807
+(uild the utilities needed \(genser\), the library)-.2 F 3.307(,t)-.65 G
+.806(he clients using the library and)-3.307 F(the k)72 336 Q
+(ernel module.)-.1 E(There will be some w)5 E(arnings; ignore them.)-.1
+E 3.567(Iu)72 354 S 1.068(sed gcc 2.7.0; you probably need to use the l\
+atest compiler and libraries \(libg++ 2.7.0.1\) for the C++)-3.567 F
+(\(though I')72 366 Q .3 -.15(ve a)-.5 H -.2(vo)-.05 G
+(ided templates and e).2 E
+(xceptions; g++ has enough problems with simple things\).)-.15 E F1 2.5
+(2.3 Mailing)72 384 R(list)2.5 E F0 .694
+(The old USERFS channel on the Linux Acti)72 402 R .693(vists list serv)
+-.25 F .693(er is no)-.15 F 3.193(wd)-.25 G 3.193(efunct. There)-3.193 F
+.693(is a ne)3.193 F 3.193(wl)-.25 G(ist:)-3.193 E/F3 10/Courier at 0 SF
+(linux-)3.193 E(userfs at vger.rutgers.edu)72 414 Q F0 5.464(.T)C 2.964(os)
+-6.264 G .464(ubscribe, send mail to)-2.964 F F3
+(majordomo at vger.rutgers.edu)2.965 E F0(with)2.965 E(the contents)72 426
+Q/F4 9/Courier at 0 SF(subscribe linux-userfs [your email address])97 443 Q
+F1 2.5(2.4 Bugs,)72 461 R(comments, etc)2.5 E F0 .361
+(When you \214nd a b)72 479 R .361(ug, tell me.)-.2 F .361
+(Please send me the code you')5.361 F .36(re using, the k)-.5 F .36
+(ernel v)-.1 F .36(ersion, whate)-.15 F -.15(ve)-.25 G 2.86(rc).15 G
+(hanges)-2.86 E(you')72 491 Q .808 -.15(ve m)-.5 H .509(ade to userfs k)
+.15 F .509(ernel code, and instructions or a script to reproduce the b)
+-.1 F 3.009(ug. Don')-.2 F 3.009(tj)-.18 G .509(ust tell me "it)-3.009 F
+(brok)72 503 Q(e.")-.1 E 1.174(If you')72 521 R 1.474 -.15(ve m)-.5 H
+1.174(ade changes to the k).15 F 1.174
+(ernel code, please send it to me rather than sending it out to the w)
+-.1 F(orld.)-.1 E 2.177(Please send me comments, ideas for ne)72 533 R
+4.677(wk)-.25 G 2.177(ernel features, or things that you think w)-4.777
+F 2.177(ould mak)-.1 F 4.677(eg)-.1 G(ood)-4.677 E .637(\214lesystems b)
+72 545 R .637(ut you can')-.2 F 3.137(td)-.18 G 3.137(or)-3.137 G .637
+(ight no)-3.137 F 4.437 -.65(w. A)-.25 H .636
+(lso feel free to ask questions about either the implementation of).65 F
+(my code, ho)72 557 Q 2.5(wt)-.25 G 2.5(ow)-2.5 G(rite your o)-2.5 E
+(wn userfs clients, or e)-.25 E -.15(ve)-.25 G 2.5(nj).15 G
+(ust to tell me you got it w)-2.5 E(orking.)-.1 E
+(Send mail to either me \(Jeremy Fitzhardinge <jeremy at sw)72 575 Q
+(.oz.au>\) or to the mailing list \(see abo)-.65 E -.15(ve)-.15 G(\).)
+.15 E F1 2.5(3. Using)72 599 R(clients)2.5 E F0 .337
+(Clients are generally mounted with the)72 617 R F2(muserfs)2.837 E F0
+2.837(command. It')2.837 F 2.837(sq)-.55 G .337(uite simple \255 it')
+-2.837 F 2.837(sap)-.55 G .337(rogram which mak)-2.837 F(es)-.1 E 1.893
+(sure the mount point is le)72 629 R -.05(ga)-.15 G 4.393(lf).05 G 1.893
+(or the user to mount on, and mounts the gi)-4.393 F -.15(ve)-.25 G
+4.392(np).15 G 1.892(rocess with the user')-4.392 F(s)-.55 E 2.557
+(permissions. Note)72 641 R .057(that an)2.557 F 2.557(yu)-.15 G .057(s\
+er can mount a process, so more checking is done on the mount point tha\
+n for)-2.557 F 2.563(an)72 653 S .063(ormal mount.)-2.563 F .062
+(Unless the user is root, the mount point must be o)5.062 F .062
+(wned by the user and writable.)-.25 F F2(muserfs)5.062 E F0
+(has a man page, which is e)72 665 Q -.15(ve)-.25 G 2.5(nu).15 G 2.5(pt)
+-2.5 G 2.5(od)-2.5 G(ate.)-2.5 E(There are a fe)72 683 Q 2.5(wu)-.25 G
+(seful or semi-useful clients:)-2.5 E F2(homer)2.5 E F0(,)A F2(ftpfs)2.5
+E F0(,)A F2(mailfs)2.5 E F0(and)2.5 E F2(ar)2.5 E(cfs.)-.18 E F0
+(Homer is)72 701 Q .207(written in C++, and uses the C++ library in the\
+ lib directory to do most of its w)2.706 F 2.707(ork. All)-.1 F .207
+(it does is)2.707 F .579(set up a single directory under its mount poin\
+t which contains symbolic links named after each user)97 713 R .464
+(name in the passw)97 725 R .464
+(ord \214le, which points to the associated home directory)-.1 F 5.464
+(.M)-.65 G .464(ounted on /u it mak)-5.464 F .465(es a)-.1 F
+(passible replacement for ~ e)97 737 Q(xpansion in a shell \(b)-.15 E
+(ut it w)-.2 E(orks for an)-.1 E 2.5(yp)-.15 G(rogram\).)-2.5 E EP
+%%Page: 3 3
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman at 0 SF 2.5(-3-)279.67 48 S 1.94(Ftpfs is)72 96 R 1.384
+(an e)3.884 F 1.384(xperimental \214lesystem which allo)-.15 F 1.384
+(ws readonly access to FTP sites, maintaining a long-term)-.25 F .974
+(disk cache.)97 108 R .974(Its intended primarily for anon)5.974 F .975
+(ymous FTP)-.15 F 3.475(,b)-1.11 G .975
+(ut can also be used for authenticated FTP)-3.675 F(sessions.)97 120 Q
+(Mailfs is)72 138 Q 1.055(by Da)3.555 F -.2(vo)-.2 G 3.555(rJ).2 G
+(adrije)-3.555 E 3.555(vic. It)-.25 F 1.054(is for reading mail.)3.555 F
+1.054(Currently its read-only and does not track mailbox)6.054 F
+(changes, and is no longer being acti)97 150 Q -.15(ve)-.25 G(ly de).15
+E -.15(ve)-.25 G 2.5(loped. Pester).15 F(Da)2.5 E -.2(vo)-.2 G 2.5(r\()
+.2 G(or \214x it yourself\).)-2.5 E .29(Arcfs w)72 168 R .283
+(as written by Da)-.1 F .283(vid Gymer)-.2 F 5.283(.I)-.55 G 2.783(ta)
+-5.283 G(llo)-2.783 E .284
+(ws you to mount a compressed tar \214le as a read-only \214lesystem,)
+-.25 F .712(and inspect it with normal tools.)97 180 R(It')5.711 E 3.211
+(sp)-.55 G .711(retty neat, b)-3.211 F .711(ut not recommended for hea)
+-.2 F .711(vy "production" use,)-.2 F(or for v)97 192 Q(ery lar)-.15 E
+(ge \214les.)-.18 E/F1 10/Times-Italic at 0 SF 2.5(4. Theory)72 216 R
+(of oper)2.5 E(ation)-.15 E F0 .638(The k)72 234 R .638(ernel module re)
+-.1 F .638(gisters a ne)-.15 F 3.138<778c>-.25 G .638
+(lesystem type with the k)-3.138 F .638(ernel \("userfs"\).)-.1 F .638
+(The \214lesystem itself is v)5.638 F(ery)-.15 E .754
+(simple; all it does it tak)72 246 R .754(es the normal k)-.1 F .754
+(ernel \214lesystem requests, wraps them up into well-de\214ned pack)-.1
+F(ets)-.1 E 1.107(and squirts them do)72 258 R 1.107
+(wn a \214le descriptor \(presumeably connected to a process\) and w)
+-.25 F 1.107(aits for the reply on)-.1 F(another \214le descriptor)72
+270 Q(.)-.55 E 1.588(If the \214lesystem process is on the same machine\
+, then the \214le descriptors are probably ordinary pipes.)72 288 R(Ho)
+72 300 Q(we)-.25 E -.15(ve)-.25 G 2.546 -.4(r, u).15 H 1.747
+(serfs just reads and writes on the \214le descriptors, so the).4 F
+4.247(yc)-.15 G 1.747(ould be an)-4.247 F 1.747(ything; \214les, sock)
+-.15 F(ets,)-.1 E(de)72 312 Q(vices \255 userfs doesn')-.25 E 2.5(tc)
+-.18 G(are.)-2.5 E 1.954(The follo)72 330 R 1.954
+(wing is not a comprehensi)-.25 F 2.254 -.15(ve t)-.25 H 1.954
+(utorial on writing \214lesystems, or a detailed "ho).15 F 4.453(wi)-.25
+G 4.453(tw)-4.453 G 1.953(orks" or)-4.553 F 1.862
+(speci\214cation of the e)72 342 R 1.862(xisting code.)-.15 F 1.863
+(It is intended to gi)6.863 F 2.163 -.15(ve s)-.25 H 1.863
+(ome idea of what I w).15 F 1.863(as thinking, and basic)-.1 F
+(concepts to bear in mind while poking about in my k)72 354 Q
+(ernel or user code.)-.1 E F1 2.5(4.1 Priorities)72 372 R F0 2.5(Ih)72
+390 S(ad a number of goals which I w)-2.5 E
+(anted satis\214ed by this thing \(from most to least important\):)-.1 E
+(Fle)72 408 Q(xibility)-.15 E 3.607(Iw)97 426 S 1.107
+(ant the process to ha)-3.707 F 1.407 -.15(ve a)-.2 H 3.607(sm).15 G
+1.107(uch po)-3.607 F 1.106(wer as a k)-.25 F 1.106
+(ernel-resident \214lesystem as possible.)-.1 F 3.606(Iw)6.106 G 1.106
+(anted to)-3.706 F -.1(ke)97 438 S(ep the interf).1 E
+(aces as generic and \215e)-.1 E 2.5(xible. This)-.15 F
+(has been mostly achie)2.5 E -.15(ve)-.25 G(d.).15 E(Rob)72 456 Q
+(ustness)-.2 E .281(Since I see prototyping and de)97 474 R -.15(ve)-.25
+G .281(lopment a major use for userfs, it seems important to mak).15 F
+2.782(es)-.1 G .282(ure that)-2.782 F 1.336(the k)97 486 R 1.336
+(ernel code can')-.1 F 3.836(t\()-.18 G 1.336(at w)-3.836 F 1.336
+(orst\) crash or lock up if the user code f)-.1 F 3.836(ails. As)-.1 F
+1.336(it stands, it should be)3.836 F .632
+(impossible for a user process to crash the k)97 498 R .632(ernel, b)-.1
+F .632(ut it is possible for a bad user process to lock up)-.2 F
+(processes trying to use the \214lesystem.)97 510 Q 1.668(It is also po\
+ssible for a process to go strange while it is being mounted, lea)97 528
+R 1.667(ving a half-mounted)-.2 F 5.066(\214lesystem. The)97 540 R 2.566
+(mountpoint becomes a nulled out inode, b)5.066 F 2.567(ut the k)-.2 F
+2.567(ernel refuses to unmount it)-.1 F .899(\(because it isn')97 552 R
+3.398(tm)-.18 G .898(ounted\), and refuses to mount on it \(because it')
+-3.398 F 3.398(sb)-.55 G 3.398(usy\). This)-3.598 F .898
+(happens much less)3.398 F .956(often than it used to, because muserfs \
+does a simple check to see if the \214lesystem process is at all)97 564
+R(viable.)97 576 Q -1.27 -.74(Av a)72 594 T
+(ilability to users and Security).74 E(I')97 612 Q 3.623(dl)-.5 G(ik)
+-3.623 E 3.623(ea)-.1 G 1.423 -.15(ny u)-3.623 H 1.123
+(ser to be able to write a \214lesystem process.).15 F -.35(Tr)6.122 G
+(aditionally).35 E 3.622<2c8c>-.65 G 1.122(lesystems are things that)
+-3.622 F .25(embody the security of Unix, and are therefore v)97 624 R
+.251(ery much superuser)-.15 F .251(-only things.)-.2 F(Ho)5.251 E(we)
+-.25 E -.15(ve)-.25 G 1.051 -.4(r, t).15 H .251(here are).4 F 1.259
+(only a couple of really sensiti)97 636 R 1.559 -.15(ve f)-.25 H 1.259
+(eatures that shouldn').15 F 3.759(tb)-.18 G 3.759(ea)-3.759 G 1.259
+(ble to be controlled by an)-3.759 F 3.758(yu)-.15 G 1.258(ser: suid)
+-3.758 F -.15(exe)97 648 S 1.156(cutables and de).15 F 1.156
+(vice nodes.)-.25 F 1.156
+(Since a trusted superuser process is still required to call the mount)
+6.156 F .99(system call, and that process can set the no-suid and no-de)
+97 660 R .989(vice \215ags, the \214lesystem code can')-.25 F 3.489(tu)
+-.18 G(se)-3.489 E .35(these as security holes.)97 672 R 2.85(Ic)5.35 G
+(an')-2.85 E 2.85(tt)-.18 G .35(hink of an)-2.85 F .35
+(ything else that needs special care from a security point of)-.15 F
+(vie)97 684 Q 4.093 -.65(w. H)-.25 H -.25(ow).65 G -2.15 -.25(ev e).25 H
+1.093 -.4(r, s).25 H .292(ince the \214lesystem is completely under the\
+ control of the process, one can mak).4 F 2.792(en)-.1 G(o)-2.792 E .576
+(assumptions about its contents.)97 696 R -.15(Fo)5.576 G 3.076(re).15 G
+.576(xample "." and ".." may not do e)-3.226 F .576
+(xpected things, symlinks may)-.15 F .677
+(point to places other than what readlink returns.)97 708 R .677
+(This mak)5.677 F .677(es na)-.1 F(vig)-.2 E .676
+(ating such \214lesystems a ne)-.05 F 3.176(wa)-.25 G(nd)-3.176 E
+(interesting e)97 720 Q(xperience.)-.15 E EP
+%%Page: 4 4
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman at 0 SF 2.5(-4-)279.67 48 S(Ef)72 96 Q(\214cienc)-.25 E
+(y)-.15 E(Ef)97 114 Q(\214cienc)-.25 E 3.763(yi)-.15 G 3.763(sm)-3.763 G
+3.763(yl)-3.763 G -.25(ow)-3.763 G 1.263(est priority).25 F 3.763(,b)
+-.65 G 1.264(ut it is still important.)-3.963 F 1.264
+(Unfortunately the other requirements \(as)6.264 F .932(usual\) mak)97
+126 R 3.432(et)-.1 G .932(hings less ef)-3.432 F 3.432(\214cient. The)
+-.25 F .932(most signi\214cant inef)3.432 F(\214cienc)-.25 E 3.431(yi)
+-.15 G 3.431(st)-3.431 G .931(he conte)-3.431 F .931
+(xt switches between)-.15 F .416(the k)97 138 R .416
+(ernel and the process.)-.1 F 2.916(It)5.416 G .417
+(hink the most bene\214ts can be g)-2.916 F .417
+(ained by reducing the number of these.)-.05 F(There are se)97 150 Q
+-.15(ve)-.25 G(ral approaches to this:).15 E/F1 8/Times-Roman at 0 SF<83>
+114.2 168 Q F0 .037(If the process w)5 F .036(ants a def)-.1 F .036
+(ault beha)-.1 F .036
+(viour for an operation, then it can be done in the k)-.2 F 2.536
+(ernel. The)-.1 F 1.631(best e)122 180 R 1.631
+(xample of this is permission checking - if the process w)-.15 F 1.632
+(ants normal unix permission)-.1 F .667(checking then it doesn')122 192
+R 3.167(tn)-.18 G .666(eed to do it itself.)-3.167 F .666
+(Otherwise it can tak)5.666 F 3.166(ea)-.1 G .666
+(ll the permission requests)-3.166 F 2.037(from the k)122 204 R 2.037
+(ernel, and implement other permission policies.)-.1 F 2.038
+(This is currently implemented.)7.037 F .68
+(When the \214lesystem is \214rst mounted, the k)122 216 R .68
+(ernel asks the process what requests it will accept.)-.1 F .365
+(From that point the k)122 228 R .365(ernel will do sensible def)-.1 F
+.366(ault actions for requests that the process doesn')-.1 F(t)-.18 E
+-.1(wa)122 240 S(nt to handle rather than sending them do).1 E
+(wn the connection.)-.25 E F1<83>114.2 258 Q F0 1.006
+(Group requests commonly issued together into one.)5 F 1.006
+(This is hard, since the main k)6.006 F 1.005(ernel tells)-.1 F 1.172
+(the \214lesystem code v)122 270 R 1.173
+(ery little about what it is doing, so it is hard to kno)-.15 F 3.673
+(ww)-.25 G 1.173(hat to do ne)-3.673 F(xt.)-.15 E(Ho)122 282 Q(we)-.25 E
+-.15(ve)-.25 G 1.609 -.4(r, t).15 H .809(here are a couple of single k)
+.4 F .808(ernel requests that are implemented in the protocol as)-.1 F
+(tw)122 294 Q 2.5(oo)-.1 G 2.5(rm)-2.5 G(ore transactions.)-2.5 E
+(This could be \214x)5 E(ed in future.)-.15 E F1<83>114.2 312 Q F0 .767
+(Data can be cached in the k)5 F 3.267(ernel. This)-.1 F .767
+(is the most trick)3.267 F 2.067 -.65(y, s)-.15 H .767(ince k).65 F .767
+(ernel caching or read-ahead)-.1 F .182
+(limits the amount of control the process can ha)122 324 R .482 -.15
+(ve ove)-.2 H 2.682(rt).15 G .182(he data once read.)-2.682 F 2.681(It)
+5.181 G .181(hink this could be)-2.681 F .488(optionally implemented, d\
+epending on whether the process says it is OK to do caching, and if)122
+336 R(so what kinds.)122 348 Q 2.067
+(Currently directory readahead is implemented with the)122 366 R/F2 10
+/Times-Bold at 0 SF(upp_multir)4.566 E(eaddir)-.18 E F0 4.566
+(operation. This)4.566 F(allo)122 378 Q 1.466
+(ws the \214lesystem process to return as man)-.25 F 3.967(yd)-.15 G
+1.467(irectory entries as it lik)-3.967 F 1.467(es, which are then)-.1 F
+(sa)122 390 Q -.15(ve)-.2 G 3.139(di).15 G 3.139(nar)-3.139 G .639
+(eadahead b)-3.139 F(uf)-.2 E(fer)-.25 E 5.638(.I)-.55 G 3.138(ft)-5.638
+G(here')-3.138 E 3.138(saf)-.55 G .638
+(uture request which can be satis\214ed by this b)-3.138 F(uf)-.2 E .638
+(fer it)-.25 F .631
+(is, rather than sending another message to the \214lesystem.)122 402 R
+.632(In 1.3.x k)5.632 F .632(ernels, userfs can transfer)-.1 F 1.526(th\
+e whole lot to the process reading the directory in one syscall \(assum\
+ing the process has)122 414 R .401(enough space allocated for it\).)122
+426 R .401
+(This is a win if there are lots of linear directory searches \(such)
+5.401 F(as shell globbing, ls or pwd\).)122 438 Q F1<83>114.2 456 Q F0
+4.051(Al)5 G(ar)-4.051 E 1.551(ger than 4k maximum pack)-.18 F 1.551
+(et size can be used, no)-.1 F 4.05(wt)-.25 G 1.55(hat the k)-4.05 F
+1.55(ernel memory allocator)-.1 F(allo)122 468 Q 2.956(ws lar)-.25 F
+2.956(ger than 4k memory allocations.)-.18 F(Ho)7.957 E(we)-.25 E -.15
+(ve)-.25 G 3.757 -.4(r, s).15 H 2.957(ince pipes are the most common).4
+F .26(connection be)122 480 R .26(ween \214lesystems and k)-.25 F .26
+(ernels, and pipes can hold at most 4k of data, there w)-.1 F(ould)-.1 E
+1.31(still be a conte)122 492 R 1.311
+(xt switch between \214lesystem code and k)-.15 F 1.311(ernel e)-.1 F
+-.15(ve)-.25 G 1.311(ry 4k, so there w).15 F(ouldn')-.1 E 3.811(tb)-.18
+G(e)-3.811 E(much g)122 504 Q(ain.)-.05 E 3.713(An)97 522 S 1.212
+(umber of people ha)-3.713 F 1.512 -.15(ve s)-.2 H 1.212
+(uggested adding shared memory between the k).15 F 1.212
+(ernel and the \214lesystem)-.1 F 2.951(process. This)97 534 R -.1(wo)
+2.951 G .451(uld be quite limiting and least lik).1 F .451
+(ely option to impro)-.1 F .751 -.15(ve t)-.15 H 2.952(hings. At).15 F
+.452(the moment, the)2.952 F .01(\214lesystem mak)97 546 R .01(es no as\
+sumptions about the nature of the \214le descriptors for talking to the\
+ process.)-.1 F -.8(To)5.01 G .028
+(implement shared memory between the k)97 558 R .029
+(ernel and the process w)-.1 F .029(ould require some w)-.1 F .029
+(ay of \214nding the)-.1 F .196
+(process on the other end of the \214le descriptors \(if an)97 570 R
+.195(y\), and playing around with memory maps.)-.15 F(This)5.195 E .359
+(still w)97 582 R(ouldn')-.1 E 2.859(tc)-.18 G .359(ut do)-2.859 F .359
+(wn on the number of conte)-.25 F .36(xt switches at all \(it may e)-.15
+F -.15(ve)-.25 G 2.86(ni).15 G .36(ncrease the number of)-2.86 F
+(switches because of syncronisation\).)97 594 Q/F3 10/Times-Italic at 0 SF
+2.5(4.2 Pr)72 612 R(otocol)-.45 E F0 .778
+(The protocol used is machine independent, using netw)72 630 R .778
+(ork byte order and de\214ned type sizes.)-.1 F .778(The code to)5.778 F
+.567(do the pack)72 642 R .568(etisation and depack)-.1 F .568
+(etisation is generated automatically by a program, gi)-.1 F -.15(ve)
+-.25 G 3.068(nt).15 G .568(he description of)-3.068 F(each pack)72 654 Q
+2.5(et. This)-.1 F(is not fully portable, b)2.5 E(ut it a)-.2 E -.2(vo)
+-.2 G(ids byte order and structure alignment problems.).2 E 3.654(Ap)72
+672 S(ack)-3.654 E 1.154(et to or from the k)-.1 F 1.154(ernel has tw)
+-.1 F 3.654(op)-.1 G 3.654(arts. The)-3.654 F 1.153
+(\214rst is a header that contains a sequence number)3.653 F 3.653(,a)
+-.4 G(n)-3.653 E .745(operation type, a pack)72 684 R .746
+(et type, size of the follo)-.1 F .746(wing data, and a protocol v)-.25
+F .746(ersion number)-.15 F 5.746(.T)-.55 G .746(he pack)-5.746 F .746
+(et type)-.1 F 1.126(can either be a request, a reply or an enquiry)72
+696 R 6.126(.R)-.65 G 1.126(equests and enquiries are al)-6.126 F -.1
+(wa)-.1 G 1.125(ys from the k).1 F 1.125(ernel to the)-.1 F .041
+(process, and the process only e)72 708 R -.15(ve)-.25 G 2.541(rs).15 G
+.041(ends replies to the k)-2.541 F 2.541(ernel. A)-.1 F(reply')2.541 E
+2.541(sh)-.55 G .041(eader has one e)-2.541 F .041
+(xtra \214eld - an error)-.15 F .764
+(\214eld, containing an error number)72 720 R 5.764(.R)-.55 G .764
+(eplies al)-5.764 F -.1(wa)-.1 G .764(ys ha).1 F 1.064 -.15(ve t)-.2 H
+.763(he same sequence number as their corresponding).15 F .486
+(request or enquiry)72 732 R 5.486(.I)-.65 G 2.987(ft)-5.486 G .487
+(here w)-2.987 F .487(as an error performing the operation the error \
+\214eld is set to the error number)-.1 F EP
+%%Page: 5 5
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman at 0 SF 2.5(-5-)279.67 48 S
+(and there is no additional data returned.)72 96 Q
+(If there is no error the error \214eld is set to 0.)5 E -.15(Fo)72 114
+S(llo).15 E 1.744(wing a request or reply pack)-.25 F 1.744
+(et is the optional operation-speci\214c data.)-.1 F 1.744
+(This is passed through the)6.744 F
+(protocol for interpretation by the operation routines at each end.)72
+126 Q 1.245(The k)72 144 R 1.245(ernel may ha)-.1 F 1.545 -.15(ve m)-.2
+H 1.245(ultiple outstanding requests.).15 F 1.245(In other w)6.245 F
+1.245(ords, the k)-.1 F 1.245(ernel may send a ne)-.1 F 3.745(wr)-.25 G
+(equest)-3.745 E 1.56(before recei)72 156 R 1.56(ving a reply to a pre)
+-.25 F 1.56(vious one.)-.25 F 1.559(This allo)6.56 F 1.559
+(ws the \214lesystem to block one process for a slo)-.25 F(w)-.25 E .718
+(operation while other processes can use the \214lesystem for shorter o\
+perations.)72 168 R .718(This impro)5.718 F -.15(ve)-.15 G 3.218(sp).15
+G(erformance)-3.218 E .839(on, for e)72 180 R .839
+(xample, an ftp \214lesystem, where one process may be using a f)-.15 F
+.839(ast local link, and another may be)-.1 F 1.28(using a slo)72 192 R
+3.78(wi)-.25 G 1.28(nternational one, and each has to w)-3.78 F 1.28
+(ait for its o)-.1 F 1.28(wn requests to be satis\214ed.)-.25 F 1.28
+(Of course this)6.28 F .163(requires the \214lesystem process to be wri\
+tten with some form of multi-threading.)72 204 R .162
+(If the \214lesystem just reads)5.162 F .613
+(requests, acts on them and replies then it can do so and ignore an)72
+216 R 3.113(yk)-.15 G .613(ernel requests until it is ready to deal)
+-3.213 F(with them.)72 228 Q/F1 10/Times-Italic at 0 SF 2.5(4.3 Handles)72
+246 R F0 .24(The base element of a \214lesystem is an)72 264 R F1(inode)
+2.74 E F0 5.24(.T).18 G .239(here is an e)-5.24 F .239
+(xact one to one relationship between inodes and)-.15 F .626
+(\214les \(where a)72 276 R F1(\214le)3.126 E F0 .626
+(in this case can be an)3.126 F 3.127<798c>-.15 G .627
+(lesystem object, lik)-3.127 F 3.127(ean)-.1 G .627
+(ormal \214le, a directory and so on\).)-3.127 F(The)5.627 E -.1(ke)72
+288 S .373(rnel needs to be able to uniquely identify inodes.).1 F .372
+(Inodes are uniquely numbered within a \214lesystem, b)5.372 F(ut)-.2 E
+.727(each mounted \214lesystem has its o)72 300 R .727(wn numbering.)
+-.25 F .728(Therefore an inode is completely identi\214ed by an inode)
+5.727 F .751(number and a \214lesystem identi\214er \(or)72 312 R F1(de)
+3.251 E(vice)-.15 E F0 3.251(,t).18 G .751(hough it doesn')-3.251 F
+3.251(tm)-.18 G .75(ean much for a \214lesystem which has no)-3.251 F
+(ph)72 324 Q(ysical hardw)-.05 E(are associated with it\).)-.1 E 3.382
+(Ad)72 342 S -.25(ev)-3.382 G .882
+(ice is what distinguishes mounted \214lesystems from one another).25 F
+3.382(,a)-.4 G .882(nd an inode is what distinguishes)-3.382 F .286
+(\214les within a \214lesystem from each other)72 354 R 5.286(.I)-.55 G
+.286(node numbers are generated by each \214lesystem, and are used by)
+-5.286 F 2.67(the k)72 366 R 2.67(ernel to refer to speci\214c \214les \
+to the \214lesystem speci\214c code.)-.1 F 2.67
+(User process \214lesystems are no)7.67 F -.15(ex)72 378 S .824
+(ception: between the k).15 F .824
+(ernel and the \214lesystem process, \214les are refered to by using)-.1
+F F1(handles)3.323 E F0 3.323(,w).27 G .823(hich are)-3.323 F 1.482
+(essentially 32 bit unsigned numbers.)72 390 R 1.482
+(When a \214lesystem \214rst mentions a \214le to the k)6.482 F 1.483
+(ernel, it gi)-.1 F -.15(ve)-.25 G 3.983(si).15 G 3.983(ta)-3.983 G .509
+(handle, which the k)72 402 R .509
+(ernel uses for all later operations on the \214le.)-.1 F .508
+(It the the handle which identi\214es the \214le,)5.508 F .144(rather t\
+han the name, so it is important to use distinct handles for distinct \
+\214les, and ne)72 414 R -.15(ve)-.25 G 2.644(rc).15 G .144
+(hange the handle)-2.644 F(of a \214le once it has been gi)72 426 Q -.15
+(ve)-.25 G 2.5(nt).15 G 2.5(ot)-2.5 G(he k)-2.5 E(ernel.)-.1 E F1 2.5
+(4.4 Random)72 444 R(oper)2.5 E(ation speci\214c advice and blurb)-.15 E
+F0 .563(This may e)72 462 R -.15(ve)-.25 G .563
+(ntually accurately describe the whole protocol, b).15 F .563(ut for no)
+-.2 F 3.063(wi)-.25 G .563(ts a list of interesting points and)-3.063 F
+(things that ha)72 474 Q .3 -.15(ve b)-.2 H(itten me.).15 E .441
+(Normally when writing a \214lesystem you should use the library)72 492
+R F1(lib)2.941 E(userfs)-.2 E F0 .441(\(see belo)2.941 F .442
+(w\), and use the advice in)-.25 F .644(this section as a guide on what\
+ kind of things should be put in your userfs operation functions, or fo\
+r idle)72 504 R(curiosity)72 516 Q(.)-.65 E F1 2.5(4.4.1 Mounting)72 534
+R F0 .138(The mount is initiated by a user process calling the mount sy\
+stem call, with the "userfs" \214lesystem type.)72 552 R(In)5.138 E .494
+(the \214lesystem speci\214c data, the process passes tw)72 564 R 2.994
+<6f8c>-.1 G .493(le descriptor numbers for the k)-2.994 F .493
+(ernel to read and write)-.1 F 3.55(to. These)72 576 R 1.05(can by an)
+3.55 F 3.55(yk)-.15 G 1.05(ind of \214le descriptor at all.)-3.55 F
+1.051(Most commonly the)6.051 F 3.551(yw)-.15 G 1.051
+(ould be pipes or sock)-3.651 F 1.051(ets, b)-.1 F(ut)-.2 E .761
+(there is no restriction.)72 588 R .761(All the k)5.761 F .76(ernel req\
+uires that the one it talks to the process with is writable, and the)-.1
+F(one it gets replies from is readable.)72 600 Q 1.236
+(The most important request is mounting.)72 618 R 1.236
+(Most important, because it is one of the tw)6.236 F 3.736(or)-.1 G
+1.236(equests that the)-3.736 F .938
+(process has to implement \(of course, not implementing an)72 630 R .938
+(ything else w)-.15 F .938(ould be completely useless\).)-.1 F(The)5.937
+E .792(request itself is not that comple)72 642 R 3.292(x. All)-.15 F
+.792(it does is return a handle of the inode at the root of the \214les\
+ystem.)3.292 F(Most commonly)72 654 Q 2.5(,t)-.65 G
+(his will be a directory)-2.5 E 5(.U)-.65 G
+(serfs does not enforce this, b)-5 E(ut the k)-.2 E(ernel itself may)-.1
+E(.)-.65 E 1.495(After the process returns the root handle, the k)72 672
+R 1.494(ernel will probe the process to see what operations it is)-.1 F
+.458(willing to support.)72 684 R .459
+(This is done by sending a series of enquire pack)5.459 F .459
+(ets to the process.)-.1 F .459(The process should)5.459 F .362
+(reply with normal reply pack)72 696 R .361(ets, with the errno \214eld\
+ either set to 0 if it is supported or ENOSYS if it isn')-.1 F(t.)-.18 E
+.351(No real operation should be done, and no additional information sh\
+ould be sent in the reply)72 708 R 5.351(.I)-.65 G 2.852(ft)-5.351 G
+.352(he process)-2.852 F .209
+(replies ENOSYS to an operation, it will ne)72 720 R -.15(ve)-.25 G
+2.709(rr).15 G(ecie)-2.709 E .508 -.15(ve i)-.25 H 2.708(ta).15 G -.05
+(ga)-2.708 G .208(in, and the k).05 F .208
+(ernel will use a sensible def)-.1 F .208(ault for)-.1 F 2.483
+(it \(typically what the k)72 732 R 2.484(ernel w)-.1 F 2.484
+(ould normally do for an in-k)-.1 F 2.484
+(ernel \214lesystem if it doesn')-.1 F 4.984(ts)-.18 G 2.484(upport the)
+-4.984 F EP
+%%Page: 6 6
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman at 0 SF 2.5(-6-)279.67 48 S 3.323(operation\). Con)72 96
+R -.15(ve)-.4 G(rsely).15 E 3.323(,i)-.65 G 3.322(ft)-3.323 G .822
+(he \214lesystem process doesn')-3.322 F 3.322(tg)-.18 G .822
+(et an enquiry about a particular operation from)-3.322 F .966(the k)72
+108 R .966(ernel, it will ne)-.1 F -.15(ve)-.25 G 3.466(rs).15 G .966
+(ee that operation from the k)-3.466 F 3.466(ernel. The)-.1 F .966
+(\214lesystem process should send 0 for the)3.466 F .239
+(operations it e)72 120 R .239(xplicitly supports, and ENOSYS for e)-.15
+F -.15(ve)-.25 G .238(rything else, so the protocol can be e).15 F .238
+(xtended without)-.15 F(ha)72 132 Q(ving to modify e)-.2 E
+(xisting clients.)-.15 E/F1 10/Times-Italic at 0 SF 2.5(4.4.2 Reading)72
+162 R(Inodes)2.5 E F0 .415
+(The most common thing for a \214lesystem to be ask)72 180 R .415
+(ed to do is to read inodes.)-.1 F -.15(Fo)5.415 G 2.915(rt).15 G .415
+(he process, this in)-2.915 F -.2(vo)-.4 G(lv).2 E(es)-.15 E .254
+(\214lling out a structure much lik)72 192 R 2.754(et)-.1 G .253(he k)
+-2.754 F(ernel')-.1 E 2.753(si)-.55 G .253
+(node structure and the stat structure.)-2.753 F(It')5.253 E 2.753(si)
+-.55 G .253(mportant is to mak)-2.753 F(e)-.1 E .963
+(sure the nlinks \214eld is non-zero.)72 204 R .963(This \214eld is the\
+ number of names the inode has, that is, the number of)5.963 F .492
+(directory entries in the \214lesystem which refer to this inode.)72 216
+R .492(In theory)5.492 F 2.991(,t)-.65 G .491(his can ne)-2.991 F -.15
+(ve)-.25 G 2.991(rb).15 G 2.991(e0w)-2.991 G .491(hen the k)-2.991 F
+(ernel)-.1 E 1.615(asks for the inode, because that means that the k)72
+228 R 1.616(ernel ask)-.1 F 1.616(ed for the inode without e)-.1 F -.15
+(ve)-.25 G 4.116(rs).15 G 1.616(eeing a name)-4.116 F .205
+(referring to it, implying that the \214lesystem ne)72 240 R -.15(ve)
+-.25 G 2.705(rt).15 G .205(old the k)-2.705 F .205
+(ernel about the \214le.)-.1 F .204(If it is 0 then the k)5.205 F .204
+(ernel will)-.1 F(ne)72 252 Q -.15(ve)-.25 G 2.5(r").15 G
+(put" the inode, and it will mak)-2.5 E 2.5(et)-.1 G
+(he \214lesystem un-umountable.)-2.5 E 1.302(When the k)72 270 R 1.302
+(ernel w)-.1 F 1.302(ants an inode from the \214lesystem, it uses the)
+-.1 F/F2 10/Times-Bold at 0 SF(upp_ir)3.803 E(ead)-.18 E F0 1.303
+(protocol request to fetch it.)3.803 F 1.118
+(This happens if something in the k)72 282 R 1.118
+(ernel asks for the inode, b)-.1 F 1.118(ut it isn')-.2 F 3.618(ta)-.18
+G 1.118(lready in the k)-3.618 F 1.117(ernel inode table.)-.1 F .466
+(Therefore, once the k)72 294 R .466(ernel has ask)-.1 F .466
+(ed the \214lesystem for an inode, it will not ask for it ag)-.1 F .467
+(ain while an)-.05 F(ything)-.15 E(in the k)72 306 Q(ernel is using it.)
+-.1 E .71(Once nothing in the k)72 324 R .71
+(ernel is using the inode, the k)-.1 F .71(ernel will issue an)-.1 F F2
+(upp_iput)3.21 E F0 .71(operation, which may be)3.21 F 1.835
+(preceded by an)72 336 R F2(upp_iwrite)4.335 E F0 1.835(if the inode w)
+4.335 F 1.835(as modi\214ed in use.)-.1 F 4.335<418c>6.835 G 1.835
+(lesystem need not implement these)-4.335 F
+(operations if there is no need to do so.)72 348 Q F1 2.5(4.4.3 Open)72
+366 R(and Close)2.5 E F0 .192
+(Reading and putting inodes are the basic operations: re)72 384 R -.05
+(ga)-.15 G .192(rdless of what an inode is being used for it will be).05
+F .185(read and put.)72 396 R(The)5.185 E F2(upp_open)2.685 E F0(and)
+2.686 E F2(upp_close)2.686 E F0 .186
+(operations speci\214cally correspond to the)2.686 F F2(open)2.686 E F0
+.186(\(2\) and)B F2(close)2.686 E F0(\(2\))A .271(system calls.)72 408 R
+.271(Normally a \214lesystem doesn')5.271 F 2.771(tn)-.18 G .271
+(eed to perform an)-2.771 F 2.771(ys)-.15 G .27
+(pecial handling for these operations, and)-2.771 F -.1(wo)72 420 S
+1.853(uld not normally implement them, e).1 F 1.853(xcept if it w)-.15 F
+1.854(ants to kno)-.1 F 4.354(wt)-.25 G 1.854
+(he identity of the process doing the)-4.354 F 3.593(operations. When)72
+432 R 3.593(ap)3.593 G 1.092(rogram issues an open system call for a \
+\214le on the user \214lesystem, the k)-3.593 F 1.092(ernel will)-.1 F
+.471(send a)72 444 R F1(upp_open)2.971 E F0 .471(operation for the \214\
+le, which includes complete identifcation for the process which issued)
+2.971 F .155(the open.)72 456 R .154
+(When the \214lesystem replies it returns a)5.155 F F1(cr)2.654 E .154
+(edentials tok)-.37 F(en.)-.1 E F0 .154
+(From then on, that credentials tok)5.154 F .154(en is)-.1 F .274(sent \
+to the \214lesystem in all operations which correspond to a system call\
+ which tak)72 468 R .275(es a \214le descriptor as an)-.1 F(ar)72 480 Q
+(gument, such as)-.18 E F2 -.18(re)2.5 G(ad).18 E F0(,)A F2(write)A F0
+(,)A F2 -.18(re)C(addir).18 E F0(,)A F2(lseek)A F0(and so on.)2.5 E
+1.403(This may seem a bit comple)72 498 R 1.403(x: wh)-.15 F 3.903(yn)
+-.05 G 1.403(ot just send the uid of the process with the operations?)
+-3.903 F -.8(We)6.402 G 1.402(ll, the).8 F .436
+(credentials of a process are quite comple)72 510 R .436(x, since the)
+-.15 F 2.936(yi)-.15 G .436(nclude the real, sa)-2.936 F -.15(ve)-.2 G
+2.936(da).15 G .436(nd ef)-2.936 F(fecti)-.25 E .736 -.15(ve u)-.25 H
+.437(ids and gids of).15 F .44
+(the process, and all the auxillary groups.)72 522 R .439
+(Sending this with each request w)5.44 F .439(ould be quite an o)-.1 F
+-.15(ve)-.15 G 2.939(rhead. The).15 F .305(idea is that all the info is\
+ sent on a open, and the \214lesystem process can associate it with a t\
+ok)72 534 R .306(en internally)-.1 F(,)-.65 E(and only use the tok)72
+546 Q(en in correspondance with the k)-.1 E(ernel.)-.1 E 1.145(Also not\
+e that the credentials are associated with an open \214le descriptor)72
+564 R 3.644(,n)-.4 G 1.144(ot the process performing the)-3.644 F 3.009
+(operation. Mostly)72 576 R 3.009(ap)3.009 G .509
+(rocess will deal with \214le descriptors it has created itself, b)
+-3.009 F .51(ut its quite possible that it)-.2 F 2.473
+(can inherit \214le descriptors from another process with a dif)72 588 R
+2.472(ferent set of credentials.)-.25 F 2.472(In this case the)7.472 F
+2.658(\214lesystem kno)72 600 R 2.658(ws the original process')-.25 F
+5.158(sc)-.55 G 2.658(redentials, b)-5.158 F 2.659
+(ut not for the process which is performing the)-.2 F(operation.)72 612
+Q F1 2.5(4.4.4 Handle)72 630 R(Mana)2.5 E -.1(ge)-.1 G(ment).1 E F0 .403
+(The handle of an inode is only w)72 648 R .403(ay the k)-.1 F .402
+(ernel and the \214lesystem can talk about a \214le.)-.1 F .402
+(An inode may ha)5.402 F -.15(ve)-.2 G .667(more than one name, or no n\
+ames at all, so \214le names are not a good w)72 660 R .667(ay of k)-.1
+F .667(eeping track of a \214le.)-.1 F(Use)5.667 E
+(inodes in your \214lesystem code to k)72 672 Q(eep track of \214les, e)
+-.1 E -.15(ve)-.25 G 2.5(ni).15 G 2.5(fy)-2.5 G(ou ha)-2.5 E .3 -.15
+(ve a s)-.2 H(imple 1:1 name to \214le mapping.).15 E 1.43
+(Handles must also be consistent.)72 690 R 1.43(Of course you must al)
+6.43 F -.1(wa)-.1 G 1.429(ys k).1 F 1.429
+(eep the handles of \214les currently in use)-.1 F .778(consistent, b)72
+702 R .779(ut you must also k)-.2 F .779
+(eep them consistent between uses.)-.1 F .779
+(If a process opens a \214le once, closes it)5.779 F .159
+(and then reopens it, then it will e)72 714 R .159(xpect it to ha)-.15 F
+.459 -.15(ve t)-.2 H .158
+(he same inode number if it is supposed to be the same \214le).15 F
+(\(which is ho)72 726 Q 2.5(wp)-.25 G
+(rocesses using a user \214lesystem will see the \214le handles\).)-2.5
+E EP
+%%Page: 7 7
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman at 0 SF 2.5(-7-)279.67 48 S .106(Also, if you e)72 96 R
+-.15(ve)-.25 G 2.606(rr).15 G .106
+(efer to a handle in communication with the k)-2.606 F .107
+(ernel, you must be prepared for the k)-.1 F .107(ernel to)-.1 F 1.668
+(ask about it.)72 108 R -.15(Fo)6.668 G 4.168(re).15 G 1.667
+(xample, if the k)-4.318 F 1.667(ernel reads a directory with the)-.1 F
+/F1 10/Times-Bold at 0 SF(upp_r)4.167 E(eaddir)-.18 E F0(or)4.167 E F1
+(upp_multir)4.167 E(eaddir)-.18 E F0 1.531
+(operations, each entry in the reply will ha)72 120 R 1.831 -.15(ve a n)
+-.2 H 1.532(ame and a handle.).15 F 1.532
+(Each of those handles must be the)6.532 F .609
+(handle of the \214le if the k)72 132 R .609
+(ernel looks at the \214le more closely)-.1 F 5.609(.I)-.65 G 3.109(fy)
+-5.609 G .609(ou mak)-3.109 F 3.109(et)-.1 G .609
+(hem all the same, for e)-3.109 F(xample,)-.15 E(then a program w)72 144
+Q(ould be entitled to belie)-.1 E .3 -.15(ve t)-.25 H
+(hat all the names in the directory refer to one actual \214le.).15 E/F2
+10/Times-Italic at 0 SF 2.5(4.4.5 Dealing)72 162 R(with muserfs)2.5 E F0
+.107(Writing a client which can be handled by muserfs is v)72 180 R .107
+(ery easy)-.15 F 5.107(.T)-.65 G .107
+(he important thing to remember is that the)-5.107 F(\214lesystem proce\
+ss can basically ignore muserfs, and ignore issues lik)72 192 Q 2.5(eh)
+-.1 G .5 -.25(ow t)-2.5 H 2.5(oq).25 G(uit and so on.)-2.5 E 3.201(Au)72
+210 S .701(serfs \214lesystem process should only terminate under one c\
+ondition: it gets an EOF \(a read of 0 bytes\))-3.201 F .912(from the k)
+72 222 R .913
+(ernel on the \214le descriptor its reading operation requests from.)-.1
+F .913(Muserfs will e)5.913 F -.15(xe)-.15 G .913(cute it so that).15 F
+1.581(most signals are ignored, so it can handle them itself.)72 234 R
+1.58(When the muserfs process is sent a SIGINT or)6.581 F .188
+(SIGTERM it unmounts the \214lesystem mount point with the)72 246 R F1
+(umount)2.688 E F0 .188(\(8\) command \(used so that /etc/mtab is)B
+1.106(updated properly\).)72 258 R 1.106(This causes the k)6.106 F 1.106
+(ernel to send the \214lesystem process a)-.1 F F1(upp_umount)3.605 E F0
+3.605(operation. The)3.605 F -.1(ke)72 270 S .513(rnel will close its e\
+nd of the \214le descriptors, and the process is e).1 F .513
+(xpected to do the same, e)-.15 F -.15(ve)-.25 G 3.013(ni).15 G 3.013
+(fo)-3.013 G .513(nly by)-3.013 F -.15(ex)72 282 S 3.06
+(iting. Therefore,).15 F .559(when trying to unmount a userfs \214lesys\
+tem, do not kill the \214lesystem process directly)3.06 F(,)-.65 E
+(and do not kill muserfs with SIGKILL.)72 294 Q(Either w)5 E
+(ay you should be able to unmount with)-.1 E F1(umount)2.5 E F0
+(as root.)2.5 E F2 2.5(5. Using)72 318 R(lib)2.5 E(userfs)-.2 E(lib)72
+336 Q(userfs)-.2 E F0 .495(is a C++ library designed to mak)2.995 F
+2.995(ew)-.1 G .496(riting \214lesystem clients easier)-2.995 F 5.496
+(.I)-.55 G 2.996(ti)-5.496 G 2.996(sd)-2.996 G .496
+(esigned so all the w)-2.996 F(ork)-.1 E 1.215
+(common to almost all \214lesystems is encapsulated into a fe)72 348 R
+3.715(wg)-.25 G 1.214(eneric classes, which can be used as base)-3.715 F
+(classes for speci\214c \214lesystem functions.)72 360 Q F2 2.5
+(5.1 Basic)72 378 R(Classes)2.5 E F0 .232(The most basic classes,)72 396
+R F1(Comm)2.733 E F0(,)A F1(Filesystem)2.733 E F0(and)2.733 E F1(Inode)
+2.733 E F0 .233(implement the basic communication with the k)2.733 F
+(ernel)-.1 E(and stub methods for each operation.)72 408 Q 1.018
+(The Comm class reads from the k)72 426 R 1.018
+(ernel and decodes the headers of the operation pack)-.1 F 1.017
+(ets, and passes the)-.1 F .346(remainder to the Filesystem class.)72
+438 R .347
+(The Filesystem performs the operation and returns an unencoded return)
+5.346 F(header and the encoded body of the reply)72 450 Q 2.5(,i)-.65 G
+2.5(fa)-2.5 G -.15(ny)-2.5 G 5(.A)-.5 G(ll this is not e)-5 E
+(xposed to the code using the library)-.15 E(.)-.65 E 1.068
+(Filesystem tak)72 468 R 1.067
+(es each operation and dispatches it to the appropriate place.)-.1 F
+1.067(The Filesystem class directly)6.067 F 1.367(handles the operation\
+s which are global to the whole \214lesystem, such as mounting or unmou\
+nting.)72 480 R -.15(Fo)6.368 G(r).15 E 2.035(operation which pertain t\
+o a particular Inode \(such as reading, or looking up a name in a direc\
+tory\),)72 492 R(Filesystem looks up the Inode in its table and dispatc\
+hes the operation to it.)72 504 Q .136
+(The Inode class has all its methods implemented as stubs which f)72 522
+R .137(ail with the "not implemented" error code.)-.1 F .196(It also ha\
+s members for the standard inode properties of mode, type, size, o)72
+534 R .196(wnership, links, timestamps and)-.25 F(so on.)72 546 Q .863
+(These classes are completely useless on their o)72 564 R .863
+(wn, so the)-.25 F 3.363(ym)-.15 G .864
+(ust be used as base classes for other classes)-3.363 F
+(with actually do something.)72 576 Q F2(lib)5 E(userfs)-.2 E F0
+(has more speci\214c, b)2.5 E(ut still generally useful classes.)-.2 E
+F1(SimpleInode)72 594 Q F0 1.7
+(implements a simple inode with some normally e)4.2 F 1.7(xpected beha)
+-.15 F(viour)-.2 E 6.7(.I)-.55 G 4.2(th)-6.7 G 1.7(as a constructor)-4.2
+F .428(which initializes the inode properties to sensible v)72 606 R
+.429(alues, and methods which implement simple def)-.25 F .429
+(aults for)-.1 F(the open, close and permissions check operations.)72
+618 Q F1(DirInode,)72 636 Q F0(deri)4.773 E -.15(ve)-.25 G 4.773(df).15
+G 2.272
+(rom SimpleInode, implements all the operations needed for a directory)
+-4.773 F 4.772(,i)-.65 G(ncluding)-4.772 E .097(linking and unlinking i\
+nodes to/from names, rename, and directory scanning and lookup.)72 648 R
+.098(It tak)5.098 F .098(es v)-.1 F .098(ery little)-.15 F -.15(ex)72
+660 S(tra code to implemement simple directory beha).15 E(viour)-.2 E(.)
+-.55 E F2 2.5(5.2 Writing)72 678 R(your own \214lesystem classes)2.5 E
+F0 3.199(Ac)72 696 S .699(omplete \214lesystem has tw)-3.199 F 3.199(op)
+-.1 G .699(arts: a collection of inodes, one for each \214le, and the \
+\214lesystem structure)-3.199 F .23
+(itself, which holds all the inodes together)72 708 R 5.23(.E)-.55 G
+.231(ach inode represents a \214le in the \214lesystem, re)-5.23 F -.05
+(ga)-.15 G .231(rdless of type.).05 F 1.215
+(There is only one inode per \214le in the \214lesystem, e)72 720 R -.15
+(ve)-.25 G 3.715(ni).15 G 3.715(ft)-3.715 G 1.215
+(he \214le appears multiple times under dif)-3.715 F(ferent)-.25 E
+(names.)72 732 Q EP
+%%Page: 8 8
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman at 0 SF 2.5(-8-)279.67 48 S/F1 10/Times-Italic at 0 SF 2.5
+(5.2.1 Ar)72 96 R(guments and r)-.37 E(eturn values of oper)-.37 E
+(ation methods)-.15 E F0 .118(Each method with the name)72 114 R/F2 10
+/Times-Bold at 0 SF(do_something)2.618 E F0 .118
+(in the Filesystem and Inode classes corresponds to an operation)2.618 F
+.378(in the userfs protocol.)72 126 R .378(As a result, the)5.378 F
+2.878(ya)-.15 G .378(ll ha)-2.878 F .678 -.15(ve s)-.2 H .378(imilar ar)
+.15 F .377(gument structures.)-.18 F .377(All such methods ha)5.377 F
+-.15(ve)-.2 G F2(const)3.027 E(up_pr)72 138 Q 1.358(eamble &pr)-.18 F(e)
+-.18 E F0(and)3.858 E F2(upp_r)3.858 E 1.358(epl &r)-.18 F(epl)-.18 E F0
+1.359(which are references to the operation reqest and reply pack)3.858
+F(et)-.1 E 2.688(headers. Mostly)72 150 R .188(there is no reason for o\
+peration methods to use them, because their contents are dealt with)
+2.688 F(in lo)72 162 Q(wer le)-.25 E -.15(ve)-.25 G(ls of the library)
+.15 E 2.5(,b)-.65 G(ut the)-2.7 E 2.5(ya)-.15 G(re there if you w)-2.5 E
+(ant them.)-.1 E .395(Each userfs protocol operation may ha)72 180 R
+.695 -.15(ve a)-.2 H -.18(rg).15 G .395(uments, return v).18 F .395
+(alues, both or neither)-.25 F 2.895(,a)-.4 G .395
+(nd the method for that)-2.895 F 1.4(operation will ha)72 192 R 1.7 -.15
+(ve c)-.2 H 1.4(orresponding ar).15 F 3.899(guments. F)-.18 F 1.399
+(or an operation named)-.15 F F1(x)3.899 E F0 1.399(the method ar)3.899
+F 1.399(gument with the)-.18 F .783(operation ar)72 204 R .783
+(guments will ha)-.18 F 1.083 -.15(ve t)-.2 H .783(he type).15 F F2 .783
+(const upp_)3.283 F F1(x)A F2(_s)A F0 3.283(,a)C .783(nd the return v)
+-3.283 F .783(alues ar)-.25 F .783(gument will ha)-.18 F 1.084 -.15
+(ve t)-.2 H .784(he type).15 F F2(upp_)72 216 Q F1(x)A F2(_r)A F0 2.5
+(,F)C(or e)-2.65 E
+(xample, the up_read operation will correspond to the Inode method)-.15
+E/F3 9/Courier at 0 SF
+(int Inode::do_read\(const up_preamble &pre, upp_repl &repl,)97 233 Q
+(const upp_read_s &args, upp_read_r &ret\);)199.6 244 Q F0 1.201(The co\
+ntents of the structures, along with encoding and decoding functions, a\
+re machine generated, and)72 262 R 3.27(therefore ha)72 274 R 3.57 -.15
+(ve a c)-.2 H 3.27(onsistent set of rules.).15 F 3.271
+(Mostly its quite simple, with normal base types directly)8.271 F .707
+(corresponding to C and C++ types.)72 286 R(Ho)5.707 E(we)-.25 E -.15
+(ve)-.25 G 1.507 -.4(r, v).15 H .707(ariable sized types need to ha).15
+F 1.006 -.15(ve b)-.2 H .706(oth a pointer to the data).15 F .413
+(and the size of the data encoded into them.)72 298 R .414
+(Memory for the data is allocated with the C++ ne)5.413 F 2.914(wa)-.25
+G .414(nd delete)-2.914 F 1.552(operators, with the)72 310 R F2(alloc)
+4.052 E F0 1.551(method of a v)4.052 F 1.551(ariable sized object.)-.25
+F 1.551(The memory is automatically freed by the)6.551 F(method')72 322
+Q 2.557(sc)-.55 G(aller)-2.557 E 5.057(.F)-.55 G .057(or e)-5.207 F .057
+(xample, if a return v)-.15 F .057
+(alue of a method contains an member called)-.25 F F2(name)2.557 E F0
+.058(representing a)2.557 F(\214lename, it w)72 334 Q
+(ould be set with the follo)-.1 E(wing sequence \(assuming)-.25 E F2
+(our)2.5 E(name)-.15 E F0(is a normal 0 terminated string\):)2.5 E F3
+(int namelen = strlen\(ourname\);)97 351 Q 97.2
+(ret.name.alloc\(namelen\); //)97 362 R(Allocate memory)5.4 E
+(ret.name.nelem = namelen;)97 373 Q(// Set name length)97.2 E
+(memcpy\(&ret.name.elems, ourname, namelen\); // Set name contents)97
+384 Q(// ...)97 395 Q F0(\(alternati)72 413 Q -.15(ve)-.25 G(ly).15 E
+3.694(,y)-.65 G 1.194(ou could just point)-3.694 F F1 -.37(re)3.694 G
+(t.name).37 E(.elems)-.15 E F0 1.194(directly at)3.694 F F1(ourname)
+3.694 E F0 3.694(,b).18 G 1.194(ecause it w)-3.694 F(on')-.1 E 3.694(tt)
+-.18 G 1.194(ry and free the)-3.694 F(string if it w)72 425 Q(as ne)-.1
+E -.15(ve)-.25 G 2.5(ra).15 G(llocated\).)-2.5 E 1.837
+(Note that strings are ne)72 443 R -.15(ve)-.25 G 4.337(rz).15 G 1.838
+(ero terminated; the length of the returned string is e)-4.337 F 1.838
+(xactly the number of)-.15 F(characters in the string.)72 455 Q 2.065
+(If the operation the method is performing f)72 473 R 2.065
+(ails, it should return the appropriate error code, or 0 if it)-.1 F
+2.772(succeeds. Don')72 485 R 2.773(tr)-.18 G .273
+(eturn -1 unless you mean to \255 it has special meaning \(see belo)
+-2.773 F 1.573 -.65(w, i)-.25 H 2.773(n").65 G .273
+(Deferring Replies"\).)-2.773 F F1 2.5(5.2.2 Deriving)72 503 R(fr)2.5 E
+(om F)-.45 E(ilesystem)-.45 E F0
+(Filesystem class must implement a number of methods to mak)72 521 Q 2.5
+(et)-.1 G(he \214lesystem viable:)-2.5 E F1(Enquir)72 539 Q(e)-.37 E F0
+1.962(is called when the k)2.5 F 1.962(ernel w)-.1 F 1.961
+(ants to \214nd what operations your \214lesystem supports.)-.1 F -.15
+(Fo)6.961 G 4.461(ra).15 G 1.961(ll the)-4.461 F(operations that an)97
+551 Q 2.5(yi)-.15 G
+(node will implement, return 0 and return ENOSYS for the rest.)-2.5 E F1
+(do_mount)72 569 Q F0(tak)2.5 E 1.134(es no ar)-.1 F 1.135(guments and \
+returns the handle for the inode for the root directory \(that is, the \
+top)-.18 F(directory of your \214lesystem\).)97 581 Q(The k)5 E
+(ernel immediately does a)-.1 E F2(do_ir)2.5 E(ead)-.18 E F0
+(operation using this handle.)2.5 E -1.1(Yo)72 593 S 3.196(uc)1.1 G .696
+(an also implement)-3.196 F F1(do_statfs)3.196 E F0 .696(which allo)
+3.196 F .696(ws the k)-.25 F .696
+(ernel to get space and inode usage statistics, such as)-.1 F 2.278
+(when "df" is e)72 605 R -.15(xe)-.15 G 2.278(cuted, and).15 F F1
+(do_umount)4.778 E F0 2.278
+(so the \214lesystem is formally informed when it is unmounted)4.778 F
+(\(normally it just gets an EOF from the k)72 617 Q
+(ernel, and Comm::Run returns\).)-.1 E F1 2.5(5.2.3 Deriving)72 635 R
+(fr)2.5 E(om Inode)-.45 E F0 .086(Most of the w)72 653 R .086
+(ork of the \214lesystem is done in the inodes.)-.1 F .085
+(All inode classes must be deri)5.085 F -.15(ve)-.25 G 2.585(df).15 G
+.085(rom Inode, and)-2.585 F(generally there will be a number of dif)72
+665 Q(ferent Inode based classes.)-.25 E 1.134(It is probably better to\
+ use SimpleInode as a base rather than plain Inode, because it implemen\
+ts simple)72 683 R(def)72 695 Q 1.547(aults for some methods, which w)
+-.1 F 1.547(ould otherwise f)-.1 F 4.047(ail. If)-.1 F 1.547
+(Filesystem::Enquire says that the \214lesystem)4.047 F
+(supports a particular operation, then an)72 707 Q 2.5(yi)-.15 G
+(node should be prepared to get that operation from the k)-2.5 E(ernel.)
+-.1 E(Similarly)72 725 Q 2.5(,u)-.65 G
+(nless you are doing something special, deri)-2.5 E
+(ving directories from DirInode sa)-.25 E -.15(ve)-.2 G 2.5(sal).15 G
+(ot of w)-2.5 E(ork.)-.1 E(Only)72 743 Q F1(do_ir)3.19 E(ead)-.37 E F0
+.69(need be implemented, b)3.19 F .691(ut ob)-.2 F .691
+(viously the \214lesystem will do nothing interesting unless other)-.15
+F EP
+%%Page: 9 9
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman at 0 SF 2.5(-9-)279.67 48 S .452
+(operations are implemented.)72 96 R .452
+(do_iread returns the details of the inode.)5.452 F .452
+(Note that the Filesystem class calls)5.452 F .074
+(the do_iread of the Inode when the operation comes from the k)72 108 R
+.074(ernel, so the inode must e)-.1 F .074(xist by the time the)-.15 F
+-.1(ke)72 120 S 1.358(rnel asks for it.).1 F 1.357
+(The constructor for Inode automatically re)6.358 F 1.357
+(gisters the inode in the Filesystem')-.15 F 3.857(si)-.55 G(node)-3.857
+E(table; con)72 132 Q -.15(ve)-.4 G(rsely).15 E 2.5(,t)-.65 G
+(he destructor remo)-2.5 E -.15(ve)-.15 G 2.5(si).15 G(t.)-2.5 E 2.521(\
+Here are some other useful methods for an Inode; the descriptions are b\
+rief and general, and don')72 150 R(t)-.18 E
+(necessarily refer to all the ar)72 162 Q(guments and return v)-.18 E
+(alues, which means the)-.25 E 2.5(yc)-.15 G(an be ignored.)-2.5 E/F1 10
+/Times-Italic at 0 SF(do_iwrite)72 180 Q F0(is, ob)2.5 E(viously)-.15 E 2.5
+(,t)-.65 G(he opposite of do_iread.)-2.5 E(It simply sets the v)5 E
+(arious Inode v)-.25 E(alues.)-.25 E F1(do_iput)72 198 Q F0 1.078
+(is called when the k)2.5 F 1.078(ernel is no longer using the inode.)
+-.1 F 1.077(That is, the inode is no longer open, the)6.077 F .21
+(current or root directory of a process, being e)97 210 R -.15(xe)-.15 G
+.21(cuted from or being mapped from.).15 F .21(If an inode is iput)5.21
+F(and has no names \(has no name to inode mapping in an)97 222 Q 2.5(yd)
+-.15 G(irectory\) it can be destro)-2.5 E(yed.)-.1 E F1(do_r)72 240 Q
+(ead)-.37 E F0(allo)2.5 E .472(ws data to be read from the \214le.)-.25
+F .472(The ar)5.472 F .472(guments are the of)-.18 F .471
+(fset in the \214le to start reading from,)-.25 F 1.295
+(and the number of bytes desiried.)97 252 R 1.295
+(The method may return as man)6.295 F 3.795(yb)-.15 G 1.295
+(ytes up to that number as it)-3.795 F(lik)97 264 Q
+(es, including 0, which means EOF)-.1 E(.)-.8 E F1(do_write)72 282 Q F0
+.049(does the con)2.5 F -.15(ve)-.4 G .049
+(rse; a block of data and an of).15 F .049
+(fset is passed in, and the method returns the number of)-.25 F
+(bytes actually written.)97 294 Q F1(do_lookup)72 312 Q F0 .882
+(translates a name into an inode reference.)2.5 F .882
+(This is typically implemented for directories; if the)5.882 F(name e)97
+324 Q(xists in the directory the method should return the handle of the\
+ inode, or f)-.15 E(ail with ENOENT)-.1 E(.)-.74 E F1(do_dirr)72 342 Q
+(ead)-.37 E F0 .765(returns the ne)2.5 F .765
+(xt directory entry at the passed of)-.15 F 3.265(fset. It)-.25 F .764
+(returns the name and inode of the ne)3.265 F(xt)-.15 E .043
+(\214le in the directory)97 354 R 2.543(,a)-.65 G .043
+(nd the size of the entry returned. This is added by the k)-2.543 F .043
+(ernel to the current of)-.1 F(fset)-.25 E 1.041
+(in the directory to form the of)97 366 R 1.041(fset of the ne)-.25 F
+1.041(xt directory entry for the ne)-.15 F 1.041(xt call.)-.15 F 1.041
+(Since the directory)6.041 F 1.26(entries don')97 378 R 3.76(tc)-.18 G
+1.26(orrespond to real \214le storage as in other)-3.76 F 3.76(,m)-.4 G
+1.26(ore con)-3.76 F -.15(ve)-.4 G 1.26
+(ntional \214lesystems, a directory).15 F(entry can be re)97 390 Q -.05
+(ga)-.15 G(rded as ha).05 E(ving an of)-.2 E(fset of 1.)-.25 E
+(If the end of the directory has been reached, it should return a ne)97
+408 Q 2.5(wo)-.25 G -.25(ff)-2.5 G(set of 0.).25 E F1(do_multir)72 426 Q
+(eaddir)-.37 E F0 .606(is similar to do_readdir)2.5 F 3.106(,b)-.4 G
+.606(ut can return an)-3.306 F 3.106(yn)-.15 G .605
+(umber of directory entries, which are cached)-3.106 F .495
+(in a readahead b)97 438 R(uf)-.2 E .495(fer in the k)-.25 F 2.995
+(ernel. If)-.1 F 2.995(ap)2.995 G .495
+(rogram asks for a directory entry for an inode which has a)-2.995 F
+2.46(cached directory entry then the entry will come from within the k)
+97 450 R 2.46(ernel rather than asking the)-.1 F .578
+(\214lesystem process.)97 462 R .579
+(This operation can return only one entry \(and so is lik)5.578 F 3.079
+(ed)-.1 G .579(o_readdir\), or as man)-3.079 F(y)-.15 E .91
+(as will \214t in a return pack)97 474 R .91
+(et \(up to 4k or so of entries\).)-.1 F .909
+(Returning no entries means the end of the)5.909 F .361
+(directory has been reached.)97 486 R .362
+(Returning multiple entries impro)5.361 F -.15(ve)-.15 G 2.862(st).15 G
+.362(he performance of directory scans,)-2.862 F
+(most frequently done by ls, pwd and shell globbing.)97 498 Q .064(Look\
+ at the implementation of DirInode::do_multireaddir for details of ho)97
+516 R 2.563(wt)-.25 G .063(his should be dealt with.)-2.563 F F1(do_cr)
+72 534 Q(eate)-.37 E F0 1.01
+(does all \214le creation, whether it be a normal \214le, a directory)
+2.5 F 3.51(,a\214)-.65 G 1.01(fo \214le or a de)-3.51 F 1.01(vice node.)
+-.25 F(The)6.01 E(mode contains the type of the \214le in same w)97 546
+Q(ay as the stat structure member)-.1 E/F2 10/Times-Bold at 0 SF(st_mode.)
+2.5 E F1(do_unlink)72 564 Q F0 2.682
+(is the opposite, and is used for unlinking \(remo)2.5 F 2.682
+(ving a name to inode mapping\) \214les and)-.15 F 3.092
+(directories. If)97 576 R .592
+(an inode is not in use and has no links then it can be destro)3.092 F
+.593(yed and its handle can be)-.1 F(reused.)97 588 Q F1(do_symlink)72
+606 Q F0(is used to create ne)2.5 E 2.5(ws)-.25 G(ymlink inodes.)-2.5 E
+(It returns the handle of the ne)5 E 2.5(wi)-.25 G(node.)-2.5 E F1(do_r)
+72 624 Q(eadlink)-.37 E F0
+(returns the pathname which a symbolic link is pointing to.)2.5 E F1
+(do_followlink)72 642 Q F0 .443(returns the pathname of the \214le a sy\
+mbolic link is really referring to.)2.5 F .442(If Filesystem::Enquire)
+5.442 F(says the \214lesystem does not support this operation, the read\
+link operation is used instead.)97 654 Q F1(do_open)72 672 Q F0 .34
+(is called when a \214le is actually opened.)2.5 F .341
+(It is only necessary to implement this if it is important to)5.34 F
+(kno)97 684 Q 4.045(ww)-.25 G 1.545
+(hether a \214le is being opened as opposed to being used in an)-4.045 F
+4.044(yo)-.15 G 1.544(ther w)-4.044 F(ay)-.1 E 6.544(.T)-.65 G 1.544
+(his operation)-6.544 F .96(passes the \214lesystem the complete authen\
+tication credentials of the process doing the open, so that)97 696 R
+.048(the \214lesystem can do e)97 708 R .048
+(xtended security checking or change the beha)-.15 F .047
+(viour of the \214le depending on the)-.2 F(user)97 720 Q(.)-.55 E .061
+(This method can return a credential tok)97 738 R .062
+(en, which is a magic number used by the \214lesystem process to)-.1 F
+EP
+%%Page: 10 10
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman at 0 SF 2.5(-1)277.17 48 S 2.5(0-)-2.5 G .321
+(refer to the set of credentials passed by the k)97 96 R 2.821
+(ernel. The)-.1 F -.1(ke)2.821 G .321
+(rnel attaches this credentials tok).1 F .321(en to each)-.1 F .233(eac\
+h operation generated by system calls on the \214le descriptor generate\
+d by the open \(read\(\), write\(\),)97 108 R .47
+(readdir\(\) and close\(\)\).)97 120 R .47(The credentials tok)5.47 F
+.469(en is part of the \214le descriptor)-.1 F 2.969(,s)-.4 G 2.969(oi)
+-2.969 G 2.969(si)-2.969 G .469(nhereited unchanged)-2.969 F
+(if the descriptor is passed to another process, e)97 132 Q -.15(ve)-.25
+G 2.5(ni).15 G 2.5(fi)-2.5 G 2.5(th)-2.5 G(as dif)-2.5 E
+(ferent credentials.)-.25 E .111(When a \214le is opened, a ne)97 150 R
+2.611<778c>-.25 G .111(le table entry for the inode is created.)-2.611 F
+.111(That \214le table entry has a single)5.111 F .037
+(\214le descriptor referring to it.)97 162 R .036(More \214le descripto\
+rs can be made to refer to the \214le table entry with the)5.037 F/F1 10
+/Times-Bold at 0 SF(dup)97 174 Q F0(\(2\) system call, and can be remo)A
+-.15(ve)-.15 G 2.5(dw).15 G(ith)-2.5 E F1(close)2.5 E F0(\(2\).)A/F2 10
+/Times-Italic at 0 SF(do_close)72 192 Q F0 .293(is called when the last \
+\214le descriptor for a \214le table entry is closed.)2.5 F .293
+(The only ar)5.293 F .294(gument for this is)-.18 F(the credentials tok)
+97 204 Q(en for that \214le table entry)-.1 E 2.5(,s)-.65 G 2.5(ot)-2.5
+G(hat the \214lesystem can free all references to it.)-2.5 E F2
+(do_permission)72 222 Q F0 .445
+(is called when the \214lesystem says it w)2.5 F .445
+(ants to do permissions checking.)-.1 F .445(This is called a lot,)5.445
+F 2.026(and can cause man)97 234 R 4.526(ym)-.15 G 2.026
+(ore operations to pass between the k)-4.526 F 2.026
+(ernel and \214lesystem process.)-.1 F 2.026(If the)7.026 F(\214lesyste\
+m does not implement it the normal unix user/group/others checking is p\
+erformed.)97 246 Q F2(do_r)72 264 Q(ename)-.37 E F0(mo)2.5 E -.15(ve)
+-.15 G 2.5(sa\214).15 G(le from one directory to a ne)-2.5 E 2.5(wo)-.25
+G(ne \(though it may be the same\).)-2.5 E F2 2.5(5.2.4 Deriving)72 282
+R(fr)2.5 E(om DirInode)-.45 E F0 1.152(DirInode implements a number of \
+userfs operation methods for directories, such as readdir)72 300 R 3.652
+(,m)-.4 G(ultireaddir)-3.652 E .252(and lookup.)72 312 R .252
+(It also automatically constructs directories with "." and "..")5.252 F
+.252(entries pointing to the appropriate)5.252 F(places.)72 324 Q .108
+(DirInode deals with strings a lot, and rather than using the normal)72
+342 R F1 .107(char *)2.607 F F0 .107(it uses the libg++)2.607 F F1
+(String)2.607 E F0 .107(class for)2.607 F(all string ar)72 354 Q
+(guments to its o)-.18 E(wn methods \(b)-.25 E
+(ut not, of course, for the userfs protocol operation methods\).)-.2 E
+1.631(DirInode e)72 372 R 1.631
+(xpects a pointer to the parent directory)-.15 F 4.132(,w)-.65 G 1.632
+(hich is also a class deri)-4.132 F -.15(ve)-.25 G 4.132(df).15 G 1.632
+(rom DirInode.)-4.132 F 1.632(If the)6.632 F .418
+(directory is at the top of the \214lesystem')72 384 R 2.917(st)-.55 G
+.417(ree, it should be a NULL pointer)-2.917 F 5.417(.T)-.55 G .417
+(he protected member)-5.417 F F1(par)2.917 E(ent)-.18 E F0
+(points the the parent inode, or)72 396 Q F1(this)2.5 E F0
+(for the top one.)2.5 E(It should ne)5 E -.15(ve)-.25 G 2.5(rb).15 G 2.5
+(eN)-2.5 G(ULL.)-2.5 E .897(DirInode k)72 414 R .897
+(eeps a list of \214les in the directory)-.1 F 3.397(,b)-.65 G .898
+(ut does not allo)-3.597 F 3.398(wt)-.25 G .898
+(hat list to be directly visible.)-3.398 F .898(The only)5.898 F
+(operations for manipulating the directory contents for a deri)72 426 Q
+-.15(ve)-.25 G 2.5(dc).15 G(lass are:)-2.5 E F1
+(int link\(const String name, Inode *\))72 444 Q F0 .344
+(which links a ne)2.5 F 2.844(wn)-.25 G .344(ame into the directory)
+-2.844 F 2.843(,u)-.65 G .343(pdating all the reference)-2.843 F
+(and link counts;)97 456 Q F1(int unlink\(const String name\))72 474 Q
+F0(which does the opposite;)2.5 E F1
+(DirEntry *lookup\(const String name\))72 492 Q F0 3.165
+(which returns a directory entry if it \214nds the \214le, or NULL)2.5 F
+(otherwise; and)97 504 Q F1(DirEntry *scan\(DirEntry * &pos\))72 522 Q
+F0 .727(which returns the directory entry at)2.5 F F2(pos,)3.227 E F0
+.726(updating it in the process, or)3.227 F
+(NULL if there are no more entries.)97 534 Q F1
+(DirEntry *scan\(int &pos\))72 552 Q F0(is the same, e)2.5 E
+(xcept it uses an inte)-.15 E(ger of)-.15 E(fset, which is less ef)-.25
+E(\214cient.)-.25 E F2 2.5(5.3 Communications)72 570 R(classes)2.5 E F0
+.299(There are a number of communications classes in the library)72 588
+R 2.799(,w)-.65 G .3(hich pro)-2.799 F .3(vide dif)-.15 F .3(ferent w)
+-.25 F .3(ays of multiple)-.1 F(xing)-.15 E(replies.)72 600 Q .396
+(The most simple is the Comm class, which simply tak)72 618 R .395
+(es each request, passes it to the \214lesystem and sends)-.1 F
+(back the reply)72 630 Q 5(.T)-.65 G(here are more comple)-5 E 2.5(xc)
+-.15 G(omms classes though.)-2.5 E F2 2.5(5.3.1 F)72 648 R
+(ile Descriptor Dispatc)-.45 E(her)-.15 E F0(The)72 666 Q F1(CommBase)
+3.546 E F0 1.046(class \(base of all comms classes\) pro)3.546 F 1.046
+(vides a dispatcher which allo)-.15 F 1.046(ws classes to re)-.25 F
+(gister)-.15 E .575(interest in acti)72 678 R .575
+(vity on \214le descriptors.)-.25 F .575
+(This is used internally to get input from the k)5.575 F .574(ernel, b)
+-.1 F .574(ut can be used)-.2 F .07(by a \214lesystem to monitor an)72
+690 R 2.57<798c>-.15 G .07(le descriptor for an)-2.57 F 2.57(yr)-.15 G
+2.57(eason. T)-2.57 F 2.57(od)-.8 G 2.57(oi)-2.57 G .07(t, simply deri)
+-2.57 F .37 -.15(ve a d)-.25 H .07(ispatcher class from).15 F F1
+(DispatchFD)72 702 Q F0 .942(and call)3.442 F F1 .942
+(struct disp_fd CommBase::addDispatch\(int fd, DispatchFD *, int what\))
+3.442 F F0 3.441(,w)C(here)-3.441 E 1.894(what can be one or more of)72
+714 R F2(DISP_R)4.394 E F0(,).27 E F2(DISP_W)4.974 E F0(or)5.624 E F2
+(DISP_E)4.974 E F0 4.395(,f).73 G 1.895(or interest in read ready)-4.395
+F 4.395(,w)-.65 G 1.895(rite ready or)-4.395 F -.15(ex)72 726 S 3.678
+(ceptions. When).15 F 1.178(an e)3.678 F -.15(ve)-.25 G 1.178
+(nt occurs, the).15 F F1 1.178(DispatchFD::dispatch\(int fd, int what\))
+3.678 F F0 1.178(method is called of the)3.678 F(re)72 738 Q .159
+(gistered class.)-.15 F .159(If it returns 0 then it is remo)5.159 F
+-.15(ve)-.15 G 2.659(df).15 G .16(rom the dispatch list.)-2.659 F .16
+(If it returns -1 it indicates an error;)5.16 F EP
+%%Page: 11 11
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman at 0 SF 2.5(-1)277.17 48 S 2.5(1-)-2.5 G(it is remo)72
+96 Q -.15(ve)-.15 G(d, and).15 E/F1 10/Times-Bold at 0 SF
+(CommBase::Run\(\))2.5 E F0 2.5(returns. Returning)2.5 F 2.5(1i)2.5 G
+2.5(san)-2.5 G(ormal return.)-2.5 E F1(CommBase::Run\(\))72 114 Q F0
+(returns normally when there are no more entries on the dispatch list.)
+2.5 E/F2 10/Times-Italic at 0 SF 2.5(5.3.2 Deferring)72 132 R(Replies)2.5 E
+F0 .792(In normal operation, the \214lesystem processes one request at \
+a time, so each operation is replied to before)72 150 R .81(the ne)72
+162 R .81(xt is look)-.15 F .81(ed at.)-.1 F .81(This is a con)5.81 F
+-.15(ve)-.4 G .81(ntion of the w).15 F .811(ay the user code w)-.1 F
+.811(orks, and not something the k)-.1 F(ernel)-.1 E 3.218(enforces. It)
+72 174 R .718(just sends requsts as processes using the \214lesystem ne\
+ed them, and the)3.218 F 3.217(yb)-.15 G .717(lock until the reply)
+-3.217 F .056(for their particular request is replied to.)72 186 R .056
+(Therefore, it is possible for multiple processes to use the \214lesyst\
+em)5.056 F(at once.)72 198 Q(The)72 216 Q F1(DeferComm)3.31 E F0(and)
+3.31 E F1(DeferFilesys)3.31 E F0 .81(classes ha)3.31 F 1.11 -.15(ve a m)
+-.2 H .81(ethod called).15 F F1(DeferReply)3.31 E F0 .81
+(\(the DeferFilesys once just)3.31 F 1.606
+(calls the DeferComm one to mak)72 228 R 4.107(ei)-.1 G 4.107(ta)-4.107
+G 1.607(ccessable to things within the \214lesystem\).)-4.107 F 1.607
+(DeferReply forks the)6.607 F .931(\214lesystem; on the child side it r\
+eturns 0 and in the parent it returns the pid of the child.)72 240 R .93
+(If the operation)5.93 F .805(method returns -1 then the Filesystem jus\
+t goes on to processing the ne)72 252 R .806(xt request from the k)-.15
+F 3.306(ernel. When)-.1 F 2.104(the child is ready to reply)72 264 R
+4.604(,i)-.65 G 4.604(tc)-4.604 G 2.104(an just return in the normal w)
+-4.604 F(ay)-.1 E 7.103(.T)-.65 G 2.103
+(he call to DeferReply sets up the)-7.103 F .321(DeferComm class in the\
+ child process to reply though the parent rather than going straight to\
+ the k)72 276 R .321(ernel, in)-.1 F .224(order to mak)72 288 R 2.724
+(es)-.1 G .224(ure the replies from multiple processes don')-2.724 F
+2.723(tg)-.18 G .223(et jumbled up.)-2.723 F .223
+(When the reply has been sent)5.223 F(back, the child process just e)72
+300 Q(xits.)-.15 E .39
+(Because the child is really a child process, you ha)72 318 R .691 -.15
+(ve t)-.2 H 2.891(od).15 G 2.891(oa)-2.891 G .391
+(ll the changes in \214lesystem state before calling)-2.891 F
+(DeferReply)72 330 Q 2.5(,o)-.65 G 2.5(ra)-2.5 G
+(rrange for some other mechanism for the parent and children to talk.)
+-2.5 E F2 2.5(5.3.3 Multi-thr)72 348 R(eaded \214lesystems)-.37 E F0
+(The)72 366 Q F1(Thr)3.35 E(eadComm)-.18 E F0 .85(class creates a ne)
+3.35 F 3.35(wl)-.25 G .85
+(ightweight thread for each request, using the Re)-3.35 F 3.35(xl)-.15 G
+.85(wp library \(in)-3.45 F 1.48(the l)72 378 R 1.48(wp directory\).)-.1
+F 1.48(This allo)6.48 F 1.481(ws multiple requests to be handled within\
+ the one process, so long as one)-.25 F .856
+(thread does not block the whole process in a system call.)72 390 R .856
+(The \214le descriptor dispatcher in CommBase is)5.856 F(useful for pre)
+72 402 Q -.15(ve)-.25 G(nting this: see).15 E F1(ftpfs)2.5 E F0
+(for a complete e)2.5 E(xample of a multithreaded \214lesystem.)-.15 E
+EP
+%%Trailer
+end
+%%EOF
More information about the Userfs-commits
mailing list