⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fscreate.cpp

📁 XOSL 多操作系统管理工具 源代码 多系统引导工具
💻 CPP
字号:
/*
 * Extended Operating System Loader (XOSL)
 * Copyright (c) 1999 by Geurt Vos
 *
 * This code is distributed under GNU General Public License (GPL)
 *
 * The full text of the license can be found in the GPL.TXT file,
 * or at http://www.gnu.org
 */


#include <FsCreate.h>
#include <string.h>
#include <memory.h>

#include <disk.h>
#include <transfer.h>

CFsCreator::CFsCreator(CTextUI &TextUIToUse, CXoslFiles &XoslFilesToUse, CDosFile &DosFileToUse):
	TextUI(TextUIToUse),
	XoslFiles(XoslFilesToUse),
	DosFile(DosFileToUse)
{
}

CFsCreator::~CFsCreator()
{
}

int CFsCreator::InstallFs(unsigned short Drive, unsigned long Sector)
{
	MemSet(Fat,0,sizeof(unsigned short[256]));
	MemSet(RootDir,0,sizeof(CDirectoryEntry[32]));

	if (LoadIplS(Drive) == -1)
		return -1;
	if (PackFiles() == -1)
		return -1;
	if (InitBootRecord(Drive,Sector) == -1)
		return -1;

	if (BackupPartition(Drive,Sector) == -1)
		return -1;
	if (InstallXoslImg(Drive,Sector) == -1)
		return -1;
	
	return 0;
}

int CFsCreator::LoadIplS(int Drive)
{
	CDiskAccess DiskAccess;
	const char *IplFileName;
	int hFile;

	MemSet(&BootRecord,0,512);
	if (DiskAccess.LBAAccessAvail(Drive) != -1)
		IplFileName = XoslFiles.GetIplFileName(CXoslFiles::enumIplSLba);
	else
		IplFileName = XoslFiles.GetIplFileName(CXoslFiles::enumIplS);

	if ((hFile = DosFile.Open(IplFileName,CDosFile::accessReadOnly)) == -1) {
		TextUI.OutputStr("Unable to open %s\n",IplFileName);
		return -1;
	}
	DosFile.Read(hFile,&BootRecord,512);
	DosFile.Close(hFile);
	return 0;
}


int CFsCreator::InitBootRecord(unsigned short Drive, unsigned long Sector)
{
	CDiskAccess DiskAccess;
	int HeadCount, SectorCount;


	TextUI.OutputStr("Initializing boot record...");
	if (DiskAccess.GetDriveInfo(Drive,HeadCount,SectorCount) == -1) {
		TextUI.OutputStr("failed\nUnable to retreive drive info\n");
		return -1;
	}

/*	BootRecord.Jump[0] = 0xeb;
	BootRecord.Jump[1] = 0x3c;
	BootRecord.Jump[2] = 0x90;*/

	MemCopy(BootRecord.OEM_ID,"XOSLINST",8);
	BootRecord.SectorSize = 512;
	BootRecord.ClusterSize = 16;
	BootRecord.ReservedSectors = 1;
	BootRecord.FATCopies = 1;
	BootRecord.RootEntries = 32;
	BootRecord.SectorCount = (FatIndex - 2) * 16 + 4;
	BootRecord.MediaDescriptor = 0xf8;
	BootRecord.FATSize = 1;

	BootRecord.TrackSize = SectorCount;
	BootRecord.HeadCount = HeadCount;

	BootRecord.HiddenSectors = Sector;
	BootRecord.BigSectorCount = 0;
	BootRecord.Drive = Drive;
	BootRecord.Signature = 0x29;
	BootRecord.SerialNo = 0x4c534f58;
	MemCopy(BootRecord.Label,"XOSL114    ",11);
	MemCopy(BootRecord.FSID,"FAT16   ",8);
	BootRecord.MagicNumber = 0x534f;
	TextUI.OutputStr("done\n");
	return 0;
}

