blob: 882f2cd9e37dd3725bb5a8093f7d1d33e7cb10df [file] [log] [blame]
Miklos Szeredi76c17522005-07-13 14:08:19 +00001/*
2 FUSE: Filesystem in Userspace
3 Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
4
5 This program can be distributed under the terms of the GNU GPL.
6 See the file COPYING.
7*/
8
9#include <fuse_lowlevel.h>
10#include <fuse.h>
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14#include <errno.h>
15#include <fcntl.h>
16#include <unistd.h>
17#include <assert.h>
18
19static const char *hello_str = "Hello World!\n";
20static const char *hello_name = "hello";
21
22static int hello_stat(fuse_ino_t ino, struct stat *stbuf)
23{
24 stbuf->st_ino = ino;
25 switch (ino) {
26 case 1:
27 stbuf->st_mode = S_IFDIR | 0755;
28 stbuf->st_nlink = 2;
29 break;
Miklos Szeredi9b813af2005-07-21 07:59:37 +000030
Miklos Szeredi76c17522005-07-13 14:08:19 +000031 case 2:
32 stbuf->st_mode = S_IFREG | 0444;
33 stbuf->st_nlink = 1;
34 stbuf->st_size = strlen(hello_str);
35 break;
Miklos Szeredi9b813af2005-07-21 07:59:37 +000036
Miklos Szeredi76c17522005-07-13 14:08:19 +000037 default:
38 return -1;
39 }
40 return 0;
41}
42
Miklos Szerediecce1bf2005-08-25 15:19:06 +000043static void hello_ll_getattr(fuse_req_t req, fuse_ino_t ino,
44 struct fuse_file_info *fi)
Miklos Szeredi76c17522005-07-13 14:08:19 +000045{
46 struct stat stbuf;
47
Miklos Szerediecce1bf2005-08-25 15:19:06 +000048 (void) fi;
49
Miklos Szeredi76c17522005-07-13 14:08:19 +000050 memset(&stbuf, 0, sizeof(stbuf));
51 if (hello_stat(ino, &stbuf) == -1)
52 fuse_reply_err(req, ENOENT);
53 else
54 fuse_reply_attr(req, &stbuf, 1.0);
55}
56
57static void hello_ll_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
58{
59 struct fuse_entry_param e;
60
61 if (parent != 1 || strcmp(name, hello_name) != 0)
62 fuse_reply_err(req, ENOENT);
63 else {
64 memset(&e, 0, sizeof(e));
65 e.ino = 2;
66 e.attr_timeout = 1.0;
67 e.entry_timeout = 1.0;
68 hello_stat(e.ino, &e.attr);
Miklos Szeredi9b813af2005-07-21 07:59:37 +000069
Miklos Szeredi76c17522005-07-13 14:08:19 +000070 fuse_reply_entry(req, &e);
71 }
72}
73
74struct dirbuf {
75 char *p;
76 size_t size;
77};
78
79static void dirbuf_add(struct dirbuf *b, const char *name, fuse_ino_t ino)
80{
81 struct stat stbuf;
82 size_t oldsize = b->size;
83 b->size += fuse_dirent_size(strlen(name));
Miklos Szeredif6e0ec62005-08-03 09:11:06 +000084 b->p = (char *) realloc(b->p, b->size);
Miklos Szeredi76c17522005-07-13 14:08:19 +000085 memset(&stbuf, 0, sizeof(stbuf));
86 stbuf.st_ino = ino;
87 fuse_add_dirent(b->p + oldsize, name, &stbuf, b->size);
88}
89
90#define min(x, y) ((x) < (y) ? (x) : (y))
91
92static int reply_buf_limited(fuse_req_t req, const char *buf, size_t bufsize,
93 off_t off, size_t maxsize)
94{
Miklos Szeredi76c17522005-07-13 14:08:19 +000095 if (off < bufsize)
96 return fuse_reply_buf(req, buf + off, min(bufsize - off, maxsize));
97 else
98 return fuse_reply_buf(req, NULL, 0);
99}
100
101static void hello_ll_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
102 off_t off, struct fuse_file_info *fi)
103{
104 (void) fi;
105
106 if (ino != 1)
107 fuse_reply_err(req, ENOTDIR);
108 else {
109 struct dirbuf b;
Miklos Szeredi9b813af2005-07-21 07:59:37 +0000110
Miklos Szeredi76c17522005-07-13 14:08:19 +0000111 memset(&b, 0, sizeof(b));
112 dirbuf_add(&b, ".", 1);
113 dirbuf_add(&b, "..", 1);
114 dirbuf_add(&b, hello_name, 2);
115 reply_buf_limited(req, b.p, b.size, off, size);
116 free(b.p);
117 }
118}
119
120static void hello_ll_open(fuse_req_t req, fuse_ino_t ino,
121 struct fuse_file_info *fi)
122{
123 if (ino != 2)
124 fuse_reply_err(req, EISDIR);
125 else if ((fi->flags & 3) != O_RDONLY)
126 fuse_reply_err(req, EACCES);
127 else
128 fuse_reply_open(req, fi);
129}
130
131static void hello_ll_read(fuse_req_t req, fuse_ino_t ino, size_t size,
132 off_t off, struct fuse_file_info *fi)
133{
134 (void) fi;
135
136 assert(ino == 2);
137 reply_buf_limited(req, hello_str, strlen(hello_str), off, size);
138}
139
Miklos Szeredia1482422005-08-14 23:00:27 +0000140static struct fuse_lowlevel_ops hello_ll_oper = {
Miklos Szeredi76c17522005-07-13 14:08:19 +0000141 .lookup = hello_ll_lookup,
142 .getattr = hello_ll_getattr,
143 .readdir = hello_ll_readdir,
144 .open = hello_ll_open,
145 .read = hello_ll_read,
146};
147
148int main(int argc, char *argv[])
149{
150 const char *mountpoint;
Miklos Szeredi76c17522005-07-13 14:08:19 +0000151 int err = -1;
152 int fd;
153
154 if (argc != 2) {
155 fprintf(stderr, "usage: %s mountpoint\n", argv[0]);
156 return 1;
157 }
158 mountpoint = argv[1];
159 fd = fuse_mount(mountpoint, NULL);
160 if (fd != -1) {
Miklos Szeredia1482422005-08-14 23:00:27 +0000161 struct fuse_session *se;
162
163 se = fuse_lowlevel_new("debug", &hello_ll_oper, sizeof(hello_ll_oper),
164 NULL);
165 if (se != NULL) {
166 struct fuse_chan *ch = fuse_kern_chan_new(fd);
167 if (ch != NULL) {
168 fuse_session_add_chan(se, ch);
169 err = fuse_session_loop(se);
170 }
171 fuse_session_destroy(se);
Miklos Szeredi76c17522005-07-13 14:08:19 +0000172 }
173 close(fd);
174 }
175 fuse_unmount(mountpoint);
176
177 return err ? 1 : 0;
178}