GCC Code Coverage Report


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

fx_unicode_directory_entry_read.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 /** Unicode */
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_unicode.h"
30 #include "fx_utility.h"
31
32
33 /**************************************************************************/
34 /* */
35 /* FUNCTION RELEASE */
36 /* */
37 /* _fx_unicode_directory_entry_read PORTABLE C */
38 /* 6.1 */
39 /* AUTHOR */
40 /* */
41 /* William E. Lamie, Microsoft Corporation */
42 /* */
43 /* DESCRIPTION */
44 /* */
45 /* This function reads a unicode directory entry. */
46 /* */
47 /* INPUT */
48 /* */
49 /* media_ptr Pointer to media */
50 /* source_dir Pointer to source directory */
51 /* entry_ptr Entry index in the directory */
52 /* destination_ptr Destination directory */
53 /* unicode_name Destination unicode name */
54 /* unicode_size Destination unicode name size */
55 /* */
56 /* OUTPUT */
57 /* */
58 /* Completion Status */
59 /* */
60 /* CALLS */
61 /* */
62 /* _fx_utility_FAT_entry_read Read a FAT entry */
63 /* _fx_utility_logical_sector_read Read a logical sector */
64 /* _fx_utility_16_unsigned_read Read a 2-byte value */
65 /* _fx_utility_32_unsigned_read Read a 4-byte value */
66 /* */
67 /* CALLED BY */
68 /* */
69 /* Unicode Utilities */
70 /* */
71 /**************************************************************************/
72 86682 UINT _fx_unicode_directory_entry_read(FX_MEDIA *media_ptr, FX_DIR_ENTRY *source_dir,
73 ULONG *entry_ptr, FX_DIR_ENTRY *destination_ptr,
74 UCHAR *unicode_name, ULONG *unicode_size)
75 {
76
77 UINT i, j, k, card, dotflag, get_short_name;
78 UINT number_of_lfns;
79 UINT status;
80 86682 ULONG cluster, next_cluster = 0;
81 UINT relative_cluster;
82 UINT relative_sector;
83 ULONG logical_sector;
84 ULONG byte_offset;
85 ULONG bytes_per_cluster;
86 UCHAR *read_ptr;
87 CHAR *short_name_ptr;
88 86682 ULONG entry = *entry_ptr;
89 UINT u;
90
91
92 #ifndef FX_MEDIA_STATISTICS_DISABLE
93
94 /* Increment the number of directory entry read requests. */
95 86682 media_ptr -> fx_media_directory_entry_reads++;
96 #endif
97
98 /* Calculate the byte offset of this directory entry. */
99 86682 byte_offset = entry * FX_DIR_ENTRY_SIZE;
100
101 /* Determine if a sub-directory or FAT32 root directory is specified. */
102
4/4
✓ Branch 2 → 3 taken 49281 times.
✓ Branch 2 → 4 taken 37401 times.
✓ Branch 3 → 4 taken 24930 times.
✓ Branch 3 → 28 taken 24351 times.
86682 if ((source_dir) || (media_ptr -> fx_media_32_bit_FAT))
103 {
104
105 /* Yes, a sub-directory is present. */
106
107 /* Calculate the number of bytes per cluster. */
108 62331 bytes_per_cluster = ((ULONG)media_ptr -> fx_media_bytes_per_sector) *
109 62331 ((ULONG)media_ptr -> fx_media_sectors_per_cluster);
110
111 /* Check for invalid value. */
112
2/2
✓ Branch 4 → 5 taken 9 times.
✓ Branch 4 → 6 taken 62322 times.
62331 if (bytes_per_cluster == 0)
113 {
114
115 /* Invalid media, return error. */
116 9 return(FX_MEDIA_INVALID);
117 }
118
119 /* Now determine the relative cluster in the sub-directory file. */
120 62322 relative_cluster = (UINT)(byte_offset / bytes_per_cluster);
121
122 /* Calculate the byte offset within the cluster. */
123 62322 byte_offset = byte_offset % bytes_per_cluster;
124
125 /* Now figure out the relative sector within the cluster. */
126 62322 relative_sector = (UINT)(byte_offset / ((ULONG)media_ptr -> fx_media_bytes_per_sector));
127
128 /* Read the directory sector into the internal memory buffer. */
129
130 /* Determine if there is a sub-directory. */
131
2/2
✓ Branch 6 → 7 taken 37401 times.
✓ Branch 6 → 14 taken 24921 times.
62322 if (source_dir)
132 {
133
134 /* Determine if this source directory has valid information from the previous call. */
135
2/2
✓ Branch 7 → 8 taken 35456 times.
✓ Branch 7 → 12 taken 1945 times.
37401 if ((source_dir -> fx_dir_entry_last_search_cluster) &&
136
2/2
✓ Branch 8 → 9 taken 35447 times.
✓ Branch 8 → 12 taken 9 times.
35456 (source_dir -> fx_dir_entry_last_search_relative_cluster <= relative_cluster) &&
137
2/2
✓ Branch 9 → 10 taken 35438 times.
✓ Branch 9 → 12 taken 9 times.
35447 (source_dir -> fx_dir_entry_last_search_log_sector == source_dir -> fx_dir_entry_log_sector) &&
138
2/2
✓ Branch 10 → 11 taken 35429 times.
✓ Branch 10 → 12 taken 9 times.
35438 (source_dir -> fx_dir_entry_last_search_byte_offset == source_dir -> fx_dir_entry_byte_offset))
139 {
140
141 /* Use the previous information to start the search. */
142 35429 cluster = source_dir -> fx_dir_entry_last_search_cluster;
143
144 /* Setup the relative cluster index to the saved relative cluster. */
145 35429 i = source_dir -> fx_dir_entry_last_search_relative_cluster;
146
147 /* Clear the search cluster. It will be updated prior to successful return. */
148 35429 source_dir -> fx_dir_entry_last_search_cluster = 0;
149 }
150 else
151 {
152
153 /* Nothing from the previous directory read, just setup the starting cluster to the
154 beginning of the sub-directory. */
155 1972 cluster = source_dir -> fx_dir_entry_cluster;
156
157 /* Setup the relative cluster index to zero. */
158 1972 i = 0;
159 }
160 }
161 else
162 {
163
164 /* No, setup the starting cluster to the FAT32 root cluster. */
165 24921 cluster = media_ptr -> fx_media_root_cluster_32;
166
167 /* Setup the relative cluster index to zero. */
168 24921 i = 0;
169 }
170
171 /* Loop to position to the appropriate cluster. */
172
2/2
✓ Branch 23 → 16 taken 6617 times.
✓ Branch 23 → 24 taken 62299 times.
68916 while (i < relative_cluster)
173 {
174
175 /* Check the value of the new cluster - it must be a valid cluster number
176 or something is really wrong! */
177
4/4
✓ Branch 16 → 17 taken 6610 times.
✓ Branch 16 → 18 taken 7 times.
✓ Branch 17 → 18 taken 9 times.
✓ Branch 17 → 19 taken 6601 times.
6617 if ((cluster < FX_FAT_ENTRY_START) || (cluster > media_ptr -> fx_media_fat_reserved))
178 {
179
180 /* Send error message back to caller. */
181 16 return(FX_FILE_CORRUPT);
182 }
183
184 /* Read the next cluster. */
185 6601 status = _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
186
187 /* There is a potential for loop, but hardly anything can be done */
188
189 /* Check for I/O error. */
190
2/2
✓ Branch 20 → 21 taken 7 times.
✓ Branch 20 → 22 taken 6594 times.
6601 if (status != FX_SUCCESS)
191 {
192
193 /* Return error code. */
194 7 return(status);
195 }
196
197 /* Setup the actual cluster. */
198 6594 cluster = next_cluster;
199
200 /* Increment the relative cluster number. */
201 6594 i++;
202 }
203
204 /* At this point, the directory data sector needs to be read. */
205 62299 logical_sector = ((ULONG)media_ptr -> fx_media_data_sector_start) +
206 62299 (((ULONG)cluster - FX_FAT_ENTRY_START) *
207 62299 ((ULONG)media_ptr -> fx_media_sectors_per_cluster)) +
208 relative_sector;
209
210 /* Read the logical directory sector. */
211 62299 status = _fx_utility_logical_sector_read(media_ptr, (ULONG64) logical_sector,
212 62299 media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
213
214 /* Determine if an error occurred. */
215
2/2
✓ Branch 25 → 26 taken 15 times.
✓ Branch 25 → 27 taken 62284 times.
62299 if (status != FX_SUCCESS)
216 {
217
218 /* Return error code. */
219 15 return(status);
220 }
221
222 /* Calculate the byte offset within this sector. */
223 62284 byte_offset = byte_offset % media_ptr -> fx_media_bytes_per_sector;
224 }
225 else
226 {
227
228 /* Read the entry from the root directory. */
229
230 /* Determine which sector the requested root directory entry is in. */
231 24351 logical_sector = (byte_offset / media_ptr -> fx_media_bytes_per_sector) +
232 24351 (ULONG)media_ptr -> fx_media_root_sector_start;
233
234 /* Read the logical directory sector. */
235 24351 status = _fx_utility_logical_sector_read(media_ptr, (ULONG64) logical_sector,
236 24351 media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
237
238 /* Determine if an error occurred. */
239
2/2
✓ Branch 29 → 30 taken 9 times.
✓ Branch 29 → 31 taken 24342 times.
24351 if (status != FX_SUCCESS)
240 {
241
242 /* Return error code. */
243 9 return(status);
244 }
245
246 /* Set the cluster and relative variables (not used in this case) to avoid any compiler
247 warnings. */
248 24342 relative_cluster = relative_sector = cluster = 0;
249
250 /* Now calculate the byte offset into this sector. */
251 24342 byte_offset = byte_offset -
252 24342 ((logical_sector - (ULONG)media_ptr -> fx_media_root_sector_start) *
253 24342 media_ptr -> fx_media_bytes_per_sector);
254 }
255
256 /* Setup a pointer into the buffer. */
257 86626 read_ptr = (UCHAR *)media_ptr -> fx_media_memory_buffer + (UINT)byte_offset;
258
259 /* Save the logical sector and byte offset in the returned directory entry. */
260 86626 destination_ptr -> fx_dir_entry_log_sector = logical_sector;
261 86626 destination_ptr -> fx_dir_entry_byte_offset = byte_offset;
262
263 /* Clear the short file name information. */
264 86626 destination_ptr -> fx_dir_entry_long_name_shorted = 0;
265 86626 destination_ptr -> fx_dir_entry_short_name[0] = 0;
266
267 /* Setup short name pointer. */
268 86626 short_name_ptr = destination_ptr -> fx_dir_entry_name;
269
270 /* Initialize the unicode index. */
271 86626 u = 0;
272
273 /* Check if long file name exists. */
274 86626 get_short_name = 0;
275
4/4
✓ Branch 32 → 33 taken 76256 times.
✓ Branch 32 → 92 taken 10370 times.
✓ Branch 33 → 34 taken 75351 times.
✓ Branch 33 → 92 taken 905 times.
86626 if ((*(read_ptr + 11) == (UCHAR)FX_LONG_NAME) && (*read_ptr != (UCHAR)FX_DIR_ENTRY_FREE))
276 {
277
278 /* Collate the long name. */
279
280
281 /* Save the number of LFN entries. */
282 75351 number_of_lfns = (UINT)(*read_ptr & (UCHAR)0x1f);
283
284
2/2
✓ Branch 34 → 35 taken 9 times.
✓ Branch 34 → 36 taken 75342 times.
75351 if(number_of_lfns == 0)
285 {
286 /* Number of LFN cannot is 1-based. Therefore it cannot be zero. */
287 9 return(FX_FILE_CORRUPT);
288 }
289 else
290 {
291 /* Pickup the file name length. */
292 75342 i = (number_of_lfns - 1) * FX_LONG_NAME_ENTRY_LEN;
293 }
294
295 /* Check the file name size. */
296
2/2
✓ Branch 36 → 37 taken 124 times.
✓ Branch 36 → 38 taken 75218 times.
75342 if (i >= (FX_MAX_LONG_NAME_LEN - 1))
297 {
298
299 /* Name is too big, shorten it. */
300 124 get_short_name = 1;
301 124 destination_ptr -> fx_dir_entry_long_name_shorted = (UINT)(*read_ptr & (UCHAR)0x1f);
302 }
303 else
304 {
305
306 /* Size of name is fine, save pointer to short file name. */
307 75218 short_name_ptr = destination_ptr -> fx_dir_entry_short_name;
308
309 /* Loop to make sure the long file name is NULL terminated. */
310 75218 j = i + FX_LONG_NAME_ENTRY_LEN + 1;
311 do
312 {
313 /* Place a NULL in the long name. */
314 1052447 destination_ptr -> fx_dir_entry_name[i] = 0;
315
316 /* Position to the next entry. */
317 1052447 i++;
318
4/4
✓ Branch 39 → 40 taken 977350 times.
✓ Branch 39 → 42 taken 75097 times.
✓ Branch 40 → 41 taken 977229 times.
✓ Branch 40 → 42 taken 121 times.
1052447 } while ((i < j) && (i < FX_MAX_LONG_NAME_LEN));
319 }
320
321 /* Loop to pickup the rest of the name. */
322 do
323 {
324
325 /* Get the lower 5 bit containing the cardinality. */
326 110315 card = (*read_ptr) & 0x1f;
327
328
2/2
✓ Branch 43 → 44 taken 12 times.
✓ Branch 43 → 45 taken 110303 times.
110315 if(card == 0)
329 {
330
331 /* Number of LFN starts from one. Therefore it cannot be zero. */
332 12 return(FX_FILE_CORRUPT);
333 }
334 else
335 {
336 110303 card = card - 1;
337 }
338 /* For simplicity no checksum or cardinality checking is done */
339
4/4
✓ Branch 45 → 46 taken 5697 times.
✓ Branch 45 → 47 taken 104606 times.
✓ Branch 46 → 47 taken 3271 times.
✓ Branch 46 → 69 taken 2426 times.
110303 if ((get_short_name == 0) || (u))
340 {
341
342 /* Loop to pickup name. */
343
2/2
✓ Branch 68 → 48 taken 1725337 times.
✓ Branch 68 → 69 taken 107750 times.
1833087 for (i = 1, j = 0, k = 0; i < FX_DIR_ENTRY_SIZE; i += 2)
344 {
345
346
4/4
✓ Branch 48 → 49 taken 1617466 times.
✓ Branch 48 → 50 taken 107871 times.
✓ Branch 49 → 50 taken 107750 times.
✓ Branch 49 → 51 taken 1509716 times.
1725337 if ((i == 11) || (i == 26))
347 {
348 215621 continue;
349 }
350
351 /* i = 12, 27 is not generated due to +=2 */
352
2/2
✓ Branch 51 → 52 taken 107871 times.
✓ Branch 51 → 53 taken 1401845 times.
1509716 if (i == 13)
353 {
354 107871 i = 12;
355 107871 continue; /* this time next unicode is byte offset 14*/
356 }
357
358 /* Determine if there is an actual unicode character present. */
359
2/2
✓ Branch 53 → 54 taken 746830 times.
✓ Branch 53 → 57 taken 655015 times.
1401845 if (read_ptr[i + 1])
360 {
361
362 /* Extended byte is non-zero, make sure both bytes of the unicode entry are not
363 all ones, since this is a normal case. */
364
4/4
✓ Branch 54 → 55 taken 728046 times.
✓ Branch 54 → 56 taken 18784 times.
✓ Branch 55 → 56 taken 9 times.
✓ Branch 55 → 57 taken 728037 times.
746830 if ((read_ptr[i + 1] != (UCHAR)0xFF) || (read_ptr[i] != (UCHAR)0xFF))
365 {
366
367 /* Name is an actual unicode name, shorten it. */
368 18793 get_short_name = 1;
369
370 /* Save the number of directory entries the LFN has. This will be
371 used later when updating the 8.3 portion of the LFN. */
372 18793 destination_ptr -> fx_dir_entry_long_name_shorted = number_of_lfns;
373
374 /* Setup short name pointer. */
375 18793 short_name_ptr = destination_ptr -> fx_dir_entry_name;
376 }
377 }
378
379 /* Determine if the character is NULL. */
380
4/4
✓ Branch 57 → 58 taken 76202 times.
✓ Branch 57 → 59 taken 1325643 times.
✓ Branch 58 → 59 taken 1145 times.
✓ Branch 58 → 61 taken 75057 times.
1401845 if (((read_ptr[i] == FX_NULL) && (read_ptr[i + 1] == FX_NULL)) ||
381
4/4
✓ Branch 59 → 60 taken 728172 times.
✓ Branch 59 → 62 taken 598616 times.
✓ Branch 60 → 61 taken 728037 times.
✓ Branch 60 → 62 taken 135 times.
1326788 ((read_ptr[i] == (UCHAR)0xFF) && (read_ptr[i + 1] == (UCHAR)0xFF)))
382 {
383 803094 continue;
384 }
385
386 /* Determine if the name is too big. */
387
2/2
✓ Branch 62 → 63 taken 127 times.
✓ Branch 62 → 64 taken 598624 times.
598751 if ((card * 13 + j) >= (FX_MAX_LONG_NAME_LEN - 1))
388 {
389
390 /* Name is actually too big, shorten it. */
391 127 get_short_name = 1;
392
393 /* Save the number of directory entries the LFN has. This will be
394 used later when updating the 8.3 portion of the LFN. */
395 127 destination_ptr -> fx_dir_entry_long_name_shorted = number_of_lfns;
396
397 /* Also reposition the short name pointer. */
398 127 short_name_ptr = destination_ptr -> fx_dir_entry_name;
399
400 127 break;
401 }
402
403 /* Each entry contains 13 unicode and first byte ASCII, second byte is extended. */
404
2/2
✓ Branch 64 → 65 taken 539773 times.
✓ Branch 64 → 66 taken 58851 times.
598624 if (get_short_name == 0)
405 {
406 539773 destination_ptr -> fx_dir_entry_name[13 * card + j] = (CHAR)read_ptr[i];
407 }
408
409 /* Save the potential unicode characters. */
410 598624 unicode_name[k + 26 * card + j] = read_ptr[i];
411 598624 unicode_name[k + 26 * card + j + 1] = read_ptr[i + 1];
412 598624 k++;
413 598624 u++;
414
415 598624 j++;
416 }
417 }
418
419 /* Determine if a new sector needs to be read. */
420
2/2
✓ Branch 69 → 70 taken 21147 times.
✓ Branch 69 → 88 taken 89156 times.
110303 if (byte_offset + FX_DIR_ENTRY_SIZE >= media_ptr -> fx_media_bytes_per_sector)
421 {
422
423 /* Determine if a sub-directory or FAT32 root directory is specified. */
424
4/4
✓ Branch 70 → 71 taken 7949 times.
✓ Branch 70 → 72 taken 13198 times.
✓ Branch 71 → 72 taken 2885 times.
✓ Branch 71 → 82 taken 5064 times.
21147 if ((source_dir) || (media_ptr -> fx_media_32_bit_FAT))
425 {
426
427 /* Determine the next sector of the directory entry. */
428
2/2
✓ Branch 72 → 73 taken 2915 times.
✓ Branch 72 → 74 taken 13168 times.
16083 if (relative_sector < (media_ptr -> fx_media_sectors_per_cluster - 1))
429 {
430
431 /* More sectors in this cluster. */
432
433 /* Simply increment the logical sector. */
434 2915 logical_sector++;
435
436 /* Increment the relative sector. */
437 2915 relative_sector++;
438 }
439 else
440 {
441
442 /* We need to move to the next cluster. */
443
444 /* Pickup the next cluster. */
445 13168 status = _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
446
447 /* Check for I/O error. */
448
2/2
✓ Branch 75 → 76 taken 7 times.
✓ Branch 75 → 77 taken 13161 times.
13168 if (status != FX_SUCCESS)
449 {
450
451 /* Return error code. */
452 7 return(status);
453 }
454
455 /* Copy next cluster to the current cluster. */
456 13161 cluster = next_cluster;
457
458 /* Check the value of the new cluster - it must be a valid cluster number
459 or something is really wrong! */
460
4/4
✓ Branch 77 → 78 taken 13156 times.
✓ Branch 77 → 79 taken 5 times.
✓ Branch 78 → 79 taken 5 times.
✓ Branch 78 → 80 taken 13151 times.
13161 if ((cluster < FX_FAT_ENTRY_START) || (cluster > media_ptr -> fx_media_fat_reserved))
461 {
462
463 /* Send error message back to caller. */
464 10 return(FX_FILE_CORRUPT);
465 }
466
467 /* Now increment the relative cluster. */
468 13151 relative_cluster++;
469
470 /* Setup the relative sector (this is zero for subsequent cluster. */
471 13151 relative_sector = 0;
472
473 /* Calculate the next logical sector. */
474 13151 logical_sector = ((ULONG)media_ptr -> fx_media_data_sector_start) +
475 13151 (((ULONG)cluster - FX_FAT_ENTRY_START) *
476 13151 ((ULONG)media_ptr -> fx_media_sectors_per_cluster));
477 }
478 }
479 else
480 {
481
482 /* Non-FAT 32 root directory. */
483
484 /* Advance to the next sector. */
485 5064 logical_sector++;
486
487 /* Determine if the logical sector is valid. */
488
2/2
✓ Branch 82 → 83 taken 13 times.
✓ Branch 82 → 84 taken 5051 times.
5064 if (logical_sector >= (ULONG)(media_ptr -> fx_media_root_sector_start + media_ptr -> fx_media_root_sectors))
489 {
490
491 /* Trying to read past root directory - send error message back to caller. */
492 13 return(FX_FILE_CORRUPT);
493 }
494 }
495
496 /* Read the new sector. */
497 21117 status = _fx_utility_logical_sector_read(media_ptr, (ULONG64) logical_sector,
498 21117 media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
499
500 /* Check I/O status. */
501
2/2
✓ Branch 85 → 86 taken 9 times.
✓ Branch 85 → 87 taken 21108 times.
21117 if (status != FX_SUCCESS)
502 {
503 9 return(status);
504 }
505
506 /* Set the byte offset to 0 for new sector. */
507 21108 byte_offset = 0;
508 }
509 else
510 {
511
512 /* Calculate the new byte offset. */
513 89156 byte_offset += FX_DIR_ENTRY_SIZE;
514 }
515
516 /* Calculate the next read pointer. */
517 110264 read_ptr = (UCHAR *)media_ptr -> fx_media_memory_buffer + (UINT)byte_offset;
518
519 /* Move to the next entry. */
520 110264 entry++;
521
2/2
✓ Branch 89 → 90 taken 34973 times.
✓ Branch 89 → 91 taken 75291 times.
110264 } while (card > 0);
522
523 /* Set flag indicating long file name is present. */
524 75291 destination_ptr -> fx_dir_entry_long_name_present = 1;
525 }
526 else
527 {
528 /* No long file name is present. */
529 11275 get_short_name = 1;
530 }
531
532 /* Determine if we need to clear the long name flag. */
533
2/2
✓ Branch 93 → 94 taken 15949 times.
✓ Branch 93 → 95 taken 70617 times.
86566 if (get_short_name == 1)
534 {
535
536 /* Clear the long name flag. */
537 15949 destination_ptr -> fx_dir_entry_long_name_present = 0;
538 }
539
540 /* Store the unicode name size. */
541 86566 *unicode_size = u;
542
543 /* Pickup the short file name. */
544 86566 short_name_ptr[0] = 0;
545 86566 dotflag = 0;
546
2/2
✓ Branch 111 → 96 taken 898574 times.
✓ Branch 111 → 112 taken 81009 times.
979583 for (i = 0, j = 0; i < (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE); i++)
547 {
548
549 /* Check for a NULL. */
550
2/2
✓ Branch 96 → 97 taken 5557 times.
✓ Branch 96 → 98 taken 893017 times.
898574 if ((CHAR)read_ptr[i] == 0)
551 {
552 5557 break;
553 }
554
555 /* Check for a dot. This happens for the first two directory entries, no
556 extra dot is needed. */
557
2/2
✓ Branch 98 → 99 taken 5832 times.
✓ Branch 98 → 100 taken 887185 times.
893017 if ((CHAR)read_ptr[i] == '.')
558 {
559 5832 dotflag = 2;
560 }
561
562 /* Check for a space. */
563
2/2
✓ Branch 100 → 101 taken 499246 times.
✓ Branch 100 → 104 taken 393771 times.
893017 if ((CHAR)read_ptr[i] == ' ')
564 {
565 /* Put a dot if a character comes after space. */
566
2/2
✓ Branch 101 → 102 taken 76961 times.
✓ Branch 101 → 103 taken 422285 times.
499246 if (dotflag == 0)
567 {
568 76961 dotflag = 1;
569 }
570 499246 continue;
571 }
572
573 /* Check for the main short file name size. */
574
2/2
✓ Branch 104 → 105 taken 183 times.
✓ Branch 104 → 107 taken 393588 times.
393771 if (i == FX_DIR_NAME_SIZE)
575 {
576 /* Check to see if we need to insert a dot. */
577
2/2
✓ Branch 105 → 106 taken 166 times.
✓ Branch 105 → 107 taken 17 times.
183 if (dotflag == 0)
578 {
579 166 dotflag = 1;
580 }
581 }
582
583 /* Check to see if we need to add a dot. */
584
2/2
✓ Branch 107 → 108 taken 174 times.
✓ Branch 107 → 109 taken 393597 times.
393771 if (dotflag == 1)
585 {
586 /* Add dot to short file name. */
587 174 short_name_ptr[j++] = '.';
588 174 dotflag = 2; /* no more dot for spaces */
589 }
590
591 /* Copy a character. */
592 393771 short_name_ptr[j] = (CHAR)read_ptr[i];
593
594 /* Increment size. */
595 393771 j++;
596 }
597
598 /* Determine if a long file name is present and its associated short file
599 name is actually free. */
600
4/4
✓ Branch 112 → 113 taken 70617 times.
✓ Branch 112 → 115 taken 15949 times.
✓ Branch 113 → 114 taken 9 times.
✓ Branch 113 → 115 taken 70608 times.
86566 if ((destination_ptr -> fx_dir_entry_long_name_present) && (((UCHAR)short_name_ptr[0]) == (UCHAR)FX_DIR_ENTRY_FREE))
601 {
602
603 /* Yes, the short file name is really free even though long file name entries directly precede it.
604 In this case, simply place the free directory marker at the front of the long file name. */
605 9 destination_ptr -> fx_dir_entry_name[0] = (CHAR)FX_DIR_ENTRY_FREE;
606 9 short_name_ptr[0] = (CHAR)0;
607 }
608
609 /* Determine if the short name pointer is NULL while the read pointer is
610 non-NULL. */
611
4/4
✓ Branch 115 → 116 taken 4697 times.
✓ Branch 115 → 120 taken 81869 times.
✓ Branch 116 → 117 taken 36 times.
✓ Branch 116 → 120 taken 4661 times.
86566 if ((short_name_ptr[0] == 0) && (read_ptr[0] == ' '))
612 {
613
614 /* This condition can occur with an all blank volume name. Simply
615 copy the volume name to the short name in this case. */
616
2/2
✓ Branch 119 → 118 taken 396 times.
✓ Branch 119 → 120 taken 36 times.
432 for (j = 0; j < (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE); j++)
617 {
618
619 /* Copy a byte of the volume name. */
620 396 short_name_ptr[j] = (CHAR)read_ptr[j];
621 }
622 }
623
624 /* Set end of string to null. */
625 86566 short_name_ptr[j] = 0;
626
627 /* Load up the destination directory entry. */
628 86566 read_ptr += (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE);
629
630 /* Copy the attribute into the destination. */
631 86566 destination_ptr -> fx_dir_entry_attributes = *read_ptr++;
632
633 /* Pickup the reserved byte. */
634 86566 destination_ptr -> fx_dir_entry_reserved = *read_ptr++;
635
636 /* Check for an undocumented NT file name feature for optimizing the storage
637 of all lower case file names that otherwise are valid 8.3 file names. The
638 following reserved bit definitions are present:
639
640 BIT3 - set if 8.3 is all in lower case and no extended filename.
641 BIT4 - set for file, clear for directory entry if no extended filename.
642
643 This is true for all NT systems. Prior to NT follows MSDOS FAT documentation and
644 is set to 0x00, all bits cleared. Therefore if BIT3 is set force lowercase. */
645
4/4
✓ Branch 120 → 121 taken 15949 times.
✓ Branch 120 → 129 taken 70617 times.
✓ Branch 121 → 122 taken 162 times.
✓ Branch 121 → 129 taken 15787 times.
86566 if ((get_short_name) && (destination_ptr -> fx_dir_entry_reserved & 0x08))
646 {
647
648 /* Microsoft undocumented NT file name feature... convert short name to lower
649 case. */
650
4/4
✓ Branch 127 → 128 taken 1494 times.
✓ Branch 127 → 129 taken 72 times.
✓ Branch 128 → 123 taken 1404 times.
✓ Branch 128 → 129 taken 90 times.
1566 for (j = 0; j <= (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE) && (short_name_ptr[j] != 0x00); j++)
651 {
652
653 /* Determine if an upper case character is present. */
654
4/4
✓ Branch 123 → 124 taken 1260 times.
✓ Branch 123 → 126 taken 144 times.
✓ Branch 124 → 125 taken 648 times.
✓ Branch 124 → 126 taken 612 times.
1404 if ((short_name_ptr[j] >= 'A') && (short_name_ptr[j] <= 'Z'))
655 {
656
657 /* Yes, an upper case character is present. Force it to lower case. */
658 648 short_name_ptr[j] = (CHAR)((INT)short_name_ptr[j] + 32);
659 }
660 }
661 }
662
663 /* Pickup the created time in milliseconds. */
664 86566 destination_ptr -> fx_dir_entry_created_time_ms = *read_ptr++;
665
666 /* Pickup the created time. */
667 86566 destination_ptr -> fx_dir_entry_created_time = _fx_utility_16_unsigned_read(read_ptr);
668 86566 read_ptr = read_ptr + 2; /* Always 2 bytes */
669
670 /* Pickup the created date. */
671 86566 destination_ptr -> fx_dir_entry_created_date = _fx_utility_16_unsigned_read(read_ptr);
672 86566 read_ptr = read_ptr + 2; /* Always 2 bytes */
673
674 /* Pickup the last accessed date. */
675 86566 destination_ptr -> fx_dir_entry_last_accessed_date = _fx_utility_16_unsigned_read(read_ptr);
676 86566 read_ptr = read_ptr + 2; /* Always 2 bytes */
677
678 /* read the upper 2 bytes of starting cluster - required only for 32 bit FAT */
679
2/2
✓ Branch 132 → 133 taken 53534 times.
✓ Branch 132 → 135 taken 33032 times.
86566 if (media_ptr -> fx_media_32_bit_FAT)
680 {
681
682 /* FAT32 only. */
683 53534 destination_ptr -> fx_dir_entry_cluster = _fx_utility_16_unsigned_read(read_ptr);
684 53534 destination_ptr -> fx_dir_entry_cluster <<= 16;
685 }
686 else
687 {
688 /* Not required for non FAT32. */
689 33032 destination_ptr -> fx_dir_entry_cluster = 0;
690 }
691
692 /* Advance the read pointer. */
693 86566 read_ptr = read_ptr + 2; /* Always 2 bytes */
694
695 /* Copy the time into the destination. */
696 86566 destination_ptr -> fx_dir_entry_time = _fx_utility_16_unsigned_read(read_ptr);
697 86566 read_ptr = read_ptr + 2; /* Always 2 bytes */
698
699 /* Copy the date into the destination. */
700 86566 destination_ptr -> fx_dir_entry_date = _fx_utility_16_unsigned_read(read_ptr);
701 86566 read_ptr = read_ptr + 2; /* Always 2 bytes */
702
703 /* Copy the starting cluster into the destination. */
704 86566 destination_ptr -> fx_dir_entry_cluster += _fx_utility_16_unsigned_read(read_ptr);
705 86566 read_ptr = read_ptr + 2; /* Always 2 bytes */
706
707 /* Copy the file size into the destination. */
708 86566 destination_ptr -> fx_dir_entry_file_size = _fx_utility_32_unsigned_read(read_ptr);
709
710 /* Clear the destination search specific fields. */
711 86566 destination_ptr -> fx_dir_entry_last_search_cluster = 0;
712 86566 destination_ptr -> fx_dir_entry_last_search_relative_cluster = 0;
713 86566 destination_ptr -> fx_dir_entry_last_search_log_sector = 0;
714 86566 destination_ptr -> fx_dir_entry_last_search_byte_offset = 0;
715
716 /* Remember the entry number. */
717 86566 destination_ptr -> fx_dir_entry_number = entry;
718
719 /* Return entry number. */
720 86566 *entry_ptr = entry;
721
722 /* Determine if we should remember the last cluster and relative cluster. */
723
2/2
✓ Branch 140 → 141 taken 37363 times.
✓ Branch 140 → 142 taken 49203 times.
86566 if (source_dir)
724 {
725
726 /* Yes, remember the last cluster and relative cluster for a subsequent call
727 to read a directory entry. */
728 37363 source_dir -> fx_dir_entry_last_search_cluster = cluster;
729 37363 source_dir -> fx_dir_entry_last_search_relative_cluster = relative_cluster;
730
731 /* Also remember several other items that are unique to the directory... just to verify that the
732 search information can be used. */
733 37363 source_dir -> fx_dir_entry_last_search_log_sector = source_dir -> fx_dir_entry_log_sector;
734 37363 source_dir -> fx_dir_entry_last_search_byte_offset = source_dir -> fx_dir_entry_byte_offset;
735 }
736
737 /* Return success to the caller. */
738 86566 return(FX_SUCCESS);
739 }
740
741