GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: fx_directory_entry_read.c Lines: 188 188 100.0 %
Date: 2024-01-10 21:53:23 Branches: 128 128 100.0 %

Line Branch Exec Source
1
/**************************************************************************/
2
/*                                                                        */
3
/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
4
/*                                                                        */
5
/*       This software is licensed under the Microsoft Software License   */
6
/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
7
/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
8
/*       and in the root directory of this software.                      */
9
/*                                                                        */
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
#ifdef FX_ENABLE_EXFAT
33
#include "fx_directory_exFAT.h"
34
35
36
37
#endif /* FX_ENABLE_EXFAT */
38
39
40
/**************************************************************************/
41
/*                                                                        */
42
/*  FUNCTION                                               RELEASE        */
43
/*                                                                        */
44
/*    _fx_directory_entry_read                            PORTABLE C      */
45
/*                                                           6.1          */
46
/*  AUTHOR                                                                */
47
/*                                                                        */
48
/*    William E. Lamie, Microsoft Corporation                             */
49
/*                                                                        */
50
/*  DESCRIPTION                                                           */
51
/*                                                                        */
52
/*    This function reads the supplied directory entry from the supplied  */
53
/*    source directory.  If the supplied directory entry is NULL, then    */
54
/*    the root directory is assumed.                                      */
55
/*                                                                        */
56
/*  INPUT                                                                 */
57
/*                                                                        */
58
/*    media_ptr                             Media control block pointer   */
59
/*    source_dir                            Source directory entry        */
60
/*    entry_ptr                             Directory entry number        */
61
/*    destination_ptr                       Pointer to destination for    */
62
/*                                            the directory entry         */
63
/*                                                                        */
64
/*  OUTPUT                                                                */
65
/*                                                                        */
66
/*    return status                                                       */
67
/*    *entry_ptr should point to the 8:3 entry if it is a long name       */
68
/*                                                                        */
69
/*  CALLS                                                                 */
70
/*                                                                        */
71
/*    _fx_directory_exFAT_entry_read        Read exFAT entries            */
72
/*    _fx_utility_FAT_entry_read            Read a FAT entry              */
73
/*    _fx_utility_logical_sector_read       Read directory sector         */
74
/*    _fx_utility_16_unsigned_read          Read a UINT from memory       */
75
/*    _fx_utility_32_unsigned_read          Read a ULONG from memory      */
76
/*                                                                        */
77
/*  CALLED BY                                                             */
78
/*                                                                        */
79
/*    FileX System Functions                                              */
80
/*                                                                        */
81
/*  RELEASE HISTORY                                                       */
82
/*                                                                        */
83
/*    DATE              NAME                      DESCRIPTION             */
84
/*                                                                        */
85
/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
86
/*  09-30-2020     William E. Lamie         Modified comment(s),          */
87
/*                                            resulting in version 6.1    */
88
/*                                                                        */
89
/**************************************************************************/
90
#ifdef FX_ENABLE_EXFAT
91
UINT  _fx_directory_entry_read_FAT(FX_MEDIA *media_ptr, FX_DIR_ENTRY *source_dir,
92
                                   ULONG *entry_ptr, FX_DIR_ENTRY *destination_ptr)
93
#else
94
2418163
UINT  _fx_directory_entry_read(FX_MEDIA *media_ptr, FX_DIR_ENTRY *source_dir,
95
                               ULONG *entry_ptr, FX_DIR_ENTRY *destination_ptr)
