endif(ENABLE_CODECOVERAGE)
set(SOURCE_FILES
+ stringmem.c
fuse_xattrs.c
passthrough.c
binary_storage.c
#include "binary_storage.h"
#include "utils.h"
#include "fuse_xattrs_config.h"
+#include "stringmem.h"
#include <sys/xattr.h>
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);
}
#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
#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;
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);
}
fclose(file);
- free(buffer);
+ strfree(buffer);
return res;
}
{
struct on_memory_attr *attr = __read_on_memory_attr(&offset, buffer, _buffer_size);
if (attr == NULL) {
- free(buffer);
+ strfree(buffer);
return -EILSEQ;
}
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;
}
{
struct on_memory_attr *attr = __read_on_memory_attr(&offset, buffer, _buffer_size);
if (attr == NULL) {
- free(buffer);
+ strfree(buffer);
return -EILSEQ;
}
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);
}
__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 ?
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
}
fclose(file);
- free(buffer);
+ strfree(buffer);
return res;
}
#include "xattrs_config.h"
#include "utils.h"
#include "passthrough.h"
-
+#include "stringmem.h"
#include "binary_storage.h"
struct xattrs_config xattrs_config;
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;
}
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;
}
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;
}
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,
absolute_path[len-2] = '/';
if (is_directory(absolute_path) == -1) {
- free(absolute_path);
+ strfree(absolute_path);
return NULL;
}
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),
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]);
#include "xattrs_config.h"
#include "utils.h"
+#include "stringmem.h"
int xmp_getattr(const char *path, struct stat *stbuf) {
int res;
char *_path = prepend_source_directory(path);
res = lstat(_path, stbuf);
- free(_path);
+ strfree(_path);
if (res == -1)
return -errno;
char *_path = prepend_source_directory(path);
res = access(_path, mask);
- free(_path);
+ strfree(_path);
if (res == -1)
return -errno;
char *_path = prepend_source_directory(path);
res = readlink(_path, buf, size - 1);
- free(_path);
+ strfree(_path);
if (res == -1)
return -errno;
} else {
char *_path = prepend_source_directory(path);
dp = opendir(_path);
- free(_path);
+ strfree(_path);
}
if (dp == NULL)
else
res = mknod(_path, mode, rdev);
- free(_path);
+ strfree(_path);
if (res == -1)
return -errno;
char *_path = prepend_source_directory(path);
res = mkdir(_path, mode);
- free(_path);
+ strfree(_path);
if (res == -1)
return -errno;
res = unlink(_path);
if (res == -1) {
- free(_path);
+ strfree(_path);
return -errno;
}
error_print("Error removing sidecar file: %s\n", sidecar_path);
}
}
- free(sidecar_path);
- free(_path);
+ strfree(sidecar_path);
+ strfree(_path);
return 0;
}
char *_path = prepend_source_directory(path);
res = rmdir(_path);
- free(_path);
+ strfree(_path);
if (res == -1)
return -errno;
char *_to = prepend_source_directory(to);
res = symlink(from, _to);
- free(_to);
+ strfree(_to);
if (res == -1)
return -errno;
res = rename(_from, _to);
if (res == -1) {
- free(_from);
- free(_to);
+ strfree(_from);
+ strfree(_to);
return -errno;
}
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;
}
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;
char *_path = prepend_source_directory(path);
res = chmod(_path, mode);
- free(_path);
+ strfree(_path);
if (res == -1)
return -errno;
char *_path = prepend_source_directory(path);
res = lchown(_path, uid, gid);
- free(_path);
+ strfree(_path);
if (res == -1)
return -errno;
char *_path = prepend_source_directory(path);
res = truncate(_path, size);
- free(_path);
+ strfree(_path);
if (res == -1)
return -errno;
}
#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;
char *_path = prepend_source_directory(path);
fd = open(_path, fi->flags);
- free(_path);
+ strfree(_path);
if (fd == -1)
return -errno;
char *_path = prepend_source_directory(path);
res = statvfs(_path, stbuf);
- free(_path);
+ strfree(_path);
if (res == -1)
return -errno;
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);
--- /dev/null
+#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 );
+ }
+}
--- /dev/null
+
+// 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);
#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) {
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
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;