Refactor AppleDOS and solves bug preventing VTOC from being retrieved as "$Vtoc".

This commit is contained in:
2017-12-22 07:05:08 +00:00
parent 0ad9da7b3a
commit 56986338be
5 changed files with 50 additions and 61 deletions

View File

@@ -47,9 +47,7 @@ namespace DiscImageChef.Filesystems.AppleDOS
/// <param name="dest">Link destination.</param> /// <param name="dest">Link destination.</param>
public override Errno ReadLink(string path, ref string dest) public override Errno ReadLink(string path, ref string dest)
{ {
if(!mounted) return Errno.AccessDenied; return !mounted ? Errno.AccessDenied : Errno.NotSupported;
return Errno.NotSupported;
} }
/// <summary> /// <summary>
@@ -97,10 +95,9 @@ namespace DiscImageChef.Filesystems.AppleDOS
if(debug) catalogMs.Write(catSectorB, 0, catSectorB.Length); if(debug) catalogMs.Write(catSectorB, 0, catSectorB.Length);
// Read the catalog sector // Read the catalog sector
CatalogSector catSector;
IntPtr catPtr = Marshal.AllocHGlobal(256); IntPtr catPtr = Marshal.AllocHGlobal(256);
Marshal.Copy(catSectorB, 0, catPtr, 256); Marshal.Copy(catSectorB, 0, catPtr, 256);
catSector = (CatalogSector)Marshal.PtrToStructure(catPtr, typeof(CatalogSector)); CatalogSector catSector = (CatalogSector)Marshal.PtrToStructure(catPtr, typeof(CatalogSector));
Marshal.FreeHGlobal(catPtr); Marshal.FreeHGlobal(catPtr);
foreach(FileEntry entry in catSector.entries.Where(entry => entry.extentTrack > 0)) { foreach(FileEntry entry in catSector.entries.Where(entry => entry.extentTrack > 0)) {

View File

@@ -33,6 +33,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace DiscImageChef.Filesystems.AppleDOS namespace DiscImageChef.Filesystems.AppleDOS
@@ -70,7 +71,6 @@ namespace DiscImageChef.Filesystems.AppleDOS
if(pathElements.Length != 1) return Errno.NotSupported; if(pathElements.Length != 1) return Errno.NotSupported;
byte[] file; byte[] file;
Errno error;
string filename = pathElements[0].ToUpperInvariant(); string filename = pathElements[0].ToUpperInvariant();
if(filename.Length > 30) return Errno.NameTooLong; if(filename.Length > 30) return Errno.NameTooLong;
@@ -78,15 +78,18 @@ namespace DiscImageChef.Filesystems.AppleDOS
string.Compare(path, "$Boot", StringComparison.InvariantCulture) == 0 || string.Compare(path, "$Boot", StringComparison.InvariantCulture) == 0 ||
string.Compare(path, "$Vtoc", StringComparison.InvariantCulture) == 0)) string.Compare(path, "$Vtoc", StringComparison.InvariantCulture) == 0))
{ {
if(string.Compare(path, "$", StringComparison.InvariantCulture) == 0) file = catalogBlocks; if(string.Compare(path, "$", StringComparison.InvariantCulture) == 0)
if(string.Compare(path, "$Vtoc", StringComparison.InvariantCulture) == 0) file = vtocBlocks; file = catalogBlocks;
else file = bootBlocks; else if(string.Compare(path, "$Vtoc", StringComparison.InvariantCulture) == 0)
file = vtocBlocks;
else
file = bootBlocks;
} }
else else
{ {
if(!fileCache.TryGetValue(filename, out file)) if(!fileCache.TryGetValue(filename, out file))
{ {
error = CacheFile(filename); Errno error = CacheFile(filename);
if(error != Errno.NoError) return error; if(error != Errno.NoError) return error;
if(!fileCache.TryGetValue(filename, out file)) return Errno.InvalidArgument; if(!fileCache.TryGetValue(filename, out file)) return Errno.InvalidArgument;
@@ -116,10 +119,9 @@ namespace DiscImageChef.Filesystems.AppleDOS
if(!fileCache.ContainsKey(filename)) return Errno.NoSuchFile; if(!fileCache.ContainsKey(filename)) return Errno.NoSuchFile;
int filesize;
FileAttributes attrs = new FileAttributes(); FileAttributes attrs = new FileAttributes();
fileSizeCache.TryGetValue(filename, out filesize); fileSizeCache.TryGetValue(filename, out int filesize);
GetAttributes(path, ref attrs); GetAttributes(path, ref attrs);
stat = new FileEntryInfo(); stat = new FileEntryInfo();
@@ -152,10 +154,8 @@ namespace DiscImageChef.Filesystems.AppleDOS
public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock)
{ {
if(!mounted) return Errno.AccessDenied;
// TODO: Not really important. // TODO: Not really important.
return Errno.NotImplemented; return !mounted ? Errno.AccessDenied : Errno.NotImplemented;
} }
Errno CacheFile(string path) Errno CacheFile(string path)
@@ -166,9 +166,7 @@ namespace DiscImageChef.Filesystems.AppleDOS
string filename = pathElements[0].ToUpperInvariant(); string filename = pathElements[0].ToUpperInvariant();
if(filename.Length > 30) return Errno.NameTooLong; if(filename.Length > 30) return Errno.NameTooLong;
ushort ts; if(!catalogCache.TryGetValue(filename, out ushort ts)) return Errno.NoSuchFile;
if(!catalogCache.TryGetValue(filename, out ts)) return Errno.NoSuchFile;
ulong lba = (ulong)(((ts & 0xFF00) >> 8) * sectorsPerTrack + (ts & 0xFF)); ulong lba = (ulong)(((ts & 0xFF00) >> 8) * sectorsPerTrack + (ts & 0xFF));
MemoryStream fileMs = new MemoryStream(); MemoryStream fileMs = new MemoryStream();
@@ -182,10 +180,9 @@ namespace DiscImageChef.Filesystems.AppleDOS
if(debug) tsListMs.Write(tsSectorB, 0, tsSectorB.Length); if(debug) tsListMs.Write(tsSectorB, 0, tsSectorB.Length);
// Read the track/sector list sector // Read the track/sector list sector
TrackSectorList tsSector;
IntPtr tsPtr = Marshal.AllocHGlobal(256); IntPtr tsPtr = Marshal.AllocHGlobal(256);
Marshal.Copy(tsSectorB, 0, tsPtr, 256); Marshal.Copy(tsSectorB, 0, tsPtr, 256);
tsSector = (TrackSectorList)Marshal.PtrToStructure(tsPtr, typeof(TrackSectorList)); TrackSectorList tsSector = (TrackSectorList)Marshal.PtrToStructure(tsPtr, typeof(TrackSectorList));
Marshal.FreeHGlobal(tsPtr); Marshal.FreeHGlobal(tsPtr);
if(tsSector.sectorOffset > expectedBlock) if(tsSector.sectorOffset > expectedBlock)
@@ -225,13 +222,9 @@ namespace DiscImageChef.Filesystems.AppleDOS
{ {
fileCache = new Dictionary<string, byte[]>(); fileCache = new Dictionary<string, byte[]>();
extentCache = new Dictionary<string, byte[]>(); extentCache = new Dictionary<string, byte[]>();
Errno error;
foreach(string file in catalogCache.Keys) foreach(Errno error in catalogCache.Keys.Select(CacheFile).Where(error => error != Errno.NoError))
{ { return error; }
error = CacheFile(file);
if(error != Errno.NoError) return error;
}
uint tracksOnBoot = 1; uint tracksOnBoot = 1;
if(!track1UsedByFiles) tracksOnBoot++; if(!track1UsedByFiles) tracksOnBoot++;

View File

@@ -48,8 +48,7 @@ namespace DiscImageChef.Filesystems.AppleDOS
if(partition.Start > 0 || imagePlugin.ImageInfo.SectorSize != 256) return false; if(partition.Start > 0 || imagePlugin.ImageInfo.SectorSize != 256) return false;
int spt; int spt;
if(imagePlugin.ImageInfo.Sectors == 455) spt = 13; spt = imagePlugin.ImageInfo.Sectors == 455 ? 13 : 16;
else spt = 16;
byte[] vtocB = imagePlugin.ReadSector((ulong)(17 * spt)); byte[] vtocB = imagePlugin.ReadSector((ulong)(17 * spt));
vtoc = new Vtoc(); vtoc = new Vtoc();
@@ -68,8 +67,7 @@ namespace DiscImageChef.Filesystems.AppleDOS
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
int spt; int spt;
if(imagePlugin.ImageInfo.Sectors == 455) spt = 13; spt = imagePlugin.ImageInfo.Sectors == 455 ? 13 : 16;
else spt = 16;
byte[] vtocB = imagePlugin.ReadSector((ulong)(17 * spt)); byte[] vtocB = imagePlugin.ReadSector((ulong)(17 * spt));
vtoc = new Vtoc(); vtoc = new Vtoc();
@@ -93,11 +91,13 @@ namespace DiscImageChef.Filesystems.AppleDOS
information = sb.ToString(); information = sb.ToString();
xmlFSType = new FileSystemType(); xmlFSType = new FileSystemType
xmlFSType.Bootable = true; {
xmlFSType.Clusters = (long)imagePlugin.ImageInfo.Sectors; Bootable = true,
xmlFSType.ClusterSize = (int)imagePlugin.ImageInfo.SectorSize; Clusters = (long)imagePlugin.ImageInfo.Sectors,
xmlFSType.Type = "Apple DOS"; ClusterSize = (int)imagePlugin.ImageInfo.SectorSize,
Type = "Apple DOS"
};
} }
} }
} }

