diff --git a/CMakeLists.txt b/CMakeLists.txt index 763873ad8..3ee6ff985 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,5 +58,35 @@ add_subdirectory(src) if (NOT DARLING_NO_EXECUTABLES) install(FILES etc/dylib.conf etc/version.conf DESTINATION libexec/darling/etc/darling) -endif (NOT DARLING_NO_EXECUTABLES) + install(FILES etc/resolv.conf + DESTINATION libexec/darling/etc) + + install(DIRECTORY DESTINATION libexec/darling/Volumes) + install(DIRECTORY DESTINATION libexec/darling/Volumes/SystemRoot) + InstallSymlink(/ ${CMAKE_INSTALL_PREFIX}/libexec/darling/Volumes/DarlingEmulatedDrive) + + install(DIRECTORY DESTINATION libexec/darling/proc) + + install(DIRECTORY DESTINATION libexec/darling/var) + install(DIRECTORY DESTINATION libexec/darling/var/root) + install(DIRECTORY DESTINATION libexec/darling/var/run) + InstallSymlink(/dev/log ${CMAKE_INSTALL_PREFIX}/libexec/darling/var/run/syslog) + install(DIRECTORY DESTINATION libexec/darling/usr) + install(DIRECTORY DESTINATION libexec/darling/usr/local) + install(DIRECTORY DESTINATION libexec/darling/usr/local/share) + InstallSymlink(/Volumes/SystemRoot${CMAKE_INSTALL_PREFIX}/share/darling ${CMAKE_INSTALL_PREFIX}/libexec/darling/usr/local/share/darling) + + InstallSymlink(/Volumes/SystemRoot/dev ${CMAKE_INSTALL_PREFIX}/libexec/darling/dev) + InstallSymlink(/Volumes/SystemRoot/tmp ${CMAKE_INSTALL_PREFIX}/libexec/darling/tmp) + InstallSymlink(/Volumes/SystemRoot/home ${CMAKE_INSTALL_PREFIX}/libexec/darling/Users) + + InstallSymlink(/proc/self/mounts ${CMAKE_INSTALL_PREFIX}/libexec/darling/etc/mtab) + InstallSymlink(/Volumes/SystemRoot/etc/passwd ${CMAKE_INSTALL_PREFIX}/libexec/darling/etc/passwd) + InstallSymlink(/Volumes/SystemRoot/etc/group ${CMAKE_INSTALL_PREFIX}/libexec/darling/etc/group) + + install(DIRECTORY DESTINATION libexec/darling/etc/ld.so.conf.d) + install(CODE "execute_process(COMMAND bash ${DARLING_TOP_DIRECTORY}/src/setup-ld-so.sh WORKING_DIRECTORY ${CMAKE_INSTALL_PREFIX}/libexec/darling)") + InstallSymlink(/Volumes/SystemRoot/lib ${CMAKE_INSTALL_PREFIX}/libexec/darling/lib) + InstallSymlink(/Volumes/SystemRoot/lib64 ${CMAKE_INSTALL_PREFIX}/libexec/darling/lib64) +endif (NOT DARLING_NO_EXECUTABLES) diff --git a/README.md b/README.md index bac675712..3079e153f 100644 --- a/README.md +++ b/README.md @@ -61,15 +61,6 @@ make make install ```` -To build the new, experimental `darling` executable: - -```` -cmake ../.. -DCMAKE_TOOLCHAIN_FILE=../../Toolchain-x86_64.cmake -DNEW_DARLING=TRUE -make -make install -chmod +s $(which darling) -```` - #### For running i386 OS X binaries diff --git a/etc/resolv.conf b/etc/resolv.conf new file mode 100644 index 000000000..276c26b19 --- /dev/null +++ b/etc/resolv.conf @@ -0,0 +1,2 @@ +nameserver 8.8.8.8 +nameserver 8.8.4.4 diff --git a/src/darling-config.h.in b/src/darling-config.h.in index 300b6c22c..dac3e069b 100644 --- a/src/darling-config.h.in +++ b/src/darling-config.h.in @@ -9,6 +9,8 @@ #define DYLD_PATH "${CMAKE_INSTALL_PREFIX}/bin/dyld" #define ETC_DARLING_PATH "/etc/darling" +// Path where the system root gets "mounted" inside the prefix +#define SYSTEM_ROOT "/Volumes/SystemRoot" #cmakedefine MULTILIB #cmakedefine FRAMEWORK_COREAUDIO @@ -17,7 +19,7 @@ #ifndef __APPLE__ /* - * Credit: + * Credit: * * David Chisnall * http://comments.gmane.org/gmane.comp.desktop.etoile.devel/1556 diff --git a/src/dyld/CMakeLists.txt b/src/dyld/CMakeLists.txt index 4ad381afa..91716bb40 100644 --- a/src/dyld/CMakeLists.txt +++ b/src/dyld/CMakeLists.txt @@ -37,21 +37,14 @@ add_executable(dyld-bin ${dyld_SRCS}) set_target_properties(dyld-bin PROPERTIES OUTPUT_NAME dyld${SUFFIX}) target_link_libraries(dyld-bin dyld darling-util mach-o) -if (NEW_DARLING) - add_executable(darling darling.c) -endif (NEW_DARLING) +add_executable(darling darling.c) if (NOT DARLING_NO_EXECUTABLES) add_executable(dyldd dyldd.cpp) target_link_libraries(dyldd dyld darling-util mach-o) install(TARGETS dyldd DESTINATION bin) - if (NEW_DARLING) - install(TARGETS darling DESTINATION bin) - else (NEW_DARLING) - install(PROGRAMS darling DESTINATION bin - PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ - GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) - endif(NEW_DARLING) + install(TARGETS darling DESTINATION bin + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE SETUID) add_library(dexe_startup STATIC darling-so-start.S) endif (NOT DARLING_NO_EXECUTABLES) @@ -62,5 +55,3 @@ if (BITS EQUAL 64) set_target_properties(dyld-multilib PROPERTIES OUTPUT_NAME dyld) install(TARGETS dyld-multilib DESTINATION bin) endif (BITS EQUAL 64) - - diff --git a/src/dyld/darling b/src/dyld/darling deleted file mode 100755 index 2e2f24af6..000000000 --- a/src/dyld/darling +++ /dev/null @@ -1,236 +0,0 @@ -#!/bin/bash -# -# This file is part of Darling. -# -# Copyright (C) 2015 Lubos Dolezel -# -# Darling is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Darling is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Darling. If not, see . -# - -export PATH="/bin:/sbin:/usr/bin:/usr/local/bin" - -SCRIPT=$(readlink -f "$0") -SCRIPTPATH=$(dirname "$SCRIPT") -DARLING_PREFIX=$(realpath "$SCRIPTPATH/..") - -selfmtime=$(stat -c %Y "$DARLING_PREFIX/bin/darling") - -check_prefix() { - - if [ ! -d "$DPREFIX" -o ! -f "$DPREFIX/.update-timestamp" ]; then - setup_prefix "$DPREFIX" - else - - updatets=$(cat $DPREFIX/.update-timestamp) - case $updatets in - disable*) - ;; - ''|*[!0-9]*) - setup_prefix "$DPREFIX" - ;; - *) - [ $updatets -lt $selfmtime ] && setup_prefix "$DPREFIX" - ;; - esac - - return 0 - fi -} - -setup_prefix() { - prefix_pkg="/tmp/prefix.$$.pkg" - - >&2 echo "Setting up prefix at $1" - >&2 echo - - mkdir -p "$1" - rm -f "$1/darling-prefix" - - rm -f "$1/system-root" - ln -s / "$1/system-root" - - rm -f "$1/darling-prefix" - ln -s "system-root${DARLING_PREFIX}" "$1/darling-prefix" - - rm -f "$1/dev" - ln -sf "system-root/dev" "$1/dev" - - rm -f "$1/home" - ln -sf "system-root/home" "$1/home" - - rm -f "$1/Users" - ln -sf "home" "$1/Users" - - rm -f "$1/tmp" - ln -sf "system-root/tmp" "$1/tmp" - - rm -f "$1/etc" 2>/dev/null || true - mkdir -p "$1/etc" - ln -sf "../system-root/etc/timezone" "$1/etc/timezone" - ln -sf "../system-root/etc/resolv.conf" "$1/etc/resolv.conf" - ln -sf "../system-root/etc/passwd" "$1/etc/passwd" - ln -sf "../system-root/etc/group" "$1/etc/group" - ln -sf "../system-root/etc/hosts" "$1/etc/hosts" - ln -sf "../system-root/etc/localtime" "$1/etc/localtime" || true - - mkdir -p "$1/usr/share" - rm -f "$1/usr/share/zoneinfo" 2>/dev/null || true - ln -sf "../../system-root/usr/share/zoneinfo" "$1/usr/share/zoneinfo" - - mkdir -p "$1/Volumes" "$1/Applications" "$1/var/root" || true - mkdir -p "$1/var/run" || true - ln -sf "../../system-root/dev/log" "$1/var/run/syslog" || true - - # Clean up old cruft (symlinks) - rm -f "$1/bin" "$1/usr/bin" "$1/etc" "$1/System/Library/Frameworks" "$1/System/Library/PrivateFrameworks" 2>/dev/null || true - cp -rf "${DARLING_PREFIX}/libexec/darling/"* "$1" - echo -n "$selfmtime" > "$1/.update-timestamp" - - install_pkg "org.darlinghq.pkg.OpenSSLCertificates" - - >&2 echo "Building manpage database..." - "${dexec_path}" "${DPREFIX}/bin/bash" -c "/usr/libexec/makewhatis" - - >&2 echo "Prefix is ready." -} - -install_pkg() { - temp="/tmp/pkgs.$$" - mkdir "$temp" || true - - >&2 echo "Getting latest version of $1..." - version=$(wget "http://packages.darlinghq.org/${1}/latest.txt" -O- 2>/dev/null) - pkgpath="$temp/${1}-${version}.pkg" - - >&2 echo "Downloading $1 (version $version)..." - wget "http://packages.darlinghq.org/${1}/${1}-${version}.pkg" -O "$pkgpath" 2>/dev/null - - "${DARLING_PREFIX}/libexec/darling/usr/bin/installer" -pkg "/system-root${pkgpath}" -target / - - rm -rf "$temp" -} - -is_sudo_allowed() { - if type -p sudo &> /dev/null; then - sudo -nl "$@" &> /dev/null && return 0 - fi - return 1 -} - -launch_with_su() { - if [ "$(id -u)" = 0 ]; then - "$@" - elif is_sudo_allowed; then - sudo "$@" - else - local cmd=$(printf '%q ' "$@") - su --shell=$BASH --command "$cmd" - fi -} - -darling_check() { - # Returning values: - # 0: module is loaded, file permissions are good - # 1: module is loaded, file permissions are wrong - # 2: module is not loaded - grep -q darling_mach "/proc/modules" - if [ $? -eq 0 ]; then - [ -r "/dev/mach" -a -w "/dev/mach" ] && return 0 || return 1 - else - return 2 - fi -} - -darling_load() { - if $(darling_check); then - >&2 echo "Module is already loaded." - else - >&2 echo -n "Loading module... " - launch_with_su modprobe darling-mach && >&2 echo "Done." || >&2 echo "Fail." - sleep 1 # Wait for module loading - launch_with_su chmod a+rw "/dev/mach" - fi - -} - -darling_unload() { - if $(darling_check); then - >&2 echo -n "Unloading module... " - launch_with_su rmmod darling-mach && >&2 echo "Done." || >&2 echo "Fail." - else - >&2 echo "Module is not loaded, so it can't be unloaded." - fi -} - -if [ $# -eq 0 ]; then - >&2 echo "This is Darling, a runtime environment for OS X applications." - >&2 echo - >&2 echo "Copyright (C) 2012-2015 Lubos Dolezel" - >&2 echo "Includes software components which are Copyright (C) Apple Computer, Inc. and many others." - >&2 echo - >&2 echo -e "Usage:\tdarling PROGRAM [ARGUMENTS...]\tRun the specified program" - >&2 echo -e "\tdarling shell\t\t\tStart bash shell in prefix" - #>&2 echo -e "\tdarling hdiutil\t\t\tMount DMG disk images" - #>&2 echo -e "\tdarling pkgutil\t\t\tInstall PKG packages" - >&2 echo -e "\tdarling load\t\t\tLoad kernel module" - >&2 echo -e "\tdarling unload\t\t\tUnload kernel module" - >&2 echo - >&2 echo "The prefix is specified by the DPREFIX environment variable." - >&2 echo "The default DPREFIX is \$HOME/.darling" - exit 1 -fi - -set -e - -if [ -z "$DPREFIX" ]; then - export DPREFIX="$HOME/.darling" -fi - -if ! $(darling_check) && [ "$1" != "load" ] && [ "$1" != "unload" ]; then - 2>&1 echo "Cannot open /dev/mach, running 'darling load'." - darling_load -fi - -dexec_path="${0%darling}dyld" -#dexec_path="${DARLING_PREFIX}/bin/darling-exec" - -case "$1" in -"shell") - check_prefix - - if [ $# -gt 1 ]; then - exec "${dexec_path}" "${DPREFIX}/bin/bash" -c "${*:2}" - else - exec "${dexec_path}" "${DPREFIX}/bin/bash" - fi - ;; -#"hdiutil") -# exec "${DPREFIX}/usr/bin/hdiutil" "${@:2}" -# exit $? -# ;; -#"pkgutil") -# >2& echo "Not implemented yet" -# exit 1 -# ;; -"load") - darling_load - ;; -"unload") - darling_unload - ;; -*) - check_prefix - exec "${dexec_path}" "$1" "${@:2}" - ;; -esac diff --git a/src/dyld/darling-so-start.S b/src/dyld/darling-so-start.S index d63900bdf..a8fc8f847 100644 --- a/src/dyld/darling-so-start.S +++ b/src/dyld/darling-so-start.S @@ -3,7 +3,13 @@ .text +// For running executables from inside the prefix dyld_path: +.ascii SYSTEM_ROOT +.string DYLD_PATH + +// Additionally, we support running them from the host system +dyld_host_path: .string DYLD_PATH proc_self_exe: @@ -56,6 +62,17 @@ strcat_end: movl $__NR_execve, %eax syscall + // If we failed to find dyld under the system root, + // try again without it + leaq dyld_host_path(%rip), %rdi // exec path + movq %rsp, %rsi // argv + movl 0(%rsp), %ecx // argc + leaq 16(%rsp, %rcx, 8), %rdx // envp + movq %rdi, (%rsi) // overwrite argc with dyld_path + + movl $__NR_execve, %eax + syscall + fail: movl $2, %edi leaq failure_msg(%rip), %rsi @@ -64,4 +81,3 @@ fail: syscall ud2 - diff --git a/src/dyld/darling.c b/src/dyld/darling.c index c9186ea38..af02a81a5 100644 --- a/src/dyld/darling.c +++ b/src/dyld/darling.c @@ -37,8 +37,6 @@ along with Darling. If not, see . #include "darling.h" #include "darling-config.h" -// Path where the system root gets "mounted" inside the prefix -#define SYSTEM_ROOT "/system-root" const char* DARLING_INIT_COMM = "darling-init"; char *prefix; @@ -47,7 +45,6 @@ uid_t g_originalUid, g_originalGid; int main(int argc, const char** argv) { pid_t pidInit, pidChild; - char path[4096]; int wstatus; if (argc <= 1) @@ -73,7 +70,7 @@ int main(int argc, const char** argv) prefix = defaultPrefixPath(); if (!prefix) return 1; - setenv("DPREFIX", prefix, 0); + unsetenv("DPREFIX"); if (!checkPrefixDir()) setupPrefix(); @@ -81,6 +78,21 @@ int main(int argc, const char** argv) pidInit = getInitProcess(); + if (strcmp(argv[1], "shutdown") == 0) + { + if (pidInit == 0) + { + fprintf(stderr, "Darling container is not running\n"); + return 1; + } + + // TODO: when we have a working launchd, + // this is where we ask it to shut down nicely + + kill(pidInit, SIGKILL); + return 0; + } + // If prefix's init is not running, start it up if (pidInit == 0) { @@ -91,19 +103,35 @@ int main(int argc, const char** argv) if (strcmp(argv[1], "shell") != 0) { + char *path = realpath(argv[1], NULL); + char *fullPath; + + if (path == NULL) + { + fprintf(stderr, "Cannot resolve path: %s\n", strerror(errno)); + exit(1); + } + const char *argv_child[argc + 1]; - argv_child[0] = "dyld"; - for (int i = 1; i < argc; i++) + argv_child[0] = SYSTEM_ROOT DYLD_PATH; + + fullPath = malloc(strlen(SYSTEM_ROOT) + strlen(path) + 1); + strcpy(fullPath, SYSTEM_ROOT); + strcat(fullPath, path); + argv_child[1] = fullPath; + + for (int i = 2; i < argc; i++) argv_child[i] = argv[i]; argv_child[argc] = NULL; - pidChild = spawnChild(pidInit, DYLD_PATH, argv_child); + pidChild = spawnChild(pidInit, SYSTEM_ROOT DYLD_PATH, argv_child); + free(path); + free(fullPath); } else { // Spawn the shell - snprintf(path, sizeof(path), "%s/bin/bash", prefix); if (argc > 2) { size_t total_len = 0; @@ -118,12 +146,12 @@ int main(int argc, const char** argv) // Overwrite the last whitespace *(to - 1) = '\0'; - pidChild = spawnChild(pidInit, DYLD_PATH, - (const char *[5]) {"dyld", path, "-c", buffer, NULL}); + pidChild = spawnChild(pidInit, SYSTEM_ROOT DYLD_PATH, + (const char *[5]) {SYSTEM_ROOT DYLD_PATH, "/bin/bash", "-c", buffer, NULL}); } else - pidChild = spawnChild(pidInit, DYLD_PATH, - (const char *[3]) {"dyld", path, NULL}); + pidChild = spawnChild(pidInit, SYSTEM_ROOT DYLD_PATH, + (const char *[3]) {SYSTEM_ROOT DYLD_PATH, "/bin/bash", NULL}); } // Drop the privileges so that we can be killed, etc by the user @@ -197,23 +225,27 @@ pid_t spawnChild(int pidInit, const char *path, const char *const argv[]) } close(fdNS); - snprintf(pathNS, sizeof(pathNS), "/proc/%d/ns/user", pidInit); + /* + snprintf(pathNS, sizeof(pathNS), SYSTEM_ROOT "/proc/%d/ns/user", pidInit); fdNS = open(pathNS, O_RDONLY); if (fdNS < 0) { fprintf(stderr, "Cannot open user namespace file: %s\n", strerror(errno)); exit(1); } + */ setresuid(g_originalUid, g_originalUid, g_originalUid); setresgid(g_originalGid, g_originalGid, g_originalGid); + /* if (setns(fdNS, CLONE_NEWUSER) != 0) { fprintf(stderr, "Cannot join user namespace: %s\n", strerror(errno)); exit(1); } close(fdNS); + */ setupChild(curPath); @@ -231,7 +263,17 @@ void setupChild(const char *curPath) char buffer1[4096]; char buffer2[4096]; - setenv("PATH", "/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin", 1); + setenv("PATH", + "/usr/bin:" + "/bin:" + "/usr/sbin:" + "/sbin:" + "/usr/local/bin", + 1); + + setenv("LD_LIBRARY_PATH", + SYSTEM_ROOT LIB_PATH, + 1); sscanf(getenv("HOME"), "/home/%4096s", buffer1); snprintf(buffer2, sizeof(buffer2), "/Users/%s", buffer1); @@ -242,16 +284,12 @@ void setupChild(const char *curPath) // We're currently inside our home directory snprintf(buffer2, sizeof(buffer2), "/Users/%s", buffer1); setenv("PWD", buffer2, 1); - - snprintf(buffer2, sizeof(buffer2), "%s/Users/%s", prefix, buffer1); chdir(buffer2); } else { snprintf(buffer2, sizeof(buffer2), SYSTEM_ROOT "%s", curPath); setenv("PWD", buffer2, 1); - - snprintf(buffer2, sizeof(buffer2), "%s" SYSTEM_ROOT "%s", prefix, curPath); chdir(buffer2); } } @@ -288,7 +326,7 @@ pid_t spawnInitProcess(void) { pid_t pid; int pipefd[2]; - char idmap[100]; + // char idmap[100]; char buffer[1]; FILE *file; @@ -317,6 +355,7 @@ pid_t spawnInitProcess(void) // The child char *opts; + char putOld[4096]; // Since overlay cannot be mounted inside user namespaces, we have to setup a new mount namespace // and do the mount while we can be root @@ -334,7 +373,7 @@ pid_t spawnInitProcess(void) exit(1); } - opts = (char*) malloc(strlen(prefix)*2 + sizeof(LIBEXEC_PATH) + 50); + opts = (char*) malloc(strlen(prefix)*2 + sizeof(LIBEXEC_PATH) + 100); sprintf(opts, "lowerdir=%s,upperdir=%s,workdir=%s.workdir", LIBEXEC_PATH, prefix, prefix); // Mount overlay onto our prefix @@ -346,6 +385,21 @@ pid_t spawnInitProcess(void) free(opts); + snprintf(putOld, sizeof(putOld), "%s" SYSTEM_ROOT, prefix); + + if (syscall(SYS_pivot_root, prefix, putOld) != 0) + { + fprintf(stderr, "Cannot pivot_root: %s\n", strerror(errno)); + exit(1); + } + + // mount procfs for our new PID namespace + if (mount("proc", "/proc", "proc", 0, "") != 0) + { + fprintf(stderr, "Cannot mount procfs: %s\n", strerror(errno)); + exit(1); + } + // Drop the privileges setresuid(g_originalUid, g_originalUid, g_originalUid); setresgid(g_originalGid, g_originalGid, g_originalGid); @@ -353,13 +407,15 @@ pid_t spawnInitProcess(void) prctl(PR_SET_NAME, DARLING_INIT_COMM, 0, 0); + /* if (unshare(CLONE_NEWUSER) != 0) { fprintf(stderr, "Cannot unshare user namespace: %s\n", strerror(errno)); exit(1); } + */ - // Tell the parent we're ready for it to set up UID/GID mappings + // Tell the parent we're ready write(pipefd[1], buffer, 1); close(pipefd[1]); // And wait for it to do it @@ -374,6 +430,7 @@ pid_t spawnInitProcess(void) read(pipefd[0], buffer, 1); close(pipefd[0]); + /* snprintf(idmap, sizeof(idmap), "/proc/%d/uid_map", pid); file = fopen(idmap, "w"); @@ -399,6 +456,7 @@ pid_t spawnInitProcess(void) { fprintf(stderr, "Cannot set gid_map for the init process: %s\n", strerror(errno)); } + */ // Resume the child write(pipefd[1], buffer, 1); @@ -552,53 +610,21 @@ void setupPrefix() createDir(prefix); - snprintf(path, sizeof(path), "%s" SYSTEM_ROOT, prefix); - if (symlink("/", path) != 0) - { - fprintf(stderr, "Cannot symlink %s: %s\n", path, strerror(errno)); - exit(1); - } - - snprintf(path, sizeof(path), "%s/dev", prefix); - if (symlink(SYSTEM_ROOT "/dev" + 1, path) != 0) - { - fprintf(stderr, "Cannot symlink %s: %s\n", path, strerror(errno)); - exit(1); - } - - snprintf(path, sizeof(path), "%s/tmp", prefix); - if (symlink(SYSTEM_ROOT "/tmp" + 1, path) != 0) - { - fprintf(stderr, "Cannot symlink %s: %s\n", path, strerror(errno)); - exit(1); - } - - snprintf(path, sizeof(path), "%s/Users", prefix); - if (symlink(SYSTEM_ROOT "/home" + 1, path) != 0) - { - fprintf(stderr, "Cannot symlink %s: %s\n", path, strerror(errno)); - exit(1); - } - + // The user needs to be able to create mountpoints, snprintf(path, sizeof(path), "%s/Volumes", prefix); createDir(path); + // ... to install applications, snprintf(path, sizeof(path), "%s/Applications", prefix); createDir(path); - snprintf(path, sizeof(path), "%s/var", prefix); + // ... and to put stuff in /usr/local + snprintf(path, sizeof(path), "%s/usr", prefix); createDir(path); - snprintf(path, sizeof(path), "%s/var/root", prefix); + snprintf(path, sizeof(path), "%s/usr/local", prefix); createDir(path); - snprintf(path, sizeof(path), "%s/var/run", prefix); + snprintf(path, sizeof(path), "%s/usr/local/share", prefix); createDir(path); - snprintf(path, sizeof(path), "%s/var/run/syslog", prefix); - if (symlink("../.." SYSTEM_ROOT "/dev/log", path) != 0) - { - fprintf(stderr, "Cannot symlink %s: %s\n", path, strerror(errno)); - exit(1); - } - seteuid(0); setegid(0); } diff --git a/src/dyld/dirstructure.cpp b/src/dyld/dirstructure.cpp index 92b338d2f..1948f5ea5 100644 --- a/src/dyld/dirstructure.cpp +++ b/src/dyld/dirstructure.cpp @@ -33,12 +33,11 @@ static std::string GetUserLibrary() std::stringstream ss; std::string path; - prefix = getenv("DPREFIX"); home = getenv("HOME"); - if (!prefix || !home) + if (!home) return std::string(); // give up on this user - ss << prefix << home << '/' << "Library" << '/'; + ss << home << '/' << "Library" << '/'; return ss.str(); } diff --git a/src/dyld/dyld.cpp b/src/dyld/dyld.cpp index 274f9bef5..82ffe3faa 100644 --- a/src/dyld/dyld.cpp +++ b/src/dyld/dyld.cpp @@ -32,7 +32,6 @@ along with Darling. If not, see . #include #include #include "dirstructure.h" -#include #include #include #include @@ -52,16 +51,16 @@ int main(int argc, char** argv, char** envp) printHelp(argv[0]); return 1; } - + if (!HasUserDirectoryStructure()) SetupUserDirectoryStructure(); try { MachOMgr* mgr = MachOMgr::instance(); - std::string executable, unprefixed_argv0; + std::string executable; const char* pretendArgv0; - + pretendArgv0 = findFakeArgv0(argv[1]); executable = locateBundleExecutable(argv[1]); @@ -89,12 +88,7 @@ int main(int argc, char** argv, char** envp) mgr->setSysRoot(path); if (const char* path = getenv("DYLD_TRAMPOLINE")) mgr->setUseTrampolines(true, path); - if (const char* path = getenv("DPREFIX")) - { - __prefix_set(path); - unprefixed_argv0 = __prefix_untranslate_path(argv[1], strlen(argv[1])); - } - + if (getenv("DYLD_GDBJIT") != nullptr) Darling::SetupGDBJIT(); @@ -115,14 +109,12 @@ int main(int argc, char** argv, char** envp) if (pretendArgv0 != nullptr) argv[1] = (char*) pretendArgv0; - else if (!unprefixed_argv0.empty()) - argv[1] = (char*) unprefixed_argv0.c_str(); exit(main(argc-1, &argv[1], envp)); } else { MachOObject* obj; - + if (::mmap(0, 4096, PROT_READ|PROT_EXEC, MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) != 0) { if (errno == EPERM) @@ -138,12 +130,10 @@ int main(int argc, char** argv, char** envp) throw std::runtime_error("This is not a Mach-O executable; dynamic libraries, " "kernel extensions and other Mach-O files cannot be executed with dyld"); } - + if (pretendArgv0 != nullptr) argv[1] = (char*) pretendArgv0; - else if (!unprefixed_argv0.empty()) - argv[1] = (char*) unprefixed_argv0.c_str(); - + obj->setCommandLine(argc-1, &argv[1], envp); obj->load(); @@ -161,12 +151,12 @@ static std::string pathToSelf() { char buf[4096]; int rd; - + rd = readlink("/proc/self/exe", buf, sizeof(buf)-1); if (rd <= 0) return std::string(); buf[rd] = 0; - + return std::string(buf); } @@ -201,9 +191,9 @@ static std::string locateBundleExecutable(std::string bundlePath) { std::regex re(".*/([^\\.]+)\\.app/?$", std::regex::icase); std::smatch match; - + std::string myBundlePath = "./" + bundlePath; // TODO: fix the regexp to work without this - + if (std::regex_match(myBundlePath, match, re)) { std::stringstream ss; @@ -245,7 +235,7 @@ static bool isELF(const char* path) static const char* findFakeArgv0(char* a0) { char* excl; - + excl = strchr(a0, '!'); if (excl == nullptr) return nullptr; diff --git a/src/dyld/dyldd.cpp b/src/dyld/dyldd.cpp index 7d2e30a43..ccc9a743f 100644 --- a/src/dyld/dyldd.cpp +++ b/src/dyld/dyldd.cpp @@ -28,7 +28,6 @@ along with Darling. If not, see . #include #include #include -#include #define ANSI_COLOR_RED "\x1b[31m" #define ANSI_COLOR_GREEN "\x1b[32m" @@ -49,27 +48,25 @@ int main(int argc, char** argv, char** envp) { if (argc != 2 || strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0) showHelp(argv[0]); - + try { MachOObject* obj; std::set deps; MachOMgr* mgr = MachOMgr::instance(); - + mgr->detectSysRootFromPath(argv[1]); - if (const char* path = getenv("DPREFIX")) - __prefix_set(path); - + mgr->setLoadAnyArchitecture(true); - - obj = new MachOObject(__prefix_translate_path(argv[1])); - + + obj = new MachOObject(argv[1]); + mgr->add(obj, true); - + std::cout << c(ANSI_COLOR_GRAY) << "Resolving dependencies of " << obj->path() << "\n\n" << c(ANSI_COLOR_RESET); - + resolve(obj, deps); - + mgr->remove(obj); } catch (const std::exception& e) @@ -85,37 +82,37 @@ void resolve(MachOObject* obj, std::set& deps) { LoadableObject* dep; std::string dylib = d.name; - + if (dylib.empty()) continue; - + std::string path = DylibSearch::instance()->resolve(dylib, obj); if (path.empty()) { if (deps.find(dylib) == deps.end()) { deps.insert(dylib); - + std::cout << dylib << " => " << c(ANSI_COLOR_RED) << "not found" << c(ANSI_COLOR_RESET) << std::endl; } - + continue; } dep = LoadableObject::instantiateForPath(path, obj); - + if (deps.find(dep->path()) != deps.end()) { dep->delRef(); continue; } - + deps.insert(dep->path()); - + if (MachOObject* mach = dynamic_cast(dep)) { std::cout << dylib << " => " << c(ANSI_COLOR_BLUE) << dep->path() << c(ANSI_COLOR_RESET) << std::endl; - + resolve(mach, deps); } else @@ -135,7 +132,7 @@ void showHelp(const char* argv0) std::cerr << "Copyright (C) 2012-2014 Lubos Dolezel\n\n"; std::cerr << "Usage: " << argv0 << " executable\n\n"; std::cerr << "If your terminal supports colors, then native dependencies are " << c(ANSI_COLOR_GREEN) << "green" << c(ANSI_COLOR_RESET) - << " and Mach-O dependencies are " << c(ANSI_COLOR_BLUE) << "blue" << c(ANSI_COLOR_RESET) << ".\n"; - + << " and Mach-O dependencies are " << c(ANSI_COLOR_BLUE) << "blue" << c(ANSI_COLOR_RESET) << ".\n"; + exit(1); } diff --git a/src/kernel/emulation/linux/dirent/getdirentries.c b/src/kernel/emulation/linux/dirent/getdirentries.c index 8df6a895e..048003043 100644 --- a/src/kernel/emulation/linux/dirent/getdirentries.c +++ b/src/kernel/emulation/linux/dirent/getdirentries.c @@ -3,7 +3,6 @@ #include "../errno.h" #include #include -#include extern __SIZE_TYPE__ strlen(const char* s); extern char* strcpy(char* dest, const char* src); @@ -51,10 +50,7 @@ long sys_getdirentries(int fd, char* ibuf, unsigned int len, long* basep) bsd->d_ino = l64->d_ino; bsd->d_type = l64->d_type; strcpy(bsd->d_name, l64->d_name); - - if (strcmp(l64->d_name, __SYSTEM_ROOT+1) == 0) - bsd->d_type = DT_DIR; - + bsd->d_reclen = sizeof(struct bsd_dirent) + slen + 1; bsd->d_namlen = slen; @@ -97,10 +93,7 @@ long sys_getdirentries64(int fd, char* ibuf, unsigned int len, long* basep) bsd->d_ino = l64->d_ino; bsd->d_type = l64->d_type; strcpy(bsd->d_name, l64->d_name); - - if (strcmp(l64->d_name, __SYSTEM_ROOT+1) == 0) - bsd->d_type = DT_DIR; - + bsd->d_reclen = sizeof(struct bsd_dirent64) + slen + 1; bsd->d_namlen = slen; bsd->d_seekoff = 0; diff --git a/src/kernel/emulation/linux/fcntl/open.c b/src/kernel/emulation/linux/fcntl/open.c index 90a17ce2e..51ac4ba7c 100644 --- a/src/kernel/emulation/linux/fcntl/open.c +++ b/src/kernel/emulation/linux/fcntl/open.c @@ -4,7 +4,6 @@ #include //#include "../../../../platform-include/sys/fcntl.h" #include "../../../../libc/include/fcntl.h" -#include #ifndef O_NOFOLLOW # define O_NOFOLLOW 0x0100 @@ -40,8 +39,7 @@ long sys_open_nocancel(const char* filename, int flags, unsigned int mode) if (strcmp(filename, "/dev/random") == 0) filename = "/dev/urandom"; - ret = LINUX_SYSCALL(__NR_open, __prefix_translate_path(filename), - linux_flags, mode); + ret = LINUX_SYSCALL(__NR_open, filename, linux_flags, mode); if (ret < 0) ret = errno_linux_to_bsd(ret); diff --git a/src/kernel/emulation/linux/misc/sysctl.c b/src/kernel/emulation/linux/misc/sysctl.c index f452bb449..ded019ba8 100644 --- a/src/kernel/emulation/linux/misc/sysctl.c +++ b/src/kernel/emulation/linux/misc/sysctl.c @@ -7,7 +7,6 @@ #include #include #include "../../../../../platform-include/sys/errno.h" -#include "../../../../libdyld/VirtualPrefix.h" #include "sysctl_inc.h" #include #include @@ -58,7 +57,7 @@ long sys_sysctl(int* name, unsigned int nlen, void* old, { return sysctl_name_to_oid((const char*) _new, (int*) old, oldlen); } - + if (name[0] == CTL_HW) { int* ovalue = (int*) old; @@ -89,7 +88,7 @@ long sys_sysctl(int* name, unsigned int nlen, void* old, if (*oldlen < sizeof(int)) return -EINVAL; *oldlen = sizeof(int); - + switch (name[1]) { case HW_AVAILCPU: @@ -257,7 +256,7 @@ static void need_uname(void) if (!lu.sysname[0]) { __linux_uname(&lu); - version_conf = iniconfig_load(__prefix_translate_path(ETC_DARLING_PATH "/version.conf")); + version_conf = iniconfig_load(ETC_DARLING_PATH "/version.conf"); if (version_conf != NULL) version_conf_sect = iniconfig_getsection(version_conf, "uname"); } @@ -278,7 +277,7 @@ static long sysctl_name_to_oid(const char* name, int* oid_name, { const char* dot; unsigned long cat_len; - + if (*oid_len < 2) return -EINVAL; @@ -292,7 +291,7 @@ static long sysctl_name_to_oid(const char* name, int* oid_name, { oid_name[0] = CTL_HW; *oid_len = 2 * sizeof(int); - + if (strcmp(dot+1, "activecpu") == 0) oid_name[1] = HW_AVAILCPU; else if (strcmp(dot+1, "ncpu") == 0) @@ -317,7 +316,7 @@ static long sysctl_name_to_oid(const char* name, int* oid_name, oid_name[1] = _HW_CPUTHREADTYPE; else return -ENOTDIR; - + return 0; } else if (strncmp(name, "kern", cat_len) == 0) @@ -336,4 +335,3 @@ static long sysctl_name_to_oid(const char* name, int* oid_name, __simple_printf("Unknown sysctl: %s\n", name); return -ENOTDIR; } - diff --git a/src/kernel/emulation/linux/process/execve.c b/src/kernel/emulation/linux/process/execve.c index 6564d8fef..5da29b25c 100644 --- a/src/kernel/emulation/linux/process/execve.c +++ b/src/kernel/emulation/linux/process/execve.c @@ -9,7 +9,6 @@ #include #include #include -#include #define MH_MAGIC 0xfeedface #define MH_CIGAM 0xcefaedfe @@ -40,11 +39,11 @@ long sys_execve(char* fname, char** argvp, char** envp) uint32_t magic; char magic_array[256]; } m; - + // Ideally, if everybody used binfmt_misc to allow direct // execution of Mach-O binaries under Darling, this wouldn't // be necessary. But we cannot rely on that. - + fd = sys_open(fname, BSD_O_RDONLY, 0); if (fd < 0) return fd; @@ -52,41 +51,6 @@ long sys_execve(char* fname, char** argvp, char** envp) ret = sys_read(fd, m.magic_array, sizeof(m.magic_array)); if (ret < 4) goto no_macho; - - if (__prefix_get() != NULL) - { - // Inject DPREFIX if DPREFIX is missing - int i; - bool has_dprefix = false; - char** new_envp; - - for (i = 0; envp[i] != NULL; i++) - { - if (strncmp(envp[i], "DPREFIX=", 8) == 0) - { - has_dprefix = true; - break; - } - } - - if (!has_dprefix) - { - char* dprefix; - - new_envp = (char**) __builtin_alloca(sizeof(char*) * (i+1)); - dprefix = (char*) __builtin_alloca(strlen(__prefix_get()) + 9); - - for (i = 0; envp[i] != NULL; i++) - new_envp[i] = envp[i]; - - strcpy(dprefix, "DPREFIX="); - strcat(dprefix, __prefix_get()); - new_envp[i++] = dprefix; - new_envp[i] = NULL; - - envp = new_envp; - } - } if (m.magic == MH_MAGIC || m.magic == MH_CIGAM || m.magic == MH_MAGIC_64 || m.magic == MH_CIGAM_64 @@ -95,11 +59,12 @@ long sys_execve(char* fname, char** argvp, char** envp) // It is a Mach-O file int len, i; char** modargvp; - char *translated, *buf; - - len = __prefix_get_dyld_path(dyld_path, sizeof(dyld_path)-1); + char *buf; + + len = LINUX_SYSCALL(__NR_readlink, "/proc/self/exe", dyld_path, sizeof(dyld_path)-1); if (len < 0) goto no_macho; + dyld_path[len] = '\0'; // Remove 64 or 32 suffix if present if (strcmp(&dyld_path[len - 2], "32") == 0 @@ -117,11 +82,10 @@ long sys_execve(char* fname, char** argvp, char** envp) // Allocate a new argvp, execute dyld_path modargvp = (char**) __builtin_alloca(sizeof(void*) * (len+1)); modargvp[0] = dyld_path; - - translated = (char*) __prefix_translate_path_link(fname); - buf = __builtin_alloca(strlen(translated) + 2 + strlen(argvp[0])); - - strcpy(buf, translated); + + buf = __builtin_alloca(strlen(fname) + 2 + strlen(argvp[0])); + + strcpy(buf, fname); strcat(buf, "!"); strcat(buf, argvp[0]); modargvp[1] = buf; @@ -132,65 +96,6 @@ long sys_execve(char* fname, char** argvp, char** envp) argvp = modargvp; fname = dyld_path; } - else if (__prefix_get() != NULL) - { - // shebang handling... - if (m.magic_array[0] == '#' && m.magic_array[1] == '!') - { - char *nl, *interp, *arg; - char** modargvp; - int i, j, len = 0; - - nl = memchr(m.magic_array, '\n', sizeof(m.magic_array)); - if (nl == NULL) - goto no_macho; - - *nl = '\0'; - - for (i = 2; isspace(m.magic_array[i]); i++); - - interp = &m.magic_array[i]; - - for (i = 0; !isspace(interp[i]) && interp[i]; i++); - - if (interp[i] == '\0') - arg = NULL; - else - arg = &interp[i]; - - if (arg != NULL) - { - *arg = '\0'; // terminate interp - while (isspace(*arg)) - arg++; - if (*arg == '\0') - arg = NULL; // no argument, just whitespace - } - - // Count original arguments - while (argvp[len++]); - - // Allocate a new argvp - modargvp = (char**) __builtin_alloca(sizeof(void*) * (len+2)); - - i = 0; - modargvp[i++] = interp; - if (arg != NULL) - modargvp[i++] = arg; - modargvp[i] = fname; - - // Append original arguments - for (j = 1; j < len+1; j++) - modargvp[i+j] = argvp[j]; - - argvp = modargvp; - fname = (char*) __prefix_translate_path(modargvp[0]); - } - else - { - fname = (char*) __prefix_translate_path(fname); - } - } no_macho: sys_close(fd); @@ -201,4 +106,3 @@ long sys_execve(char* fname, char** argvp, char** envp) return ret; } - diff --git a/src/kernel/emulation/linux/stat/lstat.c b/src/kernel/emulation/linux/stat/lstat.c index 79c0a6644..2feb363f0 100644 --- a/src/kernel/emulation/linux/stat/lstat.c +++ b/src/kernel/emulation/linux/stat/lstat.c @@ -3,7 +3,6 @@ #include "../base.h" #include "../errno.h" #include -#include long sys_lstat(const char* path, struct stat* stat) { @@ -11,15 +10,13 @@ long sys_lstat(const char* path, struct stat* stat) struct linux_stat lstat; #ifdef __NR_lstat64 - ret = LINUX_SYSCALL(__NR_lstat64, __prefix_translate_path_link(path), &lstat); + ret = LINUX_SYSCALL(__NR_lstat64, path, &lstat); #else - ret = LINUX_SYSCALL(__NR_lstat, __prefix_translate_path_link(path), &lstat); + ret = LINUX_SYSCALL(__NR_lstat, path, &lstat); #endif if (ret < 0) return errno_linux_to_bsd(ret); - else if (__prefix_is_system_root(path)) - lstat.st_mode = (lstat.st_mode & ~0120000) | 0040000; // make directory stat_linux_to_bsd(&lstat, stat); @@ -32,18 +29,15 @@ long sys_lstat64(const char* path, struct stat64* stat) struct linux_stat lstat; #ifdef __NR_lstat64 - ret = LINUX_SYSCALL(__NR_lstat64, __prefix_translate_path_link(path), &lstat); + ret = LINUX_SYSCALL(__NR_lstat64, path, &lstat); #else - ret = LINUX_SYSCALL(__NR_lstat, __prefix_translate_path_link(path), &lstat); + ret = LINUX_SYSCALL(__NR_lstat, path, &lstat); #endif if (ret < 0) return errno_linux_to_bsd(ret); - else if (__prefix_is_system_root(path)) - lstat.st_mode = (lstat.st_mode & ~0120000) | 0040000; // make directory stat_linux_to_bsd64(&lstat, stat); return 0; } - diff --git a/src/kernel/emulation/linux/stat/mkdir.c b/src/kernel/emulation/linux/stat/mkdir.c index 28e2fab1c..2cd1964d8 100644 --- a/src/kernel/emulation/linux/stat/mkdir.c +++ b/src/kernel/emulation/linux/stat/mkdir.c @@ -3,17 +3,15 @@ #include "../base.h" #include "../errno.h" #include -#include long sys_mkdir(const char* path, unsigned int mode) { int ret; - ret = LINUX_SYSCALL(__NR_mkdir, __prefix_translate_path(path), mode); + ret = LINUX_SYSCALL(__NR_mkdir, path, mode); if (ret < 0) return errno_linux_to_bsd(ret); return 0; } - diff --git a/src/kernel/emulation/linux/stat/mkfifo.c b/src/kernel/emulation/linux/stat/mkfifo.c index 986d8b965..a106f4b3c 100644 --- a/src/kernel/emulation/linux/stat/mkfifo.c +++ b/src/kernel/emulation/linux/stat/mkfifo.c @@ -3,7 +3,6 @@ #include "../base.h" #include "../errno.h" #include -#include #define LINUX_S_IFIFO 0010000 @@ -11,12 +10,10 @@ long sys_mkfifo(const char* path, unsigned int mode) { int ret; - ret = LINUX_SYSCALL(__NR_mknod, __prefix_translate_path(path), - mode | LINUX_S_IFIFO, 0); + ret = LINUX_SYSCALL(__NR_mknod, path, mode | LINUX_S_IFIFO, 0); if (ret < 0) return errno_linux_to_bsd(ret); return 0; } - diff --git a/src/kernel/emulation/linux/stat/rmdir.c b/src/kernel/emulation/linux/stat/rmdir.c index aa7325662..2e6e30180 100644 --- a/src/kernel/emulation/linux/stat/rmdir.c +++ b/src/kernel/emulation/linux/stat/rmdir.c @@ -3,17 +3,15 @@ #include "../base.h" #include "../errno.h" #include -#include long sys_rmdir(const char* path) { int ret; - ret = LINUX_SYSCALL(__NR_rmdir, __prefix_translate_path(path)); + ret = LINUX_SYSCALL(__NR_rmdir, path); if (ret < 0) return errno_linux_to_bsd(ret); return 0; } - diff --git a/src/kernel/emulation/linux/stat/stat.c b/src/kernel/emulation/linux/stat/stat.c index f7cf8c980..24bbbabdd 100644 --- a/src/kernel/emulation/linux/stat/stat.c +++ b/src/kernel/emulation/linux/stat/stat.c @@ -3,7 +3,6 @@ #include "../base.h" #include "../errno.h" #include -#include long sys_stat(const char* path, struct stat* stat) { @@ -11,15 +10,13 @@ long sys_stat(const char* path, struct stat* stat) struct linux_stat lstat; #ifdef __NR_stat64 - ret = LINUX_SYSCALL(__NR_stat64, __prefix_translate_path(path), &lstat); + ret = LINUX_SYSCALL(__NR_stat64, path, &lstat); #else - ret = LINUX_SYSCALL(__NR_stat, __prefix_translate_path(path), &lstat); + ret = LINUX_SYSCALL(__NR_stat, path, &lstat); #endif if (ret < 0) return errno_linux_to_bsd(ret); - else if (__prefix_is_system_root(path)) - lstat.st_mode = (lstat.st_mode & ~0120000) | 0040000; // make directory stat_linux_to_bsd(&lstat, stat); @@ -32,18 +29,15 @@ long sys_stat64(const char* path, struct stat64* stat) struct linux_stat lstat; #ifdef __NR_stat64 - ret = LINUX_SYSCALL(__NR_stat64, __prefix_translate_path(path), &lstat); + ret = LINUX_SYSCALL(__NR_stat64, path, &lstat); #else - ret = LINUX_SYSCALL(__NR_stat, __prefix_translate_path(path), &lstat); + ret = LINUX_SYSCALL(__NR_stat, path, &lstat); #endif if (ret < 0) return errno_linux_to_bsd(ret); - else if (__prefix_is_system_root(path)) - lstat.st_mode = (lstat.st_mode & ~0120000) | 0040000; // make directory stat_linux_to_bsd64(&lstat, stat); return 0; } - diff --git a/src/kernel/emulation/linux/time/utimes.c b/src/kernel/emulation/linux/time/utimes.c index e50270a28..7b4cd0cca 100644 --- a/src/kernel/emulation/linux/time/utimes.c +++ b/src/kernel/emulation/linux/time/utimes.c @@ -2,7 +2,6 @@ #include "../base.h" #include "../errno.h" #include -#include long sys_utimes(const char* path, struct bsd_timeval* tv) { @@ -14,10 +13,9 @@ long sys_utimes(const char* path, struct bsd_timeval* tv) ltv[1].tv_sec = tv[1].tv_sec; ltv[1].tv_usec = tv[1].tv_usec; - ret = LINUX_SYSCALL(__NR_utimes, __prefix_translate_path(path), ltv); + ret = LINUX_SYSCALL(__NR_utimes, path, ltv); if (ret < 0) ret = errno_linux_to_bsd(ret); return ret; } - diff --git a/src/kernel/emulation/linux/unistd/access.c b/src/kernel/emulation/linux/unistd/access.c index ce35b9491..3147793c5 100644 --- a/src/kernel/emulation/linux/unistd/access.c +++ b/src/kernel/emulation/linux/unistd/access.c @@ -2,17 +2,15 @@ #include "../base.h" #include "../errno.h" #include -#include long sys_access(const char* filename, int amode) { int ret; #ifdef __NR_access - ret = LINUX_SYSCALL(__NR_access, __prefix_translate_path(filename), amode); + ret = LINUX_SYSCALL(__NR_access, filename, amode); #else - ret = LINUX_SYSCALL(__NR_faccessat, LINUX_AT_FDCWD, - __prefix_translate_path(filename), amode, 0); + ret = LINUX_SYSCALL(__NR_faccessat, LINUX_AT_FDCWD, filename, amode, 0); #endif if (ret < 0) @@ -20,4 +18,3 @@ long sys_access(const char* filename, int amode) return ret; } - diff --git a/src/kernel/emulation/linux/unistd/chdir.c b/src/kernel/emulation/linux/unistd/chdir.c index 0df7a5099..eaae78c53 100644 --- a/src/kernel/emulation/linux/unistd/chdir.c +++ b/src/kernel/emulation/linux/unistd/chdir.c @@ -2,20 +2,13 @@ #include "../base.h" #include "../errno.h" #include -#include -long sys_chdir(const char* in_path) +long sys_chdir(const char* path) { int ret; - const char* path; - - path = __prefix_translate_path(in_path); ret = LINUX_SYSCALL(__NR_chdir, path); if (ret < 0) ret = errno_linux_to_bsd(ret); - else - __prefix_cwd(in_path); return ret; } - diff --git a/src/kernel/emulation/linux/unistd/chmod.c b/src/kernel/emulation/linux/unistd/chmod.c index d03e5a128..33e465575 100644 --- a/src/kernel/emulation/linux/unistd/chmod.c +++ b/src/kernel/emulation/linux/unistd/chmod.c @@ -2,16 +2,14 @@ #include "../base.h" #include "../errno.h" #include -#include long sys_chmod(const char* path, int mode) { int ret; - ret = LINUX_SYSCALL(__NR_chmod, __prefix_translate_path(path), mode); + ret = LINUX_SYSCALL(__NR_chmod, path, mode); if (ret < 0) ret = errno_linux_to_bsd(ret); return ret; } - diff --git a/src/kernel/emulation/linux/unistd/chmod_extended.c b/src/kernel/emulation/linux/unistd/chmod_extended.c index dd14ddb4f..5222cf237 100644 --- a/src/kernel/emulation/linux/unistd/chmod_extended.c +++ b/src/kernel/emulation/linux/unistd/chmod_extended.c @@ -2,23 +2,18 @@ #include "../base.h" #include "../errno.h" #include -#include long sys_chmod_extended(const char* path, int uid, int gid, int mode, void* xsec) { int ret; - const char* xpath; - - xpath = __prefix_translate_path(path); - ret = LINUX_SYSCALL(__NR_chmod, xpath, mode); + ret = LINUX_SYSCALL(__NR_chmod, path, mode); if (ret < 0) return errno_linux_to_bsd(ret); - - ret = LINUX_SYSCALL(__NR_chown, xpath, uid, gid); + + ret = LINUX_SYSCALL(__NR_chown, path, uid, gid); if (ret < 0) return errno_linux_to_bsd(ret); - + return ret; } - diff --git a/src/kernel/emulation/linux/unistd/chown.c b/src/kernel/emulation/linux/unistd/chown.c index fc6cbbf57..434f976e7 100644 --- a/src/kernel/emulation/linux/unistd/chown.c +++ b/src/kernel/emulation/linux/unistd/chown.c @@ -2,20 +2,18 @@ #include "../base.h" #include "../errno.h" #include -#include long sys_chown(const char* path, int uid, int gid) { int ret; #ifdef __NR_chown32 - ret = LINUX_SYSCALL(__NR_chown32, __prefix_translate_path(path), uid, gid); + ret = LINUX_SYSCALL(__NR_chown32, path, uid, gid); #else - ret = LINUX_SYSCALL(__NR_chown, __prefix_translate_path(path), uid, gid); + ret = LINUX_SYSCALL(__NR_chown, path, uid, gid); #endif if (ret < 0) ret = errno_linux_to_bsd(ret); return ret; } - diff --git a/src/kernel/emulation/linux/unistd/chroot.c b/src/kernel/emulation/linux/unistd/chroot.c index 5dd533c4a..0ac296e70 100644 --- a/src/kernel/emulation/linux/unistd/chroot.c +++ b/src/kernel/emulation/linux/unistd/chroot.c @@ -2,18 +2,14 @@ #include "../base.h" #include "../errno.h" #include -#include long sys_chroot(const char* path) { int ret; - // TODO: should we support chroot with virtual prefixes? - - ret = LINUX_SYSCALL(__NR_chroot, __prefix_translate_path(path)); + ret = LINUX_SYSCALL(__NR_chroot, path); if (ret < 0) ret = errno_linux_to_bsd(ret); return ret; } - diff --git a/src/kernel/emulation/linux/unistd/fchdir.c b/src/kernel/emulation/linux/unistd/fchdir.c index 69cdfe190..19ae2e92b 100644 --- a/src/kernel/emulation/linux/unistd/fchdir.c +++ b/src/kernel/emulation/linux/unistd/fchdir.c @@ -2,7 +2,6 @@ #include "../base.h" #include "../errno.h" #include -#include long sys_fchdir(int fd) { @@ -11,9 +10,6 @@ long sys_fchdir(int fd) ret = LINUX_SYSCALL1(__NR_fchdir, fd); if (ret < 0) ret = errno_linux_to_bsd(ret); - else - __prefix_cwd_fd(fd); return ret; } - diff --git a/src/kernel/emulation/linux/unistd/lchown.c b/src/kernel/emulation/linux/unistd/lchown.c index 6ad3441ff..a190fc55f 100644 --- a/src/kernel/emulation/linux/unistd/lchown.c +++ b/src/kernel/emulation/linux/unistd/lchown.c @@ -2,20 +2,18 @@ #include "../base.h" #include "../errno.h" #include -#include long sys_lchown(const char* path, int uid, int gid) { int ret; #ifdef __NR_chown32 - ret = LINUX_SYSCALL(__NR_lchown32, __prefix_translate_path_link(path), uid, gid); + ret = LINUX_SYSCALL(__NR_lchown32, path, uid, gid); #else - ret = LINUX_SYSCALL(__NR_lchown, __prefix_translate_path_link(path), uid, gid); + ret = LINUX_SYSCALL(__NR_lchown, path, uid, gid); #endif if (ret < 0) ret = errno_linux_to_bsd(ret); return ret; } - diff --git a/src/kernel/emulation/linux/unistd/link.c b/src/kernel/emulation/linux/unistd/link.c index 073c8896f..e1338495f 100644 --- a/src/kernel/emulation/linux/unistd/link.c +++ b/src/kernel/emulation/linux/unistd/link.c @@ -2,7 +2,6 @@ #include "../base.h" #include "../errno.h" #include -#include #include "../../../../../platform-include/sys/errno.h" extern char* strcpy(char* dst, const char* src); @@ -10,19 +9,10 @@ extern char* strcpy(char* dst, const char* src); long sys_link(const char* path, const char* link) { int ret; - char resolved_path[1024]; - char resolved_link[1024]; - - if (!path || !link) - return -EINVAL; - strcpy(resolved_path, __prefix_translate_path(path)); - strcpy(resolved_link, __prefix_translate_path(link)); - - ret = LINUX_SYSCALL(__NR_link, resolved_path, resolved_link); + ret = LINUX_SYSCALL(__NR_link, path, link); if (ret < 0) ret = errno_linux_to_bsd(ret); return ret; } - diff --git a/src/kernel/emulation/linux/unistd/mknod.c b/src/kernel/emulation/linux/unistd/mknod.c index 221d6d13c..4a1ac2878 100644 --- a/src/kernel/emulation/linux/unistd/mknod.c +++ b/src/kernel/emulation/linux/unistd/mknod.c @@ -2,16 +2,14 @@ #include "../base.h" #include "../errno.h" #include -#include long sys_mknod(const char* path, int mode, int dev) { int ret; - ret = LINUX_SYSCALL(__NR_mknod, __prefix_translate_path(path), mode, dev); + ret = LINUX_SYSCALL(__NR_mknod, path, mode, dev); if (ret < 0) ret = errno_linux_to_bsd(ret); return ret; } - diff --git a/src/kernel/emulation/linux/unistd/readlink.c b/src/kernel/emulation/linux/unistd/readlink.c index 5491d0e22..430d31dd6 100644 --- a/src/kernel/emulation/linux/unistd/readlink.c +++ b/src/kernel/emulation/linux/unistd/readlink.c @@ -2,7 +2,6 @@ #include "../base.h" #include "../errno.h" #include -#include extern __SIZE_TYPE__ strlen(const char* str); @@ -10,22 +9,9 @@ long sys_readlink(const char* path, char* buf, int count) { int ret; - ret = LINUX_SYSCALL(__NR_readlink, __prefix_translate_path_link(path), - buf, count); + ret = LINUX_SYSCALL(__NR_readlink, path, buf, count); if (ret < 0) ret = errno_linux_to_bsd(ret); - /*else - { - const char* xl; - __SIZE_TYPE__ newlen; - - xl = __prefix_untranslate_path(buf, ret); - newlen = strlen(xl); - - memcpy(buf, xl, (newlen < count) ? newlen : count); - ret = newlen; - }*/ return ret; } - diff --git a/src/kernel/emulation/linux/unistd/rename.c b/src/kernel/emulation/linux/unistd/rename.c index d99a7d82a..242647f4b 100644 --- a/src/kernel/emulation/linux/unistd/rename.c +++ b/src/kernel/emulation/linux/unistd/rename.c @@ -3,27 +3,17 @@ #include "../errno.h" #include #include "../../../../../platform-include/sys/errno.h" -#include extern char* strcpy(char* dst, const char* src); long sys_rename(const char* oldpath, const char* newpath) { int ret; - char resolved_oldpath[1024]; - char resolved_newpath[1024]; - - if (!oldpath || !newpath) - return -EINVAL; - strcpy(resolved_oldpath, __prefix_translate_path(oldpath)); - strcpy(resolved_newpath, __prefix_translate_path(newpath)); - - ret = LINUX_SYSCALL(__NR_rename, resolved_oldpath, resolved_newpath); + ret = LINUX_SYSCALL(__NR_rename, oldpath, newpath); if (ret < 0) return errno_linux_to_bsd(ret); return 0; } - diff --git a/src/kernel/emulation/linux/unistd/symlink.c b/src/kernel/emulation/linux/unistd/symlink.c index 1b4b0abf8..2de0c051b 100644 --- a/src/kernel/emulation/linux/unistd/symlink.c +++ b/src/kernel/emulation/linux/unistd/symlink.c @@ -2,7 +2,6 @@ #include "../base.h" #include "../errno.h" #include -#include #include "../../../../../platform-include/sys/errno.h" extern char* strcpy(char* dst, const char* src); @@ -10,19 +9,10 @@ extern char* strcpy(char* dst, const char* src); long sys_symlink(const char* path, const char* link) { int ret; - //char resolved_path[1024]; - char resolved_link[1024]; - - if (!path || !link) - return -EINVAL; - - //strcpy(resolved_path, __prefix_translate_path(path)); - strcpy(resolved_link, __prefix_translate_path_link(link)); - ret = LINUX_SYSCALL(__NR_symlink, path, resolved_link); + ret = LINUX_SYSCALL(__NR_symlink, path, link); if (ret < 0) ret = errno_linux_to_bsd(ret); return ret; } - diff --git a/src/kernel/emulation/linux/unistd/truncate.c b/src/kernel/emulation/linux/unistd/truncate.c index c1489289a..95f12cc7d 100644 --- a/src/kernel/emulation/linux/unistd/truncate.c +++ b/src/kernel/emulation/linux/unistd/truncate.c @@ -2,22 +2,18 @@ #include "../base.h" #include "../errno.h" #include -#include long sys_truncate(const char* path, long long length) { int ret; #ifdef __NR_truncate64 - ret = LINUX_SYSCALL(__NR_truncate64, __prefix_translate_path(path), - LL_ARG(length)); + ret = LINUX_SYSCALL(__NR_truncate64, path, LL_ARG(length)); #else - ret = LINUX_SYSCALL(__NR_truncate, __prefix_translate_path(path), - LL_ARG(length)); + ret = LINUX_SYSCALL(__NR_truncate, path, LL_ARG(length)); #endif if (ret < 0) ret = errno_linux_to_bsd(ret); return ret; } - diff --git a/src/kernel/emulation/linux/unistd/unlink.c b/src/kernel/emulation/linux/unistd/unlink.c index d644d8e2e..278120e50 100644 --- a/src/kernel/emulation/linux/unistd/unlink.c +++ b/src/kernel/emulation/linux/unistd/unlink.c @@ -2,16 +2,14 @@ #include "../base.h" #include "../errno.h" #include -#include long sys_unlink(const char* path) { int ret; - ret = LINUX_SYSCALL(__NR_unlink, __prefix_translate_path_link(path)); + ret = LINUX_SYSCALL(__NR_unlink, path); if (ret < 0) ret = errno_linux_to_bsd(ret); return ret; } - diff --git a/src/kernel/emulation/linux/xattr/getxattr.c b/src/kernel/emulation/linux/xattr/getxattr.c index 0f2c578c8..6a28dbb0e 100644 --- a/src/kernel/emulation/linux/xattr/getxattr.c +++ b/src/kernel/emulation/linux/xattr/getxattr.c @@ -3,7 +3,6 @@ #include "../errno.h" #include "../../../../../platform-include/sys/errno.h" #include -#include #define XATTR_NOFOLLOW 1 @@ -11,20 +10,17 @@ long sys_getxattr(const char* path, const char* name, char* value, unsigned long size, unsigned int pos, int options) { int ret; - + if (pos != 0) return -ERANGE; if (options & XATTR_NOFOLLOW) - ret = LINUX_SYSCALL(__NR_lgetxattr, __prefix_translate_path(path), - name, value, size); + ret = LINUX_SYSCALL(__NR_lgetxattr, path, name, value, size); else - ret = LINUX_SYSCALL(__NR_getxattr, __prefix_translate_path(path), - name, value, size); + ret = LINUX_SYSCALL(__NR_getxattr, path, name, value, size); if (ret < 0) return errno_linux_to_bsd(ret); return 0; } - diff --git a/src/kernel/emulation/linux/xattr/listxattr.c b/src/kernel/emulation/linux/xattr/listxattr.c index e4358db8d..f7eacc39a 100644 --- a/src/kernel/emulation/linux/xattr/listxattr.c +++ b/src/kernel/emulation/linux/xattr/listxattr.c @@ -2,7 +2,6 @@ #include "../base.h" #include "../errno.h" #include -#include #define XATTR_NOFOLLOW 1 @@ -11,15 +10,12 @@ long sys_listxattr(const char* path, char* namebuf, unsigned long size, int opti int ret; if (options & XATTR_NOFOLLOW) - ret = LINUX_SYSCALL(__NR_llistxattr, __prefix_translate_path(path), - namebuf, size); + ret = LINUX_SYSCALL(__NR_llistxattr, path, namebuf, size); else - ret = LINUX_SYSCALL(__NR_listxattr, __prefix_translate_path(path), - namebuf, size); + ret = LINUX_SYSCALL(__NR_listxattr, path, namebuf, size); if (ret < 0) return errno_linux_to_bsd(ret); return ret; } - diff --git a/src/kernel/emulation/linux/xattr/removexattr.c b/src/kernel/emulation/linux/xattr/removexattr.c index 942af579e..5e0373de7 100644 --- a/src/kernel/emulation/linux/xattr/removexattr.c +++ b/src/kernel/emulation/linux/xattr/removexattr.c @@ -2,7 +2,6 @@ #include "../base.h" #include "../errno.h" #include -#include #define XATTR_NOFOLLOW 1 @@ -11,15 +10,12 @@ long sys_removexattr(const char* path, const char* name, int options) int ret; if (options & XATTR_NOFOLLOW) - ret = LINUX_SYSCALL(__NR_lremovexattr, __prefix_translate_path(path), - name); + ret = LINUX_SYSCALL(__NR_lremovexattr, path, name); else - ret = LINUX_SYSCALL(__NR_removexattr, __prefix_translate_path(path), - name); + ret = LINUX_SYSCALL(__NR_removexattr, path, name); if (ret < 0) return errno_linux_to_bsd(ret); return ret; } - diff --git a/src/kernel/emulation/linux/xattr/setxattr.c b/src/kernel/emulation/linux/xattr/setxattr.c index 72c069636..17d7d007c 100644 --- a/src/kernel/emulation/linux/xattr/setxattr.c +++ b/src/kernel/emulation/linux/xattr/setxattr.c @@ -3,7 +3,6 @@ #include "../errno.h" #include "../../../../../platform-include/sys/errno.h" #include -#include #define XATTR_NOFOLLOW 1 @@ -17,13 +16,11 @@ long sys_setxattr(const char* path, const char* name, const void* value, if (options & XATTR_NOFOLLOW) { - ret = LINUX_SYSCALL(__NR_lsetxattr, __prefix_translate_path(path), - name, value, size); + ret = LINUX_SYSCALL(__NR_lsetxattr, path, name, value, size); } else { - ret = LINUX_SYSCALL(__NR_setxattr, __prefix_translate_path(path), - name, value, size); + ret = LINUX_SYSCALL(__NR_setxattr, path, name, value, size); } if (ret < 0) @@ -31,4 +28,3 @@ long sys_setxattr(const char* path, const char* name, const void* value, return ret; } - diff --git a/src/libdyld/CMakeLists.txt b/src/libdyld/CMakeLists.txt index edbcf6223..cff3f2ef8 100644 --- a/src/libdyld/CMakeLists.txt +++ b/src/libdyld/CMakeLists.txt @@ -31,7 +31,7 @@ set(dyld_SRCS dyld_priv.cpp dl_public.cpp binfmt_misc.cpp - + MachOObject.cpp LoadableObject.cpp NativeObject.cpp @@ -39,7 +39,6 @@ set(dyld_SRCS DylibSearch.cpp environ.c threads.cpp - VirtualPrefix.cpp gdbjit.cpp ) @@ -63,7 +62,7 @@ set(dyld_SRCS SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/darling") #SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--enable-new-dtags") -SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) +SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) set_source_files_properties(environ.c COMPILE_FLAGS "-no-integrated-as") @@ -72,5 +71,3 @@ add_library(dyld SHARED ${dyld_SRCS}) target_link_libraries(dyld PRIVATE -ldl -lpthread mach-o darling-util) install(TARGETS dyld DESTINATION ${CMAKE_INSTALL_LIBDIR}/darling) - - diff --git a/src/libdyld/DylibSearch.cpp b/src/libdyld/DylibSearch.cpp index 12bcbd215..3c9169800 100644 --- a/src/libdyld/DylibSearch.cpp +++ b/src/libdyld/DylibSearch.cpp @@ -23,7 +23,6 @@ along with Darling. If not, see . #include #include "MachOObject.h" #include "MachOMgr.h" -#include "VirtualPrefix.h" //#include "DummyObject.h" #include #include @@ -39,10 +38,7 @@ DylibSearch::DylibSearch() { try { - if (__prefix_get() != nullptr) - m_config = new IniConfig(__prefix_translate_path(ETC_DARLING_PATH "/dylib.conf")); - else - m_config = new IniConfig(LIBEXEC_PATH ETC_DARLING_PATH "/dylib.conf"); + m_config = new IniConfig(ETC_DARLING_PATH "/dylib.conf"); } catch (const std::exception& e) { @@ -85,10 +81,10 @@ std::string DylibSearch::resolve(std::string dylib, MachOObject* requester) if (dylib.compare(0, 16, "@executable_path") == 0) { MachOObject* mainModule = MachOMgr::instance()->mainModule(); - + if (!mainModule) throw std::runtime_error("Cannot resolve @executable_path without a main module"); - + dylib.replace(0, 16, mainModule->directory()); } else if (dylib.compare(0, 12, "@loader_path") == 0) @@ -100,34 +96,34 @@ std::string DylibSearch::resolve(std::string dylib, MachOObject* requester) return resolveViaRpath(dylib, requester); } } - + // Search in configuration if (const char* aliasTarget = resolveAlias(dylib)) { std::string p; - + if (!strchr(aliasTarget, '/')) { - p = LIB_PATH; + p = SYSTEM_ROOT LIB_PATH; p += '/'; p += aliasTarget; // std::cout << p << std::endl; } - + return p; } - + // Search in extra paths std::string epath; epath = resolveInPathList(dylib, m_extraPaths); if (!epath.empty()) return epath; - + // Search in DYLD_LIBRARY_PATH epath = resolveInLdPath(dylib); if (!epath.empty()) return epath; - + // Try the path as is epath = checkPresence(dylib); if (!epath.empty()) @@ -136,8 +132,7 @@ std::string DylibSearch::resolve(std::string dylib, MachOObject* requester) // If absolute, search in sysroot if (dylib[0] == '/') { - const char* prefix = __prefix_get(); - + if (!MachOMgr::instance()->sysRoot().empty()) { std::vector roots = string_explode(MachOMgr::instance()->sysRoot(), ':'); @@ -145,10 +140,7 @@ std::string DylibSearch::resolve(std::string dylib, MachOObject* requester) for (const std::string& in_path : roots) { std::string path; - - if (prefix != nullptr) - path = prefix; - + path += in_path; path += '/'; path += dylib; @@ -158,20 +150,11 @@ std::string DylibSearch::resolve(std::string dylib, MachOObject* requester) return epath; } } - if (prefix != nullptr) - { - std::string path = prefix; - path += dylib; - - epath = checkPresence(path); - if (!epath.empty()) - return epath; - } } - + /*if (MachOMgr::instance()->ignoreMissingDependencies()) { - + }*/ return std::string(); @@ -180,23 +163,23 @@ std::string DylibSearch::resolve(std::string dylib, MachOObject* requester) std::string DylibSearch::checkPresence(const std::string& path) { std::string str = path; - + if (::access(str.c_str(), F_OK) == 0) return str; - + str += ".dylib"; - + if (::access(str.c_str(), F_OK) == 0) return str; - + for (const std::string& suffix : m_suffixes) { str = path + suffix; - + if (::access(str.c_str(), F_OK) == 0) return str; } - + return std::string(); } @@ -209,20 +192,16 @@ std::string DylibSearch::resolveInLdPath(std::string name) return std::string(); elems = string_explode(name, ':'); - + return resolveInPathList(name, elems); } std::string DylibSearch::resolveInPathList(std::string name, const std::vector& paths) { - const char* prefix = __prefix_get(); for (const std::string& e : paths) { std::string path; - - if (prefix) - path = prefix; - + path += e + "/" + name; if (::access(path.c_str(), F_OK) == 0) @@ -249,38 +228,38 @@ const char* DylibSearch::resolveAlias(const std::string& library) if (std::regex_match(library, match, m_reFrameworkPath)) { std::string name, version; - + name = match[1]; version = match[2]; - + if (m_config->hasSection(name)) { const IniConfig::ValueMap* m = m_config->getSection(name); auto it = m->find(version); - + if (it != m->end()) return it->second.c_str(); } } - + if (std::regex_match(library, match, m_reDefaultFrameworkPath)) { std::string name; - + name = match[1]; - + if (m_config->hasSection(name)) { const IniConfig::ValueMap* m = m_config->getSection(name); auto it = m->find("default"); - + if (it != m->end()) return it->second.c_str(); else return m->begin()->second.c_str(); } } - + return nullptr; } @@ -301,14 +280,14 @@ std::string DylibSearch::resolveViaRpath(std::string name, MachOObject* requeste { std::string expanded = name; std::string result; - + expanded.replace(0, 6, rpath); if (print) std::cerr << "dyld: Expanding \"" << name << "\" -> \"" << expanded << "\"\n"; result = resolve(expanded, requester); - + if (!result.empty()) { if (print) @@ -321,7 +300,7 @@ std::string DylibSearch::resolveViaRpath(std::string name, MachOObject* requeste std::cerr << "dyld: @rpath expansion not successful\n"; } } - + return std::string(); } @@ -329,13 +308,13 @@ std::string DylibSearch::realpath(const std::string& path) { char* real; std::string rv; - + real = ::realpath(path.c_str(), nullptr); - + if (real) { rv = real; - + free(real); return rv; } diff --git a/src/libdyld/VirtualPrefix.cpp b/src/libdyld/VirtualPrefix.cpp deleted file mode 100644 index 4bb71254d..000000000 --- a/src/libdyld/VirtualPrefix.cpp +++ /dev/null @@ -1,523 +0,0 @@ -/* -This file is part of Darling. - -Copyright (C) 2015 Lubos Dolezel - -Darling is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -Darling is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Darling. If not, see . -*/ - -#include "darling-config.h" -#include "VirtualPrefix.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static std::string g_prefix; -static std::list g_prefixComponents; -static std::string g_cwd; -static pthread_rwlock_t g_cwdLock = PTHREAD_RWLOCK_INITIALIZER; -static const char SYSTEM_ROOT[] = __SYSTEM_ROOT; - -static std::list explode_path(const std::string& path); -static std::string join_path(const std::list& path_components); - -static std::list& canonicalize_path(std::list& path_components); -static std::string resolve_path(std::list& path_components, bool symlink); -static const char* translate_path_common(const char* path, bool symlink); - -void __prefix_set(const char* path) -{ - char cwd[256]; - size_t pos = 0, last_pos; - - getcwd(cwd, sizeof(cwd)); - - assert(path[0] == '/'); - assert(g_prefix.empty()); - - g_prefix = path; - g_prefixComponents.clear(); - - while (pos != std::string::npos) - { - size_t len; - last_pos = pos + 1; - - pos = g_prefix.find('/', last_pos); - len = (pos == std::string::npos) ? pos : (pos - last_pos); - g_prefixComponents.push_back(g_prefix.substr(last_pos, len)); - } - - if (g_prefix[g_prefix.length()-1] != '/') - g_prefix += '/'; - - if (strncmp(cwd, path, strlen(path)) == 0) - { - g_cwd = cwd + strlen(path); - if (g_cwd.empty() || g_cwd[g_cwd.length()-1] != '/') - g_cwd += "/"; - } - else - { - g_cwd = SYSTEM_ROOT; - g_cwd += cwd; - g_cwd += '/'; - } - - // std::cout << "### Prefix initialized with cwd " << g_cwd << " from " << cwd << std::endl; -} - -const char* __prefix_get(void) -{ - if (g_prefix.empty()) - return nullptr; - else - return g_prefix.c_str(); -} - -const char* translate_path_common(const char* path, bool symlink) -{ - static thread_local char resolved_path[1024]; - std::string str; - std::list path_components; - - if (!path) - return nullptr; - - if (g_prefix.empty()) - return path; - - // std::cout << "\tCWD is " << g_cwd << std::endl; - - if (path[0] != '/') - { - pthread_rwlock_rdlock(&g_cwdLock); - str = g_cwd; - pthread_rwlock_unlock(&g_cwdLock); - } - str += path; - // std::cout << "*** Before explode: " << str << std::endl; - - path_components = explode_path(str); - str = resolve_path(path_components, symlink); - - strncpy(resolved_path, str.c_str(), sizeof(resolved_path)-1); - resolved_path[sizeof(resolved_path)-1] = '\0'; - - // std::cout << "*** In: " << path << "; out: " << resolved_path << std::endl; - - return resolved_path; -} - -const char* __prefix_translate_path(const char* path) -{ - return translate_path_common(path, false); -} - -const char* __prefix_translate_path_link(const char* path) -{ - return translate_path_common(path, true); -} - -const char* __prefix_untranslate_path(const char* path, unsigned long count) -{ - static thread_local char resolved_path[1024]; - size_t test_len; - - // FIXME: The following strcmp is a bit of a hack needed for isatty() - // and friends. - if (g_prefix.empty() || !count || path[0] != '/' - || strncmp(path, "/dev/", 5) == 0) - { - memcpy(resolved_path, path, count); - resolved_path[count] = '\0'; - return resolved_path; - } - - test_len = (path[count-1] != '/') ? (g_prefix.length()-1) - : (g_prefix.length()); - - if (strncmp(path, g_prefix.c_str(), test_len) == 0) - { - size_t len = count - (g_prefix.length()-1); - memcpy(resolved_path, path + g_prefix.length() - 1, - count - (g_prefix.length() - 1)); - - if (len > 0) - resolved_path[len] = '\0'; - else - strcpy(resolved_path, "/"); - } - else - { - size_t len = std::min(sizeof(resolved_path) - - sizeof(SYSTEM_ROOT), count); - - strcpy(resolved_path, SYSTEM_ROOT); - strncat(resolved_path, path, len); - resolved_path[len + sizeof(SYSTEM_ROOT)-1] = '\0'; - } - - // std::cout << "*** UNTRANSLATE: " << path << " -> " << resolved_path << std::endl; - - return resolved_path; -} - -void __prefix_cwd(const char* in_path) -{ - if (!*in_path) - return; - - std::string path; - std::list path_components; - - // std::cout << "CWD to " << in_path << std::endl; - - pthread_rwlock_wrlock(&g_cwdLock); - if (in_path[0] != '/') - { - path = g_cwd; - path += in_path; - } - else - path = in_path; - - path_components = explode_path(path); - g_cwd = join_path(canonicalize_path(path_components)); - - if (g_cwd[g_cwd.length()-1] != '/') - g_cwd += '/'; - - // std::cout << "\t+++ CWD In: " << in_path << "; out: " << g_cwd << std::endl; - - pthread_rwlock_unlock(&g_cwdLock); -} - -void __prefix_cwd_fd(int fd) -{ - char path[1024]; - int count; - - if (g_prefix.empty()) - return; - - sprintf(path, "/proc/self/fd/%d", fd); - count = readlink(path, path, sizeof(path)-1); - - if (count < 0) - return; - - __prefix_cwd(__prefix_untranslate_path(path, count)); -} - -bool __prefix_is_system_root(const char* path) -{ - return strcmp(__prefix_translate_path(path), "/") == 0; -} - -int __prefix_get_dyld_path(char* buf, unsigned long size) -{ - int len; - len = readlink("/proc/self/exe", buf, size); - - if (len < 0) - buf[0] = '\0'; - else - buf[len] = '\0'; - - return len; -} - -std::list explode_path(const std::string& path) -{ - std::list path_components; - size_t pos = 0, last_pos; - - if (path.empty()) - return path_components; - - while (pos != std::string::npos) - { - size_t len; - - if (pos != 0 || path[0] == '/') - last_pos = pos + 1; // skip first slash - else - last_pos = pos; - - pos = path.find('/', last_pos); - len = (pos == std::string::npos) ? pos : (pos - last_pos); - path_components.push_back(path.substr(last_pos, len)); - } - - return path_components; -} - -std::string join_path(const std::list& path_components) -{ - std::string path; - - for (const std::string& comp : path_components) - { - path += '/'; - path += comp; - } - - return path; -} - -std::list& canonicalize_path(std::list& path_components) -{ - for (std::list::iterator it = path_components.begin(); - it != path_components.end(); ) - { - if (*it == "." || it->empty()) - { - it = path_components.erase(it); - } - else if (*it == "..") - { - if (it != path_components.begin()) - { - it--; - it = path_components.erase(it); - } - it = path_components.erase(it); - } - else - it++; - } - - return path_components; -} - -std::string resolve_path(std::list& path_components, bool symlink) -{ - std::string path, real_path; - bool had_failure = false; - - real_path = g_prefix; - - // The resolution process is restarted when a symlink is encountered -restart_process: - - canonicalize_path(path_components); - path.clear(); - - for (std::list::iterator it = path_components.begin(); - it != path_components.end(); it++) - { - std::string& comp = *it; - - path += '/'; - - if (!had_failure) // check if there is any sense in using opendir() or lstat() again - { - DIR* dir; - struct dirent* ent; - struct stat st; - bool isLink = false; - bool is_system_root; - - real_path.replace(g_prefix.size(), std::string::npos, path); - real_path += comp; - - // Do NOT perform symlink resolution on /system-root, - // because that should look like a bind mount rather than - // a symlink from inside the DPREFIX - is_system_root = (it == path_components.begin()) - && (comp == (SYSTEM_ROOT+1)); - - // We try an lstat() first as an optimization, - // because the opendir() path below is VERY slow on NFS mounts. - if (lstat(real_path.c_str(), &st) == 0) - { - isLink = S_ISLNK(st.st_mode); - } - else - { - // std::cout << "*** opendir: " << real_path << std::endl; - real_path.resize(real_path.length() - comp.length()); - - dir = opendir(real_path.c_str()); - - if (dir != nullptr) - { - std::string best_match; - unsigned char best_match_type; - - while ((ent = readdir(dir)) != nullptr) - { - // Commented out: replaced with lstat() above - /* if (comp == ent->d_name) - break; - else*/ if (strcasecmp(comp.c_str(), ent->d_name) == 0) - { - best_match = ent->d_name; - best_match_type = ent->d_type; - } - } - - if (ent != nullptr || !best_match.empty()) - { - if (ent == nullptr) - { - // correct the case - comp = best_match; - } - else - best_match_type = ent->d_type; - - if (best_match_type == DT_LNK && !is_system_root) - { - isLink = true; - real_path += comp; - } - } - else - had_failure = true; - - closedir(dir); - } - else - had_failure = true; - } - - if (symlink && it == --path_components.end()) - isLink = false; - - // Perform symlink resolution - if (isLink && !is_system_root) - { - char link[4096]; - int len; - - // std::cout << "*** readlink: " << real_path << std::endl; - len = readlink(real_path.c_str(), link, sizeof(link)-1); - - if (len > 0) - { - std::list link_components; - - link[len] = '\0'; - - /* - if (strncmp(link, "@darling_prefix@", 16) == 0) - { - std::string copy; - - copy = link; - copy.replace(0, 16, INSTALL_PREFIX); - - strcpy(link, copy.c_str()); - } - */ - link_components = explode_path(link); - - if (link[0] == '/') - { - // absolute symlink - it++; - it = path_components.erase(path_components.begin(), it); - } - else - { - // relative symlink - it = path_components.erase(it); - } - - path_components.insert(it, - link_components.begin(), - link_components.end()); - - // We always restart the process - // 1) For absolute symlinks, because we're moving to a completely different path - // 2) For relative symlinks, because they may contain '..' - goto restart_process; - } - } - } - - path += comp; - } - - if (!path_components.empty()) - { - if (*path_components.begin() == "proc" || path == "/dev/mach") - { - return path; - } - else if (*path_components.begin() == (SYSTEM_ROOT+1)) - { - if (!symlink || path_components.size() > 1) - { - // Exit virtual prefix - path = path.substr(sizeof(SYSTEM_ROOT)-1); - - if (path.empty()) - return "/"; - else - return path; - } - } - } - if (path.compare(0, sizeof(SHARE_PATH "/")-1, SHARE_PATH "/") == 0) - { - return path; - } - - // Apply virtual prefix - real_path.replace(g_prefix.size(), std::string::npos, path); - return real_path; -} - -/* -void path_to_string(const std::list& path, char* outPath, - size_t maxLen) -{ - size_t lenSoFar = 1; - - if (maxLen < 2) - return; - - outPath[0] = '\0'; - - for (const std::string& comp : path) - { - if (lenSoFar+1 > maxLen) - break; - - strcat(outPath, "/"); - lenSoFar++; - - if (lenSoFar + comp.length() > maxLen) - { - strncat(outPath, comp.c_str(), maxLen - lenSoFar); - break; - } - else - { - strcat(outPath, comp.c_str()); - lenSoFar += comp.length(); - } - } -} -*/ diff --git a/src/libdyld/VirtualPrefix.h b/src/libdyld/VirtualPrefix.h deleted file mode 100644 index 11fad8030..000000000 --- a/src/libdyld/VirtualPrefix.h +++ /dev/null @@ -1,66 +0,0 @@ -/* -This file is part of Darling. - -Copyright (C) 2015 Lubos Dolezel - -Darling is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -Darling is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Darling. If not, see . -*/ - -#ifndef VIRTUALPREFIX_H -#define VIRTUALPREFIX_H -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define __SYSTEM_ROOT "/system-root" - -// Set prefix path. Should be run only once at startup. -// If this is never called, then __prefix_translate_path() -// is a no-op. -void __prefix_set(const char* path); - -// Returns the current prefix or NULL; -const char* __prefix_get(void); - -// Translate from path in prefix to physical path. -const char* __prefix_translate_path(const char* path); - -// Translate from path in prefix to physical path, treat the leaf node -// as a symlink. -const char* __prefix_translate_path_link(const char* path); - -// Translate from physical path to path in prefix. -// The path is expected to be canonical. -const char* __prefix_untranslate_path(const char* path, unsigned long count); - -// Called whenever current working directory changes. -// This is used to resolve relative paths passed to -// __prefix_translate_path(). -void __prefix_cwd(const char* path); - -void __prefix_cwd_fd(int fd); - -// Is the given path equivalent to __SYSTEM_ROOT? -bool __prefix_is_system_root(const char* path); - -int __prefix_get_dyld_path(char* buf, unsigned long size); - -#ifdef __cplusplus -} -#endif - -#endif /* VIRTUALPREFIX_H */ - diff --git a/src/setup-ld-so.sh b/src/setup-ld-so.sh new file mode 100644 index 000000000..4c3d3ab30 --- /dev/null +++ b/src/setup-ld-so.sh @@ -0,0 +1,12 @@ +#! /bin/bash + +# This runs as root, +# with the current directory set to ${CMAKE_INSTALL_PREFIX}/libexec/darling + +for file in /etc/ld.so.conf $(find /etc/ld.so.conf.d/ -type f); do + # Copy lines from e.g. /etc/ld.so.conf into ./etc/ld.so.conf, + # prepending "/Volumes/SystemRoot" to each line that starts with a slash + awk '/^\// { print "/Volumes/SystemRoot" $0 }; /^[^/]/' $file > .$file +done + +unshare --mount bash -c "mount --rbind / Volumes/SystemRoot && ldconfig -r . -X"