Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hrydgard
GitHub Repository: hrydgard/ppsspp
Path: blob/master/Common/File/VFS/VFS.cpp
5654 views
1
#include <cstring>
2
3
#include "Common/Common.h"
4
#include "Common/Log.h"
5
#include "Common/File/VFS/VFS.h"
6
#include "Common/File/FileUtil.h"
7
#include "Common/File/AndroidStorage.h"
8
#include "Common/StringUtils.h"
9
10
VFS g_VFS;
11
12
void VFS::Register(std::string_view prefix, VFSBackend *reader) {
13
if (reader) {
14
entries_.push_back(VFSEntry{ prefix, reader });
15
DEBUG_LOG(Log::IO, "Registered VFS for prefix %.*s: %s", STR_VIEW(prefix), reader->toString().c_str());
16
} else {
17
ERROR_LOG(Log::IO, "Trying to register null VFS backend for prefix %.*s", STR_VIEW(prefix));
18
}
19
}
20
21
void VFS::Clear() {
22
for (auto &entry : entries_) {
23
delete entry.reader;
24
}
25
entries_.clear();
26
}
27
28
// TODO: Use Path more.
29
static bool IsLocalAbsolutePath(std::string_view path) {
30
bool isUnixLocal = path[0] == '/';
31
#ifdef _WIN32
32
bool isWindowsLocal = (isalpha(path[0]) && path[1] == ':') || startsWith(path, "\\\\") || startsWith(path, "//");
33
#else
34
bool isWindowsLocal = false;
35
#endif
36
bool isContentURI = Android_IsContentUri(path);
37
return isUnixLocal || isWindowsLocal || isContentURI;
38
}
39
40
// The returned data should be free'd with delete[].
41
uint8_t *VFS::ReadFile(std::string_view filename, size_t *size) {
42
if (IsLocalAbsolutePath(filename)) {
43
// Local path, not VFS.
44
// INFO_LOG(Log::IO, "Not a VFS path: %s . Reading local file.", filename);
45
return File::ReadLocalFile(Path(filename), size);
46
}
47
48
const int fn_len = (int)filename.length();
49
bool fileSystemFound = false;
50
for (const auto &entry : entries_) {
51
int prefix_len = (int)entry.prefix.length();
52
if (prefix_len >= fn_len) continue;
53
if (0 == memcmp(filename.data(), entry.prefix.data(), prefix_len)) {
54
fileSystemFound = true;
55
// INFO_LOG(Log::IO, "Prefix match: %s (%s) -> %s", entries[i].prefix, filename, filename + prefix_len);
56
uint8_t *data = entry.reader->ReadFile(filename.substr(prefix_len), size);
57
if (data)
58
return data;
59
else
60
continue;
61
// Else try the other registered file systems.
62
}
63
}
64
if (!fileSystemFound) {
65
ERROR_LOG(Log::IO, "Missing filesystem for '%s'", filename);
66
} // Otherwise, the file was just missing. No need to log.
67
return nullptr;
68
}
69
70
bool VFS::GetFileListing(std::string_view path, std::vector<File::FileInfo> *listing, const char *filter) {
71
if (IsLocalAbsolutePath(path)) {
72
// Local path, not VFS.
73
// INFO_LOG(Log::IO, "Not a VFS path: %s . Reading local directory.", path);
74
File::GetFilesInDir(Path(path), listing, filter);
75
return true;
76
}
77
78
int fn_len = (int)path.length();
79
bool fileSystemFound = false;
80
for (const auto &entry : entries_) {
81
int prefix_len = (int)entry.prefix.length();
82
if (prefix_len >= fn_len) continue;
83
if (0 == memcmp(path.data(), entry.prefix.data(), prefix_len)) {
84
fileSystemFound = true;
85
if (entry.reader->GetFileListing(path.substr(prefix_len), listing, filter)) {
86
return true;
87
}
88
}
89
}
90
91
if (!fileSystemFound) {
92
ERROR_LOG(Log::IO, "Missing filesystem for %s", path);
93
} // Otherwise, the file was just missing. No need to log.
94
return false;
95
}
96
97
bool VFS::GetFileInfo(std::string_view path, File::FileInfo *info) {
98
if (IsLocalAbsolutePath(path)) {
99
// Local path, not VFS.
100
// INFO_LOG(Log::IO, "Not a VFS path: %s . Getting local file info.", path);
101
return File::GetFileInfo(Path(path), info);
102
}
103
104
bool fileSystemFound = false;
105
int fn_len = (int)path.length();
106
for (const auto &entry : entries_) {
107
int prefix_len = (int)entry.prefix.length();
108
if (prefix_len >= fn_len) continue;
109
if (0 == memcmp(path.data(), entry.prefix.data(), prefix_len)) {
110
fileSystemFound = true;
111
if (entry.reader->GetFileInfo(path.substr(prefix_len), info))
112
return true;
113
else
114
continue;
115
}
116
}
117
if (!fileSystemFound) {
118
ERROR_LOG(Log::IO, "Missing filesystem for '%s'", path);
119
} // Otherwise, the file was just missing. No need to log.
120
return false;
121
}
122
123
bool VFS::Exists(std::string_view path) {
124
if (IsLocalAbsolutePath(path)) {
125
// Local path, not VFS.
126
// INFO_LOG(Log::IO, "Not a VFS path: %s . Getting local file info.", path);
127
return File::Exists(Path(path));
128
}
129
130
bool fileSystemFound = false;
131
int fn_len = (int)path.length();
132
for (const auto &entry : entries_) {
133
int prefix_len = (int)entry.prefix.length();
134
if (prefix_len >= fn_len) continue;
135
if (0 == memcmp(path.data(), entry.prefix.data(), prefix_len)) {
136
fileSystemFound = true;
137
if (entry.reader->Exists(path.substr(prefix_len)))
138
return true;
139
else
140
continue;
141
}
142
}
143
if (!fileSystemFound) {
144
ERROR_LOG(Log::IO, "Missing filesystem for '%s'", path);
145
} // Otherwise, the file was just missing. No need to log.
146
return false;
147
}
148
149