#include "local_file_access.h" #include "file_access.h" #include "path.h" #include #include #include #include #include #include #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, };