mirror of
https://github.com/aaru-dps/Aaru.Server.git
synced 2025-12-16 19:24:27 +00:00
REFACTOR: All refactor in DiscImageChef.Filesystems.
This commit is contained in:
@@ -46,55 +46,55 @@ namespace DiscImageChef.Filesystems
|
||||
// Information from Apple ProDOS 8 Technical Reference
|
||||
public class ProDOSPlugin : Filesystem
|
||||
{
|
||||
const byte EmptyStorageType = 0x00;
|
||||
const byte EMPTY_STORAGE_TYPE = 0x00;
|
||||
/// <summary>
|
||||
/// A file that occupies one block or less
|
||||
/// </summary>
|
||||
const byte SeedlingFileType = 0x01;
|
||||
const byte SEEDLING_FILE_TYPE = 0x01;
|
||||
/// <summary>
|
||||
/// A file that occupies between 2 and 256 blocks
|
||||
/// </summary>
|
||||
const byte SaplingFileType = 0x02;
|
||||
const byte SAPLING_FILE_TYPE = 0x02;
|
||||
/// <summary>
|
||||
/// A file that occupies between 257 and 32768 blocks
|
||||
/// </summary>
|
||||
const byte TreeFileType = 0x03;
|
||||
const byte PascalAreaType = 0x04;
|
||||
const byte SubDirectoryType = 0x0D;
|
||||
const byte SubDirectoryHeaderType = 0x0E;
|
||||
const byte RootDirectoryType = 0x0F;
|
||||
const byte TREE_FILE_TYPE = 0x03;
|
||||
const byte PASCAL_AREA_TYPE = 0x04;
|
||||
const byte SUBDIRECTORY_TYPE = 0x0D;
|
||||
const byte SUBDIRECTORY_HEADER_TYPE = 0x0E;
|
||||
const byte ROOT_DIRECTORY_TYPE = 0x0F;
|
||||
|
||||
const byte ProDOSVersion1 = 0x00;
|
||||
const byte VERSION1 = 0x00;
|
||||
|
||||
const uint ProDOSYearMask = 0xFE000000;
|
||||
const uint ProDOSMonthMask = 0x1E00000;
|
||||
const uint ProDOSDayMask = 0x1F0000;
|
||||
const uint ProDOSHourMask = 0x1F00;
|
||||
const uint ProDOSMinuteMask = 0x3F;
|
||||
const uint YEAR_MASK = 0xFE000000;
|
||||
const uint MONTH_MASK = 0x1E00000;
|
||||
const uint DAY_MASK = 0x1F0000;
|
||||
const uint HOUR_MASK = 0x1F00;
|
||||
const uint MINUTE_MASK = 0x3F;
|
||||
|
||||
const byte ProDOSDestroyAttribute = 0x80;
|
||||
const byte ProDOSRenameAttribute = 0x40;
|
||||
const byte ProDOSBackupAttribute = 0x20;
|
||||
const byte ProDOSWriteAttribute = 0x02;
|
||||
const byte ProDOSReadAttribute = 0x01;
|
||||
const byte ProDOSReservedAttributeMask = 0x1C;
|
||||
const byte DESTROY_ATTRIBUTE = 0x80;
|
||||
const byte RENAME_ATTRIBUTE = 0x40;
|
||||
const byte BACKUP_ATTRIBUTE = 0x20;
|
||||
const byte WRITE_ATTRIBUTE = 0x02;
|
||||
const byte READ_ATTRIBUTE = 0x01;
|
||||
const byte RESERVED_ATTRIBUTE_MASK = 0x1C;
|
||||
|
||||
const byte ProDOSStorageTypeMask = 0xF0;
|
||||
const byte ProDOSNameLengthMask = 0x0F;
|
||||
const byte ProDOSEntryLength = 0x27;
|
||||
const byte ProDOSEntriesPerBlock = 0x0D;
|
||||
const byte STORAGE_TYPE_MASK = 0xF0;
|
||||
const byte NAME_LENGTH_MASK = 0x0F;
|
||||
const byte ENTRY_LENGTH = 0x27;
|
||||
const byte ENTRIES_PER_BLOCK = 0x0D;
|
||||
|
||||
public ProDOSPlugin()
|
||||
{
|
||||
Name = "Apple ProDOS filesystem";
|
||||
PluginUUID = new Guid("43874265-7B8A-4739-BCF7-07F80D5932BF");
|
||||
PluginUuid = new Guid("43874265-7B8A-4739-BCF7-07F80D5932BF");
|
||||
CurrentEncoding = new LisaRoman();
|
||||
}
|
||||
|
||||
public ProDOSPlugin(Encoding encoding)
|
||||
{
|
||||
Name = "Apple ProDOS filesystem";
|
||||
PluginUUID = new Guid("43874265-7B8A-4739-BCF7-07F80D5932BF");
|
||||
PluginUuid = new Guid("43874265-7B8A-4739-BCF7-07F80D5932BF");
|
||||
// TODO: Until Apple ][ encoding is implemented
|
||||
CurrentEncoding = new LisaRoman();
|
||||
}
|
||||
@@ -102,7 +102,7 @@ namespace DiscImageChef.Filesystems
|
||||
public ProDOSPlugin(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
|
||||
{
|
||||
Name = "Apple ProDOS filesystem";
|
||||
PluginUUID = new Guid("43874265-7B8A-4739-BCF7-07F80D5932BF");
|
||||
PluginUuid = new Guid("43874265-7B8A-4739-BCF7-07F80D5932BF");
|
||||
// TODO: Until Apple ][ encoding is implemented
|
||||
CurrentEncoding = new LisaRoman();
|
||||
}
|
||||
@@ -121,8 +121,8 @@ namespace DiscImageChef.Filesystems
|
||||
byte[] tmp = imagePlugin.ReadSectors(partition.Start, 2);
|
||||
|
||||
foreach(int offset in new[] {0, 0x200, 0x400, 0x600, 0x800, 0xA00}.Where(offset => BitConverter.ToUInt16(tmp, offset) == 0 &&
|
||||
(byte)((tmp[offset + 0x04] & ProDOSStorageTypeMask) >> 4) == RootDirectoryType &&
|
||||
tmp[offset + 0x23] == ProDOSEntryLength && tmp[offset + 0x24] == ProDOSEntriesPerBlock)) {
|
||||
(byte)((tmp[offset + 0x04] & STORAGE_TYPE_MASK) >> 4) == ROOT_DIRECTORY_TYPE &&
|
||||
tmp[offset + 0x23] == ENTRY_LENGTH && tmp[offset + 0x24] == ENTRIES_PER_BLOCK)) {
|
||||
Array.Copy(tmp, offset, rootDirectoryKeyBlock, 0, 0x200);
|
||||
APMFromHDDOnCD = true;
|
||||
break;
|
||||
@@ -133,28 +133,28 @@ namespace DiscImageChef.Filesystems
|
||||
DicConsole.DebugWriteLine("ProDOS plugin", "prePointer = {0}", prePointer);
|
||||
if(prePointer != 0) return false;
|
||||
|
||||
byte storage_type = (byte)((rootDirectoryKeyBlock[0x04] & ProDOSStorageTypeMask) >> 4);
|
||||
DicConsole.DebugWriteLine("ProDOS plugin", "storage_type = {0}", storage_type);
|
||||
if(storage_type != RootDirectoryType) return false;
|
||||
byte storageType = (byte)((rootDirectoryKeyBlock[0x04] & STORAGE_TYPE_MASK) >> 4);
|
||||
DicConsole.DebugWriteLine("ProDOS plugin", "storage_type = {0}", storageType);
|
||||
if(storageType != ROOT_DIRECTORY_TYPE) return false;
|
||||
|
||||
byte entry_length = rootDirectoryKeyBlock[0x23];
|
||||
DicConsole.DebugWriteLine("ProDOS plugin", "entry_length = {0}", entry_length);
|
||||
if(entry_length != ProDOSEntryLength) return false;
|
||||
byte entryLength = rootDirectoryKeyBlock[0x23];
|
||||
DicConsole.DebugWriteLine("ProDOS plugin", "entry_length = {0}", entryLength);
|
||||
if(entryLength != ENTRY_LENGTH) return false;
|
||||
|
||||
byte entries_per_block = rootDirectoryKeyBlock[0x24];
|
||||
DicConsole.DebugWriteLine("ProDOS plugin", "entries_per_block = {0}", entries_per_block);
|
||||
if(entries_per_block != ProDOSEntriesPerBlock) return false;
|
||||
byte entriesPerBlock = rootDirectoryKeyBlock[0x24];
|
||||
DicConsole.DebugWriteLine("ProDOS plugin", "entries_per_block = {0}", entriesPerBlock);
|
||||
if(entriesPerBlock != ENTRIES_PER_BLOCK) return false;
|
||||
|
||||
ushort bit_map_pointer = BitConverter.ToUInt16(rootDirectoryKeyBlock, 0x27);
|
||||
DicConsole.DebugWriteLine("ProDOS plugin", "bit_map_pointer = {0}", bit_map_pointer);
|
||||
if(bit_map_pointer > partition.End) return false;
|
||||
ushort bitMapPointer = BitConverter.ToUInt16(rootDirectoryKeyBlock, 0x27);
|
||||
DicConsole.DebugWriteLine("ProDOS plugin", "bit_map_pointer = {0}", bitMapPointer);
|
||||
if(bitMapPointer > partition.End) return false;
|
||||
|
||||
ushort total_blocks = BitConverter.ToUInt16(rootDirectoryKeyBlock, 0x29);
|
||||
if(APMFromHDDOnCD) total_blocks /= 4;
|
||||
ushort totalBlocks = BitConverter.ToUInt16(rootDirectoryKeyBlock, 0x29);
|
||||
if(APMFromHDDOnCD) totalBlocks /= 4;
|
||||
|
||||
DicConsole.DebugWriteLine("ProDOS plugin", "{0} <= ({1} - {2} + 1)? {3}", total_blocks, partition.End,
|
||||
partition.Start, total_blocks <= partition.End - partition.Start + 1);
|
||||
return total_blocks <= partition.End - partition.Start + 1;
|
||||
DicConsole.DebugWriteLine("ProDOS plugin", "{0} <= ({1} - {2} + 1)? {3}", totalBlocks, partition.End,
|
||||
partition.Start, totalBlocks <= partition.End - partition.Start + 1);
|
||||
return totalBlocks <= partition.End - partition.Start + 1;
|
||||
}
|
||||
|
||||
public override void GetInformation(ImagePlugin imagePlugin, Partition partition,
|
||||
@@ -173,50 +173,45 @@ namespace DiscImageChef.Filesystems
|
||||
byte[] tmp = imagePlugin.ReadSectors(partition.Start, 2);
|
||||
|
||||
foreach(int offset in new[] {0, 0x200, 0x400, 0x600, 0x800, 0xA00}.Where(offset => BitConverter.ToUInt16(tmp, offset) == 0 &&
|
||||
(byte)((tmp[offset + 0x04] & ProDOSStorageTypeMask) >> 4) == RootDirectoryType &&
|
||||
tmp[offset + 0x23] == ProDOSEntryLength && tmp[offset + 0x24] == ProDOSEntriesPerBlock)) {
|
||||
(byte)((tmp[offset + 0x04] & STORAGE_TYPE_MASK) >> 4) == ROOT_DIRECTORY_TYPE &&
|
||||
tmp[offset + 0x23] == ENTRY_LENGTH && tmp[offset + 0x24] == ENTRIES_PER_BLOCK)) {
|
||||
Array.Copy(tmp, offset, rootDirectoryKeyBlockBytes, 0, 0x200);
|
||||
APMFromHDDOnCD = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ProDOSRootDirectoryKeyBlock rootDirectoryKeyBlock = new ProDOSRootDirectoryKeyBlock();
|
||||
rootDirectoryKeyBlock.header = new ProDOSRootDirectoryHeader();
|
||||
|
||||
byte[] temporal;
|
||||
int year, month, day, hour, minute;
|
||||
ushort temp_timestamp_left, temp_timestamp_right;
|
||||
uint temp_timestamp;
|
||||
ProDOSRootDirectoryKeyBlock rootDirectoryKeyBlock =
|
||||
new ProDOSRootDirectoryKeyBlock {header = new ProDOSRootDirectoryHeader()};
|
||||
|
||||
rootDirectoryKeyBlock.zero = BitConverter.ToUInt16(rootDirectoryKeyBlockBytes, 0x00);
|
||||
rootDirectoryKeyBlock.next_pointer = BitConverter.ToUInt16(rootDirectoryKeyBlockBytes, 0x02);
|
||||
rootDirectoryKeyBlock.header.storage_type =
|
||||
(byte)((rootDirectoryKeyBlockBytes[0x04] & ProDOSStorageTypeMask) >> 4);
|
||||
rootDirectoryKeyBlock.header.name_length = (byte)(rootDirectoryKeyBlockBytes[0x04] & ProDOSNameLengthMask);
|
||||
temporal = new byte[rootDirectoryKeyBlock.header.name_length];
|
||||
(byte)((rootDirectoryKeyBlockBytes[0x04] & STORAGE_TYPE_MASK) >> 4);
|
||||
rootDirectoryKeyBlock.header.name_length = (byte)(rootDirectoryKeyBlockBytes[0x04] & NAME_LENGTH_MASK);
|
||||
byte[] temporal = new byte[rootDirectoryKeyBlock.header.name_length];
|
||||
Array.Copy(rootDirectoryKeyBlockBytes, 0x05, temporal, 0, rootDirectoryKeyBlock.header.name_length);
|
||||
rootDirectoryKeyBlock.header.volume_name = CurrentEncoding.GetString(temporal);
|
||||
rootDirectoryKeyBlock.header.reserved = BitConverter.ToUInt64(rootDirectoryKeyBlockBytes, 0x14);
|
||||
|
||||
temp_timestamp_left = BitConverter.ToUInt16(rootDirectoryKeyBlockBytes, 0x1C);
|
||||
temp_timestamp_right = BitConverter.ToUInt16(rootDirectoryKeyBlockBytes, 0x1E);
|
||||
ushort tempTimestampLeft = BitConverter.ToUInt16(rootDirectoryKeyBlockBytes, 0x1C);
|
||||
ushort tempTimestampRight = BitConverter.ToUInt16(rootDirectoryKeyBlockBytes, 0x1E);
|
||||
|
||||
bool dateCorrect;
|
||||
try
|
||||
{
|
||||
temp_timestamp = (uint)((temp_timestamp_left << 16) + temp_timestamp_right);
|
||||
year = (int)((temp_timestamp & ProDOSYearMask) >> 25);
|
||||
month = (int)((temp_timestamp & ProDOSMonthMask) >> 21);
|
||||
day = (int)((temp_timestamp & ProDOSDayMask) >> 16);
|
||||
hour = (int)((temp_timestamp & ProDOSHourMask) >> 8);
|
||||
minute = (int)(temp_timestamp & ProDOSMinuteMask);
|
||||
uint tempTimestamp = (uint)((tempTimestampLeft << 16) + tempTimestampRight);
|
||||
int year = (int)((tempTimestamp & YEAR_MASK) >> 25);
|
||||
int month = (int)((tempTimestamp & MONTH_MASK) >> 21);
|
||||
int day = (int)((tempTimestamp & DAY_MASK) >> 16);
|
||||
int hour = (int)((tempTimestamp & HOUR_MASK) >> 8);
|
||||
int minute = (int)(tempTimestamp & MINUTE_MASK);
|
||||
year += 1900;
|
||||
if(year < 1940) year += 100;
|
||||
|
||||
DicConsole.DebugWriteLine("ProDOS plugin", "temp_timestamp_left = 0x{0:X4}", temp_timestamp_left);
|
||||
DicConsole.DebugWriteLine("ProDOS plugin", "temp_timestamp_right = 0x{0:X4}", temp_timestamp_right);
|
||||
DicConsole.DebugWriteLine("ProDOS plugin", "temp_timestamp = 0x{0:X8}", temp_timestamp);
|
||||
DicConsole.DebugWriteLine("ProDOS plugin", "temp_timestamp_left = 0x{0:X4}", tempTimestampLeft);
|
||||
DicConsole.DebugWriteLine("ProDOS plugin", "temp_timestamp_right = 0x{0:X4}", tempTimestampRight);
|
||||
DicConsole.DebugWriteLine("ProDOS plugin", "temp_timestamp = 0x{0:X8}", tempTimestamp);
|
||||
DicConsole.DebugWriteLine("ProDOS plugin",
|
||||
"Datetime field year {0}, month {1}, day {2}, hour {3}, minute {4}.", year,
|
||||
month, day, hour, minute);
|
||||
@@ -240,20 +235,20 @@ namespace DiscImageChef.Filesystems
|
||||
sbInformation.AppendLine("ProDOS uses 512 bytes/sector while devices uses 2048 bytes/sector.")
|
||||
.AppendLine();
|
||||
|
||||
if(rootDirectoryKeyBlock.header.version != ProDOSVersion1 ||
|
||||
rootDirectoryKeyBlock.header.min_version != ProDOSVersion1)
|
||||
if(rootDirectoryKeyBlock.header.version != VERSION1 ||
|
||||
rootDirectoryKeyBlock.header.min_version != VERSION1)
|
||||
{
|
||||
sbInformation.AppendLine("Warning! Detected unknown ProDOS version ProDOS filesystem.");
|
||||
sbInformation.AppendLine("All of the following information may be incorrect");
|
||||
}
|
||||
|
||||
if(rootDirectoryKeyBlock.header.version == ProDOSVersion1)
|
||||
if(rootDirectoryKeyBlock.header.version == VERSION1)
|
||||
sbInformation.AppendLine("ProDOS version 1 used to create this volume.");
|
||||
else
|
||||
sbInformation.AppendFormat("Unknown ProDOS version with field {0} used to create this volume.",
|
||||
rootDirectoryKeyBlock.header.version).AppendLine();
|
||||
|
||||
if(rootDirectoryKeyBlock.header.min_version == ProDOSVersion1)
|
||||
if(rootDirectoryKeyBlock.header.min_version == VERSION1)
|
||||
sbInformation.AppendLine("ProDOS version 1 at least required for reading this volume.");
|
||||
else
|
||||
sbInformation
|
||||
@@ -275,36 +270,36 @@ namespace DiscImageChef.Filesystems
|
||||
sbInformation.AppendFormat("Bitmap starts at block {0}", rootDirectoryKeyBlock.header.bit_map_pointer)
|
||||
.AppendLine();
|
||||
|
||||
if((rootDirectoryKeyBlock.header.access & ProDOSReadAttribute) == ProDOSReadAttribute)
|
||||
if((rootDirectoryKeyBlock.header.access & READ_ATTRIBUTE) == READ_ATTRIBUTE)
|
||||
sbInformation.AppendLine("Volume can be read");
|
||||
if((rootDirectoryKeyBlock.header.access & ProDOSWriteAttribute) == ProDOSWriteAttribute)
|
||||
if((rootDirectoryKeyBlock.header.access & WRITE_ATTRIBUTE) == WRITE_ATTRIBUTE)
|
||||
sbInformation.AppendLine("Volume can be written");
|
||||
if((rootDirectoryKeyBlock.header.access & ProDOSRenameAttribute) == ProDOSRenameAttribute)
|
||||
if((rootDirectoryKeyBlock.header.access & RENAME_ATTRIBUTE) == RENAME_ATTRIBUTE)
|
||||
sbInformation.AppendLine("Volume can be renamed");
|
||||
if((rootDirectoryKeyBlock.header.access & ProDOSDestroyAttribute) == ProDOSDestroyAttribute)
|
||||
if((rootDirectoryKeyBlock.header.access & DESTROY_ATTRIBUTE) == DESTROY_ATTRIBUTE)
|
||||
sbInformation.AppendLine("Volume can be destroyed");
|
||||
if((rootDirectoryKeyBlock.header.access & ProDOSBackupAttribute) == ProDOSBackupAttribute)
|
||||
if((rootDirectoryKeyBlock.header.access & BACKUP_ATTRIBUTE) == BACKUP_ATTRIBUTE)
|
||||
sbInformation.AppendLine("Volume must be backed up");
|
||||
|
||||
if((rootDirectoryKeyBlock.header.access & ProDOSReservedAttributeMask) != 0)
|
||||
if((rootDirectoryKeyBlock.header.access & RESERVED_ATTRIBUTE_MASK) != 0)
|
||||
DicConsole.DebugWriteLine("ProDOS plugin", "Reserved attributes are set: {0:X2}",
|
||||
rootDirectoryKeyBlock.header.access);
|
||||
|
||||
information = sbInformation.ToString();
|
||||
|
||||
xmlFSType = new FileSystemType();
|
||||
xmlFSType.VolumeName = rootDirectoryKeyBlock.header.volume_name;
|
||||
XmlFsType = new FileSystemType();
|
||||
XmlFsType.VolumeName = rootDirectoryKeyBlock.header.volume_name;
|
||||
if(dateCorrect)
|
||||
{
|
||||
xmlFSType.CreationDate = rootDirectoryKeyBlock.header.creation_time;
|
||||
xmlFSType.CreationDateSpecified = true;
|
||||
XmlFsType.CreationDate = rootDirectoryKeyBlock.header.creation_time;
|
||||
XmlFsType.CreationDateSpecified = true;
|
||||
}
|
||||
xmlFSType.Files = rootDirectoryKeyBlock.header.file_count;
|
||||
xmlFSType.FilesSpecified = true;
|
||||
xmlFSType.Clusters = rootDirectoryKeyBlock.header.total_blocks;
|
||||
xmlFSType.ClusterSize = (int)((partition.End - partition.Start + 1) * imagePlugin.ImageInfo.SectorSize /
|
||||
(ulong)xmlFSType.Clusters);
|
||||
xmlFSType.Type = "ProDOS";
|
||||
XmlFsType.Files = rootDirectoryKeyBlock.header.file_count;
|
||||
XmlFsType.FilesSpecified = true;
|
||||
XmlFsType.Clusters = rootDirectoryKeyBlock.header.total_blocks;
|
||||
XmlFsType.ClusterSize = (int)((partition.End - partition.Start + 1) * imagePlugin.ImageInfo.SectorSize /
|
||||
(ulong)XmlFsType.Clusters);
|
||||
XmlFsType.Type = "ProDOS";
|
||||
}
|
||||
|
||||
public override Errno Mount()
|
||||
|
||||
Reference in New Issue
Block a user