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