Beispiel #1
0
        public void Open(Stream stream)
        {
            byte[] mtimeB = new byte[4];
            byte[] isizeB = new byte[4];

            _dataStream = stream;
            _basePath   = null;

            _dataStream.Seek(4, SeekOrigin.Begin);
            _dataStream.Read(mtimeB, 0, 4);
            _dataStream.Seek(-4, SeekOrigin.End);
            _dataStream.Read(isizeB, 0, 4);
            _dataStream.Seek(0, SeekOrigin.Begin);

            uint mtime = BitConverter.ToUInt32(mtimeB, 0);
            uint isize = BitConverter.ToUInt32(isizeB, 0);

            _decompressedSize = isize;
            _creationTime     = DateHandlers.UnixUnsignedToDateTime(mtime);
            _lastWriteTime    = _creationTime;

            _zStream = new ForcedSeekStream <GZipStream>(_decompressedSize, _dataStream, CompressionMode.Decompress);

            _opened = true;
        }
Beispiel #2
0
        public void Open(byte[] buffer)
        {
            byte[] mtime_b = new byte[4];
            byte[] isize_b = new byte[4];

            dataStream = new MemoryStream(buffer);
            basePath   = null;

            dataStream.Seek(4, SeekOrigin.Begin);
            dataStream.Read(mtime_b, 0, 4);
            dataStream.Seek(-4, SeekOrigin.End);
            dataStream.Read(isize_b, 0, 4);
            dataStream.Seek(0, SeekOrigin.Begin);

            uint mtime = BitConverter.ToUInt32(mtime_b, 0);
            uint isize = BitConverter.ToUInt32(isize_b, 0);

            decompressedSize = isize;
            creationTime     = DateHandlers.UnixUnsignedToDateTime(mtime);
            lastWriteTime    = creationTime;

            zStream = new ForcedSeekStream <GZipStream>(decompressedSize, dataStream, CompressionMode.Decompress);

            opened = true;
        }
Beispiel #3
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            Encoding = encoding ?? Encoding.GetEncoding("iso-8859-1");
            byte[]    rootBlockSector = imagePlugin.ReadSector(partition.Start);
            RootBlock rootBlock       = Marshal.ByteArrayToStructureBigEndian <RootBlock>(rootBlockSector);

            var sbInformation = new StringBuilder();

            sbInformation.AppendLine("SmartFileSystem");

            sbInformation.AppendFormat("Volume version {0}", rootBlock.version).AppendLine();

            sbInformation.AppendFormat("Volume starts on device byte {0} and ends on byte {1}", rootBlock.firstbyte,
                                       rootBlock.lastbyte).AppendLine();

            sbInformation.
            AppendFormat("Volume has {0} blocks of {1} bytes each", rootBlock.totalblocks, rootBlock.blocksize).
            AppendLine();

            sbInformation.AppendFormat("Volume created on {0}",
                                       DateHandlers.UnixUnsignedToDateTime(rootBlock.datecreated).AddYears(8)).
            AppendLine();

            sbInformation.AppendFormat("Bitmap starts in block {0}", rootBlock.bitmapbase).AppendLine();

            sbInformation.AppendFormat("Admin space container starts in block {0}", rootBlock.adminspacecontainer).
            AppendLine();

            sbInformation.AppendFormat("Root object container starts in block {0}", rootBlock.rootobjectcontainer).
            AppendLine();

            sbInformation.
            AppendFormat("Root node of the extent B-tree resides in block {0}", rootBlock.extentbnoderoot).
            AppendLine();

            sbInformation.AppendFormat("Root node of the object B-tree resides in block {0}", rootBlock.objectnoderoot).
            AppendLine();

            if (rootBlock.bits.HasFlag(Flags.CaseSensitive))
            {
                sbInformation.AppendLine("Volume is case sensitive");
            }

            if (rootBlock.bits.HasFlag(Flags.RecycledFolder))
            {
                sbInformation.AppendLine("Volume moves deleted files to a recycled folder");
            }

            information = sbInformation.ToString();

            XmlFsType = new FileSystemType
            {
                CreationDate          = DateHandlers.UnixUnsignedToDateTime(rootBlock.datecreated).AddYears(8),
                CreationDateSpecified = true,
                Clusters    = rootBlock.totalblocks,
                ClusterSize = rootBlock.blocksize,
                Type        = "SmartFileSystem"
            };
        }
Beispiel #4
0
        public void Open(string path)
        {
            byte[] mtimeB = new byte[4];
            byte[] isizeB = new byte[4];

            _dataStream = new FileStream(path, FileMode.Open, FileAccess.Read);
            _basePath   = Path.GetFullPath(path);

            _dataStream.Seek(4, SeekOrigin.Begin);
            _dataStream.Read(mtimeB, 0, 4);
            _dataStream.Seek(-4, SeekOrigin.End);
            _dataStream.Read(isizeB, 0, 4);
            _dataStream.Seek(0, SeekOrigin.Begin);

            uint mtime = BitConverter.ToUInt32(mtimeB, 0);
            uint isize = BitConverter.ToUInt32(isizeB, 0);

            _decompressedSize = isize;
            var fi = new FileInfo(path);

            _creationTime  = fi.CreationTimeUtc;
            _lastWriteTime = DateHandlers.UnixUnsignedToDateTime(mtime);
            _zStream       = new ForcedSeekStream <GZipStream>(_decompressedSize, _dataStream, CompressionMode.Decompress);
            _opened        = true;
        }
Beispiel #5
0
        public static string PrettifyHPModePage_3C(HP_ModePage_3C?modePage)
        {
            if (!modePage.HasValue)
            {
                return(null);
            }

            HP_ModePage_3C page = modePage.Value;
            var            sb   = new StringBuilder();

            sb.AppendLine("HP Device Time Mode Page:");

            if (page.PS)
            {
                sb.AppendLine("\tParameters can be saved");
            }

            if (page.PT)
            {
                sb.AppendFormat("\tDrive has been powered up {0} times", page.CurrentPowerOn);

                sb.AppendFormat("\tDrive has been powered up since {0} this time",
                                TimeSpan.FromSeconds(page.PowerOnTime)).AppendLine();

                sb.AppendFormat("\tDrive has been powered up a total of {0}",
                                TimeSpan.FromSeconds(page.CumulativePowerOn)).AppendLine();
            }

            if (page.WT)
            {
                sb.AppendFormat("\tDrive's date/time is: {0}", DateHandlers.UnixUnsignedToDateTime(page.WorldTime)).
                AppendLine();

                if (page.UTC)
                {
                    sb.AppendLine("\tDrive's time is UTC");
                }

                if (page.NTP)
                {
                    sb.AppendLine("\tDrive's time is synchronized with a NTP source");
                }
            }

            if (page.LT)
            {
                sb.AppendFormat("\tLibrary time is {0}",
                                new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, page.LibraryHours,
                                             page.LibraryMinutes, page.LibrarySeconds)).AppendLine();
            }

            return(sb.ToString());
        }
Beispiel #6
0
        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);

            SuperBlock vxSb = Marshal.ByteArrayToStructureLittleEndian <SuperBlock>(sector);

            var 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
            };
        }
Beispiel #7
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            Encoding = encoding ?? Encoding.UTF8;
            ulong vmfsSuperOff = VMFS_BASE / imagePlugin.Info.SectorSize;

            byte[] sector = imagePlugin.ReadSector(partition.Start + vmfsSuperOff);

            VolumeInfo volInfo    = new VolumeInfo();
            IntPtr     volInfoPtr = Marshal.AllocHGlobal(Marshal.SizeOf(volInfo));

            Marshal.Copy(sector, 0, volInfoPtr, Marshal.SizeOf(volInfo));
            volInfo = (VolumeInfo)Marshal.PtrToStructure(volInfoPtr, typeof(VolumeInfo));
            Marshal.FreeHGlobal(volInfoPtr);

            StringBuilder sbInformation = new StringBuilder();

            sbInformation.AppendLine("VMware file system");

            uint ctimeSecs     = (uint)(volInfo.ctime / 1000000);
            uint ctimeNanoSecs = (uint)(volInfo.ctime % 1000000);
            uint mtimeSecs     = (uint)(volInfo.mtime / 1000000);
            uint mtimeNanoSecs = (uint)(volInfo.mtime % 1000000);

            sbInformation.AppendFormat("Volume version {0}", volInfo.version).AppendLine();
            sbInformation.AppendFormat("Volume name {0}", StringHandlers.CToString(volInfo.name, Encoding))
            .AppendLine();
            sbInformation.AppendFormat("Volume size {0} bytes", volInfo.size * 256).AppendLine();
            sbInformation.AppendFormat("Volume UUID {0}", volInfo.uuid).AppendLine();
            sbInformation
            .AppendFormat("Volume created on {0}", DateHandlers.UnixUnsignedToDateTime(ctimeSecs, ctimeNanoSecs))
            .AppendLine();
            sbInformation.AppendFormat("Volume last modified on {0}",
                                       DateHandlers.UnixUnsignedToDateTime(mtimeSecs, mtimeNanoSecs)).AppendLine();

            information = sbInformation.ToString();

            XmlFsType = new FileSystemType
            {
                Type                      = "VMware file system",
                CreationDate              = DateHandlers.UnixUnsignedToDateTime(ctimeSecs, ctimeNanoSecs),
                CreationDateSpecified     = true,
                ModificationDate          = DateHandlers.UnixUnsignedToDateTime(mtimeSecs, mtimeNanoSecs),
                ModificationDateSpecified = true,
                Clusters                  = volInfo.size * 256 / imagePlugin.Info.SectorSize,
                ClusterSize               = (int)imagePlugin.Info.SectorSize,
                VolumeSerial              = volInfo.uuid.ToString()
            };
        }
Beispiel #8
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            Encoding    = encoding ?? Encoding.GetEncoding("iso-8859-15");
            information = "";

            if (imagePlugin.Info.SectorSize < 512)
            {
                return;
            }

            uint sbAddr = REISER_SUPER_OFFSET / imagePlugin.Info.SectorSize;

            if (sbAddr == 0)
            {
                sbAddr = 1;
            }

            uint sbSize = (uint)(Marshal.SizeOf <Reiser_Superblock>() / imagePlugin.Info.SectorSize);

            if (Marshal.SizeOf <Reiser_Superblock>() % imagePlugin.Info.SectorSize != 0)
            {
                sbSize++;
            }

            byte[] sector = imagePlugin.ReadSectors(partition.Start + sbAddr, sbSize);

            if (sector.Length < Marshal.SizeOf <Reiser_Superblock>())
            {
                return;
            }

            Reiser_Superblock reiserSb = Marshal.ByteArrayToStructureLittleEndian <Reiser_Superblock>(sector);

            if (!reiser35_magic.SequenceEqual(reiserSb.magic) &&
                !reiser36_magic.SequenceEqual(reiserSb.magic) &&
                !reiserJr_magic.SequenceEqual(reiserSb.magic))
            {
                return;
            }

            var sb = new StringBuilder();

            if (reiser35_magic.SequenceEqual(reiserSb.magic))
            {
                sb.AppendLine("Reiser 3.5 filesystem");
            }
            else if (reiser36_magic.SequenceEqual(reiserSb.magic))
            {
                sb.AppendLine("Reiser 3.6 filesystem");
            }
            else if (reiserJr_magic.SequenceEqual(reiserSb.magic))
            {
                sb.AppendLine("Reiser Jr. filesystem");
            }

            sb.AppendFormat("Volume has {0} blocks with {1} blocks free", reiserSb.block_count, reiserSb.free_blocks).
            AppendLine();

            sb.AppendFormat("{0} bytes per block", reiserSb.blocksize).AppendLine();
            sb.AppendFormat("Root directory resides on block {0}", reiserSb.root_block).AppendLine();

            if (reiserSb.umount_state == 2)
            {
                sb.AppendLine("Volume has not been cleanly umounted");
            }

            sb.AppendFormat("Volume last checked on {0}", DateHandlers.UnixUnsignedToDateTime(reiserSb.last_check)).
            AppendLine();

            if (reiserSb.version >= 2)
            {
                sb.AppendFormat("Volume UUID: {0}", reiserSb.uuid).AppendLine();
                sb.AppendFormat("Volume name: {0}", Encoding.GetString(reiserSb.label)).AppendLine();
            }

            information = sb.ToString();

            XmlFsType = new FileSystemType();

            if (reiser35_magic.SequenceEqual(reiserSb.magic))
            {
                XmlFsType.Type = "Reiser 3.5 filesystem";
            }
            else if (reiser36_magic.SequenceEqual(reiserSb.magic))
            {
                XmlFsType.Type = "Reiser 3.6 filesystem";
            }
            else if (reiserJr_magic.SequenceEqual(reiserSb.magic))
            {
                XmlFsType.Type = "Reiser Jr. filesystem";
            }

            XmlFsType.ClusterSize           = reiserSb.blocksize;
            XmlFsType.Clusters              = reiserSb.block_count;
            XmlFsType.FreeClusters          = reiserSb.free_blocks;
            XmlFsType.FreeClustersSpecified = true;
            XmlFsType.Dirty = reiserSb.umount_state == 2;

            if (reiserSb.version < 2)
            {
                return;
            }

            XmlFsType.VolumeName   = Encoding.GetString(reiserSb.label);
            XmlFsType.VolumeSerial = reiserSb.uuid.ToString();
        }
