1 // Copyright (C) 2003 Dolphin Project.
2
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, version 2.0 or later versions.
6
7 // This program is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 // GNU General Public License 2.0 for more details.
11
12 // A copy of the GPL 2.0 should have been included with the program.
13 // If not, see http://www.gnu.org/licenses/
14
15 // Official SVN repository and contact information can be found at
16 // http://code.google.com/p/dolphin-emu/
17
18 #pragma once
19
20 #include <fstream>
21 #include <cstdio>
22 #include <string>
23 #include <vector>
24 #include <time.h>
25 #include <cstdint>
26
27 #include "Common/Common.h"
28 #include "Common/File/Path.h"
29
30 // Some functions here support Android content URIs. These are marked as such.
31
32 #ifdef _MSC_VER
localtime_r(const time_t * clock,struct tm * result)33 inline struct tm* localtime_r(const time_t *clock, struct tm *result) {
34 if (localtime_s(result, clock) == 0)
35 return result;
36 return NULL;
37 }
38 #endif
39
40 namespace File {
41
42 // Mostly to handle UTF-8 filenames better on Windows.
43 FILE *OpenCFile(const Path &filename, const char *mode);
44
45 // Reminiscent of PSP's FileAccess enum, due to its use in emulating it.
46 enum OpenFlag {
47 OPEN_NONE = 0,
48 OPEN_READ = 1,
49 OPEN_WRITE = 2,
50 OPEN_APPEND = 4,
51 OPEN_CREATE = 8,
52 OPEN_TRUNCATE = 16,
53 // EXCL?
54 };
55
56 // TODO: This currently only handles Android Content URIs, but might port the rest
57 // of DirectoryFileSystem::Open here eventually for symmetry.
58 int OpenFD(const Path &filename, OpenFlag flags);
59
60 // Resolves symlinks and similar.
61 std::string ResolvePath(const std::string &path);
62
63 // Returns true if file filename exists
64 bool Exists(const Path &path);
65
66 // Returns true if file filename exists in directory path.
67 bool ExistsInDir(const Path &path, const std::string &filename);
68
69 // Returns true if filename exists, and is a directory
70 // Supports Android content URIs.
71 bool IsDirectory(const Path &filename);
72
73 // Returns struct with modification date of file
74 bool GetModifTime(const Path &filename, tm &return_time);
75
76 // Returns the size of filename (64bit)
77 uint64_t GetFileSize(const Path &filename);
78
79 // Overloaded GetSize, accepts FILE*
80 uint64_t GetFileSize(FILE *f);
81
82 // Computes the recursive size of a directory. Warning: Might be slow!
83 uint64_t ComputeRecursiveDirectorySize(const Path &path);
84
85 // Returns true if successful, or path already exists.
86 bool CreateDir(const Path &filename);
87
88 // Creates the full path of fullPath returns true on success
89 bool CreateFullPath(const Path &fullPath);
90
91 // Deletes a given filename, return true on success
92 // Doesn't supports deleting a directory
93 bool Delete(const Path &filename);
94
95 // Deletes a directory filename, returns true on success
96 // Directory must be empty.
97 bool DeleteDir(const Path &filename);
98
99 // Deletes the given directory and anything under it. Returns true on success.
100 bool DeleteDirRecursively(const Path &directory);
101
102 // Renames file srcFilename to destFilename, returns true on success
103 // Will usually only work with in the same partition or other unit of storage,
104 // so you might have to fall back to copy/delete.
105 bool Rename(const Path &srcFilename, const Path &destFilename);
106
107 // copies file srcFilename to destFilename, returns true on success
108 bool Copy(const Path &srcFilename, const Path &destFilename);
109
110 // Tries to rename srcFilename to destFilename, if that fails,
111 // it tries to copy and delete the src if succeeded. If that fails too,
112 // returns false, otherwise returns true.
113 bool Move(const Path &srcFilename, const Path &destFilename);
114
115 // Move file, but only if it can be done quickly (rename or similar).
116 bool MoveIfFast(const Path &srcFilename, const Path &destFilename);
117
118 // creates an empty file filename, returns true on success
119 bool CreateEmptyFile(const Path &filename);
120
121 // Opens ini file (cheats, texture replacements etc.)
122 // TODO: Belongs in System or something.
123 bool OpenFileInEditor(const Path &fileName);
124
125 // TODO: Belongs in System or something.
126 const Path &GetExeDirectory();
127
128 // simple wrapper for cstdlib file functions to
129 // hopefully will make error checking easier
130 // and make forgetting an fclose() harder
131 class IOFile {
132 public:
IOFile()133 IOFile() {}
134 IOFile(const Path &filename, const char openmode[]);
135 ~IOFile();
136
137 // Prevent copies.
138 IOFile(const IOFile &) = delete;
139 void operator=(const IOFile &) = delete;
140
141 bool Open(const Path &filename, const char openmode[]);
142 bool Close();
143
144 template <typename T>
ReadArray(T * data,size_t length)145 bool ReadArray(T* data, size_t length)
146 {
147 if (!IsOpen() || length != std::fread(data, sizeof(T), length, m_file))
148 m_good = false;
149
150 return m_good;
151 }
152
153 template <typename T>
WriteArray(const T * data,size_t length)154 bool WriteArray(const T* data, size_t length)
155 {
156 if (!IsOpen() || length != std::fwrite(data, sizeof(T), length, m_file))
157 m_good = false;
158
159 return m_good;
160 }
161
ReadBytes(void * data,size_t length)162 bool ReadBytes(void* data, size_t length)
163 {
164 return ReadArray(reinterpret_cast<char*>(data), length);
165 }
166
WriteBytes(const void * data,size_t length)167 bool WriteBytes(const void* data, size_t length)
168 {
169 return WriteArray(reinterpret_cast<const char*>(data), length);
170 }
171
IsOpen()172 bool IsOpen() const { return nullptr != m_file; }
173
174 // m_good is set to false when a read, write or other function fails
IsGood()175 bool IsGood() const { return m_good; }
176 operator bool() const { return IsGood() && IsOpen(); }
177
178 std::FILE* ReleaseHandle();
179
GetHandle()180 std::FILE* GetHandle() { return m_file; }
181
182 void SetHandle(std::FILE* file);
183
184 bool Seek(int64_t off, int origin);
185 uint64_t Tell();
186 uint64_t GetSize();
187 bool Resize(uint64_t size);
188 bool Flush();
189
190 // clear error state
Clear()191 void Clear() {
192 m_good = true;
193 #undef clearerr
194 std::clearerr(m_file);
195 }
196
197 private:
198 std::FILE *m_file = nullptr;
199 bool m_good = true;
200 };
201
202 // TODO: Refactor, this was moved from the old file_util.cpp.
203
204 // Whole-file reading/writing
205 bool WriteStringToFile(bool text_file, const std::string &str, const Path &filename);
206 bool WriteDataToFile(bool text_file, const void* data, const unsigned int size, const Path &filename);
207
208 bool ReadFileToString(bool text_file, const Path &filename, std::string &str);
209 // Return value must be delete[]-d.
210 uint8_t *ReadLocalFile(const Path &filename, size_t *size);
211
212 } // namespace
213