-
Notifications
You must be signed in to change notification settings - Fork 0
/
fs.c
325 lines (244 loc) · 16 KB
/
fs.c
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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
#include "fs.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
FileSystem* init_fs(int buff_size){
FileSystem* fs = (FileSystem*)malloc(sizeof(FileSystem)); // we allocate memory for the file system
if(!fs){
handle_error_ret("\n#### ERROR in allocating memory for file system! ####\n", NULL); // if there's an error we return NULL
}
fs->buff = (char*)malloc(buff_size); // we allocate memory for the buffer
if(!fs->buff){
free(fs);
handle_error_ret("\n#### ERROR in allocating memory for buffer! ####\n", NULL); // if there's an error we return NULL
}
fs->buff_size = buff_size; // we set the buffer size to the size we want
fs->root_directory = (Directory*)malloc(sizeof(Directory)); // we allocate memory for the root directory
if(!fs->root_directory){ // if there's an error we free the buffer and the file system and return NULL
free(fs->buff);
free(fs);
handle_error_ret("\n#### ERROR in allocating memory for root directory! ####\n", NULL);
}
strncpy(fs->root_directory->dir_name, "root", MAX_FILE_NAME); // we set the name of the root directory to "root"
fs->root_directory->elements = NULL; // we set the elements of the root directory to NULL
fs->root_directory->num_elements = 0; // we set the number of elements in the root directory to 0
fs->root_directory->num_subdirectories = 0; // we set the number of subdirectories in the root directory to 0
fs->root_directory->parent = NULL; // we set the parent of the root directory to NULL (it's the root)
fs->curr_directory = fs->root_directory; // we set the current directory to the root directory
printf("\n#### HOLD UP! File System initialized successfully! ####\n");
return fs; // we return the file system
}
FileHandler* create_file(FileSystem *fs, const char *name){
if (!fs){ // File system not found
handle_error_ret("\n#### ERROR! File System not found! ####\n", NULL);
}
for(int i = 0; i < fs->curr_directory->num_elements; i++){ // Checking whether the name is already in use
if(strcmp(fs->curr_directory->elements[i].name, name) == 0){ // it goes through all the elements in the current directory and checks the name
handle_error_ret("\n #### ERROR! File with this name already exists! ####\n", NULL);
}
}
int flag = -1;
for(int i = 0; i < fs->buff_size; i++){ // Checking if there's some free space in the File System buffer
if(fs->buff[i] == '\0'){ // If there is space, the block will recieve position of flag in the FS buffer (first free block) :)
flag = i;
break;
}
}
if(flag == -1){ // If there isn't any space the buffer is full :(
perror("\n#### ERROR! Buffer is full! ####\n");
return NULL;
}
DirectoryElement *new_elements = realloc(fs->curr_directory->elements, sizeof(DirectoryElement) * (fs->curr_directory->num_elements + 1)); // we reallocate memory in the current directory to be able to add a new element
if (!new_elements){
handle_error_ret("\n#### ERROR in reallocating memory for directory elements! ####\n", NULL);
}
fs->curr_directory->elements = new_elements;
DirectoryElement* new_element = &fs->curr_directory->elements[fs->curr_directory->num_elements++]; // Creating a new DirectoryElement thas has the address of the last element in the current directory
strncpy(new_element->name, name, MAX_FILE_NAME); // we "copy" the file name to the new_element DirectoryElement with its position in the buffer
new_element->pos = flag;
new_element->parent = fs->curr_directory; // we set the parent of the new element to the current directory
printf("\n#### HOLD UP! %s created successfully! ####\n", name);
FileHandler* fh = (FileHandler*)malloc(sizeof(FileHandler)); // we create a new FileHandler
if(!fh){
handle_error_ret("\n#### ERROR in allocating memory for file handler! ####\n", NULL);
free(new_elements);
}
fh->pos = 0; // we set the position of the file handler to 0
fh->element_index = fs->curr_directory->num_elements - 1; // we set the element index of the file handler to the index of the new element in the current directory
fh->directory = fs->curr_directory; // we set the directory of the file handler to the current directory
return fh;
}
void erase_file(FileSystem *fs, const char *name){
if (!fs){
handle_error("\n#### ERROR! File System not found! ####\n");
return;
}
int file_found = -1; // we set the file_found flag to -1
for(int i = 0; i < fs->curr_directory->num_elements; i++){
if(strcmp(fs->curr_directory->elements[i].name, name) == 0){ // we search for the file in the current directory
memset(fs->buff + fs->curr_directory->elements[i].pos, 0, MAX_FILE_SIZE); // we erase the file in the buffer (buffer + position of the file in the buffer)
memmove(&(fs->curr_directory->elements[i]), &(fs->curr_directory->elements[i+1]), sizeof(DirectoryElement) * (fs->curr_directory->num_elements-i-1)); // we move the elements in the directory to the left
DirectoryElement *new_elements = realloc(fs->curr_directory->elements, sizeof(DirectoryElement) * (fs->curr_directory->num_elements - 1)); // we reallocate memory in the current directory to be able to remove the element
if (new_elements || fs->curr_directory->num_elements - 1 == 0){ // if there's no error or the number of elements in the current directory is 0
fs->curr_directory->elements = new_elements; // we set the new elements in the current directory
}
if(fs->curr_directory->num_elements > 0) fs->curr_directory->num_elements--; // we decrement the number of elements in the current directory :)
printf("\n#### HOLD UP! %s erased successfully! ####\n", name);
file_found = 1; // file has been found! :)
break;
}
}
if(file_found == -1){ // if the file has not been found :(
printf("\n#### ERROR! %s not found! ####\n", name);
return;
}
}
void write_file(FileSystem *fs, FileHandler *fh, const char *data){
if (!fs){
handle_error("\n#### ERROR! File System not found! ####\n");
return;
}
if(!fh){
handle_error("\n#### ERROR! File Handler not found! ####\n");
return;
}
DirectoryElement *element = &fh->directory->elements[fh->element_index]; // we get the file from the directory based off its index in the directory
int content_size = strlen(data);
if(content_size > MAX_FILE_SIZE){
handle_error("\n#### ERROR! Content size is greater than the maximum file size! ####\n");
return;
}
if(element->pos + fh->pos + content_size > fs->buff_size){ // if the position of the file in the buffer + the position of the file cursor + the content size is greater than the buffer size
handle_error("\n#### ERROR! Content size is greater than the buffer size! ####\n");
return;
}
memcpy(fs->buff + element->pos + fh->pos, data, content_size); // we copy the data to the buffer at the position of the file in the buffer + the position of the file cursor
printf("\n#### HOLD UP! Content written successfully to %s! ####\n", element->name);
return;
}
void read_file(FileSystem *fs, FileHandler *fh){
if (!fs){
handle_error("\n#### ERROR! File System not found! ####\n");
return;
}
if (!fh){
handle_error("\n#### ERROR! File Handler not found! ####\n");
return;
}
DirectoryElement *element = &fh->directory->elements[fh->element_index];
printf("\n#### Content of %s: %s ####\n", element->name, fs->buff + element->pos + fh->pos); // we print the content of the file in the buffer at the position of the file in the buffer + the position of the file cursor
return;
}
void seek_file(FileHandler *fh, int pos){
if(pos < 0){
handle_error("\n#### ERROR! Position is less than 0! ####\n");
}
if(!fh){
handle_error("\n#### ERROR! File Handler not found! ####\n");
}
fh->pos = pos; // we set the file cursor to the position we want
return;
}
void create_directory(FileSystem *fs, const char *name){
if (!fs){
handle_error("\n#### ERROR! File System not found! ####\n");
return;
}
for(int i = 0; i < fs->curr_directory->num_subdirectories; i++){ // Checking whether the name is already in use
if(strcmp(fs->curr_directory->subdirectories[i]->dir_name, name) == 0){
handle_error("\n#### ERROR! Directory with this name already exists! ####\n");
return;
}
}
Directory *new_directory = (Directory*)malloc(sizeof(Directory)); // if not we allocate memory for the new directory
if(!new_directory){
handle_error("\n#### Error in allocating memory for new directory! ####\n");
return;
}
strncpy(new_directory->dir_name, name, MAX_FILE_NAME); // we set directory parameters
new_directory->elements = NULL;
new_directory->num_elements = 0;
new_directory->num_subdirectories = 0;
new_directory->parent = fs->curr_directory; // we set the parent of the new subdirectory to the "current directory" on which the File System is working on
fs->curr_directory->subdirectories[fs->curr_directory->num_subdirectories++] = new_directory; // we add the new directory to the subdirectories of the current directory
printf("\n#### HOLD UP! %s created successfully! ####\n", name);
return;
}
void erase_directory(FileSystem *fs, const char *name){
if (!fs){
handle_error("\n#### ERROR! File System not found! ####\n");
return;
}
int dir_found = -1; // we set the dir_found flag to -1
for (int i = 0; i < fs->curr_directory->num_subdirectories; i++){ // we search for the subdirectory in the current directory
if (strcmp(fs->curr_directory->subdirectories[i]->dir_name, name) == 0){
Directory *dir_to_erase = fs->curr_directory->subdirectories[i];
while (dir_to_erase->num_subdirectories > 0){
erase_directory(fs, dir_to_erase->subdirectories[dir_to_erase->num_subdirectories - 1]->dir_name); // we delete all the subdirectories of the directory we want to erase
dir_to_erase->num_subdirectories--;
}
while (dir_to_erase->num_elements > 0){ // we delete all the files in the directory we want to erase
erase_file(fs, dir_to_erase->elements[dir_to_erase->num_elements - 1].name);
dir_to_erase->num_elements--;
if (dir_to_erase->num_elements == 0){
break;
}
}
memmove(&(fs->curr_directory->subdirectories[i]), &(fs->curr_directory->subdirectories[i+1]), sizeof(Directory*) * (fs->curr_directory->num_subdirectories-i-1)); // we move the subdirectories to the left
fs->curr_directory->num_subdirectories--;
free(dir_to_erase);
printf("\n#### HOLD UP! Directory %s erased successfully! ####\n", name);
return;
}
}
if(dir_found == -1){
handle_error("\n#### ERRROR! Directory not found! ####\n");
return;
}
}
void change_directory(FileSystem *fs, const char *name){
if (!fs){
handle_error("\n#### ERROR! File System not found! ####\n");
return;
}
if(strcmp(name, "..") == 0){ // if the name is ".." we go to the parent directory
if(fs->curr_directory->parent){ // if the parent of the current directory is not NULL (root)
fs->curr_directory = fs->curr_directory->parent; // we set the current directory to the parent directory
printf("\n#### HOLD UP! Directory changed to %s! ####\n", fs->curr_directory->dir_name);
return;
}
else{
printf("\n#### HOLD UP! Already in root directory! ####\n");
return;
}
}
int dir_found = -1;
for (int i = 0; i < fs->curr_directory->num_subdirectories; i++){
if (strcmp(fs->curr_directory->subdirectories[i]->dir_name, name) == 0){
printf("\n#### HOLD UP! Directory changed to %s! ####\n", name);
fs->curr_directory = fs->curr_directory->subdirectories[i]; // we set the current directory to the subdirectory we want to go to
dir_found = 1;
break;
}
}
if(dir_found == -1){
handle_error("\n#### ERRROR! Directory not found! ####\n");
return;
}
}
void list_directory(FileSystem *fs){
if (!fs){
handle_error("\n#### ERROR! File System not found! ####\n");
return;
}
printf("\n------ Current Directory: %s ------- \n", fs->curr_directory->dir_name);
printf("Directories:\n");
for (int i = 0; i < fs->curr_directory->num_subdirectories; i++){
printf(" %s\n", fs->curr_directory->subdirectories[i]->dir_name);
}
printf("Files:\n");
for (int i = 0; i < fs->curr_directory->num_elements; i++){
printf(" %s\n", fs->curr_directory->elements[i].name);
}
printf("--------------------------------------\n");
}