diff -r -u -N -x {arch} -x .arch-ids dazuko--vendor--2.1/configure dazuko--contrib-symlink2--2.1/configure
--- dazuko--vendor--2.1/configure	2006-03-03 15:11:02.000000000 +0200
+++ dazuko--contrib-symlink2--2.1/configure	2006-03-03 15:24:10.000000000 +0200
@@ -354,64 +354,67 @@
 
 do_linux26()
 {
-	echo -n "checking if security module support is enabled... "
-	if [ $CONFIG_SECURITY -eq 0 ]
+	if [ $LINUX26_USE_SYSCALLS -eq 0 ]
 	then
-		echo "no"
-		echo "error: security module support must be enabled in your kernel"
-		exit 1
-	else
-		echo "yes"
-	fi
+		echo -n "checking if security module support is enabled... "
+		if [ $CONFIG_SECURITY -eq 0 ]
+		then
+			echo "no"
+			echo "error: security module support must be enabled in your kernel"
+			exit 1
+		else
+			echo "yes"
+		fi
 
-	echo -n "verifying capabilities are not built-in... "
-	if [ $CONFIG_SECURITY_CAPABILITIES -ne 0 ]
-	then
-		echo "built-in :("
-		echo "error: capabilities are built-in to the kernel:"
-		echo "       you will need to recompile a kernel with capabilities"
-		echo "       as a kernel module"
-		exit 1
-	else
-		echo "ok"
-	fi
+		echo -n "verifying capabilities are not built-in... "
+		if [ $CONFIG_SECURITY_CAPABILITIES -ne 0 ]
+		then
+			echo "built-in :("
+			echo "error: capabilities are built-in to the kernel:"
+			echo "       you will need to recompile a kernel with capabilities"
+			echo "       as a kernel module"
+			exit 1
+		else
+			echo "ok"
+		fi
 
-	if [ $CONFIG_SECURITY_CAPABILITIES_MODULE -eq 0 ]
-	then
-		NO_CAPABILITIES=1
-	fi
+		if [ $CONFIG_SECURITY_CAPABILITIES_MODULE -eq 0 ]
+		then
+			NO_CAPABILITIES=1
+		fi
 
-	echo -n "locating LSM API header... "
+		echo -n "locating LSM API header... "
 
-	SRC_PATH_END="/include/linux/security.h"
-	get_src_path
+		SRC_PATH_END="/include/linux/security.h"
+		get_src_path
 
-	if [ ! -f "$SRC_PATH" ]
-	then
-		echo "failed"
-		echo "error: unable to locate security.h"
-		exit 1
-	else
-		echo "ok"
-	fi
+		if [ ! -f "$SRC_PATH" ]
+		then
+			echo "failed"
+			echo "error: unable to locate security.h"
+			exit 1
+		else
+			echo "ok"
+		fi
 
-	echo -n "identifying LSM API... "
-	if [ ! -x "linux_lsm_conf" ]
-	then
-		echo "failed"
-		echo "error: linux_lsm_conf missing in Dazuko distribution"
-		exit 1
-	fi
+		echo -n "identifying LSM API... "
+		if [ ! -x "linux_lsm_conf" ]
+		then
+			echo "failed"
+			echo "error: linux_lsm_conf missing in Dazuko distribution"
+			exit 1
+		fi
 
-	./linux_lsm_conf $SRC_PATH
-	if [ $? -ne 0 ]
-	then
-		echo "failed"
-		echo "error: could not analyze security.h"
-		exit 1
-	fi
+		./linux_lsm_conf $SRC_PATH
+		if [ $? -ne 0 ]
+		then
+			echo "failed"
+			echo "error: could not analyze security.h"
+			exit 1
+		fi
 
-	echo "ok"
+		echo "ok"
+	fi
 
 	echo -n "inspecting suspend function... "
 
@@ -485,41 +488,79 @@
 		echo "ok (class_simple)"
 	fi
 
-	if [ $ON_CLOSE -ne 0 ]
-	then
-		echo "disabling ON_CLOSE events (not available for Linux 2.6)"
-		ON_CLOSE=0
-	fi
+	echo "configure: creating Makefile"
 
-	if [ ${ON_UNLINK} -ne 0 ]
-	then
-		echo "disabling ON_UNLINK events (not available for Linux 2.6)"
-		ON_UNLINK=0
-	fi
+	echo "EXTRA_CFLAGS += -Wall -DLINUX26_SUPPORT" > Makefile
 
-	if [ ${ON_RMDIR} -ne 0 ]
+	if [ $LINUX26_USE_SYSCALLS -eq 0 ]
 	then
-		echo "disabling ON_RMDIR events (not available for Linux 2.6)"
-		ON_RMDIR=0
-	fi
+		if [ $ON_CLOSE -ne 0 ]
+		then
+			echo "disabling ON_CLOSE events (not available for Linux 2.6)"
+			ON_CLOSE=0
+		fi
 
-	if [ ${ON_CLOSE_MODIFIED} -ne 0 ]
-	then
-		echo "disabling ON_CLOSE_MODIFIED events (not available for Linux 2.6)"
-		ON_CLOSE_MODIFIED=0
-	fi
+		if [ ${ON_UNLINK} -ne 0 ]
+		then
+			echo "disabling ON_UNLINK events (not available for Linux 2.6)"
+			ON_UNLINK=0
+		fi
 
-	LINUX26_OBJS="dazuko_linux26.o"
+		if [ ${ON_RMDIR} -ne 0 ]
+		then
+			echo "disabling ON_RMDIR events (not available for Linux 2.6)"
+			ON_RMDIR=0
+		fi
 
-	echo "configure: creating Makefile"
+		if [ ${ON_CLOSE_MODIFIED} -ne 0 ]
+		then
+			echo "disabling ON_CLOSE_MODIFIED events (not available for Linux 2.6)"
+			ON_CLOSE_MODIFIED=0
+		fi
 
-	echo "EXTRA_CFLAGS += -Wall -DLINUX26_SUPPORT" > Makefile
+		LINUX26_OBJS="dazuko_linux26.o"
+
+		if [ ${LSM_STACKING} -eq 1 ]
+		then
+			LINUX26_OBJS="dazuko_linux26_lsm.o ${LINUX26_OBJS}"
+		else
+			echo "EXTRA_CFLAGS += -DNO_STACKING_SUPPORT" >> Makefile
+		fi
+
+		if [ ${NO_CAPABILITIES} -eq 1 ]
+		then
+			echo "EXTRA_CFLAGS += -DNO_CAPABILITIES" >> Makefile
+		fi
 
-	if [ ${LSM_STACKING} -eq 1 ]
-	then
-		LINUX26_OBJS="dazuko_linux26_lsm.o ${LINUX26_OBJS}"
 	else
-		echo "EXTRA_CFLAGS += -DNO_STACKING_SUPPORT" >> Makefile
+		LINUX26_OBJS="dazuko_linux26_syscall.o"
+		echo "EXTRA_CFLAGS += -DHIDDEN_SCT -DUSE_SYSCALLS" >> Makefile
+
+		echo -n "Finding do_execve from: "
+		found=false
+		for m in $MAPFILES
+		do
+			echo -n "$m "
+			if [ -r $m ] && awk 'BEGIN { rc = 1 }
+					$3 == "do_execve" { print "EXTRA_CFLAGS += -DDO_EXECVE_ADDR=0x" $1; rc = 0; exit } 
+					END { exit rc }' $m >> Makefile
+			then
+				found=true
+				echo "OK"
+				break
+			fi
+		done
+
+		if $found
+		then
+			:
+		else
+			echo
+			echo "configure: error:"
+			echo "Could not find address of do_execve kernel function from above System.map file(s)"
+			echo "Please retry configure with option --mapfile=/path/to/your/kernel/System.map"
+			exit 1
+		fi
 	fi
 
 	if [ ${LOCAL_DPATH} -eq 1 ]
@@ -527,11 +568,6 @@
 		echo "EXTRA_CFLAGS += -DWITH_LOCAL_DPATH" >> Makefile
 	fi
 
-	if [ ${NO_CAPABILITIES} -eq 1 ]
-	then
-		echo "EXTRA_CFLAGS += -DNO_CAPABILITIES" >> Makefile
-	fi
-
 	if [ ${LINUX26_USE_SUSPEND} -eq 1 ]
 	then
 		echo "EXTRA_CFLAGS += -DUSE_TRYTOFREEZEVOID" >> Makefile
@@ -567,6 +603,31 @@
 		echo "EXTRA_CFLAGS += -DON_OPEN_SUPPORT" >> Makefile
 	fi
 
+	if [ ${ON_CLOSE} -eq 1 ]
+	then
+		echo "EXTRA_CFLAGS += -DON_CLOSE_SUPPORT" >> Makefile
+	fi
+
+	if [ ${ON_EXEC} -eq 1 ]
+	then
+		echo "EXTRA_CFLAGS += -DON_EXEC_SUPPORT" >> Makefile
+	fi
+
+	if [ ${ON_UNLINK} -eq 1 ]
+	then
+		echo "EXTRA_CFLAGS += -DON_UNLINK_SUPPORT" >> Makefile
+	fi
+
+	if [ ${ON_RMDIR} -eq 1 ]
+	then
+		echo "EXTRA_CFLAGS += -DON_RMDIR_SUPPORT" >> Makefile
+	fi
+
+	if [ ${ON_CLOSE_MODIFIED} -eq 1 ]
+	then
+		echo "EXTRA_CFLAGS += -DON_CLOSE_MODIFIED_SUPPORT" >> Makefile
+	fi
+
 	if [ ${TRUSTED} -eq 1 ]
 	then
 		echo "EXTRA_CFLAGS += -DTRUSTED_APPLICATION_SUPPORT" >> Makefile
@@ -1064,12 +1125,17 @@
 
 			if echo $LINUX_VERSION | grep -q ^2\.6\.
 			then
-				echo -n "stacking support = "
-				if [ ${LSM_STACKING} -eq 1 ]
+				if [ $LINUX26_USE_SYSCALLS -eq 1 ]
 				then
-					echo "yes"
+					echo "using system call hooking"
 				else
-					echo "no"
+					echo -n "stacking support = "
+					if [ ${LSM_STACKING} -eq 1 ]
+					then
+						echo "yes"
+					else
+						echo "no"
+					fi
 				fi
 
 				echo -n "local __d_path() = "
@@ -1161,6 +1227,7 @@
 LINUX26_USE_SUSPEND=0
 LINUX26_USE_CLASS=0
 LINUX26_USE_CHROOT=0
+LINUX26_USE_SYSCALLS=0
 NO_CAPABILITIES=0
 SMP=0
 HIDDEN_SCT=0
@@ -1174,6 +1241,7 @@
 FREEBSD_VERSION=0
 UNAME=`uname`
 UNAME_R=`uname -r`
+MAPFILES="/boot/System.map-$UNAME_R /lib/modules/$UNAME_R/System.map /usr/src/linux/System.map"
 
 for option in $@
 do
@@ -1238,6 +1306,12 @@
 		--disable-stacking)
 			LSM_STACKING=0
 			;;
