GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: fx_directory_create.c Lines: 144 144 100.0 %
Date: 2024-01-10 21:53:23 Branches: 64 64 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_file.h"
32
#include "fx_utility.h"
33
#ifdef FX_ENABLE_FAULT_TOLERANT
34
#include "fx_fault_tolerant.h"
35
#endif /* FX_ENABLE_FAULT_TOLERANT */
36
37
38
/**************************************************************************/
39
/*                                                                        */
40
/*  FUNCTION                                               RELEASE        */
41
/*                                                                        */
42
/*    _fx_directory_create                                PORTABLE C      */
43
/*                                                           6.1          */
44
/*  AUTHOR                                                                */
45
/*                                                                        */
46
/*    William E. Lamie, Microsoft Corporation                             */
47
/*                                                                        */
48
/*  DESCRIPTION                                                           */
49
/*                                                                        */
50
/*    This function first attempts to find the specified directory.       */
51
/*    If found, the create request is invalid and an error is returned    */
52
/*    to the caller.  After the file name verification is made, a search  */
53
/*    for a free directory entry will be made.  If nothing is available,  */
54
/*    an error will be returned to the caller.  Otherwise, if all is      */
55
/*    okay, an empty directory will be created.                           */
56
/*                                                                        */
57
/*  INPUT                                                                 */
58
/*                                                                        */
59
/*    media_ptr                             Media control block pointer   */
60
/*    directory_name                        Directory name                */
61
/*                                                                        */
62
/*  OUTPUT                                                                */
63
/*                                                                        */
64
/*    return status                                                       */
65
/*                                                                        */
66
/*  CALLS                                                                 */
67
/*                                                                        */
68
/*    _fx_directory_entry_write             Write the new directory entry */
69
/*    _fx_directory_name_extract            Pickup next part of name      */
70
/*    _fx_directory_search                  Search for the file name in   */
71
/*                                          the directory structure       */
72
/*    _fx_directory_free_search             Search for a free directory   */
73
/*                                            entry                       */
74
/*    _fx_utility_exFAT_bitmap_free_cluster_find                          */
75
/*                                            Find exFAT free cluster     */
76
/*    _fx_utility_exFAT_cluster_state_set   Set cluster state             */
77
/*    _fx_utility_FAT_flush                 Flush written FAT entries     */
78
/*    _fx_utility_FAT_entry_read            Read a FAT entry              */
79
/*    _fx_utility_FAT_entry_write           Write a FAT entry             */
80
/*    _fx_utility_logical_sector_flush      Flush the written log sector  */
81
/*    _fx_utility_logical_sector_read       Read logical sector           */
82
/*    _fx_fault_tolerant_transaction_start  Start fault tolerant          */
83
/*                                            transaction                 */
84
/*    _fx_fault_tolerant_transaction_end    End fault tolerant transaction*/
85
/*    _fx_fault_tolerant_recover            Recover FAT chain             */
86
/*    _fx_fault_tolerant_reset_log_file     Reset the log file            */
87
/*                                                                        */
88
/*  CALLED BY                                                             */
89
/*                                                                        */
90
/*    Application Code                                                    */
91
/*                                                                        */
92
/*  RELEASE HISTORY                                                       */
93
/*                                                                        */
94
/*    DATE              NAME                      DESCRIPTION             */
95
/*                                                                        */
96
/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
97
/*  09-30-2020     William E. Lamie         Modified comment(s),          */
98
/*                                            resulting in version 6.1    */
99
/*                                                                        */
100
/**************************************************************************/
101
22143
UINT  _fx_directory_create(FX_MEDIA *media_ptr, CHAR *directory_name)
102
{
103
104
UINT         status;
105
ULONG        FAT_index;
106
ULONG        FAT_value;
107
UINT         sectors;
108
ULONG        total_clusters;
109
CHAR        *work_ptr;
110
ULONG64      logical_sector;
111
ULONG        i;
112
FX_DIR_ENTRY dir_entry;
113
FX_DIR_ENTRY sub_dir_entry;
114
FX_DIR_ENTRY search_directory;
115
116
#ifdef FX_ENABLE_EXFAT
117
ULONG64      dir_size;
118
#endif /* FX_ENABLE_EXFAT */
119
FX_INT_SAVE_AREA
120
121
122
#ifndef FX_MEDIA_STATISTICS_DISABLE
123
124
    /* Increment the number of times this service has been called.  */
125
22143
    media_ptr -> fx_media_directory_creates++;
126
#endif
127
128
    /* Determine if the supplied name is less than the maximum supported name size. The
129
       maximum name (FX_MAX_LONG_NAME_LEN) is defined in fx_api.h.  */
130
22143
    i =  0;
131
22143
    work_ptr =  (CHAR *)directory_name;
132

128139
    while (*work_ptr && (i < FX_MAX_LONG_NAME_LEN))
133
    {
134
135
        /* Determine if the character designates a new path.  */
136

105996
        if ((*work_ptr == '\\') || (*work_ptr == '/'))
137
        {
138
            /* Yes, reset the name size.  */
139
779
            i =  0;
140
        }
141
        /* Check for leading spaces.  */
142

105217
        else if ((*work_ptr != ' ') || (i != 0))
143
        {
144
145
            /* No leading spaces, increment the name size.  */
146
105151
            i++;
147
        }
148
149
        /* Move to the next character.  */
150
105996
        work_ptr++;
151
    }
152
153
    /* Determine if the supplied name is valid.  */
154

22143
    if ((i == 0) || (i >= FX_MAX_LONG_NAME_LEN))
155
    {
156
157
        /* Return an invalid name value.  */
158
2
        return(FX_INVALID_NAME);
159
    }
160
161
    /* Setup pointer to media name buffer.  */
162
22141
    dir_entry.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
163
164
    /* Setup search directory pointer to another media name buffer.  */
165
22141
    search_directory.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN * 2;
166
167
    /* Clear the short name string.  */
168
22141
    dir_entry.fx_dir_entry_short_name[0] =  0;
169
170
    /* Clear the search short name string.  */
171
22141
    search_directory.fx_dir_entry_short_name[0] =  0;
172
173
    /* Check the media to make sure it is open.  */
174
22141
    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
175
    {
176
177
        /* Return the media not opened error.  */
178
1
        return(FX_MEDIA_NOT_OPEN);
179
    }
180
181
    /* If trace is enabled, insert this event into the trace buffer.  */
182
    FX_TRACE_IN_LINE_INSERT(FX_TRACE_DIRECTORY_CREATE, media_ptr, directory_name, 0, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
183
184
    /* Protect against other threads accessing the media.  */
185
22140
    FX_PROTECT
186
187
    /* Check for write protect at the media level (set by driver).  */
188
22140
    if (media_ptr -> fx_media_driver_write_protect)
189
    {
190
191
        /* Release media protection.  */
192
1
        FX_UNPROTECT
193
194
        /* Return write protect error.  */
195
1
        return(FX_WRITE_PROTECT);
196
    }
197
198
    /* Make sure there is at least one cluster remaining for the new file.  */
199
22139
    if (!media_ptr -> fx_media_available_clusters)
200
    {
201
202
        /* Release media protection.  */
203
1
        FX_UNPROTECT
204
205
        /* Return a no-space error.  */
206
1
        return(FX_NO_MORE_SPACE);
207
    }
208
209
    /* Search the system for the supplied directory name.  */
210
22138
    status =  _fx_directory_search(media_ptr, directory_name, &dir_entry, &search_directory, &work_ptr);
211
212
    /* Determine if the search was successful.  */
213
22138
    if (status == FX_SUCCESS)
214
    {
215
216
        /* Release media protection.  */
217
2287
        FX_UNPROTECT
218
219
        /* Directory found - Return the error code.  */
220
2287
        return(FX_ALREADY_CREATED);
221
    }
222
223
    /* Determine if there is anything left after the name.  */
224
19851
    if (_fx_directory_name_extract(work_ptr, &dir_entry.fx_dir_entry_name[0]))
225
    {
226
227
        /* Release media protection.  */
228
1
        FX_UNPROTECT
229
230
        /* Extra information after the file name, return an invalid name
231
           error.  */
232
1
        return(FX_INVALID_PATH);
233
    }
234
235
#ifdef FX_ENABLE_EXFAT
236
    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
237
    {
238
        if (((dir_entry.fx_dir_entry_name[0] == '.') && (dir_entry.fx_dir_entry_name[1] == 0)) ||
239
            ((dir_entry.fx_dir_entry_name[0] == '.') && (dir_entry.fx_dir_entry_name[1] == '.') && (dir_entry.fx_dir_entry_name[2] == 0)))
240
        {
241
242
            /* Release media protection.  */
243
            FX_UNPROTECT
244
245
            /* We don't need '.' or '..' dirs for exFAT.  */
246
            return(FX_ALREADY_CREATED);
247
        }
248
    }
249
250
    /* Save the directory entry size.  */
251
    dir_size = search_directory.fx_dir_entry_file_size;
252
#endif /* FX_ENABLE_EXFAT */
253
254
#ifdef FX_ENABLE_FAULT_TOLERANT
255
    /* Start transaction. */
256
    _fx_fault_tolerant_transaction_start(media_ptr);
257
#endif /* FX_ENABLE_FAULT_TOLERANT */
258
259
    /* Find a free slot for the new directory.  */
260
19850
    status =  _fx_directory_free_search(media_ptr, &search_directory, &dir_entry);
261
262
    /* Determine if the search was successful.  */
263
19850
    if (status != FX_SUCCESS)
264
    {
265
266
#ifdef FX_ENABLE_FAULT_TOLERANT
267
        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
268
#endif /* FX_ENABLE_FAULT_TOLERANT */
269
270
        /* Release media protection.  */
271
86
        FX_UNPROTECT
272
273
        /* Return the error code.  */
274
86
        return(status);
275
    }
276
277
    /* Now allocate a cluster for our new sub-directory entry.  */
278
#ifdef FX_ENABLE_EXFAT
279
    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
280
    {
281
282
        /* Find free cluster from exFAT media.  */
283
        status = _fx_utility_exFAT_bitmap_free_cluster_find(media_ptr,
284
                                                            media_ptr -> fx_media_cluster_search_start,
285
                                                            &FAT_index);
286
287
        /* Check for a bad status.  */
288
        if (status != FX_SUCCESS)
289
        {
290
291
#ifdef FX_ENABLE_FAULT_TOLERANT
292
            FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
293
#endif /* FX_ENABLE_FAULT_TOLERANT */
294
295
            /* Release media protection.  */
296
            FX_UNPROTECT
297
298
            /* Return the bad status.  */
299
            return(status);
300
        }
301
    }
302
    else
303
    {
304
#endif /* FX_ENABLE_EXFAT */
305
306
19764
        FAT_index    =      media_ptr -> fx_media_cluster_search_start;
307
19764
        total_clusters =    media_ptr -> fx_media_total_clusters;
308
309
        /* Loop to find the first available cluster.  */
310
        do
311
        {
312
313
            /* Make sure we don't go past the FAT table.  */
314
19766
            if (!total_clusters)
315
            {
316
317
#ifdef FX_ENABLE_FAULT_TOLERANT
318
                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
319
#endif /* FX_ENABLE_FAULT_TOLERANT */
320
321
                /* Release media protection.  */
322
1
                FX_UNPROTECT
323
324
                /* Something is wrong with the media - the desired clusters were
325
                   not found in the FAT table.  */
326
1
                return(FX_NO_MORE_SPACE);
327
            }
328
329
            /* Read FAT entry.  */
330
19765
            status =  _fx_utility_FAT_entry_read(media_ptr, FAT_index, &FAT_value);
331
332
            /* Check for a bad status.  */
333
19765
            if (status != FX_SUCCESS)
334
            {
335
336
#ifdef FX_ENABLE_FAULT_TOLERANT
337
                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
338
#endif /* FX_ENABLE_FAULT_TOLERANT */
339
340
                /* Release media protection.  */
341
1
                FX_UNPROTECT
342
343
                /* Return the bad status.  */
344
1
                return(status);
345
            }
346
347
            /* Decrement the total cluster count.  */
348
19764
            total_clusters--;
349
350
            /* Determine if the FAT entry is free.  */
351
19764
            if (FAT_value == FX_FREE_CLUSTER)
352
            {
353
354
                /* Move cluster search pointer forward.  */
355
19762
                media_ptr -> fx_media_cluster_search_start =  FAT_index + 1;
356
357
                /* Determine if this needs to be wrapped.  */
358
19762
                if (media_ptr -> fx_media_cluster_search_start >= (media_ptr -> fx_media_total_clusters + FX_FAT_ENTRY_START))
359
                {
360
361
                    /* Wrap the search to the beginning FAT entry.  */
362
1
                    media_ptr -> fx_media_cluster_search_start =  FX_FAT_ENTRY_START;
363
                }
364
365
                /* Break this loop.  */
366
19762
                break;
367
            }
368
            else
369
            {
370
371
                /* FAT entry is not free... Advance the FAT index.  */
372
2
                FAT_index++;
373
374
                /* Determine if we need to wrap the FAT index around.  */
375
2
                if (FAT_index >= (media_ptr -> fx_media_total_clusters + FX_FAT_ENTRY_START))
376
                {
377
378
                    /* Wrap the search to the beginning FAT entry.  */
379
1
                    FAT_index =  FX_FAT_ENTRY_START;
380
                }
381
            }
382
        } while (FX_TRUE);
383
#ifdef FX_ENABLE_EXFAT
384
    }
385
#endif /* FX_ENABLE_EXFAT */
386
387
    /* Decrease the number of available clusters for the media.  */
388
19762
    media_ptr -> fx_media_available_clusters--;
389
390
    /* Defer the writing of the FAT entry until the directory's first sector
391
       has been properly written. If a power loss occurs prior to writing
392
       the FAT entry, it will not result in a lost cluster.  */
393
394
    /* Populate the directory entry.  */
395
396
    /* Isolate the file name.  */
397
19762
    _fx_directory_name_extract(work_ptr, &dir_entry.fx_dir_entry_name[0]);
398
399
    /* Lockout interrupts for time/date access.  */
400
19762
    FX_DISABLE_INTS
401
402
    /* Set time and date stamps.  */
403
19762
    dir_entry.fx_dir_entry_time =  _fx_system_time;
404
19762
    dir_entry.fx_dir_entry_date =  _fx_system_date;
405
406
    /* Restore interrupts.  */
407
19762
    FX_RESTORE_INTS
408
409
    /* Set the attributes for the file.  */
410
19762
    dir_entry.fx_dir_entry_attributes =  FX_DIRECTORY;
411
412
#ifdef FX_ENABLE_EXFAT
413
    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
414
    {
415
        dir_entry.fx_dir_entry_file_size =
416
            media_ptr -> fx_media_sectors_per_cluster * media_ptr -> fx_media_bytes_per_sector;
417
        dir_entry.fx_dir_entry_available_file_size = dir_entry.fx_dir_entry_file_size;
418
419
        /* Don't use FAT by default.  */
420
        dir_entry.fx_dir_entry_dont_use_fat = (CHAR)((INT)((search_directory.fx_dir_entry_dont_use_fat & 1) << 1) | 1);
421
    }
422
    else
423
    {
424
#endif /* FX_ENABLE_EXFAT */
425
426
        /* Set file size to 0. */
427
19762
        dir_entry.fx_dir_entry_file_size =  0;
428
429
#ifdef FX_ENABLE_EXFAT
430
    }
431
#endif /* FX_ENABLE_EXFAT */
432
433
    /* Set the cluster to EOF.  */
434
19762
    dir_entry.fx_dir_entry_cluster =    FAT_index;
435
436
    /* Is there a leading dot?  */
437
19762
    if (dir_entry.fx_dir_entry_name[0] == '.')
438
    {
439
440
        /* Yes, toggle the hidden attribute bit.  */
441
2
        dir_entry.fx_dir_entry_attributes |=  FX_HIDDEN;
442
    }
443
444
    /* In previous versions, the new directory was written here.  It
445
       is now at the bottom of the file - after the FAT and the initial
446
       sub-directory is written out.  This makes the directory create
447
       more fault tolerant.  */
448
449
    /* Calculate the first sector of the sub-directory file.  */
450
19762
    logical_sector =    ((ULONG) media_ptr -> fx_media_data_sector_start) +
451
19762
                         (((ULONG64) FAT_index - FX_FAT_ENTRY_START) *
452
19762
                         ((ULONG) media_ptr -> fx_media_sectors_per_cluster));
453
454
    /* Pickup the number of sectors for the initial sub-directory cluster.  */
455
19762
    sectors =  media_ptr -> fx_media_sectors_per_cluster;
456
457
    /* Read the first logical sector associated with the allocated
458
       cluster.  */
459
19762
    status =  _fx_utility_logical_sector_read(media_ptr, logical_sector,
460
19762
                                              media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
461
462
    /* Determine if an error occurred.  */
463
19762
    if (status != FX_SUCCESS)
464
    {
465
466
#ifdef FX_ENABLE_FAULT_TOLERANT
467
        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
468
#endif /* FX_ENABLE_FAULT_TOLERANT */
469
470
        /* Release media protection.  */
471
1
        FX_UNPROTECT
472
473
        /* Return error code.  */
474
1
        return(status);
475
    }
476
477
    /* Clear the entire first sector of the new sub-directory cluster.  */
478
19761
    work_ptr =  (CHAR *)media_ptr -> fx_media_memory_buffer;
479
19761
    i =  0;
480
656145
    while (i < media_ptr -> fx_media_bytes_per_sector)
481
    {
482
483
        /* Clear 4 bytes.  */
484
636384
        *((ULONG *)work_ptr) =  (ULONG)0;
485
486
        /* Increment pointer.  */
487
636384
        work_ptr =  work_ptr + sizeof(ULONG);
488
489
        /* Increment counter.  */
490
636384
        i =  i + (ULONG)sizeof(ULONG);
491
    }
492
493
#ifdef FX_ENABLE_FAULT_TOLERANT
494
    if (media_ptr -> fx_media_fault_tolerant_enabled == FX_TRUE)
495
    {
496
497
        /* Write back. */
498
        status =  _fx_utility_logical_sector_write(media_ptr, logical_sector,
499
                                                   media_ptr -> fx_media_memory_buffer, (ULONG)1, FX_DIRECTORY_SECTOR);
500
501
        /* Determine if an error occurred.  */
502
        if (status != FX_SUCCESS)
503
        {
504
            FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
505
506
            /* Release media protection.  */
507
            FX_UNPROTECT
508
509
            /* Return error code.  */
510
            return(status);
511
        }
512
513
        /* Force flush the internal logical sector cache.  */
514
        status =  _fx_utility_logical_sector_flush(media_ptr, logical_sector, sectors, FX_TRUE);
515
516
        /* Determine if the write was successful.  */
517
        if (status != FX_SUCCESS)
518
        {
519
            FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
520
521
            /* Release media protection.  */
522
            FX_UNPROTECT
523
524
            /* Return the error code.  */
525
            return(status);
526
        }
527
    }
528
#endif /* FX_ENABLE_FAULT_TOLERANT */
529
530
    /* Determine if there are more sectors to clear in the first cluster of the new
531
       sub-directory.  */
532
19761
    if (sectors > 1)
533
    {
534
535
        /* Yes, invalidate all cached sectors that are contained in the newly allocated first
536
           cluster of the directory.  */
537
538
#ifdef FX_ENABLE_FAULT_TOLERANT
539
        if (media_ptr -> fx_media_fault_tolerant_enabled == FX_FALSE)
540
#endif /* FX_ENABLE_FAULT_TOLERANT */
541
        {
542
543
            /* Flush the internal logical sector cache.  */
544
146
            status =  _fx_utility_logical_sector_flush(media_ptr, logical_sector + 1, ((ULONG64)(sectors - 1)), FX_TRUE);
545
546
            /* Determine if the write was successful.  */
547
146
            if (status != FX_SUCCESS)
548
            {
549
550
#ifdef FX_ENABLE_FAULT_TOLERANT
551
                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
552
#endif /* FX_ENABLE_FAULT_TOLERANT */
553
554
                /* Release media protection.  */
555
1
                FX_UNPROTECT
556
557
                /* Return the error code.  */
558
1
                return(status);
559
            }
560
        }
561
562
        /* Clear all additional sectors of new sub-directory.  */
563
145
        sectors--;
564
1045
        while (sectors)
565
        {
566
567
#ifndef FX_MEDIA_STATISTICS_DISABLE
568
569
            /* Increment the number of driver write sector(s) requests.  */
570
901
            media_ptr -> fx_media_driver_write_requests++;
571
#endif
572
573
            /* Build Write request to the driver.  */
574
901
            media_ptr -> fx_media_driver_request =          FX_DRIVER_WRITE;
575
901
            media_ptr -> fx_media_driver_status =           FX_IO_ERROR;
576
901
            media_ptr -> fx_media_driver_buffer =           media_ptr -> fx_media_memory_buffer;
577
#ifdef FX_DRIVER_USE_64BIT_LBA
578
            media_ptr -> fx_media_driver_logical_sector =   logical_sector + ((ULONG)sectors);
579
#else
580
901
            media_ptr -> fx_media_driver_logical_sector =   (ULONG)logical_sector + ((ULONG)sectors);
581
#endif
582
901
            media_ptr -> fx_media_driver_sectors =          1;
583
901
            media_ptr -> fx_media_driver_sector_type =      FX_DIRECTORY_SECTOR;
584
585
            /* Set the system write flag since we are writing a directory sector.  */
586
901
            media_ptr -> fx_media_driver_system_write =  FX_TRUE;
587
588
            /* If trace is enabled, insert this event into the trace buffer.  */
589
            FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_WRITE, media_ptr, ((ULONG)logical_sector) + ((ULONG)sectors), 1, media_ptr -> fx_media_memory_buffer, FX_TRACE_INTERNAL_EVENTS, 0, 0)
590
591
            /* Invoke the driver to write the sector.  */
592
901
                (media_ptr -> fx_media_driver_entry) (media_ptr);
593
594
            /* Clear the system write flag.  */
595
901
            media_ptr -> fx_media_driver_system_write =  FX_FALSE;
596
597
            /* Determine if an error occurred.  */
598
901
            if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
599
            {
600
601
#ifdef FX_ENABLE_FAULT_TOLERANT
602
                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
603
#endif /* FX_ENABLE_FAULT_TOLERANT */
604
605
                /* Release media protection.  */
606
1
                FX_UNPROTECT
607
608
                /* Return error code.  */
609
1
                return(media_ptr -> fx_media_driver_status);
610
            }
611
612
            /* Decrease the number of sectors to clear.  */
613
900
            sectors--;
614
        }
615
    }
616
617
#ifdef FX_ENABLE_EXFAT
618
    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
619
    {
620
621
        /* Build Write request to the driver.  */
622
        media_ptr -> fx_media_driver_request =          FX_DRIVER_WRITE;
623
        media_ptr -> fx_media_driver_status =           FX_IO_ERROR;
624
        media_ptr -> fx_media_driver_buffer =           media_ptr -> fx_media_memory_buffer;
625
        media_ptr -> fx_media_driver_logical_sector =   (ULONG)logical_sector;
626
        media_ptr -> fx_media_driver_sectors =          1;
627
        media_ptr -> fx_media_driver_sector_type =      FX_DIRECTORY_SECTOR;
628
629
        /* Set the system write flag since we are writing a directory sector.  */
630
        media_ptr -> fx_media_driver_system_write =  FX_TRUE;
631
632
        /* If trace is enabled, insert this event into the trace buffer.  */
633
        FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_WRITE, media_ptr, ((ULONG)logical_sector) + ((ULONG)sectors), 1, media_ptr -> fx_media_memory_buffer, FX_TRACE_INTERNAL_EVENTS, 0, 0)
634
635
        /* Invoke the driver to write the sector.  */
636
            (media_ptr -> fx_media_driver_entry) (media_ptr);
637
638
        /* Clear the system write flag.  */
639
        media_ptr -> fx_media_driver_system_write =  FX_FALSE;
640
641
        /* Determine if an error occurred.  */
642
        if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
643
        {
644
645
#ifdef FX_ENABLE_FAULT_TOLERANT
646
            FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
647
#endif /* FX_ENABLE_FAULT_TOLERANT */
648
649
            /* Release media protection.  */
650
            FX_UNPROTECT
651
652
            /* Return error code.  */
653
            return(media_ptr -> fx_media_driver_status);
654
        }
655
656
        /* Mark the cluster as used.  */
657
        status = _fx_utility_exFAT_cluster_state_set(media_ptr, FAT_index, FX_EXFAT_BITMAP_CLUSTER_OCCUPIED);
658
659
        /* Check for a bad status.  */
660
        if (status != FX_SUCCESS)
661
        {
662
663
#ifdef FX_ENABLE_FAULT_TOLERANT
664
            FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
665
#endif /* FX_ENABLE_FAULT_TOLERANT */
666
667
            /* Release media protection.  */
668
            FX_UNPROTECT
669
670
            /* Return the bad status.  */
671
            return(status);
672
        }
673
674
        /* Move cluster search pointer forward. */
675
        media_ptr -> fx_media_cluster_search_start = FAT_index + 1;
676
677
        /* Determine if this needs to be wrapped. */
678
        if (media_ptr -> fx_media_cluster_search_start >= media_ptr -> fx_media_total_clusters + FX_FAT_ENTRY_START)
679
        {
680
681
            /* Wrap the search to the beginning FAT entry. */
682
            media_ptr -> fx_media_cluster_search_start = FX_FAT_ENTRY_START;
683
        }
684
685
        if (search_directory.fx_dir_entry_name[0])
686
        {
687
688
            /* Not root directory.  */
689
            /* Copy the date and time from the actual sub-directory.  */
690
            search_directory.fx_dir_entry_time = dir_entry.fx_dir_entry_time;
691
            search_directory.fx_dir_entry_date = dir_entry.fx_dir_entry_date;
692
693
            /* Check if the directory size has changed.  */
694
            if (search_directory.fx_dir_entry_file_size == dir_size)
695
            {
696
697
                /* Not changed, we need only update time stamps.  */
698
                status = _fx_directory_exFAT_entry_write(media_ptr, &search_directory, UPDATE_FILE);
699
            }
700
            else
701
            {
702
703
                /* Directory size changed, update time stamps and the stream size.  */
704
                status = _fx_directory_exFAT_entry_write(media_ptr, &search_directory, UPDATE_STREAM);
705
            }
706
707
            /* Check for a bad status.  */
708
            if (status != FX_SUCCESS)
709
            {
710
711
#ifdef FX_ENABLE_FAULT_TOLERANT
712
                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
713
#endif /* FX_ENABLE_FAULT_TOLERANT */
714
715
                /* Release media protection.  */
716
                FX_UNPROTECT
717
718
                /* Return the bad status.  */
719
                return(status);
720
            }
721
        }
722
    }
723
    else
724
    {
725
#endif /* FX_ENABLE_EXFAT */
726
727
        /* Now setup the first sector with the initial sub-directory information.  */
728
729
        /* Copy the base directory entry to the sub-directory entry.  */
730
19759
        sub_dir_entry =  dir_entry;
731
732
        /* Setup pointer to media name buffer.  */
733
19759
        sub_dir_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + (FX_MAX_LONG_NAME_LEN * 3);
734
735
        /* Set the directory entry name to all blanks.  */
736
19759
        work_ptr =  &sub_dir_entry.fx_dir_entry_name[0];
737
237108
        for (i = 0; i < (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE); i++)
738
        {
739
217349
            *work_ptr++ = ' ';
740
        }
741
742
19759
        sub_dir_entry.fx_dir_entry_long_name_present = 0;
743
744
        /* Now build the "." directory entry.  */
745
19759
        sub_dir_entry.fx_dir_entry_name[0] =        '.';
746
19759
        sub_dir_entry.fx_dir_entry_name[1] =        0;
747
19759
        sub_dir_entry.fx_dir_entry_log_sector =     logical_sector;
748
19759
        sub_dir_entry.fx_dir_entry_byte_offset =    0;
749
750
        /* Write the directory's first entry.  */
751
19759
        status =  _fx_directory_entry_write(media_ptr, &sub_dir_entry);
752
753
        /* Check for error condition.  */
754
19759
        if (status != FX_SUCCESS)
755
        {
756
757
#ifdef FX_ENABLE_FAULT_TOLERANT
758
            FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
759
#endif /* FX_ENABLE_FAULT_TOLERANT */
760
761
            /* Release media protection.  */
762
1
            FX_UNPROTECT
763
764
            /* Return error status.  */
765
1
            return(status);
766
        }
767
768
        /* Now build the ".." directory entry.  */
769
770
        /* Determine if the search directory is the root.  */
771
19758
        if (search_directory.fx_dir_entry_name[0])
772
        {
773
774
            /* Previous directory is not the root directory.  */
775
776
            /* Copy into the working directory entry.  */
777
454
            sub_dir_entry =  search_directory;
778
779
            /* Copy the date and time from the actual sub-directory.  */
780
454
            sub_dir_entry.fx_dir_entry_time =  dir_entry.fx_dir_entry_time;
781
454
            sub_dir_entry.fx_dir_entry_date =  dir_entry.fx_dir_entry_date;
782
783
            /* Adjust pointer to media name buffer.  */
784
454
            sub_dir_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + (FX_MAX_LONG_NAME_LEN * 3);
785
786
            /* Change the name to ".."  */
787
454
            work_ptr =  &sub_dir_entry.fx_dir_entry_name[0];
788
5448
            for (i = 0; i < (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE); i++)
789
            {
790
4994
                *work_ptr++ = ' ';
791
            }
792
793
454
            sub_dir_entry.fx_dir_entry_name[0] =  '.';
794
454
            sub_dir_entry.fx_dir_entry_name[1] =  '.';
795
454
            sub_dir_entry.fx_dir_entry_name[2] =   0;
796
797
454
            sub_dir_entry.fx_dir_entry_long_name_present = 0;
798
799
            /* Set file size to 0. */
800
454
            sub_dir_entry.fx_dir_entry_file_size =  0;
801
802
            /* Change the logical sector for this entry.  */
803
454
            sub_dir_entry.fx_dir_entry_log_sector =  logical_sector;
804
        }
805
        else
806
        {
807
808
            /* Just modify the current directory since the parent
809
               directory is the root.  */
810
19304
            sub_dir_entry.fx_dir_entry_name[1] =  '.';
811
19304
            sub_dir_entry.fx_dir_entry_name[2] =   0;
812
813
            /* Clear the cluster to indicate the root directory.  */
814
19304
            sub_dir_entry.fx_dir_entry_cluster =  0;
815
        }
816
817
        /* Setup the byte offset.  */
818
19758
        sub_dir_entry.fx_dir_entry_byte_offset =  FX_DIR_ENTRY_SIZE;
819
820
        /* Write the directory's second entry.  */
821
19758
        status =  _fx_directory_entry_write(media_ptr, &sub_dir_entry);
822
823
        /* Check for error condition.  */
824
19758
        if (status != FX_SUCCESS)
825
        {
826
827
#ifdef FX_ENABLE_FAULT_TOLERANT
828
            FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
829
#endif /* FX_ENABLE_FAULT_TOLERANT */
830
831
            /* Release media protection.  */
832
1
            FX_UNPROTECT
833
834
            /* Return error status.  */
835
1
            return(status);
836
        }
837
838
        /* Write an EOF in the found FAT entry.  */
839
19757
        status =  _fx_utility_FAT_entry_write(media_ptr, FAT_index, media_ptr -> fx_media_fat_last);
840
841
        /* Check for a bad status.  */
842
19757
        if (status != FX_SUCCESS)
843
        {
844
845
#ifdef FX_ENABLE_FAULT_TOLERANT
846
            FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
847
#endif /* FX_ENABLE_FAULT_TOLERANT */
848
849
            /* Release media protection.  */
850
1
            FX_UNPROTECT
851
852
            /* Return the bad status.  */
853
1
            return(status);
854
        }
855
856
#ifdef FX_ENABLE_EXFAT
857
    }
858
#endif /* FX_ENABLE_EXFAT */
859
860
#ifdef FX_FAULT_TOLERANT
861
862
    /* Flush the cached individual FAT entries */
863
    _fx_utility_FAT_flush(media_ptr);
864
#endif
865
866
    /* Now write out the new directory entry.  */
867
#ifdef FX_ENABLE_EXFAT
868
    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
869
    {
870
        status = _fx_directory_exFAT_entry_write(media_ptr, &dir_entry, UPDATE_FULL);
871
    }
872
    else
873
    {
874
#endif /* FX_ENABLE_EXFAT */
875
876
19756
        status = _fx_directory_entry_write(media_ptr, &dir_entry);
877
#ifdef FX_ENABLE_EXFAT
878
    }
879
#endif /* FX_ENABLE_EXFAT */
880
881
#ifdef FX_ENABLE_FAULT_TOLERANT
882
    /* Check for a bad status.  */
883
    if (status != FX_SUCCESS)
884
    {
885
        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
886
887
        /* Release media protection.  */
888
        FX_UNPROTECT
889
890
        /* Return the bad status.  */
891
        return(status);
892
    }
893
894
    /* End transaction. */
895
    status = _fx_fault_tolerant_transaction_end(media_ptr);
896
#endif /* FX_ENABLE_FAULT_TOLERANT */
897
898
    /* Release media protection.  */
899
19756
    FX_UNPROTECT
900
901
    /* Directory create is complete, return status.  */
902
19756
    return(status);
903
}
904