Beispiel #9
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            Encoding    = encoding ?? Encoding.GetEncoding("iso-8859-15");
            information = "";

            StringBuilder sb = new StringBuilder();

            bool newExt2 = false;
            bool ext3    = false;
            bool ext4    = false;

            int  sbSizeInBytes   = Marshal.SizeOf(typeof(ext2FSSuperBlock));
            uint sbSizeInSectors = (uint)(sbSizeInBytes / imagePlugin.Info.SectorSize);

            if (sbSizeInBytes % imagePlugin.Info.SectorSize > 0)
            {
                sbSizeInSectors++;
            }

            ulong sbSectorOff = SB_POS / imagePlugin.Info.SectorSize;
            uint  sbOff       = SB_POS % imagePlugin.Info.SectorSize;

            byte[] sbSector = imagePlugin.ReadSectors(sbSectorOff + partition.Start, sbSizeInSectors);
            byte[] sblock   = new byte[sbSizeInBytes];
            Array.Copy(sbSector, sbOff, sblock, 0, sbSizeInBytes);
            IntPtr sbPtr = Marshal.AllocHGlobal(sbSizeInBytes);

            Marshal.Copy(sblock, 0, sbPtr, sbSizeInBytes);
            ext2FSSuperBlock supblk = (ext2FSSuperBlock)Marshal.PtrToStructure(sbPtr, typeof(ext2FSSuperBlock));

            Marshal.FreeHGlobal(sbPtr);

            XmlFsType = new FileSystemType();

            switch (supblk.magic)
            {
            case EXT2_MAGIC_OLD:
                sb.AppendLine("ext2 (old) filesystem");
                XmlFsType.Type = "ext2";
                break;

            case EXT2_MAGIC:
                ext3 |=
                    (supblk.ftr_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) == EXT3_FEATURE_COMPAT_HAS_JOURNAL ||
                    (supblk.ftr_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) == EXT3_FEATURE_INCOMPAT_RECOVER ||
                    (supblk.ftr_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) ==
                    EXT3_FEATURE_INCOMPAT_JOURNAL_DEV;

                if ((supblk.ftr_ro_compat & EXT4_FEATURE_RO_COMPAT_HUGE_FILE) == EXT4_FEATURE_RO_COMPAT_HUGE_FILE ||
                    (supblk.ftr_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM) == EXT4_FEATURE_RO_COMPAT_GDT_CSUM ||
                    (supblk.ftr_ro_compat & EXT4_FEATURE_RO_COMPAT_DIR_NLINK) == EXT4_FEATURE_RO_COMPAT_DIR_NLINK ||
                    (supblk.ftr_ro_compat & EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE) ==
                    EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE ||
                    (supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_64BIT) == EXT4_FEATURE_INCOMPAT_64BIT ||
                    (supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_MMP) == EXT4_FEATURE_INCOMPAT_MMP ||
                    (supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_FLEX_BG) == EXT4_FEATURE_INCOMPAT_FLEX_BG ||
                    (supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_EA_INODE) == EXT4_FEATURE_INCOMPAT_EA_INODE ||
                    (supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_DIRDATA) == EXT4_FEATURE_INCOMPAT_DIRDATA)
                {
                    ext3 = false;
                    ext4 = true;
                }

                newExt2 |= !ext3 && !ext4;

                if (newExt2)
                {
                    sb.AppendLine("ext2 filesystem");
                    XmlFsType.Type = "ext2";
                }

                if (ext3)
                {
                    sb.AppendLine("ext3 filesystem");
                    XmlFsType.Type = "ext3";
                }

                if (ext4)
                {
                    sb.AppendLine("ext4 filesystem");
                    XmlFsType.Type = "ext4";
                }

                break;

            default:
                information = "Not a ext2/3/4 filesystem" + Environment.NewLine;
                return;
            }

            string extOs;

            switch (supblk.creator_os)
            {
            case EXT2_OS_FREEBSD:
                extOs = "FreeBSD";
                break;

            case EXT2_OS_HURD:
                extOs = "Hurd";
                break;

            case EXT2_OS_LINUX:
                extOs = "Linux";
                break;

            case EXT2_OS_LITES:
                extOs = "Lites";
                break;

            case EXT2_OS_MASIX:
                extOs = "MasIX";
                break;

            default:
                extOs = $"Unknown OS ({supblk.creator_os})";
                break;
            }

            XmlFsType.SystemIdentifier = extOs;

            if (supblk.mkfs_t > 0)
            {
                sb.AppendFormat("Volume was created on {0} for {1}", DateHandlers.UnixUnsignedToDateTime(supblk.mkfs_t),
                                extOs).AppendLine();
                XmlFsType.CreationDate          = DateHandlers.UnixUnsignedToDateTime(supblk.mkfs_t);
                XmlFsType.CreationDateSpecified = true;
            }
            else
            {
                sb.AppendFormat("Volume was created for {0}", extOs).AppendLine();
            }

            byte[] tempBytes = new byte[8];
            ulong  blocks, reserved, free;

            if ((supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_64BIT) == EXT4_FEATURE_INCOMPAT_64BIT)
            {
                byte[] tempLo = BitConverter.GetBytes(supblk.blocks);
                byte[] tempHi = BitConverter.GetBytes(supblk.blocks_hi);
                tempBytes[0] = tempLo[0];
                tempBytes[1] = tempLo[1];
                tempBytes[2] = tempLo[2];
                tempBytes[3] = tempLo[3];
                tempBytes[4] = tempHi[0];
                tempBytes[5] = tempHi[1];
                tempBytes[6] = tempHi[2];
                tempBytes[7] = tempHi[3];
                blocks       = BitConverter.ToUInt64(tempBytes, 0);

                tempLo       = BitConverter.GetBytes(supblk.reserved_blocks);
                tempHi       = BitConverter.GetBytes(supblk.reserved_blocks_hi);
                tempBytes[0] = tempLo[0];
                tempBytes[1] = tempLo[1];
                tempBytes[2] = tempLo[2];
                tempBytes[3] = tempLo[3];
                tempBytes[4] = tempHi[0];
                tempBytes[5] = tempHi[1];
                tempBytes[6] = tempHi[2];
                tempBytes[7] = tempHi[3];
                reserved     = BitConverter.ToUInt64(tempBytes, 0);

                tempLo       = BitConverter.GetBytes(supblk.free_blocks);
                tempHi       = BitConverter.GetBytes(supblk.free_blocks_hi);
                tempBytes[0] = tempLo[0];
                tempBytes[1] = tempLo[1];
                tempBytes[2] = tempLo[2];
                tempBytes[3] = tempLo[3];
                tempBytes[4] = tempHi[0];
                tempBytes[5] = tempHi[1];
                tempBytes[6] = tempHi[2];
                tempBytes[7] = tempHi[3];
                free         = BitConverter.ToUInt64(tempBytes, 0);
            }
            else
            {
                blocks   = supblk.blocks;
                reserved = supblk.reserved_blocks;
                free     = supblk.free_blocks;
            }

            if (supblk.block_size == 0) // Then it is 1024 bytes
            {
                supblk.block_size = 1024;
            }

            sb.AppendFormat("Volume has {0} blocks of {1} bytes, for a total of {2} bytes", blocks,
                            1024 << (int)supblk.block_size, blocks * (ulong)(1024 << (int)supblk.block_size))
            .AppendLine();
            XmlFsType.Clusters    = (long)blocks;
            XmlFsType.ClusterSize = 1024 << (int)supblk.block_size;
            if (supblk.mount_t > 0 || supblk.mount_c > 0)
            {
                if (supblk.mount_t > 0)
                {
                    sb.AppendFormat("Last mounted on {0}", DateHandlers.UnixUnsignedToDateTime(supblk.mount_t))
                    .AppendLine();
                }
                if (supblk.max_mount_c != -1)
                {
                    sb.AppendFormat("Volume has been mounted {0} times of a maximum of {1} mounts before checking",
                                    supblk.mount_c, supblk.max_mount_c).AppendLine();
                }
                else
                {
                    sb.AppendFormat("Volume has been mounted {0} times with no maximum no. of mounts before checking",
                                    supblk.mount_c).AppendLine();
                }
                if (!string.IsNullOrEmpty(StringHandlers.CToString(supblk.last_mount_dir, Encoding)))
                {
                    sb.AppendFormat("Last mounted on: \"{0}\"",
                                    StringHandlers.CToString(supblk.last_mount_dir, Encoding)).AppendLine();
                }
                if (!string.IsNullOrEmpty(StringHandlers.CToString(supblk.mount_options, Encoding)))
                {
                    sb.AppendFormat("Last used mount options were: {0}",
                                    StringHandlers.CToString(supblk.mount_options, Encoding)).AppendLine();
                }
            }
            else
            {
                sb.AppendLine("Volume has never been mounted");
                if (supblk.max_mount_c != -1)
                {
                    sb.AppendFormat("Volume can be mounted {0} times before checking", supblk.max_mount_c).AppendLine();
                }
                else
                {
                    sb.AppendLine("Volume has no maximum no. of mounts before checking");
                }
            }

            if (supblk.check_t > 0)
            {
                if (supblk.check_inv > 0)
                {
                    sb.AppendFormat("Last checked on {0} (should check every {1} seconds)",
                                    DateHandlers.UnixUnsignedToDateTime(supblk.check_t), supblk.check_inv).AppendLine();
                }
                else
                {
                    sb.AppendFormat("Last checked on {0}", DateHandlers.UnixUnsignedToDateTime(supblk.check_t))
                    .AppendLine();
                }
            }
            else
            {
                if (supblk.check_inv > 0)
                {
                    sb.AppendFormat("Volume has never been checked (should check every {0})", supblk.check_inv)
                    .AppendLine();
                }
                else
                {
                    sb.AppendLine("Volume has never been checked");
                }
            }

            if (supblk.write_t > 0)
            {
                sb.AppendFormat("Last written on {0}", DateHandlers.UnixUnsignedToDateTime(supblk.write_t))
                .AppendLine();
                XmlFsType.ModificationDate          = DateHandlers.UnixUnsignedToDateTime(supblk.write_t);
                XmlFsType.ModificationDateSpecified = true;
            }
            else
            {
                sb.AppendLine("Volume has never been written");
            }

            XmlFsType.Dirty = true;
            switch (supblk.state)
            {
            case EXT2_VALID_FS:
                sb.AppendLine("Volume is clean");
                XmlFsType.Dirty = false;
                break;

            case EXT2_ERROR_FS:
                sb.AppendLine("Volume is dirty");
                break;

            case EXT3_ORPHAN_FS:
                sb.AppendLine("Volume is recovering orphan files");
                break;

            default:
                sb.AppendFormat("Volume is in an unknown state ({0})", supblk.state).AppendLine();
                break;
            }

            if (!string.IsNullOrEmpty(StringHandlers.CToString(supblk.volume_name, Encoding)))
            {
                sb.AppendFormat("Volume name: \"{0}\"", StringHandlers.CToString(supblk.volume_name, Encoding))
                .AppendLine();
                XmlFsType.VolumeName = StringHandlers.CToString(supblk.volume_name, Encoding);
            }

            switch (supblk.err_behaviour)
            {
            case EXT2_ERRORS_CONTINUE:
                sb.AppendLine("On errors, filesystem should continue");
                break;

            case EXT2_ERRORS_RO:
                sb.AppendLine("On errors, filesystem should remount read-only");
                break;

            case EXT2_ERRORS_PANIC:
                sb.AppendLine("On errors, filesystem should panic");
                break;

            default:
                sb.AppendFormat("On errors filesystem will do an unknown thing ({0})", supblk.err_behaviour)
                .AppendLine();
                break;
            }

            if (supblk.revision > 0)
            {
                sb.AppendFormat("Filesystem revision: {0}.{1}", supblk.revision, supblk.minor_revision).AppendLine();
            }

            if (supblk.uuid != Guid.Empty)
            {
                sb.AppendFormat("Volume UUID: {0}", supblk.uuid).AppendLine();
                XmlFsType.VolumeSerial = supblk.uuid.ToString();
            }

            if (supblk.kbytes_written > 0)
            {
                sb.AppendFormat("{0} KiB has been written on volume", supblk.kbytes_written).AppendLine();
            }

            sb.AppendFormat("{0} reserved and {1} free blocks", reserved, free).AppendLine();
            XmlFsType.FreeClusters          = (long)free;
            XmlFsType.FreeClustersSpecified = true;
            sb.AppendFormat("{0} inodes with {1} free inodes ({2}%)", supblk.inodes, supblk.free_inodes,
                            supblk.free_inodes * 100 / supblk.inodes).AppendLine();
            if (supblk.first_inode > 0)
            {
                sb.AppendFormat("First inode is {0}", supblk.first_inode).AppendLine();
            }
            if (supblk.frag_size > 0)
            {
                sb.AppendFormat("{0} bytes per fragment", supblk.frag_size).AppendLine();
            }
            if (supblk.blocks_per_grp > 0 && supblk.flags_per_grp > 0 && supblk.inodes_per_grp > 0)
            {
                sb.AppendFormat("{0} blocks, {1} flags and {2} inodes per group", supblk.blocks_per_grp,
                                supblk.flags_per_grp, supblk.inodes_per_grp).AppendLine();
            }
            if (supblk.first_block > 0)
            {
                sb.AppendFormat("{0} is first data block", supblk.first_block).AppendLine();
            }
            sb.AppendFormat("Default UID: {0}, GID: {1}", supblk.default_uid, supblk.default_gid).AppendLine();
            if (supblk.block_group_no > 0)
            {
                sb.AppendFormat("Block group number is {0}", supblk.block_group_no).AppendLine();
            }
            if (supblk.desc_grp_size > 0)
            {
                sb.AppendFormat("Group descriptor size is {0} bytes", supblk.desc_grp_size).AppendLine();
            }
            if (supblk.first_meta_bg > 0)
            {
                sb.AppendFormat("First metablock group is {0}", supblk.first_meta_bg).AppendLine();
            }
            if (supblk.raid_stride > 0)
            {
                sb.AppendFormat("RAID stride: {0}", supblk.raid_stride).AppendLine();
            }
            if (supblk.raid_stripe_width > 0)
            {
                sb.AppendFormat("{0} blocks on all data disks", supblk.raid_stripe_width).AppendLine();
            }
            if (supblk.mmp_interval > 0 && supblk.mmp_block > 0)
            {
                sb.AppendFormat("{0} seconds for multi-mount protection wait, on block {1}", supblk.mmp_interval,
                                supblk.mmp_block).AppendLine();
            }
            if (supblk.flex_bg_grp_size > 0)
            {
                sb.AppendFormat("{0} Flexible block group size", supblk.flex_bg_grp_size).AppendLine();
            }
            if (supblk.hash_seed_1 > 0 && supblk.hash_seed_2 > 0 && supblk.hash_seed_3 > 0 && supblk.hash_seed_4 > 0)
            {
                sb.AppendFormat("Hash seed: {0:X8}{1:X8}{2:X8}{3:X8}, version {4}", supblk.hash_seed_1,
                                supblk.hash_seed_2, supblk.hash_seed_3, supblk.hash_seed_4, supblk.hash_version)
                .AppendLine();
            }

            if ((supblk.ftr_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) == EXT3_FEATURE_COMPAT_HAS_JOURNAL ||
                (supblk.ftr_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) == EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
            {
                sb.AppendLine("Volume is journaled");
                if (supblk.journal_uuid != Guid.Empty)
                {
                    sb.AppendFormat("Journal UUID: {0}", supblk.journal_uuid).AppendLine();
                }
                sb.AppendFormat("Journal has inode {0}", supblk.journal_inode).AppendLine();
                if ((supblk.ftr_compat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) == EXT3_FEATURE_INCOMPAT_JOURNAL_DEV &&
                    supblk.journal_dev > 0)
                {
                    sb.AppendFormat("Journal is on device {0}", supblk.journal_dev).AppendLine();
                }
                if (supblk.jnl_backup_type > 0)
                {
                    sb.AppendFormat("Journal backup type: {0}", supblk.jnl_backup_type).AppendLine();
                }
                if (supblk.last_orphan > 0)
                {
                    sb.AppendFormat("Last orphaned inode is {0}", supblk.last_orphan).AppendLine();
                }
                else
                {
                    sb.AppendLine("There are no orphaned inodes");
                }
            }

            if (ext4)
            {
                if (supblk.snapshot_id > 0)
                {
                    sb
                    .AppendFormat("Active snapshot has ID {0}, on inode {1}, with {2} blocks reserved, list starting on block {3}",
                                  supblk.snapshot_id, supblk.snapshot_inum, supblk.snapshot_blocks,
                                  supblk.snapshot_list).AppendLine();
                }

                if (supblk.error_count > 0)
                {
                    sb.AppendFormat("{0} errors registered", supblk.error_count).AppendLine();
                    sb.AppendFormat("First error occurred on {0}, last on {1}",
                                    DateHandlers.UnixUnsignedToDateTime(supblk.first_error_t),
                                    DateHandlers.UnixUnsignedToDateTime(supblk.last_error_t)).AppendLine();
                    sb.AppendFormat("First error inode is {0}, last is {1}", supblk.first_error_inode,
                                    supblk.last_error_inode).AppendLine();
                    sb.AppendFormat("First error block is {0}, last is {1}", supblk.first_error_block,
                                    supblk.last_error_block).AppendLine();
                    sb.AppendFormat("First error function is \"{0}\", last is \"{1}\"", supblk.first_error_func,
                                    supblk.last_error_func).AppendLine();
                }
            }

            sb.AppendFormat("Flags…:").AppendLine();
            if ((supblk.flags & EXT2_FLAGS_SIGNED_HASH) == EXT2_FLAGS_SIGNED_HASH)
            {
                sb.AppendLine("Signed directory hash is in use");
            }
            if ((supblk.flags & EXT2_FLAGS_UNSIGNED_HASH) == EXT2_FLAGS_UNSIGNED_HASH)
            {
                sb.AppendLine("Unsigned directory hash is in use");
            }
            if ((supblk.flags & EXT2_FLAGS_TEST_FILESYS) == EXT2_FLAGS_TEST_FILESYS)
            {
                sb.AppendLine("Volume is testing development code");
            }
            if ((supblk.flags & 0xFFFFFFF8) != 0)
            {
                sb.AppendFormat("Unknown set flags: {0:X8}", supblk.flags);
            }

            sb.AppendLine();

            sb.AppendFormat("Default mount options…:").AppendLine();
            if ((supblk.default_mnt_opts & EXT2_DEFM_DEBUG) == EXT2_DEFM_DEBUG)
            {
                sb.AppendLine("(debug): Enable debugging code");
            }
            if ((supblk.default_mnt_opts & EXT2_DEFM_BSDGROUPS) == EXT2_DEFM_BSDGROUPS)
            {
                sb.AppendLine("(bsdgroups): Emulate BSD behaviour when creating new files");
            }
            if ((supblk.default_mnt_opts & EXT2_DEFM_XATTR_USER) == EXT2_DEFM_XATTR_USER)
            {
                sb.AppendLine("(user_xattr): Enable user-specified extended attributes");
            }
            if ((supblk.default_mnt_opts & EXT2_DEFM_ACL) == EXT2_DEFM_ACL)
            {
                sb.AppendLine("(acl): Enable POSIX ACLs");
            }
            if ((supblk.default_mnt_opts & EXT2_DEFM_UID16) == EXT2_DEFM_UID16)
            {
                sb.AppendLine("(uid16): Disable 32bit UIDs and GIDs");
            }
            if ((supblk.default_mnt_opts & EXT3_DEFM_JMODE_DATA) == EXT3_DEFM_JMODE_DATA)
            {
                sb.AppendLine("(journal_data): Journal data and metadata");
            }
            if ((supblk.default_mnt_opts & EXT3_DEFM_JMODE_ORDERED) == EXT3_DEFM_JMODE_ORDERED)
            {
                sb.AppendLine("(journal_data_ordered): Write data before journaling metadata");
            }
            if ((supblk.default_mnt_opts & EXT3_DEFM_JMODE_WBACK) == EXT3_DEFM_JMODE_WBACK)
            {
                sb.AppendLine("(journal_data_writeback): Write journal before data");
            }
            if ((supblk.default_mnt_opts & 0xFFFFFE20) != 0)
            {
                sb.AppendFormat("Unknown set default mount options: {0:X8}", supblk.default_mnt_opts);
            }

            sb.AppendLine();

            sb.AppendFormat("Compatible features…:").AppendLine();
            if ((supblk.ftr_compat & EXT2_FEATURE_COMPAT_DIR_PREALLOC) == EXT2_FEATURE_COMPAT_DIR_PREALLOC)
            {
                sb.AppendLine("Pre-allocate directories");
            }
            if ((supblk.ftr_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES) == EXT2_FEATURE_COMPAT_IMAGIC_INODES)
            {
                sb.AppendLine("imagic inodes ?");
            }
            if ((supblk.ftr_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) == EXT3_FEATURE_COMPAT_HAS_JOURNAL)
            {
                sb.AppendLine("Has journal (ext3)");
            }
            if ((supblk.ftr_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) == EXT2_FEATURE_COMPAT_EXT_ATTR)
            {
                sb.AppendLine("Has extended attribute blocks");
            }
            if ((supblk.ftr_compat & EXT2_FEATURE_COMPAT_RESIZE_INO) == EXT2_FEATURE_COMPAT_RESIZE_INO)
            {
                sb.AppendLine("Has online filesystem resize reservations");
            }
            if ((supblk.ftr_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) == EXT2_FEATURE_COMPAT_DIR_INDEX)
            {
                sb.AppendLine("Can use hashed indexes on directories");
            }
            if ((supblk.ftr_compat & 0xFFFFFFC0) != 0)
            {
                sb.AppendFormat("Unknown compatible features: {0:X8}", supblk.ftr_compat);
            }

            sb.AppendLine();

            sb.AppendFormat("Compatible features if read-only…:").AppendLine();
            if ((supblk.ftr_ro_compat & EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) == EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)
            {
                sb.AppendLine("Reduced number of superblocks");
            }
            if ((supblk.ftr_ro_compat & EXT2_FEATURE_RO_COMPAT_LARGE_FILE) == EXT2_FEATURE_RO_COMPAT_LARGE_FILE)
            {
                sb.AppendLine("Can have files bigger than 2GiB");
            }
            if ((supblk.ftr_ro_compat & EXT2_FEATURE_RO_COMPAT_BTREE_DIR) == EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
            {
                sb.AppendLine("Uses B-Tree for directories");
            }
            if ((supblk.ftr_ro_compat & EXT4_FEATURE_RO_COMPAT_HUGE_FILE) == EXT4_FEATURE_RO_COMPAT_HUGE_FILE)
            {
                sb.AppendLine("Can have files bigger than 2TiB (ext4)");
            }
            if ((supblk.ftr_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM) == EXT4_FEATURE_RO_COMPAT_GDT_CSUM)
            {
                sb.AppendLine("Group descriptor checksums and sparse inode table (ext4)");
            }
            if ((supblk.ftr_ro_compat & EXT4_FEATURE_RO_COMPAT_DIR_NLINK) == EXT4_FEATURE_RO_COMPAT_DIR_NLINK)
            {
                sb.AppendLine("More than 32000 directory entries (ext4)");
            }
            if ((supblk.ftr_ro_compat & EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE) == EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE)
            {
                sb.AppendLine("Supports nanosecond timestamps and creation time (ext4)");
            }
            if ((supblk.ftr_ro_compat & 0xFFFFFF80) != 0)
            {
                sb.AppendFormat("Unknown read-only compatible features: {0:X8}", supblk.ftr_ro_compat);
            }

            sb.AppendLine();

            sb.AppendFormat("Incompatible features…:").AppendLine();
            if ((supblk.ftr_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION) == EXT2_FEATURE_INCOMPAT_COMPRESSION)
            {
                sb.AppendLine("Uses compression");
            }
            if ((supblk.ftr_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE) == EXT2_FEATURE_INCOMPAT_FILETYPE)
            {
                sb.AppendLine("Filetype in directory entries");
            }
            if ((supblk.ftr_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) == EXT3_FEATURE_INCOMPAT_RECOVER)
            {
                sb.AppendLine("Journal needs recovery (ext3)");
            }
            if ((supblk.ftr_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) == EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
            {
                sb.AppendLine("Has journal on another device (ext3)");
            }
            if ((supblk.ftr_incompat & EXT2_FEATURE_INCOMPAT_META_BG) == EXT2_FEATURE_INCOMPAT_META_BG)
            {
                sb.AppendLine("Reduced block group backups");
            }
            if ((supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_EXTENTS) == EXT4_FEATURE_INCOMPAT_EXTENTS)
            {
                sb.AppendLine("Volume use extents (ext4)");
            }
            if ((supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_64BIT) == EXT4_FEATURE_INCOMPAT_64BIT)
            {
                sb.AppendLine("Supports volumes bigger than 2^32 blocks (ext4)");
            }
            if ((supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_MMP) == EXT4_FEATURE_INCOMPAT_MMP)
            {
                sb.AppendLine("Multi-mount protection (ext4)");
            }
            if ((supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_FLEX_BG) == EXT4_FEATURE_INCOMPAT_FLEX_BG)
            {
                sb.AppendLine("Flexible block group metadata location (ext4)");
            }
            if ((supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_EA_INODE) == EXT4_FEATURE_INCOMPAT_EA_INODE)
            {
                sb.AppendLine("Extended attributes can reside in inode (ext4)");
            }
            if ((supblk.ftr_incompat & EXT4_FEATURE_INCOMPAT_DIRDATA) == EXT4_FEATURE_INCOMPAT_DIRDATA)
            {
                sb.AppendLine("Data can reside in directory entry (ext4)");
            }
            if ((supblk.ftr_incompat & 0xFFFFF020) != 0)
            {
                sb.AppendFormat("Unknown incompatible features: {0:X8}", supblk.ftr_incompat);
            }

            information = sb.ToString();
        }
Beispiel #10
0
        public void Open(string path)
        {
            FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);

            fs.Seek(0, SeekOrigin.Begin);

            byte[] hdr_b = new byte[26];
            fs.Read(hdr_b, 0, 26);
            header = Marshal.ByteArrayToStructureBigEndian <AppleSingleHeader>(hdr_b);

            AppleSingleEntry[] entries = new AppleSingleEntry[header.entries];
            for (int i = 0; i < header.entries; i++)
            {
                byte[] entry = new byte[12];
                fs.Read(entry, 0, 12);
                entries[i] = Marshal.ByteArrayToStructureBigEndian <AppleSingleEntry>(entry);
            }

            creationTime  = DateTime.UtcNow;
            lastWriteTime = creationTime;
            foreach (AppleSingleEntry entry in entries)
            {
                switch ((AppleSingleEntryID)entry.id)
                {
                case AppleSingleEntryID.DataFork:
                    dataFork = entry;
                    break;

                case AppleSingleEntryID.FileDates:
                    fs.Seek(entry.offset, SeekOrigin.Begin);
                    byte[] dates_b = new byte[16];
                    fs.Read(dates_b, 0, 16);
                    AppleSingleFileDates dates =
                        Marshal.ByteArrayToStructureBigEndian <AppleSingleFileDates>(dates_b);
                    creationTime  = DateHandlers.MacToDateTime(dates.creationDate);
                    lastWriteTime = DateHandlers.MacToDateTime(dates.modificationDate);
                    break;

                case AppleSingleEntryID.FileInfo:
                    fs.Seek(entry.offset, SeekOrigin.Begin);
                    byte[] finfo = new byte[entry.length];
                    fs.Read(finfo, 0, finfo.Length);
                    if (MacintoshHome.SequenceEqual(header.homeFilesystem))
                    {
                        AppleSingleMacFileInfo macinfo =
                            Marshal.ByteArrayToStructureBigEndian <AppleSingleMacFileInfo>(finfo);
                        creationTime  = DateHandlers.MacToDateTime(macinfo.creationDate);
                        lastWriteTime = DateHandlers.MacToDateTime(macinfo.modificationDate);
                    }
                    else if (ProDOSHome.SequenceEqual(header.homeFilesystem))
                    {
                        AppleSingleProDOSFileInfo prodosinfo =
                            Marshal.ByteArrayToStructureBigEndian <AppleSingleProDOSFileInfo>(finfo);
                        creationTime  = DateHandlers.MacToDateTime(prodosinfo.creationDate);
                        lastWriteTime = DateHandlers.MacToDateTime(prodosinfo.modificationDate);
                    }
                    else if (UNIXHome.SequenceEqual(header.homeFilesystem))
                    {
                        AppleSingleUNIXFileInfo unixinfo =
                            Marshal.ByteArrayToStructureBigEndian <AppleSingleUNIXFileInfo>(finfo);
                        creationTime  = DateHandlers.UnixUnsignedToDateTime(unixinfo.creationDate);
                        lastWriteTime = DateHandlers.UnixUnsignedToDateTime(unixinfo.modificationDate);
                    }
                    else if (DOSHome.SequenceEqual(header.homeFilesystem))
                    {
                        AppleSingleDOSFileInfo dosinfo =
                            Marshal.ByteArrayToStructureBigEndian <AppleSingleDOSFileInfo>(finfo);
                        lastWriteTime =
                            DateHandlers.DosToDateTime(dosinfo.modificationDate, dosinfo.modificationTime);
                    }

                    break;

                case AppleSingleEntryID.ResourceFork:
                    rsrcFork = entry;
                    break;
                }
            }

            fs.Close();
            opened   = true;
            isPath   = true;
            basePath = path;
        }
Beispiel #11
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            Encoding    = encoding ?? Encoding.GetEncoding("iso-8859-15");
            information = "";
            var  sb          = new StringBuilder();
            uint bootSectors = JFS_BOOT_BLOCKS_SIZE / imagePlugin.Info.SectorSize;

            byte[] sector = imagePlugin.ReadSector(partition.Start + bootSectors);

            if (sector.Length < 512)
            {
                return;
            }

            JfsSuperBlock jfsSb = Marshal.ByteArrayToStructureLittleEndian <JfsSuperBlock>(sector);

            sb.AppendLine("JFS filesystem");
            sb.AppendFormat("Version {0}", jfsSb.s_version).AppendLine();
            sb.AppendFormat("{0} blocks of {1} bytes", jfsSb.s_size, jfsSb.s_bsize).AppendLine();
            sb.AppendFormat("{0} blocks per allocation group", jfsSb.s_agsize).AppendLine();

            if (jfsSb.s_flags.HasFlag(JfsFlags.Unicode))
            {
                sb.AppendLine("Volume uses Unicode for directory entries");
            }

            if (jfsSb.s_flags.HasFlag(JfsFlags.RemountRO))
            {
                sb.AppendLine("Volume remounts read-only on error");
            }

            if (jfsSb.s_flags.HasFlag(JfsFlags.Continue))
            {
                sb.AppendLine("Volume continues on error");
            }

            if (jfsSb.s_flags.HasFlag(JfsFlags.Panic))
            {
                sb.AppendLine("Volume panics on error");
            }

            if (jfsSb.s_flags.HasFlag(JfsFlags.UserQuota))
            {
                sb.AppendLine("Volume has user quotas enabled");
            }

            if (jfsSb.s_flags.HasFlag(JfsFlags.GroupQuota))
            {
                sb.AppendLine("Volume has group quotas enabled");
            }

            if (jfsSb.s_flags.HasFlag(JfsFlags.NoJournal))
            {
                sb.AppendLine("Volume is not using any journal");
            }

            if (jfsSb.s_flags.HasFlag(JfsFlags.Discard))
            {
                sb.AppendLine("Volume sends TRIM/UNMAP commands to underlying device");
            }

            if (jfsSb.s_flags.HasFlag(JfsFlags.GroupCommit))
            {
                sb.AppendLine("Volume commits in groups of 1");
            }

            if (jfsSb.s_flags.HasFlag(JfsFlags.LazyCommit))
            {
                sb.AppendLine("Volume commits lazy");
            }

            if (jfsSb.s_flags.HasFlag(JfsFlags.Temporary))
            {
                sb.AppendLine("Volume does not commit to log");
            }

            if (jfsSb.s_flags.HasFlag(JfsFlags.InlineLog))
            {
                sb.AppendLine("Volume has log withing itself");
            }

            if (jfsSb.s_flags.HasFlag(JfsFlags.InlineMoving))
            {
                sb.AppendLine("Volume has log withing itself and is moving it out");
            }

            if (jfsSb.s_flags.HasFlag(JfsFlags.BadSAIT))
            {
                sb.AppendLine("Volume has bad current secondary ait");
            }

            if (jfsSb.s_flags.HasFlag(JfsFlags.Sparse))
            {
                sb.AppendLine("Volume supports sparse files");
            }

            if (jfsSb.s_flags.HasFlag(JfsFlags.DASDEnabled))
            {
                sb.AppendLine("Volume has DASD limits enabled");
            }

            if (jfsSb.s_flags.HasFlag(JfsFlags.DASDPrime))
            {
                sb.AppendLine("Volume primes DASD on boot");
            }

            if (jfsSb.s_flags.HasFlag(JfsFlags.SwapBytes))
            {
                sb.AppendLine("Volume is in a big-endian system");
            }

            if (jfsSb.s_flags.HasFlag(JfsFlags.DirIndex))
            {
                sb.AppendLine("Volume has presistent indexes");
            }

            if (jfsSb.s_flags.HasFlag(JfsFlags.Linux))
            {
                sb.AppendLine("Volume supports Linux");
            }

            if (jfsSb.s_flags.HasFlag(JfsFlags.DFS))
            {
                sb.AppendLine("Volume supports DCE DFS LFS");
            }

            if (jfsSb.s_flags.HasFlag(JfsFlags.OS2))
            {
                sb.AppendLine("Volume supports OS/2, and is case insensitive");
            }

            if (jfsSb.s_flags.HasFlag(JfsFlags.AIX))
            {
                sb.AppendLine("Volume supports AIX");
            }

            if (jfsSb.s_state != 0)
            {
                sb.AppendLine("Volume is dirty");
            }

            sb.AppendFormat("Volume was last updated on {0}",
                            DateHandlers.UnixUnsignedToDateTime(jfsSb.s_time.tv_sec, jfsSb.s_time.tv_nsec)).
            AppendLine();

            if (jfsSb.s_version == 1)
            {
                sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(jfsSb.s_fpack, Encoding)).AppendLine();
            }
            else
            {
                sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(jfsSb.s_label, Encoding)).AppendLine();
            }

            sb.AppendFormat("Volume UUID: {0}", jfsSb.s_uuid).AppendLine();

            XmlFsType = new FileSystemType
            {
                Type       = "JFS filesystem", Clusters = jfsSb.s_size, ClusterSize = jfsSb.s_bsize,
                Bootable   = true,
                VolumeName =
                    StringHandlers.CToString(jfsSb.s_version == 1 ? jfsSb.s_fpack : jfsSb.s_label, Encoding),
                VolumeSerial     = $"{jfsSb.s_uuid}",
                ModificationDate =
                    DateHandlers.UnixUnsignedToDateTime(jfsSb.s_time.tv_sec, jfsSb.s_time.tv_nsec),
                ModificationDateSpecified = true
            };

            if (jfsSb.s_state != 0)
            {
                XmlFsType.Dirty = true;
            }

            information = sb.ToString();
        }
