* Fix definition of FUSE_OPT_ENT for C++. Reported by Tim
[fuse.git] / example / fusexmp_fh.c
blobb86d3f6f8a9d9a21d3bb8571ab68917e1be30abb
1 /*
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.
6 See the file COPYING.
8 gcc -Wall `pkg-config fuse --cflags --libs` -lulockmgr fusexmp_fh.c -o fusexmp_fh
9 */
11 #define FUSE_USE_VERSION 26
13 #ifdef HAVE_CONFIG_H
14 #include <config.h>
15 #endif
17 #define _GNU_SOURCE
19 #include <fuse.h>
20 #include <ulockmgr.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <fcntl.h>
26 #include <dirent.h>
27 #include <errno.h>
28 #include <sys/time.h>
29 #ifdef HAVE_SETXATTR
30 #include <sys/xattr.h>
31 #endif
33 static int xmp_getattr(const char *path, struct stat *stbuf)
35 int res;
37 res = lstat(path, stbuf);
38 if (res == -1)
39 return -errno;
41 return 0;
44 static int xmp_fgetattr(const char *path, struct stat *stbuf,
45 struct fuse_file_info *fi)
47 int res;
49 (void) path;
51 res = fstat(fi->fh, stbuf);
52 if (res == -1)
53 return -errno;
55 return 0;
58 static int xmp_access(const char *path, int mask)
60 int res;
62 res = access(path, mask);
63 if (res == -1)
64 return -errno;
66 return 0;
69 static int xmp_readlink(const char *path, char *buf, size_t size)
71 int res;
73 res = readlink(path, buf, size - 1);
74 if (res == -1)
75 return -errno;
77 buf[res] = '\0';
78 return 0;
81 struct xmp_dirp {
82 DIR *dp;
83 struct dirent *entry;
84 off_t offset;
87 static int xmp_opendir(const char *path, struct fuse_file_info *fi)
89 int res;
90 struct xmp_dirp *d = malloc(sizeof(struct xmp_dirp));
91 if (d == NULL)
92 return -ENOMEM;
94 d->dp = opendir(path);
95 if (d->dp == NULL) {
96 res = -errno;
97 free(d);
98 return res;
100 d->offset = 0;
101 d->entry = NULL;
103 fi->fh = (unsigned long) d;
104 return 0;
107 static inline struct xmp_dirp *get_dirp(struct fuse_file_info *fi)
109 return (struct xmp_dirp *) (uintptr_t) fi->fh;
112 static int xmp_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
113 off_t offset, struct fuse_file_info *fi)
115 struct xmp_dirp *d = get_dirp(fi);
117 (void) path;
118 if (offset != d->offset) {
119 seekdir(d->dp, offset);
120 d->entry = NULL;
121 d->offset = offset;
123 while (1) {
124 struct stat st;
125 off_t nextoff;
127 if (!d->entry) {
128 d->entry = readdir(d->dp);
129 if (!d->entry)
130 break;
133 memset(&st, 0, sizeof(st));
134 st.st_ino = d->entry->d_ino;
135 st.st_mode = d->entry->d_type << 12;
136 nextoff = telldir(d->dp);
137 if (filler(buf, d->entry->d_name, &st, nextoff))
138 break;
140 d->entry = NULL;
141 d->offset = nextoff;
144 return 0;
147 static int xmp_releasedir(const char *path, struct fuse_file_info *fi)
149 struct xmp_dirp *d = get_dirp(fi);
150 (void) path;
151 closedir(d->dp);
152 free(d);
153 return 0;
156 static int xmp_mknod(const char *path, mode_t mode, dev_t rdev)
158 int res;
160 if (S_ISFIFO(mode))
161 res = mkfifo(path, mode);
162 else
163 res = mknod(path, mode, rdev);
164 if (res == -1)
165 return -errno;
167 return 0;
170 static int xmp_mkdir(const char *path, mode_t mode)
172 int res;
174 res = mkdir(path, mode);
175 if (res == -1)
176 return -errno;
178 return 0;
181 static int xmp_unlink(const char *path)
183 int res;
185 res = unlink(path);
186 if (res == -1)
187 return -errno;
189 return 0;
192 static int xmp_rmdir(const char *path)
194 int res;
196 res = rmdir(path);
197 if (res == -1)
198 return -errno;
200 return 0;
203 static int xmp_symlink(const char *from, const char *to)
205 int res;
207 res = symlink(from, to);
208 if (res == -1)
209 return -errno;
211 return 0;
214 static int xmp_rename(const char *from, const char *to)
216 int res;
218 res = rename(from, to);
219 if (res == -1)
220 return -errno;
222 return 0;
225 static int xmp_link(const char *from, const char *to)
227 int res;
229 res = link(from, to);
230 if (res == -1)
231 return -errno;
233 return 0;
236 static int xmp_chmod(const char *path, mode_t mode)
238 int res;
240 res = chmod(path, mode);
241 if (res == -1)
242 return -errno;
244 return 0;
247 static int xmp_chown(const char *path, uid_t uid, gid_t gid)
249 int res;
251 res = lchown(path, uid, gid);
252 if (res == -1)
253 return -errno;
255 return 0;
258 static int xmp_truncate(const char *path, off_t size)
260 int res;
262 res = truncate(path, size);
263 if (res == -1)
264 return -errno;
266 return 0;
269 static int xmp_ftruncate(const char *path, off_t size,
270 struct fuse_file_info *fi)
272 int res;
274 (void) path;
276 res = ftruncate(fi->fh, size);
277 if (res == -1)
278 return -errno;
280 return 0;
283 static int xmp_utimens(const char *path, const struct timespec ts[2])
285 int res;
286 struct timeval tv[2];
288 tv[0].tv_sec = ts[0].tv_sec;
289 tv[0].tv_usec = ts[0].tv_nsec / 1000;
290 tv[1].tv_sec = ts[1].tv_sec;
291 tv[1].tv_usec = ts[1].tv_nsec / 1000;
293 res = utimes(path, tv);
294 if (res == -1)
295 return -errno;
297 return 0;
300 static int xmp_create(const char *path, mode_t mode, struct fuse_file_info *fi)
302 int fd;
304 fd = open(path, fi->flags, mode);
305 if (fd == -1)
306 return -errno;
308 fi->fh = fd;
309 return 0;
312 static int xmp_open(const char *path, struct fuse_file_info *fi)
314 int fd;
316 fd = open(path, fi->flags);
317 if (fd == -1)
318 return -errno;
320 fi->fh = fd;
321 return 0;
324 static int xmp_read(const char *path, char *buf, size_t size, off_t offset,
325 struct fuse_file_info *fi)
327 int res;
329 (void) path;
330 res = pread(fi->fh, buf, size, offset);
331 if (res == -1)
332 res = -errno;
334 return res;
337 static int xmp_write(const char *path, const char *buf, size_t size,
338 off_t offset, struct fuse_file_info *fi)
340 int res;
342 (void) path;
343 res = pwrite(fi->fh, buf, size, offset);
344 if (res == -1)
345 res = -errno;
347 return res;
350 static int xmp_statfs(const char *path, struct statvfs *stbuf)
352 int res;
354 res = statvfs(path, stbuf);
355 if (res == -1)
356 return -errno;
358 return 0;
361 static int xmp_flush(const char *path, struct fuse_file_info *fi)
363 int res;
365 (void) path;
366 /* This is called from every close on an open file, so call the
367 close on the underlying filesystem. But since flush may be
368 called multiple times for an open file, this must not really
369 close the file. This is important if used on a network
370 filesystem like NFS which flush the data/metadata on close() */
371 res = close(dup(fi->fh));
372 if (res == -1)
373 return -errno;
375 return 0;
378 static int xmp_release(const char *path, struct fuse_file_info *fi)
380 (void) path;
381 close(fi->fh);
383 return 0;
386 static int xmp_fsync(const char *path, int isdatasync,
387 struct fuse_file_info *fi)
389 int res;
390 (void) path;
392 #ifndef HAVE_FDATASYNC
393 (void) isdatasync;
394 #else
395 if (isdatasync)
396 res = fdatasync(fi->fh);
397 else
398 #endif
399 res = fsync(fi->fh);
400 if (res == -1)
401 return -errno;
403 return 0;
406 #ifdef HAVE_SETXATTR
407 /* xattr operations are optional and can safely be left unimplemented */
408 static int xmp_setxattr(const char *path, const char *name, const char *value,
409 size_t size, int flags)
411 int res = lsetxattr(path, name, value, size, flags);
412 if (res == -1)
413 return -errno;
414 return 0;
417 static int xmp_getxattr(const char *path, const char *name, char *value,
418 size_t size)
420 int res = lgetxattr(path, name, value, size);
421 if (res == -1)
422 return -errno;
423 return res;
426 static int xmp_listxattr(const char *path, char *list, size_t size)
428 int res = llistxattr(path, list, size);
429 if (res == -1)
430 return -errno;
431 return res;
434 static int xmp_removexattr(const char *path, const char *name)
436 int res = lremovexattr(path, name);
437 if (res == -1)
438 return -errno;
439 return 0;
441 #endif /* HAVE_SETXATTR */
443 static int xmp_lock(const char *path, struct fuse_file_info *fi, int cmd,
444 struct flock *lock)
446 (void) path;
448 return ulockmgr_op(fi->fh, cmd, lock, &fi->lock_owner,
449 sizeof(fi->lock_owner));
452 static struct fuse_operations xmp_oper = {
453 .getattr = xmp_getattr,
454 .fgetattr = xmp_fgetattr,
455 .access = xmp_access,
456 .readlink = xmp_readlink,
457 .opendir = xmp_opendir,
458 .readdir = xmp_readdir,
459 .releasedir = xmp_releasedir,
460 .mknod = xmp_mknod,
461 .mkdir = xmp_mkdir,
462 .symlink = xmp_symlink,
463 .unlink = xmp_unlink,
464 .rmdir = xmp_rmdir,
465 .rename = xmp_rename,
466 .link = xmp_link,
467 .chmod = xmp_chmod,
468 .chown = xmp_chown,
469 .truncate = xmp_truncate,
470 .ftruncate = xmp_ftruncate,
471 .utimens = xmp_utimens,
472 .create = xmp_create,
473 .open = xmp_open,
474 .read = xmp_read,
475 .write = xmp_write,
476 .statfs = xmp_statfs,
477 .flush = xmp_flush,
478 .release = xmp_release,
479 .fsync = xmp_fsync,
480 #ifdef HAVE_SETXATTR
481 .setxattr = xmp_setxattr,
482 .getxattr = xmp_getxattr,
483 .listxattr = xmp_listxattr,
484 .removexattr = xmp_removexattr,
485 #endif
486 .lock = xmp_lock,
488 .flag_nullpath_ok = 1,
491 int main(int argc, char *argv[])
493 umask(0);
494 return fuse_main(argc, argv, &xmp_oper, NULL);