diff --git a/DiskArc/Arc/AppleLink.cs b/DiskArc/Arc/AppleLink.cs
index c270fb2..76e44fe 100644
--- a/DiskArc/Arc/AppleLink.cs
+++ b/DiskArc/Arc/AppleLink.cs
@@ -293,5 +293,8 @@ public void AddPart(IFileEntry entry, FilePart part, IPartSource partSource,
public void DeletePart(IFileEntry entry, FilePart part) {
throw new InvalidOperationException("This archive format is read-only");
}
+
+ // IArchive
+ public string? DebugDump() { return null; }
}
}
diff --git a/DiskArc/Arc/AppleSingle.cs b/DiskArc/Arc/AppleSingle.cs
index 801f4b1..38e4f17 100644
--- a/DiskArc/Arc/AppleSingle.cs
+++ b/DiskArc/Arc/AppleSingle.cs
@@ -429,5 +429,8 @@ private void CheckModAccess(IFileEntry ientry) {
Debug.Assert(entry.ChangeObject != null);
}
}
+
+ // IArchive
+ public string? DebugDump() { return null; }
}
}
diff --git a/DiskArc/Arc/AudioRecording.cs b/DiskArc/Arc/AudioRecording.cs
index eb8d07e..272865f 100644
--- a/DiskArc/Arc/AudioRecording.cs
+++ b/DiskArc/Arc/AudioRecording.cs
@@ -397,5 +397,8 @@ public void AddPart(IFileEntry entry, FilePart part, IPartSource partSource,
public void DeletePart(IFileEntry entry, FilePart part) {
throw new InvalidOperationException("This archive format is read-only");
}
+
+ // IArchive
+ public string? DebugDump() { return null; }
}
}
diff --git a/DiskArc/Arc/Binary2.cs b/DiskArc/Arc/Binary2.cs
index 8200068..6341b79 100644
--- a/DiskArc/Arc/Binary2.cs
+++ b/DiskArc/Arc/Binary2.cs
@@ -614,6 +614,9 @@ public void DeletePart(IFileEntry ientry, FilePart part) {
IsReconstructionNeeded = true;
}
+ // IArchive
+ public string? DebugDump() { return null; }
+
///
/// Confirms that we are allowed to modify this entry.
///
diff --git a/DiskArc/Arc/GZip.cs b/DiskArc/Arc/GZip.cs
index eca527a..e8e1186 100644
--- a/DiskArc/Arc/GZip.cs
+++ b/DiskArc/Arc/GZip.cs
@@ -373,5 +373,8 @@ public static string StripGZExtension(string pathName) {
return pathName;
}
}
+
+ // IArchive
+ public string? DebugDump() { return null; }
}
}
diff --git a/DiskArc/Arc/MacBinary.cs b/DiskArc/Arc/MacBinary.cs
index 42d5e9f..5fd1215 100644
--- a/DiskArc/Arc/MacBinary.cs
+++ b/DiskArc/Arc/MacBinary.cs
@@ -227,5 +227,8 @@ public void AddPart(IFileEntry entry, FilePart part, IPartSource partSource,
public void DeletePart(IFileEntry entry, FilePart part) {
throw new InvalidOperationException("This archive format is read-only");
}
+
+ // IArchive
+ public string? DebugDump() { return null; }
}
}
diff --git a/DiskArc/Arc/NuFX.cs b/DiskArc/Arc/NuFX.cs
index 4d1b1df..1fa98d0 100644
--- a/DiskArc/Arc/NuFX.cs
+++ b/DiskArc/Arc/NuFX.cs
@@ -747,6 +747,9 @@ public void DeletePart(IFileEntry ientry, FilePart part) {
((NuFX_FileEntry)ientry).DeletePart(part);
}
+ // IArchive
+ public string? DebugDump() { return null; }
+
///
/// Confirms that we are allowed to modify this entry.
///
diff --git a/DiskArc/Arc/Zip.cs b/DiskArc/Arc/Zip.cs
index e7d26ce..bfcb5f1 100644
--- a/DiskArc/Arc/Zip.cs
+++ b/DiskArc/Arc/Zip.cs
@@ -664,6 +664,9 @@ public void DeletePart(IFileEntry ientry, FilePart part) {
((Zip_FileEntry)ientry).DeletePart();
}
+ // IArchive
+ public string? DebugDump() { return null; }
+
///
/// Confirms that we are allowed to modify this entry.
///
diff --git a/DiskArc/FS/CPM.cs b/DiskArc/FS/CPM.cs
index a8dbb99..d0a9321 100644
--- a/DiskArc/FS/CPM.cs
+++ b/DiskArc/FS/CPM.cs
@@ -427,6 +427,9 @@ public override string ToString() {
return "[CP/M" + rawStr + "]";
}
+ // IFileSystem
+ public string? DebugDump() { return null; }
+
// IDisposable generic finalizer.
~CPM() {
Dispose(false);
diff --git a/DiskArc/FS/DOS.cs b/DiskArc/FS/DOS.cs
index 271c29c..685002d 100644
--- a/DiskArc/FS/DOS.cs
+++ b/DiskArc/FS/DOS.cs
@@ -383,6 +383,9 @@ public override string ToString() {
return "[DOS " + id + "]";
}
+ // IFileSystem
+ public string? DebugDump() { return null; }
+
// IDisposable generic finalizer.
~DOS() {
diff --git a/DiskArc/FS/Gutenberg.cs b/DiskArc/FS/Gutenberg.cs
index 488e3cb..7710416 100644
--- a/DiskArc/FS/Gutenberg.cs
+++ b/DiskArc/FS/Gutenberg.cs
@@ -173,6 +173,9 @@ public override string ToString() {
return "[Gutenberg (" + id + ")]";
}
+ // IFileSystem
+ public string? DebugDump() { return null; }
+
// IDisposable generic finalizer.
~Gutenberg() {
Dispose(false);
diff --git a/DiskArc/FS/HFS.cs b/DiskArc/FS/HFS.cs
index 7907fee..ac4a48a 100644
--- a/DiskArc/FS/HFS.cs
+++ b/DiskArc/FS/HFS.cs
@@ -225,6 +225,9 @@ public override string ToString() {
return "[HFS vol: " + id + "]";
}
+ // IFileSystem
+ public string? DebugDump() { return HFS_Dump.Dump(this); }
+
// IDisposable generic finalizer.
~HFS() {
Dispose(false);
diff --git a/DiskArc/FS/HFS_Dump.cs b/DiskArc/FS/HFS_Dump.cs
index 51fb217..5c3708a 100644
--- a/DiskArc/FS/HFS_Dump.cs
+++ b/DiskArc/FS/HFS_Dump.cs
@@ -53,6 +53,7 @@ public static string Dump(HFS fs) {
sb.AppendLine("Total Files : " + mdb.FileCount);
sb.AppendLine("Total Dirs : " + mdb.DirCount);
sb.AppendLine("Next CNID : " + mdb.NextCatalogID);
+ sb.AppendLine("Blessed system CNID: " + mdb.FndrInfo[0]);
sb.AppendLine("Vol Bitmap Start : " + mdb.VolBitmapStart);
sb.AppendLine("Free Blocks : " + mdb.FreeBlocks);
diff --git a/DiskArc/FS/HFS_MDB.cs b/DiskArc/FS/HFS_MDB.cs
index d9ae281..4fff80e 100644
--- a/DiskArc/FS/HFS_MDB.cs
+++ b/DiskArc/FS/HFS_MDB.cs
@@ -212,6 +212,13 @@ public uint DirCount {
/// drFndrInfo: information used by the Macintosh Finder.
private uint[] drFndrInfo = new uint[8];
+ public uint[] FndrInfo {
+ get {
+ uint[] copy = new uint[8];
+ Array.Copy(drFndrInfo, copy, drFndrInfo.Length);
+ return copy;
+ }
+ }
/// drVCSize / drEmbedSigWord: originally, size (in allocation blocks) of the
/// volume cache. Changed to embedded volume signature.
diff --git a/DiskArc/FS/MFS.cs b/DiskArc/FS/MFS.cs
index f123208..6480334 100644
--- a/DiskArc/FS/MFS.cs
+++ b/DiskArc/FS/MFS.cs
@@ -163,6 +163,9 @@ public override string ToString() {
return "[MFS (" + id + ")]";
}
+ // IFileSystem
+ public string? DebugDump() { return null; }
+
// IDisposable generic finalizer.
~MFS() {
Dispose(false);
diff --git a/DiskArc/FS/Pascal.cs b/DiskArc/FS/Pascal.cs
index 5077481..d21a68c 100644
--- a/DiskArc/FS/Pascal.cs
+++ b/DiskArc/FS/Pascal.cs
@@ -253,6 +253,9 @@ public override string ToString() {
return "[Pascal vol '" + id + "']";
}
+ // IFileSystem
+ public string? DebugDump() { return null; }
+
// IDisposable generic finalizer.
~Pascal() {
Dispose(false);
diff --git a/DiskArc/FS/ProDOS.cs b/DiskArc/FS/ProDOS.cs
index 994bf82..f8d1b61 100644
--- a/DiskArc/FS/ProDOS.cs
+++ b/DiskArc/FS/ProDOS.cs
@@ -246,6 +246,9 @@ public override string ToString() {
return "[ProDOS vol '" + id + "']";
}
+ // IFileSystem
+ public string? DebugDump() { return null; }
+
// IDisposable generic finalizer.
~ProDOS() {
Dispose(false);
diff --git a/DiskArc/FS/RDOS.cs b/DiskArc/FS/RDOS.cs
index 8804902..0bb3f1d 100644
--- a/DiskArc/FS/RDOS.cs
+++ b/DiskArc/FS/RDOS.cs
@@ -254,6 +254,9 @@ public override string ToString() {
return "[RDOS (" + id + ")]";
}
+ // IFileSystem
+ public string? DebugDump() { return null; }
+
// IDisposable generic finalizer.
~RDOS() {
Dispose(false);
diff --git a/DiskArc/IArchive.cs b/DiskArc/IArchive.cs
index cf6b45c..abfb3ba 100644
--- a/DiskArc/IArchive.cs
+++ b/DiskArc/IArchive.cs
@@ -296,5 +296,11 @@ void AddPart(IFileEntry entry, Defs.FilePart part, IPartSource partSource,
/// This type of archive does not allow this
/// part.
void DeletePart(IFileEntry entry, Defs.FilePart part);
+
+ ///
+ /// Generates detailed human-readable information about the archive.
+ ///
+ /// Formatted text, or null if not implemented.
+ string? DebugDump();
}
}
diff --git a/DiskArc/IFileSystem.cs b/DiskArc/IFileSystem.cs
index 13df2f0..884331a 100644
--- a/DiskArc/IFileSystem.cs
+++ b/DiskArc/IFileSystem.cs
@@ -399,5 +399,11 @@ enum FileAccessMode {
/// Closes all open files.
///
void CloseAll();
+
+ ///
+ /// Generates detailed human-readable information about the filesystem.
+ ///
+ /// Formatted text, or null if not implemented.
+ string? DebugDump();
}
}
diff --git a/cp2/CP2Main.cs b/cp2/CP2Main.cs
index ed1d8b8..7bf6852 100644
--- a/cp2/CP2Main.cs
+++ b/cp2/CP2Main.cs
@@ -247,11 +247,16 @@ public Command(string[] names, string summary, string usage, bool needsArchive,
usage: "",
needsArchive: false, acceptsMultipleArgs: false,
handler: HandleCrash),
+ new Command(names: new string[] { "debug-show-info" },
+ summary: "displays detailed archive-specific information",
+ usage: "",
+ needsArchive: true, acceptsMultipleArgs: false,
+ handler: DebugCmd.HandleShowInfo),
new Command(names: new string[] { "debug-wtree" },
summary: "displays work tree for an archive",
usage: "",
needsArchive: true, acceptsMultipleArgs: false,
- handler: Tests.DebugWorkTree.HandleDumpTree),
+ handler: DebugCmd.HandleDumpWTree),
new Command(names: new string[] { "debug-test" },
summary: "executes program tests",
usage: "",
diff --git a/cp2/Tests/DebugWorkTree.cs b/cp2/DebugCmd.cs
similarity index 56%
rename from cp2/Tests/DebugWorkTree.cs
rename to cp2/DebugCmd.cs
index d0d8832..9a21571 100644
--- a/cp2/Tests/DebugWorkTree.cs
+++ b/cp2/DebugCmd.cs
@@ -17,29 +17,90 @@
using System.Diagnostics;
using AppCommon;
-using CommonUtil;
+using DiskArc.Arc;
+using DiskArc.Multi;
using DiskArc;
using static AppCommon.WorkTree;
-namespace cp2.Tests {
- public static class DebugWorkTree {
+namespace cp2 {
+ public static class DebugCmd {
///
- /// Handles "debug-wtree" command.
+ /// Handles "debug-show-info" command.
///
- public static bool HandleDumpTree(string cmdName, string[] args, ParamsBag parms) {
+ public static bool HandleShowInfo(string cmdName, string[] args, ParamsBag parms) {
+ Debug.Assert(args.Length == 1);
+ if (!ExtArchive.OpenExtArc(args[0], false, true, parms, out DiskArcNode? rootNode,
+ out DiskArcNode? leafNode, out object? leaf, out IFileEntry endDirEntry)) {
+ return false;
+ }
+ Debug.Assert(rootNode != null && leaf != null);
+
+ using (rootNode) {
+ string? hdrStr = null;
+ string? outStr = null;
+ if (leaf is IArchive) {
+ IArchive archive = (IArchive)leaf;
+ hdrStr = "--- " + ThingString.IArchive(archive) + " ---";
+ outStr = archive.DebugDump();
+ } else if (leaf is IDiskImage) {
+ IDiskImage disk = (IDiskImage)leaf;
+ if (disk.Contents is IFileSystem) {
+ IFileSystem fs = (IFileSystem)disk.Contents;
+ hdrStr = "--- " + ThingString.IFileSystem(fs) + " ---";
+ outStr = fs.DebugDump();
+ } else if (disk.Contents is IMultiPart) {
+ outStr = "No info available for multi-part filesystem.";
+ } else {
+ Console.Error.WriteLine("Error: disk image contents not recognized");
+ return false;
+ }
+ } else if (leaf is Partition) {
+ Partition part = (Partition)leaf;
+ if (part.FileSystem == null) {
+ part.AnalyzePartition();
+ }
+ if (part.FileSystem != null) {
+ hdrStr = "--- " + ThingString.IFileSystem(part.FileSystem) + " ---";
+ outStr = part.FileSystem.DebugDump();
+ } else {
+ outStr = "Partition has unknown contents.";
+ }
+ } else {
+ Console.Error.WriteLine("Internal issue: what is " + leaf);
+ Debug.Assert(false);
+ return false;
+ }
+ if (hdrStr != null) {
+ Console.WriteLine(hdrStr);
+ }
+ if (outStr != null) {
+ Console.WriteLine(outStr);
+ } else {
+ Console.WriteLine("Debug info not available.");
+ }
+ return true;
+ }
+ }
+
+
+ ///
+ /// Handles "debug-wtree" command. This displays the WorkTree structure, which is
+ /// only used by the GUI app.
+ ///
+ public static bool HandleDumpWTree(string cmdName, string[] args, ParamsBag parms) {
if (args.Length != 1) {
CP2Main.ShowUsage(cmdName);
return false;
}
- string extArchive = args[0];
+ string fileName = args[0]; // not processing ext-archive strings
// Include the config parameters in the closure.
DepthLimiter limiter =
delegate (DepthParentKind parentKind, DepthChildKind childKind) {
return DepthLimit(parentKind, childKind, parms.Depth);
- };
- using (WorkTree tree = new WorkTree(extArchive, limiter, true, null, parms.AppHook)) {
+ };
+ using (WorkTree tree = new WorkTree(fileName, limiter, true, null, parms.AppHook)) {
Console.Write(tree.GenerateTreeSummary());
}