GCC Code Coverage Report


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

fx_directory_next_entry_find.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 #ifndef FX_NO_LOCAL_PATH
34 FX_LOCAL_PATH_SETUP
35 #endif
36
37
38 /**************************************************************************/
39 /* */
40 /* FUNCTION RELEASE */
41 /* */
42 /* _fx_directory_next_entry_find PORTABLE C */
43 /* 6.1 */
44 /* AUTHOR */
45 /* */
46 /* William E. Lamie, Microsoft Corporation */
47 /* */
48 /* DESCRIPTION */
49 /* */
50 /* This function returns the name of the next entry in the current */
51 /* working directory. The function that returns the first name in the */
52 /* current directory must be called prior to this function. */
53 /* */
54 /* INPUT */
55 /* */
56 /* media_ptr Media control block pointer */
57 /* directory_name Destination for directory */
58 /* name */
59 /* */
60 /* OUTPUT */
61 /* */
62 /* return status */
63 /* */
64 /* CALLS */
65 /* */
66 /* _fx_directory_entry_read Read entries from root dir */
67 /* _fx_utility_FAT_entry_read Read FAT entries to calculate */
68 /* the sub-directory size */
69 /* */
70 /* CALLED BY */
71 /* */
72 /* Application Code and */
73 /* FileX System Functions */
74 /* */
75 /**************************************************************************/
76 17005 UINT _fx_directory_next_entry_find(FX_MEDIA *media_ptr, CHAR *directory_name)
77 {
78
79 ULONG i;
80 UINT status;
81 UINT temp_status;
82 17005 ULONG cluster, next_cluster = 0;
83 ULONG64 directory_size;
84 FX_DIR_ENTRY entry;
85 FX_DIR_ENTRY *search_dir_ptr;
86 FX_PATH *path_ptr;
87 #ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
88 UINT index;
89 17005 CHAR *path_string_ptr = FX_NULL;
90 #endif
91
92
93 #ifndef FX_MEDIA_STATISTICS_DISABLE
94
95 /* Increment the number of times this service has been called. */
96 17005 media_ptr -> fx_media_directory_next_entry_finds++;
97 #endif
98
99 /* Setup pointer to media name buffer. */
100 17005 entry.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
101
102 /* Clear the short name string. */
103 17005 entry.fx_dir_entry_short_name[0] = 0;
104
105 /* Check the media to make sure it is open. */
106
2/2
✓ Branch 2 → 3 taken 9 times.
✓ Branch 2 → 4 taken 16996 times.
17005 if (media_ptr -> fx_media_id != FX_MEDIA_ID)
107 {
108
109 /* Return the media not opened error. */
110 9 return(FX_MEDIA_NOT_OPEN);
111 }
112
113 /* If trace is enabled, insert this event into the trace buffer. */
114 FX_TRACE_IN_LINE_INSERT(FX_TRACE_DIRECTORY_NEXT_ENTRY_FIND, media_ptr, directory_name, 0, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
115
116 /* Protect against other threads accessing the media. */
117 14506 FX_PROTECT
118
119 /* First check for a local path pointer stored in the thread control block. This
120 is only available in ThreadX Version 4 and above. */
121
122 #ifndef FX_NO_LOCAL_PATH
123
124
2/2
✓ Branch 5 → 6 taken 13526 times.
✓ Branch 5 → 9 taken 980 times.
14506 if (_tx_thread_current_ptr -> tx_thread_filex_ptr)
125 {
126
127 /* Setup the default path pointer. */
128 13526 path_ptr = (FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr;
129
130 /* Determine if we are at the root directory. */
131
2/2
✓ Branch 6 → 7 taken 12657 times.
✓ Branch 6 → 8 taken 869 times.
13526 if (path_ptr -> fx_path_directory.fx_dir_entry_name[0])
132 {
133
134 /* No, we are not at the root directory. */
135
136 #ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
137
138 /* Setup pointer to the path. */
139 12657 path_string_ptr = ((FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr) -> fx_path_string;
140 #endif
141
142 /* Set the internal pointer to the search directory as well. */
143 12657 search_dir_ptr = &(path_ptr -> fx_path_directory);
144 }
145 else
146 {
147
148 /* The current default directory is the root so just set the
149 search directory pointer to NULL. */
150 869 search_dir_ptr = FX_NULL;
151 }
152 }
153 else
154 #endif
155
156 /* Set the initial search directory to the current working
157 directory - if there is one. */
158
4/4
✓ Branch 4 → 5 taken 1726 times.
✓ Branch 4 → 6 taken 764 times.
✓ Branch 9 → 10 taken 585 times.
✓ Branch 9 → 11 taken 395 times.
3470 if (media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name[0])
159 {
160
161 /* Setup the path pointer to the global media path. */
162 2311 path_ptr = &media_ptr -> fx_media_default_path;
163
164 #ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
165
166 /* Setup pointer to the path. */
167 2311 path_string_ptr = media_ptr -> fx_media_default_path.fx_path_string;
168 #endif
169
170 /* Set the internal pointer to the search directory as well. */
171 2311 search_dir_ptr = &(path_ptr -> fx_path_directory);
172 }
173 else
174 {
175
176 /* Setup the path pointer to the global media path. */
177 1159 path_ptr = &media_ptr -> fx_media_default_path;
178
179 /* The current default directory is the root so just set the
180 search directory pointer to NULL. */
181 1159 search_dir_ptr = FX_NULL;
182 }
183
184 /* Calculate the directory size. */
185
4/4
✓ Branch 7 → 8 taken 1726 times.
✓ Branch 7 → 21 taken 764 times.
✓ Branch 12 → 13 taken 13242 times.
✓ Branch 12 → 28 taken 1264 times.
16996 if (search_dir_ptr)
186 {
187 /* Determine the directory size. */
188
4/4
✓ Branch 8 → 9 taken 1330 times.
✓ Branch 8 → 10 taken 396 times.
✓ Branch 13 → 14 taken 9886 times.
✓ Branch 13 → 15 taken 3356 times.
14968 if (path_ptr -> fx_path_current_entry != 0)
189 {
190
191 /* Pickup the previously saved directory size. */
192 11216 directory_size = search_dir_ptr -> fx_dir_entry_file_size;
193 }
194 else
195 {
196
197 /* This should only be done on the first time into next directory find. */
198
199 /* Ensure that the search directory's last search cluster is cleared. */
200 3752 search_dir_ptr -> fx_dir_entry_last_search_cluster = 0;
201
202 /* Calculate the directory size by counting the allocated
203 clusters for it. */
204 3752 i = 0;
205 3752 cluster = search_dir_ptr -> fx_dir_entry_cluster;
206
4/4
✓ Branch 19 → 11 taken 624 times.
✓ Branch 19 → 20 taken 380 times.
✓ Branch 26 → 16 taken 4081 times.
✓ Branch 26 → 27 taken 3336 times.
8421 while (cluster < media_ptr -> fx_media_fat_reserved)
207 {
208
209 /* Increment the cluster count. */
210 4705 i++;
211
212 /* Read the next FAT entry. */
213 4705 status = _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
214
215 /* Check the return status. */
216
4/4
✓ Branch 12 → 13 taken 4 times.
✓ Branch 12 → 14 taken 620 times.
✓ Branch 17 → 18 taken 5 times.
✓ Branch 17 → 20 taken 4076 times.
4705 if (status != FX_SUCCESS)
217 {
218
219 /* Release media protection. */
220 5 FX_UNPROTECT
221
222 /* Return the bad status. */
223 9 return(status);
224 }
225
226
12/12
✓ Branch 14 → 15 taken 616 times.
✓ Branch 14 → 17 taken 4 times.
✓ Branch 15 → 16 taken 612 times.
✓ Branch 15 → 17 taken 4 times.
✓ Branch 16 → 17 taken 4 times.
✓ Branch 16 → 18 taken 608 times.
✓ Branch 20 → 21 taken 4071 times.
✓ Branch 20 → 23 taken 5 times.
✓ Branch 21 → 22 taken 4066 times.
✓ Branch 21 → 23 taken 5 times.
✓ Branch 22 → 23 taken 5 times.
✓ Branch 22 → 25 taken 4061 times.
4696 if ((cluster < FX_FAT_ENTRY_START) || (cluster == next_cluster) || (i > media_ptr -> fx_media_total_clusters))
227 {
228
229 /* Release media protection. */
230 15 FX_UNPROTECT
231
232 /* Return the bad status. */
233 27 return(FX_FAT_READ_ERROR);
234 }
235
236 4669 cluster = next_cluster;
237 }
238
239 /* Now we can calculate the directory size. */
240 3716 directory_size = (((ULONG64)media_ptr -> fx_media_bytes_per_sector) *
241 3716 ((ULONG64)media_ptr -> fx_media_sectors_per_cluster) * i) /
242 (ULONG64)FX_DIR_ENTRY_SIZE;
243
244 /* Save how many entries there are in the directory. */
245 3716 search_dir_ptr -> fx_dir_entry_file_size = directory_size;
246 }
247 }
248 else
249 {
250
251 /* Directory size is the number of entries in the root directory. */
252 2028 directory_size = (ULONG)media_ptr -> fx_media_root_directory_entries;
253 }
254
255 /* Preset status with an error return. */
256 16960 status = FX_NO_MORE_ENTRIES;
257
258 /* Determine if the current entry is inside of the directory's range. */
259
4/4
✓ Branch 56 → 23 taken 2514 times.
✓ Branch 56 → 57 taken 4 times.
✓ Branch 64 → 30 taken 14554 times.
✓ Branch 64 → 65 taken 5 times.
17077 while (path_ptr -> fx_path_current_entry < directory_size)
260 {
261
262 /* Read an entry from the directory. */
263 17068 temp_status = _fx_directory_entry_read(media_ptr, search_dir_ptr,
264 &(path_ptr -> fx_path_current_entry), &entry);
265
266 /* Check for error status. */
267
4/4
✓ Branch 24 → 25 taken 40 times.
✓ Branch 24 → 26 taken 2474 times.
✓ Branch 31 → 32 taken 50 times.
✓ Branch 31 → 34 taken 14504 times.
17068 if (temp_status != FX_SUCCESS)
268 {
269
270 /* Release media protection. */
271 50 FX_UNPROTECT
272
273 /* Return error status. */
274 90 return(temp_status);
275 }
276
277 /* Check to see if the entry has something in it. */
278
8/8
✓ Branch 26 → 27 taken 48 times.
✓ Branch 26 → 29 taken 2426 times.
✓ Branch 27 → 28 taken 44 times.
✓ Branch 27 → 29 taken 4 times.
✓ Branch 34 → 35 taken 78 times.
✓ Branch 34 → 37 taken 14426 times.
✓ Branch 35 → 36 taken 73 times.
✓ Branch 35 → 37 taken 5 times.
16978 if (((UCHAR)entry.fx_dir_entry_name[0] == (UCHAR)FX_DIR_ENTRY_FREE) && (entry.fx_dir_entry_short_name[0] == 0))
279 {
280
281 /* Current entry is free, skip to next entry and continue the loop. */
282 117 path_ptr -> fx_path_current_entry++;
283 117 continue;
284 }
285
4/4
✓ Branch 29 → 30 taken 2124 times.
✓ Branch 29 → 55 taken 306 times.
✓ Branch 37 → 38 taken 10958 times.
✓ Branch 37 → 63 taken 3473 times.
16861 else if ((UCHAR)entry.fx_dir_entry_name[0] != (UCHAR)FX_DIR_ENTRY_DONE)
286 {
287
288 /* A valid directory entry is present. */
289
290 /* Copy the name into the destination. */
291
4/4
✓ Branch 32 → 31 taken 10394 times.
✓ Branch 32 → 33 taken 2124 times.
✓ Branch 40 → 39 taken 43872 times.
✓ Branch 40 → 41 taken 10958 times.
67348 for (i = 0; entry.fx_dir_entry_name[i]; i++)
292 {
293
294 54266 *directory_name = entry.fx_dir_entry_name[i];
295 54266 directory_name++;
296 }
297
298 /* Place a NULL at the end of the directory name. */
299 13082 *directory_name = (CHAR)0;
300
301 /* Increment the current entry for the media. */
302 13082 path_ptr -> fx_path_current_entry++;
303
304 #ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
305 {
306 UINT v, j;
307
308
309 /* If a subsequent search for the same name is done, it will find it immediately. */
310
311 /* Set the index of the saved name string. */
312 13082 v = 0;
313
314 /* First, build the full path and name. */
315
4/4
✓ Branch 33 → 34 taken 1404 times.
✓ Branch 33 → 38 taken 720 times.
✓ Branch 41 → 42 taken 9896 times.
✓ Branch 41 → 46 taken 1062 times.
13082 if (path_string_ptr)
316 {
317
318 /* Copy the path into the destination. */
319
8/8
✓ Branch 36 → 37 taken 15840 times.
✓ Branch 36 → 38 taken 24 times.
✓ Branch 37 → 35 taken 14460 times.
✓ Branch 37 → 38 taken 1380 times.
✓ Branch 44 → 45 taken 113162 times.
✓ Branch 44 → 46 taken 74 times.
✓ Branch 45 → 43 taken 103340 times.
✓ Branch 45 → 46 taken 9822 times.
129100 while ((v < (FX_MAX_LAST_NAME_LEN - 1)) && (path_string_ptr[v]))
320 {
321
322 /* Copy one character. */
323 117800 media_ptr -> fx_media_last_found_name[v] = path_string_ptr[v];
324
325 /* Move to next character. */
326 117800 v++;
327 }
328 }
329
330 /* We know there is room at this point, place a directory separator character. */
331 13082 media_ptr -> fx_media_last_found_name[v++] = '/';
332
333 /* Now append the name to the path. */
334 13082 j = 0;
335
8/8
✓ Branch 40 → 41 taken 12374 times.
✓ Branch 40 → 42 taken 28 times.
✓ Branch 41 → 39 taken 10278 times.
✓ Branch 41 → 42 taken 2096 times.
✓ Branch 48 → 49 taken 54486 times.
✓ Branch 48 → 50 taken 97 times.
✓ Branch 49 → 47 taken 43625 times.
✓ Branch 49 → 50 taken 10861 times.
66985 while ((v < FX_MAX_LAST_NAME_LEN) && (entry.fx_dir_entry_name[j]))
336 {
337
338 /* Copy one character. */
339 53903 media_ptr -> fx_media_last_found_name[v] = entry.fx_dir_entry_name[j];
340
341 /* Move to next character. */
342 53903 v++;
343 53903 j++;
344 }
345
346 /* Null terminate the last name string. */
347
4/4
✓ Branch 42 → 43 taken 2096 times.
✓ Branch 42 → 44 taken 28 times.
✓ Branch 50 → 51 taken 10861 times.
✓ Branch 50 → 52 taken 97 times.
13082 if (v < FX_MAX_LAST_NAME_LEN)
348 {
349
350 /* Null terminate. */
351 12957 media_ptr -> fx_media_last_found_name[v] = FX_NULL;
352 }
353 else
354 {
355
356 /* The string is too big, NULL the string so it won't be used in searching. */
357 125 media_ptr -> fx_media_last_found_name[0] = FX_NULL;
358 }
359
360 /* Determine if there is a search pointer. */
361
4/4
✓ Branch 45 → 46 taken 1404 times.
✓ Branch 45 → 47 taken 720 times.
✓ Branch 53 → 54 taken 9896 times.
✓ Branch 53 → 55 taken 1062 times.
13082 if (search_dir_ptr)
362 {
363
364 /* Yes, there is a search directory pointer so save it! */
365 11300 media_ptr -> fx_media_last_found_directory = *search_dir_ptr;
366
367 /* Indicate the search directory is valid. */
368 11300 media_ptr -> fx_media_last_found_directory_valid = FX_TRUE;
369 }
370 else
371 {
372
373 /* Indicate the search directory is not valid. */
374 1782 media_ptr -> fx_media_last_found_directory_valid = FX_FALSE;
375 }
376
377 /* Copy the directory entry. */
378 13082 media_ptr -> fx_media_last_found_entry = entry;
379
380 /* Setup the last found directory entry to point at the last found internal file name. */
381 13082 media_ptr -> fx_media_last_found_entry.fx_dir_entry_name = media_ptr -> fx_media_last_found_file_name;
382
383 /* Copy the actual directory name into the cached directory name. */
384
4/4
✓ Branch 53 → 49 taken 18542 times.
✓ Branch 53 → 54 taken 28 times.
✓ Branch 61 → 57 taken 73530 times.
✓ Branch 61 → 62 taken 101 times.
92201 for (index = 0; index < FX_MAX_LONG_NAME_LEN; index++)
385 {
386
387 /* Copy character into the cached directory name. */
388 92072 media_ptr -> fx_media_last_found_file_name[index] = entry.fx_dir_entry_name[index];
389
390 /* See if we have copied the NULL termination character. */
391
4/4
✓ Branch 49 → 50 taken 2316 times.
✓ Branch 49 → 52 taken 16226 times.
✓ Branch 57 → 58 taken 11290 times.
✓ Branch 57 → 60 taken 62240 times.
92072 if (entry.fx_dir_entry_name[index] == (CHAR)FX_NULL)
392 {
393
394 /* Check to see if we use the break to get out of the loop. */
395
4/4
✓ Branch 50 → 51 taken 2096 times.
✓ Branch 50 → 52 taken 220 times.
✓ Branch 58 → 59 taken 10857 times.
✓ Branch 58 → 60 taken 433 times.
13606 if (v < (FX_MAX_LONG_NAME_LEN - 1))
396 {
397
398 /* Yes, not at the end of the string, break. */
399 12953 break;
400 }
401 }
402 }
403 }
404 #endif
405
406 /* Set return status to success. */
407 13082 status = FX_SUCCESS;
408
409 /* Get out of the loop. */
410 13082 break;
411 }
412 else
413 {
414
415 /* Set the error code. */
416 3779 status = FX_NO_MORE_ENTRIES;
417
418 /* Get out of the loop. */
419 3779 break;
420 }
421 }
422
423 /* Release media protection. */
424 14436 FX_UNPROTECT
425
426 /* Return status to the caller. */
427 16870 return(status);
428 }
429
430