@@ 0,0 1,21 @@
+#ifndef __LOCAL_FILE_ACCESS_H__
+#define __LOCAL_FILE_ACCESS_H__
+
+#include "file_access.h"
+
+fileaccess_state_t local_fileaccess_init_state(void *data);
+bool local_fileaccess_deinit_state(fileaccess_state_t state);
+
+directory_or_error_t local_fileaccess_directory_list(fileaccess_state_t state, char *path);
+directory_or_error_t local_fileaccess_root_list(fileaccess_state_t state);
+
+directory_or_error_t local_fileaccess_directory_create(fileaccess_state_t state, char *path);
+file_operation_error_t local_fileaccess_directory_delete(fileaccess_state_t state, char *path);
+
+file_operation_error_t local_fileaccess_directory_close(fileaccess_state_t state, directory_t *directory);
+
+file_operation_error_t local_fileaccess_file_get_mime_type(fileaccess_state_t state, file_t *file, char *mime);
+pid_or_error_t local_fileaccess_file_execute(fileaccess_state_t state, file_t *file, char *args);
+file_operation_error_t local_fileaccess_file_delete(fileaccess_state_t state, char *path);
+
+#endif // __LOCAL_FILE_ACCESS_H__
@@ 0,0 1,206 @@
+#include "local_file_access.h"
+#include "file_access.h"
+#include "path.h"
+#include <errno.h>
+#include <ftw.h>
+#include <magic.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+
+#define ROOT "/"
+static int nfw_callback(const char *fpath, const struct stat *sb, int typeflag);
+static int delete_file(const char *path);
+static int delete_directory(const char *path);
+
+static int delete_directory(const char *path) {
+ int err = ftw(path, nfw_callback, 5);
+ if (err != 1) {
+ err = FILOPER_UNKNOWN;
+ }
+
+ if (err != 0) {
+ return err;
+ }
+
+ return delete_file(path);
+}
+
+static int delete_file(const char *path) {
+ int err = 0;
+ if (remove(path) == -1) {
+ err = file_operation_error_from_errno(errno);
+ }
+
+ return err;
+}
+
+static int nfw_callback(const char *fpath, const struct stat *sb,
+ int typeflag) {
+ if (typeflag == FTW_D) {
+ return delete_directory(fpath);
+ } else {
+ return delete_file(fpath);
+ }
+}
+
+fileaccess_state_t local_fileaccess_init_state(void *data) {
+ fileaccess_state_t state = {.state = ROOT, .fileaccess = &local_file_access};
+ return state;
+}
+
+bool local_fileaccess_deinit_state(fileaccess_state_t data) {
+ // nothing needs to be done
+ return true;
+}
+
+directory_or_error_t local_fileaccess_directory_list(fileaccess_state_t state,
+ char *path) {
+ directory_or_error_t ret;
+ char *full_path = path_join((char *)state.state, path);
+ if (full_path == NULL) {
+ ret.error = true;
+ ret.payload.error = FILOPER_UNKNOWN;
+ return ret;
+ }
+
+ free(full_path);
+ return ret;
+}
+
+directory_or_error_t local_fileaccess_root_list(fileaccess_state_t state) {
+ return local_fileaccess_directory_list(state, (char *)state.state);
+}
+
+directory_or_error_t local_fileaccess_directory_create(fileaccess_state_t state,
+ char *path) {
+ directory_or_error_t ret;
+ char *full_path = path_join((char *)state.state, path);
+ if (full_path == NULL) {
+ ret.error = true;
+ ret.payload.error = FILOPER_UNKNOWN;
+ return ret;
+ }
+
+ int status = mkdir(full_path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+
+ if (status == -1) {
+ ret.error = true;
+ ret.payload.error = file_operation_error_from_errno(errno);
+ } else {
+ ret = local_fileaccess_directory_list(state, full_path);
+ }
+
+ free(full_path);
+ return ret;
+}
+
+file_operation_error_t
+local_fileaccess_directory_delete(fileaccess_state_t state, char *path) {
+ file_operation_error_t error = FILOPER_SUCCESS;
+ char *full_path = path_join((char *)state.state, path);
+ if (full_path == NULL) {
+ return FILOPER_UNKNOWN;
+ }
+
+ int status = delete_directory(full_path);
+ if (status != 0) {
+ error = status;
+ }
+
+ free(full_path);
+ return error;
+}
+
+file_operation_error_t
+local_fileaccess_directory_close(fileaccess_state_t state,
+ directory_t *directory) {
+ free(directory);
+ return FILOPER_SUCCESS;
+}
+
+file_operation_error_t
+local_fileaccess_file_get_mime_type(fileaccess_state_t state, file_t *file,
+ char *mime) {
+ file_operation_error_t error = FILOPER_SUCCESS;
+
+ magic_t magic = magic_open(MAGIC_MIME_TYPE);
+ magic_load(magic, NULL);
+
+ char *full_path = path_join((char *)state.state, file->path);
+ if (full_path == NULL) {
+ return FILOPER_UNKNOWN;
+ }
+
+ const char *data = magic_file(magic, full_path);
+ if (data == NULL) {
+ error = file_operation_error_from_errno(errno);
+ }
+
+ uint16_t i = 0;
+ while (*data != '\0') {
+ mime[i++] = *data;
+ }
+ mime[i] = '\0';
+
+ free(full_path);
+ magic_close(magic);
+ return error;
+}
+
+executing_file_or_error_t local_fileaccess_file_execute(fileaccess_state_t state,
+ file_t *file, char *args) {
+ executing_file_or_error_t ret;
+ char *full_path = path_join((char *)state.state, file->path);
+ // TODO: check permissions
+
+ if (full_path == NULL) {
+ ret.error = true;
+ ret.payload.error = FILOPER_UNKNOWN;
+ return ret;
+ }
+
+ executing_file_error_t efile = executing_file_execute(full_path, args);
+ if (efile.error == true) {
+ ret.error = true;
+ ret.payload.error = FILOPER_UNKNOWN;
+ } else {
+ ret.payload.file = efile.file;
+ }
+
+ free(full_path);
+ return ret;
+}
+
+file_operation_error_t local_fileaccess_file_delete(fileaccess_state_t state,
+ char *path) {
+ file_operation_error_t error = FILOPER_SUCCESS;
+ char *full_path = path_join((char *)state.state, path);
+
+ if (full_path == NULL) {
+ return FILOPER_UNKNOWN;
+ }
+
+ int status = remove(path);
+
+ if (status == -1) {
+ error = file_operation_error_from_errno(errno);
+ }
+
+ free(full_path);
+ return error;
+}
+
+const fileaccess_t local_file_access = {
+ .type = FA_LOCAL,
+ .delete_file = local_fileaccess_file_delete,
+ .delete_directory = local_fileaccess_directory_delete,
+ .close_directory = local_fileaccess_directory_close,
+ .create_directory = local_fileaccess_directory_create,
+ .list_directory = local_fileaccess_directory_list,
+ .list_root = local_fileaccess_root_list,
+ .init = local_fileaccess_init_state,
+ .deinit = local_fileaccess_deinit_state,
+ .get_mime_type = local_fileaccess_file_get_mime_type,
+ .execute_file = local_fileaccess_file_execute,
+};