2 * $Id: fat.c,v 1.8 2000/12/28 03:38:08 dwelch Exp $
4 * COPYRIGHT: See COPYING in the top level directory
5 * PROJECT: ReactOS kernel
6 * FILE: services/fs/vfat/fat.c
7 * PURPOSE: VFAT Filesystem
8 * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
12 /* INCLUDES *****************************************************************/
14 #include <ddk/ntddk.h>
16 #include <ddk/cctypes.h>
23 /* FUNCTIONS ****************************************************************/
26 Fat32GetNextCluster(PDEVICE_EXTENSION DeviceExt
, ULONG CurrentCluster
)
28 * FUNCTION: Retrieve the next FAT32 cluster from the FAT table via a physical
36 Block
= ExAllocatePool(NonPagedPool
,1024);
37 FATsector
=CurrentCluster
/(512/sizeof(ULONG
));
38 FATeis
=CurrentCluster
-(FATsector
*(512/sizeof(ULONG
)));
39 VFATReadSectors(DeviceExt
->StorageDevice
40 ,(ULONG
)(DeviceExt
->FATStart
+FATsector
), 1,(UCHAR
*) Block
);
41 CurrentCluster
= Block
[FATeis
];
42 if (CurrentCluster
>= 0xffffff8 && CurrentCluster
<= 0xfffffff)
43 CurrentCluster
= 0xffffffff;
45 return(CurrentCluster
);
49 Fat16GetNextCluster(PDEVICE_EXTENSION DeviceExt
, ULONG CurrentCluster
)
51 * FUNCTION: Retrieve the next FAT16 cluster from the FAT table from the
56 Block
=(PUSHORT
)DeviceExt
->FAT
;
57 CurrentCluster
= Block
[CurrentCluster
];
58 if (CurrentCluster
>= 0xfff8 && CurrentCluster
<= 0xffff)
59 CurrentCluster
= 0xffffffff;
60 DPRINT("Returning %x\n",CurrentCluster
);
61 return(CurrentCluster
);
65 Fat12GetNextCluster(PDEVICE_EXTENSION DeviceExt
, ULONG CurrentCluster
)
67 * FUNCTION: Retrieve the next FAT12 cluster from the FAT table from the
71 unsigned char* CBlock
;
74 CBlock
= DeviceExt
->FAT
;
75 FATOffset
= (CurrentCluster
* 12)/ 8;//first byte containing value
76 if ((CurrentCluster
% 2) == 0)
78 Entry
= CBlock
[FATOffset
];
79 Entry
|= ((CBlock
[FATOffset
+1] & 0xf)<<8);
83 Entry
= (CBlock
[FATOffset
] >> 4);
84 Entry
|= (CBlock
[FATOffset
+1] << 4);
86 DPRINT("Entry %x\n",Entry
);
87 if (Entry
>= 0xff8 && Entry
<= 0xfff)
89 DPRINT("Returning %x\n",Entry
);
94 GetNextCluster(PDEVICE_EXTENSION DeviceExt
, ULONG CurrentCluster
)
96 * FUNCTION: Retrieve the next cluster depending on the FAT type
101 DPRINT("GetNextCluster(DeviceExt %x, CurrentCluster %x)\n",
102 DeviceExt
,CurrentCluster
);
104 ExAcquireResourceSharedLite(&DeviceExt
->FatResource
, TRUE
);
106 if (DeviceExt
->FatType
== FAT16
)
108 NextCluster
= Fat16GetNextCluster(DeviceExt
, CurrentCluster
);
110 else if (DeviceExt
->FatType
== FAT32
)
112 NextCluster
= Fat32GetNextCluster(DeviceExt
, CurrentCluster
);
116 NextCluster
= Fat12GetNextCluster(DeviceExt
, CurrentCluster
);
119 ExReleaseResourceLite(&DeviceExt
->FatResource
);
125 FAT16FindAvailableCluster(PDEVICE_EXTENSION DeviceExt
)
127 * FUNCTION: Finds the first available cluster in a FAT16 table
132 Block
=(PUSHORT
)DeviceExt
->FAT
;
133 for(i
=2;i
<(DeviceExt
->Boot
->FATSectors
*256) ;i
++)
136 /* Give an error message (out of disk space) if we reach here) */
141 FAT12FindAvailableCluster(PDEVICE_EXTENSION DeviceExt
)
143 * FUNCTION: Finds the first available cluster in a FAT12 table
148 PUCHAR CBlock
=DeviceExt
->FAT
;
150 for(i
=2;i
<((DeviceExt
->Boot
->FATSectors
*512*8)/12) ;i
++)
152 FATOffset
= (i
* 12)/8;
155 Entry
= CBlock
[FATOffset
];
156 Entry
|= ((CBlock
[FATOffset
+ 1] & 0xf)<<8);
160 Entry
= (CBlock
[FATOffset
] >> 4);
161 Entry
|= (CBlock
[FATOffset
+ 1] << 4);
166 /* Give an error message (out of disk space) if we reach here) */
167 DbgPrint("Disk full, %d clusters used\n",i
);
172 FAT32FindAvailableCluster(PDEVICE_EXTENSION DeviceExt
)
174 * FUNCTION: Finds the first available cluster in a FAT32 table
180 Block
= ExAllocatePool(NonPagedPool
,BLOCKSIZE
);
182 ;sector
< ((struct _BootSector32
*)(DeviceExt
->Boot
))->FATSectors32
185 VFATReadSectors(DeviceExt
->StorageDevice
186 ,(ULONG
)(DeviceExt
->FATStart
+sector
), 1,(UCHAR
*) Block
);
193 return (i
+sector
*128);
197 /* Give an error message (out of disk space) if we reach here) */
203 FAT12CountAvailableClusters(PDEVICE_EXTENSION DeviceExt
)
205 * FUNCTION: Counts free cluster in a FAT12 table
210 PUCHAR CBlock
=DeviceExt
->FAT
;
214 ExAcquireResourceSharedLite(&DeviceExt
->FatResource
, TRUE
);
216 for(i
=2;i
<((DeviceExt
->Boot
->FATSectors
*512*8)/12) ;i
++)
218 FATOffset
= (i
* 12)/8;
221 Entry
= CBlock
[FATOffset
];
222 Entry
|= ((CBlock
[FATOffset
+ 1] & 0xf)<<8);
226 Entry
= (CBlock
[FATOffset
] >> 4);
227 Entry
|= (CBlock
[FATOffset
+ 1] << 4);
233 ExReleaseResourceLite(&DeviceExt
->FatResource
);
239 FAT16CountAvailableClusters(PDEVICE_EXTENSION DeviceExt
)
241 * FUNCTION: Counts free clusters in a FAT16 table
248 ExAcquireResourceSharedLite(&DeviceExt
->FatResource
, TRUE
);
250 Block
=(PUSHORT
)DeviceExt
->FAT
;
251 for(i
=2;i
<(DeviceExt
->Boot
->FATSectors
*256);i
++)
257 ExReleaseResourceLite(&DeviceExt
->FatResource
);
263 FAT32CountAvailableClusters(PDEVICE_EXTENSION DeviceExt
)
265 * FUNCTION: Counts free clusters in a FAT32 table
273 ExAcquireResourceSharedLite(&DeviceExt
->FatResource
, TRUE
);
275 Block
= ExAllocatePool(NonPagedPool
,BLOCKSIZE
);
277 ;sector
< ((struct _BootSector32
*)(DeviceExt
->Boot
))->FATSectors32
280 VFATReadSectors(DeviceExt
->StorageDevice
281 ,(ULONG
)(DeviceExt
->FATStart
+sector
), 1,(UCHAR
*) Block
);
289 /* Give an error message (out of disk space) if we reach here) */
291 ExReleaseResourceLite(&DeviceExt
->FatResource
);
296 FAT12WriteCluster(PDEVICE_EXTENSION DeviceExt
, ULONG ClusterToWrite
,
299 * FUNCTION: Writes a cluster to the FAT12 physical and in-memory tables
304 PUCHAR CBlock
=DeviceExt
->FAT
;
306 FATOffset
= (ClusterToWrite
* 12)/8;
307 if ((ClusterToWrite
% 2) == 0)
309 CBlock
[FATOffset
]=NewValue
;
310 CBlock
[FATOffset
+ 1] &=0xf0;
311 CBlock
[FATOffset
+ 1]
312 |= (NewValue
&0xf00)>>8;
316 CBlock
[FATOffset
] &=0x0f;
318 |= (NewValue
&0xf)<<4;
319 CBlock
[FATOffset
+1]=NewValue
>>4;
321 /* Write the changed FAT sector(s) to disk */
322 FATsector
=FATOffset
/BLOCKSIZE
;
323 for(i
=0;i
<DeviceExt
->Boot
->FATCount
;i
++)
325 if( (FATOffset
%BLOCKSIZE
)==(BLOCKSIZE
-1))//entry is on 2 sectors
327 VFATWriteSectors(DeviceExt
->StorageDevice
,
328 DeviceExt
->FATStart
+FATsector
329 +i
*DeviceExt
->Boot
->FATSectors
,
331 CBlock
+FATsector
*512);
335 VFATWriteSectors(DeviceExt
->StorageDevice
,
336 DeviceExt
->FATStart
+FATsector
337 +i
*DeviceExt
->Boot
->FATSectors
,
339 CBlock
+FATsector
*512);
345 FAT16WriteCluster(PDEVICE_EXTENSION DeviceExt
, ULONG ClusterToWrite
,
348 * FUNCTION: Writes a cluster to the FAT16 physical and in-memory tables
356 DbgPrint("FAT16WriteCluster %u : %u\n", ClusterToWrite
, NewValue
);
358 Block
=(PUSHORT
)DeviceExt
->FAT
;
359 FATsector
=ClusterToWrite
/(512/sizeof(USHORT
));
361 /* Update the in-memory FAT */
362 Block
[ClusterToWrite
] = NewValue
;
364 /* Write the changed FAT sector to disk (all FAT's) */
365 Start
= DeviceExt
->FATStart
+ FATsector
;
366 for (i
= 0; i
< DeviceExt
->Boot
->FATCount
; i
++)
368 VFATWriteSectors(DeviceExt
->StorageDevice
,
371 ((UCHAR
*)Block
)+FATsector
*512);
372 Start
+= DeviceExt
->Boot
->FATSectors
;
377 FAT32WriteCluster(PDEVICE_EXTENSION DeviceExt
, ULONG ClusterToWrite
,
380 * FUNCTION: Writes a cluster to the FAT32 physical tables
388 struct _BootSector32
*pBoot
;
389 DbgPrint("FAT32WriteCluster %u : %u\n",ClusterToWrite
,NewValue
);
390 Block
= ExAllocatePool(NonPagedPool
,BLOCKSIZE
);
391 FATsector
=ClusterToWrite
/128;
392 FATeis
=ClusterToWrite
-(FATsector
*128);
393 /* load sector, change value, then rewrite sector */
394 VFATReadSectors(DeviceExt
->StorageDevice
,
395 DeviceExt
->FATStart
+FATsector
,
398 Block
[FATeis
] = NewValue
;
399 /* Write the changed FAT sector to disk (all FAT's) */
400 Start
= DeviceExt
->FATStart
+ FATsector
;
401 pBoot
= (struct _BootSector32
*) DeviceExt
->Boot
;
402 for (i
= 0; i
< pBoot
->FATCount
; i
++)
404 VFATWriteSectors(DeviceExt
->StorageDevice
,
408 Start
+= pBoot
->FATSectors
;
414 WriteCluster(PDEVICE_EXTENSION DeviceExt
, ULONG ClusterToWrite
,
417 * FUNCTION: Write a changed FAT entry
420 if (DeviceExt
->FatType
==FAT16
)
422 FAT16WriteCluster(DeviceExt
, ClusterToWrite
, NewValue
);
424 else if (DeviceExt
->FatType
==FAT32
)
426 FAT32WriteCluster(DeviceExt
, ClusterToWrite
, NewValue
);
430 FAT12WriteCluster(DeviceExt
, ClusterToWrite
, NewValue
);
435 GetNextWriteCluster(PDEVICE_EXTENSION DeviceExt
, ULONG CurrentCluster
)
437 * FUNCTION: Determines the next cluster to be written
440 ULONG LastCluster
, NewCluster
;
443 DPRINT("GetNextWriteCluster(DeviceExt %x, CurrentCluster %x)\n",
444 DeviceExt
,CurrentCluster
);
446 /* Find out what was happening in the last cluster's AU */
447 LastCluster
=GetNextCluster(DeviceExt
,
449 /* Check to see if we must append or overwrite */
450 if (LastCluster
== 0xffffffff)
452 /* we are after last existing cluster : we must add one to file */
454 /* Firstly, find the next available open allocation unit */
455 if (DeviceExt
->FatType
== FAT16
)
457 NewCluster
= FAT16FindAvailableCluster(DeviceExt
);
458 DPRINT1("NewCluster %x\n", NewCluster
);
460 else if (DeviceExt
->FatType
== FAT32
)
462 NewCluster
= FAT32FindAvailableCluster(DeviceExt
);
466 NewCluster
= FAT12FindAvailableCluster(DeviceExt
);
467 DPRINT( "NewFat12Cluster: %x\n", NewCluster
);
469 /* Mark the new AU as the EOF */
470 WriteCluster(DeviceExt
, NewCluster
, 0xFFFFFFFF);
471 /* Now, write the AU of the LastCluster with the value of the newly
475 WriteCluster(DeviceExt
, CurrentCluster
, NewCluster
);
477 // fill cluster with zero
478 Buffer2
=ExAllocatePool(NonPagedPool
,DeviceExt
->BytesPerCluster
);
479 memset(Buffer2
,0,DeviceExt
->BytesPerCluster
);
480 VFATWriteCluster(DeviceExt
,Buffer2
,NewCluster
);
482 /* Return NewCluster as CurrentCluster */
487 /* Overwrite: Return LastCluster as CurrentCluster */
493 ClusterToSector(PDEVICE_EXTENSION DeviceExt
,
494 unsigned long Cluster
)
496 * FUNCTION: Converts the cluster number to a sector number for this physical
500 return DeviceExt
->dataStart
+((Cluster
-2)*DeviceExt
->Boot
->SectorsPerCluster
);
504 VFATLoadCluster(PDEVICE_EXTENSION DeviceExt
, PVOID Buffer
, ULONG Cluster
)
506 * FUNCTION: Load a cluster from the physical device
511 DPRINT("VFATLoadCluster(DeviceExt %x, Buffer %x, Cluster %d)\n",
512 DeviceExt
,Buffer
,Cluster
);
514 Sector
= ClusterToSector(DeviceExt
, Cluster
);
516 VFATReadSectors(DeviceExt
->StorageDevice
,
518 DeviceExt
->Boot
->SectorsPerCluster
,
520 DPRINT("Finished VFATReadSectors\n");
524 VFATWriteCluster(PDEVICE_EXTENSION DeviceExt
, PVOID Buffer
, ULONG Cluster
)
526 * FUNCTION: Write a cluster to the physical device
530 DPRINT("VFATWriteCluster(DeviceExt %x, Buffer %x, Cluster %d)\n",
531 DeviceExt
,Buffer
,Cluster
);
533 Sector
= ClusterToSector(DeviceExt
, Cluster
);
535 VFATWriteSectors(DeviceExt
->StorageDevice
,
537 DeviceExt
->Boot
->SectorsPerCluster
,