summaryrefslogtreecommitdiff
path: root/Source/Core/Common/FileUtil.h
blob: cfe6eddffbc63c31a2abe00822a3ccd7cc29da7b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
// Copyright 2008 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include <filesystem>
#include <string>
#include <string_view>
#include <vector>

#include <sys/stat.h>

#include "Common/CommonTypes.h"

#ifdef _WIN32
#include "Common/StringUtil.h"
#endif

#ifdef ANDROID
#include "Common/StringUtil.h"
#include "jni/AndroidCommon/AndroidCommon.h"
#endif

// User directory indices for GetUserPath
enum
{
  D_USER_IDX,
  D_GCUSER_IDX,
  D_WIIROOT_IDX,  // always points to User/Wii or global user-configured directory
  D_TRIUSER_IDX,
  D_SESSION_WIIROOT_IDX,  // may point to minimal temporary directory for determinism
  D_CONFIG_IDX,           // global settings
  D_GAMESETTINGS_IDX,     // user-specified settings which override both the global and the default
                          // settings (per game)
  D_SKYLANDERS_IDX,

  D_MAPS_IDX,
  D_CACHE_IDX,
  D_COVERCACHE_IDX,
  D_REDUMPCACHE_IDX,
  D_SHADERCACHE_IDX,
  D_RETROACHIEVEMENTSCACHE_IDX,
  D_SHADERS_IDX,
  D_STATESAVES_IDX,
  D_SCREENSHOTS_IDX,
  D_HIRESTEXTURES_IDX,
  D_RIIVOLUTION_IDX,
  D_DUMP_IDX,
  D_DUMPFRAMES_IDX,
  D_DUMPOBJECTS_IDX,
  D_DUMPAUDIO_IDX,
  D_DUMPTEXTURES_IDX,
  D_DUMPDSP_IDX,
  D_DUMPSSL_IDX,
  D_DUMPDEBUG_IDX,
  D_DUMPDEBUG_BRANCHWATCH_IDX,
  D_DUMPDEBUG_JITBLOCKS_IDX,
  D_LOAD_IDX,
  D_LOGS_IDX,
  D_THEMES_IDX,
  D_STYLES_IDX,
  D_PIPES_IDX,
  D_MEMORYWATCHER_IDX,
  D_WFSROOT_IDX,
  D_BACKUP_IDX,
  D_RESOURCEPACK_IDX,
  D_DYNAMICINPUT_IDX,
  D_GRAPHICSMOD_IDX,
  D_FIRMWARE_IDX,
  D_GBAUSER_IDX,
  D_GBASAVES_IDX,
  D_WIISDCARDSYNCFOLDER_IDX,
  D_WIISYSCONF_IDX,
  D_GPU_DRIVERS_EXTRACTED,
  D_GPU_DRIVERS_TMP,
  D_GPU_DRIVERS_HOOKS,
  D_GPU_DRIVERS_FILE_REDIRECT,
  D_ASM_ROOT_IDX,
  D_BANNERS_WIIROOT_IDX,
  FIRST_FILE_USER_PATH_IDX,
  F_DOLPHINCONFIG_IDX = FIRST_FILE_USER_PATH_IDX,
  F_GCPADCONFIG_IDX,
  F_WIIPADCONFIG_IDX,
  F_GCKEYBOARDCONFIG_IDX,
  F_GFXCONFIG_IDX,
  F_LOGGERCONFIG_IDX,
  F_MAINLOG_IDX,
  F_MEM1DUMP_IDX,
  F_MEM2DUMP_IDX,
  F_ARAMDUMP_IDX,
  F_FAKEVMEMDUMP_IDX,
  F_GCSRAM_IDX,
  F_MEMORYWATCHERLOCATIONS_IDX,
  F_MEMORYWATCHERSOCKET_IDX,
  F_WIISDCARDIMAGE_IDX,
  F_WIISYSCONF_IDX,
  F_DUALSHOCKUDPCLIENTCONFIG_IDX,
  F_FREELOOKCONFIG_IDX,
  F_GBABIOS_IDX,
  F_RETROACHIEVEMENTSCONFIG_IDX,
  NUM_PATH_INDICES
};

namespace File
{
// FileSystem tree node
struct FSTEntry
{
  bool isDirectory = false;
  u64 size = 0;              // File length, or for directories, recursive count of children
  std::string physicalName;  // Name on disk
  std::string virtualName;   // Name in FST names table
  std::vector<FSTEntry> children;
};

// The functions in this class are functionally identical to the standalone functions
// below, but if you are going to be calling more than one of the functions using the
// same path, creating a single FileInfo object and calling its functions multiple
// times is faster than calling standalone functions multiple times.
class FileInfo final
{
public:
  explicit FileInfo(const std::string& path);
  explicit FileInfo(const char* path);

