Ejemplo n.º 1
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Syncless.Monitor.DTO.FileSystemEvent" /> class for non-rename event, given the specified path, the event change type and the file system change type.
 /// </summary>
 /// <param name="path">A <see cref="string" /> specifying the affected path.</param>
 /// <param name="eventType">A <see cref="Syncless.Monitor.DTO.EventChangeType" /> enum specifying the event change type.</param>
 /// <param name="fileSystemType">A <see cref="Syncless.Monitor.DTO.FileSystemType" /> enum specifying the file system change type.</param>
 public FileSystemEvent(string path, EventChangeType eventType, FileSystemType fileSystemType)
 {
     this._path = path;
     this._oldPath = null;
     this._watchPath = null;
     this._eventType = eventType;
     this._fileSystemType = fileSystemType;
 }
Ejemplo n.º 2
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Syncless.Monitor.DTO.FileSystemEvent" /> class for rename event only, given the old path, the new path and the file system change type.
 /// </summary>
 /// <param name="oldPath">A <see cref="string" /> class specifying the old path.</param>
 /// <param name="newPath">A <see cref="string" /> class specifying the new path.</param>
 /// <param name="fileSystemType">A <see cref="Syncless.Monitor.DTO.FileSystemType" /> enum specifying the file system change type.</param>
 public FileSystemEvent(string oldPath, string newPath, FileSystemType fileSystemType)
 {
     this._oldPath = oldPath;
     this._path = newPath;
     this._watchPath = null;
     this._eventType = EventChangeType.RENAMED;
     this._fileSystemType = fileSystemType;
 }
Ejemplo n.º 3
0
 public GenericFileSystemProvider(FileSystemType type, Func<string, bool> isValidFileFunc,
     Func<string, bool> isContainerFunc, Func<string, IFile> createFunc)
 {
     Type = type;
     IsValidFileFunc = isValidFileFunc;
     IsContainerFunc = isContainerFunc;
     CreateFunc = createFunc;
 }
Ejemplo n.º 4
0
        public Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding,
                           Dictionary <string, string> options, string @namespace)
        {
            device         = imagePlugin;
            this.partition = partition;
            Encoding       = encoding ?? Encoding.GetEncoding("IBM437");

            // As the identification is so complex, just call Identify() and relay on its findings
            if (!Identify(device, partition) || !cpmFound || workingDefinition == null || dpb == null)
            {
                return(Errno.InvalidArgument);
            }

            // Build the software interleaving sector mask
            if (workingDefinition.sides == 1)
            {
                sectorMask = new int[workingDefinition.side1.sectorIds.Length];
                for (int m = 0; m < sectorMask.Length; m++)
                {
                    sectorMask[m] = workingDefinition.side1.sectorIds[m] - workingDefinition.side1.sectorIds[0];
                }
            }
            else
            {
                // Head changes after every track
                if (string.Compare(workingDefinition.order, "SIDES", StringComparison.InvariantCultureIgnoreCase) == 0)
                {
                    sectorMask = new int[workingDefinition.side1.sectorIds.Length +
                                         workingDefinition.side2.sectorIds.Length];
                    for (int m = 0; m < workingDefinition.side1.sectorIds.Length; m++)
                    {
                        sectorMask[m] = workingDefinition.side1.sectorIds[m] - workingDefinition.side1.sectorIds[0];
                    }
                    // Skip first track (first side)
                    for (int m = 0; m < workingDefinition.side2.sectorIds.Length; m++)
                    {
                        sectorMask[m + workingDefinition.side1.sectorIds.Length] =
                            workingDefinition.side2.sectorIds[m] - workingDefinition.side2.sectorIds[0] +
                            workingDefinition.side1.sectorIds.Length;
                    }
                }
                // Head changes after whole side
                else if (string.Compare(workingDefinition.order, "CYLINDERS",
                                        StringComparison.InvariantCultureIgnoreCase) == 0)
                {
                    for (int m = 0; m < workingDefinition.side1.sectorIds.Length; m++)
                    {
                        sectorMask[m] = workingDefinition.side1.sectorIds[m] - workingDefinition.side1.sectorIds[0];
                    }
                    // Skip first track (first side) and first track (second side)
                    for (int m = 0; m < workingDefinition.side1.sectorIds.Length; m++)
                    {
                        sectorMask[m + workingDefinition.side1.sectorIds.Length] =
                            workingDefinition.side1.sectorIds[m] - workingDefinition.side1.sectorIds[0] +
                            workingDefinition.side1.sectorIds.Length +
                            workingDefinition.side2.sectorIds.Length;
                    }

                    // TODO: Implement CYLINDERS ordering
                    DicConsole.DebugWriteLine("CP/M Plugin", "CYLINDERS ordering not yet implemented.");
                    return(Errno.NotImplemented);
                }
                // TODO: Implement COLUMBIA ordering
                else if (string.Compare(workingDefinition.order, "COLUMBIA",
                                        StringComparison.InvariantCultureIgnoreCase) == 0)
                {
                    DicConsole.DebugWriteLine("CP/M Plugin",
                                              "Don't know how to handle COLUMBIA ordering, not proceeding with this definition.");
                    return(Errno.NotImplemented);
                }
                // TODO: Implement EAGLE ordering
                else if (string.Compare(workingDefinition.order, "EAGLE", StringComparison.InvariantCultureIgnoreCase) ==
                         0)
                {
                    DicConsole.DebugWriteLine("CP/M Plugin",
                                              "Don't know how to handle EAGLE ordering, not proceeding with this definition.");
                    return(Errno.NotImplemented);
                }
                else
                {
                    DicConsole.DebugWriteLine("CP/M Plugin",
                                              "Unknown order type \"{0}\", not proceeding with this definition.",
                                              workingDefinition.order);
                    return(Errno.NotSupported);
                }
            }

            // Deinterleave whole volume
            Dictionary <ulong, byte[]> deinterleavedSectors = new Dictionary <ulong, byte[]>();

            if (workingDefinition.sides == 1 ||
                string.Compare(workingDefinition.order, "SIDES", StringComparison.InvariantCultureIgnoreCase) == 0)
            {
                DicConsole.DebugWriteLine("CP/M Plugin", "Deinterleaving whole volume.");

                for (int p = 0; p <= (int)(partition.End - partition.Start); p++)
                {
                    byte[] readSector =
                        device.ReadSector((ulong)((int)partition.Start + p / sectorMask.Length * sectorMask.Length +
                                                  sectorMask[p % sectorMask.Length]));
                    if (workingDefinition.complement)
                    {
                        for (int b = 0; b < readSector.Length; b++)
                        {
                            readSector[b] = (byte)(~readSector[b] & 0xFF);
                        }
                    }

                    deinterleavedSectors.Add((ulong)p, readSector);
                }
            }

            int          blockSize       = 128 << dpb.bsh;
            MemoryStream blockMs         = new MemoryStream();
            ulong        blockNo         = 0;
            int          sectorsPerBlock = 0;
            Dictionary <ulong, byte[]> allocationBlocks = new Dictionary <ulong, byte[]>();

            DicConsole.DebugWriteLine("CP/M Plugin", "Creating allocation blocks.");

            // For each volume sector
            for (ulong a = 0; a < (ulong)deinterleavedSectors.Count; a++)
            {
                deinterleavedSectors.TryGetValue(a, out byte[] sector);

                // May it happen? Just in case, CP/M blocks are smaller than physical sectors
                if (sector.Length > blockSize)
                {
                    for (int i = 0; i < sector.Length / blockSize; i++)
                    {
                        byte[] tmp = new byte[blockSize];
                        Array.Copy(sector, blockSize * i, tmp, 0, blockSize);
                        allocationBlocks.Add(blockNo++, tmp);
                    }
                }
                // CP/M blocks are larger than physical sectors
                else if (sector.Length < blockSize)
                {
                    blockMs.Write(sector, 0, sector.Length);
                    sectorsPerBlock++;

                    if (sectorsPerBlock != blockSize / sector.Length)
                    {
                        continue;
                    }

                    allocationBlocks.Add(blockNo++, blockMs.ToArray());
                    sectorsPerBlock = 0;
                    blockMs         = new MemoryStream();
                }
                // CP/M blocks are same size than physical sectors
                else
                {
                    allocationBlocks.Add(blockNo++, sector);
                }
            }

            DicConsole.DebugWriteLine("CP/M Plugin", "Reading directory.");

            int dirOff;
            int dirSectors = (dpb.drm + 1) * 32 / workingDefinition.bytesPerSector;

            if (workingDefinition.sofs > 0)
            {
                dirOff = workingDefinition.sofs;
            }
            else
            {
                dirOff = workingDefinition.ofs * workingDefinition.sectorsPerTrack;
            }

            // Read the whole directory blocks
            MemoryStream dirMs = new MemoryStream();

            for (int d = 0; d < dirSectors; d++)
            {
                deinterleavedSectors.TryGetValue((ulong)(d + dirOff), out byte[] sector);
                dirMs.Write(sector, 0, sector.Length);
            }

            byte[] directory = dirMs.ToArray();

            if (directory == null)
            {
                return(Errno.InvalidArgument);
            }

            int    dirCnt = 0;
            string file1  = null;
            string file2  = null;
            string file3  = null;
            Dictionary <string, Dictionary <int, List <ushort> > > fileExtents =
                new Dictionary <string, Dictionary <int, List <ushort> > >();

            statCache = new Dictionary <string, FileEntryInfo>();
            cpmStat   = new FileSystemInfo();
            bool atime = false;

            dirList           = new List <string>();
            labelCreationDate = null;
            labelUpdateDate   = null;
            passwordCache     = new Dictionary <string, byte[]>();

            DicConsole.DebugWriteLine("CP/M Plugin", "Traversing directory.");

            // For each directory entry
            for (int dOff = 0; dOff < directory.Length; dOff += 32)
            {
                // Describes a file (does not support PDOS entries with user >= 16, because they're identical to password entries
                if ((directory[dOff] & 0x7F) < 0x10)
                {
                    if (allocationBlocks.Count > 256)
                    {
                        DirectoryEntry16 entry =
                            Marshal.ByteArrayToStructureLittleEndian <DirectoryEntry16>(directory, dOff, 32);

                        bool hidden = (entry.statusUser & 0x80) == 0x80;
                        bool rdOnly = (entry.filename[0] & 0x80) == 0x80 || (entry.extension[0] & 0x80) == 0x80;
                        bool system = (entry.filename[1] & 0x80) == 0x80 || (entry.extension[2] & 0x80) == 0x80;
                        //bool backed = (entry.filename[3] & 0x80) == 0x80 || (entry.extension[3] & 0x80) == 0x80;
                        int user = entry.statusUser & 0x0F;

                        bool validEntry = true;

                        for (int i = 0; i < 8; i++)
                        {
                            entry.filename[i] &= 0x7F;
                            validEntry        &= entry.filename[i] >= 0x20;
                        }

                        for (int i = 0; i < 3; i++)
                        {
                            entry.extension[i] &= 0x7F;
                            validEntry         &= entry.extension[i] >= 0x20;
                        }

                        if (!validEntry)
                        {
                            continue;
                        }

                        string filename  = Encoding.ASCII.GetString(entry.filename).Trim();
                        string extension = Encoding.ASCII.GetString(entry.extension).Trim();

                        // If user is != 0, append user to name to have identical filenames
                        if (user > 0)
                        {
                            filename = $"{user:X1}:{filename}";
                        }
                        if (!string.IsNullOrEmpty(extension))
                        {
                            filename = filename + "." + extension;
                        }

                        int entryNo = (32 * entry.extentCounter + entry.extentCounterHigh) / (dpb.exm + 1);

                        // Do we have a stat for the file already?
                        if (statCache.TryGetValue(filename, out FileEntryInfo fInfo))
                        {
                            statCache.Remove(filename);
                        }
                        else
                        {
                            fInfo = new FileEntryInfo {
                                Attributes = new FileAttributes()
                            }
                        };

                        // And any extent?
                        if (fileExtents.TryGetValue(filename, out Dictionary <int, List <ushort> > extentBlocks))
                        {
                            fileExtents.Remove(filename);
                        }
                        else
                        {
                            extentBlocks = new Dictionary <int, List <ushort> >();
                        }

                        // Do we already have this extent? Should never happen
                        if (extentBlocks.TryGetValue(entryNo, out List <ushort> blocks))
                        {
                            extentBlocks.Remove(entryNo);
                        }
                        else
                        {
                            blocks = new List <ushort>();
                        }

                        // Attributes
                        if (hidden)
                        {
                            fInfo.Attributes |= FileAttributes.Hidden;
                        }
                        if (rdOnly)
                        {
                            fInfo.Attributes |= FileAttributes.ReadOnly;
                        }
                        if (system)
                        {
                            fInfo.Attributes |= FileAttributes.System;
                        }

                        // Supposedly there is a value in the directory entry telling how many blocks are designated in
                        // this entry. However some implementations tend to do whatever they wish, but none will ever
                        // allocate block 0 for a file because that's where the directory resides.
                        // There is also a field telling how many bytes are used in the last block, but its meaning is
                        // non-standard so we must ignore it.
                        foreach (ushort blk in entry.allocations.Where(blk => !blocks.Contains(blk) && blk != 0))
                        {
                            blocks.Add(blk);
                        }

                        // Save the file
                        fInfo.UID = (ulong)user;
                        extentBlocks.Add(entryNo, blocks);
                        fileExtents.Add(filename, extentBlocks);
                        statCache.Add(filename, fInfo);

                        // Add the file to the directory listing
                        if (!dirList.Contains(filename))
                        {
                            dirList.Add(filename);
                        }

                        // Count entries 3 by 3 for timestamps
                        switch (dirCnt % 3)
                        {
                        case 0:
                            file1 = filename;
                            break;

                        case 1:
                            file2 = filename;
                            break;

                        case 2:
                            file3 = filename;
                            break;
                        }

                        dirCnt++;
                    }
                    else
                    {
                        DirectoryEntry entry =
                            Marshal.ByteArrayToStructureLittleEndian <DirectoryEntry>(directory, dOff, 32);

                        bool hidden = (entry.statusUser & 0x80) == 0x80;
                        bool rdOnly = (entry.filename[0] & 0x80) == 0x80 || (entry.extension[0] & 0x80) == 0x80;
                        bool system = (entry.filename[1] & 0x80) == 0x80 || (entry.extension[2] & 0x80) == 0x80;
                        //bool backed = (entry.filename[3] & 0x80) == 0x80 || (entry.extension[3] & 0x80) == 0x80;
                        int user = entry.statusUser & 0x0F;

                        bool validEntry = true;

                        for (int i = 0; i < 8; i++)
                        {
                            entry.filename[i] &= 0x7F;
                            validEntry        &= entry.filename[i] >= 0x20;
                        }

                        for (int i = 0; i < 3; i++)
                        {
                            entry.extension[i] &= 0x7F;
                            validEntry         &= entry.extension[i] >= 0x20;
                        }

                        if (!validEntry)
                        {
                            continue;
                        }

                        string filename  = Encoding.ASCII.GetString(entry.filename).Trim();
                        string extension = Encoding.ASCII.GetString(entry.extension).Trim();

                        // If user is != 0, append user to name to have identical filenames
                        if (user > 0)
                        {
                            filename = $"{user:X1}:{filename}";
                        }
                        if (!string.IsNullOrEmpty(extension))
                        {
                            filename = filename + "." + extension;
                        }

                        int entryNo = (32 * entry.extentCounterHigh + entry.extentCounter) / (dpb.exm + 1);

                        // Do we have a stat for the file already?
                        if (statCache.TryGetValue(filename, out FileEntryInfo fInfo))
                        {
                            statCache.Remove(filename);
                        }
                        else
                        {
                            fInfo = new FileEntryInfo {
                                Attributes = new FileAttributes()
                            }
                        };

                        // And any extent?
                        if (fileExtents.TryGetValue(filename, out Dictionary <int, List <ushort> > extentBlocks))
                        {
                            fileExtents.Remove(filename);
                        }
                        else
                        {
                            extentBlocks = new Dictionary <int, List <ushort> >();
                        }

                        // Do we already have this extent? Should never happen
                        if (extentBlocks.TryGetValue(entryNo, out List <ushort> blocks))
                        {
                            extentBlocks.Remove(entryNo);
                        }
                        else
                        {
                            blocks = new List <ushort>();
                        }

                        // Attributes
                        if (hidden)
                        {
                            fInfo.Attributes |= FileAttributes.Hidden;
                        }
                        if (rdOnly)
                        {
                            fInfo.Attributes |= FileAttributes.ReadOnly;
                        }
                        if (system)
                        {
                            fInfo.Attributes |= FileAttributes.System;
                        }

                        // Supposedly there is a value in the directory entry telling how many blocks are designated in
                        // this entry. However some implementations tend to do whatever they wish, but none will ever
                        // allocate block 0 for a file because that's where the directory resides.
                        // There is also a field telling how many bytes are used in the last block, but its meaning is
                        // non-standard so we must ignore it.
                        foreach (ushort blk in entry.allocations.Cast <ushort>()
                                 .Where(blk => !blocks.Contains(blk) && blk != 0))
                        {
                            blocks.Add(blk);
                        }

                        // Save the file
                        fInfo.UID = (ulong)user;
                        extentBlocks.Add(entryNo, blocks);
                        fileExtents.Add(filename, extentBlocks);
                        statCache.Add(filename, fInfo);

                        // Add the file to the directory listing
                        if (!dirList.Contains(filename))
                        {
                            dirList.Add(filename);
                        }

                        // Count entries 3 by 3 for timestamps
                        switch (dirCnt % 3)
                        {
                        case 0:
                            file1 = filename;
                            break;

                        case 1:
                            file2 = filename;
                            break;

                        case 2:
                            file3 = filename;
                            break;
                        }

                        dirCnt++;
                    }
                }
                // A password entry (or a file entry in PDOS, but this does not handle that case)
                else if ((directory[dOff] & 0x7F) >= 0x10 && (directory[dOff] & 0x7F) < 0x20)
                {
                    PasswordEntry entry = Marshal.ByteArrayToStructureLittleEndian <PasswordEntry>(directory, dOff, 32);

                    int user = entry.userNumber & 0x0F;

                    for (int i = 0; i < 8; i++)
                    {
                        entry.filename[i] &= 0x7F;
                    }
                    for (int i = 0; i < 3; i++)
                    {
                        entry.extension[i] &= 0x7F;
                    }

                    string filename  = Encoding.ASCII.GetString(entry.filename).Trim();
                    string extension = Encoding.ASCII.GetString(entry.extension).Trim();

                    // If user is != 0, append user to name to have identical filenames
                    if (user > 0)
                    {
                        filename = $"{user:X1}:{filename}";
                    }
                    if (!string.IsNullOrEmpty(extension))
                    {
                        filename = filename + "." + extension;
                    }

                    // Do not repeat passwords
                    if (passwordCache.ContainsKey(filename))
                    {
                        passwordCache.Remove(filename);
                    }

                    // Copy whole password entry
                    byte[] tmp = new byte[32];
                    Array.Copy(directory, dOff, tmp, 0, 32);
                    passwordCache.Add(filename, tmp);

                    // Count entries 3 by 3 for timestamps
                    switch (dirCnt % 3)
                    {
                    case 0:
                        file1 = filename;
                        break;

                    case 1:
                        file2 = filename;
                        break;

                    case 2:
                        file3 = filename;
                        break;
                    }

                    dirCnt++;
                }
                // Volume label and password entry. Volume password is ignored.
                else
                {
                    switch (directory[dOff] & 0x7F)
                    {
                    case 0x20:
                        LabelEntry labelEntry =
                            Marshal.ByteArrayToStructureLittleEndian <LabelEntry>(directory, dOff, 32);

                        // The volume label defines if one of the fields in CP/M 3 timestamp is a creation or an
                        // access time
                        atime |= (labelEntry.flags & 0x40) == 0x40;

                        label             = Encoding.ASCII.GetString(directory, dOff + 1, 11).Trim();
                        labelCreationDate = new byte[4];
                        labelUpdateDate   = new byte[4];
                        Array.Copy(directory, dOff + 24, labelCreationDate, 0, 4);
                        Array.Copy(directory, dOff + 28, labelUpdateDate, 0, 4);

                        // Count entries 3 by 3 for timestamps
                        switch (dirCnt % 3)
                        {
                        case 0:
                            file1 = null;
                            break;

                        case 1:
                            file2 = null;
                            break;

                        case 2:
                            file3 = null;
                            break;
                        }

                        dirCnt++;
                        break;

                    case 0x21:
                        if (directory[dOff + 10] == 0x00 && directory[dOff + 20] == 0x00 &&
                            directory[dOff + 30] == 0x00 && directory[dOff + 31] == 0x00)
                        {
                            DateEntry dateEntry =
                                Marshal.ByteArrayToStructureLittleEndian <DateEntry>(directory, dOff, 32);

                            FileEntryInfo fInfo;

                            // Entry contains timestamps for last 3 entries, whatever the kind they are.
                            if (!string.IsNullOrEmpty(file1))
                            {
                                if (statCache.TryGetValue(file1, out fInfo))
                                {
                                    statCache.Remove(file1);
                                }
                                else
                                {
                                    fInfo = new FileEntryInfo();
                                }

                                if (atime)
                                {
                                    fInfo.AccessTime = DateHandlers.CpmToDateTime(dateEntry.date1);
                                }
                                else
                                {
                                    fInfo.CreationTime = DateHandlers.CpmToDateTime(dateEntry.date1);
                                }

                                fInfo.LastWriteTime = DateHandlers.CpmToDateTime(dateEntry.date2);

                                statCache.Add(file1, fInfo);
                            }

                            if (!string.IsNullOrEmpty(file2))
                            {
                                if (statCache.TryGetValue(file2, out fInfo))
                                {
                                    statCache.Remove(file2);
                                }
                                else
                                {
                                    fInfo = new FileEntryInfo();
                                }

                                if (atime)
                                {
                                    fInfo.AccessTime = DateHandlers.CpmToDateTime(dateEntry.date3);
                                }
                                else
                                {
                                    fInfo.CreationTime = DateHandlers.CpmToDateTime(dateEntry.date3);
                                }

                                fInfo.LastWriteTime = DateHandlers.CpmToDateTime(dateEntry.date4);

                                statCache.Add(file2, fInfo);
                            }

                            if (!string.IsNullOrEmpty(file3))
                            {
                                if (statCache.TryGetValue(file3, out fInfo))
                                {
                                    statCache.Remove(file3);
                                }
                                else
                                {
                                    fInfo = new FileEntryInfo();
                                }

                                if (atime)
                                {
                                    fInfo.AccessTime = DateHandlers.CpmToDateTime(dateEntry.date5);
                                }
                                else
                                {
                                    fInfo.CreationTime = DateHandlers.CpmToDateTime(dateEntry.date5);
                                }

                                fInfo.LastWriteTime = DateHandlers.CpmToDateTime(dateEntry.date6);

                                statCache.Add(file3, fInfo);
                            }

                            file1  = null;
                            file2  = null;
                            file3  = null;
                            dirCnt = 0;
                        }
                        // However, if this byte is 0, timestamp is in Z80DOS or DOS+ format
                        else if (directory[dOff + 1] == 0x00)
                        {
                            TrdPartyDateEntry trdPartyDateEntry =
                                Marshal.ByteArrayToStructureLittleEndian <TrdPartyDateEntry>(directory, dOff, 32);

                            FileEntryInfo fInfo;

                            // Entry contains timestamps for last 3 entries, whatever the kind they are.
                            if (!string.IsNullOrEmpty(file1))
                            {
                                if (statCache.TryGetValue(file1, out fInfo))
                                {
                                    statCache.Remove(file1);
                                }
                                else
                                {
                                    fInfo = new FileEntryInfo();
                                }

                                byte[] ctime = new byte[4];
                                ctime[0] = trdPartyDateEntry.create1[0];
                                ctime[1] = trdPartyDateEntry.create1[1];

                                fInfo.AccessTime    = DateHandlers.CpmToDateTime(trdPartyDateEntry.access1);
                                fInfo.CreationTime  = DateHandlers.CpmToDateTime(ctime);
                                fInfo.LastWriteTime = DateHandlers.CpmToDateTime(trdPartyDateEntry.modify1);

                                statCache.Add(file1, fInfo);
                            }

                            if (!string.IsNullOrEmpty(file2))
                            {
                                if (statCache.TryGetValue(file2, out fInfo))
                                {
                                    statCache.Remove(file2);
                                }
                                else
                                {
                                    fInfo = new FileEntryInfo();
                                }

                                byte[] ctime = new byte[4];
                                ctime[0] = trdPartyDateEntry.create2[0];
                                ctime[1] = trdPartyDateEntry.create2[1];

                                fInfo.AccessTime    = DateHandlers.CpmToDateTime(trdPartyDateEntry.access2);
                                fInfo.CreationTime  = DateHandlers.CpmToDateTime(ctime);
                                fInfo.LastWriteTime = DateHandlers.CpmToDateTime(trdPartyDateEntry.modify2);

                                statCache.Add(file2, fInfo);
                            }

                            if (!string.IsNullOrEmpty(file3))
                            {
                                if (statCache.TryGetValue(file1, out fInfo))
                                {
                                    statCache.Remove(file3);
                                }
                                else
                                {
                                    fInfo = new FileEntryInfo();
                                }

                                byte[] ctime = new byte[4];
                                ctime[0] = trdPartyDateEntry.create3[0];
                                ctime[1] = trdPartyDateEntry.create3[1];

                                fInfo.AccessTime    = DateHandlers.CpmToDateTime(trdPartyDateEntry.access3);
                                fInfo.CreationTime  = DateHandlers.CpmToDateTime(ctime);
                                fInfo.LastWriteTime = DateHandlers.CpmToDateTime(trdPartyDateEntry.modify3);

                                statCache.Add(file3, fInfo);
                            }

                            file1  = null;
                            file2  = null;
                            file3  = null;
                            dirCnt = 0;
                        }

                        break;
                    }
                }
            }

            // Cache all files. As CP/M maximum volume size is 8 Mib
            // this should not be a problem
            DicConsole.DebugWriteLine("CP/M Plugin", "Reading files.");
            long usedBlocks = 0;

            fileCache = new Dictionary <string, byte[]>();
            foreach (string filename in dirList)
            {
                MemoryStream fileMs = new MemoryStream();

                if (statCache.TryGetValue(filename, out FileEntryInfo fInfo))
                {
                    statCache.Remove(filename);
                }

                fInfo.Blocks = 0;

                if (fileExtents.TryGetValue(filename, out Dictionary <int, List <ushort> > extents))
                {
                    for (int ex = 0; ex < extents.Count; ex++)
                    {
                        if (!extents.TryGetValue(ex, out List <ushort> alBlks))
                        {
                            continue;
                        }

                        foreach (ushort alBlk in alBlks)
                        {
                            allocationBlocks.TryGetValue(alBlk, out byte[] blk);
                            fileMs.Write(blk, 0, blk.Length);
                            fInfo.Blocks++;
                        }
                    }
                }

                // If you insist to call CP/M "extent based"
                fInfo.Attributes |= FileAttributes.Extents;
                fInfo.BlockSize   = blockSize;
                fInfo.Length      = fileMs.Length;
                cpmStat.Files++;
                usedBlocks += fInfo.Blocks;

                statCache.Add(filename, fInfo);
                fileCache.Add(filename, fileMs.ToArray());
            }

            decodedPasswordCache = new Dictionary <string, byte[]>();
            // For each stored password, store a decoded version of it
            if (passwordCache.Count > 0)
            {
                foreach (KeyValuePair <string, byte[]> kvp in passwordCache)
                {
                    byte[] tmp = new byte[8];
                    Array.Copy(kvp.Value, 16, tmp, 0, 8);
                    for (int t = 0; t < 8; t++)
                    {
                        tmp[t] ^= kvp.Value[13];
                    }

                    decodedPasswordCache.Add(kvp.Key, tmp);
                }
            }

            // Generate statfs.
            cpmStat.Blocks         = (ulong)(dpb.dsm + 1);
            cpmStat.FilenameLength = 11;
            cpmStat.Files          = (ulong)fileCache.Count;
            cpmStat.FreeBlocks     = cpmStat.Blocks - (ulong)usedBlocks;
            cpmStat.PluginId       = Id;
            cpmStat.Type           = "CP/M filesystem";

            // Generate XML info
            XmlFsType = new FileSystemType
            {
                Clusters              = cpmStat.Blocks,
                ClusterSize           = (uint)blockSize,
                Files                 = (ulong)fileCache.Count,
                FilesSpecified        = true,
                FreeClusters          = cpmStat.FreeBlocks,
                FreeClustersSpecified = true,
                Type = "CP/M filesystem"
            };
            if (labelCreationDate != null)
            {
                XmlFsType.CreationDate          = DateHandlers.CpmToDateTime(labelCreationDate);
                XmlFsType.CreationDateSpecified = true;
            }

            if (labelUpdateDate != null)
            {
                XmlFsType.ModificationDate          = DateHandlers.CpmToDateTime(labelUpdateDate);
                XmlFsType.ModificationDateSpecified = true;
            }

            if (!string.IsNullOrEmpty(label))
            {
                XmlFsType.VolumeName = label;
            }

            mounted = true;
            return(Errno.NoError);
        }
