1 /* $Id: rw.c,v 1.3 2000/02/22 02:02:08 ekohl Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: services/fs/vfat/rw.c
6 * PURPOSE: VFAT Filesystem
7 * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
11 /* INCLUDES *****************************************************************/
13 #include <ddk/ntddk.h>
15 #include <internal/string.h>
16 #include <ddk/cctypes.h>
19 #include <internal/debug.h>
23 /* FUNCTIONS ****************************************************************/
25 NTSTATUS
FsdReadFile(PDEVICE_EXTENSION DeviceExt
, PFILE_OBJECT FileObject
,
26 PVOID Buffer
, ULONG Length
, ULONG ReadOffset
,
29 * FUNCTION: Reads data from a file
40 assert(DeviceExt
!= NULL
);
41 assert(DeviceExt
->BytesPerCluster
!= 0);
42 assert(FileObject
!= NULL
);
43 assert(FileObject
->FsContext
!= NULL
);
45 DPRINT("FsdReadFile(DeviceExt %x, FileObject %x, Buffer %x, "
46 "Length %d, ReadOffset %d)\n",DeviceExt
,FileObject
,Buffer
,
49 Fcb
= ((PVFATCCB
)(FileObject
->FsContext2
))->pFcb
;
50 if (DeviceExt
->FatType
== FAT32
)
51 CurrentCluster
= Fcb
->entry
.FirstCluster
52 +Fcb
->entry
.FirstClusterHigh
*65536;
54 CurrentCluster
= Fcb
->entry
.FirstCluster
;
55 FirstCluster
=CurrentCluster
;
56 DPRINT("DeviceExt->BytesPerCluster %x\n",DeviceExt
->BytesPerCluster
);
58 if (Fcb
->entry
.Attrib
& FILE_ATTRIBUTE_DIRECTORY
)
60 return(STATUS_FILE_IS_A_DIRECTORY
);
63 if (ReadOffset
>= Fcb
->entry
.FileSize
64 && !(Fcb
->entry
.Attrib
& FILE_ATTRIBUTE_DIRECTORY
))
66 return(STATUS_END_OF_FILE
);
68 if ((ReadOffset
+ Length
) > Fcb
->entry
.FileSize
69 && !(Fcb
->entry
.Attrib
& FILE_ATTRIBUTE_DIRECTORY
))
71 Length
= Fcb
->entry
.FileSize
- ReadOffset
;
74 /* FIXME: optimize by remembering the last cluster read and using if possible */
75 Temp
= ExAllocatePool(NonPagedPool
,DeviceExt
->BytesPerCluster
);
76 if(!Temp
) return STATUS_UNSUCCESSFUL
;
78 { //root of FAT16 or FAT12
79 CurrentCluster
=DeviceExt
->rootStart
+ReadOffset
80 /(DeviceExt
->BytesPerCluster
)*DeviceExt
->Boot
->SectorsPerCluster
;
83 for (FileOffset
=0; FileOffset
< ReadOffset
/ DeviceExt
->BytesPerCluster
86 CurrentCluster
= GetNextCluster(DeviceExt
,CurrentCluster
);
89 if ((ReadOffset
% DeviceExt
->BytesPerCluster
)!=0)
93 VFATReadSectors(DeviceExt
->StorageDevice
,CurrentCluster
94 ,DeviceExt
->Boot
->SectorsPerCluster
,Temp
);
95 CurrentCluster
+= DeviceExt
->Boot
->SectorsPerCluster
;
99 VFATLoadCluster(DeviceExt
,Temp
,CurrentCluster
);
100 CurrentCluster
= GetNextCluster(DeviceExt
, CurrentCluster
);
102 TempLength
= min(Length
,DeviceExt
->BytesPerCluster
-
103 (ReadOffset
% DeviceExt
->BytesPerCluster
));
105 memcpy(Buffer
, Temp
+ ReadOffset
% DeviceExt
->BytesPerCluster
,
108 (*LengthRead
) = (*LengthRead
) + TempLength
;
109 Length
= Length
- TempLength
;
110 Buffer
= Buffer
+ TempLength
;
113 while (Length
>= DeviceExt
->BytesPerCluster
)
117 VFATReadSectors(DeviceExt
->StorageDevice
,CurrentCluster
118 ,DeviceExt
->Boot
->SectorsPerCluster
,Buffer
);
119 CurrentCluster
+= DeviceExt
->Boot
->SectorsPerCluster
;
123 VFATLoadCluster(DeviceExt
,Buffer
,CurrentCluster
);
124 CurrentCluster
= GetNextCluster(DeviceExt
, CurrentCluster
);
126 if (CurrentCluster
== 0xffffffff)
129 return(STATUS_SUCCESS
);
132 (*LengthRead
) = (*LengthRead
) + DeviceExt
->BytesPerCluster
;
133 Buffer
= Buffer
+ DeviceExt
->BytesPerCluster
;
134 Length
= Length
- DeviceExt
->BytesPerCluster
;
139 (*LengthRead
) = (*LengthRead
) + Length
;
142 VFATReadSectors(DeviceExt
->StorageDevice
,CurrentCluster
143 ,DeviceExt
->Boot
->SectorsPerCluster
,Temp
);
144 CurrentCluster
+= DeviceExt
->Boot
->SectorsPerCluster
;
148 VFATLoadCluster(DeviceExt
,Temp
,CurrentCluster
);
149 CurrentCluster
= GetNextCluster(DeviceExt
, CurrentCluster
);
151 memcpy(Buffer
, Temp
, Length
);
154 return(STATUS_SUCCESS
);
157 NTSTATUS
FsdWriteFile(PDEVICE_EXTENSION DeviceExt
, PFILE_OBJECT FileObject
,
158 PVOID Buffer
, ULONG Length
, ULONG WriteOffset
)
160 * FUNCTION: Writes data to file
163 ULONG CurrentCluster
;
169 ULONG TempLength
,Length2
=Length
;
171 DPRINT1("FsdWriteFile(FileObject %x, Buffer %x, Length %x, "
172 "WriteOffset %x\n", FileObject
, Buffer
, Length
, WriteOffset
);
174 /* Locate the first cluster of the file */
176 pCcb
=(PVFATCCB
)(FileObject
->FsContext2
);
180 if (DeviceExt
->FatType
== FAT32
)
183 Fcb
->entry
.FirstCluster
+Fcb
->entry
.FirstClusterHigh
*65536;
187 CurrentCluster
= Fcb
->entry
.FirstCluster
;
189 FirstCluster
=CurrentCluster
;
191 /* Allocate a buffer to hold 1 cluster of data */
192 Temp
= ExAllocatePool(NonPagedPool
, DeviceExt
->BytesPerCluster
);
195 /* Find the cluster according to the offset in the file */
196 if (CurrentCluster
==1)
198 CurrentCluster
=DeviceExt
->rootStart
+WriteOffset
199 / DeviceExt
->BytesPerCluster
*DeviceExt
->Boot
->SectorsPerCluster
;
203 if (CurrentCluster
==0)
208 CurrentCluster
=GetNextWriteCluster(DeviceExt
,0);
209 if (DeviceExt
->FatType
== FAT32
)
211 Fcb
->entry
.FirstClusterHigh
= CurrentCluster
>>16;
212 Fcb
->entry
.FirstCluster
= CurrentCluster
;
215 Fcb
->entry
.FirstCluster
=CurrentCluster
;
220 FileOffset
< WriteOffset
/ DeviceExt
->BytesPerCluster
;
223 CurrentCluster
= GetNextCluster(DeviceExt
,CurrentCluster
);
230 * If the offset in the cluster doesn't fall on the cluster boundary
231 * then we have to write only from the specified offset
234 if ((WriteOffset
% DeviceExt
->BytesPerCluster
)!=0)
237 TempLength
= min(Length
,DeviceExt
->BytesPerCluster
-
238 (WriteOffset
% DeviceExt
->BytesPerCluster
));
239 /* Read in the existing cluster data */
242 VFATReadSectors(DeviceExt
->StorageDevice
,
244 DeviceExt
->Boot
->SectorsPerCluster
,
249 VFATLoadCluster(DeviceExt
,Temp
,CurrentCluster
);
252 /* Overwrite the last parts of the data as necessary */
253 memcpy(Temp
+ (WriteOffset
% DeviceExt
->BytesPerCluster
),
257 /* Write the cluster back */
260 VFATWriteSectors(DeviceExt
->StorageDevice
,
262 DeviceExt
->Boot
->SectorsPerCluster
,
264 CurrentCluster
+= DeviceExt
->Boot
->SectorsPerCluster
;
268 VFATWriteCluster(DeviceExt
,Temp
,CurrentCluster
);
269 CurrentCluster
= GetNextCluster(DeviceExt
, CurrentCluster
);
271 Length2
-= TempLength
;
272 Buffer
= Buffer
+ TempLength
;
276 /* Write the buffer in chunks of 1 cluster */
278 while (Length2
>= DeviceExt
->BytesPerCluster
)
281 if (CurrentCluster
== 0)
284 return(STATUS_UNSUCCESSFUL
);
288 VFATWriteSectors(DeviceExt
->StorageDevice
,
290 DeviceExt
->Boot
->SectorsPerCluster
,
292 CurrentCluster
+= DeviceExt
->Boot
->SectorsPerCluster
;
296 VFATWriteCluster(DeviceExt
,Buffer
,CurrentCluster
);
297 CurrentCluster
= GetNextCluster(DeviceExt
, CurrentCluster
);
299 Buffer
= Buffer
+ DeviceExt
->BytesPerCluster
;
300 Length2
-= DeviceExt
->BytesPerCluster
;
304 /* Write the remainder */
309 if (CurrentCluster
== 0)
312 return(STATUS_UNSUCCESSFUL
);
315 /* Read in the existing cluster data */
318 VFATReadSectors(DeviceExt
->StorageDevice
,
320 DeviceExt
->Boot
->SectorsPerCluster
,
325 VFATLoadCluster(DeviceExt
,Temp
,CurrentCluster
);
327 memcpy(Temp
, Buffer
, Length2
);
331 VFATWriteSectors(DeviceExt
->StorageDevice
,
333 DeviceExt
->Boot
->SectorsPerCluster
,
338 VFATWriteCluster(DeviceExt
,Temp
,CurrentCluster
);
345 * FIXME : set last write time and date
347 if (Fcb
->entry
.FileSize
< WriteOffset
+Length
348 && !(Fcb
->entry
.Attrib
& FILE_ATTRIBUTE_DIRECTORY
))
350 Fcb
->entry
.FileSize
= WriteOffset
+Length
;
352 * update entry in directory
354 updEntry(DeviceExt
,FileObject
);
358 return (STATUS_SUCCESS
);
361 NTSTATUS
FsdWrite(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
363 * FUNCTION: Write to a file
369 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
370 PFILE_OBJECT FileObject
= Stack
->FileObject
;
371 PDEVICE_EXTENSION DeviceExt
= DeviceObject
->DeviceExtension
;
374 DPRINT("FsdWrite(DeviceObject %x Irp %x)\n",DeviceObject
,Irp
);
376 Length
= Stack
->Parameters
.Write
.Length
;
377 Buffer
= MmGetSystemAddressForMdl(Irp
->MdlAddress
);
378 Offset
= Stack
->Parameters
.Write
.ByteOffset
.u
.LowPart
;
380 Status
= FsdWriteFile(DeviceExt
,FileObject
,Buffer
,Length
,Offset
);
382 Irp
->IoStatus
.Status
= Status
;
383 Irp
->IoStatus
.Information
= Length
;
384 IoCompleteRequest(Irp
,IO_NO_INCREMENT
);
389 NTSTATUS
FsdRead(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
391 * FUNCTION: Read from a file
397 PIO_STACK_LOCATION Stack
;
398 PFILE_OBJECT FileObject
;
399 PDEVICE_EXTENSION DeviceExt
;
403 DPRINT("FsdRead(DeviceObject %x, Irp %x)\n",DeviceObject
,Irp
);
405 /* Precondition / Initialization */
407 Stack
= IoGetCurrentIrpStackLocation(Irp
);
408 assert(Stack
!= NULL
);
409 FileObject
= Stack
->FileObject
;
410 assert(FileObject
!= NULL
);
411 DeviceExt
= DeviceObject
->DeviceExtension
;
412 assert(DeviceExt
!= NULL
);
414 Length
= Stack
->Parameters
.Read
.Length
;
415 Buffer
= MmGetSystemAddressForMdl(Irp
->MdlAddress
);
416 Offset
= Stack
->Parameters
.Read
.ByteOffset
.u
.LowPart
;
418 Status
= FsdReadFile(DeviceExt
,FileObject
,Buffer
,Length
,Offset
,
421 Irp
->IoStatus
.Status
= Status
;
422 Irp
->IoStatus
.Information
= LengthRead
;
423 IoCompleteRequest(Irp
,IO_NO_INCREMENT
);