mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-29 19:07:08 +00:00
On *nix, use a realpath(3) variant (which does not expand symlinks) in NormalizePath
Before this commit, when a source file is a symlink, cquery is not able to serve LSP requests for it.
This commit is contained in:
parent
38ff70ebc3
commit
eac644d81a
@ -29,10 +29,8 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <fcntl.h> /* For O_* constants */
|
|
||||||
#include <semaphore.h>
|
#include <semaphore.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/stat.h> /* For mode constants */
|
|
||||||
|
|
||||||
#ifndef __APPLE__
|
#ifndef __APPLE__
|
||||||
#include <sys/prctl.h>
|
#include <sys/prctl.h>
|
||||||
@ -42,6 +40,73 @@
|
|||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// Returns the canonicalized absolute pathname, without expanding symbolic links.
|
||||||
|
// This is a variant of realpath(2), C++ rewrite of
|
||||||
|
// https://github.com/freebsd/freebsd/blob/master/lib/libc/stdlib/realpath.c
|
||||||
|
optional<std::string> RealPathNotExpandSymlink(std::string path) {
|
||||||
|
if (path.empty()) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return nullopt;
|
||||||
|
}
|
||||||
|
if (path[0] == '\0') {
|
||||||
|
errno = ENOENT;
|
||||||
|
return nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do not use PATH_MAX because it is tricky on Linux.
|
||||||
|
// See https://eklitzke.org/path-max-is-tricky
|
||||||
|
char tmp[1024];
|
||||||
|
std::string resolved;
|
||||||
|
size_t i = 0;
|
||||||
|
struct stat sb;
|
||||||
|
if (path[0] == '/') {
|
||||||
|
resolved = "/";
|
||||||
|
i = 1;
|
||||||
|
} else {
|
||||||
|
if (!getcwd(tmp, sizeof tmp))
|
||||||
|
return nullopt;
|
||||||
|
resolved = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (i < path.size()) {
|
||||||
|
auto j = path.find('/', i);
|
||||||
|
if (j == std::string::npos)
|
||||||
|
j = path.size();
|
||||||
|
auto next_token = path.substr(i, j - i);
|
||||||
|
i = j + 1;
|
||||||
|
if (resolved.back() != '/')
|
||||||
|
resolved += '/';
|
||||||
|
if (next_token.empty() || next_token == ".") {
|
||||||
|
// Handle consequential slashes and "."
|
||||||
|
continue;
|
||||||
|
} else if (next_token == "..") {
|
||||||
|
// Strip the last path component except when it is single "/"
|
||||||
|
if (resolved.size() > 1)
|
||||||
|
resolved.resize(resolved.rfind('/', resolved.size() - 2) + 1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Append the next path component.
|
||||||
|
// Here we differ from realpath(3), we use stat(2) instead of
|
||||||
|
// lstat(2) because we do not want to resolve symlinks.
|
||||||
|
resolved += next_token;
|
||||||
|
if (stat(resolved.c_str(), &sb) != 0)
|
||||||
|
return nullopt;
|
||||||
|
if (!S_ISDIR(sb.st_mode) && j < path.size()) {
|
||||||
|
errno = ENOTDIR;
|
||||||
|
return nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove trailing slash except when a single "/".
|
||||||
|
if (resolved.size() > 1 && resolved.back() == '/')
|
||||||
|
resolved.pop_back();
|
||||||
|
return resolved;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
struct PlatformMutexLinux : public PlatformMutex {
|
struct PlatformMutexLinux : public PlatformMutex {
|
||||||
sem_t* sem_ = nullptr;
|
sem_t* sem_ = nullptr;
|
||||||
|
|
||||||
@ -155,12 +220,8 @@ std::string GetWorkingDirectory() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string NormalizePath(const std::string& path) {
|
std::string NormalizePath(const std::string& path) {
|
||||||
errno = 0;
|
optional<std::string> resolved = RealPathNotExpandSymlink(path);
|
||||||
char name[PATH_MAX + 1];
|
return resolved ? *resolved : path;
|
||||||
(void)realpath(path.c_str(), name);
|
|
||||||
if (errno)
|
|
||||||
return path;
|
|
||||||
return name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TryMakeDirectory(const std::string& absolute_path) {
|
bool TryMakeDirectory(const std::string& absolute_path) {
|
||||||
|
Loading…
Reference in New Issue
Block a user