Ejemplo n.º 5
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            // UDF is always UTF-8
            Encoding = Encoding.UTF8;
            byte[] sector;

            var sbInformation = new StringBuilder();

            sbInformation.AppendLine("Universal Disk Format");

            var anchor = new AnchorVolumeDescriptorPointer();

            // All positions where anchor may reside, with the ratio between 512 and 2048bps
            ulong[][] positions =
            {
                new ulong[]
                {
                    256, 1
                },
                new ulong[]
                {
                    512, 1
                },
                new ulong[]
                {
                    partition.End - 256, 1
                },
                new ulong[]
                {
                    partition.End, 1
                },
                new ulong[]
                {
                    1024, 4
                },
                new ulong[]
                {
                    2048, 4
                },
                new ulong[]
                {
                    partition.End - 1024, 4
                },
                new ulong[]
                {
                    partition.End - 4, 4
                }
            };

            uint ratio = 1;

            foreach(ulong[] position in positions)
            {
                sector = imagePlugin.ReadSectors(position[0], (uint)position[1]);
                anchor = Marshal.ByteArrayToStructureLittleEndian<AnchorVolumeDescriptorPointer>(sector);

                if(anchor.tag.tagIdentifier != TagIdentifier.AnchorVolumeDescriptorPointer ||
                   anchor.tag.tagLocation != position[0] / position[1] ||
                   anchor.mainVolumeDescriptorSequenceExtent.location + partition.Start >= partition.End)
                    continue;

                ratio = (uint)position[1];

                break;
            }

            ulong count = 0;

            var pvd    = new PrimaryVolumeDescriptor();
            var lvd    = new LogicalVolumeDescriptor();
            var lvid   = new LogicalVolumeIntegrityDescriptor();
            var lvidiu = new LogicalVolumeIntegrityDescriptorImplementationUse();

            while(count < 256)
            {
                sector =
                    imagePlugin.
                        ReadSectors(partition.Start + (anchor.mainVolumeDescriptorSequenceExtent.location * ratio) + (count * ratio),
                                    ratio);

                var  tagId    = (TagIdentifier)BitConverter.ToUInt16(sector, 0);
                uint location = BitConverter.ToUInt32(sector, 0x0C);

                if(location == (partition.Start / ratio) + anchor.mainVolumeDescriptorSequenceExtent.location + count)
                {
                    if(tagId == TagIdentifier.TerminatingDescriptor)
                        break;

                    switch(tagId)
                    {
                        case TagIdentifier.LogicalVolumeDescriptor:
                            lvd = Marshal.ByteArrayToStructureLittleEndian<LogicalVolumeDescriptor>(sector);

                            break;
                        case TagIdentifier.PrimaryVolumeDescriptor:
                            pvd = Marshal.ByteArrayToStructureLittleEndian<PrimaryVolumeDescriptor>(sector);

                            break;
                    }
                }
                else
                    break;

                count++;
            }

            sector = imagePlugin.ReadSectors(lvd.integritySequenceExtent.location * ratio, ratio);
            lvid   = Marshal.ByteArrayToStructureLittleEndian<LogicalVolumeIntegrityDescriptor>(sector);

            if(lvid.tag.tagIdentifier == TagIdentifier.LogicalVolumeIntegrityDescriptor &&
               lvid.tag.tagLocation   == lvd.integritySequenceExtent.location)
                lvidiu =
                    Marshal.ByteArrayToStructureLittleEndian<LogicalVolumeIntegrityDescriptorImplementationUse>(sector,
                        (int)((lvid.numberOfPartitions * 8) + 80),
                        System.Runtime.InteropServices.Marshal.SizeOf(lvidiu));
            else
                lvid = new LogicalVolumeIntegrityDescriptor();

            sbInformation.AppendFormat("Volume is number {0} of {1}", pvd.volumeSequenceNumber,
                                       pvd.maximumVolumeSequenceNumber).AppendLine();

            sbInformation.AppendFormat("Volume set identifier: {0}",
                                       StringHandlers.DecompressUnicode(pvd.volumeSetIdentifier)).AppendLine();

            sbInformation.
                AppendFormat("Volume name: {0}", StringHandlers.DecompressUnicode(lvd.logicalVolumeIdentifier)).
                AppendLine();

            sbInformation.AppendFormat("Volume uses {0} bytes per block", lvd.logicalBlockSize).AppendLine();

            sbInformation.AppendFormat("Volume was last written in {0}", EcmaToDateTime(lvid.recordingDateTime)).
                          AppendLine();

            sbInformation.AppendFormat("Volume contains {0} partitions", lvid.numberOfPartitions).AppendLine();

            sbInformation.
                AppendFormat("Volume contains {0} files and {1} directories", lvidiu.files, lvidiu.directories).
                AppendLine();

            sbInformation.AppendFormat("Volume conforms to {0}",
                                       Encoding.GetString(lvd.domainIdentifier.identifier).TrimEnd('\u0000')).
                          AppendLine();

            sbInformation.AppendFormat("Volume was last written by: {0}",
                                       Encoding.GetString(pvd.implementationIdentifier.identifier).TrimEnd('\u0000')).
                          AppendLine();

            sbInformation.AppendFormat("Volume requires UDF version {0}.{1:X2} to be read",
                                       Convert.ToInt32($"{(lvidiu.minimumReadUDF & 0xFF00) >> 8}", 10),
                                       Convert.ToInt32($"{lvidiu.minimumReadUDF & 0xFF}", 10)).AppendLine();

            sbInformation.AppendFormat("Volume requires UDF version {0}.{1:X2} to be written to",
                                       Convert.ToInt32($"{(lvidiu.minimumWriteUDF & 0xFF00) >> 8}", 10),
                                       Convert.ToInt32($"{lvidiu.minimumWriteUDF & 0xFF}", 10)).AppendLine();

            sbInformation.AppendFormat("Volume cannot be written by any UDF version higher than {0}.{1:X2}",
                                       Convert.ToInt32($"{(lvidiu.maximumWriteUDF & 0xFF00) >> 8}", 10),
                                       Convert.ToInt32($"{lvidiu.maximumWriteUDF & 0xFF}", 10)).AppendLine();

            XmlFsType = new FileSystemType
            {
                Type =
                    $"UDF v{Convert.ToInt32($"{(lvidiu.maximumWriteUDF & 0xFF00) >> 8}", 10)}.{Convert.ToInt32($"{lvidiu.maximumWriteUDF & 0xFF}", 10):X2}",
                ApplicationIdentifier = Encoding.GetString(pvd.implementationIdentifier.identifier).TrimEnd('\u0000'),
                ClusterSize = lvd.logicalBlockSize,
                ModificationDate = EcmaToDateTime(lvid.recordingDateTime),
                ModificationDateSpecified = true,
                Files = lvidiu.files,
                FilesSpecified = true,
                VolumeName = StringHandlers.DecompressUnicode(lvd.logicalVolumeIdentifier),
                VolumeSetIdentifier = StringHandlers.DecompressUnicode(pvd.volumeSetIdentifier),
                VolumeSerial = StringHandlers.DecompressUnicode(pvd.volumeSetIdentifier),
                SystemIdentifier = Encoding.GetString(pvd.implementationIdentifier.identifier).TrimEnd('\u0000')
            };

            XmlFsType.Clusters = (partition.End - partition.Start + 1) * imagePlugin.Info.SectorSize /
                                 XmlFsType.ClusterSize;

            information = sbInformation.ToString();
        }
Ejemplo n.º 6
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            Encoding    = encoding ?? Encoding.GetEncoding("iso-8859-15");
            information = "";
            byte[] sector = imagePlugin.ReadSector(partition.Start + 1);
            if (sector.Length < 512)
            {
                return;
            }

            IntPtr sbPtr = Marshal.AllocHGlobal(512);

            Marshal.Copy(sector, 0, sbPtr, 512);
            QNX4_Superblock qnxSb = (QNX4_Superblock)Marshal.PtrToStructure(sbPtr, typeof(QNX4_Superblock));

            Marshal.FreeHGlobal(sbPtr);

            // Too much useless information

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

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

            XmlFsType = new FileSystemType
            {
                Type                      = "QNX4 filesystem",
                Clusters                  = (long)partition.Length,
                ClusterSize               = 512,
                CreationDate              = DateHandlers.UnixUnsignedToDateTime(qnxSb.rootDir.di_ftime),
                CreationDateSpecified     = true,
                ModificationDate          = DateHandlers.UnixUnsignedToDateTime(qnxSb.rootDir.di_mtime),
                ModificationDateSpecified = true
            };
            XmlFsType.Bootable |= qnxSb.boot.di_size != 0 || qnxSb.altBoot.di_size != 0;
        }
Ejemplo n.º 7
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            Encoding    = Encoding.BigEndianUnicode;
            information = "";

            var vh = new VolumeHeader();

            ulong hfspOffset;
            bool  wrapped;

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

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

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

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

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

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

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

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

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

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

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

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

            var sb = new StringBuilder();

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                XmlFsType = new FileSystemType();

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

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

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

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

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

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

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

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

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

            information = sb.ToString();
        }
Ejemplo n.º 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;
            }

            XFS_Superblock xfsSb = new XFS_Superblock();

            // Misaligned
            if (imagePlugin.Info.XmlMediaType == XmlMediaType.OpticalDisc)
            {
                uint sbSize = (uint)((Marshal.SizeOf(xfsSb) + 0x400) / imagePlugin.Info.SectorSize);
                if ((Marshal.SizeOf(xfsSb) + 0x400) % imagePlugin.Info.SectorSize != 0)
                {
                    sbSize++;
                }

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

                byte[] sbpiece = new byte[Marshal.SizeOf(xfsSb)];

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

                    xfsSb = BigEndianMarshal.ByteArrayToStructureBigEndian <XFS_Superblock>(sbpiece);

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

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

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

                    xfsSb = BigEndianMarshal.ByteArrayToStructureBigEndian <XFS_Superblock>(sector);

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

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

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

            StringBuilder sb = new StringBuilder();

            sb.AppendLine("XFS filesystem");
            sb.AppendFormat("Filesystem version {0}", xfsSb.version & 0xF).AppendLine();
            sb.AppendFormat("{0} bytes per sector", xfsSb.sectsize).AppendLine();
            sb.AppendFormat("{0} bytes per block", xfsSb.blocksize).AppendLine();
            sb.AppendFormat("{0} bytes per inode", xfsSb.inodesize).AppendLine();
            sb.AppendFormat("{0} data blocks in volume, {1} free", xfsSb.dblocks, xfsSb.fdblocks).AppendLine();
            sb.AppendFormat("{0} blocks per allocation group", xfsSb.agblocks).AppendLine();
            sb.AppendFormat("{0} allocation groups in volume", xfsSb.agcount).AppendLine();
            sb.AppendFormat("{0} inodes in volume, {1} free", xfsSb.icount, xfsSb.ifree).AppendLine();
            if (xfsSb.inprogress > 0)
            {
                sb.AppendLine("fsck in progress");
            }
            sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(xfsSb.fname, Encoding)).AppendLine();
            sb.AppendFormat("Volume UUID: {0}", xfsSb.uuid).AppendLine();

            information = sb.ToString();

            XmlFsType = new FileSystemType
            {
                Type                  = "XFS filesystem",
                ClusterSize           = (int)xfsSb.blocksize,
                Clusters              = (long)xfsSb.dblocks,
                FreeClusters          = (long)xfsSb.fdblocks,
                FreeClustersSpecified = true,
                Files                 = (long)(xfsSb.icount - xfsSb.ifree),
                FilesSpecified        = true,
                Dirty                 = xfsSb.inprogress > 0,
                VolumeName            = StringHandlers.CToString(xfsSb.fname, Encoding),
                VolumeSerial          = xfsSb.uuid.ToString()
            };
        }
Ejemplo n.º 9
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            Encoding    = encoding ?? Encoding.GetEncoding("iso-8859-15");
            information = "";

            StringBuilder sb = new StringBuilder();

            BeSuperBlock besb = new BeSuperBlock();

            byte[] sbSector = imagePlugin.ReadSector(0 + partition.Start);

            bool littleEndian;

            besb.magic1 = BigEndianBitConverter.ToUInt32(sbSector, 0x20);
            if (besb.magic1 == BEFS_MAGIC1 || besb.magic1 == BEFS_CIGAM1) // Magic is at offset
            {
                littleEndian = besb.magic1 == BEFS_CIGAM1;
            }
            else
            {
                sbSector    = imagePlugin.ReadSector(1 + partition.Start);
                besb.magic1 = BigEndianBitConverter.ToUInt32(sbSector, 0x20);

                if (besb.magic1 == BEFS_MAGIC1 || besb.magic1 == BEFS_CIGAM1) // There is a boot sector
                {
                    littleEndian = besb.magic1 == BEFS_CIGAM1;
                }
                else if (sbSector.Length >= 0x400)
                {
                    byte[] temp = imagePlugin.ReadSector(0 + partition.Start);
                    besb.magic1 = BigEndianBitConverter.ToUInt32(temp, 0x220);

                    if (besb.magic1 == BEFS_MAGIC1 || besb.magic1 == BEFS_CIGAM1) // There is a boot sector
                    {
                        littleEndian = besb.magic1 == BEFS_CIGAM1;
                        sbSector     = new byte[0x200];
                        Array.Copy(temp, 0x200, sbSector, 0, 0x200);
                    }
                    else
                    {
                        return;
                    }
                }
                else
                {
                    return;
                }
            }

            if (littleEndian)
            {
                GCHandle handle = GCHandle.Alloc(sbSector, GCHandleType.Pinned);
                besb = (BeSuperBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(BeSuperBlock));
                handle.Free();
            }
            else
            {
                besb = BigEndianMarshal.ByteArrayToStructureBigEndian <BeSuperBlock>(sbSector);
            }

            sb.AppendLine(littleEndian ? "Little-endian BeFS" : "Big-endian BeFS");

            if (besb.magic1 != BEFS_MAGIC1 || besb.fs_byte_order != BEFS_ENDIAN ||
                besb.magic2 != BEFS_MAGIC2 ||
                besb.magic3 != BEFS_MAGIC3 || besb.root_dir_len != 1 ||
                besb.indices_len != 1 ||
                1 << (int)besb.block_shift != besb.block_size)
            {
                sb.AppendLine("Superblock seems corrupt, following information may be incorrect");
                sb.AppendFormat("Magic 1: 0x{0:X8} (Should be 0x42465331)", besb.magic1).AppendLine();
                sb.AppendFormat("Magic 2: 0x{0:X8} (Should be 0xDD121031)", besb.magic2).AppendLine();
                sb.AppendFormat("Magic 3: 0x{0:X8} (Should be 0x15B6830E)", besb.magic3).AppendLine();
                sb.AppendFormat("Filesystem endianness: 0x{0:X8} (Should be 0x42494745)", besb.fs_byte_order)
                .AppendLine();
                sb.AppendFormat("Root folder's i-node size: {0} blocks (Should be 1)", besb.root_dir_len).AppendLine();
                sb.AppendFormat("Indices' i-node size: {0} blocks (Should be 1)", besb.indices_len).AppendLine();
                sb.AppendFormat("1 << block_shift == block_size => 1 << {0} == {1} (Should be {2})", besb.block_shift,
                                1 << (int)besb.block_shift, besb.block_size).AppendLine();
            }

            switch (besb.flags)
            {
            case BEFS_CLEAN:
                sb.AppendLine(besb.log_start == besb.log_end ? "Filesystem is clean" : "Filesystem is dirty");
                break;

            case BEFS_DIRTY:
                sb.AppendLine("Filesystem is dirty");
                break;

            default:
                sb.AppendFormat("Unknown flags: {0:X8}", besb.flags).AppendLine();
                break;
            }

            sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(besb.name, Encoding)).AppendLine();
            sb.AppendFormat("{0} bytes per block", besb.block_size).AppendLine();
            sb.AppendFormat("{0} blocks in volume ({1} bytes)", besb.num_blocks, besb.num_blocks * besb.block_size)
            .AppendLine();
            sb.AppendFormat("{0} used blocks ({1} bytes)", besb.used_blocks, besb.used_blocks * besb.block_size)
            .AppendLine();
            sb.AppendFormat("{0} bytes per i-node", besb.inode_size).AppendLine();
            sb.AppendFormat("{0} blocks per allocation group ({1} bytes)", besb.blocks_per_ag,
                            besb.blocks_per_ag * besb.block_size).AppendLine();
            sb.AppendFormat("{0} allocation groups in volume", besb.num_ags).AppendLine();
            sb.AppendFormat("Journal resides in block {0} of allocation group {1} and runs for {2} blocks ({3} bytes)",
                            besb.log_blocks_start, besb.log_blocks_ag, besb.log_blocks_len,
                            besb.log_blocks_len * besb.block_size).AppendLine();
            sb.AppendFormat("Journal starts in byte {0} and ends in byte {1}", besb.log_start, besb.log_end)
            .AppendLine();
            sb
            .AppendFormat("Root folder's i-node resides in block {0} of allocation group {1} and runs for {2} blocks ({3} bytes)",
                          besb.root_dir_start, besb.root_dir_ag, besb.root_dir_len,
                          besb.root_dir_len * besb.block_size).AppendLine();
            sb
            .AppendFormat("Indices' i-node resides in block {0} of allocation group {1} and runs for {2} blocks ({3} bytes)",
                          besb.indices_start, besb.indices_ag, besb.indices_len, besb.indices_len * besb.block_size)
            .AppendLine();

            information = sb.ToString();

            XmlFsType = new FileSystemType
            {
                Clusters              = besb.num_blocks,
                ClusterSize           = (int)besb.block_size,
                Dirty                 = besb.flags == BEFS_DIRTY,
                FreeClusters          = besb.num_blocks - besb.used_blocks,
                FreeClustersSpecified = true,
                Type       = "BeFS",
                VolumeName = StringHandlers.CToString(besb.name, Encoding)
            };
        }
Ejemplo n.º 10
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();

            XmlFsType = new FileSystemType();

            byte[]           vbrSector = imagePlugin.ReadSector(0 + partition.Start);
            VolumeBootRecord vbr       = Marshal.ByteArrayToStructureLittleEndian <VolumeBootRecord>(vbrSector);

            byte[]            parametersSector = imagePlugin.ReadSector(9 + partition.Start);
            OemParameterTable parametersTable  =
                Marshal.ByteArrayToStructureLittleEndian <OemParameterTable>(parametersSector);

            byte[]         chkSector = imagePlugin.ReadSector(11 + partition.Start);
            ChecksumSector chksector = Marshal.ByteArrayToStructureLittleEndian <ChecksumSector>(chkSector);

            sb.AppendLine("Microsoft exFAT");
            sb.AppendFormat("Partition offset: {0}", vbr.offset).AppendLine();
            sb.AppendFormat("Volume has {0} sectors of {1} bytes each for a total of {2} bytes", vbr.sectors,
                            1 << vbr.sectorShift, vbr.sectors * (ulong)(1 << vbr.sectorShift)).AppendLine();
            sb.AppendFormat("Volume uses clusters of {0} sectors ({1} bytes) each", 1 << vbr.clusterShift,
                            (1 << vbr.sectorShift) * (1 << vbr.clusterShift)).AppendLine();
            sb.AppendFormat("First FAT starts at sector {0} and runs for {1} sectors", vbr.fatOffset, vbr.fatLength)
            .AppendLine();
            sb.AppendFormat("Volume uses {0} FATs", vbr.fats).AppendLine();
            sb.AppendFormat("Cluster heap starts at sector {0}, contains {1} clusters and is {2}% used",
                            vbr.clusterHeapOffset, vbr.clusterHeapLength, vbr.heapUsage).AppendLine();
            sb.AppendFormat("Root directory starts at cluster {0}", vbr.rootDirectoryCluster).AppendLine();
            sb.AppendFormat("Filesystem revision is {0}.{1:D2}", (vbr.revision & 0xFF00) >> 8, vbr.revision & 0xFF)
            .AppendLine();
            sb.AppendFormat("Volume serial number: {0:X8}", vbr.volumeSerial).AppendLine();
            sb.AppendFormat("BIOS drive is {0:X2}h", vbr.drive).AppendLine();
            if (vbr.flags.HasFlag(VolumeFlags.SecondFatActive))
            {
                sb.AppendLine("2nd FAT is in use");
            }
            if (vbr.flags.HasFlag(VolumeFlags.VolumeDirty))
            {
                sb.AppendLine("Volume is dirty");
            }
            if (vbr.flags.HasFlag(VolumeFlags.MediaFailure))
            {
                sb.AppendLine("Underlying media presented errors");
            }

            int count = 1;

            foreach (OemParameter parameter in parametersTable.parameters)
            {
                if (parameter.OemParameterType == OEM_FLASH_PARAMETER_GUID)
                {
                    sb.AppendFormat("OEM Parameters {0}:", count).AppendLine();
                    sb.AppendFormat("\t{0} bytes in erase block", parameter.eraseBlockSize).AppendLine();
                    sb.AppendFormat("\t{0} bytes per page", parameter.pageSize).AppendLine();
                    sb.AppendFormat("\t{0} spare blocks", parameter.spareBlocks).AppendLine();
                    sb.AppendFormat("\t{0} nanoseconds random access time", parameter.randomAccessTime).AppendLine();
                    sb.AppendFormat("\t{0} nanoseconds program time", parameter.programTime).AppendLine();
                    sb.AppendFormat("\t{0} nanoseconds read cycle time", parameter.readCycleTime).AppendLine();
                    sb.AppendFormat("\t{0} nanoseconds write cycle time", parameter.writeCycleTime).AppendLine();
                }
                else if (parameter.OemParameterType != Guid.Empty)
                {
                    sb.AppendFormat("Found unknown parameter type {0}", parameter.OemParameterType).AppendLine();
                }

                count++;
            }

            sb.AppendFormat("Checksum 0x{0:X8}", chksector.checksum[0]).AppendLine();

            XmlFsType.ClusterSize  = (uint)((1 << vbr.sectorShift) * (1 << vbr.clusterShift));
            XmlFsType.Clusters     = vbr.clusterHeapLength;
            XmlFsType.Dirty        = vbr.flags.HasFlag(VolumeFlags.VolumeDirty);
            XmlFsType.Type         = "exFAT";
            XmlFsType.VolumeSerial = $"{vbr.volumeSerial:X8}";

            information = sb.ToString();
        }
Ejemplo n.º 11
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            Encoding    = Encoding.Unicode;
            information = "";

            if (imagePlugin.Info.SectorSize < F2FS_MIN_SECTOR ||
                imagePlugin.Info.SectorSize > F2FS_MAX_SECTOR)
            {
                return;
            }

            uint sbAddr = F2FS_SUPER_OFFSET / imagePlugin.Info.SectorSize;

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

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

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

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

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

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

            if (f2fsSb.magic != F2FS_MAGIC)
            {
                return;
            }

            var sb = new StringBuilder();

            sb.AppendLine("F2FS filesystem");
            sb.AppendFormat("Version {0}.{1}", f2fsSb.major_ver, f2fsSb.minor_ver).AppendLine();
            sb.AppendFormat("{0} bytes per sector", 1 << (int)f2fsSb.log_sectorsize).AppendLine();

            sb.AppendFormat("{0} sectors ({1} bytes) per block", 1 << (int)f2fsSb.log_sectors_per_block,
                            1 << (int)f2fsSb.log_blocksize).AppendLine();

            sb.AppendFormat("{0} blocks per segment", f2fsSb.log_blocks_per_seg).AppendLine();
            sb.AppendFormat("{0} blocks in volume", f2fsSb.block_count).AppendLine();
            sb.AppendFormat("{0} segments per section", f2fsSb.segs_per_sec).AppendLine();
            sb.AppendFormat("{0} sections per zone", f2fsSb.secs_per_zone).AppendLine();
            sb.AppendFormat("{0} sections", f2fsSb.section_count).AppendLine();
            sb.AppendFormat("{0} segments", f2fsSb.segment_count).AppendLine();
            sb.AppendFormat("Root directory resides on inode {0}", f2fsSb.root_ino).AppendLine();
            sb.AppendFormat("Volume UUID: {0}", f2fsSb.uuid).AppendLine();

            sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(f2fsSb.volume_name, Encoding.Unicode, true)).
            AppendLine();

            sb.AppendFormat("Volume last mounted on kernel version: {0}", StringHandlers.CToString(f2fsSb.version)).
            AppendLine();

            sb.AppendFormat("Volume created on kernel version: {0}", StringHandlers.CToString(f2fsSb.init_version)).
            AppendLine();

            information = sb.ToString();

            XmlFsType = new FileSystemType
            {
                Type                   = "F2FS filesystem",
                SystemIdentifier       = Encoding.ASCII.GetString(f2fsSb.version),
                Clusters               = f2fsSb.block_count,
                ClusterSize            = (uint)(1 << (int)f2fsSb.log_blocksize),
                DataPreparerIdentifier = Encoding.ASCII.GetString(f2fsSb.init_version),
                VolumeName             = StringHandlers.CToString(f2fsSb.volume_name, Encoding.Unicode, true),
                VolumeSerial           = f2fsSb.uuid.ToString()
            };
        }
Ejemplo n.º 12
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            Encoding    = Encoding.Unicode;
            information = "";

            var sb = new StringBuilder();

            byte[] ntfsBpb = imagePlugin.ReadSector(0 + partition.Start);

            BiosParameterBlock ntfsBb = Marshal.ByteArrayToStructureLittleEndian <BiosParameterBlock>(ntfsBpb);

            sb.AppendFormat("{0} bytes per sector", ntfsBb.bps).AppendLine();
            sb.AppendFormat("{0} sectors per cluster ({1} bytes)", ntfsBb.spc, ntfsBb.spc * ntfsBb.bps).AppendLine();

            //          sb.AppendFormat("{0} reserved sectors", ntfs_bb.rsectors).AppendLine();
            //          sb.AppendFormat("{0} FATs", ntfs_bb.fats_no).AppendLine();
            //          sb.AppendFormat("{0} entries in the root folder", ntfs_bb.root_ent).AppendLine();
            //          sb.AppendFormat("{0} sectors on volume (small)", ntfs_bb.sml_sectors).AppendLine();
            sb.AppendFormat("Media descriptor: 0x{0:X2}", ntfsBb.media).AppendLine();

            //          sb.AppendFormat("{0} sectors per FAT", ntfs_bb.spfat).AppendLine();
            sb.AppendFormat("{0} sectors per track", ntfsBb.sptrk).AppendLine();
            sb.AppendFormat("{0} heads", ntfsBb.heads).AppendLine();
            sb.AppendFormat("{0} hidden sectors before filesystem", ntfsBb.hsectors).AppendLine();

            //          sb.AppendFormat("{0} sectors on volume (big)", ntfs_bb.big_sectors).AppendLine();
            sb.AppendFormat("BIOS drive number: 0x{0:X2}", ntfsBb.drive_no).AppendLine();

            //          sb.AppendFormat("NT flags: 0x{0:X2}", ntfs_bb.nt_flags).AppendLine();
            //          sb.AppendFormat("Signature 1: 0x{0:X2}", ntfs_bb.signature1).AppendLine();
            sb.AppendFormat("{0} sectors on volume ({1} bytes)", ntfsBb.sectors, ntfsBb.sectors * ntfsBb.bps).
            AppendLine();

            sb.AppendFormat("Cluster where $MFT starts: {0}", ntfsBb.mft_lsn).AppendLine();
            sb.AppendFormat("Cluster where $MFTMirr starts: {0}", ntfsBb.mftmirror_lsn).AppendLine();

            if (ntfsBb.mft_rc_clusters > 0)
            {
                sb.AppendFormat("{0} clusters per MFT record ({1} bytes)", ntfsBb.mft_rc_clusters,
                                ntfsBb.mft_rc_clusters * ntfsBb.bps * ntfsBb.spc).AppendLine();
            }
            else
            {
                sb.AppendFormat("{0} bytes per MFT record", 1 << -ntfsBb.mft_rc_clusters).AppendLine();
            }

            if (ntfsBb.index_blk_cts > 0)
            {
                sb.AppendFormat("{0} clusters per Index block ({1} bytes)", ntfsBb.index_blk_cts,
                                ntfsBb.index_blk_cts * ntfsBb.bps * ntfsBb.spc).AppendLine();
            }
            else
            {
                sb.AppendFormat("{0} bytes per Index block", 1 << -ntfsBb.index_blk_cts).AppendLine();
            }

            sb.AppendFormat("Volume serial number: {0:X16}", ntfsBb.serial_no).AppendLine();

            //          sb.AppendFormat("Signature 2: 0x{0:X4}", ntfs_bb.signature2).AppendLine();

            XmlFsType = new FileSystemType();

            if (ntfsBb.jump[0] == 0xEB &&
                ntfsBb.jump[1] > 0x4E &&
                ntfsBb.jump[1] < 0x80 &&
                ntfsBb.signature2 == 0xAA55)
            {
                XmlFsType.Bootable = true;
                string bootChk = Sha1Context.Data(ntfsBb.boot_code, out _);
                sb.AppendLine("Volume is bootable");
                sb.AppendFormat("Boot code's SHA1: {0}", bootChk).AppendLine();
            }

            XmlFsType.ClusterSize  = (uint)(ntfsBb.spc * ntfsBb.bps);
            XmlFsType.Clusters     = (ulong)(ntfsBb.sectors / ntfsBb.spc);
            XmlFsType.VolumeSerial = $"{ntfsBb.serial_no:X16}";
            XmlFsType.Type         = "NTFS";

            information = sb.ToString();
        }
Ejemplo n.º 13
0
 public Result OpenFileSystemWithPatch(out IFileSystem fileSystem, TitleId titleId, FileSystemType type)
 {
     throw new NotImplementedException();
 }
Ejemplo n.º 14
0
 public Result OpenFileSystemWithId(out IFileSystem fileSystem, ref FsPath path, TitleId titleId, FileSystemType type)
 {
     throw new NotImplementedException();
 }
Ejemplo n.º 15
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Syncless.Monitor.DTO.FileSystemEvent" /> class for delete event with unknown file system type only, given the affected path and the path being monitored.
 /// </summary>
 /// <param name="path">A <see cref="string" /> specifying the affected path.</param>
 /// <param name="watchPath">A <see cref="string" /> specifying the path being monitored.</param>
 public FileSystemEvent(string path, string watchPath)
 {
     this._path = path;
     this._oldPath = null;
     this._watchPath = watchPath;
     this._eventType = EventChangeType.DELETED;
     this._fileSystemType = FileSystemType.UNKNOWN;
 }
