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_utility.h"
30 #ifdef FX_ENABLE_FAULT_TOLERANT
31 #include "fx_fault_tolerant.h"
32 #endif /* FX_ENABLE_FAULT_TOLERANT */
33 
34 
35 /**************************************************************************/
36 /*                                                                        */
37 /*  FUNCTION                                               RELEASE        */
38 /*                                                                        */
39 /*    _fx_unicode_directory_entry_change                  PORTABLE C      */
40 /*                                                           6.1          */
41 /*  AUTHOR                                                                */
42 /*                                                                        */
43 /*    William E. Lamie, Microsoft Corporation                             */
44 /*                                                                        */
45 /*  DESCRIPTION                                                           */
46 /*                                                                        */
47 /*    This function changes the unicode name of a directory entry.        */
48 /*                                                                        */
49 /*  INPUT                                                                 */
50 /*                                                                        */
51 /*    media_ptr                             Pointer to media              */
52 /*    entry_ptr                             Directory entry               */
53 /*    unicode_name                          Destination unicode name      */
54 /*    unicode_name_length                   Unicode name size             */
55 /*                                                                        */
56 /*  OUTPUT                                                                */
57 /*                                                                        */
58 /*    Completion Status                                                   */
59 /*                                                                        */
60 /*  CALLS                                                                 */
61 /*                                                                        */
62 /*    _fx_utility_FAT_entry_read            Read a FAT entry              */
63 /*    _fx_utility_logical_sector_read       Read a logical sector         */
64 /*    _fx_utility_logical_sector_write      Write a logical sector        */
65 /*    _fx_fault_tolerant_add_dir_log        Add directory redo log        */
66 /*                                                                        */
67 /*  CALLED BY                                                             */
68 /*                                                                        */
69 /*    Unicode Utilities                                                   */
70 /*                                                                        */
71 /*  RELEASE HISTORY                                                       */
72 /*                                                                        */
73 /*    DATE              NAME                      DESCRIPTION             */
74 /*                                                                        */
75 /*  05-19-2020     William E. Lamie         Initial Version 6.0           */
76 /*  09-30-2020     William E. Lamie         Modified comment(s),          */
77 /*                                            resulting in version 6.1    */
78 /*                                                                        */
79 /**************************************************************************/
_fx_unicode_directory_entry_change(FX_MEDIA * media_ptr,FX_DIR_ENTRY * entry_ptr,UCHAR * unicode_name,ULONG unicode_name_length)80 UINT  _fx_unicode_directory_entry_change(FX_MEDIA *media_ptr, FX_DIR_ENTRY *entry_ptr, UCHAR *unicode_name, ULONG unicode_name_length)
81 {
82 
83 UCHAR *work_ptr, *sector_base_ptr;
84 UINT   status;
85 UINT   i, j, k, u, card, lfn_entries;
86 UCHAR  eof_marker;
87 ULONG  logical_sector, relative_sector;
88 ULONG  byte_offset;
89 ULONG  cluster, next_cluster;
90 
91 #ifdef FX_ENABLE_FAULT_TOLERANT
92 UCHAR *changed_ptr;
93 UINT   changed_size;
94 ULONG  changed_offset;
95 #endif /* FX_ENABLE_FAULT_TOLERANT */
96 
97 
98 #ifndef FX_MEDIA_STATISTICS_DISABLE
99 
100     /* Increment the number of directory entry write requests.  */
101     media_ptr -> fx_media_directory_entry_writes++;
102 #endif
103 
104     /* Pickup the byte offset of the entry.  */
105     byte_offset = entry_ptr -> fx_dir_entry_byte_offset;
106 
107     /* Pickup the logical sector of the entry.  */
108     logical_sector = (ULONG)entry_ptr -> fx_dir_entry_log_sector;
109 
110     /* Figure out where what cluster we are in.  */
111     if (logical_sector >= (ULONG)(media_ptr -> fx_media_data_sector_start))
112     {
113 
114         /* Calculate the cluster that this logical sector is in.  */
115         cluster =  (logical_sector - media_ptr -> fx_media_data_sector_start) / (media_ptr -> fx_media_sectors_per_cluster) + FX_FAT_ENTRY_START;
116 
117         /* Calculate the relative cluster.  */
118         relative_sector =  logical_sector -  (((ULONG)media_ptr -> fx_media_data_sector_start) +
119                                               (((ULONG)cluster - FX_FAT_ENTRY_START) *
120                                                ((ULONG)media_ptr -> fx_media_sectors_per_cluster)));
121     }
122     else
123     {
124 
125         /* Clear the cluster and the relative sector.  */
126         cluster =  0;
127         relative_sector =  0;
128     }
129 
130     /* Read the logical directory sector.  */
131     status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) entry_ptr -> fx_dir_entry_log_sector,
132                                               media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
133 
134     /* Determine if an error occurred.  */
135     if (status != FX_SUCCESS)
136     {
137 
138         /* Return the error status.  */
139         return(status);
140     }
141 
142     /* Setup a pointer into the buffer.  */
143     sector_base_ptr = (UCHAR *)media_ptr -> fx_media_memory_buffer;
144     work_ptr =  sector_base_ptr + (UINT)entry_ptr -> fx_dir_entry_byte_offset;
145 
146     /* Initialize the unicode index.  */
147     u =  0;
148 
149 #ifdef FX_ENABLE_FAULT_TOLERANT
150     /* Initialize data for fault tolerant. */
151     changed_ptr = work_ptr;
152     changed_size = 0;
153     changed_offset = entry_ptr -> fx_dir_entry_byte_offset;
154 #endif /* FX_ENABLE_FAULT_TOLERANT */
155 
156     /* Check for a valid long name.  */
157     if ((0x40 & (*work_ptr)))
158     {
159 
160         /* Get the lower 5 bit containing the cardinality.  */
161         card = (*work_ptr & (UCHAR)0x1f);
162         lfn_entries =  card;
163 
164         /* Loop through the file name.  */
165         for (j = 0; j < lfn_entries; j++)
166         {
167 
168             /* Clear the eof marker.  */
169             eof_marker =  0;
170 
171             /* Loop through file name fields.  */
172             for (i = 1, k = (26 * (card - 1)) & 0xFFFFFFFF; i < FX_DIR_ENTRY_SIZE; i += 2)
173             {
174 
175                 /* Process relative to specific fields.  */
176                 if ((i == 11) || (i == 26))
177                 {
178                     continue;
179                 }
180 
181                 if (i == 13)
182                 {
183                     i = 12;
184                     continue;
185                 }
186 
187                 /* Determine if the EOF marker is present.  */
188                 if (eof_marker)
189                 {
190 
191                     work_ptr[i] = eof_marker;
192                     work_ptr[i + 1] = eof_marker;
193                 }
194                 else if (k < (unicode_name_length * 2))
195                 {
196 
197                     work_ptr[i] = unicode_name[k];
198                     work_ptr[i + 1] = unicode_name[k + 1];
199                     u =  u + 2;
200                 }
201                 else if (k == (unicode_name_length * 2))
202                 {
203 
204                     work_ptr[i] = 0;
205                     work_ptr[i + 1] =  0;
206 
207                     /* end of name, pad with 0xff.  */
208                     eof_marker =  (UCHAR)0xff;
209                 }
210 
211                 k =  k + 2;
212             }
213 
214             /* Decrement the card.  */
215             card--;
216 
217             /* Setup pointers for the name write.  */
218             work_ptr += FX_DIR_ENTRY_SIZE;
219             byte_offset += FX_DIR_ENTRY_SIZE;
220 
221 #ifdef FX_ENABLE_FAULT_TOLERANT
222             /* Update changed_size. */
223             changed_size += FX_DIR_ENTRY_SIZE;
224 #endif /* FX_ENABLE_FAULT_TOLERANT */
225 
226             /* Determine if the write is within the current sector.   */
227             if (byte_offset >= media_ptr -> fx_media_bytes_per_sector)
228             {
229 #ifdef FX_ENABLE_FAULT_TOLERANT
230                 if (media_ptr -> fx_media_fault_tolerant_enabled)
231                 {
232 
233                     /* Redirect this request to log file. */
234                     status = _fx_fault_tolerant_add_dir_log(media_ptr, (ULONG64) logical_sector, changed_offset, changed_ptr, changed_size);
235                 }
236                 else
237                 {
238 
239                     /* Write the current sector out.  */
240                     status =  _fx_utility_logical_sector_write(media_ptr, (ULONG64) logical_sector,
241                                                                sector_base_ptr, ((ULONG) 1), FX_DIRECTORY_SECTOR);
242                 }
243 
244 
245                 /* Determine if an error occurred.  */
246                 if (status != FX_SUCCESS)
247                 {
248 
249                     /* Return the error status.  */
250                     return(status);
251                 }
252 #else /* FX_ENABLE_FAULT_TOLERANT */
253 
254                 /* Write the current sector out.  */
255                 /* Note: Since the sector is in the cache after a sector read, therefore _fx_utility_logical_sector_write
256                    always returns success when FX_ENABLE_FAULT_TOLERANT is not defined.  In other words, the checking
257                    on the return value is needed only when FX_ENABLE_FAULT_TOLERANT is defined. */
258                 _fx_utility_logical_sector_write(media_ptr, (ULONG64) logical_sector,
259                                                  sector_base_ptr, ((ULONG) 1), FX_DIRECTORY_SECTOR);
260 #endif /* FX_ENABLE_FAULT_TOLERANT */
261 
262                 /* Determine if we are in the root directory.  */
263                 if (logical_sector >= (ULONG)(media_ptr -> fx_media_data_sector_start))
264                 {
265 
266                     /* Determine the next sector of the directory entry.  */
267                     if (relative_sector < (media_ptr -> fx_media_sectors_per_cluster - 1))
268                     {
269 
270                         /* More sectors in this cluster.  */
271 
272                         /* Simply increment the logical sector.  */
273                         logical_sector++;
274 
275                         /* Increment the relative sector.  */
276                         relative_sector++;
277                     }
278                     else
279                     {
280 
281                         /* We need to move to the next cluster.  */
282 
283                         /* Pickup the next cluster.  */
284                         status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
285 
286                         /* Check for I/O error.  */
287                         if (status != FX_SUCCESS)
288                         {
289 
290                             /* Return error code.  */
291                             return(status);
292                         }
293 
294                         /* Copy next cluster to the current cluster.  */
295                         cluster =  next_cluster;
296 
297                         /* Check the value of the new cluster - it must be a valid cluster number
298                            or something is really wrong!  */
299                         if ((cluster < FX_FAT_ENTRY_START) || (cluster > media_ptr -> fx_media_fat_reserved))
300                         {
301 
302                             /* Send error message back to caller.  */
303                             return(FX_FILE_CORRUPT);
304                         }
305 
306                         /* Setup the relative sector (this is zero for subsequent cluster.  */
307                         relative_sector =  0;
308 
309                         /* Calculate the next logical sector.  */
310                         logical_sector =   ((ULONG)media_ptr -> fx_media_data_sector_start) +
311                             (((ULONG)cluster - FX_FAT_ENTRY_START) *
312                              ((ULONG)media_ptr -> fx_media_sectors_per_cluster));
313                     }
314                 }
315                 else
316                 {
317 
318                     /* Increment the logical sector.  */
319                     logical_sector++;
320 
321                     /* Determine if the logical sector is valid.  */
322                     if (logical_sector >= (ULONG)(media_ptr -> fx_media_data_sector_start))
323                     {
324 
325                         /* We have exceeded the root directory.  */
326 
327                         /* Send error message back to caller.  */
328                         return(FX_FILE_CORRUPT);
329                     }
330                 }
331 
332                 /* Read the next logical sector.  */
333                 status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) logical_sector,
334                                                           media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
335 
336                 /* Determine if an error occurred.  */
337                 if (status != FX_SUCCESS)
338                 {
339 
340                     /* Return the error status.  */
341                     return(status);
342                 }
343 
344                 /* Move to the next sector buffer.  */
345                 sector_base_ptr = media_ptr -> fx_media_memory_buffer;
346 
347                 /* Setup new buffer pointers.  */
348                 byte_offset =  0;
349                 work_ptr = sector_base_ptr;
350 
351 #ifdef FX_ENABLE_FAULT_TOLERANT
352                 /* Initialize data for fault tolerant. */
353                 changed_ptr = work_ptr;
354                 changed_size = 0;
355                 changed_offset = 0;
356 #endif /* FX_ENABLE_FAULT_TOLERANT */
357             }
358         }
359     }
360 
361     /* Check for an error!  */
362     if (u != (unicode_name_length * 2))
363     {
364 
365         /* Return an error!  */
366         return(FX_FILE_CORRUPT);
367     }
368 
369 #ifdef FX_ENABLE_FAULT_TOLERANT
370     if (media_ptr -> fx_media_fault_tolerant_enabled)
371     {
372 
373         /* Redirect this request to log file. */
374         status = _fx_fault_tolerant_add_dir_log(media_ptr, (ULONG64) logical_sector, changed_offset, changed_ptr, changed_size);
375     }
376     else
377     {
378 #endif /* FX_ENABLE_FAULT_TOLERANT */
379 
380         /* Write the directory sector to the media.  */
381         status =  _fx_utility_logical_sector_write(media_ptr, (ULONG64) logical_sector,
382                                                    sector_base_ptr, ((ULONG) 1), FX_DIRECTORY_SECTOR);
383 #ifdef FX_ENABLE_FAULT_TOLERANT
384     }
385 #endif /* FX_ENABLE_FAULT_TOLERANT */
386 
387     return(status);
388 }
389 
390