예제 #1
0
        public bool Identify(IMediaImage imagePlugin, Partition partition)
        {
            if (imagePlugin.Info.SectorSize < 512)
            {
                return(false);
            }

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

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

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

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

            Superblock unicosSb = Marshal.ByteArrayToStructureBigEndian <Superblock>(sector);

            AaruConsole.DebugWriteLine("UNICOS plugin", "magic = 0x{0:X16} (expected 0x{1:X16})", unicosSb.s_magic,
                                       UNICOS_MAGIC);

            return(unicosSb.s_magic == UNICOS_MAGIC);
        }
예제 #2
0
파일: MacBinary.cs 프로젝트: paulyc/Aaru
        public bool Identify(string path)
        {
            if (!File.Exists(path))
            {
                return(false);
            }

            var fstream = new FileStream(path, FileMode.Open, FileAccess.Read);

            if (fstream.Length < 128)
            {
                return(false);
            }

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

            fstream.Close();

            return(_header.magic == MAGIC || (_header.version == 0 && _header.filename[0] > 0 &&
                                              _header.filename[0] < 64 && _header.zero1 == 0 && _header.zero2 == 0 &&
                                              _header.reserved == 0 &&
                                              (_header.dataLength > 0 || _header.resourceLength > 0)));
        }
예제 #3
0
파일: SFS.cs 프로젝트: paulyc/Aaru
        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"
            };
        }
예제 #4
0
        public bool Identify(IMediaImage imagePlugin, Partition partition)
        {
            if (imagePlugin.Info.SectorSize < 256)
            {
                return(false);
            }

            // Documentation says ID should be sector 0
            // I've found that OS-9/X68000 has it on sector 4
            // I've read OS-9/Apple2 has it on sector 15
            foreach (int i in new[]
            {
                0, 4, 15
            })
            {
                ulong location = (ulong)i;

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

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

                if (partition.Start + location + sbSize >= imagePlugin.Info.Sectors)
                {
                    break;
                }

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

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

                IdSector    rbfSb     = Marshal.ByteArrayToStructureBigEndian <IdSector>(sector);
                NewIdSector rbf9000Sb = Marshal.ByteArrayToStructureBigEndian <NewIdSector>(sector);

                AaruConsole.DebugWriteLine("RBF plugin",
                                           "magic at {0} = 0x{1:X8} or 0x{2:X8} (expected 0x{3:X8} or 0x{4:X8})",
                                           location, rbfSb.dd_sync, rbf9000Sb.rid_sync, RBF_SYNC, RBF_CNYS);

                if (rbfSb.dd_sync == RBF_SYNC ||
                    rbf9000Sb.rid_sync == RBF_SYNC ||
                    rbf9000Sb.rid_sync == RBF_CNYS)
                {
                    return(true);
                }
            }

            return(false);
        }
예제 #5
0
        public bool Identify(IMediaImage imagePlugin, Partition partition)
        {
            if (imagePlugin.Info.SectorSize < 256)
            {
                return(false);
            }

            byte[]      sector = imagePlugin.ReadSector(partition.Start);
            SystemBlock lifSb  = Marshal.ByteArrayToStructureBigEndian <SystemBlock>(sector);

            AaruConsole.DebugWriteLine("LIF plugin", "magic 0x{0:X8} (expected 0x{1:X8})", lifSb.magic, LIF_MAGIC);

            return(lifSb.magic == LIF_MAGIC);
        }
예제 #6
0
파일: AppleSingle.cs 프로젝트: paulyc/Aaru
        public bool Identify(byte[] buffer)
        {
            if (buffer == null ||
                buffer.Length < 26)
            {
                return(false);
            }

            byte[] hdrB = new byte[26];
            Array.Copy(buffer, 0, hdrB, 0, 26);
            _header = Marshal.ByteArrayToStructureBigEndian <Header>(hdrB);

            return(_header.magic == MAGIC && (_header.version == VERSION || _header.version == VERSION2));
        }
예제 #7
0
파일: AppleSingle.cs 프로젝트: paulyc/Aaru
        public bool Identify(Stream stream)
        {
            if (stream == null ||
                stream.Length < 26)
            {
                return(false);
            }

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

            return(_header.magic == MAGIC && (_header.version == VERSION || _header.version == VERSION2));
        }
예제 #8
0
        static RootBlock MarshalRootBlock(byte[] block)
        {
            byte[] tmp = new byte[228];
            Array.Copy(block, 0, tmp, 0, 24);
            Array.Copy(block, block.Length - 200, tmp, 28, 200);
            RootBlock root = Marshal.ByteArrayToStructureBigEndian <RootBlock>(tmp);

            root.hashTable = new uint[(block.Length - 224) / 4];

            for (int i = 0; i < root.hashTable.Length; i++)
            {
                root.hashTable[i] = BigEndianBitConverter.ToUInt32(block, 24 + (i * 4));
            }

            return(root);
        }
예제 #9
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            Encoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
            byte[] sector = imagePlugin.ReadSector(partition.Start);
            uint   magic  = BitConverter.ToUInt32(sector, 0x00);

            var  crSb         = new SuperBlock();
            bool littleEndian = true;

            switch (magic)
            {
            case CRAM_MAGIC:
                crSb = Marshal.ByteArrayToStructureLittleEndian <SuperBlock>(sector);

                break;

            case CRAM_CIGAM:
                crSb         = Marshal.ByteArrayToStructureBigEndian <SuperBlock>(sector);
                littleEndian = false;

                break;
            }

            var sbInformation = new StringBuilder();

            sbInformation.AppendLine("Cram file system");
            sbInformation.AppendLine(littleEndian ? "Little-endian" : "Big-endian");
            sbInformation.AppendFormat("Volume edition {0}", crSb.edition).AppendLine();
            sbInformation.AppendFormat("Volume name: {0}", StringHandlers.CToString(crSb.name, Encoding)).AppendLine();
            sbInformation.AppendFormat("Volume has {0} bytes", crSb.size).AppendLine();
            sbInformation.AppendFormat("Volume has {0} blocks", crSb.blocks).AppendLine();
            sbInformation.AppendFormat("Volume has {0} files", crSb.files).AppendLine();

            information = sbInformation.ToString();

            XmlFsType = new FileSystemType
            {
                VolumeName            = StringHandlers.CToString(crSb.name, Encoding),
                Type                  = "Cram file system",
                Clusters              = crSb.blocks,
                Files                 = crSb.files,
                FilesSpecified        = true,
                FreeClusters          = 0,
                FreeClustersSpecified = true
            };
        }
예제 #10
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 < 256)
            {
                return;
            }

            byte[]      sector = imagePlugin.ReadSector(partition.Start);
            SystemBlock lifSb  = Marshal.ByteArrayToStructureBigEndian <SystemBlock>(sector);

            if (lifSb.magic != LIF_MAGIC)
            {
                return;
            }

            var sb = new StringBuilder();

            sb.AppendLine("HP Logical Interchange Format");
            sb.AppendFormat("Directory starts at cluster {0}", lifSb.directoryStart).AppendLine();
            sb.AppendFormat("LIF identifier: {0}", lifSb.lifId).AppendLine();
            sb.AppendFormat("Directory size: {0} clusters", lifSb.directorySize).AppendLine();
            sb.AppendFormat("LIF version: {0}", lifSb.lifVersion).AppendLine();

            // How is this related to volume size? I have only CDs to test and makes no sense there
            sb.AppendFormat("{0} tracks", lifSb.tracks).AppendLine();
            sb.AppendFormat("{0} heads", lifSb.heads).AppendLine();
            sb.AppendFormat("{0} sectors", lifSb.sectors).AppendLine();
            sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(lifSb.volumeLabel, Encoding)).AppendLine();
            sb.AppendFormat("Volume created on {0}", DateHandlers.LifToDateTime(lifSb.creationDate)).AppendLine();

            information = sb.ToString();

            XmlFsType = new FileSystemType
            {
                Type                  = "HP Logical Interchange Format",
                ClusterSize           = 256,
                Clusters              = partition.Size / 256,
                CreationDate          = DateHandlers.LifToDateTime(lifSb.creationDate),
                CreationDateSpecified = true,
                VolumeName            = StringHandlers.CToString(lifSb.volumeLabel, Encoding)
            };
        }
예제 #11
0
        public bool Identify(byte[] buffer)
        {
            if (buffer == null ||
                buffer.Length < 128)
            {
                return(false);
            }

            byte[] hdrB = new byte[128];
            Array.Copy(buffer, 0, hdrB, 0, 128);
            _header = Marshal.ByteArrayToStructureBigEndian <MacBinaryHeader>(hdrB);

            return(_header.magic == MAGIC || (_header.version == 0 && _header.filename[0] > 0 &&
                                              _header.filename[0] < 64 && _header.zero1 == 0 && _header.zero2 == 0 &&
                                              _header.reserved == 0 &&
                                              (_header.dataLength > 0 || _header.resourceLength > 0)));
        }
예제 #12
0
        public bool Identify(IMediaImage imagePlugin, Partition partition)
        {
            ulong hdrSector = HEADER_POS / imagePlugin.Info.SectorSize;

            if (partition.Start + hdrSector > imagePlugin.Info.Sectors)
            {
                return(false);
            }

            byte[] sector = imagePlugin.ReadSector(partition.Start + hdrSector);
            Header hdr    = Marshal.ByteArrayToStructureBigEndian <Header>(sector);

            AaruConsole.DebugWriteLine("Fossil plugin", "magic at 0x{0:X8} (expected 0x{1:X8})", hdr.magic,
                                       FOSSIL_HDR_MAGIC);

            return(hdr.magic == FOSSIL_HDR_MAGIC);
        }