Ejemplo n.º 16
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            Encoding    = encoding ?? Encoding.ASCII;
            information = "";
            StringBuilder isoMetadata = new StringBuilder();

            byte[] vdMagic = new byte[5];            // Volume Descriptor magic "CD001"
            byte[] hsMagic = new byte[5];            // Volume Descriptor magic "CDROM"

            string bootSpec = "";

            PrimaryVolumeDescriptor?pvd      = null;
            PrimaryVolumeDescriptor?jolietvd = null;
            BootRecord?bvd = null;
            HighSierraPrimaryVolumeDescriptor?hsvd = null;
            FileStructureVolumeDescriptor?    fsvd = null;
            ElToritoBootRecord?torito = null;

            // ISO9660 is designed for 2048 bytes/sector devices
            if (imagePlugin.Info.SectorSize < 2048)
            {
                return;
            }

            // ISO9660 Primary Volume Descriptor starts at sector 16, so that's minimal size.
            if (partition.End < 16)
            {
                return;
            }

            ulong counter = 0;

            byte[] vdSector = imagePlugin.ReadSector(16 + counter + partition.Start);
            int    xaOff    = vdSector.Length == 2336 ? 8 : 0;

            Array.Copy(vdSector, 0x009 + xaOff, hsMagic, 0, 5);
            bool highSierra = Encoding.GetString(hsMagic) == HIGH_SIERRA_MAGIC;
            int  hsOff      = 0;

            if (highSierra)
            {
                hsOff = 8;
            }
            bool cdi = false;

            while (true)
            {
                DicConsole.DebugWriteLine("ISO9660 plugin", "Processing VD loop no. {0}", counter);
                // Seek to Volume Descriptor
                DicConsole.DebugWriteLine("ISO9660 plugin", "Reading sector {0}", 16 + counter + partition.Start);
                byte[] vdSectorTmp = imagePlugin.ReadSector(16 + counter + partition.Start);
                vdSector = new byte[vdSectorTmp.Length - xaOff];
                Array.Copy(vdSectorTmp, xaOff, vdSector, 0, vdSector.Length);

                byte vdType = vdSector[0 + hsOff]; // Volume Descriptor Type, should be 1 or 2.
                DicConsole.DebugWriteLine("ISO9660 plugin", "VDType = {0}", vdType);

                if (vdType == 255) // Supposedly we are in the PVD.
                {
                    if (counter == 0)
                    {
                        return;
                    }

                    break;
                }

                Array.Copy(vdSector, 0x001, vdMagic, 0, 5);
                Array.Copy(vdSector, 0x009, hsMagic, 0, 5);

                if (Encoding.GetString(vdMagic) != ISO_MAGIC && Encoding.GetString(hsMagic) != HIGH_SIERRA_MAGIC &&
                    Encoding.GetString(vdMagic) != CDI_MAGIC
                    ) // Recognized, it is an ISO9660, now check for rest of data.
                {
                    if (counter == 0)
                    {
                        return;
                    }

                    break;
                }

                cdi |= Encoding.GetString(vdMagic) == CDI_MAGIC;

                switch (vdType)
                {
                case 0:
                {
                    bvd = Marshal.ByteArrayToStructureLittleEndian <BootRecord>(vdSector, hsOff, 2048 - hsOff);

                    bootSpec = "Unknown";

                    if (Encoding.GetString(bvd.Value.system_id).Substring(0, 23) == "EL TORITO SPECIFICATION")
                    {
                        bootSpec = "El Torito";
                        torito   =
                            Marshal.ByteArrayToStructureLittleEndian <ElToritoBootRecord>(vdSector, hsOff,
                                                                                          2048 - hsOff);
                    }

                    break;
                }

                case 1:
                {
                    if (highSierra)
                    {
                        hsvd = Marshal
                               .ByteArrayToStructureLittleEndian <HighSierraPrimaryVolumeDescriptor>(vdSector);
                    }
                    else if (cdi)
                    {
                        fsvd = Marshal.ByteArrayToStructureBigEndian <FileStructureVolumeDescriptor>(vdSector);
                    }
                    else
                    {
                        pvd = Marshal.ByteArrayToStructureLittleEndian <PrimaryVolumeDescriptor>(vdSector);
                    }

                    break;
                }

                case 2:
                {
                    PrimaryVolumeDescriptor svd =
                        Marshal.ByteArrayToStructureLittleEndian <PrimaryVolumeDescriptor>(vdSector);

                    // Check if this is Joliet
                    if (svd.escape_sequences[0] == '%' && svd.escape_sequences[1] == '/')
                    {
                        if (svd.escape_sequences[2] == '@' || svd.escape_sequences[2] == 'C' ||
                            svd.escape_sequences[2] == 'E')
                        {
                            jolietvd = svd;
                        }
                        else
                        {
                            DicConsole.WriteLine("ISO9660 plugin", "Found unknown supplementary volume descriptor");
                        }
                    }

                    break;
                }
                }

                counter++;
            }

            DecodedVolumeDescriptor decodedVd;
            DecodedVolumeDescriptor decodedJolietVd = new DecodedVolumeDescriptor();

            XmlFsType = new FileSystemType();

            if (pvd == null && hsvd == null && fsvd == null)
            {
                information = "ERROR: Could not find primary volume descriptor";
                return;
            }

            if (highSierra)
            {
                decodedVd = DecodeVolumeDescriptor(hsvd.Value);
            }
            else if (cdi)
            {
                decodedVd = DecodeVolumeDescriptor(fsvd.Value);
            }
            else
            {
                decodedVd = DecodeVolumeDescriptor(pvd.Value);
            }

            if (jolietvd != null)
            {
                decodedJolietVd = DecodeJolietDescriptor(jolietvd.Value);
            }

            uint rootLocation = 0;
            uint rootSize     = 0;

            // No need to read root on CD-i, as extensions are not supported...
            if (!cdi)
            {
                rootLocation = highSierra
                                   ? hsvd.Value.root_directory_record.extent
                                   : pvd.Value.root_directory_record.extent;

                if (highSierra)
                {
                    rootSize = hsvd.Value.root_directory_record.size / hsvd.Value.logical_block_size;
                    if (hsvd.Value.root_directory_record.size % hsvd.Value.logical_block_size > 0)
                    {
                        rootSize++;
                    }
                }
                else
                {
                    rootSize = pvd.Value.root_directory_record.size / pvd.Value.logical_block_size;
                    if (pvd.Value.root_directory_record.size % pvd.Value.logical_block_size > 0)
                    {
                        rootSize++;
                    }
                }
            }

            byte[] rootDir      = new byte[0];
            int    rootOff      = 0;
            bool   xaExtensions = false;
            bool   apple        = false;
            bool   susp         = false;
            bool   rrip         = false;
            bool   ziso         = false;
            bool   amiga        = false;
            bool   aaip         = false;
            List <ContinuationArea> contareas       = new List <ContinuationArea>();
            List <byte[]>           refareas        = new List <byte[]>();
            StringBuilder           suspInformation = new StringBuilder();

            if (rootLocation + rootSize < imagePlugin.Info.Sectors)
            {
                rootDir = imagePlugin.ReadSectors(rootLocation, rootSize);
            }

            BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian;

            // Walk thru root directory to see system area extensions in use
            while (rootOff + Marshal.SizeOf <DirectoryRecord>() < rootDir.Length && !cdi)
            {
                DirectoryRecord record =
                    Marshal.ByteArrayToStructureLittleEndian <DirectoryRecord>(rootDir, rootOff,
                                                                               Marshal.SizeOf <DirectoryRecord>());

                int saOff = Marshal.SizeOf <DirectoryRecord>() + record.name_len;
                saOff += saOff % 2;
                int saLen = record.length - saOff;

                if (saLen > 0 && rootOff + saOff + saLen <= rootDir.Length)
                {
                    byte[] sa = new byte[saLen];
                    Array.Copy(rootDir, rootOff + saOff, sa, 0, saLen);
                    saOff = 0;

                    while (saOff < saLen)
                    {
                        bool noneFound = true;

                        if (Marshal.SizeOf <CdromXa>() + saOff <= saLen)
                        {
                            CdromXa xa = Marshal.ByteArrayToStructureBigEndian <CdromXa>(sa);
                            if (xa.signature == XA_MAGIC)
                            {
                                xaExtensions = true;
                                saOff       += Marshal.SizeOf <CdromXa>();
                                noneFound    = false;
                            }
                        }

                        if (saOff + 2 >= saLen)
                        {
                            break;
                        }

                        ushort nextSignature = BigEndianBitConverter.ToUInt16(sa, saOff);

                        switch (nextSignature)
                        {
                        // Easy, contains size field
                        case APPLE_MAGIC:
                            apple     = true;
                            saOff    += sa[saOff + 2];
                            noneFound = false;
                            break;

                        // Not easy, contains size field
                        case APPLE_MAGIC_OLD:
                            apple = true;
                            AppleOldId appleId = (AppleOldId)sa[saOff + 2];
                            noneFound = false;

                            switch (appleId)
                            {
                            case AppleOldId.ProDOS:
                                saOff += Marshal.SizeOf <AppleProDOSOldSystemUse>();
                                break;

                            case AppleOldId.TypeCreator:
                            case AppleOldId.TypeCreatorBundle:
                                saOff += Marshal.SizeOf <AppleHFSTypeCreatorSystemUse>();
                                break;

                            case AppleOldId.TypeCreatorIcon:
                            case AppleOldId.TypeCreatorIconBundle:
                                saOff += Marshal.SizeOf <AppleHFSIconSystemUse>();
                                break;

                            case AppleOldId.HFS:
                                saOff += Marshal.SizeOf <AppleHFSOldSystemUse>();
                                break;
                            }

                            break;

                        // IEEE-P1281 aka SUSP 1.12
                        case SUSP_INDICATOR:
                            susp      = true;
                            saOff    += sa[saOff + 2];
                            noneFound = false;

                            while (saOff + 2 < saLen)
                            {
                                nextSignature = BigEndianBitConverter.ToUInt16(sa, saOff);

                                switch (nextSignature)
                                {
                                case APPLE_MAGIC:
                                    if (sa[saOff + 3] == 1 && sa[saOff + 2] == 7)
                                    {
                                        apple = true;
                                    }
                                    else
                                    {
                                        apple |= sa[saOff + 3] != 1;
                                    }
                                    break;

                                case SUSP_CONTINUATION when saOff + sa[saOff + 2] <= saLen:
                                    byte[] ce = new byte[sa[saOff + 2]];
                                    Array.Copy(sa, saOff, ce, 0, ce.Length);
                                    ContinuationArea ca =
                                        Marshal.ByteArrayToStructureBigEndian <ContinuationArea>(ce);
                                    contareas.Add(ca);
                                    break;

                                case SUSP_REFERENCE when saOff + sa[saOff + 2] <= saLen:
                                    byte[] er = new byte[sa[saOff + 2]];
                                    Array.Copy(sa, saOff, er, 0, er.Length);
                                    refareas.Add(er);
                                    break;
                                }

                                rrip |= nextSignature == RRIP_MAGIC ||
                                        nextSignature == RRIP_POSIX_ATTRIBUTES ||
                                        nextSignature == RRIP_POSIX_DEV_NO ||
                                        nextSignature == RRIP_SYMLINK ||
                                        nextSignature == RRIP_NAME ||
                                        nextSignature == RRIP_CHILDLINK ||
                                        nextSignature == RRIP_PARENTLINK ||
                                        nextSignature == RRIP_RELOCATED_DIR ||
                                        nextSignature == RRIP_TIMESTAMPS || nextSignature == RRIP_SPARSE;

                                ziso  |= nextSignature == ZISO_MAGIC;
                                amiga |= nextSignature == AMIGA_MAGIC;
                                aaip  |= nextSignature == AAIP_MAGIC || nextSignature == AAIP_MAGIC_OLD &&
                                         sa[saOff + 3] == 1 &&
                                         sa[saOff + 2] >= 9;

                                saOff += sa[saOff + 2];

                                if (nextSignature == SUSP_TERMINATOR)
                                {
                                    break;
                                }
                            }

                            break;
                        }

                        if (noneFound)
                        {
                            break;
                        }
                    }
                }

                rootOff += record.length;

                if (record.length == 0)
                {
                    break;
                }
            }

            foreach (ContinuationArea ca in contareas)
            {
                uint caLen = (ca.ca_length_be + ca.offset_be) /
                             (highSierra ? hsvd.Value.logical_block_size : pvd.Value.logical_block_size);
                if ((ca.ca_length_be + ca.offset_be) %
                    (highSierra ? hsvd.Value.logical_block_size : pvd.Value.logical_block_size) > 0)
                {
                    caLen++;
                }

                byte[] caSectors = imagePlugin.ReadSectors(ca.block_be, caLen);
                byte[] caData    = new byte[ca.ca_length_be];
                Array.Copy(caSectors, ca.offset_be, caData, 0, ca.ca_length_be);
                int caOff = 0;

                while (caOff < ca.ca_length_be)
                {
                    ushort nextSignature = BigEndianBitConverter.ToUInt16(caData, caOff);

                    switch (nextSignature)
                    {
                    // Apple never said to include its extensions inside a continuation area, but just in case
                    case APPLE_MAGIC:
                        if (caData[caOff + 3] == 1 && caData[caOff + 2] == 7)
                        {
                            apple = true;
                        }
                        else
                        {
                            apple |= caData[caOff + 3] != 1;
                        }
                        break;

                    case SUSP_REFERENCE when caOff + caData[caOff + 2] <= ca.ca_length_be:
                        byte[] er = new byte[caData[caOff + 2]];
                        Array.Copy(caData, caOff, er, 0, er.Length);
                        refareas.Add(er);
                        break;
                    }

                    rrip |= nextSignature == RRIP_MAGIC || nextSignature == RRIP_POSIX_ATTRIBUTES ||
                            nextSignature == RRIP_POSIX_DEV_NO || nextSignature == RRIP_SYMLINK ||
                            nextSignature == RRIP_NAME || nextSignature == RRIP_CHILDLINK ||
                            nextSignature == RRIP_PARENTLINK || nextSignature == RRIP_RELOCATED_DIR ||
                            nextSignature == RRIP_TIMESTAMPS || nextSignature == RRIP_SPARSE;

                    ziso  |= nextSignature == ZISO_MAGIC;
                    amiga |= nextSignature == AMIGA_MAGIC;
                    aaip  |= nextSignature == AAIP_MAGIC || nextSignature == AAIP_MAGIC_OLD && caData[caOff + 3] == 1 &&
                             caData[caOff + 2] >= 9;

                    caOff += caData[caOff + 2];
                }
            }

            if (refareas.Count > 0)
            {
                suspInformation.AppendLine("----------------------------------------");
                suspInformation.AppendLine("SYSTEM USE SHARING PROTOCOL INFORMATION:");
                suspInformation.AppendLine("----------------------------------------");

                counter = 1;
                foreach (byte[] erb in refareas)
                {
                    ReferenceArea er    = Marshal.ByteArrayToStructureBigEndian <ReferenceArea>(erb);
                    string        extId =
                        Encoding.GetString(erb, Marshal.SizeOf <ReferenceArea>(), er.id_len);
                    string extDes =
                        Encoding.GetString(erb, Marshal.SizeOf <ReferenceArea>() + er.id_len, er.des_len);
                    string extSrc = Encoding.GetString(erb, Marshal.SizeOf <ReferenceArea>() + er.id_len + er.des_len,
                                                       er.src_len);
                    suspInformation.AppendFormat("Extension: {0}", counter).AppendLine();
                    suspInformation.AppendFormat("\tID: {0}, version {1}", extId, er.ext_ver).AppendLine();
                    suspInformation.AppendFormat("\tDescription: {0}", extDes).AppendLine();
                    suspInformation.AppendFormat("\tSource: {0}", extSrc).AppendLine();
                    counter++;
                }
            }

            byte[]          ipbinSector = imagePlugin.ReadSector(0 + partition.Start);
            CD.IPBin?       segaCd      = CD.DecodeIPBin(ipbinSector);
            Saturn.IPBin?   saturn      = Saturn.DecodeIPBin(ipbinSector);
            Dreamcast.IPBin?dreamcast   = Dreamcast.DecodeIPBin(ipbinSector);

            string fsFormat;

            if (highSierra)
            {
                fsFormat = "High Sierra Format";
            }
            else if (cdi)
            {
                fsFormat = "CD-i";
            }
            else
            {
                fsFormat = "ISO9660";
            }

            isoMetadata.AppendFormat("{0} file system", fsFormat).AppendLine();
            if (xaExtensions)
            {
                isoMetadata.AppendLine("CD-ROM XA extensions present.");
            }
            if (amiga)
            {
                isoMetadata.AppendLine("Amiga extensions present.");
            }
            if (apple)
            {
                isoMetadata.AppendLine("Apple extensions present.");
            }
            if (jolietvd != null)
            {
                isoMetadata.AppendLine("Joliet extensions present.");
            }
            if (susp)
            {
                isoMetadata.AppendLine("System Use Sharing Protocol present.");
            }
            if (rrip)
            {
                isoMetadata.AppendLine("Rock Ridge Interchange Protocol present.");
            }
            if (aaip)
            {
                isoMetadata.AppendLine("Arbitrary Attribute Interchange Protocol present.");
            }
            if (ziso)
            {
                isoMetadata.AppendLine("zisofs compression present.");
            }
            if (bvd != null)
            {
                isoMetadata.AppendFormat("Disc bootable following {0} specifications.", bootSpec).AppendLine();
            }
            if (segaCd != null)
            {
                isoMetadata.AppendLine("This is a SegaCD / MegaCD disc.");
                isoMetadata.AppendLine(CD.Prettify(segaCd));
            }

            if (saturn != null)
            {
                isoMetadata.AppendLine("This is a Sega Saturn disc.");
                isoMetadata.AppendLine(Saturn.Prettify(saturn));
            }

            if (dreamcast != null)
            {
                isoMetadata.AppendLine("This is a Sega Dreamcast disc.");
                isoMetadata.AppendLine(Dreamcast.Prettify(dreamcast));
            }

            isoMetadata.AppendFormat("{0}------------------------------", cdi ? "---------------" : "").AppendLine();
            isoMetadata.AppendFormat("{0}VOLUME DESCRIPTOR INFORMATION:", cdi ? "FILE STRUCTURE " : "").AppendLine();
            isoMetadata.AppendFormat("{0}------------------------------", cdi ? "---------------" : "").AppendLine();
            isoMetadata.AppendFormat("System identifier: {0}", decodedVd.SystemIdentifier).AppendLine();
            isoMetadata.AppendFormat("Volume identifier: {0}", decodedVd.VolumeIdentifier).AppendLine();
            isoMetadata.AppendFormat("Volume set identifier: {0}", decodedVd.VolumeSetIdentifier).AppendLine();
            isoMetadata.AppendFormat("Publisher identifier: {0}", decodedVd.PublisherIdentifier).AppendLine();
            isoMetadata.AppendFormat("Data preparer identifier: {0}", decodedVd.DataPreparerIdentifier).AppendLine();
            isoMetadata.AppendFormat("Application identifier: {0}", decodedVd.ApplicationIdentifier).AppendLine();
            isoMetadata.AppendFormat("Volume creation date: {0}", decodedVd.CreationTime).AppendLine();
            if (decodedVd.HasModificationTime)
            {
                isoMetadata.AppendFormat("Volume modification date: {0}", decodedVd.ModificationTime).AppendLine();
            }
            else
            {
                isoMetadata.AppendFormat("Volume has not been modified.").AppendLine();
            }
            if (decodedVd.HasExpirationTime)
            {
                isoMetadata.AppendFormat("Volume expiration date: {0}", decodedVd.ExpirationTime).AppendLine();
            }
            else
            {
                isoMetadata.AppendFormat("Volume does not expire.").AppendLine();
            }
            if (decodedVd.HasEffectiveTime)
            {
                isoMetadata.AppendFormat("Volume effective date: {0}", decodedVd.EffectiveTime).AppendLine();
            }
            else
            {
                isoMetadata.AppendFormat("Volume has always been effective.").AppendLine();
            }
            isoMetadata.AppendFormat("Volume has {0} blocks of {1} bytes each", decodedVd.Blocks, decodedVd.BlockSize)
            .AppendLine();

            if (jolietvd != null)
            {
                isoMetadata.AppendLine("-------------------------------------");
                isoMetadata.AppendLine("JOLIET VOLUME DESCRIPTOR INFORMATION:");
                isoMetadata.AppendLine("-------------------------------------");
                isoMetadata.AppendFormat("System identifier: {0}", decodedJolietVd.SystemIdentifier).AppendLine();
                isoMetadata.AppendFormat("Volume identifier: {0}", decodedJolietVd.VolumeIdentifier).AppendLine();
                isoMetadata.AppendFormat("Volume set identifier: {0}", decodedJolietVd.VolumeSetIdentifier)
                .AppendLine();
                isoMetadata.AppendFormat("Publisher identifier: {0}", decodedJolietVd.PublisherIdentifier).AppendLine();
                isoMetadata.AppendFormat("Data preparer identifier: {0}", decodedJolietVd.DataPreparerIdentifier)
                .AppendLine();
                isoMetadata.AppendFormat("Application identifier: {0}", decodedJolietVd.ApplicationIdentifier)
                .AppendLine();
                isoMetadata.AppendFormat("Volume creation date: {0}", decodedJolietVd.CreationTime).AppendLine();
                if (decodedJolietVd.HasModificationTime)
                {
                    isoMetadata.AppendFormat("Volume modification date: {0}", decodedJolietVd.ModificationTime)
                    .AppendLine();
                }
                else
                {
                    isoMetadata.AppendFormat("Volume has not been modified.").AppendLine();
                }
                if (decodedJolietVd.HasExpirationTime)
                {
                    isoMetadata.AppendFormat("Volume expiration date: {0}", decodedJolietVd.ExpirationTime)
                    .AppendLine();
                }
                else
                {
                    isoMetadata.AppendFormat("Volume does not expire.").AppendLine();
                }
                if (decodedJolietVd.HasEffectiveTime)
                {
                    isoMetadata.AppendFormat("Volume effective date: {0}", decodedJolietVd.EffectiveTime).AppendLine();
                }
                else
                {
                    isoMetadata.AppendFormat("Volume has always been effective.").AppendLine();
                }
            }

            if (torito != null)
            {
                vdSector = imagePlugin.ReadSector(torito.Value.catalog_sector + partition.Start);

                int toritoOff = 0;

                if (vdSector[toritoOff] != 1)
                {
                    goto exit_torito;
                }

                ElToritoValidationEntry valentry =
                    Marshal.ByteArrayToStructureLittleEndian <ElToritoValidationEntry>(vdSector, toritoOff,
                                                                                       EL_TORITO_ENTRY_SIZE);

                if (valentry.signature != EL_TORITO_MAGIC)
                {
                    goto exit_torito;
                }

                toritoOff += EL_TORITO_ENTRY_SIZE;

                ElToritoInitialEntry initialEntry =
                    Marshal.ByteArrayToStructureLittleEndian <ElToritoInitialEntry>(vdSector, toritoOff,
                                                                                    EL_TORITO_ENTRY_SIZE);

                initialEntry.boot_type = (ElToritoEmulation)((byte)initialEntry.boot_type & 0xF);

                DicConsole.DebugWriteLine("DEBUG (ISO9660 plugin)", "initialEntry.load_rba = {0}",
                                          initialEntry.load_rba);
                DicConsole.DebugWriteLine("DEBUG (ISO9660 plugin)", "initialEntry.sector_count = {0}",
                                          initialEntry.sector_count);

                byte[] bootImage =
                    initialEntry.load_rba + partition.Start + initialEntry.sector_count - 1 <= partition.End
                        ? imagePlugin.ReadSectors(initialEntry.load_rba + partition.Start, initialEntry.sector_count)
                        : null;

                isoMetadata.AppendLine("----------------------");
                isoMetadata.AppendLine("EL TORITO INFORMATION:");
                isoMetadata.AppendLine("----------------------");

                isoMetadata.AppendLine("Initial entry:");
                isoMetadata.AppendFormat("\tDeveloper ID: {0}", Encoding.GetString(valentry.developer_id)).AppendLine();
                if (initialEntry.bootable == ElToritoIndicator.Bootable)
                {
                    isoMetadata.AppendFormat("\tBootable on {0}", valentry.platform_id).AppendLine();
                    isoMetadata.AppendFormat("\tBootable image starts at sector {0} and runs for {1} sectors",
                                             initialEntry.load_rba, initialEntry.sector_count).AppendLine();
                    if (valentry.platform_id == ElToritoPlatform.x86)
                    {
                        isoMetadata.AppendFormat("\tBootable image will be loaded at segment {0:X4}h",
                                                 initialEntry.load_seg == 0 ? 0x7C0 : initialEntry.load_seg)
                        .AppendLine();
                    }
                    else
                    {
                        isoMetadata.AppendFormat("\tBootable image will be loaded at 0x{0:X8}",
                                                 (uint)initialEntry.load_seg * 10).AppendLine();
                    }
                    switch (initialEntry.boot_type)
                    {
                    case ElToritoEmulation.None:
                        isoMetadata.AppendLine("\tImage uses no emulation");
                        break;

                    case ElToritoEmulation.Md2hd:
                        isoMetadata.AppendLine("\tImage emulates a 5.25\" high-density (MD2HD, 1.2Mb) floppy");
                        break;

                    case ElToritoEmulation.Mf2hd:
                        isoMetadata.AppendLine("\tImage emulates a 3.5\" high-density (MF2HD, 1.44Mb) floppy");
                        break;

                    case ElToritoEmulation.Mf2ed:
                        isoMetadata.AppendLine("\tImage emulates a 3.5\" extra-density (MF2ED, 2.88Mb) floppy");
                        break;

                    default:
                        isoMetadata.AppendFormat("\tImage uses unknown emulation type {0}",
                                                 (byte)initialEntry.boot_type).AppendLine();
                        break;
                    }

                    isoMetadata.AppendFormat("\tSystem type: 0x{0:X2}", initialEntry.system_type).AppendLine();
                    if (bootImage != null)
                    {
                        isoMetadata.AppendFormat("\tBootable image's SHA1: {0}", Sha1Context.Data(bootImage, out _))
                        .AppendLine();
                    }
                }
                else
                {
                    isoMetadata.AppendLine("\tNot bootable");
                }

                toritoOff += EL_TORITO_ENTRY_SIZE;

                const int SECTION_COUNTER = 2;

                while (toritoOff < vdSector.Length && (vdSector[toritoOff] == (byte)ElToritoIndicator.Header ||
                                                       vdSector[toritoOff] == (byte)ElToritoIndicator.LastHeader))
                {
                    ElToritoSectionHeaderEntry sectionHeader =
                        Marshal.ByteArrayToStructureLittleEndian <ElToritoSectionHeaderEntry>(vdSector, toritoOff,
                                                                                              EL_TORITO_ENTRY_SIZE);
                    toritoOff += EL_TORITO_ENTRY_SIZE;

                    isoMetadata.AppendFormat("Boot section {0}:", SECTION_COUNTER);
                    isoMetadata.AppendFormat("\tSection ID: {0}", Encoding.GetString(sectionHeader.identifier))
                    .AppendLine();

                    for (int entryCounter = 1; entryCounter <= sectionHeader.entries && toritoOff < vdSector.Length;
                         entryCounter++)
                    {
                        ElToritoSectionEntry sectionEntry =
                            Marshal.ByteArrayToStructureLittleEndian <ElToritoSectionEntry>(vdSector, toritoOff,
                                                                                            EL_TORITO_ENTRY_SIZE);
                        toritoOff += EL_TORITO_ENTRY_SIZE;

                        isoMetadata.AppendFormat("\tEntry {0}:", entryCounter);
                        if (sectionEntry.bootable == ElToritoIndicator.Bootable)
                        {
                            bootImage =
                                sectionEntry.load_rba + partition.Start + sectionEntry.sector_count - 1 <= partition.End
                                    ? imagePlugin.ReadSectors(sectionEntry.load_rba + partition.Start,
                                                              sectionEntry.sector_count)
                                    : null;

                            isoMetadata.AppendFormat("\t\tBootable on {0}", sectionHeader.platform_id).AppendLine();
                            isoMetadata.AppendFormat("\t\tBootable image starts at sector {0} and runs for {1} sectors",
                                                     sectionEntry.load_rba, sectionEntry.sector_count).AppendLine();
                            if (valentry.platform_id == ElToritoPlatform.x86)
                            {
                                isoMetadata.AppendFormat("\t\tBootable image will be loaded at segment {0:X4}h",
                                                         sectionEntry.load_seg == 0 ? 0x7C0 : sectionEntry.load_seg)
                                .AppendLine();
                            }
                            else
                            {
                                isoMetadata.AppendFormat("\t\tBootable image will be loaded at 0x{0:X8}",
                                                         (uint)sectionEntry.load_seg * 10).AppendLine();
                            }
                            switch ((ElToritoEmulation)((byte)sectionEntry.boot_type & 0xF))
                            {
                            case ElToritoEmulation.None:
                                isoMetadata.AppendLine("\t\tImage uses no emulation");
                                break;

                            case ElToritoEmulation.Md2hd:
                                isoMetadata
                                .AppendLine("\t\tImage emulates a 5.25\" high-density (MD2HD, 1.2Mb) floppy");
                                break;

                            case ElToritoEmulation.Mf2hd:
                                isoMetadata
                                .AppendLine("\t\tImage emulates a 3.5\" high-density (MF2HD, 1.44Mb) floppy");
                                break;

                            case ElToritoEmulation.Mf2ed:
                                isoMetadata
                                .AppendLine("\t\tImage emulates a 3.5\" extra-density (MF2ED, 2.88Mb) floppy");
                                break;

                            default:
                                isoMetadata.AppendFormat("\t\tImage uses unknown emulation type {0}",
                                                         (byte)initialEntry.boot_type).AppendLine();
                                break;
                            }

                            isoMetadata.AppendFormat("\t\tSelection criteria type: {0}",
                                                     sectionEntry.selection_criteria_type).AppendLine();
                            isoMetadata.AppendFormat("\t\tSystem type: 0x{0:X2}", sectionEntry.system_type)
                            .AppendLine();
                            if (bootImage != null)
                            {
                                isoMetadata.AppendFormat("\t\tBootable image's SHA1: {0}",
                                                         Sha1Context.Data(bootImage, out _)).AppendLine();
                            }
                        }
                        else
                        {
                            isoMetadata.AppendLine("\t\tNot bootable");
                        }

                        ElToritoFlags flags = (ElToritoFlags)((byte)sectionEntry.boot_type & 0xF0);
                        if (flags.HasFlag(ElToritoFlags.ATAPI))
                        {
                            isoMetadata.AppendLine("\t\tImage contains ATAPI drivers");
                        }
                        if (flags.HasFlag(ElToritoFlags.SCSI))
                        {
                            isoMetadata.AppendLine("\t\tImage contains SCSI drivers");
                        }

                        if (!flags.HasFlag(ElToritoFlags.Continued))
                        {
                            continue;
                        }

                        while (toritoOff < vdSector.Length)
                        {
                            ElToritoSectionEntryExtension sectionExtension =
                                Marshal.ByteArrayToStructureLittleEndian <ElToritoSectionEntryExtension>(vdSector,
                                                                                                         toritoOff,
                                                                                                         EL_TORITO_ENTRY_SIZE);
                            toritoOff += EL_TORITO_ENTRY_SIZE;

                            if (!sectionExtension.extension_flags.HasFlag(ElToritoFlags.Continued))
                            {
                                break;
                            }
                        }
                    }

                    if (sectionHeader.header_id == ElToritoIndicator.LastHeader)
                    {
                        break;
                    }
                }
            }