View File

@@ -70,14 +70,13 @@ namespace DiscImageChef.Filesystems.AppleDOS
return Errno.InOutError; return Errno.InOutError;
} }
if(device.ImageInfo.Sectors == 455) sectorsPerTrack = 13; sectorsPerTrack = device.ImageInfo.Sectors == 455 ? 13 : 16;
else sectorsPerTrack = 16;
// Read the VTOC // Read the VTOC
byte[] vtocB = device.ReadSector((ulong)(17 * sectorsPerTrack)); vtocBlocks = device.ReadSector((ulong)(17 * sectorsPerTrack));
vtoc = new Vtoc(); vtoc = new Vtoc();
IntPtr vtocPtr = Marshal.AllocHGlobal(256); IntPtr vtocPtr = Marshal.AllocHGlobal(256);
Marshal.Copy(vtocB, 0, vtocPtr, 256); Marshal.Copy(vtocBlocks, 0, vtocPtr, 256);
vtoc = (Vtoc)Marshal.PtrToStructure(vtocPtr, typeof(Vtoc)); vtoc = (Vtoc)Marshal.PtrToStructure(vtocPtr, typeof(Vtoc));
Marshal.FreeHGlobal(vtocPtr); Marshal.FreeHGlobal(vtocPtr);
@@ -85,9 +84,7 @@ namespace DiscImageChef.Filesystems.AppleDOS
track2UsedByFiles = false; track2UsedByFiles = false;
usedSectors = 1; usedSectors = 1;
Errno error; Errno error = ReadCatalog();
error = ReadCatalog();
if(error != Errno.NoError) if(error != Errno.NoError)
{ {
DicConsole.DebugWriteLine("Apple DOS plugin", "Unable to read catalog."); DicConsole.DebugWriteLine("Apple DOS plugin", "Unable to read catalog.");
@@ -102,15 +99,17 @@ namespace DiscImageChef.Filesystems.AppleDOS
} }
// Create XML metadata for mounted filesystem // Create XML metadata for mounted filesystem
xmlFSType = new FileSystemType(); xmlFSType = new FileSystemType
xmlFSType.Bootable = true; {
xmlFSType.Clusters = (long)device.ImageInfo.Sectors; Bootable = true,
xmlFSType.ClusterSize = vtoc.bytesPerSector; Clusters = (long)device.ImageInfo.Sectors,
xmlFSType.Files = catalogCache.Count; ClusterSize = vtoc.bytesPerSector,
xmlFSType.FilesSpecified = true; Files = catalogCache.Count,
FilesSpecified = true,
FreeClustersSpecified = true,
Type = "Apple DOS"
};
xmlFSType.FreeClusters = xmlFSType.Clusters - usedSectors; xmlFSType.FreeClusters = xmlFSType.Clusters - usedSectors;
xmlFSType.FreeClustersSpecified = true;
xmlFSType.Type = "Apple DOS";
this.debug = debug; this.debug = debug;
mounted = true; mounted = true;
@@ -137,14 +136,16 @@ namespace DiscImageChef.Filesystems.AppleDOS
/// <param name="stat">Information about the mounted volume.</param> /// <param name="stat">Information about the mounted volume.</param>
public override Errno StatFs(ref FileSystemInfo stat) public override Errno StatFs(ref FileSystemInfo stat)
{ {
stat = new FileSystemInfo(); stat = new FileSystemInfo
stat.Blocks = (long)device.ImageInfo.Sectors; {
stat.FilenameLength = 30; Blocks = (long)device.ImageInfo.Sectors,
stat.Files = (ulong)catalogCache.Count; FilenameLength = 30,
stat.FreeBlocks = stat.Blocks - usedSectors; Files = (ulong)catalogCache.Count,
PluginId = PluginUUID,
Type = "Apple DOS"
};
stat.FreeFiles = totalFileEntries - stat.Files; stat.FreeFiles = totalFileEntries - stat.Files;
stat.PluginId = PluginUUID; stat.FreeBlocks = stat.Blocks - usedSectors;
stat.Type = "Apple DOS";
return Errno.NoError; return Errno.NoError;
} }

