~ruther/CTU-FEE-B0B35APO-Semestral-project

ab9ad098dd3a1880cb3bbd42d372ab1a205d0b01 — František Boháček 3 years ago be6250a
feat: add local file access functions
2 files changed, 227 insertions(+), 0 deletions(-)

A file-browser/include/local_file_access.h
A file-browser/src/local_file_access.c
A file-browser/include/local_file_access.h => file-browser/include/local_file_access.h +21 -0
@@ 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__

A file-browser/src/local_file_access.c => file-browser/src/local_file_access.c +206 -0
@@ 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,
};

Do not follow this link