public HttpResponseMessage UploadReport(long timestamp)
        {
            DicServerContext ctx = new DicServerContext();

            SyncDto  sync     = new SyncDto();
            DateTime lastSync = DateHandlers.UnixToDateTime(timestamp);

            sync.UsbVendors = new List <UsbVendorDto>();
            foreach (UsbVendor vendor in ctx.UsbVendors.Where(v => v.ModifiedWhen > lastSync))
            {
                sync.UsbVendors.Add(new UsbVendorDto {
                    VendorId = (ushort)vendor.VendorId, Vendor = vendor.Vendor
                });
            }

            sync.UsbProducts = new List <UsbProductDto>();
            foreach (UsbProduct product in ctx.UsbProducts.Where(p => p.ModifiedWhen > lastSync))
            {
                sync.UsbProducts.Add(new UsbProductDto
                {
                    Id        = product.Id,
                    Product   = product.Product,
                    ProductId = (ushort)product.ProductId,
                    VendorId  = (ushort)product.Vendor.VendorId
                });
            }

            sync.Offsets = new List <CdOffsetDto>();
            foreach (CompactDiscOffset offset in ctx.CdOffsets.Where(o => o.ModifiedWhen > lastSync))
            {
                sync.Offsets.Add(new CdOffsetDto(offset, offset.Id));
            }

            sync.Devices = new List <DeviceDto>();
            foreach (Device device in ctx.Devices.Where(d => d.ModifiedWhen > lastSync).ToList())
            {
                sync.Devices.Add(new
                                 DeviceDto(JsonConvert.DeserializeObject <DeviceReportV2>(JsonConvert.SerializeObject(device, Formatting.None, new JsonSerializerSettings {
                    ReferenceLoopHandling = ReferenceLoopHandling.Ignore
                })),
                                           device.Id, device.OptimalMultipleSectorsRead));
            }

            JsonSerializer js = JsonSerializer.Create();
            StringWriter   sw = new StringWriter();

            js.Serialize(sw, sync);

            return(new HttpResponseMessage
            {
                StatusCode = HttpStatusCode.OK,
                Content = new StringContent(sw.ToString(), Encoding.UTF8, "application/json")
            });
        }