Beispiel #12
0
        public bool Open(IFilter imageFilter)
        {
            Stream stream = imageFilter.GetDataForkStream();

            stream.Seek(0, SeekOrigin.Begin);

            if (stream.Length < 512)
            {
                return(false);
            }

            byte[] qHdrB = new byte[48];
            stream.Read(qHdrB, 0, 48);
            qHdr = Marshal.SpanToStructureBigEndian <QCowHeader>(qHdrB);

            AaruConsole.DebugWriteLine("QCOW plugin", "qHdr.magic = 0x{0:X8}", qHdr.magic);
            AaruConsole.DebugWriteLine("QCOW plugin", "qHdr.version = {0}", qHdr.version);
            AaruConsole.DebugWriteLine("QCOW plugin", "qHdr.backing_file_offset = {0}", qHdr.backing_file_offset);
            AaruConsole.DebugWriteLine("QCOW plugin", "qHdr.backing_file_size = {0}", qHdr.backing_file_size);
            AaruConsole.DebugWriteLine("QCOW plugin", "qHdr.mtime = {0}", qHdr.mtime);
            AaruConsole.DebugWriteLine("QCOW plugin", "qHdr.size = {0}", qHdr.size);
            AaruConsole.DebugWriteLine("QCOW plugin", "qHdr.cluster_bits = {0}", qHdr.cluster_bits);
            AaruConsole.DebugWriteLine("QCOW plugin", "qHdr.l2_bits = {0}", qHdr.l2_bits);
            AaruConsole.DebugWriteLine("QCOW plugin", "qHdr.padding = {0}", qHdr.padding);
            AaruConsole.DebugWriteLine("QCOW plugin", "qHdr.crypt_method = {0}", qHdr.crypt_method);
            AaruConsole.DebugWriteLine("QCOW plugin", "qHdr.l1_table_offset = {0}", qHdr.l1_table_offset);

            if (qHdr.size <= 1)
            {
                throw new ArgumentOutOfRangeException(nameof(qHdr.size), "Image size is too small");
            }

            if (qHdr.cluster_bits < 9 ||
                qHdr.cluster_bits > 16)
            {
                throw new ArgumentOutOfRangeException(nameof(qHdr.cluster_bits),
                                                      "Cluster size must be between 512 bytes and 64 Kbytes");
            }

            if (qHdr.l2_bits < 9 - 3 ||
                qHdr.l2_bits > 16 - 3)
            {
                throw new ArgumentOutOfRangeException(nameof(qHdr.l2_bits),
                                                      "L2 size must be between 512 bytes and 64 Kbytes");
            }

            if (qHdr.crypt_method > QCOW_ENCRYPTION_AES)
            {
                throw new ArgumentOutOfRangeException(nameof(qHdr.crypt_method), "Invalid encryption method");
            }

            if (qHdr.crypt_method > QCOW_ENCRYPTION_NONE)
            {
                throw new NotImplementedException("AES encrypted images not yet supported");
            }

            if (qHdr.backing_file_offset != 0)
            {
                throw new NotImplementedException("Differencing images not yet supported");
            }

            int shift = qHdr.cluster_bits + qHdr.l2_bits;

            if (qHdr.size > ulong.MaxValue - (ulong)(1 << shift))
            {
                throw new ArgumentOutOfRangeException(nameof(qHdr.size), "Image is too large");
            }

            clusterSize    = 1 << qHdr.cluster_bits;
            clusterSectors = 1 << (qHdr.cluster_bits - 9);
            l1Size         = (uint)(((qHdr.size + (ulong)(1 << shift)) - 1) >> shift);
            l2Size         = 1 << qHdr.l2_bits;

            AaruConsole.DebugWriteLine("QCOW plugin", "qHdr.clusterSize = {0}", clusterSize);
            AaruConsole.DebugWriteLine("QCOW plugin", "qHdr.clusterSectors = {0}", clusterSectors);
            AaruConsole.DebugWriteLine("QCOW plugin", "qHdr.l1Size = {0}", l1Size);
            AaruConsole.DebugWriteLine("QCOW plugin", "qHdr.l2Size = {0}", l2Size);
            AaruConsole.DebugWriteLine("QCOW plugin", "qHdr.sectors = {0}", imageInfo.Sectors);

            byte[] l1TableB = new byte[l1Size * 8];
            stream.Seek((long)qHdr.l1_table_offset, SeekOrigin.Begin);
            stream.Read(l1TableB, 0, (int)l1Size * 8);
            l1Table = MemoryMarshal.Cast <byte, ulong>(l1TableB).ToArray();
            AaruConsole.DebugWriteLine("QCOW plugin", "Reading L1 table");

            for (long i = 0; i < l1Table.LongLength; i++)
            {
                l1Table[i] = Swapping.Swap(l1Table[i]);
            }

            l1Mask = 0;
            int c = 0;

            l1Shift = qHdr.l2_bits + qHdr.cluster_bits;

            for (int i = 0; i < 64; i++)
            {
                l1Mask <<= 1;

                if (c >= 64 - l1Shift)
                {
                    continue;
                }

                l1Mask += 1;
                c++;
            }

            l2Mask = 0;

            for (int i = 0; i < qHdr.l2_bits; i++)
            {
                l2Mask = (l2Mask << 1) + 1;
            }

            l2Mask <<= qHdr.cluster_bits;

            sectorMask = 0;

            for (int i = 0; i < qHdr.cluster_bits; i++)
            {
                sectorMask = (sectorMask << 1) + 1;
            }

            AaruConsole.DebugWriteLine("QCOW plugin", "qHdr.l1Mask = {0:X}", l1Mask);
            AaruConsole.DebugWriteLine("QCOW plugin", "qHdr.l1Shift = {0}", l1Shift);
            AaruConsole.DebugWriteLine("QCOW plugin", "qHdr.l2Mask = {0:X}", l2Mask);
            AaruConsole.DebugWriteLine("QCOW plugin", "qHdr.sectorMask = {0:X}", sectorMask);

            maxL2TableCache = MAX_CACHE_SIZE / (l2Size * 8);
            maxClusterCache = MAX_CACHE_SIZE / clusterSize;

            imageStream = stream;

            sectorCache  = new Dictionary <ulong, byte[]>();
            l2TableCache = new Dictionary <ulong, ulong[]>();
            clusterCache = new Dictionary <ulong, byte[]>();

            imageInfo.CreationTime = imageFilter.GetCreationTime();

            imageInfo.LastModificationTime = qHdr.mtime > 0 ? DateHandlers.UnixUnsignedToDateTime(qHdr.mtime)
                                                 : imageFilter.GetLastWriteTime();

            imageInfo.MediaTitle   = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
            imageInfo.Sectors      = qHdr.size / 512;
            imageInfo.SectorSize   = 512;
            imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
            imageInfo.MediaType    = MediaType.GENERIC_HDD;
            imageInfo.ImageSize    = qHdr.size;

            imageInfo.Cylinders       = (uint)(imageInfo.Sectors / 16 / 63);
            imageInfo.Heads           = 16;
            imageInfo.SectorsPerTrack = 63;

            return(true);
        }
Beispiel #13
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            Encoding = encoding ?? Encoding.UTF8;
            byte[] sector = imagePlugin.ReadSector(partition.Start);
            uint   magic  = BitConverter.ToUInt32(sector, 0x00);

            var  sqSb         = new SquashSuperBlock();
            bool littleEndian = true;

            switch (magic)
            {
            case SQUASH_MAGIC:
                sqSb = Marshal.ByteArrayToStructureLittleEndian <SquashSuperBlock>(sector);

                break;

            case SQUASH_CIGAM:
                sqSb         = Marshal.ByteArrayToStructureBigEndian <SquashSuperBlock>(sector);
                littleEndian = false;

                break;
            }

            var sbInformation = new StringBuilder();

            sbInformation.AppendLine("Squash file system");
            sbInformation.AppendLine(littleEndian ? "Little-endian" : "Big-endian");
            sbInformation.AppendFormat("Volume version {0}.{1}", sqSb.s_major, sqSb.s_minor).AppendLine();
            sbInformation.AppendFormat("Volume has {0} bytes", sqSb.bytes_used).AppendLine();
            sbInformation.AppendFormat("Volume has {0} bytes per block", sqSb.block_size).AppendLine();

            sbInformation.AppendFormat("Volume created on {0}", DateHandlers.UnixUnsignedToDateTime(sqSb.mkfs_time)).
            AppendLine();

            sbInformation.AppendFormat("Volume has {0} inodes", sqSb.inodes).AppendLine();

            switch (sqSb.compression)
            {
            case (ushort)SquashCompression.Lz4:
                sbInformation.AppendLine("Volume is compressed using LZ4");

                break;

            case (ushort)SquashCompression.Lzo:
                sbInformation.AppendLine("Volume is compressed using LZO");

                break;

            case (ushort)SquashCompression.Lzma:
                sbInformation.AppendLine("Volume is compressed using LZMA");

                break;

            case (ushort)SquashCompression.Xz:
                sbInformation.AppendLine("Volume is compressed using XZ");

                break;

            case (ushort)SquashCompression.Zlib:
                sbInformation.AppendLine("Volume is compressed using GZIP");

                break;

            case (ushort)SquashCompression.Zstd:
                sbInformation.AppendLine("Volume is compressed using Zstandard");

                break;

            default:
                sbInformation.AppendFormat("Volume is compressed using unknown algorithm {0}", sqSb.compression).
                AppendLine();

                break;
            }

            information = sbInformation.ToString();

            XmlFsType = new FileSystemType
            {
                Type                  = "Squash file system",
                CreationDate          = DateHandlers.UnixUnsignedToDateTime(sqSb.mkfs_time),
                CreationDateSpecified = true,
                Clusters              = (((partition.End - partition.Start) + 1) * imagePlugin.Info.SectorSize) /
                                        sqSb.block_size,
                ClusterSize           = sqSb.block_size, Files = sqSb.inodes, FilesSpecified = true, FreeClusters = 0,
                FreeClustersSpecified = true
            };
        }
Beispiel #14
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            Encoding    = encoding ?? Encoding.UTF8;
            information = "";
            if (imagePlugin.Info.SectorSize < 512)
            {
                return;
            }

            uint sbAddr = NILFS2_SUPER_OFFSET / imagePlugin.Info.SectorSize;

            if (sbAddr == 0)
            {
                sbAddr = 1;
            }

            uint sbSize = (uint)(Marshal.SizeOf <NILFS2_Superblock>() / imagePlugin.Info.SectorSize);

            if (Marshal.SizeOf <NILFS2_Superblock>() % imagePlugin.Info.SectorSize != 0)
            {
                sbSize++;
            }

            byte[] sector = imagePlugin.ReadSectors(partition.Start + sbAddr, sbSize);
            if (sector.Length < Marshal.SizeOf <NILFS2_Superblock>())
            {
                return;
            }

            NILFS2_Superblock nilfsSb = Marshal.ByteArrayToStructureLittleEndian <NILFS2_Superblock>(sector);

            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}", StringHandlers.CToString(nilfsSb.volume_name, Encoding)).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 FileSystemType
            {
                Type                      = "NILFS2 filesystem",
                ClusterSize               = (uint)(1 << (int)(nilfsSb.log_block_size + 10)),
                VolumeName                = StringHandlers.CToString(nilfsSb.volume_name, Encoding),
                VolumeSerial              = nilfsSb.uuid.ToString(),
                CreationDate              = DateHandlers.UnixUnsignedToDateTime(nilfsSb.ctime),
                CreationDateSpecified     = true,
                ModificationDate          = DateHandlers.UnixUnsignedToDateTime(nilfsSb.wtime),
                ModificationDateSpecified = true
            };
            if (nilfsSb.creator_os == 0)
            {
                XmlFsType.SystemIdentifier = "Linux";
            }
            XmlFsType.Clusters = nilfsSb.dev_size / XmlFsType.ClusterSize;
        }
