Read existing tape file and partition blocks in dicformat.

This commit is contained in:
2019-05-02 00:25:24 +01:00
parent b31d40bd87
commit 6d7fc3cb5c
5 changed files with 128 additions and 8 deletions

View File

@@ -122,7 +122,6 @@ namespace DiscImageChef.DiscImages
List<IndexEntry> index;
/// <summary>If set to <c>true</c>, the DDT entries are in-memory.</summary>
bool inMemoryDdt;
bool isTape;
ulong lastWrittenBlock;
/// <summary>LZMA stream.</summary>
LzmaStream lzmaBlockStream;

View File

@@ -248,7 +248,7 @@ namespace DiscImageChef.DiscImages
{
if(inMemoryDdt)
{
if(isTape) tapeDdt[sectorAddress] = pointer;
if(IsTape) tapeDdt[sectorAddress] = pointer;
else userDataDdt[sectorAddress] = pointer;
return;
}

View File

@@ -811,6 +811,59 @@ namespace DiscImageChef.DiscImages
DicConsole.DebugWriteLine("DiscImageChef format plugin", "Memory snapshot: {0} bytes",
GC.GetTotalMemory(false));
break;
// Tape partition block
case BlockType.TapePartitionBlock:
structureBytes = new byte[Marshal.SizeOf<TapePartitionHeader>()];
imageStream.Read(structureBytes, 0, structureBytes.Length);
TapePartitionHeader partitionHeader =
Marshal.SpanToStructureLittleEndian<TapePartitionHeader>(structureBytes);
if(partitionHeader.identifier != BlockType.TapePartitionBlock) break;
DicConsole.DebugWriteLine("DiscImageChef format plugin",
"Found tape partition block at position {0}", entry.offset);
byte[] tapePartitionBytes = new byte[partitionHeader.length];
imageStream.Read(tapePartitionBytes, 0, tapePartitionBytes.Length);
Span<TapePartitionEntry> tapePartitions =
MemoryMarshal.Cast<byte, TapePartitionEntry>(tapePartitionBytes);
TapePartitions = new List<TapePartition>();
foreach(TapePartitionEntry tapePartition in tapePartitions)
TapePartitions.Add(new TapePartition
{
FirstBlock = tapePartition.FirstBlock,
LastBlock = tapePartition.LastBlock,
Number = tapePartition.Number
});
IsTape = true;
break;
// Tape file block
case BlockType.TapeFileBlock:
structureBytes = new byte[Marshal.SizeOf<TapeFileHeader>()];
imageStream.Read(structureBytes, 0, structureBytes.Length);
TapeFileHeader fileHeader = Marshal.SpanToStructureLittleEndian<TapeFileHeader>(structureBytes);
if(fileHeader.identifier != BlockType.TapeFileBlock) break;
DicConsole.DebugWriteLine("DiscImageChef format plugin",
"Found tape file block at position {0}", entry.offset);
byte[] tapeFileBytes = new byte[fileHeader.length];
imageStream.Read(tapeFileBytes, 0, tapeFileBytes.Length);
Span<TapeFileEntry> tapeFiles = MemoryMarshal.Cast<byte, TapeFileEntry>(tapeFileBytes);
Files = new List<TapeFile>();
foreach(TapeFileEntry file in tapeFiles)
Files.Add(new TapeFile
{
FirstBlock = file.FirstBlock,
LastBlock = file.LastBlock,
Partition = file.Partition,
File = file.File
});
IsTape = true;
break;
}
}
@@ -1150,6 +1203,7 @@ namespace DiscImageChef.DiscImages
dataSource = sectorPrefix;
break;
}
case SectorTagType.CdSectorHeader:
{
sectorOffset = 12;
@@ -1158,6 +1212,7 @@ namespace DiscImageChef.DiscImages
dataSource = sectorPrefix;
break;
}
case SectorTagType.CdSectorSubHeader:
throw new ArgumentException("Unsupported tag requested for this track", nameof(tag));
case SectorTagType.CdSectorEcc:
@@ -1168,6 +1223,7 @@ namespace DiscImageChef.DiscImages
dataSource = sectorSuffix;
break;
}
case SectorTagType.CdSectorEccP:
{
sectorOffset = 12;
@@ -1176,6 +1232,7 @@ namespace DiscImageChef.DiscImages
dataSource = sectorSuffix;
break;
}
case SectorTagType.CdSectorEccQ:
{
sectorOffset = 184;
@@ -1184,6 +1241,7 @@ namespace DiscImageChef.DiscImages
dataSource = sectorSuffix;
break;
}
case SectorTagType.CdSectorEdc:
{
sectorOffset = 0;
@@ -1192,6 +1250,7 @@ namespace DiscImageChef.DiscImages
dataSource = sectorSuffix;
break;
}
case SectorTagType.CdSectorSubchannel:
{
sectorOffset = 0;
@@ -1200,6 +1259,7 @@ namespace DiscImageChef.DiscImages
dataSource = sectorSubchannel;
break;
}
default: throw new ArgumentException("Unsupported tag requested", nameof(tag));
}
@@ -1218,6 +1278,7 @@ namespace DiscImageChef.DiscImages
dataSource = sectorPrefix;
break;
}
case SectorTagType.CdSectorHeader:
{
sectorOffset = 12;
@@ -1226,6 +1287,7 @@ namespace DiscImageChef.DiscImages
dataSource = sectorPrefix;
break;
}
// These could be implemented
case SectorTagType.CdSectorEcc:
case SectorTagType.CdSectorEccP:
@@ -1241,11 +1303,13 @@ namespace DiscImageChef.DiscImages
dataSource = sectorSubchannel;
break;
}
default: throw new ArgumentException("Unsupported tag requested", nameof(tag));
}
break;
}
case TrackType.Audio:
{
switch(tag)
@@ -1258,11 +1322,13 @@ namespace DiscImageChef.DiscImages
dataSource = sectorSubchannel;
break;
}
default: throw new ArgumentException("Unsupported tag requested", nameof(tag));
}
break;
}
default: throw new FeatureSupportedButNotImplementedImageException("Unsupported track type");
}
}

