pg /c database 通过。似乎是pg使用 open/write 写入了某个文件,通过 fopen/fscanf 绕过了hook路径导致的。出现了新的段错误。
This commit is contained in:
@@ -19,6 +19,97 @@
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* 内部:open/openat 调试日志 */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
static inline const char *
|
||||
zvfs_dbg_str(const char *s)
|
||||
{
|
||||
return s ? s : "(null)";
|
||||
}
|
||||
|
||||
static int
|
||||
zvfs_debug_open_enabled(void)
|
||||
{
|
||||
static int inited = 0;
|
||||
static int enabled = 0;
|
||||
const char *v;
|
||||
|
||||
if (!inited) {
|
||||
v = getenv("ZVFS_DEBUG_OPEN");
|
||||
enabled = (v && v[0] != '\0' && strcmp(v, "0") != 0);
|
||||
inited = 1;
|
||||
}
|
||||
return enabled;
|
||||
}
|
||||
|
||||
static const char *
|
||||
zvfs_debug_open_match(void)
|
||||
{
|
||||
static int inited = 0;
|
||||
static const char *match = NULL;
|
||||
|
||||
if (!inited) {
|
||||
match = getenv("ZVFS_DEBUG_OPEN_MATCH");
|
||||
if (match && match[0] == '\0') {
|
||||
match = NULL;
|
||||
}
|
||||
inited = 1;
|
||||
}
|
||||
return match;
|
||||
}
|
||||
|
||||
static int
|
||||
zvfs_debug_open_should_log(const char *path1, const char *path2)
|
||||
{
|
||||
const char *match;
|
||||
|
||||
if (!zvfs_debug_open_enabled()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
match = zvfs_debug_open_match();
|
||||
if (!match) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (path1 && strstr(path1, match)) {
|
||||
return 1;
|
||||
}
|
||||
if (path2 && strstr(path2, match)) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
zvfs_debug_open_log(const char *path1, const char *path2, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (!zvfs_debug_open_should_log(path1, path2)) {
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(stderr, "[zvfs][open-dbg][pid=%d][tid=%lu] ",
|
||||
getpid(), (unsigned long)pthread_self());
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
fputc('\n', stderr);
|
||||
}
|
||||
|
||||
static int
|
||||
zvfs_debug_has_fd_mapping(int fd)
|
||||
{
|
||||
int found = 0;
|
||||
pthread_mutex_lock(&g_fs.fd_mu);
|
||||
found = (openfile_lookup(fd) != NULL);
|
||||
pthread_mutex_unlock(&g_fs.fd_mu);
|
||||
return found;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* 内部:路径判定辅助 */
|
||||
/* ------------------------------------------------------------------ */
|
||||
@@ -104,6 +195,84 @@ zvfs_classify_path(const char *abspath, int may_create,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* 内部:fopen 模式解析 */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
static int
|
||||
zvfs_parse_fopen_mode(const char *mode, int extra_flags, int *flags_out, mode_t *create_mode_out)
|
||||
{
|
||||
int flags = 0;
|
||||
int plus = 0;
|
||||
int excl = 0;
|
||||
int cloexec = 0;
|
||||
const char *p;
|
||||
|
||||
if (!mode || !*mode || !flags_out || !create_mode_out) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (p = mode + 1; *p && *p != ','; ++p) {
|
||||
if (*p == '+') plus = 1;
|
||||
else if (*p == 'x') excl = 1;
|
||||
else if (*p == 'e') cloexec = 1;
|
||||
}
|
||||
|
||||
switch (mode[0]) {
|
||||
case 'r':
|
||||
flags = plus ? O_RDWR : O_RDONLY;
|
||||
break;
|
||||
case 'w':
|
||||
flags = (plus ? O_RDWR : O_WRONLY) | O_CREAT | O_TRUNC;
|
||||
break;
|
||||
case 'a':
|
||||
flags = (plus ? O_RDWR : O_WRONLY) | O_CREAT | O_APPEND;
|
||||
break;
|
||||
default:
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (excl) {
|
||||
flags |= O_EXCL;
|
||||
}
|
||||
if (cloexec) {
|
||||
flags |= O_CLOEXEC;
|
||||
}
|
||||
flags |= extra_flags;
|
||||
|
||||
*flags_out = flags;
|
||||
*create_mode_out = 0666;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
zvfs_sanitize_fdopen_mode(const char *mode, char out[4])
|
||||
{
|
||||
int i = 0;
|
||||
int plus = 0;
|
||||
int binary = 0;
|
||||
const char *p;
|
||||
|
||||
out[0] = 'r';
|
||||
out[1] = '\0';
|
||||
|
||||
if (!mode || !*mode) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (p = mode + 1; *p && *p != ','; ++p) {
|
||||
if (*p == '+') plus = 1;
|
||||
else if (*p == 'b') binary = 1;
|
||||
}
|
||||
|
||||
out[i++] = mode[0];
|
||||
if (binary && i < 3) out[i++] = 'b';
|
||||
if (plus && i < 3) out[i++] = '+';
|
||||
out[i] = '\0';
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* 内部:open 的核心逻辑(路径已解析为绝对路径) */
|
||||
/* ------------------------------------------------------------------ */
|
||||
@@ -125,6 +294,10 @@ zvfs_open_impl(int real_fd, const char *abspath, int flags, mode_t mode)
|
||||
uint64_t blob_id = 0;
|
||||
uint64_t handle_id = 0;
|
||||
|
||||
zvfs_debug_open_log(abspath, NULL,
|
||||
"open_impl enter real_fd=%d path=%s flags=0x%x mode=%#o",
|
||||
real_fd, zvfs_dbg_str(abspath), flags, (unsigned)mode);
|
||||
|
||||
if (flags & O_CREAT) {
|
||||
/* ---- 创建路径 -------------------------------------------- */
|
||||
|
||||
@@ -135,19 +308,41 @@ zvfs_open_impl(int real_fd, const char *abspath, int flags, mode_t mode)
|
||||
fprintf(stderr,
|
||||
"[zvfs] create blob failed path=%s flags=0x%x errno=%d(%s)\n",
|
||||
abspath, flags, saved, strerror(saved));
|
||||
zvfs_debug_open_log(abspath, NULL,
|
||||
"create branch blob_create fail errno=%d(%s)",
|
||||
saved, strerror(saved));
|
||||
errno = saved;
|
||||
goto fail;
|
||||
}
|
||||
zvfs_debug_open_log(abspath, NULL,
|
||||
"create branch blob_create ok blob_id=%lu handle_id=%lu",
|
||||
(unsigned long)blob_id, (unsigned long)handle_id);
|
||||
|
||||
/* 2. 把 blob_id 写入真实文件的 xattr */
|
||||
if (zvfs_xattr_write_blob_id(real_fd, blob_id) < 0) goto fail;
|
||||
if (zvfs_xattr_write_blob_id(real_fd, blob_id) < 0) {
|
||||
zvfs_debug_open_log(abspath, NULL,
|
||||
"create branch xattr_write fail errno=%d(%s)",
|
||||
errno, strerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
zvfs_debug_open_log(abspath, NULL, "create branch xattr_write ok");
|
||||
|
||||
/* 3. logical_size = 0,让 st_size 也为 0 */
|
||||
if (real_ftruncate(real_fd, 0) < 0) goto fail;
|
||||
if (real_ftruncate(real_fd, 0) < 0) {
|
||||
zvfs_debug_open_log(abspath, NULL,
|
||||
"create branch real_ftruncate(0) fail errno=%d(%s)",
|
||||
errno, strerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
zvfs_debug_open_log(abspath, NULL, "create branch real_ftruncate(0) ok");
|
||||
|
||||
/* 4. 分配 inode */
|
||||
inode = inode_alloc(blob_id, mode ? mode : 0666, ZVFS_ITYPE_FILE);
|
||||
if (!inode) { errno = ENOMEM; goto fail; }
|
||||
if (!inode) {
|
||||
errno = ENOMEM;
|
||||
zvfs_debug_open_log(abspath, NULL, "create branch inode_alloc fail ENOMEM");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* 5. 插入全局表 */
|
||||
pthread_mutex_lock(&g_fs.inode_mu);
|
||||
@@ -158,6 +353,9 @@ zvfs_open_impl(int real_fd, const char *abspath, int flags, mode_t mode)
|
||||
pthread_mutex_lock(&g_fs.path_mu);
|
||||
path_cache_insert(abspath, inode);
|
||||
pthread_mutex_unlock(&g_fs.path_mu);
|
||||
zvfs_debug_open_log(abspath, NULL,
|
||||
"create branch inode/path_cache inserted logical_size=%lu",
|
||||
(unsigned long)inode->logical_size);
|
||||
|
||||
} else {
|
||||
/* ---- 打开已有文件路径 ------------------------------------- */
|
||||
@@ -169,21 +367,38 @@ zvfs_open_impl(int real_fd, const char *abspath, int flags, mode_t mode)
|
||||
pthread_mutex_unlock(&g_fs.path_mu);
|
||||
|
||||
if (inode) {
|
||||
zvfs_debug_open_log(abspath, NULL,
|
||||
"open existing path_cache hit inode_blob_id=%lu",
|
||||
(unsigned long)inode->blob_id);
|
||||
/* path_cache 命中:直接用缓存的 inode,重新 blob_open */
|
||||
blob_id = inode->blob_id;
|
||||
if (blob_open(blob_id, &handle_id) != 0) {
|
||||
if (errno == 0) errno = EIO;
|
||||
zvfs_debug_open_log(abspath, NULL,
|
||||
"open existing path_cache-hit blob_open fail errno=%d(%s)",
|
||||
errno, strerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
/* 共享 inode,增加引用 */
|
||||
atomic_fetch_add(&inode->ref_count, 1);
|
||||
zvfs_debug_open_log(abspath, NULL,
|
||||
"open existing path_cache-hit blob_open ok handle_id=%lu",
|
||||
(unsigned long)handle_id);
|
||||
|
||||
} else {
|
||||
zvfs_debug_open_log(abspath, NULL, "open existing path_cache miss");
|
||||
/* 未命中:从 xattr 读 blob_id,可能是进程首次 open */
|
||||
if (zvfs_xattr_read_blob_id(real_fd, &blob_id) < 0) {
|
||||
/* xattr 不存在:不是 zvfs 管理的文件,降级透传 */
|
||||
int saved = errno;
|
||||
zvfs_debug_open_log(abspath, NULL,
|
||||
"open existing xattr_read miss errno=%d(%s), passthrough real_fd=%d",
|
||||
saved, strerror(saved), real_fd);
|
||||
return real_fd; /* 直接返回,不做任何包装 */
|
||||
}
|
||||
zvfs_debug_open_log(abspath, NULL,
|
||||
"open existing xattr_read ok blob_id=%lu",
|
||||
(unsigned long)blob_id);
|
||||
|
||||
/* 再查 inode_table(另一个 fd 可能已经 open 但路径未缓存)*/
|
||||
pthread_mutex_lock(&g_fs.inode_mu);
|
||||
@@ -191,18 +406,37 @@ zvfs_open_impl(int real_fd, const char *abspath, int flags, mode_t mode)
|
||||
pthread_mutex_unlock(&g_fs.inode_mu);
|
||||
|
||||
if (inode) {
|
||||
zvfs_debug_open_log(abspath, NULL,
|
||||
"open existing inode_table hit blob_id=%lu",
|
||||
(unsigned long)blob_id);
|
||||
if (blob_open(blob_id, &handle_id) != 0) {
|
||||
if (errno == 0) errno = EIO;
|
||||
zvfs_debug_open_log(abspath, NULL,
|
||||
"open existing inode_table-hit blob_open fail errno=%d(%s)",
|
||||
errno, strerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
atomic_fetch_add(&inode->ref_count, 1);
|
||||
zvfs_debug_open_log(abspath, NULL,
|
||||
"open existing inode_table-hit blob_open ok handle_id=%lu",
|
||||
(unsigned long)handle_id);
|
||||
} else {
|
||||
/* 全新 inode:需从真实文件 stat 获取 mode/size */
|
||||
struct stat st;
|
||||
if (zvfs_real_fstat(real_fd, &st) < 0) goto fail;
|
||||
if (zvfs_real_fstat(real_fd, &st) < 0) {
|
||||
zvfs_debug_open_log(abspath, NULL,
|
||||
"open existing fstat fail errno=%d(%s)",
|
||||
errno, strerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
inode = inode_alloc(blob_id, st.st_mode, ZVFS_ITYPE_FILE);
|
||||
if (!inode) { errno = ENOMEM; goto fail; }
|
||||
if (!inode) {
|
||||
errno = ENOMEM;
|
||||
zvfs_debug_open_log(abspath, NULL,
|
||||
"open existing inode_alloc fail ENOMEM");
|
||||
goto fail;
|
||||
}
|
||||
inode->logical_size = (uint64_t)st.st_size;
|
||||
|
||||
pthread_mutex_lock(&g_fs.inode_mu);
|
||||
@@ -214,8 +448,15 @@ zvfs_open_impl(int real_fd, const char *abspath, int flags, mode_t mode)
|
||||
pthread_mutex_unlock(&g_fs.path_mu);
|
||||
if (blob_open(blob_id, &handle_id) != 0) {
|
||||
if (errno == 0) errno = EIO;
|
||||
zvfs_debug_open_log(abspath, NULL,
|
||||
"open existing new-inode blob_open fail errno=%d(%s)",
|
||||
errno, strerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
zvfs_debug_open_log(abspath, NULL,
|
||||
"open existing new-inode ready handle_id=%lu logical_size=%lu",
|
||||
(unsigned long)handle_id,
|
||||
(unsigned long)inode->logical_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -227,6 +468,11 @@ zvfs_open_impl(int real_fd, const char *abspath, int flags, mode_t mode)
|
||||
pthread_mutex_lock(&g_fs.fd_mu);
|
||||
openfile_insert(of);
|
||||
pthread_mutex_unlock(&g_fs.fd_mu);
|
||||
zvfs_debug_open_log(abspath, NULL,
|
||||
"open_impl success real_fd=%d handle_id=%lu inode_blob_id=%lu",
|
||||
real_fd,
|
||||
(unsigned long)handle_id,
|
||||
(unsigned long)(inode ? inode->blob_id : 0));
|
||||
|
||||
return real_fd;
|
||||
|
||||
@@ -235,6 +481,9 @@ fail_handle:
|
||||
blob_close(handle_id);
|
||||
}
|
||||
fail:
|
||||
zvfs_debug_open_log(abspath, NULL,
|
||||
"open_impl fail errno=%d(%s) real_fd=%d",
|
||||
errno, strerror(errno), real_fd);
|
||||
/* inode 若刚分配(ref_count==1)需要回滚 */
|
||||
if (inode && atomic_load(&inode->ref_count) == 1) {
|
||||
pthread_mutex_lock(&g_fs.inode_mu);
|
||||
@@ -259,6 +508,8 @@ open(const char *path, int flags, ...)
|
||||
|
||||
char abspath[PATH_MAX];
|
||||
char normpath[PATH_MAX];
|
||||
abspath[0] = '\0';
|
||||
normpath[0] = '\0';
|
||||
int is_zvfs_path = 0;
|
||||
|
||||
mode_t mode = 0;
|
||||
@@ -272,11 +523,26 @@ open(const char *path, int flags, ...)
|
||||
if (zvfs_resolve_atpath(AT_FDCWD, path, abspath, sizeof(abspath)) == 0) {
|
||||
is_zvfs_path = zvfs_classify_path(abspath, (flags & O_CREAT) != 0,
|
||||
normpath, sizeof(normpath));
|
||||
zvfs_debug_open_log(path, abspath,
|
||||
"open resolve ok path=%s abspath=%s norm=%s flags=0x%x is_zvfs=%d",
|
||||
zvfs_dbg_str(path), zvfs_dbg_str(abspath),
|
||||
zvfs_dbg_str(normpath), flags, is_zvfs_path);
|
||||
} else {
|
||||
zvfs_debug_open_log(path, NULL,
|
||||
"open resolve fail path=%s flags=0x%x errno=%d(%s)",
|
||||
zvfs_dbg_str(path), flags, errno, strerror(errno));
|
||||
}
|
||||
|
||||
int ret;
|
||||
if (ZVFS_IN_HOOK() || !is_zvfs_path) {
|
||||
zvfs_debug_open_log(path, abspath,
|
||||
"open passthrough reason=%s path=%s flags=0x%x",
|
||||
ZVFS_IN_HOOK() ? "reentrant" : "non-zvfs",
|
||||
zvfs_dbg_str(path), flags);
|
||||
ret = real_open(path, flags, mode);
|
||||
zvfs_debug_open_log(path, abspath,
|
||||
"open passthrough ret=%d errno=%d(%s)",
|
||||
ret, (ret < 0) ? errno : 0, (ret < 0) ? strerror(errno) : "OK");
|
||||
ZVFS_HOOK_LEAVE();
|
||||
return ret;
|
||||
}
|
||||
@@ -285,13 +551,28 @@ open(const char *path, int flags, ...)
|
||||
|
||||
/* 先让真实 FS 创建 / 打开文件(获得 real_fd) */
|
||||
int real_fd = real_open(path, flags, mode);
|
||||
if (real_fd < 0) { ZVFS_HOOK_LEAVE(); return -1; }
|
||||
if (real_fd < 0) {
|
||||
zvfs_debug_open_log(path, abspath,
|
||||
"open real_open fail path=%s flags=0x%x errno=%d(%s)",
|
||||
zvfs_dbg_str(path), flags, errno, strerror(errno));
|
||||
ZVFS_HOOK_LEAVE();
|
||||
return -1;
|
||||
}
|
||||
zvfs_debug_open_log(path, abspath,
|
||||
"open real_open ok real_fd=%d path=%s norm=%s",
|
||||
real_fd, zvfs_dbg_str(path), zvfs_dbg_str(normpath));
|
||||
|
||||
ret = zvfs_open_impl(real_fd, normpath, flags, mode);
|
||||
if (ret < 0) {
|
||||
int saved = errno;
|
||||
real_close(real_fd);
|
||||
errno = saved;
|
||||
zvfs_debug_open_log(path, abspath,
|
||||
"open zvfs_open_impl fail real_fd=%d errno=%d(%s)",
|
||||
real_fd, saved, strerror(saved));
|
||||
} else {
|
||||
zvfs_debug_open_log(path, abspath,
|
||||
"open zvfs_open_impl success fd=%d", ret);
|
||||
}
|
||||
|
||||
ZVFS_HOOK_LEAVE();
|
||||
@@ -319,6 +600,9 @@ openat(int dirfd, const char *path, int flags, ...)
|
||||
ZVFS_HOOK_ENTER();
|
||||
|
||||
char normpath[PATH_MAX];
|
||||
char abspath[PATH_MAX];
|
||||
normpath[0] = '\0';
|
||||
abspath[0] = '\0';
|
||||
int is_zvfs_path = 0;
|
||||
|
||||
mode_t mode = 0;
|
||||
@@ -329,17 +613,30 @@ openat(int dirfd, const char *path, int flags, ...)
|
||||
}
|
||||
|
||||
/* 解析绝对路径判断是否属于 zvfs */
|
||||
char abspath[PATH_MAX];
|
||||
if (zvfs_resolve_atpath(dirfd, path, abspath, sizeof(abspath)) < 0) {
|
||||
zvfs_debug_open_log(path, NULL,
|
||||
"openat resolve fail dirfd=%d path=%s flags=0x%x errno=%d(%s)",
|
||||
dirfd, zvfs_dbg_str(path), flags, errno, strerror(errno));
|
||||
ZVFS_HOOK_LEAVE();
|
||||
return -1;
|
||||
}
|
||||
is_zvfs_path = zvfs_classify_path(abspath, (flags & O_CREAT) != 0,
|
||||
normpath, sizeof(normpath));
|
||||
zvfs_debug_open_log(path, abspath,
|
||||
"openat resolve ok dirfd=%d path=%s abspath=%s norm=%s flags=0x%x is_zvfs=%d",
|
||||
dirfd, zvfs_dbg_str(path), zvfs_dbg_str(abspath),
|
||||
zvfs_dbg_str(normpath), flags, is_zvfs_path);
|
||||
|
||||
int ret;
|
||||
if (ZVFS_IN_HOOK() || !is_zvfs_path) {
|
||||
zvfs_debug_open_log(path, abspath,
|
||||
"openat passthrough reason=%s dirfd=%d path=%s flags=0x%x",
|
||||
ZVFS_IN_HOOK() ? "reentrant" : "non-zvfs",
|
||||
dirfd, zvfs_dbg_str(path), flags);
|
||||
ret = real_openat(dirfd, path, flags, mode);
|
||||
zvfs_debug_open_log(path, abspath,
|
||||
"openat passthrough ret=%d errno=%d(%s)",
|
||||
ret, (ret < 0) ? errno : 0, (ret < 0) ? strerror(errno) : "OK");
|
||||
ZVFS_HOOK_LEAVE();
|
||||
return ret;
|
||||
}
|
||||
@@ -347,13 +644,28 @@ openat(int dirfd, const char *path, int flags, ...)
|
||||
zvfs_ensure_init();
|
||||
|
||||
int real_fd = real_openat(dirfd, path, flags, mode);
|
||||
if (real_fd < 0) { ZVFS_HOOK_LEAVE(); return -1; }
|
||||
if (real_fd < 0) {
|
||||
zvfs_debug_open_log(path, abspath,
|
||||
"openat real_openat fail dirfd=%d path=%s flags=0x%x errno=%d(%s)",
|
||||
dirfd, zvfs_dbg_str(path), flags, errno, strerror(errno));
|
||||
ZVFS_HOOK_LEAVE();
|
||||
return -1;
|
||||
}
|
||||
zvfs_debug_open_log(path, abspath,
|
||||
"openat real_openat ok real_fd=%d dirfd=%d path=%s norm=%s",
|
||||
real_fd, dirfd, zvfs_dbg_str(path), zvfs_dbg_str(normpath));
|
||||
|
||||
ret = zvfs_open_impl(real_fd, normpath, flags, mode);
|
||||
if (ret < 0) {
|
||||
int saved = errno;
|
||||
real_close(real_fd);
|
||||
errno = saved;
|
||||
zvfs_debug_open_log(path, abspath,
|
||||
"openat zvfs_open_impl fail real_fd=%d errno=%d(%s)",
|
||||
real_fd, saved, strerror(saved));
|
||||
} else {
|
||||
zvfs_debug_open_log(path, abspath,
|
||||
"openat zvfs_open_impl success fd=%d", ret);
|
||||
}
|
||||
|
||||
ZVFS_HOOK_LEAVE();
|
||||
@@ -371,6 +683,102 @@ int openat64(int dirfd, const char *path, int flags, ...)
|
||||
return openat(dirfd, path, flags | O_LARGEFILE, mode);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* fopen / fopen64 */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
static FILE *
|
||||
zvfs_fopen_common(const char *path, const char *mode, int extra_open_flags, int use_fopen64)
|
||||
{
|
||||
char abspath[PATH_MAX];
|
||||
char normpath[PATH_MAX];
|
||||
char fdopen_mode[4];
|
||||
int is_zvfs_path = 0;
|
||||
int flags = 0;
|
||||
mode_t create_mode = 0666;
|
||||
int real_fd = -1;
|
||||
FILE *fp = NULL;
|
||||
|
||||
if (zvfs_parse_fopen_mode(mode, extra_open_flags, &flags, &create_mode) != 0) {
|
||||
if (use_fopen64 && real_fopen64) return real_fopen64(path, mode);
|
||||
if (real_fopen) return real_fopen(path, mode);
|
||||
errno = ENOSYS;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (zvfs_resolve_atpath(AT_FDCWD, path, abspath, sizeof(abspath)) == 0) {
|
||||
is_zvfs_path = zvfs_classify_path(abspath, (flags & O_CREAT) != 0,
|
||||
normpath, sizeof(normpath));
|
||||
zvfs_debug_open_log(path, abspath,
|
||||
"fopen resolve ok path=%s mode=%s norm=%s flags=0x%x is_zvfs=%d",
|
||||
zvfs_dbg_str(path), zvfs_dbg_str(mode),
|
||||
zvfs_dbg_str(normpath), flags, is_zvfs_path);
|
||||
} else {
|
||||
zvfs_debug_open_log(path, NULL,
|
||||
"fopen resolve fail path=%s mode=%s errno=%d(%s)",
|
||||
zvfs_dbg_str(path), zvfs_dbg_str(mode), errno, strerror(errno));
|
||||
}
|
||||
|
||||
if (ZVFS_IN_HOOK() || !is_zvfs_path) {
|
||||
if (use_fopen64 && real_fopen64) return real_fopen64(path, mode);
|
||||
if (real_fopen) return real_fopen(path, mode);
|
||||
errno = ENOSYS;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
zvfs_ensure_init();
|
||||
|
||||
real_fd = real_open(path, flags, create_mode);
|
||||
if (real_fd < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (zvfs_open_impl(real_fd, normpath, flags, create_mode) < 0) {
|
||||
int saved = errno;
|
||||
real_close(real_fd);
|
||||
errno = saved;
|
||||
return NULL;
|
||||
}
|
||||
zvfs_debug_open_log(path, normpath,
|
||||
"fopen mapped-after-open_impl fd=%d mapped=%d",
|
||||
real_fd, zvfs_debug_has_fd_mapping(real_fd));
|
||||
|
||||
zvfs_sanitize_fdopen_mode(mode, fdopen_mode);
|
||||
if (real_fdopen) {
|
||||
fp = real_fdopen(real_fd, fdopen_mode);
|
||||
} else {
|
||||
fp = fdopen(real_fd, fdopen_mode);
|
||||
}
|
||||
if (!fp) {
|
||||
int saved = errno;
|
||||
close(real_fd);
|
||||
errno = saved;
|
||||
return NULL;
|
||||
}
|
||||
zvfs_debug_open_log(path, normpath,
|
||||
"fopen mapped-after-fdopen fd=%d mapped=%d",
|
||||
real_fd, zvfs_debug_has_fd_mapping(real_fd));
|
||||
return fp;
|
||||
}
|
||||
|
||||
FILE *
|
||||
fopen(const char *path, const char *mode)
|
||||
{
|
||||
ZVFS_HOOK_ENTER();
|
||||
FILE *fp = zvfs_fopen_common(path, mode, 0, 0);
|
||||
ZVFS_HOOK_LEAVE();
|
||||
return fp;
|
||||
}
|
||||
|
||||
FILE *
|
||||
fopen64(const char *path, const char *mode)
|
||||
{
|
||||
ZVFS_HOOK_ENTER();
|
||||
FILE *fp = zvfs_fopen_common(path, mode, O_LARGEFILE, 1);
|
||||
ZVFS_HOOK_LEAVE();
|
||||
return fp;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* creat */
|
||||
/* ------------------------------------------------------------------ */
|
||||
@@ -411,6 +819,28 @@ int __open64(const char *path, int flags, ...)
|
||||
return open64(path, flags, mode);
|
||||
}
|
||||
|
||||
int __openat(int dirfd, const char *path, int flags, ...)
|
||||
{
|
||||
mode_t mode = 0;
|
||||
if (flags & O_CREAT) {
|
||||
va_list ap; va_start(ap, flags);
|
||||
mode = (mode_t)va_arg(ap, unsigned int);
|
||||
va_end(ap);
|
||||
}
|
||||
return openat(dirfd, path, flags, mode);
|
||||
}
|
||||
|
||||
int __openat64(int dirfd, const char *path, int flags, ...)
|
||||
{
|
||||
mode_t mode = 0;
|
||||
if (flags & O_CREAT) {
|
||||
va_list ap; va_start(ap, flags);
|
||||
mode = (mode_t)va_arg(ap, unsigned int);
|
||||
va_end(ap);
|
||||
}
|
||||
return openat64(dirfd, path, flags, mode);
|
||||
}
|
||||
|
||||
int __libc_open(const char *path, int flags, ...)
|
||||
{
|
||||
mode_t mode = 0;
|
||||
@@ -422,6 +852,109 @@ int __libc_open(const char *path, int flags, ...)
|
||||
return open(path, flags, mode);
|
||||
}
|
||||
|
||||
int __libc_open64(const char *path, int flags, ...)
|
||||
{
|
||||
mode_t mode = 0;
|
||||
if (flags & O_CREAT) {
|
||||
va_list ap; va_start(ap, flags);
|
||||
mode = (mode_t)va_arg(ap, unsigned int);
|
||||
va_end(ap);
|
||||
}
|
||||
return open64(path, flags, mode);
|
||||
}
|
||||
|
||||
int __libc_openat(int dirfd, const char *path, int flags, ...)
|
||||
{
|
||||
mode_t mode = 0;
|
||||
if (flags & O_CREAT) {
|
||||
va_list ap; va_start(ap, flags);
|
||||
mode = (mode_t)va_arg(ap, unsigned int);
|
||||
va_end(ap);
|
||||
}
|
||||
return openat(dirfd, path, flags, mode);
|
||||
}
|
||||
|
||||
int __libc_openat64(int dirfd, const char *path, int flags, ...)
|
||||
{
|
||||
mode_t mode = 0;
|
||||
if (flags & O_CREAT) {
|
||||
va_list ap; va_start(ap, flags);
|
||||
mode = (mode_t)va_arg(ap, unsigned int);
|
||||
va_end(ap);
|
||||
}
|
||||
return openat64(dirfd, path, flags, mode);
|
||||
}
|
||||
|
||||
int __open_2(const char *path, int flags)
|
||||
{
|
||||
zvfs_debug_open_log(path, NULL,
|
||||
"__open_2 called path=%s flags=0x%x",
|
||||
zvfs_dbg_str(path), flags);
|
||||
return open(path, flags);
|
||||
}
|
||||
|
||||
int __open64_2(const char *path, int flags)
|
||||
{
|
||||
return open64(path, flags);
|
||||
}
|
||||
|
||||
int __openat_2(int dirfd, const char *path, int flags)
|
||||
{
|
||||
zvfs_debug_open_log(path, NULL,
|
||||
"__openat_2 called dirfd=%d path=%s flags=0x%x",
|
||||
dirfd, zvfs_dbg_str(path), flags);
|
||||
return openat(dirfd, path, flags);
|
||||
}
|
||||
|
||||
int __openat64_2(int dirfd, const char *path, int flags)
|
||||
{
|
||||
return openat64(dirfd, path, flags);
|
||||
}
|
||||
|
||||
int __open_nocancel(const char *path, int flags, ...)
|
||||
{
|
||||
mode_t mode = 0;
|
||||
if (flags & O_CREAT) {
|
||||
va_list ap; va_start(ap, flags);
|
||||
mode = (mode_t)va_arg(ap, unsigned int);
|
||||
va_end(ap);
|
||||
}
|
||||
return open(path, flags, mode);
|
||||
}
|
||||
|
||||
int __open64_nocancel(const char *path, int flags, ...)
|
||||
{
|
||||
mode_t mode = 0;
|
||||
if (flags & O_CREAT) {
|
||||
va_list ap; va_start(ap, flags);
|
||||
mode = (mode_t)va_arg(ap, unsigned int);
|
||||
va_end(ap);
|
||||
}
|
||||
return open64(path, flags, mode);
|
||||
}
|
||||
|
||||
int __openat_nocancel(int dirfd, const char *path, int flags, ...)
|
||||
{
|
||||
mode_t mode = 0;
|
||||
if (flags & O_CREAT) {
|
||||
va_list ap; va_start(ap, flags);
|
||||
mode = (mode_t)va_arg(ap, unsigned int);
|
||||
va_end(ap);
|
||||
}
|
||||
return openat(dirfd, path, flags, mode);
|
||||
}
|
||||
|
||||
int __openat64_nocancel(int dirfd, const char *path, int flags, ...)
|
||||
{
|
||||
mode_t mode = 0;
|
||||
if (flags & O_CREAT) {
|
||||
va_list ap; va_start(ap, flags);
|
||||
mode = (mode_t)va_arg(ap, unsigned int);
|
||||
va_end(ap);
|
||||
}
|
||||
return openat64(dirfd, path, flags, mode);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* close */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
Reference in New Issue
Block a user