Пример #2
0
        public bool GetInformation(IMediaImage imagePlugin, out List <Partition> partitions, ulong sectorOffset)
        {
            partitions = new List <Partition>();

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

            if (sectorOffset + 2 >= imagePlugin.Info.Sectors)
            {
                return(false);
            }

            bool useDkl = false, useDkl8 = false, useDkl16 = false;

            byte[] sunSector = imagePlugin.ReadSector(sectorOffset);

            dk_label   dkl   = Marshal.ByteArrayToStructureLittleEndian <dk_label>(sunSector);
            dk_label8  dkl8  = Marshal.ByteArrayToStructureLittleEndian <dk_label8>(sunSector);
            dk_label16 dkl16 = Marshal.ByteArrayToStructureLittleEndian <dk_label16>(sunSector);

            DicConsole.DebugWriteLine("Sun plugin", "dkl.dkl_magic = 0x{0:X4}", dkl.dkl_magic);
            DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_vtoc.v_sanity = 0x{0:X8}", dkl8.dkl_vtoc.v_sanity);
            DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_vtoc.v_sanity = 0x{0:X8}", dkl16.dkl_vtoc.v_sanity);

            if (dkl.dkl_magic == DKL_MAGIC || dkl.dkl_magic == DKL_CIGAM)
            {
                if (dkl16.dkl_vtoc.v_sanity == VTOC_SANE || dkl16.dkl_vtoc.v_sanity == VTOC_ENAS)
                {
                    useDkl16 = true;
                }
                else if (dkl8.dkl_vtoc.v_sanity == VTOC_SANE || dkl8.dkl_vtoc.v_sanity == VTOC_ENAS)
                {
                    useDkl8 = true;
                }
                else
                {
                    useDkl = true;
                }
            }

            if (!useDkl && !useDkl8 && !useDkl16)
            {
                sunSector = imagePlugin.ReadSector(sectorOffset + 1);

                dkl   = Marshal.ByteArrayToStructureLittleEndian <dk_label>(sunSector);
                dkl8  = Marshal.ByteArrayToStructureLittleEndian <dk_label8>(sunSector);
                dkl16 = Marshal.ByteArrayToStructureLittleEndian <dk_label16>(sunSector);

                if (dkl.dkl_magic == DKL_MAGIC || dkl.dkl_magic == DKL_CIGAM)
                {
                    if (dkl16.dkl_vtoc.v_sanity == VTOC_SANE || dkl16.dkl_vtoc.v_sanity == VTOC_ENAS)
                    {
                        useDkl16 = true;
                    }
                    else if (dkl8.dkl_vtoc.v_sanity == VTOC_SANE || dkl8.dkl_vtoc.v_sanity == VTOC_ENAS)
                    {
                        useDkl8 = true;
                    }
                    else
                    {
                        useDkl = true;
                    }
                }
            }

            if (!useDkl && !useDkl8 && !useDkl16)
            {
                return(false);
            }

            if (useDkl16 && dkl16.dkl_magic == DKL_CIGAM)
            {
                dkl16 = SwapDiskLabel(dkl16);
            }
            else if (useDkl8 && dkl8.dkl_magic == DKL_CIGAM)
            {
                dkl8 = SwapDiskLabel(dkl8);
            }
            else if (useDkl && dkl.dkl_magic == DKL_CIGAM)
            {
                dkl = SwapDiskLabel(dkl);
            }

            if (useDkl)
            {
                ulong sectorsPerCylinder = (ulong)(dkl.dkl_nsect * dkl.dkl_nhead);

                DicConsole.DebugWriteLine("Sun plugin", "dkl.dkl_asciilabel = \"{0}\"",
                                          StringHandlers.CToString(dkl.dkl_asciilabel));
                DicConsole.DebugWriteLine("Sun plugin", "dkl.dkl_rpm = {0}", dkl.dkl_rpm);
                DicConsole.DebugWriteLine("Sun plugin", "dkl.dkl_pcyl = {0}", dkl.dkl_pcyl);
                DicConsole.DebugWriteLine("Sun plugin", "dkl.dkl_apc = {0}", dkl.dkl_apc);
                DicConsole.DebugWriteLine("Sun plugin", "dkl.dkl_gap1 = {0}", dkl.dkl_gap1);
                DicConsole.DebugWriteLine("Sun plugin", "dkl.dkl_gap2 = {0}", dkl.dkl_gap2);
                DicConsole.DebugWriteLine("Sun plugin", "dkl.dkl_intrlv = {0}", dkl.dkl_intrlv);
                DicConsole.DebugWriteLine("Sun plugin", "dkl.dkl_ncyl = {0}", dkl.dkl_ncyl);
                DicConsole.DebugWriteLine("Sun plugin", "dkl.dkl_acyl = {0}", dkl.dkl_acyl);
                DicConsole.DebugWriteLine("Sun plugin", "dkl.dkl_nhead = {0}", dkl.dkl_nhead);
                DicConsole.DebugWriteLine("Sun plugin", "dkl.dkl_nsect = {0}", dkl.dkl_nsect);
                DicConsole.DebugWriteLine("Sun plugin", "dkl.dkl_bhead = {0}", dkl.dkl_bhead);
                DicConsole.DebugWriteLine("Sun plugin", "dkl.dkl_ppart = {0}", dkl.dkl_ppart);
                for (int i = 0; i < NDKMAP; i++)
                {
                    DicConsole.DebugWriteLine("Sun plugin", "dkl.dkl_map[{0}].dkl_cylno = {1}", i,
                                              dkl.dkl_map[i].dkl_cylno);
                    DicConsole.DebugWriteLine("Sun plugin", "dkl.dkl_map[{0}].dkl_nblk = {1}", i,
                                              dkl.dkl_map[i].dkl_nblk);
                }

                DicConsole.DebugWriteLine("Sun plugin", "dkl.dkl_magic = 0x{0:X4}", dkl.dkl_magic);
                DicConsole.DebugWriteLine("Sun plugin", "dkl.dkl_cksum = 0x{0:X4}", dkl.dkl_cksum);
                DicConsole.DebugWriteLine("Sun plugin", "sectorsPerCylinder = {0}", sectorsPerCylinder);

                for (int i = 0; i < NDKMAP; i++)
                {
                    if (dkl.dkl_map[i].dkl_cylno > 0 && dkl.dkl_map[i].dkl_nblk > 0)
                    {
                        Partition part = new Partition
                        {
                            Size     = (ulong)dkl.dkl_map[i].dkl_nblk * DK_LABEL_SIZE,
                            Length   = (ulong)(dkl.dkl_map[i].dkl_nblk * DK_LABEL_SIZE / imagePlugin.Info.SectorSize),
                            Sequence = (ulong)i,
                            Offset   =
                                ((ulong)dkl.dkl_map[i].dkl_cylno * sectorsPerCylinder + sectorOffset) *
                                DK_LABEL_SIZE,
                            Start = ((ulong)dkl.dkl_map[i].dkl_cylno * sectorsPerCylinder + sectorOffset) *
                                    DK_LABEL_SIZE / imagePlugin.Info.SectorSize,
                            Type   = "SunOS partition",
                            Scheme = Name
                        };
                        if (part.Start < imagePlugin.Info.Sectors && part.End <= imagePlugin.Info.Sectors)
                        {
                            partitions.Add(part);
                        }
                    }
                }
            }
            else if (useDkl8)
            {
                ulong sectorsPerCylinder = (ulong)(dkl8.dkl_nsect * dkl8.dkl_nhead);

                DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_asciilabel = \"{0}\"",
                                          StringHandlers.CToString(dkl8.dkl_asciilabel));
                DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_vtoc.v_version = {0}", dkl8.dkl_vtoc.v_version);
                DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_vtoc.v_volume = \"{0}\"",
                                          StringHandlers.CToString(dkl8.dkl_vtoc.v_volume));
                DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_vtoc.v_nparts = {0}", dkl8.dkl_vtoc.v_nparts);
                DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_vtoc.v_sanity = 0x{0:X8}", dkl8.dkl_vtoc.v_sanity);
                DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_write_reinstruct = {0}", dkl8.dkl_write_reinstruct);
                DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_read_reinstruct = {0}", dkl8.dkl_read_reinstruct);
                DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_rpm = {0}", dkl8.dkl_rpm);
                DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_pcyl = {0}", dkl8.dkl_pcyl);
                DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_apc = {0}", dkl8.dkl_apc);
                DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_obs1 = {0}", dkl8.dkl_obs1);
                DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_obs2 = {0}", dkl8.dkl_obs2);
                DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_intrlv = {0}", dkl8.dkl_intrlv);
                DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_ncyl = {0}", dkl8.dkl_ncyl);
                DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_acyl = {0}", dkl8.dkl_acyl);
                DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_nhead = {0}", dkl8.dkl_nhead);
                DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_nsect = {0}", dkl8.dkl_nsect);
                DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_obs3 = {0}", dkl8.dkl_obs3);
                DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_obs4 = {0}", dkl8.dkl_obs4);
                for (int i = 0; i < NDKMAP; i++)
                {
                    DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_map[{0}].dkl_cylno = {1}", i,
                                              dkl8.dkl_map[i].dkl_cylno);
                    DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_map[{0}].dkl_nblk = {1}", i,
                                              dkl8.dkl_map[i].dkl_nblk);
                    DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_vtoc.v_part[{0}].p_tag = {1} ({2})", i,
                                              dkl8.dkl_vtoc.v_part[i].p_tag, (ushort)dkl8.dkl_vtoc.v_part[i].p_tag);
                    DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_vtoc.v_part[{0}].p_flag = {1} ({2})", i,
                                              dkl8.dkl_vtoc.v_part[i].p_flag, (ushort)dkl8.dkl_vtoc.v_part[i].p_flag);
                    DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_vtoc.v_timestamp[{0}] = {1}", i,
                                              DateHandlers.UnixToDateTime(dkl8.dkl_vtoc.v_timestamp[i]));
                }

                DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_magic = 0x{0:X4}", dkl8.dkl_magic);
                DicConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_cksum = 0x{0:X4}", dkl8.dkl_cksum);
                DicConsole.DebugWriteLine("Sun plugin", "sectorsPerCylinder = {0}", sectorsPerCylinder);

                if (dkl8.dkl_vtoc.v_nparts > NDKMAP)
                {
                    return(false);
                }

                for (int i = 0; i < dkl8.dkl_vtoc.v_nparts; i++)
                {
                    if (dkl8.dkl_map[i].dkl_nblk > 0 && dkl8.dkl_vtoc.v_part[i].p_tag != SunTag.SunEmpty &&
                        dkl8.dkl_vtoc.v_part[i].p_tag != SunTag.SunWholeDisk)
                    {
                        Partition part = new Partition
                        {
                            Description = SunFlagsToString(dkl8.dkl_vtoc.v_part[i].p_flag),
                            Size        = (ulong)dkl8.dkl_map[i].dkl_nblk * DK_LABEL_SIZE,
                            Length      =
                                (ulong)(dkl8.dkl_map[i].dkl_nblk * DK_LABEL_SIZE / imagePlugin.Info.SectorSize),
                            Sequence = (ulong)i,
                            Offset   =
                                ((ulong)dkl8.dkl_map[i].dkl_cylno * sectorsPerCylinder + sectorOffset) *
                                DK_LABEL_SIZE,
                            Start = ((ulong)dkl8.dkl_map[i].dkl_cylno * sectorsPerCylinder + sectorOffset) *
                                    DK_LABEL_SIZE / imagePlugin.Info.SectorSize,
                            Type   = SunIdToString(dkl8.dkl_vtoc.v_part[i].p_tag),
                            Scheme = Name
                        };
                        if (dkl8.dkl_vtoc.v_timestamp[i] != 0)
                        {
                            part.Description +=
                                $"\nPartition timestamped on {DateHandlers.UnixToDateTime(dkl8.dkl_vtoc.v_timestamp[i])}";
                        }

                        if (part.Start < imagePlugin.Info.Sectors && part.End <= imagePlugin.Info.Sectors)
                        {
                            partitions.Add(part);
                        }
                    }
                }
            }
            else
            {
                DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_vtoc.v_sanity = 0x{0:X8}", dkl16.dkl_vtoc.v_sanity);
                DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_vtoc.v_version = {0}", dkl16.dkl_vtoc.v_version);
                DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_vtoc.v_volume = \"{0}\"",
                                          StringHandlers.CToString(dkl16.dkl_vtoc.v_volume));
                DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_vtoc.v_sectorsz = {0}", dkl16.dkl_vtoc.v_sectorsz);
                DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_vtoc.v_nparts = {0}", dkl16.dkl_vtoc.v_nparts);
                DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_vtoc.v_asciilabel = \"{0}\"",
                                          StringHandlers.CToString(dkl16.dkl_vtoc.v_asciilabel));
                DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_pcyl = {0}", dkl16.dkl_pcyl);
                DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_ncyl = {0}", dkl16.dkl_ncyl);
                DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_acyl = {0}", dkl16.dkl_acyl);
                DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_bcyl = {0}", dkl16.dkl_bcyl);
                DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_nhead = {0}", dkl16.dkl_nhead);
                DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_nsect = {0}", dkl16.dkl_nsect);
                DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_intrlv = {0}", dkl16.dkl_intrlv);
                DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_skew = {0}", dkl16.dkl_skew);
                DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_apc = {0}", dkl16.dkl_apc);
                DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_rpm = {0}", dkl16.dkl_rpm);
                DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_write_reinstruct = {0}", dkl16.dkl_write_reinstruct);
                DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_read_reinstruct = {0}", dkl16.dkl_read_reinstruct);
                for (int i = 0; i < NDKMAP16; i++)
                {
                    DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_vtoc.v_part[{0}].p_start = {1}", i,
                                              dkl16.dkl_vtoc.v_part[i].p_start);
                    DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_vtoc.v_part[{0}].p_size = {1}", i,
                                              dkl16.dkl_vtoc.v_part[i].p_size);
                    DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_vtoc.v_part[{0}].p_tag = {1} ({2})", i,
                                              dkl16.dkl_vtoc.v_part[i].p_tag, (ushort)dkl16.dkl_vtoc.v_part[i].p_tag);
                    DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_vtoc.v_part[{0}].p_flag = {1} ({2})", i,
                                              dkl16.dkl_vtoc.v_part[i].p_flag, (ushort)dkl16.dkl_vtoc.v_part[i].p_flag);
                    DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_vtoc.v_timestamp[{0}] = {1}", i,
                                              DateHandlers.UnixToDateTime(dkl16.dkl_vtoc.v_timestamp[i]));
                }

                DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_magic = 0x{0:X4}", dkl16.dkl_magic);
                DicConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_cksum = 0x{0:X4}", dkl16.dkl_cksum);

                if (dkl16.dkl_vtoc.v_nparts > NDKMAP16)
                {
                    return(false);
                }

                for (int i = 0; i < dkl16.dkl_vtoc.v_nparts; i++)
                {
                    if (dkl16.dkl_vtoc.v_part[i].p_size > 0 && dkl16.dkl_vtoc.v_part[i].p_tag != SunTag.SunEmpty &&
                        dkl16.dkl_vtoc.v_part[i].p_tag != SunTag.SunWholeDisk)
                    {
                        Partition part = new Partition
                        {
                            Description = SunFlagsToString(dkl16.dkl_vtoc.v_part[i].p_flag),
                            Size        = (ulong)dkl16.dkl_vtoc.v_part[i].p_size * dkl16.dkl_vtoc.v_sectorsz,
                            Length      =
                                (ulong)(dkl16.dkl_vtoc.v_part[i].p_size * dkl16.dkl_vtoc.v_sectorsz /
                                        imagePlugin.Info.SectorSize),
                            Sequence = (ulong)i,
                            Offset   =
                                ((ulong)dkl16.dkl_vtoc.v_part[i].p_start + sectorOffset) *
                                dkl16.dkl_vtoc.v_sectorsz,
                            Start = ((ulong)dkl16.dkl_vtoc.v_part[i].p_start + sectorOffset) *
                                    dkl16.dkl_vtoc.v_sectorsz / imagePlugin.Info.SectorSize,
                            Type   = SunIdToString(dkl16.dkl_vtoc.v_part[i].p_tag),
                            Scheme = Name
                        };
                        if (dkl16.dkl_vtoc.v_timestamp[i] != 0)
                        {
                            part.Description +=
                                $"\nPartition timestamped on {DateHandlers.UnixToDateTime(dkl16.dkl_vtoc.v_timestamp[i])}";
                        }
                        if (part.Start < imagePlugin.Info.Sectors && part.End <= imagePlugin.Info.Sectors)
                        {
                            partitions.Add(part);
                        }
                    }
                }
            }

            return(partitions.Count > 0);
        }
