MODULE Partitions;
IMPORT KernelLog, Texts, TextUtilities, Disks, Files, Lib := PartitionsLib, Plugins, Commands, Streams, Strings, FATScavenger;
CONST
Trace = FALSE;
Invalid = MIN(LONGINT);
BootManagerMBRFile = "BootManagerMBR.Bin";
BootManagerTailFile = "BootManagerTail.Bin";
PROCEDURE ShowOps*(context : Commands.Context);
VAR par : ARRAY 10 OF CHAR; details : BOOLEAN;
BEGIN
par := ""; context.arg.SkipWhitespace; context.arg.String(par);
details := (par = "detail");
Lib.operations.Show(context.out, details);
END ShowOps;
PROCEDURE ShowOp*(context : Commands.Context);
VAR operation : Lib.Operation; uid : LONGINT;
BEGIN
IF context.arg.GetInteger(uid, FALSE) THEN
operation := Lib.operations.GetByUid(uid);
IF operation # NIL THEN
operation.Show(context.out, TRUE);
ELSE context.error.String("Error: Operation UID "); context.error.Int(uid, 0); context.error.String(" not found"); context.error.Ln;
END;
ELSE context.error.String("Exspected parameters: uid"); context.error.Ln;
END;
END ShowOp;
PROCEDURE Abort*(context : Commands.Context);
VAR operation : Lib.Operation; uid : LONGINT;
BEGIN
IF context.arg.GetInteger(uid, FALSE) THEN
operation := Lib.operations.GetByUid(uid);
IF operation # NIL THEN
operation.Abort;
context.out.String("Operation UID "); context.out.Int(uid, 0); context.out.String(" aborted"); context.out.Ln;
ELSE context.error.String("Error: Operation UID "); context.error.Int(uid, 0); context.error.String(" not found"); context.error.Ln;
END;
ELSE context.error.String("Exspected parameters: uid"); context.error.Ln;
END;
END Abort;
PROCEDURE Remove*(context : Commands.Context);
VAR par : ARRAY 128 OF CHAR; uid, num : LONGINT;
BEGIN
IF context.arg.GetInteger(uid, FALSE) THEN
IF Lib.operations.RemoveByUid(uid) THEN
context.out.String("Operation UID "); context.out.Int(uid, 0); context.out.String(" has been removed"); context.out.Ln;
ELSE
context.error.String("Error: Could not remove operation UID "); context.error.Int(uid, 0); context.error.Ln;
END;
ELSIF context.arg.res = Streams.FormatError THEN
par := "";
context.arg.SetPos(0);
IF context.arg.GetString(par) THEN
Strings.UpperCase(par);
IF par = "ALL" THEN
num := Lib.operations.RemoveAll(TRUE);
context.out.Int(num, 0); context.out.String(" operations have been removed"); context.out.Ln;
ELSIF par = "FINISHED" THEN
context.out.String("All finished operation have been removed"); context.out.Ln;
ELSE
context.error.String("Expected parameters: uid | all | finished"); context.error.Ln;
END;
ELSE context.error.String("Expected parameters: uid | all | finished"); context.error.Ln;
END;
ELSE context.error.String("Expected parameters: uid | all | finished"); context.error.Ln;
END;
END Remove;
PROCEDURE Mount*(context : Commands.Context);
VAR
mount :Lib.Mount;
prefix, alias, volumePars, fsPars : ARRAY 64 OF CHAR;
selection : Lib.Selection;
BEGIN
IF GetSelection(context, TRUE, selection) THEN
volumePars := ""; fsPars := "";
IF context.arg.GetString(alias) & context.arg.GetString(prefix) THEN
NEW(mount, selection.disk, selection.partition, context.out);
mount.SetParameters(prefix, alias, volumePars, fsPars);
mount.SetBlockingStart;
ELSE
context.error.String("Expected parameters: dev#part alias prefix"); context.error.Ln;
END;
END;
END Mount;
PROCEDURE Format*(context : Commands.Context);
VAR
formatAos : Lib.FormatPartition; formatFat : FATScavenger.FormatPartition;
fsname, bootfile, quick : ARRAY 128 OF CHAR;
fsRes, flags : LONGINT;
quickFormat : BOOLEAN;
selection : Lib.Selection;
BEGIN
IF GetSelection(context, TRUE, selection) THEN
IF context.arg.GetString(fsname) THEN
IF fsname = "FatFS" THEN
quickFormat := context.arg.GetString(quick) & (quick = "Quick");
NEW(formatFat, selection.disk, selection.partition, context.out);
formatFat.SetParameters(Strings.NewString("no name"), quickFormat);
formatFat.SetBlockingStart;
context.out.String("Partitions UID "); context.out.Int(formatFat.uid, 0);
context.out.String(": Started FAT format on "); context.out.String(formatFat.diskpartString); context.out.Ln;
ELSIF (fsname = "AosFS") OR (fsname = "NatFS") OR (fsname = "NatFS1") OR (fsname = "NatFS2") THEN
bootfile := ""; fsRes := -2; flags := 0;
IF context.arg.GetInteger(fsRes, FALSE) THEN
IF context.arg.GetString(bootfile) THEN
context.arg.SkipWhitespace; context.arg.Int(flags, FALSE);
END;
END;
NEW(formatAos, selection.disk, selection.partition, context.out);
formatAos.SetParameters(fsname, bootfile, fsRes, flags);
formatAos.SetBlockingStart;
ELSE
context.error.String("File system "); context.error.String(fsname); context.error.String(" is not supported"); context.error.Ln;
END;
ELSE
NEW(formatAos, selection.disk, selection.partition, context.out);
formatAos.SetParameters("AosFS", "", -2, 0);
formatAos.SetBlockingStart;
context.out.String("Partitions UID "); context.out.Int(formatAos.uid, 0);
context.out.String(": Started format on "); context.out.String(formatAos.diskpartString); context.out.Ln;
END;
END;
END Format;
PROCEDURE UpdateBootFile*(context : Commands.Context);
VAR
updateBootFile : Lib.UpdateBootFile;
selection : Lib.Selection;
filename : Files.FileName;
BEGIN
IF GetSelection(context, FALSE, selection) THEN
IF context.arg.GetString(filename) THEN
NEW(updateBootFile, selection.disk, selection.partition, context.out);
updateBootFile.SetParameters(filename);
updateBootFile.SetBlockingStart;
ELSE
context.error.String("Expected parameters: dev#part bootfilename"); context.error.Ln;
END;
END;
END UpdateBootFile;
PROCEDURE GetConfig*(context : Commands.Context);
CONST MaxSize = 2048;
VAR
getConfig : Lib.GetConfig;
selection : Lib.Selection;
configuration : Lib.Configuration;
table : Streams.StringWriter;
string : ARRAY MaxSize OF CHAR;
i : LONGINT;
BEGIN
IF GetSelection(context, TRUE, selection) THEN
NEW(getConfig, selection.disk, selection.partition, context.out);
getConfig.SetBlockingStart;
IF getConfig.state.status * Lib.StatusError = {} THEN
NEW(configuration);
configuration.table := getConfig.GetTable();
table := configuration.GetTableAsString();
table.Get(string);
FOR i := 0 TO LEN(string)-1 DO IF string[i] = ";" THEN string[i] := ","; END; END;
context.out.String("Partitions.SetConfig "); context.out.String(getConfig.diskpartString); context.out.Ln;
context.out.String(string); context.out.Ln;
END;
END;
END GetConfig;
PROCEDURE SetConfig*(context : Commands.Context);
VAR
setConfig : Lib.SetConfig;
selection : Lib.Selection;
configString : Strings.String;
ch : CHAR;
i : LONGINT;
BEGIN
IF GetSelection(context, TRUE, selection) THEN
IF context.arg.CanSetPos() THEN
NEW(configString, context.arg.Available() + 1);
i := 0;
WHILE (context.arg.Available() > 0) DO
context.arg.Char(ch);
IF (ch = ",") THEN
configString[i] := ";";
ELSE
configString[i] := ch;
END;
INC(i);
END;
configString[i-1] := "~";
configString[i] := 0X;
NEW(setConfig, selection.disk, selection.partition, context.out);
setConfig.SetParameters(configString, 0);
setConfig.SetBlockingStart;
ELSE
context.error.String("Expected argument stream that supports SetPos"); context.error.Ln;
END;
END;
END SetConfig;
PROCEDURE Check*(context : Commands.Context);
VAR
selection : Lib.Selection;
checkPartition : Lib.CheckPartition;
BEGIN
IF GetSelection(context, FALSE, selection) THEN
NEW(checkPartition, selection.disk, selection.partition, context.out);
checkPartition.SetBlockingStart;
ELSE
END;
END Check;
PROCEDURE ChangeType*(context : Commands.Context);
VAR
change : Lib.ChangePartType;
oldtype, newtype : LONGINT;
selection : Lib.Selection;
BEGIN
IF GetSelection(context, TRUE, selection) THEN
IF ~selection.disk.isDiskette THEN
IF context.arg.GetInteger(oldtype, FALSE) & (oldtype > 0) & (oldtype < 256) THEN
IF context.arg.GetInteger(newtype, FALSE) & (newtype > 0) & (newtype < 256) THEN
NEW(change, selection.disk, selection.partition, context.out);
change.SetParameters(oldtype, newtype);
change.SetBlockingStart;
ELSE context.error.String("Expected parameters: dev#part oldtype newtype, failed to parse newtype"); context.error.Ln;
END;
ELSE context.error.String("Expected parameters: dev#part oldtype newtype, failed to parse oldtype"); context.error.Ln;
END;
ELSE context.error.String("Operation not support for floppy disk drives."); context.error.Ln;
END;
END;
END ChangeType;
PROCEDURE Delete*(context : Commands.Context);
VAR
delete : Lib.DeletePartition;
selection : Lib.Selection;
type : LONGINT;
BEGIN
IF GetSelection(context, FALSE, selection) THEN
IF ~selection.disk.isDiskette THEN
IF context.arg.GetInteger(type, FALSE) & (type > 0) & (type < 256) THEN
NEW(delete, selection.disk, selection.partition, context.out);
delete.SetParameters(type);
delete.SetBlockingStart;
ELSE context.error.String("Expected parameters: dev#part type sizeMB, error while parsing type"); context.error.Ln;
END;
ELSE context.error.String("Operation not supported for floppy disks"); context.error.Ln;
END;
END;
END Delete;
PROCEDURE Create*(context : Commands.Context);
VAR
create : Lib.CreatePartition;
selection : Lib.Selection;
type, size : LONGINT;
BEGIN
IF GetSelection(context, FALSE, selection) THEN
IF ~selection.disk.isDiskette THEN
IF context.arg.GetInteger(type, FALSE) & (type > 0) & (type < 256) THEN
IF context.arg.GetInteger(size, FALSE) & (size > 0) THEN
NEW(create, selection.disk, selection.partition, context.out);
create.SetParameters(size, type, FALSE);
create.SetBlockingStart;
ELSE context.error.String("Expected parameters: dev#part type sizeMB, error while parsing size"); context.error.Ln;
END;
ELSE context.error.String("Expected parameters: dev#part type sizeMB, error while parsing type"); context.error.Ln;
END;
ELSE context.error.String("Operation not supported on floppy disks"); context.error.Ln;
END;
END;
END Create;
PROCEDURE Activate*(context : Commands.Context);
BEGIN
ChangeActiveBit(TRUE, context);
END Activate;
PROCEDURE Deactivate*(context : Commands.Context);
BEGIN
ChangeActiveBit(FALSE, context);
END Deactivate;
PROCEDURE ChangeActiveBit(active : BOOLEAN; context : Commands.Context);
VAR
setFlags : Lib.SetFlags;
selection : Lib.Selection;
BEGIN
IF GetSelection(context, TRUE, selection) THEN
IF ~selection.disk.isDiskette THEN
NEW(setFlags, selection.disk, selection.partition, context.out);
setFlags.SetParameters(active);
setFlags.SetBlockingStart;
ELSE
context.error.String("Operation not supported for floppy disks"); context.error.Ln;
END;
END;
END ChangeActiveBit;
PROCEDURE FileToPartition*(context : Commands.Context);
VAR
fileToPartition : Lib.FileToPartition;
filename : ARRAY 128 OF CHAR;
block, numblocks : LONGINT;
selection : Lib.Selection;
BEGIN
IF GetSelection(context, TRUE, selection) THEN
IF context.arg.GetString(filename) THEN
IF context.arg.GetInteger(block, FALSE) THEN
IF ~context.arg.GetInteger(numblocks, FALSE) THEN
context.error.String("Exspected parameters: dev#part filename [block numblocks], failed to parse numblocks"); context.error.Ln;
RETURN;
END;
ELSE
block := -1; numblocks := -1;
END;
NEW(fileToPartition, selection.disk, selection.partition, context.out);
fileToPartition.SetParameters(filename, block, numblocks);
fileToPartition.SetBlockingStart;
ELSE
context.error.String("Exspected parameters: dev#part name [block numblocks], failed to parse filename"); context.error.Ln;
END;
END;
END FileToPartition;
PROCEDURE PartitionToFile*(context : Commands.Context);
VAR
partitionToFile : Lib.PartitionToFile;
filename : ARRAY 128 OF CHAR;
block, numblocks : LONGINT;
selection : Lib.Selection;
BEGIN
IF GetSelection(context, TRUE, selection) THEN
IF context.arg.GetString(filename) THEN
IF context.arg.GetInteger(block, FALSE) THEN
IF ~context.arg.GetInteger(numblocks, FALSE) THEN
context.error.String("Exspected parameters: dev#part filename [block numblocks], failed to parse numblocks"); context.error.Ln;
RETURN;
END;
ELSE
block := -1; numblocks := -1;
END;
NEW(partitionToFile, selection.disk, selection.partition, context.out);
partitionToFile.SetParameters(filename, block, numblocks);
partitionToFile.SetBlockingStart;
context.out.String("Partitions UID "); context.out.Int(partitionToFile.uid, 0); context.out.String(": Started PartitionToFile on ");
context.out.String(partitionToFile.diskpartString); context.out.Ln;
ELSE context.error.String("Exspected parameters: dev#part name [block numblocks], failed to parse filename"); context.error.Ln;
END;
END;
END PartitionToFile;
PROCEDURE WriteMBR*(context : Commands.Context);
VAR
writeMBR : Lib.WriteMBR;
filename, destroy : ARRAY 128 OF CHAR;
selection : Lib.Selection;
BEGIN
IF GetSelection(context, FALSE, selection) THEN
IF ~selection.disk.isDiskette THEN
IF selection.partition = 0 THEN
IF context.arg.GetString(filename) THEN
NEW(writeMBR, selection.disk, selection.partition, context.out);
IF context.arg.GetString(destroy) & (destroy = "DESTROY") THEN
writeMBR.SetParameters(filename, FALSE, FALSE);
ELSE
writeMBR.SetParameters(filename, TRUE, FALSE);
END;
writeMBR.SetBlockingStart;
ELSE context.error.String("Expected parameters: dev#0 filename, failed to parse filename"); context.error.Ln;
END;
ELSE context.error.String("Expected parameters: dev#0 filename, partition is not 0"); context.error.Ln;
END;
ELSE context.error.String("Operation not supported for floppy disks"); context.error.Ln;
END;
END;
END WriteMBR;
PROCEDURE UpdateBootLoader*(context : Commands.Context);
VAR
updateLoader : Lib.UpdateBootLoader;
selection : Lib.Selection;
filename : Files.FileName;
BEGIN
IF GetSelection(context, FALSE, selection) THEN
IF context.arg.GetString(filename) THEN
NEW(updateLoader, selection.disk, selection.partition, context.out);
updateLoader.SetParameters(filename);
updateLoader.SetBlockingStart;
ELSE
context.error.String("Expected parameters: dev#part bootloader"); context.error.Ln;
END;
END;
END UpdateBootLoader;
PROCEDURE InstallBootManager*(context : Commands.Context);
VAR installBootManager : Lib.InstallBootManager; selection : Lib.Selection; mbrFile, tailFile : Files.FileName;
BEGIN
IF GetSelection(context, FALSE, selection) THEN
IF ~context.arg.GetString(mbrFile) THEN mbrFile := BootManagerMBRFile; END;
IF ~context.arg.GetString(tailFile) THEN tailFile := BootManagerTailFile; END;
NEW(installBootManager, selection.disk, selection.partition, context.out);
installBootManager.SetParameters(mbrFile, tailFile);
installBootManager.SetBlockingStart;
END;
END InstallBootManager;
PROCEDURE ShowBlockCallback(text : Texts.Text);
VAR string : Strings.String;
BEGIN
text.AcquireRead;
NEW(string, text.GetLength()); TextUtilities.TextToStr(text, string^);
text.ReleaseRead;
KernelLog.String(string^); KernelLog.Ln;
END ShowBlockCallback;
PROCEDURE ShowBlocks*(context : Commands.Context);
VAR
showBlocks : Lib.ShowBlocks;
block, numblocks : LONGINT;
selection : Lib.Selection;
BEGIN
IF GetSelection(context, FALSE, selection) THEN
IF context.arg.GetInteger(block, FALSE) THEN
IF ~context.arg.GetInteger(numblocks, FALSE) THEN
numblocks := -1;
END;
NEW(showBlocks, selection.disk, selection.partition, context.out);
showBlocks.SetParameters(block, numblocks);
showBlocks.SetCallback(ShowBlockCallback);
showBlocks.SetBlockingStart;
ELSE
context.error.String("Exspected parameters: dev#part block [numblocks], failed to parse block"); context.error.Ln;
END;
END;
END ShowBlocks;
PROCEDURE Eject*(context : Commands.Context);
VAR
plugin : Plugins.Plugin;
dev : Disks.Device;
name : ARRAY 32 OF CHAR;
temp: ARRAY 256 OF CHAR;
BEGIN
IF context.arg.GetString(name) THEN
plugin := Disks.registry.Get(name);
IF plugin # NIL THEN
dev := plugin (Disks.Device);
Lib.Eject(dev, temp); context.out.String(temp); context.out.Ln;
ELSE
context.error.String("Device "); context.error.String(name); context.error.String(" not found"); context.error.Ln;
END;
ELSE
context.error.String("Exspected parameters: dev"); context.error.Ln;
END;
END Eject;
PROCEDURE Unsafe*(context : Commands.Context);
BEGIN
Lib.safe := FALSE;
context.out.String("NOW in UNSAFE mode!"); context.out.Ln;
END Unsafe;
PROCEDURE Safe*(context : Commands.Context);
BEGIN
Lib.safe := TRUE;
context.out.String("Now in safe mode"); context.out.Ln;
END Safe;
PROCEDURE Show*(context : Commands.Context);
VAR
diskTable : Lib.Disks; disk : Lib.Disk;
par : ARRAY 10 OF CHAR;
verbose : BOOLEAN;
i : LONGINT;
temp : ARRAY 256 OF CHAR;
BEGIN
par := ""; context.arg.SkipWhitespace; context.arg.String(par);
verbose := (par = "detail");
Lib.diskModel.Update;
Lib.diskModel.Acquire;
diskTable := Lib.diskModel.disks;
IF diskTable # NIL THEN
FOR i := 0 TO LEN(diskTable)-1 DO
disk := diskTable[i];
ShowDevice(context, disk, verbose);
IF disk.res # Disks.MediaMissing THEN
IF (disk.table # NIL) THEN
ShowTable(context, disk, disk.table, verbose)
ELSE
Lib.GetErrorMsg("Error", disk.res, temp); context.error.String(temp); context.error.Ln;
END
END;
context.error.Ln;
END;
ELSE
context.error.String("No Devices found"); context.error.Ln;
END;
Lib.diskModel.Release;
END Show;
PROCEDURE ShowDevice(context : Commands.Context; disk: Lib.Disk; verbose: BOOLEAN);
VAR temp: ARRAY 256 OF CHAR;
BEGIN
context.out.String("Disk: "); context.out.String(disk.device.name); context.out.String(", ");
IF disk.res = Disks.Ok THEN
Lib.WriteK(context.out, ENTIER(disk.size * 1.0 * disk.device.blockSize / 1024));
IF verbose THEN
context.out.String(" = "); context.out.Int(disk.size, 1);
context.out.String(" * "); context.out.Int(disk.device.blockSize,1);
END
ELSE
Lib.GetErrorMsg("GetSize failed", disk.res, temp); context.error.String(temp);
END;
IF Disks.Removable IN disk.device.flags THEN context.out.String(", removable") END;
IF Disks.ReadOnly IN disk.device.flags THEN context.out.String(", read-only") END;
IF verbose THEN
IF disk.res # Disks.MediaMissing THEN
context.out.String(", ");
IF disk.gres = Disks.Ok THEN
context.out.String("CHS: "); context.out.Int(disk.geo.cyls, 1); context.out.String("*");
context.out.Int(disk.geo.hds, 1); context.out. String("*"); context.out.Int(disk.geo.spt, 1);
ELSE
Lib.GetErrorMsg("GetCHS: ", disk.gres, temp); context.error.String(temp);
END
END
END;
IF disk.device.desc # "" THEN context.out.String(", "); context.out.String(disk.device.desc) END;
IF verbose THEN context.out.String(", mntcnt="); context.out.Int(disk.device.openCount, 1) END;
context.out.Ln;
END ShowDevice;
PROCEDURE ShowTable( context : Commands.Context; disk: Lib.Disk; table: Disks.PartitionTable; verbose: BOOLEAN);
VAR j: LONGINT; r: LONGREAL; ugly : ARRAY 10 OF CHAR; temp : ARRAY 128 OF CHAR; ignore : LONGINT;
BEGIN
FOR j := 0 TO LEN(table)-1 DO
r := (table[j].size * 1.0D0 * disk.device.blockSize) / (1024*1024);
Lib.WritePart(context.out, disk.device, j);
IF verbose THEN
context.out.Int(table[j].start, 12);
context.out.Int(table[j].size, 12)
END;
Strings.FloatToStr(r, 6, 1, 0, ugly);
IF r < 10 THEN context.out.String(ugly);
ELSE context.out.Int(ENTIER(r), 6)
END;
context.out.String(" MB ");
IF (table[j].type >= 1) & (table[j].type <= 255) THEN
context.out.Int(table[j].type, 3)
ELSE
context.out.String("---")
END;
context.out.Char(" ");
IF (j # 0) & ~(Disks.Primary IN table[j].flags) THEN context.out.String( " | ") END;
IF Disks.Boot IN table[j].flags THEN context.out.String(" * ") END;
Lib.WriteType(table[j].type, temp, ignore); context.out.String(temp);
IF verbose THEN
IF Disks.Mounted IN table[j].flags THEN context.out.String(" [mounted]") END
END;
context.out.Ln;
END
END ShowTable;
PROCEDURE ShowAosFSLimits*(context : Commands.Context);
BEGIN
Lib.ShowAosFSLimits;
END ShowAosFSLimits;
PROCEDURE UpdateDiskModel*(context : Commands.Context);
BEGIN
Lib.diskModel.Update;
context.out.String("Disk model updated."); context.out.Ln;
END UpdateDiskModel;
PROCEDURE GetSelection*(context : Commands.Context; check : BOOLEAN; VAR selection : Lib.Selection) : BOOLEAN;
VAR devpart : ARRAY 32 OF CHAR;
BEGIN
selection.disk.device := NIL; selection.partition := -1;
IF ~context.arg.GetString(devpart) THEN
context.error.String("Expected parameters: dev#part"); context.error.Ln; context.error.Update;
RETURN FALSE;
END;
context.arg.SkipWhitespace;
IF Strings.Match("Diskette*", devpart) THEN
check := FALSE;
END;
Lib.diskModel.Update;
IF Lib.diskModel.GetDisk(devpart, selection, check) THEN
IF Trace THEN
KernelLog.String("Partitions: Command line selection: "); KernelLog.String(selection.disk.device.name);
KernelLog.Char("#"); KernelLog.Int(selection.partition, 0); KernelLog.Ln;
END;
RETURN TRUE;
ELSE
context.error.String("Partition "); context.error.String(devpart); context.out.String(" not found."); context.error.Ln;
context.error.Update;
END;
RETURN FALSE;
END GetSelection;
END Partitions.
SystemTools.Free DiskBenchmark Partitions ~