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_utility.h"
31 #ifdef FX_ENABLE_FAULT_TOLERANT
32 #include "fx_fault_tolerant.h"
33 #endif /* FX_ENABLE_FAULT_TOLERANT */
34
35
36 /**************************************************************************/
37 /* */
38 /* FUNCTION RELEASE */
39 /* */
40 /* _fx_unicode_directory_rename PORTABLE C */
41 /* 6.1 */
42 /* AUTHOR */
43 /* */
44 /* William E. Lamie, Microsoft Corporation */
45 /* */
46 /* DESCRIPTION */
47 /* */
48 /* This function creates the specified unicode directory. */
49 /* This function first attempts to find the specified directory. */
50 /* If found, the unicode rename request is valid and the directory */
51 /* will be changed to the new unicode name. Otherwise, if the directory*/
52 /* is not found, the 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 Old unicode name length */
61 /* new_short_name Pointer to new short name */
62 /* */
63 /* OUTPUT */
64 /* */
65 /* Completion Status */
66 /* */
67 /* CALLS */
68 /* */
69 /* _fx_unicode_short_name_get Get the directory short name */
70 /* _fx_unicode_directory_search Search for unicode name */
71 /* _fx_unicode_directory_entry_change Change unicode file name */
72 /* _fx_directory_rename Rename the directory */
73 /* _fx_directory_search Search directory */
74 /* */
75 /* CALLED BY */
76 /* */
77 /* Application Code */
78 /* */
79 /* RELEASE HISTORY */
80 /* */
81 /* DATE NAME DESCRIPTION */
82 /* */
83 /* 05-19-2020 William E. Lamie Initial Version 6.0 */
84 /* 09-30-2020 William E. Lamie Modified comment(s), */
85 /* resulting in version 6.1 */
86 /* */
87 /**************************************************************************/
_fx_unicode_directory_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)88 UINT _fx_unicode_directory_rename(FX_MEDIA *media_ptr, UCHAR *old_unicode_name, ULONG old_unicode_length,
89 UCHAR *new_unicode_name, ULONG new_unicode_length, CHAR *new_short_name)
90 {
91
92 FX_DIR_ENTRY dir_entry;
93 UINT i, status;
94 ULONG temp_length;
95 CHAR old_dir_short_name[13];
96 CHAR new_dir_short_name[13];
97 UCHAR alpha, beta;
98
99
100 /* Clear the return short name. */
101 new_short_name[0] = FX_NULL;
102
103 /* Set shortname to null. */
104 old_dir_short_name[0] = FX_NULL;
105 new_dir_short_name[0] = FX_NULL;
106
107 /* Check the media to make sure it is open. */
108 if (media_ptr -> fx_media_id != FX_MEDIA_ID)
109 {
110
111 /* Return the media not opened error. */
112 return(FX_MEDIA_NOT_OPEN);
113 }
114
115
116 /* Get the old short name. */
117 status = _fx_unicode_short_name_get(media_ptr, old_unicode_name, old_unicode_length, &old_dir_short_name[0]);
118
119 /* Determine if the search was successful. */
120 if (status != FX_SUCCESS)
121 {
122
123 /* Return the error code. */
124 return(status);
125 }
126
127 /* Protect media. */
128 FX_PROTECT
129
130 /* Setup temporary length. */
131 temp_length = new_unicode_length;
132
133 /* Setup pointer to media name buffer. */
134 dir_entry.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
135
136 /* Clear the short name string. */
137 dir_entry.fx_dir_entry_short_name[0] = FX_NULL;
138
139 /* Determine if the new directory name is already present. */
140 status = _fx_unicode_directory_search(media_ptr, &dir_entry, (UCHAR *)new_dir_short_name, sizeof(new_dir_short_name), new_unicode_name, &temp_length, 0);
141
142 /* Determine if the search was successful. */
143 if (status == FX_SUCCESS)
144 {
145
146 /* Determine if the name length are equal. */
147 if (old_unicode_length == new_unicode_length)
148 {
149
150 /* Determine if the new name simply has a UNICODE case change. If so, simply let the processing
151 continue. */
152 i = 0;
153 do
154 {
155
156 /* Pickup an old name and new name character and convert to upper case if necessary. */
157 alpha = old_unicode_name[i * 2];
158 if ((alpha >= 'a') && (alpha <= 'z') && (old_unicode_name[i * 2 + 1] == 0))
159 {
160
161 /* Lower case, convert to upper case! */
162 alpha = (UCHAR)((INT)alpha - 0x20);
163 }
164 beta = new_unicode_name[i * 2];
165 if ((beta >= 'a') && (beta <= 'z') && (new_unicode_name[i * 2 + 1] == 0))
166 {
167
168 /* Lower case, convert to upper case! */
169 beta = (UCHAR)((INT)beta - 0x20);
170 }
171
172 /* Now compare the characters. */
173 if (alpha != beta)
174 {
175
176 /* Get out of this loop! */
177 break;
178 }
179
180 /* Pickup the high bytes. */
181 alpha = old_unicode_name[i * 2 + 1];
182 beta = new_unicode_name[i * 2 + 1];
183
184 /* Now compare the byte. */
185 if ((alpha != beta))
186 {
187
188 /* Get out of this loop! */
189 break;
190 }
191
192 /* Move to next character. */
193 i++;
194 } while (i < old_unicode_length);
195 }
196 else
197 {
198 alpha = 0;
199 beta = 1;
200 }
201
202 /* Now determine if the names match. */
203 if (alpha != beta)
204 {
205
206 /* Yes, the directory name already exists in the target location. */
207
208 /* Release media protection. */
209 FX_UNPROTECT
210
211 /* Return the error code. */
212 return(FX_ALREADY_CREATED);
213 }
214 }
215
216 #ifdef FX_ENABLE_FAULT_TOLERANT
217 /* Start transaction. */
218 _fx_fault_tolerant_transaction_start(media_ptr);
219 #endif /* FX_ENABLE_FAULT_TOLERANT */
220
221 /* Okay, at this point we need to create a new long directory name that has enough space for the
222 eventual unicode directory name. */
223
224 /* Copy the characters from the unicode directory name and make sure they are
225 within the ASCII range. */
226 _fx_unicode_temp_long_file_name[0] = 'z';
227 for (i = 1; i < new_unicode_length; i++)
228 {
229
230 /* Build temporary long file name. */
231 _fx_unicode_temp_long_file_name[i] = (UCHAR)((UINT)'0' + (i % 9));
232 }
233 _fx_unicode_temp_long_file_name[i] = FX_NULL;
234
235 /* Loop to try different temp long file names... if necessary. */
236 do
237 {
238
239 /* Rename the directory name. */
240 status = _fx_directory_rename(media_ptr, old_dir_short_name, (CHAR *)_fx_unicode_temp_long_file_name);
241
242 /* Determine if there was an error. */
243 if (status == FX_ALREADY_CREATED)
244 {
245
246 /* Adjust the name slightly and try again! */
247 _fx_unicode_temp_long_file_name[0]--;
248
249 /* Determine if it is outside the lower case boundary. */
250 if (_fx_unicode_temp_long_file_name[0] < 0x61)
251 {
252 break;
253 }
254 }
255 } while (status == FX_ALREADY_CREATED);
256
257 /* Determine if there was an error. */
258 if (status)
259 {
260
261 #ifdef FX_ENABLE_FAULT_TOLERANT
262 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
263 #endif /* FX_ENABLE_FAULT_TOLERANT */
264
265 /* Release media protection. */
266 FX_UNPROTECT
267
268 /* Return error. */
269 return(status);
270 }
271
272 /* Setup pointer to media name buffer. */
273 dir_entry.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
274
275 /* Clear the short name string. */
276 dir_entry.fx_dir_entry_short_name[0] = FX_NULL;
277
278 /* Search the system for the supplied file name. */
279 status = _fx_directory_search(media_ptr, (CHAR *)_fx_unicode_temp_long_file_name, &dir_entry, FX_NULL, FX_NULL);
280
281 /* Determine if the search was successful. */
282 if (status != FX_SUCCESS)
283 {
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 /* Determine if the rename was 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