Пример #3
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;
            }

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

            spcl16   oldHdr = new spcl16();
            spcl_aix aixHdr = new spcl_aix();
            s_spcl   newHdr = new s_spcl();

            uint sbSize = (uint)(Marshal.SizeOf(newHdr) / imagePlugin.Info.SectorSize);

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

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

            IntPtr oldPtr = Marshal.AllocHGlobal(Marshal.SizeOf(oldHdr));

            Marshal.Copy(sector, 0, oldPtr, Marshal.SizeOf(oldHdr));
            oldHdr = (spcl16)Marshal.PtrToStructure(oldPtr, typeof(spcl16));
            Marshal.FreeHGlobal(oldPtr);

            IntPtr aixPtr = Marshal.AllocHGlobal(Marshal.SizeOf(aixHdr));

            Marshal.Copy(sector, 0, aixPtr, Marshal.SizeOf(aixHdr));
            aixHdr = (spcl_aix)Marshal.PtrToStructure(aixPtr, typeof(spcl_aix));
            Marshal.FreeHGlobal(aixPtr);

            IntPtr newPtr = Marshal.AllocHGlobal(Marshal.SizeOf(newHdr));

            Marshal.Copy(sector, 0, newPtr, Marshal.SizeOf(newHdr));
            newHdr = (s_spcl)Marshal.PtrToStructure(newPtr, typeof(s_spcl));
            Marshal.FreeHGlobal(newPtr);

            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 = BigEndianMarshal.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 = BigEndianMarshal.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;
            }

            StringBuilder sb = new StringBuilder();

            XmlFsType = new FileSystemType {
                ClusterSize = 1024, Clusters = (long)(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();
        }
Пример #4
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            Encoding    = encoding ?? Encoding.GetEncoding("iso-8859-15");
            information = "";

            StringBuilder sb = new StringBuilder();

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

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

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

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

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

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

                    start = i;
                    break;
                }

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

                    start = i;
                    break;
                }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            XmlFsType = new FileSystemType();

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            information = sb.ToString();

            BigEndianBitConverter.IsLittleEndian = false; // Return to default (bigendian)
        }
Пример #5
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            Encoding    = encoding ?? Encoding.GetEncoding("iso-8859-15");
            information = "";
            StringBuilder sbInformation = new StringBuilder();

            uint magic = 0;
            uint sb_size_in_sectors;

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

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

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

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

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

                magic = 0;
            }

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

            XmlFsType = new FileSystemType();

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

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

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

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

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

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

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

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

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

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

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

            Marshal.FreeHGlobal(sbPtr);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            information = sbInformation.ToString();
        }
Пример #6
0
        public bool Open(IFilter imageFilter)
        {
            Header    = new ScpHeader();
            scpStream = imageFilter.GetDataForkStream();
            scpStream.Seek(0, SeekOrigin.Begin);
            if (scpStream.Length < Marshal.SizeOf(Header))
            {
                return(false);
            }

            byte[] hdr = new byte[Marshal.SizeOf(Header)];
            scpStream.Read(hdr, 0, Marshal.SizeOf(Header));

            IntPtr hdrPtr = Marshal.AllocHGlobal(Marshal.SizeOf(Header));

            Marshal.Copy(hdr, 0, hdrPtr, Marshal.SizeOf(Header));
            Header = (ScpHeader)Marshal.PtrToStructure(hdrPtr, typeof(ScpHeader));
            Marshal.FreeHGlobal(hdrPtr);

            DicConsole.DebugWriteLine("SuperCardPro plugin", "header.signature = \"{0}\"",
                                      StringHandlers.CToString(Header.signature));
            DicConsole.DebugWriteLine("SuperCardPro plugin", "header.version = {0}.{1}", (Header.version & 0xF0) >> 4,
                                      Header.version & 0xF);
            DicConsole.DebugWriteLine("SuperCardPro plugin", "header.type = {0}", Header.type);
            DicConsole.DebugWriteLine("SuperCardPro plugin", "header.revolutions = {0}", Header.revolutions);
            DicConsole.DebugWriteLine("SuperCardPro plugin", "header.start = {0}", Header.start);
            DicConsole.DebugWriteLine("SuperCardPro plugin", "header.end = {0}", Header.end);
            DicConsole.DebugWriteLine("SuperCardPro plugin", "header.flags = {0}", Header.flags);
            DicConsole.DebugWriteLine("SuperCardPro plugin", "header.bitCellEncoding = {0}", Header.bitCellEncoding);
            DicConsole.DebugWriteLine("SuperCardPro plugin", "header.heads = {0}", Header.heads);
            DicConsole.DebugWriteLine("SuperCardPro plugin", "header.reserved = {0}", Header.reserved);
            DicConsole.DebugWriteLine("SuperCardPro plugin", "header.checksum = 0x{0:X8}", Header.checksum);

            if (!scpSignature.SequenceEqual(Header.signature))
            {
                return(false);
            }

            ScpTracks = new Dictionary <byte, TrackHeader>();

            for (byte t = Header.start; t <= Header.end; t++)
            {
                if (t >= Header.offsets.Length)
                {
                    break;
                }

                scpStream.Position = Header.offsets[t];
                TrackHeader trk =
                    new TrackHeader {
                    Signature = new byte[3], Entries = new TrackEntry[Header.revolutions]
                };
                scpStream.Read(trk.Signature, 0, trk.Signature.Length);
                trk.TrackNumber = (byte)scpStream.ReadByte();

                if (!trk.Signature.SequenceEqual(trkSignature))
                {
                    DicConsole.DebugWriteLine("SuperCardPro plugin",
                                              "Track header at {0} contains incorrect signature.", Header.offsets[t]);
                    continue;
                }

                if (trk.TrackNumber != t)
                {
                    DicConsole.DebugWriteLine("SuperCardPro plugin", "Track number at {0} should be {1} but is {2}.",
                                              Header.offsets[t], t, trk.TrackNumber);
                    continue;
                }

                DicConsole.DebugWriteLine("SuperCardPro plugin", "Found track {0} at {1}.", t, Header.offsets[t]);

                for (byte r = 0; r < Header.revolutions; r++)
                {
                    byte[] rev = new byte[Marshal.SizeOf(typeof(TrackEntry))];
                    scpStream.Read(rev, 0, Marshal.SizeOf(typeof(TrackEntry)));

                    IntPtr revPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(TrackEntry)));
                    Marshal.Copy(rev, 0, revPtr, Marshal.SizeOf(typeof(TrackEntry)));
                    trk.Entries[r] = (TrackEntry)Marshal.PtrToStructure(revPtr, typeof(TrackEntry));
                    Marshal.FreeHGlobal(revPtr);
                    // De-relative offsets
                    trk.Entries[r].dataOffset += Header.offsets[t];
                }

                ScpTracks.Add(t, trk);
            }

            if (Header.flags.HasFlag(ScpFlags.HasFooter))
            {
                long position = scpStream.Position;
                scpStream.Seek(-4, SeekOrigin.End);

                while (scpStream.Position >= position)
                {
                    byte[] footerSig = new byte[4];
                    scpStream.Read(footerSig, 0, 4);
                    uint footerMagic = BitConverter.ToUInt32(footerSig, 0);

                    if (footerMagic == FOOTER_SIGNATURE)
                    {
                        scpStream.Seek(-Marshal.SizeOf(typeof(ScpFooter)), SeekOrigin.Current);

                        DicConsole.DebugWriteLine("SuperCardPro plugin", "Found footer at {0}", scpStream.Position);

                        byte[] ftr = new byte[Marshal.SizeOf(typeof(ScpFooter))];
                        scpStream.Read(ftr, 0, Marshal.SizeOf(typeof(ScpFooter)));

                        IntPtr ftrPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(ScpFooter)));
                        Marshal.Copy(ftr, 0, ftrPtr, Marshal.SizeOf(typeof(ScpFooter)));
                        ScpFooter footer = (ScpFooter)Marshal.PtrToStructure(ftrPtr, typeof(ScpFooter));
                        Marshal.FreeHGlobal(ftrPtr);

                        DicConsole.DebugWriteLine("SuperCardPro plugin", "footer.manufacturerOffset = 0x{0:X8}",
                                                  footer.manufacturerOffset);
                        DicConsole.DebugWriteLine("SuperCardPro plugin", "footer.modelOffset = 0x{0:X8}",
                                                  footer.modelOffset);
                        DicConsole.DebugWriteLine("SuperCardPro plugin", "footer.serialOffset = 0x{0:X8}",
                                                  footer.serialOffset);
                        DicConsole.DebugWriteLine("SuperCardPro plugin", "footer.creatorOffset = 0x{0:X8}",
                                                  footer.creatorOffset);
                        DicConsole.DebugWriteLine("SuperCardPro plugin", "footer.applicationOffset = 0x{0:X8}",
                                                  footer.applicationOffset);
                        DicConsole.DebugWriteLine("SuperCardPro plugin", "footer.commentsOffset = 0x{0:X8}",
                                                  footer.commentsOffset);
                        DicConsole.DebugWriteLine("SuperCardPro plugin", "footer.creationTime = {0}",
                                                  footer.creationTime);
                        DicConsole.DebugWriteLine("SuperCardPro plugin", "footer.modificationTime = {0}",
                                                  footer.modificationTime);
                        DicConsole.DebugWriteLine("SuperCardPro plugin", "footer.applicationVersion = {0}.{1}",
                                                  (footer.applicationVersion & 0xF0) >> 4,
                                                  footer.applicationVersion & 0xF);
                        DicConsole.DebugWriteLine("SuperCardPro plugin", "footer.hardwareVersion = {0}.{1}",
                                                  (footer.hardwareVersion & 0xF0) >> 4, footer.hardwareVersion & 0xF);
                        DicConsole.DebugWriteLine("SuperCardPro plugin", "footer.firmwareVersion = {0}.{1}",
                                                  (footer.firmwareVersion & 0xF0) >> 4, footer.firmwareVersion & 0xF);
                        DicConsole.DebugWriteLine("SuperCardPro plugin", "footer.imageVersion = {0}.{1}",
                                                  (footer.imageVersion & 0xF0) >> 4, footer.imageVersion & 0xF);
                        DicConsole.DebugWriteLine("SuperCardPro plugin", "footer.signature = \"{0}\"",
                                                  StringHandlers.CToString(BitConverter.GetBytes(footer.signature)));

                        imageInfo.DriveManufacturer = ReadPStringUtf8(scpStream, footer.manufacturerOffset);
                        imageInfo.DriveModel        = ReadPStringUtf8(scpStream, footer.modelOffset);
                        imageInfo.DriveSerialNumber = ReadPStringUtf8(scpStream, footer.serialOffset);
                        imageInfo.Creator           = ReadPStringUtf8(scpStream, footer.creatorOffset);
                        imageInfo.Application       = ReadPStringUtf8(scpStream, footer.applicationOffset);
                        imageInfo.Comments          = ReadPStringUtf8(scpStream, footer.commentsOffset);

                        DicConsole.DebugWriteLine("SuperCardPro plugin", "ImageInfo.driveManufacturer = \"{0}\"",
                                                  imageInfo.DriveManufacturer);
                        DicConsole.DebugWriteLine("SuperCardPro plugin", "ImageInfo.driveModel = \"{0}\"",
                                                  imageInfo.DriveModel);
                        DicConsole.DebugWriteLine("SuperCardPro plugin", "ImageInfo.driveSerialNumber = \"{0}\"",
                                                  imageInfo.DriveSerialNumber);
                        DicConsole.DebugWriteLine("SuperCardPro plugin", "ImageInfo.imageCreator = \"{0}\"",
                                                  imageInfo.Creator);
                        DicConsole.DebugWriteLine("SuperCardPro plugin", "ImageInfo.imageApplication = \"{0}\"",
                                                  imageInfo.Application);
                        DicConsole.DebugWriteLine("SuperCardPro plugin", "ImageInfo.imageComments = \"{0}\"",
                                                  imageInfo.Comments);

                        imageInfo.CreationTime = footer.creationTime != 0
                                                     ? DateHandlers.UnixToDateTime(footer.creationTime)
                                                     : imageFilter.GetCreationTime();

                        imageInfo.LastModificationTime = footer.modificationTime != 0
                                                             ? DateHandlers.UnixToDateTime(footer.modificationTime)
                                                             : imageFilter.GetLastWriteTime();

                        DicConsole.DebugWriteLine("SuperCardPro plugin", "ImageInfo.imageCreationTime = {0}",
                                                  imageInfo.CreationTime);
                        DicConsole.DebugWriteLine("SuperCardPro plugin", "ImageInfo.imageLastModificationTime = {0}",
                                                  imageInfo.LastModificationTime);

                        imageInfo.ApplicationVersion =
                            $"{(footer.applicationVersion & 0xF0) >> 4}.{footer.applicationVersion & 0xF}";
                        imageInfo.DriveFirmwareRevision =
                            $"{(footer.firmwareVersion & 0xF0) >> 4}.{footer.firmwareVersion & 0xF}";
                        imageInfo.Version = $"{(footer.imageVersion & 0xF0) >> 4}.{footer.imageVersion & 0xF}";

                        break;
                    }

                    scpStream.Seek(-8, SeekOrigin.Current);
                }
            }
            else
            {
                imageInfo.Application          = "SuperCardPro";
                imageInfo.ApplicationVersion   = $"{(Header.version & 0xF0) >> 4}.{Header.version & 0xF}";
                imageInfo.CreationTime         = imageFilter.GetCreationTime();
                imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
                imageInfo.Version = "1.5";
            }

            throw new NotImplementedException("Flux decoding is not yet implemented.");
        }
