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

CTU-FEE-B0B35APO-Semestral-project/file-browser/src/local_file_utils.c -rw-r--r-- 3.9 KiB
7aa0ada9 — Rutherther chore: fix image in readme 2 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#include "local_file_utils.h"
#include <stdlib.h>
#include <sys/stat.h>
#include "path.h"
#include <errno.h>
#include <ftw.h>
#include <string.h>
#include <stdio.h>
#include "dirent.h"

static int nfw_callback(const char *fpath, const struct stat *sb, int typeflag);

size_t file_get_full_path_memory_size(fileaccess_state_t state, directory_t *directory, file_t *file) {
  size_t root = strlen(state.payload.local.path);
  size_t dir = strlen(directory->path);
  size_t file_name = strlen(file->name);

  return root + 1 + dir + 1 + file_name + 1;
}

bool file_get_full_path(fileaccess_state_t state,
                        directory_t *directory, file_t *file, char *out) {
  char base_path[path_join_memory_size(state.payload.local.path, directory->path)];
  if (!path_join((char*)state.payload.local.path, directory->path, base_path)) {
    return false;
  }

  if (!path_join(base_path, file->name, out)) {
    return false;
  }

  return true;
}

int directory_delete(const char *path) {
  int err = ftw(path, nfw_callback, 5);
  if (err != 1) {
    err = FILOPER_UNKNOWN;
  }

  if (err != 0) {
    return err;
  }

  return file_delete(path);
}

int file_delete(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 directory_delete(fpath);
  } else {
    return file_delete(fpath);
  }
}


file_operation_error_t file_get_information(void *malloced,
                                                   uint64_t *file_offset,
                                                   uint64_t *names_offset,
                                                   fileaccess_state_t state,
                                                   file_t file) {
  size_t name_len = strlen(file.name);

  char full_path[file_get_full_path_memory_size(state, file.directory, &file)];
  file_get_full_path(state, file.directory, &file, full_path);

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

  if (status == -1) {
    file.size = 0;
    file.gid = 0;
    file.uid = 0;
    file.permissions = 0;
    file.modify_time = 0;
  } else {
    file.size = stats.st_size;
    file.gid = stats.st_gid;
    file.uid = stats.st_uid;
    file.permissions = stats.st_mode;
    file.modify_time = stats.st_mtim.tv_sec;
  }

  file_t *stored = malloced + *file_offset;
  *stored = file;
  *file_offset += sizeof(file_t);

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

  return FILOPER_SUCCESS;
}

file_operation_error_t directory_list(fileaccess_state_t state, void *malloced,
                                      char *show_path, uint32_t files_count,
                                      DIR *dirptr, directory_t *directory) {
  uint64_t files_offset = sizeof(directory_t) + strlen(show_path) + 1;
  uint64_t names_offset = files_count * sizeof(file_t) + files_offset;

  file_operation_error_t error = FILOPER_SUCCESS;
  directory->path = malloced + sizeof(directory_t);
  directory->files = malloced + files_offset;
  directory->files_count = 0;
  strcpy(directory->path, show_path);

  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;
    }

    error = file_get_information(malloced, &files_offset,
                                 &names_offset, state, file);
    errno = 0;
    if (error != FILOPER_SUCCESS) {
      return error;
    }

    directory->files_count++;
  }

  closedir(dirptr);
  return error;
}