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

@@ -38,117 +38,35 @@ using System.Runtime.InteropServices;
namespace DiscImageChef.Filters namespace DiscImageChef.Filters
{ {
/// <summary> /// <summary>
/// Decodes AppleDouble files /// Decodes AppleDouble files
/// </summary> /// </summary>
public class AppleDouble : Filter 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 AppleDoubleMagic = 0x00051607;
const uint AppleDoubleVersion = 0x00010000; const uint AppleDoubleVersion = 0x00010000;
const uint AppleDoubleVersion2 = 0x00020000; 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 = readonly byte[] MacintoshHome =
{0x4D, 0x61, 0x63, 0x69, 0x6E, 0x74, 0x6F, 0x73, 0x68, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20}; {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 = readonly byte[] ProDOSHome =
{0x50, 0x72, 0x6F, 0x44, 0x4F, 0x53, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20}; {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 = readonly byte[] UNIXHome =
{0x55, 0x6E, 0x69, 0x78, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20}; {0x55, 0x6E, 0x69, 0x78, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20};
readonly byte[] VMXHome = readonly byte[] VMXHome =
{0x56, 0x41, 0x58, 0x20, 0x56, 0x4D, 0x53, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20}; {0x56, 0x41, 0x58, 0x20, 0x56, 0x4D, 0x53, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20};
readonly byte[] OSXHome = string basePath;
{0x4D, 0x61, 0x63, 0x20, 0x4F, 0x53, 0x20, 0x58, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20}; DateTime creationTime;
AppleDoubleEntry dataFork; AppleDoubleEntry dataFork;
AppleDoubleEntry rsrcFork; AppleDoubleHeader header;
bool opened;
string basePath;
string headerPath; string headerPath;
DateTime lastWriteTime; DateTime lastWriteTime;
DateTime creationTime; bool opened;
AppleDoubleHeader header; AppleDoubleEntry rsrcFork;
public AppleDouble() public AppleDouble()
{ {
@@ -263,7 +181,8 @@ namespace DiscImageChef.Filters
UNIXAppleDouble = Path.Combine(parentFolder, "%" + filename); UNIXAppleDouble = Path.Combine(parentFolder, "%" + filename);
DOSAppleDouble = Path.Combine(parentFolder, filenameNoExt + ".ADF"); DOSAppleDouble = Path.Combine(parentFolder, filenameNoExt + ".ADF");
DOSAppleDoubleLower = 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); DAVEAppleDouble = Path.Combine(parentFolder, "resource.frk", filename);
OSXAppleDouble = Path.Combine(parentFolder, "._" + filename); OSXAppleDouble = Path.Combine(parentFolder, "._" + filename);
UnArAppleDouble = Path.Combine(parentFolder, filename + ".rsrc"); UnArAppleDouble = Path.Combine(parentFolder, filename + ".rsrc");
@@ -431,7 +350,8 @@ namespace DiscImageChef.Filters
UNIXAppleDouble = Path.Combine(parentFolder, "%" + filename); UNIXAppleDouble = Path.Combine(parentFolder, "%" + filename);
DOSAppleDouble = Path.Combine(parentFolder, filenameNoExt + ".ADF"); DOSAppleDouble = Path.Combine(parentFolder, filenameNoExt + ".ADF");
DOSAppleDoubleLower = 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); DAVEAppleDouble = Path.Combine(parentFolder, "resource.frk", filename);
OSXAppleDouble = Path.Combine(parentFolder, "._" + filename); OSXAppleDouble = Path.Combine(parentFolder, "._" + filename);
UnArAppleDouble = Path.Combine(parentFolder, filename + ".rsrc"); UnArAppleDouble = Path.Combine(parentFolder, filename + ".rsrc");
@@ -646,5 +566,87 @@ namespace DiscImageChef.Filters
opened = true; opened = true;
basePath = path; 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

@@ -38,118 +38,36 @@ using System.Runtime.InteropServices;
namespace DiscImageChef.Filters namespace DiscImageChef.Filters
{ {
/// <summary> /// <summary>
/// Decodes AppleSingle files /// Decodes AppleSingle files
/// </summary> /// </summary>
public class AppleSingle : Filter 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 AppleSingleMagic = 0x00051600;
const uint AppleSingleVersion = 0x00010000; const uint AppleSingleVersion = 0x00010000;
const uint AppleSingleVersion2 = 0x00020000; 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 = readonly byte[] MacintoshHome =
{0x4D, 0x61, 0x63, 0x69, 0x6E, 0x74, 0x6F, 0x73, 0x68, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20}; {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 = readonly byte[] ProDOSHome =
{0x50, 0x72, 0x6F, 0x44, 0x4F, 0x53, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20}; {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 = readonly byte[] UNIXHome =
{0x55, 0x6E, 0x69, 0x78, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20}; {0x55, 0x6E, 0x69, 0x78, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20};
readonly byte[] VMSHome = readonly byte[] VMSHome =
{0x56, 0x41, 0x58, 0x20, 0x56, 0x4D, 0x53, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20}; {0x56, 0x41, 0x58, 0x20, 0x56, 0x4D, 0x53, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20};
readonly byte[] OSXHome = string basePath;
{0x4D, 0x61, 0x63, 0x20, 0x4F, 0x53, 0x20, 0x58, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20}; byte[] bytes;
DateTime creationTime;
AppleSingleEntry dataFork; AppleSingleEntry dataFork;
AppleSingleEntry rsrcFork;
byte[] bytes;
Stream stream;
bool isBytes, isStream, isPath, opened;
string basePath;
DateTime lastWriteTime;
DateTime creationTime;
AppleSingleHeader header; AppleSingleHeader header;
bool isBytes, isStream, isPath, opened;
DateTime lastWriteTime;
AppleSingleEntry rsrcFork;
Stream stream;
public AppleSingle() public AppleSingle()
{ {
@@ -519,5 +437,87 @@ namespace DiscImageChef.Filters
isPath = true; isPath = true;
basePath = path; 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

@@ -38,17 +38,17 @@ using SharpCompress.Compressors.BZip2;
namespace DiscImageChef.Filters namespace DiscImageChef.Filters
{ {
/// <summary> /// <summary>
/// Decompress bz2 files while reading /// Decompress bz2 files while reading
/// </summary> /// </summary>
public class BZip2 : Filter public class BZip2 : Filter
{ {
Stream dataStream;
string basePath; string basePath;
DateTime lastWriteTime;
DateTime creationTime; DateTime creationTime;
bool opened; Stream dataStream;
long decompressedSize; long decompressedSize;
Stream innerStream; Stream innerStream;
DateTime lastWriteTime;
bool opened;
public BZip2() public BZip2()
{ {
@@ -96,7 +96,8 @@ namespace DiscImageChef.Filters
if(buffer.Length <= 512) return true; 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) public override bool Identify(Stream stream)
@@ -139,8 +140,7 @@ namespace DiscImageChef.Filters
stream.Read(buffer, 0, 4); stream.Read(buffer, 0, 4);
stream.Seek(0, SeekOrigin.Begin); stream.Seek(0, SeekOrigin.Begin);
// Check it is not an UDIF // Check it is not an UDIF
if(buffer[0] == 0x6B && buffer[1] == 0x6F && buffer[2] == 0x6C && buffer[3] == 0x79) if(buffer[0] == 0x6B && buffer[1] == 0x6F && buffer[2] == 0x6C && buffer[3] == 0x79) return false;
return false;
return true; return true;
} }

View File

@@ -41,126 +41,127 @@ namespace DiscImageChef.Filters
public Guid UUID; public Guid UUID;
/// <summary> /// <summary>
/// Closes all opened streams. /// Closes all opened streams.
/// </summary> /// </summary>
public abstract void Close(); public abstract void Close();
/// <summary> /// <summary>
/// Gets the path used to open this filter.<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/> /// 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 /// Windows: C:\path\to\archive.zip\path\to\file.bin => C:\path\to\archive.zip\path\to\file.bin
/// </summary> /// </summary>
/// <returns>Path used to open this filter.</returns> /// <returns>Path used to open this filter.</returns>
public abstract string GetBasePath(); public abstract string GetBasePath();
/// <summary> /// <summary>
/// Gets creation time of file referenced by this filter. /// Gets creation time of file referenced by this filter.
/// </summary> /// </summary>
/// <returns>The creation time.</returns> /// <returns>The creation time.</returns>
public abstract DateTime GetCreationTime(); public abstract DateTime GetCreationTime();
/// <summary> /// <summary>
/// Gets length of this filter's data fork. /// Gets length of this filter's data fork.
/// </summary> /// </summary>
/// <returns>The data fork length.</returns> /// <returns>The data fork length.</returns>
public abstract long GetDataForkLength(); public abstract long GetDataForkLength();
/// <summary> /// <summary>
/// Gets a stream to access the data fork contents. /// Gets a stream to access the data fork contents.
/// </summary> /// </summary>
/// <returns>The data fork stream.</returns> /// <returns>The data fork stream.</returns>
public abstract Stream GetDataForkStream(); public abstract Stream GetDataForkStream();
/// <summary> /// <summary>
/// Gets the filename for the file referenced by this filter.<br/> /// Gets the filename for the file referenced by this filter.<br />
/// UNIX: /path/to/archive.zip/path/to/file.bin => file.bin <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 /// Windows: C:\path\to\archive.zip\path\to\file.bin => file.bin
/// </summary> /// </summary>
/// <returns>The filename.</returns> /// <returns>The filename.</returns>
public abstract string GetFilename(); public abstract string GetFilename();
/// <summary> /// <summary>
/// Gets last write time of file referenced by this filter. /// Gets last write time of file referenced by this filter.
/// </summary> /// </summary>
/// <returns>The last write time.</returns> /// <returns>The last write time.</returns>
public abstract DateTime GetLastWriteTime(); public abstract DateTime GetLastWriteTime();
/// <summary> /// <summary>
/// Gets length of file referenced by ths filter. /// Gets length of file referenced by ths filter.
/// </summary> /// </summary>
/// <returns>The length.</returns> /// <returns>The length.</returns>
public abstract long GetLength(); public abstract long GetLength();
/// <summary> /// <summary>
/// Gets full path to file referenced by this filter. If it's an archive, it's the path inside the archive.<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/> /// 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 /// Windows: C:\path\to\archive.zip\path\to\file.bin => \path\to\file.bin
/// </summary> /// </summary>
/// <returns>The path.</returns> /// <returns>The path.</returns>
public abstract string GetPath(); public abstract string GetPath();
/// <summary> /// <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/> /// Gets path to parent folder to the file referenced by this filter. If it's an archive, it's the full path to the
/// UNIX: /path/to/archive.zip/path/to/file.bin => /path/to/archive.zip <br/> /// archive itself.<br />
/// Windows: C:\path\to\archive.zip\path\to\file.bin => C:\path\to\archive.zip /// 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> /// </summary>
/// <returns>The parent folder.</returns> /// <returns>The parent folder.</returns>
public abstract string GetParentFolder(); public abstract string GetParentFolder();
/// <summary> /// <summary>
/// Gets length of this filter's resource fork. /// Gets length of this filter's resource fork.
/// </summary> /// </summary>
/// <returns>The resource fork length.</returns> /// <returns>The resource fork length.</returns>
public abstract long GetResourceForkLength(); public abstract long GetResourceForkLength();
/// <summary> /// <summary>
/// Gets a stream to access the resource fork contents. /// Gets a stream to access the resource fork contents.
/// </summary> /// </summary>
/// <returns>The resource fork stream.</returns> /// <returns>The resource fork stream.</returns>
public abstract Stream GetResourceForkStream(); public abstract Stream GetResourceForkStream();
/// <summary> /// <summary>
/// Returns true if the file referenced by this filter has a resource fork /// Returns true if the file referenced by this filter has a resource fork
/// </summary> /// </summary>
public abstract bool HasResourceFork(); public abstract bool HasResourceFork();
/// <summary> /// <summary>
/// Identifies if the specified path contains data recognizable by this filter instance /// Identifies if the specified path contains data recognizable by this filter instance
/// </summary> /// </summary>
/// <param name="path">Path.</param> /// <param name="path">Path.</param>
public abstract bool Identify(string path); public abstract bool Identify(string path);
/// <summary> /// <summary>
/// Identifies if the specified stream contains data recognizable by this filter instance /// Identifies if the specified stream contains data recognizable by this filter instance
/// </summary> /// </summary>
/// <param name="stream">Stream.</param> /// <param name="stream">Stream.</param>
public abstract bool Identify(Stream stream); public abstract bool Identify(Stream stream);
/// <summary> /// <summary>
/// Identifies if the specified buffer contains data recognizable by this filter instance /// Identifies if the specified buffer contains data recognizable by this filter instance
/// </summary> /// </summary>
/// <param name="buffer">Buffer.</param> /// <param name="buffer">Buffer.</param>
public abstract bool Identify(byte[] buffer); public abstract bool Identify(byte[] buffer);
/// <summary> /// <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> /// </summary>
public abstract bool IsOpened(); public abstract bool IsOpened();
/// <summary> /// <summary>
/// Opens the specified path with this filter instance /// Opens the specified path with this filter instance
/// </summary> /// </summary>
/// <param name="path">Path.</param> /// <param name="path">Path.</param>
public abstract void Open(string path); public abstract void Open(string path);
/// <summary> /// <summary>
/// Opens the specified stream with this filter instance /// Opens the specified stream with this filter instance
/// </summary> /// </summary>
/// <param name="stream">Stream.</param> /// <param name="stream">Stream.</param>
public abstract void Open(Stream stream); public abstract void Open(Stream stream);
/// <summary> /// <summary>
/// Opens the specified buffer with this filter instance /// Opens the specified buffer with this filter instance
/// </summary> /// </summary>
/// <param name="buffer">Buffer.</param> /// <param name="buffer">Buffer.</param>
public abstract void Open(byte[] buffer); public abstract void Open(byte[] buffer);

View File

@@ -42,7 +42,7 @@ namespace DiscImageChef.Filters
public SortedDictionary<string, Filter> Filters; public SortedDictionary<string, Filter> Filters;
/// <summary> /// <summary>
/// Fills the list of all known filters /// Fills the list of all known filters
/// </summary> /// </summary>
public FiltersList() public FiltersList()
{ {
@@ -55,13 +55,14 @@ namespace DiscImageChef.Filters
if(!type.IsSubclassOf(typeof(Filter))) continue; if(!type.IsSubclassOf(typeof(Filter))) continue;
Filter filter = (Filter)type.GetConstructor(Type.EmptyTypes)?.Invoke(new object[] { }); 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); } catch(Exception exception) { DicConsole.ErrorWriteLine("Exception {0}", exception); }
} }
/// <summary> /// <summary>
/// Gets the filter that allows to read the specified path /// Gets the filter that allows to read the specified path
/// </summary> /// </summary>
/// <param name="path">Path</param> /// <param name="path">Path</param>
/// <returns>The filter that allows reading the specified path</returns> /// <returns>The filter that allows reading the specified path</returns>
@@ -91,7 +92,7 @@ namespace DiscImageChef.Filters
} }
/// <summary> /// <summary>
/// Gets all known filters /// Gets all known filters
/// </summary> /// </summary>
/// <returns>Known filters</returns> /// <returns>Known filters</returns>
public SortedDictionary<string, Filter> GetFiltersList() public SortedDictionary<string, Filter> GetFiltersList()

View File

@@ -36,19 +36,19 @@ using System.IO;
namespace DiscImageChef.Filters namespace DiscImageChef.Filters
{ {
/// <summary> /// <summary>
/// ForcedSeekStream allows to seek a forward-readable stream (like System.IO.Compression streams) /// ForcedSeekStream allows to seek a forward-readable stream (like System.IO.Compression streams)
/// by doing the slow and known trick of rewinding and forward reading until arriving the desired position. /// by doing the slow and known trick of rewinding and forward reading until arriving the desired position.
/// </summary> /// </summary>
public class ForcedSeekStream<T> : Stream where T : Stream public class ForcedSeekStream<T> : Stream where T : Stream
{ {
const int BUFFER_LEN = 1048576;
string backFile;
FileStream backStream;
T baseStream; T baseStream;
long streamLength; long streamLength;
const int BUFFER_LEN = 1048576;
FileStream backStream;
string backFile;
/// <summary> /// <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> /// </summary>
/// <param name="length">The real (uncompressed) length of the stream.</param> /// <param name="length">The real (uncompressed) length of the stream.</param>
/// <param name="args">Parameters that are used to create the base stream.</param> /// <param name="args">Parameters that are used to create the base stream.</param>
@@ -62,7 +62,7 @@ namespace DiscImageChef.Filters
} }
/// <summary> /// <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> /// </summary>
/// <param name="args">Parameters that are used to create the base stream.</param> /// <param name="args">Parameters that are used to create the base stream.</param>
public ForcedSeekStream(params object[] args) public ForcedSeekStream(params object[] args)
@@ -73,27 +73,6 @@ namespace DiscImageChef.Filters
CalculateLength(); CalculateLength();
} }
/// <summary>
/// Calculates the real (uncompressed) length of the stream.
/// It basically reads (uncompresses) the whole stream to memory discarding its contents,
/// so it should be used as a last resort.
/// </summary>
/// <returns>The length.</returns>
public void CalculateLength()
{
int read;
do
{
byte[] buffer = new byte[BUFFER_LEN];
read = baseStream.Read(buffer, 0, BUFFER_LEN);
backStream.Write(buffer, 0, read);
}
while(read == BUFFER_LEN);
streamLength = backStream.Length;
backStream.Position = 0;
}
public override bool CanRead => baseStream.CanRead; public override bool CanRead => baseStream.CanRead;
public override bool CanSeek => true; public override bool CanSeek => true;
@@ -109,6 +88,27 @@ namespace DiscImageChef.Filters
set => SetPosition(value); set => SetPosition(value);
} }
/// <summary>
/// Calculates the real (uncompressed) length of the stream.
/// It basically reads (uncompresses) the whole stream to memory discarding its contents,
/// so it should be used as a last resort.
/// </summary>
/// <returns>The length.</returns>
public void CalculateLength()
{
int read;
do
{
byte[] buffer = new byte[BUFFER_LEN];
read = baseStream.Read(buffer, 0, BUFFER_LEN);
backStream.Write(buffer, 0, read);
}
while(read == BUFFER_LEN);
streamLength = backStream.Length;
backStream.Position = 0;
}
void SetPosition(long position) void SetPosition(long position)
{ {
if(position == backStream.Position) return; if(position == backStream.Position) return;

View File

@@ -37,16 +37,16 @@ using System.IO.Compression;
namespace DiscImageChef.Filters namespace DiscImageChef.Filters
{ {
/// <summary> /// <summary>
/// Decompress gzip files while reading /// Decompress gzip files while reading
/// </summary> /// </summary>
public class GZip : Filter public class GZip : Filter
{ {
Stream dataStream;
string basePath; string basePath;
DateTime lastWriteTime;
DateTime creationTime; DateTime creationTime;
bool opened; Stream dataStream;
uint decompressedSize; uint decompressedSize;
DateTime lastWriteTime;
bool opened;
Stream zStream; Stream zStream;
public GZip() public GZip()

View File

@@ -38,17 +38,17 @@ using SharpCompress.Compressors.LZMA;
namespace DiscImageChef.Filters namespace DiscImageChef.Filters
{ {
/// <summary> /// <summary>
/// Decompress lzip files while reading /// Decompress lzip files while reading
/// </summary> /// </summary>
public class LZip : Filter public class LZip : Filter
{ {
Stream dataStream;
string basePath; string basePath;
DateTime lastWriteTime;
DateTime creationTime; DateTime creationTime;
bool opened; Stream dataStream;
long decompressedSize; long decompressedSize;
Stream innerStream; Stream innerStream;
DateTime lastWriteTime;
bool opened;
public LZip() public LZip()
{ {

View File

@@ -39,143 +39,22 @@ namespace DiscImageChef.Filters
{ {
// TODO: Interpret fdScript // TODO: Interpret fdScript
/// <summary> /// <summary>
/// Decodes MacBinary files /// Decodes MacBinary files
/// </summary> /// </summary>
public class MacBinary : Filter public class MacBinary : Filter
{ {
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct MacBinaryHeader
{
/// <summary>
/// 0x00, MacBinary version, 0
/// </summary>
public byte version;
/// <summary>
/// 0x01, Str63 Pascal filename
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)] public byte[] filename;
/// <summary>
/// 0x41, File type
/// </summary>
public uint type;
/// <summary>
/// 0x45, File creator
/// </summary>
public uint creator;
/// <summary>
/// 0x49, High byte of Finder flags
/// </summary>
public byte finderFlags;
/// <summary>
/// 0x4A, Must be 0
/// </summary>
public byte zero1;
/// <summary>
/// 0x4B, File's icon vertical position within its window
/// </summary>
public ushort verticalPosition;
/// <summary>
/// 0x4D, File's icon horizontal position within its window
/// </summary>
public ushort horizontalPosition;
/// <summary>
/// 0x4F, File's window or folder ID
/// </summary>
public short windowID;
/// <summary>
/// 0x51, Protected flag
/// </summary>
public byte protect;
/// <summary>
/// 0x52, Must be 0
/// </summary>
public byte zero2;
/// <summary>
/// 0x53, Size of data fork
/// </summary>
public uint dataLength;
/// <summary>
/// 0x57, Size of resource fork
/// </summary>
public uint resourceLength;
/// <summary>
/// 0x5B, File's creation time
/// </summary>
public uint creationTime;
/// <summary>
/// 0x5F, File's last modified time
/// </summary>
public uint modificationTime;
/// <summary>
/// 0x63, Length of Get Info comment
/// </summary>
public ushort commentLength;
/// <summary>
/// 0x65, Low byte of Finder flags
/// </summary>
public byte finderFlags2;
#region MacBinary III
/// <summary>
/// 0x66, magic identifier, "mBIN"
/// </summary>
public uint magic;
/// <summary>
/// 0x6A, fdScript from fxInfo, identifies codepage of filename
/// </summary>
public byte fdScript;
/// <summary>
/// 0x6B, fdXFlags from fxInfo, extended Mac OS 8 finder flags
/// </summary>
public byte fdXFlags;
#endregion MacBinary III
/// <summary>
/// 0x6C, unused
/// </summary>
public ulong reserved;
/// <summary>
/// 0x74, Total unpacked files
/// </summary>
public uint totalPackedFiles;
#region MacBinary II
/// <summary>
/// 0x78, Length of secondary header
/// </summary>
public ushort secondaryHeaderLength;
/// <summary>
/// 0x7A, version number of MacBinary that wrote this file, starts at 129
/// </summary>
public byte version2;
/// <summary>
/// 0x7B, version number of MacBinary required to open this file, starts at 129
/// </summary>
public byte minVersion;
/// <summary>
/// 0x7C, CRC of previous bytes
/// </summary>
public short crc;
#endregion MacBinary II
/// <summary>
/// 0x7E, Reserved for computer type and OS ID
/// </summary>
public short computerID;
}
const uint MACBINARY_MAGIC = 0x6D42494E; const uint MACBINARY_MAGIC = 0x6D42494E;
string basePath;
byte[] bytes;
DateTime creationTime;
long dataForkOff; long dataForkOff;
long rsrcForkOff;
byte[] bytes;
Stream stream;
bool isBytes, isStream, isPath, opened;
string basePath;
DateTime lastWriteTime;
DateTime creationTime;
MacBinaryHeader header;
string filename; string filename;
MacBinaryHeader header;
bool isBytes, isStream, isPath, opened;
DateTime lastWriteTime;
long rsrcForkOff;
Stream stream;
public MacBinary() public MacBinary()
{ {
@@ -278,8 +157,7 @@ namespace DiscImageChef.Filters
header = BigEndianMarshal.ByteArrayToStructureBigEndian<MacBinaryHeader>(hdr_b); header = BigEndianMarshal.ByteArrayToStructureBigEndian<MacBinaryHeader>(hdr_b);
return header.magic == MACBINARY_MAGIC || header.version == 0 && header.filename[0] > 0 && return header.magic == MACBINARY_MAGIC || header.version == 0 && header.filename[0] > 0 &&
header.filename[0] < 64 && header.zero1 == 0 && header.filename[0] < 64 && header.zero1 == 0 && header.zero2 == 0 && header.reserved == 0 &&
header.zero2 == 0 && header.reserved == 0 &&
(header.dataLength > 0 || header.resourceLength > 0); (header.dataLength > 0 || header.resourceLength > 0);
} }
@@ -293,8 +171,7 @@ namespace DiscImageChef.Filters
header = BigEndianMarshal.ByteArrayToStructureBigEndian<MacBinaryHeader>(hdr_b); header = BigEndianMarshal.ByteArrayToStructureBigEndian<MacBinaryHeader>(hdr_b);
return header.magic == MACBINARY_MAGIC || header.version == 0 && header.filename[0] > 0 && return header.magic == MACBINARY_MAGIC || header.version == 0 && header.filename[0] > 0 &&
header.filename[0] < 64 && header.zero1 == 0 && header.filename[0] < 64 && header.zero1 == 0 && header.zero2 == 0 && header.reserved == 0 &&
header.zero2 == 0 && header.reserved == 0 &&
(header.dataLength > 0 || header.resourceLength > 0); (header.dataLength > 0 || header.resourceLength > 0);
} }
@@ -309,8 +186,7 @@ namespace DiscImageChef.Filters
fstream.Close(); fstream.Close();
return header.magic == MACBINARY_MAGIC || header.version == 0 && header.filename[0] > 0 && return header.magic == MACBINARY_MAGIC || header.version == 0 && header.filename[0] > 0 &&
header.filename[0] < 64 && header.zero1 == 0 && header.filename[0] < 64 && header.zero1 == 0 && header.zero2 == 0 && header.reserved == 0 &&
header.zero2 == 0 && header.reserved == 0 &&
(header.dataLength > 0 || header.resourceLength > 0); (header.dataLength > 0 || header.resourceLength > 0);
} }
@@ -398,5 +274,126 @@ namespace DiscImageChef.Filters
isPath = true; isPath = true;
basePath = path; basePath = path;
} }
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct MacBinaryHeader
{
/// <summary>
/// 0x00, MacBinary version, 0
/// </summary>
public byte version;
/// <summary>
/// 0x01, Str63 Pascal filename
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)] public byte[] filename;
/// <summary>
/// 0x41, File type
/// </summary>
public uint type;
/// <summary>
/// 0x45, File creator
/// </summary>
public uint creator;
/// <summary>
/// 0x49, High byte of Finder flags
/// </summary>
public byte finderFlags;
/// <summary>
/// 0x4A, Must be 0
/// </summary>
public byte zero1;
/// <summary>
/// 0x4B, File's icon vertical position within its window
/// </summary>
public ushort verticalPosition;
/// <summary>
/// 0x4D, File's icon horizontal position within its window
/// </summary>
public ushort horizontalPosition;
/// <summary>
/// 0x4F, File's window or folder ID
/// </summary>
public short windowID;
/// <summary>
/// 0x51, Protected flag
/// </summary>
public byte protect;
/// <summary>
/// 0x52, Must be 0
/// </summary>
public byte zero2;
/// <summary>
/// 0x53, Size of data fork
/// </summary>
public uint dataLength;
/// <summary>
/// 0x57, Size of resource fork
/// </summary>
public uint resourceLength;
/// <summary>
/// 0x5B, File's creation time
/// </summary>
public uint creationTime;
/// <summary>
/// 0x5F, File's last modified time
/// </summary>
public uint modificationTime;
/// <summary>
/// 0x63, Length of Get Info comment
/// </summary>
public ushort commentLength;
/// <summary>
/// 0x65, Low byte of Finder flags
/// </summary>
public byte finderFlags2;
#region MacBinary III
/// <summary>
/// 0x66, magic identifier, "mBIN"
/// </summary>
public uint magic;
/// <summary>
/// 0x6A, fdScript from fxInfo, identifies codepage of filename
/// </summary>
public byte fdScript;
/// <summary>
/// 0x6B, fdXFlags from fxInfo, extended Mac OS 8 finder flags
/// </summary>
public byte fdXFlags;
#endregion MacBinary III
/// <summary>
/// 0x6C, unused
/// </summary>
public ulong reserved;
/// <summary>
/// 0x74, Total unpacked files
/// </summary>
public uint totalPackedFiles;
#region MacBinary II
/// <summary>
/// 0x78, Length of secondary header
/// </summary>
public ushort secondaryHeaderLength;
/// <summary>
/// 0x7A, version number of MacBinary that wrote this file, starts at 129
/// </summary>
public byte version2;
/// <summary>
/// 0x7B, version number of MacBinary required to open this file, starts at 129
/// </summary>
public byte minVersion;
/// <summary>
/// 0x7C, CRC of previous bytes
/// </summary>
public short crc;
#endregion MacBinary II
/// <summary>
/// 0x7E, Reserved for computer type and OS ID
/// </summary>
public short computerID;
}
} }
} }

View File

@@ -38,13 +38,13 @@ using Microsoft.Win32.SafeHandles;
namespace DiscImageChef.Filters namespace DiscImageChef.Filters
{ {
/// <summary> /// <summary>
/// Creates a stream that is a subset of another stream. /// Creates a stream that is a subset of another stream.
/// </summary> /// </summary>
public class OffsetStream : Stream public class OffsetStream : Stream
{ {
readonly Stream baseStream; readonly Stream baseStream;
readonly long streamStart;
readonly long streamEnd; readonly long streamEnd;
readonly long streamStart;
public OffsetStream(Stream stream, long start, long end) 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."); 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 CanRead => baseStream.CanRead;
public override bool CanSeek => baseStream.CanSeek; 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, public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback,
object state) object state)
{ {

View File

@@ -40,82 +40,22 @@ using System.Text;
namespace DiscImageChef.Filters namespace DiscImageChef.Filters
{ {
/// <summary> /// <summary>
/// Decodes PCExchange files /// Decodes PCExchange files
/// </summary> /// </summary>
public class PCExchange : Filter public class PCExchange : Filter
{ {
const string FILE_ID = "FILEID.DAT"; const string FILE_ID = "FILEID.DAT";
const string FINDER_INFO = "FINDER.DAT"; const string FINDER_INFO = "FINDER.DAT";
const string RESOURCES = "RESOURCE.FRK"; 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 basePath;
string dataPath;
string rsrcPath;
DateTime lastWriteTime;
DateTime creationTime; DateTime creationTime;
long dataLen; long dataLen;
string dataPath;
DateTime lastWriteTime;
bool opened;
long rsrcLen; long rsrcLen;
string rsrcPath;
public PCExchange() public PCExchange()
{ {
@@ -203,7 +143,8 @@ namespace DiscImageChef.Filters
{ {
string parentFolder = Path.GetDirectoryName(path); 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; if(!Directory.Exists(Path.Combine(parentFolder, RESOURCES))) return false;
@@ -233,9 +174,10 @@ namespace DiscImageChef.Filters
if(baseFilename != macName && baseFilename != dosName && baseFilename != dosNameLow) continue; if(baseFilename != macName && baseFilename != dosName && baseFilename != dosNameLow) continue;
dataFound |= File.Exists(Path.Combine(parentFolder, macName ?? throw new InvalidOperationException())) || dataFound |=
File.Exists(Path.Combine(parentFolder, dosName)) || File.Exists(Path.Combine(parentFolder, macName ?? throw new InvalidOperationException())) ||
File.Exists(Path.Combine(parentFolder, dosNameLow)); File.Exists(Path.Combine(parentFolder, dosName)) ||
File.Exists(Path.Combine(parentFolder, dosNameLow));
rsrcFound |= File.Exists(Path.Combine(parentFolder, RESOURCES, dosName)) || rsrcFound |= File.Exists(Path.Combine(parentFolder, RESOURCES, dosName)) ||
File.Exists(Path.Combine(parentFolder, RESOURCES, dosNameLow)); File.Exists(Path.Combine(parentFolder, RESOURCES, dosNameLow));
@@ -269,7 +211,8 @@ namespace DiscImageChef.Filters
string baseFilename = Path.GetFileName(path); string baseFilename = Path.GetFileName(path);
FileStream finderDatStream = 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) while(finderDatStream.Position + 0x5C <= finderDatStream.Length)
{ {
@@ -288,7 +231,8 @@ namespace DiscImageChef.Filters
if(baseFilename != macName && baseFilename != dosName && baseFilename != dosNameLow) continue; 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))) else if(File.Exists(Path.Combine(parentFolder, dosName)))
dataPath = Path.Combine(parentFolder, dosName); dataPath = Path.Combine(parentFolder, dosName);
else if(File.Exists(Path.Combine(parentFolder, dosNameLow))) else if(File.Exists(Path.Combine(parentFolder, dosNameLow)))
@@ -315,5 +259,65 @@ namespace DiscImageChef.Filters
finderDatStream.Close(); 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

@@ -37,17 +37,17 @@ using SharpCompress.Compressors.Xz;
namespace DiscImageChef.Filters namespace DiscImageChef.Filters
{ {
/// <summary> /// <summary>
/// Decompress xz files while reading /// Decompress xz files while reading
/// </summary> /// </summary>
public class XZ : Filter public class XZ : Filter
{ {
Stream dataStream;
string basePath; string basePath;
DateTime lastWriteTime;
DateTime creationTime; DateTime creationTime;
bool opened; Stream dataStream;
long decompressedSize; long decompressedSize;
Stream innerStream; Stream innerStream;
DateTime lastWriteTime;
bool opened;
public XZ() public XZ()
{ {
@@ -242,7 +242,10 @@ namespace DiscImageChef.Filters
{ {
if(basePath?.EndsWith(".xz", StringComparison.InvariantCultureIgnoreCase) == true) if(basePath?.EndsWith(".xz", StringComparison.InvariantCultureIgnoreCase) == true)
return basePath.Substring(0, basePath.Length - 3); 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() public override string GetParentFolder()

View File

@@ -36,14 +36,14 @@ using System.IO;
namespace DiscImageChef.Filters namespace DiscImageChef.Filters
{ {
/// <summary> /// <summary>
/// No filter for reading files not recognized by any filter /// No filter for reading files not recognized by any filter
/// </summary> /// </summary>
public class ZZZNoFilter : Filter public class ZZZNoFilter : Filter
{ {
Stream dataStream;
string basePath; string basePath;
DateTime lastWriteTime;
DateTime creationTime; DateTime creationTime;
Stream dataStream;
DateTime lastWriteTime;
bool opened; bool opened;
public ZZZNoFilter() public ZZZNoFilter()