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

View File

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

View File

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

View File

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

View File

@@ -77,14 +77,14 @@ namespace DiscImageChef.Filesystems.AppleDOS
public AppleDOS()
{
Name = "Apple DOS File System";
PluginUUID = new Guid("8658A1E9-B2E7-4BCC-9638-157A31B0A700\n");
PluginUuid = new Guid("8658A1E9-B2E7-4BCC-9638-157A31B0A700\n");
CurrentEncoding = new LisaRoman();
}
public AppleDOS(Encoding encoding)
{
Name = "Apple DOS File System";
PluginUUID = new Guid("8658A1E9-B2E7-4BCC-9638-157A31B0A700\n");
PluginUuid = new Guid("8658A1E9-B2E7-4BCC-9638-157A31B0A700\n");
// TODO: Until Apple ][ encoding is implemented
CurrentEncoding = new LisaRoman();
}
@@ -94,7 +94,7 @@ namespace DiscImageChef.Filesystems.AppleDOS
device = imagePlugin;
start = partition.Start;
Name = "Apple DOS File System";
PluginUUID = new Guid("8658A1E9-B2E7-4BCC-9638-157A31B0A700\n");
PluginUuid = new Guid("8658A1E9-B2E7-4BCC-9638-157A31B0A700\n");
// TODO: Until Apple ][ encoding is implemented
CurrentEncoding = new LisaRoman();
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -58,9 +58,7 @@ namespace DiscImageChef.Filesystems.LisaFS
/// <param name="contents">Directory contents.</param>
public override Errno ReadDir(string path, ref List<string> contents)
{
short fileId;
bool isDir;
Errno error = LookupFileId(path, out fileId, out isDir);
Errno error = LookupFileId(path, out short fileId, out bool isDir);
if(error != Errno.NoError) return error;
if(!isDir) return Errno.NotDirectory;
@@ -106,13 +104,10 @@ namespace DiscImageChef.Filesystems.LisaFS
catalogCache = new List<CatalogEntry>();
Errno error;
// Do differently for V1 and V2
if(mddf.fsversion == LisaFSv2 || mddf.fsversion == LisaFSv1)
if(mddf.fsversion == LISA_V2 || mddf.fsversion == LISA_V1)
{
byte[] buf;
error = ReadFile((short)FILEID_CATALOG, out buf);
Errno error = ReadFile((short)FILEID_CATALOG, out byte[] buf);
if(error != Errno.NoError) return error;
int offset = 0;
@@ -142,18 +137,19 @@ namespace DiscImageChef.Filesystems.LisaFS
// Convert entries to V3 format
foreach(CatalogEntryV2 entV2 in catalogV2)
{
ExtentFile ext;
error = ReadExtentsFile(entV2.fileID, out ext);
error = ReadExtentsFile(entV2.fileID, out ExtentFile ext);
if(error != Errno.NoError) continue;
CatalogEntry entV3 = new CatalogEntry();
entV3.fileID = entV2.fileID;
entV3.filename = new byte[32];
CatalogEntry entV3 = new CatalogEntry
{
fileID = entV2.fileID,
filename = new byte[32],
fileType = entV2.fileType,
length = (int)srecords[entV2.fileID].filesize,
dtc = ext.dtc,
dtm = ext.dtm
};
Array.Copy(entV2.filename, 0, entV3.filename, 0, entV2.filenameLen);
entV3.fileType = entV2.fileType;
entV3.length = (int)srecords[entV2.fileID].filesize;
entV3.dtc = ext.dtc;
entV3.dtm = ext.dtm;
catalogCache.Add(entV3);
}
@@ -168,8 +164,7 @@ namespace DiscImageChef.Filesystems.LisaFS
// If root catalog is not pointed in MDDF (unchecked) maybe it's always following S-Records File?
for(ulong i = 0; i < device.GetSectors(); i++)
{
LisaTag.PriamTag catTag;
DecodeTag(device.ReadSectorTag(i, SectorTagType.AppleSectorTag), out catTag);
DecodeTag(device.ReadSectorTag(i, SectorTagType.AppleSectorTag), out LisaTag.PriamTag catTag);
if(catTag.FileId != FILEID_CATALOG || catTag.RelPage != 0) continue;
@@ -186,9 +181,8 @@ namespace DiscImageChef.Filesystems.LisaFS
// Traverse double-linked list until first catalog block
while(prevCatalogPointer != 0xFFFFFFFF)
{
LisaTag.PriamTag prevTag;
DecodeTag(device.ReadSectorTag(prevCatalogPointer + mddf.mddf_block + volumePrefix, SectorTagType.AppleSectorTag),
out prevTag);
out LisaTag.PriamTag prevTag);
if(prevTag.FileId != FILEID_CATALOG) return Errno.InvalidArgument;
@@ -199,15 +193,13 @@ namespace DiscImageChef.Filesystems.LisaFS
ulong nextCatalogPointer;
nextCatalogPointer = BigEndianBitConverter.ToUInt32(firstCatalogBlock, 0x7FA);
List<byte[]> catalogBlocks = new List<byte[]>();
catalogBlocks.Add(firstCatalogBlock);
List<byte[]> catalogBlocks = new List<byte[]> {firstCatalogBlock};
// Traverse double-linked list to read full catalog
while(nextCatalogPointer != 0xFFFFFFFF)
{
LisaTag.PriamTag nextTag;
DecodeTag(device.ReadSectorTag(nextCatalogPointer + mddf.mddf_block + volumePrefix, SectorTagType.AppleSectorTag),
out nextTag);
out LisaTag.PriamTag nextTag);
if(nextTag.FileId != FILEID_CATALOG) return Errno.InvalidArgument;
@@ -232,24 +224,25 @@ namespace DiscImageChef.Filesystems.LisaFS
// Normal entry
else if(buf[offset + 0x24] == 0x03 && buf[offset] == 0x24)
{
CatalogEntry entry = new CatalogEntry();
entry.marker = buf[offset];
entry.parentID = BigEndianBitConverter.ToUInt16(buf, offset + 0x01);
entry.filename = new byte[E_NAME];
CatalogEntry entry = new CatalogEntry
{
marker = buf[offset],
parentID = BigEndianBitConverter.ToUInt16(buf, offset + 0x01),
filename = new byte[E_NAME],
terminator = buf[offset + 0x23],
fileType = buf[offset + 0x24],
unknown = buf[offset + 0x25],
fileID = BigEndianBitConverter.ToInt16(buf, offset + 0x26),
dtc = BigEndianBitConverter.ToUInt32(buf, offset + 0x28),
dtm = BigEndianBitConverter.ToUInt32(buf, offset + 0x2C),
length = BigEndianBitConverter.ToInt32(buf, offset + 0x30),
wasted = BigEndianBitConverter.ToInt32(buf, offset + 0x34),
tail = new byte[8]
};
Array.Copy(buf, offset + 0x03, entry.filename, 0, E_NAME);
entry.terminator = buf[offset + 0x23];
entry.fileType = buf[offset + 0x24];
entry.unknown = buf[offset + 0x25];
entry.fileID = BigEndianBitConverter.ToInt16(buf, offset + 0x26);
entry.dtc = BigEndianBitConverter.ToUInt32(buf, offset + 0x28);
entry.dtm = BigEndianBitConverter.ToUInt32(buf, offset + 0x2C);
entry.length = BigEndianBitConverter.ToInt32(buf, offset + 0x30);
entry.wasted = BigEndianBitConverter.ToInt32(buf, offset + 0x34);
entry.tail = new byte[8];
Array.Copy(buf, offset + 0x38, entry.tail, 0, 8);
ExtentFile ext;
if(ReadExtentsFile(entry.fileID, out ext) == Errno.NoError)
if(ReadExtentsFile(entry.fileID, out _) == Errno.NoError)
if(!fileSizeCache.ContainsKey(entry.fileID))
{
catalogCache.Add(entry);
@@ -261,23 +254,25 @@ namespace DiscImageChef.Filesystems.LisaFS
// Subdirectory entry
else if(buf[offset + 0x24] == 0x01 && buf[offset] == 0x24)
{
CatalogEntry entry = new CatalogEntry();
entry.marker = buf[offset];
entry.parentID = BigEndianBitConverter.ToUInt16(buf, offset + 0x01);
entry.filename = new byte[E_NAME];
CatalogEntry entry = new CatalogEntry
{
marker = buf[offset],
parentID = BigEndianBitConverter.ToUInt16(buf, offset + 0x01),
filename = new byte[E_NAME],
terminator = buf[offset + 0x23],
fileType = buf[offset + 0x24],
unknown = buf[offset + 0x25],
fileID = BigEndianBitConverter.ToInt16(buf, offset + 0x26),
dtc = BigEndianBitConverter.ToUInt32(buf, offset + 0x28),
dtm = BigEndianBitConverter.ToUInt32(buf, offset + 0x2C),
length = 0,
wasted = 0,
tail = null
};
Array.Copy(buf, offset + 0x03, entry.filename, 0, E_NAME);
entry.terminator = buf[offset + 0x23];
entry.fileType = buf[offset + 0x24];
entry.unknown = buf[offset + 0x25];
entry.fileID = BigEndianBitConverter.ToInt16(buf, offset + 0x26);
entry.dtc = BigEndianBitConverter.ToUInt32(buf, offset + 0x28);
entry.dtm = BigEndianBitConverter.ToUInt32(buf, offset + 0x2C);
entry.length = 0;
entry.wasted = 0;
entry.tail = null;
if(!directoryDTCCache.ContainsKey(entry.fileID))
directoryDTCCache.Add(entry.fileID, DateHandlers.LisaToDateTime(entry.dtc));
if(!directoryDtcCache.ContainsKey(entry.fileID))
directoryDtcCache.Add(entry.fileID, DateHandlers.LisaToDateTime(entry.dtc));
catalogCache.Add(entry);
@@ -295,21 +290,22 @@ namespace DiscImageChef.Filesystems.LisaFS
if(!mounted) return Errno.AccessDenied;
stat = new FileEntryInfo();
stat.Attributes = new FileAttributes();
DateTime tmp;
stat = new FileEntryInfo
{
Attributes = new FileAttributes(),
Inode = FILEID_CATALOG,
Mode = 0x16D,
Links = 0,
UID = 0,
GID = 0,
DeviceNo = 0,
Length = 0,
BlockSize = mddf.datasize,
Blocks = 0
};
directoryDTCCache.TryGetValue(dirId, out tmp);
directoryDtcCache.TryGetValue(dirId, out DateTime tmp);
stat.CreationTime = tmp;
stat.Inode = FILEID_CATALOG;
stat.Mode = 0x16D;
stat.Links = 0;
stat.UID = 0;
stat.GID = 0;
stat.DeviceNo = 0;
stat.Length = 0;
stat.BlockSize = mddf.datasize;
stat.Blocks = 0;
return Errno.NoError;
}

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -44,46 +44,46 @@ namespace DiscImageChef.Filesystems
public PCEnginePlugin()
{
Name = "PC Engine CD Plugin";
PluginUUID = new Guid("e5ee6d7c-90fa-49bd-ac89-14ef750b8af3");
PluginUuid = new Guid("e5ee6d7c-90fa-49bd-ac89-14ef750b8af3");
CurrentEncoding = Encoding.GetEncoding("shift_jis");
}
public PCEnginePlugin(Encoding encoding)
{
Name = "PC Engine CD Plugin";
PluginUUID = new Guid("e5ee6d7c-90fa-49bd-ac89-14ef750b8af3");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("shift_jis");
else CurrentEncoding = encoding;
PluginUuid = new Guid("e5ee6d7c-90fa-49bd-ac89-14ef750b8af3");
CurrentEncoding = encoding ?? Encoding.GetEncoding("shift_jis");
}
public PCEnginePlugin(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
{
Name = "PC Engine CD Plugin";
PluginUUID = new Guid("e5ee6d7c-90fa-49bd-ac89-14ef750b8af3");
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("shift_jis");
else CurrentEncoding = encoding;
PluginUuid = new Guid("e5ee6d7c-90fa-49bd-ac89-14ef750b8af3");
CurrentEncoding = encoding ?? Encoding.GetEncoding("shift_jis");
}
public override bool Identify(ImagePlugin imagePlugin, Partition partition)
{
if(2 + partition.Start >= partition.End) return false;
byte[] system_descriptor = new byte[23];
byte[] systemDescriptor = new byte[23];
byte[] sector = imagePlugin.ReadSector(1 + partition.Start);
Array.Copy(sector, 0x20, system_descriptor, 0, 23);
Array.Copy(sector, 0x20, systemDescriptor, 0, 23);
return Encoding.ASCII.GetString(system_descriptor) == "PC Engine CD-ROM SYSTEM";
return Encoding.ASCII.GetString(systemDescriptor) == "PC Engine CD-ROM SYSTEM";
}
public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
out string information)
{
information = "";
xmlFSType = new FileSystemType();
xmlFSType.Type = "PC Engine filesystem";
xmlFSType.Clusters = (long)((partition.End - partition.Start + 1) / imagePlugin.GetSectorSize() * 2048);
xmlFSType.ClusterSize = 2048;
XmlFsType = new FileSystemType
{
Type = "PC Engine filesystem",
Clusters = (long)((partition.End - partition.Start + 1) / imagePlugin.GetSectorSize() * 2048),
ClusterSize = 2048
};
}
public override Errno Mount()

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -54,14 +54,14 @@ namespace DiscImageChef.Filesystems.UCSDPascal
public PascalPlugin()
{
Name = "U.C.S.D. Pascal filesystem";
PluginUUID = new Guid("B0AC2CB5-72AA-473A-9200-270B5A2C2D53");
PluginUuid = new Guid("B0AC2CB5-72AA-473A-9200-270B5A2C2D53");
CurrentEncoding = new LisaRoman();
}
public PascalPlugin(Encoding encoding)
{
Name = "U.C.S.D. Pascal filesystem";
PluginUUID = new Guid("B0AC2CB5-72AA-473A-9200-270B5A2C2D53");
PluginUuid = new Guid("B0AC2CB5-72AA-473A-9200-270B5A2C2D53");
// TODO: Until Apple ][ encoding is implemented
CurrentEncoding = new LisaRoman();
}
@@ -70,7 +70,7 @@ namespace DiscImageChef.Filesystems.UCSDPascal
{
device = imagePlugin;
Name = "U.C.S.D. Pascal filesystem";
PluginUUID = new Guid("B0AC2CB5-72AA-473A-9200-270B5A2C2D53");
PluginUuid = new Guid("B0AC2CB5-72AA-473A-9200-270B5A2C2D53");
// TODO: Until Apple ][ encoding is implemented
CurrentEncoding = new LisaRoman();
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -67,7 +67,7 @@ namespace DiscImageChef.Commands
if(formatsOptions.Verbose) DicConsole.VerboseWriteLine("GUID\t\t\t\t\tPlugin");
foreach(KeyValuePair<string, Filesystem> kvp in plugins.PluginsList)
if(formatsOptions.Verbose)
DicConsole.VerboseWriteLine("{0}\t{1}", kvp.Value.PluginUUID, kvp.Value.Name);
DicConsole.VerboseWriteLine("{0}\t{1}", kvp.Value.PluginUuid, kvp.Value.Name);
else DicConsole.WriteLine(kvp.Value.Name);
DicConsole.WriteLine();