#include "webfuse/adapter/impl/filesystem.h" #include "webfuse/adapter/impl/operations.h" #include "webfuse/adapter/impl/session.h" #include #include #include #include #include #include #include #include #include #include #include static struct fuse_lowlevel_ops const filesystem_operations = { .lookup = &wf_impl_operation_lookup, .getattr = &wf_impl_operation_getattr, .readdir = &wf_impl_operation_readdir, .open = &wf_impl_operation_open, .release = &wf_impl_operation_close, .read = &wf_impl_operation_read }; static char * wf_impl_filesystem_create_id(void) { uuid_t uuid; uuid_generate(uuid); char id[UUID_STR_LEN]; uuid_unparse(uuid, id); return strdup(id); } static bool wf_impl_filesystem_is_link_broken(char const * path, char const * id) { bool result = false; char buffer[PATH_MAX]; ssize_t count = readlink(path, buffer, PATH_MAX); if ((0 < count) && (count < PATH_MAX)) { buffer[count] = '\0'; result = (0 == strcmp(buffer, id)); } return result; } static bool wf_impl_filesystem_get_first_subdir( char const * serviceDir, char * buffer, size_t buffer_size) { bool result = false; DIR * dir = opendir(serviceDir); if (NULL != dir) { struct dirent * entry = readdir(dir); while (NULL != entry) { if ((DT_DIR == entry->d_type) && ('.' != entry->d_name[0])) { buffer[0] = '\0'; strncat(buffer, entry->d_name, buffer_size); /* Flawfinder: ignore */ result = true; break; } entry = readdir(dir); } closedir(dir); } return result; } static void wf_impl_filesystem_cleanup( struct wf_impl_filesystem * filesystem) { fuse_session_reset(filesystem->session); fuse_session_unmount(filesystem->session); fuse_session_destroy(filesystem->session); filesystem->session = NULL; free(filesystem->buffer.mem); fuse_opt_free_args(&filesystem->args); struct wf_impl_session * session = filesystem->user_data.session; char path[PATH_MAX]; snprintf(path, PATH_MAX, "%s/%s/%s", session->mount_point, filesystem->user_data.name, filesystem->id); rmdir(path); char serviceDir[PATH_MAX]; snprintf(serviceDir, PATH_MAX, "%s/%s", session->mount_point, filesystem->user_data.name); snprintf(path, PATH_MAX, "%s/%s/default", session->mount_point, filesystem->user_data.name); if (wf_impl_filesystem_is_link_broken(path, filesystem->id)) { unlink(path); char firstDir[PATH_MAX]; bool found = wf_impl_filesystem_get_first_subdir(serviceDir, firstDir, PATH_MAX); if (found) { symlink(firstDir, path); } else { rmdir(serviceDir); } } free(filesystem->user_data.name); free(filesystem->id); } static bool wf_impl_filesystem_init( struct wf_impl_filesystem * filesystem, struct wf_impl_session * session, char const * name) { bool result = false; wf_dlist_item_init(&filesystem->item); char * argv[] = {"", NULL}; filesystem->args.argc = 1; filesystem->args.argv = argv; filesystem->args.allocated = 0; filesystem->user_data.session = session; filesystem->user_data.timeout = 1.0; filesystem->user_data.name = strdup(name); filesystem->id = wf_impl_filesystem_create_id(); memset(&filesystem->buffer, 0, sizeof(struct fuse_buf)); char path[PATH_MAX]; snprintf(path, PATH_MAX, "%s/%s", session->mount_point, name); mkdir(path, 0755); snprintf(path, PATH_MAX, "%s/%s/%s", session->mount_point, name, filesystem->id); mkdir(path, 0755); char defaultPath[PATH_MAX]; snprintf(defaultPath, PATH_MAX, "%s/%s/default", session->mount_point, name); symlink(filesystem->id, defaultPath); filesystem->session = fuse_session_new( &filesystem->args, &filesystem_operations, sizeof(filesystem_operations), &filesystem->user_data); if (NULL != filesystem->session) { result = (0 == fuse_session_mount(filesystem->session, path)); } if (result) { lws_sock_file_fd_type fd; fd.filefd = fuse_session_fd(filesystem->session); struct lws_protocols const * protocol = lws_get_protocol(session->wsi); filesystem->wsi = lws_adopt_descriptor_vhost(lws_get_vhost(session->wsi), LWS_ADOPT_RAW_FILE_DESC, fd, protocol->name, session->wsi); if (NULL == filesystem->wsi) { wf_impl_filesystem_cleanup(filesystem); result = false; } } return result; } struct wf_impl_filesystem * wf_impl_filesystem_create( struct wf_impl_session * session, char const * name) { struct wf_impl_filesystem * filesystem = malloc(sizeof(struct wf_impl_filesystem)); if (NULL != filesystem) { bool success = wf_impl_filesystem_init(filesystem, session, name); if (!success) { free(filesystem); filesystem = NULL; } } return filesystem; } void wf_impl_filesystem_dispose( struct wf_impl_filesystem * filesystem) { wf_impl_filesystem_cleanup(filesystem); free(filesystem); } void wf_impl_filesystem_process_request( struct wf_impl_filesystem * filesystem) { int const result = fuse_session_receive_buf(filesystem->session, &filesystem->buffer); if (0 < result) { fuse_session_process_buf(filesystem->session, &filesystem->buffer); } else if (-EINTR != result) { // ToDo } }