96
#endif /* FX_ENABLE_EXFAT */
97
{
98
99
UINT   i, j, card, dotflag, get_short_name;
100
UINT   number_of_lfns;
101
UINT   status;
102
2418163
ULONG  cluster, next_cluster = 0;
103
UINT   relative_cluster;
104
UINT   relative_sector;
105
ULONG  logical_sector;
106
ULONG  byte_offset;
107
ULONG  bytes_per_cluster;
108
UCHAR *read_ptr;
109
CHAR  *short_name_ptr;
110
2418163
ULONG  entry = *entry_ptr;
111
112
113
#ifndef FX_MEDIA_STATISTICS_DISABLE
114
115
    /* Increment the number of directory entry read requests.  */
116
2418163
    media_ptr -> fx_media_directory_entry_reads++;
117
#endif
118
119
    /* Extended port-specific processing macro, which is by default defined to white space.  */
120

2418163
    FX_DIRECTORY_ENTRY_READ_EXTENSION
121
122
    /* If trace is enabled, insert this event into the trace buffer.  */
123
    FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_DIR_ENTRY_READ, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
124
125
    /* Calculate the byte offset of this directory entry.  */
126
2418162
    byte_offset =  entry * FX_DIR_ENTRY_SIZE;
127
128
    /* Determine if a sub-directory or FAT32 root directory is specified.  */
129
#ifdef FX_ENABLE_EXFAT
130
    if ((source_dir) || (media_ptr -> fx_media_FAT_type == FX_FAT32))
131
#else
132

2418162
    if ((source_dir) || (media_ptr -> fx_media_32_bit_FAT))
133
#endif
134
    {
135
136
        /* Yes, a sub-directory is present.  */
137
138
        /* Calculate the number of bytes per cluster.  */
139
1210972
        bytes_per_cluster =  ((ULONG)media_ptr -> fx_media_bytes_per_sector) *
140
1210972
            ((ULONG)media_ptr -> fx_media_sectors_per_cluster);
141
142
        /* Check for invalid value.  */
143
1210972
        if (bytes_per_cluster == 0)
144
        {
145
146
            /* Invalid media, return error.  */
147
3
            return(FX_MEDIA_INVALID);
148
        }
149
150
        /* Now determine the relative cluster in the sub-directory file.  */
151
1210969
        relative_cluster =   (UINT)(byte_offset / bytes_per_cluster);
152
153
        /* Calculate the byte offset within the cluster.  */
154
1210969
        byte_offset =  byte_offset % bytes_per_cluster;
155
156
        /* Now figure out the relative sector within the cluster.  */
157
1210969
        relative_sector =    (UINT)(byte_offset / ((ULONG)media_ptr -> fx_media_bytes_per_sector));
158
159
        /* Read the directory sector into the internal memory buffer.  */
160
161
        /* Determine if there is a sub-directory.  */
162
1210969
        if (source_dir)
163
        {
164
165
            /* Determine if this source directory has valid information from the previous call.  */
166
164165
            if ((source_dir -> fx_dir_entry_last_search_cluster) &&
167
132720
                (source_dir -> fx_dir_entry_last_search_relative_cluster <= relative_cluster) &&
168
132719
                (source_dir -> fx_dir_entry_last_search_log_sector == source_dir -> fx_dir_entry_log_sector) &&
169
132718
                (source_dir -> fx_dir_entry_last_search_byte_offset == source_dir -> fx_dir_entry_byte_offset))
170
            {
171
172
                /* Use the previous information to start the search.  */
173
132717
                cluster =  source_dir -> fx_dir_entry_last_search_cluster;
174
175
                /* Setup the relative cluster index to the saved relative cluster.  */
176
132717
                i =  source_dir -> fx_dir_entry_last_search_relative_cluster;
177
178
                /* Clear the search cluster.  It will be updated prior to successful return.  */
179
132717
                source_dir -> fx_dir_entry_last_search_cluster =  0;
180
            }
181
            else
182
            {
183
184
                /* Nothing from the previous directory read, just setup the starting cluster to the
185
                   beginning of the sub-directory.  */
186
31448
                cluster =  source_dir -> fx_dir_entry_cluster;
187
188
                /* Setup the relative cluster index to zero.  */
189
31448
                i =  0;
190
            }
191
        }
192
        else
193
        {
194
195
            /* No, setup the starting cluster to the FAT32 root cluster.  */
196
1046804
            cluster =  media_ptr -> fx_media_root_cluster_32;
197
198
            /* Setup the relative cluster index to zero.  */
199
1046804
            i =  0;
200
        }
201
202
        /* Loop to position to the appropriate cluster.  */
203
3247450
        while (i < relative_cluster)
204
        {
205
206
            /* Check the value of the new cluster - it must be a valid cluster number
207
               or something is really wrong!  */
208

2036484
            if ((cluster < FX_FAT_ENTRY_START) || (cluster >= media_ptr -> fx_media_fat_reserved))
209
            {
210
211
                /* Send error message back to caller.  */
212
2
                return(FX_FILE_CORRUPT);
213
            }
214
215
            /* Read the next cluster.  */
216
2036482
            status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
217
218
            /* There is a potential for loop, but hardly anything can be done */
219
220
            /* Check for I/O error.  */
221
2036482
            if (status != FX_SUCCESS)
222
            {
223
224
                /* Return error code.  */
225
1
                return(status);
226
            }
227
228
            /* Setup the actual cluster.  */
229
2036481
            cluster = next_cluster;
230
231
            /* Increment the relative cluster number.  */
232
2036481
            i++;
233
        }
234
235
        /* At this point, the directory data sector needs to be read.  */
236
1210966
        logical_sector =    ((ULONG)media_ptr -> fx_media_data_sector_start) +
237
1210966
            (((ULONG)cluster - FX_FAT_ENTRY_START) *
238
1210966
             ((ULONG)media_ptr -> fx_media_sectors_per_cluster)) +
239
            relative_sector;
240
241
        /* Read the logical directory sector.  */
242
1210966
        status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) logical_sector,
243
1210966
                                                  media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
244
245
        /* Determine if an error occurred.  */
246
1210966
        if (status != FX_SUCCESS)
247
        {
248
249
            /* Return error code.  */
250
221
            return(status);
251
        }
252
253
        /* Calculate the byte offset within this sector.  */
254
1210745
        byte_offset =  byte_offset % media_ptr -> fx_media_bytes_per_sector;
255
    }
