CMakeLists.txt: Change required cmake version to 2.8
[rrq/fuse_xattrs.git] / fuse_xattrs.c
1 /*
2   fuse_xattrs - Add xattrs support using sidecar files
3
4   Copyright (C) 2016  Felipe Barriga Richards <felipe {at} felipebarriga.cl>
5
6   Based on passthrough.c (libfuse example)
7
8   This program can be distributed under the terms of the GNU GPL.
9   See the file COPYING.
10 */
11
12 #define FUSE_USE_VERSION 30
13
14 /* For pread()/pwrite()/utimensat() */
15 #define _XOPEN_SOURCE 700
16
17 #include <errno.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20
21 #include <fuse.h>
22 #include <sys/xattr.h>
23
24 #include "utils.h"
25 #include "passthrough.h"
26
27 #include "binary_storage.h"
28 #include "const.h"
29
30 static int xmp_setxattr(const char *path, const char *name, const char *value, size_t size, int flags)
31 {
32     if (get_namespace(name) != USER) {
33         debug_print("Only user namespace is supported. name=%s\n", name);
34         return -ENOTSUP;
35     }
36     if (strlen(name) > XATTR_NAME_MAX) {
37         debug_print("attribute name must be equal or smaller than %d bytes\n", XATTR_NAME_MAX);
38         return -ERANGE;
39     }
40     if (size > XATTR_SIZE_MAX) {
41         debug_print("attribute value cannot be bigger than %d bytes\n", XATTR_SIZE_MAX);
42         return -ENOSPC;
43     }
44
45 #ifdef DEBUG
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);
49
50     free(sanitized_value);
51 #endif
52      return binary_storage_write_key(path, name, value, size, flags);
53 }
54
55 static int xmp_getxattr(const char *path, const char *name, char *value, size_t size)
56 {
57     if (get_namespace(name) != USER) {
58         debug_print("Only user namespace is supported. name=%s\n", name);
59         return -ENOTSUP;
60     }
61     if (strlen(name) > XATTR_NAME_MAX) {
62         debug_print("attribute name must be equal or smaller than %d bytes\n", XATTR_NAME_MAX);
63         return -ERANGE;
64     }
65
66     debug_print("path=%s name=%s size=%zu\n", path, name, size);
67     return binary_storage_read_key(path, name, value, size);
68 }
69
70 static int xmp_listxattr(const char *path, char *list, size_t size)
71 {
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");
74         return -E2BIG;
75     }
76
77     debug_print("path=%s size=%zu\n", path, size);
78     return binary_storage_list_keys(path, list, size);
79 }
80
81 static int xmp_removexattr(const char *path, const char *name)
82 {
83     if (get_namespace(name) != USER) {
84         debug_print("Only user namespace is supported. name=%s\n", name);
85         return -ENOTSUP;
86     }
87     if (strlen(name) > XATTR_NAME_MAX) {
88         debug_print("attribute name must be equal or smaller than %d bytes\n", XATTR_NAME_MAX);
89         return -ERANGE;
90     }
91
92     debug_print("path=%s name=%s\n", path, name);
93     return binary_storage_remove_key(path, name);
94 }
95
96 static struct fuse_operations xmp_oper = {
97         .getattr     = xmp_getattr,
98         .access      = xmp_access,
99         .readlink    = xmp_readlink,
100         .readdir     = xmp_readdir,
101         .mknod       = xmp_mknod,
102         .mkdir       = xmp_mkdir,
103         .symlink     = xmp_symlink,
104         .unlink      = xmp_unlink,
105         .rmdir       = xmp_rmdir,
106         .rename      = xmp_rename,
107         .link        = xmp_link,
108         .chmod       = xmp_chmod,
109         .chown       = xmp_chown,
110         .truncate    = xmp_truncate,
111 #ifdef HAVE_UTIMENSAT
112         .utimens     = xmp_utimens,
113 #endif
114         .open        = xmp_open,
115         .read        = xmp_read,
116         .write       = xmp_write,
117         .statfs      = xmp_statfs,
118         .release     = xmp_release,
119         .fsync       = xmp_fsync,
120 #ifdef HAVE_POSIX_FALLOCATE
121         .fallocate   = xmp_fallocate,
122 #endif
123         .setxattr    = xmp_setxattr,
124         .getxattr    = xmp_getxattr,
125         .listxattr   = xmp_listxattr,
126         .removexattr = xmp_removexattr,
127 };
128
129 int main(int argc, char *argv[])
130 {
131     // TODO: parse options...
132     umask(0);
133     return fuse_main(argc, argv, &xmp_oper, NULL);
134 }