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_rename 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 rename request is valid and the directory entry will be changed */
51 /* to the new file name. Otherwise, if the file is not found, the */
52 /* appropriate error code is returned to the caller. */
53 /* */
54 /* INPUT */
55 /* */
56 /* media_ptr Pointer to media */
57 /* old_unicode_name Pointer to old unicode name */
58 /* old_unicode_length Old unicode name length */
59 /* new_unicode_name Pointer to new unicode name */
60 /* new_unicode_length New unicode name length */
61 /* new_short_name Designated new short name */
62 /* */
63 /* OUTPUT */
64 /* */
65 /* Completion Status */
66 /* */
67 /* CALLS */
68 /* */
69 /* _fx_unicode_short_name_get Get short name of unicode name*/
70 /* _fx_directory_search Search directory */
71 /* _fx_unicode_directory_entry_change Change unicode file name */
72 /* _fx_unicode_directory_search Search for unicode name */
73 /* _fx_file_rename Rename for ASCII file name */
74 /* _fx_fault_tolerant_transaction_start Start fault tolerant */
75 /* transaction */
76 /* _fx_fault_tolerant_transaction_end End fault tolerant transaction*/
77 /* */
78 /* CALLED BY */
79 /* */
80 /* Application Code */
81 /* */
82 /* RELEASE HISTORY */
83 /* */
84 /* DATE NAME DESCRIPTION */
85 /* */
86 /* 05-19-2020 William E. Lamie Initial Version 6.0 */
87 /* 09-30-2020 William E. Lamie Modified comment(s), */
88 /* resulting in version 6.1 */
89 /* */
90 /**************************************************************************/
_fx_unicode_file_rename(FX_MEDIA * media_ptr,UCHAR * old_unicode_name,ULONG old_unicode_length,UCHAR * new_unicode_name,ULONG new_unicode_length,CHAR * new_short_name)91 UINT _fx_unicode_file_rename(FX_MEDIA *media_ptr, UCHAR *old_unicode_name, ULONG old_unicode_length,
92 UCHAR *new_unicode_name, ULONG new_unicode_length, CHAR *new_short_name)
93 {
94 ULONG i;
95 UINT status;
96 CHAR alpha, beta;
97 CHAR old_shortname[13];
98 CHAR new_shortname[13];
99 FX_DIR_ENTRY dir_entry;
100
101
102 /* Clear the return short name. */
103 new_short_name[0] = FX_NULL;
104
105 /* Set shortname to null. */
106 old_shortname[0] = FX_NULL;
107 new_shortname[0] = FX_NULL;
108
109 /* Check the media to make sure it is open. */
110 if (media_ptr -> fx_media_id != FX_MEDIA_ID)
111 {
112
113 /* Return the media not opened error. */
114 return(FX_MEDIA_NOT_OPEN);
115 }
116
117
118 /* Get shortname of old unicode name. */
119 status = _fx_unicode_short_name_get(media_ptr, old_unicode_name, old_unicode_length, old_shortname);
120
121 /* Determine if the result was successful. */
122 if (status != FX_SUCCESS)
123 {
124
125 /* Return the error code. */
126 return(status);
127 }
128
129 /* Protect media. */
130 FX_PROTECT
131
132 /* Setup pointer to media name buffer. */
133 dir_entry.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
134
135 /* Clear the short name string. */
136 dir_entry.fx_dir_entry_short_name[0] = FX_NULL;
137
138 /* Search the target directory for the same file name. */
139 status = _fx_unicode_directory_search(media_ptr, &dir_entry, (UCHAR *)new_shortname, sizeof(new_shortname),
140 new_unicode_name, &new_unicode_length, 0);
141
142 /* Determine if the name already exists. */
143 if (status == FX_SUCCESS)
144 {
145
146 if (old_unicode_length == new_unicode_length)
147 {
148
149 /* Determine if the new name simply has an ASCII case change. If so, simply let the processing
150 continue. */
151 i = 0;
152 do
153 {
154
155 /* Pickup an old name and new name character and convert to upper case if necessary. */
156 alpha = (CHAR)old_unicode_name[i << 1];
157 if ((alpha >= 'a') && (alpha <= 'z') && (old_unicode_name[(i << 1) + 1] == 0))
158 {
159
160 /* Lower case, convert to upper case! */
161 alpha = (CHAR)((INT)alpha - 0x20);
162 }
163 beta = (CHAR)new_unicode_name[i << 1];
164 if ((beta >= 'a') && (beta <= 'z') && (new_unicode_name[(i << 1) + 1] == 0))
165 {
166
167 /* Lower case, convert to upper case! */
168 beta = (CHAR)((INT)beta - 0x20);
169 }
170
171 /* Now compare the characters. */
172 if ((alpha != beta))
173 {
174
175 /* Get out of this loop! */
176 break;
177 }
178
179 /* Pickup the high bytes. */
180 alpha = (CHAR)old_unicode_name[(i << 1) + 1];
181 beta = (CHAR)new_unicode_name[(i << 1) + 1];
182
183 /* Now compare the byte. */
184 if ((alpha != beta))
185 {
186
187 /* Get out of this loop! */
188 break;
189 }
190
191 /* Move to next character. */
192 i++;
193 } while (i < old_unicode_length);
194 }
195 else
196 {
197
198 /* Names not match. */
199 alpha = 0;
200 beta = 1;
201 }
202
203 /* Now determine if the names match. */
204 if (alpha != beta)
205 {
206
207 /* No, the names do not match so simply return an error
208 to the caller. */
209
210 /* Release media protection. */
211 FX_UNPROTECT
212
213 /* Return the not a file error code. */
214 return(FX_ALREADY_CREATED);
215 }
216 }
217
218 #ifdef FX_ENABLE_FAULT_TOLERANT
219 /* Start transaction. */
220 _fx_fault_tolerant_transaction_start(media_ptr);
221 #endif /* FX_ENABLE_FAULT_TOLERANT */
222
223 /* Okay, at this point we need to rename to a new long file name that has enough space for the
224 eventual unicode file name. */
225
226 /* Copy the characters from the unicode file name and make sure they are
227 within the ASCII range. */
228 _fx_unicode_temp_long_file_name[0] = 'z';
229 for (i = 1; i < new_unicode_length; i++)
230 {
231
232 /* Build temporary long file name. */
233 _fx_unicode_temp_long_file_name[i] = (UCHAR)((UINT)'0' + (i % 9));
234 }
235 _fx_unicode_temp_long_file_name[i] = FX_NULL;
236
237 /* Loop to try different temp long file names... if necessary. */
238 do
239 {
240
241 /* Create a new file with the temp long file name. */
242 status = _fx_file_rename(media_ptr, old_shortname, (CHAR *)_fx_unicode_temp_long_file_name);
243
244 /* Determine if there was an error. */
245 if (status == FX_ALREADY_CREATED)
246 {
247
248 /* Adjust the name slightly and try again! */
249 _fx_unicode_temp_long_file_name[0]--;
250
251 /* Determine if it is outside the lower case boundary. */
252 if (_fx_unicode_temp_long_file_name[0] < 0x61)
253 {
254 break;
255 }
256 }
257 } while (status == FX_ALREADY_CREATED);
258
259 /* Determine if there was an error. */
260 if (status)
261 {
262 #ifdef FX_ENABLE_FAULT_TOLERANT
263 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
264 #endif /* FX_ENABLE_FAULT_TOLERANT */
265
266 /* Release media protection. */
267 FX_UNPROTECT
268
269 /* Return error. */
270 return(status);
271 }
272
273 /* Setup pointer to media name buffer. */
274 dir_entry.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
275
276 /* Clear the short name string. */
277 dir_entry.fx_dir_entry_short_name[0] = 0;
278
279 /* Search the system for the supplied file name. */
280 status = _fx_directory_search(media_ptr, (CHAR *)_fx_unicode_temp_long_file_name, &dir_entry, FX_NULL, FX_NULL);
281
282 /* Determine if the search was successful. */
283 if (status != FX_SUCCESS)
284 {
285 #ifdef FX_ENABLE_FAULT_TOLERANT
286 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
287 #endif /* FX_ENABLE_FAULT_TOLERANT */
288
289 /* Release media protection. */
290 FX_UNPROTECT
291
292 /* Return the error status. */
293 return(status);
294 }
295
296 /* We can now change the temporary long file name with the destination unicode name. */
297 status = _fx_unicode_directory_entry_change(media_ptr, &dir_entry, new_unicode_name, new_unicode_length);
298
299 /* Was this successful? */
300 if (status == FX_SUCCESS)
301 {
302
303 /* Yes, copy the short file name to the destination. */
304 /* The new short name only have 8 characters, since we didn't include a dot in temp_long_file_name. */
305 for (i = 0; i < FX_DIR_NAME_SIZE; i++)
306 {
307
308 /* Copy a character. */
309 new_short_name[i] = dir_entry.fx_dir_entry_short_name[i];
310
311 /* Are we done? */
312 if (new_short_name[i] == FX_NULL)
313 {
314 break;
315 }
316 }
317 }
318
319 #ifdef FX_ENABLE_FAULT_TOLERANT
320 /* Check for a bad status. */
321 if (status != FX_SUCCESS)
322 {
323
324 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
325
326 /* Release media protection. */
327 FX_UNPROTECT
328
329 /* Return the bad status. */
330 return(status);
331 }
332
333 /* End transaction. */
334 status = _fx_fault_tolerant_transaction_end(media_ptr);
335 #endif /* FX_ENABLE_FAULT_TOLERANT */
336
337 /* Release the protection. */
338 FX_UNPROTECT
339
340 /* Return completion status. */
341 return(status);
342 }
343
344