// /*************************************************************************** // The Disc Image Chef // ---------------------------------------------------------------------------- // // Filename : VxFS.cs // Author(s) : Natalia Portillo // // Component : Veritas File System plugin. // // --[ Description ] ---------------------------------------------------------- // // Identifies the Veritas file system 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-2019 Natalia Portillo // ****************************************************************************/ using System; using System.Runtime.InteropServices; using System.Text; using DiscImageChef.CommonTypes; using DiscImageChef.CommonTypes.Interfaces; using Schemas; using Marshal = DiscImageChef.Helpers.Marshal; namespace DiscImageChef.Filesystems { public class VxFS : IFilesystem { /// /// Identifier for VxFS /// const uint VXFS_MAGIC = 0xA501FCF5; const uint VXFS_BASE = 0x400; public FileSystemType XmlFsType { get; private set; } public Encoding Encoding { get; private set; } public string Name => "Veritas filesystem"; public Guid Id => new Guid("EC372605-7687-453C-8BEA-7E0DFF79CB03"); public string Author => "Natalia Portillo"; public bool Identify(IMediaImage imagePlugin, Partition partition) { ulong vmfsSuperOff = VXFS_BASE / imagePlugin.Info.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 void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding) { Encoding = encoding ?? Encoding.UTF8; ulong vmfsSuperOff = VXFS_BASE / imagePlugin.Info.SectorSize; byte[] sector = imagePlugin.ReadSector(partition.Start + vmfsSuperOff); VxSuperBlock vxSb = Marshal.ByteArrayToStructureLittleEndian(sector); 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, Encoding)) .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 = (ulong)vxSb.vs_size, ClusterSize = (uint)vxSb.vs_bsize, Dirty = vxSb.vs_clean != 0, FreeClusters = (ulong)vxSb.vs_free, FreeClustersSpecified = true }; } [StructLayout(LayoutKind.Sequential, Pack = 1)] struct VxSuperBlock { /// Magic number public readonly uint vs_magic; /// VxFS version public readonly int vs_version; /// create time - secs public readonly uint vs_ctime; /// create time - usecs public readonly uint vs_cutime; /// unused public readonly int __unused1; /// unused public readonly int __unused2; /// obsolete public readonly int vs_old_logstart; /// obsolete public readonly int vs_old_logend; /// block size public readonly int vs_bsize; /// number of blocks public readonly int vs_size; /// number of data blocks public readonly int vs_dsize; /// obsolete public readonly uint vs_old_ninode; /// obsolete public readonly int vs_old_nau; /// unused public readonly int __unused3; /// obsolete public readonly int vs_old_defiextsize; /// obsolete public readonly int vs_old_ilbsize; /// size of immediate data area public readonly int vs_immedlen; /// number of direct extentes public readonly int vs_ndaddr; /// address of first AU public readonly int vs_firstau; /// offset of extent map in AU public readonly int vs_emap; /// offset of inode map in AU public readonly int vs_imap; /// offset of ExtOp. map in AU public readonly int vs_iextop; /// offset of inode list in AU public readonly int vs_istart; /// offset of fdblock in AU public readonly int vs_bstart; /// aufirst + emap public readonly int vs_femap; /// aufirst + imap public readonly int vs_fimap; /// aufirst + iextop public readonly int vs_fiextop; /// aufirst + istart public readonly int vs_fistart; /// aufirst + bstart public readonly int vs_fbstart; /// number of entries in indir public readonly int vs_nindir; /// length of AU in blocks public readonly int vs_aulen; /// length of imap in blocks public readonly int vs_auimlen; /// length of emap in blocks public readonly int vs_auemlen; /// length of ilist in blocks public readonly int vs_auilen; /// length of pad in blocks public readonly int vs_aupad; /// data blocks in AU public readonly int vs_aublocks; /// log base 2 of aublocks public readonly int vs_maxtier; /// number of inodes per blk public readonly int vs_inopb; /// obsolete public readonly int vs_old_inopau; /// obsolete public readonly int vs_old_inopilb; /// obsolete public readonly int vs_old_ndiripau; /// size of indirect addr ext. public readonly int vs_iaddrlen; /// log base 2 of bsize public readonly int vs_bshift; /// log base 2 of inobp public readonly int vs_inoshift; /// ~( bsize - 1 ) public readonly int vs_bmask; /// bsize - 1 public readonly int vs_boffmask; /// old_inopilb - 1 public readonly int vs_old_inomask; /// checksum of V1 data public readonly int vs_checksum; /// number of free blocks public readonly int vs_free; /// number of free inodes public readonly int vs_ifree; /// number of free extents by size [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public readonly int[] vs_efree; /// flags ?!? public readonly int vs_flags; /// filesystem has been changed public readonly byte vs_mod; /// clean FS public readonly byte vs_clean; /// unused public readonly ushort __unused4; /// mount time log ID public readonly uint vs_firstlogid; /// last time written - sec public readonly uint vs_wtime; /// last time written - usec public readonly uint vs_wutime; /// FS name [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] public readonly byte[] vs_fname; /// FS pack name [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] public readonly byte[] vs_fpack; /// log format version public readonly int vs_logversion; /// unused public readonly int __unused5; /// OLT extent and replica [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public readonly int[] vs_oltext; /// OLT extent size public readonly int vs_oltsize; /// size of inode map public readonly int vs_iauimlen; /// size of IAU in blocks public readonly int vs_iausize; /// size of inode in bytes public readonly int vs_dinosize; /// indir levels per inode public readonly int vs_old_dniaddr; /// checksum of V2 RO public readonly int vs_checksum2; } } }