use larger string heap
[rrq/fuse_xattrs.git] / binary_storage.c
index cbe3333c57d55deeab8a7c4d51846362ba7d0282..e8eaba4564fba93768181f6a4c98d3e322715e34 100644 (file)
 #include <string.h>
 #include <errno.h>
 #include <assert.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
 
 #include "binary_storage.h"
 #include "utils.h"
 #include "fuse_xattrs_config.h"
+#include "stringmem.h"
+#include "xattrs_config.h"
 
-#include <attr/xattr.h>
+#include <sys/xattr.h>
+
+#ifndef ENOATTR
+    #define ENOATTR ENODATA
+#endif
 
 struct on_memory_attr {
     u_int16_t name_size;
@@ -37,14 +46,18 @@ 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)
 {
-    free(attr->name);
-    free(attr->value);
+    if(attr->name != NULL)
+        strfree(attr->name);
+
+    if(attr->value != NULL)
+        strfree(attr->value);
+
     free(attr);
 }
 
@@ -109,7 +122,7 @@ char *__read_file_sidecar(const char *path, int *buffer_size)
     debug_print("path=%s sidecar_path=%s\n", path, sidecar_path);
 
     char *buffer = __read_file(sidecar_path, buffer_size);
-    free (sidecar_path);
+    strfree (sidecar_path);
     return buffer;
 }
 
@@ -131,6 +144,8 @@ struct on_memory_attr *__read_on_memory_attr(size_t *offset, char *buffer, size_
 {
     debug_print("offset=%zu\n", *offset);
     struct on_memory_attr *attr = malloc(sizeof(struct on_memory_attr));
+    attr->name = NULL;
+    attr->value = NULL;
 
     ////////////////////////////////
     // Read name size
@@ -191,8 +206,8 @@ 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 sanitized_value=%s value_size=%zu\n", name, sanitized_value, value_size);
-    free(sanitized_value);
+    debug_print("name='%s' name_size=%hu sanitized_value='%s' value_size=%zu\n", name, name_size, sanitized_value, value_size);
+    strfree(sanitized_value);
 #endif
 
     // write name
@@ -207,13 +222,46 @@ int __write_to_file(FILE *file, const char *name, const char *value, const size_
     if (fwrite(&value_size, sizeof(size_t), 1, file) != 1) {
         return -1;
     }
-    if (fwrite(value, value_size, 1, file) != 1) {
-        return -1;
+    // write value content only if we have something to write.
+    if (value_size > 0) {
+        if (fwrite(value, value_size, 1, file) != 1) {
+            return -1;
+        }
     }
 
     return 0;
 }
 
+// Ensure existence of tail path from either source_dir or sidecar_dir
+static int ensure_dirs(char *path) {
+    int n = strlen( path );
+    char *p = stralloc( n+1 );
+    memcpy( p, path, n+1 );
+    char *e = p + 1;
+    if ( strncmp( path, xattrs_config.source_dir,
+                 xattrs_config.source_dir_size ) == 0 ) {
+       e += xattrs_config.source_dir_size;
+    } else if ( strncmp( path, xattrs_config.sidecar_dir,
+                        xattrs_config.sidecar_dir_size ) == 0 ) {
+       e += xattrs_config.sidecar_dir_size;
+    }
+    if ( e - p >= n ) {
+       return 0;
+    }
+    for ( ;; ) {
+       while ( *e && *e != '/' ) e++;
+       if ( *e ) {
+           *e = 0;
+           if ( access( p, F_OK ) && mkdir( p, 0777 ) ) {
+               return 1;
+           }
+           *(e++) = '/';
+       } else {
+           return 0;
+       }
+    }
+}
+
 /**
  *
  * @param path - path to file.
@@ -221,14 +269,14 @@ int __write_to_file(FILE *file, const char *name, const char *value, const size_
  * @param value - attribute value. size < XATTR_SIZE_MAX
  * @param size
  * @param flags - XATTR_CREATE and/or XATTR_REPLACE
- * @return On success, zero is returned.  On failure, -errno is returnted.
+ * @return On success, zero is returned.  On failure, -errno is returned.
  */
 int binary_storage_write_key(const char *path, const char *name, const char *value, size_t size, int flags)
 {
 #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;
@@ -236,7 +284,7 @@ int binary_storage_write_key(const char *path, const char *name, const char *val
 
     if (buffer == NULL && buffer_size == -ENOENT && flags & XATTR_REPLACE) {
         error_print("No xattr. (flag XATTR_REPLACE)");
-        return -ENODATA;
+        return -ENOATTR;
     }
 
     if (buffer == NULL && buffer_size != -ENOENT) {
@@ -245,15 +293,20 @@ int binary_storage_write_key(const char *path, const char *name, const char *val
 
     int status;
     char *sidecar_path = get_sidecar_path(path);
+
+    if ( ensure_dirs( sidecar_path ) ) {
+       return -ENOATTR;
+    }
+
     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);
@@ -301,7 +354,7 @@ int binary_storage_write_key(const char *path, const char *name, const char *val
     }
 
     fclose(file);
-    free(buffer);
+    strfree(buffer);
     return res;
 }
 
@@ -329,7 +382,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;
         }
 
@@ -345,13 +398,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;
 }
@@ -382,7 +435,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;
         }
 
@@ -391,7 +444,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);
@@ -402,11 +455,11 @@ 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 ?
-        return -E2BIG;
+        return -ENOSPC;
     }
 
     return (int)res;
@@ -426,7 +479,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
@@ -463,6 +516,6 @@ int binary_storage_remove_key(const char *path, const char *name)
     }
 
     fclose(file);
-    free(buffer);
+    strfree(buffer);
     return res;
-}
\ No newline at end of file
+}