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
32 #include "lib/file/vfs/vfs_path.h"
33 
34 constexpr size_t VFS_MIN_PRIORITY = 0;
35 constexpr size_t VFS_MAX_PRIORITY = std::numeric_limits<size_t>::max();
36 
37 namespace 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.)
76 struct 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 
220 typedef 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  **/
228 PIVFS CreateVfs();
229 
230 #endif // #ifndef INCLUDED_VFS
const Status VFS_ALREADY_MOUNTED
Definition: vfs.h:41
const Status VFS_DIR_NOT_FOUND
Definition: vfs.h:39
VfsMountFlags
Definition: vfs.h:45
Status GetDirectoryEntries(const OsPath &path, CFileInfos *files, DirectoryNames *subdirectoryNames)
Definition: file_system.cpp:86
std::shared_ptr< IVFS > PIVFS
Definition: vfs.h:220
return ERR::VFS_DIR_NOT_FOUND if the given real path doesn&#39;t exist.
Definition: vfs.h:63
Definition: path.h:79
keep the files named "*.DELETED" visible in the VFS directories.
Definition: vfs.h:71
const Status VFS_FILE_NOT_FOUND
Definition: vfs.h:40
anything mounted from here should be included when building archives.
Definition: vfs.h:57
all real directories mounted during this operation will be watched for changes.
Definition: vfs.h:52
i64 Status
Error handling system.
Definition: status.h:169
Introduction
Definition: debug.h:407
constexpr size_t VFS_MAX_PRIORITY
Definition: vfs.h:35
std::vector< OsPath > DirectoryNames
Definition: file_system.h:78
PIVFS CreateVfs()
create an instance of a Virtual File System.
Definition: vfs.cpp:280
Definition: vfs.h:76
std::vector< CFileInfo > CFileInfos
Definition: file_system.h:77
Definition: file_system.h:42
constexpr size_t VFS_MIN_PRIORITY
Definition: vfs.h:34
Status GetFileInfo(const OsPath &pathname, CFileInfo *pPtrInfo)
Definition: file_system.cpp:64
virtual ~IVFS()
Definition: vfs.h:78