예제 #13
0
        public bool Identify(string path)
        {
            var fstream = new FileStream(path, FileMode.Open, FileAccess.Read);

            if (fstream.Length < 26)
            {
                return(false);
            }

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

            fstream.Close();

            return(_header.magic == MAGIC && (_header.version == VERSION || _header.version == VERSION2));
        }
예제 #14
0
        public bool Identify(Stream stream)
        {
            if (stream == null ||
                stream.Length < 128)
            {
                return(false);
            }

            byte[] hdrB = new byte[128];
            stream.Seek(0, SeekOrigin.Begin);
            stream.Read(hdrB, 0, 128);
            _header = Marshal.ByteArrayToStructureBigEndian <MacBinaryHeader>(hdrB);

            return(_header.magic == MAGIC || (_header.version == 0 && _header.filename[0] > 0 &&
                                              _header.filename[0] < 64 && _header.zero1 == 0 && _header.zero2 == 0 &&
                                              _header.reserved == 0 &&
                                              (_header.dataLength > 0 || _header.resourceLength > 0)));
        }
예제 #15
0
        public void Open(string path)
        {
            var fs = new FileStream(path, FileMode.Open, FileAccess.Read);

            fs.Seek(0, SeekOrigin.Begin);

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

            uint blocks = 1;

            blocks += (uint)(_header.secondaryHeaderLength / 128);

            if (_header.secondaryHeaderLength % 128 > 0)
            {
                blocks++;
            }

            _dataForkOff = blocks * 128;
            blocks      += _header.dataLength / 128;

            if (_header.dataLength % 128 > 0)
            {
                blocks++;
            }

            _rsrcForkOff = blocks * 128;

            _filename      = StringHandlers.PascalToString(_header.filename, Encoding.GetEncoding("macintosh"));
            _creationTime  = DateHandlers.MacToDateTime(_header.creationTime);
            _lastWriteTime = DateHandlers.MacToDateTime(_header.modificationTime);

            fs.Close();
            _opened   = true;
            _isPath   = true;
            _basePath = path;
        }
예제 #16
0
        public void Open(byte[] buffer)
        {
            var ms = new MemoryStream(buffer);

            ms.Seek(0, SeekOrigin.Begin);

            byte[] hdrB = new byte[128];
            ms.Read(hdrB, 0, 128);
            _header = Marshal.ByteArrayToStructureBigEndian <MacBinaryHeader>(hdrB);

            uint blocks = 1;

            blocks += (uint)(_header.secondaryHeaderLength / 128);

            if (_header.secondaryHeaderLength % 128 > 0)
            {
                blocks++;
            }

            _dataForkOff = blocks * 128;
            blocks      += _header.dataLength / 128;

            if (_header.dataLength % 128 > 0)
            {
                blocks++;
            }

            _rsrcForkOff = blocks * 128;

            _filename      = StringHandlers.PascalToString(_header.filename, Encoding.GetEncoding("macintosh"));
            _creationTime  = DateHandlers.MacToDateTime(_header.creationTime);
            _lastWriteTime = DateHandlers.MacToDateTime(_header.modificationTime);

            ms.Close();
            _opened  = true;
            _isBytes = true;
            _bytes   = buffer;
        }
예제 #17
0
파일: MacBinary.cs 프로젝트: paulyc/Aaru
        public void Open(Stream stream)
        {
            stream.Seek(0, SeekOrigin.Begin);

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

            uint blocks = 1;

            blocks += (uint)(_header.secondaryHeaderLength / 128);

            if (_header.secondaryHeaderLength % 128 > 0)
            {
                blocks++;
            }

            _dataForkOff = blocks * 128;
            blocks      += _header.dataLength / 128;

            if (_header.dataLength % 128 > 0)
            {
                blocks++;
            }

            _rsrcForkOff = blocks * 128;

            _filename      = StringHandlers.PascalToString(_header.filename, Encoding.GetEncoding("macintosh"));
            _creationTime  = DateHandlers.MacToDateTime(_header.creationTime);
            _lastWriteTime = DateHandlers.MacToDateTime(_header.modificationTime);

            stream.Seek(0, SeekOrigin.Begin);
            _opened   = true;
            _isStream = true;
            _stream   = stream;
        }
예제 #18
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;
            }

            var xfsSb = new Superblock();

            // Misaligned
            if (imagePlugin.Info.XmlMediaType == XmlMediaType.OpticalDisc)
            {
                uint sbSize = (uint)((Marshal.SizeOf <Superblock>() + 0x400) / imagePlugin.Info.SectorSize);

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

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

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

                byte[] sbpiece = new byte[Marshal.SizeOf <Superblock>()];

                foreach (int location in new[]
                {
                    0, 0x200, 0x400
                })
                {
                    Array.Copy(sector, location, sbpiece, 0, Marshal.SizeOf <Superblock>());

                    xfsSb = Marshal.ByteArrayToStructureBigEndian <Superblock>(sbpiece);

                    AaruConsole.DebugWriteLine("XFS plugin", "magic at 0x{0:X3} = 0x{1:X8} (expected 0x{2:X8})",
                                               location, xfsSb.magicnum, XFS_MAGIC);

                    if (xfsSb.magicnum == XFS_MAGIC)
                    {
                        break;
                    }
                }
            }
            else
            {
                foreach (int i in new[]
                {
                    0, 1, 2
                })
                {
                    ulong location = (ulong)i;
                    uint  sbSize   = (uint)(Marshal.SizeOf <Superblock>() / imagePlugin.Info.SectorSize);

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

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

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

                    xfsSb = Marshal.ByteArrayToStructureBigEndian <Superblock>(sector);

                    AaruConsole.DebugWriteLine("XFS plugin", "magic at {0} = 0x{1:X8} (expected 0x{2:X8})", location,
                                               xfsSb.magicnum, XFS_MAGIC);

                    if (xfsSb.magicnum == XFS_MAGIC)
                    {
                        break;
                    }
                }
            }

            if (xfsSb.magicnum != XFS_MAGIC)
            {
                return;
            }

            var sb = new StringBuilder();

            sb.AppendLine("XFS filesystem");
            sb.AppendFormat("Filesystem version {0}", xfsSb.version & 0xF).AppendLine();
            sb.AppendFormat("{0} bytes per sector", xfsSb.sectsize).AppendLine();
            sb.AppendFormat("{0} bytes per block", xfsSb.blocksize).AppendLine();
            sb.AppendFormat("{0} bytes per inode", xfsSb.inodesize).AppendLine();
            sb.AppendFormat("{0} data blocks in volume, {1} free", xfsSb.dblocks, xfsSb.fdblocks).AppendLine();
            sb.AppendFormat("{0} blocks per allocation group", xfsSb.agblocks).AppendLine();
            sb.AppendFormat("{0} allocation groups in volume", xfsSb.agcount).AppendLine();
            sb.AppendFormat("{0} inodes in volume, {1} free", xfsSb.icount, xfsSb.ifree).AppendLine();

            if (xfsSb.inprogress > 0)
            {
                sb.AppendLine("fsck in progress");
            }

            sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(xfsSb.fname, Encoding)).AppendLine();
            sb.AppendFormat("Volume UUID: {0}", xfsSb.uuid).AppendLine();

            information = sb.ToString();

            XmlFsType = new FileSystemType
            {
                Type                  = "XFS filesystem",
                ClusterSize           = xfsSb.blocksize,
                Clusters              = xfsSb.dblocks,
                FreeClusters          = xfsSb.fdblocks,
                FreeClustersSpecified = true,
                Files                 = xfsSb.icount - xfsSb.ifree,
                FilesSpecified        = true,
                Dirty                 = xfsSb.inprogress > 0,
                VolumeName            = StringHandlers.CToString(xfsSb.fname, Encoding),
                VolumeSerial          = xfsSb.uuid.ToString()
            };
        }
예제 #19
0
파일: AppleSingle.cs 프로젝트: paulyc/Aaru
        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;
        }
예제 #20
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;
        }
