mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
[AMG] Implement Open and Close.
This commit is contained in:
@@ -1,10 +1,15 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using Aaru.CommonTypes.Interfaces;
|
using Aaru.CommonTypes.Interfaces;
|
||||||
|
|
||||||
namespace Aaru.Archives;
|
namespace Aaru.Archives;
|
||||||
|
|
||||||
public sealed partial class Amg : IArchive
|
public sealed partial class Amg : IArchive
|
||||||
{
|
{
|
||||||
|
List<FileEntry> _files;
|
||||||
|
Stream _stream;
|
||||||
|
|
||||||
#region IArchive Members
|
#region IArchive Members
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -14,14 +19,14 @@ public sealed partial class Amg : 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 => ArchiveSupportedFeature.HasEntryTimestamp |
|
||||||
ArchiveSupportedFeature.SupportsCompression |
|
ArchiveSupportedFeature.SupportsCompression |
|
||||||
ArchiveSupportedFeature.SupportsFilenames |
|
ArchiveSupportedFeature.SupportsFilenames |
|
||||||
ArchiveSupportedFeature.SupportsSubdirectories;
|
ArchiveSupportedFeature.SupportsSubdirectories;
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public int NumberOfEntries { get; }
|
public int NumberOfEntries => Opened ? _files.Count : -1;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
@@ -2,5 +2,6 @@ namespace Aaru.Archives;
|
|||||||
|
|
||||||
public sealed partial class Amg
|
public sealed partial class Amg
|
||||||
{
|
{
|
||||||
const ushort ARC_MAGIC = 0x36AD;
|
const ushort ARC_MAGIC = 0x36AD;
|
||||||
|
const ushort FILE_MAGIC = 0x1C94;
|
||||||
}
|
}
|
||||||
109
Aaru.Archives/Amg/Open.cs
Normal file
109
Aaru.Archives/Amg/Open.cs
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using Aaru.CommonTypes.Enums;
|
||||||
|
using Aaru.CommonTypes.Interfaces;
|
||||||
|
using Aaru.Helpers;
|
||||||
|
|
||||||
|
namespace Aaru.Archives;
|
||||||
|
|
||||||
|
public sealed partial class Amg
|
||||||
|
{
|
||||||
|
#region IArchive Members
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public ErrorNumber Open(IFilter filter, Encoding encoding)
|
||||||
|
{
|
||||||
|
encoding ??= Encoding.ASCII;
|
||||||
|
|
||||||
|
if(filter.DataForkLength < Marshal.SizeOf<ArcHeader>()) return ErrorNumber.InvalidArgument;
|
||||||
|
|
||||||
|
_stream = filter.GetDataForkStream();
|
||||||
|
_stream.Position = 0;
|
||||||
|
|
||||||
|
byte[] hdr = new byte[Marshal.SizeOf<ArcHeader>()];
|
||||||
|
|
||||||
|
_stream.ReadExactly(hdr, 0, hdr.Length);
|
||||||
|
|
||||||
|
ArcHeader header = Marshal.ByteArrayToStructureLittleEndian<ArcHeader>(hdr);
|
||||||
|
|
||||||
|
// Not a valid magic
|
||||||
|
if(header.magic != ARC_MAGIC) return ErrorNumber.InvalidArgument;
|
||||||
|
|
||||||
|
|
||||||
|
// Skip comment
|
||||||
|
_stream.Position += header.commentLength;
|
||||||
|
|
||||||
|
int fileHeaderLen = Marshal.SizeOf<FileHeader>();
|
||||||
|
|
||||||
|
_files = [];
|
||||||
|
|
||||||
|
while(_stream.Position + fileHeaderLen < _stream.Length)
|
||||||
|
{
|
||||||
|
byte[] fileHdr = new byte[fileHeaderLen];
|
||||||
|
|
||||||
|
_stream.ReadExactly(fileHdr, 0, fileHdr.Length);
|
||||||
|
|
||||||
|
FileHeader fh = Marshal.ByteArrayToStructureLittleEndian<FileHeader>(fileHdr);
|
||||||
|
|
||||||
|
// Not a valid file magic
|
||||||
|
if(fh.magic != FILE_MAGIC) break;
|
||||||
|
|
||||||
|
var entry = new FileEntry
|
||||||
|
{
|
||||||
|
Attributes = (FileAttributes)fh.attr,
|
||||||
|
Compressed = (uint)(fh.compressed - fh.pathLength - fh.commentLength - fileHeaderLen),
|
||||||
|
Crc = fh.crc,
|
||||||
|
Flags = fh.flags,
|
||||||
|
LastWrite = DateHandlers.DosToDateTime(fh.date, fh.time),
|
||||||
|
Uncompressed = fh.uncompressed,
|
||||||
|
Filename = StringHandlers.CToString(fh.filename, encoding)
|
||||||
|
};
|
||||||
|
|
||||||
|
string extension = StringHandlers.CToString(fh.extension, encoding);
|
||||||
|
|
||||||
|
if(!string.IsNullOrEmpty(extension)) entry.Filename += "." + extension;
|
||||||
|
|
||||||
|
if(fh.pathLength > 0)
|
||||||
|
{
|
||||||
|
byte[] buffer = new byte[fh.pathLength];
|
||||||
|
_stream.ReadExactly(buffer, 0, buffer.Length);
|
||||||
|
string path = StringHandlers.CToString(buffer, encoding);
|
||||||
|
path = path.Replace('\\', Path.DirectorySeparatorChar);
|
||||||
|
entry.Filename = Path.Combine(path, entry.Filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fh.commentLength > 0)
|
||||||
|
{
|
||||||
|
byte[] buffer = new byte[fh.commentLength];
|
||||||
|
_stream.ReadExactly(buffer, 0, buffer.Length);
|
||||||
|
entry.Comment = StringHandlers.CToString(buffer, encoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
entry.Offset = _stream.Position;
|
||||||
|
|
||||||
|
_files.Add(entry);
|
||||||
|
|
||||||
|
// Skip compressed data
|
||||||
|
_stream.Position += entry.Compressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
Opened = true;
|
||||||
|
|
||||||
|
return ErrorNumber.NoError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
// Already closed
|
||||||
|
if(!Opened) return;
|
||||||
|
|
||||||
|
_stream?.Close();
|
||||||
|
_files?.Clear();
|
||||||
|
|
||||||
|
_stream = null;
|
||||||
|
Opened = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Aaru.Archives;
|
namespace Aaru.Archives;
|
||||||
@@ -17,5 +19,50 @@ public sealed partial class Amg
|
|||||||
public readonly ushort commentLength;
|
public readonly ushort commentLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Nested type: FileEntry
|
||||||
|
|
||||||
|
struct FileEntry
|
||||||
|
{
|
||||||
|
public uint Uncompressed;
|
||||||
|
public uint Compressed;
|
||||||
|
public DateTime LastWrite;
|
||||||
|
public FileAttributes Attributes;
|
||||||
|
public byte Flags;
|
||||||
|
public uint Crc;
|
||||||
|
public string Filename;
|
||||||
|
public string Comment;
|
||||||
|
public long Offset;
|
||||||
|
|
||||||
|
public override string ToString() => Filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Nested type: FileHeader
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
|
||||||
|
readonly struct FileHeader
|
||||||
|
{
|
||||||
|
public readonly ushort magic;
|
||||||
|
public readonly uint compressed;
|
||||||
|
public readonly uint uncompressed;
|
||||||
|
public readonly ushort time;
|
||||||
|
public readonly ushort date;
|
||||||
|
public readonly byte attr;
|
||||||
|
public readonly byte flags;
|
||||||
|
|
||||||
|
// Something changes in processing when 0x80 is set
|
||||||
|
public readonly byte unknown;
|
||||||
|
public readonly uint crc;
|
||||||
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
|
||||||
|
public readonly byte[] filename;
|
||||||
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
|
||||||
|
public readonly byte[] extension;
|
||||||
|
public readonly byte pathLength;
|
||||||
|
public readonly ushort commentLength;
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
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;
|
||||||
@@ -12,15 +11,6 @@ public sealed partial class Amg
|
|||||||
{
|
{
|
||||||
#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();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user