Beispiel #15
0
        public void Open(string path)
        {
            string filename      = Path.GetFileName(path);
            string filenameNoExt = Path.GetFileNameWithoutExtension(path);
            string parentFolder  = Path.GetDirectoryName(path);

            // Prepend data fork name with "R."
            string ProDosAppleDouble =
                Path.Combine(parentFolder ?? throw new InvalidOperationException(), "R." + filename);
            // Prepend data fork name with '%'
            string UNIXAppleDouble = Path.Combine(parentFolder, "%" + filename);
            // Change file extension to ADF
            string DOSAppleDouble = Path.Combine(parentFolder, filenameNoExt + ".ADF");
            // Change file extension to adf
            string DOSAppleDoubleLower = Path.Combine(parentFolder, filenameNoExt + ".adf");
            // Store AppleDouble header file in ".AppleDouble" folder with same name
            string NetatalkAppleDouble =
                Path.Combine(parentFolder, ".AppleDouble", filename ?? throw new InvalidOperationException());
            // Store AppleDouble header file in "resource.frk" folder with same name
            string DAVEAppleDouble = Path.Combine(parentFolder, "resource.frk", filename);
            // Prepend data fork name with "._"
            string OSXAppleDouble = Path.Combine(parentFolder, "._" + filename);
            // Adds ".rsrc" extension
            string UnArAppleDouble = Path.Combine(parentFolder, filename + ".rsrc");

            // Check AppleDouble created by A/UX in ProDOS filesystem
            if (File.Exists(ProDosAppleDouble))
            {
                FileStream prodosStream = new FileStream(ProDosAppleDouble, FileMode.Open, FileAccess.Read);
                if (prodosStream.Length > 26)
                {
                    byte[] prodos_b = new byte[26];
                    prodosStream.Read(prodos_b, 0, 26);
                    header = BigEndianMarshal.ByteArrayToStructureBigEndian <AppleDoubleHeader>(prodos_b);
                    prodosStream.Close();
                    if (header.magic == AppleDoubleMagic &&
                        (header.version == AppleDoubleVersion || header.version == AppleDoubleVersion2))
                    {
                        headerPath = ProDosAppleDouble;
                    }
                }
            }

            // Check AppleDouble created by A/UX in UFS filesystem
            if (File.Exists(UNIXAppleDouble))
            {
                FileStream unixStream = new FileStream(UNIXAppleDouble, FileMode.Open, FileAccess.Read);
                if (unixStream.Length > 26)
                {
                    byte[] unix_b = new byte[26];
                    unixStream.Read(unix_b, 0, 26);
                    header = BigEndianMarshal.ByteArrayToStructureBigEndian <AppleDoubleHeader>(unix_b);
                    unixStream.Close();
                    if (header.magic == AppleDoubleMagic &&
                        (header.version == AppleDoubleVersion || header.version == AppleDoubleVersion2))
                    {
                        headerPath = UNIXAppleDouble;
                    }
                }
            }

            // Check AppleDouble created by A/UX in FAT filesystem
            if (File.Exists(DOSAppleDouble))
            {
                FileStream dosStream = new FileStream(DOSAppleDouble, FileMode.Open, FileAccess.Read);
                if (dosStream.Length > 26)
                {
                    byte[] dos_b = new byte[26];
                    dosStream.Read(dos_b, 0, 26);
                    header = BigEndianMarshal.ByteArrayToStructureBigEndian <AppleDoubleHeader>(dos_b);
                    dosStream.Close();
                    if (header.magic == AppleDoubleMagic &&
                        (header.version == AppleDoubleVersion || header.version == AppleDoubleVersion2))
                    {
                        headerPath = DOSAppleDouble;
                    }
                }
            }

            // Check AppleDouble created by A/UX in case preserving FAT filesystem
            if (File.Exists(DOSAppleDoubleLower))
            {
                FileStream doslStream = new FileStream(DOSAppleDoubleLower, FileMode.Open, FileAccess.Read);
                if (doslStream.Length > 26)
                {
                    byte[] dosl_b = new byte[26];
                    doslStream.Read(dosl_b, 0, 26);
                    header = BigEndianMarshal.ByteArrayToStructureBigEndian <AppleDoubleHeader>(dosl_b);
                    doslStream.Close();
                    if (header.magic == AppleDoubleMagic &&
                        (header.version == AppleDoubleVersion || header.version == AppleDoubleVersion2))
                    {
                        headerPath = DOSAppleDoubleLower;
                    }
                }
            }

            // Check AppleDouble created by Netatalk
            if (File.Exists(NetatalkAppleDouble))
            {
                FileStream netatalkStream = new FileStream(NetatalkAppleDouble, FileMode.Open, FileAccess.Read);
                if (netatalkStream.Length > 26)
                {
                    byte[] netatalk_b = new byte[26];
                    netatalkStream.Read(netatalk_b, 0, 26);
                    header = BigEndianMarshal.ByteArrayToStructureBigEndian <AppleDoubleHeader>(netatalk_b);
                    netatalkStream.Close();
                    if (header.magic == AppleDoubleMagic &&
                        (header.version == AppleDoubleVersion || header.version == AppleDoubleVersion2))
                    {
                        headerPath = NetatalkAppleDouble;
                    }
                }
            }

            // Check AppleDouble created by DAVE
            if (File.Exists(DAVEAppleDouble))
            {
                FileStream daveStream = new FileStream(DAVEAppleDouble, FileMode.Open, FileAccess.Read);
                if (daveStream.Length > 26)
                {
                    byte[] dave_b = new byte[26];
                    daveStream.Read(dave_b, 0, 26);
                    header = BigEndianMarshal.ByteArrayToStructureBigEndian <AppleDoubleHeader>(dave_b);
                    daveStream.Close();
                    if (header.magic == AppleDoubleMagic &&
                        (header.version == AppleDoubleVersion || header.version == AppleDoubleVersion2))
                    {
                        headerPath = DAVEAppleDouble;
                    }
                }
            }

            // Check AppleDouble created by Mac OS X
            if (File.Exists(OSXAppleDouble))
            {
                FileStream osxStream = new FileStream(OSXAppleDouble, FileMode.Open, FileAccess.Read);
                if (osxStream.Length > 26)
                {
                    byte[] osx_b = new byte[26];
                    osxStream.Read(osx_b, 0, 26);
                    header = BigEndianMarshal.ByteArrayToStructureBigEndian <AppleDoubleHeader>(osx_b);
                    osxStream.Close();
                    if (header.magic == AppleDoubleMagic &&
                        (header.version == AppleDoubleVersion || header.version == AppleDoubleVersion2))
                    {
                        headerPath = OSXAppleDouble;
                    }
                }
            }

            // Check AppleDouble created by UnAr (from The Unarchiver)
            if (File.Exists(UnArAppleDouble))
            {
                FileStream unarStream = new FileStream(UnArAppleDouble, FileMode.Open, FileAccess.Read);
                if (unarStream.Length > 26)
                {
                    byte[] unar_b = new byte[26];
                    unarStream.Read(unar_b, 0, 26);
                    header = BigEndianMarshal.ByteArrayToStructureBigEndian <AppleDoubleHeader>(unar_b);
                    unarStream.Close();
                    if (header.magic == AppleDoubleMagic &&
                        (header.version == AppleDoubleVersion || header.version == AppleDoubleVersion2))
                    {
                        headerPath = UnArAppleDouble;
                    }
                }
            }

            FileStream fs = new FileStream(headerPath, FileMode.Open, FileAccess.Read);

            fs.Seek(0, SeekOrigin.Begin);

            byte[] hdr_b = new byte[26];
            fs.Read(hdr_b, 0, 26);
            header = BigEndianMarshal.ByteArrayToStructureBigEndian <AppleDoubleHeader>(hdr_b);

            AppleDoubleEntry[] entries = new AppleDoubleEntry[header.entries];
            for (int i = 0; i < header.entries; i++)
            {
                byte[] entry = new byte[12];
                fs.Read(entry, 0, 12);
                entries[i] = BigEndianMarshal.ByteArrayToStructureBigEndian <AppleDoubleEntry>(entry);
            }

            creationTime  = DateTime.UtcNow;
            lastWriteTime = creationTime;
            foreach (AppleDoubleEntry entry in entries)
            {
                switch ((AppleDoubleEntryID)entry.id)
                {
                case AppleDoubleEntryID.DataFork:
                    // AppleDouble have datafork in separated file
                    break;

                case AppleDoubleEntryID.FileDates:
                    fs.Seek(entry.offset, SeekOrigin.Begin);
                    byte[] dates_b = new byte[16];
                    fs.Read(dates_b, 0, 16);
                    AppleDoubleFileDates dates =
                        BigEndianMarshal.ByteArrayToStructureBigEndian <AppleDoubleFileDates>(dates_b);
                    creationTime  = DateHandlers.UnixUnsignedToDateTime(dates.creationDate);
                    lastWriteTime = DateHandlers.UnixUnsignedToDateTime(dates.modificationDate);
                    break;

                case AppleDoubleEntryID.FileInfo:
                    fs.Seek(entry.offset, SeekOrigin.Begin);
                    byte[] finfo = new byte[entry.length];
                    fs.Read(finfo, 0, finfo.Length);
                    if (MacintoshHome.SequenceEqual(header.homeFilesystem))
                    {
                        AppleDoubleMacFileInfo macinfo =
                            BigEndianMarshal.ByteArrayToStructureBigEndian <AppleDoubleMacFileInfo>(finfo);
                        creationTime  = DateHandlers.MacToDateTime(macinfo.creationDate);
                        lastWriteTime = DateHandlers.MacToDateTime(macinfo.modificationDate);
                    }
                    else if (ProDOSHome.SequenceEqual(header.homeFilesystem))
                    {
                        AppleDoubleProDOSFileInfo prodosinfo =
                            BigEndianMarshal.ByteArrayToStructureBigEndian <AppleDoubleProDOSFileInfo>(finfo);
                        creationTime  = DateHandlers.MacToDateTime(prodosinfo.creationDate);
                        lastWriteTime = DateHandlers.MacToDateTime(prodosinfo.modificationDate);
                    }
                    else if (UNIXHome.SequenceEqual(header.homeFilesystem))
                    {
                        AppleDoubleUNIXFileInfo unixinfo =
                            BigEndianMarshal.ByteArrayToStructureBigEndian <AppleDoubleUNIXFileInfo>(finfo);
                        creationTime  = DateHandlers.UnixUnsignedToDateTime(unixinfo.creationDate);
                        lastWriteTime = DateHandlers.UnixUnsignedToDateTime(unixinfo.modificationDate);
                    }
                    else if (DOSHome.SequenceEqual(header.homeFilesystem))
                    {
                        AppleDoubleDOSFileInfo dosinfo =
                            BigEndianMarshal.ByteArrayToStructureBigEndian <AppleDoubleDOSFileInfo>(finfo);
                        lastWriteTime =
                            DateHandlers.DosToDateTime(dosinfo.modificationDate, dosinfo.modificationTime);
                    }

                    break;

                case AppleDoubleEntryID.ResourceFork:
                    rsrcFork = entry;
                    break;
                }
            }

            dataFork = new AppleDoubleEntry {
                id = (uint)AppleDoubleEntryID.DataFork
            };
            if (File.Exists(path))
            {
                FileStream dataFs = new FileStream(path, FileMode.Open, FileAccess.Read);
                dataFork.length = (uint)dataFs.Length;
                dataFs.Close();
            }

            fs.Close();
            opened   = true;
            basePath = path;
        }
Beispiel #16
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            Encoding    = encoding ?? Encoding.GetEncoding("iso-8859-15");
            information = "";
            StringBuilder sb          = new StringBuilder();
            uint          sectors     = QNX6_SUPER_BLOCK_SIZE / imagePlugin.Info.SectorSize;
            uint          bootSectors = QNX6_BOOT_BLOCKS_SIZE / imagePlugin.Info.SectorSize;

            byte[] audiSector = imagePlugin.ReadSectors(partition.Start, sectors);
            byte[] sector     = imagePlugin.ReadSectors(partition.Start + bootSectors, sectors);
            if (sector.Length < QNX6_SUPER_BLOCK_SIZE)
            {
                return;
            }

            QNX6_AudiSuperBlock audiSb = new QNX6_AudiSuperBlock();
            IntPtr audiPtr             = Marshal.AllocHGlobal(Marshal.SizeOf(audiSb));

            Marshal.Copy(audiSector, 0, audiPtr, Marshal.SizeOf(audiSb));
            audiSb = (QNX6_AudiSuperBlock)Marshal.PtrToStructure(audiPtr, typeof(QNX6_AudiSuperBlock));
            Marshal.FreeHGlobal(audiPtr);

            QNX6_SuperBlock qnxSb = new QNX6_SuperBlock();
            IntPtr          sbPtr = Marshal.AllocHGlobal(Marshal.SizeOf(qnxSb));

            Marshal.Copy(sector, 0, sbPtr, Marshal.SizeOf(qnxSb));
            qnxSb = (QNX6_SuperBlock)Marshal.PtrToStructure(sbPtr, typeof(QNX6_SuperBlock));
            Marshal.FreeHGlobal(sbPtr);

            bool audi = audiSb.magic == QNX6_MAGIC;

            if (audi)
            {
                sb.AppendLine("QNX6 (Audi) filesystem");
                sb.AppendFormat("Checksum: 0x{0:X8}", audiSb.checksum).AppendLine();
                sb.AppendFormat("Serial: 0x{0:X16}", audiSb.checksum).AppendLine();
                sb.AppendFormat("{0} bytes per block", audiSb.blockSize).AppendLine();
                sb.AppendFormat("{0} inodes free of {1}", audiSb.freeInodes, audiSb.numInodes).AppendLine();
                sb.AppendFormat("{0} blocks ({1} bytes) free of {2} ({3} bytes)", audiSb.freeBlocks,
                                audiSb.freeBlocks * audiSb.blockSize, audiSb.numBlocks,
                                audiSb.numBlocks * audiSb.blockSize).AppendLine();

                XmlFsType = new FileSystemType
                {
                    Type                  = "QNX6 (Audi) filesystem",
                    Clusters              = audiSb.numBlocks,
                    ClusterSize           = (int)audiSb.blockSize,
                    Bootable              = true,
                    Files                 = audiSb.numInodes - audiSb.freeInodes,
                    FilesSpecified        = true,
                    FreeClusters          = audiSb.freeBlocks,
                    FreeClustersSpecified = true,
                    VolumeSerial          = $"{audiSb.serial:X16}"
                };
                //xmlFSType.VolumeName = CurrentEncoding.GetString(audiSb.id);

                information = sb.ToString();
                return;
            }

            sb.AppendLine("QNX6 filesystem");
            sb.AppendFormat("Checksum: 0x{0:X8}", qnxSb.checksum).AppendLine();
            sb.AppendFormat("Serial: 0x{0:X16}", qnxSb.checksum).AppendLine();
            sb.AppendFormat("Created on {0}", DateHandlers.UnixUnsignedToDateTime(qnxSb.ctime)).AppendLine();
            sb.AppendFormat("Last mounted on {0}", DateHandlers.UnixUnsignedToDateTime(qnxSb.atime)).AppendLine();
            sb.AppendFormat("Flags: 0x{0:X8}", qnxSb.flags).AppendLine();
            sb.AppendFormat("Version1: 0x{0:X4}", qnxSb.version1).AppendLine();
            sb.AppendFormat("Version2: 0x{0:X4}", qnxSb.version2).AppendLine();
            //sb.AppendFormat("Volume ID: \"{0}\"", CurrentEncoding.GetString(qnxSb.volumeid)).AppendLine();
            sb.AppendFormat("{0} bytes per block", qnxSb.blockSize).AppendLine();
            sb.AppendFormat("{0} inodes free of {1}", qnxSb.freeInodes, qnxSb.numInodes).AppendLine();
            sb.AppendFormat("{0} blocks ({1} bytes) free of {2} ({3} bytes)", qnxSb.freeBlocks,
                            qnxSb.freeBlocks * qnxSb.blockSize, qnxSb.numBlocks, qnxSb.numBlocks * qnxSb.blockSize)
            .AppendLine();

            XmlFsType = new FileSystemType
            {
                Type                      = "QNX6 filesystem",
                Clusters                  = qnxSb.numBlocks,
                ClusterSize               = (int)qnxSb.blockSize,
                Bootable                  = true,
                Files                     = qnxSb.numInodes - qnxSb.freeInodes,
                FilesSpecified            = true,
                FreeClusters              = qnxSb.freeBlocks,
                FreeClustersSpecified     = true,
                VolumeSerial              = $"{qnxSb.serial:X16}",
                CreationDate              = DateHandlers.UnixUnsignedToDateTime(qnxSb.ctime),
                CreationDateSpecified     = true,
                ModificationDate          = DateHandlers.UnixUnsignedToDateTime(qnxSb.atime),
                ModificationDateSpecified = true
            };
            //xmlFSType.VolumeName = CurrentEncoding.GetString(qnxSb.volumeid);

            information = sb.ToString();
        }
