2 FUSE: Filesystem in Userspace
3 Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
5 This program can be distributed under the terms of the GNU GPL.
8 gcc -Wall `pkg-config fuse --cflags --libs` hello_ll.c -o hello_ll
11 #define FUSE_USE_VERSION 26
13 #include <fuse_lowlevel.h>
22 static const char *hello_str
= "Hello World!\n";
23 static const char *hello_name
= "hello";
25 static int hello_stat(fuse_ino_t ino
, struct stat
*stbuf
)
30 stbuf
->st_mode
= S_IFDIR
| 0755;
35 stbuf
->st_mode
= S_IFREG
| 0444;
37 stbuf
->st_size
= strlen(hello_str
);
46 static void hello_ll_getattr(fuse_req_t req
, fuse_ino_t ino
,
47 struct fuse_file_info
*fi
)
53 memset(&stbuf
, 0, sizeof(stbuf
));
54 if (hello_stat(ino
, &stbuf
) == -1)
55 fuse_reply_err(req
, ENOENT
);
57 fuse_reply_attr(req
, &stbuf
, 1.0);
60 static void hello_ll_lookup(fuse_req_t req
, fuse_ino_t parent
, const char *name
)
62 struct fuse_entry_param e
;
64 if (parent
!= 1 || strcmp(name
, hello_name
) != 0)
65 fuse_reply_err(req
, ENOENT
);
67 memset(&e
, 0, sizeof(e
));
70 e
.entry_timeout
= 1.0;
71 hello_stat(e
.ino
, &e
.attr
);
73 fuse_reply_entry(req
, &e
);
82 static void dirbuf_add(fuse_req_t req
, struct dirbuf
*b
, const char *name
,
86 size_t oldsize
= b
->size
;
87 b
->size
+= fuse_add_direntry(req
, NULL
, 0, name
, NULL
, 0);
88 b
->p
= (char *) realloc(b
->p
, b
->size
);
89 memset(&stbuf
, 0, sizeof(stbuf
));
91 fuse_add_direntry(req
, b
->p
+ oldsize
, b
->size
- oldsize
, name
, &stbuf
,
95 #define min(x, y) ((x) < (y) ? (x) : (y))
97 static int reply_buf_limited(fuse_req_t req
, const char *buf
, size_t bufsize
,
98 off_t off
, size_t maxsize
)
101 return fuse_reply_buf(req
, buf
+ off
, min(bufsize
- off
, maxsize
));
103 return fuse_reply_buf(req
, NULL
, 0);
106 static void hello_ll_readdir(fuse_req_t req
, fuse_ino_t ino
, size_t size
,
107 off_t off
, struct fuse_file_info
*fi
)
112 fuse_reply_err(req
, ENOTDIR
);
116 memset(&b
, 0, sizeof(b
));
117 dirbuf_add(req
, &b
, ".", 1);
118 dirbuf_add(req
, &b
, "..", 1);
119 dirbuf_add(req
, &b
, hello_name
, 2);
120 reply_buf_limited(req
, b
.p
, b
.size
, off
, size
);
125 static void hello_ll_open(fuse_req_t req
, fuse_ino_t ino
,
126 struct fuse_file_info
*fi
)
129 fuse_reply_err(req
, EISDIR
);
130 else if ((fi
->flags
& 3) != O_RDONLY
)
131 fuse_reply_err(req
, EACCES
);
133 fuse_reply_open(req
, fi
);
136 static void hello_ll_read(fuse_req_t req
, fuse_ino_t ino
, size_t size
,
137 off_t off
, struct fuse_file_info
*fi
)
142 reply_buf_limited(req
, hello_str
, strlen(hello_str
), off
, size
);
145 static struct fuse_lowlevel_ops hello_ll_oper
= {
146 .lookup
= hello_ll_lookup
,
147 .getattr
= hello_ll_getattr
,
148 .readdir
= hello_ll_readdir
,
149 .open
= hello_ll_open
,
150 .read
= hello_ll_read
,
153 int main(int argc
, char *argv
[])
155 struct fuse_args args
= FUSE_ARGS_INIT(argc
, argv
);
156 struct fuse_chan
*ch
;
160 if (fuse_parse_cmdline(&args
, &mountpoint
, NULL
, NULL
) != -1 &&
161 (ch
= fuse_mount(mountpoint
, &args
)) != NULL
) {
162 struct fuse_session
*se
;
164 se
= fuse_lowlevel_new(&args
, &hello_ll_oper
, sizeof(hello_ll_oper
),
167 if (fuse_set_signal_handlers(se
) != -1) {
168 fuse_session_add_chan(se
, ch
);
169 err
= fuse_session_loop(se
);
170 fuse_remove_signal_handlers(se
);
171 fuse_session_remove_chan(ch
);
173 fuse_session_destroy(se
);
175 fuse_unmount(mountpoint
, ch
);
177 fuse_opt_free_args(&args
);