diff -urN linux-2.4.30-pre2/Documentation/Configure.help linux-2.4.30-pre2-evfs/Documentation/Configure.help
--- linux-2.4.30-pre2/Documentation/Configure.help	Mon Jan 31 22:01:10 2005
+++ linux-2.4.30-pre2-evfs/Documentation/Configure.help	Sun Mar  6 15:07:05 2005
@@ -16592,6 +16592,22 @@
   partition (the one containing the directory /) cannot be compiled as
   a module.
 
+Encrypted Virtual File System (EXPERIMENTAL)
+CONFIG_EVFS_FS
+  EVFS is virtual filesystem hack which can provide run-time encryption
+  over any existing directory in per-user basis. It encrypts filenames,
+  file contents and symlink values. It doesn't requiere real block device,
+  it's file access is based on top of vfs (i.e. accessing mount source by
+  vfs) and is not currently considered to be SMP safe. You'll need special
+  utility 'efs' which can mount encrypted directories.
+  
+  The cipher used is Rijndael (AES) in with 256 bit key (which is made from
+  sha256-ed user-supplied password while mount), the cipherblocks is
+  128bit in CBC mode for each 4k page. Look into evfs_core.c and aes.c
+  for more details how is encryption done.
+  
+  For more information and user 'efs' wrapper look at http://hysteria.sk/evfs
+
 Reiserfs support
 CONFIG_REISERFS_FS
   Stores not just filenames but the files themselves in a balanced
diff -urN linux-2.4.30-pre2/fs/Config.in linux-2.4.30-pre2-evfs/fs/Config.in
--- linux-2.4.30-pre2/fs/Config.in	Sun Sep 12 18:31:01 2004
+++ linux-2.4.30-pre2-evfs/fs/Config.in	Sun Mar  6 15:07:05 2005
@@ -7,6 +7,8 @@
 bool 'Quota support' CONFIG_QUOTA
 dep_tristate '  VFS v0 quota format support' CONFIG_QFMT_V2 $CONFIG_QUOTA
 
+tristate 'Virtual Encrypted File System' CONFIG_EVFS_FS
+
 tristate 'Kernel automounter support' CONFIG_AUTOFS_FS
 tristate 'Kernel automounter version 4 support (also supports v3)' CONFIG_AUTOFS4_FS
 
diff -urN linux-2.4.30-pre2/fs/Makefile linux-2.4.30-pre2-evfs/fs/Makefile
--- linux-2.4.30-pre2/fs/Makefile	Fri Feb 20 07:38:31 2004
+++ linux-2.4.30-pre2-evfs/fs/Makefile	Sun Mar  6 15:07:05 2005
@@ -7,7 +7,8 @@
 
 O_TARGET := fs.o
 
-export-objs :=	filesystems.o open.o dcache.o buffer.o dquot.o exec.o quota.o
+export-objs :=	filesystems.o open.o dcache.o buffer.o dquot.o exec.o quota.o \
+		read_write.o
 mod-subdirs :=	nls
 
 obj-y :=	open.o read_write.o devices.o file_table.o buffer.o \
@@ -66,6 +66,7 @@
 subdir-$(CONFIG_SUN_OPENPROMFS)	+= openpromfs
 subdir-$(CONFIG_BEFS_FS)	+= befs
 subdir-$(CONFIG_JFS_FS)		+= jfs
+subdir-$(CONFIG_EVFS_FS)	+= evfs
 subdir-$(CONFIG_XFS_FS)		+= xfs
 
 obj-$(CONFIG_BINFMT_AOUT)	+= binfmt_aout.o