Beispiel #17
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            Encoding    = encoding ?? Encoding.GetEncoding("iso-8859-15");
            information = "";
            StringBuilder sbInformation = new StringBuilder();

            uint magic = 0;
            uint sb_size_in_sectors;

            byte[] ufs_sb_sectors;
            ulong  sb_offset     = partition.Start;
            bool   fs_type_42bsd = false;
            bool   fs_type_43bsd = false;
            bool   fs_type_44bsd = false;
            bool   fs_type_ufs   = false;
            bool   fs_type_ufs2  = false;
            bool   fs_type_sun   = false;
            bool   fs_type_sun86 = false;

            if (imagePlugin.Info.SectorSize == 2336 || imagePlugin.Info.SectorSize == 2352 ||
                imagePlugin.Info.SectorSize == 2448)
            {
                sb_size_in_sectors = block_size / 2048;
            }
            else
            {
                sb_size_in_sectors = block_size / imagePlugin.Info.SectorSize;
            }

            ulong[] locations =
            {
                sb_start_floppy,                    sb_start_boot,                       sb_start_long_boot, sb_start_piggy, sb_start_att_dsdd,
                8192 / imagePlugin.Info.SectorSize, 65536 / imagePlugin.Info.SectorSize,
                262144 / imagePlugin.Info.SectorSize
            };

            foreach (ulong loc in locations.Where(loc => partition.End > partition.Start + loc + sb_size_in_sectors))
            {
                ufs_sb_sectors = imagePlugin.ReadSectors(partition.Start + loc, sb_size_in_sectors);
                magic          = BitConverter.ToUInt32(ufs_sb_sectors, 0x055C);

                if (magic == UFS_MAGIC || magic == UFS_CIGAM || magic == UFS_MAGIC_BW || magic == UFS_CIGAM_BW ||
                    magic == UFS2_MAGIC || magic == UFS2_CIGAM || magic == UFS_BAD_MAGIC || magic == UFS_BAD_CIGAM)
                {
                    sb_offset = partition.Start + loc;
                    break;
                }

                magic = 0;
            }

            if (magic == 0)
            {
                information = "Not a UFS filesystem, I shouldn't have arrived here!";
                return;
            }

            XmlFsType = new FileSystemType();

            switch (magic)
            {
            case UFS_MAGIC:
                sbInformation.AppendLine("UFS filesystem");
                XmlFsType.Type = "UFS";
                break;

            case UFS_CIGAM:
                sbInformation.AppendLine("Big-endian UFS filesystem");
                XmlFsType.Type = "UFS";
                break;

            case UFS_MAGIC_BW:
                sbInformation.AppendLine("BorderWare UFS filesystem");
                XmlFsType.Type = "UFS";
                break;

            case UFS_CIGAM_BW:
                sbInformation.AppendLine("Big-endian BorderWare UFS filesystem");
                XmlFsType.Type = "UFS";
                break;

            case UFS2_MAGIC:
                sbInformation.AppendLine("UFS2 filesystem");
                XmlFsType.Type = "UFS2";
                break;

            case UFS2_CIGAM:
                sbInformation.AppendLine("Big-endian UFS2 filesystem");
                XmlFsType.Type = "UFS2";
                break;

            case UFS_BAD_MAGIC:
                sbInformation.AppendLine("Incompletely initialized UFS filesystem");
                sbInformation.AppendLine("BEWARE!!! Following information may be completely wrong!");
                XmlFsType.Type = "UFS";
                break;

            case UFS_BAD_CIGAM:
                sbInformation.AppendLine("Incompletely initialized big-endian UFS filesystem");
                sbInformation.AppendLine("BEWARE!!! Following information may be completely wrong!");
                XmlFsType.Type = "UFS";
                break;
            }

            // Fun with seeking follows on superblock reading!
            ufs_sb_sectors = imagePlugin.ReadSectors(sb_offset, sb_size_in_sectors);

            IntPtr sbPtr = Marshal.AllocHGlobal(ufs_sb_sectors.Length);

            Marshal.Copy(ufs_sb_sectors, 0, sbPtr, ufs_sb_sectors.Length);
            UFSSuperBlock ufs_sb = (UFSSuperBlock)Marshal.PtrToStructure(sbPtr, typeof(UFSSuperBlock));

            Marshal.FreeHGlobal(sbPtr);

            UFSSuperBlock bs_sfu = BigEndianMarshal.ByteArrayToStructureBigEndian <UFSSuperBlock>(ufs_sb_sectors);

            if (bs_sfu.fs_magic == UFS_MAGIC && ufs_sb.fs_magic == UFS_CIGAM ||
                bs_sfu.fs_magic == UFS_MAGIC_BW && ufs_sb.fs_magic == UFS_CIGAM_BW ||
                bs_sfu.fs_magic == UFS2_MAGIC && ufs_sb.fs_magic == UFS2_CIGAM ||
                bs_sfu.fs_magic == UFS_BAD_MAGIC && ufs_sb.fs_magic == UFS_BAD_CIGAM)
            {
                ufs_sb = bs_sfu;
                ufs_sb.fs_old_cstotal.cs_nbfree  = Swapping.Swap(ufs_sb.fs_old_cstotal.cs_nbfree);
                ufs_sb.fs_old_cstotal.cs_ndir    = Swapping.Swap(ufs_sb.fs_old_cstotal.cs_ndir);
                ufs_sb.fs_old_cstotal.cs_nffree  = Swapping.Swap(ufs_sb.fs_old_cstotal.cs_nffree);
                ufs_sb.fs_old_cstotal.cs_nifree  = Swapping.Swap(ufs_sb.fs_old_cstotal.cs_nifree);
                ufs_sb.fs_cstotal.cs_numclusters = Swapping.Swap(ufs_sb.fs_cstotal.cs_numclusters);
                ufs_sb.fs_cstotal.cs_nbfree      = Swapping.Swap(ufs_sb.fs_cstotal.cs_nbfree);
                ufs_sb.fs_cstotal.cs_ndir        = Swapping.Swap(ufs_sb.fs_cstotal.cs_ndir);
                ufs_sb.fs_cstotal.cs_nffree      = Swapping.Swap(ufs_sb.fs_cstotal.cs_nffree);
                ufs_sb.fs_cstotal.cs_nifree      = Swapping.Swap(ufs_sb.fs_cstotal.cs_nifree);
                ufs_sb.fs_cstotal.cs_spare[0]    = Swapping.Swap(ufs_sb.fs_cstotal.cs_spare[0]);
                ufs_sb.fs_cstotal.cs_spare[1]    = Swapping.Swap(ufs_sb.fs_cstotal.cs_spare[1]);
                ufs_sb.fs_cstotal.cs_spare[2]    = Swapping.Swap(ufs_sb.fs_cstotal.cs_spare[2]);
            }

            DicConsole.DebugWriteLine("FFS plugin", "ufs_sb offset: 0x{0:X8}", sb_offset);
            DicConsole.DebugWriteLine("FFS plugin", "fs_rlink: 0x{0:X8}", ufs_sb.fs_rlink);
            DicConsole.DebugWriteLine("FFS plugin", "fs_sblkno: 0x{0:X8}", ufs_sb.fs_sblkno);
            DicConsole.DebugWriteLine("FFS plugin", "fs_cblkno: 0x{0:X8}", ufs_sb.fs_cblkno);
            DicConsole.DebugWriteLine("FFS plugin", "fs_iblkno: 0x{0:X8}", ufs_sb.fs_iblkno);
            DicConsole.DebugWriteLine("FFS plugin", "fs_dblkno: 0x{0:X8}", ufs_sb.fs_dblkno);
            DicConsole.DebugWriteLine("FFS plugin", "fs_size: 0x{0:X8}", ufs_sb.fs_size);
            DicConsole.DebugWriteLine("FFS plugin", "fs_dsize: 0x{0:X8}", ufs_sb.fs_dsize);
            DicConsole.DebugWriteLine("FFS plugin", "fs_ncg: 0x{0:X8}", ufs_sb.fs_ncg);
            DicConsole.DebugWriteLine("FFS plugin", "fs_bsize: 0x{0:X8}", ufs_sb.fs_bsize);
            DicConsole.DebugWriteLine("FFS plugin", "fs_fsize: 0x{0:X8}", ufs_sb.fs_fsize);
            DicConsole.DebugWriteLine("FFS plugin", "fs_frag: 0x{0:X8}", ufs_sb.fs_frag);
            DicConsole.DebugWriteLine("FFS plugin", "fs_minfree: 0x{0:X8}", ufs_sb.fs_minfree);
            DicConsole.DebugWriteLine("FFS plugin", "fs_bmask: 0x{0:X8}", ufs_sb.fs_bmask);
            DicConsole.DebugWriteLine("FFS plugin", "fs_fmask: 0x{0:X8}", ufs_sb.fs_fmask);
            DicConsole.DebugWriteLine("FFS plugin", "fs_bshift: 0x{0:X8}", ufs_sb.fs_bshift);
            DicConsole.DebugWriteLine("FFS plugin", "fs_fshift: 0x{0:X8}", ufs_sb.fs_fshift);
            DicConsole.DebugWriteLine("FFS plugin", "fs_maxcontig: 0x{0:X8}", ufs_sb.fs_maxcontig);
            DicConsole.DebugWriteLine("FFS plugin", "fs_maxbpg: 0x{0:X8}", ufs_sb.fs_maxbpg);
            DicConsole.DebugWriteLine("FFS plugin", "fs_fragshift: 0x{0:X8}", ufs_sb.fs_fragshift);
            DicConsole.DebugWriteLine("FFS plugin", "fs_fsbtodb: 0x{0:X8}", ufs_sb.fs_fsbtodb);
            DicConsole.DebugWriteLine("FFS plugin", "fs_sbsize: 0x{0:X8}", ufs_sb.fs_sbsize);
            DicConsole.DebugWriteLine("FFS plugin", "fs_csmask: 0x{0:X8}", ufs_sb.fs_csmask);
            DicConsole.DebugWriteLine("FFS plugin", "fs_csshift: 0x{0:X8}", ufs_sb.fs_csshift);
            DicConsole.DebugWriteLine("FFS plugin", "fs_nindir: 0x{0:X8}", ufs_sb.fs_nindir);
            DicConsole.DebugWriteLine("FFS plugin", "fs_inopb: 0x{0:X8}", ufs_sb.fs_inopb);
            DicConsole.DebugWriteLine("FFS plugin", "fs_optim: 0x{0:X8}", ufs_sb.fs_optim);
            DicConsole.DebugWriteLine("FFS plugin", "fs_id_1: 0x{0:X8}", ufs_sb.fs_id_1);
            DicConsole.DebugWriteLine("FFS plugin", "fs_id_2: 0x{0:X8}", ufs_sb.fs_id_2);
            DicConsole.DebugWriteLine("FFS plugin", "fs_csaddr: 0x{0:X8}", ufs_sb.fs_csaddr);
            DicConsole.DebugWriteLine("FFS plugin", "fs_cssize: 0x{0:X8}", ufs_sb.fs_cssize);
            DicConsole.DebugWriteLine("FFS plugin", "fs_cgsize: 0x{0:X8}", ufs_sb.fs_cgsize);
            DicConsole.DebugWriteLine("FFS plugin", "fs_ipg: 0x{0:X8}", ufs_sb.fs_ipg);
            DicConsole.DebugWriteLine("FFS plugin", "fs_fpg: 0x{0:X8}", ufs_sb.fs_fpg);
            DicConsole.DebugWriteLine("FFS plugin", "fs_fmod: 0x{0:X2}", ufs_sb.fs_fmod);
            DicConsole.DebugWriteLine("FFS plugin", "fs_clean: 0x{0:X2}", ufs_sb.fs_clean);
            DicConsole.DebugWriteLine("FFS plugin", "fs_ronly: 0x{0:X2}", ufs_sb.fs_ronly);
            DicConsole.DebugWriteLine("FFS plugin", "fs_flags: 0x{0:X2}", ufs_sb.fs_flags);
            DicConsole.DebugWriteLine("FFS plugin", "fs_magic: 0x{0:X8}", ufs_sb.fs_magic);

            if (ufs_sb.fs_magic == UFS2_MAGIC)
            {
                fs_type_ufs2 = true;
            }
            else
            {
                const uint
                    SunOSEpoch =
                    0x1A54C580;     // We are supposing there cannot be a Sun's fs created before 1/1/1982 00:00:00

                fs_type_43bsd =
                    true; // There is no way of knowing this is the version, but there is of knowing it is not.

                if (ufs_sb.fs_link > 0)
                {
                    fs_type_42bsd = true; // It was used in 4.2BSD
                    fs_type_43bsd = false;
                }

                if ((ufs_sb.fs_maxfilesize & 0xFFFFFFFF) > SunOSEpoch &&
                    DateHandlers.UnixUnsignedToDateTime(ufs_sb.fs_maxfilesize & 0xFFFFFFFF) < DateTime.Now)
                {
                    fs_type_42bsd = false;
                    fs_type_sun   = true;
                    fs_type_43bsd = false;
                }

                // This is for sure, as it is shared with a sectors/track with non-x86 SunOS, Epoch is absurdly high for that
                if (ufs_sb.fs_old_npsect > SunOSEpoch && DateHandlers.UnixToDateTime(ufs_sb.fs_old_npsect) < DateTime.Now
                    )
                {
                    fs_type_42bsd = false;
                    fs_type_sun86 = true;
                    fs_type_sun   = false;
                    fs_type_43bsd = false;
                }

                if (ufs_sb.fs_cgrotor > 0x00000000 && (uint)ufs_sb.fs_cgrotor < 0xFFFFFFFF)
                {
                    fs_type_42bsd = false;
                    fs_type_sun   = false;
                    fs_type_sun86 = false;
                    fs_type_ufs   = true;
                    fs_type_43bsd = false;
                }

                // 4.3BSD code does not use these fields, they are always set up to 0
                fs_type_43bsd &= ufs_sb.fs_id_2 == 0 && ufs_sb.fs_id_1 == 0;

                // This is the only 4.4BSD inode format
                fs_type_44bsd |= ufs_sb.fs_old_inodefmt == 2;
            }

            if (!fs_type_ufs2)
            {
                sbInformation.AppendLine("There are a lot of variants of UFS using overlapped values on same fields");
                sbInformation
                .AppendLine("I will try to guess which one it is, but unless it's UFS2, I may be surely wrong");
            }

            if (fs_type_42bsd)
            {
                sbInformation.AppendLine("Guessed as 42BSD FFS");
            }
            if (fs_type_43bsd)
            {
                sbInformation.AppendLine("Guessed as 43BSD FFS");
            }
            if (fs_type_44bsd)
            {
                sbInformation.AppendLine("Guessed as 44BSD FFS");
            }
            if (fs_type_sun)
            {
                sbInformation.AppendLine("Guessed as SunOS FFS");
            }
            if (fs_type_sun86)
            {
                sbInformation.AppendLine("Guessed as SunOS/x86 FFS");
            }
            if (fs_type_ufs)
            {
                sbInformation.AppendLine("Guessed as UFS");
            }

            if (fs_type_42bsd)
            {
                sbInformation.AppendFormat("Linked list of filesystems: 0x{0:X8}", ufs_sb.fs_link).AppendLine();
            }
            sbInformation.AppendFormat("Superblock LBA: {0}", ufs_sb.fs_sblkno).AppendLine();
            sbInformation.AppendFormat("Cylinder-block LBA: {0}", ufs_sb.fs_cblkno).AppendLine();
            sbInformation.AppendFormat("inode-block LBA: {0}", ufs_sb.fs_iblkno).AppendLine();
            sbInformation.AppendFormat("First data block LBA: {0}", ufs_sb.fs_dblkno).AppendLine();
            sbInformation.AppendFormat("Cylinder group offset in cylinder: {0}", ufs_sb.fs_old_cgoffset).AppendLine();
            sbInformation.AppendFormat("Volume last written on {0}", DateHandlers.UnixToDateTime(ufs_sb.fs_old_time))
            .AppendLine();
            XmlFsType.ModificationDate          = DateHandlers.UnixToDateTime(ufs_sb.fs_old_time);
            XmlFsType.ModificationDateSpecified = true;
            sbInformation.AppendFormat("{0} blocks in volume ({1} bytes)", ufs_sb.fs_old_size,
                                       (long)ufs_sb.fs_old_size * ufs_sb.fs_fsize).AppendLine();
            XmlFsType.Clusters    = ufs_sb.fs_old_size;
            XmlFsType.ClusterSize = ufs_sb.fs_fsize;
            sbInformation.AppendFormat("{0} data blocks in volume ({1} bytes)", ufs_sb.fs_old_dsize,
                                       (long)ufs_sb.fs_old_dsize * ufs_sb.fs_fsize).AppendLine();
            sbInformation.AppendFormat("{0} cylinder groups in volume", ufs_sb.fs_ncg).AppendLine();
            sbInformation.AppendFormat("{0} bytes in a basic block", ufs_sb.fs_bsize).AppendLine();
            sbInformation.AppendFormat("{0} bytes in a frag block", ufs_sb.fs_fsize).AppendLine();
            sbInformation.AppendFormat("{0} frags in a block", ufs_sb.fs_frag).AppendLine();
            sbInformation.AppendFormat("{0}% of blocks must be free", ufs_sb.fs_minfree).AppendLine();
            sbInformation.AppendFormat("{0}ms for optimal next block", ufs_sb.fs_old_rotdelay).AppendLine();
            sbInformation.AppendFormat("disk rotates {0} times per second ({1}rpm)", ufs_sb.fs_old_rps,
                                       ufs_sb.fs_old_rps * 60).AppendLine();

            /*          sbInformation.AppendFormat("fs_bmask: 0x{0:X8}", ufs_sb.fs_bmask).AppendLine();
             *          sbInformation.AppendFormat("fs_fmask: 0x{0:X8}", ufs_sb.fs_fmask).AppendLine();
             *          sbInformation.AppendFormat("fs_bshift: 0x{0:X8}", ufs_sb.fs_bshift).AppendLine();
             *          sbInformation.AppendFormat("fs_fshift: 0x{0:X8}", ufs_sb.fs_fshift).AppendLine();*/
            sbInformation.AppendFormat("{0} contiguous blocks at maximum", ufs_sb.fs_maxcontig).AppendLine();
            sbInformation.AppendFormat("{0} blocks per cylinder group at maximum", ufs_sb.fs_maxbpg).AppendLine();
            sbInformation.AppendFormat("Superblock is {0} bytes", ufs_sb.fs_sbsize).AppendLine();
            sbInformation.AppendFormat("NINDIR: 0x{0:X8}", ufs_sb.fs_nindir).AppendLine();
            sbInformation.AppendFormat("INOPB: 0x{0:X8}", ufs_sb.fs_inopb).AppendLine();
            sbInformation.AppendFormat("NSPF: 0x{0:X8}", ufs_sb.fs_old_nspf).AppendLine();
            switch (ufs_sb.fs_optim)
            {
            case 0:
                sbInformation.AppendLine("Filesystem will minimize allocation time");
                break;

            case 1:
                sbInformation.AppendLine("Filesystem will minimize volume fragmentation");
                break;

            default:
                sbInformation.AppendFormat("Unknown optimization value: 0x{0:X8}", ufs_sb.fs_optim).AppendLine();
                break;
            }

            if (fs_type_sun)
            {
                sbInformation.AppendFormat("{0} sectors/track", ufs_sb.fs_old_npsect).AppendLine();
            }
            else if (fs_type_sun86)
            {
                sbInformation.AppendFormat("Volume state on {0}", DateHandlers.UnixToDateTime(ufs_sb.fs_old_npsect))
                .AppendLine();
            }
            sbInformation.AppendFormat("Hardware sector interleave: {0}", ufs_sb.fs_old_interleave).AppendLine();
            sbInformation.AppendFormat("Sector 0 skew: {0}/track", ufs_sb.fs_old_trackskew).AppendLine();
            if (!fs_type_43bsd && ufs_sb.fs_id_1 > 0 && ufs_sb.fs_id_2 > 0)
            {
                sbInformation.AppendFormat("Volume ID: 0x{0:X8}{1:X8}", ufs_sb.fs_id_1, ufs_sb.fs_id_2).AppendLine();
            }
            else if (fs_type_43bsd && ufs_sb.fs_id_1 > 0 && ufs_sb.fs_id_2 > 0)
            {
                sbInformation.AppendFormat("{0} µsec for head switch", ufs_sb.fs_id_1).AppendLine();
                sbInformation.AppendFormat("{0} µsec for track-to-track seek", ufs_sb.fs_id_2).AppendLine();
            }
            sbInformation.AppendFormat("Cylinder group summary LBA: {0}", ufs_sb.fs_old_csaddr).AppendLine();
            sbInformation.AppendFormat("{0} bytes in cylinder group summary", ufs_sb.fs_cssize).AppendLine();
            sbInformation.AppendFormat("{0} bytes in cylinder group", ufs_sb.fs_cgsize).AppendLine();
            sbInformation.AppendFormat("{0} tracks/cylinder", ufs_sb.fs_old_ntrak).AppendLine();
            sbInformation.AppendFormat("{0} sectors/track", ufs_sb.fs_old_nsect).AppendLine();
            sbInformation.AppendFormat("{0} sectors/cylinder", ufs_sb.fs_old_spc).AppendLine();
            sbInformation.AppendFormat("{0} cylinder in volume", ufs_sb.fs_old_ncyl).AppendLine();
            sbInformation.AppendFormat("{0} cylinders/group", ufs_sb.fs_old_cpg).AppendLine();
            sbInformation.AppendFormat("{0} inodes per cylinder group", ufs_sb.fs_ipg).AppendLine();
            sbInformation.AppendFormat("{0} blocks per group", ufs_sb.fs_fpg / ufs_sb.fs_frag).AppendLine();
            sbInformation.AppendFormat("{0} directories", ufs_sb.fs_old_cstotal.cs_ndir).AppendLine();
            sbInformation.AppendFormat("{0} free blocks ({1} bytes)", ufs_sb.fs_old_cstotal.cs_nbfree,
                                       (long)ufs_sb.fs_old_cstotal.cs_nbfree * ufs_sb.fs_fsize).AppendLine();
            XmlFsType.FreeClusters          = ufs_sb.fs_old_cstotal.cs_nbfree;
            XmlFsType.FreeClustersSpecified = true;
            sbInformation.AppendFormat("{0} free inodes", ufs_sb.fs_old_cstotal.cs_nifree).AppendLine();
            sbInformation.AppendFormat("{0} free frags", ufs_sb.fs_old_cstotal.cs_nffree).AppendLine();
            if (ufs_sb.fs_fmod == 1)
            {
                sbInformation.AppendLine("Superblock is under modification");
                XmlFsType.Dirty = true;
            }
            if (ufs_sb.fs_clean == 1)
            {
                sbInformation.AppendLine("Volume is clean");
            }
            if (ufs_sb.fs_ronly == 1)
            {
                sbInformation.AppendLine("Volume is read-only");
            }
            sbInformation.AppendFormat("Volume flags: 0x{0:X2}", ufs_sb.fs_flags).AppendLine();
            if (fs_type_ufs)
            {
                sbInformation.AppendFormat("Volume last mounted on \"{0}\"", StringHandlers.CToString(ufs_sb.fs_fsmnt))
                .AppendLine();
            }
            else if (fs_type_ufs2)
            {
                sbInformation.AppendFormat("Volume last mounted on \"{0}\"", StringHandlers.CToString(ufs_sb.fs_fsmnt))
                .AppendLine();
                sbInformation.AppendFormat("Volume name: \"{0}\"", StringHandlers.CToString(ufs_sb.fs_volname))
                .AppendLine();
                XmlFsType.VolumeName = StringHandlers.CToString(ufs_sb.fs_volname);
                sbInformation.AppendFormat("Volume ID: 0x{0:X16}", ufs_sb.fs_swuid).AppendLine();
                //xmlFSType.VolumeSerial = string.Format("{0:X16}", ufs_sb.fs_swuid);
                sbInformation.AppendFormat("Last searched cylinder group: {0}", ufs_sb.fs_cgrotor).AppendLine();
                sbInformation.AppendFormat("{0} contiguously allocated directories", ufs_sb.fs_contigdirs).AppendLine();
                sbInformation.AppendFormat("Standard superblock LBA: {0}", ufs_sb.fs_sblkno).AppendLine();
                sbInformation.AppendFormat("{0} directories", ufs_sb.fs_cstotal.cs_ndir).AppendLine();
                sbInformation.AppendFormat("{0} free blocks ({1} bytes)", ufs_sb.fs_cstotal.cs_nbfree,
                                           ufs_sb.fs_cstotal.cs_nbfree * ufs_sb.fs_fsize).AppendLine();
                XmlFsType.FreeClusters          = ufs_sb.fs_cstotal.cs_nbfree;
                XmlFsType.FreeClustersSpecified = true;
                sbInformation.AppendFormat("{0} free inodes", ufs_sb.fs_cstotal.cs_nifree).AppendLine();
                sbInformation.AppendFormat("{0} free frags", ufs_sb.fs_cstotal.cs_nffree).AppendLine();
                sbInformation.AppendFormat("{0} free clusters", ufs_sb.fs_cstotal.cs_numclusters).AppendLine();
                sbInformation.AppendFormat("Volume last written on {0}", DateHandlers.UnixToDateTime(ufs_sb.fs_time))
                .AppendLine();
                XmlFsType.ModificationDate          = DateHandlers.UnixToDateTime(ufs_sb.fs_time);
                XmlFsType.ModificationDateSpecified = true;
                sbInformation.AppendFormat("{0} blocks ({1} bytes)", ufs_sb.fs_size, ufs_sb.fs_size * ufs_sb.fs_fsize)
                .AppendLine();
                XmlFsType.Clusters = ufs_sb.fs_size;
                sbInformation
                .AppendFormat("{0} data blocks ({1} bytes)", ufs_sb.fs_dsize, ufs_sb.fs_dsize * ufs_sb.fs_fsize)
                .AppendLine();
                sbInformation.AppendFormat("Cylinder group summary area LBA: {0}", ufs_sb.fs_csaddr).AppendLine();
                sbInformation.AppendFormat("{0} blocks pending of being freed", ufs_sb.fs_pendingblocks).AppendLine();
                sbInformation.AppendFormat("{0} inodes pending of being freed", ufs_sb.fs_pendinginodes).AppendLine();
            }
            if (fs_type_sun)
            {
                sbInformation.AppendFormat("Volume state on {0}", DateHandlers.UnixToDateTime(ufs_sb.fs_old_npsect))
                .AppendLine();
            }
            else if (fs_type_sun86)
            {
                sbInformation.AppendFormat("{0} sectors/track", ufs_sb.fs_state).AppendLine();
            }
            else if (fs_type_44bsd)
            {
                sbInformation.AppendFormat("{0} blocks on cluster summary array", ufs_sb.fs_contigsumsize).AppendLine();
                sbInformation.AppendFormat("Maximum length of a symbolic link: {0}", ufs_sb.fs_maxsymlinklen)
                .AppendLine();
                sbInformation.AppendFormat("A file can be {0} bytes at max", ufs_sb.fs_maxfilesize).AppendLine();
                sbInformation.AppendFormat("Volume state on {0}", DateHandlers.UnixToDateTime(ufs_sb.fs_state))
                .AppendLine();
            }
            if (ufs_sb.fs_old_nrpos > 0)
            {
                sbInformation.AppendFormat("{0} rotational positions", ufs_sb.fs_old_nrpos).AppendLine();
            }
            if (ufs_sb.fs_old_rotbloff > 0)
            {
                sbInformation.AppendFormat("{0} blocks per rotation", ufs_sb.fs_old_rotbloff).AppendLine();
            }

            information = sbInformation.ToString();
        }
