comparison fat.c @ 19:5f9a40d6991b

Import SD handling from http://www.roland-riegel.de/sd-reader/index.html Use smaller build options
author Matt Johnston <matt@ucc.asn.au>
date Tue, 25 Jun 2013 13:55:11 +0800
parents
children
comparison
equal deleted inserted replaced
18:021e6e0006f4 19:5f9a40d6991b
1
2 /*
3 * Copyright (c) 2006-2012 by Roland Riegel <[email protected]>
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