diff --git a/nufxlib/.gitignore b/nufxlib/.gitignore index 78ae93c..0f68fbd 100644 --- a/nufxlib/.gitignore +++ b/nufxlib/.gitignore @@ -11,5 +11,6 @@ samples/imgconv samples/launder samples/test-basic samples/test-extract +samples/test-names samples/test-simple samples/test-twirl diff --git a/nufxlib/Archive.c b/nufxlib/Archive.c index caefda2..7c97cb3 100644 --- a/nufxlib/Archive.c +++ b/nufxlib/Archive.c @@ -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); } diff --git a/nufxlib/Bzip2.c b/nufxlib/Bzip2.c index d3d0365..6515e21 100644 --- a/nufxlib/Bzip2.c +++ b/nufxlib/Bzip2.c @@ -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; } diff --git a/nufxlib/Charset.c b/nufxlib/Charset.c new file mode 100644 index 0000000..c1778b3 --- /dev/null +++ b/nufxlib/Charset.c @@ -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; +} + diff --git a/nufxlib/Crc16.c b/nufxlib/Crc16.c index 8c49a1f..fd49b90 100644 --- a/nufxlib/Crc16.c +++ b/nufxlib/Crc16.c @@ -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 diff --git a/nufxlib/Debug.c b/nufxlib/Debug.c index 7f06ec0..8a704f9 100644 --- a/nufxlib/Debug.c +++ b/nufxlib/Debug.c @@ -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 ? "" : pRecord->filename, + filenameUNI == NULL ? "" : 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 */ diff --git a/nufxlib/Deferred.c b/nufxlib/Deferred.c index e368720..c5f293d 100644 --- a/nufxlib/Deferred.c +++ b/nufxlib/Deferred.c @@ -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 */ } diff --git a/nufxlib/Entry.c b/nufxlib/Entry.c index 9f93d6d..12a805c 100644 --- a/nufxlib/Entry.c +++ b/nufxlib/Entry.c @@ -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); +} + /* * =========================================================================== diff --git a/nufxlib/FileIO.c b/nufxlib/FileIO.c index 60038d4..02d3888 100644 --- a/nufxlib/FileIO.c +++ b/nufxlib/FileIO.c @@ -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 diff --git a/nufxlib/Funnel.c b/nufxlib/Funnel.c index d7fa6c6..58a0797 100644 --- a/nufxlib/Funnel.c +++ b/nufxlib/Funnel.c @@ -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; diff --git a/nufxlib/Makefile.in b/nufxlib/Makefile.in index 8307c9f..66c2ae4 100644 --- a/nufxlib/Makefile.in +++ b/nufxlib/Makefile.in @@ -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 diff --git a/nufxlib/Makefile.msc b/nufxlib/Makefile.msc index aafb34c..8c2bb90 100644 --- a/nufxlib/Makefile.msc +++ b/nufxlib/Makefile.msc @@ -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) diff --git a/nufxlib/MiscUtils.c b/nufxlib/MiscUtils.c index 28590a3..a3efd53 100644 --- a/nufxlib/MiscUtils.c +++ b/nufxlib/MiscUtils.c @@ -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; diff --git a/nufxlib/NufxLib.h b/nufxlib/NufxLib.h index 80ade62..57c70ad 100644 --- a/nufxlib/NufxLib.h +++ b/nufxlib/NufxLib.h @@ -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 +//# 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) \ ) diff --git a/nufxlib/NufxLibPriv.h b/nufxlib/NufxLibPriv.h index 3c2d714..d1e449a 100644 --- a/nufxlib/NufxLibPriv.h +++ b/nufxlib/NufxLibPriv.h @@ -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*/ diff --git a/nufxlib/README.txt b/nufxlib/README.txt index 61bb8c9..0b54194 100644 --- a/nufxlib/README.txt +++ b/nufxlib/README.txt @@ -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 ======== diff --git a/nufxlib/Record.c b/nufxlib/Record.c index 3f1859d..d77899c 100644 --- a/nufxlib/Record.c +++ b/nufxlib/Record.c @@ -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; } diff --git a/nufxlib/SourceSink.c b/nufxlib/SourceSink.c index 1385380..e5d6313 100644 --- a/nufxlib/SourceSink.c +++ b/nufxlib/SourceSink.c @@ -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); diff --git a/nufxlib/SysDefs.h b/nufxlib/SysDefs.h index 290f759..2b3a01a 100644 --- a/nufxlib/SysDefs.h +++ b/nufxlib/SysDefs.h @@ -69,6 +69,7 @@ # define HAVE_CHSIZE # define snprintf _snprintf # define vsnprintf _vsnprintf + #endif #ifdef HAVE_MALLOC_H diff --git a/nufxlib/Thread.c b/nufxlib/Thread.c index 7bc7d88..efad155 100644 --- a/nufxlib/Thread.c +++ b/nufxlib/Thread.c @@ -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; diff --git a/nufxlib/Version.c b/nufxlib/Version.c index b3ba91b..9c3396c 100644 --- a/nufxlib/Version.c +++ b/nufxlib/Version.c @@ -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; diff --git a/nufxlib/nufxlib.def b/nufxlib/nufxlib.def index 0fc2673..ad33e3e 100644 --- a/nufxlib/nufxlib.def +++ b/nufxlib/nufxlib.def @@ -16,6 +16,8 @@ EXPORTS NuAddThread NuClose NuContents + NuConvertMORToUNI + NuConvertUNIToMOR NuCreateDataSinkForBuffer NuCreateDataSinkForFP NuCreateDataSinkForFile diff --git a/nufxlib/samples/Common.h b/nufxlib/samples/Common.h index a8c1aa2..2391747 100644 --- a/nufxlib/samples/Common.h +++ b/nufxlib/samples/Common.h @@ -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*/ diff --git a/nufxlib/samples/Exerciser.c b/nufxlib/samples/Exerciser.c index 86b29cd..18b72dc 100644 --- a/nufxlib/samples/Exerciser.c +++ b/nufxlib/samples/Exerciser.c @@ -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 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"); diff --git a/nufxlib/samples/ImgConv.c b/nufxlib/samples/ImgConv.c index 5e6fd7f..620b827 100644 --- a/nufxlib/samples/ImgConv.c +++ b/nufxlib/samples/ImgConv.c @@ -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; diff --git a/nufxlib/samples/Launder.c b/nufxlib/samples/Launder.c index 5face0d..fba4913 100644 --- a/nufxlib/samples/Launder.c +++ b/nufxlib/samples/Launder.c @@ -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; diff --git a/nufxlib/samples/Makefile.in b/nufxlib/samples/Makefile.in index 6590a08..ca765ef 100644 --- a/nufxlib/samples/Makefile.in +++ b/nufxlib/samples/Makefile.in @@ -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) diff --git a/nufxlib/samples/TestBasic.c b/nufxlib/samples/TestBasic.c index 5cd2d85..2559608 100644 --- a/nufxlib/samples/TestBasic.c +++ b/nufxlib/samples/TestBasic.c @@ -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); diff --git a/nufxlib/samples/TestExtract.c b/nufxlib/samples/TestExtract.c index f3470be..4e8bfb2 100644 --- a/nufxlib/samples/TestExtract.c +++ b/nufxlib/samples/TestExtract.c @@ -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(""); + if (pRecord->filenameMOR == NULL) + pArcRec->filenameMOR = strdup(""); 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 ? "":(const char*)pRecord->filename); + pRecord->filenameMOR == NULL ? + "" : 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) { diff --git a/nufxlib/samples/TestNames.c b/nufxlib/samples/TestNames.c new file mode 100644 index 0000000..8d0029b --- /dev/null +++ b/nufxlib/samples/TestNames.c @@ -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 +#include +#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); +} + diff --git a/nufxlib/samples/TestSimple.c b/nufxlib/samples/TestSimple.c index 2b6e1ca..cc77e8b 100644 --- a/nufxlib/samples/TestSimple.c +++ b/nufxlib/samples/TestSimple.c @@ -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) { diff --git a/nufxlib/samples/TestTwirl.c b/nufxlib/samples/TestTwirl.c index 1d8e221..8e8c34e 100644 --- a/nufxlib/samples/TestTwirl.c +++ b/nufxlib/samples/TestTwirl.c @@ -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) { diff --git a/nulib2/Add.c b/nulib2/Add.c index 3413e8b..809b172 100644 --- a/nulib2/Add.c +++ b/nulib2/Add.c @@ -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); diff --git a/nulib2/ArcUtils.c b/nulib2/ArcUtils.c index 7d6a031..400e410 100644 --- a/nulib2/ArcUtils.c +++ b/nulib2/ArcUtils.c @@ -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'); diff --git a/nulib2/Binary2.c b/nulib2/Binary2.c index 38ef6b1..9cd0eff 100644 --- a/nulib2/Binary2.c +++ b/nulib2/Binary2.c @@ -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 @@ -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; diff --git a/nulib2/Delete.c b/nulib2/Delete.c index 2c502c3..92aeebe 100644 --- a/nulib2/Delete.c +++ b/nulib2/Delete.c @@ -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" /* diff --git a/nulib2/Extract.c b/nulib2/Extract.c index 27c9c28..0498502 100644 --- a/nulib2/Extract.c +++ b/nulib2/Extract.c @@ -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) { diff --git a/nulib2/Filename.c b/nulib2/Filename.c index c6a1188..51c374c 100644 --- a/nulib2/Filename.c +++ b/nulib2/Filename.c @@ -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 @@ -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 */ diff --git a/nulib2/List.c b/nulib2/List.c index 2b38a80..0511b43 100644 --- a/nulib2/List.c +++ b/nulib2/List.c @@ -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 ? "":(const char*)pRecord->filename); + UNICHAR* filenameUNI = CopyMORToUNI(pRecord->filenameMOR); + printf("%s\n", filenameUNI == NULL ? "" : 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 ? - "" : (const char*)pRecord->filename); + filenameUNI = CopyMORToUNI(pRecord->filenameMOR); + printf("(ERROR on '%s')\n", + filenameUNI == NULL ? "" : filenameUNI); + free(filenameUNI); } return kNuOK; } diff --git a/nulib2/Main.c b/nulib2/Main.c index 83b3408..0955081 100644 --- a/nulib2/Main.c +++ b/nulib2/Main.c @@ -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 /* * 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; diff --git a/nulib2/Makefile.in b/nulib2/Makefile.in index aa97fd9..2c81380 100644 --- a/nulib2/Makefile.in +++ b/nulib2/Makefile.in @@ -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) diff --git a/nulib2/MiscUtils.c b/nulib2/MiscUtils.c index c3bfc6f..2b3c3e2 100644 --- a/nulib2/MiscUtils.c +++ b/nulib2/MiscUtils.c @@ -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; +} + diff --git a/nulib2/Nulib2.h b/nulib2/NuLib2.h similarity index 98% rename from nulib2/Nulib2.h rename to nulib2/NuLib2.h index 2323f65..1f2cc2f 100644 --- a/nulib2/Nulib2.h +++ b/nulib2/NuLib2.h @@ -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, diff --git a/nulib2/State.c b/nulib2/State.c index c040723..a64bf2f 100644 --- a/nulib2/State.c +++ b/nulib2/State.c @@ -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) { diff --git a/nulib2/State.h b/nulib2/State.h index 0ae31ae..5f5e8c8 100644 --- a/nulib2/State.h +++ b/nulib2/State.h @@ -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.) */ diff --git a/nulib2/SysDefs.h b/nulib2/SysDefs.h index b7b7844..215ec94 100644 --- a/nulib2/SysDefs.h +++ b/nulib2/SysDefs.h @@ -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. diff --git a/nulib2/SysUtils.c b/nulib2/SysUtils.c index e21806c..b1e917e 100644 --- a/nulib2/SysUtils.c +++ b/nulib2/SysUtils.c @@ -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 @@ -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;