View File

@@ -40,6 +40,7 @@ namespace DiscImageChef.DiscImages
{
public List<TapeFile> Files { get; private set; }
public List<TapePartition> TapePartitions { get; private set; }
public bool IsTape { get; private set; }
public bool AddFile(TapeFile file)
{
@@ -69,7 +70,7 @@ namespace DiscImageChef.DiscImages
{
Files = new List<TapeFile>();
TapePartitions = new List<TapePartition>();
return isTape = true;
return IsTape = true;
}
}
}

View File

@@ -407,7 +407,7 @@ namespace DiscImageChef.DiscImages
if(ddtHeader.identifier != BlockType.DeDuplicationTable) break;
if(ddtHeader.entries != imageInfo.Sectors && !isTape)
if(ddtHeader.entries != imageInfo.Sectors && !IsTape)
{
ErrorMessage =
$"Trying to write a media with {imageInfo.Sectors} sectors to an image with {ddtHeader.entries} sectors, not continuing...";
@@ -449,7 +449,7 @@ namespace DiscImageChef.DiscImages
ImageNotSupportedException($"Found unsupported compression algorithm {(ushort)ddtHeader.compression}");
}
if(isTape)
if(IsTape)
{
tapeDdt = new Dictionary<ulong, ulong>();
for(long i = 0; i < userDataDdt.LongLength; i++)
@@ -672,6 +672,60 @@ namespace DiscImageChef.DiscImages
if(DumpHardware.Count == 0) DumpHardware = null;
break;
// Tape partition block
case BlockType.TapePartitionBlock:
structureBytes = new byte[Marshal.SizeOf<TapePartitionHeader>()];
imageStream.Read(structureBytes, 0, structureBytes.Length);
TapePartitionHeader partitionHeader =
Marshal.SpanToStructureLittleEndian<TapePartitionHeader>(structureBytes);
if(partitionHeader.identifier != BlockType.TapePartitionBlock) break;
DicConsole.DebugWriteLine("DiscImageChef format plugin",
"Found tape partition block at position {0}", entry.offset);
byte[] tapePartitionBytes = new byte[partitionHeader.length];
imageStream.Read(tapePartitionBytes, 0, tapePartitionBytes.Length);
Span<TapePartitionEntry> tapePartitions =
MemoryMarshal.Cast<byte, TapePartitionEntry>(tapePartitionBytes);
TapePartitions = new List<TapePartition>();
foreach(TapePartitionEntry tapePartition in tapePartitions)
TapePartitions.Add(new TapePartition
{
FirstBlock = tapePartition.FirstBlock,
LastBlock = tapePartition.LastBlock,
Number = tapePartition.Number
});
IsTape = true;
break;
// Tape file block
case BlockType.TapeFileBlock:
structureBytes = new byte[Marshal.SizeOf<TapeFileHeader>()];
imageStream.Read(structureBytes, 0, structureBytes.Length);
TapeFileHeader fileHeader =
Marshal.SpanToStructureLittleEndian<TapeFileHeader>(structureBytes);
if(fileHeader.identifier != BlockType.TapeFileBlock) break;
DicConsole.DebugWriteLine("DiscImageChef format plugin",
"Found tape file block at position {0}", entry.offset);
byte[] tapeFileBytes = new byte[fileHeader.length];
imageStream.Read(tapeFileBytes, 0, tapeFileBytes.Length);
Span<TapeFileEntry> tapeFiles = MemoryMarshal.Cast<byte, TapeFileEntry>(tapeFileBytes);
Files = new List<TapeFile>();
foreach(TapeFileEntry file in tapeFiles)
Files.Add(new TapeFile
{
FirstBlock = file.FirstBlock,
LastBlock = file.LastBlock,
Partition = file.Partition,
File = file.File
});
IsTape = true;
break;
}
}
@@ -699,7 +753,7 @@ namespace DiscImageChef.DiscImages
// If in memory, easy
if(inMemoryDdt)
{
if(isTape) tapeDdt = new Dictionary<ulong, ulong>();
if(IsTape) tapeDdt = new Dictionary<ulong, ulong>();
else userDataDdt = new ulong[sectors];
}
// If not, create the block, add to index, and enlarge the file to allow the DDT to exist on-disk
@@ -811,7 +865,7 @@ namespace DiscImageChef.DiscImages
return false;
}
if(sectorAddress >= Info.Sectors && !isTape)
if(sectorAddress >= Info.Sectors && !IsTape)
{
ErrorMessage = "Tried to write past image size";
return false;
@@ -1867,7 +1921,7 @@ namespace DiscImageChef.DiscImages
}
}
if(isTape)
if(IsTape)
{
ulong latestBlock = tapeDdt.Max(b => b.Key);