Tizen 2.1 base
[framework/base/fuse.git] / example / fusexmp.c
1 /*
2   FUSE: Filesystem in Userspace
3   Copyright (C) 2001-2007  Miklos Szeredi <miklos@szeredi.hu>
4   Copyright (C) 2011       Sebastian Pipping <sebastian@pipping.org>
5
6   This program can be distributed under the terms of the GNU GPL.
7   See the file COPYING.
8
9   gcc -Wall fusexmp.c `pkg-config fuse --cflags --libs` -o fusexmp
10 */
11
12 #define FUSE_USE_VERSION 26
13
14 #ifdef HAVE_CONFIG_H
15 #include <config.h>
16 #endif
17
18 #ifdef linux
19 /* For pread()/pwrite()/utimensat() */
20 #define _XOPEN_SOURCE 700
21 #endif
22
23 #include <fuse.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <fcntl.h>
28 #include <sys/stat.h>
29 #include <dirent.h>
30 #include <errno.h>
31 #include <sys/time.h>
32 #ifdef HAVE_SETXATTR
33 #include <sys/xattr.h>
34 #endif
35
36 static int xmp_getattr(const char *path, struct stat *stbuf)
37 {
38         int res;
39
40         res = lstat(path, stbuf);
41         if (res == -1)
42                 return -errno;
43
44         return 0;
45 }
46
47 static int xmp_access(const char *path, int mask)
48 {
49         int res;
50
51         res = access(path, mask);
52         if (res == -1)
53                 return -errno;
54
55         return 0;
56 }
57
58 static int xmp_readlink(const char *path, char *buf, size_t size)
59 {
60         int res;
61
62         res = readlink(path, buf, size - 1);
63         if (res == -1)
64                 return -errno;
65
66         buf[res] = '\0';
67         return 0;
68 }
69
70
71 static int xmp_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
72                        off_t offset, struct fuse_file_info *fi)
73 {
74         DIR *dp;
75         struct dirent *de;
76
77         (void) offset;
78         (void) fi;
79
80         dp = opendir(path);
81         if (dp == NULL)
82                 return -errno;
83
84         while ((de = readdir(dp)) != NULL) {
85                 struct stat st;
86                 memset(&st, 0, sizeof(st));
87                 st.st_ino = de->d_ino;
88                 st.st_mode = de->d_type << 12;
89                 if (filler(buf, de->d_name, &st, 0))
90                         break;
91         }
92
93         closedir(dp);
94         return 0;
95 }
96
97 static int xmp_mknod(const char *path, mode_t mode, dev_t rdev)
98 {
99         int res;
100
101         /* On Linux this could just be 'mknod(path, mode, rdev)' but this
102            is more portable */
103         if (S_ISREG(mode)) {
104                 res = open(path, O_CREAT | O_EXCL | O_WRONLY, mode);
105                 if (res >= 0)
106                         res = close(res);
107         } else if (S_ISFIFO(mode))
108                 res = mkfifo(path, mode);
109         else
110                 res = mknod(path, mode, rdev);
111         if (res == -1)
112                 return -errno;
113
114         return 0;
115 }
116
117 static int xmp_mkdir(const char *path, mode_t mode)
118 {
119         int res;
120
121         res = mkdir(path, mode);
122         if (res == -1)
123                 return -errno;
124
125         return 0;
126 }
127
128 static int xmp_unlink(const char *path)
129 {
130         int res;
131
132         res = unlink(path);
133         if (res == -1)
134                 return -errno;
135
136         return 0;
137 }
138
139 static int xmp_rmdir(const char *path)
140 {
141         int res;
142
143         res = rmdir(path);
144         if (res == -1)
145                 return -errno;
146
147         return 0;
148 }
149
150 static int xmp_symlink(const char *from, const char *to)
151 {
152         int res;
153
154         res = symlink(from, to);
155         if (res == -1)
156                 return -errno;
157
158         return 0;
159 }
160
161 static int xmp_rename(const char *from, const char *to)
162 {
163         int res;
164
165         res = rename(from, to);
166         if (res == -1)
167                 return -errno;
168
169         return 0;
170 }
171
172 static int xmp_link(const char *from, const char *to)
173 {
174         int res;
175
176         res = link(from, to);
177         if (res == -1)
178                 return -errno;
179
180         return 0;
181 }
182
183 static int xmp_chmod(const char *path, mode_t mode)
184 {
185         int res;
186
187         res = chmod(path, mode);
188         if (res == -1)
189                 return -errno;
190
191         return 0;
192 }
193
194 static int xmp_chown(const char *path, uid_t uid, gid_t gid)
195 {
196         int res;
197
198         res = lchown(path, uid, gid);
199         if (res == -1)
200                 return -errno;
201
202         return 0;
203 }
204
205 static int xmp_truncate(const char *path, off_t size)
206 {
207         int res;
208
209         res = truncate(path, size);
210         if (res == -1)
211                 return -errno;
212
213         return 0;
214 }
215
216 #ifdef HAVE_UTIMENSAT
217 static int xmp_utimens(const char *path, const struct timespec ts[2])
218 {
219         int res;
220
221         /* don't use utime/utimes since they follow symlinks */
222         res = utimensat(0, path, ts, AT_SYMLINK_NOFOLLOW);
223         if (res == -1)
224                 return -errno;
225
226         return 0;
227 }
228 #endif
229
230 static int xmp_open(const char *path, struct fuse_file_info *fi)
231 {
232         int res;
233
234         res = open(path, fi->flags);
235         if (res == -1)
236                 return -errno;
237
238         close(res);
239         return 0;
240 }
241
242 static int xmp_read(const char *path, char *buf, size_t size, off_t offset,
243                     struct fuse_file_info *fi)
244 {
245         int fd;
246         int res;
247
248         (void) fi;
249         fd = open(path, O_RDONLY);
250         if (fd == -1)
251                 return -errno;
252
253         res = pread(fd, buf, size, offset);
254         if (res == -1)
255                 res = -errno;
256
257         close(fd);
258         return res;
259 }
260
261 static int xmp_write(const char *path, const char *buf, size_t size,
262                      off_t offset, struct fuse_file_info *fi)
263 {
264         int fd;
265         int res;
266
267         (void) fi;
268         fd = open(path, O_WRONLY);
269         if (fd == -1)
270                 return -errno;
271
272         res = pwrite(fd, buf, size, offset);
273         if (res == -1)
274                 res = -errno;
275
276         close(fd);
277         return res;
278 }
279
280 static int xmp_statfs(const char *path, struct statvfs *stbuf)
281 {
282         int res;
283
284         res = statvfs(path, stbuf);
285         if (res == -1)
286                 return -errno;
287
288         return 0;
289 }
290
291 static int xmp_release(const char *path, struct fuse_file_info *fi)
292 {
293         /* Just a stub.  This method is optional and can safely be left
294            unimplemented */
295
296         (void) path;
297         (void) fi;
298         return 0;
299 }
300
301 static int xmp_fsync(const char *path, int isdatasync,
302                      struct fuse_file_info *fi)
303 {
304         /* Just a stub.  This method is optional and can safely be left
305            unimplemented */
306
307         (void) path;
308         (void) isdatasync;
309         (void) fi;
310         return 0;
311 }
312
313 #ifdef HAVE_POSIX_FALLOCATE
314 static int xmp_fallocate(const char *path, int mode,
315                         off_t offset, off_t length, struct fuse_file_info *fi)
316 {
317         int fd;
318         int res;
319
320         (void) fi;
321
322         if (mode)
323                 return -EOPNOTSUPP;
324
325         fd = open(path, O_WRONLY);
326         if (fd == -1)
327                 return -errno;
328
329         res = -posix_fallocate(fd, offset, length);
330
331         close(fd);
332         return res;
333 }
334 #endif
335
336 #ifdef HAVE_SETXATTR
337 /* xattr operations are optional and can safely be left unimplemented */
338 static int xmp_setxattr(const char *path, const char *name, const char *value,
339                         size_t size, int flags)
340 {
341         int res = lsetxattr(path, name, value, size, flags);
342         if (res == -1)
343                 return -errno;
344         return 0;
345 }
346
347 static int xmp_getxattr(const char *path, const char *name, char *value,
348                         size_t size)
349 {
350         int res = lgetxattr(path, name, value, size);
351         if (res == -1)
352                 return -errno;
353         return res;
354 }
355
356 static int xmp_listxattr(const char *path, char *list, size_t size)
357 {
358         int res = llistxattr(path, list, size);
359         if (res == -1)
360                 return -errno;
361         return res;
362 }
363
364 static int xmp_removexattr(const char *path, const char *name)
365 {
366         int res = lremovexattr(path, name);
367         if (res == -1)
368                 return -errno;
369         return 0;
370 }
371 #endif /* HAVE_SETXATTR */
372
373 static struct fuse_operations xmp_oper = {
374         .getattr        = xmp_getattr,
375         .access         = xmp_access,
376         .readlink       = xmp_readlink,
377         .readdir        = xmp_readdir,
378         .mknod          = xmp_mknod,
379         .mkdir          = xmp_mkdir,
380         .symlink        = xmp_symlink,
381         .unlink         = xmp_unlink,
382         .rmdir          = xmp_rmdir,
383         .rename         = xmp_rename,
384         .link           = xmp_link,
385         .chmod          = xmp_chmod,
386         .chown          = xmp_chown,
387         .truncate       = xmp_truncate,
388 #ifdef HAVE_UTIMENSAT
389         .utimens        = xmp_utimens,
390 #endif
391         .open           = xmp_open,
392         .read           = xmp_read,
393         .write          = xmp_write,
394         .statfs         = xmp_statfs,
395         .release        = xmp_release,
396         .fsync          = xmp_fsync,
397 #ifdef HAVE_POSIX_FALLOCATE
398         .fallocate      = xmp_fallocate,
399 #endif
400 #ifdef HAVE_SETXATTR
401         .setxattr       = xmp_setxattr,
402         .getxattr       = xmp_getxattr,
403         .listxattr      = xmp_listxattr,
404         .removexattr    = xmp_removexattr,
405 #endif
406 };
407
408 int main(int argc, char *argv[])
409 {
410         umask(0);
411         return fuse_main(argc, argv, &xmp_oper, NULL);
412 }