Hanna
Sourcecode Batteriemanagementsystem
fat.c
gehe zur Dokumentation dieser Datei
1 
16 /*
17  * Copyright (c) 2006-2011 by Roland Riegel <feedback@roland-riegel.de>
18  *
19  * This file is free software; you can redistribute it and/or modify
20  * it under the terms of either the GNU General Public License version 2
21  * or the GNU Lesser General Public License version 2.1, both as
22  * published by the Free Software Foundation.
23  */
24 
25 #include "byteordering.h"
26 #include "partition.h"
27 #include "fat.h"
28 #include "fat_config.h"
29 #include "sd-reader_config.h"
30 #include "ds1388_rtc.h"
31 
32 #include <string.h>
33 
34 #if USE_DYNAMIC_MEMORY
35 #include <stdlib.h>
36 #endif
37 
85 #define FAT16_CLUSTER_FREE 0x0000
86 #define FAT16_CLUSTER_RESERVED_MIN 0xfff0
87 #define FAT16_CLUSTER_RESERVED_MAX 0xfff6
88 #define FAT16_CLUSTER_BAD 0xfff7
89 #define FAT16_CLUSTER_LAST_MIN 0xfff8
90 #define FAT16_CLUSTER_LAST_MAX 0xffff
91 
92 #define FAT32_CLUSTER_FREE 0x00000000
93 #define FAT32_CLUSTER_RESERVED_MIN 0x0ffffff0
94 #define FAT32_CLUSTER_RESERVED_MAX 0x0ffffff6
95 #define FAT32_CLUSTER_BAD 0x0ffffff7
96 #define FAT32_CLUSTER_LAST_MIN 0x0ffffff8
97 #define FAT32_CLUSTER_LAST_MAX 0x0fffffff
98 
99 #define FAT_DIRENTRY_DELETED 0xe5
100 #define FAT_DIRENTRY_LFNLAST (1 << 6)
101 #define FAT_DIRENTRY_LFNSEQMASK ((1 << 6) - 1)
102 
103 /* Each entry within the directory table has a size of 32 bytes
104  * and either contains a 8.3 DOS-style file name or a part of a
105  * long file name, which may consist of several directory table
106  * entries at once.
107  *
108  * multi-byte integer values are stored little-endian!
109  *
110  * 8.3 file name entry:
111  * ====================
112  * offset length description
113  * 0 8 name (space padded)
114  * 8 3 extension (space padded)
115  * 11 1 attributes (FAT_ATTRIB_*)
116  *
117  * long file name (lfn) entry ordering for a single file name:
118  * ===========================================================
119  * LFN entry n
120  * ...
121  * LFN entry 2
122  * LFN entry 1
123  * 8.3 entry (see above)
124  *
125  * lfn entry:
126  * ==========
127  * offset length description
128  * 0 1 ordinal field
129  * 1 2 unicode character 1
130  * 3 3 unicode character 2
131  * 5 3 unicode character 3
132  * 7 3 unicode character 4
133  * 9 3 unicode character 5
134  * 11 1 attribute (always 0x0f)
135  * 12 1 type (reserved, always 0)
136  * 13 1 checksum
137  * 14 2 unicode character 6
138  * 16 2 unicode character 7
139  * 18 2 unicode character 8
140  * 20 2 unicode character 9
141  * 22 2 unicode character 10
142  * 24 2 unicode character 11
143  * 26 2 cluster (unused, always 0)
144  * 28 2 unicode character 12
145  * 30 2 unicode character 13
146  *
147  * The ordinal field contains a descending number, from n to 1.
148  * For the n'th lfn entry the ordinal field is or'ed with 0x40.
149  * For deleted lfn entries, the ordinal field is set to 0xe5.
150  */
151 
153 {
154  offset_t size;
155 
156  offset_t fat_offset;
157  uint32_t fat_size;
158 
159  uint16_t sector_size;
160  uint16_t cluster_size;
161 
162  offset_t cluster_zero_offset;
163 
164  offset_t root_dir_offset;
165 #if FAT_FAT32_SUPPORT
166  cluster_t root_dir_cluster;
167 #endif
168 };
169 
171 {
172  struct partition_struct* partition;
173  struct fat_header_struct header;
174  cluster_t cluster_free;
175 };
176 
178 {
179  struct fat_fs_struct* fs;
180  struct fat_dir_entry_struct dir_entry;
181  offset_t pos;
182  cluster_t pos_cluster;
183 };
184 
186 {
187  struct fat_fs_struct* fs;
188  struct fat_dir_entry_struct dir_entry;
189  cluster_t entry_cluster;
190  uint16_t entry_offset;
191 };
192 
194 {
195  struct fat_dir_entry_struct* dir_entry;
196  uintptr_t bytes_read;
197 #if FAT_LFN_SUPPORT
198  uint8_t checksum;
199 #endif
200  uint8_t finished;
201 };
202 
204 {
205  cluster_t cluster_count;
206  uintptr_t buffer_size;
207 };
208 
209 #if !USE_DYNAMIC_MEMORY
210 static struct fat_fs_struct fat_fs_handles[FAT_FS_COUNT];
211 static struct fat_file_struct fat_file_handles[FAT_FILE_COUNT];
212 static struct fat_dir_struct fat_dir_handles[FAT_DIR_COUNT];
213 #endif
214 
215 static uint8_t fat_read_header ( struct fat_fs_struct* fs );
216 static cluster_t fat_get_next_cluster ( const struct fat_fs_struct* fs, cluster_t cluster_num );
217 static offset_t fat_cluster_offset ( const struct fat_fs_struct* fs, cluster_t cluster_num );
218 static uint8_t fat_dir_entry_read_callback ( uint8_t* buffer, offset_t offset, void* p );
219 #if FAT_LFN_SUPPORT
220 static uint8_t fat_calc_83_checksum ( const uint8_t* file_name_83 );
221 #endif
222 
223 static uint8_t fat_get_fs_free_16_callback ( uint8_t* buffer, offset_t offset, void* p );
224 #if FAT_FAT32_SUPPORT
225 static uint8_t fat_get_fs_free_32_callback ( uint8_t* buffer, offset_t offset, void* p );
226 #endif
227 
228 #if FAT_WRITE_SUPPORT
229 static cluster_t fat_append_clusters ( struct fat_fs_struct* fs, cluster_t cluster_num, cluster_t count );
230 static uint8_t fat_free_clusters ( struct fat_fs_struct* fs, cluster_t cluster_num );
231 static uint8_t fat_terminate_clusters ( struct fat_fs_struct* fs, cluster_t cluster_num );
232 static uint8_t fat_clear_cluster ( const struct fat_fs_struct* fs, cluster_t cluster_num );
233 static uintptr_t fat_clear_cluster_callback ( uint8_t* buffer, offset_t offset, void* p );
234 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 );
235 static uint8_t fat_write_dir_entry ( const struct fat_fs_struct* fs, struct fat_dir_entry_struct* dir_entry );
236 #if FAT_DATETIME_SUPPORT
237 static void fat_set_file_modification_date ( struct fat_dir_entry_struct* dir_entry, uint16_t year, uint8_t month, uint8_t day );
238 static void fat_set_file_modification_time ( struct fat_dir_entry_struct* dir_entry, uint8_t hour, uint8_t min, uint8_t sec );
239 #endif
240 #endif
241 
250 struct fat_fs_struct* fat_open ( struct partition_struct* partition )
251 {
252  if ( !partition ||
254  !partition->device_write || !partition->device_write_interval
255 #else
256  0
257 #endif
258  ) return 0;
259 
260 #if USE_DYNAMIC_MEMORY
261  struct fat_fs_struct* fs = malloc(sizeof(*fs));
262  if(!fs)
263  return 0;
264 #else
265  struct fat_fs_struct* fs = fat_fs_handles;
266  uint8_t i;
267  for ( i = 0; i < FAT_FS_COUNT; ++i )
268  {
269  if ( !fs->partition ) break;
270 
271  ++fs;
272  }
273  if ( i >= FAT_FS_COUNT ) return 0;
274 #endif
275 
276  memset ( fs, 0, sizeof(*fs) );
277 
278  fs->partition = partition;
279  if ( !fat_read_header ( fs ) )
280  {
281 #if USE_DYNAMIC_MEMORY
282  free(fs);
283 #else
284  fs->partition = 0;
285 #endif
286  return 0;
287  }
288 
289  return fs;
290 }
291 
302 void fat_close ( struct fat_fs_struct* fs )
303 {
304  if ( !fs ) return;
305 
306 #if USE_DYNAMIC_MEMORY
307  free(fs);
308 #else
309  fs->partition = 0;
310 #endif
311 }
312 
320 uint8_t fat_read_header ( struct fat_fs_struct* fs )
321 {
322  if ( !fs ) return 0;
323 
324  struct partition_struct* partition = fs->partition;
325  if ( !partition ) return 0;
326 
327  /* read fat parameters */
328 #if FAT_FAT32_SUPPORT
329  uint8_t buffer[37];
330 #else
331  uint8_t buffer[25];
332 #endif
333  offset_t partition_offset = (offset_t) partition->offset * 512;
334  if ( !partition->device_read ( partition_offset + 0x0b, buffer, sizeof(buffer) ) ) return 0;
335 
336  uint16_t bytes_per_sector = read16( &buffer[0x00] );
337  uint16_t reserved_sectors = read16( &buffer[0x03] );
338  uint8_t sectors_per_cluster = buffer[0x02];
339  uint8_t fat_copies = buffer[0x05];
340  uint16_t max_root_entries = read16( &buffer[0x06] );
341  uint16_t sector_count_16 = read16( &buffer[0x08] );
342  uint16_t sectors_per_fat = read16( &buffer[0x0b] );
343  uint32_t sector_count = read32( &buffer[0x15] );
344 #if FAT_FAT32_SUPPORT
345  uint32_t sectors_per_fat32 = read32( &buffer[0x19] );
346  uint32_t cluster_root_dir = read32( &buffer[0x21] );
347 #endif
348 
349  if ( sector_count == 0 )
350  {
351  if ( sector_count_16 == 0 )
352  /* illegal volume size */
353  return 0;
354  else
355  sector_count = sector_count_16;
356  }
357 #if FAT_FAT32_SUPPORT
358  if ( sectors_per_fat != 0 )
359  sectors_per_fat32 = sectors_per_fat;
360  else if ( sectors_per_fat32 == 0 )
361  /* this is neither FAT16 nor FAT32 */
362  return 0;
363 #else
364  if(sectors_per_fat == 0)
365  /* this is not a FAT16 */
366  return 0;
367 #endif
368 
369  /* determine the type of FAT we have here */
370  uint32_t data_sector_count = sector_count - reserved_sectors
371 #if FAT_FAT32_SUPPORT
372  - sectors_per_fat32 * fat_copies
373 #else
374  - (uint32_t) sectors_per_fat * fat_copies
375 #endif
376  - ((max_root_entries * 32 + bytes_per_sector - 1) / bytes_per_sector);
377  uint32_t data_cluster_count = data_sector_count / sectors_per_cluster;
378  if ( data_cluster_count < 4085 )
379  /* this is a FAT12, not supported */
380  return 0;
381  else if ( data_cluster_count < 65525 )
382  /* this is a FAT16 */
383  partition->type = PARTITION_TYPE_FAT16;
384  else
385  /* this is a FAT32 */
386  partition->type = PARTITION_TYPE_FAT32;
387 
388  /* fill header information */
389  struct fat_header_struct* header = &fs->header;
390  memset ( header, 0, sizeof(*header) );
391 
392  header->size = (offset_t) sector_count * bytes_per_sector;
393 
394  header->fat_offset = /* jump to partition */
395  partition_offset +
396  /* jump to fat */
397  (offset_t) reserved_sectors * bytes_per_sector;
398  header->fat_size = (data_cluster_count + 2) * (partition->type == PARTITION_TYPE_FAT16 ? 2 : 4);
399 
400  header->sector_size = bytes_per_sector;
401  header->cluster_size = (uint16_t) bytes_per_sector * sectors_per_cluster;
402 
403 #if FAT_FAT32_SUPPORT
404  if ( partition->type == PARTITION_TYPE_FAT16 )
405 #endif
406  {
407  header->root_dir_offset = /* jump to fats */
408  header->fat_offset +
409  /* jump to root directory entries */
410  (offset_t) fat_copies * sectors_per_fat * bytes_per_sector;
411 
412  header->cluster_zero_offset = /* jump to root directory entries */
413  header->root_dir_offset +
414  /* skip root directory entries */
415  (offset_t) max_root_entries * 32;
416  }
417 #if FAT_FAT32_SUPPORT
418  else
419  {
420  header->cluster_zero_offset = /* jump to fats */
421  header->fat_offset +
422  /* skip fats */
423  (offset_t) fat_copies * sectors_per_fat32 * bytes_per_sector;
424 
425  header->root_dir_cluster = cluster_root_dir;
426  }
427 #endif
428 
429  return 1;
430 }
431 
444 cluster_t fat_get_next_cluster ( const struct fat_fs_struct* fs, cluster_t cluster_num )
445 {
446  if ( !fs || cluster_num < 2 ) return 0;
447 
448 #if FAT_FAT32_SUPPORT
449  if ( fs->partition->type == PARTITION_TYPE_FAT32 )
450  {
451  /* read appropriate fat entry */
452  uint32_t fat_entry;
453  if ( !fs->partition->device_read ( fs->header.fat_offset + (offset_t) cluster_num * sizeof(fat_entry), (uint8_t*) &fat_entry, sizeof(fat_entry) ) ) return 0;
454 
455  /* determine next cluster from fat */
456  cluster_num = ltoh32( fat_entry );
457 
458  if ( cluster_num == FAT32_CLUSTER_FREE || cluster_num == FAT32_CLUSTER_BAD || (cluster_num >= FAT32_CLUSTER_RESERVED_MIN && cluster_num <= FAT32_CLUSTER_RESERVED_MAX)
459  || (cluster_num >= FAT32_CLUSTER_LAST_MIN && cluster_num <= FAT32_CLUSTER_LAST_MAX) ) return 0;
460  }
461  else
462 #endif
463  {
464  /* read appropriate fat entry */
465  uint16_t fat_entry;
466  if ( !fs->partition->device_read ( fs->header.fat_offset + (offset_t) cluster_num * sizeof(fat_entry), (uint8_t*) &fat_entry, sizeof(fat_entry) ) ) return 0;
467 
468  /* determine next cluster from fat */
469  cluster_num = ltoh16( fat_entry );
470 
471  if ( cluster_num == FAT16_CLUSTER_FREE || cluster_num == FAT16_CLUSTER_BAD || (cluster_num >= FAT16_CLUSTER_RESERVED_MIN && cluster_num <= FAT16_CLUSTER_RESERVED_MAX)
472  || (cluster_num >= FAT16_CLUSTER_LAST_MIN && cluster_num <= FAT16_CLUSTER_LAST_MAX) ) return 0;
473  }
474 
475  return cluster_num;
476 }
477 
478 #if DOXYGEN || FAT_WRITE_SUPPORT
479 
490 cluster_t fat_append_clusters ( struct fat_fs_struct* fs, cluster_t cluster_num, cluster_t count )
491 {
492  if ( !fs ) return 0;
493 
494  device_read_t device_read = fs->partition->device_read;
495  device_write_t device_write = fs->partition->device_write;
496  offset_t fat_offset = fs->header.fat_offset;
497  cluster_t count_left = count;
498  cluster_t cluster_current = fs->cluster_free;
499  cluster_t cluster_next = 0;
500  cluster_t cluster_count;
501  uint16_t fat_entry16;
502 #if FAT_FAT32_SUPPORT
503  uint32_t fat_entry32;
504  uint8_t is_fat32 = (fs->partition->type == PARTITION_TYPE_FAT32);
505 
506  if ( is_fat32 )
507  cluster_count = fs->header.fat_size / sizeof(fat_entry32);
508  else
509 #endif
510  cluster_count = fs->header.fat_size / sizeof(fat_entry16);
511 
512  fs->cluster_free = 0;
513  for ( cluster_t cluster_left = cluster_count; cluster_left > 0; --cluster_left, ++cluster_current )
514  {
515  if ( cluster_current < 2 || cluster_current >= cluster_count ) cluster_current = 2;
516 
517 #if FAT_FAT32_SUPPORT
518  if ( is_fat32 )
519  {
520  if ( !device_read ( fat_offset + (offset_t) cluster_current * sizeof(fat_entry32), (uint8_t*) &fat_entry32, sizeof(fat_entry32) ) ) return 0;
521  }
522  else
523 #endif
524  {
525  if ( !device_read ( fat_offset + (offset_t) cluster_current * sizeof(fat_entry16), (uint8_t*) &fat_entry16, sizeof(fat_entry16) ) ) return 0;
526  }
527 
528 #if FAT_FAT32_SUPPORT
529  if ( is_fat32 )
530  {
531  /* check if this is a free cluster */
532  if ( fat_entry32 != HTOL32( FAT32_CLUSTER_FREE ) ) continue;
533 
534  /* If we don't need this free cluster for the
535  * current allocation, we keep it in mind for
536  * the next time.
537  */
538  if ( count_left == 0 )
539  {
540  fs->cluster_free = cluster_current;
541  break;
542  }
543 
544  /* allocate cluster */
545  if ( cluster_next == 0 )
546  fat_entry32 = HTOL32( FAT32_CLUSTER_LAST_MAX );
547  else
548  fat_entry32 = htol32( cluster_next );
549 
550  if ( !device_write ( fat_offset + (offset_t) cluster_current * sizeof(fat_entry32), (uint8_t*) &fat_entry32, sizeof(fat_entry32) ) ) break;
551  }
552  else
553 #endif
554  {
555  /* check if this is a free cluster */
556  if ( fat_entry16 != HTOL16( FAT16_CLUSTER_FREE ) ) continue;
557 
558  /* If we don't need this free cluster for the
559  * current allocation, we keep it in mind for
560  * the next time.
561  */
562  if ( count_left == 0 )
563  {
564  fs->cluster_free = cluster_current;
565  break;
566  }
567 
568  /* allocate cluster */
569  if ( cluster_next == 0 )
570  fat_entry16 = HTOL16( FAT16_CLUSTER_LAST_MAX );
571  else
572  fat_entry16 = htol16( (uint16_t ) cluster_next );
573 
574  if ( !device_write ( fat_offset + (offset_t) cluster_current * sizeof(fat_entry16), (uint8_t*) &fat_entry16, sizeof(fat_entry16) ) ) break;
575  }
576 
577  cluster_next = cluster_current;
578  --count_left;
579  }
580 
581  do
582  {
583  if ( count_left > 0 ) break;
584 
585  /* We allocated a new cluster chain. Now join
586  * it with the existing one (if any).
587  */
588  if ( cluster_num >= 2 )
589  {
590 #if FAT_FAT32_SUPPORT
591  if ( is_fat32 )
592  {
593  fat_entry32 = htol32( cluster_next );
594 
595  if ( !device_write ( fat_offset + (offset_t) cluster_num * sizeof(fat_entry32), (uint8_t*) &fat_entry32, sizeof(fat_entry32) ) ) break;
596  }
597  else
598 #endif
599  {
600  fat_entry16 = htol16( (uint16_t ) cluster_next );
601 
602  if ( !device_write ( fat_offset + (offset_t) cluster_num * sizeof(fat_entry16), (uint8_t*) &fat_entry16, sizeof(fat_entry16) ) ) break;
603  }
604  }
605 
606  return cluster_next;
607 
608  }
609  while ( 0 );
610 
611  /* No space left on device or writing error.
612  * Free up all clusters already allocated.
613  */
614  fat_free_clusters ( fs, cluster_next );
615 
616  return 0;
617 }
618 #endif
619 
620 #if DOXYGEN || FAT_WRITE_SUPPORT
621 
638 uint8_t fat_free_clusters ( struct fat_fs_struct* fs, cluster_t cluster_num )
639 {
640  if ( !fs || cluster_num < 2 ) return 0;
641 
642  offset_t fat_offset = fs->header.fat_offset;
643 #if FAT_FAT32_SUPPORT
644  if ( fs->partition->type == PARTITION_TYPE_FAT32 )
645  {
646  uint32_t fat_entry;
647  while ( cluster_num )
648  {
649  if ( !fs->partition->device_read ( fat_offset + (offset_t) cluster_num * sizeof(fat_entry), (uint8_t*) &fat_entry, sizeof(fat_entry) ) ) return 0;
650 
651  /* get next cluster of current cluster before freeing current cluster */
652  uint32_t cluster_num_next = ltoh32( fat_entry );
653 
654  if ( cluster_num_next == FAT32_CLUSTER_FREE ) return 1;
655  if ( cluster_num_next == FAT32_CLUSTER_BAD || (cluster_num_next >= FAT32_CLUSTER_RESERVED_MIN && cluster_num_next <= FAT32_CLUSTER_RESERVED_MAX) ) return 0;
656  if ( cluster_num_next >= FAT32_CLUSTER_LAST_MIN && cluster_num_next <= FAT32_CLUSTER_LAST_MAX ) cluster_num_next = 0;
657 
658  /* We know we will free the cluster, so remember it as
659  * free for the next allocation.
660  */
661  if ( !fs->cluster_free ) fs->cluster_free = cluster_num;
662 
663  /* free cluster */
664  fat_entry = HTOL32( FAT32_CLUSTER_FREE );
665  fs->partition->device_write ( fat_offset + (offset_t) cluster_num * sizeof(fat_entry), (uint8_t*) &fat_entry, sizeof(fat_entry) );
666 
667  /* We continue in any case here, even if freeing the cluster failed.
668  * The cluster is lost, but maybe we can still free up some later ones.
669  */
670 
671  cluster_num = cluster_num_next;
672  }
673  }
674  else
675 #endif
676  {
677  uint16_t fat_entry;
678  while ( cluster_num )
679  {
680  if ( !fs->partition->device_read ( fat_offset + (offset_t) cluster_num * sizeof(fat_entry), (uint8_t*) &fat_entry, sizeof(fat_entry) ) ) return 0;
681 
682  /* get next cluster of current cluster before freeing current cluster */
683  uint16_t cluster_num_next = ltoh16( fat_entry );
684 
685  if ( cluster_num_next == FAT16_CLUSTER_FREE ) return 1;
686  if ( cluster_num_next == FAT16_CLUSTER_BAD || (cluster_num_next >= FAT16_CLUSTER_RESERVED_MIN && cluster_num_next <= FAT16_CLUSTER_RESERVED_MAX) ) return 0;
687  if ( cluster_num_next >= FAT16_CLUSTER_LAST_MIN && cluster_num_next <= FAT16_CLUSTER_LAST_MAX ) cluster_num_next = 0;
688 
689  /* free cluster */
690  fat_entry = HTOL16( FAT16_CLUSTER_FREE );
691  fs->partition->device_write ( fat_offset + (offset_t) cluster_num * sizeof(fat_entry), (uint8_t*) &fat_entry, sizeof(fat_entry) );
692 
693  /* We continue in any case here, even if freeing the cluster failed.
694  * The cluster is lost, but maybe we can still free up some later ones.
695  */
696 
697  cluster_num = cluster_num_next;
698  }
699  }
700 
701  return 1;
702 }
703 #endif
704 
705 #if DOXYGEN || FAT_WRITE_SUPPORT
706 
718 uint8_t fat_terminate_clusters ( struct fat_fs_struct* fs, cluster_t cluster_num )
719 {
720  if ( !fs || cluster_num < 2 ) return 0;
721 
722  /* fetch next cluster before overwriting the cluster entry */
723  cluster_t cluster_num_next = fat_get_next_cluster ( fs, cluster_num );
724 
725  /* mark cluster as the last one */
726 #if FAT_FAT32_SUPPORT
727  if ( fs->partition->type == PARTITION_TYPE_FAT32 )
728  {
729  uint32_t fat_entry = HTOL32( FAT32_CLUSTER_LAST_MAX );
730  if ( !fs->partition->device_write ( fs->header.fat_offset + (offset_t) cluster_num * sizeof(fat_entry), (uint8_t*) &fat_entry, sizeof(fat_entry) ) ) return 0;
731  }
732  else
733 #endif
734  {
735  uint16_t fat_entry = HTOL16( FAT16_CLUSTER_LAST_MAX );
736  if ( !fs->partition->device_write ( fs->header.fat_offset + (offset_t) cluster_num * sizeof(fat_entry), (uint8_t*) &fat_entry, sizeof(fat_entry) ) ) return 0;
737  }
738 
739  /* free remaining clusters */
740  if ( cluster_num_next )
741  return fat_free_clusters ( fs, cluster_num_next );
742  else
743  return 1;
744 }
745 #endif
746 
747 #if DOXYGEN || FAT_WRITE_SUPPORT
748 
758 uint8_t fat_clear_cluster ( const struct fat_fs_struct* fs, cluster_t cluster_num )
759 {
760  if ( cluster_num < 2 ) return 0;
761 
762  offset_t cluster_offset = fat_cluster_offset ( fs, cluster_num );
763 
764  uint8_t zero[16];
765  memset ( zero, 0, sizeof(zero) );
766  return fs->partition->device_write_interval ( cluster_offset, zero, fs->header.cluster_size, fat_clear_cluster_callback, 0 );
767 }
768 #endif
769 
770 #if DOXYGEN || FAT_WRITE_SUPPORT
771 
775 uintptr_t fat_clear_cluster_callback ( uint8_t* buffer, offset_t offset, void* p )
776 {
777  return 16;
778 }
779 #endif
780 
789 offset_t fat_cluster_offset ( const struct fat_fs_struct* fs, cluster_t cluster_num )
790 {
791  if ( !fs || cluster_num < 2 ) return 0;
792 
793  return fs->header.cluster_zero_offset + (offset_t) (cluster_num - 2) * fs->header.cluster_size;
794 }
795 
808 uint8_t fat_get_dir_entry_of_path ( struct fat_fs_struct* fs, const char* path, struct fat_dir_entry_struct* dir_entry )
809 {
810  if ( !fs || !path || path[0] == '\0' || !dir_entry ) return 0;
811 
812  if ( path[0] == '/' ) ++path;
813 
814  /* begin with the root directory */
815  memset ( dir_entry, 0, sizeof(*dir_entry) );
816  dir_entry->attributes = FAT_ATTRIB_DIR;
817 
818  while ( 1 )
819  {
820  if ( path[0] == '\0' ) return 1;
821 
822  struct fat_dir_struct* dd = fat_open_dir ( fs, dir_entry );
823  if ( !dd ) break;
824 
825  /* extract the next hierarchy we will search for */
826  const char* sub_path = strchr ( path, '/' );
827  uint8_t length_to_sep;
828  if ( sub_path )
829  {
830  length_to_sep = sub_path - path;
831  ++sub_path;
832  }
833  else
834  {
835  length_to_sep = strlen ( path );
836  sub_path = path + length_to_sep;
837  }
838 
839  /* read directory entries */
840  while ( fat_read_dir ( dd, dir_entry ) )
841  {
842  /* check if we have found the next hierarchy */
843  if ( (strlen ( dir_entry->long_name ) != length_to_sep || strncmp ( path, dir_entry->long_name, length_to_sep ) != 0) ) continue;
844 
845  fat_close_dir ( dd );
846  dd = 0;
847 
848  if ( path[length_to_sep] == '\0' )
849  /* we iterated through the whole path and have found the file */
850  return 1;
851 
852  if ( dir_entry->attributes & FAT_ATTRIB_DIR )
853  {
854  /* we found a parent directory of the file we are searching for */
855  path = sub_path;
856  break;
857  }
858 
859  /* a parent of the file exists, but not the file itself */
860  return 0;
861  }
862 
863  fat_close_dir ( dd );
864  }
865 
866  return 0;
867 }
868 
878 struct fat_file_struct* fat_open_file ( struct fat_fs_struct* fs, const struct fat_dir_entry_struct* dir_entry )
879 {
880  if ( !fs || !dir_entry || (dir_entry->attributes & FAT_ATTRIB_DIR) ) return 0;
881 
882 #if USE_DYNAMIC_MEMORY
883  struct fat_file_struct* fd = malloc(sizeof(*fd));
884  if(!fd)
885  return 0;
886 #else
887  struct fat_file_struct* fd = fat_file_handles;
888  uint8_t i;
889  for ( i = 0; i < FAT_FILE_COUNT; ++i )
890  {
891  if ( !fd->fs ) break;
892 
893  ++fd;
894  }
895  if ( i >= FAT_FILE_COUNT ) return 0;
896 #endif
897 
898  memcpy ( &fd->dir_entry, dir_entry, sizeof(*dir_entry) );
899  fd->fs = fs;
900  fd->pos = 0;
901  fd->pos_cluster = dir_entry->cluster;
902 
903  return fd;
904 }
905 
913 void fat_close_file ( struct fat_file_struct* fd )
914 {
915  if ( fd )
916  {
917 #if FAT_DELAY_DIRENTRY_UPDATE
918  /* write directory entry */
919  fat_write_dir_entry(fd->fs, &fd->dir_entry);
920 #endif
921 
922 #if USE_DYNAMIC_MEMORY
923  free(fd);
924 #else
925  fd->fs = 0;
926 #endif
927  }
928 }
929 
942 intptr_t fat_read_file ( struct fat_file_struct* fd, uint8_t* buffer, uintptr_t buffer_len )
943 {
944  /* check arguments */
945  if ( !fd || !buffer || buffer_len < 1 ) return -1;
946 
947  /* determine number of bytes to read */
948  if ( fd->pos + buffer_len > fd->dir_entry.file_size ) buffer_len = fd->dir_entry.file_size - fd->pos;
949  if ( buffer_len == 0 ) return 0;
950 
951  uint16_t cluster_size = fd->fs->header.cluster_size;
952  cluster_t cluster_num = fd->pos_cluster;
953  uintptr_t buffer_left = buffer_len;
954  uint16_t first_cluster_offset = (uint16_t) (fd->pos & (cluster_size - 1));
955 
956  /* find cluster in which to start reading */
957  if ( !cluster_num )
958  {
959  cluster_num = fd->dir_entry.cluster;
960 
961  if ( !cluster_num )
962  {
963  if ( !fd->pos )
964  return 0;
965  else
966  return -1;
967  }
968 
969  if ( fd->pos )
970  {
971  uint32_t pos = fd->pos;
972  while ( pos >= cluster_size )
973  {
974  pos -= cluster_size;
975  cluster_num = fat_get_next_cluster ( fd->fs, cluster_num );
976  if ( !cluster_num ) return -1;
977  }
978  }
979  }
980 
981  /* read data */
982  do
983  {
984  /* calculate data size to copy from cluster */
985  offset_t cluster_offset = fat_cluster_offset ( fd->fs, cluster_num ) + first_cluster_offset;
986  uint16_t copy_length = cluster_size - first_cluster_offset;
987  if ( copy_length > buffer_left ) copy_length = buffer_left;
988 
989  /* read data */
990  if ( !fd->fs->partition->device_read ( cluster_offset, buffer, copy_length ) ) return buffer_len - buffer_left;
991 
992  /* calculate new file position */
993  buffer += copy_length;
994  buffer_left -= copy_length;
995  fd->pos += copy_length;
996 
997  if ( first_cluster_offset + copy_length >= cluster_size )
998  {
999  /* we are on a cluster boundary, so get the next cluster */
1000  if ( (cluster_num = fat_get_next_cluster ( fd->fs, cluster_num )) )
1001  {
1002  first_cluster_offset = 0;
1003  }
1004  else
1005  {
1006  fd->pos_cluster = 0;
1007  return buffer_len - buffer_left;
1008  }
1009  }
1010 
1011  fd->pos_cluster = cluster_num;
1012 
1013  }
1014  while ( buffer_left > 0 ); /* check if we are done */
1015 
1016  return buffer_len;
1017 }
1018 
1019 #if DOXYGEN || FAT_WRITE_SUPPORT
1020 
1032 intptr_t fat_write_file ( struct fat_file_struct* fd, const uint8_t* buffer, uintptr_t buffer_len )
1033 {
1034  /* check arguments */
1035  if ( !fd || !buffer || buffer_len < 1 ) return -1;
1036  if ( fd->pos > fd->dir_entry.file_size ) return -1;
1037 
1038  uint16_t cluster_size = fd->fs->header.cluster_size;
1039  cluster_t cluster_num = fd->pos_cluster;
1040  uintptr_t buffer_left = buffer_len;
1041  uint16_t first_cluster_offset = (uint16_t) (fd->pos & (cluster_size - 1));
1042 
1043  /* find cluster in which to start writing */
1044  if ( !cluster_num )
1045  {
1046  cluster_num = fd->dir_entry.cluster;
1047 
1048  if ( !cluster_num )
1049  {
1050  if ( !fd->pos )
1051  {
1052  /* empty file */
1053  fd->dir_entry.cluster = cluster_num = fat_append_clusters ( fd->fs, 0, 1 );
1054  if ( !cluster_num ) return 0;
1055  }
1056  else
1057  {
1058  return -1;
1059  }
1060  }
1061 
1062  if ( fd->pos )
1063  {
1064  uint32_t pos = fd->pos;
1065  cluster_t cluster_num_next;
1066  while ( pos >= cluster_size )
1067  {
1068  pos -= cluster_size;
1069  cluster_num_next = fat_get_next_cluster ( fd->fs, cluster_num );
1070  if ( !cluster_num_next )
1071  {
1072  if ( pos != 0 ) return -1; /* current file position points beyond end of file */
1073 
1074  /* the file exactly ends on a cluster boundary, and we append to it */
1075  cluster_num_next = fat_append_clusters ( fd->fs, cluster_num, 1 );
1076  if ( !cluster_num_next ) return 0;
1077  }
1078 
1079  cluster_num = cluster_num_next;
1080  }
1081  }
1082  }
1083 
1084  /* write data */
1085  do
1086  {
1087  /* calculate data size to write to cluster */
1088  offset_t cluster_offset = fat_cluster_offset ( fd->fs, cluster_num ) + first_cluster_offset;
1089  uint16_t write_length = cluster_size - first_cluster_offset;
1090  if ( write_length > buffer_left ) write_length = buffer_left;
1091 
1092  /* write data which fits into the current cluster */
1093  if ( !fd->fs->partition->device_write ( cluster_offset, buffer, write_length ) ) break;
1094 
1095  /* calculate new file position */
1096  buffer += write_length;
1097  buffer_left -= write_length;
1098  fd->pos += write_length;
1099 
1100  if ( first_cluster_offset + write_length >= cluster_size )
1101  {
1102  /* we are on a cluster boundary, so get the next cluster */
1103  cluster_t cluster_num_next = fat_get_next_cluster ( fd->fs, cluster_num );
1104  if ( !cluster_num_next && buffer_left > 0 )
1105  /* we reached the last cluster, append a new one */
1106  cluster_num_next = fat_append_clusters ( fd->fs, cluster_num, 1 );
1107  if ( !cluster_num_next )
1108  {
1109  fd->pos_cluster = 0;
1110  break;
1111  }
1112 
1113  cluster_num = cluster_num_next;
1114  first_cluster_offset = 0;
1115  }
1116 
1117  fd->pos_cluster = cluster_num;
1118 
1119  }
1120  while ( buffer_left > 0 ); /* check if we are done */
1121 
1122  /* update directory entry */
1123  if ( fd->pos > fd->dir_entry.file_size )
1124  {
1125 #if !FAT_DELAY_DIRENTRY_UPDATE
1126  uint32_t size_old = fd->dir_entry.file_size;
1127 #endif
1128 
1129  /* update file size */
1130  fd->dir_entry.file_size = fd->pos;
1131 
1132 #if !FAT_DELAY_DIRENTRY_UPDATE
1133  /* write directory entry */
1134  if ( !fat_write_dir_entry ( fd->fs, &fd->dir_entry ) )
1135  {
1136  /* We do not return an error here since we actually wrote
1137  * some data to disk. So we calculate the amount of data
1138  * we wrote to disk and which lies within the old file size.
1139  */
1140  buffer_left = fd->pos - size_old;
1141  fd->pos = size_old;
1142  }
1143 #endif
1144  }
1145 
1146  return buffer_len - buffer_left;
1147 }
1148 #endif
1149 
1186 uint8_t fat_seek_file ( struct fat_file_struct* fd, int32_t* offset, uint8_t whence )
1187 {
1188  if ( !fd || !offset ) return 0;
1189 
1190  uint32_t new_pos = fd->pos;
1191  switch (whence)
1192  {
1193  case FAT_SEEK_SET:
1194  new_pos = *offset;
1195  break;
1196  case FAT_SEEK_CUR:
1197  new_pos += *offset;
1198  break;
1199  case FAT_SEEK_END:
1200  new_pos = fd->dir_entry.file_size + *offset;
1201  break;
1202  default:
1203  return 0;
1204  }
1205 
1206  if ( new_pos > fd->dir_entry.file_size
1208  && !fat_resize_file ( fd, new_pos )
1209 #endif
1210  ) return 0;
1211 
1212  fd->pos = new_pos;
1213  fd->pos_cluster = 0;
1214 
1215  *offset = (int32_t) new_pos;
1216  return 1;
1217 }
1218 
1219 #if DOXYGEN || FAT_WRITE_SUPPORT
1220 
1239 uint8_t fat_resize_file ( struct fat_file_struct* fd, uint32_t size )
1240 {
1241  if ( !fd ) return 0;
1242 
1243  cluster_t cluster_num = fd->dir_entry.cluster;
1244  uint16_t cluster_size = fd->fs->header.cluster_size;
1245  uint32_t size_new = size;
1246 
1247  do
1248  {
1249  if ( cluster_num == 0 && size_new == 0 )
1250  /* the file stays empty */
1251  break;
1252 
1253  /* seek to the next cluster as long as we need the space */
1254  while ( size_new > cluster_size )
1255  {
1256  /* get next cluster of file */
1257  cluster_t cluster_num_next = fat_get_next_cluster ( fd->fs, cluster_num );
1258  if ( cluster_num_next )
1259  {
1260  cluster_num = cluster_num_next;
1261  size_new -= cluster_size;
1262  }
1263  else
1264  {
1265  break;
1266  }
1267  }
1268 
1269  if ( size_new > cluster_size || cluster_num == 0 )
1270  {
1271  /* Allocate new cluster chain and append
1272  * it to the existing one, if available.
1273  */
1274  cluster_t cluster_count = (size_new + cluster_size - 1) / cluster_size;
1275  cluster_t cluster_new_chain = fat_append_clusters ( fd->fs, cluster_num, cluster_count );
1276  if ( !cluster_new_chain ) return 0;
1277 
1278  if ( !cluster_num )
1279  {
1280  cluster_num = cluster_new_chain;
1281  fd->dir_entry.cluster = cluster_num;
1282  }
1283  }
1284 
1285  /* write new directory entry */
1286  fd->dir_entry.file_size = size;
1287  if ( size == 0 ) fd->dir_entry.cluster = 0;
1288  if ( !fat_write_dir_entry ( fd->fs, &fd->dir_entry ) ) return 0;
1289 
1290  if ( size == 0 )
1291  {
1292  /* free all clusters of file */
1293  fat_free_clusters ( fd->fs, cluster_num );
1294  }
1295  else if ( size_new <= cluster_size )
1296  {
1297  /* free all clusters no longer needed */
1298  fat_terminate_clusters ( fd->fs, cluster_num );
1299  }
1300 
1301  }
1302  while ( 0 );
1303 
1304  /* correct file position */
1305  if ( size < fd->pos )
1306  {
1307  fd->pos = size;
1308  fd->pos_cluster = 0;
1309  }
1310 
1311  return 1;
1312 }
1313 #endif
1314 
1324 struct fat_dir_struct* fat_open_dir ( struct fat_fs_struct* fs, const struct fat_dir_entry_struct* dir_entry )
1325 {
1326  if ( !fs || !dir_entry || !(dir_entry->attributes & FAT_ATTRIB_DIR) ) return 0;
1327 
1328 #if USE_DYNAMIC_MEMORY
1329  struct fat_dir_struct* dd = malloc(sizeof(*dd));
1330  if(!dd)
1331  return 0;
1332 #else
1333  struct fat_dir_struct* dd = fat_dir_handles;
1334  uint8_t i;
1335  for ( i = 0; i < FAT_DIR_COUNT; ++i )
1336  {
1337  if ( !dd->fs ) break;
1338 
1339  ++dd;
1340  }
1341  if ( i >= FAT_DIR_COUNT ) return 0;
1342 #endif
1343 
1344  memcpy ( &dd->dir_entry, dir_entry, sizeof(*dir_entry) );
1345  dd->fs = fs;
1346  dd->entry_cluster = dir_entry->cluster;
1347  dd->entry_offset = 0;
1348 
1349  return dd;
1350 }
1351 
1363 void fat_close_dir ( struct fat_dir_struct* dd )
1364 {
1365  if ( dd )
1366 #if USE_DYNAMIC_MEMORY
1367  free(dd);
1368 #else
1369  dd->fs = 0;
1370 #endif
1371 }
1372 
1382 uint8_t fat_read_dir ( struct fat_dir_struct* dd, struct fat_dir_entry_struct* dir_entry )
1383 {
1384  if ( !dd || !dir_entry ) return 0;
1385 
1386  /* get current position of directory handle */
1387  struct fat_fs_struct* fs = dd->fs;
1388  const struct fat_header_struct* header = &fs->header;
1389  uint16_t cluster_size = header->cluster_size;
1390  cluster_t cluster_num = dd->entry_cluster;
1391  uint16_t cluster_offset = dd->entry_offset;
1392  struct fat_read_dir_callback_arg arg;
1393 
1394  if ( cluster_offset >= cluster_size )
1395  {
1396  /* The latest call hit the border of the last cluster in
1397  * the chain, but it still returned a directory entry.
1398  * So we now reset the handle and signal the caller the
1399  * end of the listing.
1400  */
1401  fat_reset_dir ( dd );
1402  return 0;
1403  }
1404 
1405  /* reset callback arguments */
1406  memset ( &arg, 0, sizeof(arg) );
1407  memset ( dir_entry, 0, sizeof(*dir_entry) );
1408  arg.dir_entry = dir_entry;
1409 
1410  /* check if we read from the root directory */
1411  if ( cluster_num == 0 )
1412  {
1413 #if FAT_FAT32_SUPPORT
1414  if ( fs->partition->type == PARTITION_TYPE_FAT32 )
1415  cluster_num = header->root_dir_cluster;
1416  else
1417 #endif
1418  cluster_size = header->cluster_zero_offset - header->root_dir_offset;
1419  }
1420 
1421  /* read entries */
1422  uint8_t buffer[32];
1423  while ( !arg.finished )
1424  {
1425  /* read directory entries up to the cluster border */
1426  uint16_t cluster_left = cluster_size - cluster_offset;
1427  offset_t pos = cluster_offset;
1428  if ( cluster_num == 0 )
1429  pos += header->root_dir_offset;
1430  else
1431  pos += fat_cluster_offset ( fs, cluster_num );
1432 
1433  arg.bytes_read = 0;
1434  if ( !fs->partition->device_read_interval ( pos, buffer, sizeof(buffer), cluster_left, fat_dir_entry_read_callback, &arg ) ) return 0;
1435 
1436  cluster_offset += arg.bytes_read;
1437 
1438  if ( cluster_offset >= cluster_size )
1439  {
1440  /* we reached the cluster border and switch to the next cluster */
1441 
1442  /* get number of next cluster */
1443  if ( (cluster_num = fat_get_next_cluster ( fs, cluster_num )) != 0 )
1444  {
1445  cluster_offset = 0;
1446  continue;
1447  }
1448 
1449  /* we are at the end of the cluster chain */
1450  if ( !arg.finished )
1451  {
1452  /* directory entry not found, reset directory handle */
1453  fat_reset_dir ( dd );
1454  return 0;
1455  }
1456  else
1457  {
1458  /* The current execution of the function has been successful,
1459  * so we can not signal an end of the directory listing to
1460  * the caller, but must wait for the next call. So we keep an
1461  * invalid cluster offset to mark this directory handle's
1462  * traversal as finished.
1463  */
1464  }
1465 
1466  break;
1467  }
1468  }
1469 
1470  dd->entry_cluster = cluster_num;
1471  dd->entry_offset = cluster_offset;
1472 
1473  return arg.finished;
1474 }
1475 
1487 uint8_t fat_reset_dir ( struct fat_dir_struct* dd )
1488 {
1489  if ( !dd ) return 0;
1490 
1491  dd->entry_cluster = dd->dir_entry.cluster;
1492  dd->entry_offset = 0;
1493  return 1;
1494 }
1495 
1515 uint8_t fat_dir_entry_read_callback ( uint8_t* buffer, offset_t offset, void* p )
1516 {
1517  struct fat_read_dir_callback_arg* arg = p;
1518  struct fat_dir_entry_struct* dir_entry = arg->dir_entry;
1519 
1520  arg->bytes_read += 32;
1521 
1522  /* skip deleted or empty entries */
1523  if ( buffer[0] == FAT_DIRENTRY_DELETED || !buffer[0] )
1524  {
1525 #if FAT_LFN_SUPPORT
1526  arg->checksum = 0;
1527 #endif
1528  return 1;
1529  }
1530 
1531 #if !FAT_LFN_SUPPORT
1532  /* skip lfn entries */
1533  if(buffer[11] == 0x0f)
1534  return 1;
1535 #endif
1536 
1537  char* long_name = dir_entry->long_name;
1538 #if FAT_LFN_SUPPORT
1539  if ( buffer[11] == 0x0f )
1540  {
1541  /* checksum validation */
1542  if ( arg->checksum == 0 || arg->checksum != buffer[13] )
1543  {
1544  /* reset directory entry */
1545  memset ( dir_entry, 0, sizeof(*dir_entry) );
1546 
1547  arg->checksum = buffer[13];
1548  dir_entry->entry_offset = offset;
1549  }
1550 
1551  /* lfn supports unicode, but we do not, for now.
1552  * So we assume pure ascii and read only every
1553  * second byte.
1554  */
1555  uint16_t char_offset = ((buffer[0] & 0x3f) - 1) * 13;
1556  const uint8_t char_mapping[] = { 1, 3, 5, 7, 9, 14, 16, 18, 20, 22, 24, 28, 30 };
1557  for ( uint8_t i = 0; i <= 12 && char_offset + i < sizeof(dir_entry->long_name) - 1; ++i )
1558  long_name[char_offset + i] = buffer[char_mapping[i]];
1559 
1560  return 1;
1561  }
1562  else
1563 #endif
1564  {
1565 #if FAT_LFN_SUPPORT
1566  /* if we do not have a long name or the previous lfn does not match, take the 8.3 name */
1567  if ( long_name[0] == '\0' || arg->checksum != fat_calc_83_checksum ( buffer ) )
1568 #endif
1569  {
1570  /* reset directory entry */
1571  memset ( dir_entry, 0, sizeof(*dir_entry) );
1572  dir_entry->entry_offset = offset;
1573 
1574  uint8_t i;
1575  for ( i = 0; i < 8; ++i )
1576  {
1577  if ( buffer[i] == ' ' ) break;
1578  long_name[i] = buffer[i];
1579 
1580  /* Windows NT and later versions do not store lfn entries
1581  * for 8.3 names which have a lowercase basename, extension
1582  * or both when everything else is uppercase. They use two
1583  * extra bits to signal a lowercase basename or extension.
1584  */
1585  if ( (buffer[12] & 0x08) && buffer[i] >= 'A' && buffer[i] <= 'Z' ) long_name[i] += 'a' - 'A';
1586  }
1587  if ( long_name[0] == 0x05 ) long_name[0] = (char) FAT_DIRENTRY_DELETED;
1588 
1589  if ( buffer[8] != ' ' )
1590  {
1591  long_name[i++] = '.';
1592 
1593  uint8_t j = 8;
1594  for ( ; j < 11; ++j )
1595  {
1596  if ( buffer[j] == ' ' ) break;
1597  long_name[i] = buffer[j];
1598 
1599  /* See above for the lowercase 8.3 name handling of
1600  * Windows NT and later.
1601  */
1602  if ( (buffer[12] & 0x10) && buffer[j] >= 'A' && buffer[j] <= 'Z' ) long_name[i] += 'a' - 'A';
1603 
1604  ++i;
1605  }
1606  }
1607 
1608  long_name[i] = '\0';
1609  }
1610 
1611  /* extract properties of file and store them within the structure */
1612  dir_entry->attributes = buffer[11];
1613  dir_entry->cluster = read16( &buffer[26] );
1614 #if FAT_FAT32_SUPPORT
1615  dir_entry->cluster |= ((cluster_t) read16( &buffer[20] )) << 16;
1616 #endif
1617  dir_entry->file_size = read32( &buffer[28] );
1618 
1619 #if FAT_DATETIME_SUPPORT
1620  dir_entry->modification_time = read16( &buffer[22] );
1621  dir_entry->modification_date = read16( &buffer[24] );
1622 #endif
1623 
1624  arg->finished = 1;
1625  return 0;
1626  }
1627 }
1628 
1629 #if DOXYGEN || FAT_LFN_SUPPORT
1630 
1638 uint8_t fat_calc_83_checksum ( const uint8_t* file_name_83 )
1639 {
1640  uint8_t checksum = file_name_83[0];
1641  for ( uint8_t i = 1; i < 11; ++i )
1642  checksum = ((checksum >> 1) | (checksum << 7)) + file_name_83[i];
1643 
1644  return checksum;
1645 }
1646 #endif
1647 
1648 #if DOXYGEN || FAT_WRITE_SUPPORT
1649 
1658 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 )
1659 {
1660  if ( !fs || !dir_entry ) return 0;
1661 
1662  /* search for a place where to write the directory entry to disk */
1663 #if FAT_LFN_SUPPORT
1664  uint8_t free_dir_entries_needed = (strlen ( dir_entry->long_name ) + 12) / 13 + 1;
1665  uint8_t free_dir_entries_found = 0;
1666 #endif
1667  cluster_t cluster_num = parent->dir_entry.cluster;
1668  offset_t dir_entry_offset = 0;
1669  offset_t offset = 0;
1670  offset_t offset_to = 0;
1671 #if FAT_FAT32_SUPPORT
1672  uint8_t is_fat32 = (fs->partition->type == PARTITION_TYPE_FAT32);
1673 #endif
1674 
1675  if ( cluster_num == 0 )
1676  {
1677 #if FAT_FAT32_SUPPORT
1678  if ( is_fat32 )
1679  {
1680  cluster_num = fs->header.root_dir_cluster;
1681  }
1682  else
1683 #endif
1684  {
1685  /* we read/write from the root directory entry */
1686  offset = fs->header.root_dir_offset;
1687  offset_to = fs->header.cluster_zero_offset;
1688  dir_entry_offset = offset;
1689  }
1690  }
1691 
1692  while ( 1 )
1693  {
1694  if ( offset == offset_to )
1695  {
1696  if ( cluster_num == 0 )
1697  /* We iterated through the whole root directory and
1698  * could not find enough space for the directory entry.
1699  */
1700  return 0;
1701 
1702  if ( offset )
1703  {
1704  /* We reached a cluster boundary and have to
1705  * switch to the next cluster.
1706  */
1707 
1708  cluster_t cluster_next = fat_get_next_cluster ( fs, cluster_num );
1709  if ( !cluster_next )
1710  {
1711  cluster_next = fat_append_clusters ( fs, cluster_num, 1 );
1712  if ( !cluster_next ) return 0;
1713 
1714  /* we appended a new cluster and know it is free */
1715  dir_entry_offset = fs->header.cluster_zero_offset + (offset_t) (cluster_next - 2) * fs->header.cluster_size;
1716 
1717  /* clear cluster to avoid garbage directory entries */
1718  fat_clear_cluster ( fs, cluster_next );
1719 
1720  break;
1721  }
1722  cluster_num = cluster_next;
1723  }
1724 
1725  offset = fat_cluster_offset ( fs, cluster_num );
1726  offset_to = offset + fs->header.cluster_size;
1727  dir_entry_offset = offset;
1728 #if FAT_LFN_SUPPORT
1729  free_dir_entries_found = 0;
1730 #endif
1731  }
1732 
1733  /* read next lfn or 8.3 entry */
1734  uint8_t first_char;
1735  if ( !fs->partition->device_read ( offset, &first_char, sizeof(first_char) ) ) return 0;
1736 
1737  /* check if we found a free directory entry */
1738  if ( first_char == FAT_DIRENTRY_DELETED || !first_char )
1739  {
1740  /* check if we have the needed number of available entries */
1741 #if FAT_LFN_SUPPORT
1742  ++free_dir_entries_found;
1743  if ( free_dir_entries_found >= free_dir_entries_needed )
1744 #endif
1745  break;
1746 
1747  offset += 32;
1748  }
1749  else
1750  {
1751  offset += 32;
1752  dir_entry_offset = offset;
1753 #if FAT_LFN_SUPPORT
1754  free_dir_entries_found = 0;
1755 #endif
1756  }
1757  }
1758 
1759  return dir_entry_offset;
1760 }
1761 #endif
1762 
1763 #if DOXYGEN || FAT_WRITE_SUPPORT
1764 
1783 uint8_t fat_write_dir_entry ( const struct fat_fs_struct* fs, struct fat_dir_entry_struct* dir_entry )
1784 {
1785  if ( !fs || !dir_entry ) return 0;
1786 
1787 #if FAT_DATETIME_SUPPORT
1788  {
1789  uint16_t year;
1790  uint8_t month;
1791  uint8_t day;
1792  uint8_t hour;
1793  uint8_t min;
1794  uint8_t sec;
1795 
1796  fat_get_datetime( &year, &month, &day, &hour, &min, &sec );
1797  fat_set_file_modification_date ( dir_entry, year, month, day );
1798  fat_set_file_modification_time ( dir_entry, hour, min, sec );
1799  }
1800 #endif
1801 
1802  device_write_t device_write = fs->partition->device_write;
1803  offset_t offset = dir_entry->entry_offset;
1804  const char* name = dir_entry->long_name;
1805  uint8_t name_len = strlen ( name );
1806 #if FAT_LFN_SUPPORT
1807  uint8_t lfn_entry_count = (name_len + 12) / 13;
1808 #endif
1809  uint8_t buffer[32];
1810 
1811  /* write 8.3 entry */
1812 
1813  /* generate 8.3 file name */
1814  memset ( &buffer[0], ' ', 11 );
1815  char* name_ext = strrchr ( name, '.' );
1816  if ( name_ext && *++name_ext )
1817  {
1818  uint8_t name_ext_len = strlen ( name_ext );
1819  name_len -= name_ext_len + 1;
1820 
1821  if ( name_ext_len > 3 )
1822 #if FAT_LFN_SUPPORT
1823  name_ext_len = 3;
1824 #else
1825  return 0;
1826 #endif
1827 
1828  memcpy ( &buffer[8], name_ext, name_ext_len );
1829  }
1830 
1831  if ( name_len <= 8 )
1832  {
1833  memcpy ( buffer, name, name_len );
1834 
1835 #if FAT_LFN_SUPPORT
1836  /* For now, we create lfn entries for all files,
1837  * except the "." and ".." directory references.
1838  * This is to avoid difficulties with capitalization,
1839  * as 8.3 filenames allow uppercase letters only.
1840  *
1841  * Theoretically it would be possible to leave
1842  * the 8.3 entry alone if the basename and the
1843  * extension have no mixed capitalization.
1844  */
1845  if ( name[0] == '.' && ((name[1] == '.' && name[2] == '\0') || name[1] == '\0') ) lfn_entry_count = 0;
1846 #endif
1847  }
1848  else
1849  {
1850 #if FAT_LFN_SUPPORT
1851  memcpy ( buffer, name, 8 );
1852 
1853  /* Minimize 8.3 name clashes by appending
1854  * the lower byte of the cluster number.
1855  */
1856  uint8_t num = dir_entry->cluster & 0xff;
1857 
1858  buffer[6] = (num < 0xa0) ? ('0' + (num >> 4)) : ('a' + (num >> 4));
1859  num &= 0x0f;
1860  buffer[7] = (num < 0x0a) ? ('0' + num) : ('a' + num);
1861 #else
1862  return 0;
1863 #endif
1864  }
1865  if ( buffer[0] == FAT_DIRENTRY_DELETED ) buffer[0] = 0x05;
1866 
1867  /* fill directory entry buffer */
1868  memset ( &buffer[11], 0, sizeof(buffer) - 11 );
1869  buffer[0x0b] = dir_entry->attributes;
1870 #if FAT_DATETIME_SUPPORT
1871  write16( &buffer[0x16], dir_entry->modification_time );
1872  write16( &buffer[0x18], dir_entry->modification_date );
1873 #endif
1874 #if FAT_FAT32_SUPPORT
1875  write16( &buffer[0x14], (uint16_t ) (dir_entry->cluster >> 16) );
1876 #endif
1877  write16( &buffer[0x1a], dir_entry->cluster );
1878  write32( &buffer[0x1c], dir_entry->file_size );
1879 
1880  /* write to disk */
1881 #if FAT_LFN_SUPPORT
1882  if ( !device_write ( offset + (uint16_t) lfn_entry_count * 32, buffer, sizeof(buffer) ) )
1883 #else
1884  if(!device_write(offset, buffer, sizeof(buffer)))
1885 #endif
1886  return 0;
1887 
1888 #if FAT_LFN_SUPPORT
1889  /* calculate checksum of 8.3 name */
1890  uint8_t checksum = fat_calc_83_checksum ( buffer );
1891 
1892  /* write lfn entries */
1893  for ( uint8_t lfn_entry = lfn_entry_count; lfn_entry > 0; --lfn_entry )
1894  {
1895  memset ( buffer, 0xff, sizeof(buffer) );
1896 
1897  /* set file name */
1898  const char* long_name_curr = name + (lfn_entry - 1) * 13;
1899  uint8_t i = 1;
1900  while ( i < 0x1f )
1901  {
1902  buffer[i++] = *long_name_curr;
1903  buffer[i++] = 0;
1904 
1905  switch (i)
1906  {
1907  case 0x0b:
1908  i = 0x0e;
1909  break;
1910  case 0x1a:
1911  i = 0x1c;
1912  break;
1913  }
1914 
1915  if ( !*long_name_curr++ ) break;
1916  }
1917 
1918  /* set index of lfn entry */
1919  buffer[0x00] = lfn_entry;
1920  if ( lfn_entry == lfn_entry_count ) buffer[0x00] |= FAT_DIRENTRY_LFNLAST;
1921 
1922  /* mark as lfn entry */
1923  buffer[0x0b] = 0x0f;
1924 
1925  /* set 8.3 checksum */
1926  buffer[0x0d] = checksum;
1927 
1928  /* clear reserved bytes */
1929  buffer[0x0c] = 0;
1930  buffer[0x1a] = 0;
1931  buffer[0x1b] = 0;
1932 
1933  /* write entry */
1934  device_write ( offset, buffer, sizeof(buffer) );
1935 
1936  offset += sizeof(buffer);
1937  }
1938 #endif
1939 
1940  return 1;
1941 }
1942 #endif
1943 
1944 #if DOXYGEN || FAT_WRITE_SUPPORT
1945 
1971 uint8_t fat_create_file ( struct fat_dir_struct* parent, const char* file, struct fat_dir_entry_struct* dir_entry )
1972 {
1973  if ( !parent || !file || !file[0] || !dir_entry ) return 0;
1974 
1975  /* check if the file already exists */
1976  while ( 1 )
1977  {
1978  if ( !fat_read_dir ( parent, dir_entry ) ) break;
1979 
1980  if ( strcmp ( file, dir_entry->long_name ) == 0 )
1981  {
1982  fat_reset_dir ( parent );
1983  return 2;
1984  }
1985  }
1986 
1987  struct fat_fs_struct* fs = parent->fs;
1988 
1989  /* prepare directory entry with values already known */
1990  memset ( dir_entry, 0, sizeof(*dir_entry) );
1991  strncpy ( dir_entry->long_name, file, sizeof(dir_entry->long_name) - 1 );
1992 
1993  /* find place where to store directory entry */
1994  if ( !(dir_entry->entry_offset = fat_find_offset_for_dir_entry ( fs, parent, dir_entry )) ) return 0;
1995 
1996  /* write directory entry to disk */
1997  if ( !fat_write_dir_entry ( fs, dir_entry ) ) return 0;
1998 
1999  return 1;
2000 }
2001 #endif
2002 
2003 #if DOXYGEN || FAT_WRITE_SUPPORT
2004 
2018 uint8_t fat_delete_file ( struct fat_fs_struct* fs, struct fat_dir_entry_struct* dir_entry )
2019 {
2020  if ( !fs || !dir_entry ) return 0;
2021 
2022  /* get offset of the file's directory entry */
2023  offset_t dir_entry_offset = dir_entry->entry_offset;
2024  if ( !dir_entry_offset ) return 0;
2025 
2026 #if FAT_LFN_SUPPORT
2027  uint8_t buffer[12];
2028  while ( 1 )
2029  {
2030  /* read directory entry */
2031  if ( !fs->partition->device_read ( dir_entry_offset, buffer, sizeof(buffer) ) ) return 0;
2032 
2033  /* mark the directory entry as deleted */
2034  buffer[0] = FAT_DIRENTRY_DELETED;
2035 
2036  /* write back entry */
2037  if ( !fs->partition->device_write ( dir_entry_offset, buffer, sizeof(buffer) ) ) return 0;
2038 
2039  /* check if we deleted the whole entry */
2040  if ( buffer[11] != 0x0f ) break;
2041 
2042  dir_entry_offset += 32;
2043  }
2044 #else
2045  /* mark the directory entry as deleted */
2046  uint8_t first_char = FAT_DIRENTRY_DELETED;
2047  if(!fs->partition->device_write(dir_entry_offset, &first_char, 1))
2048  return 0;
2049 #endif
2050 
2051  /* We deleted the directory entry. The next thing to do is
2052  * marking all occupied clusters as free.
2053  */
2054  return (dir_entry->cluster == 0 || fat_free_clusters ( fs, dir_entry->cluster ));
2055 }
2056 #endif
2057 
2058 #if DOXYGEN || FAT_WRITE_SUPPORT
2059 
2083 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 )
2084 {
2085  if ( !fs || !dir_entry || !parent_new || (file_new && !file_new[0]) ) return 0;
2086  if ( fs != parent_new->fs ) return 0;
2087 
2088  /* use existing file name if none has been specified */
2089  if ( !file_new ) file_new = dir_entry->long_name;
2090 
2091  /* create file with new file name */
2092  struct fat_dir_entry_struct dir_entry_new;
2093  if ( !fat_create_file ( parent_new, file_new, &dir_entry_new ) ) return 0;
2094 
2095  /* copy members of directory entry which do not change with rename */
2096  dir_entry_new.attributes = dir_entry->attributes;
2097 #if FAT_DATETIME_SUPPORT
2098  dir_entry_new.modification_time = dir_entry->modification_time;
2099  dir_entry_new.modification_date = dir_entry->modification_date;
2100 #endif
2101  dir_entry_new.cluster = dir_entry->cluster;
2102  dir_entry_new.file_size = dir_entry->file_size;
2103 
2104  /* make the new file name point to the old file's content */
2105  if ( !fat_write_dir_entry ( fs, &dir_entry_new ) )
2106  {
2107  fat_delete_file ( fs, &dir_entry_new );
2108  return 0;
2109  }
2110 
2111  /* delete the old file, but not its clusters, which have already been remapped above */
2112  dir_entry->cluster = 0;
2113  if ( !fat_delete_file ( fs, dir_entry ) ) return 0;
2114 
2115  *dir_entry = dir_entry_new;
2116  return 1;
2117 }
2118 #endif
2119 
2120 #if DOXYGEN || FAT_WRITE_SUPPORT
2121 
2139 uint8_t fat_create_dir ( struct fat_dir_struct* parent, const char* dir, struct fat_dir_entry_struct* dir_entry )
2140 {
2141  if ( !parent || !dir || !dir[0] || !dir_entry ) return 0;
2142 
2143  /* check if the file or directory already exists */
2144  while ( fat_read_dir ( parent, dir_entry ) )
2145  {
2146  if ( strcmp ( dir, dir_entry->long_name ) == 0 )
2147  {
2148  fat_reset_dir ( parent );
2149  return 0;
2150  }
2151  }
2152 
2153  struct fat_fs_struct* fs = parent->fs;
2154 
2155  /* allocate cluster which will hold directory entries */
2156  cluster_t dir_cluster = fat_append_clusters ( fs, 0, 1 );
2157  if ( !dir_cluster ) return 0;
2158 
2159  /* clear cluster to prevent bogus directory entries */
2160  fat_clear_cluster ( fs, dir_cluster );
2161 
2162  memset ( dir_entry, 0, sizeof(*dir_entry) );
2163  dir_entry->attributes = FAT_ATTRIB_DIR;
2164 
2165  /* create "." directory self reference */
2166  dir_entry->entry_offset = fs->header.cluster_zero_offset + (offset_t) (dir_cluster - 2) * fs->header.cluster_size;
2167  dir_entry->long_name[0] = '.';
2168  dir_entry->cluster = dir_cluster;
2169  if ( !fat_write_dir_entry ( fs, dir_entry ) )
2170  {
2171  fat_free_clusters ( fs, dir_cluster );
2172  return 0;
2173  }
2174 
2175  /* create ".." parent directory reference */
2176  dir_entry->entry_offset += 32;
2177  dir_entry->long_name[1] = '.';
2178  dir_entry->cluster = parent->dir_entry.cluster;
2179  if ( !fat_write_dir_entry ( fs, dir_entry ) )
2180  {
2181  fat_free_clusters ( fs, dir_cluster );
2182  return 0;
2183  }
2184 
2185  /* fill directory entry */
2186  strncpy ( dir_entry->long_name, dir, sizeof(dir_entry->long_name) - 1 );
2187  dir_entry->cluster = dir_cluster;
2188 
2189  /* find place where to store directory entry */
2190  if ( !(dir_entry->entry_offset = fat_find_offset_for_dir_entry ( fs, parent, dir_entry )) )
2191  {
2192  fat_free_clusters ( fs, dir_cluster );
2193  return 0;
2194  }
2195 
2196  /* write directory to disk */
2197  if ( !fat_write_dir_entry ( fs, dir_entry ) )
2198  {
2199  fat_free_clusters ( fs, dir_cluster );
2200  return 0;
2201  }
2202 
2203  return 1;
2204 }
2205 #endif
2206 
2222 #ifdef DOXYGEN
2223 uint8_t fat_delete_dir(struct fat_fs_struct* fs, struct fat_dir_entry_struct* dir_entry);
2224 #endif
2225 
2239 #ifdef DOXYGEN
2240 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);
2241 #endif
2242 
2243 #if DOXYGEN || FAT_DATETIME_SUPPORT
2244 
2253 void fat_get_file_modification_date ( const struct fat_dir_entry_struct* dir_entry, uint16_t* year, uint8_t* month, uint8_t* day )
2254 {
2255  if ( !dir_entry ) return;
2256 
2257  *year = 1980 + ((dir_entry->modification_date >> 9) & 0x7f);
2258  *month = (dir_entry->modification_date >> 5) & 0x0f;
2259  *day = (dir_entry->modification_date >> 0) & 0x1f;
2260 }
2261 #endif
2262 
2263 #if DOXYGEN || FAT_DATETIME_SUPPORT
2264 
2273 void fat_get_file_modification_time ( const struct fat_dir_entry_struct* dir_entry, uint8_t* hour, uint8_t* min, uint8_t* sec )
2274 {
2275  if ( !dir_entry ) return;
2276 
2277  *hour = (dir_entry->modification_time >> 11) & 0x1f;
2278  *min = (dir_entry->modification_time >> 5) & 0x3f;
2279  *sec = ((dir_entry->modification_time >> 0) & 0x1f) * 2;
2280 }
2281 #endif
2282 
2283 #if DOXYGEN || (FAT_WRITE_SUPPORT && FAT_DATETIME_SUPPORT)
2284 
2293 void fat_set_file_modification_date ( struct fat_dir_entry_struct* dir_entry, uint16_t year, uint8_t month, uint8_t day )
2294 {
2295  if ( !dir_entry ) return;
2296 
2297  dir_entry->modification_date = ((year - 1980) << 9) | ((uint16_t) month << 5) | ((uint16_t) day << 0);
2298 }
2299 #endif
2300 
2301 #if DOXYGEN || (FAT_WRITE_SUPPORT && FAT_DATETIME_SUPPORT)
2302 
2311 void fat_set_file_modification_time ( struct fat_dir_entry_struct* dir_entry, uint8_t hour, uint8_t min, uint8_t sec )
2312 {
2313  if ( !dir_entry ) return;
2314 
2315  dir_entry->modification_time = ((uint16_t) hour << 11) | ((uint16_t) min << 5) | ((uint16_t) sec >> 1);
2316 }
2317 #endif
2318 
2326 offset_t fat_get_fs_size ( const struct fat_fs_struct* fs )
2327 {
2328  if ( !fs ) return 0;
2329 
2330 #if FAT_FAT32_SUPPORT
2331  if ( fs->partition->type == PARTITION_TYPE_FAT32 )
2332  return (offset_t) (fs->header.fat_size / 4 - 2) * fs->header.cluster_size;
2333  else
2334 #endif
2335  return (offset_t) (fs->header.fat_size / 2 - 2) * fs->header.cluster_size;
2336 }
2337 
2348 offset_t fat_get_fs_free ( const struct fat_fs_struct* fs )
2349 {
2350  if ( !fs ) return 0;
2351 
2352  uint8_t fat[32];
2353  struct fat_usage_count_callback_arg count_arg;
2354  count_arg.cluster_count = 0;
2355  count_arg.buffer_size = sizeof(fat);
2356 
2357  offset_t fat_offset = fs->header.fat_offset;
2358  uint32_t fat_size = fs->header.fat_size;
2359  while ( fat_size > 0 )
2360  {
2361  uintptr_t length = UINTPTR_MAX - 1;
2362  if ( fat_size < length ) length = fat_size;
2363 
2364  if ( !fs->partition->device_read_interval ( fat_offset, fat, sizeof(fat), length,
2367 #else
2369 #endif
2370  &count_arg ) ) return 0;
2371 
2372  fat_offset += length;
2373  fat_size -= length;
2374  }
2375 
2376  return (offset_t) count_arg.cluster_count * fs->header.cluster_size;
2377 }
2378 
2383 uint8_t fat_get_fs_free_16_callback ( uint8_t* buffer, offset_t offset, void* p )
2384 {
2385  struct fat_usage_count_callback_arg* count_arg = (struct fat_usage_count_callback_arg*) p;
2386  uintptr_t buffer_size = count_arg->buffer_size;
2387 
2388  for ( uintptr_t i = 0; i < buffer_size; i += 2, buffer += 2 )
2389  {
2390  uint16_t cluster = read16( buffer );
2391  if ( cluster == HTOL16( FAT16_CLUSTER_FREE ) ) ++(count_arg->cluster_count);
2392  }
2393 
2394  return 1;
2395 }
2396 
2397 #if DOXYGEN || FAT_FAT32_SUPPORT
2398 
2402 uint8_t fat_get_fs_free_32_callback ( uint8_t* buffer, offset_t offset, void* p )
2403 {
2404  struct fat_usage_count_callback_arg* count_arg = (struct fat_usage_count_callback_arg*) p;
2405  uintptr_t buffer_size = count_arg->buffer_size;
2406 
2407  for ( uintptr_t i = 0; i < buffer_size; i += 4, buffer += 4 )
2408  {
2409  uint32_t cluster = read32( buffer );
2410  if ( cluster == HTOL32( FAT32_CLUSTER_FREE ) ) ++(count_arg->cluster_count);
2411  }
2412 
2413  return 1;
2414 }
2415 #endif
2416 
2417 #if FAT_DATETIME_SUPPORT
2418 
2452 void get_datetime ( uint16_t* year, uint8_t* month, uint8_t* day, uint8_t* hour, uint8_t* min, uint8_t* sec )
2453 {
2455  *year = now.year + 2000;
2456  *month = now.month;
2457  *day = now.day;
2458  *hour = now.hours;
2459  *min = now.minutes;
2460  *sec = now.seconds;
2461 }
2462 #endif
2463 
#define HTOL16(val)
Definition: byteordering.h:113
uint8_t(* device_write_t)(offset_t offset, const uint8_t *buffer, uintptr_t length)
Definition: partition.h:131
device_read_t device_read
Definition: partition.h:173
uint8_t(* device_read_t)(offset_t offset, uint8_t *buffer, uintptr_t length)
Definition: partition.h:95
SD-Card Reader Bibliothek von Roland Riegel. Common SD-reader configuration used by all modules (lice...
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)
Definition: fat.c:2083
struct fat_dir_struct * fat_open_dir(struct fat_fs_struct *fs, const struct fat_dir_entry_struct *dir_entry)
Definition: fat.c:1324
uint8_t fat_reset_dir(struct fat_dir_struct *dd)
Definition: fat.c:1487
Header, Definition der Konstanten und Commands für DS1388.
void fat_close_dir(struct fat_dir_struct *dd)
Definition: fat.c:1363
offset_t entry_offset
Definition: fat.h:101
SD-Card Reader Bibliothek von Roland Riegel.
offset_t fat_get_fs_size(const struct fat_fs_struct *fs)
Definition: fat.c:2326
void DS1388_get_datetime(void)
Die Uhrzeit und das Datum werden ausgelesen.
Definition: ds1388_rtc.c:107
static void fat_set_file_modification_date(struct fat_dir_entry_struct *dir_entry, uint16_t year, uint8_t month, uint8_t day)
Definition: fat.c:2293
uint8_t fat_read_dir(struct fat_dir_struct *dd, struct fat_dir_entry_struct *dir_entry)
Definition: fat.c:1382
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)
Definition: fat.c:1658
uint16_t modification_time
Definition: fat.h:92
#define FAT_DIR_COUNT
Definition: fat_config.h:124
static offset_t fat_cluster_offset(const struct fat_fs_struct *fs, cluster_t cluster_num)
Definition: fat.c:789
device_read_interval_t device_read_interval
Definition: partition.h:180
SD-Card Reader Bibliothek von Roland Riegel.
intptr_t fat_read_file(struct fat_file_struct *fd, uint8_t *buffer, uintptr_t buffer_len)
Definition: fat.c:942
#define FAT_ATTRIB_DIR
Definition: fat.h:60
void write16(uint8_t *p, uint16_t i)
Definition: byteordering.c:101
uint16_t modification_date
Definition: fat.h:94
static void fat_set_file_modification_time(struct fat_dir_entry_struct *dir_entry, uint8_t hour, uint8_t min, uint8_t sec)
Definition: fat.c:2311
uint8_t fat_create_dir(struct fat_dir_struct *parent, const char *dir, struct fat_dir_entry_struct *dir_entry)
Definition: fat.c:2139
uint8_t attributes
Definition: fat.h:89
uint32_t read32(const uint8_t *p)
Definition: byteordering.c:87
static cluster_t fat_append_clusters(struct fat_fs_struct *fs, cluster_t cluster_num, cluster_t count)
Definition: fat.c:490
void write32(uint8_t *p, uint32_t i)
Definition: byteordering.c:113
uint8_t fat_delete_file(struct fat_fs_struct *fs, struct fat_dir_entry_struct *dir_entry)
Definition: fat.c:2018
uint32_t offset
Definition: partition.h:205
#define FAT_SEEK_CUR
Definition: fat.h:67
SD-Card Reader Bibliothek von Roland Riegel.
static uint8_t fat_dir_entry_read_callback(uint8_t *buffer, offset_t offset, void *p)
Definition: fat.c:1515
uint8_t fat_create_file(struct fat_dir_struct *parent, const char *file, struct fat_dir_entry_struct *dir_entry)
Definition: fat.c:1971
static uint8_t fat_free_clusters(struct fat_fs_struct *fs, cluster_t cluster_num)
Definition: fat.c:638
uint32_t file_size
Definition: fat.h:99
static uint8_t fat_get_fs_free_16_callback(uint8_t *buffer, offset_t offset, void *p)
Definition: fat.c:2383
uint16_t read16(const uint8_t *p)
Definition: byteordering.c:75
static uint8_t fat_terminate_clusters(struct fat_fs_struct *fs, cluster_t cluster_num)
Definition: fat.c:718
#define FAT_SEEK_SET
Definition: fat.h:65
#define PARTITION_TYPE_FAT32
Definition: partition.h:70
static uint8_t fat_clear_cluster(const struct fat_fs_struct *fs, cluster_t cluster_num)
Definition: fat.c:758
static uint8_t fat_get_fs_free_32_callback(uint8_t *buffer, offset_t offset, void *p)
Definition: fat.c:2402
cluster_t cluster
Definition: fat.h:97
void fat_close_file(struct fat_file_struct *fd)
Definition: fat.c:913
#define FAT_SEEK_END
Definition: fat.h:69
#define PARTITION_TYPE_FAT16
Definition: partition.h:66
void fat_close(struct fat_fs_struct *fs)
Definition: fat.c:302
void get_datetime(uint16_t *year, uint8_t *month, uint8_t *day, uint8_t *hour, uint8_t *min, uint8_t *sec)
This function is the link between the hardware RTC and the timekeeping function to the sd-reader code...
Definition: fat.c:2452
device_write_interval_t device_write_interval
Definition: partition.h:194
uint8_t fat_get_dir_entry_of_path(struct fat_fs_struct *fs, const char *path, struct fat_dir_entry_struct *dir_entry)
Definition: fat.c:808
static uint8_t fat_calc_83_checksum(const uint8_t *file_name_83)
Definition: fat.c:1638
intptr_t fat_write_file(struct fat_file_struct *fd, const uint8_t *buffer, uintptr_t buffer_len)
Definition: fat.c:1032
device_write_t device_write
Definition: partition.h:187
struct fat_file_struct * fat_open_file(struct fat_fs_struct *fs, const struct fat_dir_entry_struct *dir_entry)
Definition: fat.c:878
uint8_t fat_seek_file(struct fat_file_struct *fd, int32_t *offset, uint8_t whence)
Definition: fat.c:1186
struct fat_fs_struct * fat_open(struct partition_struct *partition)
Definition: fat.c:250
static uint8_t fat_read_header(struct fat_fs_struct *fs)
Definition: fat.c:320
void fat_get_file_modification_time(const struct fat_dir_entry_struct *dir_entry, uint8_t *hour, uint8_t *min, uint8_t *sec)
Definition: fat.c:2273
#define fat_get_datetime(year, month, day, hour, min, sec)
Definition: fat_config.h:103
char long_name[32]
Definition: fat.h:87
void fat_get_file_modification_date(const struct fat_dir_entry_struct *dir_entry, uint16_t *year, uint8_t *month, uint8_t *day)
Definition: fat.c:2253
#define FAT_WRITE_SUPPORT
Definition: fat_config.h:51
static cluster_t fat_get_next_cluster(const struct fat_fs_struct *fs, cluster_t cluster_num)
Definition: fat.c:444
#define FAT_FS_COUNT
Definition: fat_config.h:112
static uint8_t fat_write_dir_entry(const struct fat_fs_struct *fs, struct fat_dir_entry_struct *dir_entry)
Definition: fat.c:1783
static uintptr_t fat_clear_cluster_callback(uint8_t *buffer, offset_t offset, void *p)
Definition: fat.c:775
#define FAT_FAT32_SUPPORT
Definition: fat_config.h:75
SD-Card Reader Bibliothek von Roland Riegel.
#define HTOL32(val)
Definition: byteordering.h:114
#define FAT_FILE_COUNT
Definition: fat_config.h:118
offset_t fat_get_fs_free(const struct fat_fs_struct *fs)
Definition: fat.c:2348
uint8_t fat_resize_file(struct fat_file_struct *fd, uint32_t size)
Definition: fat.c:1239