* README.md:
	* DiscImageChef.sln:
	* DiscImageChef/Commands/Ls.cs:
	* DiscImageChef.Filters/GZip.cs:
	* DiscImageChef.DiscImages/BLU.cs:
	* DiscImageChef.DiscImages/VHD.cs:
	* DiscImageChef.DiscImages/VDI.cs:
	* DiscImageChef.DiscImages/QED.cs:
	* DiscImageChef.DiscImages/DIM.cs:
	* DiscImageChef.DiscImages/GDI.cs:
	* DiscImageChef.Filters/Filter.cs:
	* DiscImageChef/Commands/Decode.cs:
	* DiscImageChef.DiscImages/QCOW.cs:
	* DiscImageChef.Filters/Filters.cs:
	* DiscImageChef/Core/Statistics.cs:
	* DiscImageChef.DiscImages/VHDX.cs:
	* DiscImageChef.DiscImages/Nero.cs:
	* DiscImageChef/Commands/Verify.cs:
	* DiscImageChef.DiscImages/UDIF.cs:
	* DiscImageChef/Commands/Compare.cs:
	* DiscImageChef/Commands/Analyze.cs:
	* DiscImageChef.DiscImages/QCOW2.cs:
	* DiscImageChef/Commands/Entropy.cs:
	* DiscImageChef/Commands/Formats.cs:
	* DiscImageChef/Commands/PrintHex.cs:
	* DiscImageChef.DiscImages/VMware.cs:
	* DiscImageChef.Settings/Settings.cs:
	* DiscImageChef/DetectImageFormat.cs:
	* DiscImageChef/DiscImageChef.csproj:
	* DiscImageChef.DiscImages/CDRDAO.cs:
	* DiscImageChef.DiscImages/CPCDSK.cs:
	* DiscImageChef/Commands/Checksum.cs:
	* DiscImageChef.DiscImages/CopyQM.cs:
	* DiscImageChef.DiscImages/CDRWin.cs:
	* DiscImageChef/Commands/Configure.cs:
	* DiscImageChef/Commands/DumpMedia.cs:
	* DiscImageChef/Commands/Statistics.cs:
	* DiscImageChef.Filters/ZZZNoFilter.cs:
	* DiscImageChef.DiscImages/TeleDisk.cs:
	* DiscImageChef.DiscImages/Apple2MG.cs:
	* DiscImageChef.Filters/OffsetStream.cs:
	* DiscImageChef.DiscImages/Parallels.cs:
	* DiscImageChef/Commands/ExtractFiles.cs:
	* DiscImageChef.DiscImages/DiskCopy42.cs:
	* DiscImageChef.DiscImages/Alcohol120.cs:
	* DiscImageChef.DiscImages/ZZZRawImage.cs:
	* DiscImageChef/Commands/CreateSidecar.cs:
	* DiscImageChef.DiscImages/ImagePlugin.cs:
	* DiscImageChef.DiscImages/BlindWrite5.cs:
	* DiscImageChef.DiscImages/BlindWrite4.cs:
	* DiscImageChef.Filters/ForcedSeekStream.cs:
	* DiscImageChef.Filters/Properties/AssemblyInfo.cs:
	* DiscImageChef.Filters/DiscImageChef.Filters.csproj:
	* DiscImageChef.DiscImages/DiscImageChef.DiscImages.csproj:
	  Added filters.

	* DiscImageChef.Filesystems/CPM/Info.cs:
	  Do not throw identification exceptions.

	* DiscImageChef/Plugins.cs:
	  Sorted plugins lists.
This commit is contained in:
2016-09-05 17:37:31 +01:00
parent e4c4b2572f
commit 71af0eda23
62 changed files with 2600 additions and 837 deletions

View File

@@ -0,0 +1,11 @@
2016-09-05 Natalia Portillo <claunia@claunia.com>
* GZip.cs:
* Filter.cs:
* Filters.cs:
* ZZZNoFilter.cs:
* OffsetStream.cs:
* ForcedSeekStream.cs:
* AssemblyInfo.cs:
* DiscImageChef.Filters.csproj: Added filters.

View File

