Verified Commit 20108549 authored by Tommaso Tocci's avatar Tommaso Tocci
Browse files

bugfix: do not always follow last link in path

when resolving path we don't want always
to resolve also the last components if it is a link. Cause in some cases
we want exactly the path of that link and not the one it points to.

lstat and readlink are some example of functions that don't want to
resolve the last link.
parent 40b06b22
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -82,9 +82,10 @@ class PreloadContext {

    RelativizeStatus relativize_fd_path(int dirfd,
                                        const char * raw_path,
                                        std::string& relative_path) const;
                                        std::string& relative_path,
                                        bool resolve_last_link = true) const;

    bool relativize_path(const char * raw_path, std::string& relative_path) const;
    bool relativize_path(const char * raw_path, std::string& relative_path, bool resolve_last_link = true) const;
    const std::shared_ptr<OpenFileMap>& file_map() const;

    void distributor(std::shared_ptr<Distributor> distributor);
+1 −1
Original line number Diff line number Diff line
#include <string>

bool resolve_path (const std::string& path, std::string& resolved);
bool resolve_path (const std::string& path, std::string& resolved, bool resolve_last_link = true);

std::string get_sys_cwd();
void set_sys_cwd(const std::string& path);
+3 −3
Original line number Diff line number Diff line
@@ -555,7 +555,7 @@ int unlink(const char* path) __THROW {
    }
    CTX->log()->trace("{}() called with path '{}'", __func__, path);
    std::string rel_path;
    if (!CTX->relativize_path(path, rel_path)) {
    if (!CTX->relativize_path(path, rel_path, false)) {
        return LIBC_FUNC(unlink, rel_path.c_str());
    }
    return adafs_rm_node(rel_path);
@@ -731,7 +731,7 @@ int lstat(const char* path, struct stat* buf) __THROW {
    }
    CTX->log()->trace("{}() called with path '{}'", __func__, path);
    std::string rel_path;
    if (!CTX->relativize_path(path, rel_path)) {
    if (!CTX->relativize_path(path, rel_path, false)) {
        return LIBC_FUNC(lstat, rel_path.c_str(), buf);
    }
    CTX->log()->warn("{}() No symlinks are supported. Stats will always target the given path", __func__);
@@ -861,7 +861,7 @@ int __lxstat(int ver, const char* path, struct stat* buf) __THROW {
    }
    CTX->log()->trace("{}() called with path '{}'", __func__, path);
    std::string rel_path;
    if (!CTX->relativize_path(path, rel_path)) {
    if (!CTX->relativize_path(path, rel_path, false)) {
        return LIBC_FUNC(__lxstat, ver, path, buf);
    }
    return adafs_stat(rel_path, buf);
+5 −4
Original line number Diff line number Diff line
@@ -56,7 +56,8 @@ const std::string& PreloadContext::cwd() const {

RelativizeStatus PreloadContext::relativize_fd_path(int dirfd,
                                                    const char * raw_path,
                                                    std::string& relative_path) const {
                                                    std::string& relative_path,
                                                    bool resolve_last_link) const {

    // Relativize path should be called only after the library constructor has been executed
    assert(initialized_);
@@ -91,13 +92,13 @@ RelativizeStatus PreloadContext::relativize_fd_path(int dirfd,
        path = raw_path;
    }

    if (resolve_path(path, relative_path)) {
    if (resolve_path(path, relative_path, resolve_last_link)) {
        return RelativizeStatus::internal;
    }
    return RelativizeStatus::external;
}

bool PreloadContext::relativize_path(const char * raw_path, std::string& relative_path) const {
bool PreloadContext::relativize_path(const char * raw_path, std::string& relative_path, bool resolve_last_link) const {
    // Relativize path should be called only after the library constructor has been executed
    assert(initialized_);
    // If we run the constructor we also already setup the mountdir
@@ -116,7 +117,7 @@ bool PreloadContext::relativize_path(const char * raw_path, std::string& relativ
    } else {
        path = raw_path;
    }
    return resolve_path(path, relative_path);
    return resolve_path(path, relative_path, resolve_last_link);
}

const std::shared_ptr<OpenFileMap>& PreloadContext::file_map() const {
+16 −1
Original line number Diff line number Diff line
@@ -48,7 +48,19 @@ unsigned int path_match_components(const std::string& path, unsigned int &path_c
    return matched;
}

bool resolve_path (const std::string& path, std::string& resolved) {
/* Resolve path to its canonical representation
 *
 * Populate `resolved` with the canonical representation of `path`.
 *
 * ".", ".." and symbolic links gets resolved.
 *
 * If `resolve_last_link` is false, the last components in path
 * won't be resolved if its a link.
 *
 * returns true if the resolved path fall inside GekkoFS namespace,
 * and false otherwise.
 */
 bool resolve_path (const std::string& path, std::string& resolved, bool resolve_last_link) {
    CTX->log()->debug("{}() path: '{}'", __func__, path);

    struct stat st;
@@ -121,6 +133,9 @@ bool resolve_path (const std::string& path, std::string& resolved) {
                return false;
            }
            if (S_ISLNK(st.st_mode)) {
                if (!resolve_last_link && end == path.size()) {
                    continue;
                }
                char link_resolved[PATH_MAX_LEN];
                if (LIBC_FUNC(realpath, resolved.c_str(), link_resolved) == nullptr) {
                    CTX->log()->error("{}() Failed to get realpath for link '{}'. Error: {}", __func__, resolved, strerror(errno));