GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: fx_file_delete.c Lines: 57 57 100.0 %
Date: 2024-01-10 21:53:23 Branches: 30 30 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
/**   File                                                                */
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_file_delete                                     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 file.  If found, */
51
/*    the delete request is valid and all of its clusters will be         */
52
/*    released and its directory entry will be marked as available.       */
53
/*    Otherwise, if the file is not found, the appropriate error code is  */
54
/*    returned to the caller.                                             */
55
/*                                                                        */
56
/*  INPUT                                                                 */
57
/*                                                                        */
58
/*    media_ptr                             Media control block pointer   */
59
/*    file_name                             File name pointer             */
60
/*                                                                        */
61
/*  OUTPUT                                                                */
62
/*                                                                        */
63
/*    return status                                                       */
64
/*                                                                        */
65
/*  CALLS                                                                 */
66
/*                                                                        */
67
/*    _fx_directory_entry_write             Write the new directory entry */
68
/*    _fx_directory_search                  Search for the file name in   */
69
/*                                          the directory structure       */
70
/*    _fx_utility_exFAT_cluster_state_set   Set cluster state             */
71
/*    _fx_utility_FAT_entry_read            Read a FAT entry              */
72
/*    _fx_utility_FAT_entry_write           Write a FAT entry             */
73
/*    _fx_utility_FAT_flush                 Flush written FAT entries     */
74
/*    _fx_fault_tolerant_transaction_start  Start fault tolerant          */
75
/*                                            transaction                 */
76
/*    _fx_fault_tolerant_transaction_end    End fault tolerant transaction*/
77
/*    _fx_fault_tolerant_recover            Recover FAT chain             */
78
/*    _fx_fault_tolerant_reset_log_file     Reset the log file            */
79
/*    _fx_fault_tolerant_set_FAT_chain      Set data of FAT chain         */
80
/*                                                                        */
81
/*  CALLED BY                                                             */
82
/*                                                                        */
83
/*    Application Code                                                    */
84
/*                                                                        */
85
/*  RELEASE HISTORY                                                       */
86
/*                                                                        */
87
/*    DATE              NAME                      DESCRIPTION             */
88
/*                                                                        */
89
/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
90
/*  09-30-2020     William E. Lamie         Modified comment(s),          */
91
/*                                            resulting in version 6.1    */
92
/*                                                                        */
93
/**************************************************************************/
94
111
UINT  _fx_file_delete(FX_MEDIA *media_ptr, CHAR *file_name)
95
{
96
97
UINT         status;
98
ULONG        cluster;
99
ULONG        contents;
100
ULONG        open_count;
101
FX_FILE     *search_ptr;
102
ULONG        cluster_count;
103
FX_DIR_ENTRY dir_entry;
104
UCHAR        not_a_file_attr;
105
#ifdef FX_ENABLE_EXFAT
106
ULONG        bytes_per_cluster;
107
ULONG        clusters_count;
108
#endif /* FX_ENABLE_EXFAT */
109
110
#ifndef FX_MEDIA_STATISTICS_DISABLE
111
112
    /* Increment the number of times this service has been called.  */
113
111
    media_ptr -> fx_media_file_deletes++;
114
#endif
115
116
    /* Setup pointer to media name buffer.  */
117
111
    dir_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
118
119
    /* Clear the short name string.  */
120
111
    dir_entry.fx_dir_entry_short_name[0] =  0;
121
122
    /* Check the media to make sure it is open.  */
123
111
    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
124
    {
125
126
        /* Return the media not opened error.  */
127
1
        return(FX_MEDIA_NOT_OPEN);
128
    }
129
130
    /* If trace is enabled, insert this event into the trace buffer.  */
131
    FX_TRACE_IN_LINE_INSERT(FX_TRACE_FILE_DELETE, media_ptr, file_name, 0, 0, FX_TRACE_FILE_EVENTS, 0, 0)
132
133
    /* Protect against other threads accessing the media.  */
134
110
    FX_PROTECT
135
136
#ifdef FX_ENABLE_FAULT_TOLERANT
137
    /* Start transaction. */
138
    _fx_fault_tolerant_transaction_start(media_ptr);
139
#endif /* FX_ENABLE_FAULT_TOLERANT */
140
141
    /* Check for write protect at the media level (set by driver).  */
142
110
    if (media_ptr -> fx_media_driver_write_protect)
143
    {
144
145
#ifdef FX_ENABLE_FAULT_TOLERANT
146
        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
147
#endif /* FX_ENABLE_FAULT_TOLERANT */
148
149
        /* Release media protection.  */
150
2
        FX_UNPROTECT
151
152
        /* Return write protect error.  */
153
2
        return(FX_WRITE_PROTECT);
154
    }
155
156
    /* Search the system for the supplied file name.  */
157
108
    status =  _fx_directory_search(media_ptr, file_name, &dir_entry, FX_NULL, FX_NULL);
158
159
    /* Determine if the search was successful.  */
160
108
    if (status != FX_SUCCESS)
161
    {
162
163
#ifdef FX_ENABLE_FAULT_TOLERANT
164
        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
165
#endif /* FX_ENABLE_FAULT_TOLERANT */
166
167
        /* Release media protection.  */
168
1
        FX_UNPROTECT
169
170
        /* Return the error code.  */
171
1
        return(status);
172
    }
173
174
#ifdef FX_ENABLE_EXFAT
175
    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
176
    {
177
        not_a_file_attr = FX_DIRECTORY;
178
    }
179
    else
180
    {
181
#endif /* FX_ENABLE_EXFAT */
182
107
        not_a_file_attr = FX_DIRECTORY | FX_VOLUME;
183
#ifdef FX_ENABLE_EXFAT
184
    }
185
#endif /* FX_ENABLE_EXFAT */
186
187
    /* Check to make sure the found entry is a file.  */
188
107
    if (dir_entry.fx_dir_entry_attributes & not_a_file_attr)
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 file error code.  */
199
1
        return(FX_NOT_A_FILE);
200
    }