exit_torito:
            if (refareas.Count > 0)
            {
                isoMetadata.Append(suspInformation);
            }

            XmlFsType.Type = fsFormat;

            if (jolietvd != null)
            {
                XmlFsType.VolumeName = decodedJolietVd.VolumeIdentifier;

                if (string.IsNullOrEmpty(decodedJolietVd.SystemIdentifier) ||
                    decodedVd.SystemIdentifier.Length > decodedJolietVd.SystemIdentifier.Length)
                {
                    XmlFsType.SystemIdentifier = decodedVd.SystemIdentifier;
                }
                else
                {
                    XmlFsType.SystemIdentifier = string.IsNullOrEmpty(decodedJolietVd.SystemIdentifier)
                                                     ? null
                                                     : decodedJolietVd.SystemIdentifier;
                }

                if (string.IsNullOrEmpty(decodedJolietVd.VolumeSetIdentifier) || decodedVd.VolumeSetIdentifier.Length >
                    decodedJolietVd.VolumeSetIdentifier.Length)
                {
                    XmlFsType.VolumeSetIdentifier = decodedVd.VolumeSetIdentifier;
                }
                else
                {
                    XmlFsType.VolumeSetIdentifier = string.IsNullOrEmpty(decodedJolietVd.VolumeSetIdentifier)
                                                        ? null
                                                        : decodedJolietVd.VolumeSetIdentifier;
                }

                if (string.IsNullOrEmpty(decodedJolietVd.PublisherIdentifier) || decodedVd.PublisherIdentifier.Length >
                    decodedJolietVd.PublisherIdentifier.Length)
                {
                    XmlFsType.PublisherIdentifier = decodedVd.PublisherIdentifier;
                }
                else
                {
                    XmlFsType.PublisherIdentifier = string.IsNullOrEmpty(decodedJolietVd.PublisherIdentifier)
                                                        ? null
                                                        : decodedJolietVd.PublisherIdentifier;
                }

                if (string.IsNullOrEmpty(decodedJolietVd.DataPreparerIdentifier) ||
                    decodedVd.DataPreparerIdentifier.Length > decodedJolietVd.DataPreparerIdentifier.Length)
                {
                    XmlFsType.DataPreparerIdentifier = decodedVd.DataPreparerIdentifier;
                }
                else
                {
                    XmlFsType.DataPreparerIdentifier = string.IsNullOrEmpty(decodedJolietVd.DataPreparerIdentifier)
                                                           ? null
                                                           : decodedJolietVd.DataPreparerIdentifier;
                }

                if (string.IsNullOrEmpty(decodedJolietVd.ApplicationIdentifier) ||
                    decodedVd.ApplicationIdentifier.Length > decodedJolietVd.ApplicationIdentifier.Length)
                {
                    XmlFsType.ApplicationIdentifier = decodedVd.ApplicationIdentifier;
                }
                else
                {
                    XmlFsType.ApplicationIdentifier = string.IsNullOrEmpty(decodedJolietVd.ApplicationIdentifier)
                                                          ? null
                                                          : decodedJolietVd.ApplicationIdentifier;
                }

                XmlFsType.CreationDate          = decodedJolietVd.CreationTime;
                XmlFsType.CreationDateSpecified = true;
                if (decodedJolietVd.HasModificationTime)
                {
                    XmlFsType.ModificationDate          = decodedJolietVd.ModificationTime;
                    XmlFsType.ModificationDateSpecified = true;
                }

                if (decodedJolietVd.HasExpirationTime)
                {
                    XmlFsType.ExpirationDate          = decodedJolietVd.ExpirationTime;
                    XmlFsType.ExpirationDateSpecified = true;
                }

                if (decodedJolietVd.HasEffectiveTime)
                {
                    XmlFsType.EffectiveDate          = decodedJolietVd.EffectiveTime;
                    XmlFsType.EffectiveDateSpecified = true;
                }
            }
            else
            {
                XmlFsType.SystemIdentifier       = decodedVd.SystemIdentifier;
                XmlFsType.VolumeName             = decodedVd.VolumeIdentifier;
                XmlFsType.VolumeSetIdentifier    = decodedVd.VolumeSetIdentifier;
                XmlFsType.PublisherIdentifier    = decodedVd.PublisherIdentifier;
                XmlFsType.DataPreparerIdentifier = decodedVd.DataPreparerIdentifier;
                XmlFsType.ApplicationIdentifier  = decodedVd.ApplicationIdentifier;
                XmlFsType.CreationDate           = decodedVd.CreationTime;
                XmlFsType.CreationDateSpecified  = true;
                if (decodedVd.HasModificationTime)
                {
                    XmlFsType.ModificationDate          = decodedVd.ModificationTime;
                    XmlFsType.ModificationDateSpecified = true;
                }

                if (decodedVd.HasExpirationTime)
                {
                    XmlFsType.ExpirationDate          = decodedVd.ExpirationTime;
                    XmlFsType.ExpirationDateSpecified = true;
                }

                if (decodedVd.HasEffectiveTime)
                {
                    XmlFsType.EffectiveDate          = decodedVd.EffectiveTime;
                    XmlFsType.EffectiveDateSpecified = true;
                }
            }

            XmlFsType.Bootable   |= bvd != null || segaCd != null || saturn != null || dreamcast != null;
            XmlFsType.Clusters    = decodedVd.Blocks;
            XmlFsType.ClusterSize = decodedVd.BlockSize;

            information = isoMetadata.ToString();
        }
Ejemplo n.º 17
0
        public static void ServerSetup(
            FileSystemType fsType,
            SignState sutSignState,
            bool isSupportDfs,
            bool isSupportPreviousVersion,
            bool isMessageModePipe)
        {
            Condition.IsTrue(smbState == SmbState.ConnectionSuccess);

            if (Parameter.sutPlatform != Platform.NonWindows)
            {
                if (Parameter.sutPlatform == Platform.Win2K3)
                {
                    // It is not possible to disable the DFS capability from the WS03 the SUT.
                    Condition.IsTrue(isSupportDfs);
                }
            }

            if (Parameter.sutPlatform != Platform.NonWindows)
            {
                if (fsType == FileSystemType.Fat)
                {
                    Parameter.isSupportQuota = false;
                    // In Windows, the Generic file system (FAT) does not support File IDs.
                    Parameter.isSupportUniqueFileId = false;
                    // FAT does not support streams.
                    Parameter.isSupportStream = false;
                    // FAT does not support the previous version.
                    Condition.IsTrue(!isSupportPreviousVersion);

                    Requirement.AssumeCaptured("Server doesn't support stream");
                }
                else
                {
                    Parameter.isSupportQuota = true;
                    // In Windows, the Generic file system (NTFS) file system supports File IDs.
                    Parameter.isSupportUniqueFileId = true;
                    // NTFS supports streams.
                    Parameter.isSupportStream = true;
                    // NTFS supports the previous version.
                    Condition.IsTrue(isSupportPreviousVersion);
                    Requirement.AssumeCaptured("Server doesn't support stream");
                }
            }

            Parameter.isSupportPreviousVersion = isSupportPreviousVersion;
            Parameter.fsType = fsType;
            Parameter.isSupportDfs = isSupportDfs;
            Parameter.sutSignState = sutSignState;
            Parameter.isMessageModePipe = isMessageModePipe;
            smbState = SmbState.ServerSetupRequest;
        }
Ejemplo n.º 18
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            Encoding    = new LisaRoman();
            information = "";
            StringBuilder sb = new StringBuilder();

            try
            {
                if (imagePlugin.Info.ReadableSectorTags == null)
                {
                    return;
                }

                if (!imagePlugin.Info.ReadableSectorTags.Contains(SectorTagType.AppleSectorTag))
                {
                    return;
                }

                // LisaOS is big-endian
                BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian;

                // Minimal LisaOS disk is 3.5" single sided double density, 800 sectors
                if (imagePlugin.Info.Sectors < 800)
                {
                    return;
                }

                int beforeMddf = -1;

                // LisaOS searches sectors until tag tells MDDF resides there, so we'll search 100 sectors
                for (int i = 0; i < 100; i++)
                {
                    DecodeTag(imagePlugin.ReadSectorTag((ulong)i, SectorTagType.AppleSectorTag),
                              out LisaTag.PriamTag searchTag);

                    DicConsole.DebugWriteLine("LisaFS plugin", "Sector {0}, file ID 0x{1:X4}", i, searchTag.FileId);

                    if (beforeMddf == -1 && searchTag.FileId == FILEID_LOADER_SIGNED)
                    {
                        beforeMddf = i - 1;
                    }

                    if (searchTag.FileId != FILEID_MDDF)
                    {
                        continue;
                    }

                    byte[] sector   = imagePlugin.ReadSector((ulong)i);
                    MDDF   infoMddf = new MDDF();
                    byte[] pString  = new byte[33];

                    infoMddf.fsversion = BigEndianBitConverter.ToUInt16(sector, 0x00);
                    infoMddf.volid     = BigEndianBitConverter.ToUInt64(sector, 0x02);
                    infoMddf.volnum    = BigEndianBitConverter.ToUInt16(sector, 0x0A);
                    Array.Copy(sector, 0x0C, pString, 0, 33);
                    infoMddf.volname  = StringHandlers.PascalToString(pString, Encoding);
                    infoMddf.unknown1 = sector[0x2D];
                    Array.Copy(sector, 0x2E, pString, 0, 33);
                    // Prevent garbage
                    infoMddf.password       = pString[0] <= 32 ? StringHandlers.PascalToString(pString, Encoding) : "";
                    infoMddf.unknown2       = sector[0x4F];
                    infoMddf.machine_id     = BigEndianBitConverter.ToUInt32(sector, 0x50);
                    infoMddf.master_copy_id = BigEndianBitConverter.ToUInt32(sector, 0x54);
                    uint lisaTime = BigEndianBitConverter.ToUInt32(sector, 0x58);
                    infoMddf.dtvc                         = DateHandlers.LisaToDateTime(lisaTime);
                    lisaTime                              = BigEndianBitConverter.ToUInt32(sector, 0x5C);
                    infoMddf.dtcc                         = DateHandlers.LisaToDateTime(lisaTime);
                    lisaTime                              = BigEndianBitConverter.ToUInt32(sector, 0x60);
                    infoMddf.dtvb                         = DateHandlers.LisaToDateTime(lisaTime);
                    lisaTime                              = BigEndianBitConverter.ToUInt32(sector, 0x64);
                    infoMddf.dtvs                         = DateHandlers.LisaToDateTime(lisaTime);
                    infoMddf.unknown3                     = BigEndianBitConverter.ToUInt32(sector, 0x68);
                    infoMddf.mddf_block                   = BigEndianBitConverter.ToUInt32(sector, 0x6C);
                    infoMddf.volsize_minus_one            = BigEndianBitConverter.ToUInt32(sector, 0x70);
                    infoMddf.volsize_minus_mddf_minus_one = BigEndianBitConverter.ToUInt32(sector, 0x74);
                    infoMddf.vol_size                     = BigEndianBitConverter.ToUInt32(sector, 0x78);
                    infoMddf.blocksize                    = BigEndianBitConverter.ToUInt16(sector, 0x7C);
                    infoMddf.datasize                     = BigEndianBitConverter.ToUInt16(sector, 0x7E);
                    infoMddf.unknown4                     = BigEndianBitConverter.ToUInt16(sector, 0x80);
                    infoMddf.unknown5                     = BigEndianBitConverter.ToUInt32(sector, 0x82);
                    infoMddf.unknown6                     = BigEndianBitConverter.ToUInt32(sector, 0x86);
                    infoMddf.clustersize                  = BigEndianBitConverter.ToUInt16(sector, 0x8A);
                    infoMddf.fs_size                      = BigEndianBitConverter.ToUInt32(sector, 0x8C);
                    infoMddf.unknown7                     = BigEndianBitConverter.ToUInt32(sector, 0x90);
                    infoMddf.srec_ptr                     = BigEndianBitConverter.ToUInt32(sector, 0x94);
                    infoMddf.unknown9                     = BigEndianBitConverter.ToUInt16(sector, 0x98);
                    infoMddf.srec_len                     = BigEndianBitConverter.ToUInt16(sector, 0x9A);
                    infoMddf.unknown10                    = BigEndianBitConverter.ToUInt32(sector, 0x9C);
                    infoMddf.unknown11                    = BigEndianBitConverter.ToUInt32(sector, 0xA0);
                    infoMddf.unknown12                    = BigEndianBitConverter.ToUInt32(sector, 0xA4);
                    infoMddf.unknown13                    = BigEndianBitConverter.ToUInt32(sector, 0xA8);
                    infoMddf.unknown14                    = BigEndianBitConverter.ToUInt32(sector, 0xAC);
                    infoMddf.filecount                    = BigEndianBitConverter.ToUInt16(sector, 0xB0);
                    infoMddf.unknown15                    = BigEndianBitConverter.ToUInt32(sector, 0xB2);
                    infoMddf.unknown16                    = BigEndianBitConverter.ToUInt32(sector, 0xB6);
                    infoMddf.freecount                    = BigEndianBitConverter.ToUInt32(sector, 0xBA);
                    infoMddf.unknown17                    = BigEndianBitConverter.ToUInt16(sector, 0xBE);
                    infoMddf.unknown18                    = BigEndianBitConverter.ToUInt32(sector, 0xC0);
                    infoMddf.overmount_stamp              = BigEndianBitConverter.ToUInt64(sector, 0xC4);
                    infoMddf.serialization                = BigEndianBitConverter.ToUInt32(sector, 0xCC);
                    infoMddf.unknown19                    = BigEndianBitConverter.ToUInt32(sector, 0xD0);
                    infoMddf.unknown_timestamp            = BigEndianBitConverter.ToUInt32(sector, 0xD4);
                    infoMddf.unknown20                    = BigEndianBitConverter.ToUInt32(sector, 0xD8);
                    infoMddf.unknown21                    = BigEndianBitConverter.ToUInt32(sector, 0xDC);
                    infoMddf.unknown22                    = BigEndianBitConverter.ToUInt32(sector, 0xE0);
                    infoMddf.unknown23                    = BigEndianBitConverter.ToUInt32(sector, 0xE4);
                    infoMddf.unknown24                    = BigEndianBitConverter.ToUInt32(sector, 0xE8);
                    infoMddf.unknown25                    = BigEndianBitConverter.ToUInt32(sector, 0xEC);
                    infoMddf.unknown26                    = BigEndianBitConverter.ToUInt32(sector, 0xF0);
                    infoMddf.unknown27                    = BigEndianBitConverter.ToUInt32(sector, 0xF4);
                    infoMddf.unknown28                    = BigEndianBitConverter.ToUInt32(sector, 0xF8);
                    infoMddf.unknown29                    = BigEndianBitConverter.ToUInt32(sector, 0xFC);
                    infoMddf.unknown30                    = BigEndianBitConverter.ToUInt32(sector, 0x100);
                    infoMddf.unknown31                    = BigEndianBitConverter.ToUInt32(sector, 0x104);
                    infoMddf.unknown32                    = BigEndianBitConverter.ToUInt32(sector, 0x108);
                    infoMddf.unknown33                    = BigEndianBitConverter.ToUInt32(sector, 0x10C);
                    infoMddf.unknown34                    = BigEndianBitConverter.ToUInt32(sector, 0x110);
                    infoMddf.unknown35                    = BigEndianBitConverter.ToUInt32(sector, 0x114);
                    infoMddf.backup_volid                 = BigEndianBitConverter.ToUInt64(sector, 0x118);
                    infoMddf.label_size                   = BigEndianBitConverter.ToUInt16(sector, 0x120);
                    infoMddf.fs_overhead                  = BigEndianBitConverter.ToUInt16(sector, 0x122);
                    infoMddf.result_scavenge              = BigEndianBitConverter.ToUInt16(sector, 0x124);
                    infoMddf.boot_code                    = BigEndianBitConverter.ToUInt16(sector, 0x126);
                    infoMddf.boot_environ                 = BigEndianBitConverter.ToUInt16(sector, 0x6C);
                    infoMddf.unknown36                    = BigEndianBitConverter.ToUInt32(sector, 0x12A);
                    infoMddf.unknown37                    = BigEndianBitConverter.ToUInt32(sector, 0x12E);
                    infoMddf.unknown38                    = BigEndianBitConverter.ToUInt32(sector, 0x132);
                    infoMddf.vol_sequence                 = BigEndianBitConverter.ToUInt16(sector, 0x136);
                    infoMddf.vol_left_mounted             = sector[0x138];

                    DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown1 = 0x{0:X2} ({0})", infoMddf.unknown1);
                    DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown2 = 0x{0:X2} ({0})", infoMddf.unknown2);
                    DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown3 = 0x{0:X8} ({0})", infoMddf.unknown3);
                    DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown4 = 0x{0:X4} ({0})", infoMddf.unknown4);
                    DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown5 = 0x{0:X8} ({0})", infoMddf.unknown5);
                    DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown6 = 0x{0:X8} ({0})", infoMddf.unknown6);
                    DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown7 = 0x{0:X8} ({0})", infoMddf.unknown7);
                    DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown9 = 0x{0:X4} ({0})", infoMddf.unknown9);
                    DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown10 = 0x{0:X8} ({0})", infoMddf.unknown10);
                    DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown11 = 0x{0:X8} ({0})", infoMddf.unknown11);
                    DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown12 = 0x{0:X8} ({0})", infoMddf.unknown12);
                    DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown13 = 0x{0:X8} ({0})", infoMddf.unknown13);
                    DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown14 = 0x{0:X8} ({0})", infoMddf.unknown14);
                    DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown15 = 0x{0:X8} ({0})", infoMddf.unknown15);
                    DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown16 = 0x{0:X8} ({0})", infoMddf.unknown16);
                    DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown17 = 0x{0:X4} ({0})", infoMddf.unknown17);
                    DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown18 = 0x{0:X8} ({0})", infoMddf.unknown18);
                    DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown19 = 0x{0:X8} ({0})", infoMddf.unknown19);
                    DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown20 = 0x{0:X8} ({0})", infoMddf.unknown20);
                    DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown21 = 0x{0:X8} ({0})", infoMddf.unknown21);
                    DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown22 = 0x{0:X8} ({0})", infoMddf.unknown22);
                    DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown23 = 0x{0:X8} ({0})", infoMddf.unknown23);
                    DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown24 = 0x{0:X8} ({0})", infoMddf.unknown24);
                    DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown25 = 0x{0:X8} ({0})", infoMddf.unknown25);
                    DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown26 = 0x{0:X8} ({0})", infoMddf.unknown26);
                    DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown27 = 0x{0:X8} ({0})", infoMddf.unknown27);
                    DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown28 = 0x{0:X8} ({0})", infoMddf.unknown28);
                    DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown29 = 0x{0:X8} ({0})", infoMddf.unknown29);
                    DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown30 = 0x{0:X8} ({0})", infoMddf.unknown30);
                    DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown31 = 0x{0:X8} ({0})", infoMddf.unknown31);
                    DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown32 = 0x{0:X8} ({0})", infoMddf.unknown32);
                    DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown33 = 0x{0:X8} ({0})", infoMddf.unknown33);
                    DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown34 = 0x{0:X8} ({0})", infoMddf.unknown34);
                    DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown35 = 0x{0:X8} ({0})", infoMddf.unknown35);
                    DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown36 = 0x{0:X8} ({0})", infoMddf.unknown36);
                    DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown37 = 0x{0:X8} ({0})", infoMddf.unknown37);
                    DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown38 = 0x{0:X8} ({0})", infoMddf.unknown38);
                    DicConsole.DebugWriteLine("LisaFS plugin", "mddf.unknown_timestamp = 0x{0:X8} ({0}, {1})",
                                              infoMddf.unknown_timestamp,
                                              DateHandlers.LisaToDateTime(infoMddf.unknown_timestamp));

                    if (infoMddf.mddf_block != i - beforeMddf)
                    {
                        return;
                    }

                    if (infoMddf.vol_size > imagePlugin.Info.Sectors)
                    {
                        return;
                    }

                    if (infoMddf.vol_size - 1 != infoMddf.volsize_minus_one)
                    {
                        return;
                    }

                    if (infoMddf.vol_size - i - 1 != infoMddf.volsize_minus_mddf_minus_one - beforeMddf)
                    {
                        return;
                    }

                    if (infoMddf.datasize > infoMddf.blocksize)
                    {
                        return;
                    }

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

                    if (infoMddf.datasize != imagePlugin.Info.SectorSize)
                    {
                        return;
                    }

                    switch (infoMddf.fsversion)
                    {
                    case LISA_V1:
                        sb.AppendLine("LisaFS v1");
                        break;

                    case LISA_V2:
                        sb.AppendLine("LisaFS v2");
                        break;

                    case LISA_V3:
                        sb.AppendLine("LisaFS v3");
                        break;

                    default:
                        sb.AppendFormat("Uknown LisaFS version {0}", infoMddf.fsversion).AppendLine();
                        break;
                    }

                    sb.AppendFormat("Volume name: \"{0}\"", infoMddf.volname).AppendLine();
                    sb.AppendFormat("Volume password: \"{0}\"", infoMddf.password).AppendLine();
                    sb.AppendFormat("Volume ID: 0x{0:X16}", infoMddf.volid).AppendLine();
                    sb.AppendFormat("Backup volume ID: 0x{0:X16}", infoMddf.backup_volid).AppendLine();

                    sb.AppendFormat("Master copy ID: 0x{0:X8}", infoMddf.master_copy_id).AppendLine();

                    sb.AppendFormat("Volume is number {0} of {1}", infoMddf.volnum, infoMddf.vol_sequence).AppendLine();

                    sb.AppendFormat("Serial number of Lisa computer that created this volume: {0}", infoMddf.machine_id)
                    .AppendLine();
                    sb.AppendFormat("Serial number of Lisa computer that can use this volume's software {0}",
                                    infoMddf.serialization).AppendLine();

                    sb.AppendFormat("Volume created on {0}", infoMddf.dtvc).AppendLine();
                    sb.AppendFormat("Some timestamp, says {0}", infoMddf.dtcc).AppendLine();
                    sb.AppendFormat("Volume backed up on {0}", infoMddf.dtvb).AppendLine();
                    sb.AppendFormat("Volume scavenged on {0}", infoMddf.dtvs).AppendLine();
                    sb.AppendFormat("MDDF is in block {0}", infoMddf.mddf_block + beforeMddf).AppendLine();
                    sb.AppendFormat("There are {0} reserved blocks before volume", beforeMddf).AppendLine();
                    sb.AppendFormat("{0} blocks minus one", infoMddf.volsize_minus_one).AppendLine();
                    sb.AppendFormat("{0} blocks minus one minus MDDF offset", infoMddf.volsize_minus_mddf_minus_one)
                    .AppendLine();
                    sb.AppendFormat("{0} blocks in volume", infoMddf.vol_size).AppendLine();
                    sb.AppendFormat("{0} bytes per sector (uncooked)", infoMddf.blocksize).AppendLine();
                    sb.AppendFormat("{0} bytes per sector", infoMddf.datasize).AppendLine();
                    sb.AppendFormat("{0} blocks per cluster", infoMddf.clustersize).AppendLine();
                    sb.AppendFormat("{0} blocks in filesystem", infoMddf.fs_size).AppendLine();
                    sb.AppendFormat("{0} files in volume", infoMddf.filecount).AppendLine();
                    sb.AppendFormat("{0} blocks free", infoMddf.freecount).AppendLine();
                    sb.AppendFormat("{0} bytes in LisaInfo", infoMddf.label_size).AppendLine();
                    sb.AppendFormat("Filesystem overhead: {0}", infoMddf.fs_overhead).AppendLine();
                    sb.AppendFormat("Scanvenger result code: 0x{0:X8}", infoMddf.result_scavenge).AppendLine();
                    sb.AppendFormat("Boot code: 0x{0:X8}", infoMddf.boot_code).AppendLine();
                    sb.AppendFormat("Boot environment:  0x{0:X8}", infoMddf.boot_environ).AppendLine();
                    sb.AppendFormat("Overmount stamp: 0x{0:X16}", infoMddf.overmount_stamp).AppendLine();
                    sb.AppendFormat("S-Records start at {0} and spans for {1} blocks",
                                    infoMddf.srec_ptr + infoMddf.mddf_block + beforeMddf, infoMddf.srec_len)
                    .AppendLine();

                    sb.AppendLine(infoMddf.vol_left_mounted == 0 ? "Volume is clean" : "Volume is dirty");

                    information = sb.ToString();

                    XmlFsType = new FileSystemType();
                    if (DateTime.Compare(infoMddf.dtvb, DateHandlers.LisaToDateTime(0)) > 0)
                    {
                        XmlFsType.BackupDate          = infoMddf.dtvb;
                        XmlFsType.BackupDateSpecified = true;
                    }

                    XmlFsType.Clusters    = infoMddf.vol_size;
                    XmlFsType.ClusterSize = infoMddf.clustersize * infoMddf.datasize;
                    if (DateTime.Compare(infoMddf.dtvc, DateHandlers.LisaToDateTime(0)) > 0)
                    {
                        XmlFsType.CreationDate          = infoMddf.dtvc;
                        XmlFsType.CreationDateSpecified = true;
                    }

                    XmlFsType.Dirty                 = infoMddf.vol_left_mounted != 0;
                    XmlFsType.Files                 = infoMddf.filecount;
                    XmlFsType.FilesSpecified        = true;
                    XmlFsType.FreeClusters          = infoMddf.freecount;
                    XmlFsType.FreeClustersSpecified = true;
                    XmlFsType.Type         = "LisaFS";
                    XmlFsType.VolumeName   = infoMddf.volname;
                    XmlFsType.VolumeSerial = $"{infoMddf.volid:X16}";

                    return;
                }
            }
            catch (Exception ex)
            {
                DicConsole.ErrorWriteLine("Exception {0}, {1}, {2}", ex.Message, ex.InnerException, ex.StackTrace);
            }
        }
Ejemplo n.º 19
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;
            }

            UNICOS_Superblock unicosSb = new UNICOS_Superblock();

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

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

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

            unicosSb = BigEndianMarshal.ByteArrayToStructureBigEndian <UNICOS_Superblock>(sector);

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

            StringBuilder 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                  = unicosSb.s_fsize,
                VolumeName                = StringHandlers.CToString(unicosSb.s_fname, Encoding),
                ModificationDate          = DateHandlers.UnixToDateTime(unicosSb.s_time),
                ModificationDateSpecified = true
            };
            XmlFsType.Dirty |= unicosSb.s_error > 0;
        }
Ejemplo n.º 20
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            Encoding = encoding ?? Encoding.GetEncoding("iso-8859-15");
            StringBuilder sbInformation = new StringBuilder();

            XmlFsType   = new FileSystemType();
            information = "";

            ulong sbSectorOff  = 0x10000 / imagePlugin.Info.SectorSize;
            uint  sbSectorSize = 0x1000 / imagePlugin.Info.SectorSize;

            byte[] sector = imagePlugin.ReadSectors(sbSectorOff + partition.Start, sbSectorSize);

            GCHandle   handle  = GCHandle.Alloc(sector, GCHandleType.Pinned);
            SuperBlock btrfsSb = (SuperBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(SuperBlock));

            handle.Free();

            DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.checksum = {0}", btrfsSb.checksum);
            DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.uuid = {0}", btrfsSb.uuid);
            DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.pba = {0}", btrfsSb.pba);
            DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.flags = {0}", btrfsSb.flags);
            DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.magic = {0}", btrfsSb.magic);
            DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.generation = {0}", btrfsSb.generation);
            DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.root_lba = {0}", btrfsSb.root_lba);
            DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.chunk_lba = {0}", btrfsSb.chunk_lba);
            DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.log_lba = {0}", btrfsSb.log_lba);
            DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.log_root_transid = {0}", btrfsSb.log_root_transid);
            DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.total_bytes = {0}", btrfsSb.total_bytes);
            DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.bytes_used = {0}", btrfsSb.bytes_used);
            DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.root_dir_objectid = {0}", btrfsSb.root_dir_objectid);
            DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.num_devices = {0}", btrfsSb.num_devices);
            DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.sectorsize = {0}", btrfsSb.sectorsize);
            DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.nodesize = {0}", btrfsSb.nodesize);
            DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.leafsize = {0}", btrfsSb.leafsize);
            DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.stripesize = {0}", btrfsSb.stripesize);
            DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.n = {0}", btrfsSb.n);
            DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.chunk_root_generation = {0}",
                                      btrfsSb.chunk_root_generation);
            DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.compat_flags = 0x{0:X16}", btrfsSb.compat_flags);
            DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.compat_ro_flags = 0x{0:X16}", btrfsSb.compat_ro_flags);
            DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.incompat_flags = 0x{0:X16}", btrfsSb.incompat_flags);
            DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.csum_type = {0}", btrfsSb.csum_type);
            DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.root_level = {0}", btrfsSb.root_level);
            DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.chunk_root_level = {0}", btrfsSb.chunk_root_level);
            DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.log_root_level = {0}", btrfsSb.log_root_level);
            DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.dev_item.id = 0x{0:X16}", btrfsSb.dev_item.id);
            DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.dev_item.bytes = {0}", btrfsSb.dev_item.bytes);
            DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.dev_item.used = {0}", btrfsSb.dev_item.used);
            DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.dev_item.optimal_align = {0}",
                                      btrfsSb.dev_item.optimal_align);
            DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.dev_item.optimal_width = {0}",
                                      btrfsSb.dev_item.optimal_width);
            DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.dev_item.minimal_size = {0}",
                                      btrfsSb.dev_item.minimal_size);
            DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.dev_item.type = {0}", btrfsSb.dev_item.type);
            DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.dev_item.generation = {0}", btrfsSb.dev_item.generation);
            DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.dev_item.start_offset = {0}",
                                      btrfsSb.dev_item.start_offset);
            DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.dev_item.dev_group = {0}", btrfsSb.dev_item.dev_group);
            DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.dev_item.seek_speed = {0}", btrfsSb.dev_item.seek_speed);
            DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.dev_item.bandwitdh = {0}", btrfsSb.dev_item.bandwitdh);
            DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.dev_item.device_uuid = {0}",
                                      btrfsSb.dev_item.device_uuid);
            DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.dev_item.uuid = {0}", btrfsSb.dev_item.uuid);
            DicConsole.DebugWriteLine("BTRFS Plugin", "btrfsSb.label = {0}", btrfsSb.label);

            sbInformation.AppendLine("B-tree filesystem");
            sbInformation.AppendFormat("UUID: {0}", btrfsSb.uuid).AppendLine();
            sbInformation.AppendFormat("This superblock resides on physical block {0}", btrfsSb.pba).AppendLine();
            sbInformation.AppendFormat("Root tree starts at LBA {0}", btrfsSb.root_lba).AppendLine();
            sbInformation.AppendFormat("Chunk tree starts at LBA {0}", btrfsSb.chunk_lba).AppendLine();
            sbInformation.AppendFormat("Log tree starts at LBA {0}", btrfsSb.log_lba).AppendLine();
            sbInformation.AppendFormat("Volume has {0} bytes spanned in {1} devices", btrfsSb.total_bytes,
                                       btrfsSb.num_devices).AppendLine();
            sbInformation.AppendFormat("Volume has {0} bytes used", btrfsSb.bytes_used).AppendLine();
            sbInformation.AppendFormat("{0} bytes/sector", btrfsSb.sectorsize).AppendLine();
            sbInformation.AppendFormat("{0} bytes/node", btrfsSb.nodesize).AppendLine();
            sbInformation.AppendFormat("{0} bytes/leaf", btrfsSb.leafsize).AppendLine();
            sbInformation.AppendFormat("{0} bytes/stripe", btrfsSb.stripesize).AppendLine();
            sbInformation.AppendFormat("Flags: 0x{0:X}", btrfsSb.flags).AppendLine();
            sbInformation.AppendFormat("Compatible flags: 0x{0:X}", btrfsSb.compat_flags).AppendLine();
            sbInformation.AppendFormat("Read-only compatible flags: 0x{0:X}", btrfsSb.compat_ro_flags).AppendLine();
            sbInformation.AppendFormat("Incompatible flags: 0x{0:X}", btrfsSb.incompat_flags).AppendLine();
            sbInformation.AppendFormat("Device's UUID: {0}", btrfsSb.dev_item.uuid).AppendLine();
            sbInformation.AppendFormat("Volume label: {0}", btrfsSb.label).AppendLine();

            information = sbInformation.ToString();

            XmlFsType = new FileSystemType
            {
                Clusters              = (long)(btrfsSb.total_bytes / btrfsSb.sectorsize),
                ClusterSize           = (int)btrfsSb.sectorsize,
                FreeClustersSpecified = true,
                VolumeName            = btrfsSb.label,
                VolumeSerial          = $"{btrfsSb.uuid}",
                VolumeSetIdentifier   = $"{btrfsSb.dev_item.device_uuid}",
                Type = Name
            };
            XmlFsType.FreeClusters = XmlFsType.Clusters - (long)(btrfsSb.bytes_used / btrfsSb.sectorsize);
        }