int CFsCreator::PackFiles()
{
	int hClusterFile;
	int Index, Count;
	const char *FileName;
	long FileSize;
	int AppendStat;

	TextUI.OutputStr("Packing XOSL files...\n");
	FatIndex = 2; // first two are reserved!
	RootDirIndex = 0;

	TextUI.OutputStr("Creating "XOSLIMG_FILE"...");
	if ((hClusterFile = DosFile.Create(XOSLIMG_FILE)) == -1) {
		TextUI.OutputStr("failed\n");
		return - 1;
	}
	TextUI.OutputStr("done\n");

	Count = XoslFiles.GetCount();


	for (Index = 0; Index < Count; ++Index) {
		FileName = XoslFiles.GetFileName(Index);
		TextUI.OutputStr("Packing %s...",FileName);

		FileSize = DosFile.FileSize(FileName);
		AppendStat = DosFile.Append(hClusterFile,FileName);

		if (FileSize == -1 || AppendStat == -1) {
			TextUI.OutputStr("failed\n");
			DosFile.Close(hClusterFile);
			return -1;
		}

		// AddRootDirEntry() needs current FatIndex, 
		// so can't swap next two function calls
		AddRootDirEntry(FileName,FileSize);
		AddFatEntries(FileSize);

		// fill last part of the cluster with random data
		FileSize = CLUSTER_SIZE - (FileSize % CLUSTER_SIZE);
		if (FileSize != CLUSTER_SIZE)
			if (DosFile.Write(hClusterFile,CDosFile::TransferBuffer,FileSize) != FileSize) {
				TextUI.OutputStr("failed\nDisk full.\n");
				DosFile.Close(hClusterFile);
				return -1;
			}

		
		TextUI.OutputStr("done\n");
	}
	DosFile.Close(hClusterFile);
	return 0;
}


void CFsCreator::AddRootDirEntry(const char *FileName, long FileSize)
{
	CDirectoryEntry &Entry = RootDir[RootDirIndex++];
	char Name[9];
	char Ext[4];
	int Len;
	

	DosFile.GetNameExt(FileName,Name,Ext);

	Len = strlen(Name);
	MemSet(&Name[Len],' ',8 - Len);

	Len = strlen(Ext);
	MemSet(&Ext[Len],' ',3 - Len);

	MemCopy(Entry.FileName,Name,8);
	MemCopy(Entry.Extension,Ext,3);
	Entry.StartCluster = FatIndex;
	Entry.FileSize = FileSize;
}

void CFsCreator::AddFatEntries(long FileSize)
{
	int ClusterCount = FileSize / CLUSTER_SIZE;
	int Index;

	if ((FileSize % CLUSTER_SIZE) != 0)
		++ClusterCount;

	for (Index = 0; Index < ClusterCount - 1; ++Index, ++FatIndex)
		Fat[FatIndex] = FatIndex + 1;
	Fat[FatIndex++] = 0xffff;
}

int CFsCreator::BackupPartition(int Drive, unsigned long Sector)
{
	long ImageSize;
	int TransferCount;
	int Index;
	CDisk Disk;
	int hFile;

	TextUI.OutputStr("Creating backup...");
	if ((ImageSize = DosFile.FileSize(XOSLIMG_FILE)) == -1) {
		TextUI.OutputStr("failed\nUnable to determine image size\n");
		return -1;
	}

	TransferCount = (ImageSize >> 11) + 1;

	if (Disk.Map(Drive,Sector) == -1) {
		TextUI.OutputStr("failed\nUnable to map partition\n");
		return -1;
	}

	if ((hFile = DosFile.Create(PARTBACKUP_FILE)) == -1) {
		TextUI.OutputStr("failed\nUnable to create "PARTBACKUP_FILE"\n");
		return -1;
	}

	if (DosFile.Write(hFile,&Drive,sizeof (unsigned short)) != sizeof (unsigned short)) {
		TextUI.OutputStr("failed\nDisk full.\n");
		DosFile.Close(hFile);
		return -1;
	}
	if (DosFile.Write(hFile,&Sector,sizeof (unsigned long)) != sizeof (unsigned long)) {
		TextUI.OutputStr("failed\nDisk full.\n");
		DosFile.Close(hFile);
		return -1;
	}

	for (Index = 0; Index < TransferCount; ++Index) {
		if (Disk.Read(Index,CDosFile::TransferBuffer,4) == -1) {
			TextUI.OutputStr("failed\nUnable to read partition data\n");
			DosFile.Close(hFile);
			return -1;
		}
		if (DosFile.Write(hFile,CDosFile::TransferBuffer,2048) != 2048) {
			TextUI.OutputStr("failed\nDisk full.\n");
			DosFile.Close(hFile);
			return -1;
		}
	}
	DosFile.Close(hFile);
	TextUI.OutputStr("done\n");
	return 0;
}


