CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

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