201
202
    /* Check if the entry is read only */
203
106
    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
    /* Search the opened files to see if this file is currently
217
       opened.  */
218
105
    open_count =  media_ptr -> fx_media_opened_file_count;
219
105
    search_ptr =  media_ptr -> fx_media_opened_file_list;
220
120
    while (open_count)
221
    {
222
223
        /* Look at each opened file to see if the same file is opened.  */
224
16
        if ((search_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector == dir_entry.fx_dir_entry_log_sector) &&
225
14
            (search_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset == dir_entry.fx_dir_entry_byte_offset))
226
        {
227
228
#ifdef FX_ENABLE_FAULT_TOLERANT
229
            FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
230
#endif /* FX_ENABLE_FAULT_TOLERANT */
231
232
            /* Release media protection.  */
233
1
            FX_UNPROTECT
234
235
            /* The file is currently open.  */
236
1
            return(FX_ACCESS_ERROR);
237
        }
238
239
        /* Adjust the pointer and decrement the search count.  */
240
15
        search_ptr =  search_ptr -> fx_file_opened_next;
241
15
        open_count--;
242
    }
243
244
    /* Pickup the starting cluster of the file.  */
245
104
    cluster =           dir_entry.fx_dir_entry_cluster;
246
247
    /* At this point, make the directory entry invalid in order to delete the file.  */
248
249
#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
250
251
    /* Invalidate the directory search saved information.  */
252
104
    media_ptr -> fx_media_last_found_name[0] =  FX_NULL;
253
#endif
254
255
    /* Mark the directory entry as available, while leaving the other
256
       information for the sake of posterity.  */
257
104
    dir_entry.fx_dir_entry_name[0] =        (CHAR)FX_DIR_ENTRY_FREE;
258
104
    dir_entry.fx_dir_entry_short_name[0] =  (CHAR)FX_DIR_ENTRY_FREE;
259
260
    /* Now write out the directory entry.  */
