nulib2/nulib2/Extract.c

181 lines
4.6 KiB
C
Raw Permalink 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
*
* Extract files and test archives.
*/
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
/*
* Extract all of the records from the archive, pulling out and displaying
* comment threads.
*
* The "bulk extract" call doesn't deal with comments. Since we want to
* show them while we're extracting the files, we have to manually find
* and extract them.
*/
static NuError ExtractAllRecords(NulibState* pState, NuArchive* pArchive)
2000-05-23 01:55:31 +00:00
{
NuError err;
const NuRecord* pRecord;
const NuThread* pThread;
NuRecordIdx recordIdx;
NuAttr numRecords;
int idx, threadIdx;
DBUG(("--- doing manual extract\n"));
Assert(NState_GetCommand(pState) == kCommandExtract); /* no "-p" here */
err = NuGetAttr(pArchive, kNuAttrNumRecords, &numRecords);
for (idx = 0; idx < (int) numRecords; idx++) {
err = NuGetRecordIdxByPosition(pArchive, idx, &recordIdx);
if (err != kNuErrNone) {
fprintf(stderr, "ERROR: couldn't get record #%d (err=%d)\n",
idx, err);
goto bail;
}
err = NuGetRecord(pArchive, recordIdx, &pRecord);
if (err != kNuErrNone) {
fprintf(stderr, "ERROR: unable to get recordIdx %u\n", recordIdx);
goto bail;
}
/* do we want to extract this record? */
if (!IsSpecified(pState, pRecord))
continue;
NState_IncMatchCount(pState);
/*
* Look for a comment thread.
*/
for (threadIdx = 0; (uint32_t)threadIdx < pRecord->recTotalThreads;
threadIdx++)
{
pThread = NuGetThread(pRecord, threadIdx);
2014-12-22 02:17:23 +00:00
Assert(pThread != NULL);
if (NuGetThreadID(pThread) == kNuThreadIDComment &&
pThread->actualThreadEOF > 0)
{
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* filenameUNI = CopyMORToUNI(pRecord->filenameMOR);
printf("----- '%s':\n", filenameUNI);
free(filenameUNI);
err = NuExtractThread(pArchive, pThread->threadIdx,
NState_GetCommentSink(pState));
if (err != kNuErrNone) {
printf("[comment extraction failed, continuing\n");
} else {
printf("\n-----\n");
}
}
}
/* extract the record, using the usual mechanisms */
err = NuExtractRecord(pArchive, recordIdx);
if (err != kNuErrNone)
goto bail;
}
2000-05-23 01:55:31 +00:00
bail:
return err;
2000-05-23 01:55:31 +00:00
}
/*
* Extract the specified files.
*/
NuError DoExtract(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 (NState_GetModBinaryII(pState))
return BNYDoExtract(pState);
err = OpenArchiveReadOnly(pState);
if (err == kNuErrIsBinary2)
return BNYDoExtract(pState);
if (err != kNuErrNone)
goto bail;
pArchive = NState_GetNuArchive(pState);
2014-12-22 02:17:23 +00:00
Assert(pArchive != NULL);
NState_SetMatchCount(pState, 0);
/*
* If we're not interested in comments, just use the "bulk" extract
* call. If we want comments, we need to do this one at a time.
*/
if (!NState_GetModComments(pState)) {
err = NuExtract(pArchive);
if (err != kNuErrNone)
goto bail;
} else {
err = ExtractAllRecords(pState, pArchive);
if (err != kNuErrNone)
goto bail;
}
if (!NState_GetMatchCount(pState))
printf("%s: no records match\n", gProgName);
2000-05-23 01:55:31 +00:00
bail:
2014-12-22 02:17:23 +00:00
if (pArchive != NULL)
(void) NuClose(pArchive);
return err;
2000-05-23 01:55:31 +00:00
}
/*
* Extract the specified files to stdout.
*/
NuError DoExtractToPipe(NulibState* pState)
2000-05-23 01:55:31 +00:00
{
/* we handle the "to pipe" part farther down */
return DoExtract(pState);
2000-05-23 01:55:31 +00:00
}
/*
* Do an integrity check on one or more records in the archive.
*/
NuError DoTest(NulibState* pState)
2000-05-23 01:55:31 +00:00
{
NuError err;
2014-12-22 02:17:23 +00:00
NuArchive* pArchive = NULL;
2000-05-23 01:55:31 +00:00
2014-12-22 02:17:23 +00:00
Assert(pState != NULL);
if (NState_GetModBinaryII(pState))
return BNYDoTest(pState);
2000-05-23 01:55:31 +00:00
err = OpenArchiveReadOnly(pState);
if (err == kNuErrIsBinary2)
return BNYDoTest(pState);
if (err != kNuErrNone)
goto bail;
pArchive = NState_GetNuArchive(pState);
2014-12-22 02:17:23 +00:00
Assert(pArchive != NULL);
2000-05-23 01:55:31 +00:00
NState_SetMatchCount(pState, 0);
2000-05-23 01:55:31 +00:00
err = NuTest(pArchive);
if (err != kNuErrNone)
goto bail;
2000-05-23 01:55:31 +00:00
if (!NState_GetMatchCount(pState))
printf("%s: no records match\n", gProgName);
2000-05-23 01:55:31 +00:00
bail:
2014-12-22 02:17:23 +00:00
if (pArchive != NULL)
(void) NuClose(pArchive);
return err;
2000-05-23 01:55:31 +00:00
}