256
    else
257
    {
258
259
        /* Read the entry from the root directory.  */
260
261
        /* Determine which sector the requested root directory entry is in.  */
262
1207190
        logical_sector =  (byte_offset / media_ptr -> fx_media_bytes_per_sector) +
263
1207190
            (ULONG)media_ptr -> fx_media_root_sector_start;
264
265
        /* Read the logical directory sector.  */
266
1207190
        status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) logical_sector,
267
1207190
                                                  media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
268
269
        /* Determine if an error occurred.  */
270
1207190
        if (status != FX_SUCCESS)
271
        {
272
273
            /* Return error code.  */
274
519
            return(status);
275
        }
276
277
        /* Set the cluster and relative variables (not used in this case) to avoid any compiler
278
           warnings.  */
279
1206671
        relative_cluster =  relative_sector =  cluster =  0;
280
281
        /* Now calculate the byte offset into this sector.  */
282
1206671
        byte_offset =  byte_offset -
283
1206671
            ((logical_sector - (ULONG)media_ptr -> fx_media_root_sector_start) *
284
1206671
             media_ptr -> fx_media_bytes_per_sector);
285
    }
286
287
    /* Setup a pointer into the buffer.  */
288
2417416
    read_ptr =  (UCHAR *)media_ptr -> fx_media_memory_buffer + (UINT)byte_offset;
289
290
    /* Save the logical sector and byte offset in the returned directory entry.  */
291
2417416
    destination_ptr -> fx_dir_entry_log_sector =       logical_sector;
292
2417416
    destination_ptr -> fx_dir_entry_byte_offset =      byte_offset;
293
294
    /* Clear the short file name information.  */
295
2417416
    destination_ptr -> fx_dir_entry_long_name_shorted =  0;
296
2417416
    destination_ptr -> fx_dir_entry_short_name[0]     =  0;
297
298
    /* Setup short name pointer.  */
299
2417416
    short_name_ptr =  destination_ptr -> fx_dir_entry_name;
300
301
    /* Check if long file name exists.  */
302
2417416
    get_short_name =  0;
303

2417416
    if ((*(read_ptr + 11) == (UCHAR)FX_LONG_NAME) && (*read_ptr != (UCHAR)FX_DIR_ENTRY_FREE))
