nulib2/nulib2/State.c

492 lines
11 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
*
* Global-ish state object.
*/
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
2017-09-21 18:52:37 +00:00
static const char* gProgramVersion = "3.1.0";
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
* Allocate and initialize the semi-global NuLib2 state object.
2000-05-23 01:55:31 +00:00
*/
NuError NState_Init(NulibState** ppState)
2000-05-23 01:55:31 +00:00
{
2014-12-22 02:17:23 +00:00
Assert(ppState != NULL);
2000-05-23 01:55:31 +00:00
*ppState = Calloc(sizeof(**ppState));
2014-12-22 02:17:23 +00:00
if (*ppState == NULL)
return kNuErrMalloc;
2000-05-23 01:55:31 +00:00
/*
* Initialize the contents to default values.
*/
(*ppState)->systemPathSeparator = PATH_SEP;
#ifdef PATH_SEP2
(*ppState)->altSystemPathSeparator = PATH_SEP2;
#else
(*ppState)->altSystemPathSeparator = '\0';
#endif
(*ppState)->programVersion = gProgramVersion;
2000-05-23 01:55:31 +00:00
return kNuErrNone;
2000-05-23 01:55:31 +00:00
}
/*
* A little extra initialization, performed after arguments are parsed.
*/
NuError NState_ExtraInit(NulibState* pState)
2000-05-23 01:55:31 +00:00
{
NuError err;
NuValue convertEOL;
2000-05-23 01:55:31 +00:00
/*
* Create a data sink for "stdout", in case we use the "-p" command.
* Set the EOL conversion according to the "-l" modifier.
*/
convertEOL = kNuConvertOff;
if (pState->modConvertText)
convertEOL = kNuConvertAuto;
if (pState->modConvertAll)
convertEOL = kNuConvertOn;
2000-05-23 01:55:31 +00:00
err = NuCreateDataSinkForFP(true, convertEOL, stdout, &pState->pPipeSink);
if (err != kNuErrNone)
return err;
2000-05-23 01:55:31 +00:00
/*
* Create a data sink for "stdout", in case we use the "-c" modifier.
* The EOL conversion is always on.
*/
err = NuCreateDataSinkForFP(true, kNuConvertOn, stdout,
&pState->pCommentSink);
return err;
2000-05-23 01:55:31 +00:00
}
/*
* Free up the state structure and its contents.
*/
void NState_Free(NulibState* pState)
2000-05-23 01:55:31 +00:00
{
2014-12-22 02:17:23 +00:00
if (pState == NULL)
return;
2000-05-23 01:55:31 +00:00
Free(pState->renameToStr); /* ?? */
Free(pState->tempPathnameBuf);
2014-12-22 02:17:23 +00:00
if (pState->pPipeSink != NULL)
NuFreeDataSink(pState->pPipeSink);
2014-12-22 02:17:23 +00:00
if (pState->pCommentSink != NULL)
NuFreeDataSink(pState->pCommentSink);
Free(pState);
2000-05-23 01:55:31 +00:00
}
#ifdef DEBUG_MSGS
void NState_DebugDump(const NulibState* pState)
2000-05-23 01:55:31 +00:00
{
/* this table will break if the code changes, but it's just for debugging */
static const char* kCommandNames[] = {
"<unknown>",
"add",
"delete",
"extract",
"extractToPipe",
"listShort",
"listVerbose",
"listDebug",
"test",
"help",
};
2014-12-22 02:17:23 +00:00
Assert(pState != NULL);
printf("NState:\n");
printf(" programVersion: '%s'\n", pState->programVersion);
printf(" systemPathSeparator: '%c'\n", pState->systemPathSeparator);
if (pState->altSystemPathSeparator != '\0')
printf(" altSystemPathSeparator: '%c'\n",
pState->altSystemPathSeparator);
printf(" archiveFilename: '%s'\n", pState->archiveFilename);
printf(" filespec: %ld (%s ...)\n", pState->filespecCount,
!pState->filespecCount ? "<none>" : *pState->filespecPointer);
printf(" command: %d (%s); modifiers:\n", pState->command,
kCommandNames[pState->command]);
if (pState->modUpdate)
printf(" update\n");
if (pState->modFreshen)
printf(" freshen\n");
if (pState->modRecurse)
printf(" recurse\n");
if (pState->modJunkPaths)
printf(" junkPaths\n");
if (pState->modNoCompression)
printf(" noCompression\n");
if (pState->modCompressDeflate)
printf(" compressDeflate\n");
if (pState->modCompressBzip2)
printf(" compressBzip2\n");
if (pState->modComments)
printf(" comments\n");
if (pState->modBinaryII)
printf(" binaryII\n");
if (pState->modConvertText)
printf(" convertText\n");
if (pState->modConvertAll)
printf(" convertAll\n");
if (pState->modOverwriteExisting)
printf(" overwriteExisting\n");
if (pState->modPreserveType)
printf(" preserveType\n");
if (pState->modPreserveTypeExtended)
printf(" preserveTypeExtended\n");
printf("\n");
2000-05-23 01:55:31 +00:00
}
#endif
/*
* ===========================================================================
* Simple set/get functions
2000-05-23 01:55:31 +00:00
* ===========================================================================
*/
char NState_GetSystemPathSeparator(const NulibState* pState)
2000-05-23 01:55:31 +00:00
{
return pState->systemPathSeparator;
2000-05-23 01:55:31 +00:00
}
char NState_GetAltSystemPathSeparator(const NulibState* pState)
{
return pState->altSystemPathSeparator;
}
const char* NState_GetProgramVersion(const NulibState* pState)
2000-05-23 01:55:31 +00:00
{
return pState->programVersion;
2000-05-23 01:55:31 +00:00
}
NuArchive* NState_GetNuArchive(const NulibState* pState)
2000-05-23 01:55:31 +00:00
{
return pState->pArchive;
2000-05-23 01:55:31 +00:00
}
void NState_SetNuArchive(NulibState* pState, NuArchive* pArchive)
2000-05-23 01:55:31 +00:00
{
pState->pArchive = pArchive;
2000-05-23 01:55:31 +00:00
}
Boolean NState_GetSuppressOutput(const NulibState* pState)
2000-05-23 01:55:31 +00:00
{
return pState->suppressOutput;
2000-05-23 01:55:31 +00:00
}
void NState_SetSuppressOutput(NulibState* pState, Boolean doSuppress)
2000-05-23 01:55:31 +00:00
{
pState->suppressOutput = doSuppress;
2000-05-23 01:55:31 +00:00
}
Boolean NState_GetInputUnavailable(const NulibState* pState)
2000-05-23 01:55:31 +00:00
{
return pState->inputUnavailable;
2000-05-23 01:55:31 +00:00
}
void NState_SetInputUnavailable(NulibState* pState, Boolean isUnavailable)
2000-05-23 01:55:31 +00:00
{
pState->inputUnavailable = isUnavailable;
2000-05-23 01:55:31 +00:00
}
NuRecordIdx NState_GetRenameFromIdx(const NulibState* pState)
2000-05-23 01:55:31 +00:00
{
return pState->renameFromIdx;
2000-05-23 01:55:31 +00:00
}
void NState_SetRenameFromIdx(NulibState* pState, NuRecordIdx recordIdx)
2000-05-23 01:55:31 +00:00
{
pState->renameFromIdx = recordIdx;
2000-05-23 01:55:31 +00:00
}
char* NState_GetRenameToStr(const NulibState* pState)
2000-05-23 01:55:31 +00:00
{
return pState->renameToStr;
2000-05-23 01:55:31 +00:00
}
void NState_SetRenameToStr(NulibState* pState, char* str)
2000-05-23 01:55:31 +00:00
{
Free(pState->renameToStr);
pState->renameToStr = str;
2000-05-23 01:55:31 +00:00
}
NuDataSink* NState_GetPipeSink(const NulibState* pState)
2000-05-23 01:55:31 +00:00
{
return pState->pPipeSink;
2000-05-23 01:55:31 +00:00
}
NuDataSink* NState_GetCommentSink(const NulibState* pState)
2000-05-23 01:55:31 +00:00
{
return pState->pCommentSink;
2000-05-23 01:55:31 +00:00
}
long NState_GetMatchCount(const NulibState* pState)
2000-05-23 01:55:31 +00:00
{
return pState->matchCount;
2000-05-23 01:55:31 +00:00
}
void NState_SetMatchCount(NulibState* pState, long count)
2000-05-23 01:55:31 +00:00
{
pState->matchCount = count;
2000-05-23 01:55:31 +00:00
}
void NState_IncMatchCount(NulibState* pState)
2000-05-23 01:55:31 +00:00
{
pState->matchCount++;
2000-05-23 01:55:31 +00:00
}
void NState_AddToTotals(NulibState* pState, long len, long compLen)
2000-05-23 01:55:31 +00:00
{
pState->totalLen += len;
pState->totalCompLen += compLen;
2000-05-23 01:55:31 +00:00
}
void NState_GetTotals(NulibState* pState, long* pTotalLen, long* pTotalCompLen)
2000-05-23 01:55:31 +00:00
{
*pTotalLen = pState->totalLen;
*pTotalCompLen = pState->totalCompLen;
2000-05-23 01:55:31 +00:00
}
long NState_GetTempPathnameLen(NulibState* pState)
2000-05-23 01:55:31 +00:00
{
return pState->tempPathnameAlloc;
2000-05-23 01:55:31 +00:00
}
void NState_SetTempPathnameLen(NulibState* pState, long len)
2000-05-23 01:55:31 +00:00
{
char* newBuf;
2000-05-23 01:55:31 +00:00
len++; /* add one for the '\0' */
2000-05-23 01:55:31 +00:00
if (pState->tempPathnameAlloc < len) {
2014-12-22 02:17:23 +00:00
if (pState->tempPathnameBuf == NULL)
newBuf = Malloc(len);
else
newBuf = Realloc(pState->tempPathnameBuf, len);
2014-12-22 02:17:23 +00:00
Assert(newBuf != NULL);
if (newBuf == NULL) {
Free(pState->tempPathnameBuf);
2014-12-22 02:17:23 +00:00
pState->tempPathnameBuf = NULL;
pState->tempPathnameAlloc = 0;
ReportError(kNuErrMalloc, "buf realloc failed (%ld)", len);
return;
}
2000-05-23 01:55:31 +00:00
pState->tempPathnameBuf = newBuf;
pState->tempPathnameAlloc = len;
}
2000-05-23 01:55:31 +00:00
}
char* NState_GetTempPathnameBuf(NulibState* pState)
2000-05-23 01:55:31 +00:00
{
return pState->tempPathnameBuf;
2000-05-23 01:55:31 +00:00
}
Command NState_GetCommand(const NulibState* pState)
2000-05-23 01:55:31 +00:00
{
return pState->command;
2000-05-23 01:55:31 +00:00
}
void NState_SetCommand(NulibState* pState, Command cmd)
2000-05-23 01:55:31 +00:00
{
pState->command = cmd;
2000-05-23 01:55:31 +00:00
}
const char* NState_GetArchiveFilename(const NulibState* pState)
2000-05-23 01:55:31 +00:00
{
return pState->archiveFilename;
2000-05-23 01:55:31 +00:00
}
void NState_SetArchiveFilename(NulibState* pState, const char* archiveFilename)
2000-05-23 01:55:31 +00:00
{
pState->archiveFilename = archiveFilename;
2000-05-23 01:55:31 +00:00
}
char* const* NState_GetFilespecPointer(const NulibState* pState)
2000-05-23 01:55:31 +00:00
{
return pState->filespecPointer;
2000-05-23 01:55:31 +00:00
}
void NState_SetFilespecPointer(NulibState* pState, char* const* filespecPointer)
2000-05-23 01:55:31 +00:00
{
pState->filespecPointer = filespecPointer;
2000-05-23 01:55:31 +00:00
}
long NState_GetFilespecCount(const NulibState* pState)
2000-05-23 01:55:31 +00:00
{
return pState->filespecCount;
2000-05-23 01:55:31 +00:00
}
void NState_SetFilespecCount(NulibState* pState, long filespecCount)
2000-05-23 01:55:31 +00:00
{
pState->filespecCount = filespecCount;
2000-05-23 01:55:31 +00:00
}
Boolean NState_GetModUpdate(const NulibState* pState)
2000-05-23 01:55:31 +00:00
{
return pState->modUpdate;
2000-05-23 01:55:31 +00:00
}
void NState_SetModUpdate(NulibState* pState, Boolean val)
2000-05-23 01:55:31 +00:00
{
pState->modUpdate = val;
2000-05-23 01:55:31 +00:00
}
Boolean NState_GetModFreshen(const NulibState* pState)
2000-05-23 01:55:31 +00:00
{
return pState->modFreshen;
2000-05-23 01:55:31 +00:00
}
void NState_SetModFreshen(NulibState* pState, Boolean val)
2000-05-23 01:55:31 +00:00
{
pState->modFreshen = val;
2000-05-23 01:55:31 +00:00
}
Boolean NState_GetModRecurse(const NulibState* pState)
2000-05-23 01:55:31 +00:00
{
return pState->modRecurse;
2000-05-23 01:55:31 +00:00
}
void NState_SetModRecurse(NulibState* pState, Boolean val)
2000-05-23 01:55:31 +00:00
{
pState->modRecurse = val;
2000-05-23 01:55:31 +00:00
}
Boolean NState_GetModJunkPaths(const NulibState* pState)
2000-05-23 01:55:31 +00:00
{
return pState->modJunkPaths;
2000-05-23 01:55:31 +00:00
}
void NState_SetModJunkPaths(NulibState* pState, Boolean val)
2000-05-23 01:55:31 +00:00
{
pState->modJunkPaths = val;
2000-05-23 01:55:31 +00:00
}
Boolean NState_GetModNoCompression(const NulibState* pState)
2000-05-23 01:55:31 +00:00
{
return pState->modNoCompression;
2000-05-23 01:55:31 +00:00
}
void NState_SetModNoCompression(NulibState* pState, Boolean val)
2000-05-23 01:55:31 +00:00
{
pState->modNoCompression = val;
2000-05-23 01:55:31 +00:00
}
Boolean NState_GetModCompressDeflate(const NulibState* pState)
{
return pState->modCompressDeflate;
}
void NState_SetModCompressDeflate(NulibState* pState, Boolean val)
{
pState->modCompressDeflate = val;
}
Boolean NState_GetModCompressBzip2(const NulibState* pState)
{
return pState->modCompressBzip2;
}
void NState_SetModCompressBzip2(NulibState* pState, Boolean val)
{
pState->modCompressBzip2 = val;
}
Boolean NState_GetModComments(const NulibState* pState)
2000-05-23 01:55:31 +00:00
{
return pState->modComments;
2000-05-23 01:55:31 +00:00
}
void NState_SetModComments(NulibState* pState, Boolean val)
2000-05-23 01:55:31 +00:00
{
pState->modComments = val;
2000-05-23 01:55:31 +00:00
}
Boolean NState_GetModBinaryII(const NulibState* pState)
{
return pState->modBinaryII;
}
void NState_SetModBinaryII(NulibState* pState, Boolean val)
{
pState->modBinaryII = val;
}
Boolean NState_GetModConvertText(const NulibState* pState)
2000-05-23 01:55:31 +00:00
{
return pState->modConvertText;
2000-05-23 01:55:31 +00:00
}
void NState_SetModConvertText(NulibState* pState, Boolean val)
2000-05-23 01:55:31 +00:00
{
pState->modConvertText = val;
2000-05-23 01:55:31 +00:00
}
Boolean NState_GetModConvertAll(const NulibState* pState)
2000-05-23 01:55:31 +00:00
{
return pState->modConvertAll;
2000-05-23 01:55:31 +00:00
}
void NState_SetModConvertAll(NulibState* pState, Boolean val)
2000-05-23 01:55:31 +00:00
{
pState->modConvertAll = val;
2000-05-23 01:55:31 +00:00
}
Boolean NState_GetModOverwriteExisting(const NulibState* pState)
2000-05-23 01:55:31 +00:00
{
return pState->modOverwriteExisting;
2000-05-23 01:55:31 +00:00
}
void NState_SetModOverwriteExisting(NulibState* pState, Boolean val)
2000-05-23 01:55:31 +00:00
{
pState->modOverwriteExisting = val;
2000-05-23 01:55:31 +00:00
}
Boolean NState_GetModAddAsDisk(const NulibState* pState)
2000-05-23 01:55:31 +00:00
{
return pState->modAddAsDisk;
2000-05-23 01:55:31 +00:00
}
void NState_SetModAddAsDisk(NulibState* pState, Boolean val)
2000-05-23 01:55:31 +00:00
{
pState->modAddAsDisk = val;
2000-05-23 01:55:31 +00:00
}
Boolean NState_GetModPreserveType(const NulibState* pState)
2000-05-23 01:55:31 +00:00
{
return pState->modPreserveType;
2000-05-23 01:55:31 +00:00
}
void NState_SetModPreserveType(NulibState* pState, Boolean val)
2000-05-23 01:55:31 +00:00
{
pState->modPreserveType = val;
2000-05-23 01:55:31 +00:00
}
Boolean NState_GetModPreserveTypeExtended(const NulibState* pState)
2000-05-23 01:55:31 +00:00
{
return pState->modPreserveTypeExtended;
2000-05-23 01:55:31 +00:00
}
void NState_SetModPreserveTypeExtended(NulibState* pState, Boolean val)
2000-05-23 01:55:31 +00:00
{
pState->modPreserveTypeExtended = val;
2000-05-23 01:55:31 +00:00
}