pg /c database 通过。似乎是pg使用 open/write 写入了某个文件,通过 fopen/fscanf 绕过了hook路径导致的。出现了新的段错误。

This commit is contained in:
2026-03-13 10:49:31 +00:00
parent 544f532bf5
commit 4d350d5aea
28 changed files with 1686 additions and 128 deletions

View File

@@ -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 */
/* ------------------------------------------------------------------ */