diff -urN linux-2.4.30-pre2/fs/evfs/Makefile linux-2.4.30-pre2-evfs/fs/evfs/Makefile
--- linux-2.4.30-pre2/fs/evfs/Makefile	Thu Jan  1 01:00:00 1970
+++ linux-2.4.30-pre2-evfs/fs/evfs/Makefile	Sun Mar  6 15:07:05 2005
@@ -0,0 +1,6 @@
+O_TARGET := evfs.o
+
+obj-y    := aes.o sha256.o evfs_core.o base64.o
+obj-m    := $(O_TARGET)
+
+include $(TOPDIR)/Rules.make
diff -urN linux-2.4.30-pre2/fs/evfs/aes.c linux-2.4.30-pre2-evfs/fs/evfs/aes.c
--- linux-2.4.30-pre2/fs/evfs/aes.c	Thu Jan  1 01:00:00 1970
+++ linux-2.4.30-pre2-evfs/fs/evfs/aes.c	Sun Mar  6 15:07:05 2005
@@ -0,0 +1,324 @@
+/*
+ * The most believed to be secure cipher today ... ripped from kernel 2.5.66
+ *
+ * Copyright (c) 2002, Dr Brian Gladman <brg@gladman.me.uk>, Worcester, UK.
+ * All rights reserved.
+ *
+ * LICENSE TERMS
+ *
+ * The free distribution and use of this software in both source and binary
+ * form is allowed (with or without changes) provided that:
+ *
+ *   1. distributions of this source code include the above copyright
+ *      notice, this list of conditions and the following disclaimer;
+ *
+ *   2. distributions in binary form include the above copyright
+ *      notice, this list of conditions and the following disclaimer
+ *      in the documentation and/or other associated materials;
+ *
+ *   3. the copyright holder's name is not used to endorse products
+ *      built using this software without specific written permission.
+ *
+ * ALTERNATIVELY, provided that this notice is retained in full, this product
+ * may be distributed under the terms of the GNU General Public License (GPL),
+ * in which case the provisions of the GPL apply INSTEAD OF those given above.
+ *
+ * DISCLAIMER
+ *
+ * This software is provided 'as is' with no explicit or implied warranties
+ * in respect of its properties, including, but not limited to, correctness
+ * and/or fitness for purpose.
+ * ---------------------------------------------------------------------------
+ */
+
+#include "aes.h"
+#include <linux/string.h>
+
+static u8 pow_tab[256];
+static u8 log_tab[256];
+static u8 sbx_tab[256];
+static u8 isb_tab[256];
+static u32 rco_tab[10];
+static u32 ft_tab[4][256];
+static u32 it_tab[4][256];
+
+static u32 fl_tab[4][256];
+static u32 il_tab[4][256];
+
+static inline u8
+f_mult (u8 a, u8 b)
+{
+	u8 aa = log_tab[a], cc = aa + log_tab[b];
+
+	return pow_tab[cc + (cc < aa ? 1 : 0)];
+}
+
+
+void gen_tabs (void)
+{
+	u32 i, t;
+	u8 p, q;
+
+	/* log and power tables for GF(2**8) finite field with
+	   0x011b as modular polynomial - the simplest prmitive
+	   root is 0x03, used here to generate the tables */
+
+	for (i = 0, p = 1; i < 256; ++i) {
+		pow_tab[i] = (u8) p;
+		log_tab[p] = (u8) i;
+
+		p ^= (p << 1) ^ (p & 0x80 ? 0x01b : 0);
+	}
+
+	log_tab[1] = 0;
+
+	for (i = 0, p = 1; i < 10; ++i) {
+		rco_tab[i] = p;
+
+		p = (p << 1) ^ (p & 0x80 ? 0x01b : 0);
+	}
+
+	for (i = 0; i < 256; ++i) {
+		p = (i ? pow_tab[255 - log_tab[i]] : 0);
+		q = ((p >> 7) | (p << 1)) ^ ((p >> 6) | (p << 2));
+		p ^= 0x63 ^ q ^ ((q >> 6) | (q << 2));
+		sbx_tab[i] = p;
+		isb_tab[p] = (u8) i;
+	}
+
+	for (i = 0; i < 256; ++i) {
+		p = sbx_tab[i];
+
+		t = p;
+		fl_tab[0][i] = t;
+		fl_tab[1][i] = rotl (t, 8);
+		fl_tab[2][i] = rotl (t, 16);
+		fl_tab[3][i] = rotl (t, 24);
+
+		t = ((u32) ff_mult (2, p)) |
+		    ((u32) p << 8) |
+		    ((u32) p << 16) | ((u32) ff_mult (3, p) << 24);
+
+		ft_tab[0][i] = t;
+		ft_tab[1][i] = rotl (t, 8);
+		ft_tab[2][i] = rotl (t, 16);
+		ft_tab[3][i] = rotl (t, 24);
+
+		p = isb_tab[i];
+
+		t = p;
+		il_tab[0][i] = t;
+		il_tab[1][i] = rotl (t, 8);
+		il_tab[2][i] = rotl (t, 16);
+		il_tab[3][i] = rotl (t, 24);
+
+		t = ((u32) ff_mult (14, p)) |
+		    ((u32) ff_mult (9, p) << 8) |
+		    ((u32) ff_mult (13, p) << 16) |
+		    ((u32) ff_mult (11, p) << 24);
+
+		it_tab[0][i] = t;
+		it_tab[1][i] = rotl (t, 8);
+		it_tab[2][i] = rotl (t, 16);
+		it_tab[3][i] = rotl (t, 24);
+	}
+}
+
+#define star_x(x) (((x) & 0x7f7f7f7f) << 1) ^ ((((x) & 0x80808080) >> 7) * 0x1b)
+
+#define imix_col(y,x)       \
+    u   = star_x(x);        \
+    v   = star_x(u);        \
+    w   = star_x(v);        \
+    t   = w ^ (x);          \
+   (y)  = u ^ v ^ w;        \
+   (y) ^= rotr(u ^ t,  8) ^ \
+          rotr(v ^ t, 16) ^ \
+          rotr(t,24)
+
+/* initialise the key schedule from the user supplied key */
+
+#define loop4(i)                                    \
+{   t = rotr(t,  8); t = ls_box(t) ^ rco_tab[i];    \
+    t ^= E_KEY[4 * i];     E_KEY[4 * i + 4] = t;    \
+    t ^= E_KEY[4 * i + 1]; E_KEY[4 * i + 5] = t;    \
+    t ^= E_KEY[4 * i + 2]; E_KEY[4 * i + 6] = t;    \
+    t ^= E_KEY[4 * i + 3]; E_KEY[4 * i + 7] = t;    \
+}
+
+#define loop6(i)                                    \
+{   t = rotr(t,  8); t = ls_box(t) ^ rco_tab[i];    \
+    t ^= E_KEY[6 * i];     E_KEY[6 * i + 6] = t;    \
+    t ^= E_KEY[6 * i + 1]; E_KEY[6 * i + 7] = t;    \
+    t ^= E_KEY[6 * i + 2]; E_KEY[6 * i + 8] = t;    \
+    t ^= E_KEY[6 * i + 3]; E_KEY[6 * i + 9] = t;    \
+    t ^= E_KEY[6 * i + 4]; E_KEY[6 * i + 10] = t;   \
+    t ^= E_KEY[6 * i + 5]; E_KEY[6 * i + 11] = t;   \
+}
+
+#define loop8(i)                                    \
+{   t = rotr(t,  8); ; t = ls_box(t) ^ rco_tab[i];  \
+    t ^= E_KEY[8 * i];     E_KEY[8 * i + 8] = t;    \
+    t ^= E_KEY[8 * i + 1]; E_KEY[8 * i + 9] = t;    \
+    t ^= E_KEY[8 * i + 2]; E_KEY[8 * i + 10] = t;   \
+    t ^= E_KEY[8 * i + 3]; E_KEY[8 * i + 11] = t;   \
+    t  = E_KEY[8 * i + 4] ^ ls_box(t);    \
+    E_KEY[8 * i + 12] = t;                \
+    t ^= E_KEY[8 * i + 5]; E_KEY[8 * i + 13] = t;   \
+    t ^= E_KEY[8 * i + 6]; E_KEY[8 * i + 14] = t;   \
+    t ^= E_KEY[8 * i + 7]; E_KEY[8 * i + 15] = t;   \
+}
+
+int aes_set_key(void *ctx_arg, const u8 *in_key)
+{
+	struct aes_ctx *ctx = ctx_arg;
+	u32 i, t, u, v, w;
+
+	E_KEY[0] = u32_in (in_key);
+	E_KEY[1] = u32_in (in_key + 4);
+	E_KEY[2] = u32_in (in_key + 8);
+	E_KEY[3] = u32_in (in_key + 12);
+
+	E_KEY[4] = u32_in (in_key + 16);
+	E_KEY[5] = u32_in (in_key + 20);
+	E_KEY[6] = u32_in (in_key + 24);
+	t = E_KEY[7] = u32_in (in_key + 28);
+	for (i = 0; i < 7; ++i)
+		loop8 (i);
+
+	D_KEY[0] = E_KEY[0];
+	D_KEY[1] = E_KEY[1];
+	D_KEY[2] = E_KEY[2];
+	D_KEY[3] = E_KEY[3];
+
+	for (i = 4; i < 32 + 24; ++i) {
+		imix_col (D_KEY[i], E_KEY[i]);
+	}
+
+	return 0;
+}
+
+/* encrypt a block of text */
+
+#define f_nround(bo, bi, k) \
+    f_rn(bo, bi, 0, k);     \
+    f_rn(bo, bi, 1, k);     \
+    f_rn(bo, bi, 2, k);     \
+    f_rn(bo, bi, 3, k);     \
+    k += 4
+
+#define f_lround(bo, bi, k) \
+    f_rl(bo, bi, 0, k);     \
+    f_rl(bo, bi, 1, k);     \
+    f_rl(bo, bi, 2, k);     \
+    f_rl(bo, bi, 3, k)
+
+void aes_encrypt(void *ctx_arg, u8 *out, const u8 *in, u8 *salt)
+{
+	const struct aes_ctx *ctx = ctx_arg;
+	u32 b0[4], b1[4];
+	const u32 *kp = E_KEY + 4;
+
+	b0[0] = u32_in(salt) ^ u32_in (in) ^ E_KEY[0];
+	b0[1] = u32_in(salt + 4) ^ u32_in (in + 4) ^ E_KEY[1];
+	b0[2] = u32_in(salt + 8) ^ u32_in (in + 8) ^ E_KEY[2];
+	b0[3] = u32_in(salt + 12) ^ u32_in (in + 12) ^ E_KEY[3];
+
+	f_nround (b1, b0, kp);
+	f_nround (b0, b1, kp);
+	f_nround (b1, b0, kp);
+	f_nround (b0, b1, kp);
+	f_nround (b1, b0, kp);
+	f_nround (b0, b1, kp);
+	f_nround (b1, b0, kp);
+	f_nround (b0, b1, kp);
+	f_nround (b1, b0, kp);
+	f_nround (b0, b1, kp);
+	f_nround (b1, b0, kp);
+	f_nround (b0, b1, kp);
+	f_nround (b1, b0, kp);
+	f_lround (b0, b1, kp);
+
+	u32_out (out, b0[0]);
+	u32_out (out + 4, b0[1]);
+	u32_out (out + 8, b0[2]);
+	u32_out (out + 12, b0[3]);
+
+	u32_out (salt, b0[0]);
+	u32_out (salt + 4, b0[1]);
+	u32_out (salt + 8, b0[2]);
+	u32_out (salt + 12, b0[3]);
+}
+
+/* decrypt a block of text */
+
+#define i_nround(bo, bi, k) \
+    i_rn(bo, bi, 0, k);     \
+    i_rn(bo, bi, 1, k);     \
+    i_rn(bo, bi, 2, k);     \
+    i_rn(bo, bi, 3, k);     \
+    k -= 4
+
+#define i_lround(bo, bi, k) \
+    i_rl(bo, bi, 0, k);     \
+    i_rl(bo, bi, 1, k);     \
+    i_rl(bo, bi, 2, k);     \
+    i_rl(bo, bi, 3, k)
+
+void aes_decrypt(void *ctx_arg, u8 *out, const u8 *in, u8 *salt)
+{
+	const struct aes_ctx *ctx = ctx_arg;
+	u32 b0[4], b1[4], ss[4];
+	const u32 *kp = D_KEY + 32 + 20;
+	
+	memcpy(ss, in, sizeof(ss));
+
+	b0[0] = (u32_in (in)) ^ E_KEY[32 + 24];
+	b0[1] = (u32_in (in + 4)) ^ E_KEY[32 + 25];
+	b0[2] = (u32_in (in + 8)) ^ E_KEY[32 + 26];
+	b0[3] = (u32_in (in + 12)) ^ E_KEY[32 + 27];
+
+	i_nround (b1, b0, kp);
+	i_nround (b0, b1, kp);
+	i_nround (b1, b0, kp);
+	i_nround (b0, b1, kp);
+	i_nround (b1, b0, kp);
+	i_nround (b0, b1, kp);
+	i_nround (b1, b0, kp);
+	i_nround (b0, b1, kp);
+	i_nround (b1, b0, kp);
+	i_nround (b0, b1, kp);
+	i_nround (b1, b0, kp);
+	i_nround (b0, b1, kp);
+	i_nround (b1, b0, kp);
+	i_lround (b0, b1, kp);
+
+	u32_out (out, b0[0] ^ u32_in(salt));
+	u32_out (out + 4, b0[1] ^ u32_in(salt + 4));
+	u32_out (out + 8, b0[2] ^ u32_in(salt + 8));
+	u32_out (out + 12, b0[3] ^ u32_in(salt + 12));
+	
+	memcpy(salt, ss, sizeof(ss));
+}
+
+#define AES_BLOCK_SIZE		16
+
+void	aes_encrypt_str(void *ctx_arg, u8 *out, const u8 *in, int len, u8 *salt)
+{
+	register	int	i, l = len / AES_BLOCK_SIZE;
+	register	const	u8 *p = in;
+	register	u8 *op = out;
+	
+	for (i = 0; i < l; i++, p+=AES_BLOCK_SIZE,op+=AES_BLOCK_SIZE)
+		aes_encrypt(ctx_arg, op, p, salt);
+}
+
+void	aes_decrypt_str(void *ctx_arg, u8 *out, const u8 *in, int len, u8 *salt)
+{
+	register	int	i, l = len / AES_BLOCK_SIZE;
+	register	const	u8 *p = in;
+	register	u8 *op = out;
+
+	for (i = 0; i < l; i++, p+=AES_BLOCK_SIZE,op+=AES_BLOCK_SIZE)
+		aes_decrypt(ctx_arg, op, p, salt);
+}
diff -urN linux-2.4.30-pre2/fs/evfs/aes.h linux-2.4.30-pre2-evfs/fs/evfs/aes.h
--- linux-2.4.30-pre2/fs/evfs/aes.h	Thu Jan  1 01:00:00 1970
+++ linux-2.4.30-pre2-evfs/fs/evfs/aes.h	Sun Mar  6 15:07:05 2005
@@ -0,0 +1,96 @@
+#ifndef AES_H
+#define AES_H
+
+#ifndef __KERNEL__
+#define __KERNEL__
+#endif
+#include <asm/types.h>
+#include <linux/byteorder/little_endian.h>
+
+#define AES_MIN_KEY_SIZE	16
+#define AES_MAX_KEY_SIZE	32
+
+#define AES_BLOCK_SIZE		16
+
+struct aes_ctx {
+	u32 E[60];
+	u32 D[60];
+};
+
+static inline 
+u32 generic_rotr32 (const u32 x, const unsigned bits)
+{
+	const unsigned n = bits % 32;
+	return (x >> n) | (x << (32 - n));
+}
+
+static inline 
+u32 generic_rotl32 (const u32 x, const unsigned bits)
+{
+	const unsigned n = bits % 32;
+	return (x << n) | (x >> (32 - n));
+}
+
+#define rotl generic_rotl32
+#define rotr generic_rotr32
+
+/*
+ * #define byte(x, nr) ((unsigned char)((x) >> (nr*8))) 
+ */
+inline static u8
+byte(const u32 x, const unsigned n)
+{
+	return x >> (n << 3);
+}
+
+#define u32_in(x) le32_to_cpu(*(const u32 *)(x))
+#define u32_out(to, from) (*(u32 *)(to) = cpu_to_le32(from))
+
+#define E_KEY ctx->E
+#define D_KEY ctx->D
+
+
+#define ff_mult(a,b)    (a && b ? f_mult(a, b) : 0)
+
+#define f_rn(bo, bi, n, k)					\
+    bo[n] =  ft_tab[0][byte(bi[n],0)] ^				\
+             ft_tab[1][byte(bi[(n + 1) & 3],1)] ^		\
+             ft_tab[2][byte(bi[(n + 2) & 3],2)] ^		\
+             ft_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n)
+
+#define i_rn(bo, bi, n, k)					\
+    bo[n] =  it_tab[0][byte(bi[n],0)] ^				\
+             it_tab[1][byte(bi[(n + 3) & 3],1)] ^		\
+             it_tab[2][byte(bi[(n + 2) & 3],2)] ^		\
+             it_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n)
+
+#define ls_box(x)				\
+    ( fl_tab[0][byte(x, 0)] ^			\
+      fl_tab[1][byte(x, 1)] ^			\
+      fl_tab[2][byte(x, 2)] ^			\
+      fl_tab[3][byte(x, 3)] )
+
+#define f_rl(bo, bi, n, k)					\
+    bo[n] =  fl_tab[0][byte(bi[n],0)] ^				\
+             fl_tab[1][byte(bi[(n + 1) & 3],1)] ^		\
+             fl_tab[2][byte(bi[(n + 2) & 3],2)] ^		\
+             fl_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n)
+
+#define i_rl(bo, bi, n, k)					\
+    bo[n] =  il_tab[0][byte(bi[n],0)] ^				\
+             il_tab[1][byte(bi[(n + 3) & 3],1)] ^		\
+             il_tab[2][byte(bi[(n + 2) & 3],2)] ^		\
+             il_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n)
+
+
+
+extern	void gen_tabs (void);
+extern	int aes_set_key(void *ctx_arg, const u8 *in_key);
+extern	void aes_encrypt(void *ctx_arg, u8 *out, const u8 *in, u8 *salt);
+extern	void aes_decrypt(void *ctx_arg, u8 *out, const u8 *in, u8 *salt);
+extern	void aes_encrypt_str(void *ctx_arg, u8 *out, const u8 *in, int len, u8 *salt);
+extern	void aes_decrypt_str(void *ctx_arg, u8 *out, const u8 *in, int len, u8 *salt);
+
+
+
+#endif
diff -urN linux-2.4.30-pre2/fs/evfs/base64.c linux-2.4.30-pre2-evfs/fs/evfs/base64.c
--- linux-2.4.30-pre2/fs/evfs/base64.c	Thu Jan  1 01:00:00 1970
+++ linux-2.4.30-pre2-evfs/fs/evfs/base64.c	Sun Mar  6 15:07:05 2005
@@ -0,0 +1,83 @@
+/*
+ * $Id: base64.c, base64 codec for filenames
+ */
+
+#include "base64.h"
+
+/* bin => b64 table */
+static	char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";
+/* b64 => bin table */
+static	int tab64[256] = {
+	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x00,0x00,
+	0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x00,0x00,
+	0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,
+	0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,
+	0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x00,0x00,0x00,0x00,0x3e,
+	0x00,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,
+	0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,
+	0x31,0x32,0x33 };
+
+
+/* encode binary string to base64 */
+int	base64_encode(const unsigned char *data, unsigned char *out, int len)
+{
+	register int	i, j, a1 = 0, k;
+	for (i = 0, j = 0, k = 0; i < len; i++) {
+		switch (k) {
+
+			case 0:
+				a1 = b64[(data[i] & 0x3f)];
+				break;
+			case 1:
+				out[j++] = a1;
+				out[j++] = b64[(data[i-1] >> 6) | ((data[i] & 0xf) << 2)];
+				break;
+			case 2:
+				out[j++] = b64[(data[i-1] >> 4 | ((data[i] & 0x3) << 4))];
+				out[j++] = b64[(data[i] >> 2)];
+				k = 0;
+				continue;
+				
+		}
+		k++;
+
+	}
+	if (k == 1) {
+		out[j++] = a1;
+		out[j++] = b64[(data[i-1] >> 6)];
+	}
+	if (k == 2) {
+		out[j++] = b64[(data[i-1] >> 4)];
+	}
+	return j;
+}
+
+int	base64_decode(const unsigned char *data, unsigned char *out, int len)
+{
+	register	int i, j;
+	for (i = j = 0; i < len; i++) {
+		register int val = (int) tab64[(int)data[i]];
+		switch (i & 3) {
+			case 0:
+				out[j++] = val;
+				break;
+			case 1:
+				out[j-1] |= (val & 3) << 6;
+				out[j++] = (val >> 2);
+				break;
+			case 2:
+				out[j-1] |= (val & 0xf) << 4;
+				out[j++] = (val >> 4);
+				break;
+			case 3:
+				out[j-1] |= val << 2;
+				break;
+		}
+	}
+	return j;
+}
+
+
diff -urN linux-2.4.30-pre2/fs/evfs/base64.h linux-2.4.30-pre2-evfs/fs/evfs/base64.h
--- linux-2.4.30-pre2/fs/evfs/base64.h	Thu Jan  1 01:00:00 1970
+++ linux-2.4.30-pre2-evfs/fs/evfs/base64.h	Sun Mar  6 15:07:05 2005
@@ -0,0 +1,15 @@
+/*
+ * $Id: base64.c, base64 codec for filenames
+ */
+
+#ifndef BASE64_H
+#define BASE64_H
+
+/* approximate lengths you'll get after conversions */
+#define norm2baselen(x) (((x)*8+5)/6)
+#define base2normlen(x) ((x)*6/8)
+
+extern	int	base64_encode(const unsigned char *data,unsigned  char *out, int len);
+extern	int	base64_decode(const unsigned char *data,unsigned  char *out, int len);
+
+#endif
diff -urN linux-2.4.30-pre2/fs/evfs/evfs.h linux-2.4.30-pre2-evfs/fs/evfs/evfs.h
--- linux-2.4.30-pre2/fs/evfs/evfs.h	Thu Jan  1 01:00:00 1970
+++ linux-2.4.30-pre2-evfs/fs/evfs/evfs.h	Sun Mar  6 15:07:05 2005
@@ -0,0 +1,7 @@
+#ifndef EVFS_H
+#define EVFS_H
+
+#define EVFS_MAGIC 0xdefaced0
+#define EVFS_COOKIE ".evfs"
+
+#endif
diff -urN linux-2.4.30-pre2/fs/evfs/evfs_core.c linux-2.4.30-pre2-evfs/fs/evfs/evfs_core.c
--- linux-2.4.30-pre2/fs/evfs/evfs_core.c	Thu Jan  1 01:00:00 1970
+++ linux-2.4.30-pre2-evfs/fs/evfs/evfs_core.c	Sun Mar  6 15:09:27 2005
@@ -0,0 +1,1202 @@
+/* evfs 0.3 2003 sd */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/romfs_fs.h>
+#include <linux/fs.h>
+#include <linux/locks.h>
+#include <linux/init.h>
+#include <linux/smp_lock.h>
+#include <asm/uaccess.h>
+#include <linux/file.h>
+#include <linux/unistd.h>
+#include <linux/dnotify.h>
+
+#include "evfs.h"
+#include "aes.h"
+#include "sha256.h"
+#include "base64.h"
+
+/* those is considered to be the fastest */
+#define EVFS_BLK_SIZE	PAGE_CACHE_SIZE
+#define	EVFS_BLK_BITS	12
+/* padlen, all of it's bits must be *always* 1 in line, f.e. : 1,3,7,15,31 ... */
+#define	PADLEN		(AES_BLOCK_SIZE-1)
+#define KBUFSZ		(PADLEN+PAGE_CACHE_SIZE)
+#define SALTLEN		16
+
+//#define track() printk("track: " __func__ "()/%d reached\n", __LINE__)
+#define track()
+
+
+extern long sys_readlink(const char * path, char * buf, int bufsiz);
+extern long sys_link(const char * oldname, const char * newname);
+extern long sys_unlink(const char * pathname);
+extern long sys_symlink(const char * oldname, const char * newname);
+extern long sys_mkdir(const char * pathname, int mode);
+extern long sys_rmdir(const char * pathname);
+extern long sys_mknod(const char * filename, int mode, dev_t dev);
+extern long sys_rename(const char * oldname, const char * newname);
+
+
+struct	evfs_ctx  {
+	struct	aes_ctx aes;	/* master aes key */
+	/* we've 256 salts by 16 bytes, after 1mb it will repeat
+	  - give chance to compress really big files ;)) */
+	/* (256*PAGE_CACHE_SIZE) */
+	char	salts[256][SALTLEN];
+	int	recursion;
+};
+
+
+static struct super_operations evfs_sbops;
+static	struct	inode_operations evfs_file_iops;
+static	struct	inode_operations evfs_dir_iops;
+static	struct	file_operations evfs_fops;
+static struct file_operations evfs_dir_fops;
+static struct address_space_operations evfs_aops;
+static struct address_space_operations evfs_link_aops;
+static struct dentry_operations evfs_dentry_ops;
+
+/**************************************************************************
+ General purpose functions
+ **************************************************************************/
+
+#define get_mem() kmalloc(PAGE_CACHE_SIZE + 1024, GFP_KERNEL)
+#define put_mem(x) kfree(x)
+#define COPY_INODE(i,g) \
+	i->i_size = S_ISREG(g->i_mode)?((g->i_size > PADLEN)?g->i_size - PADLEN:0):(S_ISLNK(g->i_mode)?0:g->i_size); \
+	i->i_ino = g->i_ino; \
+	i->i_mode = g->i_mode; \
+	i->i_nlink = g->i_nlink; \
+	i->i_uid = g->i_uid; \
+	i->i_gid = g->i_gid; \
+	i->i_rdev = g->i_rdev; \
+	i->i_atime = g->i_atime; \
+	i->i_mtime = g->i_mtime; \
+	i->i_ctime = g->i_ctime; \
+	i->i_blkbits = EVFS_BLK_BITS; \
+	i->i_blksize = EVFS_BLK_SIZE; \
+	i->i_blocks = (g->i_blocks * (1 << g->i_blkbits)) / EVFS_BLK_SIZE;
+
+
+struct	evfs_inode {
+	char	*host_filename;
+	char	*sym;
+	struct	file *fd;
+};
+#define evfs_i(x) (*((struct evfs_inode *) &(x)->u.generic_ip))
+#define file_evfs_i(file) (&evfs_i((file)->f_dentry->d_inode))
+#define evfs_key(x) ((struct evfs_ctx *) (x)->u.generic_sbp)
+#define gk(i) (evfs_key((i->i_sb)))
+
+static	int my_truncate(struct dentry *dentry, loff_t length)
+{
+	struct inode *inode = dentry->d_inode;
+	int error;
+	struct iattr newattrs;
+
+	down(&inode->i_sem);
+	newattrs.ia_size = length;
+	newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
+	error = notify_change(dentry, &newattrs);
+	up(&inode->i_sem);
+	return error;
+}
+
+static	inline char *get_salt(struct evfs_ctx *ctx, u8 index, char *buf)
+{
+	if (!ctx)
+		memset(buf, 0, SALTLEN);
+	else
+		memcpy(buf, &ctx->salts[index][0], SALTLEN);
+	return buf;  
+}
+
+static	inline	char *kstrdup(char *s)
+{
+	char	*p = kmalloc(strlen(s) + 1, GFP_KERNEL);
+	if (!p)
+		return NULL;
+	strcpy(p, s);
+	return p;
+}
+
+static	inline	int hpath_lookup_dir(char *name, struct nameidata *nd, int flags)
+{
+	int error = 0;
+	track();
+	if (path_init(name, LOOKUP_POSITIVE|LOOKUP_DIRECTORY|flags, nd))
+		error = path_walk(name, nd);
+	track();
+	return error;
+}
+
+
+static	inline	int hpath_lookup(char *name, struct nameidata *nd)
+{
+	int error = 0;
+	track();
+	if (path_init(name, LOOKUP_POSITIVE, nd))
+		error = path_walk(name, nd);
+	track();
+	return error;
+}
+
+static	int	read_name(struct inode *ino, char *name)
+{
+	struct	nameidata nd;
+	int	error = hpath_lookup(name, &nd);
+	track();
+	if (error) return error;
+	if (!nd.dentry->d_inode) {
+		path_release(&nd);
+		return -ENOENT;
+	}
+	COPY_INODE(ino, nd.dentry->d_inode);
+	path_release(&nd);
+	return error;
+}
+
+static	int	file_type(char *name, int *rdev)
+{
+	struct	nameidata nd;
+	int	error = hpath_lookup(name, &nd);
+	track();
+	if (!error) {
+		if (nd.dentry->d_inode) {
+			error = nd.dentry->d_inode->i_mode;
+			if (rdev)
+				*rdev = nd.dentry->d_inode->i_rdev;
+		} else {
+			error = -1024;
+		}
+		path_release(&nd);
+	}
+	return error;
+}
+
+
+
+/* translate our virtual path (discovered by traversing
+   dcache tree) to real encrypted names path */
+static char *dentry_name(struct dentry *dentry, int extra, struct super_block *sb)
+{
+	struct	dentry *parent;
+	char	*name, *root;
+	int	len, rootlen;
+	char	tmp[NAME_MAX + 1];
+
+	track();
+/*	if ((dentry->d_name.len == sizeof(EVFS_COOKIE)-1) &&
+	    (!memcmp(dentry->d_name.name, EVFS_COOKIE, sizeof(EVFS_COOKIE)-1)))
+		return NULL; */
+	len = 0;
+	for (parent = dentry; parent->d_parent != parent; parent = parent->d_parent)
+		len += norm2baselen((parent->d_name.len + PADLEN) & ~PADLEN) + 1; /* +1 for '/' */
+
+	track();
+	root = evfs_i(parent->d_inode).host_filename;
+	rootlen = strlen(root);
+	len += rootlen;
+	track();
+	name = kmalloc(len + extra + 1, GFP_KERNEL);
+	if (!name)
+		return NULL;
+	track();
+	memcpy(name, root, rootlen);
+	name[len] = 0;
+
+	/* count length of whole tree (only approx!) */
+	track();
+	for (parent = dentry; parent->d_parent != parent; parent  = parent->d_parent) {
+		int	alen = (parent->d_name.len + PADLEN) & ~PADLEN;
+		int	elen = norm2baselen(alen);
+		char	salt[SALTLEN];
+
+		track();
+		len -= elen + 1;
+		name[len] = '/';
+		memset(tmp, 0, alen);
+		memcpy(tmp, parent->d_name.name, parent->d_name.len);
+		track();
+		if (!sb) sb = dentry->d_inode->i_sb;
+		aes_encrypt_str(&evfs_key(sb)->aes, tmp, tmp, alen, get_salt(NULL, 0, salt));
+		track();
+		base64_encode(tmp, name + len + 1, alen);
+	}
+	return name;
+}
+
+static char *inode_name(struct inode *ino, int extra)
+{
+	struct dentry *dentry;
+
+	track();
+	dentry = list_entry(ino->i_dentry.next, struct dentry, d_alias);
+	return(dentry_name(dentry, extra, ino->i_sb));
+}
+
+static struct inode *get_inode(struct super_block *sb, struct dentry *dentry,
+			       int *error)
+{
+	struct inode *inode;
+	char *name;
+	int type, err = -ENOMEM, rdev;
+
+	track();
+	inode = get_empty_inode();
+	if(inode == NULL) 
+		goto out;
+
+	evfs_i(inode).host_filename = NULL;
+	evfs_i(inode).fd = NULL;
+	evfs_i(inode).sym = NULL;
+	insert_inode_hash(inode);
+	if(dentry){
+		name = dentry_name(dentry, 0, sb);
+		if(name == NULL){
+			err = -ENOMEM;
+			goto out_put;
+		}
+		type = file_type(name, &rdev);
+		if (type == -1024) {
+			type = S_IFLNK;
+		} else
+		if (S_ISLNK(type)) {
+			int	c, n;
+			char	*buf = get_mem();
+			mm_segment_t fs = get_fs();
+			set_fs(KERNEL_DS);
+			c = sys_readlink(name, buf, PAGE_CACHE_SIZE-1);
+			set_fs(fs);
+			n = base2normlen(c);
+			if ((c > 0) && !(n & PADLEN)) {
+				char	*tmp = get_mem();
+				char	salt[SALTLEN];
+				/* symlink is ok, decode it */
+				base64_decode(buf, tmp, c);
+				aes_decrypt_str(&evfs_key(sb)->aes, tmp, tmp, n, get_salt(NULL, 0, salt));
+				tmp[n] = 0;
+				evfs_i(inode).sym = tmp;
+			}
+			put_mem(buf);
+		}
+		kfree(name); 
+	}
+	else type = S_IFDIR;
+	inode->i_sb = sb;
+
+	err = 0;
+	if(S_ISLNK(type))
+		inode->i_op = &page_symlink_inode_operations;
+	else if(S_ISDIR(type))
+		inode->i_op = &evfs_dir_iops;
+	else inode->i_op = &evfs_file_iops;
+
+	if(S_ISDIR(type)) inode->i_fop = &evfs_dir_fops;
+	else inode->i_fop = &evfs_fops;
+
+	if(S_ISLNK(type))
+		inode->i_mapping->a_ops = &evfs_link_aops;
+	else inode->i_mapping->a_ops = &evfs_aops;
+
+	if (S_ISCHR(type))
+		init_special_inode(inode, S_IFCHR, rdev);
+		else
+	if (S_ISBLK(type))
+		init_special_inode(inode, S_IFBLK, rdev);
+		else
+	if (S_ISFIFO(type))
+		init_special_inode(inode, S_IFIFO, 0);
+		else
+	if (S_ISSOCK(type))
+		init_special_inode(inode, S_IFSOCK, 0);
+
+	if(error) *error = err;
+	return(inode);
+ out_put:
+	iput(inode);
+ out:
+	if(error) *error = err;
+	return(NULL);
+}
+
+
+
+/**************************************************************************
+ Super operations
+ **************************************************************************/
+/* purge an evfs inode */
+static	void evfs_delete_inode(struct inode *ino)
+{
+	track();
+	if (evfs_i(ino).host_filename)
+		kfree(evfs_i(ino).host_filename);
+	evfs_i(ino).host_filename = NULL;
+
+	if(evfs_i(ino).fd) {
+		/* set real size */
+		if (S_ISREG(ino->i_mode))
+			my_truncate(evfs_i(ino).fd->f_dentry, ino->i_size + PADLEN);
+		fput(evfs_i(ino).fd);
+		evfs_i(ino).fd = NULL;
+	}
+	if(evfs_i(ino).sym)  {
+		put_mem(evfs_i(ino).sym);
+		evfs_i(ino).sym = NULL;
+	}
+	clear_inode(ino);
+}
+
+
+/* stat a filesystem */
+int	evfs_statfs(struct super_block *sb, struct statfs *sf)
+{
+	struct	nameidata nd;
+	int	error;
+	error = hpath_lookup(evfs_i(sb->s_root->d_inode).host_filename, &nd);
+	if (!error) {
+		error = vfs_statfs(nd.dentry->d_inode->i_sb, sf);
+		path_release(&nd);
+	}
+	return error;
+}
+
+static	void	evfs_putsuper(struct super_block *s)
+{
+	track();
+	kfree(evfs_key(s));
+}
+
+/* read evfs superblock */
+static	struct	super_block *evfs_read_super(struct super_block *s, void *d, int silent)
+{
+	char	*data = d;
+	char	*password;
+	char	*name, *to;
+	struct	inode *root_inode;
+	char	buf[32];
+	struct	sha256_ctx ctx;
+	struct	nameidata nd, ns;
+	struct	dentry *parent;
+
+	int	uid = current->fsuid;
+	int	gid = current->fsgid;
+
+	track();
+	/* first some basic super ops */
+	s->s_blocksize = EVFS_BLK_SIZE;
+	s->s_blocksize_bits = EVFS_BLK_BITS;
+	s->s_magic = EVFS_MAGIC;
+	s->s_op = &evfs_sbops;
+
+	/* and some common checks */
+	if (!data || !*data) {
+		printk("evfs: source mount directory not specified\n");
+		return NULL;
+	}
+
+	/* extract from, to and password */
+	for (to = data; *to != ' '; to++) {
+		if (!*to) {
+			printk("evfs: invalid number of arguments (destination and password missing)\n");
+			return NULL;
+		}
+	}
+	*to++ = 0;
+
+	for (password = to; *password != ' '; password++)
+		if (!*password) {
+			printk("evfs: no password supplied while mounting %s\n", data);
+			return NULL;
+		}
+	*password++ = 0;
+
+	if (hpath_lookup_dir(to, &nd, LOOKUP_FOLLOW)) {
+		printk("evfs: error while looking up mount destination!\n");
+		return NULL;
+	}
+
+	/* check uid ... */
+	if (uid)
+	if ((nd.dentry->d_inode->i_uid != uid) || (nd.dentry->d_inode->i_gid != gid)) {
+		printk("evfs: *WARNING*, uid %d supplied someone's else directory as destination!\n", uid);
+		goto out_nd;
+	}
+
+	/* and absolute path */
+	if (data[0] != '/') {
+		printk("evfs: attempted to mount relative path %s!\n", data);
+		goto out_nd;
+	}
+
+	/* create root inode */
+	root_inode = get_inode(s, NULL, NULL);
+	if (!root_inode)
+		goto out_nd;
+	name = kstrdup(data);
+	track();
+	s->s_root = d_alloc_root(root_inode);
+	evfs_i(root_inode).host_filename = name;
+	track();
+
+	if (hpath_lookup_dir(name, &ns, 0))
+		goto out;
+
+	if (ns.dentry->d_inode->i_sb->s_magic == EVFS_MAGIC) {
+		printk("evfs: uid %d tried to mount evfs from evfs - not supported yet, to avoid recursion.\n", uid);
+		goto out_put;
+	}
+
+	COPY_INODE(root_inode, ns.dentry->d_inode);
+
+	track();
+	/* hrmm. comparing whether source is not in destinating directory *is* good idea */
+	for (parent = ns.dentry; parent != parent->d_parent; parent = parent->d_parent) {
+		if (parent == nd.dentry)
+			goto out_put;
+	}
+	track();
+
+	if (uid)
+	if ((root_inode->i_uid != uid || root_inode->i_gid != gid) &&
+	    ((uid != 0) && (gid != 0)))
+		goto out_put;
+
+	evfs_key(s) = kmalloc(sizeof(struct evfs_ctx), GFP_KERNEL);
+	if (!evfs_key(s))
+		goto out_put;
+	sha256_init(&ctx);
+	sha256_update(&ctx, password, strlen(password));
+	sha256_final(&ctx, buf);
+	memset(&ctx, 0xF8, sizeof(ctx));
+	aes_set_key(&evfs_key(s)->aes, buf);
+	evfs_key(s)->recursion = 0;
+	memset(evfs_key(s)->salts, buf[0] + buf[31], sizeof(evfs_key(s)->salts));
+	/* initialize disk block salts (one for one blocks, 256 total, then repeats */
+	aes_encrypt_str(&evfs_key(s)->aes, &evfs_key(s)->salts[0][0], &evfs_key(s)->salts[0][0], sizeof(evfs_key(s)->salts), buf);
+	memset(buf, 0xF8, 32);
+
+	path_release(&nd);
+	path_release(&ns);
+	return s;
+out_put:
+	track();
+	path_release(&ns);
+out:
+	iput(root_inode);
+out_nd:
+	track();
+	path_release(&nd);
+	return NULL;	
+}
+
+/**************************************************************************
+ Inode operations
+ **************************************************************************/
+int evfs_create(struct inode *dir, struct dentry *dentry, int mode)
+{
+	struct inode *inode;
+	char *name;
+	struct file *fd;
+	int error;
+
+	track();
+	inode = get_inode(dir->i_sb, dentry, &error);
+	if (error) return(error);
+	name = dentry_name(dentry, 0, dir->i_sb);
+	if(name == NULL){
+		iput(inode);
+		return(-ENOMEM);
+	}
+	fd = filp_open(name, O_CREAT | O_EXCL, mode);
+	error = IS_ERR(fd);
+	if (!error) {
+		my_truncate(fd->f_dentry, PADLEN);
+		fput(fd);
+	}
+	else error = PTR_ERR(fd);
+	if(!error) error = read_name(inode, name);
+	kfree(name);
+	if(error) {
+		iput(inode);
+		return(error);
+	}
+	d_instantiate(dentry, inode);
+	return(0);
+}
+
+struct dentry *evfs_lookup(struct inode *ino, struct dentry *dentry)
+{
+	struct inode *inode;
+	char *name;
+	int error;
+
+	track();
+	inode = get_inode(ino->i_sb, dentry, &error);
+	if(error != 0) return(ERR_PTR(error));
+	name = dentry_name(dentry, 0, ino->i_sb);
+	if(name == NULL) return(ERR_PTR(-ENOMEM));
+	error = read_name(inode, name);
+	kfree(name);
+	if(error){
+		iput(inode);
+		if(error == -ENOENT) inode = NULL;
+		else return(ERR_PTR(error));
+	}
+	d_add(dentry, inode);
+	dentry->d_op = &evfs_dentry_ops;
+	return(NULL);
+}
+
+static char *inode_dentry_name(struct inode *ino, struct dentry *dentry)
+{
+        char	*file;
+	int	fl, i;
+	int	alen = (dentry->d_name.len + PADLEN) & ~PADLEN;
+	int	elen = norm2baselen(alen);
+	char	tmp[NAME_MAX + 1];
+	char	salt[SALTLEN];
+
+/*	if ((dentry->d_name.len == sizeof(EVFS_COOKIE)-1) &&
+	    (!memcmp(dentry->d_name.name, EVFS_COOKIE, sizeof(EVFS_COOKIE)-1)))
+		return NULL; */
+
+	track();
+	file = inode_name(ino, elen + 1);
+	if (file == NULL) return(NULL);
+	fl = strlen(file);
+	file[fl++] = '/';
+	memset(tmp, 0, alen);
+	memcpy(tmp, dentry->d_name.name, dentry->d_name.len);
+	aes_encrypt_str(&evfs_key(ino->i_sb)->aes, tmp, tmp, alen, get_salt(NULL, 0, salt));
+	i = base64_encode(tmp, file + fl, alen);
+	file[fl + i] = 0;
+        return(file);
+}
+
+int evfs_link(struct dentry *to, struct inode *ino, struct dentry *from)
+{
+        char *from_name, *to_name;
+        int err;
+	mm_segment_t fs;
+
+	track();
+        if((from_name = inode_dentry_name(ino, from)) == NULL) 
+                return(-ENOMEM);
+        to_name = dentry_name(to, 0, ino->i_sb);
+	if(to_name == NULL){
+		kfree(from_name);
+		return(-ENOMEM);
+	}
+	fs = get_fs(); set_fs(KERNEL_DS);
+        err = sys_link(to_name, from_name);
+	set_fs(fs);
+        kfree(from_name);
+        kfree(to_name);
+        return(err);
+}
+
+int evfs_unlink(struct inode *ino, struct dentry *dentry)
+{
+	char *file;
+	int err;
+	mm_segment_t fs;
+
+	track();
+	if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM);
+	fs = get_fs(); set_fs(KERNEL_DS);
+	err = sys_unlink(file);
+	set_fs(fs);
+	kfree(file);
+	return(err);
+}
+
+int evfs_symlink(struct inode *ino, struct dentry *dentry, const char *to)
+{
+	char *file;
+	int err;
+	mm_segment_t fs;
+	char	salt[SALTLEN];
+	char	*buf = get_mem();
+	char	*buf2 = get_mem();
+
+	int	len = strlen(to);
+	int	alen = (len + PADLEN) & ~PADLEN;
+
+	track();
+	if (alen > PAGE_CACHE_SIZE) return -ENOMEM;
+
+	if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM);
+	fs = get_fs(); set_fs(KERNEL_DS);
+
+	if (!buf) return -ENOMEM;
+	if (!buf2) {
+		put_mem(buf);
+		return -ENOMEM;
+	}
+
+	memset(buf, 0, alen);
+	memcpy(buf, to, len);
+
+	aes_encrypt_str(&gk(ino)->aes, buf, buf, alen, get_salt(NULL, 0, salt));
+	buf2[base64_encode(buf, buf2, alen)] = 0;
+
+	err = sys_symlink(buf2, file);
+	put_mem(buf);
+	put_mem(buf2);
+	set_fs(fs);
+	kfree(file);
+	return(err);
+}
+
+int evfs_mkdir(struct inode *ino, struct dentry *dentry, int mode)
+{
+	char *file;
+	int err;
+	mm_segment_t fs;
+
+	track();
+	if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM);
+	fs = get_fs(); set_fs(KERNEL_DS);
+	err = sys_mkdir(file, mode);
+	set_fs(fs);
+	kfree(file);
+	return(err);
+}
+
+int evfs_rmdir(struct inode *ino, struct dentry *dentry)
+{
+	char *file;
+	int err;
+	mm_segment_t fs;
+
+	if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM);
+	fs = get_fs(); set_fs(KERNEL_DS);
+	err = sys_rmdir(file);
+	set_fs(fs);
+	kfree(file);
+	return(err);
+}
+
+int evfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int dev)
+{
+	struct inode *inode;
+	char *name;
+	int error;
+ 	mm_segment_t fs;
+
+	track();
+	inode = get_inode(dir->i_sb, dentry, &error);
+	if(error) return(error);
+	name = dentry_name(dentry, 0, dir->i_sb);
+	if(name == NULL){
+		iput(inode);
+		return(-ENOMEM);
+	}
+	init_special_inode(inode, mode, dev);
+	fs = get_fs(); set_fs(KERNEL_DS);
+	error = sys_mknod(name, mode, dev);
+	set_fs(fs);
+	if(!error) error = read_name(inode, name);
+	kfree(name);
+	if(error){
+		iput(inode);
+		return(error);
+	}
+	d_instantiate(dentry, inode);
+	return(0);
+}
+
+int evfs_rename(struct inode *from_ino, struct dentry *from,
+		  struct inode *to_ino, struct dentry *to)
+{
+	char *from_name, *to_name;
+	int err;
+ 	mm_segment_t fs;
+
+	if((from_name = inode_dentry_name(from_ino, from)) == NULL)
+		return(-ENOMEM);
+	if((to_name = inode_dentry_name(to_ino, to)) == NULL){
+		kfree(from_name);
+		return(-ENOMEM);
+	}
+	fs = get_fs(); set_fs(KERNEL_DS);
+	err = sys_rename(from_name, to_name);
+	set_fs(fs);
+	kfree(from_name);
+	kfree(to_name);
+	return(err);
+}
+
+void evfs_truncate(struct inode *ino)
+{
+	return -EINVAL;
+}
+
+int evfs_permission(struct inode *ino, int desired)
+{
+	int	err;
+	char	*name;
+	struct	nameidata nd;
+
+	track();
+	name = inode_name(ino, 0);
+	if(name == NULL) return(-ENOMEM);
+
+	err = hpath_lookup(name, &nd);
+	kfree(name);
+	if(!err) {
+		err = permission(nd.dentry->d_inode, desired);
+		path_release(&nd);
+	}
+	return(err);
+}
+
+int evfs_setattr(struct dentry *dentry, struct iattr *attr)
+{
+	struct	nameidata nd;
+	char *name;
+	int err;
+
+	track();
+	name = dentry_name(dentry, 0, NULL);
+	if(name == NULL) return(-ENOMEM);
+	err = hpath_lookup(name, &nd);
+	kfree(name);
+	if (!err) {
+		/* handle truncate */
+		if (attr->ia_valid & ATTR_SIZE) {
+			attr->ia_size += PADLEN;
+		}
+		err = inode_setattr(nd.dentry->d_inode, attr);
+		path_release(&nd);
+	}
+	return(err);
+}
+
+/**************************************************************************
+ File operations
+ **************************************************************************/
+
+
+int evfs_file_open(struct inode *ino, struct file *file)
+{
+	char *name;
+	struct	file *fd;
+
+	track();
+	if(evfs_i(ino).fd) {
+		fput(evfs_i(ino).fd);
+		evfs_i(ino).fd = NULL;
+	}
+	name = dentry_name(file->f_dentry, 0, ino->i_sb);
+	if(name == NULL) 
+		return(-ENOMEM);
+
+	fd = filp_open(name, file->f_flags & ~(O_APPEND | O_EXCL | O_CREAT), file->f_mode);
+	kfree(name);
+	if (IS_ERR(fd)) return(PTR_ERR(fd));
+	file_evfs_i(file)->fd = fd;
+	return(0);
+}
+
+int evfs_fsync(struct file *file, struct dentry *dentry, int datasync)
+{
+	return(0);
+}
+
+/**************************************************************************
+ Directory operations
+ **************************************************************************/
+int evfs_dir_release(struct inode *ino, struct file *file)
+{
+	track();
+	return(0);
+}
+
+struct	my_ent {
+	void	*old_filler;
+	void	*old_ent;
+	struct	super_block *sb;
+};
+
+static int my_filldir(struct my_ent *e, const char * name, int namlen, loff_t offset,
+		   ino_t ino, unsigned int d_type)
+{
+	filldir_t old_filldir;
+	int	len, nlen;
+	char	buf[NAME_MAX + 1];
+	char	salt[SALTLEN];
+
+	old_filldir = e->old_filler;
+	/* hide magic */
+	if ((namlen == sizeof(EVFS_COOKIE)-1) && (!memcmp(name, EVFS_COOKIE, namlen)))
+		return 0;
+	/* and do not ever try to decode '.' and '..' */
+	if ((name[0] == '.') && ((namlen == 1) || (namlen == 2 && name[1] == '.')))
+		return old_filldir(e->old_ent, name, namlen, offset, ino, d_type);
+	/* the rest will get decrypted */
+	len = base2normlen(namlen);
+	/* unaligned sucks */
+	if (len & PADLEN)
+		return 0;
+
+	base64_decode(name, buf, namlen);
+	aes_decrypt_str(&evfs_key(e->sb)->aes, buf, buf, len, get_salt(NULL, 0, salt));
+	nlen = strnlen(buf, len);
+	buf[nlen] = 0;
+	return old_filldir(e->old_ent, buf, nlen, offset, ino, d_type);
+}
+
+int evfs_readdir(struct file *file, void *ent, filldir_t filldir)
+{
+	struct	my_ent e;
+	track();
+	e.old_filler = filldir;
+	e.old_ent = ent;
+	e.sb = file->f_dentry->d_inode->i_sb;
+	return vfs_readdir(file_evfs_i(file)->fd, (void *) my_filldir, (void *) &e);
+}
+
+/**************************************************************************
+ Address space operations
+ **************************************************************************/
+int evfs_do_read(struct file *file, long long *start, char *buf, size_t count)
+{
+	int	ret = -EBADF;
+	mm_segment_t fs = get_fs();
+	set_fs(KERNEL_DS);
+
+	ret = rw_verify_area(READ, file, *start, count);
+	if (!ret) {
+		ssize_t (*read)(struct file *, char *, size_t, loff_t *);
+		ret = -EINVAL;
+		if (file->f_op && (read = file->f_op->read) != NULL) {
+			ret = read(file, buf, count, start);
+		}
+	}
+	if (ret > 0)
+		dnotify_parent(file->f_dentry, DN_ACCESS);
+	set_fs(fs);
+	return ret;
+}
+
+int evfs_do_write(struct file *file, long long *start, char *buf, size_t count)
+{
+	int	ret = -EBADF;
+	mm_segment_t fs = get_fs();
+	set_fs(KERNEL_DS);
+
+	track();
+	ret = rw_verify_area(WRITE, file, *start, count);
+	if (!ret) {
+		ssize_t (*write)(struct file *, const char *, size_t, loff_t *);
+		ret = -EINVAL;
+		if (file->f_op && (write = file->f_op->write) != NULL) {
+			ret = write(file, buf, count, start);
+		}
+	}
+	if (ret > 0)
+		dnotify_parent(file->f_dentry, DN_MODIFY);
+	set_fs(fs);
+	return ret;
+}
+
+
+int evfs_writepage(struct page *page)
+{
+	struct address_space *mapping = page->mapping;
+	struct inode *inode = mapping->host;
+	char *buffer;
+	unsigned long long base;
+	int count = PAGE_CACHE_SIZE;
+	int end_index = inode->i_size >> PAGE_CACHE_SHIFT;
+	int err;
+	char	*kbuf = get_mem();
+	char	buf[SALTLEN];
+
+	if (!kbuf)
+		return -ENOMEM;
+
+	track();
+	if (page->index >= end_index)
+		count = (inode->i_size & (PAGE_CACHE_SIZE-1));
+
+	buffer = kmap(page);
+	base = ((unsigned long long) page->index) << PAGE_CACHE_SHIFT;
+
+	aes_encrypt_str(&gk(inode)->aes, kbuf, buffer, (count+PADLEN) & ~PADLEN, get_salt(gk(inode), page->index, buf));
+	err = evfs_do_write(evfs_i(inode).fd, &base, kbuf, (count + PADLEN) & ~PADLEN);
+	if(err != count){
+		ClearPageUptodate(page);
+		goto out;
+	}
+
+	if (base > inode->i_size) {
+		inode->i_size = base;
+	}
+
+	/* this is just for everyone else using that file, real fs will get
+	   notified by regular do_truncate about real size when we'll fput this
+	   file */
+	evfs_i(inode).fd->f_dentry->d_inode->i_size = inode->i_size + PADLEN;
+
+	if (PageError(page))
+		ClearPageError(page);	
+	err = 0;
+
+ out:	
+	kunmap(page);
+
+	UnlockPage(page);
+	put_mem(kbuf);
+	return err; 
+} 
+
+
+int evfs_readpage(struct file *file, struct page *page)
+{
+	char *buffer;
+	long long start, tmp;
+	int err = 0;
+	struct	inode *inode = file->f_dentry->d_inode;
+	struct	file *f = file_evfs_i(file)->fd;
+	int end_index = inode->i_size >> PAGE_CACHE_SHIFT;
+	char buf[SALTLEN];
+
+	track();
+	start = (long long) page->index << PAGE_CACHE_SHIFT;
+	buffer = kmap(page);
+	tmp = start;
+	err = evfs_do_read(f, &start, buffer,
+			PAGE_CACHE_SIZE);
+	if(err < 0) goto out;
+
+	if (err & PADLEN) {
+		if (!(page->index >= end_index))
+		printk("EVFS WARNING: access beyond end of padding of file!\n");
+	}
+	/* yeah ! */
+	aes_decrypt_str(&gk(inode)->aes, buffer, buffer, err & ~PADLEN, get_salt(gk(inode), page->index, buf));
+
+	/* do we've reached padding (i.e. virtual size) ? */
+	if (start > inode->i_size) {
+		/* my dear, we did - round it up to virtual size */
+		start = inode->i_size;
+		err = start - tmp;
+		if (err < 0) err = 0;
+	}
+
+	flush_dcache_page(page);
+	SetPageUptodate(page);
+	if (PageError(page)) ClearPageError(page);
+	err = 0;
+ out:
+	kunmap(page);
+	UnlockPage(page);
+	return(err);
+}
+
+
+int evfs_prepare_write(struct file *file, struct page *page, 
+			 unsigned int from, unsigned int to)
+{
+	return 0;
+}
+
+int evfs_commit_write(struct file *file, struct page *page, unsigned from,
+		 unsigned to)
+{
+	struct address_space *mapping = page->mapping;
+	struct inode *inode = mapping->host;
+	char *buffer, *kbuf;
+	long long o, tmp, start;
+	int err = 0;
+	int end_index = inode->i_size >> PAGE_CACHE_SHIFT;
+	char	buf[SALTLEN];
+
+	kbuf = get_mem();
+	if (!kbuf)
+		return -ENOMEM;
+
+	track();
+	o = tmp = start = (long long) (page->index << PAGE_CACHE_SHIFT);
+	buffer = kmap(page);
+
+	memset(kbuf, 0, PAGE_CACHE_SIZE);
+
+	/* we've to get at least partly complete page to do some encryption */
+	err = evfs_do_read(file_evfs_i(file)->fd, &tmp, kbuf, PAGE_CACHE_SIZE);
+	if (err < 0) goto out;
+	if (err & PADLEN) {
+		if (!(page->index >= end_index))
+		printk("EVFS WARNING: access beyond end of padding of file!\n");
+	}
+	/* oki, we've that bitch, now decrypt it :) */
+	aes_decrypt_str(&gk(inode)->aes, kbuf, kbuf, (err + PADLEN) & ~PADLEN, get_salt(gk(inode), page->index, buf));
+	/* overwrite it with new data */
+	memcpy(kbuf + from, buffer + from, to - from);
+	if (to > err) err = to;
+	/* and encrypt whole thingie */
+	aes_encrypt_str(&gk(inode)->aes, kbuf, kbuf, (err + PADLEN) & ~PADLEN, get_salt(gk(inode), page->index, buf));
+	err = evfs_do_write(file_evfs_i(file)->fd, &start, kbuf, (err + PADLEN) & ~PADLEN);
+	if (err < to)
+		err = -EPIPE;
+	else {
+		o += to;
+		if (o > inode->i_size)
+			inode->i_size = o;
+		err = 0;
+		/* this is just for everyone else using that file, real fs will get
+		   notified by regular do_truncate about real size when we'll fput this
+		   file */
+		evfs_i(inode).fd->f_dentry->d_inode->i_size = inode->i_size + PADLEN;
+	}
+out:
+	kunmap(page);
+	put_mem(kbuf);
+	return(err);
+}
+
+static __inline__ int
+do_revalidate(struct dentry *dentry)
+{
+	struct inode * inode = dentry->d_inode;
+	if (inode->i_op && inode->i_op->revalidate)
+		return inode->i_op->revalidate(dentry);
+	return 0;
+}
+
+
+int evfs_link_readpage(struct file *file, struct page *page)
+{
+	struct	inode *ino;
+	char *buffer;
+	long long start;
+	int err;
+
+	track();
+	start = page->index << PAGE_CACHE_SHIFT;
+	buffer = kmap(page);
+	ino = page->mapping->host;
+	track();
+
+	err = -EINVAL;
+	if (ino) {
+		if ((!evfs_i(ino).sym) || (!ino))
+			err = -ENOENT;
+		else {
+			strncpy(buffer, evfs_i(ino).sym, PAGE_CACHE_SIZE-1);
+			buffer[PAGE_CACHE_SIZE-1] = 0;
+			err = strlen(buffer);
+		}
+	}
+	if(err > 0) {
+		flush_dcache_page(page);
+		SetPageUptodate(page);
+		if (PageError(page)) ClearPageError(page);
+		err = 0;
+	}
+	kunmap(page);
+	UnlockPage(page);
+	return(err);
+}
+
+
+int evfs_d_delete(struct dentry *dentry)
+{
+	return(1);
+}
+
+
+DECLARE_FSTYPE(evfs_type, "evfs", evfs_read_super, 0);
+
+static	int	__init init_evfs(void)
+{
+	gen_tabs();
+	return register_filesystem(&evfs_type);
+}
+
+static	void	__exit exit_evfs(void)
+{
+	unregister_filesystem(&evfs_type);
+}
+
+static struct super_operations evfs_sbops = {
+	put_inode:	force_delete,
+	put_super:	evfs_putsuper,
+	delete_inode:	evfs_delete_inode,
+	statfs:		evfs_statfs
+};
+
+static	struct	inode_operations evfs_file_iops = {
+	create:		evfs_create,
+	link:		evfs_link,
+	unlink:		evfs_unlink,
+	symlink:	evfs_symlink,
+	mkdir:		evfs_mkdir,
+	rmdir:		evfs_rmdir,
+	mknod:		evfs_mknod,
+	rename:		evfs_rename,
+	truncate:	evfs_truncate,
+	permission:	evfs_permission,
+	setattr:	evfs_setattr
+};
+
+static	struct	inode_operations evfs_dir_iops = {
+	create:		evfs_create,
+	lookup:		evfs_lookup,
+	link:		evfs_link,
+	unlink:		evfs_unlink,
+	symlink:	evfs_symlink,
+	mkdir:		evfs_mkdir,
+	rmdir:		evfs_rmdir,
+	mknod:		evfs_mknod,
+	rename:		evfs_rename,
+	truncate:	evfs_truncate,
+	permission:	evfs_permission,
+	setattr:	evfs_setattr
+};
+
+static	struct	file_operations evfs_fops = {
+	owner:		NULL,
+	read:		generic_file_read,
+	write:		generic_file_write,
+	mmap:		generic_file_mmap,
+	open:		evfs_file_open,
+	release:	NULL,
+	fsync:		evfs_fsync,
+};
+
+static struct file_operations evfs_dir_fops = {
+	owner:		NULL,
+	readdir:	evfs_readdir,
+	open:		evfs_file_open,
+	release:	evfs_dir_release,
+	fsync:		evfs_fsync,
+};
+
+static	struct dentry_operations evfs_dentry_ops = {
+	d_delete:	evfs_d_delete,
+};
+
+static struct address_space_operations evfs_aops = {
+	writepage: 	evfs_writepage,
+	readpage:	evfs_readpage,
+	prepare_write:	evfs_prepare_write,
+	commit_write:	evfs_commit_write
+};
+
+static struct address_space_operations evfs_link_aops = {
+	readpage:	evfs_link_readpage
+};
+
+EXPORT_NO_SYMBOLS;
+
+module_init(init_evfs);
+module_exit(exit_evfs);
+MODULE_LICENSE("BSD/GPL");
diff -urN linux-2.4.30-pre2/fs/evfs/sha256.c linux-2.4.30-pre2-evfs/fs/evfs/sha256.c
--- linux-2.4.30-pre2/fs/evfs/sha256.c	Thu Jan  1 01:00:00 1970
+++ linux-2.4.30-pre2-evfs/fs/evfs/sha256.c	Sun Mar  6 15:07:05 2005
@@ -0,0 +1,272 @@
+/*
+ * Cryptographic API.
+ *
+ * SHA-256, as specified in
+ * http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf
+ *
+ * SHA-256 code by Jean-Luc Cooke <jlcooke@certainkey.com>.
+ *
+ * Copyright (c) Jean-Luc Cooke <jlcooke@certainkey.com>
+ * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.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 "sha256.h"
+#include <linux/string.h>
+
+static void sha256_transform(u32 *state, const u8 *input)
+{
+	u32 a, b, c, d, e, f, g, h, t1, t2;
+	u32 W[64];
+	int i;
+
+	/* load the input */
+	for (i = 0; i < 16; i++)
+		LOAD_OP(i, W, input);
+
+	/* now blend */
+	for (i = 16; i < 64; i++)
+		BLEND_OP(i, W);
+    
+	/* load the state into our registers */
+	a=state[0];  b=state[1];  c=state[2];  d=state[3];
+	e=state[4];  f=state[5];  g=state[6];  h=state[7];
+
+	/* now iterate */
+	t1 = h + e1(e) + Ch(e,f,g) + 0x428a2f98 + W[ 0];
+	t2 = e0(a) + Maj(a,b,c);    d+=t1;    h=t1+t2;
+	t1 = g + e1(d) + Ch(d,e,f) + 0x71374491 + W[ 1];
+	t2 = e0(h) + Maj(h,a,b);    c+=t1;    g=t1+t2;
+	t1 = f + e1(c) + Ch(c,d,e) + 0xb5c0fbcf + W[ 2];
+	t2 = e0(g) + Maj(g,h,a);    b+=t1;    f=t1+t2;
+	t1 = e + e1(b) + Ch(b,c,d) + 0xe9b5dba5 + W[ 3];
+	t2 = e0(f) + Maj(f,g,h);    a+=t1;    e=t1+t2;
+	t1 = d + e1(a) + Ch(a,b,c) + 0x3956c25b + W[ 4];
+	t2 = e0(e) + Maj(e,f,g);    h+=t1;    d=t1+t2;
+	t1 = c + e1(h) + Ch(h,a,b) + 0x59f111f1 + W[ 5];
+	t2 = e0(d) + Maj(d,e,f);    g+=t1;    c=t1+t2;
+	t1 = b + e1(g) + Ch(g,h,a) + 0x923f82a4 + W[ 6];
+	t2 = e0(c) + Maj(c,d,e);    f+=t1;    b=t1+t2;
+	t1 = a + e1(f) + Ch(f,g,h) + 0xab1c5ed5 + W[ 7];
+	t2 = e0(b) + Maj(b,c,d);    e+=t1;    a=t1+t2;
+
+	t1 = h + e1(e) + Ch(e,f,g) + 0xd807aa98 + W[ 8];
+	t2 = e0(a) + Maj(a,b,c);    d+=t1;    h=t1+t2;
+	t1 = g + e1(d) + Ch(d,e,f) + 0x12835b01 + W[ 9];
+	t2 = e0(h) + Maj(h,a,b);    c+=t1;    g=t1+t2;
+	t1 = f + e1(c) + Ch(c,d,e) + 0x243185be + W[10];
+	t2 = e0(g) + Maj(g,h,a);    b+=t1;    f=t1+t2;
+	t1 = e + e1(b) + Ch(b,c,d) + 0x550c7dc3 + W[11];
+	t2 = e0(f) + Maj(f,g,h);    a+=t1;    e=t1+t2;
+	t1 = d + e1(a) + Ch(a,b,c) + 0x72be5d74 + W[12];
+	t2 = e0(e) + Maj(e,f,g);    h+=t1;    d=t1+t2;
+	t1 = c + e1(h) + Ch(h,a,b) + 0x80deb1fe + W[13];
+	t2 = e0(d) + Maj(d,e,f);    g+=t1;    c=t1+t2;
+	t1 = b + e1(g) + Ch(g,h,a) + 0x9bdc06a7 + W[14];
+	t2 = e0(c) + Maj(c,d,e);    f+=t1;    b=t1+t2;
+	t1 = a + e1(f) + Ch(f,g,h) + 0xc19bf174 + W[15];
+	t2 = e0(b) + Maj(b,c,d);    e+=t1;    a=t1+t2;
+
+	t1 = h + e1(e) + Ch(e,f,g) + 0xe49b69c1 + W[16];
+	t2 = e0(a) + Maj(a,b,c);    d+=t1;    h=t1+t2;
+	t1 = g + e1(d) + Ch(d,e,f) + 0xefbe4786 + W[17];
+	t2 = e0(h) + Maj(h,a,b);    c+=t1;    g=t1+t2;
+	t1 = f + e1(c) + Ch(c,d,e) + 0x0fc19dc6 + W[18];
+	t2 = e0(g) + Maj(g,h,a);    b+=t1;    f=t1+t2;
+	t1 = e + e1(b) + Ch(b,c,d) + 0x240ca1cc + W[19];
+	t2 = e0(f) + Maj(f,g,h);    a+=t1;    e=t1+t2;
+	t1 = d + e1(a) + Ch(a,b,c) + 0x2de92c6f + W[20];
+	t2 = e0(e) + Maj(e,f,g);    h+=t1;    d=t1+t2;
+	t1 = c + e1(h) + Ch(h,a,b) + 0x4a7484aa + W[21];
+	t2 = e0(d) + Maj(d,e,f);    g+=t1;    c=t1+t2;
+	t1 = b + e1(g) + Ch(g,h,a) + 0x5cb0a9dc + W[22];
+	t2 = e0(c) + Maj(c,d,e);    f+=t1;    b=t1+t2;
+	t1 = a + e1(f) + Ch(f,g,h) + 0x76f988da + W[23];
+	t2 = e0(b) + Maj(b,c,d);    e+=t1;    a=t1+t2;
+
+	t1 = h + e1(e) + Ch(e,f,g) + 0x983e5152 + W[24];
+	t2 = e0(a) + Maj(a,b,c);    d+=t1;    h=t1+t2;
+	t1 = g + e1(d) + Ch(d,e,f) + 0xa831c66d + W[25];
+	t2 = e0(h) + Maj(h,a,b);    c+=t1;    g=t1+t2;
+	t1 = f + e1(c) + Ch(c,d,e) + 0xb00327c8 + W[26];
+	t2 = e0(g) + Maj(g,h,a);    b+=t1;    f=t1+t2;
+	t1 = e + e1(b) + Ch(b,c,d) + 0xbf597fc7 + W[27];
+	t2 = e0(f) + Maj(f,g,h);    a+=t1;    e=t1+t2;
+	t1 = d + e1(a) + Ch(a,b,c) + 0xc6e00bf3 + W[28];
+	t2 = e0(e) + Maj(e,f,g);    h+=t1;    d=t1+t2;
+	t1 = c + e1(h) + Ch(h,a,b) + 0xd5a79147 + W[29];
+	t2 = e0(d) + Maj(d,e,f);    g+=t1;    c=t1+t2;
+	t1 = b + e1(g) + Ch(g,h,a) + 0x06ca6351 + W[30];
+	t2 = e0(c) + Maj(c,d,e);    f+=t1;    b=t1+t2;
+	t1 = a + e1(f) + Ch(f,g,h) + 0x14292967 + W[31];
+	t2 = e0(b) + Maj(b,c,d);    e+=t1;    a=t1+t2;
+
+	t1 = h + e1(e) + Ch(e,f,g) + 0x27b70a85 + W[32];
+	t2 = e0(a) + Maj(a,b,c);    d+=t1;    h=t1+t2;
+	t1 = g + e1(d) + Ch(d,e,f) + 0x2e1b2138 + W[33];
+	t2 = e0(h) + Maj(h,a,b);    c+=t1;    g=t1+t2;
+	t1 = f + e1(c) + Ch(c,d,e) + 0x4d2c6dfc + W[34];
+	t2 = e0(g) + Maj(g,h,a);    b+=t1;    f=t1+t2;
+	t1 = e + e1(b) + Ch(b,c,d) + 0x53380d13 + W[35];
+	t2 = e0(f) + Maj(f,g,h);    a+=t1;    e=t1+t2;
+	t1 = d + e1(a) + Ch(a,b,c) + 0x650a7354 + W[36];
+	t2 = e0(e) + Maj(e,f,g);    h+=t1;    d=t1+t2;
+	t1 = c + e1(h) + Ch(h,a,b) + 0x766a0abb + W[37];
+	t2 = e0(d) + Maj(d,e,f);    g+=t1;    c=t1+t2;
+	t1 = b + e1(g) + Ch(g,h,a) + 0x81c2c92e + W[38];
+	t2 = e0(c) + Maj(c,d,e);    f+=t1;    b=t1+t2;
+	t1 = a + e1(f) + Ch(f,g,h) + 0x92722c85 + W[39];
+	t2 = e0(b) + Maj(b,c,d);    e+=t1;    a=t1+t2;
+
+	t1 = h + e1(e) + Ch(e,f,g) + 0xa2bfe8a1 + W[40];
+	t2 = e0(a) + Maj(a,b,c);    d+=t1;    h=t1+t2;
+	t1 = g + e1(d) + Ch(d,e,f) + 0xa81a664b + W[41];
+	t2 = e0(h) + Maj(h,a,b);    c+=t1;    g=t1+t2;
+	t1 = f + e1(c) + Ch(c,d,e) + 0xc24b8b70 + W[42];
+	t2 = e0(g) + Maj(g,h,a);    b+=t1;    f=t1+t2;
+	t1 = e + e1(b) + Ch(b,c,d) + 0xc76c51a3 + W[43];
+	t2 = e0(f) + Maj(f,g,h);    a+=t1;    e=t1+t2;
+	t1 = d + e1(a) + Ch(a,b,c) + 0xd192e819 + W[44];
+	t2 = e0(e) + Maj(e,f,g);    h+=t1;    d=t1+t2;
+	t1 = c + e1(h) + Ch(h,a,b) + 0xd6990624 + W[45];
+	t2 = e0(d) + Maj(d,e,f);    g+=t1;    c=t1+t2;
+	t1 = b + e1(g) + Ch(g,h,a) + 0xf40e3585 + W[46];
+	t2 = e0(c) + Maj(c,d,e);    f+=t1;    b=t1+t2;
+	t1 = a + e1(f) + Ch(f,g,h) + 0x106aa070 + W[47];
+	t2 = e0(b) + Maj(b,c,d);    e+=t1;    a=t1+t2;
+
+	t1 = h + e1(e) + Ch(e,f,g) + 0x19a4c116 + W[48];
+	t2 = e0(a) + Maj(a,b,c);    d+=t1;    h=t1+t2;
+	t1 = g + e1(d) + Ch(d,e,f) + 0x1e376c08 + W[49];
+	t2 = e0(h) + Maj(h,a,b);    c+=t1;    g=t1+t2;
+	t1 = f + e1(c) + Ch(c,d,e) + 0x2748774c + W[50];
+	t2 = e0(g) + Maj(g,h,a);    b+=t1;    f=t1+t2;
+	t1 = e + e1(b) + Ch(b,c,d) + 0x34b0bcb5 + W[51];
+	t2 = e0(f) + Maj(f,g,h);    a+=t1;    e=t1+t2;
+	t1 = d + e1(a) + Ch(a,b,c) + 0x391c0cb3 + W[52];
+	t2 = e0(e) + Maj(e,f,g);    h+=t1;    d=t1+t2;
+	t1 = c + e1(h) + Ch(h,a,b) + 0x4ed8aa4a + W[53];
+	t2 = e0(d) + Maj(d,e,f);    g+=t1;    c=t1+t2;
+	t1 = b + e1(g) + Ch(g,h,a) + 0x5b9cca4f + W[54];
+	t2 = e0(c) + Maj(c,d,e);    f+=t1;    b=t1+t2;
+	t1 = a + e1(f) + Ch(f,g,h) + 0x682e6ff3 + W[55];
+	t2 = e0(b) + Maj(b,c,d);    e+=t1;    a=t1+t2;
+
+	t1 = h + e1(e) + Ch(e,f,g) + 0x748f82ee + W[56];
+	t2 = e0(a) + Maj(a,b,c);    d+=t1;    h=t1+t2;
+	t1 = g + e1(d) + Ch(d,e,f) + 0x78a5636f + W[57];
+	t2 = e0(h) + Maj(h,a,b);    c+=t1;    g=t1+t2;
+	t1 = f + e1(c) + Ch(c,d,e) + 0x84c87814 + W[58];
+	t2 = e0(g) + Maj(g,h,a);    b+=t1;    f=t1+t2;
+	t1 = e + e1(b) + Ch(b,c,d) + 0x8cc70208 + W[59];
+	t2 = e0(f) + Maj(f,g,h);    a+=t1;    e=t1+t2;
+	t1 = d + e1(a) + Ch(a,b,c) + 0x90befffa + W[60];
+	t2 = e0(e) + Maj(e,f,g);    h+=t1;    d=t1+t2;
+	t1 = c + e1(h) + Ch(h,a,b) + 0xa4506ceb + W[61];
+	t2 = e0(d) + Maj(d,e,f);    g+=t1;    c=t1+t2;
+	t1 = b + e1(g) + Ch(g,h,a) + 0xbef9a3f7 + W[62];
+	t2 = e0(c) + Maj(c,d,e);    f+=t1;    b=t1+t2;
+	t1 = a + e1(f) + Ch(f,g,h) + 0xc67178f2 + W[63];
+	t2 = e0(b) + Maj(b,c,d);    e+=t1;    a=t1+t2;
+
+	state[0] += a; state[1] += b; state[2] += c; state[3] += d;
+	state[4] += e; state[5] += f; state[6] += g; state[7] += h;
+
+	/* clear any sensitive info... */
+	a = b = c = d = e = f = g = h = t1 = t2 = 0;
+	memset(W, 0, 64 * sizeof(u32));
+}
+
+void sha256_init(void *ctx)
+{
+	struct sha256_ctx *sctx = ctx;
+	sctx->state[0] = H0;
+	sctx->state[1] = H1;
+	sctx->state[2] = H2;
+	sctx->state[3] = H3;
+	sctx->state[4] = H4;
+	sctx->state[5] = H5;
+	sctx->state[6] = H6;
+	sctx->state[7] = H7;
+	sctx->count[0] = sctx->count[1] = 0;
+	memset(sctx->buf, 0, sizeof(sctx->buf));
+}
+
+void sha256_update(void *ctx, const u8 *data, unsigned int len)
+{
+	struct sha256_ctx *sctx = ctx;
+	unsigned int i, index, part_len;
+
+	/* Compute number of bytes mod 128 */
+	index = (unsigned int)((sctx->count[0] >> 3) & 0x3f);
+
+	/* Update number of bits */
+	if ((sctx->count[0] += (len << 3)) < (len << 3)) {
+		sctx->count[1]++;
+		sctx->count[1] += (len >> 29);
+	}
+
+	part_len = 64 - index;
+
+	/* Transform as many times as possible. */
+	if (len >= part_len) {
+		memcpy(&sctx->buf[index], data, part_len);
+		sha256_transform(sctx->state, sctx->buf);
+
+		for (i = part_len; i + 63 < len; i += 64)
+			sha256_transform(sctx->state, &data[i]);
+		index = 0;
+	} else {
+		i = 0;
+	}
+	
+	/* Buffer remaining input */
+	memcpy(&sctx->buf[index], &data[i], len-i);
+}
+
+void sha256_final(void* ctx, u8 *out)
+{
+	struct sha256_ctx *sctx = ctx;
+	u8 bits[8];
+	unsigned int index, pad_len, t;
+	int i, j;
+	const u8 padding[64] = { 0x80, };
+
+	/* Save number of bits */
+	t = sctx->count[0];
+	bits[7] = t; t >>= 8;
+	bits[6] = t; t >>= 8;
+	bits[5] = t; t >>= 8;
+	bits[4] = t;
+	t = sctx->count[1];
+	bits[3] = t; t >>= 8;
+	bits[2] = t; t >>= 8;
+	bits[1] = t; t >>= 8;
+	bits[0] = t;
+
+	/* Pad out to 56 mod 64. */
+	index = (sctx->count[0] >> 3) & 0x3f;
+	pad_len = (index < 56) ? (56 - index) : ((64+56) - index);
+	sha256_update(sctx, padding, pad_len);
+
+	/* Append length (before padding) */
+	sha256_update(sctx, bits, 8);
+
+	/* Store state in digest */
+	for (i = j = 0; i < 8; i++, j += 4) {
+		t = sctx->state[i];
+		out[j+3] = t; t >>= 8;
+		out[j+2] = t; t >>= 8;
+		out[j+1] = t; t >>= 8;
+		out[j  ] = t;
+	}
+
+	/* Zeroize sensitive information. */
+	memset(sctx, 0, sizeof(*sctx));
+}
diff -urN linux-2.4.30-pre2/fs/evfs/sha256.h linux-2.4.30-pre2-evfs/fs/evfs/sha256.h
--- linux-2.4.30-pre2/fs/evfs/sha256.h	Thu Jan  1 01:00:00 1970
+++ linux-2.4.30-pre2-evfs/fs/evfs/sha256.h	Sun Mar  6 15:07:05 2005
@@ -0,0 +1,70 @@
+#ifndef SHA256_H
+#define SHA256_H
+
+#ifndef __KERNEL__
+#define __KERNEL__
+#endif
+#include <asm/types.h>
+#include <linux/byteorder/little_endian.h>
+
+#define SHA256_DIGEST_SIZE	32
+#define SHA256_HMAC_BLOCK_SIZE	64
+
+struct sha256_ctx {
+	u32 count[2];
+	u32 state[8];
+	u8 buf[128];
+};
+
+static inline u32 Ch(u32 x, u32 y, u32 z)
+{
+	return ((x & y) ^ (~x & z));
+}
+
+static inline u32 Maj(u32 x, u32 y, u32 z)
+{
+	return ((x & y) ^ (x & z) ^ (y & z));
+}
+
+static inline u32 RORu32(u32 x, u32 y)
+{
+	return (x >> y) | (x << (32 - y));
+}
+
+#define e0(x)       (RORu32(x, 2) ^ RORu32(x,13) ^ RORu32(x,22))
+#define e1(x)       (RORu32(x, 6) ^ RORu32(x,11) ^ RORu32(x,25))
+#define s0(x)       (RORu32(x, 7) ^ RORu32(x,18) ^ (x >> 3))
+#define s1(x)       (RORu32(x,17) ^ RORu32(x,19) ^ (x >> 10))
+
+#define H0         0x6a09e667
+#define H1         0xbb67ae85
+#define H2         0x3c6ef372
+#define H3         0xa54ff53a
+#define H4         0x510e527f
+#define H5         0x9b05688c
+#define H6         0x1f83d9ab
+#define H7         0x5be0cd19
+
+static inline void LOAD_OP(int I, u32 *W, const u8 *input)
+{
+	u32 t1 = input[(4 * I)] & 0xff;
+
+	t1 <<= 8;
+	t1 |= input[(4 * I) + 1] & 0xff;
+	t1 <<= 8;
+	t1 |= input[(4 * I) + 2] & 0xff;
+	t1 <<= 8;
+	t1 |= input[(4 * I) + 3] & 0xff;
+	W[I] = t1;
+}
+
+static inline void BLEND_OP(int I, u32 *W)
+{
+	W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16];
+}
+
+extern void sha256_init(void *ctx);
+extern void sha256_update(void *ctx, const u8 *data, unsigned int len);
+extern void sha256_final(void* ctx, u8 *out);
+
+#endif
diff -urN linux-2.4.30-pre2/kernel/ksyms.c linux-2.4.30-pre2-evfs/kernel/ksyms.c
--- linux-2.4.30-pre2/kernel/ksyms.c	Fri Feb 20 07:38:35 2004
+++ linux-2.4.30-pre2-evfs/kernel/ksyms.c	Sun Mar  6 15:07:05 2005
@@ -619,6 +619,25 @@
 /* debug */
 EXPORT_SYMBOL(dump_stack);
 
