在 CentOS(或一般 Linux)里,“重写 readdir”通常有几种不同含义,取决于你想在哪里、以什么方式重写它。下面按常见场景给你说明,并给出示例。
readdir 是 glibc 提供的函数,用于读取目录内容。
你不能直接修改 glibc,但可以通过 符号介入(symbol interposition) 或 封装函数 的方式“重写”。
#define _GNU_SOURCE
#include <dirent.h>
#include <dlfcn.h>
#include <string.h>
#include <stdio.h>
struct dirent *readdir(DIR *dirp) {
static struct dirent *(*original_readdir)(DIR *) = NULL;
if (!original_readdir) {
original_readdir = dlsym(RTLD_NEXT, "readdir");
}
struct dirent *entry;
while ((entry = original_readdir(dirp)) != NULL) {
// 示例:过滤掉 . 和 ..
if (strcmp(entry->d_name, ".") == 0 ||
strcmp(entry->d_name, "..") == 0) {
continue;
}
return entry;
}
return NULL;
}
gcc -fPIC -shared -o myreaddir.so readdir.c -ldl
export LD_PRELOAD=./myreaddir.so
ls
✅ 此时 ls 实际调用的是你重写的 readdir
#include <dirent.h>
#include <stdio.h>
DIR *my_opendir(const char *path) {
return opendir(path);
}
struct dirent *my_readdir(DIR *dirp) {
struct dirent *entry;
while ((entry = readdir(dirp)) != NULL) {
if (entry->d_name[0] != '.') {
return entry;
}
}
return NULL;
}
✅ 不影响系统函数,最安全
readdir 在内核中是 getdents / getdents64| 位置 | 说明 |
|---|---|
fs/readdir.c |
用户态 → 内核态的入口 |
struct file_operations 中的 .iterate |
具体文件系统实现 |
| LSM / eBPF | 更安全的方式 |
⚠️ 不建议直接改内核
bpftrace -e '
tracepoint:syscalls:sys_enter_getdents {
printf("getdents called by %s\n", comm);
}'
或者写 BPF LSM 过滤文件名
#define readdir?#define readdir my_readdir // ❌ 不安全
会导致 glibc 内部调用混乱,强烈不推荐。
✅ 能,glibc + LD_PRELOAD 完全支持
如果你能告诉我:
我可以直接给你最合适的实现方案 + 完整代码。