mirror of
https://github.com/fadden/nulib2.git
synced 2024-12-27 17:29:57 +00:00
Upped version number to v2.0.0.
Fixed filename conversion issues. Specifically: - Correctly handle '%' when preservation is OFF. - Accept 4-character extensions in '-ee' without risk of buffer overflow. - Fixed broken assert when converting long %xx names. - Store "AUX" as "%00AUX" when preserving names under Win32 (vs. "_AUX"). - Always store files with ':' as path separator. - Recognize that some Win32 variants (Win2K and later at the least) will accept both '/' and '\' as pathname separators. - Correctly convert ".//foo" to "foo" instead of "/foo". Corrected definition of F_OK under Win32.
This commit is contained in:
parent
861eb84b4d
commit
0d053dca09
@ -20,7 +20,7 @@
|
||||
#define kFilenameExtDelim '.' /* separates extension from filename */
|
||||
#define kResourceFlag 'r'
|
||||
#define kDiskImageFlag 'i'
|
||||
#define kMaxExtLen 4 /* ".123" */
|
||||
#define kMaxExtLen 5 /* ".1234" */
|
||||
#define kResourceStr "_rsrc_"
|
||||
|
||||
/* must be longer then strlen(kResourceStr)... no problem there */
|
||||
@ -182,7 +182,7 @@ AddPreservationString(NulibState* pState,
|
||||
pExt = nil;
|
||||
else
|
||||
pExt = FindExtension(pState, pathBuf);
|
||||
if (pExt != nil && strlen(pExt+1) <= kMaxExtLen) {
|
||||
if (pExt != nil && strlen(pExt+1) < kMaxExtLen) {
|
||||
pExt++; /* skip past the '.' */
|
||||
|
||||
/* if it's strictly decimal-numeric, don't use it (.1, .2, etc) */
|
||||
@ -250,6 +250,7 @@ NormalizePath(NulibState* pState, NuPathnameProposal* pPathProposal)
|
||||
const char* endp;
|
||||
char* dstp;
|
||||
char localFssep;
|
||||
int newBufLen;
|
||||
|
||||
Assert(pState != nil);
|
||||
Assert(pPathProposal != nil);
|
||||
@ -262,8 +263,8 @@ NormalizePath(NulibState* pState, NuPathnameProposal* pPathProposal)
|
||||
* requires converting all chars to '%' codes and adding the longest
|
||||
* possible preservation string.
|
||||
*/
|
||||
NState_SetTempPathnameLen(pState,
|
||||
strlen(pPathProposal->pathname)*3 + kMaxPathGrowth +1);
|
||||
newBufLen = strlen(pPathProposal->pathname)*3 + kMaxPathGrowth +1;
|
||||
NState_SetTempPathnameLen(pState, newBufLen);
|
||||
pathBuf = NState_GetTempPathnameBuf(pState);
|
||||
Assert(pathBuf != nil);
|
||||
if (pathBuf == nil)
|
||||
@ -316,8 +317,7 @@ NormalizePath(NulibState* pState, NuPathnameProposal* pPathProposal)
|
||||
pPathProposal->newFilenameSeparator = localFssep;
|
||||
|
||||
/* check for overflow */
|
||||
Assert(dstp - pathBuf <=
|
||||
(int)(strlen(pPathProposal->pathname) + kMaxPathGrowth));
|
||||
Assert(dstp - pathBuf <= newBufLen);
|
||||
|
||||
/*
|
||||
* If "junk paths" is set, drop everything but the last component.
|
||||
@ -543,7 +543,8 @@ DenormalizePath(NulibState* pState, char* pathBuf)
|
||||
if (isxdigit((int)*srcp)) {
|
||||
/* valid, output char */
|
||||
ch += HexDigit(*srcp);
|
||||
*dstp++ = ch;
|
||||
if (ch != '\0') /* used by Win32 converter */
|
||||
*dstp++ = ch;
|
||||
srcp++;
|
||||
} else {
|
||||
/* bogus '%' with trailing hex digit found! */
|
||||
|
@ -20,6 +20,9 @@
|
||||
/* replace unsupported chars with '%xx' */
|
||||
#define kForeignIndic '%'
|
||||
|
||||
/* use this to separate path components in stored filenames */
|
||||
#define kStorageFssep ':'
|
||||
|
||||
/* make our one-line comments this big */
|
||||
#define kDefaultCommentLen 200
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include "Nulib2.h"
|
||||
|
||||
|
||||
static const char* gProgramVersion = "1.1.0";
|
||||
static const char* gProgramVersion = "2.0.0";
|
||||
|
||||
|
||||
/*
|
||||
@ -28,6 +28,11 @@ NState_Init(NulibState** ppState)
|
||||
* 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;
|
||||
|
||||
return kNuErrNone;
|
||||
@ -108,6 +113,9 @@ NState_DebugDump(const NulibState* pState)
|
||||
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);
|
||||
@ -160,6 +168,12 @@ NState_GetSystemPathSeparator(const NulibState* pState)
|
||||
return pState->systemPathSeparator;
|
||||
}
|
||||
|
||||
char
|
||||
NState_GetAltSystemPathSeparator(const NulibState* pState)
|
||||
{
|
||||
return pState->altSystemPathSeparator;
|
||||
}
|
||||
|
||||
const char*
|
||||
NState_GetProgramVersion(const NulibState* pState)
|
||||
{
|
||||
|
@ -38,6 +38,7 @@ typedef struct NulibState {
|
||||
|
||||
/* system-specific values */
|
||||
char systemPathSeparator;
|
||||
char altSystemPathSeparator;
|
||||
|
||||
/* pointer to archive we're working with */
|
||||
NuArchive* pArchive;
|
||||
@ -88,6 +89,7 @@ void NState_DebugDump(const NulibState* pState);
|
||||
#endif
|
||||
|
||||
char NState_GetSystemPathSeparator(const NulibState* pState);
|
||||
char NState_GetAltSystemPathSeparator(const NulibState* pState);
|
||||
const char* NState_GetProgramVersion(const NulibState* pState);
|
||||
NuArchive* NState_GetNuArchive(const NulibState* pState);
|
||||
void NState_SetNuArchive(NulibState* pState, NuArchive* pArchive);
|
||||
|
@ -94,7 +94,7 @@
|
||||
|
||||
#if defined(WINDOWS_LIKE)
|
||||
# ifndef F_OK
|
||||
# define F_OK 02
|
||||
# define F_OK 00
|
||||
# endif
|
||||
# ifndef R_OK
|
||||
# define R_OK 04
|
||||
|
@ -80,9 +80,10 @@ UNIXNormalizeFileName(NulibState* pState, const char* srcp, long srcLen,
|
||||
while (srcLen--) { /* don't go until null found! */
|
||||
Assert(*srcp != '\0');
|
||||
|
||||
if (*srcp == '%') {
|
||||
if (*srcp == kForeignIndic) {
|
||||
/* change '%' to "%%" */
|
||||
*dstp++ = *srcp;
|
||||
if (NState_GetModPreserveType(pState))
|
||||
*dstp++ = *srcp;
|
||||
*dstp++ = *srcp++;
|
||||
} else if (*srcp == '/') {
|
||||
/* change '/' to "%2f" */
|
||||
@ -110,7 +111,9 @@ UNIXNormalizeFileName(NulibState* pState, const char* srcp, long srcLen,
|
||||
#elif defined(WINDOWS_LIKE)
|
||||
/*
|
||||
* You can't create files or directories with these names on a FAT filesystem,
|
||||
* because they're MS-DOS "device special files".
|
||||
* because they're MS-DOS "device special files". So, we either prepend
|
||||
* a '_' (if we're not preserving filenames) or "%00" (if we are). The
|
||||
* "%00" sequence gets stripped off during denormalization.
|
||||
*
|
||||
* The list comes from the Linux kernel's fs/msdos/namei.c.
|
||||
*/
|
||||
@ -139,7 +142,12 @@ Win32NormalizeFileName(NulibState* pState, const char* srcp, long srcLen,
|
||||
for (ppcch = fatReservedNames3; *ppcch != nil; ppcch++) {
|
||||
if (strncasecmp(srcp, *ppcch, srcLen) == 0) {
|
||||
DBUG(("--- fixing '%s'\n", *ppcch));
|
||||
*dstp++ = '_';
|
||||
if (NState_GetModPreserveType(pState)) {
|
||||
*dstp++ = kForeignIndic;
|
||||
*dstp++ = '0';
|
||||
*dstp++ = '0';
|
||||
} else
|
||||
*dstp++ = '_';
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -149,7 +157,12 @@ Win32NormalizeFileName(NulibState* pState, const char* srcp, long srcLen,
|
||||
for (ppcch = fatReservedNames4; *ppcch != nil; ppcch++) {
|
||||
if (strncasecmp(srcp, *ppcch, srcLen) == 0) {
|
||||
DBUG(("--- fixing '%s'\n", *ppcch));
|
||||
*dstp++ = '_';
|
||||
if (NState_GetModPreserveType(pState)) {
|
||||
*dstp++ = kForeignIndic;
|
||||
*dstp++ = '0';
|
||||
*dstp++ = '0';
|
||||
} else
|
||||
*dstp++ = '_';
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -159,9 +172,10 @@ Win32NormalizeFileName(NulibState* pState, const char* srcp, long srcLen,
|
||||
while (srcLen--) { /* don't go until null found! */
|
||||
Assert(*srcp != '\0');
|
||||
|
||||
if (*srcp == '%') {
|
||||
if (*srcp == kForeignIndic) {
|
||||
/* change '%' to "%%" */
|
||||
*dstp++ = *srcp;
|
||||
if (NState_GetModPreserveType(pState))
|
||||
*dstp++ = *srcp;
|
||||
*dstp++ = *srcp++;
|
||||
} else if (strchr(kInvalid, *srcp) != nil) {
|
||||
/* change invalid char to "%2f" or '_' */
|
||||
@ -397,6 +411,22 @@ UNIXTimeToDateTime(const time_t* pWhen, NuDateTime *pDateTime)
|
||||
#endif
|
||||
|
||||
#if defined(UNIX_LIKE) || defined(WINDOWS_LIKE)
|
||||
/*
|
||||
* Replace "oldc" with "newc". If we find an instance of "newc" already
|
||||
* in the string, replace it with "newSubst".
|
||||
*/
|
||||
static void
|
||||
ReplaceFssep(char* str, char oldc, char newc, char newSubst)
|
||||
{
|
||||
while (*str != '\0') {
|
||||
if (*str == oldc)
|
||||
*str = newc;
|
||||
else if (*str == newc)
|
||||
*str = newSubst;
|
||||
str++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the contents of a NuFileDetails structure, based on the pathname
|
||||
* and characteristics of the file.
|
||||
@ -407,6 +437,7 @@ SetFileDetails(NulibState* pState, const char* pathname, struct stat* psb,
|
||||
{
|
||||
Boolean wasPreserved;
|
||||
Boolean doJunk = false;
|
||||
Boolean adjusted;
|
||||
char* livePathStr;
|
||||
char slashDotDotSlash[5] = "_.._";
|
||||
time_t now;
|
||||
@ -421,12 +452,20 @@ SetFileDetails(NulibState* pState, const char* pathname, struct stat* psb,
|
||||
Assert(livePathStr != nil);
|
||||
strcpy(livePathStr, pathname);
|
||||
|
||||
/* under Win32, both '/' and '\' work... we want to settle on one */
|
||||
if (NState_GetAltSystemPathSeparator(pState) != '\0') {
|
||||
ReplaceFssep(livePathStr,
|
||||
NState_GetAltSystemPathSeparator(pState),
|
||||
NState_GetSystemPathSeparator(pState),
|
||||
NState_GetSystemPathSeparator(pState));
|
||||
}
|
||||
|
||||
/* init to defaults */
|
||||
memset(pDetails, 0, sizeof(*pDetails));
|
||||
pDetails->threadID = kNuThreadIDDataFork;
|
||||
pDetails->storageName = livePathStr; /* point at temp buffer */
|
||||
pDetails->fileSysID = kNuFileSysUnknown;
|
||||
pDetails->fileSysInfo = NState_GetSystemPathSeparator(pState);
|
||||
pDetails->fileSysInfo = kStorageFssep;
|
||||
pDetails->fileType = 0;
|
||||
pDetails->extraType = 0;
|
||||
pDetails->storageType = kNuStorageUnknown; /* let NufxLib worry about it */
|
||||
@ -483,23 +522,40 @@ SetFileDetails(NulibState* pState, const char* pathname, struct stat* psb,
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for other unpleasantness, such as a leading fssep.
|
||||
* Strip bad chars off the front of the pathname. Every time we
|
||||
* remove one thing we potentially expose another, so we have to
|
||||
* loop until it's sanitized.
|
||||
*
|
||||
* The outer loop isn't really necessary under Win32, because you'd
|
||||
* need to do something like ".\\foo", which isn't allowed. UNIX
|
||||
* silently allows ".//foo", so this is a problem there. (We could
|
||||
* probably do away with the inner loops, but those were already
|
||||
* written when I saw the larger problem.)
|
||||
*/
|
||||
Assert(NState_GetSystemPathSeparator(pState) != '\0');
|
||||
while (livePathStr[0] == NState_GetSystemPathSeparator(pState)) {
|
||||
/* slide it down, len is strlen +1 (for null) -1 (dropping first char)*/
|
||||
memmove(livePathStr, livePathStr+1, strlen(livePathStr));
|
||||
}
|
||||
do {
|
||||
adjusted = false;
|
||||
|
||||
/*
|
||||
* Remove leading "./".
|
||||
*/
|
||||
while (livePathStr[0] == '.' &&
|
||||
livePathStr[1] == NState_GetSystemPathSeparator(pState))
|
||||
{
|
||||
/* slide it down, len is strlen +1 (for null) -2 (dropping two chars) */
|
||||
memmove(livePathStr, livePathStr+2, strlen(livePathStr)-1);
|
||||
}
|
||||
/*
|
||||
* Check for other unpleasantness, such as a leading fssep.
|
||||
*/
|
||||
Assert(NState_GetSystemPathSeparator(pState) != '\0');
|
||||
while (livePathStr[0] == NState_GetSystemPathSeparator(pState)) {
|
||||
/* slide it down, len is (strlen +1), -1 (dropping first char)*/
|
||||
memmove(livePathStr, livePathStr+1, strlen(livePathStr));
|
||||
adjusted = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove leading "./".
|
||||
*/
|
||||
while (livePathStr[0] == '.' &&
|
||||
livePathStr[1] == NState_GetSystemPathSeparator(pState))
|
||||
{
|
||||
/* slide it down, len is (strlen +1) -2 (dropping two chars) */
|
||||
memmove(livePathStr, livePathStr+2, strlen(livePathStr)-1);
|
||||
adjusted = true;
|
||||
}
|
||||
} while (adjusted);
|
||||
|
||||
/*
|
||||
* If there's a "/../" present anywhere in the name, junk everything
|
||||
@ -517,6 +573,13 @@ SetFileDetails(NulibState* pState, const char* pathname, struct stat* psb,
|
||||
doJunk = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan for and remove "/./" and trailing "/.". They're filesystem
|
||||
* no-ops that work just fine under Win32 and UNIX but could confuse
|
||||
* a IIgs. (Of course, the user could just omit them from the pathname.)
|
||||
*/
|
||||
/* TO DO 20030208 */
|
||||
|
||||
/*
|
||||
* If "junk paths" is set, drop everything before the last fssep char.
|
||||
*/
|
||||
@ -529,6 +592,16 @@ SetFileDetails(NulibState* pState, const char* pathname, struct stat* psb,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Finally, substitute our generally-accepted path separator in place of
|
||||
* the local one, stomping on anything with a ':' in it as we do. The
|
||||
* goal is to avoid having "subdir:foo/bar" turn into "subdir/foo/bar".
|
||||
* Were we a general-purpose archiver, this might be a mistake, but
|
||||
* we're not. NuFX doesn't really give us a choice.
|
||||
*/
|
||||
ReplaceFssep(livePathStr, NState_GetSystemPathSeparator(pState),
|
||||
kStorageFssep, 'X');
|
||||
|
||||
/*bail:*/
|
||||
return kNuErrNone;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user