Branch data Line data Source code
1 : : #include <errno.h>
2 : : #include "virtualfile.h"
3 : : #include "platform/file-helpers.h"
4 : : #include "warnings.h"
5 : :
6 : : class virtual_file
7 : : {
8 : : public:
9 : 266 : virtual ~virtual_file()
10 : 266 : {
11 : 266 : }
12 : :
13 : : virtual void close() = 0;
14 : :
15 : : virtual size_t read(void* out_buffer, size_t pos, size_t num_bytes) = 0;
16 : :
17 : : virtual size_t get_size() = 0;
18 : : };
19 : :
20 : : class memory_file : public virtual_file
21 : : {
22 : : public:
23 : 0 : memory_file(const void* data, size_t length)
24 : 0 : : m_data(data), m_length(length)
25 : : {
26 : 0 : }
27 : :
28 : 0 : virtual ~memory_file()
29 : 0 : {
30 : 0 : close();
31 : 0 : }
32 : :
33 : 0 : virtual void close()
34 : : {
35 : 0 : }
36 : :
37 : 0 : virtual size_t read(void* out_buffer, size_t pos, size_t num_bytes)
38 : : {
39 [ # # ]: 0 : if(pos > m_length) return 0;
40 : :
41 : 0 : int diff = (int)(pos + num_bytes) - (int)m_length;
42 : 0 : num_bytes -= diff < 0 ? 0 : (unsigned int)diff;
43 : :
44 : 0 : memcpy(out_buffer, (const char*)m_data + pos, num_bytes);
45 : 0 : return num_bytes;
46 : : }
47 : :
48 : 0 : virtual size_t get_size()
49 : : {
50 : 0 : return m_length;
51 : : }
52 : :
53 : : private:
54 : : const void* m_data;
55 : : size_t m_length;
56 : : };
57 : :
58 : : class physical_file : public virtual_file
59 : : {
60 : : public:
61 : 266 : physical_file()
62 : 532 : : m_file_handle(InvalidFileHandle)
63 : : {
64 : 266 : }
65 : :
66 : 1064 : virtual ~physical_file()
67 : 532 : {
68 : 532 : close();
69 : 1064 : }
70 : :
71 : 532 : virtual_file_error open(const string& path)
72 : : {
73 [ + - ]: 532 : if (path != "")
74 : : {
75 : : // randomdude999: checking this before file regularity to improve error messages
76 [ + + + + ]: 532 : if(!file_exists((const char*)path)) return vfe_doesnt_exist;
77 [ + + + + ]: 516 : if(!check_is_regular_file((const char*)path)) return vfe_not_regular_file;
78 : :
79 : 504 : FileOpenError error = FileOpenError_None;
80 : :
81 : 504 : m_file_handle = open_file((const char*)path, FileOpenMode_Read, &error);
82 : :
83 [ - + ]: 504 : if (m_file_handle == InvalidFileHandle)
84 : : {
85 [ # # ]: 0 : if (error == FileOpenError_NotFound)
86 : : {
87 : 0 : return vfe_doesnt_exist;
88 : : }
89 [ # # ]: 0 : else if (error == FileOpenError_AccessDenied)
90 : : {
91 : 0 : return vfe_access_denied;
92 : : }
93 : : else
94 : : {
95 : 0 : return vfe_unknown;
96 : : }
97 : : }
98 : :
99 : 252 : return vfe_none;
100 : : }
101 : :
102 : 0 : return vfe_doesnt_exist;
103 : : }
104 : :
105 : 1036 : virtual void close()
106 : : {
107 [ + + ]: 1036 : if (m_file_handle != InvalidFileHandle)
108 : : {
109 : 504 : close_file(m_file_handle);
110 : 504 : m_file_handle = InvalidFileHandle;
111 : : }
112 : 1036 : }
113 : :
114 : 518 : virtual size_t read(void* out_buffer, size_t pos, size_t num_bytes)
115 : : {
116 : 518 : set_file_pos(m_file_handle, (uint64_t)pos);
117 : 518 : return (size_t)read_file(m_file_handle, out_buffer, (uint32_t)num_bytes);
118 : : }
119 : :
120 : 504 : virtual size_t get_size()
121 : : {
122 : 504 : return (size_t)get_file_size(m_file_handle);
123 : : }
124 : :
125 : : private:
126 : : friend class virtual_filesystem;
127 : :
128 : : FileHandleType m_file_handle;
129 : : };
130 : :
131 : :
132 : :
133 : 230 : void virtual_filesystem::initialize(const char** include_paths, size_t num_include_paths)
134 : : {
135 : 230 : m_include_paths.reset();
136 : :
137 [ + + ]: 690 : for (size_t i = 0; i < num_include_paths; ++i)
138 : : {
139 : 460 : m_include_paths[(int)i] = include_paths[i];
140 : : }
141 : :
142 : 230 : m_last_error = vfe_none;
143 : 230 : m_memory_files.reset();
144 : 230 : }
145 : :
146 : 230 : void virtual_filesystem::destroy()
147 : : {
148 : 230 : m_include_paths.reset();
149 : 230 : }
150 : :
151 : :
152 : 532 : virtual_file_handle virtual_filesystem::open_file(const char* path, const char* base_path)
153 : : {
154 : 532 : m_last_error = vfe_none;
155 : :
156 : 532 : string absolutepath = create_absolute_path(base_path, path);
157 : :
158 : 532 : virtual_file_type vft = get_file_type_from_path(absolutepath);
159 : :
160 [ + + ]: 532 : if (vft != vft_memory_file)
161 : : {
162 : 532 : asar_throw_warning(0, warning_id_check_memory_file, path, (int)warning_id_check_memory_file);
163 : : }
164 : :
165 [ + - - ]: 532 : switch (vft)
166 : : {
167 : 532 : case vft_physical_file:
168 : : {
169 : 532 : physical_file* new_file = new physical_file;
170 : :
171 [ - + ]: 266 : if (new_file == nullptr)
172 : : {
173 : 0 : m_last_error = vfe_unknown;
174 : 0 : return INVALID_VIRTUAL_FILE_HANDLE;
175 : : }
176 : :
177 : 532 : virtual_file_error error = new_file->open(absolutepath);
178 : :
179 [ + + ]: 532 : if (error != vfe_none)
180 : : {
181 : 28 : delete new_file;
182 : 28 : m_last_error = error;
183 : 28 : return INVALID_VIRTUAL_FILE_HANDLE;
184 : : }
185 : :
186 : 252 : return static_cast<virtual_file_handle>(new_file);
187 : : }
188 : :
189 : 0 : case vft_memory_file:
190 : : {
191 [ # # # # ]: 0 : if(m_memory_files.exists(absolutepath)) {
192 : 0 : memory_buffer mem_buf = m_memory_files.find(absolutepath);
193 : 0 : memory_file* new_file = new memory_file(mem_buf.data, mem_buf.length);
194 : 0 : return static_cast<virtual_file_handle>(new_file);
195 : : } else {
196 : 0 : m_last_error = vfe_doesnt_exist;
197 : 0 : return INVALID_VIRTUAL_FILE_HANDLE;
198 : : }
199 : : }
200 : :
201 : 0 : default:
202 : : // We should not get here
203 : 0 : m_last_error = vfe_unknown;
204 : 0 : return INVALID_VIRTUAL_FILE_HANDLE;
205 : : }
206 : 532 : }
207 : :
208 : 504 : void virtual_filesystem::close_file(virtual_file_handle file_handle)
209 : : {
210 [ + - ]: 504 : if (file_handle != INVALID_VIRTUAL_FILE_HANDLE)
211 : : {
212 : 252 : virtual_file* file = static_cast<virtual_file*>(file_handle);
213 : :
214 : 504 : file->close();
215 : :
216 : 504 : delete file;
217 : : }
218 : 504 : }
219 : :
220 : :
221 : :
222 : 518 : size_t virtual_filesystem::read_file(virtual_file_handle file_handle, void* out_buffer, size_t pos, size_t num_bytes)
223 : : {
224 [ + - ]: 518 : if (file_handle != INVALID_VIRTUAL_FILE_HANDLE)
225 : : {
226 : 259 : virtual_file* file = static_cast<virtual_file*>(file_handle);
227 : :
228 : 518 : return file->read(out_buffer, pos, num_bytes);
229 : : }
230 : :
231 : 0 : return 0u;
232 : : }
233 : :
234 : 504 : size_t virtual_filesystem::get_file_size(virtual_file_handle file_handle)
235 : : {
236 [ + - ]: 504 : if (file_handle != INVALID_VIRTUAL_FILE_HANDLE)
237 : : {
238 : 252 : virtual_file* file = static_cast<virtual_file*>(file_handle);
239 : :
240 : 504 : return file->get_size();
241 : : }
242 : :
243 : 0 : return 0u;
244 : : }
245 : :
246 : :
247 : 532 : virtual_filesystem::virtual_file_type virtual_filesystem::get_file_type_from_path(const char* path)
248 : : {
249 [ + + ]: 532 : if(m_memory_files.exists(path)) {
250 : 0 : return vft_memory_file;
251 : : } else {
252 : 532 : return vft_physical_file;
253 : : }
254 : : }
255 : :
256 : 0 : void virtual_filesystem::add_memory_file(const char* name, const void* buffer, size_t length) {
257 : 0 : memory_buffer mem_buf = { buffer, length };
258 : 0 : string normalized_path = normalize_path(name);
259 : 0 : m_memory_files.remove(normalized_path);
260 : 0 : m_memory_files.create(normalized_path) = mem_buf;
261 : 0 : }
262 : :
263 : 3745 : bool virtual_filesystem::is_path_absolute(const char* path)
264 : : {
265 : 3745 : return path_is_absolute(path);
266 : : }
267 : :
268 : 5279 : string virtual_filesystem::create_absolute_path(const char* base, const char* target)
269 : : {
270 [ + + + + : 5279 : if (is_path_absolute(target) || base == nullptr || base[0] == '\0')
+ + + + +
+ ]
271 : : {
272 : 1790 : return normalize_path(target);
273 : : }
274 : :
275 : 3489 : string path_to_use = "";
276 : 3489 : string test_path = "";
277 : :
278 : 3489 : test_path = normalize_path(target);
279 : :
280 : : // First check if path is absolute
281 [ + - - + ]: 3489 : if (path_is_absolute(test_path))
282 : : {
283 [ # # # # : 0 : if (m_memory_files.exists(test_path) || file_exists(test_path))
# # # # #
# ]
284 : : {
285 : 0 : path_to_use = test_path;
286 : : }
287 : : }
288 : : else
289 : : {
290 : : // Now check if path exists relative to the base path
291 [ + - ]: 2850 : if (base != nullptr)
292 : : {
293 : 3489 : test_path = create_combined_path(dir(base), target);
294 : : }
295 : :
296 [ + - + - : 3489 : if (test_path != "" && (m_memory_files.exists(test_path) || file_exists(test_path)))
+ - + + +
+ + + ]
297 : : {
298 : 2834 : path_to_use = test_path;
299 : : }
300 : : else
301 : : {
302 : : // Finally check if path exists relative to any include path
303 : 16 : bool found = false;
304 [ + + ]: 90 : for (int i = 0; i < m_include_paths.count; ++i)
305 : : {
306 : 64 : test_path = create_combined_path(m_include_paths[i], target);
307 : :
308 [ + - + - : 64 : if (m_memory_files.exists(test_path) || file_exists(test_path))
+ + + + +
+ ]
309 : : {
310 : 3 : found = true;
311 : 3 : path_to_use = test_path;
312 : 3 : break;
313 : : }
314 : : }
315 : :
316 [ + + ]: 16 : if (!found)
317 : : {
318 : : // Reset our path so that we don't return an empty one
319 : : // (that will do some weird shit and fuck up error messages)
320 : 13 : path_to_use = target;
321 : : }
322 : : }
323 : : }
324 : :
325 : 3489 : return path_to_use;
326 : 3489 : }
|