]> git.proxmox.com Git - mirror_edk2.git/blame - FatPkg/EnhancedFatDxe/ReadWrite.c
FatPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / FatPkg / EnhancedFatDxe / ReadWrite.c
CommitLineData
cae7420b
DB
1/** @file\r
2 Functions that perform file read/write.\r
b9ec9330 3\r
64b25f5d 4Copyright (c) 2005 - 2017, Intel Corporation. All rights reserved.<BR>\r
eb6cb4ce 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
b9ec9330
QH
6\r
7\r
cae7420b 8**/\r
b9ec9330 9\r
cae7420b 10#include "Fat.h"\r
b9ec9330 11\r
cae7420b 12/**\r
b9ec9330 13\r
cae7420b 14 Get the file's position of the file.\r
b9ec9330 15\r
b9ec9330 16\r
cae7420b
DB
17 @param FHand - The handle of file.\r
18 @param Position - The file's position of the file.\r
b9ec9330 19\r
cae7420b
DB
20 @retval EFI_SUCCESS - Get the info successfully.\r
21 @retval EFI_DEVICE_ERROR - Can not find the OFile for the file.\r
22 @retval EFI_UNSUPPORTED - The open file is not a file.\r
b9ec9330 23\r
cae7420b 24**/\r
b9ec9330
QH
25EFI_STATUS\r
26EFIAPI\r
27FatGetPosition (\r
dba03ba1 28 IN EFI_FILE_PROTOCOL *FHand,\r
b9ec9330
QH
29 OUT UINT64 *Position\r
30 )\r
b9ec9330
QH
31{\r
32 FAT_IFILE *IFile;\r
33 FAT_OFILE *OFile;\r
34\r
35 IFile = IFILE_FROM_FHAND (FHand);\r
36 OFile = IFile->OFile;\r
37\r
38 if (OFile->Error == EFI_NOT_FOUND) {\r
39 return EFI_DEVICE_ERROR;\r
40 }\r
41\r
42 if (OFile->ODir != NULL) {\r
43 return EFI_UNSUPPORTED;\r
44 }\r
45\r
46 *Position = IFile->Position;\r
47 return EFI_SUCCESS;\r
48}\r
49\r
cae7420b
DB
50/**\r
51\r
52 Set the file's position of the file.\r
53\r
54 @param FHand - The handle of file.\r
55 @param Position - The file's position of the file.\r
56\r
57 @retval EFI_SUCCESS - Set the info successfully.\r
58 @retval EFI_DEVICE_ERROR - Can not find the OFile for the file.\r
59 @retval EFI_UNSUPPORTED - Set a directory with a not-zero position.\r
60\r
61**/\r
b9ec9330
QH
62EFI_STATUS\r
63EFIAPI\r
64FatSetPosition (\r
dba03ba1
QH
65 IN EFI_FILE_PROTOCOL *FHand,\r
66 IN UINT64 Position\r
b9ec9330 67 )\r
b9ec9330
QH
68{\r
69 FAT_IFILE *IFile;\r
70 FAT_OFILE *OFile;\r
71\r
72 IFile = IFILE_FROM_FHAND (FHand);\r
73 OFile = IFile->OFile;\r
74\r
75 if (OFile->Error == EFI_NOT_FOUND) {\r
76 return EFI_DEVICE_ERROR;\r
77 }\r
149d6335
RN
78\r
79 FatWaitNonblockingTask (IFile);\r
80\r
b9ec9330
QH
81 //\r
82 // If this is a directory, we can only set back to position 0\r
83 //\r
84 if (OFile->ODir != NULL) {\r
85 if (Position != 0) {\r
86 //\r
87 // Reset current directory cursor;\r
88 //\r
89 return EFI_UNSUPPORTED;\r
90 }\r
91\r
92 FatResetODirCursor (OFile);\r
93 }\r
94 //\r
95 // Set the position\r
96 //\r
c4ba493e 97 if (Position == (UINT64)-1) {\r
b9ec9330
QH
98 Position = OFile->FileSize;\r
99 }\r
100 //\r
101 // Set the position\r
102 //\r
103 IFile->Position = Position;\r
104 return EFI_SUCCESS;\r
105}\r
106\r
cae7420b
DB
107/**\r
108\r
109 Get the file info from the open file of the IFile into Buffer.\r
110\r
111 @param IFile - The instance of the open file.\r
112 @param BufferSize - Size of Buffer.\r
113 @param Buffer - Buffer containing read data.\r
114\r
115 @retval EFI_SUCCESS - Get the file info successfully.\r
116 @retval other - An error occurred when operation the disk.\r
117\r
118**/\r
b9ec9330
QH
119EFI_STATUS\r
120FatIFileReadDir (\r
121 IN FAT_IFILE *IFile,\r
122 IN OUT UINTN *BufferSize,\r
123 OUT VOID *Buffer\r
124 )\r
b9ec9330
QH
125{\r
126 EFI_STATUS Status;\r
127 FAT_OFILE *OFile;\r
128 FAT_ODIR *ODir;\r
129 FAT_DIRENT *DirEnt;\r
130 UINT32 CurrentPos;\r
131\r
132 OFile = IFile->OFile;\r
133 ODir = OFile->ODir;\r
134 CurrentPos = ((UINT32) IFile->Position) / sizeof (FAT_DIRECTORY_ENTRY);\r
135\r
136 //\r
137 // We need to relocate the directory\r
138 //\r
139 if (CurrentPos < ODir->CurrentPos) {\r
140 //\r
141 // The directory cursor has been modified by another IFile, we reset the cursor\r
142 //\r
143 FatResetODirCursor (OFile);\r
144 }\r
145 //\r
146 // We seek the next directory entry's position\r
147 //\r
148 do {\r
149 Status = FatGetNextDirEnt (OFile, &DirEnt);\r
150 if (EFI_ERROR (Status) || DirEnt == NULL) {\r
151 //\r
152 // Something error occurred or reach the end of directory,\r
153 // return 0 buffersize\r
154 //\r
155 *BufferSize = 0;\r
156 goto Done;\r
157 }\r
158 } while (ODir->CurrentPos <= CurrentPos);\r
159 Status = FatGetDirEntInfo (OFile->Volume, DirEnt, BufferSize, Buffer);\r
160\r
161Done:\r
162 //\r
163 // Update IFile's Position\r
164 //\r
165 if (!EFI_ERROR (Status)) {\r
166 //\r
167 // Update IFile->Position, if everything is all right\r
168 //\r
169 CurrentPos = ODir->CurrentPos;\r
64b25f5d 170 IFile->Position = CurrentPos * sizeof (FAT_DIRECTORY_ENTRY);\r
b9ec9330
QH
171 }\r
172\r
173 return Status;\r
174}\r
175\r
cae7420b
DB
176/**\r
177\r
178 Get the file info from the open file of the IFile into Buffer.\r
179\r
180 @param FHand - The file handle to access.\r
181 @param IoMode - Indicate whether the access mode is reading or writing.\r
182 @param BufferSize - Size of Buffer.\r
183 @param Buffer - Buffer containing read data.\r
184 @param Token - A pointer to the token associated with the transaction.\r
185\r
186 @retval EFI_SUCCESS - Get the file info successfully.\r
187 @retval EFI_DEVICE_ERROR - Can not find the OFile for the file.\r
188 @retval EFI_VOLUME_CORRUPTED - The file type of open file is error.\r
189 @retval EFI_WRITE_PROTECTED - The disk is write protect.\r
190 @retval EFI_ACCESS_DENIED - The file is read-only.\r
191 @return other - An error occurred when operating on the disk.\r
192\r
193**/\r
b9ec9330
QH
194EFI_STATUS\r
195FatIFileAccess (\r
dba03ba1 196 IN EFI_FILE_PROTOCOL *FHand,\r
b9ec9330
QH
197 IN IO_MODE IoMode,\r
198 IN OUT UINTN *BufferSize,\r
149d6335
RN
199 IN OUT VOID *Buffer,\r
200 IN EFI_FILE_IO_TOKEN *Token\r
b9ec9330 201 )\r
b9ec9330
QH
202{\r
203 EFI_STATUS Status;\r
204 FAT_IFILE *IFile;\r
205 FAT_OFILE *OFile;\r
206 FAT_VOLUME *Volume;\r
207 UINT64 EndPosition;\r
149d6335 208 FAT_TASK *Task;\r
b9ec9330
QH
209\r
210 IFile = IFILE_FROM_FHAND (FHand);\r
211 OFile = IFile->OFile;\r
212 Volume = OFile->Volume;\r
149d6335 213 Task = NULL;\r
b9ec9330 214\r
55248f85
RN
215 //\r
216 // Write to a directory is unsupported\r
217 //\r
c1680e88 218 if ((OFile->ODir != NULL) && (IoMode == WriteData)) {\r
55248f85
RN
219 return EFI_UNSUPPORTED;\r
220 }\r
221\r
b9ec9330
QH
222 if (OFile->Error == EFI_NOT_FOUND) {\r
223 return EFI_DEVICE_ERROR;\r
224 }\r
225\r
c1680e88 226 if (IoMode == ReadData) {\r
b9ec9330
QH
227 //\r
228 // If position is at EOF, then return device error\r
229 //\r
230 if (IFile->Position > OFile->FileSize) {\r
231 return EFI_DEVICE_ERROR;\r
232 }\r
233 } else {\r
234 //\r
235 // Check if the we can write data\r
236 //\r
237 if (Volume->ReadOnly) {\r
238 return EFI_WRITE_PROTECTED;\r
239 }\r
240\r
241 if (IFile->ReadOnly) {\r
242 return EFI_ACCESS_DENIED;\r
243 }\r
244 }\r
245\r
149d6335
RN
246 if (Token == NULL) {\r
247 FatWaitNonblockingTask (IFile);\r
248 } else {\r
249 //\r
250 // Caller shouldn't call the non-blocking interfaces if the low layer doesn't support DiskIo2.\r
251 // But if it calls, the below check can avoid crash.\r
252 //\r
253 if (FHand->Revision < EFI_FILE_PROTOCOL_REVISION2) {\r
254 return EFI_UNSUPPORTED;\r
255 }\r
256 Task = FatCreateTask (IFile, Token);\r
257 if (Task == NULL) {\r
258 return EFI_OUT_OF_RESOURCES;\r
259 }\r
260 }\r
261\r
b9ec9330
QH
262 FatAcquireLock ();\r
263\r
264 Status = OFile->Error;\r
265 if (!EFI_ERROR (Status)) {\r
266 if (OFile->ODir != NULL) {\r
267 //\r
55248f85 268 // Read a directory is supported\r
b9ec9330 269 //\r
c1680e88 270 ASSERT (IoMode == ReadData);\r
55248f85 271 Status = FatIFileReadDir (IFile, BufferSize, Buffer);\r
b9ec9330
QH
272 OFile = NULL;\r
273 } else {\r
274 //\r
275 // Access a file\r
276 //\r
277 EndPosition = IFile->Position + *BufferSize;\r
278 if (EndPosition > OFile->FileSize) {\r
279 //\r
280 // The position goes beyond the end of file\r
281 //\r
c1680e88 282 if (IoMode == ReadData) {\r
b9ec9330
QH
283 //\r
284 // Adjust the actual size read\r
285 //\r
286 *BufferSize -= (UINTN) EndPosition - OFile->FileSize;\r
287 } else {\r
288 //\r
289 // We expand the file size of OFile\r
290 //\r
291 Status = FatGrowEof (OFile, EndPosition);\r
292 if (EFI_ERROR (Status)) {\r
293 //\r
294 // Must update the file's info into the file's Directory Entry\r
295 // and then flush the dirty cache info into disk.\r
296 //\r
297 *BufferSize = 0;\r
298 FatOFileFlush (OFile);\r
299 OFile = NULL;\r
300 goto Done;\r
301 }\r
302\r
303 FatUpdateDirEntClusterSizeInfo (OFile);\r
304 }\r
305 }\r
306\r
149d6335 307 Status = FatAccessOFile (OFile, IoMode, (UINTN) IFile->Position, BufferSize, Buffer, Task);\r
b9ec9330
QH
308 IFile->Position += *BufferSize;\r
309 }\r
310 }\r
311\r
149d6335
RN
312 if (Token != NULL) {\r
313 if (!EFI_ERROR (Status)) {\r
314 Status = FatQueueTask (IFile, Task);\r
315 } else {\r
316 FatDestroyTask (Task);\r
317 }\r
b9ec9330 318 }\r
149d6335
RN
319\r
320Done:\r
b9ec9330
QH
321 //\r
322 // On EFI_SUCCESS case, not calling FatCleanupVolume():\r
323 // 1) The Cache flush operation is avoided to enhance\r
324 // performance. Caller is responsible to call Flush() when necessary.\r
325 // 2) The volume dirty bit is probably set already, and is expected to be\r
326 // cleaned in subsequent Flush() or other operations.\r
327 // 3) Write operation doesn't affect OFile/IFile structure, so\r
328 // Reference checking is not necessary.\r
329 //\r
149d6335
RN
330 if (EFI_ERROR (Status)) {\r
331 Status = FatCleanupVolume (Volume, OFile, Status, NULL);\r
332 }\r
333\r
b9ec9330
QH
334 FatReleaseLock ();\r
335 return Status;\r
336}\r
337\r
cae7420b
DB
338/**\r
339\r
340 Get the file info.\r
341\r
342 @param FHand - The handle of the file.\r
343 @param BufferSize - Size of Buffer.\r
344 @param Buffer - Buffer containing read data.\r
345\r
346\r
347 @retval EFI_SUCCESS - Get the file info successfully.\r
348 @retval EFI_DEVICE_ERROR - Can not find the OFile for the file.\r
349 @retval EFI_VOLUME_CORRUPTED - The file type of open file is error.\r
350 @return other - An error occurred when operation the disk.\r
351\r
352**/\r
b9ec9330
QH
353EFI_STATUS\r
354EFIAPI\r
355FatRead (\r
dba03ba1
QH
356 IN EFI_FILE_PROTOCOL *FHand,\r
357 IN OUT UINTN *BufferSize,\r
358 OUT VOID *Buffer\r
b9ec9330 359 )\r
cae7420b
DB
360{\r
361 return FatIFileAccess (FHand, ReadData, BufferSize, Buffer, NULL);\r
362}\r
b9ec9330 363\r
cae7420b 364/**\r
b9ec9330
QH
365\r
366 Get the file info.\r
367\r
cae7420b
DB
368 @param FHand - The handle of the file.\r
369 @param Token - A pointer to the token associated with the transaction.\r
b9ec9330 370\r
cae7420b
DB
371 @retval EFI_SUCCESS - Get the file info successfully.\r
372 @retval EFI_DEVICE_ERROR - Can not find the OFile for the file.\r
373 @retval EFI_VOLUME_CORRUPTED - The file type of open file is error.\r
374 @return other - An error occurred when operation the disk.\r
149d6335 375\r
cae7420b 376**/\r
149d6335
RN
377EFI_STATUS\r
378EFIAPI\r
379FatReadEx (\r
380 IN EFI_FILE_PROTOCOL *FHand,\r
381 IN OUT EFI_FILE_IO_TOKEN *Token\r
382 )\r
cae7420b
DB
383{\r
384 return FatIFileAccess (FHand, ReadData, &Token->BufferSize, Token->Buffer, Token);\r
385}\r
149d6335 386\r
cae7420b 387/**\r
149d6335 388\r
cae7420b 389 Write the content of buffer into files.\r
149d6335 390\r
cae7420b
DB
391 @param FHand - The handle of the file.\r
392 @param BufferSize - Size of Buffer.\r
393 @param Buffer - Buffer containing write data.\r
149d6335 394\r
cae7420b
DB
395 @retval EFI_SUCCESS - Set the file info successfully.\r
396 @retval EFI_WRITE_PROTECTED - The disk is write protect.\r
397 @retval EFI_ACCESS_DENIED - The file is read-only.\r
398 @retval EFI_DEVICE_ERROR - The OFile is not valid.\r
399 @retval EFI_UNSUPPORTED - The open file is not a file.\r
400 - The writing file size is larger than 4GB.\r
401 @return other - An error occurred when operation the disk.\r
b9ec9330 402\r
cae7420b 403**/\r
b9ec9330
QH
404EFI_STATUS\r
405EFIAPI\r
406FatWrite (\r
dba03ba1
QH
407 IN EFI_FILE_PROTOCOL *FHand,\r
408 IN OUT UINTN *BufferSize,\r
409 IN VOID *Buffer\r
b9ec9330 410 )\r
cae7420b
DB
411{\r
412 return FatIFileAccess (FHand, WriteData, BufferSize, Buffer, NULL);\r
413}\r
b9ec9330 414\r
cae7420b 415/**\r
b9ec9330 416\r
cae7420b 417 Get the file info.\r
b9ec9330 418\r
cae7420b
DB
419 @param FHand - The handle of the file.\r
420 @param Token - A pointer to the token associated with the transaction.\r
b9ec9330 421\r
cae7420b
DB
422 @retval EFI_SUCCESS - Get the file info successfully.\r
423 @retval EFI_DEVICE_ERROR - Can not find the OFile for the file.\r
424 @retval EFI_VOLUME_CORRUPTED - The file type of open file is error.\r
425 @return other - An error occurred when operation the disk.\r
149d6335 426\r
cae7420b 427**/\r
149d6335
RN
428EFI_STATUS\r
429EFIAPI\r
430FatWriteEx (\r
431 IN EFI_FILE_PROTOCOL *FHand,\r
432 IN OUT EFI_FILE_IO_TOKEN *Token\r
433 )\r
cae7420b
DB
434{\r
435 return FatIFileAccess (FHand, WriteData, &Token->BufferSize, Token->Buffer, Token);\r
436}\r
149d6335 437\r
cae7420b 438/**\r
149d6335 439\r
cae7420b
DB
440 This function reads data from a file or writes data to a file.\r
441 It uses OFile->PosRem to determine how much data can be accessed in one time.\r
149d6335 442\r
cae7420b
DB
443 @param OFile - The open file.\r
444 @param IoMode - Indicate whether the access mode is reading or writing.\r
445 @param Position - The position where data will be accessed.\r
446 @param DataBufferSize - Size of Buffer.\r
447 @param UserBuffer - Buffer containing data.\r
448 @param Task point to task instance.\r
149d6335 449\r
cae7420b
DB
450 @retval EFI_SUCCESS - Access the data successfully.\r
451 @return other - An error occurred when operating on the disk.\r
b9ec9330 452\r
cae7420b 453**/\r
b9ec9330
QH
454EFI_STATUS\r
455FatAccessOFile (\r
456 IN FAT_OFILE *OFile,\r
457 IN IO_MODE IoMode,\r
458 IN UINTN Position,\r
459 IN OUT UINTN *DataBufferSize,\r
149d6335
RN
460 IN OUT UINT8 *UserBuffer,\r
461 IN FAT_TASK *Task\r
b9ec9330 462 )\r
b9ec9330
QH
463{\r
464 FAT_VOLUME *Volume;\r
465 UINTN Len;\r
466 EFI_STATUS Status;\r
467 UINTN BufferSize;\r
468\r
469 BufferSize = *DataBufferSize;\r
470 Volume = OFile->Volume;\r
471 ASSERT_VOLUME_LOCKED (Volume);\r
472\r
473 Status = EFI_SUCCESS;\r
474 while (BufferSize > 0) {\r
475 //\r
476 // Seek the OFile to the file position\r
477 //\r
478 Status = FatOFilePosition (OFile, Position, BufferSize);\r
479 if (EFI_ERROR (Status)) {\r
480 break;\r
481 }\r
482 //\r
483 // Clip length to block run\r
484 //\r
485 Len = BufferSize > OFile->PosRem ? OFile->PosRem : BufferSize;\r
486\r
487 //\r
488 // Write the data\r
489 //\r
149d6335 490 Status = FatDiskIo (Volume, IoMode, OFile->PosDisk, Len, UserBuffer, Task);\r
b9ec9330
QH
491 if (EFI_ERROR (Status)) {\r
492 break;\r
493 }\r
494 //\r
495 // Data was successfully accessed\r
496 //\r
497 Position += Len;\r
498 UserBuffer += Len;\r
499 BufferSize -= Len;\r
c1680e88 500 if (IoMode == WriteData) {\r
b9ec9330
QH
501 OFile->Dirty = TRUE;\r
502 OFile->Archive = TRUE;\r
503 }\r
504 //\r
505 // Make sure no outbound occurred\r
506 //\r
507 ASSERT (Position <= OFile->FileSize);\r
508 }\r
509 //\r
510 // Update the number of bytes accessed\r
511 //\r
512 *DataBufferSize -= BufferSize;\r
513 return Status;\r
514}\r
515\r
cae7420b 516/**\r
b9ec9330
QH
517\r
518 Expand OFile by appending zero bytes at the end of OFile.\r
519\r
cae7420b
DB
520 @param OFile - The open file.\r
521 @param ExpandedSize - The number of zero bytes appended at the end of the file.\r
b9ec9330 522\r
cae7420b
DB
523 @retval EFI_SUCCESS - The file is expanded successfully.\r
524 @return other - An error occurred when expanding file.\r
b9ec9330 525\r
cae7420b
DB
526**/\r
527EFI_STATUS\r
528FatExpandOFile (\r
529 IN FAT_OFILE *OFile,\r
530 IN UINT64 ExpandedSize\r
531 )\r
b9ec9330
QH
532{\r
533 EFI_STATUS Status;\r
534 UINTN WritePos;\r
535\r
536 WritePos = OFile->FileSize;\r
537 Status = FatGrowEof (OFile, ExpandedSize);\r
538 if (!EFI_ERROR (Status)) {\r
539 Status = FatWriteZeroPool (OFile, WritePos);\r
540 }\r
541\r
542 return Status;\r
543}\r
544\r
cae7420b 545/**\r
b9ec9330
QH
546\r
547 Write zero pool from the WritePos to the end of OFile.\r
548\r
cae7420b
DB
549 @param OFile - The open file to write zero pool.\r
550 @param WritePos - The number of zero bytes written.\r
b9ec9330 551\r
cae7420b
DB
552 @retval EFI_SUCCESS - Write the zero pool successfully.\r
553 @retval EFI_OUT_OF_RESOURCES - Not enough memory to perform the operation.\r
554 @return other - An error occurred when writing disk.\r
b9ec9330 555\r
cae7420b
DB
556**/\r
557EFI_STATUS\r
558FatWriteZeroPool (\r
559 IN FAT_OFILE *OFile,\r
560 IN UINTN WritePos\r
561 )\r
b9ec9330
QH
562{\r
563 EFI_STATUS Status;\r
564 VOID *ZeroBuffer;\r
565 UINTN AppendedSize;\r
566 UINTN BufferSize;\r
567 UINTN WriteSize;\r
568\r
569 AppendedSize = OFile->FileSize - WritePos;\r
570 BufferSize = AppendedSize;\r
571 if (AppendedSize > FAT_MAX_ALLOCATE_SIZE) {\r
572 //\r
573 // If the appended size is larger, maybe we can not allocate the whole\r
574 // memory once. So if the growed size is larger than 10M, we just\r
575 // allocate 10M memory (one healthy system should have 10M available\r
576 // memory), and then write the zerobuffer to the file several times.\r
577 //\r
578 BufferSize = FAT_MAX_ALLOCATE_SIZE;\r
579 }\r
580\r
581 ZeroBuffer = AllocateZeroPool (BufferSize);\r
582 if (ZeroBuffer == NULL) {\r
583 return EFI_OUT_OF_RESOURCES;\r
584 }\r
585\r
586 do {\r
587 WriteSize = AppendedSize > BufferSize ? BufferSize : (UINTN) AppendedSize;\r
588 AppendedSize -= WriteSize;\r
c1680e88 589 Status = FatAccessOFile (OFile, WriteData, WritePos, &WriteSize, ZeroBuffer, NULL);\r
b9ec9330
QH
590 if (EFI_ERROR (Status)) {\r
591 break;\r
592 }\r
593\r
594 WritePos += WriteSize;\r
595 } while (AppendedSize > 0);\r
596\r
597 FreePool (ZeroBuffer);\r
598 return Status;\r
599}\r
600\r
cae7420b 601/**\r
b9ec9330
QH
602\r
603 Truncate the OFile to smaller file size.\r
604\r
cae7420b
DB
605 @param OFile - The open file.\r
606 @param TruncatedSize - The new file size.\r
b9ec9330 607\r
cae7420b
DB
608 @retval EFI_SUCCESS - The file is truncated successfully.\r
609 @return other - An error occurred when truncating file.\r
b9ec9330 610\r
cae7420b
DB
611**/\r
612EFI_STATUS\r
613FatTruncateOFile (\r
614 IN FAT_OFILE *OFile,\r
615 IN UINTN TruncatedSize\r
616 )\r
b9ec9330
QH
617{\r
618 OFile->FileSize = TruncatedSize;\r
619 return FatShrinkEof (OFile);\r
620}\r