예제 #21
0
        public bool Identify(IMediaImage imagePlugin, Partition partition)
        {
            if (imagePlugin.Info.SectorSize < 512)
            {
                return(false);
            }

            // Misaligned
            if (imagePlugin.Info.XmlMediaType == XmlMediaType.OpticalDisc)
            {
                uint sbSize = (uint)((Marshal.SizeOf <Superblock>() + 0x400) / imagePlugin.Info.SectorSize);

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

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

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

                byte[] sbpiece = new byte[Marshal.SizeOf <Superblock>()];

                foreach (int location in new[]
                {
                    0, 0x200, 0x400
                })
                {
                    Array.Copy(sector, location, sbpiece, 0, Marshal.SizeOf <Superblock>());

                    Superblock xfsSb = Marshal.ByteArrayToStructureBigEndian <Superblock>(sbpiece);

                    AaruConsole.DebugWriteLine("XFS plugin", "magic at 0x{0:X3} = 0x{1:X8} (expected 0x{2:X8})",
                                               location, xfsSb.magicnum, XFS_MAGIC);

                    if (xfsSb.magicnum == XFS_MAGIC)
                    {
                        return(true);
                    }
                }
            }
            else
            {
                foreach (int i in new[]
                {
                    0, 1, 2
                })
                {
                    ulong location = (ulong)i;

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

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

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

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

                    Superblock xfsSb = Marshal.ByteArrayToStructureBigEndian <Superblock>(sector);

                    AaruConsole.DebugWriteLine("XFS plugin", "magic at {0} = 0x{1:X8} (expected 0x{2:X8})", location,
                                               xfsSb.magicnum, XFS_MAGIC);

                    if (xfsSb.magicnum == XFS_MAGIC)
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
예제 #22
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            Encoding    = Encoding.BigEndianUnicode;
            information = "";

            var vh = new VolumeHeader();

            ulong hfspOffset;
            bool  wrapped;

            uint sectorsToRead = 0x800 / imagePlugin.Info.SectorSize;

            if (0x800 % imagePlugin.Info.SectorSize > 0)
            {
                sectorsToRead++;
            }

            byte[] vhSector = imagePlugin.ReadSectors(partition.Start, sectorsToRead);

            ushort drSigWord = BigEndianBitConverter.ToUInt16(vhSector, 0x400);

            if (drSigWord == AppleCommon.HFS_MAGIC)                          // "BD"
            {
                drSigWord = BigEndianBitConverter.ToUInt16(vhSector, 0x47C); // Read embedded HFS+ signature

                if (drSigWord == AppleCommon.HFSP_MAGIC)                     // "H+"
                {
                    ushort xdrStABNt = BigEndianBitConverter.ToUInt16(vhSector, 0x47E);

                    uint drAlBlkSiz = BigEndianBitConverter.ToUInt32(vhSector, 0x414);

                    ushort drAlBlSt = BigEndianBitConverter.ToUInt16(vhSector, 0x41C);

                    hfspOffset = (ulong)(((drAlBlSt * 512) + (xdrStABNt * drAlBlkSiz)) / imagePlugin.Info.SectorSize);
                    wrapped    = true;
                }
                else
                {
                    hfspOffset = 0;
                    wrapped    = false;
                }
            }
            else
            {
                hfspOffset = 0;
                wrapped    = false;
            }

            vhSector = imagePlugin.ReadSectors(partition.Start + hfspOffset, sectorsToRead); // Read volume header

            vh.signature = BigEndianBitConverter.ToUInt16(vhSector, 0x400);

            if (vh.signature != AppleCommon.HFSP_MAGIC &&
                vh.signature != AppleCommon.HFSX_MAGIC)
            {
                return;
            }

            var sb = new StringBuilder();

            if (vh.signature == 0x482B)
            {
                sb.AppendLine("HFS+ filesystem.");
            }

            if (vh.signature == 0x4858)
            {
                sb.AppendLine("HFSX filesystem.");
            }

            if (wrapped)
            {
                sb.AppendLine("Volume is wrapped inside an HFS volume.");
            }

            byte[] tmp = new byte[0x400];
            Array.Copy(vhSector, 0x400, tmp, 0, 0x400);
            vhSector = tmp;

            vh = Marshal.ByteArrayToStructureBigEndian <VolumeHeader>(vhSector);

            if (vh.version == 4 ||
                vh.version == 5)
            {
                sb.AppendFormat("Filesystem version is {0}.", vh.version).AppendLine();

                if ((vh.attributes & 0x80) == 0x80)
                {
                    sb.AppendLine("Volume is locked on hardware.");
                }

                if ((vh.attributes & 0x100) == 0x100)
                {
                    sb.AppendLine("Volume is unmounted.");
                }

                if ((vh.attributes & 0x200) == 0x200)
                {
                    sb.AppendLine("There are bad blocks in the extents file.");
                }

                if ((vh.attributes & 0x400) == 0x400)
                {
                    sb.AppendLine("Volume does not require cache.");
                }

                if ((vh.attributes & 0x800) == 0x800)
                {
                    sb.AppendLine("Volume state is inconsistent.");
                }

                if ((vh.attributes & 0x1000) == 0x1000)
                {
                    sb.AppendLine("CNIDs are reused.");
                }

                if ((vh.attributes & 0x2000) == 0x2000)
                {
                    sb.AppendLine("Volume is journaled.");
                }

                if ((vh.attributes & 0x8000) == 0x8000)
                {
                    sb.AppendLine("Volume is locked on software.");
                }

                sb.AppendFormat("Implementation that last mounted the volume: \"{0}\".",
                                Encoding.ASCII.GetString(vh.lastMountedVersion)).AppendLine();

                if ((vh.attributes & 0x2000) == 0x2000)
                {
                    sb.AppendFormat("Journal starts at allocation block {0}.", vh.journalInfoBlock).AppendLine();
                }

                sb.AppendFormat("Creation date: {0}", DateHandlers.MacToDateTime(vh.createDate)).AppendLine();
                sb.AppendFormat("Last modification date: {0}", DateHandlers.MacToDateTime(vh.modifyDate)).AppendLine();

                if (vh.backupDate > 0)
                {
                    sb.AppendFormat("Last backup date: {0}", DateHandlers.MacToDateTime(vh.backupDate)).AppendLine();
                }
                else
                {
                    sb.AppendLine("Volume has never been backed up");
                }

                if (vh.backupDate > 0)
                {
                    sb.AppendFormat("Last check date: {0}", DateHandlers.MacToDateTime(vh.checkedDate)).AppendLine();
                }
                else
                {
                    sb.AppendLine("Volume has never been checked up");
                }

                sb.AppendFormat("{0} files on volume.", vh.fileCount).AppendLine();
                sb.AppendFormat("{0} folders on volume.", vh.folderCount).AppendLine();
                sb.AppendFormat("{0} bytes per allocation block.", vh.blockSize).AppendLine();
                sb.AppendFormat("{0} allocation blocks.", vh.totalBlocks).AppendLine();
                sb.AppendFormat("{0} free blocks.", vh.freeBlocks).AppendLine();
                sb.AppendFormat("Next allocation block: {0}.", vh.nextAllocation).AppendLine();
                sb.AppendFormat("Resource fork clump size: {0} bytes.", vh.rsrcClumpSize).AppendLine();
                sb.AppendFormat("Data fork clump size: {0} bytes.", vh.dataClumpSize).AppendLine();
                sb.AppendFormat("Next unused CNID: {0}.", vh.nextCatalogID).AppendLine();
                sb.AppendFormat("Volume has been mounted writable {0} times.", vh.writeCount).AppendLine();
                sb.AppendFormat("Allocation File is {0} bytes.", vh.allocationFile_logicalSize).AppendLine();
                sb.AppendFormat("Extents File is {0} bytes.", vh.extentsFile_logicalSize).AppendLine();
                sb.AppendFormat("Catalog File is {0} bytes.", vh.catalogFile_logicalSize).AppendLine();
                sb.AppendFormat("Attributes File is {0} bytes.", vh.attributesFile_logicalSize).AppendLine();
                sb.AppendFormat("Startup File is {0} bytes.", vh.startupFile_logicalSize).AppendLine();
                sb.AppendLine("Finder info:");
                sb.AppendFormat("CNID of bootable system's directory: {0}", vh.drFndrInfo0).AppendLine();
                sb.AppendFormat("CNID of first-run application's directory: {0}", vh.drFndrInfo1).AppendLine();
                sb.AppendFormat("CNID of previously opened directory: {0}", vh.drFndrInfo2).AppendLine();
                sb.AppendFormat("CNID of bootable Mac OS 8 or 9 directory: {0}", vh.drFndrInfo3).AppendLine();
                sb.AppendFormat("CNID of bootable Mac OS X directory: {0}", vh.drFndrInfo5).AppendLine();

                if (vh.drFndrInfo6 != 0 &&
                    vh.drFndrInfo7 != 0)
                {
                    sb.AppendFormat("Mac OS X Volume ID: {0:X8}{1:X8}", vh.drFndrInfo6, vh.drFndrInfo7).AppendLine();
                }

                XmlFsType = new FileSystemType();

                if (vh.backupDate > 0)
                {
                    XmlFsType.BackupDate          = DateHandlers.MacToDateTime(vh.backupDate);
                    XmlFsType.BackupDateSpecified = true;
                }

                XmlFsType.Bootable   |= vh.drFndrInfo0 != 0 || vh.drFndrInfo3 != 0 || vh.drFndrInfo5 != 0;
                XmlFsType.Clusters    = vh.totalBlocks;
                XmlFsType.ClusterSize = vh.blockSize;

                if (vh.createDate > 0)
                {
                    XmlFsType.CreationDate          = DateHandlers.MacToDateTime(vh.createDate);
                    XmlFsType.CreationDateSpecified = true;
                }

                XmlFsType.Dirty                 = (vh.attributes & 0x100) != 0x100;
                XmlFsType.Files                 = vh.fileCount;
                XmlFsType.FilesSpecified        = true;
                XmlFsType.FreeClusters          = vh.freeBlocks;
                XmlFsType.FreeClustersSpecified = true;

                if (vh.modifyDate > 0)
                {
                    XmlFsType.ModificationDate          = DateHandlers.MacToDateTime(vh.modifyDate);
                    XmlFsType.ModificationDateSpecified = true;
                }

                if (vh.signature == 0x482B)
                {
                    XmlFsType.Type = "HFS+";
                }

                if (vh.signature == 0x4858)
                {
                    XmlFsType.Type = "HFSX";
                }

                if (vh.drFndrInfo6 != 0 &&
                    vh.drFndrInfo7 != 0)
                {
                    XmlFsType.VolumeSerial = $"{vh.drFndrInfo6:X8}{vh.drFndrInfo7:X8}";
                }

                XmlFsType.SystemIdentifier = Encoding.ASCII.GetString(vh.lastMountedVersion);
            }
            else
            {
                sb.AppendFormat("Filesystem version is {0}.", vh.version).AppendLine();
                sb.AppendLine("This version is not supported yet.");
            }

            information = sb.ToString();
        }
예제 #23
0
        public bool Identify(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)
            {
                return(false);
            }

            // 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))
                    {
                        return(true);
                    }
                }
            }

            // 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))
                    {
                        return(true);
                    }
                }
            }

            // 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))
                    {
                        return(true);
                    }
                }
            }

            // 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))
                    {
                        return(true);
                    }
                }
            }

            // 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))
                    {
                        return(true);
                    }
                }
            }

            // 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))
                    {
                        return(true);
                    }
                }
            }

            // 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))
                    {
                        return(true);
                    }
                }
            }

            // Check AppleDouble created by UnAr (from The Unarchiver)
            if (!File.Exists(unArAppleDouble))
            {
                return(false);
            }

            var unarStream = new FileStream(unArAppleDouble, FileMode.Open, FileAccess.Read);

            if (unarStream.Length <= 26)
            {
                return(false);
            }

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

            return(_header.magic == MAGIC && (_header.version == VERSION || _header.version == VERSION2));
        }
