X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;ds=inline;f=libs%2Fpbd%2Ffile_utils.cc;h=bb290fa6aaf1ae9ccdeba64e9a3941ed734b0184;hb=b880a381523b2cfdb7ebd17c27fff1adf90fa028;hp=956b7002cbd12bcdd2234ca7d42f421e96431080;hpb=a22dd8c20a656a36d93e3e31ee3c04ca7e9b7278;p=ardour.git diff --git a/libs/pbd/file_utils.cc b/libs/pbd/file_utils.cc index 956b7002cb..bb290fa6aa 100644 --- a/libs/pbd/file_utils.cc +++ b/libs/pbd/file_utils.cc @@ -18,6 +18,10 @@ */ #include +#include + +#include +#include #include #include @@ -29,6 +33,7 @@ #include "pbd/file_utils.h" #include "pbd/error.h" #include "pbd/pathscanner.h" +#include "pbd/stl_delete.h" #include "i18n.h" @@ -139,7 +144,7 @@ copy_file(const std::string & from_path, const std::string & to_path) try { - from_file->copy (to_file); + from_file->copy (to_file, Gio::FILE_COPY_OVERWRITE); } catch(const Glib::Exception& ex) { @@ -162,11 +167,80 @@ copy_files(const std::string & from_path, const std::string & to_dir) { PathScanner scanner; vector* files = scanner (from_path, accept_all_files, 0, true, false); - for (vector::iterator i = files->begin(); i != files->end(); ++i) { - std::string from = Glib::build_filename (from_path, **i); - std::string to = Glib::build_filename (to_dir, **i); - copy_file (from, to); + + if (files) { + for (vector::iterator i = files->begin(); i != files->end(); ++i) { + std::string from = Glib::build_filename (from_path, **i); + std::string to = Glib::build_filename (to_dir, **i); + copy_file (from, to); + } + vector_delete (files); + } +} + +std::string +get_absolute_path (const std::string & p) +{ + Glib::RefPtr f = Gio::File::create_for_path (p); + return f->get_path (); +} + +bool +equivalent_paths (const std::string& a, const std::string& b) +{ + struct stat bA; + int const rA = g_stat (a.c_str(), &bA); + struct stat bB; + int const rB = g_stat (b.c_str(), &bB); + + return (rA == 0 && rB == 0 && bA.st_dev == bB.st_dev && bA.st_ino == bB.st_ino); +} + +bool +path_is_within (std::string const & haystack, std::string needle) +{ + while (1) { + if (equivalent_paths (haystack, needle)) { + return true; + } + + needle = Glib::path_get_dirname (needle); + if (needle == "." || needle == "/") { + break; + } } + + return false; +} + +bool +exists_and_writable (const std::string & p) +{ + /* writable() really reflects the whole folder, but if for any + reason the session state file can't be written to, still + make us unwritable. + */ + + struct stat statbuf; + + if (g_stat (p.c_str(), &statbuf) != 0) { + /* doesn't exist - not writable */ + return false; + } else { + if (!(statbuf.st_mode & S_IWUSR)) { + /* exists and is not writable */ + return false; + } + /* filesystem may be mounted read-only, so even though file + * permissions permit access, the mount status does not. + * access(2) seems like the best test for this. + */ + if (g_access (p.c_str(), W_OK) != 0) { + return false; + } + } + + return true; } } // namespace PBD