Hook readdir()时,如何从opendir()返回的DIR结构体恢复目录路径?
针对readdir()钩子拦截特定路径的实现方案
核心思路:追踪DIR结构体与路径的绑定关系
要实现只拦截特定路径的readdir()调用,关键是在**opendir()/fdopendir()**的调用阶段就记录下DIR结构体对应的路径,这样后续readdir()被hook时,直接通过DIR指针查找对应的路径即可判断是否需要拦截。
具体实现步骤
Hook opendir系列函数
- 拦截
opendir(const char *name):调用原始opendir得到DIR后,把这个DIR指针和传入的路径name关联存储(比如用哈希表,key是DIR,value是路径字符串的深拷贝)。 - 拦截
fdopendir(int fd):先通过readlink("/proc/self/fd/<fd>")(Linux)或fcntl(fd, F_GETPATH)(BSD)获取fd对应的路径,再调用原始fdopendir得到DIR*,同样把DIR*和路径关联存储。 - 注意:要做路径规范化处理,比如解析符号链接、去除末尾斜杠,避免同一路径的不同写法导致匹配失败。
- 拦截
Hook readdir()函数
- 当
readdir(DIR *dirp)被调用时,先在哈希表中查找dirp对应的路径。 - 如果路径匹配目标拦截路径,执行自定义逻辑(比如修改返回的dirent、记录访问日志);不匹配则直接调用原始readdir返回结果。
- 当
Hook closedir()函数
- 拦截
closedir(DIR *dirp):调用原始closedir后,从哈希表中删除该DIR*对应的条目,释放路径字符串内存,避免内存泄漏和无效指针残留。
- 拦截
关键细节处理
- 线程安全:多线程环境下,哈希表的读写操作要加锁(比如用
pthread_mutex_t),防止并发冲突。 - 内存管理:存储路径时必须深拷贝,不能直接使用原始参数指针(opendir的参数可能是临时缓冲区),closedir时要释放路径内存。
- 特殊场景兼容:处理dup/dup2复制目录fd后调用fdopendir的情况,确保每个新DIR*都能关联到正确路径;部分系统的DIR结构体内置fd,可通过
dirfd(dirp)获取fd后反向查路径作为 fallback。
依赖系统实现的替代方案
部分系统(如Linux)的DIR结构体内部包含文件描述符fd,可直接通过DIR*获取fd再反向查路径:
// Linux下从DIR*提取fd的近似实现(需参考系统头文件确认结构体布局) #define dirfd(dirp) ((dirp)->fd)
之后用readlink("/proc/self/fd/<fd>")获取路径,这种方法无需hook opendir,但移植性差,且每次readdir都要查询路径,性能略低。
内容的提问来源于stack exchange,提问作者sawntoe
相关产品推荐
相关产品推荐

