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/test-basic
samples/test-extract
samples/test-names
samples/test-simple
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->newRecordSet);
Nu_Free(NULL, pArchive->archivePathname);
Nu_Free(NULL, pArchive->tmpPathname);
Nu_Free(NULL, pArchive->archivePathnameUNI);
Nu_Free(NULL, pArchive->tmpPathnameUNI);
Nu_Free(NULL, pArchive->compBuf);
Nu_Free(NULL, pArchive->lzwCompressState);
Nu_Free(NULL, pArchive->lzwExpandState);
@ -743,7 +743,7 @@ NuError Nu_StreamOpenRO(FILE* infp, NuArchive** ppArchive)
pArchive->openMode = kNuOpenStreamingRO;
pArchive->archiveFp = infp;
pArchive->archivePathname = strdup("(stream)");
pArchive->archivePathnameUNI = strdup("(stream)");
err = Nu_ReadMasterHeader(pArchive);
BailError(err);
@ -761,20 +761,24 @@ bail:
/*
* 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;
NuArchive* pArchive = NULL;
FILE* fp = NULL;
if (archivePathname == NULL || !strlen(archivePathname) || ppArchive == NULL)
if (archivePathnameUNI == NULL || !strlen(archivePathnameUNI) ||
ppArchive == NULL)
{
return kNuErrInvalidArg;
}
*ppArchive = NULL;
fp = fopen(archivePathname, kNuFileOpenReadOnly);
fp = fopen(archivePathnameUNI, kNuFileOpenReadOnly);
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;
goto bail;
}
@ -787,7 +791,7 @@ NuError Nu_OpenRO(const char* archivePathname, NuArchive** ppArchive)
pArchive->openMode = kNuOpenRO;
pArchive->archiveFp = fp;
fp = NULL;
pArchive->archivePathname = strdup(archivePathname);
pArchive->archivePathnameUNI = strdup(archivePathnameUNI);
err = Nu_ReadMasterHeader(pArchive);
BailError(err);
@ -807,12 +811,13 @@ bail:
/*
* 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
* 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 */
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
* things.
*/
len = strlen(fileName);
if (len > 6 && strcmp(fileName + len - 6, "XXXXXX") == 0) {
len = strlen(fileNameUNI);
if (len > 6 && strcmp(fileNameUNI + len - 6, "XXXXXX") == 0) {
#if defined(HAVE_MKSTEMP) && defined(HAVE_FDOPEN)
int fd;
DBUG(("+++ Using mkstemp\n"));
/* this modifies the template *and* opens the file */
fd = mkstemp(fileName);
fd = mkstemp(fileNameUNI);
if (fd < 0) {
err = errno ? errno : kNuErrFileOpen;
Nu_ReportError(NU_BLOB, kNuErrNone, "mkstemp failed on '%s'",
fileName);
fileNameUNI);
goto bail;
}
DBUG(("--- Fd-opening temp file '%s'\n", fileName));
DBUG(("--- Fd-opening temp file '%s'\n", fileNameUNI));
*pFp = fdopen(fd, kNuFileOpenReadWriteCreat);
if (*pFp == NULL) {
close(fd);
@ -858,10 +863,10 @@ static NuError Nu_OpenTempFile(char* fileName, FILE** pFp)
char* result;
DBUG(("+++ Using mktemp\n"));
result = mktemp(fileName);
result = mktemp(fileNameUNI);
if (result == NULL) {
Nu_ReportError(NU_BLOB, kNuErrNone, "mktemp failed on '%s'",
fileName);
fileNameUNI);
err = kNuErrInternal;
goto bail;
}
@ -870,13 +875,13 @@ static NuError Nu_OpenTempFile(char* fileName, FILE** pFp)
#endif
}
DBUG(("--- Opening temp file '%s'\n", fileName));
DBUG(("--- Opening temp file '%s'\n", fileNameUNI));
#if defined(HAVE_FDOPEN)
{
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) {
err = errno ? errno : kNuErrFileOpen;
goto bail;
@ -890,13 +895,12 @@ static NuError Nu_OpenTempFile(char* fileName, FILE** pFp)
}
}
#else
/* (not sure how portable "access" is... I think it's POSIX) */
if (access(fileName, F_OK) == 0) {
if (access(fileNameUNI, F_OK) == 0) {
err = kNuErrFileExists;
goto bail;
}
*pFp = fopen(fileName, kNuFileOpenReadWriteCreat);
*pFp = fopen(fileNameUNI, kNuFileOpenReadWriteCreat);
if (*pFp == NULL) {
err = errno ? errno : kNuErrFileOpen;
goto bail;
@ -912,8 +916,8 @@ bail:
* Open an archive in read-write mode, optionally creating it if it doesn't
* exist.
*/
NuError Nu_OpenRW(const char* archivePathname, const char* tmpPathname,
uint32_t flags, NuArchive** ppArchive)
NuError Nu_OpenRW(const UNICHAR* archivePathnameUNI,
const UNICHAR* tmpPathnameUNI, uint32_t flags, NuArchive** ppArchive)
{
NuError err;
FILE* fp = NULL;
@ -923,14 +927,14 @@ NuError Nu_OpenRW(const char* archivePathname, const char* tmpPathname,
Boolean archiveExists;
Boolean newlyCreated;
if (archivePathname == NULL || !strlen(archivePathname) ||
tmpPathname == NULL || !strlen(tmpPathname) || ppArchive == NULL ||
(flags & ~(kNuOpenCreat|kNuOpenExcl)) != 0)
if (archivePathnameUNI == NULL || !strlen(archivePathnameUNI) ||
tmpPathnameUNI == NULL || !strlen(tmpPathnameUNI) ||
ppArchive == NULL || (flags & ~(kNuOpenCreat|kNuOpenExcl)) != 0)
{
return kNuErrInvalidArg;
}
archiveExists = (access(archivePathname, F_OK) == 0);
archiveExists = (access(archivePathnameUNI, F_OK) == 0);
/*
* Open or create archive file.
@ -938,18 +942,20 @@ NuError Nu_OpenRW(const char* archivePathname, const char* tmpPathname,
if (archiveExists) {
if ((flags & kNuOpenCreat) && (flags & kNuOpenExcl)) {
err = kNuErrFileExists;
Nu_ReportError(NU_BLOB, err, "File '%s' exists", archivePathname);
Nu_ReportError(NU_BLOB, err, "File '%s' exists",
archivePathnameUNI);
goto bail;
}
fp = fopen(archivePathname, kNuFileOpenReadWrite);
fp = fopen(archivePathnameUNI, kNuFileOpenReadWrite);
newlyCreated = false;
} else {
if (!(flags & kNuOpenCreat)) {
err = kNuErrFileNotFound;
Nu_ReportError(NU_BLOB, err, "File '%s' not found",archivePathname);
Nu_ReportError(NU_BLOB, err, "File '%s' not found",
archivePathnameUNI);
goto bail;
}
fp = fopen(archivePathname, kNuFileOpenReadWriteCreat);
fp = fopen(archivePathnameUNI, kNuFileOpenReadWriteCreat);
newlyCreated = true;
}
@ -958,7 +964,8 @@ NuError Nu_OpenRW(const char* archivePathname, const char* tmpPathname,
err = kNuErrFileAccessDenied;
else
err = kNuErrFileOpen;
Nu_ReportError(NU_BLOB, errno, "Unable to open '%s'", archivePathname);
Nu_ReportError(NU_BLOB, errno, "Unable to open '%s'",
archivePathnameUNI);
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
* do any harm, and might save us some troubles later.
*/
tmpPathDup = strdup(tmpPathname);
tmpPathDup = strdup(tmpPathnameUNI);
BailNil(tmpPathDup);
err = Nu_OpenTempFile(tmpPathDup, &tmpFp);
if (err != kNuErrNone) {
Nu_ReportError(NU_BLOB, err, "Failed opening temp file '%s'",
tmpPathname);
tmpPathnameUNI);
goto bail;
}
@ -1002,12 +1009,12 @@ NuError Nu_OpenRW(const char* archivePathname, const char* tmpPathname,
pArchive->openMode = kNuOpenRW;
pArchive->newlyCreated = newlyCreated;
pArchive->archivePathname = strdup(archivePathname);
pArchive->archivePathnameUNI = strdup(archivePathnameUNI);
pArchive->archiveFp = fp;
fp = NULL;
pArchive->tmpFp = tmpFp;
tmpFp = NULL;
pArchive->tmpPathname = tmpPathDup;
pArchive->tmpPathnameUNI = tmpPathDup;
tmpPathDup = NULL;
if (archiveExists && !newlyCreated) {
@ -1116,10 +1123,10 @@ static void Nu_CloseAndFree(NuArchive* pArchive)
DBUG(("--- Closing and removing temp file\n"));
fclose(pArchive->tmpFp);
pArchive->tmpFp = NULL;
Assert(pArchive->tmpPathname != NULL);
if (remove(pArchive->tmpPathname) != 0) {
Assert(pArchive->tmpPathnameUNI != NULL);
if (remove(pArchive->tmpPathnameUNI) != 0) {
Nu_ReportError(NU_BLOB, errno, "Unable to remove temp file '%s'",
pArchive->tmpPathname);
pArchive->tmpPathnameUNI);
/* keep going */
}
}
@ -1127,9 +1134,9 @@ static void Nu_CloseAndFree(NuArchive* pArchive)
if (pArchive->newlyCreated && Nu_RecordSet_IsEmpty(&pArchive->origRecordSet))
{
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'",
pArchive->archivePathname);
pArchive->archivePathnameUNI);
}
}
@ -1142,7 +1149,7 @@ static void Nu_CloseAndFree(NuArchive* pArchive)
NuError Nu_Close(NuArchive* pArchive)
{
NuError err = kNuErrNone;
long flushStatus;
uint32_t flushStatus;
Assert(pArchive != NULL);
@ -1174,9 +1181,9 @@ NuError Nu_DeleteArchiveFile(NuArchive* pArchive)
{
Assert(pArchive != 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->archiveFp == NULL);
Assert(pArchive->tmpFp == NULL);
Assert(pArchive->archivePathname != NULL);
Assert(pArchive->tmpPathname != NULL);
Assert(pArchive->archivePathnameUNI != 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:
if (outbuf != NULL)
free(outbuf);
Nu_Free(NULL, outbuf);
return err;
}
@ -289,7 +289,7 @@ bz_bail:
bail:
if (outbuf != NULL)
free(outbuf);
Nu_Free(NULL, outbuf);
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
* might be slower than the loop computation.
*/
#define __Crc16_c__ 1
#define COMPILE_CRC16_C 1
#include "NufxLibPriv.h"
#define CRC_TAB

View File

@ -161,9 +161,9 @@ void Nu_DebugDumpThread(const NuThread* pThread)
printf("%sThreadKind: 0x%04x (%s)\n", kInd,
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);
printf("%s*File data offset: %ld actualThreadEOF: %ld\n", kInd,
printf("%s*File data offset: %ld actualThreadEOF: %d\n", kInd,
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,
(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] " : "",
pXrefRecord != NULL && pXrefRecord->pThreadMods != NULL ? "[MOD] " : "",
pRecord->filename == NULL ? "<not specified>" : pRecord->filename,
filenameUNI == NULL ? "<not specified>" : filenameUNI,
pRecord->recordIdx);
free(filenameUNI);
printf("%sHeaderID: '%.4s' VersionNumber: 0x%04x HeaderCRC: 0x%04x\n",
kInd,
pRecord->recNufxID, pRecord->recVersionNumber, pRecord->recHeaderCRC);
printf("%sAttribCount: %u TotalThreads: %lu\n", kInd,
printf("%sAttribCount: %u TotalThreads: %u\n", kInd,
pRecord->recAttribCount, pRecord->recTotalThreads);
printf("%sFileSysID: %u (%s) FileSysInfo: 0x%04x ('%c')\n", kInd,
pRecord->recFileSysID,
@ -205,7 +207,7 @@ static void Nu_DebugDumpRecord(NuArchive* pArchive, const NuRecord* pRecord,
pRecord->recFileSysInfo,
NuGetSepFromSysInfo(pRecord->recFileSysInfo));
/* 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);
printf("%sCreateWhen: %s\n", kInd,
Nu_DebugDumpDate(&pRecord->recCreateWhen, dateBuf));
@ -225,7 +227,7 @@ static void Nu_DebugDumpRecord(NuArchive* pArchive, const NuRecord* pRecord,
Nu_Free(pArchive, outBuf);
}
printf("%s*ExtraCount: %ld RecFileOffset: %ld RecHeaderLength: %ld\n",
printf("%s*ExtraCount: %d RecFileOffset: %ld RecHeaderLength: %d\n",
kInd,
pRecord->extraCount, pRecord->fileOffset, pRecord->recHeaderLength);
@ -236,7 +238,7 @@ static void Nu_DebugDumpRecord(NuArchive* pArchive, const NuRecord* pRecord,
pThread = Nu_GetThread(pRecord, idx);
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]" : "");
Nu_DebugDumpThread(pThread);
}
@ -251,17 +253,17 @@ static void Nu_DebugDumpRecord(NuArchive* pArchive, const NuRecord* pRecord,
while (pThreadMod != NULL) {
switch (pThreadMod->entry.kind) {
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.threadFormat,
Nu_DataSourceGetType(pThreadMod->entry.add.pDataSource));
break;
case kNuThreadModUpdate:
printf("%s *-ThreadMod UPDATE %6ld\n", kInd,
printf("%s *-ThreadMod UPDATE %6d\n", kInd,
pThreadMod->entry.update.threadIdx);
break;
case kNuThreadModDelete:
printf("%s *-ThreadMod DELETE %6ld\n", kInd,
printf("%s *-ThreadMod DELETE %6d\n", kInd,
pThreadMod->entry.delete.threadIdx);
break;
case kNuThreadModUnknown:
@ -276,7 +278,7 @@ static void Nu_DebugDumpRecord(NuArchive* pArchive, const NuRecord* pRecord,
/*printf("%s*TotalLength: %ld TotalCompLength: %ld\n",
kInd, pRecord->totalLength, pRecord->totalCompLength);*/
printf("%s*TotalCompLength: %ld\n", kInd, pRecord->totalCompLength);
printf("%s*TotalCompLength: %u\n", kInd, pRecord->totalCompLength);
printf("\n");
bail:
@ -334,14 +336,14 @@ static void Nu_DebugDumpMH(const NuMasterHeader* pMasterHeader)
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->mhTotalRecords);
printf("%sArchiveCreateWhen: %s\n", kInd,
Nu_DebugDumpDate(&pMasterHeader->mhArchiveCreateWhen, dateBuf1));
printf("%sArchiveModWhen: %s\n", kInd,
Nu_DebugDumpDate(&pMasterHeader->mhArchiveModWhen, dateBuf1));
printf("%sMasterVersion: %u MasterEOF: %lu\n", kInd,
printf("%sMasterVersion: %u MasterEOF: %u\n", kInd,
pMasterHeader->mhMasterVersion, pMasterHeader->mhMasterEOF);
}
@ -357,15 +359,15 @@ void Nu_DebugDumpAll(NuArchive* pArchive)
{
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("*Header offset: %ld (junk offset=%ld)\n",
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->copyRecordSet),
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);
/* 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
* successfully completed.
*
* "newName" must be allocated storage.
* "newName" must be allocated storage, Mac OS Roman charset.
*/
static void Nu_SetNewThreadFilename(NuArchive* pArchive, NuRecord* pRecord,
char* newName)
char* newNameMOR)
{
Assert(pRecord != NULL);
Assert(newName != NULL);
Assert(newNameMOR != NULL);
Nu_Free(pArchive, pRecord->threadFilename);
pRecord->threadFilename = newName;
pRecord->filename = pRecord->threadFilename;
Nu_Free(pArchive, pRecord->threadFilenameMOR);
pRecord->threadFilenameMOR = newNameMOR;
pRecord->filenameMOR = pRecord->threadFilenameMOR;
}
/*
@ -647,14 +647,14 @@ static NuError Nu_ConstructArchiveUpdate(NuArchive* pArchive, FILE* fp,
if (NuGetThreadID(pThread) == kNuThreadIDFilename) {
/* special handling for filename updates */
char* savedCopy = NULL;
char* savedCopyMOR = NULL;
err = Nu_CopyPresizedToArchive(pArchive, pDataSource,
NuGetThreadID(pThread), fp, pThread, &savedCopy);
NuGetThreadID(pThread), fp, pThread, &savedCopyMOR);
if (err != kNuErrNone) {
Nu_ReportError(NU_BLOB, err, "thread update failed");
goto bail;
}
Nu_SetNewThreadFilename(pArchive, pRecord, savedCopy);
Nu_SetNewThreadFilename(pArchive, pRecord, savedCopyMOR);
} else {
err = Nu_CopyPresizedToArchive(pArchive, pDataSource,
@ -700,6 +700,7 @@ static NuError Nu_HandleAddThreadMods(NuArchive* pArchive, NuRecord* pRecord,
NuProgressData* pProgressData;
NuThreadMod* pThreadMod;
NuThread* pNewThread;
UNICHAR* pathnameUNIStorage = NULL;
Boolean foundOne = false;
/*
@ -747,17 +748,19 @@ static NuError Nu_HandleAddThreadMods(NuArchive* pArchive, NuRecord* pRecord,
* Do something different here for data sinks with
* filenames attached. ++ATM 2003/02/17]
*/
pathnameUNIStorage = Nu_CopyMORToUNI(pRecord->filenameMOR);
if (Nu_DataSourceGetType(pThreadMod->entry.add.pDataSource)
== kNuDataSourceFromFile)
{
/* use on-disk filename */
err = Nu_ProgressDataInit_Compress(pArchive, &progressData,
pRecord, Nu_DataSourceFile_GetPathname(
pThreadMod->entry.add.pDataSource));
pThreadMod->entry.add.pDataSource),
pathnameUNIStorage);
} else {
/* use archive filename for both */
err = Nu_ProgressDataInit_Compress(pArchive, &progressData,
pRecord, pRecord->filename);
pRecord, pathnameUNIStorage, pathnameUNIStorage);
}
BailError(err);
@ -820,14 +823,14 @@ static NuError Nu_HandleAddThreadMods(NuArchive* pArchive, NuRecord* pRecord,
if (pThreadMod->entry.add.threadID == kNuThreadIDFilename) {
/* filenames are special */
char* savedCopy = NULL;
char* savedCopyMOR = NULL;
Assert(pThreadMod->entry.add.threadFormat ==
kNuThreadFormatUncompressed);
err = Nu_CopyPresizedToArchive(pArchive,
pThreadMod->entry.add.pDataSource,
pThreadMod->entry.add.threadID,
dstFp, pNewThread, &savedCopy);
dstFp, pNewThread, &savedCopyMOR);
if (err != kNuErrNone) {
Nu_ReportError(NU_BLOB, err, "fn thread add failed");
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
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) {
/* don't compress, just copy */
@ -874,6 +877,7 @@ static NuError Nu_HandleAddThreadMods(NuArchive* pArchive, NuRecord* pRecord,
}
bail:
Nu_Free(pArchive, pathnameUNIStorage);
return err;
}
@ -1081,24 +1085,25 @@ static NuError Nu_ConstructArchiveRecord(NuArchive* pArchive, NuRecord* pRecord)
/*
* Handle filename deletion.
*/
if (!numFilenameThreads && pRecord->threadFilename) {
if (!numFilenameThreads && pRecord->threadFilenameMOR != NULL) {
/* looks like a previously existing filename thread got removed */
DBUG(("--- Dropping thread filename '%s'\n", pRecord->threadFilename));
if (pRecord->filename == pRecord->threadFilename)
pRecord->filename = NULL; /* don't point at freed memory! */
Nu_Free(pArchive, pRecord->threadFilename);
pRecord->threadFilename = NULL;
DBUG(("--- Dropping thread filename '%s'\n",
pRecord->threadFilenameMOR));
if (pRecord->filenameMOR == pRecord->threadFilenameMOR)
pRecord->filenameMOR = NULL; /* don't point at freed memory! */
Nu_Free(pArchive, pRecord->threadFilenameMOR);
pRecord->threadFilenameMOR = NULL;
/* 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)
{
DBUG(("--- HEY, how did this happen?\n"));
pRecord->filename = pRecord->recFilename;
pRecord->filenameMOR = pRecord->recFilenameMOR;
}
}
if (pRecord->filename == NULL)
pRecord->filename = kNuDefaultRecordName;
if (pRecord->filenameMOR == NULL)
pRecord->filenameMOR = kNuDefaultRecordName;
/*
* 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
* filename. If somehow it didn't, assign a default.
*/
if (pRecord->filename == NULL) {
pRecord->newFilename = strdup(kNuDefaultRecordName);
pRecord->filename = pRecord->newFilename;
if (pRecord->filenameMOR == NULL) {
pRecord->newFilenameMOR = strdup(kNuDefaultRecordName);
pRecord->filenameMOR = pRecord->newFilenameMOR;
}
DBUG(("--- No filename thread found, adding one ('%s')\n",
pRecord->filename));
pRecord->filenameMOR));
/*
* 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
* leave some extra space on the end...?)
*/
len = strlen(pRecord->filename);
len = strlen(pRecord->filenameMOR);
maxLen = len > kNuDefaultFilenameThreadSize ?
len : kNuDefaultFilenameThreadSize;
err = Nu_DataSourceBuffer_New(kNuThreadFormatUncompressed,
maxLen, (const uint8_t*)pRecord->filename, 0,
strlen(pRecord->filename), NULL, &pTmpDataSource);
maxLen, (const uint8_t*)pRecord->filenameMOR, 0,
strlen(pRecord->filenameMOR), NULL, &pTmpDataSource);
BailError(err);
/* 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? */
Assert(pArchive != NULL);
Assert(pArchive->tmpPathname != NULL);
Assert(pArchive->tmpPathnameUNI != NULL);
#if 0 /* keep the temp file around for examination */
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 (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) {
err = errno ? errno : kNuErrFileOpen;
Nu_ReportError(NU_BLOB, errno, "Unable to open temp file '%s'",
pArchive->tmpPathname);
pArchive->tmpPathnameUNI);
goto bail;
}
} else {
@ -1933,19 +1941,20 @@ if (pArchive->tmpFp != NULL) {
/* do it the hard way if we don't have ftruncate or equivalent */
err = kNuErrNone;
fclose(pArchive->tmpFp);
pArchive->tmpFp = fopen(pArchive->tmpPathname, kNuFileOpenWriteTrunc);
pArchive->tmpFp = fopen(pArchive->tmpPathnameUNI,
kNuFileOpenWriteTrunc);
if (pArchive->tmpFp == NULL) {
err = errno ? errno : kNuErrFileOpen;
Nu_ReportError(NU_BLOB, err, "failed truncating tmp file");
goto bail;
}
fclose(pArchive->tmpFp);
pArchive->tmpFp =
fopen(pArchive->tmpPathname, kNuFileOpenReadWriteCreat);
pArchive->tmpFp = fopen(pArchive->tmpPathnameUNI,
kNuFileOpenReadWriteCreat);
if (pArchive->tmpFp == NULL) {
err = errno ? errno : kNuErrFileOpen;
Nu_ReportError(NU_BLOB, err, "Unable to open temp file '%s'",
pArchive->tmpPathname);
pArchive->tmpPathnameUNI);
goto bail;
}
}
@ -2110,7 +2119,7 @@ bail:
* If the things this function is doing aren't making any sense at all,
* read "NOTES.txt" for an introduction.
*/
NuError Nu_Flush(NuArchive* pArchive, long* pStatusFlags)
NuError Nu_Flush(NuArchive* pArchive, uint32_t* pStatusFlags)
{
NuError err = kNuErrNone;
Boolean canAbort = true;
@ -2388,7 +2397,7 @@ NuError Nu_Flush(NuArchive* pArchive, long* pStatusFlags)
if (err != kNuErrNone) {
Nu_ReportError(NU_BLOB, err, "unable to remove original archive");
Nu_ReportError(NU_BLOB, kNuErrNone, "New data is in '%s'",
pArchive->tmpPathname);
pArchive->tmpPathnameUNI);
*pStatusFlags |= kNuFlushInaccessible;
goto bail_reopen; /* must re-open archiveFp */
}
@ -2400,24 +2409,25 @@ NuError Nu_Flush(NuArchive* pArchive, long* pStatusFlags)
if (err != kNuErrNone) {
Nu_ReportError(NU_BLOB, err, "unable to rename temp file");
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) */
Nu_Free(pArchive, pArchive->archivePathname);
pArchive->archivePathname = NULL;
Nu_Free(pArchive, pArchive->tmpPathname);
pArchive->tmpPathname = NULL;
Nu_Free(pArchive, pArchive->archivePathnameUNI);
pArchive->archivePathnameUNI = NULL;
Nu_Free(pArchive, pArchive->tmpPathnameUNI);
pArchive->tmpPathnameUNI = NULL;
/* bail will put us into read-only mode, which is what we want */
goto bail;
}
bail_reopen:
pArchive->archiveFp = fopen(pArchive->archivePathname,
pArchive->archiveFp = fopen(pArchive->archivePathnameUNI,
kNuFileOpenReadWrite);
if (pArchive->archiveFp == NULL) {
err = errno ? errno : -1;
Nu_ReportError(NU_BLOB, err,
"unable to reopen archive file '%s' after rename",
pArchive->archivePathname);
pArchive->archivePathnameUNI);
*pStatusFlags |= kNuFlushInaccessible;
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 */
Assert(pArchive->archivePathname == NULL || pArchive->archiveFp != NULL);
if (pArchive->archivePathname != NULL && pArchive->archiveFp == NULL)
Assert(pArchive->archivePathnameUNI == NULL || pArchive->archiveFp != NULL);
if (pArchive->archivePathnameUNI != NULL && pArchive->archiveFp == NULL)
return kNuErrInternal;
Assert(pArchive->tmpPathname == NULL || pArchive->tmpFp != NULL);
if (pArchive->tmpPathname != NULL && pArchive->tmpFp == NULL)
Assert(pArchive->tmpPathnameUNI == NULL || pArchive->tmpFp != NULL);
if (pArchive->tmpPathnameUNI != NULL && pArchive->tmpFp == NULL)
return kNuErrInternal;
/* 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;
err = Nu_OpenRO(filename, (NuArchive**) ppArchive);
err = Nu_OpenRO(archivePathnameUNI, (NuArchive**) ppArchive);
return err;
}
@ -230,14 +231,14 @@ NUFXLIB_API NuError NuGetRecord(NuArchive* pArchive, NuRecordIdx recordIdx,
return err;
}
NUFXLIB_API NuError NuGetRecordIdxByName(NuArchive* pArchive, const char* name,
NuRecordIdx* pRecordIdx)
NUFXLIB_API NuError NuGetRecordIdxByName(NuArchive* pArchive,
const char* nameMOR, NuRecordIdx* pRecordIdx)
{
NuError err;
if ((err = Nu_ValidateNuArchive(pArchive)) == kNuErrNone) {
Nu_SetBusy(pArchive);
err = Nu_GetRecordIdxByName(pArchive, name, pRecordIdx);
err = Nu_GetRecordIdxByName(pArchive, nameMOR, pRecordIdx);
Nu_ClearBusy(pArchive);
}
@ -265,18 +266,18 @@ NUFXLIB_API NuError NuGetRecordIdxByPosition(NuArchive* pArchive, uint32_t posit
* ===========================================================================
*/
NUFXLIB_API NuError NuOpenRW(const char* archivePathname,
const char* tmpPathname, uint32_t flags, NuArchive** ppArchive)
NUFXLIB_API NuError NuOpenRW(const UNICHAR* archivePathnameUNI,
const UNICHAR* tmpPathnameUNI, uint32_t flags, NuArchive** ppArchive)
{
NuError err;
err = Nu_OpenRW(archivePathname, tmpPathname, flags,
err = Nu_OpenRW(archivePathnameUNI, tmpPathnameUNI, flags,
(NuArchive**) ppArchive);
return err;
}
NUFXLIB_API NuError NuFlush(NuArchive* pArchive, long* pStatusFlags)
NUFXLIB_API NuError NuFlush(NuArchive* pArchive, uint32_t* pStatusFlags)
{
NuError err;
@ -331,7 +332,7 @@ NUFXLIB_API NuError NuAddThread(NuArchive* pArchive, NuRecordIdx recordIdx,
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,
NuRecordIdx* pRecordIdx)
{
@ -339,7 +340,7 @@ NUFXLIB_API NuError NuAddFile(NuArchive* pArchive, const char* pathname,
if ((err = Nu_ValidateNuArchive(pArchive)) == kNuErrNone) {
Nu_SetBusy(pArchive);
err = Nu_AddFile(pArchive, pathname, pFileDetails,
err = Nu_AddFile(pArchive, pathnameUNI, pFileDetails,
(Boolean)(isFromRsrcFork != 0), pRecordIdx);
Nu_ClearBusy(pArchive);
}
@ -348,13 +349,13 @@ NUFXLIB_API NuError NuAddFile(NuArchive* pArchive, const char* pathname,
}
NUFXLIB_API NuError NuRename(NuArchive* pArchive, NuRecordIdx recordIdx,
const char* pathname, char fssep)
const char* pathnameMOR, char fssep)
{
NuError err;
if ((err = Nu_ValidateNuArchive(pArchive)) == kNuErrNone) {
Nu_SetBusy(pArchive);
err = Nu_Rename(pArchive, recordIdx, pathname, fssep);
err = Nu_Rename(pArchive, recordIdx, pathnameMOR, fssep);
Nu_ClearBusy(pArchive);
}
@ -377,7 +378,7 @@ NUFXLIB_API NuError NuSetRecordAttr(NuArchive* pArchive, NuRecordIdx recordIdx,
}
NUFXLIB_API NuError NuUpdatePresizedThread(NuArchive* pArchive,
NuThreadIdx threadIdx, NuDataSource* pDataSource, long* pMaxLen)
NuThreadIdx threadIdx, NuDataSource* pDataSource, int32_t* pMaxLen)
{
NuError err;
@ -538,11 +539,11 @@ NUFXLIB_API NuError NuDebugDumpArchive(NuArchive* pArchive)
*/
NUFXLIB_API NuError NuCreateDataSourceForFile(NuThreadFormat threadFormat,
uint32_t otherLen, const char* pathname, short isFromRsrcFork,
uint32_t otherLen, const UNICHAR* pathnameUNI, short isFromRsrcFork,
NuDataSource** ppDataSource)
{
return Nu_DataSourceFile_New(threadFormat, otherLen,
pathname, (Boolean)(isFromRsrcFork != 0), ppDataSource);
pathnameUNI, (Boolean)(isFromRsrcFork != 0), ppDataSource);
}
NUFXLIB_API NuError NuCreateDataSourceForFP(NuThreadFormat threadFormat,
@ -576,10 +577,10 @@ NUFXLIB_API NuError NuDataSourceSetRawCrc(NuDataSource* pDataSource,
}
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,
fssep, ppDataSink);
return Nu_DataSinkFile_New((Boolean)(doExpand != 0), convertEOL,
pathnameUNI, fssep, ppDataSink);
}
NUFXLIB_API NuError NuCreateDataSinkForFP(short doExpand, NuValue convertEOL,
@ -624,8 +625,8 @@ NUFXLIB_API const char* NuStrError(NuError err)
return Nu_StrError(err);
}
NUFXLIB_API NuError NuGetVersion(long* pMajorVersion, long* pMinorVersion,
long* pBugVersion, const char** ppBuildDate, const char** ppBuildFlags)
NUFXLIB_API NuError NuGetVersion(int32_t* pMajorVersion, int32_t* pMinorVersion,
int32_t* pBugVersion, const char** ppBuildDate, const char** ppBuildFlags)
{
return Nu_GetVersion(pMajorVersion, pMinorVersion, pBugVersion,
ppBuildDate, ppBuildFlags);
@ -709,7 +710,7 @@ NUFXLIB_API uint32_t NuRecordGetNumThreads(const NuRecord* pNuRecord)
}
NUFXLIB_API const NuThread* NuThreadGetByIdx(const NuThread* pNuThread,
long idx)
int32_t idx)
{
if (pNuThread == NULL)
return NULL;
@ -721,6 +722,18 @@ NUFXLIB_API short NuIsPresizedThreadID(NuThreadID 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
* 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)
{
NuError err = kNuErrNone;
Assert(pArchive != NULL);
Assert(pathname != NULL);
Assert(pathnameUNI != NULL);
Assert(pFileInfo != NULL);
pFileInfo->isValid = false;
@ -277,7 +277,7 @@ static NuError Nu_GetFileInfo(NuArchive* pArchive, const char* pathname,
struct stat sbuf;
int cc;
cc = stat(pathname, &sbuf);
cc = stat(pathnameUNI, &sbuf);
if (cc) {
if (errno == ENOENT)
err = kNuErrFileNotFound;
@ -300,7 +300,7 @@ static NuError Nu_GetFileInfo(NuArchive* pArchive, const char* pathname,
pFileInfo->auxType = kDefaultAuxType;
# if defined(MAC_LIKE)
if (!pFileInfo->isDirectory) {
char path[4096];
char path[4096]; // TODO: use dynamic alloc or snprintf
struct stat res_sbuf;
OSErr result;
OSType fileType, creator;
@ -308,7 +308,7 @@ static NuError Nu_GetFileInfo(NuArchive* pArchive, const char* pathname,
FSRef ref;
uint32_t proType, proAux;
strcpy(path, pathname);
strcpy(path, pathnameUNI);
strcat(path, "/rsrc");
cc = stat(path, &res_sbuf);
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) {
result = FSGetCatalogInfo(&ref, kFSCatInfoFinderInfo, &catalogInfo,
NULL, NULL, NULL);
@ -411,14 +411,14 @@ bail:
* file with data and resource forks, we only claim it exists if it has
* nonzero length.
*/
static NuError Nu_FileForkExists(NuArchive* pArchive, const char* pathname,
Boolean isForkedFile, Boolean checkRsrcFork, Boolean* pExists,
NuFileInfo* pFileInfo)
static NuError Nu_FileForkExists(NuArchive* pArchive,
const UNICHAR* pathnameUNI, Boolean isForkedFile, Boolean checkRsrcFork,
Boolean* pExists, NuFileInfo* pFileInfo)
{
NuError err = kNuErrNone;
Assert(pArchive != NULL);
Assert(pathname != NULL);
Assert(pathnameUNI != NULL);
Assert(checkRsrcFork == true || checkRsrcFork == false);
Assert(pExists != NULL);
Assert(pFileInfo != NULL);
@ -433,8 +433,8 @@ static NuError Nu_FileForkExists(NuArchive* pArchive, const char* pathname,
/*
* Check the data fork.
*/
Assert(pArchive->lastFileCreated == NULL);
err = Nu_GetFileInfo(pArchive, pathname, pFileInfo);
Assert(pArchive->lastFileCreatedUNI == NULL);
err = Nu_GetFileInfo(pArchive, pathnameUNI, pFileInfo);
if (err == kNuErrFileNotFound) {
err = kNuErrNone;
*pExists = false;
@ -444,8 +444,8 @@ static NuError Nu_FileForkExists(NuArchive* pArchive, const char* pathname,
/*
* Check the resource fork.
*/
char path[4096];
strncpy(path, pathname, 4089);
char path[4096]; // TODO - dynamic alloc or snprintf
strncpy(path, pathnameUNI, 4089);
strcat(path, "/rsrc");
err = Nu_GetFileInfo(pArchive, path, pFileInfo);
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".
* The file must not exist at all.
*/
Assert(pArchive->lastFileCreated == NULL);
Assert(pArchive->lastFileCreatedUNI == NULL);
*pExists = true;
err = Nu_GetFileInfo(pArchive, pathname, pFileInfo);
err = Nu_GetFileInfo(pArchive, pathnameUNI, pFileInfo);
if (err == kNuErrFileNotFound) {
err = kNuErrNone;
*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.
*/
static NuError Nu_SetFileDates(NuArchive* pArchive, const NuRecord* pRecord,
const char* pathname)
const UNICHAR* pathnameUNI)
{
NuError err = kNuErrNone;
Assert(pArchive != NULL);
Assert(pRecord != NULL);
Assert(pathname != NULL);
Assert(pathnameUNI != NULL);
#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 */
if (utbuf.modtime) {
if (utime(pathname, &utbuf) < 0) {
if (utime(pathnameUNI, &utbuf) < 0) {
Nu_ReportError(NU_BLOB, errno,
"Unable to set time stamp on '%s'", pathname);
"Unable to set time stamp on '%s'", pathnameUNI);
err = kNuErrFileSetDate;
goto bail;
}
@ -570,13 +570,13 @@ static Boolean Nu_IsRecordLocked(const NuRecord* pRecord)
* to do something if the original file was "locked".
*/
static NuError Nu_SetFileAccess(NuArchive* pArchive, const NuRecord* pRecord,
const char* pathname)
const UNICHAR* pathnameUNI)
{
NuError err = kNuErrNone;
Assert(pArchive != NULL);
Assert(pRecord != NULL);
Assert(pathname != NULL);
Assert(pathnameUNI != NULL);
#if defined(UNIX_LIKE) || defined(WINDOWS_LIKE)
/* 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);
//DBUG(("+++ chmod '%s' %03o (mask=%03o)\n", pathname,
// (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,
"unable to set access for '%s' to %03o", pathname, (int) mask);
"unable to set access for '%s' to %03o", pathnameUNI,
(int) mask);
err = kNuErrFileSetAccess;
goto bail;
}
@ -617,16 +618,16 @@ bail:
* Generally this just involves ensuring that the file is writable. If
* this is a convenient place to truncate it, we should do that too.
*/
static NuError Nu_PrepareForWriting(NuArchive* pArchive, const char* pathname,
Boolean prepRsrc, NuFileInfo* pFileInfo)
static NuError Nu_PrepareForWriting(NuArchive* pArchive,
const UNICHAR* pathnameUNI, Boolean prepRsrc, NuFileInfo* pFileInfo)
{
NuError err = kNuErrNone;
#if defined(MAC_LIKE)
char path[4096];
char path[4096]; // TODO: use dynamic alloc or snprintf
#endif
Assert(pArchive != NULL);
Assert(pathname != NULL);
Assert(pathnameUNI != NULL);
Assert(prepRsrc == true || prepRsrc == false);
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(MAC_LIKE)
if (prepRsrc) {
strcpy(path, pathname);
strcpy(path, pathnameUNI);
strcat(path, "/rsrc");
pathname = path;
}
# endif
if (!(pFileInfo->unixMode & S_IWUSR)) {
/* 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,
"unable to set access for '%s'", pathname);
"unable to set access for '%s'", pathnameUNI);
err = kNuErrFileSetAccess;
goto bail;
}
@ -703,21 +704,21 @@ bail:
* subdirectory level doesn't exist either, cut down the pathname and
* recurse.
*/
static NuError Nu_CreateSubdirIFN(NuArchive* pArchive, const char* pathStart,
const char* pathEnd, char fssep)
static NuError Nu_CreateSubdirIFN(NuArchive* pArchive,
const UNICHAR* pathStartUNI, const char* pathEnd, char fssep)
{
NuError err = kNuErrNone;
NuFileInfo fileInfo;
char* tmpBuf = NULL;
Assert(pArchive != NULL);
Assert(pathStart != NULL);
Assert(pathStartUNI != NULL);
Assert(pathEnd != NULL);
Assert(fssep != '\0');
/* pathStart might have whole path, but we only want up to "pathEnd" */
tmpBuf = strdup(pathStart);
tmpBuf[pathEnd - pathStart +1] = '\0';
tmpBuf = strdup(pathStartUNI);
tmpBuf[pathEnd - pathStartUNI +1] = '\0';
err = Nu_GetFileInfo(pArchive, tmpBuf, &fileInfo);
if (err == kNuErrFileNotFound) {
@ -757,21 +758,21 @@ bail:
* If "pathname" is just a filename, or the set of directories matches
* the last directory we created, we don't do anything.
*/
static NuError Nu_CreatePathIFN(NuArchive* pArchive, const char* pathname,
char fssep)
static NuError Nu_CreatePathIFN(NuArchive* pArchive, const UNICHAR* pathnameUNI,
UNICHAR fssep)
{
NuError err = kNuErrNone;
const char* pathStart;
const char* pathEnd;
Assert(pArchive != NULL);
Assert(pathname != NULL);
Assert(pathnameUNI != NULL);
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 (pathname[0] == fssep)
#if !defined(MAC_LIKE) /* On the Mac, if it's a full path, treat it like one */
if (pathnameUNI[0] == fssep)
pathStart++;
#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,
* so we want to use the most restrictive case.
*/
if (pArchive->lastDirCreated &&
strncmp(pathStart, pArchive->lastDirCreated, pathEnd - pathStart +1) == 0)
if (pArchive->lastDirCreatedUNI &&
strncmp(pathStart, pArchive->lastDirCreatedUNI,
pathEnd - pathStart +1) == 0)
{
/* we created this one recently, don't do it again */
goto bail;
@ -815,18 +817,20 @@ bail:
/*
* Open the file for writing, possibly truncating it.
*/
static NuError Nu_OpenFileForWrite(NuArchive* pArchive, const char* pathname,
Boolean openRsrc, FILE** pFp)
static NuError Nu_OpenFileForWrite(NuArchive* pArchive,
const UNICHAR* pathnameUNI, Boolean openRsrc, FILE** pFp)
{
#if defined(MAC_LIKE)
// TODO: fix this -- use dynamic alloc or snprintf
char path[4096];
if (openRsrc) {
strcpy(path, pathname);
strcpy(path, pathnameUNI);
strcat(path, "/rsrc");
pathname = path;
pathnameUNI = path;
}
#endif
*pFp = fopen(pathname, kNuFileOpenWriteTrunc);
*pFp = fopen(pathnameUNI, kNuFileOpenWriteTrunc);
if (*pFp == NULL)
return errno ? errno : -1;
return kNuErrNone;
@ -843,7 +847,7 @@ static NuError Nu_OpenFileForWrite(NuArchive* pArchive, const char* pathname,
* older than what we have.
*/
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)
{
NuError err = kNuErrNone;
@ -855,7 +859,7 @@ NuError Nu_OpenOutputFile(NuArchive* pArchive, const NuRecord* pRecord,
Assert(pArchive != NULL);
Assert(pRecord != NULL);
Assert(pThread != NULL);
Assert(newPathname != NULL);
Assert(newPathnameUNI != NULL);
Assert(pFp != NULL);
/* 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.message = NULL;
errorStatus.pRecord = pRecord;
errorStatus.pathname = newPathname;
errorStatus.pathnameUNI = newPathnameUNI;
errorStatus.origPathname = NULL;
errorStatus.filenameSeparator = newFssep;
/*errorStatus.origArchiveTouched = false;*/
@ -891,7 +895,7 @@ NuError Nu_OpenOutputFile(NuArchive* pArchive, const NuRecord* pRecord,
* empty, this will *not* set "exists".
*/
fileInfo.isValid = false;
err = Nu_FileForkExists(pArchive, newPathname, isForkedFile,
err = Nu_FileForkExists(pArchive, newPathnameUNI, isForkedFile,
extractingRsrc, &exists, &fileInfo);
BailError(err);
@ -989,7 +993,7 @@ NuError Nu_OpenOutputFile(NuArchive* pArchive, const NuRecord* pRecord,
* return kNuSkip.
*/
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) {
errorStatus.err = kNuErrDuplicateNotFound;
@ -1040,23 +1044,23 @@ NuError Nu_OpenOutputFile(NuArchive* pArchive, const NuRecord* pRecord,
*/
if (exists) {
Assert(fileInfo.isValid == true);
err = Nu_PrepareForWriting(pArchive, newPathname, extractingRsrc,
err = Nu_PrepareForWriting(pArchive, newPathnameUNI, extractingRsrc,
&fileInfo);
BailError(err);
} else if (!fileInfo.isValid) {
err = Nu_CreatePathIFN(pArchive, newPathname, newFssep);
err = Nu_CreatePathIFN(pArchive, newPathnameUNI, newFssep);
BailError(err);
}
/*
* Open sesame.
*/
err = Nu_OpenFileForWrite(pArchive, newPathname, extractingRsrc, pFp);
err = Nu_OpenFileForWrite(pArchive, newPathnameUNI, extractingRsrc, pFp);
BailError(err);
#if defined(HAS_RESOURCE_FORKS)
pArchive->lastFileCreated = newPathname;
pArchive->lastFileCreatedUNI = newPathnameUNI;
#endif
bail:
@ -1065,7 +1069,7 @@ bail:
err != kNuErrFileExists)
{
Nu_ReportError(NU_BLOB, err, "Unable to open '%s'%s",
newPathname, extractingRsrc ? " (rsrc fork)" : "");
newPathnameUNI, extractingRsrc ? " (rsrc fork)" : "");
}
}
return err;
@ -1090,7 +1094,7 @@ bail:
* quite right, but it's close enough.
*/
NuError Nu_CloseOutputFile(NuArchive* pArchive, const NuRecord* pRecord,
FILE* fp, const char* pathname)
FILE* fp, const UNICHAR* pathnameUNI)
{
NuError err;
@ -1100,10 +1104,10 @@ NuError Nu_CloseOutputFile(NuArchive* pArchive, const NuRecord* pRecord,
fclose(fp);
err = Nu_SetFileDates(pArchive, pRecord, pathname);
err = Nu_SetFileDates(pArchive, pRecord, pathnameUNI);
BailError(err);
err = Nu_SetFileAccess(pArchive, pRecord, pathname);
err = Nu_SetFileAccess(pArchive, pRecord, pathnameUNI);
BailError(err);
#ifdef MAC_LIKE
@ -1112,11 +1116,11 @@ NuError Nu_CloseOutputFile(NuArchive* pArchive, const NuRecord* pRecord,
FSCatalogInfo catalogInfo;
FSRef ref;
result = FSPathMakeRef(pathname, &ref, NULL);
result = FSPathMakeRef(pathnameUNI, &ref, NULL);
BailError(result);
result = FSGetCatalogInfo(&ref, kFSCatInfoNodeFlags|kFSCatInfoFinderInfo, &catalogInfo,
NULL, NULL, NULL);
result = FSGetCatalogInfo(&ref, kFSCatInfoNodeFlags | kFSCatInfoFinderInfo,
&catalogInfo, NULL, NULL, NULL);
if (result) {
BailError(kNuErrFileStat);
}
@ -1148,10 +1152,10 @@ bail:
/*
* Open the file for reading, in "binary" mode when necessary.
*/
static NuError Nu_OpenFileForRead(NuArchive* pArchive, const char* pathname,
Boolean openRsrc, FILE** pFp)
static NuError Nu_OpenFileForRead(NuArchive* pArchive,
const UNICHAR* pathnameUNI, Boolean openRsrc, FILE** pFp)
{
*pFp = fopen(pathname, kNuFileOpenReadOnly);
*pFp = fopen(pathnameUNI, kNuFileOpenReadOnly);
if (*pFp == NULL)
return errno ? errno : -1;
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
* 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)
{
NuError err = kNuErrNone;
@ -1173,15 +1177,15 @@ NuError Nu_OpenInputFile(NuArchive* pArchive, const char* pathname,
NuResult result;
Assert(pArchive != NULL);
Assert(pathname != NULL);
Assert(pathnameUNI != NULL);
Assert(pFp != NULL);
#if defined(MAC_LIKE)
char path[4096];
char path[4096]; // TODO - dynamic alloc or snprintf
if (openRsrc) {
strcpy(path, pathname);
strcpy(path, pathnameUNI);
strcat(path, "/rsrc");
pathname = path;
pathnameUNI = path;
}
#endif
@ -1189,7 +1193,7 @@ retry:
/*
* Open sesame.
*/
err = Nu_OpenFileForRead(pArchive, pathname, openRsrc, pFp);
err = Nu_OpenFileForRead(pArchive, pathnameUNI, openRsrc, pFp);
if (err == kNuErrNone) /* success! */
goto bail;
@ -1202,7 +1206,7 @@ retry:
errorStatus.sysErr = 0;
errorStatus.message = NULL;
errorStatus.pRecord = NULL;
errorStatus.pathname = pathname;
errorStatus.pathnameUNI = pathnameUNI;
errorStatus.origPathname = NULL;
errorStatus.filenameSeparator = '\0';
/*errorStatus.origArchiveTouched = false;*/
@ -1246,7 +1250,7 @@ bail:
err != kNuErrFileExists)
{
Nu_ReportError(NU_BLOB, err, "Unable to open '%s'%s",
pathname, openRsrc ? " (rsrc fork)" : "");
pathnameUNI, openRsrc ? " (rsrc fork)" : "");
}
}
return err;
@ -1262,14 +1266,14 @@ bail:
/*
* Delete a file.
*/
NuError Nu_DeleteFile(const char* pathname)
NuError Nu_DeleteFile(const UNICHAR* pathnameUNI)
{
#if defined(UNIX_LIKE) || defined(WINDOWS_LIKE)
int cc;
DBUG(("--- Deleting '%s'\n", pathname));
DBUG(("--- Deleting '%s'\n", pathnameUNI));
cc = unlink(pathname);
cc = unlink(pathnameUNI);
if (cc < 0)
return errno ? errno : -1;
else
@ -1282,14 +1286,14 @@ NuError Nu_DeleteFile(const char* pathname)
/*
* 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)
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)
return errno ? errno : -1;
else

View File

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

View File

@ -12,6 +12,9 @@
#
# 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.
prefix = @prefix@
@ -33,12 +36,12 @@ OPT = @CFLAGS@
GCC_FLAGS = -Wall -Wwrite-strings -Wstrict-prototypes -Wpointer-arith -Wshadow
CFLAGS = @BUILD_FLAGS@ -I. @DEFS@ -DOPTFLAGSTR="\"$(OPT)\""
SRCS = Archive.c ArchiveIO.c Bzip2.c Compress.c Crc16.c Debug.c \
Deferred.c Deflate.c Entry.c Expand.c FileIO.c Funnel.c \
SRCS = Archive.c ArchiveIO.c Bzip2.c Charset.c Compress.c Crc16.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 \
Squeeze.c Thread.c Value.c Version.c
OBJS = Archive.o ArchiveIO.o Bzip2.o Compress.o Crc16.o Debug.o \
Deferred.o Deflate.o Entry.o Expand.o FileIO.o Funnel.o \
OBJS = Archive.o ArchiveIO.o Bzip2.o Charset.o Compress.o Crc16.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 \
Squeeze.o Thread.o Value.o Version.o
@ -79,7 +82,7 @@ $(STATIC_PRODUCT): $(OBJS)
$(AR) $@ $(OBJS)
@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.
$(SHARED_PRODUCT): $(OBJS)
-rm -f $(STATIC_PRODUCT) $(SHARED_PRODUCT)
@ -110,12 +113,29 @@ baktar:
@gzip -9 nufxlib.tar
@mv -i nufxlib.tar.gz /home/fadden/BAK/
depend:
makedepend -- $(CFLAGS) -I/usr/local/include -- $(SRCS)
@(cd samples; unset CFLAGS OBJS; @SET_MAKE@ $(MAKE) depend)
# catch OPTFLAGSTR updates
Version.o: Makefile
# DO NOT DELETE THIS LINE -- make depend depends on it.
# dependency info
COMMON_HDRS = NufxLibPriv.h NufxLib.h MiscStuff.h SysDefs.h
Archive.o: Archive.c $(COMMON_HDRS)
ArchiveIO.o: ArchiveIO.c $(COMMON_HDRS)
Bzip2.o: Bzip2.c $(COMMON_HDRS)
Charset.o: Charset.c $(COMMON_HDRS)
Compress.o: Compress.c $(COMMON_HDRS)
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
OBJS = Archive.obj ArchiveIO.obj Bzip2.obj Compress.obj Crc16.obj Debug.obj \
Deferred.obj Deflate.obj Entry.obj Expand.obj FileIO.obj Funnel.obj \
Lzc.obj Lzw.obj MiscStuff.obj MiscUtils.obj Record.obj SourceSink.obj \
Squeeze.obj Thread.obj Value.obj Version.obj
OBJS = Archive.obj ArchiveIO.obj Bzip2.obj Charset.obj Compress.obj \
Crc16.obj Debug.obj Deferred.obj Deflate.obj Entry.obj Expand.obj \
FileIO.obj Funnel.obj Lzc.obj Lzw.obj MiscStuff.obj MiscUtils.obj \
Record.obj SourceSink.obj Squeeze.obj Thread.obj Value.obj Version.obj
# build targets -- static library, dynamic library, and test programs
all: $(STATICLIB) $(SHAREDLIB) $(IMPLIB) \
exerciser.exe imgconv.exe launder.exe test-basic.exe \
test-basic-d.exe test-extract.exe test-simple.exe test-twirl.exe
exerciser.exe imgconv.exe launder.exe test-basic.exe test-basic-d.exe \
test-extract.exe test-names.exe test-simple.exe test-twirl.exe
clean:
-del *.obj *.pdb *.exp
@ -107,6 +107,9 @@ test-basic-d.exe: TestBasic.obj $(IMPLIB)
test-extract.exe: 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)
$(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)
ArchiveIO.obj: ArchiveIO.c $(COMMON_HDRS)
Bzip2.obj: Bzip2.c $(COMMON_HDRS)
Charset.obj: Charset.c $(COMMON_HDRS)
Compress.obj: Compress.c $(COMMON_HDRS)
Crc16.obj: Crc16.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)
TestBasic.obj: samples/TestBasic.c $(COMMON_HDRS)
TestExtract.obj: samples/TestExtract.c $(COMMON_HDRS)
TestNames.obj: samples/TestNames.c $(COMMON_HDRS)
TestSimple.obj: samples/TestSimple.c $(COMMON_HDRS)
TestTwirl.obj: samples/TestTwirl.c $(COMMON_HDRS)

View File

@ -6,7 +6,6 @@
*
* Miscellaneous NufxLib utility functions.
*/
#define __MiscUtils_c__
#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.
*/
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;
const char* msg;

View File

@ -32,8 +32,8 @@ extern "C" {
* The "bug" version can usually be ignored, since it represents minor
* fixes. Unless, of course, your code depends upon that fix.
*/
#define kNuVersionMajor 2
#define kNuVersionMinor 3
#define kNuVersionMajor 3
#define kNuVersionMinor 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.
*
@ -199,7 +226,7 @@ typedef enum NuThreadFormat {
/* extract the filesystem separator char from the "file_sys_info" field */
#define NuGetSepFromSysInfo(sysInfo) \
((char) ((sysInfo) & 0xff))
((UNICHAR) ((sysInfo) & 0xff))
/* return a file_sys_info with a replaced filesystem separator */
#define NuSetSepInSysInfo(sysInfo, newSep) \
((uint16_t) (((sysInfo) & 0xff00) | ((newSep) & 0xff)) )
@ -420,6 +447,10 @@ typedef struct NuThread {
* NuFX "record" definition.
*
* (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 kNuReasonableAttribCount 256
@ -449,20 +480,20 @@ typedef struct NuRecord {
uint8_t* recOptionList; /* NULL if v0 or recOptionSize==0 */
/* data specified by recAttribCount, not accounted for by option list */
long extraCount;
int32_t extraCount;
uint8_t* extraBytes;
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 */
NuRecordIdx recordIdx; /* session-unique record index */
char* threadFilename; /* extracted from filename thread */
char* newFilename; /* memorized during "add file" call */
const char* filename; /* points at recFilen or threadFilen */
char* threadFilenameMOR; /* extracted from filename thread */
char* newFilenameMOR; /* memorized during "add file" call */
const char* filenameMOR; /* points at recFilen or threadFilen */
uint32_t recHeaderLength; /* size of rec hdr, incl thread hdrs */
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 */
long fileOffset; /* file offset of record header */
@ -527,14 +558,19 @@ typedef struct NuRecordAttr {
/*
* 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 {
/* used during AddFile call */
NuThreadID threadID; /* data, rsrc, disk img? */
const char* origName;
const void* origName; /* arbitrary pointer, usually a string */
/* these go straight into the NuRecord */
const char* storageName;
const char* storageNameMOR;
NuFileSysID fileSysID;
uint16_t fileSysInfo;
uint32_t access;
@ -559,12 +595,12 @@ typedef struct NuSelectionProposal {
* Passed into the OutputPathnameFilter callback.
*/
typedef struct NuPathnameProposal {
const char* pathname;
const UNICHAR* pathnameUNI;
char filenameSeparator;
const NuRecord* pRecord;
const NuThread* pThread;
const char* newPathname;
const UNICHAR* newPathnameUNI;
uint8_t newFilenameSeparator;
/*NuThreadID newStorage;*/
NuDataSink* newDataSink;
@ -599,7 +635,8 @@ typedef enum 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
* call the progressFunc when the "percentComplete" changes by more
@ -614,11 +651,11 @@ typedef struct NuProgressData {
short percentComplete; /* 0-100 */
/* 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) */
const char* pathname;
/* basename of "pathname" */
const char* filename;
const UNICHAR* pathnameUNI;
/* basename of "pathname" (for convenience) */
const UNICHAR* filenameUNI;
/* pointer to the record we're expanding from */
const NuRecord* pRecord;
@ -650,11 +687,11 @@ typedef struct NuErrorStatus {
NuOperation operation; /* were we adding, extracting, ?? */
NuError err; /* library error code */
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 char* pathname; /* problematic pathname, if any */
const char* origPathname; /* original pathname, if any */
char filenameSeparator; /* fssep for pathname, if any */
const UNICHAR* pathnameUNI; /* problematic pathname, if any */
const void* origPathname; /* original pathname ref, if any */
UNICHAR filenameSeparator; /* fssep for pathname, if any */
/*char origArchiveTouched;*/
char canAbort; /* give option to abort */
@ -670,12 +707,12 @@ typedef struct NuErrorStatus {
* Error message callback gets one of these.
*/
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) */
short isDebug; /* set for debug-only messages */
/* 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 */
const char* function; /* function name (might be NULL) */
} NuErrorMessage;
@ -728,37 +765,38 @@ NUFXLIB_API NuError NuExtract(NuArchive* pArchive);
NUFXLIB_API NuError NuTest(NuArchive* pArchive);
/* 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 NuExtractThread(NuArchive* pArchive, NuThreadIdx threadIdx,
NuDataSink* pDataSink);
NUFXLIB_API NuError NuTestRecord(NuArchive* pArchive, NuRecordIdx recordIdx);
NUFXLIB_API NuError NuGetRecord(NuArchive* pArchive, NuRecordIdx recordIdx,
const NuRecord** ppRecord);
NUFXLIB_API NuError NuGetRecordIdxByName(NuArchive* pArchive, const char* name,
NuRecordIdx* pRecordIdx);
NUFXLIB_API NuError NuGetRecordIdxByName(NuArchive* pArchive,
const char* nameMOR, NuRecordIdx* pRecordIdx);
NUFXLIB_API NuError NuGetRecordIdxByPosition(NuArchive* pArchive,
uint32_t position, NuRecordIdx* pRecordIdx);
/* read/write interfaces */
NUFXLIB_API NuError NuOpenRW(const char* archivePathname,
const char* tempPathname, uint32_t flags,
NUFXLIB_API NuError NuOpenRW(const UNICHAR* archivePathnameUNI,
const UNICHAR* tempPathnameUNI, uint32_t flags,
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,
const NuFileDetails* pFileDetails, NuRecordIdx* pRecordIdx);
NUFXLIB_API NuError NuAddThread(NuArchive* pArchive, NuRecordIdx recordIdx,
NuThreadID threadID, NuDataSource* pDataSource,
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,
NuRecordIdx* pRecordIdx);
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,
const NuRecordAttr* pRecordAttr);
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 NuDeleteRecord(NuArchive* pArchive, NuRecordIdx recordIdx);
NUFXLIB_API NuError NuDeleteThread(NuArchive* pArchive, NuThreadIdx threadIdx);
@ -780,7 +818,7 @@ NUFXLIB_API NuError NuDebugDumpArchive(NuArchive* pArchive);
/* sources and sinks */
NUFXLIB_API NuError NuCreateDataSourceForFile(NuThreadFormat threadFormat,
uint32_t otherLen, const char* pathname,
uint32_t otherLen, const UNICHAR* pathnameUNI,
short isFromRsrcFork, NuDataSource** ppDataSource);
NUFXLIB_API NuError NuCreateDataSourceForFP(NuThreadFormat threadFormat,
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,
uint16_t crc);
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,
FILE* fp, NuDataSink** ppDataSink);
NUFXLIB_API NuError NuCreateDataSinkForBuffer(short doExpand,
@ -803,8 +841,8 @@ NUFXLIB_API NuError NuDataSinkGetOutCount(NuDataSink* pDataSink,
uint32_t* pOutCount);
/* miscellaneous non-archive operations */
NUFXLIB_API NuError NuGetVersion(long* pMajorVersion, long* pMinorVersion,
long* pBugVersion, const char** ppBuildDate,
NUFXLIB_API NuError NuGetVersion(int32_t* pMajorVersion, int32_t* pMinorVersion,
int32_t* pBugVersion, const char** ppBuildDate,
const char** ppBuildFlags);
NUFXLIB_API const char* NuStrError(NuError err);
NUFXLIB_API NuError NuTestFeature(NuFeature feature);
@ -813,12 +851,17 @@ NUFXLIB_API void NuRecordCopyAttr(NuRecordAttr* pRecordAttr,
NUFXLIB_API NuError NuRecordCopyThreads(const NuRecord* pRecord,
NuThread** ppThreads);
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 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*) \
((uint32_t) (idx) < (uint32_t) (pRecord)->recTotalThreads ? \
&(pRecord)->pThreads[(idx)] : NULL) \
#define NuGetThread(pRecord, idx) ( (const NuThread*) \
((uint32_t) (idx) < (pRecord)->recTotalThreads ? \
&(pRecord)->pThreads[(idx)] : NULL) \
)

View File

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

View File

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

View File

@ -100,7 +100,7 @@ NuError Nu_DataSourceFree(NuDataSource* pDataSource)
switch (pDataSource->sourceType) {
case kNuDataSourceFromFile:
Nu_Free(NULL, pDataSource->fromFile.pathname);
Nu_Free(NULL, pDataSource->fromFile.pathnameUNI);
if (pDataSource->fromFile.fp != NULL) {
fclose(pDataSource->fromFile.fp);
pDataSource->fromFile.fp = NULL;
@ -137,11 +137,12 @@ NuError Nu_DataSourceFree(NuDataSource* pDataSource)
* Create a data source for an unopened file.
*/
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;
if (pathname == NULL ||
if (pathnameUNI == NULL ||
!(isFromRsrcFork == true || isFromRsrcFork == false) ||
ppDataSource == NULL)
{
@ -158,7 +159,7 @@ NuError Nu_DataSourceFile_New(NuThreadFormat threadFormat, uint32_t otherLen,
(*ppDataSource)->common.otherLen = otherLen;
(*ppDataSource)->common.refCount = 1;
(*ppDataSource)->fromFile.pathname = strdup(pathname);
(*ppDataSource)->fromFile.pathnameUNI = strdup(pathnameUNI);
(*ppDataSource)->fromFile.fromRsrcFork = isFromRsrcFork;
(*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.
*/
err = Nu_OpenInputFile(pArchive,
pDataSource->fromFile.pathname, pDataSource->fromFile.fromRsrcFork,
&fileFp);
pDataSource->fromFile.pathnameUNI,
pDataSource->fromFile.fromRsrcFork, &fileFp);
BailError(err);
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)
{
Assert(pDataSource != NULL);
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) {
case kNuDataSinkToFile:
Nu_DataSinkFile_Close(pDataSink);
Nu_Free(NULL, pDataSink->toFile.pathname);
Nu_Free(NULL, pDataSink->toFile.pathnameUNI);
break;
case kNuDataSinkToFP:
break;
@ -551,14 +552,14 @@ NuError Nu_DataSinkFree(NuDataSink* pDataSink)
* Create a data sink for an unopened file.
*/
NuError Nu_DataSinkFile_New(Boolean doExpand, NuValue convertEOL,
const char* pathname, char fssep, NuDataSink** ppDataSink)
const UNICHAR* pathnameUNI, UNICHAR fssep, NuDataSink** ppDataSink)
{
NuError err;
if ((doExpand != true && doExpand != false) ||
(convertEOL != kNuConvertOff && convertEOL != kNuConvertOn &&
convertEOL != kNuConvertAuto) ||
pathname == NULL ||
pathnameUNI == NULL ||
fssep == 0 ||
ppDataSink == NULL)
{
@ -575,7 +576,7 @@ NuError Nu_DataSinkFile_New(Boolean doExpand, NuValue convertEOL,
else
(*ppDataSink)->common.convertEOL = kNuConvertOff;
(*ppDataSink)->common.outCount = 0;
(*ppDataSink)->toFile.pathname = strdup(pathname);
(*ppDataSink)->toFile.pathnameUNI = strdup(pathnameUNI);
(*ppDataSink)->toFile.fssep = fssep;
(*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)
{
Assert(pDataSink != NULL);
Assert(pDataSink->sinkType == kNuDataSinkToFile);
return pDataSink->toFile.pathname;
return pDataSink->toFile.pathnameUNI;
}
/*
* 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->sinkType == kNuDataSinkToFile);

View File

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

View File

@ -6,7 +6,7 @@
*
* Thread-level operations.
*/
#define __Thread_c__ 1
#define COMPILE_THREAD_C 1
#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
* threadID.
*/
Boolean Nu_ThreadHasCRC(long recordVersion, NuThreadID threadID)
Boolean Nu_ThreadHasCRC(uint16_t recordVersion, NuThreadID threadID)
{
return recordVersion >= 3 &&
NuThreadIDGetClass(threadID) == kNuThreadClassData;
@ -412,7 +412,7 @@ NuError Nu_ScanThreads(NuArchive* pArchive, NuRecord* pRecord, long numThreads)
pThread = pRecord->pThreads;
while (numThreads--) {
if (pRecord->threadFilename == NULL &&
if (pRecord->threadFilenameMOR == NULL &&
NuMakeThreadID(pThread->thThreadClass, pThread->thThreadKind) ==
kNuThreadIDFilename)
{
@ -423,12 +423,12 @@ NuError Nu_ScanThreads(NuArchive* pArchive, NuRecord* pRecord, long numThreads)
pThread->thCompThreadEOF);
goto bail;
}
pRecord->threadFilename = Nu_Malloc(pArchive,
pRecord->threadFilenameMOR = Nu_Malloc(pArchive,
pThread->thCompThreadEOF +1);
BailAlloc(pRecord->threadFilename);
BailAlloc(pRecord->threadFilenameMOR);
/* 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);
if ((err = Nu_HeaderIOFailed(pArchive, fp)) != kNuErrNone) {
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 */
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 */
if (pRecord->filename != NULL) {
if (pRecord->filenameMOR != NULL) {
DBUG(("--- HEY: got record filename and thread filename\n"));
}
pRecord->filename = pRecord->threadFilename;
pRecord->filenameMOR = pRecord->threadFilenameMOR;
} else {
/* 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
* 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"));
pRecord->filename = kNuDefaultRecordName;
pRecord->filenameMOR = kNuDefaultRecordName;
}
pArchive->currentOffset += pRecord->totalCompLength;
@ -573,8 +573,9 @@ static NuError Nu_ExtractThreadCommon(NuArchive* pArchive,
NuProgressData progressData;
NuProgressData* pProgressData;
NuDataSink* pOrigDataSink;
char* newPathStorage = NULL;
const char* newPathname;
UNICHAR* newPathStorageUNI = NULL;
UNICHAR* recFilenameStorageUNI = NULL;
const UNICHAR* newPathnameUNI;
NuResult result;
uint8_t newFssep;
Boolean doFreeSink = false;
@ -619,9 +620,11 @@ static NuError Nu_ExtractThreadCommon(NuArchive* pArchive,
}
}
newPathname = NULL;
newPathnameUNI = NULL;
newFssep = 0;
recFilenameStorageUNI = Nu_CopyMORToUNI(pRecord->filenameMOR);
retry_name:
if (Nu_DataSinkGetType(pDataSink) == kNuDataSinkToFile) {
/*
@ -632,18 +635,18 @@ retry_name:
* Start by resetting everything to defaults, in case this isn't
* our first time through the "rename" loop.
*/
newPathname = Nu_DataSinkFile_GetPathname(pDataSink);
newPathnameUNI = Nu_DataSinkFile_GetPathname(pDataSink);
newFssep = Nu_DataSinkFile_GetFssep(pDataSink);
pDataSink = pOrigDataSink;
/* if they don't have a pathname func defined, we just use default */
if (pArchive->outputPathnameFunc != NULL) {
pathProposal.pathname = pRecord->filename;
pathProposal.pathnameUNI = recFilenameStorageUNI;
pathProposal.filenameSeparator =
NuGetSepFromSysInfo(pRecord->recFileSysInfo);
pathProposal.pRecord = pRecord;
pathProposal.pThread = pThread;
pathProposal.newPathname = NULL;
pathProposal.newPathnameUNI = NULL;
pathProposal.newFilenameSeparator = '\0';
/*pathProposal.newStorage = (NuThreadID)-1;*/
pathProposal.newDataSink = NULL;
@ -658,11 +661,13 @@ retry_name:
}
/* we don't own this string, so make a copy */
if (pathProposal.newPathname != NULL) {
newPathStorage = strdup(pathProposal.newPathname);
newPathname = newPathStorage;
} else
newPathname = NULL;
if (pathProposal.newPathnameUNI != NULL) {
Nu_Free(pArchive, newPathStorageUNI);
newPathStorageUNI = strdup(pathProposal.newPathnameUNI);
newPathnameUNI = newPathStorageUNI;
} else {
newPathnameUNI = NULL;
}
if (pathProposal.newFilenameSeparator != '\0')
newFssep = pathProposal.newFilenameSeparator;
@ -672,21 +677,22 @@ retry_name:
}
/* 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.
*/
if (newPathname == NULL) {
if (newPathnameUNI == NULL) {
/* using a data sink; get the pathname out of the record */
newPathname = pRecord->filename;
newPathnameUNI = recFilenameStorageUNI;
newFssep = NuGetSepFromSysInfo(pRecord->recFileSysInfo);
}
if (pThread->thThreadClass == kNuThreadClassData) {
pProgressData = &progressData;
err = Nu_ProgressDataInit_Expand(pArchive, pProgressData, pRecord,
newPathname, newFssep, Nu_DataSinkGetConvertEOL(pOrigDataSink));
newPathnameUNI, newFssep, recFilenameStorageUNI,
Nu_DataSinkGetConvertEOL(pOrigDataSink));
BailError(err);
/* send initial progress so they see the right name if "open" fails */
@ -702,14 +708,14 @@ retry_name:
*/
FILE* fileFp = NULL;
err = Nu_OpenOutputFile(pArchive, pRecord, pThread, newPathname,
err = Nu_OpenOutputFile(pArchive, pRecord, pThread, newPathnameUNI,
newFssep, &fileFp);
if (err == kNuErrRename) {
/* they want to rename; the OutputPathname callback handles this */
Nu_Free(pArchive, newPathStorage);
newPathStorage = NULL;
Nu_Free(pArchive, newPathStorageUNI);
newPathStorageUNI = NULL;
/* reset these just to be careful */
newPathname = NULL;
newPathnameUNI = NULL;
fileFp = NULL;
goto retry_name;
} else if (err != kNuErrNone) {
@ -739,7 +745,7 @@ retry_name:
* permissions as appropriate.
*/
err = Nu_CloseOutputFile(pArchive, pRecord,
Nu_DataSinkFile_GetFP(pDataSink), newPathname);
Nu_DataSinkFile_GetFP(pDataSink), newPathnameUNI);
Nu_DataSinkFile_SetFP(pDataSink, NULL);
BailError(err);
}
@ -760,7 +766,8 @@ bail:
if (Nu_DataSinkGetType(pDataSink) == kNuDataSinkToFile)
Nu_DataSinkFile_Close(pDataSink);
Nu_Free(pArchive, newPathStorage);
Nu_Free(pArchive, newPathStorageUNI);
Nu_Free(pArchive, recFilenameStorageUNI);
if (doFreeSink)
Nu_DataSinkFree(pDataSink);
@ -777,6 +784,7 @@ NuError Nu_ExtractThreadBulk(NuArchive* pArchive, const NuRecord* pRecord,
{
NuError err;
NuDataSink* pDataSink = NULL;
UNICHAR* recFilenameStorageUNI = NULL;
NuValue eolConv;
/*
@ -792,7 +800,8 @@ NuError Nu_ExtractThreadBulk(NuArchive* pArchive, const NuRecord* pRecord,
eolConv = pArchive->valConvertExtractedEOL;
if (NuGetThreadID(pThread) == kNuThreadIDDiskImage)
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);
BailError(err);
@ -805,6 +814,7 @@ bail:
if (err == kNuErrNone)
err = err2;
}
Nu_Free(pArchive, recFilenameStorageUNI);
return err;
}
@ -1175,7 +1185,7 @@ bail:
* newly-added threads isn't possible, since they aren't really threads yet.
*/
NuError Nu_UpdatePresizedThread(NuArchive* pArchive, NuThreadIdx threadIdx,
NuDataSource* pDataSource, long* pMaxLen)
NuDataSource* pDataSource, int32_t* pMaxLen)
{
NuError err;
NuThreadMod* pThreadMod = NULL;

View File

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

View File

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

View File

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

View File

@ -44,8 +44,7 @@ typedef struct ExerciserState {
} ExerciserState;
ExerciserState*
ExerciserState_New(void)
ExerciserState* ExerciserState_New(void)
{
ExerciserState* pExerState;
@ -60,8 +59,7 @@ ExerciserState_New(void)
return pExerState;
}
void
ExerciserState_Free(ExerciserState* pExerState)
void ExerciserState_Free(ExerciserState* pExerState)
{
if (pExerState == NULL)
return;
@ -77,26 +75,24 @@ ExerciserState_Free(ExerciserState* pExerState)
free(pExerState);
}
inline NuArchive*
ExerciserState_GetNuArchive(const ExerciserState* pExerState)
inline NuArchive* ExerciserState_GetNuArchive(const ExerciserState* pExerState)
{
return pExerState->pArchive;
}
inline void
ExerciserState_SetNuArchive(ExerciserState* pExerState, NuArchive* newArchive)
inline void ExerciserState_SetNuArchive(ExerciserState* pExerState,
NuArchive* newArchive)
{
pExerState->pArchive = newArchive;
}
inline char*
ExerciserState_GetArchivePath(const ExerciserState* pExerState)
inline char* ExerciserState_GetArchivePath(const ExerciserState* pExerState)
{
return pExerState->archivePath;
}
inline void
ExerciserState_SetArchivePath(ExerciserState* pExerState, char* newPath)
inline void ExerciserState_SetArchivePath(ExerciserState* pExerState,
char* newPath)
{
if (pExerState->archivePath != NULL)
free(pExerState->archivePath);
@ -115,8 +111,7 @@ ExerciserState_SetArchivePath(ExerciserState* pExerState, char* newPath)
}
}
inline const char*
ExerciserState_GetArchiveFile(const ExerciserState* pExerState)
inline const char* ExerciserState_GetArchiveFile(const ExerciserState* pExerState)
{
if (pExerState->archiveFile == NULL)
return "[no archive open]";
@ -134,8 +129,7 @@ ExerciserState_GetArchiveFile(const ExerciserState* pExerState)
/*
* NuContents callback function. Print the contents of an individual record.
*/
NuResult
PrintEntry(NuArchive* pArchive, void* vpRecord)
NuResult PrintEntry(NuArchive* pArchive, void* vpRecord)
{
const NuRecord* pRecord = (const NuRecord*) vpRecord;
int idx;
@ -143,7 +137,7 @@ PrintEntry(NuArchive* pArchive, void* vpRecord)
(void)pArchive; /* shut up, gcc */
printf("RecordIdx %u: '%s'\n",
pRecord->recordIdx, pRecord->filename);
pRecord->recordIdx, pRecord->filenameMOR);
for (idx = 0; idx < (int) pRecord->recTotalThreads; idx++) {
const NuThread* pThread;
@ -211,8 +205,7 @@ PrintEntry(NuArchive* pArchive, void* vpRecord)
/*
* Get a line of input, stripping the '\n' off the end.
*/
static NuError
GetLine(const char* prompt, char* buffer, int bufferSize)
static NuError GetLine(const char* prompt, char* buffer, int bufferSize)
{
printf("%s> ", prompt);
fflush(stdout);
@ -230,13 +223,12 @@ GetLine(const char* prompt, char* buffer, int bufferSize)
/*
* Selection filter for mass "extract" and "delete" operations.
*/
NuResult
SelectionFilter(NuArchive* pArchive, void* vselFilt)
NuResult SelectionFilter(NuArchive* pArchive, void* vselFilt)
{
const NuSelectionProposal* selProposal = (NuSelectionProposal*) vselFilt;
char buffer[8];
printf("%s (N/y)? ", selProposal->pRecord->filename);
printf("%s (N/y)? ", selProposal->pRecord->filenameMOR);
fflush(stdout);
if (fgets(buffer, sizeof(buffer), stdin) == NULL)
@ -252,8 +244,7 @@ SelectionFilter(NuArchive* pArchive, void* vselFilt)
/*
* General-purpose error handler.
*/
NuResult
ErrorHandler(NuArchive* pArchive, void* vErrorStatus)
NuResult ErrorHandler(NuArchive* pArchive, void* vErrorStatus)
{
const NuErrorStatus* pErrorStatus = (const NuErrorStatus*) vErrorStatus;
char buffer[8];
@ -263,7 +254,7 @@ ErrorHandler(NuArchive* pArchive, void* vErrorStatus)
"\tfilename='%s' '%c'(0x%02x)\n",
pErrorStatus->operation, pErrorStatus->err, pErrorStatus->sysErr,
pErrorStatus->message == NULL ? "(NULL)" : pErrorStatus->message,
pErrorStatus->pathname, pErrorStatus->filenameSeparator,
pErrorStatus->pathnameUNI, pErrorStatus->filenameSeparator,
pErrorStatus->filenameSeparator);
printf("\tValid options are:");
if (pErrorStatus->canAbort)
@ -303,8 +294,7 @@ ErrorHandler(NuArchive* pArchive, void* vErrorStatus)
/*
* This gets called when a buffer DataSource is no longer needed.
*/
NuResult
FreeCallback(NuArchive* pArchive, void* args)
NuResult FreeCallback(NuArchive* pArchive, void* args)
{
free(args);
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.
*/
static NuError
NothingFunc(ExerciserState* pState, int argc, char** argv)
static NuError NothingFunc(ExerciserState* pState, int argc, char** argv)
{
(void) pState, (void) argc, (void) argv; /* shut up, gcc */
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
* practice, we catch this earlier, and won't actually call here.
*/
static NuError
QuitFunc(ExerciserState* pState, int argc, char** argv)
static NuError QuitFunc(ExerciserState* pState, int argc, char** argv)
{
(void) pState, (void) argc, (void) argv; /* shut up, gcc */
assert(0);
@ -361,8 +349,7 @@ QuitFunc(ExerciserState* pState, int argc, char** argv)
/*
* ab - abort current changes
*/
static NuError
AbortFunc(ExerciserState* pState, int argc, char** argv)
static NuError AbortFunc(ExerciserState* pState, int argc, char** argv)
{
(void) pState, (void) argc, (void) argv; /* shut up, gcc */
assert(ExerciserState_GetNuArchive(pState) != NULL);
@ -374,8 +361,7 @@ AbortFunc(ExerciserState* pState, int argc, char** argv)
/*
* af - add file to archive
*/
static NuError
AddFileFunc(ExerciserState* pState, int argc, char** argv)
static NuError AddFileFunc(ExerciserState* pState, int argc, char** argv)
{
NuFileDetails nuFileDetails;
@ -385,7 +371,7 @@ AddFileFunc(ExerciserState* pState, int argc, char** argv)
memset(&nuFileDetails, 0, sizeof(nuFileDetails));
nuFileDetails.threadID = kNuThreadIDDataFork;
nuFileDetails.storageName = argv[1];
nuFileDetails.storageNameMOR = argv[1];
nuFileDetails.fileSysID = kNuFileSysUnknown;
nuFileDetails.fileSysInfo = (short) kFssep;
nuFileDetails.access = kUnlocked;
@ -398,8 +384,7 @@ AddFileFunc(ExerciserState* pState, int argc, char** argv)
/*
* ar - add an empty record
*/
static NuError
AddRecordFunc(ExerciserState* pState, int argc, char** argv)
static NuError AddRecordFunc(ExerciserState* pState, int argc, char** argv)
{
NuError err;
NuRecordIdx recordIdx;
@ -411,7 +396,7 @@ AddRecordFunc(ExerciserState* pState, int argc, char** argv)
memset(&nuFileDetails, 0, sizeof(nuFileDetails));
nuFileDetails.threadID = 0; /* irrelevant */
nuFileDetails.storageName = argv[1];
nuFileDetails.storageNameMOR = argv[1];
nuFileDetails.fileSysID = kNuFileSysUnknown;
nuFileDetails.fileSysInfo = (short) kFssep;
nuFileDetails.access = kUnlocked;
@ -427,8 +412,7 @@ AddRecordFunc(ExerciserState* pState, int argc, char** argv)
/*
* at - add thread to record
*/
static NuError
AddThreadFunc(ExerciserState* pState, int argc, char** argv)
static NuError AddThreadFunc(ExerciserState* pState, int argc, char** argv)
{
NuError err;
NuDataSource* pDataSource = NULL;
@ -516,8 +500,7 @@ bail:
/*
* cl - close archive
*/
static NuError
CloseFunc(ExerciserState* pState, int argc, char** argv)
static NuError CloseFunc(ExerciserState* pState, int argc, char** argv)
{
NuError err;
@ -537,8 +520,7 @@ CloseFunc(ExerciserState* pState, int argc, char** argv)
/*
* d - delete all records (selection-filtered)
*/
static NuError
DeleteFunc(ExerciserState* pState, int argc, char** argv)
static NuError DeleteFunc(ExerciserState* pState, int argc, char** argv)
{
(void) pState, (void) argc, (void) argv; /* shut up, gcc */
assert(ExerciserState_GetNuArchive(pState) != NULL);
@ -552,8 +534,7 @@ DeleteFunc(ExerciserState* pState, int argc, char** argv)
/*
* dr - delete record
*/
static NuError
DeleteRecordFunc(ExerciserState* pState, int argc, char** argv)
static NuError DeleteRecordFunc(ExerciserState* pState, int argc, char** argv)
{
(void) pState, (void) argc, (void) argv; /* shut up, gcc */
assert(ExerciserState_GetNuArchive(pState) != NULL);
@ -566,8 +547,7 @@ DeleteRecordFunc(ExerciserState* pState, int argc, char** argv)
/*
* dt - delete thread
*/
static NuError
DeleteThreadFunc(ExerciserState* pState, int argc, char** argv)
static NuError DeleteThreadFunc(ExerciserState* pState, int argc, char** argv)
{
(void) pState, (void) argc, (void) argv; /* shut up, gcc */
assert(ExerciserState_GetNuArchive(pState) != NULL);
@ -580,8 +560,7 @@ DeleteThreadFunc(ExerciserState* pState, int argc, char** argv)
/*
* e - extract all files (selection-filtered)
*/
static NuError
ExtractFunc(ExerciserState* pState, int argc, char** argv)
static NuError ExtractFunc(ExerciserState* pState, int argc, char** argv)
{
(void) pState, (void) argc, (void) argv; /* shut up, gcc */
assert(ExerciserState_GetNuArchive(pState) != NULL);
@ -595,8 +574,7 @@ ExtractFunc(ExerciserState* pState, int argc, char** argv)
/*
* er - extract record
*/
static NuError
ExtractRecordFunc(ExerciserState* pState, int argc, char** argv)
static NuError ExtractRecordFunc(ExerciserState* pState, int argc, char** argv)
{
(void) pState, (void) argc, (void) argv; /* shut up, gcc */
assert(ExerciserState_GetNuArchive(pState) != NULL);
@ -609,8 +587,7 @@ ExtractRecordFunc(ExerciserState* pState, int argc, char** argv)
/*
* et - extract thread
*/
static NuError
ExtractThreadFunc(ExerciserState* pState, int argc, char** argv)
static NuError ExtractThreadFunc(ExerciserState* pState, int argc, char** argv)
{
NuError err;
NuDataSink* pDataSink = NULL;
@ -638,11 +615,10 @@ bail:
/*
* fl - flush changes to archive
*/
static NuError
FlushFunc(ExerciserState* pState, int argc, char** argv)
static NuError FlushFunc(ExerciserState* pState, int argc, char** argv)
{
NuError err;
long flushStatus;
uint32_t flushStatus;
(void) pState, (void) argc, (void) argv; /* shut up, gcc */
assert(ExerciserState_GetNuArchive(pState) != NULL);
@ -650,7 +626,7 @@ FlushFunc(ExerciserState* pState, int argc, char** argv)
err = NuFlush(ExerciserState_GetNuArchive(pState), &flushStatus);
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;
}
@ -660,8 +636,7 @@ FlushFunc(ExerciserState* pState, int argc, char** argv)
* Currently takes numeric arguments. We could be nice and accept the
* things like "IgnoreCRC" for kNuValueIgnoreCRC, but not yet.
*/
static NuError
GetValueFunc(ExerciserState* pState, int argc, char** argv)
static NuError GetValueFunc(ExerciserState* pState, int argc, char** argv)
{
NuError err;
NuValue value;
@ -680,8 +655,8 @@ GetValueFunc(ExerciserState* pState, int argc, char** argv)
/*
* gmh - get master header
*/
static NuError
GetMasterHeaderFunc(ExerciserState* pState, int argc, char** argv)
static NuError GetMasterHeaderFunc(ExerciserState* pState, int argc,
char** argv)
{
NuError err;
const NuMasterHeader* pMasterHeader;
@ -703,8 +678,7 @@ GetMasterHeaderFunc(ExerciserState* pState, int argc, char** argv)
/*
* gr - get record attributes
*/
static NuError
GetRecordFunc(ExerciserState* pState, int argc, char** argv)
static NuError GetRecordFunc(ExerciserState* pState, int argc, char** argv)
{
NuError err;
const NuRecord* pRecord;
@ -733,8 +707,8 @@ GetRecordFunc(ExerciserState* pState, int argc, char** argv)
/*
* grin - get record idx by name
*/
static NuError
GetRecordIdxByNameFunc(ExerciserState* pState, int argc, char** argv)
static NuError GetRecordIdxByNameFunc(ExerciserState* pState, int argc,
char** argv)
{
NuError err;
NuRecordIdx recIdx;
@ -753,8 +727,8 @@ GetRecordIdxByNameFunc(ExerciserState* pState, int argc, char** argv)
/*
* grip - get record idx by position
*/
static NuError
GetRecordIdxByPositionFunc(ExerciserState* pState, int argc, char** argv)
static NuError GetRecordIdxByPositionFunc(ExerciserState* pState, int argc,
char** argv)
{
NuError err;
NuRecordIdx recIdx;
@ -773,8 +747,8 @@ GetRecordIdxByPositionFunc(ExerciserState* pState, int argc, char** argv)
/*
* ocrw - open/create read-write
*/
static NuError
OpenCreateReadWriteFunc(ExerciserState* pState, int argc, char** argv)
static NuError OpenCreateReadWriteFunc(ExerciserState* pState, int argc,
char** argv)
{
NuError err;
NuArchive* pArchive;
@ -794,8 +768,7 @@ OpenCreateReadWriteFunc(ExerciserState* pState, int argc, char** argv)
/*
* oro - open read-only
*/
static NuError
OpenReadOnlyFunc(ExerciserState* pState, int argc, char** argv)
static NuError OpenReadOnlyFunc(ExerciserState* pState, int argc, char** argv)
{
NuError err;
NuArchive* pArchive;
@ -815,8 +788,8 @@ OpenReadOnlyFunc(ExerciserState* pState, int argc, char** argv)
/*
* ors - open streaming read-only
*/
static NuError
OpenStreamingReadOnlyFunc(ExerciserState* pState, int argc, char** argv)
static NuError OpenStreamingReadOnlyFunc(ExerciserState* pState, int argc,
char** argv)
{
NuError err;
NuArchive* pArchive;
@ -846,8 +819,7 @@ OpenStreamingReadOnlyFunc(ExerciserState* pState, int argc, char** argv)
/*
* orw - open read-write
*/
static NuError
OpenReadWriteFunc(ExerciserState* pState, int argc, char** argv)
static NuError OpenReadWriteFunc(ExerciserState* pState, int argc, char** argv)
{
NuError err;
NuArchive* pArchive;
@ -867,8 +839,7 @@ OpenReadWriteFunc(ExerciserState* pState, int argc, char** argv)
/*
* p - print
*/
static NuError
PrintFunc(ExerciserState* pState, int argc, char** argv)
static NuError PrintFunc(ExerciserState* pState, int argc, char** argv)
{
(void) pState, (void) argc, (void) argv; /* shut up, gcc */
assert(ExerciserState_GetNuArchive(pState) != NULL);
@ -880,8 +851,7 @@ PrintFunc(ExerciserState* pState, int argc, char** argv)
/*
* pd - print debug
*/
static NuError
PrintDebugFunc(ExerciserState* pState, int argc, char** argv)
static NuError PrintDebugFunc(ExerciserState* pState, int argc, char** argv)
{
(void) pState, (void) argc, (void) argv; /* shut up, gcc */
assert(ExerciserState_GetNuArchive(pState) != NULL);
@ -893,8 +863,7 @@ PrintDebugFunc(ExerciserState* pState, int argc, char** argv)
/*
* re - rename record
*/
static NuError
RenameFunc(ExerciserState* pState, int argc, char** argv)
static NuError RenameFunc(ExerciserState* pState, int argc, char** argv)
{
(void) pState, (void) argc, (void) argv; /* shut up, gcc */
assert(ExerciserState_GetNuArchive(pState) != NULL);
@ -909,8 +878,8 @@ RenameFunc(ExerciserState* pState, int argc, char** argv)
*
* Use an error handler callback.
*/
static NuError
SetErrorCallbackFunc(ExerciserState* pState, int argc, char** argv)
static NuError SetErrorCallbackFunc(ExerciserState* pState, int argc,
char** argv)
{
(void) pState, (void) argc, (void) argv; /* shut up, gcc */
assert(ExerciserState_GetNuArchive(pState) != NULL);
@ -925,8 +894,7 @@ SetErrorCallbackFunc(ExerciserState* pState, int argc, char** argv)
*
* Currently takes numeric arguments.
*/
static NuError
SetValueFunc(ExerciserState* pState, int argc, char** argv)
static NuError SetValueFunc(ExerciserState* pState, int argc, char** argv)
{
(void) pState, (void) argc, (void) argv; /* shut up, gcc */
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
* you'd need to list all of them every time.
*/
static NuError
SetRecordAttrFunc(ExerciserState* pState, int argc, char** argv)
static NuError SetRecordAttrFunc(ExerciserState* pState, int argc, char** argv)
{
NuError err;
const NuRecord* pRecord;
@ -971,8 +938,7 @@ SetRecordAttrFunc(ExerciserState* pState, int argc, char** argv)
/*
* t - test archive
*/
static NuError
TestFunc(ExerciserState* pState, int argc, char** argv)
static NuError TestFunc(ExerciserState* pState, int argc, char** argv)
{
(void) pState, (void) argc, (void) argv; /* shut up, gcc */
assert(ExerciserState_GetNuArchive(pState) != NULL);
@ -984,8 +950,7 @@ TestFunc(ExerciserState* pState, int argc, char** argv)
/*
* tr - test record
*/
static NuError
TestRecordFunc(ExerciserState* pState, int argc, char** argv)
static NuError TestRecordFunc(ExerciserState* pState, int argc, char** argv)
{
(void) pState, (void) argc, (void) argv; /* shut up, gcc */
assert(ExerciserState_GetNuArchive(pState) != NULL);
@ -998,13 +963,14 @@ TestRecordFunc(ExerciserState* pState, int argc, char** argv)
/*
* upt - update pre-sized thread
*/
static NuError
UpdatePresizedThreadFunc(ExerciserState* pState, int argc, char** argv)
static NuError UpdatePresizedThreadFunc(ExerciserState* pState, int argc,
char** argv)
{
NuError err;
NuDataSource* pDataSource = NULL;
char* lineBuf = NULL;
long ourLen, maxLen;
long ourLen;
int32_t maxLen;
(void) pState, (void) argc, (void) argv; /* shut up, gcc */
assert(ExerciserState_GetNuArchive(pState) != NULL);
@ -1032,7 +998,7 @@ UpdatePresizedThreadFunc(ExerciserState* pState, int argc, char** argv)
err = NuUpdatePresizedThread(ExerciserState_GetNuArchive(pState),
strtol(argv[1], NULL, 0), pDataSource, &maxLen);
if (err == kNuErrNone)
printf("Exerciser: success; function returned maxLen=%ld\n", maxLen);
printf("Exerciser: success; function returned maxLen=%d\n", maxLen);
bail:
NuFreeDataSource(pDataSource);
@ -1138,8 +1104,7 @@ static const struct {
/*
* Display a summary of available commands.
*/
static NuError
HelpFunc(ExerciserState* pState, int argc, char** argv)
static NuError HelpFunc(ExerciserState* pState, int argc, char** argv)
{
int i;
@ -1171,9 +1136,8 @@ static const char* kWhitespace = " \t\n";
* "lineBuf" will be mangled. On success, "pFunc", "pArgc", and "pArgv"
* will receive the results.
*/
static NuError
ParseLine(char* lineBuf, ExerciserState* pState, CommandFunc* pFunc, int* pArgc,
char*** pArgv)
static NuError ParseLine(char* lineBuf, ExerciserState* pState,
CommandFunc* pFunc, int* pArgc, char*** pArgv)
{
NuError err = kNuErrSyntax;
char* command;
@ -1259,12 +1223,10 @@ bail:
}
/*
* Interpret commands, do clever things.
*/
static NuError
CommandLoop(void)
static NuError CommandLoop(void)
{
NuError err = kNuErrNone;
ExerciserState* pState = ExerciserState_New();
@ -1334,17 +1296,16 @@ CommandLoop(void)
*
* We don't currently take any arguments, so this is pretty straightforward.
*/
int
main(void)
int main(void)
{
NuError result;
long majorVersion, minorVersion, bugVersion;
int32_t majorVersion, minorVersion, bugVersion;
const char* nufxLibDate;
const char* nufxLibFlags;
(void) NuGetVersion(&majorVersion, &minorVersion, &bugVersion,
&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);
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.
*/
void
ReadShortLE(FILE* fp, uint16_t* pBuf)
void ReadShortLE(FILE* fp, uint16_t* pBuf)
{
*pBuf = getc(fp);
*pBuf += (uint16_t) getc(fp) << 8;
@ -78,8 +77,7 @@ ReadShortLE(FILE* fp, uint16_t* pBuf)
/*
* Write a two-byte little-endian value.
*/
void
WriteShortLE(FILE* fp, uint16_t val)
void WriteShortLE(FILE* fp, uint16_t val)
{
putc(val, fp);
putc(val >> 8, fp);
@ -88,8 +86,7 @@ WriteShortLE(FILE* fp, uint16_t val)
/*
* Read a four-byte little-endian value.
*/
void
ReadLongLE(FILE* fp, uint32_t* pBuf)
void ReadLongLE(FILE* fp, uint32_t* pBuf)
{
*pBuf = getc(fp);
*pBuf += (uint32_t) getc(fp) << 8;
@ -100,8 +97,7 @@ ReadLongLE(FILE* fp, uint32_t* pBuf)
/*
* Write a four-byte little-endian value.
*/
void
WriteLongLE(FILE* fp, uint32_t val)
void WriteLongLE(FILE* fp, uint32_t val)
{
putc(val, fp);
putc(val >> 8, fp);
@ -112,8 +108,7 @@ WriteLongLE(FILE* fp, uint32_t val)
/*
* Read the header from a 2IMG file.
*/
int
ReadImgHeader(FILE* fp, ImgHeader* pHeader)
int ReadImgHeader(FILE* fp, ImgHeader* pHeader)
{
size_t ignored;
ignored = fread(pHeader->magic, 4, 1, fp);
@ -154,8 +149,7 @@ ReadImgHeader(FILE* fp, ImgHeader* pHeader)
/*
* Write the header to a 2IMG file.
*/
int
WriteImgHeader(FILE* fp, ImgHeader* pHeader)
int WriteImgHeader(FILE* fp, ImgHeader* pHeader)
{
fwrite(pHeader->magic, 4, 1, fp);
fwrite(pHeader->creator, 4, 1, fp);
@ -185,8 +179,7 @@ WriteImgHeader(FILE* fp, ImgHeader* pHeader)
/*
* Dump the contents of an ImgHeader.
*/
void
DumpImgHeader(ImgHeader* pHeader)
void DumpImgHeader(ImgHeader* pHeader)
{
printf("--- header contents:\n");
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.
*/
NuResult
FreeCallback(NuArchive* pArchive, void* args)
NuResult FreeCallback(NuArchive* pArchive, void* args)
{
free(args);
return kNuOK;
@ -227,8 +219,7 @@ FreeCallback(NuArchive* pArchive, void* args)
/*
* This gets called when an "FP" DataSource is no longer needed.
*/
NuResult
FcloseCallback(NuArchive* pArchive, void* args)
NuResult FcloseCallback(NuArchive* pArchive, void* args)
{
fclose((FILE*) args);
return kNuOK;
@ -242,8 +233,7 @@ FcloseCallback(NuArchive* pArchive, void* args)
* of NufxLib. We could just as easily not set it and call fclose()
* ourselves, because the structure of this program is pretty simple.
*/
NuError
CreateProdosSource(const ImgHeader* pHeader, FILE* fp,
NuError CreateProdosSource(const ImgHeader* pHeader, FILE* fp,
NuDataSource** ppDataSource)
{
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,
* since we have to reorder the blocks into ProDOS ordering for ShrinkIt.
*/
NuError
CreateDosSource(const ImgHeader* pHeader, FILE* fp,
NuError CreateDosSource(const ImgHeader* pHeader, FILE* fp,
NuDataSource** ppDataSource)
{
NuError err;
@ -338,8 +327,7 @@ bail:
* This requires opening up the 2IMG file, verifying that it's okay, and
* then creating a new disk image record and thread.
*/
int
ConvertFromImgToShk(const char* srcName, const char* dstName)
int ConvertFromImgToShk(const char* srcName, const char* dstName)
{
NuError err;
NuArchive* pArchive = NULL;
@ -348,7 +336,7 @@ ConvertFromImgToShk(const char* srcName, const char* dstName)
NuFileDetails fileDetails;
ImgHeader header;
FILE* fp = NULL;
long flushStatus;
uint32_t flushStatus;
char* storageName = NULL;
char* cp;
@ -410,7 +398,7 @@ ConvertFromImgToShk(const char* srcName, const char* dstName)
/* set up the contents of the NuFX Record */
memset(&fileDetails, 0, sizeof(fileDetails));
fileDetails.storageName = cp;
fileDetails.storageNameMOR = cp;
fileDetails.fileSysID = kNuFileSysUnknown; /* DOS? ProDOS? */
fileDetails.fileSysInfo = kLocalFssep;
fileDetails.access = kNuAccessUnlocked;
@ -461,7 +449,7 @@ ConvertFromImgToShk(const char* srcName, const char* dstName)
/* nothing happens until we Flush */
err = NuFlush(pArchive, &flushStatus);
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);
goto bail;
}
@ -492,8 +480,7 @@ bail:
* 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.
*/
int
ConvertFromShkToImg(const char* srcName, const char* dstName)
int ConvertFromShkToImg(const char* srcName, const char* dstName)
{
NuError err;
NuArchive* pArchive = NULL;
@ -604,8 +591,7 @@ bail:
/*
* Figure out what kind of archive this is by looking at the filename.
*/
ArchiveKind
DetermineKind(const char* filename)
ArchiveKind DetermineKind(const char* filename)
{
const char* dot;
@ -626,8 +612,7 @@ DetermineKind(const char* filename)
/*
* Figure out what we want to do.
*/
int
main(int argc, char** argv)
int main(int argc, char** argv)
{
ArchiveKind kind;
int cc;

View File

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

View File

@ -28,29 +28,12 @@ ALL_SRCS = Exerciser.c ImgConv.c Launder.c TestBasic.c \
NUFXLIB = -L.. -lnufx
PRODUCTS = exerciser imgconv launder test-basic test-extract test-simple \
test-twirl
#ifdef PURIFY_BUILD
# PURIFY = purify
# CFLAGS += -DPURIFY
#endif
#ifdef QUANTIFY_BUILD
# QUANTIFY = quantify
# CFLAGS += -DQUANTIFY
#endif
PRODUCTS = exerciser imgconv launder test-basic test-extract test-names \
test-simple test-twirl
all: $(PRODUCTS)
@true
#quantify:
# -rm -f $(PRODUCT)
# @$(MAKE) QUANTIFY_BUILD=1
#
#purify:
# -rm -f $(PRODUCT)
# @$(MAKE) PURIFY_BUILD=1
exerciser: Exerciser.o $(LIB_PRODUCT)
$(PURIFY) $(QUANTIFY) $(CC) -o $@ Exerciser.o $(NUFXLIB) @LIBS@
@ -63,12 +46,15 @@ launder: Launder.o $(LIB_PRODUCT)
test-basic: TestBasic.o $(LIB_PRODUCT)
$(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)
$(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)
$(PURIFY) $(QUANTIFY) $(CC) -o $@ TestTwirl.o $(NUFXLIB) @LIBS@
@ -84,8 +70,12 @@ distclean: clean
-rm -f tags
-rm -f Makefile Makefile.bak
depend:
makedepend -- $(CFLAGS) -I/usr/local/include -- $(ALL_SRCS)
# DO NOT DELETE THIS LINE -- make depend depends on it.
COMMON_HDRS = ../NufxLibPriv.h ../NufxLib.h ../MiscStuff.h ../SysDefs.h
Exerciser.o: Exerciser.c $(COMMON_HDRS)
ImgConv.o: ImgConv.c $(COMMON_HDRS)
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 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 kTestEntryBytesUPPER "BYTES"
#define kTestEntryEnglish "English"
@ -39,8 +41,7 @@ char gSuppressError = false;
/*
* Get a single character of input from the user.
*/
static char
TGetReplyChar(char defaultReply)
static char TGetReplyChar(char defaultReply)
{
char tmpBuf[32];
@ -52,14 +53,13 @@ TGetReplyChar(char defaultReply)
return tmpBuf[0];
}
NuError
AddSimpleRecord(NuArchive* pArchive, const char* filename,
NuError AddSimpleRecord(NuArchive* pArchive, const char* filenameMOR,
NuRecordIdx* pRecordIdx)
{
NuFileDetails fileDetails;
memset(&fileDetails, 0, sizeof(fileDetails));
fileDetails.storageName = filename;
fileDetails.storageNameMOR = filenameMOR;
fileDetails.fileSysInfo = kLocalFssep;
fileDetails.access = kNuAccessUnlocked;
@ -70,8 +70,7 @@ AddSimpleRecord(NuArchive* pArchive, const char* filename,
/*
* Display error messages... or not.
*/
NuResult
ErrorMessageHandler(NuArchive* pArchive, void* vErrorMessage)
NuResult ErrorMessageHandler(NuArchive* pArchive, void* 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.
*/
NuResult
FreeCallback(NuArchive* pArchive, void* args)
NuResult FreeCallback(NuArchive* pArchive, void* args)
{
free(args);
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,
* and verify that we handle existing zero-byte archive files correctly.
*/
int
Test_OpenFlags(void)
int Test_OpenFlags(void)
{
NuError err;
FILE* fp = NULL;
@ -170,14 +192,13 @@ failed:
/*
* Add some files to the archive. These will be used by later tests.
*/
int
Test_AddStuff(NuArchive* pArchive)
int Test_AddStuff(NuArchive* pArchive)
{
NuError err;
uint8_t* buf = NULL;
NuDataSource* pDataSource = NULL;
NuRecordIdx recordIdx;
long status;
uint32_t status;
int i;
static const char* testMsg =
"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"
"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"
"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"
"anybody who says otherwise is a pinko commie lowlife. Verily.\n";
@ -308,7 +329,7 @@ Test_AddStuff(NuArchive* pArchive)
*/
err = NuFlush(pArchive, &status);
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);
goto failed;
}
@ -318,7 +339,7 @@ Test_AddStuff(NuArchive* pArchive)
*/
err = NuFlush(pArchive, &status);
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);
goto failed;
}
@ -336,19 +357,18 @@ failed:
/*
* Make sure that what we're seeing makes sense.
*/
NuResult
TestContentsCallback(NuArchive* pArchive, void* vpRecord)
NuResult TestContentsCallback(NuArchive* pArchive, void* vpRecord)
{
const NuRecord* pRecord = (NuRecord*) vpRecord;
if (strcmp(pRecord->filename, kTestEntryBytes) == 0 ||
strcmp(pRecord->filename, kTestEntryEnglish) == 0 ||
strcmp(pRecord->filename, kTestEntryLong) == 0)
if (strcmp(pRecord->filenameMOR, kTestEntryBytes) == 0 ||
strcmp(pRecord->filenameMOR, kTestEntryEnglish) == 0 ||
strcmp(pRecord->filenameMOR, kTestEntryLong) == 0)
{
return kNuOK;
}
fprintf(stderr, "ERROR: found mystery entry '%s'\n", pRecord->filename);
fprintf(stderr, "ERROR: found mystery entry '%s'\n", pRecord->filenameMOR);
return kNuAbort;
}
@ -356,8 +376,7 @@ TestContentsCallback(NuArchive* pArchive, void* vpRecord)
/*
* Verify that the contents look about right.
*/
int
Test_Contents(NuArchive* pArchive)
int Test_Contents(NuArchive* pArchive)
{
NuError err;
long posn;
@ -394,13 +413,13 @@ Test_Contents(NuArchive* pArchive)
switch (posn) {
case 0:
cc = strcmp(pRecord->filename, kTestEntryBytes);
cc = strcmp(pRecord->filenameMOR, kTestEntryBytes);
break;
case 1:
cc = strcmp(pRecord->filename, kTestEntryEnglish);
cc = strcmp(pRecord->filenameMOR, kTestEntryEnglish);
break;
case 2:
cc = strcmp(pRecord->filename, kTestEntryLong);
cc = strcmp(pRecord->filenameMOR, kTestEntryLong);
if (!cc)
cc = !(pRecord->recStorageType == kNuStorageExtended);
break;
@ -412,7 +431,7 @@ Test_Contents(NuArchive* pArchive)
if (cc) {
fprintf(stderr, "ERROR: got '%s' for %ld (%u), not expected\n",
pRecord->filename, posn, recordIdx);
pRecord->filenameMOR, posn, recordIdx);
goto failed;
}
}
@ -437,15 +456,14 @@ failed:
/*
* Selection callback filter for "test". This gets called once per record.
*/
NuResult
VerifySelectionCallback(NuArchive* pArchive, void* vpProposal)
NuResult VerifySelectionCallback(NuArchive* pArchive, void* vpProposal)
{
NuError err;
const NuSelectionProposal* pProposal = vpProposal;
long count;
if (pProposal->pRecord == NULL || pProposal->pThread == NULL ||
pProposal->pRecord->filename == NULL)
pProposal->pRecord->filenameMOR == NULL)
{
fprintf(stderr, "ERROR: unexpected NULL in proposal\n");
goto failed;
@ -473,8 +491,7 @@ failed:
/*
* Verify the archive contents.
*/
int
Test_Verify(NuArchive* pArchive)
int Test_Verify(NuArchive* pArchive)
{
NuError err;
long count;
@ -520,8 +537,7 @@ failed:
/*
* Extract stuff.
*/
int
Test_Extract(NuArchive* pArchive)
int Test_Extract(NuArchive* pArchive)
{
NuError err;
NuRecordIdx recordIdx;
@ -780,8 +796,7 @@ failed:
/*
* Delete the first and last records. Does *not* flush the archive.
*/
int
Test_Delete(NuArchive* pArchive)
int Test_Delete(NuArchive* pArchive)
{
NuError err;
NuRecordIdx recordIdx;
@ -847,6 +862,7 @@ Test_Delete(NuArchive* pArchive)
/*
* Make sure the attr hasn't been updated yet.
*/
count = 0;
err = NuGetAttr(pArchive, kNuAttrNumRecords, (uint32_t*) &count);
if (count != kNumEntries) {
fprintf(stderr, "ERROR: kNuAttrNumRecords %ld vs %d\n",
@ -901,8 +917,7 @@ failed:
/*
* Verify that the count in the master header has been updated.
*/
int
Test_MasterCount(NuArchive* pArchive, long expected)
int Test_MasterCount(NuArchive* pArchive, long expected)
{
NuError err;
const NuMasterHeader* pMasterHeader;
@ -932,41 +947,21 @@ failed:
*
* Returns 0 on success, -1 on error.
*/
int
DoTests(void)
int DoTests(void)
{
NuError err;
NuArchive* pArchive = NULL;
long status;
uint32_t status;
int cc, result = 0;
char answer;
/*
* Make sure we're starting with a clean slate.
*/
if (access(kTestArchive, F_OK) == 0) {
printf("Test archive '%s' exists, remove (y/n)? ", kTestArchive);
fflush(stdout);
answer = TGetReplyChar('n');
if (tolower(answer) != 'y')
goto failed;
cc = unlink(kTestArchive);
if (cc < 0) {
perror("unlink kTestArchive");
goto failed;
}
if (RemoveTestFile("Test archive", kTestArchive) < 0) {
goto failed;
}
if (access(kTestTempFile, F_OK) == 0) {
printf("Test temp file '%s' exists, remove (y/n)? ", kTestTempFile);
fflush(stdout);
answer = TGetReplyChar('n');
if (tolower(answer) != 'y')
goto failed;
cc = unlink(kTestTempFile);
if (cc < 0) {
perror("unlink kTestTempFile");
goto failed;
}
if (RemoveTestFile("Test temp file", kTestTempFile) < 0) {
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");
if (Test_Contents(pArchive) != 0)
goto failed;
/*
* Verify the archive contents.
* Verify the archive data.
*/
if (Test_Verify(pArchive) != 0)
goto failed;
@ -1107,7 +1102,7 @@ DoTests(void)
*/
err = NuFlush(pArchive, &status);
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);
goto failed;
}
@ -1148,16 +1143,15 @@ failed:
/*
* Crank away.
*/
int
main(void)
int main(void)
{
long major, minor, bug;
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%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",
major, minor, bug, pBuildDate, pBuildFlags);

View File

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

View File

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

View File

@ -1,12 +1,12 @@
/*
* Nulib2
* NuLib2
* 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.
*
* Add files to or update files in the archive.
*/
#include "Nulib2.h"
#include "NuLib2.h"
static NuError AddToArchive(NulibState* pState, NuArchive* pArchive);
@ -18,7 +18,7 @@ NuError DoAdd(NulibState* pState)
{
NuError err;
NuArchive* pArchive = NULL;
long flushStatus;
uint32_t flushStatus;
Assert(pState != NULL);
@ -61,7 +61,7 @@ bail:
"failed afterward");
} else {
ReportError(err,
"Unable to flush archive changes (status=0x%04lx)",
"Unable to flush archive changes (status=0x%04x)",
flushStatus);
}
NuAbort(pArchive);

View File

@ -1,12 +1,12 @@
/*
* Nulib2
* NuLib2
* 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.
*
* 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;
NulibState* pState;
const char* newPathname;
const UNICHAR* newPathnameUNI;
NuRecordIdx renameFromIdx;
char* renameToStr;
char* resultBuf;
UNICHAR* renameToStrUNI;
UNICHAR* resultBufUNI;
Assert(pArchive != NULL);
(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
* that it's okay (and let the OS tell them if it isn't).
*/
renameToStr = NState_GetRenameToStr(pState);
if (renameToStr != NULL) {
renameToStrUNI = NState_GetRenameToStr(pState);
if (renameToStrUNI != NULL) {
renameFromIdx = NState_GetRenameFromIdx(pState);
if (renameFromIdx == pathProposal->pRecord->recordIdx) {
/* right source file, proceed with the rename */
NState_SetTempPathnameLen(pState, strlen(renameToStr) +1);
resultBuf = NState_GetTempPathnameBuf(pState);
Assert(resultBuf != NULL);
strcpy(resultBuf, renameToStr);
NState_SetTempPathnameLen(pState, strlen(renameToStrUNI) +1);
resultBufUNI = NState_GetTempPathnameBuf(pState);
Assert(resultBufUNI != NULL);
strcpy(resultBufUNI, renameToStrUNI);
pathProposal->newPathname = resultBuf;
pathProposal->newPathnameUNI = resultBufUNI;
}
/* free up renameToStr */
/* free up renameToStrUNI */
NState_SetRenameToStr(pState, NULL);
goto bail;
@ -72,13 +72,13 @@ static NuResult OutputPathnameFilter(NuArchive* pArchive, void* vproposal)
/*
* Convert the pathname into something suitable for the current OS.
*/
newPathname = NormalizePath(pState, pathProposal);
if (newPathname == NULL) {
newPathnameUNI = NormalizePath(pState, pathProposal);
if (newPathnameUNI == NULL) {
ReportError(kNuErrNone, "unable to convert pathname");
return kNuAbort;
}
pathProposal->newPathname = newPathname;
pathProposal->newPathnameUNI = newPathnameUNI;
bail:
return kNuOK;
@ -202,9 +202,9 @@ static Boolean SpecMatchesRecord(NulibState* pState, const char* spec,
return (strcmp(spec, pRecord->filename) == 0);
#else
if (NState_GetModRecurse(pState))
return (strncasecmp(spec, pRecord->filename, strlen(spec)) == 0);
return (strncasecmp(spec, pRecord->filenameMOR, strlen(spec)) == 0);
else
return (strcasecmp(spec, pRecord->filename) == 0);
return (strcasecmp(spec, pRecord->filenameMOR) == 0);
#endif
}
@ -253,12 +253,14 @@ NuResult SelectionFilter(NuArchive* pArchive, void* vproposal)
NState_IncMatchCount(pState);
/* we don't get progress notifications for delete, so do it here */
if (NState_GetCommand(pState) == kCommandDelete)
printf("Deleting %s\n", selProposal->pRecord->filename);
if (NState_GetCommand(pState) == kCommandDelete) {
printf("Deleting %s\n", selProposal->pRecord->filenameMOR);
}
return kNuOK;
} else
} else {
return kNuSkip;
}
}
@ -401,12 +403,13 @@ NuResult ProgressUpdater(NuArchive* pArchive, void* vProgress)
* Could also use "origPathname", but I like to show what they're
* getting instead of what they're giving.
*/
int len = strlen(pProgress->pathname);
int len = strlen(pProgress->pathnameUNI);
if (len < sizeof(nameBuf)) {
strcpy(nameBuf, pProgress->pathname);
strcpy(nameBuf, pProgress->pathnameUNI);
} else {
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);
nameBuf[sizeof(nameBuf)-1] = '\0';
}
@ -450,7 +453,7 @@ static NuResult HandleReplaceExisting(NulibState* pState, NuArchive* pArchive,
Assert(pState != NULL);
Assert(pErrorStatus != NULL);
Assert(pErrorStatus->pathname != NULL);
Assert(pErrorStatus->pathnameUNI != NULL);
Assert(pErrorStatus->canOverwrite);
Assert(pErrorStatus->canSkip);
@ -465,7 +468,7 @@ static NuResult HandleReplaceExisting(NulibState* pState, NuArchive* pArchive,
while (1) {
printf("\n Replace %s? [y]es, [n]o, [A]ll, [N]one",
pErrorStatus->pathname);
pErrorStatus->pathnameUNI);
if (pErrorStatus->canRename) /* renaming record adds not allowed */
printf(", [r]ename: ");
else
@ -545,9 +548,9 @@ static NuResult HandleBadCRC(NulibState* pState, NuArchive* pArchive,
}
while (1) {
if (pErrorStatus->pathname != NULL)
if (pErrorStatus->pathnameUNI != NULL)
fprintf(stderr, "\n Found a bad CRC in %s\n",
pErrorStatus->pathname);
pErrorStatus->pathnameUNI);
else
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(pErrorStatus != NULL);
Assert(pErrorStatus->pathname != NULL);
Assert(pErrorStatus->pathnameUNI != NULL);
if (NState_GetInputUnavailable(pState)) {
putc('\n', stdout);
@ -606,7 +609,7 @@ static NuResult HandleAddNotFound(NulibState* pState, NuArchive* pArchive,
while (1) {
fprintf(stderr, "\n Couldn't find %s, continue? [y]es, [n]o: ",
pErrorStatus->pathname);
pErrorStatus->pathnameUNI);
fflush(stderr);
reply = GetReplyChar('n');

View File

@ -1,5 +1,5 @@
/*
* Nulib2
* NuLib2
* 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.
@ -17,7 +17,7 @@
*
* TO DO: add "junk skipping" like NufxLib has.
*/
#include "Nulib2.h"
#include "NuLib2.h"
#ifdef HAVE_FCNTL_H
# include <fcntl.h>
@ -136,7 +136,7 @@ typedef struct BNYEntry {
NuDateTime createWhen; /* computed from previous two fields */
uint32_t eof;
uint32_t realEOF; /* eof is bogus for directories */
char fileName[kBNYMaxFileName+1];
char fileName[kBNYMaxFileName+1]; /* ASCII only */
char nativeName[kBNYMaxNativeName+1];
uint32_t diskSpace; /* in 512-byte blocks */
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(&fakeThread, 0xa5, sizeof(fakeThread));
pathProposal.pathname = pEntry->fileName;
pathProposal.pathnameUNI = pEntry->fileName;
pathProposal.filenameSeparator = '/'; /* BNY always uses ProDOS conv */
pathProposal.pRecord = &fakeRecord;
pathProposal.pThread = &fakeThread;
pathProposal.newPathname = NULL;
pathProposal.newPathnameUNI = NULL;
pathProposal.newFilenameSeparator = '\0';
pathProposal.newDataSink = NULL;

View File

@ -1,12 +1,12 @@
/*
* Nulib2
* NuLib2
* 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.
*
* 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.
* This is free software; you can redistribute it and/or modify it under the
* terms of the BSD License, see the file COPYING.
*
* 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 &&
pThread->actualThreadEOF > 0)
{
printf("----- '%s':\n", pRecord->filename);
UNICHAR* filenameUNI = CopyMORToUNI(pRecord->filenameMOR);
printf("----- '%s':\n", filenameUNI);
free(filenameUNI);
err = NuExtractThread(pArchive, pThread->threadIdx,
NState_GetCommentSink(pState));
if (err != kNuErrNone) {

View File

@ -1,12 +1,12 @@
/*
* Nulib2
* NuLib2
* 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.
*
* Filename manipulation, including file type preservation.
*/
#include "Nulib2.h"
#include "NuLib2.h"
#include <ctype.h>
@ -258,7 +258,7 @@ const char* NormalizePath(NulibState* pState, NuPathnameProposal* pPathProposal)
Assert(pState != NULL);
Assert(pPathProposal != NULL);
Assert(pPathProposal->pathname != NULL);
Assert(pPathProposal->pathnameUNI != NULL);
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
* possible preservation string.
*/
newBufLen = strlen(pPathProposal->pathname)*3 + kMaxPathGrowth +1;
newBufLen = strlen(pPathProposal->pathnameUNI)*3 + kMaxPathGrowth +1;
NState_SetTempPathnameLen(pState, newBufLen);
pathBuf = NState_GetTempPathnameBuf(pState);
Assert(pathBuf != NULL);
if (pathBuf == NULL)
return NULL;
startp = pPathProposal->pathname;
startp = pPathProposal->pathnameUNI;
dstp = pathBuf;
while (*startp == pPathProposal->filenameSeparator) {
/* 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;
/* check for overflow */

View File

@ -1,12 +1,12 @@
/*
* Nulib2
* NuLib2
* 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.
*
* List files in the archive.
*/
#include "Nulib2.h"
#include "NuLib2.h"
/* kinds of records */
@ -111,8 +111,9 @@ static NuResult ShowContentsShort(NuArchive* pArchive, void* vpRecord)
if (!IsSpecified(pState, pRecord))
goto bail;
printf("%s\n",
pRecord->filename == NULL ? "<unknown>":(const char*)pRecord->filename);
UNICHAR* filenameUNI = CopyMORToUNI(pRecord->filenameMOR);
printf("%s\n", filenameUNI == NULL ? "<unknown>" : filenameUNI);
free(filenameUNI);
bail:
return kNuOK;
@ -209,14 +210,32 @@ static NuResult ShowContentsVerbose(NuArchive* pArchive, void* vpRecord)
if (err != kNuErrNone)
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) {
printf("%c%-27.27s ", IsRecordReadOnly(pRecord) ? '+' : ' ',
pRecord->filename);
filenameUNI = CopyMORToUNI(pRecord->filenameMOR);
printf("%c%s%s ", IsRecordReadOnly(pRecord) ? '+' : ' ',
filenameUNI, &kSpaces[len]);
} else {
printf("%c..%-25.25s ", IsRecordReadOnly(pRecord) ? '+' : ' ',
pRecord->filename + len - 25);
filenameUNI = CopyMORToUNI(pRecord->filenameMOR + len - 25);
printf("%c..%s ", IsRecordReadOnly(pRecord) ? '+' : ' ',
filenameUNI);
}
free(filenameUNI);
switch (recordKind) {
case kRecordKindUnknown:
printf("%s- $%04X ",
@ -266,8 +285,10 @@ static NuResult ShowContentsVerbose(NuArchive* pArchive, void* vpRecord)
bail:
if (err != kNuErrNone) {
printf("(ERROR on '%s')\n", pRecord->filename == NULL ?
"<unknown>" : (const char*)pRecord->filename);
filenameUNI = CopyMORToUNI(pRecord->filenameMOR);
printf("(ERROR on '%s')\n",
filenameUNI == NULL ? "<unknown>" : filenameUNI);
free(filenameUNI);
}
return kNuOK;
}

View File

@ -1,19 +1,19 @@
/*
* Nulib2
* NuLib2
* 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.
*
* Main entry point and shell command argument processing.
*/
#include "Nulib2.h"
#include "NuLib2.h"
#include <ctype.h>
/*
* 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)
{
long majorVersion, minorVersion, bugVersion;
int32_t majorVersion, minorVersion, bugVersion;
const char* nufxLibDate;
const char* nufxLibFlags;
(void) NuGetVersion(&majorVersion, &minorVersion, &bugVersion,
&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),
majorVersion, minorVersion, bugVersion, nufxLibFlags);
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)
{
NulibState* pState = NULL;
long majorVersion, minorVersion, bugVersion;
int32_t majorVersion, minorVersion, bugVersion;
int result = 0;
(void) NuGetVersion(&majorVersion, &minorVersion, &bugVersion, NULL, NULL);
if (majorVersion != kNuVersionMajor || minorVersion < kNuVersionMinor) {
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,
majorVersion, minorVersion, bugVersion);
goto bail;

View File

@ -141,8 +141,19 @@ baktar:
@gzip -9 nulib2.tar
@mv -i nulib2.tar.gz /home/fadden/BAK/
depend:
makedepend -- $(CFLAGS) -- $(SRCS)
# DO NOT DELETE THIS LINE -- make depend depends on it.
# dependency info
COMMON_HDRS = NuLib2.h SysDefs.h State.h MiscStuff.h config.h \
$(NUFXSRCDIR)/NufxLib.h
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.
* This is free software; you can redistribute it and/or modify it under the
* terms of the BSD License, see the file COPYING.
*
* Misc support functions.
*/
#define __MiscUtils_c__
#include "Nulib2.h"
#include "NuLib2.h"
/*
@ -113,3 +112,27 @@ NuResult FreeCallback(NuArchive* pArchive, void* args)
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.
* This is free software; you can redistribute it and/or modify it under the
* terms of the BSD License, see the file COPYING.
@ -98,6 +98,7 @@ void* Realloc(void* ptr, size_t size);
void Free(void* ptr);
#endif
NuResult FreeCallback(NuArchive* pArchive, void* args);
UNICHAR* CopyMORToUNI(const char* stringMOR);
/* SysUtils.c */
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.
* This is free software; you can redistribute it and/or modify it under the
* terms of the BSD License, see the file COPYING.
*
* 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)
{

View File

@ -1,5 +1,5 @@
/*
* Nulib2
* NuLib2
* 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.
@ -11,7 +11,7 @@
#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.)
*/

View File

@ -1,5 +1,5 @@
/*
* Nulib2
* NuLib2
* 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.

View File

@ -1,12 +1,12 @@
/*
* Nulib2
* NuLib2
* 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.
*
* System-dependent utility functions.
*/
#include "Nulib2.h"
#include "NuLib2.h"
#ifdef HAVE_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
* 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)
{
Boolean wasPreserved;
@ -442,14 +442,14 @@ static NuError GetFileDetails(NulibState* pState, const char* pathname,
time_t now;
Assert(pState != NULL);
Assert(pathname != NULL);
Assert(pathnameMOR != NULL);
Assert(pDetails != NULL);
/* 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);
Assert(livePathStr != NULL);
strcpy(livePathStr, pathname);
strcpy(livePathStr, pathnameMOR);
/* under Win32, both '/' and '\' work... we want to settle on one */
if (NState_GetAltSystemPathSeparator(pState) != '\0') {
@ -462,7 +462,7 @@ static NuError GetFileDetails(NulibState* pState, const char* pathname,
/* init to defaults */
memset(pDetails, 0, sizeof(*pDetails));
pDetails->threadID = kNuThreadIDDataFork;
pDetails->storageName = livePathStr; /* point at temp buffer */
pDetails->storageNameMOR = livePathStr; /* point at temp buffer */
pDetails->origName = NULL;
pDetails->fileSysID = kNuFileSysUnknown;
pDetails->fileSysInfo = kStorageFssep;