mirror of
https://github.com/fadden/ciderpress.git
synced 2025-02-08 15:30:26 +00:00
Update NufxLib with recent 3.1.0 changes
This commit is contained in:
parent
7596c950fa
commit
6bcf388c3e
@ -1,4 +1,8 @@
|
|||||||
2005/01/09 ***** v3.0.0 shipped *****
|
2015/12/26 fadden
|
||||||
|
- Fix handling of entries with missing threads.
|
||||||
|
- Improve handling of Mac OS X file type attributes.
|
||||||
|
|
||||||
|
2015/01/09 ***** v3.0.0 shipped *****
|
||||||
|
|
||||||
2015/01/03 fadden
|
2015/01/03 fadden
|
||||||
- Mac OS X: replace Carbon FinderInfo calls with BSD xattr.
|
- Mac OS X: replace Carbon FinderInfo calls with BSD xattr.
|
||||||
|
@ -228,6 +228,13 @@ typedef struct NuFileInfo {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Determine whether the record has both data and resource forks.
|
* Determine whether the record has both data and resource forks.
|
||||||
|
*
|
||||||
|
* TODO: if we're not using "mask dataless", scanning threads may not
|
||||||
|
* get the right answer, because GSHK omits theads for zero-length forks.
|
||||||
|
* We could check pRecord->recStorageType, though we have to be careful
|
||||||
|
* because that's overloaded for disk images. In any event, the result
|
||||||
|
* from this method isn't relevant unless we're trying to use forked
|
||||||
|
* files on the native filesystem.
|
||||||
*/
|
*/
|
||||||
static Boolean Nu_IsForkedFile(NuArchive* pArchive, const NuRecord* pRecord)
|
static Boolean Nu_IsForkedFile(NuArchive* pArchive, const NuRecord* pRecord)
|
||||||
{
|
{
|
||||||
@ -320,20 +327,44 @@ static NuError Nu_SetFinderInfo(NuArchive* pArchive, const NuRecord* pRecord,
|
|||||||
return kNuErrFile;
|
return kNuErrFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* build type and creator from 8-bit type and 16-bit aux type */
|
uint8_t proType = (uint8_t) pRecord->recFileType;
|
||||||
uint32_t fileType, creator;
|
uint16_t proAux = (uint16_t) pRecord->recExtraType;
|
||||||
fileType = ('p' << 24) | ((pRecord->recFileType & 0xff) << 16) |
|
|
||||||
(pRecord->recExtraType & 0xffff);
|
|
||||||
creator = 'pdos';
|
|
||||||
|
|
||||||
fiBuf[0] = fileType >> 24;
|
/*
|
||||||
fiBuf[1] = fileType >> 16;
|
* Attempt to use one of the convenience types. If nothing matches,
|
||||||
fiBuf[2] = fileType >> 8;
|
* use the generic pdos/pXYZ approach. Note that PSYS/PS16 will
|
||||||
fiBuf[3] = fileType;
|
* lose the file's aux type.
|
||||||
fiBuf[4] = creator >> 24;
|
*
|
||||||
fiBuf[5] = creator >> 16;
|
* I'm told this is from page 336 of _Programmer's Reference for
|
||||||
fiBuf[6] = creator >> 8;
|
* System 6.0_.
|
||||||
fiBuf[7] = creator;
|
*/
|
||||||
|
uint8_t* fileTypeBuf = fiBuf;
|
||||||
|
uint8_t* creatorBuf = fiBuf + 4;
|
||||||
|
|
||||||
|
memcpy(creatorBuf, "pdos", 4);
|
||||||
|
if (proType == 0x00 && proAux == 0x0000) {
|
||||||
|
memcpy(fileTypeBuf, "BINA", 4);
|
||||||
|
} else if (proType == 0x04 && proAux == 0x0000) {
|
||||||
|
memcpy(fileTypeBuf, "TEXT", 4);
|
||||||
|
} else if (proType == 0xff) {
|
||||||
|
memcpy(fileTypeBuf, "PSYS", 4);
|
||||||
|
} else if (proType == 0xb3 && (proAux & 0xff00) != 0xdb00) {
|
||||||
|
memcpy(fileTypeBuf, "PS16", 4);
|
||||||
|
} else if (proType == 0xd7 && proAux == 0x0000) {
|
||||||
|
memcpy(fileTypeBuf, "MIDI", 4);
|
||||||
|
} else if (proType == 0xd8 && proAux == 0x0000) {
|
||||||
|
memcpy(fileTypeBuf, "AIFF", 4);
|
||||||
|
} else if (proType == 0xd8 && proAux == 0x0001) {
|
||||||
|
memcpy(fileTypeBuf, "AIFC", 4);
|
||||||
|
} else if (proType == 0xe0 && proAux == 0x0005) {
|
||||||
|
memcpy(creatorBuf, "dCpy", 4);
|
||||||
|
memcpy(fileTypeBuf, "dImg", 4);
|
||||||
|
} else {
|
||||||
|
fileTypeBuf[0] = 'p';
|
||||||
|
fileTypeBuf[1] = proType;
|
||||||
|
fileTypeBuf[2] = (uint8_t) (proAux >> 8);
|
||||||
|
fileTypeBuf[3] = (uint8_t) proAux;
|
||||||
|
}
|
||||||
|
|
||||||
if (setxattr(pathnameUNI, XATTR_FINDERINFO_NAME, fiBuf, sizeof(fiBuf),
|
if (setxattr(pathnameUNI, XATTR_FINDERINFO_NAME, fiBuf, sizeof(fiBuf),
|
||||||
0, 0) != 0)
|
0, 0) != 0)
|
||||||
|
@ -33,7 +33,7 @@ extern "C" {
|
|||||||
* fixes. Unless, of course, your code depends upon that fix.
|
* fixes. Unless, of course, your code depends upon that fix.
|
||||||
*/
|
*/
|
||||||
#define kNuVersionMajor 3
|
#define kNuVersionMajor 3
|
||||||
#define kNuVersionMinor 0
|
#define kNuVersionMinor 1
|
||||||
#define kNuVersionBug 0
|
#define kNuVersionBug 0
|
||||||
|
|
||||||
|
|
||||||
@ -201,13 +201,16 @@ typedef uint32_t NuThreadID;
|
|||||||
#define kNuThreadClassControl 0x0001
|
#define kNuThreadClassControl 0x0001
|
||||||
#define kNuThreadClassData 0x0002
|
#define kNuThreadClassData 0x0002
|
||||||
#define kNuThreadClassFilename 0x0003
|
#define kNuThreadClassFilename 0x0003
|
||||||
|
#define kNuThreadKindDataFork 0x0000 /* when class=data */
|
||||||
|
#define kNuThreadKindDiskImage 0x0001 /* when class=data */
|
||||||
|
#define kNuThreadKindRsrcFork 0x0002 /* when class=data */
|
||||||
#define kNuThreadIDOldComment NuMakeThreadID(kNuThreadClassMessage, 0x0000)
|
#define kNuThreadIDOldComment NuMakeThreadID(kNuThreadClassMessage, 0x0000)
|
||||||
#define kNuThreadIDComment NuMakeThreadID(kNuThreadClassMessage, 0x0001)
|
#define kNuThreadIDComment NuMakeThreadID(kNuThreadClassMessage, 0x0001)
|
||||||
#define kNuThreadIDIcon NuMakeThreadID(kNuThreadClassMessage, 0x0002)
|
#define kNuThreadIDIcon NuMakeThreadID(kNuThreadClassMessage, 0x0002)
|
||||||
#define kNuThreadIDMkdir NuMakeThreadID(kNuThreadClassControl, 0x0000)
|
#define kNuThreadIDMkdir NuMakeThreadID(kNuThreadClassControl, 0x0000)
|
||||||
#define kNuThreadIDDataFork NuMakeThreadID(kNuThreadClassData, 0x0000)
|
#define kNuThreadIDDataFork NuMakeThreadID(kNuThreadClassData, kNuThreadKindDataFork)
|
||||||
#define kNuThreadIDDiskImage NuMakeThreadID(kNuThreadClassData, 0x0001)
|
#define kNuThreadIDDiskImage NuMakeThreadID(kNuThreadClassData, kNuThreadKindDiskImage)
|
||||||
#define kNuThreadIDRsrcFork NuMakeThreadID(kNuThreadClassData, 0x0002)
|
#define kNuThreadIDRsrcFork NuMakeThreadID(kNuThreadClassData, kNuThreadKindRsrcFork)
|
||||||
#define kNuThreadIDFilename NuMakeThreadID(kNuThreadClassFilename, 0x0000)
|
#define kNuThreadIDFilename NuMakeThreadID(kNuThreadClassFilename, 0x0000)
|
||||||
#define kNuThreadIDWildcard NuMakeThreadID(0xffff, 0xffff)
|
#define kNuThreadIDWildcard NuMakeThreadID(0xffff, 0xffff)
|
||||||
|
|
||||||
|
@ -1524,7 +1524,7 @@ NuError Nu_StreamExtract(NuArchive* pArchive)
|
|||||||
{
|
{
|
||||||
NuError err = kNuErrNone;
|
NuError err = kNuErrNone;
|
||||||
NuRecord tmpRecord;
|
NuRecord tmpRecord;
|
||||||
Boolean hasInterestingThread;
|
Boolean needFakeData, needFakeRsrc;
|
||||||
uint32_t count;
|
uint32_t count;
|
||||||
long idx;
|
long idx;
|
||||||
|
|
||||||
@ -1573,7 +1573,8 @@ NuError Nu_StreamExtract(NuArchive* pArchive)
|
|||||||
/*Nu_DebugDumpRecord(&tmpRecord);
|
/*Nu_DebugDumpRecord(&tmpRecord);
|
||||||
printf("\n");*/
|
printf("\n");*/
|
||||||
|
|
||||||
hasInterestingThread = false;
|
needFakeData = true;
|
||||||
|
needFakeRsrc = (tmpRecord.recStorageType == kNuStorageExtended);
|
||||||
|
|
||||||
/* extract all relevant (remaining) threads */
|
/* extract all relevant (remaining) threads */
|
||||||
pArchive->lastFileCreatedUNI = NULL;
|
pArchive->lastFileCreatedUNI = NULL;
|
||||||
@ -1581,7 +1582,11 @@ NuError Nu_StreamExtract(NuArchive* pArchive)
|
|||||||
const NuThread* pThread = Nu_GetThread(&tmpRecord, idx);
|
const NuThread* pThread = Nu_GetThread(&tmpRecord, idx);
|
||||||
|
|
||||||
if (pThread->thThreadClass == kNuThreadClassData) {
|
if (pThread->thThreadClass == kNuThreadClassData) {
|
||||||
hasInterestingThread = true;
|
if (pThread->thThreadKind == kNuThreadKindDataFork) {
|
||||||
|
needFakeData = false;
|
||||||
|
} else if (pThread->thThreadKind == kNuThreadKindRsrcFork) {
|
||||||
|
needFakeRsrc = false;
|
||||||
|
}
|
||||||
err = Nu_ExtractThreadBulk(pArchive, &tmpRecord, pThread);
|
err = Nu_ExtractThreadBulk(pArchive, &tmpRecord, pThread);
|
||||||
if (err == kNuErrSkipped) {
|
if (err == kNuErrSkipped) {
|
||||||
err = Nu_SkipThread(pArchive, &tmpRecord, pThread);
|
err = Nu_SkipThread(pArchive, &tmpRecord, pThread);
|
||||||
@ -1595,7 +1600,8 @@ NuError Nu_StreamExtract(NuArchive* pArchive)
|
|||||||
if (NuGetThreadID(pThread) != kNuThreadIDComment &&
|
if (NuGetThreadID(pThread) != kNuThreadIDComment &&
|
||||||
NuGetThreadID(pThread) != kNuThreadIDFilename)
|
NuGetThreadID(pThread) != kNuThreadIDFilename)
|
||||||
{
|
{
|
||||||
hasInterestingThread = true;
|
/* unknown stuff in record, skip thread fakery */
|
||||||
|
needFakeData = needFakeRsrc = false;
|
||||||
}
|
}
|
||||||
err = Nu_SkipThread(pArchive, &tmpRecord, pThread);
|
err = Nu_SkipThread(pArchive, &tmpRecord, pThread);
|
||||||
BailError(err);
|
BailError(err);
|
||||||
@ -1603,19 +1609,19 @@ NuError Nu_StreamExtract(NuArchive* pArchive)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we're trying to be compatible with ShrinkIt, and the record
|
* As in Nu_ExtractRecordByPtr, we need to synthesize empty forks for
|
||||||
* had nothing in it but comments and filenames, then we need to
|
* cases where GSHK omitted the data thread entirely.
|
||||||
* create a zero-byte data file (and possibly a resource fork).
|
|
||||||
*
|
|
||||||
* See notes in previous instance, above.
|
|
||||||
*/
|
*/
|
||||||
if (/*pArchive->valMaskDataless &&*/ !hasInterestingThread) {
|
Assert(!pArchive->valMaskDataless || (!needFakeData && !needFakeRsrc));
|
||||||
err = Nu_FakeZeroExtract(pArchive, &tmpRecord, 0x0000);
|
if (needFakeData) {
|
||||||
|
err = Nu_FakeZeroExtract(pArchive, &tmpRecord,
|
||||||
|
kNuThreadKindDataFork);
|
||||||
|
BailError(err);
|
||||||
|
}
|
||||||
|
if (needFakeRsrc) {
|
||||||
|
err = Nu_FakeZeroExtract(pArchive, &tmpRecord,
|
||||||
|
kNuThreadKindRsrcFork);
|
||||||
BailError(err);
|
BailError(err);
|
||||||
if (tmpRecord.recStorageType == kNuStorageExtended) {
|
|
||||||
err = Nu_FakeZeroExtract(pArchive, &tmpRecord, 0x0002);
|
|
||||||
BailError(err);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* dispose of the entry */
|
/* dispose of the entry */
|
||||||
@ -1698,20 +1704,26 @@ bail:
|
|||||||
static NuError Nu_ExtractRecordByPtr(NuArchive* pArchive, NuRecord* pRecord)
|
static NuError Nu_ExtractRecordByPtr(NuArchive* pArchive, NuRecord* pRecord)
|
||||||
{
|
{
|
||||||
NuError err = kNuErrNone;
|
NuError err = kNuErrNone;
|
||||||
Boolean hasInterestingThread;
|
Boolean needFakeData, needFakeRsrc;
|
||||||
uint32_t idx;
|
uint32_t idx;
|
||||||
|
|
||||||
|
needFakeData = true;
|
||||||
|
needFakeRsrc = (pRecord->recStorageType == kNuStorageExtended);
|
||||||
|
|
||||||
Assert(!Nu_IsStreaming(pArchive)); /* we don't skip things we don't read */
|
Assert(!Nu_IsStreaming(pArchive)); /* we don't skip things we don't read */
|
||||||
Assert(pRecord != NULL);
|
Assert(pRecord != NULL);
|
||||||
|
|
||||||
/* extract all relevant threads */
|
/* extract all relevant threads */
|
||||||
hasInterestingThread = false;
|
|
||||||
pArchive->lastFileCreatedUNI = NULL;
|
pArchive->lastFileCreatedUNI = NULL;
|
||||||
for (idx = 0; idx < pRecord->recTotalThreads; idx++) {
|
for (idx = 0; idx < pRecord->recTotalThreads; idx++) {
|
||||||
const NuThread* pThread = Nu_GetThread(pRecord, idx);
|
const NuThread* pThread = Nu_GetThread(pRecord, idx);
|
||||||
|
|
||||||
if (pThread->thThreadClass == kNuThreadClassData) {
|
if (pThread->thThreadClass == kNuThreadClassData) {
|
||||||
hasInterestingThread = true;
|
if (pThread->thThreadKind == kNuThreadKindDataFork) {
|
||||||
|
needFakeData = false;
|
||||||
|
} else if (pThread->thThreadKind == kNuThreadKindRsrcFork) {
|
||||||
|
needFakeRsrc = false;
|
||||||
|
}
|
||||||
err = Nu_ExtractThreadBulk(pArchive, pRecord, pThread);
|
err = Nu_ExtractThreadBulk(pArchive, pRecord, pThread);
|
||||||
if (err == kNuErrSkipped) {
|
if (err == kNuErrSkipped) {
|
||||||
err = Nu_SkipThread(pArchive, pRecord, pThread);
|
err = Nu_SkipThread(pArchive, pRecord, pThread);
|
||||||
@ -1722,7 +1734,13 @@ static NuError Nu_ExtractRecordByPtr(NuArchive* pArchive, NuRecord* pRecord)
|
|||||||
if (NuGetThreadID(pThread) != kNuThreadIDComment &&
|
if (NuGetThreadID(pThread) != kNuThreadIDComment &&
|
||||||
NuGetThreadID(pThread) != kNuThreadIDFilename)
|
NuGetThreadID(pThread) != kNuThreadIDFilename)
|
||||||
{
|
{
|
||||||
hasInterestingThread = true;
|
/*
|
||||||
|
* This record has a thread we don't recognize. Disable
|
||||||
|
* the thread fakery to avoid doing anything weird -- we
|
||||||
|
* should only need to create zero-length files for
|
||||||
|
* simple file records.
|
||||||
|
*/
|
||||||
|
needFakeData = needFakeRsrc = false;
|
||||||
}
|
}
|
||||||
DBUG(("IGNORING 0x%08lx from '%s'\n",
|
DBUG(("IGNORING 0x%08lx from '%s'\n",
|
||||||
NuMakeThreadID(pThread->thThreadClass, pThread->thThreadKind),
|
NuMakeThreadID(pThread->thThreadClass, pThread->thThreadKind),
|
||||||
@ -1731,28 +1749,27 @@ static NuError Nu_ExtractRecordByPtr(NuArchive* pArchive, NuRecord* pRecord)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we're trying to be compatible with ShrinkIt, and the record
|
* GSHK creates empty threads for zero-length forks. It doesn't always
|
||||||
* had nothing in it but comments and filenames, then we need to
|
* handle them correctly when extracting, so it appears this behavior
|
||||||
* create a zero-byte file.
|
* may not be intentional.
|
||||||
*
|
*
|
||||||
* (GSHK handles empty data and resource forks by not storing a
|
* We need to create an empty file for whichever forks are missing.
|
||||||
* thread at all. It doesn't correctly deal with them when extracting
|
* Could be the data fork, resource fork, or both. The only way to
|
||||||
* though, so it appears this behavior wasn't entirely expected.)
|
* know what's expected is to examine the file's storage type.
|
||||||
*
|
*
|
||||||
* If it's a forked file, we also need to create an empty rsrc file.
|
* If valMaskDataless is enabled, this won't fire, because we will have
|
||||||
*
|
* "forged" the appropriate threads.
|
||||||
* If valMaskDataless is enabled, this won't fire, because we "forge"
|
|
||||||
* appropriate threads.
|
|
||||||
*
|
*
|
||||||
* Note there's another one of these below, in Nu_StreamExtract.
|
* Note there's another one of these below, in Nu_StreamExtract.
|
||||||
*/
|
*/
|
||||||
if (/*pArchive->valMaskDataless &&*/ !hasInterestingThread) {
|
Assert(!pArchive->valMaskDataless || (!needFakeData && !needFakeRsrc));
|
||||||
err = Nu_FakeZeroExtract(pArchive, pRecord, 0x0000 /*data*/);
|
if (needFakeData) {
|
||||||
|
err = Nu_FakeZeroExtract(pArchive, pRecord, kNuThreadKindDataFork);
|
||||||
|
BailError(err);
|
||||||
|
}
|
||||||
|
if (needFakeRsrc) {
|
||||||
|
err = Nu_FakeZeroExtract(pArchive, pRecord, kNuThreadKindRsrcFork);
|
||||||
BailError(err);
|
BailError(err);
|
||||||
if (pRecord->recStorageType == kNuStorageExtended) {
|
|
||||||
err = Nu_FakeZeroExtract(pArchive, pRecord, 0x0002 /*rsrc*/);
|
|
||||||
BailError(err);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bail:
|
bail:
|
||||||
|
@ -193,7 +193,10 @@ NuError Nu_ReadThreadHeaders(NuArchive* pArchive, NuRecord* pRecord,
|
|||||||
NuError err = kNuErrNone;
|
NuError err = kNuErrNone;
|
||||||
NuThread* pThread;
|
NuThread* pThread;
|
||||||
long count;
|
long count;
|
||||||
Boolean hasData = false;
|
Boolean needFakeData, needFakeRsrc;
|
||||||
|
|
||||||
|
needFakeData = true;
|
||||||
|
needFakeRsrc = (pRecord->recStorageType == kNuStorageExtended);
|
||||||
|
|
||||||
Assert(pArchive != NULL);
|
Assert(pArchive != NULL);
|
||||||
Assert(pRecord != NULL);
|
Assert(pRecord != NULL);
|
||||||
@ -215,8 +218,13 @@ NuError Nu_ReadThreadHeaders(NuArchive* pArchive, NuRecord* pRecord,
|
|||||||
err = Nu_ReadThreadHeader(pArchive, pThread, pCrc);
|
err = Nu_ReadThreadHeader(pArchive, pThread, pCrc);
|
||||||
BailError(err);
|
BailError(err);
|
||||||
|
|
||||||
if (pThread->thThreadClass == kNuThreadClassData)
|
if (pThread->thThreadClass == kNuThreadClassData) {
|
||||||
hasData = true;
|
if (pThread->thThreadKind == kNuThreadKindDataFork) {
|
||||||
|
needFakeData = false;
|
||||||
|
} else if (pThread->thThreadKind == kNuThreadKindRsrcFork) {
|
||||||
|
needFakeRsrc = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Some versions of ShrinkIt write an invalid thThreadEOF for disks,
|
* Some versions of ShrinkIt write an invalid thThreadEOF for disks,
|
||||||
@ -258,13 +266,14 @@ NuError Nu_ReadThreadHeaders(NuArchive* pArchive, NuRecord* pRecord,
|
|||||||
* If "mask threadless" is set, create "fake" threads with empty
|
* If "mask threadless" is set, create "fake" threads with empty
|
||||||
* data and resource forks as needed.
|
* data and resource forks as needed.
|
||||||
*/
|
*/
|
||||||
if (!hasData && pArchive->valMaskDataless) {
|
if ((needFakeData || needFakeRsrc) && pArchive->valMaskDataless) {
|
||||||
Boolean needRsrc = (pRecord->recStorageType == kNuStorageExtended);
|
|
||||||
int firstNewThread = pRecord->recTotalThreads;
|
int firstNewThread = pRecord->recTotalThreads;
|
||||||
|
|
||||||
pRecord->recTotalThreads++;
|
if (needFakeData) {
|
||||||
pRecord->fakeThreads++;
|
pRecord->recTotalThreads++;
|
||||||
if (needRsrc) {
|
pRecord->fakeThreads++;
|
||||||
|
}
|
||||||
|
if (needFakeRsrc) {
|
||||||
pRecord->recTotalThreads++;
|
pRecord->recTotalThreads++;
|
||||||
pRecord->fakeThreads++;
|
pRecord->fakeThreads++;
|
||||||
}
|
}
|
||||||
@ -275,22 +284,23 @@ NuError Nu_ReadThreadHeaders(NuArchive* pArchive, NuRecord* pRecord,
|
|||||||
|
|
||||||
pThread = pRecord->pThreads + firstNewThread;
|
pThread = pRecord->pThreads + firstNewThread;
|
||||||
|
|
||||||
pThread->thThreadClass = kNuThreadClassData;
|
if (needFakeData) {
|
||||||
pThread->thThreadFormat = kNuThreadFormatUncompressed;
|
|
||||||
pThread->thThreadKind = 0x0000; /* data fork */
|
|
||||||
pThread->thThreadCRC = kNuInitialThreadCRC;
|
|
||||||
pThread->thThreadEOF = 0;
|
|
||||||
pThread->thCompThreadEOF = 0;
|
|
||||||
pThread->threadIdx = Nu_GetNextThreadIdx(pArchive);
|
|
||||||
pThread->actualThreadEOF = 0;
|
|
||||||
pThread->fileOffset = -99999999;
|
|
||||||
pThread->used = false;
|
|
||||||
|
|
||||||
if (needRsrc) {
|
|
||||||
pThread++;
|
|
||||||
pThread->thThreadClass = kNuThreadClassData;
|
pThread->thThreadClass = kNuThreadClassData;
|
||||||
pThread->thThreadFormat = kNuThreadFormatUncompressed;
|
pThread->thThreadFormat = kNuThreadFormatUncompressed;
|
||||||
pThread->thThreadKind = 0x0002; /* rsrc fork */
|
pThread->thThreadKind = kNuThreadKindDataFork;
|
||||||
|
pThread->thThreadCRC = kNuInitialThreadCRC;
|
||||||
|
pThread->thThreadEOF = 0;
|
||||||
|
pThread->thCompThreadEOF = 0;
|
||||||
|
pThread->threadIdx = Nu_GetNextThreadIdx(pArchive);
|
||||||
|
pThread->actualThreadEOF = 0;
|
||||||
|
pThread->fileOffset = -99999999;
|
||||||
|
pThread->used = false;
|
||||||
|
pThread++;
|
||||||
|
}
|
||||||
|
if (needFakeRsrc) {
|
||||||
|
pThread->thThreadClass = kNuThreadClassData;
|
||||||
|
pThread->thThreadFormat = kNuThreadFormatUncompressed;
|
||||||
|
pThread->thThreadKind = kNuThreadKindRsrcFork;
|
||||||
pThread->thThreadCRC = kNuInitialThreadCRC;
|
pThread->thThreadCRC = kNuInitialThreadCRC;
|
||||||
pThread->thThreadEOF = 0;
|
pThread->thThreadEOF = 0;
|
||||||
pThread->thCompThreadEOF = 0;
|
pThread->thCompThreadEOF = 0;
|
||||||
|
@ -24,6 +24,15 @@ static const char kFssep = PATH_SEP;
|
|||||||
|
|
||||||
#define kTempFile "exer-temp"
|
#define kTempFile "exer-temp"
|
||||||
|
|
||||||
|
#ifndef HAVE_STRCASECMP
|
||||||
|
static int strcasecmp(const char *str1, const char *str2)
|
||||||
|
{
|
||||||
|
while (*str1 && *str2 && toupper(*str1) == toupper(*str2))
|
||||||
|
str1++, str2++;
|
||||||
|
return (toupper(*str1) - toupper(*str2));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ===========================================================================
|
* ===========================================================================
|
||||||
@ -364,13 +373,25 @@ static NuError AbortFunc(ExerciserState* pState, int argc, char** argv)
|
|||||||
static NuError AddFileFunc(ExerciserState* pState, int argc, char** argv)
|
static NuError AddFileFunc(ExerciserState* pState, int argc, char** argv)
|
||||||
{
|
{
|
||||||
NuFileDetails nuFileDetails;
|
NuFileDetails nuFileDetails;
|
||||||
|
int fromRsrc = false;
|
||||||
|
|
||||||
(void) pState, (void) argc, (void) argv; /* shut up, gcc */
|
(void) pState, (void) argc, (void) argv; /* shut up, gcc */
|
||||||
assert(ExerciserState_GetNuArchive(pState) != NULL);
|
assert(ExerciserState_GetNuArchive(pState) != NULL);
|
||||||
assert(argc == 2);
|
assert(argc == 3);
|
||||||
|
|
||||||
|
if (strcasecmp(argv[2], "true") == 0) {
|
||||||
|
fromRsrc = true;
|
||||||
|
} else if (strcasecmp(argv[2], "false") != 0) {
|
||||||
|
fprintf(stderr, "WARNING: fromRsrc should be 'true' or 'false'\n");
|
||||||
|
/* ignore */
|
||||||
|
}
|
||||||
|
|
||||||
memset(&nuFileDetails, 0, sizeof(nuFileDetails));
|
memset(&nuFileDetails, 0, sizeof(nuFileDetails));
|
||||||
nuFileDetails.threadID = kNuThreadIDDataFork;
|
if (fromRsrc) {
|
||||||
|
nuFileDetails.threadID = kNuThreadIDRsrcFork;
|
||||||
|
} else {
|
||||||
|
nuFileDetails.threadID = kNuThreadIDDataFork;
|
||||||
|
}
|
||||||
nuFileDetails.storageNameMOR = argv[1];
|
nuFileDetails.storageNameMOR = argv[1];
|
||||||
nuFileDetails.fileSysID = kNuFileSysUnknown;
|
nuFileDetails.fileSysID = kNuFileSysUnknown;
|
||||||
nuFileDetails.fileSysInfo = (short) kFssep;
|
nuFileDetails.fileSysInfo = (short) kFssep;
|
||||||
@ -378,7 +399,7 @@ static NuError AddFileFunc(ExerciserState* pState, int argc, char** argv)
|
|||||||
/* fileType, extraType, storageType, dates */
|
/* fileType, extraType, storageType, dates */
|
||||||
|
|
||||||
return NuAddFile(ExerciserState_GetNuArchive(pState), argv[1],
|
return NuAddFile(ExerciserState_GetNuArchive(pState), argv[1],
|
||||||
&nuFileDetails, false, NULL);
|
&nuFileDetails, fromRsrc, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1039,7 +1060,7 @@ static const struct {
|
|||||||
|
|
||||||
{ "ab", AbortFunc, 0, "", kFlagArchiveReq,
|
{ "ab", AbortFunc, 0, "", kFlagArchiveReq,
|
||||||
"Abort current changes" },
|
"Abort current changes" },
|
||||||
{ "af", AddFileFunc, 1, "filename", kFlagArchiveReq,
|
{ "af", AddFileFunc, 2, "filename fromRsrc", kFlagArchiveReq,
|
||||||
"Add file" },
|
"Add file" },
|
||||||
{ "ar", AddRecordFunc, 1, "storageName", kFlagArchiveReq,
|
{ "ar", AddRecordFunc, 1, "storageName", kFlagArchiveReq,
|
||||||
"Add record" },
|
"Add record" },
|
||||||
|
@ -16,8 +16,7 @@
|
|||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
|
|
||||||
#ifndef HAVE_STRCASECMP
|
#ifndef HAVE_STRCASECMP
|
||||||
static int
|
static int strcasecmp(const char *str1, const char *str2)
|
||||||
strcasecmp(const char *str1, const char *str2)
|
|
||||||
{
|
{
|
||||||
while (*str1 && *str2 && toupper(*str1) == toupper(*str2))
|
while (*str1 && *str2 && toupper(*str1) == toupper(*str2))
|
||||||
str1++, str2++;
|
str1++, str2++;
|
||||||
|
@ -298,7 +298,8 @@ int Test_AddStuff(NuArchive* pArchive)
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create an empty file with a rather non-empty name.
|
* Create an empty file with a rather non-empty name. Add it as
|
||||||
|
* a resource fork.
|
||||||
*/
|
*/
|
||||||
printf("... add 'long' record\n");
|
printf("... add 'long' record\n");
|
||||||
err = NuCreateDataSourceForBuffer(kNuThreadFormatUncompressed,
|
err = NuCreateDataSourceForBuffer(kNuThreadFormatUncompressed,
|
||||||
@ -454,7 +455,8 @@ failed:
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Selection callback filter for "test". This gets called once per record.
|
* Selection callback filter for "test". This gets called once per record,
|
||||||
|
* twice per record for forked files.
|
||||||
*/
|
*/
|
||||||
NuResult VerifySelectionCallback(NuArchive* pArchive, void* vpProposal)
|
NuResult VerifySelectionCallback(NuArchive* pArchive, void* vpProposal)
|
||||||
{
|
{
|
||||||
@ -523,7 +525,9 @@ int Test_Verify(NuArchive* pArchive)
|
|||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count != kNumEntries) {
|
/* the count will be one higher than the number of records because
|
||||||
|
the last entry is forked, and each fork is tested separately */
|
||||||
|
if (count != kNumEntries + 1) {
|
||||||
fprintf(stderr, "ERROR: verified %ld when expecting %d\n", count,
|
fprintf(stderr, "ERROR: verified %ld when expecting %d\n", count,
|
||||||
kNumEntries);
|
kNumEntries);
|
||||||
goto failed;
|
goto failed;
|
||||||
|
@ -184,6 +184,7 @@ CRCList* GatherCRCs(NuArchive* pArchive)
|
|||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int rsrcCrcIdx = -1;
|
||||||
for (i = 0; i < (int)NuRecordGetNumThreads(pRecord); i++) {
|
for (i = 0; i < (int)NuRecordGetNumThreads(pRecord); i++) {
|
||||||
pThread = NuGetThread(pRecord, i);
|
pThread = NuGetThread(pRecord, i);
|
||||||
if (pThread->thThreadClass == kNuThreadClassData) {
|
if (pThread->thThreadClass == kNuThreadClassData) {
|
||||||
@ -194,7 +195,30 @@ CRCList* GatherCRCs(NuArchive* pArchive)
|
|||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
pEntries[crcIdx++] = pThread->thThreadCRC;
|
/*
|
||||||
|
* Ensure that the data fork CRC comes first. Otherwise
|
||||||
|
* we can fail if it gets rearranged. This is only a
|
||||||
|
* problem for GSHK-created archives that don't have
|
||||||
|
* threads for every fork, so "mask dataless" is create
|
||||||
|
* fake entries.
|
||||||
|
*
|
||||||
|
* The correct way to do this is to store a tuple
|
||||||
|
* { thread-kind, crc }, but that's more work.
|
||||||
|
*/
|
||||||
|
if (pThread->thThreadKind == kNuThreadKindRsrcFork) {
|
||||||
|
rsrcCrcIdx = crcIdx;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pThread->thThreadKind == kNuThreadKindDataFork &&
|
||||||
|
rsrcCrcIdx != -1)
|
||||||
|
{
|
||||||
|
/* this is the data fork, we've already seen the
|
||||||
|
resource fork; swap entries */
|
||||||
|
pEntries[crcIdx++] = pEntries[rsrcCrcIdx];
|
||||||
|
pEntries[rsrcCrcIdx] = pThread->thThreadCRC;
|
||||||
|
} else {
|
||||||
|
pEntries[crcIdx++] = pThread->thThreadCRC;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user