nulib2/nulib2/ArcUtils.c

977 lines
28 KiB
C
Raw Normal View History

2000-05-23 01:55:31 +00:00
/*
Distinguish Unicode and Mac OS Roman strings NufxLib has historically made no effort to distinguish between the character set used for filenames on the local disk, and for filenames stored within the archive. Now all Unicode filename strings use the UNICHAR type and have "UNI" in the name, and all Mac OS Roman strings have "MOR" in the name. (The naming convention makes it obvious when you're assigning the wrong thing; on Linux both formats are char*, so the compiler won't tell you if you get it wrong.) The distinction is necessary because filesystems generally support Unicode these days, but on Windows you need to use a separate set of wide-character file I/O functions. (On Linux it all works with "narrow" strings, and the UTF-8 encoding is interpreted by applications.) The character set used for NuFX archive filenames is MOR, matching what GS/OS + HFS supported, and we want to be able to convert back and forth between MOR and a Unicode representation. This change updates the various character types and string names, adds conversion functions, and updates NuLib2 for proper execution on Linux. It does not include the (probably extensive) changes required for Windows UTF-16 support. Instead, the conversion functions are no-ops, which should result in NuLib2 for Windows continuing to behave in the same slightly broken way. This adds "test-names", which exercises Unicode filenames a bit. It will not pass on Win32. Also, tweaked the Linux makefiles to have explicit dependencies, rather than empty space and an expectation that "makedepend" exists. Also, minor source code cleanups. While this probably doesn't affect binary compatibility -- it's mainly a matter of naming and string interpretation -- there's enough going on that it should be considered an API revision, so this updates the version to 3.0.0.
2014-12-24 19:14:32 +00:00
* NuLib2
2007-02-19 23:11:55 +00:00
* Copyright (C) 2000-2007 by Andy McFadden, All Rights Reserved.
2000-05-23 01:55:31 +00:00
* This is free software; you can redistribute it and/or modify it under the
2007-02-19 23:11:55 +00:00
* terms of the BSD License, see the file COPYING.
2000-05-23 01:55:31 +00:00
*
* Common archive-related utility functions.
*/
Distinguish Unicode and Mac OS Roman strings NufxLib has historically made no effort to distinguish between the character set used for filenames on the local disk, and for filenames stored within the archive. Now all Unicode filename strings use the UNICHAR type and have "UNI" in the name, and all Mac OS Roman strings have "MOR" in the name. (The naming convention makes it obvious when you're assigning the wrong thing; on Linux both formats are char*, so the compiler won't tell you if you get it wrong.) The distinction is necessary because filesystems generally support Unicode these days, but on Windows you need to use a separate set of wide-character file I/O functions. (On Linux it all works with "narrow" strings, and the UTF-8 encoding is interpreted by applications.) The character set used for NuFX archive filenames is MOR, matching what GS/OS + HFS supported, and we want to be able to convert back and forth between MOR and a Unicode representation. This change updates the various character types and string names, adds conversion functions, and updates NuLib2 for proper execution on Linux. It does not include the (probably extensive) changes required for Windows UTF-16 support. Instead, the conversion functions are no-ops, which should result in NuLib2 for Windows continuing to behave in the same slightly broken way. This adds "test-names", which exercises Unicode filenames a bit. It will not pass on Win32. Also, tweaked the Linux makefiles to have explicit dependencies, rather than empty space and an expectation that "makedepend" exists. Also, minor source code cleanups. While this probably doesn't affect binary compatibility -- it's mainly a matter of naming and string interpretation -- there's enough going on that it should be considered an API revision, so this updates the version to 3.0.0.
2014-12-24 19:14:32 +00:00
#include "NuLib2.h"
2000-05-23 01:55:31 +00:00
/*
* ===========================================================================
* Output pathnames
2000-05-23 01:55:31 +00:00
* ===========================================================================
*/
/*
* General-purpose output pathname filter, invoked by nufxlib via a
* callback. Normalizes the pathname to match the current OS requirements.
*
* If we're extracting to stdout, this fills in the "newFp" field instead.
*
* The buffer we return to the archive library will be overwritten the
* next time this function gets called. This is expected.
*/
static NuResult OutputPathnameFilter(NuArchive* pArchive, void* vproposal)
2000-05-23 01:55:31 +00:00
{
NuPathnameProposal* pathProposal = vproposal;
NulibState* pState;
Distinguish Unicode and Mac OS Roman strings NufxLib has historically made no effort to distinguish between the character set used for filenames on the local disk, and for filenames stored within the archive. Now all Unicode filename strings use the UNICHAR type and have "UNI" in the name, and all Mac OS Roman strings have "MOR" in the name. (The naming convention makes it obvious when you're assigning the wrong thing; on Linux both formats are char*, so the compiler won't tell you if you get it wrong.) The distinction is necessary because filesystems generally support Unicode these days, but on Windows you need to use a separate set of wide-character file I/O functions. (On Linux it all works with "narrow" strings, and the UTF-8 encoding is interpreted by applications.) The character set used for NuFX archive filenames is MOR, matching what GS/OS + HFS supported, and we want to be able to convert back and forth between MOR and a Unicode representation. This change updates the various character types and string names, adds conversion functions, and updates NuLib2 for proper execution on Linux. It does not include the (probably extensive) changes required for Windows UTF-16 support. Instead, the conversion functions are no-ops, which should result in NuLib2 for Windows continuing to behave in the same slightly broken way. This adds "test-names", which exercises Unicode filenames a bit. It will not pass on Win32. Also, tweaked the Linux makefiles to have explicit dependencies, rather than empty space and an expectation that "makedepend" exists. Also, minor source code cleanups. While this probably doesn't affect binary compatibility -- it's mainly a matter of naming and string interpretation -- there's enough going on that it should be considered an API revision, so this updates the version to 3.0.0.
2014-12-24 19:14:32 +00:00
const UNICHAR* newPathnameUNI;
NuRecordIdx renameFromIdx;
Distinguish Unicode and Mac OS Roman strings NufxLib has historically made no effort to distinguish between the character set used for filenames on the local disk, and for filenames stored within the archive. Now all Unicode filename strings use the UNICHAR type and have "UNI" in the name, and all Mac OS Roman strings have "MOR" in the name. (The naming convention makes it obvious when you're assigning the wrong thing; on Linux both formats are char*, so the compiler won't tell you if you get it wrong.) The distinction is necessary because filesystems generally support Unicode these days, but on Windows you need to use a separate set of wide-character file I/O functions. (On Linux it all works with "narrow" strings, and the UTF-8 encoding is interpreted by applications.) The character set used for NuFX archive filenames is MOR, matching what GS/OS + HFS supported, and we want to be able to convert back and forth between MOR and a Unicode representation. This change updates the various character types and string names, adds conversion functions, and updates NuLib2 for proper execution on Linux. It does not include the (probably extensive) changes required for Windows UTF-16 support. Instead, the conversion functions are no-ops, which should result in NuLib2 for Windows continuing to behave in the same slightly broken way. This adds "test-names", which exercises Unicode filenames a bit. It will not pass on Win32. Also, tweaked the Linux makefiles to have explicit dependencies, rather than empty space and an expectation that "makedepend" exists. Also, minor source code cleanups. While this probably doesn't affect binary compatibility -- it's mainly a matter of naming and string interpretation -- there's enough going on that it should be considered an API revision, so this updates the version to 3.0.0.
2014-12-24 19:14:32 +00:00
UNICHAR* renameToStrUNI;
UNICHAR* resultBufUNI;
2014-12-22 02:17:23 +00:00
Assert(pArchive != NULL);
(void) NuGetExtraData(pArchive, (void**) &pState);
2014-12-22 02:17:23 +00:00
Assert(pState != NULL);
/* handle extract-to-pipe */
if (NState_GetCommand(pState) == kCommandExtractToPipe) {
pathProposal->newDataSink = NState_GetPipeSink(pState);
NState_SetSuppressOutput(pState, true);
return kNuOK;
}
/*
* If they're trying to rename this file, do so now. We don't run
* 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).
*/
Distinguish Unicode and Mac OS Roman strings NufxLib has historically made no effort to distinguish between the character set used for filenames on the local disk, and for filenames stored within the archive. Now all Unicode filename strings use the UNICHAR type and have "UNI" in the name, and all Mac OS Roman strings have "MOR" in the name. (The naming convention makes it obvious when you're assigning the wrong thing; on Linux both formats are char*, so the compiler won't tell you if you get it wrong.) The distinction is necessary because filesystems generally support Unicode these days, but on Windows you need to use a separate set of wide-character file I/O functions. (On Linux it all works with "narrow" strings, and the UTF-8 encoding is interpreted by applications.) The character set used for NuFX archive filenames is MOR, matching what GS/OS + HFS supported, and we want to be able to convert back and forth between MOR and a Unicode representation. This change updates the various character types and string names, adds conversion functions, and updates NuLib2 for proper execution on Linux. It does not include the (probably extensive) changes required for Windows UTF-16 support. Instead, the conversion functions are no-ops, which should result in NuLib2 for Windows continuing to behave in the same slightly broken way. This adds "test-names", which exercises Unicode filenames a bit. It will not pass on Win32. Also, tweaked the Linux makefiles to have explicit dependencies, rather than empty space and an expectation that "makedepend" exists. Also, minor source code cleanups. While this probably doesn't affect binary compatibility -- it's mainly a matter of naming and string interpretation -- there's enough going on that it should be considered an API revision, so this updates the version to 3.0.0.
2014-12-24 19:14:32 +00:00
renameToStrUNI = NState_GetRenameToStr(pState);
if (renameToStrUNI != NULL) {
renameFromIdx = NState_GetRenameFromIdx(pState);
if (renameFromIdx == pathProposal->pRecord->recordIdx) {
/* right source file, proceed with the rename */
Distinguish Unicode and Mac OS Roman strings NufxLib has historically made no effort to distinguish between the character set used for filenames on the local disk, and for filenames stored within the archive. Now all Unicode filename strings use the UNICHAR type and have "UNI" in the name, and all Mac OS Roman strings have "MOR" in the name. (The naming convention makes it obvious when you're assigning the wrong thing; on Linux both formats are char*, so the compiler won't tell you if you get it wrong.) The distinction is necessary because filesystems generally support Unicode these days, but on Windows you need to use a separate set of wide-character file I/O functions. (On Linux it all works with "narrow" strings, and the UTF-8 encoding is interpreted by applications.) The character set used for NuFX archive filenames is MOR, matching what GS/OS + HFS supported, and we want to be able to convert back and forth between MOR and a Unicode representation. This change updates the various character types and string names, adds conversion functions, and updates NuLib2 for proper execution on Linux. It does not include the (probably extensive) changes required for Windows UTF-16 support. Instead, the conversion functions are no-ops, which should result in NuLib2 for Windows continuing to behave in the same slightly broken way. This adds "test-names", which exercises Unicode filenames a bit. It will not pass on Win32. Also, tweaked the Linux makefiles to have explicit dependencies, rather than empty space and an expectation that "makedepend" exists. Also, minor source code cleanups. While this probably doesn't affect binary compatibility -- it's mainly a matter of naming and string interpretation -- there's enough going on that it should be considered an API revision, so this updates the version to 3.0.0.
2014-12-24 19:14:32 +00:00
NState_SetTempPathnameLen(pState, strlen(renameToStrUNI) +1);
resultBufUNI = NState_GetTempPathnameBuf(pState);
Assert(resultBufUNI != NULL);
strcpy(resultBufUNI, renameToStrUNI);
Distinguish Unicode and Mac OS Roman strings NufxLib has historically made no effort to distinguish between the character set used for filenames on the local disk, and for filenames stored within the archive. Now all Unicode filename strings use the UNICHAR type and have "UNI" in the name, and all Mac OS Roman strings have "MOR" in the name. (The naming convention makes it obvious when you're assigning the wrong thing; on Linux both formats are char*, so the compiler won't tell you if you get it wrong.) The distinction is necessary because filesystems generally support Unicode these days, but on Windows you need to use a separate set of wide-character file I/O functions. (On Linux it all works with "narrow" strings, and the UTF-8 encoding is interpreted by applications.) The character set used for NuFX archive filenames is MOR, matching what GS/OS + HFS supported, and we want to be able to convert back and forth between MOR and a Unicode representation. This change updates the various character types and string names, adds conversion functions, and updates NuLib2 for proper execution on Linux. It does not include the (probably extensive) changes required for Windows UTF-16 support. Instead, the conversion functions are no-ops, which should result in NuLib2 for Windows continuing to behave in the same slightly broken way. This adds "test-names", which exercises Unicode filenames a bit. It will not pass on Win32. Also, tweaked the Linux makefiles to have explicit dependencies, rather than empty space and an expectation that "makedepend" exists. Also, minor source code cleanups. While this probably doesn't affect binary compatibility -- it's mainly a matter of naming and string interpretation -- there's enough going on that it should be considered an API revision, so this updates the version to 3.0.0.
2014-12-24 19:14:32 +00:00
pathProposal->newPathnameUNI = resultBufUNI;
}
Distinguish Unicode and Mac OS Roman strings NufxLib has historically made no effort to distinguish between the character set used for filenames on the local disk, and for filenames stored within the archive. Now all Unicode filename strings use the UNICHAR type and have "UNI" in the name, and all Mac OS Roman strings have "MOR" in the name. (The naming convention makes it obvious when you're assigning the wrong thing; on Linux both formats are char*, so the compiler won't tell you if you get it wrong.) The distinction is necessary because filesystems generally support Unicode these days, but on Windows you need to use a separate set of wide-character file I/O functions. (On Linux it all works with "narrow" strings, and the UTF-8 encoding is interpreted by applications.) The character set used for NuFX archive filenames is MOR, matching what GS/OS + HFS supported, and we want to be able to convert back and forth between MOR and a Unicode representation. This change updates the various character types and string names, adds conversion functions, and updates NuLib2 for proper execution on Linux. It does not include the (probably extensive) changes required for Windows UTF-16 support. Instead, the conversion functions are no-ops, which should result in NuLib2 for Windows continuing to behave in the same slightly broken way. This adds "test-names", which exercises Unicode filenames a bit. It will not pass on Win32. Also, tweaked the Linux makefiles to have explicit dependencies, rather than empty space and an expectation that "makedepend" exists. Also, minor source code cleanups. While this probably doesn't affect binary compatibility -- it's mainly a matter of naming and string interpretation -- there's enough going on that it should be considered an API revision, so this updates the version to 3.0.0.
2014-12-24 19:14:32 +00:00
/* free up renameToStrUNI */
2014-12-22 02:17:23 +00:00
NState_SetRenameToStr(pState, NULL);
goto bail;
}
/*
* Convert the pathname into something suitable for the current OS.
*/
Distinguish Unicode and Mac OS Roman strings NufxLib has historically made no effort to distinguish between the character set used for filenames on the local disk, and for filenames stored within the archive. Now all Unicode filename strings use the UNICHAR type and have "UNI" in the name, and all Mac OS Roman strings have "MOR" in the name. (The naming convention makes it obvious when you're assigning the wrong thing; on Linux both formats are char*, so the compiler won't tell you if you get it wrong.) The distinction is necessary because filesystems generally support Unicode these days, but on Windows you need to use a separate set of wide-character file I/O functions. (On Linux it all works with "narrow" strings, and the UTF-8 encoding is interpreted by applications.) The character set used for NuFX archive filenames is MOR, matching what GS/OS + HFS supported, and we want to be able to convert back and forth between MOR and a Unicode representation. This change updates the various character types and string names, adds conversion functions, and updates NuLib2 for proper execution on Linux. It does not include the (probably extensive) changes required for Windows UTF-16 support. Instead, the conversion functions are no-ops, which should result in NuLib2 for Windows continuing to behave in the same slightly broken way. This adds "test-names", which exercises Unicode filenames a bit. It will not pass on Win32. Also, tweaked the Linux makefiles to have explicit dependencies, rather than empty space and an expectation that "makedepend" exists. Also, minor source code cleanups. While this probably doesn't affect binary compatibility -- it's mainly a matter of naming and string interpretation -- there's enough going on that it should be considered an API revision, so this updates the version to 3.0.0.
2014-12-24 19:14:32 +00:00
newPathnameUNI = NormalizePath(pState, pathProposal);
if (newPathnameUNI == NULL) {
ReportError(kNuErrNone, "unable to convert pathname");
return kNuAbort;
}
Distinguish Unicode and Mac OS Roman strings NufxLib has historically made no effort to distinguish between the character set used for filenames on the local disk, and for filenames stored within the archive. Now all Unicode filename strings use the UNICHAR type and have "UNI" in the name, and all Mac OS Roman strings have "MOR" in the name. (The naming convention makes it obvious when you're assigning the wrong thing; on Linux both formats are char*, so the compiler won't tell you if you get it wrong.) The distinction is necessary because filesystems generally support Unicode these days, but on Windows you need to use a separate set of wide-character file I/O functions. (On Linux it all works with "narrow" strings, and the UTF-8 encoding is interpreted by applications.) The character set used for NuFX archive filenames is MOR, matching what GS/OS + HFS supported, and we want to be able to convert back and forth between MOR and a Unicode representation. This change updates the various character types and string names, adds conversion functions, and updates NuLib2 for proper execution on Linux. It does not include the (probably extensive) changes required for Windows UTF-16 support. Instead, the conversion functions are no-ops, which should result in NuLib2 for Windows continuing to behave in the same slightly broken way. This adds "test-names", which exercises Unicode filenames a bit. It will not pass on Win32. Also, tweaked the Linux makefiles to have explicit dependencies, rather than empty space and an expectation that "makedepend" exists. Also, minor source code cleanups. While this probably doesn't affect binary compatibility -- it's mainly a matter of naming and string interpretation -- there's enough going on that it should be considered an API revision, so this updates the version to 3.0.0.
2014-12-24 19:14:32 +00:00
pathProposal->newPathnameUNI = newPathnameUNI;
2000-05-23 01:55:31 +00:00
bail:
return kNuOK;
2000-05-23 01:55:31 +00:00
}
/*
* ===========================================================================
* User input
2000-05-23 01:55:31 +00:00
* ===========================================================================
*/
/*
* Get a single character from the input.
*
* For portability, I'm just getting a line of input and keeping the
* first character. A fancier version would play with line disciplines
* so you wouldn't have to hit "return".
*/
static char GetReplyChar(char defaultReply)
2000-05-23 01:55:31 +00:00
{
char tmpBuf[32];
2000-05-23 01:55:31 +00:00
2014-12-22 02:17:23 +00:00
if (fgets(tmpBuf, sizeof(tmpBuf), stdin) == NULL)
return defaultReply;
if (tmpBuf[0] == '\n' || tmpBuf[0] == '\r')
return defaultReply;
2000-05-23 01:55:31 +00:00
return tmpBuf[0];
2000-05-23 01:55:31 +00:00
}
#define kMaxInputLen 128
2000-05-23 01:55:31 +00:00
/*
* Get a string back from the user.
*
* String returned should be freed by the caller.
*/
static char* GetReplyString(const char* prompt)
2000-05-23 01:55:31 +00:00
{
char buf[kMaxInputLen];
char* result;
int len;
printf("%s", prompt);
fflush(stdout);
result = fgets(buf, sizeof(buf), stdin);
2014-12-22 02:17:23 +00:00
if (result == NULL || feof(stdin) || ferror(stdin) || buf[0] == '\0' ||
buf[0] == '\n')
{
2014-12-22 02:17:23 +00:00
return NULL;
}
/* nuke the terminating '\n', which is lots of fun in filenames */
len = strlen(buf);
if (buf[len-1] == '\n')
buf[len-1] = '\0';
return strdup(buf);
2000-05-23 01:55:31 +00:00
}
/*
* Get a one-line comment from the user, of at most "maxLen" bytes.
*
2014-12-22 02:17:23 +00:00
* If the user enters a blank line, return "NULL".
2000-05-23 01:55:31 +00:00
*
* A pointer to a newly-allocated buffer is returned.
*/
char* GetSimpleComment(NulibState* pState, const char* pathname, int maxLen)
2000-05-23 01:55:31 +00:00
{
2014-12-22 02:17:23 +00:00
char* buf = NULL;
char* result;
int len;
buf = Malloc(maxLen);
2014-12-22 02:17:23 +00:00
if (buf == NULL)
return NULL;
printf("Enter one-line comment for '%s'\n: ", pathname);
fflush(stdout);
result = fgets(buf, maxLen, stdin);
2014-12-22 02:17:23 +00:00
if (result == NULL || feof(stdin) || ferror(stdin) || buf[0] == '\0' ||
buf[0] == '\n')
{
Free(buf);
2014-12-22 02:17:23 +00:00
return NULL;
}
/* nuke the terminating '\n', which we don't need */
len = strlen(buf);
if (buf[len-1] == '\n')
buf[len-1] = '\0';
return buf;
2000-05-23 01:55:31 +00:00
}
/*
* ===========================================================================
* Callbacks (progress updates, error handling, record selection)
2000-05-23 01:55:31 +00:00
* ===========================================================================
*/
#define kMaxDisplayLen 60
2000-05-23 01:55:31 +00:00
/*
* Returns "true" if the filespec in "spec" matches what's in "pRecord".
*
* (Someday "spec" might be a regexp.)
*/
static Boolean SpecMatchesRecord(NulibState* pState, const char* spec,
const NuRecord* pRecord)
2000-05-23 01:55:31 +00:00
{
#ifdef NU_CASE_SENSITIVE
if (NState_GetModRecurse(pState))
return (strncmp(spec, pRecord->filename, strlen(spec)) == 0);
else
return (strcmp(spec, pRecord->filename) == 0);
#else
if (NState_GetModRecurse(pState))
Distinguish Unicode and Mac OS Roman strings NufxLib has historically made no effort to distinguish between the character set used for filenames on the local disk, and for filenames stored within the archive. Now all Unicode filename strings use the UNICHAR type and have "UNI" in the name, and all Mac OS Roman strings have "MOR" in the name. (The naming convention makes it obvious when you're assigning the wrong thing; on Linux both formats are char*, so the compiler won't tell you if you get it wrong.) The distinction is necessary because filesystems generally support Unicode these days, but on Windows you need to use a separate set of wide-character file I/O functions. (On Linux it all works with "narrow" strings, and the UTF-8 encoding is interpreted by applications.) The character set used for NuFX archive filenames is MOR, matching what GS/OS + HFS supported, and we want to be able to convert back and forth between MOR and a Unicode representation. This change updates the various character types and string names, adds conversion functions, and updates NuLib2 for proper execution on Linux. It does not include the (probably extensive) changes required for Windows UTF-16 support. Instead, the conversion functions are no-ops, which should result in NuLib2 for Windows continuing to behave in the same slightly broken way. This adds "test-names", which exercises Unicode filenames a bit. It will not pass on Win32. Also, tweaked the Linux makefiles to have explicit dependencies, rather than empty space and an expectation that "makedepend" exists. Also, minor source code cleanups. While this probably doesn't affect binary compatibility -- it's mainly a matter of naming and string interpretation -- there's enough going on that it should be considered an API revision, so this updates the version to 3.0.0.
2014-12-24 19:14:32 +00:00
return (strncasecmp(spec, pRecord->filenameMOR, strlen(spec)) == 0);
else
Distinguish Unicode and Mac OS Roman strings NufxLib has historically made no effort to distinguish between the character set used for filenames on the local disk, and for filenames stored within the archive. Now all Unicode filename strings use the UNICHAR type and have "UNI" in the name, and all Mac OS Roman strings have "MOR" in the name. (The naming convention makes it obvious when you're assigning the wrong thing; on Linux both formats are char*, so the compiler won't tell you if you get it wrong.) The distinction is necessary because filesystems generally support Unicode these days, but on Windows you need to use a separate set of wide-character file I/O functions. (On Linux it all works with "narrow" strings, and the UTF-8 encoding is interpreted by applications.) The character set used for NuFX archive filenames is MOR, matching what GS/OS + HFS supported, and we want to be able to convert back and forth between MOR and a Unicode representation. This change updates the various character types and string names, adds conversion functions, and updates NuLib2 for proper execution on Linux. It does not include the (probably extensive) changes required for Windows UTF-16 support. Instead, the conversion functions are no-ops, which should result in NuLib2 for Windows continuing to behave in the same slightly broken way. This adds "test-names", which exercises Unicode filenames a bit. It will not pass on Win32. Also, tweaked the Linux makefiles to have explicit dependencies, rather than empty space and an expectation that "makedepend" exists. Also, minor source code cleanups. While this probably doesn't affect binary compatibility -- it's mainly a matter of naming and string interpretation -- there's enough going on that it should be considered an API revision, so this updates the version to 3.0.0.
2014-12-24 19:14:32 +00:00
return (strcasecmp(spec, pRecord->filenameMOR) == 0);
#endif
2000-05-23 01:55:31 +00:00
}
/*
* Determine whether the current record we're examining is described by
* the file specification given on the command line.
*
* If no filespec was provided, then all records are "specified".
*
* We pass the entire NuRecord in because we may want to allow
* extraction by criteria other than name, e.g. all text files or all
* files archived before a certain date.
2000-05-23 01:55:31 +00:00
*/
Boolean IsSpecified(NulibState* pState, const NuRecord* pRecord)
2000-05-23 01:55:31 +00:00
{
char* const* pSpec;
int i;
2000-05-23 01:55:31 +00:00
if (!NState_GetFilespecCount(pState))
return true;
2000-05-23 01:55:31 +00:00
pSpec = NState_GetFilespecPointer(pState);
for (i = NState_GetFilespecCount(pState); i > 0; i--, pSpec++) {
if (SpecMatchesRecord(pState, *pSpec, pRecord))
return true;
}
2000-05-23 01:55:31 +00:00
return false;
2000-05-23 01:55:31 +00:00
}
/*
* General-purpose selection filter, invoked as a callback. Compares the
* selection proposal with the filenames in "filespec".
*/
NuResult SelectionFilter(NuArchive* pArchive, void* vproposal)
2000-05-23 01:55:31 +00:00
{
const NuSelectionProposal* selProposal = vproposal;
NulibState* pState;
2000-05-23 01:55:31 +00:00
2014-12-22 02:17:23 +00:00
Assert(pArchive != NULL);
(void) NuGetExtraData(pArchive, (void**) &pState);
2014-12-22 02:17:23 +00:00
Assert(pState != NULL);
2000-05-23 01:55:31 +00:00
if (IsSpecified(pState, selProposal->pRecord)) {
NState_IncMatchCount(pState);
2000-05-23 01:55:31 +00:00
/* we don't get progress notifications for delete, so do it here */
Distinguish Unicode and Mac OS Roman strings NufxLib has historically made no effort to distinguish between the character set used for filenames on the local disk, and for filenames stored within the archive. Now all Unicode filename strings use the UNICHAR type and have "UNI" in the name, and all Mac OS Roman strings have "MOR" in the name. (The naming convention makes it obvious when you're assigning the wrong thing; on Linux both formats are char*, so the compiler won't tell you if you get it wrong.) The distinction is necessary because filesystems generally support Unicode these days, but on Windows you need to use a separate set of wide-character file I/O functions. (On Linux it all works with "narrow" strings, and the UTF-8 encoding is interpreted by applications.) The character set used for NuFX archive filenames is MOR, matching what GS/OS + HFS supported, and we want to be able to convert back and forth between MOR and a Unicode representation. This change updates the various character types and string names, adds conversion functions, and updates NuLib2 for proper execution on Linux. It does not include the (probably extensive) changes required for Windows UTF-16 support. Instead, the conversion functions are no-ops, which should result in NuLib2 for Windows continuing to behave in the same slightly broken way. This adds "test-names", which exercises Unicode filenames a bit. It will not pass on Win32. Also, tweaked the Linux makefiles to have explicit dependencies, rather than empty space and an expectation that "makedepend" exists. Also, minor source code cleanups. While this probably doesn't affect binary compatibility -- it's mainly a matter of naming and string interpretation -- there's enough going on that it should be considered an API revision, so this updates the version to 3.0.0.
2014-12-24 19:14:32 +00:00
if (NState_GetCommand(pState) == kCommandDelete) {
printf("Deleting %s\n", selProposal->pRecord->filenameMOR);
}
2000-05-23 01:55:31 +00:00
return kNuOK;
Distinguish Unicode and Mac OS Roman strings NufxLib has historically made no effort to distinguish between the character set used for filenames on the local disk, and for filenames stored within the archive. Now all Unicode filename strings use the UNICHAR type and have "UNI" in the name, and all Mac OS Roman strings have "MOR" in the name. (The naming convention makes it obvious when you're assigning the wrong thing; on Linux both formats are char*, so the compiler won't tell you if you get it wrong.) The distinction is necessary because filesystems generally support Unicode these days, but on Windows you need to use a separate set of wide-character file I/O functions. (On Linux it all works with "narrow" strings, and the UTF-8 encoding is interpreted by applications.) The character set used for NuFX archive filenames is MOR, matching what GS/OS + HFS supported, and we want to be able to convert back and forth between MOR and a Unicode representation. This change updates the various character types and string names, adds conversion functions, and updates NuLib2 for proper execution on Linux. It does not include the (probably extensive) changes required for Windows UTF-16 support. Instead, the conversion functions are no-ops, which should result in NuLib2 for Windows continuing to behave in the same slightly broken way. This adds "test-names", which exercises Unicode filenames a bit. It will not pass on Win32. Also, tweaked the Linux makefiles to have explicit dependencies, rather than empty space and an expectation that "makedepend" exists. Also, minor source code cleanups. While this probably doesn't affect binary compatibility -- it's mainly a matter of naming and string interpretation -- there's enough going on that it should be considered an API revision, so this updates the version to 3.0.0.
2014-12-24 19:14:32 +00:00
} else {
return kNuSkip;
Distinguish Unicode and Mac OS Roman strings NufxLib has historically made no effort to distinguish between the character set used for filenames on the local disk, and for filenames stored within the archive. Now all Unicode filename strings use the UNICHAR type and have "UNI" in the name, and all Mac OS Roman strings have "MOR" in the name. (The naming convention makes it obvious when you're assigning the wrong thing; on Linux both formats are char*, so the compiler won't tell you if you get it wrong.) The distinction is necessary because filesystems generally support Unicode these days, but on Windows you need to use a separate set of wide-character file I/O functions. (On Linux it all works with "narrow" strings, and the UTF-8 encoding is interpreted by applications.) The character set used for NuFX archive filenames is MOR, matching what GS/OS + HFS supported, and we want to be able to convert back and forth between MOR and a Unicode representation. This change updates the various character types and string names, adds conversion functions, and updates NuLib2 for proper execution on Linux. It does not include the (probably extensive) changes required for Windows UTF-16 support. Instead, the conversion functions are no-ops, which should result in NuLib2 for Windows continuing to behave in the same slightly broken way. This adds "test-names", which exercises Unicode filenames a bit. It will not pass on Win32. Also, tweaked the Linux makefiles to have explicit dependencies, rather than empty space and an expectation that "makedepend" exists. Also, minor source code cleanups. While this probably doesn't affect binary compatibility -- it's mainly a matter of naming and string interpretation -- there's enough going on that it should be considered an API revision, so this updates the version to 3.0.0.
2014-12-24 19:14:32 +00:00
}
2000-05-23 01:55:31 +00:00
}
/*
* Print a three-digit progress percentage; range is 0% to 100%.
*/
void PrintPercentage(uint32_t total, uint32_t progress)
2000-05-23 01:55:31 +00:00
{
uint32_t perc;
if (!total) {
/*printf(" %%");*/
printf(" ");
return;
}
if (total < 21474836) {
perc = (progress * 100 + 50) / total;
if (perc > 100)
perc = 100;
} else {
perc = progress / (total / 100);
if (perc > 100)
perc = 100;
}
printf("%3d%%", perc);
2000-05-23 01:55:31 +00:00
}
/*
* Show our progress, unless we're expanding to a pipe. Invoked as a
* callback by nufxlib.
*/
NuResult ProgressUpdater(NuArchive* pArchive, void* vProgress)
2000-05-23 01:55:31 +00:00
{
const NuProgressData* pProgress = vProgress;
NulibState* pState;
const char* percStr;
const char* actionStr;
char nameBuf[kMaxDisplayLen+1];
Boolean showName, eolConv;
2014-12-22 02:17:23 +00:00
Assert(pArchive != NULL);
(void) NuGetExtraData(pArchive, (void**) &pState);
2014-12-22 02:17:23 +00:00
Assert(pState != NULL);
if (NState_GetSuppressOutput(pState))
return kNuOK;
2014-12-22 02:17:23 +00:00
percStr = NULL;
showName = false;
eolConv = false;
switch (pProgress->operation) {
case kNuOpAdd:
switch (pProgress->state) {
case kNuProgressPreparing:
case kNuProgressOpening:
actionStr = "adding ";
showName = true;
break;
case kNuProgressAnalyzing:
actionStr = "analyzing ";
break;
case kNuProgressCompressing:
actionStr = "compressing";
break;
case kNuProgressStoring:
actionStr = "storing ";
break;
default:
actionStr = "?????? ";
break;
}
break;
case kNuOpExtract:
switch (pProgress->state) {
case kNuProgressPreparing:
case kNuProgressOpening:
actionStr = "extracting";
showName = true;
break;
case kNuProgressExpanding:
actionStr = "expanding ";
break;
case kNuProgressCopying:
actionStr = "extracting";
break;
default:
actionStr = "?????? ";
break;
}
if (pProgress->expand.convertEOL == kNuConvertOn)
eolConv = true;
break;
case kNuOpTest:
switch (pProgress->state) {
case kNuProgressPreparing:
case kNuProgressOpening:
showName = true;
/* no break */
case kNuProgressExpanding:
case kNuProgressCopying:
actionStr = "verifying";
break;
default:
actionStr = "?????? ";
break;
}
break;
default:
Assert(0);
actionStr = "????";
}
switch (pProgress->state) {
case kNuProgressDone:
2014-12-22 02:17:23 +00:00
actionStr = NULL;
percStr = "DONE\n";
break;
case kNuProgressSkipped:
2014-12-22 02:17:23 +00:00
actionStr = NULL;
percStr = "SKIP\n";
break;
2003-02-08 22:30:30 +00:00
case kNuProgressAborted: /* not currently possible in NuLib2 */
2014-12-22 02:17:23 +00:00
actionStr = NULL;
2003-02-08 22:30:30 +00:00
percStr = "CNCL\n";
break;
case kNuProgressFailed:
2014-12-22 02:17:23 +00:00
actionStr = NULL;
percStr = "FAIL\n";
break;
default:
break;
}
if (showName) {
/*
* Use "pathname" (whole thing) rather than "filename" (file part).
* Could also use "origPathname", but I like to show what they're
* getting instead of what they're giving.
*/
Distinguish Unicode and Mac OS Roman strings NufxLib has historically made no effort to distinguish between the character set used for filenames on the local disk, and for filenames stored within the archive. Now all Unicode filename strings use the UNICHAR type and have "UNI" in the name, and all Mac OS Roman strings have "MOR" in the name. (The naming convention makes it obvious when you're assigning the wrong thing; on Linux both formats are char*, so the compiler won't tell you if you get it wrong.) The distinction is necessary because filesystems generally support Unicode these days, but on Windows you need to use a separate set of wide-character file I/O functions. (On Linux it all works with "narrow" strings, and the UTF-8 encoding is interpreted by applications.) The character set used for NuFX archive filenames is MOR, matching what GS/OS + HFS supported, and we want to be able to convert back and forth between MOR and a Unicode representation. This change updates the various character types and string names, adds conversion functions, and updates NuLib2 for proper execution on Linux. It does not include the (probably extensive) changes required for Windows UTF-16 support. Instead, the conversion functions are no-ops, which should result in NuLib2 for Windows continuing to behave in the same slightly broken way. This adds "test-names", which exercises Unicode filenames a bit. It will not pass on Win32. Also, tweaked the Linux makefiles to have explicit dependencies, rather than empty space and an expectation that "makedepend" exists. Also, minor source code cleanups. While this probably doesn't affect binary compatibility -- it's mainly a matter of naming and string interpretation -- there's enough going on that it should be considered an API revision, so this updates the version to 3.0.0.
2014-12-24 19:14:32 +00:00
int len = strlen(pProgress->pathnameUNI);
if (len < sizeof(nameBuf)) {
Distinguish Unicode and Mac OS Roman strings NufxLib has historically made no effort to distinguish between the character set used for filenames on the local disk, and for filenames stored within the archive. Now all Unicode filename strings use the UNICHAR type and have "UNI" in the name, and all Mac OS Roman strings have "MOR" in the name. (The naming convention makes it obvious when you're assigning the wrong thing; on Linux both formats are char*, so the compiler won't tell you if you get it wrong.) The distinction is necessary because filesystems generally support Unicode these days, but on Windows you need to use a separate set of wide-character file I/O functions. (On Linux it all works with "narrow" strings, and the UTF-8 encoding is interpreted by applications.) The character set used for NuFX archive filenames is MOR, matching what GS/OS + HFS supported, and we want to be able to convert back and forth between MOR and a Unicode representation. This change updates the various character types and string names, adds conversion functions, and updates NuLib2 for proper execution on Linux. It does not include the (probably extensive) changes required for Windows UTF-16 support. Instead, the conversion functions are no-ops, which should result in NuLib2 for Windows continuing to behave in the same slightly broken way. This adds "test-names", which exercises Unicode filenames a bit. It will not pass on Win32. Also, tweaked the Linux makefiles to have explicit dependencies, rather than empty space and an expectation that "makedepend" exists. Also, minor source code cleanups. While this probably doesn't affect binary compatibility -- it's mainly a matter of naming and string interpretation -- there's enough going on that it should be considered an API revision, so this updates the version to 3.0.0.
2014-12-24 19:14:32 +00:00
strcpy(nameBuf, pProgress->pathnameUNI);
} else {
nameBuf[0] = nameBuf[1] = '.';
Distinguish Unicode and Mac OS Roman strings NufxLib has historically made no effort to distinguish between the character set used for filenames on the local disk, and for filenames stored within the archive. Now all Unicode filename strings use the UNICHAR type and have "UNI" in the name, and all Mac OS Roman strings have "MOR" in the name. (The naming convention makes it obvious when you're assigning the wrong thing; on Linux both formats are char*, so the compiler won't tell you if you get it wrong.) The distinction is necessary because filesystems generally support Unicode these days, but on Windows you need to use a separate set of wide-character file I/O functions. (On Linux it all works with "narrow" strings, and the UTF-8 encoding is interpreted by applications.) The character set used for NuFX archive filenames is MOR, matching what GS/OS + HFS supported, and we want to be able to convert back and forth between MOR and a Unicode representation. This change updates the various character types and string names, adds conversion functions, and updates NuLib2 for proper execution on Linux. It does not include the (probably extensive) changes required for Windows UTF-16 support. Instead, the conversion functions are no-ops, which should result in NuLib2 for Windows continuing to behave in the same slightly broken way. This adds "test-names", which exercises Unicode filenames a bit. It will not pass on Win32. Also, tweaked the Linux makefiles to have explicit dependencies, rather than empty space and an expectation that "makedepend" exists. Also, minor source code cleanups. While this probably doesn't affect binary compatibility -- it's mainly a matter of naming and string interpretation -- there's enough going on that it should be considered an API revision, so this updates the version to 3.0.0.
2014-12-24 19:14:32 +00:00
strncpy(nameBuf+2,
pProgress->pathnameUNI + len - (sizeof(nameBuf)-3),
sizeof(nameBuf)-3);
nameBuf[sizeof(nameBuf)-1] = '\0';
}
}
2014-12-22 02:17:23 +00:00
if (actionStr == NULL && percStr != NULL) {
printf("\r%s", percStr);
2014-12-22 02:17:23 +00:00
} else if (actionStr != NULL && percStr == NULL) {
if (percStr == NULL) {
putc('\r', stdout);
PrintPercentage(pProgress->uncompressedLength,
pProgress->uncompressedProgress);
if (showName)
printf(" %s%c %s", actionStr, eolConv ? '+' : ' ', nameBuf);
else
printf(" %s%c", actionStr, eolConv ? '+' : ' ');
}
} else {
Assert(0);
printf("????\n");
}
fflush(stdout);
/*printf(" %ld \n", pProgress->uncompressedProgress);*/
/*usleep(250000);*/
return kNuOK;
2000-05-23 01:55:31 +00:00
}
/*
* Decide whether or not to replace an existing file (during extract)
* or record (during add).
*/
static NuResult HandleReplaceExisting(NulibState* pState, NuArchive* pArchive,
const NuErrorStatus* pErrorStatus)
2000-05-23 01:55:31 +00:00
{
NuResult result = kNuOK;
char* renameName;
char reply;
2014-12-22 02:17:23 +00:00
Assert(pState != NULL);
Assert(pErrorStatus != NULL);
Distinguish Unicode and Mac OS Roman strings NufxLib has historically made no effort to distinguish between the character set used for filenames on the local disk, and for filenames stored within the archive. Now all Unicode filename strings use the UNICHAR type and have "UNI" in the name, and all Mac OS Roman strings have "MOR" in the name. (The naming convention makes it obvious when you're assigning the wrong thing; on Linux both formats are char*, so the compiler won't tell you if you get it wrong.) The distinction is necessary because filesystems generally support Unicode these days, but on Windows you need to use a separate set of wide-character file I/O functions. (On Linux it all works with "narrow" strings, and the UTF-8 encoding is interpreted by applications.) The character set used for NuFX archive filenames is MOR, matching what GS/OS + HFS supported, and we want to be able to convert back and forth between MOR and a Unicode representation. This change updates the various character types and string names, adds conversion functions, and updates NuLib2 for proper execution on Linux. It does not include the (probably extensive) changes required for Windows UTF-16 support. Instead, the conversion functions are no-ops, which should result in NuLib2 for Windows continuing to behave in the same slightly broken way. This adds "test-names", which exercises Unicode filenames a bit. It will not pass on Win32. Also, tweaked the Linux makefiles to have explicit dependencies, rather than empty space and an expectation that "makedepend" exists. Also, minor source code cleanups. While this probably doesn't affect binary compatibility -- it's mainly a matter of naming and string interpretation -- there's enough going on that it should be considered an API revision, so this updates the version to 3.0.0.
2014-12-24 19:14:32 +00:00
Assert(pErrorStatus->pathnameUNI != NULL);
Assert(pErrorStatus->canOverwrite);
Assert(pErrorStatus->canSkip);
Assert(pErrorStatus->canAbort);
if (NState_GetInputUnavailable(pState)) {
putc('\n', stdout);
ReportError(pErrorStatus->err, "Giving up");
result = kNuAbort;
goto bail;
}
while (1) {
printf("\n Replace %s? [y]es, [n]o, [A]ll, [N]one",
Distinguish Unicode and Mac OS Roman strings NufxLib has historically made no effort to distinguish between the character set used for filenames on the local disk, and for filenames stored within the archive. Now all Unicode filename strings use the UNICHAR type and have "UNI" in the name, and all Mac OS Roman strings have "MOR" in the name. (The naming convention makes it obvious when you're assigning the wrong thing; on Linux both formats are char*, so the compiler won't tell you if you get it wrong.) The distinction is necessary because filesystems generally support Unicode these days, but on Windows you need to use a separate set of wide-character file I/O functions. (On Linux it all works with "narrow" strings, and the UTF-8 encoding is interpreted by applications.) The character set used for NuFX archive filenames is MOR, matching what GS/OS + HFS supported, and we want to be able to convert back and forth between MOR and a Unicode representation. This change updates the various character types and string names, adds conversion functions, and updates NuLib2 for proper execution on Linux. It does not include the (probably extensive) changes required for Windows UTF-16 support. Instead, the conversion functions are no-ops, which should result in NuLib2 for Windows continuing to behave in the same slightly broken way. This adds "test-names", which exercises Unicode filenames a bit. It will not pass on Win32. Also, tweaked the Linux makefiles to have explicit dependencies, rather than empty space and an expectation that "makedepend" exists. Also, minor source code cleanups. While this probably doesn't affect binary compatibility -- it's mainly a matter of naming and string interpretation -- there's enough going on that it should be considered an API revision, so this updates the version to 3.0.0.
2014-12-24 19:14:32 +00:00
pErrorStatus->pathnameUNI);
if (pErrorStatus->canRename) /* renaming record adds not allowed */
printf(", [r]ename: ");
else
printf(": ");
fflush(stdout);
reply = GetReplyChar('n');
switch (reply) {
case 'y':
result = kNuOverwrite;
goto bail;
case 'n':
result = kNuSkip;
goto bail;
case 'A':
(void) NuSetValue(pArchive, kNuValueHandleExisting,
kNuAlwaysOverwrite);
result = kNuOverwrite;
goto bail;
case 'N':
(void) NuSetValue(pArchive, kNuValueHandleExisting,
kNuNeverOverwrite);
result = kNuSkip;
goto bail;
case 'r':
if (!pErrorStatus->canRename) {
printf("Response not acceptable\n");
break; /* continue in "while" loop */
}
renameName = GetReplyString("New name: ");
2014-12-22 02:17:23 +00:00
if (renameName == NULL)
break; /* continue in "while" loop */
2014-12-22 02:17:23 +00:00
if (pErrorStatus->pRecord == NULL) {
ReportError(kNuErrNone, "Unexpected NULL record");
break; /* continue in "while" loop */
}
NState_SetRenameFromIdx(pState,
pErrorStatus->pRecord->recordIdx);
NState_SetRenameToStr(pState, renameName);
result = kNuRename;
goto bail;
case 'q': /* stealth option to quit */
case 'Q':
result = kNuAbort;
goto bail;
default:
printf("Response not understood -- please use y/n/A/N/r\n");
break; /* continue in "while" loop */
}
}
2000-05-23 01:55:31 +00:00
bail:
return result;
2000-05-23 01:55:31 +00:00
}
/*
* Found a bad CRC... should we press onward?
*
2014-12-22 02:17:23 +00:00
* Note pErrorStatus->pathname may be NULL if the error was found in the
2000-05-23 01:55:31 +00:00
* master header or in the record header.
*/
static NuResult HandleBadCRC(NulibState* pState, NuArchive* pArchive,
const NuErrorStatus* pErrorStatus)
2000-05-23 01:55:31 +00:00
{
NuResult result = kNuOK;
char reply;
2014-12-22 02:17:23 +00:00
Assert(pState != NULL);
Assert(pErrorStatus != NULL);
if (NState_GetInputUnavailable(pState)) {
putc('\n', stderr);
ReportError(pErrorStatus->err, "Giving up");
result = kNuAbort;
goto bail;
}
while (1) {
Distinguish Unicode and Mac OS Roman strings NufxLib has historically made no effort to distinguish between the character set used for filenames on the local disk, and for filenames stored within the archive. Now all Unicode filename strings use the UNICHAR type and have "UNI" in the name, and all Mac OS Roman strings have "MOR" in the name. (The naming convention makes it obvious when you're assigning the wrong thing; on Linux both formats are char*, so the compiler won't tell you if you get it wrong.) The distinction is necessary because filesystems generally support Unicode these days, but on Windows you need to use a separate set of wide-character file I/O functions. (On Linux it all works with "narrow" strings, and the UTF-8 encoding is interpreted by applications.) The character set used for NuFX archive filenames is MOR, matching what GS/OS + HFS supported, and we want to be able to convert back and forth between MOR and a Unicode representation. This change updates the various character types and string names, adds conversion functions, and updates NuLib2 for proper execution on Linux. It does not include the (probably extensive) changes required for Windows UTF-16 support. Instead, the conversion functions are no-ops, which should result in NuLib2 for Windows continuing to behave in the same slightly broken way. This adds "test-names", which exercises Unicode filenames a bit. It will not pass on Win32. Also, tweaked the Linux makefiles to have explicit dependencies, rather than empty space and an expectation that "makedepend" exists. Also, minor source code cleanups. While this probably doesn't affect binary compatibility -- it's mainly a matter of naming and string interpretation -- there's enough going on that it should be considered an API revision, so this updates the version to 3.0.0.
2014-12-24 19:14:32 +00:00
if (pErrorStatus->pathnameUNI != NULL)
fprintf(stderr, "\n Found a bad CRC in %s\n",
Distinguish Unicode and Mac OS Roman strings NufxLib has historically made no effort to distinguish between the character set used for filenames on the local disk, and for filenames stored within the archive. Now all Unicode filename strings use the UNICHAR type and have "UNI" in the name, and all Mac OS Roman strings have "MOR" in the name. (The naming convention makes it obvious when you're assigning the wrong thing; on Linux both formats are char*, so the compiler won't tell you if you get it wrong.) The distinction is necessary because filesystems generally support Unicode these days, but on Windows you need to use a separate set of wide-character file I/O functions. (On Linux it all works with "narrow" strings, and the UTF-8 encoding is interpreted by applications.) The character set used for NuFX archive filenames is MOR, matching what GS/OS + HFS supported, and we want to be able to convert back and forth between MOR and a Unicode representation. This change updates the various character types and string names, adds conversion functions, and updates NuLib2 for proper execution on Linux. It does not include the (probably extensive) changes required for Windows UTF-16 support. Instead, the conversion functions are no-ops, which should result in NuLib2 for Windows continuing to behave in the same slightly broken way. This adds "test-names", which exercises Unicode filenames a bit. It will not pass on Win32. Also, tweaked the Linux makefiles to have explicit dependencies, rather than empty space and an expectation that "makedepend" exists. Also, minor source code cleanups. While this probably doesn't affect binary compatibility -- it's mainly a matter of naming and string interpretation -- there's enough going on that it should be considered an API revision, so this updates the version to 3.0.0.
2014-12-24 19:14:32 +00:00
pErrorStatus->pathnameUNI);
else
fprintf(stderr, "\n Found a bad CRC in the archive\n");
fprintf(stderr,
" Archive may be damaged, continue anyway? [y]es, [n]o: ");
fflush(stderr);
reply = GetReplyChar('n');
switch (reply) {
case 'y':
result = kNuIgnore;
goto bail;
case 'n':
case 'N':
result = kNuAbort;
goto bail;
default:
fprintf(stderr, "Response not understood -- please use y/n\n");
break; /* continue in "while" loop */
}
}
2000-05-23 01:55:31 +00:00
bail:
return result;
2000-05-23 01:55:31 +00:00
}
/*
* Tried to add a nonexistent file; continue?
*
* To make this happen, you need to:
* - nulib2 aer lots-of-files another-file
* - remove another-file while nulib2 is still processing lots-of-files
*
* The trick is to delete a file explicitly mentioned on the command line
* after NuFlush starts to do its thing. Otherwise, we're just using
* the system equivalent of readdir to scan a directory, so deleting a
* file just means it won't get added.
2000-05-23 01:55:31 +00:00
*/
static NuResult HandleAddNotFound(NulibState* pState, NuArchive* pArchive,
const NuErrorStatus* pErrorStatus)
2000-05-23 01:55:31 +00:00
{
NuResult result = kNuOK;
char reply;
2014-12-22 02:17:23 +00:00
Assert(pState != NULL);
Assert(pErrorStatus != NULL);
Distinguish Unicode and Mac OS Roman strings NufxLib has historically made no effort to distinguish between the character set used for filenames on the local disk, and for filenames stored within the archive. Now all Unicode filename strings use the UNICHAR type and have "UNI" in the name, and all Mac OS Roman strings have "MOR" in the name. (The naming convention makes it obvious when you're assigning the wrong thing; on Linux both formats are char*, so the compiler won't tell you if you get it wrong.) The distinction is necessary because filesystems generally support Unicode these days, but on Windows you need to use a separate set of wide-character file I/O functions. (On Linux it all works with "narrow" strings, and the UTF-8 encoding is interpreted by applications.) The character set used for NuFX archive filenames is MOR, matching what GS/OS + HFS supported, and we want to be able to convert back and forth between MOR and a Unicode representation. This change updates the various character types and string names, adds conversion functions, and updates NuLib2 for proper execution on Linux. It does not include the (probably extensive) changes required for Windows UTF-16 support. Instead, the conversion functions are no-ops, which should result in NuLib2 for Windows continuing to behave in the same slightly broken way. This adds "test-names", which exercises Unicode filenames a bit. It will not pass on Win32. Also, tweaked the Linux makefiles to have explicit dependencies, rather than empty space and an expectation that "makedepend" exists. Also, minor source code cleanups. While this probably doesn't affect binary compatibility -- it's mainly a matter of naming and string interpretation -- there's enough going on that it should be considered an API revision, so this updates the version to 3.0.0.
2014-12-24 19:14:32 +00:00
Assert(pErrorStatus->pathnameUNI != NULL);
if (NState_GetInputUnavailable(pState)) {
putc('\n', stdout);
ReportError(pErrorStatus->err, "Giving up");
result = kNuAbort;
goto bail;
}
while (1) {
fprintf(stderr, "\n Couldn't find %s, continue? [y]es, [n]o: ",
Distinguish Unicode and Mac OS Roman strings NufxLib has historically made no effort to distinguish between the character set used for filenames on the local disk, and for filenames stored within the archive. Now all Unicode filename strings use the UNICHAR type and have "UNI" in the name, and all Mac OS Roman strings have "MOR" in the name. (The naming convention makes it obvious when you're assigning the wrong thing; on Linux both formats are char*, so the compiler won't tell you if you get it wrong.) The distinction is necessary because filesystems generally support Unicode these days, but on Windows you need to use a separate set of wide-character file I/O functions. (On Linux it all works with "narrow" strings, and the UTF-8 encoding is interpreted by applications.) The character set used for NuFX archive filenames is MOR, matching what GS/OS + HFS supported, and we want to be able to convert back and forth between MOR and a Unicode representation. This change updates the various character types and string names, adds conversion functions, and updates NuLib2 for proper execution on Linux. It does not include the (probably extensive) changes required for Windows UTF-16 support. Instead, the conversion functions are no-ops, which should result in NuLib2 for Windows continuing to behave in the same slightly broken way. This adds "test-names", which exercises Unicode filenames a bit. It will not pass on Win32. Also, tweaked the Linux makefiles to have explicit dependencies, rather than empty space and an expectation that "makedepend" exists. Also, minor source code cleanups. While this probably doesn't affect binary compatibility -- it's mainly a matter of naming and string interpretation -- there's enough going on that it should be considered an API revision, so this updates the version to 3.0.0.
2014-12-24 19:14:32 +00:00
pErrorStatus->pathnameUNI);
fflush(stderr);
reply = GetReplyChar('n');
switch (reply) {
case 'y':
result = kNuSkip;
goto bail;
case 'n':
case 'N':
result = kNuAbort;
goto bail;
default:
fprintf(stderr, "Response not understood -- please use y/n\n");
break; /* continue in "while" loop */
}
}
2000-05-23 01:55:31 +00:00
bail:
return result;
2000-05-23 01:55:31 +00:00
}
/*
* Something failed, and the user may want to choose how to handle it.
* Invoked as a callback.
*/
NuResult ErrorHandler(NuArchive* pArchive, void* vErrorStatus)
2000-05-23 01:55:31 +00:00
{
const NuErrorStatus* pErrorStatus = vErrorStatus;
NulibState* pState;
NuResult result;
2014-12-22 02:17:23 +00:00
Assert(pArchive != NULL);
(void) NuGetExtraData(pArchive, (void**) &pState);
2014-12-22 02:17:23 +00:00
Assert(pState != NULL);
/* default action is to abort the current operation */
result = kNuAbort;
/*
* When extracting, the error handler callback gets invoked for several
* different problems because we might want to rename the file. Also,
* because extractions are done with "bulk" calls, returning an
* individual error message would be meaningless.
*
* When adding files, the NuAddFile and NuAddRecord calls can return
* immediate, specific results for a single add. The only reasons for
* calling here are to decide if an existing record should be replaced
* or not (without even an option to rename), or to decide what to do
* when the NuFlush call runs into a problem while adding a file.
*/
if (pErrorStatus->operation == kNuOpExtract) {
if (pErrorStatus->err == kNuErrFileExists) {
result = HandleReplaceExisting(pState, pArchive, pErrorStatus);
} else if (pErrorStatus->err == kNuErrNotNewer) {
/* if we were expecting this, it's okay */
if (NState_GetModFreshen(pState) || NState_GetModUpdate(pState)) {
printf("\rSKIP\n");
result = kNuSkip;
} else {
DBUG(("WEIRD one\n"));
}
} else if (pErrorStatus->err == kNuErrDuplicateNotFound) {
/* if we were expecting this, it's okay */
if (NState_GetModFreshen(pState)) {
printf("\rSKIP\n");
result = kNuSkip;
} else {
DBUG(("WEIRD two\n"));
}
}
} else if (pErrorStatus->operation == kNuOpAdd) {
if (pErrorStatus->err == kNuErrRecordExists) {
/* if they want to update or freshen, don't hassle them */
if (NState_GetModFreshen(pState) || NState_GetModUpdate(pState))
result = kNuOverwrite;
else
result = HandleReplaceExisting(pState, pArchive, pErrorStatus);
} else if (pErrorStatus->err == kNuErrFileNotFound) {
/* file was specified with NuAdd but removed during NuFlush */
result = HandleAddNotFound(pState, pArchive, pErrorStatus);
}
} else if (pErrorStatus->operation == kNuOpTest) {
if (pErrorStatus->err == kNuErrBadMHCRC ||
pErrorStatus->err == kNuErrBadRHCRC ||
pErrorStatus->err == kNuErrBadThreadCRC ||
pErrorStatus->err == kNuErrBadDataCRC)
{
result = HandleBadCRC(pState, pArchive, pErrorStatus);
}
}
return result;
2000-05-23 01:55:31 +00:00
}
#if 0
/*
* Display an error message.
*
* (This was just a test to see if it worked... NufxLib's default behavior
* is fine for NuLib2.)
*/
NuResult ErrorMessageHandler(NuArchive* pArchive, void* vErrorMessage)
2000-05-23 01:55:31 +00:00
{
const NuErrorMessage* pErrorMessage = (const NuErrorMessage*) vErrorMessage;
2000-05-23 01:55:31 +00:00
fprintf(stderr, "%s%d %3d %s:%d %s %s\n",
2014-12-22 02:17:23 +00:00
pArchive == NULL ? "(GLOBAL)" : "",
pErrorMessage->isDebug, pErrorMessage->err, pErrorMessage->file,
pErrorMessage->line, pErrorMessage->function, pErrorMessage->message);
return kNuOK;
2000-05-23 01:55:31 +00:00
}
#endif
/*
* ===========================================================================
* Open an archive
2000-05-23 01:55:31 +00:00
* ===========================================================================
*/
/* an archive name of "-" indicates we want to use stdin */
static const char* kStdinArchive = "-";
/*
* Determine whether the access bits on the record make it a read-only
* file or not.
*
* Uses a simplified view of the access flags.
*/
Boolean IsRecordReadOnly(const NuRecord* pRecord)
2000-05-23 01:55:31 +00:00
{
if (pRecord->recAccess == 0x21L || pRecord->recAccess == 0x01L)
return true;
else
return false;
2000-05-23 01:55:31 +00:00
}
/*
* Returns "true" if "archiveName" is the name we use to represent stdin.
*/
Boolean IsFilenameStdin(const char* archiveName)
2000-05-23 01:55:31 +00:00
{
2014-12-22 02:17:23 +00:00
Assert(archiveName != NULL);
return (strcmp(archiveName, kStdinArchive) == 0);
2000-05-23 01:55:31 +00:00
}
#define BailError(err) { if (err != kNuErrNone) goto bail; }
/*
* Open the archive in read-only mode. We use "file mode" for a file, or
* "streaming mode" for stdin.
*/
NuError OpenArchiveReadOnly(NulibState* pState)
2000-05-23 01:55:31 +00:00
{
NuError err;
2014-12-22 02:17:23 +00:00
NuArchive* pArchive = NULL;
2014-12-22 02:17:23 +00:00
Assert(pState != NULL);
if (IsFilenameStdin(NState_GetArchiveFilename(pState))) {
err = NuStreamOpenRO(stdin, &pArchive);
if (err != kNuErrNone) {
ReportError(err, "unable to open stdin archive");
if (err == kNuErrIsBinary2)
err = kNuErrNotNuFX; /* we can't seek back, so forget BNY */
goto bail;
}
/*
* Since the archive is on stdin, we can't ask the user questions.
* On a UNIX system we could open /dev/tty, but that's not portable,
* and I don't think archives on stdin are going to be popular
* enough to make this worth doing.
*/
NState_SetInputUnavailable(pState, true);
} else {
err = NuOpenRO(NState_GetArchiveFilename(pState), &pArchive);
if (err != kNuErrNone) {
if (err != kNuErrIsBinary2) {
ReportError(err, "unable to open '%s'",
NState_GetArchiveFilename(pState));
}
goto bail;
}
}
/* introduce them */
NState_SetNuArchive(pState, pArchive);
err = NuSetExtraData(pArchive, pState);
NuSetSelectionFilter(pArchive, SelectionFilter);
NuSetOutputPathnameFilter(pArchive, OutputPathnameFilter);
NuSetProgressUpdater(pArchive, ProgressUpdater);
NuSetErrorHandler(pArchive, ErrorHandler);
/*NuSetErrorMessageHandler(pArchive, ErrorMessageHandler);*/
/* set the EOL conversion */
if (NState_GetModConvertAll(pState))
err = NuSetValue(pArchive, kNuValueConvertExtractedEOL, kNuConvertOn);
else if (NState_GetModConvertText(pState))
err = NuSetValue(pArchive, kNuValueConvertExtractedEOL, kNuConvertAuto);
else
err = NuSetValue(pArchive, kNuValueConvertExtractedEOL, kNuConvertOff);
BailError(err);
2003-03-10 23:01:44 +00:00
/* if we're converting EOL, we probably ought to do this too */
err = NuSetValue(pArchive, kNuValueStripHighASCII, true);
BailError(err);
/* handle "-s" flag */
if (NState_GetModOverwriteExisting(pState)) {
err = NuSetValue(pArchive, kNuValueHandleExisting, kNuAlwaysOverwrite);
BailError(err);
}
/* handle "-f" and "-u" flags (this overrides "-s" during extraction) */
if (NState_GetModFreshen(pState) || NState_GetModUpdate(pState)) {
err = NuSetValue(pArchive, kNuValueOnlyUpdateOlder, true);
BailError(err);
}
if (NState_GetModFreshen(pState)) {
err = NuSetValue(pArchive, kNuValueHandleExisting, kNuMustOverwrite);
BailError(err);
}
DBUG(("--- enabling ShrinkIt compatibility mode\n"));
err = NuSetValue(pArchive, kNuValueMimicSHK, true);
BailError(err);
/* handy for some malformed archives */
err = NuSetValue(pArchive, kNuValueHandleBadMac, true);
BailError(err);
/*
DBUG(("--- enabling 'mask dataless' mode\n"));
err = NuSetValue(pArchive, kNuValueMaskDataless, true);
BailError(err);
*/
if (strcmp(SYSTEM_DEFAULT_EOL, "\r") == 0)
err = NuSetValue(pArchive, kNuValueEOL, kNuEOLCR);
else if (strcmp(SYSTEM_DEFAULT_EOL, "\n") == 0)
err = NuSetValue(pArchive, kNuValueEOL, kNuEOLLF);
else if (strcmp(SYSTEM_DEFAULT_EOL, "\r\n") == 0)
err = NuSetValue(pArchive, kNuValueEOL, kNuEOLCRLF);
else {
Assert(0);
err = kNuErrInternal;
ReportError(err, "Unknown SYSTEM_DEFAULT_EOL '%s'", SYSTEM_DEFAULT_EOL);
goto bail;
}
BailError(err);
2000-05-23 01:55:31 +00:00
bail:
2014-12-22 02:17:23 +00:00
if (err != kNuErrNone && pArchive != NULL) {
/* clean up */
(void) NuClose(pArchive);
2014-12-22 02:17:23 +00:00
NState_SetNuArchive(pState, NULL);
}
return err;
2000-05-23 01:55:31 +00:00
}
/*
* Open the archive in read-write mode, for purposes of adding, deleting,
* or updating files. We don't plan on extracting anything with this.
*
* "Streaming mode" isn't allowed.
*/
NuError OpenArchiveReadWrite(NulibState* pState)
2000-05-23 01:55:31 +00:00
{
NuError err = kNuErrNone;
2014-12-22 02:17:23 +00:00
NuArchive* pArchive = NULL;
char* tempName = NULL;
2014-12-22 02:17:23 +00:00
Assert(pState != NULL);
Assert(IsFilenameStdin(NState_GetArchiveFilename(pState)) == false);
tempName = MakeTempArchiveName(pState);
2014-12-22 02:17:23 +00:00
if (tempName == NULL)
goto bail;
DBUG(("TEMP NAME = '%s'\n", tempName));
err = NuOpenRW(NState_GetArchiveFilename(pState), tempName,
kNuOpenCreat, &pArchive);
if (err != kNuErrNone) {
ReportError(err, "unable to open '%s'",
NState_GetArchiveFilename(pState));
goto bail;
}
/* introduce them */
NState_SetNuArchive(pState, pArchive);
err = NuSetExtraData(pArchive, pState);
BailError(err);
NuSetSelectionFilter(pArchive, SelectionFilter);
NuSetProgressUpdater(pArchive, ProgressUpdater);
NuSetErrorHandler(pArchive, ErrorHandler);
/*NuSetErrorMessageHandler(pArchive, ErrorMessageHandler);*/
/* handle "-0" flag */
if (NState_GetModNoCompression(pState)) {
err = NuSetValue(pArchive, kNuValueDataCompression, kNuCompressNone);
BailError(err);
}
/* handle "-z" flag */
if (NState_GetModCompressDeflate(pState)) {
err = NuSetValue(pArchive, kNuValueDataCompression, kNuCompressDeflate);
BailError(err);
}
/* handle "-zz" flag */
if (NState_GetModCompressBzip2(pState)) {
err = NuSetValue(pArchive, kNuValueDataCompression, kNuCompressBzip2);
BailError(err);
}
/* handle "-f" and "-u" flags */
/* (BUG: if "-f" is set, creating a new archive is impossible) */
if (NState_GetModFreshen(pState) || NState_GetModUpdate(pState)) {
err = NuSetValue(pArchive, kNuValueOnlyUpdateOlder, true);
BailError(err);
}
if (NState_GetModFreshen(pState)) {
err = NuSetValue(pArchive, kNuValueHandleExisting, kNuMustOverwrite);
BailError(err);
}
DBUG(("--- enabling ShrinkIt compatibility mode\n"));
err = NuSetValue(pArchive, kNuValueMimicSHK, true);
BailError(err);
/* this probably isn't needed here, but set it anyway */
if (strcmp(SYSTEM_DEFAULT_EOL, "\r") == 0)
err = NuSetValue(pArchive, kNuValueEOL, kNuEOLCR);
else if (strcmp(SYSTEM_DEFAULT_EOL, "\n") == 0)
err = NuSetValue(pArchive, kNuValueEOL, kNuEOLLF);
else if (strcmp(SYSTEM_DEFAULT_EOL, "\r\n") == 0)
err = NuSetValue(pArchive, kNuValueEOL, kNuEOLCRLF);
else {
Assert(0);
err = kNuErrInternal;
ReportError(err, "Unknown SYSTEM_DEFAULT_EOL '%s'", SYSTEM_DEFAULT_EOL);
goto bail;
}
BailError(err);
/*(void) NuSetValue(pArchive, kNuValueAllowDuplicates, true);*/
2000-05-23 01:55:31 +00:00
bail:
Free(tempName);
2014-12-22 02:17:23 +00:00
if (err != kNuErrNone && pArchive != NULL) {
/* clean up */
NuAbort(pArchive);
(void) NuClose(pArchive);
2014-12-22 02:17:23 +00:00
NState_SetNuArchive(pState, NULL);
}
return err;
2000-05-23 01:55:31 +00:00
}