GCC Code Coverage Report


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

fx_directory_delete.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_file.h"
32 #include "fx_utility.h"
33 #ifdef FX_ENABLE_FAULT_TOLERANT
34 #include "fx_fault_tolerant.h"
35 #endif /* FX_ENABLE_FAULT_TOLERANT */
36
37
38 /**************************************************************************/
39 /* */
40 /* FUNCTION RELEASE */
41 /* */
42 /* _fx_directory_delete PORTABLE C */
43 /* 6.1 */
44 /* AUTHOR */
45 /* */
46 /* William E. Lamie, Microsoft Corporation */
47 /* */
48 /* DESCRIPTION */
49 /* */
50 /* This function first attempts to find the specified directory. */
51 /* If found, the directory is examined to make sure it is empty. If */
52 /* the directory is not empty, an error code is returned to the */
53 /* caller. Otherwise, the directory will be deleted and its clusters */
54 /* will be made available. */
55 /* */
56 /* INPUT */
57 /* */
58 /* media_ptr Media control block pointer */
59 /* directory_name Directory name to delete */
60 /* */
61 /* OUTPUT */
62 /* */
63 /* return status */
64 /* */
65 /* CALLS */
66 /* */
67 /* _fx_directory_entry_read Read a directory entry */
68 /* _fx_directory_entry_write Write the new directory entry */
69 /* _fx_directory_search Search for the file name in */
70 /* the directory structure */
71 /* _fx_utility_logical_sector_flush Flush the written log sector */
72 /* _fx_utility_FAT_entry_read Read FAT entries to calculate */
73 /* the sub-directory size */
74 /* _fx_utility_FAT_entry_write Write FAT entry */
75 /* _fx_utility_FAT_flush Flush FAT cache */
76 /* _fx_fault_tolerant_transaction_start Start fault tolerant */
77 /* transaction */
78 /* _fx_fault_tolerant_transaction_end End fault tolerant transaction*/
79 /* _fx_fault_tolerant_recover Recover FAT chain */
80 /* _fx_fault_tolerant_reset_log_file Reset the log file */
81 /* */
82 /* CALLED BY */
83 /* */
84 /* Application Code */
85 /* */
86 /**************************************************************************/
87 1980 UINT _fx_directory_delete(FX_MEDIA *media_ptr, CHAR *directory_name)
88 {
89
90 UINT status;
91 ULONG cluster, next_cluster;
92 ULONG i, directory_size;
93 FX_DIR_ENTRY dir_entry;
94 FX_DIR_ENTRY search_directory;
95 FX_DIR_ENTRY search_entry;
96
97
98
99 #ifndef FX_MEDIA_STATISTICS_DISABLE
100
101 /* Increment the number of times this service has been called. */
102 1980 media_ptr -> fx_media_directory_deletes++;
103 #endif
104
105 /* Setup pointer to media name buffer. */
106 1980 dir_entry.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
107
108 /* Setup search pointer to media name buffer. */
109 1980 search_directory.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN * 2;
110
111 /* Setup search entry pointer to media name buffer. */
112 1980 search_entry.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN * 3;
113
114 /* Clear the short name string of the three file names that will be worked with. */
115 1980 dir_entry.fx_dir_entry_short_name[0] = 0;
116 1980 search_directory.fx_dir_entry_short_name[0] = 0;
117 1980 search_entry.fx_dir_entry_short_name[0] = 0;
118
119 /* Check the media to make sure it is open. */
120
2/2
✓ Branch 2 → 3 taken 9 times.
✓ Branch 2 → 4 taken 1971 times.
1980 if (media_ptr -> fx_media_id != FX_MEDIA_ID)
121 {
122
123 /* Return the media not opened error. */
124 9 return(FX_MEDIA_NOT_OPEN);
125 }
126
127 /* If trace is enabled, insert this event into the trace buffer. */
128 FX_TRACE_IN_LINE_INSERT(FX_TRACE_DIRECTORY_DELETE, media_ptr, directory_name, 0, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
129
130 /* Protect against other threads accessing the media. */
131 1098 FX_PROTECT
132
133 #ifdef FX_ENABLE_FAULT_TOLERANT
134 /* Start transaction. */
135 890 _fx_fault_tolerant_transaction_start(media_ptr);
136 #endif /* FX_ENABLE_FAULT_TOLERANT */
137
138 /* Check for write protect at the media level (set by driver). */
139
6/6
✓ Branch 4 → 5 taken 2 times.
✓ Branch 4 → 6 taken 428 times.
✓ Branch 5 → 6 taken 5 times.
✓ Branch 5 → 8 taken 1089 times.
✓ Branch 6 → 7 taken 2 times.
✓ Branch 6 → 10 taken 445 times.
1971 if (media_ptr -> fx_media_driver_write_protect)
140 {
141
142 #ifdef FX_ENABLE_FAULT_TOLERANT
143 4 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
144 #endif /* FX_ENABLE_FAULT_TOLERANT */
145
146 /* Release media protection. */
147 5 FX_UNPROTECT
148
149 /* Return write protect error. */
150 9 return(FX_WRITE_PROTECT);
151 }
152
153 /* Search the system for the supplied directory name. */
154 1962 status = _fx_directory_search(media_ptr, directory_name, &dir_entry, FX_NULL, FX_NULL);
155
156 /* Determine if the search was successful. */
157
6/6
✓ Branch 7 → 8 taken 4 times.
✓ Branch 7 → 9 taken 424 times.
✓ Branch 9 → 10 taken 10 times.
✓ Branch 9 → 12 taken 1079 times.
✓ Branch 11 → 12 taken 4 times.
✓ Branch 11 → 15 taken 441 times.
1962 if (status != FX_SUCCESS)
158 {
159
160 #ifdef FX_ENABLE_FAULT_TOLERANT
161 8 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
162 #endif /* FX_ENABLE_FAULT_TOLERANT */
163
164 /* Release media protection. */
165 10 FX_UNPROTECT
166
167 /* Return the error code. */
168 18 return(status);
169 }
170
171 /* Check to make sure the found entry is a directory. */
172
6/6
✓ Branch 9 → 10 taken 2 times.
✓ Branch 9 → 11 taken 422 times.
✓ Branch 12 → 13 taken 5 times.
✓ Branch 12 → 15 taken 1074 times.
✓ Branch 15 → 16 taken 2 times.
✓ Branch 15 → 19 taken 439 times.
1944 if (!(dir_entry.fx_dir_entry_attributes & (UCHAR)(FX_DIRECTORY)))
173 {
174
175 #ifdef FX_ENABLE_FAULT_TOLERANT
176 4 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
177 #endif /* FX_ENABLE_FAULT_TOLERANT */
178
179 /* Release media protection. */
180 5 FX_UNPROTECT
181
182 /* Return the not a directory error code. */
183 9 return(FX_NOT_DIRECTORY);
184 }
185
186 /* Check if the entry is read only */
187
6/6
✓ Branch 11 → 12 taken 2 times.
✓ Branch 11 → 13 taken 420 times.
✓ Branch 15 → 16 taken 5 times.
✓ Branch 15 → 18 taken 1069 times.
✓ Branch 19 → 20 taken 2 times.
✓ Branch 19 → 23 taken 437 times.
1935 if (dir_entry.fx_dir_entry_attributes & (UCHAR)(FX_READ_ONLY))
188 {
189 #ifdef FX_ENABLE_FAULT_TOLERANT
190 4 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
191 #endif /* FX_ENABLE_FAULT_TOLERANT */
192
193 /* Release media protection. */
194 5 FX_UNPROTECT
195
196 /* Return the not a directory error code. */
197 9 return(FX_WRITE_PROTECT);
198 }
199
200 /* Copy the directory entry to the search directory structure for
201 looking at the specified sub-directory contents. */
202 1926 search_directory = dir_entry;
203
204 /* Ensure that the search directory's last search cluster is cleared. */
205 1926 search_directory.fx_dir_entry_last_search_cluster = 0;
206
207
208 /* Calculate the directory size by counting the allocated
209 clusters for it. */
210 1926 i = 0;
211 1926 cluster = search_directory.fx_dir_entry_cluster;
212
6/6
✓ Branch 22 → 14 taken 498 times.
✓ Branch 22 → 23 taken 412 times.
✓ Branch 29 → 19 taken 1247 times.
✓ Branch 29 → 30 taken 1049 times.
✓ Branch 36 → 24 taken 497 times.
✓ Branch 36 → 37 taken 429 times.
4132 while (cluster < media_ptr -> fx_media_fat_reserved)
213 {
214
215 /* Increment the cluster count. */
216 2242 i++;
217
218 /* Read the next FAT entry. */
219 2242 status = _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
220
221 /* Check the return status. */
222
6/6
✓ Branch 15 → 16 taken 2 times.
✓ Branch 15 → 17 taken 496 times.
✓ Branch 20 → 21 taken 5 times.
✓ Branch 20 → 23 taken 1242 times.
✓ Branch 25 → 26 taken 2 times.
✓ Branch 25 → 29 taken 495 times.
2242 if (status != FX_SUCCESS)
223 {
224
225 #ifdef FX_ENABLE_FAULT_TOLERANT
226 4 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
227 #endif /* FX_ENABLE_FAULT_TOLERANT */
228
229 /* Release media protection. */
230 5 FX_UNPROTECT
231
232 /* Return the bad status. */
233 9 return(status);
234 }
235
236
18/18
✓ Branch 17 → 18 taken 494 times.
✓ Branch 17 → 20 taken 2 times.
✓ Branch 18 → 19 taken 492 times.
✓ Branch 18 → 20 taken 2 times.
✓ Branch 19 → 20 taken 2 times.
✓ Branch 19 → 21 taken 490 times.
✓ Branch 23 → 24 taken 1237 times.
✓ Branch 23 → 26 taken 5 times.
✓ Branch 24 → 25 taken 1232 times.
✓ Branch 24 → 26 taken 5 times.
✓ Branch 25 → 26 taken 5 times.
✓ Branch 25 → 28 taken 1227 times.
✓ Branch 29 → 30 taken 493 times.
✓ Branch 29 → 32 taken 2 times.
✓ Branch 30 → 31 taken 491 times.
✓ Branch 30 → 32 taken 2 times.
✓ Branch 31 → 32 taken 2 times.
✓ Branch 31 → 35 taken 489 times.
2233 if ((cluster < FX_FAT_ENTRY_START) || (cluster == next_cluster) || (i > media_ptr -> fx_media_total_clusters))
237 {
238 #ifdef FX_ENABLE_FAULT_TOLERANT
239 12 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
240 #endif /* FX_ENABLE_FAULT_TOLERANT */
241
242 /* Release media protection. */
243 15 FX_UNPROTECT
244
245 /* Return the bad status. */
246 27 return(FX_FAT_READ_ERROR);
247 }
248
249 2206 cluster = next_cluster;
250 }
251
252 /* Now we can calculate the directory size. */
253 1890 directory_size = (((ULONG)media_ptr -> fx_media_bytes_per_sector) *
254 1890 ((ULONG)media_ptr -> fx_media_sectors_per_cluster) * i) /
255 (ULONG)FX_DIR_ENTRY_SIZE;
256
257 /* Also save this in the directory entry so we don't have to
258 calculate it later. */
259 1890 search_directory.fx_dir_entry_file_size = directory_size;
260
261 /* Make sure the new name is not in the current directory. */
262 /* The first two entries are skipped because they are just part of the sub-directory. */
263 1890 i = 2;
264
265 do
266 {
267
268 /* Read an entry from the directory. */
269 3682 status = _fx_directory_entry_read(media_ptr, &search_directory, &i, &search_entry);
270
271 /* Check for error status. */
272
6/6
✓ Branch 25 → 26 taken 2 times.
✓ Branch 25 → 27 taken 806 times.
✓ Branch 32 → 33 taken 5 times.
✓ Branch 32 → 35 taken 2040 times.
✓ Branch 39 → 40 taken 2 times.
✓ Branch 39 → 43 taken 827 times.
3682 if (status != FX_SUCCESS)
273 {
274
275 #ifdef FX_ENABLE_FAULT_TOLERANT
276 4 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
277 #endif /* FX_ENABLE_FAULT_TOLERANT */
278
279 /* Release media protection. */
280 5 FX_UNPROTECT
281
282 /* Return error condition. */
283 9 return(status);
284 }
285
286 /* Determine if this is the last directory entry. */
287
6/6
✓ Branch 27 → 28 taken 386 times.
✓ Branch 27 → 29 taken 420 times.
✓ Branch 35 → 36 taken 984 times.
✓ Branch 35 → 37 taken 1056 times.
✓ Branch 43 → 44 taken 403 times.
✓ Branch 43 → 45 taken 424 times.
3673 if (search_entry.fx_dir_entry_name[0] == FX_DIR_ENTRY_DONE)
288 {
289 1773 break;
290 }
291
292
293 /* Determine if this is an empty entry. */
294
6/6
✓ Branch 29 → 30 taken 2 times.
✓ Branch 29 → 31 taken 418 times.
✓ Branch 37 → 38 taken 5 times.
✓ Branch 37 → 40 taken 1051 times.
✓ Branch 45 → 46 taken 2 times.
✓ Branch 45 → 49 taken 422 times.
1900 if ((UCHAR)search_entry.fx_dir_entry_name[0] != (UCHAR)FX_DIR_ENTRY_FREE)
295 {
296
297 #ifdef FX_ENABLE_FAULT_TOLERANT
298 4 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
299 #endif /* FX_ENABLE_FAULT_TOLERANT */
300
301 /* Release media protection. */
302 5 FX_UNPROTECT
303
304 /* Return error status. */
305 9 return(FX_DIR_NOT_EMPTY);
306 }
307
308 1891 i++;
309
6/6
✓ Branch 31 → 32 taken 396 times.
✓ Branch 31 → 33 taken 22 times.
✓ Branch 40 → 41 taken 996 times.
✓ Branch 40 → 42 taken 55 times.
✓ Branch 49 → 50 taken 400 times.
✓ Branch 49 → 51 taken 22 times.
1891 } while (i < directory_size);
310
311 /* At this point, we are going to delete the empty directory. */
312
313 #ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
314
315 /* Invalidate the directory search saved information. */
316 1872 media_ptr -> fx_media_last_found_name[0] = FX_NULL;
317 #endif
318
319 /* Mark the sub-directory entry as available. */
320 1872 dir_entry.fx_dir_entry_name[0] = (CHAR)FX_DIR_ENTRY_FREE;
321 1872 dir_entry.fx_dir_entry_short_name[0] = (CHAR)FX_DIR_ENTRY_FREE;
322
323 /* Now write out the directory entry. */
324 1872 status = _fx_directory_entry_write(media_ptr, &dir_entry);
325
326 /* Determine if the write was successful. */
327
6/6
✓ Branch 34 → 35 taken 2 times.
✓ Branch 34 → 36 taken 406 times.
✓ Branch 43 → 44 taken 5 times.
✓ Branch 43 → 46 taken 1034 times.
✓ Branch 52 → 53 taken 2 times.
✓ Branch 52 → 56 taken 423 times.
1872 if (status != FX_SUCCESS)
328 {
329
330 #ifdef FX_ENABLE_FAULT_TOLERANT
331 4 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
332 #endif /* FX_ENABLE_FAULT_TOLERANT */
333
334 /* Release media protection. */
335 5 FX_UNPROTECT
336
337 /* Return the error code. */
338 9 return(status);
339 }
340
341
342 /* Walk through the directory's clusters and release them. */
343 1863 cluster = search_directory.fx_dir_entry_cluster;
344
345
6/6
✓ Branch 48 → 37 taken 482 times.
✓ Branch 48 → 49 taken 396 times.
✓ Branch 61 → 47 taken 1209 times.
✓ Branch 61 → 62 taken 1009 times.
✓ Branch 74 → 57 taken 483 times.
✓ Branch 74 → 75 taken 413 times.
3992 while (cluster < media_ptr -> fx_media_fat_reserved)
346 {
347
348 /* Increment the cluster count. */
349 2174 i++;
350
351
352 /* Read the next FAT entry. */
353 2174 status = _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
354
355 /* Check the return status. */
356
6/6
✓ Branch 38 → 39 taken 2 times.
✓ Branch 38 → 40 taken 480 times.
✓ Branch 48 → 49 taken 5 times.
✓ Branch 48 → 51 taken 1204 times.
✓ Branch 58 → 59 taken 2 times.
✓ Branch 58 → 62 taken 481 times.
2174 if (status != FX_SUCCESS)
357 {
358
359 #ifdef FX_ENABLE_FAULT_TOLERANT
360 4 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
361 #endif /* FX_ENABLE_FAULT_TOLERANT */
362
363 /* Release media protection. */
364 5 FX_UNPROTECT
365
366 /* Return the bad status. */
367 9 return(status);
368 }
369
370
18/18
✓ Branch 40 → 41 taken 478 times.
✓ Branch 40 → 43 taken 2 times.
✓ Branch 41 → 42 taken 476 times.
✓ Branch 41 → 43 taken 2 times.
✓ Branch 42 → 43 taken 2 times.
✓ Branch 42 → 44 taken 474 times.
✓ Branch 51 → 52 taken 1199 times.
✓ Branch 51 → 54 taken 5 times.
✓ Branch 52 → 53 taken 1194 times.
✓ Branch 52 → 54 taken 5 times.
✓ Branch 53 → 54 taken 5 times.
✓ Branch 53 → 56 taken 1189 times.
✓ Branch 62 → 63 taken 479 times.
✓ Branch 62 → 65 taken 2 times.
✓ Branch 63 → 64 taken 477 times.
✓ Branch 63 → 65 taken 2 times.
✓ Branch 64 → 65 taken 2 times.
✓ Branch 64 → 68 taken 475 times.
2165 if ((cluster < FX_FAT_ENTRY_START) || (cluster == next_cluster) || (i > media_ptr -> fx_media_total_clusters))
371 {
372
373 #ifdef FX_ENABLE_FAULT_TOLERANT
374 12 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
375 #endif /* FX_ENABLE_FAULT_TOLERANT */
376
377 /* Release media protection. */
378 15 FX_UNPROTECT
379
380 /* Return the bad status. */
381 27 return(FX_FAT_READ_ERROR);
382 }
383
384 /* Release the current cluster. */
385
386 2138 status = _fx_utility_FAT_entry_write(media_ptr, cluster, FX_FREE_CLUSTER);
387
388 /* Check the return status. */
389
6/6
✓ Branch 45 → 46 taken 2 times.
✓ Branch 45 → 47 taken 472 times.
✓ Branch 57 → 58 taken 5 times.
✓ Branch 57 → 60 taken 1184 times.
✓ Branch 69 → 70 taken 2 times.
✓ Branch 69 → 73 taken 473 times.
2138 if (status != FX_SUCCESS)
390 {
391
392 #ifdef FX_ENABLE_FAULT_TOLERANT
393 4 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
394 #endif /* FX_ENABLE_FAULT_TOLERANT */
395
396 /* Release media protection. */
397 5 FX_UNPROTECT
398
399 /* Return the bad status. */
400 9 return(status);
401 }
402
403 /* Increment the number of available clusters for the media. */
404 2129 media_ptr -> fx_media_available_clusters++;
405
406 /* Copy next cluster to current cluster. */
407 2129 cluster = next_cluster;
408 }
409
410 #ifdef FX_FAULT_TOLERANT
411
412 /* Flush the cached individual FAT entries */
413 822 _fx_utility_FAT_flush(media_ptr);
414 #endif
415
416 /* Flush the logical sector cache. */
417 1818 status = _fx_utility_logical_sector_flush(media_ptr, ((ULONG64) 1), (ULONG64)(media_ptr -> fx_media_sectors_per_FAT), FX_FALSE);
418
419 #ifdef FX_ENABLE_FAULT_TOLERANT
420 /* Check for a bad status. */
421
4/4
✓ Branch 64 → 65 taken 1 time.
✓ Branch 64 → 67 taken 408 times.
✓ Branch 77 → 78 taken 1 time.
✓ Branch 77 → 81 taken 412 times.
822 if (status != FX_SUCCESS)
422 {
423
424 2 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
425
426 /* Release media protection. */
427 1 FX_UNPROTECT
428
429 /* Return the bad status. */
430 2 return(status);
431 }
432
433 /* End transaction. */
434 820 status = _fx_fault_tolerant_transaction_end(media_ptr);
435 #endif /* FX_ENABLE_FAULT_TOLERANT */
436
437 /* Release media protection. */
438 1000 FX_UNPROTECT
439
440 /* Directory delete is complete, return status. */
441 1792 return(status);
442 }
443
444