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