mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
[ZOO] Implement opening archive.
This commit is contained in:
184
Aaru.Archives/Zoo/Open.cs
Normal file
184
Aaru.Archives/Zoo/Open.cs
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
// /***************************************************************************
|
||||||
|
// Aaru Data Preservation Suite
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Filename : Consts.cs
|
||||||
|
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
||||||
|
//
|
||||||
|
// Component : Zoo plugin.
|
||||||
|
//
|
||||||
|
// --[ 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-2025 Natalia Portillo
|
||||||
|
// ****************************************************************************/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using Aaru.CommonTypes.Enums;
|
||||||
|
using Aaru.CommonTypes.Interfaces;
|
||||||
|
using Aaru.Helpers;
|
||||||
|
using Aaru.Logging;
|
||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace Aaru.Archives;
|
||||||
|
|
||||||
|
public sealed partial class Zoo
|
||||||
|
{
|
||||||
|
List<Direntry> _files;
|
||||||
|
|
||||||
|
#region IArchive Members
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public ErrorNumber Open(IFilter filter, Encoding encoding)
|
||||||
|
{
|
||||||
|
if(filter.DataForkLength < Marshal.SizeOf<ZooHeader>()) return ErrorNumber.InvalidArgument;
|
||||||
|
|
||||||
|
_stream = filter.GetDataForkStream();
|
||||||
|
_stream.Position = 0;
|
||||||
|
encoding ??= Encoding.UTF8;
|
||||||
|
|
||||||
|
_features = ArchiveSupportedFeature.HasEntryTimestamp |
|
||||||
|
ArchiveSupportedFeature.SupportsFilenames |
|
||||||
|
ArchiveSupportedFeature.SupportsSubdirectories;
|
||||||
|
|
||||||
|
byte[] hdr = new byte[Marshal.SizeOf<ZooHeader>()];
|
||||||
|
|
||||||
|
_stream.ReadExactly(hdr, 0, hdr.Length);
|
||||||
|
|
||||||
|
ZooHeader header = Marshal.ByteArrayToStructureLittleEndian<ZooHeader>(hdr);
|
||||||
|
|
||||||
|
AaruLogging.Debug(MODULE_NAME,
|
||||||
|
"[blue]header.text[/] = [green]\"{0}\"[/]",
|
||||||
|
Markup.Escape(Encoding.UTF8.GetString(header.text).TrimEnd('\0')));
|
||||||
|
|
||||||
|
AaruLogging.Debug(MODULE_NAME, "[blue]header.zoo_tag[/] = [teal]0x{0:X8}[/]", header.zoo_tag);
|
||||||
|
AaruLogging.Debug(MODULE_NAME, "[blue]header.zoo_start[/] = [teal]{0}[/]", header.zoo_start);
|
||||||
|
AaruLogging.Debug(MODULE_NAME, "[blue]header.zoo_minus[/] = [teal]{0}[/]", header.zoo_minus);
|
||||||
|
AaruLogging.Debug(MODULE_NAME, "[blue]header.major_ver[/] = [teal]{0}[/]", header.major_ver);
|
||||||
|
AaruLogging.Debug(MODULE_NAME, "[blue]header.minor_ver[/] = [teal]{0}[/]", header.minor_ver);
|
||||||
|
AaruLogging.Debug(MODULE_NAME, "[blue]header.type[/] = [teal]{0}[/]", header.type);
|
||||||
|
AaruLogging.Debug(MODULE_NAME, "[blue]header.acmt_pos[/] = [teal]{0}[/]", header.acmt_pos);
|
||||||
|
AaruLogging.Debug(MODULE_NAME, "[blue]header.acmt_len[/] = [teal]{0}[/]", header.acmt_len);
|
||||||
|
AaruLogging.Debug(MODULE_NAME, "[blue]header.vdata[/] = [teal]0x{0:X4}[/]", header.vdata);
|
||||||
|
|
||||||
|
_files = [];
|
||||||
|
|
||||||
|
AaruLogging.Debug(MODULE_NAME, "Seeking to [teal]{0} for first file.", header.zoo_start);
|
||||||
|
|
||||||
|
_stream.Position = header.zoo_start;
|
||||||
|
|
||||||
|
Direntry entry;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
byte[] buf = new byte[Marshal.SizeOf<Direntry>()];
|
||||||
|
|
||||||
|
if(_stream.Position + buf.Length >= _stream.Length) break;
|
||||||
|
|
||||||
|
_stream.ReadExactly(buf, 0, buf.Length);
|
||||||
|
|
||||||
|
entry = Marshal.ByteArrayToStructureLittleEndian<Direntry>(buf);
|
||||||
|
|
||||||
|
int pos = 56; // dir_crc
|
||||||
|
if(entry.namlen > 0) entry.lfname = new byte[entry.namlen];
|
||||||
|
Array.Copy(buf, pos, entry.lfname, 0, entry.namlen);
|
||||||
|
pos += entry.namlen;
|
||||||
|
entry.dirname = new byte[entry.dirlen];
|
||||||
|
Array.Copy(buf, pos, entry.dirname, 0, entry.dirlen);
|
||||||
|
pos += entry.dirlen;
|
||||||
|
entry.system_id = BitConverter.ToUInt16(buf, pos);
|
||||||
|
pos += 2;
|
||||||
|
entry.fattr = BitConverter.ToUInt32(buf, pos);
|
||||||
|
pos += 4;
|
||||||
|
entry.vflag = BitConverter.ToUInt16(buf, pos);
|
||||||
|
pos += 2;
|
||||||
|
entry.version_no = BitConverter.ToUInt16(buf, pos);
|
||||||
|
|
||||||
|
AaruLogging.Debug(MODULE_NAME, "[blue]entry.zoo_tag[/] = [teal]0x{0:X8}[/]", entry.zoo_tag);
|
||||||
|
AaruLogging.Debug(MODULE_NAME, "[blue]entry.type[/] = [teal]{0}[/]", entry.type);
|
||||||
|
AaruLogging.Debug(MODULE_NAME, "[blue]entry.packing_method[/] = [teal]{0}[/]", entry.packing_method);
|
||||||
|
AaruLogging.Debug(MODULE_NAME, "[blue]entry.next[/] = [teal]{0}[/]", entry.next);
|
||||||
|
AaruLogging.Debug(MODULE_NAME, "[blue]entry.offset[/] = [teal]{0}[/]", entry.offset);
|
||||||
|
AaruLogging.Debug(MODULE_NAME, "[blue]entry.date[/] = [teal]{0}[/]", entry.date);
|
||||||
|
AaruLogging.Debug(MODULE_NAME, "[blue]entry.time[/] = [teal]{0}[/]", entry.time);
|
||||||
|
AaruLogging.Debug(MODULE_NAME, "[blue]entry.file_crc[/] = [teal]0x{0:X4}[/]", entry.file_crc);
|
||||||
|
AaruLogging.Debug(MODULE_NAME, "[blue]entry.org_size[/] = [teal]{0}[/]", entry.org_size);
|
||||||
|
AaruLogging.Debug(MODULE_NAME, "[blue]entry.size_now[/] = [teal]{0}[/]", entry.size_now);
|
||||||
|
AaruLogging.Debug(MODULE_NAME, "[blue]entry.major_ver[/] = [teal]{0}[/]", entry.major_ver);
|
||||||
|
AaruLogging.Debug(MODULE_NAME, "[blue]entry.minor_ver[/] = [teal]{0}[/]", entry.minor_ver);
|
||||||
|
AaruLogging.Debug(MODULE_NAME, "[blue]entry.deleted[/] = [teal]{0}[/]", entry.deleted);
|
||||||
|
AaruLogging.Debug(MODULE_NAME, "[blue]entry.struc[/] = [teal]{0}[/]", entry.struc);
|
||||||
|
AaruLogging.Debug(MODULE_NAME, "[blue]entry.comment[/] = [teal]{0}[/]", entry.comment);
|
||||||
|
AaruLogging.Debug(MODULE_NAME, "[blue]entry.cmt_size[/] = [teal]{0}[/]", entry.cmt_size);
|
||||||
|
|
||||||
|
AaruLogging.Debug(MODULE_NAME,
|
||||||
|
"[blue]entry.fname[/] = [green]\"{0}\"[/]",
|
||||||
|
StringHandlers.CToString(entry.fname, encoding));
|
||||||
|
|
||||||
|
AaruLogging.Debug(MODULE_NAME, "[blue]entry.var_dir_len[/] = [teal]{0}[/]", entry.var_dir_len);
|
||||||
|
AaruLogging.Debug(MODULE_NAME, "[blue]entry.tz[/] = [teal]{0}[/]", entry.tz);
|
||||||
|
AaruLogging.Debug(MODULE_NAME, "[blue]entry.dir_crc[/] = [teal]0x{0:X4}[/]", entry.dir_crc);
|
||||||
|
AaruLogging.Debug(MODULE_NAME, "[blue]entry.namlen[/] = [teal]{0}[/]", entry.namlen);
|
||||||
|
AaruLogging.Debug(MODULE_NAME, "[blue]entry.dirlen[/] = [teal]{0}[/]", entry.dirlen);
|
||||||
|
|
||||||
|
AaruLogging.Debug(MODULE_NAME,
|
||||||
|
"[blue]entry.lfname[/] = [green]\"{0}\"[/]",
|
||||||
|
StringHandlers.CToString(entry.lfname, encoding));
|
||||||
|
|
||||||
|
AaruLogging.Debug(MODULE_NAME,
|
||||||
|
"[blue]entry.dirname[/] = [green]\"{0}\"[/]",
|
||||||
|
StringHandlers.CToString(entry.dirname, encoding));
|
||||||
|
|
||||||
|
AaruLogging.Debug(MODULE_NAME, "[blue]entry.system_id[/] = [teal]{0}[/]", entry.system_id);
|
||||||
|
AaruLogging.Debug(MODULE_NAME, "[blue]entry.fattr[/] = [teal]{0}[/]", entry.fattr);
|
||||||
|
AaruLogging.Debug(MODULE_NAME, "[blue]entry.vflag[/] = [teal]{0}[/]", entry.vflag);
|
||||||
|
AaruLogging.Debug(MODULE_NAME, "[blue]entry.version_no[/] = [teal]{0}[/]", entry.version_no);
|
||||||
|
|
||||||
|
_files.Add(entry);
|
||||||
|
|
||||||
|
if(entry.packing_method > 0) _features |= ArchiveSupportedFeature.SupportsCompression;
|
||||||
|
if(entry.cmt_size > 0) _features |= ArchiveSupportedFeature.SupportsXAttrs;
|
||||||
|
|
||||||
|
if(entry.next > 0 && entry.next < filter.DataForkLength)
|
||||||
|
{
|
||||||
|
AaruLogging.Debug(MODULE_NAME, "Seeking to [teal]{0}[/] for next file.", entry.next);
|
||||||
|
_stream.Position = entry.next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
} while(entry.next > 0);
|
||||||
|
|
||||||
|
Opened = true;
|
||||||
|
|
||||||
|
return ErrorNumber.NoError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
// Already closed
|
||||||
|
if(!Opened) return;
|
||||||
|
|
||||||
|
_stream?.Close();
|
||||||
|
|
||||||
|
_stream = null;
|
||||||
|
Opened = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
@@ -42,7 +42,7 @@ public sealed partial class Zoo
|
|||||||
#region Nested type: Direntry
|
#region Nested type: Direntry
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
|
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
|
||||||
readonly struct Direntry
|
struct Direntry
|
||||||
{
|
{
|
||||||
/// <summary>tag -- redundancy check </summary>
|
/// <summary>tag -- redundancy check </summary>
|
||||||
public readonly uint zoo_tag;
|
public readonly uint zoo_tag;
|
||||||
@@ -78,7 +78,7 @@ public sealed partial class Zoo
|
|||||||
public readonly byte[] fname;
|
public readonly byte[] fname;
|
||||||
|
|
||||||
/// <summary>length of variable part of dir entry </summary>
|
/// <summary>length of variable part of dir entry </summary>
|
||||||
public readonly int var_dir_len;
|
public readonly short var_dir_len;
|
||||||
/// <summary>timezone where file was archived </summary>
|
/// <summary>timezone where file was archived </summary>
|
||||||
public readonly byte tz;
|
public readonly byte tz;
|
||||||
/// <summary>CRC of directory entry </summary>
|
/// <summary>CRC of directory entry </summary>
|
||||||
@@ -92,18 +92,18 @@ public sealed partial class Zoo
|
|||||||
public readonly byte dirlen;
|
public readonly byte dirlen;
|
||||||
/// <summary>long filename </summary>
|
/// <summary>long filename </summary>
|
||||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = LFNAMESIZE)]
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = LFNAMESIZE)]
|
||||||
public readonly char lfname;
|
public byte[] lfname;
|
||||||
/// <summary>directory name </summary>
|
/// <summary>directory name </summary>
|
||||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = PATHSIZE)]
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = PATHSIZE)]
|
||||||
public readonly byte[] dirname;
|
public byte[] dirname;
|
||||||
/// <summary>Filesystem ID </summary>
|
/// <summary>Filesystem ID </summary>
|
||||||
public readonly ushort system_id;
|
public ushort system_id;
|
||||||
/// <summary>File attributes -- 24 bits </summary>
|
/// <summary>File attributes -- 24 bits </summary>
|
||||||
public readonly uint fattr;
|
public uint fattr;
|
||||||
/// <summary>version flag bits -- one byte in archive </summary>
|
/// <summary>version flag bits -- one byte in archive </summary>
|
||||||
public readonly ushort vflag;
|
public ushort vflag;
|
||||||
/// <summary>file version number if any </summary>
|
/// <summary>file version number if any </summary>
|
||||||
public readonly ushort version_no;
|
public ushort version_no;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@@ -28,7 +28,6 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
|
||||||
using Aaru.CommonTypes.Enums;
|
using Aaru.CommonTypes.Enums;
|
||||||
using Aaru.CommonTypes.Interfaces;
|
using Aaru.CommonTypes.Interfaces;
|
||||||
using Aaru.CommonTypes.Structs;
|
using Aaru.CommonTypes.Structs;
|
||||||
@@ -40,15 +39,6 @@ public sealed partial class Zoo
|
|||||||
{
|
{
|
||||||
#region IArchive Members
|
#region IArchive Members
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public ErrorNumber Open(IFilter filter, Encoding encoding) => throw new NotImplementedException();
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public void Close()
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public ErrorNumber GetFilename(int entryNumber, out string fileName) => throw new NotImplementedException();
|
public ErrorNumber GetFilename(int entryNumber, out string fileName) => throw new NotImplementedException();
|
||||||
|
|
||||||
|
|||||||
@@ -27,13 +27,16 @@
|
|||||||
// ****************************************************************************/
|
// ****************************************************************************/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.IO;
|
||||||
using Aaru.CommonTypes.Interfaces;
|
using Aaru.CommonTypes.Interfaces;
|
||||||
|
|
||||||
namespace Aaru.Archives;
|
namespace Aaru.Archives;
|
||||||
|
|
||||||
public sealed partial class Zoo : IArchive
|
public sealed partial class Zoo : IArchive
|
||||||
{
|
{
|
||||||
const string MODULE_NAME = "zoo Archive Plugin";
|
const string MODULE_NAME = "zoo Archive Plugin";
|
||||||
|
ArchiveSupportedFeature _features;
|
||||||
|
Stream _stream;
|
||||||
|
|
||||||
#region IArchive Members
|
#region IArchive Members
|
||||||
|
|
||||||
@@ -44,15 +47,18 @@ public sealed partial class Zoo : IArchive
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string Author => Authors.NataliaPortillo;
|
public string Author => Authors.NataliaPortillo;
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public bool Opened { get; }
|
public bool Opened { get; private set; }
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public ArchiveSupportedFeature ArchiveFeatures => ArchiveSupportedFeature.HasEntryTimestamp |
|
public ArchiveSupportedFeature ArchiveFeatures => !Opened
|
||||||
ArchiveSupportedFeature.SupportsCompression |
|
? ArchiveSupportedFeature.SupportsFilenames |
|
||||||
ArchiveSupportedFeature.SupportsFilenames |
|
ArchiveSupportedFeature.SupportsCompression |
|
||||||
ArchiveSupportedFeature.SupportsSubdirectories |
|
ArchiveSupportedFeature.SupportsSubdirectories |
|
||||||
ArchiveSupportedFeature.SupportsXAttrs;
|
ArchiveSupportedFeature.HasEntryTimestamp |
|
||||||
|
ArchiveSupportedFeature.SupportsXAttrs
|
||||||
|
: _features;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public int NumberOfEntries { get; }
|
public int NumberOfEntries => Opened ? _files.Count : -1;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user