windows-nt/Source/XPSP1/NT/base/ntsetup/mpk/imagpart/cluster.c
2020-09-26 16:20:57 +08:00

228 lines
4.7 KiB
C

#include "imagpart.h"
BOOL
BuildClusterBitmap(
IN FilesystemType FsType,
IN HPARTITION PartitionHandle,
IN UINT FileHandle,
IN OUT PARTITION_IMAGE *PartitionImage
)
/*++
Routine Description:
This routine builds a bitmap representing all clusters in the
source volume, 1 bit per cluster (0=unused, 1=used). The bitmap
is written into a file.
Arguments:
FsType - supplies the type of the file system
PartitionHandle - supplies handle to source partition
FileHandle - supplies handle for output file. It is assumed that
this file is empty. On output this file is rewound to offset 0.
PartitionImage - supplies information about the source partition.
On output, the following fields are filled in:
LastUsedCluster
UsedClusterCount
Return Value:
Boolean value indicating outcome. If false, a message will have been
printed out explaining why.
--*/
{
BOOL b;
if(FsType == FilesystemFat) {
b = FatBuildClusterBitmap(PartitionHandle,FileHandle,PartitionImage);
} else {
if(FsType == FilesystemNtfs) {
b = NtfsBuildClusterBitmap(PartitionHandle,FileHandle,PartitionImage);
} else {
fprintf(stderr,"\n%s\n",textUnsupportedFs);
b = FALSE;
}
}
if(b) {
DosSeek(FileHandle,0,DOSSEEK_START);
}
return(b);
}
FPBYTE _ClusterBuffer;
ULONG _BaseCluster;
UINT _ClusterFileHandle;
ULONG _LastUsedCluster;
ULONG _NextClusterToExamine;
BYTE BitValue[8] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
VOID
InitClusterBuffer(
IN FPBYTE _512ByteBuffer,
IN UINT FileHandle
)
{
_ClusterBuffer = _512ByteBuffer;
_BaseCluster = 0L;
_ClusterFileHandle = FileHandle;
memset(_512ByteBuffer,0,512);
}
BOOL
MarkClusterUsed(
IN ULONG Cluster
)
{
unsigned Written;
BOOL NeedToZero;
//
// See if the cluster we're updating is past the end of what
// we're currently buffering. Note that it could be way beyond.
//
NeedToZero = TRUE;
while(Cluster >= _BaseCluster+(8*512)) {
if(_dos_write(_ClusterFileHandle,_ClusterBuffer,512,&Written) || (Written != 512)) {
fprintf(stderr,"\n%s\n",textFileWriteError);
return(FALSE);
}
_BaseCluster += 8*512;
if(NeedToZero) {
memset(_ClusterBuffer,0,512);
NeedToZero = FALSE;
}
}
//
// Set the relevent bit.
//
Cluster -= _BaseCluster;
_ClusterBuffer[Cluster/8] |= BitValue[Cluster%8];
return(TRUE);
}
BOOL
FlushClusterBuffer(
VOID
)
{
unsigned Written;
unsigned u;
BOOL b;
u = _dos_write(_ClusterFileHandle,_ClusterBuffer,512,&Written);
b = (!u && (Written == 512));
if(!b) {
fprintf(stderr,"\n%s\n",textFileWriteError);
}
return(b);
}
BOOL
InitClusterMap(
OUT FPBYTE _512ByteBuffer,
IN UINT FileHandle,
IN ULONG LastUsedCluster
)
{
unsigned Read;
_ClusterBuffer = _512ByteBuffer;
_ClusterFileHandle = FileHandle;
_BaseCluster = 0L;
_NextClusterToExamine = 0L;
_LastUsedCluster = LastUsedCluster;
if(_dos_read(FileHandle,_ClusterBuffer,512,&Read) || (Read != 512)) {
fprintf(stderr,"\n%s\n",textFileReadFailed);
return(FALSE);
}
return(TRUE);
}
BOOL
GetNextClusterRun(
OUT ULONG *StartCluster,
OUT ULONG *ClusterCount
)
{
UINT cluster;
unsigned Read;
BOOL b;
*ClusterCount=0;
//
// Scan forward for the next 1 bit
//
while(_NextClusterToExamine <= _LastUsedCluster) {
//
// Reload the cluster buffer if necessary.
//
if(_NextClusterToExamine && !(_NextClusterToExamine % (512*8))) {
if(_dos_read(_ClusterFileHandle,_ClusterBuffer,512,&Read) || (Read != 512)) {
fprintf(stderr,"\n%s\n",textFileReadFailed);
return(FALSE);
}
_BaseCluster += 512*8;
}
cluster = (UINT)(_NextClusterToExamine - _BaseCluster);
//
// To simplify things, the run will not span into the next sector
// of the cluster map.
//
b = FALSE;
while((_ClusterBuffer[cluster/8] & BitValue[cluster%8])
&& (cluster < (512*8)) && (_NextClusterToExamine <= _LastUsedCluster)) {
if(!b) {
*StartCluster = _NextClusterToExamine;
b = TRUE;
}
*ClusterCount += 1;
cluster++;
_NextClusterToExamine++;
}
if(b) {
return(TRUE);
}
_NextClusterToExamine++;
}
//
// No more used clusters.
//
return(TRUE);
}