3cc97e880d44a69e72765bb3f3bef873d21d0d17
[monolithium.git] / drivers / fatfs / src / main.c
1 /*
2  * FAT12/16/32 Filesystem Driver
3  * main.c
4  *
5  * Copyright (C) 2016 Aleksandar Andrejevic <theflash@sdf.lonestar.org>
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU Affero General Public License as
9  * published by the Free Software Foundation, either version 3 of the
10  * License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Affero General Public License for more details.
16  *
17  * You should have received a copy of the GNU Affero General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include "fat.h"
22 #include <syscalls.h>
23 #include <heap.h>
24 #include <exception.h>
25 #include <user.h>
26
27 const char driver_name[] = "fatfs";
28
29 static dword_t fatfs_mount(const char *device, const char *mountpoint, dword_t flags);
30 static dword_t fatfs_unmount(mounted_volume_t *volume);
31 static dword_t fatfs_load_file(file_t **file);
32 static dword_t fatfs_unload_file(file_t *file);
33 static dword_t fatfs_open_file(file_instance_t **instance);
34 static dword_t fatfs_close_file(file_instance_t *instance);
35 static dword_t fatfs_delete_file(mounted_volume_t *volume, const char *path, bool_t purge);
36 static dword_t fatfs_read_file(file_instance_t *file, void *buffer, qword_t offset, size_t length, size_t *bytes_read);
37 static dword_t fatfs_write_file(file_instance_t *file, const void *buffer, qword_t offset, size_t length, size_t *bytes_written);
38 static dword_t fatfs_list_dir(file_instance_t *directory, char *filename, bool_t continue_scan);
39 static dword_t fatfs_set_file(file_t *file, dword_t info_type, const void *buffer, size_t size);
40
41 static dword_t fatfs_read_internal(object_t *obj, void *buffer, qword_t offset, size_t length, size_t *bytes_read);
42 static dword_t fatfs_write_internal(object_t *obj, const void *buffer, qword_t offset, size_t length, size_t *bytes_written);
43
44 static fs_driver_t fatfs_driver =
45 {
46     .name = "FAT",
47     .mount = fatfs_mount,
48     .unmount = fatfs_unmount,
49     .load_file = fatfs_load_file,
50     .unload_file = fatfs_unload_file,
51     .open_file = fatfs_open_file,
52     .close_file = fatfs_close_file,
53     .delete_file = fatfs_delete_file,
54     .read_file = fatfs_read_file,
55     .write_file = fatfs_write_file,
56     .list_dir = fatfs_list_dir,
57     .set_file = fatfs_set_file
58 };
59
60 static void fatfs_get_entry_name(fatfs_dirent_t *dirent, char *name)
61 {
62     byte_t *src = dirent->filename;
63     char *dest = name;
64     byte_t *last_name_ptr = &dirent->filename[7];
65     byte_t *last_ext_ptr = &dirent->extension[2];
66
67     while (*last_name_ptr == ' ' && last_name_ptr >= dirent->filename) last_name_ptr--;
68     while (*last_ext_ptr == ' ' && last_ext_ptr >= dirent->extension) last_ext_ptr--;
69     while (src <= last_name_ptr) *dest++ = *src++;
70
71     src = dirent->extension;
72     if (src <= last_ext_ptr) *dest++ = '.';
73     while (src <= last_ext_ptr) *dest++ = *src++;
74     *dest = '\0';
75 }
76
77 static bool_t fatfs_check_name(const char *name)
78 {
79     const char *illegal = "\"*+,/:;<=>?[\\]|";
80     size_t num_dots = 0;
81     size_t count_before = 0;
82     size_t count_after = 0;
83
84     while (*name)
85     {
86         if (strrchr(illegal, *name) || (*name >= 'a' && *name <= 'z')) return FALSE;
87
88         if (*name == '.')
89         {
90             num_dots++;
91             if (num_dots > 1) return FALSE;
92         }
93         else if (num_dots == 0)
94         {
95             count_before++;
96             if (count_before > 8) return FALSE;
97         }
98         else
99         {
100             count_after++;
101             if (count_after > 3) return FALSE;
102         }
103
104         name++;
105     }
106
107     return TRUE;
108 }
109
110 static void fatfs_set_entry_name(fatfs_dirent_t *dirent, const char *name)
111 {
112     const char *src = name;
113     byte_t *dest = dirent->filename;
114
115     while (*src != '.' && *src != '\0') *dest++ = toupper(*src++);
116     while (dest < &dirent->filename[8]) *dest++ = ' ';
117
118     if (*src == '.')
119     {
120         src++;
121         dest = dirent->extension;
122         while (*src != '\0') *dest++ = toupper(*src++);
123     }
124 }
125
126 static inline void fatfs_pack_file_time(clock_time_t *os_time, word_t *date, word_t *time)
127 {
128     if (date) *date = (os_time->year << 9) | (os_time->month << 5) | os_time->day;
129     if (time) *time = (os_time->hours << 11) | (os_time->minutes << 5) | (os_time->seconds >> 1);
130 }
131
132 static inline void fatfs_unpack_file_time(word_t date, word_t time, clock_time_t *os_time)
133 {
134     os_time->day = date & 0x1F;
135     os_time->month = (date >> 5) & 0x0F;
136     os_time->year = (date >> 9) & 0x7F;
137     os_time->seconds = (time & 0x1F) << 1;
138     os_time->minutes = (time >> 5) & 0x3F;
139     os_time->hours = (time >> 11) & 0x1F;
140 }
141
142 static dword_t fatfs_get_next_cluster(fatfs_volume_t *volume, dword_t cluster)
143 {
144     qword_t entry_offset = (qword_t)(volume->reserved_sectors * volume->bytes_per_sector);
145
146     switch (volume->type)
147     {
148     case FAT12:
149         entry_offset += (qword_t)(cluster + (cluster >> 1));
150         break;
151
152     case FAT16:
153         entry_offset += (qword_t)(cluster << 1);
154         break;
155
156     case FAT32:
157         entry_offset += (qword_t)(cluster << 2);
158         break;
159     }
160
161     dword_t entry;
162     dword_t bytes_read;
163     dword_t ret = device_read(volume->header.device,
164                               (byte_t*)&entry,
165                               entry_offset,
166                               (volume->type == FAT32) ? sizeof(dword_t) : sizeof(word_t),
167                               &bytes_read);
168     if (ret != ERR_SUCCESS) return FATFS_INVALID_CLUSTER;
169
170     switch (volume->type)
171     {
172     case FAT12:
173         entry = ((cluster & 1) ? (entry >> 4) : entry) & 0xFFF;
174         if (entry >= 0xFF0) entry |= FATFS_INVALID_CLUSTER;
175         break;
176
177     case FAT16:
178         entry &= 0xFFFF;
179         if (entry >= 0xFFF0) entry |= FATFS_INVALID_CLUSTER;
180         break;
181
182     case FAT32:
183         entry &= 0x0FFFFFFF;
184         if (entry >= 0x0FFFFFF0) entry |= FATFS_INVALID_CLUSTER;
185         break;
186     }
187
188     if (entry == 0) entry = FATFS_INVALID_CLUSTER;
189     return entry;
190 }
191
192 static dword_t fatfs_set_next_cluster(fatfs_volume_t *volume, dword_t cluster, dword_t next)
193 {
194     qword_t entry_offset = (qword_t)(volume->reserved_sectors * volume->bytes_per_sector);
195
196     switch (volume->type)
197     {
198     case FAT12:
199         next &= 0xFFF;
200         entry_offset += (qword_t)(cluster + (cluster >> 1));
201         break;
202
203     case FAT16:
204         next &= 0xFFFF;
205         entry_offset += (qword_t)(cluster << 1);
206         break;
207
208     case FAT32:
209         next &= 0xFFFFFFFF;
210         entry_offset += (qword_t)(cluster << 2);
211         break;
212     }
213
214     dword_t entry;
215
216     if (volume->type == FAT12)
217     {
218         dword_t bytes_read;
219         dword_t ret = device_read(volume->header.device, (byte_t*)&entry, entry_offset, sizeof(word_t), &bytes_read);
220         if (ret != ERR_SUCCESS) return ret;
221
222         entry &= 0xF000 >> ((cluster & 1) * 12);
223         entry |= next << ((cluster & 1) * 4);
224     }
225     else
226     {
227         entry = next;
228     }
229
230     dword_t bytes_written;
231     return device_write(volume->header.device,
232                         (byte_t*)&entry,
233                         entry_offset,
234                         (volume->type == FAT32) ? sizeof(dword_t) : sizeof(word_t),
235                         &bytes_written);
236 }
237
238 static qword_t fatfs_get_cluster_offset(fatfs_volume_t *volume, dword_t number)
239 {
240     qword_t sector = (qword_t)(number - volume->root_dir_cluster)
241                      * (qword_t)volume->sectors_per_cluster
242                      + (qword_t)volume->reserved_sectors
243                      + (qword_t)(volume->num_fats * volume->sectors_per_fat);
244     qword_t offset = sector * (qword_t)volume->bytes_per_sector;
245
246     if (number != volume->root_dir_cluster)
247     {
248         offset += (qword_t)(volume->num_root_dirents * sizeof(fatfs_dirent_t));
249     }
250
251     return offset;
252 }
253
254 static dword_t fatfs_read_cluster(fatfs_volume_t *volume, dword_t number, void *buffer)
255 {
256     dword_t bytes_read;
257     return device_read(volume->header.device,
258                        buffer,
259                        fatfs_get_cluster_offset(volume, number),
260                        volume->sectors_per_cluster * volume->bytes_per_sector,
261                        &bytes_read);
262 }
263
264 static dword_t fatfs_zero_cluster(fatfs_volume_t *volume, dword_t number)
265 {
266     byte_t *buffer = __builtin_alloca(volume->sectors_per_cluster * volume->bytes_per_sector);
267     memset(buffer, 0, volume->sectors_per_cluster * volume->bytes_per_sector);
268
269     dword_t bytes_written;
270     return device_write(volume->header.device,
271                         buffer,
272                         fatfs_get_cluster_offset(volume, number),
273                         volume->sectors_per_cluster * volume->bytes_per_sector,
274                         &bytes_written);
275 }
276
277 static dword_t fatfs_get_free_cluster(fatfs_volume_t *volume, dword_t *cluster)
278 {
279     dword_t starting_cluster = volume->last_free_cluster;
280
281     do
282     {
283         if (fatfs_get_next_cluster(volume, volume->last_free_cluster) == FATFS_FREE_CLUSTER)
284         {
285             *cluster = volume->last_free_cluster;
286             return ERR_SUCCESS;
287         }
288
289         volume->last_free_cluster++;
290         volume->last_free_cluster %= volume->total_clusters;
291         if (volume->last_free_cluster <= volume->root_dir_cluster) volume->last_free_cluster = volume->root_dir_cluster + 1;
292     }
293     while (volume->last_free_cluster != starting_cluster);
294
295     return ERR_DISKFULL;
296 }
297
298 static dword_t fatfs_find_entry(fatfs_volume_t *volume, const char *path, dword_t *cluster_num, dword_t *entry_num, fatfs_dirent_t *dirent)
299 {
300     dword_t ret = ERR_SUCCESS;
301     dword_t i;
302     byte_t *cluster_buffer = NULL;
303     char path_copy[MAX_PATH];
304     fatfs_dirent_t root_dirent =
305     {
306         .attributes = FATFS_ATTR_DIRECTORY,
307         .first_cluster_high = volume->root_dir_cluster >> 16,
308         .first_cluster_low = volume->root_dir_cluster & 0xFFFF,
309         .size = volume->num_root_dirents * sizeof(fatfs_dirent_t)
310     };
311
312     if (path[0] == '\0')
313     {
314         if (cluster_num) *cluster_num = (dword_t)-1;
315         if (entry_num) *entry_num = (dword_t)-1;
316         if (dirent) *dirent = root_dirent;
317         goto cleanup;
318     }
319
320     dword_t cluster_size = volume->sectors_per_cluster * volume->bytes_per_sector;
321     cluster_buffer = (byte_t*)malloc(cluster_size);
322
323     if (cluster_buffer == NULL)
324     {
325         ret = ERR_NOMEMORY;
326         goto cleanup;
327     }
328
329     dword_t previous_cluster = (dword_t)-1;
330     dword_t current_cluster = volume->root_dir_cluster;
331     dword_t current_index = 0;
332     fatfs_dirent_t current_dirent = root_dirent;
333
334     char *token, *endptr;
335     strcpy(path_copy, path);
336
337     for (token = strtok_r(path_copy, PATH_DELIMITER_STRING, &endptr); token != NULL; token = strtok_r(NULL, PATH_DELIMITER_STRING, &endptr))
338     {
339         if (!(current_dirent.attributes & FATFS_ATTR_DIRECTORY))
340         {
341             ret = ERR_NOTFOUND;
342             goto cleanup;
343         }
344
345         while (TRUE)
346         {
347             ret = fatfs_read_cluster(volume, current_cluster, cluster_buffer);
348             if (ret != ERR_SUCCESS) goto cleanup;
349
350             fatfs_dirent_t *entries = (fatfs_dirent_t*)cluster_buffer;
351             dword_t num_entries = cluster_size / sizeof(fatfs_dirent_t);
352
353             for (i = 0; i < num_entries; i++)
354             {
355                 if (!(entries[i].attributes & FATFS_ATTR_VOLUME_ID)
356                     && entries[i].filename[0] != 0
357                     && entries[i].filename[0] != FATFS_DELETED)
358                 {
359                     char filename[13];
360                     fatfs_get_entry_name(&entries[i], filename);
361                     if (strcmp(token, filename) == 0) break;
362                 }
363             }
364
365             previous_cluster = current_cluster;
366
367             if (i != num_entries)
368             {
369                 current_cluster = entries[i].first_cluster_low | (entries[i].first_cluster_high << 16);
370                 current_index = i;
371                 current_dirent = entries[i];
372                 break;
373             }
374
375             current_cluster = fatfs_get_next_cluster(volume, current_cluster);
376             if (current_cluster >= FATFS_INVALID_CLUSTER)
377             {
378                 ret = ERR_NOTFOUND;
379                 break;
380             }
381         }
382     }
383
384     if (cluster_num) *cluster_num = previous_cluster;
385     if (entry_num) *entry_num = current_index;
386     if (dirent) *dirent = current_dirent;
387
388 cleanup:
389     if (cluster_buffer) free(cluster_buffer);
390     return ret;
391 }
392
393 static dword_t fatfs_resize_file(fatfs_file_t *file, qword_t new_size)
394 {
395     dword_t ret;
396     dword_t bytes;
397     fatfs_volume_t *volume = CONTAINER_OF(file->header.volume, fatfs_volume_t, header);
398
399     if (new_size == file->header.size) return ERR_SUCCESS;
400
401     dword_t cluster_size = volume->sectors_per_cluster * volume->bytes_per_sector;
402     dword_t num_clusters_old = (file->header.size + cluster_size - 1) / cluster_size;
403     dword_t num_clusters_new = (new_size + cluster_size - 1) / cluster_size;
404
405     dword_t prev_cluster = FATFS_FREE_CLUSTER;
406     dword_t current_cluster = file->first_cluster;
407
408     if (num_clusters_new > num_clusters_old)
409     {
410         while (current_cluster != FATFS_FREE_CLUSTER && current_cluster < FATFS_INVALID_CLUSTER)
411         {
412             prev_cluster = current_cluster;
413             current_cluster = fatfs_get_next_cluster(volume, current_cluster);
414         }
415
416         dword_t new_clusters = num_clusters_new - num_clusters_old;
417         while (new_clusters--)
418         {
419             dword_t new_cluster;
420             ret = fatfs_get_free_cluster(volume, &new_cluster);
421             if (ret != ERR_SUCCESS) break;
422
423             ret = fatfs_zero_cluster(volume, new_cluster);
424             if (ret != ERR_SUCCESS)
425             {
426                 fatfs_set_next_cluster(volume, new_cluster, FATFS_BAD_CLUSTER);
427                 new_clusters++;
428                 continue;
429             }
430
431             if (prev_cluster == FATFS_FREE_CLUSTER)
432             {
433                 file->first_cluster = new_cluster;
434             }
435             else
436             {
437                 ret = fatfs_set_next_cluster(volume, prev_cluster, new_cluster);
438                 if (ret != ERR_SUCCESS) break;
439             }
440
441             prev_cluster = new_cluster;
442         }
443
444         ret = fatfs_set_next_cluster(volume, prev_cluster, FATFS_LAST_CLUSTER);
445     }
446     else if (num_clusters_new < num_clusters_old)
447     {
448         while (num_clusters_new--)
449         {
450             prev_cluster = current_cluster;
451             current_cluster = fatfs_get_next_cluster(volume, current_cluster);
452             if (current_cluster >= FATFS_INVALID_CLUSTER) break;
453         }
454
455         if (prev_cluster == FATFS_FREE_CLUSTER)
456         {
457             file->first_cluster = 0;
458         }
459         else
460         {
461             ret = fatfs_set_next_cluster(volume, prev_cluster, FATFS_LAST_CLUSTER);
462         }
463
464         while (current_cluster < FATFS_INVALID_CLUSTER)
465         {
466             dword_t next_cluster = fatfs_get_next_cluster(volume, current_cluster);
467             ret = fatfs_set_next_cluster(volume, current_cluster, FATFS_FREE_CLUSTER);
468             if (ret != ERR_SUCCESS) break;
469             current_cluster = next_cluster;
470         }
471     }
472
473     clock_time_t current_time;
474     syscall(SYSCALL_CLOCK_GET_TIME, &current_time);
475
476     file->header.size = new_size;
477     fatfs_dirent_t dirent;
478
479     ret = device_read(volume->header.device,
480                       &dirent,
481                       fatfs_get_cluster_offset(volume, file->dirent_cluster) + (qword_t)file->dirent_index * sizeof(fatfs_dirent_t),
482                       sizeof(fatfs_dirent_t),
483                       &bytes);
484     if (ret != ERR_SUCCESS) return ret;
485
486     dirent.size = file->header.size;
487     dirent.first_cluster_low = file->first_cluster & 0xFFFF;
488     dirent.first_cluster_high = file->first_cluster >> 16;
489     fatfs_pack_file_time(&current_time, &dirent.modification_date, &dirent.modification_time);
490
491     return device_write(volume->header.device,
492                         &dirent,
493                         fatfs_get_cluster_offset(volume, file->dirent_cluster) + (qword_t)file->dirent_index * sizeof(fatfs_dirent_t),
494                         sizeof(fatfs_dirent_t),
495                         &bytes);
496 }
497
498 static inline dword_t fatfs_rw_file(object_t *object, byte_t *buffer, qword_t offset, size_t length, size_t *bytes, bool_t write)
499 {
500     dword_t ret;
501     dword_t count = 0;
502     fatfs_file_t *file;
503     fatfs_file_instance_t *instance;
504
505     if (object->type == OBJECT_FILE_INSTANCE)
506     {
507         instance = CONTAINER_OF(CONTAINER_OF(object, file_instance_t, header), fatfs_file_instance_t, header);
508         file = CONTAINER_OF(instance->header.global, fatfs_file_t, header);
509     }
510     else
511     {
512         ASSERT(object->type == OBJECT_FILE);
513         file = CONTAINER_OF(CONTAINER_OF(object, file_t, header), fatfs_file_t, header);
514         instance = NULL;
515     }
516
517     fatfs_volume_t *volume = CONTAINER_OF(file->header.volume, fatfs_volume_t, header);
518
519     if (!length)
520     {
521         if (bytes) *bytes = 0;
522         return ERR_SUCCESS;
523     }
524
525     if (offset > 0xFFFFFFFFULL)
526     {
527         if (bytes) *bytes = 0;
528         return ERR_BEYOND;
529     }
530
531     if (write && (offset + (qword_t)length) < file->header.size)
532     {
533         ret = fatfs_resize_file(file, offset + (qword_t)length);
534         if (ret != ERR_SUCCESS) return ret;
535     }
536
537     if (file->header.size == 0)
538     {
539         if (bytes) *bytes = 0;
540         return ERR_BEYOND;
541     }
542
543     dword_t offset_low = (dword_t)offset;
544     dword_t cluster_size = volume->sectors_per_cluster * volume->bytes_per_sector;
545     dword_t current_cluster = file->first_cluster;
546
547     while (offset_low >= cluster_size)
548     {
549         current_cluster = fatfs_get_next_cluster(volume, current_cluster);
550         if (current_cluster >= FATFS_INVALID_CLUSTER)
551         {
552             if (bytes) *bytes = 0;
553             return ERR_BEYOND;
554         }
555
556         offset_low -= cluster_size;
557     }
558
559     while (TRUE)
560     {
561         dword_t amount = MIN(length - count, cluster_size - offset_low);
562         dword_t actually_rw;
563         if (amount == 0) break;
564
565         if (write)
566         {
567             ret = device_write(volume->header.device,
568                                &buffer[count],
569                                fatfs_get_cluster_offset(volume, current_cluster) + (qword_t)offset_low,
570                                amount,
571                                &actually_rw);
572
573         }
574         else
575         {
576             ret = device_read(volume->header.device,
577                               &buffer[count],
578                               fatfs_get_cluster_offset(volume, current_cluster) + (qword_t)offset_low,
579                               amount,
580                               &actually_rw);
581         }
582
583         if (ret != ERR_SUCCESS) goto cleanup;
584
585         offset_low = 0;
586         count += amount;
587
588         current_cluster = fatfs_get_next_cluster(volume, current_cluster);
589         if (current_cluster >= FATFS_INVALID_CLUSTER) break;
590     }
591
592     ret = (count == length) ? ERR_SUCCESS : ERR_BEYOND;
593
594 cleanup:
595     if (bytes) *bytes = count;
596     return ret;
597 }
598
599 static dword_t fatfs_read_internal(object_t *obj, void *buffer, qword_t offset, size_t length, size_t *bytes_read)
600 {
601     return fatfs_rw_file(obj, buffer, offset, length, bytes_read, FALSE);
602 }
603
604 static dword_t fatfs_write_internal(object_t *obj, const void *buffer, qword_t offset, size_t length, size_t *bytes_written)
605 {
606     return fatfs_rw_file(obj, (void*)buffer, offset, length, bytes_written, TRUE);
607 }
608
609 static dword_t fatfs_mount(const char *device, const char *mountpoint, dword_t flags)
610 {
611     fatfs_bpb_t bpb;
612     fat_version_t type;
613     device_t *block_device = get_block_device(device);
614     if (block_device == NULL) return ERR_NOTFOUND;
615
616     dword_t ret = device_read(block_device, (byte_t*)&bpb, 0ULL, sizeof(fatfs_bpb_t), NULL);
617     if (ret != ERR_SUCCESS) return ret;
618     if (bpb.sectors_per_cluster == 0) return ERR_INVALID;
619
620     dword_t total_sectors;
621     if (bpb.total_sectors) total_sectors = bpb.total_sectors;
622     else total_sectors = bpb.total_sectors_32;
623
624     dword_t sectors_per_fat;
625     if (bpb.sectors_per_fat) sectors_per_fat = bpb.sectors_per_fat;
626     else sectors_per_fat = bpb.ext_bpb_32.sectors_per_fat;
627
628     dword_t root_dir_size = (bpb.num_dirent * sizeof(fatfs_dirent_t) + bpb.bytes_per_sector - 1) / bpb.bytes_per_sector;
629     dword_t total_clusters = (total_sectors - bpb.reserved_sectors - bpb.num_fats * sectors_per_fat - root_dir_size) / bpb.sectors_per_cluster;
630
631     if (total_clusters < 4086) type = FAT12;
632     else if (total_clusters < 65525) type = FAT16;
633     else type = FAT32;
634
635     if ((type != FAT32 && bpb.ext_bpb.signature != 0x28 && bpb.ext_bpb.signature != 0x29)
636         || (type == FAT32 && bpb.ext_bpb_32.signature != 0x28 && bpb.ext_bpb_32.signature != 0x29))
637     {
638         return ERR_INVALID;
639     }
640
641     fatfs_volume_t *volume = (fatfs_volume_t*)malloc(sizeof(fatfs_volume_t));
642     if (volume == NULL) return ERR_NOMEMORY;
643
644     volume->header.device = get_block_device(device);
645     volume->header.mountpoint = strdup(mountpoint);
646     volume->header.driver = &fatfs_driver;
647     volume->type = type;
648     volume->bytes_per_sector = bpb.bytes_per_sector;
649     volume->sectors_per_cluster = bpb.sectors_per_cluster;
650     volume->reserved_sectors = bpb.reserved_sectors;
651     volume->root_dir_cluster = (type == FAT32) ? bpb.ext_bpb_32.root_dir_cluster : 2;
652     volume->num_root_dirents = bpb.num_dirent;
653     volume->num_fats = bpb.num_fats;
654     volume->sectors_per_fat = sectors_per_fat;
655     volume->total_clusters = total_clusters;
656     volume->last_free_cluster = volume->root_dir_cluster + 1;
657     volume->owner_uid = get_current_uid();
658
659     ret = register_mounted_volume(&volume->header);
660     if (ret != ERR_SUCCESS) free(volume);
661
662     return ret;
663 }
664
665 static dword_t fatfs_unmount(mounted_volume_t *volume)
666 {
667     dword_t ret = unregister_mounted_volume(volume);
668     if (ret != ERR_SUCCESS) return ret;
669
670     free(volume->mountpoint);
671     free(volume);
672     return ERR_SUCCESS;
673 }
674
675 static dword_t fatfs_load_file(file_t **_file)
676 {
677     fatfs_file_t *file = (fatfs_file_t*)realloc(*_file, sizeof(fatfs_file_t));
678     if (file == NULL) return ERR_NOMEMORY;
679     *_file = &file->header;
680
681     fatfs_dirent_t dirent;
682     dword_t cluster, entry;
683     fatfs_volume_t *volume = CONTAINER_OF(file->header.volume, fatfs_volume_t, header);
684
685     dword_t ret = fatfs_find_entry(volume, file->header.path, &cluster, &entry, &dirent);
686
687     if (ret == ERR_NOTFOUND && (file->header.global_mode & FILE_MODE_CREATE))
688     {
689         dword_t i;
690
691         char *parent_path = __builtin_alloca(strlen(file->header.path) + 1);
692         strcpy(parent_path, file->header.path);
693
694         char *file_name = NULL;
695         char *last_slash = strrchr(parent_path, '/');
696         if (last_slash)
697         {
698             *last_slash = '\0';
699             file_name = last_slash + 1;
700         }
701         else
702         {
703             *parent_path = '\0';
704             file_name = file->header.path;
705         }
706
707         if (!fatfs_check_name(file_name)) return ERR_INVALID;
708
709         fatfs_dirent_t parent_dirent;
710         dword_t parent_cluster, parent_entry;
711
712         ret = fatfs_find_entry(volume, parent_path, &parent_cluster, &parent_entry, &parent_dirent);
713         if (ret != ERR_SUCCESS) return ret;
714
715         dword_t entries_per_cluster = (volume->sectors_per_cluster * volume->bytes_per_sector) / sizeof(fatfs_dirent_t);
716         fatfs_dirent_t *entries = (fatfs_dirent_t*)malloc(volume->sectors_per_cluster * volume->bytes_per_sector);
717         if (entries == NULL) return ERR_NOMEMORY;
718
719         dword_t prev_cluster = FATFS_FREE_CLUSTER;
720         dword_t current_cluster = parent_dirent.first_cluster_low | (parent_dirent.first_cluster_high << 16);
721
722         while (TRUE)
723         {
724             if (current_cluster == FATFS_FREE_CLUSTER || (current_cluster >= FATFS_END_CLUSTER))
725             {
726                 dword_t new_cluster;
727                 ret = fatfs_get_free_cluster(volume, &new_cluster);
728                 if (ret != ERR_SUCCESS) break;
729
730                 ret = fatfs_zero_cluster(volume, new_cluster);
731                 if (ret != ERR_SUCCESS)
732                 {
733                     fatfs_set_next_cluster(volume, new_cluster, FATFS_BAD_CLUSTER);
734                     continue;
735                 }
736
737                 if (prev_cluster == FATFS_FREE_CLUSTER)
738                 {
739                     parent_dirent.first_cluster_low = new_cluster & 0xFFFF;
740                     parent_dirent.first_cluster_high = new_cluster >> 16;
741                 }
742                 else
743                 {
744                     ret = fatfs_set_next_cluster(volume, prev_cluster, new_cluster);
745                     if (ret != ERR_SUCCESS) break;
746                 }
747
748                 current_cluster = new_cluster;
749             }
750
751             ret = fatfs_read_cluster(volume, current_cluster, entries);
752             if (ret != ERR_SUCCESS) break;
753
754             bool_t found = FALSE;
755
756             for (i = 0; i < entries_per_cluster; i++)
757             {
758                 if (entries[i].filename[0] == '\0' || entries[i].filename[0] == FATFS_DELETED)
759                 {
760                     cluster = current_cluster;
761                     entry = i;
762                     found = TRUE;
763                     break;
764                 }
765             }
766
767             if (found) break;
768
769             prev_cluster = current_cluster;
770             current_cluster = fatfs_get_next_cluster(volume, current_cluster);
771         }
772
773         free(entries);
774         if (ret != ERR_SUCCESS) return ret;
775
776         clock_time_t current_time;
777         syscall(SYSCALL_CLOCK_GET_TIME, &current_time);
778
779         dirent.attributes = 0;
780         if (!(file->header.attributes & FILE_ATTR_OWNER_WRITABLE)) dirent.attributes |= FATFS_ATTR_READONLY;
781         if (file->header.attributes & FILE_ATTR_DIRECTORY) dirent.attributes |= FATFS_ATTR_DIRECTORY;
782
783         fatfs_set_entry_name(&dirent, file_name);
784         dirent.duration = 1;
785         fatfs_pack_file_time(&current_time, &dirent.creation_date, &dirent.creation_time);
786         fatfs_pack_file_time(&current_time, &dirent.modification_date, &dirent.modification_time);
787         fatfs_pack_file_time(&current_time, &dirent.last_accessed_date, NULL);
788         dirent.first_cluster_high = 0;
789         dirent.first_cluster_low = 0;
790         dirent.size = 0;
791
792         dword_t actually_written;
793         ret = device_write(volume->header.device,
794                            &dirent,
795                            fatfs_get_cluster_offset(volume, cluster) + (qword_t)(entry * sizeof(fatfs_dirent_t)),
796                            sizeof(fatfs_dirent_t),
797                            &actually_written);
798         if (ret != ERR_SUCCESS) return ret;
799     }
800
801     file->header.attributes = FILE_ATTR_OWNER_READABLE;
802     if (!(dirent.attributes & FATFS_ATTR_READONLY)) file->header.attributes |= FILE_ATTR_OWNER_WRITABLE;
803     if (dirent.attributes & FATFS_ATTR_DIRECTORY) file->header.attributes |= FILE_ATTR_DIRECTORY;
804
805     file->header.size = dirent.size;
806     file->first_cluster = dirent.first_cluster_low | (dirent.first_cluster_high << 16);
807     file->dirent_cluster = cluster;
808     file->dirent_index = entry;
809
810     init_cache(&file->cache,
811                0,
812                volume->bytes_per_sector,
813                (read_write_buffer_proc_t)fatfs_read_internal,
814                (read_write_buffer_proc_t)fatfs_write_internal);
815
816     return ret;
817 }
818
819 static dword_t fatfs_purge_file(fatfs_volume_t *volume, dword_t starting_cluster)
820 {
821     dword_t current_cluster = starting_cluster;
822
823     while (TRUE)
824     {
825         dword_t next_cluster = fatfs_get_next_cluster(volume, current_cluster);
826         fatfs_set_next_cluster(volume, current_cluster, 0);
827         current_cluster = next_cluster;
828     }
829
830     return ERR_SUCCESS;
831 }
832
833 static dword_t fatfs_unload_file(file_t *_file)
834 {
835     fatfs_file_t *file = CONTAINER_OF(_file, fatfs_file_t, header);
836     fatfs_volume_t *volume = CONTAINER_OF(file->header.volume, fatfs_volume_t, header);
837
838     if (file->header.attributes & FILE_ATTR_DELETED)
839     {
840         return fatfs_purge_file(volume, file->first_cluster);
841     }
842     else
843     {
844         return flush_cache(&file->cache, &file->header.header);
845     }
846 }
847
848 static dword_t fatfs_open_file(file_instance_t **_instance)
849 {
850     fatfs_file_t *file = CONTAINER_OF((*_instance)->global, fatfs_file_t, header);
851
852     fatfs_volume_t *volume = CONTAINER_OF(file->header.volume, fatfs_volume_t, header);
853     if (get_current_uid() != volume->owner_uid) return ERR_FORBIDDEN;
854
855     fatfs_file_instance_t *instance = (fatfs_file_instance_t*)realloc(*_instance, sizeof(fatfs_file_instance_t));
856     if (instance == NULL) return ERR_NOMEMORY;
857     *_instance = &instance->header;
858
859     instance->last_offset = 0;
860     instance->last_cluster = file->first_cluster;
861     return ERR_SUCCESS;
862 }
863
864 static dword_t fatfs_close_file(file_instance_t *_instance)
865 {
866     return ERR_SUCCESS;
867 }
868
869 static dword_t fatfs_delete_file(mounted_volume_t *_volume, const char *path, bool_t purge)
870 {
871     fatfs_volume_t *volume = CONTAINER_OF(volume, fatfs_volume_t, header);
872     if (get_current_uid() != volume->owner_uid) return ERR_FORBIDDEN;
873
874     fatfs_dirent_t dirent;
875     dword_t cluster_num;
876     dword_t entry_num;
877
878     dword_t ret = fatfs_find_entry(volume, path, &cluster_num, &entry_num, &dirent);
879     if (ret != ERR_SUCCESS) return ret;
880
881     byte_t deleted = FATFS_DELETED;
882     size_t actually_written = 0;
883
884     ret = device_write(volume->header.device,
885                        &deleted,
886                        fatfs_get_cluster_offset(volume, cluster_num) + (qword_t)(entry_num * sizeof(fatfs_dirent_t)),
887                        sizeof(byte_t),
888                        &actually_written);
889     if (ret != ERR_SUCCESS) return ret;
890
891     if (cluster_num != volume->root_dir_cluster)
892     {
893         dword_t cluster_size = volume->sectors_per_cluster * volume->bytes_per_sector;
894         dword_t entries_per_cluster = cluster_size / sizeof(fatfs_dirent_t);
895
896         byte_t *cluster_buffer = (byte_t*)malloc(cluster_size);
897         if (cluster_buffer == NULL) return ERR_SUCCESS;
898
899         ret = fatfs_read_cluster(volume, cluster_num, cluster_buffer);
900         if (ret != ERR_SUCCESS)
901         {
902             free(cluster_buffer);
903             return ERR_SUCCESS;
904         }
905
906         dword_t i;
907         bool_t in_use = FALSE;
908         fatfs_dirent_t *entries = (fatfs_dirent_t*)cluster_buffer;
909
910         for (i = 0; i < entries_per_cluster; i++)
911         {
912             if (entries[i].filename[0] != FATFS_DELETED && entries[i].filename[0] == 0)
913             {
914                 in_use = TRUE;
915                 break;
916             }
917         }
918
919         free(cluster_buffer);
920         cluster_buffer = NULL;
921         entries = NULL;
922
923         if (!in_use)
924         {
925             dword_t next_in_directory = fatfs_get_next_cluster(volume, cluster_num);
926
927             dword_t directory_start = volume->root_dir_cluster;
928             fatfs_dirent_t parent_dirent;
929             dword_t parent_dir_entry_cluster;
930             dword_t parent_dir_entry_number;
931             char *parent_path = __builtin_alloca(strlen(path) + 1);
932             strcpy(parent_path, path);
933             char *last_slash = strrchr(parent_path, '/');
934
935             if (last_slash)
936             {
937                 *last_slash = '\0';
938
939                 ret = fatfs_find_entry(volume, parent_path, &parent_dir_entry_cluster, &parent_dir_entry_number, &parent_dirent);
940                 ASSERT(ret == ERR_SUCCESS);
941
942                 directory_start = parent_dirent.first_cluster_low | (parent_dirent.first_cluster_high << 16);
943             }
944
945             if (directory_start == cluster_num)
946             {
947                 if (next_in_directory >= FATFS_INVALID_CLUSTER) next_in_directory = 0;
948                 parent_dirent.first_cluster_low = next_in_directory & 0xFFFF;
949                 parent_dirent.first_cluster_high = next_in_directory >> 16;
950
951                 device_write(volume->header.device,
952                              &parent_dirent,
953                              fatfs_get_cluster_offset(volume, parent_dir_entry_cluster)
954                              + (qword_t)(parent_dir_entry_number * sizeof(fatfs_dirent_t)),
955                              sizeof(fatfs_dirent_t),
956                              &actually_written);
957             }
958             else
959             {
960                 dword_t current_cluster = directory_start;
961
962                 while (TRUE)
963                 {
964                     dword_t next_cluster = fatfs_get_next_cluster(volume, current_cluster);
965                     ASSERT(next_cluster < FATFS_INVALID_CLUSTER);
966                     if (next_cluster == cluster_num) break;
967                 }
968
969                 fatfs_set_next_cluster(volume, current_cluster, next_in_directory);
970             }
971
972             fatfs_set_next_cluster(volume, cluster_num, 0);
973         }
974     }
975
976     if (purge) return fatfs_purge_file(volume, dirent.first_cluster_low | (dirent.first_cluster_high << 16));
977     else return TRUE;
978 }
979
980 static dword_t fatfs_read_file(file_instance_t *instance, void *buffer, qword_t offset, size_t length, size_t *bytes_read)
981 {
982     if (instance->mode & FILE_MODE_NO_CACHE)
983     {
984         return fatfs_read_internal(&instance->header, buffer, offset, length, bytes_read);
985     }
986     else
987     {
988         fatfs_file_t *file = CONTAINER_OF(instance->global, fatfs_file_t, header);
989         return read_cache(&file->cache, &instance->header, buffer, offset, length, bytes_read);
990     }
991 }
992
993 static dword_t fatfs_write_file(file_instance_t *instance, const void *buffer, qword_t offset, size_t length, size_t *bytes_written)
994 {
995     if (instance->mode & FILE_MODE_NO_CACHE)
996     {
997         return fatfs_write_internal(&instance->header, buffer, offset, length, bytes_written);
998     }
999     else
1000     {
1001         fatfs_file_t *file = CONTAINER_OF(instance->global, fatfs_file_t, header);
1002         return write_cache(&file->cache, &instance->header, buffer, offset, length, bytes_written);
1003     }
1004 }
1005
1006 static dword_t fatfs_list_dir(file_instance_t *_directory, char *filename, bool_t continue_scan)
1007 {
1008     fatfs_volume_t *volume = CONTAINER_OF(_directory->global->volume, fatfs_volume_t, header);
1009     fatfs_file_t *directory = CONTAINER_OF(_directory->global, fatfs_file_t, header);
1010     fatfs_file_instance_t *instance = CONTAINER_OF(_directory, fatfs_file_instance_t, header);
1011
1012     if (!continue_scan)
1013     {
1014         instance->last_offset = 0ULL;
1015         instance->last_cluster = directory->first_cluster;
1016     }
1017
1018     if (instance->last_cluster >= FATFS_INVALID_CLUSTER) return ERR_NOMORE;
1019
1020     fatfs_dirent_t dirent;
1021     size_t actually_read;
1022
1023     dword_t ret = device_read(volume->header.device,
1024                               &dirent,
1025                               fatfs_get_cluster_offset(volume, instance->last_cluster) + (instance->last_offset & 0x1FF),
1026                               sizeof(fatfs_dirent_t),
1027                               &actually_read);
1028     if (ret != ERR_SUCCESS) return ret;
1029
1030     instance->last_offset += sizeof(fatfs_dirent_t);
1031
1032     if ((instance->last_offset & 0x1FF) == 0)
1033     {
1034         instance->last_cluster = fatfs_get_next_cluster(volume, instance->last_cluster);
1035     }
1036
1037     fatfs_get_entry_name(&dirent, filename);
1038     return ERR_SUCCESS;
1039 }
1040
1041 static dword_t fatfs_set_file(file_t *_file, dword_t info_type, const void *buffer, size_t size)
1042 {
1043     fatfs_file_t *file = CONTAINER_OF(_file, fatfs_file_t, header);
1044
1045     switch (info_type)
1046     {
1047     case FILE_INFO_ATTRIBUTES:
1048     case FILE_INFO_TIME:
1049         return ERR_NOSYSCALL; // TODO
1050
1051     case FILE_INFO_SIZE:
1052         if (size >= sizeof(qword_t))
1053         {
1054             return fatfs_resize_file(file, *(qword_t*)buffer);
1055         }
1056         else
1057         {
1058             return ERR_SMALLBUF;
1059         }
1060
1061     default:
1062         return ERR_INVALID;
1063     }
1064 }
1065
1066 dword_t driver_load(const char *parameters)
1067 {
1068     register_filesystem_driver(&fatfs_driver);
1069     return ERR_SUCCESS;
1070 }