// /*************************************************************************** // The Disc Image Chef // ---------------------------------------------------------------------------- // // Filename : BSD.cs // Author(s) : Natalia Portillo // // Component : Partitioning scheme plugins. // // --[ Description ] ---------------------------------------------------------- // // Manages BSD disklabels. // // --[ License ] -------------------------------------------------------------- // // This library is free software; you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as // published by the Free Software Foundation; either version 2.1 of the // License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, see . // // ---------------------------------------------------------------------------- // Copyright © 2011-2016 Natalia Portillo // ****************************************************************************/ using System; using System.Collections.Generic; using System.Runtime.InteropServices; using DiscImageChef.CommonTypes; using DiscImageChef.ImagePlugins; namespace DiscImageChef.PartPlugins { class BSD : PartPlugin { public const uint DISKMAGIC = 0x82564557; public BSD() { Name = "BSD disklabel"; PluginUUID = new Guid("246A6D93-4F1A-1F8A-344D-50187A5513A9"); } public override bool GetInformation(ImagePlugin imagePlugin, out List partitions) { partitions = new List(); byte[] sector = imagePlugin.ReadSector(0); if(sector.Length < 512) return false; bool found = false; DiskLabel dl = GetDiskLabel(sector); if(dl.d_magic == DISKMAGIC || dl.d_magic2 == DISKMAGIC) found = true; else { sector = imagePlugin.ReadSector(1); dl = GetDiskLabel(sector); found |= (dl.d_magic == DISKMAGIC || dl.d_magic2 == DISKMAGIC); } if(found) { ulong counter = 0; foreach(BSDPartition entry in dl.d_partitions) { Partition part = new Partition(); part.PartitionStartSector = entry.p_offset; part.PartitionStart = (entry.p_offset * dl.d_secsize); part.PartitionLength = entry.p_size; part.PartitionSectors = (entry.p_size * dl.d_secsize); part.PartitionType = fsTypeToString(entry.p_fstype); part.PartitionSequence = counter; if(entry.p_fstype != fsType.Unused) { partitions.Add(part); counter++; } } } return found; } /// Drive type public enum dType : ushort { /// SMD, XSMD SMD = 1, /// MSCP MSCP = 2, /// Other DEC (rk, rl) DEC = 3, /// SCSI SCSI = 4, /// ESDI ESDI = 5, /// ST506 et al ST506 = 6, /// CS/80 on HP-IB HPIB = 7, /// HP Fiber-link HPFL = 8, /// Floppy FLOPPY = 10, /// Concatenated disk CCD = 11, /// uvnode pseudo-disk VND = 12, /// DiskOnChip DOC2K = 13, /// ATAPI ATAPI = 13, /// CMU RAIDframe RAID = 14, /// Logical disk LD = 15, /// IBM JFS 2 JFS2 = 16, /// Cryptographic pseudo-disk CGD = 17, /// Vinum volume VINUM = 18, /// Flash memory devices FLASH = 19, /// Device-mapper pseudo-disk devices DM = 20, /// Rump virtual disk RUMPD = 21, /// Memory disk MD = 22 } /// Filesystem type public enum fsType : byte { /// Unused entry Unused = 0, /// Swap partition Swap = 1, /// UNIX 6th Edition V6 = 2, /// UNIX 7th Edition V7 = 3, /// UNIX System V SystemV = 4, /// UNIX 7th Edition with 1K blocks V7_1K = 5, /// UNIX 8th Edition with 4K blocks V8 = 6, /// 4.2BSD Fast File System BSDFFS = 7, /// MS-DOS filesystem MSDOS = 8, /// 4.4LFS BSDLFS = 9, /// In use, unknown or unsupported Other = 10, /// HPFS HPFS = 11, /// ISO9660 ISO9660 = 12, /// Boot partition Boot = 13, /// Amiga FFS AFFS = 14, /// Apple HFS HFS = 15, /// Acorn ADFS FileCore = 16, /// Digital Advanced File System ADVfs = 16, /// Digital LSM Public Region LSMpublic = 17, /// Linux ext2 ext2 = 17, /// Digital LSM Private Region LSMprivate = 18, /// NTFS NTFS = 18, /// Digital LSM Simple Disk LSMsimple = 19, /// RAIDframe component RAID = 19, /// Concatenated disk component CCD = 20, /// IBM JFS2 JFS2 = 21, /// Apple UFS AppleUFS = 22, /// Hammer filesystem HAMMER = 22, /// Hammer2 filesystem HAMMER2 = 23, /// UDF UDF = 24, /// System V Boot filesystem SysVBoot = 25, /// EFS EFS = 26, /// ZFS ZFS = 27, /// NiLFS NILFS = 27, /// Cryptographic disk CGD = 28, /// MINIX v3 MINIX = 29, /// FreeBSD nandfs NANDFS = 30 } /// /// Drive flags /// [Flags] public enum dFlags : uint { /// Removable media Removable = 0x01, /// Drive supports ECC ECC = 0x02, /// Drive supports bad sector forwarding BadSectorForward = 0x04, /// Disk emulator RAMDisk = 0x08, /// Can do back to back transfer Chain = 0x10, /// Dynamic geometry device DynamicGeometry = 0x20 } [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct DiskLabel { /// public uint d_magic; /// public dType d_type; /// Disk subtype public ushort d_subtype; /// Type name [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] d_typename; /// Pack identifier [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] d_packname; /// Bytes per sector public uint d_secsize; /// Sectors per track public uint d_nsectors; /// Tracks per cylinder public uint d_ntracks; /// Cylinders per unit public uint d_ncylinders; /// Sectors per cylinder public uint d_secpercyl; /// Sectors per unit public uint d_secperunit; /// Spare sectors per track public ushort d_sparespertrack; /// Spare sectors per cylinder public ushort d_sparespercyl; /// Alternate cylinders public uint d_acylinders; /// Rotational speed public ushort d_rpm; /// Hardware sector interleave public ushort d_interleave; /// Sector 0 skew per track public ushort d_trackskew; /// Sector 0 sker per cylinder public ushort d_cylskeew; /// Head switch time in microseconds public uint d_headswitch; /// Track to track seek in microseconds public uint d_trkseek; /// public dFlags d_flags; /// Drive-specific information [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)] public uint[] d_drivedata; /// Reserved [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)] /// public uint[] d_spare; /// again public uint d_magic2; /// XOR of data public ushort d_checksum; /// How many partitions public ushort d_npartitions; /// Size of boot area in bytes public uint d_bbsize; /// Maximum size of superblock in bytes public uint d_sbsize; /// Partitions [MarshalAs(UnmanagedType.ByValArray, SizeConst = 18)] public BSDPartition[] d_partitions; } [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct BSDPartition { /// Sectors in partition public uint p_size; /// Starting sector public uint p_offset; /// Fragment size public uint p_fsize; /// Filesystem type, public fsType p_fstype; /// Fragment size public byte p_frag; /// Cylinder per group public ushort p_cpg; } public static string fsTypeToString(fsType typ) { switch(typ) { case fsType.Unused: return "Unused entry"; case fsType.Swap: return "Swap partition"; case fsType.V6: return "UNIX 6th Edition"; case fsType.V7: return "UNIX 7th Edition"; case fsType.SystemV: return "UNIX System V"; case fsType.V7_1K: return "UNIX 7th Edition with 1K blocks"; case fsType.V8: return "UNIX 8th Edition with 4K blocks"; case fsType.BSDFFS: return "4.2BSD Fast File System"; case fsType.BSDLFS: return "4.4LFS"; case fsType.HPFS: return "HPFS"; case fsType.ISO9660: return "ISO9660"; case fsType.Boot: return "Boot"; case fsType.AFFS: return "Amiga FFS"; case fsType.HFS: return "Apple HFS"; case fsType.ADVfs: return "Digital Advanced File System"; case fsType.LSMpublic: return "Digital LSM Public Region"; case fsType.LSMprivate: return "Digital LSM Private Region"; case fsType.LSMsimple: return "Digital LSM Simple Disk"; case fsType.CCD: return "Concatenated disk"; case fsType.JFS2: return "IBM JFS2"; case fsType.HAMMER: return "Hammer"; case fsType.HAMMER2: return "Hammer2"; case fsType.UDF: return "UDF"; case fsType.EFS: return "EFS"; case fsType.ZFS: return "ZFS"; case fsType.NANDFS: return "FreeBSD nandfs"; case fsType.Other: return "Other or unknown"; default: return "Unknown"; } } public static DiskLabel GetDiskLabel(byte[] disklabel) { DiskLabel dl = new DiskLabel(); IntPtr dlPtr = Marshal.AllocHGlobal(512); Marshal.Copy(disklabel, 0, dlPtr, 512); dl = (DiskLabel)Marshal.PtrToStructure(dlPtr, typeof(DiskLabel)); Marshal.FreeHGlobal(dlPtr); return dl; } } }