LCOV - code coverage report
Current view: top level - source/lib/file/vfs - vfs.h (source / functions) Hit Total Coverage
Test: 0 A.D. test coverage report Lines: 2 2 100.0 %
Date: 2023-01-19 00:18:29 Functions: 2 3 66.7 %

          Line data    Source code
       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)
      45             : enum VfsMountFlags
      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             :      **/
      52             :     VFS_MOUNT_WATCH = 1,
      53             : 
      54             :     /**
      55             :      * anything mounted from here should be included when building archives.
      56             :      **/
      57             :     VFS_MOUNT_ARCHIVABLE = 2,
      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             :      **/
      63             :     VFS_MOUNT_MUST_EXIST = 4,
      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             :      **/
      71             :     VFS_MOUNT_KEEP_DELETED = 8
      72             : };
      73             : 
      74             : // (member functions are thread-safe after the instance has been
      75             : // constructed - each acquires a mutex.)
      76          83 : struct IVFS
      77             : {
      78          83 :     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

Generated by: LCOV version 1.13