Пример #7
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            Encoding    = encoding ?? Encoding.GetEncoding("ibm850");
            information = "";

            var sb = new StringBuilder();

            byte[] hpfsBpbSector =
                imagePlugin.ReadSector(0 + partition.Start); // Seek to BIOS parameter block, on logical sector 0

            byte[] hpfsSbSector =
                imagePlugin.ReadSector(16 + partition.Start); // Seek to superblock, on logical sector 16

            byte[] hpfsSpSector =
                imagePlugin.ReadSector(17 + partition.Start); // Seek to spareblock, on logical sector 17

            BiosParameterBlock bpb = Marshal.ByteArrayToStructureLittleEndian <BiosParameterBlock>(hpfsBpbSector);

            SuperBlock hpfsSb = Marshal.ByteArrayToStructureLittleEndian <SuperBlock>(hpfsSbSector);

            SpareBlock sp = Marshal.ByteArrayToStructureLittleEndian <SpareBlock>(hpfsSpSector);

            if (StringHandlers.CToString(bpb.fs_type) != "HPFS    " ||
                hpfsSb.magic1 != 0xF995E849 ||
                hpfsSb.magic2 != 0xFA53E9C5 ||
                sp.magic1 != 0xF9911849 ||
                sp.magic2 != 0xFA5229C5)
            {
                sb.AppendLine("This may not be HPFS, following information may be not correct.");
                sb.AppendFormat("File system type: \"{0}\" (Should be \"HPFS    \")", bpb.fs_type).AppendLine();
                sb.AppendFormat("Superblock magic1: 0x{0:X8} (Should be 0xF995E849)", hpfsSb.magic1).AppendLine();
                sb.AppendFormat("Superblock magic2: 0x{0:X8} (Should be 0xFA53E9C5)", hpfsSb.magic2).AppendLine();
                sb.AppendFormat("Spareblock magic1: 0x{0:X8} (Should be 0xF9911849)", sp.magic1).AppendLine();
                sb.AppendFormat("Spareblock magic2: 0x{0:X8} (Should be 0xFA5229C5)", sp.magic2).AppendLine();
            }

            sb.AppendFormat("OEM name: {0}", StringHandlers.CToString(bpb.oem_name)).AppendLine();
            sb.AppendFormat("{0} bytes per sector", bpb.bps).AppendLine();

            //          sb.AppendFormat("{0} sectors per cluster", hpfs_bpb.spc).AppendLine();
            //          sb.AppendFormat("{0} reserved sectors", hpfs_bpb.rsectors).AppendLine();
            //          sb.AppendFormat("{0} FATs", hpfs_bpb.fats_no).AppendLine();
            //          sb.AppendFormat("{0} entries on root directory", hpfs_bpb.root_ent).AppendLine();
            //          sb.AppendFormat("{0} mini sectors on volume", hpfs_bpb.sectors).AppendLine();
            sb.AppendFormat("Media descriptor: 0x{0:X2}", bpb.media).AppendLine();

            //          sb.AppendFormat("{0} sectors per FAT", hpfs_bpb.spfat).AppendLine();
            //          sb.AppendFormat("{0} sectors per track", hpfs_bpb.sptrk).AppendLine();
            //          sb.AppendFormat("{0} heads", hpfs_bpb.heads).AppendLine();
            sb.AppendFormat("{0} sectors hidden before BPB", bpb.hsectors).AppendLine();

            sb.AppendFormat("{0} sectors on volume ({1} bytes)", hpfsSb.sectors, hpfsSb.sectors * bpb.bps).AppendLine();

            //          sb.AppendFormat("{0} sectors on volume ({1} bytes)", hpfs_bpb.big_sectors, hpfs_bpb.big_sectors * hpfs_bpb.bps).AppendLine();
            sb.AppendFormat("BIOS Drive Number: 0x{0:X2}", bpb.drive_no).AppendLine();
            sb.AppendFormat("NT Flags: 0x{0:X2}", bpb.nt_flags).AppendLine();
            sb.AppendFormat("Signature: 0x{0:X2}", bpb.signature).AppendLine();
            sb.AppendFormat("Serial number: 0x{0:X8}", bpb.serial_no).AppendLine();
            sb.AppendFormat("Volume label: {0}", StringHandlers.CToString(bpb.volume_label, Encoding)).AppendLine();

            //          sb.AppendFormat("Filesystem type: \"{0}\"", hpfs_bpb.fs_type).AppendLine();

            DateTime lastChk   = DateHandlers.UnixToDateTime(hpfsSb.last_chkdsk);
            DateTime lastOptim = DateHandlers.UnixToDateTime(hpfsSb.last_optim);

            sb.AppendFormat("HPFS version: {0}", hpfsSb.version).AppendLine();
            sb.AppendFormat("Functional version: {0}", hpfsSb.func_version).AppendLine();
            sb.AppendFormat("Sector of root directory FNode: {0}", hpfsSb.root_fnode).AppendLine();
            sb.AppendFormat("{0} sectors are marked bad", hpfsSb.badblocks).AppendLine();
            sb.AppendFormat("Sector of free space bitmaps: {0}", hpfsSb.bitmap_lsn).AppendLine();
            sb.AppendFormat("Sector of bad blocks list: {0}", hpfsSb.badblock_lsn).AppendLine();

            if (hpfsSb.last_chkdsk > 0)
            {
                sb.AppendFormat("Date of last integrity check: {0}", lastChk).AppendLine();
            }
            else
            {
                sb.AppendLine("Filesystem integrity has never been checked");
            }

            if (hpfsSb.last_optim > 0)
            {
                sb.AppendFormat("Date of last optimization {0}", lastOptim).AppendLine();
            }
            else
            {
                sb.AppendLine("Filesystem has never been optimized");
            }

            sb.AppendFormat("Directory band has {0} sectors", hpfsSb.dband_sectors).AppendLine();
            sb.AppendFormat("Directory band starts at sector {0}", hpfsSb.dband_start).AppendLine();
            sb.AppendFormat("Directory band ends at sector {0}", hpfsSb.dband_last).AppendLine();
            sb.AppendFormat("Sector of directory band bitmap: {0}", hpfsSb.dband_bitmap).AppendLine();
            sb.AppendFormat("Sector of ACL directory: {0}", hpfsSb.acl_start).AppendLine();

            sb.AppendFormat("Sector of Hotfix directory: {0}", sp.hotfix_start).AppendLine();
            sb.AppendFormat("{0} used Hotfix entries", sp.hotfix_used).AppendLine();
            sb.AppendFormat("{0} total Hotfix entries", sp.hotfix_entries).AppendLine();
            sb.AppendFormat("{0} free spare DNodes", sp.spare_dnodes_free).AppendLine();
            sb.AppendFormat("{0} total spare DNodes", sp.spare_dnodes).AppendLine();
            sb.AppendFormat("Sector of codepage directory: {0}", sp.codepage_lsn).AppendLine();
            sb.AppendFormat("{0} codepages used in the volume", sp.codepages).AppendLine();
            sb.AppendFormat("SuperBlock CRC32: {0:X8}", sp.sb_crc32).AppendLine();
            sb.AppendFormat("SpareBlock CRC32: {0:X8}", sp.sp_crc32).AppendLine();

            sb.AppendLine("Flags:");
            sb.AppendLine((sp.flags1 & 0x01) == 0x01 ? "Filesystem is dirty." : "Filesystem is clean.");

            if ((sp.flags1 & 0x02) == 0x02)
            {
                sb.AppendLine("Spare directory blocks are in use");
            }

            if ((sp.flags1 & 0x04) == 0x04)
            {
                sb.AppendLine("Hotfixes are in use");
            }

            if ((sp.flags1 & 0x08) == 0x08)
            {
                sb.AppendLine("Disk contains bad sectors");
            }

            if ((sp.flags1 & 0x10) == 0x10)
            {
                sb.AppendLine("Disk has a bad bitmap");
            }

            if ((sp.flags1 & 0x20) == 0x20)
            {
                sb.AppendLine("Filesystem was formatted fast");
            }

            if ((sp.flags1 & 0x40) == 0x40)
            {
                sb.AppendLine("Unknown flag 0x40 on flags1 is active");
            }

            if ((sp.flags1 & 0x80) == 0x80)
            {
                sb.AppendLine("Filesystem has been mounted by an old IFS");
            }

            if ((sp.flags2 & 0x01) == 0x01)
            {
                sb.AppendLine("Install DASD limits");
            }

            if ((sp.flags2 & 0x02) == 0x02)
            {
                sb.AppendLine("Resync DASD limits");
            }

            if ((sp.flags2 & 0x04) == 0x04)
            {
                sb.AppendLine("DASD limits are operational");
            }

            if ((sp.flags2 & 0x08) == 0x08)
            {
                sb.AppendLine("Multimedia is active");
            }

            if ((sp.flags2 & 0x10) == 0x10)
            {
                sb.AppendLine("DCE ACLs are active");
            }

            if ((sp.flags2 & 0x20) == 0x20)
            {
                sb.AppendLine("DASD limits are dirty");
            }

            if ((sp.flags2 & 0x40) == 0x40)
            {
                sb.AppendLine("Unknown flag 0x40 on flags2 is active");
            }

            if ((sp.flags2 & 0x80) == 0x80)
            {
                sb.AppendLine("Unknown flag 0x80 on flags2 is active");
            }

            XmlFsType = new FileSystemType();

            // Theoretically everything from BPB to SB is boot code, should I hash everything or only the sector loaded by BIOS itself?
            if (bpb.jump[0] == 0xEB &&
                bpb.jump[1] > 0x3C &&
                bpb.jump[1] < 0x80 &&
                bpb.signature2 == 0xAA55)
            {
                XmlFsType.Bootable = true;
                string bootChk = Sha1Context.Data(bpb.boot_code, out byte[] _);
                sb.AppendLine("Volume is bootable");
                sb.AppendFormat("Boot code's SHA1: {0}", bootChk).AppendLine();
            }

            XmlFsType.Dirty           |= (sp.flags1 & 0x01) == 0x01;
            XmlFsType.Clusters         = hpfsSb.sectors;
            XmlFsType.ClusterSize      = bpb.bps;
            XmlFsType.Type             = "HPFS";
            XmlFsType.VolumeName       = StringHandlers.CToString(bpb.volume_label, Encoding);
            XmlFsType.VolumeSerial     = $"{bpb.serial_no:X8}";
            XmlFsType.SystemIdentifier = StringHandlers.CToString(bpb.oem_name);

            information = sb.ToString();
        }
