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