summaryrefslogtreecommitdiff
path: root/lib/intercept/intercept.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/intercept/intercept.cpp')
-rw-r--r--lib/intercept/intercept.cpp141
1 files changed, 132 insertions, 9 deletions
diff --git a/lib/intercept/intercept.cpp b/lib/intercept/intercept.cpp
index 65514ae2..7a33b610 100644
--- a/lib/intercept/intercept.cpp
+++ b/lib/intercept/intercept.cpp
@@ -22,6 +22,7 @@
#endif
#include <errno.h>
+#include <stdarg.h>
#ifdef HAVE_DLFCN_H
#include <dlfcn.h>
@@ -84,6 +85,12 @@ static closedir_t* closedir_real = NULL;
static lstat_t* lstat_real = NULL;
static lstat_t* lstat_hook = NULL;
static const char* lstat_file = NULL;
+static lstat_t* stat_real = NULL;
+static lstat_t* stat_hook = NULL;
+static const char* stat_file = NULL;
+
+static lstat_post_hook_t* lstat_post_hook = NULL;
+static lstat_post_hook_t* stat_post_hook = NULL;
#define SIZE_ALWAYS_ERROR -773
@@ -97,7 +104,10 @@ void intercept_clear_setup()
intercept_filepos = 0;
intercept_delay_ms = 0;
readdir_hook = NULL;
+ stat_hook = NULL;
lstat_hook = NULL;
+ stat_post_hook = NULL;
+ lstat_post_hook = NULL;
}
bool intercept_triggered()
@@ -222,8 +232,16 @@ int intercept_reterr()
} \
}
+#if defined _FILE_OFFSET_BITS && _FILE_OFFSET_BITS == 64
+ #define DEFINE_ONLY_OPEN64
+#endif
+
extern "C" int
-open(const char *path, int flags, mode_t mode)
+#ifdef DEFINE_ONLY_OPEN64
+ open64(const char *path, int flags, ...)
+#else
+ open(const char *path, int flags, ...)
+#endif // DEFINE_ONLY_OPEN64
{
if(intercept_count > 0)
{
@@ -236,6 +254,15 @@ open(const char *path, int flags, mode_t mode)
}
}
+ mode_t mode = 0;
+ if (flags & O_CREAT)
+ {
+ va_list ap;
+ va_start(ap, flags);
+ mode = va_arg(ap, int);
+ va_end(ap);
+ }
+
#ifdef PLATFORM_NO_SYSCALL
int r = TEST_open(path, flags, mode);
#else
@@ -257,14 +284,27 @@ open(const char *path, int flags, mode_t mode)
return r;
}
+#ifndef DEFINE_ONLY_OPEN64
extern "C" int
-open64(const char *path, int flags, mode_t mode)
+// open64(const char *path, int flags, mode_t mode)
+// open64(const char *path, int flags, ...)
+open64 (__const char *path, int flags, ...)
{
+ mode_t mode = 0;
+ if (flags & O_CREAT)
+ {
+ va_list ap;
+ va_start(ap, flags);
+ mode = va_arg(ap, int);
+ va_end(ap);
+ }
+
// With _FILE_OFFSET_BITS set to 64 this should really use (flags |
// O_LARGEFILE) here, but not actually necessary for the tests and not
// worth the trouble finding O_LARGEFILE
return open(path, flags, mode);
}
+#endif // !DEFINE_ONLY_OPEN64
extern "C" int
close(int d)
@@ -375,12 +415,12 @@ void intercept_setup_readdir_hook(const char *dirname, readdir_t hookfn)
if (hookfn != NULL)
{
- TRACE2("readdir hooked to %p for %s\n", hookfn, dirname);
+ BOX_TRACE("readdir hooked to " << hookfn << " for " << dirname);
}
else if (intercept_filename != NULL)
{
- TRACE2("readdir unhooked from %p for %s\n", readdir_hook,
- intercept_filename);
+ BOX_TRACE("readdir unhooked from " << readdir_hook <<
+ " for " << intercept_filename);
}
intercept_filename = dirname;
@@ -392,11 +432,11 @@ void intercept_setup_lstat_hook(const char *filename, lstat_t hookfn)
/*
if (hookfn != NULL)
{
- TRACE2("lstat hooked to %p for %s\n", hookfn, filename);
+ BOX_TRACE("lstat hooked to " << hookfn << " for " << filename);
}
else
{
- TRACE2("lstat unhooked from %p for %s\n", lstat_hook,
+ BOX_TRACE("lstat unhooked from " << lstat_hook << " for " <<
lstat_file);
}
*/
@@ -405,6 +445,40 @@ void intercept_setup_lstat_hook(const char *filename, lstat_t hookfn)
lstat_hook = hookfn;
}
+void intercept_setup_lstat_post_hook(lstat_post_hook_t hookfn)
+{
+ /*
+ if (hookfn != NULL)
+ {
+ BOX_TRACE("lstat hooked to " << hookfn << " for " << filename);
+ }
+ else
+ {
+ BOX_TRACE("lstat unhooked from " << lstat_hook << " for " <<
+ lstat_file);
+ }
+ */
+
+ lstat_post_hook = hookfn;
+}
+
+void intercept_setup_stat_post_hook(lstat_post_hook_t hookfn)
+{
+ /*
+ if (hookfn != NULL)
+ {
+ BOX_TRACE("lstat hooked to " << hookfn << " for " << filename);
+ }
+ else
+ {
+ BOX_TRACE("lstat unhooked from " << lstat_hook << " for " <<
+ lstat_file);
+ }
+ */
+
+ stat_post_hook = hookfn;
+}
+
static void * find_function(const char *pName)
{
dlerror();
@@ -534,10 +608,15 @@ lstat(const char *file_name, STAT_STRUCT *buf)
if (lstat_hook == NULL || strcmp(file_name, lstat_file) != 0)
{
#ifdef LINUX_WEIRD_LSTAT
- return lstat_real(ver, file_name, buf);
+ int ret = lstat_real(ver, file_name, buf);
#else
- return lstat_real(file_name, buf);
+ int ret = lstat_real(file_name, buf);
#endif
+ if (lstat_post_hook != NULL)
+ {
+ ret = lstat_post_hook(ret, file_name, buf);
+ }
+ return ret;
}
#ifdef LINUX_WEIRD_LSTAT
@@ -547,4 +626,48 @@ lstat(const char *file_name, STAT_STRUCT *buf)
#endif
}
+extern "C" int
+#ifdef LINUX_WEIRD_LSTAT
+__xstat(int ver, const char *file_name, STAT_STRUCT *buf)
+#else
+stat(const char *file_name, STAT_STRUCT *buf)
+#endif
+{
+ if (stat_real == NULL)
+ {
+ #ifdef LINUX_WEIRD_LSTAT
+ stat_real = (lstat_t*)find_function("__xstat");
+ #else
+ stat_real = (lstat_t*)find_function("stat");
+ #endif
+ }
+
+ if (stat_real == NULL)
+ {
+ perror("cannot find real stat");
+ errno = ENOSYS;
+ return -1;
+ }
+
+ if (stat_hook == NULL || strcmp(file_name, stat_file) != 0)
+ {
+ #ifdef LINUX_WEIRD_LSTAT
+ int ret = stat_real(ver, file_name, buf);
+ #else
+ int ret = stat_real(file_name, buf);
+ #endif
+ if (stat_post_hook != NULL)
+ {
+ ret = stat_post_hook(ret, file_name, buf);
+ }
+ return ret;
+ }
+
+ #ifdef LINUX_WEIRD_LSTAT
+ return stat_hook(ver, file_name, buf);
+ #else
+ return stat_hook(file_name, buf);
+ #endif
+}
+
#endif // n PLATFORM_CLIB_FNS_INTERCEPTION_IMPOSSIBLE