REFACTOR: All refactor in DiscImageChef.Filesystems.

This commit is contained in:
2017-12-22 08:43:22 +00:00
parent ef2fff0abd
commit c59e424ec8
87 changed files with 3834 additions and 4122 deletions

View File

@@ -48,21 +48,21 @@ namespace DiscImageChef.Filesystems
public AODOS() public AODOS()
{ {
Name = "Alexander Osipov DOS file system"; 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"); CurrentEncoding = Encoding.GetEncoding("koi8-r");
} }
public AODOS(Encoding encoding) public AODOS(Encoding encoding)
{ {
Name = "Alexander Osipov DOS file system"; 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"); CurrentEncoding = Encoding.GetEncoding("koi8-r");
} }
public AODOS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public AODOS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "Alexander Osipov DOS file system"; 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"); CurrentEncoding = Encoding.GetEncoding("koi8-r");
} }
@@ -112,9 +112,7 @@ namespace DiscImageChef.Filesystems
// Does AO-DOS support any other kind of disk? // Does AO-DOS support any other kind of disk?
if(imagePlugin.ImageInfo.Sectors != 800 && imagePlugin.ImageInfo.Sectors != 1600) return false; if(imagePlugin.ImageInfo.Sectors != 800 && imagePlugin.ImageInfo.Sectors != 1600) return false;
byte[] sector; byte[] sector = imagePlugin.ReadSector(0);
sector = imagePlugin.ReadSector(0);
AODOS_BootBlock bb = new AODOS_BootBlock(); AODOS_BootBlock bb = new AODOS_BootBlock();
IntPtr bbPtr = Marshal.AllocHGlobal(Marshal.SizeOf(bb)); IntPtr bbPtr = Marshal.AllocHGlobal(Marshal.SizeOf(bb));
Marshal.Copy(sector, 0, bbPtr, 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, public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
out string information) out string information)
{ {
byte[] sector; byte[] sector = imagePlugin.ReadSector(0);
sector = imagePlugin.ReadSector(0);
AODOS_BootBlock bb = new AODOS_BootBlock(); AODOS_BootBlock bb = new AODOS_BootBlock();
IntPtr bbPtr = Marshal.AllocHGlobal(Marshal.SizeOf(bb)); IntPtr bbPtr = Marshal.AllocHGlobal(Marshal.SizeOf(bb));
Marshal.Copy(sector, 0, bbPtr, 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"); sbInformation.AppendLine("Alexander Osipov DOS file system");
xmlFSType = new FileSystemType XmlFsType = new FileSystemType
{ {
Type = "Alexander Osipov DOS file system", Type = "Alexander Osipov DOS file system",
Clusters = (long)imagePlugin.ImageInfo.Sectors, Clusters = (long)imagePlugin.ImageInfo.Sectors,

View File

@@ -42,27 +42,27 @@ namespace DiscImageChef.Filesystems
{ {
public class APFS : Filesystem public class APFS : Filesystem
{ {
const uint ApfsContainerMagic = 0x4253584E; // "NXSB" const uint APFS_CONTAINER_MAGIC = 0x4253584E; // "NXSB"
const uint ApfsVolumeMagic = 0x42535041; // "APSB" const uint APFS_VOLUME_MAGIC = 0x42535041; // "APSB"
public APFS() public APFS()
{ {
Name = "Apple File System"; Name = "Apple File System";
PluginUUID = new Guid("A4060F9D-2909-42E2-9D95-DB31FA7EA797"); PluginUuid = new Guid("A4060F9D-2909-42E2-9D95-DB31FA7EA797");
CurrentEncoding = Encoding.UTF8; CurrentEncoding = Encoding.UTF8;
} }
public APFS(Encoding encoding) public APFS(Encoding encoding)
{ {
Name = "Apple File System"; Name = "Apple File System";
PluginUUID = new Guid("A4060F9D-2909-42E2-9D95-DB31FA7EA797"); PluginUuid = new Guid("A4060F9D-2909-42E2-9D95-DB31FA7EA797");
CurrentEncoding = Encoding.UTF8; CurrentEncoding = Encoding.UTF8;
} }
public APFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public APFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "Apple File System"; Name = "Apple File System";
PluginUUID = new Guid("A4060F9D-2909-42E2-9D95-DB31FA7EA797"); PluginUuid = new Guid("A4060F9D-2909-42E2-9D95-DB31FA7EA797");
CurrentEncoding = Encoding.UTF8; CurrentEncoding = Encoding.UTF8;
} }
@@ -94,16 +94,14 @@ namespace DiscImageChef.Filesystems
} }
catch { return false; } catch { return false; }
if(nxSb.magic == ApfsContainerMagic) return true; return nxSb.magic == APFS_CONTAINER_MAGIC;
return false;
} }
public override void GetInformation(ImagePlugin imagePlugin, Partition partition, public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
out string information) out string information)
{ {
StringBuilder sbInformation = new StringBuilder(); StringBuilder sbInformation = new StringBuilder();
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType();
information = ""; information = "";
if(partition.Start >= partition.End) return; if(partition.Start >= partition.End) return;
@@ -120,7 +118,7 @@ namespace DiscImageChef.Filesystems
} }
catch { return; } catch { return; }
if(nxSb.magic != ApfsContainerMagic) return; if(nxSb.magic != APFS_CONTAINER_MAGIC) return;
sbInformation.AppendLine("Apple File System"); sbInformation.AppendLine("Apple File System");
sbInformation.AppendLine(); sbInformation.AppendLine();
@@ -130,11 +128,13 @@ namespace DiscImageChef.Filesystems
information = sbInformation.ToString(); information = sbInformation.ToString();
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType
xmlFSType.Bootable = false; {
xmlFSType.Clusters = (long)nxSb.containerBlocks; Bootable = false,
xmlFSType.ClusterSize = (int)nxSb.blockSize; Clusters = (long)nxSb.containerBlocks,
xmlFSType.Type = "Apple File System"; ClusterSize = (int)nxSb.blockSize,
Type = "Apple File System"
};
} }
public override Errno Mount() public override Errno Mount()

View File

@@ -46,49 +46,47 @@ namespace DiscImageChef.Filesystems
/// <summary> /// <summary>
/// Location for boot block, in bytes /// Location for boot block, in bytes
/// </summary> /// </summary>
const ulong bootBlockLocation = 0xC00; const ulong BOOT_BLOCK_LOCATION = 0xC00;
/// <summary> /// <summary>
/// Size of boot block, in bytes /// Size of boot block, in bytes
/// </summary> /// </summary>
const uint bootBlockSize = 0x200; const uint BOOT_BLOCK_SIZE = 0x200;
/// <summary> /// <summary>
/// Location of new directory, in bytes /// Location of new directory, in bytes
/// </summary> /// </summary>
const ulong newDirectoryLocation = 0x400; const ulong NEW_DIRECTORY_LOCATION = 0x400;
/// <summary> /// <summary>
/// Location of old directory, in bytes /// Location of old directory, in bytes
/// </summary> /// </summary>
const ulong oldDirectoryLocation = 0x200; const ulong OLD_DIRECTORY_LOCATION = 0x200;
/// <summary> /// <summary>
/// Size of old directory /// Size of old directory
/// </summary> /// </summary>
const uint oldDirectorySize = 1280; const uint OLD_DIRECTORY_SIZE = 1280;
/// <summary> /// <summary>
/// Size of new directory /// Size of new directory
/// </summary> /// </summary>
const uint newDirectorySize = 2048; const uint NEW_DIRECTORY_SIZE = 2048;
public AcornADFS() public AcornADFS()
{ {
Name = "Acorn Advanced Disc Filing System"; 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"); CurrentEncoding = Encoding.GetEncoding("iso-8859-1");
} }
public AcornADFS(Encoding encoding) public AcornADFS(Encoding encoding)
{ {
Name = "Acorn Advanced Disc Filing System"; Name = "Acorn Advanced Disc Filing System";
PluginUUID = new Guid("BAFC1E50-9C64-4CD3-8400-80628CC27AFA"); PluginUuid = new Guid("BAFC1E50-9C64-4CD3-8400-80628CC27AFA");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-1"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1");
else CurrentEncoding = encoding;
} }
public AcornADFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public AcornADFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "Acorn Advanced Disc Filing System"; Name = "Acorn Advanced Disc Filing System";
PluginUUID = new Guid("BAFC1E50-9C64-4CD3-8400-80628CC27AFA"); PluginUuid = new Guid("BAFC1E50-9C64-4CD3-8400-80628CC27AFA");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-1"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1");
else CurrentEncoding = encoding;
} }
/// <summary> /// <summary>
@@ -186,11 +184,11 @@ namespace DiscImageChef.Filesystems
/// <summary> /// <summary>
/// New directory format magic number, "Nick" /// New directory format magic number, "Nick"
/// </summary> /// </summary>
const uint newDirMagic = 0x6B63694E; const uint NEW_DIR_MAGIC = 0x6B63694E;
/// <summary> /// <summary>
/// Old directory format magic number, "Hugo" /// Old directory format magic number, "Hugo"
/// </summary> /// </summary>
const uint oldDirMagic = 0x6F677548; const uint OLD_DIR_MAGIC = 0x6F677548;
/// <summary> /// <summary>
/// Directory header, common to "old" and "new" directories /// 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 // ADFS-S, ADFS-M, ADFS-L, ADFS-D without partitions
if(partition.Start == 0) if(partition.Start == 0)
{ {
OldMapSector0 oldMap0;
OldMapSector1 oldMap1;
OldDirectory oldRoot;
byte oldChk0;
byte oldChk1;
byte dirChk;
sector = imagePlugin.ReadSector(0); sector = imagePlugin.ReadSector(0);
oldChk0 = AcornMapChecksum(sector, 255); byte oldChk0 = AcornMapChecksum(sector, 255);
ptr = GCHandle.Alloc(sector, GCHandleType.Pinned); 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); sector = imagePlugin.ReadSector(1);
oldChk1 = AcornMapChecksum(sector, 255); byte oldChk1 = AcornMapChecksum(sector, 255);
ptr = GCHandle.Alloc(sector, GCHandleType.Pinned); 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", "oldMap0.checksum = {0}", oldMap0.checksum);
DicConsole.DebugWriteLine("ADFS Plugin", "oldChk0 = {0}", oldChk0); DicConsole.DebugWriteLine("ADFS Plugin", "oldChk0 = {0}", oldChk0);
@@ -313,21 +304,21 @@ namespace DiscImageChef.Filesystems
if(oldMap0.checksum == oldChk0 && oldMap1.checksum == oldChk1 && oldMap0.checksum != 0 && if(oldMap0.checksum == oldChk0 && oldMap1.checksum == oldChk1 && oldMap0.checksum != 0 &&
oldMap1.checksum != 0) oldMap1.checksum != 0)
{ {
sbSector = oldDirectoryLocation / imagePlugin.ImageInfo.SectorSize; sbSector = OLD_DIRECTORY_LOCATION / imagePlugin.ImageInfo.SectorSize;
sectorsToRead = oldDirectorySize / imagePlugin.ImageInfo.SectorSize; sectorsToRead = OLD_DIRECTORY_SIZE / imagePlugin.ImageInfo.SectorSize;
if(oldDirectorySize % imagePlugin.ImageInfo.SectorSize > 0) sectorsToRead++; if(OLD_DIRECTORY_SIZE % imagePlugin.ImageInfo.SectorSize > 0) sectorsToRead++;
sector = imagePlugin.ReadSectors(sbSector, sectorsToRead); sector = imagePlugin.ReadSectors(sbSector, sectorsToRead);
if(sector.Length > oldDirectorySize) if(sector.Length > OLD_DIRECTORY_SIZE)
{ {
byte[] tmp = new byte[oldDirectorySize]; byte[] tmp = new byte[OLD_DIRECTORY_SIZE];
Array.Copy(sector, 0, tmp, 0, oldDirectorySize - 53); Array.Copy(sector, 0, tmp, 0, OLD_DIRECTORY_SIZE - 53);
Array.Copy(sector, sector.Length - 54, tmp, oldDirectorySize - 54, 53); Array.Copy(sector, sector.Length - 54, tmp, OLD_DIRECTORY_SIZE - 54, 53);
sector = tmp; sector = tmp;
} }
ptr = GCHandle.Alloc(sector, GCHandleType.Pinned); ptr = GCHandle.Alloc(sector, GCHandleType.Pinned);
oldRoot = (OldDirectory)Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(OldDirectory)); OldDirectory oldRoot = (OldDirectory)Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(OldDirectory));
dirChk = AcornDirectoryChecksum(sector, (int)oldDirectorySize - 1); byte dirChk = AcornDirectoryChecksum(sector, (int)OLD_DIRECTORY_SIZE - 1);
DicConsole.DebugWriteLine("ADFS Plugin", "oldRoot.header.magic at 0x200 = {0}", DicConsole.DebugWriteLine("ADFS Plugin", "oldRoot.header.magic at 0x200 = {0}",
oldRoot.header.magic); oldRoot.header.magic);
@@ -336,25 +327,25 @@ namespace DiscImageChef.Filesystems
oldRoot.tail.checkByte); oldRoot.tail.checkByte);
DicConsole.DebugWriteLine("ADFS Plugin", "dirChk at 0x200 = {0}", dirChk); DicConsole.DebugWriteLine("ADFS Plugin", "dirChk at 0x200 = {0}", dirChk);
if(oldRoot.header.magic == oldDirMagic && oldRoot.tail.magic == oldDirMagic || if(oldRoot.header.magic == OLD_DIR_MAGIC && oldRoot.tail.magic == OLD_DIR_MAGIC ||
oldRoot.header.magic == newDirMagic && oldRoot.tail.magic == newDirMagic) return true; 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... // 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; sbSector = NEW_DIRECTORY_LOCATION / imagePlugin.ImageInfo.SectorSize;
sectorsToRead = newDirectorySize / imagePlugin.ImageInfo.SectorSize; sectorsToRead = NEW_DIRECTORY_SIZE / imagePlugin.ImageInfo.SectorSize;
if(newDirectorySize % imagePlugin.ImageInfo.SectorSize > 0) sectorsToRead++; if(NEW_DIRECTORY_SIZE % imagePlugin.ImageInfo.SectorSize > 0) sectorsToRead++;
sector = imagePlugin.ReadSectors(sbSector, sectorsToRead); sector = imagePlugin.ReadSectors(sbSector, sectorsToRead);
if(sector.Length > oldDirectorySize) if(sector.Length > OLD_DIRECTORY_SIZE)
{ {
byte[] tmp = new byte[oldDirectorySize]; byte[] tmp = new byte[OLD_DIRECTORY_SIZE];
Array.Copy(sector, 0, tmp, 0, oldDirectorySize - 53); Array.Copy(sector, 0, tmp, 0, OLD_DIRECTORY_SIZE - 53);
Array.Copy(sector, sector.Length - 54, tmp, oldDirectorySize - 54, 53); Array.Copy(sector, sector.Length - 54, tmp, OLD_DIRECTORY_SIZE - 54, 53);
sector = tmp; sector = tmp;
} }
ptr = GCHandle.Alloc(sector, GCHandleType.Pinned); ptr = GCHandle.Alloc(sector, GCHandleType.Pinned);
oldRoot = (OldDirectory)Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(OldDirectory)); 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}", DicConsole.DebugWriteLine("ADFS Plugin", "oldRoot.header.magic at 0x400 = {0}",
oldRoot.header.magic); oldRoot.header.magic);
@@ -363,8 +354,8 @@ namespace DiscImageChef.Filesystems
oldRoot.tail.checkByte); oldRoot.tail.checkByte);
DicConsole.DebugWriteLine("ADFS Plugin", "dirChk at 0x400 = {0}", dirChk); DicConsole.DebugWriteLine("ADFS Plugin", "dirChk at 0x400 = {0}", dirChk);
if(oldRoot.header.magic == oldDirMagic && oldRoot.tail.magic == oldDirMagic || if(oldRoot.header.magic == OLD_DIR_MAGIC && oldRoot.tail.magic == OLD_DIR_MAGIC ||
oldRoot.header.magic == newDirMagic && oldRoot.tail.magic == newDirMagic) return true; 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", "newChk = {0}", newChk);
DicConsole.DebugWriteLine("ADFS Plugin", "map.zoneChecksum = {0}", sector[0]); DicConsole.DebugWriteLine("ADFS Plugin", "map.zoneChecksum = {0}", sector[0]);
sbSector = bootBlockLocation / imagePlugin.ImageInfo.SectorSize; sbSector = BOOT_BLOCK_LOCATION / imagePlugin.ImageInfo.SectorSize;
sectorsToRead = bootBlockSize / imagePlugin.ImageInfo.SectorSize; sectorsToRead = BOOT_BLOCK_SIZE / imagePlugin.ImageInfo.SectorSize;
if(bootBlockSize % imagePlugin.ImageInfo.SectorSize > 0) sectorsToRead++; if(BOOT_BLOCK_SIZE % imagePlugin.ImageInfo.SectorSize > 0) sectorsToRead++;
if(sbSector + partition.Start + sectorsToRead >= partition.End) return false; if(sbSector + partition.Start + sectorsToRead >= partition.End) return false;
@@ -424,9 +415,7 @@ namespace DiscImageChef.Filesystems
bytes *= 0x100000000; bytes *= 0x100000000;
bytes += drSb.disc_size; bytes += drSb.disc_size;
if(bytes > imagePlugin.GetSectors() * imagePlugin.GetSectorSize()) return false; return bytes <= imagePlugin.GetSectors() * imagePlugin.GetSectorSize();
return true;
} }
// TODO: Find root directory on volumes with DiscRecord // TODO: Find root directory on volumes with DiscRecord
@@ -436,7 +425,7 @@ namespace DiscImageChef.Filesystems
out string information) out string information)
{ {
StringBuilder sbInformation = new StringBuilder(); StringBuilder sbInformation = new StringBuilder();
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType();
information = ""; information = "";
ulong sbSector; ulong sbSector;
@@ -444,27 +433,19 @@ namespace DiscImageChef.Filesystems
uint sectorsToRead; uint sectorsToRead;
GCHandle ptr; GCHandle ptr;
ulong bytes; ulong bytes;
string discname;
// ADFS-S, ADFS-M, ADFS-L, ADFS-D without partitions // ADFS-S, ADFS-M, ADFS-L, ADFS-D without partitions
if(partition.Start == 0) if(partition.Start == 0)
{ {
OldMapSector0 oldMap0;
OldMapSector1 oldMap1;
OldDirectory oldRoot;
NewDirectory newRoot;
byte oldChk0;
byte oldChk1;
sector = imagePlugin.ReadSector(0); sector = imagePlugin.ReadSector(0);
oldChk0 = AcornMapChecksum(sector, 255); byte oldChk0 = AcornMapChecksum(sector, 255);
ptr = GCHandle.Alloc(sector, GCHandleType.Pinned); 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); sector = imagePlugin.ReadSector(1);
oldChk1 = AcornMapChecksum(sector, 255); byte oldChk1 = AcornMapChecksum(sector, 255);
ptr = GCHandle.Alloc(sector, GCHandleType.Pinned); 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) // 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) if(oldMap0.checksum == oldChk0 && oldMap1.checksum != oldChk1 && sector.Length >= 512)
@@ -488,7 +469,7 @@ namespace DiscImageChef.Filesystems
namebytes[i * 2 + 1] = oldMap1.name[i]; namebytes[i * 2 + 1] = oldMap1.name[i];
} }
xmlFSType = new FileSystemType XmlFsType = new FileSystemType
{ {
Bootable = oldMap1.boot != 0, // Or not? Bootable = oldMap1.boot != 0, // Or not?
Clusters = (long)(bytes / imagePlugin.ImageInfo.SectorSize), Clusters = (long)(bytes / imagePlugin.ImageInfo.SectorSize),
@@ -498,56 +479,56 @@ namespace DiscImageChef.Filesystems
if(ArrayHelpers.ArrayIsNullOrEmpty(namebytes)) if(ArrayHelpers.ArrayIsNullOrEmpty(namebytes))
{ {
sbSector = oldDirectoryLocation / imagePlugin.ImageInfo.SectorSize; sbSector = OLD_DIRECTORY_LOCATION / imagePlugin.ImageInfo.SectorSize;
sectorsToRead = oldDirectorySize / imagePlugin.ImageInfo.SectorSize; sectorsToRead = OLD_DIRECTORY_SIZE / imagePlugin.ImageInfo.SectorSize;
if(oldDirectorySize % imagePlugin.ImageInfo.SectorSize > 0) sectorsToRead++; if(OLD_DIRECTORY_SIZE % imagePlugin.ImageInfo.SectorSize > 0) sectorsToRead++;
sector = imagePlugin.ReadSectors(sbSector, sectorsToRead); sector = imagePlugin.ReadSectors(sbSector, sectorsToRead);
if(sector.Length > oldDirectorySize) if(sector.Length > OLD_DIRECTORY_SIZE)
{ {
byte[] tmp = new byte[oldDirectorySize]; byte[] tmp = new byte[OLD_DIRECTORY_SIZE];
Array.Copy(sector, 0, tmp, 0, oldDirectorySize - 53); Array.Copy(sector, 0, tmp, 0, OLD_DIRECTORY_SIZE - 53);
Array.Copy(sector, sector.Length - 54, tmp, oldDirectorySize - 54, 53); Array.Copy(sector, sector.Length - 54, tmp, OLD_DIRECTORY_SIZE - 54, 53);
sector = tmp; sector = tmp;
} }
ptr = GCHandle.Alloc(sector, GCHandleType.Pinned); 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 else
{ {
// RISC OS says the old directory can't be in the new location, hard disks created by RISC OS 3.10 do that... // 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; sbSector = NEW_DIRECTORY_LOCATION / imagePlugin.ImageInfo.SectorSize;
sectorsToRead = newDirectorySize / imagePlugin.ImageInfo.SectorSize; sectorsToRead = NEW_DIRECTORY_SIZE / imagePlugin.ImageInfo.SectorSize;
if(newDirectorySize % imagePlugin.ImageInfo.SectorSize > 0) sectorsToRead++; if(NEW_DIRECTORY_SIZE % imagePlugin.ImageInfo.SectorSize > 0) sectorsToRead++;
sector = imagePlugin.ReadSectors(sbSector, sectorsToRead); sector = imagePlugin.ReadSectors(sbSector, sectorsToRead);
if(sector.Length > oldDirectorySize) if(sector.Length > OLD_DIRECTORY_SIZE)
{ {
byte[] tmp = new byte[oldDirectorySize]; byte[] tmp = new byte[OLD_DIRECTORY_SIZE];
Array.Copy(sector, 0, tmp, 0, oldDirectorySize - 53); Array.Copy(sector, 0, tmp, 0, OLD_DIRECTORY_SIZE - 53);
Array.Copy(sector, sector.Length - 54, tmp, oldDirectorySize - 54, 53); Array.Copy(sector, sector.Length - 54, tmp, OLD_DIRECTORY_SIZE - 54, 53);
sector = tmp; sector = tmp;
} }
ptr = GCHandle.Alloc(sector, GCHandleType.Pinned); ptr = GCHandle.Alloc(sector, GCHandleType.Pinned);
oldRoot = (OldDirectory)Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), oldRoot = (OldDirectory)Marshal.PtrToStructure(ptr.AddrOfPinnedObject(),
typeof(OldDirectory)); 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 else
{ {
sector = imagePlugin.ReadSectors(sbSector, sectorsToRead); sector = imagePlugin.ReadSectors(sbSector, sectorsToRead);
if(sector.Length > newDirectorySize) if(sector.Length > NEW_DIRECTORY_SIZE)
{ {
byte[] tmp = new byte[newDirectorySize]; byte[] tmp = new byte[NEW_DIRECTORY_SIZE];
Array.Copy(sector, 0, tmp, 0, newDirectorySize - 41); Array.Copy(sector, 0, tmp, 0, NEW_DIRECTORY_SIZE - 41);
Array.Copy(sector, sector.Length - 42, tmp, newDirectorySize - 42, 41); Array.Copy(sector, sector.Length - 42, tmp, NEW_DIRECTORY_SIZE - 42, 41);
sector = tmp; sector = tmp;
} }
ptr = GCHandle.Alloc(sector, GCHandleType.Pinned); ptr = GCHandle.Alloc(sector, GCHandleType.Pinned);
newRoot = (NewDirectory)Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), NewDirectory newRoot = (NewDirectory)Marshal.PtrToStructure(ptr.AddrOfPinnedObject(),
typeof(NewDirectory)); 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(); .AppendLine();
if(oldMap1.discId > 0) if(oldMap1.discId > 0)
{ {
xmlFSType.VolumeSerial = $"{oldMap1.discId:X4}"; XmlFsType.VolumeSerial = $"{oldMap1.discId:X4}";
sbInformation.AppendFormat("Volume ID: {0:X4}", oldMap1.discId).AppendLine(); sbInformation.AppendFormat("Volume ID: {0:X4}", oldMap1.discId).AppendLine();
} }
if(!ArrayHelpers.ArrayIsNullOrEmpty(namebytes)) if(!ArrayHelpers.ArrayIsNullOrEmpty(namebytes))
xmlFSType.VolumeName = StringHandlers.CToString(namebytes, CurrentEncoding); XmlFsType.VolumeName = StringHandlers.CToString(namebytes, CurrentEncoding);
information = sbInformation.ToString(); information = sbInformation.ToString();
@@ -580,9 +561,9 @@ namespace DiscImageChef.Filesystems
DicConsole.DebugWriteLine("ADFS Plugin", "newChk = {0}", newChk); DicConsole.DebugWriteLine("ADFS Plugin", "newChk = {0}", newChk);
DicConsole.DebugWriteLine("ADFS Plugin", "map.zoneChecksum = {0}", sector[0]); DicConsole.DebugWriteLine("ADFS Plugin", "map.zoneChecksum = {0}", sector[0]);
sbSector = bootBlockLocation / imagePlugin.ImageInfo.SectorSize; sbSector = BOOT_BLOCK_LOCATION / imagePlugin.ImageInfo.SectorSize;
sectorsToRead = bootBlockSize / imagePlugin.ImageInfo.SectorSize; sectorsToRead = BOOT_BLOCK_SIZE / imagePlugin.ImageInfo.SectorSize;
if(bootBlockSize % imagePlugin.ImageInfo.SectorSize > 0) sectorsToRead++; if(BOOT_BLOCK_SIZE % imagePlugin.ImageInfo.SectorSize > 0) sectorsToRead++;
byte[] bootSector = imagePlugin.ReadSectors(sbSector + partition.Start, sectorsToRead); byte[] bootSector = imagePlugin.ReadSectors(sbSector + partition.Start, sectorsToRead);
int bootChk = 0; int bootChk = 0;
@@ -648,7 +629,7 @@ namespace DiscImageChef.Filesystems
if(bytes > imagePlugin.GetSectors() * imagePlugin.GetSectorSize()) return; if(bytes > imagePlugin.GetSectors() * imagePlugin.GetSectorSize()) return;
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType();
sbInformation.AppendLine("Acorn Advanced Disc Filing System"); sbInformation.AppendLine("Acorn Advanced Disc Filing System");
sbInformation.AppendLine(); sbInformation.AppendLine();
@@ -666,22 +647,22 @@ namespace DiscImageChef.Filesystems
sbInformation.AppendFormat("Volume flags: 0x{0:X4}", drSb.flags).AppendLine(); sbInformation.AppendFormat("Volume flags: 0x{0:X4}", drSb.flags).AppendLine();
if(drSb.disc_id > 0) 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(); sbInformation.AppendFormat("Volume ID: {0:X4}", drSb.disc_id).AppendLine();
} }
if(!ArrayHelpers.ArrayIsNullOrEmpty(drSb.disc_name)) if(!ArrayHelpers.ArrayIsNullOrEmpty(drSb.disc_name))
{ {
discname = StringHandlers.CToString(drSb.disc_name, CurrentEncoding); string discname = StringHandlers.CToString(drSb.disc_name, CurrentEncoding);
xmlFSType.VolumeName = discname; XmlFsType.VolumeName = discname;
sbInformation.AppendFormat("Volume name: {0}", discname).AppendLine(); sbInformation.AppendFormat("Volume name: {0}", discname).AppendLine();
} }
information = sbInformation.ToString(); information = sbInformation.ToString();
xmlFSType.Bootable |= drSb.bootoption != 0; // Or not? XmlFsType.Bootable |= drSb.bootoption != 0; // Or not?
xmlFSType.Clusters = (long)(bytes / (ulong)(1 << drSb.log2secsize)); XmlFsType.Clusters = (long)(bytes / (ulong)(1 << drSb.log2secsize));
xmlFSType.ClusterSize = 1 << drSb.log2secsize; XmlFsType.ClusterSize = 1 << drSb.log2secsize;
xmlFSType.Type = "Acorn Advanced Disc Filing System"; XmlFsType.Type = "Acorn Advanced Disc Filing System";
} }
public override Errno Mount() public override Errno Mount()
@@ -768,48 +749,43 @@ namespace DiscImageChef.Filesystems
return (byte)(sum & 0xFF); 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 rover;
uint sumVector0 = 0;
uint sumVector1 = 0;
uint sumVector2 = 0;
uint sumVector3 = 0;
sum_vector0 = 0; for(rover = (uint)(mapBase.Length - 4); rover > 0; rover -= 4)
sum_vector1 = 0;
sum_vector2 = 0;
sum_vector3 = 0;
for(rover = (uint)(map_base.Length - 4); rover > 0; rover -= 4)
{ {
sum_vector0 += map_base[rover + 0] + (sum_vector3 >> 8); sumVector0 += mapBase[rover + 0] + (sumVector3 >> 8);
sum_vector3 &= 0xff; sumVector3 &= 0xff;
sum_vector1 += map_base[rover + 1] + (sum_vector0 >> 8); sumVector1 += mapBase[rover + 1] + (sumVector0 >> 8);
sum_vector0 &= 0xff; sumVector0 &= 0xff;
sum_vector2 += map_base[rover + 2] + (sum_vector1 >> 8); sumVector2 += mapBase[rover + 2] + (sumVector1 >> 8);
sum_vector1 &= 0xff; sumVector1 &= 0xff;
sum_vector3 += map_base[rover + 3] + (sum_vector2 >> 8); sumVector3 += mapBase[rover + 3] + (sumVector2 >> 8);
sum_vector2 &= 0xff; sumVector2 &= 0xff;
} }
/* /*
Don't add the check byte when calculating its value Don't add the check byte when calculating its value
*/ */
sum_vector0 += sum_vector3 >> 8; sumVector0 += sumVector3 >> 8;
sum_vector1 += map_base[rover + 1] + (sum_vector0 >> 8); sumVector1 += mapBase[rover + 1] + (sumVector0 >> 8);
sum_vector2 += map_base[rover + 2] + (sum_vector1 >> 8); sumVector2 += mapBase[rover + 2] + (sumVector1 >> 8);
sum_vector3 += map_base[rover + 3] + (sum_vector2 >> 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... // TODO: This is not correct...
byte AcornDirectoryChecksum(byte[] data, int length) static byte AcornDirectoryChecksum(IList<byte> data, int length)
{ {
uint sum = 0; uint sum = 0;
if(length > data.Length) length = data.Length; if(length > data.Count) length = data.Count;
// EOR r0, r1, r0, ROR #13 // EOR r0, r1, r0, ROR #13
for(int i = 0; i < length; i++) for(int i = 0; i < length; i++)

View File

@@ -48,24 +48,22 @@ namespace DiscImageChef.Filesystems
public AmigaDOSPlugin() public AmigaDOSPlugin()
{ {
Name = "Amiga DOS filesystem"; 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"); CurrentEncoding = Encoding.GetEncoding("iso-8859-1");
} }
public AmigaDOSPlugin(Encoding encoding) public AmigaDOSPlugin(Encoding encoding)
{ {
Name = "Amiga DOS filesystem"; Name = "Amiga DOS filesystem";
PluginUUID = new Guid("3c882400-208c-427d-a086-9119852a1bc7"); PluginUuid = new Guid("3c882400-208c-427d-a086-9119852a1bc7");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-1"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1");
else CurrentEncoding = encoding;
} }
public AmigaDOSPlugin(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public AmigaDOSPlugin(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "Amiga DOS filesystem"; Name = "Amiga DOS filesystem";
PluginUUID = new Guid("3c882400-208c-427d-a086-9119852a1bc7"); PluginUuid = new Guid("3c882400-208c-427d-a086-9119852a1bc7");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-1"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1");
else CurrentEncoding = encoding;
} }
/// <summary> /// <summary>
@@ -206,11 +204,11 @@ namespace DiscImageChef.Filesystems
public uint sec_type; public uint sec_type;
} }
public const uint FFS_Mask = 0x444F5300; const uint FFS_MASK = 0x444F5300;
public const uint MuFS_Mask = 0x6D754600; const uint MUFS_MASK = 0x6D754600;
public const uint TypeHeader = 2; const uint TYPE_HEADER = 2;
public const uint SubTypeRoot = 1; const uint SUBTYPE_ROOT = 1;
public override bool Identify(ImagePlugin imagePlugin, Partition partition) public override bool Identify(ImagePlugin imagePlugin, Partition partition)
{ {
@@ -229,14 +227,14 @@ namespace DiscImageChef.Filesystems
// AROS boot floppies... // AROS boot floppies...
if(sector.Length >= 512 && sector[510] == 0x55 && sector[511] == 0xAA && 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); sector = imagePlugin.ReadSectors(1 + partition.Start, 2);
bblk = BigEndianMarshal.ByteArrayToStructureBigEndian<BootBlock>(sector); bblk = BigEndianMarshal.ByteArrayToStructureBigEndian<BootBlock>(sector);
} }
// Not FFS or MuFS? // 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 // Clear checksum on sector
sector[4] = sector[5] = sector[6] = sector[7] = 0; 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", "bblk.checksum = 0x{0:X8}", bblk.checksum);
DicConsole.DebugWriteLine("AmigaDOS plugin", "bsum = 0x{0:X8}", bsum); 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 bootblock is correct, let's take its rootblock pointer
if(bsum == bblk.checksum) if(bsum == bblk.checksum)
{ {
b_root_ptr = bblk.root_ptr + partition.Start; bRootPtr = bblk.root_ptr + partition.Start;
DicConsole.DebugWriteLine("AmigaDOS plugin", "Bootblock points to {0} as Rootblock", b_root_ptr); 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 - 1,
(partition.End - partition.Start + 1) / 2 + partition.Start, (partition.End - partition.Start + 1) / 2 + partition.Start,
(partition.End - partition.Start + 1) / 2 + partition.Start + 4 (partition.End - partition.Start + 1) / 2 + partition.Start + 4
@@ -265,14 +263,14 @@ namespace DiscImageChef.Filesystems
RootBlock rblk = new RootBlock(); RootBlock rblk = new RootBlock();
// So to handle even number of sectors // 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)) { foreach(ulong rootPtr in rootPtrs.Where(rootPtr => rootPtr < partition.End && rootPtr >= partition.Start)) {
DicConsole.DebugWriteLine("AmigaDOS plugin", "Searching for Rootblock in sector {0}", root_ptr); 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); rblk.type = BigEndianBitConverter.ToUInt32(sector, 0x00);
DicConsole.DebugWriteLine("AmigaDOS plugin", "rblk.type = {0}", rblk.type); 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); rblk.hashTableSize = BigEndianBitConverter.ToUInt32(sector, 0x0C);
@@ -286,9 +284,9 @@ namespace DiscImageChef.Filesystems
if(blockSize % sector.Length > 0) sectorsPerBlock++; 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 // Clear checksum on sector
rblk.checksum = BigEndianBitConverter.ToUInt32(sector, 20); rblk.checksum = BigEndianBitConverter.ToUInt32(sector, 20);
@@ -301,7 +299,7 @@ namespace DiscImageChef.Filesystems
rblk.sec_type = BigEndianBitConverter.ToUInt32(sector, sector.Length - 4); rblk.sec_type = BigEndianBitConverter.ToUInt32(sector, sector.Length - 4);
DicConsole.DebugWriteLine("AmigaDOS plugin", "rblk.sec_type = {0}", rblk.sec_type); 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; return false;
@@ -311,88 +309,88 @@ namespace DiscImageChef.Filesystems
out string information) out string information)
{ {
StringBuilder sbInformation = new StringBuilder(); StringBuilder sbInformation = new StringBuilder();
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType();
information = null; information = null;
BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; 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); BootBlock bootBlk = BigEndianMarshal.ByteArrayToStructureBigEndian<BootBlock>(bootBlockSectors);
bootBlk.bootCode = new byte[BootBlockSectors.Length - 12]; bootBlk.bootCode = new byte[bootBlockSectors.Length - 12];
Array.Copy(BootBlockSectors, 12, bootBlk.bootCode, 0, bootBlk.bootCode.Length); Array.Copy(bootBlockSectors, 12, bootBlk.bootCode, 0, bootBlk.bootCode.Length);
BootBlockSectors[4] = BootBlockSectors[5] = BootBlockSectors[6] = BootBlockSectors[7] = 0; bootBlockSectors[4] = bootBlockSectors[5] = bootBlockSectors[6] = bootBlockSectors[7] = 0;
uint bsum = AmigaBootChecksum(BootBlockSectors); uint bsum = AmigaBootChecksum(bootBlockSectors);
ulong b_root_ptr = 0; ulong bRootPtr = 0;
// If bootblock is correct, let's take its rootblock pointer // If bootblock is correct, let's take its rootblock pointer
if(bsum == bootBlk.checksum) if(bsum == bootBlk.checksum)
{ {
b_root_ptr = bootBlk.root_ptr + partition.Start; bRootPtr = bootBlk.root_ptr + partition.Start;
DicConsole.DebugWriteLine("AmigaDOS plugin", "Bootblock points to {0} as Rootblock", b_root_ptr); 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 - 1,
(partition.End - partition.Start + 1) / 2 + partition.Start, (partition.End - partition.Start + 1) / 2 + partition.Start,
(partition.End - partition.Start + 1) / 2 + partition.Start + 4 (partition.End - partition.Start + 1) / 2 + partition.Start + 4
}; };
RootBlock rootBlk = new RootBlock(); RootBlock rootBlk = new RootBlock();
byte[] RootBlockSector = null; byte[] rootBlockSector = null;
bool root_found = false; bool rootFound = false;
uint blockSize = 0; uint blockSize = 0;
// So to handle even number of sectors // 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)) { foreach(ulong rootPtr in rootPtrs.Where(rootPtr => rootPtr < partition.End && rootPtr >= partition.Start)) {
DicConsole.DebugWriteLine("AmigaDOS plugin", "Searching for Rootblock in sector {0}", root_ptr); 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); 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); DicConsole.DebugWriteLine("AmigaDOS plugin", "rootBlk.hashTableSize = {0}", rootBlk.hashTableSize);
blockSize = (rootBlk.hashTableSize + 56) * 4; 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", "blockSize = {0}", blockSize);
DicConsole.DebugWriteLine("AmigaDOS plugin", "sectorsPerBlock = {0}", sectorsPerBlock); 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 // Clear checksum on sector
rootBlk.checksum = BigEndianBitConverter.ToUInt32(RootBlockSector, 20); rootBlk.checksum = BigEndianBitConverter.ToUInt32(rootBlockSector, 20);
RootBlockSector[20] = RootBlockSector[21] = RootBlockSector[22] = RootBlockSector[23] = 0; rootBlockSector[20] = rootBlockSector[21] = rootBlockSector[22] = rootBlockSector[23] = 0;
uint rsum = AmigaChecksum(RootBlockSector); uint rsum = AmigaChecksum(rootBlockSector);
DicConsole.DebugWriteLine("AmigaDOS plugin", "rootBlk.checksum = 0x{0:X8}", rootBlk.checksum); DicConsole.DebugWriteLine("AmigaDOS plugin", "rootBlk.checksum = 0x{0:X8}", rootBlk.checksum);
DicConsole.DebugWriteLine("AmigaDOS plugin", "rsum = 0x{0:X8}", rsum); 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); 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); rootBlockSector = imagePlugin.ReadSectors(rootPtr, sectorsPerBlock);
root_found = true; rootFound = true;
break; break;
} }
if(!root_found) return; if(!rootFound) return;
rootBlk = MarshalRootBlock(RootBlockSector); rootBlk = MarshalRootBlock(rootBlockSector);
string diskName = StringHandlers.PascalToString(rootBlk.diskName, CurrentEncoding); string diskName = StringHandlers.PascalToString(rootBlk.diskName, CurrentEncoding);
@@ -400,35 +398,35 @@ namespace DiscImageChef.Filesystems
{ {
case 0: case 0:
sbInformation.Append("Amiga Original File System"); sbInformation.Append("Amiga Original File System");
xmlFSType.Type = "Amiga OFS"; XmlFsType.Type = "Amiga OFS";
break; break;
case 1: case 1:
sbInformation.Append("Amiga Fast File System"); sbInformation.Append("Amiga Fast File System");
xmlFSType.Type = "Amiga FFS"; XmlFsType.Type = "Amiga FFS";
break; break;
case 2: case 2:
sbInformation.Append("Amiga Original File System with international characters"); sbInformation.Append("Amiga Original File System with international characters");
xmlFSType.Type = "Amiga OFS"; XmlFsType.Type = "Amiga OFS";
break; break;
case 3: case 3:
sbInformation.Append("Amiga Fast File System with international characters"); sbInformation.Append("Amiga Fast File System with international characters");
xmlFSType.Type = "Amiga FFS"; XmlFsType.Type = "Amiga FFS";
break; break;
case 4: case 4:
sbInformation.Append("Amiga Original File System with directory cache"); sbInformation.Append("Amiga Original File System with directory cache");
xmlFSType.Type = "Amiga OFS"; XmlFsType.Type = "Amiga OFS";
break; break;
case 5: case 5:
sbInformation.Append("Amiga Fast File System with directory cache"); sbInformation.Append("Amiga Fast File System with directory cache");
xmlFSType.Type = "Amiga FFS"; XmlFsType.Type = "Amiga FFS";
break; break;
case 6: case 6:
sbInformation.Append("Amiga Original File System with long filenames"); sbInformation.Append("Amiga Original File System with long filenames");
xmlFSType.Type = "Amiga OFS2"; XmlFsType.Type = "Amiga OFS2";
break; break;
case 7: case 7:
sbInformation.Append("Amiga Fast File System with long filenames"); sbInformation.Append("Amiga Fast File System with long filenames");
xmlFSType.Type = "Amiga FFS2"; XmlFsType.Type = "Amiga FFS2";
break; break;
} }
@@ -472,17 +470,17 @@ namespace DiscImageChef.Filesystems
sbInformation.AppendFormat("Root block checksum is 0x{0:X8}", rootBlk.checksum).AppendLine(); sbInformation.AppendFormat("Root block checksum is 0x{0:X8}", rootBlk.checksum).AppendLine();
information = sbInformation.ToString(); information = sbInformation.ToString();
xmlFSType.CreationDate = DateHandlers.AmigaToDateTime(rootBlk.cDays, rootBlk.cMins, rootBlk.cTicks); XmlFsType.CreationDate = DateHandlers.AmigaToDateTime(rootBlk.cDays, rootBlk.cMins, rootBlk.cTicks);
xmlFSType.CreationDateSpecified = true; XmlFsType.CreationDateSpecified = true;
xmlFSType.ModificationDate = DateHandlers.AmigaToDateTime(rootBlk.vDays, rootBlk.vMins, rootBlk.vTicks); XmlFsType.ModificationDate = DateHandlers.AmigaToDateTime(rootBlk.vDays, rootBlk.vMins, rootBlk.vTicks);
xmlFSType.ModificationDateSpecified = true; XmlFsType.ModificationDateSpecified = true;
xmlFSType.Dirty = rootBlk.bitmapFlag != 0xFFFFFFFF; XmlFsType.Dirty = rootBlk.bitmapFlag != 0xFFFFFFFF;
xmlFSType.Clusters = blocks; XmlFsType.Clusters = blocks;
xmlFSType.ClusterSize = (int)blockSize; XmlFsType.ClusterSize = (int)blockSize;
xmlFSType.VolumeName = diskName; XmlFsType.VolumeName = diskName;
xmlFSType.Bootable = bsum == bootBlk.checksum; XmlFsType.Bootable = bsum == bootBlk.checksum;
// Useful as a serial // Useful as a serial
xmlFSType.VolumeSerial = $"{rootBlk.checksum:X8}"; XmlFsType.VolumeSerial = $"{rootBlk.checksum:X8}";
} }
static RootBlock MarshalRootBlock(byte[] block) static RootBlock MarshalRootBlock(byte[] block)
@@ -511,12 +509,12 @@ namespace DiscImageChef.Filesystems
static uint AmigaBootChecksum(byte[] data) static uint AmigaBootChecksum(byte[] data)
{ {
uint sum, psum; uint sum;
sum = 0; sum = 0;
for(int i = 0; i < data.Length; i += 4) 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])) < if((sum += (uint)((data[i] << 24) + (data[i + 1] << 16) + (data[i + 2] << 8) + data[i + 3])) <
psum) sum++; psum) sum++;
} }

View File

@@ -77,14 +77,14 @@ namespace DiscImageChef.Filesystems.AppleDOS
public AppleDOS() public AppleDOS()
{ {
Name = "Apple DOS File System"; 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(); CurrentEncoding = new LisaRoman();
} }
public AppleDOS(Encoding encoding) public AppleDOS(Encoding encoding)
{ {
Name = "Apple DOS File System"; 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 // TODO: Until Apple ][ encoding is implemented
CurrentEncoding = new LisaRoman(); CurrentEncoding = new LisaRoman();
} }
@@ -94,7 +94,7 @@ namespace DiscImageChef.Filesystems.AppleDOS
device = imagePlugin; device = imagePlugin;
start = partition.Start; start = partition.Start;
Name = "Apple DOS File System"; 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 // TODO: Until Apple ][ encoding is implemented
CurrentEncoding = new LisaRoman(); CurrentEncoding = new LisaRoman();
} }

View File

@@ -91,7 +91,7 @@ namespace DiscImageChef.Filesystems.AppleDOS
information = sb.ToString(); information = sb.ToString();
xmlFSType = new FileSystemType XmlFsType = new FileSystemType
{ {
Bootable = true, Bootable = true,
Clusters = (long)imagePlugin.ImageInfo.Sectors, Clusters = (long)imagePlugin.ImageInfo.Sectors,

View File

@@ -99,7 +99,7 @@ namespace DiscImageChef.Filesystems.AppleDOS
} }
// Create XML metadata for mounted filesystem // Create XML metadata for mounted filesystem
xmlFSType = new FileSystemType XmlFsType = new FileSystemType
{ {
Bootable = true, Bootable = true,
Clusters = (long)device.ImageInfo.Sectors, Clusters = (long)device.ImageInfo.Sectors,
@@ -109,7 +109,7 @@ namespace DiscImageChef.Filesystems.AppleDOS
FreeClustersSpecified = true, FreeClustersSpecified = true,
Type = "Apple DOS" Type = "Apple DOS"
}; };
xmlFSType.FreeClusters = xmlFSType.Clusters - usedSectors; XmlFsType.FreeClusters = XmlFsType.Clusters - usedSectors;
this.debug = debug; this.debug = debug;
mounted = true; mounted = true;
@@ -141,7 +141,7 @@ namespace DiscImageChef.Filesystems.AppleDOS
Blocks = (long)device.ImageInfo.Sectors, Blocks = (long)device.ImageInfo.Sectors,
FilenameLength = 30, FilenameLength = 30,
Files = (ulong)catalogCache.Count, Files = (ulong)catalogCache.Count,
PluginId = PluginUUID, PluginId = PluginUuid,
Type = "Apple DOS" Type = "Apple DOS"
}; };
stat.FreeFiles = totalFileEntries - stat.Files; stat.FreeFiles = totalFileEntries - stat.Files;

View File

@@ -60,58 +60,56 @@ namespace DiscImageChef.Filesystems
public AppleHFS() public AppleHFS()
{ {
Name = "Apple Hierarchical File System"; 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"); CurrentEncoding = Encoding.GetEncoding("macintosh");
} }
public AppleHFS(Encoding encoding) public AppleHFS(Encoding encoding)
{ {
Name = "Apple Hierarchical File System"; Name = "Apple Hierarchical File System";
PluginUUID = new Guid("36405F8D-0D26-6ECC-0BBB-1D5225FF404F"); PluginUuid = new Guid("36405F8D-0D26-6ECC-0BBB-1D5225FF404F");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("macintosh"); CurrentEncoding = encoding ?? Encoding.GetEncoding("macintosh");
else CurrentEncoding = encoding;
} }
public AppleHFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public AppleHFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "Apple Hierarchical File System"; Name = "Apple Hierarchical File System";
PluginUUID = new Guid("36405F8D-0D26-6ECC-0BBB-1D5225FF404F"); PluginUuid = new Guid("36405F8D-0D26-6ECC-0BBB-1D5225FF404F");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("macintosh"); CurrentEncoding = encoding ?? Encoding.GetEncoding("macintosh");
else CurrentEncoding = encoding;
} }
public override bool Identify(ImagePlugin imagePlugin, Partition partition) public override bool Identify(ImagePlugin imagePlugin, Partition partition)
{ {
if(2 + partition.Start >= partition.End) return false; if(2 + partition.Start >= partition.End) return false;
byte[] mdb_sector; byte[] mdbSector;
ushort drSigWord; ushort drSigWord;
if(imagePlugin.GetSectorSize() == 2352 || imagePlugin.GetSectorSize() == 2448 || if(imagePlugin.GetSectorSize() == 2352 || imagePlugin.GetSectorSize() == 2448 ||
imagePlugin.GetSectorSize() == 2048) 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}) 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; if(drSigWord != HFS_MAGIC) continue;
drSigWord = drSigWord =
BigEndianBitConverter BigEndianBitConverter
.ToUInt16(mdb_sector, offset + 0x7C); // Seek to embedded HFS+ signature .ToUInt16(mdbSector, offset + 0x7C); // Seek to embedded HFS+ signature
return drSigWord != HFSP_MAGIC; return drSigWord != HFSP_MAGIC;
} }
} }
else else
{ {
mdb_sector = imagePlugin.ReadSector(2 + partition.Start); mdbSector = imagePlugin.ReadSector(2 + partition.Start);
drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0); drSigWord = BigEndianBitConverter.ToUInt16(mdbSector, 0);
if(drSigWord != HFS_MAGIC) return false; 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; return drSigWord != HFSP_MAGIC;
} }
@@ -126,11 +124,8 @@ namespace DiscImageChef.Filesystems
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
HFS_MasterDirectoryBlock MDB; byte[] bbSector = null;
HFS_BootBlock BB; byte[] mdbSector = null;
byte[] bb_sector = null;
byte[] mdb_sector = null;
ushort drSigWord; ushort drSigWord;
bool APMFromHDDOnCD = false; bool APMFromHDDOnCD = false;
@@ -138,17 +133,17 @@ namespace DiscImageChef.Filesystems
if(imagePlugin.GetSectorSize() == 2352 || imagePlugin.GetSectorSize() == 2448 || if(imagePlugin.GetSectorSize() == 2352 || imagePlugin.GetSectorSize() == 2448 ||
imagePlugin.GetSectorSize() == 2048) 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}) 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; if(drSigWord != HFS_MAGIC) continue;
bb_sector = new byte[1024]; bbSector = new byte[1024];
mdb_sector = new byte[512]; mdbSector = new byte[512];
if(offset >= 0x400) Array.Copy(tmp_sector, offset - 0x400, bb_sector, 0, 1024); if(offset >= 0x400) Array.Copy(tmpSector, offset - 0x400, bbSector, 0, 1024);
Array.Copy(tmp_sector, offset, mdb_sector, 0, 512); Array.Copy(tmpSector, offset, mdbSector, 0, 512);
APMFromHDDOnCD = true; APMFromHDDOnCD = true;
break; break;
} }
@@ -157,15 +152,15 @@ namespace DiscImageChef.Filesystems
} }
else else
{ {
mdb_sector = imagePlugin.ReadSector(2 + partition.Start); mdbSector = imagePlugin.ReadSector(2 + partition.Start);
drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0); 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; else return;
} }
MDB = BigEndianMarshal.ByteArrayToStructureBigEndian<HFS_MasterDirectoryBlock>(mdb_sector); HFS_MasterDirectoryBlock MDB = BigEndianMarshal.ByteArrayToStructureBigEndian<HFS_MasterDirectoryBlock>(mdbSector);
BB = BigEndianMarshal.ByteArrayToStructureBigEndian<HFS_BootBlock>(bb_sector); HFS_BootBlock BB = BigEndianMarshal.ByteArrayToStructureBigEndian<HFS_BootBlock>(bbSector);
sb.AppendLine("Apple Hierarchical File System"); sb.AppendLine("Apple Hierarchical File System");
sb.AppendLine(); sb.AppendLine();
@@ -182,8 +177,7 @@ namespace DiscImageChef.Filesystems
else sb.AppendLine("Volume has never been backed up"); else sb.AppendLine("Volume has never been backed up");
if((MDB.drAtrb & 0x80) == 0x80) sb.AppendLine("Volume is locked by hardware."); if((MDB.drAtrb & 0x80) == 0x80) sb.AppendLine("Volume is locked by hardware.");
if((MDB.drAtrb & 0x100) == 0x100) sb.AppendLine("Volume was unmonted."); sb.AppendLine((MDB.drAtrb & 0x100) == 0x100 ? "Volume was unmonted." : "Volume is mounted.");
else sb.AppendLine("Volume is mounted.");
if((MDB.drAtrb & 0x200) == 0x200) sb.AppendLine("Volume has spared bad blocks."); 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 & 0x400) == 0x400) sb.AppendLine("Volume does not need cache.");
if((MDB.drAtrb & 0x800) == 0x800) sb.AppendLine("Boot volume is inconsistent."); if((MDB.drAtrb & 0x800) == 0x800) sb.AppendLine("Boot volume is inconsistent.");
@@ -275,45 +269,45 @@ namespace DiscImageChef.Filesystems
information = sb.ToString(); information = sb.ToString();
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType();
if(MDB.drVolBkUp > 0) if(MDB.drVolBkUp > 0)
{ {
xmlFSType.BackupDate = DateHandlers.MacToDateTime(MDB.drVolBkUp); XmlFsType.BackupDate = DateHandlers.MacToDateTime(MDB.drVolBkUp);
xmlFSType.BackupDateSpecified = true; XmlFsType.BackupDateSpecified = true;
} }
xmlFSType.Bootable = BB.signature == HFSBB_MAGIC || MDB.drFndrInfo0 != 0 || MDB.drFndrInfo3 != 0 || MDB.drFndrInfo5 != 0; XmlFsType.Bootable = BB.signature == HFSBB_MAGIC || MDB.drFndrInfo0 != 0 || MDB.drFndrInfo3 != 0 || MDB.drFndrInfo5 != 0;
xmlFSType.Clusters = MDB.drNmAlBlks; XmlFsType.Clusters = MDB.drNmAlBlks;
xmlFSType.ClusterSize = (int)MDB.drAlBlkSiz; XmlFsType.ClusterSize = (int)MDB.drAlBlkSiz;
if(MDB.drCrDate > 0) if(MDB.drCrDate > 0)
{ {
xmlFSType.CreationDate = DateHandlers.MacToDateTime(MDB.drCrDate); XmlFsType.CreationDate = DateHandlers.MacToDateTime(MDB.drCrDate);
xmlFSType.CreationDateSpecified = true; XmlFsType.CreationDateSpecified = true;
} }
xmlFSType.Dirty = (MDB.drAtrb & 0x100) != 0x100; XmlFsType.Dirty = (MDB.drAtrb & 0x100) != 0x100;
xmlFSType.Files = MDB.drFilCnt; XmlFsType.Files = MDB.drFilCnt;
xmlFSType.FilesSpecified = true; XmlFsType.FilesSpecified = true;
xmlFSType.FreeClusters = MDB.drFreeBks; XmlFsType.FreeClusters = MDB.drFreeBks;
xmlFSType.FreeClustersSpecified = true; XmlFsType.FreeClustersSpecified = true;
if(MDB.drLsMod > 0) if(MDB.drLsMod > 0)
{ {
xmlFSType.ModificationDate = DateHandlers.MacToDateTime(MDB.drLsMod); XmlFsType.ModificationDate = DateHandlers.MacToDateTime(MDB.drLsMod);
xmlFSType.ModificationDateSpecified = true; XmlFsType.ModificationDateSpecified = true;
} }
xmlFSType.Type = "HFS"; XmlFsType.Type = "HFS";
xmlFSType.VolumeName = StringHandlers.PascalToString(MDB.drVN, CurrentEncoding); XmlFsType.VolumeName = StringHandlers.PascalToString(MDB.drVN, CurrentEncoding);
if(MDB.drFndrInfo6 != 0 && MDB.drFndrInfo7 != 0) 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; ulong lba2K = lba / 4;
int Remainder = (int)(LBA % 4); int remainder = (int)(lba % 4);
byte[] buffer = imagePlugin.ReadSector(LBA2k); byte[] buffer = imagePlugin.ReadSector(lba2K);
byte[] sector = new byte[512]; byte[] sector = new byte[512];
Array.Copy(buffer, Remainder * 512, sector, 0, 512); Array.Copy(buffer, remainder * 512, sector, 0, 512);
return sector; return sector;
} }

View File

@@ -59,21 +59,21 @@ namespace DiscImageChef.Filesystems
public AppleHFSPlus() public AppleHFSPlus()
{ {
Name = "Apple HFS+ filesystem"; Name = "Apple HFS+ filesystem";
PluginUUID = new Guid("36405F8D-0D26-6EBE-436F-62F0586B4F08"); PluginUuid = new Guid("36405F8D-0D26-6EBE-436F-62F0586B4F08");
CurrentEncoding = Encoding.BigEndianUnicode; CurrentEncoding = Encoding.BigEndianUnicode;
} }
public AppleHFSPlus(Encoding encoding) public AppleHFSPlus(Encoding encoding)
{ {
Name = "Apple HFS+ filesystem"; Name = "Apple HFS+ filesystem";
PluginUUID = new Guid("36405F8D-0D26-6EBE-436F-62F0586B4F08"); PluginUuid = new Guid("36405F8D-0D26-6EBE-436F-62F0586B4F08");
CurrentEncoding = Encoding.BigEndianUnicode; CurrentEncoding = Encoding.BigEndianUnicode;
} }
public AppleHFSPlus(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public AppleHFSPlus(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "Apple HFS+ filesystem"; Name = "Apple HFS+ filesystem";
PluginUUID = new Guid("36405F8D-0D26-6EBE-436F-62F0586B4F08"); PluginUuid = new Guid("36405F8D-0D26-6EBE-436F-62F0586B4F08");
CurrentEncoding = Encoding.BigEndianUnicode; CurrentEncoding = Encoding.BigEndianUnicode;
} }
@@ -82,47 +82,41 @@ namespace DiscImageChef.Filesystems
if(2 + partition.Start >= partition.End) return false; if(2 + partition.Start >= partition.End) return false;
ushort drSigWord; ushort drSigWord;
ushort xdrStABNt;
ushort drAlBlSt;
uint drAlBlkSiz;
byte[] vh_sector; ulong hfspOffset;
ulong hfsp_offset;
uint sectorsToRead = 0x800 / imagePlugin.ImageInfo.SectorSize; uint sectorsToRead = 0x800 / imagePlugin.ImageInfo.SectorSize;
if(0x800 % imagePlugin.ImageInfo.SectorSize > 0) sectorsToRead++; if(0x800 % imagePlugin.ImageInfo.SectorSize > 0) sectorsToRead++;
vh_sector = imagePlugin.ReadSectors(partition.Start, byte[] vhSector = imagePlugin.ReadSectors(partition.Start,
sectorsToRead); // Read volume header, of HFS Wrapper MDB 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" 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+" if(drSigWord == HFSP_MAGIC) // "H+"
{ {
xdrStABNt = BigEndianBitConverter ushort xdrStABNt = BigEndianBitConverter
.ToUInt16(vh_sector, 0x47E); // Starting block number of embedded HFS+ volume .ToUInt16(vhSector, 0x47E);
drAlBlkSiz = BigEndianBitConverter.ToUInt32(vh_sector, 0x414); // Block size uint drAlBlkSiz = BigEndianBitConverter.ToUInt32(vhSector, 0x414);
drAlBlSt = BigEndianBitConverter ushort drAlBlSt = BigEndianBitConverter
.ToUInt16(vh_sector, 0x41C); // Start of allocated blocks (in 512-byte/block) .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); drSigWord = BigEndianBitConverter.ToUInt16(vhSector, 0x400);
if(drSigWord == HFSP_MAGIC || drSigWord == HFSX_MAGIC) return true; return drSigWord == HFSP_MAGIC || drSigWord == HFSX_MAGIC;
return false;
} }
public override void GetInformation(ImagePlugin imagePlugin, Partition partition, public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
@@ -131,55 +125,51 @@ namespace DiscImageChef.Filesystems
information = ""; information = "";
ushort drSigWord; ushort drSigWord;
ushort xdrStABNt;
ushort drAlBlSt;
uint drAlBlkSiz;
HFSPlusVolumeHeader HPVH = new HFSPlusVolumeHeader(); HFSPlusVolumeHeader HPVH = new HFSPlusVolumeHeader();
ulong hfsp_offset; ulong hfspOffset;
bool wrapped; bool wrapped;
byte[] vh_sector;
uint sectorsToRead = 0x800 / imagePlugin.ImageInfo.SectorSize; uint sectorsToRead = 0x800 / imagePlugin.ImageInfo.SectorSize;
if(0x800 % imagePlugin.ImageInfo.SectorSize > 0) sectorsToRead++; if(0x800 % imagePlugin.ImageInfo.SectorSize > 0) sectorsToRead++;
vh_sector = imagePlugin.ReadSectors(partition.Start, byte[] vhSector = imagePlugin.ReadSectors(partition.Start,
sectorsToRead); // Read volume header, of HFS Wrapper MDB 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" 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+" if(drSigWord == HFSP_MAGIC) // "H+"
{ {
xdrStABNt = BigEndianBitConverter ushort xdrStABNt = BigEndianBitConverter
.ToUInt16(vh_sector, 0x47E); // Starting block number of embedded HFS+ volume .ToUInt16(vhSector, 0x47E);
drAlBlkSiz = BigEndianBitConverter.ToUInt32(vh_sector, 0x414); // Block size uint drAlBlkSiz = BigEndianBitConverter.ToUInt32(vhSector, 0x414);
drAlBlSt = BigEndianBitConverter ushort drAlBlSt = BigEndianBitConverter
.ToUInt16(vh_sector, 0x41C); // Start of allocated blocks (in 512-byte/block) .ToUInt16(vhSector, 0x41C);
hfsp_offset = (ulong)((drAlBlSt * 512 + xdrStABNt * drAlBlkSiz) / imagePlugin.GetSectorSize()); hfspOffset = (ulong)((drAlBlSt * 512 + xdrStABNt * drAlBlkSiz) / imagePlugin.GetSectorSize());
wrapped = true; wrapped = true;
} }
else else
{ {
hfsp_offset = 0; hfspOffset = 0;
wrapped = false; wrapped = false;
} }
} }
else else
{ {
hfsp_offset = 0; hfspOffset = 0;
wrapped = false; 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) if(HPVH.signature == HFSP_MAGIC || HPVH.signature == HFSX_MAGIC)
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
@@ -189,10 +179,10 @@ namespace DiscImageChef.Filesystems
if(wrapped) sb.AppendLine("Volume is wrapped inside an HFS volume."); if(wrapped) sb.AppendLine("Volume is wrapped inside an HFS volume.");
byte[] tmp = new byte[0x400]; byte[] tmp = new byte[0x400];
Array.Copy(vh_sector, 0x400, tmp, 0, 0x400); Array.Copy(vhSector, 0x400, tmp, 0, 0x400);
vh_sector = tmp; vhSector = tmp;
HPVH = BigEndianMarshal.ByteArrayToStructureBigEndian<HFSPlusVolumeHeader>(vh_sector); HPVH = BigEndianMarshal.ByteArrayToStructureBigEndian<HFSPlusVolumeHeader>(vhSector);
if(HPVH.version == 4 || HPVH.version == 5) 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) sb.AppendFormat("Mac OS X Volume ID: {0:X8}{1:X8}", HPVH.drFndrInfo6, HPVH.drFndrInfo7)
.AppendLine(); .AppendLine();
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType();
if(HPVH.backupDate > 0) if(HPVH.backupDate > 0)
{ {
xmlFSType.BackupDate = DateHandlers.MacToDateTime(HPVH.backupDate); XmlFsType.BackupDate = DateHandlers.MacToDateTime(HPVH.backupDate);
xmlFSType.BackupDateSpecified = true; XmlFsType.BackupDateSpecified = true;
} }
xmlFSType.Bootable |= HPVH.drFndrInfo0 != 0 || HPVH.drFndrInfo3 != 0 || HPVH.drFndrInfo5 != 0; XmlFsType.Bootable |= HPVH.drFndrInfo0 != 0 || HPVH.drFndrInfo3 != 0 || HPVH.drFndrInfo5 != 0;
xmlFSType.Clusters = HPVH.totalBlocks; XmlFsType.Clusters = HPVH.totalBlocks;
xmlFSType.ClusterSize = (int)HPVH.blockSize; XmlFsType.ClusterSize = (int)HPVH.blockSize;
if(HPVH.createDate > 0) if(HPVH.createDate > 0)
{ {
xmlFSType.CreationDate = DateHandlers.MacToDateTime(HPVH.createDate); XmlFsType.CreationDate = DateHandlers.MacToDateTime(HPVH.createDate);
xmlFSType.CreationDateSpecified = true; XmlFsType.CreationDateSpecified = true;
} }
xmlFSType.Dirty = (HPVH.attributes & 0x100) != 0x100; XmlFsType.Dirty = (HPVH.attributes & 0x100) != 0x100;
xmlFSType.Files = HPVH.fileCount; XmlFsType.Files = HPVH.fileCount;
xmlFSType.FilesSpecified = true; XmlFsType.FilesSpecified = true;
xmlFSType.FreeClusters = HPVH.freeBlocks; XmlFsType.FreeClusters = HPVH.freeBlocks;
xmlFSType.FreeClustersSpecified = true; XmlFsType.FreeClustersSpecified = true;
if(HPVH.modifyDate > 0) if(HPVH.modifyDate > 0)
{ {
xmlFSType.ModificationDate = DateHandlers.MacToDateTime(HPVH.modifyDate); XmlFsType.ModificationDate = DateHandlers.MacToDateTime(HPVH.modifyDate);
xmlFSType.ModificationDateSpecified = true; XmlFsType.ModificationDateSpecified = true;
} }
if(HPVH.signature == 0x482B) xmlFSType.Type = "HFS+"; if(HPVH.signature == 0x482B) XmlFsType.Type = "HFS+";
if(HPVH.signature == 0x4858) xmlFSType.Type = "HFSX"; if(HPVH.signature == 0x4858) XmlFsType.Type = "HFSX";
if(HPVH.drFndrInfo6 != 0 && HPVH.drFndrInfo7 != 0) if(HPVH.drFndrInfo6 != 0 && HPVH.drFndrInfo7 != 0)
xmlFSType.VolumeSerial = $"{HPVH.drFndrInfo6:X8}{HPVH.drFndrInfo7:X8}"; XmlFsType.VolumeSerial = $"{HPVH.drFndrInfo6:X8}{HPVH.drFndrInfo7:X8}";
xmlFSType.SystemIdentifier = Encoding.ASCII.GetString(HPVH.lastMountedVersion); XmlFsType.SystemIdentifier = Encoding.ASCII.GetString(HPVH.lastMountedVersion);
} }
else else
{ {

View File

@@ -65,26 +65,24 @@ namespace DiscImageChef.Filesystems.AppleMFS
public AppleMFS() public AppleMFS()
{ {
Name = "Apple Macintosh File System"; 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"); CurrentEncoding = Encoding.GetEncoding("macintosh");
} }
public AppleMFS(Encoding encoding) public AppleMFS(Encoding encoding)
{ {
Name = "Apple Macintosh File System"; Name = "Apple Macintosh File System";
PluginUUID = new Guid("36405F8D-0D26-4066-6538-5DBF5D065C3A"); PluginUuid = new Guid("36405F8D-0D26-4066-6538-5DBF5D065C3A");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("macintosh"); CurrentEncoding = encoding ?? Encoding.GetEncoding("macintosh");
else CurrentEncoding = encoding;
} }
public AppleMFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public AppleMFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "Apple Macintosh File System"; Name = "Apple Macintosh File System";
PluginUUID = new Guid("36405F8D-0D26-4066-6538-5DBF5D065C3A"); PluginUuid = new Guid("36405F8D-0D26-4066-6538-5DBF5D065C3A");
device = imagePlugin; device = imagePlugin;
partitionStart = partition.Start; partitionStart = partition.Start;
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("macintosh"); CurrentEncoding = encoding ?? Encoding.GetEncoding("macintosh");
else CurrentEncoding = encoding;
} }
} }
} }

View File

@@ -61,7 +61,7 @@ namespace DiscImageChef.Filesystems.AppleMFS
return Errno.NoError; return Errno.NoError;
} }
public bool FillDirectory() bool FillDirectory()
{ {
idToFilename = new Dictionary<uint, string>(); idToFilename = new Dictionary<uint, string>();
idToEntry = new Dictionary<uint, MFS_FileEntry>(); idToEntry = new Dictionary<uint, MFS_FileEntry>();
@@ -70,11 +70,12 @@ namespace DiscImageChef.Filesystems.AppleMFS
int offset = 0; int offset = 0;
while(offset + 51 < directoryBlocks.Length) while(offset + 51 < directoryBlocks.Length)
{ {
MFS_FileEntry entry = new MFS_FileEntry(); MFS_FileEntry entry = new MFS_FileEntry
string lowerFilename; {
entry.flUsrWds = new byte[16]; 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; if(!entry.flFlags.HasFlag(MFS_FileFlags.Used)) break;
entry.flTyp = directoryBlocks[offset + 1]; entry.flTyp = directoryBlocks[offset + 1];
@@ -90,8 +91,8 @@ namespace DiscImageChef.Filesystems.AppleMFS
entry.flMdDat = BigEndianBitConverter.ToUInt32(directoryBlocks, offset + 46); entry.flMdDat = BigEndianBitConverter.ToUInt32(directoryBlocks, offset + 46);
entry.flNam = new byte[directoryBlocks[offset + 50] + 1]; entry.flNam = new byte[directoryBlocks[offset + 50] + 1];
Array.Copy(directoryBlocks, offset + 50, entry.flNam, 0, entry.flNam.Length); 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('/', ':'); .Replace('/', ':');
if(entry.flFlags.HasFlag(MFS_FileFlags.Used) && !idToFilename.ContainsKey(entry.flFlNum) && if(entry.flFlags.HasFlag(MFS_FileFlags.Used) && !idToFilename.ContainsKey(entry.flFlNum) &&
!idToEntry.ContainsKey(entry.flFlNum) && !filenameToId.ContainsKey(lowerFilename) && !idToEntry.ContainsKey(entry.flFlNum) && !filenameToId.ContainsKey(lowerFilename) &&

View File

@@ -49,12 +49,9 @@ namespace DiscImageChef.Filesystems.AppleMFS
string[] pathElements = path.Split(new[] {'/'}, StringSplitOptions.RemoveEmptyEntries); string[] pathElements = path.Split(new[] {'/'}, StringSplitOptions.RemoveEmptyEntries);
if(pathElements.Length != 1) return Errno.NotSupported; if(pathElements.Length != 1) return Errno.NotSupported;
uint fileID; if(!filenameToId.TryGetValue(path.ToLowerInvariant(), out uint fileId)) return Errno.NoSuchFile;
MFS_FileEntry entry;
if(!filenameToId.TryGetValue(path.ToLowerInvariant(), out fileID)) return Errno.NoSuchFile; if(!idToEntry.TryGetValue(fileId, out MFS_FileEntry entry)) return Errno.NoSuchFile;
if(!idToEntry.TryGetValue(fileID, out entry)) return Errno.NoSuchFile;
if(fileBlock > entry.flPyLen / volMDB.drAlBlkSiz) return Errno.InvalidArgument; if(fileBlock > entry.flPyLen / volMDB.drAlBlkSiz) return Errno.InvalidArgument;
@@ -85,12 +82,9 @@ namespace DiscImageChef.Filesystems.AppleMFS
string[] pathElements = path.Split(new[] {'/'}, StringSplitOptions.RemoveEmptyEntries); string[] pathElements = path.Split(new[] {'/'}, StringSplitOptions.RemoveEmptyEntries);
if(pathElements.Length != 1) return Errno.NotSupported; if(pathElements.Length != 1) return Errno.NotSupported;
uint fileID; if(!filenameToId.TryGetValue(path.ToLowerInvariant(), out uint fileId)) return Errno.NoSuchFile;
MFS_FileEntry entry;
if(!filenameToId.TryGetValue(path.ToLowerInvariant(), out fileID)) return Errno.NoSuchFile; if(!idToEntry.TryGetValue(fileId, out MFS_FileEntry entry)) return Errno.NoSuchFile;
if(!idToEntry.TryGetValue(fileID, out entry)) return Errno.NoSuchFile;
attributes = new FileAttributes(); attributes = new FileAttributes();
MFS_FinderFlags fdFlags = (MFS_FinderFlags)BigEndianBitConverter.ToUInt16(entry.flUsrWds, 0x08); 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, "$Bitmap", StringComparison.InvariantCulture) == 0 ||
string.Compare(path, "$MDB", StringComparison.InvariantCulture) == 0) string.Compare(path, "$MDB", StringComparison.InvariantCulture) == 0)
{ {
stat = new FileEntryInfo(); stat = new FileEntryInfo
stat.Attributes = new FileAttributes(); {
stat.Attributes = FileAttributes.System; BlockSize = device.GetSectorSize(),
stat.BlockSize = device.GetSectorSize(); DeviceNo = 0,
stat.DeviceNo = 0; GID = 0,
stat.GID = 0; Inode = 0,
stat.Inode = 0; Links = 1,
stat.Links = 1; Mode = 0x124,
stat.Mode = 0x124; UID = 0,
stat.UID = 0; Attributes = FileAttributes.System
};
if(string.Compare(path, "$", StringComparison.InvariantCulture) == 0) if(string.Compare(path, "$", StringComparison.InvariantCulture) == 0)
{ {
@@ -198,30 +193,29 @@ namespace DiscImageChef.Filesystems.AppleMFS
return Errno.NoError; return Errno.NoError;
} }
uint fileID; if(!filenameToId.TryGetValue(path.ToLowerInvariant(), out uint fileId)) return Errno.NoSuchFile;
MFS_FileEntry entry;
if(!filenameToId.TryGetValue(path.ToLowerInvariant(), out fileID)) return Errno.NoSuchFile; if(!idToEntry.TryGetValue(fileId, out MFS_FileEntry entry)) return Errno.NoSuchFile;
if(!idToEntry.TryGetValue(fileID, out entry)) return Errno.NoSuchFile;
FileAttributes attr = new FileAttributes(); FileAttributes attr = new FileAttributes();
Errno error = GetAttributes(path, ref attr); Errno error = GetAttributes(path, ref attr);
if(error != Errno.NoError) return error; if(error != Errno.NoError) return error;
stat = new FileEntryInfo(); stat = new FileEntryInfo
stat.Attributes = attr; {
stat.Blocks = entry.flLgLen / volMDB.drAlBlkSiz; Attributes = attr,
stat.BlockSize = volMDB.drAlBlkSiz; Blocks = entry.flLgLen / volMDB.drAlBlkSiz,
stat.CreationTime = DateHandlers.MacToDateTime(entry.flCrDat); BlockSize = volMDB.drAlBlkSiz,
stat.DeviceNo = 0; CreationTime = DateHandlers.MacToDateTime(entry.flCrDat),
stat.GID = 0; DeviceNo = 0,
stat.Inode = entry.flFlNum; GID = 0,
stat.LastWriteTime = DateHandlers.MacToDateTime(entry.flMdDat); Inode = entry.flFlNum,
stat.Length = entry.flPyLen; LastWriteTime = DateHandlers.MacToDateTime(entry.flMdDat),
stat.Links = 1; Length = entry.flPyLen,
stat.Mode = 0x124; Links = 1,
stat.UID = 0; Mode = 0x124,
UID = 0
};
return Errno.NoError; return Errno.NoError;
} }
@@ -240,12 +234,9 @@ namespace DiscImageChef.Filesystems.AppleMFS
string[] pathElements = path.Split(new[] {'/'}, StringSplitOptions.RemoveEmptyEntries); string[] pathElements = path.Split(new[] {'/'}, StringSplitOptions.RemoveEmptyEntries);
if(pathElements.Length != 1) return Errno.NotSupported; if(pathElements.Length != 1) return Errno.NotSupported;
uint fileID; if(!filenameToId.TryGetValue(path.ToLowerInvariant(), out uint fileId)) return Errno.NoSuchFile;
MFS_FileEntry entry;
if(!filenameToId.TryGetValue(path.ToLowerInvariant(), out fileID)) return Errno.NoSuchFile; if(!idToEntry.TryGetValue(fileId, out MFS_FileEntry entry)) return Errno.NoSuchFile;
if(!idToEntry.TryGetValue(fileID, out entry)) return Errno.NoSuchFile;
uint nextBlock; uint nextBlock;
@@ -271,10 +262,10 @@ namespace DiscImageChef.Filesystems.AppleMFS
} }
MemoryStream ms = new MemoryStream(); MemoryStream ms = new MemoryStream();
byte[] sectors;
do do
{ {
byte[] sectors;
if(tags) if(tags)
sectors = sectors =
device.ReadSectorsTag((ulong)((nextBlock - 2) * sectorsPerBlock) + volMDB.drAlBlSt + partitionStart, device.ReadSectorsTag((ulong)((nextBlock - 2) * sectorsPerBlock) + volMDB.drAlBlSt + partitionStart,

View File

@@ -47,11 +47,11 @@ namespace DiscImageChef.Filesystems.AppleMFS
if(2 + partition.Start >= partition.End) return false; 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; BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian;
drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0x000); drSigWord = BigEndianBitConverter.ToUInt16(mdbSector, 0x000);
return drSigWord == MFS_MAGIC; return drSigWord == MFS_MAGIC;
} }
@@ -67,63 +67,62 @@ namespace DiscImageChef.Filesystems.AppleMFS
MFS_BootBlock BB = new MFS_BootBlock(); MFS_BootBlock BB = new MFS_BootBlock();
byte[] pString = new byte[16]; byte[] pString = new byte[16];
byte[] variable_size;
byte[] mdb_sector = imagePlugin.ReadSector(2 + partition.Start); byte[] mdbSector = imagePlugin.ReadSector(2 + partition.Start);
byte[] bb_sector = imagePlugin.ReadSector(0 + partition.Start); byte[] bbSector = imagePlugin.ReadSector(0 + partition.Start);
BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian;
MDB.drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0x000); MDB.drSigWord = BigEndianBitConverter.ToUInt16(mdbSector, 0x000);
if(MDB.drSigWord != MFS_MAGIC) return; if(MDB.drSigWord != MFS_MAGIC) return;
MDB.drCrDate = BigEndianBitConverter.ToUInt32(mdb_sector, 0x002); MDB.drCrDate = BigEndianBitConverter.ToUInt32(mdbSector, 0x002);
MDB.drLsBkUp = BigEndianBitConverter.ToUInt32(mdb_sector, 0x006); MDB.drLsBkUp = BigEndianBitConverter.ToUInt32(mdbSector, 0x006);
MDB.drAtrb = BigEndianBitConverter.ToUInt16(mdb_sector, 0x00A); MDB.drAtrb = BigEndianBitConverter.ToUInt16(mdbSector, 0x00A);
MDB.drNmFls = BigEndianBitConverter.ToUInt16(mdb_sector, 0x00C); MDB.drNmFls = BigEndianBitConverter.ToUInt16(mdbSector, 0x00C);
MDB.drDirSt = BigEndianBitConverter.ToUInt16(mdb_sector, 0x00E); MDB.drDirSt = BigEndianBitConverter.ToUInt16(mdbSector, 0x00E);
MDB.drBlLen = BigEndianBitConverter.ToUInt16(mdb_sector, 0x010); MDB.drBlLen = BigEndianBitConverter.ToUInt16(mdbSector, 0x010);
MDB.drNmAlBlks = BigEndianBitConverter.ToUInt16(mdb_sector, 0x012); MDB.drNmAlBlks = BigEndianBitConverter.ToUInt16(mdbSector, 0x012);
MDB.drAlBlkSiz = BigEndianBitConverter.ToUInt32(mdb_sector, 0x014); MDB.drAlBlkSiz = BigEndianBitConverter.ToUInt32(mdbSector, 0x014);
MDB.drClpSiz = BigEndianBitConverter.ToUInt32(mdb_sector, 0x018); MDB.drClpSiz = BigEndianBitConverter.ToUInt32(mdbSector, 0x018);
MDB.drAlBlSt = BigEndianBitConverter.ToUInt16(mdb_sector, 0x01C); MDB.drAlBlSt = BigEndianBitConverter.ToUInt16(mdbSector, 0x01C);
MDB.drNxtFNum = BigEndianBitConverter.ToUInt32(mdb_sector, 0x01E); MDB.drNxtFNum = BigEndianBitConverter.ToUInt32(mdbSector, 0x01E);
MDB.drFreeBks = BigEndianBitConverter.ToUInt16(mdb_sector, 0x022); MDB.drFreeBks = BigEndianBitConverter.ToUInt16(mdbSector, 0x022);
MDB.drVNSiz = mdb_sector[0x024]; MDB.drVNSiz = mdbSector[0x024];
variable_size = new byte[MDB.drVNSiz + 1]; byte[] variableSize = new byte[MDB.drVNSiz + 1];
Array.Copy(mdb_sector, 0x024, variable_size, 0, MDB.drVNSiz + 1); Array.Copy(mdbSector, 0x024, variableSize, 0, MDB.drVNSiz + 1);
MDB.drVN = StringHandlers.PascalToString(variable_size, CurrentEncoding); MDB.drVN = StringHandlers.PascalToString(variableSize, CurrentEncoding);
BB.signature = BigEndianBitConverter.ToUInt16(bb_sector, 0x000); BB.signature = BigEndianBitConverter.ToUInt16(bbSector, 0x000);
if(BB.signature == MFSBB_MAGIC) if(BB.signature == MFSBB_MAGIC)
{ {
BB.branch = BigEndianBitConverter.ToUInt32(bb_sector, 0x002); BB.branch = BigEndianBitConverter.ToUInt32(bbSector, 0x002);
BB.boot_flags = bb_sector[0x006]; BB.boot_flags = bbSector[0x006];
BB.boot_version = bb_sector[0x007]; 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); 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); 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); 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); 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); 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); 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.clipbrd_name = StringHandlers.PascalToString(pString, CurrentEncoding);
BB.max_files = BigEndianBitConverter.ToUInt16(bb_sector, 0x07A); BB.max_files = BigEndianBitConverter.ToUInt16(bbSector, 0x07A);
BB.queue_size = BigEndianBitConverter.ToUInt16(bb_sector, 0x07C); BB.queue_size = BigEndianBitConverter.ToUInt16(bbSector, 0x07C);
BB.heap_128k = BigEndianBitConverter.ToUInt32(bb_sector, 0x07E); BB.heap_128k = BigEndianBitConverter.ToUInt32(bbSector, 0x07E);
BB.heap_256k = BigEndianBitConverter.ToUInt32(bb_sector, 0x082); BB.heap_256k = BigEndianBitConverter.ToUInt32(bbSector, 0x082);
BB.heap_512k = BigEndianBitConverter.ToUInt32(bb_sector, 0x086); BB.heap_512k = BigEndianBitConverter.ToUInt32(bbSector, 0x086);
} }
else BB.signature = 0x0000; else BB.signature = 0x0000;
@@ -175,26 +174,26 @@ namespace DiscImageChef.Filesystems.AppleMFS
information = sb.ToString(); information = sb.ToString();
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType();
if(MDB.drLsBkUp > 0) if(MDB.drLsBkUp > 0)
{ {
xmlFSType.BackupDate = DateHandlers.MacToDateTime(MDB.drLsBkUp); XmlFsType.BackupDate = DateHandlers.MacToDateTime(MDB.drLsBkUp);
xmlFSType.BackupDateSpecified = true; XmlFsType.BackupDateSpecified = true;
} }
xmlFSType.Bootable = BB.signature == MFSBB_MAGIC; XmlFsType.Bootable = BB.signature == MFSBB_MAGIC;
xmlFSType.Clusters = MDB.drNmAlBlks; XmlFsType.Clusters = MDB.drNmAlBlks;
xmlFSType.ClusterSize = (int)MDB.drAlBlkSiz; XmlFsType.ClusterSize = (int)MDB.drAlBlkSiz;
if(MDB.drCrDate > 0) if(MDB.drCrDate > 0)
{ {
xmlFSType.CreationDate = DateHandlers.MacToDateTime(MDB.drCrDate); XmlFsType.CreationDate = DateHandlers.MacToDateTime(MDB.drCrDate);
xmlFSType.CreationDateSpecified = true; XmlFsType.CreationDateSpecified = true;
} }
xmlFSType.Files = MDB.drNmFls; XmlFsType.Files = MDB.drNmFls;
xmlFSType.FilesSpecified = true; XmlFsType.FilesSpecified = true;
xmlFSType.FreeClusters = MDB.drFreeBks; XmlFsType.FreeClusters = MDB.drFreeBks;
xmlFSType.FreeClustersSpecified = true; XmlFsType.FreeClustersSpecified = true;
xmlFSType.Type = "MFS"; XmlFsType.Type = "MFS";
xmlFSType.VolumeName = MDB.drVN; XmlFsType.VolumeName = MDB.drVN;
} }
} }
} }

View File

@@ -31,10 +31,14 @@
// ****************************************************************************/ // ****************************************************************************/
using System; using System;
using System.Diagnostics.CodeAnalysis;
#pragma warning disable 169
namespace DiscImageChef.Filesystems.AppleMFS namespace DiscImageChef.Filesystems.AppleMFS
{ {
// Information from Inside Macintosh Volume II // Information from Inside Macintosh Volume II
[SuppressMessage("ReSharper", "InconsistentNaming")]
[SuppressMessage("ReSharper", "NotAccessedField.Local")]
public partial class AppleMFS public partial class AppleMFS
{ {
/// <summary> /// <summary>

View File

@@ -44,8 +44,6 @@ namespace DiscImageChef.Filesystems.AppleMFS
this.debug = debug; this.debug = debug;
volMDB = new MFS_MasterDirectoryBlock(); volMDB = new MFS_MasterDirectoryBlock();
byte[] variable_size;
mdbBlocks = device.ReadSector(2 + partitionStart); mdbBlocks = device.ReadSector(2 + partitionStart);
bootBlocks = device.ReadSector(0 + partitionStart); bootBlocks = device.ReadSector(0 + partitionStart);
@@ -67,19 +65,19 @@ namespace DiscImageChef.Filesystems.AppleMFS
volMDB.drNxtFNum = BigEndianBitConverter.ToUInt32(mdbBlocks, 0x01E); volMDB.drNxtFNum = BigEndianBitConverter.ToUInt32(mdbBlocks, 0x01E);
volMDB.drFreeBks = BigEndianBitConverter.ToUInt16(mdbBlocks, 0x022); volMDB.drFreeBks = BigEndianBitConverter.ToUInt16(mdbBlocks, 0x022);
volMDB.drVNSiz = mdbBlocks[0x024]; volMDB.drVNSiz = mdbBlocks[0x024];
variable_size = new byte[volMDB.drVNSiz + 1]; byte[] variableSize = new byte[volMDB.drVNSiz + 1];
Array.Copy(mdbBlocks, 0x024, variable_size, 0, volMDB.drVNSiz + 1); Array.Copy(mdbBlocks, 0x024, variableSize, 0, volMDB.drVNSiz + 1);
volMDB.drVN = StringHandlers.PascalToString(variable_size, CurrentEncoding); volMDB.drVN = StringHandlers.PascalToString(variableSize, CurrentEncoding);
directoryBlocks = device.ReadSectors(volMDB.drDirSt + partitionStart, volMDB.drBlLen); directoryBlocks = device.ReadSectors(volMDB.drDirSt + partitionStart, volMDB.drBlLen);
int bytesInBlockMap = volMDB.drNmAlBlks * 12 / 8 + volMDB.drNmAlBlks * 12 % 8; int bytesInBlockMap = volMDB.drNmAlBlks * 12 / 8 + volMDB.drNmAlBlks * 12 % 8;
int bytesBeforeBlockMap = 64; const int BYTES_BEFORE_BLOCK_MAP = 64;
int bytesInWholeMDB = bytesInBlockMap + bytesBeforeBlockMap; int bytesInWholeMdb = bytesInBlockMap + BYTES_BEFORE_BLOCK_MAP;
int sectorsInWholeMDB = bytesInWholeMDB / (int)device.ImageInfo.SectorSize + int sectorsInWholeMdb = bytesInWholeMdb / (int)device.ImageInfo.SectorSize +
bytesInWholeMDB % (int)device.ImageInfo.SectorSize; bytesInWholeMdb % (int)device.ImageInfo.SectorSize;
byte[] wholeMDB = device.ReadSectors(partitionStart + 2, (uint)sectorsInWholeMDB); byte[] wholeMdb = device.ReadSectors(partitionStart + 2, (uint)sectorsInWholeMdb);
blockMapBytes = new byte[bytesInBlockMap]; 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; int offset = 0;
blockMap = new uint[volMDB.drNmAlBlks + 2 + 1]; blockMap = new uint[volMDB.drNmAlBlks + 2 + 1];
@@ -113,7 +111,7 @@ namespace DiscImageChef.Filesystems.AppleMFS
bootTags = device.ReadSectorTag(0 + partitionStart, SectorTagType.AppleSectorTag); bootTags = device.ReadSectorTag(0 + partitionStart, SectorTagType.AppleSectorTag);
directoryTags = device.ReadSectorsTag(volMDB.drDirSt + partitionStart, volMDB.drBlLen, directoryTags = device.ReadSectorsTag(volMDB.drDirSt + partitionStart, volMDB.drBlLen,
SectorTagType.AppleSectorTag); SectorTagType.AppleSectorTag);
bitmapTags = device.ReadSectorsTag(partitionStart + 2, (uint)sectorsInWholeMDB, bitmapTags = device.ReadSectorsTag(partitionStart + 2, (uint)sectorsInWholeMdb,
SectorTagType.AppleSectorTag); SectorTagType.AppleSectorTag);
} }
@@ -127,26 +125,26 @@ namespace DiscImageChef.Filesystems.AppleMFS
if(bbSig != MFSBB_MAGIC) bootBlocks = null; if(bbSig != MFSBB_MAGIC) bootBlocks = null;
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType();
if(volMDB.drLsBkUp > 0) if(volMDB.drLsBkUp > 0)
{ {
xmlFSType.BackupDate = DateHandlers.MacToDateTime(volMDB.drLsBkUp); XmlFsType.BackupDate = DateHandlers.MacToDateTime(volMDB.drLsBkUp);
xmlFSType.BackupDateSpecified = true; XmlFsType.BackupDateSpecified = true;
} }
xmlFSType.Bootable = bbSig == MFSBB_MAGIC; XmlFsType.Bootable = bbSig == MFSBB_MAGIC;
xmlFSType.Clusters = volMDB.drNmAlBlks; XmlFsType.Clusters = volMDB.drNmAlBlks;
xmlFSType.ClusterSize = (int)volMDB.drAlBlkSiz; XmlFsType.ClusterSize = (int)volMDB.drAlBlkSiz;
if(volMDB.drCrDate > 0) if(volMDB.drCrDate > 0)
{ {
xmlFSType.CreationDate = DateHandlers.MacToDateTime(volMDB.drCrDate); XmlFsType.CreationDate = DateHandlers.MacToDateTime(volMDB.drCrDate);
xmlFSType.CreationDateSpecified = true; XmlFsType.CreationDateSpecified = true;
} }
xmlFSType.Files = volMDB.drNmFls; XmlFsType.Files = volMDB.drNmFls;
xmlFSType.FilesSpecified = true; XmlFsType.FilesSpecified = true;
xmlFSType.FreeClusters = volMDB.drFreeBks; XmlFsType.FreeClusters = volMDB.drFreeBks;
xmlFSType.FreeClustersSpecified = true; XmlFsType.FreeClustersSpecified = true;
xmlFSType.Type = "MFS"; XmlFsType.Type = "MFS";
xmlFSType.VolumeName = volMDB.drVN; XmlFsType.VolumeName = volMDB.drVN;
return Errno.NoError; return Errno.NoError;
} }
@@ -169,14 +167,16 @@ namespace DiscImageChef.Filesystems.AppleMFS
public override Errno StatFs(ref FileSystemInfo stat) public override Errno StatFs(ref FileSystemInfo stat)
{ {
stat = new FileSystemInfo(); stat = new FileSystemInfo
stat.Blocks = volMDB.drNmAlBlks; {
stat.FilenameLength = 255; Blocks = volMDB.drNmAlBlks,
stat.Files = volMDB.drNmFls; FilenameLength = 255,
stat.FreeBlocks = volMDB.drFreeBks; Files = volMDB.drNmFls,
FreeBlocks = volMDB.drFreeBks,
PluginId = PluginUuid,
Type = "Apple MFS"
};
stat.FreeFiles = uint.MaxValue - stat.Files; stat.FreeFiles = uint.MaxValue - stat.Files;
stat.PluginId = PluginUUID;
stat.Type = "Apple MFS";
return Errno.NoError; return Errno.NoError;
} }

View File

@@ -61,12 +61,9 @@ namespace DiscImageChef.Filesystems.AppleMFS
return Errno.NoError; return Errno.NoError;
} }
uint fileID; if(!filenameToId.TryGetValue(path.ToLowerInvariant(), out uint fileId)) return Errno.NoSuchFile;
MFS_FileEntry entry;
if(!filenameToId.TryGetValue(path.ToLowerInvariant(), out fileID)) return Errno.NoSuchFile; if(!idToEntry.TryGetValue(fileId, out MFS_FileEntry entry)) return Errno.NoSuchFile;
if(!idToEntry.TryGetValue(fileID, out entry)) return Errno.NoSuchFile;
if(entry.flRLgLen > 0) if(entry.flRLgLen > 0)
{ {
@@ -130,13 +127,11 @@ namespace DiscImageChef.Filesystems.AppleMFS
} }
else return Errno.NoSuchExtendedAttribute; else return Errno.NoSuchExtendedAttribute;
uint fileID;
MFS_FileEntry entry;
Errno error; 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 && if(entry.flRLgLen > 0 &&
string.Compare(xattr, "com.apple.ResourceFork", StringComparison.InvariantCulture) == 0) string.Compare(xattr, "com.apple.ResourceFork", StringComparison.InvariantCulture) == 0)

View File

@@ -53,24 +53,22 @@ namespace DiscImageChef.Filesystems
public AtheOS() public AtheOS()
{ {
Name = "AtheOS Filesystem"; 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"); CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
} }
public AtheOS(Encoding encoding) public AtheOS(Encoding encoding)
{ {
Name = "AtheOS Filesystem"; Name = "AtheOS Filesystem";
PluginUUID = new Guid("AAB2C4F1-DC07-49EE-A948-576CC51B58C5"); PluginUuid = new Guid("AAB2C4F1-DC07-49EE-A948-576CC51B58C5");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public AtheOS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public AtheOS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "AtheOS Filesystem"; Name = "AtheOS Filesystem";
PluginUUID = new Guid("AAB2C4F1-DC07-49EE-A948-576CC51B58C5"); PluginUuid = new Guid("AAB2C4F1-DC07-49EE-A948-576CC51B58C5");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public override bool Identify(ImagePlugin imagePlugin, Partition partition) public override bool Identify(ImagePlugin imagePlugin, Partition partition)
@@ -87,10 +85,10 @@ namespace DiscImageChef.Filesystems
uint magic; uint magic;
byte[] tmp = imagePlugin.ReadSectors(sector + partition.Start, run); byte[] tmp = imagePlugin.ReadSectors(sector + partition.Start, run);
byte[] sb_sector = new byte[AFS_SUPERBLOCK_SIZE]; byte[] sbSector = new byte[AFS_SUPERBLOCK_SIZE];
Array.Copy(tmp, offset, sb_sector, 0, 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; return magic == AFS_MAGIC1;
} }
@@ -102,8 +100,6 @@ namespace DiscImageChef.Filesystems
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
AtheosSuperBlock afs_sb;
ulong sector = AFS_BOOTBLOCK_SIZE / imagePlugin.GetSectorSize(); ulong sector = AFS_BOOTBLOCK_SIZE / imagePlugin.GetSectorSize();
uint offset = AFS_BOOTBLOCK_SIZE % imagePlugin.GetSectorSize(); uint offset = AFS_BOOTBLOCK_SIZE % imagePlugin.GetSectorSize();
uint run = 1; uint run = 1;
@@ -112,58 +108,58 @@ namespace DiscImageChef.Filesystems
run = AFS_SUPERBLOCK_SIZE / imagePlugin.GetSectorSize(); run = AFS_SUPERBLOCK_SIZE / imagePlugin.GetSectorSize();
byte[] tmp = imagePlugin.ReadSectors(sector + partition.Start, run); byte[] tmp = imagePlugin.ReadSectors(sector + partition.Start, run);
byte[] sb_sector = new byte[AFS_SUPERBLOCK_SIZE]; byte[] sbSector = new byte[AFS_SUPERBLOCK_SIZE];
Array.Copy(tmp, offset, sb_sector, 0, AFS_SUPERBLOCK_SIZE); Array.Copy(tmp, offset, sbSector, 0, AFS_SUPERBLOCK_SIZE);
GCHandle handle = GCHandle.Alloc(sb_sector, GCHandleType.Pinned); GCHandle handle = GCHandle.Alloc(sbSector, GCHandleType.Pinned);
afs_sb = (AtheosSuperBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(AtheosSuperBlock)); AtheosSuperBlock afsSb = (AtheosSuperBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(AtheosSuperBlock));
handle.Free(); handle.Free();
sb.AppendLine("Atheos filesystem"); 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("Volume name: {0}", StringHandlers.CToString(afsSb.name, CurrentEncoding)).AppendLine();
sb.AppendFormat("{0} bytes per block", afs_sb.block_size).AppendLine(); sb.AppendFormat("{0} bytes per block", afsSb.block_size).AppendLine();
sb.AppendFormat("{0} blocks in volume ({1} bytes)", afs_sb.num_blocks, sb.AppendFormat("{0} blocks in volume ({1} bytes)", afsSb.num_blocks,
afs_sb.num_blocks * afs_sb.block_size).AppendLine(); afsSb.num_blocks * afsSb.block_size).AppendLine();
sb.AppendFormat("{0} used blocks ({1} bytes)", afs_sb.used_blocks, afs_sb.used_blocks * afs_sb.block_size) sb.AppendFormat("{0} used blocks ({1} bytes)", afsSb.used_blocks, afsSb.used_blocks * afsSb.block_size)
.AppendLine(); .AppendLine();
sb.AppendFormat("{0} bytes per i-node", afs_sb.inode_size).AppendLine(); sb.AppendFormat("{0} bytes per i-node", afsSb.inode_size).AppendLine();
sb.AppendFormat("{0} blocks per allocation group ({1} bytes)", afs_sb.blocks_per_ag, sb.AppendFormat("{0} blocks per allocation group ({1} bytes)", afsSb.blocks_per_ag,
afs_sb.blocks_per_ag * afs_sb.block_size).AppendLine(); afsSb.blocks_per_ag * afsSb.block_size).AppendLine();
sb.AppendFormat("{0} allocation groups in volume", afs_sb.num_ags).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)", 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, afsSb.log_blocks_start, afsSb.log_blocks_ag, afsSb.log_blocks_len,
afs_sb.log_blocks_len * afs_sb.block_size).AppendLine(); afsSb.log_blocks_len * afsSb.block_size).AppendLine();
sb.AppendFormat("Journal starts in byte {0} and has {1} bytes in {2} blocks", afs_sb.log_start, sb.AppendFormat("Journal starts in byte {0} and has {1} bytes in {2} blocks", afsSb.log_start,
afs_sb.log_size, afs_sb.log_valid_blocks).AppendLine(); afsSb.log_size, afsSb.log_valid_blocks).AppendLine();
sb sb
.AppendFormat("Root folder's i-node resides in block {0} of allocation group {1} and runs for {2} blocks ({3} bytes)", .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, afsSb.root_dir_start, afsSb.root_dir_ag, afsSb.root_dir_len,
afs_sb.root_dir_len * afs_sb.block_size).AppendLine(); afsSb.root_dir_len * afsSb.block_size).AppendLine();
sb 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)", .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, afsSb.deleted_start, afsSb.deleted_ag, afsSb.deleted_len,
afs_sb.deleted_len * afs_sb.block_size).AppendLine(); afsSb.deleted_len * afsSb.block_size).AppendLine();
sb sb
.AppendFormat("Indices' i-node resides in block {0} of allocation group {1} and runs for {2} blocks ({3} bytes)", .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, afsSb.indices_start, afsSb.indices_ag, afsSb.indices_len,
afs_sb.indices_len * afs_sb.block_size).AppendLine(); afsSb.indices_len * afsSb.block_size).AppendLine();
sb.AppendFormat("{0} blocks for bootloader ({1} bytes)", afs_sb.boot_size, sb.AppendFormat("{0} blocks for bootloader ({1} bytes)", afsSb.boot_size,
afs_sb.boot_size * afs_sb.block_size).AppendLine(); afsSb.boot_size * afsSb.block_size).AppendLine();
information = sb.ToString(); information = sb.ToString();
xmlFSType = new FileSystemType XmlFsType = new FileSystemType
{ {
Clusters = afs_sb.num_blocks, Clusters = afsSb.num_blocks,
ClusterSize = (int)afs_sb.block_size, ClusterSize = (int)afsSb.block_size,
Dirty = false, Dirty = false,
FreeClusters = afs_sb.num_blocks - afs_sb.used_blocks, FreeClusters = afsSb.num_blocks - afsSb.used_blocks,
FreeClustersSpecified = true, FreeClustersSpecified = true,
Type = "AtheOS filesystem", Type = "AtheOS filesystem",
VolumeName = StringHandlers.CToString(afs_sb.name, CurrentEncoding) VolumeName = StringHandlers.CToString(afsSb.name, CurrentEncoding)
}; };
} }

View File

@@ -58,24 +58,22 @@ namespace DiscImageChef.Filesystems
public BeFS() public BeFS()
{ {
Name = "Be Filesystem"; 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"); CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
} }
public BeFS(Encoding encoding) public BeFS(Encoding encoding)
{ {
Name = "Be Filesystem"; Name = "Be Filesystem";
PluginUUID = new Guid("dc8572b3-b6ad-46e4-8de9-cbe123ff6672"); PluginUuid = new Guid("dc8572b3-b6ad-46e4-8de9-cbe123ff6672");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public BeFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public BeFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "Be Filesystem"; Name = "Be Filesystem";
PluginUUID = new Guid("dc8572b3-b6ad-46e4-8de9-cbe123ff6672"); PluginUuid = new Guid("dc8572b3-b6ad-46e4-8de9-cbe123ff6672");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public override bool Identify(ImagePlugin imagePlugin, Partition partition) public override bool Identify(ImagePlugin imagePlugin, Partition partition)
@@ -83,58 +81,55 @@ namespace DiscImageChef.Filesystems
if(2 + partition.Start >= partition.End) return false; if(2 + partition.Start >= partition.End) return false;
uint magic; 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 = BitConverter.ToUInt32(sbSector, 0x20);
magic_be = BigEndianBitConverter.ToUInt32(sb_sector, 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 = BitConverter.ToUInt32(sbSector, 0x220);
magic_be = BigEndianBitConverter.ToUInt32(sb_sector, 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 = BitConverter.ToUInt32(sbSector, 0x20);
magic_be = BigEndianBitConverter.ToUInt32(sb_sector, 0x20); magicBe = BigEndianBitConverter.ToUInt32(sbSector, 0x20);
if(magic == BEFS_MAGIC1 || magic_be == BEFS_MAGIC1) return true; return magic == BEFS_MAGIC1 || magicBe == BEFS_MAGIC1;
return false;
} }
public override void GetInformation(ImagePlugin imagePlugin, Partition partition, public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
out string information) out string information)
{ {
information = ""; information = "";
byte[] name_bytes = new byte[32];
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
BeSuperBlock besb = new BeSuperBlock(); BeSuperBlock besb = new BeSuperBlock();
byte[] sb_sector = imagePlugin.ReadSector(0 + partition.Start); byte[] sbSector = imagePlugin.ReadSector(0 + partition.Start);
bool littleEndian; 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 if(besb.magic1 == BEFS_MAGIC1 || besb.magic1 == BEFS_CIGAM1) // Magic is at offset
littleEndian = besb.magic1 == BEFS_CIGAM1; littleEndian = besb.magic1 == BEFS_CIGAM1;
else else
{ {
sb_sector = imagePlugin.ReadSector(1 + partition.Start); sbSector = imagePlugin.ReadSector(1 + partition.Start);
besb.magic1 = BigEndianBitConverter.ToUInt32(sb_sector, 0x20); besb.magic1 = BigEndianBitConverter.ToUInt32(sbSector, 0x20);
if(besb.magic1 == BEFS_MAGIC1 || besb.magic1 == BEFS_CIGAM1) // There is a boot sector if(besb.magic1 == BEFS_MAGIC1 || besb.magic1 == BEFS_CIGAM1) // There is a boot sector
littleEndian = besb.magic1 == BEFS_CIGAM1; littleEndian = besb.magic1 == BEFS_CIGAM1;
else if(sb_sector.Length >= 0x400) else if(sbSector.Length >= 0x400)
{ {
byte[] temp = imagePlugin.ReadSector(0 + partition.Start); byte[] temp = imagePlugin.ReadSector(0 + partition.Start);
besb.magic1 = BigEndianBitConverter.ToUInt32(temp, 0x220); 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 if(besb.magic1 == BEFS_MAGIC1 || besb.magic1 == BEFS_CIGAM1) // There is a boot sector
{ {
littleEndian = besb.magic1 == BEFS_CIGAM1; littleEndian = besb.magic1 == BEFS_CIGAM1;
sb_sector = new byte[0x200]; sbSector = new byte[0x200];
Array.Copy(temp, 0x200, sb_sector, 0, 0x200); Array.Copy(temp, 0x200, sbSector, 0, 0x200);
} }
else return; else return;
} }
@@ -152,15 +147,13 @@ namespace DiscImageChef.Filesystems
if(littleEndian) 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)); besb = (BeSuperBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(BeSuperBlock));
handle.Free(); handle.Free();
} }
else besb = BigEndianMarshal.ByteArrayToStructureBigEndian<BeSuperBlock>(sb_sector); else besb = BigEndianMarshal.ByteArrayToStructureBigEndian<BeSuperBlock>(sbSector);
if(littleEndian) // Big-endian filesystem sb.AppendLine(littleEndian ? "Little-endian BeFS" : "Big-endian BeFS");
sb.AppendLine("Little-endian BeFS");
else sb.AppendLine("Big-endian BeFS");
if(besb.magic1 != BEFS_MAGIC1 || besb.fs_byte_order != BEFS_ENDIAN || besb.magic2 != BEFS_MAGIC2 || 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 || besb.magic3 != BEFS_MAGIC3 || besb.root_dir_len != 1 || besb.indices_len != 1 ||
@@ -180,8 +173,7 @@ namespace DiscImageChef.Filesystems
switch(besb.flags) { switch(besb.flags) {
case BEFS_CLEAN: case BEFS_CLEAN:
if(besb.log_start == besb.log_end) sb.AppendLine("Filesystem is clean"); sb.AppendLine(besb.log_start == besb.log_end ? "Filesystem is clean" : "Filesystem is dirty");
else sb.AppendLine("Filesystem is dirty");
break; break;
case BEFS_DIRTY: sb.AppendLine("Filesystem is dirty"); case BEFS_DIRTY: sb.AppendLine("Filesystem is dirty");
break; break;
@@ -215,14 +207,16 @@ namespace DiscImageChef.Filesystems
information = sb.ToString(); information = sb.ToString();
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType
xmlFSType.Clusters = besb.num_blocks; {
xmlFSType.ClusterSize = (int)besb.block_size; Clusters = besb.num_blocks,
xmlFSType.Dirty = besb.flags == BEFS_DIRTY; ClusterSize = (int)besb.block_size,
xmlFSType.FreeClusters = besb.num_blocks - besb.used_blocks; Dirty = besb.flags == BEFS_DIRTY,
xmlFSType.FreeClustersSpecified = true; FreeClusters = besb.num_blocks - besb.used_blocks,
xmlFSType.Type = "BeFS"; FreeClustersSpecified = true,
xmlFSType.VolumeName = StringHandlers.CToString(besb.name, CurrentEncoding); Type = "BeFS",
VolumeName = StringHandlers.CToString(besb.name, CurrentEncoding)
};
} }
/// <summary> /// <summary>

View File

@@ -51,24 +51,22 @@ namespace DiscImageChef.Filesystems
public BTRFS() public BTRFS()
{ {
Name = "B-tree file system"; 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"); CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
} }
public BTRFS(Encoding encoding) public BTRFS(Encoding encoding)
{ {
Name = "B-tree file system"; Name = "B-tree file system";
PluginUUID = new Guid("C904CF15-5222-446B-B7DB-02EAC5D781B3"); PluginUuid = new Guid("C904CF15-5222-446B-B7DB-02EAC5D781B3");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public BTRFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public BTRFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "B-tree file system"; Name = "B-tree file system";
PluginUUID = new Guid("C904CF15-5222-446B-B7DB-02EAC5D781B3"); PluginUuid = new Guid("C904CF15-5222-446B-B7DB-02EAC5D781B3");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
[StructLayout(LayoutKind.Sequential, Pack = 1)] [StructLayout(LayoutKind.Sequential, Pack = 1)]
@@ -159,17 +157,16 @@ namespace DiscImageChef.Filesystems
out string information) out string information)
{ {
StringBuilder sbInformation = new StringBuilder(); StringBuilder sbInformation = new StringBuilder();
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType();
information = ""; information = "";
ulong sbSectorOff = 0x10000 / imagePlugin.GetSectorSize(); ulong sbSectorOff = 0x10000 / imagePlugin.GetSectorSize();
uint sbSectorSize = 0x1000 / imagePlugin.GetSectorSize(); uint sbSectorSize = 0x1000 / imagePlugin.GetSectorSize();
byte[] sector = imagePlugin.ReadSectors(sbSectorOff + partition.Start, sbSectorSize); byte[] sector = imagePlugin.ReadSectors(sbSectorOff + partition.Start, sbSectorSize);
SuperBlock btrfsSb;
GCHandle handle = GCHandle.Alloc(sector, GCHandleType.Pinned); 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(); handle.Free();
DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.checksum = {0}", btrfsSb.checksum); DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.checksum = {0}", btrfsSb.checksum);
@@ -243,15 +240,17 @@ namespace DiscImageChef.Filesystems
information = sbInformation.ToString(); information = sbInformation.ToString();
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType
xmlFSType.Clusters = (long)(btrfsSb.total_bytes / btrfsSb.sectorsize); {
xmlFSType.ClusterSize = (int)btrfsSb.sectorsize; Clusters = (long)(btrfsSb.total_bytes / btrfsSb.sectorsize),
xmlFSType.FreeClusters = xmlFSType.Clusters - (long)(btrfsSb.bytes_used / btrfsSb.sectorsize); ClusterSize = (int)btrfsSb.sectorsize,
xmlFSType.FreeClustersSpecified = true; FreeClustersSpecified = true,
xmlFSType.VolumeName = btrfsSb.label; VolumeName = btrfsSb.label,
xmlFSType.VolumeSerial = $"{btrfsSb.uuid}"; VolumeSerial = $"{btrfsSb.uuid}",
xmlFSType.VolumeSetIdentifier = $"{btrfsSb.dev_item.device_uuid}"; VolumeSetIdentifier = $"{btrfsSb.dev_item.device_uuid}",
xmlFSType.Type = Name; Type = Name
};
XmlFsType.FreeClusters = XmlFsType.Clusters - (long)(btrfsSb.bytes_used / btrfsSb.sectorsize);
} }
public override Errno Mount() public override Errno Mount()

View File

@@ -47,21 +47,21 @@ namespace DiscImageChef.Filesystems
public CBM() public CBM()
{ {
Name = "Commodore file system"; Name = "Commodore file system";
PluginUUID = new Guid("D104744E-A376-450C-BAC0-1347C93F983B"); PluginUuid = new Guid("D104744E-A376-450C-BAC0-1347C93F983B");
CurrentEncoding = new PETSCII(); CurrentEncoding = new PETSCII();
} }
public CBM(Encoding encoding) public CBM(Encoding encoding)
{ {
Name = "Commodore file system"; Name = "Commodore file system";
PluginUUID = new Guid("D104744E-A376-450C-BAC0-1347C93F983B"); PluginUuid = new Guid("D104744E-A376-450C-BAC0-1347C93F983B");
CurrentEncoding = new PETSCII(); CurrentEncoding = new PETSCII();
} }
public CBM(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public CBM(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "Commodore file system"; Name = "Commodore file system";
PluginUUID = new Guid("D104744E-A376-450C-BAC0-1347C93F983B"); PluginUuid = new Guid("D104744E-A376-450C-BAC0-1347C93F983B");
CurrentEncoding = new PETSCII(); CurrentEncoding = new PETSCII();
} }
@@ -231,10 +231,12 @@ namespace DiscImageChef.Filesystems
sbInformation.AppendLine("Commodore file system"); sbInformation.AppendLine("Commodore file system");
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType
xmlFSType.Type = "Commodore file system"; {
xmlFSType.Clusters = (long)imagePlugin.ImageInfo.Sectors; Type = "Commodore file system",
xmlFSType.ClusterSize = 256; Clusters = (long)imagePlugin.ImageInfo.Sectors,
ClusterSize = 256
};
if(imagePlugin.ImageInfo.Sectors == 3200) if(imagePlugin.ImageInfo.Sectors == 3200)
{ {
@@ -258,8 +260,8 @@ namespace DiscImageChef.Filesystems
sbInformation.AppendFormat("Disk name: {0}", StringHandlers.CToString(cbmHdr.name, CurrentEncoding)) sbInformation.AppendFormat("Disk name: {0}", StringHandlers.CToString(cbmHdr.name, CurrentEncoding))
.AppendLine(); .AppendLine();
xmlFSType.VolumeName = StringHandlers.CToString(cbmHdr.name, CurrentEncoding); XmlFsType.VolumeName = StringHandlers.CToString(cbmHdr.name, CurrentEncoding);
xmlFSType.VolumeSerial = $"{cbmHdr.diskId}"; XmlFsType.VolumeSerial = $"{cbmHdr.diskId}";
} }
else else
{ {
@@ -281,8 +283,8 @@ namespace DiscImageChef.Filesystems
sbInformation.AppendFormat("Disk name: {0}", StringHandlers.CToString(cbmBam.name, CurrentEncoding)) sbInformation.AppendFormat("Disk name: {0}", StringHandlers.CToString(cbmBam.name, CurrentEncoding))
.AppendLine(); .AppendLine();
xmlFSType.VolumeName = StringHandlers.CToString(cbmBam.name, CurrentEncoding); XmlFsType.VolumeName = StringHandlers.CToString(cbmBam.name, CurrentEncoding);
xmlFSType.VolumeSerial = $"{cbmBam.diskId}"; XmlFsType.VolumeSerial = $"{cbmBam.diskId}";
} }
information = sbInformation.ToString(); information = sbInformation.ToString();

View File

@@ -113,16 +113,15 @@ namespace DiscImageChef.Filesystems.CPM
public CPM() public CPM()
{ {
Name = "CP/M File System"; 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"); CurrentEncoding = Encoding.GetEncoding("IBM437");
} }
public CPM(Encoding encoding) public CPM(Encoding encoding)
{ {
Name = "CP/M File System"; Name = "CP/M File System";
PluginUUID = new Guid("AA2B8585-41DF-4E3B-8A35-D1A935E2F8A1"); PluginUuid = new Guid("AA2B8585-41DF-4E3B-8A35-D1A935E2F8A1");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("IBM437"); CurrentEncoding = encoding ?? Encoding.GetEncoding("IBM437");
else CurrentEncoding = encoding;
} }
public CPM(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public CPM(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
@@ -130,9 +129,8 @@ namespace DiscImageChef.Filesystems.CPM
device = imagePlugin; device = imagePlugin;
this.partition = partition; this.partition = partition;
Name = "CP/M File System"; Name = "CP/M File System";
PluginUUID = new Guid("AA2B8585-41DF-4E3B-8A35-D1A935E2F8A1"); PluginUuid = new Guid("AA2B8585-41DF-4E3B-8A35-D1A935E2F8A1");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("IBM437"); CurrentEncoding = encoding ?? Encoding.GetEncoding("IBM437");
else CurrentEncoding = encoding;
} }
} }
} }

View File

@@ -59,18 +59,14 @@ namespace DiscImageChef.Filesystems.CPM
{ {
if(def.side1 == null) if(def.side1 == null)
{ {
def.side1 = new Side(); def.side1 = new Side {sideId = 0, sectorIds = new int[def.sectorsPerTrack]};
def.side1.sideId = 0;
def.side1.sectorIds = new int[def.sectorsPerTrack];
for(int i = 0; i < def.sectorsPerTrack; i++) def.side1.sectorIds[i] = i + 1; for(int i = 0; i < def.sectorsPerTrack; i++) def.side1.sectorIds[i] = i + 1;
} }
if(def.sides != 2 || def.side2 != null) continue; if(def.sides != 2 || def.side2 != null) continue;
{ {
def.side2 = new Side(); def.side2 = new Side {sideId = 1, sectorIds = new int[def.sectorsPerTrack]};
def.side2.sideId = 1;
def.side2.sectorIds = new int[def.sectorsPerTrack];
for(int i = 0; i < def.sectorsPerTrack; i++) def.side2.sectorIds[i] = i + 1; for(int i = 0; i < def.sectorsPerTrack; i++) def.side2.sectorIds[i] = i + 1;
} }
} }

View File

@@ -69,10 +69,9 @@ namespace DiscImageChef.Filesystems.CPM
for(int off = 0; off < directory.Length; off += 32) for(int off = 0; off < directory.Length; off += 32)
{ {
DirectoryEntry entry;
IntPtr dirPtr = Marshal.AllocHGlobal(32); IntPtr dirPtr = Marshal.AllocHGlobal(32);
Marshal.Copy(directory, off, dirPtr, 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); Marshal.FreeHGlobal(dirPtr);
if((entry.statusUser & 0x7F) < 0x20) if((entry.statusUser & 0x7F) < 0x20)

View File

@@ -43,8 +43,6 @@ namespace DiscImageChef.Filesystems.CPM
string[] pathElements = path.Split(new[] {'/'}, StringSplitOptions.RemoveEmptyEntries); string[] pathElements = path.Split(new[] {'/'}, StringSplitOptions.RemoveEmptyEntries);
if(pathElements.Length != 1) return Errno.NotSupported; if(pathElements.Length != 1) return Errno.NotSupported;
FileEntryInfo fInfo;
if(string.IsNullOrEmpty(pathElements[0]) || if(string.IsNullOrEmpty(pathElements[0]) ||
string.Compare(pathElements[0], "/", StringComparison.OrdinalIgnoreCase) == 0) string.Compare(pathElements[0], "/", StringComparison.OrdinalIgnoreCase) == 0)
{ {
@@ -53,18 +51,16 @@ namespace DiscImageChef.Filesystems.CPM
return Errno.NoError; 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; attributes = fInfo.Attributes;
return Errno.NoError; return Errno.NoError;
} }
// TODO: Implementing this would require storing the interleaving
public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock)
{ {
if(!mounted) return Errno.AccessDenied; return !mounted ? Errno.AccessDenied : Errno.NotImplemented;
// TODO: Implementing this would require storing the interleaving
return Errno.NotImplemented;
} }
public override Errno Read(string path, long offset, long size, ref byte[] buf) 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); string[] pathElements = path.Split(new[] {'/'}, StringSplitOptions.RemoveEmptyEntries);
if(pathElements.Length != 1) return Errno.NotSupported; if(pathElements.Length != 1) return Errno.NotSupported;
byte[] file; if(!fileCache.TryGetValue(pathElements[0].ToUpperInvariant(), out byte[] file)) return Errno.NoSuchFile;
if(!fileCache.TryGetValue(pathElements[0].ToUpperInvariant(), out file)) return Errno.NoSuchFile;
if(offset >= file.Length) return Errno.EINVAL; if(offset >= file.Length) return Errno.EINVAL;
@@ -114,7 +108,7 @@ namespace DiscImageChef.Filesystems.CPM
if(labelCreationDate != null) stat.CreationTime = DateHandlers.CPMToDateTime(labelCreationDate); if(labelCreationDate != null) stat.CreationTime = DateHandlers.CPMToDateTime(labelCreationDate);
if(labelUpdateDate != null) stat.StatusChangeTime = DateHandlers.CPMToDateTime(labelUpdateDate); if(labelUpdateDate != null) stat.StatusChangeTime = DateHandlers.CPMToDateTime(labelUpdateDate);
stat.Attributes = FileAttributes.Directory; stat.Attributes = FileAttributes.Directory;
stat.BlockSize = xmlFSType.ClusterSize; stat.BlockSize = XmlFsType.ClusterSize;
return Errno.NoError; return Errno.NoError;
} }

View File

@@ -164,9 +164,7 @@ namespace DiscImageChef.Filesystems.CPM
try try
{ {
byte[] sector; byte[] sector;
ulong sectorCount;
ulong sectorSize; ulong sectorSize;
ulong sides;
ulong firstDirectorySector; ulong firstDirectorySector;
byte[] directory = null; byte[] directory = null;
workingDefinition = null; workingDefinition = null;
@@ -200,8 +198,8 @@ namespace DiscImageChef.Filesystems.CPM
amsSb.format == 2 && (amsSb.sidedness & 0x02) == 2) amsSb.format == 2 && (amsSb.sidedness & 0x02) == 2)
{ {
// Calculate device limits // Calculate device limits
sides = (ulong)(amsSb.format == 0 ? 1 : 2); ulong sides = (ulong)(amsSb.format == 0 ? 1 : 2);
sectorCount = (ulong)(amsSb.tps * amsSb.spt * (byte)sides); ulong sectorCount = (ulong)(amsSb.tps * amsSb.spt * (byte)sides);
sectorSize = (ulong)(128 << amsSb.psh); sectorSize = (ulong)(128 << amsSb.psh);
// Compare device limits from superblock to real limits // Compare device limits from superblock to real limits
@@ -211,10 +209,12 @@ namespace DiscImageChef.Filesystems.CPM
firstDirectorySector = (ulong)(amsSb.off * amsSb.spt); firstDirectorySector = (ulong)(amsSb.off * amsSb.spt);
// Build a DiscParameterBlock // Build a DiscParameterBlock
dpb = new DiscParameterBlock(); dpb = new DiscParameterBlock
dpb.al0 = sectorCount == 1440 ? (byte)0xF0 : (byte)0xC0; {
dpb.spt = amsSb.spt; al0 = sectorCount == 1440 ? (byte)0xF0 : (byte)0xC0,
dpb.bsh = amsSb.bsh; spt = amsSb.spt,
bsh = amsSb.bsh
};
for(int i = 0; i < dpb.bsh; i++) dpb.blm += (byte)Math.Pow(2, i); for(int i = 0; i < dpb.bsh; i++) dpb.blm += (byte)Math.Pow(2, i);
if(sectorCount >= 1440) if(sectorCount >= 1440)
@@ -239,27 +239,27 @@ namespace DiscImageChef.Filesystems.CPM
directoryLength); directoryLength);
// Build a CP/M disk definition // Build a CP/M disk definition
workingDefinition = new CpmDefinition(); workingDefinition = new CpmDefinition
workingDefinition.al0 = dpb.al0; {
workingDefinition.al1 = dpb.al1; al0 = dpb.al0,
workingDefinition.bitrate = "LOW"; al1 = dpb.al1,
workingDefinition.blm = dpb.blm; bitrate = "LOW",
workingDefinition.bsh = dpb.bsh; blm = dpb.blm,
workingDefinition.bytesPerSector = 512; bsh = dpb.bsh,
workingDefinition.cylinders = amsSb.tps; bytesPerSector = 512,
workingDefinition.drm = dpb.drm; cylinders = amsSb.tps,
workingDefinition.dsm = dpb.dsm; drm = dpb.drm,
workingDefinition.encoding = "MFM"; dsm = dpb.dsm,
workingDefinition.evenOdd = false; encoding = "MFM",
workingDefinition.exm = dpb.exm; evenOdd = false,
workingDefinition.label = null; exm = dpb.exm,
workingDefinition.comment = "Amstrad PCW superblock"; label = null,
workingDefinition.ofs = dpb.off; comment = "Amstrad PCW superblock",
workingDefinition.sectorsPerTrack = amsSb.spt; 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; for(int si = 0; si < amsSb.spt; si++) workingDefinition.side1.sectorIds[si] = si + 1;
if(amsSb.format == 2) if(amsSb.format == 2)
@@ -273,9 +273,7 @@ namespace DiscImageChef.Filesystems.CPM
break; break;
} }
workingDefinition.side2 = new Side(); workingDefinition.side2 = new Side {sideId = 1, sectorIds = new int[amsSb.spt]};
workingDefinition.side2.sideId = 1;
workingDefinition.side2.sectorIds = new int[amsSb.spt];
for(int si = 0; si < amsSb.spt; si++) workingDefinition.side2.sectorIds[si] = si + 1; for(int si = 0; si < amsSb.spt; si++) workingDefinition.side2.sectorIds[si] = si + 1;
} }
else workingDefinition.order = null; else workingDefinition.order = null;
@@ -323,56 +321,59 @@ namespace DiscImageChef.Filesystems.CPM
firstDirectorySector = (ulong)(hddSb.off * hddSb.sectorsPerTrack); firstDirectorySector = (ulong)(hddSb.off * hddSb.sectorsPerTrack);
// Build a DiscParameterBlock // Build a DiscParameterBlock
dpb = new DiscParameterBlock(); dpb = new DiscParameterBlock
dpb.al0 = (byte)hddSb.al0; {
dpb.al1 = (byte)hddSb.al1; al0 = (byte)hddSb.al0,
dpb.blm = hddSb.blm; al1 = (byte)hddSb.al1,
dpb.bsh = hddSb.bsh; blm = hddSb.blm,
dpb.cks = hddSb.cks; bsh = hddSb.bsh,
dpb.drm = hddSb.drm; cks = hddSb.cks,
dpb.dsm = hddSb.dsm; drm = hddSb.drm,
dpb.exm = hddSb.exm; dsm = hddSb.dsm,
dpb.off = hddSb.off; exm = hddSb.exm,
dpb.phm = 0; // Needed? off = hddSb.off,
dpb.psh = 0; // Needed? // Needed?
dpb.spt = hddSb.spt; phm = 0,
// Needed?
psh = 0,
spt = hddSb.spt
};
uint directoryLength = (uint)(((ulong)dpb.drm + 1) * 32 / sectorSize); uint directoryLength = (uint)(((ulong)dpb.drm + 1) * 32 / sectorSize);
directory = imagePlugin.ReadSectors(firstDirectorySector + partition.Start, directory = imagePlugin.ReadSectors(firstDirectorySector + partition.Start,
directoryLength); directoryLength);
DicConsole.DebugWriteLine("CP/M Plugin", "Found CP/M-86 hard disk superblock."); DicConsole.DebugWriteLine("CP/M Plugin", "Found CP/M-86 hard disk superblock.");
// Build a CP/M disk definition // Build a CP/M disk definition
workingDefinition = new CpmDefinition(); workingDefinition = new CpmDefinition
workingDefinition.al0 = dpb.al0; {
workingDefinition.al1 = dpb.al1; al0 = dpb.al0,
workingDefinition.bitrate = "HIGH"; al1 = dpb.al1,
workingDefinition.blm = dpb.blm; bitrate = "HIGH",
workingDefinition.bsh = dpb.bsh; blm = dpb.blm,
workingDefinition.bytesPerSector = 512; bsh = dpb.bsh,
workingDefinition.cylinders = hddSb.cylinders; bytesPerSector = 512,
workingDefinition.drm = dpb.drm; cylinders = hddSb.cylinders,
workingDefinition.dsm = dpb.dsm; drm = dpb.drm,
workingDefinition.encoding = "MFM"; dsm = dpb.dsm,
workingDefinition.evenOdd = false; encoding = "MFM",
workingDefinition.exm = dpb.exm; evenOdd = false,
workingDefinition.label = null; exm = dpb.exm,
workingDefinition.comment = "CP/M-86 hard disk superblock"; label = null,
workingDefinition.ofs = dpb.off; comment = "CP/M-86 hard disk superblock",
workingDefinition.sectorsPerTrack = hddSb.sectorsPerTrack; ofs = dpb.off,
workingDefinition.side1 = new Side(); sectorsPerTrack = hddSb.sectorsPerTrack,
workingDefinition.side1.sideId = 0; side1 = new Side {sideId = 0, sectorIds = new int[hddSb.sectorsPerTrack]},
workingDefinition.side1.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++) for(int si = 0; si < hddSb.sectorsPerTrack; si++)
workingDefinition.side1.sectorIds[si] = si + 1; 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; 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; cpmFound = true;
firstDirectorySector86 = 8; firstDirectorySector86 = 8;
dpb = new DiscParameterBlock(); dpb = new DiscParameterBlock
dpb.al0 = 0xC0; {
dpb.al1 = 0; al0 = 0xC0,
dpb.blm = 7; al1 = 0,
dpb.bsh = 3; blm = 7,
dpb.cks = 0x10; bsh = 3,
dpb.drm = 0x3F; cks = 0x10,
dpb.dsm = 0x9B; drm = 0x3F,
dpb.exm = 0; dsm = 0x9B,
dpb.off = 1; exm = 0,
dpb.phm = 3; off = 1,
dpb.psh = 2; phm = 3,
dpb.spt = 8 * 4; 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; for(int si = 0; si < 8; si++) workingDefinition.side1.sectorIds[si] = si + 1;
workingDefinition.skew = 0;
workingDefinition.sofs = 0;
} }
break; break;
@@ -450,50 +453,49 @@ namespace DiscImageChef.Filesystems.CPM
{ {
cpmFound = true; cpmFound = true;
firstDirectorySector86 = 16; firstDirectorySector86 = 16;
dpb = new DiscParameterBlock(); dpb = new DiscParameterBlock
dpb.al0 = 0x80; {
dpb.al1 = 0; al0 = 0x80,
dpb.blm = 0x0F; al1 = 0,
dpb.bsh = 4; blm = 0x0F,
dpb.cks = 0x10; bsh = 4,
dpb.drm = 0x3F; cks = 0x10,
dpb.dsm = 0x9D; drm = 0x3F,
dpb.exm = 1; dsm = 0x9D,
dpb.off = 2; exm = 1,
dpb.phm = 3; off = 2,
dpb.psh = 2; phm = 3,
dpb.spt = 8 * 4; 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; 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; for(int si = 0; si < 8; si++) workingDefinition.side2.sectorIds[si] = si + 1;
workingDefinition.skew = 0;
workingDefinition.sofs = 0;
} }
break; break;
@@ -504,50 +506,49 @@ namespace DiscImageChef.Filesystems.CPM
{ {
cpmFound = true; cpmFound = true;
firstDirectorySector86 = 36; firstDirectorySector86 = 36;
dpb = new DiscParameterBlock(); dpb = new DiscParameterBlock
dpb.al0 = 0x80; {
dpb.al1 = 0; al0 = 0x80,
dpb.blm = 0x0F; al1 = 0,
dpb.bsh = 4; blm = 0x0F,
dpb.cks = 0x10; bsh = 4,
dpb.drm = 0x3F; cks = 0x10,
dpb.dsm = 0; // Unknown. Needed? drm = 0x3F,
dpb.exm = 1; dsm = 0, // Unknown. Needed?
dpb.off = 4; exm = 1,
dpb.phm = 3; off = 4,
dpb.psh = 2; phm = 3,
dpb.spt = 9 * 4; 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; 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; for(int si = 0; si < 9; si++) workingDefinition.side2.sectorIds[si] = si + 1;
workingDefinition.skew = 0;
workingDefinition.sofs = 0;
} }
break; break;
@@ -557,50 +558,49 @@ namespace DiscImageChef.Filesystems.CPM
{ {
cpmFound = true; cpmFound = true;
firstDirectorySector86 = 36; firstDirectorySector86 = 36;
dpb = new DiscParameterBlock(); dpb = new DiscParameterBlock
dpb.al0 = 0xF0; {
dpb.al1 = 0; al0 = 0xF0,
dpb.blm = 0x0F; al1 = 0,
dpb.bsh = 4; blm = 0x0F,
dpb.cks = 0x40; bsh = 4,
dpb.drm = 0xFF; cks = 0x40,
dpb.dsm = 0x15E; drm = 0xFF,
dpb.exm = 0; dsm = 0x15E,
dpb.off = 4; exm = 0,
dpb.phm = 3; off = 4,
dpb.psh = 2; phm = 3,
dpb.spt = 9 * 4; 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; 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; for(int si = 0; si < 9; si++) workingDefinition.side2.sectorIds[si] = si + 1;
workingDefinition.skew = 0;
workingDefinition.sofs = 0;
} }
break; break;
@@ -609,50 +609,49 @@ namespace DiscImageChef.Filesystems.CPM
{ {
cpmFound = true; cpmFound = true;
firstDirectorySector86 = 18; firstDirectorySector86 = 18;
dpb = new DiscParameterBlock(); dpb = new DiscParameterBlock
dpb.al0 = 0xF0; {
dpb.al1 = 0; al0 = 0xF0,
dpb.blm = 0x0F; al1 = 0,
dpb.bsh = 4; blm = 0x0F,
dpb.cks = 0x40; bsh = 4,
dpb.drm = 0xFF; cks = 0x40,
dpb.dsm = 0x162; drm = 0xFF,
dpb.exm = 0; dsm = 0x162,
dpb.off = 2; exm = 0,
dpb.phm = 3; off = 2,
dpb.psh = 2; phm = 3,
dpb.spt = 9 * 4; 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; 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; for(int si = 0; si < 9; si++) workingDefinition.side2.sectorIds[si] = si + 1;
workingDefinition.skew = 0;
workingDefinition.sofs = 0;
} }
break; break;
@@ -661,50 +660,49 @@ namespace DiscImageChef.Filesystems.CPM
{ {
cpmFound = true; cpmFound = true;
firstDirectorySector86 = 30; firstDirectorySector86 = 30;
dpb = new DiscParameterBlock(); dpb = new DiscParameterBlock
dpb.al0 = 0xC0; {
dpb.al1 = 0; al0 = 0xC0,
dpb.blm = 0x1F; al1 = 0,
dpb.bsh = 5; blm = 0x1F,
dpb.cks = 0x40; bsh = 5,
dpb.drm = 0xFF; cks = 0x40,
dpb.dsm = 0x127; drm = 0xFF,
dpb.exm = 1; dsm = 0x127,
dpb.off = 2; exm = 1,
dpb.phm = 3; off = 2,
dpb.psh = 2; phm = 3,
dpb.spt = 15 * 4; 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; 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; for(int si = 0; si < 15; si++) workingDefinition.side2.sectorIds[si] = si + 1;
workingDefinition.skew = 0;
workingDefinition.sofs = 0;
} }
break; break;
@@ -713,50 +711,49 @@ namespace DiscImageChef.Filesystems.CPM
{ {
cpmFound = true; cpmFound = true;
firstDirectorySector86 = 36; firstDirectorySector86 = 36;
dpb = new DiscParameterBlock(); dpb = new DiscParameterBlock
dpb.al0 = 0xC0; {
dpb.al1 = 0; al0 = 0xC0,
dpb.blm = 0x1F; al1 = 0,
dpb.bsh = 5; blm = 0x1F,
dpb.cks = 0x40; bsh = 5,
dpb.drm = 0xFF; cks = 0x40,
dpb.dsm = 0x162; drm = 0xFF,
dpb.exm = 1; dsm = 0x162,
dpb.off = 2; exm = 1,
dpb.phm = 3; off = 2,
dpb.psh = 2; phm = 3,
dpb.spt = 18 * 4; 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; 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; for(int si = 0; si < 18; si++) workingDefinition.side2.sectorIds[si] = si + 1;
workingDefinition.skew = 0;
workingDefinition.sofs = 0;
} }
break; break;
@@ -787,8 +784,7 @@ namespace DiscImageChef.Filesystems.CPM
{ {
// Load all definitions // Load all definitions
DicConsole.DebugWriteLine("CP/M Plugin", "Trying to load definitions."); DicConsole.DebugWriteLine("CP/M Plugin", "Trying to load definitions.");
if(LoadDefinitions() && definitions != null && definitions.definitions != null && if(LoadDefinitions() && definitions?.definitions != null && definitions.definitions.Count > 0)
definitions.definitions.Count > 0)
{ {
DicConsole.DebugWriteLine("CP/M Plugin", "Trying all known definitions."); 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) { 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 // Build a Disc Parameter Block
workingDefinition = def; workingDefinition = def;
dpb = new DiscParameterBlock(); dpb = new DiscParameterBlock
dpb.al0 = (byte)def.al0; {
dpb.al1 = (byte)def.al1; al0 = (byte)def.al0,
dpb.blm = (byte)def.blm; al1 = (byte)def.al1,
dpb.bsh = (byte)def.bsh; blm = (byte)def.blm,
dpb.cks = 0; // Needed? bsh = (byte)def.bsh,
dpb.drm = (ushort)def.drm; // Needed?
dpb.dsm = (ushort)def.dsm; cks = 0,
dpb.exm = (byte)def.exm; drm = (ushort)def.drm,
dpb.off = (ushort)def.ofs; dsm = (ushort)def.dsm,
exm = (byte)def.exm,
off = (ushort)def.ofs,
spt = (ushort)(def.sectorsPerTrack * def.bytesPerSector / 128)
};
switch(def.bytesPerSector) switch(def.bytesPerSector)
{ {
case 128: case 128:
@@ -939,7 +939,6 @@ namespace DiscImageChef.Filesystems.CPM
break; break;
} }
dpb.spt = (ushort)(def.sectorsPerTrack * def.bytesPerSector / 128);
cpmFound = true; cpmFound = true;
workingDefinition = def; workingDefinition = def;
@@ -991,12 +990,9 @@ namespace DiscImageChef.Filesystems.CPM
workingDefinition.ofs * workingDefinition.sectorsPerTrack, workingDefinition.ofs) workingDefinition.ofs * workingDefinition.sectorsPerTrack, workingDefinition.ofs)
.AppendLine(); .AppendLine();
int interleaveSide1;
int interleaveSide2;
if(workingDefinition.side1.sectorIds.Length >= 2) 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) if(interleaveSide1 > 1)
sb.AppendFormat("Side 0 uses {0}:1 software interleaving", interleaveSide1).AppendLine(); 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) 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) if(interleaveSide2 > 1)
sb.AppendFormat("Side 1 uses {0}:1 software interleaving", interleaveSide2).AppendLine(); sb.AppendFormat("Side 1 uses {0}:1 software interleaving", interleaveSide2).AppendLine();
} }
@@ -1046,23 +1042,23 @@ namespace DiscImageChef.Filesystems.CPM
if(labelUpdateDate != null) if(labelUpdateDate != null)
sb.AppendFormat("Volume updated on {0}", DateHandlers.CPMToDateTime(labelUpdateDate)).AppendLine(); sb.AppendFormat("Volume updated on {0}", DateHandlers.CPMToDateTime(labelUpdateDate)).AppendLine();
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType();
xmlFSType.Bootable |= workingDefinition.sofs > 0 || workingDefinition.ofs > 0; XmlFsType.Bootable |= workingDefinition.sofs > 0 || workingDefinition.ofs > 0;
xmlFSType.ClusterSize = 128 << dpb.bsh; XmlFsType.ClusterSize = 128 << dpb.bsh;
if(dpb.dsm > 0) xmlFSType.Clusters = dpb.dsm; if(dpb.dsm > 0) XmlFsType.Clusters = dpb.dsm;
else xmlFSType.Clusters = (long)(partition.End - partition.Start); else XmlFsType.Clusters = (long)(partition.End - partition.Start);
if(labelCreationDate != null) if(labelCreationDate != null)
{ {
xmlFSType.CreationDate = DateHandlers.CPMToDateTime(labelCreationDate); XmlFsType.CreationDate = DateHandlers.CPMToDateTime(labelCreationDate);
xmlFSType.CreationDateSpecified = true; XmlFsType.CreationDateSpecified = true;
} }
if(labelUpdateDate != null) if(labelUpdateDate != null)
{ {
xmlFSType.ModificationDate = DateHandlers.CPMToDateTime(labelUpdateDate); XmlFsType.ModificationDate = DateHandlers.CPMToDateTime(labelUpdateDate);
xmlFSType.ModificationDateSpecified = true; XmlFsType.ModificationDateSpecified = true;
} }
xmlFSType.Type = "CP/M"; XmlFsType.Type = "CP/M";
xmlFSType.VolumeName = label; XmlFsType.VolumeName = label;
information = sb.ToString(); information = sb.ToString();
} }

View File

@@ -149,8 +149,7 @@ namespace DiscImageChef.Filesystems.CPM
// For each volume sector // For each volume sector
for(ulong a = 0; a < (ulong)deinterleavedSectors.Count; a++) for(ulong a = 0; a < (ulong)deinterleavedSectors.Count; a++)
{ {
byte[] sector; deinterleavedSectors.TryGetValue(a, out byte[] sector);
deinterleavedSectors.TryGetValue(a, out sector);
// May it happen? Just in case, CP/M blocks are smaller than physical sectors // May it happen? Just in case, CP/M blocks are smaller than physical sectors
if(sector.Length > blockSize) if(sector.Length > blockSize)
@@ -187,8 +186,7 @@ namespace DiscImageChef.Filesystems.CPM
MemoryStream dirMs = new MemoryStream(); MemoryStream dirMs = new MemoryStream();
for(int d = 0; d < dirSectors; d++) for(int d = 0; d < dirSectors; d++)
{ {
byte[] sector; deinterleavedSectors.TryGetValue((ulong)(d + dirOff), out byte[] sector);
deinterleavedSectors.TryGetValue((ulong)(d + dirOff), out sector);
dirMs.Write(sector, 0, sector.Length); dirMs.Write(sector, 0, sector.Length);
} }
@@ -219,10 +217,9 @@ namespace DiscImageChef.Filesystems.CPM
if((directory[dOff] & 0x7F) < 0x10) if((directory[dOff] & 0x7F) < 0x10)
if(allocationBlocks.Count > 256) if(allocationBlocks.Count > 256)
{ {
DirectoryEntry16 entry;
dirPtr = Marshal.AllocHGlobal(32); dirPtr = Marshal.AllocHGlobal(32);
Marshal.Copy(directory, dOff, dirPtr, 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); Marshal.FreeHGlobal(dirPtr);
bool hidden = (entry.statusUser & 0x80) == 0x80; bool hidden = (entry.statusUser & 0x80) == 0x80;
@@ -254,24 +251,18 @@ namespace DiscImageChef.Filesystems.CPM
if(!string.IsNullOrEmpty(extension)) filename = filename + "." + extension; if(!string.IsNullOrEmpty(extension)) filename = filename + "." + extension;
int entryNo = (32 * entry.extentCounter + entry.extentCounterHigh) / (dpb.exm + 1); 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? // 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 else
{ { fInfo = new FileEntryInfo {Attributes = new FileAttributes()}; }
fInfo = new FileEntryInfo();
fInfo.Attributes = new FileAttributes();
}
// And any extent? // 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>>(); else extentBlocks = new Dictionary<int, List<ushort>>();
// Do we already have this extent? Should never happen // 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>(); else blocks = new List<ushort>();
// Attributes // Attributes
@@ -313,10 +304,9 @@ namespace DiscImageChef.Filesystems.CPM
} }
else else
{ {
DirectoryEntry entry;
dirPtr = Marshal.AllocHGlobal(32); dirPtr = Marshal.AllocHGlobal(32);
Marshal.Copy(directory, dOff, dirPtr, 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); Marshal.FreeHGlobal(dirPtr);
bool hidden = (entry.statusUser & 0x80) == 0x80; bool hidden = (entry.statusUser & 0x80) == 0x80;
@@ -348,24 +338,18 @@ namespace DiscImageChef.Filesystems.CPM
if(!string.IsNullOrEmpty(extension)) filename = filename + "." + extension; if(!string.IsNullOrEmpty(extension)) filename = filename + "." + extension;
int entryNo = (32 * entry.extentCounterHigh + entry.extentCounter) / (dpb.exm + 1); 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? // 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 else
{ { fInfo = new FileEntryInfo {Attributes = new FileAttributes()}; }
fInfo = new FileEntryInfo();
fInfo.Attributes = new FileAttributes();
}
// And any extent? // 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>>(); else extentBlocks = new Dictionary<int, List<ushort>>();
// Do we already have this extent? Should never happen // 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>(); else blocks = new List<ushort>();
// Attributes // 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) // 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) else if((directory[dOff] & 0x7F) >= 0x10 && (directory[dOff] & 0x7F) < 0x20)
{ {
PasswordEntry entry;
dirPtr = Marshal.AllocHGlobal(32); dirPtr = Marshal.AllocHGlobal(32);
Marshal.Copy(directory, dOff, dirPtr, 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); Marshal.FreeHGlobal(dirPtr);
int user = entry.userNumber & 0x0F; 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 && if(directory[dOff + 10] == 0x00 && directory[dOff + 20] == 0x00 && directory[dOff + 30] == 0x00 &&
directory[dOff + 31] == 0x00) directory[dOff + 31] == 0x00)
{ {
DateEntry dateEntry;
dirPtr = Marshal.AllocHGlobal(32); dirPtr = Marshal.AllocHGlobal(32);
Marshal.Copy(directory, dOff, dirPtr, 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); Marshal.FreeHGlobal(dirPtr);
FileEntryInfo fInfo; FileEntryInfo fInfo;
@@ -544,10 +526,9 @@ namespace DiscImageChef.Filesystems.CPM
// However, if this byte is 0, timestamp is in Z80DOS or DOS+ format // However, if this byte is 0, timestamp is in Z80DOS or DOS+ format
else if(directory[dOff + 1] == 0x00) else if(directory[dOff + 1] == 0x00)
{ {
TrdPartyDateEntry trdPartyDateEntry;
dirPtr = Marshal.AllocHGlobal(32); dirPtr = Marshal.AllocHGlobal(32);
Marshal.Copy(directory, dOff, dirPtr, 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); Marshal.FreeHGlobal(dirPtr);
FileEntryInfo fInfo; FileEntryInfo fInfo;
@@ -617,24 +598,19 @@ namespace DiscImageChef.Filesystems.CPM
foreach(string filename in dirList) foreach(string filename in dirList)
{ {
MemoryStream fileMs = new MemoryStream(); 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; fInfo.Blocks = 0;
Dictionary<int, List<ushort>> extents; if(fileExtents.TryGetValue(filename, out Dictionary<int, List<ushort>> extents))
if(fileExtents.TryGetValue(filename, out extents))
for(int ex = 0; ex < extents.Count; ex++) for(int ex = 0; ex < extents.Count; ex++)
{ {
List<ushort> alBlks; if(!extents.TryGetValue(ex, out List<ushort> alBlks)) continue;
if(!extents.TryGetValue(ex, out alBlks)) continue;
foreach(ushort alBlk in alBlks) foreach(ushort alBlk in alBlks)
{ {
byte[] blk; allocationBlocks.TryGetValue(alBlk, out byte[] blk);
allocationBlocks.TryGetValue(alBlk, out blk);
fileMs.Write(blk, 0, blk.Length); fileMs.Write(blk, 0, blk.Length);
fInfo.Blocks++; fInfo.Blocks++;
} }
@@ -668,29 +644,31 @@ namespace DiscImageChef.Filesystems.CPM
cpmStat.FilenameLength = 11; cpmStat.FilenameLength = 11;
cpmStat.Files = (ulong)fileCache.Count; cpmStat.Files = (ulong)fileCache.Count;
cpmStat.FreeBlocks = cpmStat.Blocks - usedBlocks; cpmStat.FreeBlocks = cpmStat.Blocks - usedBlocks;
cpmStat.PluginId = PluginUUID; cpmStat.PluginId = PluginUuid;
cpmStat.Type = "CP/M filesystem"; cpmStat.Type = "CP/M filesystem";
// Generate XML info // Generate XML info
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType
xmlFSType.Clusters = cpmStat.Blocks; {
xmlFSType.ClusterSize = blockSize; Clusters = cpmStat.Blocks,
ClusterSize = blockSize,
Files = fileCache.Count,
FilesSpecified = true,
FreeClusters = cpmStat.FreeBlocks,
FreeClustersSpecified = true,
Type = "CP/M filesystem"
};
if(labelCreationDate != null) if(labelCreationDate != null)
{ {
xmlFSType.CreationDate = DateHandlers.CPMToDateTime(labelCreationDate); XmlFsType.CreationDate = DateHandlers.CPMToDateTime(labelCreationDate);
xmlFSType.CreationDateSpecified = true; XmlFsType.CreationDateSpecified = true;
} }
if(labelUpdateDate != null) if(labelUpdateDate != null)
{ {
xmlFSType.ModificationDate = DateHandlers.CPMToDateTime(labelUpdateDate); XmlFsType.ModificationDate = DateHandlers.CPMToDateTime(labelUpdateDate);
xmlFSType.ModificationDateSpecified = true; XmlFsType.ModificationDateSpecified = true;
} }
xmlFSType.Files = fileCache.Count; if(!string.IsNullOrEmpty(label)) XmlFsType.VolumeName = label;
xmlFSType.FilesSpecified = true;
xmlFSType.FreeClusters = cpmStat.FreeBlocks;
xmlFSType.FreeClustersSpecified = true;
xmlFSType.Type = "CP/M filesystem";
if(!string.IsNullOrEmpty(label)) xmlFSType.VolumeName = label;
mounted = true; mounted = true;
return Errno.NoError; return Errno.NoError;

View File

@@ -58,9 +58,7 @@ namespace DiscImageChef.Filesystems.CPM
if(string.Compare(xattr, "com.caldera.cpm.password.text", StringComparison.InvariantCulture) != 0) if(string.Compare(xattr, "com.caldera.cpm.password.text", StringComparison.InvariantCulture) != 0)
return Errno.NoSuchExtendedAttribute; return Errno.NoSuchExtendedAttribute;
if(!passwordCache.TryGetValue(pathElements[0].ToUpperInvariant(), out buf)) return Errno.NoError; return !passwordCache.TryGetValue(pathElements[0].ToUpperInvariant(), out buf) ? Errno.NoError : Errno.NoSuchExtendedAttribute;
return Errno.NoSuchExtendedAttribute;
} }
/// <summary> /// <summary>

View File

@@ -45,24 +45,22 @@ namespace DiscImageChef.Filesystems
public Cram() public Cram()
{ {
Name = "Cram filesystem"; 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"); CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
} }
public Cram(Encoding encoding) public Cram(Encoding encoding)
{ {
Name = "Cram filesystem"; Name = "Cram filesystem";
PluginUUID = new Guid("F8F6E46F-7A2A-48E3-9C0A-46AF4DC29E09"); PluginUuid = new Guid("F8F6E46F-7A2A-48E3-9C0A-46AF4DC29E09");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public Cram(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public Cram(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "Cram filesystem"; Name = "Cram filesystem";
PluginUUID = new Guid("F8F6E46F-7A2A-48E3-9C0A-46AF4DC29E09"); PluginUuid = new Guid("F8F6E46F-7A2A-48E3-9C0A-46AF4DC29E09");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
enum CramCompression : ushort enum CramCompression : ushort
@@ -92,8 +90,8 @@ namespace DiscImageChef.Filesystems
/// <summary> /// <summary>
/// Identifier for Cram /// Identifier for Cram
/// </summary> /// </summary>
const uint Cram_MAGIC = 0x28CD3D45; const uint CRAM_MAGIC = 0x28CD3D45;
const uint Cram_CIGAM = 0x453DCD28; const uint CRAM_CIGAM = 0x453DCD28;
public override bool Identify(ImagePlugin imagePlugin, Partition partition) public override bool Identify(ImagePlugin imagePlugin, Partition partition)
{ {
@@ -103,7 +101,7 @@ namespace DiscImageChef.Filesystems
uint magic = BitConverter.ToUInt32(sector, 0x00); 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, public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
@@ -116,13 +114,13 @@ namespace DiscImageChef.Filesystems
bool littleEndian = true; bool littleEndian = true;
switch(magic) { switch(magic) {
case Cram_MAGIC: case CRAM_MAGIC:
IntPtr crSbPtr = Marshal.AllocHGlobal(Marshal.SizeOf(crSb)); IntPtr crSbPtr = Marshal.AllocHGlobal(Marshal.SizeOf(crSb));
Marshal.Copy(sector, 0, crSbPtr, Marshal.SizeOf(crSb)); Marshal.Copy(sector, 0, crSbPtr, Marshal.SizeOf(crSb));
crSb = (CramSuperBlock)Marshal.PtrToStructure(crSbPtr, typeof(CramSuperBlock)); crSb = (CramSuperBlock)Marshal.PtrToStructure(crSbPtr, typeof(CramSuperBlock));
Marshal.FreeHGlobal(crSbPtr); Marshal.FreeHGlobal(crSbPtr);
break; break;
case Cram_CIGAM: case CRAM_CIGAM:
crSb = BigEndianMarshal.ByteArrayToStructureBigEndian<CramSuperBlock>(sector); crSb = BigEndianMarshal.ByteArrayToStructureBigEndian<CramSuperBlock>(sector);
littleEndian = false; littleEndian = false;
break; break;
@@ -131,8 +129,7 @@ namespace DiscImageChef.Filesystems
StringBuilder sbInformation = new StringBuilder(); StringBuilder sbInformation = new StringBuilder();
sbInformation.AppendLine("Cram file system"); sbInformation.AppendLine("Cram file system");
if(littleEndian) sbInformation.AppendLine("Little-endian"); sbInformation.AppendLine(littleEndian ? "Little-endian" : "Big-endian");
else sbInformation.AppendLine("Big-endian");
sbInformation.AppendFormat("Volume edition {0}", crSb.edition).AppendLine(); sbInformation.AppendFormat("Volume edition {0}", crSb.edition).AppendLine();
sbInformation.AppendFormat("Volume name: {0}", StringHandlers.CToString(crSb.name, CurrentEncoding)) sbInformation.AppendFormat("Volume name: {0}", StringHandlers.CToString(crSb.name, CurrentEncoding))
.AppendLine(); .AppendLine();
@@ -142,14 +139,16 @@ namespace DiscImageChef.Filesystems
information = sbInformation.ToString(); information = sbInformation.ToString();
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType
xmlFSType.VolumeName = StringHandlers.CToString(crSb.name, CurrentEncoding); {
xmlFSType.Type = "Cram file system"; VolumeName = StringHandlers.CToString(crSb.name, CurrentEncoding),
xmlFSType.Clusters = crSb.blocks; Type = "Cram file system",
xmlFSType.Files = crSb.files; Clusters = crSb.blocks,
xmlFSType.FilesSpecified = true; Files = crSb.files,
xmlFSType.FreeClusters = 0; FilesSpecified = true,
xmlFSType.FreeClustersSpecified = true; FreeClusters = 0,
FreeClustersSpecified = true
};
} }
public override Errno Mount() public override Errno Mount()

View File

@@ -46,24 +46,22 @@ namespace DiscImageChef.Filesystems
public ECMA67() public ECMA67()
{ {
Name = "ECMA-67"; 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"); CurrentEncoding = Encoding.GetEncoding("iso-8859-1");
} }
public ECMA67(Encoding encoding) public ECMA67(Encoding encoding)
{ {
Name = "ECMA-67"; Name = "ECMA-67";
PluginUUID = new Guid("62A2D44A-CBC1-4377-B4B6-28C5C92034A1"); PluginUuid = new Guid("62A2D44A-CBC1-4377-B4B6-28C5C92034A1");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-1"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1");
else CurrentEncoding = encoding;
} }
public ECMA67(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public ECMA67(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "ECMA-67"; Name = "ECMA-67";
PluginUUID = new Guid("62A2D44A-CBC1-4377-B4B6-28C5C92034A1"); PluginUuid = new Guid("62A2D44A-CBC1-4377-B4B6-28C5C92034A1");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-1"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1");
else CurrentEncoding = encoding;
} }
readonly byte[] ECMA67_Magic = {0x56, 0x4F, 0x4C}; 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 name: {0}", Encoding.ASCII.GetString(vol.volumeIdentifier)).AppendLine();
sbInformation.AppendFormat("Volume owner: {0}", Encoding.ASCII.GetString(vol.owner)).AppendLine(); sbInformation.AppendFormat("Volume owner: {0}", Encoding.ASCII.GetString(vol.owner)).AppendLine();
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType
xmlFSType.Type = "ECMA-67"; {
xmlFSType.ClusterSize = 256; Type = "ECMA-67",
xmlFSType.Clusters = (long)(partition.End - partition.Start + 1); ClusterSize = 256,
xmlFSType.VolumeName = Encoding.ASCII.GetString(vol.volumeIdentifier); Clusters = (long)(partition.End - partition.Start + 1),
VolumeName = Encoding.ASCII.GetString(vol.volumeIdentifier)
};
information = sbInformation.ToString(); information = sbInformation.ToString();
} }

View File

@@ -32,6 +32,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
using DiscImageChef.CommonTypes; using DiscImageChef.CommonTypes;
@@ -44,6 +45,7 @@ namespace DiscImageChef.Filesystems
public class EFS : Filesystem public class EFS : Filesystem
{ {
[StructLayout(LayoutKind.Sequential, Pack = 1)] [StructLayout(LayoutKind.Sequential, Pack = 1)]
[SuppressMessage("ReSharper", "InconsistentNaming")]
struct EFS_Superblock struct EFS_Superblock
{ {
/* 0: fs size incl. bb 0 (in bb) */ /* 0: fs size incl. bb 0 (in bb) */
@@ -90,30 +92,28 @@ namespace DiscImageChef.Filesystems
public uint sb_checksum; public uint sb_checksum;
} }
const uint EFS_Magic = 0x00072959; const uint EFS_MAGIC = 0x00072959;
const uint EFS_Magic_New = 0x0007295A; const uint EFS_MAGIC_NEW = 0x0007295A;
public EFS() public EFS()
{ {
Name = "Extent File System Plugin"; 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"); CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
} }
public EFS(Encoding encoding) public EFS(Encoding encoding)
{ {
Name = "Extent File System Plugin"; Name = "Extent File System Plugin";
PluginUUID = new Guid("52A43F90-9AF3-4391-ADFE-65598DEEABAB"); PluginUuid = new Guid("52A43F90-9AF3-4391-ADFE-65598DEEABAB");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public EFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public EFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "Extent File System Plugin"; Name = "Extent File System Plugin";
PluginUUID = new Guid("52A43F90-9AF3-4391-ADFE-65598DEEABAB"); PluginUuid = new Guid("52A43F90-9AF3-4391-ADFE-65598DEEABAB");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public override bool Identify(ImagePlugin imagePlugin, Partition partition) public override bool Identify(ImagePlugin imagePlugin, Partition partition)
@@ -123,24 +123,24 @@ namespace DiscImageChef.Filesystems
// Misaligned // Misaligned
if(imagePlugin.ImageInfo.XmlMediaType == XmlMediaType.OpticalDisc) 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()); uint sbSize = (uint)((Marshal.SizeOf(efsSb) + 0x200) / imagePlugin.GetSectorSize());
if((Marshal.SizeOf(efs_sb) + 0x200) % imagePlugin.GetSectorSize() != 0) sbSize++; if((Marshal.SizeOf(efsSb) + 0x200) % imagePlugin.GetSectorSize() != 0) sbSize++;
byte[] sector = imagePlugin.ReadSectors(partition.Start, 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})", 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 else
{ {
@@ -155,9 +155,9 @@ namespace DiscImageChef.Filesystems
efsSb = BigEndianMarshal.ByteArrayToStructureBigEndian<EFS_Superblock>(sector); 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, 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; return false;
@@ -187,7 +187,7 @@ namespace DiscImageChef.Filesystems
efsSb = 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})", 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 else
{ {
@@ -200,15 +200,15 @@ namespace DiscImageChef.Filesystems
efsSb = BigEndianMarshal.ByteArrayToStructureBigEndian<EFS_Superblock>(sector); 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, 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(); StringBuilder sb = new StringBuilder();
sb.AppendLine("SGI extent filesystem"); 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("Filesystem size: {0} basic blocks", efsSb.sb_size).AppendLine();
sb.AppendFormat("First cylinder group starts at block {0}", efsSb.sb_firstcg).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(); sb.AppendFormat("Cylinder group size: {0} basic blocks", efsSb.sb_cgfsize).AppendLine();
@@ -231,7 +231,7 @@ namespace DiscImageChef.Filesystems
information = sb.ToString(); information = sb.ToString();
xmlFSType = new FileSystemType XmlFsType = new FileSystemType
{ {
Type = "Extent File System", Type = "Extent File System",
ClusterSize = 512, ClusterSize = 512,

View File

@@ -32,6 +32,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
using DiscImageChef.CommonTypes; using DiscImageChef.CommonTypes;
@@ -43,6 +44,7 @@ namespace DiscImageChef.Filesystems
public class F2FS : Filesystem public class F2FS : Filesystem
{ {
[StructLayout(LayoutKind.Sequential, Pack = 1)] [StructLayout(LayoutKind.Sequential, Pack = 1)]
[SuppressMessage("ReSharper", "InconsistentNaming")]
struct F2FS_Superblock struct F2FS_Superblock
{ {
public uint magic; public uint magic;
@@ -92,39 +94,39 @@ namespace DiscImageChef.Filesystems
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 871)] public byte[] reserved; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 871)] public byte[] reserved;
} }
const uint F2FS_Magic = 0xF2F52010; const uint F2FS_MAGIC = 0xF2F52010;
const uint F2FS_SuperOffset = 1024; const uint F2FS_SUPER_OFFSET = 1024;
const uint F2FS_MinSector = 512; const uint F2FS_MIN_SECTOR = 512;
const uint F2FS_MaxSector = 4096; const uint F2FS_MAX_SECTOR = 4096;
const uint F2FS_BlockSize = 4096; const uint F2FS_BLOCK_SIZE = 4096;
public F2FS() public F2FS()
{ {
Name = "F2FS Plugin"; Name = "F2FS Plugin";
PluginUUID = new Guid("82B0920F-5F0D-4063-9F57-ADE0AE02ECE5"); PluginUuid = new Guid("82B0920F-5F0D-4063-9F57-ADE0AE02ECE5");
CurrentEncoding = Encoding.Unicode; CurrentEncoding = Encoding.Unicode;
} }
public F2FS(Encoding encoding) public F2FS(Encoding encoding)
{ {
Name = "F2FS Plugin"; Name = "F2FS Plugin";
PluginUUID = new Guid("82B0920F-5F0D-4063-9F57-ADE0AE02ECE5"); PluginUuid = new Guid("82B0920F-5F0D-4063-9F57-ADE0AE02ECE5");
CurrentEncoding = Encoding.Unicode; CurrentEncoding = Encoding.Unicode;
} }
public F2FS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public F2FS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "F2FS Plugin"; Name = "F2FS Plugin";
PluginUUID = new Guid("82B0920F-5F0D-4063-9F57-ADE0AE02ECE5"); PluginUuid = new Guid("82B0920F-5F0D-4063-9F57-ADE0AE02ECE5");
CurrentEncoding = Encoding.Unicode; CurrentEncoding = Encoding.Unicode;
} }
public override bool Identify(ImagePlugin imagePlugin, Partition partition) 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; return false;
uint sbAddr = F2FS_SuperOffset / imagePlugin.GetSectorSize(); uint sbAddr = F2FS_SUPER_OFFSET / imagePlugin.GetSectorSize();
if(sbAddr == 0) sbAddr = 1; if(sbAddr == 0) sbAddr = 1;
F2FS_Superblock f2fsSb = new F2FS_Superblock(); F2FS_Superblock f2fsSb = new F2FS_Superblock();
@@ -142,16 +144,16 @@ namespace DiscImageChef.Filesystems
f2fsSb = (F2FS_Superblock)Marshal.PtrToStructure(sbPtr, typeof(F2FS_Superblock)); f2fsSb = (F2FS_Superblock)Marshal.PtrToStructure(sbPtr, typeof(F2FS_Superblock));
Marshal.FreeHGlobal(sbPtr); Marshal.FreeHGlobal(sbPtr);
return f2fsSb.magic == F2FS_Magic; return f2fsSb.magic == F2FS_MAGIC;
} }
public override void GetInformation(ImagePlugin imagePlugin, Partition partition, public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
out string information) out string information)
{ {
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; if(sbAddr == 0) sbAddr = 1;
F2FS_Superblock f2fsSb = new F2FS_Superblock(); F2FS_Superblock f2fsSb = new F2FS_Superblock();
@@ -167,7 +169,7 @@ namespace DiscImageChef.Filesystems
f2fsSb = (F2FS_Superblock)Marshal.PtrToStructure(sbPtr, typeof(F2FS_Superblock)); f2fsSb = (F2FS_Superblock)Marshal.PtrToStructure(sbPtr, typeof(F2FS_Superblock));
Marshal.FreeHGlobal(sbPtr); Marshal.FreeHGlobal(sbPtr);
if(f2fsSb.magic != F2FS_Magic) return; if(f2fsSb.magic != F2FS_MAGIC) return;
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
@@ -193,14 +195,16 @@ namespace DiscImageChef.Filesystems
information = sb.ToString(); information = sb.ToString();
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType
xmlFSType.Type = "F2FS filesystem"; {
xmlFSType.SystemIdentifier = Encoding.ASCII.GetString(f2fsSb.version); Type = "F2FS filesystem",
xmlFSType.Clusters = (long)f2fsSb.block_count; SystemIdentifier = Encoding.ASCII.GetString(f2fsSb.version),
xmlFSType.ClusterSize = 1 << (int)f2fsSb.log_blocksize; Clusters = (long)f2fsSb.block_count,
xmlFSType.DataPreparerIdentifier = Encoding.ASCII.GetString(f2fsSb.init_version); ClusterSize = 1 << (int)f2fsSb.log_blocksize,
xmlFSType.VolumeName = StringHandlers.CToString(f2fsSb.volume_name, Encoding.Unicode, true); DataPreparerIdentifier = Encoding.ASCII.GetString(f2fsSb.init_version),
xmlFSType.VolumeSerial = f2fsSb.uuid.ToString(); VolumeName = StringHandlers.CToString(f2fsSb.volume_name, Encoding.Unicode, true),
VolumeSerial = f2fsSb.uuid.ToString()
};
} }
public override Errno Mount() public override Errno Mount()

File diff suppressed because it is too large Load Diff

View File

@@ -51,26 +51,26 @@ namespace DiscImageChef.Filesystems
public uint rootDirectoryCluster; public uint rootDirectoryCluster;
} }
const uint FATX_Magic = 0x58544146; const uint FATX_MAGIC = 0x58544146;
public FATX() public FATX()
{ {
Name = "FATX Filesystem Plugin"; Name = "FATX Filesystem Plugin";
PluginUUID = new Guid("ED27A721-4A17-4649-89FD-33633B46E228"); PluginUuid = new Guid("ED27A721-4A17-4649-89FD-33633B46E228");
CurrentEncoding = Encoding.UTF8; CurrentEncoding = Encoding.UTF8;
} }
public FATX(Encoding encoding) public FATX(Encoding encoding)
{ {
Name = "FATX Filesystem Plugin"; Name = "FATX Filesystem Plugin";
PluginUUID = new Guid("ED27A721-4A17-4649-89FD-33633B46E228"); PluginUuid = new Guid("ED27A721-4A17-4649-89FD-33633B46E228");
CurrentEncoding = Encoding.UTF8; CurrentEncoding = Encoding.UTF8;
} }
public FATX(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public FATX(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "FATX Filesystem Plugin"; Name = "FATX Filesystem Plugin";
PluginUUID = new Guid("ED27A721-4A17-4649-89FD-33633B46E228"); PluginUuid = new Guid("ED27A721-4A17-4649-89FD-33633B46E228");
CurrentEncoding = Encoding.UTF8; CurrentEncoding = Encoding.UTF8;
} }
@@ -83,7 +83,7 @@ namespace DiscImageChef.Filesystems
fatxSb = BigEndianMarshal.ByteArrayToStructureBigEndian<FATX_Superblock>(sector); fatxSb = BigEndianMarshal.ByteArrayToStructureBigEndian<FATX_Superblock>(sector);
return fatxSb.magic == FATX_Magic; return fatxSb.magic == FATX_MAGIC;
} }
public override void GetInformation(ImagePlugin imagePlugin, Partition partition, public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
@@ -98,7 +98,7 @@ namespace DiscImageChef.Filesystems
fatxSb = BigEndianMarshal.ByteArrayToStructureBigEndian<FATX_Superblock>(sector); fatxSb = BigEndianMarshal.ByteArrayToStructureBigEndian<FATX_Superblock>(sector);
if(fatxSb.magic != FATX_Magic) return; if(fatxSb.magic != FATX_MAGIC) return;
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
@@ -110,11 +110,13 @@ namespace DiscImageChef.Filesystems
information = sb.ToString(); information = sb.ToString();
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType
xmlFSType.Type = "FATX filesystem"; {
xmlFSType.ClusterSize = (int)(fatxSb.sectorsPerCluster * imagePlugin.ImageInfo.SectorSize); Type = "FATX filesystem",
xmlFSType.Clusters = (long)((partition.End - partition.Start + 1) * imagePlugin.ImageInfo.SectorSize / ClusterSize = (int)(fatxSb.sectorsPerCluster * imagePlugin.ImageInfo.SectorSize)
(ulong)xmlFSType.ClusterSize); };
XmlFsType.Clusters = (long)((partition.End - partition.Start + 1) * imagePlugin.ImageInfo.SectorSize /
(ulong)XmlFsType.ClusterSize);
} }
public override Errno Mount() public override Errno Mount()

View File

@@ -32,6 +32,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
@@ -45,42 +46,39 @@ using ufs_daddr_t = System.Int32;
namespace DiscImageChef.Filesystems namespace DiscImageChef.Filesystems
{ {
// Using information from Linux kernel headers // Using information from Linux kernel headers
[SuppressMessage("ReSharper", "InconsistentNaming")]
public class FFSPlugin : Filesystem public class FFSPlugin : Filesystem
{ {
public FFSPlugin() public FFSPlugin()
{ {
Name = "BSD Fast File System (aka UNIX File System, UFS)"; 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"); CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
} }
public FFSPlugin(Encoding encoding) public FFSPlugin(Encoding encoding)
{ {
Name = "BSD Fast File System (aka UNIX File System, UFS)"; 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");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public FFSPlugin(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public FFSPlugin(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "BSD Fast File System (aka UNIX File System, UFS)"; 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");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public override bool Identify(ImagePlugin imagePlugin, Partition partition) public override bool Identify(ImagePlugin imagePlugin, Partition partition)
{ {
if(2 + partition.Start >= partition.End) return false; if(2 + partition.Start >= partition.End) return false;
uint magic; uint sbSizeInSectors;
uint sb_size_in_sectors;
byte[] ufs_sb_sectors;
if(imagePlugin.GetSectorSize() == 2336 || imagePlugin.GetSectorSize() == 2352 || if(imagePlugin.GetSectorSize() == 2336 || imagePlugin.GetSectorSize() == 2352 ||
imagePlugin.GetSectorSize() == 2448) sb_size_in_sectors = block_size / 2048; imagePlugin.GetSectorSize() == 2448) sbSizeInSectors = block_size / 2048;
else sb_size_in_sectors = block_size / imagePlugin.GetSectorSize(); else sbSizeInSectors = block_size / imagePlugin.GetSectorSize();
ulong[] locations = ulong[] locations =
{ {
@@ -89,16 +87,7 @@ namespace DiscImageChef.Filesystems
262144 / imagePlugin.GetSectorSize() 262144 / imagePlugin.GetSectorSize()
}; };
foreach(ulong loc in locations.Where(loc => partition.End > partition.Start + loc + sb_size_in_sectors)) { 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);
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;
} }
public override void GetInformation(ImagePlugin imagePlugin, Partition partition, public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
@@ -150,43 +139,43 @@ namespace DiscImageChef.Filesystems
return; return;
} }
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType();
switch(magic) switch(magic)
{ {
case UFS_MAGIC: case UFS_MAGIC:
sbInformation.AppendLine("UFS filesystem"); sbInformation.AppendLine("UFS filesystem");
xmlFSType.Type = "UFS"; XmlFsType.Type = "UFS";
break; break;
case UFS_CIGAM: case UFS_CIGAM:
sbInformation.AppendLine("Big-endian UFS filesystem"); sbInformation.AppendLine("Big-endian UFS filesystem");
xmlFSType.Type = "UFS"; XmlFsType.Type = "UFS";
break; break;
case UFS_MAGIC_BW: case UFS_MAGIC_BW:
sbInformation.AppendLine("BorderWare UFS filesystem"); sbInformation.AppendLine("BorderWare UFS filesystem");
xmlFSType.Type = "UFS"; XmlFsType.Type = "UFS";
break; break;
case UFS_CIGAM_BW: case UFS_CIGAM_BW:
sbInformation.AppendLine("Big-endian BorderWare UFS filesystem"); sbInformation.AppendLine("Big-endian BorderWare UFS filesystem");
xmlFSType.Type = "UFS"; XmlFsType.Type = "UFS";
break; break;
case UFS2_MAGIC: case UFS2_MAGIC:
sbInformation.AppendLine("UFS2 filesystem"); sbInformation.AppendLine("UFS2 filesystem");
xmlFSType.Type = "UFS2"; XmlFsType.Type = "UFS2";
break; break;
case UFS2_CIGAM: case UFS2_CIGAM:
sbInformation.AppendLine("Big-endian UFS2 filesystem"); sbInformation.AppendLine("Big-endian UFS2 filesystem");
xmlFSType.Type = "UFS2"; XmlFsType.Type = "UFS2";
break; break;
case UFS_BAD_MAGIC: case UFS_BAD_MAGIC:
sbInformation.AppendLine("Incompletely initialized UFS filesystem"); sbInformation.AppendLine("Incompletely initialized UFS filesystem");
sbInformation.AppendLine("BEWARE!!! Following information may be completely wrong!"); sbInformation.AppendLine("BEWARE!!! Following information may be completely wrong!");
xmlFSType.Type = "UFS"; XmlFsType.Type = "UFS";
break; break;
case UFS_BAD_CIGAM: case UFS_BAD_CIGAM:
sbInformation.AppendLine("Incompletely initialized big-endian UFS filesystem"); sbInformation.AppendLine("Incompletely initialized big-endian UFS filesystem");
sbInformation.AppendLine("BEWARE!!! Following information may be completely wrong!"); sbInformation.AppendLine("BEWARE!!! Following information may be completely wrong!");
xmlFSType.Type = "UFS"; XmlFsType.Type = "UFS";
break; break;
} }
@@ -332,12 +321,12 @@ namespace DiscImageChef.Filesystems
sbInformation.AppendFormat("Cylinder group offset in cylinder: {0}", ufs_sb.fs_old_cgoffset).AppendLine(); 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)) sbInformation.AppendFormat("Volume last written on {0}", DateHandlers.UNIXToDateTime(ufs_sb.fs_old_time))
.AppendLine(); .AppendLine();
xmlFSType.ModificationDate = DateHandlers.UNIXToDateTime(ufs_sb.fs_old_time); XmlFsType.ModificationDate = DateHandlers.UNIXToDateTime(ufs_sb.fs_old_time);
xmlFSType.ModificationDateSpecified = true; XmlFsType.ModificationDateSpecified = true;
sbInformation.AppendFormat("{0} blocks in volume ({1} bytes)", ufs_sb.fs_old_size, sbInformation.AppendFormat("{0} blocks in volume ({1} bytes)", ufs_sb.fs_old_size,
(long)ufs_sb.fs_old_size * ufs_sb.fs_fsize).AppendLine(); (long)ufs_sb.fs_old_size * ufs_sb.fs_fsize).AppendLine();
xmlFSType.Clusters = ufs_sb.fs_old_size; XmlFsType.Clusters = ufs_sb.fs_old_size;
xmlFSType.ClusterSize = ufs_sb.fs_fsize; XmlFsType.ClusterSize = ufs_sb.fs_fsize;
sbInformation.AppendFormat("{0} data blocks in volume ({1} bytes)", ufs_sb.fs_old_dsize, 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(); (long)ufs_sb.fs_old_dsize * ufs_sb.fs_fsize).AppendLine();
sbInformation.AppendFormat("{0} cylinder groups in volume", ufs_sb.fs_ncg).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(); default: sbInformation.AppendFormat("Unknown optimization value: 0x{0:X8}", ufs_sb.fs_optim).AppendLine();
break; break;
} }
if(fs_type_sun) sbInformation.AppendFormat("{0} sectors/track", ufs_sb.fs_old_npsect).AppendLine(); if(fs_type_sun) sbInformation.AppendFormat("{0} sectors/track", ufs_sb.fs_old_npsect).AppendLine();
else if(fs_type_sun86) else if(fs_type_sun86)
sbInformation.AppendFormat("Volume state on {0}", DateHandlers.UNIXToDateTime(ufs_sb.fs_old_npsect)) 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} directories", ufs_sb.fs_old_cstotal.cs_ndir).AppendLine();
sbInformation.AppendFormat("{0} free blocks ({1} bytes)", ufs_sb.fs_old_cstotal.cs_nbfree, 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(); (long)ufs_sb.fs_old_cstotal.cs_nbfree * ufs_sb.fs_fsize).AppendLine();
xmlFSType.FreeClusters = ufs_sb.fs_old_cstotal.cs_nbfree; XmlFsType.FreeClusters = ufs_sb.fs_old_cstotal.cs_nbfree;
xmlFSType.FreeClustersSpecified = true; XmlFsType.FreeClustersSpecified = true;
sbInformation.AppendFormat("{0} free inodes", ufs_sb.fs_old_cstotal.cs_nifree).AppendLine(); 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(); sbInformation.AppendFormat("{0} free frags", ufs_sb.fs_old_cstotal.cs_nffree).AppendLine();
if(ufs_sb.fs_fmod == 1) if(ufs_sb.fs_fmod == 1)
{ {
sbInformation.AppendLine("Superblock is under modification"); 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_clean == 1) sbInformation.AppendLine("Volume is clean");
if(ufs_sb.fs_ronly == 1) sbInformation.AppendLine("Volume is read-only"); if(ufs_sb.fs_ronly == 1) sbInformation.AppendLine("Volume is read-only");
@@ -412,7 +402,7 @@ namespace DiscImageChef.Filesystems
.AppendLine(); .AppendLine();
sbInformation.AppendFormat("Volume name: \"{0}\"", StringHandlers.CToString(ufs_sb.fs_volname)) sbInformation.AppendFormat("Volume name: \"{0}\"", StringHandlers.CToString(ufs_sb.fs_volname))
.AppendLine(); .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(); sbInformation.AppendFormat("Volume ID: 0x{0:X16}", ufs_sb.fs_swuid).AppendLine();
//xmlFSType.VolumeSerial = string.Format("{0:X16}", ufs_sb.fs_swuid); //xmlFSType.VolumeSerial = string.Format("{0:X16}", ufs_sb.fs_swuid);
sbInformation.AppendFormat("Last searched cylinder group: {0}", ufs_sb.fs_cgrotor).AppendLine(); 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} directories", ufs_sb.fs_cstotal.cs_ndir).AppendLine();
sbInformation.AppendFormat("{0} free blocks ({1} bytes)", ufs_sb.fs_cstotal.cs_nbfree, sbInformation.AppendFormat("{0} free blocks ({1} bytes)", ufs_sb.fs_cstotal.cs_nbfree,
ufs_sb.fs_cstotal.cs_nbfree * ufs_sb.fs_fsize).AppendLine(); ufs_sb.fs_cstotal.cs_nbfree * ufs_sb.fs_fsize).AppendLine();
xmlFSType.FreeClusters = ufs_sb.fs_cstotal.cs_nbfree; XmlFsType.FreeClusters = ufs_sb.fs_cstotal.cs_nbfree;
xmlFSType.FreeClustersSpecified = true; XmlFsType.FreeClustersSpecified = true;
sbInformation.AppendFormat("{0} free inodes", ufs_sb.fs_cstotal.cs_nifree).AppendLine(); 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 frags", ufs_sb.fs_cstotal.cs_nffree).AppendLine();
sbInformation.AppendFormat("{0} free clusters", ufs_sb.fs_cstotal.cs_numclusters).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)) sbInformation.AppendFormat("Volume last written on {0}", DateHandlers.UNIXToDateTime(ufs_sb.fs_time))
.AppendLine(); .AppendLine();
xmlFSType.ModificationDate = DateHandlers.UNIXToDateTime(ufs_sb.fs_time); XmlFsType.ModificationDate = DateHandlers.UNIXToDateTime(ufs_sb.fs_time);
xmlFSType.ModificationDateSpecified = true; XmlFsType.ModificationDateSpecified = true;
sbInformation.AppendFormat("{0} blocks ({1} bytes)", ufs_sb.fs_size, ufs_sb.fs_size * ufs_sb.fs_fsize) sbInformation.AppendFormat("{0} blocks ({1} bytes)", ufs_sb.fs_size, ufs_sb.fs_size * ufs_sb.fs_fsize)
.AppendLine(); .AppendLine();
xmlFSType.Clusters = ufs_sb.fs_size; XmlFsType.Clusters = ufs_sb.fs_size;
sbInformation sbInformation
.AppendFormat("{0} data blocks ({1} bytes)", ufs_sb.fs_dsize, ufs_sb.fs_dsize * ufs_sb.fs_fsize) .AppendFormat("{0} data blocks ({1} bytes)", ufs_sb.fs_dsize, ufs_sb.fs_dsize * ufs_sb.fs_fsize)
.AppendLine(); .AppendLine();

View File

@@ -47,18 +47,15 @@ namespace DiscImageChef.Filesystems
/// <summary>Plugin name.</summary> /// <summary>Plugin name.</summary>
public string Name; public string Name;
/// <summary>Plugin UUID.</summary> /// <summary>Plugin UUID.</summary>
public Guid PluginUUID; public Guid PluginUuid;
internal FileSystemType xmlFSType; internal FileSystemType XmlFsType;
public Encoding CurrentEncoding; protected Encoding CurrentEncoding;
/// <summary> /// <summary>
/// Information about the filesystem as expected by CICM Metadata XML /// Information about the filesystem as expected by CICM Metadata XML
/// </summary> /// </summary>
/// <value>Information about the filesystem as expected by CICM Metadata XML</value> /// <value>Information about the filesystem as expected by CICM Metadata XML</value>
public FileSystemType XmlFSType public FileSystemType XmlFSType => XmlFsType;
{
get { return xmlFSType; }
}
protected Filesystem() { } protected Filesystem() { }

View File

@@ -121,22 +121,22 @@ namespace DiscImageChef.Filesystems
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] public byte[] name; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] public byte[] name;
} }
const uint Fossil_HdrMagic = 0x3776AE89; const uint FOSSIL_HDR_MAGIC = 0x3776AE89;
const uint Fossil_SbMagic = 0x2340A3B1; const uint FOSSIL_SB_MAGIC = 0x2340A3B1;
// Fossil header starts at 128KiB // Fossil header starts at 128KiB
const ulong HeaderPos = 128 * 1024; const ulong HEADER_POS = 128 * 1024;
public Fossil() public Fossil()
{ {
Name = "Fossil Filesystem Plugin"; Name = "Fossil Filesystem Plugin";
PluginUUID = new Guid("932BF104-43F6-494F-973C-45EF58A51DA9"); PluginUuid = new Guid("932BF104-43F6-494F-973C-45EF58A51DA9");
CurrentEncoding = Encoding.UTF8; CurrentEncoding = Encoding.UTF8;
} }
public Fossil(Encoding encoding) public Fossil(Encoding encoding)
{ {
Name = "Fossil Filesystem Plugin"; 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 // Technically everything on Plan 9 from Bell Labs is in UTF-8
CurrentEncoding = Encoding.UTF8; CurrentEncoding = Encoding.UTF8;
} }
@@ -144,14 +144,14 @@ namespace DiscImageChef.Filesystems
public Fossil(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public Fossil(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "Fossil Filesystem Plugin"; 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 // Technically everything on Plan 9 from Bell Labs is in UTF-8
CurrentEncoding = Encoding.UTF8; CurrentEncoding = Encoding.UTF8;
} }
public override bool Identify(ImagePlugin imagePlugin, Partition partition) public override bool Identify(ImagePlugin imagePlugin, Partition partition)
{ {
ulong hdrSector = HeaderPos / imagePlugin.GetSectorSize(); ulong hdrSector = HEADER_POS / imagePlugin.GetSectorSize();
FossilHeader hdr; FossilHeader hdr;
@@ -161,9 +161,9 @@ namespace DiscImageChef.Filesystems
hdr = BigEndianMarshal.ByteArrayToStructureBigEndian<FossilHeader>(sector); hdr = BigEndianMarshal.ByteArrayToStructureBigEndian<FossilHeader>(sector);
DicConsole.DebugWriteLine("Fossil plugin", "magic at 0x{0:X8} (expected 0x{1:X8})", hdr.magic, 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, public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
@@ -172,7 +172,7 @@ namespace DiscImageChef.Filesystems
information = ""; information = "";
if(imagePlugin.GetSectorSize() < 512) return; if(imagePlugin.GetSectorSize() < 512) return;
ulong hdrSector = HeaderPos / imagePlugin.GetSectorSize(); ulong hdrSector = HEADER_POS / imagePlugin.GetSectorSize();
FossilHeader hdr; FossilHeader hdr;
@@ -180,7 +180,7 @@ namespace DiscImageChef.Filesystems
hdr = BigEndianMarshal.ByteArrayToStructureBigEndian<FossilHeader>(sector); hdr = BigEndianMarshal.ByteArrayToStructureBigEndian<FossilHeader>(sector);
DicConsole.DebugWriteLine("Fossil plugin", "magic at 0x{0:X8} (expected 0x{1:X8})", hdr.magic, DicConsole.DebugWriteLine("Fossil plugin", "magic at 0x{0:X8} (expected 0x{1:X8})", hdr.magic,
Fossil_HdrMagic); FOSSIL_HDR_MAGIC);
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
@@ -194,7 +194,7 @@ namespace DiscImageChef.Filesystems
ulong sbLocation = hdr.super * (hdr.blockSize / imagePlugin.GetSectorSize()) + partition.Start; ulong sbLocation = hdr.super * (hdr.blockSize / imagePlugin.GetSectorSize()) + partition.Start;
xmlFSType = new FileSystemType XmlFsType = new FileSystemType
{ {
Type = "Fossil filesystem", Type = "Fossil filesystem",
ClusterSize = hdr.blockSize, ClusterSize = hdr.blockSize,
@@ -207,9 +207,9 @@ namespace DiscImageChef.Filesystems
FossilSuperBlock fsb = BigEndianMarshal.ByteArrayToStructureBigEndian<FossilSuperBlock>(sector); FossilSuperBlock fsb = BigEndianMarshal.ByteArrayToStructureBigEndian<FossilSuperBlock>(sector);
DicConsole.DebugWriteLine("Fossil plugin", "magic 0x{0:X8} (expected 0x{1:X8})", fsb.magic, 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 low {0}", fsb.epochLow).AppendLine();
sb.AppendFormat("Epoch high {0}", fsb.epochHigh).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("Curren root block {0}", fsb.current).AppendLine();
sb.AppendFormat("Volume label: \"{0}\"", StringHandlers.CToString(fsb.name, CurrentEncoding)) sb.AppendFormat("Volume label: \"{0}\"", StringHandlers.CToString(fsb.name, CurrentEncoding))
.AppendLine(); .AppendLine();
xmlFSType.VolumeName = StringHandlers.CToString(fsb.name, CurrentEncoding); XmlFsType.VolumeName = StringHandlers.CToString(fsb.name, CurrentEncoding);
} }
} }

View File

@@ -32,6 +32,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
using DiscImageChef.CommonTypes; using DiscImageChef.CommonTypes;
@@ -40,9 +41,12 @@ using Schemas;
using hammer_crc_t = System.UInt32; using hammer_crc_t = System.UInt32;
using hammer_off_t = System.UInt64; using hammer_off_t = System.UInt64;
using hammer_tid_t = System.UInt64; using hammer_tid_t = System.UInt64;
#pragma warning disable 169
namespace DiscImageChef.Filesystems namespace DiscImageChef.Filesystems
{ {
[SuppressMessage("ReSharper", "BuiltInTypeReferenceStyle")]
[SuppressMessage("ReSharper", "InconsistentNaming")]
public class HAMMER : Filesystem public class HAMMER : Filesystem
{ {
const ulong HAMMER_FSBUF_VOLUME = 0xC8414D4DC5523031; const ulong HAMMER_FSBUF_VOLUME = 0xC8414D4DC5523031;
@@ -53,24 +57,22 @@ namespace DiscImageChef.Filesystems
public HAMMER() public HAMMER()
{ {
Name = "HAMMER Filesystem"; 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"); CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
} }
public HAMMER(Encoding encoding) public HAMMER(Encoding encoding)
{ {
Name = "HAMMER Filesystem"; Name = "HAMMER Filesystem";
PluginUUID = new Guid("91A188BF-5FD7-4677-BBD3-F59EBA9C864D"); PluginUuid = new Guid("91A188BF-5FD7-4677-BBD3-F59EBA9C864D");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public HAMMER(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public HAMMER(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "HAMMER Filesystem"; Name = "HAMMER Filesystem";
PluginUUID = new Guid("91A188BF-5FD7-4677-BBD3-F59EBA9C864D"); PluginUuid = new Guid("91A188BF-5FD7-4677-BBD3-F59EBA9C864D");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public override bool Identify(ImagePlugin imagePlugin, Partition partition) public override bool Identify(ImagePlugin imagePlugin, Partition partition)
@@ -83,9 +85,9 @@ namespace DiscImageChef.Filesystems
ulong magic; 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; return magic == HAMMER_FSBUF_VOLUME || magic == HAMMER_FSBUF_VOLUME_REV;
} }
@@ -97,7 +99,7 @@ namespace DiscImageChef.Filesystems
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
HammerSuperBlock hammer_sb; HammerSuperBlock hammerSb;
uint run = HAMMER_VOLHDR_SIZE / imagePlugin.GetSectorSize(); uint run = HAMMER_VOLHDR_SIZE / imagePlugin.GetSectorSize();
@@ -105,56 +107,56 @@ namespace DiscImageChef.Filesystems
ulong magic; 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) if(magic == HAMMER_FSBUF_VOLUME)
{ {
GCHandle handle = GCHandle.Alloc(sb_sector, GCHandleType.Pinned); GCHandle handle = GCHandle.Alloc(sbSector, GCHandleType.Pinned);
hammer_sb = (HammerSuperBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), hammerSb = (HammerSuperBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),
typeof(HammerSuperBlock)); typeof(HammerSuperBlock));
handle.Free(); handle.Free();
} }
else hammer_sb = BigEndianMarshal.ByteArrayToStructureBigEndian<HammerSuperBlock>(sb_sector); else hammerSb = BigEndianMarshal.ByteArrayToStructureBigEndian<HammerSuperBlock>(sbSector);
sb.AppendLine("HAMMER filesystem"); sb.AppendLine("HAMMER filesystem");
sb.AppendFormat("Volume version: {0}", hammer_sb.vol_version).AppendLine(); sb.AppendFormat("Volume version: {0}", hammerSb.vol_version).AppendLine();
sb.AppendFormat("Volume {0} of {1} on this filesystem", hammer_sb.vol_no + 1, hammer_sb.vol_count) sb.AppendFormat("Volume {0} of {1} on this filesystem", hammerSb.vol_no + 1, hammerSb.vol_count)
.AppendLine(); .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(); .AppendLine();
sb.AppendFormat("Volume serial: {0}", hammer_sb.vol_fsid).AppendLine(); sb.AppendFormat("Volume serial: {0}", hammerSb.vol_fsid).AppendLine();
sb.AppendFormat("Filesystem type: {0}", hammer_sb.vol_fstype).AppendLine(); sb.AppendFormat("Filesystem type: {0}", hammerSb.vol_fstype).AppendLine();
sb.AppendFormat("Boot area starts at {0}", hammer_sb.vol_bot_beg).AppendLine(); sb.AppendFormat("Boot area starts at {0}", hammerSb.vol_bot_beg).AppendLine();
sb.AppendFormat("Memory log starts at {0}", hammer_sb.vol_mem_beg).AppendLine(); sb.AppendFormat("Memory log starts at {0}", hammerSb.vol_mem_beg).AppendLine();
sb.AppendFormat("First volume buffer starts at {0}", hammer_sb.vol_buf_beg).AppendLine(); sb.AppendFormat("First volume buffer starts at {0}", hammerSb.vol_buf_beg).AppendLine();
sb.AppendFormat("Volume ends at {0}", hammer_sb.vol_buf_end).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), Clusters = (long)(partition.Size / HAMMER_BIGBLOCK_SIZE),
ClusterSize = HAMMER_BIGBLOCK_SIZE, ClusterSize = HAMMER_BIGBLOCK_SIZE,
Dirty = false, Dirty = false,
Type = "HAMMER", Type = "HAMMER",
VolumeName = StringHandlers.CToString(hammer_sb.vol_label, CurrentEncoding), VolumeName = StringHandlers.CToString(hammerSb.vol_label, CurrentEncoding),
VolumeSerial = hammer_sb.vol_fsid.ToString() 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, sb.AppendFormat("Filesystem contains {0} \"big-blocks\" ({1} bytes)", hammerSb.vol0_stat_bigblocks,
hammer_sb.vol0_stat_bigblocks * HAMMER_BIGBLOCK_SIZE).AppendLine(); hammerSb.vol0_stat_bigblocks * HAMMER_BIGBLOCK_SIZE).AppendLine();
sb.AppendFormat("Filesystem has {0} \"big-blocks\" free ({1} bytes)", hammer_sb.vol0_stat_freebigblocks, sb.AppendFormat("Filesystem has {0} \"big-blocks\" free ({1} bytes)", hammerSb.vol0_stat_freebigblocks,
hammer_sb.vol0_stat_freebigblocks * HAMMER_BIGBLOCK_SIZE).AppendLine(); hammerSb.vol0_stat_freebigblocks * HAMMER_BIGBLOCK_SIZE).AppendLine();
sb.AppendFormat("Filesystem has {0} inode used", hammer_sb.vol0_stat_inodes).AppendLine(); sb.AppendFormat("Filesystem has {0} inode used", hammerSb.vol0_stat_inodes).AppendLine();
xmlFSType.Clusters = hammer_sb.vol0_stat_bigblocks; XmlFsType.Clusters = hammerSb.vol0_stat_bigblocks;
xmlFSType.FreeClusters = hammer_sb.vol0_stat_freebigblocks; XmlFsType.FreeClusters = hammerSb.vol0_stat_freebigblocks;
xmlFSType.FreeClustersSpecified = true; XmlFsType.FreeClustersSpecified = true;
xmlFSType.Files = hammer_sb.vol0_stat_inodes; XmlFsType.Files = hammerSb.vol0_stat_inodes;
xmlFSType.FilesSpecified = true; XmlFsType.FilesSpecified = true;
} }
// 0 ? // 0 ?
//sb.AppendFormat("Volume header CRC: 0x{0:X8}", afs_sb.vol_crc).AppendLine(); //sb.AppendFormat("Volume header CRC: 0x{0:X8}", afs_sb.vol_crc).AppendLine();

View File

@@ -47,24 +47,22 @@ namespace DiscImageChef.Filesystems
public HPFS() public HPFS()
{ {
Name = "OS/2 High Performance File System"; 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"); CurrentEncoding = Encoding.GetEncoding("ibm850");
} }
public HPFS(Encoding encoding) public HPFS(Encoding encoding)
{ {
Name = "OS/2 High Performance File System"; Name = "OS/2 High Performance File System";
PluginUUID = new Guid("33513B2C-f590-4acb-8bf2-0b1d5e19dec5"); PluginUuid = new Guid("33513B2C-f590-4acb-8bf2-0b1d5e19dec5");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("ibm850"); CurrentEncoding = encoding ?? Encoding.GetEncoding("ibm850");
else CurrentEncoding = encoding;
} }
public HPFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public HPFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "OS/2 High Performance File System"; Name = "OS/2 High Performance File System";
PluginUUID = new Guid("33513B2C-f590-4acb-8bf2-0b1d5e19dec5"); PluginUuid = new Guid("33513B2C-f590-4acb-8bf2-0b1d5e19dec5");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("ibm850"); CurrentEncoding = encoding ?? Encoding.GetEncoding("ibm850");
else CurrentEncoding = encoding;
} }
public override bool Identify(ImagePlugin imagePlugin, Partition partition) public override bool Identify(ImagePlugin imagePlugin, Partition partition)
@@ -73,14 +71,12 @@ namespace DiscImageChef.Filesystems
uint magic1, magic2; uint magic1, magic2;
byte[] hpfs_sb_sector = byte[] hpfsSbSector =
imagePlugin.ReadSector(16 + partition.Start); // Seek to superblock, on logical sector 16 imagePlugin.ReadSector(16 + partition.Start); // Seek to superblock, on logical sector 16
magic1 = BitConverter.ToUInt32(hpfs_sb_sector, 0x000); magic1 = BitConverter.ToUInt32(hpfsSbSector, 0x000);
magic2 = BitConverter.ToUInt32(hpfs_sb_sector, 0x004); magic2 = BitConverter.ToUInt32(hpfsSbSector, 0x004);
if(magic1 == 0xF995E849 && magic2 == 0xFA53E9C5) return true; return magic1 == 0xF995E849 && magic2 == 0xFA53E9C5;
return false;
} }
public override void GetInformation(ImagePlugin imagePlugin, Partition partition, public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
@@ -90,135 +86,130 @@ namespace DiscImageChef.Filesystems
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
HPFS_BIOSParameterBlock hpfs_bpb; byte[] hpfsBpbSector =
HPFS_SuperBlock hpfs_sb;
HPFS_SpareBlock hpfs_sp;
byte[] hpfs_bpb_sector =
imagePlugin.ReadSector(0 + partition.Start); // Seek to BIOS parameter block, on logical sector 0 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 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 imagePlugin.ReadSector(17 + partition.Start); // Seek to spareblock, on logical sector 17
IntPtr bpbPtr = Marshal.AllocHGlobal(512); IntPtr bpbPtr = Marshal.AllocHGlobal(512);
Marshal.Copy(hpfs_bpb_sector, 0, bpbPtr, 512); Marshal.Copy(hpfsBpbSector, 0, bpbPtr, 512);
hpfs_bpb = (HPFS_BIOSParameterBlock)Marshal.PtrToStructure(bpbPtr, typeof(HPFS_BIOSParameterBlock)); HPFS_BIOSParameterBlock hpfsBpb = (HPFS_BIOSParameterBlock)Marshal.PtrToStructure(bpbPtr, typeof(HPFS_BIOSParameterBlock));
Marshal.FreeHGlobal(bpbPtr); Marshal.FreeHGlobal(bpbPtr);
IntPtr sbPtr = Marshal.AllocHGlobal(512); IntPtr sbPtr = Marshal.AllocHGlobal(512);
Marshal.Copy(hpfs_sb_sector, 0, sbPtr, 512); Marshal.Copy(hpfsSbSector, 0, sbPtr, 512);
hpfs_sb = (HPFS_SuperBlock)Marshal.PtrToStructure(sbPtr, typeof(HPFS_SuperBlock)); HPFS_SuperBlock hpfsSb = (HPFS_SuperBlock)Marshal.PtrToStructure(sbPtr, typeof(HPFS_SuperBlock));
Marshal.FreeHGlobal(sbPtr); Marshal.FreeHGlobal(sbPtr);
IntPtr spPtr = Marshal.AllocHGlobal(512); IntPtr spPtr = Marshal.AllocHGlobal(512);
Marshal.Copy(hpfs_sp_sector, 0, spPtr, 512); Marshal.Copy(hpfsSpSector, 0, spPtr, 512);
hpfs_sp = (HPFS_SpareBlock)Marshal.PtrToStructure(spPtr, typeof(HPFS_SpareBlock)); HPFS_SpareBlock hpfsSp = (HPFS_SpareBlock)Marshal.PtrToStructure(spPtr, typeof(HPFS_SpareBlock));
Marshal.FreeHGlobal(spPtr); Marshal.FreeHGlobal(spPtr);
if(StringHandlers.CToString(hpfs_bpb.fs_type) != "HPFS " || hpfs_sb.magic1 != 0xF995E849 || if(StringHandlers.CToString(hpfsBpb.fs_type) != "HPFS " || hpfsSb.magic1 != 0xF995E849 ||
hpfs_sb.magic2 != 0xFA53E9C5 || hpfs_sp.magic1 != 0xF9911849 || hpfs_sp.magic2 != 0xFA5229C5) hpfsSb.magic2 != 0xFA53E9C5 || hpfsSp.magic1 != 0xF9911849 || hpfsSp.magic2 != 0xFA5229C5)
{ {
sb.AppendLine("This may not be HPFS, following information may be not correct."); 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("File system type: \"{0}\" (Should be \"HPFS \")", hpfsBpb.fs_type).AppendLine();
sb.AppendFormat("Superblock magic1: 0x{0:X8} (Should be 0xF995E849)", hpfs_sb.magic1).AppendLine(); sb.AppendFormat("Superblock magic1: 0x{0:X8} (Should be 0xF995E849)", hpfsSb.magic1).AppendLine();
sb.AppendFormat("Superblock magic2: 0x{0:X8} (Should be 0xFA53E9C5)", hpfs_sb.magic2).AppendLine(); sb.AppendFormat("Superblock magic2: 0x{0:X8} (Should be 0xFA53E9C5)", hpfsSb.magic2).AppendLine();
sb.AppendFormat("Spareblock magic1: 0x{0:X8} (Should be 0xF9911849)", hpfs_sp.magic1).AppendLine(); sb.AppendFormat("Spareblock magic1: 0x{0:X8} (Should be 0xF9911849)", hpfsSp.magic1).AppendLine();
sb.AppendFormat("Spareblock magic2: 0x{0:X8} (Should be 0xFA5229C5)", hpfs_sp.magic2).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("OEM name: {0}", StringHandlers.CToString(hpfsBpb.oem_name)).AppendLine();
sb.AppendFormat("{0} bytes per sector", hpfs_bpb.bps).AppendLine(); sb.AppendFormat("{0} bytes per sector", hpfsBpb.bps).AppendLine();
// sb.AppendFormat("{0} sectors per cluster", hpfs_bpb.spc).AppendLine(); // sb.AppendFormat("{0} sectors per cluster", hpfs_bpb.spc).AppendLine();
// sb.AppendFormat("{0} reserved sectors", hpfs_bpb.rsectors).AppendLine(); // sb.AppendFormat("{0} reserved sectors", hpfs_bpb.rsectors).AppendLine();
// sb.AppendFormat("{0} FATs", hpfs_bpb.fats_no).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} entries on root directory", hpfs_bpb.root_ent).AppendLine();
// sb.AppendFormat("{0} mini sectors on volume", hpfs_bpb.sectors).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 FAT", hpfs_bpb.spfat).AppendLine();
// sb.AppendFormat("{0} sectors per track", hpfs_bpb.sptrk).AppendLine(); // sb.AppendFormat("{0} sectors per track", hpfs_bpb.sptrk).AppendLine();
// sb.AppendFormat("{0} heads", hpfs_bpb.heads).AppendLine(); // sb.AppendFormat("{0} heads", hpfs_bpb.heads).AppendLine();
sb.AppendFormat("{0} sectors hidden before BPB", hpfs_bpb.hsectors).AppendLine(); sb.AppendFormat("{0} sectors hidden before BPB", hpfsBpb.hsectors).AppendLine();
sb.AppendFormat("{0} sectors on volume ({1} bytes)", hpfs_sb.sectors, hpfs_sb.sectors * hpfs_bpb.bps) sb.AppendFormat("{0} sectors on volume ({1} bytes)", hpfsSb.sectors, hpfsSb.sectors * hpfsBpb.bps)
.AppendLine(); .AppendLine();
// sb.AppendFormat("{0} sectors on volume ({1} bytes)", hpfs_bpb.big_sectors, hpfs_bpb.big_sectors * hpfs_bpb.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("BIOS Drive Number: 0x{0:X2}", hpfsBpb.drive_no).AppendLine();
sb.AppendFormat("NT Flags: 0x{0:X2}", hpfs_bpb.nt_flags).AppendLine(); sb.AppendFormat("NT Flags: 0x{0:X2}", hpfsBpb.nt_flags).AppendLine();
sb.AppendFormat("Signature: 0x{0:X2}", hpfs_bpb.signature).AppendLine(); sb.AppendFormat("Signature: 0x{0:X2}", hpfsBpb.signature).AppendLine();
sb.AppendFormat("Serial number: 0x{0:X8}", hpfs_bpb.serial_no).AppendLine(); sb.AppendFormat("Serial number: 0x{0:X8}", hpfsBpb.serial_no).AppendLine();
sb.AppendFormat("Volume label: {0}", StringHandlers.CToString(hpfs_bpb.volume_label, CurrentEncoding)) sb.AppendFormat("Volume label: {0}", StringHandlers.CToString(hpfsBpb.volume_label, CurrentEncoding))
.AppendLine(); .AppendLine();
// sb.AppendFormat("Filesystem type: \"{0}\"", hpfs_bpb.fs_type).AppendLine(); // sb.AppendFormat("Filesystem type: \"{0}\"", hpfs_bpb.fs_type).AppendLine();
DateTime last_chk = DateHandlers.UNIXToDateTime(hpfs_sb.last_chkdsk); DateTime lastChk = DateHandlers.UNIXToDateTime(hpfsSb.last_chkdsk);
DateTime last_optim = DateHandlers.UNIXToDateTime(hpfs_sb.last_optim); DateTime lastOptim = DateHandlers.UNIXToDateTime(hpfsSb.last_optim);
sb.AppendFormat("HPFS version: {0}", hpfs_sb.version).AppendLine(); sb.AppendFormat("HPFS version: {0}", hpfsSb.version).AppendLine();
sb.AppendFormat("Functional version: {0}", hpfs_sb.func_version).AppendLine(); sb.AppendFormat("Functional version: {0}", hpfsSb.func_version).AppendLine();
sb.AppendFormat("Sector of root directory FNode: {0}", hpfs_sb.root_fnode).AppendLine(); sb.AppendFormat("Sector of root directory FNode: {0}", hpfsSb.root_fnode).AppendLine();
sb.AppendFormat("{0} sectors are marked bad", hpfs_sb.badblocks).AppendLine(); sb.AppendFormat("{0} sectors are marked bad", hpfsSb.badblocks).AppendLine();
sb.AppendFormat("Sector of free space bitmaps: {0}", hpfs_sb.bitmap_lsn).AppendLine(); sb.AppendFormat("Sector of free space bitmaps: {0}", hpfsSb.bitmap_lsn).AppendLine();
sb.AppendFormat("Sector of bad blocks list: {0}", hpfs_sb.badblock_lsn).AppendLine(); sb.AppendFormat("Sector of bad blocks list: {0}", hpfsSb.badblock_lsn).AppendLine();
if(hpfs_sb.last_chkdsk > 0) sb.AppendFormat("Date of last integrity check: {0}", last_chk).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"); 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"); else sb.AppendLine("Filesystem has never been optimized");
sb.AppendFormat("Directory band has {0} sectors", hpfs_sb.dband_sectors).AppendLine(); sb.AppendFormat("Directory band has {0} sectors", hpfsSb.dband_sectors).AppendLine();
sb.AppendFormat("Directory band starts at sector {0}", hpfs_sb.dband_start).AppendLine(); sb.AppendFormat("Directory band starts at sector {0}", hpfsSb.dband_start).AppendLine();
sb.AppendFormat("Directory band ends at sector {0}", hpfs_sb.dband_last).AppendLine(); sb.AppendFormat("Directory band ends at sector {0}", hpfsSb.dband_last).AppendLine();
sb.AppendFormat("Sector of directory band bitmap: {0}", hpfs_sb.dband_bitmap).AppendLine(); sb.AppendFormat("Sector of directory band bitmap: {0}", hpfsSb.dband_bitmap).AppendLine();
sb.AppendFormat("Sector of ACL directory: {0}", hpfs_sb.acl_start).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("Sector of Hotfix directory: {0}", hpfsSp.hotfix_start).AppendLine();
sb.AppendFormat("{0} used Hotfix entries", hpfs_sp.hotfix_used).AppendLine(); sb.AppendFormat("{0} used Hotfix entries", hpfsSp.hotfix_used).AppendLine();
sb.AppendFormat("{0} total Hotfix entries", hpfs_sp.hotfix_entries).AppendLine(); sb.AppendFormat("{0} total Hotfix entries", hpfsSp.hotfix_entries).AppendLine();
sb.AppendFormat("{0} free spare DNodes", hpfs_sp.spare_dnodes_free).AppendLine(); sb.AppendFormat("{0} free spare DNodes", hpfsSp.spare_dnodes_free).AppendLine();
sb.AppendFormat("{0} total spare DNodes", hpfs_sp.spare_dnodes).AppendLine(); sb.AppendFormat("{0} total spare DNodes", hpfsSp.spare_dnodes).AppendLine();
sb.AppendFormat("Sector of codepage directory: {0}", hpfs_sp.codepage_lsn).AppendLine(); sb.AppendFormat("Sector of codepage directory: {0}", hpfsSp.codepage_lsn).AppendLine();
sb.AppendFormat("{0} codepages used in the volume", hpfs_sp.codepages).AppendLine(); sb.AppendFormat("{0} codepages used in the volume", hpfsSp.codepages).AppendLine();
sb.AppendFormat("SuperBlock CRC32: {0:X8}", hpfs_sp.sb_crc32).AppendLine(); sb.AppendFormat("SuperBlock CRC32: {0:X8}", hpfsSp.sb_crc32).AppendLine();
sb.AppendFormat("SpareBlock CRC32: {0:X8}", hpfs_sp.sp_crc32).AppendLine(); sb.AppendFormat("SpareBlock CRC32: {0:X8}", hpfsSp.sp_crc32).AppendLine();
sb.AppendLine("Flags:"); sb.AppendLine("Flags:");
if((hpfs_sp.flags1 & 0x01) == 0x01) sb.AppendLine("Filesystem is dirty."); sb.AppendLine((hpfsSp.flags1 & 0x01) == 0x01 ? "Filesystem is dirty." : "Filesystem is clean.");
else sb.AppendLine("Filesystem is clean."); if((hpfsSp.flags1 & 0x02) == 0x02) sb.AppendLine("Spare directory blocks are in use");
if((hpfs_sp.flags1 & 0x02) == 0x02) sb.AppendLine("Spare directory blocks are in use"); if((hpfsSp.flags1 & 0x04) == 0x04) sb.AppendLine("Hotfixes are in use");
if((hpfs_sp.flags1 & 0x04) == 0x04) sb.AppendLine("Hotfixes are in use"); if((hpfsSp.flags1 & 0x08) == 0x08) sb.AppendLine("Disk contains bad sectors");
if((hpfs_sp.flags1 & 0x08) == 0x08) sb.AppendLine("Disk contains bad sectors"); if((hpfsSp.flags1 & 0x10) == 0x10) sb.AppendLine("Disk has a bad bitmap");
if((hpfs_sp.flags1 & 0x10) == 0x10) sb.AppendLine("Disk has a bad bitmap"); if((hpfsSp.flags1 & 0x20) == 0x20) sb.AppendLine("Filesystem was formatted fast");
if((hpfs_sp.flags1 & 0x20) == 0x20) sb.AppendLine("Filesystem was formatted fast"); if((hpfsSp.flags1 & 0x40) == 0x40) sb.AppendLine("Unknown flag 0x40 on flags1 is active");
if((hpfs_sp.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((hpfs_sp.flags1 & 0x80) == 0x80) sb.AppendLine("Filesystem has been mounted by an old IFS"); if((hpfsSp.flags2 & 0x01) == 0x01) sb.AppendLine("Install DASD limits");
if((hpfs_sp.flags2 & 0x01) == 0x01) sb.AppendLine("Install DASD limits"); if((hpfsSp.flags2 & 0x02) == 0x02) sb.AppendLine("Resync DASD limits");
if((hpfs_sp.flags2 & 0x02) == 0x02) sb.AppendLine("Resync DASD limits"); if((hpfsSp.flags2 & 0x04) == 0x04) sb.AppendLine("DASD limits are operational");
if((hpfs_sp.flags2 & 0x04) == 0x04) sb.AppendLine("DASD limits are operational"); if((hpfsSp.flags2 & 0x08) == 0x08) sb.AppendLine("Multimedia is active");
if((hpfs_sp.flags2 & 0x08) == 0x08) sb.AppendLine("Multimedia is active"); if((hpfsSp.flags2 & 0x10) == 0x10) sb.AppendLine("DCE ACLs are active");
if((hpfs_sp.flags2 & 0x10) == 0x10) sb.AppendLine("DCE ACLs are active"); if((hpfsSp.flags2 & 0x20) == 0x20) sb.AppendLine("DASD limits are dirty");
if((hpfs_sp.flags2 & 0x20) == 0x20) sb.AppendLine("DASD limits are dirty"); if((hpfsSp.flags2 & 0x40) == 0x40) sb.AppendLine("Unknown flag 0x40 on flags2 is active");
if((hpfs_sp.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");
if((hpfs_sp.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? // 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 && if(hpfsBpb.jump[0] == 0xEB && hpfsBpb.jump[1] > 0x3C && hpfsBpb.jump[1] < 0x80 &&
hpfs_bpb.signature2 == 0xAA55) hpfsBpb.signature2 == 0xAA55)
{ {
xmlFSType.Bootable = true; XmlFsType.Bootable = true;
Sha1Context sha1Ctx = new Sha1Context(); Sha1Context sha1Ctx = new Sha1Context();
sha1Ctx.Init(); 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.AppendLine("Volume is bootable");
sb.AppendFormat("Boot code's SHA1: {0}", bootChk).AppendLine(); sb.AppendFormat("Boot code's SHA1: {0}", bootChk).AppendLine();
} }
xmlFSType.Dirty |= (hpfs_sp.flags1 & 0x01) == 0x01; XmlFsType.Dirty |= (hpfsSp.flags1 & 0x01) == 0x01;
xmlFSType.Clusters = hpfs_sb.sectors; XmlFsType.Clusters = hpfsSb.sectors;
xmlFSType.ClusterSize = hpfs_bpb.bps; XmlFsType.ClusterSize = hpfsBpb.bps;
xmlFSType.Type = "HPFS"; XmlFsType.Type = "HPFS";
xmlFSType.VolumeName = StringHandlers.CToString(hpfs_bpb.volume_label, CurrentEncoding); XmlFsType.VolumeName = StringHandlers.CToString(hpfsBpb.volume_label, CurrentEncoding);
xmlFSType.VolumeSerial = $"{hpfs_bpb.serial_no:X8}"; XmlFsType.VolumeSerial = $"{hpfsBpb.serial_no:X8}";
xmlFSType.SystemIdentifier = StringHandlers.CToString(hpfs_bpb.oem_name); XmlFsType.SystemIdentifier = StringHandlers.CToString(hpfsBpb.oem_name);
information = sb.ToString(); information = sb.ToString();
} }

View File

@@ -43,21 +43,21 @@ namespace DiscImageChef.Filesystems.ISO9660
public ISO9660() public ISO9660()
{ {
Name = "ISO9660 Filesystem"; Name = "ISO9660 Filesystem";
PluginUUID = new Guid("d812f4d3-c357-400d-90fd-3b22ef786aa8"); PluginUuid = new Guid("d812f4d3-c357-400d-90fd-3b22ef786aa8");
CurrentEncoding = Encoding.ASCII; CurrentEncoding = Encoding.ASCII;
} }
public ISO9660(Encoding encoding) public ISO9660(Encoding encoding)
{ {
Name = "ISO9660 Filesystem"; Name = "ISO9660 Filesystem";
PluginUUID = new Guid("d812f4d3-c357-400d-90fd-3b22ef786aa8"); PluginUuid = new Guid("d812f4d3-c357-400d-90fd-3b22ef786aa8");
CurrentEncoding = encoding ?? Encoding.ASCII; CurrentEncoding = encoding ?? Encoding.ASCII;
} }
public ISO9660(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public ISO9660(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "ISO9660 Filesystem"; Name = "ISO9660 Filesystem";
PluginUUID = new Guid("d812f4d3-c357-400d-90fd-3b22ef786aa8"); PluginUuid = new Guid("d812f4d3-c357-400d-90fd-3b22ef786aa8");
CurrentEncoding = encoding ?? Encoding.ASCII; CurrentEncoding = encoding ?? Encoding.ASCII;
} }
} }

View File

@@ -213,7 +213,7 @@ namespace DiscImageChef.Filesystems.ISO9660
DecodedVolumeDescriptor decodedVd; DecodedVolumeDescriptor decodedVd;
DecodedVolumeDescriptor decodedJolietVd = new DecodedVolumeDescriptor(); DecodedVolumeDescriptor decodedJolietVd = new DecodedVolumeDescriptor();
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType();
if(pvd == null && hsvd == null && fsvd == null) if(pvd == null && hsvd == null && fsvd == null)
{ {
@@ -716,85 +716,85 @@ namespace DiscImageChef.Filesystems.ISO9660
exit_torito: exit_torito:
if(refareas.Count > 0) isoMetadata.Append(suspInformation); if(refareas.Count > 0) isoMetadata.Append(suspInformation);
xmlFSType.Type = fsFormat; XmlFsType.Type = fsFormat;
if(jolietvd != null) if(jolietvd != null)
{ {
xmlFSType.VolumeName = decodedJolietVd.VolumeIdentifier; XmlFsType.VolumeName = decodedJolietVd.VolumeIdentifier;
if(decodedJolietVd.SystemIdentifier == null || if(decodedJolietVd.SystemIdentifier == null ||
decodedVd.SystemIdentifier.Length > decodedJolietVd.SystemIdentifier.Length) decodedVd.SystemIdentifier.Length > decodedJolietVd.SystemIdentifier.Length)
xmlFSType.SystemIdentifier = decodedVd.SystemIdentifier; XmlFsType.SystemIdentifier = decodedVd.SystemIdentifier;
else xmlFSType.SystemIdentifier = decodedJolietVd.SystemIdentifier; else XmlFsType.SystemIdentifier = decodedJolietVd.SystemIdentifier;
if(decodedJolietVd.VolumeSetIdentifier == null || decodedVd.VolumeSetIdentifier.Length > if(decodedJolietVd.VolumeSetIdentifier == null || decodedVd.VolumeSetIdentifier.Length >
decodedJolietVd.VolumeSetIdentifier.Length) decodedJolietVd.VolumeSetIdentifier.Length)
xmlFSType.VolumeSetIdentifier = decodedVd.VolumeSetIdentifier; XmlFsType.VolumeSetIdentifier = decodedVd.VolumeSetIdentifier;
else xmlFSType.VolumeSetIdentifier = decodedJolietVd.VolumeSetIdentifier; else XmlFsType.VolumeSetIdentifier = decodedJolietVd.VolumeSetIdentifier;
if(decodedJolietVd.PublisherIdentifier == null || decodedVd.PublisherIdentifier.Length > if(decodedJolietVd.PublisherIdentifier == null || decodedVd.PublisherIdentifier.Length >
decodedJolietVd.PublisherIdentifier.Length) decodedJolietVd.PublisherIdentifier.Length)
xmlFSType.PublisherIdentifier = decodedVd.PublisherIdentifier; XmlFsType.PublisherIdentifier = decodedVd.PublisherIdentifier;
else xmlFSType.PublisherIdentifier = decodedJolietVd.PublisherIdentifier; else XmlFsType.PublisherIdentifier = decodedJolietVd.PublisherIdentifier;
if(decodedJolietVd.DataPreparerIdentifier == null || decodedVd.DataPreparerIdentifier.Length > if(decodedJolietVd.DataPreparerIdentifier == null || decodedVd.DataPreparerIdentifier.Length >
decodedJolietVd.DataPreparerIdentifier.Length) decodedJolietVd.DataPreparerIdentifier.Length)
xmlFSType.DataPreparerIdentifier = decodedVd.DataPreparerIdentifier; XmlFsType.DataPreparerIdentifier = decodedVd.DataPreparerIdentifier;
else xmlFSType.DataPreparerIdentifier = decodedJolietVd.SystemIdentifier; else XmlFsType.DataPreparerIdentifier = decodedJolietVd.SystemIdentifier;
if(decodedJolietVd.ApplicationIdentifier == null || decodedVd.ApplicationIdentifier.Length > if(decodedJolietVd.ApplicationIdentifier == null || decodedVd.ApplicationIdentifier.Length >
decodedJolietVd.ApplicationIdentifier.Length) decodedJolietVd.ApplicationIdentifier.Length)
xmlFSType.ApplicationIdentifier = decodedVd.ApplicationIdentifier; XmlFsType.ApplicationIdentifier = decodedVd.ApplicationIdentifier;
else xmlFSType.ApplicationIdentifier = decodedJolietVd.SystemIdentifier; else XmlFsType.ApplicationIdentifier = decodedJolietVd.SystemIdentifier;
xmlFSType.CreationDate = decodedJolietVd.CreationTime; XmlFsType.CreationDate = decodedJolietVd.CreationTime;
xmlFSType.CreationDateSpecified = true; XmlFsType.CreationDateSpecified = true;
if(decodedJolietVd.HasModificationTime) if(decodedJolietVd.HasModificationTime)
{ {
xmlFSType.ModificationDate = decodedJolietVd.ModificationTime; XmlFsType.ModificationDate = decodedJolietVd.ModificationTime;
xmlFSType.ModificationDateSpecified = true; XmlFsType.ModificationDateSpecified = true;
} }
if(decodedJolietVd.HasExpirationTime) if(decodedJolietVd.HasExpirationTime)
{ {
xmlFSType.ExpirationDate = decodedJolietVd.ExpirationTime; XmlFsType.ExpirationDate = decodedJolietVd.ExpirationTime;
xmlFSType.ExpirationDateSpecified = true; XmlFsType.ExpirationDateSpecified = true;
} }
if(decodedJolietVd.HasEffectiveTime) if(decodedJolietVd.HasEffectiveTime)
{ {
xmlFSType.EffectiveDate = decodedJolietVd.EffectiveTime; XmlFsType.EffectiveDate = decodedJolietVd.EffectiveTime;
xmlFSType.EffectiveDateSpecified = true; XmlFsType.EffectiveDateSpecified = true;
} }
} }
else else
{ {
xmlFSType.SystemIdentifier = decodedVd.SystemIdentifier; XmlFsType.SystemIdentifier = decodedVd.SystemIdentifier;
xmlFSType.VolumeName = decodedVd.VolumeIdentifier; XmlFsType.VolumeName = decodedVd.VolumeIdentifier;
xmlFSType.VolumeSetIdentifier = decodedVd.VolumeSetIdentifier; XmlFsType.VolumeSetIdentifier = decodedVd.VolumeSetIdentifier;
xmlFSType.PublisherIdentifier = decodedVd.PublisherIdentifier; XmlFsType.PublisherIdentifier = decodedVd.PublisherIdentifier;
xmlFSType.DataPreparerIdentifier = decodedVd.DataPreparerIdentifier; XmlFsType.DataPreparerIdentifier = decodedVd.DataPreparerIdentifier;
xmlFSType.ApplicationIdentifier = decodedVd.ApplicationIdentifier; XmlFsType.ApplicationIdentifier = decodedVd.ApplicationIdentifier;
xmlFSType.CreationDate = decodedVd.CreationTime; XmlFsType.CreationDate = decodedVd.CreationTime;
xmlFSType.CreationDateSpecified = true; XmlFsType.CreationDateSpecified = true;
if(decodedVd.HasModificationTime) if(decodedVd.HasModificationTime)
{ {
xmlFSType.ModificationDate = decodedVd.ModificationTime; XmlFsType.ModificationDate = decodedVd.ModificationTime;
xmlFSType.ModificationDateSpecified = true; XmlFsType.ModificationDateSpecified = true;
} }
if(decodedVd.HasExpirationTime) if(decodedVd.HasExpirationTime)
{ {
xmlFSType.ExpirationDate = decodedVd.ExpirationTime; XmlFsType.ExpirationDate = decodedVd.ExpirationTime;
xmlFSType.ExpirationDateSpecified = true; XmlFsType.ExpirationDateSpecified = true;
} }
if(decodedVd.HasEffectiveTime) if(decodedVd.HasEffectiveTime)
{ {
xmlFSType.EffectiveDate = decodedVd.EffectiveTime; XmlFsType.EffectiveDate = decodedVd.EffectiveTime;
xmlFSType.EffectiveDateSpecified = true; XmlFsType.EffectiveDateSpecified = true;
} }
} }
xmlFSType.Bootable |= bvd != null || segaCd != null || saturn != null || dreamcast != null; XmlFsType.Bootable |= bvd != null || segaCd != null || saturn != null || dreamcast != null;
xmlFSType.Clusters = decodedVd.Blocks; XmlFsType.Clusters = decodedVd.Blocks;
xmlFSType.ClusterSize = decodedVd.BlockSize; XmlFsType.ClusterSize = decodedVd.BlockSize;
information = isoMetadata.ToString(); information = isoMetadata.ToString();
} }

View File

@@ -131,35 +131,33 @@ namespace DiscImageChef.Filesystems
public Guid s_loguuid; public Guid s_loguuid;
} }
const uint JFS_BootBlocksSize = 0x8000; const uint JFS_BOOT_BLOCKS_SIZE = 0x8000;
const uint JFS_Magic = 0x3153464A; const uint JFS_MAGIC = 0x3153464A;
public JFS() public JFS()
{ {
Name = "JFS Plugin"; 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"); CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
} }
public JFS(Encoding encoding) public JFS(Encoding encoding)
{ {
Name = "JFS Plugin"; Name = "JFS Plugin";
PluginUUID = new Guid("D3BE2A41-8F28-4055-94DC-BB6C72A0E9C4"); PluginUuid = new Guid("D3BE2A41-8F28-4055-94DC-BB6C72A0E9C4");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public JFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public JFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "JFS Plugin"; Name = "JFS Plugin";
PluginUUID = new Guid("D3BE2A41-8F28-4055-94DC-BB6C72A0E9C4"); PluginUuid = new Guid("D3BE2A41-8F28-4055-94DC-BB6C72A0E9C4");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public override bool Identify(ImagePlugin imagePlugin, Partition partition) 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; if(partition.Start + bootSectors >= partition.End) return false;
byte[] sector = imagePlugin.ReadSector(partition.Start + bootSectors); byte[] sector = imagePlugin.ReadSector(partition.Start + bootSectors);
@@ -171,7 +169,7 @@ namespace DiscImageChef.Filesystems
jfsSb = (JFS_SuperBlock)Marshal.PtrToStructure(sbPtr, typeof(JFS_SuperBlock)); jfsSb = (JFS_SuperBlock)Marshal.PtrToStructure(sbPtr, typeof(JFS_SuperBlock));
Marshal.FreeHGlobal(sbPtr); Marshal.FreeHGlobal(sbPtr);
return jfsSb.s_magic == JFS_Magic; return jfsSb.s_magic == JFS_MAGIC;
} }
public override void GetInformation(ImagePlugin imagePlugin, Partition partition, public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
@@ -179,7 +177,7 @@ namespace DiscImageChef.Filesystems
{ {
information = ""; information = "";
StringBuilder sb = new StringBuilder(); 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); byte[] sector = imagePlugin.ReadSector(partition.Start + bootSectors);
if(sector.Length < 512) return; if(sector.Length < 512) return;
@@ -228,17 +226,18 @@ namespace DiscImageChef.Filesystems
else sb.AppendFormat("Volume name: {0}", CurrentEncoding.GetString(jfsSb.s_label)).AppendLine(); else sb.AppendFormat("Volume name: {0}", CurrentEncoding.GetString(jfsSb.s_label)).AppendLine();
sb.AppendFormat("Volume UUID: {0}", jfsSb.s_uuid).AppendLine(); sb.AppendFormat("Volume UUID: {0}", jfsSb.s_uuid).AppendLine();
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType
xmlFSType.Type = "JFS filesystem"; {
xmlFSType.Clusters = (long)jfsSb.s_size; Type = "JFS filesystem",
xmlFSType.ClusterSize = (int)jfsSb.s_bsize; Clusters = (long)jfsSb.s_size,
xmlFSType.Bootable = true; ClusterSize = (int)jfsSb.s_bsize,
if(jfsSb.s_version == 1) xmlFSType.VolumeName = CurrentEncoding.GetString(jfsSb.s_fpack); Bootable = true,
else xmlFSType.VolumeName = CurrentEncoding.GetString(jfsSb.s_label); VolumeName = CurrentEncoding.GetString(jfsSb.s_version == 1 ? jfsSb.s_fpack : jfsSb.s_label),
xmlFSType.VolumeSerial = $"{jfsSb.s_uuid}"; VolumeSerial = $"{jfsSb.s_uuid}",
xmlFSType.ModificationDate = DateHandlers.UNIXUnsignedToDateTime(jfsSb.s_time.tv_sec, jfsSb.s_time.tv_nsec); ModificationDate = DateHandlers.UNIXUnsignedToDateTime(jfsSb.s_time.tv_sec, jfsSb.s_time.tv_nsec),
xmlFSType.ModificationDateSpecified = true; ModificationDateSpecified = true
if(jfsSb.s_state != 0) xmlFSType.Dirty = true; };
if(jfsSb.s_state != 0) XmlFsType.Dirty = true;
information = sb.ToString(); information = sb.ToString();
} }

View File

@@ -61,42 +61,38 @@ namespace DiscImageChef.Filesystems
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] public byte[] creationDate; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] public byte[] creationDate;
} }
const uint LIF_Magic = 0x8000; const uint LIF_MAGIC = 0x8000;
public LIF() public LIF()
{ {
Name = "HP Logical Interchange Format Plugin"; 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"); CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
} }
public LIF(Encoding encoding) public LIF(Encoding encoding)
{ {
Name = "HP Logical Interchange Format Plugin"; Name = "HP Logical Interchange Format Plugin";
PluginUUID = new Guid("41535647-77A5-477B-9206-DA727ACDC704"); PluginUuid = new Guid("41535647-77A5-477B-9206-DA727ACDC704");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public LIF(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public LIF(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "HP Logical Interchange Format Plugin"; Name = "HP Logical Interchange Format Plugin";
PluginUUID = new Guid("41535647-77A5-477B-9206-DA727ACDC704"); PluginUuid = new Guid("41535647-77A5-477B-9206-DA727ACDC704");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public override bool Identify(ImagePlugin imagePlugin, Partition partition) public override bool Identify(ImagePlugin imagePlugin, Partition partition)
{ {
if(imagePlugin.GetSectorSize() < 256) return false; if(imagePlugin.GetSectorSize() < 256) return false;
LIF_SystemBlock LIFSb;
byte[] sector = imagePlugin.ReadSector(partition.Start); byte[] sector = imagePlugin.ReadSector(partition.Start);
LIFSb = BigEndianMarshal.ByteArrayToStructureBigEndian<LIF_SystemBlock>(sector); LIF_SystemBlock lifSb = BigEndianMarshal.ByteArrayToStructureBigEndian<LIF_SystemBlock>(sector);
DicConsole.DebugWriteLine("LIF plugin", "magic 0x{0:X8} (expected 0x{1:X8})", LIFSb.magic, LIF_Magic); 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, public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
@@ -106,38 +102,36 @@ namespace DiscImageChef.Filesystems
if(imagePlugin.GetSectorSize() < 256) return; if(imagePlugin.GetSectorSize() < 256) return;
LIF_SystemBlock LIFSb;
byte[] sector = imagePlugin.ReadSector(partition.Start); 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(); StringBuilder sb = new StringBuilder();
sb.AppendLine("HP Logical Interchange Format"); sb.AppendLine("HP Logical Interchange Format");
sb.AppendFormat("Directory starts at cluster {0}", LIFSb.directoryStart).AppendLine(); sb.AppendFormat("Directory starts at cluster {0}", lifSb.directoryStart).AppendLine();
sb.AppendFormat("LIF identifier: {0}", LIFSb.lifId).AppendLine(); sb.AppendFormat("LIF identifier: {0}", lifSb.lifId).AppendLine();
sb.AppendFormat("Directory size: {0} clusters", LIFSb.directorySize).AppendLine(); sb.AppendFormat("Directory size: {0} clusters", lifSb.directorySize).AppendLine();
sb.AppendFormat("LIF version: {0}", LIFSb.lifVersion).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 // 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} tracks", lifSb.tracks).AppendLine();
sb.AppendFormat("{0} heads", LIFSb.heads).AppendLine(); sb.AppendFormat("{0} heads", lifSb.heads).AppendLine();
sb.AppendFormat("{0} sectors", LIFSb.sectors).AppendLine(); sb.AppendFormat("{0} sectors", lifSb.sectors).AppendLine();
sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(LIFSb.volumeLabel, CurrentEncoding)) sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(lifSb.volumeLabel, CurrentEncoding))
.AppendLine(); .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(); information = sb.ToString();
xmlFSType = new FileSystemType XmlFsType = new FileSystemType
{ {
Type = "HP Logical Interchange Format", Type = "HP Logical Interchange Format",
ClusterSize = 256, ClusterSize = 256,
Clusters = (long)(partition.Size / 256), Clusters = (long)(partition.Size / 256),
CreationDate = DateHandlers.LifToDateTime(LIFSb.creationDate), CreationDate = DateHandlers.LifToDateTime(lifSb.creationDate),
CreationDateSpecified = true, CreationDateSpecified = true,
VolumeName = StringHandlers.CToString(LIFSb.volumeLabel, CurrentEncoding) VolumeName = StringHandlers.CToString(lifSb.volumeLabel, CurrentEncoding)
}; };
} }

View File

@@ -38,13 +38,13 @@ namespace DiscImageChef.Filesystems.LisaFS
/// Lisa FS v1, from Lisa OS 1.0 (Workshop or Office) /// Lisa FS v1, from Lisa OS 1.0 (Workshop or Office)
/// Never seen on Sony floppies. /// Never seen on Sony floppies.
/// </summary> /// </summary>
const byte LisaFSv1 = 0x0E; const byte LISA_V1 = 0x0E;
/// <summary> /// <summary>
/// Lisa FS v2, from Lisa OS 2.0 (Workshop or Office) /// Lisa FS v2, from Lisa OS 2.0 (Workshop or Office)
/// Contrary to what most information online says the only difference with V1 /// Contrary to what most information online says the only difference with V1
/// is the Extents File size. Catalog format is the same /// is the Extents File size. Catalog format is the same
/// </summary> /// </summary>
const byte LisaFSv2 = 0x0F; const byte LISA_V2 = 0x0F;
/// <summary> /// <summary>
/// Lisa FS v3, from Lisa OS 3.0 (Workshop or Office) /// Lisa FS v3, from Lisa OS 3.0 (Workshop or Office)
/// Adds support for user catalogs (aka subdirectories), /// 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 /// Uses '-' as path separator (so people that created Lisa/FILE.TEXT just
/// created a file named like that :p) /// created a file named like that :p)
/// </summary> /// </summary>
const byte LisaFSv3 = 0x11; const byte LISA_V3 = 0x11;
/// <summary>Maximum string size in LisaFS</summary> /// <summary>Maximum string size in LisaFS</summary>
const uint E_NAME = 32; const uint E_NAME = 32;
/// <summary> /// <summary>

View File

@@ -58,9 +58,7 @@ namespace DiscImageChef.Filesystems.LisaFS
/// <param name="contents">Directory contents.</param> /// <param name="contents">Directory contents.</param>
public override Errno ReadDir(string path, ref List<string> contents) public override Errno ReadDir(string path, ref List<string> contents)
{ {
short fileId; Errno error = LookupFileId(path, out short fileId, out bool isDir);
bool isDir;
Errno error = LookupFileId(path, out fileId, out isDir);
if(error != Errno.NoError) return error; if(error != Errno.NoError) return error;
if(!isDir) return Errno.NotDirectory; if(!isDir) return Errno.NotDirectory;
@@ -106,13 +104,10 @@ namespace DiscImageChef.Filesystems.LisaFS
catalogCache = new List<CatalogEntry>(); catalogCache = new List<CatalogEntry>();
Errno error;
// Do differently for V1 and V2 // Do differently for V1 and V2
if(mddf.fsversion == LisaFSv2 || mddf.fsversion == LisaFSv1) if(mddf.fsversion == LISA_V2 || mddf.fsversion == LISA_V1)
{ {
byte[] buf; Errno error = ReadFile((short)FILEID_CATALOG, out byte[] buf);
error = ReadFile((short)FILEID_CATALOG, out buf);
if(error != Errno.NoError) return error; if(error != Errno.NoError) return error;
int offset = 0; int offset = 0;
@@ -142,18 +137,19 @@ namespace DiscImageChef.Filesystems.LisaFS
// Convert entries to V3 format // Convert entries to V3 format
foreach(CatalogEntryV2 entV2 in catalogV2) foreach(CatalogEntryV2 entV2 in catalogV2)
{ {
ExtentFile ext; error = ReadExtentsFile(entV2.fileID, out ExtentFile ext);
error = ReadExtentsFile(entV2.fileID, out ext);
if(error != Errno.NoError) continue; if(error != Errno.NoError) continue;
CatalogEntry entV3 = new CatalogEntry(); CatalogEntry entV3 = new CatalogEntry
entV3.fileID = entV2.fileID; {
entV3.filename = new byte[32]; 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); 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); 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? // 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++) for(ulong i = 0; i < device.GetSectors(); i++)
{ {
LisaTag.PriamTag catTag; DecodeTag(device.ReadSectorTag(i, SectorTagType.AppleSectorTag), out LisaTag.PriamTag catTag);
DecodeTag(device.ReadSectorTag(i, SectorTagType.AppleSectorTag), out catTag);
if(catTag.FileId != FILEID_CATALOG || catTag.RelPage != 0) continue; 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 // Traverse double-linked list until first catalog block
while(prevCatalogPointer != 0xFFFFFFFF) while(prevCatalogPointer != 0xFFFFFFFF)
{ {
LisaTag.PriamTag prevTag;
DecodeTag(device.ReadSectorTag(prevCatalogPointer + mddf.mddf_block + volumePrefix, SectorTagType.AppleSectorTag), DecodeTag(device.ReadSectorTag(prevCatalogPointer + mddf.mddf_block + volumePrefix, SectorTagType.AppleSectorTag),
out prevTag); out LisaTag.PriamTag prevTag);
if(prevTag.FileId != FILEID_CATALOG) return Errno.InvalidArgument; if(prevTag.FileId != FILEID_CATALOG) return Errno.InvalidArgument;
@@ -199,15 +193,13 @@ namespace DiscImageChef.Filesystems.LisaFS
ulong nextCatalogPointer; ulong nextCatalogPointer;
nextCatalogPointer = BigEndianBitConverter.ToUInt32(firstCatalogBlock, 0x7FA); nextCatalogPointer = BigEndianBitConverter.ToUInt32(firstCatalogBlock, 0x7FA);
List<byte[]> catalogBlocks = new List<byte[]>(); List<byte[]> catalogBlocks = new List<byte[]> {firstCatalogBlock};
catalogBlocks.Add(firstCatalogBlock);
// Traverse double-linked list to read full catalog // Traverse double-linked list to read full catalog
while(nextCatalogPointer != 0xFFFFFFFF) while(nextCatalogPointer != 0xFFFFFFFF)
{ {
LisaTag.PriamTag nextTag;
DecodeTag(device.ReadSectorTag(nextCatalogPointer + mddf.mddf_block + volumePrefix, SectorTagType.AppleSectorTag), DecodeTag(device.ReadSectorTag(nextCatalogPointer + mddf.mddf_block + volumePrefix, SectorTagType.AppleSectorTag),
out nextTag); out LisaTag.PriamTag nextTag);
if(nextTag.FileId != FILEID_CATALOG) return Errno.InvalidArgument; if(nextTag.FileId != FILEID_CATALOG) return Errno.InvalidArgument;
@@ -232,24 +224,25 @@ namespace DiscImageChef.Filesystems.LisaFS
// Normal entry // Normal entry
else if(buf[offset + 0x24] == 0x03 && buf[offset] == 0x24) else if(buf[offset + 0x24] == 0x03 && buf[offset] == 0x24)
{ {
CatalogEntry entry = new CatalogEntry(); CatalogEntry entry = new CatalogEntry
entry.marker = buf[offset]; {
entry.parentID = BigEndianBitConverter.ToUInt16(buf, offset + 0x01); marker = buf[offset],
entry.filename = new byte[E_NAME]; 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); 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); Array.Copy(buf, offset + 0x38, entry.tail, 0, 8);
ExtentFile ext; if(ReadExtentsFile(entry.fileID, out _) == Errno.NoError)
if(ReadExtentsFile(entry.fileID, out ext) == Errno.NoError)
if(!fileSizeCache.ContainsKey(entry.fileID)) if(!fileSizeCache.ContainsKey(entry.fileID))
{ {
catalogCache.Add(entry); catalogCache.Add(entry);
@@ -261,23 +254,25 @@ namespace DiscImageChef.Filesystems.LisaFS
// Subdirectory entry // Subdirectory entry
else if(buf[offset + 0x24] == 0x01 && buf[offset] == 0x24) else if(buf[offset + 0x24] == 0x01 && buf[offset] == 0x24)
{ {
CatalogEntry entry = new CatalogEntry(); CatalogEntry entry = new CatalogEntry
entry.marker = buf[offset]; {
entry.parentID = BigEndianBitConverter.ToUInt16(buf, offset + 0x01); marker = buf[offset],
entry.filename = new byte[E_NAME]; 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); 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)) if(!directoryDtcCache.ContainsKey(entry.fileID))
directoryDTCCache.Add(entry.fileID, DateHandlers.LisaToDateTime(entry.dtc)); directoryDtcCache.Add(entry.fileID, DateHandlers.LisaToDateTime(entry.dtc));
catalogCache.Add(entry); catalogCache.Add(entry);
@@ -295,21 +290,22 @@ namespace DiscImageChef.Filesystems.LisaFS
if(!mounted) return Errno.AccessDenied; if(!mounted) return Errno.AccessDenied;
stat = new FileEntryInfo(); stat = new FileEntryInfo
stat.Attributes = new FileAttributes(); {
DateTime tmp; 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.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; return Errno.NoError;
} }

View File

@@ -57,7 +57,7 @@ namespace DiscImageChef.Filesystems.LisaFS
if(!mounted) return Errno.AccessDenied; 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; return Errno.InvalidArgument;
if(extentCache.TryGetValue(fileId, out file)) return Errno.NoError; 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; if(extTag.FileId != (short)(-1 * fileId)) return Errno.NoSuchFile;
byte[] sector; byte[] sector = mddf.fsversion == LISA_V1 ? device.ReadSectors(ptr, 2) : device.ReadSector(ptr);
if(mddf.fsversion == LisaFSv1) sector = device.ReadSectors(ptr, 2);
else sector = device.ReadSector(ptr);
if(sector[0] >= 32 || sector[0] == 0) return Errno.InvalidArgument; if(sector[0] >= 32 || sector[0] == 0) return Errno.InvalidArgument;
@@ -151,7 +148,7 @@ namespace DiscImageChef.Filesystems.LisaFS
int extentsCount = 0; int extentsCount = 0;
int extentsOffset; int extentsOffset;
if(mddf.fsversion == LisaFSv1) if(mddf.fsversion == LISA_V1)
{ {
file.length = BigEndianBitConverter.ToInt32(sector, 0x200); file.length = BigEndianBitConverter.ToInt32(sector, 0x200);
file.unknown9 = BigEndianBitConverter.ToInt32(sector, 0x204); file.unknown9 = BigEndianBitConverter.ToInt32(sector, 0x204);
@@ -175,9 +172,11 @@ namespace DiscImageChef.Filesystems.LisaFS
for(int j = 0; j < extentsCount; j++) for(int j = 0; j < extentsCount; j++)
{ {
file.extents[j] = new Extent(); 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); start = BigEndianBitConverter.ToInt32(sector, extentsOffset + j * 6),
length = BigEndianBitConverter.ToInt16(sector, extentsOffset + j * 6 + 4)
};
} }
extentCache.Add(fileId, file); extentCache.Add(fileId, file);
@@ -278,11 +277,13 @@ namespace DiscImageChef.Filesystems.LisaFS
for(int s = 0; s < srecords.Length; s++) for(int s = 0; s < srecords.Length; s++)
{ {
srecords[s] = new SRecord(); srecords[s] = new SRecord
srecords[s].extent_ptr = BigEndianBitConverter.ToUInt32(sectors, 0x00 + 14 * s); {
srecords[s].unknown = BigEndianBitConverter.ToUInt32(sectors, 0x04 + 14 * s); extent_ptr = BigEndianBitConverter.ToUInt32(sectors, 0x00 + 14 * s),
srecords[s].filesize = BigEndianBitConverter.ToUInt32(sectors, 0x08 + 14 * s); unknown = BigEndianBitConverter.ToUInt32(sectors, 0x04 + 14 * s),
srecords[s].flags = BigEndianBitConverter.ToUInt16(sectors, 0x0C + 14 * s); filesize = BigEndianBitConverter.ToUInt32(sectors, 0x08 + 14 * s),
flags = BigEndianBitConverter.ToUInt16(sectors, 0x0C + 14 * s)
};
} }
return Errno.NoError; return Errno.NoError;

View File

@@ -41,9 +41,7 @@ namespace DiscImageChef.Filesystems.LisaFS
{ {
public override Errno GetAttributes(string path, ref FileAttributes attributes) public override Errno GetAttributes(string path, ref FileAttributes attributes)
{ {
short fileId; Errno error = LookupFileId(path, out short fileId, out bool isDir);
bool isDir;
Errno error = LookupFileId(path, out fileId, out isDir);
if(error != Errno.NoError) return error; if(error != Errno.NoError) return error;
if(!isDir) return GetAttributes(fileId, ref attributes); if(!isDir) return GetAttributes(fileId, ref attributes);
@@ -64,9 +62,7 @@ namespace DiscImageChef.Filesystems.LisaFS
if(offset < 0) return Errno.InvalidArgument; if(offset < 0) return Errno.InvalidArgument;
short fileId; Errno error = LookupFileId(path, out short fileId, out _);
bool isDir;
Errno error = LookupFileId(path, out fileId, out isDir);
if(error != Errno.NoError) return error; if(error != Errno.NoError) return error;
byte[] tmp; byte[] tmp;
@@ -100,9 +96,7 @@ namespace DiscImageChef.Filesystems.LisaFS
public override Errno Stat(string path, ref FileEntryInfo stat) public override Errno Stat(string path, ref FileEntryInfo stat)
{ {
short fileId; Errno error = LookupFileId(path, out short fileId, out bool isDir);
bool isDir;
Errno error = LookupFileId(path, out fileId, out isDir);
if(error != Errno.NoError) return error; if(error != Errno.NoError) return error;
return isDir ? StatDir(fileId, out stat) : Stat(fileId, out stat); return isDir ? StatDir(fileId, out stat) : Stat(fileId, out stat);
@@ -125,8 +119,7 @@ namespace DiscImageChef.Filesystems.LisaFS
return Errno.NoError; return Errno.NoError;
} }
ExtentFile extFile; Errno error = ReadExtentsFile(fileId, out ExtentFile extFile);
Errno error = ReadExtentsFile(fileId, out extFile);
if(error != Errno.NoError) return error; if(error != Errno.NoError) return error;
@@ -200,8 +193,7 @@ namespace DiscImageChef.Filesystems.LisaFS
if(count == 0) return Errno.NoSuchFile; if(count == 0) return Errno.NoSuchFile;
if(!tags) buf = new byte[count * device.GetSectorSize()]; buf = !tags ? new byte[count * device.GetSectorSize()] : new byte[count * devTagSize];
else buf = new byte[count * devTagSize];
// Should be enough to check 100 sectors? // Should be enough to check 100 sectors?
for(ulong i = 0; i < 100; i++) for(ulong i = 0; i < 100; i++)
@@ -210,10 +202,7 @@ namespace DiscImageChef.Filesystems.LisaFS
if(sysTag.FileId != fileId) continue; if(sysTag.FileId != fileId) continue;
byte[] sector; byte[] sector = !tags ? device.ReadSector(i) : device.ReadSectorTag(i, SectorTagType.AppleSectorTag);
if(!tags) sector = device.ReadSector(i);
else sector = device.ReadSectorTag(i, SectorTagType.AppleSectorTag);
// Relative block for $Loader starts at $Boot block // Relative block for $Loader starts at $Boot block
if(sysTag.FileId == FILEID_LOADER_SIGNED) sysTag.RelPage--; if(sysTag.FileId == FILEID_LOADER_SIGNED) sysTag.RelPage--;
@@ -239,8 +228,7 @@ namespace DiscImageChef.Filesystems.LisaFS
if(!debug || fileId == 0) return Errno.NoSuchFile; if(!debug || fileId == 0) return Errno.NoSuchFile;
else else
{ {
stat = new FileEntryInfo(); stat = new FileEntryInfo {Attributes = new FileAttributes()};
stat.Attributes = new FileAttributes();
error = GetAttributes(fileId, ref stat.Attributes); error = GetAttributes(fileId, ref stat.Attributes);
if(error != Errno.NoError) return error; if(error != Errno.NoError) return error;
@@ -267,12 +255,10 @@ namespace DiscImageChef.Filesystems.LisaFS
} }
else else
{ {
byte[] buf; error = ReadSystemFile(fileId, out byte[] buf);
error = ReadSystemFile(fileId, out buf);
if(error != Errno.NoError) return error; if(error != Errno.NoError) return error;
if(fileId != 4) stat.CreationTime = mddf.dtvc; stat.CreationTime = fileId != 4 ? mddf.dtvc : mddf.dtcc;
else stat.CreationTime = mddf.dtcc;
stat.BackupTime = mddf.dtvb; stat.BackupTime = mddf.dtvb;
@@ -290,8 +276,7 @@ namespace DiscImageChef.Filesystems.LisaFS
return Errno.NoError; return Errno.NoError;
} }
stat = new FileEntryInfo(); stat = new FileEntryInfo {Attributes = new FileAttributes()};
stat.Attributes = new FileAttributes();
error = GetAttributes(fileId, ref stat.Attributes); error = GetAttributes(fileId, ref stat.Attributes);
if(error != Errno.NoError) return error; if(error != Errno.NoError) return error;
@@ -309,8 +294,7 @@ namespace DiscImageChef.Filesystems.LisaFS
stat.UID = 0; stat.UID = 0;
stat.GID = 0; stat.GID = 0;
stat.DeviceNo = 0; stat.DeviceNo = 0;
int len; if(!fileSizeCache.TryGetValue(fileId, out int len)) stat.Length = srecords[fileId].filesize;
if(!fileSizeCache.TryGetValue(fileId, out len)) stat.Length = srecords[fileId].filesize;
else stat.Length = len; else stat.Length = len;
stat.BlockSize = mddf.datasize; stat.BlockSize = mddf.datasize;
stat.Blocks = file.length; stat.Blocks = file.length;
@@ -330,15 +314,12 @@ namespace DiscImageChef.Filesystems.LisaFS
tags &= debug; 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; return Errno.InvalidArgument;
if(!tags && fileCache.TryGetValue(fileId, out buf)) return Errno.NoError; if(!tags && fileCache.TryGetValue(fileId, out buf)) return Errno.NoError;
Errno error; Errno error = ReadExtentsFile(fileId, out ExtentFile file);
ExtentFile file;
error = ReadExtentsFile(fileId, out file);
if(error != Errno.NoError) return error; if(error != Errno.NoError) return error;
int sectorSize; int sectorSize;
@@ -365,8 +346,7 @@ namespace DiscImageChef.Filesystems.LisaFS
if(!tags) if(!tags)
{ {
int realSize; if(fileSizeCache.TryGetValue(fileId, out int realSize)) if(realSize > temp.Length) DicConsole.ErrorWriteLine("File {0} gets truncated.", fileId);
if(fileSizeCache.TryGetValue(fileId, out realSize)) if(realSize > temp.Length) DicConsole.ErrorWriteLine("File {0} gets truncated.", fileId);
buf = temp; buf = temp;
fileCache.Add(fileId, buf); fileCache.Add(fileId, buf);
@@ -393,7 +373,7 @@ namespace DiscImageChef.Filesystems.LisaFS
} }
// Only V3 supports subdirectories // 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) if(debug && pathElements.Length == 1)
{ {

View File

@@ -56,56 +56,54 @@ namespace DiscImageChef.Filesystems.LisaFS
// Minimal LisaOS disk is 3.5" single sided double density, 800 sectors // Minimal LisaOS disk is 3.5" single sided double density, 800 sectors
if(imagePlugin.GetSectors() < 800) return false; 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 // LisaOS searches sectors until tag tells MDDF resides there, so we'll search 100 sectors
for(int i = 0; i < 100; i++) for(int i = 0; i < 100; i++)
{ {
LisaTag.PriamTag searchTag; DecodeTag(imagePlugin.ReadSectorTag((ulong)i, SectorTagType.AppleSectorTag), out LisaTag.PriamTag searchTag);
DecodeTag(imagePlugin.ReadSectorTag((ulong)i, SectorTagType.AppleSectorTag), out searchTag);
DicConsole.DebugWriteLine("LisaFS plugin", "Sector {0}, file ID 0x{1:X4}", i, searchTag.FileId); 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; if(searchTag.FileId != FILEID_MDDF) continue;
byte[] sector = imagePlugin.ReadSector((ulong)i); byte[] sector = imagePlugin.ReadSector((ulong)i);
MDDF info_mddf = new MDDF(); MDDF infoMddf = new MDDF
{
info_mddf.mddf_block = BigEndianBitConverter.ToUInt32(sector, 0x6C); mddf_block = BigEndianBitConverter.ToUInt32(sector, 0x6C),
info_mddf.volsize_minus_one = BigEndianBitConverter.ToUInt32(sector, 0x70); volsize_minus_one = BigEndianBitConverter.ToUInt32(sector, 0x70),
info_mddf.volsize_minus_mddf_minus_one = BigEndianBitConverter.ToUInt32(sector, 0x74); volsize_minus_mddf_minus_one = BigEndianBitConverter.ToUInt32(sector, 0x74),
info_mddf.vol_size = BigEndianBitConverter.ToUInt32(sector, 0x78); vol_size = BigEndianBitConverter.ToUInt32(sector, 0x78),
info_mddf.blocksize = BigEndianBitConverter.ToUInt16(sector, 0x7C); blocksize = BigEndianBitConverter.ToUInt16(sector, 0x7C),
info_mddf.datasize = BigEndianBitConverter.ToUInt16(sector, 0x7E); datasize = BigEndianBitConverter.ToUInt16(sector, 0x7E)
};
DicConsole.DebugWriteLine("LisaFS plugin", "Current sector = {0}", i); 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", "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 = {0} sectors", infoMddf.vol_size);
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.vol_size - 1 = {0}", info_mddf.volsize_minus_one); 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}", 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", "Disk sector = {0} bytes", imagePlugin.GetSectorSize());
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.blocksize = {0} bytes", info_mddf.blocksize); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.blocksize = {0} bytes", infoMddf.blocksize);
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.datasize = {0} bytes", info_mddf.datasize); 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 infoMddf.datasize == imagePlugin.GetSectorSize();
return true;
} }
return false; return false;
@@ -134,243 +132,241 @@ namespace DiscImageChef.Filesystems.LisaFS
// Minimal LisaOS disk is 3.5" single sided double density, 800 sectors // Minimal LisaOS disk is 3.5" single sided double density, 800 sectors
if(imagePlugin.GetSectors() < 800) return; 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 // LisaOS searches sectors until tag tells MDDF resides there, so we'll search 100 sectors
for(int i = 0; i < 100; i++) for(int i = 0; i < 100; i++)
{ {
LisaTag.PriamTag searchTag; DecodeTag(imagePlugin.ReadSectorTag((ulong)i, SectorTagType.AppleSectorTag), out LisaTag.PriamTag searchTag);
DecodeTag(imagePlugin.ReadSectorTag((ulong)i, SectorTagType.AppleSectorTag), out searchTag);
DicConsole.DebugWriteLine("LisaFS plugin", "Sector {0}, file ID 0x{1:X4}", i, searchTag.FileId); 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; if(searchTag.FileId != FILEID_MDDF) continue;
byte[] sector = imagePlugin.ReadSector((ulong)i); byte[] sector = imagePlugin.ReadSector((ulong)i);
MDDF info_mddf = new MDDF(); MDDF infoMddf = new MDDF();
byte[] pString = new byte[33]; byte[] pString = new byte[33];
uint lisa_time; uint lisaTime;
info_mddf.fsversion = BigEndianBitConverter.ToUInt16(sector, 0x00); infoMddf.fsversion = BigEndianBitConverter.ToUInt16(sector, 0x00);
info_mddf.volid = BigEndianBitConverter.ToUInt64(sector, 0x02); infoMddf.volid = BigEndianBitConverter.ToUInt64(sector, 0x02);
info_mddf.volnum = BigEndianBitConverter.ToUInt16(sector, 0x0A); infoMddf.volnum = BigEndianBitConverter.ToUInt16(sector, 0x0A);
Array.Copy(sector, 0x0C, pString, 0, 33); Array.Copy(sector, 0x0C, pString, 0, 33);
info_mddf.volname = StringHandlers.PascalToString(pString, CurrentEncoding); infoMddf.volname = StringHandlers.PascalToString(pString, CurrentEncoding);
info_mddf.unknown1 = sector[0x2D]; infoMddf.unknown1 = sector[0x2D];
Array.Copy(sector, 0x2E, pString, 0, 33); Array.Copy(sector, 0x2E, pString, 0, 33);
// Prevent garbage // Prevent garbage
if(pString[0] <= 32) info_mddf.password = StringHandlers.PascalToString(pString, CurrentEncoding); infoMddf.password = pString[0] <= 32 ? StringHandlers.PascalToString(pString, CurrentEncoding) : "";
else info_mddf.password = ""; infoMddf.unknown2 = sector[0x4F];
info_mddf.unknown2 = sector[0x4F]; infoMddf.machine_id = BigEndianBitConverter.ToUInt32(sector, 0x50);
info_mddf.machine_id = BigEndianBitConverter.ToUInt32(sector, 0x50); infoMddf.master_copy_id = BigEndianBitConverter.ToUInt32(sector, 0x54);
info_mddf.master_copy_id = BigEndianBitConverter.ToUInt32(sector, 0x54); lisaTime = BigEndianBitConverter.ToUInt32(sector, 0x58);
lisa_time = BigEndianBitConverter.ToUInt32(sector, 0x58); infoMddf.dtvc = DateHandlers.LisaToDateTime(lisaTime);
info_mddf.dtvc = DateHandlers.LisaToDateTime(lisa_time); lisaTime = BigEndianBitConverter.ToUInt32(sector, 0x5C);
lisa_time = BigEndianBitConverter.ToUInt32(sector, 0x5C); infoMddf.dtcc = DateHandlers.LisaToDateTime(lisaTime);
info_mddf.dtcc = DateHandlers.LisaToDateTime(lisa_time); lisaTime = BigEndianBitConverter.ToUInt32(sector, 0x60);
lisa_time = BigEndianBitConverter.ToUInt32(sector, 0x60); infoMddf.dtvb = DateHandlers.LisaToDateTime(lisaTime);
info_mddf.dtvb = DateHandlers.LisaToDateTime(lisa_time); lisaTime = BigEndianBitConverter.ToUInt32(sector, 0x64);
lisa_time = BigEndianBitConverter.ToUInt32(sector, 0x64); infoMddf.dtvs = DateHandlers.LisaToDateTime(lisaTime);
info_mddf.dtvs = DateHandlers.LisaToDateTime(lisa_time); infoMddf.unknown3 = BigEndianBitConverter.ToUInt32(sector, 0x68);
info_mddf.unknown3 = BigEndianBitConverter.ToUInt32(sector, 0x68); infoMddf.mddf_block = BigEndianBitConverter.ToUInt32(sector, 0x6C);
info_mddf.mddf_block = BigEndianBitConverter.ToUInt32(sector, 0x6C); infoMddf.volsize_minus_one = BigEndianBitConverter.ToUInt32(sector, 0x70);
info_mddf.volsize_minus_one = BigEndianBitConverter.ToUInt32(sector, 0x70); infoMddf.volsize_minus_mddf_minus_one = BigEndianBitConverter.ToUInt32(sector, 0x74);
info_mddf.volsize_minus_mddf_minus_one = BigEndianBitConverter.ToUInt32(sector, 0x74); infoMddf.vol_size = BigEndianBitConverter.ToUInt32(sector, 0x78);
info_mddf.vol_size = BigEndianBitConverter.ToUInt32(sector, 0x78); infoMddf.blocksize = BigEndianBitConverter.ToUInt16(sector, 0x7C);
info_mddf.blocksize = BigEndianBitConverter.ToUInt16(sector, 0x7C); infoMddf.datasize = BigEndianBitConverter.ToUInt16(sector, 0x7E);
info_mddf.datasize = BigEndianBitConverter.ToUInt16(sector, 0x7E); infoMddf.unknown4 = BigEndianBitConverter.ToUInt16(sector, 0x80);
info_mddf.unknown4 = BigEndianBitConverter.ToUInt16(sector, 0x80); infoMddf.unknown5 = BigEndianBitConverter.ToUInt32(sector, 0x82);
info_mddf.unknown5 = BigEndianBitConverter.ToUInt32(sector, 0x82); infoMddf.unknown6 = BigEndianBitConverter.ToUInt32(sector, 0x86);
info_mddf.unknown6 = BigEndianBitConverter.ToUInt32(sector, 0x86); infoMddf.clustersize = BigEndianBitConverter.ToUInt16(sector, 0x8A);
info_mddf.clustersize = BigEndianBitConverter.ToUInt16(sector, 0x8A); infoMddf.fs_size = BigEndianBitConverter.ToUInt32(sector, 0x8C);
info_mddf.fs_size = BigEndianBitConverter.ToUInt32(sector, 0x8C); infoMddf.unknown7 = BigEndianBitConverter.ToUInt32(sector, 0x90);
info_mddf.unknown7 = BigEndianBitConverter.ToUInt32(sector, 0x90); infoMddf.srec_ptr = BigEndianBitConverter.ToUInt32(sector, 0x94);
info_mddf.srec_ptr = BigEndianBitConverter.ToUInt32(sector, 0x94); infoMddf.unknown9 = BigEndianBitConverter.ToUInt16(sector, 0x98);
info_mddf.unknown9 = BigEndianBitConverter.ToUInt16(sector, 0x98); infoMddf.srec_len = BigEndianBitConverter.ToUInt16(sector, 0x9A);
info_mddf.srec_len = BigEndianBitConverter.ToUInt16(sector, 0x9A); infoMddf.unknown10 = BigEndianBitConverter.ToUInt32(sector, 0x9C);
info_mddf.unknown10 = BigEndianBitConverter.ToUInt32(sector, 0x9C); infoMddf.unknown11 = BigEndianBitConverter.ToUInt32(sector, 0xA0);
info_mddf.unknown11 = BigEndianBitConverter.ToUInt32(sector, 0xA0); infoMddf.unknown12 = BigEndianBitConverter.ToUInt32(sector, 0xA4);
info_mddf.unknown12 = BigEndianBitConverter.ToUInt32(sector, 0xA4); infoMddf.unknown13 = BigEndianBitConverter.ToUInt32(sector, 0xA8);
info_mddf.unknown13 = BigEndianBitConverter.ToUInt32(sector, 0xA8); infoMddf.unknown14 = BigEndianBitConverter.ToUInt32(sector, 0xAC);
info_mddf.unknown14 = BigEndianBitConverter.ToUInt32(sector, 0xAC); infoMddf.filecount = BigEndianBitConverter.ToUInt16(sector, 0xB0);
info_mddf.filecount = BigEndianBitConverter.ToUInt16(sector, 0xB0); infoMddf.unknown15 = BigEndianBitConverter.ToUInt32(sector, 0xB2);
info_mddf.unknown15 = BigEndianBitConverter.ToUInt32(sector, 0xB2); infoMddf.unknown16 = BigEndianBitConverter.ToUInt32(sector, 0xB6);
info_mddf.unknown16 = BigEndianBitConverter.ToUInt32(sector, 0xB6); infoMddf.freecount = BigEndianBitConverter.ToUInt32(sector, 0xBA);
info_mddf.freecount = BigEndianBitConverter.ToUInt32(sector, 0xBA); infoMddf.unknown17 = BigEndianBitConverter.ToUInt16(sector, 0xBE);
info_mddf.unknown17 = BigEndianBitConverter.ToUInt16(sector, 0xBE); infoMddf.unknown18 = BigEndianBitConverter.ToUInt32(sector, 0xC0);
info_mddf.unknown18 = BigEndianBitConverter.ToUInt32(sector, 0xC0); infoMddf.overmount_stamp = BigEndianBitConverter.ToUInt64(sector, 0xC4);
info_mddf.overmount_stamp = BigEndianBitConverter.ToUInt64(sector, 0xC4); infoMddf.serialization = BigEndianBitConverter.ToUInt32(sector, 0xCC);
info_mddf.serialization = BigEndianBitConverter.ToUInt32(sector, 0xCC); infoMddf.unknown19 = BigEndianBitConverter.ToUInt32(sector, 0xD0);
info_mddf.unknown19 = BigEndianBitConverter.ToUInt32(sector, 0xD0); infoMddf.unknown_timestamp = BigEndianBitConverter.ToUInt32(sector, 0xD4);
info_mddf.unknown_timestamp = BigEndianBitConverter.ToUInt32(sector, 0xD4); infoMddf.unknown20 = BigEndianBitConverter.ToUInt32(sector, 0xD8);
info_mddf.unknown20 = BigEndianBitConverter.ToUInt32(sector, 0xD8); infoMddf.unknown21 = BigEndianBitConverter.ToUInt32(sector, 0xDC);
info_mddf.unknown21 = BigEndianBitConverter.ToUInt32(sector, 0xDC); infoMddf.unknown22 = BigEndianBitConverter.ToUInt32(sector, 0xE0);
info_mddf.unknown22 = BigEndianBitConverter.ToUInt32(sector, 0xE0); infoMddf.unknown23 = BigEndianBitConverter.ToUInt32(sector, 0xE4);
info_mddf.unknown23 = BigEndianBitConverter.ToUInt32(sector, 0xE4); infoMddf.unknown24 = BigEndianBitConverter.ToUInt32(sector, 0xE8);
info_mddf.unknown24 = BigEndianBitConverter.ToUInt32(sector, 0xE8); infoMddf.unknown25 = BigEndianBitConverter.ToUInt32(sector, 0xEC);
info_mddf.unknown25 = BigEndianBitConverter.ToUInt32(sector, 0xEC); infoMddf.unknown26 = BigEndianBitConverter.ToUInt32(sector, 0xF0);
info_mddf.unknown26 = BigEndianBitConverter.ToUInt32(sector, 0xF0); infoMddf.unknown27 = BigEndianBitConverter.ToUInt32(sector, 0xF4);
info_mddf.unknown27 = BigEndianBitConverter.ToUInt32(sector, 0xF4); infoMddf.unknown28 = BigEndianBitConverter.ToUInt32(sector, 0xF8);
info_mddf.unknown28 = BigEndianBitConverter.ToUInt32(sector, 0xF8); infoMddf.unknown29 = BigEndianBitConverter.ToUInt32(sector, 0xFC);
info_mddf.unknown29 = BigEndianBitConverter.ToUInt32(sector, 0xFC); infoMddf.unknown30 = BigEndianBitConverter.ToUInt32(sector, 0x100);
info_mddf.unknown30 = BigEndianBitConverter.ToUInt32(sector, 0x100); infoMddf.unknown31 = BigEndianBitConverter.ToUInt32(sector, 0x104);
info_mddf.unknown31 = BigEndianBitConverter.ToUInt32(sector, 0x104); infoMddf.unknown32 = BigEndianBitConverter.ToUInt32(sector, 0x108);
info_mddf.unknown32 = BigEndianBitConverter.ToUInt32(sector, 0x108); infoMddf.unknown33 = BigEndianBitConverter.ToUInt32(sector, 0x10C);
info_mddf.unknown33 = BigEndianBitConverter.ToUInt32(sector, 0x10C); infoMddf.unknown34 = BigEndianBitConverter.ToUInt32(sector, 0x110);
info_mddf.unknown34 = BigEndianBitConverter.ToUInt32(sector, 0x110); infoMddf.unknown35 = BigEndianBitConverter.ToUInt32(sector, 0x114);
info_mddf.unknown35 = BigEndianBitConverter.ToUInt32(sector, 0x114); infoMddf.backup_volid = BigEndianBitConverter.ToUInt64(sector, 0x118);
info_mddf.backup_volid = BigEndianBitConverter.ToUInt64(sector, 0x118); infoMddf.label_size = BigEndianBitConverter.ToUInt16(sector, 0x120);
info_mddf.label_size = BigEndianBitConverter.ToUInt16(sector, 0x120); infoMddf.fs_overhead = BigEndianBitConverter.ToUInt16(sector, 0x122);
info_mddf.fs_overhead = BigEndianBitConverter.ToUInt16(sector, 0x122); infoMddf.result_scavenge = BigEndianBitConverter.ToUInt16(sector, 0x124);
info_mddf.result_scavenge = BigEndianBitConverter.ToUInt16(sector, 0x124); infoMddf.boot_code = BigEndianBitConverter.ToUInt16(sector, 0x126);
info_mddf.boot_code = BigEndianBitConverter.ToUInt16(sector, 0x126); infoMddf.boot_environ = BigEndianBitConverter.ToUInt16(sector, 0x6C);
info_mddf.boot_environ = BigEndianBitConverter.ToUInt16(sector, 0x6C); infoMddf.unknown36 = BigEndianBitConverter.ToUInt32(sector, 0x12A);
info_mddf.unknown36 = BigEndianBitConverter.ToUInt32(sector, 0x12A); infoMddf.unknown37 = BigEndianBitConverter.ToUInt32(sector, 0x12E);
info_mddf.unknown37 = BigEndianBitConverter.ToUInt32(sector, 0x12E); infoMddf.unknown38 = BigEndianBitConverter.ToUInt32(sector, 0x132);
info_mddf.unknown38 = BigEndianBitConverter.ToUInt32(sector, 0x132); infoMddf.vol_sequence = BigEndianBitConverter.ToUInt16(sector, 0x136);
info_mddf.vol_sequence = BigEndianBitConverter.ToUInt16(sector, 0x136); infoMddf.vol_left_mounted = sector[0x138];
info_mddf.vol_left_mounted = sector[0x138];
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown1 = 0x{0:X2} ({0})", info_mddf.unknown1); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown1 = 0x{0:X2} ({0})", infoMddf.unknown1);
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown2 = 0x{0:X2} ({0})", info_mddf.unknown2); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown2 = 0x{0:X2} ({0})", infoMddf.unknown2);
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown3 = 0x{0:X8} ({0})", info_mddf.unknown3); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown3 = 0x{0:X8} ({0})", infoMddf.unknown3);
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown4 = 0x{0:X4} ({0})", info_mddf.unknown4); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown4 = 0x{0:X4} ({0})", infoMddf.unknown4);
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown5 = 0x{0:X8} ({0})", info_mddf.unknown5); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown5 = 0x{0:X8} ({0})", infoMddf.unknown5);
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown6 = 0x{0:X8} ({0})", info_mddf.unknown6); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown6 = 0x{0:X8} ({0})", infoMddf.unknown6);
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown7 = 0x{0:X8} ({0})", info_mddf.unknown7); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown7 = 0x{0:X8} ({0})", infoMddf.unknown7);
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown9 = 0x{0:X4} ({0})", info_mddf.unknown9); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown9 = 0x{0:X4} ({0})", infoMddf.unknown9);
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown10 = 0x{0:X8} ({0})", info_mddf.unknown10); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown10 = 0x{0:X8} ({0})", infoMddf.unknown10);
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown11 = 0x{0:X8} ({0})", info_mddf.unknown11); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown11 = 0x{0:X8} ({0})", infoMddf.unknown11);
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown12 = 0x{0:X8} ({0})", info_mddf.unknown12); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown12 = 0x{0:X8} ({0})", infoMddf.unknown12);
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown13 = 0x{0:X8} ({0})", info_mddf.unknown13); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown13 = 0x{0:X8} ({0})", infoMddf.unknown13);
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown14 = 0x{0:X8} ({0})", info_mddf.unknown14); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown14 = 0x{0:X8} ({0})", infoMddf.unknown14);
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown15 = 0x{0:X8} ({0})", info_mddf.unknown15); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown15 = 0x{0:X8} ({0})", infoMddf.unknown15);
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown16 = 0x{0:X8} ({0})", info_mddf.unknown16); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown16 = 0x{0:X8} ({0})", infoMddf.unknown16);
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown17 = 0x{0:X4} ({0})", info_mddf.unknown17); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown17 = 0x{0:X4} ({0})", infoMddf.unknown17);
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown18 = 0x{0:X8} ({0})", info_mddf.unknown18); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown18 = 0x{0:X8} ({0})", infoMddf.unknown18);
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown19 = 0x{0:X8} ({0})", info_mddf.unknown19); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown19 = 0x{0:X8} ({0})", infoMddf.unknown19);
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown20 = 0x{0:X8} ({0})", info_mddf.unknown20); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown20 = 0x{0:X8} ({0})", infoMddf.unknown20);
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown21 = 0x{0:X8} ({0})", info_mddf.unknown21); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown21 = 0x{0:X8} ({0})", infoMddf.unknown21);
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown22 = 0x{0:X8} ({0})", info_mddf.unknown22); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown22 = 0x{0:X8} ({0})", infoMddf.unknown22);
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown23 = 0x{0:X8} ({0})", info_mddf.unknown23); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown23 = 0x{0:X8} ({0})", infoMddf.unknown23);
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown24 = 0x{0:X8} ({0})", info_mddf.unknown24); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown24 = 0x{0:X8} ({0})", infoMddf.unknown24);
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown25 = 0x{0:X8} ({0})", info_mddf.unknown25); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown25 = 0x{0:X8} ({0})", infoMddf.unknown25);
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown26 = 0x{0:X8} ({0})", info_mddf.unknown26); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown26 = 0x{0:X8} ({0})", infoMddf.unknown26);
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown27 = 0x{0:X8} ({0})", info_mddf.unknown27); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown27 = 0x{0:X8} ({0})", infoMddf.unknown27);
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown28 = 0x{0:X8} ({0})", info_mddf.unknown28); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown28 = 0x{0:X8} ({0})", infoMddf.unknown28);
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown29 = 0x{0:X8} ({0})", info_mddf.unknown29); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown29 = 0x{0:X8} ({0})", infoMddf.unknown29);
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown30 = 0x{0:X8} ({0})", info_mddf.unknown30); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown30 = 0x{0:X8} ({0})", infoMddf.unknown30);
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown31 = 0x{0:X8} ({0})", info_mddf.unknown31); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown31 = 0x{0:X8} ({0})", infoMddf.unknown31);
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown32 = 0x{0:X8} ({0})", info_mddf.unknown32); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown32 = 0x{0:X8} ({0})", infoMddf.unknown32);
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown33 = 0x{0:X8} ({0})", info_mddf.unknown33); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown33 = 0x{0:X8} ({0})", infoMddf.unknown33);
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown34 = 0x{0:X8} ({0})", info_mddf.unknown34); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown34 = 0x{0:X8} ({0})", infoMddf.unknown34);
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown35 = 0x{0:X8} ({0})", info_mddf.unknown35); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown35 = 0x{0:X8} ({0})", infoMddf.unknown35);
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown36 = 0x{0:X8} ({0})", info_mddf.unknown36); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown36 = 0x{0:X8} ({0})", infoMddf.unknown36);
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown37 = 0x{0:X8} ({0})", info_mddf.unknown37); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown37 = 0x{0:X8} ({0})", infoMddf.unknown37);
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown38 = 0x{0:X8} ({0})", info_mddf.unknown38); DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown38 = 0x{0:X8} ({0})", infoMddf.unknown38);
DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown_timestamp = 0x{0:X8} ({0}, {1})", DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown_timestamp = 0x{0:X8} ({0}, {1})",
info_mddf.unknown_timestamp, infoMddf.unknown_timestamp,
DateHandlers.LisaToDateTime(info_mddf.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"); sb.AppendLine("LisaFS v1");
break; break;
case LisaFSv2: case LISA_V2:
sb.AppendLine("LisaFS v2"); sb.AppendLine("LisaFS v2");
break; break;
case LisaFSv3: case LISA_V3:
sb.AppendLine("LisaFS v3"); sb.AppendLine("LisaFS v3");
break; break;
default: default:
sb.AppendFormat("Uknown LisaFS version {0}", info_mddf.fsversion).AppendLine(); sb.AppendFormat("Uknown LisaFS version {0}", infoMddf.fsversion).AppendLine();
break; break;
} }
sb.AppendFormat("Volume name: \"{0}\"", info_mddf.volname).AppendLine(); sb.AppendFormat("Volume name: \"{0}\"", infoMddf.volname).AppendLine();
sb.AppendFormat("Volume password: \"{0}\"", info_mddf.password).AppendLine(); sb.AppendFormat("Volume password: \"{0}\"", infoMddf.password).AppendLine();
sb.AppendFormat("Volume ID: 0x{0:X16}", info_mddf.volid).AppendLine(); sb.AppendFormat("Volume ID: 0x{0:X16}", infoMddf.volid).AppendLine();
sb.AppendFormat("Backup volume ID: 0x{0:X16}", info_mddf.backup_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(); .AppendLine();
sb.AppendFormat("Serial number of Lisa computer that created this volume: {0}", 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}", 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("Volume created on {0}", infoMddf.dtvc).AppendLine();
sb.AppendFormat("Some timestamp, says {0}", info_mddf.dtcc).AppendLine(); sb.AppendFormat("Some timestamp, says {0}", infoMddf.dtcc).AppendLine();
sb.AppendFormat("Volume backed up on {0}", info_mddf.dtvb).AppendLine(); sb.AppendFormat("Volume backed up on {0}", infoMddf.dtvb).AppendLine();
sb.AppendFormat("Volume scavenged on {0}", info_mddf.dtvs).AppendLine(); sb.AppendFormat("Volume scavenged on {0}", infoMddf.dtvs).AppendLine();
sb.AppendFormat("MDDF is in block {0}", info_mddf.mddf_block + before_mddf).AppendLine(); sb.AppendFormat("MDDF is in block {0}", infoMddf.mddf_block + beforeMddf).AppendLine();
sb.AppendFormat("There are {0} reserved blocks before volume", before_mddf).AppendLine(); sb.AppendFormat("There are {0} reserved blocks before volume", beforeMddf).AppendLine();
sb.AppendFormat("{0} blocks minus one", info_mddf.volsize_minus_one).AppendLine(); sb.AppendFormat("{0} blocks minus one", infoMddf.volsize_minus_one).AppendLine();
sb.AppendFormat("{0} blocks minus one minus MDDF offset", info_mddf.volsize_minus_mddf_minus_one) sb.AppendFormat("{0} blocks minus one minus MDDF offset", infoMddf.volsize_minus_mddf_minus_one)
.AppendLine(); .AppendLine();
sb.AppendFormat("{0} blocks in volume", info_mddf.vol_size).AppendLine(); sb.AppendFormat("{0} blocks in volume", infoMddf.vol_size).AppendLine();
sb.AppendFormat("{0} bytes per sector (uncooked)", info_mddf.blocksize).AppendLine(); sb.AppendFormat("{0} bytes per sector (uncooked)", infoMddf.blocksize).AppendLine();
sb.AppendFormat("{0} bytes per sector", info_mddf.datasize).AppendLine(); sb.AppendFormat("{0} bytes per sector", infoMddf.datasize).AppendLine();
sb.AppendFormat("{0} blocks per cluster", info_mddf.clustersize).AppendLine(); sb.AppendFormat("{0} blocks per cluster", infoMddf.clustersize).AppendLine();
sb.AppendFormat("{0} blocks in filesystem", info_mddf.fs_size).AppendLine(); sb.AppendFormat("{0} blocks in filesystem", infoMddf.fs_size).AppendLine();
sb.AppendFormat("{0} files in volume", info_mddf.filecount).AppendLine(); sb.AppendFormat("{0} files in volume", infoMddf.filecount).AppendLine();
sb.AppendFormat("{0} blocks free", info_mddf.freecount).AppendLine(); sb.AppendFormat("{0} blocks free", infoMddf.freecount).AppendLine();
sb.AppendFormat("{0} bytes in LisaInfo", info_mddf.label_size).AppendLine(); sb.AppendFormat("{0} bytes in LisaInfo", infoMddf.label_size).AppendLine();
sb.AppendFormat("Filesystem overhead: {0}", info_mddf.fs_overhead).AppendLine(); sb.AppendFormat("Filesystem overhead: {0}", infoMddf.fs_overhead).AppendLine();
sb.AppendFormat("Scanvenger result code: 0x{0:X8}", info_mddf.result_scavenge).AppendLine(); sb.AppendFormat("Scanvenger result code: 0x{0:X8}", infoMddf.result_scavenge).AppendLine();
sb.AppendFormat("Boot code: 0x{0:X8}", info_mddf.boot_code).AppendLine(); sb.AppendFormat("Boot code: 0x{0:X8}", infoMddf.boot_code).AppendLine();
sb.AppendFormat("Boot environment: 0x{0:X8}", info_mddf.boot_environ).AppendLine(); sb.AppendFormat("Boot environment: 0x{0:X8}", infoMddf.boot_environ).AppendLine();
sb.AppendFormat("Overmount stamp: 0x{0:X16}", info_mddf.overmount_stamp).AppendLine(); sb.AppendFormat("Overmount stamp: 0x{0:X16}", infoMddf.overmount_stamp).AppendLine();
sb.AppendFormat("S-Records start at {0} and spans for {1} blocks", 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(); .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"); else sb.AppendLine("Volume is dirty");
information = sb.ToString(); information = sb.ToString();
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType();
if(DateTime.Compare(info_mddf.dtvb, DateHandlers.LisaToDateTime(0)) > 0) if(DateTime.Compare(infoMddf.dtvb, DateHandlers.LisaToDateTime(0)) > 0)
{ {
xmlFSType.BackupDate = info_mddf.dtvb; XmlFsType.BackupDate = infoMddf.dtvb;
xmlFSType.BackupDateSpecified = true; XmlFsType.BackupDateSpecified = true;
} }
xmlFSType.Clusters = info_mddf.vol_size; XmlFsType.Clusters = infoMddf.vol_size;
xmlFSType.ClusterSize = info_mddf.clustersize * info_mddf.datasize; XmlFsType.ClusterSize = infoMddf.clustersize * infoMddf.datasize;
if(DateTime.Compare(info_mddf.dtvc, DateHandlers.LisaToDateTime(0)) > 0) if(DateTime.Compare(infoMddf.dtvc, DateHandlers.LisaToDateTime(0)) > 0)
{ {
xmlFSType.CreationDate = info_mddf.dtvc; XmlFsType.CreationDate = infoMddf.dtvc;
xmlFSType.CreationDateSpecified = true; XmlFsType.CreationDateSpecified = true;
} }
xmlFSType.Dirty = info_mddf.vol_left_mounted != 0; XmlFsType.Dirty = infoMddf.vol_left_mounted != 0;
xmlFSType.Files = info_mddf.filecount; XmlFsType.Files = infoMddf.filecount;
xmlFSType.FilesSpecified = true; XmlFsType.FilesSpecified = true;
xmlFSType.FreeClusters = info_mddf.freecount; XmlFsType.FreeClusters = infoMddf.freecount;
xmlFSType.FreeClustersSpecified = true; XmlFsType.FreeClustersSpecified = true;
xmlFSType.Type = "LisaFS"; XmlFsType.Type = "LisaFS";
xmlFSType.VolumeName = info_mddf.volname; XmlFsType.VolumeName = infoMddf.volname;
xmlFSType.VolumeSerial = $"{info_mddf.volid:X16}"; XmlFsType.VolumeSerial = $"{infoMddf.volid:X16}";
return; return;
} }

View File

@@ -66,20 +66,20 @@ namespace DiscImageChef.Filesystems.LisaFS
/// <summary>Lists Extents Files already printed in debug mode to not repeat them</summary> /// <summary>Lists Extents Files already printed in debug mode to not repeat them</summary>
List<short> printedExtents; List<short> printedExtents;
/// <summary>Caches the creation times for subdirectories as to not have to traverse the Catalog File on each stat</summary> /// <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 #endregion Caches
public LisaFS() public LisaFS()
{ {
Name = "Apple Lisa File System"; Name = "Apple Lisa File System";
PluginUUID = new Guid("7E6034D1-D823-4248-A54D-239742B28391"); PluginUuid = new Guid("7E6034D1-D823-4248-A54D-239742B28391");
CurrentEncoding = new LisaRoman(); CurrentEncoding = new LisaRoman();
} }
public LisaFS(Encoding encoding) public LisaFS(Encoding encoding)
{ {
Name = "Apple Lisa File System"; Name = "Apple Lisa File System";
PluginUUID = new Guid("7E6034D1-D823-4248-A54D-239742B28391"); PluginUuid = new Guid("7E6034D1-D823-4248-A54D-239742B28391");
CurrentEncoding = new LisaRoman(); CurrentEncoding = new LisaRoman();
} }
@@ -87,7 +87,7 @@ namespace DiscImageChef.Filesystems.LisaFS
{ {
device = imagePlugin; device = imagePlugin;
Name = "Apple Lisa File System"; Name = "Apple Lisa File System";
PluginUUID = new Guid("7E6034D1-D823-4248-A54D-239742B28391"); PluginUuid = new Guid("7E6034D1-D823-4248-A54D-239742B28391");
CurrentEncoding = new LisaRoman(); CurrentEncoding = new LisaRoman();
} }
} }

View File

@@ -82,8 +82,7 @@ namespace DiscImageChef.Filesystems.LisaFS
// LisaOS searches sectors until tag tells MDDF resides there, so we'll search 100 sectors // LisaOS searches sectors until tag tells MDDF resides there, so we'll search 100 sectors
for(ulong i = 0; i < 100; i++) for(ulong i = 0; i < 100; i++)
{ {
LisaTag.PriamTag searchTag; DecodeTag(device.ReadSectorTag(i, SectorTagType.AppleSectorTag), out LisaTag.PriamTag searchTag);
DecodeTag(device.ReadSectorTag(i, SectorTagType.AppleSectorTag), out searchTag);
DicConsole.DebugWriteLine("LisaFS plugin", "Sector {0}, file ID 0x{1:X4}", i, searchTag.FileId); 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); byte[] sector = device.ReadSector(i);
mddf = new MDDF(); mddf = new MDDF();
byte[] pString = new byte[33]; byte[] pString = new byte[33];
uint lisa_time; uint lisaTime;
mddf.fsversion = BigEndianBitConverter.ToUInt16(sector, 0x00); mddf.fsversion = BigEndianBitConverter.ToUInt16(sector, 0x00);
mddf.volid = BigEndianBitConverter.ToUInt64(sector, 0x02); mddf.volid = BigEndianBitConverter.ToUInt64(sector, 0x02);
@@ -107,19 +106,18 @@ namespace DiscImageChef.Filesystems.LisaFS
mddf.unknown1 = sector[0x2D]; mddf.unknown1 = sector[0x2D];
Array.Copy(sector, 0x2E, pString, 0, 33); Array.Copy(sector, 0x2E, pString, 0, 33);
// Prevent garbage // Prevent garbage
if(pString[0] <= 32) mddf.password = StringHandlers.PascalToString(pString, CurrentEncoding); mddf.password = pString[0] <= 32 ? StringHandlers.PascalToString(pString, CurrentEncoding) : "";
else mddf.password = "";
mddf.unknown2 = sector[0x4F]; mddf.unknown2 = sector[0x4F];
mddf.machine_id = BigEndianBitConverter.ToUInt32(sector, 0x50); mddf.machine_id = BigEndianBitConverter.ToUInt32(sector, 0x50);
mddf.master_copy_id = BigEndianBitConverter.ToUInt32(sector, 0x54); mddf.master_copy_id = BigEndianBitConverter.ToUInt32(sector, 0x54);
lisa_time = BigEndianBitConverter.ToUInt32(sector, 0x58); lisaTime = BigEndianBitConverter.ToUInt32(sector, 0x58);
mddf.dtvc = DateHandlers.LisaToDateTime(lisa_time); mddf.dtvc = DateHandlers.LisaToDateTime(lisaTime);
lisa_time = BigEndianBitConverter.ToUInt32(sector, 0x5C); lisaTime = BigEndianBitConverter.ToUInt32(sector, 0x5C);
mddf.dtcc = DateHandlers.LisaToDateTime(lisa_time); mddf.dtcc = DateHandlers.LisaToDateTime(lisaTime);
lisa_time = BigEndianBitConverter.ToUInt32(sector, 0x60); lisaTime = BigEndianBitConverter.ToUInt32(sector, 0x60);
mddf.dtvb = DateHandlers.LisaToDateTime(lisa_time); mddf.dtvb = DateHandlers.LisaToDateTime(lisaTime);
lisa_time = BigEndianBitConverter.ToUInt32(sector, 0x64); lisaTime = BigEndianBitConverter.ToUInt32(sector, 0x64);
mddf.dtvs = DateHandlers.LisaToDateTime(lisa_time); mddf.dtvs = DateHandlers.LisaToDateTime(lisaTime);
mddf.unknown3 = BigEndianBitConverter.ToUInt32(sector, 0x68); mddf.unknown3 = BigEndianBitConverter.ToUInt32(sector, 0x68);
mddf.mddf_block = BigEndianBitConverter.ToUInt32(sector, 0x6C); mddf.mddf_block = BigEndianBitConverter.ToUInt32(sector, 0x6C);
mddf.volsize_minus_one = BigEndianBitConverter.ToUInt32(sector, 0x70); mddf.volsize_minus_one = BigEndianBitConverter.ToUInt32(sector, 0x70);
@@ -193,13 +191,13 @@ namespace DiscImageChef.Filesystems.LisaFS
// Check MDDF version // Check MDDF version
switch(mddf.fsversion) switch(mddf.fsversion)
{ {
case LisaFSv1: case LISA_V1:
DicConsole.DebugWriteLine("LisaFS plugin", "Mounting LisaFS v1"); DicConsole.DebugWriteLine("LisaFS plugin", "Mounting LisaFS v1");
break; break;
case LisaFSv2: case LISA_V2:
DicConsole.DebugWriteLine("LisaFS plugin", "Mounting LisaFS v2"); DicConsole.DebugWriteLine("LisaFS plugin", "Mounting LisaFS v2");
break; break;
case LisaFSv3: case LISA_V3:
DicConsole.DebugWriteLine("LisaFS plugin", "Mounting LisaFS v3"); DicConsole.DebugWriteLine("LisaFS plugin", "Mounting LisaFS v3");
break; break;
default: default:
@@ -214,23 +212,20 @@ namespace DiscImageChef.Filesystems.LisaFS
//catalogCache = new Dictionary<short, List<CatalogEntry>>(); //catalogCache = new Dictionary<short, List<CatalogEntry>>();
fileSizeCache = new Dictionary<short, int>(); fileSizeCache = new Dictionary<short, int>();
Errno error;
mounted = true; mounted = true;
this.debug = debug; this.debug = debug;
if(debug) printedExtents = new List<short>(); if(debug) printedExtents = new List<short>();
// Read the S-Records file // Read the S-Records file
error = ReadSRecords(); Errno error = ReadSRecords();
if(error != Errno.NoError) if(error != Errno.NoError)
{ {
DicConsole.ErrorWriteLine("Error {0} reading S-Records file.", error); DicConsole.ErrorWriteLine("Error {0} reading S-Records file.", error);
return error; return error;
} }
directoryDTCCache = new Dictionary<short, DateTime>(); directoryDtcCache = new Dictionary<short, DateTime> {{DIRID_ROOT, mddf.dtcc}};
directoryDTCCache.Add(DIRID_ROOT, mddf.dtcc);
// Read the Catalog File // Read the Catalog File
error = ReadCatalog(); error = ReadCatalog();
@@ -246,9 +241,7 @@ namespace DiscImageChef.Filesystems.LisaFS
// If debug, cache system files // If debug, cache system files
if(debug) if(debug)
{ {
byte[] temp; error = ReadSystemFile(FILEID_BOOT_SIGNED, out _);
error = ReadSystemFile(FILEID_BOOT_SIGNED, out temp);
if(error != Errno.NoError) if(error != Errno.NoError)
{ {
DicConsole.DebugWriteLine("LisaFS plugin", "Unable to read boot blocks"); DicConsole.DebugWriteLine("LisaFS plugin", "Unable to read boot blocks");
@@ -256,7 +249,7 @@ namespace DiscImageChef.Filesystems.LisaFS
return error; return error;
} }
error = ReadSystemFile(FILEID_LOADER_SIGNED, out temp); error = ReadSystemFile(FILEID_LOADER_SIGNED, out _);
if(error != Errno.NoError) if(error != Errno.NoError)
{ {
DicConsole.DebugWriteLine("LisaFS plugin", "Unable to read boot loader"); DicConsole.DebugWriteLine("LisaFS plugin", "Unable to read boot loader");
@@ -264,7 +257,7 @@ namespace DiscImageChef.Filesystems.LisaFS
return error; return error;
} }
error = ReadSystemFile((short)FILEID_MDDF, out temp); error = ReadSystemFile((short)FILEID_MDDF, out _);
if(error != Errno.NoError) if(error != Errno.NoError)
{ {
DicConsole.DebugWriteLine("LisaFS plugin", "Unable to read MDDF"); DicConsole.DebugWriteLine("LisaFS plugin", "Unable to read MDDF");
@@ -272,7 +265,7 @@ namespace DiscImageChef.Filesystems.LisaFS
return error; return error;
} }
error = ReadSystemFile((short)FILEID_BITMAP, out temp); error = ReadSystemFile((short)FILEID_BITMAP, out _);
if(error != Errno.NoError) if(error != Errno.NoError)
{ {
DicConsole.DebugWriteLine("LisaFS plugin", "Unable to read volume bitmap"); DicConsole.DebugWriteLine("LisaFS plugin", "Unable to read volume bitmap");
@@ -280,7 +273,7 @@ namespace DiscImageChef.Filesystems.LisaFS
return error; return error;
} }
error = ReadSystemFile((short)FILEID_SRECORD, out temp); error = ReadSystemFile((short)FILEID_SRECORD, out _);
if(error != Errno.NoError) if(error != Errno.NoError)
{ {
DicConsole.DebugWriteLine("LisaFS plugin", "Unable to read S-Records file"); DicConsole.DebugWriteLine("LisaFS plugin", "Unable to read S-Records file");
@@ -290,27 +283,27 @@ namespace DiscImageChef.Filesystems.LisaFS
} }
// Create XML metadata for mounted filesystem // Create XML metadata for mounted filesystem
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType();
if(DateTime.Compare(mddf.dtvb, DateHandlers.LisaToDateTime(0)) > 0) if(DateTime.Compare(mddf.dtvb, DateHandlers.LisaToDateTime(0)) > 0)
{ {
xmlFSType.BackupDate = mddf.dtvb; XmlFsType.BackupDate = mddf.dtvb;
xmlFSType.BackupDateSpecified = true; XmlFsType.BackupDateSpecified = true;
} }
xmlFSType.Clusters = mddf.vol_size; XmlFsType.Clusters = mddf.vol_size;
xmlFSType.ClusterSize = mddf.clustersize * mddf.datasize; XmlFsType.ClusterSize = mddf.clustersize * mddf.datasize;
if(DateTime.Compare(mddf.dtvc, DateHandlers.LisaToDateTime(0)) > 0) if(DateTime.Compare(mddf.dtvc, DateHandlers.LisaToDateTime(0)) > 0)
{ {
xmlFSType.CreationDate = mddf.dtvc; XmlFsType.CreationDate = mddf.dtvc;
xmlFSType.CreationDateSpecified = true; XmlFsType.CreationDateSpecified = true;
} }
xmlFSType.Dirty = mddf.vol_left_mounted != 0; XmlFsType.Dirty = mddf.vol_left_mounted != 0;
xmlFSType.Files = mddf.filecount; XmlFsType.Files = mddf.filecount;
xmlFSType.FilesSpecified = true; XmlFsType.FilesSpecified = true;
xmlFSType.FreeClusters = mddf.freecount; XmlFsType.FreeClusters = mddf.freecount;
xmlFSType.FreeClustersSpecified = true; XmlFsType.FreeClustersSpecified = true;
xmlFSType.Type = "LisaFS"; XmlFsType.Type = "LisaFS";
xmlFSType.VolumeName = mddf.volname; XmlFsType.VolumeName = mddf.volname;
xmlFSType.VolumeSerial = $"{mddf.volid:X16}"; XmlFsType.VolumeSerial = $"{mddf.volid:X16}";
return Errno.NoError; return Errno.NoError;
} }
@@ -353,24 +346,25 @@ namespace DiscImageChef.Filesystems.LisaFS
{ {
if(!mounted) return Errno.AccessDenied; if(!mounted) return Errno.AccessDenied;
stat = new FileSystemInfo(); stat = new FileSystemInfo
stat.Blocks = mddf.vol_size; {
stat.FilenameLength = (ushort)E_NAME; Blocks = mddf.vol_size,
stat.Files = mddf.filecount; FilenameLength = (ushort)E_NAME,
stat.FreeBlocks = mddf.freecount; Files = mddf.filecount,
FreeBlocks = mddf.freecount,
Id = {Serial64 = mddf.volid, IsLong = true},
PluginId = PluginUuid
};
stat.FreeFiles = FILEID_MAX - stat.Files; stat.FreeFiles = FILEID_MAX - stat.Files;
stat.Id.Serial64 = mddf.volid;
stat.Id.IsLong = true;
stat.PluginId = PluginUUID;
switch(mddf.fsversion) switch(mddf.fsversion)
{ {
case LisaFSv1: case LISA_V1:
stat.Type = "LisaFS v1"; stat.Type = "LisaFS v1";
break; break;
case LisaFSv2: case LISA_V2:
stat.Type = "LisaFS v2"; stat.Type = "LisaFS v2";
break; break;
case LisaFSv3: case LISA_V3:
stat.Type = "LisaFS v3"; stat.Type = "LisaFS v3";
break; break;
} }

View File

@@ -48,9 +48,7 @@ namespace DiscImageChef.Filesystems.LisaFS
/// <param name="xattrs">List of extended attributes, alternate data streams and forks.</param> /// <param name="xattrs">List of extended attributes, alternate data streams and forks.</param>
public override Errno ListXAttr(string path, ref List<string> xattrs) public override Errno ListXAttr(string path, ref List<string> xattrs)
{ {
short fileId; Errno error = LookupFileId(path, out short fileId, out bool isDir);
bool isDir;
Errno error = LookupFileId(path, out fileId, out isDir);
if(error != Errno.NoError) return error; if(error != Errno.NoError) return error;
return isDir ? Errno.InvalidArgument : ListXAttr(fileId, ref xattrs); return isDir ? Errno.InvalidArgument : ListXAttr(fileId, ref xattrs);
@@ -65,9 +63,7 @@ namespace DiscImageChef.Filesystems.LisaFS
/// <param name="buf">Buffer.</param> /// <param name="buf">Buffer.</param>
public override Errno GetXattr(string path, string xattr, ref byte[] buf) public override Errno GetXattr(string path, string xattr, ref byte[] buf)
{ {
short fileId; Errno error = LookupFileId(path, out short fileId, out bool isDir);
bool isDir;
Errno error = LookupFileId(path, out fileId, out isDir);
if(error != Errno.NoError) return error; if(error != Errno.NoError) return error;
return isDir ? Errno.InvalidArgument : GetXattr(fileId, xattr, out buf); return isDir ? Errno.InvalidArgument : GetXattr(fileId, xattr, out buf);
@@ -104,8 +100,7 @@ namespace DiscImageChef.Filesystems.LisaFS
else else
{ {
// Search for the file // Search for the file
ExtentFile file; Errno error = ReadExtentsFile(fileId, out ExtentFile file);
Errno error = ReadExtentsFile(fileId, out file);
if(error != Errno.NoError) return error; if(error != Errno.NoError) return error;
@@ -162,8 +157,7 @@ namespace DiscImageChef.Filesystems.LisaFS
} }
// Search for the file // Search for the file
ExtentFile file; Errno error = ReadExtentsFile(fileId, out ExtentFile file);
Errno error = ReadExtentsFile(fileId, out file);
if(error != Errno.NoError) return error; if(error != Errno.NoError) return error;

View File

@@ -32,6 +32,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
using DiscImageChef.CommonTypes; using DiscImageChef.CommonTypes;
@@ -55,6 +56,8 @@ using time_t = System.Int32;
namespace DiscImageChef.Filesystems namespace DiscImageChef.Filesystems
{ {
[SuppressMessage("ReSharper", "InconsistentNaming")]
[SuppressMessage("ReSharper", "BuiltInTypeReferenceStyle")]
public class Locus : Filesystem public class Locus : Filesystem
{ {
const int NICINOD = 325; const int NICINOD = 325;
@@ -195,24 +198,22 @@ namespace DiscImageChef.Filesystems
public Locus() public Locus()
{ {
Name = "Locus Filesystem Plugin"; 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"); CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
} }
public Locus(Encoding encoding) public Locus(Encoding encoding)
{ {
Name = "Locus Filesystem Plugin"; Name = "Locus Filesystem Plugin";
PluginUUID = new Guid("1A70B30A-437D-479A-88E1-D0C9C1797FF4"); PluginUuid = new Guid("1A70B30A-437D-479A-88E1-D0C9C1797FF4");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public Locus(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public Locus(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "Locus Filesystem Plugin"; Name = "Locus Filesystem Plugin";
PluginUUID = new Guid("1A70B30A-437D-479A-88E1-D0C9C1797FF4"); PluginUuid = new Guid("1A70B30A-437D-479A-88E1-D0C9C1797FF4");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public override bool Identify(ImagePlugin imagePlugin, Partition partition) public override bool Identify(ImagePlugin imagePlugin, Partition partition)
@@ -284,12 +285,9 @@ namespace DiscImageChef.Filesystems
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
if(LocusSb.s_magic == Locus_OldMagic) sb.AppendLine("Locus filesystem (old)"); sb.AppendLine(LocusSb.s_magic == Locus_OldMagic ? "Locus filesystem (old)" : "Locus filesystem");
else sb.AppendLine("Locus filesystem");
int blockSize; int blockSize = LocusSb.s_version == LocusVersion.SB_SB4096 ? 4096 : 1024;
if(LocusSb.s_version == LocusVersion.SB_SB4096) blockSize = 4096;
else blockSize = 1024;
string s_fsmnt = StringHandlers.CToString(LocusSb.s_fsmnt, CurrentEncoding); string s_fsmnt = StringHandlers.CToString(LocusSb.s_fsmnt, CurrentEncoding);
string s_fpack = StringHandlers.CToString(LocusSb.s_fpack, CurrentEncoding); string s_fpack = StringHandlers.CToString(LocusSb.s_fpack, CurrentEncoding);
@@ -345,7 +343,7 @@ namespace DiscImageChef.Filesystems
information = sb.ToString(); information = sb.ToString();
xmlFSType = new FileSystemType XmlFsType = new FileSystemType
{ {
Type = "Locus filesystem", Type = "Locus filesystem",
ClusterSize = blockSize, ClusterSize = blockSize,

View File

@@ -44,30 +44,28 @@ namespace DiscImageChef.Filesystems
// Thanks to tarlabnor for translating it // Thanks to tarlabnor for translating it
public class MicroDOS : Filesystem public class MicroDOS : Filesystem
{ {
const ushort magic = 0xA72E; const ushort MAGIC = 0xA72E;
const ushort magic2 = 0x530C; const ushort MAGIC2 = 0x530C;
public MicroDOS() public MicroDOS()
{ {
Name = "MicroDOS file system"; 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"); CurrentEncoding = Encoding.GetEncoding("koi8-r");
} }
public MicroDOS(Encoding encoding) public MicroDOS(Encoding encoding)
{ {
Name = "MicroDOS file system"; Name = "MicroDOS file system";
PluginUUID = new Guid("9F9A364A-1A27-48A3-B730-7A7122000324"); PluginUuid = new Guid("9F9A364A-1A27-48A3-B730-7A7122000324");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("koi8-r"); CurrentEncoding = encoding ?? Encoding.GetEncoding("koi8-r");
else CurrentEncoding = encoding;
} }
public MicroDOS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public MicroDOS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "MicroDOS file system"; Name = "MicroDOS file system";
PluginUUID = new Guid("9F9A364A-1A27-48A3-B730-7A7122000324"); PluginUuid = new Guid("9F9A364A-1A27-48A3-B730-7A7122000324");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("koi8-r"); CurrentEncoding = encoding ?? Encoding.GetEncoding("koi8-r");
else CurrentEncoding = encoding;
} }
public override bool Identify(ImagePlugin imagePlugin, Partition partition) public override bool Identify(ImagePlugin imagePlugin, Partition partition)
@@ -76,15 +74,13 @@ namespace DiscImageChef.Filesystems
if(imagePlugin.GetSectorSize() < 512) return false; if(imagePlugin.GetSectorSize() < 512) return false;
MicroDOSBlock0 block0;
byte[] bk0 = imagePlugin.ReadSector(0 + partition.Start); byte[] bk0 = imagePlugin.ReadSector(0 + partition.Start);
GCHandle handle = GCHandle.Alloc(bk0, GCHandleType.Pinned); 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(); handle.Free();
return block0.label == magic && block0.mklabel == magic2; return block0.label == MAGIC && block0.mklabel == MAGIC2;
} }
public override void GetInformation(ImagePlugin imagePlugin, Partition partition, public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
@@ -93,12 +89,11 @@ namespace DiscImageChef.Filesystems
information = ""; information = "";
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
MicroDOSBlock0 block0;
byte[] bk0 = imagePlugin.ReadSector(0 + partition.Start); byte[] bk0 = imagePlugin.ReadSector(0 + partition.Start);
GCHandle handle = GCHandle.Alloc(bk0, GCHandleType.Pinned); 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(); handle.Free();
sb.AppendLine("MicroDOS filesystem"); sb.AppendLine("MicroDOS filesystem");
@@ -108,7 +103,7 @@ namespace DiscImageChef.Filesystems
sb.AppendFormat("Volume contains {0} files", block0.files).AppendLine(); sb.AppendFormat("Volume contains {0} files", block0.files).AppendLine();
sb.AppendFormat("First used block is {0}", block0.firstUsedBlock).AppendLine(); sb.AppendFormat("First used block is {0}", block0.firstUsedBlock).AppendLine();
xmlFSType = new FileSystemType XmlFsType = new FileSystemType
{ {
Type = "MicroDOS", Type = "MicroDOS",
ClusterSize = 512, ClusterSize = 512,

View File

@@ -68,24 +68,22 @@ namespace DiscImageChef.Filesystems
public MinixFS() public MinixFS()
{ {
Name = "Minix Filesystem"; 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"); CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
} }
public MinixFS(Encoding encoding) public MinixFS(Encoding encoding)
{ {
Name = "Minix Filesystem"; Name = "Minix Filesystem";
PluginUUID = new Guid("FE248C3B-B727-4AE5-A39F-79EA9A07D4B3"); PluginUuid = new Guid("FE248C3B-B727-4AE5-A39F-79EA9A07D4B3");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public MinixFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public MinixFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "Minix Filesystem"; Name = "Minix Filesystem";
PluginUUID = new Guid("FE248C3B-B727-4AE5-A39F-79EA9A07D4B3"); PluginUuid = new Guid("FE248C3B-B727-4AE5-A39F-79EA9A07D4B3");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public override bool Identify(ImagePlugin imagePlugin, Partition partition) public override bool Identify(ImagePlugin imagePlugin, Partition partition)
@@ -102,23 +100,23 @@ namespace DiscImageChef.Filesystems
if(sector + partition.Start >= partition.End) return false; if(sector + partition.Start >= partition.End) return false;
ushort magic; ushort magic;
byte[] minix_sb_sector = imagePlugin.ReadSector(sector + partition.Start); byte[] minixSbSector = imagePlugin.ReadSector(sector + partition.Start);
// Optical media // Optical media
if(offset > 0) if(offset > 0)
{ {
byte[] tmp = new byte[0x200]; byte[] tmp = new byte[0x200];
Array.Copy(minix_sb_sector, offset, tmp, 0, 0x200); Array.Copy(minixSbSector, offset, tmp, 0, 0x200);
minix_sb_sector = tmp; 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 || if(magic == MINIX_MAGIC || magic == MINIX_MAGIC2 || magic == MINIX2_MAGIC || magic == MINIX2_MAGIC2 ||
magic == MINIX_CIGAM || magic == MINIX_CIGAM2 || magic == MINIX2_CIGAM || magic == MINIX_CIGAM || magic == MINIX_CIGAM2 || magic == MINIX2_CIGAM ||
magic == MINIX2_CIGAM2) return true; 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 || if(magic == MINIX_MAGIC || magic == MINIX2_MAGIC || magic == MINIX3_MAGIC || magic == MINIX_CIGAM ||
magic == MINIX2_CIGAM || magic == MINIX3_CIGAM) return true; magic == MINIX2_CIGAM || magic == MINIX3_CIGAM) return true;
@@ -146,19 +144,19 @@ namespace DiscImageChef.Filesystems
int filenamesize; int filenamesize;
string minixVersion; string minixVersion;
ushort magic; ushort magic;
byte[] minix_sb_sector = imagePlugin.ReadSector(sector + partition.Start); byte[] minixSbSector = imagePlugin.ReadSector(sector + partition.Start);
// Optical media // Optical media
if(offset > 0) if(offset > 0)
{ {
byte[] tmp = new byte[0x200]; byte[] tmp = new byte[0x200];
Array.Copy(minix_sb_sector, offset, tmp, 0, 0x200); Array.Copy(minixSbSector, offset, tmp, 0, 0x200);
minix_sb_sector = tmp; minixSbSector = tmp;
} }
magic = BitConverter.ToUInt16(minix_sb_sector, 0x018); magic = BitConverter.ToUInt16(minixSbSector, 0x018);
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType();
bool littleEndian; bool littleEndian;
@@ -172,16 +170,16 @@ namespace DiscImageChef.Filesystems
case MINIX3_MAGIC: case MINIX3_MAGIC:
case MINIX3_CIGAM: case MINIX3_CIGAM:
minixVersion = "Minix v3 filesystem"; minixVersion = "Minix v3 filesystem";
xmlFSType.Type = "Minix v3"; XmlFsType.Type = "Minix v3";
break; break;
case MINIX2_MAGIC: case MINIX2_MAGIC:
case MINIX2_CIGAM: case MINIX2_CIGAM:
minixVersion = "Minix 3 v2 filesystem"; minixVersion = "Minix 3 v2 filesystem";
xmlFSType.Type = "Minix 3 v2"; XmlFsType.Type = "Minix 3 v2";
break; break;
default: default:
minixVersion = "Minix 3 v1 filesystem"; minixVersion = "Minix 3 v1 filesystem";
xmlFSType.Type = "Minix 3 v1"; XmlFsType.Type = "Minix 3 v1";
break; break;
} }
@@ -189,7 +187,7 @@ namespace DiscImageChef.Filesystems
} }
else else
{ {
magic = BitConverter.ToUInt16(minix_sb_sector, 0x010); magic = BitConverter.ToUInt16(minixSbSector, 0x010);
switch(magic) switch(magic)
{ {
@@ -197,49 +195,49 @@ namespace DiscImageChef.Filesystems
filenamesize = 14; filenamesize = 14;
minixVersion = "Minix v1 filesystem"; minixVersion = "Minix v1 filesystem";
littleEndian = true; littleEndian = true;
xmlFSType.Type = "Minix v1"; XmlFsType.Type = "Minix v1";
break; break;
case MINIX_MAGIC2: case MINIX_MAGIC2:
filenamesize = 30; filenamesize = 30;
minixVersion = "Minix v1 filesystem"; minixVersion = "Minix v1 filesystem";
littleEndian = true; littleEndian = true;
xmlFSType.Type = "Minix v1"; XmlFsType.Type = "Minix v1";
break; break;
case MINIX2_MAGIC: case MINIX2_MAGIC:
filenamesize = 14; filenamesize = 14;
minixVersion = "Minix v2 filesystem"; minixVersion = "Minix v2 filesystem";
littleEndian = true; littleEndian = true;
xmlFSType.Type = "Minix v2"; XmlFsType.Type = "Minix v2";
break; break;
case MINIX2_MAGIC2: case MINIX2_MAGIC2:
filenamesize = 30; filenamesize = 30;
minixVersion = "Minix v2 filesystem"; minixVersion = "Minix v2 filesystem";
littleEndian = true; littleEndian = true;
xmlFSType.Type = "Minix v2"; XmlFsType.Type = "Minix v2";
break; break;
case MINIX_CIGAM: case MINIX_CIGAM:
filenamesize = 14; filenamesize = 14;
minixVersion = "Minix v1 filesystem"; minixVersion = "Minix v1 filesystem";
littleEndian = false; littleEndian = false;
xmlFSType.Type = "Minix v1"; XmlFsType.Type = "Minix v1";
break; break;
case MINIX_CIGAM2: case MINIX_CIGAM2:
filenamesize = 30; filenamesize = 30;
minixVersion = "Minix v1 filesystem"; minixVersion = "Minix v1 filesystem";
littleEndian = false; littleEndian = false;
xmlFSType.Type = "Minix v1"; XmlFsType.Type = "Minix v1";
break; break;
case MINIX2_CIGAM: case MINIX2_CIGAM:
filenamesize = 14; filenamesize = 14;
minixVersion = "Minix v2 filesystem"; minixVersion = "Minix v2 filesystem";
littleEndian = false; littleEndian = false;
xmlFSType.Type = "Minix v2"; XmlFsType.Type = "Minix v2";
break; break;
case MINIX2_CIGAM2: case MINIX2_CIGAM2:
filenamesize = 30; filenamesize = 30;
minixVersion = "Minix v2 filesystem"; minixVersion = "Minix v2 filesystem";
littleEndian = false; littleEndian = false;
xmlFSType.Type = "Minix v2"; XmlFsType.Type = "Minix v2";
break; break;
default: return; default: return;
} }
@@ -247,75 +245,73 @@ namespace DiscImageChef.Filesystems
if(minix3) if(minix3)
{ {
Minix3SuperBlock mnx_sb; Minix3SuperBlock mnxSb;
if(littleEndian) if(littleEndian)
{ {
GCHandle handle = GCHandle.Alloc(minix_sb_sector, GCHandleType.Pinned); GCHandle handle = GCHandle.Alloc(minixSbSector, GCHandleType.Pinned);
mnx_sb = (Minix3SuperBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), mnxSb = (Minix3SuperBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),
typeof(Minix3SuperBlock)); typeof(Minix3SuperBlock));
handle.Free(); 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.AppendLine(minixVersion);
sb.AppendFormat("{0} chars in filename", filenamesize).AppendLine(); sb.AppendFormat("{0} chars in filename", filenamesize).AppendLine();
if(mnx_sb.s_zones > 0) // On V2 if(mnxSb.s_zones > 0) // On V2
sb.AppendFormat("{0} zones on volume ({1} bytes)", mnx_sb.s_zones, mnx_sb.s_zones * 1024) sb.AppendFormat("{0} zones on volume ({1} bytes)", mnxSb.s_zones, mnxSb.s_zones * 1024)
.AppendLine(); .AppendLine();
else 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(); .AppendLine();
sb.AppendFormat("{0} bytes/block", mnx_sb.s_blocksize).AppendLine(); sb.AppendFormat("{0} bytes/block", mnxSb.s_blocksize).AppendLine();
sb.AppendFormat("{0} inodes on volume", mnx_sb.s_ninodes).AppendLine(); sb.AppendFormat("{0} inodes on volume", mnxSb.s_ninodes).AppendLine();
sb.AppendFormat("{0} blocks on inode map ({1} bytes)", mnx_sb.s_imap_blocks, sb.AppendFormat("{0} blocks on inode map ({1} bytes)", mnxSb.s_imap_blocks,
mnx_sb.s_imap_blocks * mnx_sb.s_blocksize).AppendLine(); mnxSb.s_imap_blocks * mnxSb.s_blocksize).AppendLine();
sb.AppendFormat("{0} blocks on zone map ({1} bytes)", mnx_sb.s_zmap_blocks, sb.AppendFormat("{0} blocks on zone map ({1} bytes)", mnxSb.s_zmap_blocks,
mnx_sb.s_zmap_blocks * mnx_sb.s_blocksize).AppendLine(); mnxSb.s_zmap_blocks * mnxSb.s_blocksize).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("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("{0} bytes maximum per file", mnxSb.s_max_size).AppendLine();
sb.AppendFormat("On-disk filesystem version: {0}", mnx_sb.s_disk_version).AppendLine(); sb.AppendFormat("On-disk filesystem version: {0}", mnxSb.s_disk_version).AppendLine();
xmlFSType.ClusterSize = mnx_sb.s_blocksize; XmlFsType.ClusterSize = mnxSb.s_blocksize;
if(mnx_sb.s_zones > 0) xmlFSType.Clusters = mnx_sb.s_zones; XmlFsType.Clusters = mnxSb.s_zones > 0 ? mnxSb.s_zones : mnxSb.s_nzones;
else xmlFSType.Clusters = mnx_sb.s_nzones;
} }
else else
{ {
MinixSuperBlock mnx_sb; MinixSuperBlock mnxSb;
if(littleEndian) if(littleEndian)
{ {
GCHandle handle = GCHandle.Alloc(minix_sb_sector, GCHandleType.Pinned); GCHandle handle = GCHandle.Alloc(minixSbSector, GCHandleType.Pinned);
mnx_sb = (MinixSuperBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), mnxSb = (MinixSuperBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),
typeof(MinixSuperBlock)); typeof(MinixSuperBlock));
handle.Free(); handle.Free();
} }
else mnx_sb = BigEndianMarshal.ByteArrayToStructureBigEndian<MinixSuperBlock>(minix_sb_sector); else mnxSb = BigEndianMarshal.ByteArrayToStructureBigEndian<MinixSuperBlock>(minixSbSector);
sb.AppendLine(minixVersion); sb.AppendLine(minixVersion);
sb.AppendFormat("{0} chars in filename", filenamesize).AppendLine(); sb.AppendFormat("{0} chars in filename", filenamesize).AppendLine();
if(mnx_sb.s_zones > 0) // On V2 if(mnxSb.s_zones > 0) // On V2
sb.AppendFormat("{0} zones on volume ({1} bytes)", mnx_sb.s_zones, mnx_sb.s_zones * 1024) sb.AppendFormat("{0} zones on volume ({1} bytes)", mnxSb.s_zones, mnxSb.s_zones * 1024)
.AppendLine(); .AppendLine();
else 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(); .AppendLine();
sb.AppendFormat("{0} inodes on volume", mnx_sb.s_ninodes).AppendLine(); sb.AppendFormat("{0} inodes on volume", mnxSb.s_ninodes).AppendLine();
sb.AppendFormat("{0} blocks on inode map ({1} bytes)", mnx_sb.s_imap_blocks, sb.AppendFormat("{0} blocks on inode map ({1} bytes)", mnxSb.s_imap_blocks,
mnx_sb.s_imap_blocks * 1024).AppendLine(); mnxSb.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} blocks on zone map ({1} bytes)", mnxSb.s_zmap_blocks, mnxSb.s_zmap_blocks * 1024)
.AppendLine(); .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("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("{0} bytes maximum per file", mnxSb.s_max_size).AppendLine();
sb.AppendFormat("Filesystem state: {0:X4}", mnx_sb.s_state).AppendLine(); sb.AppendFormat("Filesystem state: {0:X4}", mnxSb.s_state).AppendLine();
xmlFSType.ClusterSize = 1024; XmlFsType.ClusterSize = 1024;
if(mnx_sb.s_zones > 0) xmlFSType.Clusters = mnx_sb.s_zones; XmlFsType.Clusters = mnxSb.s_zones > 0 ? mnxSb.s_zones : mnxSb.s_nzones;
else xmlFSType.Clusters = mnx_sb.s_nzones;
} }
information = sb.ToString(); information = sb.ToString();
} }

View File

@@ -95,37 +95,35 @@ namespace DiscImageChef.Filesystems
public ulong feature_incompat; public ulong feature_incompat;
} }
const ushort NILFS2_Magic = 0x3434; const ushort NILFS2_MAGIC = 0x3434;
const uint NILFS2_SuperOffset = 1024; const uint NILFS2_SUPER_OFFSET = 1024;
public NILFS2() public NILFS2()
{ {
Name = "NILFS2 Plugin"; Name = "NILFS2 Plugin";
PluginUUID = new Guid("35224226-C5CC-48B5-8FFD-3781E91E86B6"); PluginUuid = new Guid("35224226-C5CC-48B5-8FFD-3781E91E86B6");
CurrentEncoding = Encoding.UTF8; CurrentEncoding = Encoding.UTF8;
} }
public NILFS2(Encoding encoding) public NILFS2(Encoding encoding)
{ {
Name = "NILFS2 Plugin"; Name = "NILFS2 Plugin";
PluginUUID = new Guid("35224226-C5CC-48B5-8FFD-3781E91E86B6"); PluginUuid = new Guid("35224226-C5CC-48B5-8FFD-3781E91E86B6");
if(encoding == null) CurrentEncoding = Encoding.UTF8; CurrentEncoding = encoding ?? Encoding.UTF8;
else CurrentEncoding = encoding;
} }
public NILFS2(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public NILFS2(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "NILFS2 Plugin"; Name = "NILFS2 Plugin";
PluginUUID = new Guid("35224226-C5CC-48B5-8FFD-3781E91E86B6"); PluginUuid = new Guid("35224226-C5CC-48B5-8FFD-3781E91E86B6");
if(encoding == null) CurrentEncoding = Encoding.UTF8; CurrentEncoding = encoding ?? Encoding.UTF8;
else CurrentEncoding = encoding;
} }
public override bool Identify(ImagePlugin imagePlugin, Partition partition) public override bool Identify(ImagePlugin imagePlugin, Partition partition)
{ {
if(imagePlugin.GetSectorSize() < 512) return false; if(imagePlugin.GetSectorSize() < 512) return false;
uint sbAddr = NILFS2_SuperOffset / imagePlugin.GetSectorSize(); uint sbAddr = NILFS2_SUPER_OFFSET / imagePlugin.GetSectorSize();
if(sbAddr == 0) sbAddr = 1; if(sbAddr == 0) sbAddr = 1;
NILFS2_Superblock nilfsSb = new NILFS2_Superblock(); NILFS2_Superblock nilfsSb = new NILFS2_Superblock();
@@ -143,7 +141,7 @@ namespace DiscImageChef.Filesystems
nilfsSb = (NILFS2_Superblock)Marshal.PtrToStructure(sbPtr, typeof(NILFS2_Superblock)); nilfsSb = (NILFS2_Superblock)Marshal.PtrToStructure(sbPtr, typeof(NILFS2_Superblock));
Marshal.FreeHGlobal(sbPtr); Marshal.FreeHGlobal(sbPtr);
return nilfsSb.magic == NILFS2_Magic; return nilfsSb.magic == NILFS2_MAGIC;
} }
public override void GetInformation(ImagePlugin imagePlugin, Partition partition, public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
@@ -152,7 +150,7 @@ namespace DiscImageChef.Filesystems
information = ""; information = "";
if(imagePlugin.GetSectorSize() < 512) return; if(imagePlugin.GetSectorSize() < 512) return;
uint sbAddr = NILFS2_SuperOffset / imagePlugin.GetSectorSize(); uint sbAddr = NILFS2_SUPER_OFFSET / imagePlugin.GetSectorSize();
if(sbAddr == 0) sbAddr = 1; if(sbAddr == 0) sbAddr = 1;
NILFS2_Superblock nilfsSb = new NILFS2_Superblock(); NILFS2_Superblock nilfsSb = new NILFS2_Superblock();
@@ -168,7 +166,7 @@ namespace DiscImageChef.Filesystems
nilfsSb = (NILFS2_Superblock)Marshal.PtrToStructure(sbPtr, typeof(NILFS2_Superblock)); nilfsSb = (NILFS2_Superblock)Marshal.PtrToStructure(sbPtr, typeof(NILFS2_Superblock));
Marshal.FreeHGlobal(sbPtr); Marshal.FreeHGlobal(sbPtr);
if(nilfsSb.magic != NILFS2_Magic) return; if(nilfsSb.magic != NILFS2_MAGIC) return;
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
@@ -192,17 +190,19 @@ namespace DiscImageChef.Filesystems
information = sb.ToString(); information = sb.ToString();
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType
xmlFSType.Type = "NILFS2 filesystem"; {
if(nilfsSb.creator_os == 0) xmlFSType.SystemIdentifier = "Linux"; Type = "NILFS2 filesystem",
xmlFSType.ClusterSize = 1 << (int)(nilfsSb.log_block_size + 10); ClusterSize = 1 << (int)(nilfsSb.log_block_size + 10),
xmlFSType.Clusters = (long)nilfsSb.dev_size / xmlFSType.ClusterSize; VolumeName = StringHandlers.CToString(nilfsSb.volume_name, CurrentEncoding),
xmlFSType.VolumeName = StringHandlers.CToString(nilfsSb.volume_name, CurrentEncoding); VolumeSerial = nilfsSb.uuid.ToString(),
xmlFSType.VolumeSerial = nilfsSb.uuid.ToString(); CreationDate = DateHandlers.UNIXUnsignedToDateTime(nilfsSb.ctime),
xmlFSType.CreationDate = DateHandlers.UNIXUnsignedToDateTime(nilfsSb.ctime); CreationDateSpecified = true,
xmlFSType.CreationDateSpecified = true; ModificationDate = DateHandlers.UNIXUnsignedToDateTime(nilfsSb.wtime),
xmlFSType.ModificationDate = DateHandlers.UNIXUnsignedToDateTime(nilfsSb.wtime); ModificationDateSpecified = true
xmlFSType.ModificationDateSpecified = true; };
if(nilfsSb.creator_os == 0) XmlFsType.SystemIdentifier = "Linux";
XmlFsType.Clusters = (long)nilfsSb.dev_size / XmlFsType.ClusterSize;
} }
public override Errno Mount() public override Errno Mount()

View File

@@ -47,21 +47,21 @@ namespace DiscImageChef.Filesystems
public NTFS() public NTFS()
{ {
Name = "New Technology File System (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; CurrentEncoding = Encoding.Unicode;
} }
public NTFS(Encoding encoding) public NTFS(Encoding encoding)
{ {
Name = "New Technology File System (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; CurrentEncoding = Encoding.Unicode;
} }
public NTFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public NTFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "New Technology File System (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; CurrentEncoding = Encoding.Unicode;
} }
@@ -69,27 +69,26 @@ namespace DiscImageChef.Filesystems
{ {
if(2 + partition.Start >= partition.End) return false; if(2 + partition.Start >= partition.End) return false;
byte[] eigth_bytes = new byte[8]; byte[] eigthBytes = new byte[8];
byte fats_no; byte fatsNo;
ushort spfat, signature; ushort spFat, signature;
string oem_name;
byte[] ntfs_bpb = imagePlugin.ReadSector(0 + partition.Start); byte[] ntfsBpb = imagePlugin.ReadSector(0 + partition.Start);
Array.Copy(ntfs_bpb, 0x003, eigth_bytes, 0, 8); Array.Copy(ntfsBpb, 0x003, eigthBytes, 0, 8);
oem_name = StringHandlers.CToString(eigth_bytes); 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; return signature == 0xAA55;
} }
@@ -101,63 +100,62 @@ namespace DiscImageChef.Filesystems
StringBuilder sb = new StringBuilder(); 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); IntPtr bpbPtr = Marshal.AllocHGlobal(512);
Marshal.Copy(ntfs_bpb, 0, bpbPtr, 512); Marshal.Copy(ntfsBpb, 0, bpbPtr, 512);
ntfs_bb = (NTFS_BootBlock)Marshal.PtrToStructure(bpbPtr, typeof(NTFS_BootBlock)); NtfsBootBlock ntfsBb = (NtfsBootBlock)Marshal.PtrToStructure(bpbPtr, typeof(NtfsBootBlock));
Marshal.FreeHGlobal(bpbPtr); Marshal.FreeHGlobal(bpbPtr);
sb.AppendFormat("{0} bytes per sector", ntfs_bb.bps).AppendLine(); sb.AppendFormat("{0} bytes per sector", ntfsBb.bps).AppendLine();
sb.AppendFormat("{0} sectors per cluster ({1} bytes)", ntfs_bb.spc, ntfs_bb.spc * ntfs_bb.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} reserved sectors", ntfs_bb.rsectors).AppendLine();
// sb.AppendFormat("{0} FATs", ntfs_bb.fats_no).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} entries in the root folder", ntfs_bb.root_ent).AppendLine();
// sb.AppendFormat("{0} sectors on volume (small)", ntfs_bb.sml_sectors).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 FAT", ntfs_bb.spfat).AppendLine();
sb.AppendFormat("{0} sectors per track", ntfs_bb.sptrk).AppendLine(); sb.AppendFormat("{0} sectors per track", ntfsBb.sptrk).AppendLine();
sb.AppendFormat("{0} heads", ntfs_bb.heads).AppendLine(); sb.AppendFormat("{0} heads", ntfsBb.heads).AppendLine();
sb.AppendFormat("{0} hidden sectors before filesystem", ntfs_bb.hsectors).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("{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("NT flags: 0x{0:X2}", ntfs_bb.nt_flags).AppendLine();
// sb.AppendFormat("Signature 1: 0x{0:X2}", ntfs_bb.signature1).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(); .AppendLine();
sb.AppendFormat("Cluster where $MFT starts: {0}", ntfs_bb.mft_lsn).AppendLine(); sb.AppendFormat("Cluster where $MFT starts: {0}", ntfsBb.mft_lsn).AppendLine();
sb.AppendFormat("Cluster where $MFTMirr starts: {0}", ntfs_bb.mftmirror_lsn).AppendLine(); sb.AppendFormat("Cluster where $MFTMirr starts: {0}", ntfsBb.mftmirror_lsn).AppendLine();
if(ntfs_bb.mft_rc_clusters > 0) if(ntfsBb.mft_rc_clusters > 0)
sb.AppendFormat("{0} clusters per MFT record ({1} bytes)", ntfs_bb.mft_rc_clusters, sb.AppendFormat("{0} clusters per MFT record ({1} bytes)", ntfsBb.mft_rc_clusters,
ntfs_bb.mft_rc_clusters * ntfs_bb.bps * ntfs_bb.spc).AppendLine(); ntfsBb.mft_rc_clusters * ntfsBb.bps * ntfsBb.spc).AppendLine();
else sb.AppendFormat("{0} bytes per MFT record", 1 << -ntfs_bb.mft_rc_clusters).AppendLine(); else sb.AppendFormat("{0} bytes per MFT record", 1 << -ntfsBb.mft_rc_clusters).AppendLine();
if(ntfs_bb.index_blk_cts > 0) if(ntfsBb.index_blk_cts > 0)
sb.AppendFormat("{0} clusters per Index block ({1} bytes)", ntfs_bb.index_blk_cts, sb.AppendFormat("{0} clusters per Index block ({1} bytes)", ntfsBb.index_blk_cts,
ntfs_bb.index_blk_cts * ntfs_bb.bps * ntfs_bb.spc).AppendLine(); ntfsBb.index_blk_cts * ntfsBb.bps * ntfsBb.spc).AppendLine();
else sb.AppendFormat("{0} bytes per Index block", 1 << -ntfs_bb.index_blk_cts).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(); // 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 && if(ntfsBb.jump[0] == 0xEB && ntfsBb.jump[1] > 0x4E && ntfsBb.jump[1] < 0x80 &&
ntfs_bb.signature2 == 0xAA55) ntfsBb.signature2 == 0xAA55)
{ {
xmlFSType.Bootable = true; XmlFsType.Bootable = true;
Sha1Context sha1Ctx = new Sha1Context(); Sha1Context sha1Ctx = new Sha1Context();
sha1Ctx.Init(); 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.AppendLine("Volume is bootable");
sb.AppendFormat("Boot code's SHA1: {0}", bootChk).AppendLine(); sb.AppendFormat("Boot code's SHA1: {0}", bootChk).AppendLine();
} }
xmlFSType.ClusterSize = ntfs_bb.spc * ntfs_bb.bps; XmlFsType.ClusterSize = ntfsBb.spc * ntfsBb.bps;
xmlFSType.Clusters = ntfs_bb.sectors / ntfs_bb.spc; XmlFsType.Clusters = ntfsBb.sectors / ntfsBb.spc;
xmlFSType.VolumeSerial = $"{ntfs_bb.serial_no:X16}"; XmlFsType.VolumeSerial = $"{ntfsBb.serial_no:X16}";
xmlFSType.Type = "NTFS"; XmlFsType.Type = "NTFS";
information = sb.ToString(); information = sb.ToString();
} }
@@ -166,7 +164,7 @@ namespace DiscImageChef.Filesystems
/// NTFS $BOOT /// NTFS $BOOT
/// </summary> /// </summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)] [StructLayout(LayoutKind.Sequential, Pack = 1)]
struct NTFS_BootBlock struct NtfsBootBlock
{ {
// Start of BIOS Parameter Block // Start of BIOS Parameter Block
/// <summary>0x000, Jump to boot code</summary> /// <summary>0x000, Jump to boot code</summary>

View File

@@ -45,24 +45,22 @@ namespace DiscImageChef.Filesystems
public NintendoPlugin() public NintendoPlugin()
{ {
Name = "Nintendo optical filesystems"; 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"); CurrentEncoding = Encoding.GetEncoding("shift_jis");
} }
public NintendoPlugin(Encoding encoding) public NintendoPlugin(Encoding encoding)
{ {
Name = "Nintendo optical filesystems"; Name = "Nintendo optical filesystems";
PluginUUID = new Guid("4675fcb4-4418-4288-9e4a-33d6a4ac1126"); PluginUuid = new Guid("4675fcb4-4418-4288-9e4a-33d6a4ac1126");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("shift_jis"); CurrentEncoding = encoding ?? Encoding.GetEncoding("shift_jis");
else CurrentEncoding = encoding;
} }
public NintendoPlugin(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public NintendoPlugin(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "Nintendo optical filesystems"; Name = "Nintendo optical filesystems";
PluginUUID = new Guid("4675fcb4-4418-4288-9e4a-33d6a4ac1126"); PluginUuid = new Guid("4675fcb4-4418-4288-9e4a-33d6a4ac1126");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("shift_jis"); CurrentEncoding = encoding ?? Encoding.GetEncoding("shift_jis");
else CurrentEncoding = encoding;
} }
public override bool Identify(ImagePlugin imagePlugin, Partition partition) public override bool Identify(ImagePlugin imagePlugin, Partition partition)
@@ -75,12 +73,10 @@ namespace DiscImageChef.Filesystems
byte[] header = imagePlugin.ReadSectors(0, 0x50000 / imagePlugin.GetSectorSize()); 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); uint magicWii = BigEndianBitConverter.ToUInt32(header, 0x18);
if(magicGC == 0xC2339F3D || magicWii == 0x5D1C9EA3) return true; return magicGc == 0xC2339F3D || magicWii == 0x5D1C9EA3;
return false;
} }
public override void GetInformation(ImagePlugin imagePlugin, Partition partition, public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
@@ -88,7 +84,7 @@ namespace DiscImageChef.Filesystems
{ {
StringBuilder sbInformation = new StringBuilder(); StringBuilder sbInformation = new StringBuilder();
information = ""; information = "";
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType();
NintendoFields fields = new NintendoFields(); NintendoFields fields = new NintendoFields();
BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian;
@@ -97,35 +93,35 @@ namespace DiscImageChef.Filesystems
bool wii = false; bool wii = false;
uint magicGC = BigEndianBitConverter.ToUInt32(header, 0x1C); uint magicGc = BigEndianBitConverter.ToUInt32(header, 0x1C);
uint magicWii = BigEndianBitConverter.ToUInt32(header, 0x18); uint magicWii = BigEndianBitConverter.ToUInt32(header, 0x18);
if(magicWii == 0x5D1C9EA3) if(magicWii == 0x5D1C9EA3)
wii = true; wii = true;
else if(magicGC != 0xC2339F3D) else if(magicGc != 0xC2339F3D)
return; return;
fields.discType = Encoding.ASCII.GetString(header, 0, 1); fields.DiscType = Encoding.ASCII.GetString(header, 0, 1);
fields.gameCode = Encoding.ASCII.GetString(header, 1, 2); fields.GameCode = Encoding.ASCII.GetString(header, 1, 2);
fields.regionCode = Encoding.ASCII.GetString(header, 3, 1); fields.RegionCode = Encoding.ASCII.GetString(header, 3, 1);
fields.publisherCode = Encoding.ASCII.GetString(header, 4, 2); fields.PublisherCode = Encoding.ASCII.GetString(header, 4, 2);
fields.discID = Encoding.ASCII.GetString(header, 0, 6); fields.DiscId = Encoding.ASCII.GetString(header, 0, 6);
fields.discNumber = header[6]; fields.DiscNumber = header[6];
fields.discVersion = header[7]; fields.DiscVersion = header[7];
fields.streaming |= header[8] > 0; fields.Streaming |= header[8] > 0;
fields.streamBufferSize = header[9]; fields.StreamBufferSize = header[9];
byte[] temp = new byte[64]; byte[] temp = new byte[64];
Array.Copy(header, 0x20, temp, 0, 64); Array.Copy(header, 0x20, temp, 0, 64);
fields.title = StringHandlers.CToString(temp, CurrentEncoding); fields.Title = StringHandlers.CToString(temp, CurrentEncoding);
if(!wii) if(!wii)
{ {
fields.debugOff = BigEndianBitConverter.ToUInt32(header, 0x0400); fields.DebugOff = BigEndianBitConverter.ToUInt32(header, 0x0400);
fields.debugAddr = BigEndianBitConverter.ToUInt32(header, 0x0404); fields.DebugAddr = BigEndianBitConverter.ToUInt32(header, 0x0404);
fields.dolOff = BigEndianBitConverter.ToUInt32(header, 0x0420); fields.DolOff = BigEndianBitConverter.ToUInt32(header, 0x0420);
fields.fstOff = BigEndianBitConverter.ToUInt32(header, 0x0424); fields.FstOff = BigEndianBitConverter.ToUInt32(header, 0x0424);
fields.fstSize = BigEndianBitConverter.ToUInt32(header, 0x0428); fields.FstSize = BigEndianBitConverter.ToUInt32(header, 0x0428);
fields.fstMax = BigEndianBitConverter.ToUInt32(header, 0x042C); fields.FstMax = BigEndianBitConverter.ToUInt32(header, 0x042C);
} }
if(wii) if(wii)
@@ -136,231 +132,229 @@ namespace DiscImageChef.Filesystems
offset3 = BigEndianBitConverter.ToUInt32(header, 0x40014) << 2; offset3 = BigEndianBitConverter.ToUInt32(header, 0x40014) << 2;
offset4 = BigEndianBitConverter.ToUInt32(header, 0x4001C) << 2; offset4 = BigEndianBitConverter.ToUInt32(header, 0x4001C) << 2;
fields.firstPartitions = new NintendoPartition[BigEndianBitConverter.ToUInt32(header, 0x40000)]; fields.FirstPartitions = new NintendoPartition[BigEndianBitConverter.ToUInt32(header, 0x40000)];
fields.secondPartitions = new NintendoPartition[BigEndianBitConverter.ToUInt32(header, 0x40008)]; fields.SecondPartitions = new NintendoPartition[BigEndianBitConverter.ToUInt32(header, 0x40008)];
fields.thirdPartitions = new NintendoPartition[BigEndianBitConverter.ToUInt32(header, 0x40010)]; fields.ThirdPartitions = new NintendoPartition[BigEndianBitConverter.ToUInt32(header, 0x40010)];
fields.fourthPartitions = new NintendoPartition[BigEndianBitConverter.ToUInt32(header, 0x40018)]; 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) if(offset1 + i * 8 + 8 < 0x50000)
{ {
fields.firstPartitions[i].offset = fields.FirstPartitions[i].Offset =
BigEndianBitConverter.ToUInt32(header, (int)(offset1 + i * 8 + 0)) << 2; 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)); 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) if(offset1 + i * 8 + 8 < 0x50000)
{ {
fields.firstPartitions[i].offset = fields.FirstPartitions[i].Offset =
BigEndianBitConverter.ToUInt32(header, (int)(offset2 + i * 8 + 0)) << 2; 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)); 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) if(offset1 + i * 8 + 8 < 0x50000)
{ {
fields.firstPartitions[i].offset = fields.FirstPartitions[i].Offset =
BigEndianBitConverter.ToUInt32(header, (int)(offset3 + i * 8 + 0)) << 2; 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)); 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) if(offset1 + i * 8 + 8 < 0x50000)
{ {
fields.firstPartitions[i].offset = fields.FirstPartitions[i].Offset =
BigEndianBitConverter.ToUInt32(header, (int)(offset4 + i * 8 + 0)) << 2; 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)); BigEndianBitConverter.ToUInt32(header, (int)(offset4 + i * 8 + 4));
} }
fields.region = header[0x4E000]; fields.Region = header[0x4E000];
fields.japanAge = header[0x4E010]; fields.JapanAge = header[0x4E010];
fields.usaAge = header[0x4E011]; fields.UsaAge = header[0x4E011];
fields.germanAge = header[0x4E013]; fields.GermanAge = header[0x4E013];
fields.pegiAge = header[0x4E014]; fields.PegiAge = header[0x4E014];
fields.finlandAge = header[0x4E015]; fields.FinlandAge = header[0x4E015];
fields.portugalAge = header[0x4E016]; fields.PortugalAge = header[0x4E016];
fields.ukAge = header[0x4E017]; fields.UkAge = header[0x4E017];
fields.australiaAge = header[0x4E018]; fields.AustraliaAge = header[0x4E018];
fields.koreaAge = header[0x4E019]; fields.KoreaAge = header[0x4E019];
} }
else else
{ {
fields.firstPartitions = new NintendoPartition[0]; fields.FirstPartitions = new NintendoPartition[0];
fields.secondPartitions = new NintendoPartition[0]; fields.SecondPartitions = new NintendoPartition[0];
fields.thirdPartitions = new NintendoPartition[0]; fields.ThirdPartitions = new NintendoPartition[0];
fields.fourthPartitions = new NintendoPartition[0]; fields.FourthPartitions = new NintendoPartition[0];
} }
DicConsole.DebugWriteLine("Nintendo plugin", "discType = {0}", fields.discType); DicConsole.DebugWriteLine("Nintendo plugin", "discType = {0}", fields.DiscType);
DicConsole.DebugWriteLine("Nintendo plugin", "gameCode = {0}", fields.gameCode); DicConsole.DebugWriteLine("Nintendo plugin", "gameCode = {0}", fields.GameCode);
DicConsole.DebugWriteLine("Nintendo plugin", "regionCode = {0}", fields.regionCode); DicConsole.DebugWriteLine("Nintendo plugin", "regionCode = {0}", fields.RegionCode);
DicConsole.DebugWriteLine("Nintendo plugin", "publisherCode = {0}", fields.publisherCode); DicConsole.DebugWriteLine("Nintendo plugin", "publisherCode = {0}", fields.PublisherCode);
DicConsole.DebugWriteLine("Nintendo plugin", "discID = {0}", fields.discID); DicConsole.DebugWriteLine("Nintendo plugin", "discID = {0}", fields.DiscId);
DicConsole.DebugWriteLine("Nintendo plugin", "discNumber = {0}", fields.discNumber); DicConsole.DebugWriteLine("Nintendo plugin", "discNumber = {0}", fields.DiscNumber);
DicConsole.DebugWriteLine("Nintendo plugin", "discVersion = {0}", fields.discVersion); DicConsole.DebugWriteLine("Nintendo plugin", "discVersion = {0}", fields.DiscVersion);
DicConsole.DebugWriteLine("Nintendo plugin", "streaming = {0}", fields.streaming); DicConsole.DebugWriteLine("Nintendo plugin", "streaming = {0}", fields.Streaming);
DicConsole.DebugWriteLine("Nintendo plugin", "streamBufferSize = {0}", fields.streamBufferSize); DicConsole.DebugWriteLine("Nintendo plugin", "streamBufferSize = {0}", fields.StreamBufferSize);
DicConsole.DebugWriteLine("Nintendo plugin", "title = \"{0}\"", fields.title); DicConsole.DebugWriteLine("Nintendo plugin", "title = \"{0}\"", fields.Title);
DicConsole.DebugWriteLine("Nintendo plugin", "debugOff = 0x{0:X8}", fields.debugOff); DicConsole.DebugWriteLine("Nintendo plugin", "debugOff = 0x{0:X8}", fields.DebugOff);
DicConsole.DebugWriteLine("Nintendo plugin", "debugAddr = 0x{0:X8}", fields.debugAddr); DicConsole.DebugWriteLine("Nintendo plugin", "debugAddr = 0x{0:X8}", fields.DebugAddr);
DicConsole.DebugWriteLine("Nintendo plugin", "dolOff = 0x{0:X8}", fields.dolOff); DicConsole.DebugWriteLine("Nintendo plugin", "dolOff = 0x{0:X8}", fields.DolOff);
DicConsole.DebugWriteLine("Nintendo plugin", "fstOff = 0x{0:X8}", fields.fstOff); DicConsole.DebugWriteLine("Nintendo plugin", "fstOff = 0x{0:X8}", fields.FstOff);
DicConsole.DebugWriteLine("Nintendo plugin", "fstSize = {0}", fields.fstSize); DicConsole.DebugWriteLine("Nintendo plugin", "fstSize = {0}", fields.FstSize);
DicConsole.DebugWriteLine("Nintendo plugin", "fstMax = {0}", fields.fstMax); DicConsole.DebugWriteLine("Nintendo plugin", "fstMax = {0}", fields.FstMax);
for(int i = 0; i < fields.firstPartitions.Length; i++) for(int i = 0; i < fields.FirstPartitions.Length; i++)
{ {
DicConsole.DebugWriteLine("Nintendo plugin", "firstPartitions[{1}].offset = {0}", 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}", 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}", 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}", 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}", 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}", 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}", 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}", 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", "region = {0}", fields.Region);
DicConsole.DebugWriteLine("Nintendo plugin", "japanAge = {0}", fields.japanAge); DicConsole.DebugWriteLine("Nintendo plugin", "japanAge = {0}", fields.JapanAge);
DicConsole.DebugWriteLine("Nintendo plugin", "usaAge = {0}", fields.usaAge); DicConsole.DebugWriteLine("Nintendo plugin", "usaAge = {0}", fields.UsaAge);
DicConsole.DebugWriteLine("Nintendo plugin", "germanAge = {0}", fields.germanAge); DicConsole.DebugWriteLine("Nintendo plugin", "germanAge = {0}", fields.GermanAge);
DicConsole.DebugWriteLine("Nintendo plugin", "pegiAge = {0}", fields.pegiAge); DicConsole.DebugWriteLine("Nintendo plugin", "pegiAge = {0}", fields.PegiAge);
DicConsole.DebugWriteLine("Nintendo plugin", "finlandAge = {0}", fields.finlandAge); DicConsole.DebugWriteLine("Nintendo plugin", "finlandAge = {0}", fields.FinlandAge);
DicConsole.DebugWriteLine("Nintendo plugin", "portugalAge = {0}", fields.portugalAge); DicConsole.DebugWriteLine("Nintendo plugin", "portugalAge = {0}", fields.PortugalAge);
DicConsole.DebugWriteLine("Nintendo plugin", "ukAge = {0}", fields.ukAge); DicConsole.DebugWriteLine("Nintendo plugin", "ukAge = {0}", fields.UkAge);
DicConsole.DebugWriteLine("Nintendo plugin", "australiaAge = {0}", fields.australiaAge); DicConsole.DebugWriteLine("Nintendo plugin", "australiaAge = {0}", fields.AustraliaAge);
DicConsole.DebugWriteLine("Nintendo plugin", "koreaAge = {0}", fields.koreaAge); DicConsole.DebugWriteLine("Nintendo plugin", "koreaAge = {0}", fields.KoreaAge);
sbInformation.AppendLine("Nintendo optical filesystem"); sbInformation.AppendLine("Nintendo optical filesystem");
if(wii) sbInformation.AppendLine("Nintendo Wii Optical Disc"); sbInformation.AppendLine(wii ? "Nintendo Wii Optical Disc" : "Nintendo GameCube Optical Disc");
else sbInformation.AppendLine("Nintendo GameCube Optical Disc"); sbInformation.AppendFormat("Disc ID is {0}", fields.DiscId).AppendLine();
sbInformation.AppendFormat("Disc ID is {0}", fields.discID).AppendLine(); sbInformation.AppendFormat("Disc is a {0} disc", DiscTypeToString(fields.DiscType)).AppendLine();
sbInformation.AppendFormat("Disc is a {0} disc", DiscTypeToString(fields.discType)).AppendLine(); sbInformation.AppendFormat("Disc region is {0}", RegionCodeToString(fields.RegionCode)).AppendLine();
sbInformation.AppendFormat("Disc region is {0}", RegionCodeToString(fields.regionCode)).AppendLine(); sbInformation.AppendFormat("Published by {0}", PublisherCodeToString(fields.PublisherCode)).AppendLine();
sbInformation.AppendFormat("Published by {0}", PublisherCodeToString(fields.publisherCode)).AppendLine(); if(fields.DiscNumber > 0)
if(fields.discNumber > 0) sbInformation.AppendFormat("Disc number {0} of a multi-disc set", fields.DiscNumber + 1).AppendLine();
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.streaming) sbInformation.AppendLine("Disc is prepared for audio streaming"); if(fields.StreamBufferSize > 0)
if(fields.streamBufferSize > 0) sbInformation.AppendFormat("Audio streaming buffer size is {0} bytes", fields.StreamBufferSize)
sbInformation.AppendFormat("Audio streaming buffer size is {0} bytes", fields.streamBufferSize)
.AppendLine(); .AppendLine();
sbInformation.AppendFormat("Title: {0}", fields.title).AppendLine(); sbInformation.AppendFormat("Title: {0}", fields.Title).AppendLine();
if(wii) 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}", sbInformation.AppendFormat("First {0} partition starts at sector {1}",
PartitionTypeToString(fields.firstPartitions[i].type), PartitionTypeToString(fields.FirstPartitions[i].Type),
fields.firstPartitions[i].offset / 2048).AppendLine(); fields.FirstPartitions[i].Offset / 2048).AppendLine();
for(int i = 0; i < fields.secondPartitions.Length; i++) for(int i = 0; i < fields.SecondPartitions.Length; i++)
sbInformation.AppendFormat("Second {0} partition starts at sector {1}", sbInformation.AppendFormat("Second {0} partition starts at sector {1}",
PartitionTypeToString(fields.secondPartitions[i].type), PartitionTypeToString(fields.SecondPartitions[i].Type),
fields.secondPartitions[i].offset / 2048).AppendLine(); fields.SecondPartitions[i].Offset / 2048).AppendLine();
for(int i = 0; i < fields.thirdPartitions.Length; i++) for(int i = 0; i < fields.ThirdPartitions.Length; i++)
sbInformation.AppendFormat("Third {0} partition starts at sector {1}", sbInformation.AppendFormat("Third {0} partition starts at sector {1}",
PartitionTypeToString(fields.thirdPartitions[i].type), PartitionTypeToString(fields.ThirdPartitions[i].Type),
fields.thirdPartitions[i].offset / 2048).AppendLine(); fields.ThirdPartitions[i].Offset / 2048).AppendLine();
for(int i = 0; i < fields.fourthPartitions.Length; i++) for(int i = 0; i < fields.FourthPartitions.Length; i++)
sbInformation.AppendFormat("Fourth {0} partition starts at sector {1}", sbInformation.AppendFormat("Fourth {0} partition starts at sector {1}",
PartitionTypeToString(fields.fourthPartitions[i].type), PartitionTypeToString(fields.FourthPartitions[i].Type),
fields.fourthPartitions[i].offset / 2048).AppendLine(); fields.FourthPartitions[i].Offset / 2048).AppendLine();
// sbInformation.AppendFormat("Region byte is {0}", fields.region).AppendLine(); // sbInformation.AppendFormat("Region byte is {0}", fields.region).AppendLine();
if((fields.japanAge & 0x80) != 0x80) if((fields.JapanAge & 0x80) != 0x80)
sbInformation.AppendFormat("Japan age rating is {0}", fields.japanAge).AppendLine(); sbInformation.AppendFormat("Japan age rating is {0}", fields.JapanAge).AppendLine();
if((fields.usaAge & 0x80) != 0x80) if((fields.UsaAge & 0x80) != 0x80)
sbInformation.AppendFormat("ESRB age rating is {0}", fields.usaAge).AppendLine(); sbInformation.AppendFormat("ESRB age rating is {0}", fields.UsaAge).AppendLine();
if((fields.germanAge & 0x80) != 0x80) if((fields.GermanAge & 0x80) != 0x80)
sbInformation.AppendFormat("German age rating is {0}", fields.germanAge).AppendLine(); sbInformation.AppendFormat("German age rating is {0}", fields.GermanAge).AppendLine();
if((fields.pegiAge & 0x80) != 0x80) if((fields.PegiAge & 0x80) != 0x80)
sbInformation.AppendFormat("PEGI age rating is {0}", fields.pegiAge).AppendLine(); sbInformation.AppendFormat("PEGI age rating is {0}", fields.PegiAge).AppendLine();
if((fields.finlandAge & 0x80) != 0x80) if((fields.FinlandAge & 0x80) != 0x80)
sbInformation.AppendFormat("Finland age rating is {0}", fields.finlandAge).AppendLine(); sbInformation.AppendFormat("Finland age rating is {0}", fields.FinlandAge).AppendLine();
if((fields.portugalAge & 0x80) != 0x80) if((fields.PortugalAge & 0x80) != 0x80)
sbInformation.AppendFormat("Portugal age rating is {0}", fields.portugalAge).AppendLine(); sbInformation.AppendFormat("Portugal age rating is {0}", fields.PortugalAge).AppendLine();
if((fields.ukAge & 0x80) != 0x80) if((fields.UkAge & 0x80) != 0x80)
sbInformation.AppendFormat("UK age rating is {0}", fields.ukAge).AppendLine(); sbInformation.AppendFormat("UK age rating is {0}", fields.UkAge).AppendLine();
if((fields.australiaAge & 0x80) != 0x80) if((fields.AustraliaAge & 0x80) != 0x80)
sbInformation.AppendFormat("Australia age rating is {0}", fields.australiaAge).AppendLine(); sbInformation.AppendFormat("Australia age rating is {0}", fields.AustraliaAge).AppendLine();
if((fields.koreaAge & 0x80) != 0x80) if((fields.KoreaAge & 0x80) != 0x80)
sbInformation.AppendFormat("Korea age rating is {0}", fields.koreaAge).AppendLine(); sbInformation.AppendFormat("Korea age rating is {0}", fields.KoreaAge).AppendLine();
} }
else 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(); .AppendLine();
information = sbInformation.ToString(); information = sbInformation.ToString();
xmlFSType.Bootable = true; XmlFsType.Bootable = true;
xmlFSType.Clusters = (long)(imagePlugin.GetSectors() * imagePlugin.GetSectorSize() / 2048); XmlFsType.Clusters = (long)(imagePlugin.GetSectors() * imagePlugin.GetSectorSize() / 2048);
xmlFSType.ClusterSize = 2048; XmlFsType.ClusterSize = 2048;
if(wii) xmlFSType.Type = "Nintendo Wii filesystem"; XmlFsType.Type = wii ? "Nintendo Wii filesystem" : "Nintendo Gamecube filesystem";
else xmlFSType.Type = "Nintendo Gamecube filesystem"; XmlFsType.VolumeName = fields.Title;
xmlFSType.VolumeName = fields.title; XmlFsType.VolumeSerial = fields.DiscId;
xmlFSType.VolumeSerial = fields.discID;
} }
struct NintendoFields struct NintendoFields
{ {
public string discType; public string DiscType;
public string gameCode; public string GameCode;
public string regionCode; public string RegionCode;
public string publisherCode; public string PublisherCode;
public string discID; public string DiscId;
public byte discNumber; public byte DiscNumber;
public byte discVersion; public byte DiscVersion;
public bool streaming; public bool Streaming;
public byte streamBufferSize; public byte StreamBufferSize;
public string title; public string Title;
public uint debugOff; public uint DebugOff;
public uint debugAddr; public uint DebugAddr;
public uint dolOff; public uint DolOff;
public uint fstOff; public uint FstOff;
public uint fstSize; public uint FstSize;
public uint fstMax; public uint FstMax;
public NintendoPartition[] firstPartitions; public NintendoPartition[] FirstPartitions;
public NintendoPartition[] secondPartitions; public NintendoPartition[] SecondPartitions;
public NintendoPartition[] thirdPartitions; public NintendoPartition[] ThirdPartitions;
public NintendoPartition[] fourthPartitions; public NintendoPartition[] FourthPartitions;
public byte region; public byte Region;
public byte japanAge; public byte JapanAge;
public byte usaAge; public byte UsaAge;
public byte germanAge; public byte GermanAge;
public byte pegiAge; public byte PegiAge;
public byte finlandAge; public byte FinlandAge;
public byte portugalAge; public byte PortugalAge;
public byte ukAge; public byte UkAge;
public byte australiaAge; public byte AustraliaAge;
public byte koreaAge; public byte KoreaAge;
} }
struct NintendoPartition struct NintendoPartition
{ {
public uint offset; public uint Offset;
public uint type; public uint Type;
} }
string DiscTypeToString(string discType) static string DiscTypeToString(string discType)
{ {
switch(discType) switch(discType)
{ {
@@ -390,7 +384,7 @@ namespace DiscImageChef.Filesystems
return $"unknown type '{discType}'"; return $"unknown type '{discType}'";
} }
string RegionCodeToString(string regionCode) static string RegionCodeToString(string regionCode)
{ {
switch(regionCode) switch(regionCode)
{ {
@@ -415,7 +409,7 @@ namespace DiscImageChef.Filesystems
return $"unknown code '{regionCode}'"; return $"unknown code '{regionCode}'";
} }
string PublisherCodeToString(string publisherCode) static string PublisherCodeToString(string publisherCode)
{ {
switch(publisherCode) switch(publisherCode)
{ {
@@ -445,7 +439,7 @@ namespace DiscImageChef.Filesystems
return $"Unknown publisher '{publisherCode}'"; return $"Unknown publisher '{publisherCode}'";
} }
string PartitionTypeToString(uint type) static string PartitionTypeToString(uint type)
{ {
switch(type) switch(type)
{ {

View File

@@ -55,24 +55,22 @@ namespace DiscImageChef.Filesystems
public ODS() public ODS()
{ {
Name = "Files-11 On-Disk Structure"; 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"); CurrentEncoding = Encoding.GetEncoding("iso-8859-1");
} }
public ODS(Encoding encoding) public ODS(Encoding encoding)
{ {
Name = "Files-11 On-Disk Structure"; Name = "Files-11 On-Disk Structure";
PluginUUID = new Guid("de20633c-8021-4384-aeb0-83b0df14491f"); PluginUuid = new Guid("de20633c-8021-4384-aeb0-83b0df14491f");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-1"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1");
else CurrentEncoding = encoding;
} }
public ODS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public ODS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "Files-11 On-Disk Structure"; Name = "Files-11 On-Disk Structure";
PluginUUID = new Guid("de20633c-8021-4384-aeb0-83b0df14491f"); PluginUuid = new Guid("de20633c-8021-4384-aeb0-83b0df14491f");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-1"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1");
else CurrentEncoding = encoding;
} }
public override bool Identify(ImagePlugin imagePlugin, Partition partition) public override bool Identify(ImagePlugin imagePlugin, Partition partition)
@@ -81,12 +79,11 @@ namespace DiscImageChef.Filesystems
if(imagePlugin.GetSectorSize() < 512) return false; if(imagePlugin.GetSectorSize() < 512) return false;
byte[] magic_b = new byte[12]; byte[] magicB = new byte[12];
string magic; byte[] hbSector = imagePlugin.ReadSector(1 + partition.Start);
byte[] hb_sector = imagePlugin.ReadSector(1 + partition.Start);
Array.Copy(hb_sector, 0x1F0, magic_b, 0, 12); Array.Copy(hbSector, 0x1F0, magicB, 0, 12);
magic = Encoding.ASCII.GetString(magic_b); string magic = Encoding.ASCII.GetString(magicB);
DicConsole.DebugWriteLine("Files-11 plugin", "magic: \"{0}\"", magic); DicConsole.DebugWriteLine("Files-11 plugin", "magic: \"{0}\"", magic);
@@ -95,18 +92,16 @@ namespace DiscImageChef.Filesystems
// Optical disc // Optical disc
if(imagePlugin.ImageInfo.XmlMediaType != XmlMediaType.OpticalDisc) return false; 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); Array.Copy(hbSector, 0x3F0, magicB, 0, 12);
magic = Encoding.ASCII.GetString(magic_b); magic = Encoding.ASCII.GetString(magicB);
DicConsole.DebugWriteLine("Files-11 plugin", "unaligned magic: \"{0}\"", magic); DicConsole.DebugWriteLine("Files-11 plugin", "unaligned magic: \"{0}\"", magic);
if(magic == "DECFILE11A " || magic == "DECFILE11B ") return true; return magic == "DECFILE11A " || magic == "DECFILE11B ";
return false;
} }
public override void GetInformation(ImagePlugin imagePlugin, Partition partition, public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
@@ -115,14 +110,11 @@ namespace DiscImageChef.Filesystems
information = ""; information = "";
StringBuilder sb = new StringBuilder(); 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); GCHandle handle = GCHandle.Alloc(hbSector, GCHandleType.Pinned);
homeblock = (ODSHomeBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(ODSHomeBlock)); OdsHomeBlock homeblock = (OdsHomeBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(OdsHomeBlock));
handle.Free(); handle.Free();
// Optical disc // Optical disc
@@ -130,14 +122,14 @@ namespace DiscImageChef.Filesystems
StringHandlers.CToString(homeblock.format) != "DECFILE11A " && StringHandlers.CToString(homeblock.format) != "DECFILE11A " &&
StringHandlers.CToString(homeblock.format) != "DECFILE11B ") StringHandlers.CToString(homeblock.format) != "DECFILE11B ")
{ {
if(hb_sector.Length < 0x400) return; if(hbSector.Length < 0x400) return;
byte[] tmp = imagePlugin.ReadSector(partition.Start); byte[] tmp = imagePlugin.ReadSector(partition.Start);
hb_sector = new byte[0x200]; hbSector = new byte[0x200];
Array.Copy(tmp, 0x200, hb_sector, 0, 0x200); Array.Copy(tmp, 0x200, hbSector, 0, 0x200);
handle = GCHandle.Alloc(hb_sector, GCHandleType.Pinned); handle = GCHandle.Alloc(hbSector, GCHandleType.Pinned);
homeblock = (ODSHomeBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(ODSHomeBlock)); homeblock = (OdsHomeBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(OdsHomeBlock));
handle.Free(); handle.Free();
if(StringHandlers.CToString(homeblock.format) != "DECFILE11A " && 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("Volume permissions (r = read, w = write, c = create, d = delete)");
sb.AppendLine("System, owner, group, world"); sb.AppendLine("System, owner, group, world");
// System // System
if((homeblock.protect & 0x1000) == 0x1000) sb.Append("-"); sb.Append((homeblock.protect & 0x1000) == 0x1000 ? "-" : "r");
else sb.Append("r"); sb.Append((homeblock.protect & 0x2000) == 0x2000 ? "-" : "w");
if((homeblock.protect & 0x2000) == 0x2000) sb.Append("-"); sb.Append((homeblock.protect & 0x4000) == 0x4000 ? "-" : "c");
else sb.Append("w"); sb.Append((homeblock.protect & 0x8000) == 0x8000 ? "-" : "d");
if((homeblock.protect & 0x4000) == 0x4000) sb.Append("-");
else sb.Append("c");
if((homeblock.protect & 0x8000) == 0x8000) sb.Append("-");
else sb.Append("d");
// Owner // Owner
if((homeblock.protect & 0x100) == 0x100) sb.Append("-"); sb.Append((homeblock.protect & 0x100) == 0x100 ? "-" : "r");
else sb.Append("r"); sb.Append((homeblock.protect & 0x200) == 0x200 ? "-" : "w");
if((homeblock.protect & 0x200) == 0x200) sb.Append("-"); sb.Append((homeblock.protect & 0x400) == 0x400 ? "-" : "c");
else sb.Append("w"); sb.Append((homeblock.protect & 0x800) == 0x800 ? "-" : "d");
if((homeblock.protect & 0x400) == 0x400) sb.Append("-");
else sb.Append("c");
if((homeblock.protect & 0x800) == 0x800) sb.Append("-");
else sb.Append("d");
// Group // Group
if((homeblock.protect & 0x10) == 0x10) sb.Append("-"); sb.Append((homeblock.protect & 0x10) == 0x10 ? "-" : "r");
else sb.Append("r"); sb.Append((homeblock.protect & 0x20) == 0x20 ? "-" : "w");
if((homeblock.protect & 0x20) == 0x20) sb.Append("-"); sb.Append((homeblock.protect & 0x40) == 0x40 ? "-" : "c");
else sb.Append("w"); sb.Append((homeblock.protect & 0x80) == 0x80 ? "-" : "d");
if((homeblock.protect & 0x40) == 0x40) sb.Append("-");
else sb.Append("c");
if((homeblock.protect & 0x80) == 0x80) sb.Append("-");
else sb.Append("d");
// World (other) // World (other)
if((homeblock.protect & 0x1) == 0x1) sb.Append("-"); sb.Append((homeblock.protect & 0x1) == 0x1 ? "-" : "r");
else sb.Append("r"); sb.Append((homeblock.protect & 0x2) == 0x2 ? "-" : "w");
if((homeblock.protect & 0x2) == 0x2) sb.Append("-"); sb.Append((homeblock.protect & 0x4) == 0x4 ? "-" : "c");
else sb.Append("w"); sb.Append((homeblock.protect & 0x8) == 0x8 ? "-" : "d");
if((homeblock.protect & 0x4) == 0x4) sb.Append("-");
else sb.Append("c");
if((homeblock.protect & 0x8) == 0x8) sb.Append("-");
else sb.Append("d");
sb.AppendLine(); sb.AppendLine();
@@ -243,7 +219,7 @@ namespace DiscImageChef.Filesystems
sb.AppendFormat("File protection: 0x{0:X4}", homeblock.fileprot).AppendLine(); sb.AppendFormat("File protection: 0x{0:X4}", homeblock.fileprot).AppendLine();
sb.AppendFormat("Record protection: 0x{0:X4}", homeblock.recprot).AppendLine(); sb.AppendFormat("Record protection: 0x{0:X4}", homeblock.recprot).AppendLine();
xmlFSType = new FileSystemType XmlFsType = new FileSystemType
{ {
Type = "FILES-11", Type = "FILES-11",
ClusterSize = homeblock.cluster * 512, ClusterSize = homeblock.cluster * 512,
@@ -253,20 +229,20 @@ namespace DiscImageChef.Filesystems
}; };
if(homeblock.credate > 0) if(homeblock.credate > 0)
{ {
xmlFSType.CreationDate = DateHandlers.VMSToDateTime(homeblock.credate); XmlFsType.CreationDate = DateHandlers.VMSToDateTime(homeblock.credate);
xmlFSType.CreationDateSpecified = true; XmlFsType.CreationDateSpecified = true;
} }
if(homeblock.revdate > 0) if(homeblock.revdate > 0)
{ {
xmlFSType.ModificationDate = DateHandlers.VMSToDateTime(homeblock.revdate); XmlFsType.ModificationDate = DateHandlers.VMSToDateTime(homeblock.revdate);
xmlFSType.ModificationDateSpecified = true; XmlFsType.ModificationDateSpecified = true;
} }
information = sb.ToString(); information = sb.ToString();
} }
[StructLayout(LayoutKind.Sequential, Pack = 1)] [StructLayout(LayoutKind.Sequential, Pack = 1)]
struct ODSHomeBlock struct OdsHomeBlock
{ {
/// <summary>0x000, LBN of THIS home block</summary> /// <summary>0x000, LBN of THIS home block</summary>
public uint homelbn; public uint homelbn;

View File

@@ -45,14 +45,14 @@ namespace DiscImageChef.Filesystems
public OperaFS() public OperaFS()
{ {
Name = "Opera Filesystem Plugin"; Name = "Opera Filesystem Plugin";
PluginUUID = new Guid("0ec84ec7-eae6-4196-83fe-943b3fe46dbd"); PluginUuid = new Guid("0ec84ec7-eae6-4196-83fe-943b3fe46dbd");
CurrentEncoding = Encoding.ASCII; CurrentEncoding = Encoding.ASCII;
} }
public OperaFS(Encoding encoding) public OperaFS(Encoding encoding)
{ {
Name = "Opera Filesystem Plugin"; 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 // TODO: Find correct default encoding
CurrentEncoding = Encoding.ASCII; CurrentEncoding = Encoding.ASCII;
} }
@@ -60,7 +60,7 @@ namespace DiscImageChef.Filesystems
public OperaFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public OperaFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "Opera Filesystem Plugin"; 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 // TODO: Find correct default encoding
CurrentEncoding = Encoding.ASCII; CurrentEncoding = Encoding.ASCII;
} }
@@ -69,75 +69,72 @@ namespace DiscImageChef.Filesystems
{ {
if(2 + partition.Start >= partition.End) return false; 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[] syncBytes = new byte[5];
byte[] sync_bytes = new byte[5];
byte record_version;
record_type = sb_sector[0x000]; byte recordType = sbSector[0x000];
Array.Copy(sb_sector, 0x001, sync_bytes, 0, 5); Array.Copy(sbSector, 0x001, syncBytes, 0, 5);
record_version = sb_sector[0x006]; 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, public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
out string information) out string information)
{ {
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); OperaSuperBlock sb = BigEndianMarshal.ByteArrayToStructureBigEndian<OperaSuperBlock>(sbSector);
byte[] cString = new byte[32];
sb.sync_bytes = new byte[5]; sb.sync_bytes = new byte[5];
if(sb.record_type != 1 || sb.record_version != 1) return; if(sb.record_type != 1 || sb.record_version != 1) return;
if(Encoding.ASCII.GetString(sb.sync_bytes) != "ZZZZZ") 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))) if(!string.IsNullOrEmpty(StringHandlers.CToString(sb.volume_label, CurrentEncoding)))
SuperBlockMetadata superBlockMetadata
.AppendFormat("Volume label: {0}", StringHandlers.CToString(sb.volume_label, CurrentEncoding)) .AppendFormat("Volume label: {0}", StringHandlers.CToString(sb.volume_label, CurrentEncoding))
.AppendLine(); .AppendLine();
if(!string.IsNullOrEmpty(StringHandlers.CToString(sb.volume_comment, CurrentEncoding))) 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)) StringHandlers.CToString(sb.volume_comment, CurrentEncoding))
.AppendLine(); .AppendLine();
SuperBlockMetadata.AppendFormat("Volume identifier: 0x{0:X8}", sb.volume_id).AppendLine(); superBlockMetadata.AppendFormat("Volume identifier: 0x{0:X8}", sb.volume_id).AppendLine();
SuperBlockMetadata.AppendFormat("Block size: {0} bytes", sb.block_size).AppendLine(); superBlockMetadata.AppendFormat("Block size: {0} bytes", sb.block_size).AppendLine();
if(imagePlugin.GetSectorSize() == 2336 || imagePlugin.GetSectorSize() == 2352 || if(imagePlugin.GetSectorSize() == 2336 || imagePlugin.GetSectorSize() == 2352 ||
imagePlugin.GetSectorSize() == 2448) imagePlugin.GetSectorSize() == 2448)
{ {
if(sb.block_size != 2048) if(sb.block_size != 2048)
SuperBlockMetadata superBlockMetadata
.AppendFormat("WARNING: Filesystem indicates {0} bytes/block while device indicates {1} bytes/block", .AppendFormat("WARNING: Filesystem indicates {0} bytes/block while device indicates {1} bytes/block",
sb.block_size, 2048); sb.block_size, 2048);
} }
else if(imagePlugin.GetSectorSize() != sb.block_size) else if(imagePlugin.GetSectorSize() != sb.block_size)
SuperBlockMetadata superBlockMetadata
.AppendFormat("WARNING: Filesystem indicates {0} bytes/block while device indicates {1} bytes/block", .AppendFormat("WARNING: Filesystem indicates {0} bytes/block while device indicates {1} bytes/block",
sb.block_size, imagePlugin.GetSectorSize()); sb.block_size, imagePlugin.GetSectorSize());
SuperBlockMetadata superBlockMetadata
.AppendFormat("Volume size: {0} blocks, {1} bytes", sb.block_count, sb.block_size * sb.block_count) .AppendFormat("Volume size: {0} blocks, {1} bytes", sb.block_count, sb.block_size * sb.block_count)
.AppendLine(); .AppendLine();
if((ulong)sb.block_count > imagePlugin.GetSectors()) if((ulong)sb.block_count > imagePlugin.GetSectors())
SuperBlockMetadata superBlockMetadata
.AppendFormat("WARNING: Filesystem indicates {0} blocks while device indicates {1} blocks", .AppendFormat("WARNING: Filesystem indicates {0} blocks while device indicates {1} blocks",
sb.block_count, imagePlugin.GetSectors()); sb.block_count, imagePlugin.GetSectors());
SuperBlockMetadata.AppendFormat("Root directory identifier: 0x{0:X8}", sb.root_dirid).AppendLine(); 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 block size: {0} bytes", sb.rootdir_bsize).AppendLine();
SuperBlockMetadata.AppendFormat("Root directory size: {0} blocks, {1} bytes", sb.rootdir_blocks, superBlockMetadata.AppendFormat("Root directory size: {0} blocks, {1} bytes", sb.rootdir_blocks,
sb.rootdir_bsize * sb.rootdir_blocks).AppendLine(); 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", Type = "Opera",
VolumeName = StringHandlers.CToString(sb.volume_label, CurrentEncoding), VolumeName = StringHandlers.CToString(sb.volume_label, CurrentEncoding),

View File

@@ -44,46 +44,46 @@ namespace DiscImageChef.Filesystems
public PCEnginePlugin() public PCEnginePlugin()
{ {
Name = "PC Engine CD Plugin"; 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"); CurrentEncoding = Encoding.GetEncoding("shift_jis");
} }
public PCEnginePlugin(Encoding encoding) public PCEnginePlugin(Encoding encoding)
{ {
Name = "PC Engine CD Plugin"; Name = "PC Engine CD Plugin";
PluginUUID = new Guid("e5ee6d7c-90fa-49bd-ac89-14ef750b8af3"); PluginUuid = new Guid("e5ee6d7c-90fa-49bd-ac89-14ef750b8af3");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("shift_jis"); CurrentEncoding = encoding ?? Encoding.GetEncoding("shift_jis");
else CurrentEncoding = encoding;
} }
public PCEnginePlugin(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public PCEnginePlugin(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "PC Engine CD Plugin"; Name = "PC Engine CD Plugin";
PluginUUID = new Guid("e5ee6d7c-90fa-49bd-ac89-14ef750b8af3"); PluginUuid = new Guid("e5ee6d7c-90fa-49bd-ac89-14ef750b8af3");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("shift_jis"); CurrentEncoding = encoding ?? Encoding.GetEncoding("shift_jis");
else CurrentEncoding = encoding;
} }
public override bool Identify(ImagePlugin imagePlugin, Partition partition) public override bool Identify(ImagePlugin imagePlugin, Partition partition)
{ {
if(2 + partition.Start >= partition.End) return false; 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); 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, public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
out string information) out string information)
{ {
information = ""; information = "";
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType
xmlFSType.Type = "PC Engine filesystem"; {
xmlFSType.Clusters = (long)((partition.End - partition.Start + 1) / imagePlugin.GetSectorSize() * 2048); Type = "PC Engine filesystem",
xmlFSType.ClusterSize = 2048; Clusters = (long)((partition.End - partition.Start + 1) / imagePlugin.GetSectorSize() * 2048),
ClusterSize = 2048
};
} }
public override Errno Mount() public override Errno Mount()

View File

@@ -45,24 +45,22 @@ namespace DiscImageChef.Filesystems
public PFS() public PFS()
{ {
Name = "Professional File System"; 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"); CurrentEncoding = Encoding.GetEncoding("iso-8859-1");
} }
public PFS(Encoding encoding) public PFS(Encoding encoding)
{ {
Name = "Professional File System"; Name = "Professional File System";
PluginUUID = new Guid("68DE769E-D957-406A-8AE4-3781CA8CDA77"); PluginUuid = new Guid("68DE769E-D957-406A-8AE4-3781CA8CDA77");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-1"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1");
else CurrentEncoding = encoding;
} }
public PFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public PFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "Professional File System"; Name = "Professional File System";
PluginUUID = new Guid("68DE769E-D957-406A-8AE4-3781CA8CDA77"); PluginUuid = new Guid("68DE769E-D957-406A-8AE4-3781CA8CDA77");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-1"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1");
else CurrentEncoding = encoding;
} }
/// <summary> /// <summary>
@@ -204,28 +202,27 @@ namespace DiscImageChef.Filesystems
public override void GetInformation(ImagePlugin imagePlugin, Partition partition, public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
out string information) out string information)
{ {
byte[] RootBlockSector = imagePlugin.ReadSector(2 + partition.Start); byte[] rootBlockSector = imagePlugin.ReadSector(2 + partition.Start);
RootBlock rootBlock; RootBlock rootBlock = BigEndianMarshal.ByteArrayToStructureBigEndian<RootBlock>(rootBlockSector);
rootBlock = BigEndianMarshal.ByteArrayToStructureBigEndian<RootBlock>(RootBlockSector);
StringBuilder sbInformation = new StringBuilder(); StringBuilder sbInformation = new StringBuilder();
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType();
switch(rootBlock.diskType) switch(rootBlock.diskType)
{ {
case AFS_DISK: case AFS_DISK:
case MUAF_DISK: case MUAF_DISK:
sbInformation.Append("Professional File System v1"); sbInformation.Append("Professional File System v1");
xmlFSType.Type = "PFS v1"; XmlFsType.Type = "PFS v1";
break; break;
case PFS2_DISK: case PFS2_DISK:
sbInformation.Append("Professional File System v2"); sbInformation.Append("Professional File System v2");
xmlFSType.Type = "PFS v2"; XmlFsType.Type = "PFS v2";
break; break;
case PFS_DISK: case PFS_DISK:
case MUPFS_DISK: case MUPFS_DISK:
sbInformation.Append("Professional File System v3"); sbInformation.Append("Professional File System v3");
xmlFSType.Type = "PFS v3"; XmlFsType.Type = "PFS v3";
break; break;
} }
@@ -248,14 +245,14 @@ namespace DiscImageChef.Filesystems
information = sbInformation.ToString(); information = sbInformation.ToString();
xmlFSType.CreationDate = XmlFsType.CreationDate =
DateHandlers.AmigaToDateTime(rootBlock.creationday, rootBlock.creationminute, rootBlock.creationtick); DateHandlers.AmigaToDateTime(rootBlock.creationday, rootBlock.creationminute, rootBlock.creationtick);
xmlFSType.CreationDateSpecified = true; XmlFsType.CreationDateSpecified = true;
xmlFSType.FreeClusters = rootBlock.blocksfree; XmlFsType.FreeClusters = rootBlock.blocksfree;
xmlFSType.FreeClustersSpecified = true; XmlFsType.FreeClustersSpecified = true;
xmlFSType.Clusters = rootBlock.diskSize; XmlFsType.Clusters = rootBlock.diskSize;
xmlFSType.ClusterSize = (int)imagePlugin.GetSectorSize(); XmlFsType.ClusterSize = (int)imagePlugin.GetSectorSize();
xmlFSType.VolumeName = StringHandlers.PascalToString(rootBlock.diskname, CurrentEncoding); XmlFsType.VolumeName = StringHandlers.PascalToString(rootBlock.diskname, CurrentEncoding);
} }
public override Errno Mount() public override Errno Mount()

View File

@@ -46,55 +46,55 @@ namespace DiscImageChef.Filesystems
// Information from Apple ProDOS 8 Technical Reference // Information from Apple ProDOS 8 Technical Reference
public class ProDOSPlugin : Filesystem public class ProDOSPlugin : Filesystem
{ {
const byte EmptyStorageType = 0x00; const byte EMPTY_STORAGE_TYPE = 0x00;
/// <summary> /// <summary>
/// A file that occupies one block or less /// A file that occupies one block or less
/// </summary> /// </summary>
const byte SeedlingFileType = 0x01; const byte SEEDLING_FILE_TYPE = 0x01;
/// <summary> /// <summary>
/// A file that occupies between 2 and 256 blocks /// A file that occupies between 2 and 256 blocks
/// </summary> /// </summary>
const byte SaplingFileType = 0x02; const byte SAPLING_FILE_TYPE = 0x02;
/// <summary> /// <summary>
/// A file that occupies between 257 and 32768 blocks /// A file that occupies between 257 and 32768 blocks
/// </summary> /// </summary>
const byte TreeFileType = 0x03; const byte TREE_FILE_TYPE = 0x03;
const byte PascalAreaType = 0x04; const byte PASCAL_AREA_TYPE = 0x04;
const byte SubDirectoryType = 0x0D; const byte SUBDIRECTORY_TYPE = 0x0D;
const byte SubDirectoryHeaderType = 0x0E; const byte SUBDIRECTORY_HEADER_TYPE = 0x0E;
const byte RootDirectoryType = 0x0F; const byte ROOT_DIRECTORY_TYPE = 0x0F;
const byte ProDOSVersion1 = 0x00; const byte VERSION1 = 0x00;
const uint ProDOSYearMask = 0xFE000000; const uint YEAR_MASK = 0xFE000000;
const uint ProDOSMonthMask = 0x1E00000; const uint MONTH_MASK = 0x1E00000;
const uint ProDOSDayMask = 0x1F0000; const uint DAY_MASK = 0x1F0000;
const uint ProDOSHourMask = 0x1F00; const uint HOUR_MASK = 0x1F00;
const uint ProDOSMinuteMask = 0x3F; const uint MINUTE_MASK = 0x3F;
const byte ProDOSDestroyAttribute = 0x80; const byte DESTROY_ATTRIBUTE = 0x80;
const byte ProDOSRenameAttribute = 0x40; const byte RENAME_ATTRIBUTE = 0x40;
const byte ProDOSBackupAttribute = 0x20; const byte BACKUP_ATTRIBUTE = 0x20;
const byte ProDOSWriteAttribute = 0x02; const byte WRITE_ATTRIBUTE = 0x02;
const byte ProDOSReadAttribute = 0x01; const byte READ_ATTRIBUTE = 0x01;
const byte ProDOSReservedAttributeMask = 0x1C; const byte RESERVED_ATTRIBUTE_MASK = 0x1C;
const byte ProDOSStorageTypeMask = 0xF0; const byte STORAGE_TYPE_MASK = 0xF0;
const byte ProDOSNameLengthMask = 0x0F; const byte NAME_LENGTH_MASK = 0x0F;
const byte ProDOSEntryLength = 0x27; const byte ENTRY_LENGTH = 0x27;
const byte ProDOSEntriesPerBlock = 0x0D; const byte ENTRIES_PER_BLOCK = 0x0D;
public ProDOSPlugin() public ProDOSPlugin()
{ {
Name = "Apple ProDOS filesystem"; Name = "Apple ProDOS filesystem";
PluginUUID = new Guid("43874265-7B8A-4739-BCF7-07F80D5932BF"); PluginUuid = new Guid("43874265-7B8A-4739-BCF7-07F80D5932BF");
CurrentEncoding = new LisaRoman(); CurrentEncoding = new LisaRoman();
} }
public ProDOSPlugin(Encoding encoding) public ProDOSPlugin(Encoding encoding)
{ {
Name = "Apple ProDOS filesystem"; 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 // TODO: Until Apple ][ encoding is implemented
CurrentEncoding = new LisaRoman(); CurrentEncoding = new LisaRoman();
} }
@@ -102,7 +102,7 @@ namespace DiscImageChef.Filesystems
public ProDOSPlugin(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public ProDOSPlugin(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "Apple ProDOS filesystem"; 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 // TODO: Until Apple ][ encoding is implemented
CurrentEncoding = new LisaRoman(); CurrentEncoding = new LisaRoman();
} }
@@ -121,8 +121,8 @@ namespace DiscImageChef.Filesystems
byte[] tmp = imagePlugin.ReadSectors(partition.Start, 2); 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 && 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 && (byte)((tmp[offset + 0x04] & STORAGE_TYPE_MASK) >> 4) == ROOT_DIRECTORY_TYPE &&
tmp[offset + 0x23] == ProDOSEntryLength && tmp[offset + 0x24] == ProDOSEntriesPerBlock)) { tmp[offset + 0x23] == ENTRY_LENGTH && tmp[offset + 0x24] == ENTRIES_PER_BLOCK)) {
Array.Copy(tmp, offset, rootDirectoryKeyBlock, 0, 0x200); Array.Copy(tmp, offset, rootDirectoryKeyBlock, 0, 0x200);
APMFromHDDOnCD = true; APMFromHDDOnCD = true;
break; break;
@@ -133,28 +133,28 @@ namespace DiscImageChef.Filesystems
DicConsole.DebugWriteLine("ProDOS plugin", "prePointer = {0}", prePointer); DicConsole.DebugWriteLine("ProDOS plugin", "prePointer = {0}", prePointer);
if(prePointer != 0) return false; if(prePointer != 0) return false;
byte storage_type = (byte)((rootDirectoryKeyBlock[0x04] & ProDOSStorageTypeMask) >> 4); byte storageType = (byte)((rootDirectoryKeyBlock[0x04] & STORAGE_TYPE_MASK) >> 4);
DicConsole.DebugWriteLine("ProDOS plugin", "storage_type = {0}", storage_type); DicConsole.DebugWriteLine("ProDOS plugin", "storage_type = {0}", storageType);
if(storage_type != RootDirectoryType) return false; if(storageType != ROOT_DIRECTORY_TYPE) return false;
byte entry_length = rootDirectoryKeyBlock[0x23]; byte entryLength = rootDirectoryKeyBlock[0x23];
DicConsole.DebugWriteLine("ProDOS plugin", "entry_length = {0}", entry_length); DicConsole.DebugWriteLine("ProDOS plugin", "entry_length = {0}", entryLength);
if(entry_length != ProDOSEntryLength) return false; if(entryLength != ENTRY_LENGTH) return false;
byte entries_per_block = rootDirectoryKeyBlock[0x24]; byte entriesPerBlock = rootDirectoryKeyBlock[0x24];
DicConsole.DebugWriteLine("ProDOS plugin", "entries_per_block = {0}", entries_per_block); DicConsole.DebugWriteLine("ProDOS plugin", "entries_per_block = {0}", entriesPerBlock);
if(entries_per_block != ProDOSEntriesPerBlock) return false; if(entriesPerBlock != ENTRIES_PER_BLOCK) return false;
ushort bit_map_pointer = BitConverter.ToUInt16(rootDirectoryKeyBlock, 0x27); ushort bitMapPointer = BitConverter.ToUInt16(rootDirectoryKeyBlock, 0x27);
DicConsole.DebugWriteLine("ProDOS plugin", "bit_map_pointer = {0}", bit_map_pointer); DicConsole.DebugWriteLine("ProDOS plugin", "bit_map_pointer = {0}", bitMapPointer);
if(bit_map_pointer > partition.End) return false; if(bitMapPointer > partition.End) return false;
ushort total_blocks = BitConverter.ToUInt16(rootDirectoryKeyBlock, 0x29); ushort totalBlocks = BitConverter.ToUInt16(rootDirectoryKeyBlock, 0x29);
if(APMFromHDDOnCD) total_blocks /= 4; if(APMFromHDDOnCD) totalBlocks /= 4;
DicConsole.DebugWriteLine("ProDOS plugin", "{0} <= ({1} - {2} + 1)? {3}", total_blocks, partition.End, DicConsole.DebugWriteLine("ProDOS plugin", "{0} <= ({1} - {2} + 1)? {3}", totalBlocks, partition.End,
partition.Start, total_blocks <= partition.End - partition.Start + 1); partition.Start, totalBlocks <= partition.End - partition.Start + 1);
return total_blocks <= partition.End - partition.Start + 1; return totalBlocks <= partition.End - partition.Start + 1;
} }
public override void GetInformation(ImagePlugin imagePlugin, Partition partition, public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
@@ -173,50 +173,45 @@ namespace DiscImageChef.Filesystems
byte[] tmp = imagePlugin.ReadSectors(partition.Start, 2); 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 && 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 && (byte)((tmp[offset + 0x04] & STORAGE_TYPE_MASK) >> 4) == ROOT_DIRECTORY_TYPE &&
tmp[offset + 0x23] == ProDOSEntryLength && tmp[offset + 0x24] == ProDOSEntriesPerBlock)) { tmp[offset + 0x23] == ENTRY_LENGTH && tmp[offset + 0x24] == ENTRIES_PER_BLOCK)) {
Array.Copy(tmp, offset, rootDirectoryKeyBlockBytes, 0, 0x200); Array.Copy(tmp, offset, rootDirectoryKeyBlockBytes, 0, 0x200);
APMFromHDDOnCD = true; APMFromHDDOnCD = true;
break; break;
} }
} }
ProDOSRootDirectoryKeyBlock rootDirectoryKeyBlock = new ProDOSRootDirectoryKeyBlock(); ProDOSRootDirectoryKeyBlock rootDirectoryKeyBlock =
rootDirectoryKeyBlock.header = new ProDOSRootDirectoryHeader(); new ProDOSRootDirectoryKeyBlock {header = new ProDOSRootDirectoryHeader()};
byte[] temporal;
int year, month, day, hour, minute;
ushort temp_timestamp_left, temp_timestamp_right;
uint temp_timestamp;
rootDirectoryKeyBlock.zero = BitConverter.ToUInt16(rootDirectoryKeyBlockBytes, 0x00); rootDirectoryKeyBlock.zero = BitConverter.ToUInt16(rootDirectoryKeyBlockBytes, 0x00);
rootDirectoryKeyBlock.next_pointer = BitConverter.ToUInt16(rootDirectoryKeyBlockBytes, 0x02); rootDirectoryKeyBlock.next_pointer = BitConverter.ToUInt16(rootDirectoryKeyBlockBytes, 0x02);
rootDirectoryKeyBlock.header.storage_type = rootDirectoryKeyBlock.header.storage_type =
(byte)((rootDirectoryKeyBlockBytes[0x04] & ProDOSStorageTypeMask) >> 4); (byte)((rootDirectoryKeyBlockBytes[0x04] & STORAGE_TYPE_MASK) >> 4);
rootDirectoryKeyBlock.header.name_length = (byte)(rootDirectoryKeyBlockBytes[0x04] & ProDOSNameLengthMask); rootDirectoryKeyBlock.header.name_length = (byte)(rootDirectoryKeyBlockBytes[0x04] & NAME_LENGTH_MASK);
temporal = new byte[rootDirectoryKeyBlock.header.name_length]; byte[] temporal = new byte[rootDirectoryKeyBlock.header.name_length];
Array.Copy(rootDirectoryKeyBlockBytes, 0x05, temporal, 0, rootDirectoryKeyBlock.header.name_length); Array.Copy(rootDirectoryKeyBlockBytes, 0x05, temporal, 0, rootDirectoryKeyBlock.header.name_length);
rootDirectoryKeyBlock.header.volume_name = CurrentEncoding.GetString(temporal); rootDirectoryKeyBlock.header.volume_name = CurrentEncoding.GetString(temporal);
rootDirectoryKeyBlock.header.reserved = BitConverter.ToUInt64(rootDirectoryKeyBlockBytes, 0x14); rootDirectoryKeyBlock.header.reserved = BitConverter.ToUInt64(rootDirectoryKeyBlockBytes, 0x14);
temp_timestamp_left = BitConverter.ToUInt16(rootDirectoryKeyBlockBytes, 0x1C); ushort tempTimestampLeft = BitConverter.ToUInt16(rootDirectoryKeyBlockBytes, 0x1C);
temp_timestamp_right = BitConverter.ToUInt16(rootDirectoryKeyBlockBytes, 0x1E); ushort tempTimestampRight = BitConverter.ToUInt16(rootDirectoryKeyBlockBytes, 0x1E);
bool dateCorrect; bool dateCorrect;
try try
{ {
temp_timestamp = (uint)((temp_timestamp_left << 16) + temp_timestamp_right); uint tempTimestamp = (uint)((tempTimestampLeft << 16) + tempTimestampRight);
year = (int)((temp_timestamp & ProDOSYearMask) >> 25); int year = (int)((tempTimestamp & YEAR_MASK) >> 25);
month = (int)((temp_timestamp & ProDOSMonthMask) >> 21); int month = (int)((tempTimestamp & MONTH_MASK) >> 21);
day = (int)((temp_timestamp & ProDOSDayMask) >> 16); int day = (int)((tempTimestamp & DAY_MASK) >> 16);
hour = (int)((temp_timestamp & ProDOSHourMask) >> 8); int hour = (int)((tempTimestamp & HOUR_MASK) >> 8);
minute = (int)(temp_timestamp & ProDOSMinuteMask); int minute = (int)(tempTimestamp & MINUTE_MASK);
year += 1900; year += 1900;
if(year < 1940) year += 100; if(year < 1940) year += 100;
DicConsole.DebugWriteLine("ProDOS plugin", "temp_timestamp_left = 0x{0:X4}", temp_timestamp_left); DicConsole.DebugWriteLine("ProDOS plugin", "temp_timestamp_left = 0x{0:X4}", tempTimestampLeft);
DicConsole.DebugWriteLine("ProDOS plugin", "temp_timestamp_right = 0x{0:X4}", temp_timestamp_right); DicConsole.DebugWriteLine("ProDOS plugin", "temp_timestamp_right = 0x{0:X4}", tempTimestampRight);
DicConsole.DebugWriteLine("ProDOS plugin", "temp_timestamp = 0x{0:X8}", temp_timestamp); DicConsole.DebugWriteLine("ProDOS plugin", "temp_timestamp = 0x{0:X8}", tempTimestamp);
DicConsole.DebugWriteLine("ProDOS plugin", DicConsole.DebugWriteLine("ProDOS plugin",
"Datetime field year {0}, month {1}, day {2}, hour {3}, minute {4}.", year, "Datetime field year {0}, month {1}, day {2}, hour {3}, minute {4}.", year,
month, day, hour, minute); month, day, hour, minute);
@@ -240,20 +235,20 @@ namespace DiscImageChef.Filesystems
sbInformation.AppendLine("ProDOS uses 512 bytes/sector while devices uses 2048 bytes/sector.") sbInformation.AppendLine("ProDOS uses 512 bytes/sector while devices uses 2048 bytes/sector.")
.AppendLine(); .AppendLine();
if(rootDirectoryKeyBlock.header.version != ProDOSVersion1 || if(rootDirectoryKeyBlock.header.version != VERSION1 ||
rootDirectoryKeyBlock.header.min_version != ProDOSVersion1) rootDirectoryKeyBlock.header.min_version != VERSION1)
{ {
sbInformation.AppendLine("Warning! Detected unknown ProDOS version ProDOS filesystem."); sbInformation.AppendLine("Warning! Detected unknown ProDOS version ProDOS filesystem.");
sbInformation.AppendLine("All of the following information may be incorrect"); 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."); sbInformation.AppendLine("ProDOS version 1 used to create this volume.");
else else
sbInformation.AppendFormat("Unknown ProDOS version with field {0} used to create this volume.", sbInformation.AppendFormat("Unknown ProDOS version with field {0} used to create this volume.",
rootDirectoryKeyBlock.header.version).AppendLine(); 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."); sbInformation.AppendLine("ProDOS version 1 at least required for reading this volume.");
else else
sbInformation sbInformation
@@ -275,36 +270,36 @@ namespace DiscImageChef.Filesystems
sbInformation.AppendFormat("Bitmap starts at block {0}", rootDirectoryKeyBlock.header.bit_map_pointer) sbInformation.AppendFormat("Bitmap starts at block {0}", rootDirectoryKeyBlock.header.bit_map_pointer)
.AppendLine(); .AppendLine();
if((rootDirectoryKeyBlock.header.access & ProDOSReadAttribute) == ProDOSReadAttribute) if((rootDirectoryKeyBlock.header.access & READ_ATTRIBUTE) == READ_ATTRIBUTE)
sbInformation.AppendLine("Volume can be read"); 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"); 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"); 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"); 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"); 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}", DicConsole.DebugWriteLine("ProDOS plugin", "Reserved attributes are set: {0:X2}",
rootDirectoryKeyBlock.header.access); rootDirectoryKeyBlock.header.access);
information = sbInformation.ToString(); information = sbInformation.ToString();
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType();
xmlFSType.VolumeName = rootDirectoryKeyBlock.header.volume_name; XmlFsType.VolumeName = rootDirectoryKeyBlock.header.volume_name;
if(dateCorrect) if(dateCorrect)
{ {
xmlFSType.CreationDate = rootDirectoryKeyBlock.header.creation_time; XmlFsType.CreationDate = rootDirectoryKeyBlock.header.creation_time;
xmlFSType.CreationDateSpecified = true; XmlFsType.CreationDateSpecified = true;
} }
xmlFSType.Files = rootDirectoryKeyBlock.header.file_count; XmlFsType.Files = rootDirectoryKeyBlock.header.file_count;
xmlFSType.FilesSpecified = true; XmlFsType.FilesSpecified = true;
xmlFSType.Clusters = rootDirectoryKeyBlock.header.total_blocks; XmlFsType.Clusters = rootDirectoryKeyBlock.header.total_blocks;
xmlFSType.ClusterSize = (int)((partition.End - partition.Start + 1) * imagePlugin.ImageInfo.SectorSize / XmlFsType.ClusterSize = (int)((partition.End - partition.Start + 1) * imagePlugin.ImageInfo.SectorSize /
(ulong)xmlFSType.Clusters); (ulong)XmlFsType.Clusters);
xmlFSType.Type = "ProDOS"; XmlFsType.Type = "ProDOS";
} }
public override Errno Mount() public override Errno Mount()

View File

@@ -108,24 +108,22 @@ namespace DiscImageChef.Filesystems
public QNX4() public QNX4()
{ {
Name = "QNX4 Plugin"; 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"); CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
} }
public QNX4(Encoding encoding) public QNX4(Encoding encoding)
{ {
Name = "QNX4 Plugin"; Name = "QNX4 Plugin";
PluginUUID = new Guid("E73A63FA-B5B0-48BF-BF82-DA5F0A8170D2"); PluginUuid = new Guid("E73A63FA-B5B0-48BF-BF82-DA5F0A8170D2");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public QNX4(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public QNX4(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "QNX4 Plugin"; Name = "QNX4 Plugin";
PluginUUID = new Guid("E73A63FA-B5B0-48BF-BF82-DA5F0A8170D2"); PluginUuid = new Guid("E73A63FA-B5B0-48BF-BF82-DA5F0A8170D2");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public override bool Identify(ImagePlugin imagePlugin, Partition partition) public override bool Identify(ImagePlugin imagePlugin, Partition partition)
@@ -135,10 +133,9 @@ namespace DiscImageChef.Filesystems
byte[] sector = imagePlugin.ReadSector(partition.Start + 1); byte[] sector = imagePlugin.ReadSector(partition.Start + 1);
if(sector.Length < 512) return false; if(sector.Length < 512) return false;
QNX4_Superblock qnxSb;
IntPtr sbPtr = Marshal.AllocHGlobal(512); IntPtr sbPtr = Marshal.AllocHGlobal(512);
Marshal.Copy(sector, 0, sbPtr, 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); Marshal.FreeHGlobal(sbPtr);
// Check root directory name // Check root directory name
@@ -169,10 +166,9 @@ namespace DiscImageChef.Filesystems
byte[] sector = imagePlugin.ReadSector(partition.Start + 1); byte[] sector = imagePlugin.ReadSector(partition.Start + 1);
if(sector.Length < 512) return; if(sector.Length < 512) return;
QNX4_Superblock qnxSb;
IntPtr sbPtr = Marshal.AllocHGlobal(512); IntPtr sbPtr = Marshal.AllocHGlobal(512);
Marshal.Copy(sector, 0, sbPtr, 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); Marshal.FreeHGlobal(sbPtr);
// Too much useless information // Too much useless information
@@ -253,7 +249,7 @@ namespace DiscImageChef.Filesystems
information = information =
$"QNX4 filesystem\nCreated on {DateHandlers.UNIXUnsignedToDateTime(qnxSb.rootDir.di_ftime)}\n"; $"QNX4 filesystem\nCreated on {DateHandlers.UNIXUnsignedToDateTime(qnxSb.rootDir.di_ftime)}\n";
xmlFSType = new FileSystemType XmlFsType = new FileSystemType
{ {
Type = "QNX4 filesystem", Type = "QNX4 filesystem",
Clusters = (long)partition.Length, Clusters = (long)partition.Length,
@@ -263,7 +259,7 @@ namespace DiscImageChef.Filesystems
ModificationDate = DateHandlers.UNIXUnsignedToDateTime(qnxSb.rootDir.di_mtime), ModificationDate = DateHandlers.UNIXUnsignedToDateTime(qnxSb.rootDir.di_mtime),
ModificationDateSpecified = true 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() public override Errno Mount()

View File

@@ -96,43 +96,41 @@ namespace DiscImageChef.Filesystems
public QNX6_RootNode unknown; public QNX6_RootNode unknown;
} }
const uint QNX6_SuperBlockSize = 0x1000; const uint QNX6_SUPER_BLOCK_SIZE = 0x1000;
const uint QNX6_BootBlocksSize = 0x2000; const uint QNX6_BOOT_BLOCKS_SIZE = 0x2000;
const uint QNX6_Magic = 0x68191122; const uint QNX6_MAGIC = 0x68191122;
public QNX6() public QNX6()
{ {
Name = "QNX6 Plugin"; 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"); CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
} }
public QNX6(Encoding encoding) public QNX6(Encoding encoding)
{ {
Name = "QNX6 Plugin"; Name = "QNX6 Plugin";
PluginUUID = new Guid("3E610EA2-4D08-4D70-8947-830CD4C74FC0"); PluginUuid = new Guid("3E610EA2-4D08-4D70-8947-830CD4C74FC0");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public QNX6(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public QNX6(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "QNX6 Plugin"; Name = "QNX6 Plugin";
PluginUUID = new Guid("3E610EA2-4D08-4D70-8947-830CD4C74FC0"); PluginUuid = new Guid("3E610EA2-4D08-4D70-8947-830CD4C74FC0");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public override bool Identify(ImagePlugin imagePlugin, Partition partition) public override bool Identify(ImagePlugin imagePlugin, Partition partition)
{ {
uint sectors = QNX6_SuperBlockSize / imagePlugin.GetSectorSize(); uint sectors = QNX6_SUPER_BLOCK_SIZE / imagePlugin.GetSectorSize();
uint bootSectors = QNX6_BootBlocksSize / imagePlugin.GetSectorSize(); uint bootSectors = QNX6_BOOT_BLOCKS_SIZE / imagePlugin.GetSectorSize();
if(partition.Start + bootSectors + sectors >= partition.End) return false; if(partition.Start + bootSectors + sectors >= partition.End) return false;
byte[] audiSector = imagePlugin.ReadSectors(partition.Start, sectors); byte[] audiSector = imagePlugin.ReadSectors(partition.Start, sectors);
byte[] sector = imagePlugin.ReadSectors(partition.Start + bootSectors, 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(); QNX6_AudiSuperBlock audiSb = new QNX6_AudiSuperBlock();
IntPtr audiPtr = Marshal.AllocHGlobal(Marshal.SizeOf(audiSb)); IntPtr audiPtr = Marshal.AllocHGlobal(Marshal.SizeOf(audiSb));
@@ -146,7 +144,7 @@ namespace DiscImageChef.Filesystems
qnxSb = (QNX6_SuperBlock)Marshal.PtrToStructure(sbPtr, typeof(QNX6_SuperBlock)); qnxSb = (QNX6_SuperBlock)Marshal.PtrToStructure(sbPtr, typeof(QNX6_SuperBlock));
Marshal.FreeHGlobal(sbPtr); 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, public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
@@ -154,12 +152,12 @@ namespace DiscImageChef.Filesystems
{ {
information = ""; information = "";
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
uint sectors = QNX6_SuperBlockSize / imagePlugin.GetSectorSize(); uint sectors = QNX6_SUPER_BLOCK_SIZE / imagePlugin.GetSectorSize();
uint bootSectors = QNX6_BootBlocksSize / imagePlugin.GetSectorSize(); uint bootSectors = QNX6_BOOT_BLOCKS_SIZE / imagePlugin.GetSectorSize();
byte[] audiSector = imagePlugin.ReadSectors(partition.Start, sectors); byte[] audiSector = imagePlugin.ReadSectors(partition.Start, sectors);
byte[] sector = imagePlugin.ReadSectors(partition.Start + bootSectors, 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(); QNX6_AudiSuperBlock audiSb = new QNX6_AudiSuperBlock();
IntPtr audiPtr = Marshal.AllocHGlobal(Marshal.SizeOf(audiSb)); IntPtr audiPtr = Marshal.AllocHGlobal(Marshal.SizeOf(audiSb));
@@ -173,7 +171,7 @@ namespace DiscImageChef.Filesystems
qnxSb = (QNX6_SuperBlock)Marshal.PtrToStructure(sbPtr, typeof(QNX6_SuperBlock)); qnxSb = (QNX6_SuperBlock)Marshal.PtrToStructure(sbPtr, typeof(QNX6_SuperBlock));
Marshal.FreeHGlobal(sbPtr); Marshal.FreeHGlobal(sbPtr);
bool audi = false || audiSb.magic == QNX6_Magic; bool audi = audiSb.magic == QNX6_MAGIC;
if(audi) if(audi)
{ {
@@ -186,17 +184,19 @@ namespace DiscImageChef.Filesystems
audiSb.freeBlocks * audiSb.blockSize, audiSb.numBlocks, audiSb.freeBlocks * audiSb.blockSize, audiSb.numBlocks,
audiSb.numBlocks * audiSb.blockSize).AppendLine(); audiSb.numBlocks * audiSb.blockSize).AppendLine();
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType
xmlFSType.Type = "QNX6 (Audi) filesystem"; {
xmlFSType.Clusters = audiSb.numBlocks; Type = "QNX6 (Audi) filesystem",
xmlFSType.ClusterSize = (int)audiSb.blockSize; Clusters = audiSb.numBlocks,
xmlFSType.Bootable = true; ClusterSize = (int)audiSb.blockSize,
xmlFSType.Files = audiSb.numInodes - audiSb.freeInodes; Bootable = true,
xmlFSType.FilesSpecified = true; Files = audiSb.numInodes - audiSb.freeInodes,
xmlFSType.FreeClusters = audiSb.freeBlocks; FilesSpecified = true,
xmlFSType.FreeClustersSpecified = true; FreeClusters = audiSb.freeBlocks,
FreeClustersSpecified = true,
VolumeSerial = $"{audiSb.serial:X16}"
};
//xmlFSType.VolumeName = CurrentEncoding.GetString(audiSb.id); //xmlFSType.VolumeName = CurrentEncoding.GetString(audiSb.id);
xmlFSType.VolumeSerial = $"{audiSb.serial:X16}";
information = sb.ToString(); information = sb.ToString();
return; return;
@@ -217,21 +217,23 @@ namespace DiscImageChef.Filesystems
qnxSb.freeBlocks * qnxSb.blockSize, qnxSb.numBlocks, qnxSb.numBlocks * qnxSb.blockSize) qnxSb.freeBlocks * qnxSb.blockSize, qnxSb.numBlocks, qnxSb.numBlocks * qnxSb.blockSize)
.AppendLine(); .AppendLine();
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType
xmlFSType.Type = "QNX6 filesystem"; {
xmlFSType.Clusters = qnxSb.numBlocks; Type = "QNX6 filesystem",
xmlFSType.ClusterSize = (int)qnxSb.blockSize; Clusters = qnxSb.numBlocks,
xmlFSType.Bootable = true; ClusterSize = (int)qnxSb.blockSize,
xmlFSType.Files = qnxSb.numInodes - qnxSb.freeInodes; Bootable = true,
xmlFSType.FilesSpecified = true; Files = qnxSb.numInodes - qnxSb.freeInodes,
xmlFSType.FreeClusters = qnxSb.freeBlocks; FilesSpecified = true,
xmlFSType.FreeClustersSpecified = 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.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(); information = sb.ToString();
} }

View File

@@ -149,30 +149,28 @@ namespace DiscImageChef.Filesystems
} }
/// <summary>Magic number for OS-9. Same for OS-9000?</summary> /// <summary>Magic number for OS-9. Same for OS-9000?</summary>
const uint RBF_Sync = 0x4372757A; const uint RBF_SYNC = 0x4372757A;
const uint RBF_Cnys = 0x7A757243; const uint RBF_CNYS = 0x7A757243;
public RBF() public RBF()
{ {
Name = "OS-9 Random Block File Plugin"; 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"); CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
} }
public RBF(Encoding encoding) public RBF(Encoding encoding)
{ {
Name = "OS-9 Random Block File Plugin"; Name = "OS-9 Random Block File Plugin";
PluginUUID = new Guid("E864E45B-0B52-4D29-A858-7BDFA9199FB2"); PluginUuid = new Guid("E864E45B-0B52-4D29-A858-7BDFA9199FB2");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public RBF(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public RBF(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "OS-9 Random Block File Plugin"; Name = "OS-9 Random Block File Plugin";
PluginUUID = new Guid("E864E45B-0B52-4D29-A858-7BDFA9199FB2"); PluginUuid = new Guid("E864E45B-0B52-4D29-A858-7BDFA9199FB2");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public override bool Identify(ImagePlugin imagePlugin, Partition partition) 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 // I've read OS-9/Apple2 has it on sector 15
foreach(ulong location in new[] {0, 4, 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()); uint sbSize = (uint)(Marshal.SizeOf(rbfSb) / imagePlugin.GetSectorSize());
if(Marshal.SizeOf(RBFSb) % imagePlugin.GetSectorSize() != 0) sbSize++; if(Marshal.SizeOf(rbfSb) % imagePlugin.GetSectorSize() != 0) sbSize++;
if(partition.Start + location + sbSize >= imagePlugin.GetSectors()) break; if(partition.Start + location + sbSize >= imagePlugin.GetSectors()) break;
byte[] sector = imagePlugin.ReadSectors(partition.Start + location, sbSize); 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); rbfSb = BigEndianMarshal.ByteArrayToStructureBigEndian<RBF_IdSector>(sector);
RBF_NewIdSector RBF9000Sb = BigEndianMarshal.ByteArrayToStructureBigEndian<RBF_NewIdSector>(sector); RBF_NewIdSector rbf9000Sb = BigEndianMarshal.ByteArrayToStructureBigEndian<RBF_NewIdSector>(sector);
DicConsole.DebugWriteLine("RBF plugin", DicConsole.DebugWriteLine("RBF plugin",
"magic at {0} = 0x{1:X8} or 0x{2:X8} (expected 0x{3:X8} or 0x{4:X8})", "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; return true;
} }
@@ -214,134 +212,132 @@ namespace DiscImageChef.Filesystems
information = ""; information = "";
if(imagePlugin.GetSectorSize() < 256) return; if(imagePlugin.GetSectorSize() < 256) return;
RBF_IdSector RBFSb = new RBF_IdSector(); RBF_IdSector rbfSb = new RBF_IdSector();
RBF_NewIdSector RBF9000Sb = new RBF_NewIdSector(); RBF_NewIdSector rbf9000Sb = new RBF_NewIdSector();
foreach(ulong location in new[] {0, 4, 15}) foreach(ulong location in new[] {0, 4, 15})
{ {
uint sbSize = (uint)(Marshal.SizeOf(RBFSb) / imagePlugin.GetSectorSize()); uint sbSize = (uint)(Marshal.SizeOf(rbfSb) / imagePlugin.GetSectorSize());
if(Marshal.SizeOf(RBFSb) % imagePlugin.GetSectorSize() != 0) sbSize++; if(Marshal.SizeOf(rbfSb) % imagePlugin.GetSectorSize() != 0) sbSize++;
byte[] sector = imagePlugin.ReadSectors(partition.Start + location, 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); rbfSb = BigEndianMarshal.ByteArrayToStructureBigEndian<RBF_IdSector>(sector);
RBF9000Sb = BigEndianMarshal.ByteArrayToStructureBigEndian<RBF_NewIdSector>(sector); rbf9000Sb = BigEndianMarshal.ByteArrayToStructureBigEndian<RBF_NewIdSector>(sector);
DicConsole.DebugWriteLine("RBF plugin", DicConsole.DebugWriteLine("RBF plugin",
"magic at {0} = 0x{1:X8} or 0x{2:X8} (expected 0x{3:X8} or 0x{4:X8})", "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(); StringBuilder sb = new StringBuilder();
sb.AppendLine("OS-9 Random Block File"); 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("Volume ID: {0:X8}", rbf9000Sb.rid_diskid).AppendLine();
sb.AppendFormat("{0} blocks in volume", RBF9000Sb.rid_totblocks).AppendLine(); sb.AppendFormat("{0} blocks in volume", rbf9000Sb.rid_totblocks).AppendLine();
sb.AppendFormat("{0} cylinders", RBF9000Sb.rid_cylinders).AppendLine(); sb.AppendFormat("{0} cylinders", rbf9000Sb.rid_cylinders).AppendLine();
sb.AppendFormat("{0} blocks in cylinder 0", RBF9000Sb.rid_cyl0size).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} blocks per cylinder", rbf9000Sb.rid_cylsize).AppendLine();
sb.AppendFormat("{0} heads", RBF9000Sb.rid_heads).AppendLine(); sb.AppendFormat("{0} heads", rbf9000Sb.rid_heads).AppendLine();
sb.AppendFormat("{0} bytes per block", RBF9000Sb.rid_blocksize).AppendLine(); sb.AppendFormat("{0} bytes per block", rbf9000Sb.rid_blocksize).AppendLine();
// TODO: Convert to flags? // TODO: Convert to flags?
if((RBF9000Sb.rid_format & 0x01) == 0x01) sb.AppendLine("Disk is double sided"); sb.AppendLine((rbf9000Sb.rid_format & 0x01) == 0x01 ? "Disk is double sided" : "Disk is single sided");
else sb.AppendLine("Disk is single sided"); sb.AppendLine((rbf9000Sb.rid_format & 0x02) == 0x02
if((RBF9000Sb.rid_format & 0x02) == 0x02) sb.AppendLine("Disk is double density"); ? "Disk is double density"
else sb.AppendLine("Disk is single density"); : "Disk is single density");
if((RBF9000Sb.rid_format & 0x10) == 0x10) sb.AppendLine("Disk is 384 TPI"); 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 & 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 if((rbf9000Sb.rid_format & 0x04) == 0x04) sb.AppendLine("Disk is 96 TPI or 135 TPI");
else sb.AppendLine("Disk is 48 TPI"); else sb.AppendLine("Disk is 48 TPI");
sb.AppendFormat("Allocation bitmap descriptor starts at block {0}", sb.AppendFormat("Allocation bitmap descriptor starts at block {0}",
RBF9000Sb.rid_bitmap == 0 ? 1 : RBF9000Sb.rid_bitmap).AppendLine(); rbf9000Sb.rid_bitmap == 0 ? 1 : rbf9000Sb.rid_bitmap).AppendLine();
if(RBF9000Sb.rid_firstboot > 0) if(rbf9000Sb.rid_firstboot > 0)
sb.AppendFormat("Debugger descriptor starts at block {0}", RBF9000Sb.rid_firstboot).AppendLine(); sb.AppendFormat("Debugger descriptor starts at block {0}", rbf9000Sb.rid_firstboot).AppendLine();
if(RBF9000Sb.rid_bootfile > 0) if(rbf9000Sb.rid_bootfile > 0)
sb.AppendFormat("Boot file descriptor starts at block {0}", RBF9000Sb.rid_bootfile).AppendLine(); 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("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) sb.AppendFormat("Disk is owned by group {0} user {1}", rbf9000Sb.rid_group, rbf9000Sb.rid_owner)
.AppendLine(); .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(); .AppendLine();
sb.AppendFormat("Volume's identification block was last written on {0}", sb.AppendFormat("Volume's identification block was last written on {0}",
DateHandlers.UNIXToDateTime(RBF9000Sb.rid_mtime)).AppendLine(); DateHandlers.UNIXToDateTime(rbf9000Sb.rid_mtime)).AppendLine();
sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(RBF9000Sb.rid_name, CurrentEncoding)) sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(rbf9000Sb.rid_name, CurrentEncoding))
.AppendLine(); .AppendLine();
xmlFSType = new FileSystemType XmlFsType = new FileSystemType
{ {
Type = "OS-9 Random Block File", Type = "OS-9 Random Block File",
Bootable = RBF9000Sb.rid_bootfile > 0, Bootable = rbf9000Sb.rid_bootfile > 0,
ClusterSize = RBF9000Sb.rid_blocksize, ClusterSize = rbf9000Sb.rid_blocksize,
Clusters = RBF9000Sb.rid_totblocks, Clusters = rbf9000Sb.rid_totblocks,
CreationDate = DateHandlers.UNIXToDateTime(RBF9000Sb.rid_ctime), CreationDate = DateHandlers.UNIXToDateTime(rbf9000Sb.rid_ctime),
CreationDateSpecified = true, CreationDateSpecified = true,
ModificationDate = DateHandlers.UNIXToDateTime(RBF9000Sb.rid_mtime), ModificationDate = DateHandlers.UNIXToDateTime(rbf9000Sb.rid_mtime),
ModificationDateSpecified = true, ModificationDateSpecified = true,
VolumeName = StringHandlers.CToString(RBF9000Sb.rid_name, CurrentEncoding), VolumeName = StringHandlers.CToString(rbf9000Sb.rid_name, CurrentEncoding),
VolumeSerial = $"{RBF9000Sb.rid_diskid:X8}" VolumeSerial = $"{rbf9000Sb.rid_diskid:X8}"
}; };
} }
else else
{ {
sb.AppendFormat("Volume ID: {0:X4}", RBFSb.dd_dsk).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} blocks in volume", LSNToUInt32(rbfSb.dd_tot)).AppendLine();
sb.AppendFormat("{0} tracks", RBFSb.dd_tks).AppendLine(); sb.AppendFormat("{0} tracks", rbfSb.dd_tks).AppendLine();
sb.AppendFormat("{0} sectors per track", RBFSb.dd_spt).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} bytes per sector", 256 << rbfSb.dd_lsnsize).AppendLine();
sb.AppendFormat("{0} sectors per cluster ({1} bytes)", RBFSb.dd_bit, sb.AppendFormat("{0} sectors per cluster ({1} bytes)", rbfSb.dd_bit,
RBFSb.dd_bit * (256 << RBFSb.dd_lsnsize)).AppendLine(); rbfSb.dd_bit * (256 << rbfSb.dd_lsnsize)).AppendLine();
// TODO: Convert to flags? // TODO: Convert to flags?
if((RBFSb.dd_fmt & 0x01) == 0x01) sb.AppendLine("Disk is double sided"); sb.AppendLine((rbfSb.dd_fmt & 0x01) == 0x01 ? "Disk is double sided" : "Disk is single sided");
else sb.AppendLine("Disk is single sided"); sb.AppendLine((rbfSb.dd_fmt & 0x02) == 0x02 ? "Disk is double density" : "Disk is single density");
if((RBFSb.dd_fmt & 0x02) == 0x02) sb.AppendLine("Disk is double density"); if((rbfSb.dd_fmt & 0x10) == 0x10) sb.AppendLine("Disk is 384 TPI");
else sb.AppendLine("Disk is single density"); else if((rbfSb.dd_fmt & 0x08) == 0x08) sb.AppendLine("Disk is 192 TPI");
if((RBFSb.dd_fmt & 0x10) == 0x10) sb.AppendLine("Disk is 384 TPI"); else if((rbfSb.dd_fmt & 0x04) == 0x04) sb.AppendLine("Disk is 96 TPI or 135 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"); else sb.AppendLine("Disk is 48 TPI");
sb.AppendFormat("Allocation bitmap descriptor starts at block {0}", sb.AppendFormat("Allocation bitmap descriptor starts at block {0}",
RBFSb.dd_maplsn == 0 ? 1 : RBFSb.dd_maplsn).AppendLine(); rbfSb.dd_maplsn == 0 ? 1 : rbfSb.dd_maplsn).AppendLine();
sb.AppendFormat("{0} bytes in allocation bitmap", RBFSb.dd_map).AppendLine(); sb.AppendFormat("{0} bytes in allocation bitmap", rbfSb.dd_map).AppendLine();
if(LSNToUInt32(RBFSb.dd_bt) > 0 && RBFSb.dd_bsz > 0) 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), sb.AppendFormat("Boot file starts at block {0} and has {1} bytes", LSNToUInt32(rbfSb.dd_bt),
RBFSb.dd_bsz).AppendLine(); rbfSb.dd_bsz).AppendLine();
sb.AppendFormat("Root directory descriptor starts at block {0}", LSNToUInt32(RBFSb.dd_dir)) sb.AppendFormat("Root directory descriptor starts at block {0}", LSNToUInt32(rbfSb.dd_dir))
.AppendLine(); .AppendLine();
sb.AppendFormat("Disk is owned by user {0}", RBFSb.dd_own).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 was created on {0}", DateHandlers.OS9ToDateTime(rbfSb.dd_dat)).AppendLine();
sb.AppendFormat("Volume attributes: {0:X2}", RBFSb.dd_att).AppendLine(); sb.AppendFormat("Volume attributes: {0:X2}", rbfSb.dd_att).AppendLine();
sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(RBFSb.dd_nam, CurrentEncoding)) sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(rbfSb.dd_nam, CurrentEncoding))
.AppendLine(); .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(); .AppendLine();
xmlFSType = new FileSystemType XmlFsType = new FileSystemType
{ {
Type = "OS-9 Random Block File", Type = "OS-9 Random Block File",
Bootable = LSNToUInt32(RBFSb.dd_bt) > 0 && RBFSb.dd_bsz > 0, Bootable = LSNToUInt32(rbfSb.dd_bt) > 0 && rbfSb.dd_bsz > 0,
ClusterSize = RBFSb.dd_bit * (256 << RBFSb.dd_lsnsize), ClusterSize = rbfSb.dd_bit * (256 << rbfSb.dd_lsnsize),
Clusters = LSNToUInt32(RBFSb.dd_tot), Clusters = LSNToUInt32(rbfSb.dd_tot),
CreationDate = DateHandlers.OS9ToDateTime(RBFSb.dd_dat), CreationDate = DateHandlers.OS9ToDateTime(rbfSb.dd_dat),
CreationDateSpecified = true, CreationDateSpecified = true,
VolumeName = StringHandlers.CToString(RBFSb.dd_nam, CurrentEncoding), VolumeName = StringHandlers.CToString(rbfSb.dd_nam, CurrentEncoding),
VolumeSerial = $"{RBFSb.dd_dsk:X4}" VolumeSerial = $"{rbfSb.dd_dsk:X4}"
}; };
} }
information = sb.ToString(); information = sb.ToString();
} }
public static uint LSNToUInt32(byte[] lsn) static uint LSNToUInt32(byte[] lsn)
{ {
if(lsn == null || lsn.Length != 3) return 0; if(lsn == null || lsn.Length != 3) return 0;

View File

@@ -47,24 +47,22 @@ namespace DiscImageChef.Filesystems
public RT11() public RT11()
{ {
Name = "RT-11 file system"; 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"); CurrentEncoding = Encoding.GetEncoding("iso-8859-1");
} }
public RT11(Encoding encoding) public RT11(Encoding encoding)
{ {
Name = "RT-11 file system"; Name = "RT-11 file system";
PluginUUID = new Guid("DB3E2F98-8F98-463C-8126-E937843DA024"); PluginUuid = new Guid("DB3E2F98-8F98-463C-8126-E937843DA024");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-1"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1");
else CurrentEncoding = encoding;
} }
public RT11(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public RT11(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "RT-11 file system"; Name = "RT-11 file system";
PluginUUID = new Guid("DB3E2F98-8F98-463C-8126-E937843DA024"); PluginUuid = new Guid("DB3E2F98-8F98-463C-8126-E937843DA024");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-1"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1");
else CurrentEncoding = encoding;
} }
public override bool Identify(ImagePlugin imagePlugin, Partition partition) public override bool Identify(ImagePlugin imagePlugin, Partition partition)
@@ -73,12 +71,11 @@ namespace DiscImageChef.Filesystems
if(imagePlugin.GetSectorSize() < 512) return false; if(imagePlugin.GetSectorSize() < 512) return false;
byte[] magic_b = new byte[12]; byte[] magicB = new byte[12];
string magic; byte[] hbSector = imagePlugin.ReadSector(1 + partition.Start);
byte[] hb_sector = imagePlugin.ReadSector(1 + partition.Start);
Array.Copy(hb_sector, 0x1F0, magic_b, 0, 12); Array.Copy(hbSector, 0x1F0, magicB, 0, 12);
magic = Encoding.ASCII.GetString(magic_b); string magic = Encoding.ASCII.GetString(magicB);
return magic == "DECRT11A "; return magic == "DECRT11A ";
} }
@@ -89,12 +86,11 @@ namespace DiscImageChef.Filesystems
information = ""; information = "";
StringBuilder sb = new StringBuilder(); 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); GCHandle handle = GCHandle.Alloc(hbSector, GCHandleType.Pinned);
homeblock = (RT11HomeBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(RT11HomeBlock)); RT11HomeBlock homeblock = (RT11HomeBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(RT11HomeBlock));
handle.Free(); handle.Free();
/* TODO: Is this correct? /* TODO: Is this correct?
@@ -107,7 +103,7 @@ namespace DiscImageChef.Filesystems
* MOV 1,@R0 * MOV 1,@R0
*/ */
ushort check = 0; 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}", sb.AppendFormat("Volume format is {0}",
StringHandlers.SpacePaddedToString(homeblock.format, CurrentEncoding)).AppendLine(); StringHandlers.SpacePaddedToString(homeblock.format, CurrentEncoding)).AppendLine();
@@ -122,7 +118,7 @@ namespace DiscImageChef.Filesystems
byte[] bootBlock = imagePlugin.ReadSector(0); byte[] bootBlock = imagePlugin.ReadSector(0);
xmlFSType = new FileSystemType XmlFsType = new FileSystemType
{ {
Type = "RT-11", Type = "RT-11",
ClusterSize = homeblock.cluster * 512, ClusterSize = homeblock.cluster * 512,

View File

@@ -88,36 +88,34 @@ namespace DiscImageChef.Filesystems
readonly byte[] Reiser35_Magic = {0x52, 0x65, 0x49, 0x73, 0x45, 0x72, 0x46, 0x73, 0x00, 0x00}; 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[] 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}; 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() public Reiser()
{ {
Name = "Reiser Filesystem Plugin"; 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"); CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
} }
public Reiser(Encoding encoding) public Reiser(Encoding encoding)
{ {
Name = "Reiser Filesystem Plugin"; Name = "Reiser Filesystem Plugin";
PluginUUID = new Guid("1D8CD8B8-27E6-410F-9973-D16409225FBA"); PluginUuid = new Guid("1D8CD8B8-27E6-410F-9973-D16409225FBA");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public Reiser(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public Reiser(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "Reiser Filesystem Plugin"; Name = "Reiser Filesystem Plugin";
PluginUUID = new Guid("1D8CD8B8-27E6-410F-9973-D16409225FBA"); PluginUuid = new Guid("1D8CD8B8-27E6-410F-9973-D16409225FBA");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public override bool Identify(ImagePlugin imagePlugin, Partition partition) public override bool Identify(ImagePlugin imagePlugin, Partition partition)
{ {
if(imagePlugin.GetSectorSize() < 512) return false; if(imagePlugin.GetSectorSize() < 512) return false;
uint sbAddr = Reiser_SuperOffset / imagePlugin.GetSectorSize(); uint sbAddr = REISER_SUPER_OFFSET / imagePlugin.GetSectorSize();
if(sbAddr == 0) sbAddr = 1; if(sbAddr == 0) sbAddr = 1;
Reiser_Superblock reiserSb = new Reiser_Superblock(); Reiser_Superblock reiserSb = new Reiser_Superblock();
@@ -145,7 +143,7 @@ namespace DiscImageChef.Filesystems
information = ""; information = "";
if(imagePlugin.GetSectorSize() < 512) return; if(imagePlugin.GetSectorSize() < 512) return;
uint sbAddr = Reiser_SuperOffset / imagePlugin.GetSectorSize(); uint sbAddr = REISER_SUPER_OFFSET / imagePlugin.GetSectorSize();
if(sbAddr == 0) sbAddr = 1; if(sbAddr == 0) sbAddr = 1;
Reiser_Superblock reiserSb = new Reiser_Superblock(); Reiser_Superblock reiserSb = new Reiser_Superblock();
@@ -184,19 +182,19 @@ namespace DiscImageChef.Filesystems
information = sb.ToString(); information = sb.ToString();
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType();
if(Reiser35_Magic.SequenceEqual(reiserSb.magic)) xmlFSType.Type = "Reiser 3.5 filesystem"; 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(Reiser36_Magic.SequenceEqual(reiserSb.magic)) XmlFsType.Type = "Reiser 3.6 filesystem";
else if(ReiserJr_Magic.SequenceEqual(reiserSb.magic)) xmlFSType.Type = "Reiser Jr. filesystem"; else if(ReiserJr_Magic.SequenceEqual(reiserSb.magic)) XmlFsType.Type = "Reiser Jr. filesystem";
xmlFSType.ClusterSize = reiserSb.blocksize; XmlFsType.ClusterSize = reiserSb.blocksize;
xmlFSType.Clusters = reiserSb.block_count; XmlFsType.Clusters = reiserSb.block_count;
xmlFSType.FreeClusters = reiserSb.free_blocks; XmlFsType.FreeClusters = reiserSb.free_blocks;
xmlFSType.FreeClustersSpecified = true; XmlFsType.FreeClustersSpecified = true;
xmlFSType.Dirty = reiserSb.umount_state == 2; XmlFsType.Dirty = reiserSb.umount_state == 2;
if(reiserSb.version < 2) return; if(reiserSb.version < 2) return;
xmlFSType.VolumeName = CurrentEncoding.GetString(reiserSb.label); XmlFsType.VolumeName = CurrentEncoding.GetString(reiserSb.label);
xmlFSType.VolumeSerial = reiserSb.uuid.ToString(); XmlFsType.VolumeSerial = reiserSb.uuid.ToString();
} }
public override Errno Mount() public override Errno Mount()

View File

@@ -55,36 +55,34 @@ namespace DiscImageChef.Filesystems
readonly byte[] Reiser4_Magic = readonly byte[] Reiser4_Magic =
{0x52, 0x65, 0x49, 0x73, 0x45, 0x72, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; {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() public Reiser4()
{ {
Name = "Reiser4 Filesystem Plugin"; 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"); CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
} }
public Reiser4(Encoding encoding) public Reiser4(Encoding encoding)
{ {
Name = "Reiser4 Filesystem Plugin"; Name = "Reiser4 Filesystem Plugin";
PluginUUID = new Guid("301F2D00-E8D5-4F04-934E-81DFB21D15BA"); PluginUuid = new Guid("301F2D00-E8D5-4F04-934E-81DFB21D15BA");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public Reiser4(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public Reiser4(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "Reiser4 Filesystem Plugin"; Name = "Reiser4 Filesystem Plugin";
PluginUUID = new Guid("301F2D00-E8D5-4F04-934E-81DFB21D15BA"); PluginUuid = new Guid("301F2D00-E8D5-4F04-934E-81DFB21D15BA");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public override bool Identify(ImagePlugin imagePlugin, Partition partition) public override bool Identify(ImagePlugin imagePlugin, Partition partition)
{ {
if(imagePlugin.GetSectorSize() < 512) return false; if(imagePlugin.GetSectorSize() < 512) return false;
uint sbAddr = Reiser4_SuperOffset / imagePlugin.GetSectorSize(); uint sbAddr = REISER4_SUPER_OFFSET / imagePlugin.GetSectorSize();
if(sbAddr == 0) sbAddr = 1; if(sbAddr == 0) sbAddr = 1;
Reiser4_Superblock reiserSb = new Reiser4_Superblock(); Reiser4_Superblock reiserSb = new Reiser4_Superblock();
@@ -111,7 +109,7 @@ namespace DiscImageChef.Filesystems
information = ""; information = "";
if(imagePlugin.GetSectorSize() < 512) return; if(imagePlugin.GetSectorSize() < 512) return;
uint sbAddr = Reiser4_SuperOffset / imagePlugin.GetSectorSize(); uint sbAddr = REISER4_SUPER_OFFSET / imagePlugin.GetSectorSize();
if(sbAddr == 0) sbAddr = 1; if(sbAddr == 0) sbAddr = 1;
Reiser4_Superblock reiserSb = new Reiser4_Superblock(); Reiser4_Superblock reiserSb = new Reiser4_Superblock();
@@ -139,13 +137,14 @@ namespace DiscImageChef.Filesystems
information = sb.ToString(); information = sb.ToString();
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType
xmlFSType.Type = "Reiser 4 filesystem"; {
xmlFSType.ClusterSize = reiserSb.blocksize; Type = "Reiser 4 filesystem",
xmlFSType.Clusters = ClusterSize = reiserSb.blocksize,
(long)((partition.End - partition.Start) * imagePlugin.GetSectorSize() / reiserSb.blocksize); Clusters = (long)((partition.End - partition.Start) * imagePlugin.GetSectorSize() / reiserSb.blocksize),
xmlFSType.VolumeName = StringHandlers.CToString(reiserSb.label, CurrentEncoding); VolumeName = StringHandlers.CToString(reiserSb.label, CurrentEncoding),
xmlFSType.VolumeSerial = reiserSb.uuid.ToString(); VolumeSerial = reiserSb.uuid.ToString()
};
} }
public override Errno Mount() public override Errno Mount()

View File

@@ -45,24 +45,22 @@ namespace DiscImageChef.Filesystems
public SFS() public SFS()
{ {
Name = "SmartFileSystem"; Name = "SmartFileSystem";
PluginUUID = new Guid("26550C19-3671-4A2D-BC2F-F20CEB7F48DC"); PluginUuid = new Guid("26550C19-3671-4A2D-BC2F-F20CEB7F48DC");
CurrentEncoding = Encoding.GetEncoding("iso-8859-1"); CurrentEncoding = Encoding.GetEncoding("iso-8859-1");
} }
public SFS(Encoding encoding) public SFS(Encoding encoding)
{ {
Name = "SmartFileSystem"; Name = "SmartFileSystem";
PluginUUID = new Guid("26550C19-3671-4A2D-BC2F-F20CEB7F48DC"); PluginUuid = new Guid("26550C19-3671-4A2D-BC2F-F20CEB7F48DC");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-1"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1");
else CurrentEncoding = encoding;
} }
public SFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public SFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "SmartFileSystem"; Name = "SmartFileSystem";
PluginUUID = new Guid("26550C19-3671-4A2D-BC2F-F20CEB7F48DC"); PluginUuid = new Guid("26550C19-3671-4A2D-BC2F-F20CEB7F48DC");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-1"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1");
else CurrentEncoding = encoding;
} }
[Flags] [Flags]
@@ -120,9 +118,8 @@ namespace DiscImageChef.Filesystems
public override void GetInformation(ImagePlugin imagePlugin, Partition partition, public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
out string information) out string information)
{ {
byte[] RootBlockSector = imagePlugin.ReadSector(partition.Start); byte[] rootBlockSector = imagePlugin.ReadSector(partition.Start);
RootBlock rootBlock; RootBlock rootBlock = BigEndianMarshal.ByteArrayToStructureBigEndian<RootBlock>(rootBlockSector);
rootBlock = BigEndianMarshal.ByteArrayToStructureBigEndian<RootBlock>(RootBlockSector);
StringBuilder sbInformation = new StringBuilder(); StringBuilder sbInformation = new StringBuilder();
@@ -151,7 +148,7 @@ namespace DiscImageChef.Filesystems
sbInformation.AppendLine("Volume moves deleted files to a recycled folder"); sbInformation.AppendLine("Volume moves deleted files to a recycled folder");
information = sbInformation.ToString(); information = sbInformation.ToString();
xmlFSType = new FileSystemType XmlFsType = new FileSystemType
{ {
CreationDate = DateHandlers.UNIXUnsignedToDateTime(rootBlock.datecreated).AddYears(8), CreationDate = DateHandlers.UNIXUnsignedToDateTime(rootBlock.datecreated).AddYears(8),
CreationDateSpecified = true, CreationDateSpecified = true,

View File

@@ -46,24 +46,22 @@ namespace DiscImageChef.Filesystems
public SolarFS() public SolarFS()
{ {
Name = "Solar_OS filesystem"; 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"); CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
} }
public SolarFS(Encoding encoding) public SolarFS(Encoding encoding)
{ {
Name = "Solar_OS filesystem"; Name = "Solar_OS filesystem";
PluginUUID = new Guid("EA3101C1-E777-4B4F-B5A3-8C57F50F6E65"); PluginUuid = new Guid("EA3101C1-E777-4B4F-B5A3-8C57F50F6E65");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public SolarFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public SolarFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "Solar_OS filesystem"; Name = "Solar_OS filesystem";
PluginUUID = new Guid("EA3101C1-E777-4B4F-B5A3-8C57F50F6E65"); PluginUuid = new Guid("EA3101C1-E777-4B4F-B5A3-8C57F50F6E65");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public override bool Identify(ImagePlugin imagePlugin, Partition partition) public override bool Identify(ImagePlugin imagePlugin, Partition partition)
@@ -71,19 +69,16 @@ namespace DiscImageChef.Filesystems
if(2 + partition.Start >= partition.End) return false; if(2 + partition.Start >= partition.End) return false;
byte signature; // 0x29 byte signature; // 0x29
string fs_type; // "SOL_FS "
byte[] bpb = imagePlugin.ReadSector(0 + partition.Start); byte[] bpb = imagePlugin.ReadSector(0 + partition.Start);
byte[] fs_type_b = new byte[8]; byte[] fsTypeB = new byte[8];
signature = bpb[0x25]; signature = bpb[0x25];
Array.Copy(bpb, 0x35, fs_type_b, 0, 8); Array.Copy(bpb, 0x35, fsTypeB, 0, 8);
fs_type = StringHandlers.CToString(fs_type_b); string fsType = StringHandlers.CToString(fsTypeB);
if(signature == 0x29 && fs_type == "SOL_FS ") return true; return signature == 0x29 && fsType == "SOL_FS ";
return false;
} }
public override void GetInformation(ImagePlugin imagePlugin, Partition partition, public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
@@ -92,86 +87,89 @@ namespace DiscImageChef.Filesystems
information = ""; information = "";
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
byte[] bpb_sector = imagePlugin.ReadSector(0 + partition.Start); byte[] bpbSector = imagePlugin.ReadSector(0 + partition.Start);
byte[] bpb_strings;
SolarOSParameterBlock BPB = new SolarOSParameterBlock();
bpb_strings = new byte[8]; SolarOSParameterBlock bpb = new SolarOSParameterBlock
Array.Copy(bpb_sector, 0x03, bpb_strings, 0, 8); {
BPB.OEMName = StringHandlers.CToString(bpb_strings); bps = BitConverter.ToUInt16(bpbSector, 0x0B),
BPB.bps = BitConverter.ToUInt16(bpb_sector, 0x0B); root_ent = BitConverter.ToUInt16(bpbSector, 0x10),
BPB.root_ent = BitConverter.ToUInt16(bpb_sector, 0x10); sectors = BitConverter.ToUInt16(bpbSector, 0x12),
BPB.sectors = BitConverter.ToUInt16(bpb_sector, 0x12); media = bpbSector[0x14],
BPB.media = bpb_sector[0x14]; spfat = BitConverter.ToUInt16(bpbSector, 0x15),
BPB.spfat = BitConverter.ToUInt16(bpb_sector, 0x15); sptrk = BitConverter.ToUInt16(bpbSector, 0x17),
BPB.sptrk = BitConverter.ToUInt16(bpb_sector, 0x17); heads = BitConverter.ToUInt16(bpbSector, 0x19),
BPB.heads = BitConverter.ToUInt16(bpb_sector, 0x19); signature = bpbSector[0x25]
BPB.signature = bpb_sector[0x25]; };
bpb_strings = new byte[8]; byte[] bpbStrings = new byte[8];
Array.Copy(bpb_sector, 0x2A, bpb_strings, 0, 11); Array.Copy(bpbSector, 0x03, bpbStrings, 0, 8);
BPB.vol_name = StringHandlers.CToString(bpb_strings, CurrentEncoding); bpb.OEMName = StringHandlers.CToString(bpbStrings);
bpb_strings = new byte[8]; bpbStrings = new byte[8];
Array.Copy(bpb_sector, 0x35, bpb_strings, 0, 8); Array.Copy(bpbSector, 0x2A, bpbStrings, 0, 11);
BPB.fs_type = StringHandlers.CToString(bpb_strings, CurrentEncoding); 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]; bpb.x86_jump = new byte[3];
Array.Copy(bpb_sector, 0x00, BPB.x86_jump, 0, 3); Array.Copy(bpbSector, 0x00, bpb.x86_jump, 0, 3);
BPB.unk1 = bpb_sector[0x0D]; bpb.unk1 = bpbSector[0x0D];
BPB.unk2 = BitConverter.ToUInt16(bpb_sector, 0x0E); bpb.unk2 = BitConverter.ToUInt16(bpbSector, 0x0E);
BPB.unk3 = new byte[10]; bpb.unk3 = new byte[10];
Array.Copy(bpb_sector, 0x1B, BPB.unk3, 0, 10); Array.Copy(bpbSector, 0x1B, bpb.unk3, 0, 10);
BPB.unk4 = BitConverter.ToUInt32(bpb_sector, 0x26); bpb.unk4 = BitConverter.ToUInt32(bpbSector, 0x26);
DicConsole.DebugWriteLine("SolarFS plugin", "BPB.x86_jump: 0x{0:X2}{1:X2}{2:X2}", BPB.x86_jump[0], 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]); bpb.x86_jump[1], bpb.x86_jump[2]);
DicConsole.DebugWriteLine("SolarFS plugin", "BPB.OEMName: \"{0}\"", BPB.OEMName); DicConsole.DebugWriteLine("SolarFS plugin", "BPB.OEMName: \"{0}\"", bpb.OEMName);
DicConsole.DebugWriteLine("SolarFS plugin", "BPB.bps: {0}", BPB.bps); 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.unk1: 0x{0:X2}", bpb.unk1);
DicConsole.DebugWriteLine("SolarFS plugin", "BPB.unk2: 0x{0:X4}", BPB.unk2); 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.root_ent: {0}", bpb.root_ent);
DicConsole.DebugWriteLine("SolarFS plugin", "BPB.sectors: {0}", BPB.sectors); 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.media: 0x{0:X2}", bpb.media);
DicConsole.DebugWriteLine("SolarFS plugin", "BPB.spfat: {0}", BPB.spfat); DicConsole.DebugWriteLine("SolarFS plugin", "BPB.spfat: {0}", bpb.spfat);
DicConsole.DebugWriteLine("SolarFS plugin", "BPB.sptrk: {0}", BPB.sptrk); DicConsole.DebugWriteLine("SolarFS plugin", "BPB.sptrk: {0}", bpb.sptrk);
DicConsole.DebugWriteLine("SolarFS plugin", "BPB.heads: {0}", BPB.heads); DicConsole.DebugWriteLine("SolarFS plugin", "BPB.heads: {0}", bpb.heads);
DicConsole.DebugWriteLine("SolarFS plugin", 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: 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[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]); 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.signature: 0x{0:X2}", bpb.signature);
DicConsole.DebugWriteLine("SolarFS plugin", "BPB.unk4: 0x{0:X8}", BPB.unk4); 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.vol_name: \"{0}\"", bpb.vol_name);
DicConsole.DebugWriteLine("SolarFS plugin", "BPB.fs_type: \"{0}\"", BPB.fs_type); DicConsole.DebugWriteLine("SolarFS plugin", "BPB.fs_type: \"{0}\"", bpb.fs_type);
sb.AppendLine("Solar_OS filesystem"); sb.AppendLine("Solar_OS filesystem");
sb.AppendFormat("Media descriptor: 0x{0:X2}", BPB.media).AppendLine(); sb.AppendFormat("Media descriptor: 0x{0:X2}", bpb.media).AppendLine();
sb.AppendFormat("{0} bytes per sector", BPB.bps).AppendLine(); sb.AppendFormat("{0} bytes per sector", bpb.bps).AppendLine();
if(imagePlugin.GetSectorSize() == 2336 || imagePlugin.GetSectorSize() == 2352 || if(imagePlugin.GetSectorSize() == 2336 || imagePlugin.GetSectorSize() == 2352 ||
imagePlugin.GetSectorSize() == 2448) imagePlugin.GetSectorSize() == 2448)
{ {
if(BPB.bps != imagePlugin.GetSectorSize()) if(bpb.bps != imagePlugin.GetSectorSize())
sb sb
.AppendFormat("WARNING: Filesystem describes a {0} bytes/sector, while device describes a {1} bytes/sector", .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 sb
.AppendFormat("WARNING: Filesystem describes a {0} bytes/sector, while device describes a {1} bytes/sector", .AppendFormat("WARNING: Filesystem describes a {0} bytes/sector, while device describes a {1} bytes/sector",
BPB.bps, imagePlugin.GetSectorSize()).AppendLine(); bpb.bps, imagePlugin.GetSectorSize()).AppendLine();
sb.AppendFormat("{0} sectors on volume ({1} bytes)", BPB.sectors, BPB.sectors * BPB.bps).AppendLine(); sb.AppendFormat("{0} sectors on volume ({1} bytes)", bpb.sectors, bpb.sectors * bpb.bps).AppendLine();
if(BPB.sectors > imagePlugin.GetSectors()) if(bpb.sectors > imagePlugin.GetSectors())
sb.AppendFormat("WARNING: Filesystem describes a {0} sectors volume, bigger than device ({1} sectors)", sb.AppendFormat("WARNING: Filesystem describes a {0} sectors volume, bigger than device ({1} sectors)",
BPB.sectors, imagePlugin.GetSectors()); bpb.sectors, imagePlugin.GetSectors());
sb.AppendFormat("{0} heads", BPB.heads).AppendLine(); sb.AppendFormat("{0} heads", bpb.heads).AppendLine();
sb.AppendFormat("{0} sectors per track", BPB.sptrk).AppendLine(); sb.AppendFormat("{0} sectors per track", bpb.sptrk).AppendLine();
sb.AppendFormat("Volume name: {0}", BPB.vol_name).AppendLine(); sb.AppendFormat("Volume name: {0}", bpb.vol_name).AppendLine();
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType
xmlFSType.Type = "SolarFS"; {
xmlFSType.Clusters = BPB.sectors; Type = "SolarFS",
xmlFSType.ClusterSize = BPB.bps; Clusters = bpb.sectors,
xmlFSType.VolumeName = BPB.vol_name; ClusterSize = bpb.bps,
VolumeName = bpb.vol_name
};
information = sb.ToString(); information = sb.ToString();
} }

View File

@@ -45,24 +45,22 @@ namespace DiscImageChef.Filesystems
public Squash() public Squash()
{ {
Name = "Squash filesystem"; Name = "Squash filesystem";
PluginUUID = new Guid("F8F6E46F-7A2A-48E3-9C0A-46AF4DC29E09"); PluginUuid = new Guid("F8F6E46F-7A2A-48E3-9C0A-46AF4DC29E09");
CurrentEncoding = Encoding.UTF8; CurrentEncoding = Encoding.UTF8;
} }
public Squash(Encoding encoding) public Squash(Encoding encoding)
{ {
Name = "Squash filesystem"; Name = "Squash filesystem";
PluginUUID = new Guid("F8F6E46F-7A2A-48E3-9C0A-46AF4DC29E09"); PluginUuid = new Guid("F8F6E46F-7A2A-48E3-9C0A-46AF4DC29E09");
if(encoding == null) CurrentEncoding = Encoding.UTF8; CurrentEncoding = encoding ?? Encoding.UTF8;
else CurrentEncoding = encoding;
} }
public Squash(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public Squash(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "Squash filesystem"; Name = "Squash filesystem";
PluginUUID = new Guid("F8F6E46F-7A2A-48E3-9C0A-46AF4DC29E09"); PluginUuid = new Guid("F8F6E46F-7A2A-48E3-9C0A-46AF4DC29E09");
if(encoding == null) CurrentEncoding = Encoding.UTF8; CurrentEncoding = encoding ?? Encoding.UTF8;
else CurrentEncoding = encoding;
} }
enum SquashCompression : ushort enum SquashCompression : ushort
@@ -102,8 +100,8 @@ namespace DiscImageChef.Filesystems
/// <summary> /// <summary>
/// Identifier for Squash /// Identifier for Squash
/// </summary> /// </summary>
const uint Squash_MAGIC = 0x73717368; const uint SQUASH_MAGIC = 0x73717368;
const uint Squash_CIGAM = 0x68737173; const uint SQUASH_CIGAM = 0x68737173;
public override bool Identify(ImagePlugin imagePlugin, Partition partition) public override bool Identify(ImagePlugin imagePlugin, Partition partition)
{ {
@@ -113,7 +111,7 @@ namespace DiscImageChef.Filesystems
uint magic = BitConverter.ToUInt32(sector, 0x00); 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, public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
@@ -126,13 +124,13 @@ namespace DiscImageChef.Filesystems
bool littleEndian = true; bool littleEndian = true;
switch(magic) { switch(magic) {
case Squash_MAGIC: case SQUASH_MAGIC:
IntPtr sqSbPtr = Marshal.AllocHGlobal(Marshal.SizeOf(sqSb)); IntPtr sqSbPtr = Marshal.AllocHGlobal(Marshal.SizeOf(sqSb));
Marshal.Copy(sector, 0, sqSbPtr, Marshal.SizeOf(sqSb)); Marshal.Copy(sector, 0, sqSbPtr, Marshal.SizeOf(sqSb));
sqSb = (SquashSuperBlock)Marshal.PtrToStructure(sqSbPtr, typeof(SquashSuperBlock)); sqSb = (SquashSuperBlock)Marshal.PtrToStructure(sqSbPtr, typeof(SquashSuperBlock));
Marshal.FreeHGlobal(sqSbPtr); Marshal.FreeHGlobal(sqSbPtr);
break; break;
case Squash_CIGAM: case SQUASH_CIGAM:
sqSb = BigEndianMarshal.ByteArrayToStructureBigEndian<SquashSuperBlock>(sector); sqSb = BigEndianMarshal.ByteArrayToStructureBigEndian<SquashSuperBlock>(sector);
littleEndian = false; littleEndian = false;
break; break;
@@ -141,8 +139,7 @@ namespace DiscImageChef.Filesystems
StringBuilder sbInformation = new StringBuilder(); StringBuilder sbInformation = new StringBuilder();
sbInformation.AppendLine("Squash file system"); sbInformation.AppendLine("Squash file system");
if(littleEndian) sbInformation.AppendLine("Little-endian"); sbInformation.AppendLine(littleEndian ? "Little-endian" : "Big-endian");
else sbInformation.AppendLine("Big-endian");
sbInformation.AppendFormat("Volume version {0}.{1}", sqSb.s_major, sqSb.s_minor).AppendLine(); 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", sqSb.bytes_used).AppendLine();
sbInformation.AppendFormat("Volume has {0} bytes per block", sqSb.block_size).AppendLine(); sbInformation.AppendFormat("Volume has {0} bytes per block", sqSb.block_size).AppendLine();
@@ -177,17 +174,19 @@ namespace DiscImageChef.Filesystems
information = sbInformation.ToString(); information = sbInformation.ToString();
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType
xmlFSType.Type = "Squash file system"; {
xmlFSType.CreationDate = DateHandlers.UNIXUnsignedToDateTime(sqSb.mkfs_time); Type = "Squash file system",
xmlFSType.CreationDateSpecified = true; CreationDate = DateHandlers.UNIXUnsignedToDateTime(sqSb.mkfs_time),
xmlFSType.Clusters = (long)((partition.End - partition.Start + 1) * imagePlugin.ImageInfo.SectorSize / CreationDateSpecified = true,
sqSb.block_size); Clusters =
xmlFSType.ClusterSize = (int)sqSb.block_size; (long)((partition.End - partition.Start + 1) * imagePlugin.ImageInfo.SectorSize / sqSb.block_size),
xmlFSType.Files = sqSb.inodes; ClusterSize = (int)sqSb.block_size,
xmlFSType.FilesSpecified = true; Files = sqSb.inodes,
xmlFSType.FreeClusters = 0; FilesSpecified = true,
xmlFSType.FreeClustersSpecified = true; FreeClusters = 0,
FreeClustersSpecified = true
};
} }
public override Errno Mount() public override Errno Mount()

View File

@@ -32,6 +32,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using DiscImageChef.CommonTypes; using DiscImageChef.CommonTypes;
@@ -41,6 +42,7 @@ using Schemas;
namespace DiscImageChef.Filesystems namespace DiscImageChef.Filesystems
{ {
// Information from the Linux kernel // Information from the Linux kernel
[SuppressMessage("ReSharper", "InconsistentNaming")]
public class SysVfs : Filesystem public class SysVfs : Filesystem
{ {
const uint XENIX_MAGIC = 0x002B5544; const uint XENIX_MAGIC = 0x002B5544;
@@ -64,55 +66,28 @@ namespace DiscImageChef.Filesystems
public SysVfs() public SysVfs()
{ {
Name = "UNIX System V filesystem"; 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"); CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
} }
public SysVfs(Encoding encoding) public SysVfs(Encoding encoding)
{ {
Name = "UNIX System V filesystem"; Name = "UNIX System V filesystem";
PluginUUID = new Guid("9B8D016A-8561-400E-A12A-A198283C211D"); PluginUuid = new Guid("9B8D016A-8561-400E-A12A-A198283C211D");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public SysVfs(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public SysVfs(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "UNIX System V filesystem"; Name = "UNIX System V filesystem";
PluginUUID = new Guid("9B8D016A-8561-400E-A12A-A198283C211D"); PluginUuid = new Guid("9B8D016A-8561-400E-A12A-A198283C211D");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public override bool Identify(ImagePlugin imagePlugin, Partition partition) public override bool Identify(ImagePlugin imagePlugin, Partition partition)
{ {
if(2 + partition.Start >= partition.End) return false; 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; byte sb_size_in_sectors;
if(imagePlugin.GetSectorSize() <= 0x400 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))) { 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) if(magic == XENIX_MAGIC || magic == XENIX_CIGAM || magic == SYSV_MAGIC || magic == SYSV_CIGAM)
return true; return true;
@@ -151,17 +126,17 @@ namespace DiscImageChef.Filesystems
byte[] coherent_string = new byte[6]; byte[] coherent_string = new byte[6];
Array.Copy(sb_sector, 0x1E4, coherent_string, 0, 6); // Coherent UNIX s_fname location 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 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 || 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; s_fname == COH_XXXXS && s_fpack == COH_XXXXN) return true;
// Now try to identify 7th edition // Now try to identify 7th edition
s_fsize = BitConverter.ToUInt32(sb_sector, 0x002); // 7th edition's s_fsize uint s_fsize = BitConverter.ToUInt32(sb_sector, 0x002);
s_nfree = BitConverter.ToUInt16(sb_sector, 0x006); // 7th edition's s_nfree ushort s_nfree = BitConverter.ToUInt16(sb_sector, 0x006);
s_ninode = BitConverter.ToUInt16(sb_sector, 0x0D0); // 7th edition's s_ninode ushort s_ninode = BitConverter.ToUInt16(sb_sector, 0x0D0);
if(s_fsize <= 0 || s_fsize >= 0xFFFFFFFF || s_nfree <= 0 || s_nfree >= 0xFFFF || s_ninode <= 0 || if(s_fsize <= 0 || s_fsize >= 0xFFFFFFFF || s_nfree <= 0 || s_nfree >= 0xFFFF || s_ninode <= 0 ||
s_ninode >= 0xFFFF) continue; s_ninode >= 0xFFFF) continue;
@@ -197,13 +172,8 @@ namespace DiscImageChef.Filesystems
BigEndianBitConverter.IsLittleEndian = BigEndianBitConverter.IsLittleEndian =
true; // Start in little endian until we know what are we handling here true; // Start in little endian until we know what are we handling here
int start = 0; int start = 0;
uint magic;
string s_fname, s_fpack;
ushort s_nfree, s_ninode;
uint s_fsize;
bool xenix = false; bool xenix = false;
bool sysv = false; bool sysv = false;
bool sysvr4;
bool sys7th = false; bool sys7th = false;
bool coherent = false; bool coherent = false;
bool xenix3 = false; bool xenix3 = false;
@@ -229,7 +199,7 @@ namespace DiscImageChef.Filesystems
foreach(int i in locations) foreach(int i in locations)
{ {
sb_sector = imagePlugin.ReadSectors((ulong)i + partition.Start, sb_size_in_sectors); 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) if(magic == XENIX_MAGIC || magic == SYSV_MAGIC)
{ {
@@ -295,9 +265,9 @@ namespace DiscImageChef.Filesystems
byte[] coherent_string = new byte[6]; byte[] coherent_string = new byte[6];
Array.Copy(sb_sector, 0x1E4, coherent_string, 0, 6); // Coherent UNIX s_fname location 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 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 || 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) s_fname == COH_XXXXS && s_fpack == COH_XXXXN)
@@ -309,9 +279,9 @@ namespace DiscImageChef.Filesystems
} }
// Now try to identify 7th edition // Now try to identify 7th edition
s_fsize = BitConverter.ToUInt32(sb_sector, 0x002); // 7th edition's s_fsize uint s_fsize = BitConverter.ToUInt32(sb_sector, 0x002);
s_nfree = BitConverter.ToUInt16(sb_sector, 0x006); // 7th edition's s_nfree ushort s_nfree = BitConverter.ToUInt16(sb_sector, 0x006);
s_ninode = BitConverter.ToUInt16(sb_sector, 0x0D0); // 7th edition's s_ninode ushort s_ninode = BitConverter.ToUInt16(sb_sector, 0x0D0);
if(s_fsize <= 0 || s_fsize >= 0xFFFFFFFF || s_nfree <= 0 || s_nfree >= 0xFFFF || s_ninode <= 0 || if(s_fsize <= 0 || s_fsize >= 0xFFFFFFFF || s_nfree <= 0 || s_nfree >= 0xFFFF || s_ninode <= 0 ||
s_ninode >= 0xFFFF) continue; s_ninode >= 0xFFFF) continue;
@@ -341,7 +311,7 @@ namespace DiscImageChef.Filesystems
if(!sys7th && !sysv && !coherent && !xenix && !xenix3) return; if(!sys7th && !sysv && !coherent && !xenix && !xenix3) return;
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType();
if(xenix || xenix3) if(xenix || xenix3)
{ {
@@ -402,22 +372,22 @@ namespace DiscImageChef.Filesystems
uint bs = 512; uint bs = 512;
sb.AppendLine("XENIX filesystem"); sb.AppendLine("XENIX filesystem");
xmlFSType.Type = "XENIX fs"; XmlFsType.Type = "XENIX fs";
switch(xnx_sb.s_type) switch(xnx_sb.s_type)
{ {
case 1: case 1:
sb.AppendLine("512 bytes per block"); sb.AppendLine("512 bytes per block");
xmlFSType.ClusterSize = 512; XmlFsType.ClusterSize = 512;
break; break;
case 2: case 2:
sb.AppendLine("1024 bytes per block"); sb.AppendLine("1024 bytes per block");
bs = 1024; bs = 1024;
xmlFSType.ClusterSize = 1024; XmlFsType.ClusterSize = 1024;
break; break;
case 3: case 3:
sb.AppendLine("2048 bytes per block"); sb.AppendLine("2048 bytes per block");
bs = 2048; bs = 2048;
xmlFSType.ClusterSize = 2048; XmlFsType.ClusterSize = 2048;
break; break;
default: default:
sb.AppendFormat("Unknown s_type value: 0x{0:X8}", xnx_sb.s_type).AppendLine(); sb.AppendFormat("Unknown s_type value: 0x{0:X8}", xnx_sb.s_type).AppendLine();
@@ -458,17 +428,17 @@ namespace DiscImageChef.Filesystems
.AppendLine(); .AppendLine();
if(xnx_sb.s_time != 0) if(xnx_sb.s_time != 0)
{ {
xmlFSType.ModificationDate = DateHandlers.UNIXToDateTime(xnx_sb.s_time); XmlFsType.ModificationDate = DateHandlers.UNIXToDateTime(xnx_sb.s_time);
xmlFSType.ModificationDateSpecified = true; XmlFsType.ModificationDateSpecified = true;
} }
sb.AppendFormat("Volume name: {0}", xnx_sb.s_fname).AppendLine(); 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(); sb.AppendFormat("Pack name: {0}", xnx_sb.s_fpack).AppendLine();
if(xnx_sb.s_clean == 0x46) sb.AppendLine("Volume is clean"); if(xnx_sb.s_clean == 0x46) sb.AppendLine("Volume is clean");
else else
{ {
sb.AppendLine("Volume is dirty"); 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); sb_sector = imagePlugin.ReadSectors((ulong)start + partition.Start, sb_size_in_sectors);
byte[] sysv_strings = new byte[6]; byte[] sysv_strings = new byte[6];
SystemVRelease4SuperBlock sysv_sb = new SystemVRelease4SuperBlock(); SystemVRelease4SuperBlock sysv_sb = new SystemVRelease4SuperBlock
sysv_sb.s_type = BigEndianBitConverter.ToUInt32(sb_sector, 0x1FC + offset); {
s_type = BigEndianBitConverter.ToUInt32(sb_sector, 0x1FC + offset)
};
uint bs = 512; uint bs = 512;
switch(sysv_sb.s_type) switch(sysv_sb.s_type)
{ {
case 1: case 1:
xmlFSType.ClusterSize = 512; XmlFsType.ClusterSize = 512;
break; break;
case 2: case 2:
bs = 1024; bs = 1024;
xmlFSType.ClusterSize = 1024; XmlFsType.ClusterSize = 1024;
break; break;
case 3: case 3:
bs = 2048; bs = 2048;
xmlFSType.ClusterSize = 2048; XmlFsType.ClusterSize = 2048;
break; break;
default: default:
sb.AppendFormat("Unknown s_type value: 0x{0:X8}", sysv_sb.s_type).AppendLine(); 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); 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) if(sysvr4)
{ {
@@ -526,7 +498,7 @@ namespace DiscImageChef.Filesystems
Array.Copy(sb_sector, 0x1BC + offset, sysv_strings, 0, 6); Array.Copy(sb_sector, 0x1BC + offset, sysv_strings, 0, 6);
sysv_sb.s_fpack = StringHandlers.CToString(sysv_strings, CurrentEncoding); sysv_sb.s_fpack = StringHandlers.CToString(sysv_strings, CurrentEncoding);
sb.AppendLine("System V Release 4 filesystem"); sb.AppendLine("System V Release 4 filesystem");
xmlFSType.Type = "SVR4 fs"; XmlFsType.Type = "SVR4 fs";
} }
else else
{ {
@@ -552,11 +524,11 @@ namespace DiscImageChef.Filesystems
Array.Copy(sb_sector, 0x1B6 + offset, sysv_strings, 0, 6); Array.Copy(sb_sector, 0x1B6 + offset, sysv_strings, 0, 6);
sysv_sb.s_fpack = StringHandlers.CToString(sysv_strings, CurrentEncoding); sysv_sb.s_fpack = StringHandlers.CToString(sysv_strings, CurrentEncoding);
sb.AppendLine("System V Release 2 filesystem"); sb.AppendLine("System V Release 2 filesystem");
xmlFSType.Type = "SVR2 fs"; XmlFsType.Type = "SVR2 fs";
} }
sb.AppendFormat("{0} bytes per block", bs).AppendLine(); 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} 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) sb.AppendFormat("{0} free zones on volume ({1} bytes)", sysv_sb.s_tfree, sysv_sb.s_tfree * bs)
.AppendLine(); .AppendLine();
@@ -577,17 +549,17 @@ namespace DiscImageChef.Filesystems
.AppendLine(); .AppendLine();
if(sysv_sb.s_time != 0) if(sysv_sb.s_time != 0)
{ {
xmlFSType.ModificationDate = DateHandlers.UNIXUnsignedToDateTime(sysv_sb.s_time); XmlFsType.ModificationDate = DateHandlers.UNIXUnsignedToDateTime(sysv_sb.s_time);
xmlFSType.ModificationDateSpecified = true; XmlFsType.ModificationDateSpecified = true;
} }
sb.AppendFormat("Volume name: {0}", sysv_sb.s_fname).AppendLine(); 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(); 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"); if(sysv_sb.s_state == 0x7C269D38 - sysv_sb.s_time) sb.AppendLine("Volume is clean");
else else
{ {
sb.AppendLine("Volume is dirty"); 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); Array.Copy(sb_sector, 0x1EA, coh_strings, 0, 6);
coh_sb.s_fpack = StringHandlers.CToString(coh_strings, CurrentEncoding); coh_sb.s_fpack = StringHandlers.CToString(coh_strings, CurrentEncoding);
xmlFSType.Type = "Coherent fs"; XmlFsType.Type = "Coherent fs";
xmlFSType.ClusterSize = 512; XmlFsType.ClusterSize = 512;
xmlFSType.Clusters = coh_sb.s_fsize; XmlFsType.Clusters = coh_sb.s_fsize;
sb.AppendLine("Coherent UNIX filesystem"); sb.AppendLine("Coherent UNIX filesystem");
if(imagePlugin.GetSectorSize() != 512) if(imagePlugin.GetSectorSize() != 512)
@@ -640,11 +612,11 @@ namespace DiscImageChef.Filesystems
.AppendLine(); .AppendLine();
if(coh_sb.s_time != 0) if(coh_sb.s_time != 0)
{ {
xmlFSType.ModificationDate = DateHandlers.UNIXUnsignedToDateTime(coh_sb.s_time); XmlFsType.ModificationDate = DateHandlers.UNIXUnsignedToDateTime(coh_sb.s_time);
xmlFSType.ModificationDateSpecified = true; XmlFsType.ModificationDateSpecified = true;
} }
sb.AppendFormat("Volume name: {0}", coh_sb.s_fname).AppendLine(); 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(); 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); Array.Copy(sb_sector, 0x1B2, sys7_strings, 0, 6);
v7_sb.s_fpack = StringHandlers.CToString(sys7_strings, CurrentEncoding); v7_sb.s_fpack = StringHandlers.CToString(sys7_strings, CurrentEncoding);
xmlFSType.Type = "UNIX 7th Edition fs"; XmlFsType.Type = "UNIX 7th Edition fs";
xmlFSType.ClusterSize = 512; XmlFsType.ClusterSize = 512;
xmlFSType.Clusters = v7_sb.s_fsize; XmlFsType.Clusters = v7_sb.s_fsize;
sb.AppendLine("UNIX 7th Edition filesystem"); sb.AppendLine("UNIX 7th Edition filesystem");
if(imagePlugin.GetSectorSize() != 512) if(imagePlugin.GetSectorSize() != 512)
sb sb
@@ -695,11 +667,11 @@ namespace DiscImageChef.Filesystems
.AppendLine(); .AppendLine();
if(v7_sb.s_time != 0) if(v7_sb.s_time != 0)
{ {
xmlFSType.ModificationDate = DateHandlers.UNIXUnsignedToDateTime(v7_sb.s_time); XmlFsType.ModificationDate = DateHandlers.UNIXUnsignedToDateTime(v7_sb.s_time);
xmlFSType.ModificationDateSpecified = true; XmlFsType.ModificationDateSpecified = true;
} }
sb.AppendFormat("Volume name: {0}", v7_sb.s_fname).AppendLine(); 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(); sb.AppendFormat("Pack name: {0}", v7_sb.s_fpack).AppendLine();
} }

View File

@@ -40,9 +40,7 @@ namespace DiscImageChef.Filesystems.UCSDPascal
{ {
public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock)
{ {
if(!mounted) return Errno.AccessDenied; return !mounted ? Errno.AccessDenied : Errno.NotImplemented;
return Errno.NotImplemented;
} }
public override Errno GetAttributes(string path, ref FileAttributes attributes) public override Errno GetAttributes(string path, ref FileAttributes attributes)
@@ -52,8 +50,7 @@ namespace DiscImageChef.Filesystems.UCSDPascal
string[] pathElements = path.Split(new[] {'/'}, StringSplitOptions.RemoveEmptyEntries); string[] pathElements = path.Split(new[] {'/'}, StringSplitOptions.RemoveEmptyEntries);
if(pathElements.Length != 1) return Errno.NotSupported; if(pathElements.Length != 1) return Errno.NotSupported;
PascalFileEntry entry; Errno error = GetFileEntry(path, out _);
Errno error = GetFileEntry(path, out entry);
if(error != Errno.NoError) return error; if(error != Errno.NoError) return error;
@@ -71,16 +68,13 @@ namespace DiscImageChef.Filesystems.UCSDPascal
if(pathElements.Length != 1) return Errno.NotSupported; if(pathElements.Length != 1) return Errno.NotSupported;
byte[] file; byte[] file;
Errno error;
if(debug && (string.Compare(path, "$", StringComparison.InvariantCulture) == 0 || if(debug && (string.Compare(path, "$", StringComparison.InvariantCulture) == 0 ||
string.Compare(path, "$Boot", StringComparison.InvariantCulture) == 0)) string.Compare(path, "$Boot", StringComparison.InvariantCulture) == 0))
if(string.Compare(path, "$", StringComparison.InvariantCulture) == 0) file = catalogBlocks; file = string.Compare(path, "$", StringComparison.InvariantCulture) == 0 ? catalogBlocks : bootBlocks;
else file = bootBlocks;
else else
{ {
PascalFileEntry entry; Errno error = GetFileEntry(path, out PascalFileEntry entry);
error = GetFileEntry(path, out entry);
if(error != Errno.NoError) return error; if(error != Errno.NoError) return error;
@@ -113,16 +107,17 @@ namespace DiscImageChef.Filesystems.UCSDPascal
if(string.Compare(path, "$", StringComparison.InvariantCulture) == 0 || if(string.Compare(path, "$", StringComparison.InvariantCulture) == 0 ||
string.Compare(path, "$Boot", StringComparison.InvariantCulture) == 0) string.Compare(path, "$Boot", StringComparison.InvariantCulture) == 0)
{ {
stat = new FileEntryInfo(); stat = new FileEntryInfo
stat.Attributes = new FileAttributes(); {
stat.Attributes = FileAttributes.System; Attributes = FileAttributes.System,
stat.BlockSize = device.GetSectorSize(); BlockSize = device.GetSectorSize(),
stat.DeviceNo = 0; DeviceNo = 0,
stat.GID = 0; GID = 0,
stat.Inode = 0; Inode = 0,
stat.Links = 1; Links = 1,
stat.Mode = 0x124; Mode = 0x124,
stat.UID = 0; UID = 0
};
if(string.Compare(path, "$", StringComparison.InvariantCulture) == 0) if(string.Compare(path, "$", StringComparison.InvariantCulture) == 0)
{ {
@@ -138,24 +133,24 @@ namespace DiscImageChef.Filesystems.UCSDPascal
return Errno.NoError; return Errno.NoError;
} }
PascalFileEntry entry; Errno error = GetFileEntry(path, out PascalFileEntry entry);
Errno error = GetFileEntry(path, out entry);
if(error != Errno.NoError) return error; if(error != Errno.NoError) return error;
stat = new FileEntryInfo(); stat = new FileEntryInfo
stat.Attributes = new FileAttributes(); {
stat.Attributes = FileAttributes.File; Attributes = FileAttributes.File,
stat.Blocks = entry.lastBlock - entry.firstBlock; Blocks = entry.lastBlock - entry.firstBlock,
stat.BlockSize = device.GetSectorSize(); BlockSize = device.GetSectorSize(),
stat.DeviceNo = 0; DeviceNo = 0,
stat.GID = 0; GID = 0,
stat.Inode = 0; Inode = 0,
stat.LastWriteTimeUtc = DateHandlers.UCSDPascalToDateTime(entry.mtime); LastWriteTimeUtc = DateHandlers.UCSDPascalToDateTime(entry.mtime),
stat.Length = (entry.lastBlock - entry.firstBlock) * device.GetSectorSize() + entry.lastBytes; Length = (entry.lastBlock - entry.firstBlock) * device.GetSectorSize() + entry.lastBytes,
stat.Links = 1; Links = 1,
stat.Mode = 0x124; Mode = 0x124,
stat.UID = 0; UID = 0
};
return Errno.NoError; return Errno.NoError;
} }

View File

@@ -143,14 +143,16 @@ namespace DiscImageChef.Filesystems.UCSDPascal
information = sbInformation.ToString(); information = sbInformation.ToString();
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType
xmlFSType.Bootable = !ArrayHelpers.ArrayIsNullOrEmpty(imagePlugin.ReadSectors(partition.Start, 2)); {
xmlFSType.Clusters = volEntry.blocks; Bootable = !ArrayHelpers.ArrayIsNullOrEmpty(imagePlugin.ReadSectors(partition.Start, 2)),
xmlFSType.ClusterSize = (int)imagePlugin.GetSectorSize(); Clusters = volEntry.blocks,
xmlFSType.Files = volEntry.files; ClusterSize = (int)imagePlugin.GetSectorSize(),
xmlFSType.FilesSpecified = true; Files = volEntry.files,
xmlFSType.Type = "UCSD Pascal"; FilesSpecified = true,
xmlFSType.VolumeName = StringHandlers.PascalToString(volEntry.volumeName, CurrentEncoding); Type = "UCSD Pascal",
VolumeName = StringHandlers.PascalToString(volEntry.volumeName, CurrentEncoding)
};
} }
} }
} }

View File

@@ -78,14 +78,16 @@ namespace DiscImageChef.Filesystems.UCSDPascal
fileEntries = new List<PascalFileEntry>(); fileEntries = new List<PascalFileEntry>();
while(offset + 26 < catalogBlocks.Length) while(offset + 26 < catalogBlocks.Length)
{ {
PascalFileEntry entry = new PascalFileEntry(); PascalFileEntry entry = new PascalFileEntry
entry.filename = new byte[16]; {
entry.firstBlock = BigEndianBitConverter.ToInt16(catalogBlocks, offset + 0x00); filename = new byte[16],
entry.lastBlock = BigEndianBitConverter.ToInt16(catalogBlocks, offset + 0x02); firstBlock = BigEndianBitConverter.ToInt16(catalogBlocks, offset + 0x00),
entry.entryType = (PascalFileKind)BigEndianBitConverter.ToInt16(catalogBlocks, offset + 0x04); 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); 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); 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); bootBlocks = device.ReadSectors(0, 2);
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType
xmlFSType.Bootable = !ArrayHelpers.ArrayIsNullOrEmpty(bootBlocks); {
xmlFSType.Clusters = mountedVolEntry.blocks; Bootable = !ArrayHelpers.ArrayIsNullOrEmpty(bootBlocks),
xmlFSType.ClusterSize = (int)device.GetSectorSize(); Clusters = mountedVolEntry.blocks,
xmlFSType.Files = mountedVolEntry.files; ClusterSize = (int)device.GetSectorSize(),
xmlFSType.FilesSpecified = true; Files = mountedVolEntry.files,
xmlFSType.Type = "UCSD Pascal"; FilesSpecified = true,
xmlFSType.VolumeName = StringHandlers.PascalToString(mountedVolEntry.volumeName, CurrentEncoding); Type = "UCSD Pascal",
VolumeName = StringHandlers.PascalToString(mountedVolEntry.volumeName, CurrentEncoding)
};
mounted = true; mounted = true;
@@ -122,7 +126,7 @@ namespace DiscImageChef.Filesystems.UCSDPascal
stat.FilenameLength = 16; stat.FilenameLength = 16;
stat.Files = (ulong)mountedVolEntry.files; stat.Files = (ulong)mountedVolEntry.files;
stat.FreeBlocks = 0; stat.FreeBlocks = 0;
stat.PluginId = PluginUUID; stat.PluginId = PluginUuid;
stat.Type = "UCSD Pascal"; stat.Type = "UCSD Pascal";
stat.FreeBlocks = mountedVolEntry.blocks - (mountedVolEntry.lastBlock - mountedVolEntry.firstBlock); stat.FreeBlocks = mountedVolEntry.blocks - (mountedVolEntry.lastBlock - mountedVolEntry.firstBlock);

View File

@@ -54,14 +54,14 @@ namespace DiscImageChef.Filesystems.UCSDPascal
public PascalPlugin() public PascalPlugin()
{ {
Name = "U.C.S.D. Pascal filesystem"; 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(); CurrentEncoding = new LisaRoman();
} }
public PascalPlugin(Encoding encoding) public PascalPlugin(Encoding encoding)
{ {
Name = "U.C.S.D. Pascal filesystem"; 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 // TODO: Until Apple ][ encoding is implemented
CurrentEncoding = new LisaRoman(); CurrentEncoding = new LisaRoman();
} }
@@ -70,7 +70,7 @@ namespace DiscImageChef.Filesystems.UCSDPascal
{ {
device = imagePlugin; device = imagePlugin;
Name = "U.C.S.D. Pascal filesystem"; 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 // TODO: Until Apple ][ encoding is implemented
CurrentEncoding = new LisaRoman(); CurrentEncoding = new LisaRoman();
} }

View File

@@ -48,14 +48,14 @@ namespace DiscImageChef.Filesystems
public UDF() public UDF()
{ {
Name = "Universal Disk Format"; Name = "Universal Disk Format";
PluginUUID = new Guid("83976FEC-A91B-464B-9293-56C719461BAB"); PluginUuid = new Guid("83976FEC-A91B-464B-9293-56C719461BAB");
CurrentEncoding = Encoding.UTF8; CurrentEncoding = Encoding.UTF8;
} }
public UDF(Encoding encoding) public UDF(Encoding encoding)
{ {
Name = "Universal Disk Format"; 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 // UDF is always UTF-8
CurrentEncoding = Encoding.UTF8; CurrentEncoding = Encoding.UTF8;
} }
@@ -63,7 +63,7 @@ namespace DiscImageChef.Filesystems
public UDF(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public UDF(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "Universal Disk Format"; 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 // UDF is always UTF-8
CurrentEncoding = Encoding.UTF8; CurrentEncoding = Encoding.UTF8;
} }
@@ -416,7 +416,7 @@ namespace DiscImageChef.Filesystems
.AppendFormat("Volume name: {0}", StringHandlers.DecompressUnicode(lvd.logicalVolumeIdentifier)) .AppendFormat("Volume name: {0}", StringHandlers.DecompressUnicode(lvd.logicalVolumeIdentifier))
.AppendLine(); .AppendLine();
sbInformation.AppendFormat("Volume uses {0} bytes per block", lvd.logicalBlockSize).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(); .AppendLine();
sbInformation.AppendFormat("Volume contains {0} partitions", lvid.numberOfPartitions).AppendLine(); sbInformation.AppendFormat("Volume contains {0} partitions", lvid.numberOfPartitions).AppendLine();
sbInformation sbInformation
@@ -445,27 +445,28 @@ namespace DiscImageChef.Filesystems
Convert.ToInt32($"{lvidiu.maximumWriteUDF & 0xFF}", 10)) Convert.ToInt32($"{lvidiu.maximumWriteUDF & 0xFF}", 10))
.AppendLine(); .AppendLine();
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType
xmlFSType.Type = {
$"UDF v{Convert.ToInt32($"{(lvidiu.maximumWriteUDF & 0xFF00) >> 8}", 10)}.{Convert.ToInt32($"{lvidiu.maximumWriteUDF & 0xFF}", 10):X2}"; Type =
xmlFSType.ApplicationIdentifier = CurrentEncoding $"UDF v{Convert.ToInt32($"{(lvidiu.maximumWriteUDF & 0xFF00) >> 8}", 10)}.{Convert.ToInt32($"{lvidiu.maximumWriteUDF & 0xFF}", 10):X2}",
.GetString(pvd.implementationIdentifier.identifier).TrimEnd('\u0000'); ApplicationIdentifier =
xmlFSType.ClusterSize = (int)lvd.logicalBlockSize; CurrentEncoding.GetString(pvd.implementationIdentifier.identifier).TrimEnd('\u0000'),
xmlFSType.Clusters = (long)((partition.End - partition.Start + 1) * imagePlugin.ImageInfo.SectorSize / ClusterSize = (int)lvd.logicalBlockSize,
(ulong)xmlFSType.ClusterSize); ModificationDate = EcmaToDateTime(lvid.recordingDateTime),
xmlFSType.ModificationDate = ECMAToDateTime(lvid.recordingDateTime); ModificationDateSpecified = true,
xmlFSType.ModificationDateSpecified = true; Files = lvidiu.files,
xmlFSType.Files = lvidiu.files; FilesSpecified = true,
xmlFSType.FilesSpecified = true; VolumeName = StringHandlers.DecompressUnicode(lvd.logicalVolumeIdentifier),
xmlFSType.VolumeName = StringHandlers.DecompressUnicode(lvd.logicalVolumeIdentifier); VolumeSetIdentifier = StringHandlers.DecompressUnicode(pvd.volumeSetIdentifier),
xmlFSType.VolumeSetIdentifier = StringHandlers.DecompressUnicode(pvd.volumeSetIdentifier); SystemIdentifier = CurrentEncoding.GetString(pvd.implementationIdentifier.identifier).TrimEnd('\u0000')
xmlFSType.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(); information = sbInformation.ToString();
} }
static DateTime ECMAToDateTime(Timestamp timestamp) static DateTime EcmaToDateTime(Timestamp timestamp)
{ {
return DateHandlers.ECMAToDateTime(timestamp.typeAndZone, timestamp.year, timestamp.month, timestamp.day, return DateHandlers.ECMAToDateTime(timestamp.typeAndZone, timestamp.year, timestamp.month, timestamp.day,
timestamp.hour, timestamp.minute, timestamp.second, timestamp.hour, timestamp.minute, timestamp.second,

View File

@@ -32,6 +32,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
using DiscImageChef.CommonTypes; using DiscImageChef.CommonTypes;
@@ -48,6 +49,8 @@ using time_t = System.Int64;
namespace DiscImageChef.Filesystems namespace DiscImageChef.Filesystems
{ {
[SuppressMessage("ReSharper", "InconsistentNaming")]
[SuppressMessage("ReSharper", "BuiltInTypeReferenceStyle")]
public class UNICOS : Filesystem public class UNICOS : Filesystem
{ {
const int NC1MAXPART = 64; const int NC1MAXPART = 64;
@@ -137,24 +140,22 @@ namespace DiscImageChef.Filesystems
public UNICOS() public UNICOS()
{ {
Name = "UNICOS Filesystem Plugin"; 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"); CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
} }
public UNICOS(Encoding encoding) public UNICOS(Encoding encoding)
{ {
Name = "UNICOS Filesystem Plugin"; Name = "UNICOS Filesystem Plugin";
PluginUUID = new Guid("61712F04-066C-44D5-A2A0-1E44C66B33F0"); PluginUuid = new Guid("61712F04-066C-44D5-A2A0-1E44C66B33F0");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public UNICOS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public UNICOS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "UNICOS Filesystem Plugin"; Name = "UNICOS Filesystem Plugin";
PluginUUID = new Guid("61712F04-066C-44D5-A2A0-1E44C66B33F0"); PluginUuid = new Guid("61712F04-066C-44D5-A2A0-1E44C66B33F0");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public override bool Identify(ImagePlugin imagePlugin, Partition partition) public override bool Identify(ImagePlugin imagePlugin, Partition partition)
@@ -213,7 +214,7 @@ namespace DiscImageChef.Filesystems
information = sb.ToString(); information = sb.ToString();
xmlFSType = new FileSystemType XmlFsType = new FileSystemType
{ {
Type = "UNICOS filesystem", Type = "UNICOS filesystem",
ClusterSize = 4096, ClusterSize = 4096,
@@ -222,7 +223,7 @@ namespace DiscImageChef.Filesystems
ModificationDate = DateHandlers.UNIXToDateTime(unicosSb.s_time), ModificationDate = DateHandlers.UNIXToDateTime(unicosSb.s_time),
ModificationDateSpecified = true ModificationDateSpecified = true
}; };
xmlFSType.Dirty |= unicosSb.s_error > 0; XmlFsType.Dirty |= unicosSb.s_error > 0;
} }
public override Errno Mount() public override Errno Mount()

View File

@@ -48,24 +48,22 @@ namespace DiscImageChef.Filesystems
public BFS() public BFS()
{ {
Name = "UNIX Boot filesystem"; 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"); CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
} }
public BFS(Encoding encoding) public BFS(Encoding encoding)
{ {
Name = "UNIX Boot filesystem"; Name = "UNIX Boot filesystem";
PluginUUID = new Guid("1E6E0DA6-F7E4-494C-80C6-CB5929E96155"); PluginUuid = new Guid("1E6E0DA6-F7E4-494C-80C6-CB5929E96155");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public BFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public BFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "UNIX Boot filesystem"; Name = "UNIX Boot filesystem";
PluginUUID = new Guid("1E6E0DA6-F7E4-494C-80C6-CB5929E96155"); PluginUuid = new Guid("1E6E0DA6-F7E4-494C-80C6-CB5929E96155");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public override bool Identify(ImagePlugin imagePlugin, Partition partition) public override bool Identify(ImagePlugin imagePlugin, Partition partition)
@@ -85,44 +83,46 @@ namespace DiscImageChef.Filesystems
information = ""; information = "";
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
byte[] bfs_sb_sector = imagePlugin.ReadSector(0 + partition.Start); byte[] bfsSbSector = imagePlugin.ReadSector(0 + partition.Start);
byte[] sb_strings = new byte[6]; 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); Array.Copy(bfsSbSector, 0x1C, sbStrings, 0, 6);
bfs_sb.s_start = BitConverter.ToUInt32(bfs_sb_sector, 0x04); bfsSb.s_fsname = StringHandlers.CToString(sbStrings, CurrentEncoding);
bfs_sb.s_end = BitConverter.ToUInt32(bfs_sb_sector, 0x08); Array.Copy(bfsSbSector, 0x22, sbStrings, 0, 6);
bfs_sb.s_from = BitConverter.ToUInt32(bfs_sb_sector, 0x0C); bfsSb.s_volume = StringHandlers.CToString(sbStrings, CurrentEncoding);
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);
DicConsole.DebugWriteLine("BFS plugin", "bfs_sb.s_magic: 0x{0:X8}", bfs_sb.s_magic); 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}", bfs_sb.s_start); 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}", bfs_sb.s_end); 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}", bfs_sb.s_from); 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}", bfs_sb.s_to); 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}", bfs_sb.s_bfrom); 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}", bfs_sb.s_bto); DicConsole.DebugWriteLine("BFS plugin", "bfs_sb.s_bto: 0x{0:X8}", bfsSb.s_bto);
DicConsole.DebugWriteLine("BFS plugin", "bfs_sb.s_fsname: 0x{0}", bfs_sb.s_fsname); DicConsole.DebugWriteLine("BFS plugin", "bfs_sb.s_fsname: 0x{0}", bfsSb.s_fsname);
DicConsole.DebugWriteLine("BFS plugin", "bfs_sb.s_volume: 0x{0}", bfs_sb.s_volume); DicConsole.DebugWriteLine("BFS plugin", "bfs_sb.s_volume: 0x{0}", bfsSb.s_volume);
sb.AppendLine("UNIX Boot filesystem"); 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, sb.AppendFormat("Volume goes from byte {0} to byte {1}, for {2} bytes", bfsSb.s_start, bfsSb.s_end,
bfs_sb.s_end - bfs_sb.s_start).AppendLine(); bfsSb.s_end - bfsSb.s_start).AppendLine();
sb.AppendFormat("Filesystem name: {0}", bfs_sb.s_fsname).AppendLine(); sb.AppendFormat("Filesystem name: {0}", bfsSb.s_fsname).AppendLine();
sb.AppendFormat("Volume name: {0}", bfs_sb.s_volume).AppendLine(); sb.AppendFormat("Volume name: {0}", bfsSb.s_volume).AppendLine();
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType();
xmlFSType.Type = "BFS"; XmlFsType.Type = "BFS";
xmlFSType.VolumeName = bfs_sb.s_volume; XmlFsType.VolumeName = bfsSb.s_volume;
xmlFSType.ClusterSize = (int)imagePlugin.GetSectorSize(); XmlFsType.ClusterSize = (int)imagePlugin.GetSectorSize();
xmlFSType.Clusters = (long)(partition.End - partition.Start + 1); XmlFsType.Clusters = (long)(partition.End - partition.Start + 1);
information = sb.ToString(); information = sb.ToString();
} }

View File

@@ -45,24 +45,22 @@ namespace DiscImageChef.Filesystems
public VMfs() public VMfs()
{ {
Name = "VMware filesystem"; Name = "VMware filesystem";
PluginUUID = new Guid("EE52BDB8-B49C-4122-A3DA-AD21CBE79843"); PluginUuid = new Guid("EE52BDB8-B49C-4122-A3DA-AD21CBE79843");
CurrentEncoding = Encoding.UTF8; CurrentEncoding = Encoding.UTF8;
} }
public VMfs(Encoding encoding) public VMfs(Encoding encoding)
{ {
Name = "VMware filesystem"; Name = "VMware filesystem";
PluginUUID = new Guid("EE52BDB8-B49C-4122-A3DA-AD21CBE79843"); PluginUuid = new Guid("EE52BDB8-B49C-4122-A3DA-AD21CBE79843");
if(encoding == null) CurrentEncoding = Encoding.UTF8; CurrentEncoding = encoding ?? Encoding.UTF8;
else CurrentEncoding = encoding;
} }
public VMfs(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public VMfs(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "VMware filesystem"; Name = "VMware filesystem";
PluginUUID = new Guid("EE52BDB8-B49C-4122-A3DA-AD21CBE79843"); PluginUuid = new Guid("EE52BDB8-B49C-4122-A3DA-AD21CBE79843");
if(encoding == null) CurrentEncoding = Encoding.UTF8; CurrentEncoding = encoding ?? Encoding.UTF8;
else CurrentEncoding = encoding;
} }
[Flags] [Flags]
@@ -92,14 +90,14 @@ namespace DiscImageChef.Filesystems
/// <summary> /// <summary>
/// Identifier for VMfs /// Identifier for VMfs
/// </summary> /// </summary>
const uint VMfs_MAGIC = 0xC001D00D; const uint VMFS_MAGIC = 0xC001D00D;
const uint VMfs_Base = 0x00100000; const uint VMFS_BASE = 0x00100000;
public override bool Identify(ImagePlugin imagePlugin, Partition partition) public override bool Identify(ImagePlugin imagePlugin, Partition partition)
{ {
if(partition.Start >= partition.End) return false; 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; if(partition.Start + vmfsSuperOff > partition.End) return false;
@@ -107,13 +105,13 @@ namespace DiscImageChef.Filesystems
uint magic = BitConverter.ToUInt32(sector, 0x00); uint magic = BitConverter.ToUInt32(sector, 0x00);
return magic == VMfs_MAGIC; return magic == VMFS_MAGIC;
} }
public override void GetInformation(ImagePlugin imagePlugin, Partition partition, public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
out string information) out string information)
{ {
ulong vmfsSuperOff = VMfs_Base / imagePlugin.ImageInfo.SectorSize; ulong vmfsSuperOff = VMFS_BASE / imagePlugin.ImageInfo.SectorSize;
byte[] sector = imagePlugin.ReadSector(partition.Start + vmfsSuperOff); byte[] sector = imagePlugin.ReadSector(partition.Start + vmfsSuperOff);
VolumeInfo volInfo = new VolumeInfo(); VolumeInfo volInfo = new VolumeInfo();
@@ -144,15 +142,17 @@ namespace DiscImageChef.Filesystems
information = sbInformation.ToString(); information = sbInformation.ToString();
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType
xmlFSType.Type = "VMware file system"; {
xmlFSType.CreationDate = DateHandlers.UNIXUnsignedToDateTime(ctimeSecs, ctimeNanoSecs); Type = "VMware file system",
xmlFSType.CreationDateSpecified = true; CreationDate = DateHandlers.UNIXUnsignedToDateTime(ctimeSecs, ctimeNanoSecs),
xmlFSType.ModificationDate = DateHandlers.UNIXUnsignedToDateTime(mtimeSecs, mtimeNanoSecs); CreationDateSpecified = true,
xmlFSType.ModificationDateSpecified = true; ModificationDate = DateHandlers.UNIXUnsignedToDateTime(mtimeSecs, mtimeNanoSecs),
xmlFSType.Clusters = volInfo.size * 256 / imagePlugin.ImageInfo.SectorSize; ModificationDateSpecified = true,
xmlFSType.ClusterSize = (int)imagePlugin.ImageInfo.SectorSize; Clusters = volInfo.size * 256 / imagePlugin.ImageInfo.SectorSize,
xmlFSType.VolumeSerial = volInfo.uuid.ToString(); ClusterSize = (int)imagePlugin.ImageInfo.SectorSize,
VolumeSerial = volInfo.uuid.ToString()
};
} }
public override Errno Mount() public override Errno Mount()

View File

@@ -45,24 +45,22 @@ namespace DiscImageChef.Filesystems
public VxFS() public VxFS()
{ {
Name = "Veritas filesystem"; Name = "Veritas filesystem";
PluginUUID = new Guid("EC372605-7687-453C-8BEA-7E0DFF79CB03"); PluginUuid = new Guid("EC372605-7687-453C-8BEA-7E0DFF79CB03");
CurrentEncoding = Encoding.UTF8; CurrentEncoding = Encoding.UTF8;
} }
public VxFS(Encoding encoding) public VxFS(Encoding encoding)
{ {
Name = "Veritas filesystem"; Name = "Veritas filesystem";
PluginUUID = new Guid("EC372605-7687-453C-8BEA-7E0DFF79CB03"); PluginUuid = new Guid("EC372605-7687-453C-8BEA-7E0DFF79CB03");
if(encoding == null) CurrentEncoding = Encoding.UTF8; CurrentEncoding = encoding ?? Encoding.UTF8;
else CurrentEncoding = encoding;
} }
public VxFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public VxFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "Veritas filesystem"; Name = "Veritas filesystem";
PluginUUID = new Guid("EC372605-7687-453C-8BEA-7E0DFF79CB03"); PluginUuid = new Guid("EC372605-7687-453C-8BEA-7E0DFF79CB03");
if(encoding == null) CurrentEncoding = Encoding.UTF8; CurrentEncoding = encoding ?? Encoding.UTF8;
else CurrentEncoding = encoding;
} }
[StructLayout(LayoutKind.Sequential, Pack = 1)] [StructLayout(LayoutKind.Sequential, Pack = 1)]
@@ -211,12 +209,12 @@ namespace DiscImageChef.Filesystems
/// <summary> /// <summary>
/// Identifier for VxFS /// Identifier for VxFS
/// </summary> /// </summary>
const uint VxFS_MAGIC = 0xA501FCF5; const uint VXFS_MAGIC = 0xA501FCF5;
const uint VxFS_Base = 0x400; const uint VXFS_Base = 0x400;
public override bool Identify(ImagePlugin imagePlugin, Partition partition) 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; if(partition.Start + vmfsSuperOff >= partition.End) return false;
@@ -224,13 +222,13 @@ namespace DiscImageChef.Filesystems
uint magic = BitConverter.ToUInt32(sector, 0x00); uint magic = BitConverter.ToUInt32(sector, 0x00);
return magic == VxFS_MAGIC; return magic == VXFS_MAGIC;
} }
public override void GetInformation(ImagePlugin imagePlugin, Partition partition, public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
out string information) out string information)
{ {
ulong vmfsSuperOff = VxFS_Base / imagePlugin.ImageInfo.SectorSize; ulong vmfsSuperOff = VXFS_Base / imagePlugin.ImageInfo.SectorSize;
byte[] sector = imagePlugin.ReadSector(partition.Start + vmfsSuperOff); byte[] sector = imagePlugin.ReadSector(partition.Start + vmfsSuperOff);
VxSuperBlock vxSb = new VxSuperBlock(); VxSuperBlock vxSb = new VxSuperBlock();
@@ -259,17 +257,19 @@ namespace DiscImageChef.Filesystems
information = sbInformation.ToString(); information = sbInformation.ToString();
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType
xmlFSType.Type = "Veritas file system"; {
xmlFSType.CreationDate = DateHandlers.UNIXUnsignedToDateTime(vxSb.vs_ctime, vxSb.vs_cutime); Type = "Veritas file system",
xmlFSType.CreationDateSpecified = true; CreationDate = DateHandlers.UNIXUnsignedToDateTime(vxSb.vs_ctime, vxSb.vs_cutime),
xmlFSType.ModificationDate = DateHandlers.UNIXUnsignedToDateTime(vxSb.vs_wtime, vxSb.vs_wutime); CreationDateSpecified = true,
xmlFSType.ModificationDateSpecified = true; ModificationDate = DateHandlers.UNIXUnsignedToDateTime(vxSb.vs_wtime, vxSb.vs_wutime),
xmlFSType.Clusters = vxSb.vs_size; ModificationDateSpecified = true,
xmlFSType.ClusterSize = vxSb.vs_bsize; Clusters = vxSb.vs_size,
xmlFSType.Dirty = vxSb.vs_clean != 0; ClusterSize = vxSb.vs_bsize,
xmlFSType.FreeClusters = vxSb.vs_free; Dirty = vxSb.vs_clean != 0,
xmlFSType.FreeClustersSpecified = true; FreeClusters = vxSb.vs_free,
FreeClustersSpecified = true
};
} }
public override Errno Mount() public override Errno Mount()

View File

@@ -104,29 +104,27 @@ namespace DiscImageChef.Filesystems
public Guid meta_uuid; public Guid meta_uuid;
} }
const uint XFS_Magic = 0x58465342; const uint XFS_MAGIC = 0x58465342;
public XFS() public XFS()
{ {
Name = "XFS Filesystem Plugin"; 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"); CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
} }
public XFS(Encoding encoding) public XFS(Encoding encoding)
{ {
Name = "XFS Filesystem Plugin"; Name = "XFS Filesystem Plugin";
PluginUUID = new Guid("1D8CD8B8-27E6-410F-9973-D16409225FBA"); PluginUuid = new Guid("1D8CD8B8-27E6-410F-9973-D16409225FBA");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public XFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public XFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "XFS Filesystem Plugin"; Name = "XFS Filesystem Plugin";
PluginUUID = new Guid("1D8CD8B8-27E6-410F-9973-D16409225FBA"); PluginUuid = new Guid("1D8CD8B8-27E6-410F-9973-D16409225FBA");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public override bool Identify(ImagePlugin imagePlugin, Partition partition) public override bool Identify(ImagePlugin imagePlugin, Partition partition)
@@ -153,9 +151,9 @@ namespace DiscImageChef.Filesystems
xfsSb = BigEndianMarshal.ByteArrayToStructureBigEndian<XFS_Superblock>(sbpiece); xfsSb = BigEndianMarshal.ByteArrayToStructureBigEndian<XFS_Superblock>(sbpiece);
DicConsole.DebugWriteLine("XFS plugin", "magic at 0x{0:X3} = 0x{1:X8} (expected 0x{2:X8})", 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 else
@@ -172,9 +170,9 @@ namespace DiscImageChef.Filesystems
xfsSb = BigEndianMarshal.ByteArrayToStructureBigEndian<XFS_Superblock>(sector); xfsSb = BigEndianMarshal.ByteArrayToStructureBigEndian<XFS_Superblock>(sector);
DicConsole.DebugWriteLine("XFS plugin", "magic at {0} = 0x{1:X8} (expected 0x{2:X8})", location, 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; return false;
@@ -206,9 +204,9 @@ namespace DiscImageChef.Filesystems
xfsSb = BigEndianMarshal.ByteArrayToStructureBigEndian<XFS_Superblock>(sbpiece); xfsSb = BigEndianMarshal.ByteArrayToStructureBigEndian<XFS_Superblock>(sbpiece);
DicConsole.DebugWriteLine("XFS plugin", "magic at 0x{0:X3} = 0x{1:X8} (expected 0x{2:X8})", 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 else
@@ -223,12 +221,12 @@ namespace DiscImageChef.Filesystems
xfsSb = BigEndianMarshal.ByteArrayToStructureBigEndian<XFS_Superblock>(sector); xfsSb = BigEndianMarshal.ByteArrayToStructureBigEndian<XFS_Superblock>(sector);
DicConsole.DebugWriteLine("XFS plugin", "magic at {0} = 0x{1:X8} (expected 0x{2:X8})", location, 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(); StringBuilder sb = new StringBuilder();
@@ -247,17 +245,19 @@ namespace DiscImageChef.Filesystems
information = sb.ToString(); information = sb.ToString();
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType
xmlFSType.Type = "XFS filesystem"; {
xmlFSType.ClusterSize = (int)xfsSb.blocksize; Type = "XFS filesystem",
xmlFSType.Clusters = (long)xfsSb.dblocks; ClusterSize = (int)xfsSb.blocksize,
xmlFSType.FreeClusters = (long)xfsSb.fdblocks; Clusters = (long)xfsSb.dblocks,
xmlFSType.FreeClustersSpecified = true; FreeClusters = (long)xfsSb.fdblocks,
xmlFSType.Files = (long)(xfsSb.icount - xfsSb.ifree); FreeClustersSpecified = true,
xmlFSType.FilesSpecified = true; Files = (long)(xfsSb.icount - xfsSb.ifree),
xmlFSType.Dirty |= xfsSb.inprogress > 0; FilesSpecified = true,
xmlFSType.VolumeName = StringHandlers.CToString(xfsSb.fname, CurrentEncoding); Dirty = xfsSb.inprogress > 0,
xmlFSType.VolumeSerial = xfsSb.uuid.ToString(); VolumeName = StringHandlers.CToString(xfsSb.fname, CurrentEncoding),
VolumeSerial = xfsSb.uuid.ToString()
};
} }
public override Errno Mount() public override Errno Mount()

View File

@@ -32,6 +32,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
using DiscImageChef.CommonTypes; using DiscImageChef.CommonTypes;
@@ -59,10 +60,11 @@ namespace DiscImageChef.Filesystems
* It can also be encoded little or big endian. * 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. * 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 public class ZFS : Filesystem
{ {
const ulong ZEC_Magic = 0x0210DA7AB10C7A11; const ulong ZEC_MAGIC = 0x0210DA7AB10C7A11;
const ulong ZEC_Cigam = 0x117A0CB17ADA1002; const ulong ZEC_CIGAM = 0x117A0CB17ADA1002;
struct ZIO_Checksum struct ZIO_Checksum
{ {
@@ -81,9 +83,9 @@ namespace DiscImageChef.Filesystems
} }
// These parameters define how the nvlist is stored // These parameters define how the nvlist is stored
const byte NVS_LittleEndian = 1; const byte NVS_LITTLE_ENDIAN = 1;
const byte NVS_BigEndian = 0; const byte NVS_BIG_ENDIAN = 0;
const byte NVS_Native = 0; const byte NVS_NATIVE = 0;
const byte NVS_XDR = 1; const byte NVS_XDR = 1;
/// <summary> /// <summary>
@@ -173,7 +175,7 @@ namespace DiscImageChef.Filesystems
} }
[StructLayout(LayoutKind.Sequential, Pack = 1)] [StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct DVA struct DVA
{ {
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public ulong[] word; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public ulong[] word;
} }
@@ -208,7 +210,7 @@ namespace DiscImageChef.Filesystems
public ZIO_Checksum checksum; public ZIO_Checksum checksum;
} }
const ulong Uberblock_Magic = 0x00BAB10C; const ulong UBERBLOCK_MAGIC = 0x00BAB10C;
[StructLayout(LayoutKind.Sequential, Pack = 1)] [StructLayout(LayoutKind.Sequential, Pack = 1)]
struct ZFS_Uberblock struct ZFS_Uberblock
@@ -222,19 +224,19 @@ namespace DiscImageChef.Filesystems
public ulong softwareVersion; public ulong softwareVersion;
} }
const uint ZFS_Magic = 0x58465342; const uint ZFS_MAGIC = 0x58465342;
public ZFS() public ZFS()
{ {
Name = "ZFS Filesystem Plugin"; Name = "ZFS Filesystem Plugin";
PluginUUID = new Guid("0750014F-A714-4692-A369-E23F6EC3659C"); PluginUuid = new Guid("0750014F-A714-4692-A369-E23F6EC3659C");
CurrentEncoding = Encoding.UTF8; CurrentEncoding = Encoding.UTF8;
} }
public ZFS(Encoding encoding) public ZFS(Encoding encoding)
{ {
Name = "ZFS Filesystem Plugin"; 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 // ZFS is always UTF-8
CurrentEncoding = Encoding.UTF8; CurrentEncoding = Encoding.UTF8;
} }
@@ -242,7 +244,7 @@ namespace DiscImageChef.Filesystems
public ZFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public ZFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "ZFS Filesystem Plugin"; 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 // ZFS is always UTF-8
CurrentEncoding = Encoding.UTF8; CurrentEncoding = Encoding.UTF8;
} }
@@ -258,16 +260,14 @@ namespace DiscImageChef.Filesystems
{ {
sector = imagePlugin.ReadSector(partition.Start + 31); sector = imagePlugin.ReadSector(partition.Start + 31);
magic = BitConverter.ToUInt64(sector, 0x1D8); 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; if(partition.Start + 16 >= partition.End) return false;
sector = imagePlugin.ReadSector(partition.Start + 16); sector = imagePlugin.ReadSector(partition.Start + 16);
magic = BitConverter.ToUInt64(sector, 0x1D8); magic = BitConverter.ToUInt64(sector, 0x1D8);
if(magic == ZEC_Magic || magic == ZEC_Cigam) return true; return magic == ZEC_MAGIC || magic == ZEC_CIGAM;
return false;
} }
public override void GetInformation(ImagePlugin imagePlugin, Partition partition, public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
@@ -281,42 +281,38 @@ namespace DiscImageChef.Filesystems
ulong nvlistOff = 32; ulong nvlistOff = 32;
uint nvlistLen = 114688 / imagePlugin.ImageInfo.SectorSize; uint nvlistLen = 114688 / imagePlugin.ImageInfo.SectorSize;
byte[] nvlist;
if(partition.Start + 31 < partition.End) if(partition.Start + 31 < partition.End)
{ {
sector = imagePlugin.ReadSector(partition.Start + 31); sector = imagePlugin.ReadSector(partition.Start + 31);
magic = BitConverter.ToUInt64(sector, 0x1D8); 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) if(partition.Start + 16 < partition.End)
{ {
sector = imagePlugin.ReadSector(partition.Start + 16); sector = imagePlugin.ReadSector(partition.Start + 16);
magic = BitConverter.ToUInt64(sector, 0x1D8); 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(); StringBuilder sb = new StringBuilder();
sb.AppendLine("ZFS filesystem"); sb.AppendLine("ZFS filesystem");
nvlist = imagePlugin.ReadSectors(partition.Start + nvlistOff, nvlistLen); byte[] nvlist = imagePlugin.ReadSectors(partition.Start + nvlistOff, nvlistLen);
Dictionary<string, NVS_Item> decodedNvList;
if(!DecodeNvList(nvlist, out decodedNvList)) sb.AppendLine("Could not decode nvlist"); sb.AppendLine(!DecodeNvList(nvlist, out Dictionary<string, NVS_Item> decodedNvList)
else sb.AppendLine(PrintNvList(decodedNvList)); ? "Could not decode nvlist"
: PrintNvList(decodedNvList));
information = sb.ToString(); information = sb.ToString();
NVS_Item tmpObj; XmlFsType = new FileSystemType {Type = "ZFS filesystem"};
if(decodedNvList.TryGetValue("name", out NVS_Item tmpObj)) XmlFsType.VolumeName = (string)tmpObj.value;
xmlFSType = new FileSystemType();
xmlFSType.Type = "ZFS filesystem";
if(decodedNvList.TryGetValue("name", out tmpObj)) xmlFSType.VolumeName = (string)tmpObj.value;
if(decodedNvList.TryGetValue("guid", out tmpObj)) if(decodedNvList.TryGetValue("guid", out tmpObj))
xmlFSType.VolumeSerial = $"{(ulong)tmpObj.value}"; XmlFsType.VolumeSerial = $"{(ulong)tmpObj.value}";
if(decodedNvList.TryGetValue("pool_guid", out tmpObj)) 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) static bool DecodeNvList(byte[] nvlist, out Dictionary<string, NVS_Item> decodedNvList)
@@ -346,7 +342,6 @@ namespace DiscImageChef.Filesystems
while(offset < nvlist.Length) while(offset < nvlist.Length)
{ {
uint nameLength; uint nameLength;
byte[] nameBytes;
NVS_Item item = new NVS_Item(); NVS_Item item = new NVS_Item();
int currOff = offset; int currOff = offset;
@@ -361,7 +356,7 @@ namespace DiscImageChef.Filesystems
nameLength = BigEndianBitConverter.ToUInt32(nvlist, offset); nameLength = BigEndianBitConverter.ToUInt32(nvlist, offset);
offset += 4; offset += 4;
if(nameLength % 4 > 0) nameLength += 4 - nameLength % 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); Array.Copy(nvlist, offset, nameBytes, 0, nameLength);
item.name = StringHandlers.CToString(nameBytes); item.name = StringHandlers.CToString(nameBytes);
offset += (int)nameLength; offset += (int)nameLength;
@@ -644,8 +639,7 @@ namespace DiscImageChef.Filesystems
byte[] subListBytes = new byte[item.encodedSize - (offset - currOff)]; byte[] subListBytes = new byte[item.encodedSize - (offset - currOff)];
Array.Copy(nvlist, offset, subListBytes, 0, subListBytes.Length); Array.Copy(nvlist, offset, subListBytes, 0, subListBytes.Length);
Dictionary<string, NVS_Item> subList; if(DecodeNvList(subListBytes, out Dictionary<string, NVS_Item> subList, true, littleEndian)) item.value = subList;
if(DecodeNvList(subListBytes, out subList, true, littleEndian)) item.value = subList;
else goto default; else goto default;
offset = (int)(currOff + item.encodedSize); offset = (int)(currOff + item.encodedSize);
break; break;

View File

@@ -32,6 +32,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
using DiscImageChef.CommonTypes; using DiscImageChef.CommonTypes;
@@ -42,6 +43,7 @@ using ufs_daddr_t = System.Int32;
namespace DiscImageChef.Filesystems namespace DiscImageChef.Filesystems
{ {
[SuppressMessage("ReSharper", "InconsistentNaming")]
public class dump : Filesystem public class dump : Filesystem
{ {
/// <summary>Magic number for old dump</summary> /// <summary>Magic number for old dump</summary>
@@ -211,24 +213,22 @@ namespace DiscImageChef.Filesystems
public dump() public dump()
{ {
Name = "dump(8) Plugin"; 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"); CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
} }
public dump(Encoding encoding) public dump(Encoding encoding)
{ {
Name = "dump(8) Plugin"; Name = "dump(8) Plugin";
PluginUUID = new Guid("E53B4D28-C858-4800-B092-DDAE80D361B9"); PluginUuid = new Guid("E53B4D28-C858-4800-B092-DDAE80D361B9");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public dump(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public dump(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "dump(8) Plugin"; Name = "dump(8) Plugin";
PluginUUID = new Guid("E53B4D28-C858-4800-B092-DDAE80D361B9"); PluginUuid = new Guid("E53B4D28-C858-4800-B092-DDAE80D361B9");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public override bool Identify(ImagePlugin imagePlugin, Partition partition) public override bool Identify(ImagePlugin imagePlugin, Partition partition)
@@ -307,13 +307,10 @@ namespace DiscImageChef.Filesystems
bool useOld = false; bool useOld = false;
bool useAix = false; bool useAix = false;
bool useNew = false;
if(newHdr.c_magic == OFS_MAGIC || newHdr.c_magic == NFS_MAGIC || newHdr.c_magic == OFS_CIGAM || 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) 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) if(newHdr.c_magic == OFS_CIGAM || newHdr.c_magic == NFS_CIGAM || newHdr.c_magic == UFS2_CIGAM)
newHdr = BigEndianMarshal.ByteArrayToStructureBigEndian<s_spcl>(sector); newHdr = BigEndianMarshal.ByteArrayToStructureBigEndian<s_spcl>(sector);
} }
@@ -340,71 +337,71 @@ namespace DiscImageChef.Filesystems
StringBuilder sb = new StringBuilder(); 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) if(useOld)
{ {
xmlFSType.Type = "Old 16-bit dump(8)"; XmlFsType.Type = "Old 16-bit dump(8)";
sb.AppendLine(xmlFSType.Type); sb.AppendLine(XmlFsType.Type);
if(oldHdr.c_date > 0) if(oldHdr.c_date > 0)
{ {
xmlFSType.CreationDate = DateHandlers.UNIXToDateTime(oldHdr.c_date); XmlFsType.CreationDate = DateHandlers.UNIXToDateTime(oldHdr.c_date);
xmlFSType.CreationDateSpecified = true; XmlFsType.CreationDateSpecified = true;
sb.AppendFormat("Dump created on {0}", xmlFSType.CreationDate).AppendLine(); sb.AppendFormat("Dump created on {0}", XmlFsType.CreationDate).AppendLine();
} }
if(oldHdr.c_ddate > 0) if(oldHdr.c_ddate > 0)
{ {
xmlFSType.BackupDate = DateHandlers.UNIXToDateTime(oldHdr.c_ddate); XmlFsType.BackupDate = DateHandlers.UNIXToDateTime(oldHdr.c_ddate);
xmlFSType.BackupDateSpecified = true; XmlFsType.BackupDateSpecified = true;
sb.AppendFormat("Previous dump created on {0}", xmlFSType.BackupDate).AppendLine(); sb.AppendFormat("Previous dump created on {0}", XmlFsType.BackupDate).AppendLine();
} }
sb.AppendFormat("Dump volume number: {0}", oldHdr.c_volume).AppendLine(); sb.AppendFormat("Dump volume number: {0}", oldHdr.c_volume).AppendLine();
} }
else if(useAix) else if(useAix)
{ {
xmlFSType.Type = "AIX dump(8)"; XmlFsType.Type = "AIX dump(8)";
sb.AppendLine(xmlFSType.Type); sb.AppendLine(XmlFsType.Type);
if(aixHdr.c_date > 0) if(aixHdr.c_date > 0)
{ {
xmlFSType.CreationDate = DateHandlers.UNIXToDateTime(aixHdr.c_date); XmlFsType.CreationDate = DateHandlers.UNIXToDateTime(aixHdr.c_date);
xmlFSType.CreationDateSpecified = true; XmlFsType.CreationDateSpecified = true;
sb.AppendFormat("Dump created on {0}", xmlFSType.CreationDate).AppendLine(); sb.AppendFormat("Dump created on {0}", XmlFsType.CreationDate).AppendLine();
} }
if(aixHdr.c_ddate > 0) if(aixHdr.c_ddate > 0)
{ {
xmlFSType.BackupDate = DateHandlers.UNIXToDateTime(aixHdr.c_ddate); XmlFsType.BackupDate = DateHandlers.UNIXToDateTime(aixHdr.c_ddate);
xmlFSType.BackupDateSpecified = true; XmlFsType.BackupDateSpecified = true;
sb.AppendFormat("Previous dump created on {0}", xmlFSType.BackupDate).AppendLine(); sb.AppendFormat("Previous dump created on {0}", XmlFsType.BackupDate).AppendLine();
} }
sb.AppendFormat("Dump volume number: {0}", aixHdr.c_volume).AppendLine(); sb.AppendFormat("Dump volume number: {0}", aixHdr.c_volume).AppendLine();
} }
else else
{ {
xmlFSType.Type = "dump(8)"; XmlFsType.Type = "dump(8)";
sb.AppendLine(xmlFSType.Type); sb.AppendLine(XmlFsType.Type);
if(newHdr.c_ndate > 0) if(newHdr.c_ndate > 0)
{ {
xmlFSType.CreationDate = DateHandlers.UNIXToDateTime(newHdr.c_ndate); XmlFsType.CreationDate = DateHandlers.UNIXToDateTime(newHdr.c_ndate);
xmlFSType.CreationDateSpecified = true; XmlFsType.CreationDateSpecified = true;
sb.AppendFormat("Dump created on {0}", xmlFSType.CreationDate).AppendLine(); sb.AppendFormat("Dump created on {0}", XmlFsType.CreationDate).AppendLine();
} }
else if(newHdr.c_date > 0) else if(newHdr.c_date > 0)
{ {
xmlFSType.CreationDate = DateHandlers.UNIXToDateTime(newHdr.c_date); XmlFsType.CreationDate = DateHandlers.UNIXToDateTime(newHdr.c_date);
xmlFSType.CreationDateSpecified = true; XmlFsType.CreationDateSpecified = true;
sb.AppendFormat("Dump created on {0}", xmlFSType.CreationDate).AppendLine(); sb.AppendFormat("Dump created on {0}", XmlFsType.CreationDate).AppendLine();
} }
if(newHdr.c_nddate > 0) if(newHdr.c_nddate > 0)
{ {
xmlFSType.BackupDate = DateHandlers.UNIXToDateTime(newHdr.c_nddate); XmlFsType.BackupDate = DateHandlers.UNIXToDateTime(newHdr.c_nddate);
xmlFSType.BackupDateSpecified = true; XmlFsType.BackupDateSpecified = true;
sb.AppendFormat("Previous dump created on {0}", xmlFSType.BackupDate).AppendLine(); sb.AppendFormat("Previous dump created on {0}", XmlFsType.BackupDate).AppendLine();
} }
else if(newHdr.c_ddate > 0) else if(newHdr.c_ddate > 0)
{ {
xmlFSType.BackupDate = DateHandlers.UNIXToDateTime(newHdr.c_ddate); XmlFsType.BackupDate = DateHandlers.UNIXToDateTime(newHdr.c_ddate);
xmlFSType.BackupDateSpecified = true; XmlFsType.BackupDateSpecified = true;
sb.AppendFormat("Previous dump created on {0}", xmlFSType.BackupDate).AppendLine(); sb.AppendFormat("Previous dump created on {0}", XmlFsType.BackupDate).AppendLine();
} }
sb.AppendFormat("Dump volume number: {0}", newHdr.c_volume).AppendLine(); sb.AppendFormat("Dump volume number: {0}", newHdr.c_volume).AppendLine();
sb.AppendFormat("Dump level: {0}", newHdr.c_level).AppendLine(); sb.AppendFormat("Dump level: {0}", newHdr.c_level).AppendLine();

View File

@@ -47,24 +47,22 @@ namespace DiscImageChef.Filesystems
public exFAT() public exFAT()
{ {
Name = "Microsoft Extended File Allocation Table"; 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"); CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
} }
public exFAT(Encoding encoding) public exFAT(Encoding encoding)
{ {
Name = "Microsoft Extended File Allocation Table"; Name = "Microsoft Extended File Allocation Table";
PluginUUID = new Guid("8271D088-1533-4CB3-AC28-D802B68BB95C"); PluginUuid = new Guid("8271D088-1533-4CB3-AC28-D802B68BB95C");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public exFAT(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public exFAT(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "Microsoft Extended File Allocation Table"; Name = "Microsoft Extended File Allocation Table";
PluginUUID = new Guid("8271D088-1533-4CB3-AC28-D802B68BB95C"); PluginUuid = new Guid("8271D088-1533-4CB3-AC28-D802B68BB95C");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public override bool Identify(ImagePlugin imagePlugin, Partition partition) public override bool Identify(ImagePlugin imagePlugin, Partition partition)
@@ -74,10 +72,9 @@ namespace DiscImageChef.Filesystems
byte[] vbrSector = imagePlugin.ReadSector(0 + partition.Start); byte[] vbrSector = imagePlugin.ReadSector(0 + partition.Start);
if(vbrSector.Length < 512) return false; if(vbrSector.Length < 512) return false;
VolumeBootRecord vbr;
IntPtr vbrPtr = Marshal.AllocHGlobal(512); IntPtr vbrPtr = Marshal.AllocHGlobal(512);
Marshal.Copy(vbrSector, 0, vbrPtr, 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); Marshal.FreeHGlobal(vbrPtr);
return Signature.SequenceEqual(vbr.signature); return Signature.SequenceEqual(vbr.signature);
@@ -88,27 +85,24 @@ namespace DiscImageChef.Filesystems
information = ""; information = "";
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType();
byte[] vbrSector = imagePlugin.ReadSector(0 + partition.Start); byte[] vbrSector = imagePlugin.ReadSector(0 + partition.Start);
VolumeBootRecord vbr;
IntPtr vbrPtr = Marshal.AllocHGlobal(512); IntPtr vbrPtr = Marshal.AllocHGlobal(512);
Marshal.Copy(vbrSector, 0, vbrPtr, 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); Marshal.FreeHGlobal(vbrPtr);
byte[] parametersSector = imagePlugin.ReadSector(9 + partition.Start); byte[] parametersSector = imagePlugin.ReadSector(9 + partition.Start);
OemParameterTable parametersTable;
IntPtr parametersPtr = Marshal.AllocHGlobal(512); IntPtr parametersPtr = Marshal.AllocHGlobal(512);
Marshal.Copy(parametersSector, 0, parametersPtr, 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); Marshal.FreeHGlobal(parametersPtr);
byte[] chkSector = imagePlugin.ReadSector(11 + partition.Start); byte[] chkSector = imagePlugin.ReadSector(11 + partition.Start);
ChecksumSector chksector;
IntPtr chkPtr = Marshal.AllocHGlobal(512); IntPtr chkPtr = Marshal.AllocHGlobal(512);
Marshal.Copy(chkSector, 0, chkPtr, 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); Marshal.FreeHGlobal(chkPtr);
sb.AppendLine("Microsoft exFAT"); sb.AppendLine("Microsoft exFAT");
@@ -152,11 +146,11 @@ namespace DiscImageChef.Filesystems
sb.AppendFormat("Checksum 0x{0:X8}", chksector.checksum[0]).AppendLine(); sb.AppendFormat("Checksum 0x{0:X8}", chksector.checksum[0]).AppendLine();
xmlFSType.ClusterSize = (1 << vbr.sectorShift) * (1 << vbr.clusterShift); XmlFsType.ClusterSize = (1 << vbr.sectorShift) * (1 << vbr.clusterShift);
xmlFSType.Clusters = vbr.clusterHeapLength; XmlFsType.Clusters = vbr.clusterHeapLength;
xmlFSType.Dirty = vbr.flags.HasFlag(VolumeFlags.VolumeDirty); XmlFsType.Dirty = vbr.flags.HasFlag(VolumeFlags.VolumeDirty);
xmlFSType.Type = "exFAT"; XmlFsType.Type = "exFAT";
xmlFSType.VolumeSerial = $"{vbr.volumeSerial:X8}"; XmlFsType.VolumeSerial = $"{vbr.volumeSerial:X8}";
information = sb.ToString(); information = sb.ToString();
} }

View File

@@ -32,6 +32,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
using DiscImageChef.CommonTypes; using DiscImageChef.CommonTypes;
@@ -43,51 +44,47 @@ namespace DiscImageChef.Filesystems
// Information from the Linux kernel // Information from the Linux kernel
public class ext2FS : Filesystem public class ext2FS : Filesystem
{ {
const int sbPos = 0x400; const int SB_POS = 0x400;
public ext2FS() public ext2FS()
{ {
Name = "Linux extended Filesystem 2, 3 and 4"; 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"); CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
} }
public ext2FS(Encoding encoding) public ext2FS(Encoding encoding)
{ {
Name = "Linux extended Filesystem 2, 3 and 4"; Name = "Linux extended Filesystem 2, 3 and 4";
PluginUUID = new Guid("6AA91B88-150B-4A7B-AD56-F84FB2DF4184"); PluginUuid = new Guid("6AA91B88-150B-4A7B-AD56-F84FB2DF4184");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public ext2FS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public ext2FS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "Linux extended Filesystem 2, 3 and 4"; Name = "Linux extended Filesystem 2, 3 and 4";
PluginUUID = new Guid("6AA91B88-150B-4A7B-AD56-F84FB2DF4184"); PluginUuid = new Guid("6AA91B88-150B-4A7B-AD56-F84FB2DF4184");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public override bool Identify(ImagePlugin imagePlugin, Partition partition) public override bool Identify(ImagePlugin imagePlugin, Partition partition)
{ {
ulong sbSector = sbPos / imagePlugin.GetSectorSize(); ulong sbSectorOff = SB_POS / imagePlugin.GetSectorSize();
uint sbOff = sbPos % 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)); int sbSizeInBytes = Marshal.SizeOf(typeof(ext2FSSuperBlock));
uint sb_size_in_sectors = (uint)(sb_size_in_bytes / imagePlugin.GetSectorSize()); uint sbSizeInSectors = (uint)(sbSizeInBytes / imagePlugin.GetSectorSize());
if(sb_size_in_bytes % imagePlugin.GetSectorSize() > 0) sb_size_in_sectors++; if(sbSizeInBytes % imagePlugin.GetSectorSize() > 0) sbSizeInSectors++;
byte[] sb_sector = imagePlugin.ReadSectors(sbSector + partition.Start, sb_size_in_sectors); byte[] sbSector = imagePlugin.ReadSectors(sbSectorOff + partition.Start, sbSizeInSectors);
byte[] sb = new byte[sb_size_in_bytes]; byte[] sb = new byte[sbSizeInBytes];
Array.Copy(sb_sector, sbOff, sb, 0, sb_size_in_bytes); Array.Copy(sbSector, sbOff, sb, 0, sbSizeInBytes);
ushort magic = BitConverter.ToUInt16(sb, 0x038); ushort magic = BitConverter.ToUInt16(sb, 0x038);
if(magic == ext2FSMagic || magic == ext2OldFSMagic) return true; return magic == EXT2_MAGIC || magic == EXT2_MAGIC_OLD;
return false;
} }
public override void GetInformation(ImagePlugin imagePlugin, Partition partition, public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
@@ -97,34 +94,33 @@ namespace DiscImageChef.Filesystems
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
ext2FSSuperBlock supblk = new ext2FSSuperBlock(); bool newExt2 = false;
bool new_ext2 = false;
bool ext3 = false; bool ext3 = false;
bool ext4 = false; bool ext4 = false;
int sb_size_in_bytes = Marshal.SizeOf(typeof(ext2FSSuperBlock)); int sbSizeInBytes = Marshal.SizeOf(typeof(ext2FSSuperBlock));
uint sb_size_in_sectors = (uint)(sb_size_in_bytes / imagePlugin.GetSectorSize()); uint sbSizeInSectors = (uint)(sbSizeInBytes / imagePlugin.GetSectorSize());
if(sb_size_in_bytes % imagePlugin.GetSectorSize() > 0) sb_size_in_sectors++; if(sbSizeInBytes % imagePlugin.GetSectorSize() > 0) sbSizeInSectors++;
ulong sbSector = sbPos / imagePlugin.GetSectorSize(); ulong sbSectorOff = SB_POS / imagePlugin.GetSectorSize();
uint sbOff = sbPos % imagePlugin.GetSectorSize(); uint sbOff = SB_POS % imagePlugin.GetSectorSize();
byte[] sb_sector = imagePlugin.ReadSectors(sbSector + partition.Start, sb_size_in_sectors); byte[] sbSector = imagePlugin.ReadSectors(sbSectorOff + partition.Start, sbSizeInSectors);
byte[] sblock = new byte[sb_size_in_bytes]; byte[] sblock = new byte[sbSizeInBytes];
Array.Copy(sb_sector, sbOff, sblock, 0, sb_size_in_bytes); Array.Copy(sbSector, sbOff, sblock, 0, sbSizeInBytes);
IntPtr sbPtr = Marshal.AllocHGlobal(sb_size_in_bytes); IntPtr sbPtr = Marshal.AllocHGlobal(sbSizeInBytes);
Marshal.Copy(sblock, 0, sbPtr, sb_size_in_bytes); Marshal.Copy(sblock, 0, sbPtr, sbSizeInBytes);
supblk = (ext2FSSuperBlock)Marshal.PtrToStructure(sbPtr, typeof(ext2FSSuperBlock)); ext2FSSuperBlock supblk = (ext2FSSuperBlock)Marshal.PtrToStructure(sbPtr, typeof(ext2FSSuperBlock));
Marshal.FreeHGlobal(sbPtr); Marshal.FreeHGlobal(sbPtr);
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType();
switch(supblk.magic) { switch(supblk.magic) {
case ext2OldFSMagic: case EXT2_MAGIC_OLD:
sb.AppendLine("ext2 (old) filesystem"); sb.AppendLine("ext2 (old) filesystem");
xmlFSType.Type = "ext2"; XmlFsType.Type = "ext2";
break; break;
case ext2FSMagic: case EXT2_MAGIC:
ext3 |= (supblk.ftr_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) == EXT3_FEATURE_COMPAT_HAS_JOURNAL || 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_RECOVER) == EXT3_FEATURE_INCOMPAT_RECOVER ||
(supblk.ftr_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) == EXT3_FEATURE_INCOMPAT_JOURNAL_DEV; (supblk.ftr_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) == EXT3_FEATURE_INCOMPAT_JOURNAL_DEV;
@@ -143,22 +139,22 @@ namespace DiscImageChef.Filesystems
ext4 = true; ext4 = true;
} }
new_ext2 |= !ext3 && !ext4; newExt2 |= !ext3 && !ext4;
if(new_ext2) if(newExt2)
{ {
sb.AppendLine("ext2 filesystem"); sb.AppendLine("ext2 filesystem");
xmlFSType.Type = "ext2"; XmlFsType.Type = "ext2";
} }
if(ext3) if(ext3)
{ {
sb.AppendLine("ext3 filesystem"); sb.AppendLine("ext3 filesystem");
xmlFSType.Type = "ext3"; XmlFsType.Type = "ext3";
} }
if(ext4) if(ext4)
{ {
sb.AppendLine("ext4 filesystem"); sb.AppendLine("ext4 filesystem");
xmlFSType.Type = "ext4"; XmlFsType.Type = "ext4";
} }
break; break;
default: default:
@@ -166,81 +162,80 @@ namespace DiscImageChef.Filesystems
return; return;
} }
string ext_os; string extOs;
switch(supblk.creator_os) switch(supblk.creator_os)
{ {
case EXT2_OS_FREEBSD: case EXT2_OS_FREEBSD:
ext_os = "FreeBSD"; extOs = "FreeBSD";
break; break;
case EXT2_OS_HURD: case EXT2_OS_HURD:
ext_os = "Hurd"; extOs = "Hurd";
break; break;
case EXT2_OS_LINUX: case EXT2_OS_LINUX:
ext_os = "Linux"; extOs = "Linux";
break; break;
case EXT2_OS_LITES: case EXT2_OS_LITES:
ext_os = "Lites"; extOs = "Lites";
break; break;
case EXT2_OS_MASIX: case EXT2_OS_MASIX:
ext_os = "MasIX"; extOs = "MasIX";
break; break;
default: default:
ext_os = $"Unknown OS ({supblk.creator_os})"; extOs = $"Unknown OS ({supblk.creator_os})";
break; break;
} }
xmlFSType.SystemIdentifier = ext_os; XmlFsType.SystemIdentifier = extOs;
if(supblk.mkfs_t > 0) if(supblk.mkfs_t > 0)
{ {
sb.AppendFormat("Volume was created on {0} for {1}", DateHandlers.UNIXUnsignedToDateTime(supblk.mkfs_t), sb.AppendFormat("Volume was created on {0} for {1}", DateHandlers.UNIXUnsignedToDateTime(supblk.mkfs_t),
ext_os).AppendLine(); extOs).AppendLine();
xmlFSType.CreationDate = DateHandlers.UNIXUnsignedToDateTime(supblk.mkfs_t); XmlFsType.CreationDate = DateHandlers.UNIXUnsignedToDateTime(supblk.mkfs_t);
xmlFSType.CreationDateSpecified = true; 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[] tempBytes = new byte[8];
byte[] temp_bytes = new byte[8];
ulong blocks, reserved, free; ulong blocks, reserved, free;
if((supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_64BIT) == EXT4_FEATURE_INCOMPAT_64BIT) if((supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_64BIT) == EXT4_FEATURE_INCOMPAT_64BIT)
{ {
temp_lo = BitConverter.GetBytes(supblk.blocks); byte[] tempLo = BitConverter.GetBytes(supblk.blocks);
temp_hi = BitConverter.GetBytes(supblk.blocks_hi); byte[] tempHi = BitConverter.GetBytes(supblk.blocks_hi);
temp_bytes[0] = temp_lo[0]; tempBytes[0] = tempLo[0];
temp_bytes[1] = temp_lo[1]; tempBytes[1] = tempLo[1];
temp_bytes[2] = temp_lo[2]; tempBytes[2] = tempLo[2];
temp_bytes[3] = temp_lo[3]; tempBytes[3] = tempLo[3];
temp_bytes[4] = temp_hi[0]; tempBytes[4] = tempHi[0];
temp_bytes[5] = temp_hi[1]; tempBytes[5] = tempHi[1];
temp_bytes[6] = temp_hi[2]; tempBytes[6] = tempHi[2];
temp_bytes[7] = temp_hi[3]; tempBytes[7] = tempHi[3];
blocks = BitConverter.ToUInt64(temp_bytes, 0); blocks = BitConverter.ToUInt64(tempBytes, 0);
temp_lo = BitConverter.GetBytes(supblk.reserved_blocks); tempLo = BitConverter.GetBytes(supblk.reserved_blocks);
temp_hi = BitConverter.GetBytes(supblk.reserved_blocks_hi); tempHi = BitConverter.GetBytes(supblk.reserved_blocks_hi);
temp_bytes[0] = temp_lo[0]; tempBytes[0] = tempLo[0];
temp_bytes[1] = temp_lo[1]; tempBytes[1] = tempLo[1];
temp_bytes[2] = temp_lo[2]; tempBytes[2] = tempLo[2];
temp_bytes[3] = temp_lo[3]; tempBytes[3] = tempLo[3];
temp_bytes[4] = temp_hi[0]; tempBytes[4] = tempHi[0];
temp_bytes[5] = temp_hi[1]; tempBytes[5] = tempHi[1];
temp_bytes[6] = temp_hi[2]; tempBytes[6] = tempHi[2];
temp_bytes[7] = temp_hi[3]; tempBytes[7] = tempHi[3];
reserved = BitConverter.ToUInt64(temp_bytes, 0); reserved = BitConverter.ToUInt64(tempBytes, 0);
temp_lo = BitConverter.GetBytes(supblk.free_blocks); tempLo = BitConverter.GetBytes(supblk.free_blocks);
temp_hi = BitConverter.GetBytes(supblk.free_blocks_hi); tempHi = BitConverter.GetBytes(supblk.free_blocks_hi);
temp_bytes[0] = temp_lo[0]; tempBytes[0] = tempLo[0];
temp_bytes[1] = temp_lo[1]; tempBytes[1] = tempLo[1];
temp_bytes[2] = temp_lo[2]; tempBytes[2] = tempLo[2];
temp_bytes[3] = temp_lo[3]; tempBytes[3] = tempLo[3];
temp_bytes[4] = temp_hi[0]; tempBytes[4] = tempHi[0];
temp_bytes[5] = temp_hi[1]; tempBytes[5] = tempHi[1];
temp_bytes[6] = temp_hi[2]; tempBytes[6] = tempHi[2];
temp_bytes[7] = temp_hi[3]; tempBytes[7] = tempHi[3];
free = BitConverter.ToUInt64(temp_bytes, 0); free = BitConverter.ToUInt64(tempBytes, 0);
} }
else else
{ {
@@ -255,8 +250,8 @@ namespace DiscImageChef.Filesystems
sb.AppendFormat("Volume has {0} blocks of {1} bytes, for a total of {2} bytes", blocks, 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)) 1024 << (int)supblk.block_size, blocks * (ulong)(1024 << (int)supblk.block_size))
.AppendLine(); .AppendLine();
xmlFSType.Clusters = (long)blocks; XmlFsType.Clusters = (long)blocks;
xmlFSType.ClusterSize = 1024 << (int)supblk.block_size; XmlFsType.ClusterSize = 1024 << (int)supblk.block_size;
if(supblk.mount_t > 0 || supblk.mount_c > 0) if(supblk.mount_t > 0 || supblk.mount_c > 0)
{ {
if(supblk.mount_t > 0) if(supblk.mount_t > 0)
@@ -302,17 +297,17 @@ namespace DiscImageChef.Filesystems
{ {
sb.AppendFormat("Last written on {0}", DateHandlers.UNIXUnsignedToDateTime(supblk.write_t)) sb.AppendFormat("Last written on {0}", DateHandlers.UNIXUnsignedToDateTime(supblk.write_t))
.AppendLine(); .AppendLine();
xmlFSType.ModificationDate = DateHandlers.UNIXUnsignedToDateTime(supblk.write_t); XmlFsType.ModificationDate = DateHandlers.UNIXUnsignedToDateTime(supblk.write_t);
xmlFSType.ModificationDateSpecified = true; XmlFsType.ModificationDateSpecified = true;
} }
else sb.AppendLine("Volume has never been written"); else sb.AppendLine("Volume has never been written");
xmlFSType.Dirty = true; XmlFsType.Dirty = true;
switch(supblk.state) switch(supblk.state)
{ {
case EXT2_VALID_FS: case EXT2_VALID_FS:
sb.AppendLine("Volume is clean"); sb.AppendLine("Volume is clean");
xmlFSType.Dirty = false; XmlFsType.Dirty = false;
break; break;
case EXT2_ERROR_FS: case EXT2_ERROR_FS:
sb.AppendLine("Volume is dirty"); sb.AppendLine("Volume is dirty");
@@ -329,7 +324,7 @@ namespace DiscImageChef.Filesystems
{ {
sb.AppendFormat("Volume name: \"{0}\"", StringHandlers.CToString(supblk.volume_name, CurrentEncoding)) sb.AppendFormat("Volume name: \"{0}\"", StringHandlers.CToString(supblk.volume_name, CurrentEncoding))
.AppendLine(); .AppendLine();
xmlFSType.VolumeName = StringHandlers.CToString(supblk.volume_name, CurrentEncoding); XmlFsType.VolumeName = StringHandlers.CToString(supblk.volume_name, CurrentEncoding);
} }
switch(supblk.err_behaviour) switch(supblk.err_behaviour)
@@ -355,15 +350,15 @@ namespace DiscImageChef.Filesystems
if(supblk.uuid != Guid.Empty) if(supblk.uuid != Guid.Empty)
{ {
sb.AppendFormat("Volume UUID: {0}", supblk.uuid).AppendLine(); sb.AppendFormat("Volume UUID: {0}", supblk.uuid).AppendLine();
xmlFSType.VolumeSerial = supblk.uuid.ToString(); XmlFsType.VolumeSerial = supblk.uuid.ToString();
} }
if(supblk.kbytes_written > 0) if(supblk.kbytes_written > 0)
sb.AppendFormat("{0} KiB has been written on volume", supblk.kbytes_written).AppendLine(); sb.AppendFormat("{0} KiB has been written on volume", supblk.kbytes_written).AppendLine();
sb.AppendFormat("{0} reserved and {1} free blocks", reserved, free).AppendLine(); sb.AppendFormat("{0} reserved and {1} free blocks", reserved, free).AppendLine();
xmlFSType.FreeClusters = (long)free; XmlFsType.FreeClusters = (long)free;
xmlFSType.FreeClustersSpecified = true; XmlFsType.FreeClustersSpecified = true;
sb.AppendFormat("{0} inodes with {1} free inodes ({2}%)", supblk.inodes, supblk.free_inodes, sb.AppendFormat("{0} inodes with {1} free inodes ({2}%)", supblk.inodes, supblk.free_inodes,
supblk.free_inodes * 100 / supblk.inodes).AppendLine(); supblk.free_inodes * 100 / supblk.inodes).AppendLine();
if(supblk.first_inode > 0) sb.AppendFormat("First inode is {0}", supblk.first_inode).AppendLine(); if(supblk.first_inode > 0) sb.AppendFormat("First inode is {0}", supblk.first_inode).AppendLine();
@@ -533,14 +528,15 @@ namespace DiscImageChef.Filesystems
/// <summary> /// <summary>
/// Same magic for ext2, ext3 and ext4 /// Same magic for ext2, ext3 and ext4
/// </summary> /// </summary>
const ushort ext2FSMagic = 0xEF53; const ushort EXT2_MAGIC = 0xEF53;
const ushort ext2OldFSMagic = 0xEF51; const ushort EXT2_MAGIC_OLD = 0xEF51;
/// <summary> /// <summary>
/// ext2/3/4 superblock /// ext2/3/4 superblock
/// </summary> /// </summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)] [StructLayout(LayoutKind.Sequential, Pack = 1)]
[SuppressMessage("ReSharper", "InconsistentNaming")]
struct ext2FSSuperBlock struct ext2FSSuperBlock
{ {
/// <summary>0x000, inodes on volume</summary> /// <summary>0x000, inodes on volume</summary>

View File

@@ -32,6 +32,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Text; using System.Text;
using DiscImageChef.CommonTypes; using DiscImageChef.CommonTypes;
using DiscImageChef.DiscImages; using DiscImageChef.DiscImages;
@@ -42,47 +43,45 @@ namespace DiscImageChef.Filesystems
// Information from the Linux kernel // Information from the Linux kernel
public class extFS : Filesystem public class extFS : Filesystem
{ {
const int sbPos = 0x400; const int SB_POS = 0x400;
public extFS() public extFS()
{ {
Name = "Linux extended Filesystem"; 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"); CurrentEncoding = Encoding.GetEncoding("iso-8859-15");
} }
public extFS(Encoding encoding) public extFS(Encoding encoding)
{ {
Name = "Linux extended Filesystem"; Name = "Linux extended Filesystem";
PluginUUID = new Guid("076CB3A2-08C2-4D69-BC8A-FCAA2E502BE2"); PluginUuid = new Guid("076CB3A2-08C2-4D69-BC8A-FCAA2E502BE2");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public extFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding) public extFS(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{ {
Name = "Linux extended Filesystem"; Name = "Linux extended Filesystem";
PluginUUID = new Guid("076CB3A2-08C2-4D69-BC8A-FCAA2E502BE2"); PluginUuid = new Guid("076CB3A2-08C2-4D69-BC8A-FCAA2E502BE2");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("iso-8859-15"); CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
else CurrentEncoding = encoding;
} }
public override bool Identify(ImagePlugin imagePlugin, Partition partition) public override bool Identify(ImagePlugin imagePlugin, Partition partition)
{ {
if(imagePlugin.GetSectorSize() < 512) return false; if(imagePlugin.GetSectorSize() < 512) return false;
ulong sbSector = sbPos / imagePlugin.GetSectorSize(); ulong sbSectorOff = SB_POS / imagePlugin.GetSectorSize();
uint sbOff = sbPos % 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]; 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); ushort magic = BitConverter.ToUInt16(sb, 0x038);
return magic == extFSMagic; return magic == EXT_MAGIC;
} }
public override void GetInformation(ImagePlugin imagePlugin, Partition partition, public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
@@ -94,44 +93,48 @@ namespace DiscImageChef.Filesystems
if(imagePlugin.GetSectorSize() < 512) return; if(imagePlugin.GetSectorSize() < 512) return;
ulong sbSector = sbPos / imagePlugin.GetSectorSize(); ulong sbSectorOff = SB_POS / imagePlugin.GetSectorSize();
uint sbOff = sbPos % 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[] sblock = imagePlugin.ReadSector(sbSectorOff + partition.Start);
byte[] sb_sector = new byte[512]; byte[] sbSector = new byte[512];
Array.Copy(sblock, sbOff, sb_sector, 0, 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.AppendLine("ext filesystem");
sb.AppendFormat("{0} zones on volume", ext_sb.zones); sb.AppendFormat("{0} zones on volume", extSb.zones);
sb.AppendFormat("{0} free blocks ({1} bytes)", ext_sb.freecountblk, ext_sb.freecountblk * 1024); sb.AppendFormat("{0} free blocks ({1} bytes)", extSb.freecountblk, extSb.freecountblk * 1024);
sb.AppendFormat("{0} inodes on volume, {1} free ({2}%)", ext_sb.inodes, ext_sb.freecountind, sb.AppendFormat("{0} inodes on volume, {1} free ({2}%)", extSb.inodes, extSb.freecountind,
ext_sb.freecountind * 100 / ext_sb.inodes); extSb.freecountind * 100 / extSb.inodes);
sb.AppendFormat("First free inode is {0}", ext_sb.firstfreeind); sb.AppendFormat("First free inode is {0}", extSb.firstfreeind);
sb.AppendFormat("First free block is {0}", ext_sb.firstfreeblk); sb.AppendFormat("First free block is {0}", extSb.firstfreeblk);
sb.AppendFormat("First data zone is {0}", ext_sb.firstdatazone); sb.AppendFormat("First data zone is {0}", extSb.firstdatazone);
sb.AppendFormat("Log zone size: {0}", ext_sb.logzonesize); sb.AppendFormat("Log zone size: {0}", extSb.logzonesize);
sb.AppendFormat("Max zone size: {0}", ext_sb.maxsize); sb.AppendFormat("Max zone size: {0}", extSb.maxsize);
xmlFSType = new FileSystemType(); XmlFsType = new FileSystemType
xmlFSType.Type = "ext"; {
xmlFSType.FreeClusters = ext_sb.freecountblk; Type = "ext",
xmlFSType.FreeClustersSpecified = true; FreeClusters = extSb.freecountblk,
xmlFSType.ClusterSize = 1024; FreeClustersSpecified = true,
xmlFSType.Clusters = (long)((partition.End - partition.Start + 1) * imagePlugin.GetSectorSize() / 1024); ClusterSize = 1024,
Clusters = (long)((partition.End - partition.Start + 1) * imagePlugin.GetSectorSize() / 1024)
};
information = sb.ToString(); information = sb.ToString();
} }
@@ -139,11 +142,12 @@ namespace DiscImageChef.Filesystems
/// <summary> /// <summary>
/// ext superblock magic /// ext superblock magic
/// </summary> /// </summary>
const ushort extFSMagic = 0x137D; const ushort EXT_MAGIC = 0x137D;
/// <summary> /// <summary>
/// ext superblock /// ext superblock
/// </summary> /// </summary>
[SuppressMessage("ReSharper", "InconsistentNaming")]
struct extFSSuperBlock struct extFSSuperBlock
{ {
/// <summary>0x000, inodes on volume</summary> /// <summary>0x000, inodes on volume</summary>

View File

@@ -67,7 +67,7 @@ namespace DiscImageChef.Commands
if(formatsOptions.Verbose) DicConsole.VerboseWriteLine("GUID\t\t\t\t\tPlugin"); if(formatsOptions.Verbose) DicConsole.VerboseWriteLine("GUID\t\t\t\t\tPlugin");
foreach(KeyValuePair<string, Filesystem> kvp in plugins.PluginsList) foreach(KeyValuePair<string, Filesystem> kvp in plugins.PluginsList)
if(formatsOptions.Verbose) 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); else DicConsole.WriteLine(kvp.Value.Name);
DicConsole.WriteLine(); DicConsole.WriteLine();