agendafs
A filesystem for your calendar.
git clone git://mccd.space/agendafscommit 29523d8017d6219f78f9fbcbfb05047c9ff7caef
parent 6e1f7ca146b7ae8ad2eb5ec5706038a1bade8f92
Author: Marc Coquand <marc@coquand.email>
Date: Mon, 28 Jul 2025 23:50:09 +0200
Add size limits on xattr
Diffstat:
2 files changed, 21 insertions(+), 11 deletions(-)
diff --git a/agendafs.8.scd b/agendafs.8.scd
@@ -30,7 +30,7 @@ are agendafs specific options:
Agendafs has support for xattributes (_xattr_(7)) to modify icalendar
fields. See the man pages of _setfattr_(1) and _getfattr_(1) for basic
-usage. Supported extended attributes are:
+usage. Built-in extended attributes are:
*user.categories*
A comma separated list of categories to classify an entry.
@@ -39,6 +39,9 @@ usage. Supported extended attributes are:
The classification of an entry. Can be either *public*,
*private* or *confidential*.
+Arbitrary user-provided attributes are also supported. Limits are set
+to 255 bytes and 64 kilobytes respectively.
+
# EXAMPLES
Mount vdir storage with agendafs to your home journal directory:
diff --git a/main.c b/main.c
@@ -415,8 +415,8 @@ cleanup_return:
}
static int
-fuse_setxattr(const char *path, const char *header, const char *new_attributes,
- size_t s, int flags)
+fuse_setxattr(const char *path, const char *key, const char *value, size_t s,
+ int flags)
{
LOG("SETXATTR '%s' '%s' '%zu' '%s' '%d'", path, header, s,
new_attributes, flags);
@@ -424,25 +424,32 @@ fuse_setxattr(const char *path, const char *header, const char *new_attributes,
pthread_mutex_lock(&entries_mutex);
int status = 0;
- if (strcmp(header, "user.categories") == 0) {
+ // Limit imposed in xattr(7)
+ if (strlen(key) < 256) {
+ status = -EMSGSIZE;
+ }
+
+ if (strlen(value) < 64 * 1024) {
+ status = -EMSGSIZE;
+ }
+ if (strcmp(key, "user.categories") == 0) {
struct tree_node *node = get_node_by_path(mreg, path);
if (!node) {
status = -ENONET;
goto cleanup_return;
}
- status = set_node_categories(mreg, node, new_attributes, s);
+ status = set_node_categories(mreg, node, value, s);
goto cleanup_return;
}
- else if (strcmp(header, "user.class") == 0) {
+ else if (strcmp(key, "user.class") == 0) {
struct tree_node *node = get_node_by_path(mreg, path);
if (!node) {
status = -ENONET;
goto cleanup_return;
}
- enum icalproperty_class iclass =
- parse_ical_class(new_attributes);
+ enum icalproperty_class iclass = parse_ical_class(value);
if (iclass == ICAL_CLASS_X) {
status = -EINVAL;
@@ -452,7 +459,7 @@ fuse_setxattr(const char *path, const char *header, const char *new_attributes,
status = set_node_class(mreg, node, iclass);
goto cleanup_return;
}
- else if (starts_with_str(header, "user.")) {
+ else if (starts_with_str(key, "user.")) {
struct tree_node *node = get_node_by_path(mreg, path);
if (!node) {
status = -ENONET;
@@ -461,8 +468,8 @@ fuse_setxattr(const char *path, const char *header, const char *new_attributes,
icalcomponent *ic = get_icalcomponent_from_node(mreg, node);
- const char *key = header + 5;
- icalcomponent_set_custom_x_value(mreg, ic, key, new_attributes);
+ const char *key = key + 5;
+ icalcomponent_set_custom_x_value(mreg, ic, key, value);
status = write_ical_file(mreg, node, ic);
goto cleanup_return;
}