[Box Backup-commit] COMMIT r1452 - box/chris/general/lib/intercept
boxbackup-dev at fluffy.co.uk
boxbackup-dev at fluffy.co.uk
Sat Mar 24 14:54:24 GMT 2007
Author: chris
Date: 2007-03-24 14:54:24 +0000 (Sat, 24 Mar 2007)
New Revision: 1452
Modified:
box/chris/general/lib/intercept/intercept.cpp
Log:
Intercept updates merged from chris/merge
Modified: box/chris/general/lib/intercept/intercept.cpp
===================================================================
--- box/chris/general/lib/intercept/intercept.cpp 2007-03-24 14:52:00 UTC (rev 1451)
+++ box/chris/general/lib/intercept/intercept.cpp 2007-03-24 14:54:24 UTC (rev 1452)
@@ -9,6 +9,8 @@
#include "Box.h"
+#include "intercept.h"
+
#ifdef HAVE_SYS_SYSCALL_H
#include <sys/syscall.h>
#endif
@@ -16,11 +18,15 @@
#include <unistd.h>
#ifdef HAVE_SYS_UIO_H
-#include <sys/uio.h>
+ #include <sys/uio.h>
#endif
#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)
@@ -59,7 +65,7 @@
#include "MemLeakFindOn.h"
-bool intercept_enabled = false;
+int intercept_count = 0;
const char *intercept_filename = 0;
int intercept_filedes = -1;
off_t intercept_errorafter = 0;
@@ -72,7 +78,7 @@
void intercept_clear_setup()
{
- intercept_enabled = false;
+ intercept_count = 0;
intercept_filename = 0;
intercept_filedes = -1;
intercept_errorafter = 0;
@@ -83,13 +89,13 @@
bool intercept_triggered()
{
- return !intercept_enabled;
+ return intercept_count == 0;
}
void intercept_setup_error(const char *filename, unsigned int errorafter, int errortoreturn, int syscalltoerror)
{
TRACE4("Setup for error: %s, after %d, err %d, syscall %d\n", filename, errorafter, errortoreturn, syscalltoerror);
- intercept_enabled = true;
+ intercept_count = 1;
intercept_filename = filename;
intercept_filedes = -1;
intercept_errorafter = errorafter;
@@ -100,11 +106,12 @@
}
void intercept_setup_delay(const char *filename, unsigned int delay_after,
- int delay_ms, int syscall_to_delay)
+ int delay_ms, int syscall_to_delay, int num_delays)
{
- TRACE4("Setup for delay: %s, after %d, wait %d ms, syscall %d\n",
- filename, delay_after, delay_ms, syscall_to_delay);
- intercept_enabled = true;
+ TRACE5("Setup for delay: %s, after %d, wait %d ms, times %d, "
+ "syscall %d\n", filename, delay_after, delay_ms,
+ num_delays, syscall_to_delay);
+ intercept_count = num_delays;
intercept_filename = filename;
intercept_filedes = -1;
intercept_errorafter = delay_after;
@@ -154,7 +161,7 @@
}
#define CHECK_FOR_FAKE_ERROR_COND(D, S, CALL, FAILRES) \
- if(intercept_enabled) \
+ if(intercept_count > 0) \
{ \
if(intercept_errornow(D, S, CALL)) \
{ \
@@ -166,7 +173,11 @@
* 1000000; \
while (nanosleep(&tm, &tm) != 0 && \
errno == EINTR) { } \
- intercept_clear_setup(); \
+ intercept_count --; \
+ if (intercept_count == 0) \
+ { \
+ intercept_clear_setup(); \
+ } \
} \
else \
{ \
@@ -179,7 +190,7 @@
extern "C" int
open(const char *path, int flags, mode_t mode)
{
- if(intercept_enabled)
+ if(intercept_count > 0)
{
if(intercept_syscall == SYS_open && strcmp(path, intercept_filename) == 0)
{
@@ -192,7 +203,7 @@
#else
int r = syscall(SYS_open, path, flags, mode);
#endif
- if(intercept_enabled && intercept_filedes == -1)
+ if(intercept_count > 0 && intercept_filedes == -1)
{
// Right file?
if(strcmp(intercept_filename, path) == 0)
@@ -312,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
More information about the Boxbackup-commit
mailing list