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
18 #include <osxfuse/fuse.h>
30 #include "xattrs_config.h"
33 int xmp_getattr(const char *path, struct stat *stbuf) {
36 if (xattrs_config.show_sidecar == 0 && filename_is_sidecar(path) == 1) {
40 char *_path = prepend_source_directory(path);
41 res = lstat(_path, stbuf);
50 int xmp_access(const char *path, int mask) {
52 if (xattrs_config.show_sidecar == 0 && filename_is_sidecar(path) == 1) {
56 char *_path = prepend_source_directory(path);
57 res = access(_path, mask);
66 int xmp_readlink(const char *path, char *buf, size_t size) {
68 if (xattrs_config.show_sidecar == 0 && filename_is_sidecar(path) == 1) {
72 char *_path = prepend_source_directory(path);
73 res = readlink(_path, buf, size - 1);
83 int xmp_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
84 off_t offset, struct fuse_file_info *fi)
91 if (fi != NULL && fi->fh != 0) {
92 dp = fdopendir(fi->fh);
94 char *_path = prepend_source_directory(path);
102 while ((de = readdir(dp)) != NULL) {
103 if (xattrs_config.show_sidecar == 0 && filename_is_sidecar(de->d_name) == 1) {
108 memset(&st, 0, sizeof(st));
109 st.st_ino = de->d_ino;
110 st.st_mode = de->d_type << 12;
111 if (filler(buf, de->d_name, &st, 0))
119 int xmp_mknod(const char *path, mode_t mode, dev_t rdev) {
121 if (xattrs_config.show_sidecar == 0 && filename_is_sidecar(path) == 1) {
125 char *_path = prepend_source_directory(path);
127 /* On Linux this could just be 'mknod(path, mode, rdev)' but this
130 res = open(_path, O_CREAT | O_EXCL | O_WRONLY, mode);
133 } else if (S_ISFIFO(mode))
134 res = mkfifo(_path, mode);
136 res = mknod(_path, mode, rdev);
145 int xmp_mkdir(const char *path, mode_t mode) {
147 if (xattrs_config.show_sidecar == 0 && filename_is_sidecar(path) == 1) {
151 char *_path = prepend_source_directory(path);
152 res = mkdir(_path, mode);
161 int xmp_unlink(const char *path) {
163 if (xattrs_config.show_sidecar == 0 && filename_is_sidecar(path) == 1) {
167 char *_path = prepend_source_directory(path);
175 char *sidecar_path = get_sidecar_path(_path);
176 if (is_regular_file(sidecar_path)) {
177 if (unlink(sidecar_path) == -1) {
178 error_print("Error removing sidecar file: %s\n", sidecar_path);
187 // FIXME: remove sidecar
188 int xmp_rmdir(const char *path) {
190 if (xattrs_config.show_sidecar == 0 && filename_is_sidecar(path) == 1) {
194 char *_path = prepend_source_directory(path);
204 int xmp_symlink(const char *from, const char *to) {
206 if (xattrs_config.show_sidecar == 0) {
207 if (filename_is_sidecar(from) == 1 || filename_is_sidecar(to)) {
212 char *_to = prepend_source_directory(to);
213 res = symlink(from, _to);
222 int xmp_rename(const char *from, const char *to) {
224 if (xattrs_config.show_sidecar == 0) {
225 if (filename_is_sidecar(from) == 1 || filename_is_sidecar(to)) {
230 char *_from = prepend_source_directory(from);
231 char *_to = prepend_source_directory(to);
232 res = rename(_from, _to);
240 char *from_sidecar_path = get_sidecar_path(_from);
241 char *to_sidecar_path = get_sidecar_path(_to);
243 // FIXME: Remove to_sidecar_path if it exists ?
244 if (is_regular_file(from_sidecar_path)) {
245 if (rename(from_sidecar_path, to_sidecar_path) == -1) {
246 error_print("Error renaming sidecar. from: %s to: %s\n", from_sidecar_path, to_sidecar_path);
249 free(from_sidecar_path);
250 free(to_sidecar_path);
258 // TODO: handle sidecar file ?
259 int xmp_link(const char *from, const char *to) {
261 if (xattrs_config.show_sidecar == 0) {
262 if (filename_is_sidecar(from) == 1 || filename_is_sidecar(to)) {
267 char *_from = prepend_source_directory(from);
268 char *_to = prepend_source_directory(to);
269 res = link(_from, _to);
279 int xmp_chmod(const char *path, mode_t mode) {
281 if (xattrs_config.show_sidecar == 0 && filename_is_sidecar(path) == 1) {
285 char *_path = prepend_source_directory(path);
286 res = chmod(_path, mode);
295 int xmp_chown(const char *path, uid_t uid, gid_t gid) {
297 if (xattrs_config.show_sidecar == 0 && filename_is_sidecar(path) == 1) {
301 char *_path = prepend_source_directory(path);
302 res = lchown(_path, uid, gid);
311 int xmp_truncate(const char *path, off_t size) {
313 if (xattrs_config.show_sidecar == 0 && filename_is_sidecar(path) == 1) {
317 char *_path = prepend_source_directory(path);
318 res = truncate(_path, size);
327 #ifdef HAVE_UTIMENSAT
328 int xmp_utimens(const char *path, const struct timespec ts[2],
329 struct fuse_file_info *fi)
331 if (xattrs_config.show_sidecar == 0 && filename_is_sidecar(path) == 1) {
338 char *_path = prepend_source_directory(path);
339 /* don't use utime/utimes since they follow symlinks */
340 res = utimensat(0, _path, ts, AT_SYMLINK_NOFOLLOW);
349 int xmp_open(const char *path, struct fuse_file_info *fi) {
351 if (xattrs_config.show_sidecar == 0 && filename_is_sidecar(path) == 1) {
355 char *_path = prepend_source_directory(path);
356 fd = open(_path, fi->flags);
366 int xmp_read(const char *path, char *buf, size_t size, off_t offset,
367 struct fuse_file_info *fi)
370 if (fi == NULL || fi->fh == 0) {
374 int res = pread(fi->fh, buf, size, offset);
381 int xmp_write(const char *path, const char *buf, size_t size,
382 off_t offset, struct fuse_file_info *fi)
385 if (fi == NULL || fi->fh == 0) {
389 int res = pwrite(fi->fh, buf, size, offset);
396 int xmp_statfs(const char *path, struct statvfs *stbuf) {
398 if (xattrs_config.show_sidecar == 0 && filename_is_sidecar(path) == 1) {
402 char *_path = prepend_source_directory(path);
403 res = statvfs(_path, stbuf);
412 int xmp_release(const char *path, struct fuse_file_info *fi) {
414 return close(fi->fh);
417 int xmp_fsync(const char *path, int isdatasync,
418 struct fuse_file_info *fi) {
419 /* Just a stub. This method is optional and can safely be left
428 #ifdef HAVE_POSIX_FALLOCATE
429 int xmp_fallocate(const char *path, int mode,
430 off_t offset, off_t length, struct fuse_file_info *fi)
433 if (fi == NULL || fi->fh == 0) {
441 res = -posix_fallocate(fi->fh, offset, length);