diff --git a/install.sh b/install.sh index a0dbe73732..517f9f8f4b 100755 --- a/install.sh +++ b/install.sh @@ -56,6 +56,24 @@ nvm_profile_is_bash_or_zsh() { # * The method used ("script" or "git" in the script, defaults to "git") # NVM_SOURCE always takes precedence unless the method is "script-nvm-exec" # +nvm_check_file_writable(){ + if [ -f "$1" ]; then + if ! [ -w "$1" ]; then + local OWNER_NAME + OWNER_NAME=$(command id -un "$(command stat -c '%u' "$1" 2>/dev/null|| command stat -f '%u' "$1" 2>/dev/null)") + nvm_echo >&2 "=> Error: $1 is not writable!" + nvm_echo >&2 "=> This file is currently owned by $OWNER_NAME." + nvm_echo >&2 "=> Please ensure you have write access to this file." + nvm_echo >&2 "=> If this is a personal machine, you might run: sudo chown $(id -un) \"$1\"" + nvm_echo >&2 "=> On managed systems, please contact your administrator." + return 1 + elif [ -w "$1" ]; then + return 0 + fi + else + return 2 + fi +} nvm_source() { local NVM_GITHUB_REPO NVM_GITHUB_REPO="${NVM_INSTALL_GITHUB_REPO:-nvm-sh/nvm}" @@ -456,6 +474,9 @@ nvm_do_install() { BASH_OR_ZSH=true fi if ! command grep -qc '/nvm.sh' "$NVM_PROFILE"; then + if ! nvm_check_file_writable "${NVM_PROFILE}"; then + exit 1 + fi nvm_echo "=> Appending nvm source string to $NVM_PROFILE" command printf '%b' "${SOURCE_STR}" >> "$NVM_PROFILE" else @@ -463,6 +484,9 @@ nvm_do_install() { fi # shellcheck disable=SC2016 if ${BASH_OR_ZSH} && ! command grep -qc '$NVM_DIR/bash_completion' "$NVM_PROFILE"; then + if ! nvm_check_file_writable "${NVM_PROFILE}"; then + exit 1 + fi nvm_echo "=> Appending bash_completion source string to $NVM_PROFILE" command printf '%b' "$COMPLETION_STR" >> "$NVM_PROFILE" else diff --git a/test/install_script/nvm_check_file_writable b/test/install_script/nvm_check_file_writable new file mode 100755 index 0000000000..7fff9be46d --- /dev/null +++ b/test/install_script/nvm_check_file_writable @@ -0,0 +1,39 @@ +#!/bin/sh + +setup () { + HOME="." + if [ -z "$BASH_VERSION" ]; then + export BASH_VERSION=$(command -v bash >/dev/null && bash -c 'echo $BASH_VERSION' || echo "5.0.0") + fi + NVM_ENV=testing \. ../../install.sh + touch "writable_test_file" + touch "readonly_test_file" + chmod -w "readonly_test_file" +} + +cleanup () { + unset HOME + unset NVM_ENV + unset -f setup cleanup die + rm -f "writable_test_file" "readonly_test_file" > "/dev/null" 2>&1 +} + +die () { echo "$@"; cleanup; exit 1; } + +setup +nvm_check_file_writable "file_not_exists" +if [ $? -ne 2 ] ; then + die "nvm_check_file_writable did not reject nonexisting file with code 2" +fi + +nvm_check_file_writable "readonly_test_file" +if [ $? -ne 1 ]; then + die "nvm_check_file_writable did not reject nonwritable file with code 1" +fi + +nvm_check_file_writable "writable_test_file" +if [ $? -ne 0 ]; then + die "nvm_check_file_writable failed on writable file for unknown reason" +fi + +cleanup