Pyrogenesis trunk
vfs.h
Go to the documentation of this file.
1/* Copyright (C) 2022 Wildfire Games.
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining
4 * a copy of this software and associated documentation files (the
5 * "Software"), to deal in the Software without restriction, including
6 * without limitation the rights to use, copy, modify, merge, publish,
7 * distribute, sublicense, and/or sell copies of the Software, and to
8 * permit persons to whom the Software is furnished to do so, subject to
9 * the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 */
22
23/*
24 * Virtual File System API - allows transparent access to files in
25 * archives, modding via multiple mount points and hotloading.
26 */
27
28#ifndef INCLUDED_VFS
29#define INCLUDED_VFS
30
31#include "lib/file/file_system.h" // CFileInfo
33
34constexpr size_t VFS_MIN_PRIORITY = 0;
35constexpr size_t VFS_MAX_PRIORITY = std::numeric_limits<size_t>::max();
36
37namespace ERR
38{
39 const Status VFS_DIR_NOT_FOUND = -110100;
40 const Status VFS_FILE_NOT_FOUND = -110101;
41 const Status VFS_ALREADY_MOUNTED = -110102;
42}
43
44// (recursive mounting and mounting archives are no longer optional since they don't hurt)
46{
47 /**
48 * all real directories mounted during this operation will be watched
49 * for changes. this flag is provided to avoid watches in output-only
50 * directories, e.g. screenshots/ (only causes unnecessary overhead).
51 **/
53
54 /**
55 * anything mounted from here should be included when building archives.
56 **/
58
59 /**
60 * return ERR::VFS_DIR_NOT_FOUND if the given real path doesn't exist.
61 * (the default behavior is to create all real directories in the path)
62 **/
64
65 /**
66 * keep the files named "*.DELETED" visible in the VFS directories.
67 * the standard behavior of hiding the file with the same name minus the
68 * ".DELETED" suffix will still apply.
69 * (the default behavior is to hide both the suffixed and unsuffixed files)
70 **/
72};
73
74// (member functions are thread-safe after the instance has been
75// constructed - each acquires a mutex.)
76struct IVFS
77{
78 virtual ~IVFS() {}
79
80 /**
81 * mount a directory into the VFS.
82 *
83 * @param mountPoint (will be created if it does not already exist)
84 * @param path real directory path
85 * @param flags
86 * @param priority
87 * @return Status.
88 *
89 * if files are encountered that already exist in the VFS (sub)directories,
90 * the most recent / highest priority/precedence version is preferred.
91 *
92 * Note that the 'real directory' associated with a VFS Path
93 * will be relative to the highest priority subdirectory in the path,
94 * and that in case of equal priority, the order is _undefined_,
95 * and will depend on the exact order of populate() calls.
96 *
97 * if files with archive extensions are seen, their contents are added
98 * as well.
99 **/
100 virtual Status Mount(const VfsPath& mountPoint, const OsPath& path, size_t flags = 0, size_t priority = 0) = 0;
101
102 /**
103 * Retrieve information about a file (similar to POSIX stat).
104 *
105 * @param pathname
106 * @param pfileInfo receives information about the file. Passing NULL
107 * suppresses warnings if the file doesn't exist.
108 *
109 * @return Status.
110 **/
111 virtual Status GetFileInfo(const VfsPath& pathname, CFileInfo* pfileInfo) const = 0;
112
113 /**
114 * Retrieve mount priority for a file.
115 *
116 * @param pathname
117 * @param ppriority receives priority value, if the file can be found.
118 *
119 * @return Status.
120 **/
121 virtual Status GetFilePriority(const VfsPath& pathname, size_t* ppriority) const = 0;
122
123 /**
124 * Retrieve lists of all files and subdirectories in a directory.
125 *
126 * @return Status.
127 *
128 * Rationale:
129 * - this interface avoids having to lock the directory while an
130 * iterator is extant.
131 * - we cannot efficiently provide routines for returning files and
132 * subdirectories separately due to the underlying POSIX interface.
133 **/
134 virtual Status GetDirectoryEntries(const VfsPath& path, CFileInfos* fileInfos, DirectoryNames* subdirectoryNames) const = 0;
135
136 /**
137 * Create a file with the given contents.
138 * @param pathname
139 * @param fileContents
140 * @param size [bytes] of the contents, will match that of the file.
141 * @return Status.
142 **/
143 virtual Status CreateFile(const VfsPath& pathname, const std::shared_ptr<u8>& fileContents, size_t size) = 0;
144
145 /**
146 * Read an entire file into memory.
147 *
148 * @param pathname
149 * @param fileContents receives a smart pointer to the contents.
150 * @param size receives the size [bytes] of the file contents.
151 * @return Status.
152 **/
153 virtual Status LoadFile(const VfsPath& pathname, std::shared_ptr<u8>& fileContents, size_t& size) = 0;
154
155 /**
156 * @return a string representation of all files and directories.
157 **/
158 virtual std::wstring TextRepresentation() const = 0;
159
160 /**
161 * Retrieve the POSIX pathname a VFS file was loaded from.
162 * This is distinct from the current 'real' path, since that depends on the parent directory's real path,
163 * which may have been overwritten by a mod or another call to Mount().
164 *
165 * This is used by the caching to split by mod, and you also ought to call this to delete a file.
166 * (note that deleting has other issues, see below).
167 **/
168 virtual Status GetOriginalPath(const VfsPath& filename, OsPath& loadedPathname) = 0;
169
170 /**
171 * Retrieve the real (POSIX) pathname underlying a VFS file.
172 * This is useful for passing paths to external libraries.
173 * Note that this returns the real path relative to the highest priority VFS subpath.
174 * @param createMissingDirectories - if true, create subdirectories on the file system as required.
175 * (this defaults to true because, in general, this function is then used to create new files).
176 **/
177 virtual Status GetRealPath(const VfsPath& pathname, OsPath& realPathname, bool createMissingDirectories = true) = 0;
178
179 /**
180 * Retrieve the real (POSIX) pathname underlying a VFS directory.
181 * This is useful for passing paths to external libraries.
182 * Note that this returns the real path relative to the highest priority VFS subpath.
183 * @param createMissingDirectories - if true, create subdirectories on the file system as required.
184 * (this defaults to true because, in general, this function is then used to create new files).
185 **/
186 virtual Status GetDirectoryRealPath(const VfsPath& pathname, OsPath& realPathname, bool createMissingDirectories = true) = 0;
187
188 /**
189 * retrieve the VFS pathname that corresponds to a real file.
190 *
191 * this is useful for reacting to file change notifications.
192 *
193 * the current implementation requires time proportional to the
194 * number of directories; this could be accelerated by only checking
195 * directories below a mount point with a matching real path.
196 **/
197 virtual Status GetVirtualPath(const OsPath& realPathname, VfsPath& pathname) = 0;
198
199 /**
200 * remove file from the virtual directory listing.
201 **/
202 virtual Status RemoveFile(const VfsPath& pathname) = 0;
203
204 /**
205 * request the directory be re-populated when it is next accessed.
206 * useful for synchronizing with the underlying filesystem after
207 * files have been created or their metadata changed.
208 **/
209 virtual Status RepopulateDirectory(const VfsPath& path) = 0;
210
211 /**
212 * empty the contents of the filesystem.
213 * this is typically only necessary when changing the set of
214 * mounted directories, e.g. when switching mods.
215 * NB: open files are not affected.
216 **/
217 virtual void Clear() = 0;
218};
219
220typedef std::shared_ptr<IVFS> PIVFS;
221
222/**
223 * create an instance of a Virtual File System.
224 *
225 * note: there is no limitation to a single instance, it may make sense
226 * to create and destroy VFS instances during each unit test.
227 **/
229
230#endif // #ifndef INCLUDED_VFS
Definition: file_system.h:43
Definition: path.h:80
std::vector< OsPath > DirectoryNames
Definition: file_system.h:78
std::vector< CFileInfo > CFileInfos
Definition: file_system.h:77
Definition: debug.h:408
const Status VFS_FILE_NOT_FOUND
Definition: vfs.h:40
const Status VFS_DIR_NOT_FOUND
Definition: vfs.h:39
const Status VFS_ALREADY_MOUNTED
Definition: vfs.h:41
i64 Status
Error handling system.
Definition: status.h:173
Definition: vfs.h:77
virtual Status GetVirtualPath(const OsPath &realPathname, VfsPath &pathname)=0
retrieve the VFS pathname that corresponds to a real file.
virtual Status LoadFile(const VfsPath &pathname, std::shared_ptr< u8 > &fileContents, size_t &size)=0
Read an entire file into memory.
virtual Status GetDirectoryRealPath(const VfsPath &pathname, OsPath &realPathname, bool createMissingDirectories=true)=0
Retrieve the real (POSIX) pathname underlying a VFS directory.
virtual Status GetRealPath(const VfsPath &pathname, OsPath &realPathname, bool createMissingDirectories=true)=0
Retrieve the real (POSIX) pathname underlying a VFS file.
virtual Status GetFileInfo(const VfsPath &pathname, CFileInfo *pfileInfo) const =0
Retrieve information about a file (similar to POSIX stat).
virtual Status Mount(const VfsPath &mountPoint, const OsPath &path, size_t flags=0, size_t priority=0)=0
mount a directory into the VFS.
virtual Status RepopulateDirectory(const VfsPath &path)=0
request the directory be re-populated when it is next accessed.
virtual Status GetDirectoryEntries(const VfsPath &path, CFileInfos *fileInfos, DirectoryNames *subdirectoryNames) const =0
Retrieve lists of all files and subdirectories in a directory.
virtual ~IVFS()
Definition: vfs.h:78
virtual void Clear()=0
empty the contents of the filesystem.
virtual Status CreateFile(const VfsPath &pathname, const std::shared_ptr< u8 > &fileContents, size_t size)=0
Create a file with the given contents.
virtual Status RemoveFile(const VfsPath &pathname)=0
remove file from the virtual directory listing.
virtual std::wstring TextRepresentation() const =0
virtual Status GetOriginalPath(const VfsPath &filename, OsPath &loadedPathname)=0
Retrieve the POSIX pathname a VFS file was loaded from.
virtual Status GetFilePriority(const VfsPath &pathname, size_t *ppriority) const =0
Retrieve mount priority for a file.
VfsMountFlags
Definition: vfs.h:46
@ VFS_MOUNT_ARCHIVABLE
anything mounted from here should be included when building archives.
Definition: vfs.h:57
@ VFS_MOUNT_KEEP_DELETED
keep the files named "*.DELETED" visible in the VFS directories.
Definition: vfs.h:71
@ VFS_MOUNT_WATCH
all real directories mounted during this operation will be watched for changes.
Definition: vfs.h:52
@ VFS_MOUNT_MUST_EXIST
return ERR::VFS_DIR_NOT_FOUND if the given real path doesn't exist.
Definition: vfs.h:63
PIVFS CreateVfs()
create an instance of a Virtual File System.
Definition: vfs.cpp:280
constexpr size_t VFS_MIN_PRIORITY
Definition: vfs.h:34
constexpr size_t VFS_MAX_PRIORITY
Definition: vfs.h:35
std::shared_ptr< IVFS > PIVFS
Definition: vfs.h:220