1 /* $Id: rw.c,v 1.1 1999/12/11 21:14:49 dwelch 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 *****************************************************************/
14 #include <internal/string.h>
15 #include <ddk/ntddk.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 /* Locate the first cluster of the file */
173 pCcb
=(PVFATCCB
)(FileObject
->FsContext2
);
177 if (DeviceExt
->FatType
== FAT32
)
178 CurrentCluster
= Fcb
->entry
.FirstCluster
+Fcb
->entry
.FirstClusterHigh
*65536;
180 CurrentCluster
= Fcb
->entry
.FirstCluster
;
181 FirstCluster
=CurrentCluster
;
182 /* Allocate a buffer to hold 1 cluster of data */
184 Temp
= ExAllocatePool(NonPagedPool
,DeviceExt
->BytesPerCluster
);
187 /* Find the cluster according to the offset in the file */
189 if (CurrentCluster
==1)
190 { //root of FAT16 or FAT12
191 CurrentCluster
=DeviceExt
->rootStart
+WriteOffset
192 /DeviceExt
->BytesPerCluster
*DeviceExt
->Boot
->SectorsPerCluster
;
195 if (CurrentCluster
==0)
196 {// file of size 0 : allocate first cluster
197 CurrentCluster
=GetNextWriteCluster(DeviceExt
,0);
198 if (DeviceExt
->FatType
== FAT32
)
200 Fcb
->entry
.FirstClusterHigh
=CurrentCluster
>>16;
201 Fcb
->entry
.FirstCluster
=CurrentCluster
;
204 Fcb
->entry
.FirstCluster
=CurrentCluster
;
207 for (FileOffset
=0; FileOffset
< WriteOffset
/ DeviceExt
->BytesPerCluster
; FileOffset
++)
209 CurrentCluster
= GetNextCluster(DeviceExt
,CurrentCluster
);
214 If the offset in the cluster doesn't fall on the cluster boundary then
215 we have to write only from the specified offset
218 if ((WriteOffset
% DeviceExt
->BytesPerCluster
)!=0)
221 TempLength
= min(Length
,DeviceExt
->BytesPerCluster
-
222 (WriteOffset
% DeviceExt
->BytesPerCluster
));
223 /* Read in the existing cluster data */
225 VFATReadSectors(DeviceExt
->StorageDevice
,CurrentCluster
226 ,DeviceExt
->Boot
->SectorsPerCluster
,Temp
);
228 VFATLoadCluster(DeviceExt
,Temp
,CurrentCluster
);
230 /* Overwrite the last parts of the data as necessary */
231 memcpy(Temp
+ (WriteOffset
% DeviceExt
->BytesPerCluster
), Buffer
,
234 /* Write the cluster back */
237 VFATWriteSectors(DeviceExt
->StorageDevice
,CurrentCluster
238 ,DeviceExt
->Boot
->SectorsPerCluster
,Temp
);
239 CurrentCluster
+= DeviceExt
->Boot
->SectorsPerCluster
;
243 VFATWriteCluster(DeviceExt
,Temp
,CurrentCluster
);
244 CurrentCluster
= GetNextCluster(DeviceExt
, CurrentCluster
);
246 Length2
-= TempLength
;
247 Buffer
= Buffer
+ TempLength
;
251 /* Write the buffer in chunks of 1 cluster */
253 while (Length2
>= DeviceExt
->BytesPerCluster
)
256 if (CurrentCluster
== 0)
259 return(STATUS_UNSUCCESSFUL
);
263 VFATWriteSectors(DeviceExt
->StorageDevice
,CurrentCluster
264 ,DeviceExt
->Boot
->SectorsPerCluster
,Buffer
);
265 CurrentCluster
+= DeviceExt
->Boot
->SectorsPerCluster
;
269 VFATWriteCluster(DeviceExt
,Buffer
,CurrentCluster
);
270 CurrentCluster
= GetNextCluster(DeviceExt
, CurrentCluster
);
272 Buffer
= Buffer
+ DeviceExt
->BytesPerCluster
;
273 Length2
-= DeviceExt
->BytesPerCluster
;
277 /* Write the remainder */
282 if (CurrentCluster
== 0)
285 return(STATUS_UNSUCCESSFUL
);
288 /* Read in the existing cluster data */
290 VFATReadSectors(DeviceExt
->StorageDevice
,CurrentCluster
291 ,DeviceExt
->Boot
->SectorsPerCluster
,Temp
);
293 VFATLoadCluster(DeviceExt
,Temp
,CurrentCluster
);
295 memcpy(Temp
, Buffer
, Length2
);
299 VFATWriteSectors(DeviceExt
->StorageDevice
,CurrentCluster
300 ,DeviceExt
->Boot
->SectorsPerCluster
,Temp
);
303 VFATWriteCluster(DeviceExt
,Temp
,CurrentCluster
);
306 //FIXME : set last write time and date
307 if(Fcb
->entry
.FileSize
<WriteOffset
+Length
308 && !(Fcb
->entry
.Attrib
&FILE_ATTRIBUTE_DIRECTORY
))
310 Fcb
->entry
.FileSize
=WriteOffset
+Length
;
311 // update entry in directory
312 updEntry(DeviceExt
,FileObject
);
315 return(STATUS_SUCCESS
);
318 NTSTATUS
FsdWrite(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
320 * FUNCTION: Write to a file
326 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
327 PFILE_OBJECT FileObject
= Stack
->FileObject
;
328 PDEVICE_EXTENSION DeviceExt
= DeviceObject
->DeviceExtension
;
331 DPRINT("FsdWrite(DeviceObject %x Irp %x)\n",DeviceObject
,Irp
);
333 Length
= Stack
->Parameters
.Write
.Length
;
334 Buffer
= MmGetSystemAddressForMdl(Irp
->MdlAddress
);
335 Offset
= Stack
->Parameters
.Write
.ByteOffset
.u
.LowPart
;
337 Status
= FsdWriteFile(DeviceExt
,FileObject
,Buffer
,Length
,Offset
);
339 Irp
->IoStatus
.Status
= Status
;
340 Irp
->IoStatus
.Information
= Length
;
341 IoCompleteRequest(Irp
,IO_NO_INCREMENT
);
346 NTSTATUS
FsdRead(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
348 * FUNCTION: Read from a file
354 PIO_STACK_LOCATION Stack
;
355 PFILE_OBJECT FileObject
;
356 PDEVICE_EXTENSION DeviceExt
;
360 DPRINT("FsdRead(DeviceObject %x, Irp %x)\n",DeviceObject
,Irp
);
362 /* Precondition / Initialization */
364 Stack
= IoGetCurrentIrpStackLocation(Irp
);
365 assert(Stack
!= NULL
);
366 FileObject
= Stack
->FileObject
;
367 assert(FileObject
!= NULL
);
368 DeviceExt
= DeviceObject
->DeviceExtension
;
369 assert(DeviceExt
!= NULL
);
371 Length
= Stack
->Parameters
.Read
.Length
;
372 Buffer
= MmGetSystemAddressForMdl(Irp
->MdlAddress
);
373 Offset
= Stack
->Parameters
.Read
.ByteOffset
.u
.LowPart
;
375 Status
= FsdReadFile(DeviceExt
,FileObject
,Buffer
,Length
,Offset
,
378 Irp
->IoStatus
.Status
= Status
;
379 Irp
->IoStatus
.Information
= LengthRead
;
380 IoCompleteRequest(Irp
,IO_NO_INCREMENT
);