rebuild
This commit is contained in:
298
src/hook/zvfs_hook_init.c
Normal file
298
src/hook/zvfs_hook_init.c
Normal file
@@ -0,0 +1,298 @@
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
#include "zvfs_hook_init.h"
|
||||
#include "zvfs_hook_reentrant.h"
|
||||
#include "fs/zvfs.h"
|
||||
#include "fs/zvfs_open_file.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <pthread.h>
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* 线程局部重入计数定义 */
|
||||
/* ------------------------------------------------------------------ */
|
||||
__thread int _zvfs_hook_depth = 0;
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* zvfs 挂载点 */
|
||||
/* ------------------------------------------------------------------ */
|
||||
#define ZVFS_MOUNT_PREFIX "/zvfs"
|
||||
#define ZVFS_MOUNT_PREFIX_LEN 5 /* strlen("/zvfs") */
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* real_* 函数指针定义 */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
/* open / close / dup */
|
||||
int (*real_open)(const char *, int, ...) = NULL;
|
||||
int (*real_open64)(const char *, int, ...) = NULL;
|
||||
int (*real_openat)(int, const char *, int, ...) = NULL;
|
||||
int (*real_openat64)(int, const char *, int, ...) = NULL;
|
||||
int (*real_creat)(const char *, mode_t) = NULL;
|
||||
int (*real_creat64)(const char *, mode_t) = NULL;
|
||||
int (*real_close)(int) = NULL;
|
||||
int (*real_close_range)(unsigned, unsigned, unsigned) = NULL;
|
||||
int (*real_dup)(int) = NULL;
|
||||
int (*real_dup2)(int, int) = NULL;
|
||||
int (*real_dup3)(int, int, int) = NULL;
|
||||
|
||||
/* read */
|
||||
ssize_t (*real_read)(int, void *, size_t) = NULL;
|
||||
ssize_t (*real_pread)(int, void *, size_t, off_t) = NULL;
|
||||
ssize_t (*real_pread64)(int, void *, size_t, off_t) = NULL;
|
||||
ssize_t (*real_readv)(int, const struct iovec *, int) = NULL;
|
||||
ssize_t (*real_preadv)(int, const struct iovec *, int, off_t) = NULL;
|
||||
ssize_t (*real_preadv64)(int, const struct iovec *, int, off_t) = NULL;
|
||||
ssize_t (*real_preadv2)(int, const struct iovec *, int, off_t, int) = NULL;
|
||||
|
||||
/* write */
|
||||
ssize_t (*real_write)(int, const void *, size_t) = NULL;
|
||||
ssize_t (*real_pwrite)(int, const void *, size_t, off_t) = NULL;
|
||||
ssize_t (*real_pwrite64)(int, const void *, size_t, off_t) = NULL;
|
||||
ssize_t (*real_writev)(int, const struct iovec *, int) = NULL;
|
||||
ssize_t (*real_pwritev)(int, const struct iovec *, int, off_t) = NULL;
|
||||
ssize_t (*real_pwritev64)(int, const struct iovec *, int, off_t) = NULL;
|
||||
ssize_t (*real_pwritev2)(int, const struct iovec *, int, off_t, int) = NULL;
|
||||
|
||||
/* lseek / truncate / fallocate */
|
||||
off_t (*real_lseek)(int, off_t, int) = NULL;
|
||||
off_t (*real_lseek64)(int, off_t, int) = NULL;
|
||||
int (*real_truncate)(const char *, off_t) = NULL;
|
||||
int (*real_truncate64)(const char *, off_t) = NULL;
|
||||
int (*real_ftruncate)(int, off_t) = NULL;
|
||||
int (*real_ftruncate64)(int, off_t) = NULL;
|
||||
int (*real_fallocate)(int, int, off_t, off_t) = NULL;
|
||||
int (*real_posix_fallocate)(int, off_t, off_t) = NULL;
|
||||
|
||||
/* stat */
|
||||
int (*real_stat)(const char *, struct stat *) = NULL;
|
||||
int (*real_stat64)(const char *, struct stat64 *) = NULL;
|
||||
int (*real_fstat)(int, struct stat *) = NULL;
|
||||
int (*real_fstat64)(int, struct stat64 *) = NULL;
|
||||
int (*real_lstat)(const char *, struct stat *) = NULL;
|
||||
int (*real_lstat64)(const char *, struct stat64 *) = NULL;
|
||||
int (*real_fstatat)(int, const char *, struct stat *, int) = NULL;
|
||||
int (*real_fstatat64)(int, const char *, struct stat64 *, int) = NULL;
|
||||
int (*real_statx)(int, const char *, int, unsigned int,
|
||||
struct statx *) = NULL;
|
||||
|
||||
/* sync */
|
||||
int (*real_fsync)(int) = NULL;
|
||||
int (*real_fdatasync)(int) = NULL;
|
||||
int (*real_sync_file_range)(int, off_t, off_t, unsigned int) = NULL;
|
||||
|
||||
/* fcntl / ioctl */
|
||||
int (*real_fcntl)(int, int, ...) = NULL;
|
||||
int (*real_fcntl64)(int, int, ...) = NULL;
|
||||
int (*real_ioctl)(int, unsigned long, ...) = NULL;
|
||||
|
||||
/* 目录 */
|
||||
int (*real_unlink)(const char *) = NULL;
|
||||
int (*real_unlinkat)(int, const char *, int) = NULL;
|
||||
int (*real_rename)(const char *, const char *) = NULL;
|
||||
int (*real_renameat)(int, const char *, int, const char *) = NULL;
|
||||
int (*real_renameat2)(int, const char *, int, const char *,
|
||||
unsigned int) = NULL;
|
||||
|
||||
/* mmap */
|
||||
void *(*real_mmap)(void *, size_t, int, int, int, off_t) = NULL;
|
||||
void *(*real_mmap64)(void *, size_t, int, int, int, off_t) = NULL;
|
||||
int (*real_munmap)(void *, size_t) = NULL;
|
||||
int (*real_msync)(void *, size_t, int) = NULL;
|
||||
|
||||
/* fork */
|
||||
pid_t (*real_fork)(void) = NULL;
|
||||
pid_t (*real_vfork)(void) = NULL;
|
||||
|
||||
/* glibc 别名 */
|
||||
int (*real___open)(const char *, int, ...) = NULL;
|
||||
int (*real___open64)(const char *, int, ...) = NULL;
|
||||
int (*real___libc_open)(const char *, int, ...) = NULL;
|
||||
ssize_t (*real___read)(int, void *, size_t) = NULL;
|
||||
ssize_t (*real___libc_read)(int, void *, size_t) = NULL;
|
||||
ssize_t (*real___write)(int, const void *, size_t) = NULL;
|
||||
ssize_t (*real___libc_write)(int, const void *, size_t) = NULL;
|
||||
int (*real___close)(int) = NULL;
|
||||
int (*real___libc_close)(int) = NULL;
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* dlsym 辅助宏 */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
/*
|
||||
* 找不到符号时不 fatal:部分 glibc 内部别名在某些发行版上可能不存在,
|
||||
* 置 NULL 后 hook 函数里做 NULL 检查再回退即可。
|
||||
*/
|
||||
#define LOAD_SYM(var, name) \
|
||||
do { \
|
||||
(var) = dlsym(RTLD_NEXT, (name)); \
|
||||
if (!(var)) \
|
||||
fprintf(stderr, "[zvfs] WARNING: dlsym(%s) = NULL\n", (name)); \
|
||||
} while (0)
|
||||
|
||||
#define LOAD_SYM_OPTIONAL(var, name) \
|
||||
do { (var) = dlsym(RTLD_NEXT, (name)); } while (0)
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* 初始化 */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
__attribute__((constructor))
|
||||
void zvfs_hook_init(void)
|
||||
{
|
||||
/* 必须存在的符号 */
|
||||
LOAD_SYM(real_open, "open");
|
||||
LOAD_SYM(real_open64, "open64");
|
||||
LOAD_SYM(real_openat, "openat");
|
||||
LOAD_SYM(real_openat64, "openat64");
|
||||
LOAD_SYM(real_creat, "creat");
|
||||
LOAD_SYM(real_creat64, "creat64");
|
||||
LOAD_SYM(real_close, "close");
|
||||
LOAD_SYM(real_dup, "dup");
|
||||
LOAD_SYM(real_dup2, "dup2");
|
||||
LOAD_SYM(real_dup3, "dup3");
|
||||
|
||||
LOAD_SYM(real_read, "read");
|
||||
LOAD_SYM(real_pread, "pread");
|
||||
LOAD_SYM(real_pread64, "pread64");
|
||||
LOAD_SYM(real_readv, "readv");
|
||||
LOAD_SYM(real_preadv, "preadv");
|
||||
LOAD_SYM(real_preadv64, "preadv64");
|
||||
LOAD_SYM(real_write, "write");
|
||||
LOAD_SYM(real_pwrite, "pwrite");
|
||||
LOAD_SYM(real_pwrite64, "pwrite64");
|
||||
LOAD_SYM(real_writev, "writev");
|
||||
LOAD_SYM(real_pwritev, "pwritev");
|
||||
LOAD_SYM(real_pwritev64, "pwritev64");
|
||||
|
||||
LOAD_SYM(real_lseek, "lseek");
|
||||
LOAD_SYM(real_lseek64, "lseek64");
|
||||
LOAD_SYM(real_truncate, "truncate");
|
||||
LOAD_SYM(real_truncate64, "truncate64");
|
||||
LOAD_SYM(real_ftruncate, "ftruncate");
|
||||
LOAD_SYM(real_ftruncate64, "ftruncate64");
|
||||
LOAD_SYM(real_fallocate, "fallocate");
|
||||
LOAD_SYM(real_posix_fallocate,"posix_fallocate");
|
||||
|
||||
LOAD_SYM(real_stat, "stat");
|
||||
LOAD_SYM(real_stat64, "stat64");
|
||||
LOAD_SYM(real_fstat, "fstat");
|
||||
LOAD_SYM(real_fstat64, "fstat64");
|
||||
LOAD_SYM(real_lstat, "lstat");
|
||||
LOAD_SYM(real_lstat64, "lstat64");
|
||||
LOAD_SYM(real_fstatat, "fstatat");
|
||||
LOAD_SYM(real_fstatat64, "fstatat64");
|
||||
LOAD_SYM(real_fsync, "fsync");
|
||||
LOAD_SYM(real_fdatasync, "fdatasync");
|
||||
LOAD_SYM(real_fcntl, "fcntl");
|
||||
LOAD_SYM(real_fcntl64, "fcntl64");
|
||||
LOAD_SYM(real_ioctl, "ioctl");
|
||||
|
||||
LOAD_SYM(real_unlink, "unlink");
|
||||
LOAD_SYM(real_unlinkat, "unlinkat");
|
||||
LOAD_SYM(real_rename, "rename");
|
||||
LOAD_SYM(real_renameat, "renameat");
|
||||
LOAD_SYM(real_mmap, "mmap");
|
||||
LOAD_SYM(real_mmap64, "mmap64");
|
||||
LOAD_SYM(real_munmap, "munmap");
|
||||
LOAD_SYM(real_msync, "msync");
|
||||
LOAD_SYM(real_fork, "fork");
|
||||
LOAD_SYM(real_vfork, "vfork");
|
||||
|
||||
/* 可选符号:glibc 内部别名,不一定存在 */
|
||||
LOAD_SYM_OPTIONAL(real_close_range, "close_range");
|
||||
LOAD_SYM_OPTIONAL(real_preadv2, "preadv2");
|
||||
LOAD_SYM_OPTIONAL(real_pwritev2, "pwritev2");
|
||||
LOAD_SYM_OPTIONAL(real_statx, "statx");
|
||||
LOAD_SYM_OPTIONAL(real_sync_file_range,"sync_file_range");
|
||||
LOAD_SYM_OPTIONAL(real_renameat2, "renameat2");
|
||||
LOAD_SYM_OPTIONAL(real___open, "__open");
|
||||
LOAD_SYM_OPTIONAL(real___open64, "__open64");
|
||||
LOAD_SYM_OPTIONAL(real___libc_open, "__libc_open");
|
||||
LOAD_SYM_OPTIONAL(real___read, "__read");
|
||||
LOAD_SYM_OPTIONAL(real___libc_read, "__libc_read");
|
||||
LOAD_SYM_OPTIONAL(real___write, "__write");
|
||||
LOAD_SYM_OPTIONAL(real___libc_write, "__libc_write");
|
||||
LOAD_SYM_OPTIONAL(real___close, "__close");
|
||||
LOAD_SYM_OPTIONAL(real___libc_close, "__libc_close");
|
||||
|
||||
/* 初始化全局 fs 结构 */
|
||||
zvfs_fs_init();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* 路径 / fd 判断 */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
int
|
||||
zvfs_is_zvfs_path(const char *path)
|
||||
{
|
||||
if (!path)
|
||||
return 0;
|
||||
/* 路径必须以 /zvfs 开头,且后一个字符是 '/' 或 '\0' */
|
||||
if (strncmp(path, ZVFS_MOUNT_PREFIX, ZVFS_MOUNT_PREFIX_LEN) != 0)
|
||||
return 0;
|
||||
char next = path[ZVFS_MOUNT_PREFIX_LEN];
|
||||
return (next == '/' || next == '\0');
|
||||
}
|
||||
|
||||
int
|
||||
zvfs_is_zvfs_fd(int fd)
|
||||
{
|
||||
if (fd < 0)
|
||||
return 0;
|
||||
pthread_mutex_lock(&g_fs.fd_mu);
|
||||
struct zvfs_open_file *of = openfile_lookup(fd);
|
||||
pthread_mutex_unlock(&g_fs.fd_mu);
|
||||
return (of != NULL);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* dirfd + 相对路径 → 绝对路径 */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
int
|
||||
zvfs_resolve_atpath(int dirfd, const char *path, char *buf, size_t bufsz)
|
||||
{
|
||||
/* 绝对路径:直接拷贝 */
|
||||
if (path && path[0] == '/') {
|
||||
if (strlen(path) >= bufsz) {
|
||||
errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
strncpy(buf, path, bufsz);
|
||||
buf[bufsz - 1] = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* AT_FDCWD:以当前工作目录为基准 */
|
||||
if (dirfd == AT_FDCWD) {
|
||||
if (!getcwd(buf, bufsz)) return -1;
|
||||
} else {
|
||||
/* 通过 /proc/self/fd/<dirfd> 读出目录的绝对路径 */
|
||||
char proc_path[64];
|
||||
snprintf(proc_path, sizeof(proc_path), "/proc/self/fd/%d", dirfd);
|
||||
ssize_t len = readlink(proc_path, buf, bufsz - 1);
|
||||
if (len < 0) return -1;
|
||||
buf[len] = '\0';
|
||||
}
|
||||
|
||||
/* 拼接 path */
|
||||
size_t dir_len = strlen(buf);
|
||||
size_t path_len = path ? strlen(path) : 0;
|
||||
if (dir_len + 1 + path_len >= bufsz) {
|
||||
errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
if (path_len > 0) {
|
||||
buf[dir_len] = '/';
|
||||
memcpy(buf + dir_len + 1, path, path_len + 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user