GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: fx_directory_entry_read.c Lines: 188 188 100.0 %
Date: 2026-03-06 18:49:02 Branches: 128 128 100.0 %

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
2418163
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
2418163
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
2418163
ULONG  entry = *entry_ptr;
91
92
93
#ifndef FX_MEDIA_STATISTICS_DISABLE
94
95
    /* Increment the number of directory entry read requests.  */
96
2418163
    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

2418163
    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
2418162
    byte_offset =  entry * FX_DIR_ENTRY_SIZE;
107
108
    /* Determine if a sub-directory or FAT32 root directory is specified.  */
109

2418162
    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
1210972
        bytes_per_cluster =  ((ULONG)media_ptr -> fx_media_bytes_per_sector) *
116
1210972
            ((ULONG)media_ptr -> fx_media_sectors_per_cluster);
117
118
        /* Check for invalid value.  */
119
1210972
        if (bytes_per_cluster == 0)
120
        {
121
122
            /* Invalid media, return error.  */
123
3
            return(FX_MEDIA_INVALID);
124
        }
125
126
        /* Now determine the relative cluster in the sub-directory file.  */
127
1210969
        relative_cluster =   (UINT)(byte_offset / bytes_per_cluster);
128
129
        /* Calculate the byte offset within the cluster.  */
130
1210969
        byte_offset =  byte_offset % bytes_per_cluster;
131
132
        /* Now figure out the relative sector within the cluster.  */
133
1210969
        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
1210969
        if (source_dir)
139
        {
140
141
            /* Determine if this source directory has valid information from the previous call.  */
142
164165
            if ((source_dir -> fx_dir_entry_last_search_cluster) &&
143
132720
                (source_dir -> fx_dir_entry_last_search_relative_cluster <= relative_cluster) &&
144
132719
                (source_dir -> fx_dir_entry_last_search_log_sector == source_dir -> fx_dir_entry_log_sector) &&
145
132718
                (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
132717
                cluster =  source_dir -> fx_dir_entry_last_search_cluster;
150
151
                /* Setup the relative cluster index to the saved relative cluster.  */
152
132717
                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
132717
                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
31448
                cluster =  source_dir -> fx_dir_entry_cluster;
163
164
                /* Setup the relative cluster index to zero.  */
165
31448
                i =  0;
166
            }
167
        }
168
        else
169
        {
170
171
            /* No, setup the starting cluster to the FAT32 root cluster.  */
172
1046804
            cluster =  media_ptr -> fx_media_root_cluster_32;
173
174
            /* Setup the relative cluster index to zero.  */
175
1046804
            i =  0;
176
        }
177
178
        /* Loop to position to the appropriate cluster.  */
179
3247450
        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

2036484
            if ((cluster < FX_FAT_ENTRY_START) || (cluster >= media_ptr -> fx_media_fat_reserved))
185
            {
186
187
                /* Send error message back to caller.  */
188
2
                return(FX_FILE_CORRUPT);
189
            }
190
191
            /* Read the next cluster.  */
192
2036482
            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
2036482
            if (status != FX_SUCCESS)
198
            {
199
200
                /* Return error code.  */
201
1
                return(status);
202
            }
203
204
            /* Setup the actual cluster.  */
205
2036481
            cluster = next_cluster;
206
207
            /* Increment the relative cluster number.  */
208
2036481
            i++;
209
        }
210
211
        /* At this point, the directory data sector needs to be read.  */
212
1210966
        logical_sector =    ((ULONG)media_ptr -> fx_media_data_sector_start) +
213
1210966
            (((ULONG)cluster - FX_FAT_ENTRY_START) *
214
1210966
             ((ULONG)media_ptr -> fx_media_sectors_per_cluster)) +
215
            relative_sector;
216
217
        /* Read the logical directory sector.  */
218
1210966
        status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) logical_sector,
219
1210966
                                                  media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
220
221
        /* Determine if an error occurred.  */
222
1210966
        if (status != FX_SUCCESS)
223
        {
224
225
            /* Return error code.  */
226
221
            return(status);
227
        }
228
229
        /* Calculate the byte offset within this sector.  */
230
1210745
        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
1207190
        logical_sector =  (byte_offset / media_ptr -> fx_media_bytes_per_sector) +
239
1207190
            (ULONG)media_ptr -> fx_media_root_sector_start;
240
241
        /* Read the logical directory sector.  */
242
1207190
        status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) logical_sector,
243
1207190
                                                  media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
244
245
        /* Determine if an error occurred.  */
246
1207190
        if (status != FX_SUCCESS)
247
        {
248
249
            /* Return error code.  */
250
519
            return(status);
251
        }
252
253
        /* Set the cluster and relative variables (not used in this case) to avoid any compiler
254
           warnings.  */
255
1206671
        relative_cluster =  relative_sector =  cluster =  0;
256
257
        /* Now calculate the byte offset into this sector.  */
258
1206671
        byte_offset =  byte_offset -
