mirror of
https://github.com/aaru-dps/Aaru.Server.git
synced 2025-12-16 19:24:27 +00:00
REFACTOR: All refactor in DiscImageChef.Filesystems.
This commit is contained in:
@@ -48,21 +48,21 @@ namespace DiscImageChef.Filesystems
|
||||
public AODOS()
|
||||
{
|
||||
Name = "Alexander Osipov DOS file system";
|
||||
PluginUUID = new Guid("668E5039-9DDD-442A-BE1B-A315D6E38E26");
|
||||
PluginUuid = new Guid("668E5039-9DDD-442A-BE1B-A315D6E38E26");
|
||||
CurrentEncoding = Encoding.GetEncoding("koi8-r");
|
||||
}
|
||||
|
||||
public AODOS(Encoding encoding)
|
||||
{
|
||||
Name = "Alexander Osipov DOS file system";
|
||||
PluginUUID = new Guid("668E5039-9DDD-442A-BE1B-A315D6E38E26");
|
||||
PluginUuid = new Guid("668E5039-9DDD-442A-BE1B-A315D6E38E26");
|
||||
CurrentEncoding = Encoding.GetEncoding("koi8-r");
|
||||
}
|
||||
|
||||
public AODOS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "Alexander Osipov DOS file system";
|
||||
PluginUUID = new Guid("668E5039-9DDD-442A-BE1B-A315D6E38E26");
|
||||
PluginUuid = new Guid("668E5039-9DDD-442A-BE1B-A315D6E38E26");
|
||||
CurrentEncoding = Encoding.GetEncoding("koi8-r");
|
||||
}
|
||||
|
||||
@@ -112,9 +112,7 @@ namespace DiscImageChef.Filesystems
|
||||
// Does AO-DOS support any other kind of disk?
|
||||
if(imagePlugin.ImageInfo.Sectors != 800 && imagePlugin.ImageInfo.Sectors != 1600) return false;
|
||||
|
||||
byte[] sector;
|
||||
|
||||
sector = imagePlugin.ReadSector(0);
|
||||
byte[] sector = imagePlugin.ReadSector(0);
|
||||
AODOS_BootBlock bb = new AODOS_BootBlock();
|
||||
IntPtr bbPtr = Marshal.AllocHGlobal(Marshal.SizeOf(bb));
|
||||
Marshal.Copy(sector, 0, bbPtr, Marshal.SizeOf(bb));
|
||||
@@ -127,9 +125,7 @@ namespace DiscImageChef.Filesystems
|
||||
public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
|
||||
out string information)
|
||||
{
|
||||
byte[] sector;
|
||||
|
||||
sector = imagePlugin.ReadSector(0);
|
||||
byte[] sector = imagePlugin.ReadSector(0);
|
||||
AODOS_BootBlock bb = new AODOS_BootBlock();
|
||||
IntPtr bbPtr = Marshal.AllocHGlobal(Marshal.SizeOf(bb));
|
||||
Marshal.Copy(sector, 0, bbPtr, Marshal.SizeOf(bb));
|
||||
@@ -140,7 +136,7 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
sbInformation.AppendLine("Alexander Osipov DOS file system");
|
||||
|
||||
xmlFSType = new FileSystemType
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
Type = "Alexander Osipov DOS file system",
|
||||
Clusters = (long)imagePlugin.ImageInfo.Sectors,
|
||||
|
||||
@@ -42,27 +42,27 @@ namespace DiscImageChef.Filesystems
|
||||
{
|
||||
public class APFS : Filesystem
|
||||
{
|
||||
const uint ApfsContainerMagic = 0x4253584E; // "NXSB"
|
||||
const uint ApfsVolumeMagic = 0x42535041; // "APSB"
|
||||
const uint APFS_CONTAINER_MAGIC = 0x4253584E; // "NXSB"
|
||||
const uint APFS_VOLUME_MAGIC = 0x42535041; // "APSB"
|
||||
|
||||
public APFS()
|
||||
{
|
||||
Name = "Apple File System";
|
||||
PluginUUID = new Guid("A4060F9D-2909-42E2-9D95-DB31FA7EA797");
|
||||
PluginUuid = new Guid("A4060F9D-2909-42E2-9D95-DB31FA7EA797");
|
||||
CurrentEncoding = Encoding.UTF8;
|
||||
}
|
||||
|
||||
public APFS(Encoding encoding)
|
||||
{
|
||||
Name = "Apple File System";
|
||||
PluginUUID = new Guid("A4060F9D-2909-42E2-9D95-DB31FA7EA797");
|
||||
PluginUuid = new Guid("A4060F9D-2909-42E2-9D95-DB31FA7EA797");
|
||||
CurrentEncoding = Encoding.UTF8;
|
||||
}
|
||||
|
||||
public APFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "Apple File System";
|
||||
PluginUUID = new Guid("A4060F9D-2909-42E2-9D95-DB31FA7EA797");
|
||||
PluginUuid = new Guid("A4060F9D-2909-42E2-9D95-DB31FA7EA797");
|
||||
CurrentEncoding = Encoding.UTF8;
|
||||
}
|
||||
|
||||
@@ -94,16 +94,14 @@ namespace DiscImageChef.Filesystems
|
||||
}
|
||||
catch { return false; }
|
||||
|
||||
if(nxSb.magic == ApfsContainerMagic) return true;
|
||||
|
||||
return false;
|
||||
return nxSb.magic == APFS_CONTAINER_MAGIC;
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
|
||||
out string information)
|
||||
{
|
||||
StringBuilder sbInformation = new StringBuilder();
|
||||
xmlFSType = new FileSystemType();
|
||||
XmlFsType = new FileSystemType();
|
||||
information = "";
|
||||
|
||||
if(partition.Start >= partition.End) return;
|
||||
@@ -120,7 +118,7 @@ namespace DiscImageChef.Filesystems
|
||||
}
|
||||
catch { return; }
|
||||
|
||||
if(nxSb.magic != ApfsContainerMagic) return;
|
||||
if(nxSb.magic != APFS_CONTAINER_MAGIC) return;
|
||||
|
||||
sbInformation.AppendLine("Apple File System");
|
||||
sbInformation.AppendLine();
|
||||
@@ -130,11 +128,13 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
information = sbInformation.ToString();
|
||||
|
||||
xmlFSType = new FileSystemType();
|
||||
xmlFSType.Bootable = false;
|
||||
xmlFSType.Clusters = (long)nxSb.containerBlocks;
|
||||
xmlFSType.ClusterSize = (int)nxSb.blockSize;
|
||||
xmlFSType.Type = "Apple File System";
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
Bootable = false,
|
||||
Clusters = (long)nxSb.containerBlocks,
|
||||
ClusterSize = (int)nxSb.blockSize,
|
||||
Type = "Apple File System"
|
||||
};
|
||||
}
|
||||
|
||||
public override Errno Mount()
|
||||
|
||||
@@ -46,49 +46,47 @@ namespace DiscImageChef.Filesystems
|
||||
/// <summary>
|
||||
/// Location for boot block, in bytes
|
||||
/// </summary>
|
||||
const ulong bootBlockLocation = 0xC00;
|
||||
const ulong BOOT_BLOCK_LOCATION = 0xC00;
|
||||
/// <summary>
|
||||
/// Size of boot block, in bytes
|
||||
/// </summary>
|
||||
const uint bootBlockSize = 0x200;
|
||||
const uint BOOT_BLOCK_SIZE = 0x200;
|
||||
/// <summary>
|
||||
/// Location of new directory, in bytes
|
||||
/// </summary>
|
||||
const ulong newDirectoryLocation = 0x400;
|
||||
const ulong NEW_DIRECTORY_LOCATION = 0x400;
|
||||
/// <summary>
|
||||
/// Location of old directory, in bytes
|
||||
/// </summary>
|
||||
const ulong oldDirectoryLocation = 0x200;
|
||||
const ulong OLD_DIRECTORY_LOCATION = 0x200;
|
||||
/// <summary>
|
||||
/// Size of old directory
|
||||
/// </summary>
|
||||
const uint oldDirectorySize = 1280;
|
||||
const uint OLD_DIRECTORY_SIZE = 1280;
|
||||
/// <summary>
|
||||
/// Size of new directory
|
||||
/// </summary>
|
||||
const uint newDirectorySize = 2048;
|
||||
const uint NEW_DIRECTORY_SIZE = 2048;
|
||||
|
||||
public AcornADFS()
|
||||
{
|
||||
Name = "Acorn Advanced Disc Filing System";
|
||||
PluginUUID = new Guid("BAFC1E50-9C64-4CD3-8400-80628CC27AFA");
|
||||
PluginUuid = new Guid("BAFC1E50-9C64-4CD3-8400-80628CC27AFA");
|
||||
CurrentEncoding = Encoding.GetEncoding("iso-8859-1");
|
||||
}
|
||||
|
||||
public AcornADFS(Encoding encoding)
|
||||
{
|
||||
Name = "Acorn Advanced Disc Filing System";
|
||||
PluginUUID = new Guid("BAFC1E50-9C64-4CD3-8400-80628CC27AFA");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-1");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("BAFC1E50-9C64-4CD3-8400-80628CC27AFA");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1");
|
||||
}
|
||||
|
||||
public AcornADFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "Acorn Advanced Disc Filing System";
|
||||
PluginUUID = new Guid("BAFC1E50-9C64-4CD3-8400-80628CC27AFA");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-1");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("BAFC1E50-9C64-4CD3-8400-80628CC27AFA");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -186,11 +184,11 @@ namespace DiscImageChef.Filesystems
|
||||
/// <summary>
|
||||
/// New directory format magic number, "Nick"
|
||||
/// </summary>
|
||||
const uint newDirMagic = 0x6B63694E;
|
||||
const uint NEW_DIR_MAGIC = 0x6B63694E;
|
||||
/// <summary>
|
||||
/// Old directory format magic number, "Hugo"
|
||||
/// </summary>
|
||||
const uint oldDirMagic = 0x6F677548;
|
||||
const uint OLD_DIR_MAGIC = 0x6F677548;
|
||||
|
||||
/// <summary>
|
||||
/// Directory header, common to "old" and "new" directories
|
||||
@@ -276,22 +274,15 @@ namespace DiscImageChef.Filesystems
|
||||
// ADFS-S, ADFS-M, ADFS-L, ADFS-D without partitions
|
||||
if(partition.Start == 0)
|
||||
{
|
||||
OldMapSector0 oldMap0;
|
||||
OldMapSector1 oldMap1;
|
||||
OldDirectory oldRoot;
|
||||
byte oldChk0;
|
||||
byte oldChk1;
|
||||
byte dirChk;
|
||||
|
||||
sector = imagePlugin.ReadSector(0);
|
||||
oldChk0 = AcornMapChecksum(sector, 255);
|
||||
byte oldChk0 = AcornMapChecksum(sector, 255);
|
||||
ptr = GCHandle.Alloc(sector, GCHandleType.Pinned);
|
||||
oldMap0 = (OldMapSector0)Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(OldMapSector0));
|
||||
OldMapSector0 oldMap0 = (OldMapSector0)Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(OldMapSector0));
|
||||
|
||||
sector = imagePlugin.ReadSector(1);
|
||||
oldChk1 = AcornMapChecksum(sector, 255);
|
||||
byte oldChk1 = AcornMapChecksum(sector, 255);
|
||||
ptr = GCHandle.Alloc(sector, GCHandleType.Pinned);
|
||||
oldMap1 = (OldMapSector1)Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(OldMapSector1));
|
||||
OldMapSector1 oldMap1 = (OldMapSector1)Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(OldMapSector1));
|
||||
|
||||
DicConsole.DebugWriteLine("ADFS Plugin", "oldMap0.checksum = {0}", oldMap0.checksum);
|
||||
DicConsole.DebugWriteLine("ADFS Plugin", "oldChk0 = {0}", oldChk0);
|
||||
@@ -313,21 +304,21 @@ namespace DiscImageChef.Filesystems
|
||||
if(oldMap0.checksum == oldChk0 && oldMap1.checksum == oldChk1 && oldMap0.checksum != 0 &&
|
||||
oldMap1.checksum != 0)
|
||||
{
|
||||
sbSector = oldDirectoryLocation / imagePlugin.ImageInfo.SectorSize;
|
||||
sectorsToRead = oldDirectorySize / imagePlugin.ImageInfo.SectorSize;
|
||||
if(oldDirectorySize % imagePlugin.ImageInfo.SectorSize > 0) sectorsToRead++;
|
||||
sbSector = OLD_DIRECTORY_LOCATION / imagePlugin.ImageInfo.SectorSize;
|
||||
sectorsToRead = OLD_DIRECTORY_SIZE / imagePlugin.ImageInfo.SectorSize;
|
||||
if(OLD_DIRECTORY_SIZE % imagePlugin.ImageInfo.SectorSize > 0) sectorsToRead++;
|
||||
|
||||
sector = imagePlugin.ReadSectors(sbSector, sectorsToRead);
|
||||
if(sector.Length > oldDirectorySize)
|
||||
if(sector.Length > OLD_DIRECTORY_SIZE)
|
||||
{
|
||||
byte[] tmp = new byte[oldDirectorySize];
|
||||
Array.Copy(sector, 0, tmp, 0, oldDirectorySize - 53);
|
||||
Array.Copy(sector, sector.Length - 54, tmp, oldDirectorySize - 54, 53);
|
||||
byte[] tmp = new byte[OLD_DIRECTORY_SIZE];
|
||||
Array.Copy(sector, 0, tmp, 0, OLD_DIRECTORY_SIZE - 53);
|
||||
Array.Copy(sector, sector.Length - 54, tmp, OLD_DIRECTORY_SIZE - 54, 53);
|
||||
sector = tmp;
|
||||
}
|
||||
ptr = GCHandle.Alloc(sector, GCHandleType.Pinned);
|
||||
oldRoot = (OldDirectory)Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(OldDirectory));
|
||||
dirChk = AcornDirectoryChecksum(sector, (int)oldDirectorySize - 1);
|
||||
OldDirectory oldRoot = (OldDirectory)Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(OldDirectory));
|
||||
byte dirChk = AcornDirectoryChecksum(sector, (int)OLD_DIRECTORY_SIZE - 1);
|
||||
|
||||
DicConsole.DebugWriteLine("ADFS Plugin", "oldRoot.header.magic at 0x200 = {0}",
|
||||
oldRoot.header.magic);
|
||||
@@ -336,25 +327,25 @@ namespace DiscImageChef.Filesystems
|
||||
oldRoot.tail.checkByte);
|
||||
DicConsole.DebugWriteLine("ADFS Plugin", "dirChk at 0x200 = {0}", dirChk);
|
||||
|
||||
if(oldRoot.header.magic == oldDirMagic && oldRoot.tail.magic == oldDirMagic ||
|
||||
oldRoot.header.magic == newDirMagic && oldRoot.tail.magic == newDirMagic) return true;
|
||||
if(oldRoot.header.magic == OLD_DIR_MAGIC && oldRoot.tail.magic == OLD_DIR_MAGIC ||
|
||||
oldRoot.header.magic == NEW_DIR_MAGIC && oldRoot.tail.magic == NEW_DIR_MAGIC) return true;
|
||||
|
||||
// RISC OS says the old directory can't be in the new location, hard disks created by RISC OS 3.10 do that...
|
||||
sbSector = newDirectoryLocation / imagePlugin.ImageInfo.SectorSize;
|
||||
sectorsToRead = newDirectorySize / imagePlugin.ImageInfo.SectorSize;
|
||||
if(newDirectorySize % imagePlugin.ImageInfo.SectorSize > 0) sectorsToRead++;
|
||||
sbSector = NEW_DIRECTORY_LOCATION / imagePlugin.ImageInfo.SectorSize;
|
||||
sectorsToRead = NEW_DIRECTORY_SIZE / imagePlugin.ImageInfo.SectorSize;
|
||||
if(NEW_DIRECTORY_SIZE % imagePlugin.ImageInfo.SectorSize > 0) sectorsToRead++;
|
||||
|
||||
sector = imagePlugin.ReadSectors(sbSector, sectorsToRead);
|
||||
if(sector.Length > oldDirectorySize)
|
||||
if(sector.Length > OLD_DIRECTORY_SIZE)
|
||||
{
|
||||
byte[] tmp = new byte[oldDirectorySize];
|
||||
Array.Copy(sector, 0, tmp, 0, oldDirectorySize - 53);
|
||||
Array.Copy(sector, sector.Length - 54, tmp, oldDirectorySize - 54, 53);
|
||||
byte[] tmp = new byte[OLD_DIRECTORY_SIZE];
|
||||
Array.Copy(sector, 0, tmp, 0, OLD_DIRECTORY_SIZE - 53);
|
||||
Array.Copy(sector, sector.Length - 54, tmp, OLD_DIRECTORY_SIZE - 54, 53);
|
||||
sector = tmp;
|
||||
}
|
||||
ptr = GCHandle.Alloc(sector, GCHandleType.Pinned);
|
||||
oldRoot = (OldDirectory)Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(OldDirectory));
|
||||
dirChk = AcornDirectoryChecksum(sector, (int)oldDirectorySize - 1);
|
||||
dirChk = AcornDirectoryChecksum(sector, (int)OLD_DIRECTORY_SIZE - 1);
|
||||
|
||||
DicConsole.DebugWriteLine("ADFS Plugin", "oldRoot.header.magic at 0x400 = {0}",
|
||||
oldRoot.header.magic);
|
||||
@@ -363,8 +354,8 @@ namespace DiscImageChef.Filesystems
|
||||
oldRoot.tail.checkByte);
|
||||
DicConsole.DebugWriteLine("ADFS Plugin", "dirChk at 0x400 = {0}", dirChk);
|
||||
|
||||
if(oldRoot.header.magic == oldDirMagic && oldRoot.tail.magic == oldDirMagic ||
|
||||
oldRoot.header.magic == newDirMagic && oldRoot.tail.magic == newDirMagic) return true;
|
||||
if(oldRoot.header.magic == OLD_DIR_MAGIC && oldRoot.tail.magic == OLD_DIR_MAGIC ||
|
||||
oldRoot.header.magic == NEW_DIR_MAGIC && oldRoot.tail.magic == NEW_DIR_MAGIC) return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -376,9 +367,9 @@ namespace DiscImageChef.Filesystems
|
||||
DicConsole.DebugWriteLine("ADFS Plugin", "newChk = {0}", newChk);
|
||||
DicConsole.DebugWriteLine("ADFS Plugin", "map.zoneChecksum = {0}", sector[0]);
|
||||
|
||||
sbSector = bootBlockLocation / imagePlugin.ImageInfo.SectorSize;
|
||||
sectorsToRead = bootBlockSize / imagePlugin.ImageInfo.SectorSize;
|
||||
if(bootBlockSize % imagePlugin.ImageInfo.SectorSize > 0) sectorsToRead++;
|
||||
sbSector = BOOT_BLOCK_LOCATION / imagePlugin.ImageInfo.SectorSize;
|
||||
sectorsToRead = BOOT_BLOCK_SIZE / imagePlugin.ImageInfo.SectorSize;
|
||||
if(BOOT_BLOCK_SIZE % imagePlugin.ImageInfo.SectorSize > 0) sectorsToRead++;
|
||||
|
||||
if(sbSector + partition.Start + sectorsToRead >= partition.End) return false;
|
||||
|
||||
@@ -424,9 +415,7 @@ namespace DiscImageChef.Filesystems
|
||||
bytes *= 0x100000000;
|
||||
bytes += drSb.disc_size;
|
||||
|
||||
if(bytes > imagePlugin.GetSectors() * imagePlugin.GetSectorSize()) return false;
|
||||
|
||||
return true;
|
||||
return bytes <= imagePlugin.GetSectors() * imagePlugin.GetSectorSize();
|
||||
}
|
||||
|
||||
// TODO: Find root directory on volumes with DiscRecord
|
||||
@@ -436,7 +425,7 @@ namespace DiscImageChef.Filesystems
|
||||
out string information)
|
||||
{
|
||||
StringBuilder sbInformation = new StringBuilder();
|
||||
xmlFSType = new FileSystemType();
|
||||
XmlFsType = new FileSystemType();
|
||||
information = "";
|
||||
|
||||
ulong sbSector;
|
||||
@@ -444,27 +433,19 @@ namespace DiscImageChef.Filesystems
|
||||
uint sectorsToRead;
|
||||
GCHandle ptr;
|
||||
ulong bytes;
|
||||
string discname;
|
||||
|
||||
// ADFS-S, ADFS-M, ADFS-L, ADFS-D without partitions
|
||||
if(partition.Start == 0)
|
||||
{
|
||||
OldMapSector0 oldMap0;
|
||||
OldMapSector1 oldMap1;
|
||||
OldDirectory oldRoot;
|
||||
NewDirectory newRoot;
|
||||
byte oldChk0;
|
||||
byte oldChk1;
|
||||
|
||||
sector = imagePlugin.ReadSector(0);
|
||||
oldChk0 = AcornMapChecksum(sector, 255);
|
||||
byte oldChk0 = AcornMapChecksum(sector, 255);
|
||||
ptr = GCHandle.Alloc(sector, GCHandleType.Pinned);
|
||||
oldMap0 = (OldMapSector0)Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(OldMapSector0));
|
||||
OldMapSector0 oldMap0 = (OldMapSector0)Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(OldMapSector0));
|
||||
|
||||
sector = imagePlugin.ReadSector(1);
|
||||
oldChk1 = AcornMapChecksum(sector, 255);
|
||||
byte oldChk1 = AcornMapChecksum(sector, 255);
|
||||
ptr = GCHandle.Alloc(sector, GCHandleType.Pinned);
|
||||
oldMap1 = (OldMapSector1)Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(OldMapSector1));
|
||||
OldMapSector1 oldMap1 = (OldMapSector1)Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(OldMapSector1));
|
||||
|
||||
// According to documentation map1 MUST start on sector 1. On ADFS-D it starts at 0x100, not on sector 1 (0x400)
|
||||
if(oldMap0.checksum == oldChk0 && oldMap1.checksum != oldChk1 && sector.Length >= 512)
|
||||
@@ -488,7 +469,7 @@ namespace DiscImageChef.Filesystems
|
||||
namebytes[i * 2 + 1] = oldMap1.name[i];
|
||||
}
|
||||
|
||||
xmlFSType = new FileSystemType
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
Bootable = oldMap1.boot != 0, // Or not?
|
||||
Clusters = (long)(bytes / imagePlugin.ImageInfo.SectorSize),
|
||||
@@ -498,56 +479,56 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
if(ArrayHelpers.ArrayIsNullOrEmpty(namebytes))
|
||||
{
|
||||
sbSector = oldDirectoryLocation / imagePlugin.ImageInfo.SectorSize;
|
||||
sectorsToRead = oldDirectorySize / imagePlugin.ImageInfo.SectorSize;
|
||||
if(oldDirectorySize % imagePlugin.ImageInfo.SectorSize > 0) sectorsToRead++;
|
||||
sbSector = OLD_DIRECTORY_LOCATION / imagePlugin.ImageInfo.SectorSize;
|
||||
sectorsToRead = OLD_DIRECTORY_SIZE / imagePlugin.ImageInfo.SectorSize;
|
||||
if(OLD_DIRECTORY_SIZE % imagePlugin.ImageInfo.SectorSize > 0) sectorsToRead++;
|
||||
|
||||
sector = imagePlugin.ReadSectors(sbSector, sectorsToRead);
|
||||
if(sector.Length > oldDirectorySize)
|
||||
if(sector.Length > OLD_DIRECTORY_SIZE)
|
||||
{
|
||||
byte[] tmp = new byte[oldDirectorySize];
|
||||
Array.Copy(sector, 0, tmp, 0, oldDirectorySize - 53);
|
||||
Array.Copy(sector, sector.Length - 54, tmp, oldDirectorySize - 54, 53);
|
||||
byte[] tmp = new byte[OLD_DIRECTORY_SIZE];
|
||||
Array.Copy(sector, 0, tmp, 0, OLD_DIRECTORY_SIZE - 53);
|
||||
Array.Copy(sector, sector.Length - 54, tmp, OLD_DIRECTORY_SIZE - 54, 53);
|
||||
sector = tmp;
|
||||
}
|
||||
ptr = GCHandle.Alloc(sector, GCHandleType.Pinned);
|
||||
oldRoot = (OldDirectory)Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(OldDirectory));
|
||||
OldDirectory oldRoot = (OldDirectory)Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(OldDirectory));
|
||||
|
||||
if(oldRoot.header.magic == oldDirMagic && oldRoot.tail.magic == oldDirMagic) namebytes = oldRoot.tail.name;
|
||||
if(oldRoot.header.magic == OLD_DIR_MAGIC && oldRoot.tail.magic == OLD_DIR_MAGIC) namebytes = oldRoot.tail.name;
|
||||
else
|
||||
{
|
||||
// RISC OS says the old directory can't be in the new location, hard disks created by RISC OS 3.10 do that...
|
||||
sbSector = newDirectoryLocation / imagePlugin.ImageInfo.SectorSize;
|
||||
sectorsToRead = newDirectorySize / imagePlugin.ImageInfo.SectorSize;
|
||||
if(newDirectorySize % imagePlugin.ImageInfo.SectorSize > 0) sectorsToRead++;
|
||||
sbSector = NEW_DIRECTORY_LOCATION / imagePlugin.ImageInfo.SectorSize;
|
||||
sectorsToRead = NEW_DIRECTORY_SIZE / imagePlugin.ImageInfo.SectorSize;
|
||||
if(NEW_DIRECTORY_SIZE % imagePlugin.ImageInfo.SectorSize > 0) sectorsToRead++;
|
||||
|
||||
sector = imagePlugin.ReadSectors(sbSector, sectorsToRead);
|
||||
if(sector.Length > oldDirectorySize)
|
||||
if(sector.Length > OLD_DIRECTORY_SIZE)
|
||||
{
|
||||
byte[] tmp = new byte[oldDirectorySize];
|
||||
Array.Copy(sector, 0, tmp, 0, oldDirectorySize - 53);
|
||||
Array.Copy(sector, sector.Length - 54, tmp, oldDirectorySize - 54, 53);
|
||||
byte[] tmp = new byte[OLD_DIRECTORY_SIZE];
|
||||
Array.Copy(sector, 0, tmp, 0, OLD_DIRECTORY_SIZE - 53);
|
||||
Array.Copy(sector, sector.Length - 54, tmp, OLD_DIRECTORY_SIZE - 54, 53);
|
||||
sector = tmp;
|
||||
}
|
||||
ptr = GCHandle.Alloc(sector, GCHandleType.Pinned);
|
||||
oldRoot = (OldDirectory)Marshal.PtrToStructure(ptr.AddrOfPinnedObject(),
|
||||
typeof(OldDirectory));
|
||||
|
||||
if(oldRoot.header.magic == oldDirMagic && oldRoot.tail.magic == oldDirMagic) namebytes = oldRoot.tail.name;
|
||||
if(oldRoot.header.magic == OLD_DIR_MAGIC && oldRoot.tail.magic == OLD_DIR_MAGIC) namebytes = oldRoot.tail.name;
|
||||
else
|
||||
{
|
||||
sector = imagePlugin.ReadSectors(sbSector, sectorsToRead);
|
||||
if(sector.Length > newDirectorySize)
|
||||
if(sector.Length > NEW_DIRECTORY_SIZE)
|
||||
{
|
||||
byte[] tmp = new byte[newDirectorySize];
|
||||
Array.Copy(sector, 0, tmp, 0, newDirectorySize - 41);
|
||||
Array.Copy(sector, sector.Length - 42, tmp, newDirectorySize - 42, 41);
|
||||
byte[] tmp = new byte[NEW_DIRECTORY_SIZE];
|
||||
Array.Copy(sector, 0, tmp, 0, NEW_DIRECTORY_SIZE - 41);
|
||||
Array.Copy(sector, sector.Length - 42, tmp, NEW_DIRECTORY_SIZE - 42, 41);
|
||||
sector = tmp;
|
||||
}
|
||||
ptr = GCHandle.Alloc(sector, GCHandleType.Pinned);
|
||||
newRoot = (NewDirectory)Marshal.PtrToStructure(ptr.AddrOfPinnedObject(),
|
||||
NewDirectory newRoot = (NewDirectory)Marshal.PtrToStructure(ptr.AddrOfPinnedObject(),
|
||||
typeof(NewDirectory));
|
||||
if(newRoot.header.magic == newDirMagic && newRoot.tail.magic == newDirMagic) namebytes = newRoot.tail.title;
|
||||
if(newRoot.header.magic == NEW_DIR_MAGIC && newRoot.tail.magic == NEW_DIR_MAGIC) namebytes = newRoot.tail.title;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -560,11 +541,11 @@ namespace DiscImageChef.Filesystems
|
||||
.AppendLine();
|
||||
if(oldMap1.discId > 0)
|
||||
{
|
||||
xmlFSType.VolumeSerial = $"{oldMap1.discId:X4}";
|
||||
XmlFsType.VolumeSerial = $"{oldMap1.discId:X4}";
|
||||
sbInformation.AppendFormat("Volume ID: {0:X4}", oldMap1.discId).AppendLine();
|
||||
}
|
||||
if(!ArrayHelpers.ArrayIsNullOrEmpty(namebytes))
|
||||
xmlFSType.VolumeName = StringHandlers.CToString(namebytes, CurrentEncoding);
|
||||
XmlFsType.VolumeName = StringHandlers.CToString(namebytes, CurrentEncoding);
|
||||
|
||||
information = sbInformation.ToString();
|
||||
|
||||
@@ -580,9 +561,9 @@ namespace DiscImageChef.Filesystems
|
||||
DicConsole.DebugWriteLine("ADFS Plugin", "newChk = {0}", newChk);
|
||||
DicConsole.DebugWriteLine("ADFS Plugin", "map.zoneChecksum = {0}", sector[0]);
|
||||
|
||||
sbSector = bootBlockLocation / imagePlugin.ImageInfo.SectorSize;
|
||||
sectorsToRead = bootBlockSize / imagePlugin.ImageInfo.SectorSize;
|
||||
if(bootBlockSize % imagePlugin.ImageInfo.SectorSize > 0) sectorsToRead++;
|
||||
sbSector = BOOT_BLOCK_LOCATION / imagePlugin.ImageInfo.SectorSize;
|
||||
sectorsToRead = BOOT_BLOCK_SIZE / imagePlugin.ImageInfo.SectorSize;
|
||||
if(BOOT_BLOCK_SIZE % imagePlugin.ImageInfo.SectorSize > 0) sectorsToRead++;
|
||||
|
||||
byte[] bootSector = imagePlugin.ReadSectors(sbSector + partition.Start, sectorsToRead);
|
||||
int bootChk = 0;
|
||||
@@ -648,7 +629,7 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
if(bytes > imagePlugin.GetSectors() * imagePlugin.GetSectorSize()) return;
|
||||
|
||||
xmlFSType = new FileSystemType();
|
||||
XmlFsType = new FileSystemType();
|
||||
|
||||
sbInformation.AppendLine("Acorn Advanced Disc Filing System");
|
||||
sbInformation.AppendLine();
|
||||
@@ -666,22 +647,22 @@ namespace DiscImageChef.Filesystems
|
||||
sbInformation.AppendFormat("Volume flags: 0x{0:X4}", drSb.flags).AppendLine();
|
||||
if(drSb.disc_id > 0)
|
||||
{
|
||||
xmlFSType.VolumeSerial = $"{drSb.disc_id:X4}";
|
||||
XmlFsType.VolumeSerial = $"{drSb.disc_id:X4}";
|
||||
sbInformation.AppendFormat("Volume ID: {0:X4}", drSb.disc_id).AppendLine();
|
||||
}
|
||||
if(!ArrayHelpers.ArrayIsNullOrEmpty(drSb.disc_name))
|
||||
{
|
||||
discname = StringHandlers.CToString(drSb.disc_name, CurrentEncoding);
|
||||
xmlFSType.VolumeName = discname;
|
||||
string discname = StringHandlers.CToString(drSb.disc_name, CurrentEncoding);
|
||||
XmlFsType.VolumeName = discname;
|
||||
sbInformation.AppendFormat("Volume name: {0}", discname).AppendLine();
|
||||
}
|
||||
|
||||
information = sbInformation.ToString();
|
||||
|
||||
xmlFSType.Bootable |= drSb.bootoption != 0; // Or not?
|
||||
xmlFSType.Clusters = (long)(bytes / (ulong)(1 << drSb.log2secsize));
|
||||
xmlFSType.ClusterSize = 1 << drSb.log2secsize;
|
||||
xmlFSType.Type = "Acorn Advanced Disc Filing System";
|
||||
XmlFsType.Bootable |= drSb.bootoption != 0; // Or not?
|
||||
XmlFsType.Clusters = (long)(bytes / (ulong)(1 << drSb.log2secsize));
|
||||
XmlFsType.ClusterSize = 1 << drSb.log2secsize;
|
||||
XmlFsType.Type = "Acorn Advanced Disc Filing System";
|
||||
}
|
||||
|
||||
public override Errno Mount()
|
||||
@@ -768,48 +749,43 @@ namespace DiscImageChef.Filesystems
|
||||
return (byte)(sum & 0xFF);
|
||||
}
|
||||
|
||||
byte NewMapChecksum(byte[] map_base)
|
||||
static byte NewMapChecksum(byte[] mapBase)
|
||||
{
|
||||
uint sum_vector0;
|
||||
uint sum_vector1;
|
||||
uint sum_vector2;
|
||||
uint sum_vector3;
|
||||
uint rover;
|
||||
uint sumVector0 = 0;
|
||||
uint sumVector1 = 0;
|
||||
uint sumVector2 = 0;
|
||||
uint sumVector3 = 0;
|
||||
|
||||
sum_vector0 = 0;
|
||||
sum_vector1 = 0;
|
||||
sum_vector2 = 0;
|
||||
sum_vector3 = 0;
|
||||
|
||||
for(rover = (uint)(map_base.Length - 4); rover > 0; rover -= 4)
|
||||
for(rover = (uint)(mapBase.Length - 4); rover > 0; rover -= 4)
|
||||
{
|
||||
sum_vector0 += map_base[rover + 0] + (sum_vector3 >> 8);
|
||||
sum_vector3 &= 0xff;
|
||||
sum_vector1 += map_base[rover + 1] + (sum_vector0 >> 8);
|
||||
sum_vector0 &= 0xff;
|
||||
sum_vector2 += map_base[rover + 2] + (sum_vector1 >> 8);
|
||||
sum_vector1 &= 0xff;
|
||||
sum_vector3 += map_base[rover + 3] + (sum_vector2 >> 8);
|
||||
sum_vector2 &= 0xff;
|
||||
sumVector0 += mapBase[rover + 0] + (sumVector3 >> 8);
|
||||
sumVector3 &= 0xff;
|
||||
sumVector1 += mapBase[rover + 1] + (sumVector0 >> 8);
|
||||
sumVector0 &= 0xff;
|
||||
sumVector2 += mapBase[rover + 2] + (sumVector1 >> 8);
|
||||
sumVector1 &= 0xff;
|
||||
sumVector3 += mapBase[rover + 3] + (sumVector2 >> 8);
|
||||
sumVector2 &= 0xff;
|
||||
}
|
||||
|
||||
/*
|
||||
Don't add the check byte when calculating its value
|
||||
*/
|
||||
sum_vector0 += sum_vector3 >> 8;
|
||||
sum_vector1 += map_base[rover + 1] + (sum_vector0 >> 8);
|
||||
sum_vector2 += map_base[rover + 2] + (sum_vector1 >> 8);
|
||||
sum_vector3 += map_base[rover + 3] + (sum_vector2 >> 8);
|
||||
sumVector0 += sumVector3 >> 8;
|
||||
sumVector1 += mapBase[rover + 1] + (sumVector0 >> 8);
|
||||
sumVector2 += mapBase[rover + 2] + (sumVector1 >> 8);
|
||||
sumVector3 += mapBase[rover + 3] + (sumVector2 >> 8);
|
||||
|
||||
return (byte)((sum_vector0 ^ sum_vector1 ^ sum_vector2 ^ sum_vector3) & 0xff);
|
||||
return (byte)((sumVector0 ^ sumVector1 ^ sumVector2 ^ sumVector3) & 0xff);
|
||||
}
|
||||
|
||||
// TODO: This is not correct...
|
||||
byte AcornDirectoryChecksum(byte[] data, int length)
|
||||
static byte AcornDirectoryChecksum(IList<byte> data, int length)
|
||||
{
|
||||
uint sum = 0;
|
||||
|
||||
if(length > data.Length) length = data.Length;
|
||||
if(length > data.Count) length = data.Count;
|
||||
|
||||
// EOR r0, r1, r0, ROR #13
|
||||
for(int i = 0; i < length; i++)
|
||||
|
||||
@@ -48,24 +48,22 @@ namespace DiscImageChef.Filesystems
|
||||
public AmigaDOSPlugin()
|
||||
{
|
||||
Name = "Amiga DOS filesystem";
|
||||
PluginUUID = new Guid("3c882400-208c-427d-a086-9119852a1bc7");
|
||||
PluginUuid = new Guid("3c882400-208c-427d-a086-9119852a1bc7");
|
||||
CurrentEncoding = Encoding.GetEncoding("iso-8859-1");
|
||||
}
|
||||
|
||||
public AmigaDOSPlugin(Encoding encoding)
|
||||
{
|
||||
Name = "Amiga DOS filesystem";
|
||||
PluginUUID = new Guid("3c882400-208c-427d-a086-9119852a1bc7");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-1");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("3c882400-208c-427d-a086-9119852a1bc7");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1");
|
||||
}
|
||||
|
||||
public AmigaDOSPlugin(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "Amiga DOS filesystem";
|
||||
PluginUUID = new Guid("3c882400-208c-427d-a086-9119852a1bc7");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-1");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("3c882400-208c-427d-a086-9119852a1bc7");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -206,11 +204,11 @@ namespace DiscImageChef.Filesystems
|
||||
public uint sec_type;
|
||||
}
|
||||
|
||||
public const uint FFS_Mask = 0x444F5300;
|
||||
public const uint MuFS_Mask = 0x6D754600;
|
||||
const uint FFS_MASK = 0x444F5300;
|
||||
const uint MUFS_MASK = 0x6D754600;
|
||||
|
||||
public const uint TypeHeader = 2;
|
||||
public const uint SubTypeRoot = 1;
|
||||
const uint TYPE_HEADER = 2;
|
||||
const uint SUBTYPE_ROOT = 1;
|
||||
|
||||
public override bool Identify(ImagePlugin imagePlugin, Partition partition)
|
||||
{
|
||||
@@ -229,14 +227,14 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
// AROS boot floppies...
|
||||
if(sector.Length >= 512 && sector[510] == 0x55 && sector[511] == 0xAA &&
|
||||
(bblk.diskType & FFS_Mask) != FFS_Mask && (bblk.diskType & MuFS_Mask) != MuFS_Mask)
|
||||
(bblk.diskType & FFS_MASK) != FFS_MASK && (bblk.diskType & MUFS_MASK) != MUFS_MASK)
|
||||
{
|
||||
sector = imagePlugin.ReadSectors(1 + partition.Start, 2);
|
||||
bblk = BigEndianMarshal.ByteArrayToStructureBigEndian<BootBlock>(sector);
|
||||
}
|
||||
|
||||
// Not FFS or MuFS?
|
||||
if((bblk.diskType & FFS_Mask) != FFS_Mask && (bblk.diskType & MuFS_Mask) != MuFS_Mask) return false;
|
||||
if((bblk.diskType & FFS_MASK) != FFS_MASK && (bblk.diskType & MUFS_MASK) != MUFS_MASK) return false;
|
||||
|
||||
// Clear checksum on sector
|
||||
sector[4] = sector[5] = sector[6] = sector[7] = 0;
|
||||
@@ -245,18 +243,18 @@ namespace DiscImageChef.Filesystems
|
||||
DicConsole.DebugWriteLine("AmigaDOS plugin", "bblk.checksum = 0x{0:X8}", bblk.checksum);
|
||||
DicConsole.DebugWriteLine("AmigaDOS plugin", "bsum = 0x{0:X8}", bsum);
|
||||
|
||||
ulong b_root_ptr = 0;
|
||||
ulong bRootPtr = 0;
|
||||
|
||||
// If bootblock is correct, let's take its rootblock pointer
|
||||
if(bsum == bblk.checksum)
|
||||
{
|
||||
b_root_ptr = bblk.root_ptr + partition.Start;
|
||||
DicConsole.DebugWriteLine("AmigaDOS plugin", "Bootblock points to {0} as Rootblock", b_root_ptr);
|
||||
bRootPtr = bblk.root_ptr + partition.Start;
|
||||
DicConsole.DebugWriteLine("AmigaDOS plugin", "Bootblock points to {0} as Rootblock", bRootPtr);
|
||||
}
|
||||
|
||||
ulong[] root_ptrs =
|
||||
ulong[] rootPtrs =
|
||||
{
|
||||
b_root_ptr + partition.Start, (partition.End - partition.Start + 1) / 2 + partition.Start - 2,
|
||||
bRootPtr + partition.Start, (partition.End - partition.Start + 1) / 2 + partition.Start - 2,
|
||||
(partition.End - partition.Start + 1) / 2 + partition.Start - 1,
|
||||
(partition.End - partition.Start + 1) / 2 + partition.Start,
|
||||
(partition.End - partition.Start + 1) / 2 + partition.Start + 4
|
||||
@@ -265,14 +263,14 @@ namespace DiscImageChef.Filesystems
|
||||
RootBlock rblk = new RootBlock();
|
||||
|
||||
// So to handle even number of sectors
|
||||
foreach(ulong root_ptr in root_ptrs.Where(root_ptr => root_ptr < partition.End && root_ptr >= partition.Start)) {
|
||||
DicConsole.DebugWriteLine("AmigaDOS plugin", "Searching for Rootblock in sector {0}", root_ptr);
|
||||
foreach(ulong rootPtr in rootPtrs.Where(rootPtr => rootPtr < partition.End && rootPtr >= partition.Start)) {
|
||||
DicConsole.DebugWriteLine("AmigaDOS plugin", "Searching for Rootblock in sector {0}", rootPtr);
|
||||
|
||||
sector = imagePlugin.ReadSector(root_ptr);
|
||||
sector = imagePlugin.ReadSector(rootPtr);
|
||||
|
||||
rblk.type = BigEndianBitConverter.ToUInt32(sector, 0x00);
|
||||
DicConsole.DebugWriteLine("AmigaDOS plugin", "rblk.type = {0}", rblk.type);
|
||||
if(rblk.type != TypeHeader) continue;
|
||||
if(rblk.type != TYPE_HEADER) continue;
|
||||
|
||||
rblk.hashTableSize = BigEndianBitConverter.ToUInt32(sector, 0x0C);
|
||||
|
||||
@@ -286,9 +284,9 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
if(blockSize % sector.Length > 0) sectorsPerBlock++;
|
||||
|
||||
if(root_ptr + sectorsPerBlock >= partition.End) continue;
|
||||
if(rootPtr + sectorsPerBlock >= partition.End) continue;
|
||||
|
||||
sector = imagePlugin.ReadSectors(root_ptr, sectorsPerBlock);
|
||||
sector = imagePlugin.ReadSectors(rootPtr, sectorsPerBlock);
|
||||
|
||||
// Clear checksum on sector
|
||||
rblk.checksum = BigEndianBitConverter.ToUInt32(sector, 20);
|
||||
@@ -301,7 +299,7 @@ namespace DiscImageChef.Filesystems
|
||||
rblk.sec_type = BigEndianBitConverter.ToUInt32(sector, sector.Length - 4);
|
||||
DicConsole.DebugWriteLine("AmigaDOS plugin", "rblk.sec_type = {0}", rblk.sec_type);
|
||||
|
||||
if(rblk.sec_type == SubTypeRoot && rblk.checksum == rsum) return true;
|
||||
if(rblk.sec_type == SUBTYPE_ROOT && rblk.checksum == rsum) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -311,88 +309,88 @@ namespace DiscImageChef.Filesystems
|
||||
out string information)
|
||||
{
|
||||
StringBuilder sbInformation = new StringBuilder();
|
||||
xmlFSType = new FileSystemType();
|
||||
XmlFsType = new FileSystemType();
|
||||
information = null;
|
||||
BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian;
|
||||
|
||||
byte[] BootBlockSectors = imagePlugin.ReadSectors(0 + partition.Start, 2);
|
||||
byte[] bootBlockSectors = imagePlugin.ReadSectors(0 + partition.Start, 2);
|
||||
|
||||
BootBlock bootBlk = BigEndianMarshal.ByteArrayToStructureBigEndian<BootBlock>(BootBlockSectors);
|
||||
bootBlk.bootCode = new byte[BootBlockSectors.Length - 12];
|
||||
Array.Copy(BootBlockSectors, 12, bootBlk.bootCode, 0, bootBlk.bootCode.Length);
|
||||
BootBlockSectors[4] = BootBlockSectors[5] = BootBlockSectors[6] = BootBlockSectors[7] = 0;
|
||||
uint bsum = AmigaBootChecksum(BootBlockSectors);
|
||||
BootBlock bootBlk = BigEndianMarshal.ByteArrayToStructureBigEndian<BootBlock>(bootBlockSectors);
|
||||
bootBlk.bootCode = new byte[bootBlockSectors.Length - 12];
|
||||
Array.Copy(bootBlockSectors, 12, bootBlk.bootCode, 0, bootBlk.bootCode.Length);
|
||||
bootBlockSectors[4] = bootBlockSectors[5] = bootBlockSectors[6] = bootBlockSectors[7] = 0;
|
||||
uint bsum = AmigaBootChecksum(bootBlockSectors);
|
||||
|
||||
ulong b_root_ptr = 0;
|
||||
ulong bRootPtr = 0;
|
||||
|
||||
// If bootblock is correct, let's take its rootblock pointer
|
||||
if(bsum == bootBlk.checksum)
|
||||
{
|
||||
b_root_ptr = bootBlk.root_ptr + partition.Start;
|
||||
DicConsole.DebugWriteLine("AmigaDOS plugin", "Bootblock points to {0} as Rootblock", b_root_ptr);
|
||||
bRootPtr = bootBlk.root_ptr + partition.Start;
|
||||
DicConsole.DebugWriteLine("AmigaDOS plugin", "Bootblock points to {0} as Rootblock", bRootPtr);
|
||||
}
|
||||
|
||||
ulong[] root_ptrs =
|
||||
ulong[] rootPtrs =
|
||||
{
|
||||
b_root_ptr + partition.Start, (partition.End - partition.Start + 1) / 2 + partition.Start - 2,
|
||||
bRootPtr + partition.Start, (partition.End - partition.Start + 1) / 2 + partition.Start - 2,
|
||||
(partition.End - partition.Start + 1) / 2 + partition.Start - 1,
|
||||
(partition.End - partition.Start + 1) / 2 + partition.Start,
|
||||
(partition.End - partition.Start + 1) / 2 + partition.Start + 4
|
||||
};
|
||||
|
||||
RootBlock rootBlk = new RootBlock();
|
||||
byte[] RootBlockSector = null;
|
||||
byte[] rootBlockSector = null;
|
||||
|
||||
bool root_found = false;
|
||||
bool rootFound = false;
|
||||
uint blockSize = 0;
|
||||
|
||||
// So to handle even number of sectors
|
||||
foreach(ulong root_ptr in root_ptrs.Where(root_ptr => root_ptr < partition.End && root_ptr >= partition.Start)) {
|
||||
DicConsole.DebugWriteLine("AmigaDOS plugin", "Searching for Rootblock in sector {0}", root_ptr);
|
||||
foreach(ulong rootPtr in rootPtrs.Where(rootPtr => rootPtr < partition.End && rootPtr >= partition.Start)) {
|
||||
DicConsole.DebugWriteLine("AmigaDOS plugin", "Searching for Rootblock in sector {0}", rootPtr);
|
||||
|
||||
RootBlockSector = imagePlugin.ReadSector(root_ptr);
|
||||
rootBlockSector = imagePlugin.ReadSector(rootPtr);
|
||||
|
||||
rootBlk.type = BigEndianBitConverter.ToUInt32(RootBlockSector, 0x00);
|
||||
rootBlk.type = BigEndianBitConverter.ToUInt32(rootBlockSector, 0x00);
|
||||
DicConsole.DebugWriteLine("AmigaDOS plugin", "rootBlk.type = {0}", rootBlk.type);
|
||||
if(rootBlk.type != TypeHeader) continue;
|
||||
if(rootBlk.type != TYPE_HEADER) continue;
|
||||
|
||||
rootBlk.hashTableSize = BigEndianBitConverter.ToUInt32(RootBlockSector, 0x0C);
|
||||
rootBlk.hashTableSize = BigEndianBitConverter.ToUInt32(rootBlockSector, 0x0C);
|
||||
|
||||
DicConsole.DebugWriteLine("AmigaDOS plugin", "rootBlk.hashTableSize = {0}", rootBlk.hashTableSize);
|
||||
|
||||
blockSize = (rootBlk.hashTableSize + 56) * 4;
|
||||
uint sectorsPerBlock = (uint)(blockSize / RootBlockSector.Length);
|
||||
uint sectorsPerBlock = (uint)(blockSize / rootBlockSector.Length);
|
||||
|
||||
DicConsole.DebugWriteLine("AmigaDOS plugin", "blockSize = {0}", blockSize);
|
||||
DicConsole.DebugWriteLine("AmigaDOS plugin", "sectorsPerBlock = {0}", sectorsPerBlock);
|
||||
|
||||
if(blockSize % RootBlockSector.Length > 0) sectorsPerBlock++;
|
||||
if(blockSize % rootBlockSector.Length > 0) sectorsPerBlock++;
|
||||
|
||||
if(root_ptr + sectorsPerBlock >= partition.End) continue;
|
||||
if(rootPtr + sectorsPerBlock >= partition.End) continue;
|
||||
|
||||
RootBlockSector = imagePlugin.ReadSectors(root_ptr, sectorsPerBlock);
|
||||
rootBlockSector = imagePlugin.ReadSectors(rootPtr, sectorsPerBlock);
|
||||
|
||||
// Clear checksum on sector
|
||||
rootBlk.checksum = BigEndianBitConverter.ToUInt32(RootBlockSector, 20);
|
||||
RootBlockSector[20] = RootBlockSector[21] = RootBlockSector[22] = RootBlockSector[23] = 0;
|
||||
uint rsum = AmigaChecksum(RootBlockSector);
|
||||
rootBlk.checksum = BigEndianBitConverter.ToUInt32(rootBlockSector, 20);
|
||||
rootBlockSector[20] = rootBlockSector[21] = rootBlockSector[22] = rootBlockSector[23] = 0;
|
||||
uint rsum = AmigaChecksum(rootBlockSector);
|
||||
|
||||
DicConsole.DebugWriteLine("AmigaDOS plugin", "rootBlk.checksum = 0x{0:X8}", rootBlk.checksum);
|
||||
DicConsole.DebugWriteLine("AmigaDOS plugin", "rsum = 0x{0:X8}", rsum);
|
||||
|
||||
rootBlk.sec_type = BigEndianBitConverter.ToUInt32(RootBlockSector, RootBlockSector.Length - 4);
|
||||
rootBlk.sec_type = BigEndianBitConverter.ToUInt32(rootBlockSector, rootBlockSector.Length - 4);
|
||||
DicConsole.DebugWriteLine("AmigaDOS plugin", "rootBlk.sec_type = {0}", rootBlk.sec_type);
|
||||
|
||||
if(rootBlk.sec_type != SubTypeRoot || rootBlk.checksum != rsum) continue;
|
||||
if(rootBlk.sec_type != SUBTYPE_ROOT || rootBlk.checksum != rsum) continue;
|
||||
|
||||
RootBlockSector = imagePlugin.ReadSectors(root_ptr, sectorsPerBlock);
|
||||
root_found = true;
|
||||
rootBlockSector = imagePlugin.ReadSectors(rootPtr, sectorsPerBlock);
|
||||
rootFound = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!root_found) return;
|
||||
if(!rootFound) return;
|
||||
|
||||
rootBlk = MarshalRootBlock(RootBlockSector);
|
||||
rootBlk = MarshalRootBlock(rootBlockSector);
|
||||
|
||||
string diskName = StringHandlers.PascalToString(rootBlk.diskName, CurrentEncoding);
|
||||
|
||||
@@ -400,35 +398,35 @@ namespace DiscImageChef.Filesystems
|
||||
{
|
||||
case 0:
|
||||
sbInformation.Append("Amiga Original File System");
|
||||
xmlFSType.Type = "Amiga OFS";
|
||||
XmlFsType.Type = "Amiga OFS";
|
||||
break;
|
||||
case 1:
|
||||
sbInformation.Append("Amiga Fast File System");
|
||||
xmlFSType.Type = "Amiga FFS";
|
||||
XmlFsType.Type = "Amiga FFS";
|
||||
break;
|
||||
case 2:
|
||||
sbInformation.Append("Amiga Original File System with international characters");
|
||||
xmlFSType.Type = "Amiga OFS";
|
||||
XmlFsType.Type = "Amiga OFS";
|
||||
break;
|
||||
case 3:
|
||||
sbInformation.Append("Amiga Fast File System with international characters");
|
||||
xmlFSType.Type = "Amiga FFS";
|
||||
XmlFsType.Type = "Amiga FFS";
|
||||
break;
|
||||
case 4:
|
||||
sbInformation.Append("Amiga Original File System with directory cache");
|
||||
xmlFSType.Type = "Amiga OFS";
|
||||
XmlFsType.Type = "Amiga OFS";
|
||||
break;
|
||||
case 5:
|
||||
sbInformation.Append("Amiga Fast File System with directory cache");
|
||||
xmlFSType.Type = "Amiga FFS";
|
||||
XmlFsType.Type = "Amiga FFS";
|
||||
break;
|
||||
case 6:
|
||||
sbInformation.Append("Amiga Original File System with long filenames");
|
||||
xmlFSType.Type = "Amiga OFS2";
|
||||
XmlFsType.Type = "Amiga OFS2";
|
||||
break;
|
||||
case 7:
|
||||
sbInformation.Append("Amiga Fast File System with long filenames");
|
||||
xmlFSType.Type = "Amiga FFS2";
|
||||
XmlFsType.Type = "Amiga FFS2";
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -472,17 +470,17 @@ namespace DiscImageChef.Filesystems
|
||||
sbInformation.AppendFormat("Root block checksum is 0x{0:X8}", rootBlk.checksum).AppendLine();
|
||||
information = sbInformation.ToString();
|
||||
|
||||
xmlFSType.CreationDate = DateHandlers.AmigaToDateTime(rootBlk.cDays, rootBlk.cMins, rootBlk.cTicks);
|
||||
xmlFSType.CreationDateSpecified = true;
|
||||
xmlFSType.ModificationDate = DateHandlers.AmigaToDateTime(rootBlk.vDays, rootBlk.vMins, rootBlk.vTicks);
|
||||
xmlFSType.ModificationDateSpecified = true;
|
||||
xmlFSType.Dirty = rootBlk.bitmapFlag != 0xFFFFFFFF;
|
||||
xmlFSType.Clusters = blocks;
|
||||
xmlFSType.ClusterSize = (int)blockSize;
|
||||
xmlFSType.VolumeName = diskName;
|
||||
xmlFSType.Bootable = bsum == bootBlk.checksum;
|
||||
XmlFsType.CreationDate = DateHandlers.AmigaToDateTime(rootBlk.cDays, rootBlk.cMins, rootBlk.cTicks);
|
||||
XmlFsType.CreationDateSpecified = true;
|
||||
XmlFsType.ModificationDate = DateHandlers.AmigaToDateTime(rootBlk.vDays, rootBlk.vMins, rootBlk.vTicks);
|
||||
XmlFsType.ModificationDateSpecified = true;
|
||||
XmlFsType.Dirty = rootBlk.bitmapFlag != 0xFFFFFFFF;
|
||||
XmlFsType.Clusters = blocks;
|
||||
XmlFsType.ClusterSize = (int)blockSize;
|
||||
XmlFsType.VolumeName = diskName;
|
||||
XmlFsType.Bootable = bsum == bootBlk.checksum;
|
||||
// Useful as a serial
|
||||
xmlFSType.VolumeSerial = $"{rootBlk.checksum:X8}";
|
||||
XmlFsType.VolumeSerial = $"{rootBlk.checksum:X8}";
|
||||
}
|
||||
|
||||
static RootBlock MarshalRootBlock(byte[] block)
|
||||
@@ -511,12 +509,12 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
static uint AmigaBootChecksum(byte[] data)
|
||||
{
|
||||
uint sum, psum;
|
||||
uint sum;
|
||||
|
||||
sum = 0;
|
||||
for(int i = 0; i < data.Length; i += 4)
|
||||
{
|
||||
psum = sum;
|
||||
uint psum = sum;
|
||||
if((sum += (uint)((data[i] << 24) + (data[i + 1] << 16) + (data[i + 2] << 8) + data[i + 3])) <
|
||||
psum) sum++;
|
||||
}
|
||||
|
||||
@@ -77,14 +77,14 @@ namespace DiscImageChef.Filesystems.AppleDOS
|
||||
public AppleDOS()
|
||||
{
|
||||
Name = "Apple DOS File System";
|
||||
PluginUUID = new Guid("8658A1E9-B2E7-4BCC-9638-157A31B0A700\n");
|
||||
PluginUuid = new Guid("8658A1E9-B2E7-4BCC-9638-157A31B0A700\n");
|
||||
CurrentEncoding = new LisaRoman();
|
||||
}
|
||||
|
||||
public AppleDOS(Encoding encoding)
|
||||
{
|
||||
Name = "Apple DOS File System";
|
||||
PluginUUID = new Guid("8658A1E9-B2E7-4BCC-9638-157A31B0A700\n");
|
||||
PluginUuid = new Guid("8658A1E9-B2E7-4BCC-9638-157A31B0A700\n");
|
||||
// TODO: Until Apple ][ encoding is implemented
|
||||
CurrentEncoding = new LisaRoman();
|
||||
}
|
||||
@@ -94,7 +94,7 @@ namespace DiscImageChef.Filesystems.AppleDOS
|
||||
device = imagePlugin;
|
||||
start = partition.Start;
|
||||
Name = "Apple DOS File System";
|
||||
PluginUUID = new Guid("8658A1E9-B2E7-4BCC-9638-157A31B0A700\n");
|
||||
PluginUuid = new Guid("8658A1E9-B2E7-4BCC-9638-157A31B0A700\n");
|
||||
// TODO: Until Apple ][ encoding is implemented
|
||||
CurrentEncoding = new LisaRoman();
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ namespace DiscImageChef.Filesystems.AppleDOS
|
||||
|
||||
information = sb.ToString();
|
||||
|
||||
xmlFSType = new FileSystemType
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
Bootable = true,
|
||||
Clusters = (long)imagePlugin.ImageInfo.Sectors,
|
||||
|
||||
@@ -99,7 +99,7 @@ namespace DiscImageChef.Filesystems.AppleDOS
|
||||
}
|
||||
|
||||
// Create XML metadata for mounted filesystem
|
||||
xmlFSType = new FileSystemType
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
Bootable = true,
|
||||
Clusters = (long)device.ImageInfo.Sectors,
|
||||
@@ -109,7 +109,7 @@ namespace DiscImageChef.Filesystems.AppleDOS
|
||||
FreeClustersSpecified = true,
|
||||
Type = "Apple DOS"
|
||||
};
|
||||
xmlFSType.FreeClusters = xmlFSType.Clusters - usedSectors;
|
||||
XmlFsType.FreeClusters = XmlFsType.Clusters - usedSectors;
|
||||
|
||||
this.debug = debug;
|
||||
mounted = true;
|
||||
@@ -141,7 +141,7 @@ namespace DiscImageChef.Filesystems.AppleDOS
|
||||
Blocks = (long)device.ImageInfo.Sectors,
|
||||
FilenameLength = 30,
|
||||
Files = (ulong)catalogCache.Count,
|
||||
PluginId = PluginUUID,
|
||||
PluginId = PluginUuid,
|
||||
Type = "Apple DOS"
|
||||
};
|
||||
stat.FreeFiles = totalFileEntries - stat.Files;
|
||||
|
||||
@@ -60,58 +60,56 @@ namespace DiscImageChef.Filesystems
|
||||
public AppleHFS()
|
||||
{
|
||||
Name = "Apple Hierarchical File System";
|
||||
PluginUUID = new Guid("36405F8D-0D26-6ECC-0BBB-1D5225FF404F");
|
||||
PluginUuid = new Guid("36405F8D-0D26-6ECC-0BBB-1D5225FF404F");
|
||||
CurrentEncoding = Encoding.GetEncoding("macintosh");
|
||||
}
|
||||
|
||||
public AppleHFS(Encoding encoding)
|
||||
{
|
||||
Name = "Apple Hierarchical File System";
|
||||
PluginUUID = new Guid("36405F8D-0D26-6ECC-0BBB-1D5225FF404F");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("macintosh");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("36405F8D-0D26-6ECC-0BBB-1D5225FF404F");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("macintosh");
|
||||
}
|
||||
|
||||
public AppleHFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "Apple Hierarchical File System";
|
||||
PluginUUID = new Guid("36405F8D-0D26-6ECC-0BBB-1D5225FF404F");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("macintosh");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("36405F8D-0D26-6ECC-0BBB-1D5225FF404F");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("macintosh");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugin imagePlugin, Partition partition)
|
||||
{
|
||||
if(2 + partition.Start >= partition.End) return false;
|
||||
|
||||
byte[] mdb_sector;
|
||||
byte[] mdbSector;
|
||||
ushort drSigWord;
|
||||
|
||||
if(imagePlugin.GetSectorSize() == 2352 || imagePlugin.GetSectorSize() == 2448 ||
|
||||
imagePlugin.GetSectorSize() == 2048)
|
||||
{
|
||||
mdb_sector = imagePlugin.ReadSectors(partition.Start, 2);
|
||||
mdbSector = imagePlugin.ReadSectors(partition.Start, 2);
|
||||
|
||||
foreach(int offset in new[] {0, 0x200, 0x400, 0x600, 0x800, 0xA00})
|
||||
{
|
||||
drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, offset);
|
||||
drSigWord = BigEndianBitConverter.ToUInt16(mdbSector, offset);
|
||||
if(drSigWord != HFS_MAGIC) continue;
|
||||
|
||||
drSigWord =
|
||||
BigEndianBitConverter
|
||||
.ToUInt16(mdb_sector, offset + 0x7C); // Seek to embedded HFS+ signature
|
||||
.ToUInt16(mdbSector, offset + 0x7C); // Seek to embedded HFS+ signature
|
||||
|
||||
return drSigWord != HFSP_MAGIC;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mdb_sector = imagePlugin.ReadSector(2 + partition.Start);
|
||||
drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0);
|
||||
mdbSector = imagePlugin.ReadSector(2 + partition.Start);
|
||||
drSigWord = BigEndianBitConverter.ToUInt16(mdbSector, 0);
|
||||
|
||||
if(drSigWord != HFS_MAGIC) return false;
|
||||
|
||||
drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0x7C); // Seek to embedded HFS+ signature
|
||||
drSigWord = BigEndianBitConverter.ToUInt16(mdbSector, 0x7C); // Seek to embedded HFS+ signature
|
||||
|
||||
return drSigWord != HFSP_MAGIC;
|
||||
}
|
||||
@@ -126,11 +124,8 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
HFS_MasterDirectoryBlock MDB;
|
||||
HFS_BootBlock BB;
|
||||
|
||||
byte[] bb_sector = null;
|
||||
byte[] mdb_sector = null;
|
||||
byte[] bbSector = null;
|
||||
byte[] mdbSector = null;
|
||||
ushort drSigWord;
|
||||
|
||||
bool APMFromHDDOnCD = false;
|
||||
@@ -138,17 +133,17 @@ namespace DiscImageChef.Filesystems
|
||||
if(imagePlugin.GetSectorSize() == 2352 || imagePlugin.GetSectorSize() == 2448 ||
|
||||
imagePlugin.GetSectorSize() == 2048)
|
||||
{
|
||||
byte[] tmp_sector = imagePlugin.ReadSectors(partition.Start, 2);
|
||||
byte[] tmpSector = imagePlugin.ReadSectors(partition.Start, 2);
|
||||
|
||||
foreach(int offset in new[] {0, 0x200, 0x400, 0x600, 0x800, 0xA00})
|
||||
{
|
||||
drSigWord = BigEndianBitConverter.ToUInt16(tmp_sector, offset);
|
||||
drSigWord = BigEndianBitConverter.ToUInt16(tmpSector, offset);
|
||||
if(drSigWord != HFS_MAGIC) continue;
|
||||
|
||||
bb_sector = new byte[1024];
|
||||
mdb_sector = new byte[512];
|
||||
if(offset >= 0x400) Array.Copy(tmp_sector, offset - 0x400, bb_sector, 0, 1024);
|
||||
Array.Copy(tmp_sector, offset, mdb_sector, 0, 512);
|
||||
bbSector = new byte[1024];
|
||||
mdbSector = new byte[512];
|
||||
if(offset >= 0x400) Array.Copy(tmpSector, offset - 0x400, bbSector, 0, 1024);
|
||||
Array.Copy(tmpSector, offset, mdbSector, 0, 512);
|
||||
APMFromHDDOnCD = true;
|
||||
break;
|
||||
}
|
||||
@@ -157,15 +152,15 @@ namespace DiscImageChef.Filesystems
|
||||
}
|
||||
else
|
||||
{
|
||||
mdb_sector = imagePlugin.ReadSector(2 + partition.Start);
|
||||
drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0);
|
||||
mdbSector = imagePlugin.ReadSector(2 + partition.Start);
|
||||
drSigWord = BigEndianBitConverter.ToUInt16(mdbSector, 0);
|
||||
|
||||
if(drSigWord == HFS_MAGIC) bb_sector = imagePlugin.ReadSector(partition.Start);
|
||||
if(drSigWord == HFS_MAGIC) bbSector = imagePlugin.ReadSector(partition.Start);
|
||||
else return;
|
||||
}
|
||||
|
||||
MDB = BigEndianMarshal.ByteArrayToStructureBigEndian<HFS_MasterDirectoryBlock>(mdb_sector);
|
||||
BB = BigEndianMarshal.ByteArrayToStructureBigEndian<HFS_BootBlock>(bb_sector);
|
||||
HFS_MasterDirectoryBlock MDB = BigEndianMarshal.ByteArrayToStructureBigEndian<HFS_MasterDirectoryBlock>(mdbSector);
|
||||
HFS_BootBlock BB = BigEndianMarshal.ByteArrayToStructureBigEndian<HFS_BootBlock>(bbSector);
|
||||
|
||||
sb.AppendLine("Apple Hierarchical File System");
|
||||
sb.AppendLine();
|
||||
@@ -182,8 +177,7 @@ namespace DiscImageChef.Filesystems
|
||||
else sb.AppendLine("Volume has never been backed up");
|
||||
|
||||
if((MDB.drAtrb & 0x80) == 0x80) sb.AppendLine("Volume is locked by hardware.");
|
||||
if((MDB.drAtrb & 0x100) == 0x100) sb.AppendLine("Volume was unmonted.");
|
||||
else sb.AppendLine("Volume is mounted.");
|
||||
sb.AppendLine((MDB.drAtrb & 0x100) == 0x100 ? "Volume was unmonted." : "Volume is mounted.");
|
||||
if((MDB.drAtrb & 0x200) == 0x200) sb.AppendLine("Volume has spared bad blocks.");
|
||||
if((MDB.drAtrb & 0x400) == 0x400) sb.AppendLine("Volume does not need cache.");
|
||||
if((MDB.drAtrb & 0x800) == 0x800) sb.AppendLine("Boot volume is inconsistent.");
|
||||
@@ -275,45 +269,45 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
information = sb.ToString();
|
||||
|
||||
xmlFSType = new FileSystemType();
|
||||
XmlFsType = new FileSystemType();
|
||||
if(MDB.drVolBkUp > 0)
|
||||
{
|
||||
xmlFSType.BackupDate = DateHandlers.MacToDateTime(MDB.drVolBkUp);
|
||||
xmlFSType.BackupDateSpecified = true;
|
||||
XmlFsType.BackupDate = DateHandlers.MacToDateTime(MDB.drVolBkUp);
|
||||
XmlFsType.BackupDateSpecified = true;
|
||||
}
|
||||
xmlFSType.Bootable = BB.signature == HFSBB_MAGIC || MDB.drFndrInfo0 != 0 || MDB.drFndrInfo3 != 0 || MDB.drFndrInfo5 != 0;
|
||||
xmlFSType.Clusters = MDB.drNmAlBlks;
|
||||
xmlFSType.ClusterSize = (int)MDB.drAlBlkSiz;
|
||||
XmlFsType.Bootable = BB.signature == HFSBB_MAGIC || MDB.drFndrInfo0 != 0 || MDB.drFndrInfo3 != 0 || MDB.drFndrInfo5 != 0;
|
||||
XmlFsType.Clusters = MDB.drNmAlBlks;
|
||||
XmlFsType.ClusterSize = (int)MDB.drAlBlkSiz;
|
||||
if(MDB.drCrDate > 0)
|
||||
{
|
||||
xmlFSType.CreationDate = DateHandlers.MacToDateTime(MDB.drCrDate);
|
||||
xmlFSType.CreationDateSpecified = true;
|
||||
XmlFsType.CreationDate = DateHandlers.MacToDateTime(MDB.drCrDate);
|
||||
XmlFsType.CreationDateSpecified = true;
|
||||
}
|
||||
xmlFSType.Dirty = (MDB.drAtrb & 0x100) != 0x100;
|
||||
xmlFSType.Files = MDB.drFilCnt;
|
||||
xmlFSType.FilesSpecified = true;
|
||||
xmlFSType.FreeClusters = MDB.drFreeBks;
|
||||
xmlFSType.FreeClustersSpecified = true;
|
||||
XmlFsType.Dirty = (MDB.drAtrb & 0x100) != 0x100;
|
||||
XmlFsType.Files = MDB.drFilCnt;
|
||||
XmlFsType.FilesSpecified = true;
|
||||
XmlFsType.FreeClusters = MDB.drFreeBks;
|
||||
XmlFsType.FreeClustersSpecified = true;
|
||||
if(MDB.drLsMod > 0)
|
||||
{
|
||||
xmlFSType.ModificationDate = DateHandlers.MacToDateTime(MDB.drLsMod);
|
||||
xmlFSType.ModificationDateSpecified = true;
|
||||
XmlFsType.ModificationDate = DateHandlers.MacToDateTime(MDB.drLsMod);
|
||||
XmlFsType.ModificationDateSpecified = true;
|
||||
}
|
||||
xmlFSType.Type = "HFS";
|
||||
xmlFSType.VolumeName = StringHandlers.PascalToString(MDB.drVN, CurrentEncoding);
|
||||
XmlFsType.Type = "HFS";
|
||||
XmlFsType.VolumeName = StringHandlers.PascalToString(MDB.drVN, CurrentEncoding);
|
||||
if(MDB.drFndrInfo6 != 0 && MDB.drFndrInfo7 != 0)
|
||||
xmlFSType.VolumeSerial = $"{MDB.drFndrInfo6:X8}{MDB.drFndrInfo7:X8}";
|
||||
XmlFsType.VolumeSerial = $"{MDB.drFndrInfo6:X8}{MDB.drFndrInfo7:X8}";
|
||||
}
|
||||
|
||||
static byte[] Read2048SectorAs512(ImagePlugin imagePlugin, ulong LBA)
|
||||
static byte[] Read2048SectorAs512(ImagePlugin imagePlugin, ulong lba)
|
||||
{
|
||||
ulong LBA2k = LBA / 4;
|
||||
int Remainder = (int)(LBA % 4);
|
||||
ulong lba2K = lba / 4;
|
||||
int remainder = (int)(lba % 4);
|
||||
|
||||
byte[] buffer = imagePlugin.ReadSector(LBA2k);
|
||||
byte[] buffer = imagePlugin.ReadSector(lba2K);
|
||||
byte[] sector = new byte[512];
|
||||
|
||||
Array.Copy(buffer, Remainder * 512, sector, 0, 512);
|
||||
Array.Copy(buffer, remainder * 512, sector, 0, 512);
|
||||
|
||||
return sector;
|
||||
}
|
||||
|
||||
@@ -59,21 +59,21 @@ namespace DiscImageChef.Filesystems
|
||||
public AppleHFSPlus()
|
||||
{
|
||||
Name = "Apple HFS+ filesystem";
|
||||
PluginUUID = new Guid("36405F8D-0D26-6EBE-436F-62F0586B4F08");
|
||||
PluginUuid = new Guid("36405F8D-0D26-6EBE-436F-62F0586B4F08");
|
||||
CurrentEncoding = Encoding.BigEndianUnicode;
|
||||
}
|
||||
|
||||
public AppleHFSPlus(Encoding encoding)
|
||||
{
|
||||
Name = "Apple HFS+ filesystem";
|
||||
PluginUUID = new Guid("36405F8D-0D26-6EBE-436F-62F0586B4F08");
|
||||
PluginUuid = new Guid("36405F8D-0D26-6EBE-436F-62F0586B4F08");
|
||||
CurrentEncoding = Encoding.BigEndianUnicode;
|
||||
}
|
||||
|
||||
public AppleHFSPlus(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "Apple HFS+ filesystem";
|
||||
PluginUUID = new Guid("36405F8D-0D26-6EBE-436F-62F0586B4F08");
|
||||
PluginUuid = new Guid("36405F8D-0D26-6EBE-436F-62F0586B4F08");
|
||||
CurrentEncoding = Encoding.BigEndianUnicode;
|
||||
}
|
||||
|
||||
@@ -82,47 +82,41 @@ namespace DiscImageChef.Filesystems
|
||||
if(2 + partition.Start >= partition.End) return false;
|
||||
|
||||
ushort drSigWord;
|
||||
ushort xdrStABNt;
|
||||
ushort drAlBlSt;
|
||||
uint drAlBlkSiz;
|
||||
|
||||
byte[] vh_sector;
|
||||
ulong hfsp_offset;
|
||||
ulong hfspOffset;
|
||||
|
||||
uint sectorsToRead = 0x800 / imagePlugin.ImageInfo.SectorSize;
|
||||
if(0x800 % imagePlugin.ImageInfo.SectorSize > 0) sectorsToRead++;
|
||||
|
||||
vh_sector = imagePlugin.ReadSectors(partition.Start,
|
||||
sectorsToRead); // Read volume header, of HFS Wrapper MDB
|
||||
byte[] vhSector = imagePlugin.ReadSectors(partition.Start,
|
||||
sectorsToRead);
|
||||
|
||||
drSigWord = BigEndianBitConverter.ToUInt16(vh_sector, 0x400); // Check for HFS Wrapper MDB
|
||||
drSigWord = BigEndianBitConverter.ToUInt16(vhSector, 0x400); // Check for HFS Wrapper MDB
|
||||
|
||||
if(drSigWord == HFS_MAGIC) // "BD"
|
||||
{
|
||||
drSigWord = BigEndianBitConverter.ToUInt16(vh_sector, 0x47C); // Read embedded HFS+ signature
|
||||
drSigWord = BigEndianBitConverter.ToUInt16(vhSector, 0x47C); // Read embedded HFS+ signature
|
||||
|
||||
if(drSigWord == HFSP_MAGIC) // "H+"
|
||||
{
|
||||
xdrStABNt = BigEndianBitConverter
|
||||
.ToUInt16(vh_sector, 0x47E); // Starting block number of embedded HFS+ volume
|
||||
ushort xdrStABNt = BigEndianBitConverter
|
||||
.ToUInt16(vhSector, 0x47E);
|
||||
|
||||
drAlBlkSiz = BigEndianBitConverter.ToUInt32(vh_sector, 0x414); // Block size
|
||||
uint drAlBlkSiz = BigEndianBitConverter.ToUInt32(vhSector, 0x414);
|
||||
|
||||
drAlBlSt = BigEndianBitConverter
|
||||
.ToUInt16(vh_sector, 0x41C); // Start of allocated blocks (in 512-byte/block)
|
||||
ushort drAlBlSt = BigEndianBitConverter
|
||||
.ToUInt16(vhSector, 0x41C);
|
||||
|
||||
hfsp_offset = (ulong)((drAlBlSt * 512 + xdrStABNt * drAlBlkSiz) / imagePlugin.GetSectorSize());
|
||||
hfspOffset = (ulong)((drAlBlSt * 512 + xdrStABNt * drAlBlkSiz) / imagePlugin.GetSectorSize());
|
||||
}
|
||||
else hfsp_offset = 0;
|
||||
else hfspOffset = 0;
|
||||
}
|
||||
else hfsp_offset = 0;
|
||||
else hfspOffset = 0;
|
||||
|
||||
vh_sector = imagePlugin.ReadSectors(partition.Start + hfsp_offset, sectorsToRead); // Read volume header
|
||||
vhSector = imagePlugin.ReadSectors(partition.Start + hfspOffset, sectorsToRead); // Read volume header
|
||||
|
||||
drSigWord = BigEndianBitConverter.ToUInt16(vh_sector, 0x400);
|
||||
if(drSigWord == HFSP_MAGIC || drSigWord == HFSX_MAGIC) return true;
|
||||
|
||||
return false;
|
||||
drSigWord = BigEndianBitConverter.ToUInt16(vhSector, 0x400);
|
||||
return drSigWord == HFSP_MAGIC || drSigWord == HFSX_MAGIC;
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
|
||||
@@ -131,55 +125,51 @@ namespace DiscImageChef.Filesystems
|
||||
information = "";
|
||||
|
||||
ushort drSigWord;
|
||||
ushort xdrStABNt;
|
||||
ushort drAlBlSt;
|
||||
uint drAlBlkSiz;
|
||||
HFSPlusVolumeHeader HPVH = new HFSPlusVolumeHeader();
|
||||
|
||||
ulong hfsp_offset;
|
||||
ulong hfspOffset;
|
||||
bool wrapped;
|
||||
byte[] vh_sector;
|
||||
|
||||
uint sectorsToRead = 0x800 / imagePlugin.ImageInfo.SectorSize;
|
||||
if(0x800 % imagePlugin.ImageInfo.SectorSize > 0) sectorsToRead++;
|
||||
|
||||
vh_sector = imagePlugin.ReadSectors(partition.Start,
|
||||
sectorsToRead); // Read volume header, of HFS Wrapper MDB
|
||||
byte[] vhSector = imagePlugin.ReadSectors(partition.Start,
|
||||
sectorsToRead);
|
||||
|
||||
drSigWord = BigEndianBitConverter.ToUInt16(vh_sector, 0x400); // Check for HFS Wrapper MDB
|
||||
drSigWord = BigEndianBitConverter.ToUInt16(vhSector, 0x400); // Check for HFS Wrapper MDB
|
||||
|
||||
if(drSigWord == HFS_MAGIC) // "BD"
|
||||
{
|
||||
drSigWord = BigEndianBitConverter.ToUInt16(vh_sector, 0x47C); // Read embedded HFS+ signature
|
||||
drSigWord = BigEndianBitConverter.ToUInt16(vhSector, 0x47C); // Read embedded HFS+ signature
|
||||
|
||||
if(drSigWord == HFSP_MAGIC) // "H+"
|
||||
{
|
||||
xdrStABNt = BigEndianBitConverter
|
||||
.ToUInt16(vh_sector, 0x47E); // Starting block number of embedded HFS+ volume
|
||||
ushort xdrStABNt = BigEndianBitConverter
|
||||
.ToUInt16(vhSector, 0x47E);
|
||||
|
||||
drAlBlkSiz = BigEndianBitConverter.ToUInt32(vh_sector, 0x414); // Block size
|
||||
uint drAlBlkSiz = BigEndianBitConverter.ToUInt32(vhSector, 0x414);
|
||||
|
||||
drAlBlSt = BigEndianBitConverter
|
||||
.ToUInt16(vh_sector, 0x41C); // Start of allocated blocks (in 512-byte/block)
|
||||
ushort drAlBlSt = BigEndianBitConverter
|
||||
.ToUInt16(vhSector, 0x41C);
|
||||
|
||||
hfsp_offset = (ulong)((drAlBlSt * 512 + xdrStABNt * drAlBlkSiz) / imagePlugin.GetSectorSize());
|
||||
hfspOffset = (ulong)((drAlBlSt * 512 + xdrStABNt * drAlBlkSiz) / imagePlugin.GetSectorSize());
|
||||
wrapped = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
hfsp_offset = 0;
|
||||
hfspOffset = 0;
|
||||
wrapped = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hfsp_offset = 0;
|
||||
hfspOffset = 0;
|
||||
wrapped = false;
|
||||
}
|
||||
|
||||
vh_sector = imagePlugin.ReadSectors(partition.Start + hfsp_offset, sectorsToRead); // Read volume header
|
||||
vhSector = imagePlugin.ReadSectors(partition.Start + hfspOffset, sectorsToRead); // Read volume header
|
||||
|
||||
HPVH.signature = BigEndianBitConverter.ToUInt16(vh_sector, 0x400);
|
||||
HPVH.signature = BigEndianBitConverter.ToUInt16(vhSector, 0x400);
|
||||
if(HPVH.signature == HFSP_MAGIC || HPVH.signature == HFSX_MAGIC)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
@@ -189,10 +179,10 @@ namespace DiscImageChef.Filesystems
|
||||
if(wrapped) sb.AppendLine("Volume is wrapped inside an HFS volume.");
|
||||
|
||||
byte[] tmp = new byte[0x400];
|
||||
Array.Copy(vh_sector, 0x400, tmp, 0, 0x400);
|
||||
vh_sector = tmp;
|
||||
Array.Copy(vhSector, 0x400, tmp, 0, 0x400);
|
||||
vhSector = tmp;
|
||||
|
||||
HPVH = BigEndianMarshal.ByteArrayToStructureBigEndian<HFSPlusVolumeHeader>(vh_sector);
|
||||
HPVH = BigEndianMarshal.ByteArrayToStructureBigEndian<HFSPlusVolumeHeader>(vhSector);
|
||||
|
||||
if(HPVH.version == 4 || HPVH.version == 5)
|
||||
{
|
||||
@@ -247,35 +237,35 @@ namespace DiscImageChef.Filesystems
|
||||
sb.AppendFormat("Mac OS X Volume ID: {0:X8}{1:X8}", HPVH.drFndrInfo6, HPVH.drFndrInfo7)
|
||||
.AppendLine();
|
||||
|
||||
xmlFSType = new FileSystemType();
|
||||
XmlFsType = new FileSystemType();
|
||||
if(HPVH.backupDate > 0)
|
||||
{
|
||||
xmlFSType.BackupDate = DateHandlers.MacToDateTime(HPVH.backupDate);
|
||||
xmlFSType.BackupDateSpecified = true;
|
||||
XmlFsType.BackupDate = DateHandlers.MacToDateTime(HPVH.backupDate);
|
||||
XmlFsType.BackupDateSpecified = true;
|
||||
}
|
||||
xmlFSType.Bootable |= HPVH.drFndrInfo0 != 0 || HPVH.drFndrInfo3 != 0 || HPVH.drFndrInfo5 != 0;
|
||||
xmlFSType.Clusters = HPVH.totalBlocks;
|
||||
xmlFSType.ClusterSize = (int)HPVH.blockSize;
|
||||
XmlFsType.Bootable |= HPVH.drFndrInfo0 != 0 || HPVH.drFndrInfo3 != 0 || HPVH.drFndrInfo5 != 0;
|
||||
XmlFsType.Clusters = HPVH.totalBlocks;
|
||||
XmlFsType.ClusterSize = (int)HPVH.blockSize;
|
||||
if(HPVH.createDate > 0)
|
||||
{
|
||||
xmlFSType.CreationDate = DateHandlers.MacToDateTime(HPVH.createDate);
|
||||
xmlFSType.CreationDateSpecified = true;
|
||||
XmlFsType.CreationDate = DateHandlers.MacToDateTime(HPVH.createDate);
|
||||
XmlFsType.CreationDateSpecified = true;
|
||||
}
|
||||
xmlFSType.Dirty = (HPVH.attributes & 0x100) != 0x100;
|
||||
xmlFSType.Files = HPVH.fileCount;
|
||||
xmlFSType.FilesSpecified = true;
|
||||
xmlFSType.FreeClusters = HPVH.freeBlocks;
|
||||
xmlFSType.FreeClustersSpecified = true;
|
||||
XmlFsType.Dirty = (HPVH.attributes & 0x100) != 0x100;
|
||||
XmlFsType.Files = HPVH.fileCount;
|
||||
XmlFsType.FilesSpecified = true;
|
||||
XmlFsType.FreeClusters = HPVH.freeBlocks;
|
||||
XmlFsType.FreeClustersSpecified = true;
|
||||
if(HPVH.modifyDate > 0)
|
||||
{
|
||||
xmlFSType.ModificationDate = DateHandlers.MacToDateTime(HPVH.modifyDate);
|
||||
xmlFSType.ModificationDateSpecified = true;
|
||||
XmlFsType.ModificationDate = DateHandlers.MacToDateTime(HPVH.modifyDate);
|
||||
XmlFsType.ModificationDateSpecified = true;
|
||||
}
|
||||
if(HPVH.signature == 0x482B) xmlFSType.Type = "HFS+";
|
||||
if(HPVH.signature == 0x4858) xmlFSType.Type = "HFSX";
|
||||
if(HPVH.signature == 0x482B) XmlFsType.Type = "HFS+";
|
||||
if(HPVH.signature == 0x4858) XmlFsType.Type = "HFSX";
|
||||
if(HPVH.drFndrInfo6 != 0 && HPVH.drFndrInfo7 != 0)
|
||||
xmlFSType.VolumeSerial = $"{HPVH.drFndrInfo6:X8}{HPVH.drFndrInfo7:X8}";
|
||||
xmlFSType.SystemIdentifier = Encoding.ASCII.GetString(HPVH.lastMountedVersion);
|
||||
XmlFsType.VolumeSerial = $"{HPVH.drFndrInfo6:X8}{HPVH.drFndrInfo7:X8}";
|
||||
XmlFsType.SystemIdentifier = Encoding.ASCII.GetString(HPVH.lastMountedVersion);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -65,26 +65,24 @@ namespace DiscImageChef.Filesystems.AppleMFS
|
||||
public AppleMFS()
|
||||
{
|
||||
Name = "Apple Macintosh File System";
|
||||
PluginUUID = new Guid("36405F8D-0D26-4066-6538-5DBF5D065C3A");
|
||||
PluginUuid = new Guid("36405F8D-0D26-4066-6538-5DBF5D065C3A");
|
||||
CurrentEncoding = Encoding.GetEncoding("macintosh");
|
||||
}
|
||||
|
||||
public AppleMFS(Encoding encoding)
|
||||
{
|
||||
Name = "Apple Macintosh File System";
|
||||
PluginUUID = new Guid("36405F8D-0D26-4066-6538-5DBF5D065C3A");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("macintosh");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("36405F8D-0D26-4066-6538-5DBF5D065C3A");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("macintosh");
|
||||
}
|
||||
|
||||
public AppleMFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "Apple Macintosh File System";
|
||||
PluginUUID = new Guid("36405F8D-0D26-4066-6538-5DBF5D065C3A");
|
||||
PluginUuid = new Guid("36405F8D-0D26-4066-6538-5DBF5D065C3A");
|
||||
device = imagePlugin;
|
||||
partitionStart = partition.Start;
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("macintosh");
|
||||
else CurrentEncoding = encoding;
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("macintosh");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -61,7 +61,7 @@ namespace DiscImageChef.Filesystems.AppleMFS
|
||||
return Errno.NoError;
|
||||
}
|
||||
|
||||
public bool FillDirectory()
|
||||
bool FillDirectory()
|
||||
{
|
||||
idToFilename = new Dictionary<uint, string>();
|
||||
idToEntry = new Dictionary<uint, MFS_FileEntry>();
|
||||
@@ -70,11 +70,12 @@ namespace DiscImageChef.Filesystems.AppleMFS
|
||||
int offset = 0;
|
||||
while(offset + 51 < directoryBlocks.Length)
|
||||
{
|
||||
MFS_FileEntry entry = new MFS_FileEntry();
|
||||
string lowerFilename;
|
||||
entry.flUsrWds = new byte[16];
|
||||
MFS_FileEntry entry = new MFS_FileEntry
|
||||
{
|
||||
flUsrWds = new byte[16],
|
||||
flFlags = (MFS_FileFlags)directoryBlocks[offset + 0]
|
||||
};
|
||||
|
||||
entry.flFlags = (MFS_FileFlags)directoryBlocks[offset + 0];
|
||||
if(!entry.flFlags.HasFlag(MFS_FileFlags.Used)) break;
|
||||
|
||||
entry.flTyp = directoryBlocks[offset + 1];
|
||||
@@ -90,7 +91,7 @@ namespace DiscImageChef.Filesystems.AppleMFS
|
||||
entry.flMdDat = BigEndianBitConverter.ToUInt32(directoryBlocks, offset + 46);
|
||||
entry.flNam = new byte[directoryBlocks[offset + 50] + 1];
|
||||
Array.Copy(directoryBlocks, offset + 50, entry.flNam, 0, entry.flNam.Length);
|
||||
lowerFilename = StringHandlers.PascalToString(entry.flNam, CurrentEncoding).ToLowerInvariant()
|
||||
string lowerFilename = StringHandlers.PascalToString(entry.flNam, CurrentEncoding).ToLowerInvariant()
|
||||
.Replace('/', ':');
|
||||
|
||||
if(entry.flFlags.HasFlag(MFS_FileFlags.Used) && !idToFilename.ContainsKey(entry.flFlNum) &&
|
||||
|
||||
@@ -49,12 +49,9 @@ namespace DiscImageChef.Filesystems.AppleMFS
|
||||
string[] pathElements = path.Split(new[] {'/'}, StringSplitOptions.RemoveEmptyEntries);
|
||||
if(pathElements.Length != 1) return Errno.NotSupported;
|
||||
|
||||
uint fileID;
|
||||
MFS_FileEntry entry;
|
||||
if(!filenameToId.TryGetValue(path.ToLowerInvariant(), out uint fileId)) return Errno.NoSuchFile;
|
||||
|
||||
if(!filenameToId.TryGetValue(path.ToLowerInvariant(), out fileID)) return Errno.NoSuchFile;
|
||||
|
||||
if(!idToEntry.TryGetValue(fileID, out entry)) return Errno.NoSuchFile;
|
||||
if(!idToEntry.TryGetValue(fileId, out MFS_FileEntry entry)) return Errno.NoSuchFile;
|
||||
|
||||
if(fileBlock > entry.flPyLen / volMDB.drAlBlkSiz) return Errno.InvalidArgument;
|
||||
|
||||
@@ -85,12 +82,9 @@ namespace DiscImageChef.Filesystems.AppleMFS
|
||||
string[] pathElements = path.Split(new[] {'/'}, StringSplitOptions.RemoveEmptyEntries);
|
||||
if(pathElements.Length != 1) return Errno.NotSupported;
|
||||
|
||||
uint fileID;
|
||||
MFS_FileEntry entry;
|
||||
if(!filenameToId.TryGetValue(path.ToLowerInvariant(), out uint fileId)) return Errno.NoSuchFile;
|
||||
|
||||
if(!filenameToId.TryGetValue(path.ToLowerInvariant(), out fileID)) return Errno.NoSuchFile;
|
||||
|
||||
if(!idToEntry.TryGetValue(fileID, out entry)) return Errno.NoSuchFile;
|
||||
if(!idToEntry.TryGetValue(fileId, out MFS_FileEntry entry)) return Errno.NoSuchFile;
|
||||
|
||||
attributes = new FileAttributes();
|
||||
MFS_FinderFlags fdFlags = (MFS_FinderFlags)BigEndianBitConverter.ToUInt16(entry.flUsrWds, 0x08);
|
||||
@@ -161,16 +155,17 @@ namespace DiscImageChef.Filesystems.AppleMFS
|
||||
string.Compare(path, "$Bitmap", StringComparison.InvariantCulture) == 0 ||
|
||||
string.Compare(path, "$MDB", StringComparison.InvariantCulture) == 0)
|
||||
{
|
||||
stat = new FileEntryInfo();
|
||||
stat.Attributes = new FileAttributes();
|
||||
stat.Attributes = FileAttributes.System;
|
||||
stat.BlockSize = device.GetSectorSize();
|
||||
stat.DeviceNo = 0;
|
||||
stat.GID = 0;
|
||||
stat.Inode = 0;
|
||||
stat.Links = 1;
|
||||
stat.Mode = 0x124;
|
||||
stat.UID = 0;
|
||||
stat = new FileEntryInfo
|
||||
{
|
||||
BlockSize = device.GetSectorSize(),
|
||||
DeviceNo = 0,
|
||||
GID = 0,
|
||||
Inode = 0,
|
||||
Links = 1,
|
||||
Mode = 0x124,
|
||||
UID = 0,
|
||||
Attributes = FileAttributes.System
|
||||
};
|
||||
|
||||
if(string.Compare(path, "$", StringComparison.InvariantCulture) == 0)
|
||||
{
|
||||
@@ -198,30 +193,29 @@ namespace DiscImageChef.Filesystems.AppleMFS
|
||||
return Errno.NoError;
|
||||
}
|
||||
|
||||
uint fileID;
|
||||
MFS_FileEntry entry;
|
||||
if(!filenameToId.TryGetValue(path.ToLowerInvariant(), out uint fileId)) return Errno.NoSuchFile;
|
||||
|
||||
if(!filenameToId.TryGetValue(path.ToLowerInvariant(), out fileID)) return Errno.NoSuchFile;
|
||||
|
||||
if(!idToEntry.TryGetValue(fileID, out entry)) return Errno.NoSuchFile;
|
||||
if(!idToEntry.TryGetValue(fileId, out MFS_FileEntry entry)) return Errno.NoSuchFile;
|
||||
|
||||
FileAttributes attr = new FileAttributes();
|
||||
Errno error = GetAttributes(path, ref attr);
|
||||
if(error != Errno.NoError) return error;
|
||||
|
||||
stat = new FileEntryInfo();
|
||||
stat.Attributes = attr;
|
||||
stat.Blocks = entry.flLgLen / volMDB.drAlBlkSiz;
|
||||
stat.BlockSize = volMDB.drAlBlkSiz;
|
||||
stat.CreationTime = DateHandlers.MacToDateTime(entry.flCrDat);
|
||||
stat.DeviceNo = 0;
|
||||
stat.GID = 0;
|
||||
stat.Inode = entry.flFlNum;
|
||||
stat.LastWriteTime = DateHandlers.MacToDateTime(entry.flMdDat);
|
||||
stat.Length = entry.flPyLen;
|
||||
stat.Links = 1;
|
||||
stat.Mode = 0x124;
|
||||
stat.UID = 0;
|
||||
stat = new FileEntryInfo
|
||||
{
|
||||
Attributes = attr,
|
||||
Blocks = entry.flLgLen / volMDB.drAlBlkSiz,
|
||||
BlockSize = volMDB.drAlBlkSiz,
|
||||
CreationTime = DateHandlers.MacToDateTime(entry.flCrDat),
|
||||
DeviceNo = 0,
|
||||
GID = 0,
|
||||
Inode = entry.flFlNum,
|
||||
LastWriteTime = DateHandlers.MacToDateTime(entry.flMdDat),
|
||||
Length = entry.flPyLen,
|
||||
Links = 1,
|
||||
Mode = 0x124,
|
||||
UID = 0
|
||||
};
|
||||
|
||||
return Errno.NoError;
|
||||
}
|
||||
@@ -240,12 +234,9 @@ namespace DiscImageChef.Filesystems.AppleMFS
|
||||
string[] pathElements = path.Split(new[] {'/'}, StringSplitOptions.RemoveEmptyEntries);
|
||||
if(pathElements.Length != 1) return Errno.NotSupported;
|
||||
|
||||
uint fileID;
|
||||
MFS_FileEntry entry;
|
||||
if(!filenameToId.TryGetValue(path.ToLowerInvariant(), out uint fileId)) return Errno.NoSuchFile;
|
||||
|
||||
if(!filenameToId.TryGetValue(path.ToLowerInvariant(), out fileID)) return Errno.NoSuchFile;
|
||||
|
||||
if(!idToEntry.TryGetValue(fileID, out entry)) return Errno.NoSuchFile;
|
||||
if(!idToEntry.TryGetValue(fileId, out MFS_FileEntry entry)) return Errno.NoSuchFile;
|
||||
|
||||
uint nextBlock;
|
||||
|
||||
@@ -271,10 +262,10 @@ namespace DiscImageChef.Filesystems.AppleMFS
|
||||
}
|
||||
|
||||
MemoryStream ms = new MemoryStream();
|
||||
byte[] sectors;
|
||||
|
||||
do
|
||||
{
|
||||
byte[] sectors;
|
||||
if(tags)
|
||||
sectors =
|
||||
device.ReadSectorsTag((ulong)((nextBlock - 2) * sectorsPerBlock) + volMDB.drAlBlSt + partitionStart,
|
||||
|
||||
@@ -47,11 +47,11 @@ namespace DiscImageChef.Filesystems.AppleMFS
|
||||
|
||||
if(2 + partition.Start >= partition.End) return false;
|
||||
|
||||
byte[] mdb_sector = imagePlugin.ReadSector(2 + partition.Start);
|
||||
byte[] mdbSector = imagePlugin.ReadSector(2 + partition.Start);
|
||||
|
||||
BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian;
|
||||
|
||||
drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0x000);
|
||||
drSigWord = BigEndianBitConverter.ToUInt16(mdbSector, 0x000);
|
||||
|
||||
return drSigWord == MFS_MAGIC;
|
||||
}
|
||||
@@ -67,63 +67,62 @@ namespace DiscImageChef.Filesystems.AppleMFS
|
||||
MFS_BootBlock BB = new MFS_BootBlock();
|
||||
|
||||
byte[] pString = new byte[16];
|
||||
byte[] variable_size;
|
||||
|
||||
byte[] mdb_sector = imagePlugin.ReadSector(2 + partition.Start);
|
||||
byte[] bb_sector = imagePlugin.ReadSector(0 + partition.Start);
|
||||
byte[] mdbSector = imagePlugin.ReadSector(2 + partition.Start);
|
||||
byte[] bbSector = imagePlugin.ReadSector(0 + partition.Start);
|
||||
|
||||
BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian;
|
||||
|
||||
MDB.drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0x000);
|
||||
MDB.drSigWord = BigEndianBitConverter.ToUInt16(mdbSector, 0x000);
|
||||
if(MDB.drSigWord != MFS_MAGIC) return;
|
||||
|
||||
MDB.drCrDate = BigEndianBitConverter.ToUInt32(mdb_sector, 0x002);
|
||||
MDB.drLsBkUp = BigEndianBitConverter.ToUInt32(mdb_sector, 0x006);
|
||||
MDB.drAtrb = BigEndianBitConverter.ToUInt16(mdb_sector, 0x00A);
|
||||
MDB.drNmFls = BigEndianBitConverter.ToUInt16(mdb_sector, 0x00C);
|
||||
MDB.drDirSt = BigEndianBitConverter.ToUInt16(mdb_sector, 0x00E);
|
||||
MDB.drBlLen = BigEndianBitConverter.ToUInt16(mdb_sector, 0x010);
|
||||
MDB.drNmAlBlks = BigEndianBitConverter.ToUInt16(mdb_sector, 0x012);
|
||||
MDB.drAlBlkSiz = BigEndianBitConverter.ToUInt32(mdb_sector, 0x014);
|
||||
MDB.drClpSiz = BigEndianBitConverter.ToUInt32(mdb_sector, 0x018);
|
||||
MDB.drAlBlSt = BigEndianBitConverter.ToUInt16(mdb_sector, 0x01C);
|
||||
MDB.drNxtFNum = BigEndianBitConverter.ToUInt32(mdb_sector, 0x01E);
|
||||
MDB.drFreeBks = BigEndianBitConverter.ToUInt16(mdb_sector, 0x022);
|
||||
MDB.drVNSiz = mdb_sector[0x024];
|
||||
variable_size = new byte[MDB.drVNSiz + 1];
|
||||
Array.Copy(mdb_sector, 0x024, variable_size, 0, MDB.drVNSiz + 1);
|
||||
MDB.drVN = StringHandlers.PascalToString(variable_size, CurrentEncoding);
|
||||
MDB.drCrDate = BigEndianBitConverter.ToUInt32(mdbSector, 0x002);
|
||||
MDB.drLsBkUp = BigEndianBitConverter.ToUInt32(mdbSector, 0x006);
|
||||
MDB.drAtrb = BigEndianBitConverter.ToUInt16(mdbSector, 0x00A);
|
||||
MDB.drNmFls = BigEndianBitConverter.ToUInt16(mdbSector, 0x00C);
|
||||
MDB.drDirSt = BigEndianBitConverter.ToUInt16(mdbSector, 0x00E);
|
||||
MDB.drBlLen = BigEndianBitConverter.ToUInt16(mdbSector, 0x010);
|
||||
MDB.drNmAlBlks = BigEndianBitConverter.ToUInt16(mdbSector, 0x012);
|
||||
MDB.drAlBlkSiz = BigEndianBitConverter.ToUInt32(mdbSector, 0x014);
|
||||
MDB.drClpSiz = BigEndianBitConverter.ToUInt32(mdbSector, 0x018);
|
||||
MDB.drAlBlSt = BigEndianBitConverter.ToUInt16(mdbSector, 0x01C);
|
||||
MDB.drNxtFNum = BigEndianBitConverter.ToUInt32(mdbSector, 0x01E);
|
||||
MDB.drFreeBks = BigEndianBitConverter.ToUInt16(mdbSector, 0x022);
|
||||
MDB.drVNSiz = mdbSector[0x024];
|
||||
byte[] variableSize = new byte[MDB.drVNSiz + 1];
|
||||
Array.Copy(mdbSector, 0x024, variableSize, 0, MDB.drVNSiz + 1);
|
||||
MDB.drVN = StringHandlers.PascalToString(variableSize, CurrentEncoding);
|
||||
|
||||
BB.signature = BigEndianBitConverter.ToUInt16(bb_sector, 0x000);
|
||||
BB.signature = BigEndianBitConverter.ToUInt16(bbSector, 0x000);
|
||||
|
||||
if(BB.signature == MFSBB_MAGIC)
|
||||
{
|
||||
BB.branch = BigEndianBitConverter.ToUInt32(bb_sector, 0x002);
|
||||
BB.boot_flags = bb_sector[0x006];
|
||||
BB.boot_version = bb_sector[0x007];
|
||||
BB.branch = BigEndianBitConverter.ToUInt32(bbSector, 0x002);
|
||||
BB.boot_flags = bbSector[0x006];
|
||||
BB.boot_version = bbSector[0x007];
|
||||
|
||||
BB.sec_sv_pages = BigEndianBitConverter.ToInt16(bb_sector, 0x008);
|
||||
BB.sec_sv_pages = BigEndianBitConverter.ToInt16(bbSector, 0x008);
|
||||
|
||||
Array.Copy(mdb_sector, 0x00A, pString, 0, 16);
|
||||
Array.Copy(mdbSector, 0x00A, pString, 0, 16);
|
||||
BB.system_name = StringHandlers.PascalToString(pString, CurrentEncoding);
|
||||
Array.Copy(mdb_sector, 0x01A, pString, 0, 16);
|
||||
Array.Copy(mdbSector, 0x01A, pString, 0, 16);
|
||||
BB.finder_name = StringHandlers.PascalToString(pString, CurrentEncoding);
|
||||
Array.Copy(mdb_sector, 0x02A, pString, 0, 16);
|
||||
Array.Copy(mdbSector, 0x02A, pString, 0, 16);
|
||||
BB.debug_name = StringHandlers.PascalToString(pString, CurrentEncoding);
|
||||
Array.Copy(mdb_sector, 0x03A, pString, 0, 16);
|
||||
Array.Copy(mdbSector, 0x03A, pString, 0, 16);
|
||||
BB.disasm_name = StringHandlers.PascalToString(pString, CurrentEncoding);
|
||||
Array.Copy(mdb_sector, 0x04A, pString, 0, 16);
|
||||
Array.Copy(mdbSector, 0x04A, pString, 0, 16);
|
||||
BB.stupscr_name = StringHandlers.PascalToString(pString, CurrentEncoding);
|
||||
Array.Copy(mdb_sector, 0x05A, pString, 0, 16);
|
||||
Array.Copy(mdbSector, 0x05A, pString, 0, 16);
|
||||
BB.bootup_name = StringHandlers.PascalToString(pString, CurrentEncoding);
|
||||
Array.Copy(mdb_sector, 0x06A, pString, 0, 16);
|
||||
Array.Copy(mdbSector, 0x06A, pString, 0, 16);
|
||||
BB.clipbrd_name = StringHandlers.PascalToString(pString, CurrentEncoding);
|
||||
|
||||
BB.max_files = BigEndianBitConverter.ToUInt16(bb_sector, 0x07A);
|
||||
BB.queue_size = BigEndianBitConverter.ToUInt16(bb_sector, 0x07C);
|
||||
BB.heap_128k = BigEndianBitConverter.ToUInt32(bb_sector, 0x07E);
|
||||
BB.heap_256k = BigEndianBitConverter.ToUInt32(bb_sector, 0x082);
|
||||
BB.heap_512k = BigEndianBitConverter.ToUInt32(bb_sector, 0x086);
|
||||
BB.max_files = BigEndianBitConverter.ToUInt16(bbSector, 0x07A);
|
||||
BB.queue_size = BigEndianBitConverter.ToUInt16(bbSector, 0x07C);
|
||||
BB.heap_128k = BigEndianBitConverter.ToUInt32(bbSector, 0x07E);
|
||||
BB.heap_256k = BigEndianBitConverter.ToUInt32(bbSector, 0x082);
|
||||
BB.heap_512k = BigEndianBitConverter.ToUInt32(bbSector, 0x086);
|
||||
}
|
||||
else BB.signature = 0x0000;
|
||||
|
||||
@@ -175,26 +174,26 @@ namespace DiscImageChef.Filesystems.AppleMFS
|
||||
|
||||
information = sb.ToString();
|
||||
|
||||
xmlFSType = new FileSystemType();
|
||||
XmlFsType = new FileSystemType();
|
||||
if(MDB.drLsBkUp > 0)
|
||||
{
|
||||
xmlFSType.BackupDate = DateHandlers.MacToDateTime(MDB.drLsBkUp);
|
||||
xmlFSType.BackupDateSpecified = true;
|
||||
XmlFsType.BackupDate = DateHandlers.MacToDateTime(MDB.drLsBkUp);
|
||||
XmlFsType.BackupDateSpecified = true;
|
||||
}
|
||||
xmlFSType.Bootable = BB.signature == MFSBB_MAGIC;
|
||||
xmlFSType.Clusters = MDB.drNmAlBlks;
|
||||
xmlFSType.ClusterSize = (int)MDB.drAlBlkSiz;
|
||||
XmlFsType.Bootable = BB.signature == MFSBB_MAGIC;
|
||||
XmlFsType.Clusters = MDB.drNmAlBlks;
|
||||
XmlFsType.ClusterSize = (int)MDB.drAlBlkSiz;
|
||||
if(MDB.drCrDate > 0)
|
||||
{
|
||||
xmlFSType.CreationDate = DateHandlers.MacToDateTime(MDB.drCrDate);
|
||||
xmlFSType.CreationDateSpecified = true;
|
||||
XmlFsType.CreationDate = DateHandlers.MacToDateTime(MDB.drCrDate);
|
||||
XmlFsType.CreationDateSpecified = true;
|
||||
}
|
||||
xmlFSType.Files = MDB.drNmFls;
|
||||
xmlFSType.FilesSpecified = true;
|
||||
xmlFSType.FreeClusters = MDB.drFreeBks;
|
||||
xmlFSType.FreeClustersSpecified = true;
|
||||
xmlFSType.Type = "MFS";
|
||||
xmlFSType.VolumeName = MDB.drVN;
|
||||
XmlFsType.Files = MDB.drNmFls;
|
||||
XmlFsType.FilesSpecified = true;
|
||||
XmlFsType.FreeClusters = MDB.drFreeBks;
|
||||
XmlFsType.FreeClustersSpecified = true;
|
||||
XmlFsType.Type = "MFS";
|
||||
XmlFsType.VolumeName = MDB.drVN;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,10 +31,14 @@
|
||||
// ****************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
#pragma warning disable 169
|
||||
|
||||
namespace DiscImageChef.Filesystems.AppleMFS
|
||||
{
|
||||
// Information from Inside Macintosh Volume II
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "NotAccessedField.Local")]
|
||||
public partial class AppleMFS
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -44,8 +44,6 @@ namespace DiscImageChef.Filesystems.AppleMFS
|
||||
this.debug = debug;
|
||||
volMDB = new MFS_MasterDirectoryBlock();
|
||||
|
||||
byte[] variable_size;
|
||||
|
||||
mdbBlocks = device.ReadSector(2 + partitionStart);
|
||||
bootBlocks = device.ReadSector(0 + partitionStart);
|
||||
|
||||
@@ -67,19 +65,19 @@ namespace DiscImageChef.Filesystems.AppleMFS
|
||||
volMDB.drNxtFNum = BigEndianBitConverter.ToUInt32(mdbBlocks, 0x01E);
|
||||
volMDB.drFreeBks = BigEndianBitConverter.ToUInt16(mdbBlocks, 0x022);
|
||||
volMDB.drVNSiz = mdbBlocks[0x024];
|
||||
variable_size = new byte[volMDB.drVNSiz + 1];
|
||||
Array.Copy(mdbBlocks, 0x024, variable_size, 0, volMDB.drVNSiz + 1);
|
||||
volMDB.drVN = StringHandlers.PascalToString(variable_size, CurrentEncoding);
|
||||
byte[] variableSize = new byte[volMDB.drVNSiz + 1];
|
||||
Array.Copy(mdbBlocks, 0x024, variableSize, 0, volMDB.drVNSiz + 1);
|
||||
volMDB.drVN = StringHandlers.PascalToString(variableSize, CurrentEncoding);
|
||||
|
||||
directoryBlocks = device.ReadSectors(volMDB.drDirSt + partitionStart, volMDB.drBlLen);
|
||||
int bytesInBlockMap = volMDB.drNmAlBlks * 12 / 8 + volMDB.drNmAlBlks * 12 % 8;
|
||||
int bytesBeforeBlockMap = 64;
|
||||
int bytesInWholeMDB = bytesInBlockMap + bytesBeforeBlockMap;
|
||||
int sectorsInWholeMDB = bytesInWholeMDB / (int)device.ImageInfo.SectorSize +
|
||||
bytesInWholeMDB % (int)device.ImageInfo.SectorSize;
|
||||
byte[] wholeMDB = device.ReadSectors(partitionStart + 2, (uint)sectorsInWholeMDB);
|
||||
const int BYTES_BEFORE_BLOCK_MAP = 64;
|
||||
int bytesInWholeMdb = bytesInBlockMap + BYTES_BEFORE_BLOCK_MAP;
|
||||
int sectorsInWholeMdb = bytesInWholeMdb / (int)device.ImageInfo.SectorSize +
|
||||
bytesInWholeMdb % (int)device.ImageInfo.SectorSize;
|
||||
byte[] wholeMdb = device.ReadSectors(partitionStart + 2, (uint)sectorsInWholeMdb);
|
||||
blockMapBytes = new byte[bytesInBlockMap];
|
||||
Array.Copy(wholeMDB, bytesBeforeBlockMap, blockMapBytes, 0, blockMapBytes.Length);
|
||||
Array.Copy(wholeMdb, BYTES_BEFORE_BLOCK_MAP, blockMapBytes, 0, blockMapBytes.Length);
|
||||
|
||||
int offset = 0;
|
||||
blockMap = new uint[volMDB.drNmAlBlks + 2 + 1];
|
||||
@@ -113,7 +111,7 @@ namespace DiscImageChef.Filesystems.AppleMFS
|
||||
bootTags = device.ReadSectorTag(0 + partitionStart, SectorTagType.AppleSectorTag);
|
||||
directoryTags = device.ReadSectorsTag(volMDB.drDirSt + partitionStart, volMDB.drBlLen,
|
||||
SectorTagType.AppleSectorTag);
|
||||
bitmapTags = device.ReadSectorsTag(partitionStart + 2, (uint)sectorsInWholeMDB,
|
||||
bitmapTags = device.ReadSectorsTag(partitionStart + 2, (uint)sectorsInWholeMdb,
|
||||
SectorTagType.AppleSectorTag);
|
||||
}
|
||||
|
||||
@@ -127,26 +125,26 @@ namespace DiscImageChef.Filesystems.AppleMFS
|
||||
|
||||
if(bbSig != MFSBB_MAGIC) bootBlocks = null;
|
||||
|
||||
xmlFSType = new FileSystemType();
|
||||
XmlFsType = new FileSystemType();
|
||||
if(volMDB.drLsBkUp > 0)
|
||||
{
|
||||
xmlFSType.BackupDate = DateHandlers.MacToDateTime(volMDB.drLsBkUp);
|
||||
xmlFSType.BackupDateSpecified = true;
|
||||
XmlFsType.BackupDate = DateHandlers.MacToDateTime(volMDB.drLsBkUp);
|
||||
XmlFsType.BackupDateSpecified = true;
|
||||
}
|
||||
xmlFSType.Bootable = bbSig == MFSBB_MAGIC;
|
||||
xmlFSType.Clusters = volMDB.drNmAlBlks;
|
||||
xmlFSType.ClusterSize = (int)volMDB.drAlBlkSiz;
|
||||
XmlFsType.Bootable = bbSig == MFSBB_MAGIC;
|
||||
XmlFsType.Clusters = volMDB.drNmAlBlks;
|
||||
XmlFsType.ClusterSize = (int)volMDB.drAlBlkSiz;
|
||||
if(volMDB.drCrDate > 0)
|
||||
{
|
||||
xmlFSType.CreationDate = DateHandlers.MacToDateTime(volMDB.drCrDate);
|
||||
xmlFSType.CreationDateSpecified = true;
|
||||
XmlFsType.CreationDate = DateHandlers.MacToDateTime(volMDB.drCrDate);
|
||||
XmlFsType.CreationDateSpecified = true;
|
||||
}
|
||||
xmlFSType.Files = volMDB.drNmFls;
|
||||
xmlFSType.FilesSpecified = true;
|
||||
xmlFSType.FreeClusters = volMDB.drFreeBks;
|
||||
xmlFSType.FreeClustersSpecified = true;
|
||||
xmlFSType.Type = "MFS";
|
||||
xmlFSType.VolumeName = volMDB.drVN;
|
||||
XmlFsType.Files = volMDB.drNmFls;
|
||||
XmlFsType.FilesSpecified = true;
|
||||
XmlFsType.FreeClusters = volMDB.drFreeBks;
|
||||
XmlFsType.FreeClustersSpecified = true;
|
||||
XmlFsType.Type = "MFS";
|
||||
XmlFsType.VolumeName = volMDB.drVN;
|
||||
|
||||
return Errno.NoError;
|
||||
}
|
||||
@@ -169,14 +167,16 @@ namespace DiscImageChef.Filesystems.AppleMFS
|
||||
|
||||
public override Errno StatFs(ref FileSystemInfo stat)
|
||||
{
|
||||
stat = new FileSystemInfo();
|
||||
stat.Blocks = volMDB.drNmAlBlks;
|
||||
stat.FilenameLength = 255;
|
||||
stat.Files = volMDB.drNmFls;
|
||||
stat.FreeBlocks = volMDB.drFreeBks;
|
||||
stat = new FileSystemInfo
|
||||
{
|
||||
Blocks = volMDB.drNmAlBlks,
|
||||
FilenameLength = 255,
|
||||
Files = volMDB.drNmFls,
|
||||
FreeBlocks = volMDB.drFreeBks,
|
||||
PluginId = PluginUuid,
|
||||
Type = "Apple MFS"
|
||||
};
|
||||
stat.FreeFiles = uint.MaxValue - stat.Files;
|
||||
stat.PluginId = PluginUUID;
|
||||
stat.Type = "Apple MFS";
|
||||
|
||||
return Errno.NoError;
|
||||
}
|
||||
|
||||
@@ -61,12 +61,9 @@ namespace DiscImageChef.Filesystems.AppleMFS
|
||||
return Errno.NoError;
|
||||
}
|
||||
|
||||
uint fileID;
|
||||
MFS_FileEntry entry;
|
||||
if(!filenameToId.TryGetValue(path.ToLowerInvariant(), out uint fileId)) return Errno.NoSuchFile;
|
||||
|
||||
if(!filenameToId.TryGetValue(path.ToLowerInvariant(), out fileID)) return Errno.NoSuchFile;
|
||||
|
||||
if(!idToEntry.TryGetValue(fileID, out entry)) return Errno.NoSuchFile;
|
||||
if(!idToEntry.TryGetValue(fileId, out MFS_FileEntry entry)) return Errno.NoSuchFile;
|
||||
|
||||
if(entry.flRLgLen > 0)
|
||||
{
|
||||
@@ -130,13 +127,11 @@ namespace DiscImageChef.Filesystems.AppleMFS
|
||||
}
|
||||
else return Errno.NoSuchExtendedAttribute;
|
||||
|
||||
uint fileID;
|
||||
MFS_FileEntry entry;
|
||||
Errno error;
|
||||
|
||||
if(!filenameToId.TryGetValue(path.ToLowerInvariant(), out fileID)) return Errno.NoSuchFile;
|
||||
if(!filenameToId.TryGetValue(path.ToLowerInvariant(), out uint fileId)) return Errno.NoSuchFile;
|
||||
|
||||
if(!idToEntry.TryGetValue(fileID, out entry)) return Errno.NoSuchFile;
|
||||
if(!idToEntry.TryGetValue(fileId, out MFS_FileEntry entry)) return Errno.NoSuchFile;
|
||||
|
||||
if(entry.flRLgLen > 0 &&
|
||||
string.Compare(xattr, "com.apple.ResourceFork", StringComparison.InvariantCulture) == 0)
|
||||
|
||||
@@ -53,24 +53,22 @@ namespace DiscImageChef.Filesystems
|
||||
public AtheOS()
|
||||
{
|
||||
Name = "AtheOS Filesystem";
|
||||
PluginUUID = new Guid("AAB2C4F1-DC07-49EE-A948-576CC51B58C5");
|
||||
PluginUuid = new Guid("AAB2C4F1-DC07-49EE-A948-576CC51B58C5");
|
||||
CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public AtheOS(Encoding encoding)
|
||||
{
|
||||
Name = "AtheOS Filesystem";
|
||||
PluginUUID = new Guid("AAB2C4F1-DC07-49EE-A948-576CC51B58C5");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("AAB2C4F1-DC07-49EE-A948-576CC51B58C5");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public AtheOS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "AtheOS Filesystem";
|
||||
PluginUUID = new Guid("AAB2C4F1-DC07-49EE-A948-576CC51B58C5");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("AAB2C4F1-DC07-49EE-A948-576CC51B58C5");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugin imagePlugin, Partition partition)
|
||||
@@ -87,10 +85,10 @@ namespace DiscImageChef.Filesystems
|
||||
uint magic;
|
||||
|
||||
byte[] tmp = imagePlugin.ReadSectors(sector + partition.Start, run);
|
||||
byte[] sb_sector = new byte[AFS_SUPERBLOCK_SIZE];
|
||||
Array.Copy(tmp, offset, sb_sector, 0, AFS_SUPERBLOCK_SIZE);
|
||||
byte[] sbSector = new byte[AFS_SUPERBLOCK_SIZE];
|
||||
Array.Copy(tmp, offset, sbSector, 0, AFS_SUPERBLOCK_SIZE);
|
||||
|
||||
magic = BitConverter.ToUInt32(sb_sector, 0x20);
|
||||
magic = BitConverter.ToUInt32(sbSector, 0x20);
|
||||
|
||||
return magic == AFS_MAGIC1;
|
||||
}
|
||||
@@ -102,8 +100,6 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
AtheosSuperBlock afs_sb;
|
||||
|
||||
ulong sector = AFS_BOOTBLOCK_SIZE / imagePlugin.GetSectorSize();
|
||||
uint offset = AFS_BOOTBLOCK_SIZE % imagePlugin.GetSectorSize();
|
||||
uint run = 1;
|
||||
@@ -112,58 +108,58 @@ namespace DiscImageChef.Filesystems
|
||||
run = AFS_SUPERBLOCK_SIZE / imagePlugin.GetSectorSize();
|
||||
|
||||
byte[] tmp = imagePlugin.ReadSectors(sector + partition.Start, run);
|
||||
byte[] sb_sector = new byte[AFS_SUPERBLOCK_SIZE];
|
||||
Array.Copy(tmp, offset, sb_sector, 0, AFS_SUPERBLOCK_SIZE);
|
||||
byte[] sbSector = new byte[AFS_SUPERBLOCK_SIZE];
|
||||
Array.Copy(tmp, offset, sbSector, 0, AFS_SUPERBLOCK_SIZE);
|
||||
|
||||
GCHandle handle = GCHandle.Alloc(sb_sector, GCHandleType.Pinned);
|
||||
afs_sb = (AtheosSuperBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(AtheosSuperBlock));
|
||||
GCHandle handle = GCHandle.Alloc(sbSector, GCHandleType.Pinned);
|
||||
AtheosSuperBlock afsSb = (AtheosSuperBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(AtheosSuperBlock));
|
||||
handle.Free();
|
||||
|
||||
sb.AppendLine("Atheos filesystem");
|
||||
|
||||
if(afs_sb.flags == 1) sb.AppendLine("Filesystem is read-only");
|
||||
if(afsSb.flags == 1) sb.AppendLine("Filesystem is read-only");
|
||||
|
||||
sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(afs_sb.name, CurrentEncoding)).AppendLine();
|
||||
sb.AppendFormat("{0} bytes per block", afs_sb.block_size).AppendLine();
|
||||
sb.AppendFormat("{0} blocks in volume ({1} bytes)", afs_sb.num_blocks,
|
||||
afs_sb.num_blocks * afs_sb.block_size).AppendLine();
|
||||
sb.AppendFormat("{0} used blocks ({1} bytes)", afs_sb.used_blocks, afs_sb.used_blocks * afs_sb.block_size)
|
||||
sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(afsSb.name, CurrentEncoding)).AppendLine();
|
||||
sb.AppendFormat("{0} bytes per block", afsSb.block_size).AppendLine();
|
||||
sb.AppendFormat("{0} blocks in volume ({1} bytes)", afsSb.num_blocks,
|
||||
afsSb.num_blocks * afsSb.block_size).AppendLine();
|
||||
sb.AppendFormat("{0} used blocks ({1} bytes)", afsSb.used_blocks, afsSb.used_blocks * afsSb.block_size)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("{0} bytes per i-node", afs_sb.inode_size).AppendLine();
|
||||
sb.AppendFormat("{0} blocks per allocation group ({1} bytes)", afs_sb.blocks_per_ag,
|
||||
afs_sb.blocks_per_ag * afs_sb.block_size).AppendLine();
|
||||
sb.AppendFormat("{0} allocation groups in volume", afs_sb.num_ags).AppendLine();
|
||||
sb.AppendFormat("{0} bytes per i-node", afsSb.inode_size).AppendLine();
|
||||
sb.AppendFormat("{0} blocks per allocation group ({1} bytes)", afsSb.blocks_per_ag,
|
||||
afsSb.blocks_per_ag * afsSb.block_size).AppendLine();
|
||||
sb.AppendFormat("{0} allocation groups in volume", afsSb.num_ags).AppendLine();
|
||||
sb.AppendFormat("Journal resides in block {0} of allocation group {1} and runs for {2} blocks ({3} bytes)",
|
||||
afs_sb.log_blocks_start, afs_sb.log_blocks_ag, afs_sb.log_blocks_len,
|
||||
afs_sb.log_blocks_len * afs_sb.block_size).AppendLine();
|
||||
sb.AppendFormat("Journal starts in byte {0} and has {1} bytes in {2} blocks", afs_sb.log_start,
|
||||
afs_sb.log_size, afs_sb.log_valid_blocks).AppendLine();
|
||||
afsSb.log_blocks_start, afsSb.log_blocks_ag, afsSb.log_blocks_len,
|
||||
afsSb.log_blocks_len * afsSb.block_size).AppendLine();
|
||||
sb.AppendFormat("Journal starts in byte {0} and has {1} bytes in {2} blocks", afsSb.log_start,
|
||||
afsSb.log_size, afsSb.log_valid_blocks).AppendLine();
|
||||
sb
|
||||
.AppendFormat("Root folder's i-node resides in block {0} of allocation group {1} and runs for {2} blocks ({3} bytes)",
|
||||
afs_sb.root_dir_start, afs_sb.root_dir_ag, afs_sb.root_dir_len,
|
||||
afs_sb.root_dir_len * afs_sb.block_size).AppendLine();
|
||||
afsSb.root_dir_start, afsSb.root_dir_ag, afsSb.root_dir_len,
|
||||
afsSb.root_dir_len * afsSb.block_size).AppendLine();
|
||||
sb
|
||||
.AppendFormat("Directory containing files scheduled for deletion's i-node resides in block {0} of allocation group {1} and runs for {2} blocks ({3} bytes)",
|
||||
afs_sb.deleted_start, afs_sb.deleted_ag, afs_sb.deleted_len,
|
||||
afs_sb.deleted_len * afs_sb.block_size).AppendLine();
|
||||
afsSb.deleted_start, afsSb.deleted_ag, afsSb.deleted_len,
|
||||
afsSb.deleted_len * afsSb.block_size).AppendLine();
|
||||
sb
|
||||
.AppendFormat("Indices' i-node resides in block {0} of allocation group {1} and runs for {2} blocks ({3} bytes)",
|
||||
afs_sb.indices_start, afs_sb.indices_ag, afs_sb.indices_len,
|
||||
afs_sb.indices_len * afs_sb.block_size).AppendLine();
|
||||
sb.AppendFormat("{0} blocks for bootloader ({1} bytes)", afs_sb.boot_size,
|
||||
afs_sb.boot_size * afs_sb.block_size).AppendLine();
|
||||
afsSb.indices_start, afsSb.indices_ag, afsSb.indices_len,
|
||||
afsSb.indices_len * afsSb.block_size).AppendLine();
|
||||
sb.AppendFormat("{0} blocks for bootloader ({1} bytes)", afsSb.boot_size,
|
||||
afsSb.boot_size * afsSb.block_size).AppendLine();
|
||||
|
||||
information = sb.ToString();
|
||||
|
||||
xmlFSType = new FileSystemType
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
Clusters = afs_sb.num_blocks,
|
||||
ClusterSize = (int)afs_sb.block_size,
|
||||
Clusters = afsSb.num_blocks,
|
||||
ClusterSize = (int)afsSb.block_size,
|
||||
Dirty = false,
|
||||
FreeClusters = afs_sb.num_blocks - afs_sb.used_blocks,
|
||||
FreeClusters = afsSb.num_blocks - afsSb.used_blocks,
|
||||
FreeClustersSpecified = true,
|
||||
Type = "AtheOS filesystem",
|
||||
VolumeName = StringHandlers.CToString(afs_sb.name, CurrentEncoding)
|
||||
VolumeName = StringHandlers.CToString(afsSb.name, CurrentEncoding)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -58,24 +58,22 @@ namespace DiscImageChef.Filesystems
|
||||
public BeFS()
|
||||
{
|
||||
Name = "Be Filesystem";
|
||||
PluginUUID = new Guid("dc8572b3-b6ad-46e4-8de9-cbe123ff6672");
|
||||
PluginUuid = new Guid("dc8572b3-b6ad-46e4-8de9-cbe123ff6672");
|
||||
CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public BeFS(Encoding encoding)
|
||||
{
|
||||
Name = "Be Filesystem";
|
||||
PluginUUID = new Guid("dc8572b3-b6ad-46e4-8de9-cbe123ff6672");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("dc8572b3-b6ad-46e4-8de9-cbe123ff6672");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public BeFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "Be Filesystem";
|
||||
PluginUUID = new Guid("dc8572b3-b6ad-46e4-8de9-cbe123ff6672");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("dc8572b3-b6ad-46e4-8de9-cbe123ff6672");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugin imagePlugin, Partition partition)
|
||||
@@ -83,58 +81,55 @@ namespace DiscImageChef.Filesystems
|
||||
if(2 + partition.Start >= partition.End) return false;
|
||||
|
||||
uint magic;
|
||||
uint magic_be;
|
||||
uint magicBe;
|
||||
|
||||
byte[] sb_sector = imagePlugin.ReadSector(0 + partition.Start);
|
||||
byte[] sbSector = imagePlugin.ReadSector(0 + partition.Start);
|
||||
|
||||
magic = BitConverter.ToUInt32(sb_sector, 0x20);
|
||||
magic_be = BigEndianBitConverter.ToUInt32(sb_sector, 0x20);
|
||||
magic = BitConverter.ToUInt32(sbSector, 0x20);
|
||||
magicBe = BigEndianBitConverter.ToUInt32(sbSector, 0x20);
|
||||
|
||||
if(magic == BEFS_MAGIC1 || magic_be == BEFS_MAGIC1) return true;
|
||||
if(magic == BEFS_MAGIC1 || magicBe == BEFS_MAGIC1) return true;
|
||||
|
||||
if(sb_sector.Length >= 0x400)
|
||||
if(sbSector.Length >= 0x400)
|
||||
{
|
||||
magic = BitConverter.ToUInt32(sb_sector, 0x220);
|
||||
magic_be = BigEndianBitConverter.ToUInt32(sb_sector, 0x220);
|
||||
magic = BitConverter.ToUInt32(sbSector, 0x220);
|
||||
magicBe = BigEndianBitConverter.ToUInt32(sbSector, 0x220);
|
||||
}
|
||||
|
||||
if(magic == BEFS_MAGIC1 || magic_be == BEFS_MAGIC1) return true;
|
||||
if(magic == BEFS_MAGIC1 || magicBe == BEFS_MAGIC1) return true;
|
||||
|
||||
sb_sector = imagePlugin.ReadSector(1 + partition.Start);
|
||||
sbSector = imagePlugin.ReadSector(1 + partition.Start);
|
||||
|
||||
magic = BitConverter.ToUInt32(sb_sector, 0x20);
|
||||
magic_be = BigEndianBitConverter.ToUInt32(sb_sector, 0x20);
|
||||
magic = BitConverter.ToUInt32(sbSector, 0x20);
|
||||
magicBe = BigEndianBitConverter.ToUInt32(sbSector, 0x20);
|
||||
|
||||
if(magic == BEFS_MAGIC1 || magic_be == BEFS_MAGIC1) return true;
|
||||
|
||||
return false;
|
||||
return magic == BEFS_MAGIC1 || magicBe == BEFS_MAGIC1;
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
|
||||
out string information)
|
||||
{
|
||||
information = "";
|
||||
byte[] name_bytes = new byte[32];
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
BeSuperBlock besb = new BeSuperBlock();
|
||||
|
||||
byte[] sb_sector = imagePlugin.ReadSector(0 + partition.Start);
|
||||
byte[] sbSector = imagePlugin.ReadSector(0 + partition.Start);
|
||||
|
||||
bool littleEndian;
|
||||
|
||||
besb.magic1 = BigEndianBitConverter.ToUInt32(sb_sector, 0x20);
|
||||
besb.magic1 = BigEndianBitConverter.ToUInt32(sbSector, 0x20);
|
||||
if(besb.magic1 == BEFS_MAGIC1 || besb.magic1 == BEFS_CIGAM1) // Magic is at offset
|
||||
littleEndian = besb.magic1 == BEFS_CIGAM1;
|
||||
else
|
||||
{
|
||||
sb_sector = imagePlugin.ReadSector(1 + partition.Start);
|
||||
besb.magic1 = BigEndianBitConverter.ToUInt32(sb_sector, 0x20);
|
||||
sbSector = imagePlugin.ReadSector(1 + partition.Start);
|
||||
besb.magic1 = BigEndianBitConverter.ToUInt32(sbSector, 0x20);
|
||||
|
||||
if(besb.magic1 == BEFS_MAGIC1 || besb.magic1 == BEFS_CIGAM1) // There is a boot sector
|
||||
littleEndian = besb.magic1 == BEFS_CIGAM1;
|
||||
else if(sb_sector.Length >= 0x400)
|
||||
else if(sbSector.Length >= 0x400)
|
||||
{
|
||||
byte[] temp = imagePlugin.ReadSector(0 + partition.Start);
|
||||
besb.magic1 = BigEndianBitConverter.ToUInt32(temp, 0x220);
|
||||
@@ -142,8 +137,8 @@ namespace DiscImageChef.Filesystems
|
||||
if(besb.magic1 == BEFS_MAGIC1 || besb.magic1 == BEFS_CIGAM1) // There is a boot sector
|
||||
{
|
||||
littleEndian = besb.magic1 == BEFS_CIGAM1;
|
||||
sb_sector = new byte[0x200];
|
||||
Array.Copy(temp, 0x200, sb_sector, 0, 0x200);
|
||||
sbSector = new byte[0x200];
|
||||
Array.Copy(temp, 0x200, sbSector, 0, 0x200);
|
||||
}
|
||||
else return;
|
||||
}
|
||||
@@ -152,15 +147,13 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
if(littleEndian)
|
||||
{
|
||||
GCHandle handle = GCHandle.Alloc(sb_sector, GCHandleType.Pinned);
|
||||
GCHandle handle = GCHandle.Alloc(sbSector, GCHandleType.Pinned);
|
||||
besb = (BeSuperBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(BeSuperBlock));
|
||||
handle.Free();
|
||||
}
|
||||
else besb = BigEndianMarshal.ByteArrayToStructureBigEndian<BeSuperBlock>(sb_sector);
|
||||
else besb = BigEndianMarshal.ByteArrayToStructureBigEndian<BeSuperBlock>(sbSector);
|
||||
|
||||
if(littleEndian) // Big-endian filesystem
|
||||
sb.AppendLine("Little-endian BeFS");
|
||||
else sb.AppendLine("Big-endian BeFS");
|
||||
sb.AppendLine(littleEndian ? "Little-endian BeFS" : "Big-endian BeFS");
|
||||
|
||||
if(besb.magic1 != BEFS_MAGIC1 || besb.fs_byte_order != BEFS_ENDIAN || besb.magic2 != BEFS_MAGIC2 ||
|
||||
besb.magic3 != BEFS_MAGIC3 || besb.root_dir_len != 1 || besb.indices_len != 1 ||
|
||||
@@ -180,8 +173,7 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
switch(besb.flags) {
|
||||
case BEFS_CLEAN:
|
||||
if(besb.log_start == besb.log_end) sb.AppendLine("Filesystem is clean");
|
||||
else sb.AppendLine("Filesystem is dirty");
|
||||
sb.AppendLine(besb.log_start == besb.log_end ? "Filesystem is clean" : "Filesystem is dirty");
|
||||
break;
|
||||
case BEFS_DIRTY: sb.AppendLine("Filesystem is dirty");
|
||||
break;
|
||||
@@ -215,14 +207,16 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
information = sb.ToString();
|
||||
|
||||
xmlFSType = new FileSystemType();
|
||||
xmlFSType.Clusters = besb.num_blocks;
|
||||
xmlFSType.ClusterSize = (int)besb.block_size;
|
||||
xmlFSType.Dirty = besb.flags == BEFS_DIRTY;
|
||||
xmlFSType.FreeClusters = besb.num_blocks - besb.used_blocks;
|
||||
xmlFSType.FreeClustersSpecified = true;
|
||||
xmlFSType.Type = "BeFS";
|
||||
xmlFSType.VolumeName = StringHandlers.CToString(besb.name, CurrentEncoding);
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
Clusters = besb.num_blocks,
|
||||
ClusterSize = (int)besb.block_size,
|
||||
Dirty = besb.flags == BEFS_DIRTY,
|
||||
FreeClusters = besb.num_blocks - besb.used_blocks,
|
||||
FreeClustersSpecified = true,
|
||||
Type = "BeFS",
|
||||
VolumeName = StringHandlers.CToString(besb.name, CurrentEncoding)
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -51,24 +51,22 @@ namespace DiscImageChef.Filesystems
|
||||
public BTRFS()
|
||||
{
|
||||
Name = "B-tree file system";
|
||||
PluginUUID = new Guid("C904CF15-5222-446B-B7DB-02EAC5D781B3");
|
||||
PluginUuid = new Guid("C904CF15-5222-446B-B7DB-02EAC5D781B3");
|
||||
CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public BTRFS(Encoding encoding)
|
||||
{
|
||||
Name = "B-tree file system";
|
||||
PluginUUID = new Guid("C904CF15-5222-446B-B7DB-02EAC5D781B3");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("C904CF15-5222-446B-B7DB-02EAC5D781B3");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public BTRFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "B-tree file system";
|
||||
PluginUUID = new Guid("C904CF15-5222-446B-B7DB-02EAC5D781B3");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("C904CF15-5222-446B-B7DB-02EAC5D781B3");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
@@ -159,17 +157,16 @@ namespace DiscImageChef.Filesystems
|
||||
out string information)
|
||||
{
|
||||
StringBuilder sbInformation = new StringBuilder();
|
||||
xmlFSType = new FileSystemType();
|
||||
XmlFsType = new FileSystemType();
|
||||
information = "";
|
||||
|
||||
ulong sbSectorOff = 0x10000 / imagePlugin.GetSectorSize();
|
||||
uint sbSectorSize = 0x1000 / imagePlugin.GetSectorSize();
|
||||
|
||||
byte[] sector = imagePlugin.ReadSectors(sbSectorOff + partition.Start, sbSectorSize);
|
||||
SuperBlock btrfsSb;
|
||||
|
||||
GCHandle handle = GCHandle.Alloc(sector, GCHandleType.Pinned);
|
||||
btrfsSb = (SuperBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(SuperBlock));
|
||||
SuperBlock btrfsSb = (SuperBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(SuperBlock));
|
||||
handle.Free();
|
||||
|
||||
DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.checksum = {0}", btrfsSb.checksum);
|
||||
@@ -243,15 +240,17 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
information = sbInformation.ToString();
|
||||
|
||||
xmlFSType = new FileSystemType();
|
||||
xmlFSType.Clusters = (long)(btrfsSb.total_bytes / btrfsSb.sectorsize);
|
||||
xmlFSType.ClusterSize = (int)btrfsSb.sectorsize;
|
||||
xmlFSType.FreeClusters = xmlFSType.Clusters - (long)(btrfsSb.bytes_used / btrfsSb.sectorsize);
|
||||
xmlFSType.FreeClustersSpecified = true;
|
||||
xmlFSType.VolumeName = btrfsSb.label;
|
||||
xmlFSType.VolumeSerial = $"{btrfsSb.uuid}";
|
||||
xmlFSType.VolumeSetIdentifier = $"{btrfsSb.dev_item.device_uuid}";
|
||||
xmlFSType.Type = Name;
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
Clusters = (long)(btrfsSb.total_bytes / btrfsSb.sectorsize),
|
||||
ClusterSize = (int)btrfsSb.sectorsize,
|
||||
FreeClustersSpecified = true,
|
||||
VolumeName = btrfsSb.label,
|
||||
VolumeSerial = $"{btrfsSb.uuid}",
|
||||
VolumeSetIdentifier = $"{btrfsSb.dev_item.device_uuid}",
|
||||
Type = Name
|
||||
};
|
||||
XmlFsType.FreeClusters = XmlFsType.Clusters - (long)(btrfsSb.bytes_used / btrfsSb.sectorsize);
|
||||
}
|
||||
|
||||
public override Errno Mount()
|
||||
|
||||
@@ -47,21 +47,21 @@ namespace DiscImageChef.Filesystems
|
||||
public CBM()
|
||||
{
|
||||
Name = "Commodore file system";
|
||||
PluginUUID = new Guid("D104744E-A376-450C-BAC0-1347C93F983B");
|
||||
PluginUuid = new Guid("D104744E-A376-450C-BAC0-1347C93F983B");
|
||||
CurrentEncoding = new PETSCII();
|
||||
}
|
||||
|
||||
public CBM(Encoding encoding)
|
||||
{
|
||||
Name = "Commodore file system";
|
||||
PluginUUID = new Guid("D104744E-A376-450C-BAC0-1347C93F983B");
|
||||
PluginUuid = new Guid("D104744E-A376-450C-BAC0-1347C93F983B");
|
||||
CurrentEncoding = new PETSCII();
|
||||
}
|
||||
|
||||
public CBM(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "Commodore file system";
|
||||
PluginUUID = new Guid("D104744E-A376-450C-BAC0-1347C93F983B");
|
||||
PluginUuid = new Guid("D104744E-A376-450C-BAC0-1347C93F983B");
|
||||
CurrentEncoding = new PETSCII();
|
||||
}
|
||||
|
||||
@@ -231,10 +231,12 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
sbInformation.AppendLine("Commodore file system");
|
||||
|
||||
xmlFSType = new FileSystemType();
|
||||
xmlFSType.Type = "Commodore file system";
|
||||
xmlFSType.Clusters = (long)imagePlugin.ImageInfo.Sectors;
|
||||
xmlFSType.ClusterSize = 256;
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
Type = "Commodore file system",
|
||||
Clusters = (long)imagePlugin.ImageInfo.Sectors,
|
||||
ClusterSize = 256
|
||||
};
|
||||
|
||||
if(imagePlugin.ImageInfo.Sectors == 3200)
|
||||
{
|
||||
@@ -258,8 +260,8 @@ namespace DiscImageChef.Filesystems
|
||||
sbInformation.AppendFormat("Disk name: {0}", StringHandlers.CToString(cbmHdr.name, CurrentEncoding))
|
||||
.AppendLine();
|
||||
|
||||
xmlFSType.VolumeName = StringHandlers.CToString(cbmHdr.name, CurrentEncoding);
|
||||
xmlFSType.VolumeSerial = $"{cbmHdr.diskId}";
|
||||
XmlFsType.VolumeName = StringHandlers.CToString(cbmHdr.name, CurrentEncoding);
|
||||
XmlFsType.VolumeSerial = $"{cbmHdr.diskId}";
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -281,8 +283,8 @@ namespace DiscImageChef.Filesystems
|
||||
sbInformation.AppendFormat("Disk name: {0}", StringHandlers.CToString(cbmBam.name, CurrentEncoding))
|
||||
.AppendLine();
|
||||
|
||||
xmlFSType.VolumeName = StringHandlers.CToString(cbmBam.name, CurrentEncoding);
|
||||
xmlFSType.VolumeSerial = $"{cbmBam.diskId}";
|
||||
XmlFsType.VolumeName = StringHandlers.CToString(cbmBam.name, CurrentEncoding);
|
||||
XmlFsType.VolumeSerial = $"{cbmBam.diskId}";
|
||||
}
|
||||
|
||||
information = sbInformation.ToString();
|
||||
|
||||
@@ -113,16 +113,15 @@ namespace DiscImageChef.Filesystems.CPM
|
||||
public CPM()
|
||||
{
|
||||
Name = "CP/M File System";
|
||||
PluginUUID = new Guid("AA2B8585-41DF-4E3B-8A35-D1A935E2F8A1");
|
||||
PluginUuid = new Guid("AA2B8585-41DF-4E3B-8A35-D1A935E2F8A1");
|
||||
CurrentEncoding = Encoding.GetEncoding("IBM437");
|
||||
}
|
||||
|
||||
public CPM(Encoding encoding)
|
||||
{
|
||||
Name = "CP/M File System";
|
||||
PluginUUID = new Guid("AA2B8585-41DF-4E3B-8A35-D1A935E2F8A1");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("IBM437");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("AA2B8585-41DF-4E3B-8A35-D1A935E2F8A1");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("IBM437");
|
||||
}
|
||||
|
||||
public CPM(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
@@ -130,9 +129,8 @@ namespace DiscImageChef.Filesystems.CPM
|
||||
device = imagePlugin;
|
||||
this.partition = partition;
|
||||
Name = "CP/M File System";
|
||||
PluginUUID = new Guid("AA2B8585-41DF-4E3B-8A35-D1A935E2F8A1");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("IBM437");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("AA2B8585-41DF-4E3B-8A35-D1A935E2F8A1");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("IBM437");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -59,18 +59,14 @@ namespace DiscImageChef.Filesystems.CPM
|
||||
{
|
||||
if(def.side1 == null)
|
||||
{
|
||||
def.side1 = new Side();
|
||||
def.side1.sideId = 0;
|
||||
def.side1.sectorIds = new int[def.sectorsPerTrack];
|
||||
def.side1 = new Side {sideId = 0, sectorIds = new int[def.sectorsPerTrack]};
|
||||
for(int i = 0; i < def.sectorsPerTrack; i++) def.side1.sectorIds[i] = i + 1;
|
||||
}
|
||||
|
||||
if(def.sides != 2 || def.side2 != null) continue;
|
||||
|
||||
{
|
||||
def.side2 = new Side();
|
||||
def.side2.sideId = 1;
|
||||
def.side2.sectorIds = new int[def.sectorsPerTrack];
|
||||
def.side2 = new Side {sideId = 1, sectorIds = new int[def.sectorsPerTrack]};
|
||||
for(int i = 0; i < def.sectorsPerTrack; i++) def.side2.sectorIds[i] = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,10 +69,9 @@ namespace DiscImageChef.Filesystems.CPM
|
||||
|
||||
for(int off = 0; off < directory.Length; off += 32)
|
||||
{
|
||||
DirectoryEntry entry;
|
||||
IntPtr dirPtr = Marshal.AllocHGlobal(32);
|
||||
Marshal.Copy(directory, off, dirPtr, 32);
|
||||
entry = (DirectoryEntry)Marshal.PtrToStructure(dirPtr, typeof(DirectoryEntry));
|
||||
DirectoryEntry entry = (DirectoryEntry)Marshal.PtrToStructure(dirPtr, typeof(DirectoryEntry));
|
||||
Marshal.FreeHGlobal(dirPtr);
|
||||
|
||||
if((entry.statusUser & 0x7F) < 0x20)
|
||||
|
||||
@@ -43,8 +43,6 @@ namespace DiscImageChef.Filesystems.CPM
|
||||
string[] pathElements = path.Split(new[] {'/'}, StringSplitOptions.RemoveEmptyEntries);
|
||||
if(pathElements.Length != 1) return Errno.NotSupported;
|
||||
|
||||
FileEntryInfo fInfo;
|
||||
|
||||
if(string.IsNullOrEmpty(pathElements[0]) ||
|
||||
string.Compare(pathElements[0], "/", StringComparison.OrdinalIgnoreCase) == 0)
|
||||
{
|
||||
@@ -53,18 +51,16 @@ namespace DiscImageChef.Filesystems.CPM
|
||||
return Errno.NoError;
|
||||
}
|
||||
|
||||
if(!statCache.TryGetValue(pathElements[0].ToUpperInvariant(), out fInfo)) return Errno.NoSuchFile;
|
||||
if(!statCache.TryGetValue(pathElements[0].ToUpperInvariant(), out FileEntryInfo fInfo)) return Errno.NoSuchFile;
|
||||
|
||||
attributes = fInfo.Attributes;
|
||||
return Errno.NoError;
|
||||
}
|
||||
|
||||
// TODO: Implementing this would require storing the interleaving
|
||||
public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock)
|
||||
{
|
||||
if(!mounted) return Errno.AccessDenied;
|
||||
|
||||
// TODO: Implementing this would require storing the interleaving
|
||||
return Errno.NotImplemented;
|
||||
return !mounted ? Errno.AccessDenied : Errno.NotImplemented;
|
||||
}
|
||||
|
||||
public override Errno Read(string path, long offset, long size, ref byte[] buf)
|
||||
@@ -82,9 +78,7 @@ namespace DiscImageChef.Filesystems.CPM
|
||||
string[] pathElements = path.Split(new[] {'/'}, StringSplitOptions.RemoveEmptyEntries);
|
||||
if(pathElements.Length != 1) return Errno.NotSupported;
|
||||
|
||||
byte[] file;
|
||||
|
||||
if(!fileCache.TryGetValue(pathElements[0].ToUpperInvariant(), out file)) return Errno.NoSuchFile;
|
||||
if(!fileCache.TryGetValue(pathElements[0].ToUpperInvariant(), out byte[] file)) return Errno.NoSuchFile;
|
||||
|
||||
if(offset >= file.Length) return Errno.EINVAL;
|
||||
|
||||
@@ -114,7 +108,7 @@ namespace DiscImageChef.Filesystems.CPM
|
||||
if(labelCreationDate != null) stat.CreationTime = DateHandlers.CPMToDateTime(labelCreationDate);
|
||||
if(labelUpdateDate != null) stat.StatusChangeTime = DateHandlers.CPMToDateTime(labelUpdateDate);
|
||||
stat.Attributes = FileAttributes.Directory;
|
||||
stat.BlockSize = xmlFSType.ClusterSize;
|
||||
stat.BlockSize = XmlFsType.ClusterSize;
|
||||
return Errno.NoError;
|
||||
}
|
||||
|
||||
|
||||
@@ -164,9 +164,7 @@ namespace DiscImageChef.Filesystems.CPM
|
||||
try
|
||||
{
|
||||
byte[] sector;
|
||||
ulong sectorCount;
|
||||
ulong sectorSize;
|
||||
ulong sides;
|
||||
ulong firstDirectorySector;
|
||||
byte[] directory = null;
|
||||
workingDefinition = null;
|
||||
@@ -200,8 +198,8 @@ namespace DiscImageChef.Filesystems.CPM
|
||||
amsSb.format == 2 && (amsSb.sidedness & 0x02) == 2)
|
||||
{
|
||||
// Calculate device limits
|
||||
sides = (ulong)(amsSb.format == 0 ? 1 : 2);
|
||||
sectorCount = (ulong)(amsSb.tps * amsSb.spt * (byte)sides);
|
||||
ulong sides = (ulong)(amsSb.format == 0 ? 1 : 2);
|
||||
ulong sectorCount = (ulong)(amsSb.tps * amsSb.spt * (byte)sides);
|
||||
sectorSize = (ulong)(128 << amsSb.psh);
|
||||
|
||||
// Compare device limits from superblock to real limits
|
||||
@@ -211,10 +209,12 @@ namespace DiscImageChef.Filesystems.CPM
|
||||
firstDirectorySector = (ulong)(amsSb.off * amsSb.spt);
|
||||
|
||||
// Build a DiscParameterBlock
|
||||
dpb = new DiscParameterBlock();
|
||||
dpb.al0 = sectorCount == 1440 ? (byte)0xF0 : (byte)0xC0;
|
||||
dpb.spt = amsSb.spt;
|
||||
dpb.bsh = amsSb.bsh;
|
||||
dpb = new DiscParameterBlock
|
||||
{
|
||||
al0 = sectorCount == 1440 ? (byte)0xF0 : (byte)0xC0,
|
||||
spt = amsSb.spt,
|
||||
bsh = amsSb.bsh
|
||||
};
|
||||
for(int i = 0; i < dpb.bsh; i++) dpb.blm += (byte)Math.Pow(2, i);
|
||||
|
||||
if(sectorCount >= 1440)
|
||||
@@ -239,27 +239,27 @@ namespace DiscImageChef.Filesystems.CPM
|
||||
directoryLength);
|
||||
|
||||
// Build a CP/M disk definition
|
||||
workingDefinition = new CpmDefinition();
|
||||
workingDefinition.al0 = dpb.al0;
|
||||
workingDefinition.al1 = dpb.al1;
|
||||
workingDefinition.bitrate = "LOW";
|
||||
workingDefinition.blm = dpb.blm;
|
||||
workingDefinition.bsh = dpb.bsh;
|
||||
workingDefinition.bytesPerSector = 512;
|
||||
workingDefinition.cylinders = amsSb.tps;
|
||||
workingDefinition.drm = dpb.drm;
|
||||
workingDefinition.dsm = dpb.dsm;
|
||||
workingDefinition.encoding = "MFM";
|
||||
workingDefinition.evenOdd = false;
|
||||
workingDefinition.exm = dpb.exm;
|
||||
workingDefinition.label = null;
|
||||
workingDefinition.comment = "Amstrad PCW superblock";
|
||||
workingDefinition.ofs = dpb.off;
|
||||
workingDefinition.sectorsPerTrack = amsSb.spt;
|
||||
workingDefinition = new CpmDefinition
|
||||
{
|
||||
al0 = dpb.al0,
|
||||
al1 = dpb.al1,
|
||||
bitrate = "LOW",
|
||||
blm = dpb.blm,
|
||||
bsh = dpb.bsh,
|
||||
bytesPerSector = 512,
|
||||
cylinders = amsSb.tps,
|
||||
drm = dpb.drm,
|
||||
dsm = dpb.dsm,
|
||||
encoding = "MFM",
|
||||
evenOdd = false,
|
||||
exm = dpb.exm,
|
||||
label = null,
|
||||
comment = "Amstrad PCW superblock",
|
||||
ofs = dpb.off,
|
||||
sectorsPerTrack = amsSb.spt,
|
||||
side1 = new Side {sideId = 0, sectorIds = new int[amsSb.spt]}
|
||||
};
|
||||
|
||||
workingDefinition.side1 = new Side();
|
||||
workingDefinition.side1.sideId = 0;
|
||||
workingDefinition.side1.sectorIds = new int[amsSb.spt];
|
||||
for(int si = 0; si < amsSb.spt; si++) workingDefinition.side1.sectorIds[si] = si + 1;
|
||||
|
||||
if(amsSb.format == 2)
|
||||
@@ -273,9 +273,7 @@ namespace DiscImageChef.Filesystems.CPM
|
||||
break;
|
||||
}
|
||||
|
||||
workingDefinition.side2 = new Side();
|
||||
workingDefinition.side2.sideId = 1;
|
||||
workingDefinition.side2.sectorIds = new int[amsSb.spt];
|
||||
workingDefinition.side2 = new Side {sideId = 1, sectorIds = new int[amsSb.spt]};
|
||||
for(int si = 0; si < amsSb.spt; si++) workingDefinition.side2.sectorIds[si] = si + 1;
|
||||
}
|
||||
else workingDefinition.order = null;
|
||||
@@ -323,56 +321,59 @@ namespace DiscImageChef.Filesystems.CPM
|
||||
firstDirectorySector = (ulong)(hddSb.off * hddSb.sectorsPerTrack);
|
||||
|
||||
// Build a DiscParameterBlock
|
||||
dpb = new DiscParameterBlock();
|
||||
dpb.al0 = (byte)hddSb.al0;
|
||||
dpb.al1 = (byte)hddSb.al1;
|
||||
dpb.blm = hddSb.blm;
|
||||
dpb.bsh = hddSb.bsh;
|
||||
dpb.cks = hddSb.cks;
|
||||
dpb.drm = hddSb.drm;
|
||||
dpb.dsm = hddSb.dsm;
|
||||
dpb.exm = hddSb.exm;
|
||||
dpb.off = hddSb.off;
|
||||
dpb.phm = 0; // Needed?
|
||||
dpb.psh = 0; // Needed?
|
||||
dpb.spt = hddSb.spt;
|
||||
dpb = new DiscParameterBlock
|
||||
{
|
||||
al0 = (byte)hddSb.al0,
|
||||
al1 = (byte)hddSb.al1,
|
||||
blm = hddSb.blm,
|
||||
bsh = hddSb.bsh,
|
||||
cks = hddSb.cks,
|
||||
drm = hddSb.drm,
|
||||
dsm = hddSb.dsm,
|
||||
exm = hddSb.exm,
|
||||
off = hddSb.off,
|
||||
// Needed?
|
||||
phm = 0,
|
||||
// Needed?
|
||||
psh = 0,
|
||||
spt = hddSb.spt
|
||||
};
|
||||
|
||||
uint directoryLength = (uint)(((ulong)dpb.drm + 1) * 32 / sectorSize);
|
||||
directory = imagePlugin.ReadSectors(firstDirectorySector + partition.Start,
|
||||
directoryLength);
|
||||
DicConsole.DebugWriteLine("CP/M Plugin", "Found CP/M-86 hard disk superblock.");
|
||||
|
||||
// Build a CP/M disk definition
|
||||
workingDefinition = new CpmDefinition();
|
||||
workingDefinition.al0 = dpb.al0;
|
||||
workingDefinition.al1 = dpb.al1;
|
||||
workingDefinition.bitrate = "HIGH";
|
||||
workingDefinition.blm = dpb.blm;
|
||||
workingDefinition.bsh = dpb.bsh;
|
||||
workingDefinition.bytesPerSector = 512;
|
||||
workingDefinition.cylinders = hddSb.cylinders;
|
||||
workingDefinition.drm = dpb.drm;
|
||||
workingDefinition.dsm = dpb.dsm;
|
||||
workingDefinition.encoding = "MFM";
|
||||
workingDefinition.evenOdd = false;
|
||||
workingDefinition.exm = dpb.exm;
|
||||
workingDefinition.label = null;
|
||||
workingDefinition.comment = "CP/M-86 hard disk superblock";
|
||||
workingDefinition.ofs = dpb.off;
|
||||
workingDefinition.sectorsPerTrack = hddSb.sectorsPerTrack;
|
||||
workingDefinition.side1 = new Side();
|
||||
workingDefinition.side1.sideId = 0;
|
||||
workingDefinition.side1.sectorIds = new int[hddSb.sectorsPerTrack];
|
||||
workingDefinition = new CpmDefinition
|
||||
{
|
||||
al0 = dpb.al0,
|
||||
al1 = dpb.al1,
|
||||
bitrate = "HIGH",
|
||||
blm = dpb.blm,
|
||||
bsh = dpb.bsh,
|
||||
bytesPerSector = 512,
|
||||
cylinders = hddSb.cylinders,
|
||||
drm = dpb.drm,
|
||||
dsm = dpb.dsm,
|
||||
encoding = "MFM",
|
||||
evenOdd = false,
|
||||
exm = dpb.exm,
|
||||
label = null,
|
||||
comment = "CP/M-86 hard disk superblock",
|
||||
ofs = dpb.off,
|
||||
sectorsPerTrack = hddSb.sectorsPerTrack,
|
||||
side1 = new Side {sideId = 0, sectorIds = new int[hddSb.sectorsPerTrack]},
|
||||
order = "SIDES",
|
||||
side2 = new Side {sideId = 1, sectorIds = new int[hddSb.sectorsPerTrack]},
|
||||
skew = 0,
|
||||
sofs = 0
|
||||
};
|
||||
|
||||
for(int si = 0; si < hddSb.sectorsPerTrack; si++)
|
||||
workingDefinition.side1.sectorIds[si] = si + 1;
|
||||
|
||||
workingDefinition.order = "SIDES";
|
||||
workingDefinition.side2 = new Side();
|
||||
workingDefinition.side2.sideId = 1;
|
||||
workingDefinition.side2.sectorIds = new int[hddSb.sectorsPerTrack];
|
||||
for(int si = 0; si < hddSb.spt; si++) workingDefinition.side2.sectorIds[si] = si + 1;
|
||||
|
||||
workingDefinition.skew = 0;
|
||||
workingDefinition.sofs = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -404,44 +405,46 @@ namespace DiscImageChef.Filesystems.CPM
|
||||
{
|
||||
cpmFound = true;
|
||||
firstDirectorySector86 = 8;
|
||||
dpb = new DiscParameterBlock();
|
||||
dpb.al0 = 0xC0;
|
||||
dpb.al1 = 0;
|
||||
dpb.blm = 7;
|
||||
dpb.bsh = 3;
|
||||
dpb.cks = 0x10;
|
||||
dpb.drm = 0x3F;
|
||||
dpb.dsm = 0x9B;
|
||||
dpb.exm = 0;
|
||||
dpb.off = 1;
|
||||
dpb.phm = 3;
|
||||
dpb.psh = 2;
|
||||
dpb.spt = 8 * 4;
|
||||
dpb = new DiscParameterBlock
|
||||
{
|
||||
al0 = 0xC0,
|
||||
al1 = 0,
|
||||
blm = 7,
|
||||
bsh = 3,
|
||||
cks = 0x10,
|
||||
drm = 0x3F,
|
||||
dsm = 0x9B,
|
||||
exm = 0,
|
||||
off = 1,
|
||||
phm = 3,
|
||||
psh = 2,
|
||||
spt = 8 * 4
|
||||
};
|
||||
|
||||
workingDefinition = new CpmDefinition
|
||||
{
|
||||
al0 = dpb.al0,
|
||||
al1 = dpb.al1,
|
||||
bitrate = "LOW",
|
||||
blm = dpb.blm,
|
||||
bsh = dpb.bsh,
|
||||
bytesPerSector = 512,
|
||||
cylinders = 40,
|
||||
drm = dpb.drm,
|
||||
dsm = dpb.dsm,
|
||||
encoding = "MFM",
|
||||
evenOdd = false,
|
||||
exm = dpb.exm,
|
||||
label = null,
|
||||
comment = "CP/M-86 floppy identifier",
|
||||
ofs = dpb.off,
|
||||
sectorsPerTrack = 8,
|
||||
side1 = new Side {sideId = 0, sectorIds = new int[8]},
|
||||
skew = 0,
|
||||
sofs = 0
|
||||
};
|
||||
|
||||
workingDefinition = new CpmDefinition();
|
||||
workingDefinition.al0 = dpb.al0;
|
||||
workingDefinition.al1 = dpb.al1;
|
||||
workingDefinition.bitrate = "LOW";
|
||||
workingDefinition.blm = dpb.blm;
|
||||
workingDefinition.bsh = dpb.bsh;
|
||||
workingDefinition.bytesPerSector = 512;
|
||||
workingDefinition.cylinders = 40;
|
||||
workingDefinition.drm = dpb.drm;
|
||||
workingDefinition.dsm = dpb.dsm;
|
||||
workingDefinition.encoding = "MFM";
|
||||
workingDefinition.evenOdd = false;
|
||||
workingDefinition.exm = dpb.exm;
|
||||
workingDefinition.label = null;
|
||||
workingDefinition.comment = "CP/M-86 floppy identifier";
|
||||
workingDefinition.ofs = dpb.off;
|
||||
workingDefinition.sectorsPerTrack = 8;
|
||||
workingDefinition.side1 = new Side();
|
||||
workingDefinition.side1.sideId = 0;
|
||||
workingDefinition.side1.sectorIds = new int[8];
|
||||
for(int si = 0; si < 8; si++) workingDefinition.side1.sectorIds[si] = si + 1;
|
||||
|
||||
workingDefinition.skew = 0;
|
||||
workingDefinition.sofs = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -450,50 +453,49 @@ namespace DiscImageChef.Filesystems.CPM
|
||||
{
|
||||
cpmFound = true;
|
||||
firstDirectorySector86 = 16;
|
||||
dpb = new DiscParameterBlock();
|
||||
dpb.al0 = 0x80;
|
||||
dpb.al1 = 0;
|
||||
dpb.blm = 0x0F;
|
||||
dpb.bsh = 4;
|
||||
dpb.cks = 0x10;
|
||||
dpb.drm = 0x3F;
|
||||
dpb.dsm = 0x9D;
|
||||
dpb.exm = 1;
|
||||
dpb.off = 2;
|
||||
dpb.phm = 3;
|
||||
dpb.psh = 2;
|
||||
dpb.spt = 8 * 4;
|
||||
dpb = new DiscParameterBlock
|
||||
{
|
||||
al0 = 0x80,
|
||||
al1 = 0,
|
||||
blm = 0x0F,
|
||||
bsh = 4,
|
||||
cks = 0x10,
|
||||
drm = 0x3F,
|
||||
dsm = 0x9D,
|
||||
exm = 1,
|
||||
off = 2,
|
||||
phm = 3,
|
||||
psh = 2,
|
||||
spt = 8 * 4
|
||||
};
|
||||
|
||||
workingDefinition = new CpmDefinition
|
||||
{
|
||||
al0 = dpb.al0,
|
||||
al1 = dpb.al1,
|
||||
bitrate = "LOW",
|
||||
blm = dpb.blm,
|
||||
bsh = dpb.bsh,
|
||||
bytesPerSector = 512,
|
||||
cylinders = 40,
|
||||
drm = dpb.drm,
|
||||
dsm = dpb.dsm,
|
||||
encoding = "MFM",
|
||||
evenOdd = false,
|
||||
exm = dpb.exm,
|
||||
label = null,
|
||||
comment = "CP/M-86 floppy identifier",
|
||||
ofs = dpb.off,
|
||||
sectorsPerTrack = 8,
|
||||
side1 = new Side {sideId = 0, sectorIds = new int[8]},
|
||||
order = "SIDES",
|
||||
side2 = new Side {sideId = 1, sectorIds = new int[8]},
|
||||
skew = 0,
|
||||
sofs = 0
|
||||
};
|
||||
|
||||
workingDefinition = new CpmDefinition();
|
||||
workingDefinition.al0 = dpb.al0;
|
||||
workingDefinition.al1 = dpb.al1;
|
||||
workingDefinition.bitrate = "LOW";
|
||||
workingDefinition.blm = dpb.blm;
|
||||
workingDefinition.bsh = dpb.bsh;
|
||||
workingDefinition.bytesPerSector = 512;
|
||||
workingDefinition.cylinders = 40;
|
||||
workingDefinition.drm = dpb.drm;
|
||||
workingDefinition.dsm = dpb.dsm;
|
||||
workingDefinition.encoding = "MFM";
|
||||
workingDefinition.evenOdd = false;
|
||||
workingDefinition.exm = dpb.exm;
|
||||
workingDefinition.label = null;
|
||||
workingDefinition.comment = "CP/M-86 floppy identifier";
|
||||
workingDefinition.ofs = dpb.off;
|
||||
workingDefinition.sectorsPerTrack = 8;
|
||||
workingDefinition.side1 = new Side();
|
||||
workingDefinition.side1.sideId = 0;
|
||||
workingDefinition.side1.sectorIds = new int[8];
|
||||
for(int si = 0; si < 8; si++) workingDefinition.side1.sectorIds[si] = si + 1;
|
||||
|
||||
workingDefinition.order = "SIDES";
|
||||
workingDefinition.side2 = new Side();
|
||||
workingDefinition.side2.sideId = 1;
|
||||
workingDefinition.side2.sectorIds = new int[8];
|
||||
for(int si = 0; si < 8; si++) workingDefinition.side2.sectorIds[si] = si + 1;
|
||||
|
||||
workingDefinition.skew = 0;
|
||||
workingDefinition.sofs = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -504,50 +506,49 @@ namespace DiscImageChef.Filesystems.CPM
|
||||
{
|
||||
cpmFound = true;
|
||||
firstDirectorySector86 = 36;
|
||||
dpb = new DiscParameterBlock();
|
||||
dpb.al0 = 0x80;
|
||||
dpb.al1 = 0;
|
||||
dpb.blm = 0x0F;
|
||||
dpb.bsh = 4;
|
||||
dpb.cks = 0x10;
|
||||
dpb.drm = 0x3F;
|
||||
dpb.dsm = 0; // Unknown. Needed?
|
||||
dpb.exm = 1;
|
||||
dpb.off = 4;
|
||||
dpb.phm = 3;
|
||||
dpb.psh = 2;
|
||||
dpb.spt = 9 * 4;
|
||||
dpb = new DiscParameterBlock
|
||||
{
|
||||
al0 = 0x80,
|
||||
al1 = 0,
|
||||
blm = 0x0F,
|
||||
bsh = 4,
|
||||
cks = 0x10,
|
||||
drm = 0x3F,
|
||||
dsm = 0, // Unknown. Needed?
|
||||
exm = 1,
|
||||
off = 4,
|
||||
phm = 3,
|
||||
psh = 2,
|
||||
spt = 9 * 4
|
||||
};
|
||||
|
||||
workingDefinition = new CpmDefinition
|
||||
{
|
||||
al0 = dpb.al0,
|
||||
al1 = dpb.al1,
|
||||
bitrate = "LOW",
|
||||
blm = dpb.blm,
|
||||
bsh = dpb.bsh,
|
||||
bytesPerSector = 512,
|
||||
cylinders = 40,
|
||||
drm = dpb.drm,
|
||||
dsm = dpb.dsm,
|
||||
encoding = "MFM",
|
||||
evenOdd = false,
|
||||
exm = dpb.exm,
|
||||
label = null,
|
||||
comment = "CP/M-86 floppy identifier",
|
||||
ofs = dpb.off,
|
||||
sectorsPerTrack = 9,
|
||||
side1 = new Side {sideId = 0, sectorIds = new int[9]},
|
||||
order = "SIDES",
|
||||
side2 = new Side {sideId = 1, sectorIds = new int[9]},
|
||||
skew = 0,
|
||||
sofs = 0
|
||||
};
|
||||
|
||||
workingDefinition = new CpmDefinition();
|
||||
workingDefinition.al0 = dpb.al0;
|
||||
workingDefinition.al1 = dpb.al1;
|
||||
workingDefinition.bitrate = "LOW";
|
||||
workingDefinition.blm = dpb.blm;
|
||||
workingDefinition.bsh = dpb.bsh;
|
||||
workingDefinition.bytesPerSector = 512;
|
||||
workingDefinition.cylinders = 40;
|
||||
workingDefinition.drm = dpb.drm;
|
||||
workingDefinition.dsm = dpb.dsm;
|
||||
workingDefinition.encoding = "MFM";
|
||||
workingDefinition.evenOdd = false;
|
||||
workingDefinition.exm = dpb.exm;
|
||||
workingDefinition.label = null;
|
||||
workingDefinition.comment = "CP/M-86 floppy identifier";
|
||||
workingDefinition.ofs = dpb.off;
|
||||
workingDefinition.sectorsPerTrack = 9;
|
||||
workingDefinition.side1 = new Side();
|
||||
workingDefinition.side1.sideId = 0;
|
||||
workingDefinition.side1.sectorIds = new int[9];
|
||||
for(int si = 0; si < 9; si++) workingDefinition.side1.sectorIds[si] = si + 1;
|
||||
|
||||
workingDefinition.order = "SIDES";
|
||||
workingDefinition.side2 = new Side();
|
||||
workingDefinition.side2.sideId = 1;
|
||||
workingDefinition.side2.sectorIds = new int[9];
|
||||
for(int si = 0; si < 9; si++) workingDefinition.side2.sectorIds[si] = si + 1;
|
||||
|
||||
workingDefinition.skew = 0;
|
||||
workingDefinition.sofs = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -557,50 +558,49 @@ namespace DiscImageChef.Filesystems.CPM
|
||||
{
|
||||
cpmFound = true;
|
||||
firstDirectorySector86 = 36;
|
||||
dpb = new DiscParameterBlock();
|
||||
dpb.al0 = 0xF0;
|
||||
dpb.al1 = 0;
|
||||
dpb.blm = 0x0F;
|
||||
dpb.bsh = 4;
|
||||
dpb.cks = 0x40;
|
||||
dpb.drm = 0xFF;
|
||||
dpb.dsm = 0x15E;
|
||||
dpb.exm = 0;
|
||||
dpb.off = 4;
|
||||
dpb.phm = 3;
|
||||
dpb.psh = 2;
|
||||
dpb.spt = 9 * 4;
|
||||
dpb = new DiscParameterBlock
|
||||
{
|
||||
al0 = 0xF0,
|
||||
al1 = 0,
|
||||
blm = 0x0F,
|
||||
bsh = 4,
|
||||
cks = 0x40,
|
||||
drm = 0xFF,
|
||||
dsm = 0x15E,
|
||||
exm = 0,
|
||||
off = 4,
|
||||
phm = 3,
|
||||
psh = 2,
|
||||
spt = 9 * 4
|
||||
};
|
||||
|
||||
workingDefinition = new CpmDefinition
|
||||
{
|
||||
al0 = dpb.al0,
|
||||
al1 = dpb.al1,
|
||||
bitrate = "LOW",
|
||||
blm = dpb.blm,
|
||||
bsh = dpb.bsh,
|
||||
bytesPerSector = 512,
|
||||
cylinders = 80,
|
||||
drm = dpb.drm,
|
||||
dsm = dpb.dsm,
|
||||
encoding = "MFM",
|
||||
evenOdd = false,
|
||||
exm = dpb.exm,
|
||||
label = null,
|
||||
comment = "CP/M-86 floppy identifier",
|
||||
ofs = dpb.off,
|
||||
sectorsPerTrack = 9,
|
||||
side1 = new Side {sideId = 0, sectorIds = new int[9]},
|
||||
order = "SIDES",
|
||||
side2 = new Side {sideId = 1, sectorIds = new int[9]},
|
||||
skew = 0,
|
||||
sofs = 0
|
||||
};
|
||||
|
||||
workingDefinition = new CpmDefinition();
|
||||
workingDefinition.al0 = dpb.al0;
|
||||
workingDefinition.al1 = dpb.al1;
|
||||
workingDefinition.bitrate = "LOW";
|
||||
workingDefinition.blm = dpb.blm;
|
||||
workingDefinition.bsh = dpb.bsh;
|
||||
workingDefinition.bytesPerSector = 512;
|
||||
workingDefinition.cylinders = 80;
|
||||
workingDefinition.drm = dpb.drm;
|
||||
workingDefinition.dsm = dpb.dsm;
|
||||
workingDefinition.encoding = "MFM";
|
||||
workingDefinition.evenOdd = false;
|
||||
workingDefinition.exm = dpb.exm;
|
||||
workingDefinition.label = null;
|
||||
workingDefinition.comment = "CP/M-86 floppy identifier";
|
||||
workingDefinition.ofs = dpb.off;
|
||||
workingDefinition.sectorsPerTrack = 9;
|
||||
workingDefinition.side1 = new Side();
|
||||
workingDefinition.side1.sideId = 0;
|
||||
workingDefinition.side1.sectorIds = new int[9];
|
||||
for(int si = 0; si < 9; si++) workingDefinition.side1.sectorIds[si] = si + 1;
|
||||
|
||||
workingDefinition.order = "SIDES";
|
||||
workingDefinition.side2 = new Side();
|
||||
workingDefinition.side2.sideId = 1;
|
||||
workingDefinition.side2.sectorIds = new int[9];
|
||||
for(int si = 0; si < 9; si++) workingDefinition.side2.sectorIds[si] = si + 1;
|
||||
|
||||
workingDefinition.skew = 0;
|
||||
workingDefinition.sofs = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -609,50 +609,49 @@ namespace DiscImageChef.Filesystems.CPM
|
||||
{
|
||||
cpmFound = true;
|
||||
firstDirectorySector86 = 18;
|
||||
dpb = new DiscParameterBlock();
|
||||
dpb.al0 = 0xF0;
|
||||
dpb.al1 = 0;
|
||||
dpb.blm = 0x0F;
|
||||
dpb.bsh = 4;
|
||||
dpb.cks = 0x40;
|
||||
dpb.drm = 0xFF;
|
||||
dpb.dsm = 0x162;
|
||||
dpb.exm = 0;
|
||||
dpb.off = 2;
|
||||
dpb.phm = 3;
|
||||
dpb.psh = 2;
|
||||
dpb.spt = 9 * 4;
|
||||
dpb = new DiscParameterBlock
|
||||
{
|
||||
al0 = 0xF0,
|
||||
al1 = 0,
|
||||
blm = 0x0F,
|
||||
bsh = 4,
|
||||
cks = 0x40,
|
||||
drm = 0xFF,
|
||||
dsm = 0x162,
|
||||
exm = 0,
|
||||
off = 2,
|
||||
phm = 3,
|
||||
psh = 2,
|
||||
spt = 9 * 4
|
||||
};
|
||||
|
||||
workingDefinition = new CpmDefinition
|
||||
{
|
||||
al0 = dpb.al0,
|
||||
al1 = dpb.al1,
|
||||
bitrate = "LOW",
|
||||
blm = dpb.blm,
|
||||
bsh = dpb.bsh,
|
||||
bytesPerSector = 512,
|
||||
cylinders = 80,
|
||||
drm = dpb.drm,
|
||||
dsm = dpb.dsm,
|
||||
encoding = "MFM",
|
||||
evenOdd = false,
|
||||
exm = dpb.exm,
|
||||
label = null,
|
||||
comment = "CP/M-86 floppy identifier",
|
||||
ofs = dpb.off,
|
||||
sectorsPerTrack = 9,
|
||||
side1 = new Side {sideId = 0, sectorIds = new int[9]},
|
||||
order = "CYLINDERS",
|
||||
side2 = new Side {sideId = 1, sectorIds = new int[9]},
|
||||
skew = 0,
|
||||
sofs = 0
|
||||
};
|
||||
|
||||
workingDefinition = new CpmDefinition();
|
||||
workingDefinition.al0 = dpb.al0;
|
||||
workingDefinition.al1 = dpb.al1;
|
||||
workingDefinition.bitrate = "LOW";
|
||||
workingDefinition.blm = dpb.blm;
|
||||
workingDefinition.bsh = dpb.bsh;
|
||||
workingDefinition.bytesPerSector = 512;
|
||||
workingDefinition.cylinders = 80;
|
||||
workingDefinition.drm = dpb.drm;
|
||||
workingDefinition.dsm = dpb.dsm;
|
||||
workingDefinition.encoding = "MFM";
|
||||
workingDefinition.evenOdd = false;
|
||||
workingDefinition.exm = dpb.exm;
|
||||
workingDefinition.label = null;
|
||||
workingDefinition.comment = "CP/M-86 floppy identifier";
|
||||
workingDefinition.ofs = dpb.off;
|
||||
workingDefinition.sectorsPerTrack = 9;
|
||||
workingDefinition.side1 = new Side();
|
||||
workingDefinition.side1.sideId = 0;
|
||||
workingDefinition.side1.sectorIds = new int[9];
|
||||
for(int si = 0; si < 9; si++) workingDefinition.side1.sectorIds[si] = si + 1;
|
||||
|
||||
workingDefinition.order = "CYLINDERS";
|
||||
workingDefinition.side2 = new Side();
|
||||
workingDefinition.side2.sideId = 1;
|
||||
workingDefinition.side2.sectorIds = new int[9];
|
||||
for(int si = 0; si < 9; si++) workingDefinition.side2.sectorIds[si] = si + 1;
|
||||
|
||||
workingDefinition.skew = 0;
|
||||
workingDefinition.sofs = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -661,50 +660,49 @@ namespace DiscImageChef.Filesystems.CPM
|
||||
{
|
||||
cpmFound = true;
|
||||
firstDirectorySector86 = 30;
|
||||
dpb = new DiscParameterBlock();
|
||||
dpb.al0 = 0xC0;
|
||||
dpb.al1 = 0;
|
||||
dpb.blm = 0x1F;
|
||||
dpb.bsh = 5;
|
||||
dpb.cks = 0x40;
|
||||
dpb.drm = 0xFF;
|
||||
dpb.dsm = 0x127;
|
||||
dpb.exm = 1;
|
||||
dpb.off = 2;
|
||||
dpb.phm = 3;
|
||||
dpb.psh = 2;
|
||||
dpb.spt = 15 * 4;
|
||||
dpb = new DiscParameterBlock
|
||||
{
|
||||
al0 = 0xC0,
|
||||
al1 = 0,
|
||||
blm = 0x1F,
|
||||
bsh = 5,
|
||||
cks = 0x40,
|
||||
drm = 0xFF,
|
||||
dsm = 0x127,
|
||||
exm = 1,
|
||||
off = 2,
|
||||
phm = 3,
|
||||
psh = 2,
|
||||
spt = 15 * 4
|
||||
};
|
||||
|
||||
workingDefinition = new CpmDefinition
|
||||
{
|
||||
al0 = dpb.al0,
|
||||
al1 = dpb.al1,
|
||||
bitrate = "HIGH",
|
||||
blm = dpb.blm,
|
||||
bsh = dpb.bsh,
|
||||
bytesPerSector = 512,
|
||||
cylinders = 80,
|
||||
drm = dpb.drm,
|
||||
dsm = dpb.dsm,
|
||||
encoding = "MFM",
|
||||
evenOdd = false,
|
||||
exm = dpb.exm,
|
||||
label = null,
|
||||
comment = "CP/M-86 floppy identifier",
|
||||
ofs = dpb.off,
|
||||
sectorsPerTrack = 15,
|
||||
side1 = new Side {sideId = 0, sectorIds = new int[15]},
|
||||
order = "CYLINDERS",
|
||||
side2 = new Side {sideId = 1, sectorIds = new int[15]},
|
||||
skew = 0,
|
||||
sofs = 0
|
||||
};
|
||||
|
||||
workingDefinition = new CpmDefinition();
|
||||
workingDefinition.al0 = dpb.al0;
|
||||
workingDefinition.al1 = dpb.al1;
|
||||
workingDefinition.bitrate = "HIGH";
|
||||
workingDefinition.blm = dpb.blm;
|
||||
workingDefinition.bsh = dpb.bsh;
|
||||
workingDefinition.bytesPerSector = 512;
|
||||
workingDefinition.cylinders = 80;
|
||||
workingDefinition.drm = dpb.drm;
|
||||
workingDefinition.dsm = dpb.dsm;
|
||||
workingDefinition.encoding = "MFM";
|
||||
workingDefinition.evenOdd = false;
|
||||
workingDefinition.exm = dpb.exm;
|
||||
workingDefinition.label = null;
|
||||
workingDefinition.comment = "CP/M-86 floppy identifier";
|
||||
workingDefinition.ofs = dpb.off;
|
||||
workingDefinition.sectorsPerTrack = 15;
|
||||
workingDefinition.side1 = new Side();
|
||||
workingDefinition.side1.sideId = 0;
|
||||
workingDefinition.side1.sectorIds = new int[15];
|
||||
for(int si = 0; si < 15; si++) workingDefinition.side1.sectorIds[si] = si + 1;
|
||||
|
||||
workingDefinition.order = "CYLINDERS";
|
||||
workingDefinition.side2 = new Side();
|
||||
workingDefinition.side2.sideId = 1;
|
||||
workingDefinition.side2.sectorIds = new int[15];
|
||||
for(int si = 0; si < 15; si++) workingDefinition.side2.sectorIds[si] = si + 1;
|
||||
|
||||
workingDefinition.skew = 0;
|
||||
workingDefinition.sofs = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -713,50 +711,49 @@ namespace DiscImageChef.Filesystems.CPM
|
||||
{
|
||||
cpmFound = true;
|
||||
firstDirectorySector86 = 36;
|
||||
dpb = new DiscParameterBlock();
|
||||
dpb.al0 = 0xC0;
|
||||
dpb.al1 = 0;
|
||||
dpb.blm = 0x1F;
|
||||
dpb.bsh = 5;
|
||||
dpb.cks = 0x40;
|
||||
dpb.drm = 0xFF;
|
||||
dpb.dsm = 0x162;
|
||||
dpb.exm = 1;
|
||||
dpb.off = 2;
|
||||
dpb.phm = 3;
|
||||
dpb.psh = 2;
|
||||
dpb.spt = 18 * 4;
|
||||
dpb = new DiscParameterBlock
|
||||
{
|
||||
al0 = 0xC0,
|
||||
al1 = 0,
|
||||
blm = 0x1F,
|
||||
bsh = 5,
|
||||
cks = 0x40,
|
||||
drm = 0xFF,
|
||||
dsm = 0x162,
|
||||
exm = 1,
|
||||
off = 2,
|
||||
phm = 3,
|
||||
psh = 2,
|
||||
spt = 18 * 4
|
||||
};
|
||||
|
||||
workingDefinition = new CpmDefinition
|
||||
{
|
||||
al0 = dpb.al0,
|
||||
al1 = dpb.al1,
|
||||
bitrate = "LOW",
|
||||
blm = dpb.blm,
|
||||
bsh = dpb.bsh,
|
||||
bytesPerSector = 512,
|
||||
cylinders = 80,
|
||||
drm = dpb.drm,
|
||||
dsm = dpb.dsm,
|
||||
encoding = "MFM",
|
||||
evenOdd = false,
|
||||
exm = dpb.exm,
|
||||
label = null,
|
||||
comment = "CP/M-86 floppy identifier",
|
||||
ofs = dpb.off,
|
||||
sectorsPerTrack = 18,
|
||||
side1 = new Side {sideId = 0, sectorIds = new int[18]},
|
||||
order = "CYLINDERS",
|
||||
side2 = new Side {sideId = 1, sectorIds = new int[18]},
|
||||
skew = 0,
|
||||
sofs = 0
|
||||
};
|
||||
|
||||
workingDefinition = new CpmDefinition();
|
||||
workingDefinition.al0 = dpb.al0;
|
||||
workingDefinition.al1 = dpb.al1;
|
||||
workingDefinition.bitrate = "LOW";
|
||||
workingDefinition.blm = dpb.blm;
|
||||
workingDefinition.bsh = dpb.bsh;
|
||||
workingDefinition.bytesPerSector = 512;
|
||||
workingDefinition.cylinders = 80;
|
||||
workingDefinition.drm = dpb.drm;
|
||||
workingDefinition.dsm = dpb.dsm;
|
||||
workingDefinition.encoding = "MFM";
|
||||
workingDefinition.evenOdd = false;
|
||||
workingDefinition.exm = dpb.exm;
|
||||
workingDefinition.label = null;
|
||||
workingDefinition.comment = "CP/M-86 floppy identifier";
|
||||
workingDefinition.ofs = dpb.off;
|
||||
workingDefinition.sectorsPerTrack = 18;
|
||||
workingDefinition.side1 = new Side();
|
||||
workingDefinition.side1.sideId = 0;
|
||||
workingDefinition.side1.sectorIds = new int[18];
|
||||
for(int si = 0; si < 18; si++) workingDefinition.side1.sectorIds[si] = si + 1;
|
||||
|
||||
workingDefinition.order = "CYLINDERS";
|
||||
workingDefinition.side2 = new Side();
|
||||
workingDefinition.side2.sideId = 1;
|
||||
workingDefinition.side2.sectorIds = new int[18];
|
||||
for(int si = 0; si < 18; si++) workingDefinition.side2.sectorIds[si] = si + 1;
|
||||
|
||||
workingDefinition.skew = 0;
|
||||
workingDefinition.sofs = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -787,8 +784,7 @@ namespace DiscImageChef.Filesystems.CPM
|
||||
{
|
||||
// Load all definitions
|
||||
DicConsole.DebugWriteLine("CP/M Plugin", "Trying to load definitions.");
|
||||
if(LoadDefinitions() && definitions != null && definitions.definitions != null &&
|
||||
definitions.definitions.Count > 0)
|
||||
if(LoadDefinitions() && definitions?.definitions != null && definitions.definitions.Count > 0)
|
||||
{
|
||||
DicConsole.DebugWriteLine("CP/M Plugin", "Trying all known definitions.");
|
||||
foreach(CpmDefinition def in from def in definitions.definitions let sectors = (ulong)(def.cylinders * def.sides * def.sectorsPerTrack) where sectors == imagePlugin.GetSectors() && def.bytesPerSector == imagePlugin.GetSectorSize() select def) {
|
||||
@@ -889,16 +885,20 @@ namespace DiscImageChef.Filesystems.CPM
|
||||
|
||||
// Build a Disc Parameter Block
|
||||
workingDefinition = def;
|
||||
dpb = new DiscParameterBlock();
|
||||
dpb.al0 = (byte)def.al0;
|
||||
dpb.al1 = (byte)def.al1;
|
||||
dpb.blm = (byte)def.blm;
|
||||
dpb.bsh = (byte)def.bsh;
|
||||
dpb.cks = 0; // Needed?
|
||||
dpb.drm = (ushort)def.drm;
|
||||
dpb.dsm = (ushort)def.dsm;
|
||||
dpb.exm = (byte)def.exm;
|
||||
dpb.off = (ushort)def.ofs;
|
||||
dpb = new DiscParameterBlock
|
||||
{
|
||||
al0 = (byte)def.al0,
|
||||
al1 = (byte)def.al1,
|
||||
blm = (byte)def.blm,
|
||||
bsh = (byte)def.bsh,
|
||||
// Needed?
|
||||
cks = 0,
|
||||
drm = (ushort)def.drm,
|
||||
dsm = (ushort)def.dsm,
|
||||
exm = (byte)def.exm,
|
||||
off = (ushort)def.ofs,
|
||||
spt = (ushort)(def.sectorsPerTrack * def.bytesPerSector / 128)
|
||||
};
|
||||
switch(def.bytesPerSector)
|
||||
{
|
||||
case 128:
|
||||
@@ -939,7 +939,6 @@ namespace DiscImageChef.Filesystems.CPM
|
||||
break;
|
||||
}
|
||||
|
||||
dpb.spt = (ushort)(def.sectorsPerTrack * def.bytesPerSector / 128);
|
||||
cpmFound = true;
|
||||
workingDefinition = def;
|
||||
|
||||
@@ -991,12 +990,9 @@ namespace DiscImageChef.Filesystems.CPM
|
||||
workingDefinition.ofs * workingDefinition.sectorsPerTrack, workingDefinition.ofs)
|
||||
.AppendLine();
|
||||
|
||||
int interleaveSide1;
|
||||
int interleaveSide2;
|
||||
|
||||
if(workingDefinition.side1.sectorIds.Length >= 2)
|
||||
{
|
||||
interleaveSide1 = workingDefinition.side1.sectorIds[1] - workingDefinition.side1.sectorIds[0];
|
||||
int interleaveSide1 = workingDefinition.side1.sectorIds[1] - workingDefinition.side1.sectorIds[0];
|
||||
if(interleaveSide1 > 1)
|
||||
sb.AppendFormat("Side 0 uses {0}:1 software interleaving", interleaveSide1).AppendLine();
|
||||
}
|
||||
@@ -1005,7 +1001,7 @@ namespace DiscImageChef.Filesystems.CPM
|
||||
{
|
||||
if(workingDefinition.side2.sectorIds.Length >= 2)
|
||||
{
|
||||
interleaveSide2 = workingDefinition.side2.sectorIds[1] - workingDefinition.side2.sectorIds[0];
|
||||
int interleaveSide2 = workingDefinition.side2.sectorIds[1] - workingDefinition.side2.sectorIds[0];
|
||||
if(interleaveSide2 > 1)
|
||||
sb.AppendFormat("Side 1 uses {0}:1 software interleaving", interleaveSide2).AppendLine();
|
||||
}
|
||||
@@ -1046,23 +1042,23 @@ namespace DiscImageChef.Filesystems.CPM
|
||||
if(labelUpdateDate != null)
|
||||
sb.AppendFormat("Volume updated on {0}", DateHandlers.CPMToDateTime(labelUpdateDate)).AppendLine();
|
||||
|
||||
xmlFSType = new FileSystemType();
|
||||
xmlFSType.Bootable |= workingDefinition.sofs > 0 || workingDefinition.ofs > 0;
|
||||
xmlFSType.ClusterSize = 128 << dpb.bsh;
|
||||
if(dpb.dsm > 0) xmlFSType.Clusters = dpb.dsm;
|
||||
else xmlFSType.Clusters = (long)(partition.End - partition.Start);
|
||||
XmlFsType = new FileSystemType();
|
||||
XmlFsType.Bootable |= workingDefinition.sofs > 0 || workingDefinition.ofs > 0;
|
||||
XmlFsType.ClusterSize = 128 << dpb.bsh;
|
||||
if(dpb.dsm > 0) XmlFsType.Clusters = dpb.dsm;
|
||||
else XmlFsType.Clusters = (long)(partition.End - partition.Start);
|
||||
if(labelCreationDate != null)
|
||||
{
|
||||
xmlFSType.CreationDate = DateHandlers.CPMToDateTime(labelCreationDate);
|
||||
xmlFSType.CreationDateSpecified = true;
|
||||
XmlFsType.CreationDate = DateHandlers.CPMToDateTime(labelCreationDate);
|
||||
XmlFsType.CreationDateSpecified = true;
|
||||
}
|
||||
if(labelUpdateDate != null)
|
||||
{
|
||||
xmlFSType.ModificationDate = DateHandlers.CPMToDateTime(labelUpdateDate);
|
||||
xmlFSType.ModificationDateSpecified = true;
|
||||
XmlFsType.ModificationDate = DateHandlers.CPMToDateTime(labelUpdateDate);
|
||||
XmlFsType.ModificationDateSpecified = true;
|
||||
}
|
||||
xmlFSType.Type = "CP/M";
|
||||
xmlFSType.VolumeName = label;
|
||||
XmlFsType.Type = "CP/M";
|
||||
XmlFsType.VolumeName = label;
|
||||
|
||||
information = sb.ToString();
|
||||
}
|
||||
|
||||
@@ -149,8 +149,7 @@ namespace DiscImageChef.Filesystems.CPM
|
||||
// For each volume sector
|
||||
for(ulong a = 0; a < (ulong)deinterleavedSectors.Count; a++)
|
||||
{
|
||||
byte[] sector;
|
||||
deinterleavedSectors.TryGetValue(a, out sector);
|
||||
deinterleavedSectors.TryGetValue(a, out byte[] sector);
|
||||
|
||||
// May it happen? Just in case, CP/M blocks are smaller than physical sectors
|
||||
if(sector.Length > blockSize)
|
||||
@@ -187,8 +186,7 @@ namespace DiscImageChef.Filesystems.CPM
|
||||
MemoryStream dirMs = new MemoryStream();
|
||||
for(int d = 0; d < dirSectors; d++)
|
||||
{
|
||||
byte[] sector;
|
||||
deinterleavedSectors.TryGetValue((ulong)(d + dirOff), out sector);
|
||||
deinterleavedSectors.TryGetValue((ulong)(d + dirOff), out byte[] sector);
|
||||
dirMs.Write(sector, 0, sector.Length);
|
||||
}
|
||||
|
||||
@@ -219,10 +217,9 @@ namespace DiscImageChef.Filesystems.CPM
|
||||
if((directory[dOff] & 0x7F) < 0x10)
|
||||
if(allocationBlocks.Count > 256)
|
||||
{
|
||||
DirectoryEntry16 entry;
|
||||
dirPtr = Marshal.AllocHGlobal(32);
|
||||
Marshal.Copy(directory, dOff, dirPtr, 32);
|
||||
entry = (DirectoryEntry16)Marshal.PtrToStructure(dirPtr, typeof(DirectoryEntry16));
|
||||
DirectoryEntry16 entry = (DirectoryEntry16)Marshal.PtrToStructure(dirPtr, typeof(DirectoryEntry16));
|
||||
Marshal.FreeHGlobal(dirPtr);
|
||||
|
||||
bool hidden = (entry.statusUser & 0x80) == 0x80;
|
||||
@@ -254,24 +251,18 @@ namespace DiscImageChef.Filesystems.CPM
|
||||
if(!string.IsNullOrEmpty(extension)) filename = filename + "." + extension;
|
||||
|
||||
int entryNo = (32 * entry.extentCounter + entry.extentCounterHigh) / (dpb.exm + 1);
|
||||
List<ushort> blocks;
|
||||
Dictionary<int, List<ushort>> extentBlocks;
|
||||
FileEntryInfo fInfo;
|
||||
|
||||
// Do we have a stat for the file already?
|
||||
if(statCache.TryGetValue(filename, out fInfo)) statCache.Remove(filename);
|
||||
if(statCache.TryGetValue(filename, out FileEntryInfo fInfo)) statCache.Remove(filename);
|
||||
else
|
||||
{
|
||||
fInfo = new FileEntryInfo();
|
||||
fInfo.Attributes = new FileAttributes();
|
||||
}
|
||||
{ fInfo = new FileEntryInfo {Attributes = new FileAttributes()}; }
|
||||
|
||||
// And any extent?
|
||||
if(fileExtents.TryGetValue(filename, out extentBlocks)) fileExtents.Remove(filename);
|
||||
if(fileExtents.TryGetValue(filename, out Dictionary<int, List<ushort>> extentBlocks)) fileExtents.Remove(filename);
|
||||
else extentBlocks = new Dictionary<int, List<ushort>>();
|
||||
|
||||
// Do we already have this extent? Should never happen
|
||||
if(extentBlocks.TryGetValue(entryNo, out blocks)) extentBlocks.Remove(entryNo);
|
||||
if(extentBlocks.TryGetValue(entryNo, out List<ushort> blocks)) extentBlocks.Remove(entryNo);
|
||||
else blocks = new List<ushort>();
|
||||
|
||||
// Attributes
|
||||
@@ -313,10 +304,9 @@ namespace DiscImageChef.Filesystems.CPM
|
||||
}
|
||||
else
|
||||
{
|
||||
DirectoryEntry entry;
|
||||
dirPtr = Marshal.AllocHGlobal(32);
|
||||
Marshal.Copy(directory, dOff, dirPtr, 32);
|
||||
entry = (DirectoryEntry)Marshal.PtrToStructure(dirPtr, typeof(DirectoryEntry));
|
||||
DirectoryEntry entry = (DirectoryEntry)Marshal.PtrToStructure(dirPtr, typeof(DirectoryEntry));
|
||||
Marshal.FreeHGlobal(dirPtr);
|
||||
|
||||
bool hidden = (entry.statusUser & 0x80) == 0x80;
|
||||
@@ -348,24 +338,18 @@ namespace DiscImageChef.Filesystems.CPM
|
||||
if(!string.IsNullOrEmpty(extension)) filename = filename + "." + extension;
|
||||
|
||||
int entryNo = (32 * entry.extentCounterHigh + entry.extentCounter) / (dpb.exm + 1);
|
||||
List<ushort> blocks;
|
||||
Dictionary<int, List<ushort>> extentBlocks;
|
||||
FileEntryInfo fInfo;
|
||||
|
||||
// Do we have a stat for the file already?
|
||||
if(statCache.TryGetValue(filename, out fInfo)) statCache.Remove(filename);
|
||||
if(statCache.TryGetValue(filename, out FileEntryInfo fInfo)) statCache.Remove(filename);
|
||||
else
|
||||
{
|
||||
fInfo = new FileEntryInfo();
|
||||
fInfo.Attributes = new FileAttributes();
|
||||
}
|
||||
{ fInfo = new FileEntryInfo {Attributes = new FileAttributes()}; }
|
||||
|
||||
// And any extent?
|
||||
if(fileExtents.TryGetValue(filename, out extentBlocks)) fileExtents.Remove(filename);
|
||||
if(fileExtents.TryGetValue(filename, out Dictionary<int, List<ushort>> extentBlocks)) fileExtents.Remove(filename);
|
||||
else extentBlocks = new Dictionary<int, List<ushort>>();
|
||||
|
||||
// Do we already have this extent? Should never happen
|
||||
if(extentBlocks.TryGetValue(entryNo, out blocks)) extentBlocks.Remove(entryNo);
|
||||
if(extentBlocks.TryGetValue(entryNo, out List<ushort> blocks)) extentBlocks.Remove(entryNo);
|
||||
else blocks = new List<ushort>();
|
||||
|
||||
// Attributes
|
||||
@@ -408,10 +392,9 @@ namespace DiscImageChef.Filesystems.CPM
|
||||
// A password entry (or a file entry in PDOS, but this does not handle that case)
|
||||
else if((directory[dOff] & 0x7F) >= 0x10 && (directory[dOff] & 0x7F) < 0x20)
|
||||
{
|
||||
PasswordEntry entry;
|
||||
dirPtr = Marshal.AllocHGlobal(32);
|
||||
Marshal.Copy(directory, dOff, dirPtr, 32);
|
||||
entry = (PasswordEntry)Marshal.PtrToStructure(dirPtr, typeof(PasswordEntry));
|
||||
PasswordEntry entry = (PasswordEntry)Marshal.PtrToStructure(dirPtr, typeof(PasswordEntry));
|
||||
Marshal.FreeHGlobal(dirPtr);
|
||||
|
||||
int user = entry.userNumber & 0x0F;
|
||||
@@ -488,10 +471,9 @@ namespace DiscImageChef.Filesystems.CPM
|
||||
if(directory[dOff + 10] == 0x00 && directory[dOff + 20] == 0x00 && directory[dOff + 30] == 0x00 &&
|
||||
directory[dOff + 31] == 0x00)
|
||||
{
|
||||
DateEntry dateEntry;
|
||||
dirPtr = Marshal.AllocHGlobal(32);
|
||||
Marshal.Copy(directory, dOff, dirPtr, 32);
|
||||
dateEntry = (DateEntry)Marshal.PtrToStructure(dirPtr, typeof(DateEntry));
|
||||
DateEntry dateEntry = (DateEntry)Marshal.PtrToStructure(dirPtr, typeof(DateEntry));
|
||||
Marshal.FreeHGlobal(dirPtr);
|
||||
|
||||
FileEntryInfo fInfo;
|
||||
@@ -544,10 +526,9 @@ namespace DiscImageChef.Filesystems.CPM
|
||||
// However, if this byte is 0, timestamp is in Z80DOS or DOS+ format
|
||||
else if(directory[dOff + 1] == 0x00)
|
||||
{
|
||||
TrdPartyDateEntry trdPartyDateEntry;
|
||||
dirPtr = Marshal.AllocHGlobal(32);
|
||||
Marshal.Copy(directory, dOff, dirPtr, 32);
|
||||
trdPartyDateEntry = (TrdPartyDateEntry)Marshal.PtrToStructure(dirPtr, typeof(TrdPartyDateEntry));
|
||||
TrdPartyDateEntry trdPartyDateEntry = (TrdPartyDateEntry)Marshal.PtrToStructure(dirPtr, typeof(TrdPartyDateEntry));
|
||||
Marshal.FreeHGlobal(dirPtr);
|
||||
|
||||
FileEntryInfo fInfo;
|
||||
@@ -617,24 +598,19 @@ namespace DiscImageChef.Filesystems.CPM
|
||||
foreach(string filename in dirList)
|
||||
{
|
||||
MemoryStream fileMs = new MemoryStream();
|
||||
FileEntryInfo fInfo;
|
||||
|
||||
if(statCache.TryGetValue(filename, out fInfo)) statCache.Remove(filename);
|
||||
if(statCache.TryGetValue(filename, out FileEntryInfo fInfo)) statCache.Remove(filename);
|
||||
|
||||
fInfo.Blocks = 0;
|
||||
|
||||
Dictionary<int, List<ushort>> extents;
|
||||
if(fileExtents.TryGetValue(filename, out extents))
|
||||
if(fileExtents.TryGetValue(filename, out Dictionary<int, List<ushort>> extents))
|
||||
for(int ex = 0; ex < extents.Count; ex++)
|
||||
{
|
||||
List<ushort> alBlks;
|
||||
|
||||
if(!extents.TryGetValue(ex, out alBlks)) continue;
|
||||
if(!extents.TryGetValue(ex, out List<ushort> alBlks)) continue;
|
||||
|
||||
foreach(ushort alBlk in alBlks)
|
||||
{
|
||||
byte[] blk;
|
||||
allocationBlocks.TryGetValue(alBlk, out blk);
|
||||
allocationBlocks.TryGetValue(alBlk, out byte[] blk);
|
||||
fileMs.Write(blk, 0, blk.Length);
|
||||
fInfo.Blocks++;
|
||||
}
|
||||
@@ -668,29 +644,31 @@ namespace DiscImageChef.Filesystems.CPM
|
||||
cpmStat.FilenameLength = 11;
|
||||
cpmStat.Files = (ulong)fileCache.Count;
|
||||
cpmStat.FreeBlocks = cpmStat.Blocks - usedBlocks;
|
||||
cpmStat.PluginId = PluginUUID;
|
||||
cpmStat.PluginId = PluginUuid;
|
||||
cpmStat.Type = "CP/M filesystem";
|
||||
|
||||
// Generate XML info
|
||||
xmlFSType = new FileSystemType();
|
||||
xmlFSType.Clusters = cpmStat.Blocks;
|
||||
xmlFSType.ClusterSize = blockSize;
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
Clusters = cpmStat.Blocks,
|
||||
ClusterSize = blockSize,
|
||||
Files = fileCache.Count,
|
||||
FilesSpecified = true,
|
||||
FreeClusters = cpmStat.FreeBlocks,
|
||||
FreeClustersSpecified = true,
|
||||
Type = "CP/M filesystem"
|
||||
};
|
||||
if(labelCreationDate != null)
|
||||
{
|
||||
xmlFSType.CreationDate = DateHandlers.CPMToDateTime(labelCreationDate);
|
||||
xmlFSType.CreationDateSpecified = true;
|
||||
XmlFsType.CreationDate = DateHandlers.CPMToDateTime(labelCreationDate);
|
||||
XmlFsType.CreationDateSpecified = true;
|
||||
}
|
||||
if(labelUpdateDate != null)
|
||||
{
|
||||
xmlFSType.ModificationDate = DateHandlers.CPMToDateTime(labelUpdateDate);
|
||||
xmlFSType.ModificationDateSpecified = true;
|
||||
XmlFsType.ModificationDate = DateHandlers.CPMToDateTime(labelUpdateDate);
|
||||
XmlFsType.ModificationDateSpecified = true;
|
||||
}
|
||||
xmlFSType.Files = fileCache.Count;
|
||||
xmlFSType.FilesSpecified = true;
|
||||
xmlFSType.FreeClusters = cpmStat.FreeBlocks;
|
||||
xmlFSType.FreeClustersSpecified = true;
|
||||
xmlFSType.Type = "CP/M filesystem";
|
||||
if(!string.IsNullOrEmpty(label)) xmlFSType.VolumeName = label;
|
||||
if(!string.IsNullOrEmpty(label)) XmlFsType.VolumeName = label;
|
||||
|
||||
mounted = true;
|
||||
return Errno.NoError;
|
||||
|
||||
@@ -58,9 +58,7 @@ namespace DiscImageChef.Filesystems.CPM
|
||||
if(string.Compare(xattr, "com.caldera.cpm.password.text", StringComparison.InvariantCulture) != 0)
|
||||
return Errno.NoSuchExtendedAttribute;
|
||||
|
||||
if(!passwordCache.TryGetValue(pathElements[0].ToUpperInvariant(), out buf)) return Errno.NoError;
|
||||
|
||||
return Errno.NoSuchExtendedAttribute;
|
||||
return !passwordCache.TryGetValue(pathElements[0].ToUpperInvariant(), out buf) ? Errno.NoError : Errno.NoSuchExtendedAttribute;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -45,24 +45,22 @@ namespace DiscImageChef.Filesystems
|
||||
public Cram()
|
||||
{
|
||||
Name = "Cram filesystem";
|
||||
PluginUUID = new Guid("F8F6E46F-7A2A-48E3-9C0A-46AF4DC29E09");
|
||||
PluginUuid = new Guid("F8F6E46F-7A2A-48E3-9C0A-46AF4DC29E09");
|
||||
CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public Cram(Encoding encoding)
|
||||
{
|
||||
Name = "Cram filesystem";
|
||||
PluginUUID = new Guid("F8F6E46F-7A2A-48E3-9C0A-46AF4DC29E09");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("F8F6E46F-7A2A-48E3-9C0A-46AF4DC29E09");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public Cram(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "Cram filesystem";
|
||||
PluginUUID = new Guid("F8F6E46F-7A2A-48E3-9C0A-46AF4DC29E09");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("F8F6E46F-7A2A-48E3-9C0A-46AF4DC29E09");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
enum CramCompression : ushort
|
||||
@@ -92,8 +90,8 @@ namespace DiscImageChef.Filesystems
|
||||
/// <summary>
|
||||
/// Identifier for Cram
|
||||
/// </summary>
|
||||
const uint Cram_MAGIC = 0x28CD3D45;
|
||||
const uint Cram_CIGAM = 0x453DCD28;
|
||||
const uint CRAM_MAGIC = 0x28CD3D45;
|
||||
const uint CRAM_CIGAM = 0x453DCD28;
|
||||
|
||||
public override bool Identify(ImagePlugin imagePlugin, Partition partition)
|
||||
{
|
||||
@@ -103,7 +101,7 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
uint magic = BitConverter.ToUInt32(sector, 0x00);
|
||||
|
||||
return magic == Cram_MAGIC || magic == Cram_CIGAM;
|
||||
return magic == CRAM_MAGIC || magic == CRAM_CIGAM;
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
|
||||
@@ -116,13 +114,13 @@ namespace DiscImageChef.Filesystems
|
||||
bool littleEndian = true;
|
||||
|
||||
switch(magic) {
|
||||
case Cram_MAGIC:
|
||||
case CRAM_MAGIC:
|
||||
IntPtr crSbPtr = Marshal.AllocHGlobal(Marshal.SizeOf(crSb));
|
||||
Marshal.Copy(sector, 0, crSbPtr, Marshal.SizeOf(crSb));
|
||||
crSb = (CramSuperBlock)Marshal.PtrToStructure(crSbPtr, typeof(CramSuperBlock));
|
||||
Marshal.FreeHGlobal(crSbPtr);
|
||||
break;
|
||||
case Cram_CIGAM:
|
||||
case CRAM_CIGAM:
|
||||
crSb = BigEndianMarshal.ByteArrayToStructureBigEndian<CramSuperBlock>(sector);
|
||||
littleEndian = false;
|
||||
break;
|
||||
@@ -131,8 +129,7 @@ namespace DiscImageChef.Filesystems
|
||||
StringBuilder sbInformation = new StringBuilder();
|
||||
|
||||
sbInformation.AppendLine("Cram file system");
|
||||
if(littleEndian) sbInformation.AppendLine("Little-endian");
|
||||
else sbInformation.AppendLine("Big-endian");
|
||||
sbInformation.AppendLine(littleEndian ? "Little-endian" : "Big-endian");
|
||||
sbInformation.AppendFormat("Volume edition {0}", crSb.edition).AppendLine();
|
||||
sbInformation.AppendFormat("Volume name: {0}", StringHandlers.CToString(crSb.name, CurrentEncoding))
|
||||
.AppendLine();
|
||||
@@ -142,14 +139,16 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
information = sbInformation.ToString();
|
||||
|
||||
xmlFSType = new FileSystemType();
|
||||
xmlFSType.VolumeName = StringHandlers.CToString(crSb.name, CurrentEncoding);
|
||||
xmlFSType.Type = "Cram file system";
|
||||
xmlFSType.Clusters = crSb.blocks;
|
||||
xmlFSType.Files = crSb.files;
|
||||
xmlFSType.FilesSpecified = true;
|
||||
xmlFSType.FreeClusters = 0;
|
||||
xmlFSType.FreeClustersSpecified = true;
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
VolumeName = StringHandlers.CToString(crSb.name, CurrentEncoding),
|
||||
Type = "Cram file system",
|
||||
Clusters = crSb.blocks,
|
||||
Files = crSb.files,
|
||||
FilesSpecified = true,
|
||||
FreeClusters = 0,
|
||||
FreeClustersSpecified = true
|
||||
};
|
||||
}
|
||||
|
||||
public override Errno Mount()
|
||||
|
||||
@@ -46,24 +46,22 @@ namespace DiscImageChef.Filesystems
|
||||
public ECMA67()
|
||||
{
|
||||
Name = "ECMA-67";
|
||||
PluginUUID = new Guid("62A2D44A-CBC1-4377-B4B6-28C5C92034A1");
|
||||
PluginUuid = new Guid("62A2D44A-CBC1-4377-B4B6-28C5C92034A1");
|
||||
CurrentEncoding = Encoding.GetEncoding("iso-8859-1");
|
||||
}
|
||||
|
||||
public ECMA67(Encoding encoding)
|
||||
{
|
||||
Name = "ECMA-67";
|
||||
PluginUUID = new Guid("62A2D44A-CBC1-4377-B4B6-28C5C92034A1");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-1");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("62A2D44A-CBC1-4377-B4B6-28C5C92034A1");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1");
|
||||
}
|
||||
|
||||
public ECMA67(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "ECMA-67";
|
||||
PluginUUID = new Guid("62A2D44A-CBC1-4377-B4B6-28C5C92034A1");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-1");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("62A2D44A-CBC1-4377-B4B6-28C5C92034A1");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1");
|
||||
}
|
||||
|
||||
readonly byte[] ECMA67_Magic = {0x56, 0x4F, 0x4C};
|
||||
@@ -123,11 +121,13 @@ namespace DiscImageChef.Filesystems
|
||||
sbInformation.AppendFormat("Volume name: {0}", Encoding.ASCII.GetString(vol.volumeIdentifier)).AppendLine();
|
||||
sbInformation.AppendFormat("Volume owner: {0}", Encoding.ASCII.GetString(vol.owner)).AppendLine();
|
||||
|
||||
xmlFSType = new FileSystemType();
|
||||
xmlFSType.Type = "ECMA-67";
|
||||
xmlFSType.ClusterSize = 256;
|
||||
xmlFSType.Clusters = (long)(partition.End - partition.Start + 1);
|
||||
xmlFSType.VolumeName = Encoding.ASCII.GetString(vol.volumeIdentifier);
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
Type = "ECMA-67",
|
||||
ClusterSize = 256,
|
||||
Clusters = (long)(partition.End - partition.Start + 1),
|
||||
VolumeName = Encoding.ASCII.GetString(vol.volumeIdentifier)
|
||||
};
|
||||
|
||||
information = sbInformation.ToString();
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using DiscImageChef.CommonTypes;
|
||||
@@ -44,6 +45,7 @@ namespace DiscImageChef.Filesystems
|
||||
public class EFS : Filesystem
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
struct EFS_Superblock
|
||||
{
|
||||
/* 0: fs size incl. bb 0 (in bb) */
|
||||
@@ -90,30 +92,28 @@ namespace DiscImageChef.Filesystems
|
||||
public uint sb_checksum;
|
||||
}
|
||||
|
||||
const uint EFS_Magic = 0x00072959;
|
||||
const uint EFS_Magic_New = 0x0007295A;
|
||||
const uint EFS_MAGIC = 0x00072959;
|
||||
const uint EFS_MAGIC_NEW = 0x0007295A;
|
||||
|
||||
public EFS()
|
||||
{
|
||||
Name = "Extent File System Plugin";
|
||||
PluginUUID = new Guid("52A43F90-9AF3-4391-ADFE-65598DEEABAB");
|
||||
PluginUuid = new Guid("52A43F90-9AF3-4391-ADFE-65598DEEABAB");
|
||||
CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public EFS(Encoding encoding)
|
||||
{
|
||||
Name = "Extent File System Plugin";
|
||||
PluginUUID = new Guid("52A43F90-9AF3-4391-ADFE-65598DEEABAB");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("52A43F90-9AF3-4391-ADFE-65598DEEABAB");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public EFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "Extent File System Plugin";
|
||||
PluginUUID = new Guid("52A43F90-9AF3-4391-ADFE-65598DEEABAB");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("52A43F90-9AF3-4391-ADFE-65598DEEABAB");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugin imagePlugin, Partition partition)
|
||||
@@ -123,24 +123,24 @@ namespace DiscImageChef.Filesystems
|
||||
// Misaligned
|
||||
if(imagePlugin.ImageInfo.XmlMediaType == XmlMediaType.OpticalDisc)
|
||||
{
|
||||
EFS_Superblock efs_sb = new EFS_Superblock();
|
||||
EFS_Superblock efsSb = new EFS_Superblock();
|
||||
|
||||
uint sbSize = (uint)((Marshal.SizeOf(efs_sb) + 0x200) / imagePlugin.GetSectorSize());
|
||||
if((Marshal.SizeOf(efs_sb) + 0x200) % imagePlugin.GetSectorSize() != 0) sbSize++;
|
||||
uint sbSize = (uint)((Marshal.SizeOf(efsSb) + 0x200) / imagePlugin.GetSectorSize());
|
||||
if((Marshal.SizeOf(efsSb) + 0x200) % imagePlugin.GetSectorSize() != 0) sbSize++;
|
||||
|
||||
byte[] sector = imagePlugin.ReadSectors(partition.Start, sbSize);
|
||||
if(sector.Length < Marshal.SizeOf(efs_sb)) return false;
|
||||
if(sector.Length < Marshal.SizeOf(efsSb)) return false;
|
||||
|
||||
byte[] sbpiece = new byte[Marshal.SizeOf(efs_sb)];
|
||||
byte[] sbpiece = new byte[Marshal.SizeOf(efsSb)];
|
||||
|
||||
Array.Copy(sector, 0x200, sbpiece, 0, Marshal.SizeOf(efs_sb));
|
||||
Array.Copy(sector, 0x200, sbpiece, 0, Marshal.SizeOf(efsSb));
|
||||
|
||||
efs_sb = BigEndianMarshal.ByteArrayToStructureBigEndian<EFS_Superblock>(sbpiece);
|
||||
efsSb = BigEndianMarshal.ByteArrayToStructureBigEndian<EFS_Superblock>(sbpiece);
|
||||
|
||||
DicConsole.DebugWriteLine("EFS plugin", "magic at 0x{0:X3} = 0x{1:X8} (expected 0x{2:X8} or 0x{3:X8})",
|
||||
0x200, efs_sb.sb_magic, EFS_Magic, EFS_Magic_New);
|
||||
0x200, efsSb.sb_magic, EFS_MAGIC, EFS_MAGIC_NEW);
|
||||
|
||||
if(efs_sb.sb_magic == EFS_Magic || efs_sb.sb_magic == EFS_Magic_New) return true;
|
||||
if(efsSb.sb_magic == EFS_MAGIC || efsSb.sb_magic == EFS_MAGIC_NEW) return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -155,9 +155,9 @@ namespace DiscImageChef.Filesystems
|
||||
efsSb = BigEndianMarshal.ByteArrayToStructureBigEndian<EFS_Superblock>(sector);
|
||||
|
||||
DicConsole.DebugWriteLine("EFS plugin", "magic at {0} = 0x{1:X8} (expected 0x{2:X8} or 0x{3:X8})", 1,
|
||||
efsSb.sb_magic, EFS_Magic, EFS_Magic_New);
|
||||
efsSb.sb_magic, EFS_MAGIC, EFS_MAGIC_NEW);
|
||||
|
||||
if(efsSb.sb_magic == EFS_Magic || efsSb.sb_magic == EFS_Magic_New) return true;
|
||||
if(efsSb.sb_magic == EFS_MAGIC || efsSb.sb_magic == EFS_MAGIC_NEW) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -187,7 +187,7 @@ namespace DiscImageChef.Filesystems
|
||||
efsSb = BigEndianMarshal.ByteArrayToStructureBigEndian<EFS_Superblock>(sbpiece);
|
||||
|
||||
DicConsole.DebugWriteLine("EFS plugin", "magic at 0x{0:X3} = 0x{1:X8} (expected 0x{2:X8} or 0x{3:X8})",
|
||||
0x200, efsSb.sb_magic, EFS_Magic, EFS_Magic_New);
|
||||
0x200, efsSb.sb_magic, EFS_MAGIC, EFS_MAGIC_NEW);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -200,15 +200,15 @@ namespace DiscImageChef.Filesystems
|
||||
efsSb = BigEndianMarshal.ByteArrayToStructureBigEndian<EFS_Superblock>(sector);
|
||||
|
||||
DicConsole.DebugWriteLine("EFS plugin", "magic at {0} = 0x{1:X8} (expected 0x{2:X8} or 0x{3:X8})", 1,
|
||||
efsSb.sb_magic, EFS_Magic, EFS_Magic_New);
|
||||
efsSb.sb_magic, EFS_MAGIC, EFS_MAGIC_NEW);
|
||||
}
|
||||
|
||||
if(efsSb.sb_magic != EFS_Magic && efsSb.sb_magic != EFS_Magic_New) return;
|
||||
if(efsSb.sb_magic != EFS_MAGIC && efsSb.sb_magic != EFS_MAGIC_NEW) return;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("SGI extent filesystem");
|
||||
if(efsSb.sb_magic == EFS_Magic_New) sb.AppendLine("New version");
|
||||
if(efsSb.sb_magic == EFS_MAGIC_NEW) sb.AppendLine("New version");
|
||||
sb.AppendFormat("Filesystem size: {0} basic blocks", efsSb.sb_size).AppendLine();
|
||||
sb.AppendFormat("First cylinder group starts at block {0}", efsSb.sb_firstcg).AppendLine();
|
||||
sb.AppendFormat("Cylinder group size: {0} basic blocks", efsSb.sb_cgfsize).AppendLine();
|
||||
@@ -231,7 +231,7 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
information = sb.ToString();
|
||||
|
||||
xmlFSType = new FileSystemType
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
Type = "Extent File System",
|
||||
ClusterSize = 512,
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using DiscImageChef.CommonTypes;
|
||||
@@ -43,6 +44,7 @@ namespace DiscImageChef.Filesystems
|
||||
public class F2FS : Filesystem
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
struct F2FS_Superblock
|
||||
{
|
||||
public uint magic;
|
||||
@@ -92,39 +94,39 @@ namespace DiscImageChef.Filesystems
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 871)] public byte[] reserved;
|
||||
}
|
||||
|
||||
const uint F2FS_Magic = 0xF2F52010;
|
||||
const uint F2FS_SuperOffset = 1024;
|
||||
const uint F2FS_MinSector = 512;
|
||||
const uint F2FS_MaxSector = 4096;
|
||||
const uint F2FS_BlockSize = 4096;
|
||||
const uint F2FS_MAGIC = 0xF2F52010;
|
||||
const uint F2FS_SUPER_OFFSET = 1024;
|
||||
const uint F2FS_MIN_SECTOR = 512;
|
||||
const uint F2FS_MAX_SECTOR = 4096;
|
||||
const uint F2FS_BLOCK_SIZE = 4096;
|
||||
|
||||
public F2FS()
|
||||
{
|
||||
Name = "F2FS Plugin";
|
||||
PluginUUID = new Guid("82B0920F-5F0D-4063-9F57-ADE0AE02ECE5");
|
||||
PluginUuid = new Guid("82B0920F-5F0D-4063-9F57-ADE0AE02ECE5");
|
||||
CurrentEncoding = Encoding.Unicode;
|
||||
}
|
||||
|
||||
public F2FS(Encoding encoding)
|
||||
{
|
||||
Name = "F2FS Plugin";
|
||||
PluginUUID = new Guid("82B0920F-5F0D-4063-9F57-ADE0AE02ECE5");
|
||||
PluginUuid = new Guid("82B0920F-5F0D-4063-9F57-ADE0AE02ECE5");
|
||||
CurrentEncoding = Encoding.Unicode;
|
||||
}
|
||||
|
||||
public F2FS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "F2FS Plugin";
|
||||
PluginUUID = new Guid("82B0920F-5F0D-4063-9F57-ADE0AE02ECE5");
|
||||
PluginUuid = new Guid("82B0920F-5F0D-4063-9F57-ADE0AE02ECE5");
|
||||
CurrentEncoding = Encoding.Unicode;
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugin imagePlugin, Partition partition)
|
||||
{
|
||||
if(imagePlugin.GetSectorSize() < F2FS_MinSector || imagePlugin.GetSectorSize() > F2FS_MaxSector)
|
||||
if(imagePlugin.GetSectorSize() < F2FS_MIN_SECTOR || imagePlugin.GetSectorSize() > F2FS_MAX_SECTOR)
|
||||
return false;
|
||||
|
||||
uint sbAddr = F2FS_SuperOffset / imagePlugin.GetSectorSize();
|
||||
uint sbAddr = F2FS_SUPER_OFFSET / imagePlugin.GetSectorSize();
|
||||
if(sbAddr == 0) sbAddr = 1;
|
||||
|
||||
F2FS_Superblock f2fsSb = new F2FS_Superblock();
|
||||
@@ -142,16 +144,16 @@ namespace DiscImageChef.Filesystems
|
||||
f2fsSb = (F2FS_Superblock)Marshal.PtrToStructure(sbPtr, typeof(F2FS_Superblock));
|
||||
Marshal.FreeHGlobal(sbPtr);
|
||||
|
||||
return f2fsSb.magic == F2FS_Magic;
|
||||
return f2fsSb.magic == F2FS_MAGIC;
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
|
||||
out string information)
|
||||
{
|
||||
information = "";
|
||||
if(imagePlugin.GetSectorSize() < F2FS_MinSector || imagePlugin.GetSectorSize() > F2FS_MaxSector) return;
|
||||
if(imagePlugin.GetSectorSize() < F2FS_MIN_SECTOR || imagePlugin.GetSectorSize() > F2FS_MAX_SECTOR) return;
|
||||
|
||||
uint sbAddr = F2FS_SuperOffset / imagePlugin.GetSectorSize();
|
||||
uint sbAddr = F2FS_SUPER_OFFSET / imagePlugin.GetSectorSize();
|
||||
if(sbAddr == 0) sbAddr = 1;
|
||||
|
||||
F2FS_Superblock f2fsSb = new F2FS_Superblock();
|
||||
@@ -167,7 +169,7 @@ namespace DiscImageChef.Filesystems
|
||||
f2fsSb = (F2FS_Superblock)Marshal.PtrToStructure(sbPtr, typeof(F2FS_Superblock));
|
||||
Marshal.FreeHGlobal(sbPtr);
|
||||
|
||||
if(f2fsSb.magic != F2FS_Magic) return;
|
||||
if(f2fsSb.magic != F2FS_MAGIC) return;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
@@ -193,14 +195,16 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
information = sb.ToString();
|
||||
|
||||
xmlFSType = new FileSystemType();
|
||||
xmlFSType.Type = "F2FS filesystem";
|
||||
xmlFSType.SystemIdentifier = Encoding.ASCII.GetString(f2fsSb.version);
|
||||
xmlFSType.Clusters = (long)f2fsSb.block_count;
|
||||
xmlFSType.ClusterSize = 1 << (int)f2fsSb.log_blocksize;
|
||||
xmlFSType.DataPreparerIdentifier = Encoding.ASCII.GetString(f2fsSb.init_version);
|
||||
xmlFSType.VolumeName = StringHandlers.CToString(f2fsSb.volume_name, Encoding.Unicode, true);
|
||||
xmlFSType.VolumeSerial = f2fsSb.uuid.ToString();
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
Type = "F2FS filesystem",
|
||||
SystemIdentifier = Encoding.ASCII.GetString(f2fsSb.version),
|
||||
Clusters = (long)f2fsSb.block_count,
|
||||
ClusterSize = 1 << (int)f2fsSb.log_blocksize,
|
||||
DataPreparerIdentifier = Encoding.ASCII.GetString(f2fsSb.init_version),
|
||||
VolumeName = StringHandlers.CToString(f2fsSb.volume_name, Encoding.Unicode, true),
|
||||
VolumeSerial = f2fsSb.uuid.ToString()
|
||||
};
|
||||
}
|
||||
|
||||
public override Errno Mount()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -51,26 +51,26 @@ namespace DiscImageChef.Filesystems
|
||||
public uint rootDirectoryCluster;
|
||||
}
|
||||
|
||||
const uint FATX_Magic = 0x58544146;
|
||||
const uint FATX_MAGIC = 0x58544146;
|
||||
|
||||
public FATX()
|
||||
{
|
||||
Name = "FATX Filesystem Plugin";
|
||||
PluginUUID = new Guid("ED27A721-4A17-4649-89FD-33633B46E228");
|
||||
PluginUuid = new Guid("ED27A721-4A17-4649-89FD-33633B46E228");
|
||||
CurrentEncoding = Encoding.UTF8;
|
||||
}
|
||||
|
||||
public FATX(Encoding encoding)
|
||||
{
|
||||
Name = "FATX Filesystem Plugin";
|
||||
PluginUUID = new Guid("ED27A721-4A17-4649-89FD-33633B46E228");
|
||||
PluginUuid = new Guid("ED27A721-4A17-4649-89FD-33633B46E228");
|
||||
CurrentEncoding = Encoding.UTF8;
|
||||
}
|
||||
|
||||
public FATX(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "FATX Filesystem Plugin";
|
||||
PluginUUID = new Guid("ED27A721-4A17-4649-89FD-33633B46E228");
|
||||
PluginUuid = new Guid("ED27A721-4A17-4649-89FD-33633B46E228");
|
||||
CurrentEncoding = Encoding.UTF8;
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
fatxSb = BigEndianMarshal.ByteArrayToStructureBigEndian<FATX_Superblock>(sector);
|
||||
|
||||
return fatxSb.magic == FATX_Magic;
|
||||
return fatxSb.magic == FATX_MAGIC;
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
|
||||
@@ -98,7 +98,7 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
fatxSb = BigEndianMarshal.ByteArrayToStructureBigEndian<FATX_Superblock>(sector);
|
||||
|
||||
if(fatxSb.magic != FATX_Magic) return;
|
||||
if(fatxSb.magic != FATX_MAGIC) return;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
@@ -110,11 +110,13 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
information = sb.ToString();
|
||||
|
||||
xmlFSType = new FileSystemType();
|
||||
xmlFSType.Type = "FATX filesystem";
|
||||
xmlFSType.ClusterSize = (int)(fatxSb.sectorsPerCluster * imagePlugin.ImageInfo.SectorSize);
|
||||
xmlFSType.Clusters = (long)((partition.End - partition.Start + 1) * imagePlugin.ImageInfo.SectorSize /
|
||||
(ulong)xmlFSType.ClusterSize);
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
Type = "FATX filesystem",
|
||||
ClusterSize = (int)(fatxSb.sectorsPerCluster * imagePlugin.ImageInfo.SectorSize)
|
||||
};
|
||||
XmlFsType.Clusters = (long)((partition.End - partition.Start + 1) * imagePlugin.ImageInfo.SectorSize /
|
||||
(ulong)XmlFsType.ClusterSize);
|
||||
}
|
||||
|
||||
public override Errno Mount()
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
@@ -45,42 +46,39 @@ using ufs_daddr_t = System.Int32;
|
||||
namespace DiscImageChef.Filesystems
|
||||
{
|
||||
// Using information from Linux kernel headers
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
public class FFSPlugin : Filesystem
|
||||
{
|
||||
public FFSPlugin()
|
||||
{
|
||||
Name = "BSD Fast File System (aka UNIX File System, UFS)";
|
||||
PluginUUID = new Guid("CC90D342-05DB-48A8-988C-C1FE000034A3");
|
||||
PluginUuid = new Guid("CC90D342-05DB-48A8-988C-C1FE000034A3");
|
||||
CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public FFSPlugin(Encoding encoding)
|
||||
{
|
||||
Name = "BSD Fast File System (aka UNIX File System, UFS)";
|
||||
PluginUUID = new Guid("CC90D342-05DB-48A8-988C-C1FE000034A3");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("CC90D342-05DB-48A8-988C-C1FE000034A3");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public FFSPlugin(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "BSD Fast File System (aka UNIX File System, UFS)";
|
||||
PluginUUID = new Guid("CC90D342-05DB-48A8-988C-C1FE000034A3");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("CC90D342-05DB-48A8-988C-C1FE000034A3");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugin imagePlugin, Partition partition)
|
||||
{
|
||||
if(2 + partition.Start >= partition.End) return false;
|
||||
|
||||
uint magic;
|
||||
uint sb_size_in_sectors;
|
||||
byte[] ufs_sb_sectors;
|
||||
uint sbSizeInSectors;
|
||||
|
||||
if(imagePlugin.GetSectorSize() == 2336 || imagePlugin.GetSectorSize() == 2352 ||
|
||||
imagePlugin.GetSectorSize() == 2448) sb_size_in_sectors = block_size / 2048;
|
||||
else sb_size_in_sectors = block_size / imagePlugin.GetSectorSize();
|
||||
imagePlugin.GetSectorSize() == 2448) sbSizeInSectors = block_size / 2048;
|
||||
else sbSizeInSectors = block_size / imagePlugin.GetSectorSize();
|
||||
|
||||
ulong[] locations =
|
||||
{
|
||||
@@ -89,16 +87,7 @@ namespace DiscImageChef.Filesystems
|
||||
262144 / imagePlugin.GetSectorSize()
|
||||
};
|
||||
|
||||
foreach(ulong loc in locations.Where(loc => partition.End > partition.Start + loc + sb_size_in_sectors)) {
|
||||
ufs_sb_sectors = imagePlugin.ReadSectors(partition.Start + loc, sb_size_in_sectors);
|
||||
magic = BitConverter.ToUInt32(ufs_sb_sectors, 0x055C);
|
||||
|
||||
if(magic == UFS_MAGIC || magic == UFS_CIGAM || magic == UFS_MAGIC_BW || magic == UFS_CIGAM_BW ||
|
||||
magic == UFS2_MAGIC || magic == UFS2_CIGAM || magic == UFS_BAD_MAGIC ||
|
||||
magic == UFS_BAD_CIGAM) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return locations.Where(loc => partition.End > partition.Start + loc + sbSizeInSectors).Select(loc => imagePlugin.ReadSectors(partition.Start + loc, sbSizeInSectors)).Select(ufsSbSectors => BitConverter.ToUInt32(ufsSbSectors, 0x055C)).Any(magic => magic == UFS_MAGIC || magic == UFS_CIGAM || magic == UFS_MAGIC_BW || magic == UFS_CIGAM_BW || magic == UFS2_MAGIC || magic == UFS2_CIGAM || magic == UFS_BAD_MAGIC || magic == UFS_BAD_CIGAM);
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
|
||||
@@ -150,43 +139,43 @@ namespace DiscImageChef.Filesystems
|
||||
return;
|
||||
}
|
||||
|
||||
xmlFSType = new FileSystemType();
|
||||
XmlFsType = new FileSystemType();
|
||||
|
||||
switch(magic)
|
||||
{
|
||||
case UFS_MAGIC:
|
||||
sbInformation.AppendLine("UFS filesystem");
|
||||
xmlFSType.Type = "UFS";
|
||||
XmlFsType.Type = "UFS";
|
||||
break;
|
||||
case UFS_CIGAM:
|
||||
sbInformation.AppendLine("Big-endian UFS filesystem");
|
||||
xmlFSType.Type = "UFS";
|
||||
XmlFsType.Type = "UFS";
|
||||
break;
|
||||
case UFS_MAGIC_BW:
|
||||
sbInformation.AppendLine("BorderWare UFS filesystem");
|
||||
xmlFSType.Type = "UFS";
|
||||
XmlFsType.Type = "UFS";
|
||||
break;
|
||||
case UFS_CIGAM_BW:
|
||||
sbInformation.AppendLine("Big-endian BorderWare UFS filesystem");
|
||||
xmlFSType.Type = "UFS";
|
||||
XmlFsType.Type = "UFS";
|
||||
break;
|
||||
case UFS2_MAGIC:
|
||||
sbInformation.AppendLine("UFS2 filesystem");
|
||||
xmlFSType.Type = "UFS2";
|
||||
XmlFsType.Type = "UFS2";
|
||||
break;
|
||||
case UFS2_CIGAM:
|
||||
sbInformation.AppendLine("Big-endian UFS2 filesystem");
|
||||
xmlFSType.Type = "UFS2";
|
||||
XmlFsType.Type = "UFS2";
|
||||
break;
|
||||
case UFS_BAD_MAGIC:
|
||||
sbInformation.AppendLine("Incompletely initialized UFS filesystem");
|
||||
sbInformation.AppendLine("BEWARE!!! Following information may be completely wrong!");
|
||||
xmlFSType.Type = "UFS";
|
||||
XmlFsType.Type = "UFS";
|
||||
break;
|
||||
case UFS_BAD_CIGAM:
|
||||
sbInformation.AppendLine("Incompletely initialized big-endian UFS filesystem");
|
||||
sbInformation.AppendLine("BEWARE!!! Following information may be completely wrong!");
|
||||
xmlFSType.Type = "UFS";
|
||||
XmlFsType.Type = "UFS";
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -332,12 +321,12 @@ namespace DiscImageChef.Filesystems
|
||||
sbInformation.AppendFormat("Cylinder group offset in cylinder: {0}", ufs_sb.fs_old_cgoffset).AppendLine();
|
||||
sbInformation.AppendFormat("Volume last written on {0}", DateHandlers.UNIXToDateTime(ufs_sb.fs_old_time))
|
||||
.AppendLine();
|
||||
xmlFSType.ModificationDate = DateHandlers.UNIXToDateTime(ufs_sb.fs_old_time);
|
||||
xmlFSType.ModificationDateSpecified = true;
|
||||
XmlFsType.ModificationDate = DateHandlers.UNIXToDateTime(ufs_sb.fs_old_time);
|
||||
XmlFsType.ModificationDateSpecified = true;
|
||||
sbInformation.AppendFormat("{0} blocks in volume ({1} bytes)", ufs_sb.fs_old_size,
|
||||
(long)ufs_sb.fs_old_size * ufs_sb.fs_fsize).AppendLine();
|
||||
xmlFSType.Clusters = ufs_sb.fs_old_size;
|
||||
xmlFSType.ClusterSize = ufs_sb.fs_fsize;
|
||||
XmlFsType.Clusters = ufs_sb.fs_old_size;
|
||||
XmlFsType.ClusterSize = ufs_sb.fs_fsize;
|
||||
sbInformation.AppendFormat("{0} data blocks in volume ({1} bytes)", ufs_sb.fs_old_dsize,
|
||||
(long)ufs_sb.fs_old_dsize * ufs_sb.fs_fsize).AppendLine();
|
||||
sbInformation.AppendFormat("{0} cylinder groups in volume", ufs_sb.fs_ncg).AppendLine();
|
||||
@@ -366,6 +355,7 @@ namespace DiscImageChef.Filesystems
|
||||
default: sbInformation.AppendFormat("Unknown optimization value: 0x{0:X8}", ufs_sb.fs_optim).AppendLine();
|
||||
break;
|
||||
}
|
||||
|
||||
if(fs_type_sun) sbInformation.AppendFormat("{0} sectors/track", ufs_sb.fs_old_npsect).AppendLine();
|
||||
else if(fs_type_sun86)
|
||||
sbInformation.AppendFormat("Volume state on {0}", DateHandlers.UNIXToDateTime(ufs_sb.fs_old_npsect))
|
||||
@@ -391,14 +381,14 @@ namespace DiscImageChef.Filesystems
|
||||
sbInformation.AppendFormat("{0} directories", ufs_sb.fs_old_cstotal.cs_ndir).AppendLine();
|
||||
sbInformation.AppendFormat("{0} free blocks ({1} bytes)", ufs_sb.fs_old_cstotal.cs_nbfree,
|
||||
(long)ufs_sb.fs_old_cstotal.cs_nbfree * ufs_sb.fs_fsize).AppendLine();
|
||||
xmlFSType.FreeClusters = ufs_sb.fs_old_cstotal.cs_nbfree;
|
||||
xmlFSType.FreeClustersSpecified = true;
|
||||
XmlFsType.FreeClusters = ufs_sb.fs_old_cstotal.cs_nbfree;
|
||||
XmlFsType.FreeClustersSpecified = true;
|
||||
sbInformation.AppendFormat("{0} free inodes", ufs_sb.fs_old_cstotal.cs_nifree).AppendLine();
|
||||
sbInformation.AppendFormat("{0} free frags", ufs_sb.fs_old_cstotal.cs_nffree).AppendLine();
|
||||
if(ufs_sb.fs_fmod == 1)
|
||||
{
|
||||
sbInformation.AppendLine("Superblock is under modification");
|
||||
xmlFSType.Dirty = true;
|
||||
XmlFsType.Dirty = true;
|
||||
}
|
||||
if(ufs_sb.fs_clean == 1) sbInformation.AppendLine("Volume is clean");
|
||||
if(ufs_sb.fs_ronly == 1) sbInformation.AppendLine("Volume is read-only");
|
||||
@@ -412,7 +402,7 @@ namespace DiscImageChef.Filesystems
|
||||
.AppendLine();
|
||||
sbInformation.AppendFormat("Volume name: \"{0}\"", StringHandlers.CToString(ufs_sb.fs_volname))
|
||||
.AppendLine();
|
||||
xmlFSType.VolumeName = StringHandlers.CToString(ufs_sb.fs_volname);
|
||||
XmlFsType.VolumeName = StringHandlers.CToString(ufs_sb.fs_volname);
|
||||
sbInformation.AppendFormat("Volume ID: 0x{0:X16}", ufs_sb.fs_swuid).AppendLine();
|
||||
//xmlFSType.VolumeSerial = string.Format("{0:X16}", ufs_sb.fs_swuid);
|
||||
sbInformation.AppendFormat("Last searched cylinder group: {0}", ufs_sb.fs_cgrotor).AppendLine();
|
||||
@@ -421,18 +411,18 @@ namespace DiscImageChef.Filesystems
|
||||
sbInformation.AppendFormat("{0} directories", ufs_sb.fs_cstotal.cs_ndir).AppendLine();
|
||||
sbInformation.AppendFormat("{0} free blocks ({1} bytes)", ufs_sb.fs_cstotal.cs_nbfree,
|
||||
ufs_sb.fs_cstotal.cs_nbfree * ufs_sb.fs_fsize).AppendLine();
|
||||
xmlFSType.FreeClusters = ufs_sb.fs_cstotal.cs_nbfree;
|
||||
xmlFSType.FreeClustersSpecified = true;
|
||||
XmlFsType.FreeClusters = ufs_sb.fs_cstotal.cs_nbfree;
|
||||
XmlFsType.FreeClustersSpecified = true;
|
||||
sbInformation.AppendFormat("{0} free inodes", ufs_sb.fs_cstotal.cs_nifree).AppendLine();
|
||||
sbInformation.AppendFormat("{0} free frags", ufs_sb.fs_cstotal.cs_nffree).AppendLine();
|
||||
sbInformation.AppendFormat("{0} free clusters", ufs_sb.fs_cstotal.cs_numclusters).AppendLine();
|
||||
sbInformation.AppendFormat("Volume last written on {0}", DateHandlers.UNIXToDateTime(ufs_sb.fs_time))
|
||||
.AppendLine();
|
||||
xmlFSType.ModificationDate = DateHandlers.UNIXToDateTime(ufs_sb.fs_time);
|
||||
xmlFSType.ModificationDateSpecified = true;
|
||||
XmlFsType.ModificationDate = DateHandlers.UNIXToDateTime(ufs_sb.fs_time);
|
||||
XmlFsType.ModificationDateSpecified = true;
|
||||
sbInformation.AppendFormat("{0} blocks ({1} bytes)", ufs_sb.fs_size, ufs_sb.fs_size * ufs_sb.fs_fsize)
|
||||
.AppendLine();
|
||||
xmlFSType.Clusters = ufs_sb.fs_size;
|
||||
XmlFsType.Clusters = ufs_sb.fs_size;
|
||||
sbInformation
|
||||
.AppendFormat("{0} data blocks ({1} bytes)", ufs_sb.fs_dsize, ufs_sb.fs_dsize * ufs_sb.fs_fsize)
|
||||
.AppendLine();
|
||||
|
||||
@@ -47,18 +47,15 @@ namespace DiscImageChef.Filesystems
|
||||
/// <summary>Plugin name.</summary>
|
||||
public string Name;
|
||||
/// <summary>Plugin UUID.</summary>
|
||||
public Guid PluginUUID;
|
||||
internal FileSystemType xmlFSType;
|
||||
public Encoding CurrentEncoding;
|
||||
public Guid PluginUuid;
|
||||
internal FileSystemType XmlFsType;
|
||||
protected Encoding CurrentEncoding;
|
||||
|
||||
/// <summary>
|
||||
/// Information about the filesystem as expected by CICM Metadata XML
|
||||
/// </summary>
|
||||
/// <value>Information about the filesystem as expected by CICM Metadata XML</value>
|
||||
public FileSystemType XmlFSType
|
||||
{
|
||||
get { return xmlFSType; }
|
||||
}
|
||||
public FileSystemType XmlFSType => XmlFsType;
|
||||
|
||||
protected Filesystem() { }
|
||||
|
||||
|
||||
@@ -121,22 +121,22 @@ namespace DiscImageChef.Filesystems
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] public byte[] name;
|
||||
}
|
||||
|
||||
const uint Fossil_HdrMagic = 0x3776AE89;
|
||||
const uint Fossil_SbMagic = 0x2340A3B1;
|
||||
const uint FOSSIL_HDR_MAGIC = 0x3776AE89;
|
||||
const uint FOSSIL_SB_MAGIC = 0x2340A3B1;
|
||||
// Fossil header starts at 128KiB
|
||||
const ulong HeaderPos = 128 * 1024;
|
||||
const ulong HEADER_POS = 128 * 1024;
|
||||
|
||||
public Fossil()
|
||||
{
|
||||
Name = "Fossil Filesystem Plugin";
|
||||
PluginUUID = new Guid("932BF104-43F6-494F-973C-45EF58A51DA9");
|
||||
PluginUuid = new Guid("932BF104-43F6-494F-973C-45EF58A51DA9");
|
||||
CurrentEncoding = Encoding.UTF8;
|
||||
}
|
||||
|
||||
public Fossil(Encoding encoding)
|
||||
{
|
||||
Name = "Fossil Filesystem Plugin";
|
||||
PluginUUID = new Guid("932BF104-43F6-494F-973C-45EF58A51DA9");
|
||||
PluginUuid = new Guid("932BF104-43F6-494F-973C-45EF58A51DA9");
|
||||
// Technically everything on Plan 9 from Bell Labs is in UTF-8
|
||||
CurrentEncoding = Encoding.UTF8;
|
||||
}
|
||||
@@ -144,14 +144,14 @@ namespace DiscImageChef.Filesystems
|
||||
public Fossil(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "Fossil Filesystem Plugin";
|
||||
PluginUUID = new Guid("932BF104-43F6-494F-973C-45EF58A51DA9");
|
||||
PluginUuid = new Guid("932BF104-43F6-494F-973C-45EF58A51DA9");
|
||||
// Technically everything on Plan 9 from Bell Labs is in UTF-8
|
||||
CurrentEncoding = Encoding.UTF8;
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugin imagePlugin, Partition partition)
|
||||
{
|
||||
ulong hdrSector = HeaderPos / imagePlugin.GetSectorSize();
|
||||
ulong hdrSector = HEADER_POS / imagePlugin.GetSectorSize();
|
||||
|
||||
FossilHeader hdr;
|
||||
|
||||
@@ -161,9 +161,9 @@ namespace DiscImageChef.Filesystems
|
||||
hdr = BigEndianMarshal.ByteArrayToStructureBigEndian<FossilHeader>(sector);
|
||||
|
||||
DicConsole.DebugWriteLine("Fossil plugin", "magic at 0x{0:X8} (expected 0x{1:X8})", hdr.magic,
|
||||
Fossil_HdrMagic);
|
||||
FOSSIL_HDR_MAGIC);
|
||||
|
||||
return hdr.magic == Fossil_HdrMagic;
|
||||
return hdr.magic == FOSSIL_HDR_MAGIC;
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
|
||||
@@ -172,7 +172,7 @@ namespace DiscImageChef.Filesystems
|
||||
information = "";
|
||||
if(imagePlugin.GetSectorSize() < 512) return;
|
||||
|
||||
ulong hdrSector = HeaderPos / imagePlugin.GetSectorSize();
|
||||
ulong hdrSector = HEADER_POS / imagePlugin.GetSectorSize();
|
||||
|
||||
FossilHeader hdr;
|
||||
|
||||
@@ -180,7 +180,7 @@ namespace DiscImageChef.Filesystems
|
||||
hdr = BigEndianMarshal.ByteArrayToStructureBigEndian<FossilHeader>(sector);
|
||||
|
||||
DicConsole.DebugWriteLine("Fossil plugin", "magic at 0x{0:X8} (expected 0x{1:X8})", hdr.magic,
|
||||
Fossil_HdrMagic);
|
||||
FOSSIL_HDR_MAGIC);
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
@@ -194,7 +194,7 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
ulong sbLocation = hdr.super * (hdr.blockSize / imagePlugin.GetSectorSize()) + partition.Start;
|
||||
|
||||
xmlFSType = new FileSystemType
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
Type = "Fossil filesystem",
|
||||
ClusterSize = hdr.blockSize,
|
||||
@@ -207,9 +207,9 @@ namespace DiscImageChef.Filesystems
|
||||
FossilSuperBlock fsb = BigEndianMarshal.ByteArrayToStructureBigEndian<FossilSuperBlock>(sector);
|
||||
|
||||
DicConsole.DebugWriteLine("Fossil plugin", "magic 0x{0:X8} (expected 0x{1:X8})", fsb.magic,
|
||||
Fossil_SbMagic);
|
||||
FOSSIL_SB_MAGIC);
|
||||
|
||||
if(fsb.magic == Fossil_SbMagic)
|
||||
if(fsb.magic == FOSSIL_SB_MAGIC)
|
||||
{
|
||||
sb.AppendFormat("Epoch low {0}", fsb.epochLow).AppendLine();
|
||||
sb.AppendFormat("Epoch high {0}", fsb.epochHigh).AppendLine();
|
||||
@@ -219,7 +219,7 @@ namespace DiscImageChef.Filesystems
|
||||
sb.AppendFormat("Curren root block {0}", fsb.current).AppendLine();
|
||||
sb.AppendFormat("Volume label: \"{0}\"", StringHandlers.CToString(fsb.name, CurrentEncoding))
|
||||
.AppendLine();
|
||||
xmlFSType.VolumeName = StringHandlers.CToString(fsb.name, CurrentEncoding);
|
||||
XmlFsType.VolumeName = StringHandlers.CToString(fsb.name, CurrentEncoding);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using DiscImageChef.CommonTypes;
|
||||
@@ -40,9 +41,12 @@ using Schemas;
|
||||
using hammer_crc_t = System.UInt32;
|
||||
using hammer_off_t = System.UInt64;
|
||||
using hammer_tid_t = System.UInt64;
|
||||
#pragma warning disable 169
|
||||
|
||||
namespace DiscImageChef.Filesystems
|
||||
{
|
||||
[SuppressMessage("ReSharper", "BuiltInTypeReferenceStyle")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
public class HAMMER : Filesystem
|
||||
{
|
||||
const ulong HAMMER_FSBUF_VOLUME = 0xC8414D4DC5523031;
|
||||
@@ -53,24 +57,22 @@ namespace DiscImageChef.Filesystems
|
||||
public HAMMER()
|
||||
{
|
||||
Name = "HAMMER Filesystem";
|
||||
PluginUUID = new Guid("91A188BF-5FD7-4677-BBD3-F59EBA9C864D");
|
||||
PluginUuid = new Guid("91A188BF-5FD7-4677-BBD3-F59EBA9C864D");
|
||||
CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public HAMMER(Encoding encoding)
|
||||
{
|
||||
Name = "HAMMER Filesystem";
|
||||
PluginUUID = new Guid("91A188BF-5FD7-4677-BBD3-F59EBA9C864D");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("91A188BF-5FD7-4677-BBD3-F59EBA9C864D");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public HAMMER(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "HAMMER Filesystem";
|
||||
PluginUUID = new Guid("91A188BF-5FD7-4677-BBD3-F59EBA9C864D");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("91A188BF-5FD7-4677-BBD3-F59EBA9C864D");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugin imagePlugin, Partition partition)
|
||||
@@ -83,9 +85,9 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
ulong magic;
|
||||
|
||||
byte[] sb_sector = imagePlugin.ReadSectors(partition.Start, run);
|
||||
byte[] sbSector = imagePlugin.ReadSectors(partition.Start, run);
|
||||
|
||||
magic = BitConverter.ToUInt64(sb_sector, 0);
|
||||
magic = BitConverter.ToUInt64(sbSector, 0);
|
||||
|
||||
return magic == HAMMER_FSBUF_VOLUME || magic == HAMMER_FSBUF_VOLUME_REV;
|
||||
}
|
||||
@@ -97,7 +99,7 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
HammerSuperBlock hammer_sb;
|
||||
HammerSuperBlock hammerSb;
|
||||
|
||||
uint run = HAMMER_VOLHDR_SIZE / imagePlugin.GetSectorSize();
|
||||
|
||||
@@ -105,56 +107,56 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
ulong magic;
|
||||
|
||||
byte[] sb_sector = imagePlugin.ReadSectors(partition.Start, run);
|
||||
byte[] sbSector = imagePlugin.ReadSectors(partition.Start, run);
|
||||
|
||||
magic = BitConverter.ToUInt64(sb_sector, 0);
|
||||
magic = BitConverter.ToUInt64(sbSector, 0);
|
||||
|
||||
if(magic == HAMMER_FSBUF_VOLUME)
|
||||
{
|
||||
GCHandle handle = GCHandle.Alloc(sb_sector, GCHandleType.Pinned);
|
||||
hammer_sb = (HammerSuperBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),
|
||||
GCHandle handle = GCHandle.Alloc(sbSector, GCHandleType.Pinned);
|
||||
hammerSb = (HammerSuperBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),
|
||||
typeof(HammerSuperBlock));
|
||||
handle.Free();
|
||||
}
|
||||
else hammer_sb = BigEndianMarshal.ByteArrayToStructureBigEndian<HammerSuperBlock>(sb_sector);
|
||||
else hammerSb = BigEndianMarshal.ByteArrayToStructureBigEndian<HammerSuperBlock>(sbSector);
|
||||
|
||||
sb.AppendLine("HAMMER filesystem");
|
||||
|
||||
sb.AppendFormat("Volume version: {0}", hammer_sb.vol_version).AppendLine();
|
||||
sb.AppendFormat("Volume {0} of {1} on this filesystem", hammer_sb.vol_no + 1, hammer_sb.vol_count)
|
||||
sb.AppendFormat("Volume version: {0}", hammerSb.vol_version).AppendLine();
|
||||
sb.AppendFormat("Volume {0} of {1} on this filesystem", hammerSb.vol_no + 1, hammerSb.vol_count)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(hammer_sb.vol_label, CurrentEncoding))
|
||||
sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(hammerSb.vol_label, CurrentEncoding))
|
||||
.AppendLine();
|
||||
sb.AppendFormat("Volume serial: {0}", hammer_sb.vol_fsid).AppendLine();
|
||||
sb.AppendFormat("Filesystem type: {0}", hammer_sb.vol_fstype).AppendLine();
|
||||
sb.AppendFormat("Boot area starts at {0}", hammer_sb.vol_bot_beg).AppendLine();
|
||||
sb.AppendFormat("Memory log starts at {0}", hammer_sb.vol_mem_beg).AppendLine();
|
||||
sb.AppendFormat("First volume buffer starts at {0}", hammer_sb.vol_buf_beg).AppendLine();
|
||||
sb.AppendFormat("Volume ends at {0}", hammer_sb.vol_buf_end).AppendLine();
|
||||
sb.AppendFormat("Volume serial: {0}", hammerSb.vol_fsid).AppendLine();
|
||||
sb.AppendFormat("Filesystem type: {0}", hammerSb.vol_fstype).AppendLine();
|
||||
sb.AppendFormat("Boot area starts at {0}", hammerSb.vol_bot_beg).AppendLine();
|
||||
sb.AppendFormat("Memory log starts at {0}", hammerSb.vol_mem_beg).AppendLine();
|
||||
sb.AppendFormat("First volume buffer starts at {0}", hammerSb.vol_buf_beg).AppendLine();
|
||||
sb.AppendFormat("Volume ends at {0}", hammerSb.vol_buf_end).AppendLine();
|
||||
|
||||
xmlFSType = new FileSystemType
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
Clusters = (long)(partition.Size / HAMMER_BIGBLOCK_SIZE),
|
||||
ClusterSize = HAMMER_BIGBLOCK_SIZE,
|
||||
Dirty = false,
|
||||
Type = "HAMMER",
|
||||
VolumeName = StringHandlers.CToString(hammer_sb.vol_label, CurrentEncoding),
|
||||
VolumeSerial = hammer_sb.vol_fsid.ToString()
|
||||
VolumeName = StringHandlers.CToString(hammerSb.vol_label, CurrentEncoding),
|
||||
VolumeSerial = hammerSb.vol_fsid.ToString()
|
||||
};
|
||||
|
||||
if(hammer_sb.vol_no == hammer_sb.vol_rootvol)
|
||||
if(hammerSb.vol_no == hammerSb.vol_rootvol)
|
||||
{
|
||||
sb.AppendFormat("Filesystem contains {0} \"big-blocks\" ({1} bytes)", hammer_sb.vol0_stat_bigblocks,
|
||||
hammer_sb.vol0_stat_bigblocks * HAMMER_BIGBLOCK_SIZE).AppendLine();
|
||||
sb.AppendFormat("Filesystem has {0} \"big-blocks\" free ({1} bytes)", hammer_sb.vol0_stat_freebigblocks,
|
||||
hammer_sb.vol0_stat_freebigblocks * HAMMER_BIGBLOCK_SIZE).AppendLine();
|
||||
sb.AppendFormat("Filesystem has {0} inode used", hammer_sb.vol0_stat_inodes).AppendLine();
|
||||
sb.AppendFormat("Filesystem contains {0} \"big-blocks\" ({1} bytes)", hammerSb.vol0_stat_bigblocks,
|
||||
hammerSb.vol0_stat_bigblocks * HAMMER_BIGBLOCK_SIZE).AppendLine();
|
||||
sb.AppendFormat("Filesystem has {0} \"big-blocks\" free ({1} bytes)", hammerSb.vol0_stat_freebigblocks,
|
||||
hammerSb.vol0_stat_freebigblocks * HAMMER_BIGBLOCK_SIZE).AppendLine();
|
||||
sb.AppendFormat("Filesystem has {0} inode used", hammerSb.vol0_stat_inodes).AppendLine();
|
||||
|
||||
xmlFSType.Clusters = hammer_sb.vol0_stat_bigblocks;
|
||||
xmlFSType.FreeClusters = hammer_sb.vol0_stat_freebigblocks;
|
||||
xmlFSType.FreeClustersSpecified = true;
|
||||
xmlFSType.Files = hammer_sb.vol0_stat_inodes;
|
||||
xmlFSType.FilesSpecified = true;
|
||||
XmlFsType.Clusters = hammerSb.vol0_stat_bigblocks;
|
||||
XmlFsType.FreeClusters = hammerSb.vol0_stat_freebigblocks;
|
||||
XmlFsType.FreeClustersSpecified = true;
|
||||
XmlFsType.Files = hammerSb.vol0_stat_inodes;
|
||||
XmlFsType.FilesSpecified = true;
|
||||
}
|
||||
// 0 ?
|
||||
//sb.AppendFormat("Volume header CRC: 0x{0:X8}", afs_sb.vol_crc).AppendLine();
|
||||
|
||||
@@ -47,24 +47,22 @@ namespace DiscImageChef.Filesystems
|
||||
public HPFS()
|
||||
{
|
||||
Name = "OS/2 High Performance File System";
|
||||
PluginUUID = new Guid("33513B2C-f590-4acb-8bf2-0b1d5e19dec5");
|
||||
PluginUuid = new Guid("33513B2C-f590-4acb-8bf2-0b1d5e19dec5");
|
||||
CurrentEncoding = Encoding.GetEncoding("ibm850");
|
||||
}
|
||||
|
||||
public HPFS(Encoding encoding)
|
||||
{
|
||||
Name = "OS/2 High Performance File System";
|
||||
PluginUUID = new Guid("33513B2C-f590-4acb-8bf2-0b1d5e19dec5");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("ibm850");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("33513B2C-f590-4acb-8bf2-0b1d5e19dec5");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("ibm850");
|
||||
}
|
||||
|
||||
public HPFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "OS/2 High Performance File System";
|
||||
PluginUUID = new Guid("33513B2C-f590-4acb-8bf2-0b1d5e19dec5");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("ibm850");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("33513B2C-f590-4acb-8bf2-0b1d5e19dec5");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("ibm850");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugin imagePlugin, Partition partition)
|
||||
@@ -73,14 +71,12 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
uint magic1, magic2;
|
||||
|
||||
byte[] hpfs_sb_sector =
|
||||
byte[] hpfsSbSector =
|
||||
imagePlugin.ReadSector(16 + partition.Start); // Seek to superblock, on logical sector 16
|
||||
magic1 = BitConverter.ToUInt32(hpfs_sb_sector, 0x000);
|
||||
magic2 = BitConverter.ToUInt32(hpfs_sb_sector, 0x004);
|
||||
magic1 = BitConverter.ToUInt32(hpfsSbSector, 0x000);
|
||||
magic2 = BitConverter.ToUInt32(hpfsSbSector, 0x004);
|
||||
|
||||
if(magic1 == 0xF995E849 && magic2 == 0xFA53E9C5) return true;
|
||||
|
||||
return false;
|
||||
return magic1 == 0xF995E849 && magic2 == 0xFA53E9C5;
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
|
||||
@@ -90,135 +86,130 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
HPFS_BIOSParameterBlock hpfs_bpb;
|
||||
HPFS_SuperBlock hpfs_sb;
|
||||
HPFS_SpareBlock hpfs_sp;
|
||||
|
||||
byte[] hpfs_bpb_sector =
|
||||
byte[] hpfsBpbSector =
|
||||
imagePlugin.ReadSector(0 + partition.Start); // Seek to BIOS parameter block, on logical sector 0
|
||||
byte[] hpfs_sb_sector =
|
||||
byte[] hpfsSbSector =
|
||||
imagePlugin.ReadSector(16 + partition.Start); // Seek to superblock, on logical sector 16
|
||||
byte[] hpfs_sp_sector =
|
||||
byte[] hpfsSpSector =
|
||||
imagePlugin.ReadSector(17 + partition.Start); // Seek to spareblock, on logical sector 17
|
||||
|
||||
IntPtr bpbPtr = Marshal.AllocHGlobal(512);
|
||||
Marshal.Copy(hpfs_bpb_sector, 0, bpbPtr, 512);
|
||||
hpfs_bpb = (HPFS_BIOSParameterBlock)Marshal.PtrToStructure(bpbPtr, typeof(HPFS_BIOSParameterBlock));
|
||||
Marshal.Copy(hpfsBpbSector, 0, bpbPtr, 512);
|
||||
HPFS_BIOSParameterBlock hpfsBpb = (HPFS_BIOSParameterBlock)Marshal.PtrToStructure(bpbPtr, typeof(HPFS_BIOSParameterBlock));
|
||||
Marshal.FreeHGlobal(bpbPtr);
|
||||
|
||||
IntPtr sbPtr = Marshal.AllocHGlobal(512);
|
||||
Marshal.Copy(hpfs_sb_sector, 0, sbPtr, 512);
|
||||
hpfs_sb = (HPFS_SuperBlock)Marshal.PtrToStructure(sbPtr, typeof(HPFS_SuperBlock));
|
||||
Marshal.Copy(hpfsSbSector, 0, sbPtr, 512);
|
||||
HPFS_SuperBlock hpfsSb = (HPFS_SuperBlock)Marshal.PtrToStructure(sbPtr, typeof(HPFS_SuperBlock));
|
||||
Marshal.FreeHGlobal(sbPtr);
|
||||
|
||||
IntPtr spPtr = Marshal.AllocHGlobal(512);
|
||||
Marshal.Copy(hpfs_sp_sector, 0, spPtr, 512);
|
||||
hpfs_sp = (HPFS_SpareBlock)Marshal.PtrToStructure(spPtr, typeof(HPFS_SpareBlock));
|
||||
Marshal.Copy(hpfsSpSector, 0, spPtr, 512);
|
||||
HPFS_SpareBlock hpfsSp = (HPFS_SpareBlock)Marshal.PtrToStructure(spPtr, typeof(HPFS_SpareBlock));
|
||||
Marshal.FreeHGlobal(spPtr);
|
||||
|
||||
if(StringHandlers.CToString(hpfs_bpb.fs_type) != "HPFS " || hpfs_sb.magic1 != 0xF995E849 ||
|
||||
hpfs_sb.magic2 != 0xFA53E9C5 || hpfs_sp.magic1 != 0xF9911849 || hpfs_sp.magic2 != 0xFA5229C5)
|
||||
if(StringHandlers.CToString(hpfsBpb.fs_type) != "HPFS " || hpfsSb.magic1 != 0xF995E849 ||
|
||||
hpfsSb.magic2 != 0xFA53E9C5 || hpfsSp.magic1 != 0xF9911849 || hpfsSp.magic2 != 0xFA5229C5)
|
||||
{
|
||||
sb.AppendLine("This may not be HPFS, following information may be not correct.");
|
||||
sb.AppendFormat("File system type: \"{0}\" (Should be \"HPFS \")", hpfs_bpb.fs_type).AppendLine();
|
||||
sb.AppendFormat("Superblock magic1: 0x{0:X8} (Should be 0xF995E849)", hpfs_sb.magic1).AppendLine();
|
||||
sb.AppendFormat("Superblock magic2: 0x{0:X8} (Should be 0xFA53E9C5)", hpfs_sb.magic2).AppendLine();
|
||||
sb.AppendFormat("Spareblock magic1: 0x{0:X8} (Should be 0xF9911849)", hpfs_sp.magic1).AppendLine();
|
||||
sb.AppendFormat("Spareblock magic2: 0x{0:X8} (Should be 0xFA5229C5)", hpfs_sp.magic2).AppendLine();
|
||||
sb.AppendFormat("File system type: \"{0}\" (Should be \"HPFS \")", hpfsBpb.fs_type).AppendLine();
|
||||
sb.AppendFormat("Superblock magic1: 0x{0:X8} (Should be 0xF995E849)", hpfsSb.magic1).AppendLine();
|
||||
sb.AppendFormat("Superblock magic2: 0x{0:X8} (Should be 0xFA53E9C5)", hpfsSb.magic2).AppendLine();
|
||||
sb.AppendFormat("Spareblock magic1: 0x{0:X8} (Should be 0xF9911849)", hpfsSp.magic1).AppendLine();
|
||||
sb.AppendFormat("Spareblock magic2: 0x{0:X8} (Should be 0xFA5229C5)", hpfsSp.magic2).AppendLine();
|
||||
}
|
||||
|
||||
sb.AppendFormat("OEM name: {0}", StringHandlers.CToString(hpfs_bpb.oem_name)).AppendLine();
|
||||
sb.AppendFormat("{0} bytes per sector", hpfs_bpb.bps).AppendLine();
|
||||
sb.AppendFormat("OEM name: {0}", StringHandlers.CToString(hpfsBpb.oem_name)).AppendLine();
|
||||
sb.AppendFormat("{0} bytes per sector", hpfsBpb.bps).AppendLine();
|
||||
// sb.AppendFormat("{0} sectors per cluster", hpfs_bpb.spc).AppendLine();
|
||||
// sb.AppendFormat("{0} reserved sectors", hpfs_bpb.rsectors).AppendLine();
|
||||
// sb.AppendFormat("{0} FATs", hpfs_bpb.fats_no).AppendLine();
|
||||
// sb.AppendFormat("{0} entries on root directory", hpfs_bpb.root_ent).AppendLine();
|
||||
// sb.AppendFormat("{0} mini sectors on volume", hpfs_bpb.sectors).AppendLine();
|
||||
sb.AppendFormat("Media descriptor: 0x{0:X2}", hpfs_bpb.media).AppendLine();
|
||||
sb.AppendFormat("Media descriptor: 0x{0:X2}", hpfsBpb.media).AppendLine();
|
||||
// sb.AppendFormat("{0} sectors per FAT", hpfs_bpb.spfat).AppendLine();
|
||||
// sb.AppendFormat("{0} sectors per track", hpfs_bpb.sptrk).AppendLine();
|
||||
// sb.AppendFormat("{0} heads", hpfs_bpb.heads).AppendLine();
|
||||
sb.AppendFormat("{0} sectors hidden before BPB", hpfs_bpb.hsectors).AppendLine();
|
||||
sb.AppendFormat("{0} sectors on volume ({1} bytes)", hpfs_sb.sectors, hpfs_sb.sectors * hpfs_bpb.bps)
|
||||
sb.AppendFormat("{0} sectors hidden before BPB", hpfsBpb.hsectors).AppendLine();
|
||||
sb.AppendFormat("{0} sectors on volume ({1} bytes)", hpfsSb.sectors, hpfsSb.sectors * hpfsBpb.bps)
|
||||
.AppendLine();
|
||||
// sb.AppendFormat("{0} sectors on volume ({1} bytes)", hpfs_bpb.big_sectors, hpfs_bpb.big_sectors * hpfs_bpb.bps).AppendLine();
|
||||
sb.AppendFormat("BIOS Drive Number: 0x{0:X2}", hpfs_bpb.drive_no).AppendLine();
|
||||
sb.AppendFormat("NT Flags: 0x{0:X2}", hpfs_bpb.nt_flags).AppendLine();
|
||||
sb.AppendFormat("Signature: 0x{0:X2}", hpfs_bpb.signature).AppendLine();
|
||||
sb.AppendFormat("Serial number: 0x{0:X8}", hpfs_bpb.serial_no).AppendLine();
|
||||
sb.AppendFormat("Volume label: {0}", StringHandlers.CToString(hpfs_bpb.volume_label, CurrentEncoding))
|
||||
sb.AppendFormat("BIOS Drive Number: 0x{0:X2}", hpfsBpb.drive_no).AppendLine();
|
||||
sb.AppendFormat("NT Flags: 0x{0:X2}", hpfsBpb.nt_flags).AppendLine();
|
||||
sb.AppendFormat("Signature: 0x{0:X2}", hpfsBpb.signature).AppendLine();
|
||||
sb.AppendFormat("Serial number: 0x{0:X8}", hpfsBpb.serial_no).AppendLine();
|
||||
sb.AppendFormat("Volume label: {0}", StringHandlers.CToString(hpfsBpb.volume_label, CurrentEncoding))
|
||||
.AppendLine();
|
||||
// sb.AppendFormat("Filesystem type: \"{0}\"", hpfs_bpb.fs_type).AppendLine();
|
||||
|
||||
DateTime last_chk = DateHandlers.UNIXToDateTime(hpfs_sb.last_chkdsk);
|
||||
DateTime last_optim = DateHandlers.UNIXToDateTime(hpfs_sb.last_optim);
|
||||
DateTime lastChk = DateHandlers.UNIXToDateTime(hpfsSb.last_chkdsk);
|
||||
DateTime lastOptim = DateHandlers.UNIXToDateTime(hpfsSb.last_optim);
|
||||
|
||||
sb.AppendFormat("HPFS version: {0}", hpfs_sb.version).AppendLine();
|
||||
sb.AppendFormat("Functional version: {0}", hpfs_sb.func_version).AppendLine();
|
||||
sb.AppendFormat("Sector of root directory FNode: {0}", hpfs_sb.root_fnode).AppendLine();
|
||||
sb.AppendFormat("{0} sectors are marked bad", hpfs_sb.badblocks).AppendLine();
|
||||
sb.AppendFormat("Sector of free space bitmaps: {0}", hpfs_sb.bitmap_lsn).AppendLine();
|
||||
sb.AppendFormat("Sector of bad blocks list: {0}", hpfs_sb.badblock_lsn).AppendLine();
|
||||
if(hpfs_sb.last_chkdsk > 0) sb.AppendFormat("Date of last integrity check: {0}", last_chk).AppendLine();
|
||||
sb.AppendFormat("HPFS version: {0}", hpfsSb.version).AppendLine();
|
||||
sb.AppendFormat("Functional version: {0}", hpfsSb.func_version).AppendLine();
|
||||
sb.AppendFormat("Sector of root directory FNode: {0}", hpfsSb.root_fnode).AppendLine();
|
||||
sb.AppendFormat("{0} sectors are marked bad", hpfsSb.badblocks).AppendLine();
|
||||
sb.AppendFormat("Sector of free space bitmaps: {0}", hpfsSb.bitmap_lsn).AppendLine();
|
||||
sb.AppendFormat("Sector of bad blocks list: {0}", hpfsSb.badblock_lsn).AppendLine();
|
||||
if(hpfsSb.last_chkdsk > 0) sb.AppendFormat("Date of last integrity check: {0}", lastChk).AppendLine();
|
||||
else sb.AppendLine("Filesystem integrity has never been checked");
|
||||
if(hpfs_sb.last_optim > 0) sb.AppendFormat("Date of last optimization {0}", last_optim).AppendLine();
|
||||
if(hpfsSb.last_optim > 0) sb.AppendFormat("Date of last optimization {0}", lastOptim).AppendLine();
|
||||
else sb.AppendLine("Filesystem has never been optimized");
|
||||
sb.AppendFormat("Directory band has {0} sectors", hpfs_sb.dband_sectors).AppendLine();
|
||||
sb.AppendFormat("Directory band starts at sector {0}", hpfs_sb.dband_start).AppendLine();
|
||||
sb.AppendFormat("Directory band ends at sector {0}", hpfs_sb.dband_last).AppendLine();
|
||||
sb.AppendFormat("Sector of directory band bitmap: {0}", hpfs_sb.dband_bitmap).AppendLine();
|
||||
sb.AppendFormat("Sector of ACL directory: {0}", hpfs_sb.acl_start).AppendLine();
|
||||
sb.AppendFormat("Directory band has {0} sectors", hpfsSb.dband_sectors).AppendLine();
|
||||
sb.AppendFormat("Directory band starts at sector {0}", hpfsSb.dband_start).AppendLine();
|
||||
sb.AppendFormat("Directory band ends at sector {0}", hpfsSb.dband_last).AppendLine();
|
||||
sb.AppendFormat("Sector of directory band bitmap: {0}", hpfsSb.dband_bitmap).AppendLine();
|
||||
sb.AppendFormat("Sector of ACL directory: {0}", hpfsSb.acl_start).AppendLine();
|
||||
|
||||
sb.AppendFormat("Sector of Hotfix directory: {0}", hpfs_sp.hotfix_start).AppendLine();
|
||||
sb.AppendFormat("{0} used Hotfix entries", hpfs_sp.hotfix_used).AppendLine();
|
||||
sb.AppendFormat("{0} total Hotfix entries", hpfs_sp.hotfix_entries).AppendLine();
|
||||
sb.AppendFormat("{0} free spare DNodes", hpfs_sp.spare_dnodes_free).AppendLine();
|
||||
sb.AppendFormat("{0} total spare DNodes", hpfs_sp.spare_dnodes).AppendLine();
|
||||
sb.AppendFormat("Sector of codepage directory: {0}", hpfs_sp.codepage_lsn).AppendLine();
|
||||
sb.AppendFormat("{0} codepages used in the volume", hpfs_sp.codepages).AppendLine();
|
||||
sb.AppendFormat("SuperBlock CRC32: {0:X8}", hpfs_sp.sb_crc32).AppendLine();
|
||||
sb.AppendFormat("SpareBlock CRC32: {0:X8}", hpfs_sp.sp_crc32).AppendLine();
|
||||
sb.AppendFormat("Sector of Hotfix directory: {0}", hpfsSp.hotfix_start).AppendLine();
|
||||
sb.AppendFormat("{0} used Hotfix entries", hpfsSp.hotfix_used).AppendLine();
|
||||
sb.AppendFormat("{0} total Hotfix entries", hpfsSp.hotfix_entries).AppendLine();
|
||||
sb.AppendFormat("{0} free spare DNodes", hpfsSp.spare_dnodes_free).AppendLine();
|
||||
sb.AppendFormat("{0} total spare DNodes", hpfsSp.spare_dnodes).AppendLine();
|
||||
sb.AppendFormat("Sector of codepage directory: {0}", hpfsSp.codepage_lsn).AppendLine();
|
||||
sb.AppendFormat("{0} codepages used in the volume", hpfsSp.codepages).AppendLine();
|
||||
sb.AppendFormat("SuperBlock CRC32: {0:X8}", hpfsSp.sb_crc32).AppendLine();
|
||||
sb.AppendFormat("SpareBlock CRC32: {0:X8}", hpfsSp.sp_crc32).AppendLine();
|
||||
|
||||
sb.AppendLine("Flags:");
|
||||
if((hpfs_sp.flags1 & 0x01) == 0x01) sb.AppendLine("Filesystem is dirty.");
|
||||
else sb.AppendLine("Filesystem is clean.");
|
||||
if((hpfs_sp.flags1 & 0x02) == 0x02) sb.AppendLine("Spare directory blocks are in use");
|
||||
if((hpfs_sp.flags1 & 0x04) == 0x04) sb.AppendLine("Hotfixes are in use");
|
||||
if((hpfs_sp.flags1 & 0x08) == 0x08) sb.AppendLine("Disk contains bad sectors");
|
||||
if((hpfs_sp.flags1 & 0x10) == 0x10) sb.AppendLine("Disk has a bad bitmap");
|
||||
if((hpfs_sp.flags1 & 0x20) == 0x20) sb.AppendLine("Filesystem was formatted fast");
|
||||
if((hpfs_sp.flags1 & 0x40) == 0x40) sb.AppendLine("Unknown flag 0x40 on flags1 is active");
|
||||
if((hpfs_sp.flags1 & 0x80) == 0x80) sb.AppendLine("Filesystem has been mounted by an old IFS");
|
||||
if((hpfs_sp.flags2 & 0x01) == 0x01) sb.AppendLine("Install DASD limits");
|
||||
if((hpfs_sp.flags2 & 0x02) == 0x02) sb.AppendLine("Resync DASD limits");
|
||||
if((hpfs_sp.flags2 & 0x04) == 0x04) sb.AppendLine("DASD limits are operational");
|
||||
if((hpfs_sp.flags2 & 0x08) == 0x08) sb.AppendLine("Multimedia is active");
|
||||
if((hpfs_sp.flags2 & 0x10) == 0x10) sb.AppendLine("DCE ACLs are active");
|
||||
if((hpfs_sp.flags2 & 0x20) == 0x20) sb.AppendLine("DASD limits are dirty");
|
||||
if((hpfs_sp.flags2 & 0x40) == 0x40) sb.AppendLine("Unknown flag 0x40 on flags2 is active");
|
||||
if((hpfs_sp.flags2 & 0x80) == 0x80) sb.AppendLine("Unknown flag 0x80 on flags2 is active");
|
||||
sb.AppendLine((hpfsSp.flags1 & 0x01) == 0x01 ? "Filesystem is dirty." : "Filesystem is clean.");
|
||||
if((hpfsSp.flags1 & 0x02) == 0x02) sb.AppendLine("Spare directory blocks are in use");
|
||||
if((hpfsSp.flags1 & 0x04) == 0x04) sb.AppendLine("Hotfixes are in use");
|
||||
if((hpfsSp.flags1 & 0x08) == 0x08) sb.AppendLine("Disk contains bad sectors");
|
||||
if((hpfsSp.flags1 & 0x10) == 0x10) sb.AppendLine("Disk has a bad bitmap");
|
||||
if((hpfsSp.flags1 & 0x20) == 0x20) sb.AppendLine("Filesystem was formatted fast");
|
||||
if((hpfsSp.flags1 & 0x40) == 0x40) sb.AppendLine("Unknown flag 0x40 on flags1 is active");
|
||||
if((hpfsSp.flags1 & 0x80) == 0x80) sb.AppendLine("Filesystem has been mounted by an old IFS");
|
||||
if((hpfsSp.flags2 & 0x01) == 0x01) sb.AppendLine("Install DASD limits");
|
||||
if((hpfsSp.flags2 & 0x02) == 0x02) sb.AppendLine("Resync DASD limits");
|
||||
if((hpfsSp.flags2 & 0x04) == 0x04) sb.AppendLine("DASD limits are operational");
|
||||
if((hpfsSp.flags2 & 0x08) == 0x08) sb.AppendLine("Multimedia is active");
|
||||
if((hpfsSp.flags2 & 0x10) == 0x10) sb.AppendLine("DCE ACLs are active");
|
||||
if((hpfsSp.flags2 & 0x20) == 0x20) sb.AppendLine("DASD limits are dirty");
|
||||
if((hpfsSp.flags2 & 0x40) == 0x40) sb.AppendLine("Unknown flag 0x40 on flags2 is active");
|
||||
if((hpfsSp.flags2 & 0x80) == 0x80) sb.AppendLine("Unknown flag 0x80 on flags2 is active");
|
||||
|
||||
xmlFSType = new FileSystemType();
|
||||
XmlFsType = new FileSystemType();
|
||||
|
||||
// Theoretically everything from BPB to SB is boot code, should I hash everything or only the sector loaded by BIOS itself?
|
||||
if(hpfs_bpb.jump[0] == 0xEB && hpfs_bpb.jump[1] > 0x3C && hpfs_bpb.jump[1] < 0x80 &&
|
||||
hpfs_bpb.signature2 == 0xAA55)
|
||||
if(hpfsBpb.jump[0] == 0xEB && hpfsBpb.jump[1] > 0x3C && hpfsBpb.jump[1] < 0x80 &&
|
||||
hpfsBpb.signature2 == 0xAA55)
|
||||
{
|
||||
xmlFSType.Bootable = true;
|
||||
XmlFsType.Bootable = true;
|
||||
Sha1Context sha1Ctx = new Sha1Context();
|
||||
sha1Ctx.Init();
|
||||
string bootChk = sha1Ctx.Data(hpfs_bpb.boot_code, out byte[] sha1_out);
|
||||
string bootChk = sha1Ctx.Data(hpfsBpb.boot_code, out byte[] sha1_out);
|
||||
sb.AppendLine("Volume is bootable");
|
||||
sb.AppendFormat("Boot code's SHA1: {0}", bootChk).AppendLine();
|
||||
}
|
||||
|
||||
xmlFSType.Dirty |= (hpfs_sp.flags1 & 0x01) == 0x01;
|
||||
xmlFSType.Clusters = hpfs_sb.sectors;
|
||||
xmlFSType.ClusterSize = hpfs_bpb.bps;
|
||||
xmlFSType.Type = "HPFS";
|
||||
xmlFSType.VolumeName = StringHandlers.CToString(hpfs_bpb.volume_label, CurrentEncoding);
|
||||
xmlFSType.VolumeSerial = $"{hpfs_bpb.serial_no:X8}";
|
||||
xmlFSType.SystemIdentifier = StringHandlers.CToString(hpfs_bpb.oem_name);
|
||||
XmlFsType.Dirty |= (hpfsSp.flags1 & 0x01) == 0x01;
|
||||
XmlFsType.Clusters = hpfsSb.sectors;
|
||||
XmlFsType.ClusterSize = hpfsBpb.bps;
|
||||
XmlFsType.Type = "HPFS";
|
||||
XmlFsType.VolumeName = StringHandlers.CToString(hpfsBpb.volume_label, CurrentEncoding);
|
||||
XmlFsType.VolumeSerial = $"{hpfsBpb.serial_no:X8}";
|
||||
XmlFsType.SystemIdentifier = StringHandlers.CToString(hpfsBpb.oem_name);
|
||||
|
||||
information = sb.ToString();
|
||||
}
|
||||
|
||||
@@ -43,21 +43,21 @@ namespace DiscImageChef.Filesystems.ISO9660
|
||||
public ISO9660()
|
||||
{
|
||||
Name = "ISO9660 Filesystem";
|
||||
PluginUUID = new Guid("d812f4d3-c357-400d-90fd-3b22ef786aa8");
|
||||
PluginUuid = new Guid("d812f4d3-c357-400d-90fd-3b22ef786aa8");
|
||||
CurrentEncoding = Encoding.ASCII;
|
||||
}
|
||||
|
||||
public ISO9660(Encoding encoding)
|
||||
{
|
||||
Name = "ISO9660 Filesystem";
|
||||
PluginUUID = new Guid("d812f4d3-c357-400d-90fd-3b22ef786aa8");
|
||||
PluginUuid = new Guid("d812f4d3-c357-400d-90fd-3b22ef786aa8");
|
||||
CurrentEncoding = encoding ?? Encoding.ASCII;
|
||||
}
|
||||
|
||||
public ISO9660(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "ISO9660 Filesystem";
|
||||
PluginUUID = new Guid("d812f4d3-c357-400d-90fd-3b22ef786aa8");
|
||||
PluginUuid = new Guid("d812f4d3-c357-400d-90fd-3b22ef786aa8");
|
||||
CurrentEncoding = encoding ?? Encoding.ASCII;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,7 +213,7 @@ namespace DiscImageChef.Filesystems.ISO9660
|
||||
DecodedVolumeDescriptor decodedVd;
|
||||
DecodedVolumeDescriptor decodedJolietVd = new DecodedVolumeDescriptor();
|
||||
|
||||
xmlFSType = new FileSystemType();
|
||||
XmlFsType = new FileSystemType();
|
||||
|
||||
if(pvd == null && hsvd == null && fsvd == null)
|
||||
{
|
||||
@@ -716,85 +716,85 @@ namespace DiscImageChef.Filesystems.ISO9660
|
||||
exit_torito:
|
||||
if(refareas.Count > 0) isoMetadata.Append(suspInformation);
|
||||
|
||||
xmlFSType.Type = fsFormat;
|
||||
XmlFsType.Type = fsFormat;
|
||||
|
||||
if(jolietvd != null)
|
||||
{
|
||||
xmlFSType.VolumeName = decodedJolietVd.VolumeIdentifier;
|
||||
XmlFsType.VolumeName = decodedJolietVd.VolumeIdentifier;
|
||||
|
||||
if(decodedJolietVd.SystemIdentifier == null ||
|
||||
decodedVd.SystemIdentifier.Length > decodedJolietVd.SystemIdentifier.Length)
|
||||
xmlFSType.SystemIdentifier = decodedVd.SystemIdentifier;
|
||||
else xmlFSType.SystemIdentifier = decodedJolietVd.SystemIdentifier;
|
||||
XmlFsType.SystemIdentifier = decodedVd.SystemIdentifier;
|
||||
else XmlFsType.SystemIdentifier = decodedJolietVd.SystemIdentifier;
|
||||
|
||||
if(decodedJolietVd.VolumeSetIdentifier == null || decodedVd.VolumeSetIdentifier.Length >
|
||||
decodedJolietVd.VolumeSetIdentifier.Length)
|
||||
xmlFSType.VolumeSetIdentifier = decodedVd.VolumeSetIdentifier;
|
||||
else xmlFSType.VolumeSetIdentifier = decodedJolietVd.VolumeSetIdentifier;
|
||||
XmlFsType.VolumeSetIdentifier = decodedVd.VolumeSetIdentifier;
|
||||
else XmlFsType.VolumeSetIdentifier = decodedJolietVd.VolumeSetIdentifier;
|
||||
|
||||
if(decodedJolietVd.PublisherIdentifier == null || decodedVd.PublisherIdentifier.Length >
|
||||
decodedJolietVd.PublisherIdentifier.Length)
|
||||
xmlFSType.PublisherIdentifier = decodedVd.PublisherIdentifier;
|
||||
else xmlFSType.PublisherIdentifier = decodedJolietVd.PublisherIdentifier;
|
||||
XmlFsType.PublisherIdentifier = decodedVd.PublisherIdentifier;
|
||||
else XmlFsType.PublisherIdentifier = decodedJolietVd.PublisherIdentifier;
|
||||
|
||||
if(decodedJolietVd.DataPreparerIdentifier == null || decodedVd.DataPreparerIdentifier.Length >
|
||||
decodedJolietVd.DataPreparerIdentifier.Length)
|
||||
xmlFSType.DataPreparerIdentifier = decodedVd.DataPreparerIdentifier;
|
||||
else xmlFSType.DataPreparerIdentifier = decodedJolietVd.SystemIdentifier;
|
||||
XmlFsType.DataPreparerIdentifier = decodedVd.DataPreparerIdentifier;
|
||||
else XmlFsType.DataPreparerIdentifier = decodedJolietVd.SystemIdentifier;
|
||||
|
||||
if(decodedJolietVd.ApplicationIdentifier == null || decodedVd.ApplicationIdentifier.Length >
|
||||
decodedJolietVd.ApplicationIdentifier.Length)
|
||||
xmlFSType.ApplicationIdentifier = decodedVd.ApplicationIdentifier;
|
||||
else xmlFSType.ApplicationIdentifier = decodedJolietVd.SystemIdentifier;
|
||||
XmlFsType.ApplicationIdentifier = decodedVd.ApplicationIdentifier;
|
||||
else XmlFsType.ApplicationIdentifier = decodedJolietVd.SystemIdentifier;
|
||||
|
||||
xmlFSType.CreationDate = decodedJolietVd.CreationTime;
|
||||
xmlFSType.CreationDateSpecified = true;
|
||||
XmlFsType.CreationDate = decodedJolietVd.CreationTime;
|
||||
XmlFsType.CreationDateSpecified = true;
|
||||
if(decodedJolietVd.HasModificationTime)
|
||||
{
|
||||
xmlFSType.ModificationDate = decodedJolietVd.ModificationTime;
|
||||
xmlFSType.ModificationDateSpecified = true;
|
||||
XmlFsType.ModificationDate = decodedJolietVd.ModificationTime;
|
||||
XmlFsType.ModificationDateSpecified = true;
|
||||
}
|
||||
if(decodedJolietVd.HasExpirationTime)
|
||||
{
|
||||
xmlFSType.ExpirationDate = decodedJolietVd.ExpirationTime;
|
||||
xmlFSType.ExpirationDateSpecified = true;
|
||||
XmlFsType.ExpirationDate = decodedJolietVd.ExpirationTime;
|
||||
XmlFsType.ExpirationDateSpecified = true;
|
||||
}
|
||||
if(decodedJolietVd.HasEffectiveTime)
|
||||
{
|
||||
xmlFSType.EffectiveDate = decodedJolietVd.EffectiveTime;
|
||||
xmlFSType.EffectiveDateSpecified = true;
|
||||
XmlFsType.EffectiveDate = decodedJolietVd.EffectiveTime;
|
||||
XmlFsType.EffectiveDateSpecified = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
xmlFSType.SystemIdentifier = decodedVd.SystemIdentifier;
|
||||
xmlFSType.VolumeName = decodedVd.VolumeIdentifier;
|
||||
xmlFSType.VolumeSetIdentifier = decodedVd.VolumeSetIdentifier;
|
||||
xmlFSType.PublisherIdentifier = decodedVd.PublisherIdentifier;
|
||||
xmlFSType.DataPreparerIdentifier = decodedVd.DataPreparerIdentifier;
|
||||
xmlFSType.ApplicationIdentifier = decodedVd.ApplicationIdentifier;
|
||||
xmlFSType.CreationDate = decodedVd.CreationTime;
|
||||
xmlFSType.CreationDateSpecified = true;
|
||||
XmlFsType.SystemIdentifier = decodedVd.SystemIdentifier;
|
||||
XmlFsType.VolumeName = decodedVd.VolumeIdentifier;
|
||||
XmlFsType.VolumeSetIdentifier = decodedVd.VolumeSetIdentifier;
|
||||
XmlFsType.PublisherIdentifier = decodedVd.PublisherIdentifier;
|
||||
XmlFsType.DataPreparerIdentifier = decodedVd.DataPreparerIdentifier;
|
||||
XmlFsType.ApplicationIdentifier = decodedVd.ApplicationIdentifier;
|
||||
XmlFsType.CreationDate = decodedVd.CreationTime;
|
||||
XmlFsType.CreationDateSpecified = true;
|
||||
if(decodedVd.HasModificationTime)
|
||||
{
|
||||
xmlFSType.ModificationDate = decodedVd.ModificationTime;
|
||||
xmlFSType.ModificationDateSpecified = true;
|
||||
XmlFsType.ModificationDate = decodedVd.ModificationTime;
|
||||
XmlFsType.ModificationDateSpecified = true;
|
||||
}
|
||||
if(decodedVd.HasExpirationTime)
|
||||
{
|
||||
xmlFSType.ExpirationDate = decodedVd.ExpirationTime;
|
||||
xmlFSType.ExpirationDateSpecified = true;
|
||||
XmlFsType.ExpirationDate = decodedVd.ExpirationTime;
|
||||
XmlFsType.ExpirationDateSpecified = true;
|
||||
}
|
||||
if(decodedVd.HasEffectiveTime)
|
||||
{
|
||||
xmlFSType.EffectiveDate = decodedVd.EffectiveTime;
|
||||
xmlFSType.EffectiveDateSpecified = true;
|
||||
XmlFsType.EffectiveDate = decodedVd.EffectiveTime;
|
||||
XmlFsType.EffectiveDateSpecified = true;
|
||||
}
|
||||
}
|
||||
|
||||
xmlFSType.Bootable |= bvd != null || segaCd != null || saturn != null || dreamcast != null;
|
||||
xmlFSType.Clusters = decodedVd.Blocks;
|
||||
xmlFSType.ClusterSize = decodedVd.BlockSize;
|
||||
XmlFsType.Bootable |= bvd != null || segaCd != null || saturn != null || dreamcast != null;
|
||||
XmlFsType.Clusters = decodedVd.Blocks;
|
||||
XmlFsType.ClusterSize = decodedVd.BlockSize;
|
||||
|
||||
information = isoMetadata.ToString();
|
||||
}
|
||||
|
||||
@@ -131,35 +131,33 @@ namespace DiscImageChef.Filesystems
|
||||
public Guid s_loguuid;
|
||||
}
|
||||
|
||||
const uint JFS_BootBlocksSize = 0x8000;
|
||||
const uint JFS_Magic = 0x3153464A;
|
||||
const uint JFS_BOOT_BLOCKS_SIZE = 0x8000;
|
||||
const uint JFS_MAGIC = 0x3153464A;
|
||||
|
||||
public JFS()
|
||||
{
|
||||
Name = "JFS Plugin";
|
||||
PluginUUID = new Guid("D3BE2A41-8F28-4055-94DC-BB6C72A0E9C4");
|
||||
PluginUuid = new Guid("D3BE2A41-8F28-4055-94DC-BB6C72A0E9C4");
|
||||
CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public JFS(Encoding encoding)
|
||||
{
|
||||
Name = "JFS Plugin";
|
||||
PluginUUID = new Guid("D3BE2A41-8F28-4055-94DC-BB6C72A0E9C4");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("D3BE2A41-8F28-4055-94DC-BB6C72A0E9C4");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public JFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "JFS Plugin";
|
||||
PluginUUID = new Guid("D3BE2A41-8F28-4055-94DC-BB6C72A0E9C4");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("D3BE2A41-8F28-4055-94DC-BB6C72A0E9C4");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugin imagePlugin, Partition partition)
|
||||
{
|
||||
uint bootSectors = JFS_BootBlocksSize / imagePlugin.GetSectorSize();
|
||||
uint bootSectors = JFS_BOOT_BLOCKS_SIZE / imagePlugin.GetSectorSize();
|
||||
if(partition.Start + bootSectors >= partition.End) return false;
|
||||
|
||||
byte[] sector = imagePlugin.ReadSector(partition.Start + bootSectors);
|
||||
@@ -171,7 +169,7 @@ namespace DiscImageChef.Filesystems
|
||||
jfsSb = (JFS_SuperBlock)Marshal.PtrToStructure(sbPtr, typeof(JFS_SuperBlock));
|
||||
Marshal.FreeHGlobal(sbPtr);
|
||||
|
||||
return jfsSb.s_magic == JFS_Magic;
|
||||
return jfsSb.s_magic == JFS_MAGIC;
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
|
||||
@@ -179,7 +177,7 @@ namespace DiscImageChef.Filesystems
|
||||
{
|
||||
information = "";
|
||||
StringBuilder sb = new StringBuilder();
|
||||
uint bootSectors = JFS_BootBlocksSize / imagePlugin.GetSectorSize();
|
||||
uint bootSectors = JFS_BOOT_BLOCKS_SIZE / imagePlugin.GetSectorSize();
|
||||
byte[] sector = imagePlugin.ReadSector(partition.Start + bootSectors);
|
||||
if(sector.Length < 512) return;
|
||||
|
||||
@@ -228,17 +226,18 @@ namespace DiscImageChef.Filesystems
|
||||
else sb.AppendFormat("Volume name: {0}", CurrentEncoding.GetString(jfsSb.s_label)).AppendLine();
|
||||
sb.AppendFormat("Volume UUID: {0}", jfsSb.s_uuid).AppendLine();
|
||||
|
||||
xmlFSType = new FileSystemType();
|
||||
xmlFSType.Type = "JFS filesystem";
|
||||
xmlFSType.Clusters = (long)jfsSb.s_size;
|
||||
xmlFSType.ClusterSize = (int)jfsSb.s_bsize;
|
||||
xmlFSType.Bootable = true;
|
||||
if(jfsSb.s_version == 1) xmlFSType.VolumeName = CurrentEncoding.GetString(jfsSb.s_fpack);
|
||||
else xmlFSType.VolumeName = CurrentEncoding.GetString(jfsSb.s_label);
|
||||
xmlFSType.VolumeSerial = $"{jfsSb.s_uuid}";
|
||||
xmlFSType.ModificationDate = DateHandlers.UNIXUnsignedToDateTime(jfsSb.s_time.tv_sec, jfsSb.s_time.tv_nsec);
|
||||
xmlFSType.ModificationDateSpecified = true;
|
||||
if(jfsSb.s_state != 0) xmlFSType.Dirty = true;
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
Type = "JFS filesystem",
|
||||
Clusters = (long)jfsSb.s_size,
|
||||
ClusterSize = (int)jfsSb.s_bsize,
|
||||
Bootable = true,
|
||||
VolumeName = CurrentEncoding.GetString(jfsSb.s_version == 1 ? jfsSb.s_fpack : jfsSb.s_label),
|
||||
VolumeSerial = $"{jfsSb.s_uuid}",
|
||||
ModificationDate = DateHandlers.UNIXUnsignedToDateTime(jfsSb.s_time.tv_sec, jfsSb.s_time.tv_nsec),
|
||||
ModificationDateSpecified = true
|
||||
};
|
||||
if(jfsSb.s_state != 0) XmlFsType.Dirty = true;
|
||||
|
||||
information = sb.ToString();
|
||||
}
|
||||
|
||||
@@ -61,42 +61,38 @@ namespace DiscImageChef.Filesystems
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] public byte[] creationDate;
|
||||
}
|
||||
|
||||
const uint LIF_Magic = 0x8000;
|
||||
const uint LIF_MAGIC = 0x8000;
|
||||
|
||||
public LIF()
|
||||
{
|
||||
Name = "HP Logical Interchange Format Plugin";
|
||||
PluginUUID = new Guid("41535647-77A5-477B-9206-DA727ACDC704");
|
||||
PluginUuid = new Guid("41535647-77A5-477B-9206-DA727ACDC704");
|
||||
CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public LIF(Encoding encoding)
|
||||
{
|
||||
Name = "HP Logical Interchange Format Plugin";
|
||||
PluginUUID = new Guid("41535647-77A5-477B-9206-DA727ACDC704");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("41535647-77A5-477B-9206-DA727ACDC704");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public LIF(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "HP Logical Interchange Format Plugin";
|
||||
PluginUUID = new Guid("41535647-77A5-477B-9206-DA727ACDC704");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("41535647-77A5-477B-9206-DA727ACDC704");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugin imagePlugin, Partition partition)
|
||||
{
|
||||
if(imagePlugin.GetSectorSize() < 256) return false;
|
||||
|
||||
LIF_SystemBlock LIFSb;
|
||||
|
||||
byte[] sector = imagePlugin.ReadSector(partition.Start);
|
||||
LIFSb = BigEndianMarshal.ByteArrayToStructureBigEndian<LIF_SystemBlock>(sector);
|
||||
DicConsole.DebugWriteLine("LIF plugin", "magic 0x{0:X8} (expected 0x{1:X8})", LIFSb.magic, LIF_Magic);
|
||||
LIF_SystemBlock lifSb = BigEndianMarshal.ByteArrayToStructureBigEndian<LIF_SystemBlock>(sector);
|
||||
DicConsole.DebugWriteLine("LIF plugin", "magic 0x{0:X8} (expected 0x{1:X8})", lifSb.magic, LIF_MAGIC);
|
||||
|
||||
return LIFSb.magic == LIF_Magic;
|
||||
return lifSb.magic == LIF_MAGIC;
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
|
||||
@@ -106,38 +102,36 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
if(imagePlugin.GetSectorSize() < 256) return;
|
||||
|
||||
LIF_SystemBlock LIFSb;
|
||||
|
||||
byte[] sector = imagePlugin.ReadSector(partition.Start);
|
||||
LIFSb = BigEndianMarshal.ByteArrayToStructureBigEndian<LIF_SystemBlock>(sector);
|
||||
LIF_SystemBlock lifSb = BigEndianMarshal.ByteArrayToStructureBigEndian<LIF_SystemBlock>(sector);
|
||||
|
||||
if(LIFSb.magic != LIF_Magic) return;
|
||||
if(lifSb.magic != LIF_MAGIC) return;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("HP Logical Interchange Format");
|
||||
sb.AppendFormat("Directory starts at cluster {0}", LIFSb.directoryStart).AppendLine();
|
||||
sb.AppendFormat("LIF identifier: {0}", LIFSb.lifId).AppendLine();
|
||||
sb.AppendFormat("Directory size: {0} clusters", LIFSb.directorySize).AppendLine();
|
||||
sb.AppendFormat("LIF version: {0}", LIFSb.lifVersion).AppendLine();
|
||||
sb.AppendFormat("Directory starts at cluster {0}", lifSb.directoryStart).AppendLine();
|
||||
sb.AppendFormat("LIF identifier: {0}", lifSb.lifId).AppendLine();
|
||||
sb.AppendFormat("Directory size: {0} clusters", lifSb.directorySize).AppendLine();
|
||||
sb.AppendFormat("LIF version: {0}", lifSb.lifVersion).AppendLine();
|
||||
// How is this related to volume size? I have only CDs to test and makes no sense there
|
||||
sb.AppendFormat("{0} tracks", LIFSb.tracks).AppendLine();
|
||||
sb.AppendFormat("{0} heads", LIFSb.heads).AppendLine();
|
||||
sb.AppendFormat("{0} sectors", LIFSb.sectors).AppendLine();
|
||||
sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(LIFSb.volumeLabel, CurrentEncoding))
|
||||
sb.AppendFormat("{0} tracks", lifSb.tracks).AppendLine();
|
||||
sb.AppendFormat("{0} heads", lifSb.heads).AppendLine();
|
||||
sb.AppendFormat("{0} sectors", lifSb.sectors).AppendLine();
|
||||
sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(lifSb.volumeLabel, CurrentEncoding))
|
||||
.AppendLine();
|
||||
sb.AppendFormat("Volume created on {0}", DateHandlers.LifToDateTime(LIFSb.creationDate)).AppendLine();
|
||||
sb.AppendFormat("Volume created on {0}", DateHandlers.LifToDateTime(lifSb.creationDate)).AppendLine();
|
||||
|
||||
information = sb.ToString();
|
||||
|
||||
xmlFSType = new FileSystemType
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
Type = "HP Logical Interchange Format",
|
||||
ClusterSize = 256,
|
||||
Clusters = (long)(partition.Size / 256),
|
||||
CreationDate = DateHandlers.LifToDateTime(LIFSb.creationDate),
|
||||
CreationDate = DateHandlers.LifToDateTime(lifSb.creationDate),
|
||||
CreationDateSpecified = true,
|
||||
VolumeName = StringHandlers.CToString(LIFSb.volumeLabel, CurrentEncoding)
|
||||
VolumeName = StringHandlers.CToString(lifSb.volumeLabel, CurrentEncoding)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -38,13 +38,13 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
/// Lisa FS v1, from Lisa OS 1.0 (Workshop or Office)
|
||||
/// Never seen on Sony floppies.
|
||||
/// </summary>
|
||||
const byte LisaFSv1 = 0x0E;
|
||||
const byte LISA_V1 = 0x0E;
|
||||
/// <summary>
|
||||
/// Lisa FS v2, from Lisa OS 2.0 (Workshop or Office)
|
||||
/// Contrary to what most information online says the only difference with V1
|
||||
/// is the Extents File size. Catalog format is the same
|
||||
/// </summary>
|
||||
const byte LisaFSv2 = 0x0F;
|
||||
const byte LISA_V2 = 0x0F;
|
||||
/// <summary>
|
||||
/// Lisa FS v3, from Lisa OS 3.0 (Workshop or Office)
|
||||
/// Adds support for user catalogs (aka subdirectories),
|
||||
@@ -52,7 +52,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
/// Uses '-' as path separator (so people that created Lisa/FILE.TEXT just
|
||||
/// created a file named like that :p)
|
||||
/// </summary>
|
||||
const byte LisaFSv3 = 0x11;
|
||||
const byte LISA_V3 = 0x11;
|
||||
/// <summary>Maximum string size in LisaFS</summary>
|
||||
const uint E_NAME = 32;
|
||||
/// <summary>
|
||||
|
||||
@@ -58,9 +58,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
/// <param name="contents">Directory contents.</param>
|
||||
public override Errno ReadDir(string path, ref List<string> contents)
|
||||
{
|
||||
short fileId;
|
||||
bool isDir;
|
||||
Errno error = LookupFileId(path, out fileId, out isDir);
|
||||
Errno error = LookupFileId(path, out short fileId, out bool isDir);
|
||||
if(error != Errno.NoError) return error;
|
||||
|
||||
if(!isDir) return Errno.NotDirectory;
|
||||
@@ -106,13 +104,10 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
|
||||
catalogCache = new List<CatalogEntry>();
|
||||
|
||||
Errno error;
|
||||
|
||||
// Do differently for V1 and V2
|
||||
if(mddf.fsversion == LisaFSv2 || mddf.fsversion == LisaFSv1)
|
||||
if(mddf.fsversion == LISA_V2 || mddf.fsversion == LISA_V1)
|
||||
{
|
||||
byte[] buf;
|
||||
error = ReadFile((short)FILEID_CATALOG, out buf);
|
||||
Errno error = ReadFile((short)FILEID_CATALOG, out byte[] buf);
|
||||
if(error != Errno.NoError) return error;
|
||||
|
||||
int offset = 0;
|
||||
@@ -142,18 +137,19 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
// Convert entries to V3 format
|
||||
foreach(CatalogEntryV2 entV2 in catalogV2)
|
||||
{
|
||||
ExtentFile ext;
|
||||
error = ReadExtentsFile(entV2.fileID, out ext);
|
||||
error = ReadExtentsFile(entV2.fileID, out ExtentFile ext);
|
||||
if(error != Errno.NoError) continue;
|
||||
|
||||
CatalogEntry entV3 = new CatalogEntry();
|
||||
entV3.fileID = entV2.fileID;
|
||||
entV3.filename = new byte[32];
|
||||
CatalogEntry entV3 = new CatalogEntry
|
||||
{
|
||||
fileID = entV2.fileID,
|
||||
filename = new byte[32],
|
||||
fileType = entV2.fileType,
|
||||
length = (int)srecords[entV2.fileID].filesize,
|
||||
dtc = ext.dtc,
|
||||
dtm = ext.dtm
|
||||
};
|
||||
Array.Copy(entV2.filename, 0, entV3.filename, 0, entV2.filenameLen);
|
||||
entV3.fileType = entV2.fileType;
|
||||
entV3.length = (int)srecords[entV2.fileID].filesize;
|
||||
entV3.dtc = ext.dtc;
|
||||
entV3.dtm = ext.dtm;
|
||||
|
||||
catalogCache.Add(entV3);
|
||||
}
|
||||
@@ -168,8 +164,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
// If root catalog is not pointed in MDDF (unchecked) maybe it's always following S-Records File?
|
||||
for(ulong i = 0; i < device.GetSectors(); i++)
|
||||
{
|
||||
LisaTag.PriamTag catTag;
|
||||
DecodeTag(device.ReadSectorTag(i, SectorTagType.AppleSectorTag), out catTag);
|
||||
DecodeTag(device.ReadSectorTag(i, SectorTagType.AppleSectorTag), out LisaTag.PriamTag catTag);
|
||||
|
||||
if(catTag.FileId != FILEID_CATALOG || catTag.RelPage != 0) continue;
|
||||
|
||||
@@ -186,9 +181,8 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
// Traverse double-linked list until first catalog block
|
||||
while(prevCatalogPointer != 0xFFFFFFFF)
|
||||
{
|
||||
LisaTag.PriamTag prevTag;
|
||||
DecodeTag(device.ReadSectorTag(prevCatalogPointer + mddf.mddf_block + volumePrefix, SectorTagType.AppleSectorTag),
|
||||
out prevTag);
|
||||
out LisaTag.PriamTag prevTag);
|
||||
|
||||
if(prevTag.FileId != FILEID_CATALOG) return Errno.InvalidArgument;
|
||||
|
||||
@@ -199,15 +193,13 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
ulong nextCatalogPointer;
|
||||
nextCatalogPointer = BigEndianBitConverter.ToUInt32(firstCatalogBlock, 0x7FA);
|
||||
|
||||
List<byte[]> catalogBlocks = new List<byte[]>();
|
||||
catalogBlocks.Add(firstCatalogBlock);
|
||||
List<byte[]> catalogBlocks = new List<byte[]> {firstCatalogBlock};
|
||||
|
||||
// Traverse double-linked list to read full catalog
|
||||
while(nextCatalogPointer != 0xFFFFFFFF)
|
||||
{
|
||||
LisaTag.PriamTag nextTag;
|
||||
DecodeTag(device.ReadSectorTag(nextCatalogPointer + mddf.mddf_block + volumePrefix, SectorTagType.AppleSectorTag),
|
||||
out nextTag);
|
||||
out LisaTag.PriamTag nextTag);
|
||||
|
||||
if(nextTag.FileId != FILEID_CATALOG) return Errno.InvalidArgument;
|
||||
|
||||
@@ -232,24 +224,25 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
// Normal entry
|
||||
else if(buf[offset + 0x24] == 0x03 && buf[offset] == 0x24)
|
||||
{
|
||||
CatalogEntry entry = new CatalogEntry();
|
||||
entry.marker = buf[offset];
|
||||
entry.parentID = BigEndianBitConverter.ToUInt16(buf, offset + 0x01);
|
||||
entry.filename = new byte[E_NAME];
|
||||
CatalogEntry entry = new CatalogEntry
|
||||
{
|
||||
marker = buf[offset],
|
||||
parentID = BigEndianBitConverter.ToUInt16(buf, offset + 0x01),
|
||||
filename = new byte[E_NAME],
|
||||
terminator = buf[offset + 0x23],
|
||||
fileType = buf[offset + 0x24],
|
||||
unknown = buf[offset + 0x25],
|
||||
fileID = BigEndianBitConverter.ToInt16(buf, offset + 0x26),
|
||||
dtc = BigEndianBitConverter.ToUInt32(buf, offset + 0x28),
|
||||
dtm = BigEndianBitConverter.ToUInt32(buf, offset + 0x2C),
|
||||
length = BigEndianBitConverter.ToInt32(buf, offset + 0x30),
|
||||
wasted = BigEndianBitConverter.ToInt32(buf, offset + 0x34),
|
||||
tail = new byte[8]
|
||||
};
|
||||
Array.Copy(buf, offset + 0x03, entry.filename, 0, E_NAME);
|
||||
entry.terminator = buf[offset + 0x23];
|
||||
entry.fileType = buf[offset + 0x24];
|
||||
entry.unknown = buf[offset + 0x25];
|
||||
entry.fileID = BigEndianBitConverter.ToInt16(buf, offset + 0x26);
|
||||
entry.dtc = BigEndianBitConverter.ToUInt32(buf, offset + 0x28);
|
||||
entry.dtm = BigEndianBitConverter.ToUInt32(buf, offset + 0x2C);
|
||||
entry.length = BigEndianBitConverter.ToInt32(buf, offset + 0x30);
|
||||
entry.wasted = BigEndianBitConverter.ToInt32(buf, offset + 0x34);
|
||||
entry.tail = new byte[8];
|
||||
Array.Copy(buf, offset + 0x38, entry.tail, 0, 8);
|
||||
|
||||
ExtentFile ext;
|
||||
if(ReadExtentsFile(entry.fileID, out ext) == Errno.NoError)
|
||||
if(ReadExtentsFile(entry.fileID, out _) == Errno.NoError)
|
||||
if(!fileSizeCache.ContainsKey(entry.fileID))
|
||||
{
|
||||
catalogCache.Add(entry);
|
||||
@@ -261,23 +254,25 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
// Subdirectory entry
|
||||
else if(buf[offset + 0x24] == 0x01 && buf[offset] == 0x24)
|
||||
{
|
||||
CatalogEntry entry = new CatalogEntry();
|
||||
entry.marker = buf[offset];
|
||||
entry.parentID = BigEndianBitConverter.ToUInt16(buf, offset + 0x01);
|
||||
entry.filename = new byte[E_NAME];
|
||||
CatalogEntry entry = new CatalogEntry
|
||||
{
|
||||
marker = buf[offset],
|
||||
parentID = BigEndianBitConverter.ToUInt16(buf, offset + 0x01),
|
||||
filename = new byte[E_NAME],
|
||||
terminator = buf[offset + 0x23],
|
||||
fileType = buf[offset + 0x24],
|
||||
unknown = buf[offset + 0x25],
|
||||
fileID = BigEndianBitConverter.ToInt16(buf, offset + 0x26),
|
||||
dtc = BigEndianBitConverter.ToUInt32(buf, offset + 0x28),
|
||||
dtm = BigEndianBitConverter.ToUInt32(buf, offset + 0x2C),
|
||||
length = 0,
|
||||
wasted = 0,
|
||||
tail = null
|
||||
};
|
||||
Array.Copy(buf, offset + 0x03, entry.filename, 0, E_NAME);
|
||||
entry.terminator = buf[offset + 0x23];
|
||||
entry.fileType = buf[offset + 0x24];
|
||||
entry.unknown = buf[offset + 0x25];
|
||||
entry.fileID = BigEndianBitConverter.ToInt16(buf, offset + 0x26);
|
||||
entry.dtc = BigEndianBitConverter.ToUInt32(buf, offset + 0x28);
|
||||
entry.dtm = BigEndianBitConverter.ToUInt32(buf, offset + 0x2C);
|
||||
entry.length = 0;
|
||||
entry.wasted = 0;
|
||||
entry.tail = null;
|
||||
|
||||
if(!directoryDTCCache.ContainsKey(entry.fileID))
|
||||
directoryDTCCache.Add(entry.fileID, DateHandlers.LisaToDateTime(entry.dtc));
|
||||
if(!directoryDtcCache.ContainsKey(entry.fileID))
|
||||
directoryDtcCache.Add(entry.fileID, DateHandlers.LisaToDateTime(entry.dtc));
|
||||
|
||||
catalogCache.Add(entry);
|
||||
|
||||
@@ -295,21 +290,22 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
|
||||
if(!mounted) return Errno.AccessDenied;
|
||||
|
||||
stat = new FileEntryInfo();
|
||||
stat.Attributes = new FileAttributes();
|
||||
DateTime tmp;
|
||||
stat = new FileEntryInfo
|
||||
{
|
||||
Attributes = new FileAttributes(),
|
||||
Inode = FILEID_CATALOG,
|
||||
Mode = 0x16D,
|
||||
Links = 0,
|
||||
UID = 0,
|
||||
GID = 0,
|
||||
DeviceNo = 0,
|
||||
Length = 0,
|
||||
BlockSize = mddf.datasize,
|
||||
Blocks = 0
|
||||
};
|
||||
|
||||
directoryDTCCache.TryGetValue(dirId, out tmp);
|
||||
directoryDtcCache.TryGetValue(dirId, out DateTime tmp);
|
||||
stat.CreationTime = tmp;
|
||||
stat.Inode = FILEID_CATALOG;
|
||||
stat.Mode = 0x16D;
|
||||
stat.Links = 0;
|
||||
stat.UID = 0;
|
||||
stat.GID = 0;
|
||||
stat.DeviceNo = 0;
|
||||
stat.Length = 0;
|
||||
stat.BlockSize = mddf.datasize;
|
||||
stat.Blocks = 0;
|
||||
|
||||
return Errno.NoError;
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
|
||||
if(!mounted) return Errno.AccessDenied;
|
||||
|
||||
if(fileId < 4 || fileId == 4 && mddf.fsversion != LisaFSv2 && mddf.fsversion != LisaFSv1)
|
||||
if(fileId < 4 || fileId == 4 && mddf.fsversion != LISA_V2 && mddf.fsversion != LISA_V1)
|
||||
return Errno.InvalidArgument;
|
||||
|
||||
if(extentCache.TryGetValue(fileId, out file)) return Errno.NoError;
|
||||
@@ -100,10 +100,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
|
||||
if(extTag.FileId != (short)(-1 * fileId)) return Errno.NoSuchFile;
|
||||
|
||||
byte[] sector;
|
||||
|
||||
if(mddf.fsversion == LisaFSv1) sector = device.ReadSectors(ptr, 2);
|
||||
else sector = device.ReadSector(ptr);
|
||||
byte[] sector = mddf.fsversion == LISA_V1 ? device.ReadSectors(ptr, 2) : device.ReadSector(ptr);
|
||||
|
||||
if(sector[0] >= 32 || sector[0] == 0) return Errno.InvalidArgument;
|
||||
|
||||
@@ -151,7 +148,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
int extentsCount = 0;
|
||||
int extentsOffset;
|
||||
|
||||
if(mddf.fsversion == LisaFSv1)
|
||||
if(mddf.fsversion == LISA_V1)
|
||||
{
|
||||
file.length = BigEndianBitConverter.ToInt32(sector, 0x200);
|
||||
file.unknown9 = BigEndianBitConverter.ToInt32(sector, 0x204);
|
||||
@@ -175,9 +172,11 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
|
||||
for(int j = 0; j < extentsCount; j++)
|
||||
{
|
||||
file.extents[j] = new Extent();
|
||||
file.extents[j].start = BigEndianBitConverter.ToInt32(sector, extentsOffset + j * 6);
|
||||
file.extents[j].length = BigEndianBitConverter.ToInt16(sector, extentsOffset + j * 6 + 4);
|
||||
file.extents[j] = new Extent
|
||||
{
|
||||
start = BigEndianBitConverter.ToInt32(sector, extentsOffset + j * 6),
|
||||
length = BigEndianBitConverter.ToInt16(sector, extentsOffset + j * 6 + 4)
|
||||
};
|
||||
}
|
||||
|
||||
extentCache.Add(fileId, file);
|
||||
@@ -278,11 +277,13 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
|
||||
for(int s = 0; s < srecords.Length; s++)
|
||||
{
|
||||
srecords[s] = new SRecord();
|
||||
srecords[s].extent_ptr = BigEndianBitConverter.ToUInt32(sectors, 0x00 + 14 * s);
|
||||
srecords[s].unknown = BigEndianBitConverter.ToUInt32(sectors, 0x04 + 14 * s);
|
||||
srecords[s].filesize = BigEndianBitConverter.ToUInt32(sectors, 0x08 + 14 * s);
|
||||
srecords[s].flags = BigEndianBitConverter.ToUInt16(sectors, 0x0C + 14 * s);
|
||||
srecords[s] = new SRecord
|
||||
{
|
||||
extent_ptr = BigEndianBitConverter.ToUInt32(sectors, 0x00 + 14 * s),
|
||||
unknown = BigEndianBitConverter.ToUInt32(sectors, 0x04 + 14 * s),
|
||||
filesize = BigEndianBitConverter.ToUInt32(sectors, 0x08 + 14 * s),
|
||||
flags = BigEndianBitConverter.ToUInt16(sectors, 0x0C + 14 * s)
|
||||
};
|
||||
}
|
||||
|
||||
return Errno.NoError;
|
||||
|
||||
@@ -41,9 +41,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
{
|
||||
public override Errno GetAttributes(string path, ref FileAttributes attributes)
|
||||
{
|
||||
short fileId;
|
||||
bool isDir;
|
||||
Errno error = LookupFileId(path, out fileId, out isDir);
|
||||
Errno error = LookupFileId(path, out short fileId, out bool isDir);
|
||||
if(error != Errno.NoError) return error;
|
||||
|
||||
if(!isDir) return GetAttributes(fileId, ref attributes);
|
||||
@@ -64,9 +62,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
|
||||
if(offset < 0) return Errno.InvalidArgument;
|
||||
|
||||
short fileId;
|
||||
bool isDir;
|
||||
Errno error = LookupFileId(path, out fileId, out isDir);
|
||||
Errno error = LookupFileId(path, out short fileId, out _);
|
||||
if(error != Errno.NoError) return error;
|
||||
|
||||
byte[] tmp;
|
||||
@@ -100,9 +96,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
|
||||
public override Errno Stat(string path, ref FileEntryInfo stat)
|
||||
{
|
||||
short fileId;
|
||||
bool isDir;
|
||||
Errno error = LookupFileId(path, out fileId, out isDir);
|
||||
Errno error = LookupFileId(path, out short fileId, out bool isDir);
|
||||
if(error != Errno.NoError) return error;
|
||||
|
||||
return isDir ? StatDir(fileId, out stat) : Stat(fileId, out stat);
|
||||
@@ -125,8 +119,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
return Errno.NoError;
|
||||
}
|
||||
|
||||
ExtentFile extFile;
|
||||
Errno error = ReadExtentsFile(fileId, out extFile);
|
||||
Errno error = ReadExtentsFile(fileId, out ExtentFile extFile);
|
||||
|
||||
if(error != Errno.NoError) return error;
|
||||
|
||||
@@ -200,8 +193,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
|
||||
if(count == 0) return Errno.NoSuchFile;
|
||||
|
||||
if(!tags) buf = new byte[count * device.GetSectorSize()];
|
||||
else buf = new byte[count * devTagSize];
|
||||
buf = !tags ? new byte[count * device.GetSectorSize()] : new byte[count * devTagSize];
|
||||
|
||||
// Should be enough to check 100 sectors?
|
||||
for(ulong i = 0; i < 100; i++)
|
||||
@@ -210,10 +202,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
|
||||
if(sysTag.FileId != fileId) continue;
|
||||
|
||||
byte[] sector;
|
||||
|
||||
if(!tags) sector = device.ReadSector(i);
|
||||
else sector = device.ReadSectorTag(i, SectorTagType.AppleSectorTag);
|
||||
byte[] sector = !tags ? device.ReadSector(i) : device.ReadSectorTag(i, SectorTagType.AppleSectorTag);
|
||||
|
||||
// Relative block for $Loader starts at $Boot block
|
||||
if(sysTag.FileId == FILEID_LOADER_SIGNED) sysTag.RelPage--;
|
||||
@@ -239,8 +228,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
if(!debug || fileId == 0) return Errno.NoSuchFile;
|
||||
else
|
||||
{
|
||||
stat = new FileEntryInfo();
|
||||
stat.Attributes = new FileAttributes();
|
||||
stat = new FileEntryInfo {Attributes = new FileAttributes()};
|
||||
|
||||
error = GetAttributes(fileId, ref stat.Attributes);
|
||||
if(error != Errno.NoError) return error;
|
||||
@@ -267,12 +255,10 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] buf;
|
||||
error = ReadSystemFile(fileId, out buf);
|
||||
error = ReadSystemFile(fileId, out byte[] buf);
|
||||
if(error != Errno.NoError) return error;
|
||||
|
||||
if(fileId != 4) stat.CreationTime = mddf.dtvc;
|
||||
else stat.CreationTime = mddf.dtcc;
|
||||
stat.CreationTime = fileId != 4 ? mddf.dtvc : mddf.dtcc;
|
||||
|
||||
stat.BackupTime = mddf.dtvb;
|
||||
|
||||
@@ -290,8 +276,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
return Errno.NoError;
|
||||
}
|
||||
|
||||
stat = new FileEntryInfo();
|
||||
stat.Attributes = new FileAttributes();
|
||||
stat = new FileEntryInfo {Attributes = new FileAttributes()};
|
||||
error = GetAttributes(fileId, ref stat.Attributes);
|
||||
if(error != Errno.NoError) return error;
|
||||
|
||||
@@ -309,8 +294,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
stat.UID = 0;
|
||||
stat.GID = 0;
|
||||
stat.DeviceNo = 0;
|
||||
int len;
|
||||
if(!fileSizeCache.TryGetValue(fileId, out len)) stat.Length = srecords[fileId].filesize;
|
||||
if(!fileSizeCache.TryGetValue(fileId, out int len)) stat.Length = srecords[fileId].filesize;
|
||||
else stat.Length = len;
|
||||
stat.BlockSize = mddf.datasize;
|
||||
stat.Blocks = file.length;
|
||||
@@ -330,15 +314,12 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
|
||||
tags &= debug;
|
||||
|
||||
if(fileId < 4 || fileId == 4 && mddf.fsversion != LisaFSv2 && mddf.fsversion != LisaFSv1)
|
||||
if(fileId < 4 || fileId == 4 && mddf.fsversion != LISA_V2 && mddf.fsversion != LISA_V1)
|
||||
return Errno.InvalidArgument;
|
||||
|
||||
if(!tags && fileCache.TryGetValue(fileId, out buf)) return Errno.NoError;
|
||||
|
||||
Errno error;
|
||||
ExtentFile file;
|
||||
|
||||
error = ReadExtentsFile(fileId, out file);
|
||||
Errno error = ReadExtentsFile(fileId, out ExtentFile file);
|
||||
if(error != Errno.NoError) return error;
|
||||
|
||||
int sectorSize;
|
||||
@@ -365,8 +346,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
|
||||
if(!tags)
|
||||
{
|
||||
int realSize;
|
||||
if(fileSizeCache.TryGetValue(fileId, out realSize)) if(realSize > temp.Length) DicConsole.ErrorWriteLine("File {0} gets truncated.", fileId);
|
||||
if(fileSizeCache.TryGetValue(fileId, out int realSize)) if(realSize > temp.Length) DicConsole.ErrorWriteLine("File {0} gets truncated.", fileId);
|
||||
buf = temp;
|
||||
|
||||
fileCache.Add(fileId, buf);
|
||||
@@ -393,7 +373,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
}
|
||||
|
||||
// Only V3 supports subdirectories
|
||||
if(pathElements.Length > 1 && mddf.fsversion != LisaFSv3) return Errno.NotSupported;
|
||||
if(pathElements.Length > 1 && mddf.fsversion != LISA_V3) return Errno.NotSupported;
|
||||
|
||||
if(debug && pathElements.Length == 1)
|
||||
{
|
||||
|
||||
@@ -56,56 +56,54 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
// Minimal LisaOS disk is 3.5" single sided double density, 800 sectors
|
||||
if(imagePlugin.GetSectors() < 800) return false;
|
||||
|
||||
int before_mddf = -1;
|
||||
int beforeMddf = -1;
|
||||
|
||||
// LisaOS searches sectors until tag tells MDDF resides there, so we'll search 100 sectors
|
||||
for(int i = 0; i < 100; i++)
|
||||
{
|
||||
LisaTag.PriamTag searchTag;
|
||||
DecodeTag(imagePlugin.ReadSectorTag((ulong)i, SectorTagType.AppleSectorTag), out searchTag);
|
||||
DecodeTag(imagePlugin.ReadSectorTag((ulong)i, SectorTagType.AppleSectorTag), out LisaTag.PriamTag searchTag);
|
||||
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "Sector {0}, file ID 0x{1:X4}", i, searchTag.FileId);
|
||||
|
||||
if(before_mddf == -1 && searchTag.FileId == FILEID_LOADER_SIGNED) before_mddf = i - 1;
|
||||
if(beforeMddf == -1 && searchTag.FileId == FILEID_LOADER_SIGNED) beforeMddf = i - 1;
|
||||
|
||||
if(searchTag.FileId != FILEID_MDDF) continue;
|
||||
|
||||
byte[] sector = imagePlugin.ReadSector((ulong)i);
|
||||
MDDF info_mddf = new MDDF();
|
||||
|
||||
info_mddf.mddf_block = BigEndianBitConverter.ToUInt32(sector, 0x6C);
|
||||
info_mddf.volsize_minus_one = BigEndianBitConverter.ToUInt32(sector, 0x70);
|
||||
info_mddf.volsize_minus_mddf_minus_one = BigEndianBitConverter.ToUInt32(sector, 0x74);
|
||||
info_mddf.vol_size = BigEndianBitConverter.ToUInt32(sector, 0x78);
|
||||
info_mddf.blocksize = BigEndianBitConverter.ToUInt16(sector, 0x7C);
|
||||
info_mddf.datasize = BigEndianBitConverter.ToUInt16(sector, 0x7E);
|
||||
MDDF infoMddf = new MDDF
|
||||
{
|
||||
mddf_block = BigEndianBitConverter.ToUInt32(sector, 0x6C),
|
||||
volsize_minus_one = BigEndianBitConverter.ToUInt32(sector, 0x70),
|
||||
volsize_minus_mddf_minus_one = BigEndianBitConverter.ToUInt32(sector, 0x74),
|
||||
vol_size = BigEndianBitConverter.ToUInt32(sector, 0x78),
|
||||
blocksize = BigEndianBitConverter.ToUInt16(sector, 0x7C),
|
||||
datasize = BigEndianBitConverter.ToUInt16(sector, 0x7E)
|
||||
};
|
||||
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "Current sector = {0}", i);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.mddf_block = {0}", info_mddf.mddf_block);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.mddf_block = {0}", infoMddf.mddf_block);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "Disk size = {0} sectors", imagePlugin.GetSectors());
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.vol_size = {0} sectors", info_mddf.vol_size);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.vol_size - 1 = {0}", info_mddf.volsize_minus_one);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.vol_size = {0} sectors", infoMddf.vol_size);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.vol_size - 1 = {0}", infoMddf.volsize_minus_one);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.vol_size - mddf.mddf_block -1 = {0}",
|
||||
info_mddf.volsize_minus_mddf_minus_one);
|
||||
infoMddf.volsize_minus_mddf_minus_one);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "Disk sector = {0} bytes", imagePlugin.GetSectorSize());
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.blocksize = {0} bytes", info_mddf.blocksize);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.datasize = {0} bytes", info_mddf.datasize);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.blocksize = {0} bytes", infoMddf.blocksize);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.datasize = {0} bytes", infoMddf.datasize);
|
||||
|
||||
if(info_mddf.mddf_block != i - before_mddf) return false;
|
||||
if(infoMddf.mddf_block != i - beforeMddf) return false;
|
||||
|
||||
if(info_mddf.vol_size > imagePlugin.GetSectors()) return false;
|
||||
if(infoMddf.vol_size > imagePlugin.GetSectors()) return false;
|
||||
|
||||
if(info_mddf.vol_size - 1 != info_mddf.volsize_minus_one) return false;
|
||||
if(infoMddf.vol_size - 1 != infoMddf.volsize_minus_one) return false;
|
||||
|
||||
if(info_mddf.vol_size - i - 1 != info_mddf.volsize_minus_mddf_minus_one - before_mddf) return false;
|
||||
if(infoMddf.vol_size - i - 1 != infoMddf.volsize_minus_mddf_minus_one - beforeMddf) return false;
|
||||
|
||||
if(info_mddf.datasize > info_mddf.blocksize) return false;
|
||||
if(infoMddf.datasize > infoMddf.blocksize) return false;
|
||||
|
||||
if(info_mddf.blocksize < imagePlugin.GetSectorSize()) return false;
|
||||
if(infoMddf.blocksize < imagePlugin.GetSectorSize()) return false;
|
||||
|
||||
if(info_mddf.datasize != imagePlugin.GetSectorSize()) return false;
|
||||
|
||||
return true;
|
||||
return infoMddf.datasize == imagePlugin.GetSectorSize();
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -134,243 +132,241 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
// Minimal LisaOS disk is 3.5" single sided double density, 800 sectors
|
||||
if(imagePlugin.GetSectors() < 800) return;
|
||||
|
||||
int before_mddf = -1;
|
||||
int beforeMddf = -1;
|
||||
|
||||
// LisaOS searches sectors until tag tells MDDF resides there, so we'll search 100 sectors
|
||||
for(int i = 0; i < 100; i++)
|
||||
{
|
||||
LisaTag.PriamTag searchTag;
|
||||
DecodeTag(imagePlugin.ReadSectorTag((ulong)i, SectorTagType.AppleSectorTag), out searchTag);
|
||||
DecodeTag(imagePlugin.ReadSectorTag((ulong)i, SectorTagType.AppleSectorTag), out LisaTag.PriamTag searchTag);
|
||||
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "Sector {0}, file ID 0x{1:X4}", i, searchTag.FileId);
|
||||
|
||||
if(before_mddf == -1 && searchTag.FileId == FILEID_LOADER_SIGNED) before_mddf = i - 1;
|
||||
if(beforeMddf == -1 && searchTag.FileId == FILEID_LOADER_SIGNED) beforeMddf = i - 1;
|
||||
|
||||
if(searchTag.FileId != FILEID_MDDF) continue;
|
||||
|
||||
byte[] sector = imagePlugin.ReadSector((ulong)i);
|
||||
MDDF info_mddf = new MDDF();
|
||||
MDDF infoMddf = new MDDF();
|
||||
byte[] pString = new byte[33];
|
||||
uint lisa_time;
|
||||
uint lisaTime;
|
||||
|
||||
info_mddf.fsversion = BigEndianBitConverter.ToUInt16(sector, 0x00);
|
||||
info_mddf.volid = BigEndianBitConverter.ToUInt64(sector, 0x02);
|
||||
info_mddf.volnum = BigEndianBitConverter.ToUInt16(sector, 0x0A);
|
||||
infoMddf.fsversion = BigEndianBitConverter.ToUInt16(sector, 0x00);
|
||||
infoMddf.volid = BigEndianBitConverter.ToUInt64(sector, 0x02);
|
||||
infoMddf.volnum = BigEndianBitConverter.ToUInt16(sector, 0x0A);
|
||||
Array.Copy(sector, 0x0C, pString, 0, 33);
|
||||
info_mddf.volname = StringHandlers.PascalToString(pString, CurrentEncoding);
|
||||
info_mddf.unknown1 = sector[0x2D];
|
||||
infoMddf.volname = StringHandlers.PascalToString(pString, CurrentEncoding);
|
||||
infoMddf.unknown1 = sector[0x2D];
|
||||
Array.Copy(sector, 0x2E, pString, 0, 33);
|
||||
// Prevent garbage
|
||||
if(pString[0] <= 32) info_mddf.password = StringHandlers.PascalToString(pString, CurrentEncoding);
|
||||
else info_mddf.password = "";
|
||||
info_mddf.unknown2 = sector[0x4F];
|
||||
info_mddf.machine_id = BigEndianBitConverter.ToUInt32(sector, 0x50);
|
||||
info_mddf.master_copy_id = BigEndianBitConverter.ToUInt32(sector, 0x54);
|
||||
lisa_time = BigEndianBitConverter.ToUInt32(sector, 0x58);
|
||||
info_mddf.dtvc = DateHandlers.LisaToDateTime(lisa_time);
|
||||
lisa_time = BigEndianBitConverter.ToUInt32(sector, 0x5C);
|
||||
info_mddf.dtcc = DateHandlers.LisaToDateTime(lisa_time);
|
||||
lisa_time = BigEndianBitConverter.ToUInt32(sector, 0x60);
|
||||
info_mddf.dtvb = DateHandlers.LisaToDateTime(lisa_time);
|
||||
lisa_time = BigEndianBitConverter.ToUInt32(sector, 0x64);
|
||||
info_mddf.dtvs = DateHandlers.LisaToDateTime(lisa_time);
|
||||
info_mddf.unknown3 = BigEndianBitConverter.ToUInt32(sector, 0x68);
|
||||
info_mddf.mddf_block = BigEndianBitConverter.ToUInt32(sector, 0x6C);
|
||||
info_mddf.volsize_minus_one = BigEndianBitConverter.ToUInt32(sector, 0x70);
|
||||
info_mddf.volsize_minus_mddf_minus_one = BigEndianBitConverter.ToUInt32(sector, 0x74);
|
||||
info_mddf.vol_size = BigEndianBitConverter.ToUInt32(sector, 0x78);
|
||||
info_mddf.blocksize = BigEndianBitConverter.ToUInt16(sector, 0x7C);
|
||||
info_mddf.datasize = BigEndianBitConverter.ToUInt16(sector, 0x7E);
|
||||
info_mddf.unknown4 = BigEndianBitConverter.ToUInt16(sector, 0x80);
|
||||
info_mddf.unknown5 = BigEndianBitConverter.ToUInt32(sector, 0x82);
|
||||
info_mddf.unknown6 = BigEndianBitConverter.ToUInt32(sector, 0x86);
|
||||
info_mddf.clustersize = BigEndianBitConverter.ToUInt16(sector, 0x8A);
|
||||
info_mddf.fs_size = BigEndianBitConverter.ToUInt32(sector, 0x8C);
|
||||
info_mddf.unknown7 = BigEndianBitConverter.ToUInt32(sector, 0x90);
|
||||
info_mddf.srec_ptr = BigEndianBitConverter.ToUInt32(sector, 0x94);
|
||||
info_mddf.unknown9 = BigEndianBitConverter.ToUInt16(sector, 0x98);
|
||||
info_mddf.srec_len = BigEndianBitConverter.ToUInt16(sector, 0x9A);
|
||||
info_mddf.unknown10 = BigEndianBitConverter.ToUInt32(sector, 0x9C);
|
||||
info_mddf.unknown11 = BigEndianBitConverter.ToUInt32(sector, 0xA0);
|
||||
info_mddf.unknown12 = BigEndianBitConverter.ToUInt32(sector, 0xA4);
|
||||
info_mddf.unknown13 = BigEndianBitConverter.ToUInt32(sector, 0xA8);
|
||||
info_mddf.unknown14 = BigEndianBitConverter.ToUInt32(sector, 0xAC);
|
||||
info_mddf.filecount = BigEndianBitConverter.ToUInt16(sector, 0xB0);
|
||||
info_mddf.unknown15 = BigEndianBitConverter.ToUInt32(sector, 0xB2);
|
||||
info_mddf.unknown16 = BigEndianBitConverter.ToUInt32(sector, 0xB6);
|
||||
info_mddf.freecount = BigEndianBitConverter.ToUInt32(sector, 0xBA);
|
||||
info_mddf.unknown17 = BigEndianBitConverter.ToUInt16(sector, 0xBE);
|
||||
info_mddf.unknown18 = BigEndianBitConverter.ToUInt32(sector, 0xC0);
|
||||
info_mddf.overmount_stamp = BigEndianBitConverter.ToUInt64(sector, 0xC4);
|
||||
info_mddf.serialization = BigEndianBitConverter.ToUInt32(sector, 0xCC);
|
||||
info_mddf.unknown19 = BigEndianBitConverter.ToUInt32(sector, 0xD0);
|
||||
info_mddf.unknown_timestamp = BigEndianBitConverter.ToUInt32(sector, 0xD4);
|
||||
info_mddf.unknown20 = BigEndianBitConverter.ToUInt32(sector, 0xD8);
|
||||
info_mddf.unknown21 = BigEndianBitConverter.ToUInt32(sector, 0xDC);
|
||||
info_mddf.unknown22 = BigEndianBitConverter.ToUInt32(sector, 0xE0);
|
||||
info_mddf.unknown23 = BigEndianBitConverter.ToUInt32(sector, 0xE4);
|
||||
info_mddf.unknown24 = BigEndianBitConverter.ToUInt32(sector, 0xE8);
|
||||
info_mddf.unknown25 = BigEndianBitConverter.ToUInt32(sector, 0xEC);
|
||||
info_mddf.unknown26 = BigEndianBitConverter.ToUInt32(sector, 0xF0);
|
||||
info_mddf.unknown27 = BigEndianBitConverter.ToUInt32(sector, 0xF4);
|
||||
info_mddf.unknown28 = BigEndianBitConverter.ToUInt32(sector, 0xF8);
|
||||
info_mddf.unknown29 = BigEndianBitConverter.ToUInt32(sector, 0xFC);
|
||||
info_mddf.unknown30 = BigEndianBitConverter.ToUInt32(sector, 0x100);
|
||||
info_mddf.unknown31 = BigEndianBitConverter.ToUInt32(sector, 0x104);
|
||||
info_mddf.unknown32 = BigEndianBitConverter.ToUInt32(sector, 0x108);
|
||||
info_mddf.unknown33 = BigEndianBitConverter.ToUInt32(sector, 0x10C);
|
||||
info_mddf.unknown34 = BigEndianBitConverter.ToUInt32(sector, 0x110);
|
||||
info_mddf.unknown35 = BigEndianBitConverter.ToUInt32(sector, 0x114);
|
||||
info_mddf.backup_volid = BigEndianBitConverter.ToUInt64(sector, 0x118);
|
||||
info_mddf.label_size = BigEndianBitConverter.ToUInt16(sector, 0x120);
|
||||
info_mddf.fs_overhead = BigEndianBitConverter.ToUInt16(sector, 0x122);
|
||||
info_mddf.result_scavenge = BigEndianBitConverter.ToUInt16(sector, 0x124);
|
||||
info_mddf.boot_code = BigEndianBitConverter.ToUInt16(sector, 0x126);
|
||||
info_mddf.boot_environ = BigEndianBitConverter.ToUInt16(sector, 0x6C);
|
||||
info_mddf.unknown36 = BigEndianBitConverter.ToUInt32(sector, 0x12A);
|
||||
info_mddf.unknown37 = BigEndianBitConverter.ToUInt32(sector, 0x12E);
|
||||
info_mddf.unknown38 = BigEndianBitConverter.ToUInt32(sector, 0x132);
|
||||
info_mddf.vol_sequence = BigEndianBitConverter.ToUInt16(sector, 0x136);
|
||||
info_mddf.vol_left_mounted = sector[0x138];
|
||||
infoMddf.password = pString[0] <= 32 ? StringHandlers.PascalToString(pString, CurrentEncoding) : "";
|
||||
infoMddf.unknown2 = sector[0x4F];
|
||||
infoMddf.machine_id = BigEndianBitConverter.ToUInt32(sector, 0x50);
|
||||
infoMddf.master_copy_id = BigEndianBitConverter.ToUInt32(sector, 0x54);
|
||||
lisaTime = BigEndianBitConverter.ToUInt32(sector, 0x58);
|
||||
infoMddf.dtvc = DateHandlers.LisaToDateTime(lisaTime);
|
||||
lisaTime = BigEndianBitConverter.ToUInt32(sector, 0x5C);
|
||||
infoMddf.dtcc = DateHandlers.LisaToDateTime(lisaTime);
|
||||
lisaTime = BigEndianBitConverter.ToUInt32(sector, 0x60);
|
||||
infoMddf.dtvb = DateHandlers.LisaToDateTime(lisaTime);
|
||||
lisaTime = BigEndianBitConverter.ToUInt32(sector, 0x64);
|
||||
infoMddf.dtvs = DateHandlers.LisaToDateTime(lisaTime);
|
||||
infoMddf.unknown3 = BigEndianBitConverter.ToUInt32(sector, 0x68);
|
||||
infoMddf.mddf_block = BigEndianBitConverter.ToUInt32(sector, 0x6C);
|
||||
infoMddf.volsize_minus_one = BigEndianBitConverter.ToUInt32(sector, 0x70);
|
||||
infoMddf.volsize_minus_mddf_minus_one = BigEndianBitConverter.ToUInt32(sector, 0x74);
|
||||
infoMddf.vol_size = BigEndianBitConverter.ToUInt32(sector, 0x78);
|
||||
infoMddf.blocksize = BigEndianBitConverter.ToUInt16(sector, 0x7C);
|
||||
infoMddf.datasize = BigEndianBitConverter.ToUInt16(sector, 0x7E);
|
||||
infoMddf.unknown4 = BigEndianBitConverter.ToUInt16(sector, 0x80);
|
||||
infoMddf.unknown5 = BigEndianBitConverter.ToUInt32(sector, 0x82);
|
||||
infoMddf.unknown6 = BigEndianBitConverter.ToUInt32(sector, 0x86);
|
||||
infoMddf.clustersize = BigEndianBitConverter.ToUInt16(sector, 0x8A);
|
||||
infoMddf.fs_size = BigEndianBitConverter.ToUInt32(sector, 0x8C);
|
||||
infoMddf.unknown7 = BigEndianBitConverter.ToUInt32(sector, 0x90);
|
||||
infoMddf.srec_ptr = BigEndianBitConverter.ToUInt32(sector, 0x94);
|
||||
infoMddf.unknown9 = BigEndianBitConverter.ToUInt16(sector, 0x98);
|
||||
infoMddf.srec_len = BigEndianBitConverter.ToUInt16(sector, 0x9A);
|
||||
infoMddf.unknown10 = BigEndianBitConverter.ToUInt32(sector, 0x9C);
|
||||
infoMddf.unknown11 = BigEndianBitConverter.ToUInt32(sector, 0xA0);
|
||||
infoMddf.unknown12 = BigEndianBitConverter.ToUInt32(sector, 0xA4);
|
||||
infoMddf.unknown13 = BigEndianBitConverter.ToUInt32(sector, 0xA8);
|
||||
infoMddf.unknown14 = BigEndianBitConverter.ToUInt32(sector, 0xAC);
|
||||
infoMddf.filecount = BigEndianBitConverter.ToUInt16(sector, 0xB0);
|
||||
infoMddf.unknown15 = BigEndianBitConverter.ToUInt32(sector, 0xB2);
|
||||
infoMddf.unknown16 = BigEndianBitConverter.ToUInt32(sector, 0xB6);
|
||||
infoMddf.freecount = BigEndianBitConverter.ToUInt32(sector, 0xBA);
|
||||
infoMddf.unknown17 = BigEndianBitConverter.ToUInt16(sector, 0xBE);
|
||||
infoMddf.unknown18 = BigEndianBitConverter.ToUInt32(sector, 0xC0);
|
||||
infoMddf.overmount_stamp = BigEndianBitConverter.ToUInt64(sector, 0xC4);
|
||||
infoMddf.serialization = BigEndianBitConverter.ToUInt32(sector, 0xCC);
|
||||
infoMddf.unknown19 = BigEndianBitConverter.ToUInt32(sector, 0xD0);
|
||||
infoMddf.unknown_timestamp = BigEndianBitConverter.ToUInt32(sector, 0xD4);
|
||||
infoMddf.unknown20 = BigEndianBitConverter.ToUInt32(sector, 0xD8);
|
||||
infoMddf.unknown21 = BigEndianBitConverter.ToUInt32(sector, 0xDC);
|
||||
infoMddf.unknown22 = BigEndianBitConverter.ToUInt32(sector, 0xE0);
|
||||
infoMddf.unknown23 = BigEndianBitConverter.ToUInt32(sector, 0xE4);
|
||||
infoMddf.unknown24 = BigEndianBitConverter.ToUInt32(sector, 0xE8);
|
||||
infoMddf.unknown25 = BigEndianBitConverter.ToUInt32(sector, 0xEC);
|
||||
infoMddf.unknown26 = BigEndianBitConverter.ToUInt32(sector, 0xF0);
|
||||
infoMddf.unknown27 = BigEndianBitConverter.ToUInt32(sector, 0xF4);
|
||||
infoMddf.unknown28 = BigEndianBitConverter.ToUInt32(sector, 0xF8);
|
||||
infoMddf.unknown29 = BigEndianBitConverter.ToUInt32(sector, 0xFC);
|
||||
infoMddf.unknown30 = BigEndianBitConverter.ToUInt32(sector, 0x100);
|
||||
infoMddf.unknown31 = BigEndianBitConverter.ToUInt32(sector, 0x104);
|
||||
infoMddf.unknown32 = BigEndianBitConverter.ToUInt32(sector, 0x108);
|
||||
infoMddf.unknown33 = BigEndianBitConverter.ToUInt32(sector, 0x10C);
|
||||
infoMddf.unknown34 = BigEndianBitConverter.ToUInt32(sector, 0x110);
|
||||
infoMddf.unknown35 = BigEndianBitConverter.ToUInt32(sector, 0x114);
|
||||
infoMddf.backup_volid = BigEndianBitConverter.ToUInt64(sector, 0x118);
|
||||
infoMddf.label_size = BigEndianBitConverter.ToUInt16(sector, 0x120);
|
||||
infoMddf.fs_overhead = BigEndianBitConverter.ToUInt16(sector, 0x122);
|
||||
infoMddf.result_scavenge = BigEndianBitConverter.ToUInt16(sector, 0x124);
|
||||
infoMddf.boot_code = BigEndianBitConverter.ToUInt16(sector, 0x126);
|
||||
infoMddf.boot_environ = BigEndianBitConverter.ToUInt16(sector, 0x6C);
|
||||
infoMddf.unknown36 = BigEndianBitConverter.ToUInt32(sector, 0x12A);
|
||||
infoMddf.unknown37 = BigEndianBitConverter.ToUInt32(sector, 0x12E);
|
||||
infoMddf.unknown38 = BigEndianBitConverter.ToUInt32(sector, 0x132);
|
||||
infoMddf.vol_sequence = BigEndianBitConverter.ToUInt16(sector, 0x136);
|
||||
infoMddf.vol_left_mounted = sector[0x138];
|
||||
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown1 = 0x{0:X2} ({0})", info_mddf.unknown1);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown2 = 0x{0:X2} ({0})", info_mddf.unknown2);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown3 = 0x{0:X8} ({0})", info_mddf.unknown3);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown4 = 0x{0:X4} ({0})", info_mddf.unknown4);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown5 = 0x{0:X8} ({0})", info_mddf.unknown5);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown6 = 0x{0:X8} ({0})", info_mddf.unknown6);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown7 = 0x{0:X8} ({0})", info_mddf.unknown7);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown9 = 0x{0:X4} ({0})", info_mddf.unknown9);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown10 = 0x{0:X8} ({0})", info_mddf.unknown10);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown11 = 0x{0:X8} ({0})", info_mddf.unknown11);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown12 = 0x{0:X8} ({0})", info_mddf.unknown12);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown13 = 0x{0:X8} ({0})", info_mddf.unknown13);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown14 = 0x{0:X8} ({0})", info_mddf.unknown14);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown15 = 0x{0:X8} ({0})", info_mddf.unknown15);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown16 = 0x{0:X8} ({0})", info_mddf.unknown16);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown17 = 0x{0:X4} ({0})", info_mddf.unknown17);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown18 = 0x{0:X8} ({0})", info_mddf.unknown18);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown19 = 0x{0:X8} ({0})", info_mddf.unknown19);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown20 = 0x{0:X8} ({0})", info_mddf.unknown20);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown21 = 0x{0:X8} ({0})", info_mddf.unknown21);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown22 = 0x{0:X8} ({0})", info_mddf.unknown22);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown23 = 0x{0:X8} ({0})", info_mddf.unknown23);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown24 = 0x{0:X8} ({0})", info_mddf.unknown24);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown25 = 0x{0:X8} ({0})", info_mddf.unknown25);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown26 = 0x{0:X8} ({0})", info_mddf.unknown26);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown27 = 0x{0:X8} ({0})", info_mddf.unknown27);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown28 = 0x{0:X8} ({0})", info_mddf.unknown28);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown29 = 0x{0:X8} ({0})", info_mddf.unknown29);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown30 = 0x{0:X8} ({0})", info_mddf.unknown30);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown31 = 0x{0:X8} ({0})", info_mddf.unknown31);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown32 = 0x{0:X8} ({0})", info_mddf.unknown32);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown33 = 0x{0:X8} ({0})", info_mddf.unknown33);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown34 = 0x{0:X8} ({0})", info_mddf.unknown34);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown35 = 0x{0:X8} ({0})", info_mddf.unknown35);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown36 = 0x{0:X8} ({0})", info_mddf.unknown36);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown37 = 0x{0:X8} ({0})", info_mddf.unknown37);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown38 = 0x{0:X8} ({0})", info_mddf.unknown38);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown1 = 0x{0:X2} ({0})", infoMddf.unknown1);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown2 = 0x{0:X2} ({0})", infoMddf.unknown2);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown3 = 0x{0:X8} ({0})", infoMddf.unknown3);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown4 = 0x{0:X4} ({0})", infoMddf.unknown4);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown5 = 0x{0:X8} ({0})", infoMddf.unknown5);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown6 = 0x{0:X8} ({0})", infoMddf.unknown6);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown7 = 0x{0:X8} ({0})", infoMddf.unknown7);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown9 = 0x{0:X4} ({0})", infoMddf.unknown9);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown10 = 0x{0:X8} ({0})", infoMddf.unknown10);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown11 = 0x{0:X8} ({0})", infoMddf.unknown11);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown12 = 0x{0:X8} ({0})", infoMddf.unknown12);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown13 = 0x{0:X8} ({0})", infoMddf.unknown13);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown14 = 0x{0:X8} ({0})", infoMddf.unknown14);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown15 = 0x{0:X8} ({0})", infoMddf.unknown15);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown16 = 0x{0:X8} ({0})", infoMddf.unknown16);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown17 = 0x{0:X4} ({0})", infoMddf.unknown17);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown18 = 0x{0:X8} ({0})", infoMddf.unknown18);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown19 = 0x{0:X8} ({0})", infoMddf.unknown19);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown20 = 0x{0:X8} ({0})", infoMddf.unknown20);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown21 = 0x{0:X8} ({0})", infoMddf.unknown21);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown22 = 0x{0:X8} ({0})", infoMddf.unknown22);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown23 = 0x{0:X8} ({0})", infoMddf.unknown23);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown24 = 0x{0:X8} ({0})", infoMddf.unknown24);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown25 = 0x{0:X8} ({0})", infoMddf.unknown25);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown26 = 0x{0:X8} ({0})", infoMddf.unknown26);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown27 = 0x{0:X8} ({0})", infoMddf.unknown27);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown28 = 0x{0:X8} ({0})", infoMddf.unknown28);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown29 = 0x{0:X8} ({0})", infoMddf.unknown29);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown30 = 0x{0:X8} ({0})", infoMddf.unknown30);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown31 = 0x{0:X8} ({0})", infoMddf.unknown31);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown32 = 0x{0:X8} ({0})", infoMddf.unknown32);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown33 = 0x{0:X8} ({0})", infoMddf.unknown33);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown34 = 0x{0:X8} ({0})", infoMddf.unknown34);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown35 = 0x{0:X8} ({0})", infoMddf.unknown35);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown36 = 0x{0:X8} ({0})", infoMddf.unknown36);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown37 = 0x{0:X8} ({0})", infoMddf.unknown37);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown38 = 0x{0:X8} ({0})", infoMddf.unknown38);
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown_timestamp = 0x{0:X8} ({0}, {1})",
|
||||
info_mddf.unknown_timestamp,
|
||||
DateHandlers.LisaToDateTime(info_mddf.unknown_timestamp));
|
||||
infoMddf.unknown_timestamp,
|
||||
DateHandlers.LisaToDateTime(infoMddf.unknown_timestamp));
|
||||
|
||||
if(info_mddf.mddf_block != i - before_mddf) return;
|
||||
if(infoMddf.mddf_block != i - beforeMddf) return;
|
||||
|
||||
if(info_mddf.vol_size > imagePlugin.GetSectors()) return;
|
||||
if(infoMddf.vol_size > imagePlugin.GetSectors()) return;
|
||||
|
||||
if(info_mddf.vol_size - 1 != info_mddf.volsize_minus_one) return;
|
||||
if(infoMddf.vol_size - 1 != infoMddf.volsize_minus_one) return;
|
||||
|
||||
if(info_mddf.vol_size - i - 1 != info_mddf.volsize_minus_mddf_minus_one - before_mddf) return;
|
||||
if(infoMddf.vol_size - i - 1 != infoMddf.volsize_minus_mddf_minus_one - beforeMddf) return;
|
||||
|
||||
if(info_mddf.datasize > info_mddf.blocksize) return;
|
||||
if(infoMddf.datasize > infoMddf.blocksize) return;
|
||||
|
||||
if(info_mddf.blocksize < imagePlugin.GetSectorSize()) return;
|
||||
if(infoMddf.blocksize < imagePlugin.GetSectorSize()) return;
|
||||
|
||||
if(info_mddf.datasize != imagePlugin.GetSectorSize()) return;
|
||||
if(infoMddf.datasize != imagePlugin.GetSectorSize()) return;
|
||||
|
||||
switch(info_mddf.fsversion)
|
||||
switch(infoMddf.fsversion)
|
||||
{
|
||||
case LisaFSv1:
|
||||
case LISA_V1:
|
||||
sb.AppendLine("LisaFS v1");
|
||||
break;
|
||||
case LisaFSv2:
|
||||
case LISA_V2:
|
||||
sb.AppendLine("LisaFS v2");
|
||||
break;
|
||||
case LisaFSv3:
|
||||
case LISA_V3:
|
||||
sb.AppendLine("LisaFS v3");
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("Uknown LisaFS version {0}", info_mddf.fsversion).AppendLine();
|
||||
sb.AppendFormat("Uknown LisaFS version {0}", infoMddf.fsversion).AppendLine();
|
||||
break;
|
||||
}
|
||||
|
||||
sb.AppendFormat("Volume name: \"{0}\"", info_mddf.volname).AppendLine();
|
||||
sb.AppendFormat("Volume password: \"{0}\"", info_mddf.password).AppendLine();
|
||||
sb.AppendFormat("Volume ID: 0x{0:X16}", info_mddf.volid).AppendLine();
|
||||
sb.AppendFormat("Backup volume ID: 0x{0:X16}", info_mddf.backup_volid).AppendLine();
|
||||
sb.AppendFormat("Volume name: \"{0}\"", infoMddf.volname).AppendLine();
|
||||
sb.AppendFormat("Volume password: \"{0}\"", infoMddf.password).AppendLine();
|
||||
sb.AppendFormat("Volume ID: 0x{0:X16}", infoMddf.volid).AppendLine();
|
||||
sb.AppendFormat("Backup volume ID: 0x{0:X16}", infoMddf.backup_volid).AppendLine();
|
||||
|
||||
sb.AppendFormat("Master copy ID: 0x{0:X8}", info_mddf.master_copy_id).AppendLine();
|
||||
sb.AppendFormat("Master copy ID: 0x{0:X8}", infoMddf.master_copy_id).AppendLine();
|
||||
|
||||
sb.AppendFormat("Volume is number {0} of {1}", info_mddf.volnum, info_mddf.vol_sequence)
|
||||
sb.AppendFormat("Volume is number {0} of {1}", infoMddf.volnum, infoMddf.vol_sequence)
|
||||
.AppendLine();
|
||||
|
||||
sb.AppendFormat("Serial number of Lisa computer that created this volume: {0}",
|
||||
info_mddf.machine_id).AppendLine();
|
||||
infoMddf.machine_id).AppendLine();
|
||||
sb.AppendFormat("Serial number of Lisa computer that can use this volume's software {0}",
|
||||
info_mddf.serialization).AppendLine();
|
||||
infoMddf.serialization).AppendLine();
|
||||
|
||||
sb.AppendFormat("Volume created on {0}", info_mddf.dtvc).AppendLine();
|
||||
sb.AppendFormat("Some timestamp, says {0}", info_mddf.dtcc).AppendLine();
|
||||
sb.AppendFormat("Volume backed up on {0}", info_mddf.dtvb).AppendLine();
|
||||
sb.AppendFormat("Volume scavenged on {0}", info_mddf.dtvs).AppendLine();
|
||||
sb.AppendFormat("MDDF is in block {0}", info_mddf.mddf_block + before_mddf).AppendLine();
|
||||
sb.AppendFormat("There are {0} reserved blocks before volume", before_mddf).AppendLine();
|
||||
sb.AppendFormat("{0} blocks minus one", info_mddf.volsize_minus_one).AppendLine();
|
||||
sb.AppendFormat("{0} blocks minus one minus MDDF offset", info_mddf.volsize_minus_mddf_minus_one)
|
||||
sb.AppendFormat("Volume created on {0}", infoMddf.dtvc).AppendLine();
|
||||
sb.AppendFormat("Some timestamp, says {0}", infoMddf.dtcc).AppendLine();
|
||||
sb.AppendFormat("Volume backed up on {0}", infoMddf.dtvb).AppendLine();
|
||||
sb.AppendFormat("Volume scavenged on {0}", infoMddf.dtvs).AppendLine();
|
||||
sb.AppendFormat("MDDF is in block {0}", infoMddf.mddf_block + beforeMddf).AppendLine();
|
||||
sb.AppendFormat("There are {0} reserved blocks before volume", beforeMddf).AppendLine();
|
||||
sb.AppendFormat("{0} blocks minus one", infoMddf.volsize_minus_one).AppendLine();
|
||||
sb.AppendFormat("{0} blocks minus one minus MDDF offset", infoMddf.volsize_minus_mddf_minus_one)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("{0} blocks in volume", info_mddf.vol_size).AppendLine();
|
||||
sb.AppendFormat("{0} bytes per sector (uncooked)", info_mddf.blocksize).AppendLine();
|
||||
sb.AppendFormat("{0} bytes per sector", info_mddf.datasize).AppendLine();
|
||||
sb.AppendFormat("{0} blocks per cluster", info_mddf.clustersize).AppendLine();
|
||||
sb.AppendFormat("{0} blocks in filesystem", info_mddf.fs_size).AppendLine();
|
||||
sb.AppendFormat("{0} files in volume", info_mddf.filecount).AppendLine();
|
||||
sb.AppendFormat("{0} blocks free", info_mddf.freecount).AppendLine();
|
||||
sb.AppendFormat("{0} bytes in LisaInfo", info_mddf.label_size).AppendLine();
|
||||
sb.AppendFormat("Filesystem overhead: {0}", info_mddf.fs_overhead).AppendLine();
|
||||
sb.AppendFormat("Scanvenger result code: 0x{0:X8}", info_mddf.result_scavenge).AppendLine();
|
||||
sb.AppendFormat("Boot code: 0x{0:X8}", info_mddf.boot_code).AppendLine();
|
||||
sb.AppendFormat("Boot environment: 0x{0:X8}", info_mddf.boot_environ).AppendLine();
|
||||
sb.AppendFormat("Overmount stamp: 0x{0:X16}", info_mddf.overmount_stamp).AppendLine();
|
||||
sb.AppendFormat("{0} blocks in volume", infoMddf.vol_size).AppendLine();
|
||||
sb.AppendFormat("{0} bytes per sector (uncooked)", infoMddf.blocksize).AppendLine();
|
||||
sb.AppendFormat("{0} bytes per sector", infoMddf.datasize).AppendLine();
|
||||
sb.AppendFormat("{0} blocks per cluster", infoMddf.clustersize).AppendLine();
|
||||
sb.AppendFormat("{0} blocks in filesystem", infoMddf.fs_size).AppendLine();
|
||||
sb.AppendFormat("{0} files in volume", infoMddf.filecount).AppendLine();
|
||||
sb.AppendFormat("{0} blocks free", infoMddf.freecount).AppendLine();
|
||||
sb.AppendFormat("{0} bytes in LisaInfo", infoMddf.label_size).AppendLine();
|
||||
sb.AppendFormat("Filesystem overhead: {0}", infoMddf.fs_overhead).AppendLine();
|
||||
sb.AppendFormat("Scanvenger result code: 0x{0:X8}", infoMddf.result_scavenge).AppendLine();
|
||||
sb.AppendFormat("Boot code: 0x{0:X8}", infoMddf.boot_code).AppendLine();
|
||||
sb.AppendFormat("Boot environment: 0x{0:X8}", infoMddf.boot_environ).AppendLine();
|
||||
sb.AppendFormat("Overmount stamp: 0x{0:X16}", infoMddf.overmount_stamp).AppendLine();
|
||||
sb.AppendFormat("S-Records start at {0} and spans for {1} blocks",
|
||||
info_mddf.srec_ptr + info_mddf.mddf_block + before_mddf, info_mddf.srec_len)
|
||||
infoMddf.srec_ptr + infoMddf.mddf_block + beforeMddf, infoMddf.srec_len)
|
||||
.AppendLine();
|
||||
|
||||
if(info_mddf.vol_left_mounted == 0) sb.AppendLine("Volume is clean");
|
||||
if(infoMddf.vol_left_mounted == 0) sb.AppendLine("Volume is clean");
|
||||
else sb.AppendLine("Volume is dirty");
|
||||
|
||||
information = sb.ToString();
|
||||
|
||||
xmlFSType = new FileSystemType();
|
||||
if(DateTime.Compare(info_mddf.dtvb, DateHandlers.LisaToDateTime(0)) > 0)
|
||||
XmlFsType = new FileSystemType();
|
||||
if(DateTime.Compare(infoMddf.dtvb, DateHandlers.LisaToDateTime(0)) > 0)
|
||||
{
|
||||
xmlFSType.BackupDate = info_mddf.dtvb;
|
||||
xmlFSType.BackupDateSpecified = true;
|
||||
XmlFsType.BackupDate = infoMddf.dtvb;
|
||||
XmlFsType.BackupDateSpecified = true;
|
||||
}
|
||||
xmlFSType.Clusters = info_mddf.vol_size;
|
||||
xmlFSType.ClusterSize = info_mddf.clustersize * info_mddf.datasize;
|
||||
if(DateTime.Compare(info_mddf.dtvc, DateHandlers.LisaToDateTime(0)) > 0)
|
||||
XmlFsType.Clusters = infoMddf.vol_size;
|
||||
XmlFsType.ClusterSize = infoMddf.clustersize * infoMddf.datasize;
|
||||
if(DateTime.Compare(infoMddf.dtvc, DateHandlers.LisaToDateTime(0)) > 0)
|
||||
{
|
||||
xmlFSType.CreationDate = info_mddf.dtvc;
|
||||
xmlFSType.CreationDateSpecified = true;
|
||||
XmlFsType.CreationDate = infoMddf.dtvc;
|
||||
XmlFsType.CreationDateSpecified = true;
|
||||
}
|
||||
xmlFSType.Dirty = info_mddf.vol_left_mounted != 0;
|
||||
xmlFSType.Files = info_mddf.filecount;
|
||||
xmlFSType.FilesSpecified = true;
|
||||
xmlFSType.FreeClusters = info_mddf.freecount;
|
||||
xmlFSType.FreeClustersSpecified = true;
|
||||
xmlFSType.Type = "LisaFS";
|
||||
xmlFSType.VolumeName = info_mddf.volname;
|
||||
xmlFSType.VolumeSerial = $"{info_mddf.volid:X16}";
|
||||
XmlFsType.Dirty = infoMddf.vol_left_mounted != 0;
|
||||
XmlFsType.Files = infoMddf.filecount;
|
||||
XmlFsType.FilesSpecified = true;
|
||||
XmlFsType.FreeClusters = infoMddf.freecount;
|
||||
XmlFsType.FreeClustersSpecified = true;
|
||||
XmlFsType.Type = "LisaFS";
|
||||
XmlFsType.VolumeName = infoMddf.volname;
|
||||
XmlFsType.VolumeSerial = $"{infoMddf.volid:X16}";
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -66,20 +66,20 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
/// <summary>Lists Extents Files already printed in debug mode to not repeat them</summary>
|
||||
List<short> printedExtents;
|
||||
/// <summary>Caches the creation times for subdirectories as to not have to traverse the Catalog File on each stat</summary>
|
||||
Dictionary<short, DateTime> directoryDTCCache;
|
||||
Dictionary<short, DateTime> directoryDtcCache;
|
||||
#endregion Caches
|
||||
|
||||
public LisaFS()
|
||||
{
|
||||
Name = "Apple Lisa File System";
|
||||
PluginUUID = new Guid("7E6034D1-D823-4248-A54D-239742B28391");
|
||||
PluginUuid = new Guid("7E6034D1-D823-4248-A54D-239742B28391");
|
||||
CurrentEncoding = new LisaRoman();
|
||||
}
|
||||
|
||||
public LisaFS(Encoding encoding)
|
||||
{
|
||||
Name = "Apple Lisa File System";
|
||||
PluginUUID = new Guid("7E6034D1-D823-4248-A54D-239742B28391");
|
||||
PluginUuid = new Guid("7E6034D1-D823-4248-A54D-239742B28391");
|
||||
CurrentEncoding = new LisaRoman();
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
{
|
||||
device = imagePlugin;
|
||||
Name = "Apple Lisa File System";
|
||||
PluginUUID = new Guid("7E6034D1-D823-4248-A54D-239742B28391");
|
||||
PluginUuid = new Guid("7E6034D1-D823-4248-A54D-239742B28391");
|
||||
CurrentEncoding = new LisaRoman();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,8 +82,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
// LisaOS searches sectors until tag tells MDDF resides there, so we'll search 100 sectors
|
||||
for(ulong i = 0; i < 100; i++)
|
||||
{
|
||||
LisaTag.PriamTag searchTag;
|
||||
DecodeTag(device.ReadSectorTag(i, SectorTagType.AppleSectorTag), out searchTag);
|
||||
DecodeTag(device.ReadSectorTag(i, SectorTagType.AppleSectorTag), out LisaTag.PriamTag searchTag);
|
||||
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "Sector {0}, file ID 0x{1:X4}", i, searchTag.FileId);
|
||||
|
||||
@@ -97,7 +96,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
byte[] sector = device.ReadSector(i);
|
||||
mddf = new MDDF();
|
||||
byte[] pString = new byte[33];
|
||||
uint lisa_time;
|
||||
uint lisaTime;
|
||||
|
||||
mddf.fsversion = BigEndianBitConverter.ToUInt16(sector, 0x00);
|
||||
mddf.volid = BigEndianBitConverter.ToUInt64(sector, 0x02);
|
||||
@@ -107,19 +106,18 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
mddf.unknown1 = sector[0x2D];
|
||||
Array.Copy(sector, 0x2E, pString, 0, 33);
|
||||
// Prevent garbage
|
||||
if(pString[0] <= 32) mddf.password = StringHandlers.PascalToString(pString, CurrentEncoding);
|
||||
else mddf.password = "";
|
||||
mddf.password = pString[0] <= 32 ? StringHandlers.PascalToString(pString, CurrentEncoding) : "";
|
||||
mddf.unknown2 = sector[0x4F];
|
||||
mddf.machine_id = BigEndianBitConverter.ToUInt32(sector, 0x50);
|
||||
mddf.master_copy_id = BigEndianBitConverter.ToUInt32(sector, 0x54);
|
||||
lisa_time = BigEndianBitConverter.ToUInt32(sector, 0x58);
|
||||
mddf.dtvc = DateHandlers.LisaToDateTime(lisa_time);
|
||||
lisa_time = BigEndianBitConverter.ToUInt32(sector, 0x5C);
|
||||
mddf.dtcc = DateHandlers.LisaToDateTime(lisa_time);
|
||||
lisa_time = BigEndianBitConverter.ToUInt32(sector, 0x60);
|
||||
mddf.dtvb = DateHandlers.LisaToDateTime(lisa_time);
|
||||
lisa_time = BigEndianBitConverter.ToUInt32(sector, 0x64);
|
||||
mddf.dtvs = DateHandlers.LisaToDateTime(lisa_time);
|
||||
lisaTime = BigEndianBitConverter.ToUInt32(sector, 0x58);
|
||||
mddf.dtvc = DateHandlers.LisaToDateTime(lisaTime);
|
||||
lisaTime = BigEndianBitConverter.ToUInt32(sector, 0x5C);
|
||||
mddf.dtcc = DateHandlers.LisaToDateTime(lisaTime);
|
||||
lisaTime = BigEndianBitConverter.ToUInt32(sector, 0x60);
|
||||
mddf.dtvb = DateHandlers.LisaToDateTime(lisaTime);
|
||||
lisaTime = BigEndianBitConverter.ToUInt32(sector, 0x64);
|
||||
mddf.dtvs = DateHandlers.LisaToDateTime(lisaTime);
|
||||
mddf.unknown3 = BigEndianBitConverter.ToUInt32(sector, 0x68);
|
||||
mddf.mddf_block = BigEndianBitConverter.ToUInt32(sector, 0x6C);
|
||||
mddf.volsize_minus_one = BigEndianBitConverter.ToUInt32(sector, 0x70);
|
||||
@@ -193,13 +191,13 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
// Check MDDF version
|
||||
switch(mddf.fsversion)
|
||||
{
|
||||
case LisaFSv1:
|
||||
case LISA_V1:
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "Mounting LisaFS v1");
|
||||
break;
|
||||
case LisaFSv2:
|
||||
case LISA_V2:
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "Mounting LisaFS v2");
|
||||
break;
|
||||
case LisaFSv3:
|
||||
case LISA_V3:
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "Mounting LisaFS v3");
|
||||
break;
|
||||
default:
|
||||
@@ -214,23 +212,20 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
//catalogCache = new Dictionary<short, List<CatalogEntry>>();
|
||||
fileSizeCache = new Dictionary<short, int>();
|
||||
|
||||
Errno error;
|
||||
|
||||
mounted = true;
|
||||
this.debug = debug;
|
||||
|
||||
if(debug) printedExtents = new List<short>();
|
||||
|
||||
// Read the S-Records file
|
||||
error = ReadSRecords();
|
||||
Errno error = ReadSRecords();
|
||||
if(error != Errno.NoError)
|
||||
{
|
||||
DicConsole.ErrorWriteLine("Error {0} reading S-Records file.", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
directoryDTCCache = new Dictionary<short, DateTime>();
|
||||
directoryDTCCache.Add(DIRID_ROOT, mddf.dtcc);
|
||||
directoryDtcCache = new Dictionary<short, DateTime> {{DIRID_ROOT, mddf.dtcc}};
|
||||
|
||||
// Read the Catalog File
|
||||
error = ReadCatalog();
|
||||
@@ -246,9 +241,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
// If debug, cache system files
|
||||
if(debug)
|
||||
{
|
||||
byte[] temp;
|
||||
|
||||
error = ReadSystemFile(FILEID_BOOT_SIGNED, out temp);
|
||||
error = ReadSystemFile(FILEID_BOOT_SIGNED, out _);
|
||||
if(error != Errno.NoError)
|
||||
{
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "Unable to read boot blocks");
|
||||
@@ -256,7 +249,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
return error;
|
||||
}
|
||||
|
||||
error = ReadSystemFile(FILEID_LOADER_SIGNED, out temp);
|
||||
error = ReadSystemFile(FILEID_LOADER_SIGNED, out _);
|
||||
if(error != Errno.NoError)
|
||||
{
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "Unable to read boot loader");
|
||||
@@ -264,7 +257,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
return error;
|
||||
}
|
||||
|
||||
error = ReadSystemFile((short)FILEID_MDDF, out temp);
|
||||
error = ReadSystemFile((short)FILEID_MDDF, out _);
|
||||
if(error != Errno.NoError)
|
||||
{
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "Unable to read MDDF");
|
||||
@@ -272,7 +265,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
return error;
|
||||
}
|
||||
|
||||
error = ReadSystemFile((short)FILEID_BITMAP, out temp);
|
||||
error = ReadSystemFile((short)FILEID_BITMAP, out _);
|
||||
if(error != Errno.NoError)
|
||||
{
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "Unable to read volume bitmap");
|
||||
@@ -280,7 +273,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
return error;
|
||||
}
|
||||
|
||||
error = ReadSystemFile((short)FILEID_SRECORD, out temp);
|
||||
error = ReadSystemFile((short)FILEID_SRECORD, out _);
|
||||
if(error != Errno.NoError)
|
||||
{
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "Unable to read S-Records file");
|
||||
@@ -290,27 +283,27 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
}
|
||||
|
||||
// Create XML metadata for mounted filesystem
|
||||
xmlFSType = new FileSystemType();
|
||||
XmlFsType = new FileSystemType();
|
||||
if(DateTime.Compare(mddf.dtvb, DateHandlers.LisaToDateTime(0)) > 0)
|
||||
{
|
||||
xmlFSType.BackupDate = mddf.dtvb;
|
||||
xmlFSType.BackupDateSpecified = true;
|
||||
XmlFsType.BackupDate = mddf.dtvb;
|
||||
XmlFsType.BackupDateSpecified = true;
|
||||
}
|
||||
xmlFSType.Clusters = mddf.vol_size;
|
||||
xmlFSType.ClusterSize = mddf.clustersize * mddf.datasize;
|
||||
XmlFsType.Clusters = mddf.vol_size;
|
||||
XmlFsType.ClusterSize = mddf.clustersize * mddf.datasize;
|
||||
if(DateTime.Compare(mddf.dtvc, DateHandlers.LisaToDateTime(0)) > 0)
|
||||
{
|
||||
xmlFSType.CreationDate = mddf.dtvc;
|
||||
xmlFSType.CreationDateSpecified = true;
|
||||
XmlFsType.CreationDate = mddf.dtvc;
|
||||
XmlFsType.CreationDateSpecified = true;
|
||||
}
|
||||
xmlFSType.Dirty = mddf.vol_left_mounted != 0;
|
||||
xmlFSType.Files = mddf.filecount;
|
||||
xmlFSType.FilesSpecified = true;
|
||||
xmlFSType.FreeClusters = mddf.freecount;
|
||||
xmlFSType.FreeClustersSpecified = true;
|
||||
xmlFSType.Type = "LisaFS";
|
||||
xmlFSType.VolumeName = mddf.volname;
|
||||
xmlFSType.VolumeSerial = $"{mddf.volid:X16}";
|
||||
XmlFsType.Dirty = mddf.vol_left_mounted != 0;
|
||||
XmlFsType.Files = mddf.filecount;
|
||||
XmlFsType.FilesSpecified = true;
|
||||
XmlFsType.FreeClusters = mddf.freecount;
|
||||
XmlFsType.FreeClustersSpecified = true;
|
||||
XmlFsType.Type = "LisaFS";
|
||||
XmlFsType.VolumeName = mddf.volname;
|
||||
XmlFsType.VolumeSerial = $"{mddf.volid:X16}";
|
||||
|
||||
return Errno.NoError;
|
||||
}
|
||||
@@ -353,24 +346,25 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
{
|
||||
if(!mounted) return Errno.AccessDenied;
|
||||
|
||||
stat = new FileSystemInfo();
|
||||
stat.Blocks = mddf.vol_size;
|
||||
stat.FilenameLength = (ushort)E_NAME;
|
||||
stat.Files = mddf.filecount;
|
||||
stat.FreeBlocks = mddf.freecount;
|
||||
stat = new FileSystemInfo
|
||||
{
|
||||
Blocks = mddf.vol_size,
|
||||
FilenameLength = (ushort)E_NAME,
|
||||
Files = mddf.filecount,
|
||||
FreeBlocks = mddf.freecount,
|
||||
Id = {Serial64 = mddf.volid, IsLong = true},
|
||||
PluginId = PluginUuid
|
||||
};
|
||||
stat.FreeFiles = FILEID_MAX - stat.Files;
|
||||
stat.Id.Serial64 = mddf.volid;
|
||||
stat.Id.IsLong = true;
|
||||
stat.PluginId = PluginUUID;
|
||||
switch(mddf.fsversion)
|
||||
{
|
||||
case LisaFSv1:
|
||||
case LISA_V1:
|
||||
stat.Type = "LisaFS v1";
|
||||
break;
|
||||
case LisaFSv2:
|
||||
case LISA_V2:
|
||||
stat.Type = "LisaFS v2";
|
||||
break;
|
||||
case LisaFSv3:
|
||||
case LISA_V3:
|
||||
stat.Type = "LisaFS v3";
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -48,9 +48,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
/// <param name="xattrs">List of extended attributes, alternate data streams and forks.</param>
|
||||
public override Errno ListXAttr(string path, ref List<string> xattrs)
|
||||
{
|
||||
short fileId;
|
||||
bool isDir;
|
||||
Errno error = LookupFileId(path, out fileId, out isDir);
|
||||
Errno error = LookupFileId(path, out short fileId, out bool isDir);
|
||||
if(error != Errno.NoError) return error;
|
||||
|
||||
return isDir ? Errno.InvalidArgument : ListXAttr(fileId, ref xattrs);
|
||||
@@ -65,9 +63,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
/// <param name="buf">Buffer.</param>
|
||||
public override Errno GetXattr(string path, string xattr, ref byte[] buf)
|
||||
{
|
||||
short fileId;
|
||||
bool isDir;
|
||||
Errno error = LookupFileId(path, out fileId, out isDir);
|
||||
Errno error = LookupFileId(path, out short fileId, out bool isDir);
|
||||
if(error != Errno.NoError) return error;
|
||||
|
||||
return isDir ? Errno.InvalidArgument : GetXattr(fileId, xattr, out buf);
|
||||
@@ -104,8 +100,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
else
|
||||
{
|
||||
// Search for the file
|
||||
ExtentFile file;
|
||||
Errno error = ReadExtentsFile(fileId, out file);
|
||||
Errno error = ReadExtentsFile(fileId, out ExtentFile file);
|
||||
|
||||
if(error != Errno.NoError) return error;
|
||||
|
||||
@@ -162,8 +157,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
}
|
||||
|
||||
// Search for the file
|
||||
ExtentFile file;
|
||||
Errno error = ReadExtentsFile(fileId, out file);
|
||||
Errno error = ReadExtentsFile(fileId, out ExtentFile file);
|
||||
|
||||
if(error != Errno.NoError) return error;
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using DiscImageChef.CommonTypes;
|
||||
@@ -55,6 +56,8 @@ using time_t = System.Int32;
|
||||
|
||||
namespace DiscImageChef.Filesystems
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "BuiltInTypeReferenceStyle")]
|
||||
public class Locus : Filesystem
|
||||
{
|
||||
const int NICINOD = 325;
|
||||
@@ -195,24 +198,22 @@ namespace DiscImageChef.Filesystems
|
||||
public Locus()
|
||||
{
|
||||
Name = "Locus Filesystem Plugin";
|
||||
PluginUUID = new Guid("1A70B30A-437D-479A-88E1-D0C9C1797FF4");
|
||||
PluginUuid = new Guid("1A70B30A-437D-479A-88E1-D0C9C1797FF4");
|
||||
CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public Locus(Encoding encoding)
|
||||
{
|
||||
Name = "Locus Filesystem Plugin";
|
||||
PluginUUID = new Guid("1A70B30A-437D-479A-88E1-D0C9C1797FF4");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("1A70B30A-437D-479A-88E1-D0C9C1797FF4");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public Locus(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "Locus Filesystem Plugin";
|
||||
PluginUUID = new Guid("1A70B30A-437D-479A-88E1-D0C9C1797FF4");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("1A70B30A-437D-479A-88E1-D0C9C1797FF4");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugin imagePlugin, Partition partition)
|
||||
@@ -284,12 +285,9 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if(LocusSb.s_magic == Locus_OldMagic) sb.AppendLine("Locus filesystem (old)");
|
||||
else sb.AppendLine("Locus filesystem");
|
||||
sb.AppendLine(LocusSb.s_magic == Locus_OldMagic ? "Locus filesystem (old)" : "Locus filesystem");
|
||||
|
||||
int blockSize;
|
||||
if(LocusSb.s_version == LocusVersion.SB_SB4096) blockSize = 4096;
|
||||
else blockSize = 1024;
|
||||
int blockSize = LocusSb.s_version == LocusVersion.SB_SB4096 ? 4096 : 1024;
|
||||
|
||||
string s_fsmnt = StringHandlers.CToString(LocusSb.s_fsmnt, CurrentEncoding);
|
||||
string s_fpack = StringHandlers.CToString(LocusSb.s_fpack, CurrentEncoding);
|
||||
@@ -345,7 +343,7 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
information = sb.ToString();
|
||||
|
||||
xmlFSType = new FileSystemType
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
Type = "Locus filesystem",
|
||||
ClusterSize = blockSize,
|
||||
|
||||
@@ -44,30 +44,28 @@ namespace DiscImageChef.Filesystems
|
||||
// Thanks to tarlabnor for translating it
|
||||
public class MicroDOS : Filesystem
|
||||
{
|
||||
const ushort magic = 0xA72E;
|
||||
const ushort magic2 = 0x530C;
|
||||
const ushort MAGIC = 0xA72E;
|
||||
const ushort MAGIC2 = 0x530C;
|
||||
|
||||
public MicroDOS()
|
||||
{
|
||||
Name = "MicroDOS file system";
|
||||
PluginUUID = new Guid("9F9A364A-1A27-48A3-B730-7A7122000324");
|
||||
PluginUuid = new Guid("9F9A364A-1A27-48A3-B730-7A7122000324");
|
||||
CurrentEncoding = Encoding.GetEncoding("koi8-r");
|
||||
}
|
||||
|
||||
public MicroDOS(Encoding encoding)
|
||||
{
|
||||
Name = "MicroDOS file system";
|
||||
PluginUUID = new Guid("9F9A364A-1A27-48A3-B730-7A7122000324");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("koi8-r");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("9F9A364A-1A27-48A3-B730-7A7122000324");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("koi8-r");
|
||||
}
|
||||
|
||||
public MicroDOS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "MicroDOS file system";
|
||||
PluginUUID = new Guid("9F9A364A-1A27-48A3-B730-7A7122000324");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("koi8-r");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("9F9A364A-1A27-48A3-B730-7A7122000324");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("koi8-r");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugin imagePlugin, Partition partition)
|
||||
@@ -76,15 +74,13 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
if(imagePlugin.GetSectorSize() < 512) return false;
|
||||
|
||||
MicroDOSBlock0 block0;
|
||||
|
||||
byte[] bk0 = imagePlugin.ReadSector(0 + partition.Start);
|
||||
|
||||
GCHandle handle = GCHandle.Alloc(bk0, GCHandleType.Pinned);
|
||||
block0 = (MicroDOSBlock0)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(MicroDOSBlock0));
|
||||
MicroDOSBlock0 block0 = (MicroDOSBlock0)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(MicroDOSBlock0));
|
||||
handle.Free();
|
||||
|
||||
return block0.label == magic && block0.mklabel == magic2;
|
||||
return block0.label == MAGIC && block0.mklabel == MAGIC2;
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
|
||||
@@ -93,12 +89,11 @@ namespace DiscImageChef.Filesystems
|
||||
information = "";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
MicroDOSBlock0 block0;
|
||||
|
||||
byte[] bk0 = imagePlugin.ReadSector(0 + partition.Start);
|
||||
|
||||
GCHandle handle = GCHandle.Alloc(bk0, GCHandleType.Pinned);
|
||||
block0 = (MicroDOSBlock0)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(MicroDOSBlock0));
|
||||
MicroDOSBlock0 block0 = (MicroDOSBlock0)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(MicroDOSBlock0));
|
||||
handle.Free();
|
||||
|
||||
sb.AppendLine("MicroDOS filesystem");
|
||||
@@ -108,7 +103,7 @@ namespace DiscImageChef.Filesystems
|
||||
sb.AppendFormat("Volume contains {0} files", block0.files).AppendLine();
|
||||
sb.AppendFormat("First used block is {0}", block0.firstUsedBlock).AppendLine();
|
||||
|
||||
xmlFSType = new FileSystemType
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
Type = "MicroDOS",
|
||||
ClusterSize = 512,
|
||||
|
||||
@@ -68,24 +68,22 @@ namespace DiscImageChef.Filesystems
|
||||
public MinixFS()
|
||||
{
|
||||
Name = "Minix Filesystem";
|
||||
PluginUUID = new Guid("FE248C3B-B727-4AE5-A39F-79EA9A07D4B3");
|
||||
PluginUuid = new Guid("FE248C3B-B727-4AE5-A39F-79EA9A07D4B3");
|
||||
CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public MinixFS(Encoding encoding)
|
||||
{
|
||||
Name = "Minix Filesystem";
|
||||
PluginUUID = new Guid("FE248C3B-B727-4AE5-A39F-79EA9A07D4B3");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("FE248C3B-B727-4AE5-A39F-79EA9A07D4B3");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public MinixFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "Minix Filesystem";
|
||||
PluginUUID = new Guid("FE248C3B-B727-4AE5-A39F-79EA9A07D4B3");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("FE248C3B-B727-4AE5-A39F-79EA9A07D4B3");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugin imagePlugin, Partition partition)
|
||||
@@ -102,23 +100,23 @@ namespace DiscImageChef.Filesystems
|
||||
if(sector + partition.Start >= partition.End) return false;
|
||||
|
||||
ushort magic;
|
||||
byte[] minix_sb_sector = imagePlugin.ReadSector(sector + partition.Start);
|
||||
byte[] minixSbSector = imagePlugin.ReadSector(sector + partition.Start);
|
||||
|
||||
// Optical media
|
||||
if(offset > 0)
|
||||
{
|
||||
byte[] tmp = new byte[0x200];
|
||||
Array.Copy(minix_sb_sector, offset, tmp, 0, 0x200);
|
||||
minix_sb_sector = tmp;
|
||||
Array.Copy(minixSbSector, offset, tmp, 0, 0x200);
|
||||
minixSbSector = tmp;
|
||||
}
|
||||
|
||||
magic = BitConverter.ToUInt16(minix_sb_sector, 0x010); // Here should reside magic number on Minix v1 & V2
|
||||
magic = BitConverter.ToUInt16(minixSbSector, 0x010); // Here should reside magic number on Minix v1 & V2
|
||||
|
||||
if(magic == MINIX_MAGIC || magic == MINIX_MAGIC2 || magic == MINIX2_MAGIC || magic == MINIX2_MAGIC2 ||
|
||||
magic == MINIX_CIGAM || magic == MINIX_CIGAM2 || magic == MINIX2_CIGAM ||
|
||||
magic == MINIX2_CIGAM2) return true;
|
||||
|
||||
magic = BitConverter.ToUInt16(minix_sb_sector, 0x018); // Here should reside magic number on Minix v3
|
||||
magic = BitConverter.ToUInt16(minixSbSector, 0x018); // Here should reside magic number on Minix v3
|
||||
|
||||
if(magic == MINIX_MAGIC || magic == MINIX2_MAGIC || magic == MINIX3_MAGIC || magic == MINIX_CIGAM ||
|
||||
magic == MINIX2_CIGAM || magic == MINIX3_CIGAM) return true;
|
||||
@@ -146,19 +144,19 @@ namespace DiscImageChef.Filesystems
|
||||
int filenamesize;
|
||||
string minixVersion;
|
||||
ushort magic;
|
||||
byte[] minix_sb_sector = imagePlugin.ReadSector(sector + partition.Start);
|
||||
byte[] minixSbSector = imagePlugin.ReadSector(sector + partition.Start);
|
||||
|
||||
// Optical media
|
||||
if(offset > 0)
|
||||
{
|
||||
byte[] tmp = new byte[0x200];
|
||||
Array.Copy(minix_sb_sector, offset, tmp, 0, 0x200);
|
||||
minix_sb_sector = tmp;
|
||||
Array.Copy(minixSbSector, offset, tmp, 0, 0x200);
|
||||
minixSbSector = tmp;
|
||||
}
|
||||
|
||||
magic = BitConverter.ToUInt16(minix_sb_sector, 0x018);
|
||||
magic = BitConverter.ToUInt16(minixSbSector, 0x018);
|
||||
|
||||
xmlFSType = new FileSystemType();
|
||||
XmlFsType = new FileSystemType();
|
||||
|
||||
bool littleEndian;
|
||||
|
||||
@@ -172,16 +170,16 @@ namespace DiscImageChef.Filesystems
|
||||
case MINIX3_MAGIC:
|
||||
case MINIX3_CIGAM:
|
||||
minixVersion = "Minix v3 filesystem";
|
||||
xmlFSType.Type = "Minix v3";
|
||||
XmlFsType.Type = "Minix v3";
|
||||
break;
|
||||
case MINIX2_MAGIC:
|
||||
case MINIX2_CIGAM:
|
||||
minixVersion = "Minix 3 v2 filesystem";
|
||||
xmlFSType.Type = "Minix 3 v2";
|
||||
XmlFsType.Type = "Minix 3 v2";
|
||||
break;
|
||||
default:
|
||||
minixVersion = "Minix 3 v1 filesystem";
|
||||
xmlFSType.Type = "Minix 3 v1";
|
||||
XmlFsType.Type = "Minix 3 v1";
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -189,7 +187,7 @@ namespace DiscImageChef.Filesystems
|
||||
}
|
||||
else
|
||||
{
|
||||
magic = BitConverter.ToUInt16(minix_sb_sector, 0x010);
|
||||
magic = BitConverter.ToUInt16(minixSbSector, 0x010);
|
||||
|
||||
switch(magic)
|
||||
{
|
||||
@@ -197,49 +195,49 @@ namespace DiscImageChef.Filesystems
|
||||
filenamesize = 14;
|
||||
minixVersion = "Minix v1 filesystem";
|
||||
littleEndian = true;
|
||||
xmlFSType.Type = "Minix v1";
|
||||
XmlFsType.Type = "Minix v1";
|
||||
break;
|
||||
case MINIX_MAGIC2:
|
||||
filenamesize = 30;
|
||||
minixVersion = "Minix v1 filesystem";
|
||||
littleEndian = true;
|
||||
xmlFSType.Type = "Minix v1";
|
||||
XmlFsType.Type = "Minix v1";
|
||||
break;
|
||||
case MINIX2_MAGIC:
|
||||
filenamesize = 14;
|
||||
minixVersion = "Minix v2 filesystem";
|
||||
littleEndian = true;
|
||||
xmlFSType.Type = "Minix v2";
|
||||
XmlFsType.Type = "Minix v2";
|
||||
break;
|
||||
case MINIX2_MAGIC2:
|
||||
filenamesize = 30;
|
||||
minixVersion = "Minix v2 filesystem";
|
||||
littleEndian = true;
|
||||
xmlFSType.Type = "Minix v2";
|
||||
XmlFsType.Type = "Minix v2";
|
||||
break;
|
||||
case MINIX_CIGAM:
|
||||
filenamesize = 14;
|
||||
minixVersion = "Minix v1 filesystem";
|
||||
littleEndian = false;
|
||||
xmlFSType.Type = "Minix v1";
|
||||
XmlFsType.Type = "Minix v1";
|
||||
break;
|
||||
case MINIX_CIGAM2:
|
||||
filenamesize = 30;
|
||||
minixVersion = "Minix v1 filesystem";
|
||||
littleEndian = false;
|
||||
xmlFSType.Type = "Minix v1";
|
||||
XmlFsType.Type = "Minix v1";
|
||||
break;
|
||||
case MINIX2_CIGAM:
|
||||
filenamesize = 14;
|
||||
minixVersion = "Minix v2 filesystem";
|
||||
littleEndian = false;
|
||||
xmlFSType.Type = "Minix v2";
|
||||
XmlFsType.Type = "Minix v2";
|
||||
break;
|
||||
case MINIX2_CIGAM2:
|
||||
filenamesize = 30;
|
||||
minixVersion = "Minix v2 filesystem";
|
||||
littleEndian = false;
|
||||
xmlFSType.Type = "Minix v2";
|
||||
XmlFsType.Type = "Minix v2";
|
||||
break;
|
||||
default: return;
|
||||
}
|
||||
@@ -247,75 +245,73 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
if(minix3)
|
||||
{
|
||||
Minix3SuperBlock mnx_sb;
|
||||
Minix3SuperBlock mnxSb;
|
||||
|
||||
if(littleEndian)
|
||||
{
|
||||
GCHandle handle = GCHandle.Alloc(minix_sb_sector, GCHandleType.Pinned);
|
||||
mnx_sb = (Minix3SuperBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),
|
||||
GCHandle handle = GCHandle.Alloc(minixSbSector, GCHandleType.Pinned);
|
||||
mnxSb = (Minix3SuperBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),
|
||||
typeof(Minix3SuperBlock));
|
||||
handle.Free();
|
||||
}
|
||||
else mnx_sb = BigEndianMarshal.ByteArrayToStructureBigEndian<Minix3SuperBlock>(minix_sb_sector);
|
||||
else mnxSb = BigEndianMarshal.ByteArrayToStructureBigEndian<Minix3SuperBlock>(minixSbSector);
|
||||
|
||||
if(magic != MINIX3_MAGIC && magic != MINIX3_CIGAM) mnx_sb.s_blocksize = 1024;
|
||||
if(magic != MINIX3_MAGIC && magic != MINIX3_CIGAM) mnxSb.s_blocksize = 1024;
|
||||
|
||||
sb.AppendLine(minixVersion);
|
||||
sb.AppendFormat("{0} chars in filename", filenamesize).AppendLine();
|
||||
if(mnx_sb.s_zones > 0) // On V2
|
||||
sb.AppendFormat("{0} zones on volume ({1} bytes)", mnx_sb.s_zones, mnx_sb.s_zones * 1024)
|
||||
if(mnxSb.s_zones > 0) // On V2
|
||||
sb.AppendFormat("{0} zones on volume ({1} bytes)", mnxSb.s_zones, mnxSb.s_zones * 1024)
|
||||
.AppendLine();
|
||||
else
|
||||
sb.AppendFormat("{0} zones on volume ({1} bytes)", mnx_sb.s_nzones, mnx_sb.s_nzones * 1024)
|
||||
sb.AppendFormat("{0} zones on volume ({1} bytes)", mnxSb.s_nzones, mnxSb.s_nzones * 1024)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("{0} bytes/block", mnx_sb.s_blocksize).AppendLine();
|
||||
sb.AppendFormat("{0} inodes on volume", mnx_sb.s_ninodes).AppendLine();
|
||||
sb.AppendFormat("{0} blocks on inode map ({1} bytes)", mnx_sb.s_imap_blocks,
|
||||
mnx_sb.s_imap_blocks * mnx_sb.s_blocksize).AppendLine();
|
||||
sb.AppendFormat("{0} blocks on zone map ({1} bytes)", mnx_sb.s_zmap_blocks,
|
||||
mnx_sb.s_zmap_blocks * mnx_sb.s_blocksize).AppendLine();
|
||||
sb.AppendFormat("First data zone: {0}", mnx_sb.s_firstdatazone).AppendLine();
|
||||
sb.AppendFormat("{0} bytes/block", mnxSb.s_blocksize).AppendLine();
|
||||
sb.AppendFormat("{0} inodes on volume", mnxSb.s_ninodes).AppendLine();
|
||||
sb.AppendFormat("{0} blocks on inode map ({1} bytes)", mnxSb.s_imap_blocks,
|
||||
mnxSb.s_imap_blocks * mnxSb.s_blocksize).AppendLine();
|
||||
sb.AppendFormat("{0} blocks on zone map ({1} bytes)", mnxSb.s_zmap_blocks,
|
||||
mnxSb.s_zmap_blocks * mnxSb.s_blocksize).AppendLine();
|
||||
sb.AppendFormat("First data zone: {0}", mnxSb.s_firstdatazone).AppendLine();
|
||||
//sb.AppendFormat("log2 of blocks/zone: {0}", mnx_sb.s_log_zone_size).AppendLine(); // Apparently 0
|
||||
sb.AppendFormat("{0} bytes maximum per file", mnx_sb.s_max_size).AppendLine();
|
||||
sb.AppendFormat("On-disk filesystem version: {0}", mnx_sb.s_disk_version).AppendLine();
|
||||
sb.AppendFormat("{0} bytes maximum per file", mnxSb.s_max_size).AppendLine();
|
||||
sb.AppendFormat("On-disk filesystem version: {0}", mnxSb.s_disk_version).AppendLine();
|
||||
|
||||
xmlFSType.ClusterSize = mnx_sb.s_blocksize;
|
||||
if(mnx_sb.s_zones > 0) xmlFSType.Clusters = mnx_sb.s_zones;
|
||||
else xmlFSType.Clusters = mnx_sb.s_nzones;
|
||||
XmlFsType.ClusterSize = mnxSb.s_blocksize;
|
||||
XmlFsType.Clusters = mnxSb.s_zones > 0 ? mnxSb.s_zones : mnxSb.s_nzones;
|
||||
}
|
||||
else
|
||||
{
|
||||
MinixSuperBlock mnx_sb;
|
||||
MinixSuperBlock mnxSb;
|
||||
|
||||
if(littleEndian)
|
||||
{
|
||||
GCHandle handle = GCHandle.Alloc(minix_sb_sector, GCHandleType.Pinned);
|
||||
mnx_sb = (MinixSuperBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),
|
||||
GCHandle handle = GCHandle.Alloc(minixSbSector, GCHandleType.Pinned);
|
||||
mnxSb = (MinixSuperBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),
|
||||
typeof(MinixSuperBlock));
|
||||
handle.Free();
|
||||
}
|
||||
else mnx_sb = BigEndianMarshal.ByteArrayToStructureBigEndian<MinixSuperBlock>(minix_sb_sector);
|
||||
else mnxSb = BigEndianMarshal.ByteArrayToStructureBigEndian<MinixSuperBlock>(minixSbSector);
|
||||
|
||||
sb.AppendLine(minixVersion);
|
||||
sb.AppendFormat("{0} chars in filename", filenamesize).AppendLine();
|
||||
if(mnx_sb.s_zones > 0) // On V2
|
||||
sb.AppendFormat("{0} zones on volume ({1} bytes)", mnx_sb.s_zones, mnx_sb.s_zones * 1024)
|
||||
if(mnxSb.s_zones > 0) // On V2
|
||||
sb.AppendFormat("{0} zones on volume ({1} bytes)", mnxSb.s_zones, mnxSb.s_zones * 1024)
|
||||
.AppendLine();
|
||||
else
|
||||
sb.AppendFormat("{0} zones on volume ({1} bytes)", mnx_sb.s_nzones, mnx_sb.s_nzones * 1024)
|
||||
sb.AppendFormat("{0} zones on volume ({1} bytes)", mnxSb.s_nzones, mnxSb.s_nzones * 1024)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("{0} inodes on volume", mnx_sb.s_ninodes).AppendLine();
|
||||
sb.AppendFormat("{0} blocks on inode map ({1} bytes)", mnx_sb.s_imap_blocks,
|
||||
mnx_sb.s_imap_blocks * 1024).AppendLine();
|
||||
sb.AppendFormat("{0} blocks on zone map ({1} bytes)", mnx_sb.s_zmap_blocks, mnx_sb.s_zmap_blocks * 1024)
|
||||
sb.AppendFormat("{0} inodes on volume", mnxSb.s_ninodes).AppendLine();
|
||||
sb.AppendFormat("{0} blocks on inode map ({1} bytes)", mnxSb.s_imap_blocks,
|
||||
mnxSb.s_imap_blocks * 1024).AppendLine();
|
||||
sb.AppendFormat("{0} blocks on zone map ({1} bytes)", mnxSb.s_zmap_blocks, mnxSb.s_zmap_blocks * 1024)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("First data zone: {0}", mnx_sb.s_firstdatazone).AppendLine();
|
||||
sb.AppendFormat("First data zone: {0}", mnxSb.s_firstdatazone).AppendLine();
|
||||
//sb.AppendFormat("log2 of blocks/zone: {0}", mnx_sb.s_log_zone_size).AppendLine(); // Apparently 0
|
||||
sb.AppendFormat("{0} bytes maximum per file", mnx_sb.s_max_size).AppendLine();
|
||||
sb.AppendFormat("Filesystem state: {0:X4}", mnx_sb.s_state).AppendLine();
|
||||
xmlFSType.ClusterSize = 1024;
|
||||
if(mnx_sb.s_zones > 0) xmlFSType.Clusters = mnx_sb.s_zones;
|
||||
else xmlFSType.Clusters = mnx_sb.s_nzones;
|
||||
sb.AppendFormat("{0} bytes maximum per file", mnxSb.s_max_size).AppendLine();
|
||||
sb.AppendFormat("Filesystem state: {0:X4}", mnxSb.s_state).AppendLine();
|
||||
XmlFsType.ClusterSize = 1024;
|
||||
XmlFsType.Clusters = mnxSb.s_zones > 0 ? mnxSb.s_zones : mnxSb.s_nzones;
|
||||
}
|
||||
information = sb.ToString();
|
||||
}
|
||||
|
||||
@@ -95,37 +95,35 @@ namespace DiscImageChef.Filesystems
|
||||
public ulong feature_incompat;
|
||||
}
|
||||
|
||||
const ushort NILFS2_Magic = 0x3434;
|
||||
const uint NILFS2_SuperOffset = 1024;
|
||||
const ushort NILFS2_MAGIC = 0x3434;
|
||||
const uint NILFS2_SUPER_OFFSET = 1024;
|
||||
|
||||
public NILFS2()
|
||||
{
|
||||
Name = "NILFS2 Plugin";
|
||||
PluginUUID = new Guid("35224226-C5CC-48B5-8FFD-3781E91E86B6");
|
||||
PluginUuid = new Guid("35224226-C5CC-48B5-8FFD-3781E91E86B6");
|
||||
CurrentEncoding = Encoding.UTF8;
|
||||
}
|
||||
|
||||
public NILFS2(Encoding encoding)
|
||||
{
|
||||
Name = "NILFS2 Plugin";
|
||||
PluginUUID = new Guid("35224226-C5CC-48B5-8FFD-3781E91E86B6");
|
||||
if(encoding == null) CurrentEncoding = Encoding.UTF8;
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("35224226-C5CC-48B5-8FFD-3781E91E86B6");
|
||||
CurrentEncoding = encoding ?? Encoding.UTF8;
|
||||
}
|
||||
|
||||
public NILFS2(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "NILFS2 Plugin";
|
||||
PluginUUID = new Guid("35224226-C5CC-48B5-8FFD-3781E91E86B6");
|
||||
if(encoding == null) CurrentEncoding = Encoding.UTF8;
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("35224226-C5CC-48B5-8FFD-3781E91E86B6");
|
||||
CurrentEncoding = encoding ?? Encoding.UTF8;
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugin imagePlugin, Partition partition)
|
||||
{
|
||||
if(imagePlugin.GetSectorSize() < 512) return false;
|
||||
|
||||
uint sbAddr = NILFS2_SuperOffset / imagePlugin.GetSectorSize();
|
||||
uint sbAddr = NILFS2_SUPER_OFFSET / imagePlugin.GetSectorSize();
|
||||
if(sbAddr == 0) sbAddr = 1;
|
||||
|
||||
NILFS2_Superblock nilfsSb = new NILFS2_Superblock();
|
||||
@@ -143,7 +141,7 @@ namespace DiscImageChef.Filesystems
|
||||
nilfsSb = (NILFS2_Superblock)Marshal.PtrToStructure(sbPtr, typeof(NILFS2_Superblock));
|
||||
Marshal.FreeHGlobal(sbPtr);
|
||||
|
||||
return nilfsSb.magic == NILFS2_Magic;
|
||||
return nilfsSb.magic == NILFS2_MAGIC;
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
|
||||
@@ -152,7 +150,7 @@ namespace DiscImageChef.Filesystems
|
||||
information = "";
|
||||
if(imagePlugin.GetSectorSize() < 512) return;
|
||||
|
||||
uint sbAddr = NILFS2_SuperOffset / imagePlugin.GetSectorSize();
|
||||
uint sbAddr = NILFS2_SUPER_OFFSET / imagePlugin.GetSectorSize();
|
||||
if(sbAddr == 0) sbAddr = 1;
|
||||
|
||||
NILFS2_Superblock nilfsSb = new NILFS2_Superblock();
|
||||
@@ -168,7 +166,7 @@ namespace DiscImageChef.Filesystems
|
||||
nilfsSb = (NILFS2_Superblock)Marshal.PtrToStructure(sbPtr, typeof(NILFS2_Superblock));
|
||||
Marshal.FreeHGlobal(sbPtr);
|
||||
|
||||
if(nilfsSb.magic != NILFS2_Magic) return;
|
||||
if(nilfsSb.magic != NILFS2_MAGIC) return;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
@@ -192,17 +190,19 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
information = sb.ToString();
|
||||
|
||||
xmlFSType = new FileSystemType();
|
||||
xmlFSType.Type = "NILFS2 filesystem";
|
||||
if(nilfsSb.creator_os == 0) xmlFSType.SystemIdentifier = "Linux";
|
||||
xmlFSType.ClusterSize = 1 << (int)(nilfsSb.log_block_size + 10);
|
||||
xmlFSType.Clusters = (long)nilfsSb.dev_size / xmlFSType.ClusterSize;
|
||||
xmlFSType.VolumeName = StringHandlers.CToString(nilfsSb.volume_name, CurrentEncoding);
|
||||
xmlFSType.VolumeSerial = nilfsSb.uuid.ToString();
|
||||
xmlFSType.CreationDate = DateHandlers.UNIXUnsignedToDateTime(nilfsSb.ctime);
|
||||
xmlFSType.CreationDateSpecified = true;
|
||||
xmlFSType.ModificationDate = DateHandlers.UNIXUnsignedToDateTime(nilfsSb.wtime);
|
||||
xmlFSType.ModificationDateSpecified = true;
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
Type = "NILFS2 filesystem",
|
||||
ClusterSize = 1 << (int)(nilfsSb.log_block_size + 10),
|
||||
VolumeName = StringHandlers.CToString(nilfsSb.volume_name, CurrentEncoding),
|
||||
VolumeSerial = nilfsSb.uuid.ToString(),
|
||||
CreationDate = DateHandlers.UNIXUnsignedToDateTime(nilfsSb.ctime),
|
||||
CreationDateSpecified = true,
|
||||
ModificationDate = DateHandlers.UNIXUnsignedToDateTime(nilfsSb.wtime),
|
||||
ModificationDateSpecified = true
|
||||
};
|
||||
if(nilfsSb.creator_os == 0) XmlFsType.SystemIdentifier = "Linux";
|
||||
XmlFsType.Clusters = (long)nilfsSb.dev_size / XmlFsType.ClusterSize;
|
||||
}
|
||||
|
||||
public override Errno Mount()
|
||||
|
||||
@@ -47,21 +47,21 @@ namespace DiscImageChef.Filesystems
|
||||
public NTFS()
|
||||
{
|
||||
Name = "New Technology File System (NTFS)";
|
||||
PluginUUID = new Guid("33513B2C-1e6d-4d21-a660-0bbc789c3871");
|
||||
PluginUuid = new Guid("33513B2C-1e6d-4d21-a660-0bbc789c3871");
|
||||
CurrentEncoding = Encoding.Unicode;
|
||||
}
|
||||
|
||||
public NTFS(Encoding encoding)
|
||||
{
|
||||
Name = "New Technology File System (NTFS)";
|
||||
PluginUUID = new Guid("33513B2C-1e6d-4d21-a660-0bbc789c3871");
|
||||
PluginUuid = new Guid("33513B2C-1e6d-4d21-a660-0bbc789c3871");
|
||||
CurrentEncoding = Encoding.Unicode;
|
||||
}
|
||||
|
||||
public NTFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "New Technology File System (NTFS)";
|
||||
PluginUUID = new Guid("33513B2C-1e6d-4d21-a660-0bbc789c3871");
|
||||
PluginUuid = new Guid("33513B2C-1e6d-4d21-a660-0bbc789c3871");
|
||||
CurrentEncoding = Encoding.Unicode;
|
||||
}
|
||||
|
||||
@@ -69,27 +69,26 @@ namespace DiscImageChef.Filesystems
|
||||
{
|
||||
if(2 + partition.Start >= partition.End) return false;
|
||||
|
||||
byte[] eigth_bytes = new byte[8];
|
||||
byte fats_no;
|
||||
ushort spfat, signature;
|
||||
string oem_name;
|
||||
byte[] eigthBytes = new byte[8];
|
||||
byte fatsNo;
|
||||
ushort spFat, signature;
|
||||
|
||||
byte[] ntfs_bpb = imagePlugin.ReadSector(0 + partition.Start);
|
||||
byte[] ntfsBpb = imagePlugin.ReadSector(0 + partition.Start);
|
||||
|
||||
Array.Copy(ntfs_bpb, 0x003, eigth_bytes, 0, 8);
|
||||
oem_name = StringHandlers.CToString(eigth_bytes);
|
||||
Array.Copy(ntfsBpb, 0x003, eigthBytes, 0, 8);
|
||||
string oemName = StringHandlers.CToString(eigthBytes);
|
||||
|
||||
if(oem_name != "NTFS ") return false;
|
||||
if(oemName != "NTFS ") return false;
|
||||
|
||||
fats_no = ntfs_bpb[0x010];
|
||||
fatsNo = ntfsBpb[0x010];
|
||||
|
||||
if(fats_no != 0) return false;
|
||||
if(fatsNo != 0) return false;
|
||||
|
||||
spfat = BitConverter.ToUInt16(ntfs_bpb, 0x016);
|
||||
spFat = BitConverter.ToUInt16(ntfsBpb, 0x016);
|
||||
|
||||
if(spfat != 0) return false;
|
||||
if(spFat != 0) return false;
|
||||
|
||||
signature = BitConverter.ToUInt16(ntfs_bpb, 0x1FE);
|
||||
signature = BitConverter.ToUInt16(ntfsBpb, 0x1FE);
|
||||
|
||||
return signature == 0xAA55;
|
||||
}
|
||||
@@ -101,63 +100,62 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
byte[] ntfs_bpb = imagePlugin.ReadSector(0 + partition.Start);
|
||||
byte[] ntfsBpb = imagePlugin.ReadSector(0 + partition.Start);
|
||||
|
||||
NTFS_BootBlock ntfs_bb;
|
||||
IntPtr bpbPtr = Marshal.AllocHGlobal(512);
|
||||
Marshal.Copy(ntfs_bpb, 0, bpbPtr, 512);
|
||||
ntfs_bb = (NTFS_BootBlock)Marshal.PtrToStructure(bpbPtr, typeof(NTFS_BootBlock));
|
||||
Marshal.Copy(ntfsBpb, 0, bpbPtr, 512);
|
||||
NtfsBootBlock ntfsBb = (NtfsBootBlock)Marshal.PtrToStructure(bpbPtr, typeof(NtfsBootBlock));
|
||||
Marshal.FreeHGlobal(bpbPtr);
|
||||
|
||||
sb.AppendFormat("{0} bytes per sector", ntfs_bb.bps).AppendLine();
|
||||
sb.AppendFormat("{0} sectors per cluster ({1} bytes)", ntfs_bb.spc, ntfs_bb.spc * ntfs_bb.bps).AppendLine();
|
||||
sb.AppendFormat("{0} bytes per sector", ntfsBb.bps).AppendLine();
|
||||
sb.AppendFormat("{0} sectors per cluster ({1} bytes)", ntfsBb.spc, ntfsBb.spc * ntfsBb.bps).AppendLine();
|
||||
// sb.AppendFormat("{0} reserved sectors", ntfs_bb.rsectors).AppendLine();
|
||||
// sb.AppendFormat("{0} FATs", ntfs_bb.fats_no).AppendLine();
|
||||
// sb.AppendFormat("{0} entries in the root folder", ntfs_bb.root_ent).AppendLine();
|
||||
// sb.AppendFormat("{0} sectors on volume (small)", ntfs_bb.sml_sectors).AppendLine();
|
||||
sb.AppendFormat("Media descriptor: 0x{0:X2}", ntfs_bb.media).AppendLine();
|
||||
sb.AppendFormat("Media descriptor: 0x{0:X2}", ntfsBb.media).AppendLine();
|
||||
// sb.AppendFormat("{0} sectors per FAT", ntfs_bb.spfat).AppendLine();
|
||||
sb.AppendFormat("{0} sectors per track", ntfs_bb.sptrk).AppendLine();
|
||||
sb.AppendFormat("{0} heads", ntfs_bb.heads).AppendLine();
|
||||
sb.AppendFormat("{0} hidden sectors before filesystem", ntfs_bb.hsectors).AppendLine();
|
||||
sb.AppendFormat("{0} sectors per track", ntfsBb.sptrk).AppendLine();
|
||||
sb.AppendFormat("{0} heads", ntfsBb.heads).AppendLine();
|
||||
sb.AppendFormat("{0} hidden sectors before filesystem", ntfsBb.hsectors).AppendLine();
|
||||
// sb.AppendFormat("{0} sectors on volume (big)", ntfs_bb.big_sectors).AppendLine();
|
||||
sb.AppendFormat("BIOS drive number: 0x{0:X2}", ntfs_bb.drive_no).AppendLine();
|
||||
sb.AppendFormat("BIOS drive number: 0x{0:X2}", ntfsBb.drive_no).AppendLine();
|
||||
// sb.AppendFormat("NT flags: 0x{0:X2}", ntfs_bb.nt_flags).AppendLine();
|
||||
// sb.AppendFormat("Signature 1: 0x{0:X2}", ntfs_bb.signature1).AppendLine();
|
||||
sb.AppendFormat("{0} sectors on volume ({1} bytes)", ntfs_bb.sectors, ntfs_bb.sectors * ntfs_bb.bps)
|
||||
sb.AppendFormat("{0} sectors on volume ({1} bytes)", ntfsBb.sectors, ntfsBb.sectors * ntfsBb.bps)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("Cluster where $MFT starts: {0}", ntfs_bb.mft_lsn).AppendLine();
|
||||
sb.AppendFormat("Cluster where $MFTMirr starts: {0}", ntfs_bb.mftmirror_lsn).AppendLine();
|
||||
sb.AppendFormat("Cluster where $MFT starts: {0}", ntfsBb.mft_lsn).AppendLine();
|
||||
sb.AppendFormat("Cluster where $MFTMirr starts: {0}", ntfsBb.mftmirror_lsn).AppendLine();
|
||||
|
||||
if(ntfs_bb.mft_rc_clusters > 0)
|
||||
sb.AppendFormat("{0} clusters per MFT record ({1} bytes)", ntfs_bb.mft_rc_clusters,
|
||||
ntfs_bb.mft_rc_clusters * ntfs_bb.bps * ntfs_bb.spc).AppendLine();
|
||||
else sb.AppendFormat("{0} bytes per MFT record", 1 << -ntfs_bb.mft_rc_clusters).AppendLine();
|
||||
if(ntfs_bb.index_blk_cts > 0)
|
||||
sb.AppendFormat("{0} clusters per Index block ({1} bytes)", ntfs_bb.index_blk_cts,
|
||||
ntfs_bb.index_blk_cts * ntfs_bb.bps * ntfs_bb.spc).AppendLine();
|
||||
else sb.AppendFormat("{0} bytes per Index block", 1 << -ntfs_bb.index_blk_cts).AppendLine();
|
||||
if(ntfsBb.mft_rc_clusters > 0)
|
||||
sb.AppendFormat("{0} clusters per MFT record ({1} bytes)", ntfsBb.mft_rc_clusters,
|
||||
ntfsBb.mft_rc_clusters * ntfsBb.bps * ntfsBb.spc).AppendLine();
|
||||
else sb.AppendFormat("{0} bytes per MFT record", 1 << -ntfsBb.mft_rc_clusters).AppendLine();
|
||||
if(ntfsBb.index_blk_cts > 0)
|
||||
sb.AppendFormat("{0} clusters per Index block ({1} bytes)", ntfsBb.index_blk_cts,
|
||||
ntfsBb.index_blk_cts * ntfsBb.bps * ntfsBb.spc).AppendLine();
|
||||
else sb.AppendFormat("{0} bytes per Index block", 1 << -ntfsBb.index_blk_cts).AppendLine();
|
||||
|
||||
sb.AppendFormat("Volume serial number: {0:X16}", ntfs_bb.serial_no).AppendLine();
|
||||
sb.AppendFormat("Volume serial number: {0:X16}", ntfsBb.serial_no).AppendLine();
|
||||
// sb.AppendFormat("Signature 2: 0x{0:X4}", ntfs_bb.signature2).AppendLine();
|
||||
|
||||
xmlFSType = new FileSystemType();
|
||||
XmlFsType = new FileSystemType();
|
||||
|
||||
if(ntfs_bb.jump[0] == 0xEB && ntfs_bb.jump[1] > 0x4E && ntfs_bb.jump[1] < 0x80 &&
|
||||
ntfs_bb.signature2 == 0xAA55)
|
||||
if(ntfsBb.jump[0] == 0xEB && ntfsBb.jump[1] > 0x4E && ntfsBb.jump[1] < 0x80 &&
|
||||
ntfsBb.signature2 == 0xAA55)
|
||||
{
|
||||
xmlFSType.Bootable = true;
|
||||
XmlFsType.Bootable = true;
|
||||
Sha1Context sha1Ctx = new Sha1Context();
|
||||
sha1Ctx.Init();
|
||||
string bootChk = sha1Ctx.Data(ntfs_bb.boot_code, out byte[] sha1_out);
|
||||
string bootChk = sha1Ctx.Data(ntfsBb.boot_code, out _);
|
||||
sb.AppendLine("Volume is bootable");
|
||||
sb.AppendFormat("Boot code's SHA1: {0}", bootChk).AppendLine();
|
||||
}
|
||||
|
||||
xmlFSType.ClusterSize = ntfs_bb.spc * ntfs_bb.bps;
|
||||
xmlFSType.Clusters = ntfs_bb.sectors / ntfs_bb.spc;
|
||||
xmlFSType.VolumeSerial = $"{ntfs_bb.serial_no:X16}";
|
||||
xmlFSType.Type = "NTFS";
|
||||
XmlFsType.ClusterSize = ntfsBb.spc * ntfsBb.bps;
|
||||
XmlFsType.Clusters = ntfsBb.sectors / ntfsBb.spc;
|
||||
XmlFsType.VolumeSerial = $"{ntfsBb.serial_no:X16}";
|
||||
XmlFsType.Type = "NTFS";
|
||||
|
||||
information = sb.ToString();
|
||||
}
|
||||
@@ -166,7 +164,7 @@ namespace DiscImageChef.Filesystems
|
||||
/// NTFS $BOOT
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
struct NTFS_BootBlock
|
||||
struct NtfsBootBlock
|
||||
{
|
||||
// Start of BIOS Parameter Block
|
||||
/// <summary>0x000, Jump to boot code</summary>
|
||||
|
||||
@@ -45,24 +45,22 @@ namespace DiscImageChef.Filesystems
|
||||
public NintendoPlugin()
|
||||
{
|
||||
Name = "Nintendo optical filesystems";
|
||||
PluginUUID = new Guid("4675fcb4-4418-4288-9e4a-33d6a4ac1126");
|
||||
PluginUuid = new Guid("4675fcb4-4418-4288-9e4a-33d6a4ac1126");
|
||||
CurrentEncoding = Encoding.GetEncoding("shift_jis");
|
||||
}
|
||||
|
||||
public NintendoPlugin(Encoding encoding)
|
||||
{
|
||||
Name = "Nintendo optical filesystems";
|
||||
PluginUUID = new Guid("4675fcb4-4418-4288-9e4a-33d6a4ac1126");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("shift_jis");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("4675fcb4-4418-4288-9e4a-33d6a4ac1126");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("shift_jis");
|
||||
}
|
||||
|
||||
public NintendoPlugin(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "Nintendo optical filesystems";
|
||||
PluginUUID = new Guid("4675fcb4-4418-4288-9e4a-33d6a4ac1126");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("shift_jis");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("4675fcb4-4418-4288-9e4a-33d6a4ac1126");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("shift_jis");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugin imagePlugin, Partition partition)
|
||||
@@ -75,12 +73,10 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
byte[] header = imagePlugin.ReadSectors(0, 0x50000 / imagePlugin.GetSectorSize());
|
||||
|
||||
uint magicGC = BigEndianBitConverter.ToUInt32(header, 0x1C);
|
||||
uint magicGc = BigEndianBitConverter.ToUInt32(header, 0x1C);
|
||||
uint magicWii = BigEndianBitConverter.ToUInt32(header, 0x18);
|
||||
|
||||
if(magicGC == 0xC2339F3D || magicWii == 0x5D1C9EA3) return true;
|
||||
|
||||
return false;
|
||||
return magicGc == 0xC2339F3D || magicWii == 0x5D1C9EA3;
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
|
||||
@@ -88,7 +84,7 @@ namespace DiscImageChef.Filesystems
|
||||
{
|
||||
StringBuilder sbInformation = new StringBuilder();
|
||||
information = "";
|
||||
xmlFSType = new FileSystemType();
|
||||
XmlFsType = new FileSystemType();
|
||||
|
||||
NintendoFields fields = new NintendoFields();
|
||||
BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian;
|
||||
@@ -97,35 +93,35 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
bool wii = false;
|
||||
|
||||
uint magicGC = BigEndianBitConverter.ToUInt32(header, 0x1C);
|
||||
uint magicGc = BigEndianBitConverter.ToUInt32(header, 0x1C);
|
||||
uint magicWii = BigEndianBitConverter.ToUInt32(header, 0x18);
|
||||
|
||||
if(magicWii == 0x5D1C9EA3)
|
||||
wii = true;
|
||||
else if(magicGC != 0xC2339F3D)
|
||||
else if(magicGc != 0xC2339F3D)
|
||||
return;
|
||||
|
||||
fields.discType = Encoding.ASCII.GetString(header, 0, 1);
|
||||
fields.gameCode = Encoding.ASCII.GetString(header, 1, 2);
|
||||
fields.regionCode = Encoding.ASCII.GetString(header, 3, 1);
|
||||
fields.publisherCode = Encoding.ASCII.GetString(header, 4, 2);
|
||||
fields.discID = Encoding.ASCII.GetString(header, 0, 6);
|
||||
fields.discNumber = header[6];
|
||||
fields.discVersion = header[7];
|
||||
fields.streaming |= header[8] > 0;
|
||||
fields.streamBufferSize = header[9];
|
||||
fields.DiscType = Encoding.ASCII.GetString(header, 0, 1);
|
||||
fields.GameCode = Encoding.ASCII.GetString(header, 1, 2);
|
||||
fields.RegionCode = Encoding.ASCII.GetString(header, 3, 1);
|
||||
fields.PublisherCode = Encoding.ASCII.GetString(header, 4, 2);
|
||||
fields.DiscId = Encoding.ASCII.GetString(header, 0, 6);
|
||||
fields.DiscNumber = header[6];
|
||||
fields.DiscVersion = header[7];
|
||||
fields.Streaming |= header[8] > 0;
|
||||
fields.StreamBufferSize = header[9];
|
||||
byte[] temp = new byte[64];
|
||||
Array.Copy(header, 0x20, temp, 0, 64);
|
||||
fields.title = StringHandlers.CToString(temp, CurrentEncoding);
|
||||
fields.Title = StringHandlers.CToString(temp, CurrentEncoding);
|
||||
|
||||
if(!wii)
|
||||
{
|
||||
fields.debugOff = BigEndianBitConverter.ToUInt32(header, 0x0400);
|
||||
fields.debugAddr = BigEndianBitConverter.ToUInt32(header, 0x0404);
|
||||
fields.dolOff = BigEndianBitConverter.ToUInt32(header, 0x0420);
|
||||
fields.fstOff = BigEndianBitConverter.ToUInt32(header, 0x0424);
|
||||
fields.fstSize = BigEndianBitConverter.ToUInt32(header, 0x0428);
|
||||
fields.fstMax = BigEndianBitConverter.ToUInt32(header, 0x042C);
|
||||
fields.DebugOff = BigEndianBitConverter.ToUInt32(header, 0x0400);
|
||||
fields.DebugAddr = BigEndianBitConverter.ToUInt32(header, 0x0404);
|
||||
fields.DolOff = BigEndianBitConverter.ToUInt32(header, 0x0420);
|
||||
fields.FstOff = BigEndianBitConverter.ToUInt32(header, 0x0424);
|
||||
fields.FstSize = BigEndianBitConverter.ToUInt32(header, 0x0428);
|
||||
fields.FstMax = BigEndianBitConverter.ToUInt32(header, 0x042C);
|
||||
}
|
||||
|
||||
if(wii)
|
||||
@@ -136,231 +132,229 @@ namespace DiscImageChef.Filesystems
|
||||
offset3 = BigEndianBitConverter.ToUInt32(header, 0x40014) << 2;
|
||||
offset4 = BigEndianBitConverter.ToUInt32(header, 0x4001C) << 2;
|
||||
|
||||
fields.firstPartitions = new NintendoPartition[BigEndianBitConverter.ToUInt32(header, 0x40000)];
|
||||
fields.secondPartitions = new NintendoPartition[BigEndianBitConverter.ToUInt32(header, 0x40008)];
|
||||
fields.thirdPartitions = new NintendoPartition[BigEndianBitConverter.ToUInt32(header, 0x40010)];
|
||||
fields.fourthPartitions = new NintendoPartition[BigEndianBitConverter.ToUInt32(header, 0x40018)];
|
||||
fields.FirstPartitions = new NintendoPartition[BigEndianBitConverter.ToUInt32(header, 0x40000)];
|
||||
fields.SecondPartitions = new NintendoPartition[BigEndianBitConverter.ToUInt32(header, 0x40008)];
|
||||
fields.ThirdPartitions = new NintendoPartition[BigEndianBitConverter.ToUInt32(header, 0x40010)];
|
||||
fields.FourthPartitions = new NintendoPartition[BigEndianBitConverter.ToUInt32(header, 0x40018)];
|
||||
|
||||
for(int i = 0; i < fields.firstPartitions.Length; i++)
|
||||
for(int i = 0; i < fields.FirstPartitions.Length; i++)
|
||||
if(offset1 + i * 8 + 8 < 0x50000)
|
||||
{
|
||||
fields.firstPartitions[i].offset =
|
||||
fields.FirstPartitions[i].Offset =
|
||||
BigEndianBitConverter.ToUInt32(header, (int)(offset1 + i * 8 + 0)) << 2;
|
||||
fields.firstPartitions[i].type =
|
||||
fields.FirstPartitions[i].Type =
|
||||
BigEndianBitConverter.ToUInt32(header, (int)(offset1 + i * 8 + 4));
|
||||
}
|
||||
|
||||
for(int i = 0; i < fields.secondPartitions.Length; i++)
|
||||
for(int i = 0; i < fields.SecondPartitions.Length; i++)
|
||||
if(offset1 + i * 8 + 8 < 0x50000)
|
||||
{
|
||||
fields.firstPartitions[i].offset =
|
||||
fields.FirstPartitions[i].Offset =
|
||||
BigEndianBitConverter.ToUInt32(header, (int)(offset2 + i * 8 + 0)) << 2;
|
||||
fields.firstPartitions[i].type =
|
||||
fields.FirstPartitions[i].Type =
|
||||
BigEndianBitConverter.ToUInt32(header, (int)(offset2 + i * 8 + 4));
|
||||
}
|
||||
|
||||
for(int i = 0; i < fields.thirdPartitions.Length; i++)
|
||||
for(int i = 0; i < fields.ThirdPartitions.Length; i++)
|
||||
if(offset1 + i * 8 + 8 < 0x50000)
|
||||
{
|
||||
fields.firstPartitions[i].offset =
|
||||
fields.FirstPartitions[i].Offset =
|
||||
BigEndianBitConverter.ToUInt32(header, (int)(offset3 + i * 8 + 0)) << 2;
|
||||
fields.firstPartitions[i].type =
|
||||
fields.FirstPartitions[i].Type =
|
||||
BigEndianBitConverter.ToUInt32(header, (int)(offset3 + i * 8 + 4));
|
||||
}
|
||||
|
||||
for(int i = 0; i < fields.fourthPartitions.Length; i++)
|
||||
for(int i = 0; i < fields.FourthPartitions.Length; i++)
|
||||
if(offset1 + i * 8 + 8 < 0x50000)
|
||||
{
|
||||
fields.firstPartitions[i].offset =
|
||||
fields.FirstPartitions[i].Offset =
|
||||
BigEndianBitConverter.ToUInt32(header, (int)(offset4 + i * 8 + 0)) << 2;
|
||||
fields.firstPartitions[i].type =
|
||||
fields.FirstPartitions[i].Type =
|
||||
BigEndianBitConverter.ToUInt32(header, (int)(offset4 + i * 8 + 4));
|
||||
}
|
||||
|
||||
fields.region = header[0x4E000];
|
||||
fields.japanAge = header[0x4E010];
|
||||
fields.usaAge = header[0x4E011];
|
||||
fields.germanAge = header[0x4E013];
|
||||
fields.pegiAge = header[0x4E014];
|
||||
fields.finlandAge = header[0x4E015];
|
||||
fields.portugalAge = header[0x4E016];
|
||||
fields.ukAge = header[0x4E017];
|
||||
fields.australiaAge = header[0x4E018];
|
||||
fields.koreaAge = header[0x4E019];
|
||||
fields.Region = header[0x4E000];
|
||||
fields.JapanAge = header[0x4E010];
|
||||
fields.UsaAge = header[0x4E011];
|
||||
fields.GermanAge = header[0x4E013];
|
||||
fields.PegiAge = header[0x4E014];
|
||||
fields.FinlandAge = header[0x4E015];
|
||||
fields.PortugalAge = header[0x4E016];
|
||||
fields.UkAge = header[0x4E017];
|
||||
fields.AustraliaAge = header[0x4E018];
|
||||
fields.KoreaAge = header[0x4E019];
|
||||
}
|
||||
else
|
||||
{
|
||||
fields.firstPartitions = new NintendoPartition[0];
|
||||
fields.secondPartitions = new NintendoPartition[0];
|
||||
fields.thirdPartitions = new NintendoPartition[0];
|
||||
fields.fourthPartitions = new NintendoPartition[0];
|
||||
fields.FirstPartitions = new NintendoPartition[0];
|
||||
fields.SecondPartitions = new NintendoPartition[0];
|
||||
fields.ThirdPartitions = new NintendoPartition[0];
|
||||
fields.FourthPartitions = new NintendoPartition[0];
|
||||
}
|
||||
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "discType = {0}", fields.discType);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "gameCode = {0}", fields.gameCode);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "regionCode = {0}", fields.regionCode);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "publisherCode = {0}", fields.publisherCode);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "discID = {0}", fields.discID);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "discNumber = {0}", fields.discNumber);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "discVersion = {0}", fields.discVersion);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "streaming = {0}", fields.streaming);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "streamBufferSize = {0}", fields.streamBufferSize);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "title = \"{0}\"", fields.title);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "debugOff = 0x{0:X8}", fields.debugOff);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "debugAddr = 0x{0:X8}", fields.debugAddr);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "dolOff = 0x{0:X8}", fields.dolOff);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "fstOff = 0x{0:X8}", fields.fstOff);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "fstSize = {0}", fields.fstSize);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "fstMax = {0}", fields.fstMax);
|
||||
for(int i = 0; i < fields.firstPartitions.Length; i++)
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "discType = {0}", fields.DiscType);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "gameCode = {0}", fields.GameCode);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "regionCode = {0}", fields.RegionCode);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "publisherCode = {0}", fields.PublisherCode);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "discID = {0}", fields.DiscId);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "discNumber = {0}", fields.DiscNumber);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "discVersion = {0}", fields.DiscVersion);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "streaming = {0}", fields.Streaming);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "streamBufferSize = {0}", fields.StreamBufferSize);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "title = \"{0}\"", fields.Title);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "debugOff = 0x{0:X8}", fields.DebugOff);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "debugAddr = 0x{0:X8}", fields.DebugAddr);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "dolOff = 0x{0:X8}", fields.DolOff);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "fstOff = 0x{0:X8}", fields.FstOff);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "fstSize = {0}", fields.FstSize);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "fstMax = {0}", fields.FstMax);
|
||||
for(int i = 0; i < fields.FirstPartitions.Length; i++)
|
||||
{
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "firstPartitions[{1}].offset = {0}",
|
||||
fields.firstPartitions[i].offset, i);
|
||||
fields.FirstPartitions[i].Offset, i);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "firstPartitions[{1}].type = {0}",
|
||||
fields.firstPartitions[i].type, i);
|
||||
fields.FirstPartitions[i].Type, i);
|
||||
}
|
||||
for(int i = 0; i < fields.secondPartitions.Length; i++)
|
||||
for(int i = 0; i < fields.SecondPartitions.Length; i++)
|
||||
{
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "secondPartitions[{1}].offset = {0}",
|
||||
fields.secondPartitions[i].offset, i);
|
||||
fields.SecondPartitions[i].Offset, i);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "secondPartitions[{1}].type = {0}",
|
||||
fields.secondPartitions[i].type, i);
|
||||
fields.SecondPartitions[i].Type, i);
|
||||
}
|
||||
for(int i = 0; i < fields.thirdPartitions.Length; i++)
|
||||
for(int i = 0; i < fields.ThirdPartitions.Length; i++)
|
||||
{
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "thirdPartitions[{1}].offset = {0}",
|
||||
fields.thirdPartitions[i].offset, i);
|
||||
fields.ThirdPartitions[i].Offset, i);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "thirdPartitions[{1}].type = {0}",
|
||||
fields.thirdPartitions[i].type, i);
|
||||
fields.ThirdPartitions[i].Type, i);
|
||||
}
|
||||
for(int i = 0; i < fields.fourthPartitions.Length; i++)
|
||||
for(int i = 0; i < fields.FourthPartitions.Length; i++)
|
||||
{
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "fourthPartitions[{1}].offset = {0}",
|
||||
fields.fourthPartitions[i].offset, i);
|
||||
fields.FourthPartitions[i].Offset, i);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "fourthPartitions[{1}].type = {0}",
|
||||
fields.fourthPartitions[i].type, i);
|
||||
fields.FourthPartitions[i].Type, i);
|
||||
}
|
||||
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "region = {0}", fields.region);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "japanAge = {0}", fields.japanAge);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "usaAge = {0}", fields.usaAge);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "germanAge = {0}", fields.germanAge);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "pegiAge = {0}", fields.pegiAge);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "finlandAge = {0}", fields.finlandAge);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "portugalAge = {0}", fields.portugalAge);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "ukAge = {0}", fields.ukAge);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "australiaAge = {0}", fields.australiaAge);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "koreaAge = {0}", fields.koreaAge);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "region = {0}", fields.Region);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "japanAge = {0}", fields.JapanAge);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "usaAge = {0}", fields.UsaAge);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "germanAge = {0}", fields.GermanAge);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "pegiAge = {0}", fields.PegiAge);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "finlandAge = {0}", fields.FinlandAge);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "portugalAge = {0}", fields.PortugalAge);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "ukAge = {0}", fields.UkAge);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "australiaAge = {0}", fields.AustraliaAge);
|
||||
DicConsole.DebugWriteLine("Nintendo plugin", "koreaAge = {0}", fields.KoreaAge);
|
||||
|
||||
sbInformation.AppendLine("Nintendo optical filesystem");
|
||||
if(wii) sbInformation.AppendLine("Nintendo Wii Optical Disc");
|
||||
else sbInformation.AppendLine("Nintendo GameCube Optical Disc");
|
||||
sbInformation.AppendFormat("Disc ID is {0}", fields.discID).AppendLine();
|
||||
sbInformation.AppendFormat("Disc is a {0} disc", DiscTypeToString(fields.discType)).AppendLine();
|
||||
sbInformation.AppendFormat("Disc region is {0}", RegionCodeToString(fields.regionCode)).AppendLine();
|
||||
sbInformation.AppendFormat("Published by {0}", PublisherCodeToString(fields.publisherCode)).AppendLine();
|
||||
if(fields.discNumber > 0)
|
||||
sbInformation.AppendFormat("Disc number {0} of a multi-disc set", fields.discNumber + 1).AppendLine();
|
||||
if(fields.streaming) sbInformation.AppendLine("Disc is prepared for audio streaming");
|
||||
if(fields.streamBufferSize > 0)
|
||||
sbInformation.AppendFormat("Audio streaming buffer size is {0} bytes", fields.streamBufferSize)
|
||||
sbInformation.AppendLine(wii ? "Nintendo Wii Optical Disc" : "Nintendo GameCube Optical Disc");
|
||||
sbInformation.AppendFormat("Disc ID is {0}", fields.DiscId).AppendLine();
|
||||
sbInformation.AppendFormat("Disc is a {0} disc", DiscTypeToString(fields.DiscType)).AppendLine();
|
||||
sbInformation.AppendFormat("Disc region is {0}", RegionCodeToString(fields.RegionCode)).AppendLine();
|
||||
sbInformation.AppendFormat("Published by {0}", PublisherCodeToString(fields.PublisherCode)).AppendLine();
|
||||
if(fields.DiscNumber > 0)
|
||||
sbInformation.AppendFormat("Disc number {0} of a multi-disc set", fields.DiscNumber + 1).AppendLine();
|
||||
if(fields.Streaming) sbInformation.AppendLine("Disc is prepared for audio streaming");
|
||||
if(fields.StreamBufferSize > 0)
|
||||
sbInformation.AppendFormat("Audio streaming buffer size is {0} bytes", fields.StreamBufferSize)
|
||||
.AppendLine();
|
||||
sbInformation.AppendFormat("Title: {0}", fields.title).AppendLine();
|
||||
sbInformation.AppendFormat("Title: {0}", fields.Title).AppendLine();
|
||||
|
||||
if(wii)
|
||||
{
|
||||
for(int i = 0; i < fields.firstPartitions.Length; i++)
|
||||
for(int i = 0; i < fields.FirstPartitions.Length; i++)
|
||||
sbInformation.AppendFormat("First {0} partition starts at sector {1}",
|
||||
PartitionTypeToString(fields.firstPartitions[i].type),
|
||||
fields.firstPartitions[i].offset / 2048).AppendLine();
|
||||
for(int i = 0; i < fields.secondPartitions.Length; i++)
|
||||
PartitionTypeToString(fields.FirstPartitions[i].Type),
|
||||
fields.FirstPartitions[i].Offset / 2048).AppendLine();
|
||||
for(int i = 0; i < fields.SecondPartitions.Length; i++)
|
||||
sbInformation.AppendFormat("Second {0} partition starts at sector {1}",
|
||||
PartitionTypeToString(fields.secondPartitions[i].type),
|
||||
fields.secondPartitions[i].offset / 2048).AppendLine();
|
||||
for(int i = 0; i < fields.thirdPartitions.Length; i++)
|
||||
PartitionTypeToString(fields.SecondPartitions[i].Type),
|
||||
fields.SecondPartitions[i].Offset / 2048).AppendLine();
|
||||
for(int i = 0; i < fields.ThirdPartitions.Length; i++)
|
||||
sbInformation.AppendFormat("Third {0} partition starts at sector {1}",
|
||||
PartitionTypeToString(fields.thirdPartitions[i].type),
|
||||
fields.thirdPartitions[i].offset / 2048).AppendLine();
|
||||
for(int i = 0; i < fields.fourthPartitions.Length; i++)
|
||||
PartitionTypeToString(fields.ThirdPartitions[i].Type),
|
||||
fields.ThirdPartitions[i].Offset / 2048).AppendLine();
|
||||
for(int i = 0; i < fields.FourthPartitions.Length; i++)
|
||||
sbInformation.AppendFormat("Fourth {0} partition starts at sector {1}",
|
||||
PartitionTypeToString(fields.fourthPartitions[i].type),
|
||||
fields.fourthPartitions[i].offset / 2048).AppendLine();
|
||||
PartitionTypeToString(fields.FourthPartitions[i].Type),
|
||||
fields.FourthPartitions[i].Offset / 2048).AppendLine();
|
||||
|
||||
// sbInformation.AppendFormat("Region byte is {0}", fields.region).AppendLine();
|
||||
if((fields.japanAge & 0x80) != 0x80)
|
||||
sbInformation.AppendFormat("Japan age rating is {0}", fields.japanAge).AppendLine();
|
||||
if((fields.usaAge & 0x80) != 0x80)
|
||||
sbInformation.AppendFormat("ESRB age rating is {0}", fields.usaAge).AppendLine();
|
||||
if((fields.germanAge & 0x80) != 0x80)
|
||||
sbInformation.AppendFormat("German age rating is {0}", fields.germanAge).AppendLine();
|
||||
if((fields.pegiAge & 0x80) != 0x80)
|
||||
sbInformation.AppendFormat("PEGI age rating is {0}", fields.pegiAge).AppendLine();
|
||||
if((fields.finlandAge & 0x80) != 0x80)
|
||||
sbInformation.AppendFormat("Finland age rating is {0}", fields.finlandAge).AppendLine();
|
||||
if((fields.portugalAge & 0x80) != 0x80)
|
||||
sbInformation.AppendFormat("Portugal age rating is {0}", fields.portugalAge).AppendLine();
|
||||
if((fields.ukAge & 0x80) != 0x80)
|
||||
sbInformation.AppendFormat("UK age rating is {0}", fields.ukAge).AppendLine();
|
||||
if((fields.australiaAge & 0x80) != 0x80)
|
||||
sbInformation.AppendFormat("Australia age rating is {0}", fields.australiaAge).AppendLine();
|
||||
if((fields.koreaAge & 0x80) != 0x80)
|
||||
sbInformation.AppendFormat("Korea age rating is {0}", fields.koreaAge).AppendLine();
|
||||
if((fields.JapanAge & 0x80) != 0x80)
|
||||
sbInformation.AppendFormat("Japan age rating is {0}", fields.JapanAge).AppendLine();
|
||||
if((fields.UsaAge & 0x80) != 0x80)
|
||||
sbInformation.AppendFormat("ESRB age rating is {0}", fields.UsaAge).AppendLine();
|
||||
if((fields.GermanAge & 0x80) != 0x80)
|
||||
sbInformation.AppendFormat("German age rating is {0}", fields.GermanAge).AppendLine();
|
||||
if((fields.PegiAge & 0x80) != 0x80)
|
||||
sbInformation.AppendFormat("PEGI age rating is {0}", fields.PegiAge).AppendLine();
|
||||
if((fields.FinlandAge & 0x80) != 0x80)
|
||||
sbInformation.AppendFormat("Finland age rating is {0}", fields.FinlandAge).AppendLine();
|
||||
if((fields.PortugalAge & 0x80) != 0x80)
|
||||
sbInformation.AppendFormat("Portugal age rating is {0}", fields.PortugalAge).AppendLine();
|
||||
if((fields.UkAge & 0x80) != 0x80)
|
||||
sbInformation.AppendFormat("UK age rating is {0}", fields.UkAge).AppendLine();
|
||||
if((fields.AustraliaAge & 0x80) != 0x80)
|
||||
sbInformation.AppendFormat("Australia age rating is {0}", fields.AustraliaAge).AppendLine();
|
||||
if((fields.KoreaAge & 0x80) != 0x80)
|
||||
sbInformation.AppendFormat("Korea age rating is {0}", fields.KoreaAge).AppendLine();
|
||||
}
|
||||
else
|
||||
sbInformation.AppendFormat("FST starts at {0} and has {1} bytes", fields.fstOff, fields.fstSize)
|
||||
sbInformation.AppendFormat("FST starts at {0} and has {1} bytes", fields.FstOff, fields.FstSize)
|
||||
.AppendLine();
|
||||
|
||||
information = sbInformation.ToString();
|
||||
xmlFSType.Bootable = true;
|
||||
xmlFSType.Clusters = (long)(imagePlugin.GetSectors() * imagePlugin.GetSectorSize() / 2048);
|
||||
xmlFSType.ClusterSize = 2048;
|
||||
if(wii) xmlFSType.Type = "Nintendo Wii filesystem";
|
||||
else xmlFSType.Type = "Nintendo Gamecube filesystem";
|
||||
xmlFSType.VolumeName = fields.title;
|
||||
xmlFSType.VolumeSerial = fields.discID;
|
||||
XmlFsType.Bootable = true;
|
||||
XmlFsType.Clusters = (long)(imagePlugin.GetSectors() * imagePlugin.GetSectorSize() / 2048);
|
||||
XmlFsType.ClusterSize = 2048;
|
||||
XmlFsType.Type = wii ? "Nintendo Wii filesystem" : "Nintendo Gamecube filesystem";
|
||||
XmlFsType.VolumeName = fields.Title;
|
||||
XmlFsType.VolumeSerial = fields.DiscId;
|
||||
}
|
||||
|
||||
struct NintendoFields
|
||||
{
|
||||
public string discType;
|
||||
public string gameCode;
|
||||
public string regionCode;
|
||||
public string publisherCode;
|
||||
public string discID;
|
||||
public byte discNumber;
|
||||
public byte discVersion;
|
||||
public bool streaming;
|
||||
public byte streamBufferSize;
|
||||
public string title;
|
||||
public uint debugOff;
|
||||
public uint debugAddr;
|
||||
public uint dolOff;
|
||||
public uint fstOff;
|
||||
public uint fstSize;
|
||||
public uint fstMax;
|
||||
public NintendoPartition[] firstPartitions;
|
||||
public NintendoPartition[] secondPartitions;
|
||||
public NintendoPartition[] thirdPartitions;
|
||||
public NintendoPartition[] fourthPartitions;
|
||||
public byte region;
|
||||
public byte japanAge;
|
||||
public byte usaAge;
|
||||
public byte germanAge;
|
||||
public byte pegiAge;
|
||||
public byte finlandAge;
|
||||
public byte portugalAge;
|
||||
public byte ukAge;
|
||||
public byte australiaAge;
|
||||
public byte koreaAge;
|
||||
public string DiscType;
|
||||
public string GameCode;
|
||||
public string RegionCode;
|
||||
public string PublisherCode;
|
||||
public string DiscId;
|
||||
public byte DiscNumber;
|
||||
public byte DiscVersion;
|
||||
public bool Streaming;
|
||||
public byte StreamBufferSize;
|
||||
public string Title;
|
||||
public uint DebugOff;
|
||||
public uint DebugAddr;
|
||||
public uint DolOff;
|
||||
public uint FstOff;
|
||||
public uint FstSize;
|
||||
public uint FstMax;
|
||||
public NintendoPartition[] FirstPartitions;
|
||||
public NintendoPartition[] SecondPartitions;
|
||||
public NintendoPartition[] ThirdPartitions;
|
||||
public NintendoPartition[] FourthPartitions;
|
||||
public byte Region;
|
||||
public byte JapanAge;
|
||||
public byte UsaAge;
|
||||
public byte GermanAge;
|
||||
public byte PegiAge;
|
||||
public byte FinlandAge;
|
||||
public byte PortugalAge;
|
||||
public byte UkAge;
|
||||
public byte AustraliaAge;
|
||||
public byte KoreaAge;
|
||||
}
|
||||
|
||||
struct NintendoPartition
|
||||
{
|
||||
public uint offset;
|
||||
public uint type;
|
||||
public uint Offset;
|
||||
public uint Type;
|
||||
}
|
||||
|
||||
string DiscTypeToString(string discType)
|
||||
static string DiscTypeToString(string discType)
|
||||
{
|
||||
switch(discType)
|
||||
{
|
||||
@@ -390,7 +384,7 @@ namespace DiscImageChef.Filesystems
|
||||
return $"unknown type '{discType}'";
|
||||
}
|
||||
|
||||
string RegionCodeToString(string regionCode)
|
||||
static string RegionCodeToString(string regionCode)
|
||||
{
|
||||
switch(regionCode)
|
||||
{
|
||||
@@ -415,7 +409,7 @@ namespace DiscImageChef.Filesystems
|
||||
return $"unknown code '{regionCode}'";
|
||||
}
|
||||
|
||||
string PublisherCodeToString(string publisherCode)
|
||||
static string PublisherCodeToString(string publisherCode)
|
||||
{
|
||||
switch(publisherCode)
|
||||
{
|
||||
@@ -445,7 +439,7 @@ namespace DiscImageChef.Filesystems
|
||||
return $"Unknown publisher '{publisherCode}'";
|
||||
}
|
||||
|
||||
string PartitionTypeToString(uint type)
|
||||
static string PartitionTypeToString(uint type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
|
||||
@@ -55,24 +55,22 @@ namespace DiscImageChef.Filesystems
|
||||
public ODS()
|
||||
{
|
||||
Name = "Files-11 On-Disk Structure";
|
||||
PluginUUID = new Guid("de20633c-8021-4384-aeb0-83b0df14491f");
|
||||
PluginUuid = new Guid("de20633c-8021-4384-aeb0-83b0df14491f");
|
||||
CurrentEncoding = Encoding.GetEncoding("iso-8859-1");
|
||||
}
|
||||
|
||||
public ODS(Encoding encoding)
|
||||
{
|
||||
Name = "Files-11 On-Disk Structure";
|
||||
PluginUUID = new Guid("de20633c-8021-4384-aeb0-83b0df14491f");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-1");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("de20633c-8021-4384-aeb0-83b0df14491f");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1");
|
||||
}
|
||||
|
||||
public ODS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "Files-11 On-Disk Structure";
|
||||
PluginUUID = new Guid("de20633c-8021-4384-aeb0-83b0df14491f");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-1");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("de20633c-8021-4384-aeb0-83b0df14491f");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugin imagePlugin, Partition partition)
|
||||
@@ -81,12 +79,11 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
if(imagePlugin.GetSectorSize() < 512) return false;
|
||||
|
||||
byte[] magic_b = new byte[12];
|
||||
string magic;
|
||||
byte[] hb_sector = imagePlugin.ReadSector(1 + partition.Start);
|
||||
byte[] magicB = new byte[12];
|
||||
byte[] hbSector = imagePlugin.ReadSector(1 + partition.Start);
|
||||
|
||||
Array.Copy(hb_sector, 0x1F0, magic_b, 0, 12);
|
||||
magic = Encoding.ASCII.GetString(magic_b);
|
||||
Array.Copy(hbSector, 0x1F0, magicB, 0, 12);
|
||||
string magic = Encoding.ASCII.GetString(magicB);
|
||||
|
||||
DicConsole.DebugWriteLine("Files-11 plugin", "magic: \"{0}\"", magic);
|
||||
|
||||
@@ -95,18 +92,16 @@ namespace DiscImageChef.Filesystems
|
||||
// Optical disc
|
||||
if(imagePlugin.ImageInfo.XmlMediaType != XmlMediaType.OpticalDisc) return false;
|
||||
|
||||
if(hb_sector.Length < 0x400) return false;
|
||||
if(hbSector.Length < 0x400) return false;
|
||||
|
||||
hb_sector = imagePlugin.ReadSector(partition.Start);
|
||||
hbSector = imagePlugin.ReadSector(partition.Start);
|
||||
|
||||
Array.Copy(hb_sector, 0x3F0, magic_b, 0, 12);
|
||||
magic = Encoding.ASCII.GetString(magic_b);
|
||||
Array.Copy(hbSector, 0x3F0, magicB, 0, 12);
|
||||
magic = Encoding.ASCII.GetString(magicB);
|
||||
|
||||
DicConsole.DebugWriteLine("Files-11 plugin", "unaligned magic: \"{0}\"", magic);
|
||||
|
||||
if(magic == "DECFILE11A " || magic == "DECFILE11B ") return true;
|
||||
|
||||
return false;
|
||||
return magic == "DECFILE11A " || magic == "DECFILE11B ";
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
|
||||
@@ -115,14 +110,11 @@ namespace DiscImageChef.Filesystems
|
||||
information = "";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
ODSHomeBlock homeblock;
|
||||
homeblock.min_class = new byte[20];
|
||||
homeblock.max_class = new byte[20];
|
||||
|
||||
byte[] hb_sector = imagePlugin.ReadSector(1 + partition.Start);
|
||||
byte[] hbSector = imagePlugin.ReadSector(1 + partition.Start);
|
||||
|
||||
GCHandle handle = GCHandle.Alloc(hb_sector, GCHandleType.Pinned);
|
||||
homeblock = (ODSHomeBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(ODSHomeBlock));
|
||||
GCHandle handle = GCHandle.Alloc(hbSector, GCHandleType.Pinned);
|
||||
OdsHomeBlock homeblock = (OdsHomeBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(OdsHomeBlock));
|
||||
handle.Free();
|
||||
|
||||
// Optical disc
|
||||
@@ -130,14 +122,14 @@ namespace DiscImageChef.Filesystems
|
||||
StringHandlers.CToString(homeblock.format) != "DECFILE11A " &&
|
||||
StringHandlers.CToString(homeblock.format) != "DECFILE11B ")
|
||||
{
|
||||
if(hb_sector.Length < 0x400) return;
|
||||
if(hbSector.Length < 0x400) return;
|
||||
|
||||
byte[] tmp = imagePlugin.ReadSector(partition.Start);
|
||||
hb_sector = new byte[0x200];
|
||||
Array.Copy(tmp, 0x200, hb_sector, 0, 0x200);
|
||||
hbSector = new byte[0x200];
|
||||
Array.Copy(tmp, 0x200, hbSector, 0, 0x200);
|
||||
|
||||
handle = GCHandle.Alloc(hb_sector, GCHandleType.Pinned);
|
||||
homeblock = (ODSHomeBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(ODSHomeBlock));
|
||||
handle = GCHandle.Alloc(hbSector, GCHandleType.Pinned);
|
||||
homeblock = (OdsHomeBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(OdsHomeBlock));
|
||||
handle.Free();
|
||||
|
||||
if(StringHandlers.CToString(homeblock.format) != "DECFILE11A " &&
|
||||
@@ -200,41 +192,25 @@ namespace DiscImageChef.Filesystems
|
||||
sb.AppendLine("Volume permissions (r = read, w = write, c = create, d = delete)");
|
||||
sb.AppendLine("System, owner, group, world");
|
||||
// System
|
||||
if((homeblock.protect & 0x1000) == 0x1000) sb.Append("-");
|
||||
else sb.Append("r");
|
||||
if((homeblock.protect & 0x2000) == 0x2000) sb.Append("-");
|
||||
else sb.Append("w");
|
||||
if((homeblock.protect & 0x4000) == 0x4000) sb.Append("-");
|
||||
else sb.Append("c");
|
||||
if((homeblock.protect & 0x8000) == 0x8000) sb.Append("-");
|
||||
else sb.Append("d");
|
||||
sb.Append((homeblock.protect & 0x1000) == 0x1000 ? "-" : "r");
|
||||
sb.Append((homeblock.protect & 0x2000) == 0x2000 ? "-" : "w");
|
||||
sb.Append((homeblock.protect & 0x4000) == 0x4000 ? "-" : "c");
|
||||
sb.Append((homeblock.protect & 0x8000) == 0x8000 ? "-" : "d");
|
||||
// Owner
|
||||
if((homeblock.protect & 0x100) == 0x100) sb.Append("-");
|
||||
else sb.Append("r");
|
||||
if((homeblock.protect & 0x200) == 0x200) sb.Append("-");
|
||||
else sb.Append("w");
|
||||
if((homeblock.protect & 0x400) == 0x400) sb.Append("-");
|
||||
else sb.Append("c");
|
||||
if((homeblock.protect & 0x800) == 0x800) sb.Append("-");
|
||||
else sb.Append("d");
|
||||
sb.Append((homeblock.protect & 0x100) == 0x100 ? "-" : "r");
|
||||
sb.Append((homeblock.protect & 0x200) == 0x200 ? "-" : "w");
|
||||
sb.Append((homeblock.protect & 0x400) == 0x400 ? "-" : "c");
|
||||
sb.Append((homeblock.protect & 0x800) == 0x800 ? "-" : "d");
|
||||
// Group
|
||||
if((homeblock.protect & 0x10) == 0x10) sb.Append("-");
|
||||
else sb.Append("r");
|
||||
if((homeblock.protect & 0x20) == 0x20) sb.Append("-");
|
||||
else sb.Append("w");
|
||||
if((homeblock.protect & 0x40) == 0x40) sb.Append("-");
|
||||
else sb.Append("c");
|
||||
if((homeblock.protect & 0x80) == 0x80) sb.Append("-");
|
||||
else sb.Append("d");
|
||||
sb.Append((homeblock.protect & 0x10) == 0x10 ? "-" : "r");
|
||||
sb.Append((homeblock.protect & 0x20) == 0x20 ? "-" : "w");
|
||||
sb.Append((homeblock.protect & 0x40) == 0x40 ? "-" : "c");
|
||||
sb.Append((homeblock.protect & 0x80) == 0x80 ? "-" : "d");
|
||||
// World (other)
|
||||
if((homeblock.protect & 0x1) == 0x1) sb.Append("-");
|
||||
else sb.Append("r");
|
||||
if((homeblock.protect & 0x2) == 0x2) sb.Append("-");
|
||||
else sb.Append("w");
|
||||
if((homeblock.protect & 0x4) == 0x4) sb.Append("-");
|
||||
else sb.Append("c");
|
||||
if((homeblock.protect & 0x8) == 0x8) sb.Append("-");
|
||||
else sb.Append("d");
|
||||
sb.Append((homeblock.protect & 0x1) == 0x1 ? "-" : "r");
|
||||
sb.Append((homeblock.protect & 0x2) == 0x2 ? "-" : "w");
|
||||
sb.Append((homeblock.protect & 0x4) == 0x4 ? "-" : "c");
|
||||
sb.Append((homeblock.protect & 0x8) == 0x8 ? "-" : "d");
|
||||
|
||||
sb.AppendLine();
|
||||
|
||||
@@ -243,7 +219,7 @@ namespace DiscImageChef.Filesystems
|
||||
sb.AppendFormat("File protection: 0x{0:X4}", homeblock.fileprot).AppendLine();
|
||||
sb.AppendFormat("Record protection: 0x{0:X4}", homeblock.recprot).AppendLine();
|
||||
|
||||
xmlFSType = new FileSystemType
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
Type = "FILES-11",
|
||||
ClusterSize = homeblock.cluster * 512,
|
||||
@@ -253,20 +229,20 @@ namespace DiscImageChef.Filesystems
|
||||
};
|
||||
if(homeblock.credate > 0)
|
||||
{
|
||||
xmlFSType.CreationDate = DateHandlers.VMSToDateTime(homeblock.credate);
|
||||
xmlFSType.CreationDateSpecified = true;
|
||||
XmlFsType.CreationDate = DateHandlers.VMSToDateTime(homeblock.credate);
|
||||
XmlFsType.CreationDateSpecified = true;
|
||||
}
|
||||
if(homeblock.revdate > 0)
|
||||
{
|
||||
xmlFSType.ModificationDate = DateHandlers.VMSToDateTime(homeblock.revdate);
|
||||
xmlFSType.ModificationDateSpecified = true;
|
||||
XmlFsType.ModificationDate = DateHandlers.VMSToDateTime(homeblock.revdate);
|
||||
XmlFsType.ModificationDateSpecified = true;
|
||||
}
|
||||
|
||||
information = sb.ToString();
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
struct ODSHomeBlock
|
||||
struct OdsHomeBlock
|
||||
{
|
||||
/// <summary>0x000, LBN of THIS home block</summary>
|
||||
public uint homelbn;
|
||||
|
||||
@@ -45,14 +45,14 @@ namespace DiscImageChef.Filesystems
|
||||
public OperaFS()
|
||||
{
|
||||
Name = "Opera Filesystem Plugin";
|
||||
PluginUUID = new Guid("0ec84ec7-eae6-4196-83fe-943b3fe46dbd");
|
||||
PluginUuid = new Guid("0ec84ec7-eae6-4196-83fe-943b3fe46dbd");
|
||||
CurrentEncoding = Encoding.ASCII;
|
||||
}
|
||||
|
||||
public OperaFS(Encoding encoding)
|
||||
{
|
||||
Name = "Opera Filesystem Plugin";
|
||||
PluginUUID = new Guid("0ec84ec7-eae6-4196-83fe-943b3fe46dbd");
|
||||
PluginUuid = new Guid("0ec84ec7-eae6-4196-83fe-943b3fe46dbd");
|
||||
// TODO: Find correct default encoding
|
||||
CurrentEncoding = Encoding.ASCII;
|
||||
}
|
||||
@@ -60,7 +60,7 @@ namespace DiscImageChef.Filesystems
|
||||
public OperaFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "Opera Filesystem Plugin";
|
||||
PluginUUID = new Guid("0ec84ec7-eae6-4196-83fe-943b3fe46dbd");
|
||||
PluginUuid = new Guid("0ec84ec7-eae6-4196-83fe-943b3fe46dbd");
|
||||
// TODO: Find correct default encoding
|
||||
CurrentEncoding = Encoding.ASCII;
|
||||
}
|
||||
@@ -69,75 +69,72 @@ namespace DiscImageChef.Filesystems
|
||||
{
|
||||
if(2 + partition.Start >= partition.End) return false;
|
||||
|
||||
byte[] sb_sector = imagePlugin.ReadSector(0 + partition.Start);
|
||||
byte[] sbSector = imagePlugin.ReadSector(0 + partition.Start);
|
||||
|
||||
byte record_type;
|
||||
byte[] sync_bytes = new byte[5];
|
||||
byte record_version;
|
||||
byte[] syncBytes = new byte[5];
|
||||
|
||||
record_type = sb_sector[0x000];
|
||||
Array.Copy(sb_sector, 0x001, sync_bytes, 0, 5);
|
||||
record_version = sb_sector[0x006];
|
||||
byte recordType = sbSector[0x000];
|
||||
Array.Copy(sbSector, 0x001, syncBytes, 0, 5);
|
||||
byte recordVersion = sbSector[0x006];
|
||||
|
||||
if(record_type != 1 || record_version != 1) return false;
|
||||
if(recordType != 1 || recordVersion != 1) return false;
|
||||
|
||||
return Encoding.ASCII.GetString(sync_bytes) == "ZZZZZ";
|
||||
return Encoding.ASCII.GetString(syncBytes) == "ZZZZZ";
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
|
||||
out string information)
|
||||
{
|
||||
information = "";
|
||||
StringBuilder SuperBlockMetadata = new StringBuilder();
|
||||
StringBuilder superBlockMetadata = new StringBuilder();
|
||||
|
||||
byte[] sb_sector = imagePlugin.ReadSector(0 + partition.Start);
|
||||
byte[] sbSector = imagePlugin.ReadSector(0 + partition.Start);
|
||||
|
||||
OperaSuperBlock sb = BigEndianMarshal.ByteArrayToStructureBigEndian<OperaSuperBlock>(sb_sector);
|
||||
byte[] cString = new byte[32];
|
||||
OperaSuperBlock sb = BigEndianMarshal.ByteArrayToStructureBigEndian<OperaSuperBlock>(sbSector);
|
||||
sb.sync_bytes = new byte[5];
|
||||
|
||||
if(sb.record_type != 1 || sb.record_version != 1) return;
|
||||
if(Encoding.ASCII.GetString(sb.sync_bytes) != "ZZZZZ") return;
|
||||
|
||||
SuperBlockMetadata.AppendFormat("Opera filesystem disc.").AppendLine();
|
||||
superBlockMetadata.AppendFormat("Opera filesystem disc.").AppendLine();
|
||||
if(!string.IsNullOrEmpty(StringHandlers.CToString(sb.volume_label, CurrentEncoding)))
|
||||
SuperBlockMetadata
|
||||
superBlockMetadata
|
||||
.AppendFormat("Volume label: {0}", StringHandlers.CToString(sb.volume_label, CurrentEncoding))
|
||||
.AppendLine();
|
||||
if(!string.IsNullOrEmpty(StringHandlers.CToString(sb.volume_comment, CurrentEncoding)))
|
||||
SuperBlockMetadata.AppendFormat("Volume comment: {0}",
|
||||
superBlockMetadata.AppendFormat("Volume comment: {0}",
|
||||
StringHandlers.CToString(sb.volume_comment, CurrentEncoding))
|
||||
.AppendLine();
|
||||
SuperBlockMetadata.AppendFormat("Volume identifier: 0x{0:X8}", sb.volume_id).AppendLine();
|
||||
SuperBlockMetadata.AppendFormat("Block size: {0} bytes", sb.block_size).AppendLine();
|
||||
superBlockMetadata.AppendFormat("Volume identifier: 0x{0:X8}", sb.volume_id).AppendLine();
|
||||
superBlockMetadata.AppendFormat("Block size: {0} bytes", sb.block_size).AppendLine();
|
||||
if(imagePlugin.GetSectorSize() == 2336 || imagePlugin.GetSectorSize() == 2352 ||
|
||||
imagePlugin.GetSectorSize() == 2448)
|
||||
{
|
||||
if(sb.block_size != 2048)
|
||||
SuperBlockMetadata
|
||||
superBlockMetadata
|
||||
.AppendFormat("WARNING: Filesystem indicates {0} bytes/block while device indicates {1} bytes/block",
|
||||
sb.block_size, 2048);
|
||||
}
|
||||
else if(imagePlugin.GetSectorSize() != sb.block_size)
|
||||
SuperBlockMetadata
|
||||
superBlockMetadata
|
||||
.AppendFormat("WARNING: Filesystem indicates {0} bytes/block while device indicates {1} bytes/block",
|
||||
sb.block_size, imagePlugin.GetSectorSize());
|
||||
SuperBlockMetadata
|
||||
superBlockMetadata
|
||||
.AppendFormat("Volume size: {0} blocks, {1} bytes", sb.block_count, sb.block_size * sb.block_count)
|
||||
.AppendLine();
|
||||
if((ulong)sb.block_count > imagePlugin.GetSectors())
|
||||
SuperBlockMetadata
|
||||
superBlockMetadata
|
||||
.AppendFormat("WARNING: Filesystem indicates {0} blocks while device indicates {1} blocks",
|
||||
sb.block_count, imagePlugin.GetSectors());
|
||||
SuperBlockMetadata.AppendFormat("Root directory identifier: 0x{0:X8}", sb.root_dirid).AppendLine();
|
||||
SuperBlockMetadata.AppendFormat("Root directory block size: {0} bytes", sb.rootdir_bsize).AppendLine();
|
||||
SuperBlockMetadata.AppendFormat("Root directory size: {0} blocks, {1} bytes", sb.rootdir_blocks,
|
||||
superBlockMetadata.AppendFormat("Root directory identifier: 0x{0:X8}", sb.root_dirid).AppendLine();
|
||||
superBlockMetadata.AppendFormat("Root directory block size: {0} bytes", sb.rootdir_bsize).AppendLine();
|
||||
superBlockMetadata.AppendFormat("Root directory size: {0} blocks, {1} bytes", sb.rootdir_blocks,
|
||||
sb.rootdir_bsize * sb.rootdir_blocks).AppendLine();
|
||||
SuperBlockMetadata.AppendFormat("Last root directory copy: {0}", sb.last_root_copy).AppendLine();
|
||||
superBlockMetadata.AppendFormat("Last root directory copy: {0}", sb.last_root_copy).AppendLine();
|
||||
|
||||
information = SuperBlockMetadata.ToString();
|
||||
information = superBlockMetadata.ToString();
|
||||
|
||||
xmlFSType = new FileSystemType
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
Type = "Opera",
|
||||
VolumeName = StringHandlers.CToString(sb.volume_label, CurrentEncoding),
|
||||
|
||||
@@ -44,46 +44,46 @@ namespace DiscImageChef.Filesystems
|
||||
public PCEnginePlugin()
|
||||
{
|
||||
Name = "PC Engine CD Plugin";
|
||||
PluginUUID = new Guid("e5ee6d7c-90fa-49bd-ac89-14ef750b8af3");
|
||||
PluginUuid = new Guid("e5ee6d7c-90fa-49bd-ac89-14ef750b8af3");
|
||||
CurrentEncoding = Encoding.GetEncoding("shift_jis");
|
||||
}
|
||||
|
||||
public PCEnginePlugin(Encoding encoding)
|
||||
{
|
||||
Name = "PC Engine CD Plugin";
|
||||
PluginUUID = new Guid("e5ee6d7c-90fa-49bd-ac89-14ef750b8af3");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("shift_jis");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("e5ee6d7c-90fa-49bd-ac89-14ef750b8af3");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("shift_jis");
|
||||
}
|
||||
|
||||
public PCEnginePlugin(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "PC Engine CD Plugin";
|
||||
PluginUUID = new Guid("e5ee6d7c-90fa-49bd-ac89-14ef750b8af3");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("shift_jis");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("e5ee6d7c-90fa-49bd-ac89-14ef750b8af3");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("shift_jis");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugin imagePlugin, Partition partition)
|
||||
{
|
||||
if(2 + partition.Start >= partition.End) return false;
|
||||
|
||||
byte[] system_descriptor = new byte[23];
|
||||
byte[] systemDescriptor = new byte[23];
|
||||
byte[] sector = imagePlugin.ReadSector(1 + partition.Start);
|
||||
|
||||
Array.Copy(sector, 0x20, system_descriptor, 0, 23);
|
||||
Array.Copy(sector, 0x20, systemDescriptor, 0, 23);
|
||||
|
||||
return Encoding.ASCII.GetString(system_descriptor) == "PC Engine CD-ROM SYSTEM";
|
||||
return Encoding.ASCII.GetString(systemDescriptor) == "PC Engine CD-ROM SYSTEM";
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
|
||||
out string information)
|
||||
{
|
||||
information = "";
|
||||
xmlFSType = new FileSystemType();
|
||||
xmlFSType.Type = "PC Engine filesystem";
|
||||
xmlFSType.Clusters = (long)((partition.End - partition.Start + 1) / imagePlugin.GetSectorSize() * 2048);
|
||||
xmlFSType.ClusterSize = 2048;
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
Type = "PC Engine filesystem",
|
||||
Clusters = (long)((partition.End - partition.Start + 1) / imagePlugin.GetSectorSize() * 2048),
|
||||
ClusterSize = 2048
|
||||
};
|
||||
}
|
||||
|
||||
public override Errno Mount()
|
||||
|
||||
@@ -45,24 +45,22 @@ namespace DiscImageChef.Filesystems
|
||||
public PFS()
|
||||
{
|
||||
Name = "Professional File System";
|
||||
PluginUUID = new Guid("68DE769E-D957-406A-8AE4-3781CA8CDA77");
|
||||
PluginUuid = new Guid("68DE769E-D957-406A-8AE4-3781CA8CDA77");
|
||||
CurrentEncoding = Encoding.GetEncoding("iso-8859-1");
|
||||
}
|
||||
|
||||
public PFS(Encoding encoding)
|
||||
{
|
||||
Name = "Professional File System";
|
||||
PluginUUID = new Guid("68DE769E-D957-406A-8AE4-3781CA8CDA77");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-1");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("68DE769E-D957-406A-8AE4-3781CA8CDA77");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1");
|
||||
}
|
||||
|
||||
public PFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "Professional File System";
|
||||
PluginUUID = new Guid("68DE769E-D957-406A-8AE4-3781CA8CDA77");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-1");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("68DE769E-D957-406A-8AE4-3781CA8CDA77");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -204,28 +202,27 @@ namespace DiscImageChef.Filesystems
|
||||
public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
|
||||
out string information)
|
||||
{
|
||||
byte[] RootBlockSector = imagePlugin.ReadSector(2 + partition.Start);
|
||||
RootBlock rootBlock;
|
||||
rootBlock = BigEndianMarshal.ByteArrayToStructureBigEndian<RootBlock>(RootBlockSector);
|
||||
byte[] rootBlockSector = imagePlugin.ReadSector(2 + partition.Start);
|
||||
RootBlock rootBlock = BigEndianMarshal.ByteArrayToStructureBigEndian<RootBlock>(rootBlockSector);
|
||||
|
||||
StringBuilder sbInformation = new StringBuilder();
|
||||
xmlFSType = new FileSystemType();
|
||||
XmlFsType = new FileSystemType();
|
||||
|
||||
switch(rootBlock.diskType)
|
||||
{
|
||||
case AFS_DISK:
|
||||
case MUAF_DISK:
|
||||
sbInformation.Append("Professional File System v1");
|
||||
xmlFSType.Type = "PFS v1";
|
||||
XmlFsType.Type = "PFS v1";
|
||||
break;
|
||||
case PFS2_DISK:
|
||||
sbInformation.Append("Professional File System v2");
|
||||
xmlFSType.Type = "PFS v2";
|
||||
XmlFsType.Type = "PFS v2";
|
||||
break;
|
||||
case PFS_DISK:
|
||||
case MUPFS_DISK:
|
||||
sbInformation.Append("Professional File System v3");
|
||||
xmlFSType.Type = "PFS v3";
|
||||
XmlFsType.Type = "PFS v3";
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -248,14 +245,14 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
information = sbInformation.ToString();
|
||||
|
||||
xmlFSType.CreationDate =
|
||||
XmlFsType.CreationDate =
|
||||
DateHandlers.AmigaToDateTime(rootBlock.creationday, rootBlock.creationminute, rootBlock.creationtick);
|
||||
xmlFSType.CreationDateSpecified = true;
|
||||
xmlFSType.FreeClusters = rootBlock.blocksfree;
|
||||
xmlFSType.FreeClustersSpecified = true;
|
||||
xmlFSType.Clusters = rootBlock.diskSize;
|
||||
xmlFSType.ClusterSize = (int)imagePlugin.GetSectorSize();
|
||||
xmlFSType.VolumeName = StringHandlers.PascalToString(rootBlock.diskname, CurrentEncoding);
|
||||
XmlFsType.CreationDateSpecified = true;
|
||||
XmlFsType.FreeClusters = rootBlock.blocksfree;
|
||||
XmlFsType.FreeClustersSpecified = true;
|
||||
XmlFsType.Clusters = rootBlock.diskSize;
|
||||
XmlFsType.ClusterSize = (int)imagePlugin.GetSectorSize();
|
||||
XmlFsType.VolumeName = StringHandlers.PascalToString(rootBlock.diskname, CurrentEncoding);
|
||||
}
|
||||
|
||||
public override Errno Mount()
|
||||
|
||||
@@ -46,55 +46,55 @@ namespace DiscImageChef.Filesystems
|
||||
// Information from Apple ProDOS 8 Technical Reference
|
||||
public class ProDOSPlugin : Filesystem
|
||||
{
|
||||
const byte EmptyStorageType = 0x00;
|
||||
const byte EMPTY_STORAGE_TYPE = 0x00;
|
||||
/// <summary>
|
||||
/// A file that occupies one block or less
|
||||
/// </summary>
|
||||
const byte SeedlingFileType = 0x01;
|
||||
const byte SEEDLING_FILE_TYPE = 0x01;
|
||||
/// <summary>
|
||||
/// A file that occupies between 2 and 256 blocks
|
||||
/// </summary>
|
||||
const byte SaplingFileType = 0x02;
|
||||
const byte SAPLING_FILE_TYPE = 0x02;
|
||||
/// <summary>
|
||||
/// A file that occupies between 257 and 32768 blocks
|
||||
/// </summary>
|
||||
const byte TreeFileType = 0x03;
|
||||
const byte PascalAreaType = 0x04;
|
||||
const byte SubDirectoryType = 0x0D;
|
||||
const byte SubDirectoryHeaderType = 0x0E;
|
||||
const byte RootDirectoryType = 0x0F;
|
||||
const byte TREE_FILE_TYPE = 0x03;
|
||||
const byte PASCAL_AREA_TYPE = 0x04;
|
||||
const byte SUBDIRECTORY_TYPE = 0x0D;
|
||||
const byte SUBDIRECTORY_HEADER_TYPE = 0x0E;
|
||||
const byte ROOT_DIRECTORY_TYPE = 0x0F;
|
||||
|
||||
const byte ProDOSVersion1 = 0x00;
|
||||
const byte VERSION1 = 0x00;
|
||||
|
||||
const uint ProDOSYearMask = 0xFE000000;
|
||||
const uint ProDOSMonthMask = 0x1E00000;
|
||||
const uint ProDOSDayMask = 0x1F0000;
|
||||
const uint ProDOSHourMask = 0x1F00;
|
||||
const uint ProDOSMinuteMask = 0x3F;
|
||||
const uint YEAR_MASK = 0xFE000000;
|
||||
const uint MONTH_MASK = 0x1E00000;
|
||||
const uint DAY_MASK = 0x1F0000;
|
||||
const uint HOUR_MASK = 0x1F00;
|
||||
const uint MINUTE_MASK = 0x3F;
|
||||
|
||||
const byte ProDOSDestroyAttribute = 0x80;
|
||||
const byte ProDOSRenameAttribute = 0x40;
|
||||
const byte ProDOSBackupAttribute = 0x20;
|
||||
const byte ProDOSWriteAttribute = 0x02;
|
||||
const byte ProDOSReadAttribute = 0x01;
|
||||
const byte ProDOSReservedAttributeMask = 0x1C;
|
||||
const byte DESTROY_ATTRIBUTE = 0x80;
|
||||
const byte RENAME_ATTRIBUTE = 0x40;
|
||||
const byte BACKUP_ATTRIBUTE = 0x20;
|
||||
const byte WRITE_ATTRIBUTE = 0x02;
|
||||
const byte READ_ATTRIBUTE = 0x01;
|
||||
const byte RESERVED_ATTRIBUTE_MASK = 0x1C;
|
||||
|
||||
const byte ProDOSStorageTypeMask = 0xF0;
|
||||
const byte ProDOSNameLengthMask = 0x0F;
|
||||
const byte ProDOSEntryLength = 0x27;
|
||||
const byte ProDOSEntriesPerBlock = 0x0D;
|
||||
const byte STORAGE_TYPE_MASK = 0xF0;
|
||||
const byte NAME_LENGTH_MASK = 0x0F;
|
||||
const byte ENTRY_LENGTH = 0x27;
|
||||
const byte ENTRIES_PER_BLOCK = 0x0D;
|
||||
|
||||
public ProDOSPlugin()
|
||||
{
|
||||
Name = "Apple ProDOS filesystem";
|
||||
PluginUUID = new Guid("43874265-7B8A-4739-BCF7-07F80D5932BF");
|
||||
PluginUuid = new Guid("43874265-7B8A-4739-BCF7-07F80D5932BF");
|
||||
CurrentEncoding = new LisaRoman();
|
||||
}
|
||||
|
||||
public ProDOSPlugin(Encoding encoding)
|
||||
{
|
||||
Name = "Apple ProDOS filesystem";
|
||||
PluginUUID = new Guid("43874265-7B8A-4739-BCF7-07F80D5932BF");
|
||||
PluginUuid = new Guid("43874265-7B8A-4739-BCF7-07F80D5932BF");
|
||||
// TODO: Until Apple ][ encoding is implemented
|
||||
CurrentEncoding = new LisaRoman();
|
||||
}
|
||||
@@ -102,7 +102,7 @@ namespace DiscImageChef.Filesystems
|
||||
public ProDOSPlugin(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "Apple ProDOS filesystem";
|
||||
PluginUUID = new Guid("43874265-7B8A-4739-BCF7-07F80D5932BF");
|
||||
PluginUuid = new Guid("43874265-7B8A-4739-BCF7-07F80D5932BF");
|
||||
// TODO: Until Apple ][ encoding is implemented
|
||||
CurrentEncoding = new LisaRoman();
|
||||
}
|
||||
@@ -121,8 +121,8 @@ namespace DiscImageChef.Filesystems
|
||||
byte[] tmp = imagePlugin.ReadSectors(partition.Start, 2);
|
||||
|
||||
foreach(int offset in new[] {0, 0x200, 0x400, 0x600, 0x800, 0xA00}.Where(offset => BitConverter.ToUInt16(tmp, offset) == 0 &&
|
||||
(byte)((tmp[offset + 0x04] & ProDOSStorageTypeMask) >> 4) == RootDirectoryType &&
|
||||
tmp[offset + 0x23] == ProDOSEntryLength && tmp[offset + 0x24] == ProDOSEntriesPerBlock)) {
|
||||
(byte)((tmp[offset + 0x04] & STORAGE_TYPE_MASK) >> 4) == ROOT_DIRECTORY_TYPE &&
|
||||
tmp[offset + 0x23] == ENTRY_LENGTH && tmp[offset + 0x24] == ENTRIES_PER_BLOCK)) {
|
||||
Array.Copy(tmp, offset, rootDirectoryKeyBlock, 0, 0x200);
|
||||
APMFromHDDOnCD = true;
|
||||
break;
|
||||
@@ -133,28 +133,28 @@ namespace DiscImageChef.Filesystems
|
||||
DicConsole.DebugWriteLine("ProDOS plugin", "prePointer = {0}", prePointer);
|
||||
if(prePointer != 0) return false;
|
||||
|
||||
byte storage_type = (byte)((rootDirectoryKeyBlock[0x04] & ProDOSStorageTypeMask) >> 4);
|
||||
DicConsole.DebugWriteLine("ProDOS plugin", "storage_type = {0}", storage_type);
|
||||
if(storage_type != RootDirectoryType) return false;
|
||||
byte storageType = (byte)((rootDirectoryKeyBlock[0x04] & STORAGE_TYPE_MASK) >> 4);
|
||||
DicConsole.DebugWriteLine("ProDOS plugin", "storage_type = {0}", storageType);
|
||||
if(storageType != ROOT_DIRECTORY_TYPE) return false;
|
||||
|
||||
byte entry_length = rootDirectoryKeyBlock[0x23];
|
||||
DicConsole.DebugWriteLine("ProDOS plugin", "entry_length = {0}", entry_length);
|
||||
if(entry_length != ProDOSEntryLength) return false;
|
||||
byte entryLength = rootDirectoryKeyBlock[0x23];
|
||||
DicConsole.DebugWriteLine("ProDOS plugin", "entry_length = {0}", entryLength);
|
||||
if(entryLength != ENTRY_LENGTH) return false;
|
||||
|
||||
byte entries_per_block = rootDirectoryKeyBlock[0x24];
|
||||
DicConsole.DebugWriteLine("ProDOS plugin", "entries_per_block = {0}", entries_per_block);
|
||||
if(entries_per_block != ProDOSEntriesPerBlock) return false;
|
||||
byte entriesPerBlock = rootDirectoryKeyBlock[0x24];
|
||||
DicConsole.DebugWriteLine("ProDOS plugin", "entries_per_block = {0}", entriesPerBlock);
|
||||
if(entriesPerBlock != ENTRIES_PER_BLOCK) return false;
|
||||
|
||||
ushort bit_map_pointer = BitConverter.ToUInt16(rootDirectoryKeyBlock, 0x27);
|
||||
DicConsole.DebugWriteLine("ProDOS plugin", "bit_map_pointer = {0}", bit_map_pointer);
|
||||
if(bit_map_pointer > partition.End) return false;
|
||||
ushort bitMapPointer = BitConverter.ToUInt16(rootDirectoryKeyBlock, 0x27);
|
||||
DicConsole.DebugWriteLine("ProDOS plugin", "bit_map_pointer = {0}", bitMapPointer);
|
||||
if(bitMapPointer > partition.End) return false;
|
||||
|
||||
ushort total_blocks = BitConverter.ToUInt16(rootDirectoryKeyBlock, 0x29);
|
||||
if(APMFromHDDOnCD) total_blocks /= 4;
|
||||
ushort totalBlocks = BitConverter.ToUInt16(rootDirectoryKeyBlock, 0x29);
|
||||
if(APMFromHDDOnCD) totalBlocks /= 4;
|
||||
|
||||
DicConsole.DebugWriteLine("ProDOS plugin", "{0} <= ({1} - {2} + 1)? {3}", total_blocks, partition.End,
|
||||
partition.Start, total_blocks <= partition.End - partition.Start + 1);
|
||||
return total_blocks <= partition.End - partition.Start + 1;
|
||||
DicConsole.DebugWriteLine("ProDOS plugin", "{0} <= ({1} - {2} + 1)? {3}", totalBlocks, partition.End,
|
||||
partition.Start, totalBlocks <= partition.End - partition.Start + 1);
|
||||
return totalBlocks <= partition.End - partition.Start + 1;
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
|
||||
@@ -173,50 +173,45 @@ namespace DiscImageChef.Filesystems
|
||||
byte[] tmp = imagePlugin.ReadSectors(partition.Start, 2);
|
||||
|
||||
foreach(int offset in new[] {0, 0x200, 0x400, 0x600, 0x800, 0xA00}.Where(offset => BitConverter.ToUInt16(tmp, offset) == 0 &&
|
||||
(byte)((tmp[offset + 0x04] & ProDOSStorageTypeMask) >> 4) == RootDirectoryType &&
|
||||
tmp[offset + 0x23] == ProDOSEntryLength && tmp[offset + 0x24] == ProDOSEntriesPerBlock)) {
|
||||
(byte)((tmp[offset + 0x04] & STORAGE_TYPE_MASK) >> 4) == ROOT_DIRECTORY_TYPE &&
|
||||
tmp[offset + 0x23] == ENTRY_LENGTH && tmp[offset + 0x24] == ENTRIES_PER_BLOCK)) {
|
||||
Array.Copy(tmp, offset, rootDirectoryKeyBlockBytes, 0, 0x200);
|
||||
APMFromHDDOnCD = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ProDOSRootDirectoryKeyBlock rootDirectoryKeyBlock = new ProDOSRootDirectoryKeyBlock();
|
||||
rootDirectoryKeyBlock.header = new ProDOSRootDirectoryHeader();
|
||||
|
||||
byte[] temporal;
|
||||
int year, month, day, hour, minute;
|
||||
ushort temp_timestamp_left, temp_timestamp_right;
|
||||
uint temp_timestamp;
|
||||
ProDOSRootDirectoryKeyBlock rootDirectoryKeyBlock =
|
||||
new ProDOSRootDirectoryKeyBlock {header = new ProDOSRootDirectoryHeader()};
|
||||
|
||||
rootDirectoryKeyBlock.zero = BitConverter.ToUInt16(rootDirectoryKeyBlockBytes, 0x00);
|
||||
rootDirectoryKeyBlock.next_pointer = BitConverter.ToUInt16(rootDirectoryKeyBlockBytes, 0x02);
|
||||
rootDirectoryKeyBlock.header.storage_type =
|
||||
(byte)((rootDirectoryKeyBlockBytes[0x04] & ProDOSStorageTypeMask) >> 4);
|
||||
rootDirectoryKeyBlock.header.name_length = (byte)(rootDirectoryKeyBlockBytes[0x04] & ProDOSNameLengthMask);
|
||||
temporal = new byte[rootDirectoryKeyBlock.header.name_length];
|
||||
(byte)((rootDirectoryKeyBlockBytes[0x04] & STORAGE_TYPE_MASK) >> 4);
|
||||
rootDirectoryKeyBlock.header.name_length = (byte)(rootDirectoryKeyBlockBytes[0x04] & NAME_LENGTH_MASK);
|
||||
byte[] temporal = new byte[rootDirectoryKeyBlock.header.name_length];
|
||||
Array.Copy(rootDirectoryKeyBlockBytes, 0x05, temporal, 0, rootDirectoryKeyBlock.header.name_length);
|
||||
rootDirectoryKeyBlock.header.volume_name = CurrentEncoding.GetString(temporal);
|
||||
rootDirectoryKeyBlock.header.reserved = BitConverter.ToUInt64(rootDirectoryKeyBlockBytes, 0x14);
|
||||
|
||||
temp_timestamp_left = BitConverter.ToUInt16(rootDirectoryKeyBlockBytes, 0x1C);
|
||||
temp_timestamp_right = BitConverter.ToUInt16(rootDirectoryKeyBlockBytes, 0x1E);
|
||||
ushort tempTimestampLeft = BitConverter.ToUInt16(rootDirectoryKeyBlockBytes, 0x1C);
|
||||
ushort tempTimestampRight = BitConverter.ToUInt16(rootDirectoryKeyBlockBytes, 0x1E);
|
||||
|
||||
bool dateCorrect;
|
||||
try
|
||||
{
|
||||
temp_timestamp = (uint)((temp_timestamp_left << 16) + temp_timestamp_right);
|
||||
year = (int)((temp_timestamp & ProDOSYearMask) >> 25);
|
||||
month = (int)((temp_timestamp & ProDOSMonthMask) >> 21);
|
||||
day = (int)((temp_timestamp & ProDOSDayMask) >> 16);
|
||||
hour = (int)((temp_timestamp & ProDOSHourMask) >> 8);
|
||||
minute = (int)(temp_timestamp & ProDOSMinuteMask);
|
||||
uint tempTimestamp = (uint)((tempTimestampLeft << 16) + tempTimestampRight);
|
||||
int year = (int)((tempTimestamp & YEAR_MASK) >> 25);
|
||||
int month = (int)((tempTimestamp & MONTH_MASK) >> 21);
|
||||
int day = (int)((tempTimestamp & DAY_MASK) >> 16);
|
||||
int hour = (int)((tempTimestamp & HOUR_MASK) >> 8);
|
||||
int minute = (int)(tempTimestamp & MINUTE_MASK);
|
||||
year += 1900;
|
||||
if(year < 1940) year += 100;
|
||||
|
||||
DicConsole.DebugWriteLine("ProDOS plugin", "temp_timestamp_left = 0x{0:X4}", temp_timestamp_left);
|
||||
DicConsole.DebugWriteLine("ProDOS plugin", "temp_timestamp_right = 0x{0:X4}", temp_timestamp_right);
|
||||
DicConsole.DebugWriteLine("ProDOS plugin", "temp_timestamp = 0x{0:X8}", temp_timestamp);
|
||||
DicConsole.DebugWriteLine("ProDOS plugin", "temp_timestamp_left = 0x{0:X4}", tempTimestampLeft);
|
||||
DicConsole.DebugWriteLine("ProDOS plugin", "temp_timestamp_right = 0x{0:X4}", tempTimestampRight);
|
||||
DicConsole.DebugWriteLine("ProDOS plugin", "temp_timestamp = 0x{0:X8}", tempTimestamp);
|
||||
DicConsole.DebugWriteLine("ProDOS plugin",
|
||||
"Datetime field year {0}, month {1}, day {2}, hour {3}, minute {4}.", year,
|
||||
month, day, hour, minute);
|
||||
@@ -240,20 +235,20 @@ namespace DiscImageChef.Filesystems
|
||||
sbInformation.AppendLine("ProDOS uses 512 bytes/sector while devices uses 2048 bytes/sector.")
|
||||
.AppendLine();
|
||||
|
||||
if(rootDirectoryKeyBlock.header.version != ProDOSVersion1 ||
|
||||
rootDirectoryKeyBlock.header.min_version != ProDOSVersion1)
|
||||
if(rootDirectoryKeyBlock.header.version != VERSION1 ||
|
||||
rootDirectoryKeyBlock.header.min_version != VERSION1)
|
||||
{
|
||||
sbInformation.AppendLine("Warning! Detected unknown ProDOS version ProDOS filesystem.");
|
||||
sbInformation.AppendLine("All of the following information may be incorrect");
|
||||
}
|
||||
|
||||
if(rootDirectoryKeyBlock.header.version == ProDOSVersion1)
|
||||
if(rootDirectoryKeyBlock.header.version == VERSION1)
|
||||
sbInformation.AppendLine("ProDOS version 1 used to create this volume.");
|
||||
else
|
||||
sbInformation.AppendFormat("Unknown ProDOS version with field {0} used to create this volume.",
|
||||
rootDirectoryKeyBlock.header.version).AppendLine();
|
||||
|
||||
if(rootDirectoryKeyBlock.header.min_version == ProDOSVersion1)
|
||||
if(rootDirectoryKeyBlock.header.min_version == VERSION1)
|
||||
sbInformation.AppendLine("ProDOS version 1 at least required for reading this volume.");
|
||||
else
|
||||
sbInformation
|
||||
@@ -275,36 +270,36 @@ namespace DiscImageChef.Filesystems
|
||||
sbInformation.AppendFormat("Bitmap starts at block {0}", rootDirectoryKeyBlock.header.bit_map_pointer)
|
||||
.AppendLine();
|
||||
|
||||
if((rootDirectoryKeyBlock.header.access & ProDOSReadAttribute) == ProDOSReadAttribute)
|
||||
if((rootDirectoryKeyBlock.header.access & READ_ATTRIBUTE) == READ_ATTRIBUTE)
|
||||
sbInformation.AppendLine("Volume can be read");
|
||||
if((rootDirectoryKeyBlock.header.access & ProDOSWriteAttribute) == ProDOSWriteAttribute)
|
||||
if((rootDirectoryKeyBlock.header.access & WRITE_ATTRIBUTE) == WRITE_ATTRIBUTE)
|
||||
sbInformation.AppendLine("Volume can be written");
|
||||
if((rootDirectoryKeyBlock.header.access & ProDOSRenameAttribute) == ProDOSRenameAttribute)
|
||||
if((rootDirectoryKeyBlock.header.access & RENAME_ATTRIBUTE) == RENAME_ATTRIBUTE)
|
||||
sbInformation.AppendLine("Volume can be renamed");
|
||||
if((rootDirectoryKeyBlock.header.access & ProDOSDestroyAttribute) == ProDOSDestroyAttribute)
|
||||
if((rootDirectoryKeyBlock.header.access & DESTROY_ATTRIBUTE) == DESTROY_ATTRIBUTE)
|
||||
sbInformation.AppendLine("Volume can be destroyed");
|
||||
if((rootDirectoryKeyBlock.header.access & ProDOSBackupAttribute) == ProDOSBackupAttribute)
|
||||
if((rootDirectoryKeyBlock.header.access & BACKUP_ATTRIBUTE) == BACKUP_ATTRIBUTE)
|
||||
sbInformation.AppendLine("Volume must be backed up");
|
||||
|
||||
if((rootDirectoryKeyBlock.header.access & ProDOSReservedAttributeMask) != 0)
|
||||
if((rootDirectoryKeyBlock.header.access & RESERVED_ATTRIBUTE_MASK) != 0)
|
||||
DicConsole.DebugWriteLine("ProDOS plugin", "Reserved attributes are set: {0:X2}",
|
||||
rootDirectoryKeyBlock.header.access);
|
||||
|
||||
information = sbInformation.ToString();
|
||||
|
||||
xmlFSType = new FileSystemType();
|
||||
xmlFSType.VolumeName = rootDirectoryKeyBlock.header.volume_name;
|
||||
XmlFsType = new FileSystemType();
|
||||
XmlFsType.VolumeName = rootDirectoryKeyBlock.header.volume_name;
|
||||
if(dateCorrect)
|
||||
{
|
||||
xmlFSType.CreationDate = rootDirectoryKeyBlock.header.creation_time;
|
||||
xmlFSType.CreationDateSpecified = true;
|
||||
XmlFsType.CreationDate = rootDirectoryKeyBlock.header.creation_time;
|
||||
XmlFsType.CreationDateSpecified = true;
|
||||
}
|
||||
xmlFSType.Files = rootDirectoryKeyBlock.header.file_count;
|
||||
xmlFSType.FilesSpecified = true;
|
||||
xmlFSType.Clusters = rootDirectoryKeyBlock.header.total_blocks;
|
||||
xmlFSType.ClusterSize = (int)((partition.End - partition.Start + 1) * imagePlugin.ImageInfo.SectorSize /
|
||||
(ulong)xmlFSType.Clusters);
|
||||
xmlFSType.Type = "ProDOS";
|
||||
XmlFsType.Files = rootDirectoryKeyBlock.header.file_count;
|
||||
XmlFsType.FilesSpecified = true;
|
||||
XmlFsType.Clusters = rootDirectoryKeyBlock.header.total_blocks;
|
||||
XmlFsType.ClusterSize = (int)((partition.End - partition.Start + 1) * imagePlugin.ImageInfo.SectorSize /
|
||||
(ulong)XmlFsType.Clusters);
|
||||
XmlFsType.Type = "ProDOS";
|
||||
}
|
||||
|
||||
public override Errno Mount()
|
||||
|
||||
@@ -108,24 +108,22 @@ namespace DiscImageChef.Filesystems
|
||||
public QNX4()
|
||||
{
|
||||
Name = "QNX4 Plugin";
|
||||
PluginUUID = new Guid("E73A63FA-B5B0-48BF-BF82-DA5F0A8170D2");
|
||||
PluginUuid = new Guid("E73A63FA-B5B0-48BF-BF82-DA5F0A8170D2");
|
||||
CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public QNX4(Encoding encoding)
|
||||
{
|
||||
Name = "QNX4 Plugin";
|
||||
PluginUUID = new Guid("E73A63FA-B5B0-48BF-BF82-DA5F0A8170D2");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("E73A63FA-B5B0-48BF-BF82-DA5F0A8170D2");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public QNX4(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "QNX4 Plugin";
|
||||
PluginUUID = new Guid("E73A63FA-B5B0-48BF-BF82-DA5F0A8170D2");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("E73A63FA-B5B0-48BF-BF82-DA5F0A8170D2");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugin imagePlugin, Partition partition)
|
||||
@@ -135,10 +133,9 @@ namespace DiscImageChef.Filesystems
|
||||
byte[] sector = imagePlugin.ReadSector(partition.Start + 1);
|
||||
if(sector.Length < 512) return false;
|
||||
|
||||
QNX4_Superblock qnxSb;
|
||||
IntPtr sbPtr = Marshal.AllocHGlobal(512);
|
||||
Marshal.Copy(sector, 0, sbPtr, 512);
|
||||
qnxSb = (QNX4_Superblock)Marshal.PtrToStructure(sbPtr, typeof(QNX4_Superblock));
|
||||
QNX4_Superblock qnxSb = (QNX4_Superblock)Marshal.PtrToStructure(sbPtr, typeof(QNX4_Superblock));
|
||||
Marshal.FreeHGlobal(sbPtr);
|
||||
|
||||
// Check root directory name
|
||||
@@ -169,10 +166,9 @@ namespace DiscImageChef.Filesystems
|
||||
byte[] sector = imagePlugin.ReadSector(partition.Start + 1);
|
||||
if(sector.Length < 512) return;
|
||||
|
||||
QNX4_Superblock qnxSb;
|
||||
IntPtr sbPtr = Marshal.AllocHGlobal(512);
|
||||
Marshal.Copy(sector, 0, sbPtr, 512);
|
||||
qnxSb = (QNX4_Superblock)Marshal.PtrToStructure(sbPtr, typeof(QNX4_Superblock));
|
||||
QNX4_Superblock qnxSb = (QNX4_Superblock)Marshal.PtrToStructure(sbPtr, typeof(QNX4_Superblock));
|
||||
Marshal.FreeHGlobal(sbPtr);
|
||||
|
||||
// Too much useless information
|
||||
@@ -253,7 +249,7 @@ namespace DiscImageChef.Filesystems
|
||||
information =
|
||||
$"QNX4 filesystem\nCreated on {DateHandlers.UNIXUnsignedToDateTime(qnxSb.rootDir.di_ftime)}\n";
|
||||
|
||||
xmlFSType = new FileSystemType
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
Type = "QNX4 filesystem",
|
||||
Clusters = (long)partition.Length,
|
||||
@@ -263,7 +259,7 @@ namespace DiscImageChef.Filesystems
|
||||
ModificationDate = DateHandlers.UNIXUnsignedToDateTime(qnxSb.rootDir.di_mtime),
|
||||
ModificationDateSpecified = true
|
||||
};
|
||||
xmlFSType.Bootable |= qnxSb.boot.di_size != 0 || qnxSb.altBoot.di_size != 0;
|
||||
XmlFsType.Bootable |= qnxSb.boot.di_size != 0 || qnxSb.altBoot.di_size != 0;
|
||||
}
|
||||
|
||||
public override Errno Mount()
|
||||
|
||||
@@ -96,43 +96,41 @@ namespace DiscImageChef.Filesystems
|
||||
public QNX6_RootNode unknown;
|
||||
}
|
||||
|
||||
const uint QNX6_SuperBlockSize = 0x1000;
|
||||
const uint QNX6_BootBlocksSize = 0x2000;
|
||||
const uint QNX6_Magic = 0x68191122;
|
||||
const uint QNX6_SUPER_BLOCK_SIZE = 0x1000;
|
||||
const uint QNX6_BOOT_BLOCKS_SIZE = 0x2000;
|
||||
const uint QNX6_MAGIC = 0x68191122;
|
||||
|
||||
public QNX6()
|
||||
{
|
||||
Name = "QNX6 Plugin";
|
||||
PluginUUID = new Guid("3E610EA2-4D08-4D70-8947-830CD4C74FC0");
|
||||
PluginUuid = new Guid("3E610EA2-4D08-4D70-8947-830CD4C74FC0");
|
||||
CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public QNX6(Encoding encoding)
|
||||
{
|
||||
Name = "QNX6 Plugin";
|
||||
PluginUUID = new Guid("3E610EA2-4D08-4D70-8947-830CD4C74FC0");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("3E610EA2-4D08-4D70-8947-830CD4C74FC0");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public QNX6(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "QNX6 Plugin";
|
||||
PluginUUID = new Guid("3E610EA2-4D08-4D70-8947-830CD4C74FC0");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("3E610EA2-4D08-4D70-8947-830CD4C74FC0");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugin imagePlugin, Partition partition)
|
||||
{
|
||||
uint sectors = QNX6_SuperBlockSize / imagePlugin.GetSectorSize();
|
||||
uint bootSectors = QNX6_BootBlocksSize / imagePlugin.GetSectorSize();
|
||||
uint sectors = QNX6_SUPER_BLOCK_SIZE / imagePlugin.GetSectorSize();
|
||||
uint bootSectors = QNX6_BOOT_BLOCKS_SIZE / imagePlugin.GetSectorSize();
|
||||
|
||||
if(partition.Start + bootSectors + sectors >= partition.End) return false;
|
||||
|
||||
byte[] audiSector = imagePlugin.ReadSectors(partition.Start, sectors);
|
||||
byte[] sector = imagePlugin.ReadSectors(partition.Start + bootSectors, sectors);
|
||||
if(sector.Length < QNX6_SuperBlockSize) return false;
|
||||
if(sector.Length < QNX6_SUPER_BLOCK_SIZE) return false;
|
||||
|
||||
QNX6_AudiSuperBlock audiSb = new QNX6_AudiSuperBlock();
|
||||
IntPtr audiPtr = Marshal.AllocHGlobal(Marshal.SizeOf(audiSb));
|
||||
@@ -146,7 +144,7 @@ namespace DiscImageChef.Filesystems
|
||||
qnxSb = (QNX6_SuperBlock)Marshal.PtrToStructure(sbPtr, typeof(QNX6_SuperBlock));
|
||||
Marshal.FreeHGlobal(sbPtr);
|
||||
|
||||
return qnxSb.magic == QNX6_Magic || audiSb.magic == QNX6_Magic;
|
||||
return qnxSb.magic == QNX6_MAGIC || audiSb.magic == QNX6_MAGIC;
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
|
||||
@@ -154,12 +152,12 @@ namespace DiscImageChef.Filesystems
|
||||
{
|
||||
information = "";
|
||||
StringBuilder sb = new StringBuilder();
|
||||
uint sectors = QNX6_SuperBlockSize / imagePlugin.GetSectorSize();
|
||||
uint bootSectors = QNX6_BootBlocksSize / imagePlugin.GetSectorSize();
|
||||
uint sectors = QNX6_SUPER_BLOCK_SIZE / imagePlugin.GetSectorSize();
|
||||
uint bootSectors = QNX6_BOOT_BLOCKS_SIZE / imagePlugin.GetSectorSize();
|
||||
|
||||
byte[] audiSector = imagePlugin.ReadSectors(partition.Start, sectors);
|
||||
byte[] sector = imagePlugin.ReadSectors(partition.Start + bootSectors, sectors);
|
||||
if(sector.Length < QNX6_SuperBlockSize) return;
|
||||
if(sector.Length < QNX6_SUPER_BLOCK_SIZE) return;
|
||||
|
||||
QNX6_AudiSuperBlock audiSb = new QNX6_AudiSuperBlock();
|
||||
IntPtr audiPtr = Marshal.AllocHGlobal(Marshal.SizeOf(audiSb));
|
||||
@@ -173,7 +171,7 @@ namespace DiscImageChef.Filesystems
|
||||
qnxSb = (QNX6_SuperBlock)Marshal.PtrToStructure(sbPtr, typeof(QNX6_SuperBlock));
|
||||
Marshal.FreeHGlobal(sbPtr);
|
||||
|
||||
bool audi = false || audiSb.magic == QNX6_Magic;
|
||||
bool audi = audiSb.magic == QNX6_MAGIC;
|
||||
|
||||
if(audi)
|
||||
{
|
||||
@@ -186,17 +184,19 @@ namespace DiscImageChef.Filesystems
|
||||
audiSb.freeBlocks * audiSb.blockSize, audiSb.numBlocks,
|
||||
audiSb.numBlocks * audiSb.blockSize).AppendLine();
|
||||
|
||||
xmlFSType = new FileSystemType();
|
||||
xmlFSType.Type = "QNX6 (Audi) filesystem";
|
||||
xmlFSType.Clusters = audiSb.numBlocks;
|
||||
xmlFSType.ClusterSize = (int)audiSb.blockSize;
|
||||
xmlFSType.Bootable = true;
|
||||
xmlFSType.Files = audiSb.numInodes - audiSb.freeInodes;
|
||||
xmlFSType.FilesSpecified = true;
|
||||
xmlFSType.FreeClusters = audiSb.freeBlocks;
|
||||
xmlFSType.FreeClustersSpecified = true;
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
Type = "QNX6 (Audi) filesystem",
|
||||
Clusters = audiSb.numBlocks,
|
||||
ClusterSize = (int)audiSb.blockSize,
|
||||
Bootable = true,
|
||||
Files = audiSb.numInodes - audiSb.freeInodes,
|
||||
FilesSpecified = true,
|
||||
FreeClusters = audiSb.freeBlocks,
|
||||
FreeClustersSpecified = true,
|
||||
VolumeSerial = $"{audiSb.serial:X16}"
|
||||
};
|
||||
//xmlFSType.VolumeName = CurrentEncoding.GetString(audiSb.id);
|
||||
xmlFSType.VolumeSerial = $"{audiSb.serial:X16}";
|
||||
|
||||
information = sb.ToString();
|
||||
return;
|
||||
@@ -217,21 +217,23 @@ namespace DiscImageChef.Filesystems
|
||||
qnxSb.freeBlocks * qnxSb.blockSize, qnxSb.numBlocks, qnxSb.numBlocks * qnxSb.blockSize)
|
||||
.AppendLine();
|
||||
|
||||
xmlFSType = new FileSystemType();
|
||||
xmlFSType.Type = "QNX6 filesystem";
|
||||
xmlFSType.Clusters = qnxSb.numBlocks;
|
||||
xmlFSType.ClusterSize = (int)qnxSb.blockSize;
|
||||
xmlFSType.Bootable = true;
|
||||
xmlFSType.Files = qnxSb.numInodes - qnxSb.freeInodes;
|
||||
xmlFSType.FilesSpecified = true;
|
||||
xmlFSType.FreeClusters = qnxSb.freeBlocks;
|
||||
xmlFSType.FreeClustersSpecified = true;
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
Type = "QNX6 filesystem",
|
||||
Clusters = qnxSb.numBlocks,
|
||||
ClusterSize = (int)qnxSb.blockSize,
|
||||
Bootable = true,
|
||||
Files = qnxSb.numInodes - qnxSb.freeInodes,
|
||||
FilesSpecified = true,
|
||||
FreeClusters = qnxSb.freeBlocks,
|
||||
FreeClustersSpecified = true,
|
||||
VolumeSerial = $"{qnxSb.serial:X16}",
|
||||
CreationDate = DateHandlers.UNIXUnsignedToDateTime(qnxSb.ctime),
|
||||
CreationDateSpecified = true,
|
||||
ModificationDate = DateHandlers.UNIXUnsignedToDateTime(qnxSb.atime),
|
||||
ModificationDateSpecified = true
|
||||
};
|
||||
//xmlFSType.VolumeName = CurrentEncoding.GetString(qnxSb.volumeid);
|
||||
xmlFSType.VolumeSerial = $"{qnxSb.serial:X16}";
|
||||
xmlFSType.CreationDate = DateHandlers.UNIXUnsignedToDateTime(qnxSb.ctime);
|
||||
xmlFSType.CreationDateSpecified = true;
|
||||
xmlFSType.ModificationDate = DateHandlers.UNIXUnsignedToDateTime(qnxSb.atime);
|
||||
xmlFSType.ModificationDateSpecified = true;
|
||||
|
||||
information = sb.ToString();
|
||||
}
|
||||
|
||||
@@ -149,30 +149,28 @@ namespace DiscImageChef.Filesystems
|
||||
}
|
||||
|
||||
/// <summary>Magic number for OS-9. Same for OS-9000?</summary>
|
||||
const uint RBF_Sync = 0x4372757A;
|
||||
const uint RBF_Cnys = 0x7A757243;
|
||||
const uint RBF_SYNC = 0x4372757A;
|
||||
const uint RBF_CNYS = 0x7A757243;
|
||||
|
||||
public RBF()
|
||||
{
|
||||
Name = "OS-9 Random Block File Plugin";
|
||||
PluginUUID = new Guid("E864E45B-0B52-4D29-A858-7BDFA9199FB2");
|
||||
PluginUuid = new Guid("E864E45B-0B52-4D29-A858-7BDFA9199FB2");
|
||||
CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public RBF(Encoding encoding)
|
||||
{
|
||||
Name = "OS-9 Random Block File Plugin";
|
||||
PluginUUID = new Guid("E864E45B-0B52-4D29-A858-7BDFA9199FB2");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("E864E45B-0B52-4D29-A858-7BDFA9199FB2");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public RBF(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "OS-9 Random Block File Plugin";
|
||||
PluginUUID = new Guid("E864E45B-0B52-4D29-A858-7BDFA9199FB2");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("E864E45B-0B52-4D29-A858-7BDFA9199FB2");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugin imagePlugin, Partition partition)
|
||||
@@ -184,24 +182,24 @@ namespace DiscImageChef.Filesystems
|
||||
// I've read OS-9/Apple2 has it on sector 15
|
||||
foreach(ulong location in new[] {0, 4, 15})
|
||||
{
|
||||
RBF_IdSector RBFSb = new RBF_IdSector();
|
||||
RBF_IdSector rbfSb = new RBF_IdSector();
|
||||
|
||||
uint sbSize = (uint)(Marshal.SizeOf(RBFSb) / imagePlugin.GetSectorSize());
|
||||
if(Marshal.SizeOf(RBFSb) % imagePlugin.GetSectorSize() != 0) sbSize++;
|
||||
uint sbSize = (uint)(Marshal.SizeOf(rbfSb) / imagePlugin.GetSectorSize());
|
||||
if(Marshal.SizeOf(rbfSb) % imagePlugin.GetSectorSize() != 0) sbSize++;
|
||||
|
||||
if(partition.Start + location + sbSize >= imagePlugin.GetSectors()) break;
|
||||
|
||||
byte[] sector = imagePlugin.ReadSectors(partition.Start + location, sbSize);
|
||||
if(sector.Length < Marshal.SizeOf(RBFSb)) return false;
|
||||
if(sector.Length < Marshal.SizeOf(rbfSb)) return false;
|
||||
|
||||
RBFSb = BigEndianMarshal.ByteArrayToStructureBigEndian<RBF_IdSector>(sector);
|
||||
RBF_NewIdSector RBF9000Sb = BigEndianMarshal.ByteArrayToStructureBigEndian<RBF_NewIdSector>(sector);
|
||||
rbfSb = BigEndianMarshal.ByteArrayToStructureBigEndian<RBF_IdSector>(sector);
|
||||
RBF_NewIdSector rbf9000Sb = BigEndianMarshal.ByteArrayToStructureBigEndian<RBF_NewIdSector>(sector);
|
||||
|
||||
DicConsole.DebugWriteLine("RBF plugin",
|
||||
"magic at {0} = 0x{1:X8} or 0x{2:X8} (expected 0x{3:X8} or 0x{4:X8})",
|
||||
location, RBFSb.dd_sync, RBF9000Sb.rid_sync, RBF_Sync, RBF_Cnys);
|
||||
location, rbfSb.dd_sync, rbf9000Sb.rid_sync, RBF_SYNC, RBF_CNYS);
|
||||
|
||||
if(RBFSb.dd_sync == RBF_Sync || RBF9000Sb.rid_sync == RBF_Sync || RBF9000Sb.rid_sync == RBF_Cnys)
|
||||
if(rbfSb.dd_sync == RBF_SYNC || rbf9000Sb.rid_sync == RBF_SYNC || rbf9000Sb.rid_sync == RBF_CNYS)
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -214,134 +212,132 @@ namespace DiscImageChef.Filesystems
|
||||
information = "";
|
||||
if(imagePlugin.GetSectorSize() < 256) return;
|
||||
|
||||
RBF_IdSector RBFSb = new RBF_IdSector();
|
||||
RBF_NewIdSector RBF9000Sb = new RBF_NewIdSector();
|
||||
RBF_IdSector rbfSb = new RBF_IdSector();
|
||||
RBF_NewIdSector rbf9000Sb = new RBF_NewIdSector();
|
||||
|
||||
foreach(ulong location in new[] {0, 4, 15})
|
||||
{
|
||||
uint sbSize = (uint)(Marshal.SizeOf(RBFSb) / imagePlugin.GetSectorSize());
|
||||
if(Marshal.SizeOf(RBFSb) % imagePlugin.GetSectorSize() != 0) sbSize++;
|
||||
uint sbSize = (uint)(Marshal.SizeOf(rbfSb) / imagePlugin.GetSectorSize());
|
||||
if(Marshal.SizeOf(rbfSb) % imagePlugin.GetSectorSize() != 0) sbSize++;
|
||||
|
||||
byte[] sector = imagePlugin.ReadSectors(partition.Start + location, sbSize);
|
||||
if(sector.Length < Marshal.SizeOf(RBFSb)) return;
|
||||
if(sector.Length < Marshal.SizeOf(rbfSb)) return;
|
||||
|
||||
RBFSb = BigEndianMarshal.ByteArrayToStructureBigEndian<RBF_IdSector>(sector);
|
||||
RBF9000Sb = BigEndianMarshal.ByteArrayToStructureBigEndian<RBF_NewIdSector>(sector);
|
||||
rbfSb = BigEndianMarshal.ByteArrayToStructureBigEndian<RBF_IdSector>(sector);
|
||||
rbf9000Sb = BigEndianMarshal.ByteArrayToStructureBigEndian<RBF_NewIdSector>(sector);
|
||||
|
||||
DicConsole.DebugWriteLine("RBF plugin",
|
||||
"magic at {0} = 0x{1:X8} or 0x{2:X8} (expected 0x{3:X8} or 0x{4:X8})",
|
||||
location, RBFSb.dd_sync, RBF9000Sb.rid_sync, RBF_Sync, RBF_Cnys);
|
||||
location, rbfSb.dd_sync, rbf9000Sb.rid_sync, RBF_SYNC, RBF_CNYS);
|
||||
|
||||
if(RBFSb.dd_sync == RBF_Sync || RBF9000Sb.rid_sync == RBF_Sync || RBF9000Sb.rid_sync == RBF_Cnys) break;
|
||||
if(rbfSb.dd_sync == RBF_SYNC || rbf9000Sb.rid_sync == RBF_SYNC || rbf9000Sb.rid_sync == RBF_CNYS) break;
|
||||
}
|
||||
|
||||
if(RBFSb.dd_sync != RBF_Sync && RBF9000Sb.rid_sync != RBF_Sync && RBF9000Sb.rid_sync != RBF_Cnys) return;
|
||||
if(rbfSb.dd_sync != RBF_SYNC && rbf9000Sb.rid_sync != RBF_SYNC && rbf9000Sb.rid_sync != RBF_CNYS) return;
|
||||
|
||||
if(RBF9000Sb.rid_sync == RBF_Cnys) RBF9000Sb = BigEndianMarshal.SwapStructureMembersEndian(RBF9000Sb);
|
||||
if(rbf9000Sb.rid_sync == RBF_CNYS) rbf9000Sb = BigEndianMarshal.SwapStructureMembersEndian(rbf9000Sb);
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("OS-9 Random Block File");
|
||||
|
||||
if(RBF9000Sb.rid_sync == RBF_Sync)
|
||||
if(rbf9000Sb.rid_sync == RBF_SYNC)
|
||||
{
|
||||
sb.AppendFormat("Volume ID: {0:X8}", RBF9000Sb.rid_diskid).AppendLine();
|
||||
sb.AppendFormat("{0} blocks in volume", RBF9000Sb.rid_totblocks).AppendLine();
|
||||
sb.AppendFormat("{0} cylinders", RBF9000Sb.rid_cylinders).AppendLine();
|
||||
sb.AppendFormat("{0} blocks in cylinder 0", RBF9000Sb.rid_cyl0size).AppendLine();
|
||||
sb.AppendFormat("{0} blocks per cylinder", RBF9000Sb.rid_cylsize).AppendLine();
|
||||
sb.AppendFormat("{0} heads", RBF9000Sb.rid_heads).AppendLine();
|
||||
sb.AppendFormat("{0} bytes per block", RBF9000Sb.rid_blocksize).AppendLine();
|
||||
sb.AppendFormat("Volume ID: {0:X8}", rbf9000Sb.rid_diskid).AppendLine();
|
||||
sb.AppendFormat("{0} blocks in volume", rbf9000Sb.rid_totblocks).AppendLine();
|
||||
sb.AppendFormat("{0} cylinders", rbf9000Sb.rid_cylinders).AppendLine();
|
||||
sb.AppendFormat("{0} blocks in cylinder 0", rbf9000Sb.rid_cyl0size).AppendLine();
|
||||
sb.AppendFormat("{0} blocks per cylinder", rbf9000Sb.rid_cylsize).AppendLine();
|
||||
sb.AppendFormat("{0} heads", rbf9000Sb.rid_heads).AppendLine();
|
||||
sb.AppendFormat("{0} bytes per block", rbf9000Sb.rid_blocksize).AppendLine();
|
||||
// TODO: Convert to flags?
|
||||
if((RBF9000Sb.rid_format & 0x01) == 0x01) sb.AppendLine("Disk is double sided");
|
||||
else sb.AppendLine("Disk is single sided");
|
||||
if((RBF9000Sb.rid_format & 0x02) == 0x02) sb.AppendLine("Disk is double density");
|
||||
else sb.AppendLine("Disk is single density");
|
||||
if((RBF9000Sb.rid_format & 0x10) == 0x10) sb.AppendLine("Disk is 384 TPI");
|
||||
else if((RBF9000Sb.rid_format & 0x08) == 0x08) sb.AppendLine("Disk is 192 TPI");
|
||||
else if((RBF9000Sb.rid_format & 0x04) == 0x04) sb.AppendLine("Disk is 96 TPI or 135 TPI");
|
||||
sb.AppendLine((rbf9000Sb.rid_format & 0x01) == 0x01 ? "Disk is double sided" : "Disk is single sided");
|
||||
sb.AppendLine((rbf9000Sb.rid_format & 0x02) == 0x02
|
||||
? "Disk is double density"
|
||||
: "Disk is single density");
|
||||
if((rbf9000Sb.rid_format & 0x10) == 0x10) sb.AppendLine("Disk is 384 TPI");
|
||||
else if((rbf9000Sb.rid_format & 0x08) == 0x08) sb.AppendLine("Disk is 192 TPI");
|
||||
else if((rbf9000Sb.rid_format & 0x04) == 0x04) sb.AppendLine("Disk is 96 TPI or 135 TPI");
|
||||
else sb.AppendLine("Disk is 48 TPI");
|
||||
sb.AppendFormat("Allocation bitmap descriptor starts at block {0}",
|
||||
RBF9000Sb.rid_bitmap == 0 ? 1 : RBF9000Sb.rid_bitmap).AppendLine();
|
||||
if(RBF9000Sb.rid_firstboot > 0)
|
||||
sb.AppendFormat("Debugger descriptor starts at block {0}", RBF9000Sb.rid_firstboot).AppendLine();
|
||||
if(RBF9000Sb.rid_bootfile > 0)
|
||||
sb.AppendFormat("Boot file descriptor starts at block {0}", RBF9000Sb.rid_bootfile).AppendLine();
|
||||
sb.AppendFormat("Root directory descriptor starts at block {0}", RBF9000Sb.rid_rootdir).AppendLine();
|
||||
sb.AppendFormat("Disk is owned by group {0} user {1}", RBF9000Sb.rid_group, RBF9000Sb.rid_owner)
|
||||
rbf9000Sb.rid_bitmap == 0 ? 1 : rbf9000Sb.rid_bitmap).AppendLine();
|
||||
if(rbf9000Sb.rid_firstboot > 0)
|
||||
sb.AppendFormat("Debugger descriptor starts at block {0}", rbf9000Sb.rid_firstboot).AppendLine();
|
||||
if(rbf9000Sb.rid_bootfile > 0)
|
||||
sb.AppendFormat("Boot file descriptor starts at block {0}", rbf9000Sb.rid_bootfile).AppendLine();
|
||||
sb.AppendFormat("Root directory descriptor starts at block {0}", rbf9000Sb.rid_rootdir).AppendLine();
|
||||
sb.AppendFormat("Disk is owned by group {0} user {1}", rbf9000Sb.rid_group, rbf9000Sb.rid_owner)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("Volume was created on {0}", DateHandlers.UNIXToDateTime(RBF9000Sb.rid_ctime))
|
||||
sb.AppendFormat("Volume was created on {0}", DateHandlers.UNIXToDateTime(rbf9000Sb.rid_ctime))
|
||||
.AppendLine();
|
||||
sb.AppendFormat("Volume's identification block was last written on {0}",
|
||||
DateHandlers.UNIXToDateTime(RBF9000Sb.rid_mtime)).AppendLine();
|
||||
sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(RBF9000Sb.rid_name, CurrentEncoding))
|
||||
DateHandlers.UNIXToDateTime(rbf9000Sb.rid_mtime)).AppendLine();
|
||||
sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(rbf9000Sb.rid_name, CurrentEncoding))
|
||||
.AppendLine();
|
||||
|
||||
xmlFSType = new FileSystemType
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
Type = "OS-9 Random Block File",
|
||||
Bootable = RBF9000Sb.rid_bootfile > 0,
|
||||
ClusterSize = RBF9000Sb.rid_blocksize,
|
||||
Clusters = RBF9000Sb.rid_totblocks,
|
||||
CreationDate = DateHandlers.UNIXToDateTime(RBF9000Sb.rid_ctime),
|
||||
Bootable = rbf9000Sb.rid_bootfile > 0,
|
||||
ClusterSize = rbf9000Sb.rid_blocksize,
|
||||
Clusters = rbf9000Sb.rid_totblocks,
|
||||
CreationDate = DateHandlers.UNIXToDateTime(rbf9000Sb.rid_ctime),
|
||||
CreationDateSpecified = true,
|
||||
ModificationDate = DateHandlers.UNIXToDateTime(RBF9000Sb.rid_mtime),
|
||||
ModificationDate = DateHandlers.UNIXToDateTime(rbf9000Sb.rid_mtime),
|
||||
ModificationDateSpecified = true,
|
||||
VolumeName = StringHandlers.CToString(RBF9000Sb.rid_name, CurrentEncoding),
|
||||
VolumeSerial = $"{RBF9000Sb.rid_diskid:X8}"
|
||||
VolumeName = StringHandlers.CToString(rbf9000Sb.rid_name, CurrentEncoding),
|
||||
VolumeSerial = $"{rbf9000Sb.rid_diskid:X8}"
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.AppendFormat("Volume ID: {0:X4}", RBFSb.dd_dsk).AppendLine();
|
||||
sb.AppendFormat("{0} blocks in volume", LSNToUInt32(RBFSb.dd_tot)).AppendLine();
|
||||
sb.AppendFormat("{0} tracks", RBFSb.dd_tks).AppendLine();
|
||||
sb.AppendFormat("{0} sectors per track", RBFSb.dd_spt).AppendLine();
|
||||
sb.AppendFormat("{0} bytes per sector", 256 << RBFSb.dd_lsnsize).AppendLine();
|
||||
sb.AppendFormat("{0} sectors per cluster ({1} bytes)", RBFSb.dd_bit,
|
||||
RBFSb.dd_bit * (256 << RBFSb.dd_lsnsize)).AppendLine();
|
||||
sb.AppendFormat("Volume ID: {0:X4}", rbfSb.dd_dsk).AppendLine();
|
||||
sb.AppendFormat("{0} blocks in volume", LSNToUInt32(rbfSb.dd_tot)).AppendLine();
|
||||
sb.AppendFormat("{0} tracks", rbfSb.dd_tks).AppendLine();
|
||||
sb.AppendFormat("{0} sectors per track", rbfSb.dd_spt).AppendLine();
|
||||
sb.AppendFormat("{0} bytes per sector", 256 << rbfSb.dd_lsnsize).AppendLine();
|
||||
sb.AppendFormat("{0} sectors per cluster ({1} bytes)", rbfSb.dd_bit,
|
||||
rbfSb.dd_bit * (256 << rbfSb.dd_lsnsize)).AppendLine();
|
||||
// TODO: Convert to flags?
|
||||
if((RBFSb.dd_fmt & 0x01) == 0x01) sb.AppendLine("Disk is double sided");
|
||||
else sb.AppendLine("Disk is single sided");
|
||||
if((RBFSb.dd_fmt & 0x02) == 0x02) sb.AppendLine("Disk is double density");
|
||||
else sb.AppendLine("Disk is single density");
|
||||
if((RBFSb.dd_fmt & 0x10) == 0x10) sb.AppendLine("Disk is 384 TPI");
|
||||
else if((RBFSb.dd_fmt & 0x08) == 0x08) sb.AppendLine("Disk is 192 TPI");
|
||||
else if((RBFSb.dd_fmt & 0x04) == 0x04) sb.AppendLine("Disk is 96 TPI or 135 TPI");
|
||||
sb.AppendLine((rbfSb.dd_fmt & 0x01) == 0x01 ? "Disk is double sided" : "Disk is single sided");
|
||||
sb.AppendLine((rbfSb.dd_fmt & 0x02) == 0x02 ? "Disk is double density" : "Disk is single density");
|
||||
if((rbfSb.dd_fmt & 0x10) == 0x10) sb.AppendLine("Disk is 384 TPI");
|
||||
else if((rbfSb.dd_fmt & 0x08) == 0x08) sb.AppendLine("Disk is 192 TPI");
|
||||
else if((rbfSb.dd_fmt & 0x04) == 0x04) sb.AppendLine("Disk is 96 TPI or 135 TPI");
|
||||
else sb.AppendLine("Disk is 48 TPI");
|
||||
sb.AppendFormat("Allocation bitmap descriptor starts at block {0}",
|
||||
RBFSb.dd_maplsn == 0 ? 1 : RBFSb.dd_maplsn).AppendLine();
|
||||
sb.AppendFormat("{0} bytes in allocation bitmap", RBFSb.dd_map).AppendLine();
|
||||
if(LSNToUInt32(RBFSb.dd_bt) > 0 && RBFSb.dd_bsz > 0)
|
||||
sb.AppendFormat("Boot file starts at block {0} and has {1} bytes", LSNToUInt32(RBFSb.dd_bt),
|
||||
RBFSb.dd_bsz).AppendLine();
|
||||
sb.AppendFormat("Root directory descriptor starts at block {0}", LSNToUInt32(RBFSb.dd_dir))
|
||||
rbfSb.dd_maplsn == 0 ? 1 : rbfSb.dd_maplsn).AppendLine();
|
||||
sb.AppendFormat("{0} bytes in allocation bitmap", rbfSb.dd_map).AppendLine();
|
||||
if(LSNToUInt32(rbfSb.dd_bt) > 0 && rbfSb.dd_bsz > 0)
|
||||
sb.AppendFormat("Boot file starts at block {0} and has {1} bytes", LSNToUInt32(rbfSb.dd_bt),
|
||||
rbfSb.dd_bsz).AppendLine();
|
||||
sb.AppendFormat("Root directory descriptor starts at block {0}", LSNToUInt32(rbfSb.dd_dir))
|
||||
.AppendLine();
|
||||
sb.AppendFormat("Disk is owned by user {0}", RBFSb.dd_own).AppendLine();
|
||||
sb.AppendFormat("Volume was created on {0}", DateHandlers.OS9ToDateTime(RBFSb.dd_dat)).AppendLine();
|
||||
sb.AppendFormat("Volume attributes: {0:X2}", RBFSb.dd_att).AppendLine();
|
||||
sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(RBFSb.dd_nam, CurrentEncoding))
|
||||
sb.AppendFormat("Disk is owned by user {0}", rbfSb.dd_own).AppendLine();
|
||||
sb.AppendFormat("Volume was created on {0}", DateHandlers.OS9ToDateTime(rbfSb.dd_dat)).AppendLine();
|
||||
sb.AppendFormat("Volume attributes: {0:X2}", rbfSb.dd_att).AppendLine();
|
||||
sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(rbfSb.dd_nam, CurrentEncoding))
|
||||
.AppendLine();
|
||||
sb.AppendFormat("Path descriptor options: {0}", StringHandlers.CToString(RBFSb.dd_opt, CurrentEncoding))
|
||||
sb.AppendFormat("Path descriptor options: {0}", StringHandlers.CToString(rbfSb.dd_opt, CurrentEncoding))
|
||||
.AppendLine();
|
||||
|
||||
xmlFSType = new FileSystemType
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
Type = "OS-9 Random Block File",
|
||||
Bootable = LSNToUInt32(RBFSb.dd_bt) > 0 && RBFSb.dd_bsz > 0,
|
||||
ClusterSize = RBFSb.dd_bit * (256 << RBFSb.dd_lsnsize),
|
||||
Clusters = LSNToUInt32(RBFSb.dd_tot),
|
||||
CreationDate = DateHandlers.OS9ToDateTime(RBFSb.dd_dat),
|
||||
Bootable = LSNToUInt32(rbfSb.dd_bt) > 0 && rbfSb.dd_bsz > 0,
|
||||
ClusterSize = rbfSb.dd_bit * (256 << rbfSb.dd_lsnsize),
|
||||
Clusters = LSNToUInt32(rbfSb.dd_tot),
|
||||
CreationDate = DateHandlers.OS9ToDateTime(rbfSb.dd_dat),
|
||||
CreationDateSpecified = true,
|
||||
VolumeName = StringHandlers.CToString(RBFSb.dd_nam, CurrentEncoding),
|
||||
VolumeSerial = $"{RBFSb.dd_dsk:X4}"
|
||||
VolumeName = StringHandlers.CToString(rbfSb.dd_nam, CurrentEncoding),
|
||||
VolumeSerial = $"{rbfSb.dd_dsk:X4}"
|
||||
};
|
||||
}
|
||||
|
||||
information = sb.ToString();
|
||||
}
|
||||
|
||||
public static uint LSNToUInt32(byte[] lsn)
|
||||
static uint LSNToUInt32(byte[] lsn)
|
||||
{
|
||||
if(lsn == null || lsn.Length != 3) return 0;
|
||||
|
||||
|
||||
@@ -47,24 +47,22 @@ namespace DiscImageChef.Filesystems
|
||||
public RT11()
|
||||
{
|
||||
Name = "RT-11 file system";
|
||||
PluginUUID = new Guid("DB3E2F98-8F98-463C-8126-E937843DA024");
|
||||
PluginUuid = new Guid("DB3E2F98-8F98-463C-8126-E937843DA024");
|
||||
CurrentEncoding = Encoding.GetEncoding("iso-8859-1");
|
||||
}
|
||||
|
||||
public RT11(Encoding encoding)
|
||||
{
|
||||
Name = "RT-11 file system";
|
||||
PluginUUID = new Guid("DB3E2F98-8F98-463C-8126-E937843DA024");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-1");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("DB3E2F98-8F98-463C-8126-E937843DA024");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1");
|
||||
}
|
||||
|
||||
public RT11(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "RT-11 file system";
|
||||
PluginUUID = new Guid("DB3E2F98-8F98-463C-8126-E937843DA024");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-1");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("DB3E2F98-8F98-463C-8126-E937843DA024");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugin imagePlugin, Partition partition)
|
||||
@@ -73,12 +71,11 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
if(imagePlugin.GetSectorSize() < 512) return false;
|
||||
|
||||
byte[] magic_b = new byte[12];
|
||||
string magic;
|
||||
byte[] hb_sector = imagePlugin.ReadSector(1 + partition.Start);
|
||||
byte[] magicB = new byte[12];
|
||||
byte[] hbSector = imagePlugin.ReadSector(1 + partition.Start);
|
||||
|
||||
Array.Copy(hb_sector, 0x1F0, magic_b, 0, 12);
|
||||
magic = Encoding.ASCII.GetString(magic_b);
|
||||
Array.Copy(hbSector, 0x1F0, magicB, 0, 12);
|
||||
string magic = Encoding.ASCII.GetString(magicB);
|
||||
|
||||
return magic == "DECRT11A ";
|
||||
}
|
||||
@@ -89,12 +86,11 @@ namespace DiscImageChef.Filesystems
|
||||
information = "";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
RT11HomeBlock homeblock;
|
||||
|
||||
byte[] hb_sector = imagePlugin.ReadSector(1 + partition.Start);
|
||||
byte[] hbSector = imagePlugin.ReadSector(1 + partition.Start);
|
||||
|
||||
GCHandle handle = GCHandle.Alloc(hb_sector, GCHandleType.Pinned);
|
||||
homeblock = (RT11HomeBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(RT11HomeBlock));
|
||||
GCHandle handle = GCHandle.Alloc(hbSector, GCHandleType.Pinned);
|
||||
RT11HomeBlock homeblock = (RT11HomeBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(RT11HomeBlock));
|
||||
handle.Free();
|
||||
|
||||
/* TODO: Is this correct?
|
||||
@@ -107,7 +103,7 @@ namespace DiscImageChef.Filesystems
|
||||
* MOV 1,@R0
|
||||
*/
|
||||
ushort check = 0;
|
||||
for(int i = 0; i < 512; i += 2) check += BitConverter.ToUInt16(hb_sector, i);
|
||||
for(int i = 0; i < 512; i += 2) check += BitConverter.ToUInt16(hbSector, i);
|
||||
|
||||
sb.AppendFormat("Volume format is {0}",
|
||||
StringHandlers.SpacePaddedToString(homeblock.format, CurrentEncoding)).AppendLine();
|
||||
@@ -122,7 +118,7 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
byte[] bootBlock = imagePlugin.ReadSector(0);
|
||||
|
||||
xmlFSType = new FileSystemType
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
Type = "RT-11",
|
||||
ClusterSize = homeblock.cluster * 512,
|
||||
|
||||
@@ -88,36 +88,34 @@ namespace DiscImageChef.Filesystems
|
||||
readonly byte[] Reiser35_Magic = {0x52, 0x65, 0x49, 0x73, 0x45, 0x72, 0x46, 0x73, 0x00, 0x00};
|
||||
readonly byte[] Reiser36_Magic = {0x52, 0x65, 0x49, 0x73, 0x45, 0x72, 0x32, 0x46, 0x73, 0x00};
|
||||
readonly byte[] ReiserJr_Magic = {0x52, 0x65, 0x49, 0x73, 0x45, 0x72, 0x33, 0x46, 0x73, 0x00};
|
||||
const uint Reiser_SuperOffset = 0x10000;
|
||||
const uint REISER_SUPER_OFFSET = 0x10000;
|
||||
|
||||
public Reiser()
|
||||
{
|
||||
Name = "Reiser Filesystem Plugin";
|
||||
PluginUUID = new Guid("1D8CD8B8-27E6-410F-9973-D16409225FBA");
|
||||
PluginUuid = new Guid("1D8CD8B8-27E6-410F-9973-D16409225FBA");
|
||||
CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public Reiser(Encoding encoding)
|
||||
{
|
||||
Name = "Reiser Filesystem Plugin";
|
||||
PluginUUID = new Guid("1D8CD8B8-27E6-410F-9973-D16409225FBA");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("1D8CD8B8-27E6-410F-9973-D16409225FBA");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public Reiser(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "Reiser Filesystem Plugin";
|
||||
PluginUUID = new Guid("1D8CD8B8-27E6-410F-9973-D16409225FBA");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("1D8CD8B8-27E6-410F-9973-D16409225FBA");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugin imagePlugin, Partition partition)
|
||||
{
|
||||
if(imagePlugin.GetSectorSize() < 512) return false;
|
||||
|
||||
uint sbAddr = Reiser_SuperOffset / imagePlugin.GetSectorSize();
|
||||
uint sbAddr = REISER_SUPER_OFFSET / imagePlugin.GetSectorSize();
|
||||
if(sbAddr == 0) sbAddr = 1;
|
||||
|
||||
Reiser_Superblock reiserSb = new Reiser_Superblock();
|
||||
@@ -145,7 +143,7 @@ namespace DiscImageChef.Filesystems
|
||||
information = "";
|
||||
if(imagePlugin.GetSectorSize() < 512) return;
|
||||
|
||||
uint sbAddr = Reiser_SuperOffset / imagePlugin.GetSectorSize();
|
||||
uint sbAddr = REISER_SUPER_OFFSET / imagePlugin.GetSectorSize();
|
||||
if(sbAddr == 0) sbAddr = 1;
|
||||
|
||||
Reiser_Superblock reiserSb = new Reiser_Superblock();
|
||||
@@ -184,19 +182,19 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
information = sb.ToString();
|
||||
|
||||
xmlFSType = new FileSystemType();
|
||||
if(Reiser35_Magic.SequenceEqual(reiserSb.magic)) xmlFSType.Type = "Reiser 3.5 filesystem";
|
||||
else if(Reiser36_Magic.SequenceEqual(reiserSb.magic)) xmlFSType.Type = "Reiser 3.6 filesystem";
|
||||
else if(ReiserJr_Magic.SequenceEqual(reiserSb.magic)) xmlFSType.Type = "Reiser Jr. filesystem";
|
||||
xmlFSType.ClusterSize = reiserSb.blocksize;
|
||||
xmlFSType.Clusters = reiserSb.block_count;
|
||||
xmlFSType.FreeClusters = reiserSb.free_blocks;
|
||||
xmlFSType.FreeClustersSpecified = true;
|
||||
xmlFSType.Dirty = reiserSb.umount_state == 2;
|
||||
XmlFsType = new FileSystemType();
|
||||
if(Reiser35_Magic.SequenceEqual(reiserSb.magic)) XmlFsType.Type = "Reiser 3.5 filesystem";
|
||||
else if(Reiser36_Magic.SequenceEqual(reiserSb.magic)) XmlFsType.Type = "Reiser 3.6 filesystem";
|
||||
else if(ReiserJr_Magic.SequenceEqual(reiserSb.magic)) XmlFsType.Type = "Reiser Jr. filesystem";
|
||||
XmlFsType.ClusterSize = reiserSb.blocksize;
|
||||
XmlFsType.Clusters = reiserSb.block_count;
|
||||
XmlFsType.FreeClusters = reiserSb.free_blocks;
|
||||
XmlFsType.FreeClustersSpecified = true;
|
||||
XmlFsType.Dirty = reiserSb.umount_state == 2;
|
||||
if(reiserSb.version < 2) return;
|
||||
|
||||
xmlFSType.VolumeName = CurrentEncoding.GetString(reiserSb.label);
|
||||
xmlFSType.VolumeSerial = reiserSb.uuid.ToString();
|
||||
XmlFsType.VolumeName = CurrentEncoding.GetString(reiserSb.label);
|
||||
XmlFsType.VolumeSerial = reiserSb.uuid.ToString();
|
||||
}
|
||||
|
||||
public override Errno Mount()
|
||||
|
||||
@@ -55,36 +55,34 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
readonly byte[] Reiser4_Magic =
|
||||
{0x52, 0x65, 0x49, 0x73, 0x45, 0x72, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
const uint Reiser4_SuperOffset = 0x10000;
|
||||
const uint REISER4_SUPER_OFFSET = 0x10000;
|
||||
|
||||
public Reiser4()
|
||||
{
|
||||
Name = "Reiser4 Filesystem Plugin";
|
||||
PluginUUID = new Guid("301F2D00-E8D5-4F04-934E-81DFB21D15BA");
|
||||
PluginUuid = new Guid("301F2D00-E8D5-4F04-934E-81DFB21D15BA");
|
||||
CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public Reiser4(Encoding encoding)
|
||||
{
|
||||
Name = "Reiser4 Filesystem Plugin";
|
||||
PluginUUID = new Guid("301F2D00-E8D5-4F04-934E-81DFB21D15BA");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("301F2D00-E8D5-4F04-934E-81DFB21D15BA");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public Reiser4(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "Reiser4 Filesystem Plugin";
|
||||
PluginUUID = new Guid("301F2D00-E8D5-4F04-934E-81DFB21D15BA");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("301F2D00-E8D5-4F04-934E-81DFB21D15BA");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugin imagePlugin, Partition partition)
|
||||
{
|
||||
if(imagePlugin.GetSectorSize() < 512) return false;
|
||||
|
||||
uint sbAddr = Reiser4_SuperOffset / imagePlugin.GetSectorSize();
|
||||
uint sbAddr = REISER4_SUPER_OFFSET / imagePlugin.GetSectorSize();
|
||||
if(sbAddr == 0) sbAddr = 1;
|
||||
|
||||
Reiser4_Superblock reiserSb = new Reiser4_Superblock();
|
||||
@@ -111,7 +109,7 @@ namespace DiscImageChef.Filesystems
|
||||
information = "";
|
||||
if(imagePlugin.GetSectorSize() < 512) return;
|
||||
|
||||
uint sbAddr = Reiser4_SuperOffset / imagePlugin.GetSectorSize();
|
||||
uint sbAddr = REISER4_SUPER_OFFSET / imagePlugin.GetSectorSize();
|
||||
if(sbAddr == 0) sbAddr = 1;
|
||||
|
||||
Reiser4_Superblock reiserSb = new Reiser4_Superblock();
|
||||
@@ -139,13 +137,14 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
information = sb.ToString();
|
||||
|
||||
xmlFSType = new FileSystemType();
|
||||
xmlFSType.Type = "Reiser 4 filesystem";
|
||||
xmlFSType.ClusterSize = reiserSb.blocksize;
|
||||
xmlFSType.Clusters =
|
||||
(long)((partition.End - partition.Start) * imagePlugin.GetSectorSize() / reiserSb.blocksize);
|
||||
xmlFSType.VolumeName = StringHandlers.CToString(reiserSb.label, CurrentEncoding);
|
||||
xmlFSType.VolumeSerial = reiserSb.uuid.ToString();
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
Type = "Reiser 4 filesystem",
|
||||
ClusterSize = reiserSb.blocksize,
|
||||
Clusters = (long)((partition.End - partition.Start) * imagePlugin.GetSectorSize() / reiserSb.blocksize),
|
||||
VolumeName = StringHandlers.CToString(reiserSb.label, CurrentEncoding),
|
||||
VolumeSerial = reiserSb.uuid.ToString()
|
||||
};
|
||||
}
|
||||
|
||||
public override Errno Mount()
|
||||
|
||||
@@ -45,24 +45,22 @@ namespace DiscImageChef.Filesystems
|
||||
public SFS()
|
||||
{
|
||||
Name = "SmartFileSystem";
|
||||
PluginUUID = new Guid("26550C19-3671-4A2D-BC2F-F20CEB7F48DC");
|
||||
PluginUuid = new Guid("26550C19-3671-4A2D-BC2F-F20CEB7F48DC");
|
||||
CurrentEncoding = Encoding.GetEncoding("iso-8859-1");
|
||||
}
|
||||
|
||||
public SFS(Encoding encoding)
|
||||
{
|
||||
Name = "SmartFileSystem";
|
||||
PluginUUID = new Guid("26550C19-3671-4A2D-BC2F-F20CEB7F48DC");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-1");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("26550C19-3671-4A2D-BC2F-F20CEB7F48DC");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1");
|
||||
}
|
||||
|
||||
public SFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "SmartFileSystem";
|
||||
PluginUUID = new Guid("26550C19-3671-4A2D-BC2F-F20CEB7F48DC");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-1");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("26550C19-3671-4A2D-BC2F-F20CEB7F48DC");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1");
|
||||
}
|
||||
|
||||
[Flags]
|
||||
@@ -120,9 +118,8 @@ namespace DiscImageChef.Filesystems
|
||||
public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
|
||||
out string information)
|
||||
{
|
||||
byte[] RootBlockSector = imagePlugin.ReadSector(partition.Start);
|
||||
RootBlock rootBlock;
|
||||
rootBlock = BigEndianMarshal.ByteArrayToStructureBigEndian<RootBlock>(RootBlockSector);
|
||||
byte[] rootBlockSector = imagePlugin.ReadSector(partition.Start);
|
||||
RootBlock rootBlock = BigEndianMarshal.ByteArrayToStructureBigEndian<RootBlock>(rootBlockSector);
|
||||
|
||||
StringBuilder sbInformation = new StringBuilder();
|
||||
|
||||
@@ -151,7 +148,7 @@ namespace DiscImageChef.Filesystems
|
||||
sbInformation.AppendLine("Volume moves deleted files to a recycled folder");
|
||||
information = sbInformation.ToString();
|
||||
|
||||
xmlFSType = new FileSystemType
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
CreationDate = DateHandlers.UNIXUnsignedToDateTime(rootBlock.datecreated).AddYears(8),
|
||||
CreationDateSpecified = true,
|
||||
|
||||
@@ -46,24 +46,22 @@ namespace DiscImageChef.Filesystems
|
||||
public SolarFS()
|
||||
{
|
||||
Name = "Solar_OS filesystem";
|
||||
PluginUUID = new Guid("EA3101C1-E777-4B4F-B5A3-8C57F50F6E65");
|
||||
PluginUuid = new Guid("EA3101C1-E777-4B4F-B5A3-8C57F50F6E65");
|
||||
CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public SolarFS(Encoding encoding)
|
||||
{
|
||||
Name = "Solar_OS filesystem";
|
||||
PluginUUID = new Guid("EA3101C1-E777-4B4F-B5A3-8C57F50F6E65");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("EA3101C1-E777-4B4F-B5A3-8C57F50F6E65");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public SolarFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "Solar_OS filesystem";
|
||||
PluginUUID = new Guid("EA3101C1-E777-4B4F-B5A3-8C57F50F6E65");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("EA3101C1-E777-4B4F-B5A3-8C57F50F6E65");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugin imagePlugin, Partition partition)
|
||||
@@ -71,19 +69,16 @@ namespace DiscImageChef.Filesystems
|
||||
if(2 + partition.Start >= partition.End) return false;
|
||||
|
||||
byte signature; // 0x29
|
||||
string fs_type; // "SOL_FS "
|
||||
|
||||
byte[] bpb = imagePlugin.ReadSector(0 + partition.Start);
|
||||
|
||||
byte[] fs_type_b = new byte[8];
|
||||
byte[] fsTypeB = new byte[8];
|
||||
|
||||
signature = bpb[0x25];
|
||||
Array.Copy(bpb, 0x35, fs_type_b, 0, 8);
|
||||
fs_type = StringHandlers.CToString(fs_type_b);
|
||||
Array.Copy(bpb, 0x35, fsTypeB, 0, 8);
|
||||
string fsType = StringHandlers.CToString(fsTypeB);
|
||||
|
||||
if(signature == 0x29 && fs_type == "SOL_FS ") return true;
|
||||
|
||||
return false;
|
||||
return signature == 0x29 && fsType == "SOL_FS ";
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
|
||||
@@ -92,86 +87,89 @@ namespace DiscImageChef.Filesystems
|
||||
information = "";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
byte[] bpb_sector = imagePlugin.ReadSector(0 + partition.Start);
|
||||
byte[] bpb_strings;
|
||||
byte[] bpbSector = imagePlugin.ReadSector(0 + partition.Start);
|
||||
|
||||
SolarOSParameterBlock BPB = new SolarOSParameterBlock();
|
||||
|
||||
bpb_strings = new byte[8];
|
||||
Array.Copy(bpb_sector, 0x03, bpb_strings, 0, 8);
|
||||
BPB.OEMName = StringHandlers.CToString(bpb_strings);
|
||||
BPB.bps = BitConverter.ToUInt16(bpb_sector, 0x0B);
|
||||
BPB.root_ent = BitConverter.ToUInt16(bpb_sector, 0x10);
|
||||
BPB.sectors = BitConverter.ToUInt16(bpb_sector, 0x12);
|
||||
BPB.media = bpb_sector[0x14];
|
||||
BPB.spfat = BitConverter.ToUInt16(bpb_sector, 0x15);
|
||||
BPB.sptrk = BitConverter.ToUInt16(bpb_sector, 0x17);
|
||||
BPB.heads = BitConverter.ToUInt16(bpb_sector, 0x19);
|
||||
BPB.signature = bpb_sector[0x25];
|
||||
bpb_strings = new byte[8];
|
||||
Array.Copy(bpb_sector, 0x2A, bpb_strings, 0, 11);
|
||||
BPB.vol_name = StringHandlers.CToString(bpb_strings, CurrentEncoding);
|
||||
bpb_strings = new byte[8];
|
||||
Array.Copy(bpb_sector, 0x35, bpb_strings, 0, 8);
|
||||
BPB.fs_type = StringHandlers.CToString(bpb_strings, CurrentEncoding);
|
||||
SolarOSParameterBlock bpb = new SolarOSParameterBlock
|
||||
{
|
||||
bps = BitConverter.ToUInt16(bpbSector, 0x0B),
|
||||
root_ent = BitConverter.ToUInt16(bpbSector, 0x10),
|
||||
sectors = BitConverter.ToUInt16(bpbSector, 0x12),
|
||||
media = bpbSector[0x14],
|
||||
spfat = BitConverter.ToUInt16(bpbSector, 0x15),
|
||||
sptrk = BitConverter.ToUInt16(bpbSector, 0x17),
|
||||
heads = BitConverter.ToUInt16(bpbSector, 0x19),
|
||||
signature = bpbSector[0x25]
|
||||
};
|
||||
byte[] bpbStrings = new byte[8];
|
||||
Array.Copy(bpbSector, 0x03, bpbStrings, 0, 8);
|
||||
bpb.OEMName = StringHandlers.CToString(bpbStrings);
|
||||
bpbStrings = new byte[8];
|
||||
Array.Copy(bpbSector, 0x2A, bpbStrings, 0, 11);
|
||||
bpb.vol_name = StringHandlers.CToString(bpbStrings, CurrentEncoding);
|
||||
bpbStrings = new byte[8];
|
||||
Array.Copy(bpbSector, 0x35, bpbStrings, 0, 8);
|
||||
bpb.fs_type = StringHandlers.CToString(bpbStrings, CurrentEncoding);
|
||||
|
||||
BPB.x86_jump = new byte[3];
|
||||
Array.Copy(bpb_sector, 0x00, BPB.x86_jump, 0, 3);
|
||||
BPB.unk1 = bpb_sector[0x0D];
|
||||
BPB.unk2 = BitConverter.ToUInt16(bpb_sector, 0x0E);
|
||||
BPB.unk3 = new byte[10];
|
||||
Array.Copy(bpb_sector, 0x1B, BPB.unk3, 0, 10);
|
||||
BPB.unk4 = BitConverter.ToUInt32(bpb_sector, 0x26);
|
||||
bpb.x86_jump = new byte[3];
|
||||
Array.Copy(bpbSector, 0x00, bpb.x86_jump, 0, 3);
|
||||
bpb.unk1 = bpbSector[0x0D];
|
||||
bpb.unk2 = BitConverter.ToUInt16(bpbSector, 0x0E);
|
||||
bpb.unk3 = new byte[10];
|
||||
Array.Copy(bpbSector, 0x1B, bpb.unk3, 0, 10);
|
||||
bpb.unk4 = BitConverter.ToUInt32(bpbSector, 0x26);
|
||||
|
||||
DicConsole.DebugWriteLine("SolarFS plugin", "BPB.x86_jump: 0x{0:X2}{1:X2}{2:X2}", BPB.x86_jump[0],
|
||||
BPB.x86_jump[1], BPB.x86_jump[2]);
|
||||
DicConsole.DebugWriteLine("SolarFS plugin", "BPB.OEMName: \"{0}\"", BPB.OEMName);
|
||||
DicConsole.DebugWriteLine("SolarFS plugin", "BPB.bps: {0}", BPB.bps);
|
||||
DicConsole.DebugWriteLine("SolarFS plugin", "BPB.unk1: 0x{0:X2}", BPB.unk1);
|
||||
DicConsole.DebugWriteLine("SolarFS plugin", "BPB.unk2: 0x{0:X4}", BPB.unk2);
|
||||
DicConsole.DebugWriteLine("SolarFS plugin", "BPB.root_ent: {0}", BPB.root_ent);
|
||||
DicConsole.DebugWriteLine("SolarFS plugin", "BPB.sectors: {0}", BPB.sectors);
|
||||
DicConsole.DebugWriteLine("SolarFS plugin", "BPB.media: 0x{0:X2}", BPB.media);
|
||||
DicConsole.DebugWriteLine("SolarFS plugin", "BPB.spfat: {0}", BPB.spfat);
|
||||
DicConsole.DebugWriteLine("SolarFS plugin", "BPB.sptrk: {0}", BPB.sptrk);
|
||||
DicConsole.DebugWriteLine("SolarFS plugin", "BPB.heads: {0}", BPB.heads);
|
||||
DicConsole.DebugWriteLine("SolarFS plugin", "BPB.x86_jump: 0x{0:X2}{1:X2}{2:X2}", bpb.x86_jump[0],
|
||||
bpb.x86_jump[1], bpb.x86_jump[2]);
|
||||
DicConsole.DebugWriteLine("SolarFS plugin", "BPB.OEMName: \"{0}\"", bpb.OEMName);
|
||||
DicConsole.DebugWriteLine("SolarFS plugin", "BPB.bps: {0}", bpb.bps);
|
||||
DicConsole.DebugWriteLine("SolarFS plugin", "BPB.unk1: 0x{0:X2}", bpb.unk1);
|
||||
DicConsole.DebugWriteLine("SolarFS plugin", "BPB.unk2: 0x{0:X4}", bpb.unk2);
|
||||
DicConsole.DebugWriteLine("SolarFS plugin", "BPB.root_ent: {0}", bpb.root_ent);
|
||||
DicConsole.DebugWriteLine("SolarFS plugin", "BPB.sectors: {0}", bpb.sectors);
|
||||
DicConsole.DebugWriteLine("SolarFS plugin", "BPB.media: 0x{0:X2}", bpb.media);
|
||||
DicConsole.DebugWriteLine("SolarFS plugin", "BPB.spfat: {0}", bpb.spfat);
|
||||
DicConsole.DebugWriteLine("SolarFS plugin", "BPB.sptrk: {0}", bpb.sptrk);
|
||||
DicConsole.DebugWriteLine("SolarFS plugin", "BPB.heads: {0}", bpb.heads);
|
||||
DicConsole.DebugWriteLine("SolarFS plugin",
|
||||
"BPB.unk3: 0x{0:X2}{1:X2}{2:X2}{3:X2}{4:X2}{5:X2}{6:X2}{7:X2}{8:X2}{9:X2}",
|
||||
BPB.unk3[0], BPB.unk3[1], BPB.unk3[2], BPB.unk3[3], BPB.unk3[4], BPB.unk3[5],
|
||||
BPB.unk3[6], BPB.unk3[7], BPB.unk3[8], BPB.unk3[9]);
|
||||
DicConsole.DebugWriteLine("SolarFS plugin", "BPB.signature: 0x{0:X2}", BPB.signature);
|
||||
DicConsole.DebugWriteLine("SolarFS plugin", "BPB.unk4: 0x{0:X8}", BPB.unk4);
|
||||
DicConsole.DebugWriteLine("SolarFS plugin", "BPB.vol_name: \"{0}\"", BPB.vol_name);
|
||||
DicConsole.DebugWriteLine("SolarFS plugin", "BPB.fs_type: \"{0}\"", BPB.fs_type);
|
||||
bpb.unk3[0], bpb.unk3[1], bpb.unk3[2], bpb.unk3[3], bpb.unk3[4], bpb.unk3[5],
|
||||
bpb.unk3[6], bpb.unk3[7], bpb.unk3[8], bpb.unk3[9]);
|
||||
DicConsole.DebugWriteLine("SolarFS plugin", "BPB.signature: 0x{0:X2}", bpb.signature);
|
||||
DicConsole.DebugWriteLine("SolarFS plugin", "BPB.unk4: 0x{0:X8}", bpb.unk4);
|
||||
DicConsole.DebugWriteLine("SolarFS plugin", "BPB.vol_name: \"{0}\"", bpb.vol_name);
|
||||
DicConsole.DebugWriteLine("SolarFS plugin", "BPB.fs_type: \"{0}\"", bpb.fs_type);
|
||||
|
||||
sb.AppendLine("Solar_OS filesystem");
|
||||
sb.AppendFormat("Media descriptor: 0x{0:X2}", BPB.media).AppendLine();
|
||||
sb.AppendFormat("{0} bytes per sector", BPB.bps).AppendLine();
|
||||
sb.AppendFormat("Media descriptor: 0x{0:X2}", bpb.media).AppendLine();
|
||||
sb.AppendFormat("{0} bytes per sector", bpb.bps).AppendLine();
|
||||
if(imagePlugin.GetSectorSize() == 2336 || imagePlugin.GetSectorSize() == 2352 ||
|
||||
imagePlugin.GetSectorSize() == 2448)
|
||||
{
|
||||
if(BPB.bps != imagePlugin.GetSectorSize())
|
||||
if(bpb.bps != imagePlugin.GetSectorSize())
|
||||
sb
|
||||
.AppendFormat("WARNING: Filesystem describes a {0} bytes/sector, while device describes a {1} bytes/sector",
|
||||
BPB.bps, 2048).AppendLine();
|
||||
bpb.bps, 2048).AppendLine();
|
||||
}
|
||||
else if(BPB.bps != imagePlugin.GetSectorSize())
|
||||
else if(bpb.bps != imagePlugin.GetSectorSize())
|
||||
sb
|
||||
.AppendFormat("WARNING: Filesystem describes a {0} bytes/sector, while device describes a {1} bytes/sector",
|
||||
BPB.bps, imagePlugin.GetSectorSize()).AppendLine();
|
||||
sb.AppendFormat("{0} sectors on volume ({1} bytes)", BPB.sectors, BPB.sectors * BPB.bps).AppendLine();
|
||||
if(BPB.sectors > imagePlugin.GetSectors())
|
||||
bpb.bps, imagePlugin.GetSectorSize()).AppendLine();
|
||||
sb.AppendFormat("{0} sectors on volume ({1} bytes)", bpb.sectors, bpb.sectors * bpb.bps).AppendLine();
|
||||
if(bpb.sectors > imagePlugin.GetSectors())
|
||||
sb.AppendFormat("WARNING: Filesystem describes a {0} sectors volume, bigger than device ({1} sectors)",
|
||||
BPB.sectors, imagePlugin.GetSectors());
|
||||
sb.AppendFormat("{0} heads", BPB.heads).AppendLine();
|
||||
sb.AppendFormat("{0} sectors per track", BPB.sptrk).AppendLine();
|
||||
sb.AppendFormat("Volume name: {0}", BPB.vol_name).AppendLine();
|
||||
bpb.sectors, imagePlugin.GetSectors());
|
||||
sb.AppendFormat("{0} heads", bpb.heads).AppendLine();
|
||||
sb.AppendFormat("{0} sectors per track", bpb.sptrk).AppendLine();
|
||||
sb.AppendFormat("Volume name: {0}", bpb.vol_name).AppendLine();
|
||||
|
||||
xmlFSType = new FileSystemType();
|
||||
xmlFSType.Type = "SolarFS";
|
||||
xmlFSType.Clusters = BPB.sectors;
|
||||
xmlFSType.ClusterSize = BPB.bps;
|
||||
xmlFSType.VolumeName = BPB.vol_name;
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
Type = "SolarFS",
|
||||
Clusters = bpb.sectors,
|
||||
ClusterSize = bpb.bps,
|
||||
VolumeName = bpb.vol_name
|
||||
};
|
||||
|
||||
information = sb.ToString();
|
||||
}
|
||||
|
||||
@@ -45,24 +45,22 @@ namespace DiscImageChef.Filesystems
|
||||
public Squash()
|
||||
{
|
||||
Name = "Squash filesystem";
|
||||
PluginUUID = new Guid("F8F6E46F-7A2A-48E3-9C0A-46AF4DC29E09");
|
||||
PluginUuid = new Guid("F8F6E46F-7A2A-48E3-9C0A-46AF4DC29E09");
|
||||
CurrentEncoding = Encoding.UTF8;
|
||||
}
|
||||
|
||||
public Squash(Encoding encoding)
|
||||
{
|
||||
Name = "Squash filesystem";
|
||||
PluginUUID = new Guid("F8F6E46F-7A2A-48E3-9C0A-46AF4DC29E09");
|
||||
if(encoding == null) CurrentEncoding = Encoding.UTF8;
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("F8F6E46F-7A2A-48E3-9C0A-46AF4DC29E09");
|
||||
CurrentEncoding = encoding ?? Encoding.UTF8;
|
||||
}
|
||||
|
||||
public Squash(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "Squash filesystem";
|
||||
PluginUUID = new Guid("F8F6E46F-7A2A-48E3-9C0A-46AF4DC29E09");
|
||||
if(encoding == null) CurrentEncoding = Encoding.UTF8;
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("F8F6E46F-7A2A-48E3-9C0A-46AF4DC29E09");
|
||||
CurrentEncoding = encoding ?? Encoding.UTF8;
|
||||
}
|
||||
|
||||
enum SquashCompression : ushort
|
||||
@@ -102,8 +100,8 @@ namespace DiscImageChef.Filesystems
|
||||
/// <summary>
|
||||
/// Identifier for Squash
|
||||
/// </summary>
|
||||
const uint Squash_MAGIC = 0x73717368;
|
||||
const uint Squash_CIGAM = 0x68737173;
|
||||
const uint SQUASH_MAGIC = 0x73717368;
|
||||
const uint SQUASH_CIGAM = 0x68737173;
|
||||
|
||||
public override bool Identify(ImagePlugin imagePlugin, Partition partition)
|
||||
{
|
||||
@@ -113,7 +111,7 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
uint magic = BitConverter.ToUInt32(sector, 0x00);
|
||||
|
||||
return magic == Squash_MAGIC || magic == Squash_CIGAM;
|
||||
return magic == SQUASH_MAGIC || magic == SQUASH_CIGAM;
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
|
||||
@@ -126,13 +124,13 @@ namespace DiscImageChef.Filesystems
|
||||
bool littleEndian = true;
|
||||
|
||||
switch(magic) {
|
||||
case Squash_MAGIC:
|
||||
case SQUASH_MAGIC:
|
||||
IntPtr sqSbPtr = Marshal.AllocHGlobal(Marshal.SizeOf(sqSb));
|
||||
Marshal.Copy(sector, 0, sqSbPtr, Marshal.SizeOf(sqSb));
|
||||
sqSb = (SquashSuperBlock)Marshal.PtrToStructure(sqSbPtr, typeof(SquashSuperBlock));
|
||||
Marshal.FreeHGlobal(sqSbPtr);
|
||||
break;
|
||||
case Squash_CIGAM:
|
||||
case SQUASH_CIGAM:
|
||||
sqSb = BigEndianMarshal.ByteArrayToStructureBigEndian<SquashSuperBlock>(sector);
|
||||
littleEndian = false;
|
||||
break;
|
||||
@@ -141,8 +139,7 @@ namespace DiscImageChef.Filesystems
|
||||
StringBuilder sbInformation = new StringBuilder();
|
||||
|
||||
sbInformation.AppendLine("Squash file system");
|
||||
if(littleEndian) sbInformation.AppendLine("Little-endian");
|
||||
else sbInformation.AppendLine("Big-endian");
|
||||
sbInformation.AppendLine(littleEndian ? "Little-endian" : "Big-endian");
|
||||
sbInformation.AppendFormat("Volume version {0}.{1}", sqSb.s_major, sqSb.s_minor).AppendLine();
|
||||
sbInformation.AppendFormat("Volume has {0} bytes", sqSb.bytes_used).AppendLine();
|
||||
sbInformation.AppendFormat("Volume has {0} bytes per block", sqSb.block_size).AppendLine();
|
||||
@@ -177,17 +174,19 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
information = sbInformation.ToString();
|
||||
|
||||
xmlFSType = new FileSystemType();
|
||||
xmlFSType.Type = "Squash file system";
|
||||
xmlFSType.CreationDate = DateHandlers.UNIXUnsignedToDateTime(sqSb.mkfs_time);
|
||||
xmlFSType.CreationDateSpecified = true;
|
||||
xmlFSType.Clusters = (long)((partition.End - partition.Start + 1) * imagePlugin.ImageInfo.SectorSize /
|
||||
sqSb.block_size);
|
||||
xmlFSType.ClusterSize = (int)sqSb.block_size;
|
||||
xmlFSType.Files = sqSb.inodes;
|
||||
xmlFSType.FilesSpecified = true;
|
||||
xmlFSType.FreeClusters = 0;
|
||||
xmlFSType.FreeClustersSpecified = true;
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
Type = "Squash file system",
|
||||
CreationDate = DateHandlers.UNIXUnsignedToDateTime(sqSb.mkfs_time),
|
||||
CreationDateSpecified = true,
|
||||
Clusters =
|
||||
(long)((partition.End - partition.Start + 1) * imagePlugin.ImageInfo.SectorSize / sqSb.block_size),
|
||||
ClusterSize = (int)sqSb.block_size,
|
||||
Files = sqSb.inodes,
|
||||
FilesSpecified = true,
|
||||
FreeClusters = 0,
|
||||
FreeClustersSpecified = true
|
||||
};
|
||||
}
|
||||
|
||||
public override Errno Mount()
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using DiscImageChef.CommonTypes;
|
||||
@@ -41,6 +42,7 @@ using Schemas;
|
||||
namespace DiscImageChef.Filesystems
|
||||
{
|
||||
// Information from the Linux kernel
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
public class SysVfs : Filesystem
|
||||
{
|
||||
const uint XENIX_MAGIC = 0x002B5544;
|
||||
@@ -64,55 +66,28 @@ namespace DiscImageChef.Filesystems
|
||||
public SysVfs()
|
||||
{
|
||||
Name = "UNIX System V filesystem";
|
||||
PluginUUID = new Guid("9B8D016A-8561-400E-A12A-A198283C211D");
|
||||
PluginUuid = new Guid("9B8D016A-8561-400E-A12A-A198283C211D");
|
||||
CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public SysVfs(Encoding encoding)
|
||||
{
|
||||
Name = "UNIX System V filesystem";
|
||||
PluginUUID = new Guid("9B8D016A-8561-400E-A12A-A198283C211D");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("9B8D016A-8561-400E-A12A-A198283C211D");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public SysVfs(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "UNIX System V filesystem";
|
||||
PluginUUID = new Guid("9B8D016A-8561-400E-A12A-A198283C211D");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("9B8D016A-8561-400E-A12A-A198283C211D");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugin imagePlugin, Partition partition)
|
||||
{
|
||||
if(2 + partition.Start >= partition.End) return false;
|
||||
|
||||
uint magic;
|
||||
string s_fname, s_fpack;
|
||||
ushort s_nfree, s_ninode;
|
||||
uint s_fsize;
|
||||
|
||||
/*for(int j = 0; j<=(br.BaseStream.Length/0x200); j++)
|
||||
{
|
||||
br.BaseStream.Seek(offset + j*0x200 + 0x1F8, SeekOrigin.Begin); // System V magic location
|
||||
magic = br.Readuint();
|
||||
|
||||
if(magic == SYSV_MAGIC || magic == SYSV_CIGAM)
|
||||
Console.WriteLine("0x{0:X8}: 0x{1:X8} FOUND", br.BaseStream.Position-4, magic);
|
||||
else
|
||||
Console.WriteLine("0x{0:X8}: 0x{1:X8}", br.BaseStream.Position-4, magic);
|
||||
}*/
|
||||
|
||||
/*uint number;
|
||||
br.BaseStream.Seek(offset+0x3A00, SeekOrigin.Begin);
|
||||
while((br.BaseStream.Position) <= (offset+0x3C00))
|
||||
{
|
||||
number = br.Readuint();
|
||||
|
||||
Console.WriteLine("@{0:X8}: 0x{1:X8} ({1})", br.BaseStream.Position-offset-4, number);
|
||||
}*/
|
||||
|
||||
byte sb_size_in_sectors;
|
||||
|
||||
if(imagePlugin.GetSectorSize() <= 0x400
|
||||
@@ -136,7 +111,7 @@ namespace DiscImageChef.Filesystems
|
||||
};
|
||||
|
||||
foreach(byte[] sb_sector in locations.TakeWhile(i => i + sb_size_in_sectors < (int)imagePlugin.ImageInfo.Sectors).Select(i => imagePlugin.ReadSectors((ulong)i + partition.Start, sb_size_in_sectors))) {
|
||||
magic = BitConverter.ToUInt32(sb_sector, 0x3F8); // XENIX magic location
|
||||
uint magic = BitConverter.ToUInt32(sb_sector, 0x3F8);
|
||||
|
||||
if(magic == XENIX_MAGIC || magic == XENIX_CIGAM || magic == SYSV_MAGIC || magic == SYSV_CIGAM)
|
||||
return true;
|
||||
@@ -151,17 +126,17 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
byte[] coherent_string = new byte[6];
|
||||
Array.Copy(sb_sector, 0x1E4, coherent_string, 0, 6); // Coherent UNIX s_fname location
|
||||
s_fname = StringHandlers.CToString(coherent_string, CurrentEncoding);
|
||||
string s_fname = StringHandlers.CToString(coherent_string, CurrentEncoding);
|
||||
Array.Copy(sb_sector, 0x1EA, coherent_string, 0, 6); // Coherent UNIX s_fpack location
|
||||
s_fpack = StringHandlers.CToString(coherent_string, CurrentEncoding);
|
||||
string s_fpack = StringHandlers.CToString(coherent_string, CurrentEncoding);
|
||||
|
||||
if(s_fname == COH_FNAME && s_fpack == COH_FPACK || s_fname == COH_XXXXX && s_fpack == COH_XXXXX ||
|
||||
s_fname == COH_XXXXS && s_fpack == COH_XXXXN) return true;
|
||||
|
||||
// Now try to identify 7th edition
|
||||
s_fsize = BitConverter.ToUInt32(sb_sector, 0x002); // 7th edition's s_fsize
|
||||
s_nfree = BitConverter.ToUInt16(sb_sector, 0x006); // 7th edition's s_nfree
|
||||
s_ninode = BitConverter.ToUInt16(sb_sector, 0x0D0); // 7th edition's s_ninode
|
||||
uint s_fsize = BitConverter.ToUInt32(sb_sector, 0x002);
|
||||
ushort s_nfree = BitConverter.ToUInt16(sb_sector, 0x006);
|
||||
ushort s_ninode = BitConverter.ToUInt16(sb_sector, 0x0D0);
|
||||
|
||||
if(s_fsize <= 0 || s_fsize >= 0xFFFFFFFF || s_nfree <= 0 || s_nfree >= 0xFFFF || s_ninode <= 0 ||
|
||||
s_ninode >= 0xFFFF) continue;
|
||||
@@ -197,13 +172,8 @@ namespace DiscImageChef.Filesystems
|
||||
BigEndianBitConverter.IsLittleEndian =
|
||||
true; // Start in little endian until we know what are we handling here
|
||||
int start = 0;
|
||||
uint magic;
|
||||
string s_fname, s_fpack;
|
||||
ushort s_nfree, s_ninode;
|
||||
uint s_fsize;
|
||||
bool xenix = false;
|
||||
bool sysv = false;
|
||||
bool sysvr4;
|
||||
bool sys7th = false;
|
||||
bool coherent = false;
|
||||
bool xenix3 = false;
|
||||
@@ -229,7 +199,7 @@ namespace DiscImageChef.Filesystems
|
||||
foreach(int i in locations)
|
||||
{
|
||||
sb_sector = imagePlugin.ReadSectors((ulong)i + partition.Start, sb_size_in_sectors);
|
||||
magic = BigEndianBitConverter.ToUInt32(sb_sector, 0x3F8); // XENIX magic location
|
||||
uint magic = BigEndianBitConverter.ToUInt32(sb_sector, 0x3F8);
|
||||
|
||||
if(magic == XENIX_MAGIC || magic == SYSV_MAGIC)
|
||||
{
|
||||
@@ -295,9 +265,9 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
byte[] coherent_string = new byte[6];
|
||||
Array.Copy(sb_sector, 0x1E4, coherent_string, 0, 6); // Coherent UNIX s_fname location
|
||||
s_fname = StringHandlers.CToString(coherent_string, CurrentEncoding);
|
||||
string s_fname = StringHandlers.CToString(coherent_string, CurrentEncoding);
|
||||
Array.Copy(sb_sector, 0x1EA, coherent_string, 0, 6); // Coherent UNIX s_fpack location
|
||||
s_fpack = StringHandlers.CToString(coherent_string, CurrentEncoding);
|
||||
string s_fpack = StringHandlers.CToString(coherent_string, CurrentEncoding);
|
||||
|
||||
if(s_fname == COH_FNAME && s_fpack == COH_FPACK || s_fname == COH_XXXXX && s_fpack == COH_XXXXX ||
|
||||
s_fname == COH_XXXXS && s_fpack == COH_XXXXN)
|
||||
@@ -309,9 +279,9 @@ namespace DiscImageChef.Filesystems
|
||||
}
|
||||
|
||||
// Now try to identify 7th edition
|
||||
s_fsize = BitConverter.ToUInt32(sb_sector, 0x002); // 7th edition's s_fsize
|
||||
s_nfree = BitConverter.ToUInt16(sb_sector, 0x006); // 7th edition's s_nfree
|
||||
s_ninode = BitConverter.ToUInt16(sb_sector, 0x0D0); // 7th edition's s_ninode
|
||||
uint s_fsize = BitConverter.ToUInt32(sb_sector, 0x002);
|
||||
ushort s_nfree = BitConverter.ToUInt16(sb_sector, 0x006);
|
||||
ushort s_ninode = BitConverter.ToUInt16(sb_sector, 0x0D0);
|
||||
|
||||
if(s_fsize <= 0 || s_fsize >= 0xFFFFFFFF || s_nfree <= 0 || s_nfree >= 0xFFFF || s_ninode <= 0 ||
|
||||
s_ninode >= 0xFFFF) continue;
|
||||
@@ -341,7 +311,7 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
if(!sys7th && !sysv && !coherent && !xenix && !xenix3) return;
|
||||
|
||||
xmlFSType = new FileSystemType();
|
||||
XmlFsType = new FileSystemType();
|
||||
|
||||
if(xenix || xenix3)
|
||||
{
|
||||
@@ -402,22 +372,22 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
uint bs = 512;
|
||||
sb.AppendLine("XENIX filesystem");
|
||||
xmlFSType.Type = "XENIX fs";
|
||||
XmlFsType.Type = "XENIX fs";
|
||||
switch(xnx_sb.s_type)
|
||||
{
|
||||
case 1:
|
||||
sb.AppendLine("512 bytes per block");
|
||||
xmlFSType.ClusterSize = 512;
|
||||
XmlFsType.ClusterSize = 512;
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendLine("1024 bytes per block");
|
||||
bs = 1024;
|
||||
xmlFSType.ClusterSize = 1024;
|
||||
XmlFsType.ClusterSize = 1024;
|
||||
break;
|
||||
case 3:
|
||||
sb.AppendLine("2048 bytes per block");
|
||||
bs = 2048;
|
||||
xmlFSType.ClusterSize = 2048;
|
||||
XmlFsType.ClusterSize = 2048;
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("Unknown s_type value: 0x{0:X8}", xnx_sb.s_type).AppendLine();
|
||||
@@ -458,17 +428,17 @@ namespace DiscImageChef.Filesystems
|
||||
.AppendLine();
|
||||
if(xnx_sb.s_time != 0)
|
||||
{
|
||||
xmlFSType.ModificationDate = DateHandlers.UNIXToDateTime(xnx_sb.s_time);
|
||||
xmlFSType.ModificationDateSpecified = true;
|
||||
XmlFsType.ModificationDate = DateHandlers.UNIXToDateTime(xnx_sb.s_time);
|
||||
XmlFsType.ModificationDateSpecified = true;
|
||||
}
|
||||
sb.AppendFormat("Volume name: {0}", xnx_sb.s_fname).AppendLine();
|
||||
xmlFSType.VolumeName = xnx_sb.s_fname;
|
||||
XmlFsType.VolumeName = xnx_sb.s_fname;
|
||||
sb.AppendFormat("Pack name: {0}", xnx_sb.s_fpack).AppendLine();
|
||||
if(xnx_sb.s_clean == 0x46) sb.AppendLine("Volume is clean");
|
||||
else
|
||||
{
|
||||
sb.AppendLine("Volume is dirty");
|
||||
xmlFSType.Dirty = true;
|
||||
XmlFsType.Dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -477,21 +447,23 @@ namespace DiscImageChef.Filesystems
|
||||
sb_sector = imagePlugin.ReadSectors((ulong)start + partition.Start, sb_size_in_sectors);
|
||||
byte[] sysv_strings = new byte[6];
|
||||
|
||||
SystemVRelease4SuperBlock sysv_sb = new SystemVRelease4SuperBlock();
|
||||
sysv_sb.s_type = BigEndianBitConverter.ToUInt32(sb_sector, 0x1FC + offset);
|
||||
SystemVRelease4SuperBlock sysv_sb = new SystemVRelease4SuperBlock
|
||||
{
|
||||
s_type = BigEndianBitConverter.ToUInt32(sb_sector, 0x1FC + offset)
|
||||
};
|
||||
uint bs = 512;
|
||||
switch(sysv_sb.s_type)
|
||||
{
|
||||
case 1:
|
||||
xmlFSType.ClusterSize = 512;
|
||||
XmlFsType.ClusterSize = 512;
|
||||
break;
|
||||
case 2:
|
||||
bs = 1024;
|
||||
xmlFSType.ClusterSize = 1024;
|
||||
XmlFsType.ClusterSize = 1024;
|
||||
break;
|
||||
case 3:
|
||||
bs = 2048;
|
||||
xmlFSType.ClusterSize = 2048;
|
||||
XmlFsType.ClusterSize = 2048;
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("Unknown s_type value: 0x{0:X8}", sysv_sb.s_type).AppendLine();
|
||||
@@ -500,7 +472,7 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
sysv_sb.s_fsize = BigEndianBitConverter.ToUInt32(sb_sector, 0x002 + offset);
|
||||
|
||||
sysvr4 = sysv_sb.s_fsize * bs <= 0 || sysv_sb.s_fsize * bs != partition.Size;
|
||||
bool sysvr4 = sysv_sb.s_fsize * bs <= 0 || sysv_sb.s_fsize * bs != partition.Size;
|
||||
|
||||
if(sysvr4)
|
||||
{
|
||||
@@ -526,7 +498,7 @@ namespace DiscImageChef.Filesystems
|
||||
Array.Copy(sb_sector, 0x1BC + offset, sysv_strings, 0, 6);
|
||||
sysv_sb.s_fpack = StringHandlers.CToString(sysv_strings, CurrentEncoding);
|
||||
sb.AppendLine("System V Release 4 filesystem");
|
||||
xmlFSType.Type = "SVR4 fs";
|
||||
XmlFsType.Type = "SVR4 fs";
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -552,11 +524,11 @@ namespace DiscImageChef.Filesystems
|
||||
Array.Copy(sb_sector, 0x1B6 + offset, sysv_strings, 0, 6);
|
||||
sysv_sb.s_fpack = StringHandlers.CToString(sysv_strings, CurrentEncoding);
|
||||
sb.AppendLine("System V Release 2 filesystem");
|
||||
xmlFSType.Type = "SVR2 fs";
|
||||
XmlFsType.Type = "SVR2 fs";
|
||||
}
|
||||
sb.AppendFormat("{0} bytes per block", bs).AppendLine();
|
||||
|
||||
xmlFSType.Clusters = sysv_sb.s_fsize;
|
||||
XmlFsType.Clusters = sysv_sb.s_fsize;
|
||||
sb.AppendFormat("{0} zones on volume ({1} bytes)", sysv_sb.s_fsize, sysv_sb.s_fsize * bs).AppendLine();
|
||||
sb.AppendFormat("{0} free zones on volume ({1} bytes)", sysv_sb.s_tfree, sysv_sb.s_tfree * bs)
|
||||
.AppendLine();
|
||||
@@ -577,17 +549,17 @@ namespace DiscImageChef.Filesystems
|
||||
.AppendLine();
|
||||
if(sysv_sb.s_time != 0)
|
||||
{
|
||||
xmlFSType.ModificationDate = DateHandlers.UNIXUnsignedToDateTime(sysv_sb.s_time);
|
||||
xmlFSType.ModificationDateSpecified = true;
|
||||
XmlFsType.ModificationDate = DateHandlers.UNIXUnsignedToDateTime(sysv_sb.s_time);
|
||||
XmlFsType.ModificationDateSpecified = true;
|
||||
}
|
||||
sb.AppendFormat("Volume name: {0}", sysv_sb.s_fname).AppendLine();
|
||||
xmlFSType.VolumeName = sysv_sb.s_fname;
|
||||
XmlFsType.VolumeName = sysv_sb.s_fname;
|
||||
sb.AppendFormat("Pack name: {0}", sysv_sb.s_fpack).AppendLine();
|
||||
if(sysv_sb.s_state == 0x7C269D38 - sysv_sb.s_time) sb.AppendLine("Volume is clean");
|
||||
else
|
||||
{
|
||||
sb.AppendLine("Volume is dirty");
|
||||
xmlFSType.Dirty = true;
|
||||
XmlFsType.Dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -615,9 +587,9 @@ namespace DiscImageChef.Filesystems
|
||||
Array.Copy(sb_sector, 0x1EA, coh_strings, 0, 6);
|
||||
coh_sb.s_fpack = StringHandlers.CToString(coh_strings, CurrentEncoding);
|
||||
|
||||
xmlFSType.Type = "Coherent fs";
|
||||
xmlFSType.ClusterSize = 512;
|
||||
xmlFSType.Clusters = coh_sb.s_fsize;
|
||||
XmlFsType.Type = "Coherent fs";
|
||||
XmlFsType.ClusterSize = 512;
|
||||
XmlFsType.Clusters = coh_sb.s_fsize;
|
||||
|
||||
sb.AppendLine("Coherent UNIX filesystem");
|
||||
if(imagePlugin.GetSectorSize() != 512)
|
||||
@@ -640,11 +612,11 @@ namespace DiscImageChef.Filesystems
|
||||
.AppendLine();
|
||||
if(coh_sb.s_time != 0)
|
||||
{
|
||||
xmlFSType.ModificationDate = DateHandlers.UNIXUnsignedToDateTime(coh_sb.s_time);
|
||||
xmlFSType.ModificationDateSpecified = true;
|
||||
XmlFsType.ModificationDate = DateHandlers.UNIXUnsignedToDateTime(coh_sb.s_time);
|
||||
XmlFsType.ModificationDateSpecified = true;
|
||||
}
|
||||
sb.AppendFormat("Volume name: {0}", coh_sb.s_fname).AppendLine();
|
||||
xmlFSType.VolumeName = coh_sb.s_fname;
|
||||
XmlFsType.VolumeName = coh_sb.s_fname;
|
||||
sb.AppendFormat("Pack name: {0}", coh_sb.s_fpack).AppendLine();
|
||||
}
|
||||
|
||||
@@ -672,9 +644,9 @@ namespace DiscImageChef.Filesystems
|
||||
Array.Copy(sb_sector, 0x1B2, sys7_strings, 0, 6);
|
||||
v7_sb.s_fpack = StringHandlers.CToString(sys7_strings, CurrentEncoding);
|
||||
|
||||
xmlFSType.Type = "UNIX 7th Edition fs";
|
||||
xmlFSType.ClusterSize = 512;
|
||||
xmlFSType.Clusters = v7_sb.s_fsize;
|
||||
XmlFsType.Type = "UNIX 7th Edition fs";
|
||||
XmlFsType.ClusterSize = 512;
|
||||
XmlFsType.Clusters = v7_sb.s_fsize;
|
||||
sb.AppendLine("UNIX 7th Edition filesystem");
|
||||
if(imagePlugin.GetSectorSize() != 512)
|
||||
sb
|
||||
@@ -695,11 +667,11 @@ namespace DiscImageChef.Filesystems
|
||||
.AppendLine();
|
||||
if(v7_sb.s_time != 0)
|
||||
{
|
||||
xmlFSType.ModificationDate = DateHandlers.UNIXUnsignedToDateTime(v7_sb.s_time);
|
||||
xmlFSType.ModificationDateSpecified = true;
|
||||
XmlFsType.ModificationDate = DateHandlers.UNIXUnsignedToDateTime(v7_sb.s_time);
|
||||
XmlFsType.ModificationDateSpecified = true;
|
||||
}
|
||||
sb.AppendFormat("Volume name: {0}", v7_sb.s_fname).AppendLine();
|
||||
xmlFSType.VolumeName = v7_sb.s_fname;
|
||||
XmlFsType.VolumeName = v7_sb.s_fname;
|
||||
sb.AppendFormat("Pack name: {0}", v7_sb.s_fpack).AppendLine();
|
||||
}
|
||||
|
||||
|
||||
@@ -40,9 +40,7 @@ namespace DiscImageChef.Filesystems.UCSDPascal
|
||||
{
|
||||
public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock)
|
||||
{
|
||||
if(!mounted) return Errno.AccessDenied;
|
||||
|
||||
return Errno.NotImplemented;
|
||||
return !mounted ? Errno.AccessDenied : Errno.NotImplemented;
|
||||
}
|
||||
|
||||
public override Errno GetAttributes(string path, ref FileAttributes attributes)
|
||||
@@ -52,8 +50,7 @@ namespace DiscImageChef.Filesystems.UCSDPascal
|
||||
string[] pathElements = path.Split(new[] {'/'}, StringSplitOptions.RemoveEmptyEntries);
|
||||
if(pathElements.Length != 1) return Errno.NotSupported;
|
||||
|
||||
PascalFileEntry entry;
|
||||
Errno error = GetFileEntry(path, out entry);
|
||||
Errno error = GetFileEntry(path, out _);
|
||||
|
||||
if(error != Errno.NoError) return error;
|
||||
|
||||
@@ -71,16 +68,13 @@ namespace DiscImageChef.Filesystems.UCSDPascal
|
||||
if(pathElements.Length != 1) return Errno.NotSupported;
|
||||
|
||||
byte[] file;
|
||||
Errno error;
|
||||
|
||||
if(debug && (string.Compare(path, "$", StringComparison.InvariantCulture) == 0 ||
|
||||
string.Compare(path, "$Boot", StringComparison.InvariantCulture) == 0))
|
||||
if(string.Compare(path, "$", StringComparison.InvariantCulture) == 0) file = catalogBlocks;
|
||||
else file = bootBlocks;
|
||||
file = string.Compare(path, "$", StringComparison.InvariantCulture) == 0 ? catalogBlocks : bootBlocks;
|
||||
else
|
||||
{
|
||||
PascalFileEntry entry;
|
||||
error = GetFileEntry(path, out entry);
|
||||
Errno error = GetFileEntry(path, out PascalFileEntry entry);
|
||||
|
||||
if(error != Errno.NoError) return error;
|
||||
|
||||
@@ -113,16 +107,17 @@ namespace DiscImageChef.Filesystems.UCSDPascal
|
||||
if(string.Compare(path, "$", StringComparison.InvariantCulture) == 0 ||
|
||||
string.Compare(path, "$Boot", StringComparison.InvariantCulture) == 0)
|
||||
{
|
||||
stat = new FileEntryInfo();
|
||||
stat.Attributes = new FileAttributes();
|
||||
stat.Attributes = FileAttributes.System;
|
||||
stat.BlockSize = device.GetSectorSize();
|
||||
stat.DeviceNo = 0;
|
||||
stat.GID = 0;
|
||||
stat.Inode = 0;
|
||||
stat.Links = 1;
|
||||
stat.Mode = 0x124;
|
||||
stat.UID = 0;
|
||||
stat = new FileEntryInfo
|
||||
{
|
||||
Attributes = FileAttributes.System,
|
||||
BlockSize = device.GetSectorSize(),
|
||||
DeviceNo = 0,
|
||||
GID = 0,
|
||||
Inode = 0,
|
||||
Links = 1,
|
||||
Mode = 0x124,
|
||||
UID = 0
|
||||
};
|
||||
|
||||
if(string.Compare(path, "$", StringComparison.InvariantCulture) == 0)
|
||||
{
|
||||
@@ -138,24 +133,24 @@ namespace DiscImageChef.Filesystems.UCSDPascal
|
||||
return Errno.NoError;
|
||||
}
|
||||
|
||||
PascalFileEntry entry;
|
||||
Errno error = GetFileEntry(path, out entry);
|
||||
Errno error = GetFileEntry(path, out PascalFileEntry entry);
|
||||
|
||||
if(error != Errno.NoError) return error;
|
||||
|
||||
stat = new FileEntryInfo();
|
||||
stat.Attributes = new FileAttributes();
|
||||
stat.Attributes = FileAttributes.File;
|
||||
stat.Blocks = entry.lastBlock - entry.firstBlock;
|
||||
stat.BlockSize = device.GetSectorSize();
|
||||
stat.DeviceNo = 0;
|
||||
stat.GID = 0;
|
||||
stat.Inode = 0;
|
||||
stat.LastWriteTimeUtc = DateHandlers.UCSDPascalToDateTime(entry.mtime);
|
||||
stat.Length = (entry.lastBlock - entry.firstBlock) * device.GetSectorSize() + entry.lastBytes;
|
||||
stat.Links = 1;
|
||||
stat.Mode = 0x124;
|
||||
stat.UID = 0;
|
||||
stat = new FileEntryInfo
|
||||
{
|
||||
Attributes = FileAttributes.File,
|
||||
Blocks = entry.lastBlock - entry.firstBlock,
|
||||
BlockSize = device.GetSectorSize(),
|
||||
DeviceNo = 0,
|
||||
GID = 0,
|
||||
Inode = 0,
|
||||
LastWriteTimeUtc = DateHandlers.UCSDPascalToDateTime(entry.mtime),
|
||||
Length = (entry.lastBlock - entry.firstBlock) * device.GetSectorSize() + entry.lastBytes,
|
||||
Links = 1,
|
||||
Mode = 0x124,
|
||||
UID = 0
|
||||
};
|
||||
|
||||
return Errno.NoError;
|
||||
}
|
||||
|
||||
@@ -143,14 +143,16 @@ namespace DiscImageChef.Filesystems.UCSDPascal
|
||||
|
||||
information = sbInformation.ToString();
|
||||
|
||||
xmlFSType = new FileSystemType();
|
||||
xmlFSType.Bootable = !ArrayHelpers.ArrayIsNullOrEmpty(imagePlugin.ReadSectors(partition.Start, 2));
|
||||
xmlFSType.Clusters = volEntry.blocks;
|
||||
xmlFSType.ClusterSize = (int)imagePlugin.GetSectorSize();
|
||||
xmlFSType.Files = volEntry.files;
|
||||
xmlFSType.FilesSpecified = true;
|
||||
xmlFSType.Type = "UCSD Pascal";
|
||||
xmlFSType.VolumeName = StringHandlers.PascalToString(volEntry.volumeName, CurrentEncoding);
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
Bootable = !ArrayHelpers.ArrayIsNullOrEmpty(imagePlugin.ReadSectors(partition.Start, 2)),
|
||||
Clusters = volEntry.blocks,
|
||||
ClusterSize = (int)imagePlugin.GetSectorSize(),
|
||||
Files = volEntry.files,
|
||||
FilesSpecified = true,
|
||||
Type = "UCSD Pascal",
|
||||
VolumeName = StringHandlers.PascalToString(volEntry.volumeName, CurrentEncoding)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -78,14 +78,16 @@ namespace DiscImageChef.Filesystems.UCSDPascal
|
||||
fileEntries = new List<PascalFileEntry>();
|
||||
while(offset + 26 < catalogBlocks.Length)
|
||||
{
|
||||
PascalFileEntry entry = new PascalFileEntry();
|
||||
entry.filename = new byte[16];
|
||||
entry.firstBlock = BigEndianBitConverter.ToInt16(catalogBlocks, offset + 0x00);
|
||||
entry.lastBlock = BigEndianBitConverter.ToInt16(catalogBlocks, offset + 0x02);
|
||||
entry.entryType = (PascalFileKind)BigEndianBitConverter.ToInt16(catalogBlocks, offset + 0x04);
|
||||
PascalFileEntry entry = new PascalFileEntry
|
||||
{
|
||||
filename = new byte[16],
|
||||
firstBlock = BigEndianBitConverter.ToInt16(catalogBlocks, offset + 0x00),
|
||||
lastBlock = BigEndianBitConverter.ToInt16(catalogBlocks, offset + 0x02),
|
||||
entryType = (PascalFileKind)BigEndianBitConverter.ToInt16(catalogBlocks, offset + 0x04),
|
||||
lastBytes = BigEndianBitConverter.ToInt16(catalogBlocks, offset + 0x16),
|
||||
mtime = BigEndianBitConverter.ToInt16(catalogBlocks, offset + 0x18)
|
||||
};
|
||||
Array.Copy(catalogBlocks, offset + 0x06, entry.filename, 0, 16);
|
||||
entry.lastBytes = BigEndianBitConverter.ToInt16(catalogBlocks, offset + 0x16);
|
||||
entry.mtime = BigEndianBitConverter.ToInt16(catalogBlocks, offset + 0x18);
|
||||
|
||||
if(entry.filename[0] <= 15 && entry.filename[0] > 0) fileEntries.Add(entry);
|
||||
|
||||
@@ -94,14 +96,16 @@ namespace DiscImageChef.Filesystems.UCSDPascal
|
||||
|
||||
bootBlocks = device.ReadSectors(0, 2);
|
||||
|
||||
xmlFSType = new FileSystemType();
|
||||
xmlFSType.Bootable = !ArrayHelpers.ArrayIsNullOrEmpty(bootBlocks);
|
||||
xmlFSType.Clusters = mountedVolEntry.blocks;
|
||||
xmlFSType.ClusterSize = (int)device.GetSectorSize();
|
||||
xmlFSType.Files = mountedVolEntry.files;
|
||||
xmlFSType.FilesSpecified = true;
|
||||
xmlFSType.Type = "UCSD Pascal";
|
||||
xmlFSType.VolumeName = StringHandlers.PascalToString(mountedVolEntry.volumeName, CurrentEncoding);
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
Bootable = !ArrayHelpers.ArrayIsNullOrEmpty(bootBlocks),
|
||||
Clusters = mountedVolEntry.blocks,
|
||||
ClusterSize = (int)device.GetSectorSize(),
|
||||
Files = mountedVolEntry.files,
|
||||
FilesSpecified = true,
|
||||
Type = "UCSD Pascal",
|
||||
VolumeName = StringHandlers.PascalToString(mountedVolEntry.volumeName, CurrentEncoding)
|
||||
};
|
||||
|
||||
mounted = true;
|
||||
|
||||
@@ -122,7 +126,7 @@ namespace DiscImageChef.Filesystems.UCSDPascal
|
||||
stat.FilenameLength = 16;
|
||||
stat.Files = (ulong)mountedVolEntry.files;
|
||||
stat.FreeBlocks = 0;
|
||||
stat.PluginId = PluginUUID;
|
||||
stat.PluginId = PluginUuid;
|
||||
stat.Type = "UCSD Pascal";
|
||||
|
||||
stat.FreeBlocks = mountedVolEntry.blocks - (mountedVolEntry.lastBlock - mountedVolEntry.firstBlock);
|
||||
|
||||
@@ -54,14 +54,14 @@ namespace DiscImageChef.Filesystems.UCSDPascal
|
||||
public PascalPlugin()
|
||||
{
|
||||
Name = "U.C.S.D. Pascal filesystem";
|
||||
PluginUUID = new Guid("B0AC2CB5-72AA-473A-9200-270B5A2C2D53");
|
||||
PluginUuid = new Guid("B0AC2CB5-72AA-473A-9200-270B5A2C2D53");
|
||||
CurrentEncoding = new LisaRoman();
|
||||
}
|
||||
|
||||
public PascalPlugin(Encoding encoding)
|
||||
{
|
||||
Name = "U.C.S.D. Pascal filesystem";
|
||||
PluginUUID = new Guid("B0AC2CB5-72AA-473A-9200-270B5A2C2D53");
|
||||
PluginUuid = new Guid("B0AC2CB5-72AA-473A-9200-270B5A2C2D53");
|
||||
// TODO: Until Apple ][ encoding is implemented
|
||||
CurrentEncoding = new LisaRoman();
|
||||
}
|
||||
@@ -70,7 +70,7 @@ namespace DiscImageChef.Filesystems.UCSDPascal
|
||||
{
|
||||
device = imagePlugin;
|
||||
Name = "U.C.S.D. Pascal filesystem";
|
||||
PluginUUID = new Guid("B0AC2CB5-72AA-473A-9200-270B5A2C2D53");
|
||||
PluginUuid = new Guid("B0AC2CB5-72AA-473A-9200-270B5A2C2D53");
|
||||
// TODO: Until Apple ][ encoding is implemented
|
||||
CurrentEncoding = new LisaRoman();
|
||||
}
|
||||
|
||||
@@ -48,14 +48,14 @@ namespace DiscImageChef.Filesystems
|
||||
public UDF()
|
||||
{
|
||||
Name = "Universal Disk Format";
|
||||
PluginUUID = new Guid("83976FEC-A91B-464B-9293-56C719461BAB");
|
||||
PluginUuid = new Guid("83976FEC-A91B-464B-9293-56C719461BAB");
|
||||
CurrentEncoding = Encoding.UTF8;
|
||||
}
|
||||
|
||||
public UDF(Encoding encoding)
|
||||
{
|
||||
Name = "Universal Disk Format";
|
||||
PluginUUID = new Guid("83976FEC-A91B-464B-9293-56C719461BAB");
|
||||
PluginUuid = new Guid("83976FEC-A91B-464B-9293-56C719461BAB");
|
||||
// UDF is always UTF-8
|
||||
CurrentEncoding = Encoding.UTF8;
|
||||
}
|
||||
@@ -63,7 +63,7 @@ namespace DiscImageChef.Filesystems
|
||||
public UDF(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "Universal Disk Format";
|
||||
PluginUUID = new Guid("83976FEC-A91B-464B-9293-56C719461BAB");
|
||||
PluginUuid = new Guid("83976FEC-A91B-464B-9293-56C719461BAB");
|
||||
// UDF is always UTF-8
|
||||
CurrentEncoding = Encoding.UTF8;
|
||||
}
|
||||
@@ -416,7 +416,7 @@ namespace DiscImageChef.Filesystems
|
||||
.AppendFormat("Volume name: {0}", StringHandlers.DecompressUnicode(lvd.logicalVolumeIdentifier))
|
||||
.AppendLine();
|
||||
sbInformation.AppendFormat("Volume uses {0} bytes per block", lvd.logicalBlockSize).AppendLine();
|
||||
sbInformation.AppendFormat("Volume was las written in {0}", ECMAToDateTime(lvid.recordingDateTime))
|
||||
sbInformation.AppendFormat("Volume was las written in {0}", EcmaToDateTime(lvid.recordingDateTime))
|
||||
.AppendLine();
|
||||
sbInformation.AppendFormat("Volume contains {0} partitions", lvid.numberOfPartitions).AppendLine();
|
||||
sbInformation
|
||||
@@ -445,27 +445,28 @@ namespace DiscImageChef.Filesystems
|
||||
Convert.ToInt32($"{lvidiu.maximumWriteUDF & 0xFF}", 10))
|
||||
.AppendLine();
|
||||
|
||||
xmlFSType = new FileSystemType();
|
||||
xmlFSType.Type =
|
||||
$"UDF v{Convert.ToInt32($"{(lvidiu.maximumWriteUDF & 0xFF00) >> 8}", 10)}.{Convert.ToInt32($"{lvidiu.maximumWriteUDF & 0xFF}", 10):X2}";
|
||||
xmlFSType.ApplicationIdentifier = CurrentEncoding
|
||||
.GetString(pvd.implementationIdentifier.identifier).TrimEnd('\u0000');
|
||||
xmlFSType.ClusterSize = (int)lvd.logicalBlockSize;
|
||||
xmlFSType.Clusters = (long)((partition.End - partition.Start + 1) * imagePlugin.ImageInfo.SectorSize /
|
||||
(ulong)xmlFSType.ClusterSize);
|
||||
xmlFSType.ModificationDate = ECMAToDateTime(lvid.recordingDateTime);
|
||||
xmlFSType.ModificationDateSpecified = true;
|
||||
xmlFSType.Files = lvidiu.files;
|
||||
xmlFSType.FilesSpecified = true;
|
||||
xmlFSType.VolumeName = StringHandlers.DecompressUnicode(lvd.logicalVolumeIdentifier);
|
||||
xmlFSType.VolumeSetIdentifier = StringHandlers.DecompressUnicode(pvd.volumeSetIdentifier);
|
||||
xmlFSType.SystemIdentifier = CurrentEncoding
|
||||
.GetString(pvd.implementationIdentifier.identifier).TrimEnd('\u0000');
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
Type =
|
||||
$"UDF v{Convert.ToInt32($"{(lvidiu.maximumWriteUDF & 0xFF00) >> 8}", 10)}.{Convert.ToInt32($"{lvidiu.maximumWriteUDF & 0xFF}", 10):X2}",
|
||||
ApplicationIdentifier =
|
||||
CurrentEncoding.GetString(pvd.implementationIdentifier.identifier).TrimEnd('\u0000'),
|
||||
ClusterSize = (int)lvd.logicalBlockSize,
|
||||
ModificationDate = EcmaToDateTime(lvid.recordingDateTime),
|
||||
ModificationDateSpecified = true,
|
||||
Files = lvidiu.files,
|
||||
FilesSpecified = true,
|
||||
VolumeName = StringHandlers.DecompressUnicode(lvd.logicalVolumeIdentifier),
|
||||
VolumeSetIdentifier = StringHandlers.DecompressUnicode(pvd.volumeSetIdentifier),
|
||||
SystemIdentifier = CurrentEncoding.GetString(pvd.implementationIdentifier.identifier).TrimEnd('\u0000')
|
||||
};
|
||||
XmlFsType.Clusters = (long)((partition.End - partition.Start + 1) * imagePlugin.ImageInfo.SectorSize /
|
||||
(ulong)XmlFsType.ClusterSize);
|
||||
|
||||
information = sbInformation.ToString();
|
||||
}
|
||||
|
||||
static DateTime ECMAToDateTime(Timestamp timestamp)
|
||||
static DateTime EcmaToDateTime(Timestamp timestamp)
|
||||
{
|
||||
return DateHandlers.ECMAToDateTime(timestamp.typeAndZone, timestamp.year, timestamp.month, timestamp.day,
|
||||
timestamp.hour, timestamp.minute, timestamp.second,
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using DiscImageChef.CommonTypes;
|
||||
@@ -48,6 +49,8 @@ using time_t = System.Int64;
|
||||
|
||||
namespace DiscImageChef.Filesystems
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "BuiltInTypeReferenceStyle")]
|
||||
public class UNICOS : Filesystem
|
||||
{
|
||||
const int NC1MAXPART = 64;
|
||||
@@ -137,24 +140,22 @@ namespace DiscImageChef.Filesystems
|
||||
public UNICOS()
|
||||
{
|
||||
Name = "UNICOS Filesystem Plugin";
|
||||
PluginUUID = new Guid("61712F04-066C-44D5-A2A0-1E44C66B33F0");
|
||||
PluginUuid = new Guid("61712F04-066C-44D5-A2A0-1E44C66B33F0");
|
||||
CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public UNICOS(Encoding encoding)
|
||||
{
|
||||
Name = "UNICOS Filesystem Plugin";
|
||||
PluginUUID = new Guid("61712F04-066C-44D5-A2A0-1E44C66B33F0");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("61712F04-066C-44D5-A2A0-1E44C66B33F0");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public UNICOS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "UNICOS Filesystem Plugin";
|
||||
PluginUUID = new Guid("61712F04-066C-44D5-A2A0-1E44C66B33F0");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("61712F04-066C-44D5-A2A0-1E44C66B33F0");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugin imagePlugin, Partition partition)
|
||||
@@ -213,7 +214,7 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
information = sb.ToString();
|
||||
|
||||
xmlFSType = new FileSystemType
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
Type = "UNICOS filesystem",
|
||||
ClusterSize = 4096,
|
||||
@@ -222,7 +223,7 @@ namespace DiscImageChef.Filesystems
|
||||
ModificationDate = DateHandlers.UNIXToDateTime(unicosSb.s_time),
|
||||
ModificationDateSpecified = true
|
||||
};
|
||||
xmlFSType.Dirty |= unicosSb.s_error > 0;
|
||||
XmlFsType.Dirty |= unicosSb.s_error > 0;
|
||||
}
|
||||
|
||||
public override Errno Mount()
|
||||
|
||||
@@ -48,24 +48,22 @@ namespace DiscImageChef.Filesystems
|
||||
public BFS()
|
||||
{
|
||||
Name = "UNIX Boot filesystem";
|
||||
PluginUUID = new Guid("1E6E0DA6-F7E4-494C-80C6-CB5929E96155");
|
||||
PluginUuid = new Guid("1E6E0DA6-F7E4-494C-80C6-CB5929E96155");
|
||||
CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public BFS(Encoding encoding)
|
||||
{
|
||||
Name = "UNIX Boot filesystem";
|
||||
PluginUUID = new Guid("1E6E0DA6-F7E4-494C-80C6-CB5929E96155");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("1E6E0DA6-F7E4-494C-80C6-CB5929E96155");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public BFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "UNIX Boot filesystem";
|
||||
PluginUUID = new Guid("1E6E0DA6-F7E4-494C-80C6-CB5929E96155");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("1E6E0DA6-F7E4-494C-80C6-CB5929E96155");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugin imagePlugin, Partition partition)
|
||||
@@ -85,44 +83,46 @@ namespace DiscImageChef.Filesystems
|
||||
information = "";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
byte[] bfs_sb_sector = imagePlugin.ReadSector(0 + partition.Start);
|
||||
byte[] sb_strings = new byte[6];
|
||||
byte[] bfsSbSector = imagePlugin.ReadSector(0 + partition.Start);
|
||||
byte[] sbStrings = new byte[6];
|
||||
|
||||
BFSSuperBlock bfs_sb = new BFSSuperBlock();
|
||||
BFSSuperBlock bfsSb = new BFSSuperBlock
|
||||
{
|
||||
s_magic = BitConverter.ToUInt32(bfsSbSector, 0x00),
|
||||
s_start = BitConverter.ToUInt32(bfsSbSector, 0x04),
|
||||
s_end = BitConverter.ToUInt32(bfsSbSector, 0x08),
|
||||
s_from = BitConverter.ToUInt32(bfsSbSector, 0x0C),
|
||||
s_to = BitConverter.ToUInt32(bfsSbSector, 0x10),
|
||||
s_bfrom = BitConverter.ToInt32(bfsSbSector, 0x14),
|
||||
s_bto = BitConverter.ToInt32(bfsSbSector, 0x18)
|
||||
};
|
||||
|
||||
bfs_sb.s_magic = BitConverter.ToUInt32(bfs_sb_sector, 0x00);
|
||||
bfs_sb.s_start = BitConverter.ToUInt32(bfs_sb_sector, 0x04);
|
||||
bfs_sb.s_end = BitConverter.ToUInt32(bfs_sb_sector, 0x08);
|
||||
bfs_sb.s_from = BitConverter.ToUInt32(bfs_sb_sector, 0x0C);
|
||||
bfs_sb.s_to = BitConverter.ToUInt32(bfs_sb_sector, 0x10);
|
||||
bfs_sb.s_bfrom = BitConverter.ToInt32(bfs_sb_sector, 0x14);
|
||||
bfs_sb.s_bto = BitConverter.ToInt32(bfs_sb_sector, 0x18);
|
||||
Array.Copy(bfs_sb_sector, 0x1C, sb_strings, 0, 6);
|
||||
bfs_sb.s_fsname = StringHandlers.CToString(sb_strings, CurrentEncoding);
|
||||
Array.Copy(bfs_sb_sector, 0x22, sb_strings, 0, 6);
|
||||
bfs_sb.s_volume = StringHandlers.CToString(sb_strings, CurrentEncoding);
|
||||
Array.Copy(bfsSbSector, 0x1C, sbStrings, 0, 6);
|
||||
bfsSb.s_fsname = StringHandlers.CToString(sbStrings, CurrentEncoding);
|
||||
Array.Copy(bfsSbSector, 0x22, sbStrings, 0, 6);
|
||||
bfsSb.s_volume = StringHandlers.CToString(sbStrings, CurrentEncoding);
|
||||
|
||||
DicConsole.DebugWriteLine("BFS plugin", "bfs_sb.s_magic: 0x{0:X8}", bfs_sb.s_magic);
|
||||
DicConsole.DebugWriteLine("BFS plugin", "bfs_sb.s_start: 0x{0:X8}", bfs_sb.s_start);
|
||||
DicConsole.DebugWriteLine("BFS plugin", "bfs_sb.s_end: 0x{0:X8}", bfs_sb.s_end);
|
||||
DicConsole.DebugWriteLine("BFS plugin", "bfs_sb.s_from: 0x{0:X8}", bfs_sb.s_from);
|
||||
DicConsole.DebugWriteLine("BFS plugin", "bfs_sb.s_to: 0x{0:X8}", bfs_sb.s_to);
|
||||
DicConsole.DebugWriteLine("BFS plugin", "bfs_sb.s_bfrom: 0x{0:X8}", bfs_sb.s_bfrom);
|
||||
DicConsole.DebugWriteLine("BFS plugin", "bfs_sb.s_bto: 0x{0:X8}", bfs_sb.s_bto);
|
||||
DicConsole.DebugWriteLine("BFS plugin", "bfs_sb.s_fsname: 0x{0}", bfs_sb.s_fsname);
|
||||
DicConsole.DebugWriteLine("BFS plugin", "bfs_sb.s_volume: 0x{0}", bfs_sb.s_volume);
|
||||
DicConsole.DebugWriteLine("BFS plugin", "bfs_sb.s_magic: 0x{0:X8}", bfsSb.s_magic);
|
||||
DicConsole.DebugWriteLine("BFS plugin", "bfs_sb.s_start: 0x{0:X8}", bfsSb.s_start);
|
||||
DicConsole.DebugWriteLine("BFS plugin", "bfs_sb.s_end: 0x{0:X8}", bfsSb.s_end);
|
||||
DicConsole.DebugWriteLine("BFS plugin", "bfs_sb.s_from: 0x{0:X8}", bfsSb.s_from);
|
||||
DicConsole.DebugWriteLine("BFS plugin", "bfs_sb.s_to: 0x{0:X8}", bfsSb.s_to);
|
||||
DicConsole.DebugWriteLine("BFS plugin", "bfs_sb.s_bfrom: 0x{0:X8}", bfsSb.s_bfrom);
|
||||
DicConsole.DebugWriteLine("BFS plugin", "bfs_sb.s_bto: 0x{0:X8}", bfsSb.s_bto);
|
||||
DicConsole.DebugWriteLine("BFS plugin", "bfs_sb.s_fsname: 0x{0}", bfsSb.s_fsname);
|
||||
DicConsole.DebugWriteLine("BFS plugin", "bfs_sb.s_volume: 0x{0}", bfsSb.s_volume);
|
||||
|
||||
sb.AppendLine("UNIX Boot filesystem");
|
||||
sb.AppendFormat("Volume goes from byte {0} to byte {1}, for {2} bytes", bfs_sb.s_start, bfs_sb.s_end,
|
||||
bfs_sb.s_end - bfs_sb.s_start).AppendLine();
|
||||
sb.AppendFormat("Filesystem name: {0}", bfs_sb.s_fsname).AppendLine();
|
||||
sb.AppendFormat("Volume name: {0}", bfs_sb.s_volume).AppendLine();
|
||||
sb.AppendFormat("Volume goes from byte {0} to byte {1}, for {2} bytes", bfsSb.s_start, bfsSb.s_end,
|
||||
bfsSb.s_end - bfsSb.s_start).AppendLine();
|
||||
sb.AppendFormat("Filesystem name: {0}", bfsSb.s_fsname).AppendLine();
|
||||
sb.AppendFormat("Volume name: {0}", bfsSb.s_volume).AppendLine();
|
||||
|
||||
xmlFSType = new FileSystemType();
|
||||
xmlFSType.Type = "BFS";
|
||||
xmlFSType.VolumeName = bfs_sb.s_volume;
|
||||
xmlFSType.ClusterSize = (int)imagePlugin.GetSectorSize();
|
||||
xmlFSType.Clusters = (long)(partition.End - partition.Start + 1);
|
||||
XmlFsType = new FileSystemType();
|
||||
XmlFsType.Type = "BFS";
|
||||
XmlFsType.VolumeName = bfsSb.s_volume;
|
||||
XmlFsType.ClusterSize = (int)imagePlugin.GetSectorSize();
|
||||
XmlFsType.Clusters = (long)(partition.End - partition.Start + 1);
|
||||
|
||||
information = sb.ToString();
|
||||
}
|
||||
|
||||
@@ -45,24 +45,22 @@ namespace DiscImageChef.Filesystems
|
||||
public VMfs()
|
||||
{
|
||||
Name = "VMware filesystem";
|
||||
PluginUUID = new Guid("EE52BDB8-B49C-4122-A3DA-AD21CBE79843");
|
||||
PluginUuid = new Guid("EE52BDB8-B49C-4122-A3DA-AD21CBE79843");
|
||||
CurrentEncoding = Encoding.UTF8;
|
||||
}
|
||||
|
||||
public VMfs(Encoding encoding)
|
||||
{
|
||||
Name = "VMware filesystem";
|
||||
PluginUUID = new Guid("EE52BDB8-B49C-4122-A3DA-AD21CBE79843");
|
||||
if(encoding == null) CurrentEncoding = Encoding.UTF8;
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("EE52BDB8-B49C-4122-A3DA-AD21CBE79843");
|
||||
CurrentEncoding = encoding ?? Encoding.UTF8;
|
||||
}
|
||||
|
||||
public VMfs(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "VMware filesystem";
|
||||
PluginUUID = new Guid("EE52BDB8-B49C-4122-A3DA-AD21CBE79843");
|
||||
if(encoding == null) CurrentEncoding = Encoding.UTF8;
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("EE52BDB8-B49C-4122-A3DA-AD21CBE79843");
|
||||
CurrentEncoding = encoding ?? Encoding.UTF8;
|
||||
}
|
||||
|
||||
[Flags]
|
||||
@@ -92,14 +90,14 @@ namespace DiscImageChef.Filesystems
|
||||
/// <summary>
|
||||
/// Identifier for VMfs
|
||||
/// </summary>
|
||||
const uint VMfs_MAGIC = 0xC001D00D;
|
||||
const uint VMfs_Base = 0x00100000;
|
||||
const uint VMFS_MAGIC = 0xC001D00D;
|
||||
const uint VMFS_BASE = 0x00100000;
|
||||
|
||||
public override bool Identify(ImagePlugin imagePlugin, Partition partition)
|
||||
{
|
||||
if(partition.Start >= partition.End) return false;
|
||||
|
||||
ulong vmfsSuperOff = VMfs_Base / imagePlugin.ImageInfo.SectorSize;
|
||||
ulong vmfsSuperOff = VMFS_BASE / imagePlugin.ImageInfo.SectorSize;
|
||||
|
||||
if(partition.Start + vmfsSuperOff > partition.End) return false;
|
||||
|
||||
@@ -107,13 +105,13 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
uint magic = BitConverter.ToUInt32(sector, 0x00);
|
||||
|
||||
return magic == VMfs_MAGIC;
|
||||
return magic == VMFS_MAGIC;
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
|
||||
out string information)
|
||||
{
|
||||
ulong vmfsSuperOff = VMfs_Base / imagePlugin.ImageInfo.SectorSize;
|
||||
ulong vmfsSuperOff = VMFS_BASE / imagePlugin.ImageInfo.SectorSize;
|
||||
byte[] sector = imagePlugin.ReadSector(partition.Start + vmfsSuperOff);
|
||||
|
||||
VolumeInfo volInfo = new VolumeInfo();
|
||||
@@ -144,15 +142,17 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
information = sbInformation.ToString();
|
||||
|
||||
xmlFSType = new FileSystemType();
|
||||
xmlFSType.Type = "VMware file system";
|
||||
xmlFSType.CreationDate = DateHandlers.UNIXUnsignedToDateTime(ctimeSecs, ctimeNanoSecs);
|
||||
xmlFSType.CreationDateSpecified = true;
|
||||
xmlFSType.ModificationDate = DateHandlers.UNIXUnsignedToDateTime(mtimeSecs, mtimeNanoSecs);
|
||||
xmlFSType.ModificationDateSpecified = true;
|
||||
xmlFSType.Clusters = volInfo.size * 256 / imagePlugin.ImageInfo.SectorSize;
|
||||
xmlFSType.ClusterSize = (int)imagePlugin.ImageInfo.SectorSize;
|
||||
xmlFSType.VolumeSerial = volInfo.uuid.ToString();
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
Type = "VMware file system",
|
||||
CreationDate = DateHandlers.UNIXUnsignedToDateTime(ctimeSecs, ctimeNanoSecs),
|
||||
CreationDateSpecified = true,
|
||||
ModificationDate = DateHandlers.UNIXUnsignedToDateTime(mtimeSecs, mtimeNanoSecs),
|
||||
ModificationDateSpecified = true,
|
||||
Clusters = volInfo.size * 256 / imagePlugin.ImageInfo.SectorSize,
|
||||
ClusterSize = (int)imagePlugin.ImageInfo.SectorSize,
|
||||
VolumeSerial = volInfo.uuid.ToString()
|
||||
};
|
||||
}
|
||||
|
||||
public override Errno Mount()
|
||||
|
||||
@@ -45,24 +45,22 @@ namespace DiscImageChef.Filesystems
|
||||
public VxFS()
|
||||
{
|
||||
Name = "Veritas filesystem";
|
||||
PluginUUID = new Guid("EC372605-7687-453C-8BEA-7E0DFF79CB03");
|
||||
PluginUuid = new Guid("EC372605-7687-453C-8BEA-7E0DFF79CB03");
|
||||
CurrentEncoding = Encoding.UTF8;
|
||||
}
|
||||
|
||||
public VxFS(Encoding encoding)
|
||||
{
|
||||
Name = "Veritas filesystem";
|
||||
PluginUUID = new Guid("EC372605-7687-453C-8BEA-7E0DFF79CB03");
|
||||
if(encoding == null) CurrentEncoding = Encoding.UTF8;
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("EC372605-7687-453C-8BEA-7E0DFF79CB03");
|
||||
CurrentEncoding = encoding ?? Encoding.UTF8;
|
||||
}
|
||||
|
||||
public VxFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "Veritas filesystem";
|
||||
PluginUUID = new Guid("EC372605-7687-453C-8BEA-7E0DFF79CB03");
|
||||
if(encoding == null) CurrentEncoding = Encoding.UTF8;
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("EC372605-7687-453C-8BEA-7E0DFF79CB03");
|
||||
CurrentEncoding = encoding ?? Encoding.UTF8;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
@@ -211,12 +209,12 @@ namespace DiscImageChef.Filesystems
|
||||
/// <summary>
|
||||
/// Identifier for VxFS
|
||||
/// </summary>
|
||||
const uint VxFS_MAGIC = 0xA501FCF5;
|
||||
const uint VxFS_Base = 0x400;
|
||||
const uint VXFS_MAGIC = 0xA501FCF5;
|
||||
const uint VXFS_Base = 0x400;
|
||||
|
||||
public override bool Identify(ImagePlugin imagePlugin, Partition partition)
|
||||
{
|
||||
ulong vmfsSuperOff = VxFS_Base / imagePlugin.ImageInfo.SectorSize;
|
||||
ulong vmfsSuperOff = VXFS_Base / imagePlugin.ImageInfo.SectorSize;
|
||||
|
||||
if(partition.Start + vmfsSuperOff >= partition.End) return false;
|
||||
|
||||
@@ -224,13 +222,13 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
uint magic = BitConverter.ToUInt32(sector, 0x00);
|
||||
|
||||
return magic == VxFS_MAGIC;
|
||||
return magic == VXFS_MAGIC;
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
|
||||
out string information)
|
||||
{
|
||||
ulong vmfsSuperOff = VxFS_Base / imagePlugin.ImageInfo.SectorSize;
|
||||
ulong vmfsSuperOff = VXFS_Base / imagePlugin.ImageInfo.SectorSize;
|
||||
byte[] sector = imagePlugin.ReadSector(partition.Start + vmfsSuperOff);
|
||||
|
||||
VxSuperBlock vxSb = new VxSuperBlock();
|
||||
@@ -259,17 +257,19 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
information = sbInformation.ToString();
|
||||
|
||||
xmlFSType = new FileSystemType();
|
||||
xmlFSType.Type = "Veritas file system";
|
||||
xmlFSType.CreationDate = DateHandlers.UNIXUnsignedToDateTime(vxSb.vs_ctime, vxSb.vs_cutime);
|
||||
xmlFSType.CreationDateSpecified = true;
|
||||
xmlFSType.ModificationDate = DateHandlers.UNIXUnsignedToDateTime(vxSb.vs_wtime, vxSb.vs_wutime);
|
||||
xmlFSType.ModificationDateSpecified = true;
|
||||
xmlFSType.Clusters = vxSb.vs_size;
|
||||
xmlFSType.ClusterSize = vxSb.vs_bsize;
|
||||
xmlFSType.Dirty = vxSb.vs_clean != 0;
|
||||
xmlFSType.FreeClusters = vxSb.vs_free;
|
||||
xmlFSType.FreeClustersSpecified = true;
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
Type = "Veritas file system",
|
||||
CreationDate = DateHandlers.UNIXUnsignedToDateTime(vxSb.vs_ctime, vxSb.vs_cutime),
|
||||
CreationDateSpecified = true,
|
||||
ModificationDate = DateHandlers.UNIXUnsignedToDateTime(vxSb.vs_wtime, vxSb.vs_wutime),
|
||||
ModificationDateSpecified = true,
|
||||
Clusters = vxSb.vs_size,
|
||||
ClusterSize = vxSb.vs_bsize,
|
||||
Dirty = vxSb.vs_clean != 0,
|
||||
FreeClusters = vxSb.vs_free,
|
||||
FreeClustersSpecified = true
|
||||
};
|
||||
}
|
||||
|
||||
public override Errno Mount()
|
||||
|
||||
@@ -104,29 +104,27 @@ namespace DiscImageChef.Filesystems
|
||||
public Guid meta_uuid;
|
||||
}
|
||||
|
||||
const uint XFS_Magic = 0x58465342;
|
||||
const uint XFS_MAGIC = 0x58465342;
|
||||
|
||||
public XFS()
|
||||
{
|
||||
Name = "XFS Filesystem Plugin";
|
||||
PluginUUID = new Guid("1D8CD8B8-27E6-410F-9973-D16409225FBA");
|
||||
PluginUuid = new Guid("1D8CD8B8-27E6-410F-9973-D16409225FBA");
|
||||
CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public XFS(Encoding encoding)
|
||||
{
|
||||
Name = "XFS Filesystem Plugin";
|
||||
PluginUUID = new Guid("1D8CD8B8-27E6-410F-9973-D16409225FBA");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("1D8CD8B8-27E6-410F-9973-D16409225FBA");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public XFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "XFS Filesystem Plugin";
|
||||
PluginUUID = new Guid("1D8CD8B8-27E6-410F-9973-D16409225FBA");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("1D8CD8B8-27E6-410F-9973-D16409225FBA");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugin imagePlugin, Partition partition)
|
||||
@@ -153,9 +151,9 @@ namespace DiscImageChef.Filesystems
|
||||
xfsSb = BigEndianMarshal.ByteArrayToStructureBigEndian<XFS_Superblock>(sbpiece);
|
||||
|
||||
DicConsole.DebugWriteLine("XFS plugin", "magic at 0x{0:X3} = 0x{1:X8} (expected 0x{2:X8})",
|
||||
location, xfsSb.magicnum, XFS_Magic);
|
||||
location, xfsSb.magicnum, XFS_MAGIC);
|
||||
|
||||
if(xfsSb.magicnum == XFS_Magic) return true;
|
||||
if(xfsSb.magicnum == XFS_MAGIC) return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -172,9 +170,9 @@ namespace DiscImageChef.Filesystems
|
||||
xfsSb = BigEndianMarshal.ByteArrayToStructureBigEndian<XFS_Superblock>(sector);
|
||||
|
||||
DicConsole.DebugWriteLine("XFS plugin", "magic at {0} = 0x{1:X8} (expected 0x{2:X8})", location,
|
||||
xfsSb.magicnum, XFS_Magic);
|
||||
xfsSb.magicnum, XFS_MAGIC);
|
||||
|
||||
if(xfsSb.magicnum == XFS_Magic) return true;
|
||||
if(xfsSb.magicnum == XFS_MAGIC) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -206,9 +204,9 @@ namespace DiscImageChef.Filesystems
|
||||
xfsSb = BigEndianMarshal.ByteArrayToStructureBigEndian<XFS_Superblock>(sbpiece);
|
||||
|
||||
DicConsole.DebugWriteLine("XFS plugin", "magic at 0x{0:X3} = 0x{1:X8} (expected 0x{2:X8})",
|
||||
location, xfsSb.magicnum, XFS_Magic);
|
||||
location, xfsSb.magicnum, XFS_MAGIC);
|
||||
|
||||
if(xfsSb.magicnum == XFS_Magic) break;
|
||||
if(xfsSb.magicnum == XFS_MAGIC) break;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -223,12 +221,12 @@ namespace DiscImageChef.Filesystems
|
||||
xfsSb = BigEndianMarshal.ByteArrayToStructureBigEndian<XFS_Superblock>(sector);
|
||||
|
||||
DicConsole.DebugWriteLine("XFS plugin", "magic at {0} = 0x{1:X8} (expected 0x{2:X8})", location,
|
||||
xfsSb.magicnum, XFS_Magic);
|
||||
xfsSb.magicnum, XFS_MAGIC);
|
||||
|
||||
if(xfsSb.magicnum == XFS_Magic) break;
|
||||
if(xfsSb.magicnum == XFS_MAGIC) break;
|
||||
}
|
||||
|
||||
if(xfsSb.magicnum != XFS_Magic) return;
|
||||
if(xfsSb.magicnum != XFS_MAGIC) return;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
@@ -247,17 +245,19 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
information = sb.ToString();
|
||||
|
||||
xmlFSType = new FileSystemType();
|
||||
xmlFSType.Type = "XFS filesystem";
|
||||
xmlFSType.ClusterSize = (int)xfsSb.blocksize;
|
||||
xmlFSType.Clusters = (long)xfsSb.dblocks;
|
||||
xmlFSType.FreeClusters = (long)xfsSb.fdblocks;
|
||||
xmlFSType.FreeClustersSpecified = true;
|
||||
xmlFSType.Files = (long)(xfsSb.icount - xfsSb.ifree);
|
||||
xmlFSType.FilesSpecified = true;
|
||||
xmlFSType.Dirty |= xfsSb.inprogress > 0;
|
||||
xmlFSType.VolumeName = StringHandlers.CToString(xfsSb.fname, CurrentEncoding);
|
||||
xmlFSType.VolumeSerial = xfsSb.uuid.ToString();
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
Type = "XFS filesystem",
|
||||
ClusterSize = (int)xfsSb.blocksize,
|
||||
Clusters = (long)xfsSb.dblocks,
|
||||
FreeClusters = (long)xfsSb.fdblocks,
|
||||
FreeClustersSpecified = true,
|
||||
Files = (long)(xfsSb.icount - xfsSb.ifree),
|
||||
FilesSpecified = true,
|
||||
Dirty = xfsSb.inprogress > 0,
|
||||
VolumeName = StringHandlers.CToString(xfsSb.fname, CurrentEncoding),
|
||||
VolumeSerial = xfsSb.uuid.ToString()
|
||||
};
|
||||
}
|
||||
|
||||
public override Errno Mount()
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using DiscImageChef.CommonTypes;
|
||||
@@ -59,10 +60,11 @@ namespace DiscImageChef.Filesystems
|
||||
* It can also be encoded little or big endian.
|
||||
* Because of this variations, ZFS stored a header indicating the used encoding and endianess before the encoded nvlist.
|
||||
*/
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
public class ZFS : Filesystem
|
||||
{
|
||||
const ulong ZEC_Magic = 0x0210DA7AB10C7A11;
|
||||
const ulong ZEC_Cigam = 0x117A0CB17ADA1002;
|
||||
const ulong ZEC_MAGIC = 0x0210DA7AB10C7A11;
|
||||
const ulong ZEC_CIGAM = 0x117A0CB17ADA1002;
|
||||
|
||||
struct ZIO_Checksum
|
||||
{
|
||||
@@ -81,9 +83,9 @@ namespace DiscImageChef.Filesystems
|
||||
}
|
||||
|
||||
// These parameters define how the nvlist is stored
|
||||
const byte NVS_LittleEndian = 1;
|
||||
const byte NVS_BigEndian = 0;
|
||||
const byte NVS_Native = 0;
|
||||
const byte NVS_LITTLE_ENDIAN = 1;
|
||||
const byte NVS_BIG_ENDIAN = 0;
|
||||
const byte NVS_NATIVE = 0;
|
||||
const byte NVS_XDR = 1;
|
||||
|
||||
/// <summary>
|
||||
@@ -173,7 +175,7 @@ namespace DiscImageChef.Filesystems
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct DVA
|
||||
struct DVA
|
||||
{
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public ulong[] word;
|
||||
}
|
||||
@@ -208,7 +210,7 @@ namespace DiscImageChef.Filesystems
|
||||
public ZIO_Checksum checksum;
|
||||
}
|
||||
|
||||
const ulong Uberblock_Magic = 0x00BAB10C;
|
||||
const ulong UBERBLOCK_MAGIC = 0x00BAB10C;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
struct ZFS_Uberblock
|
||||
@@ -222,19 +224,19 @@ namespace DiscImageChef.Filesystems
|
||||
public ulong softwareVersion;
|
||||
}
|
||||
|
||||
const uint ZFS_Magic = 0x58465342;
|
||||
const uint ZFS_MAGIC = 0x58465342;
|
||||
|
||||
public ZFS()
|
||||
{
|
||||
Name = "ZFS Filesystem Plugin";
|
||||
PluginUUID = new Guid("0750014F-A714-4692-A369-E23F6EC3659C");
|
||||
PluginUuid = new Guid("0750014F-A714-4692-A369-E23F6EC3659C");
|
||||
CurrentEncoding = Encoding.UTF8;
|
||||
}
|
||||
|
||||
public ZFS(Encoding encoding)
|
||||
{
|
||||
Name = "ZFS Filesystem Plugin";
|
||||
PluginUUID = new Guid("0750014F-A714-4692-A369-E23F6EC3659C");
|
||||
PluginUuid = new Guid("0750014F-A714-4692-A369-E23F6EC3659C");
|
||||
// ZFS is always UTF-8
|
||||
CurrentEncoding = Encoding.UTF8;
|
||||
}
|
||||
@@ -242,7 +244,7 @@ namespace DiscImageChef.Filesystems
|
||||
public ZFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "ZFS Filesystem Plugin";
|
||||
PluginUUID = new Guid("0750014F-A714-4692-A369-E23F6EC3659C");
|
||||
PluginUuid = new Guid("0750014F-A714-4692-A369-E23F6EC3659C");
|
||||
// ZFS is always UTF-8
|
||||
CurrentEncoding = Encoding.UTF8;
|
||||
}
|
||||
@@ -258,16 +260,14 @@ namespace DiscImageChef.Filesystems
|
||||
{
|
||||
sector = imagePlugin.ReadSector(partition.Start + 31);
|
||||
magic = BitConverter.ToUInt64(sector, 0x1D8);
|
||||
if(magic == ZEC_Magic || magic == ZEC_Cigam) return true;
|
||||
if(magic == ZEC_MAGIC || magic == ZEC_CIGAM) return true;
|
||||
}
|
||||
|
||||
if(partition.Start + 16 >= partition.End) return false;
|
||||
|
||||
sector = imagePlugin.ReadSector(partition.Start + 16);
|
||||
magic = BitConverter.ToUInt64(sector, 0x1D8);
|
||||
if(magic == ZEC_Magic || magic == ZEC_Cigam) return true;
|
||||
|
||||
return false;
|
||||
return magic == ZEC_MAGIC || magic == ZEC_CIGAM;
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
|
||||
@@ -281,42 +281,38 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
ulong nvlistOff = 32;
|
||||
uint nvlistLen = 114688 / imagePlugin.ImageInfo.SectorSize;
|
||||
byte[] nvlist;
|
||||
|
||||
if(partition.Start + 31 < partition.End)
|
||||
{
|
||||
sector = imagePlugin.ReadSector(partition.Start + 31);
|
||||
magic = BitConverter.ToUInt64(sector, 0x1D8);
|
||||
if(magic == ZEC_Magic || magic == ZEC_Cigam) nvlistOff = 32;
|
||||
if(magic == ZEC_MAGIC || magic == ZEC_CIGAM) nvlistOff = 32;
|
||||
}
|
||||
|
||||
if(partition.Start + 16 < partition.End)
|
||||
{
|
||||
sector = imagePlugin.ReadSector(partition.Start + 16);
|
||||
magic = BitConverter.ToUInt64(sector, 0x1D8);
|
||||
if(magic == ZEC_Magic || magic == ZEC_Cigam) nvlistOff = 17;
|
||||
if(magic == ZEC_MAGIC || magic == ZEC_CIGAM) nvlistOff = 17;
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.AppendLine("ZFS filesystem");
|
||||
|
||||
nvlist = imagePlugin.ReadSectors(partition.Start + nvlistOff, nvlistLen);
|
||||
Dictionary<string, NVS_Item> decodedNvList;
|
||||
byte[] nvlist = imagePlugin.ReadSectors(partition.Start + nvlistOff, nvlistLen);
|
||||
|
||||
if(!DecodeNvList(nvlist, out decodedNvList)) sb.AppendLine("Could not decode nvlist");
|
||||
else sb.AppendLine(PrintNvList(decodedNvList));
|
||||
sb.AppendLine(!DecodeNvList(nvlist, out Dictionary<string, NVS_Item> decodedNvList)
|
||||
? "Could not decode nvlist"
|
||||
: PrintNvList(decodedNvList));
|
||||
|
||||
information = sb.ToString();
|
||||
|
||||
NVS_Item tmpObj;
|
||||
|
||||
xmlFSType = new FileSystemType();
|
||||
xmlFSType.Type = "ZFS filesystem";
|
||||
if(decodedNvList.TryGetValue("name", out tmpObj)) xmlFSType.VolumeName = (string)tmpObj.value;
|
||||
XmlFsType = new FileSystemType {Type = "ZFS filesystem"};
|
||||
if(decodedNvList.TryGetValue("name", out NVS_Item tmpObj)) XmlFsType.VolumeName = (string)tmpObj.value;
|
||||
if(decodedNvList.TryGetValue("guid", out tmpObj))
|
||||
xmlFSType.VolumeSerial = $"{(ulong)tmpObj.value}";
|
||||
XmlFsType.VolumeSerial = $"{(ulong)tmpObj.value}";
|
||||
if(decodedNvList.TryGetValue("pool_guid", out tmpObj))
|
||||
xmlFSType.VolumeSetIdentifier = $"{(ulong)tmpObj.value}";
|
||||
XmlFsType.VolumeSetIdentifier = $"{(ulong)tmpObj.value}";
|
||||
}
|
||||
|
||||
static bool DecodeNvList(byte[] nvlist, out Dictionary<string, NVS_Item> decodedNvList)
|
||||
@@ -346,7 +342,6 @@ namespace DiscImageChef.Filesystems
|
||||
while(offset < nvlist.Length)
|
||||
{
|
||||
uint nameLength;
|
||||
byte[] nameBytes;
|
||||
NVS_Item item = new NVS_Item();
|
||||
int currOff = offset;
|
||||
|
||||
@@ -361,7 +356,7 @@ namespace DiscImageChef.Filesystems
|
||||
nameLength = BigEndianBitConverter.ToUInt32(nvlist, offset);
|
||||
offset += 4;
|
||||
if(nameLength % 4 > 0) nameLength += 4 - nameLength % 4;
|
||||
nameBytes = new byte[nameLength];
|
||||
byte[] nameBytes = new byte[nameLength];
|
||||
Array.Copy(nvlist, offset, nameBytes, 0, nameLength);
|
||||
item.name = StringHandlers.CToString(nameBytes);
|
||||
offset += (int)nameLength;
|
||||
@@ -644,8 +639,7 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
byte[] subListBytes = new byte[item.encodedSize - (offset - currOff)];
|
||||
Array.Copy(nvlist, offset, subListBytes, 0, subListBytes.Length);
|
||||
Dictionary<string, NVS_Item> subList;
|
||||
if(DecodeNvList(subListBytes, out subList, true, littleEndian)) item.value = subList;
|
||||
if(DecodeNvList(subListBytes, out Dictionary<string, NVS_Item> subList, true, littleEndian)) item.value = subList;
|
||||
else goto default;
|
||||
offset = (int)(currOff + item.encodedSize);
|
||||
break;
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using DiscImageChef.CommonTypes;
|
||||
@@ -42,6 +43,7 @@ using ufs_daddr_t = System.Int32;
|
||||
|
||||
namespace DiscImageChef.Filesystems
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
public class dump : Filesystem
|
||||
{
|
||||
/// <summary>Magic number for old dump</summary>
|
||||
@@ -211,24 +213,22 @@ namespace DiscImageChef.Filesystems
|
||||
public dump()
|
||||
{
|
||||
Name = "dump(8) Plugin";
|
||||
PluginUUID = new Guid("E53B4D28-C858-4800-B092-DDAE80D361B9");
|
||||
PluginUuid = new Guid("E53B4D28-C858-4800-B092-DDAE80D361B9");
|
||||
CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public dump(Encoding encoding)
|
||||
{
|
||||
Name = "dump(8) Plugin";
|
||||
PluginUUID = new Guid("E53B4D28-C858-4800-B092-DDAE80D361B9");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("E53B4D28-C858-4800-B092-DDAE80D361B9");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public dump(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "dump(8) Plugin";
|
||||
PluginUUID = new Guid("E53B4D28-C858-4800-B092-DDAE80D361B9");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("E53B4D28-C858-4800-B092-DDAE80D361B9");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugin imagePlugin, Partition partition)
|
||||
@@ -307,13 +307,10 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
bool useOld = false;
|
||||
bool useAix = false;
|
||||
bool useNew = false;
|
||||
|
||||
if(newHdr.c_magic == OFS_MAGIC || newHdr.c_magic == NFS_MAGIC || newHdr.c_magic == OFS_CIGAM ||
|
||||
newHdr.c_magic == NFS_CIGAM || newHdr.c_magic == UFS2_MAGIC || newHdr.c_magic == UFS2_CIGAM)
|
||||
{
|
||||
useNew = true;
|
||||
|
||||
if(newHdr.c_magic == OFS_CIGAM || newHdr.c_magic == NFS_CIGAM || newHdr.c_magic == UFS2_CIGAM)
|
||||
newHdr = BigEndianMarshal.ByteArrayToStructureBigEndian<s_spcl>(sector);
|
||||
}
|
||||
@@ -340,71 +337,71 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
xmlFSType = new FileSystemType {ClusterSize = 1024, Clusters = (long)(partition.Size / 1024)};
|
||||
XmlFsType = new FileSystemType {ClusterSize = 1024, Clusters = (long)(partition.Size / 1024)};
|
||||
|
||||
if(useOld)
|
||||
{
|
||||
xmlFSType.Type = "Old 16-bit dump(8)";
|
||||
sb.AppendLine(xmlFSType.Type);
|
||||
XmlFsType.Type = "Old 16-bit dump(8)";
|
||||
sb.AppendLine(XmlFsType.Type);
|
||||
if(oldHdr.c_date > 0)
|
||||
{
|
||||
xmlFSType.CreationDate = DateHandlers.UNIXToDateTime(oldHdr.c_date);
|
||||
xmlFSType.CreationDateSpecified = true;
|
||||
sb.AppendFormat("Dump created on {0}", xmlFSType.CreationDate).AppendLine();
|
||||
XmlFsType.CreationDate = DateHandlers.UNIXToDateTime(oldHdr.c_date);
|
||||
XmlFsType.CreationDateSpecified = true;
|
||||
sb.AppendFormat("Dump created on {0}", XmlFsType.CreationDate).AppendLine();
|
||||
}
|
||||
if(oldHdr.c_ddate > 0)
|
||||
{
|
||||
xmlFSType.BackupDate = DateHandlers.UNIXToDateTime(oldHdr.c_ddate);
|
||||
xmlFSType.BackupDateSpecified = true;
|
||||
sb.AppendFormat("Previous dump created on {0}", xmlFSType.BackupDate).AppendLine();
|
||||
XmlFsType.BackupDate = DateHandlers.UNIXToDateTime(oldHdr.c_ddate);
|
||||
XmlFsType.BackupDateSpecified = true;
|
||||
sb.AppendFormat("Previous dump created on {0}", XmlFsType.BackupDate).AppendLine();
|
||||
}
|
||||
sb.AppendFormat("Dump volume number: {0}", oldHdr.c_volume).AppendLine();
|
||||
}
|
||||
else if(useAix)
|
||||
{
|
||||
xmlFSType.Type = "AIX dump(8)";
|
||||
sb.AppendLine(xmlFSType.Type);
|
||||
XmlFsType.Type = "AIX dump(8)";
|
||||
sb.AppendLine(XmlFsType.Type);
|
||||
if(aixHdr.c_date > 0)
|
||||
{
|
||||
xmlFSType.CreationDate = DateHandlers.UNIXToDateTime(aixHdr.c_date);
|
||||
xmlFSType.CreationDateSpecified = true;
|
||||
sb.AppendFormat("Dump created on {0}", xmlFSType.CreationDate).AppendLine();
|
||||
XmlFsType.CreationDate = DateHandlers.UNIXToDateTime(aixHdr.c_date);
|
||||
XmlFsType.CreationDateSpecified = true;
|
||||
sb.AppendFormat("Dump created on {0}", XmlFsType.CreationDate).AppendLine();
|
||||
}
|
||||
if(aixHdr.c_ddate > 0)
|
||||
{
|
||||
xmlFSType.BackupDate = DateHandlers.UNIXToDateTime(aixHdr.c_ddate);
|
||||
xmlFSType.BackupDateSpecified = true;
|
||||
sb.AppendFormat("Previous dump created on {0}", xmlFSType.BackupDate).AppendLine();
|
||||
XmlFsType.BackupDate = DateHandlers.UNIXToDateTime(aixHdr.c_ddate);
|
||||
XmlFsType.BackupDateSpecified = true;
|
||||
sb.AppendFormat("Previous dump created on {0}", XmlFsType.BackupDate).AppendLine();
|
||||
}
|
||||
sb.AppendFormat("Dump volume number: {0}", aixHdr.c_volume).AppendLine();
|
||||
}
|
||||
else
|
||||
{
|
||||
xmlFSType.Type = "dump(8)";
|
||||
sb.AppendLine(xmlFSType.Type);
|
||||
XmlFsType.Type = "dump(8)";
|
||||
sb.AppendLine(XmlFsType.Type);
|
||||
if(newHdr.c_ndate > 0)
|
||||
{
|
||||
xmlFSType.CreationDate = DateHandlers.UNIXToDateTime(newHdr.c_ndate);
|
||||
xmlFSType.CreationDateSpecified = true;
|
||||
sb.AppendFormat("Dump created on {0}", xmlFSType.CreationDate).AppendLine();
|
||||
XmlFsType.CreationDate = DateHandlers.UNIXToDateTime(newHdr.c_ndate);
|
||||
XmlFsType.CreationDateSpecified = true;
|
||||
sb.AppendFormat("Dump created on {0}", XmlFsType.CreationDate).AppendLine();
|
||||
}
|
||||
else if(newHdr.c_date > 0)
|
||||
{
|
||||
xmlFSType.CreationDate = DateHandlers.UNIXToDateTime(newHdr.c_date);
|
||||
xmlFSType.CreationDateSpecified = true;
|
||||
sb.AppendFormat("Dump created on {0}", xmlFSType.CreationDate).AppendLine();
|
||||
XmlFsType.CreationDate = DateHandlers.UNIXToDateTime(newHdr.c_date);
|
||||
XmlFsType.CreationDateSpecified = true;
|
||||
sb.AppendFormat("Dump created on {0}", XmlFsType.CreationDate).AppendLine();
|
||||
}
|
||||
if(newHdr.c_nddate > 0)
|
||||
{
|
||||
xmlFSType.BackupDate = DateHandlers.UNIXToDateTime(newHdr.c_nddate);
|
||||
xmlFSType.BackupDateSpecified = true;
|
||||
sb.AppendFormat("Previous dump created on {0}", xmlFSType.BackupDate).AppendLine();
|
||||
XmlFsType.BackupDate = DateHandlers.UNIXToDateTime(newHdr.c_nddate);
|
||||
XmlFsType.BackupDateSpecified = true;
|
||||
sb.AppendFormat("Previous dump created on {0}", XmlFsType.BackupDate).AppendLine();
|
||||
}
|
||||
else if(newHdr.c_ddate > 0)
|
||||
{
|
||||
xmlFSType.BackupDate = DateHandlers.UNIXToDateTime(newHdr.c_ddate);
|
||||
xmlFSType.BackupDateSpecified = true;
|
||||
sb.AppendFormat("Previous dump created on {0}", xmlFSType.BackupDate).AppendLine();
|
||||
XmlFsType.BackupDate = DateHandlers.UNIXToDateTime(newHdr.c_ddate);
|
||||
XmlFsType.BackupDateSpecified = true;
|
||||
sb.AppendFormat("Previous dump created on {0}", XmlFsType.BackupDate).AppendLine();
|
||||
}
|
||||
sb.AppendFormat("Dump volume number: {0}", newHdr.c_volume).AppendLine();
|
||||
sb.AppendFormat("Dump level: {0}", newHdr.c_level).AppendLine();
|
||||
|
||||
@@ -47,24 +47,22 @@ namespace DiscImageChef.Filesystems
|
||||
public exFAT()
|
||||
{
|
||||
Name = "Microsoft Extended File Allocation Table";
|
||||
PluginUUID = new Guid("8271D088-1533-4CB3-AC28-D802B68BB95C");
|
||||
PluginUuid = new Guid("8271D088-1533-4CB3-AC28-D802B68BB95C");
|
||||
CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public exFAT(Encoding encoding)
|
||||
{
|
||||
Name = "Microsoft Extended File Allocation Table";
|
||||
PluginUUID = new Guid("8271D088-1533-4CB3-AC28-D802B68BB95C");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("8271D088-1533-4CB3-AC28-D802B68BB95C");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public exFAT(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "Microsoft Extended File Allocation Table";
|
||||
PluginUUID = new Guid("8271D088-1533-4CB3-AC28-D802B68BB95C");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("8271D088-1533-4CB3-AC28-D802B68BB95C");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugin imagePlugin, Partition partition)
|
||||
@@ -74,10 +72,9 @@ namespace DiscImageChef.Filesystems
|
||||
byte[] vbrSector = imagePlugin.ReadSector(0 + partition.Start);
|
||||
if(vbrSector.Length < 512) return false;
|
||||
|
||||
VolumeBootRecord vbr;
|
||||
IntPtr vbrPtr = Marshal.AllocHGlobal(512);
|
||||
Marshal.Copy(vbrSector, 0, vbrPtr, 512);
|
||||
vbr = (VolumeBootRecord)Marshal.PtrToStructure(vbrPtr, typeof(VolumeBootRecord));
|
||||
VolumeBootRecord vbr = (VolumeBootRecord)Marshal.PtrToStructure(vbrPtr, typeof(VolumeBootRecord));
|
||||
Marshal.FreeHGlobal(vbrPtr);
|
||||
|
||||
return Signature.SequenceEqual(vbr.signature);
|
||||
@@ -88,27 +85,24 @@ namespace DiscImageChef.Filesystems
|
||||
information = "";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
xmlFSType = new FileSystemType();
|
||||
XmlFsType = new FileSystemType();
|
||||
|
||||
byte[] vbrSector = imagePlugin.ReadSector(0 + partition.Start);
|
||||
VolumeBootRecord vbr;
|
||||
IntPtr vbrPtr = Marshal.AllocHGlobal(512);
|
||||
Marshal.Copy(vbrSector, 0, vbrPtr, 512);
|
||||
vbr = (VolumeBootRecord)Marshal.PtrToStructure(vbrPtr, typeof(VolumeBootRecord));
|
||||
VolumeBootRecord vbr = (VolumeBootRecord)Marshal.PtrToStructure(vbrPtr, typeof(VolumeBootRecord));
|
||||
Marshal.FreeHGlobal(vbrPtr);
|
||||
|
||||
byte[] parametersSector = imagePlugin.ReadSector(9 + partition.Start);
|
||||
OemParameterTable parametersTable;
|
||||
IntPtr parametersPtr = Marshal.AllocHGlobal(512);
|
||||
Marshal.Copy(parametersSector, 0, parametersPtr, 512);
|
||||
parametersTable = (OemParameterTable)Marshal.PtrToStructure(parametersPtr, typeof(OemParameterTable));
|
||||
OemParameterTable parametersTable = (OemParameterTable)Marshal.PtrToStructure(parametersPtr, typeof(OemParameterTable));
|
||||
Marshal.FreeHGlobal(parametersPtr);
|
||||
|
||||
byte[] chkSector = imagePlugin.ReadSector(11 + partition.Start);
|
||||
ChecksumSector chksector;
|
||||
IntPtr chkPtr = Marshal.AllocHGlobal(512);
|
||||
Marshal.Copy(chkSector, 0, chkPtr, 512);
|
||||
chksector = (ChecksumSector)Marshal.PtrToStructure(chkPtr, typeof(ChecksumSector));
|
||||
ChecksumSector chksector = (ChecksumSector)Marshal.PtrToStructure(chkPtr, typeof(ChecksumSector));
|
||||
Marshal.FreeHGlobal(chkPtr);
|
||||
|
||||
sb.AppendLine("Microsoft exFAT");
|
||||
@@ -152,11 +146,11 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
sb.AppendFormat("Checksum 0x{0:X8}", chksector.checksum[0]).AppendLine();
|
||||
|
||||
xmlFSType.ClusterSize = (1 << vbr.sectorShift) * (1 << vbr.clusterShift);
|
||||
xmlFSType.Clusters = vbr.clusterHeapLength;
|
||||
xmlFSType.Dirty = vbr.flags.HasFlag(VolumeFlags.VolumeDirty);
|
||||
xmlFSType.Type = "exFAT";
|
||||
xmlFSType.VolumeSerial = $"{vbr.volumeSerial:X8}";
|
||||
XmlFsType.ClusterSize = (1 << vbr.sectorShift) * (1 << vbr.clusterShift);
|
||||
XmlFsType.Clusters = vbr.clusterHeapLength;
|
||||
XmlFsType.Dirty = vbr.flags.HasFlag(VolumeFlags.VolumeDirty);
|
||||
XmlFsType.Type = "exFAT";
|
||||
XmlFsType.VolumeSerial = $"{vbr.volumeSerial:X8}";
|
||||
|
||||
information = sb.ToString();
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using DiscImageChef.CommonTypes;
|
||||
@@ -43,51 +44,47 @@ namespace DiscImageChef.Filesystems
|
||||
// Information from the Linux kernel
|
||||
public class ext2FS : Filesystem
|
||||
{
|
||||
const int sbPos = 0x400;
|
||||
const int SB_POS = 0x400;
|
||||
|
||||
public ext2FS()
|
||||
{
|
||||
Name = "Linux extended Filesystem 2, 3 and 4";
|
||||
PluginUUID = new Guid("6AA91B88-150B-4A7B-AD56-F84FB2DF4184");
|
||||
PluginUuid = new Guid("6AA91B88-150B-4A7B-AD56-F84FB2DF4184");
|
||||
CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public ext2FS(Encoding encoding)
|
||||
{
|
||||
Name = "Linux extended Filesystem 2, 3 and 4";
|
||||
PluginUUID = new Guid("6AA91B88-150B-4A7B-AD56-F84FB2DF4184");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("6AA91B88-150B-4A7B-AD56-F84FB2DF4184");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public ext2FS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "Linux extended Filesystem 2, 3 and 4";
|
||||
PluginUUID = new Guid("6AA91B88-150B-4A7B-AD56-F84FB2DF4184");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("6AA91B88-150B-4A7B-AD56-F84FB2DF4184");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugin imagePlugin, Partition partition)
|
||||
{
|
||||
ulong sbSector = sbPos / imagePlugin.GetSectorSize();
|
||||
uint sbOff = sbPos % imagePlugin.GetSectorSize();
|
||||
ulong sbSectorOff = SB_POS / imagePlugin.GetSectorSize();
|
||||
uint sbOff = SB_POS % imagePlugin.GetSectorSize();
|
||||
|
||||
if(sbSector + partition.Start >= partition.End) return false;
|
||||
if(sbSectorOff + partition.Start >= partition.End) return false;
|
||||
|
||||
int sb_size_in_bytes = Marshal.SizeOf(typeof(ext2FSSuperBlock));
|
||||
uint sb_size_in_sectors = (uint)(sb_size_in_bytes / imagePlugin.GetSectorSize());
|
||||
if(sb_size_in_bytes % imagePlugin.GetSectorSize() > 0) sb_size_in_sectors++;
|
||||
int sbSizeInBytes = Marshal.SizeOf(typeof(ext2FSSuperBlock));
|
||||
uint sbSizeInSectors = (uint)(sbSizeInBytes / imagePlugin.GetSectorSize());
|
||||
if(sbSizeInBytes % imagePlugin.GetSectorSize() > 0) sbSizeInSectors++;
|
||||
|
||||
byte[] sb_sector = imagePlugin.ReadSectors(sbSector + partition.Start, sb_size_in_sectors);
|
||||
byte[] sb = new byte[sb_size_in_bytes];
|
||||
Array.Copy(sb_sector, sbOff, sb, 0, sb_size_in_bytes);
|
||||
byte[] sbSector = imagePlugin.ReadSectors(sbSectorOff + partition.Start, sbSizeInSectors);
|
||||
byte[] sb = new byte[sbSizeInBytes];
|
||||
Array.Copy(sbSector, sbOff, sb, 0, sbSizeInBytes);
|
||||
|
||||
ushort magic = BitConverter.ToUInt16(sb, 0x038);
|
||||
|
||||
if(magic == ext2FSMagic || magic == ext2OldFSMagic) return true;
|
||||
|
||||
return false;
|
||||
return magic == EXT2_MAGIC || magic == EXT2_MAGIC_OLD;
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
|
||||
@@ -97,34 +94,33 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
ext2FSSuperBlock supblk = new ext2FSSuperBlock();
|
||||
bool new_ext2 = false;
|
||||
bool newExt2 = false;
|
||||
bool ext3 = false;
|
||||
bool ext4 = false;
|
||||
|
||||
int sb_size_in_bytes = Marshal.SizeOf(typeof(ext2FSSuperBlock));
|
||||
uint sb_size_in_sectors = (uint)(sb_size_in_bytes / imagePlugin.GetSectorSize());
|
||||
if(sb_size_in_bytes % imagePlugin.GetSectorSize() > 0) sb_size_in_sectors++;
|
||||
int sbSizeInBytes = Marshal.SizeOf(typeof(ext2FSSuperBlock));
|
||||
uint sbSizeInSectors = (uint)(sbSizeInBytes / imagePlugin.GetSectorSize());
|
||||
if(sbSizeInBytes % imagePlugin.GetSectorSize() > 0) sbSizeInSectors++;
|
||||
|
||||
ulong sbSector = sbPos / imagePlugin.GetSectorSize();
|
||||
uint sbOff = sbPos % imagePlugin.GetSectorSize();
|
||||
ulong sbSectorOff = SB_POS / imagePlugin.GetSectorSize();
|
||||
uint sbOff = SB_POS % imagePlugin.GetSectorSize();
|
||||
|
||||
byte[] sb_sector = imagePlugin.ReadSectors(sbSector + partition.Start, sb_size_in_sectors);
|
||||
byte[] sblock = new byte[sb_size_in_bytes];
|
||||
Array.Copy(sb_sector, sbOff, sblock, 0, sb_size_in_bytes);
|
||||
IntPtr sbPtr = Marshal.AllocHGlobal(sb_size_in_bytes);
|
||||
Marshal.Copy(sblock, 0, sbPtr, sb_size_in_bytes);
|
||||
supblk = (ext2FSSuperBlock)Marshal.PtrToStructure(sbPtr, typeof(ext2FSSuperBlock));
|
||||
byte[] sbSector = imagePlugin.ReadSectors(sbSectorOff + partition.Start, sbSizeInSectors);
|
||||
byte[] sblock = new byte[sbSizeInBytes];
|
||||
Array.Copy(sbSector, sbOff, sblock, 0, sbSizeInBytes);
|
||||
IntPtr sbPtr = Marshal.AllocHGlobal(sbSizeInBytes);
|
||||
Marshal.Copy(sblock, 0, sbPtr, sbSizeInBytes);
|
||||
ext2FSSuperBlock supblk = (ext2FSSuperBlock)Marshal.PtrToStructure(sbPtr, typeof(ext2FSSuperBlock));
|
||||
Marshal.FreeHGlobal(sbPtr);
|
||||
|
||||
xmlFSType = new FileSystemType();
|
||||
XmlFsType = new FileSystemType();
|
||||
|
||||
switch(supblk.magic) {
|
||||
case ext2OldFSMagic:
|
||||
case EXT2_MAGIC_OLD:
|
||||
sb.AppendLine("ext2 (old) filesystem");
|
||||
xmlFSType.Type = "ext2";
|
||||
XmlFsType.Type = "ext2";
|
||||
break;
|
||||
case ext2FSMagic:
|
||||
case EXT2_MAGIC:
|
||||
ext3 |= (supblk.ftr_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) == EXT3_FEATURE_COMPAT_HAS_JOURNAL ||
|
||||
(supblk.ftr_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) == EXT3_FEATURE_INCOMPAT_RECOVER ||
|
||||
(supblk.ftr_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) == EXT3_FEATURE_INCOMPAT_JOURNAL_DEV;
|
||||
@@ -143,22 +139,22 @@ namespace DiscImageChef.Filesystems
|
||||
ext4 = true;
|
||||
}
|
||||
|
||||
new_ext2 |= !ext3 && !ext4;
|
||||
newExt2 |= !ext3 && !ext4;
|
||||
|
||||
if(new_ext2)
|
||||
if(newExt2)
|
||||
{
|
||||
sb.AppendLine("ext2 filesystem");
|
||||
xmlFSType.Type = "ext2";
|
||||
XmlFsType.Type = "ext2";
|
||||
}
|
||||
if(ext3)
|
||||
{
|
||||
sb.AppendLine("ext3 filesystem");
|
||||
xmlFSType.Type = "ext3";
|
||||
XmlFsType.Type = "ext3";
|
||||
}
|
||||
if(ext4)
|
||||
{
|
||||
sb.AppendLine("ext4 filesystem");
|
||||
xmlFSType.Type = "ext4";
|
||||
XmlFsType.Type = "ext4";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -166,81 +162,80 @@ namespace DiscImageChef.Filesystems
|
||||
return;
|
||||
}
|
||||
|
||||
string ext_os;
|
||||
string extOs;
|
||||
switch(supblk.creator_os)
|
||||
{
|
||||
case EXT2_OS_FREEBSD:
|
||||
ext_os = "FreeBSD";
|
||||
extOs = "FreeBSD";
|
||||
break;
|
||||
case EXT2_OS_HURD:
|
||||
ext_os = "Hurd";
|
||||
extOs = "Hurd";
|
||||
break;
|
||||
case EXT2_OS_LINUX:
|
||||
ext_os = "Linux";
|
||||
extOs = "Linux";
|
||||
break;
|
||||
case EXT2_OS_LITES:
|
||||
ext_os = "Lites";
|
||||
extOs = "Lites";
|
||||
break;
|
||||
case EXT2_OS_MASIX:
|
||||
ext_os = "MasIX";
|
||||
extOs = "MasIX";
|
||||
break;
|
||||
default:
|
||||
ext_os = $"Unknown OS ({supblk.creator_os})";
|
||||
extOs = $"Unknown OS ({supblk.creator_os})";
|
||||
break;
|
||||
}
|
||||
|
||||
xmlFSType.SystemIdentifier = ext_os;
|
||||
XmlFsType.SystemIdentifier = extOs;
|
||||
|
||||
if(supblk.mkfs_t > 0)
|
||||
{
|
||||
sb.AppendFormat("Volume was created on {0} for {1}", DateHandlers.UNIXUnsignedToDateTime(supblk.mkfs_t),
|
||||
ext_os).AppendLine();
|
||||
xmlFSType.CreationDate = DateHandlers.UNIXUnsignedToDateTime(supblk.mkfs_t);
|
||||
xmlFSType.CreationDateSpecified = true;
|
||||
extOs).AppendLine();
|
||||
XmlFsType.CreationDate = DateHandlers.UNIXUnsignedToDateTime(supblk.mkfs_t);
|
||||
XmlFsType.CreationDateSpecified = true;
|
||||
}
|
||||
else sb.AppendFormat("Volume was created for {0}", ext_os).AppendLine();
|
||||
else sb.AppendFormat("Volume was created for {0}", extOs).AppendLine();
|
||||
|
||||
byte[] temp_lo, temp_hi;
|
||||
byte[] temp_bytes = new byte[8];
|
||||
byte[] tempBytes = new byte[8];
|
||||
ulong blocks, reserved, free;
|
||||
|
||||
if((supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_64BIT) == EXT4_FEATURE_INCOMPAT_64BIT)
|
||||
{
|
||||
temp_lo = BitConverter.GetBytes(supblk.blocks);
|
||||
temp_hi = BitConverter.GetBytes(supblk.blocks_hi);
|
||||
temp_bytes[0] = temp_lo[0];
|
||||
temp_bytes[1] = temp_lo[1];
|
||||
temp_bytes[2] = temp_lo[2];
|
||||
temp_bytes[3] = temp_lo[3];
|
||||
temp_bytes[4] = temp_hi[0];
|
||||
temp_bytes[5] = temp_hi[1];
|
||||
temp_bytes[6] = temp_hi[2];
|
||||
temp_bytes[7] = temp_hi[3];
|
||||
blocks = BitConverter.ToUInt64(temp_bytes, 0);
|
||||
byte[] tempLo = BitConverter.GetBytes(supblk.blocks);
|
||||
byte[] tempHi = BitConverter.GetBytes(supblk.blocks_hi);
|
||||
tempBytes[0] = tempLo[0];
|
||||
tempBytes[1] = tempLo[1];
|
||||
tempBytes[2] = tempLo[2];
|
||||
tempBytes[3] = tempLo[3];
|
||||
tempBytes[4] = tempHi[0];
|
||||
tempBytes[5] = tempHi[1];
|
||||
tempBytes[6] = tempHi[2];
|
||||
tempBytes[7] = tempHi[3];
|
||||
blocks = BitConverter.ToUInt64(tempBytes, 0);
|
||||
|
||||
temp_lo = BitConverter.GetBytes(supblk.reserved_blocks);
|
||||
temp_hi = BitConverter.GetBytes(supblk.reserved_blocks_hi);
|
||||
temp_bytes[0] = temp_lo[0];
|
||||
temp_bytes[1] = temp_lo[1];
|
||||
temp_bytes[2] = temp_lo[2];
|
||||
temp_bytes[3] = temp_lo[3];
|
||||
temp_bytes[4] = temp_hi[0];
|
||||
temp_bytes[5] = temp_hi[1];
|
||||
temp_bytes[6] = temp_hi[2];
|
||||
temp_bytes[7] = temp_hi[3];
|
||||
reserved = BitConverter.ToUInt64(temp_bytes, 0);
|
||||
tempLo = BitConverter.GetBytes(supblk.reserved_blocks);
|
||||
tempHi = BitConverter.GetBytes(supblk.reserved_blocks_hi);
|
||||
tempBytes[0] = tempLo[0];
|
||||
tempBytes[1] = tempLo[1];
|
||||
tempBytes[2] = tempLo[2];
|
||||
tempBytes[3] = tempLo[3];
|
||||
tempBytes[4] = tempHi[0];
|
||||
tempBytes[5] = tempHi[1];
|
||||
tempBytes[6] = tempHi[2];
|
||||
tempBytes[7] = tempHi[3];
|
||||
reserved = BitConverter.ToUInt64(tempBytes, 0);
|
||||
|
||||
temp_lo = BitConverter.GetBytes(supblk.free_blocks);
|
||||
temp_hi = BitConverter.GetBytes(supblk.free_blocks_hi);
|
||||
temp_bytes[0] = temp_lo[0];
|
||||
temp_bytes[1] = temp_lo[1];
|
||||
temp_bytes[2] = temp_lo[2];
|
||||
temp_bytes[3] = temp_lo[3];
|
||||
temp_bytes[4] = temp_hi[0];
|
||||
temp_bytes[5] = temp_hi[1];
|
||||
temp_bytes[6] = temp_hi[2];
|
||||
temp_bytes[7] = temp_hi[3];
|
||||
free = BitConverter.ToUInt64(temp_bytes, 0);
|
||||
tempLo = BitConverter.GetBytes(supblk.free_blocks);
|
||||
tempHi = BitConverter.GetBytes(supblk.free_blocks_hi);
|
||||
tempBytes[0] = tempLo[0];
|
||||
tempBytes[1] = tempLo[1];
|
||||
tempBytes[2] = tempLo[2];
|
||||
tempBytes[3] = tempLo[3];
|
||||
tempBytes[4] = tempHi[0];
|
||||
tempBytes[5] = tempHi[1];
|
||||
tempBytes[6] = tempHi[2];
|
||||
tempBytes[7] = tempHi[3];
|
||||
free = BitConverter.ToUInt64(tempBytes, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -255,8 +250,8 @@ namespace DiscImageChef.Filesystems
|
||||
sb.AppendFormat("Volume has {0} blocks of {1} bytes, for a total of {2} bytes", blocks,
|
||||
1024 << (int)supblk.block_size, blocks * (ulong)(1024 << (int)supblk.block_size))
|
||||
.AppendLine();
|
||||
xmlFSType.Clusters = (long)blocks;
|
||||
xmlFSType.ClusterSize = 1024 << (int)supblk.block_size;
|
||||
XmlFsType.Clusters = (long)blocks;
|
||||
XmlFsType.ClusterSize = 1024 << (int)supblk.block_size;
|
||||
if(supblk.mount_t > 0 || supblk.mount_c > 0)
|
||||
{
|
||||
if(supblk.mount_t > 0)
|
||||
@@ -302,17 +297,17 @@ namespace DiscImageChef.Filesystems
|
||||
{
|
||||
sb.AppendFormat("Last written on {0}", DateHandlers.UNIXUnsignedToDateTime(supblk.write_t))
|
||||
.AppendLine();
|
||||
xmlFSType.ModificationDate = DateHandlers.UNIXUnsignedToDateTime(supblk.write_t);
|
||||
xmlFSType.ModificationDateSpecified = true;
|
||||
XmlFsType.ModificationDate = DateHandlers.UNIXUnsignedToDateTime(supblk.write_t);
|
||||
XmlFsType.ModificationDateSpecified = true;
|
||||
}
|
||||
else sb.AppendLine("Volume has never been written");
|
||||
|
||||
xmlFSType.Dirty = true;
|
||||
XmlFsType.Dirty = true;
|
||||
switch(supblk.state)
|
||||
{
|
||||
case EXT2_VALID_FS:
|
||||
sb.AppendLine("Volume is clean");
|
||||
xmlFSType.Dirty = false;
|
||||
XmlFsType.Dirty = false;
|
||||
break;
|
||||
case EXT2_ERROR_FS:
|
||||
sb.AppendLine("Volume is dirty");
|
||||
@@ -329,7 +324,7 @@ namespace DiscImageChef.Filesystems
|
||||
{
|
||||
sb.AppendFormat("Volume name: \"{0}\"", StringHandlers.CToString(supblk.volume_name, CurrentEncoding))
|
||||
.AppendLine();
|
||||
xmlFSType.VolumeName = StringHandlers.CToString(supblk.volume_name, CurrentEncoding);
|
||||
XmlFsType.VolumeName = StringHandlers.CToString(supblk.volume_name, CurrentEncoding);
|
||||
}
|
||||
|
||||
switch(supblk.err_behaviour)
|
||||
@@ -355,15 +350,15 @@ namespace DiscImageChef.Filesystems
|
||||
if(supblk.uuid != Guid.Empty)
|
||||
{
|
||||
sb.AppendFormat("Volume UUID: {0}", supblk.uuid).AppendLine();
|
||||
xmlFSType.VolumeSerial = supblk.uuid.ToString();
|
||||
XmlFsType.VolumeSerial = supblk.uuid.ToString();
|
||||
}
|
||||
|
||||
if(supblk.kbytes_written > 0)
|
||||
sb.AppendFormat("{0} KiB has been written on volume", supblk.kbytes_written).AppendLine();
|
||||
|
||||
sb.AppendFormat("{0} reserved and {1} free blocks", reserved, free).AppendLine();
|
||||
xmlFSType.FreeClusters = (long)free;
|
||||
xmlFSType.FreeClustersSpecified = true;
|
||||
XmlFsType.FreeClusters = (long)free;
|
||||
XmlFsType.FreeClustersSpecified = true;
|
||||
sb.AppendFormat("{0} inodes with {1} free inodes ({2}%)", supblk.inodes, supblk.free_inodes,
|
||||
supblk.free_inodes * 100 / supblk.inodes).AppendLine();
|
||||
if(supblk.first_inode > 0) sb.AppendFormat("First inode is {0}", supblk.first_inode).AppendLine();
|
||||
@@ -533,14 +528,15 @@ namespace DiscImageChef.Filesystems
|
||||
/// <summary>
|
||||
/// Same magic for ext2, ext3 and ext4
|
||||
/// </summary>
|
||||
const ushort ext2FSMagic = 0xEF53;
|
||||
const ushort EXT2_MAGIC = 0xEF53;
|
||||
|
||||
const ushort ext2OldFSMagic = 0xEF51;
|
||||
const ushort EXT2_MAGIC_OLD = 0xEF51;
|
||||
|
||||
/// <summary>
|
||||
/// ext2/3/4 superblock
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
struct ext2FSSuperBlock
|
||||
{
|
||||
/// <summary>0x000, inodes on volume</summary>
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Text;
|
||||
using DiscImageChef.CommonTypes;
|
||||
using DiscImageChef.DiscImages;
|
||||
@@ -42,47 +43,45 @@ namespace DiscImageChef.Filesystems
|
||||
// Information from the Linux kernel
|
||||
public class extFS : Filesystem
|
||||
{
|
||||
const int sbPos = 0x400;
|
||||
const int SB_POS = 0x400;
|
||||
|
||||
public extFS()
|
||||
{
|
||||
Name = "Linux extended Filesystem";
|
||||
PluginUUID = new Guid("076CB3A2-08C2-4D69-BC8A-FCAA2E502BE2");
|
||||
PluginUuid = new Guid("076CB3A2-08C2-4D69-BC8A-FCAA2E502BE2");
|
||||
CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public extFS(Encoding encoding)
|
||||
{
|
||||
Name = "Linux extended Filesystem";
|
||||
PluginUUID = new Guid("076CB3A2-08C2-4D69-BC8A-FCAA2E502BE2");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("076CB3A2-08C2-4D69-BC8A-FCAA2E502BE2");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public extFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "Linux extended Filesystem";
|
||||
PluginUUID = new Guid("076CB3A2-08C2-4D69-BC8A-FCAA2E502BE2");
|
||||
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
|
||||
else CurrentEncoding = encoding;
|
||||
PluginUuid = new Guid("076CB3A2-08C2-4D69-BC8A-FCAA2E502BE2");
|
||||
CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
|
||||
}
|
||||
|
||||
public override bool Identify(ImagePlugin imagePlugin, Partition partition)
|
||||
{
|
||||
if(imagePlugin.GetSectorSize() < 512) return false;
|
||||
|
||||
ulong sbSector = sbPos / imagePlugin.GetSectorSize();
|
||||
uint sbOff = sbPos % imagePlugin.GetSectorSize();
|
||||
ulong sbSectorOff = SB_POS / imagePlugin.GetSectorSize();
|
||||
uint sbOff = SB_POS % imagePlugin.GetSectorSize();
|
||||
|
||||
if(sbSector + partition.Start >= partition.End) return false;
|
||||
if(sbSectorOff + partition.Start >= partition.End) return false;
|
||||
|
||||
byte[] sb_sector = imagePlugin.ReadSector(sbSector + partition.Start);
|
||||
byte[] sbSector = imagePlugin.ReadSector(sbSectorOff + partition.Start);
|
||||
byte[] sb = new byte[512];
|
||||
Array.Copy(sb_sector, sbOff, sb, 0, 512);
|
||||
Array.Copy(sbSector, sbOff, sb, 0, 512);
|
||||
|
||||
ushort magic = BitConverter.ToUInt16(sb, 0x038);
|
||||
|
||||
return magic == extFSMagic;
|
||||
return magic == EXT_MAGIC;
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
|
||||
@@ -94,44 +93,48 @@ namespace DiscImageChef.Filesystems
|
||||
|
||||
if(imagePlugin.GetSectorSize() < 512) return;
|
||||
|
||||
ulong sbSector = sbPos / imagePlugin.GetSectorSize();
|
||||
uint sbOff = sbPos % imagePlugin.GetSectorSize();
|
||||
ulong sbSectorOff = SB_POS / imagePlugin.GetSectorSize();
|
||||
uint sbOff = SB_POS % imagePlugin.GetSectorSize();
|
||||
|
||||
if(sbSector + partition.Start >= partition.End) return;
|
||||
if(sbSectorOff + partition.Start >= partition.End) return;
|
||||
|
||||
byte[] sblock = imagePlugin.ReadSector(sbSector + partition.Start);
|
||||
byte[] sb_sector = new byte[512];
|
||||
Array.Copy(sblock, sbOff, sb_sector, 0, 512);
|
||||
byte[] sblock = imagePlugin.ReadSector(sbSectorOff + partition.Start);
|
||||
byte[] sbSector = new byte[512];
|
||||
Array.Copy(sblock, sbOff, sbSector, 0, 512);
|
||||
|
||||
extFSSuperBlock ext_sb = new extFSSuperBlock();
|
||||
extFSSuperBlock extSb = new extFSSuperBlock
|
||||
{
|
||||
inodes = BitConverter.ToUInt32(sbSector, 0x000),
|
||||
zones = BitConverter.ToUInt32(sbSector, 0x004),
|
||||
firstfreeblk = BitConverter.ToUInt32(sbSector, 0x008),
|
||||
freecountblk = BitConverter.ToUInt32(sbSector, 0x00C),
|
||||
firstfreeind = BitConverter.ToUInt32(sbSector, 0x010),
|
||||
freecountind = BitConverter.ToUInt32(sbSector, 0x014),
|
||||
firstdatazone = BitConverter.ToUInt32(sbSector, 0x018),
|
||||
logzonesize = BitConverter.ToUInt32(sbSector, 0x01C),
|
||||
maxsize = BitConverter.ToUInt32(sbSector, 0x020)
|
||||
};
|
||||
|
||||
ext_sb.inodes = BitConverter.ToUInt32(sb_sector, 0x000);
|
||||
ext_sb.zones = BitConverter.ToUInt32(sb_sector, 0x004);
|
||||
ext_sb.firstfreeblk = BitConverter.ToUInt32(sb_sector, 0x008);
|
||||
ext_sb.freecountblk = BitConverter.ToUInt32(sb_sector, 0x00C);
|
||||
ext_sb.firstfreeind = BitConverter.ToUInt32(sb_sector, 0x010);
|
||||
ext_sb.freecountind = BitConverter.ToUInt32(sb_sector, 0x014);
|
||||
ext_sb.firstdatazone = BitConverter.ToUInt32(sb_sector, 0x018);
|
||||
ext_sb.logzonesize = BitConverter.ToUInt32(sb_sector, 0x01C);
|
||||
ext_sb.maxsize = BitConverter.ToUInt32(sb_sector, 0x020);
|
||||
|
||||
sb.AppendLine("ext filesystem");
|
||||
sb.AppendFormat("{0} zones on volume", ext_sb.zones);
|
||||
sb.AppendFormat("{0} free blocks ({1} bytes)", ext_sb.freecountblk, ext_sb.freecountblk * 1024);
|
||||
sb.AppendFormat("{0} inodes on volume, {1} free ({2}%)", ext_sb.inodes, ext_sb.freecountind,
|
||||
ext_sb.freecountind * 100 / ext_sb.inodes);
|
||||
sb.AppendFormat("First free inode is {0}", ext_sb.firstfreeind);
|
||||
sb.AppendFormat("First free block is {0}", ext_sb.firstfreeblk);
|
||||
sb.AppendFormat("First data zone is {0}", ext_sb.firstdatazone);
|
||||
sb.AppendFormat("Log zone size: {0}", ext_sb.logzonesize);
|
||||
sb.AppendFormat("Max zone size: {0}", ext_sb.maxsize);
|
||||
sb.AppendFormat("{0} zones on volume", extSb.zones);
|
||||
sb.AppendFormat("{0} free blocks ({1} bytes)", extSb.freecountblk, extSb.freecountblk * 1024);
|
||||
sb.AppendFormat("{0} inodes on volume, {1} free ({2}%)", extSb.inodes, extSb.freecountind,
|
||||
extSb.freecountind * 100 / extSb.inodes);
|
||||
sb.AppendFormat("First free inode is {0}", extSb.firstfreeind);
|
||||
sb.AppendFormat("First free block is {0}", extSb.firstfreeblk);
|
||||
sb.AppendFormat("First data zone is {0}", extSb.firstdatazone);
|
||||
sb.AppendFormat("Log zone size: {0}", extSb.logzonesize);
|
||||
sb.AppendFormat("Max zone size: {0}", extSb.maxsize);
|
||||
|
||||
xmlFSType = new FileSystemType();
|
||||
xmlFSType.Type = "ext";
|
||||
xmlFSType.FreeClusters = ext_sb.freecountblk;
|
||||
xmlFSType.FreeClustersSpecified = true;
|
||||
xmlFSType.ClusterSize = 1024;
|
||||
xmlFSType.Clusters = (long)((partition.End - partition.Start + 1) * imagePlugin.GetSectorSize() / 1024);
|
||||
XmlFsType = new FileSystemType
|
||||
{
|
||||
Type = "ext",
|
||||
FreeClusters = extSb.freecountblk,
|
||||
FreeClustersSpecified = true,
|
||||
ClusterSize = 1024,
|
||||
Clusters = (long)((partition.End - partition.Start + 1) * imagePlugin.GetSectorSize() / 1024)
|
||||
};
|
||||
|
||||
information = sb.ToString();
|
||||
}
|
||||
@@ -139,11 +142,12 @@ namespace DiscImageChef.Filesystems
|
||||
/// <summary>
|
||||
/// ext superblock magic
|
||||
/// </summary>
|
||||
const ushort extFSMagic = 0x137D;
|
||||
const ushort EXT_MAGIC = 0x137D;
|
||||
|
||||
/// <summary>
|
||||
/// ext superblock
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
struct extFSSuperBlock
|
||||
{
|
||||
/// <summary>0x000, inodes on volume</summary>
|
||||
|
||||
@@ -67,7 +67,7 @@ namespace DiscImageChef.Commands
|
||||
if(formatsOptions.Verbose) DicConsole.VerboseWriteLine("GUID\t\t\t\t\tPlugin");
|
||||
foreach(KeyValuePair<string, Filesystem> kvp in plugins.PluginsList)
|
||||
if(formatsOptions.Verbose)
|
||||
DicConsole.VerboseWriteLine("{0}\t{1}", kvp.Value.PluginUUID, kvp.Value.Name);
|
||||
DicConsole.VerboseWriteLine("{0}\t{1}", kvp.Value.PluginUuid, kvp.Value.Name);
|
||||
else DicConsole.WriteLine(kvp.Value.Name);
|
||||
|
||||
DicConsole.WriteLine();
|
||||
|
||||
Reference in New Issue
Block a user