예제 #24
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            Encoding    = encoding ?? Encoding.GetEncoding("iso-8859-15");
            information = "";
            var 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);

            SuperBlock sb = Marshal.ByteArrayToStructureLittleEndian <SuperBlock>(ufs_sb_sectors);

            SuperBlock bs_sfu = Marshal.ByteArrayToStructureBigEndian <SuperBlock>(ufs_sb_sectors);

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

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

            if (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 (sb.fs_link > 0)
                {
                    fs_type_42bsd = true; // It was used in 4.2BSD
                    fs_type_43bsd = false;
                }

                if ((sb.fs_maxfilesize & 0xFFFFFFFF) > SunOSEpoch &&
                    DateHandlers.UnixUnsignedToDateTime(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 (sb.fs_old_npsect > SunOSEpoch &&
                    DateHandlers.UnixToDateTime(sb.fs_old_npsect) < DateTime.Now)
                {
                    fs_type_42bsd = false;
                    fs_type_sun86 = true;
                    fs_type_sun   = false;
                    fs_type_43bsd = false;
                }

                if (sb.fs_cgrotor > 0x00000000 &&
                    (uint)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 &= sb.fs_id_2 == 0 && sb.fs_id_1 == 0;

                // This is the only 4.4BSD inode format
                fs_type_44bsd |= 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}", sb.fs_link).AppendLine();
            }

            sbInformation.AppendFormat("Superblock LBA: {0}", sb.fs_sblkno).AppendLine();
            sbInformation.AppendFormat("Cylinder-block LBA: {0}", sb.fs_cblkno).AppendLine();
            sbInformation.AppendFormat("inode-block LBA: {0}", sb.fs_iblkno).AppendLine();
            sbInformation.AppendFormat("First data block LBA: {0}", sb.fs_dblkno).AppendLine();
            sbInformation.AppendFormat("Cylinder group offset in cylinder: {0}", sb.fs_old_cgoffset).AppendLine();

            sbInformation.AppendFormat("Volume last written on {0}", DateHandlers.UnixToDateTime(sb.fs_old_time)).
            AppendLine();

            XmlFsType.ModificationDate          = DateHandlers.UnixToDateTime(sb.fs_old_time);
            XmlFsType.ModificationDateSpecified = true;

            sbInformation.AppendFormat("{0} blocks in volume ({1} bytes)", sb.fs_old_size,
                                       (long)sb.fs_old_size * sb.fs_fsize).AppendLine();

            XmlFsType.Clusters    = (ulong)sb.fs_old_size;
            XmlFsType.ClusterSize = (uint)sb.fs_fsize;

            sbInformation.AppendFormat("{0} data blocks in volume ({1} bytes)", sb.fs_old_dsize,
                                       (long)sb.fs_old_dsize * sb.fs_fsize).AppendLine();

            sbInformation.AppendFormat("{0} cylinder groups in volume", sb.fs_ncg).AppendLine();
            sbInformation.AppendFormat("{0} bytes in a basic block", sb.fs_bsize).AppendLine();
            sbInformation.AppendFormat("{0} bytes in a frag block", sb.fs_fsize).AppendLine();
            sbInformation.AppendFormat("{0} frags in a block", sb.fs_frag).AppendLine();
            sbInformation.AppendFormat("{0}% of blocks must be free", sb.fs_minfree).AppendLine();
            sbInformation.AppendFormat("{0}ms for optimal next block", sb.fs_old_rotdelay).AppendLine();

            sbInformation.AppendFormat("disk rotates {0} times per second ({1}rpm)", sb.fs_old_rps, sb.fs_old_rps * 60).
            AppendLine();

            /*          sbInformation.AppendFormat("fs_bmask: 0x{0:X8}", sb.fs_bmask).AppendLine();
             *          sbInformation.AppendFormat("fs_fmask: 0x{0:X8}", sb.fs_fmask).AppendLine();
             *          sbInformation.AppendFormat("fs_bshift: 0x{0:X8}", sb.fs_bshift).AppendLine();
             *          sbInformation.AppendFormat("fs_fshift: 0x{0:X8}", sb.fs_fshift).AppendLine();*/
            sbInformation.AppendFormat("{0} contiguous blocks at maximum", sb.fs_maxcontig).AppendLine();
            sbInformation.AppendFormat("{0} blocks per cylinder group at maximum", sb.fs_maxbpg).AppendLine();
            sbInformation.AppendFormat("Superblock is {0} bytes", sb.fs_sbsize).AppendLine();
            sbInformation.AppendFormat("NINDIR: 0x{0:X8}", sb.fs_nindir).AppendLine();
            sbInformation.AppendFormat("INOPB: 0x{0:X8}", sb.fs_inopb).AppendLine();
            sbInformation.AppendFormat("NSPF: 0x{0:X8}", sb.fs_old_nspf).AppendLine();

            switch (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}", sb.fs_optim).AppendLine();

                break;
            }

            if (fs_type_sun)
            {
                sbInformation.AppendFormat("{0} sectors/track", sb.fs_old_npsect).AppendLine();
            }
            else if (fs_type_sun86)
            {
                sbInformation.AppendFormat("Volume state on {0}", DateHandlers.UnixToDateTime(sb.fs_old_npsect)).
                AppendLine();
            }

            sbInformation.AppendFormat("Hardware sector interleave: {0}", sb.fs_old_interleave).AppendLine();
            sbInformation.AppendFormat("Sector 0 skew: {0}/track", sb.fs_old_trackskew).AppendLine();

            if (!fs_type_43bsd &&
                sb.fs_id_1 > 0 &&
                sb.fs_id_2 > 0)
            {
                sbInformation.AppendFormat("Volume ID: 0x{0:X8}{1:X8}", sb.fs_id_1, sb.fs_id_2).AppendLine();
            }
            else if (fs_type_43bsd &&
                     sb.fs_id_1 > 0 &&
                     sb.fs_id_2 > 0)
            {
                sbInformation.AppendFormat("{0} µsec for head switch", sb.fs_id_1).AppendLine();
                sbInformation.AppendFormat("{0} µsec for track-to-track seek", sb.fs_id_2).AppendLine();
            }

            sbInformation.AppendFormat("Cylinder group summary LBA: {0}", sb.fs_old_csaddr).AppendLine();
            sbInformation.AppendFormat("{0} bytes in cylinder group summary", sb.fs_cssize).AppendLine();
            sbInformation.AppendFormat("{0} bytes in cylinder group", sb.fs_cgsize).AppendLine();
            sbInformation.AppendFormat("{0} tracks/cylinder", sb.fs_old_ntrak).AppendLine();
            sbInformation.AppendFormat("{0} sectors/track", sb.fs_old_nsect).AppendLine();
            sbInformation.AppendFormat("{0} sectors/cylinder", sb.fs_old_spc).AppendLine();
            sbInformation.AppendFormat("{0} cylinder in volume", sb.fs_old_ncyl).AppendLine();
            sbInformation.AppendFormat("{0} cylinders/group", sb.fs_old_cpg).AppendLine();
            sbInformation.AppendFormat("{0} inodes per cylinder group", sb.fs_ipg).AppendLine();
            sbInformation.AppendFormat("{0} blocks per group", sb.fs_fpg / sb.fs_frag).AppendLine();
            sbInformation.AppendFormat("{0} directories", sb.fs_old_cstotal.cs_ndir).AppendLine();

            sbInformation.AppendFormat("{0} free blocks ({1} bytes)", sb.fs_old_cstotal.cs_nbfree,
                                       (long)sb.fs_old_cstotal.cs_nbfree * sb.fs_fsize).AppendLine();

            XmlFsType.FreeClusters          = (ulong)sb.fs_old_cstotal.cs_nbfree;
            XmlFsType.FreeClustersSpecified = true;
            sbInformation.AppendFormat("{0} free inodes", sb.fs_old_cstotal.cs_nifree).AppendLine();
            sbInformation.AppendFormat("{0} free frags", sb.fs_old_cstotal.cs_nffree).AppendLine();

            if (sb.fs_fmod == 1)
            {
                sbInformation.AppendLine("Superblock is under modification");
                XmlFsType.Dirty = true;
            }

            if (sb.fs_clean == 1)
            {
                sbInformation.AppendLine("Volume is clean");
            }

            if (sb.fs_ronly == 1)
            {
                sbInformation.AppendLine("Volume is read-only");
            }

            sbInformation.AppendFormat("Volume flags: 0x{0:X2}", sb.fs_flags).AppendLine();

            if (fs_type_ufs)
            {
                sbInformation.AppendFormat("Volume last mounted on \"{0}\"", StringHandlers.CToString(sb.fs_fsmnt)).
                AppendLine();
            }
            else if (fs_type_ufs2)
            {
                sbInformation.AppendFormat("Volume last mounted on \"{0}\"", StringHandlers.CToString(sb.fs_fsmnt)).
                AppendLine();

                sbInformation.AppendFormat("Volume name: \"{0}\"", StringHandlers.CToString(sb.fs_volname)).
                AppendLine();

                XmlFsType.VolumeName = StringHandlers.CToString(sb.fs_volname);
                sbInformation.AppendFormat("Volume ID: 0x{0:X16}", sb.fs_swuid).AppendLine();

                //xmlFSType.VolumeSerial = string.Format("{0:X16}", sb.fs_swuid);
                sbInformation.AppendFormat("Last searched cylinder group: {0}", sb.fs_cgrotor).AppendLine();
                sbInformation.AppendFormat("{0} contiguously allocated directories", sb.fs_contigdirs).AppendLine();
                sbInformation.AppendFormat("Standard superblock LBA: {0}", sb.fs_sblkno).AppendLine();
                sbInformation.AppendFormat("{0} directories", sb.fs_cstotal.cs_ndir).AppendLine();

                sbInformation.AppendFormat("{0} free blocks ({1} bytes)", sb.fs_cstotal.cs_nbfree,
                                           sb.fs_cstotal.cs_nbfree * sb.fs_fsize).AppendLine();

                XmlFsType.FreeClusters          = (ulong)sb.fs_cstotal.cs_nbfree;
                XmlFsType.FreeClustersSpecified = true;
                sbInformation.AppendFormat("{0} free inodes", sb.fs_cstotal.cs_nifree).AppendLine();
                sbInformation.AppendFormat("{0} free frags", sb.fs_cstotal.cs_nffree).AppendLine();
                sbInformation.AppendFormat("{0} free clusters", sb.fs_cstotal.cs_numclusters).AppendLine();

                sbInformation.AppendFormat("Volume last written on {0}", DateHandlers.UnixToDateTime(sb.fs_time)).
                AppendLine();

                XmlFsType.ModificationDate          = DateHandlers.UnixToDateTime(sb.fs_time);
                XmlFsType.ModificationDateSpecified = true;

                sbInformation.AppendFormat("{0} blocks ({1} bytes)", sb.fs_size, sb.fs_size * sb.fs_fsize).AppendLine();

                XmlFsType.Clusters = (ulong)sb.fs_size;

                sbInformation.AppendFormat("{0} data blocks ({1} bytes)", sb.fs_dsize, sb.fs_dsize * sb.fs_fsize).
                AppendLine();

                sbInformation.AppendFormat("Cylinder group summary area LBA: {0}", sb.fs_csaddr).AppendLine();
                sbInformation.AppendFormat("{0} blocks pending of being freed", sb.fs_pendingblocks).AppendLine();
                sbInformation.AppendFormat("{0} inodes pending of being freed", sb.fs_pendinginodes).AppendLine();
            }

            if (fs_type_sun)
            {
                sbInformation.AppendFormat("Volume state on {0}", DateHandlers.UnixToDateTime(sb.fs_old_npsect)).
                AppendLine();
            }
            else if (fs_type_sun86)
            {
                sbInformation.AppendFormat("{0} sectors/track", sb.fs_state).AppendLine();
            }
            else if (fs_type_44bsd)
            {
                sbInformation.AppendFormat("{0} blocks on cluster summary array", sb.fs_contigsumsize).AppendLine();

                sbInformation.AppendFormat("Maximum length of a symbolic link: {0}", sb.fs_maxsymlinklen).AppendLine();

                sbInformation.AppendFormat("A file can be {0} bytes at max", sb.fs_maxfilesize).AppendLine();

                sbInformation.AppendFormat("Volume state on {0}", DateHandlers.UnixToDateTime(sb.fs_state)).
                AppendLine();
            }

            if (sb.fs_old_nrpos > 0)
            {
                sbInformation.AppendFormat("{0} rotational positions", sb.fs_old_nrpos).AppendLine();
            }

            if (sb.fs_old_rotbloff > 0)
            {
                sbInformation.AppendFormat("{0} blocks per rotation", sb.fs_old_rotbloff).AppendLine();
            }

            information = sbInformation.ToString();
        }
