import sd-reader_source_20120612
[protos/imu.git] / fat.c
1
2 /* 
3  * Copyright (c) 2006-2012 by Roland Riegel <feedback@roland-riegel.de>
4  *
5  * This file is free software; you can redistribute it and/or modify
6  * it under the terms of either the GNU General Public License version 2
7  * or the GNU Lesser General Public License version 2.1, both as
8  * published by the Free Software Foundation.
9  */
10
11 #include "byteordering.h"
12 #include "partition.h"
13 #include "fat.h"
14 #include "fat_config.h"
15 #include "sd-reader_config.h"
16
17 #include <string.h>
18
19 #if USE_DYNAMIC_MEMORY
20     #include <stdlib.h>
21 #endif
22
23 /**
24  * \addtogroup fat FAT support
25  *
26  * This module implements FAT16/FAT32 read and write access.
27  * 
28  * The following features are supported:
29  * - File names up to 31 characters long.
30  * - Unlimited depth of subdirectories.
31  * - Short 8.3 and long filenames.
32  * - Creating and deleting files.
33  * - Reading and writing from and to files.
34  * - File resizing.
35  * - File sizes of up to 4 gigabytes.
36  * 
37  * @{
38  */
39 /**
40  * \file
41  * FAT implementation (license: GPLv2 or LGPLv2.1)
42  *
43  * \author Roland Riegel
44  */
45
46 /**
47  * \addtogroup fat_config FAT configuration
48  * Preprocessor defines to configure the FAT implementation.
49  */
50
51 /**
52  * \addtogroup fat_fs FAT access
53  * Basic functions for handling a FAT filesystem.
54  */
55
56 /**
57  * \addtogroup fat_file FAT file functions
58  * Functions for managing files.
59  */
60
61 /**
62  * \addtogroup fat_dir FAT directory functions
63  * Functions for managing directories.
64  */
65
66 /**
67  * @}
68  */
69
70 #define FAT16_CLUSTER_FREE 0x0000
71 #define FAT16_CLUSTER_RESERVED_MIN 0xfff0
72 #define FAT16_CLUSTER_RESERVED_MAX 0xfff6
73 #define FAT16_CLUSTER_BAD 0xfff7
74 #define FAT16_CLUSTER_LAST_MIN 0xfff8
75 #define FAT16_CLUSTER_LAST_MAX 0xffff
76
77 #define FAT32_CLUSTER_FREE 0x00000000
78 #define FAT32_CLUSTER_RESERVED_MIN 0x0ffffff0
79 #define FAT32_CLUSTER_RESERVED_MAX 0x0ffffff6
80 #define FAT32_CLUSTER_BAD 0x0ffffff7
81 #define FAT32_CLUSTER_LAST_MIN 0x0ffffff8
82 #define FAT32_CLUSTER_LAST_MAX 0x0fffffff
83
84 #define FAT_DIRENTRY_DELETED 0xe5
85 #define FAT_DIRENTRY_LFNLAST (1 << 6)
86 #define FAT_DIRENTRY_LFNSEQMASK ((1 << 6) - 1)
87
88 /* Each entry within the directory table has a size of 32 bytes
89  * and either contains a 8.3 DOS-style file name or a part of a
90  * long file name, which may consist of several directory table
91  * entries at once.
92  *
93  * multi-byte integer values are stored little-endian!
94  *
95  * 8.3 file name entry:
96  * ====================
97  * offset  length  description
98  *      0       8  name (space padded)
99  *      8       3  extension (space padded)
100  *     11       1  attributes (FAT_ATTRIB_*)
101  *
102  * long file name (lfn) entry ordering for a single file name:
103  * ===========================================================
104  * LFN entry n
105  *     ...
106  * LFN entry 2
107  * LFN entry 1
108  * 8.3 entry (see above)
109  * 
110  * lfn entry:
111  * ==========
112  * offset  length  description
113  *      0       1  ordinal field
114  *      1       2  unicode character 1
115  *      3       3  unicode character 2
116  *      5       3  unicode character 3
117  *      7       3  unicode character 4
118  *      9       3  unicode character 5
119  *     11       1  attribute (always 0x0f)
120  *     12       1  type (reserved, always 0)
121  *     13       1  checksum
122  *     14       2  unicode character 6
123  *     16       2  unicode character 7
124  *     18       2  unicode character 8
125  *     20       2  unicode character 9
126  *     22       2  unicode character 10
127  *     24       2  unicode character 11
128  *     26       2  cluster (unused, always 0)
129  *     28       2  unicode character 12
130  *     30       2  unicode character 13
131  * 
132  * The ordinal field contains a descending number, from n to 1.
133  * For the n'th lfn entry the ordinal field is or'ed with 0x40.
134  * For deleted lfn entries, the ordinal field is set to 0xe5.
135  */
136
137 struct fat_header_struct
138 {
139     offset_t size;
140
141     offset_t fat_offset;
142     uint32_t fat_size;
143
144     uint16_t sector_size;
145     uint16_t cluster_size;
146
147     offset_t cluster_zero_offset;
148
149     offset_t root_dir_offset;
150 #if FAT_FAT32_SUPPORT
151     cluster_t root_dir_cluster;
152 #endif
153 };
154
155 struct fat_fs_struct
156 {
157     struct partition_struct* partition;
158     struct fat_header_struct header;
159     cluster_t cluster_free;
160 };
161
162 struct fat_file_struct
163 {
164     struct fat_fs_struct* fs;
165     struct fat_dir_entry_struct dir_entry;
166     offset_t pos;
167     cluster_t pos_cluster;
168 };
169
170 struct fat_dir_struct
171 {
172     struct fat_fs_struct* fs;
173     struct fat_dir_entry_struct dir_entry;
174     cluster_t entry_cluster;
175     uint16_t entry_offset;
176 };
177
178 struct fat_read_dir_callback_arg
179 {
180     struct fat_dir_entry_struct* dir_entry;
181     uintptr_t bytes_read;
182 #if FAT_LFN_SUPPORT
183     uint8_t checksum;
184 #endif
185     uint8_t finished;
186 };
187
188 struct fat_usage_count_callback_arg
189 {
190     cluster_t cluster_count;
191     uintptr_t buffer_size;
192 };
193
194 #if !USE_DYNAMIC_MEMORY
195 static struct fat_fs_struct fat_fs_handles[FAT_FS_COUNT];
196 static struct fat_file_struct fat_file_handles[FAT_FILE_COUNT];
197 static struct fat_dir_struct fat_dir_handles[FAT_DIR_COUNT];
198 #endif
199
200 static uint8_t fat_read_header(struct fat_fs_struct* fs);
201 static cluster_t fat_get_next_cluster(const struct fat_fs_struct* fs, cluster_t cluster_num);
202 static offset_t fat_cluster_offset(const struct fat_fs_struct* fs, cluster_t cluster_num);
203 static uint8_t fat_dir_entry_read_callback(uint8_t* buffer, offset_t offset, void* p);
204 #if FAT_LFN_SUPPORT
205 static uint8_t fat_calc_83_checksum(const uint8_t* file_name_83);
206 #endif
207
208 static uint8_t fat_get_fs_free_16_callback(uint8_t* buffer, offset_t offset, void* p);
209 #if FAT_FAT32_SUPPORT
210 static uint8_t fat_get_fs_free_32_callback(uint8_t* buffer, offset_t offset, void* p);
211 #endif
212
213 #if FAT_WRITE_SUPPORT
214 static cluster_t fat_append_clusters(struct fat_fs_struct* fs, cluster_t cluster_num, cluster_t count);
215 static uint8_t fat_free_clusters(struct fat_fs_struct* fs, cluster_t cluster_num);
216 static uint8_t fat_terminate_clusters(struct fat_fs_struct* fs, cluster_t cluster_num);
217 static uint8_t fat_clear_cluster(const struct fat_fs_struct* fs, cluster_t cluster_num);
218 static uintptr_t fat_clear_cluster_callback(uint8_t* buffer, offset_t offset, void* p);
219 static offset_t fat_find_offset_for_dir_entry(struct fat_fs_struct* fs, const struct fat_dir_struct* parent, const struct fat_dir_entry_struct* dir_entry);
220 static uint8_t fat_write_dir_entry(const struct fat_fs_struct* fs, struct fat_dir_entry_struct* dir_entry);
221 #if FAT_DATETIME_SUPPORT
222 static void fat_set_file_modification_date(struct fat_dir_entry_struct* dir_entry, uint16_t year, uint8_t month, uint8_t day);
223 static void fat_set_file_modification_time(struct fat_dir_entry_struct* dir_entry, uint8_t hour, uint8_t min, uint8_t sec);
224 #endif
225 #endif
226
227 /**
228  * \ingroup fat_fs
229  * Opens a FAT filesystem.
230  *
231  * \param[in] partition Discriptor of partition on which the filesystem resides.
232  * \returns 0 on error, a FAT filesystem descriptor on success.
233  * \see fat_close
234  */
235 struct fat_fs_struct* fat_open(struct partition_struct* partition)
236 {
237     if(!partition ||
238 #if FAT_WRITE_SUPPORT
239        !partition->device_write ||
240        !partition->device_write_interval
241 #else
242        0
243 #endif
244       )
245         return 0;
246
247 #if USE_DYNAMIC_MEMORY
248     struct fat_fs_struct* fs = malloc(sizeof(*fs));
249     if(!fs)
250         return 0;
251 #else
252     struct fat_fs_struct* fs = fat_fs_handles;
253     uint8_t i;
254     for(i = 0; i < FAT_FS_COUNT; ++i)
255     {
256         if(!fs->partition)
257             break;
258
259         ++fs;
260     }
261     if(i >= FAT_FS_COUNT)
262         return 0;
263 #endif
264
265     memset(fs, 0, sizeof(*fs));
266
267     fs->partition = partition;
268     if(!fat_read_header(fs))
269     {
270 #if USE_DYNAMIC_MEMORY
271         free(fs);
272 #else
273         fs->partition = 0;
274 #endif
275         return 0;
276     }
277     
278     return fs;
279 }
280
281 /**
282  * \ingroup fat_fs
283  * Closes a FAT filesystem.
284  *
285  * When this function returns, the given filesystem descriptor
286  * will be invalid.
287  *
288  * \param[in] fs The filesystem to close.
289  * \see fat_open
290  */
291 void fat_close(struct fat_fs_struct* fs)
292 {
293     if(!fs)
294         return;
295
296 #if USE_DYNAMIC_MEMORY
297     free(fs);
298 #else
299     fs->partition = 0;
300 #endif
301 }
302
303 /**
304  * \ingroup fat_fs
305  * Reads and parses the header of a FAT filesystem.
306  *
307  * \param[in,out] fs The filesystem for which to parse the header.
308  * \returns 0 on failure, 1 on success.
309  */
310 uint8_t fat_read_header(struct fat_fs_struct* fs)
311 {
312     if(!fs)
313         return 0;
314
315     struct partition_struct* partition = fs->partition;
316     if(!partition)
317         return 0;
318
319     /* read fat parameters */
320 #if FAT_FAT32_SUPPORT
321     uint8_t buffer[37];
322 #else
323     uint8_t buffer[25];
324 #endif
325     offset_t partition_offset = (offset_t) partition->offset * 512;
326     if(!partition->device_read(partition_offset + 0x0b, buffer, sizeof(buffer)))
327         return 0;
328
329     uint16_t bytes_per_sector = read16(&buffer[0x00]);
330     uint16_t reserved_sectors = read16(&buffer[0x03]);
331     uint8_t sectors_per_cluster = buffer[0x02];
332     uint8_t fat_copies = buffer[0x05];
333     uint16_t max_root_entries = read16(&buffer[0x06]);
334     uint16_t sector_count_16 = read16(&buffer[0x08]);
335     uint16_t sectors_per_fat = read16(&buffer[0x0b]);
336     uint32_t sector_count = read32(&buffer[0x15]);
337 #if FAT_FAT32_SUPPORT
338     uint32_t sectors_per_fat32 = read32(&buffer[0x19]);
339     uint32_t cluster_root_dir = read32(&buffer[0x21]);
340 #endif
341
342     if(sector_count == 0)
343     {
344         if(sector_count_16 == 0)
345             /* illegal volume size */
346             return 0;
347         else
348             sector_count = sector_count_16;
349     }
350 #if FAT_FAT32_SUPPORT
351     if(sectors_per_fat != 0)
352         sectors_per_fat32 = sectors_per_fat;
353     else if(sectors_per_fat32 == 0)
354         /* this is neither FAT16 nor FAT32 */
355         return 0;
356 #else
357     if(sectors_per_fat == 0)
358         /* this is not a FAT16 */
359         return 0;
360 #endif
361
362     /* determine the type of FAT we have here */
363     uint32_t data_sector_count = sector_count
364                                  - reserved_sectors
365 #if FAT_FAT32_SUPPORT
366                                  - sectors_per_fat32 * fat_copies
367 #else
368                                  - (uint32_t) sectors_per_fat * fat_copies
369 #endif
370                                  - ((max_root_entries * 32 + bytes_per_sector - 1) / bytes_per_sector);
371     uint32_t data_cluster_count = data_sector_count / sectors_per_cluster;
372     if(data_cluster_count < 4085)
373         /* this is a FAT12, not supported */
374         return 0;
375     else if(data_cluster_count < 65525)
376         /* this is a FAT16 */
377         partition->type = PARTITION_TYPE_FAT16;
378     else
379         /* this is a FAT32 */
380         partition->type = PARTITION_TYPE_FAT32;
381
382     /* fill header information */
383     struct fat_header_struct* header = &fs->header;
384     memset(header, 0, sizeof(*header));
385     
386     header->size = (offset_t) sector_count * bytes_per_sector;
387
388     header->fat_offset = /* jump to partition */
389                          partition_offset +
390                          /* jump to fat */
391                          (offset_t) reserved_sectors * bytes_per_sector;
392     header->fat_size = (data_cluster_count + 2) * (partition->type == PARTITION_TYPE_FAT16 ? 2 : 4);
393
394     header->sector_size = bytes_per_sector;
395     header->cluster_size = (uint16_t) bytes_per_sector * sectors_per_cluster;
396
397 #if FAT_FAT32_SUPPORT
398     if(partition->type == PARTITION_TYPE_FAT16)
399 #endif
400     {
401         header->root_dir_offset = /* jump to fats */
402                                   header->fat_offset +
403                                   /* jump to root directory entries */
404                                   (offset_t) fat_copies * sectors_per_fat * bytes_per_sector;
405
406         header->cluster_zero_offset = /* jump to root directory entries */
407                                       header->root_dir_offset +
408                                       /* skip root directory entries */
409                                       (offset_t) max_root_entries * 32;
410     }
411 #if FAT_FAT32_SUPPORT
412     else
413     {
414         header->cluster_zero_offset = /* jump to fats */
415                                       header->fat_offset +
416                                       /* skip fats */
417                                       (offset_t) fat_copies * sectors_per_fat32 * bytes_per_sector;
418
419         header->root_dir_cluster = cluster_root_dir;
420     }
421 #endif
422
423     return 1;
424 }
425
426 /**
427  * \ingroup fat_fs
428  * Retrieves the next following cluster of a given cluster.
429  *
430  * Using the filesystem file allocation table, this function returns
431  * the number of the cluster containing the data directly following
432  * the data within the cluster with the given number.
433  *
434  * \param[in] fs The filesystem for which to determine the next cluster.
435  * \param[in] cluster_num The number of the cluster for which to determine its successor.
436  * \returns The wanted cluster number, or 0 on error.
437  */
438 cluster_t fat_get_next_cluster(const struct fat_fs_struct* fs, cluster_t cluster_num)
439 {
440     if(!fs || cluster_num < 2)
441         return 0;
442
443 #if FAT_FAT32_SUPPORT
444     if(fs->partition->type == PARTITION_TYPE_FAT32)
445     {
446         /* read appropriate fat entry */
447         uint32_t fat_entry;
448         if(!fs->partition->device_read(fs->header.fat_offset + (offset_t) cluster_num * sizeof(fat_entry), (uint8_t*) &fat_entry, sizeof(fat_entry)))
449             return 0;
450
451         /* determine next cluster from fat */
452         cluster_num = ltoh32(fat_entry);
453         
454         if(cluster_num == FAT32_CLUSTER_FREE ||
455            cluster_num == FAT32_CLUSTER_BAD ||
456            (cluster_num >= FAT32_CLUSTER_RESERVED_MIN && cluster_num <= FAT32_CLUSTER_RESERVED_MAX) ||
457            (cluster_num >= FAT32_CLUSTER_LAST_MIN && cluster_num <= FAT32_CLUSTER_LAST_MAX))
458             return 0;
459     }
460     else
461 #endif
462     {
463         /* read appropriate fat entry */
464         uint16_t fat_entry;
465         if(!fs->partition->device_read(fs->header.fat_offset + (offset_t) cluster_num * sizeof(fat_entry), (uint8_t*) &fat_entry, sizeof(fat_entry)))
466             return 0;
467
468         /* determine next cluster from fat */
469         cluster_num = ltoh16(fat_entry);
470         
471         if(cluster_num == FAT16_CLUSTER_FREE ||
472            cluster_num == FAT16_CLUSTER_BAD ||
473            (cluster_num >= FAT16_CLUSTER_RESERVED_MIN && cluster_num <= FAT16_CLUSTER_RESERVED_MAX) ||
474            (cluster_num >= FAT16_CLUSTER_LAST_MIN && cluster_num <= FAT16_CLUSTER_LAST_MAX))
475             return 0;
476     }
477
478     return cluster_num;
479 }
480
481 #if DOXYGEN || FAT_WRITE_SUPPORT
482 /**
483  * \ingroup fat_fs
484  * Appends a new cluster chain to an existing one.
485  *
486  * Set cluster_num to zero to create a completely new one.
487  *
488  * \param[in] fs The file system on which to operate.
489  * \param[in] cluster_num The cluster to which to append the new chain.
490  * \param[in] count The number of clusters to allocate.
491  * \returns 0 on failure, the number of the first new cluster on success.
492  */
493 cluster_t fat_append_clusters(struct fat_fs_struct* fs, cluster_t cluster_num, cluster_t count)
494 {
495     if(!fs)
496         return 0;
497
498     device_read_t device_read = fs->partition->device_read;
499     device_write_t device_write = fs->partition->device_write;
500     offset_t fat_offset = fs->header.fat_offset;
501     cluster_t count_left = count;
502     cluster_t cluster_current = fs->cluster_free;
503     cluster_t cluster_next = 0;
504     cluster_t cluster_count;
505     uint16_t fat_entry16;
506 #if FAT_FAT32_SUPPORT
507     uint32_t fat_entry32;
508     uint8_t is_fat32 = (fs->partition->type == PARTITION_TYPE_FAT32);
509
510     if(is_fat32)
511         cluster_count = fs->header.fat_size / sizeof(fat_entry32);
512     else
513 #endif
514         cluster_count = fs->header.fat_size / sizeof(fat_entry16);
515
516     fs->cluster_free = 0;
517     for(cluster_t cluster_left = cluster_count; cluster_left > 0; --cluster_left, ++cluster_current)
518     {
519         if(cluster_current < 2 || cluster_current >= cluster_count)
520             cluster_current = 2;
521
522 #if FAT_FAT32_SUPPORT
523         if(is_fat32)
524         {
525             if(!device_read(fat_offset + (offset_t) cluster_current * sizeof(fat_entry32), (uint8_t*) &fat_entry32, sizeof(fat_entry32)))
526                 return 0;
527         }
528         else
529 #endif
530         {
531             if(!device_read(fat_offset + (offset_t) cluster_current * sizeof(fat_entry16), (uint8_t*) &fat_entry16, sizeof(fat_entry16)))
532                 return 0;
533         }
534
535 #if FAT_FAT32_SUPPORT
536         if(is_fat32)
537         {
538             /* check if this is a free cluster */
539             if(fat_entry32 != HTOL32(FAT32_CLUSTER_FREE))
540                 continue;
541
542             /* If we don't need this free cluster for the
543              * current allocation, we keep it in mind for
544              * the next time.
545              */
546             if(count_left == 0)
547             {
548                 fs->cluster_free = cluster_current;
549                 break;
550             }
551
552             /* allocate cluster */
553             if(cluster_next == 0)
554                 fat_entry32 = HTOL32(FAT32_CLUSTER_LAST_MAX);
555             else
556                 fat_entry32 = htol32(cluster_next);
557
558             if(!device_write(fat_offset + (offset_t) cluster_current * sizeof(fat_entry32), (uint8_t*) &fat_entry32, sizeof(fat_entry32)))
559                 break;
560         }
561         else
562 #endif
563         {
564             /* check if this is a free cluster */
565             if(fat_entry16 != HTOL16(FAT16_CLUSTER_FREE))
566                 continue;
567
568             /* If we don't need this free cluster for the
569              * current allocation, we keep it in mind for
570              * the next time.
571              */
572             if(count_left == 0)
573             {
574                 fs->cluster_free = cluster_current;
575                 break;
576             }
577
578             /* allocate cluster */
579             if(cluster_next == 0)
580                 fat_entry16 = HTOL16(FAT16_CLUSTER_LAST_MAX);
581             else
582                 fat_entry16 = htol16((uint16_t) cluster_next);
583
584             if(!device_write(fat_offset + (offset_t) cluster_current * sizeof(fat_entry16), (uint8_t*) &fat_entry16, sizeof(fat_entry16)))
585                 break;
586         }
587
588         cluster_next = cluster_current;
589         --count_left;
590     }
591
592     do
593     {
594         if(count_left > 0)
595             break;
596
597         /* We allocated a new cluster chain. Now join
598          * it with the existing one (if any).
599          */
600         if(cluster_num >= 2)
601         {
602 #if FAT_FAT32_SUPPORT
603             if(is_fat32)
604             {
605                 fat_entry32 = htol32(cluster_next);
606
607                 if(!device_write(fat_offset + (offset_t) cluster_num * sizeof(fat_entry32), (uint8_t*) &fat_entry32, sizeof(fat_entry32)))
608                     break;
609             }
610             else
611 #endif
612             {
613                 fat_entry16 = htol16((uint16_t) cluster_next);
614
615                 if(!device_write(fat_offset + (offset_t) cluster_num * sizeof(fat_entry16), (uint8_t*) &fat_entry16, sizeof(fat_entry16)))
616                     break;
617             }
618         }
619
620         return cluster_next;
621
622     } while(0);
623
624     /* No space left on device or writing error.
625      * Free up all clusters already allocated.
626      */
627     fat_free_clusters(fs, cluster_next);
628
629     return 0;
630 }
631 #endif
632
633 #if DOXYGEN || FAT_WRITE_SUPPORT
634 /**
635  * \ingroup fat_fs
636  * Frees a cluster chain, or a part thereof.
637  *
638  * Marks the specified cluster and all clusters which are sequentially
639  * referenced by it as free. They may then be used again for future
640  * file allocations.
641  *
642  * \note If this function is used for freeing just a part of a cluster
643  *       chain, the new end of the chain is not correctly terminated
644  *       within the FAT. Use fat_terminate_clusters() instead.
645  *
646  * \param[in] fs The filesystem on which to operate.
647  * \param[in] cluster_num The starting cluster of the chain which to free.
648  * \returns 0 on failure, 1 on success.
649  * \see fat_terminate_clusters
650  */
651 uint8_t fat_free_clusters(struct fat_fs_struct* fs, cluster_t cluster_num)
652 {
653     if(!fs || cluster_num < 2)
654         return 0;
655
656     offset_t fat_offset = fs->header.fat_offset;
657 #if FAT_FAT32_SUPPORT
658     if(fs->partition->type == PARTITION_TYPE_FAT32)
659     {
660         uint32_t fat_entry;
661         while(cluster_num)
662         {
663             if(!fs->partition->device_read(fat_offset + (offset_t) cluster_num * sizeof(fat_entry), (uint8_t*) &fat_entry, sizeof(fat_entry)))
664                 return 0;
665
666             /* get next cluster of current cluster before freeing current cluster */
667             uint32_t cluster_num_next = ltoh32(fat_entry);
668
669             if(cluster_num_next == FAT32_CLUSTER_FREE)
670                 return 1;
671             if(cluster_num_next == FAT32_CLUSTER_BAD ||
672                (cluster_num_next >= FAT32_CLUSTER_RESERVED_MIN &&
673                 cluster_num_next <= FAT32_CLUSTER_RESERVED_MAX
674                )
675               )
676                 return 0;
677             if(cluster_num_next >= FAT32_CLUSTER_LAST_MIN && cluster_num_next <= FAT32_CLUSTER_LAST_MAX)
678                 cluster_num_next = 0;
679
680             /* We know we will free the cluster, so remember it as
681              * free for the next allocation.
682              */
683             if(!fs->cluster_free)
684                 fs->cluster_free = cluster_num;
685
686             /* free cluster */
687             fat_entry = HTOL32(FAT32_CLUSTER_FREE);
688             fs->partition->device_write(fat_offset + (offset_t) cluster_num * sizeof(fat_entry), (uint8_t*) &fat_entry, sizeof(fat_entry));
689
690             /* We continue in any case here, even if freeing the cluster failed.
691              * The cluster is lost, but maybe we can still free up some later ones.
692              */
693
694             cluster_num = cluster_num_next;
695         }
696     }
697     else
698 #endif
699     {
700         uint16_t fat_entry;
701         while(cluster_num)
702         {
703             if(!fs->partition->device_read(fat_offset + (offset_t) cluster_num * sizeof(fat_entry), (uint8_t*) &fat_entry, sizeof(fat_entry)))
704                 return 0;
705
706             /* get next cluster of current cluster before freeing current cluster */
707             uint16_t cluster_num_next = ltoh16(fat_entry);
708
709             if(cluster_num_next == FAT16_CLUSTER_FREE)
710                 return 1;
711             if(cluster_num_next == FAT16_CLUSTER_BAD ||
712                (cluster_num_next >= FAT16_CLUSTER_RESERVED_MIN &&
713                 cluster_num_next <= FAT16_CLUSTER_RESERVED_MAX
714                )
715               )
716                 return 0;
717             if(cluster_num_next >= FAT16_CLUSTER_LAST_MIN && cluster_num_next <= FAT16_CLUSTER_LAST_MAX)
718                 cluster_num_next = 0;
719
720             /* free cluster */
721             fat_entry = HTOL16(FAT16_CLUSTER_FREE);
722             fs->partition->device_write(fat_offset + (offset_t) cluster_num * sizeof(fat_entry), (uint8_t*) &fat_entry, sizeof(fat_entry));
723
724             /* We continue in any case here, even if freeing the cluster failed.
725              * The cluster is lost, but maybe we can still free up some later ones.
726              */
727
728             cluster_num = cluster_num_next;
729         }
730     }
731
732     return 1;
733 }
734 #endif
735
736 #if DOXYGEN || FAT_WRITE_SUPPORT
737 /**
738  * \ingroup fat_fs
739  * Frees a part of a cluster chain and correctly terminates the rest.
740  *
741  * Marks the specified cluster as the new end of a cluster chain and
742  * frees all following clusters.
743  *
744  * \param[in] fs The filesystem on which to operate.
745  * \param[in] cluster_num The new end of the cluster chain.
746  * \returns 0 on failure, 1 on success.
747  * \see fat_free_clusters
748  */
749 uint8_t fat_terminate_clusters(struct fat_fs_struct* fs, cluster_t cluster_num)
750 {
751     if(!fs || cluster_num < 2)
752         return 0;
753
754     /* fetch next cluster before overwriting the cluster entry */
755     cluster_t cluster_num_next = fat_get_next_cluster(fs, cluster_num);
756
757     /* mark cluster as the last one */
758 #if FAT_FAT32_SUPPORT
759     if(fs->partition->type == PARTITION_TYPE_FAT32)
760     {
761         uint32_t fat_entry = HTOL32(FAT32_CLUSTER_LAST_MAX);
762         if(!fs->partition->device_write(fs->header.fat_offset + (offset_t) cluster_num * sizeof(fat_entry), (uint8_t*) &fat_entry, sizeof(fat_entry)))
763             return 0;
764     }
765     else
766 #endif
767     {
768         uint16_t fat_entry = HTOL16(FAT16_CLUSTER_LAST_MAX);
769         if(!fs->partition->device_write(fs->header.fat_offset + (offset_t) cluster_num * sizeof(fat_entry), (uint8_t*) &fat_entry, sizeof(fat_entry)))
770             return 0;
771     }
772
773     /* free remaining clusters */
774     if(cluster_num_next)
775         return fat_free_clusters(fs, cluster_num_next);
776     else
777         return 1;
778 }
779 #endif
780
781 #if DOXYGEN || FAT_WRITE_SUPPORT
782 /**
783  * \ingroup fat_fs
784  * Clears a single cluster.
785  *
786  * The complete cluster is filled with zeros.
787  *
788  * \param[in] fs The filesystem on which to operate.
789  * \param[in] cluster_num The cluster to clear.
790  * \returns 0 on failure, 1 on success.
791  */
792 uint8_t fat_clear_cluster(const struct fat_fs_struct* fs, cluster_t cluster_num)
793 {
794     if(cluster_num < 2)
795         return 0;
796
797     offset_t cluster_offset = fat_cluster_offset(fs, cluster_num);
798
799     uint8_t zero[16];
800     memset(zero, 0, sizeof(zero));
801     return fs->partition->device_write_interval(cluster_offset,
802                                                 zero,
803                                                 fs->header.cluster_size,
804                                                 fat_clear_cluster_callback,
805                                                 0
806                                                );
807 }
808 #endif
809
810 #if DOXYGEN || FAT_WRITE_SUPPORT
811 /**
812  * \ingroup fat_fs
813  * Callback function for clearing a cluster.
814  */
815 uintptr_t fat_clear_cluster_callback(uint8_t* buffer, offset_t offset, void* p)
816 {
817     return 16;
818 }
819 #endif
820
821 /**
822  * \ingroup fat_fs
823  * Calculates the offset of the specified cluster.
824  *
825  * \param[in] fs The filesystem on which to operate.
826  * \param[in] cluster_num The cluster whose offset to calculate.
827  * \returns The cluster offset.
828  */
829 offset_t fat_cluster_offset(const struct fat_fs_struct* fs, cluster_t cluster_num)
830 {
831     if(!fs || cluster_num < 2)
832         return 0;
833
834     return fs->header.cluster_zero_offset + (offset_t) (cluster_num - 2) * fs->header.cluster_size;
835 }
836
837 /**
838  * \ingroup fat_file
839  * Retrieves the directory entry of a path.
840  *
841  * The given path may both describe a file or a directory.
842  *
843  * \param[in] fs The FAT filesystem on which to search.
844  * \param[in] path The path of which to read the directory entry.
845  * \param[out] dir_entry The directory entry to fill.
846  * \returns 0 on failure, 1 on success.
847  * \see fat_read_dir
848  */
849 uint8_t fat_get_dir_entry_of_path(struct fat_fs_struct* fs, const char* path, struct fat_dir_entry_struct* dir_entry)
850 {
851     if(!fs || !path || path[0] == '\0' || !dir_entry)
852         return 0;
853
854     if(path[0] == '/')
855         ++path;
856
857     /* begin with the root directory */
858     memset(dir_entry, 0, sizeof(*dir_entry));
859     dir_entry->attributes = FAT_ATTRIB_DIR;
860
861     while(1)
862     {
863         if(path[0] == '\0')
864             return 1;
865
866         struct fat_dir_struct* dd = fat_open_dir(fs, dir_entry);
867         if(!dd)
868             break;
869
870         /* extract the next hierarchy we will search for */
871         const char* sub_path = strchr(path, '/');
872         uint8_t length_to_sep;
873         if(sub_path)
874         {
875             length_to_sep = sub_path - path;
876             ++sub_path;
877         }
878         else
879         {
880             length_to_sep = strlen(path);
881             sub_path = path + length_to_sep;
882         }
883         
884         /* read directory entries */
885         while(fat_read_dir(dd, dir_entry))
886         {
887             /* check if we have found the next hierarchy */
888             if((strlen(dir_entry->long_name) != length_to_sep ||
889                 strncmp(path, dir_entry->long_name, length_to_sep) != 0))
890                 continue;
891
892             fat_close_dir(dd);
893             dd = 0;
894
895             if(path[length_to_sep] == '\0')
896                 /* we iterated through the whole path and have found the file */
897                 return 1;
898
899             if(dir_entry->attributes & FAT_ATTRIB_DIR)
900             {
901                 /* we found a parent directory of the file we are searching for */
902                 path = sub_path;
903                 break;
904             }
905
906             /* a parent of the file exists, but not the file itself */
907             return 0;
908         }
909
910         fat_close_dir(dd);
911     }
912     
913     return 0;
914 }
915
916 /**
917  * \ingroup fat_file
918  * Opens a file on a FAT filesystem.
919  *
920  * \param[in] fs The filesystem on which the file to open lies.
921  * \param[in] dir_entry The directory entry of the file to open.
922  * \returns The file handle, or 0 on failure.
923  * \see fat_close_file
924  */
925 struct fat_file_struct* fat_open_file(struct fat_fs_struct* fs, const struct fat_dir_entry_struct* dir_entry)
926 {
927     if(!fs || !dir_entry || (dir_entry->attributes & FAT_ATTRIB_DIR))
928         return 0;
929
930 #if USE_DYNAMIC_MEMORY
931     struct fat_file_struct* fd = malloc(sizeof(*fd));
932     if(!fd)
933         return 0;
934 #else
935     struct fat_file_struct* fd = fat_file_handles;
936     uint8_t i;
937     for(i = 0; i < FAT_FILE_COUNT; ++i)
938     {
939         if(!fd->fs)
940             break;
941
942         ++fd;
943     }
944     if(i >= FAT_FILE_COUNT)
945         return 0;
946 #endif
947     
948     memcpy(&fd->dir_entry, dir_entry, sizeof(*dir_entry));
949     fd->fs = fs;
950     fd->pos = 0;
951     fd->pos_cluster = dir_entry->cluster;
952
953     return fd;
954 }
955
956 /**
957  * \ingroup fat_file
958  * Closes a file.
959  *
960  * \param[in] fd The file handle of the file to close.
961  * \see fat_open_file
962  */
963 void fat_close_file(struct fat_file_struct* fd)
964 {
965     if(fd)
966     {
967 #if FAT_DELAY_DIRENTRY_UPDATE
968         /* write directory entry */
969         fat_write_dir_entry(fd->fs, &fd->dir_entry);
970 #endif
971
972 #if USE_DYNAMIC_MEMORY
973         free(fd);
974 #else
975         fd->fs = 0;
976 #endif
977     }
978 }
979
980 /**
981  * \ingroup fat_file
982  * Reads data from a file.
983  * 
984  * The data requested is read from the current file location.
985  *
986  * \param[in] fd The file handle of the file from which to read.
987  * \param[out] buffer The buffer into which to write.
988  * \param[in] buffer_len The amount of data to read.
989  * \returns The number of bytes read, 0 on end of file, or -1 on failure.
990  * \see fat_write_file
991  */
992 intptr_t fat_read_file(struct fat_file_struct* fd, uint8_t* buffer, uintptr_t buffer_len)
993 {
994     /* check arguments */
995     if(!fd || !buffer || buffer_len < 1)
996         return -1;
997
998     /* determine number of bytes to read */
999     if(fd->pos + buffer_len > fd->dir_entry.file_size)
1000         buffer_len = fd->dir_entry.file_size - fd->pos;
1001     if(buffer_len == 0)
1002         return 0;
1003     
1004     uint16_t cluster_size = fd->fs->header.cluster_size;
1005     cluster_t cluster_num = fd->pos_cluster;
1006     uintptr_t buffer_left = buffer_len;
1007     uint16_t first_cluster_offset = (uint16_t) (fd->pos & (cluster_size - 1));
1008
1009     /* find cluster in which to start reading */
1010     if(!cluster_num)
1011     {
1012         cluster_num = fd->dir_entry.cluster;
1013         
1014         if(!cluster_num)
1015         {
1016             if(!fd->pos)
1017                 return 0;
1018             else
1019                 return -1;
1020         }
1021
1022         if(fd->pos)
1023         {
1024             uint32_t pos = fd->pos;
1025             while(pos >= cluster_size)
1026             {
1027                 pos -= cluster_size;
1028                 cluster_num = fat_get_next_cluster(fd->fs, cluster_num);
1029                 if(!cluster_num)
1030                     return -1;
1031             }
1032         }
1033     }
1034     
1035     /* read data */
1036     do
1037     {
1038         /* calculate data size to copy from cluster */
1039         offset_t cluster_offset = fat_cluster_offset(fd->fs, cluster_num) + first_cluster_offset;
1040         uint16_t copy_length = cluster_size - first_cluster_offset;
1041         if(copy_length > buffer_left)
1042             copy_length = buffer_left;
1043
1044         /* read data */
1045         if(!fd->fs->partition->device_read(cluster_offset, buffer, copy_length))
1046             return buffer_len - buffer_left;
1047
1048         /* calculate new file position */
1049         buffer += copy_length;
1050         buffer_left -= copy_length;
1051         fd->pos += copy_length;
1052
1053         if(first_cluster_offset + copy_length >= cluster_size)
1054         {
1055             /* we are on a cluster boundary, so get the next cluster */
1056             if((cluster_num = fat_get_next_cluster(fd->fs, cluster_num)))
1057             {
1058                 first_cluster_offset = 0;
1059             }
1060             else
1061             {
1062                 fd->pos_cluster = 0;
1063                 return buffer_len - buffer_left;
1064             }
1065         }
1066
1067         fd->pos_cluster = cluster_num;
1068
1069     } while(buffer_left > 0); /* check if we are done */
1070
1071     return buffer_len;
1072 }
1073
1074 #if DOXYGEN || FAT_WRITE_SUPPORT
1075 /**
1076  * \ingroup fat_file
1077  * Writes data to a file.
1078  * 
1079  * The data is written to the current file location.
1080  *
1081  * \param[in] fd The file handle of the file to which to write.
1082  * \param[in] buffer The buffer from which to read the data to be written.
1083  * \param[in] buffer_len The amount of data to write.
1084  * \returns The number of bytes written (0 or something less than \c buffer_len on disk full) or -1 on failure.
1085  * \see fat_read_file
1086  */
1087 intptr_t fat_write_file(struct fat_file_struct* fd, const uint8_t* buffer, uintptr_t buffer_len)
1088 {
1089     /* check arguments */
1090     if(!fd || !buffer || buffer_len < 1)
1091         return -1;
1092     if(fd->pos > fd->dir_entry.file_size)
1093         return -1;
1094
1095     uint16_t cluster_size = fd->fs->header.cluster_size;
1096     cluster_t cluster_num = fd->pos_cluster;
1097     uintptr_t buffer_left = buffer_len;
1098     uint16_t first_cluster_offset = (uint16_t) (fd->pos & (cluster_size - 1));
1099
1100     /* find cluster in which to start writing */
1101     if(!cluster_num)
1102     {
1103         cluster_num = fd->dir_entry.cluster;
1104         
1105         if(!cluster_num)
1106         {
1107             if(!fd->pos)
1108             {
1109                 /* empty file */
1110                 fd->dir_entry.cluster = cluster_num = fat_append_clusters(fd->fs, 0, 1);
1111                 if(!cluster_num)
1112                     return 0;
1113             }
1114             else
1115             {
1116                 return -1;
1117             }
1118         }
1119
1120         if(fd->pos)
1121         {
1122             uint32_t pos = fd->pos;
1123             cluster_t cluster_num_next;
1124             while(pos >= cluster_size)
1125             {
1126                 pos -= cluster_size;
1127                 cluster_num_next = fat_get_next_cluster(fd->fs, cluster_num);
1128                 if(!cluster_num_next)
1129                 {
1130                     if(pos != 0)
1131                         return -1; /* current file position points beyond end of file */
1132
1133                     /* the file exactly ends on a cluster boundary, and we append to it */
1134                     cluster_num_next = fat_append_clusters(fd->fs, cluster_num, 1);
1135                     if(!cluster_num_next)
1136                         return 0;
1137                 }
1138
1139                 cluster_num = cluster_num_next;
1140             }
1141         }
1142     }
1143     
1144     /* write data */
1145     do
1146     {
1147         /* calculate data size to write to cluster */
1148         offset_t cluster_offset = fat_cluster_offset(fd->fs, cluster_num) + first_cluster_offset;
1149         uint16_t write_length = cluster_size - first_cluster_offset;
1150         if(write_length > buffer_left)
1151             write_length = buffer_left;
1152
1153         /* write data which fits into the current cluster */
1154         if(!fd->fs->partition->device_write(cluster_offset, buffer, write_length))
1155             break;
1156
1157         /* calculate new file position */
1158         buffer += write_length;
1159         buffer_left -= write_length;
1160         fd->pos += write_length;
1161
1162         if(first_cluster_offset + write_length >= cluster_size)
1163         {
1164             /* we are on a cluster boundary, so get the next cluster */
1165             cluster_t cluster_num_next = fat_get_next_cluster(fd->fs, cluster_num);
1166             if(!cluster_num_next && buffer_left > 0)
1167                 /* we reached the last cluster, append a new one */
1168                 cluster_num_next = fat_append_clusters(fd->fs, cluster_num, 1);
1169             if(!cluster_num_next)
1170             {
1171                 fd->pos_cluster = 0;
1172                 break;
1173             }
1174
1175             cluster_num = cluster_num_next;
1176             first_cluster_offset = 0;
1177         }
1178
1179         fd->pos_cluster = cluster_num;
1180
1181     } while(buffer_left > 0); /* check if we are done */
1182
1183     /* update directory entry */
1184     if(fd->pos > fd->dir_entry.file_size)
1185     {
1186 #if !FAT_DELAY_DIRENTRY_UPDATE
1187         uint32_t size_old = fd->dir_entry.file_size;
1188 #endif
1189
1190         /* update file size */
1191         fd->dir_entry.file_size = fd->pos;
1192
1193 #if !FAT_DELAY_DIRENTRY_UPDATE
1194         /* write directory entry */
1195         if(!fat_write_dir_entry(fd->fs, &fd->dir_entry))
1196         {
1197             /* We do not return an error here since we actually wrote
1198              * some data to disk. So we calculate the amount of data
1199              * we wrote to disk and which lies within the old file size.
1200              */
1201             buffer_left = fd->pos - size_old;
1202             fd->pos = size_old;
1203         }
1204 #endif
1205     }
1206
1207     return buffer_len - buffer_left;
1208 }
1209 #endif
1210
1211 /**
1212  * \ingroup fat_file
1213  * Repositions the read/write file offset.
1214  *
1215  * Changes the file offset where the next call to fat_read_file()
1216  * or fat_write_file() starts reading/writing.
1217  *
1218  * If the new offset is beyond the end of the file, fat_resize_file()
1219  * is implicitly called, i.e. the file is expanded.
1220  *
1221  * The new offset can be given in different ways determined by
1222  * the \c whence parameter:
1223  * - \b FAT_SEEK_SET: \c *offset is relative to the beginning of the file.
1224  * - \b FAT_SEEK_CUR: \c *offset is relative to the current file position.
1225  * - \b FAT_SEEK_END: \c *offset is relative to the end of the file.
1226  *
1227  * The resulting absolute offset is written to the location the \c offset
1228  * parameter points to.
1229  *
1230  * Calling this function can also be used to retrieve the current file position:
1231    \code
1232    int32_t file_pos = 0;
1233    if(!fat_seek_file(fd, &file_pos, FAT_SEEK_CUR))
1234    {
1235        // error
1236    }
1237    // file_pos now contains the absolute file position
1238    \endcode
1239  * 
1240  * \param[in] fd The file decriptor of the file on which to seek.
1241  * \param[in,out] offset A pointer to the new offset, as affected by the \c whence
1242  *                   parameter. The function writes the new absolute offset
1243  *                   to this location before it returns.
1244  * \param[in] whence Affects the way \c offset is interpreted, see above.
1245  * \returns 0 on failure, 1 on success.
1246  */
1247 uint8_t fat_seek_file(struct fat_file_struct* fd, int32_t* offset, uint8_t whence)
1248 {
1249     if(!fd || !offset)
1250         return 0;
1251
1252     uint32_t new_pos = fd->pos;
1253     switch(whence)
1254     {
1255         case FAT_SEEK_SET:
1256             new_pos = *offset;
1257             break;
1258         case FAT_SEEK_CUR:
1259             new_pos += *offset;
1260             break;
1261         case FAT_SEEK_END:
1262             new_pos = fd->dir_entry.file_size + *offset;
1263             break;
1264         default:
1265             return 0;
1266     }
1267
1268     if(new_pos > fd->dir_entry.file_size
1269 #if FAT_WRITE_SUPPORT
1270        && !fat_resize_file(fd, new_pos)
1271 #endif
1272        )
1273         return 0;
1274
1275     fd->pos = new_pos;
1276     fd->pos_cluster = 0;
1277
1278     *offset = (int32_t) new_pos;
1279     return 1;
1280 }
1281
1282 #if DOXYGEN || FAT_WRITE_SUPPORT
1283 /**
1284  * \ingroup fat_file
1285  * Resizes a file to have a specific size.
1286  *
1287  * Enlarges or shrinks the file pointed to by the file descriptor to have
1288  * exactly the specified size.
1289  *
1290  * If the file is truncated, all bytes having an equal or larger offset
1291  * than the given size are lost. If the file is expanded, the additional
1292  * bytes are allocated.
1293  *
1294  * \note Please be aware that this function just allocates or deallocates disk
1295  * space, it does not explicitely clear it. To avoid data leakage, this
1296  * must be done manually.
1297  *
1298  * \param[in] fd The file decriptor of the file which to resize.
1299  * \param[in] size The new size of the file.
1300  * \returns 0 on failure, 1 on success.
1301  */
1302 uint8_t fat_resize_file(struct fat_file_struct* fd, uint32_t size)
1303 {
1304     if(!fd)
1305         return 0;
1306
1307     cluster_t cluster_num = fd->dir_entry.cluster;
1308     uint16_t cluster_size = fd->fs->header.cluster_size;
1309     uint32_t size_new = size;
1310
1311     do
1312     {
1313         if(cluster_num == 0 && size_new == 0)
1314             /* the file stays empty */
1315             break;
1316
1317         /* seek to the next cluster as long as we need the space */
1318         while(size_new > cluster_size)
1319         {
1320             /* get next cluster of file */
1321             cluster_t cluster_num_next = fat_get_next_cluster(fd->fs, cluster_num);
1322             if(cluster_num_next)
1323             {
1324                 cluster_num = cluster_num_next;
1325                 size_new -= cluster_size;
1326             }
1327             else
1328             {
1329                 break;
1330             }
1331         }
1332
1333         if(size_new > cluster_size || cluster_num == 0)
1334         {
1335             /* Allocate new cluster chain and append
1336              * it to the existing one, if available.
1337              */
1338             cluster_t cluster_count = (size_new + cluster_size - 1) / cluster_size;
1339             cluster_t cluster_new_chain = fat_append_clusters(fd->fs, cluster_num, cluster_count);
1340             if(!cluster_new_chain)
1341                 return 0;
1342
1343             if(!cluster_num)
1344             {
1345                 cluster_num = cluster_new_chain;
1346                 fd->dir_entry.cluster = cluster_num;
1347             }
1348         }
1349
1350         /* write new directory entry */
1351         fd->dir_entry.file_size = size;
1352         if(size == 0)
1353             fd->dir_entry.cluster = 0;
1354         if(!fat_write_dir_entry(fd->fs, &fd->dir_entry))
1355             return 0;
1356
1357         if(size == 0)
1358         {
1359             /* free all clusters of file */
1360             fat_free_clusters(fd->fs, cluster_num);
1361         }
1362         else if(size_new <= cluster_size)
1363         {
1364             /* free all clusters no longer needed */
1365             fat_terminate_clusters(fd->fs, cluster_num);
1366         }
1367
1368     } while(0);
1369
1370     /* correct file position */
1371     if(size < fd->pos)
1372     {
1373         fd->pos = size;
1374         fd->pos_cluster = 0;
1375     }
1376
1377     return 1;
1378 }
1379 #endif
1380
1381 /**
1382  * \ingroup fat_dir
1383  * Opens a directory.
1384  *
1385  * \param[in] fs The filesystem on which the directory to open resides.
1386  * \param[in] dir_entry The directory entry which stands for the directory to open.
1387  * \returns An opaque directory descriptor on success, 0 on failure.
1388  * \see fat_close_dir
1389  */
1390 struct fat_dir_struct* fat_open_dir(struct fat_fs_struct* fs, const struct fat_dir_entry_struct* dir_entry)
1391 {
1392     if(!fs || !dir_entry || !(dir_entry->attributes & FAT_ATTRIB_DIR))
1393         return 0;
1394
1395 #if USE_DYNAMIC_MEMORY
1396     struct fat_dir_struct* dd = malloc(sizeof(*dd));
1397     if(!dd)
1398         return 0;
1399 #else
1400     struct fat_dir_struct* dd = fat_dir_handles;
1401     uint8_t i;
1402     for(i = 0; i < FAT_DIR_COUNT; ++i)
1403     {
1404         if(!dd->fs)
1405             break;
1406
1407         ++dd;
1408     }
1409     if(i >= FAT_DIR_COUNT)
1410         return 0;
1411 #endif
1412     
1413     memcpy(&dd->dir_entry, dir_entry, sizeof(*dir_entry));
1414     dd->fs = fs;
1415     dd->entry_cluster = dir_entry->cluster;
1416     dd->entry_offset = 0;
1417
1418     return dd;
1419 }
1420
1421 /**
1422  * \ingroup fat_dir
1423  * Closes a directory descriptor.
1424  *
1425  * This function destroys a directory descriptor which was
1426  * previously obtained by calling fat_open_dir(). When this
1427  * function returns, the given descriptor will be invalid.
1428  *
1429  * \param[in] dd The directory descriptor to close.
1430  * \see fat_open_dir
1431  */
1432 void fat_close_dir(struct fat_dir_struct* dd)
1433 {
1434     if(dd)
1435 #if USE_DYNAMIC_MEMORY
1436         free(dd);
1437 #else
1438         dd->fs = 0;
1439 #endif
1440 }
1441
1442 /**
1443  * \ingroup fat_dir
1444  * Reads the next directory entry contained within a parent directory.
1445  *
1446  * \param[in] dd The descriptor of the parent directory from which to read the entry.
1447  * \param[out] dir_entry Pointer to a buffer into which to write the directory entry information.
1448  * \returns 0 on failure, 1 on success.
1449  * \see fat_reset_dir
1450  */
1451 uint8_t fat_read_dir(struct fat_dir_struct* dd, struct fat_dir_entry_struct* dir_entry)
1452 {
1453     if(!dd || !dir_entry)
1454         return 0;
1455
1456     /* get current position of directory handle */
1457     struct fat_fs_struct* fs = dd->fs;
1458     const struct fat_header_struct* header = &fs->header;
1459     uint16_t cluster_size = header->cluster_size;
1460     cluster_t cluster_num = dd->entry_cluster;
1461     uint16_t cluster_offset = dd->entry_offset;
1462     struct fat_read_dir_callback_arg arg;
1463
1464     if(cluster_offset >= cluster_size)
1465     {
1466         /* The latest call hit the border of the last cluster in
1467          * the chain, but it still returned a directory entry.
1468          * So we now reset the handle and signal the caller the
1469          * end of the listing.
1470          */
1471         fat_reset_dir(dd);
1472         return 0;
1473     }
1474
1475     /* reset callback arguments */
1476     memset(&arg, 0, sizeof(arg));
1477     memset(dir_entry, 0, sizeof(*dir_entry));
1478     arg.dir_entry = dir_entry;
1479
1480     /* check if we read from the root directory */
1481     if(cluster_num == 0)
1482     {
1483 #if FAT_FAT32_SUPPORT
1484         if(fs->partition->type == PARTITION_TYPE_FAT32)
1485             cluster_num = header->root_dir_cluster;
1486         else
1487 #endif
1488             cluster_size = header->cluster_zero_offset - header->root_dir_offset;
1489     }
1490
1491     /* read entries */
1492     uint8_t buffer[32];
1493     while(!arg.finished)
1494     {
1495         /* read directory entries up to the cluster border */
1496         uint16_t cluster_left = cluster_size - cluster_offset;
1497         offset_t pos = cluster_offset;
1498         if(cluster_num == 0)
1499             pos += header->root_dir_offset;
1500         else
1501             pos += fat_cluster_offset(fs, cluster_num);
1502
1503         arg.bytes_read = 0;
1504         if(!fs->partition->device_read_interval(pos,
1505                                                 buffer,
1506                                                 sizeof(buffer),
1507                                                 cluster_left,
1508                                                 fat_dir_entry_read_callback,
1509                                                 &arg)
1510           )
1511             return 0;
1512
1513         cluster_offset += arg.bytes_read;
1514
1515         if(cluster_offset >= cluster_size)
1516         {
1517             /* we reached the cluster border and switch to the next cluster */
1518
1519             /* get number of next cluster */
1520             if((cluster_num = fat_get_next_cluster(fs, cluster_num)) != 0)
1521             {
1522                 cluster_offset = 0;
1523                 continue;
1524             }
1525
1526             /* we are at the end of the cluster chain */
1527             if(!arg.finished)
1528             {
1529                 /* directory entry not found, reset directory handle */
1530                 fat_reset_dir(dd);
1531                 return 0;
1532             }
1533             else
1534             {
1535                 /* The current execution of the function has been successful,
1536                  * so we can not signal an end of the directory listing to
1537                  * the caller, but must wait for the next call. So we keep an
1538                  * invalid cluster offset to mark this directory handle's
1539                  * traversal as finished.
1540                  */
1541             }
1542
1543             break;
1544         }
1545     }
1546
1547     dd->entry_cluster = cluster_num;
1548     dd->entry_offset = cluster_offset;
1549
1550     return arg.finished;
1551 }
1552
1553 /**
1554  * \ingroup fat_dir
1555  * Resets a directory handle.
1556  *
1557  * Resets the directory handle such that reading restarts
1558  * with the first directory entry.
1559  *
1560  * \param[in] dd The directory handle to reset.
1561  * \returns 0 on failure, 1 on success.
1562  * \see fat_read_dir
1563  */
1564 uint8_t fat_reset_dir(struct fat_dir_struct* dd)
1565 {
1566     if(!dd)
1567         return 0;
1568
1569     dd->entry_cluster = dd->dir_entry.cluster;
1570     dd->entry_offset = 0;
1571     return 1;
1572 }
1573
1574 /**
1575  * \ingroup fat_fs
1576  * Callback function for reading a directory entry.
1577  *
1578  * Interprets a raw directory entry and puts the contained
1579  * information into a fat_dir_entry_struct structure.
1580  * 
1581  * For a single file there may exist multiple directory
1582  * entries. All except the last one are lfn entries, which
1583  * contain parts of the long filename. The last directory
1584  * entry is a traditional 8.3 style one. It contains all
1585  * other information like size, cluster, date and time.
1586  * 
1587  * \param[in] buffer A pointer to 32 bytes of raw data.
1588  * \param[in] offset The absolute offset of the raw data.
1589  * \param[in,out] p An argument structure controlling operation.
1590  * \returns 0 on failure or completion, 1 if reading has
1591  *          to be continued
1592  */
1593 uint8_t fat_dir_entry_read_callback(uint8_t* buffer, offset_t offset, void* p)
1594 {
1595     struct fat_read_dir_callback_arg* arg = p;
1596     struct fat_dir_entry_struct* dir_entry = arg->dir_entry;
1597
1598     arg->bytes_read += 32;
1599
1600     /* skip deleted or empty entries */
1601     if(buffer[0] == FAT_DIRENTRY_DELETED || !buffer[0])
1602     {
1603 #if FAT_LFN_SUPPORT
1604         arg->checksum = 0;
1605 #endif
1606         return 1;
1607     }
1608
1609 #if !FAT_LFN_SUPPORT
1610     /* skip lfn entries */
1611     if(buffer[11] == 0x0f)
1612         return 1;
1613 #endif
1614
1615     char* long_name = dir_entry->long_name;
1616 #if FAT_LFN_SUPPORT
1617     if(buffer[11] == 0x0f)
1618     {
1619         /* checksum validation */
1620         if(arg->checksum == 0 || arg->checksum != buffer[13])
1621         {
1622             /* reset directory entry */
1623             memset(dir_entry, 0, sizeof(*dir_entry));
1624
1625             arg->checksum = buffer[13];
1626             dir_entry->entry_offset = offset;
1627         }
1628
1629         /* lfn supports unicode, but we do not, for now.
1630          * So we assume pure ascii and read only every
1631          * second byte.
1632          */
1633         uint16_t char_offset = ((buffer[0] & 0x3f) - 1) * 13;
1634         const uint8_t char_mapping[] = { 1, 3, 5, 7, 9, 14, 16, 18, 20, 22, 24, 28, 30 };
1635         for(uint8_t i = 0; i <= 12 && char_offset + i < sizeof(dir_entry->long_name) - 1; ++i)
1636             long_name[char_offset + i] = buffer[char_mapping[i]];
1637
1638         return 1;
1639     }
1640     else
1641 #endif
1642     {
1643 #if FAT_LFN_SUPPORT
1644         /* if we do not have a long name or the previous lfn does not match, take the 8.3 name */
1645         if(long_name[0] == '\0' || arg->checksum != fat_calc_83_checksum(buffer))
1646 #endif
1647         {
1648             /* reset directory entry */
1649             memset(dir_entry, 0, sizeof(*dir_entry));
1650             dir_entry->entry_offset = offset;
1651
1652             uint8_t i;
1653             for(i = 0; i < 8; ++i)
1654             {
1655                 if(buffer[i] == ' ')
1656                     break;
1657                 long_name[i] = buffer[i];
1658
1659                 /* Windows NT and later versions do not store lfn entries
1660                  * for 8.3 names which have a lowercase basename, extension
1661                  * or both when everything else is uppercase. They use two
1662                  * extra bits to signal a lowercase basename or extension.
1663                  */
1664                 if((buffer[12] & 0x08) && buffer[i] >= 'A' && buffer[i] <= 'Z')
1665                     long_name[i] += 'a' - 'A';
1666             }
1667             if(long_name[0] == 0x05)
1668                 long_name[0] = (char) FAT_DIRENTRY_DELETED;
1669
1670             if(buffer[8] != ' ')
1671             {
1672                 long_name[i++] = '.';
1673
1674                 uint8_t j = 8;
1675                 for(; j < 11; ++j)
1676                 {
1677                     if(buffer[j] == ' ')
1678                         break;
1679                     long_name[i] = buffer[j];
1680
1681                     /* See above for the lowercase 8.3 name handling of
1682                      * Windows NT and later.
1683                      */
1684                     if((buffer[12] & 0x10) && buffer[j] >= 'A' && buffer[j] <= 'Z')
1685                         long_name[i] += 'a' - 'A';
1686
1687                     ++i;
1688                 }
1689             } 
1690
1691             long_name[i] = '\0';
1692         }
1693         
1694         /* extract properties of file and store them within the structure */
1695         dir_entry->attributes = buffer[11];
1696         dir_entry->cluster = read16(&buffer[26]);
1697 #if FAT_FAT32_SUPPORT
1698         dir_entry->cluster |= ((cluster_t) read16(&buffer[20])) << 16;
1699 #endif
1700         dir_entry->file_size = read32(&buffer[28]);
1701
1702 #if FAT_DATETIME_SUPPORT
1703         dir_entry->modification_time = read16(&buffer[22]);
1704         dir_entry->modification_date = read16(&buffer[24]);
1705 #endif
1706
1707         arg->finished = 1;
1708         return 0;
1709     }
1710 }
1711
1712 #if DOXYGEN || FAT_LFN_SUPPORT
1713 /**
1714  * \ingroup fat_fs
1715  * Calculates the checksum for 8.3 names used within the
1716  * corresponding lfn directory entries.
1717  *
1718  * \param[in] file_name_83 The 11-byte file name buffer.
1719  * \returns The checksum of the given file name.
1720  */
1721 uint8_t fat_calc_83_checksum(const uint8_t* file_name_83)
1722 {
1723     uint8_t checksum = file_name_83[0];
1724     for(uint8_t i = 1; i < 11; ++i)
1725         checksum = ((checksum >> 1) | (checksum << 7)) + file_name_83[i];
1726
1727     return checksum;
1728 }
1729 #endif
1730
1731 #if DOXYGEN || FAT_WRITE_SUPPORT
1732 /**
1733  * \ingroup fat_fs
1734  * Searches for space where to store a directory entry.
1735  *
1736  * \param[in] fs The filesystem on which to operate.
1737  * \param[in] parent The directory in which to search.
1738  * \param[in] dir_entry The directory entry for which to search space.
1739  * \returns 0 on failure, a device offset on success.
1740  */
1741 offset_t fat_find_offset_for_dir_entry(struct fat_fs_struct* fs, const struct fat_dir_struct* parent, const struct fat_dir_entry_struct* dir_entry)
1742 {
1743     if(!fs || !dir_entry)
1744         return 0;
1745
1746     /* search for a place where to write the directory entry to disk */
1747 #if FAT_LFN_SUPPORT
1748     uint8_t free_dir_entries_needed = (strlen(dir_entry->long_name) + 12) / 13 + 1;
1749     uint8_t free_dir_entries_found = 0;
1750 #endif
1751     cluster_t cluster_num = parent->dir_entry.cluster;
1752     offset_t dir_entry_offset = 0;
1753     offset_t offset = 0;
1754     offset_t offset_to = 0;
1755 #if FAT_FAT32_SUPPORT
1756     uint8_t is_fat32 = (fs->partition->type == PARTITION_TYPE_FAT32);
1757 #endif
1758
1759     if(cluster_num == 0)
1760     {
1761 #if FAT_FAT32_SUPPORT
1762         if(is_fat32)
1763         {
1764             cluster_num = fs->header.root_dir_cluster;
1765         }
1766         else
1767 #endif
1768         {
1769             /* we read/write from the root directory entry */
1770             offset = fs->header.root_dir_offset;
1771             offset_to = fs->header.cluster_zero_offset;
1772             dir_entry_offset = offset;
1773         }
1774     }
1775     
1776     while(1)
1777     {
1778         if(offset == offset_to)
1779         {
1780             if(cluster_num == 0)
1781                 /* We iterated through the whole root directory and
1782                  * could not find enough space for the directory entry.
1783                  */
1784                 return 0;
1785
1786             if(offset)
1787             {
1788                 /* We reached a cluster boundary and have to
1789                  * switch to the next cluster.
1790                  */
1791
1792                 cluster_t cluster_next = fat_get_next_cluster(fs, cluster_num);
1793                 if(!cluster_next)
1794                 {
1795                     cluster_next = fat_append_clusters(fs, cluster_num, 1);
1796                     if(!cluster_next)
1797                         return 0;
1798
1799                     /* we appended a new cluster and know it is free */
1800                     dir_entry_offset = fs->header.cluster_zero_offset +
1801                                        (offset_t) (cluster_next - 2) * fs->header.cluster_size;
1802
1803                     /* clear cluster to avoid garbage directory entries */
1804                     fat_clear_cluster(fs, cluster_next);
1805
1806                     break;
1807                 }
1808                 cluster_num = cluster_next;
1809             }
1810
1811             offset = fat_cluster_offset(fs, cluster_num);
1812             offset_to = offset + fs->header.cluster_size;
1813             dir_entry_offset = offset;
1814 #if FAT_LFN_SUPPORT
1815             free_dir_entries_found = 0;
1816 #endif
1817         }
1818         
1819         /* read next lfn or 8.3 entry */
1820         uint8_t first_char;
1821         if(!fs->partition->device_read(offset, &first_char, sizeof(first_char)))
1822             return 0;
1823
1824         /* check if we found a free directory entry */
1825         if(first_char == FAT_DIRENTRY_DELETED || !first_char)
1826         {
1827             /* check if we have the needed number of available entries */
1828 #if FAT_LFN_SUPPORT
1829             ++free_dir_entries_found;
1830             if(free_dir_entries_found >= free_dir_entries_needed)
1831 #endif
1832                 break;
1833
1834             offset += 32;
1835         }
1836         else
1837         {
1838             offset += 32;
1839             dir_entry_offset = offset;
1840 #if FAT_LFN_SUPPORT
1841             free_dir_entries_found = 0;
1842 #endif
1843         }
1844     }
1845
1846     return dir_entry_offset;
1847 }
1848 #endif
1849
1850 #if DOXYGEN || FAT_WRITE_SUPPORT
1851 /**
1852  * \ingroup fat_fs
1853  * Writes a directory entry to disk.
1854  *
1855  * \note The file name is not checked for invalid characters.
1856  *
1857  * \note The generation of the short 8.3 file name is quite
1858  * simple. The first eight characters are used for the filename.
1859  * The extension, if any, is made up of the first three characters
1860  * following the last dot within the long filename. If the
1861  * filename (without the extension) is longer than eight characters,
1862  * the lower byte of the cluster number replaces the last two
1863  * characters to avoid name clashes. In any other case, it is your
1864  * responsibility to avoid name clashes.
1865  *
1866  * \param[in] fs The filesystem on which to operate.
1867  * \param[in] dir_entry The directory entry to write.
1868  * \returns 0 on failure, 1 on success.
1869  */
1870 uint8_t fat_write_dir_entry(const struct fat_fs_struct* fs, struct fat_dir_entry_struct* dir_entry)
1871 {
1872     if(!fs || !dir_entry)
1873         return 0;
1874     
1875 #if FAT_DATETIME_SUPPORT
1876     {
1877         uint16_t year;
1878         uint8_t month;
1879         uint8_t day;
1880         uint8_t hour;
1881         uint8_t min;
1882         uint8_t sec;
1883
1884         fat_get_datetime(&year, &month, &day, &hour, &min, &sec);
1885         fat_set_file_modification_date(dir_entry, year, month, day);
1886         fat_set_file_modification_time(dir_entry, hour, min, sec);
1887     }
1888 #endif
1889
1890     device_write_t device_write = fs->partition->device_write;
1891     offset_t offset = dir_entry->entry_offset;
1892     const char* name = dir_entry->long_name;
1893     uint8_t name_len = strlen(name);
1894 #if FAT_LFN_SUPPORT
1895     uint8_t lfn_entry_count = (name_len + 12) / 13;
1896 #endif
1897     uint8_t buffer[32];
1898
1899     /* write 8.3 entry */
1900
1901     /* generate 8.3 file name */
1902     memset(&buffer[0], ' ', 11);
1903     char* name_ext = strrchr(name, '.');
1904     if(name_ext && *++name_ext)
1905     {
1906         uint8_t name_ext_len = strlen(name_ext);
1907         name_len -= name_ext_len + 1;
1908
1909         if(name_ext_len > 3)
1910 #if FAT_LFN_SUPPORT
1911             name_ext_len = 3;
1912 #else
1913             return 0;
1914 #endif
1915         
1916         memcpy(&buffer[8], name_ext, name_ext_len);
1917     }
1918     
1919     if(name_len <= 8)
1920     {
1921         memcpy(buffer, name, name_len);
1922
1923 #if FAT_LFN_SUPPORT
1924         /* For now, we create lfn entries for all files,
1925          * except the "." and ".." directory references.
1926          * This is to avoid difficulties with capitalization,
1927          * as 8.3 filenames allow uppercase letters only.
1928          *
1929          * Theoretically it would be possible to leave
1930          * the 8.3 entry alone if the basename and the
1931          * extension have no mixed capitalization.
1932          */
1933         if(name[0] == '.' &&
1934            ((name[1] == '.' && name[2] == '\0') ||
1935             name[1] == '\0')
1936           )
1937             lfn_entry_count = 0;
1938 #endif
1939     }
1940     else
1941     {
1942 #if FAT_LFN_SUPPORT
1943         memcpy(buffer, name, 8);
1944
1945         /* Minimize 8.3 name clashes by appending
1946          * the lower byte of the cluster number.
1947          */
1948         uint8_t num = dir_entry->cluster & 0xff;
1949
1950         buffer[6] = (num < 0xa0) ? ('0' + (num >> 4)) : ('a' + (num >> 4));
1951         num &= 0x0f;
1952         buffer[7] = (num < 0x0a) ? ('0' + num) : ('a' + num);
1953 #else
1954         return 0;
1955 #endif
1956     }
1957     if(buffer[0] == FAT_DIRENTRY_DELETED)
1958         buffer[0] = 0x05;
1959
1960     /* fill directory entry buffer */
1961     memset(&buffer[11], 0, sizeof(buffer) - 11);
1962     buffer[0x0b] = dir_entry->attributes;
1963 #if FAT_DATETIME_SUPPORT
1964     write16(&buffer[0x16], dir_entry->modification_time);
1965     write16(&buffer[0x18], dir_entry->modification_date);
1966 #endif
1967 #if FAT_FAT32_SUPPORT
1968     write16(&buffer[0x14], (uint16_t) (dir_entry->cluster >> 16));
1969 #endif
1970     write16(&buffer[0x1a], dir_entry->cluster);
1971     write32(&buffer[0x1c], dir_entry->file_size);
1972
1973     /* write to disk */
1974 #if FAT_LFN_SUPPORT
1975     if(!device_write(offset + (uint16_t) lfn_entry_count * 32, buffer, sizeof(buffer)))
1976 #else
1977     if(!device_write(offset, buffer, sizeof(buffer)))
1978 #endif
1979         return 0;
1980     
1981 #if FAT_LFN_SUPPORT
1982     /* calculate checksum of 8.3 name */
1983     uint8_t checksum = fat_calc_83_checksum(buffer);
1984     
1985     /* write lfn entries */
1986     for(uint8_t lfn_entry = lfn_entry_count; lfn_entry > 0; --lfn_entry)
1987     {
1988         memset(buffer, 0xff, sizeof(buffer));
1989         
1990         /* set file name */
1991         const char* long_name_curr = name + (lfn_entry - 1) * 13;
1992         uint8_t i = 1;
1993         while(i < 0x1f)
1994         {
1995             buffer[i++] = *long_name_curr;
1996             buffer[i++] = 0;
1997
1998             switch(i)
1999             {
2000                 case 0x0b:
2001                     i = 0x0e;
2002                     break;
2003                 case 0x1a:
2004                     i = 0x1c;
2005                     break;
2006             }
2007
2008             if(!*long_name_curr++)
2009                 break;
2010         }
2011         
2012         /* set index of lfn entry */
2013         buffer[0x00] = lfn_entry;
2014         if(lfn_entry == lfn_entry_count)
2015             buffer[0x00] |= FAT_DIRENTRY_LFNLAST;
2016
2017         /* mark as lfn entry */
2018         buffer[0x0b] = 0x0f;
2019
2020         /* set 8.3 checksum */
2021         buffer[0x0d] = checksum;
2022
2023         /* clear reserved bytes */
2024         buffer[0x0c] = 0;
2025         buffer[0x1a] = 0;
2026         buffer[0x1b] = 0;
2027
2028         /* write entry */
2029         device_write(offset, buffer, sizeof(buffer));
2030     
2031         offset += sizeof(buffer);
2032     }
2033 #endif
2034     
2035     return 1;
2036 }
2037 #endif
2038
2039 #if DOXYGEN || FAT_WRITE_SUPPORT
2040 /**
2041  * \ingroup fat_file
2042  * Creates a file.
2043  *
2044  * Creates a file and obtains the directory entry of the
2045  * new file. If the file to create already exists, the
2046  * directory entry of the existing file will be returned
2047  * within the dir_entry parameter.
2048  *
2049  * \note The file name is not checked for invalid characters.
2050  *
2051  * \note The generation of the short 8.3 file name is quite
2052  * simple. The first eight characters are used for the filename.
2053  * The extension, if any, is made up of the first three characters
2054  * following the last dot within the long filename. If the
2055  * filename (without the extension) is longer than eight characters,
2056  * the lower byte of the cluster number replaces the last two
2057  * characters to avoid name clashes. In any other case, it is your
2058  * responsibility to avoid name clashes.
2059  *
2060  * \param[in] parent The handle of the directory in which to create the file.
2061  * \param[in] file The name of the file to create.
2062  * \param[out] dir_entry The directory entry to fill for the new (or existing) file.
2063  * \returns 0 on failure, 1 on success, 2 if the file already existed.
2064  * \see fat_delete_file
2065  */
2066 uint8_t fat_create_file(struct fat_dir_struct* parent, const char* file, struct fat_dir_entry_struct* dir_entry)
2067 {
2068     if(!parent || !file || !file[0] || !dir_entry)
2069         return 0;
2070
2071     /* check if the file already exists */
2072     while(1)
2073     {
2074         if(!fat_read_dir(parent, dir_entry))
2075             break;
2076
2077         if(strcmp(file, dir_entry->long_name) == 0)
2078         {
2079             fat_reset_dir(parent);
2080             return 2;
2081         }
2082     }
2083
2084     struct fat_fs_struct* fs = parent->fs;
2085
2086     /* prepare directory entry with values already known */
2087     memset(dir_entry, 0, sizeof(*dir_entry));
2088     strncpy(dir_entry->long_name, file, sizeof(dir_entry->long_name) - 1);
2089
2090     /* find place where to store directory entry */
2091     if(!(dir_entry->entry_offset = fat_find_offset_for_dir_entry(fs, parent, dir_entry)))
2092         return 0;
2093     
2094     /* write directory entry to disk */
2095     if(!fat_write_dir_entry(fs, dir_entry))
2096         return 0;
2097     
2098     return 1;
2099 }
2100 #endif
2101
2102 #if DOXYGEN || FAT_WRITE_SUPPORT
2103 /**
2104  * \ingroup fat_file
2105  * Deletes a file or directory.
2106  *
2107  * If a directory is deleted without first deleting its
2108  * subdirectories and files, disk space occupied by these
2109  * files will get wasted as there is no chance to release
2110  * it and mark it as free.
2111  * 
2112  * \param[in] fs The filesystem on which to operate.
2113  * \param[in] dir_entry The directory entry of the file to delete.
2114  * \returns 0 on failure, 1 on success.
2115  * \see fat_create_file
2116  */
2117 uint8_t fat_delete_file(struct fat_fs_struct* fs, struct fat_dir_entry_struct* dir_entry)
2118 {
2119     if(!fs || !dir_entry)
2120         return 0;
2121
2122     /* get offset of the file's directory entry */
2123     offset_t dir_entry_offset = dir_entry->entry_offset;
2124     if(!dir_entry_offset)
2125         return 0;
2126
2127 #if FAT_LFN_SUPPORT
2128     uint8_t buffer[12];
2129     while(1)
2130     {
2131         /* read directory entry */
2132         if(!fs->partition->device_read(dir_entry_offset, buffer, sizeof(buffer)))
2133             return 0;
2134         
2135         /* mark the directory entry as deleted */
2136         buffer[0] = FAT_DIRENTRY_DELETED;
2137         
2138         /* write back entry */
2139         if(!fs->partition->device_write(dir_entry_offset, buffer, sizeof(buffer)))
2140             return 0;
2141
2142         /* check if we deleted the whole entry */
2143         if(buffer[11] != 0x0f)
2144             break;
2145
2146         dir_entry_offset += 32;
2147     }
2148 #else
2149     /* mark the directory entry as deleted */
2150     uint8_t first_char = FAT_DIRENTRY_DELETED;
2151     if(!fs->partition->device_write(dir_entry_offset, &first_char, 1))
2152         return 0;
2153 #endif
2154
2155     /* We deleted the directory entry. The next thing to do is
2156      * marking all occupied clusters as free.
2157      */
2158     return (dir_entry->cluster == 0 || fat_free_clusters(fs, dir_entry->cluster));
2159 }
2160 #endif
2161
2162 #if DOXYGEN || FAT_WRITE_SUPPORT
2163 /**
2164  * \ingroup fat_file
2165  * Moves or renames a file.
2166  *
2167  * Changes a file's name, optionally moving it into another
2168  * directory as well. Before calling this function, the
2169  * target file name must not exist. Moving a file to a
2170  * different filesystem (i.e. \a parent_new doesn't lie on
2171  * \a fs) is not supported.
2172  * 
2173  * After successfully renaming (and moving) the file, the
2174  * given directory entry is updated such that it points to
2175  * the file's new location.
2176  *
2177  * \note The notes which apply to fat_create_file() also
2178  * apply to this function.
2179  *
2180  * \param[in] fs The filesystem on which to operate.
2181  * \param[in,out] dir_entry The directory entry of the file to move.
2182  * \param[in] parent_new The handle of the new parent directory of the file.
2183  * \param[in] file_new The file's new name.
2184  * \returns 0 on failure, 1 on success.
2185  * \see fat_create_file, fat_delete_file, fat_move_dir
2186  */
2187 uint8_t fat_move_file(struct fat_fs_struct* fs, struct fat_dir_entry_struct* dir_entry, struct fat_dir_struct* parent_new, const char* file_new)
2188 {
2189     if(!fs || !dir_entry || !parent_new || (file_new && !file_new[0]))
2190         return 0;
2191     if(fs != parent_new->fs)
2192         return 0;
2193
2194     /* use existing file name if none has been specified */
2195     if(!file_new)
2196         file_new = dir_entry->long_name;
2197
2198     /* create file with new file name */
2199     struct fat_dir_entry_struct dir_entry_new;
2200     if(!fat_create_file(parent_new, file_new, &dir_entry_new))
2201         return 0;
2202
2203     /* copy members of directory entry which do not change with rename */
2204     dir_entry_new.attributes = dir_entry->attributes;
2205 #if FAT_DATETIME_SUPPORT
2206     dir_entry_new.modification_time = dir_entry->modification_time;
2207     dir_entry_new.modification_date = dir_entry->modification_date;
2208 #endif
2209     dir_entry_new.cluster = dir_entry->cluster;
2210     dir_entry_new.file_size = dir_entry->file_size;
2211
2212     /* make the new file name point to the old file's content */
2213     if(!fat_write_dir_entry(fs, &dir_entry_new))
2214     {
2215         fat_delete_file(fs, &dir_entry_new);
2216         return 0;
2217     }
2218     
2219     /* delete the old file, but not its clusters, which have already been remapped above */
2220     dir_entry->cluster = 0;
2221     if(!fat_delete_file(fs, dir_entry))
2222         return 0;
2223
2224     *dir_entry = dir_entry_new;
2225     return 1;
2226 }
2227 #endif
2228
2229 #if DOXYGEN || FAT_WRITE_SUPPORT
2230 /**
2231  * \ingroup fat_dir
2232  * Creates a directory.
2233  *
2234  * Creates a directory and obtains its directory entry.
2235  * If the directory to create already exists, its
2236  * directory entry will be returned within the dir_entry
2237  * parameter.
2238  *
2239  * \note The notes which apply to fat_create_file() also
2240  * apply to this function.
2241  *
2242  * \param[in] parent The handle of the parent directory of the new directory.
2243  * \param[in] dir The name of the directory to create.
2244  * \param[out] dir_entry The directory entry to fill for the new directory.
2245  * \returns 0 on failure, 1 on success.
2246  * \see fat_delete_dir
2247  */
2248 uint8_t fat_create_dir(struct fat_dir_struct* parent, const char* dir, struct fat_dir_entry_struct* dir_entry)
2249 {
2250     if(!parent || !dir || !dir[0] || !dir_entry)
2251         return 0;
2252
2253     /* check if the file or directory already exists */
2254     while(fat_read_dir(parent, dir_entry))
2255     {
2256         if(strcmp(dir, dir_entry->long_name) == 0)
2257         {
2258             fat_reset_dir(parent);
2259             return 0;
2260         }
2261     }
2262
2263     struct fat_fs_struct* fs = parent->fs;
2264
2265     /* allocate cluster which will hold directory entries */
2266     cluster_t dir_cluster = fat_append_clusters(fs, 0, 1);
2267     if(!dir_cluster)
2268         return 0;
2269
2270     /* clear cluster to prevent bogus directory entries */
2271     fat_clear_cluster(fs, dir_cluster);
2272     
2273     memset(dir_entry, 0, sizeof(*dir_entry));
2274     dir_entry->attributes = FAT_ATTRIB_DIR;
2275
2276     /* create "." directory self reference */
2277     dir_entry->entry_offset = fs->header.cluster_zero_offset +
2278                               (offset_t) (dir_cluster - 2) * fs->header.cluster_size;
2279     dir_entry->long_name[0] = '.';
2280     dir_entry->cluster = dir_cluster;
2281     if(!fat_write_dir_entry(fs, dir_entry))
2282     {
2283         fat_free_clusters(fs, dir_cluster);
2284         return 0;
2285     }
2286
2287     /* create ".." parent directory reference */
2288     dir_entry->entry_offset += 32;
2289     dir_entry->long_name[1] = '.';
2290     dir_entry->cluster = parent->dir_entry.cluster;
2291     if(!fat_write_dir_entry(fs, dir_entry))
2292     {
2293         fat_free_clusters(fs, dir_cluster);
2294         return 0;
2295     }
2296
2297     /* fill directory entry */
2298     strncpy(dir_entry->long_name, dir, sizeof(dir_entry->long_name) - 1);
2299     dir_entry->cluster = dir_cluster;
2300
2301     /* find place where to store directory entry */
2302     if(!(dir_entry->entry_offset = fat_find_offset_for_dir_entry(fs, parent, dir_entry)))
2303     {
2304         fat_free_clusters(fs, dir_cluster);
2305         return 0;
2306     }
2307
2308     /* write directory to disk */
2309     if(!fat_write_dir_entry(fs, dir_entry))
2310     {
2311         fat_free_clusters(fs, dir_cluster);
2312         return 0;
2313     }
2314
2315     return 1;
2316 }
2317 #endif
2318
2319 /**
2320  * \ingroup fat_dir
2321  * Deletes a directory.
2322  *
2323  * This is just a synonym for fat_delete_file().
2324  * If a directory is deleted without first deleting its
2325  * subdirectories and files, disk space occupied by these
2326  * files will get wasted as there is no chance to release
2327  * it and mark it as free.
2328  * 
2329  * \param[in] fs The filesystem on which to operate.
2330  * \param[in] dir_entry The directory entry of the directory to delete.
2331  * \returns 0 on failure, 1 on success.
2332  * \see fat_create_dir
2333  */
2334 #ifdef DOXYGEN
2335 uint8_t fat_delete_dir(struct fat_fs_struct* fs, struct fat_dir_entry_struct* dir_entry);
2336 #endif
2337
2338 /**
2339  * \ingroup fat_dir
2340  * Moves or renames a directory.
2341  *
2342  * This is just a synonym for fat_move_file().
2343  * 
2344  * \param[in] fs The filesystem on which to operate.
2345  * \param[in,out] dir_entry The directory entry of the directory to move.
2346  * \param[in] parent_new The handle of the new parent directory.
2347  * \param[in] dir_new The directory's new name.
2348  * \returns 0 on failure, 1 on success.
2349  * \see fat_create_dir, fat_delete_dir, fat_move_file
2350  */
2351 #ifdef DOXYGEN
2352 uint8_t fat_move_dir(struct fat_fs_struct* fs, struct fat_dir_entry_struct* dir_entry, struct fat_dir_struct* parent_new, const char* dir_new);
2353 #endif
2354
2355 #if DOXYGEN || FAT_DATETIME_SUPPORT
2356 /**
2357  * \ingroup fat_file
2358  * Returns the modification date of a file.
2359  *
2360  * \param[in] dir_entry The directory entry of which to return the modification date.
2361  * \param[out] year The year the file was last modified.
2362  * \param[out] month The month the file was last modified.
2363  * \param[out] day The day the file was last modified.
2364  */
2365 void fat_get_file_modification_date(const struct fat_dir_entry_struct* dir_entry, uint16_t* year, uint8_t* month, uint8_t* day)
2366 {
2367     if(!dir_entry)
2368         return;
2369
2370     *year = 1980 + ((dir_entry->modification_date >> 9) & 0x7f);
2371     *month = (dir_entry->modification_date >> 5) & 0x0f;
2372     *day = (dir_entry->modification_date >> 0) & 0x1f;
2373 }
2374 #endif
2375
2376 #if DOXYGEN || FAT_DATETIME_SUPPORT
2377 /**
2378  * \ingroup fat_file
2379  * Returns the modification time of a file.
2380  *
2381  * \param[in] dir_entry The directory entry of which to return the modification time.
2382  * \param[out] hour The hour the file was last modified.
2383  * \param[out] min The min the file was last modified.
2384  * \param[out] sec The sec the file was last modified.
2385  */
2386 void fat_get_file_modification_time(const struct fat_dir_entry_struct* dir_entry, uint8_t* hour, uint8_t* min, uint8_t* sec)
2387 {
2388     if(!dir_entry)
2389         return;
2390
2391     *hour = (dir_entry->modification_time >> 11) & 0x1f;
2392     *min = (dir_entry->modification_time >> 5) & 0x3f;
2393     *sec = ((dir_entry->modification_time >> 0) & 0x1f) * 2;
2394 }
2395 #endif
2396
2397 #if DOXYGEN || (FAT_WRITE_SUPPORT && FAT_DATETIME_SUPPORT)
2398 /**
2399  * \ingroup fat_file
2400  * Sets the modification time of a date.
2401  *
2402  * \param[in] dir_entry The directory entry for which to set the modification date.
2403  * \param[in] year The year the file was last modified.
2404  * \param[in] month The month the file was last modified.
2405  * \param[in] day The day the file was last modified.
2406  */
2407 void fat_set_file_modification_date(struct fat_dir_entry_struct* dir_entry, uint16_t year, uint8_t month, uint8_t day)
2408 {
2409     if(!dir_entry)
2410         return;
2411
2412     dir_entry->modification_date =
2413         ((year - 1980) << 9) |
2414         ((uint16_t) month << 5) |
2415         ((uint16_t) day << 0);
2416 }
2417 #endif
2418
2419 #if DOXYGEN || (FAT_WRITE_SUPPORT && FAT_DATETIME_SUPPORT)
2420 /**
2421  * \ingroup fat_file
2422  * Sets the modification time of a file.
2423  *
2424  * \param[in] dir_entry The directory entry for which to set the modification time.
2425  * \param[in] hour The year the file was last modified.
2426  * \param[in] min The month the file was last modified.
2427  * \param[in] sec The day the file was last modified.
2428  */
2429 void fat_set_file_modification_time(struct fat_dir_entry_struct* dir_entry, uint8_t hour, uint8_t min, uint8_t sec)
2430 {
2431     if(!dir_entry)
2432         return;
2433
2434     dir_entry->modification_time =
2435         ((uint16_t) hour << 11) |
2436         ((uint16_t) min << 5) |
2437         ((uint16_t) sec >> 1) ;
2438 }
2439 #endif
2440
2441 /**
2442  * \ingroup fat_fs
2443  * Returns the amount of total storage capacity of the filesystem in bytes.
2444  *
2445  * \param[in] fs The filesystem on which to operate.
2446  * \returns 0 on failure, the filesystem size in bytes otherwise.
2447  */
2448 offset_t fat_get_fs_size(const struct fat_fs_struct* fs)
2449 {
2450     if(!fs)
2451         return 0;
2452
2453 #if FAT_FAT32_SUPPORT
2454     if(fs->partition->type == PARTITION_TYPE_FAT32)
2455         return (offset_t) (fs->header.fat_size / 4 - 2) * fs->header.cluster_size;
2456     else
2457 #endif
2458         return (offset_t) (fs->header.fat_size / 2 - 2) * fs->header.cluster_size;
2459 }
2460
2461 /**
2462  * \ingroup fat_fs
2463  * Returns the amount of free storage capacity on the filesystem in bytes.
2464  *
2465  * \note As the FAT filesystem is cluster based, this function does not
2466  *       return continuous values but multiples of the cluster size.
2467  *
2468  * \param[in] fs The filesystem on which to operate.
2469  * \returns 0 on failure, the free filesystem space in bytes otherwise.
2470  */
2471 offset_t fat_get_fs_free(const struct fat_fs_struct* fs)
2472 {
2473     if(!fs)
2474         return 0;
2475
2476     uint8_t fat[32];
2477     struct fat_usage_count_callback_arg count_arg;
2478     count_arg.cluster_count = 0;
2479     count_arg.buffer_size = sizeof(fat);
2480
2481     offset_t fat_offset = fs->header.fat_offset;
2482     uint32_t fat_size = fs->header.fat_size;
2483     while(fat_size > 0)
2484     {
2485         uintptr_t length = UINTPTR_MAX - 1;
2486         if(fat_size < length)
2487             length = fat_size;
2488
2489         if(!fs->partition->device_read_interval(fat_offset,
2490                                                 fat,
2491                                                 sizeof(fat),
2492                                                 length,
2493 #if FAT_FAT32_SUPPORT
2494                                                 (fs->partition->type == PARTITION_TYPE_FAT16) ?
2495                                                     fat_get_fs_free_16_callback :
2496                                                     fat_get_fs_free_32_callback,
2497 #else
2498                                                 fat_get_fs_free_16_callback,
2499 #endif
2500                                                 &count_arg
2501                                                )
2502           )
2503             return 0;
2504
2505         fat_offset += length;
2506         fat_size -= length;
2507     }
2508
2509     return (offset_t) count_arg.cluster_count * fs->header.cluster_size;
2510 }
2511
2512 /**
2513  * \ingroup fat_fs
2514  * Callback function used for counting free clusters in a FAT.
2515  */
2516 uint8_t fat_get_fs_free_16_callback(uint8_t* buffer, offset_t offset, void* p)
2517 {
2518     struct fat_usage_count_callback_arg* count_arg = (struct fat_usage_count_callback_arg*) p;
2519     uintptr_t buffer_size = count_arg->buffer_size;
2520
2521     for(uintptr_t i = 0; i < buffer_size; i += 2, buffer += 2)
2522     {
2523         uint16_t cluster = read16(buffer);
2524         if(cluster == HTOL16(FAT16_CLUSTER_FREE))
2525             ++(count_arg->cluster_count);
2526     }
2527
2528     return 1;
2529 }
2530
2531 #if DOXYGEN || FAT_FAT32_SUPPORT
2532 /**
2533  * \ingroup fat_fs
2534  * Callback function used for counting free clusters in a FAT32.
2535  */
2536 uint8_t fat_get_fs_free_32_callback(uint8_t* buffer, offset_t offset, void* p)
2537 {
2538     struct fat_usage_count_callback_arg* count_arg = (struct fat_usage_count_callback_arg*) p;
2539     uintptr_t buffer_size = count_arg->buffer_size;
2540
2541     for(uintptr_t i = 0; i < buffer_size; i += 4, buffer += 4)
2542     {
2543         uint32_t cluster = read32(buffer);
2544         if(cluster == HTOL32(FAT32_CLUSTER_FREE))
2545             ++(count_arg->cluster_count);
2546     }
2547
2548     return 1;
2549 }
2550 #endif
2551