259
1206671
            ((logical_sector - (ULONG)media_ptr -> fx_media_root_sector_start) *
260
1206671
             media_ptr -> fx_media_bytes_per_sector);
261
    }
262
263
    /* Setup a pointer into the buffer.  */
264
2417416
    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
2417416
    destination_ptr -> fx_dir_entry_log_sector =       logical_sector;
268
2417416
    destination_ptr -> fx_dir_entry_byte_offset =      byte_offset;
269
270
    /* Clear the short file name information.  */
271
2417416
    destination_ptr -> fx_dir_entry_long_name_shorted =  0;
272
2417416
    destination_ptr -> fx_dir_entry_short_name[0]     =  0;
273
274
    /* Setup short name pointer.  */
275
2417416
    short_name_ptr =  destination_ptr -> fx_dir_entry_name;
276
277
    /* Check if long file name exists.  */
278
2417416
    get_short_name =  0;
279

2417416
    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
62626
        i = (((UINT)(*read_ptr & (UCHAR)0x1f) - 1) * FX_LONG_NAME_ENTRY_LEN) & 0xFFFFFFFF;
286
287
        /* Save the number of LFN entries.  */
288
62626
        number_of_lfns =  (UINT)(*read_ptr & (UCHAR)0x1f);
289
290
        /* Check the file name size.  */
291
62626
        if (i >= (FX_MAX_LONG_NAME_LEN - 1))
292
        {
293
294
            /* Name is too big, shorten it.  */
295
36
            get_short_name = 1;
296
36
            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
62590
            short_name_ptr = destination_ptr -> fx_dir_entry_short_name;
303
304
            /* Loop to make sure the long file name is NULL terminated.  */
305
62590
            j = i + FX_LONG_NAME_ENTRY_LEN + 1;
306
            do
307
            {
308
                /* Place a NULL in the long name.  */
309
875020
                destination_ptr -> fx_dir_entry_name[i] =  0;
310
311
                /* Position to the next entry.  */
312
875020
                i++;
313

875020
            } 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
86148
            card = (UINT)(*read_ptr & (UCHAR)0x1f) - 1;
322
323
            /* For simplicity no checksum or cardinality checking is done */
324
86148
            if (get_short_name == 0)
325
            {
326
327
                /* Loop to pickup name.  */
328
1442028
                for (i = 1, j = 0; i < FX_DIR_ENTRY_SIZE; i += 2)
329
                {
330
331

1357223
                    if ((i == 11) || (i == 26))
332
                    {
333
169641
                        continue;
334
                    }
335
336
                    /* i = 12, 27 is not generated due to +=2 */
337
1187582
                    if (i == 13)
338
                    {
339
84836
                        i = 12;
340
84836
                        continue; /* this time next unicode is byte offset 14*/
341
                    }
342
343
                    /* Determine if there is an actual unicode character present.  */
344
1102746
                    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

542868
                        if ((read_ptr[i + 1] != (UCHAR)0xFF) || (read_ptr[i] != (UCHAR)0xFF))
350
                        {
351
352
                            /* Name is an actual unicode name, shorten it.  */
353
4091
                            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
4091
                            destination_ptr -> fx_dir_entry_long_name_shorted =  number_of_lfns;
358
359
                            /* Setup short name pointer.  */
360
4091
                            short_name_ptr =  destination_ptr -> fx_dir_entry_name;
361
                        }
362
                    }
363
364
                    /* Determine if the character is NULL.  */
365

1102746
                    if ((read_ptr[i] == FX_NULL) || (read_ptr[i] == (UCHAR)0xFF))
366
                    {
367
600999
                        continue;
368
                    }
369
370
                    /* Determine if the name is too big.  */
371
501747
                    if ((card * 13 + j) >= (FX_MAX_LONG_NAME_LEN - 1))
372
                    {
373
374
                        /* Name is actually too big, shorten it.  */
375
33
                        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
33
                        destination_ptr -> fx_dir_entry_long_name_shorted =  number_of_lfns;
380
381
                        /* Also reposition the short name pointer.  */
382
33
                        short_name_ptr =  destination_ptr -> fx_dir_entry_name;
383
384
33
                        break;
385
                    }
386
387
                    /* Each entry contains 13 unicode and first byte ASCII, second byte is extended. */
388
501714
                    destination_ptr -> fx_dir_entry_name[13 * card + j] = (CHAR)read_ptr[i];
389
390
501714
                    j++;
391
                }
392
            }
393
394
            /* Determine if a new sector needs to be read.  */
395
86148
            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

15692
                if ((source_dir) || (media_ptr -> fx_media_32_bit_FAT))
400
                {
401
402
                    /* Determine the next sector of the directory entry.  */
403
11005
                    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
4260
                        logical_sector++;
410
411
                        /* Increment the relative sector.  */
412
4260
                        relative_sector++;
413
                    }
414
                    else