예제 #25
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();

            SuperBlock superBlock;

            uint run = HAMMER_VOLHDR_SIZE / imagePlugin.Info.SectorSize;

            if (HAMMER_VOLHDR_SIZE % imagePlugin.Info.SectorSize > 0)
            {
                run++;
            }

            byte[] sbSector = imagePlugin.ReadSectors(partition.Start, run);

            ulong magic = BitConverter.ToUInt64(sbSector, 0);

            superBlock = magic == HAMMER_FSBUF_VOLUME?Marshal.ByteArrayToStructureLittleEndian <SuperBlock>(sbSector)
                             : Marshal.ByteArrayToStructureBigEndian <SuperBlock>(sbSector);

            sb.AppendLine("HAMMER filesystem");

            sb.AppendFormat("Volume version: {0}", superBlock.vol_version).AppendLine();

            sb.AppendFormat("Volume {0} of {1} on this filesystem", superBlock.vol_no + 1, superBlock.vol_count).
            AppendLine();

            sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(superBlock.vol_label, Encoding)).AppendLine();
            sb.AppendFormat("Volume serial: {0}", superBlock.vol_fsid).AppendLine();
            sb.AppendFormat("Filesystem type: {0}", superBlock.vol_fstype).AppendLine();
            sb.AppendFormat("Boot area starts at {0}", superBlock.vol_bot_beg).AppendLine();
            sb.AppendFormat("Memory log starts at {0}", superBlock.vol_mem_beg).AppendLine();
            sb.AppendFormat("First volume buffer starts at {0}", superBlock.vol_buf_beg).AppendLine();
            sb.AppendFormat("Volume ends at {0}", superBlock.vol_buf_end).AppendLine();

            XmlFsType = new FileSystemType
            {
                Clusters     = partition.Size / HAMMER_BIGBLOCK_SIZE,
                ClusterSize  = HAMMER_BIGBLOCK_SIZE,
                Dirty        = false,
                Type         = "HAMMER",
                VolumeName   = StringHandlers.CToString(superBlock.vol_label, Encoding),
                VolumeSerial = superBlock.vol_fsid.ToString()
            };

            if (superBlock.vol_no == superBlock.vol_rootvol)
            {
                sb.AppendFormat("Filesystem contains {0} \"big-blocks\" ({1} bytes)", superBlock.vol0_stat_bigblocks,
                                superBlock.vol0_stat_bigblocks * HAMMER_BIGBLOCK_SIZE).AppendLine();

                sb.AppendFormat("Filesystem has {0} \"big-blocks\" free ({1} bytes)",
                                superBlock.vol0_stat_freebigblocks,
                                superBlock.vol0_stat_freebigblocks * HAMMER_BIGBLOCK_SIZE).AppendLine();

                sb.AppendFormat("Filesystem has {0} inode used", superBlock.vol0_stat_inodes).AppendLine();

                XmlFsType.Clusters              = (ulong)superBlock.vol0_stat_bigblocks;
                XmlFsType.FreeClusters          = (ulong)superBlock.vol0_stat_freebigblocks;
                XmlFsType.FreeClustersSpecified = true;
                XmlFsType.Files          = (ulong)superBlock.vol0_stat_inodes;
                XmlFsType.FilesSpecified = true;
            }

            // 0 ?
            //sb.AppendFormat("Volume header CRC: 0x{0:X8}", afs_sb.vol_crc).AppendLine();

            information = sb.ToString();
        }
