GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: fx_directory_search.c Lines: 214 214 100.0 %
Date: 2024-01-10 21:53:23 Branches: 198 198 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
#endif /* FX_ENABLE_EXFAT */
35
36
#ifndef FX_NO_LOCAL_PATH
37
FX_LOCAL_PATH_SETUP
38
#endif
39
40
41
/**************************************************************************/
42
/*                                                                        */
43
/*  FUNCTION                                               RELEASE        */
44
/*                                                                        */
45
/*    _fx_directory_search                                PORTABLE C      */
46
/*                                                           6.1.10       */
47
/*  AUTHOR                                                                */
48
/*                                                                        */
49
/*    William E. Lamie, Microsoft Corporation                             */
50
/*                                                                        */
51
/*  DESCRIPTION                                                           */
52
/*                                                                        */
53
/*    This function searches the media for the supplied name.  The search */
54
/*    routine will find files as well as directory names.                 */
55
/*                                                                        */
56
/*  INPUT                                                                 */
57
/*                                                                        */
58
/*    media_ptr                             Media control block pointer   */
59
/*    name_ptr                              Name pointer                  */
60
/*    entry_ptr                             Pointer to directory entry    */
61
/*                                            record                      */
62
/*    last_dir_ptr                          Pointer to destination for    */
63
/*                                            the last directory entry    */
64
/*    last_name_ptr                         Pointer to the last name      */
65
/*                                            token that was searched for */
66
/*                                                                        */
67
/*  OUTPUT                                                                */
68
/*                                                                        */
69
/*    return status                                                       */
70
/*                                                                        */
71
/*  CALLS                                                                 */
72
/*                                                                        */
73
/*    _fx_directory_name_extract            Extract directory name from   */
74
/*                                            input string                */
75
/*    _fx_directory_entry_read              Read entries from root dir    */
76
/*    _fx_utility_exFAT_name_hash_get       Get name hash                 */
77
/*    _fx_utility_FAT_entry_read            Read FAT entries to calculate */
78
/*                                            the sub-directory size      */
79
/*                                                                        */
80
/*  CALLED BY                                                             */
81
/*                                                                        */
82
/*    FileX System Functions                                              */
83
/*                                                                        */
84
/*  RELEASE HISTORY                                                       */
85
/*                                                                        */
86
/*    DATE              NAME                      DESCRIPTION             */
87
/*                                                                        */
88
/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
89
/*  09-30-2020     William E. Lamie         Modified comment(s), and      */
90
/*                                            added conditional to        */
91
/*                                            disable media search cache, */
92
/*                                            resulting in version 6.1    */
93
/*  06-02-2021     Bhupendra Naphade        Modified comment(s), and      */
94
/*                                            added check for             */
95
/*                                            volume label,               */
96
/*                                            resulting in version 6.1.7  */
97
/*  01-31-2022     William E. Lamie         Modified comment(s), and      */
98
/*                                            fixed path compare,         */
99
/*                                            resulting in version 6.1.10 */
100
/*                                                                        */
101
/**************************************************************************/
102
97598
UINT  _fx_directory_search(FX_MEDIA *media_ptr, CHAR *name_ptr, FX_DIR_ENTRY *entry_ptr,
103
                           FX_DIR_ENTRY *last_dir_ptr, CHAR **last_name_ptr)
