mirror of
https://github.com/fadden/ciderpress.git
synced 2024-11-27 08:49:20 +00:00
b79498da50
Most of this change is a conversion of the old FileDetails struct into a new LocalFileDetails class. The new class keeps the members private, and keeps the Unicode and MOR representations of the string separate. The NuFX and DiskImg libraries don't support UTF-16 filenames, so we stil can't add files with non-CP-1252 filenames, but we're a step closer. Also, update NufxLib with a couple of fixes from the main project. Also, fix handling of "%00" when adding files. Also, mark most of the A2FileDOS fields private. Not sure why they weren't.
862 lines
36 KiB
C
862 lines
36 KiB
C
/*
|
|
* NuFX archive manipulation library
|
|
* Copyright (C) 2000-2007 by Andy McFadden, All Rights Reserved.
|
|
* This is free software; you can redistribute it and/or modify it under the
|
|
* terms of the BSD License, see the file COPYING-LIB.
|
|
*
|
|
* Global internal declarations and definitions.
|
|
*/
|
|
#ifndef NUFXLIB_NUFXLIBPRIV_H
|
|
#define NUFXLIB_NUFXLIBPRIV_H
|
|
|
|
/* include files that everybody needs */
|
|
#include "SysDefs.h"
|
|
#include "NufxLib.h"
|
|
#include "MiscStuff.h"
|
|
|
|
#ifdef USE_DMALLOC
|
|
/* enable with something like "dmalloc -l logfile -i 100 medium" */
|
|
# include "dmalloc.h"
|
|
#endif
|
|
|
|
|
|
/*
|
|
* ===========================================================================
|
|
* NuArchive definition
|
|
* ===========================================================================
|
|
*/
|
|
|
|
/*
|
|
* Archives can be opened in streaming read-only, non-streaming read-only,
|
|
* and non-streaming read-write mode.
|
|
*/
|
|
typedef enum NuOpenMode {
|
|
kNuOpenUnknown,
|
|
kNuOpenStreamingRO,
|
|
kNuOpenRO,
|
|
kNuOpenRW
|
|
} NuOpenMode;
|
|
#define Nu_IsStreaming(pArchive) ((pArchive)->openMode == kNuOpenStreamingRO)
|
|
#define Nu_IsReadOnly(pArchive) ((pArchive)->openMode == kNuOpenStreamingRO ||\
|
|
(pArchive)->openMode == kNuOpenRO)
|
|
|
|
#ifdef FOPEN_WANTS_B
|
|
# define kNuFileOpenReadOnly "rb"
|
|
# define kNuFileOpenReadWrite "r+b"
|
|
# define kNuFileOpenWriteTrunc "wb"
|
|
# define kNuFileOpenReadWriteCreat "w+b"
|
|
#else
|
|
# define kNuFileOpenReadOnly "r"
|
|
# define kNuFileOpenReadWrite "r+"
|
|
# define kNuFileOpenWriteTrunc "w"
|
|
# define kNuFileOpenReadWriteCreat "w+"
|
|
#endif
|
|
|
|
|
|
/*
|
|
* Some NuFX and Binary II definitions.
|
|
*/
|
|
#define kNuMasterHeaderSize 48 /* size of fixed-length master header */
|
|
#define kNuRecordHeaderBaseSize 58 /* size of rec hdr up to variable stuff */
|
|
#define kNuThreadHeaderSize 16 /* size of fixed-length thread header */
|
|
#define kNuDefaultFilenameThreadSize 32 /* default size of filename thred */
|
|
#define kNuDefaultCommentSize 200 /* size of GSHK-mimic comments */
|
|
#define kNuBinary2BlockSize 128 /* size of bxy header and padding */
|
|
#define kNuSEAOffset 0x2ee5 /* fixed(??) offset to data in SEA */
|
|
|
|
#define kNuInitialChunkCRC 0x0000 /* start for CRC in LZW/1 chunk */
|
|
#define kNuInitialThreadCRC 0xffff /* start for CRC in v3 thread header */
|
|
|
|
/* size of general-purpose compression buffer */
|
|
#define kNuGenCompBufSize 32768
|
|
|
|
#define kNuCharLF 0x0a
|
|
#define kNuCharCR 0x0d
|
|
|
|
|
|
/*
|
|
* A list of records. Generally we use one of these for read-only
|
|
* archives, and two for read-write.
|
|
*
|
|
* The "loaded" flag is set when we've made some use of the record set.
|
|
* Relying on "numRecords" won't always work; for example, if the "copy"
|
|
* record set was initialized from "orig", and then had all of its records
|
|
* deleted, you couldn't look at "numRecords" and decide whether it was
|
|
* appropriate to use "orig" or not.
|
|
*/
|
|
typedef struct NuRecordSet {
|
|
Boolean loaded;
|
|
uint32_t numRecords;
|
|
NuRecord* nuRecordHead;
|
|
NuRecord* nuRecordTail;
|
|
} NuRecordSet;
|
|
|
|
/*
|
|
* Archive state.
|
|
*/
|
|
struct NuArchive {
|
|
uint32_t structMagic;
|
|
Boolean busy;
|
|
|
|
NuOpenMode openMode;
|
|
Boolean newlyCreated;
|
|
UNICHAR* archivePathnameUNI; /* pathname or "(stream)" */
|
|
FILE* archiveFp;
|
|
NuArchiveType archiveType;
|
|
|
|
/* stuff before NuFX; both offsets are from 0, i.e. hdrOff includes junk */
|
|
long junkOffset; /* skip past leading junk */
|
|
long headerOffset; /* adjustment for BXY/SEA/BSE */
|
|
|
|
UNICHAR* tmpPathnameUNI; /* temp file, for writes */
|
|
FILE* tmpFp;
|
|
|
|
/* used during initial processing; helps avoid ftell() calls */
|
|
long currentOffset;
|
|
|
|
/* setting this changes Extract into Test */
|
|
Boolean testMode;
|
|
|
|
/* clumsy way of remembering name used for other fork in forked file */
|
|
const UNICHAR* lastFileCreatedUNI;
|
|
/* clumsy way to avoid trying to create the same subdir several times */
|
|
const UNICHAR* lastDirCreatedUNI;
|
|
|
|
/* master header from the archive */
|
|
NuMasterHeader masterHeader; /* original */
|
|
NuMasterHeader newMasterHeader; /* working copy during update */
|
|
|
|
/* list of records from archive, plus some extra state */
|
|
NuRecordIdx recordIdxSeed; /* where the NuRecordIdxs start */
|
|
NuRecordIdx nextRecordIdx; /* next record gets this value */
|
|
Boolean haveToc; /* set if we have full TOC */
|
|
NuRecordSet origRecordSet; /* records from archive */
|
|
NuRecordSet copyRecordSet; /* copy of orig, for write ops */
|
|
NuRecordSet newRecordSet; /* newly-added records */
|
|
|
|
/* state for compression functions */
|
|
uint8_t* compBuf; /* large general-purpose buffer */
|
|
void* lzwCompressState; /* state for LZW/1 and LZW/2 */
|
|
void* lzwExpandState; /* state for LZW/1 and LZW/2 */
|
|
|
|
/* options and attributes that the user can set */
|
|
/* (these can be changed by a callback, so don't cache them internally) */
|
|
void* extraData; /* application-defined pointer */
|
|
|
|
NuValue valAllowDuplicates; /* allow dups when adding? */
|
|
NuValue valConvertExtractedEOL; /* convert EOL during extract? */
|
|
NuValue valDataCompression; /* how to compress when adding? */
|
|
NuValue valDiscardWrapper; /* remove BNY or SEA header? */
|
|
NuValue valEOL; /* EOL value to convert to */
|
|
NuValue valHandleExisting; /* how to deal with existing files*/
|
|
NuValue valIgnoreCRC; /* don't compute or test CRCs */
|
|
NuValue valMaskDataless; /* alter Records w/o data threads */
|
|
NuValue valMimicSHK; /* mimic some ShrinkIt quirks */
|
|
NuValue valModifyOrig; /* modify original arc in place? */
|
|
NuValue valOnlyUpdateOlder; /* modify original arc in place? */
|
|
NuValue valStripHighASCII; /* during EOL conv, strip hi bit? */
|
|
NuValue valJunkSkipMax; /* scan this far for header */
|
|
NuValue valIgnoreLZW2Len; /* don't verify LZW/II len field */
|
|
NuValue valHandleBadMac; /* handle "bad Mac" archives */
|
|
|
|
/* callback functions */
|
|
NuCallback selectionFilterFunc;
|
|
NuCallback outputPathnameFunc;
|
|
NuCallback progressUpdaterFunc;
|
|
NuCallback errorHandlerFunc;
|
|
NuCallback messageHandlerFunc;
|
|
};
|
|
|
|
#define kNuArchiveStructMagic 0xc0edbabe
|
|
|
|
#define kNuDefaultRecordName "UNKNOWN" /* use ASCII charset */
|
|
|
|
|
|
/*
|
|
* ===========================================================================
|
|
* ThreadMod definition
|
|
* ===========================================================================
|
|
*/
|
|
|
|
/* operations we can perform on threads in a record */
|
|
typedef enum ThreadModKind {
|
|
kNuThreadModUnknown = 0,
|
|
|
|
kNuThreadModAdd,
|
|
kNuThreadModUpdate,
|
|
kNuThreadModDelete
|
|
} ThreadModKind;
|
|
|
|
/*
|
|
* We attach a list of these to records we plan to modify. Care is taken
|
|
* to ensure that they don't conflict, e.g. you can't update a thread
|
|
* right after you delete it, nor delete one you have modified.
|
|
*/
|
|
struct NuThreadMod {
|
|
union {
|
|
ThreadModKind kind;
|
|
|
|
struct {
|
|
ThreadModKind kind;
|
|
Boolean used;
|
|
} generic;
|
|
|
|
struct {
|
|
ThreadModKind kind;
|
|
Boolean used;
|
|
Boolean isPresized;
|
|
NuThreadIdx threadIdx;
|
|
NuThreadID threadID;
|
|
NuThreadFormat threadFormat;
|
|
NuDataSource* pDataSource;
|
|
} add;
|
|
|
|
struct {
|
|
ThreadModKind kind;
|
|
Boolean used;
|
|
NuThreadIdx threadIdx;
|
|
NuDataSource* pDataSource;
|
|
} update;
|
|
|
|
struct {
|
|
ThreadModKind kind;
|
|
Boolean used;
|
|
NuThreadIdx threadIdx;
|
|
NuThreadID threadID; /* used for watching filename threads */
|
|
} delete;
|
|
} entry;
|
|
|
|
struct NuThreadMod* pNext;
|
|
};
|
|
|
|
|
|
/*
|
|
* ===========================================================================
|
|
* NuFunnel/NuStraw definition
|
|
* ===========================================================================
|
|
*/
|
|
|
|
#define kNuFunnelBufSize 16384
|
|
|
|
/*
|
|
* File funnel definition. This is used for writing output to files
|
|
* (so we can do things like pipe compressed output through an LF->CR
|
|
* converter) and archive files (so we can halt compression when the
|
|
* output size exceeds the uncompressed original). [ for various reasons,
|
|
* I'm not using this on the archive anymore. ]
|
|
*
|
|
* Funnels are unidirectional. You write data into them with a
|
|
* function call; the top-level action (which is usually compressing or
|
|
* expanding data) reads from the input and crams things into the pipe.
|
|
* We could fully abstract the concept, and write the compression
|
|
* functions so that they operate as a Funnel filter, but it's much
|
|
* easier to write block-oriented compression than stream-oriented (and
|
|
* more to the point, the ShrinkIt LZW functions are very much
|
|
* block-oriented).
|
|
*/
|
|
typedef struct NuFunnel {
|
|
/* data storage */
|
|
uint8_t* buffer; /* kNuFunnelBufSize worth of storage */
|
|
long bufCount; /* #of bytes in buffer */
|
|
|
|
/* text conversion; if "auto", on first flush we convert to "on" or "off" */
|
|
NuValue convertEOL; /* on/off/auto */
|
|
NuValue convertEOLTo; /* EOL to switch to */
|
|
NuValue convertEOLFrom; /* EOL terminator we think we found */
|
|
Boolean checkStripHighASCII; /* do we want to check for it? */
|
|
Boolean doStripHighASCII; /* strip high ASCII during EOL conv */
|
|
Boolean lastCR; /* was last char a CR? */
|
|
|
|
Boolean isFirstWrite; /* cleared on first write */
|
|
|
|
#if 0
|
|
uint32_t inCount; /* total #of bytes in the top */
|
|
uint32_t outCount; /* total #of bytes out the bottom */
|
|
|
|
uint32_t outMax; /* flag an err when outCount exceeds this */
|
|
Boolean outMaxExceeded; /* in fact, it's this flag */
|
|
#endif
|
|
|
|
/* update this when stuff happens */
|
|
NuProgressData* pProgress;
|
|
|
|
/* data goeth out here */
|
|
NuDataSink* pDataSink;
|
|
} NuFunnel;
|
|
|
|
|
|
/*
|
|
* File straw definition. This is used for slurping up input data.
|
|
*
|
|
* Mostly this is an encapsulation of an input source and a progress
|
|
* updater, useful for reading uncompressed data and feeding it to a
|
|
* compressor. It doesn't make sense to show a thermometer based on
|
|
* compressed output, since we don't know how big the eventual result
|
|
* will be, so we want to do it for the input.
|
|
*/
|
|
typedef struct NuStraw {
|
|
/* update this when stuff happens */
|
|
NuProgressData* pProgress;
|
|
|
|
/* data cometh in here */
|
|
NuDataSource* pDataSource;
|
|
|
|
/* progress update fields */
|
|
uint32_t lastProgress;
|
|
uint32_t lastDisplayed;
|
|
} NuStraw;
|
|
|
|
/*NuError Nu_CopyStreamToStream(FILE* outfp, FILE* infp, uint32_t count);*/
|
|
|
|
|
|
/*
|
|
* ===========================================================================
|
|
* Data source and sink abstractions
|
|
* ===========================================================================
|
|
*/
|
|
|
|
/*
|
|
* DataSource is used when adding data to an archive.
|
|
*/
|
|
|
|
typedef enum NuDataSourceType {
|
|
kNuDataSourceUnknown = 0,
|
|
kNuDataSourceFromFile,
|
|
kNuDataSourceFromFP,
|
|
kNuDataSourceFromBuffer
|
|
} NuDataSourceType;
|
|
|
|
typedef struct NuDataSourceCommon {
|
|
NuDataSourceType sourceType;
|
|
NuThreadFormat threadFormat; /* is it already compressed? */
|
|
uint16_t rawCrc; /* crc for already-compressed data*/
|
|
/*Boolean doClose; \* close on completion? */
|
|
uint32_t dataLen; /* length of data (var for buf) */
|
|
uint32_t otherLen; /* uncomp len or preset buf size */
|
|
int refCount; /* so we can copy structs */
|
|
} NuDataSourceCommon;
|
|
|
|
union NuDataSource {
|
|
NuDataSourceType sourceType;
|
|
|
|
NuDataSourceCommon common;
|
|
|
|
struct {
|
|
NuDataSourceCommon common;
|
|
UNICHAR* pathnameUNI;
|
|
Boolean fromRsrcFork;
|
|
|
|
/* temp storage; only valid when processing in library */
|
|
FILE* fp;
|
|
} fromFile;
|
|
|
|
struct {
|
|
NuDataSourceCommon common;
|
|
FILE* fp;
|
|
long offset; /* starting offset */
|
|
|
|
NuCallback fcloseFunc; /* how to fclose the file */
|
|
} fromFP;
|
|
|
|
struct {
|
|
NuDataSourceCommon common;
|
|
const uint8_t* buffer; /* non-const if doClose=true */
|
|
long offset; /* starting offset */
|
|
|
|
long curOffset; /* current offset */
|
|
long curDataLen; /* remaining data */
|
|
|
|
NuCallback freeFunc; /* how to free data */
|
|
} fromBuffer;
|
|
};
|
|
|
|
|
|
/*
|
|
* DataSink is used when extracting data from an archive.
|
|
*/
|
|
|
|
typedef enum NuDataSinkType {
|
|
kNuDataSinkUnknown = 0,
|
|
kNuDataSinkToFile,
|
|
kNuDataSinkToFP,
|
|
kNuDataSinkToBuffer,
|
|
kNuDataSinkToVoid
|
|
} NuDataSinkType;
|
|
|
|
typedef struct NuDataSinkCommon {
|
|
NuDataSinkType sinkType;
|
|
Boolean doExpand; /* expand file? */
|
|
NuValue convertEOL; /* convert EOL? (req "expand") */
|
|
uint32_t outCount;
|
|
} NuDataSinkCommon;
|
|
|
|
union NuDataSink {
|
|
NuDataSinkType sinkType;
|
|
|
|
NuDataSinkCommon common;
|
|
|
|
struct {
|
|
NuDataSinkCommon common;
|
|
UNICHAR* pathnameUNI; /* file to open */
|
|
UNICHAR fssep;
|
|
|
|
/* temp storage; must be NULL except when processing in library */
|
|
FILE* fp;
|
|
} toFile;
|
|
|
|
struct {
|
|
NuDataSinkCommon common;
|
|
FILE* fp;
|
|
} toFP;
|
|
|
|
struct {
|
|
NuDataSinkCommon common;
|
|
uint8_t* buffer;
|
|
uint32_t bufLen; /* max amount of data "buffer" holds */
|
|
NuError stickyErr;
|
|
} toBuffer;
|
|
};
|
|
|
|
|
|
/*
|
|
* ===========================================================================
|
|
* Function prototypes
|
|
* ===========================================================================
|
|
*/
|
|
|
|
/*
|
|
* This is a little unpleasant. This blob of stuff gets stuffed in as
|
|
* the first arguments to Nu_ReportError, so we don't have to type them
|
|
* in every time we use the function. It would've been much easier to
|
|
* use a gcc-style varargs macro, but not everybody uses gcc.
|
|
*
|
|
* TODO: Visual C++ has vararg macros now; time to replace this.
|
|
*/
|
|
#ifdef HAS__FUNCTION__
|
|
# define _FUNCTION_ __FUNCTION__
|
|
#else
|
|
# define _FUNCTION_ ""
|
|
#endif
|
|
|
|
#define NU_BLOB pArchive, __FILE__, __LINE__, _FUNCTION_, false
|
|
#define NU_BLOB_DEBUG pArchive, __FILE__, __LINE__, _FUNCTION_, true
|
|
#define NU_NILBLOB NULL, __FILE__, __LINE__, _FUNCTION_, false
|
|
|
|
#ifdef DEBUG_MSGS
|
|
# define DebugShowError(err) \
|
|
Nu_ReportError(pArchive, __FILE__, __LINE__, _FUNCTION_, \
|
|
true, err, "(DEBUG)");
|
|
#else
|
|
# define DebugShowError(err) ((void)0)
|
|
#endif
|
|
|
|
/*
|
|
* The BailError macro serves two purposes. First, it's a convenient
|
|
* way to avoid typing, "if (err != kNuErrNone) goto bail;". Second,
|
|
* when the library is built with debugging enabled, it vitually gives
|
|
* us a stack trace of exiting functions. This makes it easier to debug
|
|
* problems sent in as screen dumps via e-mail.
|
|
*/
|
|
#define BailError(err) { \
|
|
if ((err) != kNuErrNone) { \
|
|
/* [should this be debug-only, or all the time?] */ \
|
|
DebugShowError(err); \
|
|
goto bail; \
|
|
} \
|
|
}
|
|
#define BailErrorQuiet(err) { \
|
|
if ((err) != kNuErrNone) \
|
|
goto bail; \
|
|
}
|
|
#define BailNil(val) { \
|
|
if ((val) == NULL) { \
|
|
err = kNuErrUnexpectedNil; \
|
|
BailError(err); \
|
|
} \
|
|
}
|
|
#define BailAlloc(val) { \
|
|
if ((val) == NULL) { \
|
|
err = kNuErrMalloc; \
|
|
BailError(err); \
|
|
} \
|
|
}
|
|
|
|
|
|
/*
|
|
* Internal function prototypes and inline functions.
|
|
*/
|
|
|
|
/* Archive.c */
|
|
void Nu_MasterHeaderCopy(NuArchive* pArchive, NuMasterHeader* pDstHeader,
|
|
const NuMasterHeader* pSrcHeader);
|
|
NuError Nu_GetMasterHeader(NuArchive* pArchive,
|
|
const NuMasterHeader** ppMasterHeader);
|
|
NuRecordIdx Nu_GetNextRecordIdx(NuArchive* pArchive);
|
|
NuThreadIdx Nu_GetNextThreadIdx(NuArchive* pArchive);
|
|
NuError Nu_CopyWrapperToTemp(NuArchive* pArchive);
|
|
NuError Nu_UpdateWrapper(NuArchive* pArchive, FILE* fp);
|
|
NuError Nu_AdjustWrapperPadding(NuArchive* pArchive, FILE* fp);
|
|
NuError Nu_AllocCompressionBufferIFN(NuArchive* pArchive);
|
|
NuError Nu_StreamOpenRO(FILE* infp, NuArchive** ppArchive);
|
|
NuError Nu_OpenRO(const UNICHAR* archivePathnameUNI, NuArchive** ppArchive);
|
|
NuError Nu_OpenRW(const UNICHAR* archivePathnameUNI,
|
|
const UNICHAR* tempPathnameUNI, uint32_t flags, NuArchive** ppArchive);
|
|
NuError Nu_WriteMasterHeader(NuArchive* pArchive, FILE* fp,
|
|
NuMasterHeader* pMasterHeader);
|
|
NuError Nu_Close(NuArchive* pArchive);
|
|
NuError Nu_Abort(NuArchive* pArchive);
|
|
NuError Nu_RenameTempToArchive(NuArchive* pArchive);
|
|
NuError Nu_DeleteArchiveFile(NuArchive* pArchive);
|
|
|
|
/* ArchiveIO.c */
|
|
uint8_t Nu_ReadOneC(NuArchive* pArchive, FILE* fp, uint16_t* pCrc);
|
|
uint8_t Nu_ReadOne(NuArchive* pArchive, FILE* fp);
|
|
void Nu_WriteOneC(NuArchive* pArchive, FILE* fp, uint8_t val, uint16_t* pCrc);
|
|
void Nu_WriteOne(NuArchive* pArchive, FILE* fp, uint8_t val);
|
|
uint16_t Nu_ReadTwoC(NuArchive* pArchive, FILE* fp, uint16_t* pCrc);
|
|
uint16_t Nu_ReadTwo(NuArchive* pArchive, FILE* fp);
|
|
void Nu_WriteTwoC(NuArchive* pArchive, FILE* fp, uint16_t val, uint16_t* pCrc);
|
|
void Nu_WriteTwo(NuArchive* pArchive, FILE* fp, uint16_t val);
|
|
uint32_t Nu_ReadFourC(NuArchive* pArchive, FILE* fp, uint16_t* pCrc);
|
|
uint32_t Nu_ReadFour(NuArchive* pArchive, FILE* fp);
|
|
void Nu_WriteFourC(NuArchive* pArchive, FILE* fp, uint32_t val, uint16_t* pCrc);
|
|
void Nu_WriteFour(NuArchive* pArchive, FILE* fp, uint32_t val);
|
|
NuDateTime Nu_ReadDateTimeC(NuArchive* pArchive, FILE* fp, uint16_t* pCrc);
|
|
NuDateTime Nu_ReadDateTime(NuArchive* pArchive, FILE* fp, uint16_t* pCrc);
|
|
void Nu_WriteDateTimeC(NuArchive* pArchive, FILE* fp, NuDateTime dateTime,
|
|
uint16_t* pCrc);
|
|
void Nu_WriteDateTime(NuArchive* pArchive, FILE* fp, NuDateTime dateTime);
|
|
void Nu_ReadBytesC(NuArchive* pArchive, FILE* fp, void* vbuffer, long count,
|
|
uint16_t* pCrc);
|
|
void Nu_ReadBytes(NuArchive* pArchive, FILE* fp, void* vbuffer, long count);
|
|
void Nu_WriteBytesC(NuArchive* pArchive, FILE* fp, const void* vbuffer,
|
|
long count, uint16_t* pCrc);
|
|
void Nu_WriteBytes(NuArchive* pArchive, FILE* fp, const void* vbuffer,
|
|
long count);
|
|
NuError Nu_HeaderIOFailed(NuArchive* pArchive, FILE* fp);
|
|
NuError Nu_SeekArchive(NuArchive* pArchive, FILE* fp, long offset,
|
|
int ptrname);
|
|
NuError Nu_RewindArchive(NuArchive* pArchive);
|
|
|
|
/* Bzip2.c */
|
|
NuError Nu_CompressBzip2(NuArchive* pArchive, NuStraw* pStraw, FILE* fp,
|
|
uint32_t srcLen, uint32_t* pDstLen, uint16_t* pCrc);
|
|
NuError Nu_ExpandBzip2(NuArchive* pArchive, const NuRecord* pRecord,
|
|
const NuThread* pThread, FILE* infp, NuFunnel* pFunnel, uint16_t* pCrc);
|
|
|
|
/* Charset.c */
|
|
size_t Nu_ConvertMORToUNI(const char* stringMOR, UNICHAR* bufUNI,
|
|
size_t bufSize);
|
|
UNICHAR* Nu_CopyMORToUNI(const char* stringMOR);
|
|
size_t Nu_ConvertUNIToMOR(const UNICHAR* stringUNI, char* bufMOR,
|
|
size_t bufSize);
|
|
|
|
/* Compress.c */
|
|
NuError Nu_CompressToArchive(NuArchive* pArchive, NuDataSource* pDataSource,
|
|
NuThreadID threadID, NuThreadFormat sourceFormat,
|
|
NuThreadFormat targetFormat, NuProgressData* progressData, FILE* dstFp,
|
|
NuThread* pThread);
|
|
NuError Nu_CopyPresizedToArchive(NuArchive* pArchive,
|
|
NuDataSource* pDataSource, NuThreadID threadID, FILE* dstFp,
|
|
NuThread* pThread, char** ppSavedCopy);
|
|
|
|
/* Crc16.c */
|
|
extern const uint16_t gNuCrc16Table[256];
|
|
uint16_t Nu_CalcCRC16(uint16_t seed, const uint8_t* ptr, int count);
|
|
/*
|
|
* Update the CRC-16.
|
|
*
|
|
* _val (uint8_t) is the byte to add to the CRC. It's evaluated once.
|
|
* _crc (uint16_t) is the previous CRC. It's evaluated twice.
|
|
* Returns the updated CRC as a uint16_t.
|
|
*/
|
|
#define Nu_UpdateCRC16(_val, _crc) \
|
|
(gNuCrc16Table[(((_crc) >> 8) & 0xff) ^ (_val)] ^ ((_crc) << 8))
|
|
|
|
/* Debug.c */
|
|
#if defined(DEBUG_MSGS) || !defined(NDEBUG)
|
|
void Nu_DebugDumpAll(NuArchive* pArchive);
|
|
void Nu_DebugDumpThread(const NuThread* pThread);
|
|
#endif
|
|
|
|
/* Deferred.c */
|
|
NuError Nu_ThreadModAdd_New(NuArchive* pArchive, NuThreadID threadID,
|
|
NuThreadFormat threadFormat, NuDataSource* pDataSource,
|
|
NuThreadMod** ppThreadMod);
|
|
NuError Nu_ThreadModUpdate_New(NuArchive* pArchive, NuThreadIdx threadIdx,
|
|
NuDataSource* pDataSource, NuThreadMod** ppThreadMod);
|
|
NuError Nu_ThreadModDelete_New(NuArchive* pArchive, NuThreadIdx threadIdx,
|
|
NuThreadID threadID, NuThreadMod** ppThreadMod);
|
|
void Nu_ThreadModFree(NuArchive* pArchive, NuThreadMod* pThreadMod);
|
|
NuError Nu_ThreadModAdd_FindByThreadID(const NuRecord* pRecord,
|
|
NuThreadID threadID, NuThreadMod** ppThreadMod);
|
|
void Nu_FreeThreadMods(NuArchive* pArchive, NuRecord* pRecord);
|
|
NuThreadMod* Nu_ThreadMod_FindByThreadIdx(const NuRecord* pRecord,
|
|
NuThreadIdx threadIdx);
|
|
NuError Nu_Flush(NuArchive* pArchive, uint32_t* pStatusFlags);
|
|
|
|
/* Deflate.c */
|
|
NuError Nu_CompressDeflate(NuArchive* pArchive, NuStraw* pStraw, FILE* fp,
|
|
uint32_t srcLen, uint32_t* pDstLen, uint16_t* pCrc);
|
|
NuError Nu_ExpandDeflate(NuArchive* pArchive, const NuRecord* pRecord,
|
|
const NuThread* pThread, FILE* infp, NuFunnel* pFunnel, uint16_t* pCrc);
|
|
|
|
/* Expand.c */
|
|
NuError Nu_ExpandStream(NuArchive* pArchive, const NuRecord* pRecord,
|
|
const NuThread* pThread, FILE* infp, NuFunnel* pFunnel);
|
|
|
|
/* FileIO.c */
|
|
void Nu_SetCurrentDateTime(NuDateTime* pDateTime);
|
|
Boolean Nu_IsOlder(const NuDateTime* pWhen1, const NuDateTime* pWhen2);
|
|
NuError Nu_OpenOutputFile(NuArchive* pArchive, const NuRecord* pRecord,
|
|
const NuThread* pThread, const UNICHAR* newPathnameUNI, UNICHAR newFssep,
|
|
FILE** pFp);
|
|
NuError Nu_CloseOutputFile(NuArchive* pArchive, const NuRecord* pRecord,
|
|
FILE* fp, const UNICHAR* pathnameUNI);
|
|
NuError Nu_OpenInputFile(NuArchive* pArchive, const UNICHAR* pathnameUNI,
|
|
Boolean openRsrc, FILE** pFp);
|
|
NuError Nu_DeleteFile(const UNICHAR* pathnameUNI);
|
|
NuError Nu_RenameFile(const UNICHAR* fromPathUNI, const UNICHAR* toPathUNI);
|
|
NuError Nu_FTell(FILE* fp, long* pOffset);
|
|
NuError Nu_FSeek(FILE* fp, long offset, int ptrname);
|
|
NuError Nu_FRead(FILE* fp, void* buf, size_t nbyte);
|
|
NuError Nu_FWrite(FILE* fp, const void* buf, size_t nbyte);
|
|
NuError Nu_CopyFileSection(NuArchive* pArchive, FILE* dstFp, FILE* srcFp,
|
|
long length);
|
|
NuError Nu_GetFileLength(NuArchive* pArchive, FILE* fp, long* pLength);
|
|
NuError Nu_TruncateOpenFile(FILE* fp, long length);
|
|
|
|
/* Funnel.c */
|
|
NuError Nu_ProgressDataInit_Compress(NuArchive* pArchive,
|
|
NuProgressData* pProgressData, const NuRecord* pRecord,
|
|
const UNICHAR* origPathnameUNI, const UNICHAR* pathnameUNI);
|
|
NuError Nu_ProgressDataInit_Expand(NuArchive* pArchive,
|
|
NuProgressData* pProgressData, const NuRecord* pRecord,
|
|
const UNICHAR* newPathnameUNI, UNICHAR newFssep,
|
|
const UNICHAR* origPathnameUNI, NuValue convertEOL);
|
|
NuError Nu_SendInitialProgress(NuArchive* pArchive, NuProgressData* pProgress);
|
|
|
|
NuError Nu_FunnelNew(NuArchive* pArchive, NuDataSink* pDataSink,
|
|
NuValue convertEOL, NuValue convertEOLTo, NuProgressData* pProgress,
|
|
NuFunnel** ppFunnel);
|
|
NuError Nu_FunnelFree(NuArchive* pArchive, NuFunnel* pFunnel);
|
|
/*void Nu_FunnelSetMaxOutput(NuFunnel* pFunnel, uint32_t maxBytes);*/
|
|
NuError Nu_FunnelWrite(NuArchive* pArchive, NuFunnel* pFunnel,
|
|
const uint8_t* buffer, uint32_t count);
|
|
NuError Nu_FunnelFlush(NuArchive* pArchive, NuFunnel* pFunnel);
|
|
NuError Nu_ProgressDataCompressPrep(NuArchive* pArchive, NuStraw* pStraw,
|
|
NuThreadFormat threadFormat, uint32_t sourceLen);
|
|
NuError Nu_ProgressDataExpandPrep(NuArchive* pArchive, NuFunnel* pFunnel,
|
|
const NuThread* pThread);
|
|
NuError Nu_FunnelSetProgressState(NuFunnel* pFunnel, NuProgressState state);
|
|
NuError Nu_FunnelSendProgressUpdate(NuArchive* pArchive, NuFunnel* pFunnel);
|
|
Boolean Nu_FunnelGetDoExpand(NuFunnel* pFunnel);
|
|
|
|
NuError Nu_StrawNew(NuArchive* pArchive, NuDataSource* pDataSource,
|
|
NuProgressData* pProgress, NuStraw** ppStraw);
|
|
NuError Nu_StrawFree(NuArchive* pArchive, NuStraw* pStraw);
|
|
NuError Nu_StrawSetProgressState(NuStraw* pStraw, NuProgressState state);
|
|
NuError Nu_StrawSendProgressUpdate(NuArchive* pArchive, NuStraw* pStraw);
|
|
NuError Nu_StrawRead(NuArchive* pArchive, NuStraw* pStraw, uint8_t* buffer,
|
|
long len);
|
|
NuError Nu_StrawRewind(NuArchive* pArchive, NuStraw* pStraw);
|
|
|
|
/* Lzc.c */
|
|
NuError Nu_CompressLZC12(NuArchive* pArchive, NuStraw* pStraw, FILE* fp,
|
|
uint32_t srcLen, uint32_t* pDstLen, uint16_t* pCrc);
|
|
NuError Nu_CompressLZC16(NuArchive* pArchive, NuStraw* pStraw, FILE* fp,
|
|
uint32_t srcLen, uint32_t* pDstLen, uint16_t* pCrc);
|
|
NuError Nu_ExpandLZC(NuArchive* pArchive, const NuRecord* pRecord,
|
|
const NuThread* pThread, FILE* infp, NuFunnel* pFunnel, uint16_t* pCrc);
|
|
|
|
/* Lzw.c */
|
|
NuError Nu_CompressLZW1(NuArchive* pArchive, NuStraw* pStraw, FILE* fp,
|
|
uint32_t srcLen, uint32_t* pDstLen, uint16_t* pCrc);
|
|
NuError Nu_CompressLZW2(NuArchive* pArchive, NuStraw* pStraw, FILE* fp,
|
|
uint32_t srcLen, uint32_t* pDstLen, uint16_t* pCrc);
|
|
NuError Nu_ExpandLZW(NuArchive* pArchive, const NuRecord* pRecord,
|
|
const NuThread* pThread, FILE* infp, NuFunnel* pFunnel,
|
|
uint16_t* pThreadCrc);
|
|
|
|
/* MiscUtils.c */
|
|
/*extern const char* kNufxLibName;*/
|
|
extern NuCallback gNuGlobalErrorMessageHandler;
|
|
const char* Nu_StrError(NuError err);
|
|
void Nu_ReportError(NuArchive* pArchive, const char* file, int line,
|
|
const char* function, Boolean isDebug, NuError err,
|
|
const UNICHAR* format, ...)
|
|
#if defined(__GNUC__)
|
|
__attribute__ ((format(printf, 7, 8)))
|
|
#endif
|
|
;
|
|
#ifdef USE_DMALLOC /* want file and line numbers for calls */
|
|
# define Nu_Malloc(archive, size) malloc(size)
|
|
# define Nu_Calloc(archive, size) calloc(1, size)
|
|
# define Nu_Realloc(archive, ptr, size) realloc(ptr, size)
|
|
# define Nu_Free(archive, ptr) (ptr != NULL ? free(ptr) : (void)0)
|
|
#else
|
|
void* Nu_Malloc(NuArchive* pArchive, size_t size);
|
|
void* Nu_Calloc(NuArchive* pArchive, size_t size);
|
|
void* Nu_Realloc(NuArchive* pArchive, void* ptr, size_t size);
|
|
void Nu_Free(NuArchive* pArchive, void* ptr);
|
|
#endif
|
|
NuResult Nu_InternalFreeCallback(NuArchive* pArchive, void* args);
|
|
|
|
/* Record.c */
|
|
void Nu_RecordAddThreadMod(NuRecord* pRecord, NuThreadMod* pThreadMod);
|
|
Boolean Nu_RecordIsEmpty(NuArchive* pArchive, const NuRecord* pRecord);
|
|
Boolean Nu_RecordSet_GetLoaded(const NuRecordSet* pRecordSet);
|
|
uint32_t Nu_RecordSet_GetNumRecords(const NuRecordSet* pRecordSet);
|
|
void Nu_RecordSet_SetNumRecords(NuRecordSet* pRecordSet, uint32_t val);
|
|
void Nu_RecordSet_IncNumRecords(NuRecordSet* pRecordSet);
|
|
NuRecord* Nu_RecordSet_GetListHead(const NuRecordSet* pRecordSet);
|
|
NuRecord** Nu_RecordSet_GetListHeadPtr(NuRecordSet* pRecordSet);
|
|
NuRecord* Nu_RecordSet_GetListTail(const NuRecordSet* pRecordSet);
|
|
Boolean Nu_RecordSet_IsEmpty(const NuRecordSet* pRecordSet);
|
|
NuError Nu_RecordSet_FreeAllRecords(NuArchive* pArchive,
|
|
NuRecordSet* pRecordSet);
|
|
NuError Nu_RecordSet_DeleteRecordPtr(NuArchive* pArchive,
|
|
NuRecordSet* pRecordSet, NuRecord** ppRecord);
|
|
NuError Nu_RecordSet_DeleteRecord(NuArchive* pArchive, NuRecordSet* pRecordSet,
|
|
NuRecord* pRecord);
|
|
NuError Nu_RecordSet_Clone(NuArchive* pArchive, NuRecordSet* pDstSet,
|
|
const NuRecordSet* pSrcSet);
|
|
NuError Nu_RecordSet_MoveAllRecords(NuArchive* pArchive, NuRecordSet* pDstSet,
|
|
NuRecordSet* pSrcSet);
|
|
NuError Nu_RecordSet_FindByIdx(const NuRecordSet* pRecordSet, NuRecordIdx rec,
|
|
NuRecord** ppRecord);
|
|
NuError Nu_RecordSet_FindByThreadIdx(NuRecordSet* pRecordSet,
|
|
NuThreadIdx threadIdx, NuRecord** ppRecord, NuThread** ppThread);
|
|
NuError Nu_RecordSet_ReplaceRecord(NuArchive* pArchive, NuRecordSet* pBadSet,
|
|
NuRecord* pBadRecord, NuRecordSet* pGoodSet, NuRecord** ppGoodRecord);
|
|
Boolean Nu_ShouldIgnoreBadCRC(NuArchive* pArchive, const NuRecord* pRecord,
|
|
NuError err);
|
|
NuError Nu_WriteRecordHeader(NuArchive* pArchive, NuRecord* pRecord, FILE* fp);
|
|
NuError Nu_GetTOCIfNeeded(NuArchive* pArchive);
|
|
NuError Nu_StreamContents(NuArchive* pArchive, NuCallback contentFunc);
|
|
NuError Nu_StreamExtract(NuArchive* pArchive);
|
|
NuError Nu_StreamTest(NuArchive* pArchive);
|
|
NuError Nu_Contents(NuArchive* pArchive, NuCallback contentFunc);
|
|
NuError Nu_Extract(NuArchive* pArchive);
|
|
NuError Nu_ExtractRecord(NuArchive* pArchive, NuRecordIdx recIdx);
|
|
NuError Nu_Test(NuArchive* pArchive);
|
|
NuError Nu_TestRecord(NuArchive* pArchive, NuRecordIdx recIdx);
|
|
NuError Nu_GetRecord(NuArchive* pArchive, NuRecordIdx recordIdx,
|
|
const NuRecord** ppRecord);
|
|
NuError Nu_GetRecordIdxByName(NuArchive* pArchive, const char* nameMOR,
|
|
NuRecordIdx* pRecordIdx);
|
|
NuError Nu_GetRecordIdxByPosition(NuArchive* pArchive, uint32_t position,
|
|
NuRecordIdx* pRecordIdx);
|
|
NuError Nu_FindRecordForWriteByIdx(NuArchive* pArchive, NuRecordIdx recIdx,
|
|
NuRecord** ppFoundRecord);
|
|
NuError Nu_AddFile(NuArchive* pArchive, const UNICHAR* pathnameUNI,
|
|
const NuFileDetails* pFileDetails, Boolean fromRsrcFork,
|
|
NuRecordIdx* pRecordIdx);
|
|
NuError Nu_AddRecord(NuArchive* pArchive, const NuFileDetails* pFileDetails,
|
|
NuRecordIdx* pRecordIdx, NuRecord** ppRecord);
|
|
NuError Nu_Rename(NuArchive* pArchive, NuRecordIdx recIdx,
|
|
const char* pathnameMOR, char fssepMOR);
|
|
NuError Nu_SetRecordAttr(NuArchive* pArchive, NuRecordIdx recordIdx,
|
|
const NuRecordAttr* pRecordAttr);
|
|
NuError Nu_Delete(NuArchive* pArchive);
|
|
NuError Nu_DeleteRecord(NuArchive* pArchive, NuRecordIdx rec);
|
|
|
|
/* SourceSink.c */
|
|
NuError Nu_DataSourceFile_New(NuThreadFormat threadFormat,
|
|
uint32_t otherLen, const UNICHAR* pathnameUNI, Boolean isFromRsrcFork,
|
|
NuDataSource** ppDataSource);
|
|
NuError Nu_DataSourceFP_New(NuThreadFormat threadFormat,
|
|
uint32_t otherLen, FILE* fp, long offset, long length,
|
|
NuCallback fcloseFunc, NuDataSource** ppDataSource);
|
|
NuError Nu_DataSourceBuffer_New(NuThreadFormat threadFormat,
|
|
uint32_t otherLen, const uint8_t* buffer, long offset, long length,
|
|
NuCallback freeFunc, NuDataSource** ppDataSource);
|
|
NuDataSource* Nu_DataSourceCopy(NuDataSource* pDataSource);
|
|
NuError Nu_DataSourceFree(NuDataSource* pDataSource);
|
|
NuDataSourceType Nu_DataSourceGetType(const NuDataSource* pDataSource);
|
|
NuThreadFormat Nu_DataSourceGetThreadFormat(const NuDataSource* pDataSource);
|
|
uint32_t Nu_DataSourceGetDataLen(const NuDataSource* pDataSource);
|
|
uint32_t Nu_DataSourceGetOtherLen(const NuDataSource* pDataSource);
|
|
void Nu_DataSourceSetOtherLen(NuDataSource* pDataSource, long otherLen);
|
|
uint16_t Nu_DataSourceGetRawCrc(const NuDataSource* pDataSource);
|
|
void Nu_DataSourceSetRawCrc(NuDataSource* pDataSource, uint16_t crc);
|
|
NuError Nu_DataSourcePrepareInput(NuArchive* pArchive,
|
|
NuDataSource* pDataSource);
|
|
void Nu_DataSourceUnPrepareInput(NuArchive* pArchive,
|
|
NuDataSource* pDataSource);
|
|
const char* Nu_DataSourceFile_GetPathname(NuDataSource* pDataSource);
|
|
NuError Nu_DataSourceGetBlock(NuDataSource* pDataSource, uint8_t* buf,
|
|
uint32_t len);
|
|
NuError Nu_DataSourceRewind(NuDataSource* pDataSource);
|
|
NuError Nu_DataSinkFile_New(Boolean doExpand, NuValue convertEOL,
|
|
const UNICHAR* pathnameUNI, UNICHAR fssep, NuDataSink** ppDataSink);
|
|
NuError Nu_DataSinkFP_New(Boolean doExpand, NuValue convertEOL, FILE* fp,
|
|
NuDataSink** ppDataSink);
|
|
NuError Nu_DataSinkBuffer_New(Boolean doExpand, NuValue convertEOL,
|
|
uint8_t* buffer, uint32_t bufLen, NuDataSink** ppDataSink);
|
|
NuError Nu_DataSinkVoid_New(Boolean doExpand, NuValue convertEOL,
|
|
NuDataSink** ppDataSink);
|
|
NuError Nu_DataSinkFree(NuDataSink* pDataSink);
|
|
NuDataSinkType Nu_DataSinkGetType(const NuDataSink* pDataSink);
|
|
Boolean Nu_DataSinkGetDoExpand(const NuDataSink* pDataSink);
|
|
NuValue Nu_DataSinkGetConvertEOL(const NuDataSink* pDataSink);
|
|
uint32_t Nu_DataSinkGetOutCount(const NuDataSink* pDataSink);
|
|
const char* Nu_DataSinkFile_GetPathname(const NuDataSink* pDataSink);
|
|
UNICHAR Nu_DataSinkFile_GetFssep(const NuDataSink* pDataSink);
|
|
FILE* Nu_DataSinkFile_GetFP(const NuDataSink* pDataSink);
|
|
void Nu_DataSinkFile_SetFP(NuDataSink* pDataSink, FILE* fp);
|
|
void Nu_DataSinkFile_Close(NuDataSink* pDataSink);
|
|
NuError Nu_DataSinkPutBlock(NuDataSink* pDataSink, const uint8_t* buf,
|
|
uint32_t len);
|
|
NuError Nu_DataSinkGetError(NuDataSink* pDataSink);
|
|
|
|
/* Squeeze.c */
|
|
NuError Nu_CompressHuffmanSQ(NuArchive* pArchive, NuStraw* pStraw, FILE* fp,
|
|
uint32_t srcLen, uint32_t* pDstLen, uint16_t* pCrc);
|
|
NuError Nu_ExpandHuffmanSQ(NuArchive* pArchive, const NuRecord* pRecord,
|
|
const NuThread* pThread, FILE* infp, NuFunnel* pFunnel, uint16_t* pCrc);
|
|
|
|
/* Thread.c */
|
|
NuThread* Nu_GetThread(const NuRecord* pRecord, int idx);
|
|
void Nu_StripHiIfAllSet(char* str);
|
|
Boolean Nu_IsPresizedThreadID(NuThreadID threadID);
|
|
Boolean Nu_IsCompressibleThreadID(NuThreadID threadID);
|
|
Boolean Nu_ThreadHasCRC(uint16_t recordVersion, NuThreadID threadID);
|
|
NuError Nu_FindThreadByIdx(const NuRecord* pRecord, NuThreadIdx thread,
|
|
NuThread** ppThread);
|
|
NuError Nu_FindThreadByID(const NuRecord* pRecord, NuThreadID threadID,
|
|
NuThread** ppThread);
|
|
void Nu_CopyThreadContents(NuThread* pDstThread, const NuThread* pSrcThread);
|
|
NuError Nu_ReadThreadHeaders(NuArchive* pArchive, NuRecord* pRecord,
|
|
uint16_t* pCrc);
|
|
NuError Nu_WriteThreadHeaders(NuArchive* pArchive, NuRecord* pRecord, FILE* fp,
|
|
uint16_t* pCrc);
|
|
NuError Nu_ComputeThreadData(NuArchive* pArchive, NuRecord* pRecord);
|
|
NuError Nu_ScanThreads(NuArchive* pArchive, NuRecord* pRecord,long numThreads);
|
|
NuError Nu_ExtractThreadBulk(NuArchive* pArchive, const NuRecord* pRecord,
|
|
const NuThread* pThread);
|
|
NuError Nu_SkipThread(NuArchive* pArchive, const NuRecord* pRecord,
|
|
const NuThread* pThread);
|
|
NuError Nu_ExtractThread(NuArchive* pArchive, NuThreadIdx threadIdx,
|
|
NuDataSink* pDataSink);
|
|
NuError Nu_OkayToAddThread(NuArchive* pArchive, const NuRecord* pRecord,
|
|
NuThreadID threadID);
|
|
NuError Nu_AddThread(NuArchive* pArchive, NuRecordIdx rec, NuThreadID threadID,
|
|
NuDataSource* pDataSource, NuThreadIdx* pThreadIdx);
|
|
NuError Nu_UpdatePresizedThread(NuArchive* pArchive, NuThreadIdx threadIdx,
|
|
NuDataSource* pDataSource, int32_t* pMaxLen);
|
|
NuError Nu_DeleteThread(NuArchive* pArchive, NuThreadIdx threadIdx);
|
|
|
|
/* Value.c */
|
|
NuError Nu_GetValue(NuArchive* pArchive, NuValueID ident, NuValue* pValue);
|
|
NuError Nu_SetValue(NuArchive* pArchive, NuValueID ident, NuValue value);
|
|
NuError Nu_GetAttr(NuArchive* pArchive, NuAttrID ident, NuAttr* pAttr);
|
|
NuThreadFormat Nu_ConvertCompressValToFormat(NuArchive* pArchive,
|
|
NuValue compValue);
|
|
|
|
/* Version.c */
|
|
NuError Nu_GetVersion(int32_t* pMajorVersion, int32_t* pMinorVersion,
|
|
int32_t* pBugVersion, const char** ppBuildDate, const char** ppBuildFlags);
|
|
|
|
#endif /*NUFXLIB_NUFXLIBPRIV_H*/
|