[Box Backup-commit] COMMIT r1187 - box/chris/merge/lib/intercept

boxbackup-dev at fluffy.co.uk boxbackup-dev at fluffy.co.uk
Sun Dec 3 10:29:01 GMT 2006


Author: chris
Date: 2006-12-03 10:29:01 +0000 (Sun, 03 Dec 2006)
New Revision: 1187

Added:
   box/chris/merge/lib/intercept/intercept.h
Modified:
   box/chris/merge/lib/intercept/intercept.cpp
Log:

Added a header file for including in test/bbackupd/testbbackupd.cpp and 
other modules which might need intercepts in future.

Added opendir/readdir and lstat hook capability.

(refs #3, refs #9)


Modified: box/chris/merge/lib/intercept/intercept.cpp
===================================================================
--- box/chris/merge/lib/intercept/intercept.cpp	2006-12-03 10:27:16 UTC (rev 1186)
+++ box/chris/merge/lib/intercept/intercept.cpp	2006-12-03 10:29:01 UTC (rev 1187)
@@ -9,6 +9,8 @@
 
 #include "Box.h"
 
+#include "intercept.h"
+
 #ifdef HAVE_SYS_SYSCALL_H
 	#include <sys/syscall.h>
 #endif
@@ -21,6 +23,10 @@
 
 #include <errno.h>
 
+#ifdef HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
 #ifndef PLATFORM_CLIB_FNS_INTERCEPTION_IMPOSSIBLE
 
 #if !defined(HAVE_SYSCALL) && !defined(HAVE___SYSCALL) && !defined(HAVE___SYSCALL_NEED_DEFN)
@@ -317,4 +323,173 @@
 	return r;
 }
 
+static opendir_t*  opendir_real  = NULL;
+static readdir_t*  readdir_real  = NULL;
+static readdir_t*  readdir_hook  = NULL;
+static closedir_t* closedir_real = NULL;
+static lstat_t*    lstat_real    = NULL;
+static lstat_t*    lstat_hook    = NULL;
+static const char* lstat_file    = NULL;
+
+void intercept_setup_readdir_hook(const char *dirname, readdir_t hookfn)
+{
+	if (hookfn != NULL && dirname == NULL)
+	{
+		dirname = intercept_filename;
+	}
+
+	if (hookfn != NULL)
+	{
+		TRACE2("readdir hooked to %p for %s\n", hookfn, dirname);
+	}
+	else
+	{
+		TRACE2("readdir unhooked from %p for %s\n", readdir_hook, 
+			intercept_filename);
+	}
+
+	intercept_filename = dirname;
+	readdir_hook = hookfn;
+}
+
+void intercept_setup_lstat_hook(const char *filename, lstat_t hookfn)
+{
+	/*
+	if (hookfn != NULL)
+	{
+		TRACE2("lstat hooked to %p for %s\n", hookfn, filename);
+	}
+	else
+	{
+		TRACE2("lstat unhooked from %p for %s\n", lstat_hook, 
+			lstat_file);
+	}
+	*/
+
+	lstat_file = filename;
+	lstat_hook = hookfn;
+}
+
+extern "C" 
+DIR *opendir(const char *dirname)
+{
+	if (opendir_real == NULL)
+	{
+		opendir_real = (opendir_t*)(dlsym(RTLD_NEXT, "opendir"));
+	}
+
+	if (opendir_real == NULL)
+	{
+		perror("cannot find real opendir");
+		return NULL;
+	}
+
+	DIR* r = opendir_real(dirname);
+
+	if(readdir_hook != NULL && intercept_filedes == -1 && 
+		strcmp(intercept_filename, dirname) == 0)
+	{
+		intercept_filedes = dirfd(r);
+		//printf("Found file to intercept, h = %d\n", r);
+	}
+
+	return r;
+}
+
+extern "C"
+struct dirent *readdir(DIR *dir)
+{
+	if (readdir_hook != NULL && dirfd(dir) == intercept_filedes)
+	{
+		return readdir_hook(dir);
+	}
+
+	if (readdir_real == NULL)
+	{
+		#if readdir == readdir64
+		readdir_real = (readdir_t*)(dlsym(RTLD_NEXT, "readdir64"));
+		#else
+		readdir_real = (readdir_t*)(dlsym(RTLD_NEXT, "readdir"));
+		#endif
+	}
+
+	if (readdir_real == NULL)
+	{
+		perror("cannot find real readdir");
+		return NULL;
+	}
+
+	return readdir_real(dir);
+}
+
+extern "C"
+int closedir(DIR *dir)
+{
+	if (dirfd(dir) == intercept_filedes)
+	{
+		intercept_filedes = -1;
+	}
+
+	if (closedir_real == NULL)
+	{
+		closedir_real = (closedir_t*)(dlsym(RTLD_NEXT, "closedir"));
+	}
+
+	if (closedir_real == NULL)
+	{
+		perror("cannot find real closedir");
+		errno = ENOSYS;
+		return -1;
+	}
+
+	return closedir_real(dir);
+}
+
+extern "C" int 
+#ifdef LINUX_WEIRD_LSTAT
+__lxstat(int ver, const char *file_name, STAT_STRUCT *buf)
+#else
+lstat(const char *file_name, STAT_STRUCT *buf)
+#endif
+{
+	if (lstat_real == NULL)
+	{
+	#ifdef LINUX_WEIRD_LSTAT
+		#if __lxstat == __lxstat64
+		lstat_real = (lstat_t*)(dlsym(RTLD_NEXT, "__lxstat64"));
+		#else
+		lstat_real = (lstat_t*)(dlsym(RTLD_NEXT, "__lxstat"));
+		#endif
+	#else
+		#if lstat == lstat64
+		lstat_real = (lstat_t*)(dlsym(RTLD_NEXT, "lstat64"));
+		#else
+		lstat_real = (lstat_t*)(dlsym(RTLD_NEXT, "lstat"));
+		#endif
+	#endif
+	}
+
+	if (lstat_real == NULL)
+	{
+		perror("cannot find real lstat");
+		errno = ENOSYS;
+		return -1;
+	}
+
+	if (lstat_hook == NULL || strcmp(file_name, lstat_file) != 0)
+	{
+	#ifdef LINUX_WEIRD_LSTAT
+		return lstat_real(ver, file_name, buf);
+	#else
+		return lstat_real(file_name, buf);
+	#endif
+	}
+
+	#ifdef LINUX_WEIRD_LSTAT
+	return lstat_hook(ver, file_name, buf);
+	#else
+	return lstat_hook(file_name, buf);
+	#endif
+}
+
 #endif // n PLATFORM_CLIB_FNS_INTERCEPTION_IMPOSSIBLE

