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

4a24b06e4435a27e4aa584700e401e713cde314c — František Boháček 3 years ago e8073d3
feat: add directory list
M file-browser/include/file_access.h => file-browser/include/file_access.h +17 -20
@@ 6,11 6,13 @@
#include <sys/types.h>
#include "file_execute.h"

typedef struct directory_t directory_t;

typedef enum {
  TYPE_FOLDER,
  TYPE_FILE,
  TYPE_OTHER,
  TYPE_UNKNOWN,
  FT_FOLDER,
  FT_FILE,
  FT_OTHER,
  FT_UNKNOWN,
} filetype_t;

typedef enum {


@@ 21,29 23,24 @@ typedef enum {
} fileaccess_type_t;

typedef struct {
  uint8_t owner : 3;
  uint8_t group : 3;
  uint8_t other : 3;
} file_permissions_t;

typedef struct {
  char *path;
  char *name;
  directory_t *directory;
  filetype_t type;

  // stats
  uint64_t size;
  uint64_t modify_date;
  uint64_t create_date;
  file_permissions_t permissions;
  char *owner;
  char *group_owner;
  time_t modify_time;

  mode_t permissions;
  uid_t uid;
  gid_t gid;
} file_t;

typedef struct {
struct directory_t {
  char *path;
  file_t *files;
  uint32_t files_count;
} directory_t;
};

typedef enum {
  FILOPER_SUCCESS,


@@ 142,8 139,8 @@ extern const fileaccess_t
extern const fileaccess_t
    temp_file_access; // state is /tmp directory descriptor

extern uint8_t connectors_count;
extern const fileaccess_connector_t connectors[(FA_COUNT-1)*FA_COUNT];
extern uint8_t fileaccess_connectors_count;
extern fileaccess_connector_t fileaccess_connectors[(FA_COUNT-1)*FA_COUNT];

fileaccess_state_t fileaccess_init(const fileaccess_t *fileaccess, void *data);
bool fileaccess_deinit(fileaccess_state_t state);

M file-browser/include/local_file_access.h => file-browser/include/local_file_access.h +1 -1
@@ 15,7 15,7 @@ file_operation_error_t local_fileaccess_directory_delete(fileaccess_state_t stat
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);
executing_file_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__

M file-browser/src/local_file_access.c => file-browser/src/local_file_access.c +129 -2
@@ 6,13 6,29 @@
#include <magic.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <dirent.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 char *file_get_full_path(fileaccess_state_t state,
                                directory_t *directory, file_t *file) {
  char *base_path = path_join((char*)state.state, directory->path);

  if (base_path == NULL) {
    return NULL;
  }

  char *full_path = path_join(base_path, file->name);
  free(base_path);

  return full_path;
}

static int delete_directory(const char *path) {
  int err = ftw(path, nfw_callback, 5);
  if (err != 1) {


@@ 54,6 70,51 @@ bool local_fileaccess_deinit_state(fileaccess_state_t data) {
  return true;
}

static file_operation_error_t file_get_information(void **malloced,
                                                   uint64_t *offset, uint64_t *bytes_malloced,
                                                   fileaccess_state_t state,
                                                   file_t file) {
  size_t name_len = strlen(file.name);
  bytes_malloced += sizeof(file_t) + name_len + 1;
  void *new = realloc(*malloced, *bytes_malloced);
  if (new == NULL) {
    free(*malloced);
    return FILOPER_UNKNOWN;
  }
  *malloced = new;

  char *full_path = file_get_full_path(state, file.directory, &file);
  if (full_path == NULL) {
    free(new);
    return FILOPER_UNKNOWN;
  }

  // load info
  struct stat stats;
  int status = stat(full_path, &stats);
  free(full_path);

  if (status == -1) {
    free(new);
    return file_operation_error_from_errno(errno);
  }

  file.size = stats.st_size;
  file.gid = stats.st_gid;
  file.uid = stats.st_uid;
  file.permissions = stats.st_mode;

  file_t *stored = new + *offset;
  *stored = file;
  *offset += sizeof(file_t);

  strcpy(new + *offset, file.name);
  stored->name = new + *offset;
  *offset += name_len + 1;

  return FILOPER_SUCCESS;
}

directory_or_error_t local_fileaccess_directory_list(fileaccess_state_t state,
                                                     char *path) {
  directory_or_error_t ret;


@@ 64,7 125,72 @@ directory_or_error_t local_fileaccess_directory_list(fileaccess_state_t state,
    return ret;
  }

  uint64_t malloc_offset = sizeof(directory_t) + strlen(path) + 1;
  uint64_t bytes_malloced = sizeof(directory_t) + strlen(path) + 1;
  directory_t *directory = malloc(malloc_offset);
  void *malloced = directory;

  if (directory == NULL) {
    ret.error = true;
    ret.payload.error = FILOPER_UNKNOWN;
    free(full_path);
    return ret;
  }

  directory->path = malloced + sizeof(directory_t);
  strcpy(directory->path, path);


  DIR *dirptr = opendir(full_path);
  free(full_path);
  if (dirptr == NULL) {
    ret.error = true;
    ret.payload.error = file_operation_error_from_errno(errno);
    free(malloced);
    return ret;
  }

  struct dirent * dir;
  errno = 0;
  while ((dir = readdir(dirptr)) != NULL) {
    file_t file;
    file.directory = directory;
    file.name = dir->d_name;

    switch(dir->d_type) {
    case DT_DIR:
      file.type = FT_FOLDER;
      break;
    case DT_REG:
      file.type = FT_FILE;
      break;
    case DT_UNKNOWN:
      file.type = FT_UNKNOWN;
      break;
    default:
      file.type = FT_OTHER;
      break;
    }

    ret.payload.error = file_get_information(&malloced, &malloc_offset,
                                             &bytes_malloced, state, file);
    if (ret.payload.error != FILOPER_SUCCESS) {
      ret.error = true;
      free(malloced);
      return ret;
    }

    directory->files_count++;
  }

  if (errno != 0) {
    ret.error = true;
    ret.payload.error = file_operation_error_from_errno(errno);
  } else {
    ret.error = false;
    ret.payload.directory = directory;
  }

  return ret;
}



@@ 127,7 253,7 @@ local_fileaccess_file_get_mime_type(fileaccess_state_t state, file_t *file,
  magic_t magic = magic_open(MAGIC_MIME_TYPE);
  magic_load(magic, NULL);

  char *full_path = path_join((char *)state.state, file->path);
  char *full_path = file_get_full_path(state, file->directory, file);
  if (full_path == NULL) {
    return FILOPER_UNKNOWN;
  }


@@ 151,7 277,7 @@ local_fileaccess_file_get_mime_type(fileaccess_state_t state, file_t *file,
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);
  char *full_path = file_get_full_path(state, file->directory, file);
  // TODO: check permissions

  if (full_path == NULL) {


@@ 165,6 291,7 @@ executing_file_or_error_t local_fileaccess_file_execute(fileaccess_state_t state
    ret.error = true;
    ret.payload.error = FILOPER_UNKNOWN;
  } else {
    ret.error = false;
    ret.payload.file = efile.file;
  }


Do not follow this link