Пример #8
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            Encoding    = encoding ?? Encoding.GetEncoding("iso-8859-15");
            information = "";

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

            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
            };
        }
Пример #9
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;
        }
Пример #10
0
        public bool GetInformation(IMediaImage imagePlugin, out List <Partition> partitions, ulong sectorOffset)
        {
            partitions = new List <Partition>();

            uint  magic = 0;
            ulong pdloc = 0;

            byte[] pdsector   = null;
            bool   magicFound = false;
            bool   absolute   = false;

            foreach (ulong i in new ulong[]
            {
                0, 1, 8, 29
            }.TakeWhile(i => i + sectorOffset < imagePlugin.Info.Sectors))
            {
                pdsector = imagePlugin.ReadSector(i + sectorOffset);
                magic    = BitConverter.ToUInt32(pdsector, 4);

                AaruConsole.DebugWriteLine("VTOC plugin", "sanity at {0} is 0x{1:X8} (should be 0x{2:X8} or 0x{3:X8})",
                                           i + sectorOffset, magic, PD_MAGIC, PD_CIGAM);

                if (magic != PD_MAGIC &&
                    magic != PD_CIGAM)
                {
                    continue;
                }

                magicFound = true;
                pdloc      = i;

                break;
            }

            if (!magicFound)
            {
                return(false);
            }

            PDInfo    pd;
            PDInfoOld pdold;

            if (magic == PD_MAGIC)
            {
                pd    = Marshal.ByteArrayToStructureLittleEndian <PDInfo>(pdsector);
                pdold = Marshal.ByteArrayToStructureLittleEndian <PDInfoOld>(pdsector);
            }
            else
            {
                pd    = Marshal.ByteArrayToStructureBigEndian <PDInfo>(pdsector);
                pdold = Marshal.ByteArrayToStructureBigEndian <PDInfoOld>(pdsector);
            }

            AaruConsole.DebugWriteLine("VTOC plugin", "pdinfo.driveid = {0}", pd.driveid);

            AaruConsole.DebugWriteLine("VTOC plugin", "pdinfo.sanity = 0x{0:X8} (should be 0x{1:X8})", pd.sanity,
                                       PD_MAGIC);

            AaruConsole.DebugWriteLine("VTOC plugin", "pdinfo.version = {0}", pd.version);
            AaruConsole.DebugWriteLine("VTOC plugin", "pdinfo.serial = \"{0}\"", StringHandlers.CToString(pd.serial));
            AaruConsole.DebugWriteLine("VTOC plugin", "pdinfo.cyls = {0}", pd.cyls);
            AaruConsole.DebugWriteLine("VTOC plugin", "pdinfo.tracks = {0}", pd.tracks);
            AaruConsole.DebugWriteLine("VTOC plugin", "pdinfo.sectors = {0}", pd.sectors);
            AaruConsole.DebugWriteLine("VTOC plugin", "pdinfo.bytes = {0}", pd.bytes);
            AaruConsole.DebugWriteLine("VTOC plugin", "pdinfo.logicalst = {0}", pd.logicalst);
            AaruConsole.DebugWriteLine("VTOC plugin", "pdinfo.errlogst = {0}", pd.errlogst);
            AaruConsole.DebugWriteLine("VTOC plugin", "pdinfo.errlogsz = {0}", pd.errlogsz);
            AaruConsole.DebugWriteLine("VTOC plugin", "pdinfo.mfgst = {0}", pd.mfgst);
            AaruConsole.DebugWriteLine("VTOC plugin", "pdinfo.mfgsz = {0}", pd.mfgsz);
            AaruConsole.DebugWriteLine("VTOC plugin", "pdinfo.defectst = {0}", pd.defectst);
            AaruConsole.DebugWriteLine("VTOC plugin", "pdinfo.defectsz = {0}", pd.defectsz);
            AaruConsole.DebugWriteLine("VTOC plugin", "pdinfo.relno = {0}", pd.relno);
            AaruConsole.DebugWriteLine("VTOC plugin", "pdinfo.relst = {0}", pd.relst);
            AaruConsole.DebugWriteLine("VTOC plugin", "pdinfo.relsz = {0}", pd.relsz);
            AaruConsole.DebugWriteLine("VTOC plugin", "pdinfo.relnext = {0}", pd.relnext);
            AaruConsole.DebugWriteLine("VTOC plugin", "pdinfo.allcstrt = {0}", pdold.allcstrt);
            AaruConsole.DebugWriteLine("VTOC plugin", "pdinfo.allcend = {0}", pdold.allcend);
            AaruConsole.DebugWriteLine("VTOC plugin", "pdinfo.vtoc_ptr = {0}", pd.vtoc_ptr);
            AaruConsole.DebugWriteLine("VTOC plugin", "pdinfo.vtoc_len = {0}", pd.vtoc_len);
            AaruConsole.DebugWriteLine("VTOC plugin", "pdinfo.vtoc_pad = {0}", pd.vtoc_pad);
            AaruConsole.DebugWriteLine("VTOC plugin", "pdinfo.alt_ptr = {0}", pd.alt_ptr);
            AaruConsole.DebugWriteLine("VTOC plugin", "pdinfo.alt_len = {0}", pd.alt_len);
            AaruConsole.DebugWriteLine("VTOC plugin", "pdinfo.pcyls = {0}", pd.pcyls);
            AaruConsole.DebugWriteLine("VTOC plugin", "pdinfo.ptracks = {0}", pd.ptracks);
            AaruConsole.DebugWriteLine("VTOC plugin", "pdinfo.psectors = {0}", pd.psectors);
            AaruConsole.DebugWriteLine("VTOC plugin", "pdinfo.pbytes = {0}", pd.pbytes);
            AaruConsole.DebugWriteLine("VTOC plugin", "pdinfo.secovhd = {0}", pd.secovhd);
            AaruConsole.DebugWriteLine("VTOC plugin", "pdinfo.interleave = {0}", pd.interleave);
            AaruConsole.DebugWriteLine("VTOC plugin", "pdinfo.skew = {0}", pd.skew);
            AaruConsole.DebugWriteLine("VTOC plugin", "pdinfo.pad[0] = {0}", pd.pad[0]);
            AaruConsole.DebugWriteLine("VTOC plugin", "pdinfo.pad[1] = {0}", pd.pad[1]);
            AaruConsole.DebugWriteLine("VTOC plugin", "pdinfo.pad[2] = {0}", pd.pad[2]);
            AaruConsole.DebugWriteLine("VTOC plugin", "pdinfo.pad[3] = {0}", pd.pad[3]);
            AaruConsole.DebugWriteLine("VTOC plugin", "pdinfo.pad[4] = {0}", pd.pad[4]);
            AaruConsole.DebugWriteLine("VTOC plugin", "pdinfo.pad[5] = {0}", pd.pad[5]);
            AaruConsole.DebugWriteLine("VTOC plugin", "pdinfo.pad[6] = {0}", pd.pad[6]);
            AaruConsole.DebugWriteLine("VTOC plugin", "pdinfo.pad[7] = {0}", pd.pad[7]);

            magicFound = false;
            bool useOld = false;

            byte[] vtocsector = imagePlugin.ReadSector(pdloc + sectorOffset + 1);
            var    vtoc       = new vtoc();
            var    vtocOld    = new vtocold();

            magic = BitConverter.ToUInt32(vtocsector, 0);

            if (magic == VTOC_SANE ||
                magic == VTOC_ENAS)
            {
                magicFound = true;
                AaruConsole.DebugWriteLine("VTOC plugin", "New VTOC found at {0}", pdloc + sectorOffset + 1);

                if (magic == VTOC_SANE)
                {
                    vtoc = Marshal.ByteArrayToStructureLittleEndian <vtoc>(vtocsector);
                }
                else
                {
                    vtoc = Marshal.ByteArrayToStructureBigEndian <vtoc>(vtocsector);

                    for (int i = 0; i < vtoc.v_part.Length; i++)
                    {
                        vtoc.v_part[i].p_tag   = (pTag)Swapping.Swap((ushort)vtoc.v_part[i].p_tag);
                        vtoc.v_part[i].p_flag  = (pFlag)Swapping.Swap((ushort)vtoc.v_part[i].p_flag);
                        vtoc.v_part[i].p_start = Swapping.Swap(vtoc.v_part[i].p_start);
                        vtoc.v_part[i].p_size  = Swapping.Swap(vtoc.v_part[i].p_size);
                        vtoc.timestamp[i]      = Swapping.Swap(vtoc.timestamp[i]);
                    }
                }
            }

            if (!magicFound &&
                pd.version < XPDVERS)
            {
                magic = BitConverter.ToUInt32(vtocsector, 12);

                if (magic == VTOC_SANE ||
                    magic == VTOC_ENAS)
                {
                    magicFound = true;
                    useOld     = true;
                    AaruConsole.DebugWriteLine("VTOC plugin", "Old VTOC found at {0}", pdloc + sectorOffset + 1);

                    if (magic == VTOC_SANE)
                    {
                        vtocOld = Marshal.ByteArrayToStructureLittleEndian <vtocold>(vtocsector);
                    }
                    else
                    {
                        vtocOld = Marshal.ByteArrayToStructureBigEndian <vtocold>(vtocsector);

                        for (int i = 0; i < vtocOld.v_part.Length; i++)
                        {
                            vtocOld.v_part[i].p_tag   = (pTag)Swapping.Swap((ushort)vtocOld.v_part[i].p_tag);
                            vtocOld.v_part[i].p_flag  = (pFlag)Swapping.Swap((ushort)vtocOld.v_part[i].p_flag);
                            vtocOld.v_part[i].p_start = Swapping.Swap(vtocOld.v_part[i].p_start);
                            vtocOld.v_part[i].p_size  = Swapping.Swap(vtocOld.v_part[i].p_size);
                            vtocOld.timestamp[i]      = Swapping.Swap(vtocOld.timestamp[i]);
                        }
                    }
                }
            }

            if (!magicFound)
            {
                AaruConsole.DebugWriteLine("VTOC plugin", "Searching for VTOC on relative byte {0}", pd.vtoc_ptr);
                ulong relSecPtr = pd.vtoc_ptr / imagePlugin.Info.SectorSize;
                uint  relSecOff = pd.vtoc_ptr % imagePlugin.Info.SectorSize;
                uint  secCount  = (relSecOff + pd.vtoc_len) / imagePlugin.Info.SectorSize;

                if ((relSecOff + pd.vtoc_len) % imagePlugin.Info.SectorSize > 0)
                {
                    secCount++;
                }

                AaruConsole.DebugWriteLine("VTOC plugin",
                                           "Going to read {0} sectors from sector {1}, getting VTOC from byte {2}",
                                           secCount, relSecPtr + sectorOffset, relSecOff);

                if (relSecPtr + sectorOffset + secCount >= imagePlugin.Info.Sectors)
                {
                    AaruConsole.DebugWriteLine("VTOC plugin", "Going to read past device size, aborting...");

                    return(false);
                }

                byte[] tmp = imagePlugin.ReadSectors(relSecPtr + sectorOffset, secCount);
                vtocsector = new byte[pd.vtoc_len];
                Array.Copy(tmp, relSecOff, vtocsector, 0, pd.vtoc_len);
                magic = BitConverter.ToUInt32(vtocsector, 0);

                if (magic == VTOC_SANE ||
                    magic == VTOC_ENAS)
                {
                    magicFound = true;
                    AaruConsole.DebugWriteLine("VTOC plugin", "New VTOC found.");

                    if (magic == VTOC_SANE)
                    {
                        vtoc = Marshal.ByteArrayToStructureLittleEndian <vtoc>(vtocsector);
                    }
                    else
                    {
                        vtoc = Marshal.ByteArrayToStructureBigEndian <vtoc>(vtocsector);

                        for (int i = 0; i < vtoc.v_part.Length; i++)
                        {
                            vtoc.v_part[i].p_tag   = (pTag)Swapping.Swap((ushort)vtoc.v_part[i].p_tag);
                            vtoc.v_part[i].p_flag  = (pFlag)Swapping.Swap((ushort)vtoc.v_part[i].p_flag);
                            vtoc.v_part[i].p_start = Swapping.Swap(vtoc.v_part[i].p_start);
                            vtoc.v_part[i].p_size  = Swapping.Swap(vtoc.v_part[i].p_size);
                            vtoc.timestamp[i]      = Swapping.Swap(vtoc.timestamp[i]);
                        }
                    }
                }
            }

            if (!magicFound)
            {
                AaruConsole.DebugWriteLine("VTOC plugin", "Cannot find VTOC.");

                return(false);
            }

            if (useOld)
            {
                AaruConsole.DebugWriteLine("VTOC plugin", "vtocOld.v_sanity = 0x{0:X8} (should be 0x{1:X8})",
                                           vtocOld.v_sanity, VTOC_SANE);

                AaruConsole.DebugWriteLine("VTOC plugin", "vtocOld.v_version = {0}", vtocOld.v_version);

                AaruConsole.DebugWriteLine("VTOC plugin", "vtocOld.v_volume = \"{0}\"",
                                           StringHandlers.CToString(vtocOld.v_volume));

                AaruConsole.DebugWriteLine("VTOC plugin", "vtocOld.v_sectorsz = {0}", vtocOld.v_sectorsz);
                AaruConsole.DebugWriteLine("VTOC plugin", "vtocOld.v_nparts = {0}", vtocOld.v_nparts);

                for (int i = 0; i < V_NUMPAR; i++)
                {
                    AaruConsole.DebugWriteLine("VTOC plugin", "vtocOld.v_part[{0}].p_tag = {1} ({2})", i,
                                               vtocOld.v_part[i].p_tag, (ushort)vtocOld.v_part[i].p_tag);

                    AaruConsole.DebugWriteLine("VTOC plugin", "vtocOld.v_part[{0}].p_flag = {1} ({2})", i,
                                               vtocOld.v_part[i].p_flag, (ushort)vtocOld.v_part[i].p_flag);

                    AaruConsole.DebugWriteLine("VTOC plugin", "vtocOld.v_part[{0}].p_start = {1}", i,
                                               vtocOld.v_part[i].p_start);

                    AaruConsole.DebugWriteLine("VTOC plugin", "vtocOld.v_part[{0}].p_size = {1}", i,
                                               vtocOld.v_part[i].p_size);

                    AaruConsole.DebugWriteLine("VTOC plugin", "vtocOld.timestamp[{0}] = {1}", i,
                                               DateHandlers.UnixToDateTime(vtocOld.timestamp[i]));
                }
            }
            else
            {
                AaruConsole.DebugWriteLine("VTOC plugin", "vtoc.v_sanity = 0x{0:X8} (should be 0x{1:X8})",
                                           vtoc.v_sanity, VTOC_SANE);

                AaruConsole.DebugWriteLine("VTOC plugin", "vtoc.v_version = {0}", vtoc.v_version);

                AaruConsole.DebugWriteLine("VTOC plugin", "vtoc.v_volume = \"{0}\"",
                                           StringHandlers.CToString(vtoc.v_volume));

                AaruConsole.DebugWriteLine("VTOC plugin", "vtoc.v_pad = {0}", vtoc.v_pad);
                AaruConsole.DebugWriteLine("VTOC plugin", "vtoc.v_nparts = {0}", vtoc.v_nparts);

                for (int i = 0; i < V_NUMPAR; i++)
                {
                    AaruConsole.DebugWriteLine("VTOC plugin", "vtoc.v_part[{0}].p_tag = {1} ({2})", i,
                                               vtoc.v_part[i].p_tag, (ushort)vtoc.v_part[i].p_tag);

                    AaruConsole.DebugWriteLine("VTOC plugin", "vtoc.v_part[{0}].p_flag = {1} ({2})", i,
                                               vtoc.v_part[i].p_flag, (ushort)vtoc.v_part[i].p_flag);

                    AaruConsole.DebugWriteLine("VTOC plugin", "vtoc.v_part[{0}].p_start = {1}", i,
                                               vtoc.v_part[i].p_start);

                    AaruConsole.DebugWriteLine("VTOC plugin", "vtoc.v_part[{0}].p_size = {1}", i,
                                               vtoc.v_part[i].p_size);

                    AaruConsole.DebugWriteLine("VTOC plugin", "vtoc.timestamp[{0}] = {1}", i,
                                               DateHandlers.UnixToDateTime(vtoc.timestamp[i]));
                }
            }

            uint bps;

            partition[] parts;
            int[]       timestamps;

            if (useOld)
            {
                bps        = vtocOld.v_sectorsz;
                parts      = vtocOld.v_part;
                timestamps = vtocOld.timestamp;
            }
            else
            {
                bps        = pd.bytes;
                parts      = vtoc.v_part;
                timestamps = vtoc.timestamp;
            }

            // Check for a partition describing the VTOC whose start is the same as the start we know.
            // This means partition starts are absolute, not relative, to the VTOC position
            for (int i = 0; i < V_NUMPAR; i++)
            {
                if (parts[i].p_tag == pTag.V_BACKUP &&
                    (ulong)parts[i].p_start == sectorOffset)
                {
                    absolute = true;

                    break;
                }
            }

            for (int i = 0; i < V_NUMPAR; i++)
            {
                if (parts[i].p_tag != pTag.V_UNUSED)
                {
                    var part = new Partition
                    {
                        Start    = (ulong)(parts[i].p_start * bps) / imagePlugin.Info.SectorSize,
                        Length   = (ulong)(parts[i].p_size * bps) / imagePlugin.Info.SectorSize,
                        Offset   = (ulong)(parts[i].p_start * bps),
                        Size     = (ulong)(parts[i].p_size * bps),
                        Sequence = (ulong)i,
                        Type     = $"UNIX: {decodeUNIXTAG(parts[i].p_tag, !useOld)}",
                        Scheme   = Name
                    };

                    string info = "";

                    // Apparently old ones are absolute :?
                    if (!useOld &&
                        !absolute)
                    {
                        part.Start  += sectorOffset;
                        part.Offset += sectorOffset * imagePlugin.Info.SectorSize;
                    }

                    if (parts[i].p_flag.HasFlag(pFlag.V_VALID))
                    {
                        info += " (valid)";
                    }

                    if (parts[i].p_flag.HasFlag(pFlag.V_UNMNT))
                    {
                        info += " (unmountable)";
                    }

                    if (parts[i].p_flag.HasFlag(pFlag.V_OPEN))
                    {
                        info += " (open)";
                    }

                    if (parts[i].p_flag.HasFlag(pFlag.V_REMAP))
                    {
                        info += " (alternate sector mapping)";
                    }

                    if (parts[i].p_flag.HasFlag(pFlag.V_RONLY))
                    {
                        info += " (read-only)";
                    }

                    if (timestamps[i] != 0)
                    {
                        info += $" created on {DateHandlers.UnixToDateTime(timestamps[i])}";
                    }

                    part.Description = "UNIX slice" + info + ".";

                    if (part.End < imagePlugin.Info.Sectors)
                    {
                        partitions.Add(part);
                    }
                }
            }

            return(partitions.Count > 0);
        }
