diff --git a/DiscImageChef.Filesystems/ChangeLog b/DiscImageChef.Filesystems/ChangeLog index 12213b14..ece4ec3d 100644 --- a/DiscImageChef.Filesystems/ChangeLog +++ b/DiscImageChef.Filesystems/ChangeLog @@ -1,3 +1,9 @@ +2016-09-02 Natalia Portillo + + * NILFS2.cs: + * DiscImageChef.Filesystems.csproj: Adds support for NILFS2 + filesystem. + 2016-09-02 Natalia Portillo * F2FS.cs: diff --git a/DiscImageChef.Filesystems/DiscImageChef.Filesystems.csproj b/DiscImageChef.Filesystems/DiscImageChef.Filesystems.csproj index b9bc4bfb..e35d5f90 100644 --- a/DiscImageChef.Filesystems/DiscImageChef.Filesystems.csproj +++ b/DiscImageChef.Filesystems/DiscImageChef.Filesystems.csproj @@ -101,6 +101,7 @@ + diff --git a/DiscImageChef.Filesystems/NILFS2.cs b/DiscImageChef.Filesystems/NILFS2.cs new file mode 100644 index 00000000..c3b3f41c --- /dev/null +++ b/DiscImageChef.Filesystems/NILFS2.cs @@ -0,0 +1,261 @@ +// /*************************************************************************** +// The Disc Image Chef +// ---------------------------------------------------------------------------- +// +// Filename : NILFS2.cs +// Author(s) : Natalia Portillo +// +// Component : Component +// +// --[ Description ] ---------------------------------------------------------- +// +// Identifies the NILFS2 filesystem and shows information. +// +// --[ 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 System.Text; + +namespace DiscImageChef.Filesystems +{ + 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_SuperOffset = 1024; + + public NILFS2() + { + Name = "NILFS2 Plugin"; + PluginUUID = new Guid("82B0920F-5F0D-4063-9F57-ADE0AE02ECE5"); + } + + public NILFS2(ImagePlugins.ImagePlugin imagePlugin, ulong partitionStart, ulong partitionEnd) + { + Name = "NILFS2 Plugin"; + PluginUUID = new Guid("82B0920F-5F0D-4063-9F57-ADE0AE02ECE5"); + } + + public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionStart, ulong partitionEnd) + { + if(imagePlugin.GetSectorSize() < 512) + return false; + + uint sbAddr = NILFS2_SuperOffset / imagePlugin.GetSectorSize(); + if(sbAddr == 0) + sbAddr = 1; + + NILFS2_Superblock nilfsSb = new NILFS2_Superblock(); + + uint sbSize = (uint)(Marshal.SizeOf(nilfsSb) / imagePlugin.GetSectorSize()); + if(Marshal.SizeOf(nilfsSb) % imagePlugin.GetSectorSize() != 0) + sbSize++; + + byte[] sector = imagePlugin.ReadSectors(partitionStart + sbAddr, sbSize); + if(sector.Length < Marshal.SizeOf(nilfsSb)) + return false; + + IntPtr sbPtr = Marshal.AllocHGlobal(Marshal.SizeOf(nilfsSb)); + Marshal.Copy(sector, 0, sbPtr, Marshal.SizeOf(nilfsSb)); + nilfsSb = (NILFS2_Superblock)Marshal.PtrToStructure(sbPtr, typeof(NILFS2_Superblock)); + Marshal.FreeHGlobal(sbPtr); + + return nilfsSb.magic == NILFS2_Magic; + } + + public override void GetInformation(ImagePlugins.ImagePlugin imagePlugin, ulong partitionStart, ulong partitionEnd, out string information) + { + information = ""; + if(imagePlugin.GetSectorSize() < 512) + return; + + uint sbAddr = NILFS2_SuperOffset / imagePlugin.GetSectorSize(); + if(sbAddr == 0) + sbAddr = 1; + + NILFS2_Superblock nilfsSb = new NILFS2_Superblock(); + + uint sbSize = (uint)(Marshal.SizeOf(nilfsSb) / imagePlugin.GetSectorSize()); + if(Marshal.SizeOf(nilfsSb) % imagePlugin.GetSectorSize() != 0) + sbSize++; + + byte[] sector = imagePlugin.ReadSectors(partitionStart + sbAddr, sbSize); + if(sector.Length < Marshal.SizeOf(nilfsSb)) + return; + + IntPtr sbPtr = Marshal.AllocHGlobal(Marshal.SizeOf(nilfsSb)); + Marshal.Copy(sector, 0, sbPtr, Marshal.SizeOf(nilfsSb)); + nilfsSb = (NILFS2_Superblock)Marshal.PtrToStructure(sbPtr, typeof(NILFS2_Superblock)); + Marshal.FreeHGlobal(sbPtr); + + if(nilfsSb.magic != NILFS2_Magic) + return; + + StringBuilder sb = new StringBuilder(); + + sb.AppendLine("NILFS2 filesystem"); + sb.AppendFormat("Version {0}.{1}", nilfsSb.rev_level, nilfsSb.minor_rev_level).AppendLine(); + sb.AppendFormat("{0} bytes per block", 1 << (int)(nilfsSb.log_block_size + 10)).AppendLine(); + sb.AppendFormat("{0} bytes in volume", nilfsSb.dev_size).AppendLine(); + sb.AppendFormat("{0} blocks per segment", nilfsSb.blocks_per_segment).AppendLine(); + sb.AppendFormat("{0} segments", nilfsSb.nsegments).AppendLine(); + if(nilfsSb.creator_os == 0) + sb.AppendLine("Filesystem created on Linux"); + else + sb.AppendFormat("Creator OS code: {0}", nilfsSb.creator_os).AppendLine(); + sb.AppendFormat("{0} bytes per inode", nilfsSb.inode_size).AppendLine(); + sb.AppendFormat("Volume UUID: {0}", nilfsSb.uuid).AppendLine(); + sb.AppendFormat("Volume name: {0}", Encoding.ASCII.GetString(nilfsSb.volume_name)).AppendLine(); + sb.AppendFormat("Volume created on {0}", DateHandlers.UNIXUnsignedToDateTime(nilfsSb.ctime)).AppendLine(); + sb.AppendFormat("Volume last mounted on {0}", DateHandlers.UNIXUnsignedToDateTime(nilfsSb.mtime)).AppendLine(); + sb.AppendFormat("Volume last written on {0}", DateHandlers.UNIXUnsignedToDateTime(nilfsSb.wtime)).AppendLine(); + + information = sb.ToString(); + + xmlFSType = new Schemas.FileSystemType(); + xmlFSType.Type = "NILFS2 filesystem"; + if(nilfsSb.creator_os == 0) + xmlFSType.SystemIdentifier = "Linux"; + xmlFSType.ClusterSize = 1 << (int)(nilfsSb.log_block_size + 10); + xmlFSType.Clusters = (long)nilfsSb.dev_size / xmlFSType.ClusterSize; + xmlFSType.VolumeName = Encoding.Unicode.GetString(nilfsSb.volume_name); + xmlFSType.VolumeSerial = nilfsSb.uuid.ToString(); + xmlFSType.CreationDate = DateHandlers.UNIXUnsignedToDateTime(nilfsSb.ctime); + xmlFSType.CreationDateSpecified = true; + xmlFSType.ModificationDate = DateHandlers.UNIXUnsignedToDateTime(nilfsSb.wtime); + xmlFSType.ModificationDateSpecified = 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.Helpers/ChangeLog b/DiscImageChef.Helpers/ChangeLog index 4180fa75..0374ccad 100644 --- a/DiscImageChef.Helpers/ChangeLog +++ b/DiscImageChef.Helpers/ChangeLog @@ -1,3 +1,7 @@ +2016-09-02 Natalia Portillo + + * DateHandlers.cs: Adds support for NILFS2 filesystem. + 2016-09-02 Natalia Portillo * DateHandlers.cs: Add supports for UNIX timestamps divided in diff --git a/DiscImageChef.Helpers/DateHandlers.cs b/DiscImageChef.Helpers/DateHandlers.cs index 6c1c563b..da2f873a 100644 --- a/DiscImageChef.Helpers/DateHandlers.cs +++ b/DiscImageChef.Helpers/DateHandlers.cs @@ -59,6 +59,11 @@ namespace DiscImageChef return UNIXEpoch.AddSeconds(UNIXTimeStamp); } + public static DateTime UNIXToDateTime(long UNIXTimeStamp) + { + return UNIXEpoch.AddSeconds(UNIXTimeStamp); + } + public static DateTime UNIXUnsignedToDateTime(uint UNIXTimeStamp) { return UNIXEpoch.AddSeconds(UNIXTimeStamp); @@ -69,6 +74,11 @@ namespace DiscImageChef return UNIXEpoch.AddSeconds(seconds).AddTicks((long)nanoseconds / 100); } + public static DateTime UNIXUnsignedToDateTime(ulong UNIXTimeStamp) + { + return UNIXEpoch.AddSeconds(UNIXTimeStamp); + } + public static DateTime ISO9660ToDateTime(byte[] VDDateTime) { int year, month, day, hour, minute, second, hundredths; diff --git a/README.md b/README.md index 6ee7c19e..8490980d 100644 --- a/README.md +++ b/README.md @@ -126,6 +126,7 @@ Supported file systems for identification and information only * QNX4 and QNX6 filesystems * IBM Journaling File System (JFS) * Flash-Friendly File System (F2FS) +* NILFS2 Supported checksums ===================