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