GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: fx_directory_create.c Lines: 144 144 100.0 %
Date: 2024-03-11 05:15:45 Branches: 64 64 100.0 %

Line Branch Exec Source
1
/***************************************************************************
2
 * Copyright (c) 2024 Microsoft Corporation
3
 *
4
 * This program and the accompanying materials are made available under the
5
 * terms of the MIT License which is available at
6
 * https://opensource.org/licenses/MIT.
7
 *
8
 * SPDX-License-Identifier: MIT
9
 **************************************************************************/
10
11
12
/**************************************************************************/
13
/**************************************************************************/
14
/**                                                                       */
15
/** FileX Component                                                       */
16
/**                                                                       */
17
/**   Directory                                                           */
18
/**                                                                       */
19
/**************************************************************************/
20
/**************************************************************************/
21
22
#define FX_SOURCE_CODE
23
24
25
/* Include necessary system files.  */
26
27
#include "fx_api.h"
28
#include "fx_system.h"
29
#include "fx_directory.h"
30
#include "fx_file.h"
31
#include "fx_utility.h"
32
#ifdef FX_ENABLE_FAULT_TOLERANT
33
#include "fx_fault_tolerant.h"
34
#endif /* FX_ENABLE_FAULT_TOLERANT */
35
36
37
/**************************************************************************/
38
/*                                                                        */
39
/*  FUNCTION                                               RELEASE        */
40
/*                                                                        */
41
/*    _fx_directory_create                                PORTABLE C      */
42
/*                                                           6.1          */
43
/*  AUTHOR                                                                */
44
/*                                                                        */
45
/*    William E. Lamie, Microsoft Corporation                             */
46
/*                                                                        */
47
/*  DESCRIPTION                                                           */
48
/*                                                                        */
49
/*    This function first attempts to find the specified directory.       */
50
/*    If found, the create request is invalid and an error is returned    */
51
/*    to the caller.  After the file name verification is made, a search  */
52
/*    for a free directory entry will be made.  If nothing is available,  */
53
/*    an error will be returned to the caller.  Otherwise, if all is      */
54
/*    okay, an empty directory will be created.                           */
55
/*                                                                        */
56
/*  INPUT                                                                 */
57
/*                                                                        */
58
/*    media_ptr                             Media control block pointer   */
59
/*    directory_name                        Directory name                */
60
/*                                                                        */
61
/*  OUTPUT                                                                */
62
/*                                                                        */
63
/*    return status                                                       */
64
/*                                                                        */
65
/*  CALLS                                                                 */
66
/*                                                                        */
67
/*    _fx_directory_entry_write             Write the new directory entry */
68
/*    _fx_directory_name_extract            Pickup next part of name      */
69
/*    _fx_directory_search                  Search for the file name in   */
70
/*                                          the directory structure       */
71
/*    _fx_directory_free_search             Search for a free directory   */
72
/*                                            entry                       */
73
/*    _fx_utility_FAT_flush                 Flush written FAT entries     */
74
/*    _fx_utility_FAT_entry_read            Read a FAT entry              */
75
/*    _fx_utility_FAT_entry_write           Write a FAT entry             */
76
/*    _fx_utility_logical_sector_flush      Flush the written log sector  */
77
/*    _fx_utility_logical_sector_read       Read logical sector           */
78
/*    _fx_fault_tolerant_transaction_start  Start fault tolerant          */
79
/*                                            transaction                 */
80
/*    _fx_fault_tolerant_transaction_end    End fault tolerant transaction*/
81
/*    _fx_fault_tolerant_recover            Recover FAT chain             */
82
/*    _fx_fault_tolerant_reset_log_file     Reset the log file            */
83
/*                                                                        */
84
/*  CALLED BY                                                             */
85
/*                                                                        */
86
/*    Application Code                                                    */
87
/*                                                                        */
88
/*  RELEASE HISTORY                                                       */
89
/*                                                                        */
90
/*    DATE              NAME                      DESCRIPTION             */
91
/*                                                                        */
92
/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
93
/*  09-30-2020     William E. Lamie         Modified comment(s),          */
94
/*                                            resulting in version 6.1    */
95
/*                                                                        */
96
/**************************************************************************/
97
22143
UINT  _fx_directory_create(FX_MEDIA *media_ptr, CHAR *directory_name)
98
{
99
100
UINT         status;
101
ULONG        FAT_index;
102
ULONG        FAT_value;
103
UINT         sectors;
104
ULONG        total_clusters;
105
CHAR        *work_ptr;
106
ULONG64      logical_sector;
107
ULONG        i;
108
FX_DIR_ENTRY dir_entry;
109
FX_DIR_ENTRY sub_dir_entry;
110
FX_DIR_ENTRY search_directory;
111
112
FX_INT_SAVE_AREA
113
114
115
#ifndef FX_MEDIA_STATISTICS_DISABLE
116
117
    /* Increment the number of times this service has been called.  */
118
22143
    media_ptr -> fx_media_directory_creates++;
119
#endif
120
121
    /* Determine if the supplied name is less than the maximum supported name size. The
122
       maximum name (FX_MAX_LONG_NAME_LEN) is defined in fx_api.h.  */
123
22143
    i =  0;
124
22143
    work_ptr =  (CHAR *)directory_name;
125

128139
    while (*work_ptr && (i < FX_MAX_LONG_NAME_LEN))
126
    {
127
128
        /* Determine if the character designates a new path.  */
129

105996
        if ((*work_ptr == '\\') || (*work_ptr == '/'))
130
        {
131
            /* Yes, reset the name size.  */
132
779
            i =  0;
133
        }
134
        /* Check for leading spaces.  */
135

105217
        else if ((*work_ptr != ' ') || (i != 0))
136
        {
137
138
            /* No leading spaces, increment the name size.  */
139
105151
            i++;
140
        }
141
142
        /* Move to the next character.  */
143
105996
        work_ptr++;
144
    }
145
146
    /* Determine if the supplied name is valid.  */
147

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