GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: fx_directory_delete.c Lines: 79 79 100.0 %
Date: 2024-01-10 21:53:23 Branches: 42 42 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_EXFAT
34
#include "fx_directory_exFAT.h"
35
#endif /* FX_ENABLE_EXFAT */
36
#ifdef FX_ENABLE_FAULT_TOLERANT
37
#include "fx_fault_tolerant.h"
38
#endif /* FX_ENABLE_FAULT_TOLERANT */
39
40
41
/**************************************************************************/
42
/*                                                                        */
43
/*  FUNCTION                                               RELEASE        */
44
/*                                                                        */
45
/*    _fx_directory_delete                                PORTABLE C      */
46
/*                                                           6.1          */
47
/*  AUTHOR                                                                */
48
/*                                                                        */
49
/*    William E. Lamie, Microsoft Corporation                             */
50
/*                                                                        */
51
/*  DESCRIPTION                                                           */
52
/*                                                                        */
53
/*    This function first attempts to find the specified directory.       */
54
/*    If found, the directory is examined to make sure it is empty.  If   */
55
/*    the directory is not empty, an error code is returned to the        */
56
/*    caller.  Otherwise, the directory will be deleted and its clusters  */
57
/*    will be made available.                                             */
58
/*                                                                        */
59
/*  INPUT                                                                 */
60
/*                                                                        */
61
/*    media_ptr                             Media control block pointer   */
62
/*    directory_name                        Directory name to delete      */
63
/*                                                                        */
64
/*  OUTPUT                                                                */
65
/*                                                                        */
66
/*    return status                                                       */
67
/*                                                                        */
68
/*  CALLS                                                                 */
69
/*                                                                        */
70
/*    _fx_directory_entry_read              Read a directory entry        */
71
/*    _fx_directory_entry_write             Write the new directory entry */
72
/*    _fx_directory_search                  Search for the file name in   */
73
/*                                          the directory structure       */
74
/*    _fx_utility_logical_sector_flush      Flush the written log sector  */
75
/*    _fx_utility_exFAT_cluster_state_set   Set cluster state             */
76
/*    _fx_utility_FAT_entry_read            Read FAT entries to calculate */
77
/*                                            the sub-directory size      */
78
/*    _fx_utility_FAT_entry_write           Write FAT entry               */
79
/*    _fx_utility_FAT_flush                 Flush FAT cache               */
80
/*    _fx_fault_tolerant_transaction_start  Start fault tolerant          */
81
/*                                            transaction                 */
82
/*    _fx_fault_tolerant_transaction_end    End fault tolerant transaction*/
83
/*    _fx_fault_tolerant_recover            Recover FAT chain             */
84
/*    _fx_fault_tolerant_reset_log_file     Reset the log file            */
85
/*                                                                        */
86
/*  CALLED BY                                                             */
87
/*                                                                        */
88
/*    Application Code                                                    */
89
/*                                                                        */
90
/*  RELEASE HISTORY                                                       */
91
/*                                                                        */
92
/*    DATE              NAME                      DESCRIPTION             */
93
/*                                                                        */
94
/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
95
/*  09-30-2020     William E. Lamie         Modified comment(s),          */
96
/*                                            resulting in version 6.1    */
97
/*                                                                        */
98
/**************************************************************************/
99
218
UINT  _fx_directory_delete(FX_MEDIA *media_ptr, CHAR *directory_name)
100
{
101
102
UINT         status;
103
ULONG        cluster, next_cluster;
104
ULONG        i, directory_size;
105
FX_DIR_ENTRY dir_entry;
106
FX_DIR_ENTRY search_directory;
107
FX_DIR_ENTRY search_entry;
108
109
#ifdef FX_ENABLE_EXFAT
110
ULONG        clusters_count;
111
ULONG        bytes_per_cluster;
112
#endif /* FX_ENABLE_EXFAT */
113
114
115
#ifndef FX_MEDIA_STATISTICS_DISABLE
116
117
    /* Increment the number of times this service has been called.  */
118
218
    media_ptr -> fx_media_directory_deletes++;
119
#endif
120
121
    /* Setup pointer to media name buffer.  */
122
218
    dir_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
123
124
    /* Setup search pointer to media name buffer.  */
125
218
    search_directory.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN * 2;
126
127
    /* Setup search entry pointer to media name buffer.  */
128
218
    search_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN * 3;
129
130
    /* Clear the short name string of the three file names that will be worked with.  */
131
218
    dir_entry.fx_dir_entry_short_name[0] =  0;
132
218
    search_directory.fx_dir_entry_short_name[0] =  0;
133
218
    search_entry.fx_dir_entry_short_name[0] =  0;
134
135
    /* Check the media to make sure it is open.  */
136
218
    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
137
    {
138
139
        /* Return the media not opened error.  */
140
1
        return(FX_MEDIA_NOT_OPEN);
141
    }
142
143
    /* If trace is enabled, insert this event into the trace buffer.  */
144
    FX_TRACE_IN_LINE_INSERT(FX_TRACE_DIRECTORY_DELETE, media_ptr, directory_name, 0, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
145
146
    /* Protect against other threads accessing the media.  */
147
217
    FX_PROTECT
148
149
#ifdef FX_ENABLE_FAULT_TOLERANT
150
    /* Start transaction. */
151
    _fx_fault_tolerant_transaction_start(media_ptr);
152
#endif /* FX_ENABLE_FAULT_TOLERANT */
153
154
    /* Check for write protect at the media level (set by driver).  */
155
217
    if (media_ptr -> fx_media_driver_write_protect)
156
    {
157
158
#ifdef FX_ENABLE_FAULT_TOLERANT
159
        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
160
#endif /* FX_ENABLE_FAULT_TOLERANT */
161
162
        /* Release media protection.  */
163
1
        FX_UNPROTECT
164
165
        /* Return write protect error.  */
166
1
        return(FX_WRITE_PROTECT);
167
    }
168
169
    /* Search the system for the supplied directory name.  */
170
216
    status =  _fx_directory_search(media_ptr, directory_name, &dir_entry, FX_NULL, FX_NULL);
171
172
    /* Determine if the search was successful.  */
173
216
    if (status != FX_SUCCESS)
174
    {
175
176
#ifdef FX_ENABLE_FAULT_TOLERANT
177
        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
178
#endif /* FX_ENABLE_FAULT_TOLERANT */
179
180
        /* Release media protection.  */
181
2
        FX_UNPROTECT
182
183
        /* Return the error code.  */
184
2
        return(status);
185
    }
186
187
    /* Check to make sure the found entry is a directory.  */
188
214
    if (!(dir_entry.fx_dir_entry_attributes & (UCHAR)(FX_DIRECTORY)))
189
    {
190
191
#ifdef FX_ENABLE_FAULT_TOLERANT
192
        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
193
#endif /* FX_ENABLE_FAULT_TOLERANT */
194
195
        /* Release media protection.  */
196
1
        FX_UNPROTECT
197
198
        /* Return the not a directory error code.  */
199
1
        return(FX_NOT_DIRECTORY);
200
    }
201
202
    /* Check if the entry is read only */
203
213
    if (dir_entry.fx_dir_entry_attributes & (UCHAR)(FX_READ_ONLY))
204
    {
205
#ifdef FX_ENABLE_FAULT_TOLERANT
206
        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
207
#endif /* FX_ENABLE_FAULT_TOLERANT */
208
209
        /* Release media protection.  */
210
1
        FX_UNPROTECT
211
212
        /* Return the not a directory error code.  */
213
1
        return(FX_WRITE_PROTECT);
214
    }
215
216
    /* Copy the directory entry to the search directory structure for
217
       looking at the specified sub-directory contents.  */
218
212
    search_directory =  dir_entry;
219
220
    /* Ensure that the search directory's last search cluster is cleared.  */
221
212
    search_directory.fx_dir_entry_last_search_cluster =  0;
222
223
#ifdef FX_ENABLE_EXFAT
224
    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
225
    {
226
        directory_size = (ULONG)search_directory.fx_dir_entry_file_size / FX_DIR_ENTRY_SIZE;
227
    }
228
    else
229
    {
230
#endif /* FX_ENABLE_EXFAT */
231
232
        /* Calculate the directory size by counting the allocated
233
           clusters for it.  */
234
212
        i =        0;
235
212
        cluster =  search_directory.fx_dir_entry_cluster;
236
460
        while (cluster < media_ptr -> fx_media_fat_reserved)
237
        {
238
239
            /* Increment the cluster count.  */
240
252
            i++;
241
242
            /* Read the next FAT entry.  */
243
252
            status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
244
245
            /* Check the return status.  */
246
252
            if (status != FX_SUCCESS)
247
            {
248
249
#ifdef FX_ENABLE_FAULT_TOLERANT
250
                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
251
#endif /* FX_ENABLE_FAULT_TOLERANT */
252
253
                /* Release media protection.  */
254
1
                FX_UNPROTECT
255
256
                /* Return the bad status.  */
257
1
                return(status);
258
            }
259
260

251
            if ((cluster < FX_FAT_ENTRY_START) || (cluster == next_cluster) || (i > media_ptr -> fx_media_total_clusters))
261
            {
262
#ifdef FX_ENABLE_FAULT_TOLERANT
263
               FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
264
#endif /* FX_ENABLE_FAULT_TOLERANT */
265
266
                /* Release media protection.  */
267
3
                FX_UNPROTECT
268
269
                /* Return the bad status.  */
270
3
                return(FX_FAT_READ_ERROR);
271
            }
272
273
248
            cluster = next_cluster;
274
        }
275
276
        /* Now we can calculate the directory size.  */
277
208
        directory_size =  (((ULONG)media_ptr -> fx_media_bytes_per_sector) *
278
208
                           ((ULONG)media_ptr -> fx_media_sectors_per_cluster) * i) /
279
                           (ULONG)FX_DIR_ENTRY_SIZE;
280
281
        /* Also save this in the directory entry so we don't have to
282
           calculate it later.  */
283
208
        search_directory.fx_dir_entry_file_size =  directory_size;
284
#ifdef FX_ENABLE_EXFAT
285
    }
286
#endif /* FX_ENABLE_EXFAT */
287
288
    /* Make sure the new name is not in the current directory.  */
289
#ifdef FX_ENABLE_EXFAT
290
    if (directory_size > 0)
291
    {
292
293
        /* exFAT directories do not record '.' and '..' directories.  */
294
        if (media_ptr -> fx_media_FAT_type == FX_exFAT)
295
        {
296
            i = 0;
297
        }
298
        else
299
        {
300
            i = 2;
301
        }
302
#else
303
        /* The first two entries are skipped because they are just part of the sub-directory.  */
304
208
        i = 2;
305
#endif /* FX_ENABLE_EXFAT */
306
307
        do
308
        {
309
310
            /* Read an entry from the directory.  */
311
408
            status = _fx_directory_entry_read(media_ptr, &search_directory, &i, &search_entry);
312
313
            /* Check for error status.  */
314
408
            if (status != FX_SUCCESS)
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
                /* Return error condition.  */
325
1
                return(status);
326
            }
327
328
            /* Determine if this is the last directory entry.  */
329
#ifdef FX_ENABLE_EXFAT
330
            if (search_entry.fx_dir_entry_type == FX_EXFAT_DIR_ENTRY_TYPE_END_MARKER)
331
#else
332
407
            if (search_entry.fx_dir_entry_name[0] == FX_DIR_ENTRY_DONE)
333
#endif /* FX_ENABLE_EXFAT */
334
            {
335
195
                break;
336
            }
337
338
#ifdef FX_ENABLE_EXFAT
339
            if (media_ptr -> fx_media_FAT_type == FX_exFAT)
340
            {
341
342
                /* Skip '.' and '..' folders if exists.  */
343
                if ((i == 1) && (search_entry.fx_dir_entry_type == FX_EXFAT_DIR_ENTRY_TYPE_FILE_DIRECTORY) &&
344
                    (search_entry.fx_dir_entry_name[0] == '.') &&
345
                    (search_entry.fx_dir_entry_name[1] == 0))
346
                {
347
348
                    continue;
349
                }
350
                if ((i == 2) && (search_entry.fx_dir_entry_type == FX_EXFAT_DIR_ENTRY_TYPE_FILE_DIRECTORY) &&
351
                    (search_entry.fx_dir_entry_name[0] == '.') && (search_entry.fx_dir_entry_name[1] == '.') &&
352
                    (search_entry.fx_dir_entry_name[2] == 0))
353
                {
354
355
                    continue;
356
                }
357
            }
358
#endif /* FX_ENABLE_EXFAT */
359
360
            /* Determine if this is an empty entry.  */
361
#ifdef FX_ENABLE_EXFAT
362
            if (search_entry.fx_dir_entry_type != FX_EXFAT_DIR_ENTRY_TYPE_FREE)
363
#else
364
212
            if ((UCHAR)search_entry.fx_dir_entry_name[0] != (UCHAR)FX_DIR_ENTRY_FREE)
365
#endif /* FX_ENABLE_EXFAT */
366
            {
367
368
#ifdef FX_ENABLE_FAULT_TOLERANT
369
                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
370
#endif /* FX_ENABLE_FAULT_TOLERANT */
371
372
                /* Release media protection.  */
373
1
                FX_UNPROTECT
374
375
                /* Return error status.  */
376
1
                return(FX_DIR_NOT_EMPTY);
377
            }
378
379
211
            i++;
380
211
        } while (i < directory_size);
381
#ifdef FX_ENABLE_EXFAT
382
    }
383
#endif /* FX_ENABLE_EXFAT */
384
385
    /* At this point, we are going to delete the empty directory.  */
386
387
#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
388
389
    /* Invalidate the directory search saved information.  */
390
206
    media_ptr -> fx_media_last_found_name[0] =  FX_NULL;
391
#endif
392
393
    /* Mark the sub-directory entry as available.  */
394
206
    dir_entry.fx_dir_entry_name[0] =  (CHAR)FX_DIR_ENTRY_FREE;
395
206
    dir_entry.fx_dir_entry_short_name[0] =  (CHAR)FX_DIR_ENTRY_FREE;
396
397
    /* Now write out the directory entry.  */
398
#ifdef FX_ENABLE_EXFAT
399
    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
400
    {
401
402
        status =  _fx_directory_exFAT_entry_write(media_ptr, &dir_entry, UPDATE_DELETE);
403
    }
404
    else
405
    {
406
#endif /* FX_ENABLE_EXFAT */
407
206
        status =  _fx_directory_entry_write(media_ptr, &dir_entry);
408
#ifdef FX_ENABLE_EXFAT
409
    }
410
#endif /* FX_ENABLE_EXFAT */
411
412
    /* Determine if the write was successful.  */
413
206
    if (status != FX_SUCCESS)
414
    {
415
416
#ifdef FX_ENABLE_FAULT_TOLERANT
417
        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
418
#endif /* FX_ENABLE_FAULT_TOLERANT */
419
420
        /* Release media protection.  */
421
1
        FX_UNPROTECT
422
423
        /* Return the error code.  */
424
1
        return(status);
425
    }
426
427
#ifdef FX_ENABLE_EXFAT
428
    bytes_per_cluster =  ((ULONG)media_ptr -> fx_media_bytes_per_sector) *
429
        ((ULONG)media_ptr -> fx_media_sectors_per_cluster);
430
431
    i = 0;
432
433
    clusters_count = (ULONG)((search_directory.fx_dir_entry_file_size + bytes_per_cluster - 1) / bytes_per_cluster - 1);
434
#endif /* FX_ENABLE_EXFAT */
435
436
    /* Walk through the directory's clusters and release them.  */
437
205
    cluster =  search_directory.fx_dir_entry_cluster;
438
439
444
    while (cluster < media_ptr -> fx_media_fat_reserved)
440
    {
441
442
        /* Increment the cluster count.  */
443
244
        i++;
444
445
#ifdef FX_ENABLE_EXFAT
446
447
        /* Read the next FAT entry.  */
448
        if (search_directory.fx_dir_entry_dont_use_fat & 1)
449
        {
450
451
            /* Check for file size range */
452
            if (i - 1 >= clusters_count)
453
            {
454
                next_cluster = FX_LAST_CLUSTER_exFAT;
455
            }
456
            else
457
            {
458
                next_cluster = cluster + 1;
459
            }
460
        }
461
        else
462
        {
463
464
#endif /* FX_ENABLE_EXFAT */
465
466
            /* Read the next FAT entry.  */
467
244
            status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
468
469
            /* Check the return status.  */
470
244
            if (status != FX_SUCCESS)
471
            {
472
473
#ifdef FX_ENABLE_FAULT_TOLERANT
474
                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
475
#endif /* FX_ENABLE_FAULT_TOLERANT */
476
477
                /* Release media protection.  */
478
1
                FX_UNPROTECT
479
480
                /* Return the bad status.  */
481
1
                return(status);
482
            }
483
#ifdef FX_ENABLE_EXFAT
484
        }
485
#endif /* FX_ENABLE_EXFAT */
486
487

243
        if ((cluster < FX_FAT_ENTRY_START) || (cluster == next_cluster) || (i > media_ptr -> fx_media_total_clusters))
488
        {
489
490
#ifdef FX_ENABLE_FAULT_TOLERANT
491
            FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
492
#endif /* FX_ENABLE_FAULT_TOLERANT */
493
494
            /* Release media protection.  */
495
3
            FX_UNPROTECT
496
497
            /* Return the bad status.  */
498
3
            return(FX_FAT_READ_ERROR);
499
        }
500
501
        /* Release the current cluster.  */
502
#ifdef FX_ENABLE_EXFAT
503
        if (!(search_directory.fx_dir_entry_dont_use_fat & 1))
504
        {
505
#endif /* FX_ENABLE_EXFAT */
506
507
240
            status =  _fx_utility_FAT_entry_write(media_ptr, cluster, FX_FREE_CLUSTER);
508
509
            /* Check the return status.  */
510
240
            if (status != FX_SUCCESS)
511
            {
512
513
#ifdef FX_ENABLE_FAULT_TOLERANT
514
                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
515
#endif /* FX_ENABLE_FAULT_TOLERANT */
516
517
                /* Release media protection.  */
518
1
                FX_UNPROTECT
519
520
                /* Return the bad status.  */
521
1
                return(status);
522
            }
523
#ifdef FX_ENABLE_EXFAT
524
        }
525
526
        if (media_ptr -> fx_media_FAT_type == FX_exFAT)
527
        {
528
529
            /* Mark the cluster as free.  */
530
            status = _fx_utility_exFAT_cluster_state_set(media_ptr, cluster, FX_EXFAT_BITMAP_CLUSTER_FREE);
531
532
            /* Check the return status.  */
533
            if (status != FX_SUCCESS)
534
            {
535
536
#ifdef FX_ENABLE_FAULT_TOLERANT
537
                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
538
#endif /* FX_ENABLE_FAULT_TOLERANT */
539
540
                /* Release media protection.  */
541
                FX_UNPROTECT
542
543
                /* Return the bad status.  */
544
                return(status);
545
            }
546
        }
547
#endif /* FX_ENABLE_EXFAT */
548
549
        /* Increment the number of available clusters for the media.  */
550
239
        media_ptr -> fx_media_available_clusters++;
551
552
        /* Copy next cluster to current cluster.  */
553
239
        cluster =  next_cluster;
554
    }
555
556
#ifdef FX_FAULT_TOLERANT
557
558
    /* Flush the cached individual FAT entries */
559
    _fx_utility_FAT_flush(media_ptr);
560
#endif
561
562
    /* Flush the logical sector cache.  */
563
200
    status =  _fx_utility_logical_sector_flush(media_ptr, ((ULONG64) 1), (ULONG64)(media_ptr -> fx_media_sectors_per_FAT), FX_FALSE);
564
565
#ifdef FX_ENABLE_FAULT_TOLERANT
566
    /* Check for a bad status.  */
567
    if (status != FX_SUCCESS)
568
    {
569
570
        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
571
572
        /* Release media protection.  */
573
        FX_UNPROTECT
574
575
        /* Return the bad status.  */
576
        return(status);
577
    }
578
579
    /* End transaction. */
580
    status = _fx_fault_tolerant_transaction_end(media_ptr);
581
#endif /* FX_ENABLE_FAULT_TOLERANT */
582
583
    /* Release media protection.  */
584
200
    FX_UNPROTECT
585
586
    /* Directory delete is complete, return status.  */
587
200
    return(status);
588
}
589