mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
109 lines
3.1 KiB
C#
109 lines
3.1 KiB
C#
|
|
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
|
||
|
|
}
|