Added: box/chris/merge/lib/intercept/intercept.h
===================================================================
--- box/chris/merge/lib/intercept/intercept.h	                        (rev 0)
+++ box/chris/merge/lib/intercept/intercept.h	2006-12-03 10:29:01 UTC (rev 1187)
@@ -0,0 +1,42 @@
+// --------------------------------------------------------------------------
+//
+// File
+//		Name:    intercept.h
+//		Purpose: Syscall interception code for unit tests
+//		Created: 2006/11/29
+//
+// --------------------------------------------------------------------------
+
+#ifndef INTERCEPT_H
+#define INTERCEPT_H
+
+#include <dirent.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+extern "C"
+{
+	typedef DIR           *(opendir_t) (const char *name);
+	typedef struct dirent *(readdir_t) (DIR *dir);
+	typedef struct dirent *(readdir_t) (DIR *dir);
+	typedef int            (closedir_t)(DIR *dir);
+#if defined __GNUC__ && __GNUC__ >= 2
+#define LINUX_WEIRD_LSTAT
+#define STAT_STRUCT struct stat /* should be stat64 */
+	typedef int            (lstat_t)   (int ver, const char *file_name, 
+	                                    STAT_STRUCT *buf);
+#else
+#define STAT_STRUCT struct stat
+	typedef int            (lstat_t)   (const char *file_name, 
+	                                    STAT_STRUCT *buf);
+#endif
+}
+
+void intercept_setup_error(const char *filename, unsigned int errorafter, 
+	int errortoreturn, int syscalltoerror);
+
+void intercept_setup_readdir_hook(const char *dirname,  readdir_t hookfn);
+void intercept_setup_lstat_hook  (const char *filename, lstat_t   hookfn);
+
+#endif // !INTERCEPT_H


Property changes on: box/chris/merge/lib/intercept/intercept.h
___________________________________________________________________
Name: svn:mime-type
   + text/x-chdr
Name: svn:eol-style
   + native




More information about the Boxbackup-commit mailing list