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