| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*  dir_access.cpp                                                       */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*                       This file is part of:                           */ | 
					
						
							|  |  |  | /*                           GODOT ENGINE                                */ | 
					
						
							| 
									
										
										
										
											2017-08-27 14:16:55 +02:00
										 |  |  | /*                      https://godotengine.org                          */ | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | /*************************************************************************/ | 
					
						
							| 
									
										
										
										
											2020-01-01 11:16:22 +01:00
										 |  |  | /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */ | 
					
						
							|  |  |  | /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */ | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* Permission is hereby granted, free of charge, to any person obtaining */ | 
					
						
							|  |  |  | /* a copy of this software and associated documentation files (the       */ | 
					
						
							|  |  |  | /* "Software"), to deal in the Software without restriction, including   */ | 
					
						
							|  |  |  | /* without limitation the rights to use, copy, modify, merge, publish,   */ | 
					
						
							|  |  |  | /* distribute, sublicense, and/or sell copies of the Software, and to    */ | 
					
						
							|  |  |  | /* permit persons to whom the Software is furnished to do so, subject to */ | 
					
						
							|  |  |  | /* the following conditions:                                             */ | 
					
						
							|  |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* The above copyright notice and this permission notice shall be        */ | 
					
						
							|  |  |  | /* included in all copies or substantial portions of the Software.       */ | 
					
						
							|  |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */ | 
					
						
							|  |  |  | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */ | 
					
						
							|  |  |  | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ | 
					
						
							|  |  |  | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */ | 
					
						
							|  |  |  | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */ | 
					
						
							|  |  |  | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */ | 
					
						
							|  |  |  | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							| 
									
										
										
										
											2018-01-05 00:50:27 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | #include "dir_access.h"
 | 
					
						
							| 
									
										
										
										
											2018-09-11 18:13:45 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-07 19:33:38 -03:00
										 |  |  | #include "core/config/project_settings.h"
 | 
					
						
							| 
									
										
										
										
											2018-09-11 18:13:45 +02:00
										 |  |  | #include "core/os/file_access.h"
 | 
					
						
							|  |  |  | #include "core/os/memory.h"
 | 
					
						
							|  |  |  | #include "core/os/os.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | String DirAccess::_get_root_path() const { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	switch (_access_type) { | 
					
						
							| 
									
										
										
										
											2020-05-10 13:00:47 +02:00
										 |  |  | 		case ACCESS_RESOURCES: | 
					
						
							|  |  |  | 			return ProjectSettings::get_singleton()->get_resource_path(); | 
					
						
							|  |  |  | 		case ACCESS_USERDATA: | 
					
						
							|  |  |  | 			return OS::get_singleton()->get_user_data_dir(); | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			return ""; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-05-14 14:29:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | String DirAccess::_get_root_string() const { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	switch (_access_type) { | 
					
						
							| 
									
										
										
										
											2020-05-10 13:00:47 +02:00
										 |  |  | 		case ACCESS_RESOURCES: | 
					
						
							|  |  |  | 			return "res://"; | 
					
						
							|  |  |  | 		case ACCESS_USERDATA: | 
					
						
							|  |  |  | 			return "user://"; | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			return ""; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-19 21:36:35 -03:00
										 |  |  | int DirAccess::get_current_drive() { | 
					
						
							|  |  |  | 	String path = get_current_dir().to_lower(); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	for (int i = 0; i < get_drive_count(); i++) { | 
					
						
							| 
									
										
										
										
											2015-05-19 21:36:35 -03:00
										 |  |  | 		String d = get_drive(i).to_lower(); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		if (path.begins_with(d)) { | 
					
						
							| 
									
										
										
										
											2015-05-19 21:36:35 -03:00
										 |  |  | 			return i; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-05-19 21:36:35 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-10 09:19:29 +01:00
										 |  |  | bool DirAccess::drives_are_shortcuts() { | 
					
						
							|  |  |  | 	return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | static Error _erase_recursive(DirAccess *da) { | 
					
						
							|  |  |  | 	List<String> dirs; | 
					
						
							|  |  |  | 	List<String> files; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	da->list_dir_begin(); | 
					
						
							|  |  |  | 	String n = da->get_next(); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	while (n != String()) { | 
					
						
							|  |  |  | 		if (n != "." && n != "..") { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 			if (da->current_is_dir()) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				dirs.push_back(n); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 			} else { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				files.push_back(n); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		n = da->get_next(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	da->list_dir_end(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	for (List<String>::Element *E = dirs.front(); E; E = E->next()) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		Error err = da->change_dir(E->get()); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		if (err == OK) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			err = _erase_recursive(da); | 
					
						
							|  |  |  | 			if (err) { | 
					
						
							| 
									
										
										
										
											2017-10-02 22:01:43 +07:00
										 |  |  | 				da->change_dir(".."); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				return err; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			err = da->change_dir(".."); | 
					
						
							|  |  |  | 			if (err) { | 
					
						
							|  |  |  | 				return err; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			err = da->remove(da->get_current_dir().plus_file(E->get())); | 
					
						
							|  |  |  | 			if (err) { | 
					
						
							|  |  |  | 				return err; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			return err; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	for (List<String>::Element *E = files.front(); E; E = E->next()) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		Error err = da->remove(da->get_current_dir().plus_file(E->get())); | 
					
						
							|  |  |  | 		if (err) { | 
					
						
							|  |  |  | 			return err; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Error DirAccess::erase_contents_recursive() { | 
					
						
							|  |  |  | 	return _erase_recursive(this); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Error DirAccess::make_dir_recursive(String p_dir) { | 
					
						
							|  |  |  | 	if (p_dir.length() < 1) { | 
					
						
							|  |  |  | 		return OK; | 
					
						
							| 
									
										
										
										
											2020-05-19 15:46:49 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-09-19 18:39:50 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	String full_dir; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-18 11:12:08 -03:00
										 |  |  | 	if (p_dir.is_rel_path()) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		//append current
 | 
					
						
							|  |  |  | 		full_dir = get_current_dir().plus_file(p_dir); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-19 18:39:50 -03:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		full_dir = p_dir; | 
					
						
							| 
									
										
										
										
											2014-09-19 18:39:50 -03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	full_dir = full_dir.replace("\\", "/"); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-18 11:12:08 -03:00
										 |  |  | 	//int slices = full_dir.get_slice_count("/");
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-18 11:12:08 -03:00
										 |  |  | 	String base; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (full_dir.begins_with("res://")) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		base = "res://"; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} else if (full_dir.begins_with("user://")) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		base = "user://"; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} else if (full_dir.begins_with("/")) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		base = "/"; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} else if (full_dir.find(":/") != -1) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		base = full_dir.substr(0, full_dir.find(":/") + 2); | 
					
						
							| 
									
										
										
										
											2016-06-18 11:12:08 -03:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		ERR_FAIL_V(ERR_INVALID_PARAMETER); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	full_dir = full_dir.replace_first(base, "").simplify_path(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	Vector<String> subdirs = full_dir.split("/"); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	String curpath = base; | 
					
						
							|  |  |  | 	for (int i = 0; i < subdirs.size(); i++) { | 
					
						
							|  |  |  | 		curpath = curpath.plus_file(subdirs[i]); | 
					
						
							| 
									
										
										
										
											2016-06-18 11:12:08 -03:00
										 |  |  | 		Error err = make_dir(curpath); | 
					
						
							|  |  |  | 		if (err != OK && err != ERR_ALREADY_EXISTS) { | 
					
						
							|  |  |  | 			ERR_FAIL_V(err); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-18 11:12:08 -03:00
										 |  |  | 	return OK; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | String DirAccess::fix_path(String p_path) const { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	switch (_access_type) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		case ACCESS_RESOURCES: { | 
					
						
							| 
									
										
										
										
											2017-07-19 17:00:46 -03:00
										 |  |  | 			if (ProjectSettings::get_singleton()) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				if (p_path.begins_with("res://")) { | 
					
						
							| 
									
										
										
										
											2017-07-19 17:00:46 -03:00
										 |  |  | 					String resource_path = ProjectSettings::get_singleton()->get_resource_path(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 					if (resource_path != "") { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 						return p_path.replace_first("res:/", resource_path); | 
					
						
							| 
									
										
										
										
											2020-05-19 15:46:49 +02:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2016-06-18 11:12:08 -03:00
										 |  |  | 					return p_path.replace_first("res://", ""); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		} break; | 
					
						
							|  |  |  | 		case ACCESS_USERDATA: { | 
					
						
							|  |  |  | 			if (p_path.begins_with("user://")) { | 
					
						
							| 
									
										
										
										
											2017-11-17 15:25:22 +01:00
										 |  |  | 				String data_dir = OS::get_singleton()->get_user_data_dir(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				if (data_dir != "") { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 					return p_path.replace_first("user:/", data_dir); | 
					
						
							| 
									
										
										
										
											2020-05-19 15:46:49 +02:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2016-06-18 11:12:08 -03:00
										 |  |  | 				return p_path.replace_first("user://", ""); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		} break; | 
					
						
							|  |  |  | 		case ACCESS_FILESYSTEM: { | 
					
						
							|  |  |  | 			return p_path; | 
					
						
							|  |  |  | 		} break; | 
					
						
							| 
									
										
										
										
											2020-05-10 13:00:47 +02:00
										 |  |  | 		case ACCESS_MAX: | 
					
						
							|  |  |  | 			break; // Can't happen, but silences warning
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return p_path; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | DirAccess::CreateFunc DirAccess::create_func[ACCESS_MAX] = { nullptr, nullptr, nullptr }; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | DirAccess *DirAccess::create_for_path(const String &p_path) { | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 	DirAccess *da = nullptr; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	if (p_path.begins_with("res://")) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		da = create(ACCESS_RESOURCES); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} else if (p_path.begins_with("user://")) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		da = create(ACCESS_USERDATA); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		da = create(ACCESS_FILESYSTEM); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return da; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | DirAccess *DirAccess::open(const String &p_path, Error *r_error) { | 
					
						
							|  |  |  | 	DirAccess *da = create_for_path(p_path); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 	ERR_FAIL_COND_V_MSG(!da, nullptr, "Cannot create DirAccess for path '" + p_path + "'."); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	Error err = da->change_dir(p_path); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (r_error) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		*r_error = err; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	if (err != OK) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		memdelete(da); | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 		return nullptr; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return da; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | DirAccess *DirAccess::create(AccessType p_access) { | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 	DirAccess *da = create_func[p_access] ? create_func[p_access]() : nullptr; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	if (da) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		da->_access_type = p_access; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return da; | 
					
						
							| 
									
										
										
										
											2020-05-19 15:46:49 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | String DirAccess::get_full_path(const String &p_path, AccessType p_access) { | 
					
						
							|  |  |  | 	DirAccess *d = DirAccess::create(p_access); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (!d) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return p_path; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	d->change_dir(p_path); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	String full = d->get_current_dir(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	memdelete(d); | 
					
						
							|  |  |  | 	return full; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-03 21:17:30 -07:00
										 |  |  | Error DirAccess::copy(String p_from, String p_to, int p_chmod_flags) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	//printf("copy %s -> %s\n",p_from.ascii().get_data(),p_to.ascii().get_data());
 | 
					
						
							|  |  |  | 	Error err; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	FileAccess *fsrc = FileAccess::open(p_from, FileAccess::READ, &err); | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	if (err) { | 
					
						
							| 
									
										
										
										
											2019-11-06 17:03:04 +01:00
										 |  |  | 		ERR_PRINT("Failed to open " + p_from); | 
					
						
							| 
									
										
										
										
											2018-03-06 12:13:18 -03:00
										 |  |  | 		return err; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	FileAccess *fdst = FileAccess::open(p_to, FileAccess::WRITE, &err); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	if (err) { | 
					
						
							|  |  |  | 		fsrc->close(); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		memdelete(fsrc); | 
					
						
							| 
									
										
										
										
											2019-11-06 17:03:04 +01:00
										 |  |  | 		ERR_PRINT("Failed to open " + p_to); | 
					
						
							| 
									
										
										
										
											2018-03-06 12:13:18 -03:00
										 |  |  | 		return err; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	fsrc->seek_end(0); | 
					
						
							| 
									
										
										
										
											2017-09-10 15:37:49 +02:00
										 |  |  | 	int size = fsrc->get_position(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	fsrc->seek(0); | 
					
						
							|  |  |  | 	err = OK; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	while (size--) { | 
					
						
							|  |  |  | 		if (fsrc->get_error() != OK) { | 
					
						
							|  |  |  | 			err = fsrc->get_error(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		if (fdst->get_error() != OK) { | 
					
						
							|  |  |  | 			err = fdst->get_error(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		fdst->store_8(fsrc->get_8()); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-03 21:17:30 -07:00
										 |  |  | 	if (err == OK && p_chmod_flags != -1) { | 
					
						
							| 
									
										
										
										
											2017-09-17 14:40:58 -03:00
										 |  |  | 		fdst->close(); | 
					
						
							| 
									
										
										
										
											2019-04-07 15:46:52 -03:00
										 |  |  | 		err = FileAccess::set_unix_permissions(p_to, p_chmod_flags); | 
					
						
							| 
									
										
										
										
											2017-12-06 20:25:41 +01:00
										 |  |  | 		// If running on a platform with no chmod support (i.e., Windows), don't fail
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		if (err == ERR_UNAVAILABLE) { | 
					
						
							| 
									
										
										
										
											2017-12-06 20:25:41 +01:00
										 |  |  | 			err = OK; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-09-17 14:40:58 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	memdelete(fsrc); | 
					
						
							|  |  |  | 	memdelete(fdst); | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	return err; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-02 22:01:43 +07:00
										 |  |  | // Changes dir for the current scope, returning back to the original dir
 | 
					
						
							|  |  |  | // when scope exits
 | 
					
						
							|  |  |  | class DirChanger { | 
					
						
							|  |  |  | 	DirAccess *da; | 
					
						
							|  |  |  | 	String original_dir; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | public: | 
					
						
							| 
									
										
										
										
											2018-12-08 15:07:33 -05:00
										 |  |  | 	DirChanger(DirAccess *p_da, String p_dir) : | 
					
						
							|  |  |  | 			da(p_da), | 
					
						
							|  |  |  | 			original_dir(p_da->get_current_dir()) { | 
					
						
							| 
									
										
										
										
											2017-10-02 22:01:43 +07:00
										 |  |  | 		p_da->change_dir(p_dir); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	~DirChanger() { | 
					
						
							|  |  |  | 		da->change_dir(original_dir); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Error DirAccess::_copy_dir(DirAccess *p_target_da, String p_to, int p_chmod_flags) { | 
					
						
							|  |  |  | 	List<String> dirs; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	String curdir = get_current_dir(); | 
					
						
							|  |  |  | 	list_dir_begin(); | 
					
						
							|  |  |  | 	String n = get_next(); | 
					
						
							|  |  |  | 	while (n != String()) { | 
					
						
							|  |  |  | 		if (n != "." && n != "..") { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 			if (current_is_dir()) { | 
					
						
							| 
									
										
										
										
											2017-10-02 22:01:43 +07:00
										 |  |  | 				dirs.push_back(n); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 			} else { | 
					
						
							| 
									
										
										
										
											2019-06-26 15:08:25 +02:00
										 |  |  | 				const String &rel_path = n; | 
					
						
							| 
									
										
										
										
											2017-10-02 22:01:43 +07:00
										 |  |  | 				if (!n.is_rel_path()) { | 
					
						
							|  |  |  | 					list_dir_end(); | 
					
						
							|  |  |  | 					return ERR_BUG; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2019-06-16 13:31:57 +01:00
										 |  |  | 				Error err = copy(get_current_dir().plus_file(n), p_to + rel_path, p_chmod_flags); | 
					
						
							| 
									
										
										
										
											2017-10-02 22:01:43 +07:00
										 |  |  | 				if (err) { | 
					
						
							|  |  |  | 					list_dir_end(); | 
					
						
							|  |  |  | 					return err; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		n = get_next(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	list_dir_end(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (List<String>::Element *E = dirs.front(); E; E = E->next()) { | 
					
						
							|  |  |  | 		String rel_path = E->get(); | 
					
						
							|  |  |  | 		String target_dir = p_to + rel_path; | 
					
						
							|  |  |  | 		if (!p_target_da->dir_exists(target_dir)) { | 
					
						
							|  |  |  | 			Error err = p_target_da->make_dir(target_dir); | 
					
						
							| 
									
										
										
										
											2019-09-25 10:28:50 +02:00
										 |  |  | 			ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot create directory '" + target_dir + "'."); | 
					
						
							| 
									
										
										
										
											2017-10-02 22:01:43 +07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Error err = change_dir(E->get()); | 
					
						
							| 
									
										
										
										
											2019-09-25 10:28:50 +02:00
										 |  |  | 		ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot change current directory to '" + E->get() + "'."); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-02 22:01:43 +07:00
										 |  |  | 		err = _copy_dir(p_target_da, p_to + rel_path + "/", p_chmod_flags); | 
					
						
							|  |  |  | 		if (err) { | 
					
						
							|  |  |  | 			change_dir(".."); | 
					
						
							| 
									
										
										
										
											2019-09-25 10:28:50 +02:00
										 |  |  | 			ERR_FAIL_V_MSG(err, "Failed to copy recursively."); | 
					
						
							| 
									
										
										
										
											2017-10-02 22:01:43 +07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		err = change_dir(".."); | 
					
						
							| 
									
										
										
										
											2019-09-25 10:28:50 +02:00
										 |  |  | 		ERR_FAIL_COND_V_MSG(err != OK, err, "Failed to go back."); | 
					
						
							| 
									
										
										
										
											2017-10-02 22:01:43 +07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Error DirAccess::copy_dir(String p_from, String p_to, int p_chmod_flags) { | 
					
						
							| 
									
										
										
										
											2019-09-25 10:28:50 +02:00
										 |  |  | 	ERR_FAIL_COND_V_MSG(!dir_exists(p_from), ERR_FILE_NOT_FOUND, "Source directory doesn't exist."); | 
					
						
							| 
									
										
										
										
											2017-10-02 22:01:43 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	DirAccess *target_da = DirAccess::create_for_path(p_to); | 
					
						
							| 
									
										
										
										
											2019-09-25 10:28:50 +02:00
										 |  |  | 	ERR_FAIL_COND_V_MSG(!target_da, ERR_CANT_CREATE, "Cannot create DirAccess for path '" + p_to + "'."); | 
					
						
							| 
									
										
										
										
											2017-10-02 22:01:43 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (!target_da->dir_exists(p_to)) { | 
					
						
							|  |  |  | 		Error err = target_da->make_dir_recursive(p_to); | 
					
						
							|  |  |  | 		if (err) { | 
					
						
							|  |  |  | 			memdelete(target_da); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-09-25 10:28:50 +02:00
										 |  |  | 		ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot create directory '" + p_to + "'."); | 
					
						
							| 
									
										
										
										
											2017-10-02 22:01:43 +07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-02 16:19:11 +01:00
										 |  |  | 	if (!p_to.ends_with("/")) { | 
					
						
							|  |  |  | 		p_to = p_to + "/"; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-02 22:01:43 +07:00
										 |  |  | 	DirChanger dir_changer(this, p_from); | 
					
						
							| 
									
										
										
										
											2018-10-02 16:19:11 +01:00
										 |  |  | 	Error err = _copy_dir(target_da, p_to, p_chmod_flags); | 
					
						
							| 
									
										
										
										
											2017-10-02 22:01:43 +07:00
										 |  |  | 	memdelete(target_da); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return err; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-12 16:45:59 -03:00
										 |  |  | bool DirAccess::exists(String p_dir) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	DirAccess *da = DirAccess::create_for_path(p_dir); | 
					
						
							|  |  |  | 	bool valid = da->change_dir(p_dir) == OK; | 
					
						
							| 
									
										
										
										
											2015-04-12 16:45:59 -03:00
										 |  |  | 	memdelete(da); | 
					
						
							|  |  |  | 	return valid; | 
					
						
							|  |  |  | } |