예제 #26
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;
            }

            var locusSb = new Superblock();

            byte[] sector = null;

            for (ulong location = 0; location <= 8; location++)
            {
                uint sbSize = (uint)(Marshal.SizeOf <Superblock>() / imagePlugin.Info.SectorSize);

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

                sector = imagePlugin.ReadSectors(partition.Start + location, sbSize);

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

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

                if (locusSb.s_magic == LOCUS_MAGIC ||
                    locusSb.s_magic == LOCUS_CIGAM ||
                    locusSb.s_magic == LOCUS_MAGIC_OLD ||
                    locusSb.s_magic == LOCUS_CIGAM_OLD)
                {
                    break;
                }
            }

            // We don't care about old version for information
            if (locusSb.s_magic != LOCUS_MAGIC &&
                locusSb.s_magic != LOCUS_CIGAM &&
                locusSb.s_magic != LOCUS_MAGIC_OLD &&
                locusSb.s_magic != LOCUS_CIGAM_OLD)
            {
                return;
            }

            // Numerical arrays are not important for information so no need to swap them
            if (locusSb.s_magic == LOCUS_CIGAM ||
                locusSb.s_magic == LOCUS_CIGAM_OLD)
            {
                locusSb         = Marshal.ByteArrayToStructureBigEndian <Superblock>(sector);
                locusSb.s_flags = (Flags)Swapping.Swap((ushort)locusSb.s_flags);
            }

            var sb = new StringBuilder();

            sb.AppendLine(locusSb.s_magic == LOCUS_MAGIC_OLD ? "Locus filesystem (old)" : "Locus filesystem");

            int blockSize = locusSb.s_version == Version.SB_SB4096 ? 4096 : 1024;

            string s_fsmnt = StringHandlers.CToString(locusSb.s_fsmnt, Encoding);
            string s_fpack = StringHandlers.CToString(locusSb.s_fpack, Encoding);

            AaruConsole.DebugWriteLine("Locus plugin", "LocusSb.s_magic = 0x{0:X8}", locusSb.s_magic);
            AaruConsole.DebugWriteLine("Locus plugin", "LocusSb.s_gfs = {0}", locusSb.s_gfs);
            AaruConsole.DebugWriteLine("Locus plugin", "LocusSb.s_fsize = {0}", locusSb.s_fsize);
            AaruConsole.DebugWriteLine("Locus plugin", "LocusSb.s_lwm = {0}", locusSb.s_lwm);
            AaruConsole.DebugWriteLine("Locus plugin", "LocusSb.s_hwm = {0}", locusSb.s_hwm);
            AaruConsole.DebugWriteLine("Locus plugin", "LocusSb.s_llst = {0}", locusSb.s_llst);
            AaruConsole.DebugWriteLine("Locus plugin", "LocusSb.s_fstore = {0}", locusSb.s_fstore);
            AaruConsole.DebugWriteLine("Locus plugin", "LocusSb.s_time = {0}", locusSb.s_time);
            AaruConsole.DebugWriteLine("Locus plugin", "LocusSb.s_tfree = {0}", locusSb.s_tfree);
            AaruConsole.DebugWriteLine("Locus plugin", "LocusSb.s_isize = {0}", locusSb.s_isize);
            AaruConsole.DebugWriteLine("Locus plugin", "LocusSb.s_nfree = {0}", locusSb.s_nfree);
            AaruConsole.DebugWriteLine("Locus plugin", "LocusSb.s_flags = {0}", locusSb.s_flags);
            AaruConsole.DebugWriteLine("Locus plugin", "LocusSb.s_tinode = {0}", locusSb.s_tinode);
            AaruConsole.DebugWriteLine("Locus plugin", "LocusSb.s_lasti = {0}", locusSb.s_lasti);
            AaruConsole.DebugWriteLine("Locus plugin", "LocusSb.s_nbehind = {0}", locusSb.s_nbehind);
            AaruConsole.DebugWriteLine("Locus plugin", "LocusSb.s_gfspack = {0}", locusSb.s_gfspack);
            AaruConsole.DebugWriteLine("Locus plugin", "LocusSb.s_ninode = {0}", locusSb.s_ninode);
            AaruConsole.DebugWriteLine("Locus plugin", "LocusSb.s_flock = {0}", locusSb.s_flock);
            AaruConsole.DebugWriteLine("Locus plugin", "LocusSb.s_ilock = {0}", locusSb.s_ilock);
            AaruConsole.DebugWriteLine("Locus plugin", "LocusSb.s_fmod = {0}", locusSb.s_fmod);
            AaruConsole.DebugWriteLine("Locus plugin", "LocusSb.s_version = {0}", locusSb.s_version);

            sb.AppendFormat("Superblock last modified on {0}", DateHandlers.UnixToDateTime(locusSb.s_time)).
            AppendLine();

            sb.AppendFormat("Volume has {0} blocks of {1} bytes each (total {2} bytes)", locusSb.s_fsize, blockSize,
                            locusSb.s_fsize * blockSize).AppendLine();

            sb.AppendFormat("{0} blocks free ({1} bytes)", locusSb.s_tfree, locusSb.s_tfree * blockSize).AppendLine();
            sb.AppendFormat("I-node list uses {0} blocks", locusSb.s_isize).AppendLine();
            sb.AppendFormat("{0} free inodes", locusSb.s_tinode).AppendLine();
            sb.AppendFormat("Next free inode search will start at inode {0}", locusSb.s_lasti).AppendLine();

            sb.AppendFormat("There are an estimate of {0} free inodes before next search start", locusSb.s_nbehind).
            AppendLine();

            if (locusSb.s_flags.HasFlag(Flags.SB_RDONLY))
            {
                sb.AppendLine("Read-only volume");
            }

            if (locusSb.s_flags.HasFlag(Flags.SB_CLEAN))
            {
                sb.AppendLine("Clean volume");
            }

            if (locusSb.s_flags.HasFlag(Flags.SB_DIRTY))
            {
                sb.AppendLine("Dirty volume");
            }

            if (locusSb.s_flags.HasFlag(Flags.SB_RMV))
            {
                sb.AppendLine("Removable volume");
            }

            if (locusSb.s_flags.HasFlag(Flags.SB_PRIMPACK))
            {
                sb.AppendLine("This is the primary pack");
            }

            if (locusSb.s_flags.HasFlag(Flags.SB_REPLTYPE))
            {
                sb.AppendLine("Replicated volume");
            }

            if (locusSb.s_flags.HasFlag(Flags.SB_USER))
            {
                sb.AppendLine("User replicated volume");
            }

            if (locusSb.s_flags.HasFlag(Flags.SB_BACKBONE))
            {
                sb.AppendLine("Backbone volume");
            }

            if (locusSb.s_flags.HasFlag(Flags.SB_NFS))
            {
                sb.AppendLine("NFS volume");
            }

            if (locusSb.s_flags.HasFlag(Flags.SB_BYHAND))
            {
                sb.AppendLine("Volume inhibits automatic fsck");
            }

            if (locusSb.s_flags.HasFlag(Flags.SB_NOSUID))
            {
                sb.AppendLine("Set-uid/set-gid is disabled");
            }

            if (locusSb.s_flags.HasFlag(Flags.SB_SYNCW))
            {
                sb.AppendLine("Volume uses synchronous writes");
            }

            sb.AppendFormat("Volume label: {0}", s_fsmnt).AppendLine();
            sb.AppendFormat("Physical volume name: {0}", s_fpack).AppendLine();
            sb.AppendFormat("Global File System number: {0}", locusSb.s_gfs).AppendLine();
            sb.AppendFormat("Global File System pack number {0}", locusSb.s_gfspack).AppendLine();

            information = sb.ToString();

            XmlFsType = new FileSystemType
            {
                Type        = "Locus filesystem",
                ClusterSize = (uint)blockSize,
                Clusters    = (ulong)locusSb.s_fsize,

                // Sometimes it uses one, or the other. Use the bigger
                VolumeName                = string.IsNullOrEmpty(s_fsmnt) ? s_fpack : s_fsmnt,
                ModificationDate          = DateHandlers.UnixToDateTime(locusSb.s_time),
                ModificationDateSpecified = true,
                Dirty                 = !locusSb.s_flags.HasFlag(Flags.SB_CLEAN) || locusSb.s_flags.HasFlag(Flags.SB_DIRTY),
                FreeClusters          = (ulong)locusSb.s_tfree,
                FreeClustersSpecified = true
            };
        }
예제 #27
0
        public bool Identify(IMediaImage imagePlugin, Partition partition)
        {
            if (partition.Start >= partition.End)
            {
                return(false);
            }

            // Boot block is unless defined otherwise, 2 blocks
            // Funny, you may need boot block to find root block if it's not in standard place just to know size of
            // block size and then read the whole boot block.
            // However while you can set a block size different from the sector size on formatting, the bootblock block
            // size for floppies is the sector size, and for RDB is usually is the hard disk sector size,
            // so this is not entirely wrong...
            byte[]    sector = imagePlugin.ReadSectors(0 + partition.Start, 2);
            BootBlock bblk   = Marshal.ByteArrayToStructureBigEndian <BootBlock>(sector);

            // AROS boot floppies...
            if (sector.Length >= 512 &&
                sector[510] == 0x55 &&
                sector[511] == 0xAA &&
                (bblk.diskType & FFS_MASK) != FFS_MASK &&
                (bblk.diskType & MUFS_MASK) != MUFS_MASK)
            {
                sector = imagePlugin.ReadSectors(1 + partition.Start, 2);
                bblk   = Marshal.ByteArrayToStructureBigEndian <BootBlock>(sector);
            }

            // Not FFS or MuFS?
            if ((bblk.diskType & FFS_MASK) != FFS_MASK &&
                (bblk.diskType & MUFS_MASK) != MUFS_MASK)
            {
                return(false);
            }

            // Clear checksum on sector
            sector[4] = sector[5] = sector[6] = sector[7] = 0;
            uint bsum = AmigaBootChecksum(sector);

            AaruConsole.DebugWriteLine("AmigaDOS plugin", "bblk.checksum = 0x{0:X8}", bblk.checksum);
            AaruConsole.DebugWriteLine("AmigaDOS plugin", "bsum = 0x{0:X8}", bsum);

            ulong bRootPtr = 0;

            // If bootblock is correct, let's take its rootblock pointer
            if (bsum == bblk.checksum)
            {
                bRootPtr = bblk.root_ptr + partition.Start;
                AaruConsole.DebugWriteLine("AmigaDOS plugin", "Bootblock points to {0} as Rootblock", bRootPtr);
            }

            ulong[] rootPtrs =
            {
                bRootPtr + partition.Start,                                            ((((partition.End - partition.Start) + 1) / 2) + partition.Start) - 2,
                ((((partition.End - partition.Start) + 1) / 2) + partition.Start) - 1,
                (((partition.End - partition.Start) + 1) / 2) + partition.Start,
                (((partition.End - partition.Start) + 1) / 2) + partition.Start + 4
            };

            var rblk = new RootBlock();

            // So to handle even number of sectors
            foreach (ulong rootPtr in rootPtrs.Where(rootPtr => rootPtr < partition.End && rootPtr >= partition.Start))
            {
                AaruConsole.DebugWriteLine("AmigaDOS plugin", "Searching for Rootblock in sector {0}", rootPtr);

                sector = imagePlugin.ReadSector(rootPtr);

                rblk.type = BigEndianBitConverter.ToUInt32(sector, 0x00);
                AaruConsole.DebugWriteLine("AmigaDOS plugin", "rblk.type = {0}", rblk.type);

                if (rblk.type != TYPE_HEADER)
                {
                    continue;
                }

                rblk.hashTableSize = BigEndianBitConverter.ToUInt32(sector, 0x0C);

                AaruConsole.DebugWriteLine("AmigaDOS plugin", "rblk.hashTableSize = {0}", rblk.hashTableSize);

                uint blockSize       = (rblk.hashTableSize + 56) * 4;
                uint sectorsPerBlock = (uint)(blockSize / sector.Length);

                AaruConsole.DebugWriteLine("AmigaDOS plugin", "blockSize = {0}", blockSize);
                AaruConsole.DebugWriteLine("AmigaDOS plugin", "sectorsPerBlock = {0}", sectorsPerBlock);

                if (blockSize % sector.Length > 0)
                {
                    sectorsPerBlock++;
                }

                if (rootPtr + sectorsPerBlock >= partition.End)
                {
                    continue;
                }

                sector = imagePlugin.ReadSectors(rootPtr, sectorsPerBlock);

                // Clear checksum on sector
                rblk.checksum = BigEndianBitConverter.ToUInt32(sector, 20);
                sector[20]    = sector[21] = sector[22] = sector[23] = 0;
                uint rsum = AmigaChecksum(sector);

                AaruConsole.DebugWriteLine("AmigaDOS plugin", "rblk.checksum = 0x{0:X8}", rblk.checksum);
                AaruConsole.DebugWriteLine("AmigaDOS plugin", "rsum = 0x{0:X8}", rsum);

                rblk.sec_type = BigEndianBitConverter.ToUInt32(sector, sector.Length - 4);
                AaruConsole.DebugWriteLine("AmigaDOS plugin", "rblk.sec_type = {0}", rblk.sec_type);

                if (rblk.sec_type == SUBTYPE_ROOT &&
                    rblk.checksum == rsum)
                {
                    return(true);
                }
            }

            return(false);
        }
