GCC Code Coverage Report


Directory: common/src/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 100.0% 206 / 0 / 206
Functions: 100.0% 1 / 0 / 1
Branches: 100.0% 279 / 0 / 279

fx_directory_free_search.c
Line Branch Exec Source
1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 * Copyright (c) 2026-present Eclipse ThreadX contributors
4 *
5 * This program and the accompanying materials are made available under the
6 * terms of the MIT License which is available at
7 * https://opensource.org/licenses/MIT.
8 *
9 * SPDX-License-Identifier: MIT
10 **************************************************************************/
11
12
13 /**************************************************************************/
14 /**************************************************************************/
15 /** */
16 /** FileX Component */
17 /** */
18 /** Directory */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22
23 #define FX_SOURCE_CODE
24
25
26 /* Include necessary system files. */
27
28 #include "fx_api.h"
29 #include "fx_system.h"
30 #include "fx_directory.h"
31 #include "fx_utility.h"
32
33
34 /**************************************************************************/
35 /* */
36 /* FUNCTION RELEASE */
37 /* */
38 /* _fx_directory_free_search PORTABLE C */
39 /* 6.1.12 */
40 /* AUTHOR */
41 /* */
42 /* William E. Lamie, Microsoft Corporation */
43 /* */
44 /* DESCRIPTION */
45 /* */
46 /* This function searches the media for a free directory entry. */
47 /* */
48 /* INPUT */
49 /* */
50 /* media_ptr Media control block pointer */
51 /* directory_ptr Pointer to directory to */
52 /* search in */
53 /* entry_ptr Pointer to directory entry */
54 /* record */
55 /* */
56 /* OUTPUT */
57 /* */
58 /* return status */
59 /* */
60 /* CALLS */
61 /* */
62 /* _fx_directory_entry_read Read entries from directory */
63 /* _fx_directory_entry_write Write entries to directory */
64 /* _fx_utility_FAT_entry_read Read a FAT entry */
65 /* _fx_utility_FAT_entry_write Write a FAT entry */
66 /* _fx_utility_FAT_flush Flush written FAT entries */
67 /* _fx_utility_logical_sector_flush Flush logical sector cache */
68 /* _fx_utility_logical_sector_read Read logical sector */
69 /* _fx_utility_logical_sector_write Write logical sector */
70 /* */
71 /* CALLED BY */
72 /* */
73 /* FileX System Functions */
74 /* */
75 /**************************************************************************/
76 679470 UINT _fx_directory_free_search(FX_MEDIA *media_ptr, FX_DIR_ENTRY *directory_ptr, FX_DIR_ENTRY *entry_ptr)
77 {
78
79 ULONG i, j;
80 UCHAR *work_ptr;
81 UINT status, total_entries;
82 ULONG entry_sector, entry_offset;
83 ULONG FAT_index, FAT_value;
84 ULONG cluster, total_clusters, clusters_needed;
85 ULONG first_new_cluster, last_cluster, clusters;
86 ULONG directory_index;
87 ULONG directory_entries;
88 ULONG logical_sector;
89 FX_DIR_ENTRY *search_dir_ptr;
90 ULONG free_entry_start;
91 UINT sectors;
92
93 FX_INT_SAVE_AREA
94
95
96
97 #ifndef FX_MEDIA_STATISTICS_DISABLE
98
99 /* Increment the number of directory free entry search requests. */
100 679470 media_ptr -> fx_media_directory_free_searches++;
101 #endif
102
103 /* Initialize the entry sector values. */
104 679470 entry_sector = entry_offset = 0;
105
106 /* Set the long file name flag to false. */
107 679470 entry_ptr -> fx_dir_entry_long_name_present = 0;
108
109 /* Are there leading dots? */
110
2/2
✓ Branch 2 → 3 taken 63 times.
✓ Branch 2 → 5 taken 679407 times.
679470 if (entry_ptr -> fx_dir_entry_name[0] == '.')
111 {
112
113 /* Is there more than 1 dot? */
114
2/2
✓ Branch 3 → 4 taken 9 times.
✓ Branch 3 → 5 taken 54 times.
63 if (entry_ptr -> fx_dir_entry_name[1] == '.')
115 {
116 /* Yes, consider the name invalid. */
117 9 return(FX_INVALID_NAME);
118 }
119 }
120
121 /* Determine if a long file name is present. */
122
2/2
✓ Branch 52 → 6 taken 6241979 times.
✓ Branch 52 → 53 taken 679452 times.
6921431 for (i = 0, j = 0; entry_ptr -> fx_dir_entry_name[i]; i++)
123 {
124
125 /* Check for upper-case characters. */
126
4/4
✓ Branch 6 → 7 taken 4610741 times.
✓ Branch 6 → 9 taken 1631238 times.
✓ Branch 7 → 8 taken 4470024 times.
✓ Branch 7 → 9 taken 140717 times.
6241979 if ((entry_ptr -> fx_dir_entry_name[i] >= 'A') && (entry_ptr -> fx_dir_entry_name[i] <= 'Z'))
127 {
128 4470024 continue;
129 }
130 /* Check for numeric characters. */
131
4/4
✓ Branch 9 → 10 taken 1278178 times.
✓ Branch 9 → 12 taken 493777 times.
✓ Branch 10 → 11 taken 1137434 times.
✓ Branch 10 → 12 taken 140744 times.
1771955 else if ((entry_ptr -> fx_dir_entry_name[i] >= '0') && (entry_ptr -> fx_dir_entry_name[i] <= '9'))
132 {
133 1137434 continue;
134 }
135 /* Check for any lower-case characters. */
136
4/4
✓ Branch 12 → 13 taken 137701 times.
✓ Branch 12 → 15 taken 496820 times.
✓ Branch 13 → 14 taken 137611 times.
✓ Branch 13 → 15 taken 90 times.
634521 else if ((entry_ptr -> fx_dir_entry_name[i] >= 'a') && (entry_ptr -> fx_dir_entry_name[i] <= 'z'))
137 {
138 137611 entry_ptr -> fx_dir_entry_long_name_present = 1;
139 }
140 /* Check for a space in the middle of the name. */
141
2/2
✓ Branch 15 → 16 taken 135 times.
✓ Branch 15 → 17 taken 496775 times.
496910 else if (entry_ptr -> fx_dir_entry_name[i] == ' ')
142 {
143 135 entry_ptr -> fx_dir_entry_long_name_present = 1;
144 }
145 /* Check for a dot in the name. */
146
2/2
✓ Branch 17 → 18 taken 492881 times.
✓ Branch 17 → 22 taken 3894 times.
496775 else if (entry_ptr -> fx_dir_entry_name[i] == '.')
147 {
148 /* Determine if this is the first dot detected. */
149
2/2
✓ Branch 18 → 19 taken 492791 times.
✓ Branch 18 → 21 taken 90 times.
492881 if (j == 0)
150 {
151 /* First dot, remember where it was. */
152 492791 j = i;
153
154 /* Determine if this is a leading dot. */
155
2/2
✓ Branch 19 → 20 taken 54 times.
✓ Branch 19 → 51 taken 492737 times.
492791 if (i == 0)
156 {
157
158 /* Leading dot detected, treat as a long filename. */
159 54 entry_ptr -> fx_dir_entry_long_name_present = 1;
160 }
161 }
162 else
163 {
164 /* Second dot detected, must have a long file name. */
165 90 entry_ptr -> fx_dir_entry_long_name_present = 1;
166 }
167 }
168 /* Check for a special 0xE5 character. */
169
2/2
✓ Branch 22 → 23 taken 90 times.
✓ Branch 22 → 24 taken 3804 times.
3894 else if ((UCHAR)entry_ptr -> fx_dir_entry_name[i] == (UCHAR)0xE5)
170 {
171 90 entry_ptr -> fx_dir_entry_long_name_present = 1;
172 }
173 /* Check for code point value greater than 127. */
174
2/2
✓ Branch 24 → 25 taken 9 times.
✓ Branch 24 → 26 taken 3795 times.
3804 else if ((UCHAR)entry_ptr -> fx_dir_entry_name[i] > (UCHAR)127)
175 {
176 9 continue;
177 }
178 /* Check for any special characters. */
179
2/2
✓ Branch 26 → 27 taken 3723 times.
✓ Branch 26 → 42 taken 72 times.
3795 else if ((entry_ptr -> fx_dir_entry_name[i] == '~') ||
180
2/2
✓ Branch 27 → 28 taken 3187 times.
✓ Branch 27 → 42 taken 536 times.
3723 (entry_ptr -> fx_dir_entry_name[i] == '-') ||
181
2/2
✓ Branch 28 → 29 taken 207 times.
✓ Branch 28 → 42 taken 2980 times.
3187 (entry_ptr -> fx_dir_entry_name[i] == '_') ||
182
2/2
✓ Branch 29 → 30 taken 198 times.
✓ Branch 29 → 42 taken 9 times.
207 (entry_ptr -> fx_dir_entry_name[i] == '}') ||
183
2/2
✓ Branch 30 → 31 taken 189 times.
✓ Branch 30 → 42 taken 9 times.
198 (entry_ptr -> fx_dir_entry_name[i] == '{') ||
184
2/2
✓ Branch 31 → 32 taken 171 times.
✓ Branch 31 → 42 taken 18 times.
189 (entry_ptr -> fx_dir_entry_name[i] == '(') ||
185
2/2
✓ Branch 32 → 33 taken 153 times.
✓ Branch 32 → 42 taken 18 times.
171 (entry_ptr -> fx_dir_entry_name[i] == ')') ||
186
2/2
✓ Branch 33 → 34 taken 144 times.
✓ Branch 33 → 42 taken 9 times.
153 (entry_ptr -> fx_dir_entry_name[i] == '`') ||
187
2/2
✓ Branch 34 → 35 taken 126 times.
✓ Branch 34 → 42 taken 18 times.
144 (entry_ptr -> fx_dir_entry_name[i] == '\'') ||
188
2/2
✓ Branch 35 → 36 taken 117 times.
✓ Branch 35 → 42 taken 9 times.
126 (entry_ptr -> fx_dir_entry_name[i] == '!') ||
189
2/2
✓ Branch 36 → 37 taken 108 times.
✓ Branch 36 → 42 taken 9 times.
117 (entry_ptr -> fx_dir_entry_name[i] == '#') ||
190
2/2
✓ Branch 37 → 38 taken 99 times.
✓ Branch 37 → 42 taken 9 times.
108 (entry_ptr -> fx_dir_entry_name[i] == '$') ||
191
2/2
✓ Branch 38 → 39 taken 90 times.
✓ Branch 38 → 42 taken 9 times.
99 (entry_ptr -> fx_dir_entry_name[i] == '&') ||
192
2/2
✓ Branch 39 → 40 taken 81 times.
✓ Branch 39 → 42 taken 9 times.
90 (entry_ptr -> fx_dir_entry_name[i] == '@') ||
193
2/2
✓ Branch 40 → 41 taken 72 times.
✓ Branch 40 → 42 taken 9 times.
81 (entry_ptr -> fx_dir_entry_name[i] == '^') ||
194
2/2
✓ Branch 41 → 42 taken 9 times.
✓ Branch 41 → 43 taken 63 times.
72 (entry_ptr -> fx_dir_entry_name[i] == '%'))
195 {
196 3732 continue;
197 }
198 /* Check for long filename special characters. */
199
2/2
✓ Branch 43 → 44 taken 54 times.
✓ Branch 43 → 49 taken 9 times.
63 else if ((entry_ptr -> fx_dir_entry_name[i] == '+') ||
200
2/2
✓ Branch 44 → 45 taken 45 times.
✓ Branch 44 → 49 taken 9 times.
54 (entry_ptr -> fx_dir_entry_name[i] == ',') ||
201
2/2
✓ Branch 45 → 46 taken 36 times.
✓ Branch 45 → 49 taken 9 times.
45 (entry_ptr -> fx_dir_entry_name[i] == ';') ||
202
2/2
✓ Branch 46 → 47 taken 27 times.
✓ Branch 46 → 49 taken 9 times.
36 (entry_ptr -> fx_dir_entry_name[i] == '=') ||
203
2/2
✓ Branch 47 → 48 taken 18 times.
✓ Branch 47 → 49 taken 9 times.
27 (entry_ptr -> fx_dir_entry_name[i] == '[') ||
204
2/2
✓ Branch 48 → 49 taken 9 times.
✓ Branch 48 → 50 taken 9 times.
18 (entry_ptr -> fx_dir_entry_name[i] == ']'))
205 {
206 54 entry_ptr -> fx_dir_entry_long_name_present = 1;
207 }
208 /* Something is wrong with the supplied name. */
209 else
210 {
211 9 return(FX_INVALID_NAME);
212 }
213 }
214
215 /* Determine if a dot was found. */
216
2/2
✓ Branch 53 → 54 taken 492737 times.
✓ Branch 53 → 56 taken 186715 times.
679452 if (j != 0)
217 {
218
219 /* Yes, Determine if the extension exceeds a 3 character extension. */
220
2/2
✓ Branch 54 → 55 taken 45 times.
✓ Branch 54 → 56 taken 492692 times.
492737 if ((i - j) > 4)
221 {
222
223 /* Yes, long file name is present. */
224 45 entry_ptr -> fx_dir_entry_long_name_present = 1;
225 }
226 }
227
228 /* Calculate the total entries needed. */
229
4/4
✓ Branch 56 → 57 taken 674584 times.
✓ Branch 56 → 62 taken 4868 times.
✓ Branch 57 → 58 taken 668387 times.
✓ Branch 57 → 62 taken 6197 times.
679452 if ((i <= 12) && (entry_ptr -> fx_dir_entry_long_name_present == 0))
230 {
231
232 /* Initialize the total entries to 1. */
233 668387 total_entries = 1;
234
235 /* Check for special instance of long file name. */
236
4/4
✓ Branch 58 → 59 taken 668378 times.
✓ Branch 58 → 60 taken 9 times.
✓ Branch 59 → 60 taken 54 times.
✓ Branch 59 → 61 taken 668324 times.
668387 if ((j >= 9) || ((i - j) >= 9))
237 {
238
239 /* The dot is after 8 character or there is no dot and the name
240 is greater than 8 character. */
241 63 entry_ptr -> fx_dir_entry_long_name_present = 1;
242 63 total_entries = 2;
243 }
244 }
245 else
246 {
247
248 /* Long file name is present, calculate how many entries are needed
249 to represent it. */
250
2/2
✓ Branch 62 → 63 taken 235 times.
✓ Branch 62 → 64 taken 10830 times.
11065 if (i % 13 == 0)
251 {
252 /* Exact fit, just add one for the 8.3 short name. */
253 235 total_entries = i / 13 + 1;
254 }
255 else
256 {
257 /* Non-exact fit, add two for 8.3 short name and overlap. */
258 10830 total_entries = i / 13 + 2;
259 }
260 }
261
262 /* Determine if the search is in the root directory or in a
263 sub-directory. Note: the directory search function clears the
264 first character of the name for the root directory. */
265
2/2
✓ Branch 65 → 66 taken 135137 times.
✓ Branch 65 → 67 taken 544315 times.
679452 if (directory_ptr -> fx_dir_entry_name[0])
266 {
267
268 /* Search for a free entry in a sub-directory. */
269
270 /* Pickup the number of entries in this directory. This was placed
271 into the unused file size field. */
272 135137 directory_entries = (ULONG)directory_ptr -> fx_dir_entry_file_size;
273
274 /* Point the search directory pointer to this entry. */
275 135137 search_dir_ptr = directory_ptr;
276
277 /* Ensure that the search directory's last search cluster is cleared. */
278 135137 search_dir_ptr -> fx_dir_entry_last_search_cluster = 0;
279
280 /* Set the initial index to 2, since the first two directory entries are
281 always allocated. */
282 135137 directory_index = 2;
283 }
284 else
285 {
286
287 /* Find a free entry in the root directory. */
288
289 /* Setup the number of directory entries. */
290 544315 directory_entries = (ULONG)media_ptr -> fx_media_root_directory_entries;
291
292 /* Set the search pointer to NULL since we are working off of the
293 root directory. */
294 544315 search_dir_ptr = FX_NULL;
295
296 /* Set the initial index to 0, since the first entry of the root directory is valid. */
297 544315 directory_index = 0;
298 }
299
300 /* Loop through entries in the search directory. Yes, this is a
301 linear search! */
302 679452 free_entry_start = directory_entries;
303 do
304 {
305
306 /* Read an entry from the directory. */
307 8804250 status = _fx_directory_entry_read(media_ptr, search_dir_ptr, &directory_index, entry_ptr);
308
309 /* Check for error status. */
310
2/2
✓ Branch 70 → 71 taken 51 times.
✓ Branch 70 → 72 taken 8804199 times.
8804250 if (status != FX_SUCCESS)
311 {
312 51 return(status);
313 }
314
315 /* Determine if this is an empty entry. */
316
4/4
✓ Branch 72 → 73 taken 5436 times.
✓ Branch 72 → 74 taken 8798763 times.
✓ Branch 73 → 74 taken 116 times.
✓ Branch 73 → 75 taken 5320 times.
8804199 if ((((UCHAR)entry_ptr -> fx_dir_entry_name[0] == (UCHAR)FX_DIR_ENTRY_FREE) && (entry_ptr -> fx_dir_entry_short_name[0] == 0)) ||
317
3/3
✓ Branch 74 → 75 taken 698102 times.
✓ Branch 74 → 88 taken 3600186 times.
✓ Branch 74 → 90 taken 4500591 times.
8798879 ((UCHAR)entry_ptr -> fx_dir_entry_name[0] == (UCHAR)FX_DIR_ENTRY_DONE))
318 {
319
320 /* Determine how many entries are needed. */
321
2/2
✓ Branch 75 → 76 taken 35116 times.
✓ Branch 75 → 80 taken 668306 times.
703422 if (total_entries > 1)
322 {
323
324 /* Multiple entries are needed for long file names. Mark this
325 entry as free. */
326
2/2
✓ Branch 76 → 77 taken 30058 times.
✓ Branch 76 → 80 taken 5058 times.
35116 if (entry_ptr -> fx_dir_entry_name[0] == FX_DIR_ENTRY_DONE)
327 {
328
329 30058 entry_ptr -> fx_dir_entry_long_name_present = 0;
330 30058 entry_ptr -> fx_dir_entry_name[0] = (CHAR)FX_DIR_ENTRY_FREE;
331 30058 entry_ptr -> fx_dir_entry_name[1] = (CHAR)0;
332
333 /* Write out the directory entry. */
334 30058 status = _fx_directory_entry_write(media_ptr, entry_ptr);
335
2/2
✓ Branch 78 → 79 taken 9 times.
✓ Branch 78 → 80 taken 30049 times.
30058 if(status != FX_SUCCESS)
336 {
337 9 return(status);
338 }
339
340 /* Note that for long names we need to avoid holes in the middle,
341 i.e. entries must be logically contiguous. */
342 }
343 }
344
345 /* Determine if we are at the first free entry. */
346
2/2
✓ Branch 80 → 81 taken 679602 times.
✓ Branch 80 → 82 taken 23811 times.
703413 if (free_entry_start == directory_entries)
347 {
348
349 /* Remember the start of the free entry. */
350 679602 free_entry_start = directory_index;
351 679602 entry_sector = (ULONG)entry_ptr -> fx_dir_entry_log_sector;
352 679602 entry_offset = entry_ptr -> fx_dir_entry_byte_offset;
353 }
354
355 /* Determine if there are enough free entries to satisfy the request. */
356
3/3
✓ Branch 82 → 83 taken 678496 times.
✓ Branch 82 → 87 taken 10637 times.
✓ Branch 82 → 89 taken 14280 times.
703413 if ((directory_index - free_entry_start + 1) >= total_entries)
357 {
358
359 /* Found an empty slot. Most pertinent information is already
360 in the entry structure. */
361
362 /* Setup the the sector and the offset. */
363 678496 entry_ptr -> fx_dir_entry_log_sector = entry_sector;
364 678496 entry_ptr -> fx_dir_entry_byte_offset = entry_offset;
365
366 /* Initialize the additional directory entries. */
367 678496 entry_ptr -> fx_dir_entry_reserved = 0;
368 678496 entry_ptr -> fx_dir_entry_created_time_ms = 0;
369
370 /* Lockout interrupts for time/date access. */
371 376922 FX_DISABLE_INTS
372
373 678496 entry_ptr -> fx_dir_entry_created_time = _fx_system_time;
374 678496 entry_ptr -> fx_dir_entry_created_date = _fx_system_date;
375 678496 entry_ptr -> fx_dir_entry_last_accessed_date = _fx_system_date;
376
377 /* Restore interrupts. */
378 376922 FX_RESTORE_INTS
379
380 /* Determine if a long file name is present. */
381
4/4
✓ Branch 83 → 84 taken 297273 times.
✓ Branch 83 → 85 taken 4301 times.
✓ Branch 85 → 86 taken 371033 times.
✓ Branch 85 → 87 taken 5889 times.
678496 if (total_entries == 1)
382 {
383 668306 entry_ptr -> fx_dir_entry_long_name_present = 0;
384 }
385 else
386 {
387 10190 entry_ptr -> fx_dir_entry_long_name_present = 1;
388 }
389
390 /* Return a successful completion. */
391 678496 return(FX_SUCCESS);
392 }
393 }
394 else
395 {
396
397 /* Reset the free entry start. */
398 8100777 free_entry_start = directory_entries;
399 }
400
401 /* Move to the next entry. */
402 8125694 directory_index++;
403
404 /* Determine if we have exceeded the number of entries in the current directory. */
405
6/6
✓ Branch 89 → 90 taken 45634 times.
✓ Branch 89 → 159 taken 1778361 times.
✓ Branch 89 → 161 taken 1786828 times.
✓ Branch 91 → 92 taken 57533 times.
✓ Branch 91 → 161 taken 2669432 times.
✓ Branch 91 → 163 taken 1787906 times.
8125694 if (directory_index >= directory_entries)
406 {
407
408 /* Calculate how many sectors we need for the new directory entry. */
409 103167 sectors = ((total_entries * FX_DIR_ENTRY_SIZE) + (media_ptr -> fx_media_bytes_per_sector - 1))/
410 103167 media_ptr -> fx_media_bytes_per_sector;
411
412 /* Now calculate how many clusters we need for the new directory entry. */
413 103167 clusters_needed = (sectors + (media_ptr -> fx_media_sectors_per_cluster - 1)) / media_ptr -> fx_media_sectors_per_cluster;
414
415 /* Not enough empty entries were found. If the specified directory is a sub-directory,
416 attempt to allocate another cluster to it. */
417
15/15
✓ Branch 90 → 91 taken 28448 times.
✓ Branch 90 → 92 taken 17186 times.
✓ Branch 91 → 92 taken 28104 times.
✓ Branch 91 → 159 taken 172 times.
✓ Branch 91 → 161 taken 172 times.
✓ Branch 92 → 93 taken 80848 times.
✓ Branch 92 → 94 taken 21971 times.
✓ Branch 92 → 159 taken 2 times.
✓ Branch 92 → 161 taken 2 times.
✓ Branch 93 → 94 taken 35132 times.
✓ Branch 93 → 161 taken 258 times.
✓ Branch 93 → 163 taken 172 times.
✓ Branch 94 → 95 taken 57098 times.
✓ Branch 94 → 161 taken 3 times.
✓ Branch 94 → 163 taken 2 times.
103167 if (((search_dir_ptr) || (media_ptr -> fx_media_32_bit_FAT)) && (media_ptr -> fx_media_available_clusters >= clusters_needed))
418 {
419
420 /* Search for the additional clusters we need. */
421 102384 first_new_cluster = 0;
422 102384 total_clusters = media_ptr -> fx_media_total_clusters;
423 102384 last_cluster = 0;
424 102384 FAT_index = media_ptr -> fx_media_cluster_search_start;
425 102384 clusters = clusters_needed;
426
427 /* Loop to find the needed clusters. */
428
4/4
✓ Branch 133 → 94 taken 45570 times.
✓ Branch 133 → 134 taken 45260 times.
✓ Branch 135 → 96 taken 57498 times.
✓ Branch 135 → 136 taken 57065 times.
205393 while (clusters)
429 {
430
431 /* Decrease the cluster count. */
432 103068 clusters--;
433
434 /* Loop to find the first available cluster. */
435 do
436 {
437
438 /* Make sure we stop looking after one pass through the FAT table. */
439
4/4
✓ Branch 95 → 96 taken 4 times.
✓ Branch 95 → 97 taken 46798 times.
✓ Branch 97 → 98 taken 5 times.
✓ Branch 97 → 99 taken 59044 times.
105851 if (!total_clusters)
440 {
441
442 /* Something is wrong with the media - the desired clusters were
443 not found in the FAT table. */
444 9 return(FX_NO_MORE_SPACE);
445 }
446
447 /* Read FAT entry. */
448 105842 status = _fx_utility_FAT_entry_read(media_ptr, FAT_index, &FAT_value);
449
450 /* Check for a bad status. */
451
4/4
✓ Branch 98 → 99 taken 4 times.
✓ Branch 98 → 100 taken 46794 times.
✓ Branch 100 → 101 taken 5 times.
✓ Branch 100 → 102 taken 59039 times.
105842 if (status != FX_SUCCESS)
452 {
453
454 /* Return the bad status. */
455 9 return(status);
456 }
457
458 /* Decrement the total cluster count. */
459 105833 total_clusters--;
460
461 /* Determine if the FAT entry is free. */
462
4/4
✓ Branch 100 → 101 taken 45562 times.
✓ Branch 100 → 104 taken 1232 times.
✓ Branch 102 → 103 taken 57488 times.
✓ Branch 102 → 106 taken 1551 times.
105833 if (FAT_value == FX_FREE_CLUSTER)
463 {
464
465 /* Move cluster search pointer forward. */
466 103050 media_ptr -> fx_media_cluster_search_start = FAT_index + 1;
467
468 /* Determine if this needs to be wrapped. */
469
4/4
✓ Branch 101 → 102 taken 8 times.
✓ Branch 101 → 103 taken 45554 times.
✓ Branch 103 → 104 taken 10 times.
✓ Branch 103 → 105 taken 57478 times.
103050 if (media_ptr -> fx_media_cluster_search_start >= (media_ptr -> fx_media_total_clusters + FX_FAT_ENTRY_START))
470 {
471
472 /* Wrap the search to the beginning FAT entry. */
473 18 media_ptr -> fx_media_cluster_search_start = FX_FAT_ENTRY_START;
474 }
475
476 /* Break this loop. */
477 103050 break;
478 }
479 else
480 {
481
482 /* FAT entry is not free... Advance the FAT index. */
483 2783 FAT_index++;
484
485 /* Determine if we need to wrap the FAT index around. */
486
4/4
✓ Branch 104 → 105 taken 46 times.
✓ Branch 104 → 106 taken 1186 times.
✓ Branch 106 → 107 taken 58 times.
✓ Branch 106 → 108 taken 1493 times.
2783 if (FAT_index >= (media_ptr -> fx_media_total_clusters + FX_FAT_ENTRY_START))
487 {
488
489 /* Wrap the search to the beginning FAT entry. */
490 104 FAT_index = FX_FAT_ENTRY_START;
491 }
492 }
493 } while (FX_TRUE);
494
495 /* We found an available cluster. We now need to clear all of entries in
496 each of the cluster's sectors. */
497
498 /* Calculate the logical sector of this cluster. */
499 103050 logical_sector = ((ULONG) media_ptr -> fx_media_data_sector_start) +
500 103050 ((((ULONG) FAT_index) - FX_FAT_ENTRY_START) *
501 103050 ((ULONG) media_ptr -> fx_media_sectors_per_cluster));
502
503 /* Pickup the number of sectors for the next directory cluster. */
504 103050 sectors = media_ptr -> fx_media_sectors_per_cluster;
505
506 /* Read the logical sector just for cache reasons. */
507 103050 status = _fx_utility_logical_sector_read(media_ptr, (ULONG64) logical_sector,
508 103050 media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
509
510 /* Check the return value. */
511
4/4
✓ Branch 108 → 109 taken 4 times.
✓ Branch 108 → 110 taken 45558 times.
✓ Branch 110 → 111 taken 5 times.
✓ Branch 110 → 112 taken 57483 times.
103050 if (status != FX_SUCCESS)
512 {
513
514 /* Return the error status. */
515 9 return(status);
516 }
517
518 /* Clear the entire first sector of the new sub-directory cluster. */
519 103041 work_ptr = (UCHAR *)media_ptr -> fx_media_memory_buffer;
520 103041 i = 0;
521
4/4
✓ Branch 112 → 111 taken 1458432 times.
✓ Branch 112 → 113 taken 45558 times.
✓ Branch 114 → 113 taken 1840128 times.
✓ Branch 114 → 115 taken 57483 times.
3401601 while (i < media_ptr -> fx_media_bytes_per_sector)
522 {
523
524 /* Clear 4 bytes. */
525 3298560 *((ULONG *)work_ptr) = (ULONG)0;
526
527 /* Increment pointer. */
528 3298560 work_ptr = work_ptr + sizeof(ULONG);
529
530 /* Increment counter. */
531 3298560 i = i + (ULONG)sizeof(ULONG);
532 }
533
534 /* Write the logical sector to ensure the zeros are written. */
535 103041 status = _fx_utility_logical_sector_write(media_ptr, (ULONG64) logical_sector,
536 103041 media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
537
538 /* Determine if the write was successful. */
539
4/4
✓ Branch 114 → 115 taken 4 times.
✓ Branch 114 → 116 taken 45554 times.
✓ Branch 116 → 117 taken 5 times.
✓ Branch 116 → 118 taken 57478 times.
103041 if (status != FX_SUCCESS)
540 {
541
542 /* Return the error code. */
543 9 return(status);
544 }
545
546 /* Determine if there are more sectors to clear in the first cluster of the new
547 sub-directory. */
548
4/4
✓ Branch 116 → 117 taken 192 times.
✓ Branch 116 → 126 taken 45362 times.
✓ Branch 118 → 119 taken 239 times.
✓ Branch 118 → 128 taken 57239 times.
103032 if (sectors > 1)
549 {
550
551 /* Yes, invalidate all cached sectors that are contained in the newly allocated first
552 cluster of the directory. */
553
554 /* Flush the internal logical sector cache. */
555 431 status = _fx_utility_logical_sector_flush(media_ptr, (ULONG64) (logical_sector + 1), (ULONG64) (sectors - 1), FX_TRUE);
556
557 /* Determine if the flush was successful. */
558
4/4
✓ Branch 118 → 119 taken 2 times.
✓ Branch 118 → 120 taken 190 times.
✓ Branch 120 → 121 taken 3 times.
✓ Branch 120 → 122 taken 236 times.
431 if (status != FX_SUCCESS)
559 {
560
561 /* Return the error code. */
562 5 return(status);
563 }
564
565 /* Clear all additional sectors of new sub-directory. */
566 426 sectors--;
567
4/4
✓ Branch 125 → 121 taken 226 times.
✓ Branch 125 → 126 taken 186 times.
✓ Branch 127 → 123 taken 272 times.
✓ Branch 127 → 128 taken 231 times.
915 while (sectors)
568 {
569
570 #ifndef FX_MEDIA_STATISTICS_DISABLE
571
572 /* Increment the number of driver write sector(s) requests. */
573 498 media_ptr -> fx_media_driver_write_requests++;
574 #endif
575
576 /* Build Write request to the driver. */
577 498 media_ptr -> fx_media_driver_request = FX_DRIVER_WRITE;
578 498 media_ptr -> fx_media_driver_status = FX_IO_ERROR;
579 498 media_ptr -> fx_media_driver_buffer = media_ptr -> fx_media_memory_buffer;
580 498 media_ptr -> fx_media_driver_logical_sector = (ULONG)logical_sector + ((ULONG)sectors);
581 498 media_ptr -> fx_media_driver_sectors = 1;
582 498 media_ptr -> fx_media_driver_sector_type = FX_DIRECTORY_SECTOR;
583
584 /* Set the system write flag since we are writing a directory sector. */
585 498 media_ptr -> fx_media_driver_system_write = FX_TRUE;
586
587 /* If trace is enabled, insert this event into the trace buffer. */
588 FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_WRITE, media_ptr, ((ULONG)logical_sector) + ((ULONG)sectors), 1, media_ptr -> fx_media_memory_buffer, FX_TRACE_INTERNAL_EVENTS, 0, 0)
589
590 /* Invoke the driver to write the sector. */
591 498 (media_ptr -> fx_media_driver_entry) (media_ptr);
592
593 /* Clear the system write flag. */
594 498 media_ptr -> fx_media_driver_system_write = FX_FALSE;
595
596 /* Determine if an error occurred. */
597
4/4
✓ Branch 122 → 123 taken 4 times.
✓ Branch 122 → 124 taken 222 times.
✓ Branch 124 → 125 taken 5 times.
✓ Branch 124 → 126 taken 267 times.
498 if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
598 {
599
600 /* Return error code. */
601 9 return(media_ptr -> fx_media_driver_status);
602 }
603
604 /* Decrease the number of sectors to clear. */
605 489 sectors--;
606 }
607 }
608
609 /* Determine if we have found the first new cluster yet. */
610
4/4
✓ Branch 126 → 127 taken 45264 times.
✓ Branch 126 → 128 taken 284 times.
✓ Branch 128 → 129 taken 57070 times.
✓ Branch 128 → 130 taken 400 times.
103018 if (first_new_cluster == 0)
611 {
612
613 /* Remember the first new cluster. */
614 102334 first_new_cluster = FAT_index;
615 }
616
617 /* Check for a valid last cluster to link. */
618
4/4
✓ Branch 128 → 129 taken 284 times.
✓ Branch 128 → 132 taken 45264 times.
✓ Branch 130 → 131 taken 400 times.
✓ Branch 130 → 134 taken 57070 times.
103018 if (last_cluster)
619 {
620
621 /* Normal condition - link the last cluster with the new
622 found cluster. */
623 684 status = _fx_utility_FAT_entry_write(media_ptr, last_cluster, FAT_index);
624
625 /* Check for a bad FAT write status. */
626
4/4
✓ Branch 130 → 131 taken 4 times.
✓ Branch 130 → 132 taken 280 times.
✓ Branch 132 → 133 taken 5 times.
✓ Branch 132 → 134 taken 395 times.
684 if (status != FX_SUCCESS)
627 {
628
629 /* Return the bad status. */
630 9 return(status);
631 }
632 }
633
634 /* Otherwise, remember the new FAT index as the last. */
635 103009 last_cluster = FAT_index;
636
637 /* Move to the next FAT entry. */
638 103009 FAT_index = media_ptr -> fx_media_cluster_search_start;
639 }
640
641 /* Place an end-of-file marker on the last cluster. */
642 102325 status = _fx_utility_FAT_entry_write(media_ptr, last_cluster, media_ptr -> fx_media_fat_last);
643
644 /* Check for a bad FAT write status. */
645
4/4
✓ Branch 135 → 136 taken 4 times.
✓ Branch 135 → 137 taken 45256 times.
✓ Branch 137 → 138 taken 5 times.
✓ Branch 137 → 139 taken 57060 times.
102325 if (status != FX_SUCCESS)
646 {
647
648 /* Return the bad status. */
649 9 return(status);
650 }
651
652 #ifdef FX_FAULT_TOLERANT
653
654 /* Ensure the new FAT chain is properly written to the media. */
655
656 /* Flush the cached individual FAT entries */
657 45434 _fx_utility_FAT_flush(media_ptr);
658 #endif
659
660 /* Now the new cluster needs to be linked to the sub-directory. */
661
8/8
✓ Branch 137 → 138 taken 8582 times.
✓ Branch 137 → 139 taken 14054 times.
✓ Branch 138 → 139 taken 8570 times.
✓ Branch 138 → 140 taken 14050 times.
✓ Branch 139 → 140 taken 13164 times.
✓ Branch 139 → 141 taken 21082 times.
✓ Branch 140 → 141 taken 8764 times.
✓ Branch 140 → 142 taken 14050 times.
102316 if (search_dir_ptr)
662 {
663 39080 cluster = search_dir_ptr -> fx_dir_entry_cluster;
664 }
665 else
666 {
667 63236 cluster = media_ptr -> fx_media_root_cluster_32;
668 }
669
670 /* Initialize loop variables. */
671 102316 last_cluster = 0;
672 102316 i = 0;
673
674 /* Follow the link of FAT entries. */
675
8/8
✓ Branch 149 → 141 taken 72792 times.
✓ Branch 149 → 150 taken 22628 times.
✓ Branch 150 → 142 taken 72778 times.
✓ Branch 150 → 151 taken 22612 times.
✓ Branch 151 → 143 taken 110017 times.
✓ Branch 151 → 152 taken 34234 times.
✓ Branch 152 → 144 taken 73328 times.
✓ Branch 152 → 153 taken 22806 times.
431195 while (cluster < media_ptr -> fx_media_fat_reserved)
676 {
677
678 /* Read the current cluster entry from the FAT. */
679 328915 status = _fx_utility_FAT_entry_read(media_ptr, cluster, &FAT_value);
680 328915 i++;
681
682 /* Check the return value. */
683
8/8
✓ Branch 142 → 143 taken 2 times.
✓ Branch 142 → 144 taken 72790 times.
✓ Branch 143 → 144 taken 2 times.
✓ Branch 143 → 145 taken 72776 times.
✓ Branch 144 → 145 taken 3 times.
✓ Branch 144 → 146 taken 110014 times.
✓ Branch 145 → 146 taken 2 times.
✓ Branch 145 → 147 taken 73326 times.
328915 if (status != FX_SUCCESS)
684 {
685
686 /* Return the error status. */
687 9 return(status);
688 }
689
690 /* Determine if the FAT read was invalid. */
691
15/15
✓ Branch 144 → 145 taken 72788 times.
✓ Branch 144 → 147 taken 2 times.
✓ Branch 145 → 146 taken 145560 times.
✓ Branch 145 → 147 taken 2 times.
✓ Branch 145 → 148 taken 2 times.
✓ Branch 146 → 147 taken 182785 times.
✓ Branch 146 → 148 taken 72786 times.
✓ Branch 146 → 149 taken 3 times.
✓ Branch 147 → 148 taken 183334 times.
✓ Branch 147 → 149 taken 72773 times.
✓ Branch 147 → 150 taken 2 times.
✓ Branch 148 → 149 taken 73325 times.
✓ Branch 148 → 150 taken 110007 times.
✓ Branch 149 → 150 taken 2 times.
✓ Branch 149 → 151 taken 73320 times.
328906 if ((cluster < FX_FAT_ENTRY_START) || (cluster == FAT_value) || (i > media_ptr -> fx_media_total_clusters))
692 {
693
694 /* Return the bad status. */
695 27 return(FX_FAT_READ_ERROR);
696 }
697
698 /* Save the last valid cluster. */
699 328879 last_cluster = cluster;
700
701 /* Setup for the next cluster. */
702 328879 cluster = FAT_value;
703 }
704
705 /* Decrease the available clusters in the media. */
706 102280 media_ptr -> fx_media_available_clusters = media_ptr -> fx_media_available_clusters - clusters_needed;
707
708 /* Increase the number of directory entries. */
709 102280 directory_entries = directory_entries + ((clusters_needed * media_ptr -> fx_media_sectors_per_cluster) * media_ptr -> fx_media_bytes_per_sector) / FX_DIR_ENTRY_SIZE;
710
711 /* Determine if we need to reset the free entry start since we changed the
712 number of directory entries. If the last entry was not free, then we
713 should definitely reset the free entry start. */
714
10/10
✓ Branch 150 → 151 taken 404 times.
✓ Branch 150 → 152 taken 22224 times.
✓ Branch 151 → 152 taken 404 times.
✓ Branch 151 → 153 taken 22612 times.
✓ Branch 152 → 153 taken 837 times.
✓ Branch 152 → 154 taken 33799 times.
✓ Branch 153 → 154 taken 557 times.
✓ Branch 153 → 155 taken 23084 times.
✓ Branch 154 → 155 taken 2 times.
✓ Branch 154 → 156 taken 552 times.
102280 if (!(((UCHAR)entry_ptr -> fx_dir_entry_name[0] == (UCHAR) FX_DIR_ENTRY_FREE) && (entry_ptr -> fx_dir_entry_short_name[0] == 0)))
715 {
716
717 /* Reset the free entry start to indicate we haven't found a starting free entry yet. */
718 100094 free_entry_start = directory_entries;
719 }
720
721 /* Update the directory size field. */
722 102280 directory_ptr -> fx_dir_entry_file_size = directory_entries;
723
724 /* Defer the update of the FAT entry and the last cluster of the current
725 directory entry until after the new cluster is initialized and written out. */
726
727 /* Determine if a FAT32 is present. */
728
13/13
✓ Branch 153 → 154 taken 18172 times.
✓ Branch 153 → 156 taken 4456 times.
✓ Branch 154 → 155 taken 32222 times.
✓ Branch 154 → 156 taken 4118 times.
✓ Branch 154 → 157 taken 4444 times.
✓ Branch 155 → 156 taken 41309 times.
✓ Branch 155 → 157 taken 4118 times.
✓ Branch 155 → 158 taken 6975 times.
✓ Branch 156 → 157 taken 39250 times.
✓ Branch 156 → 158 taken 6177 times.
✓ Branch 156 → 159 taken 4638 times.
✓ Branch 157 → 158 taken 14050 times.
✓ Branch 157 → 159 taken 4118 times.
102280 if ((media_ptr -> fx_media_32_bit_FAT) && (search_dir_ptr == FX_NULL))
729 {
730
731 /* Change root directory entry count - FAT32 has a variable sized root directory. */
732 63236 media_ptr -> fx_media_root_directory_entries = directory_entries;
733 }
734
735 /* At this point, link up the last cluster with the new cluster. */
736 102280 status = _fx_utility_FAT_entry_write(media_ptr, last_cluster, first_new_cluster);
737
738 /* Check the return value. */
739
8/8
✓ Branch 157 → 158 taken 2 times.
✓ Branch 157 → 159 taken 22626 times.
✓ Branch 158 → 159 taken 2 times.
✓ Branch 158 → 160 taken 22610 times.
✓ Branch 159 → 160 taken 3 times.
✓ Branch 159 → 161 taken 34231 times.
✓ Branch 160 → 161 taken 2 times.
✓ Branch 160 → 162 taken 22804 times.
102280 if (status != FX_SUCCESS)
740 {
741
742 /* Return the error status. */
743 9 return(status);
744 }
745
746 #ifdef FX_FAULT_TOLERANT
747
748 /* Flush the cached individual FAT entries */
749 45414 _fx_utility_FAT_flush(media_ptr);
750 #endif
751 }
752 }
753
6/6
✓ Branch 159 → 160 taken 1800987 times.
✓ Branch 159 → 161 taken 174 times.
✓ Branch 161 → 162 taken 4513101 times.
✓ Branch 161 → 163 taken 435 times.
✓ Branch 163 → 164 taken 1810710 times.
✓ Branch 163 → 165 taken 174 times.
8125581 } while (directory_index < directory_entries);
754
755 /* Return FX_NO_MORE_SPACE status to the caller. */
756 783 return(FX_NO_MORE_SPACE);
757 }
758
759