@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{D571B8EF-903D-4353-BDD5-B834F9F029EF}</ProjectGuid>
<OutputType>Library</OutputType>
<RootNamespace>DiscImageChef.Filters</RootNamespace>
<AssemblyName>DiscImageChef.Filters</AssemblyName>
<ReleaseVersion>3.2.99.2</ReleaseVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="OffsetStream.cs" />
<Compile Include="Filter.cs" />
<Compile Include="Filters.cs" />
<Compile Include="ZZZNoFilter.cs" />
<Compile Include="ForcedSeekStream.cs" />
<Compile Include="GZip.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="..\LICENSE.LGPL">
<Link>LICENSE.LGPL</Link>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\DiscImageChef.Console\DiscImageChef.Console.csproj">
<Project>{CCAA7AFE-C094-4D82-A66D-630DE8A3F545}</Project>
<Name>DiscImageChef.Console</Name>
</ProjectReference>
<ProjectReference Include="..\DiscImageChef.Helpers\DiscImageChef.Helpers.csproj">
<Project>{F8BDF57B-1571-4CD0-84B3-B422088D359A}</Project>
<Name>DiscImageChef.Helpers</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ProjectExtensions>
<MonoDevelop>
<Properties>
<Policies>
<TextStylePolicy FileWidth="120" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/x-csharp" />
<CSharpFormattingPolicy IndentSwitchSection="True" NewLinesForBracesInProperties="True" NewLinesForBracesInAccessors="True" NewLinesForBracesInAnonymousMethods="True" NewLinesForBracesInControlBlocks="True" NewLinesForBracesInAnonymousTypes="True" NewLinesForBracesInObjectCollectionArrayInitializers="True" NewLinesForBracesInLambdaExpressionBody="True" NewLineForElse="True" NewLineForCatch="True" NewLineForFinally="True" NewLineForMembersInObjectInit="True" NewLineForMembersInAnonymousTypes="True" NewLineForClausesInQuery="True" SpacingAfterMethodDeclarationName="False" SpaceAfterMethodCallName="False" SpaceAfterControlFlowStatementKeyword="False" SpaceBeforeOpenSquareBracket="False" inheritsSet="Mono" inheritsScope="text/x-csharp" scope="text/x-csharp" />
<StandardHeader Text="/***************************************************************************&#xA;The Disc Image Chef&#xA;----------------------------------------------------------------------------&#xA; &#xA;Filename : ${FileName}&#xA;Author(s) : ${AuthorName} &lt;${AuthorEmail}&gt;&#xA;&#xA;Component : Component&#xA; &#xA;--[ Description ] ----------------------------------------------------------&#xA; &#xA; Description&#xA; &#xA;--[ License ] --------------------------------------------------------------&#xA; &#xA; This library is free software; you can redistribute it and/or modify&#xA; it under the terms of the GNU Lesser General Public License as&#xA; published by the Free Software Foundation; either version 2.1 of the&#xA; License, or (at your option) any later version.&#xA;&#xA; This library is distributed in the hope that it will be useful, but&#xA; WITHOUT ANY WARRANTY; without even the implied warranty of&#xA; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU&#xA; Lesser General Public License for more details.&#xA;&#xA; You should have received a copy of the GNU Lesser General Public&#xA; License along with this library; if not, see &lt;http://www.gnu.org/licenses/&gt;.&#xA;&#xA;----------------------------------------------------------------------------&#xA;Copyright © 2011-${Year} ${CopyrightHolder}&#xA;****************************************************************************/" IncludeInNewFiles="True" />
</Policies>
</Properties>
</MonoDevelop>
</ProjectExtensions>
</Project>

View File

@@ -0,0 +1,173 @@
// /***************************************************************************
// The Disc Image Chef
// ----------------------------------------------------------------------------
//
// Filename : Filter.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : Filters.
//
// --[ Description ] ----------------------------------------------------------
//
// Defines the interface for a Filter.
//
// --[ License ] --------------------------------------------------------------
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2016 Natalia Portillo
// ****************************************************************************/
using System;
using System.IO;
namespace DiscImageChef.Filters
{
public abstract class Filter
{
public string Name;
public Guid UUID;
protected Filter()
{
}
/// <summary>
/// Closes all opened streams.
/// </summary>
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/>
/// 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>
public abstract string GetBasePath();
/// <summary>
/// Gets creation time of file referenced by this filter.
/// </summary>
/// <returns>The creation time.</returns>
public abstract DateTime GetCreationTime();
/// <summary>
/// Gets length of this filter's data fork.
/// </summary>
/// <returns>The data fork length.</returns>
public abstract long GetDataForkLength();
/// <summary>
/// Gets a stream to access the data fork contents.
/// </summary>
/// <returns>The data fork stream.</returns>
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/>
/// Windows: C:\path\to\archive.zip\path\to\file.bin => file.bin
/// </summary>
/// <returns>The filename.</returns>
public abstract string GetFilename();
/// <summary>
/// Gets last write time of file referenced by this filter.
/// </summary>
/// <returns>The last write time.</returns>
public abstract DateTime GetLastWriteTime();
/// <summary>
/// Gets length of file referenced by ths filter.
/// </summary>
/// <returns>The length.</returns>
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/>
/// 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/>
/// Windows: C:\path\to\archive.zip\path\to\file.bin => C:\path\to\archive.zip
/// </summary>
/// <returns>The parent folder.</returns>
public abstract string GetParentFolder();
/// <summary>
/// Gets length of this filter's resource fork.
/// </summary>
/// <returns>The resource fork length.</returns>
public abstract long GetResourceForkLength();
/// <summary>
/// Gets a stream to access the resource fork contents.
/// </summary>
/// <returns>The resource fork stream.</returns>
public abstract Stream GetResourceForkStream();
/// <summary>
/// Returns true if the file referenced by this filter has a resource fork
/// </summary>
public abstract bool HasResourceFork();
/// <summary>
/// Identifies if the specified path contains data recognizable by this filter instance
/// </summary>
/// <param name="path">Path.</param>
public abstract bool Identify(string path);
/// <summary>
/// Identifies if the specified stream contains data recognizable by this filter instance
/// </summary>
/// <param name="stream">Stream.</param>
public abstract bool Identify(Stream stream);
/// <summary>
/// Identifies if the specified buffer contains data recognizable by this filter instance
/// </summary>
/// <param name="buffer">Buffer.</param>
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.
/// </summary>
public abstract bool IsOpened();
/// <summary>
/// Opens the specified path with this filter instance
/// </summary>
/// <param name="path">Path.</param>
public abstract void Open(string path);
/// <summary>
/// Opens the specified stream with this filter instance
/// </summary>
/// <param name="stream">Stream.</param>
public abstract void Open(Stream stream);
/// <summary>
/// Opens the specified buffer with this filter instance
/// </summary>
/// <param name="buffer">Buffer.</param>
public abstract void Open(byte[] buffer);
}
}