304
    {
305
306
        /* Collate the long name. */
307
308
        /* Pickup the file name length.  */
309
62626
        i = (((UINT)(*read_ptr & (UCHAR)0x1f) - 1) * FX_LONG_NAME_ENTRY_LEN) & 0xFFFFFFFF;
310
311
        /* Save the number of LFN entries.  */
312
62626
        number_of_lfns =  (UINT)(*read_ptr & (UCHAR)0x1f);
313
314
        /* Check the file name size.  */
315
62626
        if (i >= (FX_MAX_LONG_NAME_LEN - 1))
316
        {
317
318
            /* Name is too big, shorten it.  */
319
36
            get_short_name = 1;
320
36
            destination_ptr -> fx_dir_entry_long_name_shorted =  (UINT)(*read_ptr & (UCHAR)0x1f);
321
        }
322
        else
323
        {
324
325
            /* Size of name is fine, save pointer to short file name.  */
326
62590
            short_name_ptr = destination_ptr -> fx_dir_entry_short_name;
327
328
            /* Loop to make sure the long file name is NULL terminated.  */
329
62590
            j = i + FX_LONG_NAME_ENTRY_LEN + 1;
330
            do
331
            {
332
                /* Place a NULL in the long name.  */
333
875020
                destination_ptr -> fx_dir_entry_name[i] =  0;
334
335
                /* Position to the next entry.  */
336
875020
                i++;
337

875020
            } while ((i < j) && (i < FX_MAX_LONG_NAME_LEN));
338
        }
339
340
        /* Loop to pickup the rest of the name.  */
341
        do
342
        {
343
344
            /* Get the lower 5 bit containing the cardinality.  */
345
86148
            card = (UINT)(*read_ptr & (UCHAR)0x1f) - 1;
346
347
            /* For simplicity no checksum or cardinality checking is done */
348
86148
            if (get_short_name == 0)
349
            {
350
351
                /* Loop to pickup name.  */
352
1442028
                for (i = 1, j = 0; i < FX_DIR_ENTRY_SIZE; i += 2)
353
                {
354
355

1357223
                    if ((i == 11) || (i == 26))
356
                    {
357
169641
                        continue;
358
                    }
359
360
                    /* i = 12, 27 is not generated due to +=2 */
361
1187582
                    if (i == 13)
362
                    {
363
84836
                        i = 12;
364
84836
                        continue; /* this time next unicode is byte offset 14*/
365
                    }
366
367
                    /* Determine if there is an actual unicode character present.  */
368
1102746
                    if (read_ptr[i + 1])
369
                    {
370
371
                        /* Extended byte is non-zero, make sure both bytes of the unicode entry are not
372
                           all ones, since this is a normal case.  */
373

542868
                        if ((read_ptr[i + 1] != (UCHAR)0xFF) || (read_ptr[i] != (UCHAR)0xFF))
374
                        {
375
376
                            /* Name is an actual unicode name, shorten it.  */
377
4091
                            get_short_name = 1;
378
379
                            /* Save the number of directory entries the LFN has.  This will be
380
                               used later when updating the 8.3 portion of the LFN.  */
381
4091
                            destination_ptr -> fx_dir_entry_long_name_shorted =  number_of_lfns;
382
383
                            /* Setup short name pointer.  */
384
4091
                            short_name_ptr =  destination_ptr -> fx_dir_entry_name;
385
                        }
386
                    }
387
388
                    /* Determine if the character is NULL.  */
389

1102746
                    if ((read_ptr[i] == FX_NULL) || (read_ptr[i] == (UCHAR)0xFF))
390
                    {
391
600999
                        continue;
392
                    }
393
394
                    /* Determine if the name is too big.  */
395
501747
                    if ((card * 13 + j) >= (FX_MAX_LONG_NAME_LEN - 1))
396
                    {
397
398
                        /* Name is actually too big, shorten it.  */
399
33
                        get_short_name =  1;
400
401
                        /* Save the number of directory entries the LFN has.  This will be
402
                           used later when updating the 8.3 portion of the LFN.  */
403
33
                        destination_ptr -> fx_dir_entry_long_name_shorted =  number_of_lfns;
404
405
                        /* Also reposition the short name pointer.  */
406
33
                        short_name_ptr =  destination_ptr -> fx_dir_entry_name;
407
408
33
                        break;
409
                    }
410
411
                    /* Each entry contains 13 unicode and first byte ASCII, second byte is extended. */
412
501714
                    destination_ptr -> fx_dir_entry_name[13 * card + j] = (CHAR)read_ptr[i];
413
414
501714
                    j++;
415
                }
416
            }
417
418
            /* Determine if a new sector needs to be read.  */
419
86148
            if (byte_offset + FX_DIR_ENTRY_SIZE >= media_ptr -> fx_media_bytes_per_sector)
420
            {
421
422
                /* Determine if a sub-directory or FAT32 root directory is specified.  */
423

15692
                if ((source_dir) || (media_ptr -> fx_media_32_bit_FAT))
424
                {
425
426
                    /* Determine the next sector of the directory entry.  */
427
11005
                    if (relative_sector < (media_ptr -> fx_media_sectors_per_cluster - 1))
428
                    {
429
430
                        /* More sectors in this cluster.  */
431
432
                        /* Simply increment the logical sector.  */
433
4260
                        logical_sector++;
434
435
                        /* Increment the relative sector.  */
436
4260
                        relative_sector++;
437
                    }
438
                    else
439
                    {
440
441
                        /* We need to move to the next cluster.  */
442
443
                        /* Pickup the next cluster.  */
444
6745
                        status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
445
446
                        /* Check for I/O error.  */
447
6745
                        if (status != FX_SUCCESS)
448
                        {
449
450
                            /* Return error code.  */
451
1
                            return(status);
452
                        }
453
454
                        /* Copy next cluster to the current cluster.  */
455
6744
                        cluster =  next_cluster;
456
457
                        /* Check the value of the new cluster - it must be a valid cluster number
458
                           or something is really wrong!  */
459

6744
                        if ((cluster < FX_FAT_ENTRY_START) || (cluster >= media_ptr -> fx_media_fat_reserved))
460
                        {
461
462
                            /* Send error message back to caller.  */
463
5
                            return(FX_FILE_CORRUPT);
464
                        }
465
466
                        /* Now increment the relative cluster.  */
467
6739
                        relative_cluster++;
468
469
                        /* Setup the relative sector (this is zero for subsequent cluster.  */
470
6739
                        relative_sector =  0;
471
472
                        /* Calculate the next logical sector.  */
473
6739
                        logical_sector =   ((ULONG)media_ptr -> fx_media_data_sector_start) +
474
6739
                            (((ULONG)cluster - FX_FAT_ENTRY_START) *
475
6739
                             ((ULONG)media_ptr -> fx_media_sectors_per_cluster));
476
                    }
477
                }
478
                else
479
                {
480
481
                    /* Non-FAT 32 root directory.  */
482
483
                    /* Advance to the next sector.  */
484
4687
                    logical_sector++;
485
486
                    /* Determine if the logical sector is valid.  */
487
4687
                    if (logical_sector >= (ULONG)(media_ptr -> fx_media_root_sector_start + media_ptr -> fx_media_root_sectors))
488
                    {
489
490
                        /* Trying to read past root directory - send error message back to caller.  */
491
5
                        return(FX_FILE_CORRUPT);
492
                    }
493
                }
494
495
                /* Read the new sector.  */
496
15681
                status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) logical_sector,
497
15681
                                                          media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
498
499
                /* Check I/O status.  */
500
15681
                if (status != FX_SUCCESS)
501
                {
502
2
                    return(status);
503
                }
504
505
                /* Set the byte offset to 0 for new sector.  */
506
15679
                byte_offset = 0;
507
            }
508
            else
509
            {
510
511
                /* Calculate the new byte offset.  */
512
70456
                byte_offset += FX_DIR_ENTRY_SIZE;
513
            }
514
515
            /* Calculate the next read pointer.  */
516
86135
            read_ptr =  (UCHAR *)media_ptr -> fx_media_memory_buffer + (UINT) byte_offset;
517
518
            /* Move to the next entry.  */
519
86135
            entry++;
520
86135
        } while (card > 0);