View File

@@ -95,8 +95,7 @@ namespace DiscImageChef.Filesystems.AppleDOS
if(string.Compare(xattr, "com.apple.dos.type", StringComparison.InvariantCulture) == 0) if(string.Compare(xattr, "com.apple.dos.type", StringComparison.InvariantCulture) == 0)
{ {
byte type; if(!fileTypeCache.TryGetValue(filename, out byte type)) return Errno.InvalidArgument;
if(!fileTypeCache.TryGetValue(filename, out type)) return Errno.InvalidArgument;
buf = new byte[1]; buf = new byte[1];
buf[0] = type; buf[0] = type;
@@ -106,8 +105,7 @@ namespace DiscImageChef.Filesystems.AppleDOS
if(string.Compare(xattr, "com.apple.dos.tracksectorlist", StringComparison.InvariantCulture) != 0 || !debug) if(string.Compare(xattr, "com.apple.dos.tracksectorlist", StringComparison.InvariantCulture) != 0 || !debug)
return Errno.NoSuchExtendedAttribute; return Errno.NoSuchExtendedAttribute;
byte[] ts; if(!extentCache.TryGetValue(filename, out byte[] ts)) return Errno.InvalidArgument;
if(!extentCache.TryGetValue(filename, out ts)) return Errno.InvalidArgument;
buf = new byte[ts.Length]; buf = new byte[ts.Length];
Array.Copy(ts, 0, buf, 0, buf.Length); Array.Copy(ts, 0, buf, 0, buf.Length);