+		--enable-syscalls)
+			LINUX26_USE_SYSCALLS=1
+			;;
+		--disable-syscalls)
+			LINUX26_USE_SYSCALLS=0
+			;;
 		--enable-local-dpath)
 			LOCAL_DPATH=1
 			;;
@@ -1306,6 +1380,16 @@
 		--system=*)
 			SYSTEM=`echo $option | sed -e s/^--system=//`
 			;;
+		--mapfile=*)
+			MAPFILES=`echo $option | sed -e s/^--mapfile=//`
+			if [ -r $MAPFILES ]
+			then
+				echo "Using System.map file at $MAPFILES"
+			else
+				echo "configure: error: $MAPFILES is not readable"
+				exit 1
+			fi
+			;;
 		--help|-h)
 			print_help
 			exit 0
diff -r -u -N -x {arch} -x .arch-ids dazuko--vendor--2.1/dazuko_core.c dazuko--contrib-symlink2--2.1/dazuko_core.c
--- dazuko--vendor--2.1/dazuko_core.c	2006-03-03 15:11:02.000000000 +0200
+++ dazuko--contrib-symlink2--2.1/dazuko_core.c	2006-03-03 15:25:57.000000000 +0200
@@ -2341,12 +2341,6 @@
 	if (!(s->write_mode))
 		return 1;
 
-	/* (CLOSE events are treated as read_only since
-	 * the action is not implemented as blockable) */
-
-	if (s->event == DAZUKO_ON_CLOSE || s->event == DAZUKO_ON_CLOSE_MODIFIED)
-		return 1;
-
 	return 0;
 }
 
diff -r -u -N -x {arch} -x .arch-ids dazuko--vendor--2.1/dazuko_linux.c dazuko--contrib-symlink2--2.1/dazuko_linux.c
--- dazuko--vendor--2.1/dazuko_linux.c	2006-03-03 15:11:02.000000000 +0200
+++ dazuko--contrib-symlink2--2.1/dazuko_linux.c	2006-03-03 15:25:57.000000000 +0200
@@ -64,7 +64,7 @@
 
 #if defined(ON_OPEN_SUPPORT)
 static asmlinkage long          (*original_sys_open)(const char *filename, int flags, int mode);
-static asmlinkage long          (*original_sys_dup)(unsigned int filedes);
+static asmlinkage long          (*original_sys_creat)(const char *filename, int mode);
 #endif
 #if defined(ON_OPEN_SUPPORT) || defined(ON_CLOSE_SUPPORT) || defined(ON_CLOSE_MODIFIED_SUPPORT)
 static asmlinkage long          (*original_sys_dup2)(unsigned int oldfd, unsigned int newfd);
@@ -350,6 +350,7 @@
 		/* make sure it is a valid name */
 		if (IS_ERR(filename))
 		{
+			DPRINT(("dazuko_get_filename_dentry: getname failed\n"));
 			filename = NULL;
 			return 0;
 		}
@@ -414,6 +415,7 @@
 	/* check if this file has no inode */
 	if (xfs->dentry->d_inode == NULL)
 	{
+		DPRINT(("dazuko_get_filename_dentry: inode is NULL\n"));
 		goto dentry_exit;
 	}
 	else
@@ -426,6 +428,7 @@
 	if (putname_filename)
 		putname(filename);
 
+	DPRINT(("dazuko_get_filename_dentry returning %d\n", rc));
 	return rc;
 }
 
@@ -690,6 +693,7 @@
 				if (IS_ERR(freeparentpath))
 				{
 					freeparentpath = NULL;
+					DPRINT(("%s: getname failed\n", dfs->extra_data->user_filename));
 					break;
 				}
 
@@ -728,6 +732,7 @@
 				{
 					putname(freeparentpath);
 					freeparentpath = NULL;
+					DPRINT(("dazuko_get_filename_dentry failed for %s\n", parentpath));
 					break;
 				}
 			}
@@ -736,6 +741,7 @@
 		{
 			if (!dazuko_get_fd_dentry(dfs->extra_data))
 			{
+				DPRINT(("dazuko_get_fd_dentry failed\n"));
 				break;
 			}
 			else
@@ -746,11 +752,15 @@
 		}
 
 		/* make sure we can get the full path */
-		if (!dazuko_get_full_filename(dfs->extra_data))
+		if (!dazuko_get_full_filename(dfs->extra_data)) 
+		{
+			DPRINT(("dazuko_get_full_filename failed for %s\n", dfs->extra_data->user_filename));
 			break;
+		}
 
 		if (freeparentpath != NULL)
 		{
+			DPRINT(("building full path at loop=%d, we have %s\n", loopcount, dfs->extra_data->full_filename));
 			/* we are working with a "fake" name */
 
 			parentpath = dfs->extra_data->full_filename;
@@ -777,38 +787,53 @@
 			/* copy filename */
 			memcpy(dfs->extra_data->full_filename + dfs->extra_data->full_filename_length, rawfilename, i + 1);
 			dfs->extra_data->full_filename_length += i;
+			DPRINT(("constructed full filename: %s\n", dfs->extra_data->full_filename));
+
+			/* Clean up dfs so that it can be reused for the new dentry */
+			dazuko_fill_file_struct_cleanup(dfs);
+
+			if (!dazuko_get_filename_dentry(dfs->extra_data, follow_symlinks, dfs->extra_data->full_filename, 0))
+			{
+				xp_free(parentpath);
+				DPRINT(("dazuko_get_filename_dentry failed for constructed filename %s\n", dfs->extra_data->full_filename));
+				break;
+			}
 
 			/* free allocated parent path */
 			xp_free(parentpath);
 		}
-		else
-		{
-			dfs->file_p.size = dfs->extra_data->dentry->d_inode->i_size;
-			dfs->file_p.set_size = 1;
-			dfs->file_p.uid = dfs->extra_data->dentry->d_inode->i_uid;
-			dfs->file_p.set_uid = 1;
-			dfs->file_p.gid = dfs->extra_data->dentry->d_inode->i_gid;
-			dfs->file_p.set_gid = 1;
-			dfs->file_p.mode = dfs->extra_data->dentry->d_inode->i_mode;
-			dfs->file_p.set_mode = 1;
-			dfs->file_p.device_type = dfs->extra_data->dentry->d_inode->i_dev;
-			dfs->file_p.set_device_type = 1;
-		}
+
+		DPRINT(("we have full path at loop=%d, %s\n", loopcount, dfs->extra_data->full_filename));
+		dfs->file_p.size = dfs->extra_data->dentry->d_inode->i_size;
+		dfs->file_p.set_size = 1;
+		dfs->file_p.uid = dfs->extra_data->dentry->d_inode->i_uid;
+		dfs->file_p.set_uid = 1;
+		dfs->file_p.gid = dfs->extra_data->dentry->d_inode->i_gid;
+		dfs->file_p.set_gid = 1;
+		dfs->file_p.mode = dfs->extra_data->dentry->d_inode->i_mode;
+		dfs->file_p.set_mode = 1;
+		dfs->file_p.device_type = dfs->extra_data->dentry->d_inode->i_dev;
+		dfs->file_p.set_device_type = 1;
 
 		if (S_ISREG(dfs->extra_data->dentry->d_inode->i_mode))
 		{
+			DPRINT(("inode is regular file\n"));
 			dfs->file_p.type = DAZUKO_REGULAR;
 			dfs->file_p.set_type = 1;
 		}
 		else if (S_ISLNK(dfs->extra_data->dentry->d_inode->i_mode))
 		{
+			DPRINT(("inode is symlink\n"));
 			dfs->file_p.type = DAZUKO_LINK;
 			dfs->file_p.set_type = 1;
 		}
 		else if (S_ISDIR(dfs->extra_data->dentry->d_inode->i_mode))
 		{
+			DPRINT(("inode is a directory\n"));
 			dfs->file_p.type = DAZUKO_DIRECTORY;
 			dfs->file_p.set_type = 1;
+			error = -1;
+			break;
 		}
 
 		listnode = (struct dazuko_file_listnode *)xp_malloc(sizeof(struct dazuko_file_listnode));
@@ -860,6 +885,8 @@
 
 	dazuko_fill_file_struct_cleanup(dfs);
 
+	DPRINT(("xp_fill_file_struct returning %d\n", error));
+
 	return error;
 }
 
@@ -1027,6 +1054,8 @@
 	struct event_properties		event_p;
 	struct xp_daemon_id		xp_id;
 
+	fd = original_sys_open(filename, flags, mode);
+
 	xp_id.pid = current->pid;
 	xp_id.file = NULL;
 	xp_id.current_p = current;
@@ -1073,119 +1102,69 @@
 	if (error)
 	{
 		/* access should be blocked */
-
+		original_sys_close(fd);
 		fd = -1;
 	}
-	else
-	{
-		/* call the standard open function */
-		fd = original_sys_open(filename, flags, mode);
-	}
 
 	return fd;
 }
 
