2 fuse_xattrs - Add xattrs support using sidecar files
4 Copyright (C) 2016 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
22 #include <sys/xattr.h>
25 #include "passthrough.h"
27 #include "binary_storage.h"
30 static int xmp_setxattr(const char *path, const char *name, const char *value, size_t size, int flags)
32 if (get_namespace(name) != USER) {
33 debug_print("Only user namespace is supported. name=%s\n", name);
36 if (strlen(name) > XATTR_NAME_MAX) {
37 debug_print("attribute name must be equal or smaller than %d bytes\n", XATTR_NAME_MAX);
40 if (size > XATTR_SIZE_MAX) {
41 debug_print("attribute value cannot be bigger than %d bytes\n", XATTR_SIZE_MAX);
46 char *sanitized_value = sanitize_value(value, size);
47 debug_print("path=%s name=%s value=%s size=%zu XATTR_CREATE=%d XATTR_REPLACE=%d\n",
48 path, name, sanitized_value, size, flags & XATTR_CREATE, flags & XATTR_REPLACE);
50 free(sanitized_value);
52 return binary_storage_write_key(path, name, value, size, flags);
55 static int xmp_getxattr(const char *path, const char *name, char *value, size_t size)
57 if (get_namespace(name) != USER) {
58 debug_print("Only user namespace is supported. name=%s\n", name);
61 if (strlen(name) > XATTR_NAME_MAX) {
62 debug_print("attribute name must be equal or smaller than %d bytes\n", XATTR_NAME_MAX);
66 debug_print("path=%s name=%s size=%zu\n", path, name, size);
67 return binary_storage_read_key(path, name, value, size);
70 static int xmp_listxattr(const char *path, char *list, size_t size)
72 if (size > XATTR_LIST_MAX) {
73 debug_print("The size of the list of attribute names for this file exceeds the system-imposed limit.\n");
77 debug_print("path=%s size=%zu\n", path, size);
78 return binary_storage_list_keys(path, list, size);
81 static int xmp_removexattr(const char *path, const char *name)
83 if (get_namespace(name) != USER) {
84 debug_print("Only user namespace is supported. name=%s\n", name);
87 if (strlen(name) > XATTR_NAME_MAX) {
88 debug_print("attribute name must be equal or smaller than %d bytes\n", XATTR_NAME_MAX);
92 debug_print("path=%s name=%s\n", path, name);
93 return binary_storage_remove_key(path, name);
96 static struct fuse_operations xmp_oper = {
97 .getattr = xmp_getattr,
99 .readlink = xmp_readlink,
100 .readdir = xmp_readdir,
103 .symlink = xmp_symlink,
104 .unlink = xmp_unlink,
106 .rename = xmp_rename,
110 .truncate = xmp_truncate,
111 #ifdef HAVE_UTIMENSAT
112 .utimens = xmp_utimens,
117 .statfs = xmp_statfs,
118 .release = xmp_release,
120 #ifdef HAVE_POSIX_FALLOCATE
121 .fallocate = xmp_fallocate,
123 .setxattr = xmp_setxattr,
124 .getxattr = xmp_getxattr,
125 .listxattr = xmp_listxattr,
126 .removexattr = xmp_removexattr,
129 int main(int argc, char *argv[])
131 // TODO: parse options...
133 return fuse_main(argc, argv, &xmp_oper, NULL);