Add symlink API to the DirAccess (on macOS and Linux).
This commit is contained in:
parent
2660fafcc0
commit
6aa8f7d85b
7 changed files with 73 additions and 7 deletions
|
@ -235,6 +235,10 @@ public:
|
||||||
virtual Error rename(String p_from, String p_to);
|
virtual Error rename(String p_from, String p_to);
|
||||||
virtual Error remove(String p_name);
|
virtual Error remove(String p_name);
|
||||||
|
|
||||||
|
virtual bool is_link(String p_file) { return false; }
|
||||||
|
virtual String read_link(String p_file) { return p_file; }
|
||||||
|
virtual Error create_link(String p_source, String p_target) { return FAILED; }
|
||||||
|
|
||||||
uint64_t get_space_left();
|
uint64_t get_space_left();
|
||||||
|
|
||||||
virtual String get_filesystem_type() const;
|
virtual String get_filesystem_type() const;
|
||||||
|
|
|
@ -334,7 +334,7 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Error DirAccess::_copy_dir(DirAccess *p_target_da, String p_to, int p_chmod_flags) {
|
Error DirAccess::_copy_dir(DirAccess *p_target_da, String p_to, int p_chmod_flags, bool p_copy_links) {
|
||||||
List<String> dirs;
|
List<String> dirs;
|
||||||
|
|
||||||
String curdir = get_current_dir();
|
String curdir = get_current_dir();
|
||||||
|
@ -342,7 +342,9 @@ Error DirAccess::_copy_dir(DirAccess *p_target_da, String p_to, int p_chmod_flag
|
||||||
String n = get_next();
|
String n = get_next();
|
||||||
while (n != String()) {
|
while (n != String()) {
|
||||||
if (n != "." && n != "..") {
|
if (n != "." && n != "..") {
|
||||||
if (current_is_dir()) {
|
if (p_copy_links && is_link(get_current_dir().plus_file(n))) {
|
||||||
|
create_link(read_link(get_current_dir().plus_file(n)), p_to + n);
|
||||||
|
} else if (current_is_dir()) {
|
||||||
dirs.push_back(n);
|
dirs.push_back(n);
|
||||||
} else {
|
} else {
|
||||||
const String &rel_path = n;
|
const String &rel_path = n;
|
||||||
|
@ -374,7 +376,7 @@ Error DirAccess::_copy_dir(DirAccess *p_target_da, String p_to, int p_chmod_flag
|
||||||
Error err = change_dir(E->get());
|
Error err = change_dir(E->get());
|
||||||
ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot change current directory to '" + E->get() + "'.");
|
ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot change current directory to '" + E->get() + "'.");
|
||||||
|
|
||||||
err = _copy_dir(p_target_da, p_to + rel_path + "/", p_chmod_flags);
|
err = _copy_dir(p_target_da, p_to + rel_path + "/", p_chmod_flags, p_copy_links);
|
||||||
if (err) {
|
if (err) {
|
||||||
change_dir("..");
|
change_dir("..");
|
||||||
ERR_FAIL_V_MSG(err, "Failed to copy recursively.");
|
ERR_FAIL_V_MSG(err, "Failed to copy recursively.");
|
||||||
|
@ -386,7 +388,7 @@ Error DirAccess::_copy_dir(DirAccess *p_target_da, String p_to, int p_chmod_flag
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error DirAccess::copy_dir(String p_from, String p_to, int p_chmod_flags) {
|
Error DirAccess::copy_dir(String p_from, String p_to, int p_chmod_flags, bool p_copy_links) {
|
||||||
ERR_FAIL_COND_V_MSG(!dir_exists(p_from), ERR_FILE_NOT_FOUND, "Source directory doesn't exist.");
|
ERR_FAIL_COND_V_MSG(!dir_exists(p_from), ERR_FILE_NOT_FOUND, "Source directory doesn't exist.");
|
||||||
|
|
||||||
DirAccess *target_da = DirAccess::create_for_path(p_to);
|
DirAccess *target_da = DirAccess::create_for_path(p_to);
|
||||||
|
@ -405,7 +407,7 @@ Error DirAccess::copy_dir(String p_from, String p_to, int p_chmod_flags) {
|
||||||
}
|
}
|
||||||
|
|
||||||
DirChanger dir_changer(this, p_from);
|
DirChanger dir_changer(this, p_from);
|
||||||
Error err = _copy_dir(target_da, p_to, p_chmod_flags);
|
Error err = _copy_dir(target_da, p_to, p_chmod_flags, p_copy_links);
|
||||||
memdelete(target_da);
|
memdelete(target_da);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
|
|
@ -50,7 +50,7 @@ private:
|
||||||
AccessType _access_type;
|
AccessType _access_type;
|
||||||
static CreateFunc create_func[ACCESS_MAX]; ///< set this to instance a filesystem object
|
static CreateFunc create_func[ACCESS_MAX]; ///< set this to instance a filesystem object
|
||||||
|
|
||||||
Error _copy_dir(DirAccess *p_target_da, String p_to, int p_chmod_flags);
|
Error _copy_dir(DirAccess *p_target_da, String p_to, int p_chmod_flags, bool p_copy_links);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
String _get_root_path() const;
|
String _get_root_path() const;
|
||||||
|
@ -89,11 +89,15 @@ public:
|
||||||
static bool exists(String p_dir);
|
static bool exists(String p_dir);
|
||||||
virtual uint64_t get_space_left() = 0;
|
virtual uint64_t get_space_left() = 0;
|
||||||
|
|
||||||
Error copy_dir(String p_from, String p_to, int p_chmod_flags = -1);
|
Error copy_dir(String p_from, String p_to, int p_chmod_flags = -1, bool p_copy_links = false);
|
||||||
virtual Error copy(String p_from, String p_to, int p_chmod_flags = -1);
|
virtual Error copy(String p_from, String p_to, int p_chmod_flags = -1);
|
||||||
virtual Error rename(String p_from, String p_to) = 0;
|
virtual Error rename(String p_from, String p_to) = 0;
|
||||||
virtual Error remove(String p_name) = 0;
|
virtual Error remove(String p_name) = 0;
|
||||||
|
|
||||||
|
virtual bool is_link(String p_file) = 0;
|
||||||
|
virtual String read_link(String p_file) = 0;
|
||||||
|
virtual Error create_link(String p_source, String p_target) = 0;
|
||||||
|
|
||||||
// Meant for editor code when we want to quickly remove a file without custom
|
// Meant for editor code when we want to quickly remove a file without custom
|
||||||
// handling (e.g. removing a cache file).
|
// handling (e.g. removing a cache file).
|
||||||
static void remove_file_or_error(String p_path) {
|
static void remove_file_or_error(String p_path) {
|
||||||
|
|
|
@ -382,6 +382,49 @@ Error DirAccessUnix::remove(String p_path) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DirAccessUnix::is_link(String p_file) {
|
||||||
|
if (p_file.is_rel_path())
|
||||||
|
p_file = get_current_dir().plus_file(p_file);
|
||||||
|
|
||||||
|
p_file = fix_path(p_file);
|
||||||
|
|
||||||
|
struct stat flags;
|
||||||
|
if ((lstat(p_file.utf8().get_data(), &flags) != 0))
|
||||||
|
return FAILED;
|
||||||
|
|
||||||
|
return S_ISLNK(flags.st_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
String DirAccessUnix::read_link(String p_file) {
|
||||||
|
if (p_file.is_rel_path())
|
||||||
|
p_file = get_current_dir().plus_file(p_file);
|
||||||
|
|
||||||
|
p_file = fix_path(p_file);
|
||||||
|
|
||||||
|
char buf[256];
|
||||||
|
memset(buf, 0, 256);
|
||||||
|
ssize_t len = readlink(p_file.utf8().get_data(), buf, sizeof(buf));
|
||||||
|
String link;
|
||||||
|
if (len > 0) {
|
||||||
|
link.parse_utf8(buf, len);
|
||||||
|
}
|
||||||
|
return link;
|
||||||
|
}
|
||||||
|
|
||||||
|
Error DirAccessUnix::create_link(String p_source, String p_target) {
|
||||||
|
if (p_target.is_rel_path())
|
||||||
|
p_target = get_current_dir().plus_file(p_target);
|
||||||
|
|
||||||
|
p_source = fix_path(p_source);
|
||||||
|
p_target = fix_path(p_target);
|
||||||
|
|
||||||
|
if (symlink(p_source.utf8().get_data(), p_target.utf8().get_data()) == 0) {
|
||||||
|
return OK;
|
||||||
|
} else {
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t DirAccessUnix::get_space_left() {
|
uint64_t DirAccessUnix::get_space_left() {
|
||||||
#ifndef NO_STATVFS
|
#ifndef NO_STATVFS
|
||||||
struct statvfs vfs;
|
struct statvfs vfs;
|
||||||
|
|
|
@ -77,6 +77,10 @@ public:
|
||||||
virtual Error rename(String p_path, String p_new_path);
|
virtual Error rename(String p_path, String p_new_path);
|
||||||
virtual Error remove(String p_path);
|
virtual Error remove(String p_path);
|
||||||
|
|
||||||
|
virtual bool is_link(String p_file);
|
||||||
|
virtual String read_link(String p_file);
|
||||||
|
virtual Error create_link(String p_source, String p_target);
|
||||||
|
|
||||||
virtual uint64_t get_space_left();
|
virtual uint64_t get_space_left();
|
||||||
|
|
||||||
virtual String get_filesystem_type() const;
|
virtual String get_filesystem_type() const;
|
||||||
|
|
|
@ -79,6 +79,11 @@ public:
|
||||||
virtual Error rename(String p_path, String p_new_path);
|
virtual Error rename(String p_path, String p_new_path);
|
||||||
virtual Error remove(String p_path);
|
virtual Error remove(String p_path);
|
||||||
|
|
||||||
|
virtual bool is_link(String p_file) { return false; };
|
||||||
|
virtual String read_link(String p_file) { return p_file; };
|
||||||
|
virtual Error create_link(String p_source, String p_target) { return FAILED; };
|
||||||
|
|
||||||
|
//virtual FileType get_file_type() const;
|
||||||
uint64_t get_space_left();
|
uint64_t get_space_left();
|
||||||
|
|
||||||
virtual String get_filesystem_type() const;
|
virtual String get_filesystem_type() const;
|
||||||
|
|
|
@ -74,6 +74,10 @@ public:
|
||||||
virtual Error rename(String p_from, String p_to);
|
virtual Error rename(String p_from, String p_to);
|
||||||
virtual Error remove(String p_name);
|
virtual Error remove(String p_name);
|
||||||
|
|
||||||
|
virtual bool is_link(String p_file) { return false; }
|
||||||
|
virtual String read_link(String p_file) { return p_file; }
|
||||||
|
virtual Error create_link(String p_source, String p_target) { return FAILED; }
|
||||||
|
|
||||||
virtual String get_filesystem_type() const;
|
virtual String get_filesystem_type() const;
|
||||||
|
|
||||||
uint64_t get_space_left();
|
uint64_t get_space_left();
|
||||||
|
|
Loading…
Reference in a new issue