-asmlinkage long linux_dazuko_sys_dup(unsigned int filedes)
+asmlinkage long	linux_dazuko_sys_creat(const char *filename, int mode)
+{
+	return linux_dazuko_sys_open(filename, O_CREAT | O_WRONLY | O_TRUNC, mode);
+}
+#endif
+
+#if defined(ON_CLOSE_SUPPORT) || defined(ON_CLOSE_MODIFIED_SUPPORT)
+asmlinkage long linux_dazuko_sys_dup2(unsigned int oldfd, unsigned int newfd)
 {
 	struct dazuko_file_struct	*dfs = NULL;
-	struct event_properties		event_p;
 	struct xp_daemon_id		xp_id;
 	int				error = 0;
 	int				check_error = 0;
+	struct event_properties		close_event_p;
+	int				will_close_newfd = 0;
 
 	xp_id.pid = current->pid;
 	xp_id.file = NULL;
 	xp_id.current_p = current;
 	xp_id.files = current->files;
 
-	check_error = dazuko_check_access(DAZUKO_ON_OPEN, 1, &xp_id, NULL);
+	check_error = dazuko_check_access(DAZUKO_ON_CLOSE, 1, &xp_id, NULL);
 
-	if (!check_error)
+	if (newfd >= 0 && newfd < current->files->max_fds)
 	{
-		dazuko_bzero(&event_p, sizeof(event_p));
-
-		if (filedes >= 0 && filedes < current->files->max_fds)
+		#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
 		{
-			event_p.pid = current->pid;
-			event_p.set_pid = 1;
-			event_p.uid = current->uid;
-			event_p.set_uid = 1;
-
-			dfs = (struct dazuko_file_struct *)xp_malloc(sizeof(struct dazuko_file_struct));
-			if (dfs != NULL)
-			{
-				dazuko_bzero(dfs, sizeof(struct dazuko_file_struct));
-
-				dfs->extra_data = (struct xp_file_struct *)xp_malloc(sizeof(struct xp_file_struct));
-				if (dfs->extra_data != NULL)
-				{
-					dazuko_bzero(dfs->extra_data, sizeof(struct xp_file_struct));
-
-					dfs->extra_data->fd = filedes;
-
-					error = dazuko_process_access(DAZUKO_ON_OPEN, dfs, &event_p, NULL);
+			read_lock(&current->files->file_lock);
+		}
+		#endif
 
-					dazuko_file_struct_cleanup(&dfs);
-				}
-				else
-				{
-					xp_free(dfs);
-					dfs = NULL;
-				}
-			}
+		if (current->files->fd[newfd] != NULL)
+		{
+			will_close_newfd = 1;
 		}
-		else
+
+		#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
 		{
-			check_error = -1;
+			read_unlock(&current->files->file_lock);
 		}
+		#endif
 	}
 
-	if (error)
-	{
-		/* access should be blocked */
-
-		error = -EPERM;
-	}
-	else
-	{
-		/* call the standard open function */
-		error = original_sys_dup(filedes);
-	}
-
-	return error;
-}
-#endif
-
-#if defined(ON_OPEN_SUPPORT) || defined(ON_CLOSE_SUPPORT) || defined(ON_CLOSE_MODIFIED_SUPPORT)
-asmlinkage long linux_dazuko_sys_dup2(unsigned int oldfd, unsigned int newfd)
-{
-	struct dazuko_file_struct	*dfs = NULL;
-	struct event_properties		open_event_p;
-	struct xp_daemon_id		xp_id;
-	int				error = 0;
-	int				check_error = 0;
-#if defined(ON_CLOSE_SUPPORT) || defined(ON_CLOSE_MODIFIED_SUPPORT)
-	struct event_properties		close_event_p;
-	int				will_close_newfd = 0;
-#endif
-
-	xp_id.pid = current->pid;
-	xp_id.file = NULL;
-	xp_id.current_p = current;
-	xp_id.files = current->files;
-
-	check_error = dazuko_check_access(DAZUKO_ON_OPEN, 1, &xp_id, NULL);
+	/* call the standard open function */
+	error = original_sys_dup2(oldfd, newfd);
 
 	if (!check_error)
 	{
-		dazuko_bzero(&open_event_p, sizeof(open_event_p));
-
-		if (oldfd != newfd && oldfd >= 0 && oldfd < current->files->max_fds)
+		if (error >= 0 && will_close_newfd)
 		{
-			open_event_p.pid = current->pid;
-			open_event_p.set_pid = 1;
-			open_event_p.uid = current->uid;
-			open_event_p.set_uid = 1;
+			dazuko_bzero(&close_event_p, sizeof(close_event_p));
+
+			close_event_p.pid = current->pid;
+			close_event_p.set_pid = 1;
+			close_event_p.uid = current->uid;
+			close_event_p.set_uid = 1;
 
 			dfs = (struct dazuko_file_struct *)xp_malloc(sizeof(struct dazuko_file_struct));
 			if (dfs != NULL)
@@ -1197,9 +1176,9 @@
 				{
 					dazuko_bzero(dfs->extra_data, sizeof(struct xp_file_struct));
 
-					dfs->extra_data->fd = oldfd;
+					dfs->extra_data->fd = newfd;
 
-					error = dazuko_process_access(DAZUKO_ON_OPEN, dfs, &open_event_p, NULL);
+					error = dazuko_process_access(DAZUKO_ON_CLOSE, dfs, &close_event_p, NULL);
 
 					dazuko_file_struct_cleanup(&dfs);
 				}
@@ -1210,84 +1189,6 @@
 				}
 			}
 		}
-		else
-		{
-			check_error = -1;
-		}
-	}
-
-	if (error)
-	{
-		/* access should be blocked */
-
-		error = -EPERM;
-	}
-	else
-	{
-		#if defined(ON_CLOSE_SUPPORT) || defined(ON_CLOSE_MODIFIED_SUPPORT)
-		if (newfd >= 0 && newfd < current->files->max_fds)
-		{
-			#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-			{
-				read_lock(&current->files->file_lock);
-			}
-			#endif
-
-			if (current->files->fd[newfd] != NULL)
-			{
-				will_close_newfd = 1;
-			}
-
-			#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-			{
-				read_unlock(&current->files->file_lock);
-			}
-			#endif
-		}
-		#endif
-
-		/* call the standard open function */
-		error = original_sys_dup2(oldfd, newfd);
-
-		#if defined(ON_CLOSE_SUPPORT) || defined(ON_CLOSE_MODIFIED_SUPPORT)
-		{
-			if (!check_error)
-			{
-				if (error >= 0 && will_close_newfd)
-				{
-					dazuko_bzero(&close_event_p, sizeof(close_event_p));
-
-					close_event_p.pid = current->pid;
-					close_event_p.set_pid = 1;
-					close_event_p.uid = current->uid;
-					close_event_p.set_uid = 1;
-
-					dfs = (struct dazuko_file_struct *)xp_malloc(sizeof(struct dazuko_file_struct));
-					if (dfs != NULL)
-					{
-						dazuko_bzero(dfs, sizeof(struct dazuko_file_struct));
-
-						dfs->extra_data = (struct xp_file_struct *)xp_malloc(sizeof(struct xp_file_struct));
-						if (dfs->extra_data != NULL)
-						{
-							dazuko_bzero(dfs->extra_data, sizeof(struct xp_file_struct));
-
-							dfs->extra_data->fd = newfd;
-
-							dazuko_process_access(DAZUKO_ON_CLOSE, dfs, &close_event_p, NULL);
-
-							dazuko_file_struct_cleanup(&dfs);
-						}
-						else
-						{
-							xp_free(dfs);
-							dfs = NULL;
-						}
-					}
-				}
-			}
-		}
-		#endif
 	}
 
 	return error;
