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 /** Unicode */
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_unicode.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_unicode_file_create PORTABLE C */
42 /* 6.1 */
43 /* AUTHOR */
44 /* */
45 /* William E. Lamie, Microsoft Corporation */
46 /* */
47 /* DESCRIPTION */
48 /* */
49 /* This function creates the specified unicode name. */
50 /* */
51 /* INPUT */
52 /* */
53 /* media_ptr Pointer to media */
54 /* source_unicode_name Pointer to source unicode name*/
55 /* source_unicode_length Unicode name length */
56 /* short_name Designated short name */
57 /* */
58 /* OUTPUT */
59 /* */
60 /* Completion Status */
61 /* */
62 /* CALLS */
63 /* */
64 /* _fx_directory_search Search directory */
65 /* _fx_unicode_directory_entry_change Change unicode file name */
66 /* _fx_unicode_directory_search Search for unicode name */
67 /* _fx_file_create Create a file */
68 /* _fx_fault_tolerant_transaction_start Start fault tolerant */
69 /* transaction */
70 /* _fx_fault_tolerant_transaction_end End fault tolerant transaction*/
71 /* _fx_fault_tolerant_recover Recover FAT chain */
72 /* _fx_fault_tolerant_reset_log_file Reset the log file */
73 /* */
74 /* CALLED BY */
75 /* */
76 /* Application Code */
77 /* */
78 /* RELEASE HISTORY */
79 /* */
80 /* DATE NAME DESCRIPTION */
81 /* */
82 /* 05-19-2020 William E. Lamie Initial Version 6.0 */
83 /* 09-30-2020 William E. Lamie Modified comment(s), */
84 /* resulting in version 6.1 */
85 /* */
86 /**************************************************************************/
_fx_unicode_file_create(FX_MEDIA * media_ptr,UCHAR * source_unicode_name,ULONG source_unicode_length,CHAR * short_name)87 UINT _fx_unicode_file_create(FX_MEDIA *media_ptr, UCHAR *source_unicode_name, ULONG source_unicode_length, CHAR *short_name)
88 {
89
90 FX_DIR_ENTRY dir_entry;
91 UINT i, status;
92 ULONG temp_length;
93 UCHAR destination_shortname[13];
94
95
96 /* Setup pointer to media name buffer. */
97 dir_entry.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
98
99 /* Clear the short name string. */
100 dir_entry.fx_dir_entry_short_name[0] = FX_NULL;
101
102 /* Set destination shortname to null. */
103 destination_shortname[0] = FX_NULL;
104
105 /* Clear the return short name. */
106 short_name[0] = FX_NULL;
107
108 /* Check the media to make sure it is open. */
109 if (media_ptr -> fx_media_id != FX_MEDIA_ID)
110 {
111
112 /* Return the media not opened error. */
113 return(FX_MEDIA_NOT_OPEN);
114 }
115
116
117 /* If trace is enabled, insert this event into the trace buffer. */
118 FX_TRACE_IN_LINE_INSERT(FX_TRACE_UNICODE_FILE_CREATE, media_ptr, source_unicode_name, source_unicode_length, short_name, FX_TRACE_FILE_EVENTS, 0, 0)
119
120 /* Protect media. */
121 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 if (media_ptr -> fx_media_driver_write_protect)
130 {
131 #ifdef FX_ENABLE_FAULT_TOLERANT
132 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
133 #endif /* FX_ENABLE_FAULT_TOLERANT */
134
135 /* Release media protection. */
136 FX_UNPROTECT
137
138 /* Return write protect error. */
139 return(FX_WRITE_PROTECT);
140 }
141
142 /* Setup temporary length. */
143 temp_length = source_unicode_length;
144
145 /* Determine if the destination file is already present. */
146 status = _fx_unicode_directory_search(media_ptr, &dir_entry, destination_shortname, sizeof(destination_shortname), source_unicode_name, &temp_length, 0);
147
148 /* Determine if the search was successful. */
149 if (status == FX_SUCCESS)
150 {
151 #ifdef FX_ENABLE_FAULT_TOLERANT
152 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
153 #endif /* FX_ENABLE_FAULT_TOLERANT */
154
155 /* Release media protection. */
156 FX_UNPROTECT
157
158 /* Return the error code. */
159 return(FX_ALREADY_CREATED);
160 }
161
162 /* Okay, at this point we need to create a new long file name that has enough space for the
163 eventual unicode file name. */
164
165 /* Copy the characters from the unicode file name and make sure they are
166 within the ASCII range. */
167 _fx_unicode_temp_long_file_name[0] = 'z';
168 for (i = 1; i < source_unicode_length; i++)
169 {
170
171 /* Build temporary long file name. */
172 _fx_unicode_temp_long_file_name[i] = (UCHAR)((UINT)'0' + (i % 9));
173 }
174 _fx_unicode_temp_long_file_name[i] = FX_NULL;
175
176 /* Loop to try different temp long file names... if necessary. */
177 do
178 {
179
180 /* Create a new file with the temp long file name. */
181 status = _fx_file_create(media_ptr, (CHAR *)_fx_unicode_temp_long_file_name);
182
183 /* Determine if there was an error. */
184 if (status == FX_ALREADY_CREATED)
185 {
186
187 /* Adjust the name slightly and try again! */
188 _fx_unicode_temp_long_file_name[0]--;
189
190 /* Determine if it is outside the lower case boundary. */
191 if (_fx_unicode_temp_long_file_name[0] < 0x61)
192 {
193 break;
194 }
195 }
196 } while (status == FX_ALREADY_CREATED);
197
198 /* Determine if there was an error. */
199 if (status)
200 {
201 #ifdef FX_ENABLE_FAULT_TOLERANT
202 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
203 #endif /* FX_ENABLE_FAULT_TOLERANT */
204
205 /* Release media protection. */
206 FX_UNPROTECT
207
208 /* Return error. */
209 return(status);
210 }
211
212 /* Setup pointer to media name buffer. */
213 dir_entry.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
214
215 /* Clear the short name string. */
216 dir_entry.fx_dir_entry_short_name[0] = 0;
217
218 /* Search the system for the supplied file name. */
219 status = _fx_directory_search(media_ptr, (CHAR *)_fx_unicode_temp_long_file_name, &dir_entry, FX_NULL, FX_NULL);
220
221 /* Determine if the search was successful. */
222 if (status != FX_SUCCESS)
223 {
224 #ifdef FX_ENABLE_FAULT_TOLERANT
225 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
226 #endif /* FX_ENABLE_FAULT_TOLERANT */
227
228 /* Release media protection. */
229 FX_UNPROTECT
230
231 /* Return the error status. */
232 return(status);
233 }
234
235 /* We can now change the temporary long file name with the destination unicode name. */
236 status = _fx_unicode_directory_entry_change(media_ptr, &dir_entry, source_unicode_name, source_unicode_length);
237
238 /* Was this successful? */
239 if (status == FX_SUCCESS)
240 {
241
242 /* Yes, copy the short file name to the destination. */
243 /* The new short name only have 8 characters, since we didn't include a dot in temp_long_file_name. */
244 for (i = 0; i < FX_DIR_NAME_SIZE; i++)
245 {
246
247 /* Copy a character. */
248 short_name[i] = dir_entry.fx_dir_entry_short_name[i];
249
250 /* Are we done? */
251 if (short_name[i] == FX_NULL)
252 {
253 break;
254 }
255 }
256 }
257
258 #ifdef FX_ENABLE_FAULT_TOLERANT
259 /* Check for a bad status. */
260 if (status != FX_SUCCESS)
261 {
262
263 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
264
265 /* Release media protection. */
266 FX_UNPROTECT
267
268 /* Return the bad status. */
269 return(status);
270 }
271
272 /* End transaction. */
273 status = _fx_fault_tolerant_transaction_end(media_ptr);
274 #endif /* FX_ENABLE_FAULT_TOLERANT */
275
276 /* Release the protection. */
277 FX_UNPROTECT
278
279 /* Return completion status. */
280 return(status);
281 }
282
283