#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 #include #include #include #include #include #include /* ------------------------------------------------------------------ */ /* 线程局部重入计数定义 */ /* ------------------------------------------------------------------ */ __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/ 读出目录的绝对路径 */ 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; }