521
522
        /* Set flag indicating long file name is present.  */
523
62613
        destination_ptr -> fx_dir_entry_long_name_present = 1;
524
    }
525
    else
526
    {
527
        /* No long file name is present.  */
528
2354790
        get_short_name = 1;
529
    }
530
531
    /* Determine if we need to clear the long name flag.  */
532
2417403
    if (get_short_name == 1)
533
    {
534
535
        /* Clear the long name flag.  */
536
2358721
        destination_ptr -> fx_dir_entry_long_name_present =  0;
537
    }
538
539
    /* Pickup the short file name.  */
540
2417403
    short_name_ptr[0] =  0;
541
2417403
    dotflag =  0;
542
27449467
    for (i = 0, j = 0; i < (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE); i++)
543
    {
544
545
        /* Check for a NULL.  */
546
25174047
        if ((CHAR)read_ptr[i] == 0)
547
        {
548
141983
            break;
549
        }
550
551
        /* Check for a dot.  This happens for the first two directory entries, no
552
           extra dot is needed.  */
553
25032064
        if ((CHAR)read_ptr[i] == '.')
554
        {
555
47976
            dotflag =  2;
556
        }
557
558
        /* Check for a space.  */
559
25032064
        if ((CHAR)read_ptr[i] == ' ')
560
        {
561
            /* Put a dot if a character comes after space.  */
562
5172728
            if (dotflag == 0)
563
            {
564
2243065
                dotflag =  1;
565
            }
566
5172728
            continue;
567
        }
568
569
        /* Check for the main short file name size.  */
570
19859336
        if (i == FX_DIR_NAME_SIZE)
571
        {
572
            /* Check to see if we need to insert a dot.  */
573
1995933
            if (dotflag == 0)
574
            {
575
370
                dotflag =  1;
576
            }
577
        }
578
579
        /* Check to see if we need to add a dot.  */
580
19859336
        if (dotflag == 1)
581
        {
582
            /* Add dot to short file name.  */
583
1995964
            short_name_ptr[j++] =  '.';
584
1995964
            dotflag =  2;    /* no more dot for spaces */
585
        }
586
587
        /* Copy a character.  */
588
19859336
        short_name_ptr[j] =  (CHAR)read_ptr[i];
589
590
        /* Increment size.  */
591
19859336
        j++;
592
    }
