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