diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure --exclude=autom4te.cache HEAD-vfs-clean/source/Makefile.in HEAD-vfs/source/Makefile.in
--- HEAD-vfs-clean/source/Makefile.in	Wed Mar 26 00:40:41 2003
+++ HEAD-vfs/source/Makefile.in	Wed Mar 26 00:26:31 2003
@@ -180,7 +180,7 @@ POPT_LIB_OBJ = lib/popt_common.o 
 UBIQX_OBJ = ubiqx/ubi_BinTree.o ubiqx/ubi_Cache.o ubiqx/ubi_SplayTree.o \
             ubiqx/ubi_dLinkList.o ubiqx/ubi_sLinkList.o 
 
-PARAM_OBJ = dynconfig.o param/loadparm.o param/params.o
+PARAM_OBJ = param/loadparm.o param/params.o dynconfig.o
 
 KRBCLIENT_OBJ = libads/kerberos.o
 
@@ -279,7 +279,7 @@ SAM_STATIC_MODULES = sam/sam_plugin.o sa
 SAM_OBJ = sam/account.o sam/get_set_account.o sam/get_set_group.o \
 		sam/get_set_domain.o sam/interface.o $(SAM_STATIC_MODULES)
 
-SAMTEST_OBJ = torture/samtest.o torture/cmd_sam.o $(PARAM_OBJ) $(SAM_OBJ) $(LIB_OBJ)  $(LIBSMB_OBJ) $(UBIQX_OBJ) $(READLINE_OBJ) lib/util_seaccess.o $(LIBADS_OBJ) $(KRBCLIENT_OBJ) $(PASSDB_OBJ) $(SECRETS_OBJ) $(GROUPDB_OBJ)
+SAMTEST_OBJ = torture/samtest.o torture/cmd_sam.o $(SAM_OBJ) $(LIB_OBJ) $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) $(READLINE_OBJ) lib/util_seaccess.o $(LIBADS_OBJ) $(KRBCLIENT_OBJ) $(PASSDB_OBJ) $(SECRETS_OBJ) $(GROUPDB_OBJ)
 
 GROUPDB_OBJ = groupdb/mapping.o
 
@@ -308,6 +308,12 @@ AUTH_OBJ = auth/auth.o @AUTH_STATIC@ aut
 
 MANGLE_OBJ = smbd/mangle.o smbd/mangle_hash.o smbd/mangle_map.o smbd/mangle_hash2.o
 
+VFS_AUDIT_OBJ = modules/vfs_audit.o
+VFS_EXTD_AUDIT_OBJ = modules/vfs_extd_audit.o
+VFS_RECYCLE_OBJ = modules/vfs_recycle.o
+VFS_NETATALK_OBJ = modules/vfs_netatalk.o
+VFS_FAKE_PERMS_OBJ = modules/vfs_fake_perms.o
+
 SMBD_OBJ_MAIN = smbd/server.o
 
 SMBD_OBJ_SRV = smbd/files.o smbd/chgpasswd.o smbd/connection.o \
@@ -372,8 +378,8 @@ WREPL_OBJ = $(WREPL_OBJ1)  $(PARAM_OBJ) 
 SWAT_OBJ1 = web/cgi.o web/diagnose.o web/startstop.o web/statuspage.o \
            web/swat.o web/neg_lang.o 
 
-SWAT_OBJ = $(SWAT_OBJ1) $(PARAM_OBJ) $(PRINTING_OBJ) $(LIBSMB_OBJ) \
-		   $(LOCKING_OBJ) $(PASSDB_OBJ) $(SECRETS_OBJ) $(KRBCLIENT_OBJ) \
+SWAT_OBJ = $(SWAT_OBJ1) $(PRINTING_OBJ) $(LIBSMB_OBJ) $(LOCKING_OBJ) \
+           $(PARAM_OBJ) $(PASSDB_OBJ) $(SECRETS_OBJ) $(KRBCLIENT_OBJ) \
 	   $(UBIQX_OBJ) $(LIB_OBJ) $(GROUPDB_OBJ) $(PLAINTEXT_AUTH_OBJ) \
 	   $(POPT_LIB_OBJ)
 
@@ -435,8 +441,8 @@ SMBWRAPPER_OBJ1 = smbwrapper/wrapped.o
 SMBWRAPPER_OBJ = $(SMBW_OBJ) $(SMBWRAPPER_OBJ1)
 
 LIBSMBCLIENT_OBJ = libsmb/libsmbclient.o libsmb/libsmb_compat.o \
-		   libsmb/libsmb_cache.o $(PARAM_OBJ) $(LIB_OBJ) \
-	  	   $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) $(UBIQX_OBJ)
+		   libsmb/libsmb_cache.o $(LIB_OBJ) \
+	  	   $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) $(PARAM_OBJ) $(UBIQX_OBJ)
 
 # This shared library is intended for linking with unit test programs
 # to test Samba internals.  It's called libbigballofmud.so to
@@ -444,7 +450,7 @@ LIBSMBCLIENT_OBJ = libsmb/libsmbclient.o
 
 LIBBIGBALLOFMUD_MAJOR = 0
 
-LIBBIGBALLOFMUD_OBJ = $(PARAM_OBJ) $(LIB_OBJ) $(UBIQX_OBJ) $(SECRETS_OBJ) \
+LIBBIGBALLOFMUD_OBJ = $(LIB_OBJ) $(UBIQX_OBJ) $(PARAM_OBJ) $(SECRETS_OBJ) \
 	$(LIBSMB_OBJ) $(LIBMSRPC_OBJ) $(RPC_PARSE_OBJ) $(PASSDB_OBJ) \
 	$(GROUPDB_OBJ) $(KRBCLIENT_OBJ)
 
@@ -461,9 +467,9 @@ NET_OBJ1 = utils/net.o utils/net_ads.o u
 	   utils/net_rpc_join.o utils/net_time.o utils/net_lookup.o \
 	   utils/net_cache.o
 
-NET_OBJ = $(NET_OBJ1) $(PARAM_OBJ) $(SECRETS_OBJ) $(LIBSMB_OBJ) \
+NET_OBJ = $(NET_OBJ1) $(SECRETS_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \
 	  $(RPC_PARSE_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
-	  $(KRBCLIENT_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) \
+	  $(PARAM_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) \
 	  $(LIBMSRPC_OBJ) $(LIBMSRPC_SERVER_OBJ) \
 	  $(LIBADS_OBJ) $(LIBADS_SERVER_OBJ) $(POPT_LIB_OBJ)
 
@@ -483,38 +489,33 @@ NMBLOOKUP_OBJ = utils/nmblookup.o $(PARA
 SMBTORTURE_OBJ1 = torture/torture.o torture/nbio.o torture/scanner.o torture/utable.o \
 		torture/denytest.o torture/mangle_test.o 
 
-SMBTORTURE_OBJ = $(SMBTORTURE_OBJ1) $(PARAM_OBJ) \
-	$(LIBSMB_OBJ) $(KRBCLIENT_OBJ) $(UBIQX_OBJ) $(LIB_OBJ)
+SMBTORTURE_OBJ = $(SMBTORTURE_OBJ1) \
+	$(LIBSMB_OBJ) $(KRBCLIENT_OBJ) $(PARAM_OBJ) $(UBIQX_OBJ) $(LIB_OBJ)
 
-MASKTEST_OBJ = torture/masktest.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \
+MASKTEST_OBJ = torture/masktest.o $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) $(PARAM_OBJ) \
                  $(UBIQX_OBJ) $(LIB_OBJ)
 
-MSGTEST_OBJ = torture/msgtest.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \
+MSGTEST_OBJ = torture/msgtest.o $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) $(PARAM_OBJ) \
                  $(UBIQX_OBJ) $(LIB_OBJ)
 
-LOCKTEST_OBJ = torture/locktest.o $(PARAM_OBJ) $(LOCKING_OBJ) $(KRBCLIENT_OBJ) \
-			   $(LIBSMB_OBJ) $(UBIQX_OBJ) $(LIB_OBJ)
+LOCKTEST_OBJ = torture/locktest.o $(LOCKING_OBJ) $(KRBCLIENT_OBJ) $(LIBSMB_OBJ) $(PARAM_OBJ) \
+                 $(UBIQX_OBJ) $(LIB_OBJ)
 
-NSSTEST_OBJ = torture/nsstest.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \
+NSSTEST_OBJ = torture/nsstest.o $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) $(PARAM_OBJ) \
                  $(UBIQX_OBJ) $(LIB_OBJ)
 
 VFSTEST_OBJ = torture/cmd_vfs.o torture/vfstest.o $(SMBD_OBJ_BASE) $(READLINE_OBJ)
 
