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 /**************************************************************************/
_fx_file_delete(FX_MEDIA * media_ptr,CHAR * file_name)92 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     media_ptr -> fx_media_file_deletes++;
108 #endif
109 
110     /* Setup pointer to media name buffer.  */
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     dir_entry.fx_dir_entry_short_name[0] =  0;
115 
116     /* Check the media to make sure it is open.  */
117     if (media_ptr -> fx_media_id != FX_MEDIA_ID)
118     {
119 
120         /* Return the media not opened error.  */
121         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     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     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         FX_UNPROTECT
145 
146         /* Return write protect error.  */
147         return(FX_WRITE_PROTECT);
148     }
149 
150     /* Search the system for the supplied file name.  */
151     status =  _fx_directory_search(media_ptr, file_name, &dir_entry, FX_NULL, FX_NULL);
152 
153     /* Determine if the search was successful.  */
154     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         FX_UNPROTECT
163 
164         /* Return the error code.  */
165         return(status);
166     }
167 
168     not_a_file_attr = FX_DIRECTORY | FX_VOLUME;
169 
170     /* Check to make sure the found entry is a file.  */
171     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         FX_UNPROTECT
180 
181         /* Return the not a file error code.  */
182         return(FX_NOT_A_FILE);
183     }
184 
185     /* Check if the entry is read only */
186     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         FX_UNPROTECT
194 
195         /* Return the not a directory error code.  */
196         return(FX_WRITE_PROTECT);
197     }
198 
199     /* Search the opened files to see if this file is currently
200        opened.  */
201     open_count =  media_ptr -> fx_media_opened_file_count;
202     search_ptr =  media_ptr -> fx_media_opened_file_list;
203     while (open_count)
204     {
205 
206         /* Look at each opened file to see if the same file is opened.  */
207         if ((search_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector == dir_entry.fx_dir_entry_log_sector) &&
208             (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             FX_UNPROTECT
217 
218             /* The file is currently open.  */
219             return(FX_ACCESS_ERROR);
220         }
221 
222         /* Adjust the pointer and decrement the search count.  */
223         search_ptr =  search_ptr -> fx_file_opened_next;
224         open_count--;
225     }
226 
227     /* Pickup the starting cluster of the file.  */
228     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     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     dir_entry.fx_dir_entry_name[0] =        (CHAR)FX_DIR_ENTRY_FREE;
241     dir_entry.fx_dir_entry_short_name[0] =  (CHAR)FX_DIR_ENTRY_FREE;
242 
243     /* Now write out the directory entry.  */
244     status = _fx_directory_entry_write(media_ptr, &dir_entry);
245 
246     /* Determine if the write was successful.  */
247     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         FX_UNPROTECT
256 
257         /* Return the error code.  */
258         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     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         while ((cluster >= FX_FAT_ENTRY_START) && (cluster < media_ptr -> fx_media_fat_reserved))
295         {
296 
297             /* Increment the number of clusters.  */
298             cluster_count++;
299 
300 
301             /* Read the current cluster entry from the FAT.  */
302             status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &contents);
303 
304             /* Check the return value.  */
305             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                 FX_UNPROTECT
314 
315                 /* Return the error status.  */
316                 return(status);
317             }
318 
319             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                 FX_UNPROTECT
328 
329                 /* Return the bad status.  */
330                 return(FX_FAT_READ_ERROR);
331             }
332 
333 
334             /* Make the current cluster available.  */
335             status =  _fx_utility_FAT_entry_write(media_ptr, cluster, FX_FREE_CLUSTER);
336 
337             /* Check the return value.  */
338             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                 FX_UNPROTECT
347 
348                 /* Return the error status.  */
349                 return(status);
350             }
351 
352             /* Setup for the next cluster.  */
353             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     media_ptr -> fx_media_available_clusters =
361         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     FX_UNPROTECT
377 
378     /* File delete is complete, return status.  */
379     return(status);
380 }
381 
382