summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorGravatar Zach Hilman2019-04-28 18:42:05 -0400
committerGravatar Zach Hilman2019-09-30 17:18:38 -0400
commitc00ed8f4ffc4e6fca6337aecaa1acd390c71a584 (patch)
tree0733056f5b215343d9482c247ba5085c6094b1df /src/core
parentexternals: Add zlib and libzip libraries to handle ZIP file parsing (diff)
downloadyuzu-c00ed8f4ffc4e6fca6337aecaa1acd390c71a584.tar.gz
yuzu-c00ed8f4ffc4e6fca6337aecaa1acd390c71a584.tar.xz
yuzu-c00ed8f4ffc4e6fca6337aecaa1acd390c71a584.zip
vfs: Add function to extract ZIP file into virtual filesystem
Diffstat (limited to 'src/core')
-rw-r--r--src/core/file_sys/vfs_libzip.cpp83
-rw-r--r--src/core/file_sys/vfs_libzip.h13
2 files changed, 96 insertions, 0 deletions
diff --git a/src/core/file_sys/vfs_libzip.cpp b/src/core/file_sys/vfs_libzip.cpp
new file mode 100644
index 000000000..64f19a0ea
--- /dev/null
+++ b/src/core/file_sys/vfs_libzip.cpp
@@ -0,0 +1,83 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <string>
6#include <zip.h>
7#include "common/logging/backend.h"
8#include "core/file_sys/vfs.h"
9#include "core/file_sys/vfs_libzip.h"
10#include "core/file_sys/vfs_vector.h"
11
12namespace FileSys {
13
14VirtualDir ExtractZIP(VirtualFile file) {
15 zip_error_t error{};
16
17 const auto data = file->ReadAllBytes();
18 const auto src = zip_source_buffer_create(data.data(), data.size(), 0, &error);
19 if (src == nullptr)
20 return nullptr;
21
22 const auto zip = zip_open_from_source(src, 0, &error);
23 if (zip == nullptr)
24 return nullptr;
25
26 std::shared_ptr<VectorVfsDirectory> out = std::make_shared<VectorVfsDirectory>();
27
28 const auto num_entries = zip_get_num_entries(zip, 0);
29 if (num_entries == -1)
30 return nullptr;
31
32 zip_stat_t stat{};
33 zip_stat_init(&stat);
34
35 for (std::size_t i = 0; i < num_entries; ++i) {
36 const auto stat_res = zip_stat_index(zip, i, 0, &stat);
37 if (stat_res == -1)
38 return nullptr;
39
40 const std::string name(stat.name);
41 if (name.empty())
42 continue;
43
44 if (name[name.size() - 1] != '/') {
45 const auto file = zip_fopen_index(zip, i, 0);
46
47 std::vector<u8> buf(stat.size);
48 if (zip_fread(file, buf.data(), buf.size()) != buf.size())
49 return nullptr;
50
51 zip_fclose(file);
52
53 const auto parts = FileUtil::SplitPathComponents(stat.name);
54 const auto new_file = std::make_shared<VectorVfsFile>(buf, parts.back());
55
56 std::shared_ptr<VectorVfsDirectory> dtrv = out;
57 for (std::size_t j = 0; j < parts.size() - 1; ++j) {
58 if (dtrv == nullptr)
59 return nullptr;
60 const auto subdir = dtrv->GetSubdirectory(parts[j]);
61 if (subdir == nullptr) {
62 const auto temp = std::make_shared<VectorVfsDirectory>(
63 std::vector<VirtualFile>{}, std::vector<VirtualDir>{}, parts[j]);
64 dtrv->AddDirectory(temp);
65 dtrv = temp;
66 } else {
67 dtrv = std::dynamic_pointer_cast<VectorVfsDirectory>(subdir);
68 }
69 }
70
71 if (dtrv == nullptr)
72 return nullptr;
73 dtrv->AddFile(new_file);
74 }
75 }
76
77 zip_source_close(src);
78 zip_close(zip);
79
80 return out;
81}
82
83} // namespace FileSys
diff --git a/src/core/file_sys/vfs_libzip.h b/src/core/file_sys/vfs_libzip.h
new file mode 100644
index 000000000..f68af576a
--- /dev/null
+++ b/src/core/file_sys/vfs_libzip.h
@@ -0,0 +1,13 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/file_sys/vfs_types.h"
8
9namespace FileSys {
10
11VirtualDir ExtractZIP(VirtualFile zip);
12
13} // namespace FileSys