void CFsCreator::RestorePartition(unsigned short Drive, unsigned long StartSector)
{
	long ImageSize;
	int TransferCount;
	int Index;
	CDisk Disk;
	int hFile;
	unsigned short BackupDrive;
	unsigned long BackupStartSector;

	TextUI.OutputStr("Restoring partition data...");
	if (DosFile.SetAttrib(PARTBACKUP_FILE,0) == -1) {
		TextUI.OutputStr("ignored\nBackup not found\n");
		return;
	}

	if ((ImageSize = DosFile.FileSize(PARTBACKUP_FILE)) == -1) {
		TextUI.OutputStr("ignored\nUnable to determine backup size\n");
		return;
	}


	if (Disk.Map(Drive,StartSector) == -1) {
		TextUI.OutputStr("ignored\nUnable to map partition\n");
		return;
	}

	if ((hFile = DosFile.Open(PARTBACKUP_FILE,CDosFile::accessReadOnly)) == -1) {
		TextUI.OutputStr("ignored\nUnable to open "PARTBACKUP_FILE"\n");
		return;
	}

	Disk.Lock();
	TransferCount = (ImageSize - 6) >> 11; // always a multiple of 2048!

	DosFile.Read(hFile,&BackupDrive,sizeof (unsigned short));
	DosFile.Read(hFile,&BackupStartSector,sizeof (unsigned long));
	if (BackupDrive != Drive || BackupStartSector != StartSector) {
		TextUI.OutputStr("ignored\nInvalid backup image\n");
		return;
	}
	
	for (Index = 0; Index < TransferCount; ++Index) {
		DosFile.Read(hFile,CDosFile::TransferBuffer,2048);
		Disk.Write(Index,CDosFile::TransferBuffer,4);
	}
	Disk.Unlock();
	DosFile.Close(hFile);
	TextUI.OutputStr("done\n");
}



int CFsCreator::InstallXoslImg(int Drive, unsigned long Sector)
{
	int hFile;
	CDisk Disk;
	int WriteIndex;


	TextUI.OutputStr("Writing XOSL image...");

	if (Disk.Map(Drive,Sector) == -1) {
		TextUI.OutputStr("failed\nUable to map partition\n");
		return -1;
	}
	
	if (Disk.Write(0,&BootRecord,1) == -1) {
		TextUI.OutputStr("failed\nUnable to write image data\n");
		return -1;
	}
	if (Disk.Write(1,Fat,1) == -1) {
		TextUI.OutputStr("failed\nUnable to write image data\n");
		return -1;
	}
	if (Disk.Write(2,RootDir,2) == -1) {
		TextUI.OutputStr("failed\nUnable to write image data\n");
		return -1;
	}

	if ((hFile = DosFile.Open(XOSLIMG_FILE,CDosFile::accessReadOnly)) == -1) {
		TextUI.OutputStr("failed\nUnable to open "XOSLIMG_FILE"\n");
		return -1;
	}

	for (WriteIndex = 4; DosFile.Read(hFile,CDosFile::TransferBuffer,2048); WriteIndex += 4)
		if (Disk.Write(WriteIndex,CDosFile::TransferBuffer,4) == -1) {
			TextUI.OutputStr("failed\nUnable to write image data\n");
			DosFile.Close(hFile);
			return -1;
		}
	DosFile.Close(hFile);
	TextUI.OutputStr("done\n");
	return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -