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