diff --git a/DiscImageChef.Partitions/VTOC.cs b/DiscImageChef.Partitions/VTOC.cs index b8d9eb2b5..7e833a1c4 100644 --- a/DiscImageChef.Partitions/VTOC.cs +++ b/DiscImageChef.Partitions/VTOC.cs @@ -34,14 +34,19 @@ using System; using System.Collections.Generic; using System.Runtime.InteropServices; using DiscImageChef.CommonTypes; +using DiscImageChef.Console; using DiscImageChef.ImagePlugins; namespace DiscImageChef.PartPlugins { public class VTOC : PartPlugin { - public const uint UNIXDiskLabel_MAGIC = 0xCA5E600D; - public const uint UNIXVTOC_MAGIC = 0x600DDEEE; + const uint PD_MAGIC = 0xCA5E600D; + const uint VTOC_SANE = 0x600DDEEE; + const uint PD_CIGAM = 0x0D605ECA; + const uint VTOC_ENAS = 0xEEDE0D60; + const int V_NUMPAR = 16; + const uint XPDVERS = 3; /* 1st version of extended pdinfo */ public VTOC() { @@ -53,8 +58,9 @@ namespace DiscImageChef.PartPlugins { partitions = new List(); - uint magic; - byte[] unix_dl_sector = null; + uint magic = 0; + ulong pdloc = 0; + byte[] pdsector = null; bool magic_found = false; foreach(ulong i in new ulong[] {0, 1, 8, 29}) @@ -62,11 +68,13 @@ namespace DiscImageChef.PartPlugins if(i + sectorOffset >= imagePlugin.GetSectors()) break; - unix_dl_sector = imagePlugin.ReadSector(i + sectorOffset); - magic = BitConverter.ToUInt32(unix_dl_sector, 4); - if(magic == UNIXDiskLabel_MAGIC) + pdsector = imagePlugin.ReadSector(i + sectorOffset); + magic = BitConverter.ToUInt32(pdsector, 4); + DicConsole.DebugWriteLine("VTOC plugin", "sanity at {0} is 0x{1:X8} (should be 0x{2:X8} or 0x{3:X8})", i + sectorOffset, magic, PD_MAGIC, PD_CIGAM); + if(magic == PD_MAGIC || magic == PD_CIGAM) { magic_found = true; + pdloc = i; break; } } @@ -74,261 +82,484 @@ namespace DiscImageChef.PartPlugins if(!magic_found) return false; - UNIXDiskLabel dl = new UNIXDiskLabel(); - UNIXVTOC vtoc = new UNIXVTOC(); // old/new - bool isNewDL = false; - int vtocoffset = 0; - ulong counter = 0; + PDInfo pd; + PDInfoOld pdold; + GCHandle handle; - vtoc.magic = BitConverter.ToUInt32(unix_dl_sector, 172); - if(vtoc.magic == UNIXVTOC_MAGIC) + if(magic == PD_MAGIC) { - isNewDL = true; - vtocoffset = 72; + handle = GCHandle.Alloc(pdsector, GCHandleType.Pinned); + pd = (PDInfo)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(PDInfo)); + pdold = (PDInfoOld)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(PDInfoOld)); + handle.Free(); } else { - vtoc.magic = BitConverter.ToUInt32(unix_dl_sector, 172); - if(vtoc.magic != UNIXDiskLabel_MAGIC) + pd = BigEndianMarshal.ByteArrayToStructureBigEndian(pdsector); + pdold = BigEndianMarshal.ByteArrayToStructureBigEndian(pdsector); + } + + DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.driveid = {0}", pd.driveid); + DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.sanity = 0x{0:X8} (should be 0x{1:X8})", pd.sanity, PD_MAGIC); + DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.version = {0}", pd.version); + DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.serial = \"{0}\"", StringHandlers.CToString(pd.serial)); + DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.cyls = {0}", pd.cyls); + DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.tracks = {0}", pd.tracks); + DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.sectors = {0}", pd.sectors); + DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.bytes = {0}", pd.bytes); + DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.logicalst = {0}", pd.logicalst); + DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.errlogst = {0}", pd.errlogst); + DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.errlogsz = {0}", pd.errlogsz); + DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.mfgst = {0}", pd.mfgst); + DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.mfgsz = {0}", pd.mfgsz); + DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.defectst = {0}", pd.defectst); + DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.defectsz = {0}", pd.defectsz); + DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.relno = {0}", pd.relno); + DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.relst = {0}", pd.relst); + DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.relsz = {0}", pd.relsz); + DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.relnext = {0}", pd.relnext); + DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.allcstrt = {0}", pdold.allcstrt); + DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.allcend = {0}", pdold.allcend); + DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.vtoc_ptr = {0}", pd.vtoc_ptr); + DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.vtoc_len = {0}", pd.vtoc_len); + DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.vtoc_pad = {0}", pd.vtoc_pad); + DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.alt_ptr = {0}", pd.alt_ptr); + DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.alt_len = {0}", pd.alt_len); + DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.pcyls = {0}", pd.pcyls); + DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.ptracks = {0}", pd.ptracks); + DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.psectors = {0}", pd.psectors); + DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.pbytes = {0}", pd.pbytes); + DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.secovhd = {0}", pd.secovhd); + DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.interleave = {0}", pd.interleave); + DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.skew = {0}", pd.skew); + DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.pad[0] = {0}", pd.pad[0]); + DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.pad[1] = {0}", pd.pad[1]); + DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.pad[2] = {0}", pd.pad[2]); + DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.pad[3] = {0}", pd.pad[3]); + DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.pad[4] = {0}", pd.pad[4]); + DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.pad[5] = {0}", pd.pad[5]); + DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.pad[6] = {0}", pd.pad[6]); + DicConsole.DebugWriteLine("VTOC plugin", "pdinfo.pad[7] = {0}", pd.pad[7]); + + magic_found = false; + bool useOld = false; + byte[] vtocsector = imagePlugin.ReadSector(pdloc + sectorOffset + 1); + vtoc vtoc = new vtoc(); + vtocold vtocOld = new vtocold(); + magic = BitConverter.ToUInt32(vtocsector, 0); + + if(magic == VTOC_SANE || magic == VTOC_ENAS) + { + magic_found = true; + useOld = false; + DicConsole.DebugWriteLine("VTOC plugin", "New VTOC found at {0}", pdloc + sectorOffset + 1); + if(magic == VTOC_SANE) { - return false; + handle = GCHandle.Alloc(vtocsector, GCHandleType.Pinned); + vtoc = (vtoc)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(vtoc)); + handle.Free(); } - } - - dl.version = BitConverter.ToUInt32(unix_dl_sector, 8); // 8 - byte[] dl_serial = new byte[12]; - Array.Copy(unix_dl_sector, 12, dl_serial, 0, 12); - dl.serial = StringHandlers.CToString(dl_serial); // 12 - dl.cyls = BitConverter.ToUInt32(unix_dl_sector, 24); // 24 - dl.trks = BitConverter.ToUInt32(unix_dl_sector, 28); // 28 - dl.secs = BitConverter.ToUInt32(unix_dl_sector, 32); // 32 - dl.bps = BitConverter.ToUInt32(unix_dl_sector, 36); // 36 - dl.start = BitConverter.ToUInt32(unix_dl_sector, 40); // 40 - dl.alt_tbl = BitConverter.ToUInt32(unix_dl_sector, 92); // 92 - dl.alt_len = BitConverter.ToUInt32(unix_dl_sector, 96); // 96 - - if(isNewDL) // Old version VTOC starts here - { - dl.phys_cyl = BitConverter.ToUInt32(unix_dl_sector, 100); // 100 - dl.phys_trk = BitConverter.ToUInt32(unix_dl_sector, 104); // 104 - dl.phys_sec = BitConverter.ToUInt32(unix_dl_sector, 108); // 108 - dl.phys_bytes = BitConverter.ToUInt32(unix_dl_sector, 112); // 112 - dl.unknown2 = BitConverter.ToUInt32(unix_dl_sector, 116); // 116 - dl.unknown3 = BitConverter.ToUInt32(unix_dl_sector, 120); // 120 - } - - if(vtoc.magic == UNIXVTOC_MAGIC) - { - vtoc.version = BitConverter.ToUInt32(unix_dl_sector, 104 + vtocoffset); // 104/176 - byte[] vtoc_name = new byte[8]; - Array.Copy(unix_dl_sector, 108 + vtocoffset, vtoc_name, 0, 8); - vtoc.name = StringHandlers.CToString(vtoc_name); // 108/180 - vtoc.slices = BitConverter.ToUInt16(unix_dl_sector, 116 + vtocoffset); // 116/188 - vtoc.unknown = BitConverter.ToUInt16(unix_dl_sector, 118 + vtocoffset); // 118/190 - - // TODO: What if number of slices overlaps sector (>23)? - for(int j = 0; j < vtoc.slices; j++) + else { - UNIXVTOCEntry vtoc_ent = new UNIXVTOCEntry + vtoc = BigEndianMarshal.ByteArrayToStructureBigEndian(vtocsector); + for(int i = 0; i < vtoc.v_part.Length; i++) { - tag = (UNIX_TAG)BitConverter.ToUInt16(unix_dl_sector, 160 + vtocoffset + j * 12 + 0), // 160/232 + j*12 - flags = BitConverter.ToUInt16(unix_dl_sector, 160 + vtocoffset + j * 12 + 2), // 162/234 + j*12 - start = BitConverter.ToUInt32(unix_dl_sector, 160 + vtocoffset + j * 12 + 6), // 166/238 + j*12 - length = BitConverter.ToUInt32(unix_dl_sector, 160 + vtocoffset + j * 12 + 10) // 170/242 + j*12 - }; - if((vtoc_ent.flags & 0x200) == 0x200 && vtoc_ent.tag != UNIX_TAG.EMPTY && vtoc_ent.tag != UNIX_TAG.WHOLE) - { - Partition part = new Partition - { - Start = vtoc_ent.start, - Length = vtoc_ent.length, - Offset = vtoc_ent.start * dl.bps, - Size = vtoc_ent.length * dl.bps, - Sequence = counter, - Type = string.Format("UNIX: {0}", decodeUNIXTAG(vtoc_ent.tag, isNewDL)), - Scheme = Name - }; - string info = ""; - - if((vtoc_ent.flags & 0x01) == 0x01) - info += " (do not mount)"; - if((vtoc_ent.flags & 0x10) == 0x10) - info += " (do not mount)"; - - part.Description = "UNIX slice" + info + "."; - - partitions.Add(part); - counter++; + vtoc.v_part[i].p_tag = (pTag)Swapping.Swap((ushort)vtoc.v_part[i].p_tag); + vtoc.v_part[i].p_flag = (pFlag)Swapping.Swap((ushort)vtoc.v_part[i].p_flag); + vtoc.v_part[i].p_start = Swapping.Swap(vtoc.v_part[i].p_start); + vtoc.v_part[i].p_size = Swapping.Swap(vtoc.v_part[i].p_size); + vtoc.timestamp[i] = Swapping.Swap(vtoc.timestamp[i]); } } } - return true; + if(!magic_found && pd.version < XPDVERS) + { + magic = BitConverter.ToUInt32(vtocsector, 12); + + if(magic == VTOC_SANE || magic == VTOC_ENAS) + { + magic_found = true; + useOld = true; + DicConsole.DebugWriteLine("VTOC plugin", "Old VTOC found at {0}", pdloc + sectorOffset + 1); + if(magic == VTOC_SANE) + { + handle = GCHandle.Alloc(vtocsector, GCHandleType.Pinned); + vtocOld = (vtocold)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(vtocold)); + handle.Free(); + } + else + { + vtocOld = BigEndianMarshal.ByteArrayToStructureBigEndian(vtocsector); + for(int i = 0; i < vtocOld.v_part.Length; i++) + { + vtocOld.v_part[i].p_tag = (pTag)Swapping.Swap((ushort)vtocOld.v_part[i].p_tag); + vtocOld.v_part[i].p_flag = (pFlag)Swapping.Swap((ushort)vtocOld.v_part[i].p_flag); + vtocOld.v_part[i].p_start = Swapping.Swap(vtocOld.v_part[i].p_start); + vtocOld.v_part[i].p_size = Swapping.Swap(vtocOld.v_part[i].p_size); + vtocOld.timestamp[i] = Swapping.Swap(vtocOld.timestamp[i]); + } + } + } + } + + if(!magic_found) + { + DicConsole.DebugWriteLine("VTOC plugin", "Searching for VTOC on relative byte {0}", pd.vtoc_ptr); + ulong rel_sec_ptr = pd.vtoc_ptr / imagePlugin.GetSectorSize(); + uint rel_sec_off =pd.vtoc_ptr % imagePlugin.GetSectorSize(); + uint sec_count = (rel_sec_off + pd.vtoc_len) / imagePlugin.GetSectorSize(); + if((rel_sec_off + pd.vtoc_len) % imagePlugin.GetSectorSize() > 0) + sec_count++; + DicConsole.DebugWriteLine("VTOC plugin", "Going to read {0} sectors from sector {1}, getting VTOC from byte {2}", sec_count, rel_sec_ptr + sectorOffset, rel_sec_off); + if(rel_sec_ptr + sectorOffset + sec_count >= imagePlugin.GetSectors()) + { + DicConsole.DebugWriteLine("VTOC plugin", "Going to read past device size, aborting..."); + return false; + } + + byte[] tmp = imagePlugin.ReadSectors(rel_sec_ptr + sectorOffset, sec_count); + vtocsector = new byte[pd.vtoc_len]; + Array.Copy(tmp, rel_sec_off, vtocsector, 0, pd.vtoc_len); + magic = BitConverter.ToUInt32(vtocsector, 0); + + if(magic == VTOC_SANE || magic == VTOC_ENAS) + { + magic_found = true; + useOld = false; + DicConsole.DebugWriteLine("VTOC plugin", "New VTOC found."); + if(magic == VTOC_SANE) + { + handle = GCHandle.Alloc(vtocsector, GCHandleType.Pinned); + vtoc = (vtoc)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(vtoc)); + handle.Free(); + } + else + { + vtoc = BigEndianMarshal.ByteArrayToStructureBigEndian(vtocsector); + for(int i = 0; i < vtoc.v_part.Length; i++) + { + vtoc.v_part[i].p_tag = (pTag)Swapping.Swap((ushort)vtoc.v_part[i].p_tag); + vtoc.v_part[i].p_flag = (pFlag)Swapping.Swap((ushort)vtoc.v_part[i].p_flag); + vtoc.v_part[i].p_start = Swapping.Swap(vtoc.v_part[i].p_start); + vtoc.v_part[i].p_size = Swapping.Swap(vtoc.v_part[i].p_size); + vtoc.timestamp[i] = Swapping.Swap(vtoc.timestamp[i]); + } + } + } + } + + if(!magic_found) + { + DicConsole.DebugWriteLine("VTOC plugin", "Cannot find VTOC."); + return false; + } + + if(useOld) + { + DicConsole.DebugWriteLine("VTOC plugin", "vtocOld.v_sanity = 0x{0:X8} (should be 0x{1:X8})", vtocOld.v_sanity, VTOC_SANE); + DicConsole.DebugWriteLine("VTOC plugin", "vtocOld.v_version = {0}", vtocOld.v_version); + DicConsole.DebugWriteLine("VTOC plugin", "vtocOld.v_volume = \"{0}\"", StringHandlers.CToString(vtocOld.v_volume)); + DicConsole.DebugWriteLine("VTOC plugin", "vtocOld.v_sectorsz = {0}", vtocOld.v_sectorsz); + DicConsole.DebugWriteLine("VTOC plugin", "vtocOld.v_nparts = {0}", vtocOld.v_nparts); + for(int i = 0; i < V_NUMPAR; i++) + { + DicConsole.DebugWriteLine("VTOC plugin", "vtocOld.v_part[{0}].p_tag = {1} ({2})", i, vtocOld.v_part[i].p_tag, (ushort)vtocOld.v_part[i].p_tag); + DicConsole.DebugWriteLine("VTOC plugin", "vtocOld.v_part[{0}].p_flag = {1} ({2})", i, vtocOld.v_part[i].p_flag, (ushort)vtocOld.v_part[i].p_flag); + DicConsole.DebugWriteLine("VTOC plugin", "vtocOld.v_part[{0}].p_start = {1}", i, vtocOld.v_part[i].p_start); + DicConsole.DebugWriteLine("VTOC plugin", "vtocOld.v_part[{0}].p_size = {1}", i, vtocOld.v_part[i].p_size); + DicConsole.DebugWriteLine("VTOC plugin", "vtocOld.timestamp[{0}] = {1}", i, DateHandlers.UNIXToDateTime(vtocOld.timestamp[i])); + } + } + else + { + DicConsole.DebugWriteLine("VTOC plugin", "vtoc.v_sanity = 0x{0:X8} (should be 0x{1:X8})", vtoc.v_sanity, VTOC_SANE); + DicConsole.DebugWriteLine("VTOC plugin", "vtoc.v_version = {0}", vtoc.v_version); + DicConsole.DebugWriteLine("VTOC plugin", "vtoc.v_volume = \"{0}\"", StringHandlers.CToString(vtoc.v_volume)); + DicConsole.DebugWriteLine("VTOC plugin", "vtoc.v_pad = {0}", vtoc.v_pad); + DicConsole.DebugWriteLine("VTOC plugin", "vtoc.v_nparts = {0}", vtoc.v_nparts); + for(int i = 0; i < V_NUMPAR; i++) + { + DicConsole.DebugWriteLine("VTOC plugin", "vtoc.v_part[{0}].p_tag = {1} ({2})", i, vtoc.v_part[i].p_tag, (ushort)vtoc.v_part[i].p_tag); + DicConsole.DebugWriteLine("VTOC plugin", "vtoc.v_part[{0}].p_flag = {1} ({2})", i, vtoc.v_part[i].p_flag, (ushort)vtoc.v_part[i].p_flag); + DicConsole.DebugWriteLine("VTOC plugin", "vtoc.v_part[{0}].p_start = {1}", i, vtoc.v_part[i].p_start); + DicConsole.DebugWriteLine("VTOC plugin", "vtoc.v_part[{0}].p_size = {1}", i, vtoc.v_part[i].p_size); + DicConsole.DebugWriteLine("VTOC plugin", "vtoc.timestamp[{0}] = {1}", i, DateHandlers.UNIXToDateTime(vtoc.timestamp[i])); + } + } + + uint bps; + partition[] parts; + int[] timestamps; + + if(useOld) + { + bps = vtocOld.v_sectorsz; + parts = vtocOld.v_part; + timestamps = vtocOld.timestamp; + } + else + { + bps = pd.bytes; + parts = vtoc.v_part; + timestamps = vtoc.timestamp; + } + + for(int i = 0; i < V_NUMPAR; i++) + { + if(parts[i].p_tag != pTag.V_UNUSED) + { + Partition part = new Partition + { + Start = ((ulong)(parts[i].p_start * bps) / imagePlugin.GetSectorSize()), + Length = (ulong)(parts[i].p_size * bps) / imagePlugin.GetSectorSize(), + Offset = (ulong)(parts[i].p_start * bps), + Size = (ulong)(parts[i].p_size * bps), + Sequence = (ulong)i, + Type = string.Format("UNIX: {0}", decodeUNIXTAG(parts[i].p_tag, !useOld)), + Scheme = Name + }; + string info = ""; + + // Apparently old ones are absolute :? + if(!useOld) + { + part.Start += sectorOffset; + part.Offset += sectorOffset * imagePlugin.GetSectorSize(); + } + + if(parts[i].p_flag.HasFlag(pFlag.V_VALID)) + info += " (valid)"; + if(parts[i].p_flag.HasFlag(pFlag.V_UNMNT)) + info += " (unmountable)"; + if(parts[i].p_flag.HasFlag(pFlag.V_OPEN)) + info += " (open)"; + if(parts[i].p_flag.HasFlag(pFlag.V_REMAP)) + info += " (alternate sector mapping)"; + if(parts[i].p_flag.HasFlag(pFlag.V_RONLY)) + info += " (read-only)"; + if(timestamps[i] != 0) + info += string.Format(" created on {0}", DateHandlers.UNIXToDateTime(timestamps[i])); + + part.Description = "UNIX slice" + info + "."; + + if(part.End < imagePlugin.GetSectors()) + partitions.Add(part); + } + } + + return partitions.Count > 0; } - // Same as Solaris VTOC [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct UNIXDiskLabel + public struct PDInfo { - /// Drive type, seems always 0 - public uint type; - /// UNIXDiskLabel_MAGIC - public uint magic; - /// Only seen 1 - public uint version; - /// 12 bytes, serial number of the device + public uint driveid; /*identifies the device type*/ + public uint sanity; /*verifies device sanity*/ + public uint version; /*version number*/ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] - public string serial; - /// data cylinders per device - public uint cyls; - /// data tracks per cylinder - public uint trks; - /// data sectors per track - public uint secs; - /// data bytes per sector - public uint bps; - /// first sector of this partition - public uint start; - /// 48 bytes - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 48)] - public byte[] unknown1; - /// byte offset of alternate table - public uint alt_tbl; - /// byte length of alternate table - public uint alt_len; - // From onward here, is not on old version - /// physical cylinders per device - public uint phys_cyl; - /// physical tracks per cylinder - public uint phys_trk; - /// physical sectors per track - public uint phys_sec; - /// physical bytes per sector - public uint phys_bytes; - /// - public uint unknown2; - /// - public uint unknown3; - /// 32bytes - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] - public byte[] pad; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct UNIXVTOC - { - /// UNIXVTOC_MAGIC - public uint magic; - /// 1 - public uint version; - /// 8 bytes + public byte[] serial; /*serial number of the device*/ + public uint cyls; /*number of cylinders per drive*/ + public uint tracks; /*number tracks per cylinder*/ + public uint sectors; /*number sectors per track*/ + public uint bytes; /*number of bytes per sector*/ + public uint logicalst; /*sector address of logical sector 0*/ + public uint errlogst; /*sector address of error log area*/ + public uint errlogsz; /*size in bytes of error log area*/ + public uint mfgst; /*sector address of mfg. defect info*/ + public uint mfgsz; /*size in bytes of mfg. defect info*/ + public uint defectst; /*sector address of the defect map*/ + public uint defectsz; /*size in bytes of defect map*/ + public uint relno; /*number of relocation areas*/ + public uint relst; /*sector address of relocation area*/ + public uint relsz; /*size in sectors of relocation area*/ + public uint relnext; /*address of next avail reloc sector*/ + /* the previous items are left intact from AT&T's 3b2 pdinfo. Following + are added for the 80386 port */ + public uint vtoc_ptr; /*byte offset of vtoc block*/ + public ushort vtoc_len; /*byte length of vtoc block*/ + public ushort vtoc_pad; /* pad for 16-bit machine alignment */ + public uint alt_ptr; /*byte offset of alternates table*/ + public ushort alt_len; /*byte length of alternates table*/ + /* new in version 3 */ + public uint pcyls; /*physical cylinders per drive*/ + public uint ptracks; /*physical tracks per cylinder*/ + public uint psectors; /*physical sectors per track*/ + public uint pbytes; /*physical bytes per sector*/ + public uint secovhd; /*sector overhead bytes per sector*/ + public ushort interleave; /*interleave factor*/ + public ushort skew; /*skew factor*/ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] - public string name; - /// # of slices - public ushort slices; - /// - public ushort unknown; - /// 40 bytes - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)] - public byte[] reserved; + public uint[] pad; /*space for more stuff*/ } [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct UNIXVTOCEntry + public struct PDInfoOld { - /// TAG - public UNIX_TAG tag; - public ushort flags; - /// Flags (see below) - public uint start; - /// Start sector - public uint length; - /// Length of slice in sectors + public uint driveid; /*identifies the device type*/ + public uint sanity; /*verifies device sanity*/ + public uint version; /*version number*/ + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] + public byte[] serial; /*serial number of the device*/ + public uint cyls; /*number of cylinders per drive*/ + public uint tracks; /*number tracks per cylinder*/ + public uint sectors; /*number sectors per track*/ + public uint bytes; /*number of bytes per sector*/ + public uint logicalst; /*sector address of logical sector 0*/ + public uint errlogst; /*sector address of error log area*/ + public uint errlogsz; /*size in bytes of error log area*/ + public uint mfgst; /*sector address of mfg. defect info*/ + public uint mfgsz; /*size in bytes of mfg. defect info*/ + public uint defectst; /*sector address of the defect map*/ + public uint defectsz; /*size in bytes of defect map*/ + public uint relno; /*number of relocation areas*/ + public uint relst; /*sector address of relocation area*/ + public uint relsz; /*size in sectors of relocation area*/ + public uint relnext; /*address of next avail reloc sector*/ + public uint allcstrt; /*start of the allocatable disk*/ + public uint allcend; /*end of allocatable disk*/ } - public enum UNIX_TAG : ushort + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct vtocold + { + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public uint[] v_bootinfo; /*info needed by mboot*/ + public uint v_sanity; /*to verify vtoc sanity*/ + public uint v_version; /*layout version*/ + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] + public byte[] v_volume; /*volume name*/ + public ushort v_sectorsz; /*sector size in bytes*/ + public ushort v_nparts; /*number of partitions*/ + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] + public uint[] v_reserved; /*free space*/ + [MarshalAs(UnmanagedType.ByValArray, SizeConst = V_NUMPAR)] + public partition[] v_part; /*partition headers*/ + [MarshalAs(UnmanagedType.ByValArray, SizeConst = V_NUMPAR)] + public int[] timestamp; /* SCSI time stamp */ + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] +struct vtoc + { + public uint v_sanity; /*to verify vtoc sanity*/ + public uint v_version; /*layout version*/ + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] + public byte[] v_volume; /*volume name*/ + public ushort v_nparts; /*number of partitions*/ + public ushort v_pad; /*pad for 286 compiler*/ + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] + public uint[] v_reserved; /*free space*/ + [MarshalAs(UnmanagedType.ByValArray, SizeConst = V_NUMPAR)] + public partition[] v_part; /*partition headers*/ + [MarshalAs(UnmanagedType.ByValArray, SizeConst = V_NUMPAR)] + public int[] timestamp; /* SCSI time stamp */ + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct partition + { + public pTag p_tag; /*ID tag of partition*/ + public pFlag p_flag; /*permision flags*/ + public int p_start; /*start sector no of partition*/ + public int p_size; /*# of blocks in partition*/ + }; + + public enum pTag : ushort { /// empty - EMPTY = 0x0000, + V_UNUSED = 0x0000, /// boot - BOOT = 0x0001, + V_BOOT = 0x0001, /// root - ROOT = 0x0002, + V_ROOT = 0x0002, /// swap - SWAP = 0x0003, + V_SWAP = 0x0003, /// /usr - USER = 0x0004, + V_USER = 0x0004, /// whole disk - WHOLE = 0x0005, + V_BACKUP = 0x0005, /// stand partition ?? - STAND = 0x0006, + V_STAND_OLD = 0x0006, /// alternate sector space - ALT_S = 0x0006, + V_ALTS_OLD = 0x0006, /// /var - VAR = 0x0007, + V_VAR_OLD = 0x0007, /// non UNIX - OTHER = 0x0007, + V_OTHER = 0x0007, /// /home - HOME = 0x0008, + V_HOME_OLD = 0x0008, /// alternate track space - ALT_T = 0x0008, + V_ALTS = 0x0008, /// alternate sector track - ALT_ST = 0x0009, + V_ALTSCTR_OLD = 0x0009, /// stand partition ?? - NEW_STAND = 0x0009, + V_STAND = 0x0009, /// cache - CACHE = 0x000A, + V_CACHE = 0x000A, /// /var - NEW_VAR = 0x000A, + V_VAR = 0x000A, /// reserved - RESERVED = 0x000B, + V_RESERVED = 0x000B, /// /home - NEW_HOME = 0x000B, + V_HOME = 0x000B, /// dump partition - DUMP = 0x000C, + V_DUMP = 0x000C, /// alternate sector track - NEW_ALT_ST = 0x000D, + V_ALTSCTR = 0x000D, /// volume mgt public partition - VM_PUBLIC = 0x000E, + V_VMPUBLIC = 0x000E, /// volume mgt private partition - VM_PRIVATE = 0x000F + V_VMPRIVATE = 0x000F } - public static string decodeUNIXTAG(UNIX_TAG type, bool isNew) + [Flags] + enum pFlag : ushort + { + /* Partition permission flags */ + V_UNMNT = 0x01, /* Unmountable partition */ + V_RONLY = 0x10, /* Read only */ + V_REMAP = 0x20, /* do alternate sector mapping */ + V_OPEN = 0x100, /* Partition open (for driver use) */ + V_VALID = 0x200, /* Partition is valid to use */ + V_VOMASK = 0x300 /* mask for open and valid */ + } + + public static string decodeUNIXTAG(pTag type, bool isNew) { switch(type) { - case UNIX_TAG.EMPTY: + case pTag.V_UNUSED: return "Unused"; - case UNIX_TAG.BOOT: + case pTag.V_BOOT: return "Boot"; - case UNIX_TAG.ROOT: + case pTag.V_ROOT: return "/"; - case UNIX_TAG.SWAP: + case pTag.V_SWAP: return "Swap"; - case UNIX_TAG.USER: + case pTag.V_USER: return "/usr"; - case UNIX_TAG.WHOLE: + case pTag.V_BACKUP: return "Whole disk"; - case UNIX_TAG.STAND: + case pTag.V_STAND_OLD: return isNew ? "Stand" : "Alternate sector space"; - case UNIX_TAG.VAR: + case pTag.V_VAR_OLD: return isNew ? "/var" : "non UNIX"; - case UNIX_TAG.HOME: + case pTag.V_HOME_OLD: return isNew ? "/home" : "Alternate track space"; - case UNIX_TAG.ALT_ST: + case pTag.V_ALTSCTR_OLD: return isNew ? "Alternate sector track" : "Stand"; - case UNIX_TAG.CACHE: + case pTag.V_CACHE: return isNew ? "Cache" : "/var"; - case UNIX_TAG.RESERVED: + case pTag.V_RESERVED: return isNew ? "Reserved" : "/home"; - case UNIX_TAG.DUMP: + case pTag.V_DUMP: return "dump"; - case UNIX_TAG.NEW_ALT_ST: + case pTag.V_ALTSCTR: return "Alternate sector track"; - case UNIX_TAG.VM_PUBLIC: + case pTag.V_VMPUBLIC: return "volume mgt public partition"; - case UNIX_TAG.VM_PRIVATE: + case pTag.V_VMPRIVATE: return "volume mgt private partition"; default: return string.Format("Unknown TAG: 0x{0:X4}", type);