Distinguish Unicode and Mac OS Roman strings

NufxLib has historically made no effort to distinguish between
the character set used for filenames on the local disk, and for
filenames stored within the archive.  Now all Unicode filename
strings use the UNICHAR type and have "UNI" in the name, and all
Mac OS Roman strings have "MOR" in the name.  (The naming
convention makes it obvious when you're assigning the wrong thing;
on Linux both formats are char*, so the compiler won't tell you
if you get it wrong.)

The distinction is necessary because filesystems generally support
Unicode these days, but on Windows you need to use a separate
set of wide-character file I/O functions.  (On Linux it all works
with "narrow" strings, and the UTF-8 encoding is interpreted by
applications.)  The character set used for NuFX archive filenames
is MOR, matching what GS/OS + HFS supported, and we want to be able
to convert back and forth between MOR and a Unicode representation.

This change updates the various character types and string names,
adds conversion functions, and updates NuLib2 for proper execution
on Linux.  It does not include the (probably extensive) changes
required for Windows UTF-16 support.  Instead, the conversion
functions are no-ops, which should result in NuLib2 for Windows
continuing to behave in the same slightly broken way.

This adds "test-names", which exercises Unicode filenames a bit.
It will not pass on Win32.

Also, tweaked the Linux makefiles to have explicit dependencies,
rather than empty space and an expectation that "makedepend" exists.

Also, minor source code cleanups.

While this probably doesn't affect binary compatibility -- it's
mainly a matter of naming and string interpretation -- there's
enough going on that it should be considered an API revision, so
this updates the version to 3.0.0.
This commit is contained in:
Andy McFadden 2014-12-24 11:14:32 -08:00
parent f4dea8b251
commit e2088e64d3
47 changed files with 2160 additions and 925 deletions

1
nufxlib/.gitignore vendored
View File

@ -11,5 +11,6 @@ samples/imgconv
samples/launder samples/launder
samples/test-basic samples/test-basic
samples/test-extract samples/test-extract
samples/test-names
samples/test-simple samples/test-simple
samples/test-twirl samples/test-twirl

View File

@ -114,8 +114,8 @@ static NuError Nu_NuArchiveFree(NuArchive* pArchive)
(void) Nu_RecordSet_FreeAllRecords(pArchive, &pArchive->copyRecordSet); (void) Nu_RecordSet_FreeAllRecords(pArchive, &pArchive->copyRecordSet);
(void) Nu_RecordSet_FreeAllRecords(pArchive, &pArchive->newRecordSet); (void) Nu_RecordSet_FreeAllRecords(pArchive, &pArchive->newRecordSet);
Nu_Free(NULL, pArchive->archivePathname); Nu_Free(NULL, pArchive->archivePathnameUNI);
Nu_Free(NULL, pArchive->tmpPathname); Nu_Free(NULL, pArchive->tmpPathnameUNI);
Nu_Free(NULL, pArchive->compBuf); Nu_Free(NULL, pArchive->compBuf);
Nu_Free(NULL, pArchive->lzwCompressState); Nu_Free(NULL, pArchive->lzwCompressState);
Nu_Free(NULL, pArchive->lzwExpandState); Nu_Free(NULL, pArchive->lzwExpandState);
@ -743,7 +743,7 @@ NuError Nu_StreamOpenRO(FILE* infp, NuArchive** ppArchive)
pArchive->openMode = kNuOpenStreamingRO; pArchive->openMode = kNuOpenStreamingRO;
pArchive->archiveFp = infp; pArchive->archiveFp = infp;
pArchive->archivePathname = strdup("(stream)"); pArchive->archivePathnameUNI = strdup("(stream)");
err = Nu_ReadMasterHeader(pArchive); err = Nu_ReadMasterHeader(pArchive);
BailError(err); BailError(err);
@ -761,20 +761,24 @@ bail:
/* /*
* Open an archive in non-streaming read-only mode. * Open an archive in non-streaming read-only mode.
*/ */
NuError Nu_OpenRO(const char* archivePathname, NuArchive** ppArchive) NuError Nu_OpenRO(const UNICHAR* archivePathnameUNI, NuArchive** ppArchive)
{ {
NuError err; NuError err;
NuArchive* pArchive = NULL; NuArchive* pArchive = NULL;
FILE* fp = NULL; FILE* fp = NULL;
if (archivePathname == NULL || !strlen(archivePathname) || ppArchive == NULL) if (archivePathnameUNI == NULL || !strlen(archivePathnameUNI) ||
ppArchive == NULL)
{
return kNuErrInvalidArg; return kNuErrInvalidArg;
}
*ppArchive = NULL; *ppArchive = NULL;
fp = fopen(archivePathname, kNuFileOpenReadOnly); fp = fopen(archivePathnameUNI, kNuFileOpenReadOnly);
if (fp == NULL) { if (fp == NULL) {
Nu_ReportError(NU_BLOB, errno, "Unable to open '%s'", archivePathname); Nu_ReportError(NU_BLOB, errno, "Unable to open '%s'",
archivePathnameUNI);
err = kNuErrFileOpen; err = kNuErrFileOpen;
goto bail; goto bail;
} }
@ -787,7 +791,7 @@ NuError Nu_OpenRO(const char* archivePathname, NuArchive** ppArchive)
pArchive->openMode = kNuOpenRO; pArchive->openMode = kNuOpenRO;
pArchive->archiveFp = fp; pArchive->archiveFp = fp;
fp = NULL; fp = NULL;
pArchive->archivePathname = strdup(archivePathname); pArchive->archivePathnameUNI = strdup(archivePathnameUNI);
err = Nu_ReadMasterHeader(pArchive); err = Nu_ReadMasterHeader(pArchive);
BailError(err); BailError(err);
@ -807,12 +811,13 @@ bail:
/* /*
* Open a temp file. If "fileName" contains six Xs ("XXXXXX"), it will * Open a temp file. If "fileName" contains six Xs ("XXXXXX"), it will
* be treated as a mktemp-style template, and modified before use. * be treated as a mktemp-style template, and modified before use (so
* pass a copy of the string in).
* *
* Thought for the day: consider using Win32 SetFileAttributes() to make * Thought for the day: consider using Win32 SetFileAttributes() to make
* temp files hidden. We will need to un-hide it before rolling it over. * temp files hidden. We will need to un-hide it before rolling it over.
*/ */
static NuError Nu_OpenTempFile(char* fileName, FILE** pFp) static NuError Nu_OpenTempFile(UNICHAR* fileNameUNI, FILE** pFp)
{ {
NuArchive* pArchive = NULL; /* dummy for NU_BLOB */ NuArchive* pArchive = NULL; /* dummy for NU_BLOB */
NuError err = kNuErrNone; NuError err = kNuErrNone;
@ -827,23 +832,23 @@ static NuError Nu_OpenTempFile(char* fileName, FILE** pFp)
* to complain about mktemp, since it's generally a bad way to do * to complain about mktemp, since it's generally a bad way to do
* things. * things.
*/ */
len = strlen(fileName); len = strlen(fileNameUNI);
if (len > 6 && strcmp(fileName + len - 6, "XXXXXX") == 0) { if (len > 6 && strcmp(fileNameUNI + len - 6, "XXXXXX") == 0) {
#if defined(HAVE_MKSTEMP) && defined(HAVE_FDOPEN) #if defined(HAVE_MKSTEMP) && defined(HAVE_FDOPEN)
int fd; int fd;
DBUG(("+++ Using mkstemp\n")); DBUG(("+++ Using mkstemp\n"));
/* this modifies the template *and* opens the file */ /* this modifies the template *and* opens the file */
fd = mkstemp(fileName); fd = mkstemp(fileNameUNI);
if (fd < 0) { if (fd < 0) {
err = errno ? errno : kNuErrFileOpen; err = errno ? errno : kNuErrFileOpen;
Nu_ReportError(NU_BLOB, kNuErrNone, "mkstemp failed on '%s'", Nu_ReportError(NU_BLOB, kNuErrNone, "mkstemp failed on '%s'",
fileName); fileNameUNI);
goto bail; goto bail;
} }
DBUG(("--- Fd-opening temp file '%s'\n", fileName)); DBUG(("--- Fd-opening temp file '%s'\n", fileNameUNI));
*pFp = fdopen(fd, kNuFileOpenReadWriteCreat); *pFp = fdopen(fd, kNuFileOpenReadWriteCreat);
if (*pFp == NULL) { if (*pFp == NULL) {
close(fd); close(fd);
@ -858,10 +863,10 @@ static NuError Nu_OpenTempFile(char* fileName, FILE** pFp)
char* result; char* result;
DBUG(("+++ Using mktemp\n")); DBUG(("+++ Using mktemp\n"));
result = mktemp(fileName); result = mktemp(fileNameUNI);
if (result == NULL) { if (result == NULL) {
Nu_ReportError(NU_BLOB, kNuErrNone, "mktemp failed on '%s'", Nu_ReportError(NU_BLOB, kNuErrNone, "mktemp failed on '%s'",
fileName); fileNameUNI);
err = kNuErrInternal; err = kNuErrInternal;
goto bail; goto bail;
} }
@ -870,13 +875,13 @@ static NuError Nu_OpenTempFile(char* fileName, FILE** pFp)
#endif #endif
} }
DBUG(("--- Opening temp file '%s'\n", fileName)); DBUG(("--- Opening temp file '%s'\n", fileNameUNI));
#if defined(HAVE_FDOPEN) #if defined(HAVE_FDOPEN)
{ {
int fd; int fd;
fd = open(fileName, O_RDWR|O_CREAT|O_EXCL|O_BINARY, 0600); fd = open(fileNameUNI, O_RDWR|O_CREAT|O_EXCL|O_BINARY, 0600);
if (fd < 0) { if (fd < 0) {
err = errno ? errno : kNuErrFileOpen; err = errno ? errno : kNuErrFileOpen;
goto bail; goto bail;
@ -890,13 +895,12 @@ static NuError Nu_OpenTempFile(char* fileName, FILE** pFp)
} }
} }
#else #else
/* (not sure how portable "access" is... I think it's POSIX) */ if (access(fileNameUNI, F_OK) == 0) {
if (access(fileName, F_OK) == 0) {
err = kNuErrFileExists; err = kNuErrFileExists;
goto bail; goto bail;
} }
*pFp = fopen(fileName, kNuFileOpenReadWriteCreat); *pFp = fopen(fileNameUNI, kNuFileOpenReadWriteCreat);
if (*pFp == NULL) { if (*pFp == NULL) {
err = errno ? errno : kNuErrFileOpen; err = errno ? errno : kNuErrFileOpen;
goto bail; goto bail;
@ -912,8 +916,8 @@ bail:
* Open an archive in read-write mode, optionally creating it if it doesn't * Open an archive in read-write mode, optionally creating it if it doesn't
* exist. * exist.
*/ */
NuError Nu_OpenRW(const char* archivePathname, const char* tmpPathname, NuError Nu_OpenRW(const UNICHAR* archivePathnameUNI,
uint32_t flags, NuArchive** ppArchive) const UNICHAR* tmpPathnameUNI, uint32_t flags, NuArchive** ppArchive)
{ {
NuError err; NuError err;
FILE* fp = NULL; FILE* fp = NULL;
@ -923,14 +927,14 @@ NuError Nu_OpenRW(const char* archivePathname, const char* tmpPathname,
Boolean archiveExists; Boolean archiveExists;
Boolean newlyCreated; Boolean newlyCreated;
if (archivePathname == NULL || !strlen(archivePathname) || if (archivePathnameUNI == NULL || !strlen(archivePathnameUNI) ||
tmpPathname == NULL || !strlen(tmpPathname) || ppArchive == NULL || tmpPathnameUNI == NULL || !strlen(tmpPathnameUNI) ||
(flags & ~(kNuOpenCreat|kNuOpenExcl)) != 0) ppArchive == NULL || (flags & ~(kNuOpenCreat|kNuOpenExcl)) != 0)
{ {
return kNuErrInvalidArg; return kNuErrInvalidArg;
} }
archiveExists = (access(archivePathname, F_OK) == 0); archiveExists = (access(archivePathnameUNI, F_OK) == 0);
/* /*
* Open or create archive file. * Open or create archive file.
@ -938,18 +942,20 @@ NuError Nu_OpenRW(const char* archivePathname, const char* tmpPathname,
if (archiveExists) { if (archiveExists) {
if ((flags & kNuOpenCreat) && (flags & kNuOpenExcl)) { if ((flags & kNuOpenCreat) && (flags & kNuOpenExcl)) {
err = kNuErrFileExists; err = kNuErrFileExists;
Nu_ReportError(NU_BLOB, err, "File '%s' exists", archivePathname); Nu_ReportError(NU_BLOB, err, "File '%s' exists",
archivePathnameUNI);
goto bail; goto bail;
} }
fp = fopen(archivePathname, kNuFileOpenReadWrite); fp = fopen(archivePathnameUNI, kNuFileOpenReadWrite);
newlyCreated = false; newlyCreated = false;
} else { } else {
if (!(flags & kNuOpenCreat)) { if (!(flags & kNuOpenCreat)) {
err = kNuErrFileNotFound; err = kNuErrFileNotFound;
Nu_ReportError(NU_BLOB, err, "File '%s' not found",archivePathname); Nu_ReportError(NU_BLOB, err, "File '%s' not found",
archivePathnameUNI);
goto bail; goto bail;
} }
fp = fopen(archivePathname, kNuFileOpenReadWriteCreat); fp = fopen(archivePathnameUNI, kNuFileOpenReadWriteCreat);
newlyCreated = true; newlyCreated = true;
} }
@ -958,7 +964,8 @@ NuError Nu_OpenRW(const char* archivePathname, const char* tmpPathname,
err = kNuErrFileAccessDenied; err = kNuErrFileAccessDenied;
else else
err = kNuErrFileOpen; err = kNuErrFileOpen;
Nu_ReportError(NU_BLOB, errno, "Unable to open '%s'", archivePathname); Nu_ReportError(NU_BLOB, errno, "Unable to open '%s'",
archivePathnameUNI);
goto bail; goto bail;
} }
@ -986,12 +993,12 @@ NuError Nu_OpenRW(const char* archivePathname, const char* tmpPathname,
* So, create a temp file whether we think we need one or not. Won't * So, create a temp file whether we think we need one or not. Won't
* do any harm, and might save us some troubles later. * do any harm, and might save us some troubles later.
*/ */
tmpPathDup = strdup(tmpPathname); tmpPathDup = strdup(tmpPathnameUNI);
BailNil(tmpPathDup); BailNil(tmpPathDup);
err = Nu_OpenTempFile(tmpPathDup, &tmpFp); err = Nu_OpenTempFile(tmpPathDup, &tmpFp);
if (err != kNuErrNone) { if (err != kNuErrNone) {
Nu_ReportError(NU_BLOB, err, "Failed opening temp file '%s'", Nu_ReportError(NU_BLOB, err, "Failed opening temp file '%s'",
tmpPathname); tmpPathnameUNI);
goto bail; goto bail;
} }
@ -1002,12 +1009,12 @@ NuError Nu_OpenRW(const char* archivePathname, const char* tmpPathname,
pArchive->openMode = kNuOpenRW; pArchive->openMode = kNuOpenRW;
pArchive->newlyCreated = newlyCreated; pArchive->newlyCreated = newlyCreated;
pArchive->archivePathname = strdup(archivePathname); pArchive->archivePathnameUNI = strdup(archivePathnameUNI);
pArchive->archiveFp = fp; pArchive->archiveFp = fp;
fp = NULL; fp = NULL;
pArchive->tmpFp = tmpFp; pArchive->tmpFp = tmpFp;
tmpFp = NULL; tmpFp = NULL;
pArchive->tmpPathname = tmpPathDup; pArchive->tmpPathnameUNI = tmpPathDup;
tmpPathDup = NULL; tmpPathDup = NULL;
if (archiveExists && !newlyCreated) { if (archiveExists && !newlyCreated) {
@ -1116,10 +1123,10 @@ static void Nu_CloseAndFree(NuArchive* pArchive)
DBUG(("--- Closing and removing temp file\n")); DBUG(("--- Closing and removing temp file\n"));
fclose(pArchive->tmpFp); fclose(pArchive->tmpFp);
pArchive->tmpFp = NULL; pArchive->tmpFp = NULL;
Assert(pArchive->tmpPathname != NULL); Assert(pArchive->tmpPathnameUNI != NULL);
if (remove(pArchive->tmpPathname) != 0) { if (remove(pArchive->tmpPathnameUNI) != 0) {
Nu_ReportError(NU_BLOB, errno, "Unable to remove temp file '%s'", Nu_ReportError(NU_BLOB, errno, "Unable to remove temp file '%s'",
pArchive->tmpPathname); pArchive->tmpPathnameUNI);
/* keep going */ /* keep going */
} }
} }
@ -1127,9 +1134,9 @@ static void Nu_CloseAndFree(NuArchive* pArchive)
if (pArchive->newlyCreated && Nu_RecordSet_IsEmpty(&pArchive->origRecordSet)) if (pArchive->newlyCreated && Nu_RecordSet_IsEmpty(&pArchive->origRecordSet))
{ {
DBUG(("--- Newly-created archive unmodified; removing it\n")); DBUG(("--- Newly-created archive unmodified; removing it\n"));
if (remove(pArchive->archivePathname) != 0) { if (remove(pArchive->archivePathnameUNI) != 0) {
Nu_ReportError(NU_BLOB, errno, "Unable to remove archive file '%s'", Nu_ReportError(NU_BLOB, errno, "Unable to remove archive file '%s'",
pArchive->archivePathname); pArchive->archivePathnameUNI);
} }
} }
@ -1142,7 +1149,7 @@ static void Nu_CloseAndFree(NuArchive* pArchive)
NuError Nu_Close(NuArchive* pArchive) NuError Nu_Close(NuArchive* pArchive)
{ {
NuError err = kNuErrNone; NuError err = kNuErrNone;
long flushStatus; uint32_t flushStatus;
Assert(pArchive != NULL); Assert(pArchive != NULL);
@ -1174,9 +1181,9 @@ NuError Nu_DeleteArchiveFile(NuArchive* pArchive)
{ {
Assert(pArchive != NULL); Assert(pArchive != NULL);
Assert(pArchive->archiveFp == NULL); Assert(pArchive->archiveFp == NULL);
Assert(pArchive->archivePathname != NULL); Assert(pArchive->archivePathnameUNI != NULL);
return Nu_DeleteFile(pArchive->archivePathname); return Nu_DeleteFile(pArchive->archivePathnameUNI);
} }
/* /*
@ -1188,9 +1195,10 @@ NuError Nu_RenameTempToArchive(NuArchive* pArchive)
Assert(pArchive != NULL); Assert(pArchive != NULL);
Assert(pArchive->archiveFp == NULL); Assert(pArchive->archiveFp == NULL);
Assert(pArchive->tmpFp == NULL); Assert(pArchive->tmpFp == NULL);
Assert(pArchive->archivePathname != NULL); Assert(pArchive->archivePathnameUNI != NULL);
Assert(pArchive->tmpPathname != NULL); Assert(pArchive->tmpPathnameUNI != NULL);
return Nu_RenameFile(pArchive->tmpPathname, pArchive->archivePathname); return Nu_RenameFile(pArchive->tmpPathnameUNI,
pArchive->archivePathnameUNI);
} }

View File

@ -156,7 +156,7 @@ bz_bail:
bail: bail:
if (outbuf != NULL) if (outbuf != NULL)
free(outbuf); Nu_Free(NULL, outbuf);
return err; return err;
} }
@ -289,7 +289,7 @@ bz_bail:
bail: bail:
if (outbuf != NULL) if (outbuf != NULL)
free(outbuf); Nu_Free(NULL, outbuf);
return err; return err;
} }

554
nufxlib/Charset.c Normal file
View File

@ -0,0 +1,554 @@
/*
* NuFX archive manipulation library
* Copyright (C) 2014 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.
*
* Miscellaneous NufxLib utility functions.
*/
#include "NufxLibPriv.h"
/*
* Convert Mac OS Roman to Unicode. Mapping comes from:
*
* http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/ROMAN.TXT
*
* We use the "Control Pictures" block for the control characters
* (0x00-0x1f, 0x7f --> 0x2400-0x241f, 0x2421). This is a bit nicer
* than embedding control characters in filenames.
*/
static const uint16_t gMORToUnicode[256] = {
/*0x00*/ 0x2400, // [control] NULL
/*0x01*/ 0x2401, // [control] START OF HEADING
/*0x02*/ 0x2402, // [control] START OF TEXT
/*0x03*/ 0x2403, // [control] END OF TEXT
/*0x04*/ 0x2404, // [control] END OF TRANSMISSION
/*0x05*/ 0x2405, // [control] ENQUIRY
/*0x06*/ 0x2406, // [control] ACKNOWLEDGE
/*0x07*/ 0x2407, // [control] BELL
/*0x08*/ 0x2408, // [control] BACKSPACE
/*0x09*/ 0x2409, // [control] HORIZONTAL TABULATION
/*0x0a*/ 0x240a, // [control] LINE FEED
/*0x0b*/ 0x240b, // [control] VERTICAL TABULATION
/*0x0c*/ 0x240c, // [control] FORM FEED
/*0x0d*/ 0x240d, // [control] CARRIAGE RETURN
/*0x0e*/ 0x240e, // [control] SHIFT OUT
/*0x0f*/ 0x240f, // [control] SHIFT IN
/*0x10*/ 0x2410, // [control] DATA LINK ESCAPE
/*0x11*/ 0x2411, // [control] DEVICE CONTROL ONE
/*0x12*/ 0x2412, // [control] DEVICE CONTROL TWO
/*0x13*/ 0x2413, // [control] DEVICE CONTROL THREE
/*0x14*/ 0x2414, // [control] DEVICE CONTROL FOUR
/*0x15*/ 0x2415, // [control] NEGATIVE ACKNOWLEDGE
/*0x16*/ 0x2416, // [control] SYNCHRONOUS IDLE
/*0x17*/ 0x2417, // [control] END OF TRANSMISSION BLOCK
/*0x18*/ 0x2418, // [control] CANCEL
/*0x19*/ 0x2419, // [control] END OF MEDIUM
/*0x1a*/ 0x241a, // [control] SUBSTITUTE
/*0x1b*/ 0x241b, // [control] ESCAPE
/*0x1c*/ 0x241c, // [control] FILE SEPARATOR
/*0x1d*/ 0x241d, // [control] GROUP SEPARATOR
/*0x1e*/ 0x241e, // [control] RECORD SEPARATOR
/*0x1f*/ 0x241f, // [control] UNIT SEPARATOR
/*0x20*/ 0x0020, // SPACE
/*0x21*/ 0x0021, // EXCLAMATION MARK
/*0x22*/ 0x0022, // QUOTATION MARK
/*0x23*/ 0x0023, // NUMBER SIGN
/*0x24*/ 0x0024, // DOLLAR SIGN
/*0x25*/ 0x0025, // PERCENT SIGN
/*0x26*/ 0x0026, // AMPERSAND
/*0x27*/ 0x0027, // APOSTROPHE
/*0x28*/ 0x0028, // LEFT PARENTHESIS
/*0x29*/ 0x0029, // RIGHT PARENTHESIS
/*0x2A*/ 0x002A, // ASTERISK
/*0x2B*/ 0x002B, // PLUS SIGN
/*0x2C*/ 0x002C, // COMMA
/*0x2D*/ 0x002D, // HYPHEN-MINUS
/*0x2E*/ 0x002E, // FULL STOP
/*0x2F*/ 0x002F, // SOLIDUS
/*0x30*/ 0x0030, // DIGIT ZERO
/*0x31*/ 0x0031, // DIGIT ONE
/*0x32*/ 0x0032, // DIGIT TWO
/*0x33*/ 0x0033, // DIGIT THREE
/*0x34*/ 0x0034, // DIGIT FOUR
/*0x35*/ 0x0035, // DIGIT FIVE
/*0x36*/ 0x0036, // DIGIT SIX
/*0x37*/ 0x0037, // DIGIT SEVEN
/*0x38*/ 0x0038, // DIGIT EIGHT
/*0x39*/ 0x0039, // DIGIT NINE
/*0x3A*/ 0x003A, // COLON
/*0x3B*/ 0x003B, // SEMICOLON
/*0x3C*/ 0x003C, // LESS-THAN SIGN
/*0x3D*/ 0x003D, // EQUALS SIGN
/*0x3E*/ 0x003E, // GREATER-THAN SIGN
/*0x3F*/ 0x003F, // QUESTION MARK
/*0x40*/ 0x0040, // COMMERCIAL AT
/*0x41*/ 0x0041, // LATIN CAPITAL LETTER A
/*0x42*/ 0x0042, // LATIN CAPITAL LETTER B
/*0x43*/ 0x0043, // LATIN CAPITAL LETTER C
/*0x44*/ 0x0044, // LATIN CAPITAL LETTER D
/*0x45*/ 0x0045, // LATIN CAPITAL LETTER E
/*0x46*/ 0x0046, // LATIN CAPITAL LETTER F
/*0x47*/ 0x0047, // LATIN CAPITAL LETTER G
/*0x48*/ 0x0048, // LATIN CAPITAL LETTER H
/*0x49*/ 0x0049, // LATIN CAPITAL LETTER I
/*0x4A*/ 0x004A, // LATIN CAPITAL LETTER J
/*0x4B*/ 0x004B, // LATIN CAPITAL LETTER K
/*0x4C*/ 0x004C, // LATIN CAPITAL LETTER L
/*0x4D*/ 0x004D, // LATIN CAPITAL LETTER M
/*0x4E*/ 0x004E, // LATIN CAPITAL LETTER N
/*0x4F*/ 0x004F, // LATIN CAPITAL LETTER O
/*0x50*/ 0x0050, // LATIN CAPITAL LETTER P
/*0x51*/ 0x0051, // LATIN CAPITAL LETTER Q
/*0x52*/ 0x0052, // LATIN CAPITAL LETTER R
/*0x53*/ 0x0053, // LATIN CAPITAL LETTER S
/*0x54*/ 0x0054, // LATIN CAPITAL LETTER T
/*0x55*/ 0x0055, // LATIN CAPITAL LETTER U
/*0x56*/ 0x0056, // LATIN CAPITAL LETTER V
/*0x57*/ 0x0057, // LATIN CAPITAL LETTER W
/*0x58*/ 0x0058, // LATIN CAPITAL LETTER X
/*0x59*/ 0x0059, // LATIN CAPITAL LETTER Y
/*0x5A*/ 0x005A, // LATIN CAPITAL LETTER Z
/*0x5B*/ 0x005B, // LEFT SQUARE BRACKET
/*0x5C*/ 0x005C, // REVERSE SOLIDUS
/*0x5D*/ 0x005D, // RIGHT SQUARE BRACKET
/*0x5E*/ 0x005E, // CIRCUMFLEX ACCENT
/*0x5F*/ 0x005F, // LOW LINE
/*0x60*/ 0x0060, // GRAVE ACCENT
/*0x61*/ 0x0061, // LATIN SMALL LETTER A
/*0x62*/ 0x0062, // LATIN SMALL LETTER B
/*0x63*/ 0x0063, // LATIN SMALL LETTER C
/*0x64*/ 0x0064, // LATIN SMALL LETTER D
/*0x65*/ 0x0065, // LATIN SMALL LETTER E
/*0x66*/ 0x0066, // LATIN SMALL LETTER F
/*0x67*/ 0x0067, // LATIN SMALL LETTER G
/*0x68*/ 0x0068, // LATIN SMALL LETTER H
/*0x69*/ 0x0069, // LATIN SMALL LETTER I
/*0x6A*/ 0x006A, // LATIN SMALL LETTER J
/*0x6B*/ 0x006B, // LATIN SMALL LETTER K
/*0x6C*/ 0x006C, // LATIN SMALL LETTER L
/*0x6D*/ 0x006D, // LATIN SMALL LETTER M
/*0x6E*/ 0x006E, // LATIN SMALL LETTER N
/*0x6F*/ 0x006F, // LATIN SMALL LETTER O
/*0x70*/ 0x0070, // LATIN SMALL LETTER P
/*0x71*/ 0x0071, // LATIN SMALL LETTER Q
/*0x72*/ 0x0072, // LATIN SMALL LETTER R
/*0x73*/ 0x0073, // LATIN SMALL LETTER S
/*0x74*/ 0x0074, // LATIN SMALL LETTER T
/*0x75*/ 0x0075, // LATIN SMALL LETTER U
/*0x76*/ 0x0076, // LATIN SMALL LETTER V
/*0x77*/ 0x0077, // LATIN SMALL LETTER W
/*0x78*/ 0x0078, // LATIN SMALL LETTER X
/*0x79*/ 0x0079, // LATIN SMALL LETTER Y
/*0x7A*/ 0x007A, // LATIN SMALL LETTER Z
/*0x7B*/ 0x007B, // LEFT CURLY BRACKET
/*0x7C*/ 0x007C, // VERTICAL LINE
/*0x7D*/ 0x007D, // RIGHT CURLY BRACKET
/*0x7E*/ 0x007E, // TILDE
/*0x7f*/ 0x2421, // [control] DELETE
/*0x80*/ 0x00C4, // LATIN CAPITAL LETTER A WITH DIAERESIS
/*0x81*/ 0x00C5, // LATIN CAPITAL LETTER A WITH RING ABOVE
/*0x82*/ 0x00C7, // LATIN CAPITAL LETTER C WITH CEDILLA
/*0x83*/ 0x00C9, // LATIN CAPITAL LETTER E WITH ACUTE
/*0x84*/ 0x00D1, // LATIN CAPITAL LETTER N WITH TILDE
/*0x85*/ 0x00D6, // LATIN CAPITAL LETTER O WITH DIAERESIS
/*0x86*/ 0x00DC, // LATIN CAPITAL LETTER U WITH DIAERESIS
/*0x87*/ 0x00E1, // LATIN SMALL LETTER A WITH ACUTE
/*0x88*/ 0x00E0, // LATIN SMALL LETTER A WITH GRAVE
/*0x89*/ 0x00E2, // LATIN SMALL LETTER A WITH CIRCUMFLEX
/*0x8A*/ 0x00E4, // LATIN SMALL LETTER A WITH DIAERESIS
/*0x8B*/ 0x00E3, // LATIN SMALL LETTER A WITH TILDE
/*0x8C*/ 0x00E5, // LATIN SMALL LETTER A WITH RING ABOVE
/*0x8D*/ 0x00E7, // LATIN SMALL LETTER C WITH CEDILLA
/*0x8E*/ 0x00E9, // LATIN SMALL LETTER E WITH ACUTE
/*0x8F*/ 0x00E8, // LATIN SMALL LETTER E WITH GRAVE
/*0x90*/ 0x00EA, // LATIN SMALL LETTER E WITH CIRCUMFLEX
/*0x91*/ 0x00EB, // LATIN SMALL LETTER E WITH DIAERESIS
/*0x92*/ 0x00ED, // LATIN SMALL LETTER I WITH ACUTE
/*0x93*/ 0x00EC, // LATIN SMALL LETTER I WITH GRAVE
/*0x94*/ 0x00EE, // LATIN SMALL LETTER I WITH CIRCUMFLEX
/*0x95*/ 0x00EF, // LATIN SMALL LETTER I WITH DIAERESIS
/*0x96*/ 0x00F1, // LATIN SMALL LETTER N WITH TILDE
/*0x97*/ 0x00F3, // LATIN SMALL LETTER O WITH ACUTE
/*0x98*/ 0x00F2, // LATIN SMALL LETTER O WITH GRAVE
/*0x99*/ 0x00F4, // LATIN SMALL LETTER O WITH CIRCUMFLEX
/*0x9A*/ 0x00F6, // LATIN SMALL LETTER O WITH DIAERESIS
/*0x9B*/ 0x00F5, // LATIN SMALL LETTER O WITH TILDE
/*0x9C*/ 0x00FA, // LATIN SMALL LETTER U WITH ACUTE
/*0x9D*/ 0x00F9, // LATIN SMALL LETTER U WITH GRAVE
/*0x9E*/ 0x00FB, // LATIN SMALL LETTER U WITH CIRCUMFLEX
/*0x9F*/ 0x00FC, // LATIN SMALL LETTER U WITH DIAERESIS
/*0xA0*/ 0x2020, // DAGGER
/*0xA1*/ 0x00B0, // DEGREE SIGN
/*0xA2*/ 0x00A2, // CENT SIGN
/*0xA3*/ 0x00A3, // POUND SIGN
/*0xA4*/ 0x00A7, // SECTION SIGN
/*0xA5*/ 0x2022, // BULLET
/*0xA6*/ 0x00B6, // PILCROW SIGN
/*0xA7*/ 0x00DF, // LATIN SMALL LETTER SHARP S
/*0xA8*/ 0x00AE, // REGISTERED SIGN
/*0xA9*/ 0x00A9, // COPYRIGHT SIGN
/*0xAA*/ 0x2122, // TRADE MARK SIGN
/*0xAB*/ 0x00B4, // ACUTE ACCENT
/*0xAC*/ 0x00A8, // DIAERESIS
/*0xAD*/ 0x2260, // NOT EQUAL TO
/*0xAE*/ 0x00C6, // LATIN CAPITAL LETTER AE
/*0xAF*/ 0x00D8, // LATIN CAPITAL LETTER O WITH STROKE
/*0xB0*/ 0x221E, // INFINITY
/*0xB1*/ 0x00B1, // PLUS-MINUS SIGN
/*0xB2*/ 0x2264, // LESS-THAN OR EQUAL TO
/*0xB3*/ 0x2265, // GREATER-THAN OR EQUAL TO
/*0xB4*/ 0x00A5, // YEN SIGN
/*0xB5*/ 0x00B5, // MICRO SIGN
/*0xB6*/ 0x2202, // PARTIAL DIFFERENTIAL
/*0xB7*/ 0x2211, // N-ARY SUMMATION
/*0xB8*/ 0x220F, // N-ARY PRODUCT
/*0xB9*/ 0x03C0, // GREEK SMALL LETTER PI
/*0xBA*/ 0x222B, // INTEGRAL
/*0xBB*/ 0x00AA, // FEMININE ORDINAL INDICATOR
/*0xBC*/ 0x00BA, // MASCULINE ORDINAL INDICATOR
/*0xBD*/ 0x03A9, // GREEK CAPITAL LETTER OMEGA
/*0xBE*/ 0x00E6, // LATIN SMALL LETTER AE
/*0xBF*/ 0x00F8, // LATIN SMALL LETTER O WITH STROKE
/*0xC0*/ 0x00BF, // INVERTED QUESTION MARK
/*0xC1*/ 0x00A1, // INVERTED EXCLAMATION MARK
/*0xC2*/ 0x00AC, // NOT SIGN
/*0xC3*/ 0x221A, // SQUARE ROOT
/*0xC4*/ 0x0192, // LATIN SMALL LETTER F WITH HOOK
/*0xC5*/ 0x2248, // ALMOST EQUAL TO
/*0xC6*/ 0x2206, // INCREMENT
/*0xC7*/ 0x00AB, // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
/*0xC8*/ 0x00BB, // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
/*0xC9*/ 0x2026, // HORIZONTAL ELLIPSIS
/*0xCA*/ 0x00A0, // NO-BREAK SPACE
/*0xCB*/ 0x00C0, // LATIN CAPITAL LETTER A WITH GRAVE
/*0xCC*/ 0x00C3, // LATIN CAPITAL LETTER A WITH TILDE
/*0xCD*/ 0x00D5, // LATIN CAPITAL LETTER O WITH TILDE
/*0xCE*/ 0x0152, // LATIN CAPITAL LIGATURE OE
/*0xCF*/ 0x0153, // LATIN SMALL LIGATURE OE
/*0xD0*/ 0x2013, // EN DASH
/*0xD1*/ 0x2014, // EM DASH
/*0xD2*/ 0x201C, // LEFT DOUBLE QUOTATION MARK
/*0xD3*/ 0x201D, // RIGHT DOUBLE QUOTATION MARK
/*0xD4*/ 0x2018, // LEFT SINGLE QUOTATION MARK
/*0xD5*/ 0x2019, // RIGHT SINGLE QUOTATION MARK
/*0xD6*/ 0x00F7, // DIVISION SIGN
/*0xD7*/ 0x25CA, // LOZENGE
/*0xD8*/ 0x00FF, // LATIN SMALL LETTER Y WITH DIAERESIS
/*0xD9*/ 0x0178, // LATIN CAPITAL LETTER Y WITH DIAERESIS
/*0xDA*/ 0x2044, // FRACTION SLASH
/*0xDB*/ 0x00A4, // CURRENCY SIGN (was EURO SIGN)
/*0xDC*/ 0x2039, // SINGLE LEFT-POINTING ANGLE QUOTATION MARK
/*0xDD*/ 0x203A, // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
/*0xDE*/ 0xFB01, // LATIN SMALL LIGATURE FI
/*0xDF*/ 0xFB02, // LATIN SMALL LIGATURE FL
/*0xE0*/ 0x2021, // DOUBLE DAGGER
/*0xE1*/ 0x00B7, // MIDDLE DOT
/*0xE2*/ 0x201A, // SINGLE LOW-9 QUOTATION MARK
/*0xE3*/ 0x201E, // DOUBLE LOW-9 QUOTATION MARK
/*0xE4*/ 0x2030, // PER MILLE SIGN
/*0xE5*/ 0x00C2, // LATIN CAPITAL LETTER A WITH CIRCUMFLEX
/*0xE6*/ 0x00CA, // LATIN CAPITAL LETTER E WITH CIRCUMFLEX
/*0xE7*/ 0x00C1, // LATIN CAPITAL LETTER A WITH ACUTE
/*0xE8*/ 0x00CB, // LATIN CAPITAL LETTER E WITH DIAERESIS
/*0xE9*/ 0x00C8, // LATIN CAPITAL LETTER E WITH GRAVE
/*0xEA*/ 0x00CD, // LATIN CAPITAL LETTER I WITH ACUTE
/*0xEB*/ 0x00CE, // LATIN CAPITAL LETTER I WITH CIRCUMFLEX
/*0xEC*/ 0x00CF, // LATIN CAPITAL LETTER I WITH DIAERESIS
/*0xED*/ 0x00CC, // LATIN CAPITAL LETTER I WITH GRAVE
/*0xEE*/ 0x00D3, // LATIN CAPITAL LETTER O WITH ACUTE
/*0xEF*/ 0x00D4, // LATIN CAPITAL LETTER O WITH CIRCUMFLEX
/*0xF0*/ 0xF8FF, // Apple logo
/*0xF1*/ 0x00D2, // LATIN CAPITAL LETTER O WITH GRAVE
/*0xF2*/ 0x00DA, // LATIN CAPITAL LETTER U WITH ACUTE
/*0xF3*/ 0x00DB, // LATIN CAPITAL LETTER U WITH CIRCUMFLEX
/*0xF4*/ 0x00D9, // LATIN CAPITAL LETTER U WITH GRAVE
/*0xF5*/ 0x0131, // LATIN SMALL LETTER DOTLESS I
/*0xF6*/ 0x02C6, // MODIFIER LETTER CIRCUMFLEX ACCENT
/*0xF7*/ 0x02DC, // SMALL TILDE
/*0xF8*/ 0x00AF, // MACRON
/*0xF9*/ 0x02D8, // BREVE
/*0xFA*/ 0x02D9, // DOT ABOVE
/*0xFB*/ 0x02DA, // RING ABOVE
/*0xFC*/ 0x00B8, // CEDILLA
/*0xFD*/ 0x02DD, // DOUBLE ACUTE ACCENT
/*0xFE*/ 0x02DB, // OGONEK
/*0xFF*/ 0x02C7 // CARON
};
/*
* Static table, populated on first use. Provides the inverse map.
*
* An entry with 0x00 indicates no conversion. That's incorrect for
* the entry for '\0', but since we're operating on null-terminated
* strings that's never valid anyway. (It's possible for a filename
* to contain 0x2400, but that would translate to 0x00, which we don't
* allow; so it makes more sense to treat it as illegal.)
*/
static uint8_t gUnicodeToMOR[65536] = { 0xff /*indicates not initialized*/ };
static void Nu_GenerateUnicodeToMOR(void)
{
memset(gUnicodeToMOR, 0, sizeof(gUnicodeToMOR));
int i;
for (i = 0; i < 256; i++) {
int codePoint = gMORToUnicode[i];
Assert(codePoint >= 0 && codePoint < 65536);
gUnicodeToMOR[codePoint] = i;
}
}
/*
* Converts stringMOR to Unicode, storing the output in bufUNI until it's
* full. Null termination is guaranteed. If the buffer size is zero or
* bufUNI is NULL, no string data is returned.
*
* Returns the number of bytes required to represent stringMOR in Unicode.
*/
size_t Nu_ConvertMORToUNI(const char* stringMOR, UNICHAR* bufUNI,
size_t bufSize)
{
Assert(stringMOR != 0);
#ifdef _WIN32
/* place-holder if we're not using UTF-16 yet */
Assert(sizeof(UNICHAR) == 1);
size_t morLen = strlen(stringMOR) + 1;
if (bufUNI != NULL && bufSize != 0) {
size_t copyLen = morLen < bufSize ? morLen : bufSize;
memcpy(bufUNI, stringMOR, copyLen);
bufUNI[bufSize-1] = '\0';
}
return morLen;
#else
/*
* Convert Mac OS Roman to UTF-8. We only output full code points,
* so if only the first byte of a UTF-8 sequence will fit we just
* stop early.
*/
size_t uniLen = 0;
Boolean doOutput = (bufUNI != NULL);
while (*stringMOR != '\0') {
// ASCII values just "convert" to themselves in this table
uint16_t us = gMORToUnicode[(uint8_t)*stringMOR];
if (us < 0x80) {
// single byte, no conversion
if (uniLen+1 >= bufSize) {
doOutput = false;
}
if (doOutput) {
bufUNI[uniLen] = (char) us;
}
uniLen++;
} else if (us < 0x7ff) {
// two bytes
if (uniLen+2 >= bufSize) {
doOutput = false;
}
if (doOutput) {
bufUNI[uniLen] = (us >> 6) | 0xc0;
bufUNI[uniLen+1] = (us & 0x3f) | 0x80;
}
uniLen += 2;
} else {
// three bytes
if (uniLen+3 >= bufSize) {
doOutput = false;
}
if (doOutput) {
bufUNI[uniLen] = (us >> 12) | 0xe0;
bufUNI[uniLen+1] = ((us >> 6) & 0x3f) | 0x80;
bufUNI[uniLen+2] = (us & 0x3f) | 0x80;
}
uniLen += 3;
}
stringMOR++;
}
// null-terminate
if (doOutput && uniLen < bufSize) {
bufUNI[uniLen] = '\0';
}
uniLen++;
return uniLen;
#endif
}
/*
* Decode a single Unicode code point from a UTF-8 string. This will
* consume 1 to 4 bytes. If an error is detected, only one byte is
* consumed, and the code point value will be 0xDCnn (invalid).
*
* cf. http://en.wikipedia.org/wiki/UTF-8#Sample_code
*/
static uint32_t Nu_DecodeUTF8(const char** pStr)
{
const uint8_t* str = (const uint8_t*) *pStr;
uint32_t codePoint;
uint32_t uc1, uc2, uc3, uc4;
uc1 = *str++;
if (uc1 < 0x80) {
// single byte
codePoint = uc1;
} else if (uc1 < 0xc2) {
// illegal: continuation or overlong 2-byte sequence
goto fail;
} else if (uc1 < 0xe0) {
// 2-byte sequence
uc2 = *str++;
if ((uc2 & 0xc0) != 0x80) {
goto fail; // not a continuation
}
codePoint = (uc1 << 6) + uc2 - 0x3080;
} else if (uc1 < 0xf0) {
// 3-byte sequence */
uc2 = *str++;
if ((uc2 & 0xc0) != 0x80) {
goto fail; // not a continuation
}
if (uc1 == 0xe0 && uc2 < 0xa0) {
goto fail; // overlong
}
uc3 = *str++;
if ((uc3 & 0xc0) != 0x80) {
goto fail; // not a continuation
}
codePoint = (uc1 << 12) + (uc2 << 6) + uc3 - 0xE2080;
} else if (uc1 < 0xf5) {
uc2 = *str++;
if ((uc2 & 0xc0) != 0x80) {
goto fail; // not a continuation
}
if (uc1 == 0xf0 && uc2 < 0x90) {
goto fail; // overlong
}
if (uc1 == 0xf4 && uc2 >= 0x90) {
goto fail; // U+10FFFF
}
uc3 = *str++;
if ((uc3 & 0xc0) != 0x80) {
goto fail; // not a continuation
}
uc4 = *str++;
if ((uc4 & 0xc0) != 0x80) {
goto fail; // not a continuation
}
codePoint = (uc1 << 18) + (uc2 << 12) + (uc3 << 6) + uc4 - 0x3C82080;
} else {
// illegal: > U+10FFFF
goto fail;
}
*pStr = (const UNICHAR*) str;
return codePoint;
fail:
(*pStr)++; // advance one char only
return 0xdc00 | uc1;
}
/*
* Converts stringUNI to Mac OS Roman, storing the output in bufMOR
* until it's full. Null termination is guaranteed. If the buffer
* size is zero or bufMOR is NULL, no string data is returned.
*
* Returns the number of bytes required to represent stringUNI in MOR.
*/
NUFXLIB_API size_t Nu_ConvertUNIToMOR(const UNICHAR* stringUNI,
char* bufMOR, size_t bufSize)
{
Assert(stringUNI != 0);
#ifdef _WIN32
/*
* Place-holder if we're not using UTF-16 yet. This doesn't pass
* tests that check for behavior with non-MOR Unicode values.
*/
Assert(sizeof(UNICHAR) == 1);
size_t uniLen = strlen(stringUNI) + 1;
if (bufMOR != NULL && bufSize != 0) {
size_t copyLen = uniLen < bufSize ? uniLen : bufSize;
memcpy(bufMOR, stringUNI, copyLen);
bufMOR[bufSize-1] = '\0';
}
return uniLen;
#else
/*
* Convert UTF-8 to Mac OS Roman. If the code point doesn't have
* a valid conversion (either because it's not in the table, or the
* UTF-8 code is damaged) we just insert an ASCII '?'.
*/
if (gUnicodeToMOR[0] == 0xff) {
Nu_GenerateUnicodeToMOR();
Assert(gUnicodeToMOR[0] != 0xff);
}
uint32_t codePoint;
size_t morLen = 0;
Boolean doOutput = (bufMOR != NULL);
while (*stringUNI != '\0') {
codePoint = Nu_DecodeUTF8(&stringUNI);
char mc;
if (codePoint < 0x80) {
mc = (char) codePoint;
} else if (codePoint < 0xffff) {
// UTF-8 errors come back as 0xDCnn, which has no mapping in table
mc = gUnicodeToMOR[codePoint];
if (mc == 0x00) {
mc = '?';
}
} else {
// non-BMP code point
mc = '?';
}
if (morLen+1 >= bufSize) {
doOutput = false;
}
if (doOutput) {
bufMOR[morLen] = mc;
}
morLen++;
}
// null-terminate
if (doOutput && morLen < bufSize) {
bufMOR[morLen] = '\0';
}
morLen++;
return morLen;
#endif
}
/*
* Utility function that wraps NuConvertMORToUTF8, allocating a new
* buffer to hold the converted string. The caller must free the result.
*
* Returns NULL if stringMOR is NULL or the conversion fails.
*/
UNICHAR* Nu_CopyMORToUNI(const char* stringMOR)
{
size_t uniLen;
UNICHAR* uniBuf;
if (stringMOR == NULL) {
return NULL;
}
uniLen = Nu_ConvertMORToUNI(stringMOR, NULL, 0);
if (uniLen == (size_t) -1) {
return NULL;
}
uniBuf = (UNICHAR*) Nu_Malloc(NULL, uniLen);
Nu_ConvertMORToUNI(stringMOR, uniBuf, uniLen);
return uniBuf;
}

View File

@ -7,7 +7,7 @@
* Compute 16-bit CRCs. Depending on the hardware, the table version * Compute 16-bit CRCs. Depending on the hardware, the table version
* might be slower than the loop computation. * might be slower than the loop computation.
*/ */
#define __Crc16_c__ 1 #define COMPILE_CRC16_C 1
#include "NufxLibPriv.h" #include "NufxLibPriv.h"
#define CRC_TAB #define CRC_TAB

View File

@ -161,9 +161,9 @@ void Nu_DebugDumpThread(const NuThread* pThread)
printf("%sThreadKind: 0x%04x (%s)\n", kInd, printf("%sThreadKind: 0x%04x (%s)\n", kInd,
pThread->thThreadKind, descr); pThread->thThreadKind, descr);
printf("%sThreadCRC: 0x%04x ThreadEOF: %lu CompThreadEOF: %lu\n", kInd, printf("%sThreadCRC: 0x%04x ThreadEOF: %u CompThreadEOF: %u\n", kInd,
pThread->thThreadCRC, pThread->thThreadEOF, pThread->thCompThreadEOF); pThread->thThreadCRC, pThread->thThreadEOF, pThread->thCompThreadEOF);
printf("%s*File data offset: %ld actualThreadEOF: %ld\n", kInd, printf("%s*File data offset: %ld actualThreadEOF: %d\n", kInd,
pThread->fileOffset, pThread->actualThreadEOF); pThread->fileOffset, pThread->actualThreadEOF);
} }
@ -189,15 +189,17 @@ static void Nu_DebugDumpRecord(NuArchive* pArchive, const NuRecord* pRecord,
/*printf("PTR: pRecord=0x%08lx pXrefRecord=0x%08lx\n", (long) pRecord, /*printf("PTR: pRecord=0x%08lx pXrefRecord=0x%08lx\n", (long) pRecord,
(long) pXrefRecord);*/ (long) pXrefRecord);*/
printf("%s%s%sFilename: '%s' (idx=%lu)\n", kInd, UNICHAR* filenameUNI = Nu_CopyMORToUNI(pRecord->filenameMOR);
printf("%s%s%sFilename: '%s' (idx=%u)\n", kInd,
isDeleted ? "[DEL] " : "", isDeleted ? "[DEL] " : "",
pXrefRecord != NULL && pXrefRecord->pThreadMods != NULL ? "[MOD] " : "", pXrefRecord != NULL && pXrefRecord->pThreadMods != NULL ? "[MOD] " : "",
pRecord->filename == NULL ? "<not specified>" : pRecord->filename, filenameUNI == NULL ? "<not specified>" : filenameUNI,
pRecord->recordIdx); pRecord->recordIdx);
free(filenameUNI);
printf("%sHeaderID: '%.4s' VersionNumber: 0x%04x HeaderCRC: 0x%04x\n", printf("%sHeaderID: '%.4s' VersionNumber: 0x%04x HeaderCRC: 0x%04x\n",
kInd, kInd,
pRecord->recNufxID, pRecord->recVersionNumber, pRecord->recHeaderCRC); pRecord->recNufxID, pRecord->recVersionNumber, pRecord->recHeaderCRC);
printf("%sAttribCount: %u TotalThreads: %lu\n", kInd, printf("%sAttribCount: %u TotalThreads: %u\n", kInd,
pRecord->recAttribCount, pRecord->recTotalThreads); pRecord->recAttribCount, pRecord->recTotalThreads);
printf("%sFileSysID: %u (%s) FileSysInfo: 0x%04x ('%c')\n", kInd, printf("%sFileSysID: %u (%s) FileSysInfo: 0x%04x ('%c')\n", kInd,
pRecord->recFileSysID, pRecord->recFileSysID,
@ -205,7 +207,7 @@ static void Nu_DebugDumpRecord(NuArchive* pArchive, const NuRecord* pRecord,
pRecord->recFileSysInfo, pRecord->recFileSysInfo,
NuGetSepFromSysInfo(pRecord->recFileSysInfo)); NuGetSepFromSysInfo(pRecord->recFileSysInfo));
/* do something fancy for ProDOS? */ /* do something fancy for ProDOS? */
printf("%sFileType: 0x%08lx ExtraType: 0x%08lx Access: 0x%08lx\n", kInd, printf("%sFileType: 0x%08x ExtraType: 0x%08x Access: 0x%08x\n", kInd,
pRecord->recFileType, pRecord->recExtraType, pRecord->recAccess); pRecord->recFileType, pRecord->recExtraType, pRecord->recAccess);
printf("%sCreateWhen: %s\n", kInd, printf("%sCreateWhen: %s\n", kInd,
Nu_DebugDumpDate(&pRecord->recCreateWhen, dateBuf)); Nu_DebugDumpDate(&pRecord->recCreateWhen, dateBuf));
@ -225,7 +227,7 @@ static void Nu_DebugDumpRecord(NuArchive* pArchive, const NuRecord* pRecord,
Nu_Free(pArchive, outBuf); Nu_Free(pArchive, outBuf);
} }
printf("%s*ExtraCount: %ld RecFileOffset: %ld RecHeaderLength: %ld\n", printf("%s*ExtraCount: %d RecFileOffset: %ld RecHeaderLength: %d\n",
kInd, kInd,
pRecord->extraCount, pRecord->fileOffset, pRecord->recHeaderLength); pRecord->extraCount, pRecord->fileOffset, pRecord->recHeaderLength);
@ -236,7 +238,7 @@ static void Nu_DebugDumpRecord(NuArchive* pArchive, const NuRecord* pRecord,
pThread = Nu_GetThread(pRecord, idx); pThread = Nu_GetThread(pRecord, idx);
Assert(pThread != NULL); Assert(pThread != NULL);
printf("%s--Thread #%lu (idx=%lu)%s\n", kInd, idx, pThread->threadIdx, printf("%s--Thread #%u (idx=%u)%s\n", kInd, idx, pThread->threadIdx,
isFake ? " [FAKE]" : ""); isFake ? " [FAKE]" : "");
Nu_DebugDumpThread(pThread); Nu_DebugDumpThread(pThread);
} }
@ -251,17 +253,17 @@ static void Nu_DebugDumpRecord(NuArchive* pArchive, const NuRecord* pRecord,
while (pThreadMod != NULL) { while (pThreadMod != NULL) {
switch (pThreadMod->entry.kind) { switch (pThreadMod->entry.kind) {
case kNuThreadModAdd: case kNuThreadModAdd:
printf("%s *-ThreadMod ADD 0x%08lx 0x%04x (sourceType=%d)\n", kInd, printf("%s *-ThreadMod ADD 0x%08x 0x%04x (sourceType=%d)\n", kInd,
pThreadMod->entry.add.threadID, pThreadMod->entry.add.threadID,
pThreadMod->entry.add.threadFormat, pThreadMod->entry.add.threadFormat,
Nu_DataSourceGetType(pThreadMod->entry.add.pDataSource)); Nu_DataSourceGetType(pThreadMod->entry.add.pDataSource));
break; break;
case kNuThreadModUpdate: case kNuThreadModUpdate:
printf("%s *-ThreadMod UPDATE %6ld\n", kInd, printf("%s *-ThreadMod UPDATE %6d\n", kInd,
pThreadMod->entry.update.threadIdx); pThreadMod->entry.update.threadIdx);
break; break;
case kNuThreadModDelete: case kNuThreadModDelete:
printf("%s *-ThreadMod DELETE %6ld\n", kInd, printf("%s *-ThreadMod DELETE %6d\n", kInd,
pThreadMod->entry.delete.threadIdx); pThreadMod->entry.delete.threadIdx);
break; break;
case kNuThreadModUnknown: case kNuThreadModUnknown:
@ -276,7 +278,7 @@ static void Nu_DebugDumpRecord(NuArchive* pArchive, const NuRecord* pRecord,
/*printf("%s*TotalLength: %ld TotalCompLength: %ld\n", /*printf("%s*TotalLength: %ld TotalCompLength: %ld\n",
kInd, pRecord->totalLength, pRecord->totalCompLength);*/ kInd, pRecord->totalLength, pRecord->totalCompLength);*/
printf("%s*TotalCompLength: %ld\n", kInd, pRecord->totalCompLength); printf("%s*TotalCompLength: %u\n", kInd, pRecord->totalCompLength);
printf("\n"); printf("\n");
bail: bail:
@ -334,14 +336,14 @@ static void Nu_DebugDumpMH(const NuMasterHeader* pMasterHeader)
Assert(pMasterHeader != NULL); Assert(pMasterHeader != NULL);
printf("%sNufileID: '%.6s' MasterCRC: 0x%04x TotalRecords: %lu\n", kInd, printf("%sNufileID: '%.6s' MasterCRC: 0x%04x TotalRecords: %u\n", kInd,
pMasterHeader->mhNufileID, pMasterHeader->mhMasterCRC, pMasterHeader->mhNufileID, pMasterHeader->mhMasterCRC,
pMasterHeader->mhTotalRecords); pMasterHeader->mhTotalRecords);
printf("%sArchiveCreateWhen: %s\n", kInd, printf("%sArchiveCreateWhen: %s\n", kInd,
Nu_DebugDumpDate(&pMasterHeader->mhArchiveCreateWhen, dateBuf1)); Nu_DebugDumpDate(&pMasterHeader->mhArchiveCreateWhen, dateBuf1));
printf("%sArchiveModWhen: %s\n", kInd, printf("%sArchiveModWhen: %s\n", kInd,
Nu_DebugDumpDate(&pMasterHeader->mhArchiveModWhen, dateBuf1)); Nu_DebugDumpDate(&pMasterHeader->mhArchiveModWhen, dateBuf1));
printf("%sMasterVersion: %u MasterEOF: %lu\n", kInd, printf("%sMasterVersion: %u MasterEOF: %u\n", kInd,
pMasterHeader->mhMasterVersion, pMasterHeader->mhMasterEOF); pMasterHeader->mhMasterVersion, pMasterHeader->mhMasterEOF);
} }
@ -357,15 +359,15 @@ void Nu_DebugDumpAll(NuArchive* pArchive)
{ {
Assert(pArchive != NULL); Assert(pArchive != NULL);
printf("*Archive pathname: '%s'\n", pArchive->archivePathname); printf("*Archive pathname: '%s'\n", pArchive->archivePathnameUNI);
printf("*Archive type: %d\n", pArchive->archiveType); printf("*Archive type: %d\n", pArchive->archiveType);
printf("*Header offset: %ld (junk offset=%ld)\n", printf("*Header offset: %ld (junk offset=%ld)\n",
pArchive->headerOffset, pArchive->junkOffset); pArchive->headerOffset, pArchive->junkOffset);
printf("*Num records: %ld orig, %ld copy, %ld new\n", printf("*Num records: %u orig, %u copy, %u new\n",
Nu_RecordSet_GetNumRecords(&pArchive->origRecordSet), Nu_RecordSet_GetNumRecords(&pArchive->origRecordSet),
Nu_RecordSet_GetNumRecords(&pArchive->copyRecordSet), Nu_RecordSet_GetNumRecords(&pArchive->copyRecordSet),
Nu_RecordSet_GetNumRecords(&pArchive->newRecordSet)); Nu_RecordSet_GetNumRecords(&pArchive->newRecordSet));
printf("*NuRecordIdx seed: %lu NuRecordIdx next: %lu\n", printf("*NuRecordIdx seed: %u NuRecordIdx next: %u\n",
pArchive->recordIdxSeed, pArchive->nextRecordIdx); pArchive->recordIdxSeed, pArchive->nextRecordIdx);
/* master header */ /* master header */

View File

@ -522,17 +522,17 @@ static Boolean Nu_VerifyAllTouched(NuArchive* pArchive, const NuRecord* pRecord)
* This call should only be made after an "add" or "update" threadMod has * This call should only be made after an "add" or "update" threadMod has
* successfully completed. * successfully completed.
* *
* "newName" must be allocated storage. * "newName" must be allocated storage, Mac OS Roman charset.
*/ */
static void Nu_SetNewThreadFilename(NuArchive* pArchive, NuRecord* pRecord, static void Nu_SetNewThreadFilename(NuArchive* pArchive, NuRecord* pRecord,
char* newName) char* newNameMOR)
{ {
Assert(pRecord != NULL); Assert(pRecord != NULL);
Assert(newName != NULL); Assert(newNameMOR != NULL);
Nu_Free(pArchive, pRecord->threadFilename); Nu_Free(pArchive, pRecord->threadFilenameMOR);
pRecord->threadFilename = newName; pRecord->threadFilenameMOR = newNameMOR;
pRecord->filename = pRecord->threadFilename; pRecord->filenameMOR = pRecord->threadFilenameMOR;
} }
/* /*
@ -647,14 +647,14 @@ static NuError Nu_ConstructArchiveUpdate(NuArchive* pArchive, FILE* fp,
if (NuGetThreadID(pThread) == kNuThreadIDFilename) { if (NuGetThreadID(pThread) == kNuThreadIDFilename) {
/* special handling for filename updates */ /* special handling for filename updates */
char* savedCopy = NULL; char* savedCopyMOR = NULL;
err = Nu_CopyPresizedToArchive(pArchive, pDataSource, err = Nu_CopyPresizedToArchive(pArchive, pDataSource,
NuGetThreadID(pThread), fp, pThread, &savedCopy); NuGetThreadID(pThread), fp, pThread, &savedCopyMOR);
if (err != kNuErrNone) { if (err != kNuErrNone) {
Nu_ReportError(NU_BLOB, err, "thread update failed"); Nu_ReportError(NU_BLOB, err, "thread update failed");
goto bail; goto bail;
} }
Nu_SetNewThreadFilename(pArchive, pRecord, savedCopy); Nu_SetNewThreadFilename(pArchive, pRecord, savedCopyMOR);
} else { } else {
err = Nu_CopyPresizedToArchive(pArchive, pDataSource, err = Nu_CopyPresizedToArchive(pArchive, pDataSource,
@ -700,6 +700,7 @@ static NuError Nu_HandleAddThreadMods(NuArchive* pArchive, NuRecord* pRecord,
NuProgressData* pProgressData; NuProgressData* pProgressData;
NuThreadMod* pThreadMod; NuThreadMod* pThreadMod;
NuThread* pNewThread; NuThread* pNewThread;
UNICHAR* pathnameUNIStorage = NULL;
Boolean foundOne = false; Boolean foundOne = false;
/* /*
@ -747,17 +748,19 @@ static NuError Nu_HandleAddThreadMods(NuArchive* pArchive, NuRecord* pRecord,
* Do something different here for data sinks with * Do something different here for data sinks with
* filenames attached. ++ATM 2003/02/17] * filenames attached. ++ATM 2003/02/17]
*/ */
pathnameUNIStorage = Nu_CopyMORToUNI(pRecord->filenameMOR);
if (Nu_DataSourceGetType(pThreadMod->entry.add.pDataSource) if (Nu_DataSourceGetType(pThreadMod->entry.add.pDataSource)
== kNuDataSourceFromFile) == kNuDataSourceFromFile)
{ {
/* use on-disk filename */ /* use on-disk filename */
err = Nu_ProgressDataInit_Compress(pArchive, &progressData, err = Nu_ProgressDataInit_Compress(pArchive, &progressData,
pRecord, Nu_DataSourceFile_GetPathname( pRecord, Nu_DataSourceFile_GetPathname(
pThreadMod->entry.add.pDataSource)); pThreadMod->entry.add.pDataSource),
pathnameUNIStorage);
} else { } else {
/* use archive filename for both */ /* use archive filename for both */
err = Nu_ProgressDataInit_Compress(pArchive, &progressData, err = Nu_ProgressDataInit_Compress(pArchive, &progressData,
pRecord, pRecord->filename); pRecord, pathnameUNIStorage, pathnameUNIStorage);
} }
BailError(err); BailError(err);
@ -820,14 +823,14 @@ static NuError Nu_HandleAddThreadMods(NuArchive* pArchive, NuRecord* pRecord,
if (pThreadMod->entry.add.threadID == kNuThreadIDFilename) { if (pThreadMod->entry.add.threadID == kNuThreadIDFilename) {
/* filenames are special */ /* filenames are special */
char* savedCopy = NULL; char* savedCopyMOR = NULL;
Assert(pThreadMod->entry.add.threadFormat == Assert(pThreadMod->entry.add.threadFormat ==
kNuThreadFormatUncompressed); kNuThreadFormatUncompressed);
err = Nu_CopyPresizedToArchive(pArchive, err = Nu_CopyPresizedToArchive(pArchive,
pThreadMod->entry.add.pDataSource, pThreadMod->entry.add.pDataSource,
pThreadMod->entry.add.threadID, pThreadMod->entry.add.threadID,
dstFp, pNewThread, &savedCopy); dstFp, pNewThread, &savedCopyMOR);
if (err != kNuErrNone) { if (err != kNuErrNone) {
Nu_ReportError(NU_BLOB, err, "fn thread add failed"); Nu_ReportError(NU_BLOB, err, "fn thread add failed");
goto bail; goto bail;
@ -838,7 +841,7 @@ static NuError Nu_HandleAddThreadMods(NuArchive* pArchive, NuRecord* pRecord,
just clear it, because we've already made space for the just clear it, because we've already made space for the
record header, and didn't include the filename in it. */ record header, and didn't include the filename in it. */
Nu_SetNewThreadFilename(pArchive, pRecord, savedCopy); Nu_SetNewThreadFilename(pArchive, pRecord, savedCopyMOR);
} else if (pThreadMod->entry.add.isPresized) { } else if (pThreadMod->entry.add.isPresized) {
/* don't compress, just copy */ /* don't compress, just copy */
@ -874,6 +877,7 @@ static NuError Nu_HandleAddThreadMods(NuArchive* pArchive, NuRecord* pRecord,
} }
bail: bail:
Nu_Free(pArchive, pathnameUNIStorage);
return err; return err;
} }
@ -1081,24 +1085,25 @@ static NuError Nu_ConstructArchiveRecord(NuArchive* pArchive, NuRecord* pRecord)
/* /*
* Handle filename deletion. * Handle filename deletion.
*/ */
if (!numFilenameThreads && pRecord->threadFilename) { if (!numFilenameThreads && pRecord->threadFilenameMOR != NULL) {
/* looks like a previously existing filename thread got removed */ /* looks like a previously existing filename thread got removed */
DBUG(("--- Dropping thread filename '%s'\n", pRecord->threadFilename)); DBUG(("--- Dropping thread filename '%s'\n",
if (pRecord->filename == pRecord->threadFilename) pRecord->threadFilenameMOR));
pRecord->filename = NULL; /* don't point at freed memory! */ if (pRecord->filenameMOR == pRecord->threadFilenameMOR)
Nu_Free(pArchive, pRecord->threadFilename); pRecord->filenameMOR = NULL; /* don't point at freed memory! */
pRecord->threadFilename = NULL; Nu_Free(pArchive, pRecord->threadFilenameMOR);
pRecord->threadFilenameMOR = NULL;
/* I don't think this is possible, but check it anyway */ /* I don't think this is possible, but check it anyway */
if (pRecord->filename == NULL && pRecord->recFilename != NULL && if (pRecord->filenameMOR == NULL && pRecord->recFilenameMOR != NULL &&
!pRecord->dropRecFilename) !pRecord->dropRecFilename)
{ {
DBUG(("--- HEY, how did this happen?\n")); DBUG(("--- HEY, how did this happen?\n"));
pRecord->filename = pRecord->recFilename; pRecord->filenameMOR = pRecord->recFilenameMOR;
} }
} }
if (pRecord->filename == NULL) if (pRecord->filenameMOR == NULL)
pRecord->filename = kNuDefaultRecordName; pRecord->filenameMOR = kNuDefaultRecordName;
/* /*
* Make a hole, including the header filename if we're not dropping it. * Make a hole, including the header filename if we're not dropping it.
@ -1303,13 +1308,13 @@ static NuError Nu_ConstructNewRecord(NuArchive* pArchive, NuRecord* pRecord,
* Generally speaking, the "add file" call should set the * Generally speaking, the "add file" call should set the
* filename. If somehow it didn't, assign a default. * filename. If somehow it didn't, assign a default.
*/ */
if (pRecord->filename == NULL) { if (pRecord->filenameMOR == NULL) {
pRecord->newFilename = strdup(kNuDefaultRecordName); pRecord->newFilenameMOR = strdup(kNuDefaultRecordName);
pRecord->filename = pRecord->newFilename; pRecord->filenameMOR = pRecord->newFilenameMOR;
} }
DBUG(("--- No filename thread found, adding one ('%s')\n", DBUG(("--- No filename thread found, adding one ('%s')\n",
pRecord->filename)); pRecord->filenameMOR));
/* /*
* Create a trivial data source for the filename. The size of * Create a trivial data source for the filename. The size of
@ -1318,12 +1323,12 @@ static NuError Nu_ConstructNewRecord(NuArchive* pArchive, NuRecord* pRecord,
* (If we're really serious about renaming it, maybe we should * (If we're really serious about renaming it, maybe we should
* leave some extra space on the end...?) * leave some extra space on the end...?)
*/ */
len = strlen(pRecord->filename); len = strlen(pRecord->filenameMOR);
maxLen = len > kNuDefaultFilenameThreadSize ? maxLen = len > kNuDefaultFilenameThreadSize ?
len : kNuDefaultFilenameThreadSize; len : kNuDefaultFilenameThreadSize;
err = Nu_DataSourceBuffer_New(kNuThreadFormatUncompressed, err = Nu_DataSourceBuffer_New(kNuThreadFormatUncompressed,
maxLen, (const uint8_t*)pRecord->filename, 0, maxLen, (const uint8_t*)pRecord->filenameMOR, 0,
strlen(pRecord->filename), NULL, &pTmpDataSource); strlen(pRecord->filenameMOR), NULL, &pTmpDataSource);
BailError(err); BailError(err);
/* put in a new "add" threadMod (which copies the data source) */ /* put in a new "add" threadMod (which copies the data source) */
@ -1901,7 +1906,7 @@ static NuError Nu_ResetTempFile(NuArchive* pArchive)
return kNuErrNone; /* or kNuErrArchiveRO? */ return kNuErrNone; /* or kNuErrArchiveRO? */
Assert(pArchive != NULL); Assert(pArchive != NULL);
Assert(pArchive->tmpPathname != NULL); Assert(pArchive->tmpPathnameUNI != NULL);
#if 0 /* keep the temp file around for examination */ #if 0 /* keep the temp file around for examination */
if (pArchive->tmpFp != NULL) { if (pArchive->tmpFp != NULL) {
@ -1915,11 +1920,14 @@ if (pArchive->tmpFp != NULL) {
/* if we renamed the temp over the original, we need to open a new temp */ /* if we renamed the temp over the original, we need to open a new temp */
if (pArchive->tmpFp == NULL) { if (pArchive->tmpFp == NULL) {
pArchive->tmpFp = fopen(pArchive->tmpPathname, kNuFileOpenReadWriteCreat); // as in Nu_OpenTempFile, skip the wchar conversion for the temp
// file name, which we lazily assume to be ASCII
pArchive->tmpFp = fopen(pArchive->tmpPathnameUNI,
kNuFileOpenReadWriteCreat);
if (pArchive->tmpFp == NULL) { if (pArchive->tmpFp == NULL) {
err = errno ? errno : kNuErrFileOpen; err = errno ? errno : kNuErrFileOpen;
Nu_ReportError(NU_BLOB, errno, "Unable to open temp file '%s'", Nu_ReportError(NU_BLOB, errno, "Unable to open temp file '%s'",
pArchive->tmpPathname); pArchive->tmpPathnameUNI);
goto bail; goto bail;
} }
} else { } else {
@ -1933,19 +1941,20 @@ if (pArchive->tmpFp != NULL) {
/* do it the hard way if we don't have ftruncate or equivalent */ /* do it the hard way if we don't have ftruncate or equivalent */
err = kNuErrNone; err = kNuErrNone;
fclose(pArchive->tmpFp); fclose(pArchive->tmpFp);
pArchive->tmpFp = fopen(pArchive->tmpPathname, kNuFileOpenWriteTrunc); pArchive->tmpFp = fopen(pArchive->tmpPathnameUNI,
kNuFileOpenWriteTrunc);
if (pArchive->tmpFp == NULL) { if (pArchive->tmpFp == NULL) {
err = errno ? errno : kNuErrFileOpen; err = errno ? errno : kNuErrFileOpen;
Nu_ReportError(NU_BLOB, err, "failed truncating tmp file"); Nu_ReportError(NU_BLOB, err, "failed truncating tmp file");
goto bail; goto bail;
} }
fclose(pArchive->tmpFp); fclose(pArchive->tmpFp);
pArchive->tmpFp = pArchive->tmpFp = fopen(pArchive->tmpPathnameUNI,
fopen(pArchive->tmpPathname, kNuFileOpenReadWriteCreat); kNuFileOpenReadWriteCreat);
if (pArchive->tmpFp == NULL) { if (pArchive->tmpFp == NULL) {
err = errno ? errno : kNuErrFileOpen; err = errno ? errno : kNuErrFileOpen;
Nu_ReportError(NU_BLOB, err, "Unable to open temp file '%s'", Nu_ReportError(NU_BLOB, err, "Unable to open temp file '%s'",
pArchive->tmpPathname); pArchive->tmpPathnameUNI);
goto bail; goto bail;
} }
} }
@ -2110,7 +2119,7 @@ bail:
* If the things this function is doing aren't making any sense at all, * If the things this function is doing aren't making any sense at all,
* read "NOTES.txt" for an introduction. * read "NOTES.txt" for an introduction.
*/ */
NuError Nu_Flush(NuArchive* pArchive, long* pStatusFlags) NuError Nu_Flush(NuArchive* pArchive, uint32_t* pStatusFlags)
{ {
NuError err = kNuErrNone; NuError err = kNuErrNone;
Boolean canAbort = true; Boolean canAbort = true;
@ -2388,7 +2397,7 @@ NuError Nu_Flush(NuArchive* pArchive, long* pStatusFlags)
if (err != kNuErrNone) { if (err != kNuErrNone) {
Nu_ReportError(NU_BLOB, err, "unable to remove original archive"); Nu_ReportError(NU_BLOB, err, "unable to remove original archive");
Nu_ReportError(NU_BLOB, kNuErrNone, "New data is in '%s'", Nu_ReportError(NU_BLOB, kNuErrNone, "New data is in '%s'",
pArchive->tmpPathname); pArchive->tmpPathnameUNI);
*pStatusFlags |= kNuFlushInaccessible; *pStatusFlags |= kNuFlushInaccessible;
goto bail_reopen; /* must re-open archiveFp */ goto bail_reopen; /* must re-open archiveFp */
} }
@ -2400,24 +2409,25 @@ NuError Nu_Flush(NuArchive* pArchive, long* pStatusFlags)
if (err != kNuErrNone) { if (err != kNuErrNone) {
Nu_ReportError(NU_BLOB, err, "unable to rename temp file"); Nu_ReportError(NU_BLOB, err, "unable to rename temp file");
Nu_ReportError(NU_BLOB, kNuErrNone, Nu_ReportError(NU_BLOB, kNuErrNone,
"NOTE: only copy of archive is in '%s'", pArchive->tmpPathname); "NOTE: only copy of archive is in '%s'",
pArchive->tmpPathnameUNI);
/* maintain Entry.c semantics (and keep them from removing temp) */ /* maintain Entry.c semantics (and keep them from removing temp) */
Nu_Free(pArchive, pArchive->archivePathname); Nu_Free(pArchive, pArchive->archivePathnameUNI);
pArchive->archivePathname = NULL; pArchive->archivePathnameUNI = NULL;
Nu_Free(pArchive, pArchive->tmpPathname); Nu_Free(pArchive, pArchive->tmpPathnameUNI);
pArchive->tmpPathname = NULL; pArchive->tmpPathnameUNI = NULL;
/* bail will put us into read-only mode, which is what we want */ /* bail will put us into read-only mode, which is what we want */
goto bail; goto bail;
} }
bail_reopen: bail_reopen:
pArchive->archiveFp = fopen(pArchive->archivePathname, pArchive->archiveFp = fopen(pArchive->archivePathnameUNI,
kNuFileOpenReadWrite); kNuFileOpenReadWrite);
if (pArchive->archiveFp == NULL) { if (pArchive->archiveFp == NULL) {
err = errno ? errno : -1; err = errno ? errno : -1;
Nu_ReportError(NU_BLOB, err, Nu_ReportError(NU_BLOB, err,
"unable to reopen archive file '%s' after rename", "unable to reopen archive file '%s' after rename",
pArchive->archivePathname); pArchive->archivePathnameUNI);
*pStatusFlags |= kNuFlushInaccessible; *pStatusFlags |= kNuFlushInaccessible;
goto bail; /* the Entry.c funcs will obstruct further use */ goto bail; /* the Entry.c funcs will obstruct further use */
} }

View File

@ -81,11 +81,11 @@ static NuError Nu_ValidateNuArchive(const NuArchive* pArchive)
} }
/* make sure we have open files to work with */ /* make sure we have open files to work with */
Assert(pArchive->archivePathname == NULL || pArchive->archiveFp != NULL); Assert(pArchive->archivePathnameUNI == NULL || pArchive->archiveFp != NULL);
if (pArchive->archivePathname != NULL && pArchive->archiveFp == NULL) if (pArchive->archivePathnameUNI != NULL && pArchive->archiveFp == NULL)
return kNuErrInternal; return kNuErrInternal;
Assert(pArchive->tmpPathname == NULL || pArchive->tmpFp != NULL); Assert(pArchive->tmpPathnameUNI == NULL || pArchive->tmpFp != NULL);
if (pArchive->tmpPathname != NULL && pArchive->tmpFp == NULL) if (pArchive->tmpPathnameUNI != NULL && pArchive->tmpFp == NULL)
return kNuErrInternal; return kNuErrInternal;
/* further validations */ /* further validations */
@ -180,11 +180,12 @@ NUFXLIB_API NuError NuTestRecord(NuArchive* pArchive, NuRecordIdx recordIdx)
* =========================================================================== * ===========================================================================
*/ */
NUFXLIB_API NuError NuOpenRO(const char* filename, NuArchive** ppArchive) NUFXLIB_API NuError NuOpenRO(const UNICHAR* archivePathnameUNI,
NuArchive** ppArchive)
{ {
NuError err; NuError err;
err = Nu_OpenRO(filename, (NuArchive**) ppArchive); err = Nu_OpenRO(archivePathnameUNI, (NuArchive**) ppArchive);
return err; return err;
} }
@ -230,14 +231,14 @@ NUFXLIB_API NuError NuGetRecord(NuArchive* pArchive, NuRecordIdx recordIdx,
return err; return err;
} }
NUFXLIB_API NuError NuGetRecordIdxByName(NuArchive* pArchive, const char* name, NUFXLIB_API NuError NuGetRecordIdxByName(NuArchive* pArchive,
NuRecordIdx* pRecordIdx) const char* nameMOR, NuRecordIdx* pRecordIdx)
{ {
NuError err; NuError err;
if ((err = Nu_ValidateNuArchive(pArchive)) == kNuErrNone) { if ((err = Nu_ValidateNuArchive(pArchive)) == kNuErrNone) {
Nu_SetBusy(pArchive); Nu_SetBusy(pArchive);
err = Nu_GetRecordIdxByName(pArchive, name, pRecordIdx); err = Nu_GetRecordIdxByName(pArchive, nameMOR, pRecordIdx);
Nu_ClearBusy(pArchive); Nu_ClearBusy(pArchive);
} }
@ -265,18 +266,18 @@ NUFXLIB_API NuError NuGetRecordIdxByPosition(NuArchive* pArchive, uint32_t posit
* =========================================================================== * ===========================================================================
*/ */
NUFXLIB_API NuError NuOpenRW(const char* archivePathname, NUFXLIB_API NuError NuOpenRW(const UNICHAR* archivePathnameUNI,
const char* tmpPathname, uint32_t flags, NuArchive** ppArchive) const UNICHAR* tmpPathnameUNI, uint32_t flags, NuArchive** ppArchive)
{ {
NuError err; NuError err;
err = Nu_OpenRW(archivePathname, tmpPathname, flags, err = Nu_OpenRW(archivePathnameUNI, tmpPathnameUNI, flags,
(NuArchive**) ppArchive); (NuArchive**) ppArchive);
return err; return err;
} }
NUFXLIB_API NuError NuFlush(NuArchive* pArchive, long* pStatusFlags) NUFXLIB_API NuError NuFlush(NuArchive* pArchive, uint32_t* pStatusFlags)
{ {
NuError err; NuError err;
@ -331,7 +332,7 @@ NUFXLIB_API NuError NuAddThread(NuArchive* pArchive, NuRecordIdx recordIdx,
return err; return err;
} }
NUFXLIB_API NuError NuAddFile(NuArchive* pArchive, const char* pathname, NUFXLIB_API NuError NuAddFile(NuArchive* pArchive, const UNICHAR* pathnameUNI,
const NuFileDetails* pFileDetails, short isFromRsrcFork, const NuFileDetails* pFileDetails, short isFromRsrcFork,
NuRecordIdx* pRecordIdx) NuRecordIdx* pRecordIdx)
{ {
@ -339,7 +340,7 @@ NUFXLIB_API NuError NuAddFile(NuArchive* pArchive, const char* pathname,
if ((err = Nu_ValidateNuArchive(pArchive)) == kNuErrNone) { if ((err = Nu_ValidateNuArchive(pArchive)) == kNuErrNone) {
Nu_SetBusy(pArchive); Nu_SetBusy(pArchive);
err = Nu_AddFile(pArchive, pathname, pFileDetails, err = Nu_AddFile(pArchive, pathnameUNI, pFileDetails,
(Boolean)(isFromRsrcFork != 0), pRecordIdx); (Boolean)(isFromRsrcFork != 0), pRecordIdx);
Nu_ClearBusy(pArchive); Nu_ClearBusy(pArchive);
} }
@ -348,13 +349,13 @@ NUFXLIB_API NuError NuAddFile(NuArchive* pArchive, const char* pathname,
} }
NUFXLIB_API NuError NuRename(NuArchive* pArchive, NuRecordIdx recordIdx, NUFXLIB_API NuError NuRename(NuArchive* pArchive, NuRecordIdx recordIdx,
const char* pathname, char fssep) const char* pathnameMOR, char fssep)
{ {
NuError err; NuError err;
if ((err = Nu_ValidateNuArchive(pArchive)) == kNuErrNone) { if ((err = Nu_ValidateNuArchive(pArchive)) == kNuErrNone) {
Nu_SetBusy(pArchive); Nu_SetBusy(pArchive);
err = Nu_Rename(pArchive, recordIdx, pathname, fssep); err = Nu_Rename(pArchive, recordIdx, pathnameMOR, fssep);
Nu_ClearBusy(pArchive); Nu_ClearBusy(pArchive);
} }
@ -377,7 +378,7 @@ NUFXLIB_API NuError NuSetRecordAttr(NuArchive* pArchive, NuRecordIdx recordIdx,
} }
NUFXLIB_API NuError NuUpdatePresizedThread(NuArchive* pArchive, NUFXLIB_API NuError NuUpdatePresizedThread(NuArchive* pArchive,
NuThreadIdx threadIdx, NuDataSource* pDataSource, long* pMaxLen) NuThreadIdx threadIdx, NuDataSource* pDataSource, int32_t* pMaxLen)
{ {
NuError err; NuError err;
@ -538,11 +539,11 @@ NUFXLIB_API NuError NuDebugDumpArchive(NuArchive* pArchive)
*/ */
NUFXLIB_API NuError NuCreateDataSourceForFile(NuThreadFormat threadFormat, NUFXLIB_API NuError NuCreateDataSourceForFile(NuThreadFormat threadFormat,
uint32_t otherLen, const char* pathname, short isFromRsrcFork, uint32_t otherLen, const UNICHAR* pathnameUNI, short isFromRsrcFork,
NuDataSource** ppDataSource) NuDataSource** ppDataSource)
{ {
return Nu_DataSourceFile_New(threadFormat, otherLen, return Nu_DataSourceFile_New(threadFormat, otherLen,
pathname, (Boolean)(isFromRsrcFork != 0), ppDataSource); pathnameUNI, (Boolean)(isFromRsrcFork != 0), ppDataSource);
} }
NUFXLIB_API NuError NuCreateDataSourceForFP(NuThreadFormat threadFormat, NUFXLIB_API NuError NuCreateDataSourceForFP(NuThreadFormat threadFormat,
@ -576,10 +577,10 @@ NUFXLIB_API NuError NuDataSourceSetRawCrc(NuDataSource* pDataSource,
} }
NUFXLIB_API NuError NuCreateDataSinkForFile(short doExpand, NuValue convertEOL, NUFXLIB_API NuError NuCreateDataSinkForFile(short doExpand, NuValue convertEOL,
const char* pathname, char fssep, NuDataSink** ppDataSink) const UNICHAR* pathnameUNI, UNICHAR fssep, NuDataSink** ppDataSink)
{ {
return Nu_DataSinkFile_New((Boolean)(doExpand != 0), convertEOL, pathname, return Nu_DataSinkFile_New((Boolean)(doExpand != 0), convertEOL,
fssep, ppDataSink); pathnameUNI, fssep, ppDataSink);
} }
NUFXLIB_API NuError NuCreateDataSinkForFP(short doExpand, NuValue convertEOL, NUFXLIB_API NuError NuCreateDataSinkForFP(short doExpand, NuValue convertEOL,
@ -624,8 +625,8 @@ NUFXLIB_API const char* NuStrError(NuError err)
return Nu_StrError(err); return Nu_StrError(err);
} }
NUFXLIB_API NuError NuGetVersion(long* pMajorVersion, long* pMinorVersion, NUFXLIB_API NuError NuGetVersion(int32_t* pMajorVersion, int32_t* pMinorVersion,
long* pBugVersion, const char** ppBuildDate, const char** ppBuildFlags) int32_t* pBugVersion, const char** ppBuildDate, const char** ppBuildFlags)
{ {
return Nu_GetVersion(pMajorVersion, pMinorVersion, pBugVersion, return Nu_GetVersion(pMajorVersion, pMinorVersion, pBugVersion,
ppBuildDate, ppBuildFlags); ppBuildDate, ppBuildFlags);
@ -709,7 +710,7 @@ NUFXLIB_API uint32_t NuRecordGetNumThreads(const NuRecord* pNuRecord)
} }
NUFXLIB_API const NuThread* NuThreadGetByIdx(const NuThread* pNuThread, NUFXLIB_API const NuThread* NuThreadGetByIdx(const NuThread* pNuThread,
long idx) int32_t idx)
{ {
if (pNuThread == NULL) if (pNuThread == NULL)
return NULL; return NULL;
@ -721,6 +722,18 @@ NUFXLIB_API short NuIsPresizedThreadID(NuThreadID threadID)
return Nu_IsPresizedThreadID(threadID); return Nu_IsPresizedThreadID(threadID);
} }
NUFXLIB_API size_t NuConvertMORToUNI(const char* stringMOR,
UNICHAR* bufUNI, size_t bufSize)
{
return Nu_ConvertMORToUNI(stringMOR, bufUNI, bufSize);
}
NUFXLIB_API size_t NuConvertUNIToMOR(const UNICHAR* stringUNI,
char* bufMOR, size_t bufSize)
{
return Nu_ConvertUNIToMOR(stringUNI, bufMOR, bufSize);
}
/* /*
* =========================================================================== * ===========================================================================

View File

@ -262,12 +262,12 @@ static Boolean Nu_IsForkedFile(NuArchive* pArchive, const NuRecord* pRecord)
* Get the file info into a NuFileInfo struct. Fields which are * Get the file info into a NuFileInfo struct. Fields which are
* inappropriate for the current system are set to default values. * inappropriate for the current system are set to default values.
*/ */
static NuError Nu_GetFileInfo(NuArchive* pArchive, const char* pathname, static NuError Nu_GetFileInfo(NuArchive* pArchive, const UNICHAR* pathnameUNI,
NuFileInfo* pFileInfo) NuFileInfo* pFileInfo)
{ {
NuError err = kNuErrNone; NuError err = kNuErrNone;
Assert(pArchive != NULL); Assert(pArchive != NULL);
Assert(pathname != NULL); Assert(pathnameUNI != NULL);
Assert(pFileInfo != NULL); Assert(pFileInfo != NULL);
pFileInfo->isValid = false; pFileInfo->isValid = false;
@ -277,7 +277,7 @@ static NuError Nu_GetFileInfo(NuArchive* pArchive, const char* pathname,
struct stat sbuf; struct stat sbuf;
int cc; int cc;
cc = stat(pathname, &sbuf); cc = stat(pathnameUNI, &sbuf);
if (cc) { if (cc) {
if (errno == ENOENT) if (errno == ENOENT)
err = kNuErrFileNotFound; err = kNuErrFileNotFound;
@ -300,7 +300,7 @@ static NuError Nu_GetFileInfo(NuArchive* pArchive, const char* pathname,
pFileInfo->auxType = kDefaultAuxType; pFileInfo->auxType = kDefaultAuxType;
# if defined(MAC_LIKE) # if defined(MAC_LIKE)
if (!pFileInfo->isDirectory) { if (!pFileInfo->isDirectory) {
char path[4096]; char path[4096]; // TODO: use dynamic alloc or snprintf
struct stat res_sbuf; struct stat res_sbuf;
OSErr result; OSErr result;
OSType fileType, creator; OSType fileType, creator;
@ -308,7 +308,7 @@ static NuError Nu_GetFileInfo(NuArchive* pArchive, const char* pathname,
FSRef ref; FSRef ref;
uint32_t proType, proAux; uint32_t proType, proAux;
strcpy(path, pathname); strcpy(path, pathnameUNI);
strcat(path, "/rsrc"); strcat(path, "/rsrc");
cc = stat(path, &res_sbuf); cc = stat(path, &res_sbuf);
if (cc) { if (cc) {
@ -317,7 +317,7 @@ static NuError Nu_GetFileInfo(NuArchive* pArchive, const char* pathname,
} }
} }
result = FSPathMakeRef(pathname, &ref, NULL); result = FSPathMakeRef(pathnameUNI, &ref, NULL);
if (!result) { if (!result) {
result = FSGetCatalogInfo(&ref, kFSCatInfoFinderInfo, &catalogInfo, result = FSGetCatalogInfo(&ref, kFSCatInfoFinderInfo, &catalogInfo,
NULL, NULL, NULL); NULL, NULL, NULL);
@ -411,14 +411,14 @@ bail:
* file with data and resource forks, we only claim it exists if it has * file with data and resource forks, we only claim it exists if it has
* nonzero length. * nonzero length.
*/ */
static NuError Nu_FileForkExists(NuArchive* pArchive, const char* pathname, static NuError Nu_FileForkExists(NuArchive* pArchive,
Boolean isForkedFile, Boolean checkRsrcFork, Boolean* pExists, const UNICHAR* pathnameUNI, Boolean isForkedFile, Boolean checkRsrcFork,
NuFileInfo* pFileInfo) Boolean* pExists, NuFileInfo* pFileInfo)
{ {
NuError err = kNuErrNone; NuError err = kNuErrNone;
Assert(pArchive != NULL); Assert(pArchive != NULL);
Assert(pathname != NULL); Assert(pathnameUNI != NULL);
Assert(checkRsrcFork == true || checkRsrcFork == false); Assert(checkRsrcFork == true || checkRsrcFork == false);
Assert(pExists != NULL); Assert(pExists != NULL);
Assert(pFileInfo != NULL); Assert(pFileInfo != NULL);
@ -433,8 +433,8 @@ static NuError Nu_FileForkExists(NuArchive* pArchive, const char* pathname,
/* /*
* Check the data fork. * Check the data fork.
*/ */
Assert(pArchive->lastFileCreated == NULL); Assert(pArchive->lastFileCreatedUNI == NULL);
err = Nu_GetFileInfo(pArchive, pathname, pFileInfo); err = Nu_GetFileInfo(pArchive, pathnameUNI, pFileInfo);
if (err == kNuErrFileNotFound) { if (err == kNuErrFileNotFound) {
err = kNuErrNone; err = kNuErrNone;
*pExists = false; *pExists = false;
@ -444,8 +444,8 @@ static NuError Nu_FileForkExists(NuArchive* pArchive, const char* pathname,
/* /*
* Check the resource fork. * Check the resource fork.
*/ */
char path[4096]; char path[4096]; // TODO - dynamic alloc or snprintf
strncpy(path, pathname, 4089); strncpy(path, pathnameUNI, 4089);
strcat(path, "/rsrc"); strcat(path, "/rsrc");
err = Nu_GetFileInfo(pArchive, path, pFileInfo); err = Nu_GetFileInfo(pArchive, path, pFileInfo);
if (err == kNuErrFileNotFound) { if (err == kNuErrFileNotFound) {
@ -463,10 +463,10 @@ static NuError Nu_FileForkExists(NuArchive* pArchive, const char* pathname,
* On Unix and Windows we ignore "isForkedFile" and "checkRsrcFork". * On Unix and Windows we ignore "isForkedFile" and "checkRsrcFork".
* The file must not exist at all. * The file must not exist at all.
*/ */
Assert(pArchive->lastFileCreated == NULL); Assert(pArchive->lastFileCreatedUNI == NULL);
*pExists = true; *pExists = true;
err = Nu_GetFileInfo(pArchive, pathname, pFileInfo); err = Nu_GetFileInfo(pArchive, pathnameUNI, pFileInfo);
if (err == kNuErrFileNotFound) { if (err == kNuErrFileNotFound) {
err = kNuErrNone; err = kNuErrNone;
*pExists = false; *pExists = false;
@ -503,13 +503,13 @@ static NuError Nu_FileForkExists(NuArchive* pArchive, const char* pathname,
* Set the dates on a file according to what's in the record. * Set the dates on a file according to what's in the record.
*/ */
static NuError Nu_SetFileDates(NuArchive* pArchive, const NuRecord* pRecord, static NuError Nu_SetFileDates(NuArchive* pArchive, const NuRecord* pRecord,
const char* pathname) const UNICHAR* pathnameUNI)
{ {
NuError err = kNuErrNone; NuError err = kNuErrNone;
Assert(pArchive != NULL); Assert(pArchive != NULL);
Assert(pRecord != NULL); Assert(pRecord != NULL);
Assert(pathname != NULL); Assert(pathnameUNI != NULL);
#if defined(UNIX_LIKE) || defined(WINDOWS_LIKE) #if defined(UNIX_LIKE) || defined(WINDOWS_LIKE)
{ {
@ -521,9 +521,9 @@ static NuError Nu_SetFileDates(NuArchive* pArchive, const NuRecord* pRecord,
/* only do it if the NuDateTime was valid */ /* only do it if the NuDateTime was valid */
if (utbuf.modtime) { if (utbuf.modtime) {
if (utime(pathname, &utbuf) < 0) { if (utime(pathnameUNI, &utbuf) < 0) {
Nu_ReportError(NU_BLOB, errno, Nu_ReportError(NU_BLOB, errno,
"Unable to set time stamp on '%s'", pathname); "Unable to set time stamp on '%s'", pathnameUNI);
err = kNuErrFileSetDate; err = kNuErrFileSetDate;
goto bail; goto bail;
} }
@ -570,13 +570,13 @@ static Boolean Nu_IsRecordLocked(const NuRecord* pRecord)
* to do something if the original file was "locked". * to do something if the original file was "locked".
*/ */
static NuError Nu_SetFileAccess(NuArchive* pArchive, const NuRecord* pRecord, static NuError Nu_SetFileAccess(NuArchive* pArchive, const NuRecord* pRecord,
const char* pathname) const UNICHAR* pathnameUNI)
{ {
NuError err = kNuErrNone; NuError err = kNuErrNone;
Assert(pArchive != NULL); Assert(pArchive != NULL);
Assert(pRecord != NULL); Assert(pRecord != NULL);
Assert(pathname != NULL); Assert(pathnameUNI != NULL);
#if defined(UNIX_LIKE) || defined(WINDOWS_LIKE) #if defined(UNIX_LIKE) || defined(WINDOWS_LIKE)
/* only need to do something if the file was "locked" */ /* only need to do something if the file was "locked" */
@ -588,9 +588,10 @@ static NuError Nu_SetFileAccess(NuArchive* pArchive, const NuRecord* pRecord,
umask(mask); umask(mask);
//DBUG(("+++ chmod '%s' %03o (mask=%03o)\n", pathname, //DBUG(("+++ chmod '%s' %03o (mask=%03o)\n", pathname,
// (S_IRUSR | S_IRGRP | S_IROTH) & ~mask, mask)); // (S_IRUSR | S_IRGRP | S_IROTH) & ~mask, mask));
if (chmod(pathname, (S_IRUSR | S_IRGRP | S_IROTH) & ~mask) < 0) { if (chmod(pathnameUNI, (S_IRUSR | S_IRGRP | S_IROTH) & ~mask) < 0) {
Nu_ReportError(NU_BLOB, errno, Nu_ReportError(NU_BLOB, errno,
"unable to set access for '%s' to %03o", pathname, (int) mask); "unable to set access for '%s' to %03o", pathnameUNI,
(int) mask);
err = kNuErrFileSetAccess; err = kNuErrFileSetAccess;
goto bail; goto bail;
} }
@ -617,16 +618,16 @@ bail:
* Generally this just involves ensuring that the file is writable. If * Generally this just involves ensuring that the file is writable. If
* this is a convenient place to truncate it, we should do that too. * this is a convenient place to truncate it, we should do that too.
*/ */
static NuError Nu_PrepareForWriting(NuArchive* pArchive, const char* pathname, static NuError Nu_PrepareForWriting(NuArchive* pArchive,
Boolean prepRsrc, NuFileInfo* pFileInfo) const UNICHAR* pathnameUNI, Boolean prepRsrc, NuFileInfo* pFileInfo)
{ {
NuError err = kNuErrNone; NuError err = kNuErrNone;
#if defined(MAC_LIKE) #if defined(MAC_LIKE)
char path[4096]; char path[4096]; // TODO: use dynamic alloc or snprintf
#endif #endif
Assert(pArchive != NULL); Assert(pArchive != NULL);
Assert(pathname != NULL); Assert(pathnameUNI != NULL);
Assert(prepRsrc == true || prepRsrc == false); Assert(prepRsrc == true || prepRsrc == false);
Assert(pFileInfo != NULL); Assert(pFileInfo != NULL);
@ -639,16 +640,16 @@ static NuError Nu_PrepareForWriting(NuArchive* pArchive, const char* pathname,
#if defined(UNIX_LIKE) || defined(WINDOWS_LIKE) #if defined(UNIX_LIKE) || defined(WINDOWS_LIKE)
# if defined(MAC_LIKE) # if defined(MAC_LIKE)
if (prepRsrc) { if (prepRsrc) {
strcpy(path, pathname); strcpy(path, pathnameUNI);
strcat(path, "/rsrc"); strcat(path, "/rsrc");
pathname = path; pathname = path;
} }
# endif # endif
if (!(pFileInfo->unixMode & S_IWUSR)) { if (!(pFileInfo->unixMode & S_IWUSR)) {
/* make it writable by owner, plus whatever it was before */ /* make it writable by owner, plus whatever it was before */
if (chmod(pathname, S_IWUSR | pFileInfo->unixMode) < 0) { if (chmod(pathnameUNI, S_IWUSR | pFileInfo->unixMode) < 0) {
Nu_ReportError(NU_BLOB, errno, Nu_ReportError(NU_BLOB, errno,
"unable to set access for '%s'", pathname); "unable to set access for '%s'", pathnameUNI);
err = kNuErrFileSetAccess; err = kNuErrFileSetAccess;
goto bail; goto bail;
} }
@ -703,21 +704,21 @@ bail:
* subdirectory level doesn't exist either, cut down the pathname and * subdirectory level doesn't exist either, cut down the pathname and
* recurse. * recurse.
*/ */
static NuError Nu_CreateSubdirIFN(NuArchive* pArchive, const char* pathStart, static NuError Nu_CreateSubdirIFN(NuArchive* pArchive,
const char* pathEnd, char fssep) const UNICHAR* pathStartUNI, const char* pathEnd, char fssep)
{ {
NuError err = kNuErrNone; NuError err = kNuErrNone;
NuFileInfo fileInfo; NuFileInfo fileInfo;
char* tmpBuf = NULL; char* tmpBuf = NULL;
Assert(pArchive != NULL); Assert(pArchive != NULL);
Assert(pathStart != NULL); Assert(pathStartUNI != NULL);
Assert(pathEnd != NULL); Assert(pathEnd != NULL);
Assert(fssep != '\0'); Assert(fssep != '\0');
/* pathStart might have whole path, but we only want up to "pathEnd" */ /* pathStart might have whole path, but we only want up to "pathEnd" */
tmpBuf = strdup(pathStart); tmpBuf = strdup(pathStartUNI);
tmpBuf[pathEnd - pathStart +1] = '\0'; tmpBuf[pathEnd - pathStartUNI +1] = '\0';
err = Nu_GetFileInfo(pArchive, tmpBuf, &fileInfo); err = Nu_GetFileInfo(pArchive, tmpBuf, &fileInfo);
if (err == kNuErrFileNotFound) { if (err == kNuErrFileNotFound) {
@ -757,21 +758,21 @@ bail:
* If "pathname" is just a filename, or the set of directories matches * If "pathname" is just a filename, or the set of directories matches
* the last directory we created, we don't do anything. * the last directory we created, we don't do anything.
*/ */
static NuError Nu_CreatePathIFN(NuArchive* pArchive, const char* pathname, static NuError Nu_CreatePathIFN(NuArchive* pArchive, const UNICHAR* pathnameUNI,
char fssep) UNICHAR fssep)
{ {
NuError err = kNuErrNone; NuError err = kNuErrNone;
const char* pathStart; const char* pathStart;
const char* pathEnd; const char* pathEnd;
Assert(pArchive != NULL); Assert(pArchive != NULL);
Assert(pathname != NULL); Assert(pathnameUNI != NULL);
Assert(fssep != '\0'); Assert(fssep != '\0');
pathStart = pathname; pathStart = pathnameUNI;
#if !defined(MAC_LIKE) /* On the Mac, if it's a full path, treat it like one */ #if !defined(MAC_LIKE) /* On the Mac, if it's a full path, treat it like one */
if (pathname[0] == fssep) if (pathnameUNI[0] == fssep)
pathStart++; pathStart++;
#endif #endif
@ -792,8 +793,9 @@ static NuError Nu_CreatePathIFN(NuArchive* pArchive, const char* pathname,
* this is meant solely as an optimization to avoid extra stat() calls, * this is meant solely as an optimization to avoid extra stat() calls,
* so we want to use the most restrictive case. * so we want to use the most restrictive case.
*/ */
if (pArchive->lastDirCreated && if (pArchive->lastDirCreatedUNI &&
strncmp(pathStart, pArchive->lastDirCreated, pathEnd - pathStart +1) == 0) strncmp(pathStart, pArchive->lastDirCreatedUNI,
pathEnd - pathStart +1) == 0)
{ {
/* we created this one recently, don't do it again */ /* we created this one recently, don't do it again */
goto bail; goto bail;
@ -815,18 +817,20 @@ bail:
/* /*
* Open the file for writing, possibly truncating it. * Open the file for writing, possibly truncating it.
*/ */
static NuError Nu_OpenFileForWrite(NuArchive* pArchive, const char* pathname, static NuError Nu_OpenFileForWrite(NuArchive* pArchive,
Boolean openRsrc, FILE** pFp) const UNICHAR* pathnameUNI, Boolean openRsrc, FILE** pFp)
{ {
#if defined(MAC_LIKE) #if defined(MAC_LIKE)
// TODO: fix this -- use dynamic alloc or snprintf
char path[4096]; char path[4096];
if (openRsrc) { if (openRsrc) {
strcpy(path, pathname); strcpy(path, pathnameUNI);
strcat(path, "/rsrc"); strcat(path, "/rsrc");
pathname = path; pathnameUNI = path;
} }
#endif #endif
*pFp = fopen(pathname, kNuFileOpenWriteTrunc);
*pFp = fopen(pathnameUNI, kNuFileOpenWriteTrunc);
if (*pFp == NULL) if (*pFp == NULL)
return errno ? errno : -1; return errno ? errno : -1;
return kNuErrNone; return kNuErrNone;
@ -843,7 +847,7 @@ static NuError Nu_OpenFileForWrite(NuArchive* pArchive, const char* pathname,
* older than what we have. * older than what we have.
*/ */
NuError Nu_OpenOutputFile(NuArchive* pArchive, const NuRecord* pRecord, NuError Nu_OpenOutputFile(NuArchive* pArchive, const NuRecord* pRecord,
const NuThread* pThread, const char* newPathname, char newFssep, const NuThread* pThread, const UNICHAR* newPathnameUNI, UNICHAR newFssep,
FILE** pFp) FILE** pFp)
{ {
NuError err = kNuErrNone; NuError err = kNuErrNone;
@ -855,7 +859,7 @@ NuError Nu_OpenOutputFile(NuArchive* pArchive, const NuRecord* pRecord,
Assert(pArchive != NULL); Assert(pArchive != NULL);
Assert(pRecord != NULL); Assert(pRecord != NULL);
Assert(pThread != NULL); Assert(pThread != NULL);
Assert(newPathname != NULL); Assert(newPathnameUNI != NULL);
Assert(pFp != NULL); Assert(pFp != NULL);
/* set up some defaults, in case something goes wrong */ /* set up some defaults, in case something goes wrong */
@ -864,7 +868,7 @@ NuError Nu_OpenOutputFile(NuArchive* pArchive, const NuRecord* pRecord,
errorStatus.sysErr = 0; errorStatus.sysErr = 0;
errorStatus.message = NULL; errorStatus.message = NULL;
errorStatus.pRecord = pRecord; errorStatus.pRecord = pRecord;
errorStatus.pathname = newPathname; errorStatus.pathnameUNI = newPathnameUNI;
errorStatus.origPathname = NULL; errorStatus.origPathname = NULL;
errorStatus.filenameSeparator = newFssep; errorStatus.filenameSeparator = newFssep;
/*errorStatus.origArchiveTouched = false;*/ /*errorStatus.origArchiveTouched = false;*/
@ -891,7 +895,7 @@ NuError Nu_OpenOutputFile(NuArchive* pArchive, const NuRecord* pRecord,
* empty, this will *not* set "exists". * empty, this will *not* set "exists".
*/ */
fileInfo.isValid = false; fileInfo.isValid = false;
err = Nu_FileForkExists(pArchive, newPathname, isForkedFile, err = Nu_FileForkExists(pArchive, newPathnameUNI, isForkedFile,
extractingRsrc, &exists, &fileInfo); extractingRsrc, &exists, &fileInfo);
BailError(err); BailError(err);
@ -989,7 +993,7 @@ NuError Nu_OpenOutputFile(NuArchive* pArchive, const NuRecord* pRecord,
* return kNuSkip. * return kNuSkip.
*/ */
if (pArchive->valHandleExisting == kNuMustOverwrite) { if (pArchive->valHandleExisting == kNuMustOverwrite) {
DBUG(("+++ can't freshen nonexistent file '%s'\n", newPathname)); DBUG(("+++ can't freshen nonexistent file '%s'\n", newPathnameUNI));
if (pArchive->errorHandlerFunc != NULL) { if (pArchive->errorHandlerFunc != NULL) {
errorStatus.err = kNuErrDuplicateNotFound; errorStatus.err = kNuErrDuplicateNotFound;
@ -1040,23 +1044,23 @@ NuError Nu_OpenOutputFile(NuArchive* pArchive, const NuRecord* pRecord,
*/ */
if (exists) { if (exists) {
Assert(fileInfo.isValid == true); Assert(fileInfo.isValid == true);
err = Nu_PrepareForWriting(pArchive, newPathname, extractingRsrc, err = Nu_PrepareForWriting(pArchive, newPathnameUNI, extractingRsrc,
&fileInfo); &fileInfo);
BailError(err); BailError(err);
} else if (!fileInfo.isValid) { } else if (!fileInfo.isValid) {
err = Nu_CreatePathIFN(pArchive, newPathname, newFssep); err = Nu_CreatePathIFN(pArchive, newPathnameUNI, newFssep);
BailError(err); BailError(err);
} }
/* /*
* Open sesame. * Open sesame.
*/ */
err = Nu_OpenFileForWrite(pArchive, newPathname, extractingRsrc, pFp); err = Nu_OpenFileForWrite(pArchive, newPathnameUNI, extractingRsrc, pFp);
BailError(err); BailError(err);
#if defined(HAS_RESOURCE_FORKS) #if defined(HAS_RESOURCE_FORKS)
pArchive->lastFileCreated = newPathname; pArchive->lastFileCreatedUNI = newPathnameUNI;
#endif #endif
bail: bail:
@ -1065,7 +1069,7 @@ bail:
err != kNuErrFileExists) err != kNuErrFileExists)
{ {
Nu_ReportError(NU_BLOB, err, "Unable to open '%s'%s", Nu_ReportError(NU_BLOB, err, "Unable to open '%s'%s",
newPathname, extractingRsrc ? " (rsrc fork)" : ""); newPathnameUNI, extractingRsrc ? " (rsrc fork)" : "");
} }
} }
return err; return err;
@ -1090,7 +1094,7 @@ bail:
* quite right, but it's close enough. * quite right, but it's close enough.
*/ */
NuError Nu_CloseOutputFile(NuArchive* pArchive, const NuRecord* pRecord, NuError Nu_CloseOutputFile(NuArchive* pArchive, const NuRecord* pRecord,
FILE* fp, const char* pathname) FILE* fp, const UNICHAR* pathnameUNI)
{ {
NuError err; NuError err;
@ -1100,10 +1104,10 @@ NuError Nu_CloseOutputFile(NuArchive* pArchive, const NuRecord* pRecord,
fclose(fp); fclose(fp);
err = Nu_SetFileDates(pArchive, pRecord, pathname); err = Nu_SetFileDates(pArchive, pRecord, pathnameUNI);
BailError(err); BailError(err);
err = Nu_SetFileAccess(pArchive, pRecord, pathname); err = Nu_SetFileAccess(pArchive, pRecord, pathnameUNI);
BailError(err); BailError(err);
#ifdef MAC_LIKE #ifdef MAC_LIKE
@ -1112,11 +1116,11 @@ NuError Nu_CloseOutputFile(NuArchive* pArchive, const NuRecord* pRecord,
FSCatalogInfo catalogInfo; FSCatalogInfo catalogInfo;
FSRef ref; FSRef ref;
result = FSPathMakeRef(pathname, &ref, NULL); result = FSPathMakeRef(pathnameUNI, &ref, NULL);
BailError(result); BailError(result);
result = FSGetCatalogInfo(&ref, kFSCatInfoNodeFlags|kFSCatInfoFinderInfo, &catalogInfo, result = FSGetCatalogInfo(&ref, kFSCatInfoNodeFlags | kFSCatInfoFinderInfo,
NULL, NULL, NULL); &catalogInfo, NULL, NULL, NULL);
if (result) { if (result) {
BailError(kNuErrFileStat); BailError(kNuErrFileStat);
} }
@ -1148,10 +1152,10 @@ bail:
/* /*
* Open the file for reading, in "binary" mode when necessary. * Open the file for reading, in "binary" mode when necessary.
*/ */
static NuError Nu_OpenFileForRead(NuArchive* pArchive, const char* pathname, static NuError Nu_OpenFileForRead(NuArchive* pArchive,
Boolean openRsrc, FILE** pFp) const UNICHAR* pathnameUNI, Boolean openRsrc, FILE** pFp)
{ {
*pFp = fopen(pathname, kNuFileOpenReadOnly); *pFp = fopen(pathnameUNI, kNuFileOpenReadOnly);
if (*pFp == NULL) if (*pFp == NULL)
return errno ? errno : -1; return errno ? errno : -1;
return kNuErrNone; return kNuErrNone;
@ -1164,7 +1168,7 @@ static NuError Nu_OpenFileForRead(NuArchive* pArchive, const char* pathname,
* If the file can't be found, we give the application an opportunity to * If the file can't be found, we give the application an opportunity to
* skip the absent file, retry, or abort the whole thing. * skip the absent file, retry, or abort the whole thing.
*/ */
NuError Nu_OpenInputFile(NuArchive* pArchive, const char* pathname, NuError Nu_OpenInputFile(NuArchive* pArchive, const UNICHAR* pathnameUNI,
Boolean openRsrc, FILE** pFp) Boolean openRsrc, FILE** pFp)
{ {
NuError err = kNuErrNone; NuError err = kNuErrNone;
@ -1173,15 +1177,15 @@ NuError Nu_OpenInputFile(NuArchive* pArchive, const char* pathname,
NuResult result; NuResult result;
Assert(pArchive != NULL); Assert(pArchive != NULL);
Assert(pathname != NULL); Assert(pathnameUNI != NULL);
Assert(pFp != NULL); Assert(pFp != NULL);
#if defined(MAC_LIKE) #if defined(MAC_LIKE)
char path[4096]; char path[4096]; // TODO - dynamic alloc or snprintf
if (openRsrc) { if (openRsrc) {
strcpy(path, pathname); strcpy(path, pathnameUNI);
strcat(path, "/rsrc"); strcat(path, "/rsrc");
pathname = path; pathnameUNI = path;
} }
#endif #endif
@ -1189,7 +1193,7 @@ retry:
/* /*
* Open sesame. * Open sesame.
*/ */
err = Nu_OpenFileForRead(pArchive, pathname, openRsrc, pFp); err = Nu_OpenFileForRead(pArchive, pathnameUNI, openRsrc, pFp);
if (err == kNuErrNone) /* success! */ if (err == kNuErrNone) /* success! */
goto bail; goto bail;
@ -1202,7 +1206,7 @@ retry:
errorStatus.sysErr = 0; errorStatus.sysErr = 0;
errorStatus.message = NULL; errorStatus.message = NULL;
errorStatus.pRecord = NULL; errorStatus.pRecord = NULL;
errorStatus.pathname = pathname; errorStatus.pathnameUNI = pathnameUNI;
errorStatus.origPathname = NULL; errorStatus.origPathname = NULL;
errorStatus.filenameSeparator = '\0'; errorStatus.filenameSeparator = '\0';
/*errorStatus.origArchiveTouched = false;*/ /*errorStatus.origArchiveTouched = false;*/
@ -1246,7 +1250,7 @@ bail:
err != kNuErrFileExists) err != kNuErrFileExists)
{ {
Nu_ReportError(NU_BLOB, err, "Unable to open '%s'%s", Nu_ReportError(NU_BLOB, err, "Unable to open '%s'%s",
pathname, openRsrc ? " (rsrc fork)" : ""); pathnameUNI, openRsrc ? " (rsrc fork)" : "");
} }
} }
return err; return err;
@ -1262,14 +1266,14 @@ bail:
/* /*
* Delete a file. * Delete a file.
*/ */
NuError Nu_DeleteFile(const char* pathname) NuError Nu_DeleteFile(const UNICHAR* pathnameUNI)
{ {
#if defined(UNIX_LIKE) || defined(WINDOWS_LIKE) #if defined(UNIX_LIKE) || defined(WINDOWS_LIKE)
int cc; int cc;
DBUG(("--- Deleting '%s'\n", pathname)); DBUG(("--- Deleting '%s'\n", pathnameUNI));
cc = unlink(pathname); cc = unlink(pathnameUNI);
if (cc < 0) if (cc < 0)
return errno ? errno : -1; return errno ? errno : -1;
else else
@ -1282,14 +1286,14 @@ NuError Nu_DeleteFile(const char* pathname)
/* /*
* Rename a file from "fromPath" to "toPath". * Rename a file from "fromPath" to "toPath".
*/ */
NuError Nu_RenameFile(const char* fromPath, const char* toPath) NuError Nu_RenameFile(const UNICHAR* fromPathUNI, const UNICHAR* toPathUNI)
{ {
#if defined(UNIX_LIKE) || defined(WINDOWS_LIKE) #if defined(UNIX_LIKE) || defined(WINDOWS_LIKE)
int cc; int cc;
DBUG(("--- Renaming '%s' to '%s'\n", fromPath, toPath)); DBUG(("--- Renaming '%s' to '%s'\n", fromPathUNI, toPathUNI));
cc = rename(fromPath, toPath); cc = rename(fromPathUNI, toPathUNI);
if (cc < 0) if (cc < 0)
return errno ? errno : -1; return errno ? errno : -1;
else else

View File

@ -24,30 +24,28 @@
*/ */
NuError Nu_ProgressDataInit_Compress(NuArchive* pArchive, NuError Nu_ProgressDataInit_Compress(NuArchive* pArchive,
NuProgressData* pProgressData, const NuRecord* pRecord, NuProgressData* pProgressData, const NuRecord* pRecord,
const char* origPathname) const UNICHAR* origPathnameUNI, const UNICHAR* pathnameUNI)
{ {
const char* cp; const char* cp;
Assert(pProgressData != NULL); Assert(pProgressData != NULL);
Assert(pArchive != NULL); Assert(pArchive != NULL);
Assert(pRecord != NULL); Assert(pRecord != NULL);
Assert(origPathname != NULL); Assert(origPathnameUNI != NULL);
Assert(pathnameUNI != NULL);
pProgressData->pRecord = pRecord; pProgressData->pRecord = pRecord;
pProgressData->origPathname = origPathname; pProgressData->origPathnameUNI = origPathnameUNI;
pProgressData->pathname = pRecord->filename; pProgressData->pathnameUNI = pathnameUNI;
cp = strrchr(pRecord->filename, cp = strrchr(pathnameUNI, NuGetSepFromSysInfo(pRecord->recFileSysInfo));
NuGetSepFromSysInfo(pRecord->recFileSysInfo));
if (cp == NULL || *(cp+1) == '\0') if (cp == NULL || *(cp+1) == '\0')
pProgressData->filename = pProgressData->pathname; pProgressData->filenameUNI = pProgressData->pathnameUNI;
else else
pProgressData->filename = cp+1; pProgressData->filenameUNI = cp+1;
pProgressData->operation = kNuOpAdd; pProgressData->operation = kNuOpAdd;
pProgressData->state = kNuProgressPreparing; pProgressData->state = kNuProgressPreparing;
/*pProgressData->compressedLength = 0;*/
/*pProgressData->compressedProgress = 0;*/
pProgressData->uncompressedLength = 0; pProgressData->uncompressedLength = 0;
pProgressData->uncompressedProgress = 0; pProgressData->uncompressedProgress = 0;
@ -69,7 +67,8 @@ NuError Nu_ProgressDataInit_Compress(NuArchive* pArchive,
*/ */
NuError Nu_ProgressDataInit_Expand(NuArchive* pArchive, NuError Nu_ProgressDataInit_Expand(NuArchive* pArchive,
NuProgressData* pProgressData, const NuRecord* pRecord, NuProgressData* pProgressData, const NuRecord* pRecord,
const char* newPathname, char newFssep, NuValue convertEOL) const UNICHAR* newPathnameUNI, UNICHAR newFssep,
const UNICHAR* origPathnameUNI, NuValue convertEOL)
{ {
const NuThread* pThreadIter; const NuThread* pThreadIter;
const char* cp; const char* cp;
@ -78,19 +77,20 @@ NuError Nu_ProgressDataInit_Expand(NuArchive* pArchive,
Assert(pProgressData != NULL); Assert(pProgressData != NULL);
Assert(pArchive != NULL); Assert(pArchive != NULL);
Assert(pRecord != NULL); Assert(pRecord != NULL);
Assert(newPathname != NULL); Assert(newPathnameUNI != NULL);
Assert(origPathnameUNI != NULL);
Assert(newFssep != 0); Assert(newFssep != 0);
pProgressData->pRecord = pRecord; pProgressData->pRecord = pRecord;
pProgressData->expand.pThread = NULL; pProgressData->expand.pThread = NULL;
pProgressData->origPathname = pRecord->filename; pProgressData->origPathnameUNI = origPathnameUNI;
pProgressData->pathname = newPathname; pProgressData->pathnameUNI = newPathnameUNI;
cp = strrchr(newPathname, newFssep); cp = strrchr(newPathnameUNI, newFssep);
if (cp == NULL || *(cp+1) == '\0') if (cp == NULL || *(cp+1) == '\0')
pProgressData->filename = newPathname; pProgressData->filenameUNI = newPathnameUNI;
else else
pProgressData->filename = cp+1; pProgressData->filenameUNI = cp+1;
pProgressData->expand.convertEOL = convertEOL; pProgressData->expand.convertEOL = convertEOL;
@ -110,8 +110,6 @@ NuError Nu_ProgressDataInit_Expand(NuArchive* pArchive,
if (pArchive->testMode) if (pArchive->testMode)
pProgressData->operation = kNuOpTest; pProgressData->operation = kNuOpTest;
pProgressData->state = kNuProgressPreparing; pProgressData->state = kNuProgressPreparing;
/*pProgressData->expand.compressedLength = 0;*/
/*pProgressData->expand.compressedProgress = 0;*/
pProgressData->uncompressedLength = 0; pProgressData->uncompressedLength = 0;
pProgressData->uncompressedProgress = 0; pProgressData->uncompressedProgress = 0;

View File

@ -12,6 +12,9 @@
# #
# The shared library support currently leaves much to be desired. # The shared library support currently leaves much to be desired.
# #
# If you build with -DDEBUG_MSGS, nulib2 will be able to use the hidden
# 'g' command, which generates a verbose archive dump for debugging.
#
# NufxLib install location. # NufxLib install location.
prefix = @prefix@ prefix = @prefix@
@ -33,12 +36,12 @@ OPT = @CFLAGS@
GCC_FLAGS = -Wall -Wwrite-strings -Wstrict-prototypes -Wpointer-arith -Wshadow GCC_FLAGS = -Wall -Wwrite-strings -Wstrict-prototypes -Wpointer-arith -Wshadow
CFLAGS = @BUILD_FLAGS@ -I. @DEFS@ -DOPTFLAGSTR="\"$(OPT)\"" CFLAGS = @BUILD_FLAGS@ -I. @DEFS@ -DOPTFLAGSTR="\"$(OPT)\""
SRCS = Archive.c ArchiveIO.c Bzip2.c Compress.c Crc16.c Debug.c \ SRCS = Archive.c ArchiveIO.c Bzip2.c Charset.c Compress.c Crc16.c \
Deferred.c Deflate.c Entry.c Expand.c FileIO.c Funnel.c \ Debug.c Deferred.c Deflate.c Entry.c Expand.c FileIO.c Funnel.c \
Lzc.c Lzw.c MiscStuff.c MiscUtils.c Record.c SourceSink.c \ Lzc.c Lzw.c MiscStuff.c MiscUtils.c Record.c SourceSink.c \
Squeeze.c Thread.c Value.c Version.c Squeeze.c Thread.c Value.c Version.c
OBJS = Archive.o ArchiveIO.o Bzip2.o Compress.o Crc16.o Debug.o \ OBJS = Archive.o ArchiveIO.o Bzip2.o Charset.o Compress.o Crc16.o \
Deferred.o Deflate.o Entry.o Expand.o FileIO.o Funnel.o \ Debug.o Deferred.o Deflate.o Entry.o Expand.o FileIO.o Funnel.o \
Lzc.o Lzw.o MiscStuff.o MiscUtils.o Record.o SourceSink.o \ Lzc.o Lzw.o MiscStuff.o MiscUtils.o Record.o SourceSink.o \
Squeeze.o Thread.o Value.o Version.o Squeeze.o Thread.o Value.o Version.o
@ -79,7 +82,7 @@ $(STATIC_PRODUCT): $(OBJS)
$(AR) $@ $(OBJS) $(AR) $@ $(OBJS)
@RANLIB@ $@ @RANLIB@ $@
# BUG: we probably want -fPIC -D_REENTRANT on the compile lines for this. # BUG: we need -fPIC, maybe -D_REENTRANT when compiling for this.
# BUG: for Linux we may want -Wl,-soname,libnufx.so.1 on the link line. # BUG: for Linux we may want -Wl,-soname,libnufx.so.1 on the link line.
$(SHARED_PRODUCT): $(OBJS) $(SHARED_PRODUCT): $(OBJS)
-rm -f $(STATIC_PRODUCT) $(SHARED_PRODUCT) -rm -f $(STATIC_PRODUCT) $(SHARED_PRODUCT)
@ -110,12 +113,29 @@ baktar:
@gzip -9 nufxlib.tar @gzip -9 nufxlib.tar
@mv -i nufxlib.tar.gz /home/fadden/BAK/ @mv -i nufxlib.tar.gz /home/fadden/BAK/
depend: # dependency info
makedepend -- $(CFLAGS) -I/usr/local/include -- $(SRCS) COMMON_HDRS = NufxLibPriv.h NufxLib.h MiscStuff.h SysDefs.h
@(cd samples; unset CFLAGS OBJS; @SET_MAKE@ $(MAKE) depend) Archive.o: Archive.c $(COMMON_HDRS)
ArchiveIO.o: ArchiveIO.c $(COMMON_HDRS)
# catch OPTFLAGSTR updates Bzip2.o: Bzip2.c $(COMMON_HDRS)
Version.o: Makefile Charset.o: Charset.c $(COMMON_HDRS)
Compress.o: Compress.c $(COMMON_HDRS)
# DO NOT DELETE THIS LINE -- make depend depends on it. Crc16.o: Crc16.c $(COMMON_HDRS)
Debug.o: Debug.c $(COMMON_HDRS)
Deferred.o: Deferred.c $(COMMON_HDRS)
Deflate.o: Deflate.c $(COMMON_HDRS)
Entry.o: Entry.c $(COMMON_HDRS)
Expand.o: Expand.c $(COMMON_HDRS)
FileIO.o: FileIO.c $(COMMON_HDRS)
Funnel.o: Funnel.c $(COMMON_HDRS)
Lzc.o: Lzc.c $(COMMON_HDRS)
Lzw.o: Lzw.c $(COMMON_HDRS)
MiscStuff.o: MiscStuff.c $(COMMON_HDRS)
MiscUtils.o: MiscUtils.c $(COMMON_HDRS)
Record.o: Record.c $(COMMON_HDRS)
SourceSink.o: SourceSink.c $(COMMON_HDRS)
Squeeze.o: Squeeze.c $(COMMON_HDRS)
Thread.o: Thread.c $(COMMON_HDRS)
Value.o: Value.c $(COMMON_HDRS)
Version.o: Version.c $(COMMON_HDRS) Makefile

View File

@ -65,16 +65,16 @@ LDFLAGS = $(LDFLAGS) zlib.lib
# object files # object files
OBJS = Archive.obj ArchiveIO.obj Bzip2.obj Compress.obj Crc16.obj Debug.obj \ OBJS = Archive.obj ArchiveIO.obj Bzip2.obj Charset.obj Compress.obj \
Deferred.obj Deflate.obj Entry.obj Expand.obj FileIO.obj Funnel.obj \ Crc16.obj Debug.obj Deferred.obj Deflate.obj Entry.obj Expand.obj \
Lzc.obj Lzw.obj MiscStuff.obj MiscUtils.obj Record.obj SourceSink.obj \ FileIO.obj Funnel.obj Lzc.obj Lzw.obj MiscStuff.obj MiscUtils.obj \
Squeeze.obj Thread.obj Value.obj Version.obj Record.obj SourceSink.obj Squeeze.obj Thread.obj Value.obj Version.obj
# build targets -- static library, dynamic library, and test programs # build targets -- static library, dynamic library, and test programs
all: $(STATICLIB) $(SHAREDLIB) $(IMPLIB) \ all: $(STATICLIB) $(SHAREDLIB) $(IMPLIB) \
exerciser.exe imgconv.exe launder.exe test-basic.exe \ exerciser.exe imgconv.exe launder.exe test-basic.exe test-basic-d.exe \
test-basic-d.exe test-extract.exe test-simple.exe test-twirl.exe test-extract.exe test-names.exe test-simple.exe test-twirl.exe
clean: clean:
-del *.obj *.pdb *.exp -del *.obj *.pdb *.exp
@ -107,6 +107,9 @@ test-basic-d.exe: TestBasic.obj $(IMPLIB)
test-extract.exe: TestExtract.obj $(STATICLIB) test-extract.exe: TestExtract.obj $(STATICLIB)
$(LD) $(LDFLAGS) -out:$@ TestExtract.obj $(STATICLIB) $(LD) $(LDFLAGS) -out:$@ TestExtract.obj $(STATICLIB)
test-names.exe: TestNames.obj $(STATICLIB)
$(LD) $(LDFLAGS) -out:$@ TestNames.obj $(STATICLIB)
test-simple.exe: TestSimple.obj $(STATICLIB) test-simple.exe: TestSimple.obj $(STATICLIB)
$(LD) $(LDFLAGS) -out:$@ TestSimple.obj $(STATICLIB) $(LD) $(LDFLAGS) -out:$@ TestSimple.obj $(STATICLIB)
@ -125,6 +128,7 @@ COMMON_HDRS = NufxLibPriv.h NufxLib.h MiscStuff.h SysDefs.h
Archive.obj: Archive.c $(COMMON_HDRS) Archive.obj: Archive.c $(COMMON_HDRS)
ArchiveIO.obj: ArchiveIO.c $(COMMON_HDRS) ArchiveIO.obj: ArchiveIO.c $(COMMON_HDRS)
Bzip2.obj: Bzip2.c $(COMMON_HDRS) Bzip2.obj: Bzip2.c $(COMMON_HDRS)
Charset.obj: Charset.c $(COMMON_HDRS)
Compress.obj: Compress.c $(COMMON_HDRS) Compress.obj: Compress.c $(COMMON_HDRS)
Crc16.obj: Crc16.c $(COMMON_HDRS) Crc16.obj: Crc16.c $(COMMON_HDRS)
Debug.obj: Debug.c $(COMMON_HDRS) Debug.obj: Debug.c $(COMMON_HDRS)
@ -150,6 +154,7 @@ ImgConv.obj: samples/ImgConv.c $(COMMON_HDRS)
Launder.obj: samples/Launder.c $(COMMON_HDRS) Launder.obj: samples/Launder.c $(COMMON_HDRS)
TestBasic.obj: samples/TestBasic.c $(COMMON_HDRS) TestBasic.obj: samples/TestBasic.c $(COMMON_HDRS)
TestExtract.obj: samples/TestExtract.c $(COMMON_HDRS) TestExtract.obj: samples/TestExtract.c $(COMMON_HDRS)
TestNames.obj: samples/TestNames.c $(COMMON_HDRS)
TestSimple.obj: samples/TestSimple.c $(COMMON_HDRS) TestSimple.obj: samples/TestSimple.c $(COMMON_HDRS)
TestTwirl.obj: samples/TestTwirl.c $(COMMON_HDRS) TestTwirl.obj: samples/TestTwirl.c $(COMMON_HDRS)

View File

@ -6,7 +6,6 @@
* *
* Miscellaneous NufxLib utility functions. * Miscellaneous NufxLib utility functions.
*/ */
#define __MiscUtils_c__
#include "NufxLibPriv.h" #include "NufxLibPriv.h"
/* /*
@ -206,7 +205,8 @@ const char* Nu_StrError(NuError err)
* can't invoke the error message callback if the pointer is NULL. * can't invoke the error message callback if the pointer is NULL.
*/ */
void Nu_ReportError(NuArchive* pArchive, const char* file, int line, void Nu_ReportError(NuArchive* pArchive, const char* file, int line,
const char* function, Boolean isDebug, NuError err, const char* format, ...) const char* function, Boolean isDebug, NuError err,
const UNICHAR* format, ...)
{ {
NuErrorMessage errorMessage; NuErrorMessage errorMessage;
const char* msg; const char* msg;

View File

@ -32,8 +32,8 @@ extern "C" {
* The "bug" version can usually be ignored, since it represents minor * The "bug" version can usually be ignored, since it represents minor
* fixes. Unless, of course, your code depends upon that fix. * fixes. Unless, of course, your code depends upon that fix.
*/ */
#define kNuVersionMajor 2 #define kNuVersionMajor 3
#define kNuVersionMinor 3 #define kNuVersionMinor 0
#define kNuVersionBug 0 #define kNuVersionBug 0
@ -43,6 +43,33 @@ extern "C" {
* =========================================================================== * ===========================================================================
*/ */
/*
* Unicode character type. For Linux and Mac OS X, filenames use "narrow"
* characters and UTF-8 encoding, which allows them to use standard file I/O
* functions like fopen(). Windows uses UTF-16, which requires a different
* character type and an alternative set of I/O functions like _wfopen().
*
* The idea is that NufxLib API functions will operate on filenames with
* the OS dominant method, so on Windows the API accepts UTF-16. This
* definition is a bit like Windows TCHAR, but it's dependent on the OS, not
* on whether _MBCS or _UNICODE is defined.
*
* The app can include "Unichar.h" to get definitions for functions that
* switch between narrow and wide functions (e.g. "unistrlen()" becomes
* strlen() or wcslen() as appropriate).
*
* We switch based on _WIN32, because we're not really switching on
* filename-character size; the key issue is all the pesky wide I/O calls.
*/
#if defined(_WIN32)
// TODO: complete this
//# include <wchar.h>
//# define UNICHAR wchar_t
# define UNICHAR char
#else
# define UNICHAR char
#endif
/* /*
* Error values returned from functions. * Error values returned from functions.
* *
@ -199,7 +226,7 @@ typedef enum NuThreadFormat {
/* extract the filesystem separator char from the "file_sys_info" field */ /* extract the filesystem separator char from the "file_sys_info" field */
#define NuGetSepFromSysInfo(sysInfo) \ #define NuGetSepFromSysInfo(sysInfo) \
((char) ((sysInfo) & 0xff)) ((UNICHAR) ((sysInfo) & 0xff))
/* return a file_sys_info with a replaced filesystem separator */ /* return a file_sys_info with a replaced filesystem separator */
#define NuSetSepInSysInfo(sysInfo, newSep) \ #define NuSetSepInSysInfo(sysInfo, newSep) \
((uint16_t) (((sysInfo) & 0xff00) | ((newSep) & 0xff)) ) ((uint16_t) (((sysInfo) & 0xff00) | ((newSep) & 0xff)) )
@ -420,6 +447,10 @@ typedef struct NuThread {
* NuFX "record" definition. * NuFX "record" definition.
* *
* (Note to developers: update Nu_AddRecord if this changes.) * (Note to developers: update Nu_AddRecord if this changes.)
*
* The filenames are in Mac OS Roman format. It's arguable whether MOR
* strings should be part of the interface at all. However, the API
* pre-dates the inclusion of Unicode support, and I'm leaving it alone.
*/ */
#define kNufxIDLen 4 /* len of 'NuFX' with funky MSBs */ #define kNufxIDLen 4 /* len of 'NuFX' with funky MSBs */
#define kNuReasonableAttribCount 256 #define kNuReasonableAttribCount 256
@ -449,20 +480,20 @@ typedef struct NuRecord {
uint8_t* recOptionList; /* NULL if v0 or recOptionSize==0 */ uint8_t* recOptionList; /* NULL if v0 or recOptionSize==0 */
/* data specified by recAttribCount, not accounted for by option list */ /* data specified by recAttribCount, not accounted for by option list */
long extraCount; int32_t extraCount;
uint8_t* extraBytes; uint8_t* extraBytes;
uint16_t recFilenameLength; /* usually zero */ uint16_t recFilenameLength; /* usually zero */
char* recFilename; /* doubles as disk volume_name */ char* recFilenameMOR; /* doubles as disk volume_name */
/* extra goodies; "dirtyHeader" does not apply to anything below */ /* extra goodies; "dirtyHeader" does not apply to anything below */
NuRecordIdx recordIdx; /* session-unique record index */ NuRecordIdx recordIdx; /* session-unique record index */
char* threadFilename; /* extracted from filename thread */ char* threadFilenameMOR; /* extracted from filename thread */
char* newFilename; /* memorized during "add file" call */ char* newFilenameMOR; /* memorized during "add file" call */
const char* filename; /* points at recFilen or threadFilen */ const char* filenameMOR; /* points at recFilen or threadFilen */
uint32_t recHeaderLength; /* size of rec hdr, incl thread hdrs */ uint32_t recHeaderLength; /* size of rec hdr, incl thread hdrs */
uint32_t totalCompLength; /* total len of data in archive file */ uint32_t totalCompLength; /* total len of data in archive file */
long fakeThreads; /* used by "MaskDataless" */ uint32_t fakeThreads; /* used by "MaskDataless" */
int isBadMac; /* malformed "bad mac" header */ int isBadMac; /* malformed "bad mac" header */
long fileOffset; /* file offset of record header */ long fileOffset; /* file offset of record header */
@ -527,14 +558,19 @@ typedef struct NuRecordAttr {
/* /*
* Some additional details about a file. * Some additional details about a file.
*
* Ideally (from an API cleanliness perspective) the storage name would
* be passed around as UTF-8 and converted internally. Passing it as
* MOR required fewer changes to the library, and allows us to avoid
* having to deal with illegal characters.
*/ */
typedef struct NuFileDetails { typedef struct NuFileDetails {
/* used during AddFile call */ /* used during AddFile call */
NuThreadID threadID; /* data, rsrc, disk img? */ NuThreadID threadID; /* data, rsrc, disk img? */
const char* origName; const void* origName; /* arbitrary pointer, usually a string */
/* these go straight into the NuRecord */ /* these go straight into the NuRecord */
const char* storageName; const char* storageNameMOR;
NuFileSysID fileSysID; NuFileSysID fileSysID;
uint16_t fileSysInfo; uint16_t fileSysInfo;
uint32_t access; uint32_t access;
@ -559,12 +595,12 @@ typedef struct NuSelectionProposal {
* Passed into the OutputPathnameFilter callback. * Passed into the OutputPathnameFilter callback.
*/ */
typedef struct NuPathnameProposal { typedef struct NuPathnameProposal {
const char* pathname; const UNICHAR* pathnameUNI;
char filenameSeparator; char filenameSeparator;
const NuRecord* pRecord; const NuRecord* pRecord;
const NuThread* pThread; const NuThread* pThread;
const char* newPathname; const UNICHAR* newPathnameUNI;
uint8_t newFilenameSeparator; uint8_t newFilenameSeparator;
/*NuThreadID newStorage;*/ /*NuThreadID newStorage;*/
NuDataSink* newDataSink; NuDataSink* newDataSink;
@ -599,7 +635,8 @@ typedef enum NuProgressState {
} NuProgressState; } NuProgressState;
/* /*
* Passed into the ProgressUpdater callback. * Passed into the ProgressUpdater callback. All pointers become
* invalid when the callback returns.
* *
* [ Thought for the day: add an optional flag that causes us to only * [ Thought for the day: add an optional flag that causes us to only
* call the progressFunc when the "percentComplete" changes by more * call the progressFunc when the "percentComplete" changes by more
@ -614,11 +651,11 @@ typedef struct NuProgressData {
short percentComplete; /* 0-100 */ short percentComplete; /* 0-100 */
/* original pathname (in archive for expand, on disk for compress) */ /* original pathname (in archive for expand, on disk for compress) */
const char* origPathname; const UNICHAR* origPathnameUNI;
/* processed pathname (PathnameFilter for expand, in-record for compress) */ /* processed pathname (PathnameFilter for expand, in-record for compress) */
const char* pathname; const UNICHAR* pathnameUNI;
/* basename of "pathname" */ /* basename of "pathname" (for convenience) */
const char* filename; const UNICHAR* filenameUNI;
/* pointer to the record we're expanding from */ /* pointer to the record we're expanding from */
const NuRecord* pRecord; const NuRecord* pRecord;
@ -650,11 +687,11 @@ typedef struct NuErrorStatus {
NuOperation operation; /* were we adding, extracting, ?? */ NuOperation operation; /* were we adding, extracting, ?? */
NuError err; /* library error code */ NuError err; /* library error code */
int sysErr; /* system error code, if applicable */ int sysErr; /* system error code, if applicable */
const char* message; /* (optional) message to user */ const UNICHAR* message; /* (optional) message to user */
const NuRecord* pRecord; /* relevant record, if any */ const NuRecord* pRecord; /* relevant record, if any */
const char* pathname; /* problematic pathname, if any */ const UNICHAR* pathnameUNI; /* problematic pathname, if any */
const char* origPathname; /* original pathname, if any */ const void* origPathname; /* original pathname ref, if any */
char filenameSeparator; /* fssep for pathname, if any */ UNICHAR filenameSeparator; /* fssep for pathname, if any */
/*char origArchiveTouched;*/ /*char origArchiveTouched;*/
char canAbort; /* give option to abort */ char canAbort; /* give option to abort */
@ -670,12 +707,12 @@ typedef struct NuErrorStatus {
* Error message callback gets one of these. * Error message callback gets one of these.
*/ */
typedef struct NuErrorMessage { typedef struct NuErrorMessage {
const char* message; /* the message itself */ const char* message; /* the message itself (UTF-8) */
NuError err; /* relevant error code (may be none) */ NuError err; /* relevant error code (may be none) */
short isDebug; /* set for debug-only messages */ short isDebug; /* set for debug-only messages */
/* these identify where the message originated if lib built w/debug set */ /* these identify where the message originated if lib built w/debug set */
const char* file; /* source file */ const char* file; /* source file (UTF-8) */
int line; /* line number */ int line; /* line number */
const char* function; /* function name (might be NULL) */ const char* function; /* function name (might be NULL) */
} NuErrorMessage; } NuErrorMessage;
@ -728,37 +765,38 @@ NUFXLIB_API NuError NuExtract(NuArchive* pArchive);
NUFXLIB_API NuError NuTest(NuArchive* pArchive); NUFXLIB_API NuError NuTest(NuArchive* pArchive);
/* strictly non-streaming read-only interfaces */ /* strictly non-streaming read-only interfaces */
NUFXLIB_API NuError NuOpenRO(const char* archivePathname,NuArchive** ppArchive); NUFXLIB_API NuError NuOpenRO(const UNICHAR* archivePathnameUNI,
NuArchive** ppArchive);
NUFXLIB_API NuError NuExtractRecord(NuArchive* pArchive, NuRecordIdx recordIdx); NUFXLIB_API NuError NuExtractRecord(NuArchive* pArchive, NuRecordIdx recordIdx);
NUFXLIB_API NuError NuExtractThread(NuArchive* pArchive, NuThreadIdx threadIdx, NUFXLIB_API NuError NuExtractThread(NuArchive* pArchive, NuThreadIdx threadIdx,
NuDataSink* pDataSink); NuDataSink* pDataSink);
NUFXLIB_API NuError NuTestRecord(NuArchive* pArchive, NuRecordIdx recordIdx); NUFXLIB_API NuError NuTestRecord(NuArchive* pArchive, NuRecordIdx recordIdx);
NUFXLIB_API NuError NuGetRecord(NuArchive* pArchive, NuRecordIdx recordIdx, NUFXLIB_API NuError NuGetRecord(NuArchive* pArchive, NuRecordIdx recordIdx,
const NuRecord** ppRecord); const NuRecord** ppRecord);
NUFXLIB_API NuError NuGetRecordIdxByName(NuArchive* pArchive, const char* name, NUFXLIB_API NuError NuGetRecordIdxByName(NuArchive* pArchive,
NuRecordIdx* pRecordIdx); const char* nameMOR, NuRecordIdx* pRecordIdx);
NUFXLIB_API NuError NuGetRecordIdxByPosition(NuArchive* pArchive, NUFXLIB_API NuError NuGetRecordIdxByPosition(NuArchive* pArchive,
uint32_t position, NuRecordIdx* pRecordIdx); uint32_t position, NuRecordIdx* pRecordIdx);
/* read/write interfaces */ /* read/write interfaces */
NUFXLIB_API NuError NuOpenRW(const char* archivePathname, NUFXLIB_API NuError NuOpenRW(const UNICHAR* archivePathnameUNI,
const char* tempPathname, uint32_t flags, const UNICHAR* tempPathnameUNI, uint32_t flags,
NuArchive** ppArchive); NuArchive** ppArchive);
NUFXLIB_API NuError NuFlush(NuArchive* pArchive, long* pStatusFlags); NUFXLIB_API NuError NuFlush(NuArchive* pArchive, uint32_t* pStatusFlags);
NUFXLIB_API NuError NuAddRecord(NuArchive* pArchive, NUFXLIB_API NuError NuAddRecord(NuArchive* pArchive,
const NuFileDetails* pFileDetails, NuRecordIdx* pRecordIdx); const NuFileDetails* pFileDetails, NuRecordIdx* pRecordIdx);
NUFXLIB_API NuError NuAddThread(NuArchive* pArchive, NuRecordIdx recordIdx, NUFXLIB_API NuError NuAddThread(NuArchive* pArchive, NuRecordIdx recordIdx,
NuThreadID threadID, NuDataSource* pDataSource, NuThreadID threadID, NuDataSource* pDataSource,
NuThreadIdx* pThreadIdx); NuThreadIdx* pThreadIdx);
NUFXLIB_API NuError NuAddFile(NuArchive* pArchive, const char* pathname, NUFXLIB_API NuError NuAddFile(NuArchive* pArchive, const UNICHAR* pathnameUNI,
const NuFileDetails* pFileDetails, short fromRsrcFork, const NuFileDetails* pFileDetails, short fromRsrcFork,
NuRecordIdx* pRecordIdx); NuRecordIdx* pRecordIdx);
NUFXLIB_API NuError NuRename(NuArchive* pArchive, NuRecordIdx recordIdx, NUFXLIB_API NuError NuRename(NuArchive* pArchive, NuRecordIdx recordIdx,
const char* pathname, char fssep); const char* pathnameMOR, UNICHAR fssep);
NUFXLIB_API NuError NuSetRecordAttr(NuArchive* pArchive, NuRecordIdx recordIdx, NUFXLIB_API NuError NuSetRecordAttr(NuArchive* pArchive, NuRecordIdx recordIdx,
const NuRecordAttr* pRecordAttr); const NuRecordAttr* pRecordAttr);
NUFXLIB_API NuError NuUpdatePresizedThread(NuArchive* pArchive, NUFXLIB_API NuError NuUpdatePresizedThread(NuArchive* pArchive,
NuThreadIdx threadIdx, NuDataSource* pDataSource, long* pMaxLen); NuThreadIdx threadIdx, NuDataSource* pDataSource, int32_t* pMaxLen);
NUFXLIB_API NuError NuDelete(NuArchive* pArchive); NUFXLIB_API NuError NuDelete(NuArchive* pArchive);
NUFXLIB_API NuError NuDeleteRecord(NuArchive* pArchive, NuRecordIdx recordIdx); NUFXLIB_API NuError NuDeleteRecord(NuArchive* pArchive, NuRecordIdx recordIdx);
NUFXLIB_API NuError NuDeleteThread(NuArchive* pArchive, NuThreadIdx threadIdx); NUFXLIB_API NuError NuDeleteThread(NuArchive* pArchive, NuThreadIdx threadIdx);
@ -780,7 +818,7 @@ NUFXLIB_API NuError NuDebugDumpArchive(NuArchive* pArchive);
/* sources and sinks */ /* sources and sinks */
NUFXLIB_API NuError NuCreateDataSourceForFile(NuThreadFormat threadFormat, NUFXLIB_API NuError NuCreateDataSourceForFile(NuThreadFormat threadFormat,
uint32_t otherLen, const char* pathname, uint32_t otherLen, const UNICHAR* pathnameUNI,
short isFromRsrcFork, NuDataSource** ppDataSource); short isFromRsrcFork, NuDataSource** ppDataSource);
NUFXLIB_API NuError NuCreateDataSourceForFP(NuThreadFormat threadFormat, NUFXLIB_API NuError NuCreateDataSourceForFP(NuThreadFormat threadFormat,
uint32_t otherLen, FILE* fp, long offset, long length, uint32_t otherLen, FILE* fp, long offset, long length,
@ -792,7 +830,7 @@ NUFXLIB_API NuError NuFreeDataSource(NuDataSource* pDataSource);
NUFXLIB_API NuError NuDataSourceSetRawCrc(NuDataSource* pDataSource, NUFXLIB_API NuError NuDataSourceSetRawCrc(NuDataSource* pDataSource,
uint16_t crc); uint16_t crc);
NUFXLIB_API NuError NuCreateDataSinkForFile(short doExpand, NuValue convertEOL, NUFXLIB_API NuError NuCreateDataSinkForFile(short doExpand, NuValue convertEOL,
const char* pathname, char fssep, NuDataSink** ppDataSink); const UNICHAR* pathnameUNI, UNICHAR fssep, NuDataSink** ppDataSink);
NUFXLIB_API NuError NuCreateDataSinkForFP(short doExpand, NuValue convertEOL, NUFXLIB_API NuError NuCreateDataSinkForFP(short doExpand, NuValue convertEOL,
FILE* fp, NuDataSink** ppDataSink); FILE* fp, NuDataSink** ppDataSink);
NUFXLIB_API NuError NuCreateDataSinkForBuffer(short doExpand, NUFXLIB_API NuError NuCreateDataSinkForBuffer(short doExpand,
@ -803,8 +841,8 @@ NUFXLIB_API NuError NuDataSinkGetOutCount(NuDataSink* pDataSink,
uint32_t* pOutCount); uint32_t* pOutCount);
/* miscellaneous non-archive operations */ /* miscellaneous non-archive operations */
NUFXLIB_API NuError NuGetVersion(long* pMajorVersion, long* pMinorVersion, NUFXLIB_API NuError NuGetVersion(int32_t* pMajorVersion, int32_t* pMinorVersion,
long* pBugVersion, const char** ppBuildDate, int32_t* pBugVersion, const char** ppBuildDate,
const char** ppBuildFlags); const char** ppBuildFlags);
NUFXLIB_API const char* NuStrError(NuError err); NUFXLIB_API const char* NuStrError(NuError err);
NUFXLIB_API NuError NuTestFeature(NuFeature feature); NUFXLIB_API NuError NuTestFeature(NuFeature feature);
@ -813,12 +851,17 @@ NUFXLIB_API void NuRecordCopyAttr(NuRecordAttr* pRecordAttr,
NUFXLIB_API NuError NuRecordCopyThreads(const NuRecord* pRecord, NUFXLIB_API NuError NuRecordCopyThreads(const NuRecord* pRecord,
NuThread** ppThreads); NuThread** ppThreads);
NUFXLIB_API uint32_t NuRecordGetNumThreads(const NuRecord* pRecord); NUFXLIB_API uint32_t NuRecordGetNumThreads(const NuRecord* pRecord);
NUFXLIB_API const NuThread* NuThreadGetByIdx(const NuThread* pThread, long idx); NUFXLIB_API const NuThread* NuThreadGetByIdx(const NuThread* pThread,
int32_t idx);
NUFXLIB_API short NuIsPresizedThreadID(NuThreadID threadID); NUFXLIB_API short NuIsPresizedThreadID(NuThreadID threadID);
NUFXLIB_API size_t NuConvertMORToUNI(const char* stringMOR,
UNICHAR* bufUNI, size_t bufSize);
NUFXLIB_API size_t NuConvertUNIToMOR(const UNICHAR* stringUNI,
char* bufMOR, size_t bufSize);
#define NuGetThread(pRecord, idx) ( (const NuThread*) \ #define NuGetThread(pRecord, idx) ( (const NuThread*) \
((uint32_t) (idx) < (uint32_t) (pRecord)->recTotalThreads ? \ ((uint32_t) (idx) < (pRecord)->recTotalThreads ? \
&(pRecord)->pThreads[(idx)] : NULL) \ &(pRecord)->pThreads[(idx)] : NULL) \
) )

View File

@ -100,7 +100,7 @@ struct NuArchive {
NuOpenMode openMode; NuOpenMode openMode;
Boolean newlyCreated; Boolean newlyCreated;
char* archivePathname; /* pathname or "(stream)" */ UNICHAR* archivePathnameUNI; /* pathname or "(stream)" */
FILE* archiveFp; FILE* archiveFp;
NuArchiveType archiveType; NuArchiveType archiveType;
@ -108,7 +108,7 @@ struct NuArchive {
long junkOffset; /* skip past leading junk */ long junkOffset; /* skip past leading junk */
long headerOffset; /* adjustment for BXY/SEA/BSE */ long headerOffset; /* adjustment for BXY/SEA/BSE */
char* tmpPathname; /* temp file, for writes */ UNICHAR* tmpPathnameUNI; /* temp file, for writes */
FILE* tmpFp; FILE* tmpFp;
/* used during initial processing; helps avoid ftell() calls */ /* used during initial processing; helps avoid ftell() calls */
@ -118,9 +118,9 @@ struct NuArchive {
Boolean testMode; Boolean testMode;
/* clumsy way of remembering name used for other fork in forked file */ /* clumsy way of remembering name used for other fork in forked file */
const char* lastFileCreated; const UNICHAR* lastFileCreatedUNI;
/* clumsy way to avoid trying to create the same subdir several times */ /* clumsy way to avoid trying to create the same subdir several times */
const char* lastDirCreated; const UNICHAR* lastDirCreatedUNI;
/* master header from the archive */ /* master header from the archive */
NuMasterHeader masterHeader; /* original */ NuMasterHeader masterHeader; /* original */
@ -169,7 +169,7 @@ struct NuArchive {
#define kNuArchiveStructMagic 0xc0edbabe #define kNuArchiveStructMagic 0xc0edbabe
#define kNuDefaultRecordName "UNKNOWN" #define kNuDefaultRecordName "UNKNOWN" /* use ASCII charset */
/* /*
@ -343,7 +343,7 @@ union NuDataSource {
struct { struct {
NuDataSourceCommon common; NuDataSourceCommon common;
char* pathname; UNICHAR* pathnameUNI;
Boolean fromRsrcFork; Boolean fromRsrcFork;
/* temp storage; only valid when processing in library */ /* temp storage; only valid when processing in library */
@ -397,8 +397,8 @@ union NuDataSink {
struct { struct {
NuDataSinkCommon common; NuDataSinkCommon common;
char* pathname; /* file to open */ UNICHAR* pathnameUNI; /* file to open */
char fssep; UNICHAR fssep;
/* temp storage; must be NULL except when processing in library */ /* temp storage; must be NULL except when processing in library */
FILE* fp; FILE* fp;
@ -469,13 +469,13 @@ union NuDataSink {
goto bail; \ goto bail; \
} }
#define BailNil(val) { \ #define BailNil(val) { \
if ((val) == NULL) { \ if ((val) == NULL) { \
err = kNuErrUnexpectedNil; \ err = kNuErrUnexpectedNil; \
BailError(err); \ BailError(err); \
} \ } \
} }
#define BailAlloc(val) { \ #define BailAlloc(val) { \
if ((val) == NULL) { \ if ((val) == NULL) { \
err = kNuErrMalloc; \ err = kNuErrMalloc; \
BailError(err); \ BailError(err); \
} \ } \
@ -498,9 +498,9 @@ NuError Nu_UpdateWrapper(NuArchive* pArchive, FILE* fp);
NuError Nu_AdjustWrapperPadding(NuArchive* pArchive, FILE* fp); NuError Nu_AdjustWrapperPadding(NuArchive* pArchive, FILE* fp);
NuError Nu_AllocCompressionBufferIFN(NuArchive* pArchive); NuError Nu_AllocCompressionBufferIFN(NuArchive* pArchive);
NuError Nu_StreamOpenRO(FILE* infp, NuArchive** ppArchive); NuError Nu_StreamOpenRO(FILE* infp, NuArchive** ppArchive);
NuError Nu_OpenRO(const char* filename, NuArchive** ppArchive); NuError Nu_OpenRO(const UNICHAR* archivePathnameUNI, NuArchive** ppArchive);
NuError Nu_OpenRW(const char* archivePathname, const char* tempPathname, NuError Nu_OpenRW(const UNICHAR* archivePathnameUNI,
uint32_t flags, NuArchive** ppArchive); const UNICHAR* tempPathnameUNI, uint32_t flags, NuArchive** ppArchive);
NuError Nu_WriteMasterHeader(NuArchive* pArchive, FILE* fp, NuError Nu_WriteMasterHeader(NuArchive* pArchive, FILE* fp,
NuMasterHeader* pMasterHeader); NuMasterHeader* pMasterHeader);
NuError Nu_Close(NuArchive* pArchive); NuError Nu_Close(NuArchive* pArchive);
@ -544,6 +544,13 @@ NuError Nu_CompressBzip2(NuArchive* pArchive, NuStraw* pStraw, FILE* fp,
NuError Nu_ExpandBzip2(NuArchive* pArchive, const NuRecord* pRecord, NuError Nu_ExpandBzip2(NuArchive* pArchive, const NuRecord* pRecord,
const NuThread* pThread, FILE* infp, NuFunnel* pFunnel, uint16_t* pCrc); 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 */ /* Compress.c */
NuError Nu_CompressToArchive(NuArchive* pArchive, NuDataSource* pDataSource, NuError Nu_CompressToArchive(NuArchive* pArchive, NuDataSource* pDataSource,
NuThreadID threadID, NuThreadFormat sourceFormat, NuThreadID threadID, NuThreadFormat sourceFormat,
@ -556,12 +563,12 @@ NuError Nu_CopyPresizedToArchive(NuArchive* pArchive,
/* Crc16.c */ /* Crc16.c */
extern const uint16_t gNuCrc16Table[256]; extern const uint16_t gNuCrc16Table[256];
uint16_t Nu_CalcCRC16(uint16_t seed, const uint8_t* ptr, int count); uint16_t Nu_CalcCRC16(uint16_t seed, const uint8_t* ptr, int count);
#ifdef __Crc16_c__ /* just doing "static inline" warns def-but-not-used */ #ifdef COMPILE_CRC16_C /* just doing "static inline" warns def-but-not-used */
#define CRC_INLINE /**/ #define CRC_INLINE /**/
#else #else
#define CRC_INLINE extern inline #define CRC_INLINE extern inline
#endif #endif
#if defined(inline) && !defined(__Crc16_c__) /* somebody ovrd inline def? */ #if defined(inline) && !defined(COMPILE_CRC16_C) /* somebody ovrd inline def? */
uint16_t Nu_UpdateCRC16(uint8_t val, uint16_t crc); uint16_t Nu_UpdateCRC16(uint8_t val, uint16_t crc);
#else #else
CRC_INLINE uint16_t CRC_INLINE uint16_t
@ -591,7 +598,7 @@ NuError Nu_ThreadModAdd_FindByThreadID(const NuRecord* pRecord,
void Nu_FreeThreadMods(NuArchive* pArchive, NuRecord* pRecord); void Nu_FreeThreadMods(NuArchive* pArchive, NuRecord* pRecord);
NuThreadMod* Nu_ThreadMod_FindByThreadIdx(const NuRecord* pRecord, NuThreadMod* Nu_ThreadMod_FindByThreadIdx(const NuRecord* pRecord,
NuThreadIdx threadIdx); NuThreadIdx threadIdx);
NuError Nu_Flush(NuArchive* pArchive, long* pStatusFlags); NuError Nu_Flush(NuArchive* pArchive, uint32_t* pStatusFlags);
/* Deflate.c */ /* Deflate.c */
NuError Nu_CompressDeflate(NuArchive* pArchive, NuStraw* pStraw, FILE* fp, NuError Nu_CompressDeflate(NuArchive* pArchive, NuStraw* pStraw, FILE* fp,
@ -607,14 +614,14 @@ NuError Nu_ExpandStream(NuArchive* pArchive, const NuRecord* pRecord,
void Nu_SetCurrentDateTime(NuDateTime* pDateTime); void Nu_SetCurrentDateTime(NuDateTime* pDateTime);
Boolean Nu_IsOlder(const NuDateTime* pWhen1, const NuDateTime* pWhen2); Boolean Nu_IsOlder(const NuDateTime* pWhen1, const NuDateTime* pWhen2);
NuError Nu_OpenOutputFile(NuArchive* pArchive, const NuRecord* pRecord, NuError Nu_OpenOutputFile(NuArchive* pArchive, const NuRecord* pRecord,
const NuThread* pThread, const char* newPathname, char newFssep, const NuThread* pThread, const UNICHAR* newPathnameUNI, UNICHAR newFssep,
FILE** pFp); FILE** pFp);
NuError Nu_CloseOutputFile(NuArchive* pArchive, const NuRecord* pRecord, NuError Nu_CloseOutputFile(NuArchive* pArchive, const NuRecord* pRecord,
FILE* fp, const char* pathname); FILE* fp, const UNICHAR* pathnameUNI);
NuError Nu_OpenInputFile(NuArchive* pArchive, const char* pathname, NuError Nu_OpenInputFile(NuArchive* pArchive, const UNICHAR* pathnameUNI,
Boolean openRsrc, FILE** pFp); Boolean openRsrc, FILE** pFp);
NuError Nu_DeleteFile(const char* pathname); NuError Nu_DeleteFile(const UNICHAR* pathnameUNI);
NuError Nu_RenameFile(const char* fromPath, const char* toPath); NuError Nu_RenameFile(const UNICHAR* fromPathUNI, const UNICHAR* toPathUNI);
NuError Nu_FTell(FILE* fp, long* pOffset); NuError Nu_FTell(FILE* fp, long* pOffset);
NuError Nu_FSeek(FILE* fp, long offset, int ptrname); NuError Nu_FSeek(FILE* fp, long offset, int ptrname);
NuError Nu_FRead(FILE* fp, void* buf, size_t nbyte); NuError Nu_FRead(FILE* fp, void* buf, size_t nbyte);
@ -627,10 +634,11 @@ NuError Nu_TruncateOpenFile(FILE* fp, long length);
/* Funnel.c */ /* Funnel.c */
NuError Nu_ProgressDataInit_Compress(NuArchive* pArchive, NuError Nu_ProgressDataInit_Compress(NuArchive* pArchive,
NuProgressData* pProgressData, const NuRecord* pRecord, NuProgressData* pProgressData, const NuRecord* pRecord,
const char* origPathname); const UNICHAR* origPathnameUNI, const UNICHAR* pathnameUNI);
NuError Nu_ProgressDataInit_Expand(NuArchive* pArchive, NuError Nu_ProgressDataInit_Expand(NuArchive* pArchive,
NuProgressData* pProgressData, const NuRecord* pRecord, NuProgressData* pProgressData, const NuRecord* pRecord,
const char* newPathname, char newFssep, NuValue convertEOL); const UNICHAR* newPathnameUNI, UNICHAR newFssep,
const UNICHAR* origPathnameUNI, NuValue convertEOL);
NuError Nu_SendInitialProgress(NuArchive* pArchive, NuProgressData* pProgress); NuError Nu_SendInitialProgress(NuArchive* pArchive, NuProgressData* pProgress);
NuError Nu_FunnelNew(NuArchive* pArchive, NuDataSink* pDataSink, NuError Nu_FunnelNew(NuArchive* pArchive, NuDataSink* pDataSink,
@ -680,7 +688,8 @@ NuError Nu_ExpandLZW(NuArchive* pArchive, const NuRecord* pRecord,
extern NuCallback gNuGlobalErrorMessageHandler; extern NuCallback gNuGlobalErrorMessageHandler;
const char* Nu_StrError(NuError err); const char* Nu_StrError(NuError err);
void Nu_ReportError(NuArchive* pArchive, const char* file, int line, void Nu_ReportError(NuArchive* pArchive, const char* file, int line,
const char* function, Boolean isDebug, NuError err, const char* format, ...) const char* function, Boolean isDebug, NuError err,
const UNICHAR* format, ...)
#if defined(__GNUC__) #if defined(__GNUC__)
__attribute__ ((format(printf, 7, 8))) __attribute__ ((format(printf, 7, 8)))
#endif #endif
@ -739,19 +748,19 @@ NuError Nu_Test(NuArchive* pArchive);
NuError Nu_TestRecord(NuArchive* pArchive, NuRecordIdx recIdx); NuError Nu_TestRecord(NuArchive* pArchive, NuRecordIdx recIdx);
NuError Nu_GetRecord(NuArchive* pArchive, NuRecordIdx recordIdx, NuError Nu_GetRecord(NuArchive* pArchive, NuRecordIdx recordIdx,
const NuRecord** ppRecord); const NuRecord** ppRecord);
NuError Nu_GetRecordIdxByName(NuArchive* pArchive, const char* name, NuError Nu_GetRecordIdxByName(NuArchive* pArchive, const char* nameMOR,
NuRecordIdx* pRecordIdx); NuRecordIdx* pRecordIdx);
NuError Nu_GetRecordIdxByPosition(NuArchive* pArchive, uint32_t position, NuError Nu_GetRecordIdxByPosition(NuArchive* pArchive, uint32_t position,
NuRecordIdx* pRecordIdx); NuRecordIdx* pRecordIdx);
NuError Nu_FindRecordForWriteByIdx(NuArchive* pArchive, NuRecordIdx recIdx, NuError Nu_FindRecordForWriteByIdx(NuArchive* pArchive, NuRecordIdx recIdx,
NuRecord** ppFoundRecord); NuRecord** ppFoundRecord);
NuError Nu_AddFile(NuArchive* pArchive, const char* pathname, NuError Nu_AddFile(NuArchive* pArchive, const UNICHAR* pathnameUNI,
const NuFileDetails* pFileDetails, Boolean fromRsrcFork, const NuFileDetails* pFileDetails, Boolean fromRsrcFork,
NuRecordIdx* pRecordIdx); NuRecordIdx* pRecordIdx);
NuError Nu_AddRecord(NuArchive* pArchive, const NuFileDetails* pFileDetails, NuError Nu_AddRecord(NuArchive* pArchive, const NuFileDetails* pFileDetails,
NuRecordIdx* pRecordIdx, NuRecord** ppRecord); NuRecordIdx* pRecordIdx, NuRecord** ppRecord);
NuError Nu_Rename(NuArchive* pArchive, NuRecordIdx recIdx, NuError Nu_Rename(NuArchive* pArchive, NuRecordIdx recIdx,
const char* pathname, char fssep); const char* pathnameMOR, char fssepMOR);
NuError Nu_SetRecordAttr(NuArchive* pArchive, NuRecordIdx recordIdx, NuError Nu_SetRecordAttr(NuArchive* pArchive, NuRecordIdx recordIdx,
const NuRecordAttr* pRecordAttr); const NuRecordAttr* pRecordAttr);
NuError Nu_Delete(NuArchive* pArchive); NuError Nu_Delete(NuArchive* pArchive);
@ -759,7 +768,7 @@ NuError Nu_DeleteRecord(NuArchive* pArchive, NuRecordIdx rec);
/* SourceSink.c */ /* SourceSink.c */
NuError Nu_DataSourceFile_New(NuThreadFormat threadFormat, NuError Nu_DataSourceFile_New(NuThreadFormat threadFormat,
uint32_t otherLen, const char* pathname, Boolean isFromRsrcFork, uint32_t otherLen, const UNICHAR* pathnameUNI, Boolean isFromRsrcFork,
NuDataSource** ppDataSource); NuDataSource** ppDataSource);
NuError Nu_DataSourceFP_New(NuThreadFormat threadFormat, NuError Nu_DataSourceFP_New(NuThreadFormat threadFormat,
uint32_t otherLen, FILE* fp, long offset, long length, uint32_t otherLen, FILE* fp, long offset, long length,
@ -785,7 +794,7 @@ NuError Nu_DataSourceGetBlock(NuDataSource* pDataSource, uint8_t* buf,
uint32_t len); uint32_t len);
NuError Nu_DataSourceRewind(NuDataSource* pDataSource); NuError Nu_DataSourceRewind(NuDataSource* pDataSource);
NuError Nu_DataSinkFile_New(Boolean doExpand, NuValue convertEOL, NuError Nu_DataSinkFile_New(Boolean doExpand, NuValue convertEOL,
const char* pathname, char fssep, NuDataSink** ppDataSink); const UNICHAR* pathnameUNI, UNICHAR fssep, NuDataSink** ppDataSink);
NuError Nu_DataSinkFP_New(Boolean doExpand, NuValue convertEOL, FILE* fp, NuError Nu_DataSinkFP_New(Boolean doExpand, NuValue convertEOL, FILE* fp,
NuDataSink** ppDataSink); NuDataSink** ppDataSink);
NuError Nu_DataSinkBuffer_New(Boolean doExpand, NuValue convertEOL, NuError Nu_DataSinkBuffer_New(Boolean doExpand, NuValue convertEOL,
@ -798,7 +807,7 @@ Boolean Nu_DataSinkGetDoExpand(const NuDataSink* pDataSink);
NuValue Nu_DataSinkGetConvertEOL(const NuDataSink* pDataSink); NuValue Nu_DataSinkGetConvertEOL(const NuDataSink* pDataSink);
uint32_t Nu_DataSinkGetOutCount(const NuDataSink* pDataSink); uint32_t Nu_DataSinkGetOutCount(const NuDataSink* pDataSink);
const char* Nu_DataSinkFile_GetPathname(const NuDataSink* pDataSink); const char* Nu_DataSinkFile_GetPathname(const NuDataSink* pDataSink);
char Nu_DataSinkFile_GetFssep(const NuDataSink* pDataSink); UNICHAR Nu_DataSinkFile_GetFssep(const NuDataSink* pDataSink);
FILE* Nu_DataSinkFile_GetFP(const NuDataSink* pDataSink); FILE* Nu_DataSinkFile_GetFP(const NuDataSink* pDataSink);
void Nu_DataSinkFile_SetFP(NuDataSink* pDataSink, FILE* fp); void Nu_DataSinkFile_SetFP(NuDataSink* pDataSink, FILE* fp);
void Nu_DataSinkFile_Close(NuDataSink* pDataSink); void Nu_DataSinkFile_Close(NuDataSink* pDataSink);
@ -813,12 +822,12 @@ NuError Nu_ExpandHuffmanSQ(NuArchive* pArchive, const NuRecord* pRecord,
const NuThread* pThread, FILE* infp, NuFunnel* pFunnel, uint16_t* pCrc); const NuThread* pThread, FILE* infp, NuFunnel* pFunnel, uint16_t* pCrc);
/* Thread.c */ /* Thread.c */
#ifdef __Thread_c__ #ifdef COMPILE_THREAD_C
#define THREAD_INLINE /**/ #define THREAD_INLINE /**/
#else #else
#define THREAD_INLINE extern inline #define THREAD_INLINE extern inline
#endif #endif
#if defined(inline) && !defined(__Thread_c__) /* somebody ovrd inline def? */ #if defined(inline) && !defined(COMPILE_THREAD_C) /*somebody ovrd inline def?*/
NuThread* Nu_GetThread(const NuRecord* pRecord, int idx); NuThread* Nu_GetThread(const NuRecord* pRecord, int idx);
#else #else
THREAD_INLINE NuThread* THREAD_INLINE NuThread*
@ -833,7 +842,7 @@ Nu_GetThread(const NuRecord* pRecord, int idx)
void Nu_StripHiIfAllSet(char* str); void Nu_StripHiIfAllSet(char* str);
Boolean Nu_IsPresizedThreadID(NuThreadID threadID); Boolean Nu_IsPresizedThreadID(NuThreadID threadID);
Boolean Nu_IsCompressibleThreadID(NuThreadID threadID); Boolean Nu_IsCompressibleThreadID(NuThreadID threadID);
Boolean Nu_ThreadHasCRC(long recordVersion, NuThreadID threadID); Boolean Nu_ThreadHasCRC(uint16_t recordVersion, NuThreadID threadID);
NuError Nu_FindThreadByIdx(const NuRecord* pRecord, NuThreadIdx thread, NuError Nu_FindThreadByIdx(const NuRecord* pRecord, NuThreadIdx thread,
NuThread** ppThread); NuThread** ppThread);
NuError Nu_FindThreadByID(const NuRecord* pRecord, NuThreadID threadID, NuError Nu_FindThreadByID(const NuRecord* pRecord, NuThreadID threadID,
@ -856,7 +865,7 @@ NuError Nu_OkayToAddThread(NuArchive* pArchive, const NuRecord* pRecord,
NuError Nu_AddThread(NuArchive* pArchive, NuRecordIdx rec, NuThreadID threadID, NuError Nu_AddThread(NuArchive* pArchive, NuRecordIdx rec, NuThreadID threadID,
NuDataSource* pDataSource, NuThreadIdx* pThreadIdx); NuDataSource* pDataSource, NuThreadIdx* pThreadIdx);
NuError Nu_UpdatePresizedThread(NuArchive* pArchive, NuThreadIdx threadIdx, NuError Nu_UpdatePresizedThread(NuArchive* pArchive, NuThreadIdx threadIdx,
NuDataSource* pDataSource, long* pMaxLen); NuDataSource* pDataSource, int32_t* pMaxLen);
NuError Nu_DeleteThread(NuArchive* pArchive, NuThreadIdx threadIdx); NuError Nu_DeleteThread(NuArchive* pArchive, NuThreadIdx threadIdx);
/* Value.c */ /* Value.c */
@ -867,7 +876,7 @@ NuThreadFormat Nu_ConvertCompressValToFormat(NuArchive* pArchive,
NuValue compValue); NuValue compValue);
/* Version.c */ /* Version.c */
NuError Nu_GetVersion(long* pMajorVersion, long* pMinorVersion, NuError Nu_GetVersion(int32_t* pMajorVersion, int32_t* pMinorVersion,
long* pBugVersion, const char** ppBuildDate, const char** ppBuildFlags); int32_t* pBugVersion, const char** ppBuildDate, const char** ppBuildFlags);
#endif /*NUFXLIB_NUFXLIBPRIV_H*/ #endif /*NUFXLIB_NUFXLIBPRIV_H*/

View File

@ -105,6 +105,13 @@ add the appropriate goodies. (Seems to me you'd always want this on, but
for some reason Solaris makes you take an extra step, so I'm not going to for some reason Solaris makes you take an extra step, so I'm not going to
define it by default.) define it by default.)
Originally, NufxLib / NuLib2 were intended to be usable natively on the
Apple IIgs, so some of the design decisions were influenced by the need
to minimize memory usage (e.g. being able to get a directory listing
without holding the entire directory in memory) and interact with GS/OS
(forked files have a single filename, files have type/auxtype). The IIgs
port was never started.
Legalese Legalese
======== ========

View File

@ -34,9 +34,9 @@ static NuError Nu_InitRecordContents(NuArchive* pArchive, NuRecord* pRecord)
pRecord->recOptionList = NULL; pRecord->recOptionList = NULL;
pRecord->extraBytes = NULL; pRecord->extraBytes = NULL;
pRecord->recFilename = NULL; pRecord->recFilenameMOR = NULL;
pRecord->threadFilename = NULL; pRecord->threadFilenameMOR = NULL;
pRecord->newFilename = NULL; pRecord->newFilenameMOR = NULL;
pRecord->pThreads = NULL; pRecord->pThreads = NULL;
pRecord->pNext = NULL; pRecord->pNext = NULL;
pRecord->pThreadMods = NULL; pRecord->pThreadMods = NULL;
@ -71,9 +71,9 @@ static NuError Nu_FreeRecordContents(NuArchive* pArchive, NuRecord* pRecord)
Nu_Free(pArchive, pRecord->recOptionList); Nu_Free(pArchive, pRecord->recOptionList);
Nu_Free(pArchive, pRecord->extraBytes); Nu_Free(pArchive, pRecord->extraBytes);
Nu_Free(pArchive, pRecord->recFilename); Nu_Free(pArchive, pRecord->recFilenameMOR);
Nu_Free(pArchive, pRecord->threadFilename); Nu_Free(pArchive, pRecord->threadFilenameMOR);
Nu_Free(pArchive, pRecord->newFilename); Nu_Free(pArchive, pRecord->newFilenameMOR);
Nu_Free(pArchive, pRecord->pThreads); Nu_Free(pArchive, pRecord->pThreads);
/* don't Free(pRecord->pNext)! */ /* don't Free(pRecord->pNext)! */
Nu_FreeThreadMods(pArchive, pRecord); Nu_FreeThreadMods(pArchive, pRecord);
@ -143,24 +143,24 @@ static NuError Nu_RecordCopy(NuArchive* pArchive, NuRecord** ppDst,
pSrc->recOptionSize); pSrc->recOptionSize);
CopySizedField(pArchive, &pDst->extraBytes, pSrc->extraBytes, CopySizedField(pArchive, &pDst->extraBytes, pSrc->extraBytes,
pSrc->extraCount); pSrc->extraCount);
CopySizedField(pArchive, &pDst->recFilename, pSrc->recFilename, CopySizedField(pArchive, &pDst->recFilenameMOR, pSrc->recFilenameMOR,
pSrc->recFilenameLength == 0 ? 0 : pSrc->recFilenameLength+1); pSrc->recFilenameLength == 0 ? 0 : pSrc->recFilenameLength+1);
CopySizedField(pArchive, &pDst->threadFilename, pSrc->threadFilename, CopySizedField(pArchive, &pDst->threadFilenameMOR, pSrc->threadFilenameMOR,
pSrc->threadFilename == NULL ? 0 : strlen(pSrc->threadFilename) +1); pSrc->threadFilenameMOR == NULL ? 0 : strlen(pSrc->threadFilenameMOR) +1);
CopySizedField(pArchive, &pDst->newFilename, pSrc->newFilename, CopySizedField(pArchive, &pDst->newFilenameMOR, pSrc->newFilenameMOR,
pSrc->newFilename == NULL ? 0 : strlen(pSrc->newFilename) +1); pSrc->newFilenameMOR == NULL ? 0 : strlen(pSrc->newFilenameMOR) +1);
CopySizedField(pArchive, &pDst->pThreads, pSrc->pThreads, CopySizedField(pArchive, &pDst->pThreads, pSrc->pThreads,
pSrc->recTotalThreads * sizeof(*pDst->pThreads)); pSrc->recTotalThreads * sizeof(*pDst->pThreads));
/* now figure out what the filename is supposed to point at */ /* now figure out what the filename is supposed to point at */
if (pSrc->filename == pSrc->threadFilename) if (pSrc->filenameMOR == pSrc->threadFilenameMOR)
pDst->filename = pDst->threadFilename; pDst->filenameMOR = pDst->threadFilenameMOR;
else if (pSrc->filename == pSrc->recFilename) else if (pSrc->filenameMOR == pSrc->recFilenameMOR)
pDst->filename = pDst->recFilename; pDst->filenameMOR = pDst->recFilenameMOR;
else if (pSrc->filename == pSrc->newFilename) else if (pSrc->filenameMOR == pSrc->newFilenameMOR)
pDst->filename = pDst->newFilename; pDst->filenameMOR = pDst->newFilenameMOR;
else else
pDst->filename = pSrc->filename; /* probably static kDefault value */ pDst->filenameMOR = pSrc->filenameMOR; /* probably static kDefault value */
pDst->pNext = NULL; pDst->pNext = NULL;
@ -629,12 +629,12 @@ NuError Nu_RecordSet_FindByThreadIdx(NuRecordSet* pRecordSet,
* string pointed to by name1 is greater than, equal to, or less than * string pointed to by name1 is greater than, equal to, or less than
* the string pointed to by s2, respectively (i.e. same as strcmp). * the string pointed to by s2, respectively (i.e. same as strcmp).
*/ */
static int Nu_CompareRecordNames(const char* name1, const char* name2) static int Nu_CompareRecordNames(const char* name1MOR, const char* name2MOR)
{ {
#ifdef NU_CASE_SENSITIVE #ifdef NU_CASE_SENSITIVE
return strcmp(name1, name2); return strcmp(name1MOR, name2MOR);
#else #else
return strcasecmp(name1, name2); return strcasecmp(name1MOR, name2MOR);
#endif #endif
} }
@ -643,18 +643,18 @@ static int Nu_CompareRecordNames(const char* name1, const char* name2)
* Find a record in the list by storageName. * Find a record in the list by storageName.
*/ */
static NuError Nu_RecordSet_FindByName(const NuRecordSet* pRecordSet, static NuError Nu_RecordSet_FindByName(const NuRecordSet* pRecordSet,
const char* name, NuRecord** ppRecord) const char* nameMOR, NuRecord** ppRecord)
{ {
NuRecord* pRecord; NuRecord* pRecord;
Assert(pRecordSet != NULL); Assert(pRecordSet != NULL);
Assert(pRecordSet->loaded); Assert(pRecordSet->loaded);
Assert(name != NULL); Assert(nameMOR != NULL);
Assert(ppRecord != NULL); Assert(ppRecord != NULL);
pRecord = pRecordSet->nuRecordHead; pRecord = pRecordSet->nuRecordHead;
while (pRecord != NULL) { while (pRecord != NULL) {
if (Nu_CompareRecordNames(pRecord->filename, name) == 0) { if (Nu_CompareRecordNames(pRecord->filenameMOR, nameMOR) == 0) {
*ppRecord = pRecord; *ppRecord = pRecord;
return kNuErrNone; return kNuErrNone;
} }
@ -674,19 +674,19 @@ static NuError Nu_RecordSet_FindByName(const NuRecordSet* pRecordSet,
* causes a notable reduction in efficiency we'll have to fix this. * causes a notable reduction in efficiency we'll have to fix this.
*/ */
static NuError Nu_RecordSet_ReverseFindByName(const NuRecordSet* pRecordSet, static NuError Nu_RecordSet_ReverseFindByName(const NuRecordSet* pRecordSet,
const char* name, NuRecord** ppRecord) const char* nameMOR, NuRecord** ppRecord)
{ {
NuRecord* pRecord; NuRecord* pRecord;
NuRecord* pFoundRecord = NULL; NuRecord* pFoundRecord = NULL;
Assert(pRecordSet != NULL); Assert(pRecordSet != NULL);
Assert(pRecordSet->loaded); Assert(pRecordSet->loaded);
Assert(name != NULL); Assert(nameMOR != NULL);
Assert(ppRecord != NULL); Assert(ppRecord != NULL);
pRecord = pRecordSet->nuRecordHead; pRecord = pRecordSet->nuRecordHead;
while (pRecord != NULL) { while (pRecord != NULL) {
if (Nu_CompareRecordNames(pRecord->filename, name) == 0) if (Nu_CompareRecordNames(pRecord->filenameMOR, nameMOR) == 0)
pFoundRecord = pRecord; pFoundRecord = pRecord;
pRecord = pRecord->pNext; pRecord = pRecord->pNext;
@ -792,6 +792,7 @@ Boolean Nu_ShouldIgnoreBadCRC(NuArchive* pArchive, const NuRecord* pRecord,
NuErrorStatus errorStatus; NuErrorStatus errorStatus;
NuResult result; NuResult result;
Boolean retval = false; Boolean retval = false;
UNICHAR* pathnameUNI = NULL;
Assert(pArchive->valIgnoreCRC == false); Assert(pArchive->valIgnoreCRC == false);
@ -801,11 +802,12 @@ Boolean Nu_ShouldIgnoreBadCRC(NuArchive* pArchive, const NuRecord* pRecord,
errorStatus.sysErr = 0; errorStatus.sysErr = 0;
errorStatus.message = NULL; errorStatus.message = NULL;
errorStatus.pRecord = pRecord; errorStatus.pRecord = pRecord;
errorStatus.pathname = NULL; errorStatus.pathnameUNI = NULL;
errorStatus.origPathname = NULL; errorStatus.origPathname = NULL;
errorStatus.filenameSeparator = 0; errorStatus.filenameSeparator = 0;
if (pRecord != NULL) { if (pRecord != NULL) {
errorStatus.pathname = pRecord->filename; pathnameUNI = Nu_CopyMORToUNI(pRecord->filenameMOR);
errorStatus.pathnameUNI = pathnameUNI;
errorStatus.filenameSeparator = errorStatus.filenameSeparator =
NuGetSepFromSysInfo(pRecord->recFileSysInfo); NuGetSepFromSysInfo(pRecord->recFileSysInfo);
} }
@ -837,6 +839,7 @@ Boolean Nu_ShouldIgnoreBadCRC(NuArchive* pArchive, const NuRecord* pRecord,
} }
bail: bail:
Nu_Free(pArchive, pathnameUNI);
return retval; return retval;
} }
@ -864,7 +867,7 @@ static NuError Nu_ReadRecordHeader(NuArchive* pArchive, NuRecord* pRecord)
pRecord->recordIdx = Nu_GetNextRecordIdx(pArchive); pRecord->recordIdx = Nu_GetNextRecordIdx(pArchive);
/* points to whichever filename storage we like best */ /* points to whichever filename storage we like best */
pRecord->filename = NULL; pRecord->filenameMOR = NULL;
pRecord->fileOffset = pArchive->currentOffset; pRecord->fileOffset = pArchive->currentOffset;
(void) Nu_ReadBytes(pArchive, fp, pRecord->recNufxID, kNufxIDLen); (void) Nu_ReadBytes(pArchive, fp, pRecord->recNufxID, kNufxIDLen);
@ -994,18 +997,19 @@ static NuError Nu_ReadRecordHeader(NuArchive* pArchive, NuRecord* pRecord)
goto bail; goto bail;
} }
if (pRecord->recFilenameLength) { if (pRecord->recFilenameLength) {
pRecord->recFilename = Nu_Malloc(pArchive, pRecord->recFilenameLength +1); pRecord->recFilenameMOR =
BailAlloc(pRecord->recFilename); Nu_Malloc(pArchive, pRecord->recFilenameLength +1);
(void) Nu_ReadBytesC(pArchive, fp, pRecord->recFilename, BailAlloc(pRecord->recFilenameMOR);
(void) Nu_ReadBytesC(pArchive, fp, pRecord->recFilenameMOR,
pRecord->recFilenameLength, &crc); pRecord->recFilenameLength, &crc);
pRecord->recFilename[pRecord->recFilenameLength] = '\0'; pRecord->recFilenameMOR[pRecord->recFilenameLength] = '\0';
bytesRead += pRecord->recFilenameLength; bytesRead += pRecord->recFilenameLength;
Nu_StripHiIfAllSet(pRecord->recFilename); Nu_StripHiIfAllSet(pRecord->recFilenameMOR);
/* use the in-header one */ /* use the in-header one */
pRecord->filename = pRecord->recFilename; pRecord->filenameMOR = pRecord->recFilenameMOR;
} }
/* /*
@ -1226,7 +1230,7 @@ NuError Nu_WriteRecordHeader(NuArchive* pArchive, NuRecord* pRecord, FILE* fp)
if (pRecord->recFilenameLength && !pRecord->dropRecFilename) { if (pRecord->recFilenameLength && !pRecord->dropRecFilename) {
Nu_WriteTwoC(pArchive, fp, pRecord->recFilenameLength, &crc); Nu_WriteTwoC(pArchive, fp, pRecord->recFilenameLength, &crc);
bytesWritten += 2; bytesWritten += 2;
Nu_WriteBytesC(pArchive, fp, pRecord->recFilename, Nu_WriteBytesC(pArchive, fp, pRecord->recFilenameMOR,
pRecord->recFilenameLength, &crc); pRecord->recFilenameLength, &crc);
} else { } else {
Nu_WriteTwoC(pArchive, fp, 0, &crc); Nu_WriteTwoC(pArchive, fp, 0, &crc);
@ -1343,7 +1347,7 @@ static NuError Nu_RecordWalkGetNext(NuArchive* pArchive, NuRecord** ppRecord)
err = Nu_ScanThreads(pArchive, *ppRecord, (*ppRecord)->recTotalThreads); err = Nu_ScanThreads(pArchive, *ppRecord, (*ppRecord)->recTotalThreads);
BailError(err); BailError(err);
DBUG(("--- Found record '%s'\n", (*ppRecord)->filename)); DBUG(("--- Found record '%s'\n", (*ppRecord)->filenameMOR));
/* add to list */ /* add to list */
err = Nu_RecordSet_AddRecord(&pArchive->origRecordSet, *ppRecord); err = Nu_RecordSet_AddRecord(&pArchive->origRecordSet, *ppRecord);
@ -1525,7 +1529,7 @@ NuError Nu_StreamExtract(NuArchive* pArchive)
long idx; long idx;
/* reset this just to be safe */ /* reset this just to be safe */
pArchive->lastDirCreated = NULL; pArchive->lastDirCreatedUNI = NULL;
Nu_InitRecordContents(pArchive, &tmpRecord); Nu_InitRecordContents(pArchive, &tmpRecord);
count = pArchive->masterHeader.mhTotalRecords; count = pArchive->masterHeader.mhTotalRecords;
@ -1559,7 +1563,7 @@ NuError Nu_StreamExtract(NuArchive* pArchive)
BailError(err); BailError(err);
} else } else
idx = 0; idx = 0;
if (tmpRecord.filename == NULL) { if (tmpRecord.filenameMOR == NULL) {
Nu_ReportError(NU_BLOB, kNuErrNone, Nu_ReportError(NU_BLOB, kNuErrNone,
"Couldn't find filename in record"); "Couldn't find filename in record");
err = kNuErrBadRecord; err = kNuErrBadRecord;
@ -1572,7 +1576,7 @@ NuError Nu_StreamExtract(NuArchive* pArchive)
hasInterestingThread = false; hasInterestingThread = false;
/* extract all relevant (remaining) threads */ /* extract all relevant (remaining) threads */
pArchive->lastFileCreated = NULL; pArchive->lastFileCreatedUNI = NULL;
for ( ; idx < (long)tmpRecord.recTotalThreads; idx++) { for ( ; idx < (long)tmpRecord.recTotalThreads; idx++) {
const NuThread* pThread = Nu_GetThread(&tmpRecord, idx); const NuThread* pThread = Nu_GetThread(&tmpRecord, idx);
@ -1671,7 +1675,7 @@ NuError Nu_Contents(NuArchive* pArchive, NuCallback contentFunc)
err = Nu_RecordWalkGetNext(pArchive, &pRecord); err = Nu_RecordWalkGetNext(pArchive, &pRecord);
BailError(err); BailError(err);
Assert(pRecord->filename != NULL); Assert(pRecord->filenameMOR != NULL);
result = (*contentFunc)(pArchive, pRecord); result = (*contentFunc)(pArchive, pRecord);
if (result == kNuAbort) { if (result == kNuAbort) {
err = kNuErrAborted; err = kNuErrAborted;
@ -1702,7 +1706,7 @@ static NuError Nu_ExtractRecordByPtr(NuArchive* pArchive, NuRecord* pRecord)
/* extract all relevant threads */ /* extract all relevant threads */
hasInterestingThread = false; hasInterestingThread = false;
pArchive->lastFileCreated = 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);
@ -1722,7 +1726,7 @@ static NuError Nu_ExtractRecordByPtr(NuArchive* pArchive, NuRecord* pRecord)
} }
DBUG(("IGNORING 0x%08lx from '%s'\n", DBUG(("IGNORING 0x%08lx from '%s'\n",
NuMakeThreadID(pThread->thThreadClass, pThread->thThreadKind), NuMakeThreadID(pThread->thThreadClass, pThread->thThreadKind),
pRecord->filename)); pRecord->filenameMOR));
} }
} }
@ -1767,7 +1771,7 @@ NuError Nu_Extract(NuArchive* pArchive)
long offset; long offset;
/* reset this just to be safe */ /* reset this just to be safe */
pArchive->lastDirCreated = NULL; pArchive->lastDirCreatedUNI = NULL;
err = Nu_RecordWalkPrepare(pArchive, &pRecord); err = Nu_RecordWalkPrepare(pArchive, &pRecord);
BailError(err); BailError(err);
@ -1905,7 +1909,7 @@ bail:
/* /*
* Find the recordIdx of a record by storage name. * Find the recordIdx of a record by storage name.
*/ */
NuError Nu_GetRecordIdxByName(NuArchive* pArchive, const char* name, NuError Nu_GetRecordIdxByName(NuArchive* pArchive, const char* nameMOR,
NuRecordIdx* pRecordIdx) NuRecordIdx* pRecordIdx)
{ {
NuError err; NuError err;
@ -1919,7 +1923,7 @@ NuError Nu_GetRecordIdxByName(NuArchive* pArchive, const char* name,
err = Nu_GetTOCIfNeeded(pArchive); err = Nu_GetTOCIfNeeded(pArchive);
BailError(err); BailError(err);
err = Nu_RecordSet_FindByName(&pArchive->origRecordSet, name, &pRecord); err = Nu_RecordSet_FindByName(&pArchive->origRecordSet, nameMOR, &pRecord);
if (err == kNuErrNone) { if (err == kNuErrNone) {
Assert(pRecord != NULL); Assert(pRecord != NULL);
*pRecordIdx = pRecord->recordIdx; *pRecordIdx = pRecord->recordIdx;
@ -2078,7 +2082,9 @@ static NuError Nu_HandleAddDuplicateRecord(NuArchive* pArchive,
errorStatus.sysErr = 0; errorStatus.sysErr = 0;
errorStatus.message = NULL; errorStatus.message = NULL;
errorStatus.pRecord = pRecord; errorStatus.pRecord = pRecord;
errorStatus.pathname = pFileDetails->storageName; UNICHAR* pathnameUNI =
Nu_CopyMORToUNI(pFileDetails->storageNameMOR);
errorStatus.pathnameUNI = pathnameUNI;
errorStatus.origPathname = pFileDetails->origName; errorStatus.origPathname = pFileDetails->origName;
errorStatus.filenameSeparator = errorStatus.filenameSeparator =
NuGetSepFromSysInfo(pFileDetails->fileSysInfo); NuGetSepFromSysInfo(pFileDetails->fileSysInfo);
@ -2091,6 +2097,7 @@ static NuError Nu_HandleAddDuplicateRecord(NuArchive* pArchive,
errorStatus.canOverwrite = true; errorStatus.canOverwrite = true;
result = (*pArchive->errorHandlerFunc)(pArchive, &errorStatus); result = (*pArchive->errorHandlerFunc)(pArchive, &errorStatus);
Nu_Free(pArchive, pathnameUNI);
switch (result) { switch (result) {
case kNuAbort: case kNuAbort:
@ -2179,8 +2186,8 @@ NuError Nu_AddRecord(NuArchive* pArchive, const NuFileDetails* pFileDetails,
NuError err; NuError err;
NuRecord* pNewRecord = NULL; NuRecord* pNewRecord = NULL;
if (pFileDetails == NULL || pFileDetails->storageName == NULL || if (pFileDetails == NULL || pFileDetails->storageNameMOR == NULL ||
pFileDetails->storageName[0] == '\0' || pFileDetails->storageNameMOR[0] == '\0' ||
NuGetSepFromSysInfo(pFileDetails->fileSysInfo) == 0) NuGetSepFromSysInfo(pFileDetails->fileSysInfo) == 0)
/* pRecordIdx may be NULL */ /* pRecordIdx may be NULL */
/* ppNewRecord may be NULL */ /* ppNewRecord may be NULL */
@ -2195,7 +2202,7 @@ NuError Nu_AddRecord(NuArchive* pArchive, const NuFileDetails* pFileDetails,
BailError(err); BailError(err);
/* NuFX spec forbids leading fssep chars */ /* NuFX spec forbids leading fssep chars */
if (pFileDetails->storageName[0] == if (pFileDetails->storageNameMOR[0] ==
NuGetSepFromSysInfo(pFileDetails->fileSysInfo)) NuGetSepFromSysInfo(pFileDetails->fileSysInfo))
{ {
err = kNuErrLeadingFssep; err = kNuErrLeadingFssep;
@ -2219,12 +2226,12 @@ NuError Nu_AddRecord(NuArchive* pArchive, const NuFileDetails* pFileDetails,
if (!Nu_RecordSet_GetLoaded(pRecordSet)) if (!Nu_RecordSet_GetLoaded(pRecordSet))
pRecordSet = &pArchive->origRecordSet; pRecordSet = &pArchive->origRecordSet;
Assert(Nu_RecordSet_GetLoaded(pRecordSet)); Assert(Nu_RecordSet_GetLoaded(pRecordSet));
err = Nu_RecordSet_FindByName(pRecordSet, pFileDetails->storageName, err = Nu_RecordSet_FindByName(pRecordSet, pFileDetails->storageNameMOR,
&pFoundRecord); &pFoundRecord);
if (err == kNuErrNone) { if (err == kNuErrNone) {
/* handle the existing record */ /* handle the existing record */
DBUG(("--- Duplicate record found (%06ld) '%s'\n", DBUG(("--- Duplicate record found (%06ld) '%s'\n",
pFoundRecord->recordIdx, pFoundRecord->filename)); pFoundRecord->recordIdx, pFoundRecord->filenameMOR));
err = Nu_HandleAddDuplicateRecord(pArchive, pRecordSet, err = Nu_HandleAddDuplicateRecord(pArchive, pRecordSet,
pFoundRecord, pFileDetails); pFoundRecord, pFileDetails);
if (err != kNuErrNone) { if (err != kNuErrNone) {
@ -2244,7 +2251,7 @@ NuError Nu_AddRecord(NuArchive* pArchive, const NuFileDetails* pFileDetails,
if (Nu_RecordSet_GetLoaded(&pArchive->newRecordSet)) { if (Nu_RecordSet_GetLoaded(&pArchive->newRecordSet)) {
err = Nu_RecordSet_FindByName(&pArchive->newRecordSet, err = Nu_RecordSet_FindByName(&pArchive->newRecordSet,
pFileDetails->storageName, &pFoundRecord); pFileDetails->storageNameMOR, &pFoundRecord);
if (err == kNuErrNone) { if (err == kNuErrNone) {
/* we can't delete from the "new" list, so return an error */ /* we can't delete from the "new" list, so return an error */
err = kNuErrRecordExists; err = kNuErrRecordExists;
@ -2281,9 +2288,9 @@ NuError Nu_AddRecord(NuArchive* pArchive, const NuFileDetails* pFileDetails,
pNewRecord->recFilenameLength = 0; pNewRecord->recFilenameLength = 0;
pNewRecord->recordIdx = Nu_GetNextRecordIdx(pArchive); pNewRecord->recordIdx = Nu_GetNextRecordIdx(pArchive);
pNewRecord->threadFilename = NULL; pNewRecord->threadFilenameMOR = NULL;
pNewRecord->newFilename = strdup(pFileDetails->storageName); pNewRecord->newFilenameMOR = strdup(pFileDetails->storageNameMOR);
pNewRecord->filename = pNewRecord->newFilename; pNewRecord->filenameMOR = pNewRecord->newFilenameMOR;
pNewRecord->recHeaderLength = -1; pNewRecord->recHeaderLength = -1;
pNewRecord->totalCompLength = 0; pNewRecord->totalCompLength = 0;
pNewRecord->fakeThreads = 0; pNewRecord->fakeThreads = 0;
@ -2313,7 +2320,7 @@ bail:
* "add file" thread mod with the same ThreadID. * "add file" thread mod with the same ThreadID.
*/ */
static NuError Nu_AddFileThreadMod(NuArchive* pArchive, NuRecord* pRecord, static NuError Nu_AddFileThreadMod(NuArchive* pArchive, NuRecord* pRecord,
const char* pathname, const NuFileDetails* pFileDetails, const UNICHAR* pathnameUNI, const NuFileDetails* pFileDetails,
Boolean fromRsrcFork) Boolean fromRsrcFork)
{ {
NuError err; NuError err;
@ -2323,7 +2330,7 @@ static NuError Nu_AddFileThreadMod(NuArchive* pArchive, NuRecord* pRecord,
Assert(pArchive != NULL); Assert(pArchive != NULL);
Assert(pRecord != NULL); Assert(pRecord != NULL);
Assert(pathname != NULL); Assert(pathnameUNI != NULL);
Assert(pFileDetails != NULL); Assert(pFileDetails != NULL);
Assert(fromRsrcFork == true || fromRsrcFork == false); Assert(fromRsrcFork == true || fromRsrcFork == false);
@ -2339,7 +2346,7 @@ static NuError Nu_AddFileThreadMod(NuArchive* pArchive, NuRecord* pRecord,
/* create a data source for this file, which is assumed uncompressed */ /* create a data source for this file, which is assumed uncompressed */
err = Nu_DataSourceFile_New(kNuThreadFormatUncompressed, 0, err = Nu_DataSourceFile_New(kNuThreadFormatUncompressed, 0,
pathname, fromRsrcFork, &pDataSource); pathnameUNI, fromRsrcFork, &pDataSource);
BailError(err); BailError(err);
/* create a new ThreadMod */ /* create a new ThreadMod */
@ -2372,7 +2379,7 @@ bail:
* *
* If "pRecordIdx" is non-NULL, it will receive the newly assigned recordID. * If "pRecordIdx" is non-NULL, it will receive the newly assigned recordID.
*/ */
NuError Nu_AddFile(NuArchive* pArchive, const char* pathname, NuError Nu_AddFile(NuArchive* pArchive, const UNICHAR* pathnameUNI,
const NuFileDetails* pFileDetails, Boolean fromRsrcFork, const NuFileDetails* pFileDetails, Boolean fromRsrcFork,
NuRecordIdx* pRecordIdx) NuRecordIdx* pRecordIdx)
{ {
@ -2380,7 +2387,7 @@ NuError Nu_AddFile(NuArchive* pArchive, const char* pathname,
NuRecordIdx recordIdx = 0; NuRecordIdx recordIdx = 0;
NuRecord* pRecord; NuRecord* pRecord;
if (pathname == NULL || pFileDetails == NULL || if (pathnameUNI == NULL || pFileDetails == NULL ||
!(fromRsrcFork == true || fromRsrcFork == false)) !(fromRsrcFork == true || fromRsrcFork == false))
{ {
return kNuErrInvalidArg; return kNuErrInvalidArg;
@ -2391,20 +2398,20 @@ NuError Nu_AddFile(NuArchive* pArchive, const char* pathname,
err = Nu_GetTOCIfNeeded(pArchive); err = Nu_GetTOCIfNeeded(pArchive);
BailError(err); BailError(err);
if (pFileDetails->storageName == NULL) { if (pFileDetails->storageNameMOR == NULL) {
err = kNuErrInvalidArg; err = kNuErrInvalidArg;
Nu_ReportError(NU_BLOB, err, "Must specify storageName"); Nu_ReportError(NU_BLOB, err, "Must specify storageName");
goto bail; goto bail;
} }
if (pFileDetails->storageName[0] == if (pFileDetails->storageNameMOR[0] ==
NuGetSepFromSysInfo(pFileDetails->fileSysInfo)) NuGetSepFromSysInfo(pFileDetails->fileSysInfo))
{ {
err = kNuErrLeadingFssep; err = kNuErrLeadingFssep;
goto bail; goto bail;
} }
DBUG(("+++ ADDING '%s' (%s) 0x%02lx 0x%04lx threadID=0x%08lx\n", pathname, DBUG(("+++ ADDING '%s' (%s) 0x%02lx 0x%04lx threadID=0x%08lx\n",
pFileDetails->storageName, pFileDetails->fileType, pathnameUNI, pFileDetails->storageName, pFileDetails->fileType,
pFileDetails->extraType, pFileDetails->threadID)); pFileDetails->extraType, pFileDetails->threadID));
/* /*
@ -2423,7 +2430,7 @@ NuError Nu_AddFile(NuArchive* pArchive, const char* pathname,
NuRecord* pNewRecord; NuRecord* pNewRecord;
err = Nu_RecordSet_ReverseFindByName(&pArchive->newRecordSet, err = Nu_RecordSet_ReverseFindByName(&pArchive->newRecordSet,
pFileDetails->storageName, &pNewRecord); pFileDetails->storageNameMOR, &pNewRecord);
if (err == kNuErrNone) { if (err == kNuErrNone) {
/* is it okay to add it here? */ /* is it okay to add it here? */
err = Nu_OkayToAddThread(pArchive, pNewRecord, err = Nu_OkayToAddThread(pArchive, pNewRecord,
@ -2433,7 +2440,7 @@ NuError Nu_AddFile(NuArchive* pArchive, const char* pathname,
/* okay to add it to this record */ /* okay to add it to this record */
DBUG((" attaching to existing record %06ld\n", DBUG((" attaching to existing record %06ld\n",
pNewRecord->recordIdx)); pNewRecord->recordIdx));
err = Nu_AddFileThreadMod(pArchive, pNewRecord, pathname, err = Nu_AddFileThreadMod(pArchive, pNewRecord, pathnameUNI,
pFileDetails, fromRsrcFork); pFileDetails, fromRsrcFork);
BailError(err); BailError(err);
recordIdx = pNewRecord->recordIdx; recordIdx = pNewRecord->recordIdx;
@ -2477,7 +2484,7 @@ NuError Nu_AddFile(NuArchive* pArchive, const char* pathname,
/* /*
* Got the record, now add a data file thread. * Got the record, now add a data file thread.
*/ */
err = Nu_AddFileThreadMod(pArchive, pRecord, pathname, pFileDetails, err = Nu_AddFileThreadMod(pArchive, pRecord, pathnameUNI, pFileDetails,
fromRsrcFork); fromRsrcFork);
BailError(err); BailError(err);
@ -2513,8 +2520,8 @@ bail:
* We might also want to screen out trailing fssep chars, though the NuFX * We might also want to screen out trailing fssep chars, though the NuFX
* spec doesn't say they're illegal. * spec doesn't say they're illegal.
*/ */
NuError Nu_Rename(NuArchive* pArchive, NuRecordIdx recIdx, const char* pathname, NuError Nu_Rename(NuArchive* pArchive, NuRecordIdx recIdx,
char fssep) const char* pathnameMOR, char fssepMOR)
{ {
NuError err; NuError err;
NuRecord* pRecord; NuRecord* pRecord;
@ -2525,10 +2532,13 @@ NuError Nu_Rename(NuArchive* pArchive, NuRecordIdx recIdx, const char* pathname,
long requiredCapacity, existingCapacity, newCapacity; long requiredCapacity, existingCapacity, newCapacity;
Boolean doDelete, doAdd, doUpdate; Boolean doDelete, doAdd, doUpdate;
if (recIdx == 0 || pathname == NULL || pathname[0] == '\0' || fssep == '\0') if (recIdx == 0 || pathnameMOR == NULL || pathnameMOR[0] == '\0' ||
fssepMOR == '\0')
{
return kNuErrInvalidArg; return kNuErrInvalidArg;
}
if (pathname[0] == fssep) { if (pathnameMOR[0] == fssepMOR) {
err = kNuErrLeadingFssep; err = kNuErrLeadingFssep;
Nu_ReportError(NU_BLOB, err, "rename path"); Nu_ReportError(NU_BLOB, err, "rename path");
goto bail; goto bail;
@ -2567,7 +2577,7 @@ NuError Nu_Rename(NuArchive* pArchive, NuRecordIdx recIdx, const char* pathname,
*/ */
doDelete = doAdd = doUpdate = false; doDelete = doAdd = doUpdate = false;
newCapacity = existingCapacity = 0; newCapacity = existingCapacity = 0;
requiredCapacity = strlen(pathname); requiredCapacity = strlen(pathnameMOR);
if (pFilenameThread != NULL) { if (pFilenameThread != NULL) {
existingCapacity = pFilenameThread->thCompThreadEOF; existingCapacity = pFilenameThread->thCompThreadEOF;
@ -2595,7 +2605,7 @@ NuError Nu_Rename(NuArchive* pArchive, NuRecordIdx recIdx, const char* pathname,
if (doAdd || doUpdate) { if (doAdd || doUpdate) {
Assert(newCapacity); Assert(newCapacity);
err = Nu_DataSourceBuffer_New(kNuThreadFormatUncompressed, err = Nu_DataSourceBuffer_New(kNuThreadFormatUncompressed,
newCapacity, (const uint8_t*)strdup(pathname), 0, newCapacity, (const uint8_t*)strdup(pathnameMOR), 0,
requiredCapacity /*(strlen)*/, Nu_InternalFreeCallback, requiredCapacity /*(strlen)*/, Nu_InternalFreeCallback,
&pDataSource); &pDataSource);
BailError(err); BailError(err);
@ -2628,17 +2638,17 @@ NuError Nu_Rename(NuArchive* pArchive, NuRecordIdx recIdx, const char* pathname,
} }
DBUG(("--- renaming '%s' to '%s' with delete=%d add=%d update=%d\n", DBUG(("--- renaming '%s' to '%s' with delete=%d add=%d update=%d\n",
pRecord->filename, pathname, doDelete, doAdd, doUpdate)); pRecord->filenameMOR, pathnameMOR, doDelete, doAdd, doUpdate));
/* /*
* Update the fssep, if necessary. (This is slightly silly -- we * Update the fssep, if necessary. (This is slightly silly -- we
* have to rewrite the record header anyway since we're changing * have to rewrite the record header anyway since we're changing
* threads around.) * threads around.)
*/ */
if (NuGetSepFromSysInfo(pRecord->recFileSysInfo) != fssep) { if (NuGetSepFromSysInfo(pRecord->recFileSysInfo) != fssepMOR) {
DBUG(("--- and updating the fssep\n")); DBUG(("--- and updating the fssep\n"));
pRecord->recFileSysInfo = NuSetSepInSysInfo(pRecord->recFileSysInfo, pRecord->recFileSysInfo = NuSetSepInSysInfo(pRecord->recFileSysInfo,
fssep); fssepMOR);
pRecord->dirtyHeader = true; pRecord->dirtyHeader = true;
} }

View File

@ -100,7 +100,7 @@ NuError Nu_DataSourceFree(NuDataSource* pDataSource)
switch (pDataSource->sourceType) { switch (pDataSource->sourceType) {
case kNuDataSourceFromFile: case kNuDataSourceFromFile:
Nu_Free(NULL, pDataSource->fromFile.pathname); Nu_Free(NULL, pDataSource->fromFile.pathnameUNI);
if (pDataSource->fromFile.fp != NULL) { if (pDataSource->fromFile.fp != NULL) {
fclose(pDataSource->fromFile.fp); fclose(pDataSource->fromFile.fp);
pDataSource->fromFile.fp = NULL; pDataSource->fromFile.fp = NULL;
@ -137,11 +137,12 @@ NuError Nu_DataSourceFree(NuDataSource* pDataSource)
* Create a data source for an unopened file. * Create a data source for an unopened file.
*/ */
NuError Nu_DataSourceFile_New(NuThreadFormat threadFormat, uint32_t otherLen, NuError Nu_DataSourceFile_New(NuThreadFormat threadFormat, uint32_t otherLen,
const char* pathname, Boolean isFromRsrcFork, NuDataSource** ppDataSource) const UNICHAR* pathnameUNI, Boolean isFromRsrcFork,
NuDataSource** ppDataSource)
{ {
NuError err; NuError err;
if (pathname == NULL || if (pathnameUNI == NULL ||
!(isFromRsrcFork == true || isFromRsrcFork == false) || !(isFromRsrcFork == true || isFromRsrcFork == false) ||
ppDataSource == NULL) ppDataSource == NULL)
{ {
@ -158,7 +159,7 @@ NuError Nu_DataSourceFile_New(NuThreadFormat threadFormat, uint32_t otherLen,
(*ppDataSource)->common.otherLen = otherLen; (*ppDataSource)->common.otherLen = otherLen;
(*ppDataSource)->common.refCount = 1; (*ppDataSource)->common.refCount = 1;
(*ppDataSource)->fromFile.pathname = strdup(pathname); (*ppDataSource)->fromFile.pathnameUNI = strdup(pathnameUNI);
(*ppDataSource)->fromFile.fromRsrcFork = isFromRsrcFork; (*ppDataSource)->fromFile.fromRsrcFork = isFromRsrcFork;
(*ppDataSource)->fromFile.fp = NULL; /* to be filled in later */ (*ppDataSource)->fromFile.fp = NULL; /* to be filled in later */
@ -359,8 +360,8 @@ NuError Nu_DataSourcePrepareInput(NuArchive* pArchive,
* We're adding from a file on disk. Open it. * We're adding from a file on disk. Open it.
*/ */
err = Nu_OpenInputFile(pArchive, err = Nu_OpenInputFile(pArchive,
pDataSource->fromFile.pathname, pDataSource->fromFile.fromRsrcFork, pDataSource->fromFile.pathnameUNI,
&fileFp); pDataSource->fromFile.fromRsrcFork, &fileFp);
BailError(err); BailError(err);
Assert(fileFp != NULL); Assert(fileFp != NULL);
@ -404,15 +405,15 @@ void Nu_DataSourceUnPrepareInput(NuArchive* pArchive, NuDataSource* pDataSource)
/* /*
* Get the pathname from a "from-file" dataSource. * Get the pathname from a "from-file" dataSource. Returned string is UTF-8.
*/ */
const char* Nu_DataSourceFile_GetPathname(NuDataSource* pDataSource) const char* Nu_DataSourceFile_GetPathname(NuDataSource* pDataSource)
{ {
Assert(pDataSource != NULL); Assert(pDataSource != NULL);
Assert(pDataSource->sourceType == kNuDataSourceFromFile); Assert(pDataSource->sourceType == kNuDataSourceFromFile);
Assert(pDataSource->fromFile.pathname != NULL); Assert(pDataSource->fromFile.pathnameUNI != NULL);
return pDataSource->fromFile.pathname; return pDataSource->fromFile.pathnameUNI;
} }
@ -527,7 +528,7 @@ NuError Nu_DataSinkFree(NuDataSink* pDataSink)
switch (pDataSink->sinkType) { switch (pDataSink->sinkType) {
case kNuDataSinkToFile: case kNuDataSinkToFile:
Nu_DataSinkFile_Close(pDataSink); Nu_DataSinkFile_Close(pDataSink);
Nu_Free(NULL, pDataSink->toFile.pathname); Nu_Free(NULL, pDataSink->toFile.pathnameUNI);
break; break;
case kNuDataSinkToFP: case kNuDataSinkToFP:
break; break;
@ -551,14 +552,14 @@ NuError Nu_DataSinkFree(NuDataSink* pDataSink)
* Create a data sink for an unopened file. * Create a data sink for an unopened file.
*/ */
NuError Nu_DataSinkFile_New(Boolean doExpand, NuValue convertEOL, NuError Nu_DataSinkFile_New(Boolean doExpand, NuValue convertEOL,
const char* pathname, char fssep, NuDataSink** ppDataSink) const UNICHAR* pathnameUNI, UNICHAR fssep, NuDataSink** ppDataSink)
{ {
NuError err; NuError err;
if ((doExpand != true && doExpand != false) || if ((doExpand != true && doExpand != false) ||
(convertEOL != kNuConvertOff && convertEOL != kNuConvertOn && (convertEOL != kNuConvertOff && convertEOL != kNuConvertOn &&
convertEOL != kNuConvertAuto) || convertEOL != kNuConvertAuto) ||
pathname == NULL || pathnameUNI == NULL ||
fssep == 0 || fssep == 0 ||
ppDataSink == NULL) ppDataSink == NULL)
{ {
@ -575,7 +576,7 @@ NuError Nu_DataSinkFile_New(Boolean doExpand, NuValue convertEOL,
else else
(*ppDataSink)->common.convertEOL = kNuConvertOff; (*ppDataSink)->common.convertEOL = kNuConvertOff;
(*ppDataSink)->common.outCount = 0; (*ppDataSink)->common.outCount = 0;
(*ppDataSink)->toFile.pathname = strdup(pathname); (*ppDataSink)->toFile.pathnameUNI = strdup(pathnameUNI);
(*ppDataSink)->toFile.fssep = fssep; (*ppDataSink)->toFile.fssep = fssep;
(*ppDataSink)->toFile.fp = NULL; (*ppDataSink)->toFile.fp = NULL;
@ -717,20 +718,20 @@ uint32_t Nu_DataSinkGetOutCount(const NuDataSink* pDataSink)
/* /*
* Get "pathname" from a to-file sink. * Get "pathname" from a to-file sink. Returned string is UTF-8.
*/ */
const char* Nu_DataSinkFile_GetPathname(const NuDataSink* pDataSink) const char* Nu_DataSinkFile_GetPathname(const NuDataSink* pDataSink)
{ {
Assert(pDataSink != NULL); Assert(pDataSink != NULL);
Assert(pDataSink->sinkType == kNuDataSinkToFile); Assert(pDataSink->sinkType == kNuDataSinkToFile);
return pDataSink->toFile.pathname; return pDataSink->toFile.pathnameUNI;
} }
/* /*
* Get "fssep" from a to-file sink. * Get "fssep" from a to-file sink.
*/ */
char Nu_DataSinkFile_GetFssep(const NuDataSink* pDataSink) UNICHAR Nu_DataSinkFile_GetFssep(const NuDataSink* pDataSink)
{ {
Assert(pDataSink != NULL); Assert(pDataSink != NULL);
Assert(pDataSink->sinkType == kNuDataSinkToFile); Assert(pDataSink->sinkType == kNuDataSinkToFile);

View File

@ -69,6 +69,7 @@
# define HAVE_CHSIZE # define HAVE_CHSIZE
# define snprintf _snprintf # define snprintf _snprintf
# define vsnprintf _vsnprintf # define vsnprintf _vsnprintf
#endif #endif
#ifdef HAVE_MALLOC_H #ifdef HAVE_MALLOC_H

View File

@ -6,7 +6,7 @@
* *
* Thread-level operations. * Thread-level operations.
*/ */
#define __Thread_c__ 1 #define COMPILE_THREAD_C 1
#include "NufxLibPriv.h" #include "NufxLibPriv.h"
@ -69,7 +69,7 @@ Boolean Nu_IsCompressibleThreadID(NuThreadID threadID)
* Decide if the thread has a CRC, based on the record version and the * Decide if the thread has a CRC, based on the record version and the
* threadID. * threadID.
*/ */
Boolean Nu_ThreadHasCRC(long recordVersion, NuThreadID threadID) Boolean Nu_ThreadHasCRC(uint16_t recordVersion, NuThreadID threadID)
{ {
return recordVersion >= 3 && return recordVersion >= 3 &&
NuThreadIDGetClass(threadID) == kNuThreadClassData; NuThreadIDGetClass(threadID) == kNuThreadClassData;
@ -412,7 +412,7 @@ NuError Nu_ScanThreads(NuArchive* pArchive, NuRecord* pRecord, long numThreads)
pThread = pRecord->pThreads; pThread = pRecord->pThreads;
while (numThreads--) { while (numThreads--) {
if (pRecord->threadFilename == NULL && if (pRecord->threadFilenameMOR == NULL &&
NuMakeThreadID(pThread->thThreadClass, pThread->thThreadKind) == NuMakeThreadID(pThread->thThreadClass, pThread->thThreadKind) ==
kNuThreadIDFilename) kNuThreadIDFilename)
{ {
@ -423,12 +423,12 @@ NuError Nu_ScanThreads(NuArchive* pArchive, NuRecord* pRecord, long numThreads)
pThread->thCompThreadEOF); pThread->thCompThreadEOF);
goto bail; goto bail;
} }
pRecord->threadFilename = Nu_Malloc(pArchive, pRecord->threadFilenameMOR = Nu_Malloc(pArchive,
pThread->thCompThreadEOF +1); pThread->thCompThreadEOF +1);
BailAlloc(pRecord->threadFilename); BailAlloc(pRecord->threadFilenameMOR);
/* note there is no CRC on a filename thread */ /* note there is no CRC on a filename thread */
(void) Nu_ReadBytes(pArchive, fp, pRecord->threadFilename, (void) Nu_ReadBytes(pArchive, fp, pRecord->threadFilenameMOR,
pThread->thCompThreadEOF); pThread->thCompThreadEOF);
if ((err = Nu_HeaderIOFailed(pArchive, fp)) != kNuErrNone) { if ((err = Nu_HeaderIOFailed(pArchive, fp)) != kNuErrNone) {
Nu_ReportError(NU_BLOB, err, "Failed reading filename thread"); Nu_ReportError(NU_BLOB, err, "Failed reading filename thread");
@ -436,15 +436,15 @@ NuError Nu_ScanThreads(NuArchive* pArchive, NuRecord* pRecord, long numThreads)
} }
/* null-terminate on the actual len, not the buffer len */ /* null-terminate on the actual len, not the buffer len */
pRecord->threadFilename[pThread->thThreadEOF] = '\0'; pRecord->threadFilenameMOR[pThread->thThreadEOF] = '\0';
Nu_StripHiIfAllSet(pRecord->threadFilename); Nu_StripHiIfAllSet(pRecord->threadFilenameMOR);
/* prefer this one over the record one, but only one should exist */ /* prefer this one over the record one, but only one should exist */
if (pRecord->filename != NULL) { if (pRecord->filenameMOR != NULL) {
DBUG(("--- HEY: got record filename and thread filename\n")); DBUG(("--- HEY: got record filename and thread filename\n"));
} }
pRecord->filename = pRecord->threadFilename; pRecord->filenameMOR = pRecord->threadFilenameMOR;
} else { } else {
/* not a filename (or not first filename), skip past it */ /* not a filename (or not first filename), skip past it */
@ -462,9 +462,9 @@ NuError Nu_ScanThreads(NuArchive* pArchive, NuRecord* pRecord, long numThreads)
* end up with a disk image that had no name attached. This will tend * end up with a disk image that had no name attached. This will tend
* to confuse things, so we go ahead and give it a name. * to confuse things, so we go ahead and give it a name.
*/ */
if (pRecord->filename == NULL) { if (pRecord->filenameMOR == NULL) {
DBUG(("+++ no filename found, using default record name\n")); DBUG(("+++ no filename found, using default record name\n"));
pRecord->filename = kNuDefaultRecordName; pRecord->filenameMOR = kNuDefaultRecordName;
} }
pArchive->currentOffset += pRecord->totalCompLength; pArchive->currentOffset += pRecord->totalCompLength;
@ -573,8 +573,9 @@ static NuError Nu_ExtractThreadCommon(NuArchive* pArchive,
NuProgressData progressData; NuProgressData progressData;
NuProgressData* pProgressData; NuProgressData* pProgressData;
NuDataSink* pOrigDataSink; NuDataSink* pOrigDataSink;
char* newPathStorage = NULL; UNICHAR* newPathStorageUNI = NULL;
const char* newPathname; UNICHAR* recFilenameStorageUNI = NULL;
const UNICHAR* newPathnameUNI;
NuResult result; NuResult result;
uint8_t newFssep; uint8_t newFssep;
Boolean doFreeSink = false; Boolean doFreeSink = false;
@ -619,9 +620,11 @@ static NuError Nu_ExtractThreadCommon(NuArchive* pArchive,
} }
} }
newPathname = NULL; newPathnameUNI = NULL;
newFssep = 0; newFssep = 0;
recFilenameStorageUNI = Nu_CopyMORToUNI(pRecord->filenameMOR);
retry_name: retry_name:
if (Nu_DataSinkGetType(pDataSink) == kNuDataSinkToFile) { if (Nu_DataSinkGetType(pDataSink) == kNuDataSinkToFile) {
/* /*
@ -632,18 +635,18 @@ retry_name:
* Start by resetting everything to defaults, in case this isn't * Start by resetting everything to defaults, in case this isn't
* our first time through the "rename" loop. * our first time through the "rename" loop.
*/ */
newPathname = Nu_DataSinkFile_GetPathname(pDataSink); newPathnameUNI = Nu_DataSinkFile_GetPathname(pDataSink);
newFssep = Nu_DataSinkFile_GetFssep(pDataSink); newFssep = Nu_DataSinkFile_GetFssep(pDataSink);
pDataSink = pOrigDataSink; pDataSink = pOrigDataSink;
/* if they don't have a pathname func defined, we just use default */ /* if they don't have a pathname func defined, we just use default */
if (pArchive->outputPathnameFunc != NULL) { if (pArchive->outputPathnameFunc != NULL) {
pathProposal.pathname = pRecord->filename; pathProposal.pathnameUNI = recFilenameStorageUNI;
pathProposal.filenameSeparator = pathProposal.filenameSeparator =
NuGetSepFromSysInfo(pRecord->recFileSysInfo); NuGetSepFromSysInfo(pRecord->recFileSysInfo);
pathProposal.pRecord = pRecord; pathProposal.pRecord = pRecord;
pathProposal.pThread = pThread; pathProposal.pThread = pThread;
pathProposal.newPathname = NULL; pathProposal.newPathnameUNI = NULL;
pathProposal.newFilenameSeparator = '\0'; pathProposal.newFilenameSeparator = '\0';
/*pathProposal.newStorage = (NuThreadID)-1;*/ /*pathProposal.newStorage = (NuThreadID)-1;*/
pathProposal.newDataSink = NULL; pathProposal.newDataSink = NULL;
@ -658,11 +661,13 @@ retry_name:
} }
/* we don't own this string, so make a copy */ /* we don't own this string, so make a copy */
if (pathProposal.newPathname != NULL) { if (pathProposal.newPathnameUNI != NULL) {
newPathStorage = strdup(pathProposal.newPathname); Nu_Free(pArchive, newPathStorageUNI);
newPathname = newPathStorage; newPathStorageUNI = strdup(pathProposal.newPathnameUNI);
} else newPathnameUNI = newPathStorageUNI;
newPathname = NULL; } else {
newPathnameUNI = NULL;
}
if (pathProposal.newFilenameSeparator != '\0') if (pathProposal.newFilenameSeparator != '\0')
newFssep = pathProposal.newFilenameSeparator; newFssep = pathProposal.newFilenameSeparator;
@ -672,21 +677,22 @@ retry_name:
} }
/* at least one of these must be set */ /* at least one of these must be set */
Assert(!(newPathname == NULL && pathProposal.newDataSink == NULL)); Assert(!(newPathnameUNI == NULL && pathProposal.newDataSink == NULL));
} }
/* /*
* Prepare the progress data if this is a data thread. * Prepare the progress data if this is a data thread.
*/ */
if (newPathname == NULL) { if (newPathnameUNI == NULL) {
/* using a data sink; get the pathname out of the record */ /* using a data sink; get the pathname out of the record */
newPathname = pRecord->filename; newPathnameUNI = recFilenameStorageUNI;
newFssep = NuGetSepFromSysInfo(pRecord->recFileSysInfo); newFssep = NuGetSepFromSysInfo(pRecord->recFileSysInfo);
} }
if (pThread->thThreadClass == kNuThreadClassData) { if (pThread->thThreadClass == kNuThreadClassData) {
pProgressData = &progressData; pProgressData = &progressData;
err = Nu_ProgressDataInit_Expand(pArchive, pProgressData, pRecord, err = Nu_ProgressDataInit_Expand(pArchive, pProgressData, pRecord,
newPathname, newFssep, Nu_DataSinkGetConvertEOL(pOrigDataSink)); newPathnameUNI, newFssep, recFilenameStorageUNI,
Nu_DataSinkGetConvertEOL(pOrigDataSink));
BailError(err); BailError(err);
/* send initial progress so they see the right name if "open" fails */ /* send initial progress so they see the right name if "open" fails */
@ -702,14 +708,14 @@ retry_name:
*/ */
FILE* fileFp = NULL; FILE* fileFp = NULL;
err = Nu_OpenOutputFile(pArchive, pRecord, pThread, newPathname, err = Nu_OpenOutputFile(pArchive, pRecord, pThread, newPathnameUNI,
newFssep, &fileFp); newFssep, &fileFp);
if (err == kNuErrRename) { if (err == kNuErrRename) {
/* they want to rename; the OutputPathname callback handles this */ /* they want to rename; the OutputPathname callback handles this */
Nu_Free(pArchive, newPathStorage); Nu_Free(pArchive, newPathStorageUNI);
newPathStorage = NULL; newPathStorageUNI = NULL;
/* reset these just to be careful */ /* reset these just to be careful */
newPathname = NULL; newPathnameUNI = NULL;
fileFp = NULL; fileFp = NULL;
goto retry_name; goto retry_name;
} else if (err != kNuErrNone) { } else if (err != kNuErrNone) {
@ -739,7 +745,7 @@ retry_name:
* permissions as appropriate. * permissions as appropriate.
*/ */
err = Nu_CloseOutputFile(pArchive, pRecord, err = Nu_CloseOutputFile(pArchive, pRecord,
Nu_DataSinkFile_GetFP(pDataSink), newPathname); Nu_DataSinkFile_GetFP(pDataSink), newPathnameUNI);
Nu_DataSinkFile_SetFP(pDataSink, NULL); Nu_DataSinkFile_SetFP(pDataSink, NULL);
BailError(err); BailError(err);
} }
@ -760,7 +766,8 @@ bail:
if (Nu_DataSinkGetType(pDataSink) == kNuDataSinkToFile) if (Nu_DataSinkGetType(pDataSink) == kNuDataSinkToFile)
Nu_DataSinkFile_Close(pDataSink); Nu_DataSinkFile_Close(pDataSink);
Nu_Free(pArchive, newPathStorage); Nu_Free(pArchive, newPathStorageUNI);
Nu_Free(pArchive, recFilenameStorageUNI);
if (doFreeSink) if (doFreeSink)
Nu_DataSinkFree(pDataSink); Nu_DataSinkFree(pDataSink);
@ -777,6 +784,7 @@ NuError Nu_ExtractThreadBulk(NuArchive* pArchive, const NuRecord* pRecord,
{ {
NuError err; NuError err;
NuDataSink* pDataSink = NULL; NuDataSink* pDataSink = NULL;
UNICHAR* recFilenameStorageUNI = NULL;
NuValue eolConv; NuValue eolConv;
/* /*
@ -792,7 +800,8 @@ NuError Nu_ExtractThreadBulk(NuArchive* pArchive, const NuRecord* pRecord,
eolConv = pArchive->valConvertExtractedEOL; eolConv = pArchive->valConvertExtractedEOL;
if (NuGetThreadID(pThread) == kNuThreadIDDiskImage) if (NuGetThreadID(pThread) == kNuThreadIDDiskImage)
eolConv = kNuConvertOff; eolConv = kNuConvertOff;
err = Nu_DataSinkFile_New(true, eolConv, pRecord->filename, recFilenameStorageUNI = Nu_CopyMORToUNI(pRecord->filenameMOR);
err = Nu_DataSinkFile_New(true, eolConv, recFilenameStorageUNI,
NuGetSepFromSysInfo(pRecord->recFileSysInfo), &pDataSink); NuGetSepFromSysInfo(pRecord->recFileSysInfo), &pDataSink);
BailError(err); BailError(err);
@ -805,6 +814,7 @@ bail:
if (err == kNuErrNone) if (err == kNuErrNone)
err = err2; err = err2;
} }
Nu_Free(pArchive, recFilenameStorageUNI);
return err; return err;
} }
@ -1175,7 +1185,7 @@ bail:
* newly-added threads isn't possible, since they aren't really threads yet. * newly-added threads isn't possible, since they aren't really threads yet.
*/ */
NuError Nu_UpdatePresizedThread(NuArchive* pArchive, NuThreadIdx threadIdx, NuError Nu_UpdatePresizedThread(NuArchive* pArchive, NuThreadIdx threadIdx,
NuDataSource* pDataSource, long* pMaxLen) NuDataSource* pDataSource, int32_t* pMaxLen)
{ {
NuError err; NuError err;
NuThreadMod* pThreadMod = NULL; NuThreadMod* pThreadMod = NULL;

View File

@ -23,8 +23,8 @@ static const char gNuBuildFlags[] = "-";
/* /*
* Return the version number, date built, and build flags. * Return the version number, date built, and build flags.
*/ */
NuError Nu_GetVersion(long* pMajorVersion, long* pMinorVersion, NuError Nu_GetVersion(int32_t* pMajorVersion, int32_t* pMinorVersion,
long* pBugVersion, const char** ppBuildDate, const char** ppBuildFlags) int32_t* pBugVersion, const char** ppBuildDate, const char** ppBuildFlags)
{ {
if (pMajorVersion != NULL) if (pMajorVersion != NULL)
*pMajorVersion = kNuVersionMajor; *pMajorVersion = kNuVersionMajor;

View File

@ -16,6 +16,8 @@ EXPORTS
NuAddThread NuAddThread
NuClose NuClose
NuContents NuContents
NuConvertMORToUNI
NuConvertUNIToMOR
NuCreateDataSinkForBuffer NuCreateDataSinkForBuffer
NuCreateDataSinkForFP NuCreateDataSinkForFP
NuCreateDataSinkForFile NuCreateDataSinkForFile

View File

@ -6,8 +6,8 @@
* *
* Common functions for NuLib tests. * Common functions for NuLib tests.
*/ */
#ifndef __Common__ #ifndef NUFXLIB_SAMPLES_COMMON_H
#define __Common__ #define NUFXLIB_SAMPLES_COMMON_H
#include "SysDefs.h" /* might as well draft off the autoconf */ #include "SysDefs.h" /* might as well draft off the autoconf */
#include "NufxLib.h" #include "NufxLib.h"
@ -63,4 +63,4 @@
# define PATH_SEP '/' # define PATH_SEP '/'
#endif #endif
#endif /*__Common__*/ #endif /*NUFXLIB_SAMPLES_COMMON_H*/

View File

@ -44,8 +44,7 @@ typedef struct ExerciserState {
} ExerciserState; } ExerciserState;
ExerciserState* ExerciserState* ExerciserState_New(void)
ExerciserState_New(void)
{ {
ExerciserState* pExerState; ExerciserState* pExerState;
@ -60,8 +59,7 @@ ExerciserState_New(void)
return pExerState; return pExerState;
} }
void void ExerciserState_Free(ExerciserState* pExerState)
ExerciserState_Free(ExerciserState* pExerState)
{ {
if (pExerState == NULL) if (pExerState == NULL)
return; return;
@ -77,26 +75,24 @@ ExerciserState_Free(ExerciserState* pExerState)
free(pExerState); free(pExerState);
} }
inline NuArchive* inline NuArchive* ExerciserState_GetNuArchive(const ExerciserState* pExerState)
ExerciserState_GetNuArchive(const ExerciserState* pExerState)
{ {
return pExerState->pArchive; return pExerState->pArchive;
} }
inline void inline void ExerciserState_SetNuArchive(ExerciserState* pExerState,
ExerciserState_SetNuArchive(ExerciserState* pExerState, NuArchive* newArchive) NuArchive* newArchive)
{ {
pExerState->pArchive = newArchive; pExerState->pArchive = newArchive;
} }
inline char* inline char* ExerciserState_GetArchivePath(const ExerciserState* pExerState)
ExerciserState_GetArchivePath(const ExerciserState* pExerState)
{ {
return pExerState->archivePath; return pExerState->archivePath;
} }
inline void inline void ExerciserState_SetArchivePath(ExerciserState* pExerState,
ExerciserState_SetArchivePath(ExerciserState* pExerState, char* newPath) char* newPath)
{ {
if (pExerState->archivePath != NULL) if (pExerState->archivePath != NULL)
free(pExerState->archivePath); free(pExerState->archivePath);
@ -115,8 +111,7 @@ ExerciserState_SetArchivePath(ExerciserState* pExerState, char* newPath)
} }
} }
inline const char* inline const char* ExerciserState_GetArchiveFile(const ExerciserState* pExerState)
ExerciserState_GetArchiveFile(const ExerciserState* pExerState)
{ {
if (pExerState->archiveFile == NULL) if (pExerState->archiveFile == NULL)
return "[no archive open]"; return "[no archive open]";
@ -134,8 +129,7 @@ ExerciserState_GetArchiveFile(const ExerciserState* pExerState)
/* /*
* NuContents callback function. Print the contents of an individual record. * NuContents callback function. Print the contents of an individual record.
*/ */
NuResult NuResult PrintEntry(NuArchive* pArchive, void* vpRecord)
PrintEntry(NuArchive* pArchive, void* vpRecord)
{ {
const NuRecord* pRecord = (const NuRecord*) vpRecord; const NuRecord* pRecord = (const NuRecord*) vpRecord;
int idx; int idx;
@ -143,7 +137,7 @@ PrintEntry(NuArchive* pArchive, void* vpRecord)
(void)pArchive; /* shut up, gcc */ (void)pArchive; /* shut up, gcc */
printf("RecordIdx %u: '%s'\n", printf("RecordIdx %u: '%s'\n",
pRecord->recordIdx, pRecord->filename); pRecord->recordIdx, pRecord->filenameMOR);
for (idx = 0; idx < (int) pRecord->recTotalThreads; idx++) { for (idx = 0; idx < (int) pRecord->recTotalThreads; idx++) {
const NuThread* pThread; const NuThread* pThread;
@ -211,8 +205,7 @@ PrintEntry(NuArchive* pArchive, void* vpRecord)
/* /*
* Get a line of input, stripping the '\n' off the end. * Get a line of input, stripping the '\n' off the end.
*/ */
static NuError static NuError GetLine(const char* prompt, char* buffer, int bufferSize)
GetLine(const char* prompt, char* buffer, int bufferSize)
{ {
printf("%s> ", prompt); printf("%s> ", prompt);
fflush(stdout); fflush(stdout);
@ -230,13 +223,12 @@ GetLine(const char* prompt, char* buffer, int bufferSize)
/* /*
* Selection filter for mass "extract" and "delete" operations. * Selection filter for mass "extract" and "delete" operations.
*/ */
NuResult NuResult SelectionFilter(NuArchive* pArchive, void* vselFilt)
SelectionFilter(NuArchive* pArchive, void* vselFilt)
{ {
const NuSelectionProposal* selProposal = (NuSelectionProposal*) vselFilt; const NuSelectionProposal* selProposal = (NuSelectionProposal*) vselFilt;
char buffer[8]; char buffer[8];
printf("%s (N/y)? ", selProposal->pRecord->filename); printf("%s (N/y)? ", selProposal->pRecord->filenameMOR);
fflush(stdout); fflush(stdout);
if (fgets(buffer, sizeof(buffer), stdin) == NULL) if (fgets(buffer, sizeof(buffer), stdin) == NULL)
@ -252,8 +244,7 @@ SelectionFilter(NuArchive* pArchive, void* vselFilt)
/* /*
* General-purpose error handler. * General-purpose error handler.
*/ */
NuResult NuResult ErrorHandler(NuArchive* pArchive, void* vErrorStatus)
ErrorHandler(NuArchive* pArchive, void* vErrorStatus)
{ {
const NuErrorStatus* pErrorStatus = (const NuErrorStatus*) vErrorStatus; const NuErrorStatus* pErrorStatus = (const NuErrorStatus*) vErrorStatus;
char buffer[8]; char buffer[8];
@ -263,7 +254,7 @@ ErrorHandler(NuArchive* pArchive, void* vErrorStatus)
"\tfilename='%s' '%c'(0x%02x)\n", "\tfilename='%s' '%c'(0x%02x)\n",
pErrorStatus->operation, pErrorStatus->err, pErrorStatus->sysErr, pErrorStatus->operation, pErrorStatus->err, pErrorStatus->sysErr,
pErrorStatus->message == NULL ? "(NULL)" : pErrorStatus->message, pErrorStatus->message == NULL ? "(NULL)" : pErrorStatus->message,
pErrorStatus->pathname, pErrorStatus->filenameSeparator, pErrorStatus->pathnameUNI, pErrorStatus->filenameSeparator,
pErrorStatus->filenameSeparator); pErrorStatus->filenameSeparator);
printf("\tValid options are:"); printf("\tValid options are:");
if (pErrorStatus->canAbort) if (pErrorStatus->canAbort)
@ -303,8 +294,7 @@ ErrorHandler(NuArchive* pArchive, void* vErrorStatus)
/* /*
* This gets called when a buffer DataSource is no longer needed. * This gets called when a buffer DataSource is no longer needed.
*/ */
NuResult NuResult FreeCallback(NuArchive* pArchive, void* args)
FreeCallback(NuArchive* pArchive, void* args)
{ {
free(args); free(args);
return kNuOK; return kNuOK;
@ -335,8 +325,7 @@ GenericFunc(ExerciserState* pState, int argc, char** argv)
/* /*
* Do nothing. Useful when the user just hits <return> on a blank line. * Do nothing. Useful when the user just hits <return> on a blank line.
*/ */
static NuError static NuError NothingFunc(ExerciserState* pState, int argc, char** argv)
NothingFunc(ExerciserState* pState, int argc, char** argv)
{ {
(void) pState, (void) argc, (void) argv; /* shut up, gcc */ (void) pState, (void) argc, (void) argv; /* shut up, gcc */
return kNuErrNone; return kNuErrNone;
@ -348,8 +337,7 @@ NothingFunc(ExerciserState* pState, int argc, char** argv)
* Do nothing. This is used as a trigger for quitting the program. In * Do nothing. This is used as a trigger for quitting the program. In
* practice, we catch this earlier, and won't actually call here. * practice, we catch this earlier, and won't actually call here.
*/ */
static NuError static NuError QuitFunc(ExerciserState* pState, int argc, char** argv)
QuitFunc(ExerciserState* pState, int argc, char** argv)
{ {
(void) pState, (void) argc, (void) argv; /* shut up, gcc */ (void) pState, (void) argc, (void) argv; /* shut up, gcc */
assert(0); assert(0);
@ -361,8 +349,7 @@ QuitFunc(ExerciserState* pState, int argc, char** argv)
/* /*
* ab - abort current changes * ab - abort current changes
*/ */
static NuError static NuError AbortFunc(ExerciserState* pState, int argc, char** argv)
AbortFunc(ExerciserState* pState, int argc, char** argv)
{ {
(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);
@ -374,8 +361,7 @@ AbortFunc(ExerciserState* pState, int argc, char** argv)
/* /*
* af - add file to archive * af - add file to archive
*/ */
static NuError static NuError AddFileFunc(ExerciserState* pState, int argc, char** argv)
AddFileFunc(ExerciserState* pState, int argc, char** argv)
{ {
NuFileDetails nuFileDetails; NuFileDetails nuFileDetails;
@ -385,7 +371,7 @@ AddFileFunc(ExerciserState* pState, int argc, char** argv)
memset(&nuFileDetails, 0, sizeof(nuFileDetails)); memset(&nuFileDetails, 0, sizeof(nuFileDetails));
nuFileDetails.threadID = kNuThreadIDDataFork; nuFileDetails.threadID = kNuThreadIDDataFork;
nuFileDetails.storageName = argv[1]; nuFileDetails.storageNameMOR = argv[1];
nuFileDetails.fileSysID = kNuFileSysUnknown; nuFileDetails.fileSysID = kNuFileSysUnknown;
nuFileDetails.fileSysInfo = (short) kFssep; nuFileDetails.fileSysInfo = (short) kFssep;
nuFileDetails.access = kUnlocked; nuFileDetails.access = kUnlocked;
@ -398,8 +384,7 @@ AddFileFunc(ExerciserState* pState, int argc, char** argv)
/* /*
* ar - add an empty record * ar - add an empty record
*/ */
static NuError static NuError AddRecordFunc(ExerciserState* pState, int argc, char** argv)
AddRecordFunc(ExerciserState* pState, int argc, char** argv)
{ {
NuError err; NuError err;
NuRecordIdx recordIdx; NuRecordIdx recordIdx;
@ -411,7 +396,7 @@ AddRecordFunc(ExerciserState* pState, int argc, char** argv)
memset(&nuFileDetails, 0, sizeof(nuFileDetails)); memset(&nuFileDetails, 0, sizeof(nuFileDetails));
nuFileDetails.threadID = 0; /* irrelevant */ nuFileDetails.threadID = 0; /* irrelevant */
nuFileDetails.storageName = argv[1]; nuFileDetails.storageNameMOR = argv[1];
nuFileDetails.fileSysID = kNuFileSysUnknown; nuFileDetails.fileSysID = kNuFileSysUnknown;
nuFileDetails.fileSysInfo = (short) kFssep; nuFileDetails.fileSysInfo = (short) kFssep;
nuFileDetails.access = kUnlocked; nuFileDetails.access = kUnlocked;
@ -427,8 +412,7 @@ AddRecordFunc(ExerciserState* pState, int argc, char** argv)
/* /*
* at - add thread to record * at - add thread to record
*/ */
static NuError static NuError AddThreadFunc(ExerciserState* pState, int argc, char** argv)
AddThreadFunc(ExerciserState* pState, int argc, char** argv)
{ {
NuError err; NuError err;
NuDataSource* pDataSource = NULL; NuDataSource* pDataSource = NULL;
@ -516,8 +500,7 @@ bail:
/* /*
* cl - close archive * cl - close archive
*/ */
static NuError static NuError CloseFunc(ExerciserState* pState, int argc, char** argv)
CloseFunc(ExerciserState* pState, int argc, char** argv)
{ {
NuError err; NuError err;
@ -537,8 +520,7 @@ CloseFunc(ExerciserState* pState, int argc, char** argv)
/* /*
* d - delete all records (selection-filtered) * d - delete all records (selection-filtered)
*/ */
static NuError static NuError DeleteFunc(ExerciserState* pState, int argc, char** argv)
DeleteFunc(ExerciserState* pState, int argc, char** argv)
{ {
(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);
@ -552,8 +534,7 @@ DeleteFunc(ExerciserState* pState, int argc, char** argv)
/* /*
* dr - delete record * dr - delete record
*/ */
static NuError static NuError DeleteRecordFunc(ExerciserState* pState, int argc, char** argv)
DeleteRecordFunc(ExerciserState* pState, int argc, char** argv)
{ {
(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);
@ -566,8 +547,7 @@ DeleteRecordFunc(ExerciserState* pState, int argc, char** argv)
/* /*
* dt - delete thread * dt - delete thread
*/ */
static NuError static NuError DeleteThreadFunc(ExerciserState* pState, int argc, char** argv)
DeleteThreadFunc(ExerciserState* pState, int argc, char** argv)
{ {
(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);
@ -580,8 +560,7 @@ DeleteThreadFunc(ExerciserState* pState, int argc, char** argv)
/* /*
* e - extract all files (selection-filtered) * e - extract all files (selection-filtered)
*/ */
static NuError static NuError ExtractFunc(ExerciserState* pState, int argc, char** argv)
ExtractFunc(ExerciserState* pState, int argc, char** argv)
{ {
(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);
@ -595,8 +574,7 @@ ExtractFunc(ExerciserState* pState, int argc, char** argv)
/* /*
* er - extract record * er - extract record
*/ */
static NuError static NuError ExtractRecordFunc(ExerciserState* pState, int argc, char** argv)
ExtractRecordFunc(ExerciserState* pState, int argc, char** argv)
{ {
(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);
@ -609,8 +587,7 @@ ExtractRecordFunc(ExerciserState* pState, int argc, char** argv)
/* /*
* et - extract thread * et - extract thread
*/ */
static NuError static NuError ExtractThreadFunc(ExerciserState* pState, int argc, char** argv)
ExtractThreadFunc(ExerciserState* pState, int argc, char** argv)
{ {
NuError err; NuError err;
NuDataSink* pDataSink = NULL; NuDataSink* pDataSink = NULL;
@ -638,11 +615,10 @@ bail:
/* /*
* fl - flush changes to archive * fl - flush changes to archive
*/ */
static NuError static NuError FlushFunc(ExerciserState* pState, int argc, char** argv)
FlushFunc(ExerciserState* pState, int argc, char** argv)
{ {
NuError err; NuError err;
long flushStatus; uint32_t flushStatus;
(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);
@ -650,7 +626,7 @@ FlushFunc(ExerciserState* pState, int argc, char** argv)
err = NuFlush(ExerciserState_GetNuArchive(pState), &flushStatus); err = NuFlush(ExerciserState_GetNuArchive(pState), &flushStatus);
if (err != kNuErrNone) if (err != kNuErrNone)
printf("Exerciser: flush failed, status flags=0x%04lx\n", flushStatus); printf("Exerciser: flush failed, status flags=0x%04x\n", flushStatus);
return err; return err;
} }
@ -660,8 +636,7 @@ FlushFunc(ExerciserState* pState, int argc, char** argv)
* Currently takes numeric arguments. We could be nice and accept the * Currently takes numeric arguments. We could be nice and accept the
* things like "IgnoreCRC" for kNuValueIgnoreCRC, but not yet. * things like "IgnoreCRC" for kNuValueIgnoreCRC, but not yet.
*/ */
static NuError static NuError GetValueFunc(ExerciserState* pState, int argc, char** argv)
GetValueFunc(ExerciserState* pState, int argc, char** argv)
{ {
NuError err; NuError err;
NuValue value; NuValue value;
@ -680,8 +655,8 @@ GetValueFunc(ExerciserState* pState, int argc, char** argv)
/* /*
* gmh - get master header * gmh - get master header
*/ */
static NuError static NuError GetMasterHeaderFunc(ExerciserState* pState, int argc,
GetMasterHeaderFunc(ExerciserState* pState, int argc, char** argv) char** argv)
{ {
NuError err; NuError err;
const NuMasterHeader* pMasterHeader; const NuMasterHeader* pMasterHeader;
@ -703,8 +678,7 @@ GetMasterHeaderFunc(ExerciserState* pState, int argc, char** argv)
/* /*
* gr - get record attributes * gr - get record attributes
*/ */
static NuError static NuError GetRecordFunc(ExerciserState* pState, int argc, char** argv)
GetRecordFunc(ExerciserState* pState, int argc, char** argv)
{ {
NuError err; NuError err;
const NuRecord* pRecord; const NuRecord* pRecord;
@ -733,8 +707,8 @@ GetRecordFunc(ExerciserState* pState, int argc, char** argv)
/* /*
* grin - get record idx by name * grin - get record idx by name
*/ */
static NuError static NuError GetRecordIdxByNameFunc(ExerciserState* pState, int argc,
GetRecordIdxByNameFunc(ExerciserState* pState, int argc, char** argv) char** argv)
{ {
NuError err; NuError err;
NuRecordIdx recIdx; NuRecordIdx recIdx;
@ -753,8 +727,8 @@ GetRecordIdxByNameFunc(ExerciserState* pState, int argc, char** argv)
/* /*
* grip - get record idx by position * grip - get record idx by position
*/ */
static NuError static NuError GetRecordIdxByPositionFunc(ExerciserState* pState, int argc,
GetRecordIdxByPositionFunc(ExerciserState* pState, int argc, char** argv) char** argv)
{ {
NuError err; NuError err;
NuRecordIdx recIdx; NuRecordIdx recIdx;
@ -773,8 +747,8 @@ GetRecordIdxByPositionFunc(ExerciserState* pState, int argc, char** argv)
/* /*
* ocrw - open/create read-write * ocrw - open/create read-write
*/ */
static NuError static NuError OpenCreateReadWriteFunc(ExerciserState* pState, int argc,
OpenCreateReadWriteFunc(ExerciserState* pState, int argc, char** argv) char** argv)
{ {
NuError err; NuError err;
NuArchive* pArchive; NuArchive* pArchive;
@ -794,8 +768,7 @@ OpenCreateReadWriteFunc(ExerciserState* pState, int argc, char** argv)
/* /*
* oro - open read-only * oro - open read-only
*/ */
static NuError static NuError OpenReadOnlyFunc(ExerciserState* pState, int argc, char** argv)
OpenReadOnlyFunc(ExerciserState* pState, int argc, char** argv)
{ {
NuError err; NuError err;
NuArchive* pArchive; NuArchive* pArchive;
@ -815,8 +788,8 @@ OpenReadOnlyFunc(ExerciserState* pState, int argc, char** argv)
/* /*
* ors - open streaming read-only * ors - open streaming read-only
*/ */
static NuError static NuError OpenStreamingReadOnlyFunc(ExerciserState* pState, int argc,
OpenStreamingReadOnlyFunc(ExerciserState* pState, int argc, char** argv) char** argv)
{ {
NuError err; NuError err;
NuArchive* pArchive; NuArchive* pArchive;
@ -846,8 +819,7 @@ OpenStreamingReadOnlyFunc(ExerciserState* pState, int argc, char** argv)
/* /*
* orw - open read-write * orw - open read-write
*/ */
static NuError static NuError OpenReadWriteFunc(ExerciserState* pState, int argc, char** argv)
OpenReadWriteFunc(ExerciserState* pState, int argc, char** argv)
{ {
NuError err; NuError err;
NuArchive* pArchive; NuArchive* pArchive;
@ -867,8 +839,7 @@ OpenReadWriteFunc(ExerciserState* pState, int argc, char** argv)
/* /*
* p - print * p - print
*/ */
static NuError static NuError PrintFunc(ExerciserState* pState, int argc, char** argv)
PrintFunc(ExerciserState* pState, int argc, char** argv)
{ {
(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);
@ -880,8 +851,7 @@ PrintFunc(ExerciserState* pState, int argc, char** argv)
/* /*
* pd - print debug * pd - print debug
*/ */
static NuError static NuError PrintDebugFunc(ExerciserState* pState, int argc, char** argv)
PrintDebugFunc(ExerciserState* pState, int argc, char** argv)
{ {
(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);
@ -893,8 +863,7 @@ PrintDebugFunc(ExerciserState* pState, int argc, char** argv)
/* /*
* re - rename record * re - rename record
*/ */
static NuError static NuError RenameFunc(ExerciserState* pState, int argc, char** argv)
RenameFunc(ExerciserState* pState, int argc, char** argv)
{ {
(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);
@ -909,8 +878,8 @@ RenameFunc(ExerciserState* pState, int argc, char** argv)
* *
* Use an error handler callback. * Use an error handler callback.
*/ */
static NuError static NuError SetErrorCallbackFunc(ExerciserState* pState, int argc,
SetErrorCallbackFunc(ExerciserState* pState, int argc, char** argv) char** argv)
{ {
(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);
@ -925,8 +894,7 @@ SetErrorCallbackFunc(ExerciserState* pState, int argc, char** argv)
* *
* Currently takes numeric arguments. * Currently takes numeric arguments.
*/ */
static NuError static NuError SetValueFunc(ExerciserState* pState, int argc, char** argv)
SetValueFunc(ExerciserState* pState, int argc, char** argv)
{ {
(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);
@ -944,8 +912,7 @@ SetValueFunc(ExerciserState* pState, int argc, char** argv)
* rigid notion of how many arguments each function should have, so * rigid notion of how many arguments each function should have, so
* you'd need to list all of them every time. * you'd need to list all of them every time.
*/ */
static NuError static NuError SetRecordAttrFunc(ExerciserState* pState, int argc, char** argv)
SetRecordAttrFunc(ExerciserState* pState, int argc, char** argv)
{ {
NuError err; NuError err;
const NuRecord* pRecord; const NuRecord* pRecord;
@ -971,8 +938,7 @@ SetRecordAttrFunc(ExerciserState* pState, int argc, char** argv)
/* /*
* t - test archive * t - test archive
*/ */
static NuError static NuError TestFunc(ExerciserState* pState, int argc, char** argv)
TestFunc(ExerciserState* pState, int argc, char** argv)
{ {
(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);
@ -984,8 +950,7 @@ TestFunc(ExerciserState* pState, int argc, char** argv)
/* /*
* tr - test record * tr - test record
*/ */
static NuError static NuError TestRecordFunc(ExerciserState* pState, int argc, char** argv)
TestRecordFunc(ExerciserState* pState, int argc, char** argv)
{ {
(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);
@ -998,13 +963,14 @@ TestRecordFunc(ExerciserState* pState, int argc, char** argv)
/* /*
* upt - update pre-sized thread * upt - update pre-sized thread
*/ */
static NuError static NuError UpdatePresizedThreadFunc(ExerciserState* pState, int argc,
UpdatePresizedThreadFunc(ExerciserState* pState, int argc, char** argv) char** argv)
{ {
NuError err; NuError err;
NuDataSource* pDataSource = NULL; NuDataSource* pDataSource = NULL;
char* lineBuf = NULL; char* lineBuf = NULL;
long ourLen, maxLen; long ourLen;
int32_t maxLen;
(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);
@ -1032,7 +998,7 @@ UpdatePresizedThreadFunc(ExerciserState* pState, int argc, char** argv)
err = NuUpdatePresizedThread(ExerciserState_GetNuArchive(pState), err = NuUpdatePresizedThread(ExerciserState_GetNuArchive(pState),
strtol(argv[1], NULL, 0), pDataSource, &maxLen); strtol(argv[1], NULL, 0), pDataSource, &maxLen);
if (err == kNuErrNone) if (err == kNuErrNone)
printf("Exerciser: success; function returned maxLen=%ld\n", maxLen); printf("Exerciser: success; function returned maxLen=%d\n", maxLen);
bail: bail:
NuFreeDataSource(pDataSource); NuFreeDataSource(pDataSource);
@ -1138,8 +1104,7 @@ static const struct {
/* /*
* Display a summary of available commands. * Display a summary of available commands.
*/ */
static NuError static NuError HelpFunc(ExerciserState* pState, int argc, char** argv)
HelpFunc(ExerciserState* pState, int argc, char** argv)
{ {
int i; int i;
@ -1171,9 +1136,8 @@ static const char* kWhitespace = " \t\n";
* "lineBuf" will be mangled. On success, "pFunc", "pArgc", and "pArgv" * "lineBuf" will be mangled. On success, "pFunc", "pArgc", and "pArgv"
* will receive the results. * will receive the results.
*/ */
static NuError static NuError ParseLine(char* lineBuf, ExerciserState* pState,
ParseLine(char* lineBuf, ExerciserState* pState, CommandFunc* pFunc, int* pArgc, CommandFunc* pFunc, int* pArgc, char*** pArgv)
char*** pArgv)
{ {
NuError err = kNuErrSyntax; NuError err = kNuErrSyntax;
char* command; char* command;
@ -1259,12 +1223,10 @@ bail:
} }
/* /*
* Interpret commands, do clever things. * Interpret commands, do clever things.
*/ */
static NuError static NuError CommandLoop(void)
CommandLoop(void)
{ {
NuError err = kNuErrNone; NuError err = kNuErrNone;
ExerciserState* pState = ExerciserState_New(); ExerciserState* pState = ExerciserState_New();
@ -1334,17 +1296,16 @@ CommandLoop(void)
* *
* We don't currently take any arguments, so this is pretty straightforward. * We don't currently take any arguments, so this is pretty straightforward.
*/ */
int int main(void)
main(void)
{ {
NuError result; NuError result;
long majorVersion, minorVersion, bugVersion; int32_t majorVersion, minorVersion, bugVersion;
const char* nufxLibDate; const char* nufxLibDate;
const char* nufxLibFlags; const char* nufxLibFlags;
(void) NuGetVersion(&majorVersion, &minorVersion, &bugVersion, (void) NuGetVersion(&majorVersion, &minorVersion, &bugVersion,
&nufxLibDate, &nufxLibFlags); &nufxLibDate, &nufxLibFlags);
printf("NufxLib exerciser, linked with NufxLib v%ld.%ld.%ld [%s]\n\n", printf("NufxLib exerciser, linked with NufxLib v%d.%d.%d [%s]\n\n",
majorVersion, minorVersion, bugVersion, nufxLibFlags); majorVersion, minorVersion, bugVersion, nufxLibFlags);
printf("Use 'h' or '?' for help, 'q' to quit.\n"); printf("Use 'h' or '?' for help, 'q' to quit.\n");

View File

@ -68,8 +68,7 @@ typedef struct ImgHeader {
/* /*
* Read a two-byte little-endian value. * Read a two-byte little-endian value.
*/ */
void void ReadShortLE(FILE* fp, uint16_t* pBuf)
ReadShortLE(FILE* fp, uint16_t* pBuf)
{ {
*pBuf = getc(fp); *pBuf = getc(fp);
*pBuf += (uint16_t) getc(fp) << 8; *pBuf += (uint16_t) getc(fp) << 8;
@ -78,8 +77,7 @@ ReadShortLE(FILE* fp, uint16_t* pBuf)
/* /*
* Write a two-byte little-endian value. * Write a two-byte little-endian value.
*/ */
void void WriteShortLE(FILE* fp, uint16_t val)
WriteShortLE(FILE* fp, uint16_t val)
{ {
putc(val, fp); putc(val, fp);
putc(val >> 8, fp); putc(val >> 8, fp);
@ -88,8 +86,7 @@ WriteShortLE(FILE* fp, uint16_t val)
/* /*
* Read a four-byte little-endian value. * Read a four-byte little-endian value.
*/ */
void void ReadLongLE(FILE* fp, uint32_t* pBuf)
ReadLongLE(FILE* fp, uint32_t* pBuf)
{ {
*pBuf = getc(fp); *pBuf = getc(fp);
*pBuf += (uint32_t) getc(fp) << 8; *pBuf += (uint32_t) getc(fp) << 8;
@ -100,8 +97,7 @@ ReadLongLE(FILE* fp, uint32_t* pBuf)
/* /*
* Write a four-byte little-endian value. * Write a four-byte little-endian value.
*/ */
void void WriteLongLE(FILE* fp, uint32_t val)
WriteLongLE(FILE* fp, uint32_t val)
{ {
putc(val, fp); putc(val, fp);
putc(val >> 8, fp); putc(val >> 8, fp);
@ -112,8 +108,7 @@ WriteLongLE(FILE* fp, uint32_t val)
/* /*
* Read the header from a 2IMG file. * Read the header from a 2IMG file.
*/ */
int int ReadImgHeader(FILE* fp, ImgHeader* pHeader)
ReadImgHeader(FILE* fp, ImgHeader* pHeader)
{ {
size_t ignored; size_t ignored;
ignored = fread(pHeader->magic, 4, 1, fp); ignored = fread(pHeader->magic, 4, 1, fp);
@ -154,8 +149,7 @@ ReadImgHeader(FILE* fp, ImgHeader* pHeader)
/* /*
* Write the header to a 2IMG file. * Write the header to a 2IMG file.
*/ */
int int WriteImgHeader(FILE* fp, ImgHeader* pHeader)
WriteImgHeader(FILE* fp, ImgHeader* pHeader)
{ {
fwrite(pHeader->magic, 4, 1, fp); fwrite(pHeader->magic, 4, 1, fp);
fwrite(pHeader->creator, 4, 1, fp); fwrite(pHeader->creator, 4, 1, fp);
@ -185,8 +179,7 @@ WriteImgHeader(FILE* fp, ImgHeader* pHeader)
/* /*
* Dump the contents of an ImgHeader. * Dump the contents of an ImgHeader.
*/ */
void void DumpImgHeader(ImgHeader* pHeader)
DumpImgHeader(ImgHeader* pHeader)
{ {
printf("--- header contents:\n"); printf("--- header contents:\n");
printf("\tmagic = '%.4s'\n", pHeader->magic); printf("\tmagic = '%.4s'\n", pHeader->magic);
@ -217,8 +210,7 @@ typedef enum ArchiveKind { kKindUnknown, kKindShk, kKindImg } ArchiveKind;
/* /*
* This gets called when a buffer DataSource is no longer needed. * This gets called when a buffer DataSource is no longer needed.
*/ */
NuResult NuResult FreeCallback(NuArchive* pArchive, void* args)
FreeCallback(NuArchive* pArchive, void* args)
{ {
free(args); free(args);
return kNuOK; return kNuOK;
@ -227,8 +219,7 @@ FreeCallback(NuArchive* pArchive, void* args)
/* /*
* This gets called when an "FP" DataSource is no longer needed. * This gets called when an "FP" DataSource is no longer needed.
*/ */
NuResult NuResult FcloseCallback(NuArchive* pArchive, void* args)
FcloseCallback(NuArchive* pArchive, void* args)
{ {
fclose((FILE*) args); fclose((FILE*) args);
return kNuOK; return kNuOK;
@ -242,8 +233,7 @@ FcloseCallback(NuArchive* pArchive, void* args)
* of NufxLib. We could just as easily not set it and call fclose() * of NufxLib. We could just as easily not set it and call fclose()
* ourselves, because the structure of this program is pretty simple. * ourselves, because the structure of this program is pretty simple.
*/ */
NuError NuError CreateProdosSource(const ImgHeader* pHeader, FILE* fp,
CreateProdosSource(const ImgHeader* pHeader, FILE* fp,
NuDataSource** ppDataSource) NuDataSource** ppDataSource)
{ {
return NuCreateDataSourceForFP(kNuThreadFormatUncompressed, 0, fp, return NuCreateDataSourceForFP(kNuThreadFormatUncompressed, 0, fp,
@ -254,8 +244,7 @@ CreateProdosSource(const ImgHeader* pHeader, FILE* fp,
* Create a data source for a DOS-ordered image. This is a little harder, * Create a data source for a DOS-ordered image. This is a little harder,
* since we have to reorder the blocks into ProDOS ordering for ShrinkIt. * since we have to reorder the blocks into ProDOS ordering for ShrinkIt.
*/ */
NuError NuError CreateDosSource(const ImgHeader* pHeader, FILE* fp,
CreateDosSource(const ImgHeader* pHeader, FILE* fp,
NuDataSource** ppDataSource) NuDataSource** ppDataSource)
{ {
NuError err; NuError err;
@ -338,8 +327,7 @@ bail:
* This requires opening up the 2IMG file, verifying that it's okay, and * This requires opening up the 2IMG file, verifying that it's okay, and
* then creating a new disk image record and thread. * then creating a new disk image record and thread.
*/ */
int int ConvertFromImgToShk(const char* srcName, const char* dstName)
ConvertFromImgToShk(const char* srcName, const char* dstName)
{ {
NuError err; NuError err;
NuArchive* pArchive = NULL; NuArchive* pArchive = NULL;
@ -348,7 +336,7 @@ ConvertFromImgToShk(const char* srcName, const char* dstName)
NuFileDetails fileDetails; NuFileDetails fileDetails;
ImgHeader header; ImgHeader header;
FILE* fp = NULL; FILE* fp = NULL;
long flushStatus; uint32_t flushStatus;
char* storageName = NULL; char* storageName = NULL;
char* cp; char* cp;
@ -410,7 +398,7 @@ ConvertFromImgToShk(const char* srcName, const char* dstName)
/* set up the contents of the NuFX Record */ /* set up the contents of the NuFX Record */
memset(&fileDetails, 0, sizeof(fileDetails)); memset(&fileDetails, 0, sizeof(fileDetails));
fileDetails.storageName = cp; fileDetails.storageNameMOR = cp;
fileDetails.fileSysID = kNuFileSysUnknown; /* DOS? ProDOS? */ fileDetails.fileSysID = kNuFileSysUnknown; /* DOS? ProDOS? */
fileDetails.fileSysInfo = kLocalFssep; fileDetails.fileSysInfo = kLocalFssep;
fileDetails.access = kNuAccessUnlocked; fileDetails.access = kNuAccessUnlocked;
@ -461,7 +449,7 @@ ConvertFromImgToShk(const char* srcName, const char* dstName)
/* nothing happens until we Flush */ /* nothing happens until we Flush */
err = NuFlush(pArchive, &flushStatus); err = NuFlush(pArchive, &flushStatus);
if (err != kNuErrNone) { if (err != kNuErrNone) {
fprintf(stderr, "ERROR: flush failed (err=%d, status=0x%04lx)\n", fprintf(stderr, "ERROR: flush failed (err=%d, status=0x%04x)\n",
err, flushStatus); err, flushStatus);
goto bail; goto bail;
} }
@ -492,8 +480,7 @@ bail:
* This takes a simple-minded approach and assumes that the first record * This takes a simple-minded approach and assumes that the first record
* in the archive has the disk image in it. If it doesn't, we give up. * in the archive has the disk image in it. If it doesn't, we give up.
*/ */
int int ConvertFromShkToImg(const char* srcName, const char* dstName)
ConvertFromShkToImg(const char* srcName, const char* dstName)
{ {
NuError err; NuError err;
NuArchive* pArchive = NULL; NuArchive* pArchive = NULL;
@ -604,8 +591,7 @@ bail:
/* /*
* Figure out what kind of archive this is by looking at the filename. * Figure out what kind of archive this is by looking at the filename.
*/ */
ArchiveKind ArchiveKind DetermineKind(const char* filename)
DetermineKind(const char* filename)
{ {
const char* dot; const char* dot;
@ -626,8 +612,7 @@ DetermineKind(const char* filename)
/* /*
* Figure out what we want to do. * Figure out what we want to do.
*/ */
int int main(int argc, char** argv)
main(int argc, char** argv)
{ {
ArchiveKind kind; ArchiveKind kind;
int cc; int cc;

View File

@ -47,8 +47,7 @@ char gSentRecordWarning = false;
/* /*
* This gets called when a buffer DataSource is no longer needed. * This gets called when a buffer DataSource is no longer needed.
*/ */
NuResult NuResult FreeCallback(NuArchive* pArchive, void* args)
FreeCallback(NuArchive* pArchive, void* args)
{ {
free(args); free(args);
return kNuOK; return kNuOK;
@ -60,8 +59,7 @@ FreeCallback(NuArchive* pArchive, void* args)
* This assumes the library is configured for compression (it defaults * This assumes the library is configured for compression (it defaults
* to LZW/2, so this is a reasonable assumption). * to LZW/2, so this is a reasonable assumption).
*/ */
NuError NuError CopyThreadRecompressed(NuArchive* pInArchive, NuArchive* pOutArchive,
CopyThreadRecompressed(NuArchive* pInArchive, NuArchive* pOutArchive,
long flags, const NuThread* pThread, long newRecordIdx) long flags, const NuThread* pThread, long newRecordIdx)
{ {
NuError err = kNuErrNone; NuError err = kNuErrNone;
@ -174,8 +172,7 @@ bail:
* reliable but extracts a little more than we need on pre-sized * reliable but extracts a little more than we need on pre-sized
* threads (filenames, comments). * threads (filenames, comments).
*/ */
NuError NuError CopyThreadUncompressed(NuArchive* pInArchive, NuArchive* pOutArchive,
CopyThreadUncompressed(NuArchive* pInArchive, NuArchive* pOutArchive,
long flags, const NuThread* pThread, long newRecordIdx) long flags, const NuThread* pThread, long newRecordIdx)
{ {
NuError err = kNuErrNone; NuError err = kNuErrNone;
@ -305,8 +302,7 @@ bail:
* Depending on "flags", this will either copy it raw or uncompress and * Depending on "flags", this will either copy it raw or uncompress and
* recompress. * recompress.
*/ */
NuError NuError CopyThread(NuArchive* pInArchive, NuArchive* pOutArchive, long flags,
CopyThread(NuArchive* pInArchive, NuArchive* pOutArchive, long flags,
const NuThread* pThread, long newRecordIdx) const NuThread* pThread, long newRecordIdx)
{ {
if (flags & kFlagCopyOnly) { if (flags & kFlagCopyOnly) {
@ -327,8 +323,7 @@ CopyThread(NuArchive* pInArchive, NuArchive* pOutArchive, long flags,
* of which will not usually have any effect since NufxLib imposes a * of which will not usually have any effect since NufxLib imposes a
* specific thread ordering on most common types) depending on "flags". * specific thread ordering on most common types) depending on "flags".
*/ */
NuError NuError CopyRecord(NuArchive* pInArchive, NuArchive* pOutArchive, long flags,
CopyRecord(NuArchive* pInArchive, NuArchive* pOutArchive, long flags,
NuRecordIdx recordIdx) NuRecordIdx recordIdx)
{ {
NuError err = kNuErrNone; NuError err = kNuErrNone;
@ -370,7 +365,7 @@ CopyRecord(NuArchive* pInArchive, NuArchive* pOutArchive, long flags,
* Create a new record that looks just like the original. * Create a new record that looks just like the original.
*/ */
memset(&fileDetails, 0, sizeof(fileDetails)); memset(&fileDetails, 0, sizeof(fileDetails));
fileDetails.storageName = pRecord->filename; fileDetails.storageNameMOR = pRecord->filenameMOR;
fileDetails.fileSysID = pRecord->recFileSysID; fileDetails.fileSysID = pRecord->recFileSysID;
fileDetails.fileSysInfo = pRecord->recFileSysInfo; fileDetails.fileSysInfo = pRecord->recFileSysInfo;
fileDetails.access = pRecord->recAccess; fileDetails.access = pRecord->recAccess;
@ -422,16 +417,15 @@ bail:
* *
* Returns 0 on success, nonzero on failure. * Returns 0 on success, nonzero on failure.
*/ */
int int LaunderArchive(const char* inFile, const char* outFile,
LaunderArchive(const char* inFile, const char* outFile, NuValue compressMethod, NuValue compressMethod, long flags)
long flags)
{ {
NuError err = kNuErrNone; NuError err = kNuErrNone;
NuArchive* pInArchive = NULL; NuArchive* pInArchive = NULL;
NuArchive* pOutArchive = NULL; NuArchive* pOutArchive = NULL;
const NuMasterHeader* pMasterHeader; const NuMasterHeader* pMasterHeader;
NuRecordIdx recordIdx; NuRecordIdx recordIdx;
long idx, flushStatus; uint32_t idx, flushStatus;
err = NuOpenRO(inFile, &pInArchive); err = NuOpenRO(inFile, &pInArchive);
if (err != kNuErrNone) { if (err != kNuErrNone) {
@ -487,10 +481,10 @@ LaunderArchive(const char* inFile, const char* outFile, NuValue compressMethod,
/* /*
* Iterate through the set of records. * Iterate through the set of records.
*/ */
for (idx = 0; idx < (int)pMasterHeader->mhTotalRecords; idx++) { for (idx = 0; idx < pMasterHeader->mhTotalRecords; idx++) {
err = NuGetRecordIdxByPosition(pInArchive, idx, &recordIdx); err = NuGetRecordIdxByPosition(pInArchive, idx, &recordIdx);
if (err != kNuErrNone) { if (err != kNuErrNone) {
fprintf(stderr, "ERROR: couldn't get record #%ld (err=%d)\n", fprintf(stderr, "ERROR: couldn't get record #%u (err=%d)\n",
idx, err); idx, err);
goto bail; goto bail;
} }
@ -525,7 +519,7 @@ LaunderArchive(const char* inFile, const char* outFile, NuValue compressMethod,
err = NuFlush(pOutArchive, &flushStatus); err = NuFlush(pOutArchive, &flushStatus);
if (err != kNuErrNone) { if (err != kNuErrNone) {
fprintf(stderr, fprintf(stderr,
"ERROR: flush failed (err=%d, status=0x%04lx)\n", "ERROR: flush failed (err=%d, status=0x%04x)\n",
err, flushStatus); err, flushStatus);
goto bail; goto bail;
} }
@ -535,7 +529,7 @@ LaunderArchive(const char* inFile, const char* outFile, NuValue compressMethod,
/* first and only flush if frequent-flushing wasn't enabled */ /* first and only flush if frequent-flushing wasn't enabled */
err = NuFlush(pOutArchive, &flushStatus); err = NuFlush(pOutArchive, &flushStatus);
if (err != kNuErrNone) { if (err != kNuErrNone) {
fprintf(stderr, "ERROR: flush failed (err=%d, status=0x%04lx)\n", fprintf(stderr, "ERROR: flush failed (err=%d, status=0x%04x)\n",
err, flushStatus); err, flushStatus);
goto bail; goto bail;
} }
@ -563,8 +557,7 @@ char* myoptarg = NULL;
const char* curchar = NULL; const char* curchar = NULL;
int skipnext = false; int skipnext = false;
int int mygetopt(int argc, char** argv, const char* optstr)
mygetopt(int argc, char** argv, const char* optstr)
{ {
if (!myoptind) { if (!myoptind) {
myoptind = 1; myoptind = 1;
@ -609,8 +602,7 @@ mygetopt(int argc, char** argv, const char* optstr)
/* /*
* Print usage info. * Print usage info.
*/ */
void void Usage(const char* argv0)
Usage(const char* argv0)
{ {
fprintf(stderr, "Usage: %s [-crfat] [-m method] infile.shk outfile.shk\n", fprintf(stderr, "Usage: %s [-crfat] [-m method] infile.shk outfile.shk\n",
argv0); argv0);
@ -627,11 +619,10 @@ Usage(const char* argv0)
/* /*
* Grab the name of an archive to read. * Grab the name of an archive to read.
*/ */
int int main(int argc, char** argv)
main(int argc, char** argv)
{ {
NuValue compressMethod = kNuCompressLZW2; NuValue compressMethod = kNuCompressLZW2;
long major, minor, bug; int32_t major, minor, bug;
const char* pBuildDate; const char* pBuildDate;
long flags = 0; long flags = 0;
int errorFlag; int errorFlag;
@ -639,7 +630,7 @@ main(int argc, char** argv)
int cc; int cc;
(void) NuGetVersion(&major, &minor, &bug, &pBuildDate, NULL); (void) NuGetVersion(&major, &minor, &bug, &pBuildDate, NULL);
printf("Using NuFX lib %ld.%ld.%ld built on or after %s\n", printf("Using NuFX lib %d.%d.%d built on or after %s\n",
major, minor, bug, pBuildDate); major, minor, bug, pBuildDate);
errorFlag = false; errorFlag = false;

View File

@ -28,29 +28,12 @@ ALL_SRCS = Exerciser.c ImgConv.c Launder.c TestBasic.c \
NUFXLIB = -L.. -lnufx NUFXLIB = -L.. -lnufx
PRODUCTS = exerciser imgconv launder test-basic test-extract test-simple \ PRODUCTS = exerciser imgconv launder test-basic test-extract test-names \
test-twirl test-simple test-twirl
#ifdef PURIFY_BUILD
# PURIFY = purify
# CFLAGS += -DPURIFY
#endif
#ifdef QUANTIFY_BUILD
# QUANTIFY = quantify
# CFLAGS += -DQUANTIFY
#endif
all: $(PRODUCTS) all: $(PRODUCTS)
@true @true
#quantify:
# -rm -f $(PRODUCT)
# @$(MAKE) QUANTIFY_BUILD=1
#
#purify:
# -rm -f $(PRODUCT)
# @$(MAKE) PURIFY_BUILD=1
exerciser: Exerciser.o $(LIB_PRODUCT) exerciser: Exerciser.o $(LIB_PRODUCT)
$(PURIFY) $(QUANTIFY) $(CC) -o $@ Exerciser.o $(NUFXLIB) @LIBS@ $(PURIFY) $(QUANTIFY) $(CC) -o $@ Exerciser.o $(NUFXLIB) @LIBS@
@ -63,12 +46,15 @@ launder: Launder.o $(LIB_PRODUCT)
test-basic: TestBasic.o $(LIB_PRODUCT) test-basic: TestBasic.o $(LIB_PRODUCT)
$(PURIFY) $(QUANTIFY) $(CC) -o $@ TestBasic.o $(NUFXLIB) @LIBS@ $(PURIFY) $(QUANTIFY) $(CC) -o $@ TestBasic.o $(NUFXLIB) @LIBS@
test-simple: TestSimple.o $(LIB_PRODUCT)
$(PURIFY) $(QUANTIFY) $(CC) -o $@ TestSimple.o $(NUFXLIB) @LIBS@
test-extract: TestExtract.o $(LIB_PRODUCT) test-extract: TestExtract.o $(LIB_PRODUCT)
$(PURIFY) $(QUANTIFY) $(CC) -o $@ TestExtract.o $(NUFXLIB) @LIBS@ $(PURIFY) $(QUANTIFY) $(CC) -o $@ TestExtract.o $(NUFXLIB) @LIBS@
test-names: TestNames.o $(LIB_PRODUCT)
$(PURIFY) $(QUANTIFY) $(CC) -o $@ TestNames.o $(NUFXLIB) @LIBS@
test-simple: TestSimple.o $(LIB_PRODUCT)
$(PURIFY) $(QUANTIFY) $(CC) -o $@ TestSimple.o $(NUFXLIB) @LIBS@
test-twirl: TestTwirl.o $(LIB_PRODUCT) test-twirl: TestTwirl.o $(LIB_PRODUCT)
$(PURIFY) $(QUANTIFY) $(CC) -o $@ TestTwirl.o $(NUFXLIB) @LIBS@ $(PURIFY) $(QUANTIFY) $(CC) -o $@ TestTwirl.o $(NUFXLIB) @LIBS@
@ -84,8 +70,12 @@ distclean: clean
-rm -f tags -rm -f tags
-rm -f Makefile Makefile.bak -rm -f Makefile Makefile.bak
depend: COMMON_HDRS = ../NufxLibPriv.h ../NufxLib.h ../MiscStuff.h ../SysDefs.h
makedepend -- $(CFLAGS) -I/usr/local/include -- $(ALL_SRCS) Exerciser.o: Exerciser.c $(COMMON_HDRS)
ImgConv.o: ImgConv.c $(COMMON_HDRS)
# DO NOT DELETE THIS LINE -- make depend depends on it. Launder.o: Launder.c $(COMMON_HDRS)
TestBasic.o: TestBasic.c $(COMMON_HDRS)
TestExtract.o: TestExtract.c $(COMMON_HDRS)
TestNames.o: TestNames.c $(COMMON_HDRS)
TestSimple.o: TestSimple.c $(COMMON_HDRS)
TestTwirl.o: TestTwirl.c $(COMMON_HDRS)

View File

@ -15,6 +15,8 @@
#define kTestTempFile "nlbt.tmp" #define kTestTempFile "nlbt.tmp"
#define kNumEntries 3 /* how many records are we going to add? */ #define kNumEntries 3 /* how many records are we going to add? */
/* stick to ASCII characters for these -- not doing conversions just yet */
#define kTestEntryBytes "bytes" #define kTestEntryBytes "bytes"
#define kTestEntryBytesUPPER "BYTES" #define kTestEntryBytesUPPER "BYTES"
#define kTestEntryEnglish "English" #define kTestEntryEnglish "English"
@ -39,8 +41,7 @@ char gSuppressError = false;
/* /*
* Get a single character of input from the user. * Get a single character of input from the user.
*/ */
static char static char TGetReplyChar(char defaultReply)
TGetReplyChar(char defaultReply)
{ {
char tmpBuf[32]; char tmpBuf[32];
@ -52,14 +53,13 @@ TGetReplyChar(char defaultReply)
return tmpBuf[0]; return tmpBuf[0];
} }
NuError NuError AddSimpleRecord(NuArchive* pArchive, const char* filenameMOR,
AddSimpleRecord(NuArchive* pArchive, const char* filename,
NuRecordIdx* pRecordIdx) NuRecordIdx* pRecordIdx)
{ {
NuFileDetails fileDetails; NuFileDetails fileDetails;
memset(&fileDetails, 0, sizeof(fileDetails)); memset(&fileDetails, 0, sizeof(fileDetails));
fileDetails.storageName = filename; fileDetails.storageNameMOR = filenameMOR;
fileDetails.fileSysInfo = kLocalFssep; fileDetails.fileSysInfo = kLocalFssep;
fileDetails.access = kNuAccessUnlocked; fileDetails.access = kNuAccessUnlocked;
@ -70,8 +70,7 @@ AddSimpleRecord(NuArchive* pArchive, const char* filename,
/* /*
* Display error messages... or not. * Display error messages... or not.
*/ */
NuResult NuResult ErrorMessageHandler(NuArchive* pArchive, void* vErrorMessage)
ErrorMessageHandler(NuArchive* pArchive, void* vErrorMessage)
{ {
const NuErrorMessage* pErrorMessage = (const NuErrorMessage*) vErrorMessage; const NuErrorMessage* pErrorMessage = (const NuErrorMessage*) vErrorMessage;
@ -95,13 +94,37 @@ ErrorMessageHandler(NuArchive* pArchive, void* vErrorMessage)
/* /*
* This gets called when a buffer DataSource is no longer needed. * This gets called when a buffer DataSource is no longer needed.
*/ */
NuResult NuResult FreeCallback(NuArchive* pArchive, void* args)
FreeCallback(NuArchive* pArchive, void* args)
{ {
free(args); free(args);
return kNuOK; return kNuOK;
} }
/*
* If the test file currently exists, ask the user if it's okay to remove
* it.
*
* Returns 0 if the file was successfully removed, -1 if the file could not
* be removed (because the unlink failed, or the user refused).
*/
int RemoveTestFile(const char* title, const char* fileName)
{
char answer;
if (access(fileName, F_OK) == 0) {
printf("%s '%s' exists, remove (y/n)? ", title, fileName);
fflush(stdout);
answer = TGetReplyChar('n');
if (tolower(answer) != 'y')
return -1;
if (unlink(fileName) < 0) {
perror("unlink");
return -1;
}
}
return 0;
}
/* /*
* =========================================================================== * ===========================================================================
@ -113,8 +136,7 @@ FreeCallback(NuArchive* pArchive, void* args)
* Make sure the flags that control how we open the file work right, * Make sure the flags that control how we open the file work right,
* and verify that we handle existing zero-byte archive files correctly. * and verify that we handle existing zero-byte archive files correctly.
*/ */
int int Test_OpenFlags(void)
Test_OpenFlags(void)
{ {
NuError err; NuError err;
FILE* fp = NULL; FILE* fp = NULL;
@ -170,14 +192,13 @@ failed:
/* /*
* Add some files to the archive. These will be used by later tests. * Add some files to the archive. These will be used by later tests.
*/ */
int int Test_AddStuff(NuArchive* pArchive)
Test_AddStuff(NuArchive* pArchive)
{ {
NuError err; NuError err;
uint8_t* buf = NULL; uint8_t* buf = NULL;
NuDataSource* pDataSource = NULL; NuDataSource* pDataSource = NULL;
NuRecordIdx recordIdx; NuRecordIdx recordIdx;
long status; uint32_t status;
int i; int i;
static const char* testMsg = static const char* testMsg =
"This is a nice test message that has linefeeds in it so we can\n" "This is a nice test message that has linefeeds in it so we can\n"
@ -185,7 +206,7 @@ Test_AddStuff(NuArchive* pArchive)
"all. It's certainly nice to know that everything works the way\n" "all. It's certainly nice to know that everything works the way\n"
"it's supposed to, which I suppose is why we have this nifty test\n" "it's supposed to, which I suppose is why we have this nifty test\n"
"program available. It sure would be nice if everybody tested\n" "program available. It sure would be nice if everybody tested\n"
"there code, but where would Microsoft be without endless upgrades\n" "their code, but where would Microsoft be without endless upgrades\n"
"and service packs? Bugs are what America was built on, and\n" "and service packs? Bugs are what America was built on, and\n"
"anybody who says otherwise is a pinko commie lowlife. Verily.\n"; "anybody who says otherwise is a pinko commie lowlife. Verily.\n";
@ -308,7 +329,7 @@ Test_AddStuff(NuArchive* pArchive)
*/ */
err = NuFlush(pArchive, &status); err = NuFlush(pArchive, &status);
if (err != kNuErrNone) { if (err != kNuErrNone) {
fprintf(stderr,"ERROR: couldn't flush after add (err=%d, status=%ld)\n", fprintf(stderr, "ERROR: couldn't flush after add (err=%d, status=%u)\n",
err, status); err, status);
goto failed; goto failed;
} }
@ -318,7 +339,7 @@ Test_AddStuff(NuArchive* pArchive)
*/ */
err = NuFlush(pArchive, &status); err = NuFlush(pArchive, &status);
if (err != kNuErrNone) { if (err != kNuErrNone) {
fprintf(stderr,"ERROR: second add flush failed (err=%d, status=%ld)\n", fprintf(stderr, "ERROR: second add flush failed (err=%d, status=%u)\n",
err, status); err, status);
goto failed; goto failed;
} }
@ -336,19 +357,18 @@ failed:
/* /*
* Make sure that what we're seeing makes sense. * Make sure that what we're seeing makes sense.
*/ */
NuResult NuResult TestContentsCallback(NuArchive* pArchive, void* vpRecord)
TestContentsCallback(NuArchive* pArchive, void* vpRecord)
{ {
const NuRecord* pRecord = (NuRecord*) vpRecord; const NuRecord* pRecord = (NuRecord*) vpRecord;
if (strcmp(pRecord->filename, kTestEntryBytes) == 0 || if (strcmp(pRecord->filenameMOR, kTestEntryBytes) == 0 ||
strcmp(pRecord->filename, kTestEntryEnglish) == 0 || strcmp(pRecord->filenameMOR, kTestEntryEnglish) == 0 ||
strcmp(pRecord->filename, kTestEntryLong) == 0) strcmp(pRecord->filenameMOR, kTestEntryLong) == 0)
{ {
return kNuOK; return kNuOK;
} }
fprintf(stderr, "ERROR: found mystery entry '%s'\n", pRecord->filename); fprintf(stderr, "ERROR: found mystery entry '%s'\n", pRecord->filenameMOR);
return kNuAbort; return kNuAbort;
} }
@ -356,8 +376,7 @@ TestContentsCallback(NuArchive* pArchive, void* vpRecord)
/* /*
* Verify that the contents look about right. * Verify that the contents look about right.
*/ */
int int Test_Contents(NuArchive* pArchive)
Test_Contents(NuArchive* pArchive)
{ {
NuError err; NuError err;
long posn; long posn;
@ -394,13 +413,13 @@ Test_Contents(NuArchive* pArchive)
switch (posn) { switch (posn) {
case 0: case 0:
cc = strcmp(pRecord->filename, kTestEntryBytes); cc = strcmp(pRecord->filenameMOR, kTestEntryBytes);
break; break;
case 1: case 1:
cc = strcmp(pRecord->filename, kTestEntryEnglish); cc = strcmp(pRecord->filenameMOR, kTestEntryEnglish);
break; break;
case 2: case 2:
cc = strcmp(pRecord->filename, kTestEntryLong); cc = strcmp(pRecord->filenameMOR, kTestEntryLong);
if (!cc) if (!cc)
cc = !(pRecord->recStorageType == kNuStorageExtended); cc = !(pRecord->recStorageType == kNuStorageExtended);
break; break;
@ -412,7 +431,7 @@ Test_Contents(NuArchive* pArchive)
if (cc) { if (cc) {
fprintf(stderr, "ERROR: got '%s' for %ld (%u), not expected\n", fprintf(stderr, "ERROR: got '%s' for %ld (%u), not expected\n",
pRecord->filename, posn, recordIdx); pRecord->filenameMOR, posn, recordIdx);
goto failed; goto failed;
} }
} }
@ -437,15 +456,14 @@ failed:
/* /*
* Selection callback filter for "test". This gets called once per record. * Selection callback filter for "test". This gets called once per record.
*/ */
NuResult NuResult VerifySelectionCallback(NuArchive* pArchive, void* vpProposal)
VerifySelectionCallback(NuArchive* pArchive, void* vpProposal)
{ {
NuError err; NuError err;
const NuSelectionProposal* pProposal = vpProposal; const NuSelectionProposal* pProposal = vpProposal;
long count; long count;
if (pProposal->pRecord == NULL || pProposal->pThread == NULL || if (pProposal->pRecord == NULL || pProposal->pThread == NULL ||
pProposal->pRecord->filename == NULL) pProposal->pRecord->filenameMOR == NULL)
{ {
fprintf(stderr, "ERROR: unexpected NULL in proposal\n"); fprintf(stderr, "ERROR: unexpected NULL in proposal\n");
goto failed; goto failed;
@ -473,8 +491,7 @@ failed:
/* /*
* Verify the archive contents. * Verify the archive contents.
*/ */
int int Test_Verify(NuArchive* pArchive)
Test_Verify(NuArchive* pArchive)
{ {
NuError err; NuError err;
long count; long count;
@ -520,8 +537,7 @@ failed:
/* /*
* Extract stuff. * Extract stuff.
*/ */
int int Test_Extract(NuArchive* pArchive)
Test_Extract(NuArchive* pArchive)
{ {
NuError err; NuError err;
NuRecordIdx recordIdx; NuRecordIdx recordIdx;
@ -780,8 +796,7 @@ failed:
/* /*
* Delete the first and last records. Does *not* flush the archive. * Delete the first and last records. Does *not* flush the archive.
*/ */
int int Test_Delete(NuArchive* pArchive)
Test_Delete(NuArchive* pArchive)
{ {
NuError err; NuError err;
NuRecordIdx recordIdx; NuRecordIdx recordIdx;
@ -847,6 +862,7 @@ Test_Delete(NuArchive* pArchive)
/* /*
* Make sure the attr hasn't been updated yet. * Make sure the attr hasn't been updated yet.
*/ */
count = 0;
err = NuGetAttr(pArchive, kNuAttrNumRecords, (uint32_t*) &count); err = NuGetAttr(pArchive, kNuAttrNumRecords, (uint32_t*) &count);
if (count != kNumEntries) { if (count != kNumEntries) {
fprintf(stderr, "ERROR: kNuAttrNumRecords %ld vs %d\n", fprintf(stderr, "ERROR: kNuAttrNumRecords %ld vs %d\n",
@ -901,8 +917,7 @@ failed:
/* /*
* Verify that the count in the master header has been updated. * Verify that the count in the master header has been updated.
*/ */
int int Test_MasterCount(NuArchive* pArchive, long expected)
Test_MasterCount(NuArchive* pArchive, long expected)
{ {
NuError err; NuError err;
const NuMasterHeader* pMasterHeader; const NuMasterHeader* pMasterHeader;
@ -932,41 +947,21 @@ failed:
* *
* Returns 0 on success, -1 on error. * Returns 0 on success, -1 on error.
*/ */
int int DoTests(void)
DoTests(void)
{ {
NuError err; NuError err;
NuArchive* pArchive = NULL; NuArchive* pArchive = NULL;
long status; uint32_t status;
int cc, result = 0; int cc, result = 0;
char answer;
/* /*
* Make sure we're starting with a clean slate. * Make sure we're starting with a clean slate.
*/ */
if (access(kTestArchive, F_OK) == 0) { if (RemoveTestFile("Test archive", kTestArchive) < 0) {
printf("Test archive '%s' exists, remove (y/n)? ", kTestArchive); goto failed;
fflush(stdout);
answer = TGetReplyChar('n');
if (tolower(answer) != 'y')
goto failed;
cc = unlink(kTestArchive);
if (cc < 0) {
perror("unlink kTestArchive");
goto failed;
}
} }
if (access(kTestTempFile, F_OK) == 0) { if (RemoveTestFile("Test temp file", kTestTempFile) < 0) {
printf("Test temp file '%s' exists, remove (y/n)? ", kTestTempFile); goto failed;
fflush(stdout);
answer = TGetReplyChar('n');
if (tolower(answer) != 'y')
goto failed;
cc = unlink(kTestTempFile);
if (cc < 0) {
perror("unlink kTestTempFile");
goto failed;
}
} }
/* /*
@ -1028,14 +1023,14 @@ DoTests(void)
} }
/* /*
* Make sure the contents are still what we expect. * Make sure the TOC (i.e. list of files) is still what we expect.
*/ */
printf("... checking contents\n"); printf("... checking contents\n");
if (Test_Contents(pArchive) != 0) if (Test_Contents(pArchive) != 0)
goto failed; goto failed;
/* /*
* Verify the archive contents. * Verify the archive data.
*/ */
if (Test_Verify(pArchive) != 0) if (Test_Verify(pArchive) != 0)
goto failed; goto failed;
@ -1107,7 +1102,7 @@ DoTests(void)
*/ */
err = NuFlush(pArchive, &status); err = NuFlush(pArchive, &status);
if (err != kNuErrNone) { if (err != kNuErrNone) {
fprintf(stderr, "ERROR: flush failed (err=%d, status=%ld)\n", fprintf(stderr, "ERROR: flush failed (err=%d, status=%d)\n",
err, status); err, status);
goto failed; goto failed;
} }
@ -1148,16 +1143,15 @@ failed:
/* /*
* Crank away. * Crank away.
*/ */
int int main(void)
main(void)
{ {
long major, minor, bug; int32_t major, minor, bug;
const char* pBuildDate; const char* pBuildDate;
const char* pBuildFlags; const char* pBuildFlags;
int cc; int cc;
(void) NuGetVersion(&major, &minor, &bug, &pBuildDate, &pBuildFlags); (void) NuGetVersion(&major, &minor, &bug, &pBuildDate, &pBuildFlags);
printf("Using NuFX library v%ld.%ld.%ld, built on or after\n" printf("Using NuFX library v%d.%d.%d, built on or after\n"
" %s with [%s]\n\n", " %s with [%s]\n\n",
major, minor, bug, pBuildDate, pBuildFlags); major, minor, bug, pBuildDate, pBuildFlags);

View File

@ -37,7 +37,7 @@
* Track an archive record. * Track an archive record.
*/ */
typedef struct ArchiveRecord { typedef struct ArchiveRecord {
char* filename; char* filenameMOR;
NuRecordIdx recordIdx; NuRecordIdx recordIdx;
long numThreads; long numThreads;
@ -50,8 +50,7 @@ typedef struct ArchiveRecord {
/* /*
* Alloc a new ArchiveRecord. * Alloc a new ArchiveRecord.
*/ */
ArchiveRecord* ArchiveRecord* ArchiveRecord_New(const NuRecord* pRecord)
ArchiveRecord_New(const NuRecord* pRecord)
{ {
ArchiveRecord* pArcRec = NULL; ArchiveRecord* pArcRec = NULL;
@ -59,10 +58,10 @@ ArchiveRecord_New(const NuRecord* pRecord)
if (pArcRec == NULL) if (pArcRec == NULL)
return NULL; return NULL;
if (pRecord->filename == NULL) if (pRecord->filenameMOR == NULL)
pArcRec->filename = strdup("<unknown>"); pArcRec->filenameMOR = strdup("<unknown>");
else else
pArcRec->filename = strdup((char*)pRecord->filename); pArcRec->filenameMOR = strdup(pRecord->filenameMOR);
pArcRec->recordIdx = pRecord->recordIdx; pArcRec->recordIdx = pRecord->recordIdx;
pArcRec->numThreads = NuRecordGetNumThreads(pRecord); pArcRec->numThreads = NuRecordGetNumThreads(pRecord);
@ -76,14 +75,13 @@ ArchiveRecord_New(const NuRecord* pRecord)
/* /*
* Free up an ArchiveRecord. * Free up an ArchiveRecord.
*/ */
void void ArchiveRecord_Free(ArchiveRecord* pArcRec)
ArchiveRecord_Free(ArchiveRecord* pArcRec)
{ {
if (pArcRec == NULL) if (pArcRec == NULL)
return; return;
if (pArcRec->filename != NULL) if (pArcRec->filenameMOR != NULL)
free(pArcRec->filename); free(pArcRec->filenameMOR);
if (pArcRec->pThreads != NULL) if (pArcRec->pThreads != NULL)
free(pArcRec->pThreads); free(pArcRec->pThreads);
free(pArcRec); free(pArcRec);
@ -92,8 +90,8 @@ ArchiveRecord_Free(ArchiveRecord* pArcRec)
/* /*
* Find a thread with a matching NuThreadID. * Find a thread with a matching NuThreadID.
*/ */
const NuThread* const NuThread* ArchiveRecord_FindThreadByID(const ArchiveRecord* pArcRec,
ArchiveRecord_FindThreadByID(const ArchiveRecord* pArcRec, NuThreadID threadID) NuThreadID threadID)
{ {
const NuThread* pThread; const NuThread* pThread;
int i; int i;
@ -108,40 +106,34 @@ ArchiveRecord_FindThreadByID(const ArchiveRecord* pArcRec, NuThreadID threadID)
} }
const char* const char* ArchiveRecord_GetFilename(const ArchiveRecord* pArcRec)
ArchiveRecord_GetFilename(const ArchiveRecord* pArcRec)
{ {
return pArcRec->filename; return pArcRec->filenameMOR;
} }
NuRecordIdx NuRecordIdx ArchiveRecord_GetRecordIdx(const ArchiveRecord* pArcRec)
ArchiveRecord_GetRecordIdx(const ArchiveRecord* pArcRec)
{ {
return pArcRec->recordIdx; return pArcRec->recordIdx;
} }
long long ArchiveRecord_GetNumThreads(const ArchiveRecord* pArcRec)
ArchiveRecord_GetNumThreads(const ArchiveRecord* pArcRec)
{ {
return pArcRec->numThreads; return pArcRec->numThreads;
} }
const NuThread* const NuThread* ArchiveRecord_GetThread(const ArchiveRecord* pArcRec, int idx)
ArchiveRecord_GetThread(const ArchiveRecord* pArcRec, int idx)
{ {
if (idx < 0 || idx >= pArcRec->numThreads) if (idx < 0 || idx >= pArcRec->numThreads)
return NULL; return NULL;
return NuThreadGetByIdx(pArcRec->pThreads, idx); return NuThreadGetByIdx(pArcRec->pThreads, idx);
} }
void void ArchiveRecord_SetNext(ArchiveRecord* pArcRec, ArchiveRecord* pNextRec)
ArchiveRecord_SetNext(ArchiveRecord* pArcRec, ArchiveRecord* pNextRec)
{ {
pArcRec->pNext = pNextRec; pArcRec->pNext = pNextRec;
} }
ArchiveRecord* ArchiveRecord* ArchiveRecord_GetNext(const ArchiveRecord* pArcRec)
ArchiveRecord_GetNext(const ArchiveRecord* pArcRec)
{ {
return pArcRec->pNext; return pArcRec->pNext;
} }
@ -163,8 +155,7 @@ typedef struct ArchiveData {
} ArchiveData; } ArchiveData;
ArchiveData* ArchiveData* ArchiveData_New(void)
ArchiveData_New(void)
{ {
ArchiveData* pArcData; ArchiveData* pArcData;
@ -178,8 +169,7 @@ ArchiveData_New(void)
return pArcData; return pArcData;
} }
void void ArchiveData_Free(ArchiveData* pArcData)
ArchiveData_Free(ArchiveData* pArcData)
{ {
ArchiveRecord* pNext; ArchiveRecord* pNext;
@ -197,16 +187,14 @@ ArchiveData_Free(ArchiveData* pArcData)
} }
ArchiveRecord* ArchiveRecord* ArchiveData_GetRecordHead(const ArchiveData* pArcData)
ArchiveData_GetRecordHead(const ArchiveData* pArcData)
{ {
return pArcData->pRecordHead; return pArcData->pRecordHead;
} }
/* add an ArchiveRecord to the list pointed at by ArchiveData */ /* add an ArchiveRecord to the list pointed at by ArchiveData */
void void ArchiveData_AddRecord(ArchiveData* pArcData, ArchiveRecord* pRecord)
ArchiveData_AddRecord(ArchiveData* pArcData, ArchiveRecord* pRecord)
{ {
assert(pRecord != NULL); assert(pRecord != NULL);
assert((pArcData->pRecordHead == NULL && pArcData->pRecordTail == NULL) || assert((pArcData->pRecordHead == NULL && pArcData->pRecordTail == NULL) ||
@ -225,8 +213,7 @@ ArchiveData_AddRecord(ArchiveData* pArcData, ArchiveRecord* pRecord)
} }
/* dump the contents of the ArchiveData to stdout */ /* dump the contents of the ArchiveData to stdout */
void void ArchiveData_DumpContents(const ArchiveData* pArcData)
ArchiveData_DumpContents(const ArchiveData* pArcData)
{ {
ArchiveRecord* pArcRec; ArchiveRecord* pArcRec;
@ -260,8 +247,7 @@ ArchiveData_DumpContents(const ArchiveData* pArcData)
/* /*
* Callback function to collect archive information. * Callback function to collect archive information.
*/ */
NuResult NuResult GatherContents(NuArchive* pArchive, void* vpRecord)
GatherContents(NuArchive* pArchive, void* vpRecord)
{ {
NuRecord* pRecord = (NuRecord*) vpRecord; NuRecord* pRecord = (NuRecord*) vpRecord;
ArchiveData* pArchiveData = NULL; ArchiveData* pArchiveData = NULL;
@ -271,7 +257,8 @@ GatherContents(NuArchive* pArchive, void* vpRecord)
assert(pArchiveData != NULL); assert(pArchiveData != NULL);
printf("*** Filename = '%s'\n", printf("*** Filename = '%s'\n",
pRecord->filename == NULL ? "<unknown>":(const char*)pRecord->filename); pRecord->filenameMOR == NULL ?
"<unknown>" : pRecord->filenameMOR);
ArchiveData_AddRecord(pArchiveData, pArchiveRecord); ArchiveData_AddRecord(pArchiveData, pArchiveRecord);
@ -282,8 +269,7 @@ GatherContents(NuArchive* pArchive, void* vpRecord)
/* /*
* Copy the filename thread from every record to "pDataSink". * Copy the filename thread from every record to "pDataSink".
*/ */
NuError NuError ReadAllFilenameThreads(NuArchive* pArchive, ArchiveData* pArchiveData,
ReadAllFilenameThreads(NuArchive* pArchive, ArchiveData* pArchiveData,
NuDataSink* pDataSink) NuDataSink* pDataSink)
{ {
NuError err = kNuErrNone; NuError err = kNuErrNone;
@ -310,8 +296,7 @@ bail:
/* extract every filename thread into a single file, overwriting each time */ /* extract every filename thread into a single file, overwriting each time */
NuError NuError ExtractToFile(NuArchive* pArchive, ArchiveData* pArchiveData)
ExtractToFile(NuArchive* pArchive, ArchiveData* pArchiveData)
{ {
NuError err; NuError err;
NuDataSink* pDataSink = NULL; NuDataSink* pDataSink = NULL;
@ -337,8 +322,7 @@ bail:
} }
/* extract every filename thread into a FILE*, appending */ /* extract every filename thread into a FILE*, appending */
NuError NuError ExtractToFP(NuArchive* pArchive, ArchiveData* pArchiveData)
ExtractToFP(NuArchive* pArchive, ArchiveData* pArchiveData)
{ {
NuError err; NuError err;
FILE* fp = NULL; FILE* fp = NULL;
@ -365,8 +349,7 @@ bail:
} }
/* extract every filename thread into a buffer, advancing as we go */ /* extract every filename thread into a buffer, advancing as we go */
NuError NuError ExtractToBuffer(NuArchive* pArchive, ArchiveData* pArchiveData)
ExtractToBuffer(NuArchive* pArchive, ArchiveData* pArchiveData)
{ {
NuError err; NuError err;
uint8_t buffer[kHappySize]; uint8_t buffer[kHappySize];
@ -409,14 +392,13 @@ bail:
/* /*
* Do file stuff. * Do file stuff.
*/ */
int int DoFileStuff(const UNICHAR* filenameUNI)
DoFileStuff(const char* filename)
{ {
NuError err; NuError err;
NuArchive* pArchive = NULL; NuArchive* pArchive = NULL;
ArchiveData* pArchiveData = ArchiveData_New(); ArchiveData* pArchiveData = ArchiveData_New();
err = NuOpenRO(filename, &pArchive); err = NuOpenRO(filenameUNI, &pArchive);
if (err != kNuErrNone) if (err != kNuErrNone)
goto bail; goto bail;
@ -459,16 +441,15 @@ bail:
/* /*
* Grab the name of an archive to read. If no name was provided, use stdin. * Grab the name of an archive to read. If no name was provided, use stdin.
*/ */
int int main(int argc, char** argv)
main(int argc, char** argv)
{ {
long major, minor, bug; int32_t major, minor, bug;
const char* pBuildDate; const char* pBuildDate;
FILE* infp = NULL; FILE* infp = NULL;
int cc; int cc;
(void) NuGetVersion(&major, &minor, &bug, &pBuildDate, NULL); (void) NuGetVersion(&major, &minor, &bug, &pBuildDate, NULL);
printf("Using NuFX lib %ld.%ld.%ld built on or after %s\n", printf("Using NuFX lib %d.%d.%d built on or after %s\n",
major, minor, bug, pBuildDate); major, minor, bug, pBuildDate);
if (argc == 2) { if (argc == 2) {

580
nufxlib/samples/TestNames.c Normal file
View File

@ -0,0 +1,580 @@
/*
* 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.
*
* Test local and storage names with Unicode and Mac OS Roman content.
*
* On Windows, opening files with fancy filenames requires UTF-16 and
* special functions. On Linux and Mac OS X we're just writing UTF-8 data,
* so they don't really need to do anything special other than be 8-bit
* clean. NufxLib functions take UTF-8 strings, so on Windows we define
* everything in UTF-16 and convert to UTF-8. (We need the UTF-16 form so
* we can use "wide" I/O functions to confirm that the file was created
* with the correct name.)
*
* To see files with the correct appearance with "ls", you may need to
* do something like:
*
* % LC_ALL=en_US.UTF-8 ls
*
* (Many users set LC_ALL=POSIX to avoid GNU grep slowdowns and altered
* sort ordering in ls.)
*/
#include <stdio.h>
#include <ctype.h>
#include "NufxLib.h"
#include "Common.h"
/*
* Test filenames.
*
* The local filename (kTestArchive) contains non-MOR Unicode values
* (two Japanese characters that Google Translate claims form the verb
* "shrink"). The temp file name is similar.
*
* The entry name uses a mix of simple ASCII, CP1252 MOR, and
* non-CP1252 MOR characters: fl ligature, double dagger, copyright symbol,
* Apple logo (the latter of which doesn't have a glyph on Windows or Linux).
* All of the characters have MOR translations.
*/
#ifdef USE_UTF16
const UNICHAR kTestArchive[] = L"nlTest\u7e2e\u3080.shk";
const UNICHAR kTestEntryName[] = L"nl-test\u2013\ufb01_\u2021_\u00a9\uf8ff!";
const UNICHAR kTestTempFile[] = L"nlTest\4e00\u6642\u30d5\u30a1\u30a4\u30eb.tmp";
#else
const UNICHAR kTestArchive[] = "nlTest\xe7\xb8\xae\xe3\x82\x80.shk";
const UNICHAR kTestEntryName[] = "nl-test\xe2\x80\x93\xef\xac\x81_\xe2\x80\xa1_"
"\xc2\xa9\xef\xa3\xbf!";
const UNICHAR kTestTempFile[] = "nlTest\xe4\xb8\x80\xe6\x99\x82\xe3\x83\x95"
"\xe3\x82\xa1\xe3\x82\xa4\xe3\x83\xab.tmp";
#endif
const UNICHAR kLocalFssep = '|';
/*
* ===========================================================================
* Helper functions
* ===========================================================================
*/
/*
* Get a single character of input from the user.
*/
static char TGetReplyChar(char defaultReply)
{
char tmpBuf[32];
if (fgets(tmpBuf, sizeof(tmpBuf), stdin) == NULL)
return defaultReply;
if (tmpBuf[0] == '\n' || tmpBuf[0] == '\r')
return defaultReply;
return tmpBuf[0];
}
NuError AddSimpleRecord(NuArchive* pArchive, const char* fileNameMOR,
NuRecordIdx* pRecordIdx)
{
NuFileDetails fileDetails;
memset(&fileDetails, 0, sizeof(fileDetails));
fileDetails.storageNameMOR = fileNameMOR;
fileDetails.fileSysInfo = kLocalFssep;
fileDetails.access = kNuAccessUnlocked;
return NuAddRecord(pArchive, &fileDetails, pRecordIdx);
}
/*
* Display error messages... or not.
*/
NuResult ErrorMessageHandler(NuArchive* pArchive, void* vErrorMessage)
{
const NuErrorMessage* pErrorMessage = (const NuErrorMessage*) vErrorMessage;
//if (gSuppressError)
// return kNuOK;
if (pErrorMessage->isDebug) {
fprintf(stderr, "%sNufxLib says: [%s:%d %s] %s\n",
pArchive == NULL ? "GLOBAL>" : "",
pErrorMessage->file, pErrorMessage->line, pErrorMessage->function,
pErrorMessage->message);
} else {
fprintf(stderr, "%sNufxLib says: %s\n",
pArchive == NULL ? "GLOBAL>" : "",
pErrorMessage->message);
}
return kNuOK;
}
#ifdef USE_UTF16
TODO - use _waccess, _wunlink, etc.
#else
int RemoveTestFile(const char* title, const char* fileName)
{
char answer;
if (access(fileName, F_OK) == 0) {
printf("%s '%s' exists, remove (y/n)? ", title, fileName);
fflush(stdout);
answer = TGetReplyChar('n');
if (tolower(answer) != 'y')
return -1;
if (unlink(fileName) < 0) {
perror("unlink");
return -1;
}
}
return 0;
}
#endif
/*
* Utility function that wraps NuConvertUNIToMOR, allocating a new
* buffer to hold the converted string. The caller must free the result.
*/
char* CopyUNIToMOR(const UNICHAR* stringUNI)
{
size_t morLen;
char* morBuf;
morLen = NuConvertUNIToMOR(stringUNI, NULL, 0);
if (morLen == (size_t) -1) {
return NULL;
}
morBuf = (char*) malloc(morLen);
(void) NuConvertUNIToMOR(stringUNI, morBuf, morLen);
return morBuf;
}
/*
* Utility function that wraps NuConvertMORToUNI, allocating a new
* buffer to hold the converted string. The caller must free the result.
*/
UNICHAR* CopyMORToUNI(const char* stringMOR)
{
size_t uniLen;
char* uniBuf;
uniLen = NuConvertMORToUNI(stringMOR, NULL, 0);
if (uniLen == (size_t) -1) {
return NULL;
}
uniBuf = (UNICHAR*) malloc(uniLen);
(void) NuConvertMORToUNI(stringMOR, uniBuf, uniLen);
return uniBuf;
}
/*
* ===========================================================================
* Tests
* ===========================================================================
*/
void DumpMorString(const char* str)
{
printf("(%d) ", (int) strlen(str));
while (*str != '\0') {
if (*str >= 0x20 && *str < 0x7f) {
putchar(*str);
} else {
printf("\\x%02x", (uint8_t) *str);
}
str++;
}
putchar('\n');
}
void DumpUnicharString(const UNICHAR* str)
{
printf("(%d) ", (int) strlen(str));
while (*str != '\0') {
if (*str >= 0x20 && *str < 0x7f) {
putchar(*str);
} else {
if (sizeof(UNICHAR) == 1) {
printf("\\x%02x", (uint8_t) *str);
} else {
printf("\\u%04x", (uint16_t) *str);
}
}
str++;
}
putchar('\n');
}
/*
* Some basic string conversion unit tests.
*
* TODO: test with short buffer, make sure we don't get partial code
* points when converting to Unicode
*/
int TestStringConversion(void)
{
static const char kMORTest[] = "test\xe0\xe9\xed\xf3\xfa#\xf0\xb0";
size_t outLen;
char morBuf[512];
UNICHAR uniBuf[512];
// convert test string to Unicode
memset(uniBuf, 0xcc, sizeof(uniBuf));
//printf("MOR: "); DumpMorString(kMORTest);
outLen = NuConvertMORToUNI(kMORTest, NULL, 0);
//printf("outLen is %u\n", (unsigned int) outLen);
if (NuConvertMORToUNI(kMORTest, uniBuf, sizeof(uniBuf)) != outLen) {
fprintf(stderr, "Inconsistent MORToUNI len\n");
return -1;
}
//printf("UNI: "); DumpUnicharString(uniBuf);
if (strlen(uniBuf) + 1 != outLen) {
fprintf(stderr, "Expected length != actual length\n");
return -1;
}
// convert Unicode back to MOR
memset(morBuf, 0xcc, sizeof(morBuf));
outLen = NuConvertUNIToMOR(uniBuf, NULL, 0);
//printf("outLen is %u\n", (unsigned int) outLen);
if (NuConvertUNIToMOR(uniBuf, morBuf, sizeof(morBuf)) != outLen) {
fprintf(stderr, "Inconsistent UNIToMOR len\n");
return -1;
}
//printf("MOR: "); DumpMorString(morBuf);
if (strlen(morBuf) + 1 != outLen) {
fprintf(stderr, "Expected length != actual length\n");
return -1;
}
// check vs. original
if (strcmp(kMORTest, morBuf) != 0) {
fprintf(stderr, "Test string corrupted by double conversion\n");
return -1;
}
#ifdef USE_UTF16
static const UNICHAR kNonMorUniStr[] = L"nlTest\u7e2e\u3080.shk";
static const UNICHAR kBadUniStr[] = L"nlTest\u7e2e\x30";
#else
static const UNICHAR kNonMorUniStr[] = "nlTest\xe7\xb8\xae\xe3\x82\x80.shk";
static const UNICHAR kBadUniStr[] = "nlTest\x81\xe7";
#endif
static const char kNonMorExpected[] = "nlTest??.shk";
static const char kBadExpected[] = "nlTest??";
NuConvertUNIToMOR(kNonMorUniStr, morBuf, sizeof(morBuf));
if (strcmp(morBuf, kNonMorExpected) != 0) {
fprintf(stderr, "Non-MOR string conversion failed\n");
return -1;
}
NuConvertUNIToMOR(kBadUniStr, morBuf, sizeof(morBuf));
if (strcmp(morBuf, kBadExpected) != 0) {
fprintf(stderr, "Bad UNI string conversion failed\n");
return -1;
}
printf("... string conversion tests successful\n");
return 0;
}
/*
* Create a new entry and give it a trivial data fork.
*/
int AddTestEntry(NuArchive* pArchive, const char* entryNameMOR)
{
NuDataSource* pDataSource = NULL;
NuRecordIdx recordIdx;
static const char* kTestMsg = "Hello, world!\n";
uint32_t status;
NuError err;
/*
* Add our test entry.
*/
err = AddSimpleRecord(pArchive, entryNameMOR, &recordIdx);
if (err != kNuErrNone) {
fprintf(stderr, "ERROR: add record failed (err=%d)\n", err);
goto failed;
}
err = NuCreateDataSourceForBuffer(kNuThreadFormatUncompressed,
0, (const uint8_t*)kTestMsg, 0, strlen(kTestMsg), NULL,
&pDataSource);
if (err != kNuErrNone) {
fprintf(stderr, "ERROR: source create failed (err=%d)\n", err);
goto failed;
}
err = NuAddThread(pArchive, recordIdx, kNuThreadIDDataFork, pDataSource,
NULL);
if (err != kNuErrNone) {
fprintf(stderr, "ERROR: thread add failed (err=%d)\n", err);
goto failed;
}
pDataSource = NULL; /* now owned by library */
/*
* Flush changes.
*/
err = NuFlush(pArchive, &status);
if (err != kNuErrNone) {
fprintf(stderr, "ERROR: couldn't flush after add (err=%d, status=%u)\n",
err, status);
goto failed;
}
return 0;
failed:
if (pDataSource != NULL)
NuFreeDataSource(pDataSource);
return -1;
}
/*
* Extract the file we created.
*/
int TestExtract(NuArchive* pArchive, const char* entryNameMOR)
{
const NuRecord* pRecord;
NuRecordIdx recordIdx;
NuError err;
err = NuGetRecordIdxByName(pArchive, entryNameMOR, &recordIdx);
if (err != kNuErrNone) {
fprintf(stderr, "ERROR: couldn't find '%s' (err=%d)\n",
entryNameMOR, err);
return -1;
}
err = NuGetRecord(pArchive, recordIdx, &pRecord);
if (err != kNuErrNone) {
fprintf(stderr, "ERROR: couldn't get record index %u (err=%d)\n",
recordIdx, err);
return -1;
}
assert(pRecord != NULL);
const NuThread* pThread = NULL;
uint32_t idx;
for (idx = 0; idx < NuRecordGetNumThreads(pRecord); idx++) {
pThread = NuGetThread(pRecord, idx);
if (NuGetThreadID(pThread) == kNuThreadIDDataFork)
break;
}
if (pThread == NULL) {
fprintf(stderr, "ERROR: no data thread?\n");
return -1;
}
/*
* Prepare the output file.
*/
UNICHAR* entryNameUNI = CopyMORToUNI(entryNameMOR);
NuDataSink* pDataSink = NULL;
err = NuCreateDataSinkForFile(true, kNuConvertOff, entryNameUNI,
kLocalFssep, &pDataSink);
if (err != kNuErrNone) {
fprintf(stderr, "ERROR: unable to create data sink for file (err=%d)\n",
err);
free(entryNameUNI);
return -1;
}
err = NuExtractThread(pArchive, pThread->threadIdx, pDataSink);
if (err != kNuErrNone) {
fprintf(stderr, "ERROR: extract failed (err=%d)\n", err);
(void) NuFreeDataSink(pDataSink);
free(entryNameUNI);
return -1;
}
(void) NuFreeDataSink(pDataSink);
printf("... confirming extraction of '%s'\n", entryNameUNI);
if (access(entryNameUNI, R_OK) != 0) {
fprintf(stderr, "ERROR: unable to read '%s' (err=%d)\n",
entryNameUNI, errno);
free(entryNameUNI);
return -1;
}
if (unlink(entryNameUNI) < 0) {
perror("unlink test entry");
free(entryNameUNI);
return -1;
}
free(entryNameUNI);
return 0;
}
/*
* Run some tests.
*
* Returns 0 on success, -1 on error.
*/
int DoTests(void)
{
NuError err;
NuArchive* pArchive = NULL;
char* testEntryNameMOR = NULL;
int result = 0;
if (TestStringConversion() < 0) {
goto failed;
}
/*
* Make sure we're starting with a clean slate.
*/
if (RemoveTestFile("Test archive", kTestArchive) < 0) {
goto failed;
}
if (RemoveTestFile("Test temp file", kTestTempFile) < 0) {
goto failed;
}
if (RemoveTestFile("Test entry", kTestEntryName) < 0) {
goto failed;
}
testEntryNameMOR = CopyUNIToMOR(kTestEntryName);
/*
* Create a new archive to play with.
*/
err = NuOpenRW(kTestArchive, kTestTempFile, kNuOpenCreat|kNuOpenExcl,
&pArchive);
if (err != kNuErrNone) {
fprintf(stderr, "ERROR: NuOpenRW failed (err=%d)\n", err);
goto failed;
}
if (NuSetErrorMessageHandler(pArchive, ErrorMessageHandler) ==
kNuInvalidCallback)
{
fprintf(stderr, "ERROR: couldn't set message handler\n");
goto failed;
}
/*
* Add a single entry.
*/
if (AddTestEntry(pArchive, testEntryNameMOR) != 0) {
goto failed;
}
printf("... checking presence of '%s' and '%s'\n",
kTestArchive, kTestTempFile);
if (access(kTestTempFile, F_OK) != 0) {
/* in theory, NufxLib doesn't need to use the temp file we provide,
so this test isn't entirely sound */
fprintf(stderr, "ERROR: did not find %s (err=%d)\n",
kTestTempFile, err);
goto failed;
}
/*
* Close it and confirm that the file has the expected name.
*/
err = NuClose(pArchive);
if (err != kNuErrNone) {
fprintf(stderr, "ERROR: mid NuClose failed (err=%d)\n", err);
goto failed;
}
pArchive = NULL;
if (access(kTestArchive, R_OK) != 0) {
fprintf(stderr, "ERROR: did not find %s (err=%d)\n", kTestArchive, err);
goto failed;
}
/*
* Reopen it read-only.
*/
printf("... reopening archive read-only\n");
err = NuOpenRO(kTestArchive, &pArchive);
if (err != kNuErrNone) {
fprintf(stderr, "ERROR: NuOpenRO failed (err=%d)\n", err);
goto failed;
}
if (NuSetErrorMessageHandler(pArchive, ErrorMessageHandler) ==
kNuInvalidCallback)
{
fprintf(stderr, "ERROR: couldn't set message handler\n");
goto failed;
}
/*
* Extract the file.
*/
if (TestExtract(pArchive, testEntryNameMOR) < 0) {
goto failed;
}
/*
* That's all, folks...
*/
NuClose(pArchive);
pArchive = NULL;
printf("... removing '%s'\n", kTestArchive);
if (unlink(kTestArchive) < 0) {
perror("unlink kTestArchive");
goto failed;
}
leave:
if (pArchive != NULL) {
NuAbort(pArchive);
NuClose(pArchive);
}
free(testEntryNameMOR);
return result;
failed:
result = -1;
goto leave;
}
/*
* Start here.
*/
int main(void)
{
int32_t major, minor, bug;
const char* pBuildDate;
const char* pBuildFlags;
int cc;
(void) NuGetVersion(&major, &minor, &bug, &pBuildDate, &pBuildFlags);
printf("Using NuFX library v%d.%d.%d, built on or after\n"
" %s with [%s]\n\n",
major, minor, bug, pBuildDate, pBuildFlags);
if (NuSetGlobalErrorMessageHandler(ErrorMessageHandler) ==
kNuInvalidCallback)
{
fprintf(stderr, "ERROR: can't set the global message handler");
exit(1);
}
printf("... starting tests\n");
cc = DoTests();
printf("... tests ended, %s\n", cc == 0 ? "SUCCESS" : "FAILURE");
exit(cc != 0);
}

View File

@ -21,12 +21,20 @@
* header, a filename thread, or a default value ("UNKNOWN", stuffed in * header, a filename thread, or a default value ("UNKNOWN", stuffed in
* when a record has no filename at all). * when a record has no filename at all).
*/ */
NuResult NuResult ShowContents(NuArchive* pArchive, void* vpRecord)
ShowContents(NuArchive* pArchive, void* vpRecord)
{ {
const NuRecord* pRecord = (NuRecord*) vpRecord; const NuRecord* pRecord = (NuRecord*) vpRecord;
printf("*** Filename = '%s'\n", pRecord->filename); size_t bufLen = NuConvertMORToUNI(pRecord->filenameMOR, NULL, 0);
if (bufLen == (size_t) -1) {
fprintf(stderr, "GLITCH: unable to convert '%s'\n",
pRecord->filenameMOR);
} else {
UNICHAR* buf = (UNICHAR*) malloc(bufLen);
NuConvertMORToUNI(pRecord->filenameMOR, buf, bufLen);
printf("*** Filename = '%s'\n", buf);
free(buf);
}
return kNuOK; return kNuOK;
} }
@ -38,8 +46,7 @@ ShowContents(NuArchive* pArchive, void* vpRecord)
* If we're not interested in handling an archive on stdin, we could just * If we're not interested in handling an archive on stdin, we could just
* pass the filename in here and use NuOpenRO instead. * pass the filename in here and use NuOpenRO instead.
*/ */
int int DoStreamStuff(FILE* fp)
DoStreamStuff(FILE* fp)
{ {
NuError err; NuError err;
NuArchive* pArchive = NULL; NuArchive* pArchive = NULL;
@ -72,16 +79,15 @@ bail:
/* /*
* Grab the name of an archive to read. If "-" was given, use stdin. * Grab the name of an archive to read. If "-" was given, use stdin.
*/ */
int int main(int argc, char** argv)
main(int argc, char** argv)
{ {
long major, minor, bug; int32_t major, minor, bug;
const char* pBuildDate; const char* pBuildDate;
FILE* infp = NULL; FILE* infp = NULL;
int cc; int cc;
(void) NuGetVersion(&major, &minor, &bug, &pBuildDate, NULL); (void) NuGetVersion(&major, &minor, &bug, &pBuildDate, NULL);
printf("Using NuFX lib %ld.%ld.%ld built on or after %s\n", printf("Using NuFX lib %d.%d.%d built on or after %s\n",
major, minor, bug, pBuildDate); major, minor, bug, pBuildDate);
if (argc != 2) { if (argc != 2) {

View File

@ -37,8 +37,7 @@ typedef struct CRCList {
/* /*
* Returns true if the compression type is supported, false otherwise. * Returns true if the compression type is supported, false otherwise.
*/ */
int int CompressionSupported(NuValue compression)
CompressionSupported(NuValue compression)
{ {
int result; int result;
@ -76,8 +75,7 @@ CompressionSupported(NuValue compression)
/* /*
* This gets called when a buffer DataSource is no longer needed. * This gets called when a buffer DataSource is no longer needed.
*/ */
NuResult NuResult FreeCallback(NuArchive* pArchive, void* args)
FreeCallback(NuArchive* pArchive, void* args)
{ {
free(args); free(args);
return kNuOK; return kNuOK;
@ -87,8 +85,7 @@ FreeCallback(NuArchive* pArchive, void* args)
/* /*
* Dump a CRC list. * Dump a CRC list.
*/ */
void void DumpCRCs(const CRCList* pCRCList)
DumpCRCs(const CRCList* pCRCList)
{ {
int i; int i;
@ -101,8 +98,7 @@ DumpCRCs(const CRCList* pCRCList)
/* /*
* Free a CRC list. * Free a CRC list.
*/ */
void void FreeCRCs(CRCList* pCRCList)
FreeCRCs(CRCList* pCRCList)
{ {
if (pCRCList == NULL) if (pCRCList == NULL)
return; return;
@ -119,8 +115,7 @@ FreeCRCs(CRCList* pCRCList)
* *
* Returns the list on success, NULL on failure. * Returns the list on success, NULL on failure.
*/ */
CRCList* CRCList* GatherCRCs(NuArchive* pArchive)
GatherCRCs(NuArchive* pArchive)
{ {
NuError err = kNuErrNone; NuError err = kNuErrNone;
const NuMasterHeader* pMasterHeader; const NuMasterHeader* pMasterHeader;
@ -228,8 +223,7 @@ bail:
* *
* Returns 0 on success, nonzero on failure. * Returns 0 on success, nonzero on failure.
*/ */
int int CompareCRCs(NuArchive* pArchive, const CRCList* pOldCRCList)
CompareCRCs(NuArchive* pArchive, const CRCList* pOldCRCList)
{ {
CRCList* pNewCRCList = NULL; CRCList* pNewCRCList = NULL;
int result = -1; int result = -1;
@ -274,8 +268,7 @@ bail:
* *
* All of this good stuff gets queued up until the next NuFlush call. * All of this good stuff gets queued up until the next NuFlush call.
*/ */
NuError NuError RecompressThread(NuArchive* pArchive, const NuRecord* pRecord,
RecompressThread(NuArchive* pArchive, const NuRecord* pRecord,
const NuThread* pThread) const NuThread* pThread)
{ {
NuError err = kNuErrNone; NuError err = kNuErrNone;
@ -315,7 +308,7 @@ RecompressThread(NuArchive* pArchive, const NuRecord* pRecord,
err = NuExtractThread(pArchive, pThread->threadIdx, pDataSink); err = NuExtractThread(pArchive, pThread->threadIdx, pDataSink);
if (err != kNuErrNone) { if (err != kNuErrNone) {
fprintf(stderr, "ERROR: failed extracting thread %u in '%s': %s\n", fprintf(stderr, "ERROR: failed extracting thread %u in '%s': %s\n",
pThread->threadIdx, pRecord->filename, NuStrError(err)); pThread->threadIdx, pRecord->filenameMOR, NuStrError(err));
goto bail; goto bail;
} }
} }
@ -367,8 +360,7 @@ bail:
* The amount of data we're holding in memory as a result of the * The amount of data we're holding in memory as a result of the
* recompression is placed in "*pLen". * recompression is placed in "*pLen".
*/ */
NuError NuError RecompressRecord(NuArchive* pArchive, NuRecordIdx recordIdx, long* pLen)
RecompressRecord(NuArchive* pArchive, NuRecordIdx recordIdx, long* pLen)
{ {
NuError err = kNuErrNone; NuError err = kNuErrNone;
const NuRecord* pRecord; const NuRecord* pRecord;
@ -412,8 +404,7 @@ bail:
/* /*
* Recompress every data thread in the archive. * Recompress every data thread in the archive.
*/ */
NuError NuError RecompressArchive(NuArchive* pArchive, NuValue compression)
RecompressArchive(NuArchive* pArchive, NuValue compression)
{ {
NuError err = kNuErrNone; NuError err = kNuErrNone;
NuRecordIdx* pIndices = NULL; NuRecordIdx* pIndices = NULL;
@ -478,7 +469,7 @@ RecompressArchive(NuArchive* pArchive, NuValue compression)
heldLen += recHeldLen; heldLen += recHeldLen;
if (heldLen > kMaxHeldLen) { if (heldLen > kMaxHeldLen) {
long statusFlags; uint32_t statusFlags;
printf(" (flush)\n"); printf(" (flush)\n");
err = NuFlush(pArchive, &statusFlags); err = NuFlush(pArchive, &statusFlags);
@ -500,8 +491,7 @@ bail:
/* /*
* Initiate the twirling. * Initiate the twirling.
*/ */
int int TwirlArchive(const char* filename)
TwirlArchive(const char* filename)
{ {
NuError err = kNuErrNone; NuError err = kNuErrNone;
NuArchive* pArchive = NULL; NuArchive* pArchive = NULL;
@ -545,7 +535,7 @@ TwirlArchive(const char* filename)
for (compression = kNuCompressNone; compression <= kNuCompressBzip2; for (compression = kNuCompressNone; compression <= kNuCompressBzip2;
compression++) compression++)
{ {
long statusFlags; uint32_t statusFlags;
if (!CompressionSupported(compression)) if (!CompressionSupported(compression))
continue; continue;
@ -571,7 +561,7 @@ TwirlArchive(const char* filename)
for (compression = kNuCompressBzip2; compression >= kNuCompressNone; for (compression = kNuCompressBzip2; compression >= kNuCompressNone;
compression--) compression--)
{ {
long statusFlags; uint32_t statusFlags;
if (!CompressionSupported(compression)) if (!CompressionSupported(compression))
continue; continue;
@ -615,8 +605,7 @@ bail:
* *
* (Note "CopyFile()" exists under Win32.) * (Note "CopyFile()" exists under Win32.)
*/ */
FILE* FILE* MyCopyFile(const char* outFileName, FILE* srcfp)
MyCopyFile(const char* outFileName, FILE* srcfp)
{ {
char buf[24576]; char buf[24576];
FILE* outfp; FILE* outfp;
@ -652,10 +641,9 @@ MyCopyFile(const char* outFileName, FILE* srcfp)
/* /*
* Let's get started. * Let's get started.
*/ */
int int main(int argc, char** argv)
main(int argc, char** argv)
{ {
long major, minor, bug; int32_t major, minor, bug;
const char* pBuildDate; const char* pBuildDate;
FILE* srcfp = NULL; FILE* srcfp = NULL;
FILE* infp = NULL; FILE* infp = NULL;
@ -666,7 +654,7 @@ main(int argc, char** argv)
setvbuf(stderr, NULL, _IONBF, 0); setvbuf(stderr, NULL, _IONBF, 0);
(void) NuGetVersion(&major, &minor, &bug, &pBuildDate, NULL); (void) NuGetVersion(&major, &minor, &bug, &pBuildDate, NULL);
printf("Using NuFX lib %ld.%ld.%ld built on or after %s\n\n", printf("Using NuFX lib %d.%d.%d built on or after %s\n\n",
major, minor, bug, pBuildDate); major, minor, bug, pBuildDate);
if (argc == 2) { if (argc == 2) {

View File

@ -1,12 +1,12 @@
/* /*
* Nulib2 * NuLib2
* Copyright (C) 2000-2007 by Andy McFadden, All Rights Reserved. * Copyright (C) 2000-2007 by Andy McFadden, All Rights Reserved.
* This is free software; you can redistribute it and/or modify it under the * This is free software; you can redistribute it and/or modify it under the
* terms of the BSD License, see the file COPYING. * terms of the BSD License, see the file COPYING.
* *
* Add files to or update files in the archive. * Add files to or update files in the archive.
*/ */
#include "Nulib2.h" #include "NuLib2.h"
static NuError AddToArchive(NulibState* pState, NuArchive* pArchive); static NuError AddToArchive(NulibState* pState, NuArchive* pArchive);
@ -18,7 +18,7 @@ NuError DoAdd(NulibState* pState)
{ {
NuError err; NuError err;
NuArchive* pArchive = NULL; NuArchive* pArchive = NULL;
long flushStatus; uint32_t flushStatus;
Assert(pState != NULL); Assert(pState != NULL);
@ -61,7 +61,7 @@ bail:
"failed afterward"); "failed afterward");
} else { } else {
ReportError(err, ReportError(err,
"Unable to flush archive changes (status=0x%04lx)", "Unable to flush archive changes (status=0x%04x)",
flushStatus); flushStatus);
} }
NuAbort(pArchive); NuAbort(pArchive);

View File

@ -1,12 +1,12 @@
/* /*
* Nulib2 * NuLib2
* Copyright (C) 2000-2007 by Andy McFadden, All Rights Reserved. * Copyright (C) 2000-2007 by Andy McFadden, All Rights Reserved.
* This is free software; you can redistribute it and/or modify it under the * This is free software; you can redistribute it and/or modify it under the
* terms of the BSD License, see the file COPYING. * terms of the BSD License, see the file COPYING.
* *
* Common archive-related utility functions. * Common archive-related utility functions.
*/ */
#include "Nulib2.h" #include "NuLib2.h"
/* /*
@ -28,10 +28,10 @@ static NuResult OutputPathnameFilter(NuArchive* pArchive, void* vproposal)
{ {
NuPathnameProposal* pathProposal = vproposal; NuPathnameProposal* pathProposal = vproposal;
NulibState* pState; NulibState* pState;
const char* newPathname; const UNICHAR* newPathnameUNI;
NuRecordIdx renameFromIdx; NuRecordIdx renameFromIdx;
char* renameToStr; UNICHAR* renameToStrUNI;
char* resultBuf; UNICHAR* resultBufUNI;
Assert(pArchive != NULL); Assert(pArchive != NULL);
(void) NuGetExtraData(pArchive, (void**) &pState); (void) NuGetExtraData(pArchive, (void**) &pState);
@ -49,21 +49,21 @@ static NuResult OutputPathnameFilter(NuArchive* pArchive, void* vproposal)
* the output through the normalizer; if the user typed it, assume * the output through the normalizer; if the user typed it, assume
* that it's okay (and let the OS tell them if it isn't). * that it's okay (and let the OS tell them if it isn't).
*/ */
renameToStr = NState_GetRenameToStr(pState); renameToStrUNI = NState_GetRenameToStr(pState);
if (renameToStr != NULL) { if (renameToStrUNI != NULL) {
renameFromIdx = NState_GetRenameFromIdx(pState); renameFromIdx = NState_GetRenameFromIdx(pState);
if (renameFromIdx == pathProposal->pRecord->recordIdx) { if (renameFromIdx == pathProposal->pRecord->recordIdx) {
/* right source file, proceed with the rename */ /* right source file, proceed with the rename */
NState_SetTempPathnameLen(pState, strlen(renameToStr) +1); NState_SetTempPathnameLen(pState, strlen(renameToStrUNI) +1);
resultBuf = NState_GetTempPathnameBuf(pState); resultBufUNI = NState_GetTempPathnameBuf(pState);
Assert(resultBuf != NULL); Assert(resultBufUNI != NULL);
strcpy(resultBuf, renameToStr); strcpy(resultBufUNI, renameToStrUNI);
pathProposal->newPathname = resultBuf; pathProposal->newPathnameUNI = resultBufUNI;
} }
/* free up renameToStr */ /* free up renameToStrUNI */
NState_SetRenameToStr(pState, NULL); NState_SetRenameToStr(pState, NULL);
goto bail; goto bail;
@ -72,13 +72,13 @@ static NuResult OutputPathnameFilter(NuArchive* pArchive, void* vproposal)
/* /*
* Convert the pathname into something suitable for the current OS. * Convert the pathname into something suitable for the current OS.
*/ */
newPathname = NormalizePath(pState, pathProposal); newPathnameUNI = NormalizePath(pState, pathProposal);
if (newPathname == NULL) { if (newPathnameUNI == NULL) {
ReportError(kNuErrNone, "unable to convert pathname"); ReportError(kNuErrNone, "unable to convert pathname");
return kNuAbort; return kNuAbort;
} }
pathProposal->newPathname = newPathname; pathProposal->newPathnameUNI = newPathnameUNI;
bail: bail:
return kNuOK; return kNuOK;
@ -202,9 +202,9 @@ static Boolean SpecMatchesRecord(NulibState* pState, const char* spec,
return (strcmp(spec, pRecord->filename) == 0); return (strcmp(spec, pRecord->filename) == 0);
#else #else
if (NState_GetModRecurse(pState)) if (NState_GetModRecurse(pState))
return (strncasecmp(spec, pRecord->filename, strlen(spec)) == 0); return (strncasecmp(spec, pRecord->filenameMOR, strlen(spec)) == 0);
else else
return (strcasecmp(spec, pRecord->filename) == 0); return (strcasecmp(spec, pRecord->filenameMOR) == 0);
#endif #endif
} }
@ -253,12 +253,14 @@ NuResult SelectionFilter(NuArchive* pArchive, void* vproposal)
NState_IncMatchCount(pState); NState_IncMatchCount(pState);
/* we don't get progress notifications for delete, so do it here */ /* we don't get progress notifications for delete, so do it here */
if (NState_GetCommand(pState) == kCommandDelete) if (NState_GetCommand(pState) == kCommandDelete) {
printf("Deleting %s\n", selProposal->pRecord->filename); printf("Deleting %s\n", selProposal->pRecord->filenameMOR);
}
return kNuOK; return kNuOK;
} else } else {
return kNuSkip; return kNuSkip;
}
} }
@ -401,12 +403,13 @@ NuResult ProgressUpdater(NuArchive* pArchive, void* vProgress)
* Could also use "origPathname", but I like to show what they're * Could also use "origPathname", but I like to show what they're
* getting instead of what they're giving. * getting instead of what they're giving.
*/ */
int len = strlen(pProgress->pathname); int len = strlen(pProgress->pathnameUNI);
if (len < sizeof(nameBuf)) { if (len < sizeof(nameBuf)) {
strcpy(nameBuf, pProgress->pathname); strcpy(nameBuf, pProgress->pathnameUNI);
} else { } else {
nameBuf[0] = nameBuf[1] = '.'; nameBuf[0] = nameBuf[1] = '.';
strncpy(nameBuf+2, pProgress->pathname + len - (sizeof(nameBuf)-3), strncpy(nameBuf+2,
pProgress->pathnameUNI + len - (sizeof(nameBuf)-3),
sizeof(nameBuf)-3); sizeof(nameBuf)-3);
nameBuf[sizeof(nameBuf)-1] = '\0'; nameBuf[sizeof(nameBuf)-1] = '\0';
} }
@ -450,7 +453,7 @@ static NuResult HandleReplaceExisting(NulibState* pState, NuArchive* pArchive,
Assert(pState != NULL); Assert(pState != NULL);
Assert(pErrorStatus != NULL); Assert(pErrorStatus != NULL);
Assert(pErrorStatus->pathname != NULL); Assert(pErrorStatus->pathnameUNI != NULL);
Assert(pErrorStatus->canOverwrite); Assert(pErrorStatus->canOverwrite);
Assert(pErrorStatus->canSkip); Assert(pErrorStatus->canSkip);
@ -465,7 +468,7 @@ static NuResult HandleReplaceExisting(NulibState* pState, NuArchive* pArchive,
while (1) { while (1) {
printf("\n Replace %s? [y]es, [n]o, [A]ll, [N]one", printf("\n Replace %s? [y]es, [n]o, [A]ll, [N]one",
pErrorStatus->pathname); pErrorStatus->pathnameUNI);
if (pErrorStatus->canRename) /* renaming record adds not allowed */ if (pErrorStatus->canRename) /* renaming record adds not allowed */
printf(", [r]ename: "); printf(", [r]ename: ");
else else
@ -545,9 +548,9 @@ static NuResult HandleBadCRC(NulibState* pState, NuArchive* pArchive,
} }
while (1) { while (1) {
if (pErrorStatus->pathname != NULL) if (pErrorStatus->pathnameUNI != NULL)
fprintf(stderr, "\n Found a bad CRC in %s\n", fprintf(stderr, "\n Found a bad CRC in %s\n",
pErrorStatus->pathname); pErrorStatus->pathnameUNI);
else else
fprintf(stderr, "\n Found a bad CRC in the archive\n"); fprintf(stderr, "\n Found a bad CRC in the archive\n");
@ -595,7 +598,7 @@ static NuResult HandleAddNotFound(NulibState* pState, NuArchive* pArchive,
Assert(pState != NULL); Assert(pState != NULL);
Assert(pErrorStatus != NULL); Assert(pErrorStatus != NULL);
Assert(pErrorStatus->pathname != NULL); Assert(pErrorStatus->pathnameUNI != NULL);
if (NState_GetInputUnavailable(pState)) { if (NState_GetInputUnavailable(pState)) {
putc('\n', stdout); putc('\n', stdout);
@ -606,7 +609,7 @@ static NuResult HandleAddNotFound(NulibState* pState, NuArchive* pArchive,
while (1) { while (1) {
fprintf(stderr, "\n Couldn't find %s, continue? [y]es, [n]o: ", fprintf(stderr, "\n Couldn't find %s, continue? [y]es, [n]o: ",
pErrorStatus->pathname); pErrorStatus->pathnameUNI);
fflush(stderr); fflush(stderr);
reply = GetReplyChar('n'); reply = GetReplyChar('n');

View File

@ -1,5 +1,5 @@
/* /*
* Nulib2 * NuLib2
* Copyright (C) 2000-2007 by Andy McFadden, All Rights Reserved. * Copyright (C) 2000-2007 by Andy McFadden, All Rights Reserved.
* This is free software; you can redistribute it and/or modify it under the * This is free software; you can redistribute it and/or modify it under the
* terms of the BSD License, see the file COPYING. * terms of the BSD License, see the file COPYING.
@ -17,7 +17,7 @@
* *
* TO DO: add "junk skipping" like NufxLib has. * TO DO: add "junk skipping" like NufxLib has.
*/ */
#include "Nulib2.h" #include "NuLib2.h"
#ifdef HAVE_FCNTL_H #ifdef HAVE_FCNTL_H
# include <fcntl.h> # include <fcntl.h>
@ -136,7 +136,7 @@ typedef struct BNYEntry {
NuDateTime createWhen; /* computed from previous two fields */ NuDateTime createWhen; /* computed from previous two fields */
uint32_t eof; uint32_t eof;
uint32_t realEOF; /* eof is bogus for directories */ uint32_t realEOF; /* eof is bogus for directories */
char fileName[kBNYMaxFileName+1]; char fileName[kBNYMaxFileName+1]; /* ASCII only */
char nativeName[kBNYMaxNativeName+1]; char nativeName[kBNYMaxNativeName+1];
uint32_t diskSpace; /* in 512-byte blocks */ uint32_t diskSpace; /* in 512-byte blocks */
uint8_t osType; /* not exactly same as NuFileSysID */ uint8_t osType; /* not exactly same as NuFileSysID */
@ -406,12 +406,12 @@ const char* BNYNormalizePath(BNYArchive* pBny, BNYEntry* pEntry)
memset(&fakeRecord, 0xa1, sizeof(fakeRecord)); memset(&fakeRecord, 0xa1, sizeof(fakeRecord));
memset(&fakeThread, 0xa5, sizeof(fakeThread)); memset(&fakeThread, 0xa5, sizeof(fakeThread));
pathProposal.pathname = pEntry->fileName; pathProposal.pathnameUNI = pEntry->fileName;
pathProposal.filenameSeparator = '/'; /* BNY always uses ProDOS conv */ pathProposal.filenameSeparator = '/'; /* BNY always uses ProDOS conv */
pathProposal.pRecord = &fakeRecord; pathProposal.pRecord = &fakeRecord;
pathProposal.pThread = &fakeThread; pathProposal.pThread = &fakeThread;
pathProposal.newPathname = NULL; pathProposal.newPathnameUNI = NULL;
pathProposal.newFilenameSeparator = '\0'; pathProposal.newFilenameSeparator = '\0';
pathProposal.newDataSink = NULL; pathProposal.newDataSink = NULL;

View File

@ -1,12 +1,12 @@
/* /*
* Nulib2 * NuLib2
* Copyright (C) 2000-2007 by Andy McFadden, All Rights Reserved. * Copyright (C) 2000-2007 by Andy McFadden, All Rights Reserved.
* This is free software; you can redistribute it and/or modify it under the * This is free software; you can redistribute it and/or modify it under the
* terms of the BSD License, see the file COPYING. * terms of the BSD License, see the file COPYING.
* *
* Delete files from the archive. * Delete files from the archive.
*/ */
#include "Nulib2.h" #include "NuLib2.h"
/* /*

View File

@ -1,12 +1,12 @@
/* /*
* Nulib2 * NuLib2
* Copyright (C) 2000-2007 by Andy McFadden, All Rights Reserved. * Copyright (C) 2000-2007 by Andy McFadden, All Rights Reserved.
* This is free software; you can redistribute it and/or modify it under the * This is free software; you can redistribute it and/or modify it under the
* terms of the BSD License, see the file COPYING. * terms of the BSD License, see the file COPYING.
* *
* Extract files and test archives. * Extract files and test archives.
*/ */
#include "Nulib2.h" #include "NuLib2.h"
/* /*
@ -61,7 +61,9 @@ static NuError ExtractAllRecords(NulibState* pState, NuArchive* pArchive)
if (NuGetThreadID(pThread) == kNuThreadIDComment && if (NuGetThreadID(pThread) == kNuThreadIDComment &&
pThread->actualThreadEOF > 0) pThread->actualThreadEOF > 0)
{ {
printf("----- '%s':\n", pRecord->filename); UNICHAR* filenameUNI = CopyMORToUNI(pRecord->filenameMOR);
printf("----- '%s':\n", filenameUNI);
free(filenameUNI);
err = NuExtractThread(pArchive, pThread->threadIdx, err = NuExtractThread(pArchive, pThread->threadIdx,
NState_GetCommentSink(pState)); NState_GetCommentSink(pState));
if (err != kNuErrNone) { if (err != kNuErrNone) {

View File

@ -1,12 +1,12 @@
/* /*
* Nulib2 * NuLib2
* Copyright (C) 2000-2007 by Andy McFadden, All Rights Reserved. * Copyright (C) 2000-2007 by Andy McFadden, All Rights Reserved.
* This is free software; you can redistribute it and/or modify it under the * This is free software; you can redistribute it and/or modify it under the
* terms of the BSD License, see the file COPYING. * terms of the BSD License, see the file COPYING.
* *
* Filename manipulation, including file type preservation. * Filename manipulation, including file type preservation.
*/ */
#include "Nulib2.h" #include "NuLib2.h"
#include <ctype.h> #include <ctype.h>
@ -258,7 +258,7 @@ const char* NormalizePath(NulibState* pState, NuPathnameProposal* pPathProposal)
Assert(pState != NULL); Assert(pState != NULL);
Assert(pPathProposal != NULL); Assert(pPathProposal != NULL);
Assert(pPathProposal->pathname != NULL); Assert(pPathProposal->pathnameUNI != NULL);
localFssep = NState_GetSystemPathSeparator(pState); localFssep = NState_GetSystemPathSeparator(pState);
@ -267,14 +267,14 @@ const char* NormalizePath(NulibState* pState, NuPathnameProposal* pPathProposal)
* requires converting all chars to '%' codes and adding the longest * requires converting all chars to '%' codes and adding the longest
* possible preservation string. * possible preservation string.
*/ */
newBufLen = strlen(pPathProposal->pathname)*3 + kMaxPathGrowth +1; newBufLen = strlen(pPathProposal->pathnameUNI)*3 + kMaxPathGrowth +1;
NState_SetTempPathnameLen(pState, newBufLen); NState_SetTempPathnameLen(pState, newBufLen);
pathBuf = NState_GetTempPathnameBuf(pState); pathBuf = NState_GetTempPathnameBuf(pState);
Assert(pathBuf != NULL); Assert(pathBuf != NULL);
if (pathBuf == NULL) if (pathBuf == NULL)
return NULL; return NULL;
startp = pPathProposal->pathname; startp = pPathProposal->pathnameUNI;
dstp = pathBuf; dstp = pathBuf;
while (*startp == pPathProposal->filenameSeparator) { while (*startp == pPathProposal->filenameSeparator) {
/* ignore leading path sep; always extract to current dir */ /* ignore leading path sep; always extract to current dir */
@ -317,7 +317,7 @@ const char* NormalizePath(NulibState* pState, NuPathnameProposal* pPathProposal)
} }
} }
pPathProposal->newPathname = pathBuf; pPathProposal->newPathnameUNI = pathBuf;
pPathProposal->newFilenameSeparator = localFssep; pPathProposal->newFilenameSeparator = localFssep;
/* check for overflow */ /* check for overflow */

View File

@ -1,12 +1,12 @@
/* /*
* Nulib2 * NuLib2
* Copyright (C) 2000-2007 by Andy McFadden, All Rights Reserved. * Copyright (C) 2000-2007 by Andy McFadden, All Rights Reserved.
* This is free software; you can redistribute it and/or modify it under the * This is free software; you can redistribute it and/or modify it under the
* terms of the BSD License, see the file COPYING. * terms of the BSD License, see the file COPYING.
* *
* List files in the archive. * List files in the archive.
*/ */
#include "Nulib2.h" #include "NuLib2.h"
/* kinds of records */ /* kinds of records */
@ -111,8 +111,9 @@ static NuResult ShowContentsShort(NuArchive* pArchive, void* vpRecord)
if (!IsSpecified(pState, pRecord)) if (!IsSpecified(pState, pRecord))
goto bail; goto bail;
printf("%s\n", UNICHAR* filenameUNI = CopyMORToUNI(pRecord->filenameMOR);
pRecord->filename == NULL ? "<unknown>":(const char*)pRecord->filename); printf("%s\n", filenameUNI == NULL ? "<unknown>" : filenameUNI);
free(filenameUNI);
bail: bail:
return kNuOK; return kNuOK;
@ -209,14 +210,32 @@ static NuResult ShowContentsVerbose(NuArchive* pArchive, void* vpRecord)
if (err != kNuErrNone) if (err != kNuErrNone)
goto bail; goto bail;
len = strlen(pRecord->filename); /*
* Display the filename, truncating if it's longer than 27 characters.
*
* Attempting to do column layout with printf string formatting (e.g.
* "%-27s") doesn't really work for UTF-8 because printf() is
* operating on bytes, and the conversion to a Unicode code point
* is happening in the terminal. We need to do the spacing ourselves,
* using the fact that one MOR character turns into one Unicode character.
*
* If the display isn't converting multi-byte sequences to individual
* characters, this won't look right, but we can't make everybody happy.
*/
static const char kSpaces[27+1] = " ";
UNICHAR* filenameUNI;
len = strlen(pRecord->filenameMOR);
if (len <= 27) { if (len <= 27) {
printf("%c%-27.27s ", IsRecordReadOnly(pRecord) ? '+' : ' ', filenameUNI = CopyMORToUNI(pRecord->filenameMOR);
pRecord->filename); printf("%c%s%s ", IsRecordReadOnly(pRecord) ? '+' : ' ',
filenameUNI, &kSpaces[len]);
} else { } else {
printf("%c..%-25.25s ", IsRecordReadOnly(pRecord) ? '+' : ' ', filenameUNI = CopyMORToUNI(pRecord->filenameMOR + len - 25);
pRecord->filename + len - 25); printf("%c..%s ", IsRecordReadOnly(pRecord) ? '+' : ' ',
filenameUNI);
} }
free(filenameUNI);
switch (recordKind) { switch (recordKind) {
case kRecordKindUnknown: case kRecordKindUnknown:
printf("%s- $%04X ", printf("%s- $%04X ",
@ -266,8 +285,10 @@ static NuResult ShowContentsVerbose(NuArchive* pArchive, void* vpRecord)
bail: bail:
if (err != kNuErrNone) { if (err != kNuErrNone) {
printf("(ERROR on '%s')\n", pRecord->filename == NULL ? filenameUNI = CopyMORToUNI(pRecord->filenameMOR);
"<unknown>" : (const char*)pRecord->filename); printf("(ERROR on '%s')\n",
filenameUNI == NULL ? "<unknown>" : filenameUNI);
free(filenameUNI);
} }
return kNuOK; return kNuOK;
} }

View File

@ -1,19 +1,19 @@
/* /*
* Nulib2 * NuLib2
* Copyright (C) 2000-2007 by Andy McFadden, All Rights Reserved. * Copyright (C) 2000-2007 by Andy McFadden, All Rights Reserved.
* This is free software; you can redistribute it and/or modify it under the * This is free software; you can redistribute it and/or modify it under the
* terms of the BSD License, see the file COPYING. * terms of the BSD License, see the file COPYING.
* *
* Main entry point and shell command argument processing. * Main entry point and shell command argument processing.
*/ */
#include "Nulib2.h" #include "NuLib2.h"
#include <ctype.h> #include <ctype.h>
/* /*
* Globals and constants. * Globals and constants.
*/ */
const char* gProgName = "Nulib2"; const char* gProgName = "NuLib2";
/* /*
@ -133,14 +133,14 @@ static const char* GetProgName(const NulibState* pState, const char* argv0)
*/ */
static void Usage(const NulibState* pState) static void Usage(const NulibState* pState)
{ {
long majorVersion, minorVersion, bugVersion; int32_t majorVersion, minorVersion, bugVersion;
const char* nufxLibDate; const char* nufxLibDate;
const char* nufxLibFlags; const char* nufxLibFlags;
(void) NuGetVersion(&majorVersion, &minorVersion, &bugVersion, (void) NuGetVersion(&majorVersion, &minorVersion, &bugVersion,
&nufxLibDate, &nufxLibFlags); &nufxLibDate, &nufxLibFlags);
printf("\nNulib2 v%s, linked with NufxLib v%ld.%ld.%ld [%s]\n", printf("\nNuLib2 v%s, linked with NufxLib v%d.%d.%d [%s]\n",
NState_GetProgramVersion(pState), NState_GetProgramVersion(pState),
majorVersion, minorVersion, bugVersion, nufxLibFlags); majorVersion, minorVersion, bugVersion, nufxLibFlags);
printf("Copyright (C) 2000-2014, Andy McFadden. All Rights Reserved.\n"); printf("Copyright (C) 2000-2014, Andy McFadden. All Rights Reserved.\n");
@ -552,13 +552,13 @@ int DoWork(NulibState* pState)
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
NulibState* pState = NULL; NulibState* pState = NULL;
long majorVersion, minorVersion, bugVersion; int32_t majorVersion, minorVersion, bugVersion;
int result = 0; int result = 0;
(void) NuGetVersion(&majorVersion, &minorVersion, &bugVersion, NULL, NULL); (void) NuGetVersion(&majorVersion, &minorVersion, &bugVersion, NULL, NULL);
if (majorVersion != kNuVersionMajor || minorVersion < kNuVersionMinor) { if (majorVersion != kNuVersionMajor || minorVersion < kNuVersionMinor) {
fprintf(stderr, "ERROR: wrong version of NufxLib --" fprintf(stderr, "ERROR: wrong version of NufxLib --"
" wanted %d.%d.x, got %ld.%ld.%ld.\n", " wanted %d.%d.x, got %d.%d.%d.\n",
kNuVersionMajor, kNuVersionMinor, kNuVersionMajor, kNuVersionMinor,
majorVersion, minorVersion, bugVersion); majorVersion, minorVersion, bugVersion);
goto bail; goto bail;

View File

@ -141,8 +141,19 @@ baktar:
@gzip -9 nulib2.tar @gzip -9 nulib2.tar
@mv -i nulib2.tar.gz /home/fadden/BAK/ @mv -i nulib2.tar.gz /home/fadden/BAK/
depend: # dependency info
makedepend -- $(CFLAGS) -- $(SRCS) COMMON_HDRS = NuLib2.h SysDefs.h State.h MiscStuff.h config.h \
$(NUFXSRCDIR)/NufxLib.h
# DO NOT DELETE THIS LINE -- make depend depends on it. Add.o: Add.c $(COMMON_HDRS)
ArcUtils.o: ArcUtils.c $(COMMON_HDRS)
Binary2.o: Binary2.c $(COMMON_HDRS)
Delete.o: Delete.c $(COMMON_HDRS)
Extract.o: Extract.c $(COMMON_HDRS)
Filename.o: Filename.c $(COMMON_HDRS)
List.o: List.c $(COMMON_HDRS)
Main.o: Main.c $(COMMON_HDRS)
MiscStuff.o: MiscStuff.c $(COMMON_HDRS)
MiscUtils.o: MiscUtils.c $(COMMON_HDRS)
State.o: State.c $(COMMON_HDRS)
SysUtils.o: SysUtils.c $(COMMON_HDRS)

View File

@ -1,13 +1,12 @@
/* /*
* Nulib2 * NuLib2
* Copyright (C) 2000-2007 by Andy McFadden, All Rights Reserved. * Copyright (C) 2000-2007 by Andy McFadden, All Rights Reserved.
* This is free software; you can redistribute it and/or modify it under the * This is free software; you can redistribute it and/or modify it under the
* terms of the BSD License, see the file COPYING. * terms of the BSD License, see the file COPYING.
* *
* Misc support functions. * Misc support functions.
*/ */
#define __MiscUtils_c__ #include "NuLib2.h"
#include "Nulib2.h"
/* /*
@ -113,3 +112,27 @@ NuResult FreeCallback(NuArchive* pArchive, void* args)
return kNuOK; return kNuOK;
} }
/*
* Convert Mac OS Roman to Unicode. The caller must free the string
* returned.
*
* Returns NULL if stringMOR is NULL or if the conversion fails.
*/
UNICHAR* CopyMORToUNI(const char* stringMOR)
{
size_t uniLen;
UNICHAR* uniBuf;
if (stringMOR == NULL) {
return NULL;
}
uniLen = NuConvertMORToUNI(stringMOR, NULL, 0);
if (uniLen == (size_t) -1) {
return NULL;
}
uniBuf = (UNICHAR*) malloc(uniLen);
NuConvertMORToUNI(stringMOR, uniBuf, uniLen);
return uniBuf;
}

View File

@ -1,5 +1,5 @@
/* /*
* Nulib2 * NuLib2
* Copyright (C) 2000-2007 by Andy McFadden, All Rights Reserved. * Copyright (C) 2000-2007 by Andy McFadden, All Rights Reserved.
* This is free software; you can redistribute it and/or modify it under the * This is free software; you can redistribute it and/or modify it under the
* terms of the BSD License, see the file COPYING. * terms of the BSD License, see the file COPYING.
@ -98,6 +98,7 @@ void* Realloc(void* ptr, size_t size);
void Free(void* ptr); void Free(void* ptr);
#endif #endif
NuResult FreeCallback(NuArchive* pArchive, void* args); NuResult FreeCallback(NuArchive* pArchive, void* args);
UNICHAR* CopyMORToUNI(const char* stringMOR);
/* SysUtils.c */ /* SysUtils.c */
NuError NormalizeFileName(NulibState* pState, const char* srcp, long srcLen, NuError NormalizeFileName(NulibState* pState, const char* srcp, long srcLen,

View File

@ -1,19 +1,19 @@
/* /*
* Nulib2 * NuLib2
* Copyright (C) 2000-2007 by Andy McFadden, All Rights Reserved. * Copyright (C) 2000-2007 by Andy McFadden, All Rights Reserved.
* This is free software; you can redistribute it and/or modify it under the * This is free software; you can redistribute it and/or modify it under the
* terms of the BSD License, see the file COPYING. * terms of the BSD License, see the file COPYING.
* *
* Global-ish state object. * Global-ish state object.
*/ */
#include "Nulib2.h" #include "NuLib2.h"
static const char* gProgramVersion = "2.3.0"; static const char* gProgramVersion = "3.0.0";
/* /*
* Allocate and initialize the semi-global Nulib2 state object. * Allocate and initialize the semi-global NuLib2 state object.
*/ */
NuError NState_Init(NulibState** ppState) NuError NState_Init(NulibState** ppState)
{ {

View File

@ -1,5 +1,5 @@
/* /*
* Nulib2 * NuLib2
* Copyright (C) 2000-2007 by Andy McFadden, All Rights Reserved. * Copyright (C) 2000-2007 by Andy McFadden, All Rights Reserved.
* This is free software; you can redistribute it and/or modify it under the * This is free software; you can redistribute it and/or modify it under the
* terms of the BSD License, see the file COPYING. * terms of the BSD License, see the file COPYING.
@ -11,7 +11,7 @@
#include "NufxLib.h" #include "NufxLib.h"
/* /*
* Things you can tell Nulib2 to do. * Things you can tell NuLib2 to do.
* *
* (Some debug code in NState_DebugDump() is sensitive to the order here.) * (Some debug code in NState_DebugDump() is sensitive to the order here.)
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Nulib2 * NuLib2
* Copyright (C) 2000-2007 by Andy McFadden, All Rights Reserved. * Copyright (C) 2000-2007 by Andy McFadden, All Rights Reserved.
* This is free software; you can redistribute it and/or modify it under the * This is free software; you can redistribute it and/or modify it under the
* terms of the BSD License, see the file COPYING. * terms of the BSD License, see the file COPYING.

View File

@ -1,12 +1,12 @@
/* /*
* Nulib2 * NuLib2
* Copyright (C) 2000-2007 by Andy McFadden, All Rights Reserved. * Copyright (C) 2000-2007 by Andy McFadden, All Rights Reserved.
* This is free software; you can redistribute it and/or modify it under the * This is free software; you can redistribute it and/or modify it under the
* terms of the BSD License, see the file COPYING. * terms of the BSD License, see the file COPYING.
* *
* System-dependent utility functions. * System-dependent utility functions.
*/ */
#include "Nulib2.h" #include "NuLib2.h"
#ifdef HAVE_WINDOWS_H #ifdef HAVE_WINDOWS_H
# include <windows.h> # include <windows.h>
@ -431,7 +431,7 @@ static void ReplaceFssep(char* str, char oldc, char newc, char newSubst)
* Set the contents of a NuFileDetails structure, based on the pathname * Set the contents of a NuFileDetails structure, based on the pathname
* and characteristics of the file. * and characteristics of the file.
*/ */
static NuError GetFileDetails(NulibState* pState, const char* pathname, static NuError GetFileDetails(NulibState* pState, const char* pathnameMOR,
struct stat* psb, NuFileDetails* pDetails) struct stat* psb, NuFileDetails* pDetails)
{ {
Boolean wasPreserved; Boolean wasPreserved;
@ -442,14 +442,14 @@ static NuError GetFileDetails(NulibState* pState, const char* pathname,
time_t now; time_t now;
Assert(pState != NULL); Assert(pState != NULL);
Assert(pathname != NULL); Assert(pathnameMOR != NULL);
Assert(pDetails != NULL); Assert(pDetails != NULL);
/* set up the pathname buffer; note pDetails->storageName is const */ /* set up the pathname buffer; note pDetails->storageName is const */
NState_SetTempPathnameLen(pState, strlen(pathname) +1); NState_SetTempPathnameLen(pState, strlen(pathnameMOR) +1);
livePathStr = NState_GetTempPathnameBuf(pState); livePathStr = NState_GetTempPathnameBuf(pState);
Assert(livePathStr != NULL); Assert(livePathStr != NULL);
strcpy(livePathStr, pathname); strcpy(livePathStr, pathnameMOR);
/* under Win32, both '/' and '\' work... we want to settle on one */ /* under Win32, both '/' and '\' work... we want to settle on one */
if (NState_GetAltSystemPathSeparator(pState) != '\0') { if (NState_GetAltSystemPathSeparator(pState) != '\0') {
@ -462,7 +462,7 @@ static NuError GetFileDetails(NulibState* pState, const char* pathname,
/* init to defaults */ /* init to defaults */
memset(pDetails, 0, sizeof(*pDetails)); memset(pDetails, 0, sizeof(*pDetails));
pDetails->threadID = kNuThreadIDDataFork; pDetails->threadID = kNuThreadIDDataFork;
pDetails->storageName = livePathStr; /* point at temp buffer */ pDetails->storageNameMOR = livePathStr; /* point at temp buffer */
pDetails->origName = NULL; pDetails->origName = NULL;
pDetails->fileSysID = kNuFileSysUnknown; pDetails->fileSysID = kNuFileSysUnknown;
pDetails->fileSysInfo = kStorageFssep; pDetails->fileSysInfo = kStorageFssep;