Skip to content

Commit

Permalink
Add support for formatting non-rdb partitions. Update information dis…
Browse files Browse the repository at this point in the history
…played for rdb fs export command
  • Loading branch information
henrikstengaard committed Dec 6, 2022
1 parent 2215133 commit 2030f5c
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 22 deletions.
4 changes: 2 additions & 2 deletions src/Hst.Imager.ConsoleApp/CommandHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -371,10 +371,10 @@ public static async Task RdbPartImport(string sourcePath, string destinationPath
await Execute(command);
}

public static async Task RdbPartFormat(string path, int partitionNumber, string name)
public static async Task RdbPartFormat(string path, int partitionNumber, string name, bool nonRdb, string chs, string dosType)
{
await Execute(new RdbPartFormatCommand(GetLogger<RdbInitCommand>(), GetCommandHelper(),
await GetPhysicalDrives(), path, partitionNumber, name));
await GetPhysicalDrives(), path, partitionNumber, name, nonRdb, chs, dosType));
}

public static async Task RdbPartKill(string path, int partitionNumber, string hexBootBytes)
Expand Down
18 changes: 17 additions & 1 deletion src/Hst.Imager.ConsoleApp/RdbCommandFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -567,12 +567,28 @@ private static Command CreateRdbPartFormat()
name: "VolumeName",
description: "Name of the volume (e.g. Workbench).");

var nonRdbOption = new Option<bool>(
new[] { "--non-rdb" },
description: "Set non-RDB.",
getDefaultValue: () => false);

var chsOption = new Option<string>(
new[] { "-chs" },
description: "Format from cylinders, heads and sectors. Optional for non-RDB partition.");

var dosTypeOption = new Option<string>(
new[] { "--dos-type", "-dt" },
description: "DOS type for the partition to use (e.g. DOS3, PFS3). Required for non-RDB partition.");

var rdbPartFormatCommand = new Command("format", "Format partition.");
rdbPartFormatCommand.SetHandler(CommandHandler.RdbPartFormat, pathArgument, partitionNumber,
volumeNameArgument);
volumeNameArgument, nonRdbOption, chsOption, dosTypeOption);
rdbPartFormatCommand.AddArgument(pathArgument);
rdbPartFormatCommand.AddArgument(partitionNumber);
rdbPartFormatCommand.AddArgument(volumeNameArgument);
rdbPartFormatCommand.AddOption(nonRdbOption);
rdbPartFormatCommand.AddOption(chsOption);
rdbPartFormatCommand.AddOption(dosTypeOption);

return rdbPartFormatCommand;
}
Expand Down
13 changes: 6 additions & 7 deletions src/Hst.Imager.Core/Commands/RdbFsExportCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,7 @@ public override async Task<Result> Execute(CancellationToken token)
}

var fileSystemHeaderBlocks = rigidDiskBlock.FileSystemHeaderBlocks.ToList();

OnDebugMessage($"Exporting file system number '{fileSystemNumber}'");


if (fileSystemNumber < 1 || fileSystemNumber > fileSystemHeaderBlocks.Count)
{
return new Result(new Error($"Invalid file system number '{fileSystemNumber}'"));
Expand All @@ -68,10 +66,11 @@ public override async Task<Result> Execute(CancellationToken token)
var fileSystemBytes = fileSystemHeaderBlock.LoadSegBlocks.SelectMany(x => x.Data).ToArray();
long fileSystemSize = fileSystemBytes.Length;

OnDebugMessage($"DOS type '0x{fileSystemHeaderBlock.DosType.FormatHex()}' ({fileSystemHeaderBlock.DosType.FormatDosType()})");
OnDebugMessage($"Version '{fileSystemHeaderBlock.VersionFormatted}'");
OnDebugMessage($"Size '{fileSystemSize.FormatBytes()}' ({fileSystemSize} bytes)");
OnDebugMessage($"File system name '{fileSystemHeaderBlock.FileSystemName}'");
OnInformationMessage($"- File system number '{fileSystemNumber}'");
OnInformationMessage($"- DOS type '0x{fileSystemHeaderBlock.DosType.FormatHex()}' ({fileSystemHeaderBlock.DosType.FormatDosType()})");
OnInformationMessage($"- Version '{fileSystemHeaderBlock.VersionFormatted}'");
OnInformationMessage($"- Size '{fileSystemSize.FormatBytes()}' ({fileSystemSize} bytes)");
OnInformationMessage($"- File system name '{fileSystemHeaderBlock.FileSystemName}'");

OnDebugMessage($"Writing file system to '{fileSystemPath}'");
await File.WriteAllBytesAsync(fileSystemPath, fileSystemBytes, token);
Expand Down
125 changes: 113 additions & 12 deletions src/Hst.Imager.Core/Commands/RdbPartFormatCommand.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
namespace Hst.Imager.Core.Commands
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Amiga.Extensions;
using Amiga.FileSystems.FastFileSystem;
using Amiga.FileSystems.Pfs3;
using Amiga.RigidDiskBlocks;
using Extensions;
using Hst.Core;
using Hst.Core.Extensions;
using Microsoft.Extensions.Logging;
Expand All @@ -19,22 +22,64 @@ public class RdbPartFormatCommand : CommandBase
private readonly string path;
private readonly int partitionNumber;
private readonly string name;
private readonly bool nonRdb;
private readonly string chs;
private readonly string dosType;

public RdbPartFormatCommand(ILogger<RdbInitCommand> logger, ICommandHelper commandHelper,
IEnumerable<IPhysicalDrive> physicalDrives, string path, int partitionNumber, string name)
IEnumerable<IPhysicalDrive> physicalDrives, string path, int partitionNumber, string name, bool nonRdb,
string chs, string dosType)
{
this.logger = logger;
this.commandHelper = commandHelper;
this.physicalDrives = physicalDrives;
this.path = path;
this.partitionNumber = partitionNumber;
this.name = name;
this.nonRdb = nonRdb;
this.chs = chs;
this.dosType = dosType;
}