593
594
    /* Determine if a long file name is present and its associated short file
595
       name is actually free.  */
596

2417403
    if ((destination_ptr -> fx_dir_entry_long_name_present) && (((UCHAR)short_name_ptr[0]) == (UCHAR)FX_DIR_ENTRY_FREE))
597
    {
598
599
        /* Yes, the short file name is really free even though long file name entries directly precede it.
600
           In this case, simply place the free directory marker at the front of the long file name.  */
601
17
        destination_ptr -> fx_dir_entry_name[0] =  (CHAR)FX_DIR_ENTRY_FREE;
602
17
        short_name_ptr[0] =  (CHAR)0;
603
    }
604
605
    /* Determine if the short name pointer is NULL while the read pointer is
606
       non-NULL.  */
607

2417403
    if ((short_name_ptr[0] == 0) && (read_ptr[0] == ' '))
608
    {
609
610
        /* This condition can occur with an all blank volume name.  Simply
611
           copy the volume name to the short name in this case.  */
612
72
        for (j = 0; j < (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE); j++)
613
        {
614
615
            /* Copy a byte of the volume name.  */
616
66
            short_name_ptr[j] =  (CHAR)read_ptr[j];
617
        }
618
    }
619
620
    /* Set end of string to null.  */
621
2417403
    short_name_ptr[j] = 0;
622
623
    /* Load up the destination directory entry.  */
624
2417403
    read_ptr += (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE);
625
626
    /* Copy the attribute into the destination.  */
627
2417403
    destination_ptr -> fx_dir_entry_attributes =  *read_ptr++;
628
629
    /* Pickup the reserved byte.  */
630
2417403
    destination_ptr -> fx_dir_entry_reserved =  *read_ptr++;
