summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tools/knarc/Makefile4
-rw-r--r--tools/knarc/Narc.cpp77
-rw-r--r--tools/knarc/Narc.h22
-rw-r--r--tools/knarc/fnmatch.c220
-rw-r--r--tools/knarc/fnmatch.h70
5 files changed, 342 insertions, 51 deletions
diff --git a/tools/knarc/Makefile b/tools/knarc/Makefile
index 62af834f..ef75789b 100644
--- a/tools/knarc/Makefile
+++ b/tools/knarc/Makefile
@@ -1,7 +1,7 @@
CXXFLAGS := -std=c++17 -O2 -Wall -Wno-switch -lstdc++fs
-SRCS := Source.cpp Narc.cpp
-HEADERS := Narc.h
+SRCS := Source.cpp Narc.cpp fnmatch.c
+HEADERS := Narc.h fnmatch.h
.PHONY: all clean
diff --git a/tools/knarc/Narc.cpp b/tools/knarc/Narc.cpp
index 2faed98e..f299375f 100644
--- a/tools/knarc/Narc.cpp
+++ b/tools/knarc/Narc.cpp
@@ -6,6 +6,7 @@
#include <fstream>
#include <iomanip>
#include <ios>
+#include <iostream>
#include <map>
#include <memory>
#include <regex>
@@ -13,10 +14,10 @@
#include <stack>
#include <string>
#include <vector>
-#include <iostream>
-#include <fnmatch.h>
-#if __GNUC__ <= 7
+#include "fnmatch.h"
+
+#if (__GNUC__ <= 7) && !defined _MSC_VER
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#else
@@ -111,31 +112,31 @@ NarcError Narc::GetError() const
class WildcardVector : public vector<string> {
public:
- WildcardVector(fs::path fp) {
- fstream infile;
- if (!fs::exists(fp)) return;
- infile.open(fp, ios_base::in);
- string line;
- while (getline(infile, line)) {
- if (!line.empty())
- {
- // strip CR
- size_t i;
- for (i = line.size() - 1; line[i] == '\r'; i--)
- ;
- if (i < line.size() - 1)
- line.erase(i + 1);
- push_back(line);
- }
- }
- }
- bool matches(string fp) {
- for (string& pattern : *this) {
- if (fnmatch(pattern.c_str(), fp.c_str(), FNM_PERIOD) == 0)
- return true;
- }
- return false;
- }
+ WildcardVector(fs::path fp) {
+ fstream infile;
+ if (!fs::exists(fp)) return;
+ infile.open(fp, ios_base::in);
+ string line;
+ while (getline(infile, line)) {
+ if (!line.empty())
+ {
+ // strip CR
+ size_t i;
+ for (i = line.size() - 1; line[i] == '\r'; i--)
+ ;
+ if (i < line.size() - 1)
+ line.erase(i + 1);
+ push_back(line);
+ }
+ }
+ }
+ bool matches(string fp) {
+ for (string& pattern : *this) {
+ if (fnmatch(pattern.c_str(), fp.c_str(), FNM_PERIOD) == 0)
+ return true;
+ }
+ return false;
+ }
};
bool Narc::Pack(const fs::path& fileName, const fs::path& directory)
@@ -158,11 +159,11 @@ bool Narc::Pack(const fs::path& fileName, const fs::path& directory)
{
++directoryCounter;
}
- else if (keep_patterns.matches(de.path().filename()) || !ignore_patterns.matches(de.path().filename()))
+ else if (keep_patterns.matches(de.path().filename().string()) || !ignore_patterns.matches(de.path().filename().string()))
{
- if (debug) {
- cerr << "DEBUG: adding file " << de.path() << endl;
- }
+ if (debug) {
+ cerr << "DEBUG: adding file " << de.path() << endl;
+ }
fatEntries.push_back(FileAllocationTableEntry
{
.Start = 0x0,
@@ -198,7 +199,7 @@ bool Narc::Pack(const fs::path& fileName, const fs::path& directory)
for (const auto& de : OrderedDirectoryIterator(directory, true))
{
- if (!subTables.count(de.path().parent_path()) && (keep_patterns.matches(de.path().filename()) || !ignore_patterns.matches(de.path().filename())))
+ if (!subTables.count(de.path().parent_path()) && (keep_patterns.matches(de.path().filename().string()) || !ignore_patterns.matches(de.path().filename().string())))
{
subTables.insert({ de.path().parent_path(), "" });
paths.push_back(de.path().parent_path());
@@ -213,7 +214,7 @@ bool Narc::Pack(const fs::path& fileName, const fs::path& directory)
subTables[de.path().parent_path()] += (0xF000 + directoryCounter) & 0xFF;
subTables[de.path().parent_path()] += (0xF000 + directoryCounter) >> 8;
}
- else if (keep_patterns.matches(de.path().filename()) || !ignore_patterns.matches(de.path().filename()))
+ else if (keep_patterns.matches(de.path().filename().string()) || !ignore_patterns.matches(de.path().filename().string()))
{
subTables[de.path().parent_path()] += static_cast<uint8_t>(de.path().filename().string().size());
subTables[de.path().parent_path()] += de.path().filename().string();
@@ -345,10 +346,10 @@ bool Narc::Pack(const fs::path& fileName, const fs::path& directory)
continue;
}
- if (!(keep_patterns.matches(de.path().filename()) || !ignore_patterns.matches(de.path().filename())))
- {
- continue;
- }
+ if (!(keep_patterns.matches(de.path().filename().string()) || !ignore_patterns.matches(de.path().filename().string())))
+ {
+ continue;
+ }
ifstream ifs(de.path(), ios::binary | ios::ate);
diff --git a/tools/knarc/Narc.h b/tools/knarc/Narc.h
index 4516d2d5..ba97cbc9 100644
--- a/tools/knarc/Narc.h
+++ b/tools/knarc/Narc.h
@@ -5,7 +5,7 @@
#include <string>
#include <vector>
-#if __GNUC__ <= 7
+#if (__GNUC__ <= 7) && !defined _MSC_VER
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#else
@@ -75,19 +75,19 @@ struct FileImages
class Narc
{
- public:
- NarcError GetError() const;
+public:
+ NarcError GetError() const;
- bool Pack(const fs::path& fileName, const fs::path& directory);
- bool Unpack(const fs::path& fileName, const fs::path& directory);
+ bool Pack(const fs::path& fileName, const fs::path& directory);
+ bool Unpack(const fs::path& fileName, const fs::path& directory);
- private:
- NarcError error = NarcError::None;
+private:
+ NarcError error = NarcError::None;
- void AlignDword(std::ofstream& ofs, uint8_t paddingChar);
+ void AlignDword(std::ofstream& ofs, uint8_t paddingChar);
- bool Cleanup(std::ifstream& ifs, const NarcError& e);
- bool Cleanup(std::ofstream& ofs, const NarcError& e);
+ bool Cleanup(std::ifstream& ifs, const NarcError& e);
+ bool Cleanup(std::ofstream& ofs, const NarcError& e);
- std::vector<fs::directory_entry> OrderedDirectoryIterator(const fs::path& path, bool recursive) const;
+ std::vector<fs::directory_entry> OrderedDirectoryIterator(const fs::path& path, bool recursive) const;
};
diff --git a/tools/knarc/fnmatch.c b/tools/knarc/fnmatch.c
new file mode 100644
index 00000000..5ab452f0
--- /dev/null
+++ b/tools/knarc/fnmatch.c
@@ -0,0 +1,220 @@
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
+
+NOTE: This source is derived from an old version taken from the GNU C
+Library (glibc).
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, 51 Franklin Street - Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#ifdef HAVE_CONFIG_H
+#if defined (CONFIG_BROKETS)
+/* We use <config.h> instead of "config.h" so that a compilation
+ using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
+ (which it would do because it found this file in $srcdir). */
+#include <config.h>
+#else
+#include "config.h"
+#endif
+#endif
+
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+/* This code to undef const added in libiberty. */
+#ifndef __STDC__
+/* This is a separate conditional since some stdc systems
+ reject `defined (const)'. */
+#ifndef const
+#define const
+#endif
+#endif
+
+#include "fnmatch.h"
+
+#include <ctype.h>
+
+ /* Comment out all this code if we are using the GNU C Library, and are not
+ actually compiling the library itself. This code is part of the GNU C
+ Library, but also included in many other GNU distributions. Compiling
+ and linking in this code is a waste when using the GNU C library
+ (especially if it is a shared library). Rather than having every GNU
+ program understand `configure --with-gnu-libc' and omit the object files,
+ it is simpler to just do this in the source for each such file. */
+
+#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
+
+
+#if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS)
+extern int errno;
+#endif
+
+/* Match STRING against the filename pattern PATTERN, returning zero if
+ it matches, nonzero if not. */
+int
+fnmatch(const char* pattern, const char* string, int flags)
+{
+ register const char* p = pattern, * n = string;
+ register unsigned char c;
+
+#define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c))
+
+ while ((c = *p++) != '\0')
+ {
+ c = FOLD(c);
+
+ switch (c)
+ {
+ case '?':
+ if (*n == '\0')
+ return FNM_NOMATCH;
+ else if ((flags & FNM_FILE_NAME) && *n == '/')
+ return FNM_NOMATCH;
+ else if ((flags & FNM_PERIOD) && *n == '.' &&
+ (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
+ return FNM_NOMATCH;
+ break;
+
+ case '\\':
+ if (!(flags & FNM_NOESCAPE))
+ {
+ c = *p++;
+ c = FOLD(c);
+ }
+ if (FOLD((unsigned char)*n) != c)
+ return FNM_NOMATCH;
+ break;
+
+ case '*':
+ if ((flags & FNM_PERIOD) && *n == '.' &&
+ (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
+ return FNM_NOMATCH;
+
+ for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
+ if (((flags & FNM_FILE_NAME) && *n == '/') ||
+ (c == '?' && *n == '\0'))
+ return FNM_NOMATCH;
+
+ if (c == '\0')
+ return 0;
+
+ {
+ unsigned char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
+ c1 = FOLD(c1);
+ for (--p; *n != '\0'; ++n)
+ if ((c == '[' || FOLD((unsigned char)*n) == c1) &&
+ fnmatch(p, n, flags & ~FNM_PERIOD) == 0)
+ return 0;
+ return FNM_NOMATCH;
+ }
+
+ case '[':
+ {
+ /* Nonzero if the sense of the character class is inverted. */
+ register int negate;
+
+ if (*n == '\0')
+ return FNM_NOMATCH;
+
+ if ((flags & FNM_PERIOD) && *n == '.' &&
+ (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
+ return FNM_NOMATCH;
+
+ negate = (*p == '!' || *p == '^');
+ if (negate)
+ ++p;
+
+ c = *p++;
+ for (;;)
+ {
+ register unsigned char cstart = c, cend = c;
+
+ if (!(flags & FNM_NOESCAPE) && c == '\\')
+ cstart = cend = *p++;
+
+ cstart = cend = FOLD(cstart);
+
+ if (c == '\0')
+ /* [ (unterminated) loses. */
+ return FNM_NOMATCH;
+
+ c = *p++;
+ c = FOLD(c);
+
+ if ((flags & FNM_FILE_NAME) && c == '/')
+ /* [/] can never match. */
+ return FNM_NOMATCH;
+
+ if (c == '-' && *p != ']')
+ {
+ cend = *p++;
+ if (!(flags & FNM_NOESCAPE) && cend == '\\')
+ cend = *p++;
+ if (cend == '\0')
+ return FNM_NOMATCH;
+ cend = FOLD(cend);
+
+ c = *p++;
+ }
+
+ if (FOLD((unsigned char)*n) >= cstart
+ && FOLD((unsigned char)*n) <= cend)
+ goto matched;
+
+ if (c == ']')
+ break;
+ }
+ if (!negate)
+ return FNM_NOMATCH;
+ break;
+
+ matched:;
+ /* Skip the rest of the [...] that already matched. */
+ while (c != ']')
+ {
+ if (c == '\0')
+ /* [... (unterminated) loses. */
+ return FNM_NOMATCH;
+
+ c = *p++;
+ if (!(flags & FNM_NOESCAPE) && c == '\\')
+ /* XXX 1003.2d11 is unclear if this is right. */
+ ++p;
+ }
+ if (negate)
+ return FNM_NOMATCH;
+ }
+ break;
+
+ default:
+ if (c != FOLD((unsigned char)*n))
+ return FNM_NOMATCH;
+ }
+
+ ++n;
+ }
+
+ if (*n == '\0')
+ return 0;
+
+ if ((flags & FNM_LEADING_DIR) && *n == '/')
+ /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */
+ return 0;
+
+ return FNM_NOMATCH;
+}
+
+#endif /* _LIBC or not __GNU_LIBRARY__. */
diff --git a/tools/knarc/fnmatch.h b/tools/knarc/fnmatch.h
new file mode 100644
index 00000000..508c59a7
--- /dev/null
+++ b/tools/knarc/fnmatch.h
@@ -0,0 +1,70 @@
+/* Copyright (C) 1991-2020 Free Software Foundation, Inc.
+
+NOTE: The canonical source of this file is maintained with the GNU C Library.
+Bugs can be reported to bug-glibc@prep.ai.mit.edu.
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, 51 Franklin Street - Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#ifndef _FNMATCH_H
+
+#define _FNMATCH_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined (__cplusplus) || (defined (__STDC__) && __STDC__)
+#undef __P
+#define __P(args) args
+#else /* Not C++ or ANSI C. */
+#undef __P
+#define __P(args) ()
+ /* We can get away without defining `const' here only because in this file
+ it is used only inside the prototype for `fnmatch', which is elided in
+ non-ANSI C where `const' is problematical. */
+#endif /* C++ or ANSI C. */
+
+
+ /* We #undef these before defining them because some losing systems
+ (HP-UX A.08.07 for example) define these in <unistd.h>. */
+#undef FNM_PATHNAME
+#undef FNM_NOESCAPE
+#undef FNM_PERIOD
+
+ /* Bits set in the FLAGS argument to `fnmatch'. */
+#define FNM_PATHNAME (1 << 0) /* No wildcard can ever match `/'. */
+#define FNM_NOESCAPE (1 << 1) /* Backslashes don't quote special chars. */
+#define FNM_PERIOD (1 << 2) /* Leading `.' is matched only explicitly. */
+
+#if !defined (_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 2 || defined (_GNU_SOURCE)
+#define FNM_FILE_NAME FNM_PATHNAME /* Preferred GNU name. */
+#define FNM_LEADING_DIR (1 << 3) /* Ignore `/...' after a match. */
+#define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */
+#endif
+
+/* Value returned by `fnmatch' if STRING does not match PATTERN. */
+#define FNM_NOMATCH 1
+
+/* Match STRING against the filename pattern PATTERN,
+ returning zero if it matches, FNM_NOMATCH if not. */
+ extern int fnmatch __P((const char* __pattern, const char* __string,
+ int __flags));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* fnmatch.h */