adding string heap and sroot=%s option
authorRalph Ronnquist <ralph.ronnquist@gmail.com>
Thu, 11 Nov 2021 06:34:45 +0000 (17:34 +1100)
committerRalph Ronnquist <ralph.ronnquist@gmail.com>
Thu, 11 Nov 2021 06:34:45 +0000 (17:34 +1100)
CMakeLists.txt
binary_storage.c
fuse_xattrs.c
passthrough.c
passthrough.h
stringmem.c [new file with mode: 0644]
stringmem.h [new file with mode: 0644]
utils.c
xattrs_config.h

index bcefc8e59bde3ceabdb1a70826c4bb3a8c01363d..0caddcf78aae935ebc90a8cd72e259e3caa54df2 100644 (file)
@@ -61,6 +61,7 @@ if(ENABLE_CODECOVERAGE)
 endif(ENABLE_CODECOVERAGE)
 
 set(SOURCE_FILES
+        stringmem.c
         fuse_xattrs.c
         passthrough.c
         binary_storage.c
index c782d8672123924ac72d155614c716f8c8faacb2..0a4321e7d69f61bec66a4b44c1c51157e4bdafb4 100644 (file)
@@ -16,6 +16,7 @@
 #include "binary_storage.h"
 #include "utils.h"
 #include "fuse_xattrs_config.h"
+#include "stringmem.h"
 
 #include <sys/xattr.h>
 
@@ -41,17 +42,17 @@ void __print_on_memory_attr(struct on_memory_attr *attr)
     debug_print("value size: %zu\n", attr->value_size);
     debug_print("sanitized_value: '%s'\n", sanitized_value);
     debug_print("--------------\n");
-    free(sanitized_value);
+    strfree(sanitized_value);
 #endif
 }
 
 void __free_on_memory_attr(struct on_memory_attr *attr)
 {
     if(attr->name != NULL)
-        free(attr->name);
+        strfree(attr->name);
 
     if(attr->value != NULL)
-        free(attr->value);
+        strfree(attr->value);
 
     free(attr);
 }
@@ -202,7 +203,7 @@ int __write_to_file(FILE *file, const char *name, const char *value, const size_
 #ifdef DEBUG
     char *sanitized_value = sanitize_value(value, value_size);
     debug_print("name='%s' name_size=%hu sanitized_value='%s' value_size=%zu\n", name, name_size, sanitized_value, value_size);
-    free(sanitized_value);
+    strfree(sanitized_value);
 #endif
 
     // write name
@@ -241,7 +242,7 @@ int binary_storage_write_key(const char *path, const char *name, const char *val
 #ifdef DEBUG
     char *sanitized_value = sanitize_value(value, size);
     debug_print("path=%s name=%s sanitized_value=%s size=%zu flags=%d\n", path, name, sanitized_value, size, flags);
-    free(sanitized_value);
+    strfree(sanitized_value);
 #endif
 
     int buffer_size;
@@ -259,14 +260,14 @@ int binary_storage_write_key(const char *path, const char *name, const char *val
     int status;
     char *sidecar_path = get_sidecar_path(path);
     FILE *file = fopen(sidecar_path, "w");
-    free(sidecar_path);
+    strfree(sidecar_path);
 
     if (buffer == NULL) {
         debug_print("new file, writing directly...\n");
         status = __write_to_file(file, name, value, size);
         assert(status == 0);
         fclose(file);
-        free(buffer);
+        strfree(buffer);
         return 0;
     }
     assert(buffer_size >= 0);
@@ -314,7 +315,7 @@ int binary_storage_write_key(const char *path, const char *name, const char *val
     }
 
     fclose(file);
-    free(buffer);
+    strfree(buffer);
     return res;
 }
 
@@ -342,7 +343,7 @@ int binary_storage_read_key(const char *path, const char *name, char *value, siz
     {
         struct on_memory_attr *attr = __read_on_memory_attr(&offset, buffer, _buffer_size);
         if (attr == NULL) {
-            free(buffer);
+            strfree(buffer);
             return -EILSEQ;
         }
 
@@ -358,13 +359,13 @@ int binary_storage_read_key(const char *path, const char *name, char *value, siz
                 error_print("error, attr->value_size=%zu > size=%zu\n", attr->value_size, size);
                 res = -ERANGE;
             }
-            free(buffer);
+            strfree(buffer);
             __free_on_memory_attr(attr);
             return res;
         }
         __free_on_memory_attr(attr);
     }
-    free(buffer);
+    strfree(buffer);
 
     return -ENOATTR;
 }
@@ -395,7 +396,7 @@ int binary_storage_list_keys(const char *path, char *list, size_t size)
     {
         struct on_memory_attr *attr = __read_on_memory_attr(&offset, buffer, _buffer_size);
         if (attr == NULL) {
-            free(buffer);
+            strfree(buffer);
             return -EILSEQ;
         }
 
@@ -404,7 +405,7 @@ int binary_storage_list_keys(const char *path, char *list, size_t size)
                 error_print("Not enough memory allocated. allocated=%zu required=%ld\n",
                             size, attr->name_size + res);
                 __free_on_memory_attr(attr);
-                free(buffer);
+                strfree(buffer);
                 return -ERANGE;
             } else {
                 memcpy(list + res, attr->name, attr->name_size);
@@ -415,7 +416,7 @@ int binary_storage_list_keys(const char *path, char *list, size_t size)
         }
         __free_on_memory_attr(attr);
     }
