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