diff options
Diffstat (limited to 'drivers/unix/dir_access_unix.cpp')
-rw-r--r-- | drivers/unix/dir_access_unix.cpp | 208 |
1 files changed, 146 insertions, 62 deletions
diff --git a/drivers/unix/dir_access_unix.cpp b/drivers/unix/dir_access_unix.cpp index 5b99a2f53f..d894ceba59 100644 --- a/drivers/unix/dir_access_unix.cpp +++ b/drivers/unix/dir_access_unix.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,29 +30,23 @@ #include "dir_access_unix.h" -#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED) +#if defined(UNIX_ENABLED) -#include "core/list.h" #include "core/os/memory.h" -#include "core/print_string.h" +#include "core/os/os.h" +#include "core/string/print_string.h" +#include "core/templates/list.h" #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> - -#ifndef ANDROID_ENABLED #include <sys/statvfs.h> -#endif #ifdef HAVE_MNTENT #include <mntent.h> #endif -DirAccess *DirAccessUnix::create_fs() { - return memnew(DirAccessUnix); -} - Error DirAccessUnix::list_dir_begin() { list_dir_end(); //close any previous dir opening! @@ -71,13 +65,13 @@ Error DirAccessUnix::list_dir_begin() { bool DirAccessUnix::file_exists(String p_file) { GLOBAL_LOCK_FUNCTION - if (p_file.is_rel_path()) { - p_file = current_dir.plus_file(p_file); + if (p_file.is_relative_path()) { + p_file = current_dir.path_join(p_file); } p_file = fix_path(p_file); - struct stat flags; + struct stat flags = {}; bool success = (stat(p_file.utf8().get_data(), &flags) == 0); if (success && S_ISDIR(flags.st_mode)) { @@ -90,35 +84,57 @@ bool DirAccessUnix::file_exists(String p_file) { bool DirAccessUnix::dir_exists(String p_dir) { GLOBAL_LOCK_FUNCTION - if (p_dir.is_rel_path()) { - p_dir = get_current_dir().plus_file(p_dir); + if (p_dir.is_relative_path()) { + p_dir = get_current_dir().path_join(p_dir); } p_dir = fix_path(p_dir); - struct stat flags; + struct stat flags = {}; bool success = (stat(p_dir.utf8().get_data(), &flags) == 0); return (success && S_ISDIR(flags.st_mode)); } +bool DirAccessUnix::is_readable(String p_dir) { + GLOBAL_LOCK_FUNCTION + + if (p_dir.is_relative_path()) { + p_dir = get_current_dir().path_join(p_dir); + } + + p_dir = fix_path(p_dir); + return (access(p_dir.utf8().get_data(), R_OK) == 0); +} + +bool DirAccessUnix::is_writable(String p_dir) { + GLOBAL_LOCK_FUNCTION + + if (p_dir.is_relative_path()) { + p_dir = get_current_dir().path_join(p_dir); + } + + p_dir = fix_path(p_dir); + return (access(p_dir.utf8().get_data(), W_OK) == 0); +} + uint64_t DirAccessUnix::get_modified_time(String p_file) { - if (p_file.is_rel_path()) { - p_file = current_dir.plus_file(p_file); + if (p_file.is_relative_path()) { + p_file = current_dir.path_join(p_file); } p_file = fix_path(p_file); - struct stat flags; + struct stat flags = {}; bool success = (stat(p_file.utf8().get_data(), &flags) == 0); if (success) { return flags.st_mtime; } else { ERR_FAIL_V(0); - }; + } return 0; -}; +} String DirAccessUnix::get_next() { if (!dir_stream) { @@ -140,9 +156,9 @@ String DirAccessUnix::get_next() { // known if it points to a directory. stat() will resolve the link // for us. if (entry->d_type == DT_UNKNOWN || entry->d_type == DT_LNK) { - String f = current_dir.plus_file(fname); + String f = current_dir.path_join(fname); - struct stat flags; + struct stat flags = {}; if (stat(f.utf8().get_data(), &flags) == 0) { _cisdir = S_ISDIR(flags.st_mode); } else { @@ -194,8 +210,11 @@ static bool _filter_drive(struct mntent *mnt) { #endif static void _get_drives(List<String> *list) { + // Add root. + list->push_back("/"); + #if defined(HAVE_MNTENT) && defined(X11_ENABLED) - // Check /etc/mtab for the list of mounted partitions + // Check /etc/mtab for the list of mounted partitions. FILE *mtab = setmntent("/etc/mtab", "r"); if (mtab) { struct mntent mnt; @@ -204,8 +223,9 @@ static void _get_drives(List<String> *list) { while (getmntent_r(mtab, &mnt, strings, sizeof(strings))) { if (mnt.mnt_dir != nullptr && _filter_drive(&mnt)) { // Avoid duplicates - if (!list->find(mnt.mnt_dir)) { - list->push_back(mnt.mnt_dir); + String name = String::utf8(mnt.mnt_dir); + if (!list->find(name)) { + list->push_back(name); } } } @@ -214,15 +234,17 @@ static void _get_drives(List<String> *list) { } #endif - // Add $HOME + // Add $HOME. const char *home = getenv("HOME"); if (home) { // Only add if it's not a duplicate - if (!list->find(home)) { - list->push_back(home); + String home_name = String::utf8(home); + if (!list->find(home_name)) { + list->push_back(home_name); } - // Check $HOME/.config/gtk-3.0/bookmarks + // Check GTK+3 bookmarks for both XDG locations (Documents, Downloads, etc.) + // and potential user-defined bookmarks. char path[1024]; snprintf(path, 1024, "%s/.config/gtk-3.0/bookmarks", home); FILE *fd = fopen(path, "r"); @@ -231,8 +253,8 @@ static void _get_drives(List<String> *list) { while (fgets(string, 1024, fd)) { // Parse only file:// links if (strncmp(string, "file://", 7) == 0) { - // Strip any unwanted edges on the strings and push_back if it's not a duplicate - String fpath = String(string + 7).strip_edges().split_spaces()[0].percent_decode(); + // Strip any unwanted edges on the strings and push_back if it's not a duplicate. + String fpath = String::utf8(string + 7).strip_edges().split_spaces()[0].uri_decode(); if (!list->find(fpath)) { list->push_back(fpath); } @@ -241,6 +263,12 @@ static void _get_drives(List<String> *list) { fclose(fd); } + + // Add Desktop dir. + String dpath = OS::get_singleton()->get_system_dir(OS::SystemDir::SYSTEM_DIR_DESKTOP); + if (dpath.length() > 0 && !list->find(dpath)) { + list->push_back(dpath); + } } list->sort(); @@ -262,6 +290,20 @@ String DirAccessUnix::get_drive(int p_drive) { return list[p_drive]; } +int DirAccessUnix::get_current_drive() { + int drive = 0; + int max_length = -1; + const String path = get_current_dir().to_lower(); + for (int i = 0; i < get_drive_count(); i++) { + const String d = get_drive(i).to_lower(); + if (max_length < d.length() && path.begins_with(d)) { + max_length = d.length(); + drive = i; + } + } + return drive; +} + bool DirAccessUnix::drives_are_shortcuts() { return true; } @@ -269,8 +311,8 @@ bool DirAccessUnix::drives_are_shortcuts() { Error DirAccessUnix::make_dir(String p_dir) { GLOBAL_LOCK_FUNCTION - if (p_dir.is_rel_path()) { - p_dir = get_current_dir().plus_file(p_dir); + if (p_dir.is_relative_path()) { + p_dir = get_current_dir().path_join(p_dir); } p_dir = fix_path(p_dir); @@ -280,11 +322,11 @@ Error DirAccessUnix::make_dir(String p_dir) { if (success) { return OK; - }; + } if (err == EEXIST) { return ERR_ALREADY_EXISTS; - }; + } return ERR_CANT_CREATE; } @@ -298,14 +340,14 @@ Error DirAccessUnix::change_dir(String p_dir) { String prev_dir; char real_current_dir_name[2048]; ERR_FAIL_COND_V(getcwd(real_current_dir_name, 2048) == nullptr, ERR_BUG); - if (prev_dir.parse_utf8(real_current_dir_name)) { + if (prev_dir.parse_utf8(real_current_dir_name) != OK) { prev_dir = real_current_dir_name; //no utf8, maybe latin? } // try_dir is the directory we are trying to change into String try_dir = ""; - if (p_dir.is_rel_path()) { - String next_dir = current_dir.plus_file(p_dir); + if (p_dir.is_relative_path()) { + String next_dir = current_dir.path_join(p_dir); next_dir = next_dir.simplify_path(); try_dir = next_dir; } else { @@ -318,7 +360,7 @@ Error DirAccessUnix::change_dir(String p_dir) { } String base = _get_root_path(); - if (base != String() && !try_dir.begins_with(base)) { + if (!base.is_empty() && !try_dir.begins_with(base)) { ERR_FAIL_COND_V(getcwd(real_current_dir_name, 2048) == nullptr, ERR_BUG); String new_dir; new_dir.parse_utf8(real_current_dir_name); @@ -334,9 +376,9 @@ Error DirAccessUnix::change_dir(String p_dir) { return OK; } -String DirAccessUnix::get_current_dir(bool p_include_drive) { +String DirAccessUnix::get_current_dir(bool p_include_drive) const { String base = _get_root_path(); - if (base != "") { + if (!base.is_empty()) { String bd = current_dir.replace_first(base, ""); if (bd.begins_with("/")) { return _get_root_string() + bd.substr(1, bd.length()); @@ -348,14 +390,14 @@ String DirAccessUnix::get_current_dir(bool p_include_drive) { } Error DirAccessUnix::rename(String p_path, String p_new_path) { - if (p_path.is_rel_path()) { - p_path = get_current_dir().plus_file(p_path); + if (p_path.is_relative_path()) { + p_path = get_current_dir().path_join(p_path); } p_path = fix_path(p_path); - if (p_new_path.is_rel_path()) { - p_new_path = get_current_dir().plus_file(p_new_path); + if (p_new_path.is_relative_path()) { + p_new_path = get_current_dir().path_join(p_new_path); } p_new_path = fix_path(p_new_path); @@ -364,13 +406,13 @@ Error DirAccessUnix::rename(String p_path, String p_new_path) { } Error DirAccessUnix::remove(String p_path) { - if (p_path.is_rel_path()) { - p_path = get_current_dir().plus_file(p_path); + if (p_path.is_relative_path()) { + p_path = get_current_dir().path_join(p_path); } p_path = fix_path(p_path); - struct stat flags; + struct stat flags = {}; if ((stat(p_path.utf8().get_data(), &flags) != 0)) { return FAILED; } @@ -382,19 +424,61 @@ Error DirAccessUnix::remove(String p_path) { } } -size_t DirAccessUnix::get_space_left() { -#ifndef NO_STATVFS +bool DirAccessUnix::is_link(String p_file) { + if (p_file.is_relative_path()) { + p_file = get_current_dir().path_join(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_relative_path()) { + p_file = get_current_dir().path_join(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_relative_path()) { + p_target = get_current_dir().path_join(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() { struct statvfs vfs; if (statvfs(current_dir.utf8().get_data(), &vfs) != 0) { return 0; - }; + } - return vfs.f_bfree * vfs.f_bsize; -#else - // FIXME: Implement this. - return 0; -#endif -}; + return (uint64_t)vfs.f_bavail * (uint64_t)vfs.f_frsize; +} String DirAccessUnix::get_filesystem_type() const { return ""; //TODO this should be implemented @@ -413,7 +497,7 @@ DirAccessUnix::DirAccessUnix() { // set current directory to an absolute path of the current directory char real_current_dir_name[2048]; ERR_FAIL_COND(getcwd(real_current_dir_name, 2048) == nullptr); - if (current_dir.parse_utf8(real_current_dir_name)) { + if (current_dir.parse_utf8(real_current_dir_name) != OK) { current_dir = real_current_dir_name; } @@ -424,4 +508,4 @@ DirAccessUnix::~DirAccessUnix() { list_dir_end(); } -#endif //posix_enabled +#endif // UNIX_ENABLED |