Beispiel #18
0
        public void Open(string path)
        {
            string filename      = Path.GetFileName(path);
            string filenameNoExt = Path.GetFileNameWithoutExtension(path);
            string parentFolder  = Path.GetDirectoryName(path);

            parentFolder ??= "";

            if (filename is null ||
                filenameNoExt is null)
            {
                throw new ArgumentNullException(nameof(path));
            }

            // Prepend data fork name with "R."
            string proDosAppleDouble = Path.Combine(parentFolder, "R." + filename);

            // Prepend data fork name with '%'
            string unixAppleDouble = Path.Combine(parentFolder, "%" + filename);

            // Change file extension to ADF
            string dosAppleDouble = Path.Combine(parentFolder, filenameNoExt + ".ADF");

            // Change file extension to adf
            string dosAppleDoubleLower = Path.Combine(parentFolder, filenameNoExt + ".adf");

            // Store AppleDouble header file in ".AppleDouble" folder with same name
            string netatalkAppleDouble = Path.Combine(parentFolder, ".AppleDouble", filename);

            // Store AppleDouble header file in "resource.frk" folder with same name
            string daveAppleDouble = Path.Combine(parentFolder, "resource.frk", filename);

            // Prepend data fork name with "._"
            string osxAppleDouble = Path.Combine(parentFolder, "._" + filename);

            // Adds ".rsrc" extension
            string unArAppleDouble = Path.Combine(parentFolder, filename + ".rsrc");

            // Check AppleDouble created by A/UX in ProDOS filesystem
            if (File.Exists(proDosAppleDouble))
            {
                var prodosStream = new FileStream(proDosAppleDouble, FileMode.Open, FileAccess.Read);

                if (prodosStream.Length > 26)
                {
                    byte[] prodosB = new byte[26];
                    prodosStream.Read(prodosB, 0, 26);
                    _header = Marshal.ByteArrayToStructureBigEndian <AppleDoubleHeader>(prodosB);
                    prodosStream.Close();

                    if (_header.magic == MAGIC &&
                        (_header.version == VERSION || _header.version == VERSION2))
                    {
                        _headerPath = proDosAppleDouble;
                    }
                }
            }

            // Check AppleDouble created by A/UX in UFS filesystem
            if (File.Exists(unixAppleDouble))
            {
                var unixStream = new FileStream(unixAppleDouble, FileMode.Open, FileAccess.Read);

                if (unixStream.Length > 26)
                {
                    byte[] unixB = new byte[26];
                    unixStream.Read(unixB, 0, 26);
                    _header = Marshal.ByteArrayToStructureBigEndian <AppleDoubleHeader>(unixB);
                    unixStream.Close();

                    if (_header.magic == MAGIC &&
                        (_header.version == VERSION || _header.version == VERSION2))
                    {
                        _headerPath = unixAppleDouble;
                    }
                }
            }

            // Check AppleDouble created by A/UX in FAT filesystem
            if (File.Exists(dosAppleDouble))
            {
                var dosStream = new FileStream(dosAppleDouble, FileMode.Open, FileAccess.Read);

                if (dosStream.Length > 26)
                {
                    byte[] dosB = new byte[26];
                    dosStream.Read(dosB, 0, 26);
                    _header = Marshal.ByteArrayToStructureBigEndian <AppleDoubleHeader>(dosB);
                    dosStream.Close();

                    if (_header.magic == MAGIC &&
                        (_header.version == VERSION || _header.version == VERSION2))
                    {
                        _headerPath = dosAppleDouble;
                    }
                }
            }

            // Check AppleDouble created by A/UX in case preserving FAT filesystem
            if (File.Exists(dosAppleDoubleLower))
            {
                var doslStream = new FileStream(dosAppleDoubleLower, FileMode.Open, FileAccess.Read);

                if (doslStream.Length > 26)
                {
                    byte[] doslB = new byte[26];
                    doslStream.Read(doslB, 0, 26);
                    _header = Marshal.ByteArrayToStructureBigEndian <AppleDoubleHeader>(doslB);
                    doslStream.Close();

                    if (_header.magic == MAGIC &&
                        (_header.version == VERSION || _header.version == VERSION2))
                    {
                        _headerPath = dosAppleDoubleLower;
                    }
                }
            }

            // Check AppleDouble created by Netatalk
            if (File.Exists(netatalkAppleDouble))
            {
                var netatalkStream = new FileStream(netatalkAppleDouble, FileMode.Open, FileAccess.Read);

                if (netatalkStream.Length > 26)
                {
                    byte[] netatalkB = new byte[26];
                    netatalkStream.Read(netatalkB, 0, 26);
                    _header = Marshal.ByteArrayToStructureBigEndian <AppleDoubleHeader>(netatalkB);
                    netatalkStream.Close();

                    if (_header.magic == MAGIC &&
                        (_header.version == VERSION || _header.version == VERSION2))
                    {
                        _headerPath = netatalkAppleDouble;
                    }
                }
            }

            // Check AppleDouble created by DAVE
            if (File.Exists(daveAppleDouble))
            {
                var daveStream = new FileStream(daveAppleDouble, FileMode.Open, FileAccess.Read);

                if (daveStream.Length > 26)
                {
                    byte[] daveB = new byte[26];
                    daveStream.Read(daveB, 0, 26);
                    _header = Marshal.ByteArrayToStructureBigEndian <AppleDoubleHeader>(daveB);
                    daveStream.Close();

                    if (_header.magic == MAGIC &&
                        (_header.version == VERSION || _header.version == VERSION2))
                    {
                        _headerPath = daveAppleDouble;
                    }
                }
            }

            // Check AppleDouble created by Mac OS X
            if (File.Exists(osxAppleDouble))
            {
                var osxStream = new FileStream(osxAppleDouble, FileMode.Open, FileAccess.Read);

                if (osxStream.Length > 26)
                {
                    byte[] osxB = new byte[26];
                    osxStream.Read(osxB, 0, 26);
                    _header = Marshal.ByteArrayToStructureBigEndian <AppleDoubleHeader>(osxB);
                    osxStream.Close();

                    if (_header.magic == MAGIC &&
                        (_header.version == VERSION || _header.version == VERSION2))
                    {
                        _headerPath = osxAppleDouble;
                    }
                }
            }

            // Check AppleDouble created by UnAr (from The Unarchiver)
            if (File.Exists(unArAppleDouble))
            {
                var unarStream = new FileStream(unArAppleDouble, FileMode.Open, FileAccess.Read);

                if (unarStream.Length > 26)
                {
                    byte[] unarB = new byte[26];
                    unarStream.Read(unarB, 0, 26);
                    _header = Marshal.ByteArrayToStructureBigEndian <AppleDoubleHeader>(unarB);
                    unarStream.Close();

                    if (_header.magic == MAGIC &&
                        (_header.version == VERSION || _header.version == VERSION2))
                    {
                        _headerPath = unArAppleDouble;
                    }
                }
            }

            var fs = new FileStream(_headerPath, FileMode.Open, FileAccess.Read);

            fs.Seek(0, SeekOrigin.Begin);

            byte[] hdrB = new byte[26];
            fs.Read(hdrB, 0, 26);
            _header = Marshal.ByteArrayToStructureBigEndian <AppleDoubleHeader>(hdrB);

            AppleDoubleEntry[] entries = new AppleDoubleEntry[_header.entries];

            for (int i = 0; i < _header.entries; i++)
            {
                byte[] entry = new byte[12];
                fs.Read(entry, 0, 12);
                entries[i] = Marshal.ByteArrayToStructureBigEndian <AppleDoubleEntry>(entry);
            }

            _creationTime  = DateTime.UtcNow;
            _lastWriteTime = _creationTime;

            foreach (AppleDoubleEntry entry in entries)
            {
                switch ((AppleDoubleEntryID)entry.id)
                {
                case AppleDoubleEntryID.DataFork:
                    // AppleDouble have datafork in separated file
                    break;

                case AppleDoubleEntryID.FileDates:
                    fs.Seek(entry.offset, SeekOrigin.Begin);
                    byte[] datesB = new byte[16];
                    fs.Read(datesB, 0, 16);

                    AppleDoubleFileDates dates =
                        Marshal.ByteArrayToStructureBigEndian <AppleDoubleFileDates>(datesB);

                    _creationTime  = DateHandlers.UnixUnsignedToDateTime(dates.creationDate);
                    _lastWriteTime = DateHandlers.UnixUnsignedToDateTime(dates.modificationDate);

                    break;

                case AppleDoubleEntryID.FileInfo:
                    fs.Seek(entry.offset, SeekOrigin.Begin);
                    byte[] finfo = new byte[entry.length];
                    fs.Read(finfo, 0, finfo.Length);

                    if (_macintoshHome.SequenceEqual(_header.homeFilesystem))
                    {
                        AppleDoubleMacFileInfo macinfo =
                            Marshal.ByteArrayToStructureBigEndian <AppleDoubleMacFileInfo>(finfo);

                        _creationTime  = DateHandlers.MacToDateTime(macinfo.creationDate);
                        _lastWriteTime = DateHandlers.MacToDateTime(macinfo.modificationDate);
                    }
                    else if (_proDosHome.SequenceEqual(_header.homeFilesystem))
                    {
                        AppleDoubleProDOSFileInfo prodosinfo =
                            Marshal.ByteArrayToStructureBigEndian <AppleDoubleProDOSFileInfo>(finfo);

                        _creationTime  = DateHandlers.MacToDateTime(prodosinfo.creationDate);
                        _lastWriteTime = DateHandlers.MacToDateTime(prodosinfo.modificationDate);
                    }
                    else if (_unixHome.SequenceEqual(_header.homeFilesystem))
                    {
                        AppleDoubleUnixFileInfo unixinfo =
                            Marshal.ByteArrayToStructureBigEndian <AppleDoubleUnixFileInfo>(finfo);

                        _creationTime  = DateHandlers.UnixUnsignedToDateTime(unixinfo.creationDate);
                        _lastWriteTime = DateHandlers.UnixUnsignedToDateTime(unixinfo.modificationDate);
                    }
                    else if (_dosHome.SequenceEqual(_header.homeFilesystem))
                    {
                        AppleDoubleDOSFileInfo dosinfo =
                            Marshal.ByteArrayToStructureBigEndian <AppleDoubleDOSFileInfo>(finfo);

                        _lastWriteTime =
                            DateHandlers.DosToDateTime(dosinfo.modificationDate, dosinfo.modificationTime);
                    }

                    break;

                case AppleDoubleEntryID.ResourceFork:
                    _rsrcFork = entry;

                    break;
                }
            }

            _dataFork = new AppleDoubleEntry
            {
                id = (uint)AppleDoubleEntryID.DataFork
            };

            if (File.Exists(path))
            {
                var dataFs = new FileStream(path, FileMode.Open, FileAccess.Read);
                _dataFork.length = (uint)dataFs.Length;
                dataFs.Close();
            }

            fs.Close();
            _opened   = true;
            _basePath = path;
        }
