diff --git a/DiscImageChef.Filesystems/AODOS.cs b/DiscImageChef.Filesystems/AODOS.cs index 79c0ba4d..d13d7969 100644 --- a/DiscImageChef.Filesystems/AODOS.cs +++ b/DiscImageChef.Filesystems/AODOS.cs @@ -45,6 +45,8 @@ namespace DiscImageChef.Filesystems // This may be missing fields, or not, I don't know russian so any help is appreciated public class AODOS : Filesystem { + readonly byte[] AODOSIdentifier = {0x20, 0x41, 0x4F, 0x2D, 0x44, 0x4F, 0x53, 0x20}; + public AODOS() { Name = "Alexander Osipov DOS file system"; @@ -66,41 +68,6 @@ namespace DiscImageChef.Filesystems CurrentEncoding = Encoding.GetEncoding("koi8-r"); } - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct AODOS_BootBlock - { - /// - /// A NOP opcode - /// - public byte nop; - /// - /// A branch to real bootloader - /// - public ushort branch; - /// - /// Unused - /// - public byte unused; - /// - /// " AO-DOS " - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] identifier; - /// - /// Volume label - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] public byte[] volumeLabel; - /// - /// How many files are present in disk - /// - public ushort files; - /// - /// How many sectors are used - /// - public ushort usedSectors; - } - - readonly byte[] AODOSIdentifier = {0x20, 0x41, 0x4F, 0x2D, 0x44, 0x4F, 0x53, 0x20}; - public override bool Identify(ImagePlugin imagePlugin, Partition partition) { // Does AO-DOS support hard disks? @@ -122,8 +89,7 @@ namespace DiscImageChef.Filesystems return bb.identifier.SequenceEqual(AODOSIdentifier); } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { byte[] sector = imagePlugin.ReadSector(0); AODOS_BootBlock bb = new AODOS_BootBlock(); @@ -216,5 +182,38 @@ namespace DiscImageChef.Filesystems { return Errno.NotImplemented; } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct AODOS_BootBlock + { + /// + /// A NOP opcode + /// + public byte nop; + /// + /// A branch to real bootloader + /// + public ushort branch; + /// + /// Unused + /// + public byte unused; + /// + /// " AO-DOS " + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] identifier; + /// + /// Volume label + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] public byte[] volumeLabel; + /// + /// How many files are present in disk + /// + public ushort files; + /// + /// How many sectors are used + /// + public ushort usedSectors; + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/APFS.cs b/DiscImageChef.Filesystems/APFS.cs index b9c6b592..c10a1215 100644 --- a/DiscImageChef.Filesystems/APFS.cs +++ b/DiscImageChef.Filesystems/APFS.cs @@ -66,18 +66,6 @@ namespace DiscImageChef.Filesystems CurrentEncoding = Encoding.UTF8; } - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct ApfsContainerSuperBlock - { - public ulong unknown1; // Varies between copies of the superblock - public ulong unknown2; - public ulong unknown3; // Varies by 1 between copies of the superblock - public ulong unknown4; - public uint magic; - public uint blockSize; - public ulong containerBlocks; - } - public override bool Identify(ImagePlugin imagePlugin, Partition partition) { if(partition.Start >= partition.End) return false; @@ -97,8 +85,7 @@ namespace DiscImageChef.Filesystems return nxSb.magic == APFS_CONTAINER_MAGIC; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { StringBuilder sbInformation = new StringBuilder(); XmlFsType = new FileSystemType(); @@ -196,5 +183,17 @@ namespace DiscImageChef.Filesystems { return Errno.NotImplemented; } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct ApfsContainerSuperBlock + { + public ulong unknown1; // Varies between copies of the superblock + public ulong unknown2; + public ulong unknown3; // Varies by 1 between copies of the superblock + public ulong unknown4; + public uint magic; + public uint blockSize; + public ulong containerBlocks; + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/Acorn.cs b/DiscImageChef.Filesystems/Acorn.cs index 413ec786..585562ec 100644 --- a/DiscImageChef.Filesystems/Acorn.cs +++ b/DiscImageChef.Filesystems/Acorn.cs @@ -44,30 +44,39 @@ namespace DiscImageChef.Filesystems public class AcornADFS : Filesystem { /// - /// Location for boot block, in bytes + /// Location for boot block, in bytes /// const ulong BOOT_BLOCK_LOCATION = 0xC00; /// - /// Size of boot block, in bytes + /// Size of boot block, in bytes /// const uint BOOT_BLOCK_SIZE = 0x200; /// - /// Location of new directory, in bytes + /// Location of new directory, in bytes /// const ulong NEW_DIRECTORY_LOCATION = 0x400; /// - /// Location of old directory, in bytes + /// Location of old directory, in bytes /// const ulong OLD_DIRECTORY_LOCATION = 0x200; /// - /// Size of old directory + /// Size of old directory /// const uint OLD_DIRECTORY_SIZE = 1280; /// - /// Size of new directory + /// Size of new directory /// const uint NEW_DIRECTORY_SIZE = 2048; + /// + /// New directory format magic number, "Nick" + /// + const uint NEW_DIR_MAGIC = 0x6B63694E; + /// + /// Old directory format magic number, "Hugo" + /// + const uint OLD_DIR_MAGIC = 0x6F677548; + public AcornADFS() { Name = "Acorn Advanced Disc Filing System"; @@ -89,175 +98,6 @@ namespace DiscImageChef.Filesystems CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1"); } - /// - /// Boot block, used in hard disks and ADFS-F and higher. - /// - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct BootBlock - { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x1C0)] public byte[] spare; - public DiscRecord discRecord; - public byte flags; - public ushort startCylinder; - public byte checksum; - } - - /// - /// Disc record, used in hard disks and ADFS-E and higher. - /// - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct DiscRecord - { - public byte log2secsize; - public byte spt; - public byte heads; - public byte density; - public byte idlen; - public byte log2bpmb; - public byte skew; - public byte bootoption; - public byte lowsector; - public byte nzones; - public ushort zone_spare; - public uint root; - public uint disc_size; - public ushort disc_id; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] public byte[] disc_name; - public uint disc_type; - public uint disc_size_high; - public byte flags; - public byte nzones_high; - public uint format_version; - public uint root_size; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] reserved; - } - - /// - /// Free block map, sector 0, used in ADFS-S, ADFS-L, ADFS-M and ADFS-D - /// - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct OldMapSector0 - { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 82 * 3)] public byte[] freeStart; - public byte reserved; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)] public byte[] name; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] size; - public byte checksum; - } - - /// - /// Free block map, sector 1, used in ADFS-S, ADFS-L, ADFS-M and ADFS-D - /// - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct OldMapSector1 - { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 82 * 3)] public byte[] freeStart; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)] public byte[] name; - public ushort discId; - public byte boot; - public byte freeEnd; - public byte checksum; - } - - /// - /// Free block map, sector 0, used in ADFS-E - /// - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct NewMap - { - public byte zoneChecksum; - public ushort freeLink; - public byte crossChecksum; - public DiscRecord discRecord; - } - - /// - /// Directory header, common to "old" and "new" directories - /// - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct DirectoryHeader - { - public byte masterSequence; - public uint magic; - } - - /// - /// New directory format magic number, "Nick" - /// - const uint NEW_DIR_MAGIC = 0x6B63694E; - /// - /// Old directory format magic number, "Hugo" - /// - const uint OLD_DIR_MAGIC = 0x6F677548; - - /// - /// Directory header, common to "old" and "new" directories - /// - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct DirectoryEntry - { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] public byte[] name; - public uint load; - public uint exec; - public uint length; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] address; - public byte atts; - } - - /// - /// Directory tail, new format - /// - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct NewDirectoryTail - { - public byte lastMark; - public ushort reserved; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] parent; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 19)] public byte[] title; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] public byte[] name; - public byte endMasSeq; - public uint magic; - public byte checkByte; - } - - /// - /// Directory tail, old format - /// - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct OldDirectoryTail - { - public byte lastMark; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] public byte[] name; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] parent; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 19)] public byte[] title; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 14)] public byte[] reserved; - public byte endMasSeq; - public uint magic; - public byte checkByte; - } - - /// - /// Directory, old format - /// - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct OldDirectory - { - public DirectoryHeader header; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 47)] public DirectoryEntry[] entries; - public OldDirectoryTail tail; - } - - /// - /// Directory, new format - /// - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct NewDirectory - { - public DirectoryHeader header; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 77)] public DirectoryEntry[] entries; - public NewDirectoryTail tail; - } - // TODO: BBC Master hard disks are untested... public override bool Identify(ImagePlugin imagePlugin, Partition partition) { @@ -277,12 +117,14 @@ namespace DiscImageChef.Filesystems sector = imagePlugin.ReadSector(0); byte oldChk0 = AcornMapChecksum(sector, 255); ptr = GCHandle.Alloc(sector, GCHandleType.Pinned); - OldMapSector0 oldMap0 = (OldMapSector0)Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(OldMapSector0)); + OldMapSector0 oldMap0 = + (OldMapSector0)Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(OldMapSector0)); sector = imagePlugin.ReadSector(1); byte oldChk1 = AcornMapChecksum(sector, 255); ptr = GCHandle.Alloc(sector, GCHandleType.Pinned); - OldMapSector1 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); @@ -317,7 +159,8 @@ namespace DiscImageChef.Filesystems sector = tmp; } ptr = GCHandle.Alloc(sector, GCHandleType.Pinned); - OldDirectory oldRoot = (OldDirectory)Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(OldDirectory)); + 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}", @@ -421,8 +264,7 @@ namespace DiscImageChef.Filesystems // TODO: Find root directory on volumes with DiscRecord // TODO: Support big directories (ADFS-G?) // TODO: Find the real freemap on volumes with DiscRecord, as DiscRecord's discid may be empty but this one isn't - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { StringBuilder sbInformation = new StringBuilder(); XmlFsType = new FileSystemType(); @@ -440,12 +282,14 @@ namespace DiscImageChef.Filesystems sector = imagePlugin.ReadSector(0); byte oldChk0 = AcornMapChecksum(sector, 255); ptr = GCHandle.Alloc(sector, GCHandleType.Pinned); - OldMapSector0 oldMap0 = (OldMapSector0)Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(OldMapSector0)); + OldMapSector0 oldMap0 = + (OldMapSector0)Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(OldMapSector0)); sector = imagePlugin.ReadSector(1); byte oldChk1 = AcornMapChecksum(sector, 255); ptr = GCHandle.Alloc(sector, GCHandleType.Pinned); - OldMapSector1 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) @@ -492,9 +336,11 @@ namespace DiscImageChef.Filesystems sector = tmp; } ptr = GCHandle.Alloc(sector, GCHandleType.Pinned); - OldDirectory oldRoot = (OldDirectory)Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(OldDirectory)); + OldDirectory oldRoot = + (OldDirectory)Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(OldDirectory)); - if(oldRoot.header.magic == OLD_DIR_MAGIC && oldRoot.tail.magic == OLD_DIR_MAGIC) 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... @@ -514,7 +360,8 @@ namespace DiscImageChef.Filesystems oldRoot = (OldDirectory)Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(OldDirectory)); - if(oldRoot.header.magic == OLD_DIR_MAGIC && oldRoot.tail.magic == OLD_DIR_MAGIC) 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); @@ -526,9 +373,11 @@ namespace DiscImageChef.Filesystems sector = tmp; } ptr = GCHandle.Alloc(sector, GCHandleType.Pinned); - NewDirectory newRoot = (NewDirectory)Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), - typeof(NewDirectory)); - if(newRoot.header.magic == NEW_DIR_MAGIC && newRoot.tail.magic == NEW_DIR_MAGIC) namebytes = newRoot.tail.title; + NewDirectory newRoot = + (NewDirectory)Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), + typeof(NewDirectory)); + if(newRoot.header.magic == NEW_DIR_MAGIC && newRoot.tail.magic == NEW_DIR_MAGIC) + namebytes = newRoot.tail.title; } } } @@ -798,5 +647,165 @@ namespace DiscImageChef.Filesystems return (byte)(((sum & 0xFF000000) >> 24) ^ ((sum & 0xFF0000) >> 16) ^ ((sum & 0xFF00) >> 8) ^ (sum & 0xFF)); } + + /// + /// Boot block, used in hard disks and ADFS-F and higher. + /// + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct BootBlock + { + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x1C0)] public byte[] spare; + public DiscRecord discRecord; + public byte flags; + public ushort startCylinder; + public byte checksum; + } + + /// + /// Disc record, used in hard disks and ADFS-E and higher. + /// + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct DiscRecord + { + public byte log2secsize; + public byte spt; + public byte heads; + public byte density; + public byte idlen; + public byte log2bpmb; + public byte skew; + public byte bootoption; + public byte lowsector; + public byte nzones; + public ushort zone_spare; + public uint root; + public uint disc_size; + public ushort disc_id; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] public byte[] disc_name; + public uint disc_type; + public uint disc_size_high; + public byte flags; + public byte nzones_high; + public uint format_version; + public uint root_size; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] reserved; + } + + /// + /// Free block map, sector 0, used in ADFS-S, ADFS-L, ADFS-M and ADFS-D + /// + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct OldMapSector0 + { + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 82 * 3)] public byte[] freeStart; + public byte reserved; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)] public byte[] name; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] size; + public byte checksum; + } + + /// + /// Free block map, sector 1, used in ADFS-S, ADFS-L, ADFS-M and ADFS-D + /// + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct OldMapSector1 + { + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 82 * 3)] public byte[] freeStart; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)] public byte[] name; + public ushort discId; + public byte boot; + public byte freeEnd; + public byte checksum; + } + + /// + /// Free block map, sector 0, used in ADFS-E + /// + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct NewMap + { + public byte zoneChecksum; + public ushort freeLink; + public byte crossChecksum; + public DiscRecord discRecord; + } + + /// + /// Directory header, common to "old" and "new" directories + /// + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct DirectoryHeader + { + public byte masterSequence; + public uint magic; + } + + /// + /// Directory header, common to "old" and "new" directories + /// + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct DirectoryEntry + { + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] public byte[] name; + public uint load; + public uint exec; + public uint length; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] address; + public byte atts; + } + + /// + /// Directory tail, new format + /// + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct NewDirectoryTail + { + public byte lastMark; + public ushort reserved; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] parent; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 19)] public byte[] title; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] public byte[] name; + public byte endMasSeq; + public uint magic; + public byte checkByte; + } + + /// + /// Directory tail, old format + /// + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct OldDirectoryTail + { + public byte lastMark; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] public byte[] name; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] parent; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 19)] public byte[] title; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 14)] public byte[] reserved; + public byte endMasSeq; + public uint magic; + public byte checkByte; + } + + /// + /// Directory, old format + /// + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct OldDirectory + { + public DirectoryHeader header; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 47)] public DirectoryEntry[] entries; + public OldDirectoryTail tail; + } + + /// + /// Directory, new format + /// + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct NewDirectory + { + public DirectoryHeader header; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 77)] public DirectoryEntry[] entries; + public NewDirectoryTail tail; + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/AmigaDOS.cs b/DiscImageChef.Filesystems/AmigaDOS.cs index 4bf63028..4a679012 100644 --- a/DiscImageChef.Filesystems/AmigaDOS.cs +++ b/DiscImageChef.Filesystems/AmigaDOS.cs @@ -45,6 +45,12 @@ namespace DiscImageChef.Filesystems { public class AmigaDOSPlugin : Filesystem { + const uint FFS_MASK = 0x444F5300; + const uint MUFS_MASK = 0x6D754600; + + const uint TYPE_HEADER = 2; + const uint SUBTYPE_ROOT = 1; + public AmigaDOSPlugin() { Name = "Amiga DOS filesystem"; @@ -66,150 +72,6 @@ namespace DiscImageChef.Filesystems CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1"); } - /// - /// Boot block, first 2 sectors - /// - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct BootBlock - { - /// - /// Offset 0x00, "DOSx" disk type - /// - public uint diskType; - /// - /// Offset 0x04, Checksum - /// - public uint checksum; - /// - /// Offset 0x08, Pointer to root block, mostly invalid - /// - public uint root_ptr; - /// - /// Offset 0x0C, Boot code, til completion. Size is intentionally incorrect to allow marshaling to work. - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] public byte[] bootCode; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct RootBlock - { - /// - /// Offset 0x00, block type, value = T_HEADER (2) - /// - public uint type; - /// - /// Offset 0x04, unused - /// - public uint headerKey; - /// - /// Offset 0x08, unused - /// - public uint highSeq; - /// - /// Offset 0x0C, longs used by hash table - /// - public uint hashTableSize; - /// - /// Offset 0x10, unused - /// - public uint firstData; - /// - /// Offset 0x14, Rootblock checksum - /// - public uint checksum; - /// - /// Offset 0x18, Hashtable, size = (block size / 4) - 56 or size = hashTableSize. - /// Size intentionally bad to allow marshalling to work. - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] public uint[] hashTable; - /// - /// Offset 0x18+hashTableSize*4+0, bitmap flag, 0xFFFFFFFF if valid - /// - public uint bitmapFlag; - /// - /// Offset 0x18+hashTableSize*4+4, bitmap pages, 25 entries - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 25)] public uint[] bitmapPages; - /// - /// Offset 0x18+hashTableSize*4+104, pointer to bitmap extension block - /// - public uint bitmapExtensionBlock; - /// - /// Offset 0x18+hashTableSize*4+108, last root alteration days since 1978/01/01 - /// - public uint rDays; - /// - /// Offset 0x18+hashTableSize*4+112, last root alteration minutes past midnight - /// - public uint rMins; - /// - /// Offset 0x18+hashTableSize*4+116, last root alteration ticks (1/50 secs) - /// - public uint rTicks; - /// - /// Offset 0x18+hashTableSize*4+120, disk name, pascal string, 31 bytes - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 31)] public byte[] diskName; - /// - /// Offset 0x18+hashTableSize*4+151, unused - /// - public byte padding; - /// - /// Offset 0x18+hashTableSize*4+152, unused - /// - public uint reserved1; - /// - /// Offset 0x18+hashTableSize*4+156, unused - /// - public uint reserved2; - /// - /// Offset 0x18+hashTableSize*4+160, last disk alteration days since 1978/01/01 - /// - public uint vDays; - /// - /// Offset 0x18+hashTableSize*4+164, last disk alteration minutes past midnight - /// - public uint vMins; - /// - /// Offset 0x18+hashTableSize*4+168, last disk alteration ticks (1/50 secs) - /// - public uint vTicks; - /// - /// Offset 0x18+hashTableSize*4+172, filesystem creation days since 1978/01/01 - /// - public uint cDays; - /// - /// Offset 0x18+hashTableSize*4+176, filesystem creation minutes since 1978/01/01 - /// - public uint cMins; - /// - /// Offset 0x18+hashTableSize*4+180, filesystem creation ticks since 1978/01/01 - /// - public uint cTicks; - /// - /// Offset 0x18+hashTableSize*4+184, unused - /// - public uint nextHash; - /// - /// Offset 0x18+hashTableSize*4+188, unused - /// - public uint parentDir; - /// - /// Offset 0x18+hashTableSize*4+192, first directory cache block - /// - public uint extension; - /// - /// Offset 0x18+hashTableSize*4+196, block secondary type = ST_ROOT (1) - /// - public uint sec_type; - } - - const uint FFS_MASK = 0x444F5300; - const uint MUFS_MASK = 0x6D754600; - - const uint TYPE_HEADER = 2; - const uint SUBTYPE_ROOT = 1; - public override bool Identify(ImagePlugin imagePlugin, Partition partition) { if(partition.Start >= partition.End) return false; @@ -263,7 +125,8 @@ namespace DiscImageChef.Filesystems RootBlock rblk = new RootBlock(); // So to handle even number of sectors - foreach(ulong rootPtr in rootPtrs.Where(rootPtr => rootPtr < partition.End && rootPtr >= partition.Start)) { + foreach(ulong rootPtr in rootPtrs.Where(rootPtr => rootPtr < partition.End && rootPtr >= partition.Start)) + { DicConsole.DebugWriteLine("AmigaDOS plugin", "Searching for Rootblock in sector {0}", rootPtr); sector = imagePlugin.ReadSector(rootPtr); @@ -305,8 +168,7 @@ namespace DiscImageChef.Filesystems return false; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { StringBuilder sbInformation = new StringBuilder(); XmlFsType = new FileSystemType(); @@ -345,7 +207,8 @@ namespace DiscImageChef.Filesystems uint blockSize = 0; // So to handle even number of sectors - foreach(ulong rootPtr in rootPtrs.Where(rootPtr => rootPtr < partition.End && rootPtr >= partition.Start)) { + foreach(ulong rootPtr in rootPtrs.Where(rootPtr => rootPtr < partition.End && rootPtr >= partition.Start)) + { DicConsole.DebugWriteLine("AmigaDOS plugin", "Searching for Rootblock in sector {0}", rootPtr); rootBlockSector = imagePlugin.ReadSector(rootPtr); @@ -453,8 +316,7 @@ namespace DiscImageChef.Filesystems if((bootBlk.diskType & 0xFF) == 4 || (bootBlk.diskType & 0xFF) == 5) sbInformation.AppendFormat("Directory cache starts at block {0}", rootBlk.extension).AppendLine(); - long blocks = (long)((partition.End - partition.Start + 1) * imagePlugin.ImageInfo.SectorSize / - blockSize); + long blocks = (long)((partition.End - partition.Start + 1) * imagePlugin.ImageInfo.SectorSize / blockSize); sbInformation.AppendFormat("Volume block size is {0} bytes", blockSize).AppendLine(); sbInformation.AppendFormat("Volume has {0} blocks", blocks).AppendLine(); @@ -581,5 +443,143 @@ namespace DiscImageChef.Filesystems { return Errno.NotImplemented; } + + /// + /// Boot block, first 2 sectors + /// + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct BootBlock + { + /// + /// Offset 0x00, "DOSx" disk type + /// + public uint diskType; + /// + /// Offset 0x04, Checksum + /// + public uint checksum; + /// + /// Offset 0x08, Pointer to root block, mostly invalid + /// + public uint root_ptr; + /// + /// Offset 0x0C, Boot code, til completion. Size is intentionally incorrect to allow marshaling to work. + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] public byte[] bootCode; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct RootBlock + { + /// + /// Offset 0x00, block type, value = T_HEADER (2) + /// + public uint type; + /// + /// Offset 0x04, unused + /// + public uint headerKey; + /// + /// Offset 0x08, unused + /// + public uint highSeq; + /// + /// Offset 0x0C, longs used by hash table + /// + public uint hashTableSize; + /// + /// Offset 0x10, unused + /// + public uint firstData; + /// + /// Offset 0x14, Rootblock checksum + /// + public uint checksum; + /// + /// Offset 0x18, Hashtable, size = (block size / 4) - 56 or size = hashTableSize. + /// Size intentionally bad to allow marshalling to work. + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] public uint[] hashTable; + /// + /// Offset 0x18+hashTableSize*4+0, bitmap flag, 0xFFFFFFFF if valid + /// + public uint bitmapFlag; + /// + /// Offset 0x18+hashTableSize*4+4, bitmap pages, 25 entries + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 25)] public uint[] bitmapPages; + /// + /// Offset 0x18+hashTableSize*4+104, pointer to bitmap extension block + /// + public uint bitmapExtensionBlock; + /// + /// Offset 0x18+hashTableSize*4+108, last root alteration days since 1978/01/01 + /// + public uint rDays; + /// + /// Offset 0x18+hashTableSize*4+112, last root alteration minutes past midnight + /// + public uint rMins; + /// + /// Offset 0x18+hashTableSize*4+116, last root alteration ticks (1/50 secs) + /// + public uint rTicks; + /// + /// Offset 0x18+hashTableSize*4+120, disk name, pascal string, 31 bytes + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 31)] public byte[] diskName; + /// + /// Offset 0x18+hashTableSize*4+151, unused + /// + public byte padding; + /// + /// Offset 0x18+hashTableSize*4+152, unused + /// + public uint reserved1; + /// + /// Offset 0x18+hashTableSize*4+156, unused + /// + public uint reserved2; + /// + /// Offset 0x18+hashTableSize*4+160, last disk alteration days since 1978/01/01 + /// + public uint vDays; + /// + /// Offset 0x18+hashTableSize*4+164, last disk alteration minutes past midnight + /// + public uint vMins; + /// + /// Offset 0x18+hashTableSize*4+168, last disk alteration ticks (1/50 secs) + /// + public uint vTicks; + /// + /// Offset 0x18+hashTableSize*4+172, filesystem creation days since 1978/01/01 + /// + public uint cDays; + /// + /// Offset 0x18+hashTableSize*4+176, filesystem creation minutes since 1978/01/01 + /// + public uint cMins; + /// + /// Offset 0x18+hashTableSize*4+180, filesystem creation ticks since 1978/01/01 + /// + public uint cTicks; + /// + /// Offset 0x18+hashTableSize*4+184, unused + /// + public uint nextHash; + /// + /// Offset 0x18+hashTableSize*4+188, unused + /// + public uint parentDir; + /// + /// Offset 0x18+hashTableSize*4+192, first directory cache block + /// + public uint extension; + /// + /// Offset 0x18+hashTableSize*4+196, block secondary type = ST_ROOT (1) + /// + public uint sec_type; + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/AppleDOS/AppleDOS.cs b/DiscImageChef.Filesystems/AppleDOS/AppleDOS.cs index 6362bc02..7952af17 100644 --- a/DiscImageChef.Filesystems/AppleDOS/AppleDOS.cs +++ b/DiscImageChef.Filesystems/AppleDOS/AppleDOS.cs @@ -41,39 +41,18 @@ namespace DiscImageChef.Filesystems.AppleDOS { public partial class AppleDOS : Filesystem { - bool mounted; - bool debug; readonly ImagePlugin device; - - #region Caches - /// Caches track/sector lists - Dictionary extentCache; - /// Caches files - Dictionary fileCache; - /// Caches catalog - Dictionary catalogCache; - /// Caches file size - Dictionary fileSizeCache; - /// Caches VTOC - byte[] vtocBlocks; - /// Caches catalog - byte[] catalogBlocks; - /// Caches boot code - byte[] bootBlocks; - /// Caches file type - Dictionary fileTypeCache; - /// Caches locked files - List lockedFiles; - #endregion Caches - - Vtoc vtoc; - ulong start; + bool debug; + bool mounted; int sectorsPerTrack; + ulong start; ulong totalFileEntries; bool track1UsedByFiles; bool track2UsedByFiles; int usedSectors; + Vtoc vtoc; + public AppleDOS() { Name = "Apple DOS File System"; @@ -98,5 +77,26 @@ namespace DiscImageChef.Filesystems.AppleDOS // TODO: Until Apple ][ encoding is implemented CurrentEncoding = new LisaRoman(); } + + #region Caches + /// Caches track/sector lists + Dictionary extentCache; + /// Caches files + Dictionary fileCache; + /// Caches catalog + Dictionary catalogCache; + /// Caches file size + Dictionary fileSizeCache; + /// Caches VTOC + byte[] vtocBlocks; + /// Caches catalog + byte[] catalogBlocks; + /// Caches boot code + byte[] bootBlocks; + /// Caches file type + Dictionary fileTypeCache; + /// Caches locked files + List lockedFiles; + #endregion Caches } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/AppleDOS/Dir.cs b/DiscImageChef.Filesystems/AppleDOS/Dir.cs index 1d3475cc..3b48864b 100644 --- a/DiscImageChef.Filesystems/AppleDOS/Dir.cs +++ b/DiscImageChef.Filesystems/AppleDOS/Dir.cs @@ -41,7 +41,7 @@ namespace DiscImageChef.Filesystems.AppleDOS public partial class AppleDOS { /// - /// Solves a symbolic link. + /// Solves a symbolic link. /// /// Link path. /// Link destination. @@ -51,7 +51,7 @@ namespace DiscImageChef.Filesystems.AppleDOS } /// - /// Lists contents from a directory. + /// Lists contents from a directory. /// /// Directory path. /// Directory contents. @@ -100,7 +100,8 @@ namespace DiscImageChef.Filesystems.AppleDOS CatalogSector catSector = (CatalogSector)Marshal.PtrToStructure(catPtr, typeof(CatalogSector)); Marshal.FreeHGlobal(catPtr); - foreach(FileEntry entry in catSector.entries.Where(entry => entry.extentTrack > 0)) { + foreach(FileEntry entry in catSector.entries.Where(entry => entry.extentTrack > 0)) + { track1UsedByFiles |= entry.extentTrack == 1; track2UsedByFiles |= entry.extentTrack == 2; diff --git a/DiscImageChef.Filesystems/AppleDOS/File.cs b/DiscImageChef.Filesystems/AppleDOS/File.cs index 185083cc..e96cf222 100644 --- a/DiscImageChef.Filesystems/AppleDOS/File.cs +++ b/DiscImageChef.Filesystems/AppleDOS/File.cs @@ -58,7 +58,8 @@ namespace DiscImageChef.Filesystems.AppleDOS if(debug && (string.Compare(path, "$", StringComparison.InvariantCulture) == 0 || string.Compare(path, "$Boot", StringComparison.InvariantCulture) == 0 || - string.Compare(path, "$Vtoc", StringComparison.InvariantCulture) == 0)) attributes |= FileAttributes.System; + string.Compare(path, "$Vtoc", StringComparison.InvariantCulture) == 0)) + attributes |= FileAttributes.System; return Errno.NoError; } @@ -77,14 +78,9 @@ namespace DiscImageChef.Filesystems.AppleDOS if(debug && (string.Compare(path, "$", StringComparison.InvariantCulture) == 0 || string.Compare(path, "$Boot", StringComparison.InvariantCulture) == 0 || string.Compare(path, "$Vtoc", StringComparison.InvariantCulture) == 0)) - { - if(string.Compare(path, "$", StringComparison.InvariantCulture) == 0) - file = catalogBlocks; - else if(string.Compare(path, "$Vtoc", StringComparison.InvariantCulture) == 0) - file = vtocBlocks; - else - file = bootBlocks; - } + if(string.Compare(path, "$", StringComparison.InvariantCulture) == 0) file = catalogBlocks; + else if(string.Compare(path, "$Vtoc", StringComparison.InvariantCulture) == 0) file = vtocBlocks; + else file = bootBlocks; else { if(!fileCache.TryGetValue(filename, out file)) @@ -224,7 +220,7 @@ namespace DiscImageChef.Filesystems.AppleDOS extentCache = new Dictionary(); foreach(Errno error in catalogCache.Keys.Select(CacheFile).Where(error => error != Errno.NoError)) - { return error; } + return error; uint tracksOnBoot = 1; if(!track1UsedByFiles) tracksOnBoot++; diff --git a/DiscImageChef.Filesystems/AppleDOS/Super.cs b/DiscImageChef.Filesystems/AppleDOS/Super.cs index be3ca5f7..bf92cf29 100644 --- a/DiscImageChef.Filesystems/AppleDOS/Super.cs +++ b/DiscImageChef.Filesystems/AppleDOS/Super.cs @@ -40,7 +40,7 @@ namespace DiscImageChef.Filesystems.AppleDOS public partial class AppleDOS { /// - /// Mounts an Apple DOS filesystem + /// Mounts an Apple DOS filesystem /// public override Errno Mount() { @@ -48,7 +48,7 @@ namespace DiscImageChef.Filesystems.AppleDOS } /// - /// Mounts an Apple DOS filesystem + /// Mounts an Apple DOS filesystem /// public override Errno Mount(bool debug) { @@ -117,7 +117,7 @@ namespace DiscImageChef.Filesystems.AppleDOS } /// - /// Umounts this DOS filesystem + /// Umounts this DOS filesystem /// public override Errno Unmount() { @@ -131,7 +131,7 @@ namespace DiscImageChef.Filesystems.AppleDOS } /// - /// Gets information about the mounted volume. + /// Gets information about the mounted volume. /// /// Information about the mounted volume. public override Errno StatFs(ref FileSystemInfo stat) diff --git a/DiscImageChef.Filesystems/AppleDOS/Xattr.cs b/DiscImageChef.Filesystems/AppleDOS/Xattr.cs index 93ee67a6..c5bcec36 100644 --- a/DiscImageChef.Filesystems/AppleDOS/Xattr.cs +++ b/DiscImageChef.Filesystems/AppleDOS/Xattr.cs @@ -38,7 +38,7 @@ namespace DiscImageChef.Filesystems.AppleDOS public partial class AppleDOS { /// - /// Lists all extended attributes, alternate data streams and forks of the given file. + /// Lists all extended attributes, alternate data streams and forks of the given file. /// /// Error number. /// Path. @@ -71,7 +71,7 @@ namespace DiscImageChef.Filesystems.AppleDOS } /// - /// Reads an extended attribute, alternate data stream or fork from the given file. + /// Reads an extended attribute, alternate data stream or fork from the given file. /// /// Error number. /// File path. @@ -89,7 +89,8 @@ namespace DiscImageChef.Filesystems.AppleDOS if(debug && (string.Compare(path, "$", StringComparison.InvariantCulture) == 0 || string.Compare(path, "$Boot", StringComparison.InvariantCulture) == 0 || - string.Compare(path, "$Vtoc", StringComparison.InvariantCulture) == 0)) return Errno.NoSuchExtendedAttribute; + string.Compare(path, "$Vtoc", StringComparison.InvariantCulture) == 0)) + return Errno.NoSuchExtendedAttribute; if(!catalogCache.ContainsKey(filename)) return Errno.NoSuchFile; diff --git a/DiscImageChef.Filesystems/AppleHFS.cs b/DiscImageChef.Filesystems/AppleHFS.cs index c8249e58..1e168547 100644 --- a/DiscImageChef.Filesystems/AppleHFS.cs +++ b/DiscImageChef.Filesystems/AppleHFS.cs @@ -45,15 +45,15 @@ namespace DiscImageChef.Filesystems public class AppleHFS : Filesystem { /// - /// "BD", HFS magic + /// "BD", HFS magic /// const ushort HFS_MAGIC = 0x4244; /// - /// "H+", HFS+ magic + /// "H+", HFS+ magic /// const ushort HFSP_MAGIC = 0x482B; /// - /// "LK", HFS bootblock magic + /// "LK", HFS bootblock magic /// const ushort HFSBB_MAGIC = 0x4C4B; @@ -96,8 +96,7 @@ namespace DiscImageChef.Filesystems if(drSigWord != HFS_MAGIC) continue; drSigWord = - BigEndianBitConverter - .ToUInt16(mdbSector, offset + 0x7C); // Seek to embedded HFS+ signature + BigEndianBitConverter.ToUInt16(mdbSector, offset + 0x7C); // Seek to embedded HFS+ signature return drSigWord != HFSP_MAGIC; } @@ -117,8 +116,7 @@ namespace DiscImageChef.Filesystems return false; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { information = ""; @@ -159,7 +157,8 @@ namespace DiscImageChef.Filesystems else return; } - HFS_MasterDirectoryBlock MDB = BigEndianMarshal.ByteArrayToStructureBigEndian(mdbSector); + HFS_MasterDirectoryBlock MDB = + BigEndianMarshal.ByteArrayToStructureBigEndian(mdbSector); HFS_BootBlock BB = BigEndianMarshal.ByteArrayToStructureBigEndian(bbSector); sb.AppendLine("Apple Hierarchical File System"); @@ -275,7 +274,8 @@ namespace DiscImageChef.Filesystems 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.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) @@ -312,8 +312,68 @@ namespace DiscImageChef.Filesystems return sector; } + public override Errno Mount() + { + return Errno.NotImplemented; + } + + public override Errno Mount(bool debug) + { + return Errno.NotImplemented; + } + + public override Errno Unmount() + { + return Errno.NotImplemented; + } + + public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + { + return Errno.NotImplemented; + } + + public override Errno GetAttributes(string path, ref FileAttributes attributes) + { + return Errno.NotImplemented; + } + + public override Errno ListXAttr(string path, ref List xattrs) + { + return Errno.NotImplemented; + } + + public override Errno GetXattr(string path, string xattr, ref byte[] buf) + { + return Errno.NotImplemented; + } + + public override Errno Read(string path, long offset, long size, ref byte[] buf) + { + return Errno.NotImplemented; + } + + public override Errno ReadDir(string path, ref List contents) + { + return Errno.NotImplemented; + } + + public override Errno StatFs(ref FileSystemInfo stat) + { + return Errno.NotImplemented; + } + + public override Errno Stat(string path, ref FileEntryInfo stat) + { + return Errno.NotImplemented; + } + + public override Errno ReadLink(string path, ref string dest) + { + return Errno.NotImplemented; + } + /// - /// Master Directory Block, should be sector 2 in volume + /// Master Directory Block, should be sector 2 in volume /// [StructLayout(LayoutKind.Sequential, Pack = 1)] struct HFS_MasterDirectoryBlock // Should be sector 2 in volume @@ -393,16 +453,20 @@ namespace DiscImageChef.Filesystems /// 0x080, Size in blocks of volume common cache public ushort drCtlCSize; // End of variable variables :D - /// 0x082, Bytes in the extents B-Tree - /// 3 HFS extents following, 32 bits each + /// + /// 0x082, Bytes in the extents B-Tree + /// 3 HFS extents following, 32 bits each + /// public uint drXTFlSize; - /// 0x092, Bytes in the catalog B-Tree - /// 3 HFS extents following, 32 bits each + /// + /// 0x092, Bytes in the catalog B-Tree + /// 3 HFS extents following, 32 bits each + /// public uint drCTFlSize; } /// - /// Should be sectors 0 and 1 in volume, followed by boot code + /// Should be sectors 0 and 1 in volume, followed by boot code /// [StructLayout(LayoutKind.Sequential, Pack = 1)] struct HFS_BootBlock // Should be sectors 0 and 1 in volume @@ -446,65 +510,5 @@ namespace DiscImageChef.Filesystems /// Fraction of RAM for system heap public uint heap_fract; } - - public override Errno Mount() - { - return Errno.NotImplemented; - } - - public override Errno Mount(bool debug) - { - return Errno.NotImplemented; - } - - public override Errno Unmount() - { - return Errno.NotImplemented; - } - - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) - { - return Errno.NotImplemented; - } - - public override Errno GetAttributes(string path, ref FileAttributes attributes) - { - return Errno.NotImplemented; - } - - public override Errno ListXAttr(string path, ref List xattrs) - { - return Errno.NotImplemented; - } - - public override Errno GetXattr(string path, string xattr, ref byte[] buf) - { - return Errno.NotImplemented; - } - - public override Errno Read(string path, long offset, long size, ref byte[] buf) - { - return Errno.NotImplemented; - } - - public override Errno ReadDir(string path, ref List contents) - { - return Errno.NotImplemented; - } - - public override Errno StatFs(ref FileSystemInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) - { - return Errno.NotImplemented; - } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/AppleHFSPlus.cs b/DiscImageChef.Filesystems/AppleHFSPlus.cs index 61aaf83c..dcd2d183 100644 --- a/DiscImageChef.Filesystems/AppleHFSPlus.cs +++ b/DiscImageChef.Filesystems/AppleHFSPlus.cs @@ -44,15 +44,15 @@ namespace DiscImageChef.Filesystems public class AppleHFSPlus : Filesystem { /// - /// "BD", HFS magic + /// "BD", HFS magic /// const ushort HFS_MAGIC = 0x4244; /// - /// "H+", HFS+ magic + /// "H+", HFS+ magic /// const ushort HFSP_MAGIC = 0x482B; /// - /// "HX", HFSX magic + /// "HX", HFSX magic /// const ushort HFSX_MAGIC = 0x4858; @@ -88,8 +88,7 @@ namespace DiscImageChef.Filesystems uint sectorsToRead = 0x800 / imagePlugin.ImageInfo.SectorSize; if(0x800 % imagePlugin.ImageInfo.SectorSize > 0) sectorsToRead++; - byte[] vhSector = imagePlugin.ReadSectors(partition.Start, - sectorsToRead); + byte[] vhSector = imagePlugin.ReadSectors(partition.Start, sectorsToRead); drSigWord = BigEndianBitConverter.ToUInt16(vhSector, 0x400); // Check for HFS Wrapper MDB @@ -99,13 +98,11 @@ namespace DiscImageChef.Filesystems if(drSigWord == HFSP_MAGIC) // "H+" { - ushort xdrStABNt = BigEndianBitConverter - .ToUInt16(vhSector, 0x47E); + ushort xdrStABNt = BigEndianBitConverter.ToUInt16(vhSector, 0x47E); uint drAlBlkSiz = BigEndianBitConverter.ToUInt32(vhSector, 0x414); - ushort drAlBlSt = BigEndianBitConverter - .ToUInt16(vhSector, 0x41C); + ushort drAlBlSt = BigEndianBitConverter.ToUInt16(vhSector, 0x41C); hfspOffset = (ulong)((drAlBlSt * 512 + xdrStABNt * drAlBlkSiz) / imagePlugin.GetSectorSize()); } @@ -119,8 +116,7 @@ namespace DiscImageChef.Filesystems return drSigWord == HFSP_MAGIC || drSigWord == HFSX_MAGIC; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { information = ""; @@ -133,8 +129,7 @@ namespace DiscImageChef.Filesystems uint sectorsToRead = 0x800 / imagePlugin.ImageInfo.SectorSize; if(0x800 % imagePlugin.ImageInfo.SectorSize > 0) sectorsToRead++; - byte[] vhSector = imagePlugin.ReadSectors(partition.Start, - sectorsToRead); + byte[] vhSector = imagePlugin.ReadSectors(partition.Start, sectorsToRead); drSigWord = BigEndianBitConverter.ToUInt16(vhSector, 0x400); // Check for HFS Wrapper MDB @@ -144,13 +139,11 @@ namespace DiscImageChef.Filesystems if(drSigWord == HFSP_MAGIC) // "H+" { - ushort xdrStABNt = BigEndianBitConverter - .ToUInt16(vhSector, 0x47E); + ushort xdrStABNt = BigEndianBitConverter.ToUInt16(vhSector, 0x47E); uint drAlBlkSiz = BigEndianBitConverter.ToUInt32(vhSector, 0x414); - ushort drAlBlSt = BigEndianBitConverter - .ToUInt16(vhSector, 0x41C); + ushort drAlBlSt = BigEndianBitConverter.ToUInt16(vhSector, 0x41C); hfspOffset = (ulong)((drAlBlSt * 512 + xdrStABNt * drAlBlkSiz) / imagePlugin.GetSectorSize()); wrapped = true; @@ -278,8 +271,68 @@ namespace DiscImageChef.Filesystems else return; } + public override Errno Mount() + { + return Errno.NotImplemented; + } + + public override Errno Mount(bool debug) + { + return Errno.NotImplemented; + } + + public override Errno Unmount() + { + return Errno.NotImplemented; + } + + public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + { + return Errno.NotImplemented; + } + + public override Errno GetAttributes(string path, ref FileAttributes attributes) + { + return Errno.NotImplemented; + } + + public override Errno ListXAttr(string path, ref List xattrs) + { + return Errno.NotImplemented; + } + + public override Errno GetXattr(string path, string xattr, ref byte[] buf) + { + return Errno.NotImplemented; + } + + public override Errno Read(string path, long offset, long size, ref byte[] buf) + { + return Errno.NotImplemented; + } + + public override Errno ReadDir(string path, ref List contents) + { + return Errno.NotImplemented; + } + + public override Errno StatFs(ref FileSystemInfo stat) + { + return Errno.NotImplemented; + } + + public override Errno Stat(string path, ref FileEntryInfo stat) + { + return Errno.NotImplemented; + } + + public override Errno ReadLink(string path, ref string dest) + { + return Errno.NotImplemented; + } + /// - /// HFS+ Volume Header, should be at offset 0x0400 bytes in volume with a size of 532 bytes + /// HFS+ Volume Header, should be at offset 0x0400 bytes in volume with a size of 532 bytes /// [StructLayout(LayoutKind.Sequential, Pack = 1)] struct HFSPlusVolumeHeader @@ -290,12 +343,14 @@ namespace DiscImageChef.Filesystems public ushort version; /// 0x004, Volume attributes public uint attributes; - /// 0x008, Implementation that last mounted the volume. - /// Reserved by Apple: - /// "8.10" Mac OS 8.1 to 9.2.2 - /// "10.0" Mac OS X - /// "HFSJ" Journaled implementation - /// "fsck" /sbin/fsck + /// + /// 0x008, Implementation that last mounted the volume. + /// Reserved by Apple: + /// "8.10" Mac OS 8.1 to 9.2.2 + /// "10.0" Mac OS X + /// "HFSJ" Journaled implementation + /// "fsck" /sbin/fsck + /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] lastMountedVersion; /// 0x00C, Allocation block number containing the journal public uint journalInfoBlock; @@ -541,65 +596,5 @@ namespace DiscImageChef.Filesystems /// 0x200 public uint startupFile_extents_blockCount7; } - - public override Errno Mount() - { - return Errno.NotImplemented; - } - - public override Errno Mount(bool debug) - { - return Errno.NotImplemented; - } - - public override Errno Unmount() - { - return Errno.NotImplemented; - } - - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) - { - return Errno.NotImplemented; - } - - public override Errno GetAttributes(string path, ref FileAttributes attributes) - { - return Errno.NotImplemented; - } - - public override Errno ListXAttr(string path, ref List xattrs) - { - return Errno.NotImplemented; - } - - public override Errno GetXattr(string path, string xattr, ref byte[] buf) - { - return Errno.NotImplemented; - } - - public override Errno Read(string path, long offset, long size, ref byte[] buf) - { - return Errno.NotImplemented; - } - - public override Errno ReadDir(string path, ref List contents) - { - return Errno.NotImplemented; - } - - public override Errno StatFs(ref FileSystemInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) - { - return Errno.NotImplemented; - } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/AppleMFS/Dir.cs b/DiscImageChef.Filesystems/AppleMFS/Dir.cs index 986da287..a79b6ec6 100644 --- a/DiscImageChef.Filesystems/AppleMFS/Dir.cs +++ b/DiscImageChef.Filesystems/AppleMFS/Dir.cs @@ -91,8 +91,8 @@ 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); - string lowerFilename = StringHandlers.PascalToString(entry.flNam, CurrentEncoding).ToLowerInvariant() - .Replace('/', ':'); + string lowerFilename = StringHandlers + .PascalToString(entry.flNam, CurrentEncoding).ToLowerInvariant().Replace('/', ':'); if(entry.flFlags.HasFlag(MFS_FileFlags.Used) && !idToFilename.ContainsKey(entry.flFlNum) && !idToEntry.ContainsKey(entry.flFlNum) && !filenameToId.ContainsKey(lowerFilename) && diff --git a/DiscImageChef.Filesystems/AppleMFS/File.cs b/DiscImageChef.Filesystems/AppleMFS/File.cs index ddbf8177..1905f3d1 100644 --- a/DiscImageChef.Filesystems/AppleMFS/File.cs +++ b/DiscImageChef.Filesystems/AppleMFS/File.cs @@ -169,8 +169,7 @@ namespace DiscImageChef.Filesystems.AppleMFS if(string.Compare(path, "$", StringComparison.InvariantCulture) == 0) { - stat.Blocks = directoryBlocks.Length / stat.BlockSize + - directoryBlocks.Length % stat.BlockSize; + stat.Blocks = directoryBlocks.Length / stat.BlockSize + directoryBlocks.Length % stat.BlockSize; stat.Length = directoryBlocks.Length; } else if(string.Compare(path, "$Bitmap", StringComparison.InvariantCulture) == 0) diff --git a/DiscImageChef.Filesystems/AppleMFS/Info.cs b/DiscImageChef.Filesystems/AppleMFS/Info.cs index 0f698698..ac5e66b9 100644 --- a/DiscImageChef.Filesystems/AppleMFS/Info.cs +++ b/DiscImageChef.Filesystems/AppleMFS/Info.cs @@ -56,8 +56,7 @@ namespace DiscImageChef.Filesystems.AppleMFS return drSigWord == MFS_MAGIC; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { information = ""; diff --git a/DiscImageChef.Filesystems/AppleMFS/Structs.cs b/DiscImageChef.Filesystems/AppleMFS/Structs.cs index 68512253..5f18435b 100644 --- a/DiscImageChef.Filesystems/AppleMFS/Structs.cs +++ b/DiscImageChef.Filesystems/AppleMFS/Structs.cs @@ -32,6 +32,7 @@ using System; using System.Diagnostics.CodeAnalysis; + #pragma warning disable 169 namespace DiscImageChef.Filesystems.AppleMFS @@ -42,7 +43,7 @@ namespace DiscImageChef.Filesystems.AppleMFS public partial class AppleMFS { /// - /// Master Directory Block, should be at offset 0x0400 bytes in volume + /// Master Directory Block, should be at offset 0x0400 bytes in volume /// struct MFS_MasterDirectoryBlock { @@ -79,7 +80,7 @@ namespace DiscImageChef.Filesystems.AppleMFS } /// - /// Should be at offset 0x0000 in volume, followed by boot code + /// Should be at offset 0x0000 in volume, followed by boot code /// struct MFS_BootBlock { diff --git a/DiscImageChef.Filesystems/AppleMFS/Xattr.cs b/DiscImageChef.Filesystems/AppleMFS/Xattr.cs index 1cdeaf23..250bfbdd 100644 --- a/DiscImageChef.Filesystems/AppleMFS/Xattr.cs +++ b/DiscImageChef.Filesystems/AppleMFS/Xattr.cs @@ -74,8 +74,8 @@ namespace DiscImageChef.Filesystems.AppleMFS if(!ArrayHelpers.ArrayIsNullOrEmpty(entry.flUsrWds)) xattrs.Add("com.apple.FinderInfo"); - if(debug && device.ImageInfo.ReadableSectorTags.Contains(SectorTagType.AppleSectorTag) && - entry.flLgLen > 0) xattrs.Add("com.apple.macintosh.tags"); + if(debug && device.ImageInfo.ReadableSectorTags.Contains(SectorTagType.AppleSectorTag) && entry.flLgLen > 0) + xattrs.Add("com.apple.macintosh.tags"); xattrs.Sort(); diff --git a/DiscImageChef.Filesystems/AtheOS.cs b/DiscImageChef.Filesystems/AtheOS.cs index 1268b7b6..5be52af4 100644 --- a/DiscImageChef.Filesystems/AtheOS.cs +++ b/DiscImageChef.Filesystems/AtheOS.cs @@ -93,8 +93,7 @@ namespace DiscImageChef.Filesystems return magic == AFS_MAGIC1; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { information = ""; @@ -112,7 +111,8 @@ namespace DiscImageChef.Filesystems Array.Copy(tmp, offset, sbSector, 0, AFS_SUPERBLOCK_SIZE); GCHandle handle = GCHandle.Alloc(sbSector, GCHandleType.Pinned); - AtheosSuperBlock afsSb = (AtheosSuperBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(AtheosSuperBlock)); + AtheosSuperBlock afsSb = + (AtheosSuperBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(AtheosSuperBlock)); handle.Free(); sb.AppendLine("Atheos filesystem"); @@ -121,8 +121,8 @@ namespace DiscImageChef.Filesystems 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} 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", afsSb.inode_size).AppendLine(); @@ -163,8 +163,68 @@ namespace DiscImageChef.Filesystems }; } + public override Errno Mount() + { + return Errno.NotImplemented; + } + + public override Errno Mount(bool debug) + { + return Errno.NotImplemented; + } + + public override Errno Unmount() + { + return Errno.NotImplemented; + } + + public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + { + return Errno.NotImplemented; + } + + public override Errno GetAttributes(string path, ref FileAttributes attributes) + { + return Errno.NotImplemented; + } + + public override Errno ListXAttr(string path, ref List xattrs) + { + return Errno.NotImplemented; + } + + public override Errno GetXattr(string path, string xattr, ref byte[] buf) + { + return Errno.NotImplemented; + } + + public override Errno Read(string path, long offset, long size, ref byte[] buf) + { + return Errno.NotImplemented; + } + + public override Errno ReadDir(string path, ref List contents) + { + return Errno.NotImplemented; + } + + public override Errno StatFs(ref FileSystemInfo stat) + { + return Errno.NotImplemented; + } + + public override Errno Stat(string path, ref FileEntryInfo stat) + { + return Errno.NotImplemented; + } + + public override Errno ReadLink(string path, ref string dest) + { + return Errno.NotImplemented; + } + /// - /// Be superblock + /// Be superblock /// [StructLayout(LayoutKind.Sequential, Pack = 1)] struct AtheosSuperBlock @@ -230,65 +290,5 @@ namespace DiscImageChef.Filesystems /// 0x08C, Size of bootloader public int boot_size; } - - public override Errno Mount() - { - return Errno.NotImplemented; - } - - public override Errno Mount(bool debug) - { - return Errno.NotImplemented; - } - - public override Errno Unmount() - { - return Errno.NotImplemented; - } - - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) - { - return Errno.NotImplemented; - } - - public override Errno GetAttributes(string path, ref FileAttributes attributes) - { - return Errno.NotImplemented; - } - - public override Errno ListXAttr(string path, ref List xattrs) - { - return Errno.NotImplemented; - } - - public override Errno GetXattr(string path, string xattr, ref byte[] buf) - { - return Errno.NotImplemented; - } - - public override Errno Read(string path, long offset, long size, ref byte[] buf) - { - return Errno.NotImplemented; - } - - public override Errno ReadDir(string path, ref List contents) - { - return Errno.NotImplemented; - } - - public override Errno StatFs(ref FileSystemInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) - { - return Errno.NotImplemented; - } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/BFS.cs b/DiscImageChef.Filesystems/BFS.cs index a9e0533f..7fd75385 100644 --- a/DiscImageChef.Filesystems/BFS.cs +++ b/DiscImageChef.Filesystems/BFS.cs @@ -106,8 +106,7 @@ namespace DiscImageChef.Filesystems return magic == BEFS_MAGIC1 || magicBe == BEFS_MAGIC1; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { information = ""; @@ -171,13 +170,16 @@ namespace DiscImageChef.Filesystems 1 << (int)besb.block_shift, besb.block_size).AppendLine(); } - switch(besb.flags) { + switch(besb.flags) + { case BEFS_CLEAN: sb.AppendLine(besb.log_start == besb.log_end ? "Filesystem is clean" : "Filesystem is dirty"); break; - case BEFS_DIRTY: sb.AppendLine("Filesystem is dirty"); + case BEFS_DIRTY: + sb.AppendLine("Filesystem is dirty"); break; - default: sb.AppendFormat("Unknown flags: {0:X8}", besb.flags).AppendLine(); + default: + sb.AppendFormat("Unknown flags: {0:X8}", besb.flags).AppendLine(); break; } @@ -219,64 +221,6 @@ namespace DiscImageChef.Filesystems }; } - /// - /// Be superblock - /// - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct BeSuperBlock - { - /// 0x000, Volume name, 32 bytes - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public byte[] name; - /// 0x020, "BFS1", 0x42465331 - public uint magic1; - /// 0x024, "BIGE", 0x42494745 - public uint fs_byte_order; - /// 0x028, Bytes per block - public uint block_size; - /// 0x02C, 1 << block_shift == block_size - public uint block_shift; - /// 0x030, Blocks in volume - public long num_blocks; - /// 0x038, Used blocks in volume - public long used_blocks; - /// 0x040, Bytes per inode - public int inode_size; - /// 0x044, 0xDD121031 - public uint magic2; - /// 0x048, Blocks per allocation group - public int blocks_per_ag; - /// 0x04C, 1 << ag_shift == blocks_per_ag - public int ag_shift; - /// 0x050, Allocation groups in volume - public int num_ags; - /// 0x054, 0x434c454e if clean, 0x44495254 if dirty - public uint flags; - /// 0x058, Allocation group of journal - public int log_blocks_ag; - /// 0x05C, Start block of journal, inside ag - public ushort log_blocks_start; - /// 0x05E, Length in blocks of journal, inside ag - public ushort log_blocks_len; - /// 0x060, Start of journal - public long log_start; - /// 0x068, End of journal - public long log_end; - /// 0x070, 0x15B6830E - public uint magic3; - /// 0x074, Allocation group where root folder's i-node resides - public int root_dir_ag; - /// 0x078, Start in ag of root folder's i-node - public ushort root_dir_start; - /// 0x07A, As this is part of inode_addr, this is 1 - public ushort root_dir_len; - /// 0x07C, Allocation group where indices' i-node resides - public int indices_ag; - /// 0x080, Start in ag of indices' i-node - public ushort indices_start; - /// 0x082, As this is part of inode_addr, this is 1 - public ushort indices_len; - } - public override Errno Mount() { return Errno.NotImplemented; @@ -336,5 +280,63 @@ namespace DiscImageChef.Filesystems { return Errno.NotImplemented; } + + /// + /// Be superblock + /// + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct BeSuperBlock + { + /// 0x000, Volume name, 32 bytes + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public byte[] name; + /// 0x020, "BFS1", 0x42465331 + public uint magic1; + /// 0x024, "BIGE", 0x42494745 + public uint fs_byte_order; + /// 0x028, Bytes per block + public uint block_size; + /// 0x02C, 1 << block_shift == block_size + public uint block_shift; + /// 0x030, Blocks in volume + public long num_blocks; + /// 0x038, Used blocks in volume + public long used_blocks; + /// 0x040, Bytes per inode + public int inode_size; + /// 0x044, 0xDD121031 + public uint magic2; + /// 0x048, Blocks per allocation group + public int blocks_per_ag; + /// 0x04C, 1 << ag_shift == blocks_per_ag + public int ag_shift; + /// 0x050, Allocation groups in volume + public int num_ags; + /// 0x054, 0x434c454e if clean, 0x44495254 if dirty + public uint flags; + /// 0x058, Allocation group of journal + public int log_blocks_ag; + /// 0x05C, Start block of journal, inside ag + public ushort log_blocks_start; + /// 0x05E, Length in blocks of journal, inside ag + public ushort log_blocks_len; + /// 0x060, Start of journal + public long log_start; + /// 0x068, End of journal + public long log_end; + /// 0x070, 0x15B6830E + public uint magic3; + /// 0x074, Allocation group where root folder's i-node resides + public int root_dir_ag; + /// 0x078, Start in ag of root folder's i-node + public ushort root_dir_start; + /// 0x07A, As this is part of inode_addr, this is 1 + public ushort root_dir_len; + /// 0x07C, Allocation group where indices' i-node resides + public int indices_ag; + /// 0x080, Start in ag of indices' i-node + public ushort indices_start; + /// 0x082, As this is part of inode_addr, this is 1 + public ushort indices_len; + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/BTRFS.cs b/DiscImageChef.Filesystems/BTRFS.cs index 4ff634a8..be8882b7 100644 --- a/DiscImageChef.Filesystems/BTRFS.cs +++ b/DiscImageChef.Filesystems/BTRFS.cs @@ -44,7 +44,7 @@ namespace DiscImageChef.Filesystems public class BTRFS : Filesystem { /// - /// BTRFS magic "_BHRfS_M" + /// BTRFS magic "_BHRfS_M" /// const ulong btrfsMagic = 0x4D5F53665248425F; @@ -69,62 +69,6 @@ namespace DiscImageChef.Filesystems CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); } - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct SuperBlock - { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x20)] public byte[] checksum; - public Guid uuid; - public ulong pba; - public ulong flags; - public ulong magic; - public ulong generation; - public ulong root_lba; - public ulong chunk_lba; - public ulong log_lba; - public ulong log_root_transid; - public ulong total_bytes; - public ulong bytes_used; - public ulong root_dir_objectid; - public ulong num_devices; - public uint sectorsize; - public uint nodesize; - public uint leafsize; - public uint stripesize; - public uint n; - public ulong chunk_root_generation; - public ulong compat_flags; - public ulong compat_ro_flags; - public ulong incompat_flags; - public ushort csum_type; - public byte root_level; - public byte chunk_root_level; - public byte log_root_level; - public DevItem dev_item; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x100)] public string label; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x100)] public byte[] reserved; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x800)] public byte[] chunkpairs; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x4D5)] public byte[] unused; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct DevItem - { - public ulong id; - public ulong bytes; - public ulong used; - public uint optimal_align; - public uint optimal_width; - public uint minimal_size; - public ulong type; - public ulong generation; - public ulong start_offset; - public uint dev_group; - public byte seek_speed; - public byte bandwitdh; - public Guid device_uuid; - public Guid uuid; - } - public override bool Identify(ImagePlugin imagePlugin, Partition partition) { if(partition.Start >= partition.End) return false; @@ -153,8 +97,7 @@ namespace DiscImageChef.Filesystems return btrfsSb.magic == btrfsMagic; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { StringBuilder sbInformation = new StringBuilder(); XmlFsType = new FileSystemType(); @@ -312,5 +255,61 @@ namespace DiscImageChef.Filesystems { return Errno.NotImplemented; } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct SuperBlock + { + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x20)] public byte[] checksum; + public Guid uuid; + public ulong pba; + public ulong flags; + public ulong magic; + public ulong generation; + public ulong root_lba; + public ulong chunk_lba; + public ulong log_lba; + public ulong log_root_transid; + public ulong total_bytes; + public ulong bytes_used; + public ulong root_dir_objectid; + public ulong num_devices; + public uint sectorsize; + public uint nodesize; + public uint leafsize; + public uint stripesize; + public uint n; + public ulong chunk_root_generation; + public ulong compat_flags; + public ulong compat_ro_flags; + public ulong incompat_flags; + public ushort csum_type; + public byte root_level; + public byte chunk_root_level; + public byte log_root_level; + public DevItem dev_item; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x100)] public string label; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x100)] public byte[] reserved; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x800)] public byte[] chunkpairs; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x4D5)] public byte[] unused; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct DevItem + { + public ulong id; + public ulong bytes; + public ulong used; + public uint optimal_align; + public uint optimal_width; + public uint minimal_size; + public ulong type; + public ulong generation; + public ulong start_offset; + public uint dev_group; + public byte seek_speed; + public byte bandwitdh; + public Guid device_uuid; + public Guid uuid; + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/CBM.cs b/DiscImageChef.Filesystems/CBM.cs index 91a83aaa..92f3e9d1 100644 --- a/DiscImageChef.Filesystems/CBM.cs +++ b/DiscImageChef.Filesystems/CBM.cs @@ -65,124 +65,6 @@ namespace DiscImageChef.Filesystems CurrentEncoding = new PETSCII(); } - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct CommodoreBAM - { - /// - /// Track where directory starts - /// - public byte directoryTrack; - /// - /// Sector where directory starts - /// - public byte directorySector; - /// - /// Disk DOS version, 0x41 - /// - public byte dosVersion; - /// - /// Set to 0x80 if 1571, 0x00 if not - /// - public byte doubleSided; - /// - /// Block allocation map - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 140)] public byte[] bam; - /// - /// Disk name - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] name; - /// - /// Filled with 0xA0 - /// - public ushort fill1; - /// - /// Disk ID - /// - public ushort diskId; - /// - /// Filled with 0xA0 - /// - public byte fill2; - /// - /// DOS type - /// - public ushort dosType; - /// - /// Filled with 0xA0 - /// - public uint fill3; - /// - /// Unused - /// - public byte unused1; - /// - /// Block allocation map for Dolphin DOS extended tracks - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] public byte[] dolphinBam; - /// - /// Block allocation map for Speed DOS extended tracks - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] public byte[] speedBam; - /// - /// Unused - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 9)] public byte[] unused2; - /// - /// Free sector count for second side in 1571 - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 9)] public byte[] freeCount; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct CommodoreHeader - { - /// - /// Track where directory starts - /// - public byte directoryTrack; - /// - /// Sector where directory starts - /// - public byte directorySector; - /// - /// Disk DOS version, 0x44 - /// - public byte diskDosVersion; - /// - /// Unusued - /// - public byte unused1; - /// - /// Disk name - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] name; - /// - /// Filled with 0xA0 - /// - public ushort fill1; - /// - /// Disk ID - /// - public ushort diskId; - /// - /// Filled with 0xA0 - /// - public byte fill2; - /// - /// DOS version ('3') - /// - public byte dosVersion; - /// - /// Disk version ('D') - /// - public byte diskVersion; - /// - /// Filled with 0xA0 - /// - public short fill3; - } - public override bool Identify(ImagePlugin imagePlugin, Partition partition) { if(partition.Start > 0) return false; @@ -222,8 +104,7 @@ namespace DiscImageChef.Filesystems return false; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { byte[] sector; @@ -249,13 +130,13 @@ namespace DiscImageChef.Filesystems sbInformation.AppendFormat("Directory starts at track {0} sector {1}", cbmHdr.directoryTrack, cbmHdr.directorySector).AppendLine(); - sbInformation.AppendFormat("Disk DOS Version: {0}", - Encoding.ASCII.GetString(new[] {cbmHdr.diskDosVersion})).AppendLine(); + sbInformation + .AppendFormat("Disk DOS Version: {0}", Encoding.ASCII.GetString(new[] {cbmHdr.diskDosVersion})) + .AppendLine(); sbInformation.AppendFormat("DOS Version: {0}", Encoding.ASCII.GetString(new[] {cbmHdr.dosVersion})) .AppendLine(); - sbInformation - .AppendFormat("Disk Version: {0}", Encoding.ASCII.GetString(new[] {cbmHdr.diskVersion})) - .AppendLine(); + sbInformation.AppendFormat("Disk Version: {0}", Encoding.ASCII.GetString(new[] {cbmHdr.diskVersion})) + .AppendLine(); sbInformation.AppendFormat("Disk ID: {0}", cbmHdr.diskId).AppendLine(); sbInformation.AppendFormat("Disk name: {0}", StringHandlers.CToString(cbmHdr.name, CurrentEncoding)) .AppendLine(); @@ -349,5 +230,123 @@ namespace DiscImageChef.Filesystems { return Errno.NotImplemented; } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct CommodoreBAM + { + /// + /// Track where directory starts + /// + public byte directoryTrack; + /// + /// Sector where directory starts + /// + public byte directorySector; + /// + /// Disk DOS version, 0x41 + /// + public byte dosVersion; + /// + /// Set to 0x80 if 1571, 0x00 if not + /// + public byte doubleSided; + /// + /// Block allocation map + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 140)] public byte[] bam; + /// + /// Disk name + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] name; + /// + /// Filled with 0xA0 + /// + public ushort fill1; + /// + /// Disk ID + /// + public ushort diskId; + /// + /// Filled with 0xA0 + /// + public byte fill2; + /// + /// DOS type + /// + public ushort dosType; + /// + /// Filled with 0xA0 + /// + public uint fill3; + /// + /// Unused + /// + public byte unused1; + /// + /// Block allocation map for Dolphin DOS extended tracks + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] public byte[] dolphinBam; + /// + /// Block allocation map for Speed DOS extended tracks + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] public byte[] speedBam; + /// + /// Unused + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 9)] public byte[] unused2; + /// + /// Free sector count for second side in 1571 + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 9)] public byte[] freeCount; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct CommodoreHeader + { + /// + /// Track where directory starts + /// + public byte directoryTrack; + /// + /// Sector where directory starts + /// + public byte directorySector; + /// + /// Disk DOS version, 0x44 + /// + public byte diskDosVersion; + /// + /// Unusued + /// + public byte unused1; + /// + /// Disk name + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] name; + /// + /// Filled with 0xA0 + /// + public ushort fill1; + /// + /// Disk ID + /// + public ushort diskId; + /// + /// Filled with 0xA0 + /// + public byte fill2; + /// + /// DOS version ('3') + /// + public byte dosVersion; + /// + /// Disk version ('D') + /// + public byte diskVersion; + /// + /// Filled with 0xA0 + /// + public short fill3; + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/CPM/CPM.cs b/DiscImageChef.Filesystems/CPM/CPM.cs index db875959..b7b3e15e 100644 --- a/DiscImageChef.Filesystems/CPM/CPM.cs +++ b/DiscImageChef.Filesystems/CPM/CPM.cs @@ -40,75 +40,75 @@ namespace DiscImageChef.Filesystems.CPM { partial class CPM : Filesystem { - bool mounted; readonly ImagePlugin device; - Partition partition; - /// - /// Stores all known CP/M disk definitions - /// - CpmDefinitions definitions; - /// - /// True if thinks this is a CP/M filesystem + /// True if thinks this is a CP/M filesystem /// bool cpmFound; - /// - /// If thinks this is a CP/M filesystem, this is the definition for it - /// - CpmDefinition workingDefinition; - /// - /// CP/M disc parameter block (on-memory) - /// - DiscParameterBlock dpb; - /// - /// Sector deinterleaving mask - /// - int[] sectorMask; - /// - /// The volume label, if the CP/M filesystem contains one - /// - string label; - /// - /// True if there are timestamps in Z80DOS or DOS+ format - /// - bool thirdPartyTimestamps; - /// - /// True if there are CP/M 3 timestamps - /// - bool standardTimestamps; - /// - /// Timestamp in volume label for creation - /// - byte[] labelCreationDate; - /// - /// Timestamp in volume label for update - /// - byte[] labelUpdateDate; /// - /// Cached + /// Cached /// FileSystemInfo cpmStat; /// - /// Cached directory listing + /// Cached file passwords, decoded + /// + Dictionary decodedPasswordCache; + + /// + /// Stores all known CP/M disk definitions + /// + CpmDefinitions definitions; + /// + /// Cached directory listing /// List dirList; /// - /// Cached file data + /// CP/M disc parameter block (on-memory) + /// + DiscParameterBlock dpb; + /// + /// Cached file data /// Dictionary fileCache; /// - /// Cached file + /// The volume label, if the CP/M filesystem contains one /// - Dictionary statCache; + string label; /// - /// Cached file passwords + /// Timestamp in volume label for creation + /// + byte[] labelCreationDate; + /// + /// Timestamp in volume label for update + /// + byte[] labelUpdateDate; + bool mounted; + Partition partition; + /// + /// Cached file passwords /// Dictionary passwordCache; /// - /// Cached file passwords, decoded + /// Sector deinterleaving mask /// - Dictionary decodedPasswordCache; + int[] sectorMask; + /// + /// True if there are CP/M 3 timestamps + /// + bool standardTimestamps; + /// + /// Cached file + /// + Dictionary statCache; + /// + /// True if there are timestamps in Z80DOS or DOS+ format + /// + bool thirdPartyTimestamps; + /// + /// If thinks this is a CP/M filesystem, this is the definition for it + /// + CpmDefinition workingDefinition; public CPM() { diff --git a/DiscImageChef.Filesystems/CPM/Consts.cs b/DiscImageChef.Filesystems/CPM/Consts.cs index 1b27890d..8da67be2 100644 --- a/DiscImageChef.Filesystems/CPM/Consts.cs +++ b/DiscImageChef.Filesystems/CPM/Consts.cs @@ -35,48 +35,48 @@ namespace DiscImageChef.Filesystems.CPM partial class CPM { /// - /// Enumerates the format identification byte used by CP/M-86 + /// Enumerates the format identification byte used by CP/M-86 /// enum FormatByte : byte { /// - /// 5.25" double-density single-side 8 sectors/track + /// 5.25" double-density single-side 8 sectors/track /// k160 = 0, /// - /// 5.25" double-density double-side 8 sectors/track + /// 5.25" double-density double-side 8 sectors/track /// k320 = 1, /// - /// 5.25" double-density double-side 9 sectors/track + /// 5.25" double-density double-side 9 sectors/track /// k360 = 0x10, /// - /// 5.25" double-density double-side 9 sectors/track + /// 5.25" double-density double-side 9 sectors/track /// k360Alt = 0x40, /// - /// 3.5" double-density double-side 9 sectors/track + /// 3.5" double-density double-side 9 sectors/track /// k720 = 0x11, /// - /// 3.5" double-density double-side 9 sectors/track using FEAT144 + /// 3.5" double-density double-side 9 sectors/track using FEAT144 /// f720 = 0x48, /// - /// 5.25" high-density double-side 15 sectors/track using FEAT144 + /// 5.25" high-density double-side 15 sectors/track using FEAT144 /// f1200 = 0x0C, /// - /// 3.5" high-density double-side 18 sectors/track using FEAT144 + /// 3.5" high-density double-side 18 sectors/track using FEAT144 /// f1440 = 0x90, /// - /// 5.25" double-density double-side 9 sectors/track + /// 5.25" double-density double-side 9 sectors/track /// k360Alt2 = 0x26, /// - /// 3.5" double-density double-side 9 sectors/track + /// 3.5" double-density double-side 9 sectors/track /// k720Alt = 0x94 } diff --git a/DiscImageChef.Filesystems/CPM/Definitions.cs b/DiscImageChef.Filesystems/CPM/Definitions.cs index c4145a02..b526c94e 100644 --- a/DiscImageChef.Filesystems/CPM/Definitions.cs +++ b/DiscImageChef.Filesystems/CPM/Definitions.cs @@ -41,7 +41,7 @@ namespace DiscImageChef.Filesystems.CPM partial class CPM { /// - /// Loads all the known CP/M disk definitions from an XML stored as an embedded resource. + /// Loads all the known CP/M disk definitions from an XML stored as an embedded resource. /// /// The definitions. bool LoadDefinitions() @@ -50,7 +50,8 @@ namespace DiscImageChef.Filesystems.CPM { XmlReader defsReader = XmlReader.Create(Assembly.GetExecutingAssembly() - .GetManifestResourceStream("DiscImageChef.Filesystems.CPM.cpmdefs.xml") ?? throw new InvalidOperationException()); + .GetManifestResourceStream("DiscImageChef.Filesystems.CPM.cpmdefs.xml") ?? + throw new InvalidOperationException()); XmlSerializer defsSerializer = new XmlSerializer(typeof(CpmDefinitions)); definitions = (CpmDefinitions)defsSerializer.Deserialize(defsReader); @@ -78,131 +79,132 @@ namespace DiscImageChef.Filesystems.CPM } /// - /// CP/M disk definitions + /// CP/M disk definitions /// class CpmDefinitions { /// - /// List of all CP/M disk definitions - /// - public List definitions; - /// - /// Timestamp of creation of the CP/M disk definitions list + /// Timestamp of creation of the CP/M disk definitions list /// public DateTime creation; + /// + /// List of all CP/M disk definitions + /// + public List definitions; } /// - /// CP/M disk definition + /// CP/M disk definition /// class CpmDefinition { /// - /// Comment and description - /// - public string comment; - /// - /// Encoding, "FM", "MFM", "GCR" - /// - public string encoding; - /// - /// Controller bitrate - /// - public string bitrate; - /// - /// Total cylinders - /// - public int cylinders; - /// - /// Total sides - /// - public int sides; - /// - /// Physical sectors per side - /// - public int sectorsPerTrack; - /// - /// Physical bytes per sector - /// - public int bytesPerSector; - /// - /// Physical sector interleaving - /// - public int skew; - /// - /// Description of controller's side 0 (usually, upper side) - /// - public Side side1; - /// - /// Description of controller's side 1 (usually, lower side) - /// - public Side side2; - /// - /// Cylinder/side ordering. SIDES = change side after each track, CYLINDERS = change side after whole side, EAGLE and COLUMBIA unknown - /// - public string order; - /// - /// Disk definition label - /// - public string label; - /// - /// Left shifts needed to translate allocation block number to lba - /// - public int bsh; - /// - /// Block mask for - /// - public int blm; - /// - /// Extent mask - /// - public int exm; - /// - /// Total number of 128 byte records on disk - /// - public int dsm; - /// - /// Total number of available directory entries - /// - public int drm; - /// - /// Maps the first 16 allocation blocks for reservation, high byte + /// Maps the first 16 allocation blocks for reservation, high byte /// public int al0; /// - /// Maps the first 16 allocation blocks for reservation, low byte + /// Maps the first 16 allocation blocks for reservation, low byte /// public int al1; /// - /// Tracks at the beginning of disk reserved for BIOS/BDOS + /// Controller bitrate /// - public int ofs; + public string bitrate; /// - /// Sectors at the beginning of disk reserved for BIOS/BDOS + /// Block mask for /// - public int sofs; + public int blm; /// - /// If true, all bytes written on disk are negated + /// Left shifts needed to translate allocation block number to lba + /// + public int bsh; + /// + /// Physical bytes per sector + /// + public int bytesPerSector; + /// + /// Comment and description + /// + public string comment; + /// + /// If true, all bytes written on disk are negated /// public bool complement; /// - /// Absolutely unknown? + /// Total cylinders + /// + public int cylinders; + /// + /// Total number of available directory entries + /// + public int drm; + /// + /// Total number of 128 byte records on disk + /// + public int dsm; + /// + /// Encoding, "FM", "MFM", "GCR" + /// + public string encoding; + /// + /// Absolutely unknown? /// public bool evenOdd; + /// + /// Extent mask + /// + public int exm; + /// + /// Disk definition label + /// + public string label; + /// + /// Tracks at the beginning of disk reserved for BIOS/BDOS + /// + public int ofs; + /// + /// Cylinder/side ordering. SIDES = change side after each track, CYLINDERS = change side after whole side, EAGLE and + /// COLUMBIA unknown + /// + public string order; + /// + /// Physical sectors per side + /// + public int sectorsPerTrack; + /// + /// Description of controller's side 0 (usually, upper side) + /// + public Side side1; + /// + /// Description of controller's side 1 (usually, lower side) + /// + public Side side2; + /// + /// Total sides + /// + public int sides; + /// + /// Physical sector interleaving + /// + public int skew; + /// + /// Sectors at the beginning of disk reserved for BIOS/BDOS + /// + public int sofs; } /// - /// Side descriptions + /// Side descriptions /// class Side { /// - /// Side ID as found in each sector address mark - /// - public int sideId; - /// - /// Software interleaving mask, [1,3,0,2] means CP/M LBA 0 is physical sector 1, LBA 1 = 3, so on + /// Software interleaving mask, [1,3,0,2] means CP/M LBA 0 is physical sector 1, LBA 1 = 3, so on /// public int[] sectorIds; + /// + /// Side ID as found in each sector address mark + /// + public int sideId; } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/CPM/Dir.cs b/DiscImageChef.Filesystems/CPM/Dir.cs index 17cb4bc8..aa59092f 100644 --- a/DiscImageChef.Filesystems/CPM/Dir.cs +++ b/DiscImageChef.Filesystems/CPM/Dir.cs @@ -52,10 +52,10 @@ namespace DiscImageChef.Filesystems.CPM } /// - /// Checks that the given directory blocks follow the CP/M filesystem directory specification - /// Corrupted directories will fail. - /// FAT firectories will false positive if all files start with 0x05, and do not use full extentions, for example: - /// "σAFILE.GZ" (using code page 437) + /// Checks that the given directory blocks follow the CP/M filesystem directory specification + /// Corrupted directories will fail. + /// FAT firectories will false positive if all files start with 0x05, and do not use full extentions, for example: + /// "σAFILE.GZ" (using code page 437) /// /// False if the directory does not follow the directory specification /// Directory blocks. @@ -76,17 +76,21 @@ namespace DiscImageChef.Filesystems.CPM if((entry.statusUser & 0x7F) < 0x20) { - for(int f = 0; f < 8; f++) if(entry.filename[f] < 0x20 && entry.filename[f] != 0x00) return false; + for(int f = 0; f < 8; f++) + if(entry.filename[f] < 0x20 && entry.filename[f] != 0x00) return false; - for(int e = 0; e < 3; e++) if(entry.extension[e] < 0x20 && entry.extension[e] != 0x00) return false; + for(int e = 0; e < 3; e++) + if(entry.extension[e] < 0x20 && entry.extension[e] != 0x00) return false; if(!ArrayHelpers.ArrayIsNullOrWhiteSpace(entry.filename)) fileCount++; } else if(entry.statusUser == 0x20) { - for(int f = 0; f < 8; f++) if(entry.filename[f] < 0x20 && entry.filename[f] != 0x00) return false; + for(int f = 0; f < 8; f++) + if(entry.filename[f] < 0x20 && entry.filename[f] != 0x00) return false; - for(int e = 0; e < 3; e++) if(entry.extension[e] < 0x20 && entry.extension[e] != 0x00) return false; + for(int e = 0; e < 3; e++) + if(entry.extension[e] < 0x20 && entry.extension[e] != 0x00) return false; label = Encoding.ASCII.GetString(directory, off + 1, 11).Trim(); labelCreationDate = new byte[4]; diff --git a/DiscImageChef.Filesystems/CPM/File.cs b/DiscImageChef.Filesystems/CPM/File.cs index 24f67f25..7d9551aa 100644 --- a/DiscImageChef.Filesystems/CPM/File.cs +++ b/DiscImageChef.Filesystems/CPM/File.cs @@ -51,7 +51,8 @@ namespace DiscImageChef.Filesystems.CPM return Errno.NoError; } - if(!statCache.TryGetValue(pathElements[0].ToUpperInvariant(), out FileEntryInfo fInfo)) return Errno.NoSuchFile; + if(!statCache.TryGetValue(pathElements[0].ToUpperInvariant(), out FileEntryInfo fInfo)) + return Errno.NoSuchFile; attributes = fInfo.Attributes; return Errno.NoError; @@ -91,9 +92,7 @@ namespace DiscImageChef.Filesystems.CPM public override Errno ReadLink(string path, ref string dest) { - if(!mounted) return Errno.AccessDenied; - - return Errno.NotSupported; + return !mounted ? Errno.AccessDenied : Errno.NotSupported; } public override Errno Stat(string path, ref FileEntryInfo stat) @@ -112,9 +111,9 @@ namespace DiscImageChef.Filesystems.CPM return Errno.NoError; } - if(statCache.TryGetValue(pathElements[0].ToUpperInvariant(), out stat)) return Errno.NoError; - - return Errno.NoSuchFile; + return statCache.TryGetValue(pathElements[0].ToUpperInvariant(), out stat) + ? Errno.NoError + : Errno.NoSuchFile; } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/CPM/Info.cs b/DiscImageChef.Filesystems/CPM/Info.cs index dba491f9..3723b73f 100644 --- a/DiscImageChef.Filesystems/CPM/Info.cs +++ b/DiscImageChef.Filesystems/CPM/Info.cs @@ -264,12 +264,16 @@ namespace DiscImageChef.Filesystems.CPM if(amsSb.format == 2) { - switch(amsSb.sidedness & 0x02) { - case 1: workingDefinition.order = "SIDES"; + switch(amsSb.sidedness & 0x02) + { + case 1: + workingDefinition.order = "SIDES"; break; - case 2: workingDefinition.order = "CYLINDERS"; + case 2: + workingDefinition.order = "CYLINDERS"; break; - default: workingDefinition.order = null; + default: + workingDefinition.order = null; break; } @@ -373,7 +377,6 @@ namespace DiscImageChef.Filesystems.CPM for(int si = 0; si < hddSb.sectorsPerTrack; si++) workingDefinition.side1.sectorIds[si] = si + 1; for(int si = 0; si < hddSb.spt; si++) workingDefinition.side2.sectorIds[si] = si + 1; - } } } @@ -787,7 +790,13 @@ namespace DiscImageChef.Filesystems.CPM 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) { + 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) + { // Definition seems to describe current disk, at least, same number of volume sectors and bytes per sector DicConsole.DebugWriteLine("CP/M Plugin", "Trying definition \"{0}\"", def.comment); ulong offset; @@ -805,8 +814,7 @@ namespace DiscImageChef.Filesystems.CPM else { // Head changes after every track - if(string.Compare(def.order, "SIDES", - StringComparison.InvariantCultureIgnoreCase) == 0) + if(string.Compare(def.order, "SIDES", StringComparison.InvariantCultureIgnoreCase) == 0) { sectorMask = new int[def.side1.sectorIds.Length + def.side2.sectorIds.Length]; for(int m = 0; m < def.side1.sectorIds.Length; m++) @@ -838,8 +846,9 @@ namespace DiscImageChef.Filesystems.CPM continue; } // TODO: Implement EAGLE ordering - else if(string.Compare(def.order, "EAGLE", - StringComparison.InvariantCultureIgnoreCase) == 0) + else if( + string.Compare(def.order, "EAGLE", StringComparison.InvariantCultureIgnoreCase) == 0 + ) { DicConsole.DebugWriteLine("CP/M Plugin", "Don't know how to handle EAGLE ordering, not proceeding with this definition."); @@ -873,14 +882,12 @@ namespace DiscImageChef.Filesystems.CPM // Complement of the directory bytes if needed if(def.complement) - for(int b = 0; b < directory.Length; b++) - directory[b] = (byte)(~directory[b] & 0xFF); + for(int b = 0; b < directory.Length; b++) directory[b] = (byte)(~directory[b] & 0xFF); // Check the directory if(CheckDir(directory)) { - DicConsole.DebugWriteLine("CP/M Plugin", - "Definition \"{0}\" has a correct directory", + DicConsole.DebugWriteLine("CP/M Plugin", "Definition \"{0}\" has a correct directory", def.comment); // Build a Disc Parameter Block diff --git a/DiscImageChef.Filesystems/CPM/Structs.cs b/DiscImageChef.Filesystems/CPM/Structs.cs index fc033171..8c76d536 100644 --- a/DiscImageChef.Filesystems/CPM/Structs.cs +++ b/DiscImageChef.Filesystems/CPM/Structs.cs @@ -37,496 +37,499 @@ namespace DiscImageChef.Filesystems.CPM partial class CPM { /// - /// Most of the times this structure is hard wired or generated by CP/M, not stored on disk + /// Most of the times this structure is hard wired or generated by CP/M, not stored on disk /// class DiscParameterBlock { /// - /// Sectors per track - /// - public ushort spt; - /// - /// Block shift - /// - public byte bsh; - /// - /// Block mask - /// - public byte blm; - /// - /// Extent mask - /// - public byte exm; - /// - /// Blocks on disk - 1 - /// - public ushort dsm; - /// - /// Directory entries - 1 - /// - public ushort drm; - /// - /// First byte of allocation bitmap + /// First byte of allocation bitmap /// public byte al0; /// - /// Second byte of allocation bitmap + /// Second byte of allocation bitmap /// public byte al1; /// - /// Checksum vector size + /// Block mask + /// + public byte blm; + /// + /// Block shift + /// + public byte bsh; + /// + /// Checksum vector size /// public ushort cks; /// - /// Reserved tracks + /// Directory entries - 1 + /// + public ushort drm; + /// + /// Blocks on disk - 1 + /// + public ushort dsm; + /// + /// Extent mask + /// + public byte exm; + /// + /// Reserved tracks /// public ushort off; /// - /// Physical sector shift + /// Physical sector mask + /// + public byte phm; + /// + /// Physical sector shift /// public byte psh; /// - /// Physical sector mask + /// Sectors per track /// - public byte phm; + public ushort spt; } /// - /// Amstrad superblock, for PCW + /// Amstrad superblock, for PCW /// [StructLayout(LayoutKind.Sequential, Pack = 1)] struct AmstradSuperBlock { /// - /// Format ID. 0 single-side, 3 double-side. 1 and 2 are for CPC but they don't use the superblock + /// Format ID. 0 single-side, 3 double-side. 1 and 2 are for CPC but they don't use the superblock /// public byte format; /// - /// Gives information about side ordering + /// Gives information about side ordering /// public byte sidedness; /// - /// Tracks per side, aka, cylinders + /// Tracks per side, aka, cylinders /// public byte tps; /// - /// Sectors per track + /// Sectors per track /// public byte spt; /// - /// Physical sector shift + /// Physical sector shift /// public byte psh; /// - /// Reserved tracks + /// Reserved tracks /// public byte off; /// - /// Block size shift + /// Block size shift /// public byte bsh; /// - /// How many blocks does the directory take + /// How many blocks does the directory take /// public byte dirBlocks; /// - /// GAP#3 length (intersector) + /// GAP#3 length (intersector) /// public byte gapLen; /// - /// GAP#4 length (end-of-track) + /// GAP#4 length (end-of-track) /// public byte formatGap; /// - /// Must be 0 + /// Must be 0 /// public byte zero1; /// - /// Must be 0 + /// Must be 0 /// public byte zero2; /// - /// Must be 0 + /// Must be 0 /// public byte zero3; /// - /// Must be 0 + /// Must be 0 /// public byte zero4; /// - /// Must be 0 + /// Must be 0 /// public byte zero5; /// - /// Indicates machine the boot code following the superblock is designed to boot + /// Indicates machine the boot code following the superblock is designed to boot /// public byte fiddle; } /// - /// Superblock found on CP/M-86 hard disk volumes + /// Superblock found on CP/M-86 hard disk volumes /// [StructLayout(LayoutKind.Sequential, Pack = 1)] struct HardDiskSuperBlock { /// - /// Value so the sum of all the superblock's sector bytes taken as 16-bit values gives 0 + /// Value so the sum of all the superblock's sector bytes taken as 16-bit values gives 0 /// public ushort checksum; /// - /// Copyright string + /// Copyright string /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x1F)] public byte[] copyright; /// - /// First cylinder of disk where this volume resides + /// First cylinder of disk where this volume resides /// public ushort firstCylinder; /// - /// How many cylinders does this volume span + /// How many cylinders does this volume span /// public ushort cylinders; /// - /// Heads on hard disk + /// Heads on hard disk /// public byte heads; /// - /// Sectors per track + /// Sectors per track /// public byte sectorsPerTrack; /// - /// Flags, only use by CCP/M where bit 0 equals verify on write + /// Flags, only use by CCP/M where bit 0 equals verify on write /// public byte flags; /// - /// Sector size / 128 + /// Sector size / 128 /// public byte recordsPerSector; /// - /// + /// /// public ushort spt; /// - /// + /// /// public byte bsh; /// - /// + /// /// public byte blm; /// - /// + /// /// public byte exm; /// - /// + /// /// public ushort dsm; /// - /// + /// /// public ushort drm; /// - /// + /// /// public ushort al0; /// - /// + /// /// public ushort al1; /// - /// + /// /// public ushort cks; /// - /// + /// /// public ushort off; /// - /// Must be zero + /// Must be zero /// public ushort zero1; /// - /// Must be zero + /// Must be zero /// public ushort zero2; /// - /// Must be zero + /// Must be zero /// public ushort zero3; /// - /// Must be zero + /// Must be zero /// public ushort zero4; /// - /// How many 128 bytes are in a block + /// How many 128 bytes are in a block /// public ushort recordsPerBlock; /// - /// Maximum number of bad blocks in the bad block list + /// Maximum number of bad blocks in the bad block list /// public ushort badBlockWordsMax; /// - /// Used number of bad blocks in the bad block list + /// Used number of bad blocks in the bad block list /// public ushort badBlockWords; /// - /// First block after the blocks reserved for bad block substitution + /// First block after the blocks reserved for bad block substitution /// public ushort firstSub; } /// - /// Volume label entry + /// Volume label entry /// [StructLayout(LayoutKind.Sequential, Pack = 1)] struct LabelEntry { /// - /// Must be 0x20 + /// Must be 0x20 /// public byte signature; /// - /// Label in ASCII + /// Label in ASCII /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] public byte[] label; /// - /// Label flags. Bit 0 = label exists, bit 4 = creation timestamp, bit 5 = modification timestamp, bit 6 = access timestamp, bit 7 = password enabled + /// Label flags. Bit 0 = label exists, bit 4 = creation timestamp, bit 5 = modification timestamp, bit 6 = access + /// timestamp, bit 7 = password enabled /// public byte flags; /// - /// Password decoder byte + /// Password decoder byte /// public byte passwordDecoder; /// - /// Must be 0 + /// Must be 0 /// public ushort reserved; /// - /// Password XOR'ed with + /// Password XOR'ed with /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] password; /// - /// Label creation time + /// Label creation time /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] ctime; /// - /// Label modification time + /// Label modification time /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] mtime; } /// - /// CP/M 3 timestamp entry + /// CP/M 3 timestamp entry /// [StructLayout(LayoutKind.Sequential, Pack = 1)] struct DateEntry { /// - /// Must be 0x21 + /// Must be 0x21 /// public byte signature; /// - /// File 1 create/access timestamp + /// File 1 create/access timestamp /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] date1; /// - /// File 1 modification timestamp + /// File 1 modification timestamp /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] date2; /// - /// File 1 password mode + /// File 1 password mode /// public byte mode1; public byte zero1; /// - /// File 2 create/access timestamp + /// File 2 create/access timestamp /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] date3; /// - /// File 2 modification timestamp + /// File 2 modification timestamp /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] date4; /// - /// File 2 password mode + /// File 2 password mode /// public byte mode2; public byte zero2; /// - /// File 3 create/access timestamp + /// File 3 create/access timestamp /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] date5; /// - /// File 3 modification timestamp + /// File 3 modification timestamp /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] date6; /// - /// File 3 password mode + /// File 3 password mode /// public byte mode3; public ushort zero3; } /// - /// Password entry + /// Password entry /// [StructLayout(LayoutKind.Sequential, Pack = 1)] struct PasswordEntry { /// - /// 16 + user number + /// 16 + user number /// public byte userNumber; /// - /// Filename + /// Filename /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] filename; /// - /// Extension + /// Extension /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] extension; /// - /// Password mode. Bit 7 = required for read, bit 6 = required for write, bit 5 = required for delete + /// Password mode. Bit 7 = required for read, bit 6 = required for write, bit 5 = required for delete /// public byte mode; /// - /// Password decoder byte + /// Password decoder byte /// public byte passwordDecoder; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public byte[] reserved; /// - /// Password XOR'ed with + /// Password XOR'ed with /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] password; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] reserved2; } /// - /// Timestamp for Z80DOS or DOS+ + /// Timestamp for Z80DOS or DOS+ /// [StructLayout(LayoutKind.Sequential, Pack = 1)] struct TrdPartyDateEntry { /// - /// Must be 0x21 + /// Must be 0x21 /// public byte signature; public byte zero; /// - /// Creation year for file 1 + /// Creation year for file 1 /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public byte[] create1; /// - /// Modification time for file 1 + /// Modification time for file 1 /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] modify1; /// - /// Access time for file 1 + /// Access time for file 1 /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] access1; /// - /// Creation year for file 2 + /// Creation year for file 2 /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public byte[] create2; /// - /// Modification time for file 2 + /// Modification time for file 2 /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] modify2; /// - /// Access time for file 2 + /// Access time for file 2 /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] access2; /// - /// Creation year for file 3 + /// Creation year for file 3 /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public byte[] create3; /// - /// Modification time for file 3 + /// Modification time for file 3 /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] modify3; /// - /// Access time for file 3 + /// Access time for file 3 /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] access3; } /// - /// Directory entry for <256 allocation blocks + /// Directory entry for <256 allocation blocks /// [StructLayout(LayoutKind.Sequential, Pack = 1)] struct DirectoryEntry { /// - /// User number. Bit 7 set in CP/M 1 means hidden + /// User number. Bit 7 set in CP/M 1 means hidden /// public byte statusUser; /// - /// Filename and bit 7 as flags + /// Filename and bit 7 as flags /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] filename; /// - /// Extension and bit 7 as flags + /// Extension and bit 7 as flags /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] extension; /// - /// Low byte of extent number + /// Low byte of extent number /// public byte extentCounter; /// - /// Last record bytes. In some implementations it means how many bytes are used in the last record, in others how many bytes are free. - /// It always refer to 128 byte records even if blocks are way bigger, so it's mostly useless. + /// Last record bytes. In some implementations it means how many bytes are used in the last record, in others how many + /// bytes are free. + /// It always refer to 128 byte records even if blocks are way bigger, so it's mostly useless. /// public byte lastRecordBytes; /// - /// High byte of extent number + /// High byte of extent number /// public byte extentCounterHigh; /// - /// How many records are used in this entry. 0x80 if all are used. + /// How many records are used in this entry. 0x80 if all are used. /// public byte records; /// - /// Allocation blocks + /// Allocation blocks /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] allocations; } /// - /// Directory entry for >256 allocation blocks + /// Directory entry for >256 allocation blocks /// [StructLayout(LayoutKind.Sequential, Pack = 1)] struct DirectoryEntry16 { /// - /// User number. Bit 7 set in CP/M 1 means hidden + /// User number. Bit 7 set in CP/M 1 means hidden /// public byte statusUser; /// - /// Filename and bit 7 as flags + /// Filename and bit 7 as flags /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] filename; /// - /// Extension and bit 7 as flags + /// Extension and bit 7 as flags /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] extension; /// - /// Low byte of extent number + /// Low byte of extent number /// public byte extentCounter; /// - /// Last record bytes. In some implementations it means how many bytes are used in the last record, in others how many bytes are free. - /// It always refer to 128 byte records even if blocks are way bigger, so it's mostly useless. + /// Last record bytes. In some implementations it means how many bytes are used in the last record, in others how many + /// bytes are free. + /// It always refer to 128 byte records even if blocks are way bigger, so it's mostly useless. /// public byte lastRecordBytes; /// - /// High byte of extent number + /// High byte of extent number /// public byte extentCounterHigh; /// - /// How many records are used in this entry. 0x80 if all are used. + /// How many records are used in this entry. 0x80 if all are used. /// public byte records; /// - /// Allocation blocks + /// Allocation blocks /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public ushort[] allocations; } diff --git a/DiscImageChef.Filesystems/CPM/Super.cs b/DiscImageChef.Filesystems/CPM/Super.cs index be6f8ab9..466de378 100644 --- a/DiscImageChef.Filesystems/CPM/Super.cs +++ b/DiscImageChef.Filesystems/CPM/Super.cs @@ -132,7 +132,8 @@ namespace DiscImageChef.Filesystems.CPM byte[] readSector = device.ReadSector((ulong)((int)partition.Start + p / sectorMask.Length * sectorMask.Length + sectorMask[p % sectorMask.Length])); - if(workingDefinition.complement) for(int b = 0; b < readSector.Length; b++) readSector[b] = (byte)(~readSector[b] & 0xFF); + if(workingDefinition.complement) + for(int b = 0; b < readSector.Length; b++) readSector[b] = (byte)(~readSector[b] & 0xFF); deinterleavedSectors.Add((ulong)p, readSector); } @@ -213,13 +214,14 @@ namespace DiscImageChef.Filesystems.CPM // For each directory entry for(int dOff = 0; dOff < directory.Length; dOff += 32) - // Describes a file (does not support PDOS entries with user >= 16, because they're identical to password entries + // Describes a file (does not support PDOS entries with user >= 16, because they're identical to password entries if((directory[dOff] & 0x7F) < 0x10) if(allocationBlocks.Count > 256) { dirPtr = Marshal.AllocHGlobal(32); Marshal.Copy(directory, dOff, dirPtr, 32); - DirectoryEntry16 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,11 +256,11 @@ namespace DiscImageChef.Filesystems.CPM // Do we have a stat for the file already? if(statCache.TryGetValue(filename, out FileEntryInfo fInfo)) statCache.Remove(filename); - else - { fInfo = new FileEntryInfo {Attributes = new FileAttributes()}; } + else fInfo = new FileEntryInfo {Attributes = new FileAttributes()}; // And any extent? - if(fileExtents.TryGetValue(filename, out Dictionary> extentBlocks)) fileExtents.Remove(filename); + if(fileExtents.TryGetValue(filename, out Dictionary> extentBlocks)) + fileExtents.Remove(filename); else extentBlocks = new Dictionary>(); // Do we already have this extent? Should never happen @@ -275,7 +277,8 @@ namespace DiscImageChef.Filesystems.CPM // because that's where the directory resides. // There is also a field telling how many bytes are used in the last block, but its meaning is non-standard so // we must ignore it. - foreach(ushort blk in entry.allocations.Where(blk => !blocks.Contains(blk) && blk != 0)) blocks.Add(blk); + foreach(ushort blk in entry.allocations.Where(blk => !blocks.Contains(blk) && blk != 0)) + blocks.Add(blk); // Save the file fInfo.UID = (ulong)user; @@ -341,11 +344,11 @@ namespace DiscImageChef.Filesystems.CPM // Do we have a stat for the file already? if(statCache.TryGetValue(filename, out FileEntryInfo fInfo)) statCache.Remove(filename); - else - { fInfo = new FileEntryInfo {Attributes = new FileAttributes()}; } + else fInfo = new FileEntryInfo {Attributes = new FileAttributes()}; // And any extent? - if(fileExtents.TryGetValue(filename, out Dictionary> extentBlocks)) fileExtents.Remove(filename); + if(fileExtents.TryGetValue(filename, out Dictionary> extentBlocks)) + fileExtents.Remove(filename); else extentBlocks = new Dictionary>(); // Do we already have this extent? Should never happen @@ -362,7 +365,8 @@ namespace DiscImageChef.Filesystems.CPM // because that's where the directory resides. // There is also a field telling how many bytes are used in the last block, but its meaning is non-standard so // we must ignore it. - foreach(ushort blk in entry.allocations.Cast().Where(blk => !blocks.Contains(blk) && blk != 0)) blocks.Add(blk); + foreach(ushort blk in entry.allocations.Cast() + .Where(blk => !blocks.Contains(blk) && blk != 0)) blocks.Add(blk); // Save the file fInfo.UID = (ulong)user; @@ -434,161 +438,164 @@ namespace DiscImageChef.Filesystems.CPM dirCnt++; } // Volume label and password entry. Volume password is ignored. - else switch(directory[dOff] & 0x7F) { - case 0x20: - LabelEntry labelEntry; - dirPtr = Marshal.AllocHGlobal(32); - Marshal.Copy(directory, dOff, dirPtr, 32); - labelEntry = (LabelEntry)Marshal.PtrToStructure(dirPtr, typeof(LabelEntry)); - Marshal.FreeHGlobal(dirPtr); + else + switch(directory[dOff] & 0x7F) + { + case 0x20: + LabelEntry labelEntry; + dirPtr = Marshal.AllocHGlobal(32); + Marshal.Copy(directory, dOff, dirPtr, 32); + labelEntry = (LabelEntry)Marshal.PtrToStructure(dirPtr, typeof(LabelEntry)); + Marshal.FreeHGlobal(dirPtr); - // The volume label defines if one of the fields in CP/M 3 timestamp is a creation or an access time - atime |= (labelEntry.flags & 0x40) == 0x40; + // The volume label defines if one of the fields in CP/M 3 timestamp is a creation or an access time + atime |= (labelEntry.flags & 0x40) == 0x40; - label = Encoding.ASCII.GetString(directory, dOff + 1, 11).Trim(); - labelCreationDate = new byte[4]; - labelUpdateDate = new byte[4]; - Array.Copy(directory, dOff + 24, labelCreationDate, 0, 4); - Array.Copy(directory, dOff + 28, labelUpdateDate, 0, 4); + label = Encoding.ASCII.GetString(directory, dOff + 1, 11).Trim(); + labelCreationDate = new byte[4]; + labelUpdateDate = new byte[4]; + Array.Copy(directory, dOff + 24, labelCreationDate, 0, 4); + Array.Copy(directory, dOff + 28, labelUpdateDate, 0, 4); + + // Count entries 3 by 3 for timestamps + switch(dirCnt % 3) + { + case 0: + file1 = null; + break; + case 1: + file2 = null; + break; + case 2: + file3 = null; + break; + } + + dirCnt++; + break; + case 0x21: + if(directory[dOff + 10] == 0x00 && directory[dOff + 20] == 0x00 && + directory[dOff + 30] == 0x00 && directory[dOff + 31] == 0x00) + { + dirPtr = Marshal.AllocHGlobal(32); + Marshal.Copy(directory, dOff, dirPtr, 32); + DateEntry dateEntry = (DateEntry)Marshal.PtrToStructure(dirPtr, typeof(DateEntry)); + Marshal.FreeHGlobal(dirPtr); + + FileEntryInfo fInfo; + + // Entry contains timestamps for last 3 entries, whatever the kind they are. + if(!string.IsNullOrEmpty(file1)) + { + if(statCache.TryGetValue(file1, out fInfo)) statCache.Remove(file1); + else fInfo = new FileEntryInfo(); + + if(atime) fInfo.AccessTime = DateHandlers.CpmToDateTime(dateEntry.date1); + else fInfo.CreationTime = DateHandlers.CpmToDateTime(dateEntry.date1); + + fInfo.LastWriteTime = DateHandlers.CpmToDateTime(dateEntry.date2); + + statCache.Add(file1, fInfo); + } + + if(!string.IsNullOrEmpty(file2)) + { + if(statCache.TryGetValue(file2, out fInfo)) statCache.Remove(file2); + else fInfo = new FileEntryInfo(); + + if(atime) fInfo.AccessTime = DateHandlers.CpmToDateTime(dateEntry.date3); + else fInfo.CreationTime = DateHandlers.CpmToDateTime(dateEntry.date3); + + fInfo.LastWriteTime = DateHandlers.CpmToDateTime(dateEntry.date4); + + statCache.Add(file2, fInfo); + } + + if(!string.IsNullOrEmpty(file3)) + { + if(statCache.TryGetValue(file3, out fInfo)) statCache.Remove(file3); + else fInfo = new FileEntryInfo(); + + if(atime) fInfo.AccessTime = DateHandlers.CpmToDateTime(dateEntry.date5); + else fInfo.CreationTime = DateHandlers.CpmToDateTime(dateEntry.date5); + + fInfo.LastWriteTime = DateHandlers.CpmToDateTime(dateEntry.date6); + + statCache.Add(file3, fInfo); + } - // Count entries 3 by 3 for timestamps - switch(dirCnt % 3) - { - case 0: file1 = null; - break; - case 1: file2 = null; - break; - case 2: file3 = null; - break; - } - - dirCnt++; - break; - case 0x21: - if(directory[dOff + 10] == 0x00 && directory[dOff + 20] == 0x00 && directory[dOff + 30] == 0x00 && - directory[dOff + 31] == 0x00) - { - dirPtr = Marshal.AllocHGlobal(32); - Marshal.Copy(directory, dOff, dirPtr, 32); - DateEntry dateEntry = (DateEntry)Marshal.PtrToStructure(dirPtr, typeof(DateEntry)); - Marshal.FreeHGlobal(dirPtr); - - FileEntryInfo fInfo; - - // Entry contains timestamps for last 3 entries, whatever the kind they are. - if(!string.IsNullOrEmpty(file1)) - { - if(statCache.TryGetValue(file1, out fInfo)) statCache.Remove(file1); - else fInfo = new FileEntryInfo(); - - if(atime) fInfo.AccessTime = DateHandlers.CpmToDateTime(dateEntry.date1); - else fInfo.CreationTime = DateHandlers.CpmToDateTime(dateEntry.date1); - - fInfo.LastWriteTime = DateHandlers.CpmToDateTime(dateEntry.date2); - - statCache.Add(file1, fInfo); + dirCnt = 0; } - - if(!string.IsNullOrEmpty(file2)) + // However, if this byte is 0, timestamp is in Z80DOS or DOS+ format + else if(directory[dOff + 1] == 0x00) { - if(statCache.TryGetValue(file2, out fInfo)) statCache.Remove(file2); - else fInfo = new FileEntryInfo(); + dirPtr = Marshal.AllocHGlobal(32); + Marshal.Copy(directory, dOff, dirPtr, 32); + TrdPartyDateEntry trdPartyDateEntry = + (TrdPartyDateEntry)Marshal.PtrToStructure(dirPtr, typeof(TrdPartyDateEntry)); + Marshal.FreeHGlobal(dirPtr); - if(atime) fInfo.AccessTime = DateHandlers.CpmToDateTime(dateEntry.date3); - else fInfo.CreationTime = DateHandlers.CpmToDateTime(dateEntry.date3); + FileEntryInfo fInfo; - fInfo.LastWriteTime = DateHandlers.CpmToDateTime(dateEntry.date4); + // Entry contains timestamps for last 3 entries, whatever the kind they are. + if(!string.IsNullOrEmpty(file1)) + { + if(statCache.TryGetValue(file1, out fInfo)) statCache.Remove(file1); + else fInfo = new FileEntryInfo(); - statCache.Add(file2, fInfo); + byte[] ctime = new byte[4]; + ctime[0] = trdPartyDateEntry.create1[0]; + ctime[1] = trdPartyDateEntry.create1[1]; + + fInfo.AccessTime = DateHandlers.CpmToDateTime(trdPartyDateEntry.access1); + fInfo.CreationTime = DateHandlers.CpmToDateTime(ctime); + fInfo.LastWriteTime = DateHandlers.CpmToDateTime(trdPartyDateEntry.modify1); + + statCache.Add(file1, fInfo); + } + + if(!string.IsNullOrEmpty(file2)) + { + if(statCache.TryGetValue(file2, out fInfo)) statCache.Remove(file2); + else fInfo = new FileEntryInfo(); + + byte[] ctime = new byte[4]; + ctime[0] = trdPartyDateEntry.create2[0]; + ctime[1] = trdPartyDateEntry.create2[1]; + + fInfo.AccessTime = DateHandlers.CpmToDateTime(trdPartyDateEntry.access2); + fInfo.CreationTime = DateHandlers.CpmToDateTime(ctime); + fInfo.LastWriteTime = DateHandlers.CpmToDateTime(trdPartyDateEntry.modify2); + + statCache.Add(file2, fInfo); + } + + if(!string.IsNullOrEmpty(file3)) + { + if(statCache.TryGetValue(file1, out fInfo)) statCache.Remove(file3); + else fInfo = new FileEntryInfo(); + + byte[] ctime = new byte[4]; + ctime[0] = trdPartyDateEntry.create3[0]; + ctime[1] = trdPartyDateEntry.create3[1]; + + fInfo.AccessTime = DateHandlers.CpmToDateTime(trdPartyDateEntry.access3); + fInfo.CreationTime = DateHandlers.CpmToDateTime(ctime); + fInfo.LastWriteTime = DateHandlers.CpmToDateTime(trdPartyDateEntry.modify3); + + statCache.Add(file3, fInfo); + } + + file1 = null; + file2 = null; + file3 = null; + dirCnt = 0; } - - if(!string.IsNullOrEmpty(file3)) - { - if(statCache.TryGetValue(file3, out fInfo)) statCache.Remove(file3); - else fInfo = new FileEntryInfo(); - - if(atime) fInfo.AccessTime = DateHandlers.CpmToDateTime(dateEntry.date5); - else fInfo.CreationTime = DateHandlers.CpmToDateTime(dateEntry.date5); - - fInfo.LastWriteTime = DateHandlers.CpmToDateTime(dateEntry.date6); - - statCache.Add(file3, fInfo); - } - - file1 = null; - file2 = null; - file3 = null; - dirCnt = 0; - } - // However, if this byte is 0, timestamp is in Z80DOS or DOS+ format - else if(directory[dOff + 1] == 0x00) - { - dirPtr = Marshal.AllocHGlobal(32); - Marshal.Copy(directory, dOff, dirPtr, 32); - TrdPartyDateEntry trdPartyDateEntry = (TrdPartyDateEntry)Marshal.PtrToStructure(dirPtr, typeof(TrdPartyDateEntry)); - Marshal.FreeHGlobal(dirPtr); - - FileEntryInfo fInfo; - - // Entry contains timestamps for last 3 entries, whatever the kind they are. - if(!string.IsNullOrEmpty(file1)) - { - if(statCache.TryGetValue(file1, out fInfo)) statCache.Remove(file1); - else fInfo = new FileEntryInfo(); - - byte[] ctime = new byte[4]; - ctime[0] = trdPartyDateEntry.create1[0]; - ctime[1] = trdPartyDateEntry.create1[1]; - - fInfo.AccessTime = DateHandlers.CpmToDateTime(trdPartyDateEntry.access1); - fInfo.CreationTime = DateHandlers.CpmToDateTime(ctime); - fInfo.LastWriteTime = DateHandlers.CpmToDateTime(trdPartyDateEntry.modify1); - - statCache.Add(file1, fInfo); - } - - if(!string.IsNullOrEmpty(file2)) - { - if(statCache.TryGetValue(file2, out fInfo)) statCache.Remove(file2); - else fInfo = new FileEntryInfo(); - - byte[] ctime = new byte[4]; - ctime[0] = trdPartyDateEntry.create2[0]; - ctime[1] = trdPartyDateEntry.create2[1]; - - fInfo.AccessTime = DateHandlers.CpmToDateTime(trdPartyDateEntry.access2); - fInfo.CreationTime = DateHandlers.CpmToDateTime(ctime); - fInfo.LastWriteTime = DateHandlers.CpmToDateTime(trdPartyDateEntry.modify2); - - statCache.Add(file2, fInfo); - } - - if(!string.IsNullOrEmpty(file3)) - { - if(statCache.TryGetValue(file1, out fInfo)) statCache.Remove(file3); - else fInfo = new FileEntryInfo(); - - byte[] ctime = new byte[4]; - ctime[0] = trdPartyDateEntry.create3[0]; - ctime[1] = trdPartyDateEntry.create3[1]; - - fInfo.AccessTime = DateHandlers.CpmToDateTime(trdPartyDateEntry.access3); - fInfo.CreationTime = DateHandlers.CpmToDateTime(ctime); - fInfo.LastWriteTime = DateHandlers.CpmToDateTime(trdPartyDateEntry.modify3); - - statCache.Add(file3, fInfo); - } - - file1 = null; - file2 = null; - file3 = null; - dirCnt = 0; - } - break; - } + break; + } // Cache all files. As CP/M maximum volume size is 8 Mib // this should not be a problem @@ -675,7 +682,7 @@ namespace DiscImageChef.Filesystems.CPM } /// - /// Gets information about the mounted volume. + /// Gets information about the mounted volume. /// /// Information about the mounted volume. public override Errno StatFs(ref FileSystemInfo stat) diff --git a/DiscImageChef.Filesystems/CPM/Xattr.cs b/DiscImageChef.Filesystems/CPM/Xattr.cs index 961a7fe4..0e8440d1 100644 --- a/DiscImageChef.Filesystems/CPM/Xattr.cs +++ b/DiscImageChef.Filesystems/CPM/Xattr.cs @@ -38,7 +38,7 @@ namespace DiscImageChef.Filesystems.CPM partial class CPM { /// - /// Reads an extended attribute, alternate data stream or fork from the given file. + /// Reads an extended attribute, alternate data stream or fork from the given file. /// /// Error number. /// File path. @@ -53,16 +53,19 @@ namespace DiscImageChef.Filesystems.CPM if(!fileCache.ContainsKey(pathElements[0].ToUpperInvariant())) return Errno.NoSuchFile; - if(string.Compare(xattr, "com.caldera.cpm.password", StringComparison.InvariantCulture) == 0) if(!passwordCache.TryGetValue(pathElements[0].ToUpperInvariant(), out buf)) return Errno.NoError; + if(string.Compare(xattr, "com.caldera.cpm.password", StringComparison.InvariantCulture) == 0) + if(!passwordCache.TryGetValue(pathElements[0].ToUpperInvariant(), out buf)) return Errno.NoError; if(string.Compare(xattr, "com.caldera.cpm.password.text", StringComparison.InvariantCulture) != 0) return Errno.NoSuchExtendedAttribute; - return !passwordCache.TryGetValue(pathElements[0].ToUpperInvariant(), out buf) ? Errno.NoError : Errno.NoSuchExtendedAttribute; + return !passwordCache.TryGetValue(pathElements[0].ToUpperInvariant(), out buf) + ? Errno.NoError + : Errno.NoSuchExtendedAttribute; } /// - /// Lists all extended attributes, alternate data streams and forks of the given file. + /// Lists all extended attributes, alternate data streams and forks of the given file. /// /// Error number. /// Path. diff --git a/DiscImageChef.Filesystems/Cram.cs b/DiscImageChef.Filesystems/Cram.cs index 862a3d33..44d9a1a4 100644 --- a/DiscImageChef.Filesystems/Cram.cs +++ b/DiscImageChef.Filesystems/Cram.cs @@ -42,6 +42,12 @@ namespace DiscImageChef.Filesystems { public class Cram : Filesystem { + /// + /// Identifier for Cram + /// + const uint CRAM_MAGIC = 0x28CD3D45; + const uint CRAM_CIGAM = 0x453DCD28; + public Cram() { Name = "Cram filesystem"; @@ -63,36 +69,6 @@ namespace DiscImageChef.Filesystems CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-15"); } - enum CramCompression : ushort - { - Zlib = 1, - Lzma = 2, - Lzo = 3, - Xz = 4, - Lz4 = 5 - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct CramSuperBlock - { - public uint magic; - public uint size; - public uint flags; - public uint future; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] signature; - public uint crc; - public uint edition; - public uint blocks; - public uint files; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] name; - } - - /// - /// Identifier for Cram - /// - const uint CRAM_MAGIC = 0x28CD3D45; - const uint CRAM_CIGAM = 0x453DCD28; - public override bool Identify(ImagePlugin imagePlugin, Partition partition) { if(partition.Start >= partition.End) return false; @@ -104,8 +80,7 @@ namespace DiscImageChef.Filesystems return magic == CRAM_MAGIC || magic == CRAM_CIGAM; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { byte[] sector = imagePlugin.ReadSector(partition.Start); uint magic = BitConverter.ToUInt32(sector, 0x00); @@ -113,7 +88,8 @@ namespace DiscImageChef.Filesystems CramSuperBlock crSb = new CramSuperBlock(); bool littleEndian = true; - switch(magic) { + switch(magic) + { case CRAM_MAGIC: IntPtr crSbPtr = Marshal.AllocHGlobal(Marshal.SizeOf(crSb)); Marshal.Copy(sector, 0, crSbPtr, Marshal.SizeOf(crSb)); @@ -210,5 +186,29 @@ namespace DiscImageChef.Filesystems { return Errno.NotImplemented; } + + enum CramCompression : ushort + { + Zlib = 1, + Lzma = 2, + Lzo = 3, + Xz = 4, + Lz4 = 5 + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct CramSuperBlock + { + public uint magic; + public uint size; + public uint flags; + public uint future; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] signature; + public uint crc; + public uint edition; + public uint blocks; + public uint files; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] name; + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/ECMA67.cs b/DiscImageChef.Filesystems/ECMA67.cs index 094cd594..aae0b90b 100644 --- a/DiscImageChef.Filesystems/ECMA67.cs +++ b/DiscImageChef.Filesystems/ECMA67.cs @@ -43,6 +43,8 @@ namespace DiscImageChef.Filesystems { public class ECMA67 : Filesystem { + readonly byte[] ECMA67_Magic = {0x56, 0x4F, 0x4C}; + public ECMA67() { Name = "ECMA-67"; @@ -64,27 +66,6 @@ namespace DiscImageChef.Filesystems CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1"); } - readonly byte[] ECMA67_Magic = {0x56, 0x4F, 0x4C}; - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct VolumeLabel - { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] labelIdentifier; - public byte labelNumber; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] public byte[] volumeIdentifier; - public byte volumeAccessibility; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 26)] public byte[] reserved1; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 14)] public byte[] owner; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] public byte[] reserved2; - public byte surface; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] reserved3; - public byte recordLength; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public byte[] reserved4; - public byte fileLabelAllocation; - public byte labelStandardVersion; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 48)] public byte[] reserved5; - } - public override bool Identify(ImagePlugin imagePlugin, Partition partition) { if(partition.Start > 0) return false; @@ -191,5 +172,24 @@ namespace DiscImageChef.Filesystems { return Errno.NotImplemented; } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct VolumeLabel + { + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] labelIdentifier; + public byte labelNumber; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] public byte[] volumeIdentifier; + public byte volumeAccessibility; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 26)] public byte[] reserved1; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 14)] public byte[] owner; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] public byte[] reserved2; + public byte surface; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] reserved3; + public byte recordLength; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public byte[] reserved4; + public byte fileLabelAllocation; + public byte labelStandardVersion; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 48)] public byte[] reserved5; + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/EFS.cs b/DiscImageChef.Filesystems/EFS.cs index 408c988b..fe44db79 100644 --- a/DiscImageChef.Filesystems/EFS.cs +++ b/DiscImageChef.Filesystems/EFS.cs @@ -44,54 +44,6 @@ 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) */ - public int sb_size; - /* 4: first cg offset (in bb) */ - public int sb_firstcg; - /* 8: cg size (in bb) */ - public int sb_cgfsize; - /* 12: inodes/cg (in bb) */ - public short sb_cgisize; - /* 14: geom: sectors/track */ - public short sb_sectors; - /* 16: geom: heads/cylinder (unused) */ - public short sb_heads; - /* 18: num of cg's in the filesystem */ - public short sb_ncg; - /* 20: non-0 indicates fsck required */ - public short sb_dirty; - /* 22: */ - public short sb_pad0; - /* 24: superblock ctime */ - public int sb_time; - /* 28: magic [0] */ - public uint sb_magic; - /* 32: name of filesystem */ - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] public byte[] sb_fname; - /* 38: name of filesystem pack */ - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] public byte[] sb_fpack; - /* 44: bitmap size (in bytes) */ - public int sb_bmsize; - /* 48: total free data blocks */ - public int sb_tfree; - /* 52: total free inodes */ - public int sb_tinode; - /* 56: bitmap offset (grown fs) */ - public int sb_bmblock; - /* 62: repl. superblock offset */ - public int sb_replsb; - /* 64: last allocated inode */ - public int sb_lastinode; - /* 68: unused */ - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] public byte[] sb_spare; - /* 88: checksum (all above) */ - public uint sb_checksum; - } - const uint EFS_MAGIC = 0x00072959; const uint EFS_MAGIC_NEW = 0x0007295A; @@ -163,8 +115,7 @@ namespace DiscImageChef.Filesystems return false; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { information = ""; if(imagePlugin.GetSectorSize() < 512) return; @@ -305,5 +256,53 @@ namespace DiscImageChef.Filesystems { return Errno.NotImplemented; } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + [SuppressMessage("ReSharper", "InconsistentNaming")] + struct EFS_Superblock + { + /* 0: fs size incl. bb 0 (in bb) */ + public int sb_size; + /* 4: first cg offset (in bb) */ + public int sb_firstcg; + /* 8: cg size (in bb) */ + public int sb_cgfsize; + /* 12: inodes/cg (in bb) */ + public short sb_cgisize; + /* 14: geom: sectors/track */ + public short sb_sectors; + /* 16: geom: heads/cylinder (unused) */ + public short sb_heads; + /* 18: num of cg's in the filesystem */ + public short sb_ncg; + /* 20: non-0 indicates fsck required */ + public short sb_dirty; + /* 22: */ + public short sb_pad0; + /* 24: superblock ctime */ + public int sb_time; + /* 28: magic [0] */ + public uint sb_magic; + /* 32: name of filesystem */ + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] public byte[] sb_fname; + /* 38: name of filesystem pack */ + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] public byte[] sb_fpack; + /* 44: bitmap size (in bytes) */ + public int sb_bmsize; + /* 48: total free data blocks */ + public int sb_tfree; + /* 52: total free inodes */ + public int sb_tinode; + /* 56: bitmap offset (grown fs) */ + public int sb_bmblock; + /* 62: repl. superblock offset */ + public int sb_replsb; + /* 64: last allocated inode */ + public int sb_lastinode; + /* 68: unused */ + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] public byte[] sb_spare; + /* 88: checksum (all above) */ + public uint sb_checksum; + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/F2FS.cs b/DiscImageChef.Filesystems/F2FS.cs index 504783d6..4b74a3fc 100644 --- a/DiscImageChef.Filesystems/F2FS.cs +++ b/DiscImageChef.Filesystems/F2FS.cs @@ -43,57 +43,6 @@ namespace DiscImageChef.Filesystems { public class F2FS : Filesystem { - [StructLayout(LayoutKind.Sequential, Pack = 1)] - [SuppressMessage("ReSharper", "InconsistentNaming")] - struct F2FS_Superblock - { - public uint magic; - public ushort major_ver; - public ushort minor_ver; - public uint log_sectorsize; - public uint log_sectors_per_block; - public uint log_blocksize; - public uint log_blocks_per_seg; - public uint segs_per_sec; - public uint secs_per_zone; - public uint checksum_offset; - public ulong block_count; - public uint section_count; - public uint segment_count; - public uint segment_count_ckpt; - public uint segment_count_sit; - public uint segment_count_nat; - public uint segment_count_ssa; - public uint segment_count_main; - public uint segment0_blkaddr; - public uint cp_blkaddr; - public uint sit_blkaddr; - public uint nat_blkaddr; - public uint ssa_blkaddr; - public uint main_blkaddr; - public uint root_ino; - public uint node_ino; - public uint meta_ino; - public Guid uuid; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024)] public byte[] volume_name; - public uint extension_count; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)] public byte[] extension_list1; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)] public byte[] extension_list2; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)] public byte[] extension_list3; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)] public byte[] extension_list4; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)] public byte[] extension_list5; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)] public byte[] extension_list6; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)] public byte[] extension_list7; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)] public byte[] extension_list8; - public uint cp_payload; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)] public byte[] version; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)] public byte[] init_version; - public uint feature; - public byte encryption_level; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] encrypt_pw_salt; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 871)] public byte[] reserved; - } - const uint F2FS_MAGIC = 0xF2F52010; const uint F2FS_SUPER_OFFSET = 1024; const uint F2FS_MIN_SECTOR = 512; @@ -147,8 +96,7 @@ namespace DiscImageChef.Filesystems return f2fsSb.magic == F2FS_MAGIC; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { information = ""; if(imagePlugin.GetSectorSize() < F2FS_MIN_SECTOR || imagePlugin.GetSectorSize() > F2FS_MAX_SECTOR) return; @@ -266,5 +214,56 @@ namespace DiscImageChef.Filesystems { return Errno.NotImplemented; } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + [SuppressMessage("ReSharper", "InconsistentNaming")] + struct F2FS_Superblock + { + public uint magic; + public ushort major_ver; + public ushort minor_ver; + public uint log_sectorsize; + public uint log_sectors_per_block; + public uint log_blocksize; + public uint log_blocks_per_seg; + public uint segs_per_sec; + public uint secs_per_zone; + public uint checksum_offset; + public ulong block_count; + public uint section_count; + public uint segment_count; + public uint segment_count_ckpt; + public uint segment_count_sit; + public uint segment_count_nat; + public uint segment_count_ssa; + public uint segment_count_main; + public uint segment0_blkaddr; + public uint cp_blkaddr; + public uint sit_blkaddr; + public uint nat_blkaddr; + public uint ssa_blkaddr; + public uint main_blkaddr; + public uint root_ino; + public uint node_ino; + public uint meta_ino; + public Guid uuid; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024)] public byte[] volume_name; + public uint extension_count; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)] public byte[] extension_list1; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)] public byte[] extension_list2; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)] public byte[] extension_list3; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)] public byte[] extension_list4; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)] public byte[] extension_list5; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)] public byte[] extension_list6; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)] public byte[] extension_list7; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)] public byte[] extension_list8; + public uint cp_payload; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)] public byte[] version; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)] public byte[] init_version; + public uint feature; + public byte encryption_level; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] encrypt_pw_salt; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 871)] public byte[] reserved; + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/FAT.cs b/DiscImageChef.Filesystems/FAT.cs index c87bc598..7e5b5cd3 100644 --- a/DiscImageChef.Filesystems/FAT.cs +++ b/DiscImageChef.Filesystems/FAT.cs @@ -49,6 +49,10 @@ namespace DiscImageChef.Filesystems // X68K uses cdate/adate from direntry for extending filename public class FAT : Filesystem { + const uint FSINFO_SIGNATURE1 = 0x41615252; + const uint FSINFO_SIGNATURE2 = 0x61417272; + const uint FSINFO_SIGNATURE3 = 0xAA550000; + public FAT() { Name = "Microsoft File Allocation Table"; @@ -120,10 +124,9 @@ namespace DiscImageChef.Filesystems string msxString = Encoding.ASCII.GetString(msxId); string fat32String = Encoding.ASCII.GetString(fat32Id); bool atariOemCorrect = atariOem[0] >= 0x20 && atariOem[1] >= 0x20 && atariOem[2] >= 0x20 && - atariOem[3] >= 0x20 && atariOem[4] >= 0x20 && atariOem[5] >= 0x20; - bool dosOemCorrect = dosOem[0] >= 0x20 && dosOem[1] >= 0x20 && dosOem[2] >= 0x20 && - dosOem[3] >= 0x20 && dosOem[4] >= 0x20 && dosOem[5] >= 0x20 && - dosOem[6] >= 0x20 && dosOem[7] >= 0x20; + atariOem[3] >= 0x20 && atariOem[4] >= 0x20 && atariOem[5] >= 0x20; + bool dosOemCorrect = dosOem[0] >= 0x20 && dosOem[1] >= 0x20 && dosOem[2] >= 0x20 && dosOem[3] >= 0x20 && + dosOem[4] >= 0x20 && dosOem[5] >= 0x20 && dosOem[6] >= 0x20 && dosOem[7] >= 0x20; string atariString = Encoding.ASCII.GetString(atariOem); string oemString = Encoding.ASCII.GetString(dosOem); @@ -156,7 +159,7 @@ namespace DiscImageChef.Filesystems byte apricotMediaDescriptor = bpbSector[0x5A]; ushort apricotFatSectors = BitConverter.ToUInt16(bpbSector, 0x5B); bool apricotCorrectSpc = apricotSpc == 1 || apricotSpc == 2 || apricotSpc == 4 || apricotSpc == 8 || - apricotSpc == 16 || apricotSpc == 32 || apricotSpc == 64; + apricotSpc == 16 || apricotSpc == 32 || apricotSpc == 64; int bitsInApricotBps = CountBits.Count(apricotBps); byte apricotPartitions = bpbSector[0x0C]; @@ -178,7 +181,8 @@ namespace DiscImageChef.Filesystems hugeSectors /= 4; } - switch(oemString) { + switch(oemString) + { // exFAT case "EXFAT ": return false; // NTFS @@ -200,32 +204,38 @@ namespace DiscImageChef.Filesystems if(hpfsMagic1 == 0xF995E849 && hpfsMagic2 == 0xFA53E9C5) return false; } - switch(bitsInBps) { + switch(bitsInBps) + { // FAT32 for sure - case 1 when correctSpc && numberOfFats <= 2 && sectors == 0 && fatSectors == 0 && fat32Signature == 0x29 && fat32String == "FAT32 ": return true; + case 1 when correctSpc && numberOfFats <= 2 && sectors == 0 && fatSectors == 0 && + fat32Signature == 0x29 && fat32String == "FAT32 ": return true; // short FAT32 - case 1 when correctSpc && numberOfFats <= 2 && sectors == 0 && fatSectors == 0 && fat32Signature == 0x28: + case 1 when correctSpc && numberOfFats <= 2 && sectors == 0 && fatSectors == 0 && fat32Signature == 0x28 + : return bigSectors == 0 ? hugeSectors <= partition.End - partition.Start + 1 : bigSectors <= partition.End - partition.Start + 1; // MSX-DOS FAT12 - case 1 when correctSpc && numberOfFats <= 2 && rootEntries > 0 && sectors <= partition.End - partition.Start + 1 && fatSectors > 0 && msxString == "VOL_ID": return true; + case 1 when correctSpc && numberOfFats <= 2 && rootEntries > 0 && + sectors <= partition.End - partition.Start + 1 && fatSectors > 0 && + msxString == "VOL_ID": return true; // EBPB - case 1 when correctSpc && numberOfFats <= 2 && rootEntries > 0 && fatSectors > 0 && (bpbSignature == 0x28 || bpbSignature == 0x29): + case 1 when correctSpc && numberOfFats <= 2 && rootEntries > 0 && fatSectors > 0 && + (bpbSignature == 0x28 || bpbSignature == 0x29): return sectors == 0 ? bigSectors <= partition.End - partition.Start + 1 : sectors <= partition.End - partition.Start + 1; // BPB - case 1 when correctSpc && reservedSecs < partition.End - partition.Start && numberOfFats <= 2 && rootEntries > 0 && fatSectors > 0: + case 1 when correctSpc && reservedSecs < partition.End - partition.Start && numberOfFats <= 2 && + rootEntries > 0 && fatSectors > 0: return sectors == 0 ? bigSectors <= partition.End - partition.Start + 1 : sectors <= partition.End - partition.Start + 1; } // Apricot BPB - if(bitsInApricotBps == 1 && apricotCorrectSpc && - apricotReservedSecs < partition.End - partition.Start && apricotFatsNo <= 2 && - apricotRootEntries > 0 && apricotFatSectors > 0 && + if(bitsInApricotBps == 1 && apricotCorrectSpc && apricotReservedSecs < partition.End - partition.Start && + apricotFatsNo <= 2 && apricotRootEntries > 0 && apricotFatSectors > 0 && apricotSectors <= partition.End - partition.Start + 1 && apricotPartitions == 0) return true; // All FAT12 without BPB can only be used on floppies, without partitions. @@ -243,8 +253,8 @@ namespace DiscImageChef.Filesystems bool equalFatIds = fat1Sector0[0] == fat2Sector0[0] && fat1Sector0[1] == fat2Sector0[1]; // Volume is software interleaved 2:1 MemoryStream rootMs = new MemoryStream(); - foreach(byte[] tmp in from ulong rootSector in new[] {0x17, 0x19, 0x1B, 0x1D, 0x1E, 0x20} select imagePlugin.ReadSector(rootSector)) - { rootMs.Write(tmp, 0, tmp.Length); } + foreach(byte[] tmp in from ulong rootSector in new[] {0x17, 0x19, 0x1B, 0x1D, 0x1E, 0x20} + select imagePlugin.ReadSector(rootSector)) rootMs.Write(tmp, 0, tmp.Length); byte[] rootDir = rootMs.ToArray(); bool validRootDir = true; @@ -327,8 +337,7 @@ namespace DiscImageChef.Filesystems return fatId == fat2Sector[0]; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { information = ""; @@ -397,37 +406,37 @@ namespace DiscImageChef.Filesystems int bitsInBpsApricot = CountBits.Count(apricotBpb.mainBPB.bps); bool correctSpcAtari = atariBpb.spc == 1 || atariBpb.spc == 2 || atariBpb.spc == 4 || - atariBpb.spc == 8 || atariBpb.spc == 16 || atariBpb.spc == 32 || - atariBpb.spc == 64; + atariBpb.spc == 8 || atariBpb.spc == 16 || atariBpb.spc == 32 || + atariBpb.spc == 64; bool correctSpcMsx = msxBpb.spc == 1 || msxBpb.spc == 2 || msxBpb.spc == 4 || msxBpb.spc == 8 || - msxBpb.spc == 16 || msxBpb.spc == 32 || msxBpb.spc == 64; + msxBpb.spc == 16 || msxBpb.spc == 32 || msxBpb.spc == 64; bool correctSpcDos20 = dos2Bpb.spc == 1 || dos2Bpb.spc == 2 || dos2Bpb.spc == 4 || dos2Bpb.spc == 8 || - dos2Bpb.spc == 16 || dos2Bpb.spc == 32 || dos2Bpb.spc == 64; + dos2Bpb.spc == 16 || dos2Bpb.spc == 32 || dos2Bpb.spc == 64; bool correctSpcDos30 = dos30Bpb.spc == 1 || dos30Bpb.spc == 2 || dos30Bpb.spc == 4 || - dos30Bpb.spc == 8 || dos30Bpb.spc == 16 || dos30Bpb.spc == 32 || - dos30Bpb.spc == 64; + dos30Bpb.spc == 8 || dos30Bpb.spc == 16 || dos30Bpb.spc == 32 || + dos30Bpb.spc == 64; bool correctSpcDos32 = dos32Bpb.spc == 1 || dos32Bpb.spc == 2 || dos32Bpb.spc == 4 || - dos32Bpb.spc == 8 || dos32Bpb.spc == 16 || dos32Bpb.spc == 32 || - dos32Bpb.spc == 64; + dos32Bpb.spc == 8 || dos32Bpb.spc == 16 || dos32Bpb.spc == 32 || + dos32Bpb.spc == 64; bool correctSpcDos33 = dos33Bpb.spc == 1 || dos33Bpb.spc == 2 || dos33Bpb.spc == 4 || - dos33Bpb.spc == 8 || dos33Bpb.spc == 16 || dos33Bpb.spc == 32 || - dos33Bpb.spc == 64; + dos33Bpb.spc == 8 || dos33Bpb.spc == 16 || dos33Bpb.spc == 32 || + dos33Bpb.spc == 64; bool correctSpcDos34 = shortEbpb.spc == 1 || shortEbpb.spc == 2 || shortEbpb.spc == 4 || - shortEbpb.spc == 8 || shortEbpb.spc == 16 || shortEbpb.spc == 32 || - shortEbpb.spc == 64; + shortEbpb.spc == 8 || shortEbpb.spc == 16 || shortEbpb.spc == 32 || + shortEbpb.spc == 64; bool correctSpcDos40 = ebpb.spc == 1 || ebpb.spc == 2 || ebpb.spc == 4 || ebpb.spc == 8 || - ebpb.spc == 16 || ebpb.spc == 32 || ebpb.spc == 64; + ebpb.spc == 16 || ebpb.spc == 32 || ebpb.spc == 64; bool correctSpcFat32Short = shortFat32Bpb.spc == 1 || shortFat32Bpb.spc == 2 || - shortFat32Bpb.spc == 4 || shortFat32Bpb.spc == 8 || - shortFat32Bpb.spc == 16 || shortFat32Bpb.spc == 32 || - shortFat32Bpb.spc == 64; + shortFat32Bpb.spc == 4 || shortFat32Bpb.spc == 8 || + shortFat32Bpb.spc == 16 || shortFat32Bpb.spc == 32 || + shortFat32Bpb.spc == 64; bool correctSpcFat32 = fat32Bpb.spc == 1 || fat32Bpb.spc == 2 || fat32Bpb.spc == 4 || - fat32Bpb.spc == 8 || fat32Bpb.spc == 16 || fat32Bpb.spc == 32 || - fat32Bpb.spc == 64; + fat32Bpb.spc == 8 || fat32Bpb.spc == 16 || fat32Bpb.spc == 32 || + fat32Bpb.spc == 64; bool correctSpcApricot = apricotBpb.mainBPB.spc == 1 || apricotBpb.mainBPB.spc == 2 || - apricotBpb.mainBPB.spc == 4 || apricotBpb.mainBPB.spc == 8 || - apricotBpb.mainBPB.spc == 16 || apricotBpb.mainBPB.spc == 32 || - apricotBpb.mainBPB.spc == 64; + apricotBpb.mainBPB.spc == 4 || apricotBpb.mainBPB.spc == 8 || + apricotBpb.mainBPB.spc == 16 || apricotBpb.mainBPB.spc == 32 || + apricotBpb.mainBPB.spc == 64; // This is to support FAT partitions on hybrid ISO/USB images if(imagePlugin.ImageInfo.XmlMediaType == XmlMediaType.OpticalDisc) @@ -452,9 +461,9 @@ namespace DiscImageChef.Filesystems } andosOemCorrect = dos33Bpb.oem_name[0] < 0x20 && dos33Bpb.oem_name[1] >= 0x20 && - dos33Bpb.oem_name[2] >= 0x20 && dos33Bpb.oem_name[3] >= 0x20 && - dos33Bpb.oem_name[4] >= 0x20 && dos33Bpb.oem_name[5] >= 0x20 && - dos33Bpb.oem_name[6] >= 0x20 && dos33Bpb.oem_name[7] >= 0x20; + dos33Bpb.oem_name[2] >= 0x20 && dos33Bpb.oem_name[3] >= 0x20 && + dos33Bpb.oem_name[4] >= 0x20 && dos33Bpb.oem_name[5] >= 0x20 && + dos33Bpb.oem_name[6] >= 0x20 && dos33Bpb.oem_name[7] >= 0x20; if(bitsInBpsFat32 == 1 && correctSpcFat32 && fat32Bpb.fats_no <= 2 && fat32Bpb.sectors == 0 && fat32Bpb.spfat == 0 && fat32Bpb.signature == 0x29 && @@ -515,9 +524,8 @@ namespace DiscImageChef.Filesystems userShortExtendedBpb = true; } } - else if(bitsInBpsDos33 == 1 && correctSpcDos33 && - dos33Bpb.rsectors < partition.End - partition.Start && dos33Bpb.fats_no <= 2 && - dos33Bpb.root_ent > 0 && dos33Bpb.spfat > 0) + else if(bitsInBpsDos33 == 1 && correctSpcDos33 && dos33Bpb.rsectors < partition.End - partition.Start && + dos33Bpb.fats_no <= 2 && dos33Bpb.root_ent > 0 && dos33Bpb.spfat > 0) if(dos33Bpb.sectors == 0 && dos33Bpb.hsectors <= partition.Start && dos33Bpb.big_sectors > 0 && dos33Bpb.big_sectors <= partition.End - partition.Start + 1) { @@ -603,8 +611,8 @@ namespace DiscImageChef.Filesystems bool equalFatIds = fat1Sector0[0] == fat2Sector0[0] && fat1Sector0[1] == fat2Sector0[1]; // Volume is software interleaved 2:1 MemoryStream rootMs = new MemoryStream(); - foreach(byte[] tmp in from ulong rootSector in new[] {0x17, 0x19, 0x1B, 0x1D, 0x1E, 0x20} select imagePlugin.ReadSector(rootSector)) - { rootMs.Write(tmp, 0, tmp.Length); } + foreach(byte[] tmp in from ulong rootSector in new[] {0x17, 0x19, 0x1B, 0x1D, 0x1E, 0x20} + select imagePlugin.ReadSector(rootSector)) rootMs.Write(tmp, 0, tmp.Length); byte[] rootDir = rootMs.ToArray(); bool validRootDir = true; @@ -646,7 +654,8 @@ namespace DiscImageChef.Filesystems } if(!useAtariBpb && !useMsxBpb && !useDos2Bpb && !useDos3Bpb && !useDos32Bpb && !useDos33Bpb && - !userShortExtendedBpb && !useExtendedBpb && !useShortFat32 && !useLongFat32 && !useApricotBpb && !useDecRainbowBpb) + !userShortExtendedBpb && !useExtendedBpb && !useShortFat32 && !useLongFat32 && !useApricotBpb && + !useDecRainbowBpb) { isFat12 = true; byte[] fatSector = imagePlugin.ReadSector(1 + partition.Start); @@ -1281,8 +1290,8 @@ namespace DiscImageChef.Filesystems // Check that jumps to a correct boot code position and has boot signature set. // This will mean that the volume will boot, even if just to say "this is not bootable change disk"...... if(XmlFsType.Bootable == false && fakeBpb.jump != null) - XmlFsType.Bootable |= fakeBpb.jump[0] == 0xEB && fakeBpb.jump[1] > 0x58 && - fakeBpb.jump[1] < 0x80 && fakeBpb.boot_signature == 0xAA55; + XmlFsType.Bootable |= fakeBpb.jump[0] == 0xEB && fakeBpb.jump[1] > 0x58 && fakeBpb.jump[1] < 0x80 && + fakeBpb.boot_signature == 0xAA55; sectorsPerRealSector = fakeBpb.bps / imagePlugin.ImageInfo.SectorSize; // First root directory sector @@ -1302,8 +1311,8 @@ namespace DiscImageChef.Filesystems if(useDecRainbowBpb) { MemoryStream rootMs = new MemoryStream(); - foreach(byte[] tmp in from ulong rootSector in new[] {0x17, 0x19, 0x1B, 0x1D, 0x1E, 0x20} select imagePlugin.ReadSector(rootSector)) - { rootMs.Write(tmp, 0, tmp.Length); } + foreach(byte[] tmp in from ulong rootSector in new[] {0x17, 0x19, 0x1B, 0x1D, 0x1E, 0x20} + select imagePlugin.ReadSector(rootSector)) rootMs.Write(tmp, 0, tmp.Length); rootDirectory = rootMs.ToArray(); } @@ -1334,7 +1343,8 @@ namespace DiscImageChef.Filesystems if(entry.ctime > 0 && entry.cdate > 0) { XmlFsType.CreationDate = DateHandlers.DosToDateTime(entry.cdate, entry.ctime); - if(entry.ctime_ms > 0) XmlFsType.CreationDate = XmlFsType.CreationDate.AddMilliseconds(entry.ctime_ms * 10); + if(entry.ctime_ms > 0) + XmlFsType.CreationDate = XmlFsType.CreationDate.AddMilliseconds(entry.ctime_ms * 10); XmlFsType.CreationDateSpecified = true; sb.AppendFormat("Volume created on {0}", XmlFsType.CreationDate).AppendLine(); } @@ -1365,8 +1375,68 @@ namespace DiscImageChef.Filesystems information = sb.ToString(); } + public override Errno Mount() + { + return Errno.NotImplemented; + } + + public override Errno Mount(bool debug) + { + return Errno.NotImplemented; + } + + public override Errno Unmount() + { + return Errno.NotImplemented; + } + + public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + { + return Errno.NotImplemented; + } + + public override Errno GetAttributes(string path, ref FileAttributes attributes) + { + return Errno.NotImplemented; + } + + public override Errno ListXAttr(string path, ref List xattrs) + { + return Errno.NotImplemented; + } + + public override Errno GetXattr(string path, string xattr, ref byte[] buf) + { + return Errno.NotImplemented; + } + + public override Errno Read(string path, long offset, long size, ref byte[] buf) + { + return Errno.NotImplemented; + } + + public override Errno ReadDir(string path, ref List contents) + { + return Errno.NotImplemented; + } + + public override Errno StatFs(ref FileSystemInfo stat) + { + return Errno.NotImplemented; + } + + public override Errno Stat(string path, ref FileEntryInfo stat) + { + return Errno.NotImplemented; + } + + public override Errno ReadLink(string path, ref string dest) + { + return Errno.NotImplemented; + } + /// - /// BIOS Parameter Block as used by Atari ST GEMDOS on FAT12 volumes. + /// BIOS Parameter Block as used by Atari ST GEMDOS on FAT12 volumes. /// [StructLayout(LayoutKind.Sequential, Pack = 1)] struct AtariParameterBlock @@ -1401,7 +1471,10 @@ namespace DiscImageChef.Filesystems public ushort hsectors; /// Word to be loaded in the cmdload system variable. Big-endian. public ushort execflag; - /// Word indicating load mode. If zero, file named is located and loaded. It not, sectors specified in and are loaded. Big endian. + /// + /// Word indicating load mode. If zero, file named is located and loaded. It not, sectors + /// specified in and are loaded. Big endian. + /// public ushort ldmode; /// Starting sector of boot code. public ushort ssect; @@ -1426,7 +1499,7 @@ namespace DiscImageChef.Filesystems } /// - /// BIOS Parameter Block as used by MSX-DOS 2. + /// BIOS Parameter Block as used by MSX-DOS 2. /// [StructLayout(LayoutKind.Sequential, Pack = 1)] struct MsxParameterBlock @@ -1769,7 +1842,7 @@ namespace DiscImageChef.Filesystems public uint serial_no; /// Volume label, 11 bytes, space-padded [MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] public byte[] reserved2; - /// Sectors in volume if equals 0 + /// Sectors in volume if equals 0 public ulong huge_sectors; /// Boot code. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 420)] public byte[] boot_code; @@ -2040,19 +2113,15 @@ namespace DiscImageChef.Filesystems public ushort startSector; } - const uint FSINFO_SIGNATURE1 = 0x41615252; - const uint FSINFO_SIGNATURE2 = 0x61417272; - const uint FSINFO_SIGNATURE3 = 0xAA550000; - /// FAT32 FS Information Sector [StructLayout(LayoutKind.Sequential, Pack = 1)] struct FsInfoSector { - /// Signature must be + /// Signature must be public uint signature1; /// Reserved [MarshalAs(UnmanagedType.ByValArray, SizeConst = 480)] public byte[] reserved1; - /// Signature must be + /// Signature must be public uint signature2; /// Free clusters public uint free_clusters; @@ -2060,7 +2129,7 @@ namespace DiscImageChef.Filesystems public uint last_cluster; /// Reserved [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] public byte[] reserved2; - /// Signature must be + /// Signature must be public uint signature3; } @@ -2095,65 +2164,5 @@ namespace DiscImageChef.Filesystems public ushort start_cluster; public uint size; } - - public override Errno Mount() - { - return Errno.NotImplemented; - } - - public override Errno Mount(bool debug) - { - return Errno.NotImplemented; - } - - public override Errno Unmount() - { - return Errno.NotImplemented; - } - - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) - { - return Errno.NotImplemented; - } - - public override Errno GetAttributes(string path, ref FileAttributes attributes) - { - return Errno.NotImplemented; - } - - public override Errno ListXAttr(string path, ref List xattrs) - { - return Errno.NotImplemented; - } - - public override Errno GetXattr(string path, string xattr, ref byte[] buf) - { - return Errno.NotImplemented; - } - - public override Errno Read(string path, long offset, long size, ref byte[] buf) - { - return Errno.NotImplemented; - } - - public override Errno ReadDir(string path, ref List contents) - { - return Errno.NotImplemented; - } - - public override Errno StatFs(ref FileSystemInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) - { - return Errno.NotImplemented; - } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/FATX.cs b/DiscImageChef.Filesystems/FATX.cs index 1462662a..b8b4b50f 100644 --- a/DiscImageChef.Filesystems/FATX.cs +++ b/DiscImageChef.Filesystems/FATX.cs @@ -42,15 +42,6 @@ namespace DiscImageChef.Filesystems { public class FATX : Filesystem { - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct FATX_Superblock - { - public uint magic; - public uint id; - public uint sectorsPerCluster; - public uint rootDirectoryCluster; - } - const uint FATX_MAGIC = 0x58544146; public FATX() @@ -86,8 +77,7 @@ namespace DiscImageChef.Filesystems return fatxSb.magic == FATX_MAGIC; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { information = ""; if(imagePlugin.GetSectorSize() < 512) return; @@ -178,5 +168,14 @@ namespace DiscImageChef.Filesystems { return Errno.NotImplemented; } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct FATX_Superblock + { + public uint magic; + public uint id; + public uint sectorsPerCluster; + public uint rootDirectoryCluster; + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/FFS.cs b/DiscImageChef.Filesystems/FFS.cs index fb2fee47..b226d055 100644 --- a/DiscImageChef.Filesystems/FFS.cs +++ b/DiscImageChef.Filesystems/FFS.cs @@ -49,6 +49,38 @@ namespace DiscImageChef.Filesystems [SuppressMessage("ReSharper", "InconsistentNaming")] public class FFSPlugin : Filesystem { + const uint block_size = 8192; + + // FreeBSD specifies starts at byte offsets 0, 8192, 65536 and 262144, but in other cases it's following sectors + // Without bootcode + const ulong sb_start_floppy = 0; + // With bootcode + const ulong sb_start_boot = 1; + // Dunno, longer boot code + const ulong sb_start_long_boot = 8; + // Found on AT&T for MD-2D floppieslzio + const ulong sb_start_att_dsdd = 14; + // Found on hard disks (Atari UNIX e.g.) + const ulong sb_start_piggy = 32; + + // MAGICs + // UFS magic + const uint UFS_MAGIC = 0x00011954; + // Big-endian UFS magic + const uint UFS_CIGAM = 0x54190100; + // BorderWare UFS + const uint UFS_MAGIC_BW = 0x0F242697; + // Big-endian BorderWare UFS + const uint UFS_CIGAM_BW = 0x9726240F; + // UFS2 magic + const uint UFS2_MAGIC = 0x19540119; + // Big-endian UFS2 magic + const uint UFS2_CIGAM = 0x19015419; + // Incomplete newfs + const uint UFS_BAD_MAGIC = 0x19960408; + // Big-endian incomplete newfs + const uint UFS_BAD_CIGAM = 0x08049619; + public FFSPlugin() { Name = "BSD Fast File System (aka UNIX File System, UFS)"; @@ -87,11 +119,15 @@ namespace DiscImageChef.Filesystems 262144 / imagePlugin.GetSectorSize() }; - 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); + 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, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { information = ""; StringBuilder sbInformation = new StringBuilder(); @@ -119,7 +155,8 @@ namespace DiscImageChef.Filesystems 262144 / imagePlugin.GetSectorSize() }; - foreach(ulong loc in locations.Where(loc => partition.End > partition.Start + loc + sb_size_in_sectors)) { + 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); @@ -347,12 +384,16 @@ namespace DiscImageChef.Filesystems sbInformation.AppendFormat("NINDIR: 0x{0:X8}", ufs_sb.fs_nindir).AppendLine(); sbInformation.AppendFormat("INOPB: 0x{0:X8}", ufs_sb.fs_inopb).AppendLine(); sbInformation.AppendFormat("NSPF: 0x{0:X8}", ufs_sb.fs_old_nspf).AppendLine(); - switch(ufs_sb.fs_optim) { - case 0: sbInformation.AppendLine("Filesystem will minimize allocation time"); + switch(ufs_sb.fs_optim) + { + case 0: + sbInformation.AppendLine("Filesystem will minimize allocation time"); break; - case 1: sbInformation.AppendLine("Filesystem will minimize volume fragmentation"); + case 1: + sbInformation.AppendLine("Filesystem will minimize volume fragmentation"); break; - default: sbInformation.AppendFormat("Unknown optimization value: 0x{0:X8}", ufs_sb.fs_optim).AppendLine(); + default: + sbInformation.AppendFormat("Unknown optimization value: 0x{0:X8}", ufs_sb.fs_optim).AppendLine(); break; } @@ -362,7 +403,8 @@ namespace DiscImageChef.Filesystems .AppendLine(); sbInformation.AppendFormat("Hardware sector interleave: {0}", ufs_sb.fs_old_interleave).AppendLine(); sbInformation.AppendFormat("Sector 0 skew: {0}/track", ufs_sb.fs_old_trackskew).AppendLine(); - if(!fs_type_43bsd && ufs_sb.fs_id_1 > 0 && ufs_sb.fs_id_2 > 0) sbInformation.AppendFormat("Volume ID: 0x{0:X8}{1:X8}", ufs_sb.fs_id_1, ufs_sb.fs_id_2).AppendLine(); + if(!fs_type_43bsd && ufs_sb.fs_id_1 > 0 && ufs_sb.fs_id_2 > 0) + sbInformation.AppendFormat("Volume ID: 0x{0:X8}{1:X8}", ufs_sb.fs_id_1, ufs_sb.fs_id_2).AppendLine(); else if(fs_type_43bsd && ufs_sb.fs_id_1 > 0 && ufs_sb.fs_id_2 > 0) { sbInformation.AppendFormat("{0} µsec for head switch", ufs_sb.fs_id_1).AppendLine(); @@ -451,37 +493,65 @@ namespace DiscImageChef.Filesystems information = sbInformation.ToString(); } - const uint block_size = 8192; + public override Errno Mount() + { + return Errno.NotImplemented; + } - // FreeBSD specifies starts at byte offsets 0, 8192, 65536 and 262144, but in other cases it's following sectors - // Without bootcode - const ulong sb_start_floppy = 0; - // With bootcode - const ulong sb_start_boot = 1; - // Dunno, longer boot code - const ulong sb_start_long_boot = 8; - // Found on AT&T for MD-2D floppieslzio - const ulong sb_start_att_dsdd = 14; - // Found on hard disks (Atari UNIX e.g.) - const ulong sb_start_piggy = 32; + public override Errno Mount(bool debug) + { + return Errno.NotImplemented; + } - // MAGICs - // UFS magic - const uint UFS_MAGIC = 0x00011954; - // Big-endian UFS magic - const uint UFS_CIGAM = 0x54190100; - // BorderWare UFS - const uint UFS_MAGIC_BW = 0x0F242697; - // Big-endian BorderWare UFS - const uint UFS_CIGAM_BW = 0x9726240F; - // UFS2 magic - const uint UFS2_MAGIC = 0x19540119; - // Big-endian UFS2 magic - const uint UFS2_CIGAM = 0x19015419; - // Incomplete newfs - const uint UFS_BAD_MAGIC = 0x19960408; - // Big-endian incomplete newfs - const uint UFS_BAD_CIGAM = 0x08049619; + public override Errno Unmount() + { + return Errno.NotImplemented; + } + + public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + { + return Errno.NotImplemented; + } + + public override Errno GetAttributes(string path, ref FileAttributes attributes) + { + return Errno.NotImplemented; + } + + public override Errno ListXAttr(string path, ref List xattrs) + { + return Errno.NotImplemented; + } + + public override Errno GetXattr(string path, string xattr, ref byte[] buf) + { + return Errno.NotImplemented; + } + + public override Errno Read(string path, long offset, long size, ref byte[] buf) + { + return Errno.NotImplemented; + } + + public override Errno ReadDir(string path, ref List contents) + { + return Errno.NotImplemented; + } + + public override Errno StatFs(ref FileSystemInfo stat) + { + return Errno.NotImplemented; + } + + public override Errno Stat(string path, ref FileEntryInfo stat) + { + return Errno.NotImplemented; + } + + public override Errno ReadLink(string path, ref string dest) + { + return Errno.NotImplemented; + } [StructLayout(LayoutKind.Sequential, Pack = 1)] struct csum @@ -518,8 +588,10 @@ namespace DiscImageChef.Filesystems { /// linked list of file systems public uint fs_link; - /// used for incore super blocks - /// on Sun: uint fs_rolled; // logging only: fs fully rolled + /// + /// used for incore super blocks + /// on Sun: uint fs_rolled; // logging only: fs fully rolled + /// public uint fs_rlink; /// addr of super-block in filesys public ufs_daddr_t fs_sblkno; @@ -586,21 +658,29 @@ namespace DiscImageChef.Filesystems /// value of NSPF public int fs_old_nspf; /* yet another configuration parameter */ - /// optimization preference, see below - /// On SVR: int fs_state; // file system state + /// + /// optimization preference, see below + /// On SVR: int fs_state; // file system state + /// public int fs_optim; /// # sectors/track including spares public int fs_old_npsect; /// hardware sector interleave public int fs_old_interleave; - /// sector 0 skew, per track - /// On A/UX: int fs_state; // file system state + /// + /// sector 0 skew, per track + /// On A/UX: int fs_state; // file system state + /// public int fs_old_trackskew; - /// unique filesystem id - /// On old: int fs_headswitch; // head switch time, usec + /// + /// unique filesystem id + /// On old: int fs_headswitch; // head switch time, usec + /// public int fs_id_1; - /// unique filesystem id - /// On old: int fs_trkseek; // track-to-track seek, usec + /// + /// unique filesystem id + /// On old: int fs_trkseek; // track-to-track seek, usec + /// public int fs_id_2; /* sizes determined by number of cylinder groups and their sizes */ /// blk addr of cyl grp summary area @@ -730,65 +810,5 @@ namespace DiscImageChef.Filesystems /// list of blocks for each rotation [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] public byte[] fs_rotbl; } - - public override Errno Mount() - { - return Errno.NotImplemented; - } - - public override Errno Mount(bool debug) - { - return Errno.NotImplemented; - } - - public override Errno Unmount() - { - return Errno.NotImplemented; - } - - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) - { - return Errno.NotImplemented; - } - - public override Errno GetAttributes(string path, ref FileAttributes attributes) - { - return Errno.NotImplemented; - } - - public override Errno ListXAttr(string path, ref List xattrs) - { - return Errno.NotImplemented; - } - - public override Errno GetXattr(string path, string xattr, ref byte[] buf) - { - return Errno.NotImplemented; - } - - public override Errno Read(string path, long offset, long size, ref byte[] buf) - { - return Errno.NotImplemented; - } - - public override Errno ReadDir(string path, ref List contents) - { - return Errno.NotImplemented; - } - - public override Errno StatFs(ref FileSystemInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) - { - return Errno.NotImplemented; - } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/Filesystem.cs b/DiscImageChef.Filesystems/Filesystem.cs index f9104c07..6bf0ccd3 100644 --- a/DiscImageChef.Filesystems/Filesystem.cs +++ b/DiscImageChef.Filesystems/Filesystem.cs @@ -40,22 +40,16 @@ using Schemas; namespace DiscImageChef.Filesystems { /// - /// Abstract class to implement filesystem plugins. + /// Abstract class to implement filesystem plugins. /// public abstract class Filesystem { + protected Encoding CurrentEncoding; /// Plugin name. public string Name; /// Plugin UUID. public Guid PluginUuid; internal FileSystemType XmlFsType; - protected Encoding CurrentEncoding; - - /// - /// Information about the filesystem as expected by CICM Metadata XML - /// - /// Information about the filesystem as expected by CICM Metadata XML - public FileSystemType XmlFSType => XmlFsType; protected Filesystem() { } @@ -63,7 +57,7 @@ namespace DiscImageChef.Filesystems protected Filesystem(Encoding encoding) { } /// - /// Initializes a filesystem instance prepared for reading contents + /// Initializes a filesystem instance prepared for reading contents /// /// Image plugin. /// Partition. @@ -71,7 +65,13 @@ namespace DiscImageChef.Filesystems protected Filesystem(ImagePlugin imagePlugin, Partition partition, Encoding encoding) { } /// - /// Identifies the filesystem in the specified LBA + /// Information about the filesystem as expected by CICM Metadata XML + /// + /// Information about the filesystem as expected by CICM Metadata XML + public FileSystemType XmlFSType => XmlFsType; + + /// + /// Identifies the filesystem in the specified LBA /// /// Disk image. /// Partition. @@ -79,31 +79,32 @@ namespace DiscImageChef.Filesystems public abstract bool Identify(ImagePlugin imagePlugin, Partition partition); /// - /// Gets information about the identified filesystem. + /// Gets information about the identified filesystem. /// /// Disk image. /// Partition. /// Filesystem information. - public abstract void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information); + public abstract void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information); /// - /// Initializates whatever internal structures the filesystem plugin needs to be able to read files and directories from the filesystem. + /// Initializates whatever internal structures the filesystem plugin needs to be able to read files and directories + /// from the filesystem. /// public abstract Errno Mount(); /// - /// Initializates whatever internal structures the filesystem plugin needs to be able to read files and directories from the filesystem. + /// Initializates whatever internal structures the filesystem plugin needs to be able to read files and directories + /// from the filesystem. /// public abstract Errno Mount(bool debug); /// - /// Frees all internal structures created by + /// Frees all internal structures created by /// public abstract Errno Unmount(); /// - /// Maps a filesystem block from a file to a block from the underlying device. + /// Maps a filesystem block from a file to a block from the underlying device. /// /// Error number. /// File path. @@ -112,7 +113,7 @@ namespace DiscImageChef.Filesystems public abstract Errno MapBlock(string path, long fileBlock, ref long deviceBlock); /// - /// Gets the attributes of a file or directory + /// Gets the attributes of a file or directory /// /// Error number. /// File path. @@ -120,7 +121,7 @@ namespace DiscImageChef.Filesystems public abstract Errno GetAttributes(string path, ref FileAttributes attributes); /// - /// Lists all extended attributes, alternate data streams and forks of the given file. + /// Lists all extended attributes, alternate data streams and forks of the given file. /// /// Error number. /// Path. @@ -128,7 +129,7 @@ namespace DiscImageChef.Filesystems public abstract Errno ListXAttr(string path, ref List xattrs); /// - /// Reads an extended attribute, alternate data stream or fork from the given file. + /// Reads an extended attribute, alternate data stream or fork from the given file. /// /// Error number. /// File path. @@ -137,7 +138,7 @@ namespace DiscImageChef.Filesystems public abstract Errno GetXattr(string path, string xattr, ref byte[] buf); /// - /// Reads data from a file (main/only data stream or data fork). + /// Reads data from a file (main/only data stream or data fork). /// /// File path. /// Offset. @@ -146,27 +147,27 @@ namespace DiscImageChef.Filesystems public abstract Errno Read(string path, long offset, long size, ref byte[] buf); /// - /// Lists contents from a directory. + /// Lists contents from a directory. /// /// Directory path. /// Directory contents. public abstract Errno ReadDir(string path, ref List contents); /// - /// Gets information about the mounted volume. + /// Gets information about the mounted volume. /// /// Information about the mounted volume. public abstract Errno StatFs(ref FileSystemInfo stat); /// - /// Gets information about a file or directory. + /// Gets information about a file or directory. /// /// File path. /// File information. public abstract Errno Stat(string path, ref FileEntryInfo stat); /// - /// Solves a symbolic link. + /// Solves a symbolic link. /// /// Link path. /// Link destination. diff --git a/DiscImageChef.Filesystems/Fossil.cs b/DiscImageChef.Filesystems/Fossil.cs index 61ef2279..2887524c 100644 --- a/DiscImageChef.Filesystems/Fossil.cs +++ b/DiscImageChef.Filesystems/Fossil.cs @@ -43,84 +43,6 @@ namespace DiscImageChef.Filesystems { public class Fossil : Filesystem { - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct FossilHeader - { - /// - /// Magic number - /// - public uint magic; - /// - /// Header version - /// - public ushort version; - /// - /// Block size - /// - public ushort blockSize; - /// - /// Block containing superblock - /// - public uint super; - /// - /// Block containing labels - /// - public uint label; - /// - /// Where do data blocks start - /// - public uint data; - /// - /// How many data blocks does it have - /// - public uint end; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct FossilSuperBlock - { - /// - /// Magic number - /// - public uint magic; - /// - /// Header version - /// - public ushort version; - /// - /// file system low epoch - /// - public uint epochLow; - /// - /// file system high(active) epoch - /// - public uint epochHigh; - /// - /// next qid to allocate - /// - public ulong qid; - /// - /// data block number: root of active file system - /// - public int active; - /// - /// data block number: root of next file system to archive - /// - public int next; - /// - /// data block number: root of file system currently being archived - /// - public int current; - /// - /// Venti score of last successful archive - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] public byte[] last; - /// - /// name of file system(just a comment) - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] public byte[] name; - } - const uint FOSSIL_HDR_MAGIC = 0x3776AE89; const uint FOSSIL_SB_MAGIC = 0x2340A3B1; // Fossil header starts at 128KiB @@ -166,8 +88,7 @@ namespace DiscImageChef.Filesystems return hdr.magic == FOSSIL_HDR_MAGIC; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { information = ""; if(imagePlugin.GetSectorSize() < 512) return; @@ -285,5 +206,83 @@ namespace DiscImageChef.Filesystems { return Errno.NotImplemented; } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct FossilHeader + { + /// + /// Magic number + /// + public uint magic; + /// + /// Header version + /// + public ushort version; + /// + /// Block size + /// + public ushort blockSize; + /// + /// Block containing superblock + /// + public uint super; + /// + /// Block containing labels + /// + public uint label; + /// + /// Where do data blocks start + /// + public uint data; + /// + /// How many data blocks does it have + /// + public uint end; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct FossilSuperBlock + { + /// + /// Magic number + /// + public uint magic; + /// + /// Header version + /// + public ushort version; + /// + /// file system low epoch + /// + public uint epochLow; + /// + /// file system high(active) epoch + /// + public uint epochHigh; + /// + /// next qid to allocate + /// + public ulong qid; + /// + /// data block number: root of active file system + /// + public int active; + /// + /// data block number: root of next file system to archive + /// + public int next; + /// + /// data block number: root of file system currently being archived + /// + public int current; + /// + /// Venti score of last successful archive + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] public byte[] last; + /// + /// name of file system(just a comment) + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] public byte[] name; + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/HAMMER.cs b/DiscImageChef.Filesystems/HAMMER.cs index ec033e96..c4bae14e 100644 --- a/DiscImageChef.Filesystems/HAMMER.cs +++ b/DiscImageChef.Filesystems/HAMMER.cs @@ -41,12 +41,11 @@ 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; @@ -92,8 +91,7 @@ namespace DiscImageChef.Filesystems return magic == HAMMER_FSBUF_VOLUME || magic == HAMMER_FSBUF_VOLUME_REV; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { information = ""; @@ -115,7 +113,7 @@ namespace DiscImageChef.Filesystems { GCHandle handle = GCHandle.Alloc(sbSector, GCHandleType.Pinned); hammerSb = (HammerSuperBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), - typeof(HammerSuperBlock)); + typeof(HammerSuperBlock)); handle.Free(); } else hammerSb = BigEndianMarshal.ByteArrayToStructureBigEndian(sbSector); @@ -164,91 +162,6 @@ namespace DiscImageChef.Filesystems information = sb.ToString(); } - /// - /// Be superblock - /// - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct HammerSuperBlock - { - /// for a valid header - public ulong vol_signature; - - /* These are relative to block device offset, not zone offsets. */ - /// offset of boot area - public long vol_bot_beg; - /// offset of memory log - public long vol_mem_beg; - /// offset of the first buffer in volume - public long vol_buf_beg; - /// offset of volume EOF (on buffer boundary) - public long vol_buf_end; - public long vol_reserved01; - - /// identify filesystem - public Guid vol_fsid; - /// identify filesystem type - public Guid vol_fstype; - /// filesystem label - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)] public byte[] vol_label; - - /// volume number within filesystem - public int vol_no; - /// number of volumes making up filesystem - public int vol_count; - - /// version control information - public uint vol_version; - /// header crc - public hammer_crc_t vol_crc; - /// volume flags - public uint vol_flags; - /// the root volume number (must be 0) - public uint vol_rootvol; - - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public uint[] vol_reserved; - - /* - * These fields are initialized and space is reserved in every - * volume making up a HAMMER filesytem, but only the root volume - * contains valid data. Note that vol0_stat_bigblocks does not - * include big-blocks for freemap and undomap initially allocated - * by newfs_hammer(8). - */ - /// total big-blocks when fs is empty - public long vol0_stat_bigblocks; - /// number of free big-blocks - public long vol0_stat_freebigblocks; - public long vol0_reserved01; - /// for statfs only - public long vol0_stat_inodes; - public long vol0_reserved02; - /// B-Tree root offset in zone-8 - public hammer_off_t vol0_btree_root; - /// highest partially synchronized TID - public hammer_tid_t vol0_next_tid; - public hammer_off_t vol0_reserved03; - - /// Blockmaps for zones. Not all zones use a blockmap. Note that the entire root blockmap is cached in the hammer_mount structure. - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public HammerBlockMap[] vol0_blockmap; - - /// Array of zone-2 addresses for undo FIFO. - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] public hammer_off_t[] vol0_undo_array; - } - - struct HammerBlockMap - { - /// zone-2 offset only used by zone-4 - public hammer_off_t phys_offset; - /// zone-X offset only used by zone-3 - public hammer_off_t first_offset; - /// zone-X offset for allocation - public hammer_off_t next_offset; - /// zone-X offset only used by zone-3 - public hammer_off_t alloc_offset; - public uint reserved01; - public hammer_crc_t entry_crc; - } - public override Errno Mount() { return Errno.NotImplemented; @@ -308,5 +221,96 @@ namespace DiscImageChef.Filesystems { return Errno.NotImplemented; } + + /// + /// Hammer superblock + /// + [StructLayout(LayoutKind.Sequential, Pack = 1)] + [SuppressMessage("ReSharper", "BuiltInTypeReferenceStyle")] + struct HammerSuperBlock + { + /// for a valid header + public ulong vol_signature; + + /* These are relative to block device offset, not zone offsets. */ + /// offset of boot area + public long vol_bot_beg; + /// offset of memory log + public long vol_mem_beg; + /// offset of the first buffer in volume + public long vol_buf_beg; + /// offset of volume EOF (on buffer boundary) + public long vol_buf_end; + public long vol_reserved01; + + /// identify filesystem + public Guid vol_fsid; + /// identify filesystem type + public Guid vol_fstype; + /// filesystem label + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)] public byte[] vol_label; + + /// volume number within filesystem + public int vol_no; + /// number of volumes making up filesystem + public int vol_count; + + /// version control information + public uint vol_version; + /// header crc + public hammer_crc_t vol_crc; + /// volume flags + public uint vol_flags; + /// the root volume number (must be 0) + public uint vol_rootvol; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public uint[] vol_reserved; + + /* + * These fields are initialized and space is reserved in every + * volume making up a HAMMER filesytem, but only the root volume + * contains valid data. Note that vol0_stat_bigblocks does not + * include big-blocks for freemap and undomap initially allocated + * by newfs_hammer(8). + */ + /// total big-blocks when fs is empty + public long vol0_stat_bigblocks; + /// number of free big-blocks + public long vol0_stat_freebigblocks; + public long vol0_reserved01; + /// for statfs only + public long vol0_stat_inodes; + public long vol0_reserved02; + /// B-Tree root offset in zone-8 + public hammer_off_t vol0_btree_root; + /// highest partially synchronized TID + public hammer_tid_t vol0_next_tid; + public hammer_off_t vol0_reserved03; + + /// + /// Blockmaps for zones. Not all zones use a blockmap. Note that the entire root blockmap is cached in the + /// hammer_mount structure. + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public HammerBlockMap[] vol0_blockmap; + + /// Array of zone-2 addresses for undo FIFO. + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] public hammer_off_t[] vol0_undo_array; + } + + [SuppressMessage("ReSharper", "InconsistentNaming")] + [SuppressMessage("ReSharper", "BuiltInTypeReferenceStyle")] + struct HammerBlockMap + { + /// zone-2 offset only used by zone-4 + public hammer_off_t phys_offset; + /// zone-X offset only used by zone-3 + public hammer_off_t first_offset; + /// zone-X offset for allocation + public hammer_off_t next_offset; + /// zone-X offset only used by zone-3 + public hammer_off_t alloc_offset; + public uint reserved01; + public hammer_crc_t entry_crc; + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/HPFS.cs b/DiscImageChef.Filesystems/HPFS.cs index b74aa1d0..23da8d03 100644 --- a/DiscImageChef.Filesystems/HPFS.cs +++ b/DiscImageChef.Filesystems/HPFS.cs @@ -79,8 +79,7 @@ namespace DiscImageChef.Filesystems return magic1 == 0xF995E849 && magic2 == 0xFA53E9C5; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { information = ""; @@ -95,7 +94,8 @@ namespace DiscImageChef.Filesystems IntPtr bpbPtr = Marshal.AllocHGlobal(512); Marshal.Copy(hpfsBpbSector, 0, bpbPtr, 512); - HPFS_BIOSParameterBlock hpfsBpb = (HPFS_BIOSParameterBlock)Marshal.PtrToStructure(bpbPtr, typeof(HPFS_BIOSParameterBlock)); + HPFS_BIOSParameterBlock hpfsBpb = + (HPFS_BIOSParameterBlock)Marshal.PtrToStructure(bpbPtr, typeof(HPFS_BIOSParameterBlock)); Marshal.FreeHGlobal(bpbPtr); IntPtr sbPtr = Marshal.AllocHGlobal(512); @@ -214,148 +214,6 @@ namespace DiscImageChef.Filesystems information = sb.ToString(); } - /// - /// BIOS Parameter Block, at sector 0 - /// - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct HPFS_BIOSParameterBlock - { - /// 0x000, Jump to boot code - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] jump; - /// 0x003, OEM Name, 8 bytes, space-padded - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] oem_name; - /// 0x00B, Bytes per sector - public ushort bps; - /// 0x00D, Sectors per cluster - public byte spc; - /// 0x00E, Reserved sectors between BPB and... does it have sense in HPFS? - public ushort rsectors; - /// 0x010, Number of FATs... seriously? - public byte fats_no; - /// 0x011, Number of entries on root directory... ok - public ushort root_ent; - /// 0x013, Sectors in volume... doubt it - public ushort sectors; - /// 0x015, Media descriptor - public byte media; - /// 0x016, Sectors per FAT... again - public ushort spfat; - /// 0x018, Sectors per track... you're kidding - public ushort sptrk; - /// 0x01A, Heads... stop! - public ushort heads; - /// 0x01C, Hidden sectors before BPB - public uint hsectors; - /// 0x024, Sectors in volume if > 65535... - public uint big_sectors; - /// 0x028, Drive number - public byte drive_no; - /// 0x029, Volume flags? - public byte nt_flags; - /// 0x02A, EPB signature, 0x29 - public byte signature; - /// 0x02B, Volume serial number - public uint serial_no; - /// 0x02F, Volume label, 11 bytes, space-padded - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] public byte[] volume_label; - /// 0x03A, Filesystem type, 8 bytes, space-padded ("HPFS ") - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] fs_type; - /// Boot code. - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 448)] public byte[] boot_code; - /// 0x1FE, 0xAA55 - public ushort signature2; - } - - /// - /// HPFS superblock at sector 16 - /// - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct HPFS_SuperBlock - { - /// 0x000, 0xF995E849 - public uint magic1; - /// 0x004, 0xFA53E9C5 - public uint magic2; - /// 0x008, HPFS version - public byte version; - /// 0x009, 2 if <= 4 GiB, 3 if > 4 GiB - public byte func_version; - /// 0x00A, Alignment - public ushort dummy; - /// 0x00C, LSN pointer to root fnode - public uint root_fnode; - /// 0x010, Sectors on volume - public uint sectors; - /// 0x014, Bad blocks on volume - public uint badblocks; - /// 0x018, LSN pointer to volume bitmap - public uint bitmap_lsn; - /// 0x01C, 0 - public uint zero1; - /// 0x020, LSN pointer to badblock directory - public uint badblock_lsn; - /// 0x024, 0 - public uint zero2; - /// 0x028, Time of last CHKDSK - public int last_chkdsk; - /// 0x02C, Time of last optimization - public int last_optim; - /// 0x030, Sectors of dir band - public uint dband_sectors; - /// 0x034, Start sector of dir band - public uint dband_start; - /// 0x038, Last sector of dir band - public uint dband_last; - /// 0x03C, LSN of free space bitmap - public uint dband_bitmap; - /// 0x040, Can be used for volume name (32 bytes) - public ulong zero3; - /// 0x048, ... - public ulong zero4; - /// 0x04C, ... - public ulong zero5; - /// 0x050, ...; - public ulong zero6; - /// 0x058, LSN pointer to ACLs (only HPFS386) - public uint acl_start; - } - - /// - /// HPFS spareblock at sector 17 - /// - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct HPFS_SpareBlock - { - /// 0x000, 0xF9911849 - public uint magic1; - /// 0x004, 0xFA5229C5 - public uint magic2; - /// 0x008, HPFS flags - public byte flags1; - /// 0x009, HPFS386 flags - public byte flags2; - /// 0x00A, Alignment - public ushort dummy; - /// 0x00C, LSN of hotfix directory - public uint hotfix_start; - /// 0x010, Used hotfixes - public uint hotfix_used; - /// 0x014, Total hotfixes available - public uint hotfix_entries; - /// 0x018, Unused spare dnodes - public uint spare_dnodes_free; - /// 0x01C, Length of spare dnodes list - public uint spare_dnodes; - /// 0x020, LSN of codepage directory - public uint codepage_lsn; - /// 0x024, Number of codepages used - public uint codepages; - /// 0x028, SuperBlock CRC32 (only HPFS386) - public uint sb_crc32; - /// 0x02C, SpareBlock CRC32 (only HPFS386) - public uint sp_crc32; - } - public override Errno Mount() { return Errno.NotImplemented; @@ -415,5 +273,147 @@ namespace DiscImageChef.Filesystems { return Errno.NotImplemented; } + + /// + /// BIOS Parameter Block, at sector 0 + /// + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct HPFS_BIOSParameterBlock + { + /// 0x000, Jump to boot code + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] jump; + /// 0x003, OEM Name, 8 bytes, space-padded + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] oem_name; + /// 0x00B, Bytes per sector + public ushort bps; + /// 0x00D, Sectors per cluster + public byte spc; + /// 0x00E, Reserved sectors between BPB and... does it have sense in HPFS? + public ushort rsectors; + /// 0x010, Number of FATs... seriously? + public byte fats_no; + /// 0x011, Number of entries on root directory... ok + public ushort root_ent; + /// 0x013, Sectors in volume... doubt it + public ushort sectors; + /// 0x015, Media descriptor + public byte media; + /// 0x016, Sectors per FAT... again + public ushort spfat; + /// 0x018, Sectors per track... you're kidding + public ushort sptrk; + /// 0x01A, Heads... stop! + public ushort heads; + /// 0x01C, Hidden sectors before BPB + public uint hsectors; + /// 0x024, Sectors in volume if > 65535... + public uint big_sectors; + /// 0x028, Drive number + public byte drive_no; + /// 0x029, Volume flags? + public byte nt_flags; + /// 0x02A, EPB signature, 0x29 + public byte signature; + /// 0x02B, Volume serial number + public uint serial_no; + /// 0x02F, Volume label, 11 bytes, space-padded + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] public byte[] volume_label; + /// 0x03A, Filesystem type, 8 bytes, space-padded ("HPFS ") + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] fs_type; + /// Boot code. + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 448)] public byte[] boot_code; + /// 0x1FE, 0xAA55 + public ushort signature2; + } + + /// + /// HPFS superblock at sector 16 + /// + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct HPFS_SuperBlock + { + /// 0x000, 0xF995E849 + public uint magic1; + /// 0x004, 0xFA53E9C5 + public uint magic2; + /// 0x008, HPFS version + public byte version; + /// 0x009, 2 if <= 4 GiB, 3 if > 4 GiB + public byte func_version; + /// 0x00A, Alignment + public ushort dummy; + /// 0x00C, LSN pointer to root fnode + public uint root_fnode; + /// 0x010, Sectors on volume + public uint sectors; + /// 0x014, Bad blocks on volume + public uint badblocks; + /// 0x018, LSN pointer to volume bitmap + public uint bitmap_lsn; + /// 0x01C, 0 + public uint zero1; + /// 0x020, LSN pointer to badblock directory + public uint badblock_lsn; + /// 0x024, 0 + public uint zero2; + /// 0x028, Time of last CHKDSK + public int last_chkdsk; + /// 0x02C, Time of last optimization + public int last_optim; + /// 0x030, Sectors of dir band + public uint dband_sectors; + /// 0x034, Start sector of dir band + public uint dband_start; + /// 0x038, Last sector of dir band + public uint dband_last; + /// 0x03C, LSN of free space bitmap + public uint dband_bitmap; + /// 0x040, Can be used for volume name (32 bytes) + public ulong zero3; + /// 0x048, ... + public ulong zero4; + /// 0x04C, ... + public ulong zero5; + /// 0x050, ...; + public ulong zero6; + /// 0x058, LSN pointer to ACLs (only HPFS386) + public uint acl_start; + } + + /// + /// HPFS spareblock at sector 17 + /// + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct HPFS_SpareBlock + { + /// 0x000, 0xF9911849 + public uint magic1; + /// 0x004, 0xFA5229C5 + public uint magic2; + /// 0x008, HPFS flags + public byte flags1; + /// 0x009, HPFS386 flags + public byte flags2; + /// 0x00A, Alignment + public ushort dummy; + /// 0x00C, LSN of hotfix directory + public uint hotfix_start; + /// 0x010, Used hotfixes + public uint hotfix_used; + /// 0x014, Total hotfixes available + public uint hotfix_entries; + /// 0x018, Unused spare dnodes + public uint spare_dnodes_free; + /// 0x01C, Length of spare dnodes list + public uint spare_dnodes; + /// 0x020, LSN of codepage directory + public uint codepage_lsn; + /// 0x024, Number of codepages used + public uint codepages; + /// 0x028, SuperBlock CRC32 (only HPFS386) + public uint sb_crc32; + /// 0x02C, SpareBlock CRC32 (only HPFS386) + public uint sp_crc32; + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/ISO9660/Info.cs b/DiscImageChef.Filesystems/ISO9660/Info.cs index 3d06aa09..612b5a05 100644 --- a/DiscImageChef.Filesystems/ISO9660/Info.cs +++ b/DiscImageChef.Filesystems/ISO9660/Info.cs @@ -77,8 +77,7 @@ namespace DiscImageChef.Filesystems.ISO9660 CurrentEncoding.GetString(vdMagic) == CDI_MAGIC; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { information = ""; StringBuilder isoMetadata = new StringBuilder(); @@ -179,8 +178,7 @@ namespace DiscImageChef.Filesystems.ISO9660 } else if(cdi) fsvd = - BigEndianMarshal - .ByteArrayToStructureBigEndian(vdSector); + BigEndianMarshal.ByteArrayToStructureBigEndian(vdSector); else { IntPtr ptr = Marshal.AllocHGlobal(2048); @@ -194,14 +192,16 @@ namespace DiscImageChef.Filesystems.ISO9660 { IntPtr ptr = Marshal.AllocHGlobal(2048); Marshal.Copy(vdSector, 0, ptr, 2048); - PrimaryVolumeDescriptor svd = (PrimaryVolumeDescriptor)Marshal.PtrToStructure(ptr, typeof(PrimaryVolumeDescriptor)); + PrimaryVolumeDescriptor svd = + (PrimaryVolumeDescriptor)Marshal.PtrToStructure(ptr, typeof(PrimaryVolumeDescriptor)); Marshal.FreeHGlobal(ptr); // Check if this is Joliet if(svd.escape_sequences[0] == '%' && svd.escape_sequences[1] == '/') if(svd.escape_sequences[2] == '@' || svd.escape_sequences[2] == 'C' || svd.escape_sequences[2] == 'E') jolietvd = svd; - else DicConsole.WriteLine("ISO9660 plugin", "Found unknown supplementary volume descriptor"); + else + DicConsole.WriteLine("ISO9660 plugin", "Found unknown supplementary volume descriptor"); break; } @@ -302,7 +302,8 @@ namespace DiscImageChef.Filesystems.ISO9660 ushort nextSignature = BigEndianBitConverter.ToUInt16(sa, saOff); - switch(nextSignature) { + switch(nextSignature) + { // Easy, contains size field case APPLE_MAGIC: apple = true; @@ -344,7 +345,8 @@ namespace DiscImageChef.Filesystems.ISO9660 { nextSignature = BigEndianBitConverter.ToUInt16(sa, saOff); - switch(nextSignature) { + switch(nextSignature) + { case APPLE_MAGIC: if(sa[saOff + 3] == 1 && sa[saOff + 2] == 7) apple = true; else apple |= sa[saOff + 3] != 1; @@ -352,8 +354,8 @@ namespace DiscImageChef.Filesystems.ISO9660 case SUSP_CONTINUATION when saOff + sa[saOff + 2] <= saLen: byte[] ce = new byte[sa[saOff + 2]]; Array.Copy(sa, saOff, ce, 0, ce.Length); - ContinuationArea ca = - BigEndianMarshal.ByteArrayToStructureBigEndian(ce); + ContinuationArea ca = BigEndianMarshal + .ByteArrayToStructureBigEndian(ce); contareas.Add(ca); break; case SUSP_REFERENCE when saOff + sa[saOff + 2] <= saLen: @@ -371,8 +373,8 @@ namespace DiscImageChef.Filesystems.ISO9660 ziso |= nextSignature == ZISO_MAGIC; amiga |= nextSignature == AMIGA_MAGIC; - aaip |= nextSignature == AAIP_MAGIC || - nextSignature == AAIP_MAGIC_OLD && sa[saOff + 3] == 1 && sa[saOff + 2] >= 9; + aaip |= nextSignature == AAIP_MAGIC || nextSignature == AAIP_MAGIC_OLD && + sa[saOff + 3] == 1 && sa[saOff + 2] >= 9; saOff += sa[saOff + 2]; @@ -394,7 +396,7 @@ namespace DiscImageChef.Filesystems.ISO9660 foreach(ContinuationArea ca in contareas) { uint caLen = (ca.ca_length_be + ca.offset_be) / - (highSierra ? hsvd.Value.logical_block_size : pvd.Value.logical_block_size); + (highSierra ? hsvd.Value.logical_block_size : pvd.Value.logical_block_size); if((ca.ca_length_be + ca.offset_be) % (highSierra ? hsvd.Value.logical_block_size : pvd.Value.logical_block_size) > 0) caLen++; @@ -407,7 +409,8 @@ namespace DiscImageChef.Filesystems.ISO9660 { ushort nextSignature = BigEndianBitConverter.ToUInt16(caData, caOff); - switch(nextSignature) { + switch(nextSignature) + { // Apple never said to include its extensions inside a continuation area, but just in case case APPLE_MAGIC: if(caData[caOff + 3] == 1 && caData[caOff + 2] == 7) apple = true; @@ -428,8 +431,8 @@ namespace DiscImageChef.Filesystems.ISO9660 ziso |= nextSignature == ZISO_MAGIC; amiga |= nextSignature == AMIGA_MAGIC; - aaip |= nextSignature == AAIP_MAGIC || - nextSignature == AAIP_MAGIC_OLD && caData[caOff + 3] == 1 && caData[caOff + 2] >= 9; + aaip |= nextSignature == AAIP_MAGIC || nextSignature == AAIP_MAGIC_OLD && caData[caOff + 3] == 1 && + caData[caOff + 2] >= 9; caOff += caData[caOff + 2]; } @@ -555,7 +558,8 @@ namespace DiscImageChef.Filesystems.ISO9660 IntPtr ptr = Marshal.AllocHGlobal(EL_TORITO_ENTRY_SIZE); Marshal.Copy(vdSector, toritoOff, ptr, EL_TORITO_ENTRY_SIZE); - ElToritoValidationEntry valentry = (ElToritoValidationEntry)Marshal.PtrToStructure(ptr, typeof(ElToritoValidationEntry)); + ElToritoValidationEntry valentry = + (ElToritoValidationEntry)Marshal.PtrToStructure(ptr, typeof(ElToritoValidationEntry)); Marshal.FreeHGlobal(ptr); if(valentry.signature != EL_TORITO_MAGIC) goto exit_torito; @@ -564,11 +568,13 @@ namespace DiscImageChef.Filesystems.ISO9660 ptr = Marshal.AllocHGlobal(EL_TORITO_ENTRY_SIZE); Marshal.Copy(vdSector, toritoOff, ptr, EL_TORITO_ENTRY_SIZE); - ElToritoInitialEntry initialEntry = (ElToritoInitialEntry)Marshal.PtrToStructure(ptr, typeof(ElToritoInitialEntry)); + ElToritoInitialEntry initialEntry = + (ElToritoInitialEntry)Marshal.PtrToStructure(ptr, typeof(ElToritoInitialEntry)); Marshal.FreeHGlobal(ptr); initialEntry.boot_type = (ElToritoEmulation)((byte)initialEntry.boot_type & 0xF); - byte[] bootImage = imagePlugin.ReadSectors(initialEntry.load_rba + partition.Start, initialEntry.sector_count); + byte[] bootImage = + imagePlugin.ReadSectors(initialEntry.load_rba + partition.Start, initialEntry.sector_count); isoMetadata.AppendLine("----------------------"); isoMetadata.AppendLine("EL TORITO INFORMATION:"); @@ -620,11 +626,12 @@ namespace DiscImageChef.Filesystems.ISO9660 const int SECTION_COUNTER = 2; while(toritoOff < vdSector.Length && (vdSector[toritoOff] == (byte)ElToritoIndicator.Header || - vdSector[toritoOff] == (byte)ElToritoIndicator.LastHeader)) + vdSector[toritoOff] == (byte)ElToritoIndicator.LastHeader)) { ptr = Marshal.AllocHGlobal(EL_TORITO_ENTRY_SIZE); Marshal.Copy(vdSector, toritoOff, ptr, EL_TORITO_ENTRY_SIZE); - ElToritoSectionHeaderEntry sectionHeader = (ElToritoSectionHeaderEntry)Marshal.PtrToStructure(ptr, typeof(ElToritoSectionHeaderEntry)); + ElToritoSectionHeaderEntry sectionHeader = + (ElToritoSectionHeaderEntry)Marshal.PtrToStructure(ptr, typeof(ElToritoSectionHeaderEntry)); Marshal.FreeHGlobal(ptr); toritoOff += EL_TORITO_ENTRY_SIZE; @@ -637,16 +644,16 @@ namespace DiscImageChef.Filesystems.ISO9660 { ptr = Marshal.AllocHGlobal(EL_TORITO_ENTRY_SIZE); Marshal.Copy(vdSector, toritoOff, ptr, EL_TORITO_ENTRY_SIZE); - ElToritoSectionEntry sectionEntry = (ElToritoSectionEntry)Marshal.PtrToStructure(ptr, typeof(ElToritoSectionEntry)); + ElToritoSectionEntry sectionEntry = + (ElToritoSectionEntry)Marshal.PtrToStructure(ptr, typeof(ElToritoSectionEntry)); Marshal.FreeHGlobal(ptr); toritoOff += EL_TORITO_ENTRY_SIZE; isoMetadata.AppendFormat("\tEntry {0}:", entryCounter); if(sectionEntry.bootable == ElToritoIndicator.Bootable) { - bootImage = - imagePlugin.ReadSectors(sectionEntry.load_rba + partition.Start, - sectionEntry.sector_count); + bootImage = imagePlugin.ReadSectors(sectionEntry.load_rba + partition.Start, + sectionEntry.sector_count); isoMetadata.AppendFormat("\t\tBootable on {0}", sectionHeader.platform_id).AppendLine(); isoMetadata.AppendFormat("\t\tBootable image starts at sector {0} and runs for {1} sectors", sectionEntry.load_rba, sectionEntry.sector_count).AppendLine(); @@ -684,8 +691,8 @@ namespace DiscImageChef.Filesystems.ISO9660 sectionEntry.selection_criteria_type).AppendLine(); isoMetadata.AppendFormat("\t\tSystem type: 0x{0:X2}", sectionEntry.system_type) .AppendLine(); - isoMetadata.AppendFormat("\t\tBootable image's SHA1: {0}", - sha1Ctx.Data(bootImage, out _)).AppendLine(); + isoMetadata.AppendFormat("\t\tBootable image's SHA1: {0}", sha1Ctx.Data(bootImage, out _)) + .AppendLine(); } else isoMetadata.AppendLine("\t\tNot bootable"); @@ -700,7 +707,8 @@ namespace DiscImageChef.Filesystems.ISO9660 { ptr = Marshal.AllocHGlobal(EL_TORITO_ENTRY_SIZE); Marshal.Copy(vdSector, toritoOff, ptr, EL_TORITO_ENTRY_SIZE); - ElToritoSectionEntryExtension sectionExtension = (ElToritoSectionEntryExtension) + ElToritoSectionEntryExtension sectionExtension = + (ElToritoSectionEntryExtension) Marshal.PtrToStructure(ptr, typeof(ElToritoSectionEntryExtension)); Marshal.FreeHGlobal(ptr); toritoOff += EL_TORITO_ENTRY_SIZE; diff --git a/DiscImageChef.Filesystems/ISO9660/Structs/CDi.cs b/DiscImageChef.Filesystems/ISO9660/Structs/CDi.cs index 71106f4a..ce00d3c1 100644 --- a/DiscImageChef.Filesystems/ISO9660/Structs/CDi.cs +++ b/DiscImageChef.Filesystems/ISO9660/Structs/CDi.cs @@ -38,6 +38,49 @@ namespace DiscImageChef.Filesystems.ISO9660 { public partial class ISO9660 { + static DecodedVolumeDescriptor DecodeVolumeDescriptor(FileStructureVolumeDescriptor pvd) + { + DecodedVolumeDescriptor decodedVD = new DecodedVolumeDescriptor + { + SystemIdentifier = Encoding.ASCII.GetString(pvd.system_id).TrimEnd().Trim('\0'), + VolumeIdentifier = Encoding.ASCII.GetString(pvd.volume_id).TrimEnd().Trim('\0'), + VolumeSetIdentifier = Encoding.ASCII.GetString(pvd.volume_set_id).TrimEnd().Trim('\0'), + PublisherIdentifier = Encoding.ASCII.GetString(pvd.publisher_id).TrimEnd().Trim('\0'), + DataPreparerIdentifier = Encoding.ASCII.GetString(pvd.preparer_id).TrimEnd().Trim('\0'), + ApplicationIdentifier = Encoding.ASCII.GetString(pvd.application_data).TrimEnd().Trim('\0') + }; + + if(pvd.creation_date[0] == '0' || pvd.creation_date[0] == 0x00) decodedVD.CreationTime = DateTime.MinValue; + else decodedVD.CreationTime = DateHandlers.HighSierraToDateTime(pvd.creation_date); + + if(pvd.modification_date[0] == '0' || pvd.modification_date[0] == 0x00) + decodedVD.HasModificationTime = false; + else + { + decodedVD.HasModificationTime = true; + decodedVD.ModificationTime = DateHandlers.HighSierraToDateTime(pvd.modification_date); + } + + if(pvd.expiration_date[0] == '0' || pvd.expiration_date[0] == 0x00) decodedVD.HasExpirationTime = false; + else + { + decodedVD.HasExpirationTime = true; + decodedVD.ExpirationTime = DateHandlers.HighSierraToDateTime(pvd.expiration_date); + } + + if(pvd.effective_date[0] == '0' || pvd.effective_date[0] == 0x00) decodedVD.HasEffectiveTime = false; + else + { + decodedVD.HasEffectiveTime = true; + decodedVD.EffectiveTime = DateHandlers.HighSierraToDateTime(pvd.effective_date); + } + + decodedVD.Blocks = pvd.volume_space_size; + decodedVD.BlockSize = pvd.logical_block_size; + + return decodedVD; + } + [StructLayout(LayoutKind.Sequential, Pack = 1)] struct FileStructureVolumeDescriptor { @@ -115,48 +158,5 @@ namespace DiscImageChef.Filesystems.ISO9660 public byte file_no; public byte reserved2; } - - static DecodedVolumeDescriptor DecodeVolumeDescriptor(FileStructureVolumeDescriptor pvd) - { - DecodedVolumeDescriptor decodedVD = new DecodedVolumeDescriptor - { - SystemIdentifier = Encoding.ASCII.GetString(pvd.system_id).TrimEnd().Trim('\0'), - VolumeIdentifier = Encoding.ASCII.GetString(pvd.volume_id).TrimEnd().Trim('\0'), - VolumeSetIdentifier = Encoding.ASCII.GetString(pvd.volume_set_id).TrimEnd().Trim('\0'), - PublisherIdentifier = Encoding.ASCII.GetString(pvd.publisher_id).TrimEnd().Trim('\0'), - DataPreparerIdentifier = Encoding.ASCII.GetString(pvd.preparer_id).TrimEnd().Trim('\0'), - ApplicationIdentifier = Encoding.ASCII.GetString(pvd.application_data).TrimEnd().Trim('\0') - }; - - if(pvd.creation_date[0] == '0' || pvd.creation_date[0] == 0x00) - decodedVD.CreationTime = DateTime.MinValue; - else decodedVD.CreationTime = DateHandlers.HighSierraToDateTime(pvd.creation_date); - - if(pvd.modification_date[0] == '0' || pvd.modification_date[0] == 0x00) decodedVD.HasModificationTime = false; - else - { - decodedVD.HasModificationTime = true; - decodedVD.ModificationTime = DateHandlers.HighSierraToDateTime(pvd.modification_date); - } - - if(pvd.expiration_date[0] == '0' || pvd.expiration_date[0] == 0x00) decodedVD.HasExpirationTime = false; - else - { - decodedVD.HasExpirationTime = true; - decodedVD.ExpirationTime = DateHandlers.HighSierraToDateTime(pvd.expiration_date); - } - - if(pvd.effective_date[0] == '0' || pvd.effective_date[0] == 0x00) decodedVD.HasEffectiveTime = false; - else - { - decodedVD.HasEffectiveTime = true; - decodedVD.EffectiveTime = DateHandlers.HighSierraToDateTime(pvd.effective_date); - } - - decodedVD.Blocks = pvd.volume_space_size; - decodedVD.BlockSize = pvd.logical_block_size; - - return decodedVD; - } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/ISO9660/Structs/HighSierra.cs b/DiscImageChef.Filesystems/ISO9660/Structs/HighSierra.cs index 32107f76..1efae045 100644 --- a/DiscImageChef.Filesystems/ISO9660/Structs/HighSierra.cs +++ b/DiscImageChef.Filesystems/ISO9660/Structs/HighSierra.cs @@ -38,6 +38,49 @@ namespace DiscImageChef.Filesystems.ISO9660 { public partial class ISO9660 { + static DecodedVolumeDescriptor DecodeVolumeDescriptor(HighSierraPrimaryVolumeDescriptor pvd) + { + DecodedVolumeDescriptor decodedVD = new DecodedVolumeDescriptor + { + SystemIdentifier = Encoding.ASCII.GetString(pvd.system_id).TrimEnd().Trim('\0'), + VolumeIdentifier = Encoding.ASCII.GetString(pvd.volume_id).TrimEnd().Trim('\0'), + VolumeSetIdentifier = Encoding.ASCII.GetString(pvd.volume_set_id).TrimEnd().Trim('\0'), + PublisherIdentifier = Encoding.ASCII.GetString(pvd.publisher_id).TrimEnd().Trim('\0'), + DataPreparerIdentifier = Encoding.ASCII.GetString(pvd.preparer_id).TrimEnd().Trim('\0'), + ApplicationIdentifier = Encoding.ASCII.GetString(pvd.application_data).TrimEnd().Trim('\0') + }; + + if(pvd.creation_date[0] == '0' || pvd.creation_date[0] == 0x00) decodedVD.CreationTime = DateTime.MinValue; + else decodedVD.CreationTime = DateHandlers.HighSierraToDateTime(pvd.creation_date); + + if(pvd.modification_date[0] == '0' || pvd.modification_date[0] == 0x00) + decodedVD.HasModificationTime = false; + else + { + decodedVD.HasModificationTime = true; + decodedVD.ModificationTime = DateHandlers.HighSierraToDateTime(pvd.modification_date); + } + + if(pvd.expiration_date[0] == '0' || pvd.expiration_date[0] == 0x00) decodedVD.HasExpirationTime = false; + else + { + decodedVD.HasExpirationTime = true; + decodedVD.ExpirationTime = DateHandlers.HighSierraToDateTime(pvd.expiration_date); + } + + if(pvd.effective_date[0] == '0' || pvd.effective_date[0] == 0x00) decodedVD.HasEffectiveTime = false; + else + { + decodedVD.HasEffectiveTime = true; + decodedVD.EffectiveTime = DateHandlers.HighSierraToDateTime(pvd.effective_date); + } + + decodedVD.Blocks = pvd.volume_space_size; + decodedVD.BlockSize = pvd.logical_block_size; + + return decodedVD; + } + [StructLayout(LayoutKind.Sequential, Pack = 1)] struct HighSierraPrimaryVolumeDescriptor { @@ -107,48 +150,5 @@ namespace DiscImageChef.Filesystems.ISO9660 public byte name_len; // Followed by name[name_len] and then system area until length arrives } - - static DecodedVolumeDescriptor DecodeVolumeDescriptor(HighSierraPrimaryVolumeDescriptor pvd) - { - DecodedVolumeDescriptor decodedVD = new DecodedVolumeDescriptor - { - SystemIdentifier = Encoding.ASCII.GetString(pvd.system_id).TrimEnd().Trim('\0'), - VolumeIdentifier = Encoding.ASCII.GetString(pvd.volume_id).TrimEnd().Trim('\0'), - VolumeSetIdentifier = Encoding.ASCII.GetString(pvd.volume_set_id).TrimEnd().Trim('\0'), - PublisherIdentifier = Encoding.ASCII.GetString(pvd.publisher_id).TrimEnd().Trim('\0'), - DataPreparerIdentifier = Encoding.ASCII.GetString(pvd.preparer_id).TrimEnd().Trim('\0'), - ApplicationIdentifier = Encoding.ASCII.GetString(pvd.application_data).TrimEnd().Trim('\0') - }; - - if(pvd.creation_date[0] == '0' || pvd.creation_date[0] == 0x00) - decodedVD.CreationTime = DateTime.MinValue; - else decodedVD.CreationTime = DateHandlers.HighSierraToDateTime(pvd.creation_date); - - if(pvd.modification_date[0] == '0' || pvd.modification_date[0] == 0x00) decodedVD.HasModificationTime = false; - else - { - decodedVD.HasModificationTime = true; - decodedVD.ModificationTime = DateHandlers.HighSierraToDateTime(pvd.modification_date); - } - - if(pvd.expiration_date[0] == '0' || pvd.expiration_date[0] == 0x00) decodedVD.HasExpirationTime = false; - else - { - decodedVD.HasExpirationTime = true; - decodedVD.ExpirationTime = DateHandlers.HighSierraToDateTime(pvd.expiration_date); - } - - if(pvd.effective_date[0] == '0' || pvd.effective_date[0] == 0x00) decodedVD.HasEffectiveTime = false; - else - { - decodedVD.HasEffectiveTime = true; - decodedVD.EffectiveTime = DateHandlers.HighSierraToDateTime(pvd.effective_date); - } - - decodedVD.Blocks = pvd.volume_space_size; - decodedVD.BlockSize = pvd.logical_block_size; - - return decodedVD; - } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/ISO9660/Structs/ISO.cs b/DiscImageChef.Filesystems/ISO9660/Structs/ISO.cs index c1a3bf54..37866aa7 100644 --- a/DiscImageChef.Filesystems/ISO9660/Structs/ISO.cs +++ b/DiscImageChef.Filesystems/ISO9660/Structs/ISO.cs @@ -38,6 +38,49 @@ namespace DiscImageChef.Filesystems.ISO9660 { public partial class ISO9660 { + static DecodedVolumeDescriptor DecodeVolumeDescriptor(PrimaryVolumeDescriptor pvd) + { + DecodedVolumeDescriptor decodedVD = new DecodedVolumeDescriptor + { + SystemIdentifier = Encoding.ASCII.GetString(pvd.system_id).TrimEnd().Trim('\0'), + VolumeIdentifier = Encoding.ASCII.GetString(pvd.volume_id).TrimEnd().Trim('\0'), + VolumeSetIdentifier = Encoding.ASCII.GetString(pvd.volume_set_id).TrimEnd().Trim('\0'), + PublisherIdentifier = Encoding.ASCII.GetString(pvd.publisher_id).TrimEnd().Trim('\0'), + DataPreparerIdentifier = Encoding.ASCII.GetString(pvd.preparer_id).TrimEnd().Trim('\0'), + ApplicationIdentifier = Encoding.ASCII.GetString(pvd.application_data).TrimEnd().Trim('\0') + }; + + if(pvd.creation_date[0] == '0' || pvd.creation_date[0] == 0x00) decodedVD.CreationTime = DateTime.MinValue; + else decodedVD.CreationTime = DateHandlers.Iso9660ToDateTime(pvd.creation_date); + + if(pvd.modification_date[0] == '0' || pvd.modification_date[0] == 0x00) + decodedVD.HasModificationTime = false; + else + { + decodedVD.HasModificationTime = true; + decodedVD.ModificationTime = DateHandlers.Iso9660ToDateTime(pvd.modification_date); + } + + if(pvd.expiration_date[0] == '0' || pvd.expiration_date[0] == 0x00) decodedVD.HasExpirationTime = false; + else + { + decodedVD.HasExpirationTime = true; + decodedVD.ExpirationTime = DateHandlers.Iso9660ToDateTime(pvd.expiration_date); + } + + if(pvd.effective_date[0] == '0' || pvd.effective_date[0] == 0x00) decodedVD.HasEffectiveTime = false; + else + { + decodedVD.HasEffectiveTime = true; + decodedVD.EffectiveTime = DateHandlers.Iso9660ToDateTime(pvd.effective_date); + } + + decodedVD.Blocks = pvd.volume_space_size; + decodedVD.BlockSize = pvd.logical_block_size; + + return decodedVD; + } + [StructLayout(LayoutKind.Sequential, Pack = 1)] struct PrimaryVolumeDescriptor { @@ -165,48 +208,5 @@ namespace DiscImageChef.Filesystems.ISO9660 public ushort parent_dirno; // Followed by name[name_len] } - - static DecodedVolumeDescriptor DecodeVolumeDescriptor(PrimaryVolumeDescriptor pvd) - { - DecodedVolumeDescriptor decodedVD = new DecodedVolumeDescriptor - { - SystemIdentifier = Encoding.ASCII.GetString(pvd.system_id).TrimEnd().Trim('\0'), - VolumeIdentifier = Encoding.ASCII.GetString(pvd.volume_id).TrimEnd().Trim('\0'), - VolumeSetIdentifier = Encoding.ASCII.GetString(pvd.volume_set_id).TrimEnd().Trim('\0'), - PublisherIdentifier = Encoding.ASCII.GetString(pvd.publisher_id).TrimEnd().Trim('\0'), - DataPreparerIdentifier = Encoding.ASCII.GetString(pvd.preparer_id).TrimEnd().Trim('\0'), - ApplicationIdentifier = Encoding.ASCII.GetString(pvd.application_data).TrimEnd().Trim('\0') - }; - - if(pvd.creation_date[0] == '0' || pvd.creation_date[0] == 0x00) - decodedVD.CreationTime = DateTime.MinValue; - else decodedVD.CreationTime = DateHandlers.Iso9660ToDateTime(pvd.creation_date); - - if(pvd.modification_date[0] == '0' || pvd.modification_date[0] == 0x00) decodedVD.HasModificationTime = false; - else - { - decodedVD.HasModificationTime = true; - decodedVD.ModificationTime = DateHandlers.Iso9660ToDateTime(pvd.modification_date); - } - - if(pvd.expiration_date[0] == '0' || pvd.expiration_date[0] == 0x00) decodedVD.HasExpirationTime = false; - else - { - decodedVD.HasExpirationTime = true; - decodedVD.ExpirationTime = DateHandlers.Iso9660ToDateTime(pvd.expiration_date); - } - - if(pvd.effective_date[0] == '0' || pvd.effective_date[0] == 0x00) decodedVD.HasEffectiveTime = false; - else - { - decodedVD.HasEffectiveTime = true; - decodedVD.EffectiveTime = DateHandlers.Iso9660ToDateTime(pvd.effective_date); - } - - decodedVD.Blocks = pvd.volume_space_size; - decodedVD.BlockSize = pvd.logical_block_size; - - return decodedVD; - } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/ISO9660/Structs/Joliet.cs b/DiscImageChef.Filesystems/ISO9660/Structs/Joliet.cs index 98782814..9680d435 100644 --- a/DiscImageChef.Filesystems/ISO9660/Structs/Joliet.cs +++ b/DiscImageChef.Filesystems/ISO9660/Structs/Joliet.cs @@ -57,21 +57,24 @@ namespace DiscImageChef.Filesystems.ISO9660 decodedVD.CreationTime = DateTime.MinValue; else decodedVD.CreationTime = DateHandlers.Iso9660ToDateTime(jolietvd.creation_date); - if(jolietvd.modification_date[0] < 0x31 || jolietvd.modification_date[0] > 0x39) decodedVD.HasModificationTime = false; + if(jolietvd.modification_date[0] < 0x31 || jolietvd.modification_date[0] > 0x39) + decodedVD.HasModificationTime = false; else { decodedVD.HasModificationTime = true; decodedVD.ModificationTime = DateHandlers.Iso9660ToDateTime(jolietvd.modification_date); } - if(jolietvd.expiration_date[0] < 0x31 || jolietvd.expiration_date[0] > 0x39) decodedVD.HasExpirationTime = false; + if(jolietvd.expiration_date[0] < 0x31 || jolietvd.expiration_date[0] > 0x39) + decodedVD.HasExpirationTime = false; else { decodedVD.HasExpirationTime = true; decodedVD.ExpirationTime = DateHandlers.Iso9660ToDateTime(jolietvd.expiration_date); } - if(jolietvd.effective_date[0] < 0x31 || jolietvd.effective_date[0] > 0x39) decodedVD.HasEffectiveTime = false; + if(jolietvd.effective_date[0] < 0x31 || jolietvd.effective_date[0] > 0x39) + decodedVD.HasEffectiveTime = false; else { decodedVD.HasEffectiveTime = true; diff --git a/DiscImageChef.Filesystems/JFS.cs b/DiscImageChef.Filesystems/JFS.cs index 3c266328..841414c6 100644 --- a/DiscImageChef.Filesystems/JFS.cs +++ b/DiscImageChef.Filesystems/JFS.cs @@ -42,95 +42,6 @@ namespace DiscImageChef.Filesystems { public class JFS : Filesystem { - [Flags] - enum JFS_Flags : uint - { - Unicode = 0x00000001, - RemountRO = 0x00000002, - Continue = 0x00000004, - Panic = 0x00000008, - UserQuota = 0x00000010, - GroupQuota = 0x00000020, - NoJournal = 0x00000040, - Discard = 0x00000080, - GroupCommit = 0x00000100, - LazyCommit = 0x00000200, - Temporary = 0x00000400, - InlineLog = 0x00000800, - InlineMoving = 0x00001000, - BadSAIT = 0x00010000, - Sparse = 0x00020000, - DASDEnabled = 0x00040000, - DASDPrime = 0x00080000, - SwapBytes = 0x00100000, - DirIndex = 0x00200000, - Linux = 0x10000000, - DFS = 0x20000000, - OS2 = 0x40000000, - AIX = 0x80000000 - } - - [Flags] - enum JFS_State : uint - { - Clean = 0, - Mounted = 1, - Dirty = 2, - Logredo = 4, - Extendfs = 8 - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct JFS_Extent - { - /// - /// Leftmost 24 bits are extent length, rest 8 bits are most significant for - /// - public uint len_addr; - public uint addr2; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct JFS_TimeStruct - { - public uint tv_sec; - public uint tv_nsec; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct JFS_SuperBlock - { - public uint s_magic; - public uint s_version; - public ulong s_size; - public uint s_bsize; - public ushort s_l2bsize; - public ushort s_l2bfactor; - public uint s_pbsize; - public ushort s_l1pbsize; - public ushort pad; - public uint s_agsize; - public JFS_Flags s_flags; - public JFS_State s_state; - public uint s_compress; - public JFS_Extent s_ait2; - public JFS_Extent s_aim2; - public uint s_logdev; - public uint s_logserial; - public JFS_Extent s_logpxd; - public JFS_Extent s_fsckpxd; - public JFS_TimeStruct s_time; - public uint s_fsckloglen; - public sbyte s_fscklog; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] public byte[] s_fpack; - public ulong s_xsize; - public JFS_Extent s_xfsckpxd; - public JFS_Extent s_xlogpxd; - public Guid s_uuid; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] s_label; - public Guid s_loguuid; - } - const uint JFS_BOOT_BLOCKS_SIZE = 0x8000; const uint JFS_MAGIC = 0x3153464A; @@ -172,8 +83,7 @@ namespace DiscImageChef.Filesystems return jfsSb.s_magic == JFS_MAGIC; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { information = ""; StringBuilder sb = new StringBuilder(); @@ -301,5 +211,94 @@ namespace DiscImageChef.Filesystems { return Errno.NotImplemented; } + + [Flags] + enum JFS_Flags : uint + { + Unicode = 0x00000001, + RemountRO = 0x00000002, + Continue = 0x00000004, + Panic = 0x00000008, + UserQuota = 0x00000010, + GroupQuota = 0x00000020, + NoJournal = 0x00000040, + Discard = 0x00000080, + GroupCommit = 0x00000100, + LazyCommit = 0x00000200, + Temporary = 0x00000400, + InlineLog = 0x00000800, + InlineMoving = 0x00001000, + BadSAIT = 0x00010000, + Sparse = 0x00020000, + DASDEnabled = 0x00040000, + DASDPrime = 0x00080000, + SwapBytes = 0x00100000, + DirIndex = 0x00200000, + Linux = 0x10000000, + DFS = 0x20000000, + OS2 = 0x40000000, + AIX = 0x80000000 + } + + [Flags] + enum JFS_State : uint + { + Clean = 0, + Mounted = 1, + Dirty = 2, + Logredo = 4, + Extendfs = 8 + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct JFS_Extent + { + /// + /// Leftmost 24 bits are extent length, rest 8 bits are most significant for + /// + public uint len_addr; + public uint addr2; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct JFS_TimeStruct + { + public uint tv_sec; + public uint tv_nsec; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct JFS_SuperBlock + { + public uint s_magic; + public uint s_version; + public ulong s_size; + public uint s_bsize; + public ushort s_l2bsize; + public ushort s_l2bfactor; + public uint s_pbsize; + public ushort s_l1pbsize; + public ushort pad; + public uint s_agsize; + public JFS_Flags s_flags; + public JFS_State s_state; + public uint s_compress; + public JFS_Extent s_ait2; + public JFS_Extent s_aim2; + public uint s_logdev; + public uint s_logserial; + public JFS_Extent s_logpxd; + public JFS_Extent s_fsckpxd; + public JFS_TimeStruct s_time; + public uint s_fsckloglen; + public sbyte s_fscklog; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] public byte[] s_fpack; + public ulong s_xsize; + public JFS_Extent s_xfsckpxd; + public JFS_Extent s_xlogpxd; + public Guid s_uuid; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] s_label; + public Guid s_loguuid; + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/LIF.cs b/DiscImageChef.Filesystems/LIF.cs index 7fc50ad2..410deb22 100644 --- a/DiscImageChef.Filesystems/LIF.cs +++ b/DiscImageChef.Filesystems/LIF.cs @@ -44,23 +44,6 @@ namespace DiscImageChef.Filesystems // Information from http://www.hp9845.net/9845/projects/hpdir/#lif_filesystem public class LIF : Filesystem { - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct LIF_SystemBlock - { - public ushort magic; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] public byte[] volumeLabel; - public uint directoryStart; - public ushort lifId; - public ushort unused; - public uint directorySize; - public ushort lifVersion; - public ushort unused2; - public uint tracks; - public uint heads; - public uint sectors; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] public byte[] creationDate; - } - const uint LIF_MAGIC = 0x8000; public LIF() @@ -95,8 +78,7 @@ namespace DiscImageChef.Filesystems return lifSb.magic == LIF_MAGIC; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { information = ""; @@ -194,5 +176,22 @@ namespace DiscImageChef.Filesystems { return Errno.NotImplemented; } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct LIF_SystemBlock + { + public ushort magic; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] public byte[] volumeLabel; + public uint directoryStart; + public ushort lifId; + public ushort unused; + public uint directorySize; + public ushort lifVersion; + public ushort unused2; + public uint tracks; + public uint heads; + public uint sectors; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] public byte[] creationDate; + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/LisaFS/Consts.cs b/DiscImageChef.Filesystems/LisaFS/Consts.cs index 7ffd8756..5e003206 100644 --- a/DiscImageChef.Filesystems/LisaFS/Consts.cs +++ b/DiscImageChef.Filesystems/LisaFS/Consts.cs @@ -35,48 +35,48 @@ namespace DiscImageChef.Filesystems.LisaFS public partial class LisaFS { /// - /// Lisa FS v1, from Lisa OS 1.0 (Workshop or Office) - /// Never seen on Sony floppies. + /// Lisa FS v1, from Lisa OS 1.0 (Workshop or Office) + /// Never seen on Sony floppies. /// const byte LISA_V1 = 0x0E; /// - /// 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 + /// 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 /// const byte LISA_V2 = 0x0F; /// - /// Lisa FS v3, from Lisa OS 3.0 (Workshop or Office) - /// Adds support for user catalogs (aka subdirectories), - /// and changes the catalog format from extents to double-linked list. - /// Uses '-' as path separator (so people that created Lisa/FILE.TEXT just - /// created a file named like that :p) + /// Lisa FS v3, from Lisa OS 3.0 (Workshop or Office) + /// Adds support for user catalogs (aka subdirectories), + /// and changes the catalog format from extents to double-linked list. + /// Uses '-' as path separator (so people that created Lisa/FILE.TEXT just + /// created a file named like that :p) /// const byte LISA_V3 = 0x11; /// Maximum string size in LisaFS const uint E_NAME = 32; /// - /// Unused file ID + /// Unused file ID /// const ushort FILEID_FREE = 0x0000; /// - /// Used by the boot blocks + /// Used by the boot blocks /// const ushort FILEID_BOOT = 0xAAAA; /// - /// Used by the operating system loader blocks + /// Used by the operating system loader blocks /// const ushort FILEID_LOADER = 0xBBBB; /// - /// Used by the MDDF + /// Used by the MDDF /// const ushort FILEID_MDDF = 0x0001; /// - /// Used by the volume bitmap, sits between MDDF and S-Records file. + /// Used by the volume bitmap, sits between MDDF and S-Records file. /// const ushort FILEID_BITMAP = 0x0002; /// - /// S-Records file + /// S-Records file /// const ushort FILEID_SRECORD = 0x0003; /// The root catalog @@ -84,7 +84,7 @@ namespace DiscImageChef.Filesystems.LisaFS const short FILEID_BOOT_SIGNED = -21846; const short FILEID_LOADER_SIGNED = -17477; /// - /// A file that has been erased + /// A file that has been erased /// const ushort FILEID_ERASED = 0x7FFF; const ushort FILEID_MAX = FILEID_ERASED; @@ -95,67 +95,67 @@ namespace DiscImageChef.Filesystems.LisaFS enum FileType : byte { /// - /// Undefined file type + /// Undefined file type /// Undefined = 0, /// - /// MDDF + /// MDDF /// MDDFile = 1, /// - /// Root catalog + /// Root catalog /// RootCat = 2, /// - /// Bitmap + /// Bitmap /// FreeList = 3, /// - /// Unknown, maybe refers to the S-Records File? + /// Unknown, maybe refers to the S-Records File? /// BadBlocks = 4, /// - /// System data + /// System data /// SysData = 5, /// - /// Printer spool + /// Printer spool /// Spool = 6, /// - /// Executable. Yet application files don't use it + /// Executable. Yet application files don't use it /// Exec = 7, /// - /// User catalog + /// User catalog /// UserCat = 8, /// - /// Pipe. Not seen on disk. + /// Pipe. Not seen on disk. /// Pipe = 9, /// - /// Boot file? + /// Boot file? /// BootFile = 10, /// - /// Swap for data + /// Swap for data /// SwapData = 11, /// - /// Swap for code + /// Swap for code /// SwapCode = 12, /// - /// Unknown + /// Unknown /// RamAP = 13, /// - /// Any file + /// Any file /// UserFile = 14, /// - /// Erased? + /// Erased? /// KilledObject = 15 } diff --git a/DiscImageChef.Filesystems/LisaFS/Dir.cs b/DiscImageChef.Filesystems/LisaFS/Dir.cs index af16a072..f5566cee 100644 --- a/DiscImageChef.Filesystems/LisaFS/Dir.cs +++ b/DiscImageChef.Filesystems/LisaFS/Dir.cs @@ -41,7 +41,7 @@ namespace DiscImageChef.Filesystems.LisaFS public partial class LisaFS { /// - /// Solves a symbolic link. + /// Solves a symbolic link. /// /// Link path. /// Link destination. @@ -52,7 +52,7 @@ namespace DiscImageChef.Filesystems.LisaFS } /// - /// Lists contents from a directory. + /// Lists contents from a directory. /// /// Directory path. /// Directory contents. @@ -90,13 +90,15 @@ namespace DiscImageChef.Filesystems.LisaFS { // Do same trick as Mac OS X, replace filesystem '/' with '-', // as '-' is the path separator in Lisa OS - contents = (from entry in catalogCache where entry.parentID == dirId select StringHandlers.CToString(entry.filename, CurrentEncoding).Replace('/', '-')).ToList(); + contents = (from entry in catalogCache + where entry.parentID == dirId + select StringHandlers.CToString(entry.filename, CurrentEncoding).Replace('/', '-')).ToList(); return Errno.NoError; } /// - /// Reads, interprets and caches the Catalog File + /// Reads, interprets and caches the Catalog File /// Errno ReadCatalog() { @@ -215,7 +217,7 @@ namespace DiscImageChef.Filesystems.LisaFS // Traverse all entries while(offset + 64 <= buf.Length) - // Catalog block header + // Catalog block header if(buf[offset + 0x24] == 0x08) offset += 78; // Maybe just garbage? Found in more than 1 disk else if(buf[offset + 0x24] == 0x7C) offset += 50; diff --git a/DiscImageChef.Filesystems/LisaFS/Extent.cs b/DiscImageChef.Filesystems/LisaFS/Extent.cs index 4c0fe095..e347262b 100644 --- a/DiscImageChef.Filesystems/LisaFS/Extent.cs +++ b/DiscImageChef.Filesystems/LisaFS/Extent.cs @@ -46,7 +46,7 @@ namespace DiscImageChef.Filesystems.LisaFS } /// - /// Searches the disk for an extents file (or gets it from cache) + /// Searches the disk for an extents file (or gets it from cache) /// /// Error. /// File identifier. @@ -171,13 +171,11 @@ namespace DiscImageChef.Filesystems.LisaFS file.extents = new Extent[extentsCount]; for(int j = 0; j < extentsCount; j++) - { file.extents[j] = new Extent - { + { start = BigEndianBitConverter.ToInt32(sector, extentsOffset + j * 6), length = BigEndianBitConverter.ToInt16(sector, extentsOffset + j * 6 + 4) }; - } extentCache.Add(fileId, file); @@ -185,77 +183,64 @@ namespace DiscImageChef.Filesystems.LisaFS if(printedExtents.Contains(fileId)) return Errno.NoError; - DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].filenameLen = {1}", fileId, - file.filenameLen); + DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].filenameLen = {1}", fileId, file.filenameLen); DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].filename = {1}", fileId, StringHandlers.CToString(file.filename, CurrentEncoding)); - DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].unknown1 = 0x{1:X4}", fileId, - file.unknown1); - DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].file_uid = 0x{1:X16}", fileId, - file.file_uid); - DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].unknown2 = 0x{1:X2}", fileId, - file.unknown2); + DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].unknown1 = 0x{1:X4}", fileId, file.unknown1); + DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].file_uid = 0x{1:X16}", fileId, file.file_uid); + DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].unknown2 = 0x{1:X2}", fileId, file.unknown2); DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].etype = 0x{1:X2}", fileId, file.etype); DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].ftype = {1}", fileId, file.ftype); - DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].unknown3 = 0x{1:X2}", fileId, - file.unknown3); + DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].unknown3 = 0x{1:X2}", fileId, file.unknown3); DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].dtc = {1}", fileId, file.dtc); DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].dta = {1}", fileId, file.dta); DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].dtm = {1}", fileId, file.dtm); DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].dtb = {1}", fileId, file.dtb); DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].dts = {1}", fileId, file.dts); DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].serial = {1}", fileId, file.serial); - DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].unknown4 = 0x{1:X2}", fileId, - file.unknown4); + DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].unknown4 = 0x{1:X2}", fileId, file.unknown4); DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].locked = {1}", fileId, file.locked > 0); - DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].protect = {1}", fileId, - file.protect > 0); + DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].protect = {1}", fileId, file.protect > 0); DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].master = {1}", fileId, file.master > 0); - DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].scavenged = {1}", fileId, - file.scavenged > 0); + DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].scavenged = {1}", fileId, file.scavenged > 0); DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].closed = {1}", fileId, file.closed > 0); DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].open = {1}", fileId, file.open > 0); DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].unknown5 = 0x{1:X2}{2:X2}{3:X2}{4:X2}{5:X2}{6:X2}{7:X2}{8:X2}{9:X2}" + - "{10:X2}{11:X2}", fileId, file.unknown5[0], file.unknown5[1], - file.unknown5[2], file.unknown5[3], file.unknown5[4], file.unknown5[5], - file.unknown5[6], file.unknown5[7], file.unknown5[8], file.unknown5[9], - file.unknown5[10]); + "{10:X2}{11:X2}", fileId, file.unknown5[0], file.unknown5[1], file.unknown5[2], + file.unknown5[3], file.unknown5[4], file.unknown5[5], file.unknown5[6], + file.unknown5[7], file.unknown5[8], file.unknown5[9], file.unknown5[10]); DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].release = {1}", fileId, file.release); DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].build = {1}", fileId, file.build); DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].compatibility = {1}", fileId, file.compatibility); DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].revision = {1}", fileId, file.revision); - DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].unknown6 = 0x{1:X4}", fileId, - file.unknown6); + DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].unknown6 = 0x{1:X4}", fileId, file.unknown6); DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].password_valid = {1}", fileId, file.password_valid > 0); DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].password = {1}", fileId, CurrentEncoding.GetString(file.password)); - DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].unknown7 = 0x{1:X2}{2:X2}{3:X2}", - fileId, file.unknown7[0], file.unknown7[1], file.unknown7[2]); + DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].unknown7 = 0x{1:X2}{2:X2}{3:X2}", fileId, + file.unknown7[0], file.unknown7[1], file.unknown7[2]); DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].overhead = {1}", fileId, file.overhead); DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].unknown8 = 0x{1:X2}{2:X2}{3:X2}{4:X2}{5:X2}{6:X2}{7:X2}{8:X2}{9:X2}" + - "{10:X2}{11:X2}{12:X2}{13:X2}{14:X2}{15:X2}{16:X2}", fileId, - file.unknown8[0], file.unknown8[1], file.unknown8[2], file.unknown8[3], - file.unknown8[4], file.unknown8[5], file.unknown8[6], file.unknown8[7], - file.unknown8[8], file.unknown8[9], file.unknown8[10], file.unknown8[11], - file.unknown8[12], file.unknown8[13], file.unknown8[14], - file.unknown8[15]); + "{10:X2}{11:X2}{12:X2}{13:X2}{14:X2}{15:X2}{16:X2}", fileId, file.unknown8[0], + file.unknown8[1], file.unknown8[2], file.unknown8[3], file.unknown8[4], + file.unknown8[5], file.unknown8[6], file.unknown8[7], file.unknown8[8], + file.unknown8[9], file.unknown8[10], file.unknown8[11], file.unknown8[12], + file.unknown8[13], file.unknown8[14], file.unknown8[15]); DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].length = {1}", fileId, file.length); - DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].unknown9 = 0x{1:X8}", fileId, - file.unknown9); + DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].unknown9 = 0x{1:X8}", fileId, file.unknown9); for(int ext = 0; ext < file.extents.Length; ext++) { - DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].extents[{1}].start = {2}", fileId, - ext, file.extents[ext].start); - DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].extents[{1}].length = {2}", fileId, - ext, file.extents[ext].length); + DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].extents[{1}].start = {2}", fileId, ext, + file.extents[ext].start); + DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].extents[{1}].length = {2}", fileId, ext, + file.extents[ext].length); } - DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].unknown10 = 0x{1:X4}", fileId, - file.unknown10); + DicConsole.DebugWriteLine("LisaFS plugin", "ExtentFile[{0}].unknown10 = 0x{1:X4}", fileId, file.unknown10); printedExtents.Add(fileId); @@ -263,7 +248,7 @@ namespace DiscImageChef.Filesystems.LisaFS } /// - /// Reads all the S-Records and caches it + /// Reads all the S-Records and caches it /// Errno ReadSRecords() { @@ -276,15 +261,13 @@ namespace DiscImageChef.Filesystems.LisaFS srecords = new SRecord[sectors.Length / 14]; for(int s = 0; s < srecords.Length; 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; } diff --git a/DiscImageChef.Filesystems/LisaFS/File.cs b/DiscImageChef.Filesystems/LisaFS/File.cs index c6e63b67..0a43a8d0 100644 --- a/DiscImageChef.Filesystems/LisaFS/File.cs +++ b/DiscImageChef.Filesystems/LisaFS/File.cs @@ -161,7 +161,8 @@ namespace DiscImageChef.Filesystems.LisaFS buf = null; if(!mounted || !debug) return Errno.AccessDenied; - if(fileId > 4 || fileId <= 0) if(fileId != FILEID_BOOT_SIGNED && fileId != FILEID_LOADER_SIGNED) return Errno.InvalidArgument; + if(fileId > 4 || fileId <= 0) + if(fileId != FILEID_BOOT_SIGNED && fileId != FILEID_LOADER_SIGNED) return Errno.InvalidArgument; if(systemFileCache.TryGetValue(fileId, out buf) && !tags) return Errno.NoError; @@ -346,7 +347,8 @@ namespace DiscImageChef.Filesystems.LisaFS if(!tags) { - if(fileSizeCache.TryGetValue(fileId, out int 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); diff --git a/DiscImageChef.Filesystems/LisaFS/Info.cs b/DiscImageChef.Filesystems/LisaFS/Info.cs index 55658956..099edd77 100644 --- a/DiscImageChef.Filesystems/LisaFS/Info.cs +++ b/DiscImageChef.Filesystems/LisaFS/Info.cs @@ -61,7 +61,8 @@ namespace DiscImageChef.Filesystems.LisaFS // LisaOS searches sectors until tag tells MDDF resides there, so we'll search 100 sectors for(int i = 0; i < 100; i++) { - DecodeTag(imagePlugin.ReadSectorTag((ulong)i, SectorTagType.AppleSectorTag), out LisaTag.PriamTag 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); @@ -137,7 +138,8 @@ namespace DiscImageChef.Filesystems.LisaFS // LisaOS searches sectors until tag tells MDDF resides there, so we'll search 100 sectors for(int i = 0; i < 100; i++) { - DecodeTag(imagePlugin.ReadSectorTag((ulong)i, SectorTagType.AppleSectorTag), out LisaTag.PriamTag 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); @@ -307,11 +309,10 @@ namespace DiscImageChef.Filesystems.LisaFS sb.AppendFormat("Master copy ID: 0x{0:X8}", infoMddf.master_copy_id).AppendLine(); - sb.AppendFormat("Volume is number {0} of {1}", infoMddf.volnum, infoMddf.vol_sequence) - .AppendLine(); + 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}", - infoMddf.machine_id).AppendLine(); + sb.AppendFormat("Serial number of Lisa computer that created this volume: {0}", infoMddf.machine_id) + .AppendLine(); sb.AppendFormat("Serial number of Lisa computer that can use this volume's software {0}", infoMddf.serialization).AppendLine(); @@ -341,8 +342,7 @@ namespace DiscImageChef.Filesystems.LisaFS infoMddf.srec_ptr + infoMddf.mddf_block + beforeMddf, infoMddf.srec_len) .AppendLine(); - if(infoMddf.vol_left_mounted == 0) sb.AppendLine("Volume is clean"); - else sb.AppendLine("Volume is dirty"); + sb.AppendLine(infoMddf.vol_left_mounted == 0 ? "Volume is clean" : "Volume is dirty"); information = sb.ToString(); diff --git a/DiscImageChef.Filesystems/LisaFS/LisaFS.cs b/DiscImageChef.Filesystems/LisaFS/LisaFS.cs index 6ac5350f..2c87f582 100644 --- a/DiscImageChef.Filesystems/LisaFS/LisaFS.cs +++ b/DiscImageChef.Filesystems/LisaFS/LisaFS.cs @@ -43,31 +43,14 @@ namespace DiscImageChef.Filesystems.LisaFS // Variable names from Lisa API public partial class LisaFS : Filesystem { - bool mounted; - bool debug; readonly ImagePlugin device; + bool debug; + int devTagSize; MDDF mddf; - ulong volumePrefix; - int devTagSize; + bool mounted; SRecord[] srecords; - - #region Caches - /// Caches Extents Files - Dictionary extentCache; - /// Caches system files - Dictionary systemFileCache; - /// Caches user files files - Dictionary fileCache; - /// Caches catalogs - List catalogCache; - /// Caches file size - Dictionary fileSizeCache; - /// Lists Extents Files already printed in debug mode to not repeat them - List printedExtents; - /// Caches the creation times for subdirectories as to not have to traverse the Catalog File on each stat - Dictionary directoryDtcCache; - #endregion Caches + ulong volumePrefix; public LisaFS() { @@ -90,5 +73,22 @@ namespace DiscImageChef.Filesystems.LisaFS PluginUuid = new Guid("7E6034D1-D823-4248-A54D-239742B28391"); CurrentEncoding = new LisaRoman(); } + + #region Caches + /// Caches Extents Files + Dictionary extentCache; + /// Caches system files + Dictionary systemFileCache; + /// Caches user files files + Dictionary fileCache; + /// Caches catalogs + List catalogCache; + /// Caches file size + Dictionary fileSizeCache; + /// Lists Extents Files already printed in debug mode to not repeat them + List printedExtents; + /// Caches the creation times for subdirectories as to not have to traverse the Catalog File on each stat + Dictionary directoryDtcCache; + #endregion Caches } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/LisaFS/Structs.cs b/DiscImageChef.Filesystems/LisaFS/Structs.cs index e59f9aa1..a7d218c5 100644 --- a/DiscImageChef.Filesystems/LisaFS/Structs.cs +++ b/DiscImageChef.Filesystems/LisaFS/Structs.cs @@ -37,11 +37,11 @@ namespace DiscImageChef.Filesystems.LisaFS public partial class LisaFS { /// - /// The MDDF is the most import block on a Lisa FS volume. - /// It describes the volume and its contents. - /// On initialization the memory where it resides is not emptied - /// so it tends to contain a lot of garbage. This has difficulted - /// its reverse engineering. + /// The MDDF is the most import block on a Lisa FS volume. + /// It describes the volume and its contents. + /// On initialization the memory where it resides is not emptied + /// so it tends to contain a lot of garbage. This has difficulted + /// its reverse engineering. /// struct MDDF { @@ -209,10 +209,10 @@ namespace DiscImageChef.Filesystems.LisaFS } /// - /// An entry in the catalog from V3. - /// The first entry is bigger than the rest, may be a header, I have not needed any of its values so I just ignored it. - /// Each catalog is divided in 4-sector blocks, and if it needs more than a block there are previous and next block - /// pointers, effectively making the V3 catalog a double-linked list. Garbage is not zeroed. + /// An entry in the catalog from V3. + /// The first entry is bigger than the rest, may be a header, I have not needed any of its values so I just ignored it. + /// Each catalog is divided in 4-sector blocks, and if it needs more than a block there are previous and next block + /// pointers, effectively making the V3 catalog a double-linked list. Garbage is not zeroed. /// struct CatalogEntry { @@ -225,11 +225,11 @@ namespace DiscImageChef.Filesystems.LisaFS /// 0x23, null-termination public byte terminator; /// - /// At 0x24 - /// 0x01 here for subdirectories, entries 48 bytes long - /// 0x03 here for entries 64 bytes long - /// 0x08 here for entries 78 bytes long - /// This is incomplete, may fail, mostly works... + /// At 0x24 + /// 0x01 here for subdirectories, entries 48 bytes long + /// 0x03 here for entries 64 bytes long + /// 0x08 here for entries 78 bytes long + /// This is incomplete, may fail, mostly works... /// public byte fileType; /// 0x25, lot of values found here, unknown @@ -249,7 +249,7 @@ namespace DiscImageChef.Filesystems.LisaFS } /// - /// An extent indicating a start and a run of sectors. + /// An extent indicating a start and a run of sectors. /// struct Extent { @@ -258,12 +258,12 @@ namespace DiscImageChef.Filesystems.LisaFS } /// - /// The Extents File. There is one Extents File per each file stored on disk. - /// The file ID present on the sectors tags for the Extents File is the negated - /// value of the file ID it represents. e.g. file = 5 (0x0005) extents = -5 (0xFFFB) - /// It spans a single sector on V2 and V3 but 2 sectors on V1. - /// It contains all information about a file, and is indexed in the S-Records file. - /// It also contains the label. Garbage is zeroed. + /// The Extents File. There is one Extents File per each file stored on disk. + /// The file ID present on the sectors tags for the Extents File is the negated + /// value of the file ID it represents. e.g. file = 5 (0x0005) extents = -5 (0xFFFB) + /// It spans a single sector on V2 and V3 but 2 sectors on V1. + /// It contains all information about a file, and is indexed in the S-Records file. + /// It also contains the label. Garbage is zeroed. /// struct ExtentFile { @@ -335,29 +335,38 @@ namespace DiscImageChef.Filesystems.LisaFS public int length; /// 0x84, 0x204 in v1, unknown public int unknown9; - /// 0x88, 0x208 in v1, extents, can contain up to 41 extents (85 in v1), dunno LisaOS maximum (never seen more than 3) + /// + /// 0x88, 0x208 in v1, extents, can contain up to 41 extents (85 in v1), dunno LisaOS maximum (never seen more + /// than 3) + /// public Extent[] extents; /// 0x17E, unknown, empty, padding? public short unknown10; /// - /// At 0x180, this is the label. - /// While 1982 pre-release documentation says the label can be up to 448 bytes, v1 onward only have space for a 128 bytes one. - /// Any application can write whatever they want in the label, however, Lisa Office uses it to store its own information, something - /// that will effectively overwrite any information a user application wrote there. - /// The information written here by Lisa Office is like the information Finder writes in the FinderInfo structures, plus - /// the non-unique name that is shown on the GUI. For this reason I called it LisaInfo. - /// I have not tried to reverse engineer it. + /// At 0x180, this is the label. + /// While 1982 pre-release documentation says the label can be up to 448 bytes, v1 onward only have space for a 128 + /// bytes one. + /// Any application can write whatever they want in the label, however, Lisa Office uses it to store its own + /// information, something + /// that will effectively overwrite any information a user application wrote there. + /// The information written here by Lisa Office is like the information Finder writes in the FinderInfo structures, + /// plus + /// the non-unique name that is shown on the GUI. For this reason I called it LisaInfo. + /// I have not tried to reverse engineer it. /// public byte[] LisaInfo; } /// - /// The S-Records File is a hashtable of S-Records, where the hash is the file ID they belong to. - /// The S-Records File cannot be fragmented or grown, and it can easily become full before the 32766 file IDs are exhausted. - /// Each S-Record entry contains a block pointer to the Extents File that correspond to that file ID as well as the real file size, - /// the only important information about a file that's not inside the Extents File. - /// It also contains a low value (less than 0x200) variable field of unknown meaning and another one that seems to be flags, - /// with values like 0, 1, 3 and 5. + /// The S-Records File is a hashtable of S-Records, where the hash is the file ID they belong to. + /// The S-Records File cannot be fragmented or grown, and it can easily become full before the 32766 file IDs are + /// exhausted. + /// Each S-Record entry contains a block pointer to the Extents File that correspond to that file ID as well as the + /// real file size, + /// the only important information about a file that's not inside the Extents File. + /// It also contains a low value (less than 0x200) variable field of unknown meaning and another one that seems to be + /// flags, + /// with values like 0, 1, 3 and 5. /// struct SRecord { @@ -372,13 +381,13 @@ namespace DiscImageChef.Filesystems.LisaFS } /// - /// The catalog entry for the V1 and V2 volume formats. - /// It merely contains the file name, type and ID, plus a few (mostly empty) unknown fields. - /// Contrary to V3, it has no header and instead of being a double-linked list it is fragmented using an Extents File. - /// The Extents File position for the root catalog is then stored in the S-Records File. - /// Its entries are not filed sequentially denoting some kind of in-memory structure while at the same time - /// forcing LisaOS to read the whole catalog. That or I missed the pointers. - /// Empty entries just contain a 0-len filename. Garbage is not zeroed. + /// The catalog entry for the V1 and V2 volume formats. + /// It merely contains the file name, type and ID, plus a few (mostly empty) unknown fields. + /// Contrary to V3, it has no header and instead of being a double-linked list it is fragmented using an Extents File. + /// The Extents File position for the root catalog is then stored in the S-Records File. + /// Its entries are not filed sequentially denoting some kind of in-memory structure while at the same time + /// forcing LisaOS to read the whole catalog. That or I missed the pointers. + /// Empty entries just contain a 0-len filename. Garbage is not zeroed. /// struct CatalogEntryV2 { diff --git a/DiscImageChef.Filesystems/LisaFS/Super.cs b/DiscImageChef.Filesystems/LisaFS/Super.cs index 0ecc70f9..67a6b5eb 100644 --- a/DiscImageChef.Filesystems/LisaFS/Super.cs +++ b/DiscImageChef.Filesystems/LisaFS/Super.cs @@ -42,7 +42,7 @@ namespace DiscImageChef.Filesystems.LisaFS public partial class LisaFS { /// - /// Mounts an Apple Lisa filesystem + /// Mounts an Apple Lisa filesystem /// public override Errno Mount() { @@ -50,7 +50,7 @@ namespace DiscImageChef.Filesystems.LisaFS } /// - /// Mounts an Apple Lisa filesystem + /// Mounts an Apple Lisa filesystem /// public override Errno Mount(bool debug) { @@ -319,7 +319,7 @@ namespace DiscImageChef.Filesystems.LisaFS } /// - /// Umounts this Lisa filesystem + /// Umounts this Lisa filesystem /// public override Errno Unmount() { @@ -339,7 +339,7 @@ namespace DiscImageChef.Filesystems.LisaFS } /// - /// Gets information about the mounted volume. + /// Gets information about the mounted volume. /// /// Information about the mounted volume. public override Errno StatFs(ref FileSystemInfo stat) diff --git a/DiscImageChef.Filesystems/LisaFS/Xattr.cs b/DiscImageChef.Filesystems/LisaFS/Xattr.cs index 553ed7df..221caf16 100644 --- a/DiscImageChef.Filesystems/LisaFS/Xattr.cs +++ b/DiscImageChef.Filesystems/LisaFS/Xattr.cs @@ -41,7 +41,7 @@ namespace DiscImageChef.Filesystems.LisaFS public partial class LisaFS { /// - /// Lists all extended attributes, alternate data streams and forks of the given file. + /// Lists all extended attributes, alternate data streams and forks of the given file. /// /// Error number. /// Path. @@ -55,7 +55,7 @@ namespace DiscImageChef.Filesystems.LisaFS } /// - /// Reads an extended attribute, alternate data stream or fork from the given file. + /// Reads an extended attribute, alternate data stream or fork from the given file. /// /// Error number. /// File path. @@ -70,7 +70,7 @@ namespace DiscImageChef.Filesystems.LisaFS } /// - /// Lists special Apple Lisa filesystem features as extended attributes + /// Lists special Apple Lisa filesystem features as extended attributes /// /// Error number. /// File identifier. @@ -125,7 +125,7 @@ namespace DiscImageChef.Filesystems.LisaFS } /// - /// Lists special Apple Lisa filesystem features as extended attributes + /// Lists special Apple Lisa filesystem features as extended attributes /// /// Error number. /// File identifier. @@ -161,7 +161,8 @@ namespace DiscImageChef.Filesystems.LisaFS if(error != Errno.NoError) return error; - switch(xattr) { + switch(xattr) + { case "com.apple.lisa.password" when file.password_valid > 0: buf = new byte[8]; Array.Copy(file.password, 0, buf, 0, 8); @@ -184,7 +185,7 @@ namespace DiscImageChef.Filesystems.LisaFS } /// - /// Decodes a sector tag. Not tested with 24-byte tags. + /// Decodes a sector tag. Not tested with 24-byte tags. /// /// Error number. /// Sector tag. diff --git a/DiscImageChef.Filesystems/Locus.cs b/DiscImageChef.Filesystems/Locus.cs index 034912a7..77c613aa 100644 --- a/DiscImageChef.Filesystems/Locus.cs +++ b/DiscImageChef.Filesystems/Locus.cs @@ -56,8 +56,6 @@ using time_t = System.Int32; namespace DiscImageChef.Filesystems { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "BuiltInTypeReferenceStyle")] public class Locus : Filesystem { const int NICINOD = 325; @@ -65,131 +63,6 @@ namespace DiscImageChef.Filesystems const int OLDNICINOD = 700; const int OLDNICFREE = 500; - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct Locus_Superblock - { - public uint s_magic; /* identifies this as a locus filesystem */ - /* defined as a constant below */ - public gfs_t s_gfs; /* global filesystem number */ - public daddr_t s_fsize; /* size in blocks of entire volume */ - /* several ints for replicated filsystems */ - public commitcnt_t s_lwm; /* all prior commits propagated */ - public commitcnt_t s_hwm; /* highest commit propagated */ - /* oldest committed version in the list. - * llst mod NCMTLST is the offset of commit #llst in the list, - * which wraps around from there. - */ - public commitcnt_t s_llst; - public fstore_t s_fstore; /* filesystem storage bit mask; if the - filsys is replicated and this is not a - primary or backbone copy, this bit mask - determines which files are stored */ - - public time_t s_time; /* last super block update */ - public daddr_t s_tfree; /* total free blocks*/ - - public ino_t s_isize; /* size in blocks of i-list */ - public short s_nfree; /* number of addresses in s_free */ - public LocusFlags s_flags; /* filsys flags, defined below */ - public ino_t s_tinode; /* total free inodes */ - public ino_t s_lasti; /* start place for circular search */ - public ino_t s_nbehind; /* est # free inodes before s_lasti */ - public pckno_t s_gfspack; /* global filesystem pack number */ - public short s_ninode; /* number of i-nodes in s_inode */ - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public short[] s_dinfo; /* interleave stuff */ - //#define s_m s_dinfo[0] - //#define s_skip s_dinfo[0] /* AIX defines */ - //#define s_n s_dinfo[1] - //#define s_cyl s_dinfo[1] /* AIX defines */ - public byte s_flock; /* lock during free list manipulation */ - public byte s_ilock; /* lock during i-list manipulation */ - public byte s_fmod; /* super block modified flag */ - public LocusVersion s_version; /* version of the data format in fs. */ - /* defined below. */ - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public byte[] s_fsmnt; /* name of this file system */ - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] - public byte[] s_fpack; /* name of this physical volume */ - [MarshalAs(UnmanagedType.ByValArray, SizeConst = NICINOD)] public ino_t[] s_inode; /* free i-node list */ - [MarshalAs(UnmanagedType.ByValArray, SizeConst = NICFREE)] - public daddr_t[] su_free; /* free block list for non-replicated filsys */ - public byte s_byteorder; /* byte order of integers */ - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct Locus_OldSuperblock - { - public uint s_magic; /* identifies this as a locus filesystem */ - /* defined as a constant below */ - public gfs_t s_gfs; /* global filesystem number */ - public daddr_t s_fsize; /* size in blocks of entire volume */ - /* several ints for replicated filsystems */ - public commitcnt_t s_lwm; /* all prior commits propagated */ - public commitcnt_t s_hwm; /* highest commit propagated */ - /* oldest committed version in the list. - * llst mod NCMTLST is the offset of commit #llst in the list, - * which wraps around from there. - */ - public commitcnt_t s_llst; - public fstore_t s_fstore; /* filesystem storage bit mask; if the - filsys is replicated and this is not a - primary or backbone copy, this bit mask - determines which files are stored */ - - public time_t s_time; /* last super block update */ - public daddr_t s_tfree; /* total free blocks*/ - - public ino_t s_isize; /* size in blocks of i-list */ - public short s_nfree; /* number of addresses in s_free */ - public LocusFlags s_flags; /* filsys flags, defined below */ - public ino_t s_tinode; /* total free inodes */ - public ino_t s_lasti; /* start place for circular search */ - public ino_t s_nbehind; /* est # free inodes before s_lasti */ - public pckno_t s_gfspack; /* global filesystem pack number */ - public short s_ninode; /* number of i-nodes in s_inode */ - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public short[] s_dinfo; /* interleave stuff */ - //#define s_m s_dinfo[0] - //#define s_skip s_dinfo[0] /* AIX defines */ - //#define s_n s_dinfo[1] - //#define s_cyl s_dinfo[1] /* AIX defines */ - public byte s_flock; /* lock during free list manipulation */ - public byte s_ilock; /* lock during i-list manipulation */ - public byte s_fmod; /* super block modified flag */ - public LocusVersion s_version; /* version of the data format in fs. */ - /* defined below. */ - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public byte[] s_fsmnt; /* name of this file system */ - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] - public byte[] s_fpack; /* name of this physical volume */ - [MarshalAs(UnmanagedType.ByValArray, SizeConst = OLDNICINOD)] public ino_t[] s_inode; /* free i-node list */ - [MarshalAs(UnmanagedType.ByValArray, SizeConst = OLDNICFREE)] - public daddr_t[] su_free; /* free block list for non-replicated filsys */ - public byte s_byteorder; /* byte order of integers */ - } - - [Flags] - enum LocusFlags : ushort - { - SB_RDONLY = 0x1, /* no writes on filesystem */ - SB_CLEAN = 0x2, /* fs unmounted cleanly (or checks run) */ - SB_DIRTY = 0x4, /* fs mounted without CLEAN bit set */ - SB_RMV = 0x8, /* fs is a removable file system */ - SB_PRIMPACK = 0x10, /* This is the primary pack of the filesystem */ - SB_REPLTYPE = 0x20, /* This is a replicated type filesystem. */ - SB_USER = 0x40, /* This is a "user" replicated filesystem. */ - SB_BACKBONE = 0x80, /* backbone pack ; complete copy of primary pack but not modifiable */ - SB_NFS = 0x100, /* This is a NFS type filesystem */ - SB_BYHAND = 0x200, /* Inhibits automatic fscks on a mangled file system */ - SB_NOSUID = 0x400, /* Set-uid/Set-gid is disabled */ - SB_SYNCW = 0x800 /* Synchronous Write */ - } - - [Flags] - enum LocusVersion : byte - { - SB_SB4096 = 1, /* smallblock filesys with 4096 byte blocks */ - SB_B1024 = 2, /* 1024 byte block filesystem */ - NUMSCANDEV = 5 /* Used by scangfs(), refed in space.h */ - } - const uint Locus_Magic = 0xFFEEDDCD; const uint Locus_Cigam = 0xCDDDEEFF; const uint Locus_OldMagic = 0xFFEEDDCC; @@ -246,8 +119,7 @@ namespace DiscImageChef.Filesystems return false; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { information = ""; if(imagePlugin.GetSectorSize() < 512) return; @@ -417,5 +289,138 @@ namespace DiscImageChef.Filesystems { return Errno.NotImplemented; } + + [SuppressMessage("ReSharper", "InconsistentNaming")] + [SuppressMessage("ReSharper", "BuiltInTypeReferenceStyle")] + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct Locus_Superblock + { + public uint s_magic; /* identifies this as a locus filesystem */ + /* defined as a constant below */ + public gfs_t s_gfs; /* global filesystem number */ + public daddr_t s_fsize; /* size in blocks of entire volume */ + /* several ints for replicated filsystems */ + public commitcnt_t s_lwm; /* all prior commits propagated */ + public commitcnt_t s_hwm; /* highest commit propagated */ + /* oldest committed version in the list. + * llst mod NCMTLST is the offset of commit #llst in the list, + * which wraps around from there. + */ + public commitcnt_t s_llst; + public fstore_t s_fstore; /* filesystem storage bit mask; if the + filsys is replicated and this is not a + primary or backbone copy, this bit mask + determines which files are stored */ + + public time_t s_time; /* last super block update */ + public daddr_t s_tfree; /* total free blocks*/ + + public ino_t s_isize; /* size in blocks of i-list */ + public short s_nfree; /* number of addresses in s_free */ + public LocusFlags s_flags; /* filsys flags, defined below */ + public ino_t s_tinode; /* total free inodes */ + public ino_t s_lasti; /* start place for circular search */ + public ino_t s_nbehind; /* est # free inodes before s_lasti */ + public pckno_t s_gfspack; /* global filesystem pack number */ + public short s_ninode; /* number of i-nodes in s_inode */ + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public short[] s_dinfo; /* interleave stuff */ + //#define s_m s_dinfo[0] + //#define s_skip s_dinfo[0] /* AIX defines */ + //#define s_n s_dinfo[1] + //#define s_cyl s_dinfo[1] /* AIX defines */ + public byte s_flock; /* lock during free list manipulation */ + public byte s_ilock; /* lock during i-list manipulation */ + public byte s_fmod; /* super block modified flag */ + public LocusVersion s_version; /* version of the data format in fs. */ + /* defined below. */ + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public byte[] s_fsmnt; /* name of this file system */ + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] + public byte[] s_fpack; /* name of this physical volume */ + [MarshalAs(UnmanagedType.ByValArray, SizeConst = NICINOD)] public ino_t[] s_inode; /* free i-node list */ + [MarshalAs(UnmanagedType.ByValArray, SizeConst = NICFREE)] + public daddr_t[] su_free; /* free block list for non-replicated filsys */ + public byte s_byteorder; /* byte order of integers */ + } + + [SuppressMessage("ReSharper", "InconsistentNaming")] + [SuppressMessage("ReSharper", "BuiltInTypeReferenceStyle")] + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct Locus_OldSuperblock + { + public uint s_magic; /* identifies this as a locus filesystem */ + /* defined as a constant below */ + public gfs_t s_gfs; /* global filesystem number */ + public daddr_t s_fsize; /* size in blocks of entire volume */ + /* several ints for replicated filsystems */ + public commitcnt_t s_lwm; /* all prior commits propagated */ + public commitcnt_t s_hwm; /* highest commit propagated */ + /* oldest committed version in the list. + * llst mod NCMTLST is the offset of commit #llst in the list, + * which wraps around from there. + */ + public commitcnt_t s_llst; + public fstore_t s_fstore; /* filesystem storage bit mask; if the + filsys is replicated and this is not a + primary or backbone copy, this bit mask + determines which files are stored */ + + public time_t s_time; /* last super block update */ + public daddr_t s_tfree; /* total free blocks*/ + + public ino_t s_isize; /* size in blocks of i-list */ + public short s_nfree; /* number of addresses in s_free */ + public LocusFlags s_flags; /* filsys flags, defined below */ + public ino_t s_tinode; /* total free inodes */ + public ino_t s_lasti; /* start place for circular search */ + public ino_t s_nbehind; /* est # free inodes before s_lasti */ + public pckno_t s_gfspack; /* global filesystem pack number */ + public short s_ninode; /* number of i-nodes in s_inode */ + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public short[] s_dinfo; /* interleave stuff */ + //#define s_m s_dinfo[0] + //#define s_skip s_dinfo[0] /* AIX defines */ + //#define s_n s_dinfo[1] + //#define s_cyl s_dinfo[1] /* AIX defines */ + public byte s_flock; /* lock during free list manipulation */ + public byte s_ilock; /* lock during i-list manipulation */ + public byte s_fmod; /* super block modified flag */ + public LocusVersion s_version; /* version of the data format in fs. */ + /* defined below. */ + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public byte[] s_fsmnt; /* name of this file system */ + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] + public byte[] s_fpack; /* name of this physical volume */ + [MarshalAs(UnmanagedType.ByValArray, SizeConst = OLDNICINOD)] public ino_t[] s_inode; /* free i-node list */ + [MarshalAs(UnmanagedType.ByValArray, SizeConst = OLDNICFREE)] + public daddr_t[] su_free; /* free block list for non-replicated filsys */ + public byte s_byteorder; /* byte order of integers */ + } + + [SuppressMessage("ReSharper", "InconsistentNaming")] + [SuppressMessage("ReSharper", "BuiltInTypeReferenceStyle")] + [Flags] + enum LocusFlags : ushort + { + SB_RDONLY = 0x1, /* no writes on filesystem */ + SB_CLEAN = 0x2, /* fs unmounted cleanly (or checks run) */ + SB_DIRTY = 0x4, /* fs mounted without CLEAN bit set */ + SB_RMV = 0x8, /* fs is a removable file system */ + SB_PRIMPACK = 0x10, /* This is the primary pack of the filesystem */ + SB_REPLTYPE = 0x20, /* This is a replicated type filesystem. */ + SB_USER = 0x40, /* This is a "user" replicated filesystem. */ + SB_BACKBONE = 0x80, /* backbone pack ; complete copy of primary pack but not modifiable */ + SB_NFS = 0x100, /* This is a NFS type filesystem */ + SB_BYHAND = 0x200, /* Inhibits automatic fscks on a mangled file system */ + SB_NOSUID = 0x400, /* Set-uid/Set-gid is disabled */ + SB_SYNCW = 0x800 /* Synchronous Write */ + } + + [SuppressMessage("ReSharper", "InconsistentNaming")] + [SuppressMessage("ReSharper", "BuiltInTypeReferenceStyle")] + [Flags] + enum LocusVersion : byte + { + SB_SB4096 = 1, /* smallblock filesys with 4096 byte blocks */ + SB_B1024 = 2, /* 1024 byte block filesystem */ + NUMSCANDEV = 5 /* Used by scangfs(), refed in space.h */ + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/MicroDOS.cs b/DiscImageChef.Filesystems/MicroDOS.cs index 3efd12d6..73b050dd 100644 --- a/DiscImageChef.Filesystems/MicroDOS.cs +++ b/DiscImageChef.Filesystems/MicroDOS.cs @@ -77,14 +77,14 @@ namespace DiscImageChef.Filesystems byte[] bk0 = imagePlugin.ReadSector(0 + partition.Start); GCHandle handle = GCHandle.Alloc(bk0, GCHandleType.Pinned); - MicroDOSBlock0 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; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { information = ""; @@ -93,7 +93,8 @@ namespace DiscImageChef.Filesystems byte[] bk0 = imagePlugin.ReadSector(0 + partition.Start); GCHandle handle = GCHandle.Alloc(bk0, GCHandleType.Pinned); - MicroDOSBlock0 block0 = (MicroDOSBlock0)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(MicroDOSBlock0)); + MicroDOSBlock0 block0 = + (MicroDOSBlock0)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(MicroDOSBlock0)); handle.Free(); sb.AppendLine("MicroDOS filesystem"); @@ -117,62 +118,6 @@ namespace DiscImageChef.Filesystems information = sb.ToString(); } - // Followed by directory entries - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct MicroDOSBlock0 - { - /// BK starts booting here - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 24)] public byte[] bootCode; - /// Number of files in directory - public ushort files; - /// Total number of blocks in files of the directory - public ushort usedBlocks; - /// Unknown - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 228)] public byte[] unknown; - /// Ownership label (label that shows it belongs to Micro DOS format) - public ushort label; - /// MK-DOS directory format label - public ushort mklabel; - /// Unknown - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 50)] public byte[] unknown2; - /// Disk size in blocks (absolute value for the system unlike NORD, NORTON etc.) that - /// doesn't use two fixed values 40 or 80 tracks, but i.e. if you drive works with 76 tracks - /// this field will contain an appropriate number of blocks - public ushort blocks; - /// Number of the first file's block. Value is changable - public ushort firstUsedBlock; - /// Unknown - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] public byte[] unknown3; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct DirectoryEntry - { - /// File status - public byte status; - /// Directory number (0 - root) - public byte directory; - /// File name 14. symbols in ASCII KOI8 - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] public byte[] filename; - /// Block number - public ushort blockNo; - /// Length in blocks - public ushort blocks; - /// Address - public ushort address; - /// Length - public ushort length; - } - - enum FileStatus : byte - { - CommonFile = 0, - Protected = 1, - LogicalDisk = 2, - BadFile = 0x80, - Deleted = 0xFF - } - public override Errno Mount() { return Errno.NotImplemented; @@ -232,5 +177,63 @@ namespace DiscImageChef.Filesystems { return Errno.NotImplemented; } + + // Followed by directory entries + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct MicroDOSBlock0 + { + /// BK starts booting here + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 24)] public byte[] bootCode; + /// Number of files in directory + public ushort files; + /// Total number of blocks in files of the directory + public ushort usedBlocks; + /// Unknown + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 228)] public byte[] unknown; + /// Ownership label (label that shows it belongs to Micro DOS format) + public ushort label; + /// MK-DOS directory format label + public ushort mklabel; + /// Unknown + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 50)] public byte[] unknown2; + /// + /// Disk size in blocks (absolute value for the system unlike NORD, NORTON etc.) that + /// doesn't use two fixed values 40 or 80 tracks, but i.e. if you drive works with 76 tracks + /// this field will contain an appropriate number of blocks + /// + public ushort blocks; + /// Number of the first file's block. Value is changable + public ushort firstUsedBlock; + /// Unknown + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] public byte[] unknown3; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct DirectoryEntry + { + /// File status + public byte status; + /// Directory number (0 - root) + public byte directory; + /// File name 14. symbols in ASCII KOI8 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] public byte[] filename; + /// Block number + public ushort blockNo; + /// Length in blocks + public ushort blocks; + /// Address + public ushort address; + /// Length + public ushort length; + } + + enum FileStatus : byte + { + CommonFile = 0, + Protected = 1, + LogicalDisk = 2, + BadFile = 0x80, + Deleted = 0xFF + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/MinixFS.cs b/DiscImageChef.Filesystems/MinixFS.cs index a388b4b7..609f99b7 100644 --- a/DiscImageChef.Filesystems/MinixFS.cs +++ b/DiscImageChef.Filesystems/MinixFS.cs @@ -124,8 +124,7 @@ namespace DiscImageChef.Filesystems return false; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { information = ""; @@ -166,7 +165,8 @@ namespace DiscImageChef.Filesystems filenamesize = 60; littleEndian = magic != MINIX3_CIGAM || magic == MINIX2_CIGAM || magic == MINIX_CIGAM; - switch(magic) { + switch(magic) + { case MINIX3_MAGIC: case MINIX3_CIGAM: minixVersion = "Minix v3 filesystem"; @@ -251,7 +251,7 @@ namespace DiscImageChef.Filesystems { GCHandle handle = GCHandle.Alloc(minixSbSector, GCHandleType.Pinned); mnxSb = (Minix3SuperBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), - typeof(Minix3SuperBlock)); + typeof(Minix3SuperBlock)); handle.Free(); } else mnxSb = BigEndianMarshal.ByteArrayToStructureBigEndian(minixSbSector); @@ -288,7 +288,7 @@ namespace DiscImageChef.Filesystems { GCHandle handle = GCHandle.Alloc(minixSbSector, GCHandleType.Pinned); mnxSb = (MinixSuperBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), - typeof(MinixSuperBlock)); + typeof(MinixSuperBlock)); handle.Free(); } else mnxSb = BigEndianMarshal.ByteArrayToStructureBigEndian(minixSbSector); @@ -302,8 +302,8 @@ namespace DiscImageChef.Filesystems sb.AppendFormat("{0} zones on volume ({1} bytes)", mnxSb.s_nzones, mnxSb.s_nzones * 1024) .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 * 1024).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}", mnxSb.s_firstdatazone).AppendLine(); @@ -316,68 +316,6 @@ namespace DiscImageChef.Filesystems information = sb.ToString(); } - /// - /// Superblock for Minix v1 and V2 filesystems - /// - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct MinixSuperBlock - { - /// 0x00, inodes on volume - public ushort s_ninodes; - /// 0x02, zones on volume - public ushort s_nzones; - /// 0x04, blocks on inode map - public short s_imap_blocks; - /// 0x06, blocks on zone map - public short s_zmap_blocks; - /// 0x08, first data zone - public ushort s_firstdatazone; - /// 0x0A, log2 of blocks/zone - public short s_log_zone_size; - /// 0x0C, max file size - public uint s_max_size; - /// 0x10, magic - public ushort s_magic; - /// 0x12, filesystem state - public ushort s_state; - /// 0x14, number of zones - public uint s_zones; - } - - /// - /// Superblock for Minix v3 filesystems - /// - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct Minix3SuperBlock - { - /// 0x00, inodes on volume - public uint s_ninodes; - /// 0x02, old zones on volume - public ushort s_nzones; - /// 0x06, blocks on inode map - public ushort s_imap_blocks; - /// 0x08, blocks on zone map - public ushort s_zmap_blocks; - /// 0x0A, first data zone - public ushort s_firstdatazone; - /// 0x0C, log2 of blocks/zone - public ushort s_log_zone_size; - /// 0x0E, padding - public ushort s_pad1; - /// 0x10, max file size - public uint s_max_size; - /// 0x14, number of zones - public uint s_zones; - /// 0x18, magic - public ushort s_magic; - /// 0x1A, padding - public ushort s_pad2; - /// 0x1C, bytes in a block - public ushort s_blocksize; - /// 0x1E, on-disk structures version - public byte s_disk_version; - } - public override Errno Mount() { return Errno.NotImplemented; @@ -437,5 +375,67 @@ namespace DiscImageChef.Filesystems { return Errno.NotImplemented; } + + /// + /// Superblock for Minix v1 and V2 filesystems + /// + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct MinixSuperBlock + { + /// 0x00, inodes on volume + public ushort s_ninodes; + /// 0x02, zones on volume + public ushort s_nzones; + /// 0x04, blocks on inode map + public short s_imap_blocks; + /// 0x06, blocks on zone map + public short s_zmap_blocks; + /// 0x08, first data zone + public ushort s_firstdatazone; + /// 0x0A, log2 of blocks/zone + public short s_log_zone_size; + /// 0x0C, max file size + public uint s_max_size; + /// 0x10, magic + public ushort s_magic; + /// 0x12, filesystem state + public ushort s_state; + /// 0x14, number of zones + public uint s_zones; + } + + /// + /// Superblock for Minix v3 filesystems + /// + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct Minix3SuperBlock + { + /// 0x00, inodes on volume + public uint s_ninodes; + /// 0x02, old zones on volume + public ushort s_nzones; + /// 0x06, blocks on inode map + public ushort s_imap_blocks; + /// 0x08, blocks on zone map + public ushort s_zmap_blocks; + /// 0x0A, first data zone + public ushort s_firstdatazone; + /// 0x0C, log2 of blocks/zone + public ushort s_log_zone_size; + /// 0x0E, padding + public ushort s_pad1; + /// 0x10, max file size + public uint s_max_size; + /// 0x14, number of zones + public uint s_zones; + /// 0x18, magic + public ushort s_magic; + /// 0x1A, padding + public ushort s_pad2; + /// 0x1C, bytes in a block + public ushort s_blocksize; + /// 0x1E, on-disk structures version + public byte s_disk_version; + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/NILFS2.cs b/DiscImageChef.Filesystems/NILFS2.cs index 4b3e029b..e775ba04 100644 --- a/DiscImageChef.Filesystems/NILFS2.cs +++ b/DiscImageChef.Filesystems/NILFS2.cs @@ -42,59 +42,6 @@ namespace DiscImageChef.Filesystems { public class NILFS2 : Filesystem { - enum NILFS2_State : ushort - { - Valid = 0x0001, - Error = 0x0002, - Resize = 0x0004 - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct NILFS2_Superblock - { - public uint rev_level; - public ushort minor_rev_level; - public ushort magic; - public ushort bytes; - public ushort flags; - public uint crc_seed; - public uint sum; - public uint log_block_size; - public ulong nsegments; - public ulong dev_size; - public ulong first_data_block; - public uint blocks_per_segment; - public uint r_segments_percentage; - public ulong last_cno; - public ulong last_pseg; - public ulong last_seq; - public ulong free_blocks_count; - public ulong ctime; - public ulong mtime; - public ulong wtime; - public ushort mnt_count; - public ushort max_mnt_count; - public NILFS2_State state; - public ushort errors; - public ulong lastcheck; - public uint checkinterval; - public uint creator_os; - public ushort def_resuid; - public ushort def_resgid; - public uint first_ino; - public ushort inode_size; - public ushort dat_entry_size; - public ushort checkpoint_size; - public ushort segment_usage_size; - public Guid uuid; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 80)] public byte[] volume_name; - public uint c_interval; - public uint c_block_max; - public ulong feature_compat; - public ulong feature_compat_ro; - public ulong feature_incompat; - } - const ushort NILFS2_MAGIC = 0x3434; const uint NILFS2_SUPER_OFFSET = 1024; @@ -144,8 +91,7 @@ namespace DiscImageChef.Filesystems return nilfsSb.magic == NILFS2_MAGIC; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { information = ""; if(imagePlugin.GetSectorSize() < 512) return; @@ -264,5 +210,58 @@ namespace DiscImageChef.Filesystems { return Errno.NotImplemented; } + + enum NILFS2_State : ushort + { + Valid = 0x0001, + Error = 0x0002, + Resize = 0x0004 + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct NILFS2_Superblock + { + public uint rev_level; + public ushort minor_rev_level; + public ushort magic; + public ushort bytes; + public ushort flags; + public uint crc_seed; + public uint sum; + public uint log_block_size; + public ulong nsegments; + public ulong dev_size; + public ulong first_data_block; + public uint blocks_per_segment; + public uint r_segments_percentage; + public ulong last_cno; + public ulong last_pseg; + public ulong last_seq; + public ulong free_blocks_count; + public ulong ctime; + public ulong mtime; + public ulong wtime; + public ushort mnt_count; + public ushort max_mnt_count; + public NILFS2_State state; + public ushort errors; + public ulong lastcheck; + public uint checkinterval; + public uint creator_os; + public ushort def_resuid; + public ushort def_resgid; + public uint first_ino; + public ushort inode_size; + public ushort dat_entry_size; + public ushort checkpoint_size; + public ushort segment_usage_size; + public Guid uuid; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 80)] public byte[] volume_name; + public uint c_interval; + public uint c_block_max; + public ulong feature_compat; + public ulong feature_compat_ro; + public ulong feature_incompat; + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/NTFS.cs b/DiscImageChef.Filesystems/NTFS.cs index 69694169..166600f5 100644 --- a/DiscImageChef.Filesystems/NTFS.cs +++ b/DiscImageChef.Filesystems/NTFS.cs @@ -93,8 +93,7 @@ namespace DiscImageChef.Filesystems return signature == 0xAA55; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { information = ""; @@ -141,8 +140,7 @@ namespace DiscImageChef.Filesystems XmlFsType = new FileSystemType(); - if(ntfsBb.jump[0] == 0xEB && ntfsBb.jump[1] > 0x4E && ntfsBb.jump[1] < 0x80 && - ntfsBb.signature2 == 0xAA55) + if(ntfsBb.jump[0] == 0xEB && ntfsBb.jump[1] > 0x4E && ntfsBb.jump[1] < 0x80 && ntfsBb.signature2 == 0xAA55) { XmlFsType.Bootable = true; Sha1Context sha1Ctx = new Sha1Context(); @@ -160,8 +158,68 @@ namespace DiscImageChef.Filesystems information = sb.ToString(); } + public override Errno Mount() + { + return Errno.NotImplemented; + } + + public override Errno Mount(bool debug) + { + return Errno.NotImplemented; + } + + public override Errno Unmount() + { + return Errno.NotImplemented; + } + + public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + { + return Errno.NotImplemented; + } + + public override Errno GetAttributes(string path, ref FileAttributes attributes) + { + return Errno.NotImplemented; + } + + public override Errno ListXAttr(string path, ref List xattrs) + { + return Errno.NotImplemented; + } + + public override Errno GetXattr(string path, string xattr, ref byte[] buf) + { + return Errno.NotImplemented; + } + + public override Errno Read(string path, long offset, long size, ref byte[] buf) + { + return Errno.NotImplemented; + } + + public override Errno ReadDir(string path, ref List contents) + { + return Errno.NotImplemented; + } + + public override Errno StatFs(ref FileSystemInfo stat) + { + return Errno.NotImplemented; + } + + public override Errno Stat(string path, ref FileEntryInfo stat) + { + return Errno.NotImplemented; + } + + public override Errno ReadLink(string path, ref string dest) + { + return Errno.NotImplemented; + } + /// - /// NTFS $BOOT + /// NTFS $BOOT /// [StructLayout(LayoutKind.Sequential, Pack = 1)] struct NtfsBootBlock @@ -231,65 +289,5 @@ namespace DiscImageChef.Filesystems /// 0x1FE, 0xAA55 public ushort signature2; } - - public override Errno Mount() - { - return Errno.NotImplemented; - } - - public override Errno Mount(bool debug) - { - return Errno.NotImplemented; - } - - public override Errno Unmount() - { - return Errno.NotImplemented; - } - - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) - { - return Errno.NotImplemented; - } - - public override Errno GetAttributes(string path, ref FileAttributes attributes) - { - return Errno.NotImplemented; - } - - public override Errno ListXAttr(string path, ref List xattrs) - { - return Errno.NotImplemented; - } - - public override Errno GetXattr(string path, string xattr, ref byte[] buf) - { - return Errno.NotImplemented; - } - - public override Errno Read(string path, long offset, long size, ref byte[] buf) - { - return Errno.NotImplemented; - } - - public override Errno ReadDir(string path, ref List contents) - { - return Errno.NotImplemented; - } - - public override Errno StatFs(ref FileSystemInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) - { - return Errno.NotImplemented; - } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/Nintendo.cs b/DiscImageChef.Filesystems/Nintendo.cs index ba013802..32c97d5a 100644 --- a/DiscImageChef.Filesystems/Nintendo.cs +++ b/DiscImageChef.Filesystems/Nintendo.cs @@ -79,8 +79,7 @@ namespace DiscImageChef.Filesystems return magicGc == 0xC2339F3D || magicWii == 0x5D1C9EA3; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { StringBuilder sbInformation = new StringBuilder(); information = ""; @@ -96,10 +95,8 @@ namespace DiscImageChef.Filesystems uint magicGc = BigEndianBitConverter.ToUInt32(header, 0x1C); uint magicWii = BigEndianBitConverter.ToUInt32(header, 0x18); - if(magicWii == 0x5D1C9EA3) - wii = true; - else if(magicGc != 0xC2339F3D) - return; + if(magicWii == 0x5D1C9EA3) wii = true; + else if(magicGc != 0xC2339F3D) return; fields.DiscType = Encoding.ASCII.GetString(header, 0, 1); fields.GameCode = Encoding.ASCII.GetString(header, 1, 2); @@ -314,46 +311,6 @@ namespace DiscImageChef.Filesystems 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; - } - - struct NintendoPartition - { - public uint Offset; - public uint Type; - } - static string DiscTypeToString(string discType) { switch(discType) @@ -510,5 +467,45 @@ namespace DiscImageChef.Filesystems { return Errno.NotImplemented; } + + 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; + } + + struct NintendoPartition + { + public uint Offset; + public uint Type; + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/ODS.cs b/DiscImageChef.Filesystems/ODS.cs index aabfdf43..51f2238b 100644 --- a/DiscImageChef.Filesystems/ODS.cs +++ b/DiscImageChef.Filesystems/ODS.cs @@ -104,8 +104,7 @@ namespace DiscImageChef.Filesystems return magic == "DECFILE11A " || magic == "DECFILE11B "; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { information = ""; @@ -114,7 +113,8 @@ namespace DiscImageChef.Filesystems byte[] hbSector = imagePlugin.ReadSector(1 + partition.Start); GCHandle handle = GCHandle.Alloc(hbSector, GCHandleType.Pinned); - OdsHomeBlock homeblock = (OdsHomeBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(OdsHomeBlock)); + OdsHomeBlock homeblock = + (OdsHomeBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(OdsHomeBlock)); handle.Free(); // Optical disc @@ -241,6 +241,66 @@ namespace DiscImageChef.Filesystems information = sb.ToString(); } + public override Errno Mount() + { + return Errno.NotImplemented; + } + + public override Errno Mount(bool debug) + { + return Errno.NotImplemented; + } + + public override Errno Unmount() + { + return Errno.NotImplemented; + } + + public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + { + return Errno.NotImplemented; + } + + public override Errno GetAttributes(string path, ref FileAttributes attributes) + { + return Errno.NotImplemented; + } + + public override Errno ListXAttr(string path, ref List xattrs) + { + return Errno.NotImplemented; + } + + public override Errno GetXattr(string path, string xattr, ref byte[] buf) + { + return Errno.NotImplemented; + } + + public override Errno Read(string path, long offset, long size, ref byte[] buf) + { + return Errno.NotImplemented; + } + + public override Errno ReadDir(string path, ref List contents) + { + return Errno.NotImplemented; + } + + public override Errno StatFs(ref FileSystemInfo stat) + { + return Errno.NotImplemented; + } + + public override Errno Stat(string path, ref FileEntryInfo stat) + { + return Errno.NotImplemented; + } + + public override Errno ReadLink(string path, ref string dest) + { + return Errno.NotImplemented; + } + [StructLayout(LayoutKind.Sequential, Pack = 1)] struct OdsHomeBlock { @@ -337,65 +397,5 @@ namespace DiscImageChef.Filesystems /// 0x1FE, Checksum of preceding 255 words (16 bit units) public ushort checksum2; } - - public override Errno Mount() - { - return Errno.NotImplemented; - } - - public override Errno Mount(bool debug) - { - return Errno.NotImplemented; - } - - public override Errno Unmount() - { - return Errno.NotImplemented; - } - - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) - { - return Errno.NotImplemented; - } - - public override Errno GetAttributes(string path, ref FileAttributes attributes) - { - return Errno.NotImplemented; - } - - public override Errno ListXAttr(string path, ref List xattrs) - { - return Errno.NotImplemented; - } - - public override Errno GetXattr(string path, string xattr, ref byte[] buf) - { - return Errno.NotImplemented; - } - - public override Errno Read(string path, long offset, long size, ref byte[] buf) - { - return Errno.NotImplemented; - } - - public override Errno ReadDir(string path, ref List contents) - { - return Errno.NotImplemented; - } - - public override Errno StatFs(ref FileSystemInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) - { - return Errno.NotImplemented; - } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/Opera.cs b/DiscImageChef.Filesystems/Opera.cs index cd0a18dc..8f825367 100644 --- a/DiscImageChef.Filesystems/Opera.cs +++ b/DiscImageChef.Filesystems/Opera.cs @@ -82,8 +82,7 @@ namespace DiscImageChef.Filesystems return Encoding.ASCII.GetString(syncBytes) == "ZZZZZ"; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { information = ""; StringBuilder superBlockMetadata = new StringBuilder(); @@ -143,37 +142,6 @@ namespace DiscImageChef.Filesystems }; } - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct OperaSuperBlock - { - /// 0x000, Record type, must be 1 - public byte record_type; - /// 0x001, 5 bytes, "ZZZZZ" - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)] public byte[] sync_bytes; - /// 0x006, Record version, must be 1 - public byte record_version; - /// 0x007, Volume flags - public byte volume_flags; - /// 0x008, 32 bytes, volume comment - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public byte[] volume_comment; - /// 0x028, 32 bytes, volume label - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public byte[] volume_label; - /// 0x048, Volume ID - public int volume_id; - /// 0x04C, Block size in bytes - public int block_size; - /// 0x050, Blocks in volume - public int block_count; - /// 0x054, Root directory ID - public int root_dirid; - /// 0x058, Root directory blocks - public int rootdir_blocks; - /// 0x05C, Root directory block size - public int rootdir_bsize; - /// 0x060, Last root directory copy - public int last_root_copy; - } - public override Errno Mount() { return Errno.NotImplemented; @@ -233,5 +201,36 @@ namespace DiscImageChef.Filesystems { return Errno.NotImplemented; } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct OperaSuperBlock + { + /// 0x000, Record type, must be 1 + public byte record_type; + /// 0x001, 5 bytes, "ZZZZZ" + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)] public byte[] sync_bytes; + /// 0x006, Record version, must be 1 + public byte record_version; + /// 0x007, Volume flags + public byte volume_flags; + /// 0x008, 32 bytes, volume comment + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public byte[] volume_comment; + /// 0x028, 32 bytes, volume label + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public byte[] volume_label; + /// 0x048, Volume ID + public int volume_id; + /// 0x04C, Block size in bytes + public int block_size; + /// 0x050, Blocks in volume + public int block_count; + /// 0x054, Root directory ID + public int root_dirid; + /// 0x058, Root directory blocks + public int rootdir_blocks; + /// 0x05C, Root directory block size + public int rootdir_bsize; + /// 0x060, Last root directory copy + public int last_root_copy; + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/PCEngine.cs b/DiscImageChef.Filesystems/PCEngine.cs index e7743bd6..ae82d25b 100644 --- a/DiscImageChef.Filesystems/PCEngine.cs +++ b/DiscImageChef.Filesystems/PCEngine.cs @@ -74,8 +74,7 @@ namespace DiscImageChef.Filesystems return Encoding.ASCII.GetString(systemDescriptor) == "PC Engine CD-ROM SYSTEM"; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { information = ""; XmlFsType = new FileSystemType diff --git a/DiscImageChef.Filesystems/PFS.cs b/DiscImageChef.Filesystems/PFS.cs index b0b7e4fc..0dda1189 100644 --- a/DiscImageChef.Filesystems/PFS.cs +++ b/DiscImageChef.Filesystems/PFS.cs @@ -42,6 +42,27 @@ namespace DiscImageChef.Filesystems { public class PFS : Filesystem { + /// + /// Identifier for AFS (PFS v1) + /// + const uint AFS_DISK = 0x41465301; + /// + /// Identifier for PFS v2 + /// + const uint PFS2_DISK = 0x50465302; + /// + /// Identifier for PFS v3 + /// + const uint PFS_DISK = 0x50465301; + /// + /// Identifier for multi-user AFS + /// + const uint MUAF_DISK = 0x6D754146; + /// + /// Identifier for multi-user PFS + /// + const uint MUPFS_DISK = 0x6D755046; + public PFS() { Name = "Professional File System"; @@ -63,128 +84,6 @@ namespace DiscImageChef.Filesystems CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1"); } - /// - /// Boot block, first 2 sectors - /// - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct BootBlock - { - /// - /// "PFS\1" disk type - /// - public uint diskType; - /// - /// Boot code, til completion - /// - public byte[] bootCode; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct RootBlock - { - /// - /// Disk type - /// - public uint diskType; - /// - /// Options - /// - public uint options; - /// - /// Current datestamp - /// - public uint datestamp; - /// - /// Volume creation day - /// - public ushort creationday; - /// - /// Volume creation minute - /// - public ushort creationminute; - /// - /// Volume creation tick - /// - public ushort creationtick; - /// - /// AmigaDOS protection bits - /// - public ushort protection; - /// - /// Volume label (Pascal string) - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public byte[] diskname; - /// - /// Last reserved block - /// - public uint lastreserved; - /// - /// First reserved block - /// - public uint firstreserved; - /// - /// Free reserved blocks - /// - public uint reservedfree; - /// - /// Size of reserved blocks in bytes - /// - public ushort reservedblocksize; - /// - /// Blocks in rootblock, including bitmap - /// - public ushort rootblockclusters; - /// - /// Free blocks - /// - public uint blocksfree; - /// - /// Blocks that must be always free - /// - public uint alwaysfree; - /// - /// Current bitmapfield number for allocation - /// - public uint rovingPointer; - /// - /// Pointer to deldir - /// - public uint delDirPtr; - /// - /// Disk size in sectors - /// - public uint diskSize; - /// - /// Rootblock extension - /// - public uint extension; - /// - /// Unused - /// - public uint unused; - } - - /// - /// Identifier for AFS (PFS v1) - /// - const uint AFS_DISK = 0x41465301; - /// - /// Identifier for PFS v2 - /// - const uint PFS2_DISK = 0x50465302; - /// - /// Identifier for PFS v3 - /// - const uint PFS_DISK = 0x50465301; - /// - /// Identifier for multi-user AFS - /// - const uint MUAF_DISK = 0x6D754146; - /// - /// Identifier for multi-user PFS - /// - const uint MUPFS_DISK = 0x6D755046; - public override bool Identify(ImagePlugin imagePlugin, Partition partition) { if(partition.Length < 3) return false; @@ -199,8 +98,7 @@ namespace DiscImageChef.Filesystems magic == MUPFS_DISK; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { byte[] rootBlockSector = imagePlugin.ReadSector(2 + partition.Start); RootBlock rootBlock = BigEndianMarshal.ByteArrayToStructureBigEndian(rootBlockSector); @@ -314,5 +212,106 @@ namespace DiscImageChef.Filesystems { return Errno.NotImplemented; } + + /// + /// Boot block, first 2 sectors + /// + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct BootBlock + { + /// + /// "PFS\1" disk type + /// + public uint diskType; + /// + /// Boot code, til completion + /// + public byte[] bootCode; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct RootBlock + { + /// + /// Disk type + /// + public uint diskType; + /// + /// Options + /// + public uint options; + /// + /// Current datestamp + /// + public uint datestamp; + /// + /// Volume creation day + /// + public ushort creationday; + /// + /// Volume creation minute + /// + public ushort creationminute; + /// + /// Volume creation tick + /// + public ushort creationtick; + /// + /// AmigaDOS protection bits + /// + public ushort protection; + /// + /// Volume label (Pascal string) + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public byte[] diskname; + /// + /// Last reserved block + /// + public uint lastreserved; + /// + /// First reserved block + /// + public uint firstreserved; + /// + /// Free reserved blocks + /// + public uint reservedfree; + /// + /// Size of reserved blocks in bytes + /// + public ushort reservedblocksize; + /// + /// Blocks in rootblock, including bitmap + /// + public ushort rootblockclusters; + /// + /// Free blocks + /// + public uint blocksfree; + /// + /// Blocks that must be always free + /// + public uint alwaysfree; + /// + /// Current bitmapfield number for allocation + /// + public uint rovingPointer; + /// + /// Pointer to deldir + /// + public uint delDirPtr; + /// + /// Disk size in sectors + /// + public uint diskSize; + /// + /// Rootblock extension + /// + public uint extension; + /// + /// Unused + /// + public uint unused; + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/ProDOS.cs b/DiscImageChef.Filesystems/ProDOS.cs index efa0861d..f6a2d525 100644 --- a/DiscImageChef.Filesystems/ProDOS.cs +++ b/DiscImageChef.Filesystems/ProDOS.cs @@ -48,15 +48,15 @@ namespace DiscImageChef.Filesystems { const byte EMPTY_STORAGE_TYPE = 0x00; /// - /// A file that occupies one block or less + /// A file that occupies one block or less /// const byte SEEDLING_FILE_TYPE = 0x01; /// - /// A file that occupies between 2 and 256 blocks + /// A file that occupies between 2 and 256 blocks /// const byte SAPLING_FILE_TYPE = 0x02; /// - /// A file that occupies between 257 and 32768 blocks + /// A file that occupies between 257 and 32768 blocks /// const byte TREE_FILE_TYPE = 0x03; const byte PASCAL_AREA_TYPE = 0x04; @@ -120,9 +120,21 @@ 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] & STORAGE_TYPE_MASK) >> 4) == ROOT_DIRECTORY_TYPE && - tmp[offset + 0x23] == ENTRY_LENGTH && tmp[offset + 0x24] == ENTRIES_PER_BLOCK)) { + foreach(int offset in new[] {0, 0x200, 0x400, 0x600, 0x800, 0xA00}.Where(offset => + BitConverter + .ToUInt16(tmp, + offset) == + 0 && + (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; @@ -157,8 +169,7 @@ namespace DiscImageChef.Filesystems return totalBlocks <= partition.End - partition.Start + 1; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { StringBuilder sbInformation = new StringBuilder(); @@ -172,9 +183,21 @@ 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] & STORAGE_TYPE_MASK) >> 4) == ROOT_DIRECTORY_TYPE && - tmp[offset + 0x23] == ENTRY_LENGTH && tmp[offset + 0x24] == ENTRIES_PER_BLOCK)) { + foreach(int offset in new[] {0, 0x200, 0x400, 0x600, 0x800, 0xA00}.Where(offset => + BitConverter + .ToUInt16(tmp, + offset) == + 0 && + (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; @@ -235,8 +258,7 @@ namespace DiscImageChef.Filesystems sbInformation.AppendLine("ProDOS uses 512 bytes/sector while devices uses 2048 bytes/sector.") .AppendLine(); - if(rootDirectoryKeyBlock.header.version != VERSION1 || - rootDirectoryKeyBlock.header.min_version != VERSION1) + 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"); @@ -363,80 +385,80 @@ namespace DiscImageChef.Filesystems } /// - /// ProDOS directory entry, decoded structure + /// ProDOS directory entry, decoded structure /// struct ProDOSEntry { /// - /// Type of file pointed by this entry - /// Offset 0x00, mask 0xF0 + /// Type of file pointed by this entry + /// Offset 0x00, mask 0xF0 /// public byte storage_type; /// - /// Length of name_length pascal string - /// Offset 0x00, mask 0x0F + /// Length of name_length pascal string + /// Offset 0x00, mask 0x0F /// public byte name_length; /// - /// Pascal string of file name - /// Offset 0x01, 15 bytes + /// Pascal string of file name + /// Offset 0x01, 15 bytes /// public string file_name; /// - /// Descriptor of internal structure of the file - /// Offset 0x10, 1 byte + /// Descriptor of internal structure of the file + /// Offset 0x10, 1 byte /// public byte file_type; /// - /// Block address of master index block for tree files. - /// Block address of index block for sapling files. - /// Block address of block for seedling files. - /// Offset 0x11, 2 bytes + /// Block address of master index block for tree files. + /// Block address of index block for sapling files. + /// Block address of block for seedling files. + /// Offset 0x11, 2 bytes /// public ushort key_pointer; /// - /// Blocks used by file or directory, including index blocks. - /// Offset 0x13, 2 bytes + /// Blocks used by file or directory, including index blocks. + /// Offset 0x13, 2 bytes /// public ushort blocks_used; /// - /// Size of file in bytes - /// Offset 0x15, 3 bytes + /// Size of file in bytes + /// Offset 0x15, 3 bytes /// public uint EOF; /// - /// File creation datetime - /// Offset 0x18, 4 bytes + /// File creation datetime + /// Offset 0x18, 4 bytes /// public DateTime creation_time; /// - /// Version of ProDOS that created this file - /// Offset 0x1C, 1 byte + /// Version of ProDOS that created this file + /// Offset 0x1C, 1 byte /// public byte version; /// - /// Minimum version of ProDOS needed to access this file - /// Offset 0x1D, 1 byte + /// Minimum version of ProDOS needed to access this file + /// Offset 0x1D, 1 byte /// public byte min_version; /// - /// File permissions - /// Offset 0x1E, 1 byte + /// File permissions + /// Offset 0x1E, 1 byte /// public byte access; /// - /// General purpose field to store additional information about file format - /// Offset 0x1F, 2 bytes + /// General purpose field to store additional information about file format + /// Offset 0x1F, 2 bytes /// public ushort aux_type; /// - /// File last modification date time - /// Offset 0x21, 4 bytes + /// File last modification date time + /// Offset 0x21, 4 bytes /// public DateTime last_mod; /// - /// Block address pointer to key block of the directory containing this entry - /// Offset 0x25, 2 bytes + /// Block address pointer to key block of the directory containing this entry + /// Offset 0x25, 2 bytes /// public ushort header_pointer; } @@ -444,71 +466,71 @@ namespace DiscImageChef.Filesystems struct ProDOSRootDirectoryHeader { /// - /// Constant 0x0F - /// Offset 0x04, mask 0xF0 + /// Constant 0x0F + /// Offset 0x04, mask 0xF0 /// public byte storage_type; /// - /// Length of volume_name pascal string - /// Offset 0x04, mask 0x0F + /// Length of volume_name pascal string + /// Offset 0x04, mask 0x0F /// public byte name_length; /// - /// The name of the volume. - /// Offset 0x05, 15 bytes + /// The name of the volume. + /// Offset 0x05, 15 bytes /// public string volume_name; /// - /// Reserved for future expansion - /// Offset 0x14, 8 bytes + /// Reserved for future expansion + /// Offset 0x14, 8 bytes /// public ulong reserved; /// - /// Creation time of the volume - /// Offset 0x1C, 4 bytes + /// Creation time of the volume + /// Offset 0x1C, 4 bytes /// public DateTime creation_time; /// - /// Version number of the volume format - /// Offset 0x20, 1 byte + /// Version number of the volume format + /// Offset 0x20, 1 byte /// public byte version; /// - /// Reserved for future use - /// Offset 0x21, 1 byte + /// Reserved for future use + /// Offset 0x21, 1 byte /// public byte min_version; /// - /// Permissions for the volume - /// Offset 0x22, 1 byte + /// Permissions for the volume + /// Offset 0x22, 1 byte /// public byte access; /// - /// Length of an entry in this directory - /// Const 0x27 - /// Offset 0x23, 1 byte + /// Length of an entry in this directory + /// Const 0x27 + /// Offset 0x23, 1 byte /// public byte entry_length; /// - /// Number of entries per block - /// Const 0x0D - /// Offset 0x24, 1 byte + /// Number of entries per block + /// Const 0x0D + /// Offset 0x24, 1 byte /// public byte entries_per_block; /// - /// Number of active files in this directory - /// Offset 0x25, 2 bytes + /// Number of active files in this directory + /// Offset 0x25, 2 bytes /// public ushort file_count; /// - /// Block address of the first block of the volume's bitmap, - /// one for every 4096 blocks or fraction - /// Offset 0x27, 2 bytes + /// Block address of the first block of the volume's bitmap, + /// one for every 4096 blocks or fraction + /// Offset 0x27, 2 bytes /// public ushort bit_map_pointer; /// - /// Total number of blocks in the volume - /// Offset 0x29, 2 bytes + /// Total number of blocks in the volume + /// Offset 0x29, 2 bytes /// public ushort total_blocks; } @@ -516,76 +538,76 @@ namespace DiscImageChef.Filesystems struct ProDOSDirectoryHeader { /// - /// Constant 0x0E - /// Offset 0x04, mask 0xF0 + /// Constant 0x0E + /// Offset 0x04, mask 0xF0 /// public byte storage_type; /// - /// Length of volume_name pascal string - /// Offset 0x04, mask 0x0F + /// Length of volume_name pascal string + /// Offset 0x04, mask 0x0F /// public byte name_length; /// - /// The name of the directory. - /// Offset 0x05, 15 bytes + /// The name of the directory. + /// Offset 0x05, 15 bytes /// public string directory_name; /// - /// Reserved for future expansion - /// Offset 0x14, 8 bytes + /// Reserved for future expansion + /// Offset 0x14, 8 bytes /// public ulong reserved; /// - /// Creation time of the volume - /// Offset 0x1C, 4 bytes + /// Creation time of the volume + /// Offset 0x1C, 4 bytes /// public DateTime creation_time; /// - /// Version number of the volume format - /// Offset 0x20, 1 byte + /// Version number of the volume format + /// Offset 0x20, 1 byte /// public byte version; /// - /// Reserved for future use - /// Offset 0x21, 1 byte + /// Reserved for future use + /// Offset 0x21, 1 byte /// public byte min_version; /// - /// Permissions for the volume - /// Offset 0x22, 1 byte + /// Permissions for the volume + /// Offset 0x22, 1 byte /// public byte access; /// - /// Length of an entry in this directory - /// Const 0x27 - /// Offset 0x23, 1 byte + /// Length of an entry in this directory + /// Const 0x27 + /// Offset 0x23, 1 byte /// public byte entry_length; /// - /// Number of entries per block - /// Const 0x0D - /// Offset 0x24, 1 byte + /// Number of entries per block + /// Const 0x0D + /// Offset 0x24, 1 byte /// public byte entries_per_block; /// - /// Number of active files in this directory - /// Offset 0x25, 2 bytes + /// Number of active files in this directory + /// Offset 0x25, 2 bytes /// public ushort file_count; /// - /// Block address of parent directory block that contains this entry - /// Offset 0x27, 2 bytes + /// Block address of parent directory block that contains this entry + /// Offset 0x27, 2 bytes /// public ushort parent_pointer; /// - /// Entry number within the block indicated in parent_pointer - /// Offset 0x29, 1 byte + /// Entry number within the block indicated in parent_pointer + /// Offset 0x29, 1 byte /// public byte parent_entry_number; /// - /// Length of the entry that holds this directory, in the parent entry - /// Const 0x27 - /// Offset 0x2A, 1 byte + /// Length of the entry that holds this directory, in the parent entry + /// Const 0x27 + /// Offset 0x2A, 1 byte /// public byte parent_entry_length; } @@ -593,23 +615,23 @@ namespace DiscImageChef.Filesystems struct ProDOSDirectoryKeyBlock { /// - /// Always 0 - /// Offset 0x00, 2 bytes + /// Always 0 + /// Offset 0x00, 2 bytes /// public ushort zero; /// - /// Pointer to next directory block, 0 if last - /// Offset 0x02, 2 bytes + /// Pointer to next directory block, 0 if last + /// Offset 0x02, 2 bytes /// public ushort next_pointer; /// - /// Directory header - /// Offset 0x04, 39 bytes + /// Directory header + /// Offset 0x04, 39 bytes /// public ProDOSDirectoryHeader header; /// - /// Directory entries - /// Offset 0x2F, 39 bytes each, 12 entries + /// Directory entries + /// Offset 0x2F, 39 bytes each, 12 entries /// public ProDOSEntry[] entries; } @@ -617,23 +639,23 @@ namespace DiscImageChef.Filesystems struct ProDOSRootDirectoryKeyBlock { /// - /// Always 0 - /// Offset 0x00, 2 bytes + /// Always 0 + /// Offset 0x00, 2 bytes /// public ushort zero; /// - /// Pointer to next directory block, 0 if last - /// Offset 0x02, 2 bytes + /// Pointer to next directory block, 0 if last + /// Offset 0x02, 2 bytes /// public ushort next_pointer; /// - /// Directory header - /// Offset 0x04, 39 bytes + /// Directory header + /// Offset 0x04, 39 bytes /// public ProDOSRootDirectoryHeader header; /// - /// Directory entries - /// Offset 0x2F, 39 bytes each, 12 entries + /// Directory entries + /// Offset 0x2F, 39 bytes each, 12 entries /// public ProDOSEntry[] entries; } @@ -641,18 +663,18 @@ namespace DiscImageChef.Filesystems struct ProDOSDirectoryBlock { /// - /// Pointer to previous directory block - /// Offset 0x00, 2 bytes + /// Pointer to previous directory block + /// Offset 0x00, 2 bytes /// public ushort zero; /// - /// Pointer to next directory block, 0 if last - /// Offset 0x02, 2 bytes + /// Pointer to next directory block, 0 if last + /// Offset 0x02, 2 bytes /// public ushort next_pointer; /// - /// Directory entries - /// Offset 0x2F, 39 bytes each, 13 entries + /// Directory entries + /// Offset 0x2F, 39 bytes each, 13 entries /// public ProDOSEntry[] entries; } @@ -660,7 +682,7 @@ namespace DiscImageChef.Filesystems struct ProDOSIndexBlock { /// - /// Up to 256 pointers to blocks, 0 to indicate the block is sparsed (non-allocated) + /// Up to 256 pointers to blocks, 0 to indicate the block is sparsed (non-allocated) /// public ushort[] block_pointer; } @@ -668,7 +690,7 @@ namespace DiscImageChef.Filesystems struct ProDOSMasterIndexBlock { /// - /// Up to 128 pointers to index blocks + /// Up to 128 pointers to index blocks /// public ushort[] index_block_pointer; } diff --git a/DiscImageChef.Filesystems/QNX4.cs b/DiscImageChef.Filesystems/QNX4.cs index b1f6216e..6ba58a22 100644 --- a/DiscImageChef.Filesystems/QNX4.cs +++ b/DiscImageChef.Filesystems/QNX4.cs @@ -43,65 +43,6 @@ namespace DiscImageChef.Filesystems { public class QNX4 : Filesystem { - struct QNX4_Extent - { - public uint block; - public uint length; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct QNX4_Inode - { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] di_fname; - public uint di_size; - public QNX4_Extent di_first_xtnt; - public uint di_xblk; - public uint di_ftime; - public uint di_mtime; - public uint di_atime; - public uint di_ctime; - public ushort di_num_xtnts; - public ushort di_mode; - public ushort di_uid; - public ushort di_gid; - public ushort di_nlink; - public uint di_zero; - public byte di_type; - public byte di_status; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct QNX4_LinkInfo - { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 48)] public byte[] dl_fname; - public uint dl_inode_blk; - public byte dl_inode_ndx; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] public byte[] dl_spare; - public byte dl_status; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct QNX4_ExtentBlock - { - public uint next_xblk; - public uint prev_xblk; - public byte num_xtnts; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] spare; - public uint num_blocks; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 60)] public QNX4_Extent[] xtnts; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] signature; - public QNX4_Extent first_xtnt; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct QNX4_Superblock - { - public QNX4_Inode rootDir; - public QNX4_Inode inode; - public QNX4_Inode boot; - public QNX4_Inode altBoot; - } - readonly byte[] QNX4_RootDir_Fname = {0x2F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; @@ -159,8 +100,7 @@ namespace DiscImageChef.Filesystems return true; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { information = ""; byte[] sector = imagePlugin.ReadSector(partition.Start + 1); @@ -321,5 +261,64 @@ namespace DiscImageChef.Filesystems { return Errno.NotImplemented; } + + struct QNX4_Extent + { + public uint block; + public uint length; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct QNX4_Inode + { + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] di_fname; + public uint di_size; + public QNX4_Extent di_first_xtnt; + public uint di_xblk; + public uint di_ftime; + public uint di_mtime; + public uint di_atime; + public uint di_ctime; + public ushort di_num_xtnts; + public ushort di_mode; + public ushort di_uid; + public ushort di_gid; + public ushort di_nlink; + public uint di_zero; + public byte di_type; + public byte di_status; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct QNX4_LinkInfo + { + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 48)] public byte[] dl_fname; + public uint dl_inode_blk; + public byte dl_inode_ndx; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] public byte[] dl_spare; + public byte dl_status; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct QNX4_ExtentBlock + { + public uint next_xblk; + public uint prev_xblk; + public byte num_xtnts; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] spare; + public uint num_blocks; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 60)] public QNX4_Extent[] xtnts; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] signature; + public QNX4_Extent first_xtnt; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct QNX4_Superblock + { + public QNX4_Inode rootDir; + public QNX4_Inode inode; + public QNX4_Inode boot; + public QNX4_Inode altBoot; + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/QNX6.cs b/DiscImageChef.Filesystems/QNX6.cs index e889f110..9cc25978 100644 --- a/DiscImageChef.Filesystems/QNX6.cs +++ b/DiscImageChef.Filesystems/QNX6.cs @@ -42,60 +42,6 @@ namespace DiscImageChef.Filesystems { public class QNX6 : Filesystem { - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct QNX6_RootNode - { - public ulong size; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public uint[] pointers; - public byte levels; - public byte mode; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] public byte[] spare; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct QNX6_SuperBlock - { - public uint magic; - public uint checksum; - public ulong serial; - public uint ctime; - public uint atime; - public uint flags; - public ushort version1; - public ushort version2; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] volumeid; - public uint blockSize; - public uint numInodes; - public uint freeInodes; - public uint numBlocks; - public uint freeBlocks; - public uint allocationGroup; - public QNX6_RootNode inode; - public QNX6_RootNode bitmap; - public QNX6_RootNode longfile; - public QNX6_RootNode unknown; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct QNX6_AudiSuperBlock - { - public uint magic; - public uint checksum; - public ulong serial; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] public byte[] spare1; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] public byte[] id; - public uint blockSize; - public uint numInodes; - public uint freeInodes; - public uint numBlocks; - public uint freeBlocks; - public uint spare2; - public QNX6_RootNode inode; - public QNX6_RootNode bitmap; - public QNX6_RootNode longfile; - public QNX6_RootNode unknown; - } - const uint QNX6_SUPER_BLOCK_SIZE = 0x1000; const uint QNX6_BOOT_BLOCKS_SIZE = 0x2000; const uint QNX6_MAGIC = 0x68191122; @@ -147,8 +93,7 @@ namespace DiscImageChef.Filesystems return qnxSb.magic == QNX6_MAGIC || audiSb.magic == QNX6_MAGIC; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { information = ""; StringBuilder sb = new StringBuilder(); @@ -297,5 +242,59 @@ namespace DiscImageChef.Filesystems { return Errno.NotImplemented; } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct QNX6_RootNode + { + public ulong size; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public uint[] pointers; + public byte levels; + public byte mode; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] public byte[] spare; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct QNX6_SuperBlock + { + public uint magic; + public uint checksum; + public ulong serial; + public uint ctime; + public uint atime; + public uint flags; + public ushort version1; + public ushort version2; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] volumeid; + public uint blockSize; + public uint numInodes; + public uint freeInodes; + public uint numBlocks; + public uint freeBlocks; + public uint allocationGroup; + public QNX6_RootNode inode; + public QNX6_RootNode bitmap; + public QNX6_RootNode longfile; + public QNX6_RootNode unknown; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct QNX6_AudiSuperBlock + { + public uint magic; + public uint checksum; + public ulong serial; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] public byte[] spare1; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] public byte[] id; + public uint blockSize; + public uint numInodes; + public uint freeInodes; + public uint numBlocks; + public uint freeBlocks; + public uint spare2; + public QNX6_RootNode inode; + public QNX6_RootNode bitmap; + public QNX6_RootNode longfile; + public QNX6_RootNode unknown; + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/RBF.cs b/DiscImageChef.Filesystems/RBF.cs index 1e667499..3eb0d02b 100644 --- a/DiscImageChef.Filesystems/RBF.cs +++ b/DiscImageChef.Filesystems/RBF.cs @@ -43,111 +43,6 @@ namespace DiscImageChef.Filesystems { public class RBF : Filesystem { - /// - /// Identification sector. Wherever the sector this resides on, becomes LSN 0. - /// - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct RBF_IdSector - { - /// Sectors on disk - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] dd_tot; - /// Tracks - public byte dd_tks; - /// Bytes in allocation map - public ushort dd_map; - /// Sectors per cluster - public ushort dd_bit; - /// LSN of root directory - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] dd_dir; - /// Owner ID - public ushort dd_own; - /// Attributes - public byte dd_att; - /// Disk ID - public ushort dd_dsk; - /// Format byte - public byte dd_fmt; - /// Sectors per track - public ushort dd_spt; - /// Reserved - public ushort dd_res; - /// LSN of boot file - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] dd_bt; - /// Size of boot file - public ushort dd_bsz; - /// Creation date - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)] public byte[] dd_dat; - /// Volume name - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public byte[] dd_nam; - /// Path options - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public byte[] dd_opt; - /// Reserved - public byte reserved; - /// Magic number - public uint dd_sync; - /// LSN of allocation map - public uint dd_maplsn; - /// Size of an LSN - public ushort dd_lsnsize; - /// Version ID - public ushort dd_versid; - } - - /// - /// Identification sector. Wherever the sector this resides on, becomes LSN 0. - /// Introduced on OS-9000, this can be big or little endian. - /// - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct RBF_NewIdSector - { - /// Magic number - public uint rid_sync; - /// Disk ID - public uint rid_diskid; - /// Sectors on disk - public uint rid_totblocks; - /// Cylinders - public ushort rid_cylinders; - /// Sectors in cylinder 0 - public ushort rid_cyl0size; - /// Sectors per cylinder - public ushort rid_cylsize; - /// Heads - public ushort rid_heads; - /// Bytes per sector - public ushort rid_blocksize; - /// Disk format - public ushort rid_format; - /// Flags - public ushort rid_flags; - /// Padding - public ushort rid_unused1; - /// Sector of allocation bitmap - public uint rid_bitmap; - /// Sector of debugger FD - public uint rid_firstboot; - /// Sector of bootfile FD - public uint rid_bootfile; - /// Sector of root directory FD - public uint rid_rootdir; - /// Group owner of media - public ushort rid_group; - /// Owner of media - public ushort rid_owner; - /// Creation time - public uint rid_ctime; - /// Last write time for this structure - public uint rid_mtime; - /// Volume name - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public byte[] rid_name; - /// Endian flag - public byte rid_endflag; - /// Padding - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] rid_unused2; - /// Parity - public uint rid_parity; - } - /// Magic number for OS-9. Same for OS-9000? const uint RBF_SYNC = 0x4372757A; const uint RBF_CNYS = 0x7A757243; @@ -206,8 +101,7 @@ namespace DiscImageChef.Filesystems return false; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { information = ""; if(imagePlugin.GetSectorSize() < 256) return; @@ -403,5 +297,110 @@ namespace DiscImageChef.Filesystems { return Errno.NotImplemented; } + + /// + /// Identification sector. Wherever the sector this resides on, becomes LSN 0. + /// + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct RBF_IdSector + { + /// Sectors on disk + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] dd_tot; + /// Tracks + public byte dd_tks; + /// Bytes in allocation map + public ushort dd_map; + /// Sectors per cluster + public ushort dd_bit; + /// LSN of root directory + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] dd_dir; + /// Owner ID + public ushort dd_own; + /// Attributes + public byte dd_att; + /// Disk ID + public ushort dd_dsk; + /// Format byte + public byte dd_fmt; + /// Sectors per track + public ushort dd_spt; + /// Reserved + public ushort dd_res; + /// LSN of boot file + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] dd_bt; + /// Size of boot file + public ushort dd_bsz; + /// Creation date + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)] public byte[] dd_dat; + /// Volume name + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public byte[] dd_nam; + /// Path options + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public byte[] dd_opt; + /// Reserved + public byte reserved; + /// Magic number + public uint dd_sync; + /// LSN of allocation map + public uint dd_maplsn; + /// Size of an LSN + public ushort dd_lsnsize; + /// Version ID + public ushort dd_versid; + } + + /// + /// Identification sector. Wherever the sector this resides on, becomes LSN 0. + /// Introduced on OS-9000, this can be big or little endian. + /// + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct RBF_NewIdSector + { + /// Magic number + public uint rid_sync; + /// Disk ID + public uint rid_diskid; + /// Sectors on disk + public uint rid_totblocks; + /// Cylinders + public ushort rid_cylinders; + /// Sectors in cylinder 0 + public ushort rid_cyl0size; + /// Sectors per cylinder + public ushort rid_cylsize; + /// Heads + public ushort rid_heads; + /// Bytes per sector + public ushort rid_blocksize; + /// Disk format + public ushort rid_format; + /// Flags + public ushort rid_flags; + /// Padding + public ushort rid_unused1; + /// Sector of allocation bitmap + public uint rid_bitmap; + /// Sector of debugger FD + public uint rid_firstboot; + /// Sector of bootfile FD + public uint rid_bootfile; + /// Sector of root directory FD + public uint rid_rootdir; + /// Group owner of media + public ushort rid_group; + /// Owner of media + public ushort rid_owner; + /// Creation time + public uint rid_ctime; + /// Last write time for this structure + public uint rid_mtime; + /// Volume name + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public byte[] rid_name; + /// Endian flag + public byte rid_endflag; + /// Padding + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] rid_unused2; + /// Parity + public uint rid_parity; + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/RT11.cs b/DiscImageChef.Filesystems/RT11.cs index 6369770a..c5fe8432 100644 --- a/DiscImageChef.Filesystems/RT11.cs +++ b/DiscImageChef.Filesystems/RT11.cs @@ -80,8 +80,7 @@ namespace DiscImageChef.Filesystems return magic == "DECRT11A "; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { information = ""; @@ -90,7 +89,8 @@ namespace DiscImageChef.Filesystems byte[] hbSector = imagePlugin.ReadSector(1 + partition.Start); GCHandle handle = GCHandle.Alloc(hbSector, GCHandleType.Pinned); - RT11HomeBlock homeblock = (RT11HomeBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(RT11HomeBlock)); + RT11HomeBlock homeblock = + (RT11HomeBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(RT11HomeBlock)); handle.Free(); /* TODO: Is this correct? @@ -130,42 +130,6 @@ namespace DiscImageChef.Filesystems information = sb.ToString(); } - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct RT11HomeBlock - { - /// Bad block replacement table - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 130)] public byte[] badBlockTable; - /// Unused - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public byte[] unused; - /// INITIALIZE/RESTORE data area - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 38)] public byte[] initArea; - /// BUP information area - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 18)] public byte[] bupInformation; - /// Empty - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 260)] public byte[] empty; - /// Reserved - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public byte[] reserved1; - /// Reserved - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public byte[] reserved2; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 14)] public byte[] empty2; - /// Cluster size - public ushort cluster; - /// Block of the first directory segment - public ushort rootBlock; - /// "V3A" in Radix-50 - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public byte[] systemVersion; - /// Name of the volume, 12 bytes - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] public byte[] volname; - /// Name of the volume owner, 12 bytes - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] public byte[] ownername; - /// RT11 defines it as "DECRT11A ", 12 bytes - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] public byte[] format; - /// Unused - public ushort unused2; - /// Checksum of preceding 255 words (16 bit units) - public ushort checksum; - } - public override Errno Mount() { return Errno.NotImplemented; @@ -225,5 +189,41 @@ namespace DiscImageChef.Filesystems { return Errno.NotImplemented; } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct RT11HomeBlock + { + /// Bad block replacement table + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 130)] public byte[] badBlockTable; + /// Unused + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public byte[] unused; + /// INITIALIZE/RESTORE data area + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 38)] public byte[] initArea; + /// BUP information area + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 18)] public byte[] bupInformation; + /// Empty + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 260)] public byte[] empty; + /// Reserved + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public byte[] reserved1; + /// Reserved + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public byte[] reserved2; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 14)] public byte[] empty2; + /// Cluster size + public ushort cluster; + /// Block of the first directory segment + public ushort rootBlock; + /// "V3A" in Radix-50 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public byte[] systemVersion; + /// Name of the volume, 12 bytes + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] public byte[] volname; + /// Name of the volume owner, 12 bytes + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] public byte[] ownername; + /// RT11 defines it as "DECRT11A ", 12 bytes + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] public byte[] format; + /// Unused + public ushort unused2; + /// Checksum of preceding 255 words (16 bit units) + public ushort checksum; + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/Reiser.cs b/DiscImageChef.Filesystems/Reiser.cs index 62f8db48..28c171ee 100644 --- a/DiscImageChef.Filesystems/Reiser.cs +++ b/DiscImageChef.Filesystems/Reiser.cs @@ -43,52 +43,11 @@ namespace DiscImageChef.Filesystems { public class Reiser : Filesystem { - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct ReiserJournalParams - { - public uint journal_1stblock; - public uint journal_dev; - public uint journal_size; - public uint journal_trans_max; - public uint journal_magic; - public uint journal_max_batch; - public uint journal_max_commit_age; - public uint journal_max_trans_age; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct Reiser_Superblock - { - public uint block_count; - public uint free_blocks; - public uint root_block; - public ReiserJournalParams journal; - public ushort blocksize; - public ushort oid_maxsize; - public ushort oid_cursize; - public ushort umount_state; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] public byte[] magic; - public ushort fs_state; - public uint hash_function_code; - public ushort tree_height; - public ushort bmap_nr; - public ushort version; - public ushort reserved_for_journal; - public uint inode_generation; - public uint flags; - public Guid uuid; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] label; - public ushort mnt_count; - public ushort max_mnt_count; - public uint last_check; - public uint check_interval; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 76)] public byte[] unused; - } + const uint REISER_SUPER_OFFSET = 0x10000; 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_SUPER_OFFSET = 0x10000; public Reiser() { @@ -137,8 +96,7 @@ namespace DiscImageChef.Filesystems ReiserJr_Magic.SequenceEqual(reiserSb.magic); } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { information = ""; if(imagePlugin.GetSectorSize() < 512) return; @@ -256,5 +214,47 @@ namespace DiscImageChef.Filesystems { return Errno.NotImplemented; } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct ReiserJournalParams + { + public uint journal_1stblock; + public uint journal_dev; + public uint journal_size; + public uint journal_trans_max; + public uint journal_magic; + public uint journal_max_batch; + public uint journal_max_commit_age; + public uint journal_max_trans_age; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct Reiser_Superblock + { + public uint block_count; + public uint free_blocks; + public uint root_block; + public ReiserJournalParams journal; + public ushort blocksize; + public ushort oid_maxsize; + public ushort oid_cursize; + public ushort umount_state; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] public byte[] magic; + public ushort fs_state; + public uint hash_function_code; + public ushort tree_height; + public ushort bmap_nr; + public ushort version; + public ushort reserved_for_journal; + public uint inode_generation; + public uint flags; + public Guid uuid; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] label; + public ushort mnt_count; + public ushort max_mnt_count; + public uint last_check; + public uint check_interval; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 76)] public byte[] unused; + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/Reiser4.cs b/DiscImageChef.Filesystems/Reiser4.cs index 4c8f483d..202de725 100644 --- a/DiscImageChef.Filesystems/Reiser4.cs +++ b/DiscImageChef.Filesystems/Reiser4.cs @@ -43,19 +43,10 @@ namespace DiscImageChef.Filesystems { public class Reiser4 : Filesystem { - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct Reiser4_Superblock - { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] magic; - public ushort diskformat; - public ushort blocksize; - public Guid uuid; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] label; - } + const uint REISER4_SUPER_OFFSET = 0x10000; readonly byte[] Reiser4_Magic = {0x52, 0x65, 0x49, 0x73, 0x45, 0x72, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - const uint REISER4_SUPER_OFFSET = 0x10000; public Reiser4() { @@ -103,8 +94,7 @@ namespace DiscImageChef.Filesystems return Reiser4_Magic.SequenceEqual(reiserSb.magic); } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { information = ""; if(imagePlugin.GetSectorSize() < 512) return; @@ -206,5 +196,15 @@ namespace DiscImageChef.Filesystems { return Errno.NotImplemented; } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct Reiser4_Superblock + { + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] magic; + public ushort diskformat; + public ushort blocksize; + public Guid uuid; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] label; + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/SFS.cs b/DiscImageChef.Filesystems/SFS.cs index 48f8ecb6..5010b687 100644 --- a/DiscImageChef.Filesystems/SFS.cs +++ b/DiscImageChef.Filesystems/SFS.cs @@ -42,6 +42,11 @@ namespace DiscImageChef.Filesystems { public class SFS : Filesystem { + /// Identifier for SFS v1 + const uint SFS_MAGIC = 0x53465300; + /// Identifier for SFS v2 + const uint SFS2_MAGIC = 0x53465302; + public SFS() { Name = "SmartFileSystem"; @@ -63,45 +68,6 @@ namespace DiscImageChef.Filesystems CurrentEncoding = encoding ?? Encoding.GetEncoding("iso-8859-1"); } - [Flags] - enum SFSFlags : byte - { - RecyledFolder = 64, - CaseSensitive = 128 - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct RootBlock - { - public uint blockId; - public uint blockChecksum; - public uint blockSelfPointer; - public ushort version; - public ushort sequence; - public uint datecreated; - public SFSFlags bits; - public byte padding1; - public ushort padding2; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public uint[] reserved1; - public ulong firstbyte; - public ulong lastbyte; - public uint totalblocks; - public uint blocksize; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public uint[] reserved2; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public uint[] reserved3; - public uint bitmapbase; - public uint adminspacecontainer; - public uint rootobjectcontainer; - public uint extentbnoderoot; - public uint objectnoderoot; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public uint[] reserved4; - } - - /// Identifier for SFS v1 - const uint SFS_MAGIC = 0x53465300; - /// Identifier for SFS v2 - const uint SFS2_MAGIC = 0x53465302; - public override bool Identify(ImagePlugin imagePlugin, Partition partition) { if(partition.Start >= partition.End) return false; @@ -115,8 +81,7 @@ namespace DiscImageChef.Filesystems return magic == SFS_MAGIC || magic == SFS2_MAGIC; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { byte[] rootBlockSector = imagePlugin.ReadSector(partition.Start); RootBlock rootBlock = BigEndianMarshal.ByteArrayToStructureBigEndian(rootBlockSector); @@ -217,5 +182,39 @@ namespace DiscImageChef.Filesystems { return Errno.NotImplemented; } + + [Flags] + enum SFSFlags : byte + { + RecyledFolder = 64, + CaseSensitive = 128 + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct RootBlock + { + public uint blockId; + public uint blockChecksum; + public uint blockSelfPointer; + public ushort version; + public ushort sequence; + public uint datecreated; + public SFSFlags bits; + public byte padding1; + public ushort padding2; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public uint[] reserved1; + public ulong firstbyte; + public ulong lastbyte; + public uint totalblocks; + public uint blocksize; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public uint[] reserved2; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public uint[] reserved3; + public uint bitmapbase; + public uint adminspacecontainer; + public uint rootobjectcontainer; + public uint extentbnoderoot; + public uint objectnoderoot; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public uint[] reserved4; + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/SolarFS.cs b/DiscImageChef.Filesystems/SolarFS.cs index 53014318..ab6b535b 100644 --- a/DiscImageChef.Filesystems/SolarFS.cs +++ b/DiscImageChef.Filesystems/SolarFS.cs @@ -81,15 +81,13 @@ namespace DiscImageChef.Filesystems return signature == 0x29 && fsType == "SOL_FS "; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { information = ""; StringBuilder sb = new StringBuilder(); byte[] bpbSector = imagePlugin.ReadSector(0 + partition.Start); - SolarOSParameterBlock bpb = new SolarOSParameterBlock { bps = BitConverter.ToUInt16(bpbSector, 0x0B), @@ -174,42 +172,6 @@ namespace DiscImageChef.Filesystems information = sb.ToString(); } - struct SolarOSParameterBlock - { - /// 0x00, x86 jump (3 bytes), jumps to 0x60 - public byte[] x86_jump; - /// 0x03, 8 bytes, "SOLAR_OS" - public string OEMName; - /// 0x0B, Bytes per sector - public ushort bps; - /// 0x0D, unknown, 0x01 - public byte unk1; - /// 0x0E, unknown, 0x0201 - public ushort unk2; - /// 0x10, Number of entries on root directory ? (no root directory found) - public ushort root_ent; - /// 0x12, Sectors in volume - public ushort sectors; - /// 0x14, Media descriptor - public byte media; - /// 0x15, Sectors per FAT ? (no FAT found) - public ushort spfat; - /// 0x17, Sectors per track - public ushort sptrk; - /// 0x19, Heads - public ushort heads; - /// 0x1B, unknown, 10 bytes, zero-filled - public byte[] unk3; - /// 0x25, 0x29 - public byte signature; - /// 0x26, unknown, zero-filled - public uint unk4; - /// 0x2A, 11 bytes, volume name, space-padded - public string vol_name; - /// 0x35, 8 bytes, "SOL_FS " - public string fs_type; - } - public override Errno Mount() { return Errno.NotImplemented; @@ -269,5 +231,41 @@ namespace DiscImageChef.Filesystems { return Errno.NotImplemented; } + + struct SolarOSParameterBlock + { + /// 0x00, x86 jump (3 bytes), jumps to 0x60 + public byte[] x86_jump; + /// 0x03, 8 bytes, "SOLAR_OS" + public string OEMName; + /// 0x0B, Bytes per sector + public ushort bps; + /// 0x0D, unknown, 0x01 + public byte unk1; + /// 0x0E, unknown, 0x0201 + public ushort unk2; + /// 0x10, Number of entries on root directory ? (no root directory found) + public ushort root_ent; + /// 0x12, Sectors in volume + public ushort sectors; + /// 0x14, Media descriptor + public byte media; + /// 0x15, Sectors per FAT ? (no FAT found) + public ushort spfat; + /// 0x17, Sectors per track + public ushort sptrk; + /// 0x19, Heads + public ushort heads; + /// 0x1B, unknown, 10 bytes, zero-filled + public byte[] unk3; + /// 0x25, 0x29 + public byte signature; + /// 0x26, unknown, zero-filled + public uint unk4; + /// 0x2A, 11 bytes, volume name, space-padded + public string vol_name; + /// 0x35, 8 bytes, "SOL_FS " + public string fs_type; + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/Squash.cs b/DiscImageChef.Filesystems/Squash.cs index ceb7a2ee..3e598751 100644 --- a/DiscImageChef.Filesystems/Squash.cs +++ b/DiscImageChef.Filesystems/Squash.cs @@ -42,6 +42,12 @@ namespace DiscImageChef.Filesystems { public class Squash : Filesystem { + /// + /// Identifier for Squash + /// + const uint SQUASH_MAGIC = 0x73717368; + const uint SQUASH_CIGAM = 0x68737173; + public Squash() { Name = "Squash filesystem"; @@ -63,46 +69,6 @@ namespace DiscImageChef.Filesystems CurrentEncoding = encoding ?? Encoding.UTF8; } - enum SquashCompression : ushort - { - Zlib = 1, - Lzma = 2, - Lzo = 3, - Xz = 4, - Lz4 = 5, - Zstd = 6 - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct SquashSuperBlock - { - public uint magic; - public uint inodes; - public uint mkfs_time; - public uint block_size; - public uint fragments; - public ushort compression; - public ushort block_log; - public ushort flags; - public ushort no_ids; - public ushort s_major; - public ushort s_minor; - public ulong root_inode; - public ulong bytes_used; - public ulong id_table_start; - public ulong xattr_id_table_start; - public ulong inode_table_start; - public ulong directory_table_start; - public ulong fragment_table_start; - public ulong lookup_table_start; - } - - /// - /// Identifier for Squash - /// - const uint SQUASH_MAGIC = 0x73717368; - const uint SQUASH_CIGAM = 0x68737173; - public override bool Identify(ImagePlugin imagePlugin, Partition partition) { if(partition.Start >= partition.End) return false; @@ -114,8 +80,7 @@ namespace DiscImageChef.Filesystems return magic == SQUASH_MAGIC || magic == SQUASH_CIGAM; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { byte[] sector = imagePlugin.ReadSector(partition.Start); uint magic = BitConverter.ToUInt32(sector, 0x00); @@ -123,7 +88,8 @@ namespace DiscImageChef.Filesystems SquashSuperBlock sqSb = new SquashSuperBlock(); bool littleEndian = true; - switch(magic) { + switch(magic) + { case SQUASH_MAGIC: IntPtr sqSbPtr = Marshal.AllocHGlobal(Marshal.SizeOf(sqSb)); Marshal.Copy(sector, 0, sqSbPtr, Marshal.SizeOf(sqSb)); @@ -248,5 +214,39 @@ namespace DiscImageChef.Filesystems { return Errno.NotImplemented; } + + enum SquashCompression : ushort + { + Zlib = 1, + Lzma = 2, + Lzo = 3, + Xz = 4, + Lz4 = 5, + Zstd = 6 + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct SquashSuperBlock + { + public uint magic; + public uint inodes; + public uint mkfs_time; + public uint block_size; + public uint fragments; + public ushort compression; + public ushort block_log; + public ushort flags; + public ushort no_ids; + public ushort s_major; + public ushort s_minor; + public ulong root_inode; + public ulong bytes_used; + public ulong id_table_start; + public ulong xattr_id_table_start; + public ulong inode_table_start; + public ulong directory_table_start; + public ulong fragment_table_start; + public ulong lookup_table_start; + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/Structs.cs b/DiscImageChef.Filesystems/Structs.cs index 1527134a..57f20be2 100644 --- a/DiscImageChef.Filesystems/Structs.cs +++ b/DiscImageChef.Filesystems/Structs.cs @@ -37,7 +37,7 @@ using System.Runtime.InteropServices; namespace DiscImageChef.Filesystems { /// - /// File attributes. + /// File attributes. /// [Flags] public enum FileAttributes : ulong @@ -143,12 +143,31 @@ namespace DiscImageChef.Filesystems } /// - /// Information about a file entry + /// Information about a file entry /// public class FileEntryInfo { /// File attributes public FileAttributes Attributes; + /// File length in blocks + public long Blocks; + /// File block size in bytes + public long BlockSize; + /// If file points to a device, device number + public ulong DeviceNo; + /// POSIX group ID + public ulong GID; + + /// inode number for this file + public ulong Inode; + /// File length in bytes + public long Length; + /// Number of hard links pointing to this file + public ulong Links; + /// POSIX permissions/mode for this file + public uint Mode; + /// POSIX owner ID + public ulong UID; /// File creation date in UTC public DateTime CreationTimeUtc { get; set; } @@ -164,77 +183,59 @@ namespace DiscImageChef.Filesystems /// File creation date public DateTime CreationTime { - get { return CreationTimeUtc.ToLocalTime(); } - set { CreationTimeUtc = value.ToUniversalTime(); } + get => CreationTimeUtc.ToLocalTime(); + set => CreationTimeUtc = value.ToUniversalTime(); } /// File last access date public DateTime AccessTime { - get { return AccessTimeUtc.ToLocalTime(); } - set { AccessTimeUtc = value.ToUniversalTime(); } + get => AccessTimeUtc.ToLocalTime(); + set => AccessTimeUtc = value.ToUniversalTime(); } /// File attributes change date public DateTime StatusChangeTime { - get { return StatusChangeTimeUtc.ToLocalTime(); } - set { StatusChangeTimeUtc = value.ToUniversalTime(); } + get => StatusChangeTimeUtc.ToLocalTime(); + set => StatusChangeTimeUtc = value.ToUniversalTime(); } /// File last backup date public DateTime BackupTime { - get { return BackupTimeUtc.ToLocalTime(); } - set { BackupTimeUtc = value.ToUniversalTime(); } + get => BackupTimeUtc.ToLocalTime(); + set => BackupTimeUtc = value.ToUniversalTime(); } /// File last modification date public DateTime LastWriteTime { - get { return LastWriteTimeUtc.ToLocalTime(); } - set { LastWriteTimeUtc = value.ToUniversalTime(); } + get => LastWriteTimeUtc.ToLocalTime(); + set => LastWriteTimeUtc = value.ToUniversalTime(); } - - /// inode number for this file - public ulong Inode; - /// POSIX permissions/mode for this file - public uint Mode; - /// Number of hard links pointing to this file - public ulong Links; - /// POSIX owner ID - public ulong UID; - /// POSIX group ID - public ulong GID; - /// If file points to a device, device number - public ulong DeviceNo; - /// File length in bytes - public long Length; - /// File block size in bytes - public long BlockSize; - /// File length in blocks - public long Blocks; } public class FileSystemInfo { + /// Blocks for this filesystem + public long Blocks; + /// Maximum length of filenames on this filesystem + public ushort FilenameLength; + /// Files on this filesystem + public ulong Files; + /// Blocks free on this filesystem + public long FreeBlocks; + /// Free inodes on this filesystem + public ulong FreeFiles; + /// Filesystem ID + public FileSystemId Id; + /// ID of plugin for this file + public Guid PluginId; + + /// Filesystem type + public string Type; + public FileSystemInfo() { Id = new FileSystemId(); } - - /// Filesystem type - public string Type; - /// ID of plugin for this file - public Guid PluginId; - /// Blocks for this filesystem - public long Blocks; - /// Blocks free on this filesystem - public long FreeBlocks; - /// Files on this filesystem - public ulong Files; - /// Free inodes on this filesystem - public ulong FreeFiles; - /// Maximum length of filenames on this filesystem - public ushort FilenameLength; - /// Filesystem ID - public FileSystemId Id; } [StructLayout(LayoutKind.Explicit)] @@ -250,7 +251,7 @@ namespace DiscImageChef.Filesystems } /// - /// Errors + /// Errors /// public enum Errno { diff --git a/DiscImageChef.Filesystems/SysV.cs b/DiscImageChef.Filesystems/SysV.cs index 98b2ac7c..f088e358 100644 --- a/DiscImageChef.Filesystems/SysV.cs +++ b/DiscImageChef.Filesystems/SysV.cs @@ -110,7 +110,10 @@ namespace DiscImageChef.Filesystems spc }; - foreach(byte[] sb_sector in locations.TakeWhile(i => i + sb_size_in_sectors < (int)imagePlugin.ImageInfo.Sectors).Select(i => imagePlugin.ReadSectors((ulong)i + partition.Start, sb_size_in_sectors))) { + foreach(byte[] sb_sector in locations + .TakeWhile(i => i + sb_size_in_sectors < (int)imagePlugin.ImageInfo.Sectors) + .Select(i => imagePlugin.ReadSectors((ulong)i + partition.Start, sb_size_in_sectors))) + { uint magic = BitConverter.ToUInt32(sb_sector, 0x3F8); if(magic == XENIX_MAGIC || magic == XENIX_CIGAM || magic == SYSV_MAGIC || magic == SYSV_CIGAM) @@ -156,15 +159,13 @@ namespace DiscImageChef.Filesystems if(s_fsize >= V7_MAXSIZE || s_nfree >= V7_NICFREE || s_ninode >= V7_NICINOD) continue; if(s_fsize * 1024 == (partition.End - partition.Start) * imagePlugin.GetSectorSize() || - s_fsize * 512 == (partition.End - partition.Start) * imagePlugin.GetSectorSize()) - return true; + s_fsize * 512 == (partition.End - partition.Start) * imagePlugin.GetSectorSize()) return true; } return false; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { information = ""; @@ -680,6 +681,66 @@ namespace DiscImageChef.Filesystems BigEndianBitConverter.IsLittleEndian = false; // Return to default (bigendian) } + public override Errno Mount() + { + return Errno.NotImplemented; + } + + public override Errno Mount(bool debug) + { + return Errno.NotImplemented; + } + + public override Errno Unmount() + { + return Errno.NotImplemented; + } + + public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + { + return Errno.NotImplemented; + } + + public override Errno GetAttributes(string path, ref FileAttributes attributes) + { + return Errno.NotImplemented; + } + + public override Errno ListXAttr(string path, ref List xattrs) + { + return Errno.NotImplemented; + } + + public override Errno GetXattr(string path, string xattr, ref byte[] buf) + { + return Errno.NotImplemented; + } + + public override Errno Read(string path, long offset, long size, ref byte[] buf) + { + return Errno.NotImplemented; + } + + public override Errno ReadDir(string path, ref List contents) + { + return Errno.NotImplemented; + } + + public override Errno StatFs(ref FileSystemInfo stat) + { + return Errno.NotImplemented; + } + + public override Errno Stat(string path, ref FileEntryInfo stat) + { + return Errno.NotImplemented; + } + + public override Errno ReadLink(string path, ref string dest) + { + return Errno.NotImplemented; + } + // Old XENIX use different offsets struct XenixSuperBlock { @@ -926,65 +987,5 @@ namespace DiscImageChef.Filesystems /// 0x1F4, zero-filled public uint s_unique; } - - public override Errno Mount() - { - return Errno.NotImplemented; - } - - public override Errno Mount(bool debug) - { - return Errno.NotImplemented; - } - - public override Errno Unmount() - { - return Errno.NotImplemented; - } - - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) - { - return Errno.NotImplemented; - } - - public override Errno GetAttributes(string path, ref FileAttributes attributes) - { - return Errno.NotImplemented; - } - - public override Errno ListXAttr(string path, ref List xattrs) - { - return Errno.NotImplemented; - } - - public override Errno GetXattr(string path, string xattr, ref byte[] buf) - { - return Errno.NotImplemented; - } - - public override Errno Read(string path, long offset, long size, ref byte[] buf) - { - return Errno.NotImplemented; - } - - public override Errno ReadDir(string path, ref List contents) - { - return Errno.NotImplemented; - } - - public override Errno StatFs(ref FileSystemInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) - { - return Errno.NotImplemented; - } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/UCSDPascal/File.cs b/DiscImageChef.Filesystems/UCSDPascal/File.cs index 5220e1e2..7d9af216 100644 --- a/DiscImageChef.Filesystems/UCSDPascal/File.cs +++ b/DiscImageChef.Filesystems/UCSDPascal/File.cs @@ -159,8 +159,14 @@ namespace DiscImageChef.Filesystems.UCSDPascal { entry = new PascalFileEntry(); - foreach(PascalFileEntry ent in fileEntries.Where(ent => string.Compare(path, StringHandlers.PascalToString(ent.filename, CurrentEncoding), - StringComparison.InvariantCultureIgnoreCase) == 0)) { + foreach(PascalFileEntry ent in fileEntries.Where(ent => + string.Compare(path, + StringHandlers + .PascalToString(ent.filename, + CurrentEncoding), + StringComparison + .InvariantCultureIgnoreCase) == 0)) + { entry = ent; return Errno.NoError; } diff --git a/DiscImageChef.Filesystems/UCSDPascal/Info.cs b/DiscImageChef.Filesystems/UCSDPascal/Info.cs index 9c8171fc..ce91db0a 100644 --- a/DiscImageChef.Filesystems/UCSDPascal/Info.cs +++ b/DiscImageChef.Filesystems/UCSDPascal/Info.cs @@ -80,13 +80,10 @@ namespace DiscImageChef.Filesystems.UCSDPascal if(volEntry.blocks < 0 || (ulong)volEntry.blocks != imagePlugin.GetSectors()) return false; // There can be not less than zero files - if(volEntry.files < 0) return false; - - return true; + return volEntry.files >= 0; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { StringBuilder sbInformation = new StringBuilder(); information = ""; diff --git a/DiscImageChef.Filesystems/UCSDPascal/Structs.cs b/DiscImageChef.Filesystems/UCSDPascal/Structs.cs index 788d58b5..50390e13 100644 --- a/DiscImageChef.Filesystems/UCSDPascal/Structs.cs +++ b/DiscImageChef.Filesystems/UCSDPascal/Structs.cs @@ -53,7 +53,7 @@ namespace DiscImageChef.Filesystems.UCSDPascal public short dummy; /// 0x14, last booted public short lastBoot; - /// 0x16, tail to make record same size as + /// 0x16, tail to make record same size as public int tail; } diff --git a/DiscImageChef.Filesystems/UCSDPascal/Super.cs b/DiscImageChef.Filesystems/UCSDPascal/Super.cs index fa58c693..2ef6f16f 100644 --- a/DiscImageChef.Filesystems/UCSDPascal/Super.cs +++ b/DiscImageChef.Filesystems/UCSDPascal/Super.cs @@ -121,13 +121,15 @@ namespace DiscImageChef.Filesystems.UCSDPascal public override Errno StatFs(ref FileSystemInfo stat) { - stat = new FileSystemInfo(); - stat.Blocks = mountedVolEntry.blocks; - stat.FilenameLength = 16; - stat.Files = (ulong)mountedVolEntry.files; - stat.FreeBlocks = 0; - stat.PluginId = PluginUuid; - stat.Type = "UCSD Pascal"; + stat = new FileSystemInfo + { + Blocks = mountedVolEntry.blocks, + FilenameLength = 16, + Files = (ulong)mountedVolEntry.files, + FreeBlocks = 0, + PluginId = PluginUuid, + Type = "UCSD Pascal" + }; stat.FreeBlocks = mountedVolEntry.blocks - (mountedVolEntry.lastBlock - mountedVolEntry.firstBlock); foreach(PascalFileEntry entry in fileEntries) stat.FreeBlocks -= entry.lastBlock - entry.firstBlock; diff --git a/DiscImageChef.Filesystems/UCSDPascal/UCSDPascal.cs b/DiscImageChef.Filesystems/UCSDPascal/UCSDPascal.cs index f715d062..5165a6e2 100644 --- a/DiscImageChef.Filesystems/UCSDPascal/UCSDPascal.cs +++ b/DiscImageChef.Filesystems/UCSDPascal/UCSDPascal.cs @@ -42,14 +42,14 @@ namespace DiscImageChef.Filesystems.UCSDPascal // Information from Call-A.P.P.L.E. Pascal Disk Directory Structure public partial class PascalPlugin : Filesystem { - bool mounted; - bool debug; readonly ImagePlugin device; - - PascalVolumeEntry mountedVolEntry; - List fileEntries; byte[] bootBlocks; byte[] catalogBlocks; + bool debug; + List fileEntries; + bool mounted; + + PascalVolumeEntry mountedVolEntry; public PascalPlugin() { diff --git a/DiscImageChef.Filesystems/UDF.cs b/DiscImageChef.Filesystems/UDF.cs index 5adf7c14..441895d6 100644 --- a/DiscImageChef.Filesystems/UDF.cs +++ b/DiscImageChef.Filesystems/UDF.cs @@ -45,6 +45,12 @@ namespace DiscImageChef.Filesystems // TODO: Detect bootable public class UDF : Filesystem { + readonly byte[] UDF_Magic = + { + 0x2A, 0x4F, 0x53, 0x54, 0x41, 0x20, 0x55, 0x44, 0x46, 0x20, 0x43, 0x6F, 0x6D, 0x70, 0x6C, 0x69, 0x61, 0x6E, + 0x74, 0x00, 0x00, 0x00, 0x00 + }; + public UDF() { Name = "Universal Disk Format"; @@ -68,11 +74,304 @@ namespace DiscImageChef.Filesystems CurrentEncoding = Encoding.UTF8; } - readonly byte[] UDF_Magic = + public override bool Identify(ImagePlugin imagePlugin, Partition partition) { - 0x2A, 0x4F, 0x53, 0x54, 0x41, 0x20, 0x55, 0x44, 0x46, 0x20, 0x43, 0x6F, 0x6D, 0x70, 0x6C, 0x69, 0x61, 0x6E, - 0x74, 0x00, 0x00, 0x00, 0x00 - }; + // UDF needs at least that + if(partition.End - partition.Start < 256) return false; + + // UDF needs at least that + if(imagePlugin.ImageInfo.SectorSize < 512) return false; + + byte[] sector; + AnchorVolumeDescriptorPointer anchor = new AnchorVolumeDescriptorPointer(); + // All positions where anchor may reside + ulong[] positions = {256, 512, partition.End - 256, partition.End}; + bool anchorFound = false; + + foreach(ulong position in positions.Where(position => position + partition.Start < partition.End)) + { + sector = imagePlugin.ReadSector(position); + anchor = new AnchorVolumeDescriptorPointer(); + IntPtr anchorPtr = Marshal.AllocHGlobal(Marshal.SizeOf(anchor)); + Marshal.Copy(sector, 0, anchorPtr, Marshal.SizeOf(anchor)); + anchor = + (AnchorVolumeDescriptorPointer)Marshal.PtrToStructure(anchorPtr, + typeof(AnchorVolumeDescriptorPointer)); + Marshal.FreeHGlobal(anchorPtr); + + DicConsole.DebugWriteLine("UDF Plugin", "anchor.tag.tagIdentifier = {0}", anchor.tag.tagIdentifier); + DicConsole.DebugWriteLine("UDF Plugin", "anchor.tag.descriptorVersion = {0}", + anchor.tag.descriptorVersion); + DicConsole.DebugWriteLine("UDF Plugin", "anchor.tag.tagChecksum = 0x{0:X2}", anchor.tag.tagChecksum); + DicConsole.DebugWriteLine("UDF Plugin", "anchor.tag.reserved = {0}", anchor.tag.reserved); + DicConsole.DebugWriteLine("UDF Plugin", "anchor.tag.tagSerialNumber = {0}", anchor.tag.tagSerialNumber); + DicConsole.DebugWriteLine("UDF Plugin", "anchor.tag.descriptorCrc = 0x{0:X4}", + anchor.tag.descriptorCrc); + DicConsole.DebugWriteLine("UDF Plugin", "anchor.tag.descriptorCrcLength = {0}", + anchor.tag.descriptorCrcLength); + DicConsole.DebugWriteLine("UDF Plugin", "anchor.tag.tagLocation = {0}", anchor.tag.tagLocation); + DicConsole.DebugWriteLine("UDF Plugin", "anchor.mainVolumeDescriptorSequenceExtent.length = {0}", + anchor.mainVolumeDescriptorSequenceExtent.length); + DicConsole.DebugWriteLine("UDF Plugin", "anchor.mainVolumeDescriptorSequenceExtent.location = {0}", + anchor.mainVolumeDescriptorSequenceExtent.location); + DicConsole.DebugWriteLine("UDF Plugin", "anchor.reserveVolumeDescriptorSequenceExtent.length = {0}", + anchor.reserveVolumeDescriptorSequenceExtent.length); + DicConsole.DebugWriteLine("UDF Plugin", "anchor.reserveVolumeDescriptorSequenceExtent.location = {0}", + anchor.reserveVolumeDescriptorSequenceExtent.location); + + if(anchor.tag.tagIdentifier != TagIdentifier.AnchorVolumeDescriptorPointer || + anchor.tag.tagLocation != position || + anchor.mainVolumeDescriptorSequenceExtent.location + partition.Start >= partition.End) continue; + + anchorFound = true; + break; + } + + if(!anchorFound) return false; + + ulong count = 0; + + while(count < 256) + { + sector = imagePlugin.ReadSector(partition.Start + anchor.mainVolumeDescriptorSequenceExtent.location + + count); + TagIdentifier tagId = (TagIdentifier)BitConverter.ToUInt16(sector, 0); + uint location = BitConverter.ToUInt32(sector, 0x0C); + + if(location == partition.Start + anchor.mainVolumeDescriptorSequenceExtent.location + count) + { + if(tagId == TagIdentifier.TerminatingDescriptor) break; + + if(tagId == TagIdentifier.LogicalVolumeDescriptor) + { + LogicalVolumeDescriptor lvd = new LogicalVolumeDescriptor(); + IntPtr lvdPtr = Marshal.AllocHGlobal(Marshal.SizeOf(lvd)); + Marshal.Copy(sector, 0, lvdPtr, Marshal.SizeOf(lvd)); + lvd = (LogicalVolumeDescriptor)Marshal.PtrToStructure(lvdPtr, typeof(LogicalVolumeDescriptor)); + Marshal.FreeHGlobal(lvdPtr); + + return UDF_Magic.SequenceEqual(lvd.domainIdentifier.identifier); + } + } + else break; + + count++; + } + + return false; + } + + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + { + byte[] sector; + + StringBuilder sbInformation = new StringBuilder(); + + sbInformation.AppendLine("Universal Disk Format"); + + AnchorVolumeDescriptorPointer anchor = new AnchorVolumeDescriptorPointer(); + // All positions where anchor may reside + ulong[] positions = {256, 512, partition.End - 256, partition.End}; + + foreach(ulong position in positions) + { + sector = imagePlugin.ReadSector(position); + anchor = new AnchorVolumeDescriptorPointer(); + IntPtr anchorPtr = Marshal.AllocHGlobal(Marshal.SizeOf(anchor)); + Marshal.Copy(sector, 0, anchorPtr, Marshal.SizeOf(anchor)); + anchor = + (AnchorVolumeDescriptorPointer)Marshal.PtrToStructure(anchorPtr, + typeof(AnchorVolumeDescriptorPointer)); + Marshal.FreeHGlobal(anchorPtr); + + if(anchor.tag.tagIdentifier == TagIdentifier.AnchorVolumeDescriptorPointer && + anchor.tag.tagLocation == position && + anchor.mainVolumeDescriptorSequenceExtent.location + partition.Start < partition.End) break; + } + + ulong count = 0; + + PrimaryVolumeDescriptor pvd = new PrimaryVolumeDescriptor(); + LogicalVolumeDescriptor lvd = new LogicalVolumeDescriptor(); + LogicalVolumeIntegrityDescriptor lvid = new LogicalVolumeIntegrityDescriptor(); + LogicalVolumeIntegrityDescriptorImplementationUse lvidiu = + new LogicalVolumeIntegrityDescriptorImplementationUse(); + + while(count < 256) + { + sector = imagePlugin.ReadSector(partition.Start + anchor.mainVolumeDescriptorSequenceExtent.location + + count); + TagIdentifier tagId = (TagIdentifier)BitConverter.ToUInt16(sector, 0); + uint location = BitConverter.ToUInt32(sector, 0x0C); + + if(location == partition.Start + anchor.mainVolumeDescriptorSequenceExtent.location + count) + { + if(tagId == TagIdentifier.TerminatingDescriptor) break; + + switch(tagId) + { + case TagIdentifier.LogicalVolumeDescriptor: + IntPtr lvdPtr = Marshal.AllocHGlobal(Marshal.SizeOf(lvd)); + Marshal.Copy(sector, 0, lvdPtr, Marshal.SizeOf(lvd)); + lvd = (LogicalVolumeDescriptor) + Marshal.PtrToStructure(lvdPtr, typeof(LogicalVolumeDescriptor)); + Marshal.FreeHGlobal(lvdPtr); + break; + case TagIdentifier.PrimaryVolumeDescriptor: + IntPtr pvdPtr = Marshal.AllocHGlobal(Marshal.SizeOf(pvd)); + Marshal.Copy(sector, 0, pvdPtr, Marshal.SizeOf(pvd)); + pvd = (PrimaryVolumeDescriptor) + Marshal.PtrToStructure(pvdPtr, typeof(PrimaryVolumeDescriptor)); + Marshal.FreeHGlobal(pvdPtr); + break; + } + } + else break; + + count++; + } + + sector = imagePlugin.ReadSector(lvd.integritySequenceExtent.location); + IntPtr lvidPtr = Marshal.AllocHGlobal(Marshal.SizeOf(lvid)); + Marshal.Copy(sector, 0, lvidPtr, Marshal.SizeOf(lvid)); + lvid = + (LogicalVolumeIntegrityDescriptor) + Marshal.PtrToStructure(lvidPtr, typeof(LogicalVolumeIntegrityDescriptor)); + Marshal.FreeHGlobal(lvidPtr); + + if(lvid.tag.tagIdentifier == TagIdentifier.LogicalVolumeIntegrityDescriptor && + lvid.tag.tagLocation == lvd.integritySequenceExtent.location) + { + IntPtr lvidiuPtr = Marshal.AllocHGlobal(Marshal.SizeOf(lvidiu)); + Marshal.Copy(sector, (int)(lvid.numberOfPartitions * 8 + 80), lvidiuPtr, Marshal.SizeOf(lvidiu)); + lvidiu = + (LogicalVolumeIntegrityDescriptorImplementationUse)Marshal.PtrToStructure(lvidiuPtr, + typeof( + LogicalVolumeIntegrityDescriptorImplementationUse + )); + Marshal.FreeHGlobal(lvidiuPtr); + } + else lvid = new LogicalVolumeIntegrityDescriptor(); + + sbInformation.AppendFormat("Volume is number {0} of {1}", pvd.volumeSequenceNumber, + pvd.maximumVolumeSequenceNumber).AppendLine(); + sbInformation.AppendFormat("Volume set identifier: {0}", + StringHandlers.DecompressUnicode(pvd.volumeSetIdentifier)).AppendLine(); + sbInformation + .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)) + .AppendLine(); + sbInformation.AppendFormat("Volume contains {0} partitions", lvid.numberOfPartitions).AppendLine(); + sbInformation + .AppendFormat("Volume contains {0} files and {1} directories", lvidiu.files, lvidiu.directories) + .AppendLine(); + sbInformation.AppendFormat("Volume conforms to {0}", + CurrentEncoding.GetString(lvd.domainIdentifier.identifier).TrimEnd('\u0000')) + .AppendLine(); + sbInformation.AppendFormat("Volume was last written by: {0}", + CurrentEncoding + .GetString(pvd.implementationIdentifier.identifier).TrimEnd('\u0000')) + .AppendLine(); + sbInformation.AppendFormat("Volume requires UDF version {0}.{1:X2} to be read", + Convert.ToInt32($"{(lvidiu.minimumReadUDF & 0xFF00) >> 8}", 10), + Convert.ToInt32($"{lvidiu.minimumReadUDF & 0xFF}", 10)).AppendLine(); + sbInformation.AppendFormat("Volume requires UDF version {0}.{1:X2} to be written to", + Convert.ToInt32($"{(lvidiu.minimumWriteUDF & 0xFF00) >> 8}", 10), + Convert.ToInt32($"{lvidiu.minimumWriteUDF & 0xFF}", 10)).AppendLine(); + sbInformation.AppendFormat("Volume cannot be written by any UDF version higher than {0}.{1:X2}", + Convert.ToInt32($"{(lvidiu.maximumWriteUDF & 0xFF00) >> 8}", 10), + Convert.ToInt32($"{lvidiu.maximumWriteUDF & 0xFF}", 10)).AppendLine(); + + 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) + { + return DateHandlers.EcmaToDateTime(timestamp.typeAndZone, timestamp.year, timestamp.month, timestamp.day, + timestamp.hour, timestamp.minute, timestamp.second, + timestamp.centiseconds, timestamp.hundredsMicroseconds, + timestamp.microseconds); + } + + public override Errno Mount() + { + return Errno.NotImplemented; + } + + public override Errno Mount(bool debug) + { + return Errno.NotImplemented; + } + + public override Errno Unmount() + { + return Errno.NotImplemented; + } + + public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + { + return Errno.NotImplemented; + } + + public override Errno GetAttributes(string path, ref FileAttributes attributes) + { + return Errno.NotImplemented; + } + + public override Errno ListXAttr(string path, ref List xattrs) + { + return Errno.NotImplemented; + } + + public override Errno GetXattr(string path, string xattr, ref byte[] buf) + { + return Errno.NotImplemented; + } + + public override Errno Read(string path, long offset, long size, ref byte[] buf) + { + return Errno.NotImplemented; + } + + public override Errno ReadDir(string path, ref List contents) + { + return Errno.NotImplemented; + } + + public override Errno StatFs(ref FileSystemInfo stat) + { + return Errno.NotImplemented; + } + + public override Errno Stat(string path, ref FileEntryInfo stat) + { + return Errno.NotImplemented; + } + + public override Errno ReadLink(string path, ref string dest) + { + return Errno.NotImplemented; + } [Flags] enum EntityFlags : byte @@ -85,15 +384,15 @@ namespace DiscImageChef.Filesystems struct EntityIdentifier { /// - /// Entity flags + /// Entity flags /// public EntityFlags flags; /// - /// Structure identifier + /// Structure identifier /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 23)] public byte[] identifier; /// - /// Structure data + /// Structure data /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] identifierSuffix; } @@ -231,307 +530,5 @@ namespace DiscImageChef.Filesystems public ushort minimumWriteUDF; public ushort maximumWriteUDF; } - - public override bool Identify(ImagePlugin imagePlugin, Partition partition) - { - // UDF needs at least that - if(partition.End - partition.Start < 256) return false; - - // UDF needs at least that - if(imagePlugin.ImageInfo.SectorSize < 512) return false; - - byte[] sector; - AnchorVolumeDescriptorPointer anchor = new AnchorVolumeDescriptorPointer(); - // All positions where anchor may reside - ulong[] positions = {256, 512, partition.End - 256, partition.End}; - bool anchorFound = false; - - foreach(ulong position in positions.Where(position => position + partition.Start < partition.End)) { - sector = imagePlugin.ReadSector(position); - anchor = new AnchorVolumeDescriptorPointer(); - IntPtr anchorPtr = Marshal.AllocHGlobal(Marshal.SizeOf(anchor)); - Marshal.Copy(sector, 0, anchorPtr, Marshal.SizeOf(anchor)); - anchor = - (AnchorVolumeDescriptorPointer)Marshal.PtrToStructure(anchorPtr, - typeof(AnchorVolumeDescriptorPointer)); - Marshal.FreeHGlobal(anchorPtr); - - DicConsole.DebugWriteLine("UDF Plugin", "anchor.tag.tagIdentifier = {0}", anchor.tag.tagIdentifier); - DicConsole.DebugWriteLine("UDF Plugin", "anchor.tag.descriptorVersion = {0}", - anchor.tag.descriptorVersion); - DicConsole.DebugWriteLine("UDF Plugin", "anchor.tag.tagChecksum = 0x{0:X2}", anchor.tag.tagChecksum); - DicConsole.DebugWriteLine("UDF Plugin", "anchor.tag.reserved = {0}", anchor.tag.reserved); - DicConsole.DebugWriteLine("UDF Plugin", "anchor.tag.tagSerialNumber = {0}", anchor.tag.tagSerialNumber); - DicConsole.DebugWriteLine("UDF Plugin", "anchor.tag.descriptorCrc = 0x{0:X4}", - anchor.tag.descriptorCrc); - DicConsole.DebugWriteLine("UDF Plugin", "anchor.tag.descriptorCrcLength = {0}", - anchor.tag.descriptorCrcLength); - DicConsole.DebugWriteLine("UDF Plugin", "anchor.tag.tagLocation = {0}", anchor.tag.tagLocation); - DicConsole.DebugWriteLine("UDF Plugin", "anchor.mainVolumeDescriptorSequenceExtent.length = {0}", - anchor.mainVolumeDescriptorSequenceExtent.length); - DicConsole.DebugWriteLine("UDF Plugin", "anchor.mainVolumeDescriptorSequenceExtent.location = {0}", - anchor.mainVolumeDescriptorSequenceExtent.location); - DicConsole.DebugWriteLine("UDF Plugin", "anchor.reserveVolumeDescriptorSequenceExtent.length = {0}", - anchor.reserveVolumeDescriptorSequenceExtent.length); - DicConsole.DebugWriteLine("UDF Plugin", "anchor.reserveVolumeDescriptorSequenceExtent.location = {0}", - anchor.reserveVolumeDescriptorSequenceExtent.location); - - if(anchor.tag.tagIdentifier != TagIdentifier.AnchorVolumeDescriptorPointer || - anchor.tag.tagLocation != position || - anchor.mainVolumeDescriptorSequenceExtent.location + partition.Start >= partition.End) continue; - - anchorFound = true; - break; - } - - if(!anchorFound) return false; - - ulong count = 0; - - while(count < 256) - { - sector = imagePlugin.ReadSector(partition.Start + anchor.mainVolumeDescriptorSequenceExtent.location + - count); - TagIdentifier tagId = (TagIdentifier)BitConverter.ToUInt16(sector, 0); - uint location = BitConverter.ToUInt32(sector, 0x0C); - - if(location == partition.Start + anchor.mainVolumeDescriptorSequenceExtent.location + count) - { - if(tagId == TagIdentifier.TerminatingDescriptor) break; - - if(tagId == TagIdentifier.LogicalVolumeDescriptor) - { - LogicalVolumeDescriptor lvd = new LogicalVolumeDescriptor(); - IntPtr lvdPtr = Marshal.AllocHGlobal(Marshal.SizeOf(lvd)); - Marshal.Copy(sector, 0, lvdPtr, Marshal.SizeOf(lvd)); - lvd = (LogicalVolumeDescriptor)Marshal.PtrToStructure(lvdPtr, typeof(LogicalVolumeDescriptor)); - Marshal.FreeHGlobal(lvdPtr); - - return UDF_Magic.SequenceEqual(lvd.domainIdentifier.identifier); - } - } - else break; - - count++; - } - - return false; - } - - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) - { - byte[] sector; - - StringBuilder sbInformation = new StringBuilder(); - - sbInformation.AppendLine("Universal Disk Format"); - - AnchorVolumeDescriptorPointer anchor = new AnchorVolumeDescriptorPointer(); - // All positions where anchor may reside - ulong[] positions = {256, 512, partition.End - 256, partition.End}; - - foreach(ulong position in positions) - { - sector = imagePlugin.ReadSector(position); - anchor = new AnchorVolumeDescriptorPointer(); - IntPtr anchorPtr = Marshal.AllocHGlobal(Marshal.SizeOf(anchor)); - Marshal.Copy(sector, 0, anchorPtr, Marshal.SizeOf(anchor)); - anchor = - (AnchorVolumeDescriptorPointer)Marshal.PtrToStructure(anchorPtr, - typeof(AnchorVolumeDescriptorPointer)); - Marshal.FreeHGlobal(anchorPtr); - - if(anchor.tag.tagIdentifier == TagIdentifier.AnchorVolumeDescriptorPointer && - anchor.tag.tagLocation == position && - anchor.mainVolumeDescriptorSequenceExtent.location + partition.Start < partition.End) break; - } - - ulong count = 0; - - PrimaryVolumeDescriptor pvd = new PrimaryVolumeDescriptor(); - LogicalVolumeDescriptor lvd = new LogicalVolumeDescriptor(); - LogicalVolumeIntegrityDescriptor lvid = new LogicalVolumeIntegrityDescriptor(); - LogicalVolumeIntegrityDescriptorImplementationUse lvidiu = - new LogicalVolumeIntegrityDescriptorImplementationUse(); - - while(count < 256) - { - sector = imagePlugin.ReadSector(partition.Start + anchor.mainVolumeDescriptorSequenceExtent.location + - count); - TagIdentifier tagId = (TagIdentifier)BitConverter.ToUInt16(sector, 0); - uint location = BitConverter.ToUInt32(sector, 0x0C); - - if(location == partition.Start + anchor.mainVolumeDescriptorSequenceExtent.location + count) - { - if(tagId == TagIdentifier.TerminatingDescriptor) break; - - switch(tagId) { - case TagIdentifier.LogicalVolumeDescriptor: - IntPtr lvdPtr = Marshal.AllocHGlobal(Marshal.SizeOf(lvd)); - Marshal.Copy(sector, 0, lvdPtr, Marshal.SizeOf(lvd)); - lvd = (LogicalVolumeDescriptor)Marshal.PtrToStructure(lvdPtr, typeof(LogicalVolumeDescriptor)); - Marshal.FreeHGlobal(lvdPtr); - break; - case TagIdentifier.PrimaryVolumeDescriptor: - IntPtr pvdPtr = Marshal.AllocHGlobal(Marshal.SizeOf(pvd)); - Marshal.Copy(sector, 0, pvdPtr, Marshal.SizeOf(pvd)); - pvd = (PrimaryVolumeDescriptor)Marshal.PtrToStructure(pvdPtr, typeof(PrimaryVolumeDescriptor)); - Marshal.FreeHGlobal(pvdPtr); - break; - } - } - else break; - - count++; - } - - sector = imagePlugin.ReadSector(lvd.integritySequenceExtent.location); - IntPtr lvidPtr = Marshal.AllocHGlobal(Marshal.SizeOf(lvid)); - Marshal.Copy(sector, 0, lvidPtr, Marshal.SizeOf(lvid)); - lvid = - (LogicalVolumeIntegrityDescriptor) - Marshal.PtrToStructure(lvidPtr, typeof(LogicalVolumeIntegrityDescriptor)); - Marshal.FreeHGlobal(lvidPtr); - - if(lvid.tag.tagIdentifier == TagIdentifier.LogicalVolumeIntegrityDescriptor && - lvid.tag.tagLocation == lvd.integritySequenceExtent.location) - { - IntPtr lvidiuPtr = Marshal.AllocHGlobal(Marshal.SizeOf(lvidiu)); - Marshal.Copy(sector, (int)(lvid.numberOfPartitions * 8 + 80), lvidiuPtr, Marshal.SizeOf(lvidiu)); - lvidiu = - (LogicalVolumeIntegrityDescriptorImplementationUse)Marshal.PtrToStructure(lvidiuPtr, - typeof( - LogicalVolumeIntegrityDescriptorImplementationUse - )); - Marshal.FreeHGlobal(lvidiuPtr); - } - else lvid = new LogicalVolumeIntegrityDescriptor(); - - sbInformation.AppendFormat("Volume is number {0} of {1}", pvd.volumeSequenceNumber, - pvd.maximumVolumeSequenceNumber).AppendLine(); - sbInformation.AppendFormat("Volume set identifier: {0}", - StringHandlers.DecompressUnicode(pvd.volumeSetIdentifier)).AppendLine(); - sbInformation - .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)) - .AppendLine(); - sbInformation.AppendFormat("Volume contains {0} partitions", lvid.numberOfPartitions).AppendLine(); - sbInformation - .AppendFormat("Volume contains {0} files and {1} directories", lvidiu.files, lvidiu.directories) - .AppendLine(); - sbInformation.AppendFormat("Volume conforms to {0}", - CurrentEncoding - .GetString(lvd.domainIdentifier.identifier).TrimEnd('\u0000')) - .AppendLine(); - sbInformation.AppendFormat("Volume was last written by: {0}", - CurrentEncoding - .GetString(pvd.implementationIdentifier.identifier) - .TrimEnd('\u0000')).AppendLine(); - sbInformation.AppendFormat("Volume requires UDF version {0}.{1:X2} to be read", - Convert.ToInt32($"{(lvidiu.minimumReadUDF & 0xFF00) >> 8}", 10), - Convert.ToInt32($"{lvidiu.minimumReadUDF & 0xFF}", 10)) - .AppendLine(); - sbInformation.AppendFormat("Volume requires UDF version {0}.{1:X2} to be written to", - Convert.ToInt32($"{(lvidiu.minimumWriteUDF & 0xFF00) >> 8}", - 10), - Convert.ToInt32($"{lvidiu.minimumWriteUDF & 0xFF}", 10)) - .AppendLine(); - sbInformation.AppendFormat("Volume cannot be written by any UDF version higher than {0}.{1:X2}", - Convert.ToInt32($"{(lvidiu.maximumWriteUDF & 0xFF00) >> 8}", - 10), - Convert.ToInt32($"{lvidiu.maximumWriteUDF & 0xFF}", 10)) - .AppendLine(); - - 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) - { - return DateHandlers.EcmaToDateTime(timestamp.typeAndZone, timestamp.year, timestamp.month, timestamp.day, - timestamp.hour, timestamp.minute, timestamp.second, - timestamp.centiseconds, timestamp.hundredsMicroseconds, - timestamp.microseconds); - } - - public override Errno Mount() - { - return Errno.NotImplemented; - } - - public override Errno Mount(bool debug) - { - return Errno.NotImplemented; - } - - public override Errno Unmount() - { - return Errno.NotImplemented; - } - - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) - { - return Errno.NotImplemented; - } - - public override Errno GetAttributes(string path, ref FileAttributes attributes) - { - return Errno.NotImplemented; - } - - public override Errno ListXAttr(string path, ref List xattrs) - { - return Errno.NotImplemented; - } - - public override Errno GetXattr(string path, string xattr, ref byte[] buf) - { - return Errno.NotImplemented; - } - - public override Errno Read(string path, long offset, long size, ref byte[] buf) - { - return Errno.NotImplemented; - } - - public override Errno ReadDir(string path, ref List contents) - { - return Errno.NotImplemented; - } - - public override Errno StatFs(ref FileSystemInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) - { - return Errno.NotImplemented; - } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/UNICOS.cs b/DiscImageChef.Filesystems/UNICOS.cs index 61997ed5..3dee0d3c 100644 --- a/DiscImageChef.Filesystems/UNICOS.cs +++ b/DiscImageChef.Filesystems/UNICOS.cs @@ -49,91 +49,11 @@ using time_t = System.Int64; namespace DiscImageChef.Filesystems { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "BuiltInTypeReferenceStyle")] public class UNICOS : Filesystem { const int NC1MAXPART = 64; const int NC1MAXIREG = 4; - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct nc1ireg_sb - { - public ushort i_unused; /* reserved */ - public ushort i_nblk; /* number of blocks */ - public uint i_sblk; /* start block number */ - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct nc1fdev_sb - { - public long fd_name; /* Physical device name */ - public uint fd_sblk; /* Start block number */ - public uint fd_nblk; /* Number of blocks */ - [MarshalAs(UnmanagedType.ByValArray, SizeConst = NC1MAXIREG)] - public nc1ireg_sb[] fd_ireg; /* Inode regions */ - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct UNICOS_Superblock - { - public ulong s_magic; /* magic number to indicate file system type */ - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] s_fname; /* file system name */ - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] s_fpack; /* file system pack name */ - public dev_t s_dev; /* major/minor device, for verification */ - - public daddr_t s_fsize; /* size in blocks of entire volume */ - public long s_isize; /* Number of total inodes */ - public long s_bigfile; /* number of bytes at which a file is big */ - public long s_bigunit; /* minimum number of blocks allocated for big files */ - public ulong s_secure; /* security: secure FS label */ - public long s_maxlvl; /* security: maximum security level */ - public long s_minlvl; /* security: minimum security level */ - public long s_valcmp; /* security: valid security compartments */ - public time_t s_time; /* last super block update */ - public blkno_t s_dboff; /* Dynamic block number */ - public ino_t s_root; /* root inode */ - public long s_error; /* Type of file system error detected */ - public blkno_t s_mapoff; /* Start map block number */ - public long s_mapblks; /* Last map block number */ - public long s_nscpys; /* Number of copies of s.b per partition */ - public long s_npart; /* Number of partitions */ - public long s_ifract; /* Ratio of inodes to blocks */ - public extent_t s_sfs; /* SFS only blocks */ - public long s_flag; /* Flag word */ - [MarshalAs(UnmanagedType.ByValArray, SizeConst = NC1MAXPART)] - public nc1fdev_sb[] s_part; /* Partition descriptors */ - public long s_iounit; /* Physical block size */ - public long s_numiresblks; /* number of inode reservation blocks */ - /* per region (currently 1) */ - /* 0 = 1*(AU) words, n = (n+1)*(AU) words */ - public long s_priparts; /* bitmap of primary partitions */ - public long s_priblock; /* block size of primary partition(s) */ - /* 0 = 1*512 words, n = (n+1)*512 words */ - public long s_prinblks; /* number of 512 wds blocks in primary */ - public long s_secparts; /* bitmap of secondary partitions */ - public long s_secblock; /* block size of secondary partition(s) */ - /* 0 = 1*512 words, n = (n+1)*512 words */ - public long s_secnblks; /* number of 512 wds blocks in secondary */ - public long s_sbdbparts; /* bitmap of partitions with file system data */ - /* including super blocks, dynamic block */ - /* and free block bitmaps (only primary */ - /* partitions may contain these) */ - public long s_rootdparts; /* bitmap of partitions with root directory */ - /* (only primary partitions) */ - public long s_nudparts; /* bitmap of no-user-data partitions */ - /* (only primary partitions) */ - public long s_nsema; /* SFS: # fs semaphores to allocate */ - public long s_priactive; /* bitmap of primary partitions which contain */ - /* active (up to date) dynamic blocks and */ - /* free block bitmaps. All bits set indicate */ - /* that all primary partitions are active, */ - /* and no kernel manipulation of active flag */ - /* is allowed. */ - public long s_sfs_arbiterid; /* SFS Arbiter ID */ - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 91)] public long[] s_fill; /* reserved */ - } - const ulong UNICOS_Magic = 0x6e6331667331636e; const ulong UNICOS_Secure = 0xcd076d1771d670cd; @@ -178,8 +98,7 @@ namespace DiscImageChef.Filesystems return unicosSb.s_magic == UNICOS_Magic; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { information = ""; if(imagePlugin.GetSectorSize() < 512) return; @@ -285,5 +204,87 @@ namespace DiscImageChef.Filesystems { return Errno.NotImplemented; } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + [SuppressMessage("ReSharper", "InconsistentNaming")] + struct nc1ireg_sb + { + public ushort i_unused; /* reserved */ + public ushort i_nblk; /* number of blocks */ + public uint i_sblk; /* start block number */ + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + [SuppressMessage("ReSharper", "InconsistentNaming")] + struct nc1fdev_sb + { + public long fd_name; /* Physical device name */ + public uint fd_sblk; /* Start block number */ + public uint fd_nblk; /* Number of blocks */ + [MarshalAs(UnmanagedType.ByValArray, SizeConst = NC1MAXIREG)] + public nc1ireg_sb[] fd_ireg; /* Inode regions */ + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + [SuppressMessage("ReSharper", "InconsistentNaming")] + [SuppressMessage("ReSharper", "BuiltInTypeReferenceStyle")] + struct UNICOS_Superblock + { + public ulong s_magic; /* magic number to indicate file system type */ + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] s_fname; /* file system name */ + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] s_fpack; /* file system pack name */ + public dev_t s_dev; /* major/minor device, for verification */ + + public daddr_t s_fsize; /* size in blocks of entire volume */ + public long s_isize; /* Number of total inodes */ + public long s_bigfile; /* number of bytes at which a file is big */ + public long s_bigunit; /* minimum number of blocks allocated for big files */ + public ulong s_secure; /* security: secure FS label */ + public long s_maxlvl; /* security: maximum security level */ + public long s_minlvl; /* security: minimum security level */ + public long s_valcmp; /* security: valid security compartments */ + public time_t s_time; /* last super block update */ + public blkno_t s_dboff; /* Dynamic block number */ + public ino_t s_root; /* root inode */ + public long s_error; /* Type of file system error detected */ + public blkno_t s_mapoff; /* Start map block number */ + public long s_mapblks; /* Last map block number */ + public long s_nscpys; /* Number of copies of s.b per partition */ + public long s_npart; /* Number of partitions */ + public long s_ifract; /* Ratio of inodes to blocks */ + public extent_t s_sfs; /* SFS only blocks */ + public long s_flag; /* Flag word */ + [MarshalAs(UnmanagedType.ByValArray, SizeConst = NC1MAXPART)] + public nc1fdev_sb[] s_part; /* Partition descriptors */ + public long s_iounit; /* Physical block size */ + public long s_numiresblks; /* number of inode reservation blocks */ + /* per region (currently 1) */ + /* 0 = 1*(AU) words, n = (n+1)*(AU) words */ + public long s_priparts; /* bitmap of primary partitions */ + public long s_priblock; /* block size of primary partition(s) */ + /* 0 = 1*512 words, n = (n+1)*512 words */ + public long s_prinblks; /* number of 512 wds blocks in primary */ + public long s_secparts; /* bitmap of secondary partitions */ + public long s_secblock; /* block size of secondary partition(s) */ + /* 0 = 1*512 words, n = (n+1)*512 words */ + public long s_secnblks; /* number of 512 wds blocks in secondary */ + public long s_sbdbparts; /* bitmap of partitions with file system data */ + /* including super blocks, dynamic block */ + /* and free block bitmaps (only primary */ + /* partitions may contain these) */ + public long s_rootdparts; /* bitmap of partitions with root directory */ + /* (only primary partitions) */ + public long s_nudparts; /* bitmap of no-user-data partitions */ + /* (only primary partitions) */ + public long s_nsema; /* SFS: # fs semaphores to allocate */ + public long s_priactive; /* bitmap of primary partitions which contain */ + /* active (up to date) dynamic blocks and */ + /* free block bitmaps. All bits set indicate */ + /* that all primary partitions are active, */ + /* and no kernel manipulation of active flag */ + /* is allowed. */ + public long s_sfs_arbiterid; /* SFS Arbiter ID */ + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 91)] public long[] s_fill; /* reserved */ + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/UNIXBFS.cs b/DiscImageChef.Filesystems/UNIXBFS.cs index a1ac9759..2d296460 100644 --- a/DiscImageChef.Filesystems/UNIXBFS.cs +++ b/DiscImageChef.Filesystems/UNIXBFS.cs @@ -77,8 +77,7 @@ namespace DiscImageChef.Filesystems return magic == BFS_MAGIC; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { information = ""; @@ -127,28 +126,6 @@ namespace DiscImageChef.Filesystems information = sb.ToString(); } - struct BFSSuperBlock - { - /// 0x00, 0x1BADFACE - public uint s_magic; - /// 0x04, start in bytes of volume - public uint s_start; - /// 0x08, end in bytes of volume - public uint s_end; - /// 0x0C, unknown :p - public uint s_from; - /// 0x10, unknown :p - public uint s_to; - /// 0x14, unknown :p - public int s_bfrom; - /// 0x18, unknown :p - public int s_bto; - /// 0x1C, 6 bytes, filesystem name - public string s_fsname; - /// 0x22, 6 bytes, volume name - public string s_volume; - } - public override Errno Mount() { return Errno.NotImplemented; @@ -208,5 +185,27 @@ namespace DiscImageChef.Filesystems { return Errno.NotImplemented; } + + struct BFSSuperBlock + { + /// 0x00, 0x1BADFACE + public uint s_magic; + /// 0x04, start in bytes of volume + public uint s_start; + /// 0x08, end in bytes of volume + public uint s_end; + /// 0x0C, unknown :p + public uint s_from; + /// 0x10, unknown :p + public uint s_to; + /// 0x14, unknown :p + public int s_bfrom; + /// 0x18, unknown :p + public int s_bto; + /// 0x1C, 6 bytes, filesystem name + public string s_fsname; + /// 0x22, 6 bytes, volume name + public string s_volume; + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/VMfs.cs b/DiscImageChef.Filesystems/VMfs.cs index a22db61c..150e0856 100644 --- a/DiscImageChef.Filesystems/VMfs.cs +++ b/DiscImageChef.Filesystems/VMfs.cs @@ -42,6 +42,12 @@ namespace DiscImageChef.Filesystems { public class VMfs : Filesystem { + /// + /// Identifier for VMfs + /// + const uint VMFS_MAGIC = 0xC001D00D; + const uint VMFS_BASE = 0x00100000; + public VMfs() { Name = "VMware filesystem"; @@ -63,36 +69,6 @@ namespace DiscImageChef.Filesystems CurrentEncoding = encoding ?? Encoding.UTF8; } - [Flags] - enum VMfsFlags : byte - { - RecyledFolder = 64, - CaseSensitive = 128 - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct VolumeInfo - { - public uint magic; - public uint version; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] public byte[] unknown1; - public byte lun; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] unknown2; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 28)] public byte[] name; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 49)] public byte[] unknown3; - public uint size; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 31)] public byte[] unknown4; - public Guid uuid; - public ulong ctime; - public ulong mtime; - } - - /// - /// Identifier for VMfs - /// - 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; @@ -108,8 +84,7 @@ namespace DiscImageChef.Filesystems return magic == VMFS_MAGIC; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { ulong vmfsSuperOff = VMFS_BASE / imagePlugin.ImageInfo.SectorSize; byte[] sector = imagePlugin.ReadSector(partition.Start + vmfsSuperOff); @@ -214,5 +189,29 @@ namespace DiscImageChef.Filesystems { return Errno.NotImplemented; } + + [Flags] + enum VMfsFlags : byte + { + RecyledFolder = 64, + CaseSensitive = 128 + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct VolumeInfo + { + public uint magic; + public uint version; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] public byte[] unknown1; + public byte lun; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] unknown2; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 28)] public byte[] name; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 49)] public byte[] unknown3; + public uint size; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 31)] public byte[] unknown4; + public Guid uuid; + public ulong ctime; + public ulong mtime; + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/VxFS.cs b/DiscImageChef.Filesystems/VxFS.cs index b2195b1b..d336df97 100644 --- a/DiscImageChef.Filesystems/VxFS.cs +++ b/DiscImageChef.Filesystems/VxFS.cs @@ -42,6 +42,12 @@ namespace DiscImageChef.Filesystems { public class VxFS : Filesystem { + /// + /// Identifier for VxFS + /// + const uint VXFS_MAGIC = 0xA501FCF5; + const uint VXFS_BASE = 0x400; + public VxFS() { Name = "Veritas filesystem"; @@ -63,6 +69,125 @@ namespace DiscImageChef.Filesystems CurrentEncoding = encoding ?? Encoding.UTF8; } + public override bool Identify(ImagePlugin imagePlugin, Partition partition) + { + ulong vmfsSuperOff = VXFS_BASE / imagePlugin.ImageInfo.SectorSize; + + if(partition.Start + vmfsSuperOff >= partition.End) return false; + + byte[] sector = imagePlugin.ReadSector(partition.Start + vmfsSuperOff); + + uint magic = BitConverter.ToUInt32(sector, 0x00); + + return magic == VXFS_MAGIC; + } + + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) + { + ulong vmfsSuperOff = VXFS_BASE / imagePlugin.ImageInfo.SectorSize; + byte[] sector = imagePlugin.ReadSector(partition.Start + vmfsSuperOff); + + VxSuperBlock vxSb = new VxSuperBlock(); + IntPtr vxSbPtr = Marshal.AllocHGlobal(Marshal.SizeOf(vxSb)); + Marshal.Copy(sector, 0, vxSbPtr, Marshal.SizeOf(vxSb)); + vxSb = (VxSuperBlock)Marshal.PtrToStructure(vxSbPtr, typeof(VxSuperBlock)); + Marshal.FreeHGlobal(vxSbPtr); + + StringBuilder sbInformation = new StringBuilder(); + + sbInformation.AppendLine("Veritas file system"); + + sbInformation.AppendFormat("Volume version {0}", vxSb.vs_version).AppendLine(); + sbInformation.AppendFormat("Volume name {0}", StringHandlers.CToString(vxSb.vs_fname, CurrentEncoding)) + .AppendLine(); + sbInformation.AppendFormat("Volume has {0} blocks of {1} bytes each", vxSb.vs_bsize, vxSb.vs_size) + .AppendLine(); + sbInformation.AppendFormat("Volume has {0} inodes per block", vxSb.vs_inopb).AppendLine(); + sbInformation.AppendFormat("Volume has {0} free inodes", vxSb.vs_ifree).AppendLine(); + sbInformation.AppendFormat("Volume has {0} free blocks", vxSb.vs_free).AppendLine(); + sbInformation.AppendFormat("Volume created on {0}", + DateHandlers.UnixUnsignedToDateTime(vxSb.vs_ctime, vxSb.vs_cutime)).AppendLine(); + sbInformation.AppendFormat("Volume last modified on {0}", + DateHandlers.UnixUnsignedToDateTime(vxSb.vs_wtime, vxSb.vs_wutime)).AppendLine(); + if(vxSb.vs_clean != 0) sbInformation.AppendLine("Volume is dirty"); + + information = sbInformation.ToString(); + + 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() + { + return Errno.NotImplemented; + } + + public override Errno Mount(bool debug) + { + return Errno.NotImplemented; + } + + public override Errno Unmount() + { + return Errno.NotImplemented; + } + + public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + { + return Errno.NotImplemented; + } + + public override Errno GetAttributes(string path, ref FileAttributes attributes) + { + return Errno.NotImplemented; + } + + public override Errno ListXAttr(string path, ref List xattrs) + { + return Errno.NotImplemented; + } + + public override Errno GetXattr(string path, string xattr, ref byte[] buf) + { + return Errno.NotImplemented; + } + + public override Errno Read(string path, long offset, long size, ref byte[] buf) + { + return Errno.NotImplemented; + } + + public override Errno ReadDir(string path, ref List contents) + { + return Errno.NotImplemented; + } + + public override Errno StatFs(ref FileSystemInfo stat) + { + return Errno.NotImplemented; + } + + public override Errno Stat(string path, ref FileEntryInfo stat) + { + return Errno.NotImplemented; + } + + public override Errno ReadLink(string path, ref string dest) + { + return Errno.NotImplemented; + } + [StructLayout(LayoutKind.Sequential, Pack = 1)] struct VxSuperBlock { @@ -205,131 +330,5 @@ namespace DiscImageChef.Filesystems /// checksum of V2 RO public int vs_checksum2; } - - /// - /// Identifier for VxFS - /// - 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; - - if(partition.Start + vmfsSuperOff >= partition.End) return false; - - byte[] sector = imagePlugin.ReadSector(partition.Start + vmfsSuperOff); - - uint magic = BitConverter.ToUInt32(sector, 0x00); - - return magic == VXFS_MAGIC; - } - - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) - { - ulong vmfsSuperOff = VXFS_Base / imagePlugin.ImageInfo.SectorSize; - byte[] sector = imagePlugin.ReadSector(partition.Start + vmfsSuperOff); - - VxSuperBlock vxSb = new VxSuperBlock(); - IntPtr vxSbPtr = Marshal.AllocHGlobal(Marshal.SizeOf(vxSb)); - Marshal.Copy(sector, 0, vxSbPtr, Marshal.SizeOf(vxSb)); - vxSb = (VxSuperBlock)Marshal.PtrToStructure(vxSbPtr, typeof(VxSuperBlock)); - Marshal.FreeHGlobal(vxSbPtr); - - StringBuilder sbInformation = new StringBuilder(); - - sbInformation.AppendLine("Veritas file system"); - - sbInformation.AppendFormat("Volume version {0}", vxSb.vs_version).AppendLine(); - sbInformation.AppendFormat("Volume name {0}", StringHandlers.CToString(vxSb.vs_fname, CurrentEncoding)) - .AppendLine(); - sbInformation.AppendFormat("Volume has {0} blocks of {1} bytes each", vxSb.vs_bsize, vxSb.vs_size) - .AppendLine(); - sbInformation.AppendFormat("Volume has {0} inodes per block", vxSb.vs_inopb).AppendLine(); - sbInformation.AppendFormat("Volume has {0} free inodes", vxSb.vs_ifree).AppendLine(); - sbInformation.AppendFormat("Volume has {0} free blocks", vxSb.vs_free).AppendLine(); - sbInformation.AppendFormat("Volume created on {0}", - DateHandlers.UnixUnsignedToDateTime(vxSb.vs_ctime, vxSb.vs_cutime)).AppendLine(); - sbInformation.AppendFormat("Volume last modified on {0}", - DateHandlers.UnixUnsignedToDateTime(vxSb.vs_wtime, vxSb.vs_wutime)).AppendLine(); - if(vxSb.vs_clean != 0) sbInformation.AppendLine("Volume is dirty"); - - information = sbInformation.ToString(); - - 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() - { - return Errno.NotImplemented; - } - - public override Errno Mount(bool debug) - { - return Errno.NotImplemented; - } - - public override Errno Unmount() - { - return Errno.NotImplemented; - } - - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) - { - return Errno.NotImplemented; - } - - public override Errno GetAttributes(string path, ref FileAttributes attributes) - { - return Errno.NotImplemented; - } - - public override Errno ListXAttr(string path, ref List xattrs) - { - return Errno.NotImplemented; - } - - public override Errno GetXattr(string path, string xattr, ref byte[] buf) - { - return Errno.NotImplemented; - } - - public override Errno Read(string path, long offset, long size, ref byte[] buf) - { - return Errno.NotImplemented; - } - - public override Errno ReadDir(string path, ref List contents) - { - return Errno.NotImplemented; - } - - public override Errno StatFs(ref FileSystemInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) - { - return Errno.NotImplemented; - } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/XFS.cs b/DiscImageChef.Filesystems/XFS.cs index 29354655..b0d91bb8 100644 --- a/DiscImageChef.Filesystems/XFS.cs +++ b/DiscImageChef.Filesystems/XFS.cs @@ -43,67 +43,6 @@ namespace DiscImageChef.Filesystems { public class XFS : Filesystem { - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct XFS_Superblock - { - public uint magicnum; - public uint blocksize; - public ulong dblocks; - public ulong rblocks; - public ulong rextents; - public Guid uuid; - public ulong logstat; - public ulong rootino; - public ulong rbmino; - public ulong rsumino; - public uint rextsize; - public uint agblocks; - public uint agcount; - public uint rbmblocks; - public uint logblocks; - public ushort version; - public ushort sectsize; - public ushort inodesize; - public ushort inopblock; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] public byte[] fname; - public byte blocklog; - public byte sectlog; - public byte inodelog; - public byte inopblog; - public byte agblklog; - public byte rextslog; - public byte inprogress; - public byte imax_pct; - public ulong icount; - public ulong ifree; - public ulong fdblocks; - public ulong frextents; - public ulong uquotino; - public ulong gquotino; - public ushort qflags; - public byte flags; - public byte shared_vn; - public ulong inoalignmt; - public ulong unit; - public ulong width; - public byte dirblklog; - public byte logsectlog; - public ushort logsectsize; - public uint logsunit; - public uint features2; - public uint bad_features2; - public uint features_compat; - public uint features_ro_compat; - public uint features_incompat; - public uint features_log_incompat; - // This field is little-endian while rest of superblock is big-endian - public uint crc; - public uint spino_align; - public ulong pquotino; - public ulong lsn; - public Guid meta_uuid; - } - const uint XFS_MAGIC = 0x58465342; public XFS() @@ -178,8 +117,7 @@ namespace DiscImageChef.Filesystems return false; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { information = ""; if(imagePlugin.GetSectorSize() < 512) return; @@ -319,5 +257,66 @@ namespace DiscImageChef.Filesystems { return Errno.NotImplemented; } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct XFS_Superblock + { + public uint magicnum; + public uint blocksize; + public ulong dblocks; + public ulong rblocks; + public ulong rextents; + public Guid uuid; + public ulong logstat; + public ulong rootino; + public ulong rbmino; + public ulong rsumino; + public uint rextsize; + public uint agblocks; + public uint agcount; + public uint rbmblocks; + public uint logblocks; + public ushort version; + public ushort sectsize; + public ushort inodesize; + public ushort inopblock; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] public byte[] fname; + public byte blocklog; + public byte sectlog; + public byte inodelog; + public byte inopblog; + public byte agblklog; + public byte rextslog; + public byte inprogress; + public byte imax_pct; + public ulong icount; + public ulong ifree; + public ulong fdblocks; + public ulong frextents; + public ulong uquotino; + public ulong gquotino; + public ushort qflags; + public byte flags; + public byte shared_vn; + public ulong inoalignmt; + public ulong unit; + public ulong width; + public byte dirblklog; + public byte logsectlog; + public ushort logsectsize; + public uint logsunit; + public uint features2; + public uint bad_features2; + public uint features_compat; + public uint features_ro_compat; + public uint features_incompat; + public uint features_log_incompat; + // This field is little-endian while rest of superblock is big-endian + public uint crc; + public uint spino_align; + public ulong pquotino; + public ulong lsn; + public Guid meta_uuid; + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/ZFS.cs b/DiscImageChef.Filesystems/ZFS.cs index d33ee8b1..cdbd1e5e 100644 --- a/DiscImageChef.Filesystems/ZFS.cs +++ b/DiscImageChef.Filesystems/ZFS.cs @@ -66,164 +66,14 @@ namespace DiscImageChef.Filesystems const ulong ZEC_MAGIC = 0x0210DA7AB10C7A11; const ulong ZEC_CIGAM = 0x117A0CB17ADA1002; - struct ZIO_Checksum - { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public ulong[] word; - } - - /// - /// There is an empty ZIO at sector 16 or sector 31, with magic and checksum, to detect it is really ZFS I suppose. - /// - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct ZIO_Empty - { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 472)] public byte[] empty; - public ulong magic; - public ZIO_Checksum checksum; - } - // These parameters define how the nvlist is stored const byte NVS_LITTLE_ENDIAN = 1; const byte NVS_BIG_ENDIAN = 0; const byte NVS_NATIVE = 0; const byte NVS_XDR = 1; - /// - /// This structure indicates which encoding method and endianness is used to encode the nvlist - /// - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct NVS_Method - { - public byte encoding; - public byte endian; - public byte reserved1; - public byte reserved2; - } - - /// - /// This structure gives information about the encoded nvlist - /// - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct NVS_XDR_Header - { - public NVS_Method encodingAndEndian; - public uint version; - public uint flags; - } - - enum NVS_DataTypes : uint - { - DATA_TYPE_UNKNOWN = 0, - DATA_TYPE_BOOLEAN, - DATA_TYPE_BYTE, - DATA_TYPE_INT16, - DATA_TYPE_UINT16, - DATA_TYPE_INT32, - DATA_TYPE_UINT32, - DATA_TYPE_INT64, - DATA_TYPE_UINT64, - DATA_TYPE_STRING, - DATA_TYPE_BYTE_ARRAY, - DATA_TYPE_INT16_ARRAY, - DATA_TYPE_UINT16_ARRAY, - DATA_TYPE_INT32_ARRAY, - DATA_TYPE_UINT32_ARRAY, - DATA_TYPE_INT64_ARRAY, - DATA_TYPE_UINT64_ARRAY, - DATA_TYPE_STRING_ARRAY, - DATA_TYPE_HRTIME, - DATA_TYPE_NVLIST, - DATA_TYPE_NVLIST_ARRAY, - DATA_TYPE_BOOLEAN_VALUE, - DATA_TYPE_INT8, - DATA_TYPE_UINT8, - DATA_TYPE_BOOLEAN_ARRAY, - DATA_TYPE_INT8_ARRAY, - DATA_TYPE_UINT8_ARRAY, - DATA_TYPE_DOUBLE - } - - /// - /// This represent an encoded nvpair (an item of an nvlist) - /// - struct NVS_Item - { - /// - /// Size in bytes when encoded in XDR - /// - public uint encodedSize; - /// - /// Size in bytes when decoded - /// - public uint decodedSize; - /// - /// On disk, it is null-padded for alignment to 4 bytes and prepended by a 4 byte length indicator - /// - public string name; - /// - /// Data type - /// - public NVS_DataTypes dataType; - /// - /// How many elements are here - /// - public uint elements; - /// - /// On disk size is relative to and always aligned to 4 bytes - /// - public object value; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct DVA - { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public ulong[] word; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct SPA_BlockPointer - { - /// - /// Data virtual address - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public DVA[] dataVirtualAddress; - /// - /// Block properties - /// - public ulong properties; - /// - /// Reserved for future expansion - /// - public ulong[] padding; - /// - /// TXG when block was allocated - /// - public ulong birthTxg; - /// - /// Transaction group at birth - /// - public ulong birth; - /// - /// Fill count - /// - public ulong fill; - public ZIO_Checksum checksum; - } - const ulong UBERBLOCK_MAGIC = 0x00BAB10C; - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct ZFS_Uberblock - { - public ulong magic; - public ulong spaVersion; - public ulong lastTxg; - public ulong guidSum; - public ulong timestamp; - public SPA_BlockPointer mosPtr; - public ulong softwareVersion; - } - const uint ZFS_MAGIC = 0x58465342; public ZFS() @@ -270,8 +120,7 @@ namespace DiscImageChef.Filesystems return magic == ZEC_MAGIC || magic == ZEC_CIGAM; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { information = ""; if(imagePlugin.GetSectorSize() < 512) return; @@ -309,8 +158,7 @@ namespace DiscImageChef.Filesystems 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}"; + if(decodedNvList.TryGetValue("guid", out tmpObj)) XmlFsType.VolumeSerial = $"{(ulong)tmpObj.value}"; if(decodedNvList.TryGetValue("pool_guid", out tmpObj)) XmlFsType.VolumeSetIdentifier = $"{(ulong)tmpObj.value}"; } @@ -639,7 +487,8 @@ namespace DiscImageChef.Filesystems byte[] subListBytes = new byte[item.encodedSize - (offset - currOff)]; Array.Copy(nvlist, offset, subListBytes, 0, subListBytes.Length); - if(DecodeNvList(subListBytes, out Dictionary subList, true, littleEndian)) item.value = subList; + if(DecodeNvList(subListBytes, out Dictionary subList, true, littleEndian)) + item.value = subList; else goto default; offset = (int)(currOff + item.encodedSize); break; @@ -849,5 +698,155 @@ namespace DiscImageChef.Filesystems { return Errno.NotImplemented; } + + struct ZIO_Checksum + { + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public ulong[] word; + } + + /// + /// There is an empty ZIO at sector 16 or sector 31, with magic and checksum, to detect it is really ZFS I suppose. + /// + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct ZIO_Empty + { + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 472)] public byte[] empty; + public ulong magic; + public ZIO_Checksum checksum; + } + + /// + /// This structure indicates which encoding method and endianness is used to encode the nvlist + /// + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct NVS_Method + { + public byte encoding; + public byte endian; + public byte reserved1; + public byte reserved2; + } + + /// + /// This structure gives information about the encoded nvlist + /// + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct NVS_XDR_Header + { + public NVS_Method encodingAndEndian; + public uint version; + public uint flags; + } + + enum NVS_DataTypes : uint + { + DATA_TYPE_UNKNOWN = 0, + DATA_TYPE_BOOLEAN, + DATA_TYPE_BYTE, + DATA_TYPE_INT16, + DATA_TYPE_UINT16, + DATA_TYPE_INT32, + DATA_TYPE_UINT32, + DATA_TYPE_INT64, + DATA_TYPE_UINT64, + DATA_TYPE_STRING, + DATA_TYPE_BYTE_ARRAY, + DATA_TYPE_INT16_ARRAY, + DATA_TYPE_UINT16_ARRAY, + DATA_TYPE_INT32_ARRAY, + DATA_TYPE_UINT32_ARRAY, + DATA_TYPE_INT64_ARRAY, + DATA_TYPE_UINT64_ARRAY, + DATA_TYPE_STRING_ARRAY, + DATA_TYPE_HRTIME, + DATA_TYPE_NVLIST, + DATA_TYPE_NVLIST_ARRAY, + DATA_TYPE_BOOLEAN_VALUE, + DATA_TYPE_INT8, + DATA_TYPE_UINT8, + DATA_TYPE_BOOLEAN_ARRAY, + DATA_TYPE_INT8_ARRAY, + DATA_TYPE_UINT8_ARRAY, + DATA_TYPE_DOUBLE + } + + /// + /// This represent an encoded nvpair (an item of an nvlist) + /// + struct NVS_Item + { + /// + /// Size in bytes when encoded in XDR + /// + public uint encodedSize; + /// + /// Size in bytes when decoded + /// + public uint decodedSize; + /// + /// On disk, it is null-padded for alignment to 4 bytes and prepended by a 4 byte length indicator + /// + public string name; + /// + /// Data type + /// + public NVS_DataTypes dataType; + /// + /// How many elements are here + /// + public uint elements; + /// + /// On disk size is relative to and always aligned to 4 bytes + /// + public object value; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct DVA + { + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public ulong[] word; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct SPA_BlockPointer + { + /// + /// Data virtual address + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public DVA[] dataVirtualAddress; + /// + /// Block properties + /// + public ulong properties; + /// + /// Reserved for future expansion + /// + public ulong[] padding; + /// + /// TXG when block was allocated + /// + public ulong birthTxg; + /// + /// Transaction group at birth + /// + public ulong birth; + /// + /// Fill count + /// + public ulong fill; + public ZIO_Checksum checksum; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct ZFS_Uberblock + { + public ulong magic; + public ulong spaVersion; + public ulong lastTxg; + public ulong guidSum; + public ulong timestamp; + public SPA_BlockPointer mosPtr; + public ulong softwareVersion; + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/dump.cs b/DiscImageChef.Filesystems/dump.cs index b8562055..ccab6ab5 100644 --- a/DiscImageChef.Filesystems/dump.cs +++ b/DiscImageChef.Filesystems/dump.cs @@ -66,150 +66,39 @@ namespace DiscImageChef.Filesystems const int TP_BSIZE = 1024; /// - /// Dump tape header + /// Dump tape header /// const short TS_TAPE = 1; /// - /// Beginning of file record + /// Beginning of file record /// const short TS_INODE = 2; /// - /// Map of inodes on tape + /// Map of inodes on tape /// const short TS_BITS = 3; /// - /// Continuation of file record + /// Continuation of file record /// const short TS_ADDR = 4; /// - /// Map of inodes deleted since last dump + /// Map of inodes deleted since last dump /// const short TS_END = 5; /// - /// Inode bitmap + /// Inode bitmap /// const short TS_CLRI = 6; const short TS_ACL = 7; const short TS_PCL = 8; - // Old 16-bit format record - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct spcl16 - { - /// Record type - public short c_type; - /// Dump date - public int c_date; - /// Previous dump date - public int c_ddate; - /// Dump volume number - public short c_volume; - /// Logical block of this record - public int c_tapea; - /// Inode number - public ushort c_inumber; - /// Magic number - public ushort c_magic; - /// Record checksum - public int c_checksum; - // Unneeded for now - /* - struct dinode c_dinode; - int c_count; - char c_addr[BSIZE]; - */ - } - - // 32-bit AIX format record - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct spcl_aix - { - /// Record type - public int c_type; - /// Dump date - public int c_date; - /// Previous dump date - public int c_ddate; - /// Dump volume number - public int c_volume; - /// Logical block of this record - public int c_tapea; - public uint c_inumber; - public uint c_magic; - public int c_checksum; - // Unneeded for now - /* - public bsd_dinode bsd_c_dinode; - public int c_count; - public char c_addr[TP_NINDIR]; - public int xix_flag; - public dinode xix_dinode; - */ - } - const int TP_NINDIR = TP_BSIZE / 2; const int LBLSIZE = 16; const int NAMELEN = 64; - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct s_spcl - { - public int c_type; /* record type (see below) */ - public int c_date; /* date of this dump */ - public int c_ddate; /* date of previous dump */ - public int c_volume; /* dump volume number */ - public int c_tapea; /* logical block of this record */ - public uint c_inumber; /* number of inode */ - public int c_magic; /* magic number (see above) */ - public int c_checksum; /* record checksum */ - public dinode c_dinode; /* ownership and mode of inode */ - public int c_count; /* number of valid c_addr entries */ - [MarshalAs(UnmanagedType.ByValArray, SizeConst = TP_NINDIR)] - public byte[] c_addr; /* 1 => data; 0 => hole in inode */ - [MarshalAs(UnmanagedType.ByValArray, SizeConst = LBLSIZE)] public byte[] c_label; /* dump label */ - public int c_level; /* level of this dump */ - [MarshalAs(UnmanagedType.ByValArray, SizeConst = NAMELEN)] - public byte[] c_filesys; /* name of dumpped file system */ - [MarshalAs(UnmanagedType.ByValArray, SizeConst = NAMELEN)] public byte[] c_dev; /* name of dumpped device */ - [MarshalAs(UnmanagedType.ByValArray, SizeConst = NAMELEN)] public byte[] c_host; /* name of dumpped host */ - public int c_flags; /* additional information */ - public int c_firstrec; /* first record on volume */ - public long c_ndate; /* date of this dump */ - public long c_nddate; /* date of previous dump */ - public long c_ntapea; /* logical block of this record */ - public long c_nfirstrec; /* first record on volume */ - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public int[] c_spare; /* reserved for future uses */ - } - const int NDADDR = 12; const int NIADDR = 3; - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct dinode - { - public ushort di_mode; /* 0: IFMT, permissions; see below. */ - public short di_nlink; /* 2: File link count. */ - public int inumber; /* 4: Lfs: inode number. */ - public ulong di_size; /* 8: File byte count. */ - public int di_atime; /* 16: Last access time. */ - public int di_atimensec; /* 20: Last access time. */ - public int di_mtime; /* 24: Last modified time. */ - public int di_mtimensec; /* 28: Last modified time. */ - public int di_ctime; /* 32: Last inode change time. */ - public int di_ctimensec; /* 36: Last inode change time. */ - [MarshalAs(UnmanagedType.ByValArray, SizeConst = NDADDR)] - public ufs_daddr_t[] di_db; /* 40: Direct disk blocks. */ - [MarshalAs(UnmanagedType.ByValArray, SizeConst = NIADDR)] - public ufs_daddr_t[] di_ib; /* 88: Indirect disk blocks. */ - public uint di_flags; /* 100: Status flags (chflags). */ - public uint di_blocks; /* 104: Blocks actually held. */ - public int di_gen; /* 108: Generation number. */ - public uint di_uid; /* 112: File owner. */ - public uint di_gid; /* 116: File group. */ - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] - public int[] di_spare; /* 120: Reserved; currently unused */ - } - public dump() { Name = "dump(8) Plugin"; @@ -272,8 +161,7 @@ namespace DiscImageChef.Filesystems newHdr.c_magic == NFS_CIGAM || newHdr.c_magic == UFS2_MAGIC || newHdr.c_magic == UFS2_CIGAM; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { information = ""; if(imagePlugin.GetSectorSize() < 512) return; @@ -482,5 +370,116 @@ namespace DiscImageChef.Filesystems { return Errno.NotImplemented; } + + // Old 16-bit format record + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct spcl16 + { + /// Record type + public short c_type; + /// Dump date + public int c_date; + /// Previous dump date + public int c_ddate; + /// Dump volume number + public short c_volume; + /// Logical block of this record + public int c_tapea; + /// Inode number + public ushort c_inumber; + /// Magic number + public ushort c_magic; + /// Record checksum + public int c_checksum; + // Unneeded for now + /* + struct dinode c_dinode; + int c_count; + char c_addr[BSIZE]; + */ + } + + // 32-bit AIX format record + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct spcl_aix + { + /// Record type + public int c_type; + /// Dump date + public int c_date; + /// Previous dump date + public int c_ddate; + /// Dump volume number + public int c_volume; + /// Logical block of this record + public int c_tapea; + public uint c_inumber; + public uint c_magic; + public int c_checksum; + // Unneeded for now + /* + public bsd_dinode bsd_c_dinode; + public int c_count; + public char c_addr[TP_NINDIR]; + public int xix_flag; + public dinode xix_dinode; + */ + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct s_spcl + { + public int c_type; /* record type (see below) */ + public int c_date; /* date of this dump */ + public int c_ddate; /* date of previous dump */ + public int c_volume; /* dump volume number */ + public int c_tapea; /* logical block of this record */ + public uint c_inumber; /* number of inode */ + public int c_magic; /* magic number (see above) */ + public int c_checksum; /* record checksum */ + public dinode c_dinode; /* ownership and mode of inode */ + public int c_count; /* number of valid c_addr entries */ + [MarshalAs(UnmanagedType.ByValArray, SizeConst = TP_NINDIR)] + public byte[] c_addr; /* 1 => data; 0 => hole in inode */ + [MarshalAs(UnmanagedType.ByValArray, SizeConst = LBLSIZE)] public byte[] c_label; /* dump label */ + public int c_level; /* level of this dump */ + [MarshalAs(UnmanagedType.ByValArray, SizeConst = NAMELEN)] + public byte[] c_filesys; /* name of dumpped file system */ + [MarshalAs(UnmanagedType.ByValArray, SizeConst = NAMELEN)] public byte[] c_dev; /* name of dumpped device */ + [MarshalAs(UnmanagedType.ByValArray, SizeConst = NAMELEN)] public byte[] c_host; /* name of dumpped host */ + public int c_flags; /* additional information */ + public int c_firstrec; /* first record on volume */ + public long c_ndate; /* date of this dump */ + public long c_nddate; /* date of previous dump */ + public long c_ntapea; /* logical block of this record */ + public long c_nfirstrec; /* first record on volume */ + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public int[] c_spare; /* reserved for future uses */ + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct dinode + { + public ushort di_mode; /* 0: IFMT, permissions; see below. */ + public short di_nlink; /* 2: File link count. */ + public int inumber; /* 4: Lfs: inode number. */ + public ulong di_size; /* 8: File byte count. */ + public int di_atime; /* 16: Last access time. */ + public int di_atimensec; /* 20: Last access time. */ + public int di_mtime; /* 24: Last modified time. */ + public int di_mtimensec; /* 28: Last modified time. */ + public int di_ctime; /* 32: Last inode change time. */ + public int di_ctimensec; /* 36: Last inode change time. */ + [MarshalAs(UnmanagedType.ByValArray, SizeConst = NDADDR)] + public ufs_daddr_t[] di_db; /* 40: Direct disk blocks. */ + [MarshalAs(UnmanagedType.ByValArray, SizeConst = NIADDR)] + public ufs_daddr_t[] di_ib; /* 88: Indirect disk blocks. */ + public uint di_flags; /* 100: Status flags (chflags). */ + public uint di_blocks; /* 104: Blocks actually held. */ + public int di_gen; /* 108: Generation number. */ + public uint di_uid; /* 112: File owner. */ + public uint di_gid; /* 116: File group. */ + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public int[] di_spare; /* 120: Reserved; currently unused */ + } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/exFAT.cs b/DiscImageChef.Filesystems/exFAT.cs index a27c2577..09d0739e 100644 --- a/DiscImageChef.Filesystems/exFAT.cs +++ b/DiscImageChef.Filesystems/exFAT.cs @@ -44,6 +44,10 @@ namespace DiscImageChef.Filesystems // Information from https://www.sans.org/reading-room/whitepapers/forensics/reverse-engineering-microsoft-exfat-file-system-33274 public class exFAT : Filesystem { + readonly Guid OEM_FLASH_PARAMETER_GUID = new Guid("0A0C7E46-3399-4021-90C8-FA6D389C4BA2"); + + readonly byte[] Signature = {0x45, 0x58, 0x46, 0x41, 0x54, 0x20, 0x20, 0x20}; + public exFAT() { Name = "Microsoft Extended File Allocation Table"; @@ -96,7 +100,8 @@ namespace DiscImageChef.Filesystems byte[] parametersSector = imagePlugin.ReadSector(9 + partition.Start); IntPtr parametersPtr = Marshal.AllocHGlobal(512); Marshal.Copy(parametersSector, 0, parametersPtr, 512); - OemParameterTable 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); @@ -155,8 +160,65 @@ namespace DiscImageChef.Filesystems information = sb.ToString(); } - readonly byte[] Signature = {0x45, 0x58, 0x46, 0x41, 0x54, 0x20, 0x20, 0x20}; - readonly Guid OEM_FLASH_PARAMETER_GUID = new Guid("0A0C7E46-3399-4021-90C8-FA6D389C4BA2"); + public override Errno GetAttributes(string path, ref FileAttributes attributes) + { + throw new NotImplementedException(); + } + + public override Errno GetXattr(string path, string xattr, ref byte[] buf) + { + throw new NotImplementedException(); + } + + public override Errno ListXAttr(string path, ref List xattrs) + { + throw new NotImplementedException(); + } + + public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + { + throw new NotImplementedException(); + } + + public override Errno Mount() + { + throw new NotImplementedException(); + } + + public override Errno Mount(bool debug) + { + throw new NotImplementedException(); + } + + public override Errno Read(string path, long offset, long size, ref byte[] buf) + { + throw new NotImplementedException(); + } + + public override Errno ReadDir(string path, ref List contents) + { + throw new NotImplementedException(); + } + + public override Errno ReadLink(string path, ref string dest) + { + throw new NotImplementedException(); + } + + public override Errno Stat(string path, ref FileEntryInfo stat) + { + throw new NotImplementedException(); + } + + public override Errno StatFs(ref FileSystemInfo stat) + { + throw new NotImplementedException(); + } + + public override Errno Unmount() + { + throw new NotImplementedException(); + } [Flags] enum VolumeFlags : ushort @@ -219,65 +281,5 @@ namespace DiscImageChef.Filesystems { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] public uint[] checksum; } - - public override Errno GetAttributes(string path, ref FileAttributes attributes) - { - throw new NotImplementedException(); - } - - public override Errno GetXattr(string path, string xattr, ref byte[] buf) - { - throw new NotImplementedException(); - } - - public override Errno ListXAttr(string path, ref List xattrs) - { - throw new NotImplementedException(); - } - - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) - { - throw new NotImplementedException(); - } - - public override Errno Mount() - { - throw new NotImplementedException(); - } - - public override Errno Mount(bool debug) - { - throw new NotImplementedException(); - } - - public override Errno Read(string path, long offset, long size, ref byte[] buf) - { - throw new NotImplementedException(); - } - - public override Errno ReadDir(string path, ref List contents) - { - throw new NotImplementedException(); - } - - public override Errno ReadLink(string path, ref string dest) - { - throw new NotImplementedException(); - } - - public override Errno Stat(string path, ref FileEntryInfo stat) - { - throw new NotImplementedException(); - } - - public override Errno StatFs(ref FileSystemInfo stat) - { - throw new NotImplementedException(); - } - - public override Errno Unmount() - { - throw new NotImplementedException(); - } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/ext2FS.cs b/DiscImageChef.Filesystems/ext2FS.cs index be46ca74..49e6e8fd 100644 --- a/DiscImageChef.Filesystems/ext2FS.cs +++ b/DiscImageChef.Filesystems/ext2FS.cs @@ -46,6 +46,122 @@ namespace DiscImageChef.Filesystems { const int SB_POS = 0x400; + /// + /// Same magic for ext2, ext3 and ext4 + /// + const ushort EXT2_MAGIC = 0xEF53; + + const ushort EXT2_MAGIC_OLD = 0xEF51; + + // ext? filesystem states + /// Cleanly-unmounted volume + const ushort EXT2_VALID_FS = 0x0001; + /// Dirty volume + const ushort EXT2_ERROR_FS = 0x0002; + /// Recovering orphan files + const ushort EXT3_ORPHAN_FS = 0x0004; + + // ext? default mount flags + /// Enable debugging messages + const uint EXT2_DEFM_DEBUG = 0x000001; + /// Emulates BSD behaviour on new file creation + const uint EXT2_DEFM_BSDGROUPS = 0x000002; + /// Enable user xattrs + const uint EXT2_DEFM_XATTR_USER = 0x000004; + /// Enable POSIX ACLs + const uint EXT2_DEFM_ACL = 0x000008; + /// Use 16bit UIDs + const uint EXT2_DEFM_UID16 = 0x000010; + /// Journal data mode + const uint EXT3_DEFM_JMODE_DATA = 0x000040; + /// Journal ordered mode + const uint EXT3_DEFM_JMODE_ORDERED = 0x000080; + /// Journal writeback mode + const uint EXT3_DEFM_JMODE_WBACK = 0x000100; + + // Behaviour on errors + /// Continue execution + const ushort EXT2_ERRORS_CONTINUE = 1; + /// Remount fs read-only + const ushort EXT2_ERRORS_RO = 2; + /// Panic + const ushort EXT2_ERRORS_PANIC = 3; + + // OS codes + const uint EXT2_OS_LINUX = 0; + const uint EXT2_OS_HURD = 1; + const uint EXT2_OS_MASIX = 2; + const uint EXT2_OS_FREEBSD = 3; + const uint EXT2_OS_LITES = 4; + + // Revision levels + /// The good old (original) format + const uint EXT2_GOOD_OLD_REV = 0; + /// V2 format w/ dynamic inode sizes + const uint EXT2_DYNAMIC_REV = 1; + + // Compatible features + /// Pre-allocate directories + const uint EXT2_FEATURE_COMPAT_DIR_PREALLOC = 0x00000001; + /// imagic inodes ? + const uint EXT2_FEATURE_COMPAT_IMAGIC_INODES = 0x00000002; + /// Has journal (it's ext3) + const uint EXT3_FEATURE_COMPAT_HAS_JOURNAL = 0x00000004; + /// EA blocks + const uint EXT2_FEATURE_COMPAT_EXT_ATTR = 0x00000008; + /// Online filesystem resize reservations + const uint EXT2_FEATURE_COMPAT_RESIZE_INO = 0x00000010; + /// Can use hashed indexes on directories + const uint EXT2_FEATURE_COMPAT_DIR_INDEX = 0x00000020; + + // Read-only compatible features + /// Reduced number of superblocks + const uint EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER = 0x00000001; + /// Can have files bigger than 2GiB + const uint EXT2_FEATURE_RO_COMPAT_LARGE_FILE = 0x00000002; + /// Use B-Tree for directories + const uint EXT2_FEATURE_RO_COMPAT_BTREE_DIR = 0x00000004; + /// Can have files bigger than 2TiB *ext4* + const uint EXT4_FEATURE_RO_COMPAT_HUGE_FILE = 0x00000008; + /// Group descriptor checksums and sparse inode table *ext4* + const uint EXT4_FEATURE_RO_COMPAT_GDT_CSUM = 0x00000010; + /// More than 32000 directory entries *ext4* + const uint EXT4_FEATURE_RO_COMPAT_DIR_NLINK = 0x00000020; + /// Nanosecond timestamps and creation time *ext4* + const uint EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE = 0x00000040; + + // Incompatible features + /// Uses compression + const uint EXT2_FEATURE_INCOMPAT_COMPRESSION = 0x00000001; + /// Filetype in directory entries + const uint EXT2_FEATURE_INCOMPAT_FILETYPE = 0x00000002; + /// Journal needs recovery *ext3* + const uint EXT3_FEATURE_INCOMPAT_RECOVER = 0x00000004; + /// Has journal on another device *ext3* + const uint EXT3_FEATURE_INCOMPAT_JOURNAL_DEV = 0x00000008; + /// Reduced block group backups + const uint EXT2_FEATURE_INCOMPAT_META_BG = 0x00000010; + /// Volume use extents *ext4* + const uint EXT4_FEATURE_INCOMPAT_EXTENTS = 0x00000040; + /// Supports volumes bigger than 2^32 blocks *ext4* + const uint EXT4_FEATURE_INCOMPAT_64BIT = 0x00000080; + /// Multi-mount protection *ext4* + const uint EXT4_FEATURE_INCOMPAT_MMP = 0x00000100; + /// Flexible block group metadata location *ext4* + const uint EXT4_FEATURE_INCOMPAT_FLEX_BG = 0x00000200; + /// EA in inode *ext4* + const uint EXT4_FEATURE_INCOMPAT_EA_INODE = 0x00000400; + /// Data can reside in directory entry *ext4* + const uint EXT4_FEATURE_INCOMPAT_DIRDATA = 0x00001000; + + // Miscellaneous filesystem flags + /// Signed dirhash in use + const uint EXT2_FLAGS_SIGNED_HASH = 0x00000001; + /// Unsigned dirhash in use + const uint EXT2_FLAGS_UNSIGNED_HASH = 0x00000002; + /// Testing development code + const uint EXT2_FLAGS_TEST_FILESYS = 0x00000004; + public ext2FS() { Name = "Linux extended Filesystem 2, 3 and 4"; @@ -87,8 +203,7 @@ namespace DiscImageChef.Filesystems return magic == EXT2_MAGIC || magic == EXT2_MAGIC_OLD; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { information = ""; @@ -115,7 +230,8 @@ namespace DiscImageChef.Filesystems XmlFsType = new FileSystemType(); - switch(supblk.magic) { + switch(supblk.magic) + { case EXT2_MAGIC_OLD: sb.AppendLine("ext2 (old) filesystem"); XmlFsType.Type = "ext2"; @@ -123,12 +239,14 @@ namespace DiscImageChef.Filesystems 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; + (supblk.ftr_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) == + EXT3_FEATURE_INCOMPAT_JOURNAL_DEV; if((supblk.ftr_ro_compat & EXT4_FEATURE_RO_COMPAT_HUGE_FILE) == EXT4_FEATURE_RO_COMPAT_HUGE_FILE || (supblk.ftr_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM) == EXT4_FEATURE_RO_COMPAT_GDT_CSUM || (supblk.ftr_ro_compat & EXT4_FEATURE_RO_COMPAT_DIR_NLINK) == EXT4_FEATURE_RO_COMPAT_DIR_NLINK || - (supblk.ftr_ro_compat & EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE) == EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE || + (supblk.ftr_ro_compat & EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE) == + EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE || (supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_64BIT) == EXT4_FEATURE_INCOMPAT_64BIT || (supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_MMP) == EXT4_FEATURE_INCOMPAT_MMP || (supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_FLEX_BG) == EXT4_FEATURE_INCOMPAT_FLEX_BG || @@ -525,15 +643,68 @@ namespace DiscImageChef.Filesystems information = sb.ToString(); } - /// - /// Same magic for ext2, ext3 and ext4 - /// - const ushort EXT2_MAGIC = 0xEF53; + public override Errno Mount() + { + return Errno.NotImplemented; + } - const ushort EXT2_MAGIC_OLD = 0xEF51; + public override Errno Mount(bool debug) + { + return Errno.NotImplemented; + } + + public override Errno Unmount() + { + return Errno.NotImplemented; + } + + public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) + { + return Errno.NotImplemented; + } + + public override Errno GetAttributes(string path, ref FileAttributes attributes) + { + return Errno.NotImplemented; + } + + public override Errno ListXAttr(string path, ref List xattrs) + { + return Errno.NotImplemented; + } + + public override Errno GetXattr(string path, string xattr, ref byte[] buf) + { + return Errno.NotImplemented; + } + + public override Errno Read(string path, long offset, long size, ref byte[] buf) + { + return Errno.NotImplemented; + } + + public override Errno ReadDir(string path, ref List contents) + { + return Errno.NotImplemented; + } + + public override Errno StatFs(ref FileSystemInfo stat) + { + return Errno.NotImplemented; + } + + public override Errno Stat(string path, ref FileEntryInfo stat) + { + return Errno.NotImplemented; + } + + public override Errno ReadLink(string path, ref string dest) + { + return Errno.NotImplemented; + } /// - /// ext2/3/4 superblock + /// ext2/3/4 superblock /// [StructLayout(LayoutKind.Sequential, Pack = 1)] [SuppressMessage("ReSharper", "InconsistentNaming")] @@ -752,174 +923,5 @@ namespace DiscImageChef.Filesystems /// crc32c(superblock) public uint checksum; } - - // ext? filesystem states - /// Cleanly-unmounted volume - const ushort EXT2_VALID_FS = 0x0001; - /// Dirty volume - const ushort EXT2_ERROR_FS = 0x0002; - /// Recovering orphan files - const ushort EXT3_ORPHAN_FS = 0x0004; - - // ext? default mount flags - /// Enable debugging messages - const uint EXT2_DEFM_DEBUG = 0x000001; - /// Emulates BSD behaviour on new file creation - const uint EXT2_DEFM_BSDGROUPS = 0x000002; - /// Enable user xattrs - const uint EXT2_DEFM_XATTR_USER = 0x000004; - /// Enable POSIX ACLs - const uint EXT2_DEFM_ACL = 0x000008; - /// Use 16bit UIDs - const uint EXT2_DEFM_UID16 = 0x000010; - /// Journal data mode - const uint EXT3_DEFM_JMODE_DATA = 0x000040; - /// Journal ordered mode - const uint EXT3_DEFM_JMODE_ORDERED = 0x000080; - /// Journal writeback mode - const uint EXT3_DEFM_JMODE_WBACK = 0x000100; - - // Behaviour on errors - /// Continue execution - const ushort EXT2_ERRORS_CONTINUE = 1; - /// Remount fs read-only - const ushort EXT2_ERRORS_RO = 2; - /// Panic - const ushort EXT2_ERRORS_PANIC = 3; - - // OS codes - const uint EXT2_OS_LINUX = 0; - const uint EXT2_OS_HURD = 1; - const uint EXT2_OS_MASIX = 2; - const uint EXT2_OS_FREEBSD = 3; - const uint EXT2_OS_LITES = 4; - - // Revision levels - /// The good old (original) format - const uint EXT2_GOOD_OLD_REV = 0; - /// V2 format w/ dynamic inode sizes - const uint EXT2_DYNAMIC_REV = 1; - - // Compatible features - /// Pre-allocate directories - const uint EXT2_FEATURE_COMPAT_DIR_PREALLOC = 0x00000001; - /// imagic inodes ? - const uint EXT2_FEATURE_COMPAT_IMAGIC_INODES = 0x00000002; - /// Has journal (it's ext3) - const uint EXT3_FEATURE_COMPAT_HAS_JOURNAL = 0x00000004; - /// EA blocks - const uint EXT2_FEATURE_COMPAT_EXT_ATTR = 0x00000008; - /// Online filesystem resize reservations - const uint EXT2_FEATURE_COMPAT_RESIZE_INO = 0x00000010; - /// Can use hashed indexes on directories - const uint EXT2_FEATURE_COMPAT_DIR_INDEX = 0x00000020; - - // Read-only compatible features - /// Reduced number of superblocks - const uint EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER = 0x00000001; - /// Can have files bigger than 2GiB - const uint EXT2_FEATURE_RO_COMPAT_LARGE_FILE = 0x00000002; - /// Use B-Tree for directories - const uint EXT2_FEATURE_RO_COMPAT_BTREE_DIR = 0x00000004; - /// Can have files bigger than 2TiB *ext4* - const uint EXT4_FEATURE_RO_COMPAT_HUGE_FILE = 0x00000008; - /// Group descriptor checksums and sparse inode table *ext4* - const uint EXT4_FEATURE_RO_COMPAT_GDT_CSUM = 0x00000010; - /// More than 32000 directory entries *ext4* - const uint EXT4_FEATURE_RO_COMPAT_DIR_NLINK = 0x00000020; - /// Nanosecond timestamps and creation time *ext4* - const uint EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE = 0x00000040; - - // Incompatible features - /// Uses compression - const uint EXT2_FEATURE_INCOMPAT_COMPRESSION = 0x00000001; - /// Filetype in directory entries - const uint EXT2_FEATURE_INCOMPAT_FILETYPE = 0x00000002; - /// Journal needs recovery *ext3* - const uint EXT3_FEATURE_INCOMPAT_RECOVER = 0x00000004; - /// Has journal on another device *ext3* - const uint EXT3_FEATURE_INCOMPAT_JOURNAL_DEV = 0x00000008; - /// Reduced block group backups - const uint EXT2_FEATURE_INCOMPAT_META_BG = 0x00000010; - /// Volume use extents *ext4* - const uint EXT4_FEATURE_INCOMPAT_EXTENTS = 0x00000040; - /// Supports volumes bigger than 2^32 blocks *ext4* - const uint EXT4_FEATURE_INCOMPAT_64BIT = 0x00000080; - /// Multi-mount protection *ext4* - const uint EXT4_FEATURE_INCOMPAT_MMP = 0x00000100; - /// Flexible block group metadata location *ext4* - const uint EXT4_FEATURE_INCOMPAT_FLEX_BG = 0x00000200; - /// EA in inode *ext4* - const uint EXT4_FEATURE_INCOMPAT_EA_INODE = 0x00000400; - /// Data can reside in directory entry *ext4* - const uint EXT4_FEATURE_INCOMPAT_DIRDATA = 0x00001000; - - // Miscellaneous filesystem flags - /// Signed dirhash in use - const uint EXT2_FLAGS_SIGNED_HASH = 0x00000001; - /// Unsigned dirhash in use - const uint EXT2_FLAGS_UNSIGNED_HASH = 0x00000002; - /// Testing development code - const uint EXT2_FLAGS_TEST_FILESYS = 0x00000004; - - public override Errno Mount() - { - return Errno.NotImplemented; - } - - public override Errno Mount(bool debug) - { - return Errno.NotImplemented; - } - - public override Errno Unmount() - { - return Errno.NotImplemented; - } - - public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock) - { - return Errno.NotImplemented; - } - - public override Errno GetAttributes(string path, ref FileAttributes attributes) - { - return Errno.NotImplemented; - } - - public override Errno ListXAttr(string path, ref List xattrs) - { - return Errno.NotImplemented; - } - - public override Errno GetXattr(string path, string xattr, ref byte[] buf) - { - return Errno.NotImplemented; - } - - public override Errno Read(string path, long offset, long size, ref byte[] buf) - { - return Errno.NotImplemented; - } - - public override Errno ReadDir(string path, ref List contents) - { - return Errno.NotImplemented; - } - - public override Errno StatFs(ref FileSystemInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno Stat(string path, ref FileEntryInfo stat) - { - return Errno.NotImplemented; - } - - public override Errno ReadLink(string path, ref string dest) - { - return Errno.NotImplemented; - } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/extFS.cs b/DiscImageChef.Filesystems/extFS.cs index 2e23ce5c..806390f1 100644 --- a/DiscImageChef.Filesystems/extFS.cs +++ b/DiscImageChef.Filesystems/extFS.cs @@ -45,6 +45,11 @@ namespace DiscImageChef.Filesystems { const int SB_POS = 0x400; + /// + /// ext superblock magic + /// + const ushort EXT_MAGIC = 0x137D; + public extFS() { Name = "Linux extended Filesystem"; @@ -84,8 +89,7 @@ namespace DiscImageChef.Filesystems return magic == EXT_MAGIC; } - public override void GetInformation(ImagePlugin imagePlugin, Partition partition, - out string information) + public override void GetInformation(ImagePlugin imagePlugin, Partition partition, out string information) { information = ""; @@ -115,7 +119,6 @@ namespace DiscImageChef.Filesystems maxsize = BitConverter.ToUInt32(sbSector, 0x020) }; - sb.AppendLine("ext filesystem"); sb.AppendFormat("{0} zones on volume", extSb.zones); sb.AppendFormat("{0} free blocks ({1} bytes)", extSb.freecountblk, extSb.freecountblk * 1024); @@ -139,49 +142,6 @@ namespace DiscImageChef.Filesystems information = sb.ToString(); } - /// - /// ext superblock magic - /// - const ushort EXT_MAGIC = 0x137D; - - /// - /// ext superblock - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - struct extFSSuperBlock - { - /// 0x000, inodes on volume - public uint inodes; - /// 0x004, zones on volume - public uint zones; - /// 0x008, first free block - public uint firstfreeblk; - /// 0x00C, free blocks count - public uint freecountblk; - /// 0x010, first free inode - public uint firstfreeind; - /// 0x014, free inodes count - public uint freecountind; - /// 0x018, first data zone - public uint firstdatazone; - /// 0x01C, log zone size - public uint logzonesize; - /// 0x020, max zone size - public uint maxsize; - /// 0x024, reserved - public uint reserved1; - /// 0x028, reserved - public uint reserved2; - /// 0x02C, reserved - public uint reserved3; - /// 0x030, reserved - public uint reserved4; - /// 0x034, reserved - public uint reserved5; - /// 0x038, 0x137D (little endian) - public ushort magic; - } - public override Errno Mount() { return Errno.NotImplemented; @@ -241,5 +201,43 @@ namespace DiscImageChef.Filesystems { return Errno.NotImplemented; } + + /// + /// ext superblock + /// + [SuppressMessage("ReSharper", "InconsistentNaming")] + struct extFSSuperBlock + { + /// 0x000, inodes on volume + public uint inodes; + /// 0x004, zones on volume + public uint zones; + /// 0x008, first free block + public uint firstfreeblk; + /// 0x00C, free blocks count + public uint freecountblk; + /// 0x010, first free inode + public uint firstfreeind; + /// 0x014, free inodes count + public uint freecountind; + /// 0x018, first data zone + public uint firstdatazone; + /// 0x01C, log zone size + public uint logzonesize; + /// 0x020, max zone size + public uint maxsize; + /// 0x024, reserved + public uint reserved1; + /// 0x028, reserved + public uint reserved2; + /// 0x02C, reserved + public uint reserved3; + /// 0x030, reserved + public uint reserved4; + /// 0x034, reserved + public uint reserved5; + /// 0x038, 0x137D (little endian) + public ushort magic; + } } } \ No newline at end of file