Пример #11
0
Файл: EFS.cs Проект: paulyc/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;
            }

            var efsSb = 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>()];

                Array.Copy(sector, 0x200, sbpiece, 0, Marshal.SizeOf <Superblock>());

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

                AaruConsole.DebugWriteLine("EFS plugin", "magic at 0x{0:X3} = 0x{1:X8} (expected 0x{2:X8} or 0x{3:X8})",
                                           0x200, efsSb.sb_magic, EFS_MAGIC, EFS_MAGIC_NEW);
            }
            else
            {
                uint sbSize = (uint)(Marshal.SizeOf <Superblock>() / imagePlugin.Info.SectorSize);

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

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

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

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

                AaruConsole.DebugWriteLine("EFS plugin", "magic at {0} = 0x{1:X8} (expected 0x{2:X8} or 0x{3:X8})", 1,
                                           efsSb.sb_magic, EFS_MAGIC, EFS_MAGIC_NEW);
            }

            if (efsSb.sb_magic != EFS_MAGIC &&
                efsSb.sb_magic != EFS_MAGIC_NEW)
            {
                return;
            }

            var sb = new StringBuilder();

            sb.AppendLine("SGI extent filesystem");

            if (efsSb.sb_magic == EFS_MAGIC_NEW)
            {
                sb.AppendLine("New version");
            }

            sb.AppendFormat("Filesystem size: {0} basic blocks", efsSb.sb_size).AppendLine();
            sb.AppendFormat("First cylinder group starts at block {0}", efsSb.sb_firstcg).AppendLine();
            sb.AppendFormat("Cylinder group size: {0} basic blocks", efsSb.sb_cgfsize).AppendLine();
            sb.AppendFormat("{0} inodes per cylinder group", efsSb.sb_cgisize).AppendLine();
            sb.AppendFormat("{0} sectors per track", efsSb.sb_sectors).AppendLine();
            sb.AppendFormat("{0} heads per cylinder", efsSb.sb_heads).AppendLine();
            sb.AppendFormat("{0} cylinder groups", efsSb.sb_ncg).AppendLine();
            sb.AppendFormat("Volume created on {0}", DateHandlers.UnixToDateTime(efsSb.sb_time)).AppendLine();
            sb.AppendFormat("{0} bytes on bitmap", efsSb.sb_bmsize).AppendLine();
            sb.AppendFormat("{0} free blocks", efsSb.sb_tfree).AppendLine();
            sb.AppendFormat("{0} free inodes", efsSb.sb_tinode).AppendLine();

            if (efsSb.sb_bmblock > 0)
            {
                sb.AppendFormat("Bitmap resides at block {0}", efsSb.sb_bmblock).AppendLine();
            }

            if (efsSb.sb_replsb > 0)
            {
                sb.AppendFormat("Replacement superblock resides at block {0}", efsSb.sb_replsb).AppendLine();
            }

            if (efsSb.sb_lastinode > 0)
            {
                sb.AppendFormat("Last inode allocated: {0}", efsSb.sb_lastinode).AppendLine();
            }

            if (efsSb.sb_dirty > 0)
            {
                sb.AppendLine("Volume is dirty");
            }

            sb.AppendFormat("Checksum: 0x{0:X8}", efsSb.sb_checksum).AppendLine();
            sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(efsSb.sb_fname, Encoding)).AppendLine();
            sb.AppendFormat("Volume pack: {0}", StringHandlers.CToString(efsSb.sb_fpack, Encoding)).AppendLine();

            information = sb.ToString();

            XmlFsType = new FileSystemType
            {
                Type                  = "Extent File System",
                ClusterSize           = 512,
                Clusters              = (ulong)efsSb.sb_size,
                FreeClusters          = (ulong)efsSb.sb_tfree,
                FreeClustersSpecified = true,
                Dirty                 = efsSb.sb_dirty > 0,
                VolumeName            = StringHandlers.CToString(efsSb.sb_fname, Encoding),
                VolumeSerial          = $"{efsSb.sb_checksum:X8}",
                CreationDate          = DateHandlers.UnixToDateTime(efsSb.sb_time),
                CreationDateSpecified = true
            };
        }
