REFACTOR: Final cleanup of DiscImageChef.Filters.

This commit is contained in:
2017-12-24 02:43:49 +00:00
parent 4115698ac8
commit f9cc6e6918
13 changed files with 495 additions and 487 deletions

View File

@@ -42,113 +42,31 @@ namespace DiscImageChef.Filters
/// </summary>
public class AppleDouble : Filter
{
enum AppleDoubleEntryID : uint
{
Invalid = 0,
DataFork = 1,
ResourceFork = 2,
RealName = 3,
Comment = 4,
Icon = 5,
ColorIcon = 6,
FileInfo = 7,
FileDates = 8,
FinderInfo = 9,
MacFileInfo = 10,
ProDOSFileInfo = 11,
DOSFileInfo = 12,
ShortName = 13,
AFPFileInfo = 14,
DirectoryID = 15
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct AppleDoubleHeader
{
public uint magic;
public uint version;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] homeFilesystem;
public ushort entries;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct AppleDoubleEntry
{
public uint id;
public uint offset;
public uint length;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct AppleDoubleFileDates
{
public uint creationDate;
public uint modificationDate;
public uint backupDate;
public uint accessDate;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct AppleDoubleMacFileInfo
{
public uint creationDate;
public uint modificationDate;
public uint backupDate;
public uint accessDate;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct AppleDoubleUNIXFileInfo
{
public uint creationDate;
public uint accessDate;
public uint modificationDate;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct AppleDoubleDOSFileInfo
{
public ushort modificationDate;
public ushort modificationTime;
public ushort attributes;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct AppleDoubleProDOSFileInfo
{
public uint creationDate;
public uint modificationDate;
public uint backupDate;
public ushort access;
public ushort fileType;
public uint auxType;
}
const uint AppleDoubleMagic = 0x00051607;
const uint AppleDoubleVersion = 0x00010000;
const uint AppleDoubleVersion2 = 0x00020000;
readonly byte[] DOSHome =
{0x4D, 0x53, 0x2D, 0x44, 0x4F, 0x53, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20};
readonly byte[] MacintoshHome =
{0x4D, 0x61, 0x63, 0x69, 0x6E, 0x74, 0x6F, 0x73, 0x68, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20};
readonly byte[] OSXHome =
{0x4D, 0x61, 0x63, 0x20, 0x4F, 0x53, 0x20, 0x58, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20};
readonly byte[] ProDOSHome =
{0x50, 0x72, 0x6F, 0x44, 0x4F, 0x53, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20};
readonly byte[] DOSHome =
{0x4D, 0x53, 0x2D, 0x44, 0x4F, 0x53, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20};
readonly byte[] UNIXHome =
{0x55, 0x6E, 0x69, 0x78, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20};
readonly byte[] VMXHome =
{0x56, 0x41, 0x58, 0x20, 0x56, 0x4D, 0x53, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20};
readonly byte[] OSXHome =
{0x4D, 0x61, 0x63, 0x20, 0x4F, 0x53, 0x20, 0x58, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20};
string basePath;
DateTime creationTime;
AppleDoubleEntry dataFork;
AppleDoubleEntry rsrcFork;
bool opened;
string basePath;
AppleDoubleHeader header;
string headerPath;
DateTime lastWriteTime;
DateTime creationTime;
AppleDoubleHeader header;
bool opened;
AppleDoubleEntry rsrcFork;
public AppleDouble()
{
@@ -263,7 +181,8 @@ namespace DiscImageChef.Filters
UNIXAppleDouble = Path.Combine(parentFolder, "%" + filename);
DOSAppleDouble = Path.Combine(parentFolder, filenameNoExt + ".ADF");
DOSAppleDoubleLower = Path.Combine(parentFolder, filenameNoExt + ".adf");
NetatalkAppleDouble = Path.Combine(parentFolder, ".AppleDouble", filename ?? throw new InvalidOperationException());
NetatalkAppleDouble = Path.Combine(parentFolder, ".AppleDouble",
filename ?? throw new InvalidOperationException());
DAVEAppleDouble = Path.Combine(parentFolder, "resource.frk", filename);
OSXAppleDouble = Path.Combine(parentFolder, "._" + filename);
UnArAppleDouble = Path.Combine(parentFolder, filename + ".rsrc");
@@ -431,7 +350,8 @@ namespace DiscImageChef.Filters
UNIXAppleDouble = Path.Combine(parentFolder, "%" + filename);
DOSAppleDouble = Path.Combine(parentFolder, filenameNoExt + ".ADF");
DOSAppleDoubleLower = Path.Combine(parentFolder, filenameNoExt + ".adf");
NetatalkAppleDouble = Path.Combine(parentFolder, ".AppleDouble", filename ?? throw new InvalidOperationException());
NetatalkAppleDouble = Path.Combine(parentFolder, ".AppleDouble",
filename ?? throw new InvalidOperationException());
DAVEAppleDouble = Path.Combine(parentFolder, "resource.frk", filename);
OSXAppleDouble = Path.Combine(parentFolder, "._" + filename);
UnArAppleDouble = Path.Combine(parentFolder, filename + ".rsrc");
@@ -646,5 +566,87 @@ namespace DiscImageChef.Filters
opened = true;
basePath = path;
}
enum AppleDoubleEntryID : uint
{
Invalid = 0,
DataFork = 1,
ResourceFork = 2,
RealName = 3,
Comment = 4,
Icon = 5,
ColorIcon = 6,
FileInfo = 7,
FileDates = 8,
FinderInfo = 9,
MacFileInfo = 10,
ProDOSFileInfo = 11,
DOSFileInfo = 12,
ShortName = 13,
AFPFileInfo = 14,
DirectoryID = 15
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct AppleDoubleHeader
{
public uint magic;
public uint version;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] homeFilesystem;
public ushort entries;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct AppleDoubleEntry
{
public uint id;
public uint offset;
public uint length;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct AppleDoubleFileDates
{
public uint creationDate;
public uint modificationDate;
public uint backupDate;
public uint accessDate;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct AppleDoubleMacFileInfo
{
public uint creationDate;
public uint modificationDate;
public uint backupDate;
public uint accessDate;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct AppleDoubleUNIXFileInfo
{
public uint creationDate;
public uint accessDate;
public uint modificationDate;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct AppleDoubleDOSFileInfo
{
public ushort modificationDate;
public ushort modificationTime;
public ushort attributes;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct AppleDoubleProDOSFileInfo
{
public uint creationDate;
public uint modificationDate;
public uint backupDate;
public ushort access;
public ushort fileType;
public uint auxType;
}
}
}

View File

@@ -42,114 +42,32 @@ namespace DiscImageChef.Filters
/// </summary>
public class AppleSingle : Filter
{
enum AppleSingleEntryID : uint
{
Invalid = 0,
DataFork = 1,
ResourceFork = 2,
RealName = 3,
Comment = 4,
Icon = 5,
ColorIcon = 6,
FileInfo = 7,
FileDates = 8,
FinderInfo = 9,
MacFileInfo = 10,
ProDOSFileInfo = 11,
DOSFileInfo = 12,
ShortName = 13,
AFPFileInfo = 14,
DirectoryID = 15
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct AppleSingleHeader
{
public uint magic;
public uint version;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] homeFilesystem;
public ushort entries;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct AppleSingleEntry
{
public uint id;
public uint offset;
public uint length;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct AppleSingleFileDates
{
public uint creationDate;
public uint modificationDate;
public uint backupDate;
public uint accessDate;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct AppleSingleMacFileInfo
{
public uint creationDate;
public uint modificationDate;
public uint backupDate;
public uint accessDate;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct AppleSingleUNIXFileInfo
{
public uint creationDate;
public uint accessDate;
public uint modificationDate;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct AppleSingleDOSFileInfo
{
public ushort modificationDate;
public ushort modificationTime;
public ushort attributes;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct AppleSingleProDOSFileInfo
{
public uint creationDate;
public uint modificationDate;
public uint backupDate;
public ushort access;
public ushort fileType;
public uint auxType;
}
const uint AppleSingleMagic = 0x00051600;
const uint AppleSingleVersion = 0x00010000;
const uint AppleSingleVersion2 = 0x00020000;
readonly byte[] DOSHome =
{0x4D, 0x53, 0x2D, 0x44, 0x4F, 0x53, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20};
readonly byte[] MacintoshHome =
{0x4D, 0x61, 0x63, 0x69, 0x6E, 0x74, 0x6F, 0x73, 0x68, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20};
readonly byte[] OSXHome =
{0x4D, 0x61, 0x63, 0x20, 0x4F, 0x53, 0x20, 0x58, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20};
readonly byte[] ProDOSHome =
{0x50, 0x72, 0x6F, 0x44, 0x4F, 0x53, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20};
readonly byte[] DOSHome =
{0x4D, 0x53, 0x2D, 0x44, 0x4F, 0x53, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20};
readonly byte[] UNIXHome =
{0x55, 0x6E, 0x69, 0x78, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20};
readonly byte[] VMSHome =
{0x56, 0x41, 0x58, 0x20, 0x56, 0x4D, 0x53, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20};
readonly byte[] OSXHome =
{0x4D, 0x61, 0x63, 0x20, 0x4F, 0x53, 0x20, 0x58, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20};
string basePath;
byte[] bytes;
DateTime creationTime;
AppleSingleEntry dataFork;
AppleSingleEntry rsrcFork;
byte[] bytes;
Stream stream;
bool isBytes, isStream, isPath, opened;
string basePath;
DateTime lastWriteTime;
DateTime creationTime;
AppleSingleHeader header;
bool isBytes, isStream, isPath, opened;
DateTime lastWriteTime;
AppleSingleEntry rsrcFork;
Stream stream;
public AppleSingle()
{
@@ -519,5 +437,87 @@ namespace DiscImageChef.Filters
isPath = true;
basePath = path;
}
enum AppleSingleEntryID : uint
{
Invalid = 0,
DataFork = 1,
ResourceFork = 2,
RealName = 3,
Comment = 4,
Icon = 5,
ColorIcon = 6,
FileInfo = 7,
FileDates = 8,
FinderInfo = 9,
MacFileInfo = 10,
ProDOSFileInfo = 11,
DOSFileInfo = 12,
ShortName = 13,
AFPFileInfo = 14,
DirectoryID = 15
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct AppleSingleHeader
{
public uint magic;
public uint version;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] homeFilesystem;
public ushort entries;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct AppleSingleEntry
{
public uint id;
public uint offset;
public uint length;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct AppleSingleFileDates
{
public uint creationDate;
public uint modificationDate;
public uint backupDate;
public uint accessDate;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct AppleSingleMacFileInfo
{
public uint creationDate;
public uint modificationDate;
public uint backupDate;
public uint accessDate;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct AppleSingleUNIXFileInfo
{
public uint creationDate;
public uint accessDate;
public uint modificationDate;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct AppleSingleDOSFileInfo
{
public ushort modificationDate;
public ushort modificationTime;
public ushort attributes;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct AppleSingleProDOSFileInfo
{
public uint creationDate;
public uint modificationDate;
public uint backupDate;
public ushort access;
public ushort fileType;
public uint auxType;
}
}
}

View File

@@ -42,13 +42,13 @@ namespace DiscImageChef.Filters
/// </summary>
public class BZip2 : Filter
{
Stream dataStream;
string basePath;
DateTime lastWriteTime;
DateTime creationTime;
bool opened;
Stream dataStream;
long decompressedSize;
Stream innerStream;
DateTime lastWriteTime;
bool opened;
public BZip2()
{
@@ -96,7 +96,8 @@ namespace DiscImageChef.Filters
if(buffer.Length <= 512) return true;
return buffer[buffer.Length - 512] != 0x6B || buffer[buffer.Length - 511] != 0x6F || buffer[buffer.Length - 510] != 0x6C || buffer[buffer.Length - 509] != 0x79;
return buffer[buffer.Length - 512] != 0x6B || buffer[buffer.Length - 511] != 0x6F ||
buffer[buffer.Length - 510] != 0x6C || buffer[buffer.Length - 509] != 0x79;
}
public override bool Identify(Stream stream)
@@ -139,8 +140,7 @@ namespace DiscImageChef.Filters
stream.Read(buffer, 0, 4);
stream.Seek(0, SeekOrigin.Begin);
// Check it is not an UDIF
if(buffer[0] == 0x6B && buffer[1] == 0x6F && buffer[2] == 0x6C && buffer[3] == 0x79)
return false;
if(buffer[0] == 0x6B && buffer[1] == 0x6F && buffer[2] == 0x6C && buffer[3] == 0x79) return false;
return true;
}

View File

@@ -46,8 +46,8 @@ namespace DiscImageChef.Filters
public abstract void Close();
/// <summary>
/// Gets the path used to open this filter.<br/>
/// UNIX: /path/to/archive.zip/path/to/file.bin => /path/to/archive.zip/path/to/file.bin <br/>
/// Gets the path used to open this filter.<br />
/// UNIX: /path/to/archive.zip/path/to/file.bin => /path/to/archive.zip/path/to/file.bin <br />
/// Windows: C:\path\to\archive.zip\path\to\file.bin => C:\path\to\archive.zip\path\to\file.bin
/// </summary>
/// <returns>Path used to open this filter.</returns>
@@ -72,8 +72,8 @@ namespace DiscImageChef.Filters
public abstract Stream GetDataForkStream();
/// <summary>
/// Gets the filename for the file referenced by this filter.<br/>
/// UNIX: /path/to/archive.zip/path/to/file.bin => file.bin <br/>
/// Gets the filename for the file referenced by this filter.<br />
/// UNIX: /path/to/archive.zip/path/to/file.bin => file.bin <br />
/// Windows: C:\path\to\archive.zip\path\to\file.bin => file.bin
/// </summary>
/// <returns>The filename.</returns>
@@ -92,16 +92,17 @@ namespace DiscImageChef.Filters
public abstract long GetLength();
/// <summary>
/// Gets full path to file referenced by this filter. If it's an archive, it's the path inside the archive.<br/>
/// UNIX: /path/to/archive.zip/path/to/file.bin => /path/to/file.bin <br/>
/// Gets full path to file referenced by this filter. If it's an archive, it's the path inside the archive.<br />
/// UNIX: /path/to/archive.zip/path/to/file.bin => /path/to/file.bin <br />
/// Windows: C:\path\to\archive.zip\path\to\file.bin => \path\to\file.bin
/// </summary>
/// <returns>The path.</returns>
public abstract string GetPath();
/// <summary>
/// Gets path to parent folder to the file referenced by this filter. If it's an archive, it's the full path to the archive itself.<br/>
/// UNIX: /path/to/archive.zip/path/to/file.bin => /path/to/archive.zip <br/>
/// Gets path to parent folder to the file referenced by this filter. If it's an archive, it's the full path to the
/// archive itself.<br />
/// UNIX: /path/to/archive.zip/path/to/file.bin => /path/to/archive.zip <br />
/// Windows: C:\path\to\archive.zip\path\to\file.bin => C:\path\to\archive.zip
/// </summary>
/// <returns>The parent folder.</returns>
@@ -143,7 +144,7 @@ namespace DiscImageChef.Filters
public abstract bool Identify(byte[] buffer);
/// <summary>
/// Returns true if the filter has a file/stream/buffer currently opened and no <see cref="Close"/> has been issued.
/// Returns true if the filter has a file/stream/buffer currently opened and no <see cref="Close" /> has been issued.
/// </summary>
public abstract bool IsOpened();

View File

@@ -55,7 +55,8 @@ namespace DiscImageChef.Filters
if(!type.IsSubclassOf(typeof(Filter))) continue;
Filter filter = (Filter)type.GetConstructor(Type.EmptyTypes)?.Invoke(new object[] { });
if(filter != null && !Filters.ContainsKey(filter.Name.ToLower())) Filters.Add(filter.Name.ToLower(), filter);
if(filter != null && !Filters.ContainsKey(filter.Name.ToLower()))
Filters.Add(filter.Name.ToLower(), filter);
}
catch(Exception exception) { DicConsole.ErrorWriteLine("Exception {0}", exception); }
}

View File

@@ -41,14 +41,14 @@ namespace DiscImageChef.Filters
/// </summary>
public class ForcedSeekStream<T> : Stream where T : Stream
{
const int BUFFER_LEN = 1048576;
string backFile;
FileStream backStream;
T baseStream;
long streamLength;
const int BUFFER_LEN = 1048576;
FileStream backStream;
string backFile;
/// <summary>
/// Initializes a new instance of the <see cref="T:DiscImageChef.Filters.ForcedSeekStream`1"/> class.
/// Initializes a new instance of the <see cref="T:DiscImageChef.Filters.ForcedSeekStream`1" /> class.
/// </summary>
/// <param name="length">The real (uncompressed) length of the stream.</param>
/// <param name="args">Parameters that are used to create the base stream.</param>
@@ -62,7 +62,7 @@ namespace DiscImageChef.Filters
}
/// <summary>
/// Initializes a new instance of the <see cref="T:DiscImageChef.Filters.ForcedSeekStream`1"/> class.
/// Initializes a new instance of the <see cref="T:DiscImageChef.Filters.ForcedSeekStream`1" /> class.
/// </summary>
/// <param name="args">Parameters that are used to create the base stream.</param>
public ForcedSeekStream(params object[] args)
@@ -73,6 +73,21 @@ namespace DiscImageChef.Filters
CalculateLength();
}
public override bool CanRead => baseStream.CanRead;
public override bool CanSeek => true;
public override bool CanWrite => false;
public override long Length => streamLength;
public override long Position
{
get => backStream.Position;
set => SetPosition(value);
}
/// <summary>
/// Calculates the real (uncompressed) length of the stream.
/// It basically reads (uncompresses) the whole stream to memory discarding its contents,
@@ -94,21 +109,6 @@ namespace DiscImageChef.Filters
backStream.Position = 0;
}
public override bool CanRead => baseStream.CanRead;
public override bool CanSeek => true;
public override bool CanWrite => false;
public override long Length => streamLength;
public override long Position
{
get => backStream.Position;
set => SetPosition(value);
}
void SetPosition(long position)
{
if(position == backStream.Position) return;

View File

@@ -41,12 +41,12 @@ namespace DiscImageChef.Filters
/// </summary>
public class GZip : Filter
{
Stream dataStream;
string basePath;
DateTime lastWriteTime;
DateTime creationTime;
bool opened;
Stream dataStream;
uint decompressedSize;
DateTime lastWriteTime;
bool opened;
Stream zStream;
public GZip()

View File

@@ -42,13 +42,13 @@ namespace DiscImageChef.Filters
/// </summary>
public class LZip : Filter
{
Stream dataStream;
string basePath;
DateTime lastWriteTime;
DateTime creationTime;
bool opened;
Stream dataStream;
long decompressedSize;
Stream innerStream;
DateTime lastWriteTime;
bool opened;
public LZip()
{

View File

@@ -43,6 +43,238 @@ namespace DiscImageChef.Filters
/// </summary>
public class MacBinary : Filter
{
const uint MACBINARY_MAGIC = 0x6D42494E;
string basePath;
byte[] bytes;
DateTime creationTime;
long dataForkOff;
string filename;
MacBinaryHeader header;
bool isBytes, isStream, isPath, opened;
DateTime lastWriteTime;
long rsrcForkOff;
Stream stream;
public MacBinary()
{
Name = "MacBinary";
UUID = new Guid("D7C321D3-E51F-45DF-A150-F6BFDF0D7704");
}
public override void Close()
{
bytes = null;
stream?.Close();
isBytes = false;
isStream = false;
isPath = false;
opened = false;
}
public override string GetBasePath()
{
return basePath;
}
public override DateTime GetCreationTime()
{
return creationTime;
}
public override long GetDataForkLength()
{
return header.dataLength;
}
public override Stream GetDataForkStream()
{
if(header.dataLength == 0) return null;
if(isBytes) return new OffsetStream(bytes, dataForkOff, dataForkOff + header.dataLength - 1);
if(isStream) return new OffsetStream(stream, dataForkOff, dataForkOff + header.dataLength - 1);
if(isPath)
return new OffsetStream(basePath, FileMode.Open, FileAccess.Read, dataForkOff,
dataForkOff + header.dataLength - 1);
return null;
}
public override string GetFilename()
{
return filename;
}
public override DateTime GetLastWriteTime()
{
return lastWriteTime;
}
public override long GetLength()
{
return header.dataLength + header.resourceLength;
}
public override string GetParentFolder()
{
return Path.GetDirectoryName(basePath);
}
public override string GetPath()
{
return basePath;
}
public override long GetResourceForkLength()
{
return header.resourceLength;
}
public override Stream GetResourceForkStream()
{
if(header.resourceLength == 0) return null;
if(isBytes) return new OffsetStream(bytes, rsrcForkOff, rsrcForkOff + header.resourceLength - 1);
if(isStream) return new OffsetStream(stream, rsrcForkOff, rsrcForkOff + header.resourceLength - 1);
if(isPath)
return new OffsetStream(basePath, FileMode.Open, FileAccess.Read, rsrcForkOff,
rsrcForkOff + header.resourceLength - 1);
return null;
}
public override bool HasResourceFork()
{
return header.resourceLength > 0;
}
public override bool Identify(byte[] buffer)
{
if(buffer == null || buffer.Length < 128) return false;
byte[] hdr_b = new byte[128];
Array.Copy(buffer, 0, hdr_b, 0, 128);
header = BigEndianMarshal.ByteArrayToStructureBigEndian<MacBinaryHeader>(hdr_b);
return header.magic == MACBINARY_MAGIC || header.version == 0 && header.filename[0] > 0 &&
header.filename[0] < 64 && header.zero1 == 0 && header.zero2 == 0 && header.reserved == 0 &&
(header.dataLength > 0 || header.resourceLength > 0);
}
public override bool Identify(Stream stream)
{
if(stream == null || stream.Length < 128) return false;
byte[] hdr_b = new byte[128];
stream.Seek(0, SeekOrigin.Begin);
stream.Read(hdr_b, 0, 128);
header = BigEndianMarshal.ByteArrayToStructureBigEndian<MacBinaryHeader>(hdr_b);
return header.magic == MACBINARY_MAGIC || header.version == 0 && header.filename[0] > 0 &&
header.filename[0] < 64 && header.zero1 == 0 && header.zero2 == 0 && header.reserved == 0 &&
(header.dataLength > 0 || header.resourceLength > 0);
}
public override bool Identify(string path)
{
FileStream fstream = new FileStream(path, FileMode.Open, FileAccess.Read);
if(fstream.Length < 128) return false;
byte[] hdr_b = new byte[128];
fstream.Read(hdr_b, 0, 128);
header = BigEndianMarshal.ByteArrayToStructureBigEndian<MacBinaryHeader>(hdr_b);
fstream.Close();
return header.magic == MACBINARY_MAGIC || header.version == 0 && header.filename[0] > 0 &&
header.filename[0] < 64 && header.zero1 == 0 && header.zero2 == 0 && header.reserved == 0 &&
(header.dataLength > 0 || header.resourceLength > 0);
}
public override bool IsOpened()
{
return opened;
}
public override void Open(byte[] buffer)
{
MemoryStream ms = new MemoryStream(buffer);
ms.Seek(0, SeekOrigin.Begin);
byte[] hdr_b = new byte[128];
ms.Read(hdr_b, 0, 128);
header = BigEndianMarshal.ByteArrayToStructureBigEndian<MacBinaryHeader>(hdr_b);
uint blocks = 1;
blocks += (uint)(header.secondaryHeaderLength / 128);
if(header.secondaryHeaderLength % 128 > 0) blocks++;
dataForkOff = blocks * 128;
blocks += header.dataLength / 128;
if(header.dataLength % 128 > 0) blocks++;
rsrcForkOff = blocks * 128;
filename = StringHandlers.PascalToString(header.filename, Encoding.GetEncoding("macintosh"));
creationTime = DateHandlers.MacToDateTime(header.creationTime);
lastWriteTime = DateHandlers.MacToDateTime(header.modificationTime);
ms.Close();
opened = true;
isBytes = true;
bytes = buffer;
}
public override void Open(Stream stream)
{
stream.Seek(0, SeekOrigin.Begin);
byte[] hdr_b = new byte[128];
stream.Read(hdr_b, 0, 128);
header = BigEndianMarshal.ByteArrayToStructureBigEndian<MacBinaryHeader>(hdr_b);
uint blocks = 1;
blocks += (uint)(header.secondaryHeaderLength / 128);
if(header.secondaryHeaderLength % 128 > 0) blocks++;
dataForkOff = blocks * 128;
blocks += header.dataLength / 128;
if(header.dataLength % 128 > 0) blocks++;
rsrcForkOff = blocks * 128;
filename = StringHandlers.PascalToString(header.filename, Encoding.GetEncoding("macintosh"));
creationTime = DateHandlers.MacToDateTime(header.creationTime);
lastWriteTime = DateHandlers.MacToDateTime(header.modificationTime);
stream.Seek(0, SeekOrigin.Begin);
opened = true;
isStream = true;
this.stream = stream;
}
public override void Open(string path)
{
FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);
fs.Seek(0, SeekOrigin.Begin);
byte[] hdr_b = new byte[128];
fs.Read(hdr_b, 0, 128);
header = BigEndianMarshal.ByteArrayToStructureBigEndian<MacBinaryHeader>(hdr_b);
uint blocks = 1;
blocks += (uint)(header.secondaryHeaderLength / 128);
if(header.secondaryHeaderLength % 128 > 0) blocks++;
dataForkOff = blocks * 128;
blocks += header.dataLength / 128;
if(header.dataLength % 128 > 0) blocks++;
rsrcForkOff = blocks * 128;
filename = StringHandlers.PascalToString(header.filename, Encoding.GetEncoding("macintosh"));
creationTime = DateHandlers.MacToDateTime(header.creationTime);
lastWriteTime = DateHandlers.MacToDateTime(header.modificationTime);
fs.Close();
opened = true;
isPath = true;
basePath = path;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct MacBinaryHeader
{
@@ -163,240 +395,5 @@ namespace DiscImageChef.Filters
/// </summary>
public short computerID;
}
const uint MACBINARY_MAGIC = 0x6D42494E;
long dataForkOff;
long rsrcForkOff;
byte[] bytes;
Stream stream;
bool isBytes, isStream, isPath, opened;
string basePath;
DateTime lastWriteTime;
DateTime creationTime;
MacBinaryHeader header;
string filename;
public MacBinary()
{
Name = "MacBinary";
UUID = new Guid("D7C321D3-E51F-45DF-A150-F6BFDF0D7704");
}
public override void Close()
{
bytes = null;
stream?.Close();
isBytes = false;
isStream = false;
isPath = false;
opened = false;
}
public override string GetBasePath()
{
return basePath;
}
public override DateTime GetCreationTime()
{
return creationTime;
}
public override long GetDataForkLength()
{
return header.dataLength;
}
public override Stream GetDataForkStream()
{
if(header.dataLength == 0) return null;
if(isBytes) return new OffsetStream(bytes, dataForkOff, dataForkOff + header.dataLength - 1);
if(isStream) return new OffsetStream(stream, dataForkOff, dataForkOff + header.dataLength - 1);
if(isPath)
return new OffsetStream(basePath, FileMode.Open, FileAccess.Read, dataForkOff,
dataForkOff + header.dataLength - 1);
return null;
}
public override string GetFilename()
{
return filename;
}
public override DateTime GetLastWriteTime()
{
return lastWriteTime;
}
public override long GetLength()
{
return header.dataLength + header.resourceLength;
}
public override string GetParentFolder()
{
return Path.GetDirectoryName(basePath);
}
public override string GetPath()
{
return basePath;
}
public override long GetResourceForkLength()
{
return header.resourceLength;
}
public override Stream GetResourceForkStream()
{
if(header.resourceLength == 0) return null;
if(isBytes) return new OffsetStream(bytes, rsrcForkOff, rsrcForkOff + header.resourceLength - 1);
if(isStream) return new OffsetStream(stream, rsrcForkOff, rsrcForkOff + header.resourceLength - 1);
if(isPath)
return new OffsetStream(basePath, FileMode.Open, FileAccess.Read, rsrcForkOff,
rsrcForkOff + header.resourceLength - 1);
return null;
}
public override bool HasResourceFork()
{
return header.resourceLength > 0;
}
public override bool Identify(byte[] buffer)
{
if(buffer == null || buffer.Length < 128) return false;
byte[] hdr_b = new byte[128];
Array.Copy(buffer, 0, hdr_b, 0, 128);
header = BigEndianMarshal.ByteArrayToStructureBigEndian<MacBinaryHeader>(hdr_b);
return header.magic == MACBINARY_MAGIC || header.version == 0 && header.filename[0] > 0 &&
header.filename[0] < 64 && header.zero1 == 0 &&
header.zero2 == 0 && header.reserved == 0 &&
(header.dataLength > 0 || header.resourceLength > 0);
}
public override bool Identify(Stream stream)
{
if(stream == null || stream.Length < 128) return false;
byte[] hdr_b = new byte[128];
stream.Seek(0, SeekOrigin.Begin);
stream.Read(hdr_b, 0, 128);
header = BigEndianMarshal.ByteArrayToStructureBigEndian<MacBinaryHeader>(hdr_b);
return header.magic == MACBINARY_MAGIC || header.version == 0 && header.filename[0] > 0 &&
header.filename[0] < 64 && header.zero1 == 0 &&
header.zero2 == 0 && header.reserved == 0 &&
(header.dataLength > 0 || header.resourceLength > 0);
}
public override bool Identify(string path)
{
FileStream fstream = new FileStream(path, FileMode.Open, FileAccess.Read);
if(fstream.Length < 128) return false;
byte[] hdr_b = new byte[128];
fstream.Read(hdr_b, 0, 128);
header = BigEndianMarshal.ByteArrayToStructureBigEndian<MacBinaryHeader>(hdr_b);
fstream.Close();
return header.magic == MACBINARY_MAGIC || header.version == 0 && header.filename[0] > 0 &&
header.filename[0] < 64 && header.zero1 == 0 &&
header.zero2 == 0 && header.reserved == 0 &&
(header.dataLength > 0 || header.resourceLength > 0);
}
public override bool IsOpened()
{
return opened;
}
public override void Open(byte[] buffer)
{
MemoryStream ms = new MemoryStream(buffer);
ms.Seek(0, SeekOrigin.Begin);
byte[] hdr_b = new byte[128];
ms.Read(hdr_b, 0, 128);
header = BigEndianMarshal.ByteArrayToStructureBigEndian<MacBinaryHeader>(hdr_b);
uint blocks = 1;
blocks += (uint)(header.secondaryHeaderLength / 128);
if(header.secondaryHeaderLength % 128 > 0) blocks++;
dataForkOff = blocks * 128;
blocks += header.dataLength / 128;
if(header.dataLength % 128 > 0) blocks++;
rsrcForkOff = blocks * 128;
filename = StringHandlers.PascalToString(header.filename, Encoding.GetEncoding("macintosh"));
creationTime = DateHandlers.MacToDateTime(header.creationTime);
lastWriteTime = DateHandlers.MacToDateTime(header.modificationTime);
ms.Close();
opened = true;
isBytes = true;
bytes = buffer;
}
public override void Open(Stream stream)
{
stream.Seek(0, SeekOrigin.Begin);
byte[] hdr_b = new byte[128];
stream.Read(hdr_b, 0, 128);
header = BigEndianMarshal.ByteArrayToStructureBigEndian<MacBinaryHeader>(hdr_b);
uint blocks = 1;
blocks += (uint)(header.secondaryHeaderLength / 128);
if(header.secondaryHeaderLength % 128 > 0) blocks++;
dataForkOff = blocks * 128;
blocks += header.dataLength / 128;
if(header.dataLength % 128 > 0) blocks++;
rsrcForkOff = blocks * 128;
filename = StringHandlers.PascalToString(header.filename, Encoding.GetEncoding("macintosh"));
creationTime = DateHandlers.MacToDateTime(header.creationTime);
lastWriteTime = DateHandlers.MacToDateTime(header.modificationTime);
stream.Seek(0, SeekOrigin.Begin);
opened = true;
isStream = true;
this.stream = stream;
}
public override void Open(string path)
{
FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);
fs.Seek(0, SeekOrigin.Begin);
byte[] hdr_b = new byte[128];
fs.Read(hdr_b, 0, 128);
header = BigEndianMarshal.ByteArrayToStructureBigEndian<MacBinaryHeader>(hdr_b);
uint blocks = 1;
blocks += (uint)(header.secondaryHeaderLength / 128);
if(header.secondaryHeaderLength % 128 > 0) blocks++;
dataForkOff = blocks * 128;
blocks += header.dataLength / 128;
if(header.dataLength % 128 > 0) blocks++;
rsrcForkOff = blocks * 128;
filename = StringHandlers.PascalToString(header.filename, Encoding.GetEncoding("macintosh"));
creationTime = DateHandlers.MacToDateTime(header.creationTime);
lastWriteTime = DateHandlers.MacToDateTime(header.modificationTime);
fs.Close();
opened = true;
isPath = true;
basePath = path;
}
}
}

View File

@@ -43,8 +43,8 @@ namespace DiscImageChef.Filters
public class OffsetStream : Stream
{
readonly Stream baseStream;
readonly long streamStart;
readonly long streamEnd;
readonly long streamStart;
public OffsetStream(Stream stream, long start, long end)
{
@@ -291,12 +291,6 @@ namespace DiscImageChef.Filters
if(end > baseStream.Length) throw new ArgumentOutOfRangeException(nameof(end), "End is after stream end.");
}
~OffsetStream()
{
baseStream.Close();
baseStream.Dispose();
}
public override bool CanRead => baseStream.CanRead;
public override bool CanSeek => baseStream.CanSeek;
@@ -317,6 +311,12 @@ namespace DiscImageChef.Filters
}
}
~OffsetStream()
{
baseStream.Close();
baseStream.Dispose();
}
public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback,
object state)
{

View File

@@ -47,75 +47,15 @@ namespace DiscImageChef.Filters
const string FILE_ID = "FILEID.DAT";
const string FINDER_INFO = "FINDER.DAT";
const string RESOURCES = "RESOURCE.FRK";
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct PCExchangeEntry
{
/// <summary>
/// Name in Macintosh. If PCExchange version supports FAT's LFN they are the same.
/// Illegal characters for FAT get substituted with '_' both here and in FAT's LFN entry.
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public byte[] macName;
/// <summary>
/// File type
/// </summary>
public uint type;
/// <summary>
/// File creator
/// </summary>
public uint creator;
/// <summary>
/// Finder flags
/// </summary>
public ushort fdFlags;
/// <summary>
/// File's icon vertical position within its window
/// </summary>
public ushort verticalPosition;
/// <summary>
/// File's icon horizontal position within its window
/// </summary>
public ushort horizontalPosition;
/// <summary>
/// Unknown, all bytes are empty but last, except in volume's label entry
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 18)] public byte[] unknown1;
/// <summary>
/// File's creation date
/// </summary>
public uint creationDate;
/// <summary>
/// File's modification date
/// </summary>
public uint modificationDate;
/// <summary>
/// File's last backup date
/// </summary>
public uint backupDate;
/// <summary>
/// Unknown, but is unique, starts 0x7FFFFFFF and counts in reverse.
/// Probably file ID for alias look up?
/// </summary>
public uint unknown2;
/// <summary>
/// Name as in FAT entry (not LFN).
/// Resource fork file is always using this name, never LFN.
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] public byte[] dosName;
/// <summary>
/// Unknown, flags?
/// </summary>
public byte unknown3;
}
bool opened;
string basePath;
string dataPath;
string rsrcPath;
DateTime lastWriteTime;
DateTime creationTime;
long dataLen;
string dataPath;
DateTime lastWriteTime;
bool opened;
long rsrcLen;
string rsrcPath;
public PCExchange()
{
@@ -203,7 +143,8 @@ namespace DiscImageChef.Filters
{
string parentFolder = Path.GetDirectoryName(path);
if(!File.Exists(Path.Combine(parentFolder ?? throw new InvalidOperationException(), FINDER_INFO))) return false;
if(!File.Exists(Path.Combine(parentFolder ?? throw new InvalidOperationException(), FINDER_INFO)))
return false;
if(!Directory.Exists(Path.Combine(parentFolder, RESOURCES))) return false;
@@ -233,7 +174,8 @@ namespace DiscImageChef.Filters
if(baseFilename != macName && baseFilename != dosName && baseFilename != dosNameLow) continue;
dataFound |= File.Exists(Path.Combine(parentFolder, macName ?? throw new InvalidOperationException())) ||
dataFound |=
File.Exists(Path.Combine(parentFolder, macName ?? throw new InvalidOperationException())) ||
File.Exists(Path.Combine(parentFolder, dosName)) ||
File.Exists(Path.Combine(parentFolder, dosNameLow));
@@ -269,7 +211,8 @@ namespace DiscImageChef.Filters
string baseFilename = Path.GetFileName(path);
FileStream finderDatStream =
new FileStream(Path.Combine(parentFolder ?? throw new InvalidOperationException(), FINDER_INFO), FileMode.Open, FileAccess.Read);
new FileStream(Path.Combine(parentFolder ?? throw new InvalidOperationException(), FINDER_INFO),
FileMode.Open, FileAccess.Read);
while(finderDatStream.Position + 0x5C <= finderDatStream.Length)
{
@@ -288,7 +231,8 @@ namespace DiscImageChef.Filters
if(baseFilename != macName && baseFilename != dosName && baseFilename != dosNameLow) continue;
if(File.Exists(Path.Combine(parentFolder, macName ?? throw new InvalidOperationException()))) dataPath = Path.Combine(parentFolder, macName);
if(File.Exists(Path.Combine(parentFolder, macName ?? throw new InvalidOperationException())))
dataPath = Path.Combine(parentFolder, macName);
else if(File.Exists(Path.Combine(parentFolder, dosName)))
dataPath = Path.Combine(parentFolder, dosName);
else if(File.Exists(Path.Combine(parentFolder, dosNameLow)))
@@ -315,5 +259,65 @@ namespace DiscImageChef.Filters
finderDatStream.Close();
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct PCExchangeEntry
{
/// <summary>
/// Name in Macintosh. If PCExchange version supports FAT's LFN they are the same.
/// Illegal characters for FAT get substituted with '_' both here and in FAT's LFN entry.
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public byte[] macName;
/// <summary>
/// File type
/// </summary>
public uint type;
/// <summary>
/// File creator
/// </summary>
public uint creator;
/// <summary>
/// Finder flags
/// </summary>
public ushort fdFlags;
/// <summary>
/// File's icon vertical position within its window
/// </summary>
public ushort verticalPosition;
/// <summary>
/// File's icon horizontal position within its window
/// </summary>
public ushort horizontalPosition;
/// <summary>
/// Unknown, all bytes are empty but last, except in volume's label entry
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 18)] public byte[] unknown1;
/// <summary>
/// File's creation date
/// </summary>
public uint creationDate;
/// <summary>
/// File's modification date
/// </summary>
public uint modificationDate;
/// <summary>
/// File's last backup date
/// </summary>
public uint backupDate;
/// <summary>
/// Unknown, but is unique, starts 0x7FFFFFFF and counts in reverse.
/// Probably file ID for alias look up?
/// </summary>
public uint unknown2;
/// <summary>
/// Name as in FAT entry (not LFN).
/// Resource fork file is always using this name, never LFN.
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] public byte[] dosName;
/// <summary>
/// Unknown, flags?
/// </summary>
public byte unknown3;
}
}
}

View File

@@ -41,13 +41,13 @@ namespace DiscImageChef.Filters
/// </summary>
public class XZ : Filter
{
Stream dataStream;
string basePath;
DateTime lastWriteTime;
DateTime creationTime;
bool opened;
Stream dataStream;
long decompressedSize;
Stream innerStream;
DateTime lastWriteTime;
bool opened;
public XZ()
{
@@ -242,7 +242,10 @@ namespace DiscImageChef.Filters
{
if(basePath?.EndsWith(".xz", StringComparison.InvariantCultureIgnoreCase) == true)
return basePath.Substring(0, basePath.Length - 3);
return basePath?.EndsWith(".xzip", StringComparison.InvariantCultureIgnoreCase) == true ? basePath.Substring(0, basePath.Length - 5) : basePath;
return basePath?.EndsWith(".xzip", StringComparison.InvariantCultureIgnoreCase) == true
? basePath.Substring(0, basePath.Length - 5)
: basePath;
}
public override string GetParentFolder()

View File

@@ -40,10 +40,10 @@ namespace DiscImageChef.Filters
/// </summary>
public class ZZZNoFilter : Filter
{
Stream dataStream;
string basePath;
DateTime lastWriteTime;
DateTime creationTime;
Stream dataStream;
DateTime lastWriteTime;
bool opened;
public ZZZNoFilter()