GCC Code Coverage Report


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

fx_directory_rename.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_rename 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 rename request is valid and the directory will be */
52 /* changed to the new name. Otherwise, if the directory is not found, */
53 /* the appropriate error code is returned to the caller. */
54 /* */
55 /* INPUT */
56 /* */
57 /* media_ptr Media control block pointer */
58 /* old_directory_name Old file directory pointer */
59 /* new_directory_name New file directory pointer */
60 /* */
61 /* OUTPUT */
62 /* */
63 /* return status */
64 /* */
65 /* CALLS */
66 /* */
67 /* _fx_directory_entry_write Write the new directory entry */
68 /* _fx_directory_free_search Search for a free directory */
69 /* entry */
70 /* _fx_directory_name_extract Extract directory name */
71 /* _fx_directory_search Search for the file name in */
72 /* the directory structure */
73 /* _fx_fault_tolerant_transaction_start Start fault tolerant */
74 /* transaction */
75 /* _fx_fault_tolerant_transaction_end End fault tolerant transaction*/
76 /* _fx_fault_tolerant_recover Recover FAT chain */
77 /* _fx_fault_tolerant_reset_log_file Reset the log file */
78 /* */
79 /* CALLED BY */
80 /* */
81 /* Application Code */
82 /* */
83 /**************************************************************************/
84 864 UINT _fx_directory_rename(FX_MEDIA *media_ptr, CHAR *old_directory_name, CHAR *new_directory_name)
85 {
86
87 UINT status;
88 FX_DIR_ENTRY old_dir_entry;
89 FX_DIR_ENTRY new_dir_entry;
90 FX_DIR_ENTRY search_directory;
91 CHAR *new_name_ptr;
92 ULONG i;
93 CHAR *work_ptr;
94 CHAR alpha, beta;
95 #ifdef FX_RENAME_PATH_INHERIT
96 UINT j;
97 #endif
98
99
100 #ifndef FX_MEDIA_STATISTICS_DISABLE
101
102 /* Increment the number of times this service has been called. */
103 864 media_ptr -> fx_media_directory_renames++;
104 #endif
105
106 /* Setup pointers to media name buffers. */
107 864 old_dir_entry.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
108 864 new_dir_entry.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN * 2;
109 864 search_directory.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN * 3;
110
111 /* Clear the short name strings. */
112 864 old_dir_entry.fx_dir_entry_short_name[0] = 0;
113 864 new_dir_entry.fx_dir_entry_short_name[0] = 0;
114 864 search_directory.fx_dir_entry_short_name[0] = 0;
115
116 /* Determine if the supplied name is less than the maximum supported name size. The
117 maximum name (FX_MAX_LONG_NAME_LEN) is defined in fx_api.h. */
118 864 i = 0;
119 864 work_ptr = (CHAR *)new_directory_name;
120
4/4
✓ Branch 10 → 11 taken 19916 times.
✓ Branch 10 → 12 taken 855 times.
✓ Branch 11 → 3 taken 19907 times.
✓ Branch 11 → 12 taken 9 times.
20771 while (*work_ptr && (i < FX_MAX_LONG_NAME_LEN))
121 {
122
123 /* Determine if the character designates a new path. */
124
4/4
✓ Branch 3 → 4 taken 19898 times.
✓ Branch 3 → 5 taken 9 times.
✓ Branch 4 → 5 taken 175 times.
✓ Branch 4 → 6 taken 19723 times.
19907 if ((*work_ptr == '\\') || (*work_ptr == '/'))
125 {
126 /* Yes, reset the name size. */
127 184 i = 0;
128 }
129 /* Check for leading spaces. */
130
4/4
✓ Branch 6 → 7 taken 81 times.
✓ Branch 6 → 8 taken 19642 times.
✓ Branch 7 → 8 taken 36 times.
✓ Branch 7 → 9 taken 45 times.
19723 else if ((*work_ptr != ' ') || (i != 0))
131 {
132
133 /* No leading spaces, increment the name size. */
134 19678 i++;
135 }
136
137 /* Move to the next character. */
138 19907 work_ptr++;
139 }
140
141 /* Determine if the supplied name is valid. */
142
4/4
✓ Branch 12 → 13 taken 855 times.
✓ Branch 12 → 14 taken 9 times.
✓ Branch 13 → 14 taken 18 times.
✓ Branch 13 → 15 taken 837 times.
864 if ((i == 0) || (i >= FX_MAX_LONG_NAME_LEN))
143 {
144
145 /* Return an invalid name value. */
146 27 return(FX_INVALID_NAME);
147 }
148
149 /* Check the media to make sure it is open. */
150
2/2
✓ Branch 15 → 16 taken 9 times.
✓ Branch 15 → 17 taken 828 times.
837 if (media_ptr -> fx_media_id != FX_MEDIA_ID)
151 {
152
153 /* Return the media not opened error. */
154 9 return(FX_MEDIA_NOT_OPEN);
155 }
156
157 /* If trace is enabled, insert this event into the trace buffer. */
158 FX_TRACE_IN_LINE_INSERT(FX_TRACE_DIRECTORY_RENAME, media_ptr, old_directory_name, new_directory_name, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
159
160 /* Protect against other threads accessing the media. */
161 456 FX_PROTECT
162
163 #ifdef FX_ENABLE_FAULT_TOLERANT
164 /* Start transaction. */
165 408 _fx_fault_tolerant_transaction_start(media_ptr);
166 #endif /* FX_ENABLE_FAULT_TOLERANT */
167
168 /* Check for write protect at the media level (set by driver). */
169
6/6
✓ Branch 17 → 18 taken 2 times.
✓ Branch 17 → 19 taken 166 times.
✓ Branch 18 → 19 taken 5 times.
✓ Branch 18 → 21 taken 451 times.
✓ Branch 19 → 20 taken 2 times.
✓ Branch 19 → 23 taken 202 times.
828 if (media_ptr -> fx_media_driver_write_protect)
170 {
171
172 #ifdef FX_ENABLE_FAULT_TOLERANT
173 4 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
174 #endif /* FX_ENABLE_FAULT_TOLERANT */
175
176 /* Release media protection. */
177 5 FX_UNPROTECT
178
179 /* Return write protect error. */
180 9 return(FX_WRITE_PROTECT);
181 }
182
183 /* Search the system for the supplied directory name. */
184 819 status = _fx_directory_search(media_ptr, old_directory_name, &old_dir_entry, &search_directory, FX_NULL);
185
186 /* Determine if the search was successful. */
187
6/6
✓ Branch 20 → 21 taken 2 times.
✓ Branch 20 → 22 taken 164 times.
✓ Branch 22 → 23 taken 7 times.
✓ Branch 22 → 25 taken 444 times.
✓ Branch 24 → 25 taken 4 times.
✓ Branch 24 → 28 taken 198 times.
819 if (status != FX_SUCCESS)
188 {
189
190 #ifdef FX_ENABLE_FAULT_TOLERANT
191 8 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
192 #endif /* FX_ENABLE_FAULT_TOLERANT */
193
194 /* Release media protection. */
195 7 FX_UNPROTECT
196
197 /* Return the error code. */
198 13 return(status);
199 }
200
201 /* Check to make sure the found entry is a directory. */
202
6/6
✓ Branch 22 → 23 taken 4 times.
✓ Branch 22 → 24 taken 160 times.
✓ Branch 25 → 26 taken 10 times.
✓ Branch 25 → 28 taken 434 times.
✓ Branch 28 → 29 taken 4 times.
✓ Branch 28 → 32 taken 194 times.
806 if (!(old_dir_entry.fx_dir_entry_attributes & (UCHAR)(FX_DIRECTORY)))
203 {
204
205 #ifdef FX_ENABLE_FAULT_TOLERANT
206 8 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
207 #endif /* FX_ENABLE_FAULT_TOLERANT */
208
209 /* Release media protection. */
210 10 FX_UNPROTECT
211
212 /* Return the not a directory error code. */
213 18 return(FX_NOT_DIRECTORY);
214 }
215
216 #ifdef FX_RENAME_PATH_INHERIT
217
218 /* Determine if the source directory name has a path and the target directory name does not. */
219 if (((old_directory_name[0] == '/') || (old_directory_name[0] == '\\')) && (new_directory_name[0] != '/') && (new_directory_name[0] != '\\'))
220 {
221
222 /* In this case, we need to prepend the path of the old directory name to that of the new directory name. */
223
224 /* Setup pointer to the rename buffer. */
225 work_ptr = (CHAR *)media_ptr -> fx_media_rename_buffer;
226
227 /* First, copy the path of the old directory name. */
228 i = 0;
229 j = 0;
230 while ((old_directory_name[i]) && (i < FX_MAXIMUM_PATH))
231 {
232
233 /* Copy a character into the rename buffer. */
234 *work_ptr++ = old_directory_name[i];
235
236 /* Determine if this character is directory separator. */
237 if ((old_directory_name[i] == '/') || (old_directory_name[i] == '\\'))
238 {
239
240 /* Yes, directory separator has been found - remember the index. */
241 j = i;
242 }
243
244 /* Move to next position in the old directory name. */
245 i++;
246 }
247
248 /* At this point, we have the path stored in the rename buffer. */
249
250 /* Position past the last slash or backslash. */
251 j++;
252
253 /* Reset the working pointer to the position after the last directory separator. */
254 work_ptr = (CHAR *)&(media_ptr -> fx_media_rename_buffer[j]);
255
256 /* Now copy the new directory name into the rename buffer. */
257 i = 0;
258 while ((new_directory_name[i]) && (j < FX_MAXIMUM_PATH))
259 {
260
261 /* Copy a character into the rename buffer. */
262 *work_ptr++ = new_directory_name[i];
263
264 /* Move to next character. */
265 i++;
266 j++;
267 }
268
269 /* Determine if the path was successfully prepended. */
270 if (new_directory_name[i])
271 {
272
273 /* No, there was not enough room in the destination buffer. */
274
275 #ifdef FX_ENABLE_FAULT_TOLERANT
276 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
277 #endif /* FX_ENABLE_FAULT_TOLERANT */
278
279 /* Release media protection. */
280 FX_UNPROTECT
281
282 /* Return the invalid path error code. */
283 return(FX_INVALID_PATH);
284 }
285
286 /* Place a NULL at the end of the string. */
287 *work_ptr = (CHAR)FX_NULL;
288
289 /* At this point, we have successfully prepended the path in the new directory name, override
290 the new directory name so it is used from now on. */
291 new_directory_name = (CHAR *)media_ptr -> fx_media_rename_buffer;
292 }
293 #endif
294
295 /* Search the media for the new directory name - including any supplied path. */
296 788 status = _fx_directory_search(media_ptr, new_directory_name, &new_dir_entry, &search_directory, &new_name_ptr);
297
298 /* Determine if the search found anything. */
299
6/6
✓ Branch 25 → 26 taken 116 times.
✓ Branch 25 → 39 taken 44 times.
✓ Branch 29 → 30 taken 304 times.
✓ Branch 29 → 44 taken 130 times.
✓ Branch 33 → 34 taken 130 times.
✓ Branch 33 → 49 taken 64 times.
788 if (status == FX_SUCCESS)
300 {
301
302 /* Determine if the new name simply has an ASCII case change. If so, simply let the processing
303 continue. */
304 550 i = 0;
305 do
306 {
307
308 /* Pickup an old name and new name character and convert to upper case if necessary. */
309 3479 alpha = old_directory_name[i];
310
12/12
✓ Branch 27 → 28 taken 522 times.
✓ Branch 27 → 30 taken 228 times.
✓ Branch 28 → 29 taken 520 times.
✓ Branch 28 → 30 taken 2 times.
✓ Branch 31 → 32 taken 1305 times.
✓ Branch 31 → 34 taken 622 times.
✓ Branch 32 → 33 taken 1300 times.
✓ Branch 32 → 34 taken 5 times.
✓ Branch 35 → 36 taken 522 times.
✓ Branch 35 → 38 taken 280 times.
✓ Branch 36 → 37 taken 520 times.
✓ Branch 36 → 38 taken 2 times.
3479 if ((alpha >= 'a') && (alpha <= 'z'))
311 {
312
313 /* Lower case, convert to upper case! */
314 2340 alpha = (CHAR)((INT)alpha - 0x20);
315 }
316 3479 beta = new_directory_name[i];
317
12/12
✓ Branch 30 → 31 taken 632 times.
✓ Branch 30 → 33 taken 118 times.
✓ Branch 31 → 32 taken 630 times.
✓ Branch 31 → 33 taken 2 times.
✓ Branch 34 → 35 taken 1594 times.
✓ Branch 34 → 37 taken 333 times.
✓ Branch 35 → 36 taken 1589 times.
✓ Branch 35 → 37 taken 5 times.
✓ Branch 38 → 39 taken 646 times.
✓ Branch 38 → 41 taken 156 times.
✓ Branch 39 → 40 taken 644 times.
✓ Branch 39 → 41 taken 2 times.
3479 if ((beta >= 'a') && (beta <= 'z'))
318 {
319
320 /* Lower case, convert to upper case! */
321 2863 beta = (CHAR)((INT)beta - 0x20);
322 }
323
324 /* Now compare the characters. */
325
12/12
✓ Branch 33 → 34 taken 664 times.
✓ Branch 33 → 37 taken 86 times.
✓ Branch 34 → 35 taken 636 times.
✓ Branch 34 → 37 taken 28 times.
✓ Branch 37 → 38 taken 1710 times.
✓ Branch 37 → 41 taken 217 times.
✓ Branch 38 → 39 taken 1628 times.
✓ Branch 38 → 41 taken 82 times.
✓ Branch 41 → 42 taken 714 times.
✓ Branch 41 → 45 taken 88 times.
✓ Branch 42 → 43 taken 674 times.
✓ Branch 42 → 45 taken 40 times.
3479 if ((alpha != beta) || (alpha == 0))
326 {
327
328 /* Get out of this loop! */
329 break;
330 }
331
332 /* Move to next character. */
333 2938 i++;
334
6/6
✓ Branch 35 → 36 taken 634 times.
✓ Branch 35 → 37 taken 2 times.
✓ Branch 39 → 40 taken 1623 times.
✓ Branch 39 → 41 taken 5 times.
✓ Branch 43 → 44 taken 672 times.
✓ Branch 43 → 45 taken 2 times.
2938 } while (i < (FX_MAXIMUM_PATH-1));
335
336 /* Now determine if the names match. */
337
6/6
✓ Branch 37 → 38 taken 86 times.
✓ Branch 37 → 39 taken 30 times.
✓ Branch 41 → 42 taken 217 times.
✓ Branch 41 → 44 taken 87 times.
✓ Branch 45 → 46 taken 88 times.
✓ Branch 45 → 49 taken 42 times.
550 if (alpha != beta)
338 {
339
340 /* Yes, the directory name already exists in the target location. */
341
342 #ifdef FX_ENABLE_FAULT_TOLERANT
343 176 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
344 #endif /* FX_ENABLE_FAULT_TOLERANT */
345
346 /* Release media protection. */
347 217 FX_UNPROTECT
348
349 /* Return the error code. */
350 391 return(FX_ALREADY_CREATED);
351 }
352 }
353
354 /* Make sure the name is valid. */
355
6/6
✓ Branch 40 → 41 taken 2 times.
✓ Branch 40 → 42 taken 72 times.
✓ Branch 45 → 46 taken 5 times.
✓ Branch 45 → 48 taken 212 times.
✓ Branch 50 → 51 taken 2 times.
✓ Branch 50 → 54 taken 104 times.
397 if (_fx_directory_name_extract(new_name_ptr, &new_dir_entry.fx_dir_entry_name[0]))
356 {
357
358 #ifdef FX_ENABLE_FAULT_TOLERANT
359 4 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
360 #endif /* FX_ENABLE_FAULT_TOLERANT */
361
362 /* Release media protection */
363 5 FX_UNPROTECT
364
365 /* Return the error code */
366 9 return(FX_INVALID_NAME);
367 }
368
369 /* Look for a free slot in the target directory. */
370 388 status = _fx_directory_free_search(media_ptr, &search_directory, &new_dir_entry);
371
372 /* Was a free slot found? */
373
6/6
✓ Branch 43 → 44 taken 4 times.
✓ Branch 43 → 45 taken 68 times.
✓ Branch 49 → 50 taken 10 times.
✓ Branch 49 → 52 taken 202 times.
✓ Branch 55 → 56 taken 2 times.
✓ Branch 55 → 59 taken 102 times.
388 if (status != FX_SUCCESS)
374 {
375
376 #ifdef FX_ENABLE_FAULT_TOLERANT
377 6 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
378 #endif /* FX_ENABLE_FAULT_TOLERANT */
379
380 /* No, release protection. */
381 8 FX_UNPROTECT
382
383 /* Return the error code. */
384 16 return(status);
385 }
386
387 /* Extract the new directory name. */
388 372 _fx_directory_name_extract(new_name_ptr, &new_dir_entry.fx_dir_entry_name[0]);
389
390 /* Determine if the name was a long directory name. */
391
6/6
✓ Branch 46 → 47 taken 66 times.
✓ Branch 46 → 48 taken 2 times.
✓ Branch 53 → 54 taken 191 times.
✓ Branch 53 → 55 taken 11 times.
✓ Branch 60 → 61 taken 94 times.
✓ Branch 60 → 62 taken 8 times.
372 if (new_dir_entry.fx_dir_entry_long_name_present)
392 {
393
394 /* Yes, clear the short directory name to force a new one. */
395 351 new_dir_entry.fx_dir_entry_short_name[0] = 0;
396 }
397
398 /* Setup new attributes for the new directory entry. */
399 372 new_dir_entry.fx_dir_entry_attributes = old_dir_entry.fx_dir_entry_attributes;
400 372 new_dir_entry.fx_dir_entry_cluster = old_dir_entry.fx_dir_entry_cluster;
401 372 new_dir_entry.fx_dir_entry_file_size = old_dir_entry.fx_dir_entry_file_size;
402
403 /* Save the reserved field. */
404 372 new_dir_entry.fx_dir_entry_reserved = old_dir_entry.fx_dir_entry_reserved;
405
406 /* Set time and date stamps. */
407 372 new_dir_entry.fx_dir_entry_created_time_ms = old_dir_entry.fx_dir_entry_created_time_ms;
408 372 new_dir_entry.fx_dir_entry_created_time = old_dir_entry.fx_dir_entry_created_time;
409 372 new_dir_entry.fx_dir_entry_created_date = old_dir_entry.fx_dir_entry_created_date;
410 372 new_dir_entry.fx_dir_entry_last_accessed_date = old_dir_entry.fx_dir_entry_last_accessed_date;
411 372 new_dir_entry.fx_dir_entry_time = old_dir_entry.fx_dir_entry_time;
412 372 new_dir_entry.fx_dir_entry_date = old_dir_entry.fx_dir_entry_date;
413
414
415 /* Is there a leading dot? */
416
6/6
✓ Branch 48 → 49 taken 2 times.
✓ Branch 48 → 50 taken 66 times.
✓ Branch 55 → 56 taken 5 times.
✓ Branch 55 → 57 taken 197 times.
✓ Branch 62 → 63 taken 2 times.
✓ Branch 62 → 64 taken 100 times.
372 if (new_dir_entry.fx_dir_entry_name[0] == '.')
417 {
418
419 /* Yes, toggle the hidden attribute bit. */
420 9 new_dir_entry.fx_dir_entry_attributes |= FX_HIDDEN;
421 }
422
423 #ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
424
425 /* Invalidate the directory cache. */
426 372 media_ptr -> fx_media_last_found_name[0] = FX_NULL;
427 #endif
428
429 /* Now write out the directory entry. */
430 372 status = _fx_directory_entry_write(media_ptr, &new_dir_entry);
431
432 /* Determine if the write was successful. */
433
6/6
✓ Branch 51 → 52 taken 2 times.
✓ Branch 51 → 53 taken 66 times.
✓ Branch 58 → 59 taken 5 times.
✓ Branch 58 → 61 taken 197 times.
✓ Branch 65 → 66 taken 2 times.
✓ Branch 65 → 69 taken 100 times.
372 if (status != FX_SUCCESS)
434 {
435
436 #ifdef FX_ENABLE_FAULT_TOLERANT
437 4 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
438 #endif /* FX_ENABLE_FAULT_TOLERANT */
439
440 /* Release media protection. */
441 5 FX_UNPROTECT
442
443 /* Return the error code. */
444 9 return(status);
445 }
446
447 /* Set the old directory entry to free. */
448 363 old_dir_entry.fx_dir_entry_name[0] = (CHAR)FX_DIR_ENTRY_FREE;
449 363 old_dir_entry.fx_dir_entry_short_name[0] = (CHAR)FX_DIR_ENTRY_FREE;
450
451 /* Now wipe out the old directory entry. */
452 363 status = _fx_directory_entry_write(media_ptr, &old_dir_entry);
453
454 #ifdef FX_ENABLE_FAULT_TOLERANT
455 /* Check for a bad status. */
456
4/4
✓ Branch 62 → 63 taken 2 times.
✓ Branch 62 → 65 taken 96 times.
✓ Branch 70 → 71 taken 2 times.
✓ Branch 70 → 74 taken 98 times.
198 if (status != FX_SUCCESS)
457 {
458
459 4 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
460
461 /* Release media protection. */
462 2 FX_UNPROTECT
463
464 /* Return the bad status. */
465 4 return(status);
466 }
467
468 /* End transaction. */
469 194 status = _fx_fault_tolerant_transaction_end(media_ptr);
470 #endif /* FX_ENABLE_FAULT_TOLERANT */
471
472 /* Release media protection. */
473 181 FX_UNPROTECT
474
475 /* Directory rename is complete, return status. */
476 327 return(status);
477 }
478
479