1 #include "Common/Log.h" 2 #include "Common/File/VFS/VFS.h" 3 #include "Common/File/VFS/AssetReader.h" 4 #include "Common/File/AndroidStorage.h" 5 6 struct VFSEntry { 7 const char *prefix; 8 AssetReader *reader; 9 }; 10 11 static VFSEntry entries[16]; 12 static int num_entries = 0; 13 14 void VFSRegister(const char *prefix, AssetReader *reader) { 15 entries[num_entries].prefix = prefix; 16 entries[num_entries].reader = reader; ~AssetReader()17 DEBUG_LOG(IO, "Registered VFS for prefix %s: %s", prefix, reader->toString().c_str()); 18 num_entries++; 19 } 20 21 void VFSShutdown() { 22 for (int i = 0; i < num_entries; i++) { 23 delete entries[i].reader; 24 } 25 num_entries = 0; 26 } 27 28 // TODO: Use Path more. 29 static bool IsLocalAbsolutePath(const char *path) { 30 bool isUnixLocal = path[0] == '/'; 31 #ifdef _WIN32 32 bool isWindowsLocal = isalpha(path[0]) && path[1] == ':'; 33 #else 34 bool isWindowsLocal = false; 35 #endif toString()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 *VFSReadFile(const char *filename, size_t *size) { 42 if (IsLocalAbsolutePath(filename)) { 43 // Local path, not VFS. 44 // INFO_LOG(IO, "Not a VFS path: %s . Reading local file.", filename); 45 return File::ReadLocalFile(Path(filename), size); 46 } 47 48 int fn_len = (int)strlen(filename); 49 bool fileSystemFound = false; 50 for (int i = 0; i < num_entries; i++) { 51 int prefix_len = (int)strlen(entries[i].prefix); 52 if (prefix_len >= fn_len) continue; toString()53 if (0 == memcmp(filename, entries[i].prefix, prefix_len)) { 54 fileSystemFound = true; 55 // INFO_LOG(IO, "Prefix match: %s (%s) -> %s", entries[i].prefix, filename, filename + prefix_len); 56 uint8_t *data = entries[i].reader->ReadAsset(filename + 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(IO, "Missing filesystem for '%s'", filename); 66 } // Otherwise, the file was just missing. No need to log. 67 return 0; 68 } 69 70 bool VFSGetFileListing(const char *path, std::vector<File::FileInfo> *listing, const char *filter) { 71 if (IsLocalAbsolutePath(path)) { 72 // Local path, not VFS. 73 // INFO_LOG(IO, "Not a VFS path: %s . Reading local directory.", path); 74 File::GetFilesInDir(Path(std::string(path)), listing, filter); 75 return true; 76 } 77 78 int fn_len = (int)strlen(path); 79 bool fileSystemFound = false; 80 for (int i = 0; i < num_entries; i++) { 81 int prefix_len = (int)strlen(entries[i].prefix); 82 if (prefix_len >= fn_len) continue; 83 if (0 == memcmp(path, entries[i].prefix, prefix_len)) { 84 fileSystemFound = true; 85 if (entries[i].reader->GetFileListing(path + prefix_len, listing, filter)) { 86 return true; 87 } 88 } 89 } 90 91 if (!fileSystemFound) { 92 ERROR_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 VFSGetFileInfo(const char *path, File::FileInfo *info) { 98 if (IsLocalAbsolutePath(path)) { 99 // Local path, not VFS. 100 // INFO_LOG(IO, "Not a VFS path: %s . Getting local file info.", path); 101 return File::GetFileInfo(Path(std::string(path)), info); 102 } 103 104 bool fileSystemFound = false; 105 int fn_len = (int)strlen(path); 106 for (int i = 0; i < num_entries; i++) { 107 int prefix_len = (int)strlen(entries[i].prefix); 108 if (prefix_len >= fn_len) continue; 109 if (0 == memcmp(path, entries[i].prefix, prefix_len)) { 110 fileSystemFound = true; 111 if (entries[i].reader->GetFileInfo(path + prefix_len, info)) 112 return true; 113 else 114 continue; 115 } 116 } 117 if (!fileSystemFound) { 118 ERROR_LOG(IO, "Missing filesystem for %s", path); 119 } // Otherwise, the file was just missing. No need to log. 120 return false; 121 } 122