From 02888809f592e98adaf7182e72262d74309af2b4 Mon Sep 17 00:00:00 2001 From: tali auster Date: Wed, 2 Oct 2024 04:04:36 -0700 Subject: [PATCH] fix: use /tmp dir if $HOME isn't writable (#1770) * fix: use tmp dir if $HOME isn't writable * Test for running without home --------- Co-authored-by: Alejandro R. Mosteo --- src/alire/alire-platforms-common.adb | 24 +++++++++++ src/alire/alire-platforms-common.ads | 10 +---- src/alr/alr-commands-version.adb | 1 + .../tests/dockerized/misc/no-home/test.py | 40 ++++++++++++++++++ .../tests/dockerized/misc/no-home/test.yaml | 7 ++++ testsuite/tests/misc/no-home/test.py | 42 +++++++++++++++++++ testsuite/tests/misc/no-home/test.yaml | 6 +++ 7 files changed, 121 insertions(+), 9 deletions(-) create mode 100644 testsuite/tests/dockerized/misc/no-home/test.py create mode 100644 testsuite/tests/dockerized/misc/no-home/test.yaml create mode 100644 testsuite/tests/misc/no-home/test.py create mode 100644 testsuite/tests/misc/no-home/test.yaml diff --git a/src/alire/alire-platforms-common.adb b/src/alire/alire-platforms-common.adb index 358e1ab68..f395df497 100644 --- a/src/alire/alire-platforms-common.adb +++ b/src/alire/alire-platforms-common.adb @@ -1,4 +1,5 @@ with AAA.Enum_Tools; +with GNAT.OS_Lib; with Alire.OS_Lib.Subprocess; @@ -71,4 +72,27 @@ package body Alire.Platforms.Common is end Detect; end Machine_Hardware_Name; + ---------------------- + -- Unix_Home_Folder -- + ---------------------- + + function Unix_Home_Folder return String + is + Home_Var : constant String := OS_Lib.Getenv ("HOME", "unset"); + Maybe_Windows : constant Boolean := Home_Var = "unset" + and then GNAT.OS_Lib.Directory_Separator = '\'; + begin + if Maybe_Windows then + raise Checked_Error with + "$HOME is not set, you might be running an" + & " `alr` built for a non-Windows OS"; + elsif Home_Var = "unset" or else + not GNAT.OS_Lib.Is_Write_Accessible_File (Home_Var) + then + return "/tmp"; + else + return Home_Var; + end if; + end Unix_Home_Folder; + end Alire.Platforms.Common; diff --git a/src/alire/alire-platforms-common.ads b/src/alire/alire-platforms-common.ads index 707176934..08a8db8e7 100644 --- a/src/alire/alire-platforms-common.ads +++ b/src/alire/alire-platforms-common.ads @@ -19,15 +19,7 @@ private package Alire.Platforms.Common is -- Unix_Home_Folder -- --------------------- - function Unix_Home_Folder return String - is (if OS_Lib.Getenv ("HOME", "unset") = "unset" and then - GNAT.OS_Lib.Directory_Separator = '\' - then - raise Checked_Error with - "$HOME is not set, you might be running an" - & " `alr` built for a non-Windows OS" - else - OS_Lib.Getenv ("HOME", Default => "/tmp")); + function Unix_Home_Folder return String; ---------------------- -- Unix_Temp_Folder -- diff --git a/src/alr/alr-commands-version.adb b/src/alr/alr-commands-version.adb index a89057d9e..a72c5ad21 100644 --- a/src/alr/alr-commands-version.adb +++ b/src/alr/alr-commands-version.adb @@ -98,6 +98,7 @@ package body Alr.Commands.Version is Add (""); Add ("CONFIGURATION"); + Add ("home folder:", Alire.Platforms.Folders.Home); Add ("settings folder:", Alire.Settings.Edit.Path); Add ("cache folder:", Alire.Cache.Path); Add ("vault folder:", Paths.Vault.Path); diff --git a/testsuite/tests/dockerized/misc/no-home/test.py b/testsuite/tests/dockerized/misc/no-home/test.py new file mode 100644 index 000000000..5be7cacee --- /dev/null +++ b/testsuite/tests/dockerized/misc/no-home/test.py @@ -0,0 +1,40 @@ +""" +Verify that alr can run with no HOME set, or with it set to an +unwritable/nonexistent directory. +NOTE: This same test is duplicated to be run under docker as a regular user. +""" + +import os +from drivers.alr import run_alr + + +def check_no_home(): + # Verify that alr is using the fallback home directory. + p = run_alr("--format", "version") + assert """{ + "key": "home folder", + "value": "/tmp" + }""" in p.out, "Unexpected output: " + p.out + + +# Remove HOME +os.environ.pop("HOME", None) +check_no_home() + +# Set HOME to a nonexistent directory +fake_home = "/tmp/fake_home_for_alr" +assert not os.path.exists(fake_home) +os.environ["HOME"] = fake_home +check_no_home() + +# Set HOME to an unwritable directory +# Under our docker, we should be a regular user and this should succeed +os.makedirs(fake_home) +os.chmod(fake_home, 0o444) +check_no_home() +# Cleanup +os.chmod(fake_home, 0o777) +os.rmdir(fake_home) + + +print("SUCCESS") diff --git a/testsuite/tests/dockerized/misc/no-home/test.yaml b/testsuite/tests/dockerized/misc/no-home/test.yaml new file mode 100644 index 000000000..0e7e8b46b --- /dev/null +++ b/testsuite/tests/dockerized/misc/no-home/test.yaml @@ -0,0 +1,7 @@ +driver: docker-wrapper +build_mode: both +control: + - [SKIP, "skip_docker", "Test is Docker-only"] + - [SKIP, "skip_unix", "Test is Unix-only"] +indexes: + compiler_only_index: {} diff --git a/testsuite/tests/misc/no-home/test.py b/testsuite/tests/misc/no-home/test.py new file mode 100644 index 000000000..3a18bd1d0 --- /dev/null +++ b/testsuite/tests/misc/no-home/test.py @@ -0,0 +1,42 @@ +""" +Verify that alr can run with no HOME set, or with it set to an +unwritable/nonexistent directory. +NOTE: This same test is duplicated to be run under docker as a regular user. +""" + +import os +from drivers.alr import run_alr + + +def check_no_home(): + # Verify that alr is using the fallback home directory. + p = run_alr("--format", "version") + assert """{ + "key": "home folder", + "value": "/tmp" + }""" in p.out, "Unexpected output: " + p.out + + +# Remove HOME +os.environ.pop("HOME", None) +check_no_home() + +# Set HOME to a nonexistent directory +fake_home = "/tmp/fake_home_for_alr" +assert not os.path.exists(fake_home) +os.environ["HOME"] = fake_home +check_no_home() + +# Set HOME to an unwritable directory +# This will fail if running under root, in which case we skip this part. +# This is tested properly under docker +if os.getuid() != 0: + os.makedirs(fake_home) + os.chmod(fake_home, 0o444) + check_no_home() + # Cleanup + os.chmod(fake_home, 0o777) + os.rmdir(fake_home) + + +print("SUCCESS") diff --git a/testsuite/tests/misc/no-home/test.yaml b/testsuite/tests/misc/no-home/test.yaml new file mode 100644 index 000000000..9a541fdd1 --- /dev/null +++ b/testsuite/tests/misc/no-home/test.yaml @@ -0,0 +1,6 @@ +driver: python-script +build_mode: both +control: + - [SKIP, "skip_unix", "Test is Unix-only"] +indexes: + compiler_only_index: {}