View File

@@ -0,0 +1,91 @@
// /***************************************************************************
// The Disc Image Chef
// ----------------------------------------------------------------------------
//
// Filename : Filters.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : Filters.
//
// --[ Description ] ----------------------------------------------------------
//
// Enumerates all filters and instantiates the correct one.
//
// --[ License ] --------------------------------------------------------------
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2016 Natalia Portillo
// ****************************************************************************/
using System;
using System.Collections.Generic;
using System.Reflection;
using DiscImageChef.Console;
namespace DiscImageChef.Filters
{
public class FiltersList
{
public SortedDictionary<string, Filter> filtersList;
public FiltersList()
{
Assembly assembly = Assembly.GetAssembly(typeof(Filter));
filtersList = new SortedDictionary<string, Filter>();
foreach(Type type in assembly.GetTypes())
{
try
{
if(type.IsSubclassOf(typeof(Filter)))
{
Filter filter = (Filter)type.GetConstructor(Type.EmptyTypes).Invoke(new object[] { });
if(!filtersList.ContainsKey(filter.Name.ToLower()))
{
filtersList.Add(filter.Name.ToLower(), filter);
}
}
}
catch(Exception exception)
{
DicConsole.ErrorWriteLine("Exception {0}", exception);
}
}
}
public Filter GetFilter(string path)
{
foreach(Filter filter in filtersList.Values)
{
if(filter.Identify(path))
{
Filter foundFilter = (Filter)filter.GetType().GetConstructor(Type.EmptyTypes).Invoke(new object[] { });
foundFilter.Open(path);
if(foundFilter.IsOpened())
return foundFilter;
}
}
return null;
}
public SortedDictionary<string, Filter> GetFiltersList()
{
return filtersList;
}
}
}

View File

