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

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

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