diff --git a/include/linuxdeploy/util/misc.h b/include/linuxdeploy/util/misc.h index 09c3c47..20b5d95 100644 --- a/include/linuxdeploy/util/misc.h +++ b/include/linuxdeploy/util/misc.h @@ -6,10 +6,33 @@ #include #include #include +#include namespace linuxdeploy { namespace util { namespace misc { + static bool path_contains_file(boost::filesystem::path dir, boost::filesystem::path file) { + // If dir ends with "/" and isn't the root directory, then the final + // component returned by iterators will include "." and will interfere + // with the std::equal check below, so we strip it before proceeding. + if (dir.filename() == ".") + dir.remove_filename(); + // We're also not interested in the file's name. + assert(file.has_filename()); + file.remove_filename(); + + // If dir has more components than file, then file can't possibly + // reside in dir. + auto dir_len = std::distance(dir.begin(), dir.end()); + auto file_len = std::distance(file.begin(), file.end()); + if (dir_len > file_len) + return false; + + // This stops checking when it reaches dir.end(), so it's OK if file + // has more directory components afterward. They won't be checked. + return std::equal(dir.begin(), dir.end(), file.begin()); + }; + static inline bool ltrim(std::string& s, char to_trim = ' ') { // TODO: find more efficient way to check whether elements have been removed size_t initialLength = s.length(); diff --git a/src/core/appdir.cpp b/src/core/appdir.cpp index c20fa4e..a1294cd 100644 --- a/src/core/appdir.cpp +++ b/src/core/appdir.cpp @@ -20,6 +20,7 @@ #include "excludelist.h" using namespace linuxdeploy::core; +using namespace linuxdeploy::util::misc; using namespace linuxdeploy::core::log; using namespace cimg_library; @@ -159,8 +160,10 @@ namespace linuxdeploy { const auto& from = pair.first; const auto& to = pair.second; - if (!copyFile(from, to)) - success = false; + if (path_contains_file(appDirPath, from)) { + success = bf::exists(to) || symlinkFile(from, to, true); // create a symbolic link + } else + success = copyFile(from, to); // copy the file copyOperations.erase(copyOperations.begin()); }