@@ -0,0 +1,228 @@
// /***************************************************************************
// The Disc Image Chef
// ----------------------------------------------------------------------------
//
// Filename : ForcedSeekStream.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : Filters.
//
// --[ Description ] ----------------------------------------------------------
//
// Provides a seekable stream from a forward-readable stream.
//
// --[ License ] --------------------------------------------------------------
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2016 Natalia Portillo
// ****************************************************************************/
using System;
using System.IO;
namespace DiscImageChef.Filters
{
/// <summary>
/// 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.
/// </summary>
public class ForcedSeekStream<T> : Stream where T : Stream
{
T baseStream;
long currentPosition;
object[] parameters;
long streamLength;
const int bufferLen = 1048576;
/// <summary>
/// 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>
public ForcedSeekStream(long length, params object[] args)
{
parameters = args;
Rewind();
streamLength = length;
}
/// <summary>
/// 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)
{
parameters = args;
Rewind();
streamLength = baseStream.Length;
}
/// <summary>
/// Rewinds the stream to start
/// </summary>
public void Rewind()
{
baseStream = (T)Activator.CreateInstance(typeof(T), parameters);
currentPosition = 0;
}
/// <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()
{
long count = 0;
int read;
Rewind();
do
{
byte[] buffer = new byte[bufferLen];
read = baseStream.Read(buffer, 0, bufferLen);
count += read;
}
while(read == bufferLen);
streamLength = count;
}
public override bool CanRead
{
get
{
return baseStream.CanRead;
}
}
public override bool CanSeek
{
get
{
return true;
}
}
public override bool CanWrite
{
get
{
return false;
}
}
public override long Length
{
get
{
return baseStream.Length;
}
}
public override long Position
{
get
{
return currentPosition;
}
set
{
if(value == currentPosition)
return;
if(value < currentPosition)
Rewind();
int fullBufferReads = (int)(value / bufferLen);
int restToRead = (int)(value % bufferLen);
byte[] buffer;
for(int i = 0; i < fullBufferReads; i++)
{
buffer = new byte[bufferLen];
baseStream.Read(buffer, 0, bufferLen);
}
buffer = new byte[restToRead];
baseStream.Read(buffer, 0, restToRead);
currentPosition = value;
}
}
public override void Flush()
{
baseStream.Flush();
}
public override int Read(byte[] buffer, int offset, int count)
{
int read = baseStream.Read(buffer, offset, count);
currentPosition += read;
return read;
}
public override int ReadByte()
{
int byt = baseStream.ReadByte();
// Because -1 equals end of stream so we cannot go farther
if(byt > 0)
currentPosition++;
return byt;
}
public override long Seek(long offset, SeekOrigin origin)
{
switch(origin)
{
case SeekOrigin.Begin:
if(offset < 0)
throw new IOException("Cannot seek before stream start.");
Position = offset;
break;
case SeekOrigin.End:
if(offset > 0)
throw new IOException("Cannot seek after stream end.");
if(streamLength == 0)
CalculateLength();
Position = streamLength + offset;
break;
default:
Position = currentPosition + offset;
break;
}
return currentPosition;
}
public override void SetLength(long value)
{
throw new NotSupportedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotSupportedException();
}
}
}

View File

@@ -0,0 +1,239 @@
// /***************************************************************************
// The Disc Image Chef
// ----------------------------------------------------------------------------
//
// Filename : GZip.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : Filters.
//
// --[ Description ] ----------------------------------------------------------
//
// Allow to open files that are compressed using gzip.
//
// --[ License ] --------------------------------------------------------------
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2016 Natalia Portillo
// ****************************************************************************/
using System;
using System.IO;
using System.IO.Compression;
namespace DiscImageChef.Filters
{
public class GZip : Filter
{
Stream dataStream;
string basePath;
DateTime lastWriteTime;
DateTime creationTime;
bool opened;
uint decompressedSize;
public GZip()
{
Name = "GZip";
UUID = new Guid("F4996661-4A29-42C9-A2C7-3904EF40F3B0");
}
public override void Close()
{
if(dataStream != null)
dataStream.Close();
dataStream = null;
basePath = null;
opened = false;
}
public override string GetBasePath()
{
return basePath;
}
public override Stream GetDataForkStream()
{
// Otherwise base stream is not at correct position and deflate throws errors
dataStream.Seek(0, SeekOrigin.Begin);
return new ForcedSeekStream<GZipStream>(decompressedSize, dataStream, CompressionMode.Decompress);
}
public override string GetPath()
{
return basePath;
}
public override Stream GetResourceForkStream()
{
return null;
}
public override bool HasResourceFork()
{
return false;
}
public override bool Identify(byte[] buffer)
{
return buffer[0] == 0x1F && buffer[1] == 0x8B && buffer[2] == 0x08;
}
public override bool Identify(Stream stream)
{
byte[] buffer = new byte[3];
stream.Seek(0, SeekOrigin.Begin);
stream.Read(buffer, 0, 3);
stream.Seek(0, SeekOrigin.Begin);
return buffer[0] == 0x1F && buffer[1] == 0x8B && buffer[2] == 0x08;
}
public override bool Identify(string path)
{
if(File.Exists(path))
{
FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read);
byte[] buffer = new byte[3];
stream.Seek(0, SeekOrigin.Begin);
stream.Read(buffer, 0, 3);
stream.Seek(0, SeekOrigin.Begin);
return buffer[0] == 0x1F && buffer[1] == 0x8B && buffer[2] == 0x08;
}
return false;
}
public override void Open(byte[] buffer)
{
byte[] mtime_b = new byte[4];
byte[] isize_b = new byte[4];
uint mtime;
uint isize;
dataStream = new MemoryStream(buffer);
basePath = null;
dataStream.Seek(4, SeekOrigin.Begin);
dataStream.Read(mtime_b, 0, 4);
dataStream.Seek(-4, SeekOrigin.End);
dataStream.Read(isize_b, 0, 4);
dataStream.Seek(0, SeekOrigin.Begin);
mtime = BitConverter.ToUInt32(mtime_b, 0);
isize = BitConverter.ToUInt32(isize_b, 0);
decompressedSize = isize;
creationTime = DateHandlers.UNIXUnsignedToDateTime(mtime);
lastWriteTime = creationTime;
opened = true;
}
public override void Open(Stream stream)
{
byte[] mtime_b = new byte[4];
byte[] isize_b = new byte[4];
uint mtime;
uint isize;
dataStream = stream;
basePath = null;
dataStream.Seek(4, SeekOrigin.Begin);
dataStream.Read(mtime_b, 0, 4);
dataStream.Seek(-4, SeekOrigin.End);
dataStream.Read(isize_b, 0, 4);
dataStream.Seek(0, SeekOrigin.Begin);
mtime = BitConverter.ToUInt32(mtime_b, 0);
isize = BitConverter.ToUInt32(isize_b, 0);
decompressedSize = isize;
creationTime = DateHandlers.UNIXUnsignedToDateTime(mtime);
lastWriteTime = creationTime;
opened = true;
}
public override void Open(string path)
{
byte[] mtime_b = new byte[4];
byte[] isize_b = new byte[4];
uint mtime;
uint isize;
dataStream = new FileStream(path, FileMode.Open, FileAccess.Read);
basePath = Path.GetFullPath(path);
dataStream.Seek(4, SeekOrigin.Begin);
dataStream.Read(mtime_b, 0, 4);
dataStream.Seek(-4, SeekOrigin.End);
dataStream.Read(isize_b, 0, 4);
dataStream.Seek(0, SeekOrigin.Begin);
mtime = BitConverter.ToUInt32(mtime_b, 0);
isize = BitConverter.ToUInt32(isize_b, 0);
decompressedSize = isize;
FileInfo fi = new FileInfo(path);
creationTime = fi.CreationTimeUtc;
lastWriteTime = DateHandlers.UNIXUnsignedToDateTime(mtime);
opened = true;
}
public override DateTime GetCreationTime()
{
return creationTime;
}
public override long GetDataForkLength()
{
return decompressedSize;
}
public override DateTime GetLastWriteTime()
{
return lastWriteTime;
}
public override long GetLength()
{
return decompressedSize;
}
public override long GetResourceForkLength()
{
return 0;
}
public override string GetFilename()
{
return basePath != null ? Path.GetFileName(basePath) : null;
}
public override string GetParentFolder()
{
return Path.GetDirectoryName(basePath);
}
public override bool IsOpened()
{
return opened;
}
}
}