631
632
    /* Check for an undocumented NT file name feature for optimizing the storage
633
       of all lower case file names that otherwise are valid 8.3 file names. The
634
       following reserved bit definitions are present:
635
636
         BIT3 - set if 8.3 is all in lower case and no extended filename.
637
         BIT4 - set for file, clear for directory entry if no extended filename.
638
639
       This is true for all NT systems. Prior to NT follows MSDOS FAT documentation and
640
       is set to 0x00, all bits cleared. Therefore if BIT3 is set force lowercase.  */
641

2417403
    if ((get_short_name) && (destination_ptr -> fx_dir_entry_reserved & 0x08))
642
    {
643
644
        /* Microsoft undocumented NT file name feature... convert short name to lower
645
           case.  */
646

540
        for (j = 0; j <= (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE) && (short_name_ptr[j] != 0x00); j++)
647
        {
648
649
            /* Determine if an upper case character is present.  */
650

484
            if ((short_name_ptr[j] >= 'A') && (short_name_ptr[j] <= 'Z'))
651
            {
652
653
                /* Yes, an upper case character is present. Force it to lower case.  */
654
248
                short_name_ptr[j] =  (CHAR)(short_name_ptr[j] + 32);
655
            }
656
        }
657
    }
658
659
    /* Pickup the created time in milliseconds.  */
660
2417403
    destination_ptr -> fx_dir_entry_created_time_ms =  *read_ptr++;
661
662
    /* Pickup the created time.  */
663
2417403
    destination_ptr -> fx_dir_entry_created_time =  _fx_utility_16_unsigned_read(read_ptr);
664
2417403
    read_ptr =  read_ptr + 2;  /* Always 2 bytes */
665
666
    /* Pickup the created date.  */
667
2417403
    destination_ptr -> fx_dir_entry_created_date =  _fx_utility_16_unsigned_read(read_ptr);
668
2417403
    read_ptr =  read_ptr + 2;  /* Always 2 bytes */
669
670
    /* Pickup the last accessed date.  */
671
2417403
    destination_ptr -> fx_dir_entry_last_accessed_date =  _fx_utility_16_unsigned_read(read_ptr);
672
2417403
    read_ptr =  read_ptr + 2;  /* Always 2 bytes */
673
674
    /* read the upper 2 bytes of starting cluster - required only for 32 bit FAT */
675
2417403
    if (media_ptr -> fx_media_32_bit_FAT)
676
    {
677
678
        /* FAT32 only.  */
679
1124328
        destination_ptr -> fx_dir_entry_cluster =  _fx_utility_16_unsigned_read(read_ptr);
680
1124328
        destination_ptr -> fx_dir_entry_cluster <<= 16;
681
    }
682
    else
683
    {
684
        /* Not required for non FAT32.  */
685
1293075
        destination_ptr -> fx_dir_entry_cluster =  0;
686
    }
687
688
    /* Advance the read pointer.  */
689
2417403
    read_ptr =  read_ptr + 2;  /* Always 2 bytes */
690
691
    /* Copy the time into the destination.  */
692
2417403
    destination_ptr -> fx_dir_entry_time =  _fx_utility_16_unsigned_read(read_ptr);
693
2417403
    read_ptr =  read_ptr + 2;  /* Always 2 bytes */
694
695
    /* Copy the date into the destination.  */
696
2417403
    destination_ptr -> fx_dir_entry_date =  _fx_utility_16_unsigned_read(read_ptr);
697
2417403
    read_ptr =  read_ptr + 2;  /* Always 2 bytes */
698
699
    /* Copy the starting cluster into the destination.  */
700
2417403
    destination_ptr -> fx_dir_entry_cluster +=  _fx_utility_16_unsigned_read(read_ptr);
701
2417403
    read_ptr =  read_ptr + 2;  /* Always 2 bytes */
702
703
    /* Copy the file size into the destination.  */
704
2417403
    destination_ptr -> fx_dir_entry_file_size =  _fx_utility_32_unsigned_read(read_ptr);
705
706
    /* Clear the destination search specific fields.  */
707
2417403
    destination_ptr -> fx_dir_entry_last_search_cluster =           0;