-    free(buffer);
+    strfree(buffer);
 
     if (size == 0 && res > XATTR_LIST_MAX) {
         // FIXME: we should return the size or an error ?
@@ -439,7 +440,7 @@ int binary_storage_remove_key(const char *path, const char *name)
 
     char *sidecar_path = get_sidecar_path(path);
     FILE *file = fopen(sidecar_path, "w");
-    free(sidecar_path);
+    strfree(sidecar_path);
 
     size_t offset = 0;
     size_t name_len = strlen(name) + 1; // null byte \0
@@ -476,6 +477,6 @@ int binary_storage_remove_key(const char *path, const char *name)
     }
 
     fclose(file);
-    free(buffer);
+    strfree(buffer);
     return res;
 }
index fe5637071b0daae80bb952b9f17cd43fc2fd0695..01d4d26a6c8bd60cc165863ed113299f840b0812 100644 (file)
@@ -35,7 +35,7 @@
 #include "xattrs_config.h"
 #include "utils.h"
 #include "passthrough.h"
-
+#include "stringmem.h"
 #include "binary_storage.h"
 
 struct xattrs_config xattrs_config;
@@ -66,11 +66,11 @@ static int xmp_setxattr(const char *path, const char *name, const char *value, s
     debug_print("path=%s name=%s value=%s size=%zu XATTR_CREATE=%d XATTR_REPLACE=%d\n",
                 _path, name, sanitized_value, size, flags & XATTR_CREATE, flags & XATTR_REPLACE);
 
-    free(sanitized_value);
+    strfree(sanitized_value);
 #endif
 
     int rtval = binary_storage_write_key(_path, name, value, size, flags);
-    free(_path);
+    strfree(_path);
 
     return rtval;
 }
@@ -93,7 +93,7 @@ static int xmp_getxattr(const char *path, const char *name, char *value, size_t
     char *_path = prepend_source_directory(path);
     debug_print("path=%s name=%s size=%zu\n", _path, name, size);
     int rtval = binary_storage_read_key(_path, name, value, size);
-    free(_path);
+    strfree(_path);
 
     return rtval;
 }
@@ -124,7 +124,7 @@ static int xmp_listxattr(const char *path, char *list, size_t size)
     char *_path = prepend_source_directory(path);
     debug_print("path=%s size=%zu\n", _path, size);
     int rtval = binary_storage_list_keys(_path, list, size);
-    free(_path);
+    strfree(_path);
 
     return rtval;
 }
@@ -147,11 +147,13 @@ static int xmp_removexattr(const char *path, const char *name)
     char *_path = prepend_source_directory(path);
     debug_print("path=%s name=%s\n", _path, name);
     int rtval = binary_storage_remove_key(_path, name);
-    free(_path);
+    strfree(_path);
 
     return rtval;
 }
 