Ejemplo n.º 21
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            Encoding    = encoding ?? Encoding.GetEncoding("IBM437");
            information = "";

            var sb = new StringBuilder();

            XmlFsType = new FileSystemType();

            uint sectorsPerBpb = imagePlugin.Info.SectorSize < 512 ? 512 / imagePlugin.Info.SectorSize : 1;

            byte[] bpbSector = imagePlugin.ReadSectors(0 + partition.Start, sectorsPerBpb);

            BpbKind bpbKind = DetectBpbKind(bpbSector, imagePlugin, partition, out BiosParameterBlockEbpb fakeBpb,
                                            out HumanParameterBlock humanBpb, out AtariParameterBlock atariBpb,
                                            out byte minBootNearJump, out bool andosOemCorrect, out bool bootable);

            bool   isFat12             = false;
            bool   isFat16             = false;
            bool   isFat32             = false;
            ulong  rootDirectorySector = 0;
            string extraInfo           = null;
            string bootChk             = null;

            XmlFsType.Bootable = bootable;

            // This is needed because for FAT16, GEMDOS increases bytes per sector count instead of using big_sectors field.
            uint sectorsPerRealSector;

            // This is needed because some OSes don't put volume label as first entry in the root directory
            uint sectorsForRootDirectory = 0;

            switch (bpbKind)
            {
            case BpbKind.DecRainbow:
            case BpbKind.Hardcoded:
            case BpbKind.Msx:
            case BpbKind.Apricot:
                isFat12 = true;

                break;

            case BpbKind.ShortFat32:
            case BpbKind.LongFat32:
            {
                isFat32 = true;

                Fat32ParameterBlock fat32Bpb =
                    Marshal.ByteArrayToStructureLittleEndian <Fat32ParameterBlock>(bpbSector);

                Fat32ParameterBlockShort shortFat32Bpb =
                    Marshal.ByteArrayToStructureLittleEndian <Fat32ParameterBlockShort>(bpbSector);

                // This is to support FAT partitions on hybrid ISO/USB images
                if (imagePlugin.Info.XmlMediaType == XmlMediaType.OpticalDisc)
                {
                    fat32Bpb.bps       *= 4;
                    fat32Bpb.spc       /= 4;
                    fat32Bpb.big_spfat /= 4;
                    fat32Bpb.hsectors  /= 4;
                    fat32Bpb.sptrk     /= 4;
                }

                if (fat32Bpb.version != 0)
                {
                    sb.AppendLine("FAT+");
                    XmlFsType.Type = "FAT+";
                }
                else
                {
                    sb.AppendLine("Microsoft FAT32");
                    XmlFsType.Type = "FAT32";
                }

                if (fat32Bpb.oem_name != null)
                {
                    if (fat32Bpb.oem_name[5] == 0x49 &&
                        fat32Bpb.oem_name[6] == 0x48 &&
                        fat32Bpb.oem_name[7] == 0x43)
                    {
                        sb.AppendLine("Volume has been modified by Windows 9x/Me Volume Tracker.");
                    }
                    else
                    {
                        XmlFsType.SystemIdentifier = StringHandlers.CToString(fat32Bpb.oem_name);
                    }
                }

                if (!string.IsNullOrEmpty(XmlFsType.SystemIdentifier))
                {
                    sb.AppendFormat("OEM Name: {0}", XmlFsType.SystemIdentifier.Trim()).AppendLine();
                }

                sb.AppendFormat("{0} bytes per sector.", fat32Bpb.bps).AppendLine();
                sb.AppendFormat("{0} sectors per cluster.", fat32Bpb.spc).AppendLine();
                XmlFsType.ClusterSize = (uint)(fat32Bpb.bps * fat32Bpb.spc);
                sb.AppendFormat("{0} sectors reserved between BPB and FAT.", fat32Bpb.rsectors).AppendLine();

                if (fat32Bpb.big_sectors == 0 &&
                    fat32Bpb.signature == 0x28)
                {
                    sb.AppendFormat("{0} sectors on volume ({1} bytes).", shortFat32Bpb.huge_sectors,
                                    shortFat32Bpb.huge_sectors * shortFat32Bpb.bps).AppendLine();

                    XmlFsType.Clusters = shortFat32Bpb.huge_sectors / shortFat32Bpb.spc;
                }
                else
                {
                    sb.AppendFormat("{0} sectors on volume ({1} bytes).", fat32Bpb.big_sectors,
                                    fat32Bpb.big_sectors * fat32Bpb.bps).AppendLine();

                    XmlFsType.Clusters = fat32Bpb.big_sectors / fat32Bpb.spc;
                }

                sb.AppendFormat("{0} clusters on volume.", XmlFsType.Clusters).AppendLine();
                sb.AppendFormat("Media descriptor: 0x{0:X2}", fat32Bpb.media).AppendLine();
                sb.AppendFormat("{0} sectors per FAT.", fat32Bpb.big_spfat).AppendLine();
                sb.AppendFormat("{0} sectors per track.", fat32Bpb.sptrk).AppendLine();
                sb.AppendFormat("{0} heads.", fat32Bpb.heads).AppendLine();
                sb.AppendFormat("{0} hidden sectors before BPB.", fat32Bpb.hsectors).AppendLine();
                sb.AppendFormat("Cluster of root directory: {0}", fat32Bpb.root_cluster).AppendLine();
                sb.AppendFormat("Sector of FSINFO structure: {0}", fat32Bpb.fsinfo_sector).AppendLine();
                sb.AppendFormat("Sector of backup FAT32 parameter block: {0}", fat32Bpb.backup_sector).AppendLine();
                sb.AppendFormat("Drive number: 0x{0:X2}", fat32Bpb.drive_no).AppendLine();
                sb.AppendFormat("Volume Serial Number: 0x{0:X8}", fat32Bpb.serial_no).AppendLine();
                XmlFsType.VolumeSerial = $"{fat32Bpb.serial_no:X8}";

                if ((fat32Bpb.flags & 0xF8) == 0x00)
                {
                    if ((fat32Bpb.flags & 0x01) == 0x01)
                    {
                        sb.AppendLine("Volume should be checked on next mount.");
                        XmlFsType.Dirty = true;
                    }

                    if ((fat32Bpb.flags & 0x02) == 0x02)
                    {
                        sb.AppendLine("Disk surface should be on next mount.");
                    }
                }

                if ((fat32Bpb.mirror_flags & 0x80) == 0x80)
                {
                    sb.AppendFormat("FATs are out of sync. FAT #{0} is in use.", fat32Bpb.mirror_flags & 0xF).
                    AppendLine();
                }
                else
                {
                    sb.AppendLine("All copies of FAT are the same.");
                }

                if ((fat32Bpb.mirror_flags & 0x6F20) == 0x6F20)
                {
                    sb.AppendLine("DR-DOS will boot this FAT32 using CHS.");
                }
                else if ((fat32Bpb.mirror_flags & 0x4F20) == 0x4F20)
                {
                    sb.AppendLine("DR-DOS will boot this FAT32 using LBA.");
                }

                if (fat32Bpb.signature == 0x29)
                {
                    XmlFsType.VolumeName = Encoding.ASCII.GetString(fat32Bpb.volume_label);

                    sb.AppendFormat("Filesystem type: {0}", Encoding.ASCII.GetString(fat32Bpb.fs_type)).
                    AppendLine();

                    bootChk = Sha1Context.Data(fat32Bpb.boot_code, out _);
                }
                else
                {
                    bootChk = Sha1Context.Data(shortFat32Bpb.boot_code, out _);
                }

                // Check that jumps to a correct boot code position and has boot signature set.
                // This will mean that the volume will boot, even if just to say "this is not bootable change disk"......
                XmlFsType.Bootable =
                    (fat32Bpb.jump[0] == 0xEB && fat32Bpb.jump[1] >= minBootNearJump && fat32Bpb.jump[1] < 0x80) ||
                    (fat32Bpb.jump[0] == 0xE9 && fat32Bpb.jump.Length >= 3 &&
                     BitConverter.ToUInt16(fat32Bpb.jump, 1) >= minBootNearJump &&
                     BitConverter.ToUInt16(fat32Bpb.jump, 1) <= 0x1FC);

                sectorsPerRealSector = fat32Bpb.bps / imagePlugin.Info.SectorSize;

                // First root directory sector
                rootDirectorySector =
                    (ulong)(((fat32Bpb.root_cluster - 2) * fat32Bpb.spc) + (fat32Bpb.big_spfat * fat32Bpb.fats_no) +
                            fat32Bpb.rsectors) * sectorsPerRealSector;

                sectorsForRootDirectory = 1;

                if (fat32Bpb.fsinfo_sector + partition.Start <= partition.End)
                {
                    byte[] fsinfoSector = imagePlugin.ReadSector(fat32Bpb.fsinfo_sector + partition.Start);

                    FsInfoSector fsInfo = Marshal.ByteArrayToStructureLittleEndian <FsInfoSector>(fsinfoSector);

                    if (fsInfo.signature1 == FSINFO_SIGNATURE1 &&
                        fsInfo.signature2 == FSINFO_SIGNATURE2 &&
                        fsInfo.signature3 == FSINFO_SIGNATURE3)
                    {
                        if (fsInfo.free_clusters < 0xFFFFFFFF)
                        {
                            sb.AppendFormat("{0} free clusters", fsInfo.free_clusters).AppendLine();
                            XmlFsType.FreeClusters          = fsInfo.free_clusters;
                            XmlFsType.FreeClustersSpecified = true;
                        }

                        if (fsInfo.last_cluster > 2 &&
                            fsInfo.last_cluster < 0xFFFFFFFF)
                        {
                            sb.AppendFormat("Last allocated cluster {0}", fsInfo.last_cluster).AppendLine();
                        }
                    }
                }

                break;
            }

            // Some fields could overflow fake BPB, those will be handled below
            case BpbKind.Atari:
            {
                ushort sum = 0;

                for (int i = 0; i < bpbSector.Length; i += 2)
                {
                    sum += BigEndianBitConverter.ToUInt16(bpbSector, i);
                }

                // TODO: Check this
                if (sum == 0x1234)
                {
                    XmlFsType.Bootable = true;
                    var atariSb = new StringBuilder();

                    atariSb.AppendFormat("cmdload will be loaded with value {0:X4}h",
                                         BigEndianBitConverter.ToUInt16(bpbSector, 0x01E)).AppendLine();

                    atariSb.AppendFormat("Boot program will be loaded at address {0:X4}h", atariBpb.ldaaddr).
                    AppendLine();

                    atariSb.AppendFormat("FAT and directory will be cached at address {0:X4}h", atariBpb.fatbuf).
                    AppendLine();

                    if (atariBpb.ldmode == 0)
                    {
                        byte[] tmp = new byte[8];
                        Array.Copy(atariBpb.fname, 0, tmp, 0, 8);
                        string fname = Encoding.ASCII.GetString(tmp).Trim();
                        tmp = new byte[3];
                        Array.Copy(atariBpb.fname, 8, tmp, 0, 3);
                        string extension = Encoding.ASCII.GetString(tmp).Trim();
                        string filename;

                        if (string.IsNullOrEmpty(extension))
                        {
                            filename = fname;
                        }
                        else
                        {
                            filename = fname + "." + extension;
                        }

                        atariSb.AppendFormat("Boot program resides in file \"{0}\"", filename).AppendLine();
                    }
                    else
                    {
                        atariSb.
                        AppendFormat("Boot program starts in sector {0} and is {1} sectors long ({2} bytes)",
                                     atariBpb.ssect, atariBpb.sectcnt, atariBpb.sectcnt * atariBpb.bps).
                        AppendLine();
                    }

                    extraInfo = atariSb.ToString();
                }

                break;
            }

            case BpbKind.Human:
                XmlFsType.Bootable = true;

                break;
            }

            if (!isFat32)
            {
                // This is to support FAT partitions on hybrid ISO/USB images
                if (imagePlugin.Info.XmlMediaType == XmlMediaType.OpticalDisc)
                {
                    fakeBpb.bps      *= 4;
                    fakeBpb.spc      /= 4;
                    fakeBpb.spfat    /= 4;
                    fakeBpb.hsectors /= 4;
                    fakeBpb.sptrk    /= 4;
                    fakeBpb.rsectors /= 4;

                    if (fakeBpb.spc == 0)
                    {
                        fakeBpb.spc = 1;
                    }
                }

                // This assumes no sane implementation will violate cluster size rules
                // However nothing prevents this to happen
                // If first file on disk uses only one cluster there is absolutely no way to differentiate between FAT12 and FAT16,
                // so let's hope implementations use common sense?
                if (!isFat12 &&
                    !isFat16)
                {
                    ulong clusters;

                    if (fakeBpb.sectors == 0)
                    {
                        clusters = fakeBpb.spc == 0 ? fakeBpb.big_sectors : fakeBpb.big_sectors / fakeBpb.spc;
                    }
                    else
                    {
                        clusters = fakeBpb.spc == 0 ? fakeBpb.sectors : (ulong)fakeBpb.sectors / fakeBpb.spc;
                    }

                    if (clusters < 4089)
                    {
                        isFat12 = true;
                    }
                    else
                    {
                        isFat16 = true;
                    }
                }

                if (isFat12)
                {
                    switch (bpbKind)
                    {
                    case BpbKind.Atari:
                        sb.AppendLine("Atari FAT12");

                        break;

                    case BpbKind.Apricot:
                        sb.AppendLine("Apricot FAT12");

                        break;

                    case BpbKind.Human:
                        sb.AppendLine("Human68k FAT12");

                        break;

                    default:
                        sb.AppendLine("Microsoft FAT12");

                        break;
                    }

                    XmlFsType.Type = "FAT12";
                }
                else if (isFat16)
                {
                    sb.AppendLine(bpbKind == BpbKind.Atari
                                      ? "Atari FAT16"
                                      : bpbKind == BpbKind.Human
                                          ? "Human68k FAT16"
                                          : "Microsoft FAT16");

                    XmlFsType.Type = "FAT16";
                }

                if (bpbKind == BpbKind.Atari)
                {
                    if (atariBpb.serial_no[0] == 0x49 &&
                        atariBpb.serial_no[1] == 0x48 &&
                        atariBpb.serial_no[2] == 0x43)
                    {
                        sb.AppendLine("Volume has been modified by Windows 9x/Me Volume Tracker.");
                    }
                    else
                    {
                        XmlFsType.VolumeSerial =
                            $"{atariBpb.serial_no[0]:X2}{atariBpb.serial_no[1]:X2}{atariBpb.serial_no[2]:X2}";
                    }

                    XmlFsType.SystemIdentifier = StringHandlers.CToString(atariBpb.oem_name);

                    if (string.IsNullOrEmpty(XmlFsType.SystemIdentifier))
                    {
                        XmlFsType.SystemIdentifier = null;
                    }
                }
                else if (fakeBpb.oem_name != null)
                {
                    if (fakeBpb.oem_name[5] == 0x49 &&
                        fakeBpb.oem_name[6] == 0x48 &&
                        fakeBpb.oem_name[7] == 0x43)
                    {
                        sb.AppendLine("Volume has been modified by Windows 9x/Me Volume Tracker.");
                    }
                    else
                    {
                        // Later versions of Windows create a DOS 3 BPB without OEM name on 8 sectors/track floppies
                        // OEM ID should be ASCII, otherwise ignore it
                        if (fakeBpb.oem_name[0] >= 0x20 &&
                            fakeBpb.oem_name[0] <= 0x7F &&
                            fakeBpb.oem_name[1] >= 0x20 &&
                            fakeBpb.oem_name[1] <= 0x7F &&
                            fakeBpb.oem_name[2] >= 0x20 &&
                            fakeBpb.oem_name[2] <= 0x7F &&
                            fakeBpb.oem_name[3] >= 0x20 &&
                            fakeBpb.oem_name[3] <= 0x7F &&
                            fakeBpb.oem_name[4] >= 0x20 &&
                            fakeBpb.oem_name[4] <= 0x7F &&
                            fakeBpb.oem_name[5] >= 0x20 &&
                            fakeBpb.oem_name[5] <= 0x7F &&
                            fakeBpb.oem_name[6] >= 0x20 &&
                            fakeBpb.oem_name[6] <= 0x7F &&
                            fakeBpb.oem_name[7] >= 0x20 &&
                            fakeBpb.oem_name[7] <= 0x7F)
                        {
                            XmlFsType.SystemIdentifier = StringHandlers.CToString(fakeBpb.oem_name);
                        }
                        else if (fakeBpb.oem_name[0] < 0x20 &&
                                 fakeBpb.oem_name[1] >= 0x20 &&
                                 fakeBpb.oem_name[1] <= 0x7F &&
                                 fakeBpb.oem_name[2] >= 0x20 &&
                                 fakeBpb.oem_name[2] <= 0x7F &&
                                 fakeBpb.oem_name[3] >= 0x20 &&
                                 fakeBpb.oem_name[3] <= 0x7F &&
                                 fakeBpb.oem_name[4] >= 0x20 &&
                                 fakeBpb.oem_name[4] <= 0x7F &&
                                 fakeBpb.oem_name[5] >= 0x20 &&
                                 fakeBpb.oem_name[5] <= 0x7F &&
                                 fakeBpb.oem_name[6] >= 0x20 &&
                                 fakeBpb.oem_name[6] <= 0x7F &&
                                 fakeBpb.oem_name[7] >= 0x20 &&
                                 fakeBpb.oem_name[7] <= 0x7F)
                        {
                            XmlFsType.SystemIdentifier = StringHandlers.CToString(fakeBpb.oem_name, Encoding, start: 1);
                        }
                    }

                    if (fakeBpb.signature == 0x28 ||
                        fakeBpb.signature == 0x29)
                    {
                        XmlFsType.VolumeSerial = $"{fakeBpb.serial_no:X8}";
                    }
                }

                if (XmlFsType.SystemIdentifier != null)
                {
                    sb.AppendFormat("OEM Name: {0}", XmlFsType.SystemIdentifier.Trim()).AppendLine();
                }

                sb.AppendFormat("{0} bytes per sector.", fakeBpb.bps).AppendLine();

                if (bpbKind != BpbKind.Human)
                {
                    if (fakeBpb.sectors == 0)
                    {
                        sb.AppendFormat("{0} sectors on volume ({1} bytes).", fakeBpb.big_sectors,
                                        fakeBpb.big_sectors * fakeBpb.bps).AppendLine();

                        XmlFsType.Clusters = fakeBpb.spc == 0 ? fakeBpb.big_sectors : fakeBpb.big_sectors / fakeBpb.spc;
                    }
                    else
                    {
                        sb.AppendFormat("{0} sectors on volume ({1} bytes).", fakeBpb.sectors,
                                        fakeBpb.sectors * fakeBpb.bps).AppendLine();

                        XmlFsType.Clusters =
                            (ulong)(fakeBpb.spc == 0 ? fakeBpb.sectors : fakeBpb.sectors / fakeBpb.spc);
                    }
                }
                else
                {
                    XmlFsType.Clusters = humanBpb.clusters == 0 ? humanBpb.big_clusters : humanBpb.clusters;

                    sb.AppendFormat("{0} sectors on volume ({1} bytes).",
                                    (XmlFsType.Clusters * humanBpb.bpc) / imagePlugin.Info.SectorSize,
                                    XmlFsType.Clusters * humanBpb.bpc).AppendLine();
                }

                sb.AppendFormat("{0} sectors per cluster.", fakeBpb.spc).AppendLine();
                sb.AppendFormat("{0} clusters on volume.", XmlFsType.Clusters).AppendLine();
                XmlFsType.ClusterSize = (uint)(fakeBpb.bps * fakeBpb.spc);
                sb.AppendFormat("{0} sectors reserved between BPB and FAT.", fakeBpb.rsectors).AppendLine();
                sb.AppendFormat("{0} FATs.", fakeBpb.fats_no).AppendLine();
                sb.AppendFormat("{0} entries on root directory.", fakeBpb.root_ent).AppendLine();

                if (fakeBpb.media > 0)
                {
                    sb.AppendFormat("Media descriptor: 0x{0:X2}", fakeBpb.media).AppendLine();
                }

                sb.AppendFormat("{0} sectors per FAT.", fakeBpb.spfat).AppendLine();

                if (fakeBpb.sptrk > 0 &&
                    fakeBpb.sptrk < 64 &&
                    fakeBpb.heads > 0 &&
                    fakeBpb.heads < 256)
                {
                    sb.AppendFormat("{0} sectors per track.", fakeBpb.sptrk).AppendLine();
                    sb.AppendFormat("{0} heads.", fakeBpb.heads).AppendLine();
                }

                if (fakeBpb.hsectors <= partition.Start)
                {
                    sb.AppendFormat("{0} hidden sectors before BPB.", fakeBpb.hsectors).AppendLine();
                }

                if (fakeBpb.signature == 0x28 ||
                    fakeBpb.signature == 0x29 ||
                    andosOemCorrect)
                {
                    sb.AppendFormat("Drive number: 0x{0:X2}", fakeBpb.drive_no).AppendLine();

                    if (XmlFsType.VolumeSerial != null)
                    {
                        sb.AppendFormat("Volume Serial Number: {0}", XmlFsType.VolumeSerial).AppendLine();
                    }

                    if ((fakeBpb.flags & 0xF8) == 0x00)
                    {
                        if ((fakeBpb.flags & 0x01) == 0x01)
                        {
                            sb.AppendLine("Volume should be checked on next mount.");
                            XmlFsType.Dirty = true;
                        }

                        if ((fakeBpb.flags & 0x02) == 0x02)
                        {
                            sb.AppendLine("Disk surface should be on next mount.");
                        }
                    }

                    if (fakeBpb.signature == 0x29 || andosOemCorrect)
                    {
                        XmlFsType.VolumeName = Encoding.ASCII.GetString(fakeBpb.volume_label);
                        sb.AppendFormat("Filesystem type: {0}", Encoding.ASCII.GetString(fakeBpb.fs_type)).AppendLine();
                    }
                }
                else if (bpbKind == BpbKind.Atari &&
                         XmlFsType.VolumeSerial != null)
                {
                    sb.AppendFormat("Volume Serial Number: {0}", XmlFsType.VolumeSerial).AppendLine();
                }

                bootChk = Sha1Context.Data(fakeBpb.boot_code, out _);

                // Workaround that PCExchange jumps into "FAT16   "...
                if (XmlFsType.SystemIdentifier == "PCX 2.0 ")
                {
                    fakeBpb.jump[1] += 8;
                }

                // Check that jumps to a correct boot code position and has boot signature set.
                // This will mean that the volume will boot, even if just to say "this is not bootable change disk"......
                if (XmlFsType.Bootable == false &&
                    fakeBpb.jump != null)
                {
                    XmlFsType.Bootable |=
                        (fakeBpb.jump[0] == 0xEB && fakeBpb.jump[1] >= minBootNearJump && fakeBpb.jump[1] < 0x80) ||
                        (fakeBpb.jump[0] == 0xE9 && fakeBpb.jump.Length >= 3 &&
                         BitConverter.ToUInt16(fakeBpb.jump, 1) >= minBootNearJump &&
                         BitConverter.ToUInt16(fakeBpb.jump, 1) <= 0x1FC);
                }

                sectorsPerRealSector = fakeBpb.bps / imagePlugin.Info.SectorSize;

                // First root directory sector
                rootDirectorySector =
                    (ulong)((fakeBpb.spfat * fakeBpb.fats_no) + fakeBpb.rsectors) * sectorsPerRealSector;

                sectorsForRootDirectory = (uint)((fakeBpb.root_ent * 32) / imagePlugin.Info.SectorSize);
            }

            if (extraInfo != null)
            {
                sb.Append(extraInfo);
            }

            if (rootDirectorySector + partition.Start < partition.End &&
                imagePlugin.Info.XmlMediaType != XmlMediaType.OpticalDisc)
            {
                byte[] rootDirectory =
                    imagePlugin.ReadSectors(rootDirectorySector + partition.Start, sectorsForRootDirectory);

                if (bpbKind == BpbKind.DecRainbow)
                {
                    var rootMs = new MemoryStream();

                    foreach (byte[] tmp in from ulong rootSector in new[]
                    {
                        0x17, 0x19, 0x1B, 0x1D, 0x1E, 0x20
                    } select imagePlugin.ReadSector(rootSector))
                    {
                        rootMs.Write(tmp, 0, tmp.Length);
                    }

                    rootDirectory = rootMs.ToArray();
                }

                for (int i = 0; i < rootDirectory.Length; i += 32)
                {
                    // Not a correct entry
                    if (rootDirectory[i] < DIRENT_MIN &&
                        rootDirectory[i] != DIRENT_E5)
                    {
                        continue;
                    }

                    // Deleted or subdirectory entry
                    if (rootDirectory[i] == DIRENT_SUBDIR ||
                        rootDirectory[i] == DIRENT_DELETED)
                    {
                        continue;
                    }

                    // Not a volume label
                    if (rootDirectory[i + 0x0B] != 0x08 &&
                        rootDirectory[i + 0x0B] != 0x28)
                    {
                        continue;
                    }

                    DirectoryEntry entry =
                        Marshal.ByteArrayToStructureLittleEndian <DirectoryEntry>(rootDirectory, i, 32);

                    byte[] fullname = new byte[11];
                    Array.Copy(entry.filename, 0, fullname, 0, 8);
                    Array.Copy(entry.extension, 0, fullname, 8, 3);
                    string volname = Encoding.GetString(fullname).Trim();

                    if (!string.IsNullOrEmpty(volname))
                    {
                        XmlFsType.VolumeName =
                            entry.caseinfo.HasFlag(CaseInfo.AllLowerCase) ? volname.ToLower() : volname;
                    }

                    if (entry.ctime > 0 &&
                        entry.cdate > 0)
                    {
                        XmlFsType.CreationDate = DateHandlers.DosToDateTime(entry.cdate, entry.ctime);

                        if (entry.ctime_ms > 0)
                        {
                            XmlFsType.CreationDate = XmlFsType.CreationDate.AddMilliseconds(entry.ctime_ms * 10);
                        }

                        XmlFsType.CreationDateSpecified = true;
                        sb.AppendFormat("Volume created on {0}", XmlFsType.CreationDate).AppendLine();
                    }

                    if (entry.mtime > 0 &&
                        entry.mdate > 0)
                    {
                        XmlFsType.ModificationDate          = DateHandlers.DosToDateTime(entry.mdate, entry.mtime);
                        XmlFsType.ModificationDateSpecified = true;
                        sb.AppendFormat("Volume last modified on {0}", XmlFsType.ModificationDate).AppendLine();
                    }

                    if (entry.adate > 0)
                    {
                        sb.AppendFormat("Volume last accessed on {0:d}", DateHandlers.DosToDateTime(entry.adate, 0)).
                        AppendLine();
                    }

                    break;
                }
            }

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

            if (XmlFsType.Bootable)
            {
                // Intel short jump
                if (bpbSector[0] == 0xEB &&
                    bpbSector[1] < 0x80)
                {
                    int    sigSize  = bpbSector[510] == 0x55 && bpbSector[511] == 0xAA ? 2 : 0;
                    byte[] bootCode = new byte[512 - sigSize - bpbSector[1] - 2];
                    Array.Copy(bpbSector, bpbSector[1] + 2, bootCode, 0, bootCode.Length);
                    Sha1Context.Data(bootCode, out _);
                }

                // Intel big jump
                else if (bpbSector[0] == 0xE9 &&
                         BitConverter.ToUInt16(bpbSector, 1) < 0x1FC)
                {
                    int    sigSize  = bpbSector[510] == 0x55 && bpbSector[511] == 0xAA ? 2 : 0;
                    byte[] bootCode = new byte[512 - sigSize - BitConverter.ToUInt16(bpbSector, 1) - 3];
                    Array.Copy(bpbSector, BitConverter.ToUInt16(bpbSector, 1) + 3, bootCode, 0, bootCode.Length);
                    Sha1Context.Data(bootCode, out _);
                }

                sb.AppendLine("Volume is bootable");
                sb.AppendFormat("Boot code's SHA1: {0}", bootChk).AppendLine();
                string bootName = _knownBootHashes.FirstOrDefault(t => t.hash == bootChk).name;

                if (string.IsNullOrWhiteSpace(bootName))
                {
                    sb.AppendLine("Unknown boot code.");
                }
                else
                {
                    sb.AppendFormat("Boot code corresponds to {0}", bootName).AppendLine();
                }
            }

            information = sb.ToString();
        }
