2 fuse_xattrs - Add xattrs support using sidecar files
4 Copyright (C) 2016-2017 Felipe Barriga Richards <felipe {at} felipebarriga.cl>
6 Based on passthrough.c (libfuse example)
8 This program can be distributed under the terms of the GNU GPL.
12 #define FUSE_USE_VERSION 30
14 /* For pread()/pwrite()/utimensat() */
15 #define _XOPEN_SOURCE 700
25 #include "xattrs_config.h"
28 int xmp_getattr(const char *path, struct stat *stbuf) {
31 if (xattrs_config.show_sidecar == 0 && filename_is_sidecar(path) == 1) {
35 char *_path = prepend_source_directory(path);
36 res = lstat(_path, stbuf);
45 int xmp_access(const char *path, int mask) {
47 if (xattrs_config.show_sidecar == 0 && filename_is_sidecar(path) == 1) {
51 char *_path = prepend_source_directory(path);
52 res = access(_path, mask);
61 int xmp_readlink(const char *path, char *buf, size_t size) {
63 if (xattrs_config.show_sidecar == 0 && filename_is_sidecar(path) == 1) {
67 char *_path = prepend_source_directory(path);
68 res = readlink(_path, buf, size - 1);
78 int xmp_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
79 off_t offset, struct fuse_file_info *fi)
87 char *_path = prepend_source_directory(path);
94 while ((de = readdir(dp)) != NULL) {
95 if (xattrs_config.show_sidecar == 0 && filename_is_sidecar(de->d_name) == 1) {
100 memset(&st, 0, sizeof(st));
101 st.st_ino = de->d_ino;
102 st.st_mode = de->d_type << 12;
103 if (filler(buf, de->d_name, &st, 0))
111 int xmp_mknod(const char *path, mode_t mode, dev_t rdev) {
113 if (xattrs_config.show_sidecar == 0 && filename_is_sidecar(path) == 1) {
117 char *_path = prepend_source_directory(path);
119 /* On Linux this could just be 'mknod(path, mode, rdev)' but this
122 res = open(_path, O_CREAT | O_EXCL | O_WRONLY, mode);
125 } else if (S_ISFIFO(mode))
126 res = mkfifo(_path, mode);
128 res = mknod(_path, mode, rdev);
137 int xmp_mkdir(const char *path, mode_t mode) {
139 if (xattrs_config.show_sidecar == 0 && filename_is_sidecar(path) == 1) {
143 char *_path = prepend_source_directory(path);
144 res = mkdir(_path, mode);
153 int xmp_unlink(const char *path) {
155 if (xattrs_config.show_sidecar == 0 && filename_is_sidecar(path) == 1) {
159 char *_path = prepend_source_directory(path);
169 int xmp_rmdir(const char *path) {
171 if (xattrs_config.show_sidecar == 0 && filename_is_sidecar(path) == 1) {
175 char *_path = prepend_source_directory(path);
185 int xmp_symlink(const char *from, const char *to) {
187 if (xattrs_config.show_sidecar == 0) {
188 if (filename_is_sidecar(from) == 1 || filename_is_sidecar(to)) {
193 char *_to = prepend_source_directory(to);
194 res = symlink(from, _to);
203 int xmp_rename(const char *from, const char *to) {
205 if (xattrs_config.show_sidecar == 0) {
206 if (filename_is_sidecar(from) == 1 || filename_is_sidecar(to)) {
211 char *_from = prepend_source_directory(from);
212 char *_to = prepend_source_directory(to);
213 res = rename(_from, _to);
223 int xmp_link(const char *from, const char *to) {
225 if (xattrs_config.show_sidecar == 0) {
226 if (filename_is_sidecar(from) == 1 || filename_is_sidecar(to)) {
231 char *_from = prepend_source_directory(from);
232 char *_to = prepend_source_directory(to);
233 res = link(_from, _to);
243 int xmp_chmod(const char *path, mode_t mode) {
245 if (xattrs_config.show_sidecar == 0 && filename_is_sidecar(path) == 1) {
249 char *_path = prepend_source_directory(path);
250 res = chmod(_path, mode);
259 int xmp_chown(const char *path, uid_t uid, gid_t gid) {
261 if (xattrs_config.show_sidecar == 0 && filename_is_sidecar(path) == 1) {
265 char *_path = prepend_source_directory(path);
266 res = lchown(_path, uid, gid);
275 int xmp_truncate(const char *path, off_t size) {
277 if (xattrs_config.show_sidecar == 0 && filename_is_sidecar(path) == 1) {
281 char *_path = prepend_source_directory(path);
282 res = truncate(_path, size);
291 #ifdef HAVE_UTIMENSAT
292 int xmp_utimens(const char *path, const struct timespec ts[2],
293 struct fuse_file_info *fi)
295 if (xattrs_config.show_sidecar == 0 && filename_is_sidecar(path) == 1) {
302 char *_path = prepend_source_directory(path);
303 /* don't use utime/utimes since they follow symlinks */
304 res = utimensat(0, _path, ts, AT_SYMLINK_NOFOLLOW);
313 int xmp_open(const char *path, struct fuse_file_info *fi) {
315 if (xattrs_config.show_sidecar == 0 && filename_is_sidecar(path) == 1) {
319 char *_path = prepend_source_directory(path);
320 res = open(_path, fi->flags);
330 int xmp_read(const char *path, char *buf, size_t size, off_t offset,
331 struct fuse_file_info *fi)
333 if (xattrs_config.show_sidecar == 0 && filename_is_sidecar(path) == 1) {
341 char *_path = prepend_source_directory(path);
342 fd = open(_path, O_RDONLY);
348 res = pread(fd, buf, size, offset);
356 int xmp_write(const char *path, const char *buf, size_t size,
357 off_t offset, struct fuse_file_info *fi)
359 if (xattrs_config.show_sidecar == 0 && filename_is_sidecar(path) == 1) {
367 char *_path = prepend_source_directory(path);
368 fd = open(_path, O_WRONLY);
374 res = pwrite(fd, buf, size, offset);
382 int xmp_statfs(const char *path, struct statvfs *stbuf) {
384 if (xattrs_config.show_sidecar == 0 && filename_is_sidecar(path) == 1) {
388 char *_path = prepend_source_directory(path);
389 res = statvfs(_path, stbuf);
398 int xmp_release(const char *path, struct fuse_file_info *fi) {
399 /* Just a stub. This method is optional and can safely be left
407 int xmp_fsync(const char *path, int isdatasync,
408 struct fuse_file_info *fi) {
409 /* Just a stub. This method is optional and can safely be left
418 #ifdef HAVE_POSIX_FALLOCATE
419 int xmp_fallocate(const char *path, int mode,
420 off_t offset, off_t length, struct fuse_file_info *fi)
422 if (xattrs_config.show_sidecar == 0 && filename_is_sidecar(path) == 1) {
434 char *_path = prepend_source_directory(path);
435 fd = open(_path, O_WRONLY);
441 res = -posix_fallocate(fd, offset, length);