Пример #12
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;
            }

            var rbfSb     = new IdSector();
            var rbf9000Sb = new NewIdSector();

            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++;
                }

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

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

                rbfSb     = Marshal.ByteArrayToStructureBigEndian <IdSector>(sector);
                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)
                {
                    break;
                }
            }

            if (rbfSb.dd_sync != RBF_SYNC &&
                rbf9000Sb.rid_sync != RBF_SYNC &&
                rbf9000Sb.rid_sync != RBF_CNYS)
            {
                return;
            }

            if (rbf9000Sb.rid_sync == RBF_CNYS)
            {
                rbf9000Sb = (NewIdSector)Marshal.SwapStructureMembersEndian(rbf9000Sb);
            }

            var sb = new StringBuilder();

            sb.AppendLine("OS-9 Random Block File");

            if (rbf9000Sb.rid_sync == RBF_SYNC)
            {
                sb.AppendFormat("Volume ID: {0:X8}", rbf9000Sb.rid_diskid).AppendLine();
                sb.AppendFormat("{0} blocks in volume", rbf9000Sb.rid_totblocks).AppendLine();
                sb.AppendFormat("{0} cylinders", rbf9000Sb.rid_cylinders).AppendLine();
                sb.AppendFormat("{0} blocks in cylinder 0", rbf9000Sb.rid_cyl0size).AppendLine();
                sb.AppendFormat("{0} blocks per cylinder", rbf9000Sb.rid_cylsize).AppendLine();
                sb.AppendFormat("{0} heads", rbf9000Sb.rid_heads).AppendLine();
                sb.AppendFormat("{0} bytes per block", rbf9000Sb.rid_blocksize).AppendLine();

                // TODO: Convert to flags?
                sb.AppendLine((rbf9000Sb.rid_format & 0x01) == 0x01 ? "Disk is double sided" : "Disk is single sided");

                sb.AppendLine((rbf9000Sb.rid_format & 0x02) == 0x02 ? "Disk is double density"
                                  : "Disk is single density");

                if ((rbf9000Sb.rid_format & 0x10) == 0x10)
                {
                    sb.AppendLine("Disk is 384 TPI");
                }
                else if ((rbf9000Sb.rid_format & 0x08) == 0x08)
                {
                    sb.AppendLine("Disk is 192 TPI");
                }
                else if ((rbf9000Sb.rid_format & 0x04) == 0x04)
                {
                    sb.AppendLine("Disk is 96 TPI or 135 TPI");
                }
                else
                {
                    sb.AppendLine("Disk is 48 TPI");
                }

                sb.AppendFormat("Allocation bitmap descriptor starts at block {0}",
                                rbf9000Sb.rid_bitmap == 0 ? 1 : rbf9000Sb.rid_bitmap).AppendLine();

                if (rbf9000Sb.rid_firstboot > 0)
                {
                    sb.AppendFormat("Debugger descriptor starts at block {0}", rbf9000Sb.rid_firstboot).AppendLine();
                }

                if (rbf9000Sb.rid_bootfile > 0)
                {
                    sb.AppendFormat("Boot file descriptor starts at block {0}", rbf9000Sb.rid_bootfile).AppendLine();
                }

                sb.AppendFormat("Root directory descriptor starts at block {0}", rbf9000Sb.rid_rootdir).AppendLine();

                sb.AppendFormat("Disk is owned by group {0} user {1}", rbf9000Sb.rid_group, rbf9000Sb.rid_owner).
                AppendLine();

                sb.AppendFormat("Volume was created on {0}", DateHandlers.UnixToDateTime(rbf9000Sb.rid_ctime)).
                AppendLine();

                sb.AppendFormat("Volume's identification block was last written on {0}",
                                DateHandlers.UnixToDateTime(rbf9000Sb.rid_mtime)).AppendLine();

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

                XmlFsType = new FileSystemType
                {
                    Type                      = "OS-9 Random Block File",
                    Bootable                  = rbf9000Sb.rid_bootfile > 0,
                    ClusterSize               = rbf9000Sb.rid_blocksize,
                    Clusters                  = rbf9000Sb.rid_totblocks,
                    CreationDate              = DateHandlers.UnixToDateTime(rbf9000Sb.rid_ctime),
                    CreationDateSpecified     = true,
                    ModificationDate          = DateHandlers.UnixToDateTime(rbf9000Sb.rid_mtime),
                    ModificationDateSpecified = true,
                    VolumeName                = StringHandlers.CToString(rbf9000Sb.rid_name, Encoding),
                    VolumeSerial              = $"{rbf9000Sb.rid_diskid:X8}"
                };
            }
            else
            {
                sb.AppendFormat("Volume ID: {0:X4}", rbfSb.dd_dsk).AppendLine();
                sb.AppendFormat("{0} blocks in volume", LSNToUInt32(rbfSb.dd_tot)).AppendLine();
                sb.AppendFormat("{0} tracks", rbfSb.dd_tks).AppendLine();
                sb.AppendFormat("{0} sectors per track", rbfSb.dd_spt).AppendLine();
                sb.AppendFormat("{0} bytes per sector", 256 << rbfSb.dd_lsnsize).AppendLine();

                sb.AppendFormat("{0} sectors per cluster ({1} bytes)", rbfSb.dd_bit,
                                rbfSb.dd_bit * (256 << rbfSb.dd_lsnsize)).AppendLine();

                // TODO: Convert to flags?
                sb.AppendLine((rbfSb.dd_fmt & 0x01) == 0x01 ? "Disk is double sided" : "Disk is single sided");
                sb.AppendLine((rbfSb.dd_fmt & 0x02) == 0x02 ? "Disk is double density" : "Disk is single density");

                if ((rbfSb.dd_fmt & 0x10) == 0x10)
                {
                    sb.AppendLine("Disk is 384 TPI");
                }
                else if ((rbfSb.dd_fmt & 0x08) == 0x08)
                {
                    sb.AppendLine("Disk is 192 TPI");
                }
                else if ((rbfSb.dd_fmt & 0x04) == 0x04)
                {
                    sb.AppendLine("Disk is 96 TPI or 135 TPI");
                }
                else
                {
                    sb.AppendLine("Disk is 48 TPI");
                }

                sb.AppendFormat("Allocation bitmap descriptor starts at block {0}",
                                rbfSb.dd_maplsn == 0 ? 1 : rbfSb.dd_maplsn).AppendLine();

                sb.AppendFormat("{0} bytes in allocation bitmap", rbfSb.dd_map).AppendLine();

                if (LSNToUInt32(rbfSb.dd_bt) > 0 &&
                    rbfSb.dd_bsz > 0)
                {
                    sb.AppendFormat("Boot file starts at block {0} and has {1} bytes", LSNToUInt32(rbfSb.dd_bt),
                                    rbfSb.dd_bsz).AppendLine();
                }

                sb.AppendFormat("Root directory descriptor starts at block {0}", LSNToUInt32(rbfSb.dd_dir)).
                AppendLine();

                sb.AppendFormat("Disk is owned by user {0}", rbfSb.dd_own).AppendLine();
                sb.AppendFormat("Volume was created on {0}", DateHandlers.Os9ToDateTime(rbfSb.dd_dat)).AppendLine();
                sb.AppendFormat("Volume attributes: {0:X2}", rbfSb.dd_att).AppendLine();
                sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(rbfSb.dd_nam, Encoding)).AppendLine();

                sb.AppendFormat("Path descriptor options: {0}", StringHandlers.CToString(rbfSb.dd_opt, Encoding)).
                AppendLine();

                XmlFsType = new FileSystemType
                {
                    Type                  = "OS-9 Random Block File",
                    Bootable              = LSNToUInt32(rbfSb.dd_bt) > 0 && rbfSb.dd_bsz > 0,
                    ClusterSize           = (uint)(rbfSb.dd_bit * (256 << rbfSb.dd_lsnsize)),
                    Clusters              = LSNToUInt32(rbfSb.dd_tot),
                    CreationDate          = DateHandlers.Os9ToDateTime(rbfSb.dd_dat),
                    CreationDateSpecified = true,
                    VolumeName            = StringHandlers.CToString(rbfSb.dd_nam, Encoding),
                    VolumeSerial          = $"{rbfSb.dd_dsk:X4}"
                };
            }

            information = sb.ToString();
        }