-VFS_AUDIT_OBJ = modules/vfs_audit.o
-VFS_EXTD_AUDIT_OBJ = modules/vfs_extd_audit.o
-VFS_RECYCLE_OBJ = modules/vfs_recycle.o
-VFS_NETATALK_OBJ = modules/vfs_netatalk.o
-VFS_FAKE_PERMS_OBJ = modules/vfs_fake_perms.o
-
-LOCKTEST2_OBJ = torture/locktest2.o $(PARAM_OBJ) $(LOCKING_OBJ) $(LIBSMB_OBJ) \
-		$(KRBCLIENT_OBJ) $(UBIQX_OBJ) $(LIB_OBJ)
+LOCKTEST2_OBJ = torture/locktest2.o $(LOCKING_OBJ) $(LIBSMB_OBJ) \
+		$(KRBCLIENT_OBJ) $(PARAM_OBJ) \
+                 $(UBIQX_OBJ) $(LIB_OBJ)
 
-SMBCACLS_OBJ = utils/smbcacls.o $(PARAM_OBJ) $(LOCKING_OBJ) $(LIBSMB_OBJ) \
-			   $(KRBCLIENT_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) $(RPC_PARSE_OBJ) \
-			   $(PASSDB_GET_SET_OBJ) $(LIBMSRPC_OBJ) $(SECRETS_OBJ) \
-			   $(POPT_LIB_OBJ)
+SMBCACLS_OBJ = utils/smbcacls.o $(LOCKING_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \
+		$(PARAM_OBJ) \
+                 $(UBIQX_OBJ) $(LIB_OBJ) $(RPC_PARSE_OBJ) $(PASSDB_GET_SET_OBJ) \
+		 $(LIBMSRPC_OBJ) $(SECRETS_OBJ) $(POPT_LIB_OBJ)
 
-TALLOCTORT_OBJ = lib/talloctort.o $(PARAM_OBJ) $(LIB_OBJ) $(UBIQX_OBJ)
+TALLOCTORT_OBJ = lib/talloctort.o  $(LIB_OBJ) $(PARAM_OBJ) $(UBIQX_OBJ)
 
 RPCTORTURE_OBJ = torture/rpctorture.o \
              rpcclient/display.o \
@@ -528,7 +529,7 @@ RPCTORTURE_OBJ = torture/rpctorture.o \
 
 DEBUG2HTML_OBJ = utils/debug2html.o ubiqx/debugparse.o
 
-SMBFILTER_OBJ = utils/smbfilter.o $(PARAM_OBJ) $(LIBSMB_OBJ) \
+SMBFILTER_OBJ = utils/smbfilter.o $(LIBSMB_OBJ) $(PARAM_OBJ) \
                  $(UBIQX_OBJ) $(LIB_OBJ) $(KRBCLIENT_OBJ) 
 
 PROTO_OBJ = $(SMBD_OBJ_MAIN) \
@@ -1119,8 +1120,8 @@ installclientlib:
 
 # Python extensions
 
-PYTHON_OBJS = $(PARAM_OBJ) $(LIB_OBJ) $(LIBSMB_OBJ) $(RPC_PARSE_OBJ) \
-	$(UBIQX_OBJ) $(LIBMSRPC_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
+PYTHON_OBJS = $(LIB_OBJ) $(LIBSMB_OBJ) $(RPC_PARSE_OBJ) $(UBIQX_OBJ) \
+	$(PARAM_OBJ) $(LIBMSRPC_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
 	$(SECRETS_OBJ) $(KRBCLIENT_OBJ)
 
 python_ext: $(PYTHON_OBJS)
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure --exclude=autom4te.cache HEAD-vfs-clean/source/configure.in HEAD-vfs/source/configure.in
--- HEAD-vfs-clean/source/configure.in	Wed Mar 26 00:40:42 2003
+++ HEAD-vfs/source/configure.in	Wed Mar 26 00:38:39 2003
@@ -3390,7 +3390,7 @@ SMB_MODULE(vfs_recycle, \$(VFS_RECYCLE_O
 SMB_MODULE(vfs_audit, \$(VFS_AUDIT_OBJ), bin/audit.so, VFS)
 SMB_MODULE(vfs_extd_audit, \$(VFS_EXTD_AUDIT_OBJ), bin/extd_audit.so, VFS)
 SMB_MODULE(vfs_fake_perms, \$(VFS_FAKE_PERMS_OBJ), bin/fake_perms.so, VFS)
-SMB_MODULE(vfs_netatalk, \$(VFS_NETATALK), bin/netatalk.so, VFS)
+SMB_MODULE(vfs_netatalk, \$(VFS_NETATALK_OBJ), bin/netatalk.so, VFS)
 SMB_SUBSYSTEM(VFS)
 
 AC_DEFINE_UNQUOTED(STRING_STATIC_MODULES, "$string_static_modules", [String list of builtin modules])
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure --exclude=autom4te.cache HEAD-vfs-clean/source/include/smb.h HEAD-vfs/source/include/smb.h
--- HEAD-vfs-clean/source/include/smb.h	Sun Mar 23 00:48:02 2003
+++ HEAD-vfs/source/include/smb.h	Tue Mar 25 20:00:58 2003
@@ -431,15 +431,6 @@ typedef struct
 #include "smb_acls.h"
 #include "vfs.h"
 
-typedef struct smb_vfs_handle_struct
-{
-    void *data;
-    /* Handle on dlopen() call */
-    void *handle;
-    struct smb_vfs_handle_struct  *next, *prev;
-    
-} smb_vfs_handle_struct;
-
 typedef struct connection_struct
 {
 	struct connection_struct *next, *prev;
@@ -458,7 +449,8 @@ typedef struct connection_struct
 	char *origpath;
 
 	struct vfs_ops vfs_ops;                   /* Filesystem operations */
-	struct smb_vfs_handle_struct *vfs_private;
+	struct vfs_ops vfs_opaque_ops;                   /* OPAQUE Filesystem operations */
+	struct smb_vfs_handle_struct *vfs_handles;
 
 	char *user; /* name of user who *opened* this connection */
 	uid_t uid; /* uid of user who *opened* this connection */
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure --exclude=autom4te.cache HEAD-vfs-clean/source/include/vfs.h HEAD-vfs/source/include/vfs.h
--- HEAD-vfs-clean/source/include/vfs.h	Tue Mar 25 20:13:55 2003
+++ HEAD-vfs/source/include/vfs.h	Wed Mar 26 00:36:33 2003
@@ -335,4 +335,37 @@ typedef struct _vfs_op_tuple {
     This prototype will be available via include/proto.h
 */
 
+
+typedef struct smb_vfs_handle_struct {
+	void *data;
+	struct vfs_ops vfs_def_ops;
+	int vfs_num;
+	struct smb_vfs_handle_struct  *next, *prev;
+} smb_vfs_handle_struct;
+
+
+#define VFS_MODULE_NUMBER static int vfs_module_number = -1
+
+#define VFS_DEFAULT_OPS	struct vfs_ops *default_vfs_ops = NULL
+
+#define VFS_HANDLE_GET_OPS(conn, ret) \
+	if ((default_vfs_ops=vfs_handle_get_ops(conn,vfs_module_number))==NULL) { \
+		DEBUG(0,("%s() failed to get default_vfs_ops!\n",FUNCTION_MACRO)); \
+	ret; \
+}
+
+#define VFS_HANDLE_GET_DATA(datap, conn, type, ret) \
+	if ((datap=(type)vfs_handle_get_data(conn,vfs_module_number))==NULL) { \
+		DEBUG(0,("%s() failed to get vfs_handle->data!\n",FUNCTION_MACRO)); \
+	ret; \
+}
+
+#define VFS_HANDLE_SET_DATA(datap, conn, type, ret) \
+	if (datap!=(type)vfs_handle_set_data(conn,(void *)datap, vfs_module_number)) { \
+		DEBUG(0,("%s() failed to set vfs_handle->data!\n",FUNCTION_MACRO)); \
+	ret; \
+}
+
+#define VFS_OP(x) ((void *) x)
+			 
 #endif /* _VFS_H */
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure --exclude=autom4te.cache HEAD-vfs-clean/source/modules/vfs_recycle.c HEAD-vfs/source/modules/vfs_recycle.c
--- HEAD-vfs-clean/source/modules/vfs_recycle.c	Tue Mar 25 20:13:55 2003
+++ HEAD-vfs/source/modules/vfs_recycle.c	Wed Mar 26 00:36:46 2003
@@ -6,6 +6,7 @@
  * Copyright (C) 2002, Alexander Bokovoy - cascaded VFS adoption,
  * Copyright (C) 2002, Juergen Hasch - added some options.
  * Copyright (C) 2002, Simo Sorce
+ * Copyright (C) 2002, Stefan (metze) Metzmacher
  *
  * 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
@@ -31,45 +32,12 @@ static int vfs_recycle_debug_level = DBG
 #undef DBGC_CLASS
 #define DBGC_CLASS vfs_recycle_debug_level
 
-static const char *delimiter = "|";		/* delimiter for options */
-
-/* One per connection */
-
-typedef struct recycle_bin_struct
-{
-	TALLOC_CTX *mem_ctx;
-	char	*repository;		/* name of the recycle bin directory */
-	BOOL	keep_dir_tree;		/* keep directory structure of deleted file in recycle bin */
-	BOOL	versions;		/* create versions of deleted files with identical name */
-	BOOL	touch;			/* touch access date of deleted file */
-	char	*exclude;		/* which files to exclude */
-	char	*exclude_dir;		/* which directories to exclude */
-	char	*noversions;		/* which files to exclude from versioning */
-	SMB_OFF_T maxsize;		/* maximum file size to be saved */
-} recycle_bin_struct;
-
-typedef struct recycle_bin_connections {
-	int conn;
-	recycle_bin_struct *data;
-	struct recycle_bin_connections *next;
-} recycle_bin_connections;
-
-typedef struct recycle_bin_private_data {
-	TALLOC_CTX *mem_ctx;
-	recycle_bin_connections *conns;
-} recycle_bin_private_data;
-
-struct smb_vfs_handle_struct *recycle_bin_private_handle;
-
-/* VFS operations */
-static struct vfs_ops default_vfs_ops;   /* For passthrough operation */
-
+VFS_MODULE_NUMBER;
+ 
 static int recycle_connect(struct connection_struct *conn, const char *service, const char *user);
 static void recycle_disconnect(struct connection_struct *conn);
 static int recycle_unlink(connection_struct *, const char *);
 
-#define VFS_OP(x) ((void *) x)
-
 static vfs_op_tuple recycle_ops[] = {
 
 	/* Disk operations */
@@ -82,187 +50,131 @@ static vfs_op_tuple recycle_ops[] = {
 	{NULL,				SMB_VFS_OP_NOOP,	SMB_VFS_LAYER_NOOP}
 };
 
-/**
- * VFS initialisation function.
- *
- * @retval initialised vfs_op_tuple array
- **/
-static vfs_op_tuple *recycle_init(const struct vfs_ops *def_vfs_ops,
-			struct smb_vfs_handle_struct *vfs_handle)
+static int recycle_connect(struct connection_struct *conn, const char *service, const char *user)
 {
-	TALLOC_CTX *mem_ctx = NULL;
+	VFS_DEFAULT_OPS;
 
-	DEBUG(10, ("Initializing VFS module recycle\n"));
-	memcpy(&default_vfs_ops, def_vfs_ops, sizeof(struct vfs_ops));
-	vfs_recycle_debug_level = debug_add_class("vfs_recycle_bin");
-	if (vfs_recycle_debug_level == -1) {
-		vfs_recycle_debug_level = DBGC_VFS;
-		DEBUG(0, ("vfs_recycle: Couldn't register custom debugging class!\n"));
-	} else {
-		DEBUG(0, ("vfs_recycle: Debug class number of 'vfs_recycle': %d\n", vfs_recycle_debug_level));
-	}
+	VFS_HANDLE_GET_OPS(conn, return -1);
 
-	recycle_bin_private_handle = vfs_handle;
-	if (!(mem_ctx = talloc_init("recycle bin data"))) {
-		DEBUG(0, ("Failed to allocate memory in VFS module recycle_bin\n"));
-		return NULL;
-	}
+	DEBUG(10,("recycle_connect() connect to service[%s] as user[%s].\n",
+		service,user));
 
-	recycle_bin_private_handle->data = talloc(mem_ctx, sizeof(recycle_bin_private_data));
-	if (recycle_bin_private_handle->data == NULL) {
-		DEBUG(0, ("Failed to allocate memory in VFS module recycle_bin\n"));
-		return NULL;
-	}
-	((recycle_bin_private_data *)(recycle_bin_private_handle->data))->mem_ctx = mem_ctx;
-	((recycle_bin_private_data *)(recycle_bin_private_handle->data))->conns = NULL;
+	return default_vfs_ops->connect(conn, service, user);		
+}
+
+static void recycle_disconnect(struct connection_struct *conn)
+{
+	VFS_DEFAULT_OPS;
 
-	return recycle_ops;
+	VFS_HANDLE_GET_OPS(conn, return);
+
+	DEBUG(10,("recycle_disconnect() connect to service[%s].\n",
+		lp_servicename(SNUM(conn))));
+
+	default_vfs_ops->disconnect(conn);	
 }
 
-static int recycle_connect(struct connection_struct *conn, const char *service, const char *user)
+static const char *recycle_repository(struct connection_struct *conn)
 {
-	TALLOC_CTX *ctx = NULL;
-	recycle_bin_struct *recbin;
-	recycle_bin_connections *recconn;
-	recycle_bin_connections *recconnbase;
-	recycle_bin_private_data *recdata;
-	char *tmp_str;
+	const char *tmp_str = NULL;
+	
+	tmp_str = lp_parm_string(SNUM(conn), "recycle_bin", "repository");
+//	tmp_str = lp_parm_string(SNUM(conn), "recycle_bin", "repository",".recycle");
 
-	DEBUG(10, ("Called for service %s (%d) as user %s\n", service, SNUM(conn), user));
+	DEBUG(10, ("recycle_bin: repository = %s\n", tmp_str));
+	
+	return tmp_str;
+}
 
-	if (recycle_bin_private_handle)
-		recdata = (recycle_bin_private_data *)(recycle_bin_private_handle->data);
-	else {
-		DEBUG(0, ("Recycle bin not initialized!\n"));
-		return -1;
-	}
+static BOOL recycle_keep_dir_tree(struct connection_struct *conn)
+{
+	BOOL ret;
+	
+	ret = lp_parm_bool(SNUM(conn), "recycle_bin", "keeptree");
+//	ret = lp_parm_bool(SNUM(conn), "recycle_bin", "keeptree", False);
 
-	if (!(ctx = talloc_init("recycle bin connection"))) {
-		DEBUG(0, ("Failed to allocate memory in VFS module recycle_bin\n"));
-		return -1;
-	}
-
-	recbin = talloc(ctx, sizeof(recycle_bin_struct));
-	if (recbin == NULL) {
-		DEBUG(0, ("Failed to allocate memory in VFS module recycle_bin\n"));
-		return -1;
-	}
-	recbin->mem_ctx = ctx;
-
-	/* Set defaults */
-	recbin->repository = talloc_strdup(recbin->mem_ctx, ".recycle");
-	ALLOC_CHECK(recbin->repository, error);
-	recbin->keep_dir_tree = False;
-	recbin->versions = False;
-	recbin->touch = False;
-	recbin->exclude = "";
-	recbin->exclude_dir = "";
-	recbin->noversions = "";
-	recbin->maxsize = 0;
-
-	/* parse configuration options */
-	if ((tmp_str = lp_parm_string(SNUM(conn), "vfs_recycle_bin", "repository")) != NULL) {
-		recbin->repository = talloc_sub_conn(recbin->mem_ctx, conn, tmp_str);
-		ALLOC_CHECK(recbin->repository, error);
-		trim_string(recbin->repository, "/", "/");
-		DEBUG(5, ("recycle.bin: repository = %s\n", recbin->repository));
-	}
-	
-	recbin->keep_dir_tree = lp_parm_bool(SNUM(conn), "vfs_recycle_bin", "keeptree");
-	DEBUG(5, ("recycle.bin: keeptree = %d\n", recbin->keep_dir_tree));
-	
-	recbin->versions = lp_parm_bool(SNUM(conn), "vfs_recycle_bin", "versions");
-	DEBUG(5, ("recycle.bin: versions = %d\n", recbin->versions));
-	
-	recbin->touch = lp_parm_bool(SNUM(conn), "vfs_recycle_bin", "touch");
-	DEBUG(5, ("recycle.bin: touch = %d\n", recbin->touch));
-
-	recbin->maxsize = lp_parm_ulong(SNUM(conn), "vfs_recycle_bin", "maxsize");
-	if (recbin->maxsize == 0) {
-		recbin->maxsize = -1;
-		DEBUG(5, ("recycle.bin: maxsize = -infinite-\n"));
-	} else {
-		DEBUG(5, ("recycle.bin: maxsize = %ld\n", (long int)recbin->maxsize));
-	}
+	DEBUG(10, ("recycle_bin: keeptree = %s\n", ret?"True":"False"));
+	
+	return ret;
+}
 
-	if ((tmp_str = lp_parm_string(SNUM(conn), "vfs_recycle_bin", "exclude")) != NULL) {
-		recbin->exclude = talloc_strdup(recbin->mem_ctx, tmp_str);
-		ALLOC_CHECK(recbin->exclude, error);
-		DEBUG(5, ("recycle.bin: exclude = %s\n", recbin->exclude));
-	}
-	if ((tmp_str = lp_parm_string(SNUM(conn), "vfs_recycle_bin", "exclude_dir")) != NULL) {
-		recbin->exclude_dir = talloc_strdup(recbin->mem_ctx, tmp_str);
-		ALLOC_CHECK(recbin->exclude_dir, error);
-		DEBUG(5, ("recycle.bin: exclude_dir = %s\n", recbin->exclude_dir));
-	}
-	if ((tmp_str = lp_parm_string(SNUM(conn), "vfs_recycle_bin", "noversions")) != NULL) {
-		recbin->noversions = talloc_strdup(recbin->mem_ctx, tmp_str);
-		ALLOC_CHECK(recbin->noversions, error);
-		DEBUG(5, ("recycle.bin: noversions = %s\n", recbin->noversions));
-	}
-
-	recconn = talloc(recdata->mem_ctx, sizeof(recycle_bin_connections));
-	if (recconn == NULL) {
-		DEBUG(0, ("Failed to allocate memory in VFS module recycle_bin\n"));
-		goto error;
-	}
-	recconn->conn = SNUM(conn);
-	recconn->data = recbin;
-	recconn->next = NULL;
-	if (recdata->conns) {
-		recconnbase = recdata->conns;
-		while (recconnbase->next != NULL) recconnbase = recconnbase->next;
-		recconnbase->next = recconn;
-	} else {
-		recdata->conns = recconn;
-	}
-	return default_vfs_ops.connect(conn, service, user);
+static BOOL recycle_versions(struct connection_struct *conn)
+{
+	BOOL ret;
+
+	ret = lp_parm_bool(SNUM(conn), "recycle_bin", "versions");	
+//	ret = lp_parm_bool(SNUM(conn), "recycle_bin", "versions", False);
 
-error:
-	talloc_destroy(ctx);
-	return -1;
+	DEBUG(10, ("recycle_bin: versions = %s\n", ret?"True":"False"));
+	
+	return ret;
 }
 
-static void recycle_disconnect(struct connection_struct *conn)
+static BOOL recycle_touch(struct connection_struct *conn)
 {
-	recycle_bin_private_data *recdata;
-	recycle_bin_connections *recconn;
+	BOOL ret;
+	
+	ret = lp_parm_bool(SNUM(conn), "recycle_bin", "touch");
+//	ret = lp_parm_bool(SNUM(conn), "recycle_bin", "touch", False);
 
-	DEBUG(10, ("Disconnecting VFS module recycle bin\n"));
+	DEBUG(10, ("recycle_bin: touch = %s\n", ret?"True":"False"));
+	
+	return ret;
+}
 
-	if (recycle_bin_private_handle)
-		recdata = (recycle_bin_private_data *)(recycle_bin_private_handle->data);
-	else {
-		DEBUG(0, ("Recycle bin not initialized!\n"));
-		return;
-	}
+static const char **recycle_exclude(struct connection_struct *conn)
+{
+	const char **tmp_lp;
+	
+	tmp_lp = lp_parm_string_list(SNUM(conn), "recycle_bin", "exclude", NULL);
 
-	if (recdata) {
-		if (recdata->conns) {
-			if (recdata->conns->conn == SNUM(conn)) {
-				talloc_destroy(recdata->conns->data->mem_ctx);
-				recdata->conns = recdata->conns->next;
-			} else {
-				recconn = recdata->conns;
-				while (recconn->next) {
-					if (recconn->next->conn == SNUM(conn)) {
-						talloc_destroy(recconn->next->data->mem_ctx);
-						recconn->next = recconn->next->next;
-						break;
-					}
-					recconn = recconn->next;
-				}
-			}
-		}
-	}
-	default_vfs_ops.disconnect(conn);
+	DEBUG(10, ("recycle_bin: exclude = %s ...\n", tmp_lp?*tmp_lp:""));
+	
+	return tmp_lp;
+}
+
+static const char **recycle_exclude_dir(struct connection_struct *conn)
+{
+	const char **tmp_lp;
+	
+	tmp_lp = lp_parm_string_list(SNUM(conn), "recycle_bin", "exclude_dir", NULL);
+
+	DEBUG(10, ("recycle_bin: exclude_dir = %s ...\n", tmp_lp?*tmp_lp:""));
+	
+	return tmp_lp;
+}
+
+static const char **recycle_noversions(struct connection_struct *conn)
+{
+	const char **tmp_lp;
+	
+	tmp_lp = lp_parm_string_list(SNUM(conn), "recycle_bin", "noversions", NULL);
+
+	DEBUG(10, ("recycle_bin: noversions = %s\n", tmp_lp?*tmp_lp:""));
+	
+	return tmp_lp;
+}
+
+static int recycle_maxsize(struct connection_struct *conn)
+{
+	int maxsize;
+	
+	maxsize = lp_parm_int(SNUM(conn), "recycle_bin", "maxsize");
+//	maxsize = lp_parm_int(SNUM(conn), "recycle_bin", "maxsize", 0);
+
+	DEBUG(10, ("recycle_bin: maxsize = %d\n", maxsize));
+	
+	return maxsize;
 }
 
 static BOOL recycle_directory_exist(connection_struct *conn, const char *dname)
 {
+	VFS_DEFAULT_OPS;
 	SMB_STRUCT_STAT st;
 
-	if (default_vfs_ops.stat(conn, dname, &st) == 0) {
+	VFS_HANDLE_GET_OPS(conn, return False);
+
+	if (default_vfs_ops->stat(conn, dname, &st) == 0) {
 		if (S_ISDIR(st.st_mode)) {
 			return True;
 		}
@@ -273,9 +185,12 @@ static BOOL recycle_directory_exist(conn
 
 static BOOL recycle_file_exist(connection_struct *conn, const char *fname)
 {
+	VFS_DEFAULT_OPS;
 	SMB_STRUCT_STAT st;
 
-	if (default_vfs_ops.stat(conn, fname, &st) == 0) {
+	VFS_HANDLE_GET_OPS(conn, return False);
+
+	if (default_vfs_ops->stat(conn, fname, &st) == 0) {
 		if (S_ISREG(st.st_mode)) {
 			return True;
 		}
@@ -292,11 +207,16 @@ static BOOL recycle_file_exist(connectio
  **/
 static SMB_OFF_T recycle_get_file_size(connection_struct *conn, const char *fname)
 {
+	VFS_DEFAULT_OPS;
 	SMB_STRUCT_STAT st;
-	if (default_vfs_ops.stat(conn, fname, &st) != 0) {
-		DEBUG(0,("recycle.bin: stat for %s returned %s\n", fname, strerror(errno)));
+	
+	VFS_HANDLE_GET_OPS(conn, return (SMB_OFF_T)-1);
+
+	if (default_vfs_ops->stat(conn, fname, &st) != 0) {
+		DEBUG(0,("recycle_bin: stat for %s returned %s\n", fname, strerror(errno)));
 		return (SMB_OFF_T)0;
 	}
+
 	return(st.st_size);
 }
 
@@ -308,6 +228,7 @@ static SMB_OFF_T recycle_get_file_size(c
  **/
 static BOOL recycle_create_dir(connection_struct *conn, const char *dname)
 {
+	VFS_DEFAULT_OPS;
 	int len;
 	mode_t mode;
 	char *new_dir = NULL;
@@ -316,6 +237,8 @@ static BOOL recycle_create_dir(connectio
 	char *tok_str;
 	BOOL ret = False;
 
+	VFS_HANDLE_GET_OPS(conn, return False);
+
 	mode = S_IREAD | S_IWRITE | S_IEXEC;
 
 	tmp_str = strdup(dname);
@@ -334,7 +257,7 @@ static BOOL recycle_create_dir(connectio
 			DEBUG(10, ("recycle.bin: dir %s already exists\n", new_dir));
 		else {
 			DEBUG(5, ("recycle.bin: creating new dir %s\n", new_dir));
-			if (default_vfs_ops.mkdir(conn, new_dir, mode) != 0) {
+			if (default_vfs_ops->mkdir(conn, new_dir, mode) != 0) {
 				DEBUG(1,("recycle.bin: mkdir failed for %s with error: %s\n", new_dir, strerror(errno)));
 				ret = False;
 				goto done;
@@ -356,30 +279,21 @@ done:
  * @param needle string to be matched exactly to haystack
  * @return True if found
  **/
-static BOOL checkparam(const char *haystack, const char *needle)
+static BOOL checkparam(const char **haystack_list, const char *needle)
 {
-	char *token;
-	char *tok_str;
-	char *tmp_str;
-	BOOL ret = False;
+	int i;
 
-	if (haystack == NULL || strlen(haystack) == 0 || needle == NULL || strlen(needle) == 0) {
+	if (haystack_list == NULL || strlen(*haystack_list) == 0 || needle == NULL || strlen(needle) == 0) {
 		return False;
 	}
 
-	tmp_str = strdup(haystack);
-	ALLOC_CHECK(tmp_str, done);
-	token = tok_str = tmp_str;
-
-	for(token = strtok(tok_str, delimiter); token; token = strtok(NULL, delimiter)) {
-		if(strcmp(token, needle) == 0) {
-			ret = True;
-			goto done;
+	for(i=0; haystack_list[i] ; i++) {
+		if(strequal(haystack_list[i], needle)) {
+			return True;
 		}
 	}
-done:
-	SAFE_FREE(tmp_str);
-	return ret;
+
+	return False;
 }
 
 /**
@@ -388,42 +302,36 @@ done:
  * @param needle string to be matched exectly to haystack including pattern matching
  * @return True if found
  **/
-static BOOL matchparam(const char *haystack, const char *needle)
+static BOOL matchparam(const char **haystack_list, const char *needle)
 {
-	char *token;
-	char *tok_str;
-	char *tmp_str;
-	BOOL ret = False;
+	int i;
 
-	if (haystack == NULL || strlen(haystack) == 0 || needle == NULL || strlen(needle) == 0) {
+	if (haystack_list == NULL || strlen(*haystack_list) == 0 || needle == NULL || strlen(needle) == 0) {
 		return False;
 	}
 
-	tmp_str = strdup(haystack);
-	ALLOC_CHECK(tmp_str, done);
-	token = tok_str = tmp_str;
-
-	for(token = strtok(tok_str, delimiter); token; token = strtok(NULL, delimiter)) {
-		if (!unix_wild_match(token, needle)) {
-			ret = True;
-			goto done;
+	for(i=0; haystack_list[i] ; i++) {
+		if(!unix_wild_match((char *)haystack_list[i], (char *)needle)) {
+			return True;
 		}
 	}
-done:
-	SAFE_FREE(tmp_str);
-	return ret;
+
+	return False;
 }
 
 /**
  * Touch access date
  **/
-static void recycle_touch(connection_struct *conn, const char *fname)
+static void recycle_do_touch(connection_struct *conn, const char *fname)
 {
+	VFS_DEFAULT_OPS;
 	SMB_STRUCT_STAT st;
 	struct utimbuf tb;
 	time_t currtime;
 
-	if (default_vfs_ops.stat(conn, fname, &st) != 0) {
+	VFS_HANDLE_GET_OPS(conn, return);
+	
+	if (default_vfs_ops->stat(conn, fname, &st) != 0) {
 		DEBUG(0,("recycle.bin: stat for %s returned %s\n", fname, strerror(errno)));
 		return;
 	}
@@ -431,57 +339,45 @@ static void recycle_touch(connection_str
 	tb.actime = currtime;
 	tb.modtime = st.st_mtime;
 
-	if (default_vfs_ops.utime(conn, fname, &tb) == -1 )
+	if (default_vfs_ops->utime(conn, fname, &tb) == -1 ) {
 		DEBUG(0, ("recycle.bin: touching %s failed, reason = %s\n", fname, strerror(errno)));
 	}
+}
 
 /**
  * Check if file should be recycled
  **/
 static int recycle_unlink(connection_struct *conn, const char *file_name)
 {
-	recycle_bin_private_data *recdata;
-	recycle_bin_connections *recconn;
-	recycle_bin_struct *recbin;
+	VFS_DEFAULT_OPS;
 	char *path_name = NULL;
        	char *temp_name = NULL;
 	char *final_name = NULL;
 	const char *base;
+	char *repository = NULL;
 	int i;
-/*	SMB_BIG_UINT dfree, dsize, bsize;	*/
+	int maxsize;
 	SMB_OFF_T file_size; /* space_avail;	*/
 	BOOL exist;
 	int rc = -1;
 
-	recbin = NULL;
-	if (recycle_bin_private_handle) {
-		recdata = (recycle_bin_private_data *)(recycle_bin_private_handle->data);
-		if (recdata) {
-			if (recdata->conns) {
-				recconn = recdata->conns;
-				while (recconn && recconn->conn != SNUM(conn)) recconn = recconn->next;
-				if (recconn != NULL) {
-					recbin = recconn->data;
-				}
-			}
-		}
-	}
-	if (recbin == NULL) {
-		DEBUG(0, ("Recycle bin not initialized!\n"));
-		rc = default_vfs_ops.unlink(conn, file_name);
-		goto done;
-	}
+	VFS_HANDLE_GET_OPS(conn, return -1);
 
-	if(!recbin->repository || *(recbin->repository) == '\0') {
-		DEBUG(3, ("Recycle path not set, purging %s...\n", file_name));
-		rc = default_vfs_ops.unlink(conn, file_name);
+	repository = alloc_sub_conn(conn, (char *)recycle_repository(conn));
+	ALLOC_CHECK(repository, done);
+	/* shouldn't we allow absolute path names here? --metze */
+	trim_string(repository, "/", "/");
+	
+	if(!repository || *(repository) == '\0') {
+		DEBUG(3, ("recycle_bin: repository path not set, purging %s...\n", file_name));
+		rc = default_vfs_ops->unlink(conn, file_name);
 		goto done;
 	}
 
 	/* we don't recycle the recycle bin... */
-	if (strncmp(file_name, recbin->repository, strlen(recbin->repository)) == 0) {
-		DEBUG(3, ("File is within recycling bin, unlinking ...\n"));
-		rc = default_vfs_ops.unlink(conn, file_name);
+	if (strncmp(file_name, repository, strlen(repository)) == 0) {
+		DEBUG(3, ("recycle_bin: File is within recycling bin, unlinking ...\n"));
+		rc = default_vfs_ops->unlink(conn, file_name);
 		goto done;
 	}
 
@@ -490,8 +386,8 @@ static int recycle_unlink(connection_str
 	 *   --- simo
 	 *
 	if(fsize == 0) {
-		DEBUG(3, ("File %s is empty, purging...\n", file_name));
-		rc = default_vfs_ops.unlink(conn,file_name);
+		DEBUG(3, ("recycle_bin: File %s is empty, purging...\n", file_name));
+		rc = default_vfs_ops->unlink(conn,file_name);
 		goto done;
 	}
 	 */
@@ -500,20 +396,21 @@ static int recycle_unlink(connection_str
 	 * not greater then maxsize, not the size of the single file, also it is better
 	 * to remove older files
 	 */
-	if(recbin->maxsize > 0 && file_size > recbin->maxsize) {
-		DEBUG(3, ("File %s exceeds maximum recycle size, purging... \n", file_name));
-		rc = default_vfs_ops.unlink(conn, file_name);
+	maxsize = recycle_maxsize(conn);
+	if(maxsize > 0 && file_size > maxsize) {
+		DEBUG(3, ("recycle_bin: File %s exceeds maximum recycle size, purging... \n", file_name));
+		rc = default_vfs_ops->unlink(conn, file_name);
 		goto done;
 	}
 
 	/* FIXME: this is wrong: moving files with rename does not change the disk space
 	 * allocation
 	 *
-	space_avail = default_vfs_ops.disk_free(conn, ".", True, &bsize, &dfree, &dsize) * 1024L;
+	space_avail = default_vfs_ops->disk_free(conn, ".", True, &bsize, &dfree, &dsize) * 1024L;
 	DEBUG(5, ("space_avail = %Lu, file_size = %Lu\n", space_avail, file_size));
 	if(space_avail < file_size) {
-		DEBUG(3, ("Not enough diskspace, purging file %s\n", file_name));
-		rc = default_vfs_ops.unlink(conn, file_name);
+		DEBUG(3, ("recycle_bin: Not enough diskspace, purging file %s\n", file_name));
+		rc = default_vfs_ops->unlink(conn, file_name);
 		goto done;
 	}
 	 */
@@ -532,13 +429,13 @@ static int recycle_unlink(connection_str
 		base++;
 	}
 
-	DEBUG(10, ("recycle.bin: fname = %s\n", file_name));	/* original filename with path */
-	DEBUG(10, ("recycle.bin: fpath = %s\n", path_name));	/* original path */
-	DEBUG(10, ("recycle.bin: base = %s\n", base));		/* filename without path */
-
-	if (matchparam(recbin->exclude, base)) {
-		DEBUG(3, ("recycle.bin: file %s is excluded \n", base));
-		rc = default_vfs_ops.unlink(conn, file_name);
+	DEBUG(10, ("recycle_bin: fname = %s\n", file_name));	/* original filename with path */
+	DEBUG(10, ("recycle_bin: fpath = %s\n", path_name));	/* original path */
+	DEBUG(10, ("recycle_bin: base = %s\n", base));		/* filename without path */
+
+	if (matchparam(recycle_exclude(conn), base)) {
+		DEBUG(3, ("recycle_bin: file %s is excluded \n", base));
+		rc = default_vfs_ops->unlink(conn, file_name);
 		goto done;
 	}
 
@@ -546,29 +443,29 @@ static int recycle_unlink(connection_str
 	 * we shoud check for every level 1, 1/2, 1/2/3, 1/2/3/4 .... 
 	 * 	---simo
 	 */
-	if (checkparam(recbin->exclude_dir, path_name)) {
-		DEBUG(3, ("recycle.bin: directory %s is excluded \n", path_name));
-		rc = default_vfs_ops.unlink(conn, file_name);
+	if (checkparam(recycle_exclude_dir(conn), path_name)) {
+		DEBUG(3, ("recycle_bin: directory %s is excluded \n", path_name));
+		rc = default_vfs_ops->unlink(conn, file_name);
 		goto done;
 	}
 
-	temp_name = (char *)strdup(recbin->repository);
+	temp_name = (char *)strdup(repository);
 	ALLOC_CHECK(temp_name, done);
 
 	/* see if we need to recreate the original directory structure in the recycle bin */
-	if (recbin->keep_dir_tree == True) {
+	if (recycle_keep_dir_tree(conn) == True) {
 		safe_strcat(temp_name, "/", PATH_MAX - 1);
 		safe_strcat(temp_name, path_name, PATH_MAX - 1);
 	}
 
 	exist = recycle_directory_exist(conn, temp_name);
 	if (exist) {
-		DEBUG(10, ("recycle.bin: Directory already exists\n"));
+		DEBUG(10, ("recycle_bin: Directory already exists\n"));
 	} else {
-		DEBUG(10, ("recycle.bin: Creating directory %s\n", temp_name));
+		DEBUG(10, ("recycle_bin: Creating directory %s\n", temp_name));
 		if (recycle_create_dir(conn, temp_name) == False) {
-			DEBUG(3, ("Could not create directory, purging %s...\n", file_name));
-			rc = default_vfs_ops.unlink(conn, file_name);
+			DEBUG(3, ("recycle_bin: Could not create directory, purging %s...\n", file_name));
+			rc = default_vfs_ops->unlink(conn, file_name);
 			goto done;
 		}
 	}
@@ -580,10 +477,10 @@ static int recycle_unlink(connection_str
 
 	/* check if we should delete file from recycle bin */
 	if (recycle_file_exist(conn, final_name)) {
-		if (recbin->versions == False || matchparam(recbin->noversions, base) == True) {
-			DEBUG(3, ("recycle.bin: Removing old file %s from recycle bin\n", final_name));
-			if (default_vfs_ops.unlink(conn, final_name) != 0) {
-				DEBUG(1, ("recycle.bin: Error deleting old file: %s\n", strerror(errno)));
+		if (recycle_versions(conn) == False || matchparam(recycle_noversions(conn), base) == True) {
+			DEBUG(3, ("recycle_bin: Removing old file %s from recycle bin\n", final_name));
+			if (default_vfs_ops->unlink(conn, final_name) != 0) {
+				DEBUG(1, ("recycle_bin: Error deleting old file: %s\n", strerror(errno)));
 			}
 		}
 	}
@@ -594,26 +491,27 @@ static int recycle_unlink(connection_str
 		snprintf(final_name, PATH_MAX, "%s/Copy #%d of %s", temp_name, i++, base);
 	}
 
-	DEBUG(10, ("recycle.bin: Moving %s to %s\n", file_name, final_name));
-	rc = default_vfs_ops.rename(conn, file_name, final_name);
+	DEBUG(10, ("recycle_bin: Moving %s to %s\n", file_name, final_name));
+	rc = default_vfs_ops->rename(conn, file_name, final_name);
 	if (rc != 0) {
-		DEBUG(3, ("recycle.bin: Move error %d (%s), purging file %s (%s)\n", errno, strerror(errno), file_name, final_name));
-		rc = default_vfs_ops.unlink(conn, file_name);
+		DEBUG(3, ("recycle_bin: Move error %d (%s), purging file %s (%s)\n", errno, strerror(errno), file_name, final_name));
+		rc = default_vfs_ops->unlink(conn, file_name);
 		goto done;
 	}
 
 	/* touch access date of moved file */
-	if (recbin->touch == True )
-		recycle_touch(conn, final_name);
+	if (recycle_touch(conn) == True )
+		recycle_do_touch(conn, final_name);
 
 done:
 	SAFE_FREE(path_name);
 	SAFE_FREE(temp_name);
 	SAFE_FREE(final_name);
+	SAFE_FREE(repository);
 	return rc;
 }
 
 int vfs_recycle_init(void)
 {
-	return smb_register_vfs("recycle", recycle_init, SMB_VFS_INTERFACE_VERSION);
+	return smb_register_vfs("recycle", recycle_ops, &vfs_module_number, SMB_VFS_INTERFACE_VERSION);
 }
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure --exclude=autom4te.cache HEAD-vfs-clean/source/smbd/conn.c HEAD-vfs/source/smbd/conn.c
--- HEAD-vfs-clean/source/smbd/conn.c	Sat Feb  1 07:24:07 2003
+++ HEAD-vfs/source/smbd/conn.c	Tue Mar 25 20:23:31 2003
@@ -195,25 +195,13 @@ void conn_clear_vuid_cache(uint16 vuid)
 
 void conn_free(connection_struct *conn)
 {
- 	smb_vfs_handle_struct *handle, *thandle;
- 	void (*done_fptr)(connection_struct *the_conn);
+ 	smb_vfs_handle_struct *handle = NULL;
 
 	/* Free vfs_connection_struct */
-	handle = conn->vfs_private;
-	while(handle) {
- 		/* Close dlopen() handle */
- 		done_fptr = (void (*)(connection_struct *))sys_dlsym(handle->handle, "vfs_done");
- 
- 		if (done_fptr == NULL) {
- 			DEBUG(3, ("No vfs_done() symbol found in module with handle %p, ignoring\n", handle->handle));
- 		} else {
- 			done_fptr(conn);
- 		}
-     		sys_dlclose(handle->handle);
-		DLIST_REMOVE(conn->vfs_private, handle);
-		thandle = handle->next;
+	handle = conn->vfs_handles;
+	while(conn->vfs_handles) {
+		DLIST_REMOVE(conn->vfs_handles, handle);
 		SAFE_FREE(handle);
-		handle = thandle;
 	}
 
 	DLIST_REMOVE(Connections, conn);
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure --exclude=autom4te.cache HEAD-vfs-clean/source/smbd/vfs.c HEAD-vfs/source/smbd/vfs.c
--- HEAD-vfs-clean/source/smbd/vfs.c	Tue Mar 25 20:13:55 2003
+++ HEAD-vfs/source/smbd/vfs.c	Wed Mar 26 00:11:35 2003
@@ -29,7 +29,8 @@
 
 struct vfs_init_function_entry {
 	char *name;
- 	vfs_op_tuple *ops, *(*init)(const struct vfs_ops *, struct smb_vfs_handle_struct *);
+ 	vfs_op_tuple *vfs_ops;
+ 	int vfs_num;
 	struct vfs_init_function_entry *prev, *next;
 };
 
@@ -42,12 +43,6 @@ struct vfs_syminfo {
 	void *fptr;
 };
 
-/*
-  Opaque (final) vfs operations. This is a combination of first-met opaque vfs operations
-  across all currently processed modules.  */
-
-static vfs_op_tuple vfs_opaque_ops[SMB_VFS_OP_LAST];
-
 /* Default vfs hooks.  WARNING: The order of these initialisers is
    very important.  They must be in the same order as defined in
    vfs.h.  Change at your own peril. */
@@ -150,10 +145,16 @@ struct vfs_init_function_entry *vfs_find
 	return NULL;
 }
 
-BOOL smb_register_vfs(const char *name, vfs_op_tuple *(*init)(const struct vfs_ops *, struct smb_vfs_handle_struct *), int version)
+BOOL smb_register_vfs(const char *name, vfs_op_tuple *vfs_ops, int *vfs_num, int version)
 {
+	static int global_vfs_num = 0;
 	struct vfs_init_function_entry *entry = backends;
-	
+
+	if (!name || !name[0] || !vfs_ops || !vfs_num) {
+		DEBUG(0,("smb_register_vfs() called with NULL pointer or empty name!\n"));
+		return False;
+	}
+
  	if ((version < SMB_VFS_INTERFACE_CASCADED)) {
  		DEBUG(0, ("vfs_init() returned wrong interface version info (was %d, should be no less than %d)\n",
  			version, SMB_VFS_INTERFACE_VERSION ));
@@ -166,7 +167,7 @@ Proceeding in compatibility mode, new op
  			version, SMB_VFS_INTERFACE_VERSION, version ));
   		return False;
   	}
-	
+
 	while(entry) {
 		if (strequal(entry->name, name)) {
 			DEBUG(0,("VFS module %s already loaded!\n", name));
@@ -177,7 +178,9 @@ Proceeding in compatibility mode, new op
 
 	entry = smb_xmalloc(sizeof(struct vfs_init_function_entry));
 	entry->name = smb_xstrdup(name);
-	entry->init = init;
+	entry->vfs_ops = vfs_ops;
+	entry->vfs_num = ++global_vfs_num;
+	*vfs_num = entry->vfs_num;
 
 	DLIST_ADD(backends, entry);
 	DEBUG(5, ("Successfully added vfs backend '%s'\n", name));
@@ -193,7 +196,8 @@ static void vfs_init_default(connection_
 	DEBUG(3, ("Initialising default vfs hooks\n"));
 
 	memcpy(&conn->vfs_ops, &default_vfs_ops, sizeof(struct vfs_ops));
-	conn->vfs_private = NULL;
+	memcpy(&conn->vfs_opaque_ops, &default_vfs_ops, sizeof(struct vfs_ops));
+	conn->vfs_handles = NULL;
 }
 
 /****************************************************************************
@@ -205,6 +209,11 @@ BOOL vfs_init_custom(connection_struct *
  	int i;
 	vfs_op_tuple *ops;
 	struct vfs_init_function_entry *entry;
+	
+	if (!conn||!vfs_object||!vfs_object[0]) {
+		DEBUG(0,("vfs_init_custon() called with NULL pointer or emtpy vfs_object!\n"));
+		return False;
+	}
 
 	if(!backends) static_init_vfs;
 
@@ -217,21 +226,28 @@ BOOL vfs_init_custom(connection_struct *
 
 	/* Initialise vfs_ops structure */
 
- 	if ((ops = entry->init(&conn->vfs_ops, conn->vfs_private)) == NULL) {
- 		DEBUG(0, ("vfs_init() function from %s failed\n", vfs_object));
-		sys_dlclose(conn->vfs_private->handle);
+	if (!conn->vfs_handles) {
+		DEBUG(0, ("conn->vfs_handles==NULL for [%s] failed\n", vfs_object));
+ 		return False;
+	}
+
+
+	memcpy(&conn->vfs_handles->vfs_def_ops, &conn->vfs_ops, sizeof(struct vfs_ops));
+	conn->vfs_handles->vfs_num = entry->vfs_num;
+
+ 	if ((ops = entry->vfs_ops) == NULL) {
+ 		DEBUG(0, ("entry->vfs_ops==NULL for [%s] failed\n", vfs_object));
  		return False;
  	}
-  
- 
+
  	for(i=0; ops[i].op != NULL; i++) {
  	  DEBUG(3, ("Checking operation #%d (type %d, layer %d)\n", i, ops[i].type, ops[i].layer));
  	  if(ops[i].layer == SMB_VFS_LAYER_OPAQUE) {
  	    /* Check whether this operation was already made opaque by different module */
- 	    if(vfs_opaque_ops[ops[i].type].op == ((void**)&default_vfs_ops)[ops[i].type]) {
+ 	    if(((void**)&conn->vfs_opaque_ops)[ops[i].type] == ((void**)&default_vfs_ops)[ops[i].type]) {
  	      /* No, it isn't overloaded yet. Overload. */
  	      DEBUG(3, ("Making operation type %d opaque [module %s]\n", ops[i].type, vfs_object));
- 	      vfs_opaque_ops[ops[i].type] = ops[i];
+ 	      ((void**)&conn->vfs_opaque_ops)[ops[i].type] = ops[i].op;
  	    }
  	  }
  	  /* Change current VFS disposition*/
@@ -250,7 +266,6 @@ BOOL smbd_vfs_init(connection_struct *co
 {
 	const char **vfs_objects;
 	char *vfs_module, *vfs_path;
-	unsigned int i;
 	unsigned int j = 0;
 	struct smb_vfs_handle_struct *handle;
 	
@@ -262,20 +277,14 @@ BOOL smbd_vfs_init(connection_struct *co
 	if (!vfs_objects)
 		return True;
 
-	for(i=0; i<SMB_VFS_OP_LAST; i++) {
-		vfs_opaque_ops[i].op = ((void**)&default_vfs_ops)[i];
-		vfs_opaque_ops[i].type = i;
-		vfs_opaque_ops[i].layer = SMB_VFS_LAYER_OPAQUE;
-	}
-
 	vfs_path = lp_vfs_path(SNUM(conn));
 	
 	for (j=0; vfs_objects[j]; j++) {
-		conn->vfs_private = NULL;
+		conn->vfs_handles = NULL;
 		handle = (struct smb_vfs_handle_struct *) smb_xmalloc(sizeof(smb_vfs_handle_struct));
 		/* Loadable object file */
-		handle->handle = NULL;
-		DLIST_ADD(conn->vfs_private, handle);
+		ZERO_STRUCT(*handle);
+		DLIST_ADD(conn->vfs_handles, handle);
 		vfs_module = NULL;
 		if (vfs_path) {
 			asprintf(&vfs_module, "%s/%s", vfs_path, vfs_objects[j]);
@@ -285,7 +294,7 @@ BOOL smbd_vfs_init(connection_struct *co
 		if (!vfs_init_custom(conn, vfs_module)) {
 			DEBUG(0, ("smbd_vfs_init: vfs_init_custom failed for %s\n", vfs_module));
 			SAFE_FREE(vfs_module);
-			DLIST_REMOVE(conn->vfs_private, handle);
+			DLIST_REMOVE(conn->vfs_handles, handle);
 			SAFE_FREE(handle);
 			return False;
 		}
@@ -294,21 +303,26 @@ BOOL smbd_vfs_init(connection_struct *co
 	return True;
 }
 
-/*******************************************************************
- Create vfs_ops reflecting current vfs_opaque_ops
-*******************************************************************/
 
-struct vfs_ops *smb_vfs_get_opaque_ops(void)
+struct vfs_ops *vfs_handle_get_ops(connection_struct *conn, int vfs_num)
 {
-  int i;
-  struct vfs_ops *ops;
+	struct smb_vfs_handle_struct *handle = NULL;
+
+	if (!conn) {
+		DEBUG(0,("vfs_handle_get_ops() called with NULL pointer.\n"));
+		return NULL;
+	}
 
-  ops = smb_xmalloc(sizeof(struct vfs_ops));
+	handle = conn->vfs_handles;
+
+	while (handle) {
+		if (handle->vfs_num == vfs_num) {
+			return &handle->vfs_def_ops;
+		}
+		handle = handle->next;
+	}
 
-  for(i=0; i<SMB_VFS_OP_LAST; i++) {
-    ((void**)ops)[i] = vfs_opaque_ops[i].op;
-  }
-  return ops;
+	return NULL;	
 }
 
 /*******************************************************************
