From: Weixie Cui <
cuiw...@gmail.com>
aux_close may return failed that should be handle.
reproduce error:
//failclose.c
static const char *hello_path = "/file";
static const char *hello_str = "hello\n";
static int x_getattr(const char *path, struct stat *st, struct fuse_file_info *fi) {
(void)fi;
memset(st, 0, sizeof(*st));
if (strcmp(path, "/") == 0) {
st->st_mode = S_IFDIR | 0555;
st->st_nlink = 2;
return 0;
}
if (strcmp(path, hello_path) == 0) {
st->st_mode = S_IFREG | 0444;
st->st_nlink = 1;
st->st_size = (off_t)strlen(hello_str);
return 0;
}
return -ENOENT;
}
static int x_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
off_t off, struct fuse_file_info *fi,
enum fuse_readdir_flags flags) {
(void)off; (void)fi; (void)flags;
if (strcmp(path, "/") != 0) return -ENOENT;
filler(buf, ".", NULL, 0, 0);
filler(buf, "..", NULL, 0, 0);
filler(buf, hello_path + 1, NULL, 0, 0); // "file"
return 0;
}
static int x_open(const char *path, struct fuse_file_info *fi) {
if (strcmp(path, hello_path) != 0) return -ENOENT;
// 只允许只读
if ((fi->flags & O_ACCMODE) != O_RDONLY) return -EACCES;
return 0;
}
static int x_read(const char *path, char *buf, size_t size, off_t off,
struct fuse_file_info *fi) {
(void)fi;
if (strcmp(path, hello_path) != 0) return -ENOENT;
size_t len = strlen(hello_str);
if ((size_t)off >= len) return 0;
if (off + (off_t)size > (off_t)len) size = len - (size_t)off;
memcpy(buf, hello_str + off, size);
return (int)size;
}
// 关键:让 flush 返回错误 -> close(fd) 会失败
static int x_flush(const char *path, struct fuse_file_info *fi) {
(void)path; (void)fi;
return -EIO; // 你也可以换成 -EPERM 等
}
static const struct fuse_operations ops = {
.getattr = x_getattr,
.readdir = x_readdir,
.open = x_open,
.read = x_read,
.flush = x_flush,
};
int main(int argc, char *argv[]) {
return fuse_main(argc, argv, &ops, NULL);
}
mount fuse:
gcc failclose.c -o failclose $(pkg-config fuse3 --cflags --libs)
mkdir -p mnt
./failclose -f mnt
// t.lua
for line in io.lines("../mnt/file") do
print(line)
end
execute command with lua with this patch:
lua t.lua
hello
./lua: t.lua:1: error closing file during lines iteration
stack traceback:
[C]: in for iterator 'for iterator'
t.lua:1: in main chunk
[C]: in ?
Signed-off-by: Weixie Cui <
cuiw...@gmail.com>
---
liolib.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/liolib.c b/liolib.c
index 57615e6f..c3d8cee9 100644
--- a/liolib.c
+++ b/liolib.c
@@ -649,9 +649,13 @@ static int io_readline (lua_State *L) {
return luaL_error(L, "%s", lua_tostring(L, -n + 1));
}
if (lua_toboolean(L, lua_upvalueindex(3))) { /* generator created file? */
+ int nclose;
lua_settop(L, 0); /* clear stack */
lua_pushvalue(L, lua_upvalueindex(1)); /* push file at index 1 */
- aux_close(L); /* close it */
+ nclose = aux_close(L); /* close it */
+ if (!lua_toboolean(L, -nclose)) {
+ return luaL_error(L, "error closing file during lines iteration");
+ }
}
return 0;
}
--
2.39.5 (Apple Git-154)