+extern int xmp_utimens(const char *path, const struct timespec ts[2]);
+
 static struct fuse_operations xmp_oper = {
         .getattr     = xmp_getattr,
         .access      = xmp_access,
@@ -226,7 +228,7 @@ const char *sanitized_source_directory(const char *path) {
         absolute_path[len-2] = '/';
 
     if (is_directory(absolute_path) == -1) {
-        free(absolute_path);
+        strfree(absolute_path);
         return NULL;
     }
 
@@ -243,6 +245,7 @@ enum {
 static struct fuse_opt xattrs_opts[] = {
         FUSE_XATTRS_OPT("show_sidecar",         show_sidecar,       1),
         FUSE_XATTRS_OPT("enable_namespaces",    enable_namespaces,  1),
+       FUSE_XATTRS_OPT("sroot=%s", sidecar_dir, 0 ),
 
         FUSE_OPT_KEY("-V",                 KEY_VERSION),
         FUSE_OPT_KEY("--version",          KEY_VERSION),
@@ -298,6 +301,12 @@ int main(int argc, char *argv[]) {
         exit(1);
     }
 
+    if ( xattrs_config.sidecar_dir ) {
+       xattrs_config.sidecar_dir =
+           sanitized_source_directory( xattrs_config.sidecar_dir );
+       return 0;
+    }
+    
     if (!xattrs_config.source_dir) {
         fprintf(stderr, "missing source directory\n");
         fprintf(stderr, "see `%s -h' for usage\n", argv[0]);
index b827da98968c4645bae6b7bbfb919df3c39b94f5..6d00593c7993853c4840bd0d7d9e53dab17984f1 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "xattrs_config.h"
 #include "utils.h"
+#include "stringmem.h"
 
 int xmp_getattr(const char *path, struct stat *stbuf) {
     int res;
@@ -39,7 +40,7 @@ int xmp_getattr(const char *path, struct stat *stbuf) {
 
     char *_path = prepend_source_directory(path);
     res = lstat(_path, stbuf);
-    free(_path);
+    strfree(_path);
 
     if (res == -1)
         return -errno;
@@ -55,7 +56,7 @@ int xmp_access(const char *path, int mask) {
 
     char *_path = prepend_source_directory(path);
     res = access(_path, mask);
-    free(_path);
+    strfree(_path);
 
     if (res == -1)
         return -errno;
@@ -71,7 +72,7 @@ int xmp_readlink(const char *path, char *buf, size_t size) {
 
     char *_path = prepend_source_directory(path);
     res = readlink(_path, buf, size - 1);
-    free(_path);
+    strfree(_path);
 
     if (res == -1)
         return -errno;
@@ -93,7 +94,7 @@ int xmp_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
     } else {
         char *_path = prepend_source_directory(path);
         dp = opendir(_path);
-        free(_path);
+        strfree(_path);
     }
 
     if (dp == NULL)
@@ -135,7 +136,7 @@ int xmp_mknod(const char *path, mode_t mode, dev_t rdev) {
     else
         res = mknod(_path, mode, rdev);
 
-    free(_path);
+    strfree(_path);
     if (res == -1)
         return -errno;
 
@@ -150,7 +151,7 @@ int xmp_mkdir(const char *path, mode_t mode) {
 
     char *_path = prepend_source_directory(path);
     res = mkdir(_path, mode);
-    free(_path);
+    strfree(_path);
 
     if (res == -1)
         return -errno;
@@ -168,7 +169,7 @@ int xmp_unlink(const char *path) {
     res = unlink(_path);
 
     if (res == -1) {
-        free(_path);
+        strfree(_path);
         return -errno;
     }
 
@@ -178,8 +179,8 @@ int xmp_unlink(const char *path) {
             error_print("Error removing sidecar file: %s\n", sidecar_path);
         }
     }
-    free(sidecar_path);
-    free(_path);
+    strfree(sidecar_path);
+    strfree(_path);
 
     return 0;
 }
@@ -193,7 +194,7 @@ int xmp_rmdir(const char *path) {
 
     char *_path = prepend_source_directory(path);
     res = rmdir(_path);
-    free(_path);
+    strfree(_path);
 
     if (res == -1)
         return -errno;
@@ -211,7 +212,7 @@ int xmp_symlink(const char *from, const char *to) {
 
     char *_to = prepend_source_directory(to);
     res = symlink(from, _to);
-    free(_to);
+    strfree(_to);
 
     if (res == -1)
         return -errno;
@@ -232,8 +233,8 @@ int xmp_rename(const char *from, const char *to) {
     res = rename(_from, _to);
 
     if (res == -1) {
-        free(_from);
-        free(_to);
+        strfree(_from);
+        strfree(_to);
         return -errno;
     }
 
@@ -246,11 +247,11 @@ int xmp_rename(const char *from, const char *to) {
             error_print("Error renaming sidecar. from: %s to: %s\n", from_sidecar_path, to_sidecar_path);
         }
     }
-    free(from_sidecar_path);
-    free(to_sidecar_path);
+    strfree(from_sidecar_path);
+    strfree(to_sidecar_path);
 
-    free(_from);
-    free(_to);
+    strfree(_from);
+    strfree(_to);
 
     return 0;
 }
@@ -267,8 +268,8 @@ int xmp_link(const char *from, const char *to) {
     char *_from = prepend_source_directory(from);
     char *_to = prepend_source_directory(to);
     res = link(_from, _to);
-    free(_from);
-    free(_to);
+    strfree(_from);
+    strfree(_to);
 
     if (res == -1)
         return -errno;
@@ -284,7 +285,7 @@ int xmp_chmod(const char *path, mode_t mode) {
 
     char *_path = prepend_source_directory(path);
     res = chmod(_path, mode);
-    free(_path);
+    strfree(_path);
 
     if (res == -1)
         return -errno;
@@ -300,7 +301,7 @@ int xmp_chown(const char *path, uid_t uid, gid_t gid) {
 
     char *_path = prepend_source_directory(path);
     res = lchown(_path, uid, gid);
-    free(_path);
+    strfree(_path);
 
     if (res == -1)
         return -errno;
@@ -316,7 +317,7 @@ int xmp_truncate(const char *path, off_t size) {
 
     char *_path = prepend_source_directory(path);
     res = truncate(_path, size);
-    free(_path);
+    strfree(_path);
 
     if (res == -1)
         return -errno;
@@ -325,20 +326,17 @@ int xmp_truncate(const char *path, off_t size) {
 }
 
 #ifdef HAVE_UTIMENSAT
-int xmp_utimens(const char *path, const struct timespec ts[2],
-struct fuse_file_info *fi)
-{
+int xmp_utimens(const char *path, const struct timespec ts[2]) {
     if (xattrs_config.show_sidecar == 0 && filename_is_sidecar(path) == 1)  {
         return -ENOENT;
     }
 
-    (void) fi;
     int res;
 
     char *_path = prepend_source_directory(path);
     /* don't use utime/utimes since they follow symlinks */
     res = utimensat(0, _path, ts, AT_SYMLINK_NOFOLLOW);
-    free(_path);
+    strfree(_path);
     if (res == -1)
         return -errno;
 
@@ -354,7 +352,7 @@ int xmp_open(const char *path, struct fuse_file_info *fi) {
 
     char *_path = prepend_source_directory(path);
     fd = open(_path, fi->flags);
-    free(_path);
+    strfree(_path);
 
     if (fd == -1)
         return -errno;
@@ -401,7 +399,7 @@ int xmp_statfs(const char *path, struct statvfs *stbuf) {
 
     char *_path = prepend_source_directory(path);
     res = statvfs(_path, stbuf);
-    free(_path);
+    strfree(_path);
 
     if (res == -1)
         return -errno;
index 928ec4a2c9210518839bde104c5d7225b37e91cb..ebc9a1b2a349715f664b84701fda9c0d256aaf2c 100644 (file)
@@ -29,7 +29,7 @@ int xmp_link(const char *from, const char *to);
 int xmp_chmod(const char *path, mode_t mode);
 int xmp_chown(const char *path, uid_t uid, gid_t gid);
 int xmp_truncate(const char *path, off_t size);
-int xmp_utimens(const char *path, const struct timespec ts[2], struct fuse_file_info *fi);
+int xmp_utimens(const char *path, const struct timespec ts[2]);
 int xmp_open(const char *path, struct fuse_file_info *fi);
 int xmp_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi);
 int xmp_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi);
diff --git a/stringmem.c b/stringmem.c
new file mode 100644 (file)
index 0000000..303add7
--- /dev/null
@@ -0,0 +1,55 @@
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define BIGSTRING 1048576
+#define STRINGSPACE ( BIGSTRING * 20 )
+
+static struct {
+    char *base;
+    char *current;
+    char *end;
+} heap;
+
+char *strjoin(const char *first,...) {
+    va_list ap;
+    if ( heap.base == 0 ) {
+       heap.base = (char*) malloc( STRINGSPACE );
+       heap.current = heap.base;
+       heap.end = heap.base + STRINGSPACE;
+    }
+    char *start = heap.current;
+    const char *p = first;
+    size_t size = strlen( first ) + 1;
+    va_start( ap, first );
+    while ( ( p = va_arg( ap, const char* ) ) ) {
+       size += strlen( p );
+    }
+    va_end( ap );
+    if ( size > BIGSTRING ) {
+       start = (char*) malloc( size );
+    } else {
+       if ( heap.current + size > heap.end ) {
+           heap.current = heap.base;
+       }
+       start = heap.current;
+       heap.current += size;
+    }
+    char *current = start;
+    strcpy( current, first );
+    current += strlen( first );
+    va_start( ap, first );
+    while ( ( p = va_arg( ap, const char* ) ) ) {
+       strcpy( current, p );
+       current += strlen( p );
+    }
+    va_end( ap );
+    *current = 0;
+    return start;
+}
+
+void strfree(char *p) {
+    if ( p < heap.base || p >= heap.end ) {
+       free( p );
+    }
+}
diff --git a/stringmem.h b/stringmem.h
new file mode 100644 (file)
index 0000000..c25218f
--- /dev/null
@@ -0,0 +1,6 @@
+
+// Concatenate strigns onto the heap if possible, or malloc new.
+extern char *strjoin(const char *first,...);
+
+// Dispose memory possibly within the string heap
+extern void strfree(char *p);
diff --git a/utils.c b/utils.c
index 2f935ab83c02b4b326dcdcf491bdc47eeb570ece..a6a8b756f8b33cbb4dc37142e5abbb2db4fed459 100644 (file)
--- a/utils.c
+++ b/utils.c
 #include "utils.h"
 #include "fuse_xattrs_config.h"
 #include "xattrs_config.h"
+#include "stringmem.h"
 
 /* TODO: re-use memory to avoid calling malloc every time */
 char *prepend_source_directory(const char *b) {
-    const size_t b_size = strlen(b);
-    const size_t dst_len = xattrs_config.source_dir_size + b_size + 1;
-    char *dst = (char*) malloc(sizeof(char) * dst_len);
-
-    memcpy(dst, xattrs_config.source_dir, xattrs_config.source_dir_size);
-    memcpy(dst+xattrs_config.source_dir_size, b, b_size + 1); // include '\0'
-    //sprintf(dst, "%s%s", a, b);
-
-    return dst;
+    return strjoin( xattrs_config.source_dir, b, 0 );
 }
 
 int is_directory(const char *path) {
@@ -59,15 +52,15 @@ int is_regular_file(const char *path) {
 
 char *get_sidecar_path(const char *path)
 {
-    const size_t path_len = strlen(path);
-    const size_t sidecar_ext_len = strlen(BINARY_SIDECAR_EXT); // this can be optimized
-    const size_t sidecar_path_len = path_len + sidecar_ext_len + 1;
-    char *sidecar_path = (char *) malloc(sidecar_path_len);
-    memset(sidecar_path, '\0', sidecar_path_len);
-    memcpy(sidecar_path, path, path_len);
-    memcpy(sidecar_path + path_len, BINARY_SIDECAR_EXT, sidecar_ext_len);
-
-    return sidecar_path;
+#define CFG xattrs_config
+    if ( strncmp( path, CFG.source_dir, CFG.source_dir_size ) == 0 ) {
+       const char *p = path + CFG.source_dir_size;
+       if ( CFG.sidecar_dir ) {
+           return strjoin( CFG.sidecar_dir, p, BINARY_SIDECAR_EXT, 0 );
+       }
+    }
+    return strjoin( path, BINARY_SIDECAR_EXT, 0 );
+#undef CFG
 }
 
 // TODO: make it work for binary data
index 347a61cba16b4a5953018314006de4b9851e801f..6d8be2a26287414973f4c59cbcc8d166fc4cc49f 100644 (file)
@@ -13,9 +13,9 @@
 extern struct xattrs_config {
     const int show_sidecar;
     const int enable_namespaces;
+    const char *sidecar_dir;
     const char *source_dir;
     size_t source_dir_size;
-
 } xattrs_config;