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 |