  // Returns true if the path exists
  bool Exists() const;
  // Returns true if the path exists and is a directory
  bool IsDirectory() const;
  // Returns true if the path exists and is a file
  bool IsFile() const;
  // Returns the size of a file (or returns 0 if the path doesn't refer to a file)
  u64 GetSize() const;

private:
  std::filesystem::file_status m_status;
  std::uintmax_t m_size;
  bool m_exists;
};

// Returns true if the path exists
bool Exists(const std::string& path);

// Returns true if the path exists and is a directory
bool IsDirectory(const std::string& path);

// Returns true if the path exists and is a file
bool IsFile(const std::string& path);

// Returns the size of a file (or returns 0 if the path isn't a file that exists)
u64 GetSize(const std::string& path);

// Overloaded GetSize, accepts FILE*
u64 GetSize(FILE* f);

// Creates a single directory. Returns true if successful or if the path already exists.
bool CreateDir(const std::string& filename);

// Creates directories recursively. Returns true if successful or if the path already exists.
bool CreateDirs(std::string_view filename);

// Creates the full path to the file given in fullPath.
// That is, for path '/a/b/c.bin', creates folders '/a' and '/a/b'.
// Returns true if creation is successful or if the path already exists.
bool CreateFullPath(std::string_view fullPath);

enum class IfAbsentBehavior
{
  ConsoleWarning,
  NoConsoleWarning
};

// Deletes a given filename, return true on success
// Doesn't supports deleting a directory
bool Delete(const std::string& filename,
            IfAbsentBehavior behavior = IfAbsentBehavior::ConsoleWarning);

// Deletes a directory filename, returns true on success
bool DeleteDir(const std::string& filename,
               IfAbsentBehavior behavior = IfAbsentBehavior::ConsoleWarning);

// renames file srcFilename to destFilename, returns true on success
bool Rename(const std::string& srcFilename, const std::string& destFilename);

// ditto, but syncs the source file and, on Unix, syncs the directories after rename
bool RenameSync(const std::string& srcFilename, const std::string& destFilename);

// Copies a file at source_path to destination_path, as if by std::filesystem::copy_file().
// If a file already exists at destination_path it is overwritten. Returns true on success.
bool CopyRegularFile(std::string_view source_path, std::string_view destination_path);

// creates an empty file filename, returns true on success
bool CreateEmptyFile(const std::string& filename);

// Recursive or non-recursive list of files and directories under directory.
FSTEntry ScanDirectoryTree(std::string directory, bool recursive);

// deletes the given directory and anything under it. Returns true on success.
bool DeleteDirRecursively(const std::string& directory);

// Returns the current directory
std::string GetCurrentDir();

// Copies source_path to dest_path, as if by std::filesystem::copy(). Returns true on success or if
// the source and destination are already the same (as determined by std::filesystem::equivalent()).
bool Copy(std::string_view source_path, std::string_view dest_path,
          bool overwrite_existing = false);

// Moves source_path to dest_path. On success, the source_path will no longer exist, and the
// dest_path will contain the data previously in source_path. Files in dest_path will be overwritten
// if they match files in source_path, but files that only exist in dest_path will be kept. No
// guarantee on the state is given on failure; the move may have completely failed or partially
// completed.
bool MoveWithOverwrite(std::string_view source_path, std::string_view dest_path);

// Set the current directory to given directory
bool SetCurrentDir(const std::string& directory);

// Creates and returns the path to a new temporary directory.
std::string CreateTempDir();

// Get a filename that can hopefully be atomically renamed to the given path.
std::string GetTempFilenameForAtomicWrite(std::string path);

// Gets a set user directory path
// Don't call prior to setting the base user directory
const std::string& GetUserPath(unsigned int dir_index);

// Sets a user directory path
// Rebuilds internal directory structure to compensate for the new directory
void SetUserPath(unsigned int dir_index, std::string path);

// probably doesn't belong here
std::string GetThemeDir(const std::string& theme_name);

// Returns the path to where the sys file are
const std::string& GetSysDirectory();

#ifdef ANDROID
void SetSysDirectory(const std::string& path);
void SetGpuDriverDirectories(const std::string& path, const std::string& lib_path);
const std::string GetGpuDriverDirectory(unsigned int dir_index);
#endif

#ifdef __APPLE__
std::string GetBundleDirectory();
#endif

std::string GetExePath();
std::string GetExeDirectory();

bool WriteStringToFile(const std::string& filename, std::string_view str);
bool ReadFileToString(const std::string& filename, std::string& str);

// To deal with Windows not fully supporting UTF-8 and Android not fully supporting paths.
template <typename T>
void OpenFStream(T& fstream, const std::string& filename, std::ios_base::openmode openmode)
{
#ifdef _WIN32
  fstream.open(UTF8ToTStr(filename).c_str(), openmode);
#else
#ifdef ANDROID
  // Unfortunately it seems like the non-standard __open is the only way to use a file descriptor
  if (IsPathAndroidContent(filename))
    fstream.__open(OpenAndroidContent(filename, OpenModeToAndroid(openmode)), openmode);
  else
#endif
    fstream.open(filename.c_str(), openmode);
#endif
}

}  // namespace File