Beispiel #19
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            Encoding    = encoding ?? Encoding.GetEncoding("iso-8859-15");
            information = "";

            StringBuilder sb = new StringBuilder();

            BigEndianBitConverter.IsLittleEndian =
                true; // Start in little endian until we know what are we handling here
            int  start    = 0;
            bool xenix    = false;
            bool sysv     = false;
            bool sys7th   = false;
            bool coherent = false;
            bool xenix3   = false;

            byte[] sb_sector;
            byte   sb_size_in_sectors;
            int    offset = 0;

            if (imagePlugin.Info.SectorSize <= 0x400
                ) // Check if underlying device sector size is smaller than SuperBlock size
            {
                sb_size_in_sectors = (byte)(0x400 / imagePlugin.Info.SectorSize);
            }
            else
            {
                sb_size_in_sectors = 1;  // If not a single sector can store it
            }
            // Sectors in a cylinder
            int spc = (int)(imagePlugin.Info.Heads * imagePlugin.Info.SectorsPerTrack);

            // Superblock can start on 0x000, 0x200, 0x600 and 0x800, not aligned, so we assume 16 (128 bytes/sector) sectors as a safe value
            int[] locations =
            {
                0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
                // Superblock can also skip one cylinder (for boot)
                spc
            };

            foreach (int i in locations)
            {
                sb_sector = imagePlugin.ReadSectors((ulong)i + partition.Start, sb_size_in_sectors);
                uint magic = BigEndianBitConverter.ToUInt32(sb_sector, 0x3F8);

                if (magic == XENIX_MAGIC || magic == SYSV_MAGIC)
                {
                    BigEndianBitConverter.IsLittleEndian = true; // Little endian
                    if (magic == SYSV_MAGIC)
                    {
                        sysv   = true;
                        offset = 0x200;
                    }
                    else
                    {
                        xenix = true;
                    }

                    start = i;
                    break;
                }

                if (magic == XENIX_CIGAM || magic == SYSV_CIGAM)
                {
                    BigEndianBitConverter.IsLittleEndian = false; // Big endian
                    if (magic == SYSV_CIGAM)
                    {
                        sysv   = true;
                        offset = 0x200;
                    }
                    else
                    {
                        xenix = true;
                    }

                    start = i;
                    break;
                }

                magic = BigEndianBitConverter.ToUInt32(sb_sector, 0x1F0); // XENIX 3 magic location

                if (magic == XENIX_MAGIC)
                {
                    BigEndianBitConverter.IsLittleEndian = true; // Little endian
                    xenix3 = true;
                    start  = i;
                    break;
                }

                if (magic == XENIX_CIGAM)
                {
                    BigEndianBitConverter.IsLittleEndian = false; // Big endian
                    xenix3 = true;
                    start  = i;
                    break;
                }

                magic = BigEndianBitConverter.ToUInt32(sb_sector, 0x1F8); // XENIX magic location

                if (magic == SYSV_MAGIC)
                {
                    BigEndianBitConverter.IsLittleEndian = true; // Little endian
                    sysv  = true;
                    start = i;
                    break;
                }

                if (magic == SYSV_CIGAM)
                {
                    BigEndianBitConverter.IsLittleEndian = false; // Big endian
                    sysv  = true;
                    start = i;
                    break;
                }

                byte[] coherent_string = new byte[6];
                Array.Copy(sb_sector, 0x1E4, coherent_string, 0, 6); // Coherent UNIX s_fname location
                string s_fname = StringHandlers.CToString(coherent_string, Encoding);
                Array.Copy(sb_sector, 0x1EA, coherent_string, 0, 6); // Coherent UNIX s_fpack location
                string s_fpack = StringHandlers.CToString(coherent_string, Encoding);

                if (s_fname == COH_FNAME && s_fpack == COH_FPACK || s_fname == COH_XXXXX && s_fpack == COH_XXXXX ||
                    s_fname == COH_XXXXS && s_fpack == COH_XXXXN)
                {
                    BigEndianBitConverter.IsLittleEndian = true; // Coherent is in PDP endianness, use helper for that
                    coherent = true;
                    start    = i;
                    break;
                }

                // Now try to identify 7th edition
                uint   s_fsize  = BitConverter.ToUInt32(sb_sector, 0x002);
                ushort s_nfree  = BitConverter.ToUInt16(sb_sector, 0x006);
                ushort s_ninode = BitConverter.ToUInt16(sb_sector, 0x0D0);

                if (s_fsize <= 0 || s_fsize >= 0xFFFFFFFF || s_nfree <= 0 || s_nfree >= 0xFFFF || s_ninode <= 0 ||
                    s_ninode >= 0xFFFF)
                {
                    continue;
                }

                if ((s_fsize & 0xFF) == 0x00 && (s_nfree & 0xFF) == 0x00 && (s_ninode & 0xFF) == 0x00)
                {
                    // Byteswap
                    s_fsize = ((s_fsize & 0xFF) << 24) + ((s_fsize & 0xFF00) << 8) + ((s_fsize & 0xFF0000) >> 8) +
                              ((s_fsize & 0xFF000000) >> 24);
                    s_nfree  = (ushort)(s_nfree >> 8);
                    s_ninode = (ushort)(s_ninode >> 8);
                }

                if ((s_fsize & 0xFF000000) != 0x00 || (s_nfree & 0xFF00) != 0x00 ||
                    (s_ninode & 0xFF00) != 0x00)
                {
                    continue;
                }

                if (s_fsize >= V7_MAXSIZE || s_nfree >= V7_NICFREE || s_ninode >= V7_NICINOD)
                {
                    continue;
                }

                if (s_fsize * 1024 != (partition.End - partition.Start) * imagePlugin.Info.SectorSize &&
                    s_fsize * 512 != (partition.End - partition.Start) * imagePlugin.Info.SectorSize)
                {
                    continue;
                }

                sys7th = true;
                BigEndianBitConverter.IsLittleEndian = true;
                start = i;
                break;
            }

            if (!sys7th && !sysv && !coherent && !xenix && !xenix3)
            {
                return;
            }

            XmlFsType = new FileSystemType();

            if (xenix || xenix3)
            {
                byte[]          xenix_strings = new byte[6];
                XenixSuperBlock xnx_sb        = new XenixSuperBlock();
                sb_sector = imagePlugin.ReadSectors((ulong)start + partition.Start, sb_size_in_sectors);

                if (xenix3)
                {
                    xnx_sb.s_isize   = BigEndianBitConverter.ToUInt16(sb_sector, 0x000);
                    xnx_sb.s_fsize   = BigEndianBitConverter.ToUInt32(sb_sector, 0x002);
                    xnx_sb.s_nfree   = BigEndianBitConverter.ToUInt16(sb_sector, 0x006);
                    xnx_sb.s_ninode  = BigEndianBitConverter.ToUInt16(sb_sector, 0x0D0);
                    xnx_sb.s_flock   = sb_sector[0x19A];
                    xnx_sb.s_ilock   = sb_sector[0x19B];
                    xnx_sb.s_fmod    = sb_sector[0x19C];
                    xnx_sb.s_ronly   = sb_sector[0x19D];
                    xnx_sb.s_time    = BigEndianBitConverter.ToInt32(sb_sector, 0x19E);
                    xnx_sb.s_tfree   = BigEndianBitConverter.ToUInt32(sb_sector, 0x1A2);
                    xnx_sb.s_tinode  = BigEndianBitConverter.ToUInt16(sb_sector, 0x1A6);
                    xnx_sb.s_cylblks = BigEndianBitConverter.ToUInt16(sb_sector, 0x1A8);
                    xnx_sb.s_gapblks = BigEndianBitConverter.ToUInt16(sb_sector, 0x1AA);
                    xnx_sb.s_dinfo0  = BigEndianBitConverter.ToUInt16(sb_sector, 0x1AC);
                    xnx_sb.s_dinfo1  = BigEndianBitConverter.ToUInt16(sb_sector, 0x1AE);
                    Array.Copy(sb_sector, 0x1B0, xenix_strings, 0, 6);
                    xnx_sb.s_fname = StringHandlers.CToString(xenix_strings, Encoding);
                    Array.Copy(sb_sector, 0x1B6, xenix_strings, 0, 6);
                    xnx_sb.s_fpack = StringHandlers.CToString(xenix_strings, Encoding);
                    xnx_sb.s_clean = sb_sector[0x1BC];
                    xnx_sb.s_magic = BigEndianBitConverter.ToUInt32(sb_sector, 0x1F0);
                    xnx_sb.s_type  = BigEndianBitConverter.ToUInt32(sb_sector, 0x1F4);
                }
                else
                {
                    xnx_sb.s_isize   = BigEndianBitConverter.ToUInt16(sb_sector, 0x000);
                    xnx_sb.s_fsize   = BigEndianBitConverter.ToUInt32(sb_sector, 0x002);
                    xnx_sb.s_nfree   = BigEndianBitConverter.ToUInt16(sb_sector, 0x006);
                    xnx_sb.s_ninode  = BigEndianBitConverter.ToUInt16(sb_sector, 0x198);
                    xnx_sb.s_flock   = sb_sector[0x262];
                    xnx_sb.s_ilock   = sb_sector[0x263];
                    xnx_sb.s_fmod    = sb_sector[0x264];
                    xnx_sb.s_ronly   = sb_sector[0x265];
                    xnx_sb.s_time    = BigEndianBitConverter.ToInt32(sb_sector, 0x266);
                    xnx_sb.s_tfree   = BigEndianBitConverter.ToUInt32(sb_sector, 0x26A);
                    xnx_sb.s_tinode  = BigEndianBitConverter.ToUInt16(sb_sector, 0x26E);
                    xnx_sb.s_cylblks = BigEndianBitConverter.ToUInt16(sb_sector, 0x270);
                    xnx_sb.s_gapblks = BigEndianBitConverter.ToUInt16(sb_sector, 0x272);
                    xnx_sb.s_dinfo0  = BigEndianBitConverter.ToUInt16(sb_sector, 0x274);
                    xnx_sb.s_dinfo1  = BigEndianBitConverter.ToUInt16(sb_sector, 0x276);
                    Array.Copy(sb_sector, 0x278, xenix_strings, 0, 6);
                    xnx_sb.s_fname = StringHandlers.CToString(xenix_strings, Encoding);
                    Array.Copy(sb_sector, 0x27E, xenix_strings, 0, 6);
                    xnx_sb.s_fpack = StringHandlers.CToString(xenix_strings, Encoding);
                    xnx_sb.s_clean = sb_sector[0x284];
                    xnx_sb.s_magic = BigEndianBitConverter.ToUInt32(sb_sector, 0x3F8);
                    xnx_sb.s_type  = BigEndianBitConverter.ToUInt32(sb_sector, 0x3FC);
                }

                uint bs = 512;
                sb.AppendLine("XENIX filesystem");
                XmlFsType.Type = "XENIX fs";
                switch (xnx_sb.s_type)
                {
                case 1:
                    sb.AppendLine("512 bytes per block");
                    XmlFsType.ClusterSize = 512;
                    break;

                case 2:
                    sb.AppendLine("1024 bytes per block");
                    bs = 1024;
                    XmlFsType.ClusterSize = 1024;
                    break;

                case 3:
                    sb.AppendLine("2048 bytes per block");
                    bs = 2048;
                    XmlFsType.ClusterSize = 2048;
                    break;

                default:
                    sb.AppendFormat("Unknown s_type value: 0x{0:X8}", xnx_sb.s_type).AppendLine();
                    break;
                }

                if (imagePlugin.Info.SectorSize == 2336 || imagePlugin.Info.SectorSize == 2352 ||
                    imagePlugin.Info.SectorSize == 2448)
                {
                    if (bs != 2048)
                    {
                        sb
                        .AppendFormat("WARNING: Filesystem indicates {0} bytes/block while device indicates {1} bytes/sector",
                                      bs, 2048).AppendLine();
                    }
                }
                else
                {
                    if (bs != imagePlugin.Info.SectorSize)
                    {
                        sb
                        .AppendFormat("WARNING: Filesystem indicates {0} bytes/block while device indicates {1} bytes/sector",
                                      bs, imagePlugin.Info.SectorSize).AppendLine();
                    }
                }

                sb.AppendFormat("{0} zones on volume ({1} bytes)", xnx_sb.s_fsize, xnx_sb.s_fsize * bs).AppendLine();
                sb.AppendFormat("{0} free zones on volume ({1} bytes)", xnx_sb.s_tfree, xnx_sb.s_tfree * bs)
                .AppendLine();
                sb.AppendFormat("{0} free blocks on list ({1} bytes)", xnx_sb.s_nfree, xnx_sb.s_nfree * bs)
                .AppendLine();
                sb.AppendFormat("{0} blocks per cylinder ({1} bytes)", xnx_sb.s_cylblks, xnx_sb.s_cylblks * bs)
                .AppendLine();
                sb.AppendFormat("{0} blocks per gap ({1} bytes)", xnx_sb.s_gapblks, xnx_sb.s_gapblks * bs).AppendLine();
                sb.AppendFormat("First data zone: {0}", xnx_sb.s_isize).AppendLine();
                sb.AppendFormat("{0} free inodes on volume", xnx_sb.s_tinode).AppendLine();
                sb.AppendFormat("{0} free inodes on list", xnx_sb.s_ninode).AppendLine();
                if (xnx_sb.s_flock > 0)
                {
                    sb.AppendLine("Free block list is locked");
                }
                if (xnx_sb.s_ilock > 0)
                {
                    sb.AppendLine("inode cache is locked");
                }
                if (xnx_sb.s_fmod > 0)
                {
                    sb.AppendLine("Superblock is being modified");
                }
                if (xnx_sb.s_ronly > 0)
                {
                    sb.AppendLine("Volume is mounted read-only");
                }
                sb.AppendFormat("Superblock last updated on {0}", DateHandlers.UnixToDateTime(xnx_sb.s_time))
                .AppendLine();
                if (xnx_sb.s_time != 0)
                {
                    XmlFsType.ModificationDate          = DateHandlers.UnixToDateTime(xnx_sb.s_time);
                    XmlFsType.ModificationDateSpecified = true;
                }

                sb.AppendFormat("Volume name: {0}", xnx_sb.s_fname).AppendLine();
                XmlFsType.VolumeName = xnx_sb.s_fname;
                sb.AppendFormat("Pack name: {0}", xnx_sb.s_fpack).AppendLine();
                if (xnx_sb.s_clean == 0x46)
                {
                    sb.AppendLine("Volume is clean");
                }
                else
                {
                    sb.AppendLine("Volume is dirty");
                    XmlFsType.Dirty = true;
                }
            }

            if (sysv)
            {
                sb_sector = imagePlugin.ReadSectors((ulong)start + partition.Start, sb_size_in_sectors);
                byte[] sysv_strings = new byte[6];

                SystemVRelease4SuperBlock sysv_sb = new SystemVRelease4SuperBlock
                {
                    s_type = BigEndianBitConverter.ToUInt32(sb_sector, 0x1FC + offset)
                };
                uint bs = 512;
                switch (sysv_sb.s_type)
                {
                case 1:
                    XmlFsType.ClusterSize = 512;
                    break;

                case 2:
                    bs = 1024;
                    XmlFsType.ClusterSize = 1024;
                    break;

                case 3:
                    bs = 2048;
                    XmlFsType.ClusterSize = 2048;
                    break;

                default:
                    sb.AppendFormat("Unknown s_type value: 0x{0:X8}", sysv_sb.s_type).AppendLine();
                    break;
                }

                sysv_sb.s_fsize = BigEndianBitConverter.ToUInt32(sb_sector, 0x002 + offset);

                bool sysvr4 = sysv_sb.s_fsize * bs <= 0 || sysv_sb.s_fsize * bs != partition.Size;

                if (sysvr4)
                {
                    sysv_sb.s_isize   = BigEndianBitConverter.ToUInt16(sb_sector, 0x000 + offset);
                    sysv_sb.s_state   = BigEndianBitConverter.ToUInt32(sb_sector, 0x1F4 + offset);
                    sysv_sb.s_magic   = BigEndianBitConverter.ToUInt32(sb_sector, 0x1F8 + offset);
                    sysv_sb.s_fsize   = BigEndianBitConverter.ToUInt32(sb_sector, 0x004 + offset);
                    sysv_sb.s_nfree   = BigEndianBitConverter.ToUInt16(sb_sector, 0x008 + offset);
                    sysv_sb.s_ninode  = BigEndianBitConverter.ToUInt16(sb_sector, 0x0D4 + offset);
                    sysv_sb.s_flock   = sb_sector[0x1A0 + offset];
                    sysv_sb.s_ilock   = sb_sector[0x1A1 + offset];
                    sysv_sb.s_fmod    = sb_sector[0x1A2 + offset];
                    sysv_sb.s_ronly   = sb_sector[0x1A3 + offset];
                    sysv_sb.s_time    = BigEndianBitConverter.ToUInt32(sb_sector, 0x1A4 + offset);
                    sysv_sb.s_cylblks = BigEndianBitConverter.ToUInt16(sb_sector, 0x1A8 + offset);
                    sysv_sb.s_gapblks = BigEndianBitConverter.ToUInt16(sb_sector, 0x1AA + offset);
                    sysv_sb.s_dinfo0  = BigEndianBitConverter.ToUInt16(sb_sector, 0x1AC + offset);
                    sysv_sb.s_dinfo1  = BigEndianBitConverter.ToUInt16(sb_sector, 0x1AE + offset);
                    sysv_sb.s_tfree   = BigEndianBitConverter.ToUInt32(sb_sector, 0x1B0 + offset);
                    sysv_sb.s_tinode  = BigEndianBitConverter.ToUInt16(sb_sector, 0x1B4 + offset);
                    Array.Copy(sb_sector, 0x1B6 + offset, sysv_strings, 0, 6);
                    sysv_sb.s_fname = StringHandlers.CToString(sysv_strings, Encoding);
                    Array.Copy(sb_sector, 0x1BC + offset, sysv_strings, 0, 6);
                    sysv_sb.s_fpack = StringHandlers.CToString(sysv_strings, Encoding);
                    sb.AppendLine("System V Release 4 filesystem");
                    XmlFsType.Type = "SVR4 fs";
                }
                else
                {
                    sysv_sb.s_isize   = BigEndianBitConverter.ToUInt16(sb_sector, 0x000 + offset);
                    sysv_sb.s_state   = BigEndianBitConverter.ToUInt32(sb_sector, 0x1F4 + offset);
                    sysv_sb.s_magic   = BigEndianBitConverter.ToUInt32(sb_sector, 0x1F8 + offset);
                    sysv_sb.s_fsize   = BigEndianBitConverter.ToUInt32(sb_sector, 0x002 + offset);
                    sysv_sb.s_nfree   = BigEndianBitConverter.ToUInt16(sb_sector, 0x006 + offset);
                    sysv_sb.s_ninode  = BigEndianBitConverter.ToUInt16(sb_sector, 0x0D0 + offset);
                    sysv_sb.s_flock   = sb_sector[0x19A + offset];
                    sysv_sb.s_ilock   = sb_sector[0x19B + offset];
                    sysv_sb.s_fmod    = sb_sector[0x19C + offset];
                    sysv_sb.s_ronly   = sb_sector[0x19D + offset];
                    sysv_sb.s_time    = BigEndianBitConverter.ToUInt32(sb_sector, 0x19E + offset);
                    sysv_sb.s_cylblks = BigEndianBitConverter.ToUInt16(sb_sector, 0x1A2 + offset);
                    sysv_sb.s_gapblks = BigEndianBitConverter.ToUInt16(sb_sector, 0x1A4 + offset);
                    sysv_sb.s_dinfo0  = BigEndianBitConverter.ToUInt16(sb_sector, 0x1A6 + offset);
                    sysv_sb.s_dinfo1  = BigEndianBitConverter.ToUInt16(sb_sector, 0x1A8 + offset);
                    sysv_sb.s_tfree   = BigEndianBitConverter.ToUInt32(sb_sector, 0x1AA + offset);
                    sysv_sb.s_tinode  = BigEndianBitConverter.ToUInt16(sb_sector, 0x1AE + offset);
                    Array.Copy(sb_sector, 0x1B0 + offset, sysv_strings, 0, 6);
                    sysv_sb.s_fname = StringHandlers.CToString(sysv_strings, Encoding);
                    Array.Copy(sb_sector, 0x1B6 + offset, sysv_strings, 0, 6);
                    sysv_sb.s_fpack = StringHandlers.CToString(sysv_strings, Encoding);
                    sb.AppendLine("System V Release 2 filesystem");
                    XmlFsType.Type = "SVR2 fs";
                }

                sb.AppendFormat("{0} bytes per block", bs).AppendLine();

                XmlFsType.Clusters = sysv_sb.s_fsize;
                sb.AppendFormat("{0} zones on volume ({1} bytes)", sysv_sb.s_fsize, sysv_sb.s_fsize * bs).AppendLine();
                sb.AppendFormat("{0} free zones on volume ({1} bytes)", sysv_sb.s_tfree, sysv_sb.s_tfree * bs)
                .AppendLine();
                sb.AppendFormat("{0} free blocks on list ({1} bytes)", sysv_sb.s_nfree, sysv_sb.s_nfree * bs)
                .AppendLine();
                sb.AppendFormat("{0} blocks per cylinder ({1} bytes)", sysv_sb.s_cylblks, sysv_sb.s_cylblks * bs)
                .AppendLine();
                sb.AppendFormat("{0} blocks per gap ({1} bytes)", sysv_sb.s_gapblks, sysv_sb.s_gapblks * bs)
                .AppendLine();
                sb.AppendFormat("First data zone: {0}", sysv_sb.s_isize).AppendLine();
                sb.AppendFormat("{0} free inodes on volume", sysv_sb.s_tinode).AppendLine();
                sb.AppendFormat("{0} free inodes on list", sysv_sb.s_ninode).AppendLine();
                if (sysv_sb.s_flock > 0)
                {
                    sb.AppendLine("Free block list is locked");
                }
                if (sysv_sb.s_ilock > 0)
                {
                    sb.AppendLine("inode cache is locked");
                }
                if (sysv_sb.s_fmod > 0)
                {
                    sb.AppendLine("Superblock is being modified");
                }
                if (sysv_sb.s_ronly > 0)
                {
                    sb.AppendLine("Volume is mounted read-only");
                }
                sb.AppendFormat("Superblock last updated on {0}", DateHandlers.UnixUnsignedToDateTime(sysv_sb.s_time))
                .AppendLine();
                if (sysv_sb.s_time != 0)
                {
                    XmlFsType.ModificationDate          = DateHandlers.UnixUnsignedToDateTime(sysv_sb.s_time);
                    XmlFsType.ModificationDateSpecified = true;
                }

                sb.AppendFormat("Volume name: {0}", sysv_sb.s_fname).AppendLine();
                XmlFsType.VolumeName = sysv_sb.s_fname;
                sb.AppendFormat("Pack name: {0}", sysv_sb.s_fpack).AppendLine();
                if (sysv_sb.s_state == 0x7C269D38 - sysv_sb.s_time)
                {
                    sb.AppendLine("Volume is clean");
                }
                else
                {
                    sb.AppendLine("Volume is dirty");
                    XmlFsType.Dirty = true;
                }
            }

            if (coherent)
            {
                sb_sector = imagePlugin.ReadSectors((ulong)start + partition.Start, sb_size_in_sectors);
                CoherentSuperBlock coh_sb      = new CoherentSuperBlock();
                byte[]             coh_strings = new byte[6];

                coh_sb.s_isize  = BitConverter.ToUInt16(sb_sector, 0x000);
                coh_sb.s_fsize  = Swapping.PDPFromLittleEndian(BitConverter.ToUInt32(sb_sector, 0x002));
                coh_sb.s_nfree  = BitConverter.ToUInt16(sb_sector, 0x006);
                coh_sb.s_ninode = BitConverter.ToUInt16(sb_sector, 0x108);
                coh_sb.s_flock  = sb_sector[0x1D2];
                coh_sb.s_ilock  = sb_sector[0x1D3];
                coh_sb.s_fmod   = sb_sector[0x1D4];
                coh_sb.s_ronly  = sb_sector[0x1D5];
                coh_sb.s_time   = Swapping.PDPFromLittleEndian(BitConverter.ToUInt32(sb_sector, 0x1D6));
                coh_sb.s_tfree  = Swapping.PDPFromLittleEndian(BitConverter.ToUInt32(sb_sector, 0x1DA));
                coh_sb.s_tinode = BitConverter.ToUInt16(sb_sector, 0x1DE);
                coh_sb.s_int_m  = BitConverter.ToUInt16(sb_sector, 0x1E0);
                coh_sb.s_int_n  = BitConverter.ToUInt16(sb_sector, 0x1E2);
                Array.Copy(sb_sector, 0x1E4, coh_strings, 0, 6);
                coh_sb.s_fname = StringHandlers.CToString(coh_strings, Encoding);
                Array.Copy(sb_sector, 0x1EA, coh_strings, 0, 6);
                coh_sb.s_fpack = StringHandlers.CToString(coh_strings, Encoding);

                XmlFsType.Type        = "Coherent fs";
                XmlFsType.ClusterSize = 512;
                XmlFsType.Clusters    = coh_sb.s_fsize;

                sb.AppendLine("Coherent UNIX filesystem");
                if (imagePlugin.Info.SectorSize != 512)
                {
                    sb
                    .AppendFormat("WARNING: Filesystem indicates {0} bytes/block while device indicates {1} bytes/sector",
                                  512, 2048).AppendLine();
                }
                sb.AppendFormat("{0} zones on volume ({1} bytes)", coh_sb.s_fsize, coh_sb.s_fsize * 512).AppendLine();
                sb.AppendFormat("{0} free zones on volume ({1} bytes)", coh_sb.s_tfree, coh_sb.s_tfree * 512)
                .AppendLine();
                sb.AppendFormat("{0} free blocks on list ({1} bytes)", coh_sb.s_nfree, coh_sb.s_nfree * 512)
                .AppendLine();
                sb.AppendFormat("First data zone: {0}", coh_sb.s_isize).AppendLine();
                sb.AppendFormat("{0} free inodes on volume", coh_sb.s_tinode).AppendLine();
                sb.AppendFormat("{0} free inodes on list", coh_sb.s_ninode).AppendLine();
                if (coh_sb.s_flock > 0)
                {
                    sb.AppendLine("Free block list is locked");
                }
                if (coh_sb.s_ilock > 0)
                {
                    sb.AppendLine("inode cache is locked");
                }
                if (coh_sb.s_fmod > 0)
                {
                    sb.AppendLine("Superblock is being modified");
                }
                if (coh_sb.s_ronly > 0)
                {
                    sb.AppendLine("Volume is mounted read-only");
                }
                sb.AppendFormat("Superblock last updated on {0}", DateHandlers.UnixUnsignedToDateTime(coh_sb.s_time))
                .AppendLine();
                if (coh_sb.s_time != 0)
                {
                    XmlFsType.ModificationDate          = DateHandlers.UnixUnsignedToDateTime(coh_sb.s_time);
                    XmlFsType.ModificationDateSpecified = true;
                }

                sb.AppendFormat("Volume name: {0}", coh_sb.s_fname).AppendLine();
                XmlFsType.VolumeName = coh_sb.s_fname;
                sb.AppendFormat("Pack name: {0}", coh_sb.s_fpack).AppendLine();
            }

            if (sys7th)
            {
                sb_sector = imagePlugin.ReadSectors((ulong)start + partition.Start, sb_size_in_sectors);
                UNIX7thEditionSuperBlock v7_sb = new UNIX7thEditionSuperBlock();
                byte[] sys7_strings            = new byte[6];

                v7_sb.s_isize  = BigEndianBitConverter.ToUInt16(sb_sector, 0x000);
                v7_sb.s_fsize  = BigEndianBitConverter.ToUInt32(sb_sector, 0x002);
                v7_sb.s_nfree  = BigEndianBitConverter.ToUInt16(sb_sector, 0x006);
                v7_sb.s_ninode = BigEndianBitConverter.ToUInt16(sb_sector, 0x0D0);
                v7_sb.s_flock  = sb_sector[0x19A];
                v7_sb.s_ilock  = sb_sector[0x19B];
                v7_sb.s_fmod   = sb_sector[0x19C];
                v7_sb.s_ronly  = sb_sector[0x19D];
                v7_sb.s_time   = BigEndianBitConverter.ToUInt32(sb_sector, 0x19E);
                v7_sb.s_tfree  = BigEndianBitConverter.ToUInt32(sb_sector, 0x1A2);
                v7_sb.s_tinode = BigEndianBitConverter.ToUInt16(sb_sector, 0x1A6);
                v7_sb.s_int_m  = BigEndianBitConverter.ToUInt16(sb_sector, 0x1A8);
                v7_sb.s_int_n  = BigEndianBitConverter.ToUInt16(sb_sector, 0x1AA);
                Array.Copy(sb_sector, 0x1AC, sys7_strings, 0, 6);
                v7_sb.s_fname = StringHandlers.CToString(sys7_strings, Encoding);
                Array.Copy(sb_sector, 0x1B2, sys7_strings, 0, 6);
                v7_sb.s_fpack = StringHandlers.CToString(sys7_strings, Encoding);

                XmlFsType.Type        = "UNIX 7th Edition fs";
                XmlFsType.ClusterSize = 512;
                XmlFsType.Clusters    = v7_sb.s_fsize;
                sb.AppendLine("UNIX 7th Edition filesystem");
                if (imagePlugin.Info.SectorSize != 512)
                {
                    sb
                    .AppendFormat("WARNING: Filesystem indicates {0} bytes/block while device indicates {1} bytes/sector",
                                  512, 2048).AppendLine();
                }
                sb.AppendFormat("{0} zones on volume ({1} bytes)", v7_sb.s_fsize, v7_sb.s_fsize * 512).AppendLine();
                sb.AppendFormat("{0} free zones on volume ({1} bytes)", v7_sb.s_tfree, v7_sb.s_tfree * 512)
                .AppendLine();
                sb.AppendFormat("{0} free blocks on list ({1} bytes)", v7_sb.s_nfree, v7_sb.s_nfree * 512).AppendLine();
                sb.AppendFormat("First data zone: {0}", v7_sb.s_isize).AppendLine();
                sb.AppendFormat("{0} free inodes on volume", v7_sb.s_tinode).AppendLine();
                sb.AppendFormat("{0} free inodes on list", v7_sb.s_ninode).AppendLine();
                if (v7_sb.s_flock > 0)
                {
                    sb.AppendLine("Free block list is locked");
                }
                if (v7_sb.s_ilock > 0)
                {
                    sb.AppendLine("inode cache is locked");
                }
                if (v7_sb.s_fmod > 0)
                {
                    sb.AppendLine("Superblock is being modified");
                }
                if (v7_sb.s_ronly > 0)
                {
                    sb.AppendLine("Volume is mounted read-only");
                }
                sb.AppendFormat("Superblock last updated on {0}", DateHandlers.UnixUnsignedToDateTime(v7_sb.s_time))
                .AppendLine();
                if (v7_sb.s_time != 0)
                {
                    XmlFsType.ModificationDate          = DateHandlers.UnixUnsignedToDateTime(v7_sb.s_time);
                    XmlFsType.ModificationDateSpecified = true;
                }

                sb.AppendFormat("Volume name: {0}", v7_sb.s_fname).AppendLine();
                XmlFsType.VolumeName = v7_sb.s_fname;
                sb.AppendFormat("Pack name: {0}", v7_sb.s_fpack).AppendLine();
            }

            information = sb.ToString();

            BigEndianBitConverter.IsLittleEndian = false; // Return to default (bigendian)
        }
