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