예제 #28
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 sbSize = (uint)(Marshal.SizeOf <Superblock>() / imagePlugin.Info.SectorSize);

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

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

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

            Superblock unicosSb = Marshal.ByteArrayToStructureBigEndian <Superblock>(sector);

            if (unicosSb.s_magic != UNICOS_MAGIC)
            {
                return;
            }

            var sb = new StringBuilder();

            sb.AppendLine("UNICOS filesystem");

            if (unicosSb.s_secure == UNICOS_SECURE)
            {
                sb.AppendLine("Volume is secure");
            }

            sb.AppendFormat("Volume contains {0} partitions", unicosSb.s_npart).AppendLine();
            sb.AppendFormat("{0} bytes per sector", unicosSb.s_iounit).AppendLine();
            sb.AppendLine("4096 bytes per block");
            sb.AppendFormat("{0} data blocks in volume", unicosSb.s_fsize).AppendLine();
            sb.AppendFormat("Root resides on inode {0}", unicosSb.s_root).AppendLine();
            sb.AppendFormat("{0} inodes in volume", unicosSb.s_isize).AppendLine();
            sb.AppendFormat("Volume last updated on {0}", DateHandlers.UnixToDateTime(unicosSb.s_time)).AppendLine();

            if (unicosSb.s_error > 0)
            {
                sb.AppendFormat("Volume is dirty, error code = 0x{0:X16}", unicosSb.s_error).AppendLine();
            }

            sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(unicosSb.s_fname, Encoding)).AppendLine();

            information = sb.ToString();

            XmlFsType = new FileSystemType
            {
                Type                      = "UNICOS filesystem",
                ClusterSize               = 4096,
                Clusters                  = (ulong)unicosSb.s_fsize,
                VolumeName                = StringHandlers.CToString(unicosSb.s_fname, Encoding),
                ModificationDate          = DateHandlers.UnixToDateTime(unicosSb.s_time),
                ModificationDateSpecified = true
            };

            XmlFsType.Dirty |= unicosSb.s_error > 0;
        }
