GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: fx_file_delete.c Lines: 57 57 100.0 %
Date: 2026-03-06 18:49:02 Branches: 30 30 100.0 %

Line Branch Exec Source
1
/***************************************************************************
2
 * Copyright (c) 2024 Microsoft Corporation
3
 * Copyright (c) 2026-present Eclipse ThreadX contributors
4
 *
5
 * This program and the accompanying materials are made available under the
6
 * terms of the MIT License which is available at
7
 * https://opensource.org/licenses/MIT.
8
 *
9
 * SPDX-License-Identifier: MIT
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_FAT_entry_read            Read a FAT entry              */
71
/*    _fx_utility_FAT_entry_write           Write a FAT entry             */
72
/*    _fx_utility_FAT_flush                 Flush written FAT entries     */
73
/*    _fx_fault_tolerant_transaction_start  Start fault tolerant          */
74
/*                                            transaction                 */
75
/*    _fx_fault_tolerant_transaction_end    End fault tolerant transaction*/
76
/*    _fx_fault_tolerant_recover            Recover FAT chain             */
77
/*    _fx_fault_tolerant_reset_log_file     Reset the log file            */
78
/*    _fx_fault_tolerant_set_FAT_chain      Set data of FAT chain         */
79
/*                                                                        */
80
/*  CALLED BY                                                             */
81
/*                                                                        */
82
/*    Application Code                                                    */
83
/*                                                                        */
84
/**************************************************************************/
85
111
UINT  _fx_file_delete(FX_MEDIA *media_ptr, CHAR *file_name)
86
{
87
88
UINT         status;
89
ULONG        cluster;
90
ULONG        contents;
91
ULONG        open_count;
92
FX_FILE     *search_ptr;
93
ULONG        cluster_count;
94
FX_DIR_ENTRY dir_entry;
95
UCHAR        not_a_file_attr;
96
97
#ifndef FX_MEDIA_STATISTICS_DISABLE
98
99
    /* Increment the number of times this service has been called.  */
100
111
    media_ptr -> fx_media_file_deletes++;
101
#endif
102
103
    /* Setup pointer to media name buffer.  */
104
111
    dir_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
105
106
    /* Clear the short name string.  */
107
111
    dir_entry.fx_dir_entry_short_name[0] =  0;
108
109
    /* Check the media to make sure it is open.  */
110
111
    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
111
    {
112
113
        /* Return the media not opened error.  */
114
1
        return(FX_MEDIA_NOT_OPEN);
115
    }
116
117
    /* If trace is enabled, insert this event into the trace buffer.  */
118
    FX_TRACE_IN_LINE_INSERT(FX_TRACE_FILE_DELETE, media_ptr, file_name, 0, 0, FX_TRACE_FILE_EVENTS, 0, 0)
119
120
    /* Protect against other threads accessing the media.  */
121
110
    FX_PROTECT
122
123
#ifdef FX_ENABLE_FAULT_TOLERANT
124
    /* Start transaction. */
125
    _fx_fault_tolerant_transaction_start(media_ptr);
126
#endif /* FX_ENABLE_FAULT_TOLERANT */
127
128
    /* Check for write protect at the media level (set by driver).  */
129
110
    if (media_ptr -> fx_media_driver_write_protect)
130
    {
131
132
#ifdef FX_ENABLE_FAULT_TOLERANT
133
        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
134
#endif /* FX_ENABLE_FAULT_TOLERANT */
135
136
        /* Release media protection.  */
137
2
        FX_UNPROTECT
138
139
        /* Return write protect error.  */
140
2
        return(FX_WRITE_PROTECT);
141
    }
142
143
    /* Search the system for the supplied file name.  */
144
108
    status =  _fx_directory_search(media_ptr, file_name, &dir_entry, FX_NULL, FX_NULL);
145
146
    /* Determine if the search was successful.  */
147
108
    if (status != FX_SUCCESS)
148
    {
149
150
#ifdef FX_ENABLE_FAULT_TOLERANT
151
        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
152
#endif /* FX_ENABLE_FAULT_TOLERANT */
153
154
        /* Release media protection.  */
155
1
        FX_UNPROTECT
156
157
        /* Return the error code.  */
158
1
        return(status);
159
    }
160
161
107
    not_a_file_attr = FX_DIRECTORY | FX_VOLUME;
162
163
    /* Check to make sure the found entry is a file.  */
164
107
    if (dir_entry.fx_dir_entry_attributes & not_a_file_attr)
165
    {
166
167
#ifdef FX_ENABLE_FAULT_TOLERANT
168
        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
169
#endif /* FX_ENABLE_FAULT_TOLERANT */
170
171
        /* Release media protection.  */
172
1
        FX_UNPROTECT
173
174
        /* Return the not a file error code.  */
175
1
        return(FX_NOT_A_FILE);
176
    }
177
178
    /* Check if the entry is read only */
179
106
    if (dir_entry.fx_dir_entry_attributes & (UCHAR)(FX_READ_ONLY))
180
    {
181
#ifdef FX_ENABLE_FAULT_TOLERANT
182
        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
183
#endif /* FX_ENABLE_FAULT_TOLERANT */
184
185
        /* Release media protection.  */
186
1
        FX_UNPROTECT
187
188
        /* Return the not a directory error code.  */
189
1
        return(FX_WRITE_PROTECT);
190
    }
191
192
    /* Search the opened files to see if this file is currently
193
       opened.  */
194
105
    open_count =  media_ptr -> fx_media_opened_file_count;
195
105
    search_ptr =  media_ptr -> fx_media_opened_file_list;
196
120
    while (open_count)
197
    {
198
199
        /* Look at each opened file to see if the same file is opened.  */
200
16
        if ((search_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector == dir_entry.fx_dir_entry_log_sector) &&
201
14
            (search_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset == dir_entry.fx_dir_entry_byte_offset))
202
        {
203
204
#ifdef FX_ENABLE_FAULT_TOLERANT
205
            FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
206
#endif /* FX_ENABLE_FAULT_TOLERANT */
207
208
            /* Release media protection.  */
209
1
            FX_UNPROTECT
210
211
            /* The file is currently open.  */
212
1
            return(FX_ACCESS_ERROR);
213
        }
214
215
        /* Adjust the pointer and decrement the search count.  */
216
15
        search_ptr =  search_ptr -> fx_file_opened_next;
217
15
        open_count--;
218
    }
219
220
    /* Pickup the starting cluster of the file.  */
221
104
    cluster =           dir_entry.fx_dir_entry_cluster;
222
223
    /* At this point, make the directory entry invalid in order to delete the file.  */
224
225
#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
226
227
    /* Invalidate the directory search saved information.  */
228
104
    media_ptr -> fx_media_last_found_name[0] =  FX_NULL;
229
#endif
230
231
    /* Mark the directory entry as available, while leaving the other
232
       information for the sake of posterity.  */
233
104
    dir_entry.fx_dir_entry_name[0] =        (CHAR)FX_DIR_ENTRY_FREE;
234
104
    dir_entry.fx_dir_entry_short_name[0] =  (CHAR)FX_DIR_ENTRY_FREE;
235
236
    /* Now write out the directory entry.  */
237
104
    status = _fx_directory_entry_write(media_ptr, &dir_entry);
238
239
    /* Determine if the write was successful.  */
240
104
    if (status != FX_SUCCESS)
241
    {
242
243
#ifdef FX_ENABLE_FAULT_TOLERANT
244
        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
245
#endif /* FX_ENABLE_FAULT_TOLERANT */
246
247
        /* Release media protection.  */
248
1
        FX_UNPROTECT
249
250
        /* Return the error code.  */
251
1
        return(status);
252
    }
253
254
    /* Now that the directory entry is no longer valid and pointing at the chain of clusters,
255
       walk the chain of allocated FAT entries and mark each of them as free.  */
256
103
    cluster_count =     0;
257
258
259
#ifdef FX_ENABLE_FAULT_TOLERANT
260
    if (media_ptr -> fx_media_fault_tolerant_enabled)
261
    {
262
263
        /* Note:  Directory entries are already written to log files. FAT chain is updated as the last step.
264
           Since there are no others FAT entries written to the log.  Therefore there is no need to set
265
           the flag FX_FRAULT_TOLERANT_STATE_SET_FAT_CHAIN here. */
266
        status = _fx_fault_tolerant_set_FAT_chain(media_ptr, FX_FALSE, 0,
267
                                                  media_ptr -> fx_media_fat_last, cluster, media_ptr -> fx_media_fat_last);
268
269
        /* Determine if the write was successful.  */
270
        if (status != FX_SUCCESS)
271
        {
272
273
            FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
274
275
            /* Release media protection.  */
276
            FX_UNPROTECT
277
278
            /* Return the error code.  */
279
            return(status);
280
        }
281
    }
282
    else
283
    {
284
#endif /* FX_ENABLE_FAULT_TOLERANT */
285
286
        /* Follow the link of FAT entries.  */
287

1601
        while ((cluster >= FX_FAT_ENTRY_START) && (cluster < media_ptr -> fx_media_fat_reserved))
288
        {
289
290
            /* Increment the number of clusters.  */
291
1502
            cluster_count++;
292
293
294
            /* Read the current cluster entry from the FAT.  */
295
1502
            status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &contents);
296
297
            /* Check the return value.  */
298
1502
            if (status != FX_SUCCESS)
299
            {
300
301
#ifdef FX_ENABLE_FAULT_TOLERANT
302
                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
303
#endif /* FX_ENABLE_FAULT_TOLERANT */
304
305
                /* Release media protection.  */
306
1
                FX_UNPROTECT
307
308
                /* Return the error status.  */
309
1
                return(status);
310
            }
311
312

1501
            if ((cluster == contents) || (cluster_count > media_ptr -> fx_media_total_clusters))
313
            {
314
315
#ifdef FX_ENABLE_FAULT_TOLERANT
316
                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
317
#endif /* FX_ENABLE_FAULT_TOLERANT */
318
319
                /* Release media protection.  */
320
2
                FX_UNPROTECT
321
322
                /* Return the bad status.  */
323
2
                return(FX_FAT_READ_ERROR);
324
            }
325
326
327
            /* Make the current cluster available.  */
328
1499
            status =  _fx_utility_FAT_entry_write(media_ptr, cluster, FX_FREE_CLUSTER);
329
330
            /* Check the return value.  */
331
1499
            if (status != FX_SUCCESS)
332
            {
333
334
#ifdef FX_ENABLE_FAULT_TOLERANT
335
                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
336
#endif /* FX_ENABLE_FAULT_TOLERANT */
337
338
                /* Release media protection.  */
339
1
                FX_UNPROTECT
340
341
                /* Return the error status.  */
342
1
                return(status);
343
            }
344
345
            /* Setup for the next cluster.  */
346
1498
            cluster =  contents;
347
        }
348
#ifdef FX_ENABLE_FAULT_TOLERANT
349
    }
350
#endif /* FX_ENABLE_FAULT_TOLERANT */
351
352
    /* Update the free clusters in the media control block.  */
353
99
    media_ptr -> fx_media_available_clusters =
354
99
        media_ptr -> fx_media_available_clusters + cluster_count;
355
356
#ifdef FX_FAULT_TOLERANT
357
358
    /* Flush the cached individual FAT entries */
359
    _fx_utility_FAT_flush(media_ptr);
360
#endif
361
362
#ifdef FX_ENABLE_FAULT_TOLERANT
363
364
    /* End transaction. */
365
    status = _fx_fault_tolerant_transaction_end(media_ptr);
366
#endif /* FX_ENABLE_FAULT_TOLERANT */
367
368
    /* Release media protection.  */
369
99
    FX_UNPROTECT
370
371
    /* File delete is complete, return status.  */
372
99
    return(status);
373
}
374