(作为答案发布,因为这对于评论来说太长了。)
您可能会发现使用 LD_PRELOAD 库并插入 open()/fopen()/open64() 或您现有软件用来访问配置文件并替换应用程序提供的文件名,其中一个指向您要使用的文件。
这段代码不在我的脑海中,我还没有尝试编译它:
#include <dlfcn.h>
// don't want to #include anything else or we're likely to get
// the vararg prototype for open()
int strcmp( const char *s1, const char *s2 );
// typedef a function pointer
typedef int ( *open_func_ptr_t )( const char *, int, mode_t );
static open_func_ptr_t real_open = NULL;
int open( const char *pathname, int flags, mode_t mode )
{
// find the real open() call
if ( real_open == NULL )
{
real_open = ( open_func_ptr_t ) dlsym( RTLD_NEXT, "open" );
}
if ( 0 == strcmp( pathname, "/path/to/config/file" );
{
pathname = "/path/to/replacement/config/file";
}
return( real_open( pathname, flags, mode ) );
}
该代码依赖于这样一个事实:尽管 open() 被声明为可变参数函数,因为当前 C 代码受到限制,但最初 C 没有原型,所以所有函数事实上可变参数函数。 open() 调用仅在需要时访问 mode 参数,因此 open() 并不总是需要传递 mode 参数。对于当前的 C,唯一的方法是使用 vararg 函数。这使得#include 文件与此代码有问题,因为open() 的任何声明都将是可变参数,这将导致代码无法编译。您可能需要将mode_t 替换为int(或任何typedef'd)才能进行编译。
用cc [-m64|-m32] -shared source.c -ldl -o mylib.so 编译它。您需要-ldl 来链接dlsym(),并且您需要正确的-m64 或-m32 选项来获得与您的应用程序匹配的64 位或32 位库。
然后将LD_PRELOAD 设置为您的.so 文件:
LD_PRELOAD=/path/to/mylib.so
export LD_PRELOAD
然后使用 LD_PRELOAD 集运行您的应用程序。您还需要非常小心,由您的应用程序生成的任何子进程都与共享对象 LD_PRELOAD 设置为相同的 32 位或 64 位。如果您要处理混合的 32 位和 64 位进程,请阅读 man page for ld.so 并特别注意 $PLATFORM 部分。
另请注意,由于竞争条件修改了real_open,代码不可重入,并且可能在多线程访问open() 时出现问题。