389 lines
9.2 KiB
C
389 lines
9.2 KiB
C
#include <mytypes.h>
|
|
#include <diskio.h>
|
|
#include <misclib.h>
|
|
#include <makepart.h>
|
|
#include <partimag.h>
|
|
#include <msgfile.h>
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <memory.h>
|
|
#include <dos.h>
|
|
#include <share.h>
|
|
#include <string.h>
|
|
|
|
#include "makemast.h"
|
|
|
|
|
|
PARTITION_IMAGE PartitionImage;
|
|
ULONG TotalSectorsToTransfer;
|
|
ULONG TotalSectorsDone;
|
|
|
|
BOOL
|
|
TransferNonClusterData(
|
|
IN HDISK DiskHandle,
|
|
IN unsigned FileHandle,
|
|
IN ULONG TargetStart
|
|
);
|
|
|
|
BOOL
|
|
ExpandClusters(
|
|
IN HDISK DiskHandle,
|
|
IN unsigned FileHandle,
|
|
IN ULONG TargetStart
|
|
);
|
|
|
|
BOOL
|
|
InitializeClusterMap(
|
|
IN unsigned FileHandle
|
|
);
|
|
|
|
BOOL
|
|
GetClusterRun(
|
|
IN unsigned FileHandle,
|
|
OUT ULONG *StartCluster,
|
|
OUT ULONG *ClusterCount
|
|
);
|
|
|
|
|
|
BOOL
|
|
ApplyImage(
|
|
IN HDISK DiskHandle,
|
|
IN ULONG TargetStart,
|
|
IN ULONG MaxSize,
|
|
IN BYTE SectorsPerTrack,
|
|
IN USHORT Heads
|
|
)
|
|
{
|
|
unsigned FileHandle;
|
|
unsigned Read;
|
|
|
|
printf("\n");
|
|
printf(textTransferringFile,CmdLineArgs.ImageFile,0);
|
|
printf("\r");
|
|
|
|
//
|
|
// Open the source file, read the image header, and validate it.
|
|
//
|
|
if(_dos_open(CmdLineArgs.ImageFile,SH_DENYWR,&FileHandle)) {
|
|
fprintf(stderr,"\n%s\n",textCantAccessImageFile);
|
|
return(FALSE);
|
|
}
|
|
|
|
if(_dos_read(FileHandle,&PartitionImage,sizeof(PARTITION_IMAGE),&Read)
|
|
|| (Read != sizeof(PARTITION_IMAGE))
|
|
|| (PartitionImage.Signature != PARTITION_IMAGE_SIGNATURE)
|
|
|| (PartitionImage.Size != sizeof(PARTITION_IMAGE))) {
|
|
|
|
_dos_close(FileHandle);
|
|
fprintf(stderr,"\n%s\n",textInvalidImageFile);
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// Make sure we've got the space.
|
|
//
|
|
if(PartitionImage.TotalSectorCount > MaxSize) {
|
|
|
|
_dos_close(FileHandle);
|
|
fprintf(stderr,"\n");
|
|
fprintf(stderr,textImageFileTooBig,PartitionImage.TotalSectorCount,MaxSize);
|
|
fprintf(stderr,"\n");
|
|
return(FALSE);
|
|
}
|
|
|
|
TotalSectorsToTransfer = PartitionImage.NonClusterSectors
|
|
+ (PartitionImage.SectorsPerCluster*PartitionImage.UsedClusterCount);
|
|
|
|
TotalSectorsDone = 0;
|
|
|
|
//
|
|
// Transfer non-cluster data from the image.
|
|
//
|
|
if(!TransferNonClusterData(DiskHandle,FileHandle,TargetStart)) {
|
|
_dos_close(FileHandle);
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// Expand out cluster data from the image.
|
|
//
|
|
if(!ExpandClusters(DiskHandle,FileHandle,TargetStart)) {
|
|
_dos_close(FileHandle);
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// Fix up BPB.
|
|
//
|
|
if(!ReadDisk(DiskHandle,TargetStart,1,IoBuffer)) {
|
|
_dos_close(FileHandle);
|
|
fprintf(stderr,"\n");
|
|
fprintf(stderr,textDiskReadError,TargetStart);
|
|
fprintf(stderr,"\n");
|
|
return(FALSE);
|
|
}
|
|
|
|
*(FPUSHORT)&((FPBYTE)IoBuffer)[24] = SectorsPerTrack;
|
|
*(FPUSHORT)&((FPBYTE)IoBuffer)[26] = Heads;
|
|
*(FPULONG)&((FPBYTE)IoBuffer)[28] = TargetStart;
|
|
|
|
if(!WriteDisk(DiskHandle,TargetStart,1,IoBuffer)) {
|
|
_dos_close(FileHandle);
|
|
fprintf(stderr,"\n");
|
|
fprintf(stderr,textDiskWriteError,TargetStart);
|
|
fprintf(stderr,"\n");
|
|
return(FALSE);
|
|
}
|
|
|
|
_dos_close(FileHandle);
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
BOOL
|
|
TransferNonClusterData(
|
|
IN HDISK DiskHandle,
|
|
IN unsigned FileHandle,
|
|
IN ULONG TargetStart
|
|
)
|
|
{
|
|
ULONG NonClusterSectorsDone;
|
|
ULONG Count;
|
|
unsigned Read;
|
|
|
|
//
|
|
// Seek past partition image header
|
|
//
|
|
if(DosSeek(FileHandle,512,DOSSEEK_START) != 512) {
|
|
fprintf(stderr,"\n%s\n",textCantAccessImageFile);
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// Now transfer the non-cluster data
|
|
//
|
|
NonClusterSectorsDone = 0;
|
|
while(NonClusterSectorsDone < PartitionImage.NonClusterSectors) {
|
|
|
|
Count = PartitionImage.NonClusterSectors - NonClusterSectorsDone;
|
|
if(Count > 63) {
|
|
Count = 63;
|
|
}
|
|
|
|
if(_dos_read(FileHandle,IoBuffer,(unsigned)Count*512,&Read) || (Read != ((unsigned)Count*512))) {
|
|
fprintf(stderr,"\n%s\n",textCantAccessImageFile);
|
|
return(FALSE);
|
|
}
|
|
|
|
if(!WriteDisk(DiskHandle,TargetStart,(BYTE)Count,IoBuffer)) {
|
|
fprintf(stderr,"\n");
|
|
fprintf(stderr,textDiskWriteError,TargetStart);
|
|
fprintf(stderr,"\n");
|
|
return(FALSE);
|
|
}
|
|
|
|
TargetStart += Count;
|
|
NonClusterSectorsDone += Count;
|
|
TotalSectorsDone += Count;
|
|
|
|
printf(textTransferringFile,CmdLineArgs.ImageFile,100*TotalSectorsDone/TotalSectorsToTransfer);
|
|
printf("\r");
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
BOOL
|
|
ExpandClusters(
|
|
IN HDISK DiskHandle,
|
|
IN unsigned FileHandle,
|
|
IN ULONG TargetStart
|
|
)
|
|
{
|
|
ULONG Start,Count;
|
|
ULONG TargetSector;
|
|
BYTE u;
|
|
unsigned Read;
|
|
|
|
if(!InitializeClusterMap(FileHandle)) {
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// Seek to start of cluster data in input file.
|
|
//
|
|
Start = (1 + PartitionImage.NonClusterSectors) * 512;
|
|
if(DosSeek(FileHandle,Start,DOSSEEK_START) != Start) {
|
|
fprintf(stderr,"\n%s\n",textCantAccessImageFile);
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// Get a run of clusters. If there are no more clusters left, we're done.
|
|
//
|
|
nextrun:
|
|
if(!GetClusterRun(FileHandle,&Start,&Count)) {
|
|
return(FALSE);
|
|
}
|
|
if(!Count) {
|
|
return(TRUE);
|
|
}
|
|
Count *= PartitionImage.SectorsPerCluster;
|
|
|
|
//
|
|
// Calculate the offset of the data in the source file and
|
|
// the starting sector number of the target.
|
|
//
|
|
TargetSector = TargetStart + PartitionImage.NonClusterSectors + (Start*PartitionImage.SectorsPerCluster);
|
|
|
|
while(Count) {
|
|
|
|
u = (BYTE)((Count > 63L) ? 63L : Count);
|
|
|
|
if(_dos_read(FileHandle,IoBuffer,u*512U,&Read) || (Read != (u*512U))) {
|
|
|
|
fprintf(stderr,"\n%s\n",textCantAccessImageFile);
|
|
return(FALSE);
|
|
}
|
|
|
|
if(!WriteDisk(DiskHandle,TargetSector,u,IoBuffer)) {
|
|
fprintf(stderr,"\n");
|
|
fprintf(stderr,textDiskWriteError,TargetSector);
|
|
fprintf(stderr,"\n");
|
|
return(FALSE);
|
|
}
|
|
|
|
TargetSector += u;
|
|
Count -= u;
|
|
|
|
TotalSectorsDone += u;
|
|
|
|
printf(textTransferringFile,CmdLineArgs.ImageFile,100*TotalSectorsDone/TotalSectorsToTransfer);
|
|
printf("\r");
|
|
}
|
|
|
|
//
|
|
// Process additional clusters.
|
|
//
|
|
goto nextrun;
|
|
}
|
|
|
|
////////////////////////////////////////////////////
|
|
|
|
ULONG _ClusterSectorFileOffset;
|
|
ULONG _NextClusterToExamine;
|
|
ULONG _ClusterBufferBase;
|
|
BYTE _ClusterBuffer[512];
|
|
|
|
extern BYTE BitValue[8];
|
|
|
|
|
|
BOOL
|
|
InitializeClusterMap(
|
|
IN unsigned FileHandle
|
|
)
|
|
{
|
|
unsigned read;
|
|
|
|
//
|
|
// Figure out where in the file the cluster bitmap starts.
|
|
//
|
|
_ClusterSectorFileOffset = PartitionImage.NonClusterSectors
|
|
+ (PartitionImage.UsedClusterCount * PartitionImage.SectorsPerCluster)
|
|
+ 1;
|
|
|
|
_ClusterSectorFileOffset *= 512;
|
|
|
|
//
|
|
// Read the first sector of the cluster bitmap. Read into IoBuffer to avoid
|
|
// DMA boundary issues.
|
|
//
|
|
if((DosSeek(FileHandle,_ClusterSectorFileOffset,DOSSEEK_START) != _ClusterSectorFileOffset)
|
|
|| _dos_read(FileHandle,IoBuffer,512,&read) || (read != 512)) {
|
|
|
|
fprintf(stderr,"\n%s\n",textCantAccessImageFile);
|
|
return(FALSE);
|
|
}
|
|
memmove(_ClusterBuffer,IoBuffer,512);
|
|
|
|
_NextClusterToExamine = 0;
|
|
_ClusterBufferBase = 0;
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
BOOL
|
|
GetClusterRun(
|
|
IN unsigned FileHandle,
|
|
OUT ULONG *StartCluster,
|
|
OUT ULONG *ClusterCount
|
|
)
|
|
{
|
|
ULONG Offset;
|
|
UINT cluster;
|
|
BOOL b;
|
|
|
|
*ClusterCount = 0;
|
|
|
|
//
|
|
// Locate the next 1 bit in the map.
|
|
//
|
|
while(_NextClusterToExamine <= PartitionImage.LastUsedCluster) {
|
|
|
|
//
|
|
// Reload the cluster buffer if necessary. Preserve file pointer!
|
|
//
|
|
if(_NextClusterToExamine && !(_NextClusterToExamine % (8*512))) {
|
|
|
|
_ClusterSectorFileOffset += 512;
|
|
|
|
if(((Offset = DosSeek(FileHandle,0,DOSSEEK_CURRENT)) == (ULONG)(-1))
|
|
|| (DosSeek(FileHandle,_ClusterSectorFileOffset,DOSSEEK_START) != _ClusterSectorFileOffset)
|
|
|| _dos_read(FileHandle,IoBuffer,512,&cluster)
|
|
|| (cluster != 512)
|
|
|| (DosSeek(FileHandle,Offset,DOSSEEK_START) != Offset)) {
|
|
|
|
fprintf(stderr,"\n%s\n",textCantAccessImageFile);
|
|
return(FALSE);
|
|
}
|
|
|
|
memmove(_ClusterBuffer,IoBuffer,512);
|
|
|
|
_ClusterBufferBase += 8*512;
|
|
}
|
|
|
|
cluster = (UINT)(_NextClusterToExamine - _ClusterBufferBase);
|
|
|
|
//
|
|
// See if this bit is one, which starts a run of used clusters.
|
|
// To simplify things, we won't return a run that spans sectors
|
|
// in the cluster bitmap.
|
|
//
|
|
b = FALSE;
|
|
|
|
while((_ClusterBuffer[cluster/8] & BitValue[cluster%8])
|
|
&& (cluster < (8*512))
|
|
&& (_NextClusterToExamine <= PartitionImage.LastUsedCluster)) {
|
|
|
|
if(!b) {
|
|
*StartCluster = _NextClusterToExamine;
|
|
b = TRUE;
|
|
}
|
|
|
|
*ClusterCount += 1;
|
|
cluster++;
|
|
_NextClusterToExamine++;
|
|
}
|
|
|
|
if(b) {
|
|
return(TRUE);
|
|
}
|
|
|
|
_NextClusterToExamine++;
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|