正しければ、ディレクトリエントリを操作します。たとえば、ファイル名を変更したり、ダミーエントリを追加したりします。あなたはそのようにそれをすることができます。
オーバーロードopendir()
、その中で実際に「real」でディレクトリを開き、「real」opendir()
ですべてのディレクトリエントリをすぐに読み取り、readdir()
必要なものを変更し、変更されたバージョンをグローバル変数に格納して、変更されていないものを返しDIR *
ます。次に、オーバーロードでは、readdir()
渡さDIR *
れたものを独自の不透明な値(たとえば、マップのキー)として扱い、以前に準備されたエントリを順番に返します。
これが厄介な概念実証です(エラーチェック、リソースのクローズ、メモリの解放、スレッドセーフなどの退屈な部分をスキップしたために厄介です):
opendir_wrap.cpp-> opendir_wrap.so:
#include <sys/types.h>
#include <dirent.h>
#include <dlfcn.h>
#include <stdio.h>
#include <map>
#include <list>
extern "C" {
static std::map<DIR *, std::list<struct dirent*> > MAP;
typedef DIR *(*OPEN_T)(const char *name);
typedef struct dirent *(*READ_T)(DIR *dirp);
static OPEN_T real_opendir = NULL;
static READ_T real_readdir = NULL;
DIR *opendir(const char *name)
{
void *handle = dlopen("/lib/libc.so.6", RTLD_LAZY);
if (!real_opendir) real_opendir = (OPEN_T) dlsym(handle, "opendir");
if (!real_readdir) real_readdir = (READ_T) dlsym(handle, "readdir");
DIR *dirp = real_opendir(name);
struct dirent *entry = NULL;
while (entry = real_readdir(dirp))
{
MAP[dirp].push_back(entry);
}
MAP[dirp].push_back(NULL);
// your modifications here
struct dirent *joke = new struct dirent;
sprintf(joke->d_name, "JOKE!");
MAP[dirp].push_front(joke);
return dirp;
}
struct dirent *readdir(DIR *dirp)
{
struct dirent *entry = MAP[dirp].front();
MAP[dirp].pop_front();
return entry;
}
} // extern "C"
opedir_use.c-> opendir_use:
#include <sys/types.h>
#include <dirent.h>
#include <dlfcn.h>
#include <stdio.h>
int main()
{
struct dirent *entry = NULL;
DIR *dirp = opendir(".");
printf("dirp = %p\n", dirp);
while (entry = readdir(dirp))
{
printf("entry->d_name = %s\n", entry->d_name);
}
}
今コンパイルします:
$ gcc -fpic -shared -ldl -lstdc++ -o ./opendir_wrap.so ./opendir_wrap.cpp
$ gcc opendir_use.c -o opendir_use
通常どおり実行します。
$ ./opendir_use
dirp = 0x9fd3008
entry->d_name = opendir_wrap.so
entry->d_name = opendir_use
entry->d_name = opendir_use.c
entry->d_name = opendir_wrap.cpp
entry->d_name = ..
entry->d_name = .
ラッパーで実行します。
$ LD_PRELOAD=`pwd`/opendir_wrap.so ./opendir_use
dirp = 0x95374b8
entry->d_name = JOKE!
entry->d_name = opendir_wrap.so
entry->d_name = opendir_use
entry->d_name = opendir_use.c
entry->d_name = opendir_wrap.cpp
entry->d_name = ..
entry->d_name = .