summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPetr Mrázek <peterix@gmail.com>2020-10-12 01:01:51 +0200
committerPetr Mrázek <peterix@gmail.com>2020-10-12 01:01:51 +0200
commitdded11004fc92e6edcfe1e64e68e534085d05868 (patch)
tree69dc64f0a4c3651602424d016e9629549fb7b599
parentf1284ab96b48f9964cf6a1d51a89084e54d6b53f (diff)
downloadMultiMC-dded11004fc92e6edcfe1e64e68e534085d05868.tar
MultiMC-dded11004fc92e6edcfe1e64e68e534085d05868.tar.gz
MultiMC-dded11004fc92e6edcfe1e64e68e534085d05868.tar.lz
MultiMC-dded11004fc92e6edcfe1e64e68e534085d05868.tar.xz
MultiMC-dded11004fc92e6edcfe1e64e68e534085d05868.zip
NOISSUE adapt to work on Windows, fix reading symlink targets on POSIX
-rw-r--r--api/logic/mojang/PackageManifest.cpp65
-rw-r--r--api/logic/mojang/PackageManifest_test.cpp51
-rw-r--r--api/logic/mojang/testdata/inspect_win/a/b.txt0
-rw-r--r--api/logic/mojang/testdata/inspect_win/a/b/b.txt0
4 files changed, 94 insertions, 22 deletions
diff --git a/api/logic/mojang/PackageManifest.cpp b/api/logic/mojang/PackageManifest.cpp
index 0b420568..b3dfd7fc 100644
--- a/api/logic/mojang/PackageManifest.cpp
+++ b/api/logic/mojang/PackageManifest.cpp
@@ -5,6 +5,12 @@
#include <QCryptographicHash>
#include <QDebug>
+#ifndef Q_OS_WIN32
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#endif
+
namespace mojang_files {
const Hash hash_of_empty_string = "da39a3ee5e6b4b0d3255bfef95601890afd80709";
@@ -177,6 +183,49 @@ Package Package::fromManifestFile(const QString & filename) {
}
}
+#ifndef Q_OS_WIN32
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+namespace {
+// FIXME: Qt obscures symlink targets by making them absolute. that is useless. this is the workaround - we do it ourselves
+bool actually_read_symlink_target(const QString & filepath, Path & out)
+{
+ struct ::stat st;
+ // FIXME: here, we assume the native filesystem encoding. May the Gods have mercy upon our Souls.
+ QByteArray nativePath = filepath.toUtf8();
+ const char * filepath_cstr = nativePath.data();
+
+ if (lstat(filepath_cstr, &st) != 0)
+ {
+ return false;
+ }
+
+ auto size = st.st_size ? st.st_size + 1 : PATH_MAX;
+ std::string temp(size, '\0');
+ // because we don't realiably know how long the damn thing actually is, we loop and expand. POSIX is naff
+ do
+ {
+ auto link_length = ::readlink(filepath_cstr, &temp[0], temp.size());
+ if(link_length == -1)
+ {
+ return false;
+ }
+ if(std::string::size_type(link_length) < temp.size())
+ {
+ // buffer was long enough and we managed to read the link target. RETURN here.
+ temp.resize(link_length);
+ out = Path(QString::fromUtf8(temp.c_str()));
+ return true;
+ }
+ temp.resize(temp.size() * 2);
+ } while (true);
+}
+}
+#endif
+
// FIXME: Qt filesystem abstraction is bad, but ... let's hope it doesn't break too much?
// FIXME: The error handling is just DEFICIENT
Package Package::fromInspectedFolder(const QString& folderPath)
@@ -190,10 +239,22 @@ Package Package::fromInspectedFolder(const QString& folderPath)
auto fileInfo = iterator.fileInfo();
auto relPath = root.relativeFilePath(fileInfo.filePath());
+ // FIXME: this is probably completely busted on Windows anyway, so just disable it.
+ // Qt makes shit up and doesn't understand the platform details
+ // TODO: Actually use a filesystem library that isn't terrible and has decen license.
+ // I only know one, and I wrote it. Sadly, currently proprietary. PAIN.
+#ifndef Q_OS_WIN32
if(fileInfo.isSymLink()) {
- out.addLink(relPath, fileInfo.symLinkTarget());
+ Path targetPath;
+ if(!actually_read_symlink_target(fileInfo.filePath(), targetPath)) {
+ qCritical() << "Folder inspection: Unknown filesystem object:" << fileInfo.absoluteFilePath();
+ out.valid = false;
+ }
+ out.addLink(relPath, targetPath);
}
- else if(fileInfo.isDir()) {
+ else
+#endif
+ if(fileInfo.isDir()) {
out.addFolder(relPath);
}
else if(fileInfo.isFile()) {
diff --git a/api/logic/mojang/PackageManifest_test.cpp b/api/logic/mojang/PackageManifest_test.cpp
index 178de5dc..d4c55c5a 100644
--- a/api/logic/mojang/PackageManifest_test.cpp
+++ b/api/logic/mojang/PackageManifest_test.cpp
@@ -20,8 +20,9 @@ private slots:
void test_parse();
void test_parse_file();
void test_inspect();
- void test_diff();
-
+#ifndef Q_OS_WIN32
+ void test_inspect_symlinks();
+#endif
void mkdir_deep();
void rmdir_deep();
@@ -87,7 +88,31 @@ void PackageManifestTest::test_parse_file() {
QVERIFY(manifest.valid == true);
}
+
void PackageManifestTest::test_inspect() {
+ auto path = QFINDTESTDATA("testdata/inspect_win/");
+ auto manifest = Package::fromInspectedFolder(path);
+ QVERIFY(manifest.valid == true);
+ QVERIFY(manifest.files.size() == 2);
+ QVERIFY(manifest.files.count(Path("a/b.txt")));
+ auto &file1 = manifest.files[Path("a/b.txt")];
+ QVERIFY(file1.executable == false);
+ QVERIFY(file1.hash == "da39a3ee5e6b4b0d3255bfef95601890afd80709");
+ QVERIFY(file1.size == 0);
+ QVERIFY(manifest.files.count(Path("a/b/b.txt")));
+ auto &file2 = manifest.files[Path("a/b/b.txt")];
+ QVERIFY(file2.executable == false);
+ QVERIFY(file2.hash == "da39a3ee5e6b4b0d3255bfef95601890afd80709");
+ QVERIFY(file2.size == 0);
+ QVERIFY(manifest.folders.size() == 3);
+ QVERIFY(manifest.folders.count(Path(".")));
+ QVERIFY(manifest.folders.count(Path("a")));
+ QVERIFY(manifest.folders.count(Path("a/b")));
+ QVERIFY(manifest.symlinks.size() == 0);
+}
+
+#ifndef Q_OS_WIN32
+void PackageManifestTest::test_inspect_symlinks() {
auto path = QFINDTESTDATA("testdata/inspect/");
auto manifest = Package::fromInspectedFolder(path);
QVERIFY(manifest.valid == true);
@@ -102,25 +127,11 @@ void PackageManifestTest::test_inspect() {
QVERIFY(manifest.folders.count(Path("a")));
QVERIFY(manifest.folders.count(Path("a/b")));
QVERIFY(manifest.symlinks.size() == 1);
+ QVERIFY(manifest.symlinks.count(Path("a/b/b.txt")));
+ qDebug() << manifest.symlinks[Path("a/b/b.txt")];
+ QVERIFY(manifest.symlinks[Path("a/b/b.txt")] == Path("../b.txt"));
}
-
-void PackageManifestTest::test_diff() {
- auto path = QFINDTESTDATA("testdata/inspect/");
- auto from = Package::fromInspectedFolder(path);
- auto to = Package::fromManifestContents(basic_manifest);
- auto operations = UpdateOperations::resolve(from, to);
- QVERIFY(operations.valid == true);
- QVERIFY(operations.mkdirs.size() == 1);
- QVERIFY(operations.mkdirs[0] == Path("a/b/c"));
-
- QVERIFY(operations.rmdirs.size() == 0);
- QVERIFY(operations.deletes.size() == 1);
- QVERIFY(operations.deletes[0] == Path("a/b/b.txt"));
- QVERIFY(operations.downloads.size() == 0);
- QVERIFY(operations.mklinks.size() == 1);
- QVERIFY(operations.mklinks.count(Path("a/b/c.txt")));
- QVERIFY(operations.mklinks[Path("a/b/c.txt")] == Path("../b.txt"));
-}
+#endif
void PackageManifestTest::mkdir_deep() {
diff --git a/api/logic/mojang/testdata/inspect_win/a/b.txt b/api/logic/mojang/testdata/inspect_win/a/b.txt
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/api/logic/mojang/testdata/inspect_win/a/b.txt
diff --git a/api/logic/mojang/testdata/inspect_win/a/b/b.txt b/api/logic/mojang/testdata/inspect_win/a/b/b.txt
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/api/logic/mojang/testdata/inspect_win/a/b/b.txt