GCC Code Coverage Report


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

fx_directory_local_path_set.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_file.h"
31 #include "fx_utility.h"
32 #include "fx_directory.h"
33
34 #ifndef FX_NO_LOCAL_PATH
35 FX_LOCAL_PATH_SETUP
36 #endif
37
38 /**************************************************************************/
39 /* */
40 /* FUNCTION RELEASE */
41 /* */
42 /* _fx_directory_local_path_set PORTABLE C */
43 /* 6.1.5 */
44 /* AUTHOR */
45 /* */
46 /* William E. Lamie, Microsoft Corporation */
47 /* */
48 /* DESCRIPTION */
49 /* */
50 /* This function sets the local default directory of the media to the */
51 /* path specified by the caller. If this path is not found, an error */
52 /* code is returned. */
53 /* */
54 /* INPUT */
55 /* */
56 /* media_ptr Media control block pointer */
57 /* local_path Local path control block ptr */
58 /* new_path_name New path to set current local */
59 /* working directory to */
60 /* */
61 /* OUTPUT */
62 /* */
63 /* return status */
64 /* */
65 /* CALLS */
66 /* */
67 /* _fx_directory_search Search for the directory name */
68 /* in the directory structure */
69 /* */
70 /* CALLED BY */
71 /* */
72 /* Application Code */
73 /* */
74 /**************************************************************************/
75 4329 UINT _fx_directory_local_path_set(FX_MEDIA *media_ptr, FX_LOCAL_PATH *local_path_ptr, CHAR *new_path_name)
76 {
77
78 #ifndef FX_NO_LOCAL_PATH
79 UINT status;
80 CHAR *path_string_ptr;
81 UINT path_string_capacity;
82 FX_PATH *path_ptr;
83 UINT i, j;
84 #endif
85 FX_DIR_ENTRY dir_entry;
86
87
88 #ifndef FX_MEDIA_STATISTICS_DISABLE
89
90 /* Increment the number of times this service has been called. */
91 4329 media_ptr -> fx_media_directory_local_path_sets++;
92 #endif
93
94 /* Setup pointer to a name buffer. */
95 4329 dir_entry.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
96
97 /* Setup the local path name buffer pointer. */
98 4329 local_path_ptr -> fx_path_directory.fx_dir_entry_name = local_path_ptr -> fx_path_name_buffer;
99
100 /* Clear the short name string. */
101 4329 dir_entry.fx_dir_entry_short_name[0] = (CHAR)0;
102
103 /* Clear the long name string. */
104 4329 dir_entry.fx_dir_entry_name[0] = (CHAR)0;
105
106 /* Check the media to make sure it is open. */
107
2/2
✓ Branch 2 → 3 taken 5 times.
✓ Branch 2 → 4 taken 4324 times.
4329 if (media_ptr -> fx_media_id != FX_MEDIA_ID)
108 {
109
110 /* Return the media not opened error. */
111 5 return(FX_MEDIA_NOT_OPEN);
112 }
113
114 #ifdef FX_NO_LOCAL_PATH
115
116 FX_PARAMETER_NOT_USED(new_path_name);
117
118 /* Error, return to caller. */
119 8 return(FX_NOT_IMPLEMENTED);
120 #else
121
122 /* If trace is enabled, insert this event into the trace buffer. */
123 FX_TRACE_IN_LINE_INSERT(FX_TRACE_DIRECTORY_LOCAL_PATH_SET, media_ptr, local_path_ptr, new_path_name, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
124
125 /* Protect against other threads accessing the media. */
126 4316 FX_PROTECT
127
128 /* Look for a root directory selection. */
129
8/8
✓ Branch 5 → 6 taken 4311 times.
✓ Branch 5 → 9 taken 5 times.
✓ Branch 6 → 7 taken 4105 times.
✓ Branch 6 → 8 taken 206 times.
✓ Branch 7 → 8 taken 231 times.
✓ Branch 7 → 10 taken 3874 times.
✓ Branch 8 → 9 taken 218 times.
✓ Branch 8 → 10 taken 219 times.
4316 if ((!new_path_name) || (((new_path_name[0] == '\\') || (new_path_name[0] == '/')) && (new_path_name[1] == (CHAR)0)))
130 {
131
132 /* Set the default local directory to the root. */
133 223 local_path_ptr -> fx_path_directory.fx_dir_entry_name[0] = (CHAR)0;
134 223 local_path_ptr -> fx_path_string[0] = (CHAR)0;
135 223 local_path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] = (CHAR)0;
136
137 /* Setup thread control block to use this local path pointer. */
138 223 _tx_thread_current_ptr -> tx_thread_filex_ptr = (VOID *)local_path_ptr;
139 }
140 else
141 {
142
143 /* Search the system for the supplied path and directory name. */
144 4093 status = _fx_directory_search(media_ptr, new_path_name, &dir_entry, FX_NULL, FX_NULL);
145
146 /* Determine if the search failed or if the entry found is not a
147 directory. */
148
4/4
✓ Branch 11 → 12 taken 4063 times.
✓ Branch 11 → 13 taken 30 times.
✓ Branch 12 → 13 taken 5 times.
✓ Branch 12 → 15 taken 4058 times.
4093 if ((status != FX_SUCCESS) || (!(dir_entry.fx_dir_entry_attributes & FX_DIRECTORY)))
149 {
150
151 /* Release media protection. */
152 35 FX_UNPROTECT
153
154 /* Invalid Path - Return the error code. */
155 35 return(FX_INVALID_PATH);
156 }
157
158 /* Now update the current path string. */
159
160 /* Setup the path string pointer to the start of the current path. */
161 4058 path_string_ptr = &(local_path_ptr -> fx_path_string[0]);
162
163 /* Setup the path string's capacity. */
164 4058 path_string_capacity = FX_MAXIMUM_PATH - 1;
165
166 /* Determine if the new path is relative from the current path. */
167
4/4
✓ Branch 15 → 16 taken 4053 times.
✓ Branch 15 → 47 taken 5 times.
✓ Branch 16 → 17 taken 3844 times.
✓ Branch 16 → 47 taken 209 times.
4058 if ((new_path_name[0] != '\\') && (new_path_name[0] != '/'))
168 {
169
170 /* Yes, a relative path was found. */
171
172 /* Setup the default path pointer to the local path. */
173 3844 path_ptr = local_path_ptr;
174
175 /* Determine if the local path is different than the current local path. */
176
2/2
✓ Branch 17 → 18 taken 3347 times.
✓ Branch 17 → 32 taken 497 times.
3844 if (local_path_ptr != (FX_LOCAL_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr)
177 {
178
179 /* Yes, there is a difference. */
180
181 /* Should we copy from the default media path or from the previous default
182 path. */
183
2/2
✓ Branch 18 → 19 taken 3286 times.
✓ Branch 18 → 26 taken 61 times.
3347 if (_tx_thread_current_ptr -> tx_thread_filex_ptr)
184 {
185
186 /* There is a local path so copy the relative path info from it. */
187 3286 i = 0;
188 do
189 {
190
191 /* Copy from previous local to new local path. */
192 18877 local_path_ptr -> fx_path_string[i] =
193 18877 ((FX_LOCAL_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr) -> fx_path_string[i];
194
195 /* Determine if we are done. */
196
2/2
✓ Branch 20 → 21 taken 3286 times.
✓ Branch 20 → 23 taken 15591 times.
18877 if (local_path_ptr -> fx_path_string[i] == 0)
197 {
198
199 /* Are we not at the end of the string? */
200
2/2
✓ Branch 21 → 22 taken 3281 times.
✓ Branch 21 → 23 taken 5 times.
3286 if (i < (FX_MAXIMUM_PATH - 1))
201 {
202
203 /* Yes, break the loop. */
204 3281 break;
205 }
206 }
207
208 /* Move to the next character. */
209 15596 i++;
210
211
2/2
✓ Branch 23 → 24 taken 15591 times.
✓ Branch 23 → 25 taken 5 times.
15596 } while (i < FX_MAXIMUM_PATH);
212 }
213 else
214 {
215
216 /* No local path, so copy the relative path information from the media
217 default. */
218 61 i = 0;
219 do
220 {
221
222 /* Copy from the media default to new local path. */
223 1336 local_path_ptr -> fx_path_string[i] =
224 1336 media_ptr -> fx_media_default_path.fx_path_string[i];
225
226 /* Determine if we are done. */
227
2/2
✓ Branch 27 → 28 taken 61 times.
✓ Branch 27 → 30 taken 1275 times.
1336 if (local_path_ptr -> fx_path_string[i] == 0)
228 {
229
230 /* Are we not at the end of the string? */
231
2/2
✓ Branch 28 → 29 taken 56 times.
✓ Branch 28 → 30 taken 5 times.
61 if (i < (FX_MAXIMUM_PATH - 1))
232 {
233
234 /* Yes, break the loop. */
235 56 break;
236 }
237 }
238
239 /* Move to the next character. */
240 1280 i++;
241
242
2/2
✓ Branch 30 → 31 taken 1275 times.
✓ Branch 30 → 32 taken 5 times.
1280 } while (i < FX_MAXIMUM_PATH);
243 }
244 }
245
246 /* First, check the current path for string overflow. If this is set,
247 don't attempt to update the current path with relative information.
248 The path won't be valid again until a complete path is given. */
249
2/2
✓ Branch 32 → 33 taken 235 times.
✓ Branch 32 → 40 taken 3609 times.
3844 if (path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] == '*')
250 {
251
252 /* Yes, don't update the string, just finish the path set processing. */
253
254 /* Determine if we are at the root directory. */
255
2/2
✓ Branch 33 → 34 taken 20 times.
✓ Branch 33 → 35 taken 215 times.
235 if (!dir_entry.fx_dir_entry_cluster)
256 {
257 /* Set the current directory back to the root directory. */
258 20 dir_entry.fx_dir_entry_name[0] = (CHAR)0;
259
260 /* Clear the current path string. */
261 20 path_ptr -> fx_path_string[0] = (CHAR)0;
262
263 /* Clear the overflow flag in the current path string... just in
264 case! */
265 20 path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] = (CHAR)0;
266 }
267
268 /* Copy the new directory entry into the media control block. */
269 235 path_ptr -> fx_path_directory = dir_entry;
270
271 /* Reset the local path name buffer pointer, since it was clobbered earlier. */
272 235 local_path_ptr -> fx_path_directory.fx_dir_entry_name = local_path_ptr -> fx_path_name_buffer;
273
274 /* Copy the directory name entry to the local path name area. */
275
2/2
✓ Branch 37 → 36 taken 60160 times.
✓ Branch 37 → 38 taken 235 times.
60395 for (j = 0; j < FX_MAX_LONG_NAME_LEN; j++)
276 {
277
278 /* Copy the name buffer. */
279 60160 local_path_ptr -> fx_path_directory.fx_dir_entry_name[j] = dir_entry.fx_dir_entry_name[j];
280 }
281
282 /* Setup thread control block to use this local path pointer. */
283 235 _tx_thread_current_ptr -> tx_thread_filex_ptr = (VOID *)local_path_ptr;
284
285 /* Release media protection. */
286 235 FX_UNPROTECT
287
288 /* Default directory set is complete, return status. */
289 235 return(FX_SUCCESS);
290 }
291
292 /* Move the current path starting pointer to the end of the current
293 path string. */
294
4/4
✓ Branch 42 → 43 taken 47650 times.
✓ Branch 42 → 44 taken 5 times.
✓ Branch 43 → 41 taken 44046 times.
✓ Branch 43 → 44 taken 3604 times.
47655 while ((path_string_capacity) && (*path_string_ptr != FX_NULL))
295 {
296 44046 path_string_ptr++;
297 44046 path_string_capacity--;
298 }
299
300 /* If room, place the \ character in the path string. */
301
2/2
✓ Branch 44 → 45 taken 3604 times.
✓ Branch 44 → 46 taken 5 times.
3609 if (path_string_capacity)
302 {
303
304 /* There is room, place the directory marker in the string. */
305 3604 *path_string_ptr++ = '\\';
306 3604 path_string_capacity--;
307 }
308 }
309 else
310 {
311
312 /* Setup the default path pointer. */
313
314 /* Setup the default path pointer to the local path. */
315 214 path_ptr = local_path_ptr;
316
317 /* Complete path name given. Check to see if we need to clear an
318 overflow character from a previous current path string update. */
319
2/2
✓ Branch 47 → 48 taken 5 times.
✓ Branch 47 → 49 taken 209 times.
214 if (path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] == '*')
320 {
321 5 path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] = (CHAR)0;
322 }
323 }
324
325 /* Copy what we can into the current path. */
326
2/2
✓ Branch 62 → 50 taken 27459 times.
✓ Branch 62 → 63 taken 3780 times.
31239 while (*new_path_name)
327 {
328
329 /* Determine if there is a ".." character sequence that specifies the
330 previous path. */
331
4/4
✓ Branch 50 → 51 taken 35 times.
✓ Branch 50 → 58 taken 27424 times.
✓ Branch 51 → 52 taken 30 times.
✓ Branch 51 → 58 taken 5 times.
27459 if ((*new_path_name == '.') && (*(new_path_name + 1) == '.'))
332 {
333
334 /* Yes, a backward path is found. The current path pointer
335 must be moved back to just after the previous \ character. */
336
337 /* Skip the current \0 that is at the end of the current path. */
338 30 path_string_capacity = path_string_capacity + 2;
339 30 path_string_ptr = path_string_ptr - 2;
340
341
2/2
✓ Branch 56 → 53 taken 535 times.
✓ Branch 56 → 57 taken 10 times.
545 while (path_string_capacity <= (FX_MAXIMUM_PATH - 1))
342 {
343
344 /* Move the current path pointer backwards until
345 a \ character is found. */
346
347
4/4
✓ Branch 53 → 54 taken 520 times.
✓ Branch 53 → 57 taken 15 times.
✓ Branch 54 → 55 taken 515 times.
✓ Branch 54 → 57 taken 5 times.
535 if ((*path_string_ptr == '\\') || (*path_string_ptr == '/'))
348 {
349
350 /* Yes, we have successfully backed up one directory. */
351 break;
352 }
353
354 /* Backup another character. */
355 515 path_string_capacity++;
356 515 path_string_ptr--;
357 }
358
359 /* Adjust the new directory pointer past the .. characters */
360 30 new_path_name = new_path_name + 2;
361 }
362 else
363 {
364
365 /* Normal characters that need to be copied into the current path. */
366
367
2/2
✓ Branch 58 → 59 taken 27386 times.
✓ Branch 58 → 60 taken 43 times.
27429 if (path_string_capacity)
368 {
369
370 /* Copy character from the new path into the current path string. */
371 27386 *path_string_ptr++ = *new_path_name++;
372
373 27386 path_string_capacity--;
374 }
375 else
376 {
377
378 /* No more room in the current path string! */
379 43 break;
380 }
381 }
382 }
383
384 /* Determine if there is still room in the current path string. */
385
2/2
✓ Branch 63 → 64 taken 3766 times.
✓ Branch 63 → 65 taken 57 times.
3823 if (path_string_capacity)
386 {
387
388 /* Yes, there is still room, place a NULL character at the
389 end of the path. */
390 3766 *path_string_ptr = (CHAR)FX_NULL;
391 }
392 else
393 {
394
395 /* No more room. Determine if the entire path was successfully
396 copied into the current path. */
397
2/2
✓ Branch 65 → 66 taken 43 times.
✓ Branch 65 → 67 taken 14 times.
57 if (*new_path_name)
398 {
399
400 /* No, we couldn't fit the entire path. Place a "*" character
401 at the end to indicate that we had overflow. Note that
402 the path is kept just the the directory default get call, so
403 the new default path is valid. */
404 43 path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] = '*';
405 }
406 }
407
408 /* Determine if we are at the root directory. */
409
2/2
✓ Branch 67 → 68 taken 15 times.
✓ Branch 67 → 69 taken 3808 times.
3823 if (!dir_entry.fx_dir_entry_cluster)
410 {
411 /* Set the current directory back to the root directory. */
412 15 dir_entry.fx_dir_entry_name[0] = (CHAR)0;
413 15 local_path_ptr -> fx_path_name_buffer[0] = (CHAR)0;
414 }
415
416 /* Copy the new directory entry into the media control block. */
417 3823 path_ptr -> fx_path_directory = dir_entry;
418
419 /* Reset the local path name buffer pointer, since it was clobbered earlier. */
420 3823 local_path_ptr -> fx_path_directory.fx_dir_entry_name = local_path_ptr -> fx_path_name_buffer;
421
422 /* Copy the directory name entry to the local path name area. */
423
2/2
✓ Branch 71 → 70 taken 978688 times.
✓ Branch 71 → 72 taken 3823 times.
982511 for (j = 0; j < FX_MAX_LONG_NAME_LEN; j++)
424 {
425
426 /* Copy the name buffer. */
427 978688 local_path_ptr -> fx_path_directory.fx_dir_entry_name[j] = dir_entry.fx_dir_entry_name[j];
428 }
429
430 /* Setup thread control block to use this local path pointer. */
431 3823 _tx_thread_current_ptr -> tx_thread_filex_ptr = (VOID *)local_path_ptr;
432 }
433
434 /* Release media protection. */
435 4046 FX_UNPROTECT
436
437 /* Default directory set is complete, return status. */
438 4046 return(FX_SUCCESS);
439 #endif
440 }
441
442