708
2417403
    destination_ptr -> fx_dir_entry_last_search_relative_cluster =  0;
709
2417403
    destination_ptr -> fx_dir_entry_last_search_log_sector =        0;
710
2417403
    destination_ptr -> fx_dir_entry_last_search_byte_offset =       0;
711
712
    /* Remember the entry number.  */
713
2417403
    destination_ptr -> fx_dir_entry_number =  entry;
714
715
    /* Return entry number.  */
716
2417403
    *entry_ptr =  entry;
717
718
    /* Determine if we should remember the last cluster and relative cluster.  */
719
2417403
    if (source_dir)
720
    {
721
722
        /* Yes, remember the last cluster and relative cluster for a subsequent call
723
           to read a directory entry.  */
724
163937
        source_dir -> fx_dir_entry_last_search_cluster =           cluster;
725
163937
        source_dir -> fx_dir_entry_last_search_relative_cluster =  relative_cluster;
726
727
        /* Also remember several other items that are unique to the directory... just to verify that the
728
           search information can be used.  */
729
163937
        source_dir -> fx_dir_entry_last_search_log_sector =        source_dir -> fx_dir_entry_log_sector;
730
163937
        source_dir -> fx_dir_entry_last_search_byte_offset =       source_dir -> fx_dir_entry_byte_offset;
731
    }
732
#ifdef FX_ENABLE_EXFAT
733
    destination_ptr -> fx_dir_entry_dont_use_fat = 0;
734
735
    /* If a file whose first byte of long name is read, fx_dir_entry_short_name will not be empty. */
736
    /* If a free dir_entry is obtained, fx_dir_entry_short_name[0] will not be assigned as 0 around Line 623 in this file. */
737
    /* If there is only a free dir_entry without front long name dir_entries, fx_dir_entry_name[0] will be assigned by the loop around Line 568. */
738
    if (((UCHAR)destination_ptr -> fx_dir_entry_name[0] == FX_DIR_ENTRY_FREE) && ((UCHAR)destination_ptr -> fx_dir_entry_short_name[0] == 0))
739
    {
740
        destination_ptr -> fx_dir_entry_type = FX_EXFAT_DIR_ENTRY_TYPE_FREE;
741
    }
742
    else if ((UCHAR)destination_ptr -> fx_dir_entry_name[0] == FX_DIR_ENTRY_DONE)
743
    {
744
        destination_ptr -> fx_dir_entry_type = FX_EXFAT_DIR_ENTRY_TYPE_END_MARKER;
745
    }
746
    else
747
    {
748
        destination_ptr -> fx_dir_entry_type = FX_EXFAT_DIR_ENTRY_TYPE_FILE_DIRECTORY;
749
    }
750
#endif /* FX_ENABLE_EXFAT */
751
752
    /* Return success to the caller.  */
753
2417403
    return(FX_SUCCESS);
754
}
755
756
757
#ifdef FX_ENABLE_EXFAT
758
UINT  _fx_directory_entry_read_ex(FX_MEDIA *media_ptr, FX_DIR_ENTRY *source_dir,
759
                                  ULONG *entry_ptr, FX_DIR_ENTRY *destination_ptr, UINT hash)
760
{
761
UINT status = FX_SUCCESS;
762
763
    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
764
    {
765
        status =
766
            _fx_directory_exFAT_entry_read(
767
                media_ptr, source_dir, entry_ptr, destination_ptr, hash, FX_FALSE, NULL, NULL);
768
    }
769
    else
770
    {
771
        status =
772
            _fx_directory_entry_read_FAT(media_ptr, source_dir, entry_ptr, destination_ptr);
773
    }
774
775
    return(status);
776
}
777
778
779
UINT  _fx_directory_entry_read(FX_MEDIA *media_ptr, FX_DIR_ENTRY *source_dir,
780
                               ULONG *entry_ptr, FX_DIR_ENTRY *destination_ptr)
781
{
782
783
    return(_fx_directory_entry_read_ex(media_ptr, source_dir, entry_ptr, destination_ptr, 0));
784
}
785
#endif /* FX_ENABLE_EXFAT */
786