diff --git a/DiscImageChef.Filesystems/APFS.cs b/DiscImageChef.Filesystems/APFS.cs new file mode 100644 index 000000000..63ff22b4c --- /dev/null +++ b/DiscImageChef.Filesystems/APFS.cs @@ -0,0 +1,134 @@ +// /*************************************************************************** +// The Disc Image Chef +// ---------------------------------------------------------------------------- +// +// Filename : APFS.cs +// Version : 1.0 +// Author(s) : Natalia Portillo +// +// Component : Component +// +// Revision : $Revision$ +// Last change by : $Author$ +// Date : $Date$ +// +// --[ Description ] ---------------------------------------------------------- +// +// Description +// +// --[ License ] -------------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// ---------------------------------------------------------------------------- +// Copyright (C) 2011-2015 Claunia.com +// ****************************************************************************/ +// //$Id$ +using System; +using System.Runtime.InteropServices; +using System.Text; +using DiscImageChef.Console; + +namespace DiscImageChef.Plugins +{ + class APFS : Plugin + { + const uint ApfsContainerMagic = 0x4253584E; // "NXSB" + const uint ApfsVolumeMagic = 0x42535041; // "APSB" + + public APFS() + { + Name = "Apple File System"; + PluginUUID = new Guid("A4060F9D-2909-42E2-9D95-DB31FA7EA797"); + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct ApfsContainerSuperBlock + { + public UInt64 unknown1; // Varies between copies of the superblock + public UInt64 unknown2; + public UInt64 unknown3; // Varies by 1 between copies of the superblock + public UInt64 unknown4; + public UInt32 magic; + public UInt32 blockSize; + public UInt64 containerBlocks; + } + + public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionStart, ulong partitionEnd) + { + if(partitionStart >= imagePlugin.GetSectors()) + return false; + + byte[] sector = imagePlugin.ReadSector(partitionStart); + ApfsContainerSuperBlock nxSb; + + try + { + GCHandle handle = GCHandle.Alloc(sector, GCHandleType.Pinned); + nxSb = (ApfsContainerSuperBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(ApfsContainerSuperBlock)); + handle.Free(); + } + catch + { + return false; + } + + if(nxSb.magic == ApfsContainerMagic) + return true; + + return false; + } + + public override void GetInformation(ImagePlugins.ImagePlugin imagePlugin, ulong partitionStart, ulong partitionEnd, out string information) + { + StringBuilder sbInformation = new StringBuilder(); + xmlFSType = new Schemas.FileSystemType(); + information = ""; + + if(partitionStart >= imagePlugin.GetSectors()) + return; + + byte[] sector = imagePlugin.ReadSector(partitionStart); + ApfsContainerSuperBlock nxSb; + + try + { + GCHandle handle = GCHandle.Alloc(sector, GCHandleType.Pinned); + nxSb = (ApfsContainerSuperBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(ApfsContainerSuperBlock)); + handle.Free(); + } + catch + { + return; + } + + if(nxSb.magic != ApfsContainerMagic) + return; + + sbInformation.AppendLine("Apple File System"); + sbInformation.AppendLine(); + sbInformation.AppendFormat("{0} bytes per block", nxSb.blockSize).AppendLine(); + sbInformation.AppendFormat("Container has {0} bytes in {1} blocks", nxSb.containerBlocks * nxSb.blockSize, nxSb.containerBlocks).AppendLine(); + + information = sbInformation.ToString(); + + xmlFSType = new Schemas.FileSystemType(); + xmlFSType.Bootable = false; + xmlFSType.Clusters = (long)nxSb.containerBlocks; + xmlFSType.ClusterSize = (int)nxSb.blockSize; + xmlFSType.Type = "Apple File System"; + } + } +} + diff --git a/DiscImageChef.Filesystems/DiscImageChef.Filesystems.csproj b/DiscImageChef.Filesystems/DiscImageChef.Filesystems.csproj index 3b6e12c9c..052c5de73 100644 --- a/DiscImageChef.Filesystems/DiscImageChef.Filesystems.csproj +++ b/DiscImageChef.Filesystems/DiscImageChef.Filesystems.csproj @@ -60,6 +60,7 @@ + @@ -92,4 +93,14 @@ DiscImageChef.Metadata + + + + + + + + + + \ No newline at end of file diff --git a/DiscImageChef.Partitions/GPT.cs b/DiscImageChef.Partitions/GPT.cs index 306e86a41..3498a69b7 100644 --- a/DiscImageChef.Partitions/GPT.cs +++ b/DiscImageChef.Partitions/GPT.cs @@ -324,6 +324,8 @@ namespace DiscImageChef.PartPlugins return "PowerPC PReP boot"; case "0311FC50-01CA-4725-AD77-9ADBB20ACE98": return "Acronis Secure Zone"; + case "7C3457EF-0000-11AA-AA11-00306543ECAC": + return "Apple File System"; default: return ""; } diff --git a/README.md b/README.md index 5cb307d3c..bdd609add 100644 --- a/README.md +++ b/README.md @@ -92,6 +92,7 @@ Supported file systems * Amiga Fast File System v2, untested * Acorn Advanced Disc Filing System * B-tree file system (btrfs) +* Apple File System (preliminary detection until on-disk layout is stable) Supported checksums ===================