261
#ifdef FX_ENABLE_EXFAT
262
    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
263
    {
264
        status = _fx_directory_exFAT_entry_write(media_ptr, &dir_entry, UPDATE_DELETE);
265
    }
266
    else
267
    {
268
#endif /* FX_ENABLE_EXFAT */
269
104
        status = _fx_directory_entry_write(media_ptr, &dir_entry);
270
#ifdef FX_ENABLE_EXFAT
271
    }
272
#endif /* FX_ENABLE_EXFAT */
273
274
    /* Determine if the write was successful.  */
275
104
    if (status != FX_SUCCESS)
276
    {
277
278
#ifdef FX_ENABLE_FAULT_TOLERANT
279
        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
280
#endif /* FX_ENABLE_FAULT_TOLERANT */
281
282
        /* Release media protection.  */
283
1
        FX_UNPROTECT
284
285
        /* Return the error code.  */
286
1
        return(status);
287
    }
288
289
    /* Now that the directory entry is no longer valid and pointing at the chain of clusters,
290
       walk the chain of allocated FAT entries and mark each of them as free.  */
291
103
    cluster_count =     0;
292
293
#ifdef FX_ENABLE_EXFAT
294
    bytes_per_cluster =  ((ULONG)media_ptr -> fx_media_bytes_per_sector) *
295
        ((ULONG)media_ptr -> fx_media_sectors_per_cluster);
296
297
    clusters_count =
298
        (ULONG)((dir_entry.fx_dir_entry_file_size + bytes_per_cluster - 1) / bytes_per_cluster - 1);
299
#endif /* FX_ENABLE_EXFAT */
300
301
#ifdef FX_ENABLE_FAULT_TOLERANT
302
    if (media_ptr -> fx_media_fault_tolerant_enabled)
303
    {
304
305
        /* Note:  Directory entries are already written to log files. FAT chain is updated as the last step.
306
           Since there are no others FAT entries written to the log.  Therefore there is no need to set
307
           the flag FX_FRAULT_TOLERANT_STATE_SET_FAT_CHAIN here. */
308
#ifdef FX_ENABLE_EXFAT
309
        if (dir_entry.fx_dir_entry_dont_use_fat & 1)
310
        {
311
            status = _fx_fault_tolerant_set_FAT_chain(media_ptr, FX_TRUE, 0,
312
                                                      media_ptr -> fx_media_fat_last, cluster, cluster + clusters_count);
313
        }
314
        else
315
        {
316
#endif /* FX_ENABLE_EXFAT */
317
            status = _fx_fault_tolerant_set_FAT_chain(media_ptr, FX_FALSE, 0,
318
                                                      media_ptr -> fx_media_fat_last, cluster, media_ptr -> fx_media_fat_last);
319
#ifdef FX_ENABLE_EXFAT
320
        }
321
#endif /* FX_ENABLE_EXFAT */
322
323
        /* Determine if the write was successful.  */
324
        if (status != FX_SUCCESS)
325
        {
326
327
            FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
328
329
            /* Release media protection.  */
330
            FX_UNPROTECT
331
332
            /* Return the error code.  */
333
            return(status);
334
        }
335
    }
336
    else