View File

@@ -0,0 +1,488 @@
// /***************************************************************************
// The Disc Image Chef
// ----------------------------------------------------------------------------
//
// Filename : OffsetStream.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : Filters.
//
// --[ Description ] ----------------------------------------------------------
//
// Provides a stream that's a subset of another stream.
//
// --[ License ] --------------------------------------------------------------
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2016 Natalia Portillo
// ****************************************************************************/
using System;
using System.IO;
using System.Security.AccessControl;
using Microsoft.Win32.SafeHandles;
namespace DiscImageChef.Filters
{
/// <summary>
/// Creates a stream that is a subset of another stream.
/// </summary>
public class OffsetStream : Stream
{
readonly Stream baseStream;
readonly long streamStart;
readonly long streamEnd;
public OffsetStream(Stream stream, long start, long end)
{
if(start < 0)
throw new ArgumentOutOfRangeException(nameof(start), "Start can't be a negative number.");
if(end < 0)
throw new ArgumentOutOfRangeException(nameof(end), "End can't be a negative number.");
streamStart = start;
streamEnd = end;
baseStream = stream;
if(end > baseStream.Length)
throw new ArgumentOutOfRangeException(nameof(end), "End is after stream end.");
}
public OffsetStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options, long start, long end)
{
if(start < 0)
throw new ArgumentOutOfRangeException(nameof(start), "Start can't be a negative number.");
if(end < 0)
throw new ArgumentOutOfRangeException(nameof(end), "End can't be a negative number.");
streamStart = start;
streamEnd = end;
baseStream = new FileStream(path, mode, access, share, bufferSize, options);
if(end > baseStream.Length)
throw new ArgumentOutOfRangeException(nameof(end), "End is after stream end.");
}
public OffsetStream(SafeFileHandle handle, FileAccess access, long start, long end)
{
if(start < 0)
throw new ArgumentOutOfRangeException(nameof(start), "Start can't be a negative number.");
if(end < 0)
throw new ArgumentOutOfRangeException(nameof(end), "End can't be a negative number.");
streamStart = start;
streamEnd = end;
baseStream = new FileStream(handle, access);
if(end > baseStream.Length)
throw new ArgumentOutOfRangeException(nameof(end), "End is after stream end.");
}
public OffsetStream(SafeFileHandle handle, FileAccess access, int bufferSize, long start, long end)
{
if(start < 0)
throw new ArgumentOutOfRangeException(nameof(start), "Start can't be a negative number.");
if(end < 0)
throw new ArgumentOutOfRangeException(nameof(end), "End can't be a negative number.");
streamStart = start;
streamEnd = end;
baseStream = new FileStream(handle, access, bufferSize);
if(end > baseStream.Length)
throw new ArgumentOutOfRangeException(nameof(end), "End is after stream end.");
}
public OffsetStream(SafeFileHandle handle, FileAccess access, int bufferSize, bool isAsync, long start, long end)
{
if(start < 0)
throw new ArgumentOutOfRangeException(nameof(start), "Start can't be a negative number.");
if(end < 0)
throw new ArgumentOutOfRangeException(nameof(end), "End can't be a negative number.");
streamStart = start;
streamEnd = end;
baseStream = new FileStream(handle, access, bufferSize, isAsync);
if(end > baseStream.Length)
throw new ArgumentOutOfRangeException(nameof(end), "End is after stream end.");
}
public OffsetStream(string path, FileMode mode, FileSystemRights rights, FileShare share, int bufferSize, FileOptions options, long start, long end)
{
if(start < 0)
throw new ArgumentOutOfRangeException(nameof(start), "Start can't be a negative number.");
if(end < 0)
throw new ArgumentOutOfRangeException(nameof(end), "End can't be a negative number.");
streamStart = start;
streamEnd = end;
baseStream = new FileStream(path, mode, rights, share, bufferSize, options);
if(end > baseStream.Length)
throw new ArgumentOutOfRangeException(nameof(end), "End is after stream end.");
}
public OffsetStream(string path, FileMode mode, FileSystemRights rights, FileShare share, int bufferSize, FileOptions options, FileSecurity fileSecurity, long start, long end)
{
if(start < 0)
throw new ArgumentOutOfRangeException(nameof(start), "Start can't be a negative number.");
if(end < 0)
throw new ArgumentOutOfRangeException(nameof(end), "End can't be a negative number.");
streamStart = start;
streamEnd = end;
baseStream = new FileStream(path, mode, rights, share, bufferSize, options, fileSecurity);
if(end > baseStream.Length)
throw new ArgumentOutOfRangeException(nameof(end), "End is after stream end.");
}
public OffsetStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, bool useAsync, long start, long end)
{
if(start < 0)
throw new ArgumentOutOfRangeException(nameof(start), "Start can't be a negative number.");
if(end < 0)
throw new ArgumentOutOfRangeException(nameof(end), "End can't be a negative number.");
streamStart = start;
streamEnd = end;
baseStream = new FileStream(path, mode, access, share, bufferSize, useAsync);
if(end > baseStream.Length)
throw new ArgumentOutOfRangeException(nameof(end), "End is after stream end.");
}
public OffsetStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, long start, long end)
{
if(start < 0)
throw new ArgumentOutOfRangeException(nameof(start), "Start can't be a negative number.");
if(end < 0)
throw new ArgumentOutOfRangeException(nameof(end), "End can't be a negative number.");
streamStart = start;
streamEnd = end;
baseStream = new FileStream(path, mode, access, share, bufferSize);
if(end > baseStream.Length)
throw new ArgumentOutOfRangeException(nameof(end), "End is after stream end.");
}
public OffsetStream(string path, FileMode mode, FileAccess access, FileShare share, long start, long end)
{
if(start < 0)
throw new ArgumentOutOfRangeException(nameof(start), "Start can't be a negative number.");
if(end < 0)
throw new ArgumentOutOfRangeException(nameof(end), "End can't be a negative number.");
streamStart = start;
streamEnd = end;
baseStream = new FileStream(path, mode, access, share);
if(end > baseStream.Length)
throw new ArgumentOutOfRangeException(nameof(end), "End is after stream end.");
}
public OffsetStream(string path, FileMode mode, FileAccess access, long start, long end)
{
if(start < 0)
throw new ArgumentOutOfRangeException(nameof(start), "Start can't be a negative number.");
if(end < 0)
throw new ArgumentOutOfRangeException(nameof(end), "End can't be a negative number.");
streamStart = start;
streamEnd = end;
baseStream = new FileStream(path, mode, access);
if(end > baseStream.Length)
throw new ArgumentOutOfRangeException(nameof(end), "End is after stream end.");
}
public OffsetStream(string path, FileMode mode, long start, long end)
{
if(start < 0)
throw new ArgumentOutOfRangeException(nameof(start), "Start can't be a negative number.");
if(end < 0)
throw new ArgumentOutOfRangeException(nameof(end), "End can't be a negative number.");
streamStart = start;
streamEnd = end;
baseStream = new FileStream(path, mode);
if(end > baseStream.Length)
throw new ArgumentOutOfRangeException(nameof(end), "End is after stream end.");
}
public OffsetStream(byte[] buffer, int index, int count, bool writable, bool publiclyVisible, long start, long end)
{
if(start < 0)
throw new ArgumentOutOfRangeException(nameof(start), "Start can't be a negative number.");
if(end < 0)
throw new ArgumentOutOfRangeException(nameof(end), "End can't be a negative number.");
streamStart = start;
streamEnd = end;
baseStream = new MemoryStream(buffer, index, count, writable, publiclyVisible);
if(end > baseStream.Length)
throw new ArgumentOutOfRangeException(nameof(end), "End is after stream end.");
}
public OffsetStream(byte[] buffer, int index, int count, bool writable, long start, long end)
{
if(start < 0)
throw new ArgumentOutOfRangeException(nameof(start), "Start can't be a negative number.");
if(end < 0)
throw new ArgumentOutOfRangeException(nameof(end), "End can't be a negative number.");
streamStart = start;
streamEnd = end;
baseStream = new MemoryStream(buffer, index, count, writable);
if(end > baseStream.Length)
throw new ArgumentOutOfRangeException(nameof(end), "End is after stream end.");
}
public OffsetStream(byte[] buffer, int index, int count, long start, long end)
{
if(start < 0)
throw new ArgumentOutOfRangeException(nameof(start), "Start can't be a negative number.");
if(end < 0)
throw new ArgumentOutOfRangeException(nameof(end), "End can't be a negative number.");
streamStart = start;
streamEnd = end;
baseStream = new MemoryStream(buffer, index, count);
if(end > baseStream.Length)
throw new ArgumentOutOfRangeException(nameof(end), "End is after stream end.");
}
public OffsetStream(byte[] buffer, bool writable, long start, long end)
{
if(start < 0)
throw new ArgumentOutOfRangeException(nameof(start), "Start can't be a negative number.");
if(end < 0)
throw new ArgumentOutOfRangeException(nameof(end), "End can't be a negative number.");
streamStart = start;
streamEnd = end;
baseStream = new MemoryStream(buffer, writable);
if(end > baseStream.Length)
throw new ArgumentOutOfRangeException(nameof(end), "End is after stream end.");
}
public OffsetStream(byte[] buffer, long start, long end)
{
if(start < 0)
throw new ArgumentOutOfRangeException(nameof(start), "Start can't be a negative number.");
if(end < 0)
throw new ArgumentOutOfRangeException(nameof(end), "End can't be a negative number.");
streamStart = start;
streamEnd = end;
baseStream = new MemoryStream(buffer);
if(end > baseStream.Length)
throw new ArgumentOutOfRangeException(nameof(end), "End is after stream end.");
}
~OffsetStream()
{
baseStream.Close();
baseStream.Dispose();
}
public override bool CanRead
{
get
{
return baseStream.CanRead;
}
}
public override bool CanSeek
{
get
{
return baseStream.CanSeek;
}
}
public override bool CanWrite
{
get
{
return baseStream.CanWrite;
}
}
public override long Length
{
get
{
return streamEnd - streamStart;
}
}
public override long Position
{
get
{
return baseStream.Position - streamStart;
}
set
{
if(value + streamStart > streamEnd)
throw new IOException("Cannot set position past stream end.");
baseStream.Position = value;
}
}
public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
{
if(baseStream.Position + count > streamEnd)
throw new IOException("Cannot read past stream end.");
return baseStream.BeginRead(buffer, offset, count, callback, state);
}
public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
{
if(baseStream.Position + count > streamEnd)
throw new IOException("Cannot write past stream end.");
return baseStream.BeginWrite(buffer, offset, count, callback, state);
}
public override void Close()
{
baseStream.Close();
}
protected new void Dispose()
{
baseStream.Dispose();
base.Dispose();
}
public override int EndRead(IAsyncResult asyncResult)
{
return baseStream.EndRead(asyncResult);
}
public override void EndWrite(IAsyncResult asyncResult)
{
baseStream.EndWrite(asyncResult);
}
public override int ReadByte()
{
return baseStream.Position == streamEnd ? -1 : baseStream.ReadByte();
}
public override void WriteByte(byte value)
{
if(baseStream.Position + 1 > streamEnd)
throw new IOException("Cannot write past stream end.");
baseStream.WriteByte(value);
}
public override void Flush()
{
baseStream.Flush();
}
public override int Read(byte[] buffer, int offset, int count)
{
if(baseStream.Position + count > streamEnd)
throw new IOException("Cannot read past stream end.");
return baseStream.Read(buffer, offset, count);
}
public override long Seek(long offset, SeekOrigin origin)
{
switch(origin)
{
case SeekOrigin.Begin:
if(offset + streamStart > streamEnd)
throw new IOException("Cannot seek past stream end.");
return baseStream.Seek(offset + streamStart, SeekOrigin.Begin) - streamStart;
case SeekOrigin.End:
if(offset - (baseStream.Length - streamEnd) < streamStart)
throw new IOException("Cannot seek before stream start.");
return baseStream.Seek(offset - (baseStream.Length - streamEnd), SeekOrigin.End) - streamStart;
default:
if(offset + baseStream.Position > streamEnd)
throw new IOException("Cannot seek past stream end.");
return baseStream.Seek(offset, SeekOrigin.Current) - streamStart;
}
}
public override void SetLength(long value)
{
throw new NotSupportedException("Growing OffsetStream is not supported.");
}
public override void Write(byte[] buffer, int offset, int count)
{
if(baseStream.Position + count > streamEnd)
throw new IOException("Cannot write past stream end.");
baseStream.Write(buffer, offset, count);
}
}
}