public override async Task<Result> Execute(CancellationToken token)
{
DiskGeometry nonRdbDiskGeometry = new DiskGeometry
{
Heads = 16,
Sectors = 63
};

if (nonRdb && string.IsNullOrWhiteSpace(dosType))
{
return new Result(new Error($"DOS type is required for formatting a non-RDB partition"));
}

if (nonRdb && !string.IsNullOrWhiteSpace(chs))
{
var values = chs.Split(',', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries);

if (values.Length != 3)
{
return new Result(new Error($"Invalid cylinders, heads and sectors value '{chs}'"));
}

if (!int.TryParse(values[0], out var cylinders) || !int.TryParse(values[1], out var heads) ||
!int.TryParse(values[2], out var sectors))
{
return new Result(new Error($"Invalid cylinders, heads and sectors value '{chs}'"));
}

nonRdbDiskGeometry = new DiskGeometry
{
DiskSize = (long)cylinders * heads * sectors * 512,
Cylinders = cylinders,
Heads = heads,
Sectors = sectors
};
}

OnInformationMessage($"Formatting partition in Rigid Disk Block at '{path}'");

OnDebugMessage($"Opening '{path}' as writable");

var mediaResult = commandHelper.GetWritableMedia(physicalDrives, path, allowPhysicalDrive: true);
Expand All @@ -44,32 +89,88 @@ public override async Task<Result> Execute(CancellationToken token)
}

using var media = mediaResult.Value;

if (nonRdb && media.IsPhysicalDrive)
{
return new Result(new Error($"Physical drives doesn't support non RDB"));
}

await using var stream = media.Stream;

OnDebugMessage("Reading Rigid Disk Block");
List<PartitionBlock> partitionBlocks;
if (!nonRdb)
{
OnDebugMessage("Reading Rigid Disk Block");

var rigidDiskBlock = await commandHelper.GetRigidDiskBlock(stream);

var rigidDiskBlock = await commandHelper.GetRigidDiskBlock(stream);
if (rigidDiskBlock == null)
{
return new Result(new Error("Rigid Disk Block not found"));
}

if (rigidDiskBlock == null)
partitionBlocks = rigidDiskBlock.PartitionBlocks.ToList();
}
else
{
return new Result(new Error("Rigid Disk Block not found"));
var cylinderSize = (long)nonRdbDiskGeometry.Heads * nonRdbDiskGeometry.Sectors * 512;
var cylinders = nonRdbDiskGeometry.Cylinders == 0
? Convert.ToInt64((double)stream.Length / cylinderSize)
: nonRdbDiskGeometry.Cylinders;
var partitionSize = cylinderSize * cylinders;

if (stream.Length != partitionSize)
{
stream.SetLength(partitionSize);
}

partitionBlocks = new List<PartitionBlock>
{
new PartitionBlock
{
DriveName = "DH0",
DosType = DosTypeHelper.FormatDosType(dosType),
Surfaces = (uint)nonRdbDiskGeometry.Heads,
BlocksPerTrack = (uint)nonRdbDiskGeometry.Sectors,
Reserved = 2,
PartitionSize = partitionSize,
LowCyl = 0,
HighCyl = (uint)(cylinders - 1),
FileSystemBlockSize = 512
}
};
}

var partitionBlocks = rigidDiskBlock.PartitionBlocks.ToList();

OnDebugMessage($"Formatting partition number '{partitionNumber}':");

if (partitionNumber < 1 || partitionNumber > partitionBlocks.Count)
{
return new Result(new Error($"Invalid partition number '{partitionNumber}'"));
}

var partitionBlock = partitionBlocks[partitionNumber - 1];

OnInformationMessage($"- Name '{partitionBlock.DriveName}'");
OnInformationMessage($"- DOS type '0x{partitionBlock.DosType.FormatHex()}' ({partitionBlock.DosType.FormatDosType()})");
OnInformationMessage(
$"- Size '{partitionBlock.PartitionSize.FormatBytes()}' ({partitionBlock.PartitionSize} bytes)");
if (nonRdb)
{
OnInformationMessage($"- Cylinders '{(partitionBlock.HighCyl - partitionBlock.LowCyl + 1)}'");
OnInformationMessage($"- Heads '{partitionBlock.Surfaces}'");
OnInformationMessage($"- Sectors '{partitionBlock.BlocksPerTrack}'");
}

OnInformationMessage($"- Low Cyl '{partitionBlock.LowCyl}'");
OnInformationMessage($"- High Cyl '{partitionBlock.HighCyl}'");
OnInformationMessage($"- Reserved '{partitionBlock.Reserved}'");
if (!nonRdb)
{
OnInformationMessage($"- Name '{partitionBlock.DriveName}'");
}

OnInformationMessage(
$"- DOS type '0x{partitionBlock.DosType.FormatHex()}' ({partitionBlock.DosType.FormatDosType()})");
OnInformationMessage($"- Volume name '{name}'");

switch (partitionBlock.DosTypeFormatted)
{
case "DOS\\1":
Expand Down

0 comments on commit 2030f5c

Please sign in to comment.