예제 #29
0
파일: dump.cs 프로젝트: morefun0302/Aaru
        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;
            }

            if (partition.Start != 0)
            {
                return;
            }

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

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

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

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

            spcl16   oldHdr = Marshal.ByteArrayToStructureLittleEndian <spcl16>(sector);
            spcl_aix aixHdr = Marshal.ByteArrayToStructureLittleEndian <spcl_aix>(sector);
            s_spcl   newHdr = Marshal.ByteArrayToStructureLittleEndian <s_spcl>(sector);

            bool useOld = false;
            bool useAix = false;

            if (newHdr.c_magic == OFS_MAGIC ||
                newHdr.c_magic == NFS_MAGIC ||
                newHdr.c_magic == OFS_CIGAM ||
                newHdr.c_magic == NFS_CIGAM ||
                newHdr.c_magic == UFS2_MAGIC ||
                newHdr.c_magic == UFS2_CIGAM)
            {
                if (newHdr.c_magic == OFS_CIGAM ||
                    newHdr.c_magic == NFS_CIGAM ||
                    newHdr.c_magic == UFS2_CIGAM)
                {
                    newHdr = Marshal.ByteArrayToStructureBigEndian <s_spcl>(sector);
                }
            }
            else if (aixHdr.c_magic == XIX_MAGIC ||
                     aixHdr.c_magic == XIX_CIGAM)
            {
                useAix = true;

                if (aixHdr.c_magic == XIX_CIGAM)
                {
                    aixHdr = Marshal.ByteArrayToStructureBigEndian <spcl_aix>(sector);
                }
            }
            else if (oldHdr.c_magic == OFS_MAGIC)
            {
                useOld = true;

                // Swap PDP-11 endian
                oldHdr.c_date  = (int)Swapping.PDPFromLittleEndian((uint)oldHdr.c_date);
                oldHdr.c_ddate = (int)Swapping.PDPFromLittleEndian((uint)oldHdr.c_ddate);
            }
            else
            {
                information = "Could not read dump(8) header block";

                return;
            }

            var sb = new StringBuilder();

            XmlFsType = new FileSystemType
            {
                ClusterSize = 1024,
                Clusters    = partition.Size / 1024
            };

            if (useOld)
            {
                XmlFsType.Type = "Old 16-bit dump(8)";
                sb.AppendLine(XmlFsType.Type);

                if (oldHdr.c_date > 0)
                {
                    XmlFsType.CreationDate          = DateHandlers.UnixToDateTime(oldHdr.c_date);
                    XmlFsType.CreationDateSpecified = true;
                    sb.AppendFormat("Dump created on {0}", XmlFsType.CreationDate).AppendLine();
                }

                if (oldHdr.c_ddate > 0)
                {
                    XmlFsType.BackupDate          = DateHandlers.UnixToDateTime(oldHdr.c_ddate);
                    XmlFsType.BackupDateSpecified = true;
                    sb.AppendFormat("Previous dump created on {0}", XmlFsType.BackupDate).AppendLine();
                }

                sb.AppendFormat("Dump volume number: {0}", oldHdr.c_volume).AppendLine();
            }
            else if (useAix)
            {
                XmlFsType.Type = "AIX dump(8)";
                sb.AppendLine(XmlFsType.Type);

                if (aixHdr.c_date > 0)
                {
                    XmlFsType.CreationDate          = DateHandlers.UnixToDateTime(aixHdr.c_date);
                    XmlFsType.CreationDateSpecified = true;
                    sb.AppendFormat("Dump created on {0}", XmlFsType.CreationDate).AppendLine();
                }

                if (aixHdr.c_ddate > 0)
                {
                    XmlFsType.BackupDate          = DateHandlers.UnixToDateTime(aixHdr.c_ddate);
                    XmlFsType.BackupDateSpecified = true;
                    sb.AppendFormat("Previous dump created on {0}", XmlFsType.BackupDate).AppendLine();
                }

                sb.AppendFormat("Dump volume number: {0}", aixHdr.c_volume).AppendLine();
            }
            else
            {
                XmlFsType.Type = "dump(8)";
                sb.AppendLine(XmlFsType.Type);

                if (newHdr.c_ndate > 0)
                {
                    XmlFsType.CreationDate          = DateHandlers.UnixToDateTime(newHdr.c_ndate);
                    XmlFsType.CreationDateSpecified = true;
                    sb.AppendFormat("Dump created on {0}", XmlFsType.CreationDate).AppendLine();
                }
                else if (newHdr.c_date > 0)
                {
                    XmlFsType.CreationDate          = DateHandlers.UnixToDateTime(newHdr.c_date);
                    XmlFsType.CreationDateSpecified = true;
                    sb.AppendFormat("Dump created on {0}", XmlFsType.CreationDate).AppendLine();
                }

                if (newHdr.c_nddate > 0)
                {
                    XmlFsType.BackupDate          = DateHandlers.UnixToDateTime(newHdr.c_nddate);
                    XmlFsType.BackupDateSpecified = true;
                    sb.AppendFormat("Previous dump created on {0}", XmlFsType.BackupDate).AppendLine();
                }
                else if (newHdr.c_ddate > 0)
                {
                    XmlFsType.BackupDate          = DateHandlers.UnixToDateTime(newHdr.c_ddate);
                    XmlFsType.BackupDateSpecified = true;
                    sb.AppendFormat("Previous dump created on {0}", XmlFsType.BackupDate).AppendLine();
                }

                sb.AppendFormat("Dump volume number: {0}", newHdr.c_volume).AppendLine();
                sb.AppendFormat("Dump level: {0}", newHdr.c_level).AppendLine();
                string dumpname = StringHandlers.CToString(newHdr.c_label);

                if (!string.IsNullOrEmpty(dumpname))
                {
                    XmlFsType.VolumeName = dumpname;
                    sb.AppendFormat("Dump label: {0}", dumpname).AppendLine();
                }

                string str = StringHandlers.CToString(newHdr.c_filesys);

                if (!string.IsNullOrEmpty(str))
                {
                    sb.AppendFormat("Dumped filesystem name: {0}", str).AppendLine();
                }

                str = StringHandlers.CToString(newHdr.c_dev);

                if (!string.IsNullOrEmpty(str))
                {
                    sb.AppendFormat("Dumped device: {0}", str).AppendLine();
                }

                str = StringHandlers.CToString(newHdr.c_host);

                if (!string.IsNullOrEmpty(str))
                {
                    sb.AppendFormat("Dump hostname: {0}", str).AppendLine();
                }
            }

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

            XmlFsType   = new FileSystemType();
            information = null;
            byte[] bootBlockSectors = imagePlugin.ReadSectors(0 + partition.Start, 2);

            BootBlock bootBlk = Marshal.ByteArrayToStructureBigEndian <BootBlock>(bootBlockSectors);

            bootBlk.bootCode = new byte[bootBlockSectors.Length - 12];
            Array.Copy(bootBlockSectors, 12, bootBlk.bootCode, 0, bootBlk.bootCode.Length);
            bootBlockSectors[4] = bootBlockSectors[5] = bootBlockSectors[6] = bootBlockSectors[7] = 0;
            uint bsum = AmigaBootChecksum(bootBlockSectors);

            ulong bRootPtr = 0;

            // If bootblock is correct, let's take its rootblock pointer
            if (bsum == bootBlk.checksum)
            {
                bRootPtr = bootBlk.root_ptr + partition.Start;
                AaruConsole.DebugWriteLine("AmigaDOS plugin", "Bootblock points to {0} as Rootblock", bRootPtr);
            }

            ulong[] rootPtrs =
            {
                bRootPtr + partition.Start,                                            ((((partition.End - partition.Start) + 1) / 2) + partition.Start) - 2,
                ((((partition.End - partition.Start) + 1) / 2) + partition.Start) - 1,
                (((partition.End - partition.Start) + 1) / 2) + partition.Start,
                (((partition.End - partition.Start) + 1) / 2) + partition.Start + 4
            };

            var rootBlk = new RootBlock();

            byte[] rootBlockSector = null;

            bool rootFound = false;
            uint blockSize = 0;

            // So to handle even number of sectors
            foreach (ulong rootPtr in rootPtrs.Where(rootPtr => rootPtr < partition.End && rootPtr >= partition.Start))
            {
                AaruConsole.DebugWriteLine("AmigaDOS plugin", "Searching for Rootblock in sector {0}", rootPtr);

                rootBlockSector = imagePlugin.ReadSector(rootPtr);

                rootBlk.type = BigEndianBitConverter.ToUInt32(rootBlockSector, 0x00);
                AaruConsole.DebugWriteLine("AmigaDOS plugin", "rootBlk.type = {0}", rootBlk.type);

                if (rootBlk.type != TYPE_HEADER)
                {
                    continue;
                }

                rootBlk.hashTableSize = BigEndianBitConverter.ToUInt32(rootBlockSector, 0x0C);

                AaruConsole.DebugWriteLine("AmigaDOS plugin", "rootBlk.hashTableSize = {0}", rootBlk.hashTableSize);

                blockSize = (rootBlk.hashTableSize + 56) * 4;
                uint sectorsPerBlock = (uint)(blockSize / rootBlockSector.Length);

                AaruConsole.DebugWriteLine("AmigaDOS plugin", "blockSize = {0}", blockSize);
                AaruConsole.DebugWriteLine("AmigaDOS plugin", "sectorsPerBlock = {0}", sectorsPerBlock);

                if (blockSize % rootBlockSector.Length > 0)
                {
                    sectorsPerBlock++;
                }

                if (rootPtr + sectorsPerBlock >= partition.End)
                {
                    continue;
                }

                rootBlockSector = imagePlugin.ReadSectors(rootPtr, sectorsPerBlock);

                // Clear checksum on sector
                rootBlk.checksum    = BigEndianBitConverter.ToUInt32(rootBlockSector, 20);
                rootBlockSector[20] = rootBlockSector[21] = rootBlockSector[22] = rootBlockSector[23] = 0;
                uint rsum = AmigaChecksum(rootBlockSector);

                AaruConsole.DebugWriteLine("AmigaDOS plugin", "rootBlk.checksum = 0x{0:X8}", rootBlk.checksum);
                AaruConsole.DebugWriteLine("AmigaDOS plugin", "rsum = 0x{0:X8}", rsum);

                rootBlk.sec_type = BigEndianBitConverter.ToUInt32(rootBlockSector, rootBlockSector.Length - 4);
                AaruConsole.DebugWriteLine("AmigaDOS plugin", "rootBlk.sec_type = {0}", rootBlk.sec_type);

                if (rootBlk.sec_type != SUBTYPE_ROOT ||
                    rootBlk.checksum != rsum)
                {
                    continue;
                }

                rootBlockSector = imagePlugin.ReadSectors(rootPtr, sectorsPerBlock);
                rootFound       = true;

                break;
            }

            if (!rootFound)
            {
                return;
            }

            rootBlk = MarshalRootBlock(rootBlockSector);

            string diskName = StringHandlers.PascalToString(rootBlk.diskName, Encoding);

            switch (bootBlk.diskType & 0xFF)
            {
            case 0:
                sbInformation.Append("Amiga Original File System");
                XmlFsType.Type = "Amiga OFS";

                break;

            case 1:
                sbInformation.Append("Amiga Fast File System");
                XmlFsType.Type = "Amiga FFS";

                break;

            case 2:
                sbInformation.Append("Amiga Original File System with international characters");
                XmlFsType.Type = "Amiga OFS";

                break;

            case 3:
                sbInformation.Append("Amiga Fast File System with international characters");
                XmlFsType.Type = "Amiga FFS";

                break;

            case 4:
                sbInformation.Append("Amiga Original File System with directory cache");
                XmlFsType.Type = "Amiga OFS";

                break;

            case 5:
                sbInformation.Append("Amiga Fast File System with directory cache");
                XmlFsType.Type = "Amiga FFS";

                break;

            case 6:
                sbInformation.Append("Amiga Original File System with long filenames");
                XmlFsType.Type = "Amiga OFS2";

                break;

            case 7:
                sbInformation.Append("Amiga Fast File System with long filenames");
                XmlFsType.Type = "Amiga FFS2";

                break;
            }

            if ((bootBlk.diskType & 0x6D754600) == 0x6D754600)
            {
                sbInformation.Append(", with multi-user patches");
            }

            sbInformation.AppendLine();

            sbInformation.AppendFormat("Volume name: {0}", diskName).AppendLine();

            if (bootBlk.checksum == bsum)
            {
                var sha1Ctx = new Sha1Context();
                sha1Ctx.Update(bootBlk.bootCode);
                sbInformation.AppendLine("Volume is bootable");
                sbInformation.AppendFormat("Boot code SHA1 is {0}", sha1Ctx.End()).AppendLine();
            }

            if (rootBlk.bitmapFlag == 0xFFFFFFFF)
            {
                sbInformation.AppendLine("Volume bitmap is valid");
            }

            if (rootBlk.bitmapExtensionBlock != 0x00000000 &&
                rootBlk.bitmapExtensionBlock != 0xFFFFFFFF)
            {
                sbInformation.AppendFormat("Bitmap extension at block {0}", rootBlk.bitmapExtensionBlock).AppendLine();
            }

            if ((bootBlk.diskType & 0xFF) == 4 ||
                (bootBlk.diskType & 0xFF) == 5)
            {
                sbInformation.AppendFormat("Directory cache starts at block {0}", rootBlk.extension).AppendLine();
            }

            ulong blocks = (((partition.End - partition.Start) + 1) * imagePlugin.Info.SectorSize) / blockSize;

            sbInformation.AppendFormat("Volume block size is {0} bytes", blockSize).AppendLine();
            sbInformation.AppendFormat("Volume has {0} blocks", blocks).AppendLine();

            sbInformation.AppendFormat("Volume created on {0}",
                                       DateHandlers.AmigaToDateTime(rootBlk.cDays, rootBlk.cMins, rootBlk.cTicks)).
            AppendLine();

            sbInformation.AppendFormat("Volume last modified on {0}",
                                       DateHandlers.AmigaToDateTime(rootBlk.vDays, rootBlk.vMins, rootBlk.vTicks)).
            AppendLine();

            sbInformation.AppendFormat("Volume root directory last modified on on {0}",
                                       DateHandlers.AmigaToDateTime(rootBlk.rDays, rootBlk.rMins, rootBlk.rTicks)).
            AppendLine();

            sbInformation.AppendFormat("Root block checksum is 0x{0:X8}", rootBlk.checksum).AppendLine();
            information = sbInformation.ToString();

            XmlFsType.CreationDate = DateHandlers.AmigaToDateTime(rootBlk.cDays, rootBlk.cMins, rootBlk.cTicks);

            XmlFsType.CreationDateSpecified = true;

            XmlFsType.ModificationDate = DateHandlers.AmigaToDateTime(rootBlk.vDays, rootBlk.vMins, rootBlk.vTicks);

            XmlFsType.ModificationDateSpecified = true;
            XmlFsType.Dirty       = rootBlk.bitmapFlag != 0xFFFFFFFF;
            XmlFsType.Clusters    = blocks;
            XmlFsType.ClusterSize = blockSize;
            XmlFsType.VolumeName  = diskName;
            XmlFsType.Bootable    = bsum == bootBlk.checksum;

            // Useful as a serial
            XmlFsType.VolumeSerial = $"{rootBlk.checksum:X8}";
        }