337
    {
338
#endif /* FX_ENABLE_FAULT_TOLERANT */
339
340
        /* Follow the link of FAT entries.  */
341

1601
        while ((cluster >= FX_FAT_ENTRY_START) && (cluster < media_ptr -> fx_media_fat_reserved))
342
        {
343
344
            /* Increment the number of clusters.  */
345
1502
            cluster_count++;
346
347
#ifdef FX_ENABLE_EXFAT
348
            if (dir_entry.fx_dir_entry_dont_use_fat & 1)
349
            {
350
351
                /* Check for file size range.  */
352
                if (cluster_count - 1 >= clusters_count)
353
                {
354
                    contents = FX_LAST_CLUSTER_exFAT;
355
                }
356
                else
357
                {
358
                    contents = cluster + 1;
359
                }
360
            }
361
            else
362
            {
363
#endif /* FX_ENABLE_EXFAT */
364
365
                /* Read the current cluster entry from the FAT.  */
366
1502
                status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &contents);
367
368
                /* Check the return value.  */
369
1502
                if (status != FX_SUCCESS)
370
                {
371
372
#ifdef FX_ENABLE_FAULT_TOLERANT
373
                    FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
374
#endif /* FX_ENABLE_FAULT_TOLERANT */
375
376
                    /* Release media protection.  */
377
1
                    FX_UNPROTECT
378
379
                    /* Return the error status.  */
380
1
                    return(status);
381
                }
382
#ifdef FX_ENABLE_EXFAT
383
            }
384
#endif /* FX_ENABLE_EXFAT */
385
386

1501
            if ((cluster == contents) || (cluster_count > media_ptr -> fx_media_total_clusters))
387
            {
388
389
#ifdef FX_ENABLE_FAULT_TOLERANT
390
                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
391
#endif /* FX_ENABLE_FAULT_TOLERANT */
392
393
                /* Release media protection.  */
394
2
                FX_UNPROTECT
395
396
                /* Return the bad status.  */
397
2
                return(FX_FAT_READ_ERROR);
398
            }
399
400
#ifdef FX_ENABLE_EXFAT
401
            if (!(dir_entry.fx_dir_entry_dont_use_fat & 1))
402
            {
403
#endif /* FX_ENABLE_EXFAT */
404
405
                /* Make the current cluster available.  */
406
1499
                status =  _fx_utility_FAT_entry_write(media_ptr, cluster, FX_FREE_CLUSTER);
407
408
                /* Check the return value.  */
409
1499
                if (status != FX_SUCCESS)
410
                {
411
412
#ifdef FX_ENABLE_FAULT_TOLERANT
413
                    FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
414
#endif /* FX_ENABLE_FAULT_TOLERANT */
415
416
                    /* Release media protection.  */
417
1
                    FX_UNPROTECT
418
419
                    /* Return the error status.  */
420
1
                    return(status);
421
                }
422
#ifdef FX_ENABLE_EXFAT
423
            }
424
425
            if (media_ptr -> fx_media_FAT_type == FX_exFAT)
426
            {
427
428
                /* Mark the cluster as free.  */
429
                status = _fx_utility_exFAT_cluster_state_set(media_ptr, cluster, FX_EXFAT_BITMAP_CLUSTER_FREE);
430
431
                /* Check the return status.  */
432
                if (status != FX_SUCCESS)
433
                {
434
435
#ifdef FX_ENABLE_FAULT_TOLERANT
436
                    FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
437
#endif /* FX_ENABLE_FAULT_TOLERANT */
438
439
                    /* Release media protection.  */
440
                    FX_UNPROTECT
441
442
                    /* Return the bad status.  */
443
                    return(status);
444
                }
445
            }
446
#endif /* FX_ENABLE_EXFAT */
447
448
            /* Setup for the next cluster.  */
449
1498
            cluster =  contents;
450
        }
451
#ifdef FX_ENABLE_FAULT_TOLERANT
452
    }
453
#endif /* FX_ENABLE_FAULT_TOLERANT */
454
455
    /* Update the free clusters in the media control block.  */
456
99
    media_ptr -> fx_media_available_clusters =
457
99
        media_ptr -> fx_media_available_clusters + cluster_count;
458
459
#ifdef FX_FAULT_TOLERANT
460
461
    /* Flush the cached individual FAT entries */
462
    _fx_utility_FAT_flush(media_ptr);
463
#endif
464
465
#ifdef FX_ENABLE_FAULT_TOLERANT
466
467
    /* End transaction. */
468
    status = _fx_fault_tolerant_transaction_end(media_ptr);
469
#endif /* FX_ENABLE_FAULT_TOLERANT */
470
471
    /* Release media protection.  */
472
99
    FX_UNPROTECT
473
474
    /* File delete is complete, return status.  */
475
99
    return(status);
476
}
477