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