1 |
|
|
/*************************************************************************** |
2 |
|
|
* Copyright (c) 2024 Microsoft Corporation |
3 |
|
|
* Copyright (c) 2026-present Eclipse ThreadX contributors |
4 |
|
|
* |
5 |
|
|
* This program and the accompanying materials are made available under the |
6 |
|
|
* terms of the MIT License which is available at |
7 |
|
|
* https://opensource.org/licenses/MIT. |
8 |
|
|
* |
9 |
|
|
* SPDX-License-Identifier: MIT |
10 |
|
|
**************************************************************************/ |
11 |
|
|
|
12 |
|
|
|
13 |
|
|
/**************************************************************************/ |
14 |
|
|
/**************************************************************************/ |
15 |
|
|
/** */ |
16 |
|
|
/** FileX Component */ |
17 |
|
|
/** */ |
18 |
|
|
/** Directory */ |
19 |
|
|
/** */ |
20 |
|
|
/**************************************************************************/ |
21 |
|
|
/**************************************************************************/ |
22 |
|
|
|
23 |
|
|
#define FX_SOURCE_CODE |
24 |
|
|
|
25 |
|
|
|
26 |
|
|
/* Include necessary system files. */ |
27 |
|
|
|
28 |
|
|
#include "fx_api.h" |
29 |
|
|
#include "fx_system.h" |
30 |
|
|
#include "fx_directory.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_directory_entry_write PORTABLE C */ |
42 |
|
|
/* 6.1.5 */ |
43 |
|
|
/* AUTHOR */ |
44 |
|
|
/* */ |
45 |
|
|
/* William E. Lamie, Microsoft Corporation */ |
46 |
|
|
/* */ |
47 |
|
|
/* DESCRIPTION */ |
48 |
|
|
/* */ |
49 |
|
|
/* This function writes the supplied directory entry to the specified */ |
50 |
|
|
/* logical sector and offset. */ |
51 |
|
|
/* */ |
52 |
|
|
/* INPUT */ |
53 |
|
|
/* */ |
54 |
|
|
/* media_ptr Media control block pointer */ |
55 |
|
|
/* entry_ptr Pointer to directory entry */ |
56 |
|
|
/* */ |
57 |
|
|
/* OUTPUT */ |
58 |
|
|
/* */ |
59 |
|
|
/* return status */ |
60 |
|
|
/* */ |
61 |
|
|
/* CALLS */ |
62 |
|
|
/* */ |
63 |
|
|
/* _fx_utility_FAT_entry_read Read a new FAT entry */ |
64 |
|
|
/* _fx_utility_logical_sector_read Read directory sector */ |
65 |
|
|
/* _fx_utility_logical_sector_write Write directory sector */ |
66 |
|
|
/* _fx_utility_16_unsigned_write Write a UINT from memory */ |
67 |
|
|
/* _fx_utility_32_unsigned_write Write a ULONG from memory */ |
68 |
|
|
/* _fx_fault_tolerant_add_dir_log Add directory redo log */ |
69 |
|
|
/* */ |
70 |
|
|
/* CALLED BY */ |
71 |
|
|
/* */ |
72 |
|
|
/* FileX System Functions */ |
73 |
|
|
/* */ |
74 |
|
|
/**************************************************************************/ |
75 |
|
145406 |
UINT _fx_directory_entry_write(FX_MEDIA *media_ptr, FX_DIR_ENTRY *entry_ptr) |
76 |
|
|
{ |
77 |
|
|
|
78 |
|
|
UCHAR *work_ptr, *sector_base_ptr; |
79 |
|
|
UINT status, temp, entry, delete_flag; |
80 |
|
|
UINT i, j, k, l, card, len, dotfound, dotpos, match; |
81 |
|
|
UCHAR checksum, eof_marker; |
82 |
|
|
CHAR alpha; |
83 |
|
|
CHAR shortname[FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE + 1]; |
84 |
|
|
ULONG logical_sector, relative_sector; |
85 |
|
|
ULONG byte_offset; |
86 |
|
|
ULONG cluster, next_cluster; |
87 |
|
|
|
88 |
|
|
|
89 |
|
|
#ifdef FX_ENABLE_FAULT_TOLERANT |
90 |
|
|
UCHAR *changed_ptr; |
91 |
|
|
UINT changed_size; |
92 |
|
|
ULONG changed_offset; |
93 |
|
|
#endif /* FX_ENABLE_FAULT_TOLERANT */ |
94 |
|
|
|
95 |
|
|
|
96 |
|
|
#ifndef FX_MEDIA_STATISTICS_DISABLE |
97 |
|
|
|
98 |
|
|
/* Increment the number of directory entry write requests. */ |
99 |
|
145406 |
media_ptr -> fx_media_directory_entry_writes++; |
100 |
|
|
#endif |
101 |
|
|
|
102 |
|
|
/* Extended port-specific processing macro, which is by default defined to white space. */ |
103 |
✓✓✓✓
|
145406 |
FX_DIRECTORY_ENTRY_WRITE_EXTENSION |
104 |
|
|
|
105 |
|
|
/* If trace is enabled, insert this event into the trace buffer. */ |
106 |
|
|
FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_DIR_ENTRY_WRITE, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0) |
107 |
|
|
|
108 |
|
|
/* Determine if this is entry is being deleted. */ |
109 |
✓✓ |
145401 |
if (((UCHAR)entry_ptr -> fx_dir_entry_name[0] == (UCHAR)FX_DIR_ENTRY_FREE) && |
110 |
✓✓ |
3487 |
((UCHAR)entry_ptr -> fx_dir_entry_short_name[0] == (UCHAR)FX_DIR_ENTRY_FREE)) |
111 |
|
|
{ |
112 |
|
|
|
113 |
|
|
/* Yes, this is a request to delete the entry. Set the flag to remember this. */ |
114 |
|
587 |
delete_flag = FX_TRUE; |
115 |
|
|
|
116 |
|
|
/* Null the short file name. */ |
117 |
|
587 |
entry_ptr -> fx_dir_entry_short_name[0] = 0; |
118 |
|
|
} |
119 |
|
|
else |
120 |
|
|
{ |
121 |
|
|
|
122 |
|
|
/* Not a deleted entry. Set the flag to false. */ |
123 |
|
144814 |
delete_flag = FX_FALSE; |
124 |
|
|
} |
125 |
|
|
|
126 |
|
|
/* Pickup the byte offset of the entry. */ |
127 |
|
145401 |
byte_offset = entry_ptr -> fx_dir_entry_byte_offset; |
128 |
|
|
|
129 |
|
|
/* Pickup the logical sector of the entry. */ |
130 |
|
145401 |
logical_sector = (ULONG)entry_ptr -> fx_dir_entry_log_sector; |
131 |
|
|
|
132 |
|
|
/* Figure out where what cluster we are in. */ |
133 |
✓✓ |
145401 |
if (logical_sector >= (ULONG)(media_ptr -> fx_media_data_sector_start)) |
134 |
|
|
{ |
135 |
|
|
|
136 |
|
|
/* Calculate the cluster that this logical sector is in. */ |
137 |
|
88836 |
cluster = (logical_sector - media_ptr -> fx_media_data_sector_start) / (media_ptr -> fx_media_sectors_per_cluster) + FX_FAT_ENTRY_START; |
138 |
|
|
|
139 |
|
|
/* Calculate the relative cluster. */ |
140 |
|
88836 |
relative_sector = logical_sector - (((ULONG)media_ptr -> fx_media_data_sector_start) + |
141 |
|
88836 |
(((ULONG)cluster - FX_FAT_ENTRY_START) * |
142 |
|
88836 |
((ULONG)media_ptr -> fx_media_sectors_per_cluster))); |
143 |
|
|
} |
144 |
|
|
else |
145 |
|
|
{ |
146 |
|
|
|
147 |
|
|
/* Clear the cluster and the relative sector. */ |
148 |
|
56565 |
cluster = 0; |
149 |
|
56565 |
relative_sector = 0; |
150 |
|
|
} |
151 |
|
|
|
152 |
|
|
/* Read the logical directory sector. */ |
153 |
|
145401 |
status = _fx_utility_logical_sector_read(media_ptr, (ULONG64) entry_ptr -> fx_dir_entry_log_sector, |
154 |
|
145401 |
media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR); |
155 |
|
|
|
156 |
|
|
/* Determine if an error occurred. */ |
157 |
✓✓ |
145401 |
if (status != FX_SUCCESS) |
158 |
|
|
{ |
159 |
|
|
|
160 |
|
|
/* Return the error status. */ |
161 |
|
30 |
return(status); |
162 |
|
|
} |
163 |
|
|
|
164 |
|
|
/* Setup a pointer into the buffer. */ |
165 |
|
145371 |
sector_base_ptr = (UCHAR *)media_ptr -> fx_media_memory_buffer; |
166 |
|
145371 |
work_ptr = sector_base_ptr + (UINT)entry_ptr -> fx_dir_entry_byte_offset; |
167 |
|
|
|
168 |
|
|
#ifdef FX_ENABLE_FAULT_TOLERANT |
169 |
|
|
/* Initialize data for fault tolerant. */ |
170 |
|
|
changed_ptr = work_ptr; |
171 |
|
|
changed_size = 0; |
172 |
|
|
changed_offset = entry_ptr -> fx_dir_entry_byte_offset; |
173 |
|
|
#endif /* FX_ENABLE_FAULT_TOLERANT */ |
174 |
|
|
|
175 |
|
|
/* Determine if a long file name is present. */ |
176 |
✓✓ |
145371 |
if (entry_ptr -> fx_dir_entry_long_name_present) |
177 |
|
|
{ |
178 |
|
|
|
179 |
|
|
/* Yes, long name is present - prepare short name and write out this name. */ |
180 |
✓✓ |
24106 |
for (len = 0, i = 0, dotpos = 0, dotfound = 0; entry_ptr -> fx_dir_entry_name[len]; len++) |
181 |
|
|
{ |
182 |
|
|
|
183 |
|
|
/* Check for a dot. */ |
184 |
✓✓ |
22901 |
if (entry_ptr -> fx_dir_entry_name[len] == '.') |
185 |
|
|
{ |
186 |
|
|
|
187 |
|
|
/* Check for leading dot. */ |
188 |
✓✓ |
109 |
if (len == 0) |
189 |
|
|
{ |
190 |
|
|
/* Yes, this is a leading dot. */ |
191 |
|
6 |
continue; |
192 |
|
|
} |
193 |
|
|
|
194 |
|
|
/* Yes, a dot is present. From this position the extension will |
195 |
|
|
be written. */ |
196 |
|
103 |
dotfound = i; |
197 |
|
103 |
dotpos = len + 1; |
198 |
|
103 |
continue; |
199 |
|
|
} |
200 |
|
|
|
201 |
|
|
/* Check for non-space and within the short file name length. */ |
202 |
✓✓✓✓
|
22792 |
if ((entry_ptr -> fx_dir_entry_name[len] != ' ') && (i < 8)) |
203 |
|
|
{ |
204 |
|
|
|
205 |
|
|
/* Copy characters into the short file name area. */ |
206 |
|
7484 |
shortname[i] = entry_ptr -> fx_dir_entry_name[len]; |
207 |
|
7484 |
i++; |
208 |
|
|
} |
209 |
|
|
} |
210 |
|
|
|
211 |
|
|
/* Fill remaining short file name with spaces. */ |
212 |
✓✓ |
6976 |
for (j = i; j < FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE; j++) |
213 |
|
|
{ |
214 |
|
5771 |
shortname[j] = ' '; |
215 |
|
|
} |
216 |
|
|
|
217 |
|
|
/* Determine if a dot was encountered. */ |
218 |
✓✓ |
1205 |
if (dotpos) |
219 |
|
|
{ |
220 |
|
|
|
221 |
|
|
/* Process relative to the dot position. */ |
222 |
✓✓ |
83 |
if (entry_ptr -> fx_dir_entry_name[dotpos]) |
223 |
|
|
{ |
224 |
|
70 |
shortname[8] = entry_ptr -> fx_dir_entry_name[dotpos++]; |
225 |
|
|
} |
226 |
✓✓ |
83 |
if (entry_ptr -> fx_dir_entry_name[dotpos]) |
227 |
|
|
{ |
228 |
|
67 |
shortname[9] = entry_ptr -> fx_dir_entry_name[dotpos++]; |
229 |
|
|
} |
230 |
✓✓ |
83 |
if (entry_ptr -> fx_dir_entry_name[dotpos]) |
231 |
|
|
{ |
232 |
|
64 |
shortname[10] = entry_ptr -> fx_dir_entry_name[dotpos++]; |
233 |
|
|
} |
234 |
|
|
|
235 |
|
|
/* Determine if additional spaces are needed. */ |
236 |
|
83 |
i = dotfound; |
237 |
|
|
|
238 |
✓✓ |
348 |
for (; dotfound <= 7; dotfound++) |
239 |
|
|
{ |
240 |
|
|
/* Add space... */ |
241 |
|
265 |
shortname[dotfound] = ' '; |
242 |
|
|
} |
243 |
|
|
} |
244 |
|
|
|
245 |
|
|
/* Each entry contains 13 unicode entries. Calculate the remainder. */ |
246 |
✓✓ |
1205 |
if (len % 13 == 0) |
247 |
|
|
{ |
248 |
|
30 |
card = len / 13; |
249 |
|
|
} |
250 |
|
|
else |
251 |
|
|
{ |
252 |
|
1175 |
card = len / 13 + 1; |
253 |
|
|
} |
254 |
|
|
|
255 |
|
|
/* Default the name match to true. */ |
256 |
|
1205 |
match = FX_TRUE; |
257 |
|
|
|
258 |
|
|
/* Loop through the newly derived short name and the original name and look |
259 |
|
|
for a non-matching character. */ |
260 |
|
1205 |
l = 0; |
261 |
|
1205 |
k = 0; |
262 |
✓✓ |
8692 |
while (k < FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE) |
263 |
|
|
{ |
264 |
|
|
|
265 |
|
|
/* Determine if a space is detected in the short name. If so, |
266 |
|
|
advance to the extension index. */ |
267 |
✓✓ |
8647 |
if (shortname[k] == ' ') |
268 |
|
|
{ |
269 |
|
|
|
270 |
|
|
/* The first pad space was detected. First, check for a name |
271 |
|
|
without an extension. */ |
272 |
✓✓ |
1194 |
if (entry_ptr -> fx_dir_entry_name[l] == FX_NULL) |
273 |
|
|
{ |
274 |
|
|
|
275 |
|
|
/* All is okay, get out of the loop! */ |
276 |
|
467 |
break; |
277 |
|
|
} |
278 |
|
|
|
279 |
|
|
/* Now check for a period in the long name... if not, there is a non-match! */ |
280 |
✓✓ |
727 |
if (entry_ptr -> fx_dir_entry_name[l] != '.') |
281 |
|
|
{ |
282 |
|
|
|
283 |
|
|
/* Set the match flag to false and exit the loop. */ |
284 |
|
670 |
match = FX_FALSE; |
285 |
|
670 |
break; |
286 |
|
|
} |
287 |
|
|
|
288 |
|
|
/* Otherwise move short file name index to the extension area and |
289 |
|
|
increment the long file name index. */ |
290 |
|
57 |
k = 8; |
291 |
|
57 |
l++; |
292 |
|
|
|
293 |
|
|
/* Restart the loop at the top. */ |
294 |
|
57 |
continue; |
295 |
|
|
} |
296 |
|
|
|
297 |
|
|
/* Check for the dot for the 8.3 match... it is no longer in the |
298 |
|
|
shortname but possibly still present in the long name. */ |
299 |
✓✓✓✓
|
7453 |
if ((k == 8) && (entry_ptr -> fx_dir_entry_name[l] == '.')) |
300 |
|
|
{ |
301 |
|
|
|
302 |
|
|
/* Yes, handle the implicit dot in the shortname by |
303 |
|
|
positioning past it in the long name. */ |
304 |
|
10 |
l++; |
305 |
|
|
} |
306 |
|
|
|
307 |
|
|
/* Do the names match? */ |
308 |
✓✓ |
7453 |
if (shortname[k] != entry_ptr -> fx_dir_entry_name[l]) |
309 |
|
|
{ |
310 |
|
|
|
311 |
|
|
/* No, the names do not match, set the match flag to false and |
312 |
|
|
exit the loop. */ |
313 |
|
23 |
match = FX_FALSE; |
314 |
|
23 |
break; |
315 |
|
|
} |
316 |
|
|
|
317 |
|
|
/* Move the indices forward. */ |
318 |
|
7430 |
k++; |
319 |
|
7430 |
l++; |
320 |
|
|
} |
321 |
|
|
|
322 |
|
|
/* Check if there is a dot in the name, but no extension in the short name. In this case, |
323 |
|
|
we should create a mangled short name. */ |
324 |
✓✓✓✓
|
1205 |
if ((dotpos) && (shortname[8] == ' ')) |
325 |
|
|
{ |
326 |
|
|
|
327 |
|
|
/* Something left.. the names do not match! */ |
328 |
|
17 |
match = FX_FALSE; |
329 |
|
|
} |
330 |
|
|
|
331 |
|
|
/* One final check to make sure there is nothing left on the long file name. */ |
332 |
✓✓ |
1205 |
if (entry_ptr -> fx_dir_entry_name[l]) |
333 |
|
|
{ |
334 |
|
|
|
335 |
|
|
/* Something left.. the names do not match! */ |
336 |
|
694 |
match = FX_FALSE; |
337 |
|
|
} |
338 |
|
|
|
339 |
|
|
/* Determine if the derived short name matches exactly the long file name. If so |
340 |
|
|
we don't need to mangle the name with a numeric value based on its entry. */ |
341 |
✓✓ |
1205 |
if (match == FX_FALSE) |
342 |
|
|
{ |
343 |
|
|
|
344 |
|
|
/* Name does not match, create a mangled name. */ |
345 |
|
|
|
346 |
|
|
/* Generate short file name from LFN. */ |
347 |
|
705 |
entry = entry_ptr -> fx_dir_entry_number; |
348 |
|
|
|
349 |
|
|
/* Name suffice is between 000 and FFFF in hex, calculate this short file |
350 |
|
|
name's numeric component. */ |
351 |
|
705 |
entry = entry % 0x10000; |
352 |
|
|
|
353 |
|
|
/* Build short name of the format xxx~NNNN.ext. */ |
354 |
✓✓ |
705 |
if (i > 3) |
355 |
|
|
{ |
356 |
|
698 |
i = 3; |
357 |
|
|
} |
358 |
|
705 |
shortname[i++] = '~'; |
359 |
|
|
|
360 |
|
|
/* Loop to build the numeric part of the name. */ |
361 |
✓✓ |
3525 |
for (l = 0; l < 4; l++) |
362 |
|
|
{ |
363 |
|
|
|
364 |
|
|
/* Shift down the entry number based on the numeric position. */ |
365 |
✓✓ |
2820 |
if (l == 0) |
366 |
|
|
{ |
367 |
|
705 |
temp = ((entry >> 12) & 0xf); |
368 |
|
|
} |
369 |
✓✓ |
2115 |
else if (l == 1) |
370 |
|
|
{ |
371 |
|
705 |
temp = ((entry >> 8) & 0xf); |
372 |
|
|
} |
373 |
✓✓ |
1410 |
else if (l == 2) |
374 |
|
|
{ |
375 |
|
705 |
temp = ((entry >> 4) & 0xf); |
376 |
|
|
} |
377 |
|
|
else |
378 |
|
|
{ |
379 |
|
705 |
temp = ((entry) & 0xf); |
380 |
|
|
} |
381 |
|
|
|
382 |
|
|
/* Now build hex value. */ |
383 |
✓✓ |
2820 |
if (temp > 9) |
384 |
|
191 |
shortname[i++] = (CHAR)('A' + (temp - 10)); |
385 |
|
|
else |
386 |
|
2629 |
shortname[i++] = (CHAR)('0' + temp); |
387 |
|
|
} |
388 |
|
|
} |
389 |
|
|
|
390 |
|
|
/* Set end of short string to NULL. */ |
391 |
|
1205 |
shortname[11] = 0; |
392 |
|
|
|
393 |
|
|
/* Determine if the first character of the short file name is the directory free |
394 |
|
|
value. If so, it must be changed. */ |
395 |
✓✓✓✓
|
1205 |
if (((UCHAR)shortname[0] == (UCHAR)FX_DIR_ENTRY_FREE) && (delete_flag == FX_FALSE)) |
396 |
|
|
{ |
397 |
|
|
|
398 |
|
|
/* Change to 0x8F to be compatible with what DOS does. */ |
399 |
|
11 |
shortname[0] = (CHAR)0x8F; |
400 |
|
|
} |
401 |
|
|
|
402 |
|
|
/* Loop to convert the new short file name to upper case. */ |
403 |
✓✓ |
14460 |
for (i = 0; i < (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE); i++) |
404 |
|
|
{ |
405 |
|
|
|
406 |
|
|
/* Pickup shortname character. */ |
407 |
|
13255 |
alpha = shortname[i]; |
408 |
|
|
|
409 |
|
|
/* Determine if character is lower case. */ |
410 |
✓✓✓✓
|
13255 |
if ((alpha >= 'a') && (alpha <= 'z')) |
411 |
|
|
{ |
412 |
|
|
|
413 |
|
|
/* Store the character - converted to upper case. */ |
414 |
|
2260 |
alpha = (CHAR)(alpha - ((CHAR)0x20)); |
415 |
|
|
} |
416 |
|
|
|
417 |
|
|
/* Now store the short name character. */ |
418 |
|
13255 |
shortname[i] = alpha; |
419 |
|
|
} |
420 |
|
|
|
421 |
|
|
/* Determine if there already is a short name and we are not deleting the entry. */ |
422 |
✓✓ |
1205 |
if (entry_ptr -> fx_dir_entry_short_name[0] != 0) |
423 |
|
|
{ |
424 |
|
|
|
425 |
|
|
/* Yes, override the calculated shortname with the original 8.3 name. */ |
426 |
|
|
|
427 |
|
|
/* Clear the short file name area. */ |
428 |
✓✓ |
636 |
for (i = 0; i < FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE; i++) |
429 |
|
|
{ |
430 |
|
583 |
shortname[i] = ' '; |
431 |
|
|
} |
432 |
|
|
|
433 |
|
|
/* Loop to copy the original short file name. */ |
434 |
✓✓ |
433 |
for (i = 0, j = 0; j < FX_DIR_NAME_SIZE; i++, j++) |
435 |
|
|
{ |
436 |
|
|
|
437 |
|
|
/* Check for end of copy conditions. */ |
438 |
✓✓ |
390 |
if ((UCHAR)entry_ptr -> fx_dir_entry_short_name[i] == '.') |
439 |
|
|
{ |
440 |
|
2 |
break; |
441 |
|
|
} |
442 |
✓✓ |
388 |
if ((UCHAR)entry_ptr -> fx_dir_entry_short_name[i] == 0) |
443 |
|
|
{ |
444 |
|
8 |
break; |
445 |
|
|
} |
446 |
|
|
|
447 |
|
|
/* Pickup the character. */ |
448 |
|
380 |
alpha = entry_ptr -> fx_dir_entry_short_name[i]; |
449 |
|
|
|
450 |
|
|
/* Copy file name character. */ |
451 |
|
380 |
shortname[j] = alpha; |
452 |
|
|
} |
453 |
|
|
|
454 |
|
|
/* Determine if there is anything left in the short file name. */ |
455 |
✓✓ |
53 |
if ((UCHAR)entry_ptr -> fx_dir_entry_short_name[i] != 0) |
456 |
|
|
{ |
457 |
|
|
|
458 |
|
|
/* Pickup remaining characters. */ |
459 |
✓✓ |
15 |
for (i++, j = FX_DIR_NAME_SIZE; j < FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE; i++, j++) |
460 |
|
|
{ |
461 |
|
|
|
462 |
|
|
/* If NULL is encountered, stop the copying. */ |
463 |
✓✓ |
12 |
if ((UCHAR)entry_ptr -> fx_dir_entry_short_name[i] == 0) |
464 |
|
|
{ |
465 |
|
1 |
break; |
466 |
|
|
} |
467 |
|
|
|
468 |
|
|
/* Pickup the character. */ |
469 |
|
11 |
alpha = entry_ptr -> fx_dir_entry_short_name[i]; |
470 |
|
|
|
471 |
|
|
/* Copy file name character. */ |
472 |
|
11 |
shortname[j] = alpha; |
473 |
|
|
} |
474 |
|
|
} |
475 |
|
|
|
476 |
|
|
/* Loop to make sure the short name is upper case. */ |
477 |
✓✓ |
636 |
for (j = 0; j < (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE); j++) |
478 |
|
|
{ |
479 |
|
|
|
480 |
|
|
/* Pickup the character. */ |
481 |
|
583 |
alpha = shortname[j]; |
482 |
|
|
|
483 |
|
|
/* Determine if character is lower case. */ |
484 |
✓✓✓✓
|
583 |
if ((alpha >= 'a') && (alpha <= 'z')) |
485 |
|
|
{ |
486 |
|
|
|
487 |
|
|
/* Store the character - converted to upper case. */ |
488 |
|
1 |
alpha = (CHAR)(alpha - ((CHAR)0x20)); |
489 |
|
|
} |
490 |
|
|
|
491 |
|
|
/* Copy file name character. */ |
492 |
|
583 |
shortname[j] = alpha; |
493 |
|
|
} |
494 |
|
|
|
495 |
|
|
/* Determine if the first character of the short file name is the directory free |
496 |
|
|
value. If so, it must be changed. */ |
497 |
✓✓ |
53 |
if (((UCHAR)shortname[0]) == ((UCHAR)FX_DIR_ENTRY_FREE)) |
498 |
|
|
{ |
499 |
|
|
|
500 |
|
|
/* Change to 0x8F to be compatible with what DOS does. */ |
501 |
|
1 |
shortname[0] = (CHAR)0x8F; |
502 |
|
|
} |
503 |
|
|
} |
504 |
|
|
|
505 |
|
|
/* Loop to calculate the checksum. */ |
506 |
✓✓ |
14460 |
for (i = checksum = 0; i < FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE; i++) |
507 |
|
|
{ |
508 |
|
|
|
509 |
|
|
/* Calculate the checksum. */ |
510 |
|
13255 |
checksum = (UCHAR)((UCHAR)(((checksum & 1) << 7) | ((checksum & (UCHAR)0xfe) >> 1)) + shortname[i]); |
511 |
|
|
} |
512 |
|
|
|
513 |
|
|
/* Set the last entry mark. */ |
514 |
|
1205 |
work_ptr[0] = (UCHAR)(0x40 | card); |
515 |
|
|
|
516 |
|
|
/* Loop to process remainder of long file name entry. */ |
517 |
✓✓ |
3636 |
while (card > 0) |
518 |
|
|
{ |
519 |
|
|
|
520 |
|
|
/* Clear eof marker. */ |
521 |
|
2437 |
eof_marker = 0; |
522 |
|
|
|
523 |
|
|
/* Determine if the entry is free. */ |
524 |
✓✓ |
2437 |
if ((UCHAR)shortname[0] == (UCHAR)FX_DIR_ENTRY_FREE) |
525 |
|
|
{ |
526 |
|
|
/* Yes, place delete marker. */ |
527 |
|
290 |
work_ptr[0] = (UCHAR)FX_DIR_ENTRY_FREE; |
528 |
|
|
} |
529 |
|
|
|
530 |
|
|
/* Setup various long file name fields. */ |
531 |
|
2437 |
work_ptr[11] = FX_LONG_NAME; |
532 |
|
2437 |
work_ptr[12] = 0; |
533 |
|
2437 |
work_ptr[13] = checksum; |
534 |
|
2437 |
work_ptr[26] = 0; |
535 |
|
2437 |
work_ptr[27] = 0; |
536 |
|
|
|
537 |
|
|
/* Loop through file name fields. */ |
538 |
✓✓ |
41429 |
for (i = 1, j = 13 * (card - 1); i < FX_DIR_ENTRY_SIZE; i += 2) |
539 |
|
|
{ |
540 |
|
|
|
541 |
|
|
/* Process relative to specific fields. */ |
542 |
✓✓✓✓
|
38992 |
if ((i == 11) || (i == 26)) |
543 |
|
|
{ |
544 |
|
4874 |
continue; |
545 |
|
|
} |
546 |
|
|
|
547 |
✓✓ |
34118 |
if (i == 13) |
548 |
|
|
{ |
549 |
|
2437 |
i = 12; |
550 |
|
2437 |
continue; |
551 |
|
|
} |
552 |
|
|
|
553 |
|
|
/* Determine if the EOF marker is present. */ |
554 |
✓✓ |
31681 |
if (eof_marker) |
555 |
|
|
{ |
556 |
|
|
|
557 |
|
8931 |
work_ptr[i] = eof_marker; |
558 |
|
8931 |
work_ptr[i + 1] = eof_marker; |
559 |
|
|
} |
560 |
|
|
else |
561 |
|
|
{ |
562 |
|
22750 |
work_ptr[i] = (UCHAR)entry_ptr -> fx_dir_entry_name[j]; |
563 |
|
22750 |
work_ptr[i + 1] = 0; |
564 |
|
|
} |
565 |
|
|
|
566 |
✓✓ |
31681 |
if (entry_ptr -> fx_dir_entry_name[j] == 0) |
567 |
|
|
{ |
568 |
|
|
|
569 |
|
|
/* end of name, pad with 0xff. */ |
570 |
|
9429 |
eof_marker = (UCHAR)0xff; |
571 |
|
|
} |
572 |
|
|
|
573 |
|
31681 |
j++; |
574 |
|
|
} |
575 |
|
|
|
576 |
|
|
/* Move to the next directory entry. */ |
577 |
|
2437 |
work_ptr += FX_DIR_ENTRY_SIZE; |
578 |
|
2437 |
byte_offset += FX_DIR_ENTRY_SIZE; |
579 |
|
|
|
580 |
|
|
#ifdef FX_ENABLE_FAULT_TOLERANT |
581 |
|
|
/* Update changed_size. */ |
582 |
|
|
changed_size += FX_DIR_ENTRY_SIZE; |
583 |
|
|
#endif /* FX_ENABLE_FAULT_TOLERANT */ |
584 |
|
|
|
585 |
|
|
/* Determine if the entry overlaps into the next sector. */ |
586 |
✓✓ |
2437 |
if (byte_offset >= media_ptr -> fx_media_bytes_per_sector) |
587 |
|
|
{ |
588 |
|
|
#ifdef FX_ENABLE_FAULT_TOLERANT |
589 |
|
|
if (media_ptr -> fx_media_fault_tolerant_enabled) |
590 |
|
|
{ |
591 |
|
|
|
592 |
|
|
/* Redirect this request to log file. */ |
593 |
|
|
status = _fx_fault_tolerant_add_dir_log(media_ptr, logical_sector, changed_offset, changed_ptr, changed_size); |
594 |
|
|
} |
595 |
|
|
else |
596 |
|
|
{ |
597 |
|
|
#endif /* FX_ENABLE_FAULT_TOLERANT */ |
598 |
|
|
|
599 |
|
|
/* Write current logical sector out. */ |
600 |
|
550 |
status = _fx_utility_logical_sector_write(media_ptr, (ULONG64) logical_sector, |
601 |
|
|
sector_base_ptr, ((ULONG) 1), FX_DIRECTORY_SECTOR); |
602 |
|
|
#ifdef FX_ENABLE_FAULT_TOLERANT |
603 |
|
|
} |
604 |
|
|
#endif /* FX_ENABLE_FAULT_TOLERANT */ |
605 |
|
|
|
606 |
|
|
/* Determine if an error occurred. */ |
607 |
✓✓ |
550 |
if (status != FX_SUCCESS) |
608 |
|
|
{ |
609 |
|
|
|
610 |
|
|
/* Return the error status. */ |
611 |
|
1 |
return(status); |
612 |
|
|
} |
613 |
|
|
|
614 |
|
|
/* Determine if we are in the root directory. */ |
615 |
✓✓ |
549 |
if (logical_sector >= (ULONG)(media_ptr -> fx_media_data_sector_start)) |
616 |
|
|
{ |
617 |
|
|
|
618 |
|
|
/* Determine the next sector of the directory entry. */ |
619 |
✓✓ |
400 |
if (relative_sector < (media_ptr -> fx_media_sectors_per_cluster - 1)) |
620 |
|
|
{ |
621 |
|
|
|
622 |
|
|
/* More sectors in this cluster. */ |
623 |
|
|
|
624 |
|
|
/* Simply increment the logical sector. */ |
625 |
|
45 |
logical_sector++; |
626 |
|
|
|
627 |
|
|
/* Increment the relative sector. */ |
628 |
|
45 |
relative_sector++; |
629 |
|
|
} |
630 |
|
|
else |
631 |
|
|
{ |
632 |
|
|
|
633 |
|
|
/* We need to move to the next cluster. */ |
634 |
|
|
|
635 |
|
|
/* Pickup the next cluster. */ |
636 |
|
355 |
status = _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster); |
637 |
|
|
|
638 |
|
|
/* Check for I/O error. */ |
639 |
✓✓ |
355 |
if (status != FX_SUCCESS) |
640 |
|
|
{ |
641 |
|
|
|
642 |
|
|
/* Return error code. */ |
643 |
|
1 |
return(status); |
644 |
|
|
} |
645 |
|
|
|
646 |
|
|
/* Copy next cluster to the current cluster. */ |
647 |
|
354 |
cluster = next_cluster; |
648 |
|
|
|
649 |
|
|
/* Check the value of the new cluster - it must be a valid cluster number |
650 |
|
|
or something is really wrong! */ |
651 |
✓✓✓✓
|
354 |
if ((cluster < FX_FAT_ENTRY_START) || (cluster >= media_ptr -> fx_media_fat_reserved)) |
652 |
|
|
{ |
653 |
|
|
|
654 |
|
|
/* Send error message back to caller. */ |
655 |
|
2 |
return(FX_FILE_CORRUPT); |
656 |
|
|
} |
657 |
|
|
|
658 |
|
|
/* Setup the relative sector (this is zero for subsequent cluster. */ |
659 |
|
352 |
relative_sector = 0; |
660 |
|
|
|
661 |
|
|
/* Calculate the next logical sector. */ |
662 |
|
352 |
logical_sector = ((ULONG)media_ptr -> fx_media_data_sector_start) + |
663 |
|
352 |
(((ULONG)cluster - FX_FAT_ENTRY_START) * |
664 |
|
352 |
((ULONG)media_ptr -> fx_media_sectors_per_cluster)); |
665 |
|
|
} |
666 |
|
|
} |
667 |
|
|
else |
668 |
|
|
{ |
669 |
|
|
|
670 |
|
|
/* Increment the logical sector. */ |
671 |
|
149 |
logical_sector++; |
672 |
|
|
|
673 |
|
|
/* Determine if the logical sector is valid. */ |
674 |
✓✓ |
149 |
if (logical_sector >= (ULONG)(media_ptr -> fx_media_data_sector_start)) |
675 |
|
|
{ |
676 |
|
|
|
677 |
|
|
/* We have exceeded the root directory. */ |
678 |
|
|
|
679 |
|
|
/* Send error message back to caller. */ |
680 |
|
1 |
return(FX_FILE_CORRUPT); |
681 |
|
|
} |
682 |
|
|
} |
683 |
|
|
|
684 |
|
|
/* Read the sector. */ |
685 |
|
545 |
status = _fx_utility_logical_sector_read(media_ptr, (ULONG64) logical_sector, |
686 |
|
545 |
media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR); |
687 |
|
|
|
688 |
|
|
/* Determine if an error occurred. */ |
689 |
✓✓ |
545 |
if (status != FX_SUCCESS) |
690 |
|
|
{ |
691 |
|
|
|
692 |
|
|
/* Return the error status. */ |
693 |
|
1 |
return(status); |
694 |
|
|
} |
695 |
|
|
|
696 |
|
|
/* Setup logical sector. */ |
697 |
|
544 |
sector_base_ptr = media_ptr -> fx_media_memory_buffer; |
698 |
|
|
|
699 |
|
|
/* Setup a fresh byte offset. */ |
700 |
|
544 |
byte_offset = 0; |
701 |
|
|
|
702 |
|
|
/* Setup a new pointer into the buffer. */ |
703 |
|
544 |
work_ptr = sector_base_ptr; |
704 |
|
|
|
705 |
|
|
#ifdef FX_ENABLE_FAULT_TOLERANT |
706 |
|
|
/* Initialize data for fault tolerant. */ |
707 |
|
|
changed_ptr = work_ptr; |
708 |
|
|
changed_size = 0; |
709 |
|
|
changed_offset = 0; |
710 |
|
|
#endif /* FX_ENABLE_FAULT_TOLERANT */ |
711 |
|
|
} |
712 |
|
|
|
713 |
|
|
/* Decrement loop control. */ |
714 |
|
2431 |
card--; |
715 |
|
2431 |
work_ptr[0] = (UCHAR)card; |
716 |
|
|
} |
717 |
|
|
|
718 |
|
|
/* Determine if there is a short name. */ |
719 |
✓✓ |
1199 |
if (entry_ptr -> fx_dir_entry_short_name[0] == 0) |
720 |
|
|
{ |
721 |
|
|
|
722 |
|
|
/* Loop to copy the new short file name. */ |
723 |
✓✓ |
13752 |
for (i = 0; i < (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE); i++) |
724 |
|
|
{ |
725 |
|
|
|
726 |
|
|
/* Pickup shortname character. */ |
727 |
|
12606 |
alpha = shortname[i]; |
728 |
|
|
|
729 |
|
|
/* Now store the short name character. */ |
730 |
|
12606 |
*work_ptr++ = (UCHAR)alpha; |
731 |
|
|
} |
732 |
|
|
} |
733 |
|
|
else |
734 |
|
|
{ |
735 |
|
|
|
736 |
|
|
/* Clear the short file name area. */ |
737 |
✓✓ |
636 |
for (i = 0; i < FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE; i++) |
738 |
|
|
{ |
739 |
|
583 |
work_ptr[i] = ' '; |
740 |
|
|
} |
741 |
|
|
|
742 |
|
|
/* Loop to copy the old short file name. */ |
743 |
✓✓ |
433 |
for (i = 0, j = 0; j < FX_DIR_NAME_SIZE; i++, j++) |
744 |
|
|
{ |
745 |
|
|
|
746 |
|
|
/* Check for end of copy conditions. */ |
747 |
✓✓ |
390 |
if ((UCHAR)entry_ptr -> fx_dir_entry_short_name[i] == '.') |
748 |
|
|
{ |
749 |
|
2 |
break; |
750 |
|
|
} |
751 |
✓✓ |
388 |
if ((UCHAR)entry_ptr -> fx_dir_entry_short_name[i] == 0) |
752 |
|
|
{ |
753 |
|
8 |
break; |
754 |
|
|
} |
755 |
|
|
|
756 |
|
|
/* Copy file name character. */ |
757 |
|
380 |
work_ptr[j] = (UCHAR)entry_ptr -> fx_dir_entry_short_name[i]; |
758 |
|
|
} |
759 |
|
|
|
760 |
|
|
/* Determine if there is anything left in the short file name. */ |
761 |
✓✓ |
53 |
if ((UCHAR)entry_ptr -> fx_dir_entry_short_name[i] != 0) |
762 |
|
|
{ |
763 |
|
|
|
764 |
|
|
/* Pickup remaining characters. */ |
765 |
✓✓ |
15 |
for (i++, j = FX_DIR_NAME_SIZE; j < FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE; i++, j++) |
766 |
|
|
{ |
767 |
|
|
|
768 |
|
|
/* If NULL is encountered, stop the copying. */ |
769 |
✓✓ |
12 |
if ((UCHAR)entry_ptr -> fx_dir_entry_short_name[i] == 0) |
770 |
|
|
{ |
771 |
|
1 |
break; |
772 |
|
|
} |
773 |
|
|
|
774 |
|
|
/* Copy file name character. */ |
775 |
|
11 |
work_ptr[j] = (UCHAR)entry_ptr -> fx_dir_entry_short_name[i]; |
776 |
|
|
} |
777 |
|
|
} |
778 |
|
|
|
779 |
|
|
/* Adjust the work pointer accordingly. */ |
780 |
|
53 |
work_ptr += (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE); |
781 |
|
|
} |
782 |
|
|
} |
783 |
|
|
else |
784 |
|
|
{ |
785 |
|
|
|
786 |
|
|
/* Determine if long name was shorted. */ |
787 |
✓✓ |
144166 |
if (entry_ptr -> fx_dir_entry_long_name_shorted > 0) |
788 |
|
|
{ |
789 |
|
|
|
790 |
|
|
/* Check for a valid short name. */ |
791 |
✓✓ |
15 |
if ((UCHAR)(0x40 | entry_ptr -> fx_dir_entry_long_name_shorted) == (UCHAR)(*work_ptr)) |
792 |
|
|
{ |
793 |
|
|
|
794 |
|
|
/* Loop through the file name. */ |
795 |
✓✓ |
89 |
for (j = 0; j < entry_ptr -> fx_dir_entry_long_name_shorted; j++) |
796 |
|
|
{ |
797 |
|
|
|
798 |
|
|
/* Check for a free entry to be written. */ |
799 |
✓✓ |
81 |
if ((UCHAR)entry_ptr -> fx_dir_entry_name[0] == (UCHAR)FX_DIR_ENTRY_FREE) |
800 |
|
|
{ |
801 |
|
|
/* Delete long parts. */ |
802 |
|
26 |
work_ptr[0] = (UCHAR)FX_DIR_ENTRY_FREE; |
803 |
|
|
} |
804 |
|
|
|
805 |
|
|
/* Setup pointers for the name write. */ |
806 |
|
81 |
work_ptr += FX_DIR_ENTRY_SIZE; |
807 |
|
81 |
byte_offset += FX_DIR_ENTRY_SIZE; |
808 |
|
|
|
809 |
|
|
#ifdef FX_ENABLE_FAULT_TOLERANT |
810 |
|
|
/* Update changed_size. */ |
811 |
|
|
changed_size += FX_DIR_ENTRY_SIZE; |
812 |
|
|
#endif /* FX_ENABLE_FAULT_TOLERANT */ |
813 |
|
|
|
814 |
|
|
/* Determine if the write is within the current sector. */ |
815 |
✓✓ |
81 |
if (byte_offset >= media_ptr -> fx_media_bytes_per_sector) |
816 |
|
|
{ |
817 |
|
|
#ifdef FX_ENABLE_FAULT_TOLERANT |
818 |
|
|
if (media_ptr -> fx_media_fault_tolerant_enabled) |
819 |
|
|
{ |
820 |
|
|
|
821 |
|
|
/* Redirect this request to log file. */ |
822 |
|
|
status = _fx_fault_tolerant_add_dir_log(media_ptr, (ULONG64) logical_sector, changed_offset, changed_ptr, changed_size); |
823 |
|
|
} |
824 |
|
|
else |
825 |
|
|
{ |
826 |
|
|
#endif /* FX_ENABLE_FAULT_TOLERANT */ |
827 |
|
|
|
828 |
|
|
/* Write the current sector out. */ |
829 |
|
22 |
status = _fx_utility_logical_sector_write(media_ptr, (ULONG64) logical_sector, |
830 |
|
|
sector_base_ptr, ((ULONG) 1), FX_DIRECTORY_SECTOR); |
831 |
|
|
#ifdef FX_ENABLE_FAULT_TOLERANT |
832 |
|
|
} |
833 |
|
|
#endif /* FX_ENABLE_FAULT_TOLERANT */ |
834 |
|
|
|
835 |
|
|
/* Determine if an error occurred. */ |
836 |
✓✓ |
22 |
if (status != FX_SUCCESS) |
837 |
|
|
{ |
838 |
|
|
|
839 |
|
|
/* Return the error status. */ |
840 |
|
1 |
return(status); |
841 |
|
|
} |
842 |
|
|
|
843 |
|
|
/* Determine if we are in the root directory. */ |
844 |
✓✓ |
21 |
if (logical_sector >= (ULONG)(media_ptr -> fx_media_data_sector_start)) |
845 |
|
|
{ |
846 |
|
|
|
847 |
|
|
/* Determine the next sector of the directory entry. */ |
848 |
✓✓ |
11 |
if (relative_sector < (media_ptr -> fx_media_sectors_per_cluster - 1)) |
849 |
|
|
{ |
850 |
|
|
|
851 |
|
|
/* More sectors in this cluster. */ |
852 |
|
|
|
853 |
|
|
/* Simply increment the logical sector. */ |
854 |
|
6 |
logical_sector++; |
855 |
|
|
|
856 |
|
|
/* Increment the relative sector. */ |
857 |
|
6 |
relative_sector++; |
858 |
|
|
} |
859 |
|
|
else |
860 |
|
|
{ |
861 |
|
|
|
862 |
|
|
/* We need to move to the next cluster. */ |
863 |
|
|
|
864 |
|
|
/* Pickup the next cluster. */ |
865 |
|
5 |
status = _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster); |
866 |
|
|
|
867 |
|
|
/* Check for I/O error. */ |
868 |
✓✓ |
5 |
if (status != FX_SUCCESS) |
869 |
|
|
{ |
870 |
|
|
|
871 |
|
|
/* Return error code. */ |
872 |
|
1 |
return(status); |
873 |
|
|
} |
874 |
|
|
|
875 |
|
|
/* Copy next cluster to the current cluster. */ |
876 |
|
4 |
cluster = next_cluster; |
877 |
|
|
|
878 |
|
|
/* Check the value of the new cluster - it must be a valid cluster number |
879 |
|
|
or something is really wrong! */ |
880 |
✓✓✓✓
|
4 |
if ((cluster < FX_FAT_ENTRY_START) || (cluster >= media_ptr -> fx_media_fat_reserved)) |
881 |
|
|
{ |
882 |
|
|
|
883 |
|
|
/* Send error message back to caller. */ |
884 |
|
2 |
return(FX_FILE_CORRUPT); |
885 |
|
|
} |
886 |
|
|
|
887 |
|
|
/* Setup the relative sector (this is zero for subsequent cluster. */ |
888 |
|
2 |
relative_sector = 0; |
889 |
|
|
|
890 |
|
|
/* Calculate the next logical sector. */ |
891 |
|
2 |
logical_sector = ((ULONG)media_ptr -> fx_media_data_sector_start) + |
892 |
|
2 |
(((ULONG)cluster - FX_FAT_ENTRY_START) * |
893 |
|
2 |
((ULONG)media_ptr -> fx_media_sectors_per_cluster)); |
894 |
|
|
} |
895 |
|
|
} |
896 |
|
|
else |
897 |
|
|
{ |
898 |
|
|
|
899 |
|
|
/* Increment the logical sector. */ |
900 |
|
10 |
logical_sector++; |
901 |
|
|
|
902 |
|
|
/* Determine if the logical sector is valid. */ |
903 |
✓✓ |
10 |
if (logical_sector >= (ULONG)(media_ptr -> fx_media_data_sector_start)) |
904 |
|
|
{ |
905 |
|
|
|
906 |
|
|
/* We have exceeded the root directory. */ |
907 |
|
|
|
908 |
|
|
/* Send error message back to caller. */ |
909 |
|
1 |
return(FX_FILE_CORRUPT); |
910 |
|
|
} |
911 |
|
|
} |
912 |
|
|
|
913 |
|
|
/* Read the next logical sector. */ |
914 |
|
17 |
status = _fx_utility_logical_sector_read(media_ptr, (ULONG64) logical_sector, |
915 |
|
17 |
media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR); |
916 |
|
|
|
917 |
|
|
/* Determine if an error occurred. */ |
918 |
✓✓ |
17 |
if (status != FX_SUCCESS) |
919 |
|
|
{ |
920 |
|
|
|
921 |
|
|
/* Return the error status. */ |
922 |
|
1 |
return(status); |
923 |
|
|
} |
924 |
|
|
|
925 |
|
|
/* Move to the next sector buffer. */ |
926 |
|
16 |
sector_base_ptr = media_ptr -> fx_media_memory_buffer; |
927 |
|
|
|
928 |
|
|
/* Setup new buffer pointers. */ |
929 |
|
16 |
byte_offset = 0; |
930 |
|
16 |
work_ptr = sector_base_ptr; |
931 |
|
|
|
932 |
|
|
#ifdef FX_ENABLE_FAULT_TOLERANT |
933 |
|
|
/* Initialize data for fault tolerant. */ |
934 |
|
|
changed_ptr = work_ptr; |
935 |
|
|
changed_size = 0; |
936 |
|
|
changed_offset = 0; |
937 |
|
|
#endif /* FX_ENABLE_FAULT_TOLERANT */ |
938 |
|
|
} |
939 |
|
|
} |
940 |
|
|
} |
941 |
|
|
} |
942 |
|
|
|
943 |
|
|
/* This is an 8.3 name. First clear the directory name. */ |
944 |
✓✓ |
1729920 |
for (j = 0; j < FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE; j++) |
945 |
|
|
{ |
946 |
|
1585760 |
work_ptr[j] = ' '; |
947 |
|
|
} |
948 |
|
|
|
949 |
|
|
/* Copy leading dots in case of first two entries of a directory. */ |
950 |
✓✓ |
203432 |
for (i = 0; (UCHAR)entry_ptr -> fx_dir_entry_name[i] == '.'; i++) |
951 |
|
|
{ |
952 |
|
59272 |
work_ptr[i] = '.'; |
953 |
|
|
} |
954 |
|
|
|
955 |
|
|
/* Determine if there are more characters to copy. */ |
956 |
✓✓ |
144160 |
if ((UCHAR)entry_ptr -> fx_dir_entry_name[i] != 0) |
957 |
|
|
{ |
958 |
|
|
|
959 |
|
|
/* Copy directory name. */ |
960 |
✓✓ |
692275 |
for (i = 0, j = 0; j < FX_DIR_NAME_SIZE; i++, j++) |
961 |
|
|
{ |
962 |
|
|
|
963 |
|
|
/* Check for end of copy conditions. */ |
964 |
✓✓ |
692268 |
if ((UCHAR)entry_ptr -> fx_dir_entry_name[i] == '.') |
965 |
|
|
{ |
966 |
|
82229 |
break; |
967 |
|
|
} |
968 |
✓✓ |
610039 |
if ((UCHAR)entry_ptr -> fx_dir_entry_name[i] == 0) |
969 |
|
|
{ |
970 |
|
22409 |
break; |
971 |
|
|
} |
972 |
|
|
|
973 |
|
|
/* Pickup shortname character. */ |
974 |
|
587630 |
alpha = entry_ptr -> fx_dir_entry_name[i]; |
975 |
|
|
|
976 |
|
|
/* Determine if character is lower case. */ |
977 |
✓✓✓✓
|
587630 |
if ((alpha >= 'a') && (alpha <= 'z')) |
978 |
|
|
{ |
979 |
|
|
|
980 |
|
|
/* Store the character - converted to upper case. */ |
981 |
|
10 |
alpha = (CHAR)(alpha - ((CHAR)0x20)); |
982 |
|
|
} |
983 |
|
|
|
984 |
|
|
/* Copy a name character. */ |
985 |
|
587630 |
work_ptr[j] = (UCHAR)alpha; |
986 |
|
|
} |
987 |
|
|
} |
988 |
|
|
|
989 |
|
|
/* Determine if there are more characters in the name. */ |
990 |
✓✓ |
144160 |
if ((UCHAR)entry_ptr -> fx_dir_entry_name[i] != 0) |
991 |
|
|
{ |
992 |
|
|
|
993 |
|
|
/* Loop to copy the remainder of the name. */ |
994 |
✓✓ |
328922 |
for (i++, j = FX_DIR_NAME_SIZE; j < FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE; i++, j++) |
995 |
|
|
{ |
996 |
|
|
|
997 |
|
|
/* Check for end of copy conditions. */ |
998 |
✓✓ |
246693 |
if ((UCHAR)entry_ptr -> fx_dir_entry_name[i] == 0) |
999 |
|
|
{ |
1000 |
|
2 |
break; |
1001 |
|
|
} |
1002 |
|
|
|
1003 |
|
|
/* Pickup shortname character. */ |
1004 |
|
246691 |
alpha = entry_ptr -> fx_dir_entry_name[i]; |
1005 |
|
|
|
1006 |
|
|
/* Determine if character is lower case. */ |
1007 |
✓✓✓✓
|
246691 |
if ((alpha >= 'a') && (alpha <= 'z')) |
1008 |
|
|
{ |
1009 |
|
|
|
1010 |
|
|
/* Store the character - converted to upper case. */ |
1011 |
|
3 |
alpha = (CHAR)(alpha - ((CHAR)0x20)); |
1012 |
|
|
} |
1013 |
|
|
|
1014 |
|
|
/* Copy a name character. */ |
1015 |
|
246691 |
work_ptr[j] = (UCHAR)alpha; |
1016 |
|
|
} |
1017 |
|
|
} |
1018 |
|
|
|
1019 |
|
|
/* Move to the next entry. */ |
1020 |
|
144160 |
work_ptr += (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE); |
1021 |
|
|
} |
1022 |
|
|
|
1023 |
|
|
/* Write out the 8.3 part of the name. */ |
1024 |
|
|
|
1025 |
|
|
/* Copy the attribute into the destination. */ |
1026 |
|
145359 |
*work_ptr++ = entry_ptr -> fx_dir_entry_attributes; |
1027 |
|
|
|
1028 |
|
|
/* Copy the reserved byte. */ |
1029 |
|
145359 |
*work_ptr++ = entry_ptr -> fx_dir_entry_reserved; |
1030 |
|
|
|
1031 |
|
|
/* Copy the created time in milliseconds. */ |
1032 |
|
145359 |
*work_ptr++ = entry_ptr -> fx_dir_entry_created_time_ms; |
1033 |
|
|
|
1034 |
|
|
/* Copy the created time. */ |
1035 |
|
145359 |
_fx_utility_16_unsigned_write(work_ptr, entry_ptr -> fx_dir_entry_created_time); |
1036 |
|
145359 |
work_ptr = work_ptr + 2; /* Always 2 bytes */ |
1037 |
|
|
|
1038 |
|
|
/* Copy the created date. */ |
1039 |
|
145359 |
_fx_utility_16_unsigned_write(work_ptr, entry_ptr -> fx_dir_entry_created_date); |
1040 |
|
145359 |
work_ptr = work_ptr + 2; /* Always 2 bytes */ |
1041 |
|
|
|
1042 |
|
|
/* Copy the last accessed date. */ |
1043 |
|
145359 |
_fx_utility_16_unsigned_write(work_ptr, entry_ptr -> fx_dir_entry_last_accessed_date); |
1044 |
|
145359 |
work_ptr = work_ptr + 2; /* Always 2 bytes */ |
1045 |
|
|
|
1046 |
|
|
/* Determine if a FAT32 entry is present. */ |
1047 |
✓✓ |
145359 |
if (media_ptr -> fx_media_32_bit_FAT) |
1048 |
|
|
{ |
1049 |
|
|
|
1050 |
|
|
/* Yes, FAT32 is present, store upper half of cluster. */ |
1051 |
|
58334 |
temp = (entry_ptr -> fx_dir_entry_cluster >> 16); |
1052 |
|
58334 |
_fx_utility_16_unsigned_write(work_ptr, temp); |
1053 |
|
|
} |
1054 |
|
|
else |
1055 |
|
|
{ |
1056 |
|
|
|
1057 |
|
|
/* No, FAT16 or FAT12 is present, just write a 0 for |
1058 |
|
|
the upper half of the cluster. */ |
1059 |
|
87025 |
_fx_utility_16_unsigned_write(work_ptr, 0); |
1060 |
|
|
} |
1061 |
|
|
|
1062 |
|
|
/* Advance the entry pointer. */ |
1063 |
|
145359 |
work_ptr = work_ptr + 2; /* Always 2 bytes */ |
1064 |
|
|
|
1065 |
|
|
/* Copy the time into the destination. */ |
1066 |
|
145359 |
_fx_utility_16_unsigned_write(work_ptr, entry_ptr -> fx_dir_entry_time); |
1067 |
|
145359 |
work_ptr = work_ptr + 2; /* Always 2 bytes */ |
1068 |
|
|
|
1069 |
|
|
/* Copy the date into the destination. */ |
1070 |
|
145359 |
_fx_utility_16_unsigned_write(work_ptr, entry_ptr -> fx_dir_entry_date); |
1071 |
|
145359 |
work_ptr = work_ptr + 2; /* Always 2 bytes */ |
1072 |
|
|
|
1073 |
|
|
/* Copy the starting cluster into the destination. */ |
1074 |
|
145359 |
_fx_utility_16_unsigned_write(work_ptr, (UINT)entry_ptr -> fx_dir_entry_cluster); |
1075 |
|
145359 |
work_ptr = work_ptr + 2; /* Always 2 bytes */ |
1076 |
|
|
|
1077 |
|
|
/* Copy the file size into the destination. */ |
1078 |
|
145359 |
_fx_utility_32_unsigned_write(work_ptr, (ULONG)entry_ptr -> fx_dir_entry_file_size); |
1079 |
|
|
|
1080 |
|
|
#ifdef FX_ENABLE_FAULT_TOLERANT |
1081 |
|
|
/* Update changed_size. */ |
1082 |
|
|
changed_size += FX_DIR_ENTRY_SIZE; |
1083 |
|
|
|
1084 |
|
|
if (media_ptr -> fx_media_fault_tolerant_enabled && |
1085 |
|
|
(media_ptr -> fx_media_fault_tolerant_state & FX_FAULT_TOLERANT_STATE_STARTED)) |
1086 |
|
|
{ |
1087 |
|
|
|
1088 |
|
|
/* Redirect this request to log file. */ |
1089 |
|
|
status = _fx_fault_tolerant_add_dir_log(media_ptr, (ULONG64) logical_sector, changed_offset, changed_ptr, changed_size); |
1090 |
|
|
} |
1091 |
|
|
else |
1092 |
|
|
{ |
1093 |
|
|
#endif /* FX_ENABLE_FAULT_TOLERANT */ |
1094 |
|
|
|
1095 |
|
|
/* Write the directory sector to the media. */ |
1096 |
|
145359 |
status = _fx_utility_logical_sector_write(media_ptr, (ULONG64) logical_sector, |
1097 |
|
|
sector_base_ptr, ((ULONG) 1), FX_DIRECTORY_SECTOR); |
1098 |
|
|
#ifdef FX_ENABLE_FAULT_TOLERANT |
1099 |
|
|
} |
1100 |
|
|
#endif /* FX_ENABLE_FAULT_TOLERANT */ |
1101 |
|
|
|
1102 |
|
|
/* Determine if an error occurred. */ |
1103 |
✓✓ |
145359 |
if (status != FX_SUCCESS) |
1104 |
|
|
{ |
1105 |
|
|
|
1106 |
|
|
/* Return the error status. */ |
1107 |
|
4 |
return(status); |
1108 |
|
|
} |
1109 |
|
|
|
1110 |
|
|
#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE |
1111 |
|
|
|
1112 |
|
|
/* Determine if there is a previously found directory entry in the directory |
1113 |
|
|
search cache. */ |
1114 |
✓✓ |
145355 |
if (media_ptr -> fx_media_last_found_name[0]) |
1115 |
|
|
{ |
1116 |
|
|
|
1117 |
|
|
/* Determine if the cached search directory entry matches the directory entry being |
1118 |
|
|
written. */ |
1119 |
✓✓ |
27092 |
if ((entry_ptr -> fx_dir_entry_log_sector == media_ptr -> fx_media_last_found_entry.fx_dir_entry_log_sector) && |
1120 |
✓✓ |
27075 |
(entry_ptr -> fx_dir_entry_byte_offset == media_ptr -> fx_media_last_found_entry.fx_dir_entry_byte_offset)) |
1121 |
|
|
{ |
1122 |
|
|
|
1123 |
|
|
/* Yes, this entry is the same as the one currently in the directory search cache. |
1124 |
|
|
Update various fields in the directory search cache with the information being |
1125 |
|
|
written now. */ |
1126 |
|
7150 |
media_ptr -> fx_media_last_found_entry.fx_dir_entry_cluster = entry_ptr -> fx_dir_entry_cluster; |
1127 |
|
7150 |
media_ptr -> fx_media_last_found_entry.fx_dir_entry_file_size = entry_ptr -> fx_dir_entry_file_size; |
1128 |
|
7150 |
media_ptr -> fx_media_last_found_entry.fx_dir_entry_attributes = entry_ptr -> fx_dir_entry_attributes; |
1129 |
|
7150 |
media_ptr -> fx_media_last_found_entry.fx_dir_entry_time = entry_ptr -> fx_dir_entry_time; |
1130 |
|
7150 |
media_ptr -> fx_media_last_found_entry.fx_dir_entry_date = entry_ptr -> fx_dir_entry_date; |
1131 |
|
7150 |
media_ptr -> fx_media_last_found_entry.fx_dir_entry_reserved = entry_ptr -> fx_dir_entry_reserved; |
1132 |
|
7150 |
media_ptr -> fx_media_last_found_entry.fx_dir_entry_created_time_ms = entry_ptr -> fx_dir_entry_created_time_ms; |
1133 |
|
7150 |
media_ptr -> fx_media_last_found_entry.fx_dir_entry_created_time = entry_ptr -> fx_dir_entry_created_time; |
1134 |
|
7150 |
media_ptr -> fx_media_last_found_entry.fx_dir_entry_created_date = entry_ptr -> fx_dir_entry_created_date; |
1135 |
|
|
} |
1136 |
|
|
} |
1137 |
|
|
#endif |
1138 |
|
|
|
1139 |
|
|
/* Return success to the caller. */ |
1140 |
|
145355 |
return(FX_SUCCESS); |
1141 |
|
|
} |
1142 |
|
|
|