+/* symbols needed for evfs */
+extern void sys_rename();
+extern void sys_readlink();
+extern void sys_unlink();
+extern void sys_symlink();
+extern void sys_mknod();
+extern void sys_mknod();
+extern void sys_mkdir();
+extern void sys_rmdir();
+extern void sys_link();
+EXPORT_SYMBOL(sys_rename);
+EXPORT_SYMBOL(sys_readlink);
+EXPORT_SYMBOL(sys_unlink);
+EXPORT_SYMBOL(sys_symlink);
+EXPORT_SYMBOL(sys_mknod);
+EXPORT_SYMBOL(sys_mkdir);
+EXPORT_SYMBOL(sys_rmdir);
+EXPORT_SYMBOL(sys_link);
+
 /* To match ksyms with System.map */
 extern const char _end[];
 EXPORT_SYMBOL(_end);
--- ./fs/read_write.c.bad	Sat Mar  5 22:47:01 2005
+++ ./fs/read_write.c	Sun Mar  6 18:11:48 2005
@@ -23,6 +23,7 @@
 #include <linux/stat.h>
 #include <linux/fcntl.h>
 #include <linux/file.h>
+#include <linux/module.h>
 #include <linux/uio.h>
 #include <linux/smp_lock.h>
 #include <linux/dnotify.h>
@@ -61,6 +62,8 @@
 Einval:
 	return -EINVAL;
 }
+
+EXPORT_SYMBOL(rw_verify_area);
 
 loff_t generic_file_llseek(struct file *file, loff_t offset, int origin)
 {