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.
9 gcc -Wall `pkg-config fuse --cflags --libs` -lulockmgr fusexmp_fh.c -o fusexmp_fh
12 #define FUSE_USE_VERSION 26
32 #include <sys/xattr.h>
34 #include <sys/file.h> /* flock(2) */
36 static int xmp_getattr(const char *path
, struct stat
*stbuf
)
40 res
= lstat(path
, stbuf
);
47 static int xmp_fgetattr(const char *path
, struct stat
*stbuf
,
48 struct fuse_file_info
*fi
)
54 res
= fstat(fi
->fh
, stbuf
);
61 static int xmp_access(const char *path
, int mask
)
65 res
= access(path
, mask
);
72 static int xmp_readlink(const char *path
, char *buf
, size_t size
)
76 res
= readlink(path
, buf
, size
- 1);
90 static int xmp_opendir(const char *path
, struct fuse_file_info
*fi
)
93 struct xmp_dirp
*d
= malloc(sizeof(struct xmp_dirp
));
97 d
->dp
= opendir(path
);
106 fi
->fh
= (unsigned long) d
;
110 static inline struct xmp_dirp
*get_dirp(struct fuse_file_info
*fi
)
112 return (struct xmp_dirp
*) (uintptr_t) fi
->fh
;
115 static int xmp_readdir(const char *path
, void *buf
, fuse_fill_dir_t filler
,
116 off_t offset
, struct fuse_file_info
*fi
)
118 struct xmp_dirp
*d
= get_dirp(fi
);
121 if (offset
!= d
->offset
) {
122 seekdir(d
->dp
, offset
);
131 d
->entry
= readdir(d
->dp
);
136 memset(&st
, 0, sizeof(st
));
137 st
.st_ino
= d
->entry
->d_ino
;
138 st
.st_mode
= d
->entry
->d_type
<< 12;
139 nextoff
= telldir(d
->dp
);
140 if (filler(buf
, d
->entry
->d_name
, &st
, nextoff
))
150 static int xmp_releasedir(const char *path
, struct fuse_file_info
*fi
)
152 struct xmp_dirp
*d
= get_dirp(fi
);
159 static int xmp_mknod(const char *path
, mode_t mode
, dev_t rdev
)
164 res
= mkfifo(path
, mode
);
166 res
= mknod(path
, mode
, rdev
);
173 static int xmp_mkdir(const char *path
, mode_t mode
)
177 res
= mkdir(path
, mode
);
184 static int xmp_unlink(const char *path
)
195 static int xmp_rmdir(const char *path
)
206 static int xmp_symlink(const char *from
, const char *to
)
210 res
= symlink(from
, to
);
217 static int xmp_rename(const char *from
, const char *to
)
221 res
= rename(from
, to
);
228 static int xmp_link(const char *from
, const char *to
)
232 res
= link(from
, to
);
239 static int xmp_chmod(const char *path
, mode_t mode
)
243 res
= chmod(path
, mode
);
250 static int xmp_chown(const char *path
, uid_t uid
, gid_t gid
)
254 res
= lchown(path
, uid
, gid
);
261 static int xmp_truncate(const char *path
, off_t size
)
265 res
= truncate(path
, size
);
272 static int xmp_ftruncate(const char *path
, off_t size
,
273 struct fuse_file_info
*fi
)
279 res
= ftruncate(fi
->fh
, size
);
286 static int xmp_utimens(const char *path
, const struct timespec ts
[2])
290 res
= utimensat(0, path
, ts
, AT_SYMLINK_NOFOLLOW
);
297 static int xmp_create(const char *path
, mode_t mode
, struct fuse_file_info
*fi
)
301 fd
= open(path
, fi
->flags
, mode
);
309 static int xmp_open(const char *path
, struct fuse_file_info
*fi
)
313 fd
= open(path
, fi
->flags
);
321 static int xmp_read(const char *path
, char *buf
, size_t size
, off_t offset
,
322 struct fuse_file_info
*fi
)
327 res
= pread(fi
->fh
, buf
, size
, offset
);
334 static int xmp_read_buf(const char *path
, struct fuse_bufvec
**bufp
,
335 size_t size
, off_t offset
, struct fuse_file_info
*fi
)
337 struct fuse_bufvec
*src
;
341 src
= malloc(sizeof(struct fuse_bufvec
));
345 *src
= FUSE_BUFVEC_INIT(size
);
347 src
->buf
[0].flags
= FUSE_BUF_IS_FD
| FUSE_BUF_FD_SEEK
;
348 src
->buf
[0].fd
= fi
->fh
;
349 src
->buf
[0].pos
= offset
;
356 static int xmp_write(const char *path
, const char *buf
, size_t size
,
357 off_t offset
, struct fuse_file_info
*fi
)
362 res
= pwrite(fi
->fh
, buf
, size
, offset
);
369 static int xmp_write_buf(const char *path
, struct fuse_bufvec
*buf
,
370 off_t offset
, struct fuse_file_info
*fi
)
372 struct fuse_bufvec dst
= FUSE_BUFVEC_INIT(fuse_buf_size(buf
));
376 dst
.buf
[0].flags
= FUSE_BUF_IS_FD
| FUSE_BUF_FD_SEEK
;
377 dst
.buf
[0].fd
= fi
->fh
;
378 dst
.buf
[0].pos
= offset
;
380 return fuse_buf_copy(&dst
, buf
, FUSE_BUF_SPLICE_NONBLOCK
);
383 static int xmp_statfs(const char *path
, struct statvfs
*stbuf
)
387 res
= statvfs(path
, stbuf
);
394 static int xmp_flush(const char *path
, struct fuse_file_info
*fi
)
399 /* This is called from every close on an open file, so call the
400 close on the underlying filesystem. But since flush may be
401 called multiple times for an open file, this must not really
402 close the file. This is important if used on a network
403 filesystem like NFS which flush the data/metadata on close() */
404 res
= close(dup(fi
->fh
));
411 static int xmp_release(const char *path
, struct fuse_file_info
*fi
)
419 static int xmp_fsync(const char *path
, int isdatasync
,
420 struct fuse_file_info
*fi
)
425 #ifndef HAVE_FDATASYNC
429 res
= fdatasync(fi
->fh
);
440 /* xattr operations are optional and can safely be left unimplemented */
441 static int xmp_setxattr(const char *path
, const char *name
, const char *value
,
442 size_t size
, int flags
)
444 int res
= lsetxattr(path
, name
, value
, size
, flags
);
450 static int xmp_getxattr(const char *path
, const char *name
, char *value
,
453 int res
= lgetxattr(path
, name
, value
, size
);
459 static int xmp_listxattr(const char *path
, char *list
, size_t size
)
461 int res
= llistxattr(path
, list
, size
);
467 static int xmp_removexattr(const char *path
, const char *name
)
469 int res
= lremovexattr(path
, name
);
474 #endif /* HAVE_SETXATTR */
476 static int xmp_lock(const char *path
, struct fuse_file_info
*fi
, int cmd
,
481 return ulockmgr_op(fi
->fh
, cmd
, lock
, &fi
->lock_owner
,
482 sizeof(fi
->lock_owner
));
485 static int xmp_flock(const char *path
, struct fuse_file_info
*fi
, int op
)
490 res
= flock(fi
->fh
, op
);
497 static struct fuse_operations xmp_oper
= {
498 .getattr
= xmp_getattr
,
499 .fgetattr
= xmp_fgetattr
,
500 .access
= xmp_access
,
501 .readlink
= xmp_readlink
,
502 .opendir
= xmp_opendir
,
503 .readdir
= xmp_readdir
,
504 .releasedir
= xmp_releasedir
,
507 .symlink
= xmp_symlink
,
508 .unlink
= xmp_unlink
,
510 .rename
= xmp_rename
,
514 .truncate
= xmp_truncate
,
515 .ftruncate
= xmp_ftruncate
,
516 .utimens
= xmp_utimens
,
517 .create
= xmp_create
,
520 .read_buf
= xmp_read_buf
,
522 .write_buf
= xmp_write_buf
,
523 .statfs
= xmp_statfs
,
525 .release
= xmp_release
,
528 .setxattr
= xmp_setxattr
,
529 .getxattr
= xmp_getxattr
,
530 .listxattr
= xmp_listxattr
,
531 .removexattr
= xmp_removexattr
,
536 .flag_nullpath_ok
= 1,
539 int main(int argc
, char *argv
[])
542 return fuse_main(argc
, argv
, &xmp_oper
, NULL
);