11#define FUSE_USE_VERSION 30
16#include <fuse_config.h>
32#include <linux/limits.h>
37static const char file_name[] =
"hello";
38static const char file_contents[] =
"Hello World!\n";
40static int tfs_stat(
fuse_ino_t ino,
struct stat *stbuf)
45 stbuf->st_mode = S_IFDIR | 0755;
50 stbuf->st_mode = S_IFREG | 0444;
52 stbuf->st_size = strlen(file_contents);
65 if (parent != FUSE_ROOT_ID || strcmp(name, file_name) != 0) {
70 memset(&e, 0,
sizeof(e));
73 e.entry_timeout = 1.0;
74 tfs_stat(e.ino, &e.attr);
86 memset(&stbuf, 0,
sizeof(stbuf));
87 if (tfs_stat(ino, &stbuf) == -1)
98static void dirbuf_add(
fuse_req_t req,
struct dirbuf *b,
const char *name,
102 size_t oldsize = b->size;
105 b->p = realloc(b->p, b->size);
106 assert(b->p != NULL);
108 memset(&stbuf, 0,
sizeof(stbuf));
114static int reply_buf_limited(
fuse_req_t req,
const char *buf,
size_t bufsize,
115 off_t off,
size_t maxsize)
117 size_t offset = (size_t) off;
119 if (off < 0 || offset >= bufsize)
122 if (bufsize - offset < maxsize)
123 maxsize = bufsize - offset;
135 if (ino != FUSE_ROOT_ID) {
140 memset(&b, 0,
sizeof(b));
141 dirbuf_add(req, &b,
".", FUSE_ROOT_ID);
142 dirbuf_add(req, &b,
"..", FUSE_ROOT_ID);
143 dirbuf_add(req, &b, file_name, FILE_INO);
144 reply_buf_limited(req, b.p, b.size, off, size);
153 else if ((fi->
flags & O_ACCMODE) != O_RDONLY)
164 assert(ino == FILE_INO);
165 reply_buf_limited(req, file_contents, strlen(file_contents), off, size);
169 .lookup = tfs_lookup,
170 .getattr = tfs_getattr,
171 .readdir = tfs_readdir,
176static void *run_fs(
void *data)
178 struct fuse_session *se = (
struct fuse_session *)data;
184static void check_readdir(
const char *mountpoint)
186 DIR *dir = opendir(mountpoint);
187 const struct dirent *ent;
191 while ((ent = readdir(dir)) != NULL) {
192 if (strcmp(ent->d_name, file_name) == 0)
195 assert(closedir(dir) == 0);
199static void check_read(
const char *mountpoint)
202 char buf[
sizeof(file_contents)];
206 assert(snprintf(path, PATH_MAX,
"%s/%s", mountpoint, file_name) > 0);
207 fd = open(path, O_RDONLY);
213 len = read(fd, buf,
sizeof(buf));
214 assert(len == (ssize_t) strlen(file_contents));
215 assert(memcmp(buf, file_contents, len) == 0);
216 assert(close(fd) == 0);
219int main(
int argc,
char *argv[])
222 struct fuse_session *se;
226 assert(fuse_parse_cmdline(&args, &fuse_opts) == 0);
230 se = fuse_session_new(&args, &tfs_oper,
sizeof(tfs_oper), NULL);
235 assert(pthread_create(&fs_thread, NULL, run_fs, (
void *)se) == 0);
237 check_readdir(fuse_opts.mountpoint);
238 check_read(fuse_opts.mountpoint);
245 assert(pthread_kill(fs_thread, SIGPIPE) == 0);
246 assert(pthread_join(fs_thread, NULL) == 0);
251 free(fuse_opts.mountpoint);
254 printf(
"Test completed successfully.\n");
int fuse_set_signal_handlers(struct fuse_session *se)
void fuse_remove_signal_handlers(struct fuse_session *se)
void fuse_session_destroy(struct fuse_session *se)
int fuse_reply_open(fuse_req_t req, const struct fuse_file_info *fi)
void fuse_session_exit(struct fuse_session *se)
int fuse_reply_err(fuse_req_t req, int err)
int fuse_reply_buf(fuse_req_t req, const char *buf, size_t size)
struct fuse_req * fuse_req_t
int fuse_session_loop(struct fuse_session *se)
int fuse_reply_entry(fuse_req_t req, const struct fuse_entry_param *e)
void fuse_session_unmount(struct fuse_session *se)
int fuse_session_mount(struct fuse_session *se, const char *mountpoint)
size_t fuse_add_direntry(fuse_req_t req, char *buf, size_t bufsize, const char *name, const struct stat *stbuf, off_t off)
int fuse_reply_attr(fuse_req_t req, const struct stat *attr, double attr_timeout)
int fuse_opt_add_arg(struct fuse_args *args, const char *arg)
void fuse_opt_free_args(struct fuse_args *args)
#define FUSE_ARGS_INIT(argc, argv)