duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

file_system.h (7607B)


      1 // SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
      2 // SPDX-License-Identifier: (GPL-3.0 OR PolyForm-Strict-1.0.0)
      3 
      4 #pragma once
      5 
      6 #include "heap_array.h"
      7 #include "types.h"
      8 
      9 #include <cstdio>
     10 #include <ctime>
     11 #include <memory>
     12 #include <optional>
     13 #include <string>
     14 #include <sys/stat.h>
     15 #include <vector>
     16 
     17 class Error;
     18 
     19 #ifdef _WIN32
     20 #define FS_OSPATH_SEPARATOR_CHARACTER '\\'
     21 #define FS_OSPATH_SEPARATOR_STR "\\"
     22 #else
     23 #define FS_OSPATH_SEPARATOR_CHARACTER '/'
     24 #define FS_OSPATH_SEPARATOR_STR "/"
     25 #endif
     26 
     27 enum FILESYSTEM_FILE_ATTRIBUTES
     28 {
     29   FILESYSTEM_FILE_ATTRIBUTE_DIRECTORY = (1 << 0),
     30   FILESYSTEM_FILE_ATTRIBUTE_READ_ONLY = (1 << 1),
     31   FILESYSTEM_FILE_ATTRIBUTE_COMPRESSED = (1 << 2),
     32   FILESYSTEM_FILE_ATTRIBUTE_LINK = (1 << 3),
     33 };
     34 
     35 enum FILESYSTEM_FIND_FLAGS
     36 {
     37   FILESYSTEM_FIND_RECURSIVE = (1 << 0),
     38   FILESYSTEM_FIND_RELATIVE_PATHS = (1 << 1),
     39   FILESYSTEM_FIND_HIDDEN_FILES = (1 << 2),
     40   FILESYSTEM_FIND_FOLDERS = (1 << 3),
     41   FILESYSTEM_FIND_FILES = (1 << 4),
     42   FILESYSTEM_FIND_KEEP_ARRAY = (1 << 5),
     43   FILESYSTEM_FIND_SORT_BY_NAME = (1 << 6),
     44 };
     45 
     46 struct FILESYSTEM_STAT_DATA
     47 {
     48   std::time_t CreationTime; // actually inode change time on linux
     49   std::time_t ModificationTime;
     50   s64 Size;
     51   u32 Attributes;
     52 };
     53 
     54 struct FILESYSTEM_FIND_DATA
     55 {
     56   std::time_t CreationTime; // actually inode change time on linux
     57   std::time_t ModificationTime;
     58   std::string FileName;
     59   s64 Size;
     60   u32 Attributes;
     61 };
     62 
     63 namespace FileSystem {
     64 using FindResultsArray = std::vector<FILESYSTEM_FIND_DATA>;
     65 
     66 /// Returns the display name of a filename. Usually this is the same as the path.
     67 std::string GetDisplayNameFromPath(std::string_view path);
     68 
     69 /// Returns a list of "root directories" (i.e. root/home directories on Linux, drive letters on Windows).
     70 std::vector<std::string> GetRootDirectoryList();
     71 
     72 /// Search for files
     73 bool FindFiles(const char* path, const char* pattern, u32 flags, FindResultsArray* results);
     74 
     75 /// Stat file
     76 bool StatFile(const char* path, struct stat* st);
     77 bool StatFile(std::FILE* fp, struct stat* st);
     78 bool StatFile(const char* path, FILESYSTEM_STAT_DATA* pStatData);
     79 bool StatFile(std::FILE* fp, FILESYSTEM_STAT_DATA* pStatData);
     80 s64 GetPathFileSize(const char* path);
     81 
     82 /// File exists?
     83 bool FileExists(const char* path);
     84 
     85 /// Directory exists?
     86 bool DirectoryExists(const char* path);
     87 bool IsRealDirectory(const char* path);
     88 
     89 /// Directory does not contain any files?
     90 bool IsDirectoryEmpty(const char* path);
     91 
     92 /// Delete file
     93 bool DeleteFile(const char* path, Error* error = nullptr);
     94 
     95 /// Rename file
     96 bool RenamePath(const char* OldPath, const char* NewPath, Error* error = nullptr);
     97 
     98 /// Deleter functor for managed file pointers
     99 struct FileDeleter
    100 {
    101   ALWAYS_INLINE void operator()(std::FILE* fp)
    102   {
    103     if (fp)
    104       std::fclose(fp);
    105   }
    106 };
    107 
    108 /// open files
    109 using ManagedCFilePtr = std::unique_ptr<std::FILE, FileDeleter>;
    110 ManagedCFilePtr OpenManagedCFile(const char* filename, const char* mode, Error* error = nullptr);
    111 std::FILE* OpenCFile(const char* filename, const char* mode, Error* error = nullptr);
    112 
    113 /// Atomically opens a file in read/write mode, and if the file does not exist, creates it.
    114 /// On Windows, if retry_ms is positive, this function will retry opening the file for this
    115 /// number of milliseconds. NOTE: The file is opened in binary mode.
    116 std::FILE* OpenExistingOrCreateCFile(const char* filename, s32 retry_ms = -1, Error* error = nullptr);
    117 ManagedCFilePtr OpenExistingOrCreateManagedCFile(const char* filename, s32 retry_ms = -1, Error* error = nullptr);
    118 
    119 int FSeek64(std::FILE* fp, s64 offset, int whence);
    120 bool FSeek64(std::FILE* fp, s64 offset, int whence, Error* error);
    121 s64 FTell64(std::FILE* fp);
    122 s64 FSize64(std::FILE* fp, Error* error = nullptr);
    123 bool FTruncate64(std::FILE* fp, s64 size, Error* error = nullptr);
    124 
    125 int OpenFDFile(const char* filename, int flags, int mode, Error* error = nullptr);
    126 
    127 /// Sharing modes for OpenSharedCFile().
    128 enum class FileShareMode
    129 {
    130   DenyReadWrite, /// Exclusive access.
    131   DenyWrite,     /// Other processes can read from this file.
    132   DenyRead,      /// Other processes can write to this file.
    133   DenyNone,      /// Other processes can read and write to this file.
    134 };
    135 
    136 /// Opens a file in shareable mode (where other processes can access it concurrently).
    137 /// Only has an effect on Windows systems.
    138 ManagedCFilePtr OpenManagedSharedCFile(const char* filename, const char* mode, FileShareMode share_mode,
    139                                        Error* error = nullptr);
    140 std::FILE* OpenSharedCFile(const char* filename, const char* mode, FileShareMode share_mode, Error* error = nullptr);
    141 
    142 /// Atomically-updated file creation.
    143 class AtomicRenamedFileDeleter
    144 {
    145 public:
    146   AtomicRenamedFileDeleter(std::string temp_filename, std::string final_filename);
    147   ~AtomicRenamedFileDeleter();
    148 
    149   void operator()(std::FILE* fp);
    150   void discard();
    151 
    152 private:
    153   std::string m_temp_filename;
    154   std::string m_final_filename;
    155 };
    156 using AtomicRenamedFile = std::unique_ptr<std::FILE, AtomicRenamedFileDeleter>;
    157 AtomicRenamedFile CreateAtomicRenamedFile(std::string filename, const char* mode, Error* error = nullptr);
    158 bool WriteAtomicRenamedFile(std::string filename, const void* data, size_t data_length, Error* error = nullptr);
    159 void DiscardAtomicRenamedFile(AtomicRenamedFile& file);
    160 
    161 /// Abstracts a POSIX file lock.
    162 #ifndef _WIN32
    163 class POSIXLock
    164 {
    165 public:
    166   POSIXLock(int fd);
    167   POSIXLock(std::FILE* fp);
    168   ~POSIXLock();
    169 
    170 private:
    171   int m_fd;
    172 };
    173 #endif
    174 
    175 std::optional<DynamicHeapArray<u8>> ReadBinaryFile(const char* filename, Error* error = nullptr);
    176 std::optional<DynamicHeapArray<u8>> ReadBinaryFile(std::FILE* fp, Error* error = nullptr);
    177 std::optional<std::string> ReadFileToString(const char* filename, Error* error = nullptr);
    178 std::optional<std::string> ReadFileToString(std::FILE* fp, Error* error = nullptr);
    179 bool WriteBinaryFile(const char* filename, const void* data, size_t data_length, Error* error = nullptr);
    180 bool WriteStringToFile(const char* filename, std::string_view sv, Error* error = nullptr);
    181 
    182 /// creates a directory in the local filesystem
    183 /// if the directory already exists, the return value will be true.
    184 /// if Recursive is specified, all parent directories will be created
    185 /// if they do not exist.
    186 bool CreateDirectory(const char* path, bool recursive, Error* error = nullptr);
    187 
    188 /// Creates a directory if it doesn't already exist.
    189 /// Returns false if it does not exist and creation failed.
    190 bool EnsureDirectoryExists(const char* path, bool recursive, Error* error = nullptr);
    191 
    192 /// Removes a directory.
    193 bool DeleteDirectory(const char* path);
    194 
    195 /// Recursively removes a directory and all subdirectories/files.
    196 bool RecursiveDeleteDirectory(const char* path);
    197 
    198 /// Copies one file to another, optionally replacing it if it already exists.
    199 bool CopyFilePath(const char* source, const char* destination, bool replace);
    200 
    201 /// Returns the path to the current executable.
    202 std::string GetProgramPath();
    203 
    204 /// Retrieves the current working directory.
    205 std::string GetWorkingDirectory();
    206 
    207 /// Sets the current working directory. Returns true if successful.
    208 bool SetWorkingDirectory(const char* path);
    209 
    210 /// Enables/disables NTFS compression on a file or directory.
    211 /// Does not apply the compression flag recursively if called for a directory.
    212 /// Does nothing and returns false on non-Windows platforms.
    213 bool SetPathCompression(const char* path, bool enable);
    214 
    215 #ifdef _WIN32
    216 // Path limit remover, but also converts to a wide string at the same time.
    217 bool GetWin32Path(std::wstring* dest, std::string_view str);
    218 std::wstring GetWin32Path(std::string_view str);
    219 #endif
    220 }; // namespace FileSystem