Loading src/client/gkfs_libc.cpp +28 −20 Changes for src/client/gkfs_libc.cpp: 28 added lines, 20 removed lines. Original line number Diff line number Diff line Loading @@ -2266,22 +2266,26 @@ int symlink(const char* path1, const char* path2) throw() { gkfs_init_routine_placeholder(); if(GKFS_INTERCEPTION_ENABLED()) { std::string resolved; if(resolve_gkfs_path(AT_FDCWD, path1, resolved) == PathStatus::Internal) { DEBUG_INFO("[GKFS] path 1 internal {}", resolved); std::string resolved2; if(resolve_gkfs_path(AT_FDCWD, path2, resolved2) == PathStatus::Internal) { if(resolve_gkfs_path(AT_FDCWD, path2, resolved2) == PathStatus::Internal) { DEBUG_INFO("[GKFS] path 2 internal {}", resolved2); if(gkfs::config::metadata::symlink_support) { // In Gekko we invert the parameters. return gkfs::syscall::gkfs_mk_symlink(resolved2, resolved); } else { if(!gkfs::config::metadata::symlink_support) { DEBUG_INFO("[GKFS] symlinks not supported/compiled"); errno = ENOTSUP; return -1; } std::string resolved; if(path1 && path1[0] != '/') { std::string parent_dir = gkfs::path::dirname(resolved2); std::string abs_target = gkfs::path::prepend_path(parent_dir, path1); if(abs_target.empty() || abs_target.front() != '/') { resolved = "/" + abs_target; } else { resolved = abs_target; } return gkfs::syscall::gkfs_mk_symlink(resolved2, resolved); } else if(resolve_gkfs_path(AT_FDCWD, path1, resolved) == PathStatus::Internal) { return gkfs::syscall::gkfs_mk_symlink(resolved2, resolved); } } } Loading @@ -2293,22 +2297,26 @@ int symlinkat(const char* path1, int newdirfd, const char* path2) throw() { gkfs_init_routine_placeholder(); if(GKFS_INTERCEPTION_ENABLED()) { std::string resolved; if(resolve_gkfs_path(AT_FDCWD, path1, resolved) == PathStatus::Internal) { DEBUG_INFO("[GKFS] path 1 internal {}", resolved); std::string resolved2; if(resolve_gkfs_path(newdirfd, path2, resolved2) == PathStatus::Internal) { if(resolve_gkfs_path(newdirfd, path2, resolved2) == PathStatus::Internal) { DEBUG_INFO("[GKFS] path 2 internal {}", resolved2); if(gkfs::config::metadata::symlink_support) { // In Gekko we invert the parameters. return gkfs::syscall::gkfs_mk_symlink(resolved2, resolved); } else { if(!gkfs::config::metadata::symlink_support) { DEBUG_INFO("[GKFS] symlinks not supported/compiled"); errno = ENOTSUP; return -1; } std::string resolved; if(path1 && path1[0] != '/') { std::string parent_dir = gkfs::path::dirname(resolved2); std::string abs_target = gkfs::path::prepend_path(parent_dir, path1); if(abs_target.empty() || abs_target.front() != '/') { resolved = "/" + abs_target; } else { resolved = abs_target; } return gkfs::syscall::gkfs_mk_symlink(resolved2, resolved); } else if(resolve_gkfs_path(AT_FDCWD, path1, resolved) == PathStatus::Internal) { return gkfs::syscall::gkfs_mk_symlink(resolved2, resolved); } } } Loading src/client/gkfs_metadata.cpp +4 −14 Changes for src/client/gkfs_metadata.cpp: 4 added lines, 14 removed lines. Original line number Diff line number Diff line Loading @@ -1639,22 +1639,12 @@ gkfs_getdents64(unsigned int fd, struct linux_dirent64* dirp, */ int gkfs_mk_symlink(const std::string& path, const std::string& target_path) { /* The following check is not POSIX compliant. * In POSIX the target is not checked at all. * Here if the target is a directory we raise a NOTSUP error. * So that application know we don't support link to directory. /* In standard POSIX symlink(2), the target is arbitrary text and is not verified * at symlink creation time. Allowing directory targets enables virtual environments * (e.g. lib64 -> lib) and standard software distributions. */ auto target_md = gkfs::utils::get_metadata(target_path, false); // std::string new_path = target_path; // unused if(target_md) { auto trg_mode = target_md->mode(); if(!(S_ISREG(trg_mode) || S_ISLNK(trg_mode))) { assert(S_ISDIR(trg_mode)); LOG(DEBUG, "Target path is a directory. Not supported"); errno = ENOTSUP; return -1; } } (void) target_md; // cppcheck-suppress knownConditionTrueFalse if(check_parent_dir(path)) { Loading src/client/hooks.cpp +16 −1 Changes for src/client/hooks.cpp: 16 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -633,7 +633,22 @@ hook_symlinkat(const char* oldname, int newdfd, const char* newname) { return -ENOTSUP; } std::string oldname_resolved; if(CTX->relativize_path(oldname, oldname_resolved)) { if(oldname[0] != gkfs::path::separator) { // oldname is a relative path (e.g. 'lib' or '../target'). // POSIX resolves relative symlinks with respect to the parent // directory of the symlink (newname), NOT process CWD. std::string parent_dir = gkfs::path::dirname(newname_resolved); std::string abs_internal_target = gkfs::path::prepend_path(parent_dir, oldname); if(abs_internal_target.empty() || abs_internal_target.front() != gkfs::path::separator) { oldname_resolved = gkfs::path::separator + abs_internal_target; } else { oldname_resolved = abs_internal_target; } return with_errno(gkfs::syscall::gkfs_mk_symlink( newname_resolved, oldname_resolved)); } else if(CTX->relativize_path(oldname, oldname_resolved)) { // Source is also in GekkoFS — create symlink inside GekkoFS. return with_errno(gkfs::syscall::gkfs_mk_symlink( newname_resolved, oldname_resolved)); Loading Loading
src/client/gkfs_libc.cpp +28 −20 Changes for src/client/gkfs_libc.cpp: 28 added lines, 20 removed lines. Original line number Diff line number Diff line Loading @@ -2266,22 +2266,26 @@ int symlink(const char* path1, const char* path2) throw() { gkfs_init_routine_placeholder(); if(GKFS_INTERCEPTION_ENABLED()) { std::string resolved; if(resolve_gkfs_path(AT_FDCWD, path1, resolved) == PathStatus::Internal) { DEBUG_INFO("[GKFS] path 1 internal {}", resolved); std::string resolved2; if(resolve_gkfs_path(AT_FDCWD, path2, resolved2) == PathStatus::Internal) { if(resolve_gkfs_path(AT_FDCWD, path2, resolved2) == PathStatus::Internal) { DEBUG_INFO("[GKFS] path 2 internal {}", resolved2); if(gkfs::config::metadata::symlink_support) { // In Gekko we invert the parameters. return gkfs::syscall::gkfs_mk_symlink(resolved2, resolved); } else { if(!gkfs::config::metadata::symlink_support) { DEBUG_INFO("[GKFS] symlinks not supported/compiled"); errno = ENOTSUP; return -1; } std::string resolved; if(path1 && path1[0] != '/') { std::string parent_dir = gkfs::path::dirname(resolved2); std::string abs_target = gkfs::path::prepend_path(parent_dir, path1); if(abs_target.empty() || abs_target.front() != '/') { resolved = "/" + abs_target; } else { resolved = abs_target; } return gkfs::syscall::gkfs_mk_symlink(resolved2, resolved); } else if(resolve_gkfs_path(AT_FDCWD, path1, resolved) == PathStatus::Internal) { return gkfs::syscall::gkfs_mk_symlink(resolved2, resolved); } } } Loading @@ -2293,22 +2297,26 @@ int symlinkat(const char* path1, int newdirfd, const char* path2) throw() { gkfs_init_routine_placeholder(); if(GKFS_INTERCEPTION_ENABLED()) { std::string resolved; if(resolve_gkfs_path(AT_FDCWD, path1, resolved) == PathStatus::Internal) { DEBUG_INFO("[GKFS] path 1 internal {}", resolved); std::string resolved2; if(resolve_gkfs_path(newdirfd, path2, resolved2) == PathStatus::Internal) { if(resolve_gkfs_path(newdirfd, path2, resolved2) == PathStatus::Internal) { DEBUG_INFO("[GKFS] path 2 internal {}", resolved2); if(gkfs::config::metadata::symlink_support) { // In Gekko we invert the parameters. return gkfs::syscall::gkfs_mk_symlink(resolved2, resolved); } else { if(!gkfs::config::metadata::symlink_support) { DEBUG_INFO("[GKFS] symlinks not supported/compiled"); errno = ENOTSUP; return -1; } std::string resolved; if(path1 && path1[0] != '/') { std::string parent_dir = gkfs::path::dirname(resolved2); std::string abs_target = gkfs::path::prepend_path(parent_dir, path1); if(abs_target.empty() || abs_target.front() != '/') { resolved = "/" + abs_target; } else { resolved = abs_target; } return gkfs::syscall::gkfs_mk_symlink(resolved2, resolved); } else if(resolve_gkfs_path(AT_FDCWD, path1, resolved) == PathStatus::Internal) { return gkfs::syscall::gkfs_mk_symlink(resolved2, resolved); } } } Loading
src/client/gkfs_metadata.cpp +4 −14 Changes for src/client/gkfs_metadata.cpp: 4 added lines, 14 removed lines. Original line number Diff line number Diff line Loading @@ -1639,22 +1639,12 @@ gkfs_getdents64(unsigned int fd, struct linux_dirent64* dirp, */ int gkfs_mk_symlink(const std::string& path, const std::string& target_path) { /* The following check is not POSIX compliant. * In POSIX the target is not checked at all. * Here if the target is a directory we raise a NOTSUP error. * So that application know we don't support link to directory. /* In standard POSIX symlink(2), the target is arbitrary text and is not verified * at symlink creation time. Allowing directory targets enables virtual environments * (e.g. lib64 -> lib) and standard software distributions. */ auto target_md = gkfs::utils::get_metadata(target_path, false); // std::string new_path = target_path; // unused if(target_md) { auto trg_mode = target_md->mode(); if(!(S_ISREG(trg_mode) || S_ISLNK(trg_mode))) { assert(S_ISDIR(trg_mode)); LOG(DEBUG, "Target path is a directory. Not supported"); errno = ENOTSUP; return -1; } } (void) target_md; // cppcheck-suppress knownConditionTrueFalse if(check_parent_dir(path)) { Loading
src/client/hooks.cpp +16 −1 Changes for src/client/hooks.cpp: 16 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -633,7 +633,22 @@ hook_symlinkat(const char* oldname, int newdfd, const char* newname) { return -ENOTSUP; } std::string oldname_resolved; if(CTX->relativize_path(oldname, oldname_resolved)) { if(oldname[0] != gkfs::path::separator) { // oldname is a relative path (e.g. 'lib' or '../target'). // POSIX resolves relative symlinks with respect to the parent // directory of the symlink (newname), NOT process CWD. std::string parent_dir = gkfs::path::dirname(newname_resolved); std::string abs_internal_target = gkfs::path::prepend_path(parent_dir, oldname); if(abs_internal_target.empty() || abs_internal_target.front() != gkfs::path::separator) { oldname_resolved = gkfs::path::separator + abs_internal_target; } else { oldname_resolved = abs_internal_target; } return with_errno(gkfs::syscall::gkfs_mk_symlink( newname_resolved, oldname_resolved)); } else if(CTX->relativize_path(oldname, oldname_resolved)) { // Source is also in GekkoFS — create symlink inside GekkoFS. return with_errno(gkfs::syscall::gkfs_mk_symlink( newname_resolved, oldname_resolved)); Loading