diff --git a/fuse/hashtbl.c b/fuse/hashtbl.c index 3100377..3d5d669 100644 --- a/fuse/hashtbl.c +++ b/fuse/hashtbl.c @@ -540,6 +540,59 @@ static struct h_entry *folder_tree_lookup_path(folder_tree * tree, return result; } +uint64_t folder_tree_path_get_num_children(folder_tree * tree, + const char *path) +{ + struct h_entry *result; + + result = folder_tree_lookup_path(tree, path); + + if (result != NULL) { + return result->num_children; + } else { + return -1; + } +} + +bool folder_tree_path_is_root(folder_tree * tree, const char *path) +{ + struct h_entry *result; + + result = folder_tree_lookup_path(tree, path); + + if (result != NULL) { + return result == &(tree->root); + } else { + return false; + } +} + +bool folder_tree_path_is_directory(folder_tree * tree, const char *path) +{ + struct h_entry *result; + + result = folder_tree_lookup_path(tree, path); + + if (result != NULL) { + return result->atime == 0; + } else { + return false; + } +} + +const char *folder_tree_path_get_key(folder_tree * tree, const char *path) +{ + struct h_entry *result; + + result = folder_tree_lookup_path(tree, path); + + if (result != NULL) { + return result->key; + } else { + return NULL; + } +} + /* * given a path, check if it exists in the hashtable */ @@ -549,7 +602,7 @@ bool folder_tree_path_exists(folder_tree * tree, const char *path) result = folder_tree_lookup_path(tree, path); - return path != NULL; + return result != NULL; } int folder_tree_getattr(folder_tree * tree, const char *path, diff --git a/fuse/hashtbl.h b/fuse/hashtbl.h index d06665e..da8d8fe 100644 --- a/fuse/hashtbl.h +++ b/fuse/hashtbl.h @@ -51,4 +51,14 @@ folder_tree *folder_tree_load(FILE * stream); bool folder_tree_path_exists(folder_tree * tree, const char *path); +uint64_t folder_tree_path_get_num_children(folder_tree * tree, + const char *path); + +bool folder_tree_path_is_directory(folder_tree * tree, + const char *path); + +const char *folder_tree_path_get_key(folder_tree * tree, const char *path); + +bool folder_tree_path_is_root(folder_tree * tree, const char *path); + #endif diff --git a/fuse/main.c b/fuse/main.c index 60bfa63..d6454bb 100644 --- a/fuse/main.c +++ b/fuse/main.c @@ -24,8 +24,12 @@ #include #include #include +#include +#include +#include #include "../mfapi/mfconn.h" +#include "../mfapi/apicalls.h" #include "hashtbl.h" enum { @@ -118,10 +122,122 @@ static void mediafirefs_destroy() folder_tree_destroy(tree); } +static int mediafirefs_mkdir(const char *path, mode_t mode) +{ + (void)mode; + + char *dirname; + int retval; + char *basename; + const char *key; + + folder_tree_update(tree, conn); + + /* before calling the remote function we check locally */ + + dirname = strdup(path); + + if (strcmp(dirname, "/") == 0) { + fprintf(stderr, "the root already exists\n"); + return -EEXIST; + } + + /* remove possible trailing slash */ + if (dirname[strlen(dirname) - 1] == '/') { + dirname[strlen(dirname) - 1] = '\0'; + } + + /* check if the path already exists */ + if (folder_tree_path_exists(tree, dirname)) { + fprintf(stderr, "the path %s already exists\n", dirname); + return -EEXIST; + } + + /* split into dirname and basename */ + + basename = rindex(dirname, '/'); + if (basename == NULL) { + fprintf(stderr, "cannot find slash\n"); + return -ENOENT; + } + + /* replace the slash by a terminating zero */ + basename[0] = '\0'; + + /* basename points to the string after the last slash */ + basename++; + + /* check if the dirname is of zero length now. If yes, then the directory + * is to be created in the root */ + if (dirname[0] == '\0') { + key = NULL; + } else { + key = folder_tree_path_get_key(tree, dirname); + } + + retval = mfconn_api_folder_create(conn, key, basename); + mfconn_update_secret_key(conn); + if (retval != 0) { + fprintf(stderr, "mfconn_api_folder_create unsuccessful\n"); + // FIXME: find better errno in this case + return -EAGAIN; + } + + free(dirname); + + folder_tree_update(tree, conn); + + return 0; +} + +int mediafirefs_rmdir(const char *path) +{ + const char *key; + int retval; + + folder_tree_update(tree, conn); + + /* check if path is directory */ + if (!folder_tree_path_is_directory(tree, path)) { + fprintf(stderr, "path is not a directory\n"); + // FIXME: find a better errno in this case + return -ENOENT; + } + + /* check if directory is empty */ + if (folder_tree_path_get_num_children(tree, path) != 0) { + fprintf(stderr, "path is not empty\n"); + return -ENOTEMPTY; + } + + /* check if directory is root */ + if (folder_tree_path_is_root(tree, path)) { + fprintf(stderr, "cannot remove root\n"); + // FIXME: find better errno in this case + return -EPERM; + } + + key = folder_tree_path_get_key(tree, path); + + retval = mfconn_api_folder_delete(conn, key); + mfconn_update_secret_key(conn); + if (retval != 0) { + fprintf(stderr, "mfconn_api_folder_create unsuccessful\n"); + // FIXME: find better errno in this case + return -EAGAIN; + } + + folder_tree_update(tree, conn); + + return 0; +} + static struct fuse_operations mediafirefs_oper = { .getattr = mediafirefs_getattr, .readdir = mediafirefs_readdir, .destroy = mediafirefs_destroy, + .mkdir = mediafirefs_mkdir, + .rmdir = mediafirefs_rmdir, /* .create = mediafirefs_create, .fsync = mediafirefs_fsync, .getattr = mediafirefs_getattr,