libfuse: clean up struct fuse_file_info
[fuse.git] / example / fusexmp_fh.c
blobe538b49bb3355a670d3901cd619261474778fc2f
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>
6 This program can be distributed under the terms of the GNU GPL.
7 See the file COPYING.
8 */
10 /** @file
11 * @tableofcontents
13 * fusexmp_fh.c - FUSE: Filesystem in Userspace
15 * \section section_compile compiling this example
17 * gcc -Wall fusexmp_fh.c `pkg-config fuse --cflags --libs` -lulockmgr -o fusexmp_fh
19 * \section section_source the complete source
20 * \include fusexmp_fh.c
23 #define FUSE_USE_VERSION 30
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
29 #define _GNU_SOURCE
31 #include <fuse.h>
32 #include <ulockmgr.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <unistd.h>
37 #include <fcntl.h>
38 #include <sys/stat.h>
39 #include <dirent.h>
40 #include <errno.h>
41 #include <sys/time.h>
42 #ifdef HAVE_SETXATTR
43 #include <sys/xattr.h>
44 #endif
45 #include <sys/file.h> /* flock(2) */
47 static int xmp_getattr(const char *path, struct stat *stbuf)
49 int res;
51 res = lstat(path, stbuf);
52 if (res == -1)
53 return -errno;
55 return 0;
58 static int xmp_fgetattr(const char *path, struct stat *stbuf,
59 struct fuse_file_info *fi)
61 int res;
63 (void) path;
65 res = fstat(fi->fh, stbuf);
66 if (res == -1)
67 return -errno;
69 return 0;
72 static int xmp_access(const char *path, int mask)
74 int res;
76 res = access(path, mask);
77 if (res == -1)
78 return -errno;
80 return 0;
83 static int xmp_readlink(const char *path, char *buf, size_t size)
85 int res;
87 res = readlink(path, buf, size - 1);
88 if (res == -1)
89 return -errno;
91 buf[res] = '\0';
92 return 0;
95 struct xmp_dirp {
96 DIR *dp;
97 struct dirent *entry;
98 off_t offset;
101 static int xmp_opendir(const char *path, struct fuse_file_info *fi)
103 int res;
104 struct xmp_dirp *d = malloc(sizeof(struct xmp_dirp));
105 if (d == NULL)
106 return -ENOMEM;
108 d->dp = opendir(path);
109 if (d->dp == NULL) {
110 res = -errno;
111 free(d);
112 return res;
114 d->offset = 0;
115 d->entry = NULL;
117 fi->fh = (unsigned long) d;
118 return 0;
121 static inline struct xmp_dirp *get_dirp(struct fuse_file_info *fi)
123 return (struct xmp_dirp *) (uintptr_t) fi->fh;
126 static int xmp_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
127 off_t offset, struct fuse_file_info *fi)
129 struct xmp_dirp *d = get_dirp(fi);
131 (void) path;
132 if (offset != d->offset) {
133 seekdir(d->dp, offset);
134 d->entry = NULL;
135 d->offset = offset;
137 while (1) {
138 struct stat st;
139 off_t nextoff;
141 if (!d->entry) {
142 d->entry = readdir(d->dp);
143 if (!d->entry)
144 break;
147 memset(&st, 0, sizeof(st));
148 st.st_ino = d->entry->d_ino;
149 st.st_mode = d->entry->d_type << 12;
150 nextoff = telldir(d->dp);
151 if (filler(buf, d->entry->d_name, &st, nextoff))
152 break;
154 d->entry = NULL;
155 d->offset = nextoff;
158 return 0;
161 static int xmp_releasedir(const char *path, struct fuse_file_info *fi)
163 struct xmp_dirp *d = get_dirp(fi);
164 (void) path;
165 closedir(d->dp);
166 free(d);
167 return 0;
170 static int xmp_mknod(const char *path, mode_t mode, dev_t rdev)
172 int res;
174 if (S_ISFIFO(mode))
175 res = mkfifo(path, mode);
176 else
177 res = mknod(path, mode, rdev);
178 if (res == -1)
179 return -errno;
181 return 0;
184 static int xmp_mkdir(const char *path, mode_t mode)
186 int res;
188 res = mkdir(path, mode);
189 if (res == -1)
190 return -errno;
192 return 0;
195 static int xmp_unlink(const char *path)
197 int res;
199 res = unlink(path);
200 if (res == -1)
201 return -errno;
203 return 0;
206 static int xmp_rmdir(const char *path)
208 int res;
210 res = rmdir(path);
211 if (res == -1)
212 return -errno;
214 return 0;
217 static int xmp_symlink(const char *from, const char *to)
219 int res;
221 res = symlink(from, to);
222 if (res == -1)
223 return -errno;
225 return 0;
228 static int xmp_rename(const char *from, const char *to)
230 int res;
232 res = rename(from, to);
233 if (res == -1)
234 return -errno;
236 return 0;
239 static int xmp_link(const char *from, const char *to)
241 int res;
243 res = link(from, to);
244 if (res == -1)
245 return -errno;
247 return 0;
250 static int xmp_chmod(const char *path, mode_t mode)
252 int res;
254 res = chmod(path, mode);
255 if (res == -1)
256 return -errno;
258 return 0;
261 static int xmp_chown(const char *path, uid_t uid, gid_t gid)
263 int res;
265 res = lchown(path, uid, gid);
266 if (res == -1)
267 return -errno;
269 return 0;
272 static int xmp_truncate(const char *path, off_t size)
274 int res;
276 res = truncate(path, size);
277 if (res == -1)
278 return -errno;
280 return 0;
283 static int xmp_ftruncate(const char *path, off_t size,
284 struct fuse_file_info *fi)
286 int res;
288 (void) path;
290 res = ftruncate(fi->fh, size);
291 if (res == -1)
292 return -errno;
294 return 0;
297 #ifdef HAVE_UTIMENSAT
298 static int xmp_utimens(const char *path, const struct timespec ts[2])
300 int res;
302 /* don't use utime/utimes since they follow symlinks */
303 res = utimensat(0, path, ts, AT_SYMLINK_NOFOLLOW);
304 if (res == -1)
305 return -errno;
307 return 0;
309 #endif
311 static int xmp_create(const char *path, mode_t mode, struct fuse_file_info *fi)
313 int fd;
315 fd = open(path, fi->flags, mode);
316 if (fd == -1)
317 return -errno;
319 fi->fh = fd;
320 return 0;
323 static int xmp_open(const char *path, struct fuse_file_info *fi)
325 int fd;
327 fd = open(path, fi->flags);
328 if (fd == -1)
329 return -errno;
331 fi->fh = fd;
332 return 0;
335 static int xmp_read(const char *path, char *buf, size_t size, off_t offset,
336 struct fuse_file_info *fi)
338 int res;
340 (void) path;
341 res = pread(fi->fh, buf, size, offset);
342 if (res == -1)
343 res = -errno;
345 return res;
348 static int xmp_read_buf(const char *path, struct fuse_bufvec **bufp,
349 size_t size, off_t offset, struct fuse_file_info *fi)
351 struct fuse_bufvec *src;
353 (void) path;
355 src = malloc(sizeof(struct fuse_bufvec));
356 if (src == NULL)
357 return -ENOMEM;
359 *src = FUSE_BUFVEC_INIT(size);
361 src->buf[0].flags = FUSE_BUF_IS_FD | FUSE_BUF_FD_SEEK;
362 src->buf[0].fd = fi->fh;
363 src->buf[0].pos = offset;
365 *bufp = src;
367 return 0;
370 static int xmp_write(const char *path, const char *buf, size_t size,
371 off_t offset, struct fuse_file_info *fi)
373 int res;
375 (void) path;
376 res = pwrite(fi->fh, buf, size, offset);
377 if (res == -1)
378 res = -errno;
380 return res;
383 static int xmp_write_buf(const char *path, struct fuse_bufvec *buf,
384 off_t offset, struct fuse_file_info *fi)
386 struct fuse_bufvec dst = FUSE_BUFVEC_INIT(fuse_buf_size(buf));
388 (void) path;
390 dst.buf[0].flags = FUSE_BUF_IS_FD | FUSE_BUF_FD_SEEK;
391 dst.buf[0].fd = fi->fh;
392 dst.buf[0].pos = offset;
394 return fuse_buf_copy(&dst, buf, FUSE_BUF_SPLICE_NONBLOCK);
397 static int xmp_statfs(const char *path, struct statvfs *stbuf)
399 int res;
401 res = statvfs(path, stbuf);
402 if (res == -1)
403 return -errno;
405 return 0;
408 static int xmp_flush(const char *path, struct fuse_file_info *fi)
410 int res;
412 (void) path;
413 /* This is called from every close on an open file, so call the
414 close on the underlying filesystem. But since flush may be
415 called multiple times for an open file, this must not really
416 close the file. This is important if used on a network
417 filesystem like NFS which flush the data/metadata on close() */
418 res = close(dup(fi->fh));
419 if (res == -1)
420 return -errno;
422 return 0;
425 static int xmp_release(const char *path, struct fuse_file_info *fi)
427 (void) path;
428 close(fi->fh);
430 return 0;
433 static int xmp_fsync(const char *path, int isdatasync,
434 struct fuse_file_info *fi)
436 int res;
437 (void) path;
439 #ifndef HAVE_FDATASYNC
440 (void) isdatasync;
441 #else
442 if (isdatasync)
443 res = fdatasync(fi->fh);
444 else
445 #endif
446 res = fsync(fi->fh);
447 if (res == -1)
448 return -errno;
450 return 0;
453 #ifdef HAVE_POSIX_FALLOCATE
454 static int xmp_fallocate(const char *path, int mode,
455 off_t offset, off_t length, struct fuse_file_info *fi)
457 (void) path;
459 if (mode)
460 return -EOPNOTSUPP;
462 return -posix_fallocate(fi->fh, offset, length);
464 #endif
466 #ifdef HAVE_SETXATTR
467 /* xattr operations are optional and can safely be left unimplemented */
468 static int xmp_setxattr(const char *path, const char *name, const char *value,
469 size_t size, int flags)
471 int res = lsetxattr(path, name, value, size, flags);
472 if (res == -1)
473 return -errno;
474 return 0;
477 static int xmp_getxattr(const char *path, const char *name, char *value,
478 size_t size)
480 int res = lgetxattr(path, name, value, size);
481 if (res == -1)
482 return -errno;
483 return res;
486 static int xmp_listxattr(const char *path, char *list, size_t size)
488 int res = llistxattr(path, list, size);
489 if (res == -1)
490 return -errno;
491 return res;
494 static int xmp_removexattr(const char *path, const char *name)
496 int res = lremovexattr(path, name);
497 if (res == -1)
498 return -errno;
499 return 0;
501 #endif /* HAVE_SETXATTR */
503 static int xmp_lock(const char *path, struct fuse_file_info *fi, int cmd,
504 struct flock *lock)
506 (void) path;
508 return ulockmgr_op(fi->fh, cmd, lock, &fi->lock_owner,
509 sizeof(fi->lock_owner));
512 static int xmp_flock(const char *path, struct fuse_file_info *fi, int op)
514 int res;
515 (void) path;
517 res = flock(fi->fh, op);
518 if (res == -1)
519 return -errno;
521 return 0;
524 static struct fuse_operations xmp_oper = {
525 .getattr = xmp_getattr,
526 .fgetattr = xmp_fgetattr,
527 .access = xmp_access,
528 .readlink = xmp_readlink,
529 .opendir = xmp_opendir,
530 .readdir = xmp_readdir,
531 .releasedir = xmp_releasedir,
532 .mknod = xmp_mknod,
533 .mkdir = xmp_mkdir,
534 .symlink = xmp_symlink,
535 .unlink = xmp_unlink,
536 .rmdir = xmp_rmdir,
537 .rename = xmp_rename,
538 .link = xmp_link,
539 .chmod = xmp_chmod,
540 .chown = xmp_chown,
541 .truncate = xmp_truncate,
542 .ftruncate = xmp_ftruncate,
543 #ifdef HAVE_UTIMENSAT
544 .utimens = xmp_utimens,
545 #endif
546 .create = xmp_create,
547 .open = xmp_open,
548 .read = xmp_read,
549 .read_buf = xmp_read_buf,
550 .write = xmp_write,
551 .write_buf = xmp_write_buf,
552 .statfs = xmp_statfs,
553 .flush = xmp_flush,
554 .release = xmp_release,
555 .fsync = xmp_fsync,
556 #ifdef HAVE_POSIX_FALLOCATE
557 .fallocate = xmp_fallocate,
558 #endif
559 #ifdef HAVE_SETXATTR
560 .setxattr = xmp_setxattr,
561 .getxattr = xmp_getxattr,
562 .listxattr = xmp_listxattr,
563 .removexattr = xmp_removexattr,
564 #endif
565 .lock = xmp_lock,
566 .flock = xmp_flock,
569 int main(int argc, char *argv[])
571 umask(0);
572 return fuse_main(argc, argv, &xmp_oper, NULL);