mirror of
https://github.com/SabreTools/SabreTools.Compression.git
synced 2026-07-09 02:16:47 +00:00
Checkpoint (nw)
This commit is contained in:
@@ -3,7 +3,7 @@ namespace SabreTools.Compression.libmspack
|
||||
/// <summary>
|
||||
/// Base class for all decompressor implementations
|
||||
/// </summary>
|
||||
public abstract class Decompressor : mspack_file
|
||||
public abstract class BaseDecompressor : mspack_file
|
||||
{
|
||||
#if NET48
|
||||
public mspack_system system { get; set; }
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using static SabreTools.Compression.libmspack.cab;
|
||||
using static SabreTools.Compression.libmspack.CAB.Constants;
|
||||
|
||||
namespace SabreTools.Compression.libmspack
|
||||
namespace SabreTools.Compression.libmspack.CAB
|
||||
{
|
||||
public unsafe class mspack_mscab_system : mspack_default_system
|
||||
public unsafe class CABSystem : mspack_default_system
|
||||
{
|
||||
/// <summary>
|
||||
/// cabd_sys_read is the internal reader function which the decompressors
|
||||
@@ -11,12 +11,12 @@ namespace SabreTools.Compression.libmspack
|
||||
/// </summary>
|
||||
public override unsafe int read(mspack_file file, void* buffer, int bytes)
|
||||
{
|
||||
mscab_decompressor self = (mscab_decompressor)file;
|
||||
Decompressor self = (Decompressor)file;
|
||||
byte* buf = (byte*)buffer;
|
||||
mspack_system sys = self.system;
|
||||
int avail, todo, outlen, ignore_cksum, ignore_blocksize;
|
||||
int avail, todo, outlen = 0, ignore_cksum, ignore_blocksize;
|
||||
|
||||
ignore_cksum = self.salvage != 0 || (self.fix_mszip != 0 && (((int)self.d.comp_type & cffoldCOMPTYPE_MASK) == cffoldCOMPTYPE_MSZIP)) == true ? 1 : 0;
|
||||
ignore_cksum = self.salvage != 0 || (self.fix_mszip != 0 && ((MSCAB_COMP)((int)self.d.comp_type & cffoldCOMPTYPE_MASK) == MSCAB_COMP.MSCAB_COMP_MSZIP)) == true ? 1 : 0;
|
||||
ignore_blocksize = self.salvage;
|
||||
|
||||
todo = bytes;
|
||||
@@ -53,14 +53,14 @@ namespace SabreTools.Compression.libmspack
|
||||
}
|
||||
|
||||
// Read a block
|
||||
self.read_error = cabd_sys_read_block(sys, self.d, ref outlen, ignore_cksum, ignore_blocksize);
|
||||
self.read_error = ReadBlock(sys, self.d, ref outlen, ignore_cksum, ignore_blocksize);
|
||||
if (self.read_error != MSPACK_ERR.MSPACK_ERR_OK) return -1;
|
||||
self.d.outlen += outlen;
|
||||
|
||||
// Special Quantum hack -- trailer byte to allow the decompressor
|
||||
// to realign itself. CAB Quantum blocks, unlike LZX blocks, can have
|
||||
// anything from 0 to 4 trailing null bytes.
|
||||
if (((int)self.d.comp_type & cffoldCOMPTYPE_MASK) == cffoldCOMPTYPE_QUANTUM)
|
||||
if ((MSCAB_COMP)((int)self.d.comp_type & cffoldCOMPTYPE_MASK) == MSCAB_COMP.MSCAB_COMP_QUANTUM)
|
||||
{
|
||||
*self.d.i_end++ = 0xFF;
|
||||
}
|
||||
@@ -68,10 +68,10 @@ namespace SabreTools.Compression.libmspack
|
||||
// Is this the last block?
|
||||
if (self.d.block >= self.d.folder.num_blocks)
|
||||
{
|
||||
if (((int)self.d.comp_type & cffoldCOMPTYPE_MASK) == cffoldCOMPTYPE_LZX)
|
||||
if ((MSCAB_COMP)((int)self.d.comp_type & cffoldCOMPTYPE_MASK) == MSCAB_COMP.MSCAB_COMP_LZX)
|
||||
{
|
||||
/* special LZX hack -- on the last block, inform LZX of the
|
||||
* size of the output data stream. */
|
||||
// Special LZX hack -- on the last block, inform LZX of the
|
||||
// size of the output data stream.
|
||||
lzxd_set_output_length((lzxd_stream)self.d.state, self.d.outlen);
|
||||
}
|
||||
}
|
||||
@@ -88,7 +88,7 @@ namespace SabreTools.Compression.libmspack
|
||||
/// </summary>
|
||||
public override unsafe int write(mspack_file file, void* buffer, int bytes)
|
||||
{
|
||||
mscab_decompressor self = (mscab_decompressor)file;
|
||||
Decompressor self = (Decompressor)file;
|
||||
self.d.offset += (uint)bytes;
|
||||
if (self.d.outfh != null)
|
||||
{
|
||||
@@ -101,7 +101,7 @@ namespace SabreTools.Compression.libmspack
|
||||
/// Reads a whole data block from a cab file. the block may span more than
|
||||
/// one cab file, if it does then the fragments will be reassembled
|
||||
/// </summary>
|
||||
private static MSPACK_ERR cabd_sys_read_block(mspack_system sys, mscabd_decompress_state d, ref int @out, int ignore_cksum, int ignore_blocksize)
|
||||
private static MSPACK_ERR ReadBlock(mspack_system sys, mscabd_decompress_state d, ref int @out, int ignore_cksum, int ignore_blocksize)
|
||||
{
|
||||
byte[] hdr = new byte[cfdata_SIZEOF];
|
||||
uint cksum;
|
||||
@@ -126,7 +126,7 @@ namespace SabreTools.Compression.libmspack
|
||||
}
|
||||
|
||||
// Blocks must not be over CAB_INPUTMAX in size
|
||||
len = EndGetI16(&hdr[cfdata_CompressedSize]);
|
||||
len = System.BitConverter.ToUInt16(hdr, cfdata_CompressedSize);
|
||||
full_len = (int)(d.i_end - d.i_ptr + len); // Include cab-spanning blocks */
|
||||
if (full_len > CAB_INPUTMAX)
|
||||
{
|
||||
@@ -139,7 +139,7 @@ namespace SabreTools.Compression.libmspack
|
||||
}
|
||||
|
||||
// Blocks must not expand to more than CAB_BLOCKMAX
|
||||
if (EndGetI16(&hdr[cfdata_UncompressedSize]) > CAB_BLOCKMAX)
|
||||
if (System.BitConverter.ToUInt16(hdr, cfdata_UncompressedSize) > CAB_BLOCKMAX)
|
||||
{
|
||||
System.Console.Error.WriteLine("block size > CAB_BLOCKMAX");
|
||||
if (ignore_blocksize == 0) return MSPACK_ERR.MSPACK_ERR_DATAFORMAT;
|
||||
@@ -152,10 +152,10 @@ namespace SabreTools.Compression.libmspack
|
||||
}
|
||||
|
||||
// Perform checksum test on the block (if one is stored)
|
||||
if ((cksum = EndGetI32(&hdr[cfdata_CheckSum])))
|
||||
if ((cksum = System.BitConverter.ToUInt32(hdr, cfdata_CheckSum)) != 0)
|
||||
{
|
||||
uint sum2 = cabd_checksum(d.i_end, (uint)len, 0);
|
||||
if (cabd_checksum(&hdr[4], 4, sum2) != cksum)
|
||||
uint sum2 = Checksum(d.i_end, (uint)len, 0);
|
||||
if (Checksum(&hdr[4], 4, sum2) != cksum)
|
||||
{
|
||||
if (ignore_cksum == 0) return MSPACK_ERR.MSPACK_ERR_CHECKSUM;
|
||||
sys.message(d.infh, "WARNING; bad block checksum found");
|
||||
@@ -171,7 +171,7 @@ namespace SabreTools.Compression.libmspack
|
||||
// reading needs to be done.
|
||||
|
||||
// EXIT POINT OF LOOP -- uncompressed size != 0
|
||||
if ((@out = EndGetI16(&hdr[cfdata_UncompressedSize])))
|
||||
if ((@out = System.BitConverter.ToInt16(hdr, cfdata_UncompressedSize)) != 0)
|
||||
{
|
||||
return MSPACK_ERR.MSPACK_ERR_OK;
|
||||
}
|
||||
@@ -207,13 +207,13 @@ namespace SabreTools.Compression.libmspack
|
||||
return MSPACK_ERR.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
private static uint cabd_checksum(byte* data, uint bytes, uint cksum)
|
||||
private static uint Checksum(byte* data, uint bytes, uint cksum)
|
||||
{
|
||||
uint len, ul = 0;
|
||||
|
||||
for (len = bytes >> 2; len-- > 0; data += 4)
|
||||
{
|
||||
cksum ^= EndGetI32(data);
|
||||
cksum ^= System.BitConverter.ToInt32(data, 0);
|
||||
}
|
||||
|
||||
switch (bytes & 3)
|
||||
1217
libmspack/CAB/Decompressor.cs
Normal file
1217
libmspack/CAB/Decompressor.cs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,5 @@
|
||||
using static SabreTools.Compression.libmspack.CAB.Constants;
|
||||
|
||||
namespace SabreTools.Compression.libmspack
|
||||
{
|
||||
public unsafe static class cab
|
||||
@@ -8,7 +10,7 @@ namespace SabreTools.Compression.libmspack
|
||||
/// cabd_free_decomp frees decompression state, according to which method
|
||||
/// was used.
|
||||
/// </summary>
|
||||
public static MSPACK_ERR cabd_init_decomp(mscab_decompressor self, MSCAB_COMP ct)
|
||||
public static MSPACK_ERR cabd_init_decomp(CAB.Decompressor self, MSCAB_COMP ct)
|
||||
{
|
||||
mspack_file fh = self;
|
||||
|
||||
@@ -43,7 +45,7 @@ namespace SabreTools.Compression.libmspack
|
||||
/// decompression method was used. relies on self.d.folder being the same
|
||||
/// as when initialised.
|
||||
/// </summary>
|
||||
public static void cabd_free_decomp(mscab_decompressor self)
|
||||
public static void cabd_free_decomp(CAB.Decompressor self)
|
||||
{
|
||||
if (self == null || self.d == null || self.d.state == null) return;
|
||||
|
||||
|
||||
@@ -1,649 +0,0 @@
|
||||
using static SabreTools.Compression.libmspack.cab;
|
||||
using static SabreTools.Compression.libmspack.CAB.Constants;
|
||||
|
||||
namespace SabreTools.Compression.libmspack
|
||||
{
|
||||
/// <summary>
|
||||
/// A decompressor for .CAB (Microsoft Cabinet) files
|
||||
///
|
||||
/// All fields are READ ONLY.
|
||||
/// </summary>
|
||||
/// <see cref="mspack_create_cab_decompressor()"/>
|
||||
/// <see cref="mspack_destroy_cab_decompressor()"/>
|
||||
public unsafe class mscab_decompressor : Decompressor
|
||||
{
|
||||
public mscabd_decompress_state d { get; set; }
|
||||
|
||||
public int buf_size { get; set; }
|
||||
|
||||
public int searchbuf_size { get; set; }
|
||||
|
||||
public int fix_mszip { get; set; }
|
||||
|
||||
public int salvage { get; set; }
|
||||
|
||||
public MSPACK_ERR read_error { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Opens a cabinet file and reads its contents.
|
||||
///
|
||||
/// If the file opened is a valid cabinet file, all headers will be read
|
||||
/// and a mscabd_cabinet structure will be returned, with a full list of
|
||||
/// folders and files.
|
||||
///
|
||||
/// In the case of an error occuring, null is returned and the error code
|
||||
/// is available from last_error().
|
||||
///
|
||||
/// The filename pointer should be considered "in use" until close() is
|
||||
/// called on the cabinet.
|
||||
/// </summary>
|
||||
/// <param name="filename">
|
||||
/// The filename of the cabinet file. This is passed
|
||||
/// directly to mspack_system::open().
|
||||
/// </param>
|
||||
/// <returns>A pointer to a mscabd_cabinet structure, or null on failure</returns>
|
||||
/// <see cref="close(mscabd_cabinet)"/>
|
||||
/// <see cref="search(in string)"/>
|
||||
/// <see cref="last_error()"/>
|
||||
public mscabd_cabinet open(in string filename)
|
||||
{
|
||||
mscabd_cabinet cab = null;
|
||||
mspack_file fh;
|
||||
MSPACK_ERR error;
|
||||
|
||||
mspack_system sys = this.system;
|
||||
if ((fh = sys.open(filename, MSPACK_SYS_OPEN.MSPACK_SYS_OPEN_READ)) != null)
|
||||
{
|
||||
cab = new mscabd_cabinet();
|
||||
cab.filename = filename;
|
||||
error = cabd_read_headers(sys, fh, cab, 0, this.salvage, 0);
|
||||
if (error != MSPACK_ERR.MSPACK_ERR_OK)
|
||||
{
|
||||
close(cab);
|
||||
cab = null;
|
||||
}
|
||||
this.error = error;
|
||||
sys.close(fh);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.error = MSPACK_ERR.MSPACK_ERR_OPEN;
|
||||
}
|
||||
|
||||
return cab;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Closes a previously opened cabinet or cabinet set.
|
||||
///
|
||||
/// This closes a cabinet, all cabinets associated with it via the
|
||||
/// mscabd_cabinet::next, mscabd_cabinet::prevcab and
|
||||
/// mscabd_cabinet::nextcab pointers, and all folders and files. All
|
||||
/// memory used by these entities is freed.
|
||||
///
|
||||
/// The cabinet pointer is now invalid and cannot be used again. All
|
||||
/// mscabd_folder and mscabd_file pointers from that cabinet or cabinet
|
||||
/// set are also now invalid, and cannot be used again.
|
||||
///
|
||||
/// If the cabinet pointer given was created using search(), it MUST be
|
||||
/// the cabinet pointer returned by search() and not one of the later
|
||||
/// cabinet pointers further along the mscabd_cabinet::next chain.
|
||||
///
|
||||
/// If extra cabinets have been added using append() or prepend(), these
|
||||
/// will all be freed, even if the cabinet pointer given is not the first
|
||||
/// cabinet in the set. Do NOT close() more than one cabinet in the set.
|
||||
///
|
||||
/// The mscabd_cabinet::filename is not freed by the library, as it is
|
||||
/// not allocated by the library. The caller should free this itself if
|
||||
/// necessary, before it is lost forever.
|
||||
/// </summary>
|
||||
/// <param name="cab">The cabinet to close</param>
|
||||
/// <see cref="open(in string)"/>
|
||||
/// <see cref="search(in string)"/>
|
||||
/// <see cref="append(mscabd_cabinet, mscabd_cabinet)"/>
|
||||
/// <see cref="prepend(mscabd_cabinet, mscabd_cabinet)"/>
|
||||
public void close(mscabd_cabinet origcab)
|
||||
{
|
||||
mscabd_folder_data dat, ndat;
|
||||
mscabd_cabinet cab, ncab;
|
||||
mscabd_folder fol, nfol;
|
||||
mscabd_file fi, nfi;
|
||||
|
||||
mspack_system sys = this.system;
|
||||
|
||||
this.error = MSPACK_ERR.MSPACK_ERR_OK;
|
||||
|
||||
while (origcab != null)
|
||||
{
|
||||
// Free files
|
||||
for (fi = origcab.files; fi != null; fi = nfi)
|
||||
{
|
||||
nfi = fi.next;
|
||||
//sys.free(fi.filename);
|
||||
//sys.free(fi);
|
||||
}
|
||||
|
||||
// Free folders
|
||||
for (fol = origcab.folders; fol != null; fol = nfol)
|
||||
{
|
||||
nfol = fol.next;
|
||||
|
||||
// Free folder decompression state if it has been decompressed
|
||||
if (this.d != null && (this.d.folder == fol))
|
||||
{
|
||||
if (this.d.infh != null) sys.close(this.d.infh);
|
||||
cabd_free_decomp(this);
|
||||
//sys.free(this.d);
|
||||
this.d = null;
|
||||
}
|
||||
|
||||
// Free folder data segments
|
||||
for (dat = fol.data.next; dat != null; dat = ndat)
|
||||
{
|
||||
ndat = dat.next;
|
||||
//sys.free(dat);
|
||||
}
|
||||
|
||||
//sys.free(fol);
|
||||
}
|
||||
|
||||
// Free predecessor cabinets (and the original cabinet's strings)
|
||||
for (cab = origcab; cab != null; cab = ncab)
|
||||
{
|
||||
ncab = cab.prevcab;
|
||||
//sys.free(cab.prevname);
|
||||
//sys.free(cab.nextname);
|
||||
//sys.free(cab.previnfo);
|
||||
//sys.free(cab.nextinfo);
|
||||
//if (cab != origcab) sys.free(cab);
|
||||
}
|
||||
|
||||
// Free successor cabinets
|
||||
for (cab = origcab.nextcab; cab != null; cab = ncab)
|
||||
{
|
||||
ncab = cab.nextcab;
|
||||
//sys.free(cab.prevname);
|
||||
//sys.free(cab.nextname);
|
||||
//sys.free(cab.previnfo);
|
||||
//sys.free(cab.nextinfo);
|
||||
//sys.free(cab);
|
||||
}
|
||||
|
||||
// Free actual cabinet structure
|
||||
cab = origcab.next;
|
||||
//sys.free(origcab);
|
||||
|
||||
// Repeat full procedure again with the cab.next pointer (if set)
|
||||
origcab = cab;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the cabinet file header, folder list and file list.
|
||||
/// Fills out a pre-existing mscabd_cabinet structure, allocates memory
|
||||
/// for folders and files as necessary
|
||||
/// </summary>
|
||||
private static MSPACK_ERR cabd_read_headers(mspack_system sys, mspack_file fh, mscabd_cabinet cab, long offset, int salvage, int quiet)
|
||||
{
|
||||
int num_folders, num_files, folder_resv, i, x, fidx;
|
||||
MSPACK_ERR err;
|
||||
mscabd_folder fol, linkfol = null;
|
||||
mscabd_file file, linkfile = null;
|
||||
byte[] buf = new byte[64];
|
||||
|
||||
// Initialise pointers
|
||||
cab.next = null;
|
||||
cab.files = null;
|
||||
cab.folders = null;
|
||||
cab.prevcab = cab.nextcab = null;
|
||||
cab.prevname = cab.nextname = null;
|
||||
cab.previnfo = cab.nextinfo = null;
|
||||
|
||||
cab.base_offset = offset;
|
||||
|
||||
// Seek to CFHEADER
|
||||
if (sys.seek(fh, offset, MSPACK_SYS_SEEK.MSPACK_SYS_SEEK_START) != 0)
|
||||
{
|
||||
return MSPACK_ERR.MSPACK_ERR_SEEK;
|
||||
}
|
||||
|
||||
// Read in the CFHEADER
|
||||
if (sys.read(fh, libmspack.system.GetArrayPointer(buf), cfhead_SIZEOF) != cfhead_SIZEOF)
|
||||
{
|
||||
return MSPACK_ERR.MSPACK_ERR_READ;
|
||||
}
|
||||
|
||||
// Check for "MSCF" signature
|
||||
if (EndGetI32((byte*)buf[cfhead_Signature]) != 0x4643534D)
|
||||
{
|
||||
return MSPACK_ERR.MSPACK_ERR_SIGNATURE;
|
||||
}
|
||||
|
||||
// Some basic header fields
|
||||
cab.length = EndGetI32((byte*)buf[cfhead_CabinetSize]);
|
||||
cab.set_id = EndGetI16((byte*)buf[cfhead_SetID]);
|
||||
cab.set_index = EndGetI16((byte*)buf[cfhead_CabinetIndex]);
|
||||
|
||||
// Get the number of folders
|
||||
num_folders = EndGetI16((byte*)buf[cfhead_NumFolders]);
|
||||
if (num_folders == 0)
|
||||
{
|
||||
if (quiet == 0) sys.message(fh, "No folders in cabinet.");
|
||||
return MSPACK_ERR.MSPACK_ERR_DATAFORMAT;
|
||||
}
|
||||
|
||||
// Get the number of files
|
||||
num_files = EndGetI16((byte*)buf[cfhead_NumFiles]);
|
||||
if (num_files == 0)
|
||||
{
|
||||
if (quiet == 0) sys.message(fh, "no files in cabinet.");
|
||||
return MSPACK_ERR.MSPACK_ERR_DATAFORMAT;
|
||||
}
|
||||
|
||||
// Check cabinet version
|
||||
if ((buf[cfhead_MajorVersion] != 1) && (buf[cfhead_MinorVersion] != 3))
|
||||
{
|
||||
if (quiet == 0) sys.message(fh, "WARNING; cabinet version is not 1.3");
|
||||
}
|
||||
|
||||
// Read the reserved-sizes part of header, if present
|
||||
cab.flags = EndGetI16((byte*)buf[cfhead_Flags]);
|
||||
|
||||
if (cab.flags.HasFlag(MSCAB_HDR.MSCAB_HDR_RESV))
|
||||
{
|
||||
if (sys.read(fh, libmspack.system.GetArrayPointer(buf), cfheadext_SIZEOF) != cfheadext_SIZEOF)
|
||||
{
|
||||
return MSPACK_ERR.MSPACK_ERR_READ;
|
||||
}
|
||||
cab.header_resv = EndGetI16((byte*)buf[cfheadext_HeaderReserved]);
|
||||
folder_resv = buf[cfheadext_FolderReserved];
|
||||
cab.block_resv = buf[cfheadext_DataReserved];
|
||||
|
||||
if (cab.header_resv > 60000)
|
||||
{
|
||||
if (quiet == 0) sys.message(fh, "WARNING; reserved header > 60000.");
|
||||
}
|
||||
|
||||
// Skip the reserved header
|
||||
if (cab.header_resv != 0)
|
||||
{
|
||||
if (sys.seek(fh, cab.header_resv, MSPACK_SYS_SEEK.MSPACK_SYS_SEEK_CUR) != 0)
|
||||
{
|
||||
return MSPACK_ERR.MSPACK_ERR_SEEK;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cab.header_resv = 0;
|
||||
folder_resv = 0;
|
||||
cab.block_resv = 0;
|
||||
}
|
||||
|
||||
// Read name and info of preceeding cabinet in set, if present
|
||||
if (cab.flags.HasFlag(MSCAB_HDR.MSCAB_HDR_PREVCAB))
|
||||
{
|
||||
cab.prevname = cabd_read_string(sys, fh, 0, out err);
|
||||
if (err != MSPACK_ERR.MSPACK_ERR_OK) return err;
|
||||
cab.previnfo = cabd_read_string(sys, fh, 1, out err);
|
||||
if (err != MSPACK_ERR.MSPACK_ERR_OK) return err;
|
||||
}
|
||||
|
||||
// Read name and info of next cabinet in set, if present
|
||||
if (cab.flags.HasFlag(MSCAB_HDR.MSCAB_HDR_NEXTCAB))
|
||||
{
|
||||
cab.nextname = cabd_read_string(sys, fh, 0, out err);
|
||||
if (err != MSPACK_ERR.MSPACK_ERR_OK) return err;
|
||||
cab.nextinfo = cabd_read_string(sys, fh, 1, out err);
|
||||
if (err != MSPACK_ERR.MSPACK_ERR_OK) return err;
|
||||
}
|
||||
|
||||
// Read folders
|
||||
for (i = 0; i < num_folders; i++)
|
||||
{
|
||||
if (sys.read(fh, libmspack.system.GetArrayPointer(buf), cffold_SIZEOF) != cffold_SIZEOF)
|
||||
{
|
||||
return MSPACK_ERR.MSPACK_ERR_READ;
|
||||
}
|
||||
if (folder_resv != 0)
|
||||
{
|
||||
if (sys.seek(fh, folder_resv, MSPACK_SYS_SEEK.MSPACK_SYS_SEEK_CUR) != 0)
|
||||
{
|
||||
return MSPACK_ERR.MSPACK_ERR_SEEK;
|
||||
}
|
||||
}
|
||||
|
||||
fol = new mscabd_folder();
|
||||
|
||||
fol.next = null;
|
||||
fol.comp_type = EndGetI16((byte*)buf[cffold_CompType]);
|
||||
fol.num_blocks = EndGetI16((byte*)buf[cffold_NumBlocks]);
|
||||
fol.data.next = null;
|
||||
fol.data.cab = cab;
|
||||
fol.data.offset = offset + (long)((uint)EndGetI32((byte*)buf[cffold_DataOffset]));
|
||||
fol.merge_prev = null;
|
||||
fol.merge_next = null;
|
||||
|
||||
// Link folder into list of folders
|
||||
if (linkfol == null) cab.folders = fol;
|
||||
else linkfol.next = fol;
|
||||
linkfol = fol;
|
||||
}
|
||||
|
||||
// Read files
|
||||
for (i = 0; i < num_files; i++)
|
||||
{
|
||||
if (sys.read(fh, libmspack.system.GetArrayPointer(buf), cffile_SIZEOF) != cffile_SIZEOF)
|
||||
{
|
||||
return MSPACK_ERR.MSPACK_ERR_READ;
|
||||
}
|
||||
|
||||
file = new mscabd_file();
|
||||
|
||||
file.next = null;
|
||||
file.length = EndGetI32((byte*)buf[cffile_UncompressedSize]);
|
||||
file.attribs = EndGetI16((byte*)buf[cffile_Attribs]);
|
||||
file.offset = EndGetI32((byte*)buf[cffile_FolderOffset]);
|
||||
|
||||
// Set folder pointer
|
||||
fidx = EndGetI16((byte*)buf[cffile_FolderIndex]);
|
||||
if (fidx < cffileCONTINUED_FROM_PREV)
|
||||
{
|
||||
/* normal folder index; count up to the correct folder */
|
||||
if (fidx < num_folders)
|
||||
{
|
||||
mscabd_folder ifol = cab.folders;
|
||||
while (fidx-- > 0) if (ifol != null) ifol = ifol.next;
|
||||
file.folder = ifol;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.Console.Error.WriteLine("Invalid folder index");
|
||||
file.folder = null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// either CONTINUED_TO_NEXT, CONTINUED_FROM_PREV or CONTINUED_PREV_AND_NEXT
|
||||
if ((fidx == cffileCONTINUED_TO_NEXT) || (fidx == cffileCONTINUED_PREV_AND_NEXT))
|
||||
{
|
||||
// Get last folder
|
||||
mscabd_folder ifol = cab.folders;
|
||||
while (ifol.next != null) ifol = ifol.next;
|
||||
file.folder = ifol;
|
||||
|
||||
// Set "merge next" pointer
|
||||
fol = ifol;
|
||||
if (fol.merge_next == null) fol.merge_next = file;
|
||||
}
|
||||
|
||||
if ((fidx == cffileCONTINUED_FROM_PREV) || (fidx == cffileCONTINUED_PREV_AND_NEXT))
|
||||
{
|
||||
// Get first folder
|
||||
file.folder = cab.folders;
|
||||
|
||||
// Set "merge prev" pointer
|
||||
fol = file.folder;
|
||||
if (fol.merge_prev == null) fol.merge_prev = file;
|
||||
}
|
||||
}
|
||||
|
||||
// Get time
|
||||
x = EndGetI16((byte*)buf[cffile_Time]);
|
||||
file.time_h = (char)(x >> 11);
|
||||
file.time_m = (char)((x >> 5) & 0x3F);
|
||||
file.time_s = (char)((x << 1) & 0x3E);
|
||||
|
||||
// Get date
|
||||
x = EndGetI16((byte*)buf[cffile_Date]);
|
||||
file.date_d = (char)(x & 0x1F);
|
||||
file.date_m = (char)((x >> 5) & 0xF);
|
||||
file.date_y = (x >> 9) + 1980;
|
||||
|
||||
// Get filename
|
||||
file.filename = cabd_read_string(sys, fh, 0, out err);
|
||||
|
||||
// If folder index or filename are bad, either skip it or fail
|
||||
if (err != MSPACK_ERR.MSPACK_ERR_OK || file.folder == null)
|
||||
{
|
||||
//sys.free(file.filename);
|
||||
//sys.free(file);
|
||||
if (salvage != 0) continue;
|
||||
return err != MSPACK_ERR.MSPACK_ERR_OK ? err : MSPACK_ERR.MSPACK_ERR_DATAFORMAT;
|
||||
}
|
||||
|
||||
// Link file entry into file list
|
||||
if (linkfile == null) cab.files = file;
|
||||
else linkfile.next = file;
|
||||
linkfile = file;
|
||||
}
|
||||
|
||||
if (cab.files == null)
|
||||
{
|
||||
// We never actually added any files to the file list. Something went wrong.
|
||||
// The file header may have been invalid
|
||||
|
||||
System.Console.Error.WriteLine($"No files found, even though header claimed to have {num_files} files");
|
||||
return MSPACK_ERR.MSPACK_ERR_DATAFORMAT;
|
||||
}
|
||||
|
||||
return MSPACK_ERR.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
private static string cabd_read_string(mspack_system sys, mspack_file fh, int permit_empty, out MSPACK_ERR error)
|
||||
{
|
||||
long @base = sys.tell(fh);
|
||||
byte[] buf = new byte[256];
|
||||
string str;
|
||||
int len, i, ok;
|
||||
|
||||
// Read up to 256 bytes */
|
||||
if ((len = sys.read(fh, libmspack.system.GetArrayPointer(buf), 256)) <= 0)
|
||||
{
|
||||
error = MSPACK_ERR.MSPACK_ERR_READ;
|
||||
return null;
|
||||
}
|
||||
|
||||
// Search for a null terminator in the buffer
|
||||
for (i = 0, ok = 0; i < len; i++) if (buf[i] == 0) { ok = 1; break; }
|
||||
/* optionally reject empty strings */
|
||||
if (i == 0 && permit_empty == 0) ok = 0;
|
||||
|
||||
if (ok == 0)
|
||||
{
|
||||
error = MSPACK_ERR.MSPACK_ERR_DATAFORMAT;
|
||||
return null;
|
||||
}
|
||||
|
||||
len = i + 1;
|
||||
|
||||
/* set the data stream to just after the string and return */
|
||||
if (sys.seek(fh, @base + len, MSPACK_SYS_SEEK.MSPACK_SYS_SEEK_START) != 0)
|
||||
{
|
||||
error = MSPACK_ERR.MSPACK_ERR_SEEK;
|
||||
return null;
|
||||
}
|
||||
|
||||
char[] strchr = new char[len];
|
||||
sys.copy(libmspack.system.GetArrayPointer(buf), libmspack.system.GetArrayPointer(strchr), len);
|
||||
str = new string(strchr);
|
||||
error = MSPACK_ERR.MSPACK_ERR_OK;
|
||||
return str;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Searches a regular file for embedded cabinets.
|
||||
///
|
||||
/// This opens a normal file with the given filename and will search the
|
||||
/// entire file for embedded cabinet files
|
||||
///
|
||||
/// If any cabinets are found, the equivalent of open() is called on each
|
||||
/// potential cabinet file at the offset it was found. All successfully
|
||||
/// open()ed cabinets are kept in a list.
|
||||
///
|
||||
/// The first cabinet found will be returned directly as the result of
|
||||
/// this method. Any further cabinets found will be chained in a list
|
||||
/// using the mscabd_cabinet::next field.
|
||||
///
|
||||
/// In the case of an error occuring anywhere other than the simulated
|
||||
/// open(), null is returned and the error code is available from
|
||||
/// last_error().
|
||||
///
|
||||
/// If no error occurs, but no cabinets can be found in the file, null is
|
||||
/// returned and last_error() returns MSPACK_ERR.MSPACK_ERR_OK.
|
||||
///
|
||||
/// The filename pointer should be considered in use until close() is
|
||||
/// called on the cabinet.
|
||||
///
|
||||
/// close() should only be called on the result of search(), not on any
|
||||
/// subsequent cabinets in the mscabd_cabinet::next chain.
|
||||
/// </summary>
|
||||
/// <param name="filename">
|
||||
/// The filename of the file to search for cabinets. This
|
||||
/// is passed directly to mspack_system::open().
|
||||
/// </param>
|
||||
/// <returns>A pointer to a mscabd_cabinet structure, or null</returns>
|
||||
/// <see cref="close(mscabd_cabinet)"/>
|
||||
/// <see cref="open(in string)"/>
|
||||
/// <see cref="last_error()"/>
|
||||
public mscabd_cabinet search(in string filename) => null;
|
||||
|
||||
/// <summary>
|
||||
/// Appends one mscabd_cabinet to another, forming or extending a cabinet
|
||||
/// set.
|
||||
///
|
||||
/// This will attempt to append one cabinet to another such that
|
||||
/// <tt>(cab.nextcab == nextcab) && (nextcab.prevcab == cab)</tt> and
|
||||
/// any folders split between the two cabinets are merged.
|
||||
///
|
||||
/// The cabinets MUST be part of a cabinet set -- a cabinet set is a
|
||||
/// cabinet that spans more than one physical cabinet file on disk -- and
|
||||
/// must be appropriately matched.
|
||||
///
|
||||
/// It can be determined if a cabinet has further parts to load by
|
||||
/// examining the mscabd_cabinet::flags field:
|
||||
///
|
||||
/// - if <tt>(flags & MSCAB_HDR_PREVCAB)</tt> is non-zero, there is a
|
||||
/// predecessor cabinet to open() and prepend(). Its MS-DOS
|
||||
/// case-insensitive filename is mscabd_cabinet::prevname
|
||||
/// - if <tt>(flags & MSCAB_HDR_NEXTCAB)</tt> is non-zero, there is a
|
||||
/// successor cabinet to open() and append(). Its MS-DOS case-insensitive
|
||||
/// filename is mscabd_cabinet::nextname
|
||||
///
|
||||
/// If the cabinets do not match, an error code will be returned. Neither
|
||||
/// cabinet has been altered, and both should be closed seperately.
|
||||
///
|
||||
/// Files and folders in a cabinet set are a single entity. All cabinets
|
||||
/// in a set use the same file list, which is updated as cabinets in the
|
||||
/// set are added. All pointers to mscabd_folder and mscabd_file
|
||||
/// structures in either cabinet must be discarded and re-obtained after
|
||||
/// merging.
|
||||
/// </summary>
|
||||
/// <param name="cab">The cabinet which will be appended to, predecessor of nextcab</param>
|
||||
/// <param name="nextcab">The cabinet which will be appended, successor of cab</param>
|
||||
/// <returns>An error code, or MSPACK_ERR.MSPACK_ERR_OK if successful</returns>
|
||||
/// <see cref="prepend(mscabd_cabinet, mscabd_cabinet)"/>
|
||||
/// <see cref="open(in string)"/>
|
||||
/// <see cref="close(mscabd_cabinet)"/>
|
||||
public MSPACK_ERR append(mscabd_cabinet cab, mscabd_cabinet nextcab) => MSPACK_ERR.MSPACK_ERR_OK;
|
||||
|
||||
/// <summary>
|
||||
/// Prepends one mscabd_cabinet to another, forming or extending a
|
||||
/// cabinet set.
|
||||
///
|
||||
/// This will attempt to prepend one cabinet to another, such that
|
||||
/// <tt>(cab.prevcab == prevcab) && (prevcab.nextcab == cab)</tt>. In
|
||||
/// all other respects, it is identical to append(). See append() for the
|
||||
/// full documentation.
|
||||
/// </summary>
|
||||
/// <param name="cab">The cabinet which will be prepended to, successor of prevcab</param>
|
||||
/// <param name="prevcab">The cabinet which will be prepended, predecessor of cab</param>
|
||||
/// <returns>An error code, or MSPACK_ERR.MSPACK_ERR_OK if successful</returns>
|
||||
/// <see cref="append(mscabd_cabinet, mscabd_cabinet)"/>
|
||||
/// <see cref="open(in string)"/>
|
||||
/// <see cref="close(mscabd_cabinet)"/>
|
||||
public MSPACK_ERR prepend(mscabd_cabinet cab, mscabd_cabinet prevcab) => MSPACK_ERR.MSPACK_ERR_OK;
|
||||
|
||||
/// <summary>
|
||||
/// Extracts a file from a cabinet or cabinet set.
|
||||
///
|
||||
/// This extracts a compressed file in a cabinet and writes it to the given
|
||||
/// filename.
|
||||
///
|
||||
/// The MS-DOS filename of the file, mscabd_file::filename, is NOT USED
|
||||
/// by extract(). The caller must examine this MS-DOS filename, copy and
|
||||
/// change it as necessary, create directories as necessary, and provide
|
||||
/// the correct filename as a parameter, which will be passed unchanged
|
||||
/// to the decompressor's mspack_system::open()
|
||||
///
|
||||
/// If the file belongs to a split folder in a multi-part cabinet set,
|
||||
/// and not enough parts of the cabinet set have been loaded and appended
|
||||
/// or prepended, an error will be returned immediately.
|
||||
/// </summary>
|
||||
/// <param name="file">The file to be decompressed</param>
|
||||
/// <param name="filename">The filename of the file being written to</param>
|
||||
/// <returns>An error code, or MSPACK_ERR.MSPACK_ERR_OK if successful</returns>
|
||||
public MSPACK_ERR extract(mscabd_file file, in string filename) => MSPACK_ERR.MSPACK_ERR_OK;
|
||||
|
||||
/// <summary>
|
||||
/// Sets a CAB decompression engine parameter.
|
||||
///
|
||||
/// The following parameters are defined:
|
||||
/// - #MSCABD_PARAM_SEARCHBUF: How many bytes should be allocated as a
|
||||
/// buffer when using search()? The minimum value is 4. The default
|
||||
/// value is 32768.
|
||||
/// - #MSCABD_PARAM_FIXMSZIP: If non-zero, extract() will ignore bad
|
||||
/// checksums and recover from decompression errors in MS-ZIP
|
||||
/// compressed folders. The default value is 0 (don't recover).
|
||||
/// - #MSCABD_PARAM_DECOMPBUF: How many bytes should be used as an input
|
||||
/// bit buffer by decompressors? The minimum value is 4. The default
|
||||
/// value is 4096.
|
||||
/// </summary>
|
||||
/// <param name="param">The parameter to set</param>
|
||||
/// <param name="value">The value to set the parameter to</param>
|
||||
/// <returns>
|
||||
/// MSPACK_ERR.MSPACK_ERR_OK if all is OK, or MSPACK_ERR.MSPACK_ERR_ARGS if there
|
||||
/// is a problem with either parameter or value.
|
||||
/// </returns>
|
||||
/// <see cref="search(in string)"/>
|
||||
/// <see cref="extract(mscabd_file, in string)"/>
|
||||
public MSPACK_ERR set_param(MSCABD_PARAM param, int value)
|
||||
{
|
||||
switch (param)
|
||||
{
|
||||
case MSCABD_PARAM.MSCABD_PARAM_SEARCHBUF:
|
||||
if (value < 4) return MSPACK_ERR.MSPACK_ERR_ARGS;
|
||||
this.searchbuf_size = value;
|
||||
break;
|
||||
case MSCABD_PARAM.MSCABD_PARAM_FIXMSZIP:
|
||||
this.fix_mszip = value;
|
||||
break;
|
||||
case MSCABD_PARAM.MSCABD_PARAM_DECOMPBUF:
|
||||
if (value < 4) return MSPACK_ERR.MSPACK_ERR_ARGS;
|
||||
this.buf_size = value;
|
||||
break;
|
||||
case MSCABD_PARAM.MSCABD_PARAM_SALVAGE:
|
||||
this.salvage = value;
|
||||
break;
|
||||
default:
|
||||
return MSPACK_ERR.MSPACK_ERR_ARGS;
|
||||
}
|
||||
|
||||
return MSPACK_ERR.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the error code set by the most recently called method.
|
||||
///
|
||||
/// This is useful for open() and search(), which do not return an error
|
||||
/// code directly.
|
||||
/// </summary>
|
||||
/// <returns>The most recent error code</returns>
|
||||
/// <see cref="open(in string)"/>
|
||||
/// <see cref="search(in string)"/>
|
||||
public MSPACK_ERR last_error()
|
||||
{
|
||||
return this.error;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
using static SabreTools.Compression.libmspack.cab;
|
||||
using SabreTools.Compression.libmspack.CAB;
|
||||
using static SabreTools.Compression.libmspack.CAB.Constants;
|
||||
|
||||
namespace SabreTools.Compression.libmspack
|
||||
{
|
||||
public abstract unsafe class mscabd_decompress_state
|
||||
public unsafe class mscabd_decompress_state
|
||||
{
|
||||
/// <summary>
|
||||
/// Current folder we're extracting from
|
||||
@@ -32,7 +33,7 @@ namespace SabreTools.Compression.libmspack
|
||||
/// <summary>
|
||||
/// Special I/O code for decompressor
|
||||
/// </summary>
|
||||
public mspack_system sys { get; set; }
|
||||
public CABSystem sys { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Type of compression used by folder
|
||||
@@ -42,7 +43,7 @@ namespace SabreTools.Compression.libmspack
|
||||
/// <summary>
|
||||
/// Decompressor code
|
||||
/// </summary>
|
||||
public abstract MSPACK_ERR decompress(object data, long offset);
|
||||
public virtual MSPACK_ERR decompress(object data, long offset) => MSPACK_ERR.MSPACK_ERR_NOMEMORY;
|
||||
|
||||
/// <summary>
|
||||
/// Decompressor state
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace SabreTools.Compression.libmspack
|
||||
/// </summary>
|
||||
/// <see cref="mspack_create_chm_decompressor()"/>
|
||||
/// <see cref="mspack_destroy_chm_decompressor()"/>
|
||||
public abstract class mschm_decompressor : Decompressor
|
||||
public abstract class mschm_decompressor : BaseDecompressor
|
||||
{
|
||||
public mschmd_decompress_state d { get; set; }
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ namespace SabreTools.Compression.libmspack
|
||||
/// <summary>
|
||||
/// TODO
|
||||
/// </summary>
|
||||
public class mshlp_decompressor : Decompressor
|
||||
public class mshlp_decompressor : BaseDecompressor
|
||||
{
|
||||
public int dummy { get; set; }
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace SabreTools.Compression.libmspack
|
||||
/// </summary>
|
||||
/// <see cref="mspack_create_kwaj_decompressor()"/>
|
||||
/// <see cref="mspack_destroy_kwaj_decompressor()"/>
|
||||
public abstract class mskwaj_decompressor : Decompressor
|
||||
public abstract class mskwaj_decompressor : BaseDecompressor
|
||||
{
|
||||
/// <summary>
|
||||
/// Opens a KWAJ file and reads the header.
|
||||
|
||||
@@ -3,7 +3,7 @@ namespace SabreTools.Compression.libmspack
|
||||
/// <summary>
|
||||
/// TODO
|
||||
/// </summary>
|
||||
public class mslit_decompressor : Decompressor
|
||||
public class mslit_decompressor : BaseDecompressor
|
||||
{
|
||||
public int dummy { get; set; }
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace SabreTools.Compression.libmspack
|
||||
/// </summary>
|
||||
/// <see cref="mspack_create_oab_decompressor()"/>
|
||||
/// <see cref="mspack_destroy_oab_decompressor()"/>
|
||||
public unsafe class msoab_decompressor : Decompressor
|
||||
public unsafe class msoab_decompressor : BaseDecompressor
|
||||
{
|
||||
public int buf_size { get; set; }
|
||||
|
||||
@@ -39,60 +39,59 @@ namespace SabreTools.Compression.libmspack
|
||||
uint block_max, target_size;
|
||||
lzxd_stream lzx = null;
|
||||
mspack_oab_system oabd_sys;
|
||||
oabd_file in_ofh, out_ofh;
|
||||
uint window_bits;
|
||||
MSPACK_ERR ret = MSPACK_ERR.MSPACK_ERR_OK;
|
||||
|
||||
sys = this.system;
|
||||
|
||||
infh = sys.open(sys, input, MSPACK_SYS_OPEN.MSPACK_SYS_OPEN_READ);
|
||||
if (!infh)
|
||||
infh = sys.open(input, MSPACK_SYS_OPEN.MSPACK_SYS_OPEN_READ);
|
||||
if (infh == null)
|
||||
{
|
||||
ret = MSPACK_ERR.MSPACK_ERR_OPEN;
|
||||
goto outlbl;
|
||||
}
|
||||
|
||||
if (sys.read(infh, hdrbuf, oabhead_SIZEOF) != oabhead_SIZEOF)
|
||||
if (sys.read(infh, libmspack.system.GetArrayPointer(hdrbuf), oabhead_SIZEOF) != oabhead_SIZEOF)
|
||||
{
|
||||
ret = MSPACK_ERR.MSPACK_ERR_READ;
|
||||
goto outlbl;
|
||||
}
|
||||
|
||||
if (EndGetI32(&hdrbuf[oabhead_VersionHi]) != 3 ||
|
||||
EndGetI32(&hdrbuf[oabhead_VersionLo]) != 1)
|
||||
if (System.BitConverter.ToInt32(hdrbuf, oabhead_VersionHi) != 3 ||
|
||||
System.BitConverter.ToInt32(hdrbuf, oabhead_VersionLo) != 1)
|
||||
{
|
||||
ret = MSPACK_ERR.MSPACK_ERR_SIGNATURE;
|
||||
goto outlbl;
|
||||
}
|
||||
|
||||
block_max = EndGetI32(&hdrbuf[oabhead_BlockMax]);
|
||||
target_size = EndGetI32(&hdrbuf[oabhead_TargetSize]);
|
||||
block_max = System.BitConverter.ToUInt32(hdrbuf, oabhead_BlockMax);
|
||||
target_size = System.BitConverter.ToUInt32(hdrbuf, oabhead_TargetSize);
|
||||
|
||||
outfh = sys.open(sys, output, MSPACK_SYS_OPEN.MSPACK_SYS_OPEN_WRITE);
|
||||
if (!outfh)
|
||||
outfh = sys.open(output, MSPACK_SYS_OPEN.MSPACK_SYS_OPEN_WRITE);
|
||||
if (outfh == null)
|
||||
{
|
||||
ret = MSPACK_ERR.MSPACK_ERR_OPEN;
|
||||
goto outlbl;
|
||||
}
|
||||
|
||||
buf = sys.alloc(sys, this.buf_size);
|
||||
if (!buf)
|
||||
buf = (byte*)sys.alloc(this.buf_size);
|
||||
if (buf == null)
|
||||
{
|
||||
ret = MSPACK_ERR.MSPACK_ERR_NOMEMORY;
|
||||
goto outlbl;
|
||||
}
|
||||
|
||||
oabd_sys = *sys;
|
||||
oabd_sys.read = oabd_sys_read;
|
||||
oabd_sys.write = oabd_sys_write;
|
||||
oabd_sys = sys as mspack_oab_system;
|
||||
|
||||
oabd_file in_ofh = new oabd_file();
|
||||
in_ofh.orig_sys = sys;
|
||||
in_ofh.orig_file = infh;
|
||||
|
||||
oabd_file out_ofh = new oabd_file();
|
||||
out_ofh.orig_sys = sys;
|
||||
out_ofh.orig_file = outfh;
|
||||
|
||||
while (target_size)
|
||||
while (target_size > 0)
|
||||
{
|
||||
uint blk_csize, blk_dsize, blk_crc, blk_flags;
|
||||
|
||||
@@ -101,10 +100,10 @@ namespace SabreTools.Compression.libmspack
|
||||
ret = MSPACK_ERR.MSPACK_ERR_READ;
|
||||
goto outlbl;
|
||||
}
|
||||
blk_flags = EndGetI32(&buf[oabblk_Flags]);
|
||||
blk_csize = EndGetI32(&buf[oabblk_CompSize]);
|
||||
blk_dsize = EndGetI32(&buf[oabblk_UncompSize]);
|
||||
blk_crc = EndGetI32(&buf[oabblk_CRC]);
|
||||
blk_flags = System.BitConverter.ToInt32(buf, oabblk_Flags);
|
||||
blk_csize = System.BitConverter.ToInt32(buf, oabblk_CompSize);
|
||||
blk_dsize = System.BitConverter.ToInt32(buf, oabblk_UncompSize);
|
||||
blk_crc = System.BitConverter.ToInt32(buf, oabblk_CRC);
|
||||
|
||||
if (blk_dsize > block_max || blk_dsize > target_size || blk_flags > 1)
|
||||
{
|
||||
@@ -112,31 +111,30 @@ namespace SabreTools.Compression.libmspack
|
||||
goto outlbl;
|
||||
}
|
||||
|
||||
if (!blk_flags)
|
||||
if (blk_flags == 0)
|
||||
{
|
||||
/* Uncompressed block */
|
||||
// Uncompressed block
|
||||
if (blk_dsize != blk_csize)
|
||||
{
|
||||
ret = MSPACK_ERR.MSPACK_ERR_DATAFORMAT;
|
||||
goto outlbl;
|
||||
}
|
||||
ret = copy_fh(sys, infh, outfh, blk_dsize, buf, this.buf_size);
|
||||
if (ret) goto outlbl;
|
||||
ret = copy_fh(sys, infh, outfh, (int)blk_dsize, buf, this.buf_size);
|
||||
if (ret != MSPACK_ERR.MSPACK_ERR_OK) goto outlbl;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* LZX compressed block */
|
||||
// LZX compressed block
|
||||
window_bits = 17;
|
||||
|
||||
while (window_bits < 25 && (1U << window_bits) < blk_dsize)
|
||||
while (window_bits < 25 && (1 << (int)window_bits) < blk_dsize)
|
||||
window_bits++;
|
||||
|
||||
in_ofh.available = blk_csize;
|
||||
in_ofh.available = (int)blk_csize;
|
||||
out_ofh.crc = 0xffffffff;
|
||||
|
||||
lzx = lzxd_init(&oabd_sys, (void*)&in_ofh, (void*)&out_ofh, window_bits,
|
||||
0, this.buf_size, blk_dsize, 1);
|
||||
if (!lzx)
|
||||
lzx = lzxd_init(&oabd_sys, (void*)&in_ofh, (void*)&out_ofh, window_bits, 0, this.buf_size, blk_dsize, 1);
|
||||
if (lzx == null)
|
||||
{
|
||||
ret = MSPACK_ERR.MSPACK_ERR_NOMEMORY;
|
||||
goto outlbl;
|
||||
@@ -149,9 +147,9 @@ namespace SabreTools.Compression.libmspack
|
||||
lzxd_free(lzx);
|
||||
lzx = null;
|
||||
|
||||
/* Consume any trailing padding bytes before the next block */
|
||||
// Consume any trailing padding bytes before the next block
|
||||
ret = copy_fh(sys, infh, null, in_ofh.available, buf, this.buf_size);
|
||||
if (ret) goto outlbl;
|
||||
if (ret != MSPACK_ERR.MSPACK_ERR_OK) goto outlbl;
|
||||
|
||||
if (out_ofh.crc != blk_crc)
|
||||
{
|
||||
@@ -163,9 +161,9 @@ namespace SabreTools.Compression.libmspack
|
||||
}
|
||||
|
||||
outlbl:
|
||||
if (lzx) lzxd_free(lzx);
|
||||
if (outfh) sys.close(outfh);
|
||||
if (infh) sys.close(infh);
|
||||
if (lzx != null) lzxd_free(lzx);
|
||||
if (outfh != null) sys.close(outfh);
|
||||
if (infh != null) sys.close(infh);
|
||||
sys.free(buf);
|
||||
|
||||
return ret;
|
||||
@@ -201,13 +199,15 @@ namespace SabreTools.Compression.libmspack
|
||||
/// <returns>An error code, or MSPACK_ERR.MSPACK_ERR_OK if successful</returns>
|
||||
public MSPACK_ERR decompress_incremental(in string input, in string @base, in string output)
|
||||
{
|
||||
mspack_file infh = null, basefh = null, outfh = null;
|
||||
lzxd_stream lzx = null;
|
||||
byte* buf = null;
|
||||
uint window_bits, window_size;
|
||||
MSPACK_ERR ret = MSPACK_ERR.MSPACK_ERR_OK;
|
||||
|
||||
mspack_system sys = this.system;
|
||||
|
||||
mspack_file infh = sys.open(input, MSPACK_SYS_OPEN.MSPACK_SYS_OPEN_READ);
|
||||
infh = sys.open(input, MSPACK_SYS_OPEN.MSPACK_SYS_OPEN_READ);
|
||||
if (infh == null)
|
||||
{
|
||||
ret = MSPACK_ERR.MSPACK_ERR_OPEN;
|
||||
@@ -222,35 +222,35 @@ namespace SabreTools.Compression.libmspack
|
||||
goto outlbl;
|
||||
}
|
||||
|
||||
if (EndGetI32(&hdrbuf[patchhead_VersionHi]) != 3 ||
|
||||
EndGetI32(&hdrbuf[patchhead_VersionLo]) != 2)
|
||||
if (System.BitConverter.ToInt32(hdrbuf, patchhead_VersionHi) != 3 ||
|
||||
System.BitConverter.ToInt32(hdrbuf, patchhead_VersionLo) != 2)
|
||||
{
|
||||
ret = MSPACK_ERR.MSPACK_ERR_SIGNATURE;
|
||||
goto outlbl;
|
||||
}
|
||||
|
||||
uint block_max = EndGetI32(&hdrbuf[patchhead_BlockMax]);
|
||||
uint target_size = EndGetI32(&hdrbuf[patchhead_TargetSize]);
|
||||
uint block_max = System.BitConverter.ToUInt32(hdrbuf, patchhead_BlockMax);
|
||||
uint target_size = System.BitConverter.ToUInt32(hdrbuf, patchhead_TargetSize);
|
||||
|
||||
// We use it for reading block headers too
|
||||
if (block_max < patchblk_SIZEOF)
|
||||
block_max = patchblk_SIZEOF;
|
||||
|
||||
mspack_file basefh = sys.open(@base, MSPACK_SYS_OPEN.MSPACK_SYS_OPEN_READ);
|
||||
basefh = sys.open(@base, MSPACK_SYS_OPEN.MSPACK_SYS_OPEN_READ);
|
||||
if (basefh == null)
|
||||
{
|
||||
ret = MSPACK_ERR.MSPACK_ERR_OPEN;
|
||||
goto outlbl;
|
||||
}
|
||||
|
||||
mspack_file outfh = sys.open(output, MSPACK_SYS_OPEN.MSPACK_SYS_OPEN_WRITE);
|
||||
outfh = sys.open(output, MSPACK_SYS_OPEN.MSPACK_SYS_OPEN_WRITE);
|
||||
if (outfh == null)
|
||||
{
|
||||
ret = MSPACK_ERR.MSPACK_ERR_OPEN;
|
||||
goto outlbl;
|
||||
}
|
||||
|
||||
byte* buf = (byte*)sys.alloc(this.buf_size);
|
||||
buf = (byte*)sys.alloc(this.buf_size);
|
||||
if (buf == null)
|
||||
{
|
||||
ret = MSPACK_ERR.MSPACK_ERR_NOMEMORY;
|
||||
@@ -275,10 +275,10 @@ namespace SabreTools.Compression.libmspack
|
||||
goto outlbl;
|
||||
}
|
||||
|
||||
uint blk_csize = EndGetI32(&buf[patchblk_PatchSize]);
|
||||
uint blk_dsize = EndGetI32(&buf[patchblk_TargetSize]);
|
||||
uint blk_ssize = EndGetI32(&buf[patchblk_SourceSize]);
|
||||
uint blk_crc = EndGetI32(&buf[patchblk_CRC]);
|
||||
uint blk_csize = System.BitConverter.ToInt32(buf, patchblk_PatchSize);
|
||||
uint blk_dsize = System.BitConverter.ToInt32(buf, patchblk_TargetSize);
|
||||
uint blk_ssize = System.BitConverter.ToInt32(buf, patchblk_SourceSize);
|
||||
uint blk_crc = System.BitConverter.ToInt32(buf, patchblk_CRC);
|
||||
|
||||
if (blk_dsize > block_max || blk_dsize > target_size ||
|
||||
blk_ssize > block_max)
|
||||
@@ -288,19 +288,18 @@ namespace SabreTools.Compression.libmspack
|
||||
}
|
||||
|
||||
|
||||
window_size = (blk_ssize + 32767) & ~32767;
|
||||
window_size = (uint)((blk_ssize + 32767) & ~32767);
|
||||
window_size += blk_dsize;
|
||||
window_bits = 17;
|
||||
|
||||
while (window_bits < 25 && (1U << window_bits) < window_size)
|
||||
while (window_bits < 25 && (1 << (int)window_bits) < window_size)
|
||||
window_bits++;
|
||||
|
||||
in_ofh.available = blk_csize;
|
||||
in_ofh.available = (int)blk_csize;
|
||||
out_ofh.crc = 0xffffffff;
|
||||
|
||||
lzx = lzxd_init(&oabd_sys, (void*)&in_ofh, (void*)&out_ofh, window_bits,
|
||||
0, 4096, blk_dsize, 1);
|
||||
if (!lzx)
|
||||
lzx = lzxd_init(&oabd_sys, (void*)&in_ofh, (void*)&out_ofh, window_bits, 0, 4096, blk_dsize, 1);
|
||||
if (lzx == null)
|
||||
{
|
||||
ret = MSPACK_ERR.MSPACK_ERR_NOMEMORY;
|
||||
goto outlbl;
|
||||
@@ -316,9 +315,9 @@ namespace SabreTools.Compression.libmspack
|
||||
lzxd_free(lzx);
|
||||
lzx = null;
|
||||
|
||||
/* Consume any trailing padding bytes before the next block */
|
||||
// Consume any trailing padding bytes before the next block
|
||||
ret = copy_fh(sys, infh, null, in_ofh.available, buf, this.buf_size);
|
||||
if (ret) goto outlbl;
|
||||
if (ret != MSPACK_ERR.MSPACK_ERR_OK) goto outlbl;
|
||||
|
||||
if (out_ofh.crc != blk_crc)
|
||||
{
|
||||
@@ -330,11 +329,11 @@ namespace SabreTools.Compression.libmspack
|
||||
}
|
||||
|
||||
outlbl:
|
||||
if (lzx) lzxd_free(lzx);
|
||||
if (outfh) sys.close(outfh);
|
||||
if (basefh) sys.close(basefh);
|
||||
if (infh) sys.close(infh);
|
||||
sys.free(buf);
|
||||
if (lzx != null) lzxd_free(lzx);
|
||||
if (outfh != null) sys.close(outfh);
|
||||
if (basefh != null) sys.close(basefh);
|
||||
if (infh != null) sys.close(infh);
|
||||
if (buf != null) sys.free(buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@ namespace SabreTools.Compression.libmspack
|
||||
{
|
||||
public partial class mspack
|
||||
{
|
||||
#region CAB
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new CAB compressor.
|
||||
/// </summary>
|
||||
@@ -14,15 +16,12 @@ namespace SabreTools.Compression.libmspack
|
||||
/// <summary>
|
||||
/// Creates a new CAB decompressor.
|
||||
/// </summary>
|
||||
/// <param name="sys">A custom <see cref="mspack_system"/> structure, or null to use the default</param>
|
||||
/// <returns>A <see cref="mscab_decompressor"/> or null</returns>
|
||||
public static mscab_decompressor mspack_create_cab_decompressor(mspack_system sys)
|
||||
/// <returns>A <see cref="CAB.Decompressor"/> or null</returns>
|
||||
public static CAB.Decompressor CreateCABDecompressor()
|
||||
{
|
||||
if (sys == null) sys = new mspack_mscab_system();
|
||||
|
||||
var self = new mscab_decompressor
|
||||
var self = new CAB.Decompressor
|
||||
{
|
||||
system = sys,
|
||||
system = new CAB.CABSystem(),
|
||||
d = null,
|
||||
error = MSPACK_ERR.MSPACK_ERR_OK,
|
||||
|
||||
@@ -44,8 +43,8 @@ namespace SabreTools.Compression.libmspack
|
||||
/// <summary>
|
||||
/// Destroys an existing CAB decompressor.
|
||||
/// </summary>
|
||||
/// <param name="self">The <see cref="mscab_decompressor"/> to destroy</param>
|
||||
public static void mspack_destroy_cab_decompressor(mscab_decompressor self)
|
||||
/// <param name="self">The <see cref="CAB.Decompressor"/> to destroy</param>
|
||||
public static void DestroyCABDecompressor(CAB.Decompressor self)
|
||||
{
|
||||
if (self != null)
|
||||
{
|
||||
@@ -53,7 +52,7 @@ namespace SabreTools.Compression.libmspack
|
||||
if (self.d != null)
|
||||
{
|
||||
if (self.d.infh != null) sys.close(self.d.infh);
|
||||
cabd_free_decomp(self);
|
||||
cab.cabd_free_decomp(self);
|
||||
//sys.free(self.d);
|
||||
}
|
||||
|
||||
@@ -61,6 +60,8 @@ namespace SabreTools.Compression.libmspack
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new CHM compressor.
|
||||
/// </summary>
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace SabreTools.Compression.libmspack
|
||||
/// </summary>
|
||||
/// <see cref="mspack_create_szdd_decompressor()"/>
|
||||
/// <see cref="mspack_destroy_szdd_decompressor()"/>
|
||||
public unsafe class msszdd_decompressor : Decompressor
|
||||
public unsafe class msszdd_decompressor : BaseDecompressor
|
||||
{
|
||||
/// <summary>
|
||||
/// Opens a SZDD file and reads the header.
|
||||
@@ -105,7 +105,7 @@ namespace SabreTools.Compression.libmspack
|
||||
if (sys.read(fh, bufPtr, 6) != 6) return MSPACK_ERR.MSPACK_ERR_READ;
|
||||
if (buf[0] != 0x41) return MSPACK_ERR.MSPACK_ERR_DATAFORMAT;
|
||||
hdr.missing_char = (char)buf[1];
|
||||
hdr.length = EndGetI32(&buf[2]);
|
||||
hdr.length = System.BitConverter.ToInt32(buf, 2);
|
||||
}
|
||||
else if (buf.SequenceEqual(szdd_signature_qbasic))
|
||||
{
|
||||
@@ -113,7 +113,7 @@ namespace SabreTools.Compression.libmspack
|
||||
hdr.format = MSSZDD_FMT.MSSZDD_FMT_QBASIC;
|
||||
if (sys.read(fh, bufPtr, 4) != 4) return MSPACK_ERR.MSPACK_ERR_READ;
|
||||
hdr.missing_char = '\0';
|
||||
hdr.length = EndGetI32(buf);
|
||||
hdr.length = System.BitConverter.ToInt32(buf, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user