415
                    {
416
417
                        /* We need to move to the next cluster.  */
418
419
                        /* Pickup the next cluster.  */
420
6745
                        status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
421
422
                        /* Check for I/O error.  */
423
6745
                        if (status != FX_SUCCESS)
424
                        {
425
426
                            /* Return error code.  */
427
1
                            return(status);
428
                        }
429
430
                        /* Copy next cluster to the current cluster.  */
431
6744
                        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

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

2417403
    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
17
        destination_ptr -> fx_dir_entry_name[0] =  (CHAR)FX_DIR_ENTRY_FREE;
578
17
        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

2417403
    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
72
        for (j = 0; j < (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE); j++)
589
        {
590
591
            /* Copy a byte of the volume name.  */
592
66
            short_name_ptr[j] =  (CHAR)read_ptr[j];
593
        }
594
    }
595
596
    /* Set end of string to null.  */
597
2417403
    short_name_ptr[j] = 0;
598
599
    /* Load up the destination directory entry.  */
600
2417403
    read_ptr += (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE);
601
602
    /* Copy the attribute into the destination.  */
603
2417403
    destination_ptr -> fx_dir_entry_attributes =  *read_ptr++;
604
605
    /* Pickup the reserved byte.  */
606
2417403
    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

2417403
    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

540
        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

484
            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
248
                short_name_ptr[j] =  (CHAR)(short_name_ptr[j] + 32);
631
            }
632
        }
633
    }
634
635
    /* Pickup the created time in milliseconds.  */
636
2417403
    destination_ptr -> fx_dir_entry_created_time_ms =  *read_ptr++;
637
638
    /* Pickup the created time.  */
639
2417403
    destination_ptr -> fx_dir_entry_created_time =  _fx_utility_16_unsigned_read(read_ptr);
640
2417403
    read_ptr =  read_ptr + 2;  /* Always 2 bytes */
641
642
    /* Pickup the created date.  */
643
2417403
    destination_ptr -> fx_dir_entry_created_date =  _fx_utility_16_unsigned_read(read_ptr);
644
2417403
    read_ptr =  read_ptr + 2;  /* Always 2 bytes */
645
646
    /* Pickup the last accessed date.  */
647
2417403
    destination_ptr -> fx_dir_entry_last_accessed_date =  _fx_utility_16_unsigned_read(read_ptr);
648
2417403
    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
2417403
    if (media_ptr -> fx_media_32_bit_FAT)
652
    {
653
654
        /* FAT32 only.  */
655
1124328
        destination_ptr -> fx_dir_entry_cluster =  _fx_utility_16_unsigned_read(read_ptr);
656
1124328
        destination_ptr -> fx_dir_entry_cluster <<= 16;
657
    }
658
    else
659
    {
660
        /* Not required for non FAT32.  */
661
1293075
        destination_ptr -> fx_dir_entry_cluster =  0;
662
    }
663
664
    /* Advance the read pointer.  */
665
2417403
    read_ptr =  read_ptr + 2;  /* Always 2 bytes */
666
667
    /* Copy the time into the destination.  */
668
2417403
    destination_ptr -> fx_dir_entry_time =  _fx_utility_16_unsigned_read(read_ptr);
669
2417403
    read_ptr =  read_ptr + 2;  /* Always 2 bytes */
670
671
    /* Copy the date into the destination.  */
672
2417403
    destination_ptr -> fx_dir_entry_date =  _fx_utility_16_unsigned_read(read_ptr);
673
2417403
    read_ptr =  read_ptr + 2;  /* Always 2 bytes */
674
675
    /* Copy the starting cluster into the destination.  */
676
2417403
    destination_ptr -> fx_dir_entry_cluster +=  _fx_utility_16_unsigned_read(read_ptr);
677
2417403
    read_ptr =  read_ptr + 2;  /* Always 2 bytes */
678
679
    /* Copy the file size into the destination.  */
680
2417403
    destination_ptr -> fx_dir_entry_file_size =  _fx_utility_32_unsigned_read(read_ptr);
681
682
    /* Clear the destination search specific fields.  */
683
2417403
    destination_ptr -> fx_dir_entry_last_search_cluster =           0;
684
2417403
    destination_ptr -> fx_dir_entry_last_search_relative_cluster =  0;
685
2417403
    destination_ptr -> fx_dir_entry_last_search_log_sector =        0;
686
2417403
    destination_ptr -> fx_dir_entry_last_search_byte_offset =       0;
687
688
    /* Remember the entry number.  */
689
2417403
    destination_ptr -> fx_dir_entry_number =  entry;
690
691
    /* Return entry number.  */
692
2417403
    *entry_ptr =  entry;
693
694
    /* Determine if we should remember the last cluster and relative cluster.  */
695
2417403
    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
163937
        source_dir -> fx_dir_entry_last_search_cluster =           cluster;
701
163937
        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
163937
        source_dir -> fx_dir_entry_last_search_log_sector =        source_dir -> fx_dir_entry_log_sector;
706
163937
        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
2417403
    return(FX_SUCCESS);
711
}
712
713
714