App: handle symlinks in Application::processFiles & DocInfo::getDocPath
This commit is contained in:
committed by
Max Wilfinger
parent
a4a1ef7294
commit
79632dd3c6
@@ -925,7 +925,7 @@ Document* Application::openDocumentPrivate(const char * FileName,
|
||||
if (!File.exists()) {
|
||||
std::stringstream str;
|
||||
str << "File '" << FileName << "' does not exist!";
|
||||
throw Base::FileSystemError(str.str().c_str());
|
||||
throw Base::FileSystemError(str.str());
|
||||
}
|
||||
|
||||
// Before creating a new document we check whether the document is already open
|
||||
@@ -2803,7 +2803,18 @@ std::list<std::string> Application::processFiles(const std::list<std::string>& f
|
||||
std::list<std::string> processed;
|
||||
Base::Console().log("Init: Processing command line files\n");
|
||||
for (const auto & it : files) {
|
||||
|
||||
Base::FileInfo file(it);
|
||||
// Can we safely remove the isSymlink check and directly query the canonical
|
||||
// path for every string? The reason for avoiding it currently is that
|
||||
// getCannonicalPath will log an error if the file doesn't exist
|
||||
if (file.isSymlink()) {
|
||||
if (auto cannonicalPath = file.getCannonicalPath()) {
|
||||
file = Base::FileInfo(*cannonicalPath);
|
||||
} else {
|
||||
Base::Console().error("Failed to process symlink file: %s\n", file.filePath());
|
||||
}
|
||||
}
|
||||
|
||||
Base::Console().log("Init: Processing file: %s\n",file.filePath().c_str());
|
||||
|
||||
|
||||
@@ -3349,7 +3349,8 @@ public:
|
||||
throw Base::RuntimeError("Owner document not saved");
|
||||
}
|
||||
|
||||
QDir docDir(QFileInfo(QString::fromUtf8(docPath)).absoluteDir());
|
||||
QFileInfo docFileInfo{QString::fromUtf8(docPath)};
|
||||
QDir docDir(docFileInfo.canonicalPath());
|
||||
if (!absolute) {
|
||||
path = QDir::cleanPath(docDir.absoluteFilePath(path));
|
||||
if (fullPath) {
|
||||
|
||||
@@ -425,6 +425,16 @@ bool FileInfo::isDir() const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FileInfo::isSymlink() const
|
||||
{
|
||||
fs::path path = stringToPath(FileName);
|
||||
if (fs::exists(path)) {
|
||||
return fs::is_symlink(path);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int FileInfo::size() const
|
||||
{
|
||||
unsigned int bytes {};
|
||||
@@ -566,3 +576,24 @@ std::vector<Base::FileInfo> FileInfo::getDirectoryContent() const
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
std::optional<std::string> FileInfo::getSymlinkTarget()
|
||||
{
|
||||
fs::path path = stringToPath(FileName);
|
||||
if (isSymlink()) {
|
||||
return pathToString(fs::read_symlink(path));
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::string> FileInfo::getCannonicalPath()
|
||||
{
|
||||
try {
|
||||
fs::path path = stringToPath(FileName);
|
||||
return pathToString(fs::canonical(path));
|
||||
}
|
||||
catch (const fs::filesystem_error& e) {
|
||||
std::clog << e.what() << '\n';
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
|
||||
#include <FCGlobal.h>
|
||||
|
||||
@@ -125,6 +126,8 @@ public:
|
||||
bool isFile() const;
|
||||
/// Checks if it is a directory (not a file)
|
||||
bool isDir() const;
|
||||
/// Checks if it is a symbolic link (returns false if the file doesn't exist)
|
||||
bool isSymlink() const;
|
||||
/// The size of the file
|
||||
unsigned int size() const;
|
||||
/// Returns the time when the file was last modified.
|
||||
@@ -153,6 +156,11 @@ public:
|
||||
/// Rename the file
|
||||
bool copyTo(const char* NewName) const;
|
||||
|
||||
/// Returns the folder or directory the symlink points
|
||||
std::optional<std::string> getSymlinkTarget();
|
||||
/// Returns the absolute path without any "..", "." or symlinks
|
||||
std::optional<std::string> getCannonicalPath();
|
||||
|
||||
/** @name Tools */
|
||||
//@{
|
||||
/// Get a unique File Name in the given or (if 0) in the temp path
|
||||
|
||||
Reference in New Issue
Block a user