|
Files | |
| file | fat.c |
| file | fat.h |
| file | fat_config.h |
Modules | |
| FAT configuration | |
| FAT access | |
| FAT file functions | |
| FAT directory functions | |
Data Structures | |
| struct | fat_dir_entry_struct |
Defines | |
| #define | fat_delete_dir fat_delete_file |
Functions | |
| struct fat_fs_struct * | fat_open (struct partition_struct *partition) |
| void | fat_close (struct fat_fs_struct *fs) |
| struct fat_file_struct * | fat_open_file (struct fat_fs_struct *fs, const struct fat_dir_entry_struct *dir_entry) |
| void | fat_close_file (struct fat_file_struct *fd) |
| intptr_t | fat_read_file (struct fat_file_struct *fd, uint8_t *buffer, uintptr_t buffer_len) |
| intptr_t | fat_write_file (struct fat_file_struct *fd, const uint8_t *buffer, uintptr_t buffer_len) |
| uint8_t | fat_seek_file (struct fat_file_struct *fd, int32_t *offset, uint8_t whence) |
| uint8_t | fat_resize_file (struct fat_file_struct *fd, uint32_t size) |
| struct fat_dir_struct * | fat_open_dir (struct fat_fs_struct *fs, const struct fat_dir_entry_struct *dir_entry) |
| void | fat_close_dir (struct fat_dir_struct *dd) |
| uint8_t | fat_read_dir (struct fat_dir_struct *dd, struct fat_dir_entry_struct *dir_entry) |
| uint8_t | fat_reset_dir (struct fat_dir_struct *dd) |
| uint8_t | fat_create_file (struct fat_dir_struct *parent, const char *file, struct fat_dir_entry_struct *dir_entry) |
| uint8_t | fat_delete_file (struct fat_fs_struct *fs, struct fat_dir_entry_struct *dir_entry) |
| uint8_t | fat_create_dir (struct fat_dir_struct *parent, const char *dir, struct fat_dir_entry_struct *dir_entry) |
| void | fat_get_file_modification_date (const struct fat_dir_entry_struct *dir_entry, uint16_t *year, uint8_t *month, uint8_t *day) |
| void | fat_get_file_modification_time (const struct fat_dir_entry_struct *dir_entry, uint8_t *hour, uint8_t *min, uint8_t *sec) |
| uint8_t | fat_get_dir_entry_of_path (struct fat_fs_struct *fs, const char *path, struct fat_dir_entry_struct *dir_entry) |
| offset_t | fat_get_fs_size (const struct fat_fs_struct *fs) |
| offset_t | fat_get_fs_free (const struct fat_fs_struct *fs) |
| void | get_datetime (uint16_t *year, uint8_t *month, uint8_t *day, uint8_t *hour, uint8_t *min, uint8_t *sec) |
The following features are supported:
| void fat_close | ( | struct fat_fs_struct * | fs | ) |
Closes a FAT filesystem.
When this function returns, the given filesystem descriptor will be invalid.
| [in] | fs | The filesystem to close. |
Definition at line 291 of file fat.c.
References fat_fs_struct::partition.
Referenced by WaspSD::close().
00292 { 00293 if(!fs) 00294 return; 00295 00296 #if USE_DYNAMIC_MEMORY 00297 free(fs); 00298 #else 00299 fs->partition = 0; 00300 #endif 00301 }

| void fat_close_dir | ( | struct fat_dir_struct * | dd | ) |
Closes a directory descriptor.
This function destroys a directory descriptor which was previously obtained by calling fat_open_dir(). When this function returns, the given descriptor will be invalid.
| [in] | dd | The directory descriptor to close. |
Definition at line 1418 of file fat.c.
References fat_dir_struct::fs.
Referenced by WaspSD::cd(), WaspSD::close(), and fat_get_dir_entry_of_path().
01419 { 01420 if(dd) 01421 #if USE_DYNAMIC_MEMORY 01422 free(dd); 01423 #else 01424 dd->fs = 0; 01425 #endif 01426 }

| void fat_close_file | ( | struct fat_file_struct * | fd | ) |
Closes a file.
| [in] | fd | The file handle of the file to close. |
Definition at line 964 of file fat.c.
References fat_file_struct::dir_entry, fat_write_dir_entry(), and fat_file_struct::fs.
Referenced by WaspSD::cat(), WaspSD::catBin(), WaspSD::catln(), WaspSD::closeFile(), WaspSD::indexOf(), WaspSD::numln(), and WaspSD::writeSD().
00965 { 00966 if(fd) 00967 { 00968 #if FAT_DELAY_DIRENTRY_UPDATE 00969 /* write directory entry */ 00970 fat_write_dir_entry(fd->fs, &fd->dir_entry); 00971 #endif 00972 00973 #if USE_DYNAMIC_MEMORY 00974 free(fd); 00975 #else 00976 fd->fs = 0; 00977 #endif 00978 } 00979 }


| uint8_t fat_create_dir | ( | struct fat_dir_struct * | parent, | |
| const char * | dir, | |||
| struct fat_dir_entry_struct * | dir_entry | |||
| ) |
Creates a directory.
Creates a directory and obtains its directory entry. If the directory to create already exists, its directory entry will be returned within the dir_entry parameter.
| [in] | parent | The handle of the parent directory of the new directory. |
| [in] | dir | The name of the directory to create. |
| [out] | dir_entry | The directory entry to fill for the new directory. |
Definition at line 2170 of file fat.c.
References fat_dir_entry_struct::attributes, fat_dir_entry_struct::cluster, fat_header_struct::cluster_size, fat_header_struct::cluster_zero_offset, fat_dir_struct::dir_entry, fat_dir_entry_struct::entry_offset, fat_append_clusters(), FAT_ATTRIB_DIR, fat_clear_cluster(), fat_find_offset_for_dir_entry(), fat_free_clusters(), fat_read_dir(), fat_reset_dir(), fat_write_dir_entry(), fat_dir_struct::fs, fat_fs_struct::header, and fat_dir_entry_struct::long_name.
Referenced by WaspSD::mkdir().
02171 { 02172 if(!parent || !dir || !dir[0] || !dir_entry) 02173 return 0; 02174 02175 /* check if the file or directory already exists */ 02176 while(fat_read_dir(parent, dir_entry)) 02177 { 02178 if(strcmp(dir, dir_entry->long_name) == 0) 02179 { 02180 fat_reset_dir(parent); 02181 return 0; 02182 } 02183 } 02184 02185 struct fat_fs_struct* fs = parent->fs; 02186 02187 /* allocate cluster which will hold directory entries */ 02188 cluster_t dir_cluster = fat_append_clusters(fs, 0, 1); 02189 if(!dir_cluster) 02190 return 0; 02191 02192 /* clear cluster to prevent bogus directory entries */ 02193 fat_clear_cluster(fs, dir_cluster); 02194 02195 memset(dir_entry, 0, sizeof(*dir_entry)); 02196 dir_entry->attributes = FAT_ATTRIB_DIR; 02197 02198 /* create "." directory self reference */ 02199 dir_entry->entry_offset = fs->header.cluster_zero_offset + 02200 (offset_t) (dir_cluster - 2) * fs->header.cluster_size; 02201 dir_entry->long_name[0] = '.'; 02202 dir_entry->cluster = dir_cluster; 02203 if(!fat_write_dir_entry(fs, dir_entry)) 02204 { 02205 fat_free_clusters(fs, dir_cluster); 02206 return 0; 02207 } 02208 02209 /* create ".." parent directory reference */ 02210 dir_entry->entry_offset += 32; 02211 dir_entry->long_name[1] = '.'; 02212 dir_entry->cluster = parent->dir_entry.cluster; 02213 if(!fat_write_dir_entry(fs, dir_entry)) 02214 { 02215 fat_free_clusters(fs, dir_cluster); 02216 return 0; 02217 } 02218 02219 /* fill directory entry */ 02220 strncpy(dir_entry->long_name, dir, sizeof(dir_entry->long_name) - 1); 02221 dir_entry->cluster = dir_cluster; 02222 02223 /* find place where to store directory entry */ 02224 if(!(dir_entry->entry_offset = fat_find_offset_for_dir_entry(fs, parent, dir_entry))) 02225 { 02226 fat_free_clusters(fs, dir_cluster); 02227 return 0; 02228 } 02229 02230 /* write directory to disk */ 02231 if(!fat_write_dir_entry(fs, dir_entry)) 02232 { 02233 fat_free_clusters(fs, dir_cluster); 02234 return 0; 02235 } 02236 02237 return 1; 02238 }


| uint8_t fat_create_file | ( | struct fat_dir_struct * | parent, | |
| const char * | file, | |||
| struct fat_dir_entry_struct * | dir_entry | |||
| ) |
Creates a file.
Creates a file and obtains the directory entry of the new file. If the file to create already exists, the directory entry of the existing file will be returned within the dir_entry parameter.
The generation of the short 8.3 file name is quite simple. The first eight characters are used for the filename. The extension, if any, is made up of the first three characters following the last dot within the long filename. If the filename (without the extension) is longer than eight characters, the lower byte of the cluster number replaces the last two characters to avoid name clashes. In any other case, it is your responsibility to avoid name clashes.
| [in] | parent | The handle of the directory in which to create the file. |
| [in] | file | The name of the file to create. |
| [out] | dir_entry | The directory entry to fill for the new file. |
Definition at line 2055 of file fat.c.
References fat_dir_entry_struct::entry_offset, fat_find_offset_for_dir_entry(), fat_read_dir(), fat_reset_dir(), fat_write_dir_entry(), fat_dir_struct::fs, and fat_dir_entry_struct::long_name.
Referenced by WaspSD::create().
02056 { 02057 if(!parent || !file || !file[0] || !dir_entry) 02058 return 0; 02059 02060 /* check if the file already exists */ 02061 while(1) 02062 { 02063 if(!fat_read_dir(parent, dir_entry)) 02064 break; 02065 02066 if(strcmp(file, dir_entry->long_name) == 0) 02067 { 02068 fat_reset_dir(parent); 02069 return 0; 02070 } 02071 } 02072 02073 struct fat_fs_struct* fs = parent->fs; 02074 02075 /* prepare directory entry with values already known */ 02076 memset(dir_entry, 0, sizeof(*dir_entry)); 02077 strncpy(dir_entry->long_name, file, sizeof(dir_entry->long_name) - 1); 02078 02079 /* find place where to store directory entry */ 02080 if(!(dir_entry->entry_offset = fat_find_offset_for_dir_entry(fs, parent, dir_entry))) 02081 return 0; 02082 02083 /* write directory entry to disk */ 02084 if(!fat_write_dir_entry(fs, dir_entry)) 02085 return 0; 02086 02087 return 1; 02088 }


| uint8_t fat_delete_file | ( | struct fat_fs_struct * | fs, | |
| struct fat_dir_entry_struct * | dir_entry | |||
| ) |
Deletes a file or directory.
If a directory is deleted without first deleting its subdirectories and files, disk space occupied by these files will get wasted as there is no chance to release it and mark it as free.
| [in] | fs | The filesystem on which to operate. |
| [in] | dir_entry | The directory entry of the file to delete. |
Definition at line 2106 of file fat.c.
References fat_dir_entry_struct::cluster, partition_struct::device_read, partition_struct::device_write, fat_dir_entry_struct::entry_offset, FAT_DIRENTRY_DELETED, fat_free_clusters(), and fat_fs_struct::partition.
Referenced by WaspSD::delDir(), and WaspSD::delFile().
02107 { 02108 if(!fs || !dir_entry) 02109 return 0; 02110 02111 /* get offset of the file's directory entry */ 02112 offset_t dir_entry_offset = dir_entry->entry_offset; 02113 if(!dir_entry_offset) 02114 return 0; 02115 02116 #if FAT_LFN_SUPPORT 02117 uint8_t buffer[12]; 02118 while(1) 02119 { 02120 /* read directory entry */ 02121 if(!fs->partition->device_read(dir_entry_offset, buffer, sizeof(buffer))) 02122 return 0; 02123 02124 /* mark the directory entry as deleted */ 02125 buffer[0] = FAT_DIRENTRY_DELETED; 02126 02127 /* write back entry */ 02128 if(!fs->partition->device_write(dir_entry_offset, buffer, sizeof(buffer))) 02129 return 0; 02130 02131 /* check if we deleted the whole entry */ 02132 if(buffer[11] != 0x0f) 02133 break; 02134 02135 dir_entry_offset += 32; 02136 } 02137 #else 02138 /* mark the directory entry as deleted */ 02139 uint8_t first_char = FAT_DIRENTRY_DELETED; 02140 if(!fs->partition->device_write(dir_entry_offset, &first_char, 1)) 02141 return 0; 02142 #endif 02143 02144 /* We deleted the directory entry. The next thing to do is 02145 * marking all occupied clusters as free. 02146 */ 02147 return (dir_entry->cluster == 0 || fat_free_clusters(fs, dir_entry->cluster)); 02148 }


| uint8_t fat_get_dir_entry_of_path | ( | struct fat_fs_struct * | fs, | |
| const char * | path, | |||
| struct fat_dir_entry_struct * | dir_entry | |||
| ) |
Retrieves the directory entry of a path.
The given path may both describe a file or a directory.
| [in] | fs | The FAT filesystem on which to search. |
| [in] | path | The path of which to read the directory entry. |
| [out] | dir_entry | The directory entry to fill. |
Definition at line 850 of file fat.c.
References fat_dir_entry_struct::attributes, FAT_ATTRIB_DIR, fat_close_dir(), fat_open_dir(), fat_read_dir(), and fat_dir_entry_struct::long_name.
Referenced by WaspSD::init().
00851 { 00852 if(!fs || !path || path[0] == '\0' || !dir_entry) 00853 return 0; 00854 00855 if(path[0] == '/') 00856 ++path; 00857 00858 /* begin with the root directory */ 00859 memset(dir_entry, 0, sizeof(*dir_entry)); 00860 dir_entry->attributes = FAT_ATTRIB_DIR; 00861 00862 while(1) 00863 { 00864 if(path[0] == '\0') 00865 return 1; 00866 00867 struct fat_dir_struct* dd = fat_open_dir(fs, dir_entry); 00868 if(!dd) 00869 break; 00870 00871 /* extract the next hierarchy we will search for */ 00872 const char* sub_path = strchr(path, '/'); 00873 uint8_t length_to_sep; 00874 if(sub_path) 00875 { 00876 length_to_sep = sub_path - path; 00877 ++sub_path; 00878 } 00879 else 00880 { 00881 length_to_sep = strlen(path); 00882 sub_path = path + length_to_sep; 00883 } 00884 00885 /* read directory entries */ 00886 while(fat_read_dir(dd, dir_entry)) 00887 { 00888 /* check if we have found the next hierarchy */ 00889 if((strlen(dir_entry->long_name) != length_to_sep || 00890 strncmp(path, dir_entry->long_name, length_to_sep) != 0)) 00891 continue; 00892 00893 fat_close_dir(dd); 00894 dd = 0; 00895 00896 if(path[length_to_sep] == '\0') 00897 /* we iterated through the whole path and have found the file */ 00898 return 1; 00899 00900 if(dir_entry->attributes & FAT_ATTRIB_DIR) 00901 { 00902 /* we found a parent directory of the file we are searching for */ 00903 path = sub_path; 00904 break; 00905 } 00906 00907 /* a parent of the file exists, but not the file itself */ 00908 return 0; 00909 } 00910 00911 fat_close_dir(dd); 00912 } 00913 00914 return 0; 00915 }


| void fat_get_file_modification_date | ( | const struct fat_dir_entry_struct * | dir_entry, | |
| uint16_t * | year, | |||
| uint8_t * | month, | |||
| uint8_t * | day | |||
| ) |
| void fat_get_file_modification_time | ( | const struct fat_dir_entry_struct * | dir_entry, | |
| uint8_t * | hour, | |||
| uint8_t * | min, | |||
| uint8_t * | sec | |||
| ) |
| offset_t fat_get_fs_free | ( | const struct fat_fs_struct * | fs | ) |
Returns the amount of free storage capacity on the filesystem in bytes.
| [in] | fs | The filesystem on which to operate. |
Definition at line 2376 of file fat.c.
References fat_usage_count_callback_arg::buffer_size, fat_usage_count_callback_arg::cluster_count, fat_header_struct::cluster_size, partition_struct::device_read_interval, FAT_FAT32_SUPPORT, fat_get_fs_free_16_callback(), fat_header_struct::fat_offset, fat_header_struct::fat_size, fat_fs_struct::header, fat_fs_struct::partition, PARTITION_TYPE_FAT16, and partition_struct::type.
Referenced by WaspSD::getDiskFree(), and WaspSD::print_disk_info().
02377 { 02378 if(!fs) 02379 return 0; 02380 02381 uint8_t fat[32]; 02382 struct fat_usage_count_callback_arg count_arg; 02383 count_arg.cluster_count = 0; 02384 count_arg.buffer_size = sizeof(fat); 02385 02386 offset_t fat_offset = fs->header.fat_offset; 02387 uint32_t fat_size = fs->header.fat_size; 02388 while(fat_size > 0) 02389 { 02390 uintptr_t length = UINTPTR_MAX - 1; 02391 if(fat_size < length) 02392 length = fat_size; 02393 02394 if(!fs->partition->device_read_interval(fat_offset, 02395 fat, 02396 sizeof(fat), 02397 length, 02398 #if FAT_FAT32_SUPPORT 02399 (fs->partition->type == PARTITION_TYPE_FAT16) ? 02400 fat_get_fs_free_16_callback : 02401 fat_get_fs_free_32_callback, 02402 #else 02403 fat_get_fs_free_16_callback, 02404 #endif 02405 &count_arg 02406 ) 02407 ) 02408 return 0; 02409 02410 fat_offset += length; 02411 fat_size -= length; 02412 } 02413 02414 return (offset_t) count_arg.cluster_count * fs->header.cluster_size; 02415 }


| offset_t fat_get_fs_size | ( | const struct fat_fs_struct * | fs | ) |
Deletes a directory.
This is just a synonym for fat_delete_file(). If a directory is deleted without first deleting its subdirectories and files, disk space occupied by these files will get wasted as there is no chance to release it and mark it as free.
| [in] | fs | The filesystem on which to operate. |
| [in] | dir_entry | The directory entry of the directory to delete. |
| [in] | fs | The filesystem on which to operate. |
Definition at line 2353 of file fat.c.
References fat_header_struct::cluster_size, fat_header_struct::fat_size, fat_fs_struct::header, fat_fs_struct::partition, PARTITION_TYPE_FAT32, and partition_struct::type.
Referenced by WaspSD::getDiskSize(), and WaspSD::print_disk_info().
02354 { 02355 if(!fs) 02356 return 0; 02357 02358 #if FAT_FAT32_SUPPORT 02359 if(fs->partition->type == PARTITION_TYPE_FAT32) 02360 return (offset_t) (fs->header.fat_size / 4 - 2) * fs->header.cluster_size; 02361 else 02362 #endif 02363 return (offset_t) (fs->header.fat_size / 2 - 2) * fs->header.cluster_size; 02364 }

| struct fat_fs_struct* fat_open | ( | struct partition_struct * | partition | ) | [read] |
Opens a FAT filesystem.
| [in] | partition | Discriptor of partition on which the filesystem resides. |
Definition at line 235 of file fat.c.
References partition_struct::device_write, partition_struct::device_write_interval, FAT_FS_COUNT, fat_fs_handles, fat_read_header(), FAT_WRITE_SUPPORT, and fat_fs_struct::partition.
Referenced by WaspSD::init().
00236 { 00237 if(!partition || 00238 #if FAT_WRITE_SUPPORT 00239 !partition->device_write || 00240 !partition->device_write_interval 00241 #else 00242 0 00243 #endif 00244 ) 00245 return 0; 00246 00247 #if USE_DYNAMIC_MEMORY 00248 struct fat_fs_struct* fs = malloc(sizeof(*fs)); 00249 if(!fs) 00250 return 0; 00251 #else 00252 struct fat_fs_struct* fs = fat_fs_handles; 00253 uint8_t i; 00254 for(i = 0; i < FAT_FS_COUNT; ++i) 00255 { 00256 if(!fs->partition) 00257 break; 00258 00259 ++fs; 00260 } 00261 if(i >= FAT_FS_COUNT) 00262 return 0; 00263 #endif 00264 00265 memset(fs, 0, sizeof(*fs)); 00266 00267 fs->partition = partition; 00268 if(!fat_read_header(fs)) 00269 { 00270 #if USE_DYNAMIC_MEMORY 00271 free(fs); 00272 #else 00273 fs->partition = 0; 00274 #endif 00275 return 0; 00276 } 00277 00278 return fs; 00279 }


| struct fat_dir_struct* fat_open_dir | ( | struct fat_fs_struct * | fs, | |
| const struct fat_dir_entry_struct * | dir_entry | |||
| ) | [read] |
Opens a directory.
| [in] | fs | The filesystem on which the directory to open resides. |
| [in] | dir_entry | The directory entry which stands for the directory to open. |
Definition at line 1376 of file fat.c.
References fat_dir_entry_struct::attributes, fat_dir_entry_struct::cluster, fat_dir_struct::dir_entry, fat_dir_struct::entry_cluster, fat_dir_struct::entry_offset, FAT_ATTRIB_DIR, FAT_DIR_COUNT, fat_dir_handles, and fat_dir_struct::fs.
Referenced by WaspSD::cd(), fat_get_dir_entry_of_path(), and WaspSD::init().
01377 { 01378 if(!fs || !dir_entry || !(dir_entry->attributes & FAT_ATTRIB_DIR)) 01379 return 0; 01380 01381 #if USE_DYNAMIC_MEMORY 01382 struct fat_dir_struct* dd = malloc(sizeof(*dd)); 01383 if(!dd) 01384 return 0; 01385 #else 01386 struct fat_dir_struct* dd = fat_dir_handles; 01387 uint8_t i; 01388 for(i = 0; i < FAT_DIR_COUNT; ++i) 01389 { 01390 if(!dd->fs) 01391 break; 01392 01393 ++dd; 01394 } 01395 if(i >= FAT_DIR_COUNT) 01396 return 0; 01397 #endif 01398 01399 memcpy(&dd->dir_entry, dir_entry, sizeof(*dir_entry)); 01400 dd->fs = fs; 01401 dd->entry_cluster = dir_entry->cluster; 01402 dd->entry_offset = 0; 01403 01404 return dd; 01405 }

| struct fat_file_struct* fat_open_file | ( | struct fat_fs_struct * | fs, | |
| const struct fat_dir_entry_struct * | dir_entry | |||
| ) | [read] |
Opens a file on a FAT filesystem.
| [in] | fs | The filesystem on which the file to open lies. |
| [in] | dir_entry | The directory entry of the file to open. |
Definition at line 926 of file fat.c.
References fat_dir_entry_struct::attributes, fat_dir_entry_struct::cluster, fat_file_struct::dir_entry, FAT_ATTRIB_DIR, FAT_FILE_COUNT, fat_file_handles, fat_file_struct::fs, fat_file_struct::pos, and fat_file_struct::pos_cluster.
Referenced by WaspSD::openFile().
00927 { 00928 if(!fs || !dir_entry || (dir_entry->attributes & FAT_ATTRIB_DIR)) 00929 return 0; 00930 00931 #if USE_DYNAMIC_MEMORY 00932 struct fat_file_struct* fd = malloc(sizeof(*fd)); 00933 if(!fd) 00934 return 0; 00935 #else 00936 struct fat_file_struct* fd = fat_file_handles; 00937 uint8_t i; 00938 for(i = 0; i < FAT_FILE_COUNT; ++i) 00939 { 00940 if(!fd->fs) 00941 break; 00942 00943 ++fd; 00944 } 00945 if(i >= FAT_FILE_COUNT) 00946 return 0; 00947 #endif 00948 00949 memcpy(&fd->dir_entry, dir_entry, sizeof(*dir_entry)); 00950 fd->fs = fs; 00951 fd->pos = 0; 00952 fd->pos_cluster = dir_entry->cluster; 00953 00954 return fd; 00955 }

| uint8_t fat_read_dir | ( | struct fat_dir_struct * | dd, | |
| struct fat_dir_entry_struct * | dir_entry | |||
| ) |
Reads the next directory entry contained within a parent directory.
| [in] | dd | The descriptor of the parent directory from which to read the entry. |
| [out] | dir_entry | Pointer to a buffer into which to write the directory entry information. |
Definition at line 1437 of file fat.c.
References fat_read_dir_callback_arg::bytes_read, fat_header_struct::cluster_size, fat_header_struct::cluster_zero_offset, partition_struct::device_read_interval, fat_read_dir_callback_arg::dir_entry, fat_dir_struct::entry_cluster, fat_dir_struct::entry_offset, fat_cluster_offset(), fat_dir_entry_read_callback(), fat_get_next_cluster(), fat_reset_dir(), fat_read_dir_callback_arg::finished, fat_dir_struct::fs, fat_fs_struct::header, fat_fs_struct::partition, PARTITION_TYPE_FAT32, fat_header_struct::root_dir_offset, and partition_struct::type.
Referenced by WaspSD::delDir(), fat_create_dir(), fat_create_file(), fat_get_dir_entry_of_path(), WaspSD::find_file_in_dir(), WaspSD::ls(), and WaspSD::numFiles().
01438 { 01439 if(!dd || !dir_entry) 01440 return 0; 01441 01442 /* get current position of directory handle */ 01443 struct fat_fs_struct* fs = dd->fs; 01444 const struct fat_header_struct* header = &fs->header; 01445 uint16_t cluster_size = header->cluster_size; 01446 cluster_t cluster_num = dd->entry_cluster; 01447 uint16_t cluster_offset = dd->entry_offset; 01448 struct fat_read_dir_callback_arg arg; 01449 01450 if(cluster_offset >= cluster_size) 01451 { 01452 /* The latest call hit the border of the last cluster in 01453 * the chain, but it still returned a directory entry. 01454 * So we now reset the handle and signal the caller the 01455 * end of the listing. 01456 */ 01457 fat_reset_dir(dd); 01458 return 0; 01459 } 01460 01461 /* reset callback arguments */ 01462 memset(&arg, 0, sizeof(arg)); 01463 memset(dir_entry, 0, sizeof(*dir_entry)); 01464 arg.dir_entry = dir_entry; 01465 01466 /* check if we read from the root directory */ 01467 if(cluster_num == 0) 01468 { 01469 #if FAT_FAT32_SUPPORT 01470 if(fs->partition->type == PARTITION_TYPE_FAT32) 01471 cluster_num = header->root_dir_cluster; 01472 else 01473 #endif 01474 cluster_size = header->cluster_zero_offset - header->root_dir_offset; 01475 } 01476 01477 /* read entries */ 01478 uint8_t buffer[32]; 01479 while(!arg.finished) 01480 { 01481 /* read directory entries up to the cluster border */ 01482 uint16_t cluster_left = cluster_size - cluster_offset; 01483 offset_t pos = cluster_offset; 01484 if(cluster_num == 0) 01485 pos += header->root_dir_offset; 01486 else 01487 pos += fat_cluster_offset(fs, cluster_num); 01488 01489 arg.bytes_read = 0; 01490 if(!fs->partition->device_read_interval(pos, 01491 buffer, 01492 sizeof(buffer), 01493 cluster_left, 01494 fat_dir_entry_read_callback, 01495 &arg) 01496 ) 01497 return 0; 01498 01499 cluster_offset += arg.bytes_read; 01500 01501 if(cluster_offset >= cluster_size) 01502 { 01503 /* we reached the cluster border and switch to the next cluster */ 01504 01505 /* get number of next cluster */ 01506 if((cluster_num = fat_get_next_cluster(fs, cluster_num)) != 0) 01507 { 01508 cluster_offset = 0; 01509 continue; 01510 } 01511 01512 /* we are at the end of the cluster chain */ 01513 if(!arg.finished) 01514 { 01515 /* directory entry not found, reset directory handle */ 01516 fat_reset_dir(dd); 01517 return 0; 01518 } 01519 else 01520 { 01521 /* The current execution of the function has been successful, 01522 * so we can not signal an end of the directory listing to 01523 * the caller, but must wait for the next call. So we keep an 01524 * invalid cluster offset to mark this directory handle's 01525 * traversal as finished. 01526 */ 01527 } 01528 01529 break; 01530 } 01531 } 01532 01533 dd->entry_cluster = cluster_num; 01534 dd->entry_offset = cluster_offset; 01535 01536 return arg.finished; 01537 }


| intptr_t fat_read_file | ( | struct fat_file_struct * | fd, | |
| uint8_t * | buffer, | |||
| uintptr_t | buffer_len | |||
| ) |
Reads data from a file.
The data requested is read from the current file location.
| [in] | fd | The file handle of the file from which to read. |
| [out] | buffer | The buffer into which to write. |
| [in] | buffer_len | The amount of data to read. |
Definition at line 993 of file fat.c.
References fat_dir_entry_struct::cluster, fat_header_struct::cluster_size, partition_struct::device_read, fat_file_struct::dir_entry, fat_cluster_offset(), fat_get_next_cluster(), fat_dir_entry_struct::file_size, fat_file_struct::fs, fat_fs_struct::header, fat_fs_struct::partition, fat_file_struct::pos, and fat_file_struct::pos_cluster.
Referenced by WaspSD::cat(), WaspSD::catBin(), WaspSD::catln(), WaspSD::indexOf(), and WaspSD::numln().
00994 { 00995 /* check arguments */ 00996 if(!fd || !buffer || buffer_len < 1) 00997 return -1; 00998 00999 /* determine number of bytes to read */ 01000 if(fd->pos + buffer_len > fd->dir_entry.file_size) 01001 buffer_len = fd->dir_entry.file_size - fd->pos; 01002 if(buffer_len == 0) 01003 return 0; 01004 01005 uint16_t cluster_size = fd->fs->header.cluster_size; 01006 cluster_t cluster_num = fd->pos_cluster; 01007 uintptr_t buffer_left = buffer_len; 01008 uint16_t first_cluster_offset = (uint16_t) (fd->pos & (cluster_size - 1)); 01009 01010 /* find cluster in which to start reading */ 01011 if(!cluster_num) 01012 { 01013 cluster_num = fd->dir_entry.cluster; 01014 01015 if(!cluster_num) 01016 { 01017 if(!fd->pos) 01018 return 0; 01019 else 01020 return -1; 01021 } 01022 01023 if(fd->pos) 01024 { 01025 uint32_t pos = fd->pos; 01026 while(pos >= cluster_size) 01027 { 01028 pos -= cluster_size; 01029 cluster_num = fat_get_next_cluster(fd->fs, cluster_num); 01030 if(!cluster_num) 01031 return -1; 01032 } 01033 } 01034 } 01035 01036 /* read data */ 01037 do 01038 { 01039 /* calculate data size to copy from cluster */ 01040 offset_t cluster_offset = fat_cluster_offset(fd->fs, cluster_num) + first_cluster_offset; 01041 uint16_t copy_length = cluster_size - first_cluster_offset; 01042 if(copy_length > buffer_left) 01043 copy_length = buffer_left; 01044 01045 /* read data */ 01046 if(!fd->fs->partition->device_read(cluster_offset, buffer, copy_length)) 01047 return buffer_len - buffer_left; 01048 01049 /* calculate new file position */ 01050 buffer += copy_length; 01051 buffer_left -= copy_length; 01052 fd->pos += copy_length; 01053 01054 if(first_cluster_offset + copy_length >= cluster_size) 01055 { 01056 /* we are on a cluster boundary, so get the next cluster */ 01057 if((cluster_num = fat_get_next_cluster(fd->fs, cluster_num))) 01058 { 01059 first_cluster_offset = 0; 01060 } 01061 else 01062 { 01063 fd->pos_cluster = 0; 01064 return buffer_len - buffer_left; 01065 } 01066 } 01067 01068 fd->pos_cluster = cluster_num; 01069 01070 } while(buffer_left > 0); /* check if we are done */ 01071 01072 return buffer_len; 01073 }


| uint8_t fat_reset_dir | ( | struct fat_dir_struct * | dd | ) |
Resets a directory handle.
Resets the directory handle such that reading restarts with the first directory entry.
| [in] | dd | The directory handle to reset. |
Definition at line 1550 of file fat.c.
References fat_dir_entry_struct::cluster, fat_dir_struct::dir_entry, fat_dir_struct::entry_cluster, and fat_dir_struct::entry_offset.
Referenced by fat_create_dir(), fat_create_file(), fat_read_dir(), and WaspSD::find_file_in_dir().
01551 { 01552 if(!dd) 01553 return 0; 01554 01555 dd->entry_cluster = dd->dir_entry.cluster; 01556 dd->entry_offset = 0; 01557 return 1; 01558 }

| uint8_t fat_resize_file | ( | struct fat_file_struct * | fd, | |
| uint32_t | size | |||
| ) |
Resizes a file to have a specific size.
Enlarges or shrinks the file pointed to by the file descriptor to have exactly the specified size.
If the file is truncated, all bytes having an equal or larger offset than the given size are lost. If the file is expanded, the additional bytes are allocated.
| [in] | fd | The file decriptor of the file which to resize. |
| [in] | size | The new size of the file. |
Definition at line 1288 of file fat.c.
References fat_dir_entry_struct::cluster, fat_header_struct::cluster_size, fat_file_struct::dir_entry, fat_append_clusters(), fat_free_clusters(), fat_get_next_cluster(), fat_terminate_clusters(), fat_write_dir_entry(), fat_dir_entry_struct::file_size, fat_file_struct::fs, fat_fs_struct::header, fat_file_struct::pos, and fat_file_struct::pos_cluster.
Referenced by fat_seek_file().
01289 { 01290 if(!fd) 01291 return 0; 01292 01293 cluster_t cluster_num = fd->dir_entry.cluster; 01294 uint16_t cluster_size = fd->fs->header.cluster_size; 01295 uint32_t size_new = size; 01296 01297 do 01298 { 01299 if(cluster_num == 0 && size_new == 0) 01300 /* the file stays empty */ 01301 break; 01302 01303 /* seek to the next cluster as long as we need the space */ 01304 while(size_new > cluster_size) 01305 { 01306 /* get next cluster of file */ 01307 cluster_t cluster_num_next = fat_get_next_cluster(fd->fs, cluster_num); 01308 if(cluster_num_next) 01309 { 01310 cluster_num = cluster_num_next; 01311 size_new -= cluster_size; 01312 } 01313 else 01314 { 01315 break; 01316 } 01317 } 01318 01319 if(size_new > cluster_size || cluster_num == 0) 01320 { 01321 /* Allocate new cluster chain and append 01322 * it to the existing one, if available. 01323 */ 01324 cluster_t cluster_count = (size_new + cluster_size - 1) / cluster_size; 01325 cluster_t cluster_new_chain = fat_append_clusters(fd->fs, cluster_num, cluster_count); 01326 if(!cluster_new_chain) 01327 return 0; 01328 01329 if(!cluster_num) 01330 { 01331 cluster_num = cluster_new_chain; 01332 fd->dir_entry.cluster = cluster_num; 01333 } 01334 } 01335 01336 /* write new directory entry */ 01337 fd->dir_entry.file_size = size; 01338 if(size == 0) 01339 fd->dir_entry.cluster = 0; 01340 if(!fat_write_dir_entry(fd->fs, &fd->dir_entry)) 01341 return 0; 01342 01343 if(size == 0) 01344 { 01345 /* free all clusters of file */ 01346 fat_free_clusters(fd->fs, cluster_num); 01347 } 01348 else if(size_new <= cluster_size) 01349 { 01350 /* free all clusters no longer needed */ 01351 fat_terminate_clusters(fd->fs, cluster_num); 01352 } 01353 01354 } while(0); 01355 01356 /* correct file position */ 01357 if(size < fd->pos) 01358 { 01359 fd->pos = size; 01360 fd->pos_cluster = 0; 01361 } 01362 01363 return 1; 01364 }


| uint8_t fat_seek_file | ( | struct fat_file_struct * | fd, | |
| int32_t * | offset, | |||
| uint8_t | whence | |||
| ) |
Repositions the read/write file offset.
Changes the file offset where the next call to fat_read_file() or fat_write_file() starts reading/writing.
If the new offset is beyond the end of the file, fat_resize_file() is implicitly called, i.e. the file is expanded.
The new offset can be given in different ways determined by the whence parameter:
*offset is relative to the beginning of the file.*offset is relative to the current file position.*offset is relative to the end of the file.
The resulting absolute offset is written to the location the offset parameter points to.
| [in] | fd | The file decriptor of the file on which to seek. |
| [in,out] | offset | A pointer to the new offset, as affected by the whence parameter. The function writes the new absolute offset to this location before it returns. |
| [in] | whence | Affects the way offset is interpreted, see above. |
Definition at line 1233 of file fat.c.
References fat_file_struct::dir_entry, fat_resize_file(), FAT_SEEK_CUR, FAT_SEEK_END, FAT_SEEK_SET, FAT_WRITE_SUPPORT, fat_dir_entry_struct::file_size, fat_file_struct::pos, and fat_file_struct::pos_cluster.
Referenced by WaspSD::cat(), WaspSD::catBin(), and WaspSD::writeSD().
01234 { 01235 if(!fd || !offset) 01236 return 0; 01237 01238 uint32_t new_pos = fd->pos; 01239 switch(whence) 01240 { 01241 case FAT_SEEK_SET: 01242 new_pos = *offset; 01243 break; 01244 case FAT_SEEK_CUR: 01245 new_pos += *offset; 01246 break; 01247 case FAT_SEEK_END: 01248 new_pos = fd->dir_entry.file_size + *offset; 01249 break; 01250 default: 01251 return 0; 01252 } 01253 01254 if(new_pos > fd->dir_entry.file_size 01255 #if FAT_WRITE_SUPPORT 01256 && !fat_resize_file(fd, new_pos) 01257 #endif 01258 ) 01259 return 0; 01260 01261 fd->pos = new_pos; 01262 fd->pos_cluster = 0; 01263 01264 *offset = (int32_t) new_pos; 01265 return 1; 01266 }


| intptr_t fat_write_file | ( | struct fat_file_struct * | fd, | |
| const uint8_t * | buffer, | |||
| uintptr_t | buffer_len | |||
| ) |
Writes data to a file.
The data is written to the current file location.
| [in] | fd | The file handle of the file to which to write. |
| [in] | buffer | The buffer from which to read the data to be written. |
| [in] | buffer_len | The amount of data to write. |
Definition at line 1088 of file fat.c.
References fat_dir_entry_struct::cluster, fat_header_struct::cluster_size, partition_struct::device_write, fat_file_struct::dir_entry, fat_append_clusters(), fat_cluster_offset(), fat_get_next_cluster(), fat_write_dir_entry(), fat_dir_entry_struct::file_size, fat_file_struct::fs, fat_fs_struct::header, fat_fs_struct::partition, fat_file_struct::pos, and fat_file_struct::pos_cluster.
Referenced by WaspSD::writeSD().
01089 { 01090 /* check arguments */ 01091 if(!fd || !buffer || buffer_len < 1) 01092 return -1; 01093 if(fd->pos > fd->dir_entry.file_size) 01094 return -1; 01095 01096 uint16_t cluster_size = fd->fs->header.cluster_size; 01097 cluster_t cluster_num = fd->pos_cluster; 01098 uintptr_t buffer_left = buffer_len; 01099 uint16_t first_cluster_offset = (uint16_t) (fd->pos & (cluster_size - 1)); 01100 01101 /* find cluster in which to start writing */ 01102 if(!cluster_num) 01103 { 01104 cluster_num = fd->dir_entry.cluster; 01105 01106 if(!cluster_num) 01107 { 01108 if(!fd->pos) 01109 { 01110 /* empty file */ 01111 fd->dir_entry.cluster = cluster_num = fat_append_clusters(fd->fs, 0, 1); 01112 if(!cluster_num) 01113 return -1; 01114 } 01115 else 01116 { 01117 return -1; 01118 } 01119 } 01120 01121 if(fd->pos) 01122 { 01123 uint32_t pos = fd->pos; 01124 cluster_t cluster_num_next; 01125 while(pos >= cluster_size) 01126 { 01127 pos -= cluster_size; 01128 cluster_num_next = fat_get_next_cluster(fd->fs, cluster_num); 01129 if(!cluster_num_next && pos == 0) 01130 /* the file exactly ends on a cluster boundary, and we append to it */ 01131 cluster_num_next = fat_append_clusters(fd->fs, cluster_num, 1); 01132 if(!cluster_num_next) 01133 return -1; 01134 01135 cluster_num = cluster_num_next; 01136 } 01137 } 01138 } 01139 01140 /* write data */ 01141 do 01142 { 01143 /* calculate data size to write to cluster */ 01144 offset_t cluster_offset = fat_cluster_offset(fd->fs, cluster_num) + first_cluster_offset; 01145 uint16_t write_length = cluster_size - first_cluster_offset; 01146 if(write_length > buffer_left) 01147 write_length = buffer_left; 01148 01149 /* write data which fits into the current cluster */ 01150 if(!fd->fs->partition->device_write(cluster_offset, buffer, write_length)) 01151 break; 01152 01153 /* calculate new file position */ 01154 buffer += write_length; 01155 buffer_left -= write_length; 01156 fd->pos += write_length; 01157 01158 if(first_cluster_offset + write_length >= cluster_size) 01159 { 01160 /* we are on a cluster boundary, so get the next cluster */ 01161 cluster_t cluster_num_next = fat_get_next_cluster(fd->fs, cluster_num); 01162 if(!cluster_num_next && buffer_left > 0) 01163 /* we reached the last cluster, append a new one */ 01164 cluster_num_next = fat_append_clusters(fd->fs, cluster_num, 1); 01165 if(!cluster_num_next) 01166 { 01167 fd->pos_cluster = 0; 01168 break; 01169 } 01170 01171 cluster_num = cluster_num_next; 01172 first_cluster_offset = 0; 01173 } 01174 01175 fd->pos_cluster = cluster_num; 01176 01177 } while(buffer_left > 0); /* check if we are done */ 01178 01179 /* update directory entry */ 01180 if(fd->pos > fd->dir_entry.file_size) 01181 { 01182 #if !FAT_DELAY_DIRENTRY_UPDATE 01183 uint32_t size_old = fd->dir_entry.file_size; 01184 #endif 01185 01186 /* update file size */ 01187 fd->dir_entry.file_size = fd->pos; 01188 01189 #if !FAT_DELAY_DIRENTRY_UPDATE 01190 /* write directory entry */ 01191 if(!fat_write_dir_entry(fd->fs, &fd->dir_entry)) 01192 { 01193 /* We do not return an error here since we actually wrote 01194 * some data to disk. So we calculate the amount of data 01195 * we wrote to disk and which lies within the old file size. 01196 */ 01197 buffer_left = fd->pos - size_old; 01198 fd->pos = size_old; 01199 } 01200 #endif 01201 } 01202 01203 return buffer_len - buffer_left; 01204 }


| void get_datetime | ( | uint16_t * | year, | |
| uint8_t * | month, | |||
| uint8_t * | day, | |||
| uint8_t * | hour, | |||
| uint8_t * | min, | |||
| uint8_t * | sec | |||
| ) |
1.5.6