fx_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 | /** Directory */ | ||
| 19 | /** */ | ||
| 20 | /**************************************************************************/ | ||
| 21 | /**************************************************************************/ | ||
| 22 | |||
| 23 | #define FX_SOURCE_CODE | ||
| 24 | |||
| 25 | |||
| 26 | /* Include necessary system files. */ | ||
| 27 | |||
| 28 | #include "fx_api.h" | ||
| 29 | #include "fx_system.h" | ||
| 30 | #include "fx_directory.h" | ||
| 31 | #include "fx_utility.h" | ||
| 32 | |||
| 33 | |||
| 34 | /**************************************************************************/ | ||
| 35 | /* */ | ||
| 36 | /* FUNCTION RELEASE */ | ||
| 37 | /* */ | ||
| 38 | /* _fx_directory_entry_read PORTABLE C */ | ||
| 39 | /* 6.1 */ | ||
| 40 | /* AUTHOR */ | ||
| 41 | /* */ | ||
| 42 | /* William E. Lamie, Microsoft Corporation */ | ||
| 43 | /* */ | ||
| 44 | /* DESCRIPTION */ | ||
| 45 | /* */ | ||
| 46 | /* This function reads the supplied directory entry from the supplied */ | ||
| 47 | /* source directory. If the supplied directory entry is NULL, then */ | ||
| 48 | /* the root directory is assumed. */ | ||
| 49 | /* */ | ||
| 50 | /* INPUT */ | ||
| 51 | /* */ | ||
| 52 | /* media_ptr Media control block pointer */ | ||
| 53 | /* source_dir Source directory entry */ | ||
| 54 | /* entry_ptr Directory entry number */ | ||
| 55 | /* destination_ptr Pointer to destination for */ | ||
| 56 | /* the directory entry */ | ||
| 57 | /* */ | ||
| 58 | /* OUTPUT */ | ||
| 59 | /* */ | ||
| 60 | /* return status */ | ||
| 61 | /* *entry_ptr should point to the 8:3 entry if it is a long name */ | ||
| 62 | /* */ | ||
| 63 | /* CALLS */ | ||
| 64 | /* */ | ||
| 65 | /* _fx_utility_FAT_entry_read Read a FAT entry */ | ||
| 66 | /* _fx_utility_logical_sector_read Read directory sector */ | ||
| 67 | /* _fx_utility_16_unsigned_read Read a UINT from memory */ | ||
| 68 | /* _fx_utility_32_unsigned_read Read a ULONG from memory */ | ||
| 69 | /* */ | ||
| 70 | /* CALLED BY */ | ||
| 71 | /* */ | ||
| 72 | /* FileX System Functions */ | ||
| 73 | /* */ | ||
| 74 | /**************************************************************************/ | ||
| 75 | 83086316 | UINT _fx_directory_entry_read(FX_MEDIA *media_ptr, FX_DIR_ENTRY *source_dir, | |
| 76 | ULONG *entry_ptr, FX_DIR_ENTRY *destination_ptr) | ||
| 77 | { | ||
| 78 | |||
| 79 | UINT i, j, card, dotflag, get_short_name; | ||
| 80 | UINT number_of_lfns; | ||
| 81 | UINT status; | ||
| 82 | 83086316 | ULONG cluster, next_cluster = 0; | |
| 83 | UINT relative_cluster; | ||
| 84 | UINT relative_sector; | ||
| 85 | ULONG logical_sector; | ||
| 86 | ULONG byte_offset; | ||
| 87 | ULONG bytes_per_cluster; | ||
| 88 | UCHAR *read_ptr; | ||
| 89 | CHAR *short_name_ptr; | ||
| 90 | 83086316 | ULONG entry = *entry_ptr; | |
| 91 | |||
| 92 | |||
| 93 | #ifndef FX_MEDIA_STATISTICS_DISABLE | ||
| 94 | |||
| 95 | /* Increment the number of directory entry read requests. */ | ||
| 96 | 83086316 | media_ptr -> fx_media_directory_entry_reads++; | |
| 97 | #endif | ||
| 98 | |||
| 99 | /* Extended port-specific processing macro, which is by default defined to white space. */ | ||
| 100 |
4/4✓ Branch 2 → 3 taken 90 times.
✓ Branch 2 → 5 taken 83086226 times.
✓ Branch 3 → 4 taken 9 times.
✓ Branch 3 → 5 taken 81 times.
|
83086316 | FX_DIRECTORY_ENTRY_READ_EXTENSION |
| 101 | |||
| 102 | /* If trace is enabled, insert this event into the trace buffer. */ | ||
| 103 | FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_DIR_ENTRY_READ, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0) | ||
| 104 | |||
| 105 | /* Calculate the byte offset of this directory entry. */ | ||
| 106 | 83086307 | byte_offset = entry * FX_DIR_ENTRY_SIZE; | |
| 107 | |||
| 108 | /* Determine if a sub-directory or FAT32 root directory is specified. */ | ||
| 109 |
4/4✓ Branch 5 → 6 taken 81526105 times.
✓ Branch 5 → 7 taken 1560202 times.
✓ Branch 6 → 7 taken 70644880 times.
✓ Branch 6 → 31 taken 10881225 times.
|
83086307 | if ((source_dir) || (media_ptr -> fx_media_32_bit_FAT)) |
| 110 | { | ||
| 111 | |||
| 112 | /* Yes, a sub-directory is present. */ | ||
| 113 | |||
| 114 | /* Calculate the number of bytes per cluster. */ | ||
| 115 | 72205082 | bytes_per_cluster = ((ULONG)media_ptr -> fx_media_bytes_per_sector) * | |
| 116 | 72205082 | ((ULONG)media_ptr -> fx_media_sectors_per_cluster); | |
| 117 | |||
| 118 | /* Check for invalid value. */ | ||
| 119 |
2/2✓ Branch 7 → 8 taken 27 times.
✓ Branch 7 → 9 taken 72205055 times.
|
72205082 | if (bytes_per_cluster == 0) |
| 120 | { | ||
| 121 | |||
| 122 | /* Invalid media, return error. */ | ||
| 123 | 27 | return(FX_MEDIA_INVALID); | |
| 124 | } | ||
| 125 | |||
| 126 | /* Now determine the relative cluster in the sub-directory file. */ | ||
| 127 | 72205055 | relative_cluster = (UINT)(byte_offset / bytes_per_cluster); | |
| 128 | |||
| 129 | /* Calculate the byte offset within the cluster. */ | ||
| 130 | 72205055 | byte_offset = byte_offset % bytes_per_cluster; | |
| 131 | |||
| 132 | /* Now figure out the relative sector within the cluster. */ | ||
| 133 | 72205055 | relative_sector = (UINT)(byte_offset / ((ULONG)media_ptr -> fx_media_bytes_per_sector)); | |
| 134 | |||
| 135 | /* Read the directory sector into the internal memory buffer. */ | ||
| 136 | |||
| 137 | /* Determine if there is a sub-directory. */ | ||
| 138 |
2/2✓ Branch 9 → 10 taken 1560193 times.
✓ Branch 9 → 17 taken 70644862 times.
|
72205055 | if (source_dir) |
| 139 | { | ||
| 140 | |||
| 141 | /* Determine if this source directory has valid information from the previous call. */ | ||
| 142 |
2/2✓ Branch 10 → 11 taken 1265166 times.
✓ Branch 10 → 15 taken 295027 times.
|
1560193 | if ((source_dir -> fx_dir_entry_last_search_cluster) && |
| 143 |
2/2✓ Branch 11 → 12 taken 1265157 times.
✓ Branch 11 → 15 taken 9 times.
|
1265166 | (source_dir -> fx_dir_entry_last_search_relative_cluster <= relative_cluster) && |
| 144 |
2/2✓ Branch 12 → 13 taken 1265148 times.
✓ Branch 12 → 15 taken 9 times.
|
1265157 | (source_dir -> fx_dir_entry_last_search_log_sector == source_dir -> fx_dir_entry_log_sector) && |
| 145 |
2/2✓ Branch 13 → 14 taken 1265139 times.
✓ Branch 13 → 15 taken 9 times.
|
1265148 | (source_dir -> fx_dir_entry_last_search_byte_offset == source_dir -> fx_dir_entry_byte_offset)) |
| 146 | { | ||
| 147 | |||
| 148 | /* Use the previous information to start the search. */ | ||
| 149 | 1265139 | cluster = source_dir -> fx_dir_entry_last_search_cluster; | |
| 150 | |||
| 151 | /* Setup the relative cluster index to the saved relative cluster. */ | ||
| 152 | 1265139 | i = source_dir -> fx_dir_entry_last_search_relative_cluster; | |
| 153 | |||
| 154 | /* Clear the search cluster. It will be updated prior to successful return. */ | ||
| 155 | 1265139 | source_dir -> fx_dir_entry_last_search_cluster = 0; | |
| 156 | } | ||
| 157 | else | ||
| 158 | { | ||
| 159 | |||
| 160 | /* Nothing from the previous directory read, just setup the starting cluster to the | ||
| 161 | beginning of the sub-directory. */ | ||
| 162 | 295054 | cluster = source_dir -> fx_dir_entry_cluster; | |
| 163 | |||
| 164 | /* Setup the relative cluster index to zero. */ | ||
| 165 | 295054 | i = 0; | |
| 166 | } | ||
| 167 | } | ||
| 168 | else | ||
| 169 | { | ||
| 170 | |||
| 171 | /* No, setup the starting cluster to the FAT32 root cluster. */ | ||
| 172 | 70644862 | cluster = media_ptr -> fx_media_root_cluster_32; | |
| 173 | |||
| 174 | /* Setup the relative cluster index to zero. */ | ||
| 175 | 70644862 | i = 0; | |
| 176 | } | ||
| 177 | |||
| 178 | /* Loop to position to the appropriate cluster. */ | ||
| 179 |
2/2✓ Branch 26 → 19 taken 18326622 times.
✓ Branch 26 → 27 taken 72205028 times.
|
90531650 | while (i < relative_cluster) |
| 180 | { | ||
| 181 | |||
| 182 | /* Check the value of the new cluster - it must be a valid cluster number | ||
| 183 | or something is really wrong! */ | ||
| 184 |
4/4✓ Branch 19 → 20 taken 18326613 times.
✓ Branch 19 → 21 taken 9 times.
✓ Branch 20 → 21 taken 9 times.
✓ Branch 20 → 22 taken 18326604 times.
|
18326622 | if ((cluster < FX_FAT_ENTRY_START) || (cluster >= media_ptr -> fx_media_fat_reserved)) |
| 185 | { | ||
| 186 | |||
| 187 | /* Send error message back to caller. */ | ||
| 188 | 18 | return(FX_FILE_CORRUPT); | |
| 189 | } | ||
| 190 | |||
| 191 | /* Read the next cluster. */ | ||
| 192 | 18326604 | status = _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster); | |
| 193 | |||
| 194 | /* There is a potential for loop, but hardly anything can be done */ | ||
| 195 | |||
| 196 | /* Check for I/O error. */ | ||
| 197 |
2/2✓ Branch 23 → 24 taken 9 times.
✓ Branch 23 → 25 taken 18326595 times.
|
18326604 | if (status != FX_SUCCESS) |
| 198 | { | ||
| 199 | |||
| 200 | /* Return error code. */ | ||
| 201 | 9 | return(status); | |
| 202 | } | ||
| 203 | |||
| 204 | /* Setup the actual cluster. */ | ||
| 205 | 18326595 | cluster = next_cluster; | |
| 206 | |||
| 207 | /* Increment the relative cluster number. */ | ||
| 208 | 18326595 | i++; | |
| 209 | } | ||
| 210 | |||
| 211 | /* At this point, the directory data sector needs to be read. */ | ||
| 212 | 72205028 | logical_sector = ((ULONG)media_ptr -> fx_media_data_sector_start) + | |
| 213 | 72205028 | (((ULONG)cluster - FX_FAT_ENTRY_START) * | |
| 214 | 72205028 | ((ULONG)media_ptr -> fx_media_sectors_per_cluster)) + | |
| 215 | relative_sector; | ||
| 216 | |||
| 217 | /* Read the logical directory sector. */ | ||
| 218 | 72205028 | status = _fx_utility_logical_sector_read(media_ptr, (ULONG64) logical_sector, | |
| 219 | 72205028 | media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR); | |
| 220 | |||
| 221 | /* Determine if an error occurred. */ | ||
| 222 |
2/2✓ Branch 28 → 29 taken 1895 times.
✓ Branch 28 → 30 taken 72203133 times.
|
72205028 | if (status != FX_SUCCESS) |
| 223 | { | ||
| 224 | |||
| 225 | /* Return error code. */ | ||
| 226 | 1895 | return(status); | |
| 227 | } | ||
| 228 | |||
| 229 | /* Calculate the byte offset within this sector. */ | ||
| 230 | 72203133 | byte_offset = byte_offset % media_ptr -> fx_media_bytes_per_sector; | |
| 231 | } | ||
| 232 | else | ||
| 233 | { | ||
| 234 | |||
| 235 | /* Read the entry from the root directory. */ | ||
| 236 | |||
| 237 | /* Determine which sector the requested root directory entry is in. */ | ||
| 238 | 10881225 | logical_sector = (byte_offset / media_ptr -> fx_media_bytes_per_sector) + | |
| 239 | 10881225 | (ULONG)media_ptr -> fx_media_root_sector_start; | |
| 240 | |||
| 241 | /* Read the logical directory sector. */ | ||
| 242 | 10881225 | status = _fx_utility_logical_sector_read(media_ptr, (ULONG64) logical_sector, | |
| 243 | 10881225 | media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR); | |
| 244 | |||
| 245 | /* Determine if an error occurred. */ | ||
| 246 |
2/2✓ Branch 32 → 33 taken 4667 times.
✓ Branch 32 → 34 taken 10876558 times.
|
10881225 | if (status != FX_SUCCESS) |
| 247 | { | ||
| 248 | |||
| 249 | /* Return error code. */ | ||
| 250 | 4667 | return(status); | |
| 251 | } | ||
| 252 | |||
| 253 | /* Set the cluster and relative variables (not used in this case) to avoid any compiler | ||
| 254 | warnings. */ | ||
| 255 | 10876558 | relative_cluster = relative_sector = cluster = 0; | |
| 256 | |||
| 257 | /* Now calculate the byte offset into this sector. */ | ||
| 258 | 10876558 | byte_offset = byte_offset - | |
| 259 | 10876558 | ((logical_sector - (ULONG)media_ptr -> fx_media_root_sector_start) * | |
| 260 | 10876558 | media_ptr -> fx_media_bytes_per_sector); | |
| 261 | } | ||
| 262 | |||
| 263 | /* Setup a pointer into the buffer. */ | ||
| 264 | 83079691 | read_ptr = (UCHAR *)media_ptr -> fx_media_memory_buffer + (UINT)byte_offset; | |
| 265 | |||
| 266 | /* Save the logical sector and byte offset in the returned directory entry. */ | ||
| 267 | 83079691 | destination_ptr -> fx_dir_entry_log_sector = logical_sector; | |
| 268 | 83079691 | destination_ptr -> fx_dir_entry_byte_offset = byte_offset; | |
| 269 | |||
| 270 | /* Clear the short file name information. */ | ||
| 271 | 83079691 | destination_ptr -> fx_dir_entry_long_name_shorted = 0; | |
| 272 | 83079691 | destination_ptr -> fx_dir_entry_short_name[0] = 0; | |
| 273 | |||
| 274 | /* Setup short name pointer. */ | ||
| 275 | 83079691 | short_name_ptr = destination_ptr -> fx_dir_entry_name; | |
| 276 | |||
| 277 | /* Check if long file name exists. */ | ||
| 278 | 83079691 | get_short_name = 0; | |
| 279 |
4/4✓ Branch 35 → 36 taken 622731 times.
✓ Branch 35 → 86 taken 82456960 times.
✓ Branch 36 → 37 taken 611335 times.
✓ Branch 36 → 86 taken 11396 times.
|
83079691 | if ((*(read_ptr + 11) == (UCHAR)FX_LONG_NAME) && (*read_ptr != (UCHAR)FX_DIR_ENTRY_FREE)) |
| 280 | { | ||
| 281 | |||
| 282 | /* Collate the long name. */ | ||
| 283 | |||
| 284 | /* Pickup the file name length. */ | ||
| 285 | 611335 | i = (((UINT)(*read_ptr & (UCHAR)0x1f) - 1) * FX_LONG_NAME_ENTRY_LEN) & 0xFFFFFFFF; | |
| 286 | |||
| 287 | /* Save the number of LFN entries. */ | ||
| 288 | 611335 | number_of_lfns = (UINT)(*read_ptr & (UCHAR)0x1f); | |
| 289 | |||
| 290 | /* Check the file name size. */ | ||
| 291 |
2/2✓ Branch 37 → 38 taken 303 times.
✓ Branch 37 → 39 taken 611032 times.
|
611335 | if (i >= (FX_MAX_LONG_NAME_LEN - 1)) |
| 292 | { | ||
| 293 | |||
| 294 | /* Name is too big, shorten it. */ | ||
| 295 | 303 | get_short_name = 1; | |
| 296 | 303 | destination_ptr -> fx_dir_entry_long_name_shorted = (UINT)(*read_ptr & (UCHAR)0x1f); | |
| 297 | } | ||
| 298 | else | ||
| 299 | { | ||
| 300 | |||
| 301 | /* Size of name is fine, save pointer to short file name. */ | ||
| 302 | 611032 | short_name_ptr = destination_ptr -> fx_dir_entry_short_name; | |
| 303 | |||
| 304 | /* Loop to make sure the long file name is NULL terminated. */ | ||
| 305 | 611032 | j = i + FX_LONG_NAME_ENTRY_LEN + 1; | |
| 306 | do | ||
| 307 | { | ||
| 308 | /* Place a NULL in the long name. */ | ||
| 309 | 8542323 | destination_ptr -> fx_dir_entry_name[i] = 0; | |
| 310 | |||
| 311 | /* Position to the next entry. */ | ||
| 312 | 8542323 | i++; | |
| 313 |
4/4✓ Branch 40 → 41 taken 7933716 times.
✓ Branch 40 → 43 taken 608607 times.
✓ Branch 41 → 42 taken 7931291 times.
✓ Branch 41 → 43 taken 2425 times.
|
8542323 | } while ((i < j) && (i < FX_MAX_LONG_NAME_LEN)); |
| 314 | } | ||
| 315 | |||
| 316 | /* Loop to pickup the rest of the name. */ | ||
| 317 | do | ||
| 318 | { | ||
| 319 | |||
| 320 | /* Get the lower 5 bit containing the cardinality. */ | ||
| 321 | 824363 | card = (UINT)(*read_ptr & (UCHAR)0x1f) - 1; | |
| 322 | |||
| 323 | /* For simplicity no checksum or cardinality checking is done */ | ||
| 324 |
2/2✓ Branch 44 → 45 taken 810420 times.
✓ Branch 44 → 63 taken 13943 times.
|
824363 | if (get_short_name == 0) |
| 325 | { | ||
| 326 | |||
| 327 | /* Loop to pickup name. */ | ||
| 328 |
2/2✓ Branch 62 → 46 taken 12965250 times.
✓ Branch 62 → 63 taken 810138 times.
|
13775388 | for (i = 1, j = 0; i < FX_DIR_ENTRY_SIZE; i += 2) |
| 329 | { | ||
| 330 | |||
| 331 |
4/4✓ Branch 46 → 47 taken 12154836 times.
✓ Branch 46 → 48 taken 810414 times.
✓ Branch 47 → 48 taken 810138 times.
✓ Branch 47 → 49 taken 11344698 times.
|
12965250 | if ((i == 11) || (i == 26)) |
| 332 | { | ||
| 333 | 1620552 | continue; | |
| 334 | } | ||
| 335 | |||
| 336 | /* i = 12, 27 is not generated due to +=2 */ | ||
| 337 |
2/2✓ Branch 49 → 50 taken 810414 times.
✓ Branch 49 → 51 taken 10534284 times.
|
11344698 | if (i == 13) |
| 338 | { | ||
| 339 | 810414 | i = 12; | |
| 340 | 810414 | continue; /* this time next unicode is byte offset 14*/ | |
| 341 | } | ||
| 342 | |||
| 343 | /* Determine if there is an actual unicode character present. */ | ||
| 344 |
2/2✓ Branch 51 → 52 taken 5437700 times.
✓ Branch 51 → 55 taken 5096584 times.
|
10534284 | if (read_ptr[i + 1]) |
| 345 | { | ||
| 346 | |||
| 347 | /* Extended byte is non-zero, make sure both bytes of the unicode entry are not | ||
| 348 | all ones, since this is a normal case. */ | ||
| 349 |
4/4✓ Branch 52 → 53 taken 5392684 times.
✓ Branch 52 → 54 taken 45016 times.
✓ Branch 53 → 54 taken 81 times.
✓ Branch 53 → 55 taken 5392603 times.
|
5437700 | if ((read_ptr[i + 1] != (UCHAR)0xFF) || (read_ptr[i] != (UCHAR)0xFF)) |
| 350 | { | ||
| 351 | |||
| 352 | /* Name is an actual unicode name, shorten it. */ | ||
| 353 | 45097 | get_short_name = 1; | |
| 354 | |||
| 355 | /* Save the number of directory entries the LFN has. This will be | ||
| 356 | used later when updating the 8.3 portion of the LFN. */ | ||
| 357 | 45097 | destination_ptr -> fx_dir_entry_long_name_shorted = number_of_lfns; | |
| 358 | |||
| 359 | /* Setup short name pointer. */ | ||
| 360 | 45097 | short_name_ptr = destination_ptr -> fx_dir_entry_name; | |
| 361 | } | ||
| 362 | } | ||
| 363 | |||
| 364 | /* Determine if the character is NULL. */ | ||
| 365 |
4/4✓ Branch 55 → 56 taken 9922002 times.
✓ Branch 55 → 57 taken 612282 times.
✓ Branch 56 → 57 taken 5392711 times.
✓ Branch 56 → 58 taken 4529291 times.
|
10534284 | if ((read_ptr[i] == FX_NULL) || (read_ptr[i] == (UCHAR)0xFF)) |
| 366 | { | ||
| 367 | 6004993 | continue; | |
| 368 | } | ||
| 369 | |||
| 370 | /* Determine if the name is too big. */ | ||
| 371 |
2/2✓ Branch 58 → 59 taken 282 times.
✓ Branch 58 → 60 taken 4529009 times.
|
4529291 | if ((card * 13 + j) >= (FX_MAX_LONG_NAME_LEN - 1)) |
| 372 | { | ||
| 373 | |||
| 374 | /* Name is actually too big, shorten it. */ | ||
| 375 | 282 | get_short_name = 1; | |
| 376 | |||
| 377 | /* Save the number of directory entries the LFN has. This will be | ||
| 378 | used later when updating the 8.3 portion of the LFN. */ | ||
| 379 | 282 | destination_ptr -> fx_dir_entry_long_name_shorted = number_of_lfns; | |
| 380 | |||
| 381 | /* Also reposition the short name pointer. */ | ||
| 382 | 282 | short_name_ptr = destination_ptr -> fx_dir_entry_name; | |
| 383 | |||
| 384 | 282 | break; | |
| 385 | } | ||
| 386 | |||
| 387 | /* Each entry contains 13 unicode and first byte ASCII, second byte is extended. */ | ||
| 388 | 4529009 | destination_ptr -> fx_dir_entry_name[13 * card + j] = (CHAR)read_ptr[i]; | |
| 389 | |||
| 390 | 4529009 | j++; | |
| 391 | } | ||
| 392 | } | ||
| 393 | |||
| 394 | /* Determine if a new sector needs to be read. */ | ||
| 395 |
2/2✓ Branch 63 → 64 taken 139072 times.
✓ Branch 63 → 82 taken 685291 times.
|
824363 | if (byte_offset + FX_DIR_ENTRY_SIZE >= media_ptr -> fx_media_bytes_per_sector) |
| 396 | { | ||
| 397 | |||
| 398 | /* Determine if a sub-directory or FAT32 root directory is specified. */ | ||
| 399 |
4/4✓ Branch 64 → 65 taken 73350 times.
✓ Branch 64 → 66 taken 65722 times.
✓ Branch 65 → 66 taken 31457 times.
✓ Branch 65 → 76 taken 41893 times.
|
139072 | if ((source_dir) || (media_ptr -> fx_media_32_bit_FAT)) |
| 400 | { | ||
| 401 | |||
| 402 | /* Determine the next sector of the directory entry. */ | ||
| 403 |
2/2✓ Branch 66 → 67 taken 38914 times.
✓ Branch 66 → 68 taken 58265 times.
|
97179 | if (relative_sector < (media_ptr -> fx_media_sectors_per_cluster - 1)) |
| 404 | { | ||
| 405 | |||
| 406 | /* More sectors in this cluster. */ | ||
| 407 | |||
| 408 | /* Simply increment the logical sector. */ | ||
| 409 | 38914 | logical_sector++; | |
| 410 | |||
| 411 | /* Increment the relative sector. */ | ||
| 412 | 38914 | relative_sector++; | |
| 413 | } | ||
| 414 | else | ||
| 415 | { | ||
| 416 | |||
| 417 | /* We need to move to the next cluster. */ | ||
| 418 | |||
| 419 | /* Pickup the next cluster. */ | ||
| 420 | 58265 | status = _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster); | |
| 421 | |||
| 422 | /* Check for I/O error. */ | ||
| 423 |
2/2✓ Branch 69 → 70 taken 9 times.
✓ Branch 69 → 71 taken 58256 times.
|
58265 | if (status != FX_SUCCESS) |
| 424 | { | ||
| 425 | |||
| 426 | /* Return error code. */ | ||
| 427 | 9 | return(status); | |
| 428 | } | ||
| 429 | |||
| 430 | /* Copy next cluster to the current cluster. */ | ||
| 431 | 58256 | cluster = next_cluster; | |
| 432 | |||
| 433 | /* Check the value of the new cluster - it must be a valid cluster number | ||
| 434 | or something is really wrong! */ | ||
| 435 |
4/4✓ Branch 71 → 72 taken 58247 times.
✓ Branch 71 → 73 taken 9 times.
✓ Branch 72 → 73 taken 24 times.
✓ Branch 72 → 74 taken 58223 times.
|
58256 | if ((cluster < FX_FAT_ENTRY_START) || (cluster >= media_ptr -> fx_media_fat_reserved)) |
| 436 | { | ||
| 437 | |||
| 438 | /* Send error message back to caller. */ | ||
| 439 | 33 | return(FX_FILE_CORRUPT); | |
| 440 | } | ||
| 441 | |||
| 442 | /* Now increment the relative cluster. */ | ||
| 443 | 58223 | relative_cluster++; | |
| 444 | |||
| 445 | /* Setup the relative sector (this is zero for subsequent cluster. */ | ||
| 446 | 58223 | relative_sector = 0; | |
| 447 | |||
| 448 | /* Calculate the next logical sector. */ | ||
| 449 | 58223 | logical_sector = ((ULONG)media_ptr -> fx_media_data_sector_start) + | |
| 450 | 58223 | (((ULONG)cluster - FX_FAT_ENTRY_START) * | |
| 451 | 58223 | ((ULONG)media_ptr -> fx_media_sectors_per_cluster)); | |
| 452 | } | ||
| 453 | } | ||
| 454 | else | ||
| 455 | { | ||
| 456 | |||
| 457 | /* Non-FAT 32 root directory. */ | ||
| 458 | |||
| 459 | /* Advance to the next sector. */ | ||
| 460 | 41893 | logical_sector++; | |
| 461 | |||
| 462 | /* Determine if the logical sector is valid. */ | ||
| 463 |
2/2✓ Branch 76 → 77 taken 41 times.
✓ Branch 76 → 78 taken 41852 times.
|
41893 | if (logical_sector >= (ULONG)(media_ptr -> fx_media_root_sector_start + media_ptr -> fx_media_root_sectors)) |
| 464 | { | ||
| 465 | |||
| 466 | /* Trying to read past root directory - send error message back to caller. */ | ||
| 467 | 41 | return(FX_FILE_CORRUPT); | |
| 468 | } | ||
| 469 | } | ||
| 470 | |||
| 471 | /* Read the new sector. */ | ||
| 472 | 138989 | status = _fx_utility_logical_sector_read(media_ptr, (ULONG64) logical_sector, | |
| 473 | 138989 | media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR); | |
| 474 | |||
| 475 | /* Check I/O status. */ | ||
| 476 |
2/2✓ Branch 79 → 80 taken 12 times.
✓ Branch 79 → 81 taken 138977 times.
|
138989 | if (status != FX_SUCCESS) |
| 477 | { | ||
| 478 | 12 | return(status); | |
| 479 | } | ||
| 480 | |||
| 481 | /* Set the byte offset to 0 for new sector. */ | ||
| 482 | 138977 | byte_offset = 0; | |
| 483 | } | ||
| 484 | else | ||
| 485 | { | ||
| 486 | |||
| 487 | /* Calculate the new byte offset. */ | ||
| 488 | 685291 | byte_offset += FX_DIR_ENTRY_SIZE; | |
| 489 | } | ||
| 490 | |||
| 491 | /* Calculate the next read pointer. */ | ||
| 492 | 824268 | read_ptr = (UCHAR *)media_ptr -> fx_media_memory_buffer + (UINT) byte_offset; | |
| 493 | |||
| 494 | /* Move to the next entry. */ | ||
| 495 | 824268 | entry++; | |
| 496 |
2/2✓ Branch 83 → 84 taken 213028 times.
✓ Branch 83 → 85 taken 611240 times.
|
824268 | } while (card > 0); |
| 497 | |||
| 498 | /* Set flag indicating long file name is present. */ | ||
| 499 | 611240 | destination_ptr -> fx_dir_entry_long_name_present = 1; | |
| 500 | } | ||
| 501 | else | ||
| 502 | { | ||
| 503 | /* No long file name is present. */ | ||
| 504 | 82468356 | get_short_name = 1; | |
| 505 | } | ||
| 506 | |||
| 507 | /* Determine if we need to clear the long name flag. */ | ||
| 508 |
2/2✓ Branch 87 → 88 taken 82506288 times.
✓ Branch 87 → 89 taken 573308 times.
|
83079596 | if (get_short_name == 1) |
| 509 | { | ||
| 510 | |||
| 511 | /* Clear the long name flag. */ | ||
| 512 | 82506288 | destination_ptr -> fx_dir_entry_long_name_present = 0; | |
| 513 | } | ||
| 514 | |||
| 515 | /* Pickup the short file name. */ | ||
| 516 | 83079596 | short_name_ptr[0] = 0; | |
| 517 | 83079596 | dotflag = 0; | |
| 518 |
2/2✓ Branch 105 → 90 taken 900936490 times.
✓ Branch 105 → 106 taken 81783385 times.
|
982719875 | for (i = 0, j = 0; i < (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE); i++) |
| 519 | { | ||
| 520 | |||
| 521 | /* Check for a NULL. */ | ||
| 522 |
2/2✓ Branch 90 → 91 taken 1296211 times.
✓ Branch 90 → 92 taken 899640279 times.
|
900936490 | if ((CHAR)read_ptr[i] == 0) |
| 523 | { | ||
| 524 | 1296211 | break; | |
| 525 | } | ||
| 526 | |||
| 527 | /* Check for a dot. This happens for the first two directory entries, no | ||
| 528 | extra dot is needed. */ | ||
| 529 |
2/2✓ Branch 92 → 93 taken 461222 times.
✓ Branch 92 → 94 taken 899179057 times.
|
899640279 | if ((CHAR)read_ptr[i] == '.') |
| 530 | { | ||
| 531 | 461222 | dotflag = 2; | |
| 532 | } | ||
| 533 | |||
| 534 | /* Check for a space. */ | ||
| 535 |
2/2✓ Branch 94 → 95 taken 219866215 times.
✓ Branch 94 → 98 taken 679774064 times.
|
899640279 | if ((CHAR)read_ptr[i] == ' ') |
| 536 | { | ||
| 537 | /* Put a dot if a character comes after space. */ | ||
| 538 |
2/2✓ Branch 95 → 96 taken 81472579 times.
✓ Branch 95 → 97 taken 138393636 times.
|
219866215 | if (dotflag == 0) |
| 539 | { | ||
| 540 | 81472579 | dotflag = 1; | |
| 541 | } | ||
| 542 | 219866215 | continue; | |
| 543 | } | ||
| 544 | |||
| 545 | /* Check for the main short file name size. */ | ||
| 546 |
2/2✓ Branch 98 → 99 taken 79184625 times.
✓ Branch 98 → 101 taken 600589439 times.
|
679774064 | if (i == FX_DIR_NAME_SIZE) |
| 547 | { | ||
| 548 | /* Check to see if we need to insert a dot. */ | ||
| 549 |
2/2✓ Branch 99 → 100 taken 3311 times.
✓ Branch 99 → 101 taken 79181314 times.
|
79184625 | if (dotflag == 0) |
| 550 | { | ||
| 551 | 3311 | dotflag = 1; | |
| 552 | } | ||
| 553 | } | ||
| 554 | |||
| 555 | /* Check to see if we need to add a dot. */ | ||
| 556 |
2/2✓ Branch 101 → 102 taken 79184904 times.
✓ Branch 101 → 103 taken 600589160 times.
|
679774064 | if (dotflag == 1) |
| 557 | { | ||
| 558 | /* Add dot to short file name. */ | ||
| 559 | 79184904 | short_name_ptr[j++] = '.'; | |
| 560 | 79184904 | dotflag = 2; /* no more dot for spaces */ | |
| 561 | } | ||
| 562 | |||
| 563 | /* Copy a character. */ | ||
| 564 | 679774064 | short_name_ptr[j] = (CHAR)read_ptr[i]; | |
| 565 | |||
| 566 | /* Increment size. */ | ||
| 567 | 679774064 | j++; | |
| 568 | } | ||
| 569 | |||
| 570 | /* Determine if a long file name is present and its associated short file | ||
| 571 | name is actually free. */ | ||
| 572 |
4/4✓ Branch 106 → 107 taken 573308 times.
✓ Branch 106 → 109 taken 82506288 times.
✓ Branch 107 → 108 taken 153 times.
✓ Branch 107 → 109 taken 573155 times.
|
83079596 | if ((destination_ptr -> fx_dir_entry_long_name_present) && (((UCHAR)short_name_ptr[0]) == (UCHAR)FX_DIR_ENTRY_FREE)) |
| 573 | { | ||
| 574 | |||
| 575 | /* Yes, the short file name is really free even though long file name entries directly precede it. | ||
| 576 | In this case, simply place the free directory marker at the front of the long file name. */ | ||
| 577 | 153 | destination_ptr -> fx_dir_entry_name[0] = (CHAR)FX_DIR_ENTRY_FREE; | |
| 578 | 153 | short_name_ptr[0] = (CHAR)0; | |
| 579 | } | ||
| 580 | |||
| 581 | /* Determine if the short name pointer is NULL while the read pointer is | ||
| 582 | non-NULL. */ | ||
| 583 |
4/4✓ Branch 109 → 110 taken 1285004 times.
✓ Branch 109 → 114 taken 81794592 times.
✓ Branch 110 → 111 taken 54 times.
✓ Branch 110 → 114 taken 1284950 times.
|
83079596 | if ((short_name_ptr[0] == 0) && (read_ptr[0] == ' ')) |
| 584 | { | ||
| 585 | |||
| 586 | /* This condition can occur with an all blank volume name. Simply | ||
| 587 | copy the volume name to the short name in this case. */ | ||
| 588 |
2/2✓ Branch 113 → 112 taken 594 times.
✓ Branch 113 → 114 taken 54 times.
|
648 | for (j = 0; j < (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE); j++) |
| 589 | { | ||
| 590 | |||
| 591 | /* Copy a byte of the volume name. */ | ||
| 592 | 594 | short_name_ptr[j] = (CHAR)read_ptr[j]; | |
| 593 | } | ||
| 594 | } | ||
| 595 | |||
| 596 | /* Set end of string to null. */ | ||
| 597 | 83079596 | short_name_ptr[j] = 0; | |
| 598 | |||
| 599 | /* Load up the destination directory entry. */ | ||
| 600 | 83079596 | read_ptr += (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE); | |
| 601 | |||
| 602 | /* Copy the attribute into the destination. */ | ||
| 603 | 83079596 | destination_ptr -> fx_dir_entry_attributes = *read_ptr++; | |
| 604 | |||
| 605 | /* Pickup the reserved byte. */ | ||
| 606 | 83079596 | destination_ptr -> fx_dir_entry_reserved = *read_ptr++; | |
| 607 | |||
| 608 | /* Check for an undocumented NT file name feature for optimizing the storage | ||
| 609 | of all lower case file names that otherwise are valid 8.3 file names. The | ||
| 610 | following reserved bit definitions are present: | ||
| 611 | |||
| 612 | BIT3 - set if 8.3 is all in lower case and no extended filename. | ||
| 613 | BIT4 - set for file, clear for directory entry if no extended filename. | ||
| 614 | |||
| 615 | This is true for all NT systems. Prior to NT follows MSDOS FAT documentation and | ||
| 616 | is set to 0x00, all bits cleared. Therefore if BIT3 is set force lowercase. */ | ||
| 617 |
4/4✓ Branch 114 → 115 taken 82506288 times.
✓ Branch 114 → 123 taken 573308 times.
✓ Branch 115 → 116 taken 504 times.
✓ Branch 115 → 123 taken 82505784 times.
|
83079596 | if ((get_short_name) && (destination_ptr -> fx_dir_entry_reserved & 0x08)) |
| 618 | { | ||
| 619 | |||
| 620 | /* Microsoft undocumented NT file name feature... convert short name to lower | ||
| 621 | case. */ | ||
| 622 |
4/4✓ Branch 121 → 122 taken 4644 times.
✓ Branch 121 → 123 taken 216 times.
✓ Branch 122 → 117 taken 4356 times.
✓ Branch 122 → 123 taken 288 times.
|
4860 | for (j = 0; j <= (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE) && (short_name_ptr[j] != 0x00); j++) |
| 623 | { | ||
| 624 | |||
| 625 | /* Determine if an upper case character is present. */ | ||
| 626 |
4/4✓ Branch 117 → 118 taken 3906 times.
✓ Branch 117 → 120 taken 450 times.
✓ Branch 118 → 119 taken 2232 times.
✓ Branch 118 → 120 taken 1674 times.
|
4356 | if ((short_name_ptr[j] >= 'A') && (short_name_ptr[j] <= 'Z')) |
| 627 | { | ||
| 628 | |||
| 629 | /* Yes, an upper case character is present. Force it to lower case. */ | ||
| 630 | 2232 | short_name_ptr[j] = (CHAR)(short_name_ptr[j] + 32); | |
| 631 | } | ||
| 632 | } | ||
| 633 | } | ||
| 634 | |||
| 635 | /* Pickup the created time in milliseconds. */ | ||
| 636 | 83079596 | destination_ptr -> fx_dir_entry_created_time_ms = *read_ptr++; | |
| 637 | |||
| 638 | /* Pickup the created time. */ | ||
| 639 | 83079596 | destination_ptr -> fx_dir_entry_created_time = _fx_utility_16_unsigned_read(read_ptr); | |
| 640 | 83079596 | read_ptr = read_ptr + 2; /* Always 2 bytes */ | |
| 641 | |||
| 642 | /* Pickup the created date. */ | ||
| 643 | 83079596 | destination_ptr -> fx_dir_entry_created_date = _fx_utility_16_unsigned_read(read_ptr); | |
| 644 | 83079596 | read_ptr = read_ptr + 2; /* Always 2 bytes */ | |
| 645 | |||
| 646 | /* Pickup the last accessed date. */ | ||
| 647 | 83079596 | destination_ptr -> fx_dir_entry_last_accessed_date = _fx_utility_16_unsigned_read(read_ptr); | |
| 648 | 83079596 | read_ptr = read_ptr + 2; /* Always 2 bytes */ | |
| 649 | |||
| 650 | /* read the upper 2 bytes of starting cluster - required only for 32 bit FAT */ | ||
| 651 |
2/2✓ Branch 126 → 127 taken 71353152 times.
✓ Branch 126 → 129 taken 11726444 times.
|
83079596 | if (media_ptr -> fx_media_32_bit_FAT) |
| 652 | { | ||
| 653 | |||
| 654 | /* FAT32 only. */ | ||
| 655 | 71353152 | destination_ptr -> fx_dir_entry_cluster = _fx_utility_16_unsigned_read(read_ptr); | |
| 656 | 71353152 | destination_ptr -> fx_dir_entry_cluster <<= 16; | |
| 657 | } | ||
| 658 | else | ||
| 659 | { | ||
| 660 | /* Not required for non FAT32. */ | ||
| 661 | 11726444 | destination_ptr -> fx_dir_entry_cluster = 0; | |
| 662 | } | ||
| 663 | |||
| 664 | /* Advance the read pointer. */ | ||
| 665 | 83079596 | read_ptr = read_ptr + 2; /* Always 2 bytes */ | |
| 666 | |||
| 667 | /* Copy the time into the destination. */ | ||
| 668 | 83079596 | destination_ptr -> fx_dir_entry_time = _fx_utility_16_unsigned_read(read_ptr); | |
| 669 | 83079596 | read_ptr = read_ptr + 2; /* Always 2 bytes */ | |
| 670 | |||
| 671 | /* Copy the date into the destination. */ | ||
| 672 | 83079596 | destination_ptr -> fx_dir_entry_date = _fx_utility_16_unsigned_read(read_ptr); | |
| 673 | 83079596 | read_ptr = read_ptr + 2; /* Always 2 bytes */ | |
| 674 | |||
| 675 | /* Copy the starting cluster into the destination. */ | ||
| 676 | 83079596 | destination_ptr -> fx_dir_entry_cluster += _fx_utility_16_unsigned_read(read_ptr); | |
| 677 | 83079596 | read_ptr = read_ptr + 2; /* Always 2 bytes */ | |
| 678 | |||
| 679 | /* Copy the file size into the destination. */ | ||
| 680 | 83079596 | destination_ptr -> fx_dir_entry_file_size = _fx_utility_32_unsigned_read(read_ptr); | |
| 681 | |||
| 682 | /* Clear the destination search specific fields. */ | ||
| 683 | 83079596 | destination_ptr -> fx_dir_entry_last_search_cluster = 0; | |
| 684 | 83079596 | destination_ptr -> fx_dir_entry_last_search_relative_cluster = 0; | |
| 685 | 83079596 | destination_ptr -> fx_dir_entry_last_search_log_sector = 0; | |
| 686 | 83079596 | destination_ptr -> fx_dir_entry_last_search_byte_offset = 0; | |
| 687 | |||
| 688 | /* Remember the entry number. */ | ||
| 689 | 83079596 | destination_ptr -> fx_dir_entry_number = entry; | |
| 690 | |||
| 691 | /* Return entry number. */ | ||
| 692 | 83079596 | *entry_ptr = entry; | |
| 693 | |||
| 694 | /* Determine if we should remember the last cluster and relative cluster. */ | ||
| 695 |
2/2✓ Branch 134 → 135 taken 1558247 times.
✓ Branch 134 → 136 taken 81521349 times.
|
83079596 | if (source_dir) |
| 696 | { | ||
| 697 | |||
| 698 | /* Yes, remember the last cluster and relative cluster for a subsequent call | ||
| 699 | to read a directory entry. */ | ||
| 700 | 1558247 | source_dir -> fx_dir_entry_last_search_cluster = cluster; | |
| 701 | 1558247 | source_dir -> fx_dir_entry_last_search_relative_cluster = relative_cluster; | |
| 702 | |||
| 703 | /* Also remember several other items that are unique to the directory... just to verify that the | ||
| 704 | search information can be used. */ | ||
| 705 | 1558247 | source_dir -> fx_dir_entry_last_search_log_sector = source_dir -> fx_dir_entry_log_sector; | |
| 706 | 1558247 | source_dir -> fx_dir_entry_last_search_byte_offset = source_dir -> fx_dir_entry_byte_offset; | |
| 707 | } | ||
| 708 | |||
| 709 | /* Return success to the caller. */ | ||
| 710 | 83079596 | return(FX_SUCCESS); | |
| 711 | } | ||
| 712 | |||
| 713 | |||
| 714 | |||
| 715 |