View File

@@ -0,0 +1,64 @@
// /***************************************************************************
// The Disc Image Chef
// ----------------------------------------------------------------------------
//
// Filename : AssemblyInfo.cs
// Version : 1.0
// Author(s) : Natalia Portillo
//
// Component : Component
//
// Revision : $Revision$
// Last change by : $Author$
// Date : $Date$
//
// --[ Description ] ----------------------------------------------------------
//
// Description
//
// --[ License ] --------------------------------------------------------------
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright (C) 2011-2015 Claunia.com
// ****************************************************************************/
// //$Id$
using System.Reflection;
using System.Runtime.CompilerServices;
// Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project.
[assembly: AssemblyTitle("DiscImageChef.Filters")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Claunia.com")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("© Claunia.com")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion("1.0.*")]
// The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing.
//[assembly: AssemblyDelaySign(false)]
//[assembly: AssemblyKeyFile("")]

View File

@@ -0,0 +1,171 @@
// /***************************************************************************
// The Disc Image Chef
// ----------------------------------------------------------------------------
//
// Filename : ZZZNoFilter.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : Filters.
//
// --[ Description ] ----------------------------------------------------------
//
// Provides a filter to open single files.
//
// --[ License ] --------------------------------------------------------------
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2016 Natalia Portillo
// ****************************************************************************/
using System;
using System.IO;
namespace DiscImageChef.Filters
{
public class ZZZNoFilter : Filter
{
Stream dataStream;
string basePath;
DateTime lastWriteTime;
DateTime creationTime;
bool opened;
public ZZZNoFilter()
{
Name = "No filter";
UUID = new Guid("12345678-AAAA-BBBB-CCCC-123456789000");
}
public override void Close()
{
if(dataStream != null)
dataStream.Close();
dataStream = null;
basePath = null;
opened = false;
}
public override string GetBasePath()
{
return basePath;
}
public override Stream GetDataForkStream()
{
return dataStream;
}
public override string GetPath()
{
return basePath;
}
public override Stream GetResourceForkStream()
{
return null;
}
public override bool HasResourceFork()
{
// TODO: Implement support for xattrs/ADS
return false;
}
public override bool Identify(byte[] buffer)
{
return buffer != null && buffer.Length > 0;
}
public override bool Identify(Stream stream)
{
return stream != null && stream.Length > 0;
}
public override bool Identify(string path)
{
return File.Exists(path);
}
public override void Open(byte[] buffer)
{
dataStream = new MemoryStream(buffer);
basePath = null;
creationTime = DateTime.UtcNow;
lastWriteTime = creationTime;
opened = true;
}
public override void Open(Stream stream)
{
dataStream = stream;
basePath = null;
creationTime = DateTime.UtcNow;
lastWriteTime = creationTime;
opened = true;
}
public override void Open(string path)
{
dataStream = new FileStream(path, FileMode.Open, FileAccess.Read);
basePath = Path.GetFullPath(path);
FileInfo fi = new FileInfo(path);
creationTime = fi.CreationTimeUtc;
lastWriteTime = fi.LastWriteTimeUtc;
opened = true;
}
public override DateTime GetCreationTime()
{
return creationTime;
}
public override long GetDataForkLength()
{
return dataStream.Length;
}
public override DateTime GetLastWriteTime()
{
return lastWriteTime;
}
public override long GetLength()
{
return dataStream.Length;
}
public override long GetResourceForkLength()
{
return 0;
}
public override string GetFilename()
{
return basePath != null ? Path.GetFileName(basePath) : null;
}
public override string GetParentFolder()
{
return Path.GetDirectoryName(basePath);
}
public override bool IsOpened()
{
return opened;
}
}
}