Ejemplo n.º 22
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            Encoding    = encoding ?? Encoding.UTF8;
            information = "";

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

            uint sbAddr = NILFS2_SUPER_OFFSET / imagePlugin.Info.SectorSize;

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

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

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

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

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

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

            if (nilfsSb.magic != NILFS2_MAGIC)
            {
                return;
            }

            var sb = new StringBuilder();

            sb.AppendLine("NILFS2 filesystem");
            sb.AppendFormat("Version {0}.{1}", nilfsSb.rev_level, nilfsSb.minor_rev_level).AppendLine();
            sb.AppendFormat("{0} bytes per block", 1 << (int)(nilfsSb.log_block_size + 10)).AppendLine();
            sb.AppendFormat("{0} bytes in volume", nilfsSb.dev_size).AppendLine();
            sb.AppendFormat("{0} blocks per segment", nilfsSb.blocks_per_segment).AppendLine();
            sb.AppendFormat("{0} segments", nilfsSb.nsegments).AppendLine();

            if (nilfsSb.creator_os == 0)
            {
                sb.AppendLine("Filesystem created on Linux");
            }
            else
            {
                sb.AppendFormat("Creator OS code: {0}", nilfsSb.creator_os).AppendLine();
            }

            sb.AppendFormat("{0} bytes per inode", nilfsSb.inode_size).AppendLine();
            sb.AppendFormat("Volume UUID: {0}", nilfsSb.uuid).AppendLine();
            sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(nilfsSb.volume_name, Encoding)).AppendLine();
            sb.AppendFormat("Volume created on {0}", DateHandlers.UnixUnsignedToDateTime(nilfsSb.ctime)).AppendLine();

            sb.AppendFormat("Volume last mounted on {0}", DateHandlers.UnixUnsignedToDateTime(nilfsSb.mtime)).
            AppendLine();

            sb.AppendFormat("Volume last written on {0}", DateHandlers.UnixUnsignedToDateTime(nilfsSb.wtime)).
            AppendLine();

            information = sb.ToString();

            XmlFsType = new FileSystemType
            {
                Type             = "NILFS2 filesystem", ClusterSize = (uint)(1 << (int)(nilfsSb.log_block_size + 10)),
                VolumeName       = StringHandlers.CToString(nilfsSb.volume_name, Encoding),
                VolumeSerial     = nilfsSb.uuid.ToString(),
                CreationDate     = DateHandlers.UnixUnsignedToDateTime(nilfsSb.ctime), CreationDateSpecified = true,
                ModificationDate = DateHandlers.UnixUnsignedToDateTime(nilfsSb.wtime), ModificationDateSpecified = true
            };

            if (nilfsSb.creator_os == 0)
            {
                XmlFsType.SystemIdentifier = "Linux";
            }

            XmlFsType.Clusters = nilfsSb.dev_size / XmlFsType.ClusterSize;
        }
Ejemplo n.º 23
0
        /// <summary>
        ///     Mounts an Apple Lisa filesystem
        /// </summary>
        public Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding,
                           Dictionary <string, string> options, string @namespace)
        {
            XmlFsType = new FileSystemType();
            if (options == null)
            {
                options = GetDefaultOptions();
            }
            if (options.TryGetValue("debug", out string debugString))
            {
                bool.TryParse(debugString, out debug);
            }

            // Default namespace
            if (@namespace is null)
            {
                @namespace = "ecs";
            }

            switch (@namespace.ToLowerInvariant())
            {
            case "dos":
                this.@namespace = Namespace.Dos;
                break;

            case "nt":
                this.@namespace = Namespace.Nt;
                break;

            case "os2":
                this.@namespace = Namespace.Os2;
                break;

            case "ecs":
                this.@namespace = Namespace.Ecs;
                break;

            case "lfn":
                this.@namespace = Namespace.Lfn;
                break;

            case "human":
                this.@namespace = Namespace.Human;
                break;

            default: return(Errno.InvalidArgument);
            }

            DicConsole.DebugWriteLine("FAT plugin", "Reading BPB");

            uint sectorsPerBpb = imagePlugin.Info.SectorSize < 512 ? 512 / imagePlugin.Info.SectorSize : 1;

            byte[] bpbSector = imagePlugin.ReadSectors(0 + partition.Start, sectorsPerBpb);

            BpbKind bpbKind = DetectBpbKind(bpbSector, imagePlugin, partition,
                                            out BiosParameterBlockEbpb fakeBpb,
                                            out HumanParameterBlock humanBpb, out AtariParameterBlock atariBpb,
                                            out byte minBootNearJump, out bool andosOemCorrect,
                                            out bool bootable);

            fat12              = false;
            fat16              = false;
            fat32              = false;
            useFirstFat        = true;
            XmlFsType.Bootable = bootable;

            statfs = new FileSystemInfo
            {
                Blocks         = XmlFsType.Clusters,
                FilenameLength = 11,
                Files          = 0, // Requires traversing all directories
                FreeFiles      = 0,
                PluginId       = Id,
                FreeBlocks     = 0 // Requires traversing the FAT
            };

            // This is needed because for FAT16, GEMDOS increases bytes per sector count instead of using big_sectors field.
            uint sectorsPerRealSector = 1;
            // This is needed because some OSes don't put volume label as first entry in the root directory
            uint sectorsForRootDirectory = 0;
            uint rootDirectoryCluster    = 0;

            switch (bpbKind)
            {
            case BpbKind.DecRainbow:
            case BpbKind.Hardcoded:
            case BpbKind.Msx:
            case BpbKind.Apricot:
                fat12 = true;
                break;

            case BpbKind.ShortFat32:
            case BpbKind.LongFat32:
            {
                fat32 = true;
                Fat32ParameterBlock fat32Bpb =
                    Marshal.ByteArrayToStructureLittleEndian <Fat32ParameterBlock>(bpbSector);
                Fat32ParameterBlockShort shortFat32Bpb =
                    Marshal.ByteArrayToStructureLittleEndian <Fat32ParameterBlockShort>(bpbSector);

                rootDirectoryCluster = fat32Bpb.root_cluster;

                // This is to support FAT partitions on hybrid ISO/USB images
                if (imagePlugin.Info.XmlMediaType == XmlMediaType.OpticalDisc)
                {
                    fat32Bpb.bps       *= 4;
                    fat32Bpb.spc       /= 4;
                    fat32Bpb.big_spfat /= 4;
                    fat32Bpb.hsectors  /= 4;
                    fat32Bpb.sptrk     /= 4;
                }

                XmlFsType.Type = fat32Bpb.version != 0 ? "FAT+" : "FAT32";

                if (fat32Bpb.oem_name != null && (fat32Bpb.oem_name[5] != 0x49 || fat32Bpb.oem_name[6] != 0x48 ||
                                                  fat32Bpb.oem_name[7] != 0x43))
                {
                    XmlFsType.SystemIdentifier = StringHandlers.CToString(fat32Bpb.oem_name);
                }

                sectorsPerCluster     = fat32Bpb.spc;
                XmlFsType.ClusterSize = (uint)(fat32Bpb.bps * fat32Bpb.spc);
                reservedSectors       = fat32Bpb.rsectors;
                if (fat32Bpb.big_sectors == 0 && fat32Bpb.signature == 0x28)
                {
                    XmlFsType.Clusters = shortFat32Bpb.huge_sectors / shortFat32Bpb.spc;
                }
                else
                {
                    XmlFsType.Clusters = fat32Bpb.big_sectors / fat32Bpb.spc;
                }

                sectorsPerFat          = fat32Bpb.big_spfat;
                XmlFsType.VolumeSerial = $"{fat32Bpb.serial_no:X8}";
                statfs.Id = new FileSystemId {
                    IsInt = true, Serial32 = fat32Bpb.serial_no
                };

                if ((fat32Bpb.flags & 0xF8) == 0x00)
                {
                    if ((fat32Bpb.flags & 0x01) == 0x01)
                    {
                        XmlFsType.Dirty = true;
                    }
                }

                if ((fat32Bpb.mirror_flags & 0x80) == 0x80)
                {
                    useFirstFat = (fat32Bpb.mirror_flags & 0xF) != 1;
                }

                if (fat32Bpb.signature == 0x29)
                {
                    XmlFsType.VolumeName = Encoding.ASCII.GetString(fat32Bpb.volume_label);
                }

                // Check that jumps to a correct boot code position and has boot signature set.
                // This will mean that the volume will boot, even if just to say "this is not bootable change disk"......
                XmlFsType.Bootable =
                    fat32Bpb.jump[0] == 0xEB && fat32Bpb.jump[1] >= minBootNearJump && fat32Bpb.jump[1] < 0x80 ||
                    fat32Bpb.jump[0] == 0xE9 && fat32Bpb.jump.Length >= 3 &&
                    BitConverter.ToUInt16(fat32Bpb.jump, 1) >= minBootNearJump &&
                    BitConverter.ToUInt16(fat32Bpb.jump, 1) <= 0x1FC;

                sectorsPerRealSector = fat32Bpb.bps / imagePlugin.Info.SectorSize;
                sectorsPerCluster   *= sectorsPerRealSector;

                // First root directory sector
                firstClusterSector =
                    (ulong)(fat32Bpb.big_spfat * fat32Bpb.fats_no + fat32Bpb.rsectors) * sectorsPerRealSector -
                    2 * sectorsPerCluster;

                if (fat32Bpb.fsinfo_sector + partition.Start <= partition.End)
                {
                    byte[]       fsinfoSector = imagePlugin.ReadSector(fat32Bpb.fsinfo_sector + partition.Start);
                    FsInfoSector fsInfo       =
                        Marshal.ByteArrayToStructureLittleEndian <FsInfoSector>(fsinfoSector);

                    if (fsInfo.signature1 == FSINFO_SIGNATURE1 && fsInfo.signature2 == FSINFO_SIGNATURE2 &&
                        fsInfo.signature3 == FSINFO_SIGNATURE3)
                    {
                        if (fsInfo.free_clusters < 0xFFFFFFFF)
                        {
                            XmlFsType.FreeClusters          = fsInfo.free_clusters;
                            XmlFsType.FreeClustersSpecified = true;
                        }
                    }
                }

                break;
            }

            // Some fields could overflow fake BPB, those will be handled below
            case BpbKind.Atari:
            {
                ushort sum = 0;
                for (int i = 0; i < bpbSector.Length; i += 2)
                {
                    sum += BigEndianBitConverter.ToUInt16(bpbSector, i);
                }

                // TODO: Check this
                if (sum == 0x1234)
                {
                    XmlFsType.Bootable = true;
                }

                break;
            }

            case BpbKind.Human:
                // If not debug set Human68k namespace and ShiftJIS codepage as defaults
                if (!debug)
                {
                    this.@namespace = Namespace.Human;
                    encoding        = Encoding.GetEncoding("shift_jis");
                }

                XmlFsType.Bootable = true;
                break;
            }

            Encoding = encoding ?? (bpbKind == BpbKind.Human
                                        ? Encoding.GetEncoding("shift_jis")
                                        : Encoding.GetEncoding("IBM437"));

            ulong firstRootSector = 0;

            if (!fat32)
            {
                // This is to support FAT partitions on hybrid ISO/USB images
                if (imagePlugin.Info.XmlMediaType == XmlMediaType.OpticalDisc)
                {
                    fakeBpb.bps      *= 4;
                    fakeBpb.spc      /= 4;
                    fakeBpb.spfat    /= 4;
                    fakeBpb.hsectors /= 4;
                    fakeBpb.sptrk    /= 4;
                    fakeBpb.rsectors /= 4;

                    if (fakeBpb.spc == 0)
                    {
                        fakeBpb.spc = 1;
                    }
                }

                // This assumes no sane implementation will violate cluster size rules
                // However nothing prevents this to happen
                // If first file on disk uses only one cluster there is absolutely no way to differentiate between FAT12 and FAT16,
                // so let's hope implementations use common sense?
                if (!fat12 && !fat16)
                {
                    ulong clusters;

                    if (fakeBpb.sectors == 0)
                    {
                        clusters = fakeBpb.spc == 0 ? fakeBpb.big_sectors : fakeBpb.big_sectors / fakeBpb.spc;
                    }
                    else
                    {
                        clusters = fakeBpb.spc == 0 ? fakeBpb.sectors : (ulong)fakeBpb.sectors / fakeBpb.spc;
                    }

                    if (clusters < 4089)
                    {
                        fat12 = true;
                    }
                    else
                    {
                        fat16 = true;
                    }
                }

                if (fat12)
                {
                    XmlFsType.Type = "FAT12";
                }
                else if (fat16)
                {
                    XmlFsType.Type = "FAT16";
                }

                if (bpbKind == BpbKind.Atari)
                {
                    if (atariBpb.serial_no[0] != 0x49 || atariBpb.serial_no[1] != 0x48 || atariBpb.serial_no[2] != 0x43)
                    {
                        XmlFsType.VolumeSerial =
                            $"{atariBpb.serial_no[0]:X2}{atariBpb.serial_no[1]:X2}{atariBpb.serial_no[2]:X2}";
                        statfs.Id = new FileSystemId
                        {
                            IsInt    = true,
                            Serial32 = (uint)((atariBpb.serial_no[0] << 16) + (atariBpb.serial_no[1] << 8) +
                                              atariBpb.serial_no[2])
                        };
                    }

                    XmlFsType.SystemIdentifier = StringHandlers.CToString(atariBpb.oem_name);
                    if (string.IsNullOrEmpty(XmlFsType.SystemIdentifier))
                    {
                        XmlFsType.SystemIdentifier = null;
                    }
                }
                else if (fakeBpb.oem_name != null)
                {
                    if (fakeBpb.oem_name[5] != 0x49 || fakeBpb.oem_name[6] != 0x48 || fakeBpb.oem_name[7] != 0x43)
                    {
                        // Later versions of Windows create a DOS 3 BPB without OEM name on 8 sectors/track floppies
                        // OEM ID should be ASCII, otherwise ignore it
                        if (fakeBpb.oem_name[0] >= 0x20 && fakeBpb.oem_name[0] <= 0x7F && fakeBpb.oem_name[1] >= 0x20 &&
                            fakeBpb.oem_name[1] <= 0x7F && fakeBpb.oem_name[2] >= 0x20 && fakeBpb.oem_name[2] <= 0x7F &&
                            fakeBpb.oem_name[3] >= 0x20 && fakeBpb.oem_name[3] <= 0x7F && fakeBpb.oem_name[4] >= 0x20 &&
                            fakeBpb.oem_name[4] <= 0x7F && fakeBpb.oem_name[5] >= 0x20 && fakeBpb.oem_name[5] <= 0x7F &&
                            fakeBpb.oem_name[6] >= 0x20 && fakeBpb.oem_name[6] <= 0x7F && fakeBpb.oem_name[7] >= 0x20 &&
                            fakeBpb.oem_name[7] <= 0x7F)
                        {
                            XmlFsType.SystemIdentifier = StringHandlers.CToString(fakeBpb.oem_name);
                        }
                        else if (fakeBpb.oem_name[0] < 0x20 && fakeBpb.oem_name[1] >= 0x20 &&
                                 fakeBpb.oem_name[1] <= 0x7F && fakeBpb.oem_name[2] >= 0x20 &&
                                 fakeBpb.oem_name[2] <= 0x7F && fakeBpb.oem_name[3] >= 0x20 &&
                                 fakeBpb.oem_name[3] <= 0x7F && fakeBpb.oem_name[4] >= 0x20 &&
                                 fakeBpb.oem_name[4] <= 0x7F && fakeBpb.oem_name[5] >= 0x20 &&
                                 fakeBpb.oem_name[5] <= 0x7F && fakeBpb.oem_name[6] >= 0x20 &&
                                 fakeBpb.oem_name[6] <= 0x7F && fakeBpb.oem_name[7] >= 0x20 &&
                                 fakeBpb.oem_name[7] <= 0x7F)
                        {
                            XmlFsType.SystemIdentifier = StringHandlers.CToString(fakeBpb.oem_name, Encoding, start: 1);
                        }
                    }

                    if (fakeBpb.signature == 0x28 || fakeBpb.signature == 0x29)
                    {
                        XmlFsType.VolumeSerial = $"{fakeBpb.serial_no:X8}";
                        statfs.Id = new FileSystemId {
                            IsInt = true, Serial32 = fakeBpb.serial_no
                        };
                    }
                }

                if (bpbKind != BpbKind.Human)
                {
                    if (fakeBpb.sectors == 0)
                    {
                        XmlFsType.Clusters = fakeBpb.spc == 0 ? fakeBpb.big_sectors : fakeBpb.big_sectors / fakeBpb.spc;
                    }
                    else
                    {
                        XmlFsType.Clusters =
                            (ulong)(fakeBpb.spc == 0 ? fakeBpb.sectors : fakeBpb.sectors / fakeBpb.spc);
                    }
                }
                else
                {
                    XmlFsType.Clusters = humanBpb.clusters == 0 ? humanBpb.big_clusters : humanBpb.clusters;
                }

                sectorsPerCluster     = fakeBpb.spc;
                XmlFsType.ClusterSize = (uint)(fakeBpb.bps * fakeBpb.spc);
                reservedSectors       = fakeBpb.rsectors;
                sectorsPerFat         = fakeBpb.spfat;

                if (fakeBpb.signature == 0x28 || fakeBpb.signature == 0x29 || andosOemCorrect)
                {
                    if ((fakeBpb.flags & 0xF8) == 0x00)
                    {
                        if ((fakeBpb.flags & 0x01) == 0x01)
                        {
                            XmlFsType.Dirty = true;
                        }
                    }

                    if (fakeBpb.signature == 0x29 || andosOemCorrect)
                    {
                        XmlFsType.VolumeName = Encoding.ASCII.GetString(fakeBpb.volume_label);
                    }
                }

                // Workaround that PCExchange jumps into "FAT16   "...
                if (XmlFsType.SystemIdentifier == "PCX 2.0 ")
                {
                    fakeBpb.jump[1] += 8;
                }

                // Check that jumps to a correct boot code position and has boot signature set.
                // This will mean that the volume will boot, even if just to say "this is not bootable change disk"......
                if (XmlFsType.Bootable == false && fakeBpb.jump != null)
                {
                    XmlFsType.Bootable |=
                        fakeBpb.jump[0] == 0xEB && fakeBpb.jump[1] >= minBootNearJump && fakeBpb.jump[1] < 0x80 ||
                        fakeBpb.jump[0] == 0xE9 && fakeBpb.jump.Length >= 3 &&
                        BitConverter.ToUInt16(fakeBpb.jump, 1) >= minBootNearJump &&
                        BitConverter.ToUInt16(fakeBpb.jump, 1) <= 0x1FC;
                }

                // First root directory sector
                firstRootSector = (ulong)(fakeBpb.spfat * fakeBpb.fats_no + fakeBpb.rsectors) * sectorsPerRealSector +
                                  partition.Start;
                sectorsForRootDirectory = (uint)(fakeBpb.root_ent * 32 / imagePlugin.Info.SectorSize);

                sectorsPerRealSector = fakeBpb.bps / imagePlugin.Info.SectorSize;
                sectorsPerCluster   *= sectorsPerRealSector;
            }

            firstClusterSector += partition.Start;

            image = imagePlugin;

            if (fat32)
            {
                fatEntriesPerSector = imagePlugin.Info.SectorSize / 4;
            }
            else if (fat16)
            {
                fatEntriesPerSector = imagePlugin.Info.SectorSize / 2;
            }
            else
            {
                fatEntriesPerSector = imagePlugin.Info.SectorSize * 2 / 3;
            }
            fatFirstSector = partition.Start + reservedSectors * sectorsPerRealSector;

            rootDirectoryCache = new Dictionary <string, CompleteDirectoryEntry>();
            byte[] rootDirectory = null;

            if (!fat32)
            {
                firstClusterSector = firstRootSector + sectorsForRootDirectory - sectorsPerCluster * 2;
                rootDirectory      = imagePlugin.ReadSectors(firstRootSector, sectorsForRootDirectory);

                if (bpbKind == BpbKind.DecRainbow)
                {
                    MemoryStream rootMs = new MemoryStream();
                    foreach (byte[] tmp in from ulong rootSector in new[] { 0x17, 0x19, 0x1B, 0x1D, 0x1E, 0x20 }
                             select imagePlugin.ReadSector(rootSector))
                    {
                        rootMs.Write(tmp, 0, tmp.Length);
                    }

                    rootDirectory = rootMs.ToArray();
                }
            }
            else
            {
                if (rootDirectoryCluster == 0)
                {
                    return(Errno.InvalidArgument);
                }

                MemoryStream rootMs = new MemoryStream();
                uint[]       rootDirectoryClusters = GetClusters(rootDirectoryCluster);

                foreach (uint cluster in rootDirectoryClusters)
                {
                    byte[] buffer =
                        imagePlugin.ReadSectors(firstClusterSector + cluster * sectorsPerCluster, sectorsPerCluster);

                    rootMs.Write(buffer, 0, buffer.Length);
                }

                rootDirectory = rootMs.ToArray();

                // OS/2 FAT32.IFS uses LFN instead of .LONGNAME
                if (this.@namespace == Namespace.Os2)
                {
                    this.@namespace = Namespace.Os2;
                }
            }

            if (rootDirectory is null)
            {
                return(Errno.InvalidArgument);
            }

            byte[] lastLfnName     = null;
            byte   lastLfnChecksum = 0;

            for (int i = 0; i < rootDirectory.Length; i += Marshal.SizeOf <DirectoryEntry>())
            {
                DirectoryEntry entry =
                    Marshal.ByteArrayToStructureLittleEndian <DirectoryEntry>(rootDirectory, i,
                                                                              Marshal.SizeOf <DirectoryEntry>());

                if (entry.filename[0] == DIRENT_FINISHED)
                {
                    break;
                }

                if (entry.attributes.HasFlag(FatAttributes.LFN))
                {
                    if (this.@namespace != Namespace.Lfn && this.@namespace != Namespace.Ecs)
                    {
                        continue;
                    }

                    LfnEntry lfnEntry =
                        Marshal.ByteArrayToStructureLittleEndian <LfnEntry>(rootDirectory, i,
                                                                            Marshal.SizeOf <LfnEntry>());

                    int lfnSequence = lfnEntry.sequence & LFN_MASK;

                    if ((lfnEntry.sequence & LFN_ERASED) > 0)
                    {
                        continue;
                    }

                    if ((lfnEntry.sequence & LFN_LAST) > 0)
                    {
                        lastLfnName     = new byte[lfnSequence * 26];
                        lastLfnChecksum = lfnEntry.checksum;
                    }

                    if (lastLfnName is null)
                    {
                        continue;
                    }
                    if (lfnEntry.checksum != lastLfnChecksum)
                    {
                        continue;
                    }

                    lfnSequence--;

                    Array.Copy(lfnEntry.name1, 0, lastLfnName, lfnSequence * 26, 10);
                    Array.Copy(lfnEntry.name2, 0, lastLfnName, lfnSequence * 26 + 10, 12);
                    Array.Copy(lfnEntry.name3, 0, lastLfnName, lfnSequence * 26 + 22, 4);

                    continue;
                }

                // Not a correct entry
                if (entry.filename[0] < DIRENT_MIN && entry.filename[0] != DIRENT_E5)
                {
                    continue;
                }

                // Self
                if (Encoding.GetString(entry.filename).TrimEnd() == ".")
                {
                    continue;
                }

                // Parent
                if (Encoding.GetString(entry.filename).TrimEnd() == "..")
                {
                    continue;
                }

                // Deleted
                if (entry.filename[0] == DIRENT_DELETED)
                {
                    continue;
                }

                string filename;

                if (entry.attributes.HasFlag(FatAttributes.VolumeLabel))
                {
                    byte[] fullname = new byte[11];
                    Array.Copy(entry.filename, 0, fullname, 0, 8);
                    Array.Copy(entry.extension, 0, fullname, 8, 3);
                    string volname = Encoding.GetString(fullname).Trim();
                    if (!string.IsNullOrEmpty(volname))
                    {
                        XmlFsType.VolumeName =
                            entry.caseinfo.HasFlag(CaseInfo.AllLowerCase) && this.@namespace == Namespace.Nt
                                ? volname.ToLower()
                                : volname;
                    }

                    if (entry.ctime > 0 && entry.cdate > 0)
                    {
                        XmlFsType.CreationDate = DateHandlers.DosToDateTime(entry.cdate, entry.ctime);
                        if (entry.ctime_ms > 0)
                        {
                            XmlFsType.CreationDate = XmlFsType.CreationDate.AddMilliseconds(entry.ctime_ms * 10);
                        }
                        XmlFsType.CreationDateSpecified = true;
                    }

                    if (entry.mtime > 0 && entry.mdate > 0)
                    {
                        XmlFsType.ModificationDate          = DateHandlers.DosToDateTime(entry.mdate, entry.mtime);
                        XmlFsType.ModificationDateSpecified = true;
                    }

                    continue;
                }

                CompleteDirectoryEntry completeEntry = new CompleteDirectoryEntry {
                    Dirent = entry
                };

                if ((this.@namespace == Namespace.Lfn || this.@namespace == Namespace.Ecs) && lastLfnName != null)
                {
                    byte calculatedLfnChecksum = LfnChecksum(entry.filename, entry.extension);

                    if (calculatedLfnChecksum == lastLfnChecksum)
                    {
                        filename = StringHandlers.CToString(lastLfnName, Encoding.Unicode, true);

                        completeEntry.Lfn = filename;
                        lastLfnName       = null;
                        lastLfnChecksum   = 0;
                    }
                }

                if (entry.filename[0] == DIRENT_E5)
                {
                    entry.filename[0] = DIRENT_DELETED;
                }

                string name      = Encoding.GetString(entry.filename).TrimEnd();
                string extension = Encoding.GetString(entry.extension).TrimEnd();

                if (this.@namespace == Namespace.Nt)
                {
                    if (entry.caseinfo.HasFlag(CaseInfo.LowerCaseExtension))
                    {
                        extension = extension.ToLower(CultureInfo.CurrentCulture);
                    }

                    if (entry.caseinfo.HasFlag(CaseInfo.LowerCaseBasename))
                    {
                        name = name.ToLower(CultureInfo.CurrentCulture);
                    }
                }

                if (extension != "")
                {
                    filename = name + "." + extension;
                }
                else
                {
                    filename = name;
                }

                completeEntry.Shortname = filename;

                if (this.@namespace == Namespace.Human)
                {
                    HumanDirectoryEntry humanEntry =
                        Marshal.ByteArrayToStructureLittleEndian <HumanDirectoryEntry>(rootDirectory, i,
                                                                                       Marshal
                                                                                       .SizeOf <HumanDirectoryEntry
                                                                                                >());

                    completeEntry.HumanDirent = humanEntry;

                    name      = StringHandlers.CToString(humanEntry.name1, Encoding).TrimEnd();
                    extension = StringHandlers.CToString(humanEntry.extension, Encoding).TrimEnd();
                    string name2 = StringHandlers.CToString(humanEntry.name2, Encoding).TrimEnd();

                    if (extension != "")
                    {
                        filename = name + name2 + "." + extension;
                    }
                    else
                    {
                        filename = name + name2;
                    }

                    completeEntry.HumanName = filename;
                }

                if (!fat32 && filename == "EA DATA. SF")
                {
                    eaDirEntry      = entry;
                    lastLfnName     = null;
                    lastLfnChecksum = 0;

                    if (debug)
                    {
                        rootDirectoryCache[completeEntry.ToString()] = completeEntry;
                    }

                    continue;
                }

                rootDirectoryCache[completeEntry.ToString()] = completeEntry;
                lastLfnName     = null;
                lastLfnChecksum = 0;
            }

            XmlFsType.VolumeName = XmlFsType.VolumeName?.Trim();
            statfs.Blocks        = XmlFsType.Clusters;

            switch (bpbKind)
            {
            case BpbKind.Hardcoded:
                statfs.Type = $"Microsoft FAT{(fat16 ? "16" : "12")}";
                break;

            case BpbKind.Atari:
                statfs.Type = $"Atari FAT{(fat16 ? "16" : "12")}";
                break;

            case BpbKind.Msx:
                statfs.Type = $"MSX FAT{(fat16 ? "16" : "12")}";
                break;

            case BpbKind.Dos2:
            case BpbKind.Dos3:
            case BpbKind.Dos32:
            case BpbKind.Dos33:
            case BpbKind.ShortExtended:
            case BpbKind.Extended:
                statfs.Type = $"Microsoft FAT{(fat16 ? "16" : "12")}";
                break;

            case BpbKind.ShortFat32:
            case BpbKind.LongFat32:
                statfs.Type = XmlFsType.Type == "FAT+" ? "FAT+" : "Microsoft FAT32";
                break;

            case BpbKind.Andos:
                statfs.Type = $"ANDOS FAT{(fat16 ? "16" : "12")}";
                break;

            case BpbKind.Apricot:
                statfs.Type = $"Apricot FAT{(fat16 ? "16" : "12")}";
                break;

            case BpbKind.DecRainbow:
                statfs.Type = $"DEC FAT{(fat16 ? "16" : "12")}";
                break;

            case BpbKind.Human:
                statfs.Type = $"Human68k FAT{(fat16 ? "16" : "12")}";
                break;

            default: throw new ArgumentOutOfRangeException();
            }

            bytesPerCluster = sectorsPerCluster * imagePlugin.Info.SectorSize;

            if (fat12)
            {
                byte[] fatBytes =
                    imagePlugin.ReadSectors(fatFirstSector + (useFirstFat ? 0 : sectorsPerFat), sectorsPerFat);

                fatEntries = new ushort[statfs.Blocks];

                int pos = 0;
                for (int i = 0; i + 3 < fatBytes.Length && pos < fatEntries.Length; i += 3)
                {
                    fatEntries[pos++] = (ushort)(((fatBytes[i + 1] & 0xF) << 8) + fatBytes[i + 0]);
                    fatEntries[pos++] = (ushort)(((fatBytes[i + 1] & 0xF0) >> 4) + (fatBytes[i + 2] << 4));
                }
            }
            else if (fat16)
            {
                DicConsole.DebugWriteLine("FAT plugin", "Reading FAT16");

                byte[] fatBytes =
                    imagePlugin.ReadSectors(fatFirstSector + (useFirstFat ? 0 : sectorsPerFat), sectorsPerFat);

                DicConsole.DebugWriteLine("FAT plugin", "Casting FAT");
                fatEntries = MemoryMarshal.Cast <byte, ushort>(fatBytes).ToArray();
            }

            // TODO: Check how this affects international filenames
            cultureInfo    = new CultureInfo("en-US", false);
            directoryCache = new Dictionary <string, Dictionary <string, CompleteDirectoryEntry> >();

            // Check it is really an OS/2 EA file
            if (eaDirEntry.start_cluster != 0)
            {
                CacheEaData();
                ushort eamagic = BitConverter.ToUInt16(cachedEaData, 0);

                if (eamagic != EADATA_MAGIC)
                {
                    eaDirEntry   = new DirectoryEntry();
                    cachedEaData = null;
                }
                else
                {
                    eaCache = new Dictionary <string, Dictionary <string, byte[]> >();
                }
            }
            else if (fat32)
            {
                eaCache = new Dictionary <string, Dictionary <string, byte[]> >();
            }

            // Check OS/2 .LONGNAME
            if (eaCache != null && (this.@namespace == Namespace.Os2 || this.@namespace == Namespace.Ecs))
            {
                List <KeyValuePair <string, CompleteDirectoryEntry> > rootFilesWithEas =
                    rootDirectoryCache.Where(t => t.Value.Dirent.ea_handle != 0).ToList();

                foreach (KeyValuePair <string, CompleteDirectoryEntry> fileWithEa in rootFilesWithEas)
                {
                    Dictionary <string, byte[]> eas = GetEas(fileWithEa.Value.Dirent.ea_handle);

                    if (eas is null)
                    {
                        continue;
                    }

                    if (!eas.TryGetValue("com.microsoft.os2.longname", out byte[] longnameEa))
Ejemplo n.º 24
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();

            HammerSuperBlock hammerSb;

            uint run = HAMMER_VOLHDR_SIZE / imagePlugin.Info.SectorSize;

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

            ulong magic;

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

            magic = BitConverter.ToUInt64(sbSector, 0);

            if (magic == HAMMER_FSBUF_VOLUME)
            {
                GCHandle handle = GCHandle.Alloc(sbSector, GCHandleType.Pinned);
                hammerSb = (HammerSuperBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),
                                                                    typeof(HammerSuperBlock));
                handle.Free();
            }
            else
            {
                hammerSb = BigEndianMarshal.ByteArrayToStructureBigEndian <HammerSuperBlock>(sbSector);
            }

            sb.AppendLine("HAMMER filesystem");

            sb.AppendFormat("Volume version: {0}", hammerSb.vol_version).AppendLine();
            sb.AppendFormat("Volume {0} of {1} on this filesystem", hammerSb.vol_no + 1, hammerSb.vol_count)
            .AppendLine();
            sb.AppendFormat("Volume name: {0}", StringHandlers.CToString(hammerSb.vol_label, Encoding)).AppendLine();
            sb.AppendFormat("Volume serial: {0}", hammerSb.vol_fsid).AppendLine();
            sb.AppendFormat("Filesystem type: {0}", hammerSb.vol_fstype).AppendLine();
            sb.AppendFormat("Boot area starts at {0}", hammerSb.vol_bot_beg).AppendLine();
            sb.AppendFormat("Memory log starts at {0}", hammerSb.vol_mem_beg).AppendLine();
            sb.AppendFormat("First volume buffer starts at {0}", hammerSb.vol_buf_beg).AppendLine();
            sb.AppendFormat("Volume ends at {0}", hammerSb.vol_buf_end).AppendLine();

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

            if (hammerSb.vol_no == hammerSb.vol_rootvol)
            {
                sb.AppendFormat("Filesystem contains {0} \"big-blocks\" ({1} bytes)", hammerSb.vol0_stat_bigblocks,
                                hammerSb.vol0_stat_bigblocks * HAMMER_BIGBLOCK_SIZE).AppendLine();
                sb.AppendFormat("Filesystem has {0} \"big-blocks\" free ({1} bytes)", hammerSb.vol0_stat_freebigblocks,
                                hammerSb.vol0_stat_freebigblocks * HAMMER_BIGBLOCK_SIZE).AppendLine();
                sb.AppendFormat("Filesystem has {0} inode used", hammerSb.vol0_stat_inodes).AppendLine();

                XmlFsType.Clusters              = hammerSb.vol0_stat_bigblocks;
                XmlFsType.FreeClusters          = hammerSb.vol0_stat_freebigblocks;
                XmlFsType.FreeClustersSpecified = true;
                XmlFsType.Files          = hammerSb.vol0_stat_inodes;
                XmlFsType.FilesSpecified = true;
            }
            // 0 ?
            //sb.AppendFormat("Volume header CRC: 0x{0:X8}", afs_sb.vol_crc).AppendLine();

            information = sb.ToString();
        }
Ejemplo n.º 25
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            Encoding    = encoding ?? Encoding.GetEncoding("iso-8859-15");
            information = "";

            StringBuilder sb = new StringBuilder();

            uint sector = 2;
            uint offset = 0;

            if (imagePlugin.Info.XmlMediaType == XmlMediaType.OpticalDisc)
            {
                sector = 0;
                offset = 0x400;
            }

            bool   minix3 = false;
            int    filenamesize;
            string minixVersion;

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

            // Optical media
            if (offset > 0)
            {
                byte[] tmp = new byte[0x200];
                Array.Copy(minixSbSector, offset, tmp, 0, 0x200);
                minixSbSector = tmp;
            }

            ushort magic = BitConverter.ToUInt16(minixSbSector, 0x018);

            XmlFsType = new FileSystemType();

            bool littleEndian;

            if (magic == MINIX3_MAGIC || magic == MINIX3_CIGAM || magic == MINIX2_MAGIC || magic == MINIX2_CIGAM ||
                magic == MINIX_MAGIC || magic == MINIX_CIGAM)
            {
                filenamesize = 60;
                littleEndian = magic != MINIX3_CIGAM || magic == MINIX2_CIGAM || magic == MINIX_CIGAM;

                switch (magic)
                {
                case MINIX3_MAGIC:
                case MINIX3_CIGAM:
                    minixVersion   = "Minix v3 filesystem";
                    XmlFsType.Type = "Minix v3";
                    break;

                case MINIX2_MAGIC:
                case MINIX2_CIGAM:
                    minixVersion   = "Minix 3 v2 filesystem";
                    XmlFsType.Type = "Minix 3 v2";
                    break;

                default:
                    minixVersion   = "Minix 3 v1 filesystem";
                    XmlFsType.Type = "Minix 3 v1";
                    break;
                }

                minix3 = true;
            }
            else
            {
                magic = BitConverter.ToUInt16(minixSbSector, 0x010);

                switch (magic)
                {
                case MINIX_MAGIC:
                    filenamesize   = 14;
                    minixVersion   = "Minix v1 filesystem";
                    littleEndian   = true;
                    XmlFsType.Type = "Minix v1";
                    break;

                case MINIX_MAGIC2:
                    filenamesize   = 30;
                    minixVersion   = "Minix v1 filesystem";
                    littleEndian   = true;
                    XmlFsType.Type = "Minix v1";
                    break;

                case MINIX2_MAGIC:
                    filenamesize   = 14;
                    minixVersion   = "Minix v2 filesystem";
                    littleEndian   = true;
                    XmlFsType.Type = "Minix v2";
                    break;

                case MINIX2_MAGIC2:
                    filenamesize   = 30;
                    minixVersion   = "Minix v2 filesystem";
                    littleEndian   = true;
                    XmlFsType.Type = "Minix v2";
                    break;

                case MINIX_CIGAM:
                    filenamesize   = 14;
                    minixVersion   = "Minix v1 filesystem";
                    littleEndian   = false;
                    XmlFsType.Type = "Minix v1";
                    break;

                case MINIX_CIGAM2:
                    filenamesize   = 30;
                    minixVersion   = "Minix v1 filesystem";
                    littleEndian   = false;
                    XmlFsType.Type = "Minix v1";
                    break;

                case MINIX2_CIGAM:
                    filenamesize   = 14;
                    minixVersion   = "Minix v2 filesystem";
                    littleEndian   = false;
                    XmlFsType.Type = "Minix v2";
                    break;

                case MINIX2_CIGAM2:
                    filenamesize   = 30;
                    minixVersion   = "Minix v2 filesystem";
                    littleEndian   = false;
                    XmlFsType.Type = "Minix v2";
                    break;

                default: return;
                }
            }

            if (minix3)
            {
                Minix3SuperBlock mnxSb;

                if (littleEndian)
                {
                    GCHandle handle = GCHandle.Alloc(minixSbSector, GCHandleType.Pinned);
                    mnxSb = (Minix3SuperBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),
                                                                     typeof(Minix3SuperBlock));
                    handle.Free();
                }
                else
                {
                    mnxSb = BigEndianMarshal.ByteArrayToStructureBigEndian <Minix3SuperBlock>(minixSbSector);
                }

                if (magic != MINIX3_MAGIC && magic != MINIX3_CIGAM)
                {
                    mnxSb.s_blocksize = 1024;
                }

                sb.AppendLine(minixVersion);
                sb.AppendFormat("{0} chars in filename", filenamesize).AppendLine();
                if (mnxSb.s_zones > 0) // On V2
                {
                    sb.AppendFormat("{0} zones on volume ({1} bytes)", mnxSb.s_zones, mnxSb.s_zones * 1024)
                    .AppendLine();
                }
                else
                {
                    sb.AppendFormat("{0} zones on volume ({1} bytes)", mnxSb.s_nzones, mnxSb.s_nzones * 1024)
                    .AppendLine();
                }
                sb.AppendFormat("{0} bytes/block", mnxSb.s_blocksize).AppendLine();
                sb.AppendFormat("{0} inodes on volume", mnxSb.s_ninodes).AppendLine();
                sb.AppendFormat("{0} blocks on inode map ({1} bytes)", mnxSb.s_imap_blocks,
                                mnxSb.s_imap_blocks * mnxSb.s_blocksize).AppendLine();
                sb.AppendFormat("{0} blocks on zone map ({1} bytes)", mnxSb.s_zmap_blocks,
                                mnxSb.s_zmap_blocks * mnxSb.s_blocksize).AppendLine();
                sb.AppendFormat("First data zone: {0}", mnxSb.s_firstdatazone).AppendLine();
                //sb.AppendFormat("log2 of blocks/zone: {0}", mnx_sb.s_log_zone_size).AppendLine(); // Apparently 0
                sb.AppendFormat("{0} bytes maximum per file", mnxSb.s_max_size).AppendLine();
                sb.AppendFormat("On-disk filesystem version: {0}", mnxSb.s_disk_version).AppendLine();

                XmlFsType.ClusterSize = mnxSb.s_blocksize;
                XmlFsType.Clusters    = mnxSb.s_zones > 0 ? mnxSb.s_zones : mnxSb.s_nzones;
            }
            else
            {
                MinixSuperBlock mnxSb;

                if (littleEndian)
                {
                    GCHandle handle = GCHandle.Alloc(minixSbSector, GCHandleType.Pinned);
                    mnxSb = (MinixSuperBlock)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),
                                                                    typeof(MinixSuperBlock));
                    handle.Free();
                }
                else
                {
                    mnxSb = BigEndianMarshal.ByteArrayToStructureBigEndian <MinixSuperBlock>(minixSbSector);
                }

                sb.AppendLine(minixVersion);
                sb.AppendFormat("{0} chars in filename", filenamesize).AppendLine();
                if (mnxSb.s_zones > 0) // On V2
                {
                    sb.AppendFormat("{0} zones on volume ({1} bytes)", mnxSb.s_zones, mnxSb.s_zones * 1024)
                    .AppendLine();
                }
                else
                {
                    sb.AppendFormat("{0} zones on volume ({1} bytes)", mnxSb.s_nzones, mnxSb.s_nzones * 1024)
                    .AppendLine();
                }
                sb.AppendFormat("{0} inodes on volume", mnxSb.s_ninodes).AppendLine();
                sb.AppendFormat("{0} blocks on inode map ({1} bytes)", mnxSb.s_imap_blocks, mnxSb.s_imap_blocks * 1024)
                .AppendLine();
                sb.AppendFormat("{0} blocks on zone map ({1} bytes)", mnxSb.s_zmap_blocks, mnxSb.s_zmap_blocks * 1024)
                .AppendLine();
                sb.AppendFormat("First data zone: {0}", mnxSb.s_firstdatazone).AppendLine();
                //sb.AppendFormat("log2 of blocks/zone: {0}", mnx_sb.s_log_zone_size).AppendLine(); // Apparently 0
                sb.AppendFormat("{0} bytes maximum per file", mnxSb.s_max_size).AppendLine();
                sb.AppendFormat("Filesystem state: {0:X4}", mnxSb.s_state).AppendLine();
                XmlFsType.ClusterSize = 1024;
                XmlFsType.Clusters    = mnxSb.s_zones > 0 ? mnxSb.s_zones : mnxSb.s_nzones;
            }

            information = sb.ToString();
        }