104
{
105
106
ULONG         i, n;
107
UINT          found;
108
UINT          status;
109
#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
110
UINT          v, j;
111
#endif /* FX_MEDIA_DISABLE_SEARCH_CACHE */
112
97598
ULONG         cluster, next_cluster = 0;
113
ULONG64       directory_size;
114
CHAR         *dir_name_ptr;
115
CHAR         *work_ptr;
116
CHAR         *source_name_ptr;
117
CHAR         *destination_name_ptr;
118
FX_DIR_ENTRY  search_dir;
119
FX_DIR_ENTRY *search_dir_ptr;
120
CHAR         *name, alpha, name_alpha;
121
#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
122
UINT          index;
123
97598
CHAR         *path_ptr =  FX_NULL;
124
97598
CHAR         *original_name =  name_ptr;
125
#endif
126
#ifdef FX_ENABLE_EXFAT
127
USHORT        hash = 0;
128
#endif /* FX_ENABLE_EXFAT */
129
130
#ifndef FX_MEDIA_STATISTICS_DISABLE
131
132
    /* Increment the number of directory search requests.  */
133
97598
    media_ptr -> fx_media_directory_searches++;
134
#endif
135
136
    /* Setup pointer to media name buffer.  */
137
97598
    name =  media_ptr -> fx_media_name_buffer;
138
139
    /* Setup the last directory, if required.  */
140
97598
    if (last_dir_ptr)
141
    {
142
143
        /* Set the first character of the directory entry to NULL to
144
           indicate root or no directory.  */
145
77838
        last_dir_ptr -> fx_dir_entry_name[0] =  0;
146
    }
147
148
    /* Determine if the file name has a full directory path.  */
149

97598
    if ((*name_ptr == '\\') || (*name_ptr == '/'))
150
    {
151
152
        /* Directory name has full path, set the search pointer to NULL.  */
153
14653
        search_dir_ptr =  FX_NULL;
154
    }
155
    else
156
    {
157
158
        /* Set the initial search directory to the current working
159
           directory - if there is one.  */
160
161
        /* First check for a local path pointer stored in the thread control block.  This
162
           is only available in ThreadX Version 4 and above.  */
163
#ifndef FX_NO_LOCAL_PATH
164
82945
        if (_tx_thread_current_ptr -> tx_thread_filex_ptr)
165
        {
166
167
            /* Determine if the local directory is not the root directory.  */
168
746
            if (((FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr) -> fx_path_directory.fx_dir_entry_name[0])
169
            {
170
171
                /* Start at the current working directory of the media.  */
172
686
                search_dir =   ((FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr) -> fx_path_directory;
173
174
#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
175
176
                /* Setup pointer to the path.  */
177
686
                path_ptr =  ((FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr) -> fx_path_string;
178
#endif
179
180
                /* Set the internal pointer to the search directory as well.  */
181
686
                search_dir_ptr =  &search_dir;
182
            }
183
            else
184
            {
185
186
                /* We are searching in the root directory.  */
187
60
                search_dir_ptr =  FX_NULL;
188
            }
189
        }
190
        else
191
#endif
192
82199
        if (media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name[0])
193
        {
194
195
            /* Start at the current working directory of the media.  */
196
466
            search_dir =  media_ptr -> fx_media_default_path.fx_path_directory;
197
198
#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
199
200
            /* Setup pointer to the path.  */
201
466
            path_ptr =  media_ptr -> fx_media_default_path.fx_path_string;
202
#endif
203
204
            /* Set the internal pointer to the search directory as well.  */
205
466
            search_dir_ptr =  &search_dir;
206
        }
207
        else
208
        {
209
210
            /* The current default directory is the root so just set the
211
               search directory pointer to NULL.  */
212
81733
            search_dir_ptr =  FX_NULL;
213
        }
214
    }
215
216
#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
217
218
    /* Determine if there is a previously found directory entry.  */
219
97598
    if (media_ptr -> fx_media_last_found_name[0])
220
    {
221
222
    UINT  match;
223
    CHAR *temp_ptr, beta;
224
225
        /* Yes, there is a previously found directory in our cache.  */
226
227
        /* Initialize the index.  */
228
21137
        v =  0;
229
230
        /* Determine if there is a full path.  */
231

21137
        if ((*name_ptr == '\\') || (*name_ptr == '/'))
232
        {
233
234
            /* Yes, the full path is in the name buffer. Simply compare with what is in
235
               the last search buffer.  */
236

3847
            while ((v < (FX_MAX_LAST_NAME_LEN - 1)) && (name_ptr[v]))
237
            {
238
239
                /* Pickup the respective name characters.  */
240
3827
                alpha =  name_ptr[v];
241
3827
                beta =   media_ptr -> fx_media_last_found_name[v];
242
243
                /* Ensure directory markers are the same.  */
244
3827
                if (alpha == '\\')
245
                {
246
17
                    alpha =  '/';
247
                }
248
3827
                if (beta == '\\')
249
                {
250
14
                    beta =  '/';
251
                }
252
253
                /* Is the name the same?  */
254
3827
                if (alpha != beta)
255
                {
256
257
                    /* Break out of loop!  */
258
23
                    break;
259
                }
260
261
                /* Move to next character.  */
262
3804
                v++;
263
            }
264
265
            /* Determine if we have a match.  */
266
43
            if (name_ptr[v] != media_ptr -> fx_media_last_found_name[v])
267
            {
268
25
                match =  FX_FALSE;
269
            }
270
            else
271
            {
272
18
                match =  FX_TRUE;
273
            }
274
        }
275
        else
276
        {
277
278
            /* Default to found.  */
279
21094
            match =  FX_TRUE;
280
281
            /* Determine if there is a default path to compare with.  */
282
21094
            if (path_ptr)
283
            {
284
285
                /* Yes, compare the current path with what is contained in the last
286
                   found buffer. Note that the last found name must have at least one
287
                   path separator as well as room for at least one character for a name. */
288

28971
                while ((v < (FX_MAX_LAST_NAME_LEN - 1)) && (path_ptr[v]))
289
                {
290
291
                    /* Pickup the respective name characters.  */
292
28285
                    alpha =  media_ptr -> fx_media_last_found_name[v];
293
28285
                    beta =   path_ptr[v];
294
295
                    /* Ensure directory markers are the same.  */
296
28285
                    if (alpha == '\\')
297
                    {
298
1504
                        alpha =  '/';
299
                    }
300
28285
                    if (beta == '\\')
301
                    {
302
1653
                        beta =  '/';
303
                    }
304
305
                    /* Is the name the same?  */
306
28285
                    if (alpha != beta)
307
                    {
308
309
                        /* Break out of loop!  */
310
10
                        break;
311
                    }
312
313
                    /* Move to next character.  */
314
28275
                    v++;
315
                }
316
317
                /* Determine if we don't have a match...  The relative path must be exhausted. */
318
696
                if (path_ptr[v])
319
                {
320
10
                    match =  FX_FALSE;
321
                }
322
            }
323
324
            /* Determine if we still have a match.  */
325
21094
            if (match)
326
            {
327
328
                /* Now examine the rest of the last name and the newly supplied
329
                   input name.  */
330
331
                /* Determine if a valid directory separator is present.  */
332
21084
                if ((media_ptr -> fx_media_last_found_name[v] != '\\') &&
333
21077
                    (media_ptr -> fx_media_last_found_name[v] != '/'))
334
                {
335
336
                    /* Set match to false - invalid directory path separator.  */
337
166
                    match =  FX_FALSE;
338
                }
339
                else
340
                {
341
                    /* Position past the next directory separator in the
342
                       last name string.  */
343
20918
                    v++;
344
                }
345
346
                /* Yes, the full path is in the name buffer. Simply compare with what is in
347
                   the last search buffer.  */
348
21084
                j =  0;
349

104709
                while ((v < (FX_MAX_LAST_NAME_LEN - 1)) && (name_ptr[j]) && (match))
350
                {
351
352
                    /* Pickup the respective name characters.  */
353
104000
                    alpha =  name_ptr[j];
354
104000
                    beta =   media_ptr -> fx_media_last_found_name[v];
355
356
                    /* Ensure directory markers are the same.  */
357
104000
                    if (alpha == '\\')
358
                    {
359
6
                        alpha =  '/';
360
                    }
361
104000
                    if (beta == '\\')
362
                    {
363
6
                        beta =  '/';
364
                    }
365
366
                    /* Is the name the same?  */
367
104000
                    if (alpha != beta)
368
                    {
369
370
                        /* Break out of loop!  */
371
20375
                        break;
372
                    }
373
374
                    /* Move to next character.  */
375
83625
                    v++;
376
83625
                    j++;
377
                }
378
379
                /* Avoid accessing fx_media_last_found_name out of bounds. */
380
21084
                if (v >= 256)
381
                {
382
1
                    match = FX_FALSE;
383
                }
384

21083
                else if ((match) && (name_ptr[j] != media_ptr -> fx_media_last_found_name[v]))
385
                {
386
387
                    /* We don't have a match.  */
388
20402
                    match =  FX_FALSE;
389
                }
390
            }
391
        }
392
393
        /* Now determine if we actually found a match.  */
394
21137
        if (match)
395
        {
396
397
            /* Save the directory entry name pointer.  */
398
533
            temp_ptr =  entry_ptr -> fx_dir_entry_name;
399
400
            /* Copy the saved directory entry.  */
401
533
            *entry_ptr =  media_ptr -> fx_media_last_found_entry;
402
403
            /* Restore the directory entry name pointer.  */
404
533
            entry_ptr -> fx_dir_entry_name =  temp_ptr;
405
406
            /* Copy the directory name into the destination directory name.  */
407
7576
            for (index = 0; index < FX_MAX_LONG_NAME_LEN; index++)
408
            {
409
410
                /* Copy character into the destination.  */
411
7574
                temp_ptr[index] =  media_ptr -> fx_media_last_found_file_name[index];
412
413
                /* See if we have copied the NULL termination character.  */
414
7574
                if (temp_ptr[index] == (CHAR)FX_NULL)
415
                {
416
417
                    /* Determine if we should break here or at the top of the loop.  */
418
533
                    if (index < (FX_MAX_LONG_NAME_LEN - 1))
419
                    {
420
421
                        /* Yes, break out of the loop early.  */
422
531
                        break;
423
                    }
424
                }
425
            }
426
427
            /* Determine if there is a search directory to copy.  */
428

533
            if ((last_dir_ptr) && (media_ptr -> fx_media_last_found_directory_valid))
429
            {
430
431
                /* Yes, there was a search directory... and one is requested in this request as well.
432
                   Simply copy it into the destination.  */
433
434
                /* First, save the name pointer from the list directory pointer.  */
435
49
                destination_name_ptr =  last_dir_ptr -> fx_dir_entry_name;
436
437
                /* Copy the entire directory entry structure.  */
438
49
                *last_dir_ptr =  media_ptr -> fx_media_last_found_directory;
439
440
                /* Restore the original name buffer pointer.  */
441
49
                last_dir_ptr -> fx_dir_entry_name =  destination_name_ptr;
442
443
                /* Pickup pointer to name to copy.  */
444
49
                source_name_ptr =  media_ptr -> fx_media_last_found_directory.fx_dir_entry_name;
445
446
                /* Loop to copy the name into the last directory name buffer.  */
447
947
                for (n = 0; n < FX_MAX_LONG_NAME_LEN; n++)
448
                {
449
450
                    /* Copy a character.  */
451
946
                    destination_name_ptr[n] =  source_name_ptr[n];
452
453
                    /* See if we have copied the NULL termination character.  */
454
946
                    if (source_name_ptr[n] == (CHAR)FX_NULL)
455
                    {
456
457
                        /* Determine if we should break here or at the top of the loop.  */
458
49
                        if (n < (FX_MAX_LONG_NAME_LEN - 1))
459
                        {
460
461
                            /* Yes, break out of the loop early.  */
462
48
                            break;
463
                        }
464
                    }
465
                }
466
            }
467
468
            /* Return the last name pointer, if required.  */
469
533
            if (last_name_ptr)
470
            {
471
472
                /* Just set the last name to initial name string.  */
473
51
                *last_name_ptr =  temp_ptr;
474
            }
475
476
#ifndef FX_MEDIA_STATISTICS_DISABLE
477
478
            /* Increment the number of directory search cache hits.  */
479
533
            media_ptr -> fx_media_directory_search_cache_hits++;
480
#endif
481
482
            /* Return success.  */
483
533
            return(FX_SUCCESS);
484
        }
485
    }
486
487
    /* Not a sequential search, invalidate the saved information.  */
488
97065
    media_ptr -> fx_media_last_found_name[0] =  FX_NULL;
489
490
#ifndef FX_MEDIA_STATISTICS_DISABLE
491
492
    /* If trace is enabled, insert this event into the trace buffer.  */
493
    FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_DIR_CACHE_MISS, media_ptr, media_ptr -> fx_media_directory_searches - media_ptr -> fx_media_directory_search_cache_hits, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
494
#else
495
496
    /* If trace is enabled, insert this event into the trace buffer.  */
497
    FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_DIR_CACHE_MISS, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
498
#endif
499
#endif
500
501
    /* Loop to traverse the directory paths to find the specified file.  */
502
    do
503
    {
504
505
        /* Remember the last name pointer, if required.  */
506
112229
        if (last_name_ptr)
507
        {
508
509
            /* Just set the last name to initial name string.  */
510
92433
            *last_name_ptr =  name_ptr;
511
        }
512
513
        /* Extract file name.  */
514
112229
        name_ptr =  _fx_directory_name_extract(name_ptr, name);
515
516
        /* Calculate the directory size.  */
517
112229
        if (search_dir_ptr)
518
        {
519
#ifdef FX_ENABLE_EXFAT
520
            if (media_ptr -> fx_media_FAT_type == FX_exFAT)
521
            {
522
                directory_size = search_dir_ptr -> fx_dir_entry_file_size / FX_DIR_ENTRY_SIZE;
523
            }
524
            else
525
            {
526
#endif /* FX_ENABLE_EXFAT */
527
528
                /* Ensure that the search directory's last search cluster is cleared.  */
529
15926
                search_dir_ptr -> fx_dir_entry_last_search_cluster =  0;
530
531
                /* Calculate the directory size by counting the allocated
532
                clusters for it.  */
533
15926
                i =        0;
534
15926
                cluster =  search_dir_ptr -> fx_dir_entry_cluster;
535
61286
                while (cluster < media_ptr -> fx_media_fat_reserved)
536
                {
537
538
                    /* Increment the cluster count.  */
539
45376
                    i++;
540
541
                    /* Read the next FAT entry.  */
542
45376
                    status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
543
544
                    /* Check the return status.  */
545
45376
                    if (status != FX_SUCCESS)
546
                    {
547
548
                        /* Return the bad status.  */
549
1
                        return(status);
550
                    }
551
552
                    /* Check for error situation.  */
553

45375
                    if ((cluster < FX_FAT_ENTRY_START) || (cluster == next_cluster) || (i > media_ptr -> fx_media_total_clusters))
554
                    {
555
556
                        /* Return the bad status.  */
557
15
                        return(FX_FAT_READ_ERROR);
558
                    }
559
560
45360
                    cluster = next_cluster;
561
                }
562
563
                /* Now we can calculate the directory size.  */
564
15910
                directory_size =  (((ULONG64) media_ptr -> fx_media_bytes_per_sector) *
565
15910
                                   ((ULONG64) media_ptr -> fx_media_sectors_per_cluster) * i)
566
                                    / (ULONG64) FX_DIR_ENTRY_SIZE;
567
568
                /* Also save this in the directory entry so we don't have to
569
                   calculate it later.  */
570
15910
                search_dir_ptr -> fx_dir_entry_file_size =  directory_size;
571
#ifdef FX_ENABLE_EXFAT
572
            }
573
#endif /* FX_ENABLE_EXFAT */
574
575
            /* If required, copy the last search directory entry into the
576
               destination.  */
577
15910
            if (last_dir_ptr)
578
            {
579
580
                /* Copy the last search directory into the destination.  */
581
582
                /* First, save the name pointer from the list directory pointer.  */
583
15185
                destination_name_ptr =  last_dir_ptr -> fx_dir_entry_name;
584
585
                /* Copy the entire directory entry structure.  */
586
15185
                *last_dir_ptr =  *search_dir_ptr;
587
588
                /* Restore the original name buffer pointer.  */
589
15185
                last_dir_ptr -> fx_dir_entry_name =  destination_name_ptr;
590
591
                /* Pickup pointer to name to copy.  */
592
15185
                source_name_ptr =  search_dir_ptr -> fx_dir_entry_name;
593
594
                /* Loop to copy the name into the last directory name buffer.  */
595
84857
                for (n = 0; n < FX_MAX_LONG_NAME_LEN; n++)
596
                {
597
598
                    /* Copy a character.  */
599
84854
                    destination_name_ptr[n] =  source_name_ptr[n];
600
601
                    /* See if we have copied the NULL termination character.  */
602
84854
                    if (source_name_ptr[n] == (CHAR) FX_NULL)
603
                    {
604
605
                        /* Determine if we should break here or at the top of the loop.  */
606
15185
                        if (n < (FX_MAX_LONG_NAME_LEN - 1))
607
                        {
608
609
                            /* Yes, break out of the loop early.  */
610
15182
                            break;
611
                        }
612
                    }
613
                }
614
            }
615
        }
616
        else
617
        {
618
619
            /* Directory size is the number of entries in the root directory.  */
620
96303
            directory_size =  (ULONG)media_ptr -> fx_media_root_directory_entries;
621
        }
622
623
        /* Loop through entries in the directory.  Yes, this is a
624
           linear search!  */
625
112213
        i =      0;
626
112213
        found =  FX_FALSE;
627
628
#ifdef FX_ENABLE_EXFAT
629
        if (media_ptr -> fx_media_FAT_type == FX_exFAT)
630
        {
631
632
            /* Get name hash.  */
633
            hash =  _fx_utility_exFAT_name_hash_get(name);
634
        }
635
#endif /* FX_ENABLE_EXFAT */
636
637
        do
638
        {
639
640
            /* Read an entry from the directory.  */
641
#ifdef FX_ENABLE_EXFAT
642
            status =  _fx_directory_entry_read_ex(media_ptr, search_dir_ptr, &i, entry_ptr, hash);
643
#else
644
1425685
            status =  _fx_directory_entry_read(media_ptr, search_dir_ptr, &i, entry_ptr);
645
#endif /* FX_ENABLE_EXFAT */
646
647
1425685
            i++;
648
649
            /* Check for error status.  */
650
1425685
            if (status != FX_SUCCESS)
651
            {
652
12
                return(status);
653
            }
654
655
            /* Determine if this is the last directory entry.  */
656
#ifdef FX_ENABLE_EXFAT
657
            if (entry_ptr -> fx_dir_entry_type == FX_EXFAT_DIR_ENTRY_TYPE_END_MARKER)
658
#else
659
1425673
            if ((UCHAR)entry_ptr -> fx_dir_entry_name[0] == (UCHAR)FX_DIR_ENTRY_DONE)
660
#endif /* FX_ENABLE_EXFAT */
661
            {
662
63561
                break;
663
            }
664
665
            /* Determine if the entry is a volume label entry */
666
1362112
            if ((entry_ptr -> fx_dir_entry_attributes & FX_VOLUME))
667
            {
668
995
                continue;
669
            }
670
671
            /* Determine if this is an empty entry.  */
672
#ifdef FX_ENABLE_EXFAT
673
            if (entry_ptr -> fx_dir_entry_type != FX_EXFAT_DIR_ENTRY_TYPE_FILE_DIRECTORY)
674
#else
675

1361117
            if (((UCHAR)entry_ptr -> fx_dir_entry_name[0] == (UCHAR)FX_DIR_ENTRY_FREE) && (entry_ptr -> fx_dir_entry_short_name[0] == 0))
676
#endif /* FX_ENABLE_EXFAT */
677
            {
678
2712
                continue;
679
            }
680
681
            /* Compare the input name and extension with the directory
682
               entry.  */
683
1358405
            work_ptr =      &name[0];
684
1358405
            dir_name_ptr =  &(entry_ptr -> fx_dir_entry_name[0]);
685
686
            /* Loop to compare names.  */
687
            do
688
            {
689
690
                /* Pickup character of directory name.  */
691
4462143
                alpha =  *dir_name_ptr;
692
693
                /* Pickup character of name.  */
694
4462143
                name_alpha =  *work_ptr;
695
696
                /* Determine if its case needs to be changed.  */
697

4462143
                if ((alpha >= 'a') && (alpha <= 'z'))
698
                {
699
700
                    /* Yes, make upper case.  */
701
69404
                    alpha =  (CHAR)((INT)alpha - 0x20);
702
                }
703
704
                /* Determine if its case needs to be changed.  */
705

4462143
                if ((name_alpha >= 'a') && (name_alpha <= 'z'))
706
                {
707
708
                    /* Yes, make upper case.  */
709
99226
                    name_alpha =  (CHAR)((INT)name_alpha - 0x20);
710
                }
711
712
                /* Compare name with directory name.  */
713
4462143
                if (alpha != name_alpha)
714
                {
715
716
                    /* The names don't match, get out of the loop. */
717
1321985
                    break;
718
                }
719
720
                /* Otherwise, increment the name pointers.  */
721
3140158
                work_ptr++;
722
3140158
                dir_name_ptr++;
723
3140158
            } while (*dir_name_ptr);
724
725
            /* Determine if the requested name has been found.  If so,
726
               return success to the caller.  */
727

1358405
            if ((*dir_name_ptr == 0) && (*work_ptr == *dir_name_ptr))
728
            {
729
730
                /* Yes, the name was located.  All pertinent directory
731
                   information is in the directory entry field.  */
732
34631
                found =  FX_TRUE;
733
            }
734
            /* Determine if there is a short name to check.  */
735
#ifdef FX_ENABLE_EXFAT
736
            else if ((media_ptr -> fx_media_FAT_type != FX_exFAT) &&
737
                     (entry_ptr -> fx_dir_entry_short_name[0] != 0))
738
#else
739
1323774
            else if (entry_ptr -> fx_dir_entry_short_name[0] != 0)
740
#endif /* FX_ENABLE_EXFAT */
741
            {
742
743
                /* Yes, check for the short part of the name.  */
744
745
                /* Compare the input name and extension with the directory entry.  */
746
46915
                work_ptr =      &name[0];
747
46915
                dir_name_ptr =  &(entry_ptr -> fx_dir_entry_short_name[0]);
748
749
                /* Loop to compare names.  */
750
                do
751
                {
752
753
                    /* Pickup character of directory name.  */
754
77450
                    alpha =  *dir_name_ptr;
755
756
                    /* Pickup character of name.  */
757
77450
                    name_alpha =  *work_ptr;
758
759
                    /* Determine if its case needs to be changed.  */
760

77450
                    if ((name_alpha >= 'a') && (name_alpha <= 'z'))
761
                    {
762
763
                        /* Yes, make upper case.  */
764
52801
                        name_alpha =  (CHAR)((INT)name_alpha - 0x20);
765
                    }
766
767
                    /* Compare name with directory name.  */
768
77450
                    if (alpha != name_alpha)
769
                    {
770
771
                        /* The names don't match, get out of the loop. */
772
43266
                        break;
773
                    }
774
775
                    /* Otherwise, move the name pointers and increment the
776
                       count.  */
777
34184
                    work_ptr++;
778
34184
                    dir_name_ptr++;
779
34184
                } while (*dir_name_ptr);
780
781
                /* Determine if the names match.  */
782

46915
                if ((*dir_name_ptr == 0) && (*work_ptr == *dir_name_ptr))
783
                {
784
785
                    /* Yes, the name was located.  All pertinent directory
786
                        information is in the directory entry field.  */
787
2742
                    found =  FX_TRUE;
788
                }
789
            }
790

1362112
        } while ((i < directory_size) && (!found));
791
792
        /* Now determine if we have a match.  */
793
112201
        if (!found)
794
        {
795
796
            /* Return a "not found" status to the caller.  */
797
74828
            return(FX_NOT_FOUND);
798
        }
799
800
        /* Determine if the found entry is indeed a sub-directory.  */
801
37373
        if (entry_ptr -> fx_dir_entry_attributes & FX_DIRECTORY)
802
        {
803
804
            /* Move the directory search pointer to this entry.  */
805
18090
            search_dir =      *entry_ptr;
806
18090
            search_dir_ptr =  &search_dir;
807
808
            /* Ensure that the search directory's last search cluster is cleared.  */
809
18090
            search_dir_ptr -> fx_dir_entry_last_search_cluster =  0;
810
811
            /* Now determine if the new search directory is the root
812
               directory.  */
813
#ifdef FX_ENABLE_EXFAT
814
            if ((!search_dir_ptr -> fx_dir_entry_cluster)
815
                && (media_ptr -> fx_media_FAT_type != FX_exFAT))
816
#else
817
18090
            if (!search_dir_ptr -> fx_dir_entry_cluster)
818
#endif /* FX_ENABLE_EXFAT */
819
            {
820
821
                /* This is a backward link to the root directory.  Make
822
                   sure this is indicated in the search directory
823
                   information.  */
824
19
                search_dir_ptr -> fx_dir_entry_name[0] =  0;
825
826
                /* Determine if we need to remember this in the last
827
                   directory searched return area.  */
828
19
                if (last_dir_ptr)
829
                {
830
831
                    /* Yes, return this value to the caller.  */
832
833
                    /* First, save the name pointer from the list directory pointer.  */
834
1
                    destination_name_ptr =  last_dir_ptr -> fx_dir_entry_name;
835
836
                    /* Copy the entire directory entry structure.  */
837
1
                    *last_dir_ptr =  *search_dir_ptr;
838
839
                    /* Restore the original name buffer pointer.  */
840
1
                    last_dir_ptr -> fx_dir_entry_name =  destination_name_ptr;
841
842
                    /* Pickup pointer to name to copy.  */
843
1
                    source_name_ptr =  search_dir_ptr -> fx_dir_entry_name;
844
845
                    /* Loop to copy the name into the last directory name buffer.  */
846
257
                    for (n = 0; n < FX_MAX_LONG_NAME_LEN; n++)
847
                    {
848
849
                        /* Copy a character.  */
850
256
                        destination_name_ptr[n] =  source_name_ptr[n];
851
                    }
852
                }
853
854
                /* Set the search directory pointer to NULL to indicate
855
                   we are at the root directory.  */
856
19
                search_dir_ptr =  FX_NULL;
857
            }
858
        }
859
        else
860
        {
861
862
            /* This is not a directory, we better return not found
863
               since we can't continue the search.  */
864
19283
            if (name_ptr)
865
            {
866
867
                /* Return not-found status to caller.  */
868
1
                return(FX_NOT_FOUND);
869
            }
870
        }
871
37372
    } while (name_ptr);
872
873
    /* If you reach this point, the directory is found absolutely, since !found will return directly in the loop above.   */
874
#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
875
876
877
    /* At this point, cache the found information.  If a subsequent search for the same name is done,
878
       it will return immediately.  */
879
880
    /* Set the index of the saved name string.  */
881
22208
    v=  0;
882
883
    /* First, build the full path and name.  */
884

22208
    if ((*original_name != '\\') && (*original_name != '/') && (path_ptr))
885
    {
886
887
        /* Copy the path into the destination.  */
888

45042
        while ((v< (FX_MAX_LAST_NAME_LEN - 1)) && (path_ptr[v]))
889
        {
890
891
            /* Copy one character.   */
892
44649
            media_ptr -> fx_media_last_found_name[v] =  path_ptr[v];
893
894
            /* Move to next character.  */
895
44649
            v++;
896
        }
897
    }
898
899
    /* Now see if there is no directory path symbol in the name itself.  */
900

22208
    if ((*original_name != '\\') && (*original_name != '/'))
901
    {
902
903
        /* If there is room, place a directory separator character.  */
904
21982
        if (v < (FX_MAX_LAST_NAME_LEN - 1))
905
        {
906
21875
            media_ptr -> fx_media_last_found_name[v++] =  '/';
907
        }
908
    }
909
910
    /* Now append the name to the path.  */
911
22208
    j =  0;
912

221448
    while ((v < FX_MAX_LAST_NAME_LEN) && (original_name[j]))
913
    {
914
915
        /* Copy one character.   */
916
199240
        media_ptr -> fx_media_last_found_name[v] =  original_name[j];
917
918
        /* Move to next character.  */
919
199240
        v++;
920
199240
        j++;
921
    }
922
923
    /* Null terminate the last name string.   */
924
22208
    if (v< FX_MAX_LAST_NAME_LEN)
925
    {
926
927
        /* Null terminate.  */
928
22058
        media_ptr -> fx_media_last_found_name[v] =  FX_NULL;
929
    }
930
    else
931
    {
932
933
        /* The string is too big, NULL the string so it won't be used in searching.  */
934
150
        media_ptr -> fx_media_last_found_name[0] =  FX_NULL;
935
    }
936
937
    /* Determine if there is a search pointer.  */
938
22208
    if (search_dir_ptr)
939
    {
940
941
        /* Yes, there is a search directory pointer so save it!   */
942
3021
        media_ptr -> fx_media_last_found_directory =  *search_dir_ptr;
943
944
        /* Indicate the search directory is valid.  */
945
3021
        media_ptr -> fx_media_last_found_directory_valid =  FX_TRUE;
946
    }
947
    else
948
    {
949
950
        /* Indicate the search directory is not valid.  */
951
19187
        media_ptr -> fx_media_last_found_directory_valid =  FX_FALSE;
952
    }
953
954
    /* Copy the directory entry.  */
955
22208
    media_ptr -> fx_media_last_found_entry =  *entry_ptr;
956
957
    /* Setup the directory entry for the last found internal file name.  */
958
22208
    media_ptr -> fx_media_last_found_entry.fx_dir_entry_name =  media_ptr -> fx_media_last_found_file_name;
959
960
    /* Copy the actual directory name into the cached directory name.  */
961
217372
    for (index = 0; index < FX_MAX_LONG_NAME_LEN; index++)
962
    {
963
964
        /* Copy character into the cached directory name.  */
965
217353
        media_ptr -> fx_media_last_found_file_name[index] =  entry_ptr ->  fx_dir_entry_name[index];
966
967
        /* See if we have copied the NULL termination character.  */
968
217353
        if (entry_ptr -> fx_dir_entry_name[index] == (CHAR)FX_NULL)
969
        {
970
971
            /* Check to see if we use the break to get out of the loop.  */
972
22208
            if (index < (FX_MAX_LONG_NAME_LEN - 1))
973
            {
974
975
                /* Yes, not at the end of the string, break.  */
976
22189
                break;
977
            }
978
        }
979
    }
980
#endif
981
982
22208
    return(FX_SUCCESS);
983
}
984