@@ -1350,7 +1251,7 @@
 	{
 		if (!check_error)
 		{
-			dazuko_process_access(DAZUKO_ON_CLOSE, dfs, &event_p, NULL);
+			error = dazuko_process_access(DAZUKO_ON_CLOSE, dfs, &event_p, NULL);
 		}
 
 		dazuko_file_struct_cleanup(&dfs);
@@ -1688,9 +1589,9 @@
 
 #if defined(ON_OPEN_SUPPORT)
 	DAZUKO_HOOK(open);
-	DAZUKO_HOOK(dup);
+	DAZUKO_HOOK(creat);
 #endif
-#if defined(ON_OPEN_SUPPORT) || defined(ON_CLOSE_SUPPORT) || defined(ON_CLOSE_MODIFIED_SUPPORT)
+#if defined(ON_CLOSE_SUPPORT) || defined(ON_CLOSE_MODIFIED_SUPPORT)
 	DAZUKO_HOOK(dup2);
 #endif
 	
@@ -1744,9 +1645,9 @@
 
 #if defined(ON_OPEN_SUPPORT)
 	DAZUKO_UNHOOK(open);
-	DAZUKO_UNHOOK(dup);
+	DAZUKO_UNHOOK(creat);
 #endif
-#if defined(ON_OPEN_SUPPORT) || defined(ON_CLOSE_SUPPORT) || defined(ON_CLOSE_MODIFIED_SUPPORT)
+#if defined(ON_CLOSE_SUPPORT) || defined(ON_CLOSE_MODIFIED_SUPPORT)
 	DAZUKO_UNHOOK(dup2);
 #endif
 
diff -r -u -N -x {arch} -x .arch-ids dazuko--vendor--2.1/dazuko_linux26_syscall.c dazuko--contrib-symlink2--2.1/dazuko_linux26_syscall.c
--- dazuko--vendor--2.1/dazuko_linux26_syscall.c	1970-01-01 02:00:00.000000000 +0200
+++ dazuko--contrib-symlink2--2.1/dazuko_linux26_syscall.c	2006-03-03 15:26:26.000000000 +0200
@@ -0,0 +1,1830 @@
+/* Dazuko Linux. Allow Linux 2.6 file access control for 3rd-party applications.
+   Copyright (c) 2003, 2004, 2005 H+BEDV Datentechnik GmbH
+   Written by John Ogness <jogness@antivir.de>
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License
+   as published by the Free Software Foundation; either version 2
+   of the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*/
+
+#include "dazuko_linux26_syscall.h"
+#include "dazuko_core.h"
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/vermagic.h>
+#include <linux/file.h>
+#include <linux/sched.h>
+#include <linux/dcache.h>
+#include <linux/namei.h>
+#include <linux/mount.h>
+#include <linux/devfs_fs_kernel.h>
+#include <linux/device.h>
+#if !defined(USE_TRYTOFREEZEVOID) && !defined(USE_SUSPEND2)
+#include <linux/suspend.h>
+#endif
+#include <asm/uaccess.h>
+#include <linux/ptrace.h>
+#include <asm/unistd.h>
+#include <linux/syscalls.h>
+
+
+#ifndef DAZUKO_DM
+#define DAZUKO_DM 0
+#endif
+
+#ifdef HIDDEN_SCT
+void **sys_call_table;
+extern asmlinkage long sys_exit(int error_code);
+#else
+extern void *sys_call_table[];
+#endif
+
+#define CHROOT_EVENT_STRING "chroot:"
+#define CHROOT_EVENT_LENGTH 7
+
+
+#ifndef WITH_LOCAL_DPATH
+extern char * __d_path(struct dentry *, struct vfsmount *, struct dentry *, struct vfsmount *, char *, int);
+#endif
+
+ssize_t linux_dazuko_device_read(struct file *, char __user *, size_t, loff_t *);
+ssize_t linux_dazuko_device_write(struct file *, const char __user *, size_t, loff_t *);
+int linux_dazuko_device_open(struct inode *, struct file *);
+int linux_dazuko_device_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long param);
+int linux_dazuko_device_release(struct inode *, struct file *);
+
+#ifdef USE_CLASS
+static struct class *dazuko_class = NULL;
+#else
+static struct class_simple *dazuko_class = NULL;
+#endif
+
+static struct vfsmount  *orig_rootmnt = NULL;
+static struct dentry    *orig_root = NULL;
+static int dev_major = -1;
+
+#if defined(ON_OPEN_SUPPORT)
+static asmlinkage long          (*original_sys_open)(const char __user *filename, int flags, int mode);
+static asmlinkage long          (*original_sys_creat)(const char __user *filename, int mode);
+#endif
+#if defined(ON_CLOSE_SUPPORT) || defined(ON_CLOSE_MODIFIED_SUPPORT)
+static asmlinkage long          (*original_sys_dup2)(unsigned int oldfd, unsigned int newfd);
+#endif
+#if defined(ON_CLOSE_SUPPORT) || defined(ON_CLOSE_MODIFIED_SUPPORT)
+static asmlinkage long          (*original_sys_close)(unsigned int fd);
+#endif
+#ifdef ON_EXEC_SUPPORT
+static asmlinkage int           (*original_sys_execve)(struct pt_regs regs);
+#endif
+#ifdef ON_UNLINK_SUPPORT
+static asmlinkage long		(*original_sys_unlink)(const char __user *pathname);
+#endif
+#ifdef ON_RMDIR_SUPPORT
+static asmlinkage long		(*original_sys_rmdir)(const char __user *pathname);
+#endif
+
+static struct file_operations	fops = {
+		.owner		= THIS_MODULE,
+		.read		= linux_dazuko_device_read,
+		.write		= linux_dazuko_device_write,
+		.ioctl		= linux_dazuko_device_ioctl,
+		.open		= linux_dazuko_device_open,
+		.release	= linux_dazuko_device_release,
+	};
+
+
+/* mutex */
+
+inline void xp_init_mutex(struct xp_mutex *mutex)
+{
+	init_MUTEX(&(mutex->mutex));
+}
+
+inline void xp_down(struct xp_mutex *mutex)
+{
+	down(&(mutex->mutex));
+}
+
+inline void xp_up(struct xp_mutex *mutex)
+{
+	up(&(mutex->mutex));
+}
+
+inline void xp_destroy_mutex(struct xp_mutex *mutex)
+{
+}
+
+
+/* read-write lock */
+
+inline void xp_init_rwlock(struct xp_rwlock *rwlock)
+{
+	rwlock_init(&(rwlock->rwlock));
+}
+
+inline void xp_write_lock(struct xp_rwlock *rwlock)
+{
+	write_lock(&(rwlock->rwlock));
+}
+
+inline void xp_write_unlock(struct xp_rwlock *rwlock)
+{
+	write_unlock(&(rwlock->rwlock));
+}
+
+inline void xp_read_lock(struct xp_rwlock *rlock)
+{
+	read_lock(&(rlock->rwlock));
+}
+
+inline void xp_read_unlock(struct xp_rwlock *rlock)
+{
+	read_unlock(&(rlock->rwlock));
+}
+
+inline void xp_destroy_rwlock(struct xp_rwlock *rwlock)
+{
+}
+
+
+/* wait-notify queue */
+
+inline int xp_init_queue(struct xp_queue *queue)
+{
+	init_waitqueue_head(&(queue->queue));
+	return 0;
+}
+
+inline int xp_wait_until_condition(struct xp_queue *queue, int (*cfunction)(void *), void *cparam, int allow_interrupt)
+{
+	/* wait until cfunction(cparam) != 0 (condition is true) */
+	int	ret = 0;
+
+	if (allow_interrupt)
+	{
+		while (1)
+		{
+			ret = wait_event_interruptible(queue->queue, cfunction(cparam) != 0);
+
+#ifdef USE_SUSPEND2
+			if (try_todo_list() == 0)
+				break;
+#elif defined (USE_TRYTOFREEZEVOID)
+			if (try_to_freeze() == 0)
+				break;
+#else
+			if (current->flags & PF_FREEZE)
+			{
+				refrigerator(PF_FREEZE);
+			}
+			else
+			{
+				break;
+			}
+#endif
+		}
+	}
+	else
+	{
+		wait_event(queue->queue, cfunction(cparam) != 0);
+	}
+
+	return ret;
+}
+
+inline int xp_notify(struct xp_queue *queue)
+{
+	wake_up(&(queue->queue));
+	return 0;
+}
+
+inline int xp_destroy_queue(struct xp_queue *queue)
+{
+	return 0;
+}
+
+
+/* memory */
+
+inline void* xp_malloc(size_t size)
+{
+	return kmalloc(size, GFP_ATOMIC);
+}
+
+inline int xp_free(void *ptr)
+{
+	kfree(ptr);
+	return 0;
+}
+
+inline int xp_copyin(const void *user_src, void *kernel_dest, size_t size)
+{
+	return copy_from_user(kernel_dest, user_src, size);
+}
+
+inline int xp_copyout(const void *kernel_src, void *user_dest, size_t size)
+{
+	return copy_to_user(user_dest, kernel_src, size);
+}
+
+inline int xp_verify_user_writable(const void *user_ptr, size_t size)
+{
+	return 0;
+}
+
+inline int xp_verify_user_readable(const void *user_ptr, size_t size)
+{
+	return 0;
+}
+
+
+/* path attribute */
+
+inline int xp_is_absolute_path(const char *path)
+{
+	if (path[0] == '/')
+		return 1;
+
+#ifdef USE_CHROOT
+	if (dazuko_get_filename_length(path) >= CHROOT_EVENT_LENGTH)
+	{
+		if (memcmp(CHROOT_EVENT_STRING, path, CHROOT_EVENT_LENGTH) == 0)
+			return 1;
+	}
+#endif
+
+	return 0;
+}
+
+
+/* atomic */
+
+inline int xp_atomic_set(struct xp_atomic *atomic, int value)
+{
+	atomic_set(&(atomic->atomic), value);
+	return 0;
+}
+
+inline int xp_atomic_inc(struct xp_atomic *atomic)
+{
+	atomic_inc(&(atomic->atomic));
+	return 0;
+}
+
+inline int xp_atomic_dec(struct xp_atomic *atomic)
+{
+	atomic_dec(&(atomic->atomic));
+	return 0;
+}
+
+inline int xp_atomic_read(struct xp_atomic *atomic)
+{
+	return atomic_read(&(atomic->atomic));
+}
+
+/* Copied 1:1 from Linux kernel source kernel/exit.c */
+/* Why is this not exported? put_files_struct is exported! */
+
+struct files_struct *get_files_struct(struct task_struct *task)
+{
+        struct files_struct *files;
+
+        task_lock(task);
+        files = task->files;
+        if (files)
+                atomic_inc(&files->count);
+        task_unlock(task);
+
+        return files;
+}
+
+/* file structure */
+
+#ifdef WITH_LOCAL_DPATH
+/* This code is taken directy from:
+   linux-2.6.0/fs/dcache.c
+   because __d_path is no longer exported.
+ */
+/**
+ * d_path - return the path of a dentry
+ * @dentry: dentry to report
+ * @vfsmnt: vfsmnt to which the dentry belongs
+ * @root: root dentry
+ * @rootmnt: vfsmnt to which the root dentry belongs
+ * @buffer: buffer to return value in
+ * @buflen: buffer length
+ *
+ * Convert a dentry into an ASCII path name. If the entry has been deleted
+ * the string " (deleted)" is appended. Note that this is ambiguous.
+ *
+ * Returns the buffer or an error code if the path was too long.
+ *
+ * "buflen" should be positive. Caller holds the dcache_lock.
+ */
+static char * __d_path( struct dentry *dentry, struct vfsmount *vfsmnt,
+			struct dentry *root, struct vfsmount *rootmnt,
+			char *buffer, int buflen)
+{
+	char * end = buffer+buflen;
+	char * retval;
+	int namelen;
+
+	*--end = '\0';
+	buflen--;
+	if (!IS_ROOT(dentry) && d_unhashed(dentry)) {
+		buflen -= 10;
+		end -= 10;
+		if (buflen < 0)
+			goto Elong;
+		memcpy(end, " (deleted)", 10);
+	}
+
+	if (buflen < 1)
+		goto Elong;
+	/* Get '/' right */
+	retval = end-1;
+	*retval = '/';
+
+	for (;;) {
+		struct dentry * parent;
+
+		if (dentry == root && vfsmnt == rootmnt)
+			break;
+		if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
+			/* Global root? */
+			if (vfsmnt->mnt_parent == vfsmnt)
+				goto global_root;
+			dentry = vfsmnt->mnt_mountpoint;
+			vfsmnt = vfsmnt->mnt_parent;
+			continue;
+		}
+		parent = dentry->d_parent;
+		prefetch(parent);
+		namelen = dentry->d_name.len;
+		buflen -= namelen + 1;
+		if (buflen < 0)
+			goto Elong;
+		end -= namelen;
+		memcpy(end, dentry->d_name.name, namelen);
+		*--end = '/';
+		retval = end;
+		dentry = parent;
+	}
+
+	return retval;
+
+global_root:
+	namelen = dentry->d_name.len;
+	buflen -= namelen;
+	if (buflen < 0)
+		goto Elong;
+	retval -= namelen-1;	/* hit the slash */
+	memcpy(retval, dentry->d_name.name, namelen);
+	return retval;
+Elong:
+	return ERR_PTR(-ENAMETOOLONG);
+}
+#endif
+
+static int dazuko_get_filename_dentry(struct xp_file_struct *xfs, int follow_symlinks, const char *local_filename, int user_ptr)
+{
+	/* We get the appropriate structures in order
+	 * to acquire the inode and store them in the
+	 * dazuko_file_struct structure. */
+
+	const char	*filename = NULL;
+	int		putname_filename = 0;
+	int		filename_length = 0;
+	int		rc = 0;
+
+	/* make sure we really need to get the filename */
+	if (user_ptr)
+	{
+		/* grab filename from filename cache */
+		filename = (char *)getname(local_filename);
+
+		/* make sure it is a valid name */
+		if (IS_ERR(filename))
+		{
+			DPRINT(("dazuko_get_filename_dentry: getname failed\n"));
+			filename = NULL;
+			return 0;
+		}
+
+		/* the name will need to be put back */
+		putname_filename = 1;
+	}
+	else
+	{
+		filename = local_filename;
+	}
+
+	filename_length = dazuko_get_filename_length(filename);
+
+	dazuko_bzero(&(xfs->nd), sizeof(struct nameidata));
+
+	if (!xfs->path_release_nd)
+	{
+		/* find file data and fill it in nameidata structure */
+		if (path_lookup(filename, follow_symlinks ? LOOKUP_FOLLOW : 0, &(xfs->nd))) {
+			DPRINT(("dazuko_get_filename_dentry: path_lookup failed\n"));
+			goto dentry_exit;
+		}
+
+		/* the nameidata will need to be released */
+		xfs->path_release_nd = 1;
+	}
+
+	/* get a local copy of the dentry to make kernel version
+	 * compatibility code eaiser to read */
+
+	/* make sure we don't already have a dentry */
+	if (!xfs->dput_dentry)
+	{
+		xfs->dentry = dget(xfs->nd.dentry);
+
+		/* the dentry will need to be put back */
+		xfs->dput_dentry = 1;
+	}
+
+	/* check if this file has no inode */
+	if (xfs->dentry->d_inode == NULL)
+	{
+		DPRINT(("dazuko_get_filename_dentry: inode is NULL\n"));
+		goto dentry_exit;
+	}
+	else
+	{
+		/* if we made it this far, we got the inode */
+		rc = 1;
+	}
+
+dentry_exit:
+	if (putname_filename)
+		putname(filename);
+
+	DPRINT(("dazuko_get_filename_dentry returning %d\n", rc));
+	return rc;
+}
+
+static int dazuko_get_fd_dentry(struct xp_file_struct *xfs)
+{
+	struct files_struct *files = NULL;
+	struct file *file = NULL;
+
+	if (unlikely(current == NULL)) {
+		return 0;
+	}
+
+	files = get_files_struct(current);
+	if (!files) {
+		return 0;
+	}
+	spin_lock(&files->file_lock);
+
+	if (likely(files->fd != NULL))
+	{
+		file = fcheck_files(files, xfs->fd);
+		if (file)
+		{
+			xfs->dentry = dget(file->f_dentry);
+			xfs->vfsmount = mntget(file->f_vfsmnt);
+		}
+	}
+
+	spin_unlock(&files->file_lock);
+	put_files_struct(files);
+
+	if (xfs->dentry == NULL || xfs->vfsmount == NULL) {
+		dput(xfs->dentry);
+		mntput(xfs->vfsmount);
+		xfs->dentry = NULL;
+		xfs->vfsmount = NULL;
+	} else {
+		xfs->dput_dentry = xfs->mntput_vfsmount = 1;
+	}
+
+	/* check if we got the dentry */
+	if (xfs->dentry == NULL)
+		return 0;
+
+	/* check if this file has no inode */
+	if (xfs->dentry->d_inode == NULL)
+		return 0;
+
+	return 1;
+}
+
+/* From 2.4 */
+static int dazuko_get_full_filename(struct xp_file_struct *xfs)
+{
+	/* Get the filename with the full path appended
+	 * to the beginning. */
+
+	char		*temp;
+	struct dentry	*root;
+	struct vfsmount	*rootmnt;
+#ifdef USE_CHROOT
+	int chrooted = 0;
+#endif
+
+	/* check if we need to allocate a buffer */
+	if (!xfs->free_page_buffer)
+	{
+		/* get pre-requisites for d_path function */
+		xfs->buffer = (char *)__get_free_page(GFP_USER);
+
+		/* the buffer will need to be freed */
+		xfs->free_page_buffer = 1;
+	}
+
+	root = dget(orig_root);
+
+	/* make sure we don't already have a vfsmount */
+	if (!xfs->mntput_vfsmount)
+	{
+		xfs->vfsmount = mntget(xfs->nd.mnt);
+
+		/* the vfsmount will need to be put back */
+		xfs->mntput_vfsmount = 1;
+	}
+
+	/* build new filename with path included, using temp */
+
+	rootmnt = mntget(orig_rootmnt);
+
+#ifdef USE_CHROOT
+	temp = d_path(xfs->dentry, xfs->vfsmount, xfs->buffer, PAGE_SIZE);
+
+	task_lock(current);
+	if (orig_root != current->fs->root)
+		chrooted = 1;
+	task_unlock(current);
+#else
+	spin_lock(&dcache_lock);
+	temp = __d_path(xfs->dentry, xfs->vfsmount, root, rootmnt, xfs->buffer, PAGE_SIZE);
+	spin_unlock(&dcache_lock);
+#endif
+
+	dput(root);
+	mntput(rootmnt);
+
+	/* make sure we really got a new filename */
+	if (temp == NULL)
+		return 0;
+
+	/* make sure we don't already have a full_filename */
+	if (!xfs->free_full_filename)
+	{
+		xfs->full_filename_length = dazuko_get_filename_length(temp);
+
+#ifdef USE_CHROOT
+		if (chrooted)
+			xfs->full_filename_length += CHROOT_EVENT_LENGTH;
+#endif
+		xfs->full_filename = (char *)xp_malloc(xfs->full_filename_length + 1);
+		if (!xfs->full_filename)
+			return 0;
+
+		/* the char array will need to be freed */
+		xfs->free_full_filename = 1;
+
+#ifdef USE_CHROOT
+		if (chrooted)
+		{
+			memcpy(xfs->full_filename, CHROOT_EVENT_STRING, CHROOT_EVENT_LENGTH + 1);
+			memcpy(xfs->full_filename + CHROOT_EVENT_LENGTH, temp, xfs->full_filename_length - CHROOT_EVENT_LENGTH + 1);
+		}
+		else
+#endif
+		memcpy(xfs->full_filename, temp, xfs->full_filename_length + 1);
+	}
+
+	/* we have a filename with the full path */
+
+	return 1;
+}
+
+static inline int dazuko_fill_file_struct_cleanup(struct dazuko_file_struct *dfs)
+{
+	/* Delete all the flagged structures from the
+	 * given dazuko_file_struct and reset all critical
+	 * values back to 0. */
+
+	if (dfs->extra_data == NULL)
+		return 0;
+
+	if (dfs->extra_data->mntput_vfsmount)
+	{
+		mntput(dfs->extra_data->vfsmount);
+		dfs->extra_data->mntput_vfsmount = 0;
+	}
+
+	if (dfs->extra_data->free_page_buffer)
+	{
+		free_page((unsigned long)dfs->extra_data->buffer);
+		dfs->extra_data->free_page_buffer = 0;
+	}
+
+	if (dfs->extra_data->dput_dentry)
+	{
+		dput(dfs->extra_data->dentry);
+		dfs->extra_data->dput_dentry = 0;
+	}
+
+	if (dfs->extra_data->path_release_nd)
+	{
+		path_release(&(dfs->extra_data->nd));
+		dfs->extra_data->path_release_nd = 0;
+	}
+
+	return 0;
+}
+
+inline int xp_fill_file_struct(struct dazuko_file_struct *dfs)
+{
+	struct dazuko_file_listnode	*listnode;
+	int				follow_symlinks = 0;
+	int				error = -1;
+	int				loopcount = 0;
+	char				*freeparentpath = NULL;
+	char				*parentpath = NULL;
+	char				*rawfilename = NULL;
+	int				i;
+
+	if (dfs == NULL)
+		return error;
+
+	/* check if filenames have already been filled in */
+	if (dfs->aliases != NULL)
+		return 0;
+
+	if (dfs->extra_data == NULL)
+		return error;
+
+	/* make sure we can get an inode */
+	while (1)
+	{
+		loopcount++;
+
+		if (dfs->extra_data->user_filename != NULL)
+		{
+			if (!dazuko_get_filename_dentry(dfs->extra_data, follow_symlinks, dfs->extra_data->user_filename, 1))
+			{
+				/* we will try to build a "fake" name from the parent directory */
+
+				freeparentpath = getname(dfs->extra_data->user_filename);
+				/* make sure it is a valid name */
+				if (IS_ERR(freeparentpath))
+				{
+					freeparentpath = NULL;
+					DPRINT(("%s: getname failed\n", dfs->extra_data->user_filename));
+					break;
+				}
+
+				parentpath = freeparentpath;
+
+				i = dazuko_get_filename_length(parentpath);
+				if (i == 0)
+					break;
+
+				while (i > 0)
+				{
+					if (parentpath[i] == '/')
+					{
+						rawfilename = parentpath + i + 1;
+						parentpath[i] = 0;
+						break;
+					}
+
+					i--;
+				}
+				if (i == 0)
+				{
+					if (parentpath[i] == '/')
+					{
+						rawfilename = parentpath + 1;
+						parentpath = "/";
+					}
+					else
+					{
+						rawfilename = parentpath;
+						parentpath = ".";
+					}
+				}
+
+				if (!dazuko_get_filename_dentry(dfs->extra_data, follow_symlinks, parentpath, 0))
+				{
+					putname(freeparentpath);
+					freeparentpath = NULL;
+					DPRINT(("dazuko_get_filename_dentry failed for %s\n", parentpath));
+					break;
+				}
+			}
+		}
+		else
+		{
+			if (!dazuko_get_fd_dentry(dfs->extra_data))
+			{
+				DPRINT(("dazuko_get_fd_dentry failed\n"));
+				break;
+			}
+			else
+			{
+				/* make sure we don't loop a 2nd time */
+				loopcount++;
+			}
+		}
+
+		/* make sure we can get the full path */
+		if (!dazuko_get_full_filename(dfs->extra_data)) 
+		{
+			DPRINT(("dazuko_get_full_filename failed for %s\n", dfs->extra_data->user_filename));
+			break;
+		}
+
+		if (freeparentpath != NULL)
+		{
+			DPRINT(("building full path at loop=%d, we have %s\n", loopcount, dfs->extra_data->full_filename));
+			/* we are working with a "fake" name */
+
+			parentpath = dfs->extra_data->full_filename;
+			i =  dazuko_get_filename_length(rawfilename);
+
+			dfs->extra_data->full_filename = (char *)xp_malloc(dfs->extra_data->full_filename_length + 1 + i + 1);
+			if (dfs->extra_data->full_filename == NULL)
+			{
+				/* put things back how they were and get out */
+				dfs->extra_data->full_filename = parentpath;
+				break;
+			}
+
+			/* copy parent path */
+			memcpy(dfs->extra_data->full_filename, parentpath, dfs->extra_data->full_filename_length);
+
+			/* possibly copy "/" */
+			if (dfs->extra_data->full_filename[dfs->extra_data->full_filename_length - 1] != '/')
+			{
+				dfs->extra_data->full_filename[dfs->extra_data->full_filename_length] = '/';
+				dfs->extra_data->full_filename_length++;
+			}
+
+			/* copy filename */
+			memcpy(dfs->extra_data->full_filename + dfs->extra_data->full_filename_length, rawfilename, i + 1);
+			dfs->extra_data->full_filename_length += i;
+			DPRINT(("constructed full filename: %s\n", dfs->extra_data->full_filename));
+
+			/* Clean up dfs so that it can be reused for the new dentry */
+			dazuko_fill_file_struct_cleanup(dfs);
+
+			if (!dazuko_get_filename_dentry(dfs->extra_data, follow_symlinks, dfs->extra_data->full_filename, 0))
+			{
+				xp_free(parentpath);
+				DPRINT(("dazuko_get_filename_dentry failed for constructed filename %s\n", dfs->extra_data->full_filename));
+				break;
+			}
+
+			/* free allocated parent path */
+			xp_free(parentpath);
+		}
+
+		DPRINT(("we have full path at loop=%d, %s\n", loopcount, dfs->extra_data->full_filename));
+
+		/* TODO: We have a pointer to dentry and have incremented its use count.
+		 * But can we assume we can access the inode without some kind of
+		 * locking or use count increment?
+		 */
+		dfs->file_p.size = dfs->extra_data->dentry->d_inode->i_size;
+		dfs->file_p.set_size = 1;
+		dfs->file_p.uid = dfs->extra_data->dentry->d_inode->i_uid;
+		dfs->file_p.set_uid = 1;
+		dfs->file_p.gid = dfs->extra_data->dentry->d_inode->i_gid;
+		dfs->file_p.set_gid = 1;
+		dfs->file_p.mode = dfs->extra_data->dentry->d_inode->i_mode;
+		dfs->file_p.set_mode = 1;
+		/* TODO: figure out where to get device number in 2.6 kernel */
+#if 0
+		dfs->file_p.device_type = dfs->extra_data->dentry->d_inode->i_dev;
+		dfs->file_p.set_device_type = 1;
+#endif
+
+		if (S_ISREG(dfs->extra_data->dentry->d_inode->i_mode))
+		{
+			DPRINT(("inode is regular file\n"));
+			dfs->file_p.type = DAZUKO_REGULAR;
+			dfs->file_p.set_type = 1;
+		}
+		else if (S_ISLNK(dfs->extra_data->dentry->d_inode->i_mode))
+		{
+			DPRINT(("inode is symlink\n"));
+			dfs->file_p.type = DAZUKO_LINK;
+			dfs->file_p.set_type = 1;
+		}
+		else if (S_ISDIR(dfs->extra_data->dentry->d_inode->i_mode))
+		{
+			DPRINT(("inode is a directory\n"));
+			dfs->file_p.type = DAZUKO_DIRECTORY;
+			dfs->file_p.set_type = 1;
+			error = -1;
+			break;
+		}
+
+		listnode = (struct dazuko_file_listnode *)xp_malloc(sizeof(struct dazuko_file_listnode));
+		if (listnode == NULL)
+			break;
+
+		dazuko_bzero(listnode, sizeof(struct dazuko_file_listnode));
+
+		listnode->filename = dfs->extra_data->full_filename;
+		listnode->filename_length = dfs->extra_data->full_filename_length;  /* the string length */
+
+		dfs->extra_data->free_full_filename = 0;
+		dfs->extra_data->full_filename = NULL;
+		dfs->extra_data->full_filename_length = 0;
+
+		if (dfs->aliases == NULL)
+		{
+			listnode->next = dfs->aliases;
+			dfs->aliases = listnode;
+		}
+		else
+		{
+			listnode->next = dfs->aliases->next;
+			dfs->aliases->next = listnode;
+		}
+
+		/* we successfully got the file information */
+		error = 0;
+
+		if (!follow_symlinks && dfs->file_p.set_type && dfs->file_p.type == DAZUKO_LINK && loopcount < 2)
+		{
+			/* this is a link, we will grab the real path now */
+
+			follow_symlinks = 1;
+
+			/* clean up because we are going to fill it again */
+			dazuko_fill_file_struct_cleanup(dfs);
+		}
+		else
+		{
+			/* we've grabbed the real path (or we already have 2 paths), so we are done */
+
+			break;
+		}
+	}
+
+	if (freeparentpath != NULL)
+		putname(freeparentpath);
+
+	dazuko_fill_file_struct_cleanup(dfs);
+
+	DPRINT(("xp_fill_file_struct returning %d\n", error));
+
+	return error;
+}
+
+static int dazuko_file_struct_cleanup(struct dazuko_file_struct **dfs)
+{
+	struct dazuko_file_listnode	*cur;
+
+	if (dfs == NULL)
+		return 0;
+
+	if (*dfs == NULL)
+		return 0;
+
+	while ((*dfs)->aliases != NULL)
+	{
+		cur = (*dfs)->aliases;
+		(*dfs)->aliases = cur->next;
+
+		if (cur->filename != NULL)
+			xp_free(cur->filename);
+
+		xp_free(cur);
+	}
+
+	if ((*dfs)->extra_data != NULL)
+		xp_free((*dfs)->extra_data);
+
+	xp_free(*dfs);
+
+	*dfs = NULL;
+
+	return 0;
+}
+
+/* daemon id */
+
+static inline int check_parent(struct task_struct *parent, struct task_struct *child)
+{
+	struct task_struct	*ts = child;
+
+	if (parent == NULL || child == NULL)
+		return -1;
+
+	while (1)
+	{
+		if (ts == parent)
+			return 0;
+
+		if (ts->parent == NULL)
+			break;
+
+		if (ts == ts->parent)
+			break;
+
+		ts = ts->parent;
+	}
+
+	return -1;
+}
+
+inline int xp_id_compare(struct xp_daemon_id *id1, struct xp_daemon_id *id2, int check_related)
+{
+	if (id1 == NULL || id2 == NULL)
+		return DAZUKO_DIFFERENT;
+
+	/* if file's are available and they match,
+	 * then we say that the id's match
+	 * ("file" is only used to unregister daemons and
+	 * here we allow other processes to do this)
+	 * Note: this is a Linux-only "hack" */
+	if (id1->file != NULL && id1->file == id2->file)
+		return DAZUKO_SAME;
+
+	if (id1->pid == id2->pid && id1->current_p == id2->current_p && id1->files == id2->files)
+		return DAZUKO_SAME;
+
+	if (check_related)
+	{
+		if (check_parent(id1->current_p, id2->current_p) == 0)
+		{
+			return DAZUKO_CHILD;
+		}
+		else if (id1->pid == id2->pid || id1->current_p == id2->current_p || id1->files == id2->files)
+		{
+			return DAZUKO_SUSPICIOUS;
+		}
+	}
+
+	return DAZUKO_DIFFERENT;
+}
+
+inline int xp_id_free(struct xp_daemon_id *id)
+{
+	xp_free(id);
+
+	return 0;
+}
+
+inline struct xp_daemon_id* xp_id_copy(struct xp_daemon_id *id)
+{
+	struct xp_daemon_id	*ptr;
+
+	if (id == NULL)
+		return NULL;
+
+	ptr = (struct xp_daemon_id *)xp_malloc(sizeof(struct xp_daemon_id));
+
+	if (ptr != NULL)
+	{
+		ptr->pid = id->pid;
+		ptr->file = id->file;
+		ptr->current_p = id->current_p;
+		ptr->files = id->files;
+	}
+
+	return ptr;
+}
+
+
+/* event */
+
+int xp_set_event_properties(struct event_properties *event_p, struct xp_daemon_id *xp_id)
+{
+	event_p->pid = xp_id->pid;
+	event_p->set_pid = 1;
+
+	return 0;
+}
+
+
+/* cache settings */
+
+int xp_init_cache(unsigned long ttl)
+{
+	return -1;
+}
+
+
+/* system calls */
+
+#if defined(ON_OPEN_SUPPORT)
+asmlinkage long	linux_dazuko_sys_open(const char __user *filename, int flags, int mode)
+{
+	/* The kernel wants to open the given filename
+	 * with the given flags and mode. The dazuko_file_struct
+	 * is used to handle the tricky job of cleaning
+	 * up the many pieces of memory that may or may
+	 * not be allocated. */
+
+	struct dazuko_file_struct	*dfs = NULL;
+	int				error = 0;
+	int				fd;
+	int				check_error = 0;
+	struct event_properties		event_p;
+	struct xp_daemon_id		xp_id;
+
+	fd = original_sys_open(filename, flags, mode);
+
+	xp_id.pid = current->pid;
+	xp_id.file = NULL;
+	xp_id.current_p = current;
+	xp_id.files = get_files_struct(current);
+
+	check_error = dazuko_check_access(DAZUKO_ON_OPEN, 1, &xp_id, NULL);
+
+	put_files_struct(xp_id.files);
+
+	if (!check_error)
+	{
+		dazuko_bzero(&event_p, sizeof(event_p));
+		event_p.flags = flags;
+		event_p.set_flags = 1;
+		event_p.mode = mode;
+		event_p.set_mode = 1;
+		event_p.pid = current->pid;
+		event_p.set_pid = 1;
+		event_p.uid = current->uid;
+		event_p.set_uid = 1;
+
+		dfs = (struct dazuko_file_struct *)xp_malloc(sizeof(struct dazuko_file_struct));
+		if (dfs != NULL)
+		{
+			dazuko_bzero(dfs, sizeof(struct dazuko_file_struct));
+
+			dfs->extra_data = (struct xp_file_struct *)xp_malloc(sizeof(struct xp_file_struct));
+			if (dfs->extra_data != NULL)
+			{
+				dazuko_bzero(dfs->extra_data, sizeof(struct xp_file_struct));
+
+				dfs->extra_data->user_filename = filename;
+
+				error = dazuko_process_access(DAZUKO_ON_OPEN, dfs, &event_p, NULL);
+
+				dazuko_file_struct_cleanup(&dfs);
+			}
+			else
+			{
+				xp_free(dfs);
+				dfs = NULL;
+			}
+		}
+	}
+
+	if (error)
+	{
+		/* access should be blocked */
+		original_sys_close(fd);
+		fd = -1;
+	}
+
+	return fd;
+}
+
+asmlinkage long	linux_dazuko_sys_creat(const char __user *filename, int mode)
+{
+	return linux_dazuko_sys_open(filename, O_CREAT | O_WRONLY | O_TRUNC, mode);
+}
+#endif
+
+#if defined(ON_CLOSE_SUPPORT) || defined(ON_CLOSE_MODIFIED_SUPPORT)
+asmlinkage long linux_dazuko_sys_dup2(unsigned int oldfd, unsigned int newfd)
+{
+	struct dazuko_file_struct	*dfs = NULL;
+	struct xp_daemon_id		xp_id;
+	int				error = 0;
+	int				check_error = 0;
+	struct event_properties		close_event_p;
+	int				will_close_newfd = 0;
+
+	xp_id.pid = current->pid;
+	xp_id.file = NULL;
+	xp_id.current_p = current;
+	xp_id.files = get_files_struct(current);
+
+	check_error = dazuko_check_access(DAZUKO_ON_CLOSE, 1, &xp_id, NULL);
+
+	if (newfd >= 0 && newfd < xp_id.files->max_fds)
+	{
+		spin_lock(&xp_id.files->file_lock);
+
+		if (fcheck_files(xp_id.files, newfd) != NULL)
+		{
+			will_close_newfd = 1;
+		}
+
+		spin_unlock(&xp_id.files->file_lock);
+	}
+
+	put_files_struct(xp_id.files);
+
+	/* call the standard open function */
+	error = original_sys_dup2(oldfd, newfd);
+
+	if (!check_error)
+	{
+		if (error >= 0 && will_close_newfd)
+		{
+			dazuko_bzero(&close_event_p, sizeof(close_event_p));
+
+			close_event_p.pid = current->pid;
+			close_event_p.set_pid = 1;
+			close_event_p.uid = current->uid;
+			close_event_p.set_uid = 1;
+
+			dfs = (struct dazuko_file_struct *)xp_malloc(sizeof(struct dazuko_file_struct));
+			if (dfs != NULL)
+			{
+				dazuko_bzero(dfs, sizeof(struct dazuko_file_struct));
+
+				dfs->extra_data = (struct xp_file_struct *)xp_malloc(sizeof(struct xp_file_struct));
+				if (dfs->extra_data != NULL)
+				{
+					dazuko_bzero(dfs->extra_data, sizeof(struct xp_file_struct));
+
+					dfs->extra_data->fd = newfd;
+
+					error = dazuko_process_access(DAZUKO_ON_CLOSE, dfs, &close_event_p, NULL);
+
+					dazuko_file_struct_cleanup(&dfs);
+				}
+				else
+				{
+					xp_free(dfs);
+					dfs = NULL;
+				}
+			}
+		}
+	}
+
+	return error;
+}
+#endif
+
+#if defined(ON_CLOSE_SUPPORT) || defined(ON_CLOSE_MODIFIED_SUPPORT)
+asmlinkage long	linux_dazuko_sys_close(unsigned int fd)
+{
+	/* The kernel wants to close the given file
+	 * descriptor. */
+
+	struct dazuko_file_struct	*dfs = NULL;
+	int				error = 0;
+	int				check_error = 0;
+	struct event_properties		event_p;
+	struct xp_daemon_id		xp_id;
+
+	xp_id.pid = current->pid;
+	xp_id.file = NULL;
+	xp_id.current_p = current;
+	xp_id.files = get_files_struct(current);
+
+	check_error = dazuko_check_access(DAZUKO_ON_CLOSE, 1, &xp_id, NULL);
+
+	if (!check_error && fd >= 0 && fd < xp_id.files->max_fds)
+	{
+		dazuko_bzero(&event_p, sizeof(event_p));
+
+		event_p.pid = current->pid;
+		event_p.set_pid = 1;
+		event_p.uid = current->uid;
+		event_p.set_uid = 1;
+
+		dfs = (struct dazuko_file_struct *)xp_malloc(sizeof(struct dazuko_file_struct));
+		if (dfs != NULL)
+		{
+			dazuko_bzero(dfs, sizeof(struct dazuko_file_struct));
+
+			dfs->extra_data = (struct xp_file_struct *)xp_malloc(sizeof(struct xp_file_struct));
+			if (dfs->extra_data != NULL)
+			{
+				dazuko_bzero(dfs->extra_data, sizeof(struct xp_file_struct));
+
+				dfs->extra_data->fd = fd;
+
+				check_error = xp_fill_file_struct(dfs);
+			}
+			else
+			{
+				xp_free(dfs);
+				dfs = NULL;
+			}
+		}
+	}
+
+	put_files_struct(xp_id.files);
+
+	error = original_sys_close(fd);
+
+	if (dfs != NULL)
+	{
+		if (!check_error)
+		{
+			error = dazuko_process_access(DAZUKO_ON_CLOSE, dfs, &event_p, NULL);
+		}
+
+		dazuko_file_struct_cleanup(&dfs);
+	}
+
+	return error;
+}
+#endif
+
+#ifdef ON_EXEC_SUPPORT
+
+typedef int (*do_execve_call_t)(char *filename, 
+				char __user *__user *argv,
+				char __user *__user *envp,
+				struct pt_regs *regs);
+
+static do_execve_call_t XXX_do_execve = (do_execve_call_t) DO_EXECVE_ADDR;
+
+asmlinkage int linux_dazuko_sys_execve(struct pt_regs regs)
+{
+	/* The kernel wants to execute the given file.
+	 * Because the given structure contains stack
+	 * address information, we can't simply call
+	 * the default standard execve. Instead we
+	 * have to manually inline the standard execve
+	 * call. */
+
+	struct dazuko_file_struct	*dfs = NULL;
+	char				*filename;
+	int				error = 0;
+	int				check_error = 0;
+	struct event_properties		event_p;
+	struct xp_daemon_id		xp_id;
+	struct slot_list		*sl = NULL;
+
+	xp_id.pid = current->pid;
+	xp_id.file = NULL;
+	xp_id.current_p = current;
+	xp_id.files = get_files_struct(current);
+
+	check_error = dazuko_check_access(DAZUKO_ON_EXEC, 0, &xp_id, &sl);
+
+	put_files_struct(xp_id.files);
+
+	if (!check_error)
+	{
+		dfs = (struct dazuko_file_struct *)xp_malloc(sizeof(struct dazuko_file_struct));
+		if (dfs)
+		{
+			dazuko_bzero(dfs, sizeof(struct dazuko_file_struct));
+
+			dfs->extra_data = (struct xp_file_struct *)xp_malloc(sizeof(struct xp_file_struct));
+			if (dfs->extra_data != NULL)
+			{
+				dazuko_bzero(dfs->extra_data, sizeof(struct xp_file_struct));
+
+				dfs->extra_data->user_filename = (char *)regs.ebx;
+
+				dazuko_bzero(&event_p, sizeof(event_p));
+				event_p.pid = current->pid;
+				event_p.set_pid = 1;
+				event_p.uid = current->uid;
+				event_p.set_uid = 1;
+
+				error = dazuko_process_access(DAZUKO_ON_EXEC, dfs, &event_p, sl);
+
+				dazuko_file_struct_cleanup(&dfs);
+			}
+			else
+			{
+				xp_free(dfs);
+				dfs = NULL;
+			}
+		}
+	}
+
+	if (error)
+	{
+		return error;
+	}
+
+	/* call the standard execve function */
+
+	/* We cannot simply call the original version of execvc
+	 * because the parameter contains stack information and
+	 * the call will push the execvc call onto a new stack
+	 * level and seg fault. :( */
+
+	/* The following code only works on i386 machines.
+	 * It is directly copied from Linux in the file:
+	 * arch/i386/kernel/process.c */
+
+        filename = getname((char __user *) regs.ebx);
+        error = PTR_ERR(filename);
+        if (IS_ERR(filename))
+                goto out;
+        error = XXX_do_execve(filename,
+                        (char __user * __user *) regs.ecx,
+                        (char __user * __user *) regs.edx,
+                        &regs);
+        if (error == 0) {
+                task_lock(current);
+                current->ptrace &= ~PT_DTRACE;
+                task_unlock(current);
+                /* Make sure we don't return using sysenter.. */
+                set_thread_flag(TIF_IRET);
+        }
+        putname(filename);
+
+out:
+	return error;
+}
+#endif
+
+static inline int linux_dazuko_sys_generic(int event, const char *user_pathname, int daemon_is_allowed)
+{
+	struct dazuko_file_struct	*dfs = NULL;
+	int				error = 0;
+	int				check_error = 0;
+	struct event_properties		event_p;
+	struct xp_daemon_id		xp_id;
+	struct slot_list		*sl = NULL;
+
+	xp_id.pid = current->pid;
+	xp_id.file = NULL;
+	xp_id.current_p = current;
+	xp_id.files = get_files_struct(current);
+
+	check_error = dazuko_check_access(event, daemon_is_allowed, &xp_id, &sl);
+
+	put_files_struct(xp_id.files);
+
+	if (!check_error)
+	{
+		dfs = (struct dazuko_file_struct *)xp_malloc(sizeof(struct dazuko_file_struct));
+		if (dfs)
+		{
+			dazuko_bzero(dfs, sizeof(struct dazuko_file_struct));
+
+			dfs->extra_data = (struct xp_file_struct *)xp_malloc(sizeof(struct xp_file_struct));
+			if (dfs->extra_data != NULL)
+			{
+				dazuko_bzero(dfs->extra_data, sizeof(struct xp_file_struct));
+
+				dfs->extra_data->user_filename = user_pathname;
+
+				dazuko_bzero(&event_p, sizeof(event_p));
+				event_p.pid = current->pid;
+				event_p.set_pid = 1;
+				event_p.uid = current->uid;
+				event_p.set_uid = 1;
+
+				error = dazuko_process_access(event, dfs, &event_p, sl);
+
+				dazuko_file_struct_cleanup(&dfs);
+			}
+			else
+			{
+				xp_free(dfs);
+				dfs = NULL;
+			}
+		}
+	}
+
+	return error;
+}
+
+#ifdef ON_UNLINK_SUPPORT
+asmlinkage long linux_dazuko_sys_unlink(const char *pathname)
+{
+	int	error;
+
+	error = linux_dazuko_sys_generic(DAZUKO_ON_UNLINK, pathname, 1);
+
+	if (error)
+		return error;
+
+	return original_sys_unlink(pathname);
+}
+#endif
+
+#ifdef ON_RMDIR_SUPPORT
+asmlinkage long linux_dazuko_sys_rmdir(const char *pathname)
+{
+	int	error;
+
+	error = linux_dazuko_sys_generic(DAZUKO_ON_RMDIR, pathname, 1);
+
+	if (error)
+		return error;
+
+	return original_sys_rmdir(pathname);
+}
+#endif
+
+/* system hook */
+
+#ifdef HIDDEN_SCT
+static void** dazuko_get_sct(void)
+{
+	unsigned long	ptr;
+	extern int	loops_per_jiffy;
+	unsigned long	*p;
+
+	for (ptr=(unsigned long)&loops_per_jiffy ; ptr<(unsigned long)&boot_cpu_data ; ptr+=sizeof(void *))
+	{
+		p = (unsigned long *)ptr;
+		if (p[6] == (unsigned long)sys_close)
+		{
+			return (void **)p;
+		}
+	}
+
+	return NULL;
+}
+#endif
+
+#define DAZUKO_HOOK(syscall_func) do \
+{ \
+	original_sys_##syscall_func = sys_call_table[__NR_##syscall_func]; \
+	sys_call_table[__NR_##syscall_func] = linux_dazuko_sys_##syscall_func; \
+	DPRINT(("dazuko: hooked sys_" #syscall_func "\n")); \
+} \
+while (0)
+
+inline int xp_sys_hook()
+{
+#ifdef HIDDEN_SCT
+	sys_call_table = dazuko_get_sct();
+	if (sys_call_table == NULL)
+	{
+		xp_print("dazuko: panic (sys_call_table == NULL)\n");
+		return -1;
+	}
+#endif
+
+	/* Make sure we have a valid task_struct. */
+
+	if (current == NULL)
+	{
+		xp_print("dazuko: panic (current == NULL)\n");
+		return -1;
+	}
+	/* Protect current->fs */
+	task_lock(current);
+	if (current->fs == NULL)
+	{
+		task_unlock(current);
+		xp_print("dazuko: panic (current->fs == NULL)\n");
+		return -1;
+	}
+	if (current->fs->root == NULL)
+	{
+		task_unlock(current);
+		xp_print("dazuko: panic (current->fs->root == NULL)\n");
+		return -1;
+	}
+	if (current->fs->rootmnt == NULL)
+	{
+		task_unlock(current);
+		xp_print("dazuko: panic (current->fs->rootmnt == NULL)\n");
+		return -1;
+	}
+
+
+#ifdef USE_CHROOT
+	xp_print("dazuko: info: using chroot events for chroot'd processes\n");
+#endif
+#if defined(CONFIG_SMP) && defined(WITH_LOCAL_DPATH)
+	xp_print("dazuko: warning: using local __dpath() dangerous for SMP kernels\n");
+#endif
+
+	/* Grab the current root. This is assumed to be the real.
+	 * If it is not the real root, we could have problems
+	 * looking up filenames. */
+
+	read_lock(&current->fs->lock);
+	orig_rootmnt = current->fs->rootmnt;
+	orig_root = current->fs->root;
+	read_unlock(&current->fs->lock);
+	task_unlock(current);
+
+	dev_major = register_chrdev(DAZUKO_DM, DEVICE_NAME, &fops);
+	if (dev_major < 0)
+	{
+		xp_print("dazuko: unable to register device, err=%d\n", dev_major);
+		return dev_major;
+	}
+
+	devfs_mk_cdev(MKDEV(dev_major, 0), S_IFCHR | S_IRUSR | S_IWUSR, DEVICE_NAME);
+
+#ifdef USE_CLASS
+	dazuko_class = class_create(THIS_MODULE, "dazuko");
+	class_device_create(dazuko_class, MKDEV(dev_major, 0), NULL, "dazuko");
+#else
+	dazuko_class = class_simple_create(THIS_MODULE, "dazuko");
+	class_simple_device_add(dazuko_class, MKDEV(dev_major, 0), NULL, "dazuko");
+#endif
+
+	/* do a file syncronization on all devices (IMPORTANT!) and replace system calls */
+	#ifdef __SMP__
+		lock_kernel();
+	#endif
+
+	/* TODO: Is this really necessary? */
+	/*fsync_dev(0);*/
+
+#if defined(ON_OPEN_SUPPORT)
+	DAZUKO_HOOK(open);
+	DAZUKO_HOOK(creat);
+#endif
+#if defined(ON_CLOSE_SUPPORT) || defined(ON_CLOSE_MODIFIED_SUPPORT)
+	DAZUKO_HOOK(dup2);
+#endif
+	
+#if defined(ON_CLOSE_SUPPORT) || defined(ON_CLOSE_MODIFIED_SUPPORT)
+	DAZUKO_HOOK(close);
+#endif
+
+#ifdef ON_EXEC_SUPPORT
+	DAZUKO_HOOK(execve);
+#endif
+
+#ifdef ON_UNLINK_SUPPORT
+	DAZUKO_HOOK(unlink);
+#endif
+
+#ifdef ON_RMDIR_SUPPORT
+	DAZUKO_HOOK(rmdir);
+#endif
+
+	#ifdef __SMP__
+		unlock_kernel();
+	#endif
+	/* done syncing and replacing */
+
+	/* initialization complete */
+
+	return 0;
+}
+
+#define DAZUKO_UNHOOK(syscall_func) do \
+{ \
+	if (sys_call_table[__NR_##syscall_func] != linux_dazuko_sys_##syscall_func) \
+		xp_print("dazuko: " #syscall_func " system call has been changed (system may be left in an unstable state!)\n"); \
+	sys_call_table[__NR_##syscall_func] = original_sys_##syscall_func; \
+	DPRINT(("dazuko: unhooked sys_" #syscall_func "\n")); \
+} \
+while (0)
+
+inline int xp_sys_unhook()
+{
+	/* do a file syncronization on all devices (IMPORTANT!) and replace system calls */
+	#ifdef __SMP__
+		lock_kernel();
+	#endif
+
+	/*fsync_dev(0);*/
+
+#if defined(ON_OPEN_SUPPORT)
+	DAZUKO_UNHOOK(open);
+	DAZUKO_UNHOOK(creat);
+#endif
+#if defined(ON_CLOSE_SUPPORT) || defined(ON_CLOSE_MODIFIED_SUPPORT)
+	DAZUKO_UNHOOK(dup2);
+#endif
+
+#if defined(ON_CLOSE_SUPPORT) || defined(ON_CLOSE_MODIFIED_SUPPORT)
+	DAZUKO_UNHOOK(close);
+#endif
+
+#ifdef ON_EXEC_SUPPORT
+	DAZUKO_UNHOOK(execve);
+#endif
+
+#ifdef ON_UNLINK_SUPPORT
+	DAZUKO_UNHOOK(unlink);
+#endif
+
+#ifdef ON_RMDIR_SUPPORT
+	DAZUKO_UNHOOK(rmdir);
+#endif
+
+	#ifdef __SMP__
+		unlock_kernel();
+	#endif
+	/* done syncing and replacing */
+
+	unregister_chrdev(dev_major, DEVICE_NAME);
+
+	devfs_remove(DEVICE_NAME);
+
+#ifdef USE_CLASS
+	class_device_destroy(dazuko_class, MKDEV(dev_major, 0));
+	class_destroy(dazuko_class);
+#else
+	class_simple_device_remove(MKDEV(dev_major, 0));
+	class_simple_destroy(dazuko_class);
+#endif
+
+	return 0;
+}
+
+
+/* output */
+
+int xp_print(const char *fmt, ...)
+{
+	va_list args;
+	char *p;
+	size_t size = 1024;
+	int length;
+
+	p = (char *)xp_malloc(size);
+	if (p == NULL)
+		return -1;
+
+	length = dazuko_get_filename_length(KERN_INFO);
+
+	memcpy(p, KERN_INFO, length);
+
+	va_start(args, fmt);
+	vsnprintf(p + length, size - length, fmt, args);
+	va_end(args);
+
+	p[size-1] = 0;
+
+	printk(p);
+
+	xp_free(p);
+
+	return 0;
+}
+
+
+/* ioctl's */
+
+int linux_dazuko_device_open(struct inode *inode, struct file *file)
+{
+	DPRINT(("dazuko: linux_dazuko_device_open() [%d]\n", current->pid));
+
+	return 0;
+}
+
+ssize_t linux_dazuko_device_read(struct file *file, char *buffer, size_t length, loff_t *pos)
+{
+	/* Reading from the dazuko device simply
+	 * returns the device number. This is to
+	 * help out the daemon. */
+
+	char    tmp[20];
+	size_t  dev_major_len;
+
+	DPRINT(("dazuko: linux_dazuko_device_read() [%d]\n", current->pid));
+	
+	if (*pos != 0)
+		return 0;
+
+	if (dev_major < 0)
+		return XP_ERROR_NODEVICE;
+
+	/* print dev_major to a string
+	 * and get length (with terminator) */
+	dazuko_bzero(tmp, sizeof(tmp));
+
+	dev_major_len = dazuko_snprintf(tmp, sizeof(tmp), "%d", dev_major) + 1;
+
+	if (tmp[sizeof(tmp)-1] != 0)
+	{
+		xp_print("dazuko: failing device_read, device number overflow for dameon %d (dev_major=%d)\n", current->pid, dev_major);
+		return XP_ERROR_FAULT;
+	}
+
+	if (length < dev_major_len)
+		return XP_ERROR_INVALID;
+
+	/* copy dev_major string to userspace */
+	if (xp_copyout(tmp, buffer, dev_major_len) != 0)
+		return XP_ERROR_FAULT;
+
+	*pos += dev_major_len;
+
+	return dev_major_len;
+}
+
+ssize_t linux_dazuko_device_write(struct file *file, const char *buffer, size_t length, loff_t *pos)
+{
+	struct xp_daemon_id	xp_id;
+	char			tmpbuffer[32];
+	int			size;
+
+	size = length;
+	if (length >= sizeof(tmpbuffer))
+		size = sizeof(tmpbuffer) -1;
+
+	/* copy request pointer string to kernelspace */
+	if (xp_copyin(buffer, tmpbuffer, size) != 0)
+		return XP_ERROR_FAULT;
+
+	tmpbuffer[size] = 0;
+
+	xp_id.pid = current->pid;
+	xp_id.file = file;
+	xp_id.current_p = current;
+	xp_id.files = current->files;
+
+	if (dazuko_handle_user_request(tmpbuffer, &xp_id) == 0)
+		return size;
+
+	return XP_ERROR_INTERRUPT;
+}
+
+int linux_dazuko_device_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long param)
+{
+	/* A daemon uses this function to interact with
+	 * the kernel. A daemon can set scanning parameters,
+	 * give scanning response, and get filenames to scan. */
+
+	struct xp_daemon_id	xp_id;
+	int			error = 0;
+
+	if (param == 0)
+	{
+		xp_print("dazuko: error: linux_dazuko_device_ioctl(..., 0)\n");
+		return XP_ERROR_INVALID;
+	}
+
+	xp_id.pid = current->pid;
+	xp_id.file = file;
+	xp_id.current_p = current;
+	xp_id.files = current->files;
+
+	error = dazuko_handle_user_request_compat1((void *)param, _IOC_NR(cmd), &xp_id);
+
+	if (error != 0)
+	{
+		/* general error occurred */
+
+		return XP_ERROR_PERMISSION;
+	}
+
+	return error;
+}
+
+int linux_dazuko_device_release(struct inode *inode, struct file *file)
+{
+	struct xp_daemon_id	xp_id;
+
+	DPRINT(("dazuko: dazuko_device_release() [%d]\n", current->pid));
+
+	xp_id.pid = current->pid;
+	xp_id.file = file;
+	xp_id.current_p = current;
+	xp_id.files = current->files;
+
+	return dazuko_unregister_daemon(&xp_id);
+}
+
+
+/* init/exit */
+
+static int __init linux_dazuko_init(void)
+{
+	return dazuko_init();
+}
+
+static void __exit linux_dazuko_exit(void)
+{
+	dazuko_exit();
+}
+
+
+MODULE_AUTHOR("H+BEDV Datentechnik GmbH <linux_support@antivir.de>");
+MODULE_DESCRIPTION("allow 3rd-party file access control");
+MODULE_LICENSE("GPL");
+MODULE_INFO(vermagic, VERMAGIC_STRING);
+
+#ifdef DAZUKO_FIST
+EXPORT_SYMBOL(dazuko_sys_generic);
+#endif
+
+security_initcall(linux_dazuko_init);
+module_exit(linux_dazuko_exit);
diff -r -u -N -x {arch} -x .arch-ids dazuko--vendor--2.1/dazuko_linux26_syscall.h dazuko--contrib-symlink2--2.1/dazuko_linux26_syscall.h
--- dazuko--vendor--2.1/dazuko_linux26_syscall.h	1970-01-01 02:00:00.000000000 +0200
+++ dazuko--contrib-symlink2--2.1/dazuko_linux26_syscall.h	2006-03-03 15:24:10.000000000 +0200
@@ -0,0 +1,82 @@
+/* Dazuko Linux. Allow Linux 2.6 file access control for 3rd-party applications.
+   Copyright (c) 2003, 2004, 2005 H+BEDV Datentechnik GmbH
+   Written by John Ogness <jogness@antivir.de>
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License
+   as published by the Free Software Foundation; either version 2
+   of the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*/
+
+#ifndef DAZUKO_LINUX26_H
+#define DAZUKO_LINUX26_H
+
+#include <linux/module.h>
+#include <linux/dcache.h>
+#include <linux/namei.h>
+
+#define	DEVICE_NAME		"dazuko"
+
+#define XP_ERROR_PERMISSION	-EPERM;
+#define XP_ERROR_INTERRUPT	-EINTR;
+#define XP_ERROR_BUSY		-EBUSY;
+#define XP_ERROR_FAULT		-EFAULT;
+#define XP_ERROR_INVALID	-EINVAL;
+#define XP_ERROR_NODEVICE	-ENODEV;
+
+
+struct xp_daemon_id
+{
+	int			pid;
+	struct file		*file;
+	struct task_struct	*current_p;
+	struct files_struct	*files;
+};
+
+struct xp_mutex
+{
+	struct semaphore mutex;
+};
+
+struct xp_atomic
+{
+	atomic_t atomic;
+};
+
+struct xp_file_struct
+{
+	const char		*user_filename;		/* userspace filename */
+	int			fd;			/* file descriptor */
+	int			full_filename_length;	/* length of filename */
+	char			*full_filename;		/* kernelspace filename with full path */
+	int			free_full_filename;	/* flag to clean up full_filename */
+	struct dentry		*dentry;		/* used to get inode */
+	int			dput_dentry;		/* flag to clean up dentry */
+	char			*buffer;		/* used to get full path */
+	int			free_page_buffer;	/* flag to clean up buffer */
+	struct nameidata	nd;			/* used to get full path */
+	int			path_release_nd;	/* flag to clean up nd */
+	struct vfsmount		*vfsmount;		/* used to get full path */
+	int			mntput_vfsmount;	/* flag to clean up vfsmount */
+};
+
+struct xp_queue
+{
+	wait_queue_head_t queue;
+};
+
+struct xp_rwlock
+{
+	rwlock_t rwlock;
+};
+
+#endif
diff -r -u -N -x {arch} -x .arch-ids dazuko--vendor--2.1/dazuko_platform.h dazuko--contrib-symlink2--2.1/dazuko_platform.h
--- dazuko--vendor--2.1/dazuko_platform.h	2006-03-03 15:11:02.000000000 +0200
+++ dazuko--contrib-symlink2--2.1/dazuko_platform.h	2006-03-03 15:24:10.000000000 +0200
@@ -1,7 +1,11 @@
 #if defined(DUMMYOS)
 	#include "dazuko_dummyos.h"
 #elif defined(LINUX26_SUPPORT)
-	#include "dazuko_linux26.h"
+	#if defined(USE_SYSCALLS)
+		#include "dazuko_linux26_syscall.h"
+	#else
+		#include "dazuko_linux26.h"
+	#endif
 #elif defined(LINUX)
 	#include "dazuko_linux.h"
 #elif defined(FREEBSD5_SUPPORT)
