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_create 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 create request is invalid and an error is returned to the */
51 /* caller. After the file name verification is made, a search for a */
52 /* free directory entry will be made. If nothing is available, an */
53 /* error will be returned to the caller. Otherwise, if all is okay, a */
54 /* file of 0 bytes will be created. */
55 /* */
56 /* INPUT */
57 /* */
58 /* media_ptr Media control block pointer */
59 /* file_name File name */
60 /* */
61 /* OUTPUT */
62 /* */
63 /* return status */
64 /* */
65 /* CALLS */
66 /* */
67 /* _fx_directory_entry_write Write the new directory entry */
68 /* _fx_directory_name_extract Extract directory name */
69 /* _fx_directory_search Search for the file name in */
70 /* the directory structure */
71 /* _fx_directory_free_search Search for a free directory */
72 /* entry */
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 /* */
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_create(FX_MEDIA * media_ptr,CHAR * file_name)92 UINT _fx_file_create(FX_MEDIA *media_ptr, CHAR *file_name)
93 {
94
95 FX_INT_SAVE_AREA
96
97 UINT status;
98 CHAR *name_ptr;
99 UINT i;
100 CHAR *work_ptr;
101 FX_DIR_ENTRY dir_entry;
102 FX_DIR_ENTRY search_directory;
103
104
105 #ifndef FX_MEDIA_STATISTICS_DISABLE
106
107 /* Increment the number of times this service has been called. */
108 media_ptr -> fx_media_file_creates++;
109 #endif
110
111 /* Determine if the supplied name is less than the maximum supported name size. The
112 maximum name (FX_MAX_LONG_NAME_LEN) is defined in fx_api.h. */
113 i = 0;
114 work_ptr = (CHAR *)file_name;
115 while (*work_ptr)
116 {
117
118 /* Determine if the character designates a new path. */
119 if ((*work_ptr == '\\') || (*work_ptr == '/'))
120 {
121 /* Yes, reset the name size. */
122 i = 0;
123 }
124 /* Check for leading spaces. */
125 else if ((*work_ptr != ' ') || (i != 0))
126 {
127
128 /* No leading spaces, increment the name size. */
129 i++;
130 }
131
132 /* Move to the next character. */
133 work_ptr++;
134 }
135
136 /* Determine if the supplied name is valid. */
137 if ((i == 0) || (i >= FX_MAX_LONG_NAME_LEN))
138 {
139
140 /* Return an invalid name value. */
141 return(FX_INVALID_NAME);
142 }
143
144 /* Setup pointer to media name buffer. */
145 dir_entry.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
146
147 /* Setup another pointer to another media name buffer. */
148 search_directory.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN * 2;
149
150 /* Clear the short name strings. */
151 dir_entry.fx_dir_entry_short_name[0] = 0;
152 search_directory.fx_dir_entry_short_name[0] = 0;
153
154 /* Check the media to make sure it is open. */
155 if (media_ptr -> fx_media_id != FX_MEDIA_ID)
156 {
157
158 /* Return the media not opened error. */
159 return(FX_MEDIA_NOT_OPEN);
160 }
161
162 /* If trace is enabled, insert this event into the trace buffer. */
163 FX_TRACE_IN_LINE_INSERT(FX_TRACE_FILE_CREATE, media_ptr, file_name, 0, 0, FX_TRACE_FILE_EVENTS, 0, 0)
164
165 /* Protect against other threads accessing the media. */
166 FX_PROTECT
167
168 #ifdef FX_ENABLE_FAULT_TOLERANT
169 /* Start transaction. */
170 _fx_fault_tolerant_transaction_start(media_ptr);
171 #endif /* FX_ENABLE_FAULT_TOLERANT */
172
173 /* Check for write protect at the media level (set by driver). */
174 if (media_ptr -> fx_media_driver_write_protect)
175 {
176
177 #ifdef FX_ENABLE_FAULT_TOLERANT
178 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
179 #endif /* FX_ENABLE_FAULT_TOLERANT */
180
181 /* Release media protection. */
182 FX_UNPROTECT
183
184 /* Return write protect error. */
185 return(FX_WRITE_PROTECT);
186 }
187
188 /* Search the system for the supplied file name. */
189 status = _fx_directory_search(media_ptr, file_name, &dir_entry, &search_directory, &name_ptr);
190
191 /* Determine if the search was successful. */
192 if (status == FX_SUCCESS)
193 {
194
195 #ifdef FX_ENABLE_FAULT_TOLERANT
196 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
197 #endif /* FX_ENABLE_FAULT_TOLERANT */
198
199 /* Release media protection. */
200 FX_UNPROTECT
201
202 /* File found - Return the error code. */
203 return(FX_ALREADY_CREATED);
204 }
205
206 /* Determine if there is anything left after the name. */
207 if (_fx_directory_name_extract(name_ptr, &dir_entry.fx_dir_entry_name[0]))
208 {
209
210 #ifdef FX_ENABLE_FAULT_TOLERANT
211 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
212 #endif /* FX_ENABLE_FAULT_TOLERANT */
213
214 /* Release media protection. */
215 FX_UNPROTECT
216
217 /* Extra information after the file name, return an invalid path
218 error. */
219 return(FX_INVALID_PATH);
220 }
221
222
223 /* Find a free slot for the new file. */
224 status = _fx_directory_free_search(media_ptr, &search_directory, &dir_entry);
225
226 /* Determine if the search was successful. */
227 if (status != FX_SUCCESS)
228 {
229
230 #ifdef FX_ENABLE_FAULT_TOLERANT
231 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
232 #endif /* FX_ENABLE_FAULT_TOLERANT */
233
234 /* Release media protection. */
235 FX_UNPROTECT
236
237 /* Return the error code. */
238 return(status);
239 }
240
241 /* Populate the directory entry. */
242
243 /* Isolate the file name. */
244 _fx_directory_name_extract(name_ptr, &dir_entry.fx_dir_entry_name[0]);
245
246 /* Disable interrupts for time/date access. */
247 FX_DISABLE_INTS
248
249 /* Set time and date stamps. */
250 dir_entry.fx_dir_entry_time = _fx_system_time;
251 dir_entry.fx_dir_entry_date = _fx_system_date;
252
253 /* Restore interrupts. */
254 FX_RESTORE_INTS
255
256 /* Set the attributes for the file. */
257 dir_entry.fx_dir_entry_attributes = FX_ARCHIVE;
258
259 /* Set file size to 0. */
260 dir_entry.fx_dir_entry_file_size = 0;
261
262
263 /* Set the cluster to NULL. */
264 dir_entry.fx_dir_entry_cluster = FX_NULL;
265
266 /* Is there a leading dot? */
267 if (dir_entry.fx_dir_entry_name[0] == '.')
268 {
269
270 /* Yes, toggle the hidden attribute bit. */
271 dir_entry.fx_dir_entry_attributes |= FX_HIDDEN;
272 }
273
274
275 /* Now write out the directory entry. */
276 status = _fx_directory_entry_write(media_ptr, &dir_entry);
277
278 #ifdef FX_ENABLE_FAULT_TOLERANT
279 /* Check for a bad status. */
280 if (status != FX_SUCCESS)
281 {
282
283 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
284
285 /* Release media protection. */
286 FX_UNPROTECT
287
288 /* Return the bad status. */
289 return(status);
290 }
291
292 /* End transaction. */
293 status = _fx_fault_tolerant_transaction_end(media_ptr);
294 #endif /* FX_ENABLE_FAULT_TOLERANT */
295
296 /* Release media protection. */
297 FX_UNPROTECT
298
299 /* File create is complete, return status. */
300 return(status);
301 }
302
303