Ejemplo n.º 26
0
        /// <summary>
        ///     Mounts an Apple DOS filesystem
        /// </summary>
        public Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding,
                           Dictionary <string, string> options, string @namespace)
        {
            device   = imagePlugin;
            start    = partition.Start;
            Encoding = encoding ?? new Apple2();

            if (device.Info.Sectors != 455 && device.Info.Sectors != 560)
            {
                DicConsole.DebugWriteLine("Apple DOS plugin", "Incorrect device size.");
                return(Errno.InOutError);
            }

            if (start > 0)
            {
                DicConsole.DebugWriteLine("Apple DOS plugin", "Partitions are not supported.");
                return(Errno.InOutError);
            }

            if (device.Info.SectorSize != 256)
            {
                DicConsole.DebugWriteLine("Apple DOS plugin", "Incorrect sector size.");
                return(Errno.InOutError);
            }

            sectorsPerTrack = device.Info.Sectors == 455 ? 13 : 16;

            // Read the VTOC
            vtocBlocks = device.ReadSector((ulong)(17 * sectorsPerTrack));
            vtoc       = Marshal.ByteArrayToStructureLittleEndian <Vtoc>(vtocBlocks);

            track1UsedByFiles = false;
            track2UsedByFiles = false;
            usedSectors       = 1;

            Errno error = ReadCatalog();

            if (error != Errno.NoError)
            {
                DicConsole.DebugWriteLine("Apple DOS plugin", "Unable to read catalog.");
                return(error);
            }

            error = CacheAllFiles();
            if (error != Errno.NoError)
            {
                DicConsole.DebugWriteLine("Apple DOS plugin", "Unable cache all files.");
                return(error);
            }

            // Create XML metadata for mounted filesystem
            XmlFsType = new FileSystemType
            {
                Bootable              = true,
                Clusters              = device.Info.Sectors,
                ClusterSize           = vtoc.bytesPerSector,
                Files                 = (ulong)catalogCache.Count,
                FilesSpecified        = true,
                FreeClustersSpecified = true,
                Type = "Apple DOS"
            };
            XmlFsType.FreeClusters = XmlFsType.Clusters - usedSectors;

            if (options == null)
            {
                options = GetDefaultOptions();
            }
            if (options.TryGetValue("debug", out string debugString))
            {
                bool.TryParse(debugString, out debug);
            }
            mounted = true;
            return(Errno.NoError);
        }
Ejemplo n.º 27
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            Encoding    = Encoding.UTF8;
            information = "";

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

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

            if (partition.Start + sbSize >= partition.End)
            {
                return;
            }

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

            RefsVolumeHeader refsVhdr = Marshal.ByteArrayToStructureLittleEndian <RefsVolumeHeader>(sector);

            DicConsole.DebugWriteLine("ReFS plugin", "VolumeHeader.jump empty? = {0}",
                                      ArrayHelpers.ArrayIsNullOrEmpty(refsVhdr.jump));
            DicConsole.DebugWriteLine("ReFS plugin", "VolumeHeader.signature = {0}",
                                      StringHandlers.CToString(refsVhdr.signature));
            DicConsole.DebugWriteLine("ReFS plugin", "VolumeHeader.mustBeZero empty? = {0}",
                                      ArrayHelpers.ArrayIsNullOrEmpty(refsVhdr.mustBeZero));
            DicConsole.DebugWriteLine("ReFS plugin", "VolumeHeader.identifier = {0}",
                                      StringHandlers.CToString(BitConverter.GetBytes(refsVhdr.identifier)));
            DicConsole.DebugWriteLine("ReFS plugin", "VolumeHeader.length = {0}", refsVhdr.length);
            DicConsole.DebugWriteLine("ReFS plugin", "VolumeHeader.checksum = 0x{0:X4}", refsVhdr.checksum);
            DicConsole.DebugWriteLine("ReFS plugin", "VolumeHeader.sectors = {0}", refsVhdr.sectors);
            DicConsole.DebugWriteLine("ReFS plugin", "VolumeHeader.bytesPerSector = {0}", refsVhdr.bytesPerSector);
            DicConsole.DebugWriteLine("ReFS plugin", "VolumeHeader.sectorsPerCluster = {0}",
                                      refsVhdr.sectorsPerCluster);
            DicConsole.DebugWriteLine("ReFS plugin", "VolumeHeader.unknown1 zero? = {0}", refsVhdr.unknown1 == 0);
            DicConsole.DebugWriteLine("ReFS plugin", "VolumeHeader.unknown2 zero? = {0}", refsVhdr.unknown2 == 0);
            DicConsole.DebugWriteLine("ReFS plugin", "VolumeHeader.unknown3 zero? = {0}", refsVhdr.unknown3 == 0);
            DicConsole.DebugWriteLine("ReFS plugin", "VolumeHeader.unknown4 zero? = {0}", refsVhdr.unknown4 == 0);
            DicConsole.DebugWriteLine("ReFS plugin", "VolumeHeader.unknown5 empty? = {0}",
                                      ArrayHelpers.ArrayIsNullOrEmpty(refsVhdr.unknown5));

            if (refsVhdr.identifier != FSRS || !ArrayHelpers.ArrayIsNullOrEmpty(refsVhdr.mustBeZero) ||
                !refsVhdr.signature.SequenceEqual(refsSignature))
            {
                return;
            }

            StringBuilder sb = new StringBuilder();

            sb.AppendLine("Microsoft Resilient File System");
            sb.AppendFormat("Volume uses {0} bytes per sector", refsVhdr.bytesPerSector).AppendLine();
            sb.AppendFormat("Volume uses {0} sectors per cluster ({1} bytes)", refsVhdr.sectorsPerCluster,
                            refsVhdr.sectorsPerCluster * refsVhdr.bytesPerSector).AppendLine();
            sb.AppendFormat("Volume has {0} sectors ({1} bytes)", refsVhdr.sectors,
                            refsVhdr.sectors * refsVhdr.bytesPerSector).AppendLine();

            information = sb.ToString();

            XmlFsType = new FileSystemType
            {
                Type        = "Resilient File System",
                ClusterSize = refsVhdr.bytesPerSector * refsVhdr.sectorsPerCluster,
                Clusters    = refsVhdr.sectors / refsVhdr.sectorsPerCluster
            };
        }
Ejemplo n.º 28
0
        public Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding,
                           Dictionary <string, string> options, string @namespace)
        {
            device   = imagePlugin;
            Encoding = encoding ?? new Apple2();
            if (options == null)
            {
                options = GetDefaultOptions();
            }
            if (options.TryGetValue("debug", out string debugString))
            {
                bool.TryParse(debugString, out debug);
            }
            if (device.Info.Sectors < 3)
            {
                return(Errno.InvalidArgument);
            }

            multiplier = (uint)(imagePlugin.Info.SectorSize == 256 ? 2 : 1);

            // Blocks 0 and 1 are boot code
            catalogBlocks = device.ReadSectors(multiplier * 2, multiplier);

            // On Apple //, it's little endian
            BigEndianBitConverter.IsLittleEndian =
                multiplier == 2 ? !BitConverter.IsLittleEndian : BitConverter.IsLittleEndian;

            mountedVolEntry.FirstBlock = BigEndianBitConverter.ToInt16(catalogBlocks, 0x00);
            mountedVolEntry.LastBlock  = BigEndianBitConverter.ToInt16(catalogBlocks, 0x02);
            mountedVolEntry.EntryType  = (PascalFileKind)BigEndianBitConverter.ToInt16(catalogBlocks, 0x04);
            mountedVolEntry.VolumeName = new byte[8];
            Array.Copy(catalogBlocks, 0x06, mountedVolEntry.VolumeName, 0, 8);
            mountedVolEntry.Blocks   = BigEndianBitConverter.ToInt16(catalogBlocks, 0x0E);
            mountedVolEntry.Files    = BigEndianBitConverter.ToInt16(catalogBlocks, 0x10);
            mountedVolEntry.Dummy    = BigEndianBitConverter.ToInt16(catalogBlocks, 0x12);
            mountedVolEntry.LastBoot = BigEndianBitConverter.ToInt16(catalogBlocks, 0x14);
            mountedVolEntry.Tail     = BigEndianBitConverter.ToInt32(catalogBlocks, 0x16);

            if (mountedVolEntry.FirstBlock != 0 ||
                mountedVolEntry.LastBlock <= mountedVolEntry.FirstBlock ||
                (ulong)mountedVolEntry.LastBlock > device.Info.Sectors / multiplier - 2 ||
                mountedVolEntry.EntryType != PascalFileKind.Volume &&
                mountedVolEntry.EntryType != PascalFileKind.Secure || mountedVolEntry.VolumeName[0] > 7 ||
                mountedVolEntry.Blocks < 0 ||
                (ulong)mountedVolEntry.Blocks != device.Info.Sectors / multiplier ||
                mountedVolEntry.Files < 0)
            {
                return(Errno.InvalidArgument);
            }

            catalogBlocks = device.ReadSectors(multiplier * 2,
                                               (uint)(mountedVolEntry.LastBlock - mountedVolEntry.FirstBlock - 2) *
                                               multiplier);
            int offset = 26;

            fileEntries = new List <PascalFileEntry>();
            while (offset + 26 < catalogBlocks.Length)
            {
                PascalFileEntry entry = new PascalFileEntry
                {
                    Filename         = new byte[16],
                    FirstBlock       = BigEndianBitConverter.ToInt16(catalogBlocks, offset + 0x00),
                    LastBlock        = BigEndianBitConverter.ToInt16(catalogBlocks, offset + 0x02),
                    EntryType        = (PascalFileKind)BigEndianBitConverter.ToInt16(catalogBlocks, offset + 0x04),
                    LastBytes        = BigEndianBitConverter.ToInt16(catalogBlocks, offset + 0x16),
                    ModificationTime = BigEndianBitConverter.ToInt16(catalogBlocks, offset + 0x18)
                };
                Array.Copy(catalogBlocks, offset + 0x06, entry.Filename, 0, 16);

                if (entry.Filename[0] <= 15 && entry.Filename[0] > 0)
                {
                    fileEntries.Add(entry);
                }

                offset += 26;
            }

            bootBlocks = device.ReadSectors(0, 2 * multiplier);

            XmlFsType = new FileSystemType
            {
                Bootable       = !ArrayHelpers.ArrayIsNullOrEmpty(bootBlocks),
                Clusters       = (ulong)mountedVolEntry.Blocks,
                ClusterSize    = device.Info.SectorSize,
                Files          = (ulong)mountedVolEntry.Files,
                FilesSpecified = true,
                Type           = "UCSD Pascal",
                VolumeName     = StringHandlers.PascalToString(mountedVolEntry.VolumeName, Encoding)
            };

            mounted = true;

            return(Errno.NoError);
        }
Ejemplo n.º 29
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            // TODO: Find correct default encoding
            Encoding    = Encoding.ASCII;
            information = "";
            var superBlockMetadata = new StringBuilder();

            byte[] sbSector = imagePlugin.ReadSector(0 + partition.Start);

            SuperBlock sb = Marshal.ByteArrayToStructureBigEndian <SuperBlock>(sbSector);

            if (sb.record_type != 1 ||
                sb.record_version != 1)
            {
                return;
            }

            if (Encoding.ASCII.GetString(sb.sync_bytes) != SYNC)
            {
                return;
            }

            superBlockMetadata.AppendFormat("Opera filesystem disc.").AppendLine();

            if (!string.IsNullOrEmpty(StringHandlers.CToString(sb.volume_label, Encoding)))
            {
                superBlockMetadata.
                AppendFormat("Volume label: {0}", StringHandlers.CToString(sb.volume_label, Encoding)).AppendLine();
            }

            if (!string.IsNullOrEmpty(StringHandlers.CToString(sb.volume_comment, Encoding)))
            {
                superBlockMetadata.
                AppendFormat("Volume comment: {0}", StringHandlers.CToString(sb.volume_comment, Encoding)).
                AppendLine();
            }

            superBlockMetadata.AppendFormat("Volume identifier: 0x{0:X8}", sb.volume_id).AppendLine();
            superBlockMetadata.AppendFormat("Block size: {0} bytes", sb.block_size).AppendLine();

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

            superBlockMetadata.
            AppendFormat("Volume size: {0} blocks, {1} bytes", sb.block_count, sb.block_size * sb.block_count).
            AppendLine();

            if (sb.block_count > imagePlugin.Info.Sectors)
            {
                superBlockMetadata.
                AppendFormat("WARNING: Filesystem indicates {0} blocks while device indicates {1} blocks",
                             sb.block_count, imagePlugin.Info.Sectors);
            }

            superBlockMetadata.AppendFormat("Root directory identifier: 0x{0:X8}", sb.root_dirid).AppendLine();
            superBlockMetadata.AppendFormat("Root directory block size: {0} bytes", sb.rootdir_bsize).AppendLine();

            superBlockMetadata.AppendFormat("Root directory size: {0} blocks, {1} bytes", sb.rootdir_blocks,
                                            sb.rootdir_bsize * sb.rootdir_blocks).AppendLine();

            superBlockMetadata.AppendFormat("Last root directory copy: {0}", sb.last_root_copy).AppendLine();

            information = superBlockMetadata.ToString();

            XmlFsType = new FileSystemType
            {
                Type        = "Opera",
                VolumeName  = StringHandlers.CToString(sb.volume_label, Encoding),
                ClusterSize = sb.block_size,
                Clusters    = sb.block_count
            };
        }
Ejemplo n.º 30
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            // Technically everything on Plan 9 from Bell Labs is in UTF-8
            Encoding    = Encoding.UTF8;
            information = "";

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

            ulong hdrSector = HEADER_POS / imagePlugin.Info.SectorSize;

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

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

            var sb = new StringBuilder();

            sb.AppendLine("Fossil");
            sb.AppendFormat("Filesystem version {0}", hdr.version).AppendLine();
            sb.AppendFormat("{0} bytes per block", hdr.blockSize).AppendLine();
            sb.AppendFormat("Superblock resides in block {0}", hdr.super).AppendLine();
            sb.AppendFormat("Labels resides in block {0}", hdr.label).AppendLine();
            sb.AppendFormat("Data starts at block {0}", hdr.data).AppendLine();
            sb.AppendFormat("Volume has {0} blocks", hdr.end).AppendLine();

            ulong sbLocation = (hdr.super * (hdr.blockSize / imagePlugin.Info.SectorSize)) + partition.Start;

            XmlFsType = new FileSystemType
            {
                Type        = "Fossil filesystem",
                ClusterSize = hdr.blockSize,
                Clusters    = hdr.end
            };

            if (sbLocation <= partition.End)
            {
                sector = imagePlugin.ReadSector(sbLocation);
                SuperBlock fsb = Marshal.ByteArrayToStructureBigEndian <SuperBlock>(sector);

                AaruConsole.DebugWriteLine("Fossil plugin", "magic 0x{0:X8} (expected 0x{1:X8})", fsb.magic,
                                           FOSSIL_SB_MAGIC);

                if (fsb.magic == FOSSIL_SB_MAGIC)
                {
                    sb.AppendFormat("Epoch low {0}", fsb.epochLow).AppendLine();
                    sb.AppendFormat("Epoch high {0}", fsb.epochHigh).AppendLine();
                    sb.AppendFormat("Next QID {0}", fsb.qid).AppendLine();
                    sb.AppendFormat("Active root block {0}", fsb.active).AppendLine();
                    sb.AppendFormat("Next root block {0}", fsb.next).AppendLine();
                    sb.AppendFormat("Current root block {0}", fsb.current).AppendLine();
                    sb.AppendFormat("Volume label: \"{0}\"", StringHandlers.CToString(fsb.name, Encoding)).AppendLine();
                    XmlFsType.VolumeName = StringHandlers.CToString(fsb.name, Encoding);
                }
            }

            information = sb.ToString();
        }
Ejemplo n.º 31
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            // ZFS is always UTF-8
            Encoding    = Encoding.UTF8;
            information = "";
            if (imagePlugin.Info.SectorSize < 512)
            {
                return;
            }

            byte[] sector;
            ulong  magic;

            ulong nvlistOff = 32;
            uint  nvlistLen = 114688 / imagePlugin.Info.SectorSize;

            if (partition.Start + 31 < partition.End)
            {
                sector = imagePlugin.ReadSector(partition.Start + 31);
                magic  = BitConverter.ToUInt64(sector, 0x1D8);
                if (magic == ZEC_MAGIC || magic == ZEC_CIGAM)
                {
                    nvlistOff = 32;
                }
            }

            if (partition.Start + 16 < partition.End)
            {
                sector = imagePlugin.ReadSector(partition.Start + 16);
                magic  = BitConverter.ToUInt64(sector, 0x1D8);
                if (magic == ZEC_MAGIC || magic == ZEC_CIGAM)
                {
                    nvlistOff = 17;
                }
            }

            StringBuilder sb = new StringBuilder();

            sb.AppendLine("ZFS filesystem");

            byte[] nvlist = imagePlugin.ReadSectors(partition.Start + nvlistOff, nvlistLen);

            sb.AppendLine(!DecodeNvList(nvlist, out Dictionary <string, NVS_Item> decodedNvList)
                              ? "Could not decode nvlist"
                              : PrintNvList(decodedNvList));

            information = sb.ToString();

            XmlFsType = new FileSystemType {
                Type = "ZFS filesystem"
            };
            if (decodedNvList.TryGetValue("name", out NVS_Item tmpObj))
            {
                XmlFsType.VolumeName = (string)tmpObj.value;
            }
            if (decodedNvList.TryGetValue("guid", out tmpObj))
            {
                XmlFsType.VolumeSerial = $"{(ulong)tmpObj.value}";
            }
            if (decodedNvList.TryGetValue("pool_guid", out tmpObj))
            {
                XmlFsType.VolumeSetIdentifier = $"{(ulong)tmpObj.value}";
            }
        }
