Pyrogenesis  trunk
vfs.h
Go to the documentation of this file.
1 /* Copyright (c) 2013 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 namespace ERR
35 {
36  const Status VFS_DIR_NOT_FOUND = -110100;
37  const Status VFS_FILE_NOT_FOUND = -110101;
38  const Status VFS_ALREADY_MOUNTED = -110102;
39 }
40 
41 // (recursive mounting and mounting archives are no longer optional since they don't hurt)
43 {
44  /**
45  * all real directories mounted during this operation will be watched
46  * for changes. this flag is provided to avoid watches in output-only
47  * directories, e.g. screenshots/ (only causes unnecessary overhead).
48  **/
50 
51  /**
52  * anything mounted from here should be included when building archives.
53  **/
55 
56  /**
57  * return ERR::VFS_DIR_NOT_FOUND if the given real path doesn't exist.
58  * (the default behavior is to create all real directories in the path)
59  **/
61 
62  /**
63  * keep the files named "*.DELETED" visible in the VFS directories.
64  * the standard behavior of hiding the file with the same name minus the
65  * ".DELETED" suffix will still apply.
66  * (the default behavior is to hide both the suffixed and unsuffixed files)
67  **/
69 
70  /**
71  * mark a directory replaceable, so that when writing a file to this path
72  * new real directories will be created instead of reusing already existing
73  * ones mounted at a subpath of the VFS path.
74  * (the default behaviour is to write to the real directory associated
75  * with the VFS directory that was last mounted to this path (or subpath))
76  **/
78 };
79 
80 // (member functions are thread-safe after the instance has been
81 // constructed - each acquires a pthread mutex.)
82 struct IVFS
83 {
84  virtual ~IVFS() {}
85 
86  /**
87  * mount a directory into the VFS.
88  *
89  * @param mountPoint (will be created if it does not already exist)
90  * @param path real directory path
91  * @param flags
92  * @param priority
93  * @return Status.
94  *
95  * if files are encountered that already exist in the VFS (sub)directories,
96  * the most recent / highest priority/precedence version is preferred.
97  *
98  * if files with archive extensions are seen, their contents are added
99  * as well.
100  **/
101  virtual Status Mount(const VfsPath& mountPoint, const OsPath& path, size_t flags = 0, size_t priority = 0) = 0;
102 
103  /**
104  * Retrieve information about a file (similar to POSIX stat).
105  *
106  * @param pathname
107  * @param pfileInfo receives information about the file. Passing NULL
108  * suppresses warnings if the file doesn't exist.
109  *
110  * @return Status.
111  **/
112  virtual Status GetFileInfo(const VfsPath& pathname, CFileInfo* pfileInfo) const = 0;
113 
114  /**
115  * Retrieve mount priority for a file.
116  *
117  * @param pathname
118  * @param ppriority receives priority value, if the file can be found.
119  *
120  * @return Status.
121  **/
122  virtual Status GetFilePriority(const VfsPath& pathname, size_t* ppriority) const = 0;
123 
124  /**
125  * Retrieve lists of all files and subdirectories in a directory.
126  *
127  * @return Status.
128  *
129  * Rationale:
130  * - this interface avoids having to lock the directory while an
131  * iterator is extant.
132  * - we cannot efficiently provide routines for returning files and
133  * subdirectories separately due to the underlying POSIX interface.
134  **/
135  virtual Status GetDirectoryEntries(const VfsPath& path, CFileInfos* fileInfos, DirectoryNames* subdirectoryNames) const = 0;
136 
137  /**
138  * Create a file with the given contents.
139  * @param pathname
140  * @param fileContents
141  * @param size [bytes] of the contents, will match that of the file.
142  * @return Status.
143  *
144  * rationale: disallowing partial writes simplifies file cache coherency
145  * (we need only invalidate cached data when closing a newly written file).
146  **/
147  virtual Status CreateFile(const VfsPath& pathname, const shared_ptr<u8>& fileContents, size_t size) = 0;
148 
149  /**
150  * Replace a file with the given contents.
151  *
152  * @see CreateFile
153  *
154  * Used to replace a file if it is already present (even if the file is not
155  * in the attached vfs directory). Calls CreateFile if the file doesn't yet
156  * exist.
157  **/
158  virtual Status ReplaceFile(const VfsPath& pathname, const shared_ptr<u8>& fileContents, size_t size) = 0;
159 
160  /**
161  * Read an entire file into memory.
162  *
163  * @param pathname
164  * @param fileContents receives a smart pointer to the contents.
165  * CAVEAT: this will be taken from the file cache if the VFS was
166  * created with cacheSize != 0 and size < cacheSize. There is no
167  * provision for Copy-on-Write, which means that such buffers
168  * must not be modified (this is enforced via mprotect).
169  * @param size receives the size [bytes] of the file contents.
170  * @return Status.
171  **/
172  virtual Status LoadFile(const VfsPath& pathname, shared_ptr<u8>& fileContents, size_t& size) = 0;
173 
174  /**
175  * @return a string representation of all files and directories.
176  **/
177  virtual std::wstring TextRepresentation() const = 0;
178 
179  /**
180  * retrieve the real (POSIX) pathname underlying a VFS file.
181  *
182  * this is useful for passing paths to external libraries.
183  **/
184  virtual Status GetRealPath(const VfsPath& pathname, OsPath& realPathname) = 0;
185 
186  /**
187  * retrieve the real (POSIX) pathname underlying a VFS directory.
188  *
189  * this is useful for passing paths to external libraries.
190  **/
191  virtual Status GetDirectoryRealPath(const VfsPath& pathname, OsPath& realPathname) = 0;
192 
193  /**
194  * retrieve the VFS pathname that corresponds to a real file.
195  *
196  * this is useful for reacting to file change notifications.
197  *
198  * the current implementation requires time proportional to the
199  * number of directories; this could be accelerated by only checking
200  * directories below a mount point with a matching real path.
201  **/
202  virtual Status GetVirtualPath(const OsPath& realPathname, VfsPath& pathname) = 0;
203 
204  /**
205  * remove file from the virtual directory listing and evict its
206  * data from the cache.
207  **/
208  virtual Status RemoveFile(const VfsPath& pathname) = 0;
209 
210  /**
211  * request the directory be re-populated when it is next accessed.
212  * useful for synchronizing with the underlying filesystem after
213  * files have been created or their metadata changed.
214  **/
215  virtual Status RepopulateDirectory(const VfsPath& path) = 0;
216 
217  /**
218  * empty the contents of the filesystem.
219  * this is typically only necessary when changing the set of
220  * mounted directories, e.g. when switching mods.
221  * NB: open files are not affected.
222  **/
223  virtual void Clear() = 0;
224 };
225 
226 typedef shared_ptr<IVFS> PIVFS;
227 
228 /**
229  * create an instance of a Virtual File System.
230  *
231  * @param cacheSize size [bytes] of memory to reserve for a file cache,
232  * or zero to disable it. if small enough to fit, file contents are
233  * stored here until no references remain and they are evicted.
234  *
235  * note: there is no limitation to a single instance, it may make sense
236  * to create and destroy VFS instances during each unit test.
237  **/
238 LIB_API PIVFS CreateVfs(size_t cacheSize);
239 
240 #endif // #ifndef INCLUDED_VFS
const Status VFS_ALREADY_MOUNTED
Definition: vfs.h:38
const Status VFS_DIR_NOT_FOUND
Definition: vfs.h:36
shared_ptr< IVFS > PIVFS
Definition: vfs.h:226
VfsMountFlags
Definition: vfs.h:42
Status GetDirectoryEntries(const OsPath &path, CFileInfos *files, DirectoryNames *subdirectoryNames)
Definition: file_system.cpp:87
return ERR::VFS_DIR_NOT_FOUND if the given real path doesn&#39;t exist.
Definition: vfs.h:60
Definition: path.h:77
LIB_API PIVFS CreateVfs(size_t cacheSize)
create an instance of a Virtual File System.
Definition: vfs.cpp:323
keep the files named "*.DELETED" visible in the VFS directories.
Definition: vfs.h:68
const Status VFS_FILE_NOT_FOUND
Definition: vfs.h:37
anything mounted from here should be included when building archives.
Definition: vfs.h:54
all real directories mounted during this operation will be watched for changes.
Definition: vfs.h:49
i64 Status
Error handling system.
Definition: status.h:171
Introduction
Definition: debug.h:404
std::vector< OsPath > DirectoryNames
Definition: file_system.h:77
Definition: vfs.h:82
std::vector< CFileInfo > CFileInfos
Definition: file_system.h:76
Definition: file_system.h:41
Status GetFileInfo(const OsPath &pathname, CFileInfo *pPtrInfo)
Definition: file_system.cpp:65
virtual ~IVFS()
Definition: vfs.h:84
mark a directory replaceable, so that when writing a file to this path new real directories will be c...
Definition: vfs.h:77