Beispiel #20
0
        public void Open(string path)
        {
            var fs = new FileStream(path, FileMode.Open, FileAccess.Read);

            fs.Seek(0, SeekOrigin.Begin);

            byte[] hdrB = new byte[26];
            fs.Read(hdrB, 0, 26);
            _header = Marshal.ByteArrayToStructureBigEndian <Header>(hdrB);

            Entry[] entries = new Entry[_header.entries];

            for (int i = 0; i < _header.entries; i++)
            {
                byte[] entry = new byte[12];
                fs.Read(entry, 0, 12);
                entries[i] = Marshal.ByteArrayToStructureBigEndian <Entry>(entry);
            }

            _creationTime  = DateTime.UtcNow;
            _lastWriteTime = _creationTime;

            foreach (Entry entry in entries)
            {
                switch ((AppleSingleEntryID)entry.id)
                {
                case AppleSingleEntryID.DataFork:
                    _dataFork = entry;

                    break;

                case AppleSingleEntryID.FileDates:
                    fs.Seek(entry.offset, SeekOrigin.Begin);
                    byte[] datesB = new byte[16];
                    fs.Read(datesB, 0, 16);

                    FileDates dates = Marshal.ByteArrayToStructureBigEndian <FileDates>(datesB);

                    _creationTime  = DateHandlers.MacToDateTime(dates.creationDate);
                    _lastWriteTime = DateHandlers.MacToDateTime(dates.modificationDate);

                    break;

                case AppleSingleEntryID.FileInfo:
                    fs.Seek(entry.offset, SeekOrigin.Begin);
                    byte[] finfo = new byte[entry.length];
                    fs.Read(finfo, 0, finfo.Length);

                    if (_macintoshHome.SequenceEqual(_header.homeFilesystem))
                    {
                        MacFileInfo macinfo = Marshal.ByteArrayToStructureBigEndian <MacFileInfo>(finfo);

                        _creationTime  = DateHandlers.MacToDateTime(macinfo.creationDate);
                        _lastWriteTime = DateHandlers.MacToDateTime(macinfo.modificationDate);
                    }
                    else if (_proDosHome.SequenceEqual(_header.homeFilesystem))
                    {
                        ProDOSFileInfo prodosinfo = Marshal.ByteArrayToStructureBigEndian <ProDOSFileInfo>(finfo);

                        _creationTime  = DateHandlers.MacToDateTime(prodosinfo.creationDate);
                        _lastWriteTime = DateHandlers.MacToDateTime(prodosinfo.modificationDate);
                    }
                    else if (_unixHome.SequenceEqual(_header.homeFilesystem))
                    {
                        UnixFileInfo unixinfo = Marshal.ByteArrayToStructureBigEndian <UnixFileInfo>(finfo);

                        _creationTime  = DateHandlers.UnixUnsignedToDateTime(unixinfo.creationDate);
                        _lastWriteTime = DateHandlers.UnixUnsignedToDateTime(unixinfo.modificationDate);
                    }
                    else if (_dosHome.SequenceEqual(_header.homeFilesystem))
                    {
                        DOSFileInfo dosinfo = Marshal.ByteArrayToStructureBigEndian <DOSFileInfo>(finfo);

                        _lastWriteTime =
                            DateHandlers.DosToDateTime(dosinfo.modificationDate, dosinfo.modificationTime);
                    }

                    break;

                case AppleSingleEntryID.ResourceFork:
                    _rsrcFork = entry;

                    break;
                }
            }

            fs.Close();
            _opened   = true;
            _isPath   = true;
            _basePath = path;
        }
Beispiel #21
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            Encoding    = encoding ?? Encoding.GetEncoding("iso-8859-15");
            information = "";
            byte[] sector = imagePlugin.ReadSector(partition.Start + 1);

            if (sector.Length < 512)
            {
                return;
            }

            Superblock qnxSb = Marshal.ByteArrayToStructureLittleEndian <Superblock>(sector);

            // Too much useless information

            /*
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.rootDir.di_fname = {0}", CurrentEncoding.GetString(qnxSb.rootDir.di_fname));
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.rootDir.di_size = {0}", qnxSb.rootDir.di_size);
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.rootDir.di_first_xtnt.block = {0}", qnxSb.rootDir.di_first_xtnt.block);
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.rootDir.di_first_xtnt.length = {0}", qnxSb.rootDir.di_first_xtnt.length);
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.rootDir.di_xblk = {0}", qnxSb.rootDir.di_xblk);
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.rootDir.di_ftime = {0}", DateHandlers.UNIXUnsignedToDateTime(qnxSb.rootDir.di_ftime));
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.rootDir.di_mtime = {0}", DateHandlers.UNIXUnsignedToDateTime(qnxSb.rootDir.di_mtime));
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.rootDir.di_atime = {0}", DateHandlers.UNIXUnsignedToDateTime(qnxSb.rootDir.di_atime));
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.rootDir.di_ctime = {0}", DateHandlers.UNIXUnsignedToDateTime(qnxSb.rootDir.di_ctime));
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.rootDir.di_num_xtnts = {0}", qnxSb.rootDir.di_num_xtnts);
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.rootDir.di_mode = {0}", Convert.ToString(qnxSb.rootDir.di_mode, 8));
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.rootDir.di_uid = {0}", qnxSb.rootDir.di_uid);
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.rootDir.di_gid = {0}", qnxSb.rootDir.di_gid);
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.rootDir.di_nlink = {0}", qnxSb.rootDir.di_nlink);
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.rootDir.di_zero = {0}", qnxSb.rootDir.di_zero);
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.rootDir.di_type = {0}", qnxSb.rootDir.di_type);
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.rootDir.di_status = {0}", qnxSb.rootDir.di_status);
             *
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.inode.di_fname = {0}", CurrentEncoding.GetString(qnxSb.inode.di_fname));
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.inode.di_size = {0}", qnxSb.inode.di_size);
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.inode.di_first_xtnt.block = {0}", qnxSb.inode.di_first_xtnt.block);
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.inode.di_first_xtnt.length = {0}", qnxSb.inode.di_first_xtnt.length);
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.inode.di_xblk = {0}", qnxSb.inode.di_xblk);
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.inode.di_ftime = {0}", DateHandlers.UNIXUnsignedToDateTime(qnxSb.inode.di_ftime));
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.inode.di_mtime = {0}", DateHandlers.UNIXUnsignedToDateTime(qnxSb.inode.di_mtime));
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.inode.di_atime = {0}", DateHandlers.UNIXUnsignedToDateTime(qnxSb.inode.di_atime));
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.inode.di_ctime = {0}", DateHandlers.UNIXUnsignedToDateTime(qnxSb.inode.di_ctime));
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.inode.di_num_xtnts = {0}", qnxSb.inode.di_num_xtnts);
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.inode.di_mode = {0}", Convert.ToString(qnxSb.inode.di_mode, 8));
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.inode.di_uid = {0}", qnxSb.inode.di_uid);
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.inode.di_gid = {0}", qnxSb.inode.di_gid);
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.inode.di_nlink = {0}", qnxSb.inode.di_nlink);
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.inode.di_zero = {0}", qnxSb.inode.di_zero);
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.inode.di_type = {0}", qnxSb.inode.di_type);
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.inode.di_status = {0}", qnxSb.inode.di_status);
             *
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.boot.di_fname = {0}", CurrentEncoding.GetString(qnxSb.boot.di_fname));
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.boot.di_size = {0}", qnxSb.boot.di_size);
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.boot.di_first_xtnt.block = {0}", qnxSb.boot.di_first_xtnt.block);
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.boot.di_first_xtnt.length = {0}", qnxSb.boot.di_first_xtnt.length);
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.boot.di_xblk = {0}", qnxSb.boot.di_xblk);
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.boot.di_ftime = {0}", DateHandlers.UNIXUnsignedToDateTime(qnxSb.boot.di_ftime));
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.boot.di_mtime = {0}", DateHandlers.UNIXUnsignedToDateTime(qnxSb.boot.di_mtime));
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.boot.di_atime = {0}", DateHandlers.UNIXUnsignedToDateTime(qnxSb.boot.di_atime));
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.boot.di_ctime = {0}", DateHandlers.UNIXUnsignedToDateTime(qnxSb.boot.di_ctime));
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.boot.di_num_xtnts = {0}", qnxSb.boot.di_num_xtnts);
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.boot.di_mode = {0}", Convert.ToString(qnxSb.boot.di_mode, 8));
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.boot.di_uid = {0}", qnxSb.boot.di_uid);
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.boot.di_gid = {0}", qnxSb.boot.di_gid);
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.boot.di_nlink = {0}", qnxSb.boot.di_nlink);
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.boot.di_zero = {0}", qnxSb.boot.di_zero);
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.boot.di_type = {0}", qnxSb.boot.di_type);
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.boot.di_status = {0}", qnxSb.boot.di_status);
             *
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.altBoot.di_fname = {0}", CurrentEncoding.GetString(qnxSb.altBoot.di_fname));
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.altBoot.di_size = {0}", qnxSb.altBoot.di_size);
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.altBoot.di_first_xtnt.block = {0}", qnxSb.altBoot.di_first_xtnt.block);
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.altBoot.di_first_xtnt.length = {0}", qnxSb.altBoot.di_first_xtnt.length);
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.altBoot.di_xblk = {0}", qnxSb.altBoot.di_xblk);
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.altBoot.di_ftime = {0}", DateHandlers.UNIXUnsignedToDateTime(qnxSb.altBoot.di_ftime));
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.altBoot.di_mtime = {0}", DateHandlers.UNIXUnsignedToDateTime(qnxSb.altBoot.di_mtime));
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.altBoot.di_atime = {0}", DateHandlers.UNIXUnsignedToDateTime(qnxSb.altBoot.di_atime));
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.altBoot.di_ctime = {0}", DateHandlers.UNIXUnsignedToDateTime(qnxSb.altBoot.di_ctime));
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.altBoot.di_num_xtnts = {0}", qnxSb.altBoot.di_num_xtnts);
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.altBoot.di_mode = {0}", Convert.ToString(qnxSb.altBoot.di_mode, 8));
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.altBoot.di_uid = {0}", qnxSb.altBoot.di_uid);
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.altBoot.di_gid = {0}", qnxSb.altBoot.di_gid);
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.altBoot.di_nlink = {0}", qnxSb.altBoot.di_nlink);
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.altBoot.di_zero = {0}", qnxSb.altBoot.di_zero);
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.altBoot.di_type = {0}", qnxSb.altBoot.di_type);
             * AaruConsole.DebugWriteLine("QNX4 plugin", "qnxSb.altBoot.di_status = {0}", qnxSb.altBoot.di_status);
             */

            information =
                $"QNX4 filesystem\nCreated on {DateHandlers.UnixUnsignedToDateTime(qnxSb.rootDir.di_ftime)}\n";

            XmlFsType = new FileSystemType
            {
                Type                      = "QNX4 filesystem",
                Clusters                  = partition.Length,
                ClusterSize               = 512,
                CreationDate              = DateHandlers.UnixUnsignedToDateTime(qnxSb.rootDir.di_ftime),
                CreationDateSpecified     = true,
                ModificationDate          = DateHandlers.UnixUnsignedToDateTime(qnxSb.rootDir.di_mtime),
                ModificationDateSpecified = true
            };

            XmlFsType.Bootable |= qnxSb.boot.di_size != 0 || qnxSb.altBoot.di_size != 0;
        }
Beispiel #22
0
        public void Open(Stream stream)
        {
            stream.Seek(0, SeekOrigin.Begin);

            byte[] hdrB = new byte[26];
            stream.Read(hdrB, 0, 26);
            _header = Marshal.ByteArrayToStructureBigEndian <AppleSingleHeader>(hdrB);

            AppleSingleEntry[] entries = new AppleSingleEntry[_header.entries];

            for (int i = 0; i < _header.entries; i++)
            {
                byte[] entry = new byte[12];
                stream.Read(entry, 0, 12);
                entries[i] = Marshal.ByteArrayToStructureBigEndian <AppleSingleEntry>(entry);
            }

            _creationTime  = DateTime.UtcNow;
            _lastWriteTime = _creationTime;

            foreach (AppleSingleEntry entry in entries)
            {
                switch ((AppleSingleEntryID)entry.id)
                {
                case AppleSingleEntryID.DataFork:
                    _dataFork = entry;

                    break;

                case AppleSingleEntryID.FileDates:
                    stream.Seek(entry.offset, SeekOrigin.Begin);
                    byte[] datesB = new byte[16];
                    stream.Read(datesB, 0, 16);

                    AppleSingleFileDates dates =
                        Marshal.ByteArrayToStructureBigEndian <AppleSingleFileDates>(datesB);

                    _creationTime  = DateHandlers.MacToDateTime(dates.creationDate);
                    _lastWriteTime = DateHandlers.MacToDateTime(dates.modificationDate);

                    break;

                case AppleSingleEntryID.FileInfo:
                    stream.Seek(entry.offset, SeekOrigin.Begin);
                    byte[] finfo = new byte[entry.length];
                    stream.Read(finfo, 0, finfo.Length);

                    if (_macintoshHome.SequenceEqual(_header.homeFilesystem))
                    {
                        AppleSingleMacFileInfo macinfo =
                            Marshal.ByteArrayToStructureBigEndian <AppleSingleMacFileInfo>(finfo);

                        _creationTime  = DateHandlers.MacToDateTime(macinfo.creationDate);
                        _lastWriteTime = DateHandlers.MacToDateTime(macinfo.modificationDate);
                    }
                    else if (_proDosHome.SequenceEqual(_header.homeFilesystem))
                    {
                        AppleSingleProDOSFileInfo prodosinfo =
                            Marshal.ByteArrayToStructureBigEndian <AppleSingleProDOSFileInfo>(finfo);

                        _creationTime  = DateHandlers.MacToDateTime(prodosinfo.creationDate);
                        _lastWriteTime = DateHandlers.MacToDateTime(prodosinfo.modificationDate);
                    }
                    else if (_unixHome.SequenceEqual(_header.homeFilesystem))
                    {
                        AppleSingleUnixFileInfo unixinfo =
                            Marshal.ByteArrayToStructureBigEndian <AppleSingleUnixFileInfo>(finfo);

                        _creationTime  = DateHandlers.UnixUnsignedToDateTime(unixinfo.creationDate);
                        _lastWriteTime = DateHandlers.UnixUnsignedToDateTime(unixinfo.modificationDate);
                    }
                    else if (_dosHome.SequenceEqual(_header.homeFilesystem))
                    {
                        AppleSingleDOSFileInfo dosinfo =
                            Marshal.ByteArrayToStructureBigEndian <AppleSingleDOSFileInfo>(finfo);

                        _lastWriteTime =
                            DateHandlers.DosToDateTime(dosinfo.modificationDate, dosinfo.modificationTime);
                    }

                    break;

                case AppleSingleEntryID.ResourceFork:
                    _rsrcFork = entry;

                    break;
                }
            }

            stream.Seek(0, SeekOrigin.Begin);
            _opened   = true;
            _isStream = true;
            _stream   = stream;
        }