Ejemplo n.º 32
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            Encoding    = encoding ?? new MacRoman();
            information = "";

            StringBuilder sb = new StringBuilder();

            MFS_MasterDirectoryBlock mdb = new MFS_MasterDirectoryBlock();
            MFS_BootBlock            bb  = new MFS_BootBlock();

            byte[] pString = new byte[16];

            byte[] mdbSector = imagePlugin.ReadSector(2 + partition.Start);
            byte[] bbSector  = imagePlugin.ReadSector(0 + partition.Start);

            mdb.drSigWord = BigEndianBitConverter.ToUInt16(mdbSector, 0x000);
            if (mdb.drSigWord != MFS_MAGIC)
            {
                return;
            }

            mdb.drCrDate   = BigEndianBitConverter.ToUInt32(mdbSector, 0x002);
            mdb.drLsBkUp   = BigEndianBitConverter.ToUInt32(mdbSector, 0x006);
            mdb.drAtrb     = BigEndianBitConverter.ToUInt16(mdbSector, 0x00A);
            mdb.drNmFls    = BigEndianBitConverter.ToUInt16(mdbSector, 0x00C);
            mdb.drDirSt    = BigEndianBitConverter.ToUInt16(mdbSector, 0x00E);
            mdb.drBlLen    = BigEndianBitConverter.ToUInt16(mdbSector, 0x010);
            mdb.drNmAlBlks = BigEndianBitConverter.ToUInt16(mdbSector, 0x012);
            mdb.drAlBlkSiz = BigEndianBitConverter.ToUInt32(mdbSector, 0x014);
            mdb.drClpSiz   = BigEndianBitConverter.ToUInt32(mdbSector, 0x018);
            mdb.drAlBlSt   = BigEndianBitConverter.ToUInt16(mdbSector, 0x01C);
            mdb.drNxtFNum  = BigEndianBitConverter.ToUInt32(mdbSector, 0x01E);
            mdb.drFreeBks  = BigEndianBitConverter.ToUInt16(mdbSector, 0x022);
            mdb.drVNSiz    = mdbSector[0x024];
            byte[] variableSize = new byte[mdb.drVNSiz + 1];
            Array.Copy(mdbSector, 0x024, variableSize, 0, mdb.drVNSiz + 1);
            mdb.drVN = StringHandlers.PascalToString(variableSize, Encoding);

            bb.signature = BigEndianBitConverter.ToUInt16(bbSector, 0x000);

            if (bb.signature == MFSBB_MAGIC)
            {
                bb.branch       = BigEndianBitConverter.ToUInt32(bbSector, 0x002);
                bb.boot_flags   = bbSector[0x006];
                bb.boot_version = bbSector[0x007];

                bb.sec_sv_pages = BigEndianBitConverter.ToInt16(bbSector, 0x008);

                Array.Copy(mdbSector, 0x00A, pString, 0, 16);
                bb.system_name = StringHandlers.PascalToString(pString, Encoding);
                Array.Copy(mdbSector, 0x01A, pString, 0, 16);
                bb.finder_name = StringHandlers.PascalToString(pString, Encoding);
                Array.Copy(mdbSector, 0x02A, pString, 0, 16);
                bb.debug_name = StringHandlers.PascalToString(pString, Encoding);
                Array.Copy(mdbSector, 0x03A, pString, 0, 16);
                bb.disasm_name = StringHandlers.PascalToString(pString, Encoding);
                Array.Copy(mdbSector, 0x04A, pString, 0, 16);
                bb.stupscr_name = StringHandlers.PascalToString(pString, Encoding);
                Array.Copy(mdbSector, 0x05A, pString, 0, 16);
                bb.bootup_name = StringHandlers.PascalToString(pString, Encoding);
                Array.Copy(mdbSector, 0x06A, pString, 0, 16);
                bb.clipbrd_name = StringHandlers.PascalToString(pString, Encoding);

                bb.max_files  = BigEndianBitConverter.ToUInt16(bbSector, 0x07A);
                bb.queue_size = BigEndianBitConverter.ToUInt16(bbSector, 0x07C);
                bb.heap_128k  = BigEndianBitConverter.ToUInt32(bbSector, 0x07E);
                bb.heap_256k  = BigEndianBitConverter.ToUInt32(bbSector, 0x082);
                bb.heap_512k  = BigEndianBitConverter.ToUInt32(bbSector, 0x086);
            }
            else
            {
                bb.signature = 0x0000;
            }

            sb.AppendLine("Apple Macintosh File System");
            sb.AppendLine();
            sb.AppendLine("Master Directory Block:");
            sb.AppendFormat("Creation date: {0}", DateHandlers.MacToDateTime(mdb.drCrDate)).AppendLine();
            sb.AppendFormat("Last backup date: {0}", DateHandlers.MacToDateTime(mdb.drLsBkUp)).AppendLine();
            if ((mdb.drAtrb & 0x80) == 0x80)
            {
                sb.AppendLine("Volume is locked by hardware.");
            }
            if ((mdb.drAtrb & 0x8000) == 0x8000)
            {
                sb.AppendLine("Volume is locked by software.");
            }
            sb.AppendFormat("{0} files on volume", mdb.drNmFls).AppendLine();
            sb.AppendFormat("First directory sector: {0}", mdb.drDirSt).AppendLine();
            sb.AppendFormat("{0} sectors in directory.", mdb.drBlLen).AppendLine();
            sb.AppendFormat("{0} volume allocation blocks.", mdb.drNmAlBlks + 1).AppendLine();
            sb.AppendFormat("Size of allocation blocks: {0} bytes", mdb.drAlBlkSiz).AppendLine();
            sb.AppendFormat("{0} bytes to allocate.", mdb.drClpSiz).AppendLine();
            sb.AppendFormat("First allocation block (#2) starts in sector {0}.", mdb.drAlBlSt).AppendLine();
            sb.AppendFormat("Next unused file number: {0}", mdb.drNxtFNum).AppendLine();
            sb.AppendFormat("{0} unused allocation blocks.", mdb.drFreeBks).AppendLine();
            sb.AppendFormat("Volume name: {0}", mdb.drVN).AppendLine();

            if (bb.signature == MFSBB_MAGIC)
            {
                sb.AppendLine("Volume is bootable.");
                sb.AppendLine();
                sb.AppendLine("Boot Block:");
                if ((bb.boot_flags & 0x40) == 0x40)
                {
                    sb.AppendLine("Boot block should be executed.");
                }
                if ((bb.boot_flags & 0x80) == 0x80)
                {
                    sb.AppendLine("Boot block is in new unknown format.");
                }
                else
                {
                    if (bb.sec_sv_pages > 0)
                    {
                        sb.AppendLine("Allocate secondary sound buffer at boot.");
                    }
                    else if (bb.sec_sv_pages < 0)
                    {
                        sb.AppendLine("Allocate secondary sound and video buffers at boot.");
                    }

                    sb.AppendFormat("System filename: {0}", bb.system_name).AppendLine();
                    sb.AppendFormat("Finder filename: {0}", bb.finder_name).AppendLine();
                    sb.AppendFormat("Debugger filename: {0}", bb.debug_name).AppendLine();
                    sb.AppendFormat("Disassembler filename: {0}", bb.disasm_name).AppendLine();
                    sb.AppendFormat("Startup screen filename: {0}", bb.stupscr_name).AppendLine();
                    sb.AppendFormat("First program to execute at boot: {0}", bb.bootup_name).AppendLine();
                    sb.AppendFormat("Clipboard filename: {0}", bb.clipbrd_name).AppendLine();
                    sb.AppendFormat("Maximum opened files: {0}", bb.max_files * 4).AppendLine();
                    sb.AppendFormat("Event queue size: {0}", bb.queue_size).AppendLine();
                    sb.AppendFormat("Heap size with 128KiB of RAM: {0} bytes", bb.heap_128k).AppendLine();
                    sb.AppendFormat("Heap size with 256KiB of RAM: {0} bytes", bb.heap_256k).AppendLine();
                    sb.AppendFormat("Heap size with 512KiB of RAM or more: {0} bytes", bb.heap_512k).AppendLine();
                }
            }
            else
            {
                sb.AppendLine("Volume is not bootable.");
            }

            information = sb.ToString();

            XmlFsType = new FileSystemType();
            if (mdb.drLsBkUp > 0)
            {
                XmlFsType.BackupDate          = DateHandlers.MacToDateTime(mdb.drLsBkUp);
                XmlFsType.BackupDateSpecified = true;
            }

            XmlFsType.Bootable    = bb.signature == MFSBB_MAGIC;
            XmlFsType.Clusters    = mdb.drNmAlBlks;
            XmlFsType.ClusterSize = mdb.drAlBlkSiz;
            if (mdb.drCrDate > 0)
            {
                XmlFsType.CreationDate          = DateHandlers.MacToDateTime(mdb.drCrDate);
                XmlFsType.CreationDateSpecified = true;
            }

            XmlFsType.Files                 = mdb.drNmFls;
            XmlFsType.FilesSpecified        = true;
            XmlFsType.FreeClusters          = mdb.drFreeBks;
            XmlFsType.FreeClustersSpecified = true;
            XmlFsType.Type       = "MFS";
            XmlFsType.VolumeName = mdb.drVN;
        }
Ejemplo n.º 33
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            Encoding = encoding ?? Encoding.GetEncoding("shift_jis");
            StringBuilder sbInformation = new StringBuilder();

            information = "";
            XmlFsType   = new FileSystemType();

            NintendoFields fields = new NintendoFields();

            BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian;

            byte[] header = imagePlugin.ReadSectors(0, 0x50000 / imagePlugin.Info.SectorSize);

            bool wii = false;

            uint magicGc  = BigEndianBitConverter.ToUInt32(header, 0x1C);
            uint magicWii = BigEndianBitConverter.ToUInt32(header, 0x18);

            if (magicWii == 0x5D1C9EA3)
            {
                wii = true;
            }
            else if (magicGc != 0xC2339F3D)
            {
                return;
            }

            fields.DiscType         = Encoding.ASCII.GetString(header, 0, 1);
            fields.GameCode         = Encoding.ASCII.GetString(header, 1, 2);
            fields.RegionCode       = Encoding.ASCII.GetString(header, 3, 1);
            fields.PublisherCode    = Encoding.ASCII.GetString(header, 4, 2);
            fields.DiscId           = Encoding.ASCII.GetString(header, 0, 6);
            fields.DiscNumber       = header[6];
            fields.DiscVersion      = header[7];
            fields.Streaming       |= header[8] > 0;
            fields.StreamBufferSize = header[9];
            byte[] temp = new byte[64];
            Array.Copy(header, 0x20, temp, 0, 64);
            fields.Title = StringHandlers.CToString(temp, Encoding);

            if (!wii)
            {
                fields.DebugOff  = BigEndianBitConverter.ToUInt32(header, 0x0400);
                fields.DebugAddr = BigEndianBitConverter.ToUInt32(header, 0x0404);
                fields.DolOff    = BigEndianBitConverter.ToUInt32(header, 0x0420);
                fields.FstOff    = BigEndianBitConverter.ToUInt32(header, 0x0424);
                fields.FstSize   = BigEndianBitConverter.ToUInt32(header, 0x0428);
                fields.FstMax    = BigEndianBitConverter.ToUInt32(header, 0x042C);
            }

            if (wii)
            {
                uint offset1 = BigEndianBitConverter.ToUInt32(header, 0x40004) << 2;
                uint offset2 = BigEndianBitConverter.ToUInt32(header, 0x4000C) << 2;
                uint offset3 = BigEndianBitConverter.ToUInt32(header, 0x40014) << 2;
                uint offset4 = BigEndianBitConverter.ToUInt32(header, 0x4001C) << 2;

                fields.FirstPartitions  = new NintendoPartition[BigEndianBitConverter.ToUInt32(header, 0x40000)];
                fields.SecondPartitions = new NintendoPartition[BigEndianBitConverter.ToUInt32(header, 0x40008)];
                fields.ThirdPartitions  = new NintendoPartition[BigEndianBitConverter.ToUInt32(header, 0x40010)];
                fields.FourthPartitions = new NintendoPartition[BigEndianBitConverter.ToUInt32(header, 0x40018)];

                for (int i = 0; i < fields.FirstPartitions.Length; i++)
                {
                    if (offset1 + i * 8 + 8 < 0x50000)
                    {
                        fields.FirstPartitions[i].Offset =
                            BigEndianBitConverter.ToUInt32(header, (int)(offset1 + i * 8 + 0)) << 2;
                        fields.FirstPartitions[i].Type =
                            BigEndianBitConverter.ToUInt32(header, (int)(offset1 + i * 8 + 4));
                    }
                }

                for (int i = 0; i < fields.SecondPartitions.Length; i++)
                {
                    if (offset1 + i * 8 + 8 < 0x50000)
                    {
                        fields.FirstPartitions[i].Offset =
                            BigEndianBitConverter.ToUInt32(header, (int)(offset2 + i * 8 + 0)) << 2;
                        fields.FirstPartitions[i].Type =
                            BigEndianBitConverter.ToUInt32(header, (int)(offset2 + i * 8 + 4));
                    }
                }

                for (int i = 0; i < fields.ThirdPartitions.Length; i++)
                {
                    if (offset1 + i * 8 + 8 < 0x50000)
                    {
                        fields.FirstPartitions[i].Offset =
                            BigEndianBitConverter.ToUInt32(header, (int)(offset3 + i * 8 + 0)) << 2;
                        fields.FirstPartitions[i].Type =
                            BigEndianBitConverter.ToUInt32(header, (int)(offset3 + i * 8 + 4));
                    }
                }

                for (int i = 0; i < fields.FourthPartitions.Length; i++)
                {
                    if (offset1 + i * 8 + 8 < 0x50000)
                    {
                        fields.FirstPartitions[i].Offset =
                            BigEndianBitConverter.ToUInt32(header, (int)(offset4 + i * 8 + 0)) << 2;
                        fields.FirstPartitions[i].Type =
                            BigEndianBitConverter.ToUInt32(header, (int)(offset4 + i * 8 + 4));
                    }
                }

                fields.Region       = header[0x4E000];
                fields.JapanAge     = header[0x4E010];
                fields.UsaAge       = header[0x4E011];
                fields.GermanAge    = header[0x4E013];
                fields.PegiAge      = header[0x4E014];
                fields.FinlandAge   = header[0x4E015];
                fields.PortugalAge  = header[0x4E016];
                fields.UkAge        = header[0x4E017];
                fields.AustraliaAge = header[0x4E018];
                fields.KoreaAge     = header[0x4E019];
            }
            else
            {
                fields.FirstPartitions  = new NintendoPartition[0];
                fields.SecondPartitions = new NintendoPartition[0];
                fields.ThirdPartitions  = new NintendoPartition[0];
                fields.FourthPartitions = new NintendoPartition[0];
            }

            DicConsole.DebugWriteLine("Nintendo plugin", "discType = {0}", fields.DiscType);
            DicConsole.DebugWriteLine("Nintendo plugin", "gameCode = {0}", fields.GameCode);
            DicConsole.DebugWriteLine("Nintendo plugin", "regionCode = {0}", fields.RegionCode);
            DicConsole.DebugWriteLine("Nintendo plugin", "publisherCode = {0}", fields.PublisherCode);
            DicConsole.DebugWriteLine("Nintendo plugin", "discID = {0}", fields.DiscId);
            DicConsole.DebugWriteLine("Nintendo plugin", "discNumber = {0}", fields.DiscNumber);
            DicConsole.DebugWriteLine("Nintendo plugin", "discVersion = {0}", fields.DiscVersion);
            DicConsole.DebugWriteLine("Nintendo plugin", "streaming = {0}", fields.Streaming);
            DicConsole.DebugWriteLine("Nintendo plugin", "streamBufferSize = {0}", fields.StreamBufferSize);
            DicConsole.DebugWriteLine("Nintendo plugin", "title = \"{0}\"", fields.Title);
            DicConsole.DebugWriteLine("Nintendo plugin", "debugOff = 0x{0:X8}", fields.DebugOff);
            DicConsole.DebugWriteLine("Nintendo plugin", "debugAddr = 0x{0:X8}", fields.DebugAddr);
            DicConsole.DebugWriteLine("Nintendo plugin", "dolOff = 0x{0:X8}", fields.DolOff);
            DicConsole.DebugWriteLine("Nintendo plugin", "fstOff = 0x{0:X8}", fields.FstOff);
            DicConsole.DebugWriteLine("Nintendo plugin", "fstSize = {0}", fields.FstSize);
            DicConsole.DebugWriteLine("Nintendo plugin", "fstMax = {0}", fields.FstMax);
            for (int i = 0; i < fields.FirstPartitions.Length; i++)
            {
                DicConsole.DebugWriteLine("Nintendo plugin", "firstPartitions[{1}].offset = {0}",
                                          fields.FirstPartitions[i].Offset, i);
                DicConsole.DebugWriteLine("Nintendo plugin", "firstPartitions[{1}].type = {0}",
                                          fields.FirstPartitions[i].Type, i);
            }

            for (int i = 0; i < fields.SecondPartitions.Length; i++)
            {
                DicConsole.DebugWriteLine("Nintendo plugin", "secondPartitions[{1}].offset = {0}",
                                          fields.SecondPartitions[i].Offset, i);
                DicConsole.DebugWriteLine("Nintendo plugin", "secondPartitions[{1}].type = {0}",
                                          fields.SecondPartitions[i].Type, i);
            }

            for (int i = 0; i < fields.ThirdPartitions.Length; i++)
            {
                DicConsole.DebugWriteLine("Nintendo plugin", "thirdPartitions[{1}].offset = {0}",
                                          fields.ThirdPartitions[i].Offset, i);
                DicConsole.DebugWriteLine("Nintendo plugin", "thirdPartitions[{1}].type = {0}",
                                          fields.ThirdPartitions[i].Type, i);
            }

            for (int i = 0; i < fields.FourthPartitions.Length; i++)
            {
                DicConsole.DebugWriteLine("Nintendo plugin", "fourthPartitions[{1}].offset = {0}",
                                          fields.FourthPartitions[i].Offset, i);
                DicConsole.DebugWriteLine("Nintendo plugin", "fourthPartitions[{1}].type = {0}",
                                          fields.FourthPartitions[i].Type, i);
            }

            DicConsole.DebugWriteLine("Nintendo plugin", "region = {0}", fields.Region);
            DicConsole.DebugWriteLine("Nintendo plugin", "japanAge = {0}", fields.JapanAge);
            DicConsole.DebugWriteLine("Nintendo plugin", "usaAge = {0}", fields.UsaAge);
            DicConsole.DebugWriteLine("Nintendo plugin", "germanAge = {0}", fields.GermanAge);
            DicConsole.DebugWriteLine("Nintendo plugin", "pegiAge = {0}", fields.PegiAge);
            DicConsole.DebugWriteLine("Nintendo plugin", "finlandAge = {0}", fields.FinlandAge);
            DicConsole.DebugWriteLine("Nintendo plugin", "portugalAge = {0}", fields.PortugalAge);
            DicConsole.DebugWriteLine("Nintendo plugin", "ukAge = {0}", fields.UkAge);
            DicConsole.DebugWriteLine("Nintendo plugin", "australiaAge = {0}", fields.AustraliaAge);
            DicConsole.DebugWriteLine("Nintendo plugin", "koreaAge = {0}", fields.KoreaAge);

            sbInformation.AppendLine("Nintendo optical filesystem");
            sbInformation.AppendLine(wii ? "Nintendo Wii Optical Disc" : "Nintendo GameCube Optical Disc");
            sbInformation.AppendFormat("Disc ID is {0}", fields.DiscId).AppendLine();
            sbInformation.AppendFormat("Disc is a {0} disc", DiscTypeToString(fields.DiscType)).AppendLine();
            sbInformation.AppendFormat("Disc region is {0}", RegionCodeToString(fields.RegionCode)).AppendLine();
            sbInformation.AppendFormat("Published by {0}", PublisherCodeToString(fields.PublisherCode)).AppendLine();
            if (fields.DiscNumber > 0)
            {
                sbInformation.AppendFormat("Disc number {0} of a multi-disc set", fields.DiscNumber + 1).AppendLine();
            }
            if (fields.Streaming)
            {
                sbInformation.AppendLine("Disc is prepared for audio streaming");
            }
            if (fields.StreamBufferSize > 0)
            {
                sbInformation.AppendFormat("Audio streaming buffer size is {0} bytes", fields.StreamBufferSize)
                .AppendLine();
            }
            sbInformation.AppendFormat("Title: {0}", fields.Title).AppendLine();

            if (wii)
            {
                for (int i = 0; i < fields.FirstPartitions.Length; i++)
                {
                    sbInformation.AppendFormat("First {0} partition starts at sector {1}",
                                               PartitionTypeToString(fields.FirstPartitions[i].Type),
                                               fields.FirstPartitions[i].Offset / 2048).AppendLine();
                }
                for (int i = 0; i < fields.SecondPartitions.Length; i++)
                {
                    sbInformation.AppendFormat("Second {0} partition starts at sector {1}",
                                               PartitionTypeToString(fields.SecondPartitions[i].Type),
                                               fields.SecondPartitions[i].Offset / 2048).AppendLine();
                }
                for (int i = 0; i < fields.ThirdPartitions.Length; i++)
                {
                    sbInformation.AppendFormat("Third {0} partition starts at sector {1}",
                                               PartitionTypeToString(fields.ThirdPartitions[i].Type),
                                               fields.ThirdPartitions[i].Offset / 2048).AppendLine();
                }
                for (int i = 0; i < fields.FourthPartitions.Length; i++)
                {
                    sbInformation.AppendFormat("Fourth {0} partition starts at sector {1}",
                                               PartitionTypeToString(fields.FourthPartitions[i].Type),
                                               fields.FourthPartitions[i].Offset / 2048).AppendLine();
                }

                //                sbInformation.AppendFormat("Region byte is {0}", fields.region).AppendLine();
                if ((fields.JapanAge & 0x80) != 0x80)
                {
                    sbInformation.AppendFormat("Japan age rating is {0}", fields.JapanAge).AppendLine();
                }
                if ((fields.UsaAge & 0x80) != 0x80)
                {
                    sbInformation.AppendFormat("ESRB age rating is {0}", fields.UsaAge).AppendLine();
                }
                if ((fields.GermanAge & 0x80) != 0x80)
                {
                    sbInformation.AppendFormat("German age rating is {0}", fields.GermanAge).AppendLine();
                }
                if ((fields.PegiAge & 0x80) != 0x80)
                {
                    sbInformation.AppendFormat("PEGI age rating is {0}", fields.PegiAge).AppendLine();
                }
                if ((fields.FinlandAge & 0x80) != 0x80)
                {
                    sbInformation.AppendFormat("Finland age rating is {0}", fields.FinlandAge).AppendLine();
                }
                if ((fields.PortugalAge & 0x80) != 0x80)
                {
                    sbInformation.AppendFormat("Portugal age rating is {0}", fields.PortugalAge).AppendLine();
                }
                if ((fields.UkAge & 0x80) != 0x80)
                {
                    sbInformation.AppendFormat("UK age rating is {0}", fields.UkAge).AppendLine();
                }
                if ((fields.AustraliaAge & 0x80) != 0x80)
                {
                    sbInformation.AppendFormat("Australia age rating is {0}", fields.AustraliaAge).AppendLine();
                }
                if ((fields.KoreaAge & 0x80) != 0x80)
                {
                    sbInformation.AppendFormat("Korea age rating is {0}", fields.KoreaAge).AppendLine();
                }
            }
            else
            {
                sbInformation.AppendFormat("FST starts at {0} and has {1} bytes", fields.FstOff, fields.FstSize)
                .AppendLine();
            }

            information            = sbInformation.ToString();
            XmlFsType.Bootable     = true;
            XmlFsType.Clusters     = (long)(imagePlugin.Info.Sectors * imagePlugin.Info.SectorSize / 2048);
            XmlFsType.ClusterSize  = 2048;
            XmlFsType.Type         = wii ? "Nintendo Wii filesystem" : "Nintendo Gamecube filesystem";
            XmlFsType.VolumeName   = fields.Title;
            XmlFsType.VolumeSerial = fields.DiscId;
        }
Ejemplo n.º 34
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;
            }

            RBF_IdSector    rbfSb     = new RBF_IdSector();
            RBF_NewIdSector rbf9000Sb = new RBF_NewIdSector();

            foreach (int i in new[] { 0, 4, 15 })
            {
                ulong location = (ulong)i;
                uint  sbSize   = (uint)(Marshal.SizeOf(rbfSb) / imagePlugin.Info.SectorSize);
                if (Marshal.SizeOf(rbfSb) % imagePlugin.Info.SectorSize != 0)
                {
                    sbSize++;
                }

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

                rbfSb     = BigEndianMarshal.ByteArrayToStructureBigEndian <RBF_IdSector>(sector);
                rbf9000Sb = BigEndianMarshal.ByteArrayToStructureBigEndian <RBF_NewIdSector>(sector);

                DicConsole.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 = (RBF_NewIdSector)BigEndianMarshal.SwapStructureMembersEndian(rbf9000Sb);
            }

            StringBuilder 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           = 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();
        }
        /// <summary>
        /// Config the SUT.
        /// </summary>
        /// <param name="fileSystemType">The file system type of the server.</param>
        /// <param name="serverSignState">Indicate what the message signing policy of server.</param>
        /// <param name="isSupportDfs">Indicate whether the server supports DFS.</param>
        /// <param name="isSupportPreviousVersion">Indicate whether the server will support previous version.</param>
        /// <param name="isMessageModePipe">Indicate the adapter to setup a message mode pipe or byte mode pipe</param>
        public void ServerSetup(
            FileSystemType fileSystemType,
            SignState serverSignState,
            bool isSupportDfs,
            bool isSupportPreviousVersion,
            bool isMessageModePipe)
        {
            bool isInteractiveAdapterUsed = bool.Parse(Site.Properties.Get("SutInteractiveAdapterIsUsed"));

            if (isInteractiveAdapterUsed)
            {
                IDeleteFilesInteractiveAdapter deleteFileAdapter = Site.GetAdapter<ISutInteractiveAdapter>();

                deleteFileAdapter.DeleteFiles();

                IConfigSignStateInteractiveAdapter configSignStateAdapter
                    = Site.GetAdapter<ISutInteractiveAdapter>();

                string sutName = Site.Properties["SutMachineName"];

                switch (serverSignState)
                {
                    case SignState.Disabled:
                        configSignStateAdapter.ConfigSignState(sutName, "Disabled");
                        break;
                    case SignState.Enabled:
                        configSignStateAdapter.ConfigSignState(sutName, "Enabled");
                        break;
                    case SignState.Required:
                        configSignStateAdapter.ConfigSignState(sutName, "Required");
                        break;
                    case SignState.DisabledUnlessRequired:
                        configSignStateAdapter.ConfigSignState(sutName, "DisabledUnlessRequired");
                        break;
                }
            }
            else
            {
                IDeleteFilesAdapter deleteFileAdapter = Site.GetAdapter<IDeleteFilesAdapter>();

                deleteFileAdapter.DeleteFiles();

                IConfigSignStateAdapter configSignStateAdapter = Site.GetAdapter<IConfigSignStateAdapter>();

                string sutName = Site.Properties["SutMachineName"];

                switch (serverSignState)
                {
                    case SignState.Disabled:
                        configSignStateAdapter.ConfigSignState(sutName, "Disabled");
                        break;
                    case SignState.Enabled:
                        configSignStateAdapter.ConfigSignState(sutName, "Enabled");
                        break;
                    case SignState.Required:
                        configSignStateAdapter.ConfigSignState(sutName, "Required");
                        break;
                    case SignState.DisabledUnlessRequired:
                        configSignStateAdapter.ConfigSignState(sutName, "DisabledUnlessRequired");
                        break;
                }
            }

            int totalByteWritten = 1;
            bool isSupportResumeKey = true;
            bool isSupportCopyChunk = true;
            if (fileSystemType == FileSystemType.Ntfs)
            {
                SmbAdapter.FsType = "Ntfs";
            }
            else
            {
                SmbAdapter.FsType = "Fat";
            }

            SmbAdapter.state = serverSignState;
            SmbAdapter.fileSystemType = fileSystemType;
            SmbAdapter.isSupportDfs = isSupportDfs;
            SmbAdapter.isMessageModePipe = isMessageModePipe;
            SmbAdapter.isPreviousVersion = isSupportPreviousVersion;

            SmbAdapter.isSupportStream = true;
            SmbAdapter.isSupportInfoLevelPassThru = true;
            SmbAdapter.isSupportNtSmb = true;
            SmbAdapter.isRapServerActive = true;
            this.ServerSetupResponse(
                totalByteWritten,
                SmbAdapter.isSupportInfoLevelPassThru,
                SmbAdapter.isSupportNtSmb,
                SmbAdapter.isRapServerActive,
                isSupportResumeKey,
                isSupportCopyChunk);
        }
Ejemplo n.º 36
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            Encoding = encoding ?? Encoding.GetEncoding("iso-8859-1");
            byte[]    rootBlockSector = imagePlugin.ReadSector(2 + partition.Start);
            RootBlock rootBlock       = Marshal.ByteArrayToStructureBigEndian <RootBlock>(rootBlockSector);

            StringBuilder sbInformation = new StringBuilder();

            XmlFsType = new FileSystemType();

            switch (rootBlock.diskType)
            {
            case AFS_DISK:
            case MUAF_DISK:
                sbInformation.Append("Professional File System v1");
                XmlFsType.Type = "PFS v1";
                break;

            case PFS2_DISK:
                sbInformation.Append("Professional File System v2");
                XmlFsType.Type = "PFS v2";
                break;

            case PFS_DISK:
            case MUPFS_DISK:
                sbInformation.Append("Professional File System v3");
                XmlFsType.Type = "PFS v3";
                break;
            }

            if (rootBlock.diskType == MUAF_DISK || rootBlock.diskType == MUPFS_DISK)
            {
                sbInformation.Append(", with multi-user support");
            }

            sbInformation.AppendLine();

            sbInformation.AppendFormat("Volume name: {0}", StringHandlers.PascalToString(rootBlock.diskname, Encoding))
            .AppendLine();
            sbInformation.AppendFormat("Volume has {0} free sectors of {1}", rootBlock.blocksfree, rootBlock.diskSize)
            .AppendLine();
            sbInformation.AppendFormat("Volume created on {0}",
                                       DateHandlers.AmigaToDateTime(rootBlock.creationday, rootBlock.creationminute,
                                                                    rootBlock.creationtick)).AppendLine();
            if (rootBlock.extension > 0)
            {
                sbInformation.AppendFormat("Root block extension resides at block {0}", rootBlock.extension)
                .AppendLine();
            }

            information = sbInformation.ToString();

            XmlFsType.CreationDate =
                DateHandlers.AmigaToDateTime(rootBlock.creationday, rootBlock.creationminute, rootBlock.creationtick);
            XmlFsType.CreationDateSpecified = true;
            XmlFsType.FreeClusters          = rootBlock.blocksfree;
            XmlFsType.FreeClustersSpecified = true;
            XmlFsType.Clusters    = rootBlock.diskSize;
            XmlFsType.ClusterSize = imagePlugin.Info.SectorSize;
            XmlFsType.VolumeName  = StringHandlers.PascalToString(rootBlock.diskname, Encoding);
        }