diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index 8efae1f..0000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1,2 +0,0 @@ -github: fsquillace -custom: https://github.com/fsquillace/junest/blob/master/README.md#donating diff --git a/.gitignore b/.gitignore index b47a408..2d39c41 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ *.swp -*pkg.tar.* +*pkg.tar.xz *.tar.gz *.SRCINFO diff --git a/.travis.yml b/.travis.yml index fab23ba..dceb835 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,62 +1,31 @@ +language: bash + sudo: required -os: linux - -cache: - directories: - - ~/.ccache - - ~/.pkg-cache - -services: -- docker env: - matrix: - TRAVIS_BASH_VERSION="4.0" before_install: - - ./ci/install-bash.sh "$TRAVIS_BASH_VERSION" - - sudo apt-get update - - sudo apt-get -y install awscli + - ./tests/integ-tests/install-bash.sh "$TRAVIS_BASH_VERSION" install: - PATH=$PWD/bin:$PATH + - junest setup + - junest -- echo "Installing JuNest (\$(uname -m))" + - JUNEST_HOME=~/.junest-arm junest setup --arch arm + - JUNEST_HOME=~/.junest-arm junest proot --fakeroot -- echo "Installing JuNest (\$(uname -m))" script: - ####################### - # Unit Tests - ####################### - bash --version - bash ./tests/checkstyle/checkstyle.sh - bash ./tests/unit-tests/unit-tests.sh - - shellcheck bin/junest lib/**/*.sh ci/*.sh tests/**/*.sh - # ARM with qemu does seem to work properly. Disabling integ tests for ARM for now. - #- export JUNEST_HOME=~/.junest-arm - #- junest setup --arch arm - #- junest proot --fakeroot -- echo "Installing JuNest (\$(uname -m))" - #- junest proot --fakeroot -- ${PWD}/lib/checks/check.sh --skip-aur-tests - #- junest proot -- ${PWD}/lib/checks/check.sh --skip-aur-tests --use-sudo - #- yes | junest setup --delete - - ####################### - # Build and validation - ####################### - - echo "$DOCKER_PASSWORD" | docker login --username "$DOCKER_USERNAME" --password-stdin - - docker run --rm -v "$(pwd):/build" -v ~/.ccache:/home/travis/.ccache -v ~/.pkg-cache:/var/cache/pacman/pkg --privileged archlinux:latest bash /build/ci/build_image.sh - - - "echo pacman pkg cache size: $(du -h ~/.pkg-cache|cut -f1) in $(ls ~/.pkg-cache|wc -l) files" - - ls -l - # Test the newly created JuNest image against Ubuntu host - - export JUNEST_HOME=~/.junest - - junest setup -i junest-x86_64.tar.gz - # TODO The check does not work at the moment: https://app.travis-ci.com/github/fsquillace/junest/builds/271706037 - # Disabling it in order to avoid having stale version of junest images. - - ${PWD}/lib/checks/check_all.sh + # Multiple tests against different execution modes: + - junest proot --fakeroot -- ${PWD}/lib/checks/check.sh + - junest ns -- ${PWD}/lib/checks/check.sh + - sudo -E ${PWD}/bin/junest groot -- ${PWD}/lib/checks/check.sh --run-root-tests - yes | junest setup --delete - -after_success: - ####################### - # Deploy and validation - ####################### - - ./ci/deploy.sh ./junest-x86_64.tar.gz + # Disable arm because it fails when exiting from check.sh for apparent no reason + #- JUNEST_HOME=~/.junest-arm junest proot -f -- ./lib/checks/check.sh --skip-aur-tests + #- yes | JUNEST_HOME=~/.junest-arm junest setup --delete diff --git a/README.md b/README.md index 1268f8b..856a9a8 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,6 @@ JuNest ====== - -> [!IMPORTANT] -> Starting from Ubuntu 23.10+, [unprivileged user namespaces has been restricted](https://ubuntu.com/blog/ubuntu-23-10-restricted-unprivileged-user-namespaces). -> If using JuNest within Ubuntu, you may need root privileges in order to enable it. -> Alternatively, you can access JuNest using the `proot` mode as described -> [below](#Proot-based). - -The lightweight Arch Linux based distro that runs, without root privileges, on top of any other Linux distro. +The lightweight Arch Linux based distro that runs upon any Linux distros without root access.

=4.0)](https://www.gnu.org/software/bash/) - [GNU coreutils](https://www.gnu.org/software/coreutils/) -## Installation from git repository ## +The minimum recommended Linux kernel of the host OS is 2.6.32 on x86 (64 bit) +and ARM architectures. It is still possible to run JuNest on lower +2.6.x host OS kernels but errors may appear, and some applications may +crash. For further information, read the [Troubleshooting](#troubleshooting) +section below. + + +## Method one (Recommended) ## Just clone the JuNest repo somewhere (for example in ~/.local/share/junest): -```sh -git clone https://github.com/fsquillace/junest.git ~/.local/share/junest -export PATH=~/.local/share/junest/bin:$PATH -``` - -Optionally you want to use the wrappers to run commands -installed in JuNest directly from host: - -```sh -export PATH="$PATH:~/.junest/usr/bin_wrappers" -``` -Update your `~/.bashrc` or `~/.zshrc` to get always the wrappers available. + git clone git://github.com/fsquillace/junest ~/.local/share/junest + export PATH=~/.local/share/junest/bin:$PATH ### Installation using AUR (Arch Linux only) ### If you are using an Arch Linux system you can, alternatively, install JuNest from the [AUR repository](https://aur.archlinux.org/packages/junest-git/). -JuNest will be located in `/opt/junest/` +After installing junest will be located in `/opt/junest/` -Quickstart -========== +## Method two ## +Alternatively, another installation method would be to directly download the JuNest image and place it to the default directory `~/.junest`: -Setup environment ------------------ - -The first operation required is to install the JuNest environment in the -location of your choice via `JUNEST_HOME` environment variable -(it must contain an absolute path) which by -default is `~/.junest`: - -```sh -junest setup -``` - -The script will download the image from the repository and will place it to the default directory `~/.junest`. - -Access to environment ---------------------- - -JuNest uses the Linux namespaces (aka `ns`) as the default backend program. To access via `ns` just type: - -```sh -junest -``` - -You can use the command `sudo` to acquire fakeroot privileges and -install/remove packages. - -Alternatively, you can access fakeroot privileges without using `sudo` all the -time with the `-f` (or `--fakeroot`) option: - -```sh -junest -f -``` - -Another execution mode is via [Proot](https://wiki.archlinux.org/index.php/Proot): - -```sh -junest proot [-f] -``` - -There are multiple backend programs, each with its own pros/cons. -To know more about the JuNest execution modes depending on the backend program -used, see the [Usage](#usage) section below. - -Run JuNest installed programs directly from host OS ---------------------------------------- - -Programs installed within JuNest can be accessible directly from host machine -without entering into a JuNest session -(namely, no need to call `junest` command first). -For instance, supposing the host OS is an Ubuntu distro you can directly -run `pacman` by simply updating the `PATH` variable: - -```sh -export PATH="$PATH:~/.junest/usr/bin_wrappers" -sudoj pacman -S htop -htop -``` - -By default the wrappers use `ns` mode. To use the `ns --fakeroot` you can use the convenient command helper `sudoj`. -For more control on backend modes you can use the `JUNEST_ARGS` environment variable too. -For instance, if you want to run `iftop` with real root privileges: - -``` -sudoj pacman -S iftop -sudo JUNEST_ARGS="groot" iftop -``` - -Bin wrappers can be always recreated (e.g. in case for some reasons they get -corrupted) with: - -``` -junest create-bin-wrappers -f -``` - -Bin wrappers are automatically generated each time they get installed inside JuNest. -This only works for executables located in `/usr/bin` path. -For executables in other locations (say `/usr/mybinpath`) you can only create -wrappers manually by executing the command: - -``` -junest create-bin-wrappers --bin-path /usr/mybinpath -``` - -Obviously, to get access to the corresponding bin wrappers you will need to -update your `PATH` variable accordingly: - -``` -export PATH="$PATH:~/.junest/usr/mybinpath_wrappers" -``` - -Install packages from AUR -------------------------- - -In `ns` mode, you can easily install package from [AUR](https://aur.archlinux.org/) repository -using the already available [`yay`](https://aur.archlinux.org/packages/yay/) -command. In `proot` mode, JuNest does no longer support the building of AUR packages. - -**Remember** that in order to build packages from AUR, `base-devel` package group is required -first: - -```sh -pacman -S base-devel -``` - -JuNest uses a modified version of `sudo` provided by `junest/sudo-fake`. And the original `core/sudo` -package will be ignored **(and must not be installed)** during the installation of `base-devel`. - -Have fun! ---------- - -If you are new on Arch Linux and you are not familiar with `pacman` package manager -visit the [pacman rosetta page](https://wiki.archlinux.org/index.php/Pacman_Rosetta). + ARCH= + mkdir ~/.junest + curl https://s3-eu-west-1.amazonaws.com/junest-repo/junest/junest-${ARCH}.tar.gz | tar -xz -C ~/.junest + export PATH=~/.junest/opt/junest/bin:$PATH Usage ===== @@ -240,18 +172,14 @@ provides the state of the user namespace on several GNU/Linux distros. In order to run JuNest via Linux namespaces: -- As normal user - Allow to make basic operations or install/remove packages -with `sudo` command: `junest ns` or `junest` -- As fakeroot - Allow to install/remove packages: `junest ns -f` or `junest -f` - -This mode is based on the fantastic -[`bubblewrap`](https://github.com/containers/bubblewrap) command. +- As fakeroot - Allow to install/remove packages: `junest ns` or `junest` PRoot based ----------- [Proot](https://wiki.archlinux.org/index.php/Proot) represents a portable -solution which allows unprivileged users to execute programs inside a sandbox -and works well in most of GNU/Linux distros available. +solution that works well in most of GNU/Linux distros available. +One of the major drawbacks is the fact that Proot is not officially +supported anymore, therefore, Proot bugs may no longer be fixed. In order to run JuNest via Proot: @@ -259,21 +187,13 @@ In order to run JuNest via Proot: - As fakeroot - Allow to install/remove packages: `junest proot -f` -In `proot` mode, the minimum recommended Linux kernel for the host OS is 2.6.32 on x86 (64 bit) -and ARM architectures. It is still possible to run JuNest on lower -2.6.x host OS kernels but errors may appear, and some applications may -crash. For further information, read the [Troubleshooting](#troubleshooting) -section below. - Chroot based ------------ This solution suits only for privileged users. JuNest provides the possibility to run the environment via `chroot` program. -In particular, it uses a special program called `GRoot`, a small and portable -version of -[arch-chroot](https://wiki.archlinux.org/index.php/Chroot) +In particular, it uses a special program called `GRoot`, an enhanced `chroot` wrapper, that allows to bind mount directories specified by the user, such as -`/proc`, `/sys`, `/dev`, `/tmp`, `/run/user/` and `$HOME`, before +`/proc`, `/sys`, `/dev`, `/tmp` and `$HOME`, before executing any programs inside the JuNest sandbox. In case the mounting will not work, JuNest is even providing the possibility to run the environment directly via the pure `chroot` command. @@ -290,8 +210,8 @@ The following table shows the capabilities that each backend program is able to | | QEMU | Root privileges required | Manage Official Packages | Manage AUR Packages | Portability | Support | User modes | | --- | ---- | ------------------------ | ------------------------ | ------------------- | ----------- | ------- | ---------- | -| **Linux Namespaces** | NO | NO | YES | YES | Poor | YES | Normal user and `fakeroot` | -| **Proot** | YES | NO | YES | NO | YES | YES | Normal user and `fakeroot` | +| **Linux Namespaces** | NO | NO | YES | YES | Poor | YES | `fakeroot` only | +| **Proot** | YES | NO | YES | YES | YES | Poor | Normal user and `fakeroot` | | **Chroot** | NO | YES | YES | YES | YES | YES | `root` only | Advanced usage @@ -337,19 +257,13 @@ armv7l ``` ## Bind directories ## -To bind a host directory to a guest location: - -```sh -junest -b "--bind /home/user/mydata /mnt/mydata" -``` - -Or using proot arguments: +To bind a host directory to a guest location, you can use proot arguments: ```sh junest proot -b "-b /mnt/mydata:/home/user/mydata" ``` -The option `-b` to provide options to the backend program will work with PRoot, Namespace and GRoot backend programs. +The option `-b` to provide options to the backeng program will work with PRoot, Namespace and GRoot backend programs. Check out the backend program options by passing `--help` option: ```sh @@ -377,6 +291,21 @@ Related wiki page: Internals ========= + +There are two main chroot jail used in JuNest. +The main one is [proot](https://wiki.archlinux.org/index.php/Proot) which +allows unprivileged users to execute programs inside a sandbox and +GRoot, a small and portable version of +[arch-chroot](https://wiki.archlinux.org/index.php/Chroot) which is an +enhanced chroot for privileged users that mounts the primary directories +(i.e. `/proc`, `/sys`, `/dev` and `/run`) before executing any programs inside +the sandbox. + +## Automatic fallback to classic chroot ## +If GRoot fails for some reasons in the host system (i.e. it is not able to +mount one of the directories), +JuNest automatically tries to fallback to the classic chroot. + ## Automatic fallback for all the dependent host OS executables ## JuNest attempts first to run the executables in the host OS located in different positions (`/usr/bin`, `/bin`, `/usr/sbin` and `/sbin`). @@ -384,10 +313,10 @@ As a fallback it tries to run the same executable if it is available in the JuNe environment. ## Automatic building of the JuNest images ## -There is a periodic automation build of the JuNest images for `x86_64` arch -only. -The JuNest image for `arm` architecture may not be always up to date because -the build is performed manually. +There is not periodic automation build of the JuNest images yet. +This was due to the difficulty to automate builds for arm architecture. +The JuNest image for the `x86_64` is built periodically every once every three +months. ## Static QEMU binaries ## There are static QEMU binaries included in JuNest image that allows to run JuNest @@ -409,22 +338,9 @@ For Arch Linux related FAQs take a look at the [General troubleshooting page](ht > In order to install AUR packages you need to install the package group `base-devel` first > that contains all the essential packages for compiling from source code (such as gcc, make, patch, etc): - #> pacman -S base-devel + #> pacman -S --ignore sudo base-devel -> Remember to not install `core/sudo` as it conflicts with `junest/sudo-fake` package. - -## Can't set user and group as root - -> **Q**: In ns mode when installing package I get the following error: - - warning: warning given when extracting /usr/file... (Can't set user=0/group=0 for - /usr/file...) - -> **A**: This is because as fakeroot is not possible to set the owner/group of -> files as root. The package will still be installed correctly even though this -> message is showed. - -## Could not change the root directory in pacman +> Remember to ignore `sudo` as it conflicts with `sudo-fake` package. ## No servers configured for repository ## @@ -534,7 +450,7 @@ For Arch Linux related FAQs take a look at the [General troubleshooting page](ht > have *suid* permission, you can list the commands from your JuNest environment > with the following command: - $> find /usr/bin -perm /4000 + $> find /usr/bin -perm +4000 ## No characters are visible on a graphic application ## @@ -602,11 +518,6 @@ Contributions are welcome! You could help improving JuNest in the following ways - [Suggesting Enhancements](CONTRIBUTING.md#suggesting-enhancements) - [Writing Code](CONTRIBUTING.md#your-first-code-contribution) -Donating -======== -To sustain the project please consider funding by donations through -the [GitHub Sponsors page](https://github.com/sponsors/fsquillace/). - Authors ======= JuNest was originally created in late 2014 by [Filippo Squillace (feel.sqoox@gmail.com)](https://github.com/fsquillace). diff --git a/VERSION b/VERSION index ef13716..9fe9ff9 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -7.4.10 +7.0.1 diff --git a/bin/groot b/bin/groot new file mode 100755 index 0000000..cb4952f --- /dev/null +++ b/bin/groot @@ -0,0 +1,242 @@ +#!/bin/bash +# +# This script is the simplified and portable version of arch-chroot +# (https://wiki.archlinux.org/index.php/Change_root#Using_arch-chroot) +# + +set -e + +# JUNEST_BASE can be overridden for testing purposes. +# There is no need for doing it for normal usage. +JUNEST_BASE="${JUNEST_BASE:-$(readlink -f $(dirname $(readlink -f "$0"))/..)}" +NAME='GRoot' +CMD='groot' +DESCRIPTION="I am $NAME!" +CHROOTCMD=${CHROOTCMD:-chroot} +SHELL="/bin/sh" +MOUNT=mount +UMOUNT=umount +MKDIR=mkdir +TOUCH=touch +CUT=cut +SORT=sort +UNIQ=uniq +CAT=cat +READLINK=readlink +MOUNTS_FILE=/proc/self/mounts + +NOT_EXISTING_FILE=103 +NOT_ABSOLUTE_PATH=111 +NO_ROOT_PRIVILEGES=110 + +source "${JUNEST_BASE}/lib/utils/utils.sh" + + +################################ MAIN FUNCTIONS ########################### + +function is_mountpoint() { + local mountpoint="$1" + for mp in $($CAT $MOUNTS_FILE | $CUT -f2 -d' ' | $SORT -r | $UNIQ) + do + [[ $mp == $mountpoint ]] && return 0 + done + return 1 +} + +function chroot_teardown() { + # Remove all mounts starting from the most nested ones. + # Suffix the CHROOTDIR with / to avoid umounting directories not belonging + # to CHROOTDIR. + local normalized_chrootdir="$($READLINK -f ${CHROOTDIR})/" + local final_res=0 + for mp in $($CAT $MOUNTS_FILE | $CUT -f2 -d' ' | $SORT -r | $UNIQ) + do + if [[ $mp =~ ^${normalized_chrootdir}.* ]] && is_mountpoint "$mp" + then + $UMOUNT $mp || final_res=$? + fi + done + $UMOUNT ${CHROOTDIR%/} + + return $final_res +} + +function chroot_maybe_add_mount() { + local cond=$1 + shift + if eval "$cond"; then + $MOUNT "$@" + return + fi + return 1 +} + +function chroot_setup() { + $OPT_NO_UMOUNT || check_and_trap 'chroot_teardown' QUIT EXIT ABRT KILL TERM INT + + if ! chroot_maybe_add_mount "! is_mountpoint '$CHROOTDIR'" --bind "$CHROOTDIR" "$CHROOTDIR" + then + warn "Failed mount of directories. $CHROOTDIR is already a mountpoint. Skipping it..." + return 0 + fi + + local re='(.*):(.*)' + for binds in ${BINDINGS[@]} + do + local host_path="" + local guest_path="" + if [[ $binds =~ $re ]] + then + local host_path="${BASH_REMATCH[1]}" + local guest_path="${BASH_REMATCH[2]}" + else + local host_path="$binds" + local guest_path="$binds" + fi + + create_node "${host_path}" "${CHROOTDIR}${guest_path}" + mount_directory "${host_path}" "${guest_path}" + done +} + +function mount_directory() { + local host_path=$($READLINK -f "$1") + local guest_path="$2" + + if ! $OPT_AVOID_BIND + then + $MOUNT $OPT_BIND "${host_path}" "${CHROOTDIR}${guest_path}" + return 0 + fi + + case "$host_path" in + /proc) $MOUNT proc "${CHROOTDIR}${guest_path}" -t proc ;; + /sys) $MOUNT sys "${CHROOTDIR}${guest_path}" -t sysfs ;; + /dev) $MOUNT udev "${CHROOTDIR}${guest_path}" -t devtmpfs; $MOUNT devpts "${guest_path}/pts" -t devpts; $MOUNT shm "${guest_path}/shm" -t tmpfs ;; + /run) $MOUNT run "${CHROOTDIR}${guest_path}" -t tmpfs ;; + /tmp) $MOUNT tmp "${CHROOTDIR}${guest_path}" -t tmpfs ;; + *) $MOUNT $OPT_BIND "${host_path}" "${CHROOTDIR}${guest_path}" ;; + esac + + return 0 +} + +function create_node() { + local src="$1" + local dst="$2" + if [[ ! -e $src ]] + then + die_on_status $NOT_EXISTING_FILE "${src} does not exist." + elif [[ $src != /* ]] + then + die_on_status $NOT_ABSOLUTE_PATH "${src} is not an absolute path." + elif [[ -f $src ]] + then + $TOUCH "$dst" + elif [[ -d $src ]] + then + $MKDIR -p "$dst" + fi +} + +function usage() { + cat < [command]] + +Options: + -b, --bind + Make the content of accessible in the guest rootfs. + + This option makes any file or directory of the host rootfs + accessible in the confined environment just as if it were part of + the guest rootfs. By default the host path is bound to the same + path in the guest rootfs but users can specify any other location + with the syntax: -b :. This option can + be invoked multiple times and the paths specified must be absolutes. + + -n, --no-umount + Do not umount after chroot session finished. + + -r, --recursive + Use rbind instead of bind. + + -i, --avoid-bind + Attempt to avoid mount --bind for common directories and use + proper mount fstype instead. Detected directories with + corresponding fstype are: /proc (proc), /sys (sysfs), + /dev (devtmpfs), /tmp (tmpfs), /run (tmpfs). + + -h, --help Print this help message + + -V, --version Show the $NAME version + +If 'command' is unspecified, $CMD will launch $SHELL. + +EOF +} + +version() { + echo -e "$NAME $(cat $JUNEST_BASE/VERSION)" +} + +function parse_arguments() { + BINDINGS=() + OPT_NO_UMOUNT=false + OPT_RECURSIVE=false + OPT_BIND="--bind" + OPT_AVOID_BIND=false + OPT_HELP=false + OPT_VERSION=false + for opt in "$@" + do + case "$1" in + -b|--bind) shift ; BINDINGS+=("$1") ; shift ;; + -n|--no-umount) OPT_NO_UMOUNT=true ; shift ;; + -r|--recursive) OPT_BIND="--rbind" ; shift ;; + -i|--avoid-bind) OPT_AVOID_BIND=true ; shift ;; + -h|--help) OPT_HELP=true ; shift ;; + -V|--version) OPT_VERSION=true ; shift ;; + -*) die "Invalid option $1" ;; + *) break ;; + esac + done + + if [[ ! -z $1 ]] + then + CHROOTDIR="$1" + shift + fi + ARGS=() + for arg in "$@" + do + ARGS+=("$arg") + done +} + +function is_user_root() { + (( EUID == 0 )) +} + +function execute_operation() { + $OPT_HELP && usage && return + $OPT_VERSION && version && return + + is_user_root || die_on_status $NO_ROOT_PRIVILEGES 'This script must be run with root privileges' + + [[ -d $CHROOTDIR ]] || die_on_status $NOT_EXISTING_FILE "Can't create chroot on non-directory $CHROOTDIR" + + chroot_setup "$CHROOTDIR" || die "Failed to setup chroot $CHROOTDIR" + + $CHROOTCMD "$CHROOTDIR" "${ARGS[@]}" +} + + +function main() { + parse_arguments "$@" + execute_operation +} + +main "$@" diff --git a/bin/junest b/bin/junest index 4084fe0..381864b 100755 --- a/bin/junest +++ b/bin/junest @@ -1,5 +1,4 @@ #!/usr/bin/env bash -# shellcheck disable=SC1091 # # This file is part of JuNest (https://github.com/fsquillace/junest). # @@ -8,7 +7,7 @@ set -e # JUNEST_BASE can be overridden for testing purposes. # There is no need for doing it for normal usage. -JUNEST_BASE="${JUNEST_BASE:-$(readlink -f "$(dirname "$(readlink -f "$0")")"/..)}" +JUNEST_BASE="${JUNEST_BASE:-$(readlink -f $(dirname $(readlink -f "$0"))/..)}" source "${JUNEST_BASE}/lib/utils/utils.sh" source "${JUNEST_BASE}/lib/core/common.sh" @@ -18,14 +17,13 @@ source "${JUNEST_BASE}/lib/core/setup.sh" source "${JUNEST_BASE}/lib/core/chroot.sh" source "${JUNEST_BASE}/lib/core/namespace.sh" source "${JUNEST_BASE}/lib/core/proot.sh" -source "${JUNEST_BASE}/lib/core/wrappers.sh" ################################### ### General functions ### ################################### usage() { - echo -e "$NAME (v$(cat "$JUNEST_BASE"/VERSION)): $DESCRIPTION" + echo -e "$NAME (v$(cat $JUNEST_BASE/VERSION)): $DESCRIPTION" echo echo -e "Usage: $CMD [action] [options] [--] [command]" echo @@ -40,52 +38,40 @@ usage() { echo -e " Defaults to the host architecture ($ARCH)" echo -e " -d, --delete Delete $NAME from ${JUNEST_HOME}" echo - echo -e " n[s] Access via Linux Namespaces using BubbleWrap (Default action)" - echo -e " -f, --fakeroot Run $NAME with fakeroot privileges" - echo -e " --backend-command Bwrap command to use" - echo -e " -b, --backend-args Arguments for bwrap backend program" - echo -e " ($CMD ns -b \"--help\" to check out the bwrap options)" + echo -e " n[s] Access via Linux Namespaces using GRoot (Default action)" + echo -e " -b, --backend-args Arguments for GRoot backend program" + echo -e " ($CMD groot -p \"--help\" to check out the GRoot options)" echo -e " -n, --no-copy-files Do not copy common etc files into $NAME environment" echo echo -e " p[root] Access via PRoot" echo -e " -f, --fakeroot Run $NAME with fakeroot privileges" - echo -e " --backend-command PRoot command to use" echo -e " -b, --backend-args Arguments for PRoot backend program" - echo -e " ($CMD proot -b \"--help\" to check out the PRoot options)" + echo -e " ($CMD proot -p \"--help\" to check out the PRoot options)" echo -e " -n, --no-copy-files Do not copy common etc files into $NAME environment" echo echo -e " g[root] Access with root privileges via GRoot" - echo -e " --backend-command GRoot command to use" echo -e " -b, --backend-args Arguments for GRoot backend program" - echo -e " ($CMD groot -b \"--help\" to check out the GRoot options)" + echo -e " ($CMD groot -p \"--help\" to check out the GRoot options)" echo -e " -n, --no-copy-files Do not copy common etc files into $NAME environment" echo echo -e " r[oot] Access with root privileges via classic chroot" - echo -e " --backend-command Chroot command to use" echo -e " -b, --backend-args Arguments for chroot backend program" - echo -e " ($CMD root -b \"--help\" to check out the chroot options)" + echo -e " ($CMD root -p \"--help\" to check out the chroot options)" echo -e " -n, --no-copy-files Do not copy common etc files into $NAME environment" echo echo -e " b[uild] Build a $NAME image (must run in ArchLinux)" echo -e " -n, --disable-check Disable the $NAME image check" echo - echo -e " create-bin-wrappers Create a bin wrappers directory according to --bin-path option" - echo -e " Default path is $JUNEST_HOME/usr/bin_wrappers" - echo -e " -f, --force Create the wrapper files even if they already exist" - echo -e " -p, --bin-path The source directory where executable are located in JuNest" - echo -e " Default value is: /usr/bin" - echo } version() { - echo -e "$NAME $(cat "$JUNEST_BASE"/VERSION)" + echo -e "$NAME $(cat $JUNEST_BASE/VERSION)" } function parse_arguments(){ # Actions ACT_SETUP=false ACT_BUILD=false - ACT_CREATE_WRAPPERS=false ACT_NAMESPACE=false ACT_PROOT=false ACT_GROOT=false @@ -96,7 +82,6 @@ function parse_arguments(){ case "$1" in s|setup) ACT_SETUP=true ; shift ;; b|build) ACT_BUILD=true ; shift ;; - create-bin-wrappers) ACT_CREATE_WRAPPERS=true ; shift ;; n|ns) ACT_NAMESPACE=true ; shift ;; p|proot) ACT_PROOT=true ; shift ;; g|groot) ACT_GROOT=true ; shift ;; @@ -112,9 +97,6 @@ function parse_arguments(){ elif $ACT_BUILD then _parse_build_opts "$@" - elif $ACT_CREATE_WRAPPERS - then - _parse_create_wrappers_opts "$@" elif $ACT_NAMESPACE then _parse_ns_opts "$@" @@ -132,16 +114,15 @@ function parse_arguments(){ function _parse_root_opts() { # Options: + OPT_BACKEND_ARGS=false BACKEND_ARGS="" OPT_NO_COPY_FILES=false - BACKEND_COMMAND="" while [[ -n "$1" ]] do case "$1" in - -b|--backend-args) shift ; BACKEND_ARGS=$1; shift ;; + -b|--backend-args) OPT_BACKEND_ARGS=true ; shift ; BACKEND_ARGS=$1; shift ;; -n|--no-copy-files) OPT_NO_COPY_FILES=true ; shift ;; - --backend-command) shift; BACKEND_COMMAND="$1"; shift ;; --) shift ; break ;; -*) die "Invalid option $1" ;; *) break ;; @@ -157,18 +138,15 @@ function _parse_root_opts() { function _parse_ns_opts() { # Options: - OPT_FAKEROOT=false + OPT_BACKEND_ARGS=false BACKEND_ARGS="" OPT_NO_COPY_FILES=false - BACKEND_COMMAND="" while [[ -n "$1" ]] do case "$1" in - -f|--fakeroot) OPT_FAKEROOT=true ; shift ;; - -b|--backend-args) shift ; BACKEND_ARGS=$1; shift ;; + -b|--backend-args) OPT_BACKEND_ARGS=true ; shift ; BACKEND_ARGS=$1; shift ;; -n|--no-copy-files) OPT_NO_COPY_FILES=true ; shift ;; - --backend-command) shift; BACKEND_COMMAND="$1"; shift ;; --) shift ; break ;; -*) die "Invalid option $1" ;; *) break ;; @@ -185,24 +163,27 @@ function _parse_ns_opts() { function _parse_proot_opts() { # Options: OPT_FAKEROOT=false + OPT_BACKEND_ARGS=false BACKEND_ARGS="" OPT_NO_COPY_FILES=false - BACKEND_COMMAND="" while [[ -n "$1" ]] do case "$1" in -f|--fakeroot) OPT_FAKEROOT=true ; shift ;; - -b|--backend-args) shift ; BACKEND_ARGS=$1; shift ;; + -b|--backend-args) OPT_BACKEND_ARGS=true ; shift ; BACKEND_ARGS=$1; shift ;; -n|--no-copy-files) OPT_NO_COPY_FILES=true ; shift ;; - --backend-command) shift; BACKEND_COMMAND="$1"; shift ;; --) shift ; break ;; -*) die "Invalid option $1" ;; *) break ;; esac done - ARGS=("$@") + ARGS=() + for arg in "$@" + do + ARGS+=("$arg") + done } function _parse_build_opts() { @@ -216,29 +197,17 @@ function _parse_build_opts() { done } -function _parse_create_wrappers_opts() { - OPT_FORCE=false - OPT_BIN_PATH="" - while [[ -n "$1" ]] - do - case "$1" in - -f|--force) OPT_FORCE=true ; shift ;; - -p|--bin-path) shift ; OPT_BIN_PATH="$1" ; shift ;; - *) die "Invalid option $1" ;; - esac - done -} - function _parse_setup_opts() { OPT_FROM_FILE=false IMAGE_FILE="" + OPT_ARCH=false ARCH_ARG="" OPT_DELETE=false while [[ -n "$1" ]] do case "$1" in -i|--from-file) OPT_FROM_FILE=true ; shift ; IMAGE_FILE=$1 ; shift ;; - -a|--arch) shift ; ARCH_ARG=$1; shift ;; + -a|--arch) OPT_ARCH=true ; shift ; ARCH_ARG=$1; shift ;; -d|--delete) OPT_DELETE=true ; shift ;; *) die "Invalid option $1" ;; esac @@ -250,7 +219,6 @@ function execute_operation() { $ACT_VERSION && version && return if $ACT_BUILD; then - # shellcheck disable=SC2086 build_image_env $OPT_DISABLE_CHECK return fi @@ -265,11 +233,10 @@ function execute_operation() { fi if $OPT_FROM_FILE; then - setup_env_from_file "$IMAGE_FILE" + setup_env_from_file $IMAGE_FILE else - setup_env "$ARCH_ARG" + setup_env $ARCH_ARG fi - create_wrappers fi return @@ -281,24 +248,14 @@ function execute_operation() { die "Error: The image is still not installed in $JUNEST_HOME. Run this first: $CMD setup" fi - if $ACT_CREATE_WRAPPERS; then - # shellcheck disable=SC2086 - create_wrappers $OPT_FORCE "$OPT_BIN_PATH" - exit - fi - local run_env if $ACT_NAMESPACE; then - if $OPT_FAKEROOT; then - run_env=run_env_as_bwrap_fakeroot - else - run_env=run_env_as_bwrap_user - fi + run_env=run_env_with_namespace elif $ACT_PROOT; then if $OPT_FAKEROOT; then - run_env=run_env_as_proot_fakeroot + run_env=run_env_as_fakeroot else - run_env=run_env_as_proot_user + run_env=run_env_as_user fi elif $ACT_GROOT; then run_env=run_env_as_groot @@ -306,11 +263,8 @@ function execute_operation() { run_env=run_env_as_chroot fi - # Call create_wrappers in case new bin files have been created - # shellcheck disable=SC2064 - trap "PATH=$PATH create_wrappers" EXIT QUIT TERM - # shellcheck disable=SC2086 - $run_env "$BACKEND_COMMAND" "${BACKEND_ARGS}" $OPT_NO_COPY_FILES "${ARGS[@]}" + $run_env "${BACKEND_ARGS}" $OPT_NO_COPY_FILES "${ARGS[@]}" + } function main() { diff --git a/bin/sudoj b/bin/sudoj deleted file mode 100755 index aa43e15..0000000 --- a/bin/sudoj +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash -# -# This file is part of JuNest (https://github.com/fsquillace/junest). -# - -export PATH="${PATH}:${JUNEST_HOME}/usr/bin_wrappers" - -JUNEST_ARGS="ns --fakeroot" "$@" diff --git a/ci/build_image.sh b/ci/build_image.sh deleted file mode 100755 index f9cda95..0000000 --- a/ci/build_image.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env bash - -set -ex - -pacman -Sy --noconfirm sudo - -# Create a travis user -echo "travis ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/travis -chmod 'u=r,g=r,o=' /etc/sudoers.d/travis -groupadd --gid "2000" "travis" -useradd --create-home --uid "2000" --gid "2000" --shell /usr/bin/false "travis" - -# Here do not make any validation (-n) because it will be done later on in the Ubuntu host directly -cd /build -runuser -u travis -- /build/bin/junest build -n diff --git a/ci/deploy.sh b/ci/deploy.sh deleted file mode 100755 index a45d0a1..0000000 --- a/ci/deploy.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env bash - -set -e - -IMG_PATH=$1 - -set -ux - -MAX_OLD_IMAGES=5 -ENDPOINT="https://8da1bcd84e423c9b013b69fe1e8b4675.r2.cloudflarestorage.com" - -# ARCH can be one of: x86, x86_64, arm -HOST_ARCH=$(uname -m) -if [ "$HOST_ARCH" == "i686" ] || [ "$HOST_ARCH" == "i386" ] -then - ARCH="x86" -elif [ "$HOST_ARCH" == "x86_64" ] -then - ARCH="x86_64" -elif [[ $HOST_ARCH =~ .*(arm).* ]] -then - ARCH="arm" -else - echo "Unknown architecture ${HOST_ARCH}" >&2 - exit 11 -fi - -if [[ "$TRAVIS_BRANCH" == "master" ]] -then - - export AWS_DEFAULT_REGION=auto - # Upload image - # The put is done via a temporary filename in order to prevent outage on the - # production file for a longer period of time. - img_name=$(basename "${IMG_PATH}") - aws s3 --endpoint-url="$ENDPOINT" cp "${IMG_PATH}" s3://junest-repo/junest/ - - DATE=$(date +'%Y-%m-%d-%H-%M-%S') - aws s3 --endpoint-url="$ENDPOINT" cp "${IMG_PATH}" "s3://junest-repo/junest/${img_name}.${DATE}" - - # Cleanup old images - aws s3 --endpoint-url="$ENDPOINT" ls s3://junest-repo/junest/junest-${ARCH}.tar.gz. | awk '{print $4}' | head -n -${MAX_OLD_IMAGES} | xargs -I {} aws s3 --endpoint-url="$ENDPOINT" rm "s3://junest-repo/junest/{}" - - # Test the newly deployed image can be downloaded correctly - junest setup - junest -- echo "Installed JuNest (\$(uname -m))" - yes | junest setup --delete -fi diff --git a/ci/install-bash.sh b/ci/install-bash.sh deleted file mode 100755 index b766123..0000000 --- a/ci/install-bash.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh -set -ex - -VERSION=$1 - -cd /tmp -wget "http://ftp.gnu.org/gnu/bash/bash-$VERSION.tar.gz" - -tar -zxf "bash-$VERSION.tar.gz" -cd /tmp/bash-"$VERSION"* -./configure -make -sudo make install diff --git a/lib/checks/check.sh b/lib/checks/check.sh index 789206e..ac34171 100755 --- a/lib/checks/check.sh +++ b/lib/checks/check.sh @@ -1,5 +1,4 @@ #!/usr/bin/env bash -# shellcheck disable=SC1091 # # This modules is used for: # - Running checks against the building JuNest image @@ -10,32 +9,21 @@ # # vim: ft=sh -set -ex - +set -eu +OPT_RUN_ROOT_TESTS=${1:-false} RUN_ROOT_TESTS=false +[[ ${OPT_RUN_ROOT_TESTS} == "--run-root-tests" ]] && RUN_ROOT_TESTS=true + +OPT_SKIP_AUR_TESTS=${1:-false} SKIP_AUR_TESTS=false -USE_SUDO=false -while [[ -n "$1" ]] -do - case "$1" in - --run-root-tests) RUN_ROOT_TESTS=true ; shift ;; - --skip-aur-tests) SKIP_AUR_TESTS=true ; shift ;; - --use-sudo) USE_SUDO=true ; shift ;; - *) die "Invalid option $1" ;; - esac -done - -set -u - -SUDO="" -[[ -n $USE_SUDO ]] && SUDO="sudo" +[[ ${OPT_SKIP_AUR_TESTS} == "--skip-aur-tests" ]] && SKIP_AUR_TESTS=true JUNEST_HOME=${JUNEST_HOME:-$HOME/.junest} # JUNEST_BASE can be overridden for testing purposes. # There is no need for doing it for normal usage. -JUNEST_BASE="${JUNEST_BASE:-$(readlink -f "$(dirname "$(readlink -f "$0")")"/../..)}" +JUNEST_BASE="${JUNEST_BASE:-$(readlink -f $(dirname $(readlink -f "$0"))/../..)}" source "${JUNEST_BASE}/lib/utils/utils.sh" source "${JUNEST_BASE}/lib/core/common.sh" @@ -45,58 +33,61 @@ info "Validating JuNest located in ${JUNEST_HOME}..." info "Initial JuNest setup..." # The following ensures that the gpg agent gets killed (if exists) # otherwise it is not possible to exit from the session -trap "[[ -e /etc/pacman.d/gnupg/S.gpg-agent ]] && gpg-connect-agent -S /etc/pacman.d/gnupg/S.gpg-agent killagent /bye" QUIT EXIT ABRT TERM INT +trap "[[ -e /etc/pacman.d/gnupg/S.gpg-agent ]] && gpg-connect-agent -S /etc/pacman.d/gnupg/S.gpg-agent killagent /bye" QUIT EXIT ABRT KILL TERM INT -prepare_archlinux "$SUDO" +echo "Server = ${DEFAULT_MIRROR}" >> /etc/pacman.d/mirrorlist +pacman --noconfirm -Syy -PACMAN_OPTIONS="--noconfirm --disable-download-timeout" -# shellcheck disable=SC2086 -$SUDO pacman $PACMAN_OPTIONS -S grep coreutils -# shellcheck disable=SC2086 -# shellcheck disable=SC2046 -$SUDO pacman $PACMAN_OPTIONS -Syu --ignore sudo base-devel +pacman-key --init + +pacman --noconfirm -S archlinux-keyring +pacman-key --populate archlinux + +pacman --noconfirm -S archlinuxarm-keyring || echo "No ARM keyring detected" +pacman-key --populate archlinuxarm || echo "No ARM keyring detected" + +pacman --noconfirm -Su +pacman --noconfirm -S grep coreutils +pacman --noconfirm -S $(pacman -Sg base-devel | cut -d ' ' -f 2 | grep -v sudo) info "Checking basic executables work..." -$SUDO pacman -Qi pacman 1> /dev/null -/usr/bin/groot --help 1> /dev/null - -# Test FAKEROOTDONTTRYCHOWN is set to true by default -set +u -if [[ -z $FAKEROOTKEY ]] -then - fakeroot chown root /tmp -else - chown root /tmp -fi -set -u +pacman -Qi pacman 1> /dev/null +/opt/makepkg/bin/makepkg --help 1> /dev/null +/opt/proot/proot-$ARCH --help 1> /dev/null repo_package1=tree echo "Checking ${repo_package1} package from official repo..." -# shellcheck disable=SC2086 -$SUDO pacman $PACMAN_OPTIONS -S ${repo_package1} +pacman --noconfirm -S ${repo_package1} tree -L 1 -# shellcheck disable=SC2086 -$SUDO pacman $PACMAN_OPTIONS -Rsn ${repo_package1} +pacman --noconfirm -Rsn ${repo_package1} repo_package2=iftop info "Checking ${repo_package2} package from official repo..." -# shellcheck disable=SC2086 -$SUDO pacman $PACMAN_OPTIONS -S ${repo_package2} -if $RUN_ROOT_TESTS -then - # Time it out given that sometimes it gets stuck after few seconds. - $SUDO timeout 10 iftop -t -s 5 || true -fi -# shellcheck disable=SC2086 -$SUDO pacman $PACMAN_OPTIONS -Rsn ${repo_package2} +pacman --noconfirm -S ${repo_package2} +$RUN_ROOT_TESTS && iftop -t -s 5 +pacman --noconfirm -Rsn ${repo_package2} if ! $SKIP_AUR_TESTS then - aur_package=tcptraceroute + aur_package=aurutils info "Checking ${aur_package} package from AUR repo..." - yay --noconfirm -S ${aur_package} - # shellcheck disable=SC2086 - $SUDO pacman $PACMAN_OPTIONS -Rsn ${aur_package} + maindir=$(mktemp -d -t ${CMD}.XXXXXXXXXX) + builtin cd ${maindir} + curl -L -J -O -k "https://aur.archlinux.org/cgit/aur.git/plain/PKGBUILD?h=${aur_package}" + curl -L -J -O -k "https://aur.archlinux.org/cgit/aur.git/plain/${aur_package}.install?h=${aur_package}" + /opt/makepkg/bin/makepkg -sfcd + + pacman --noconfirm -U ${aur_package}*.pkg.tar.xz + aur search aur 1> /dev/null + pacman --noconfirm -Rsn ${aur_package} +fi + +# The following ensures that the gpg agent gets killed (if exists) +# otherwise it is not possible to exit from the session +if [[ -e /etc/pacman.d/gnupg/S.gpg-agent ]] +then + gpg-connect-agent -S /etc/pacman.d/gnupg/S.gpg-agent killagent /bye || echo "GPG agent did not close properly" + echo "GPG agent closed" fi exit 0 diff --git a/lib/checks/check_all.sh b/lib/checks/check_all.sh deleted file mode 100755 index 13e9237..0000000 --- a/lib/checks/check_all.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env bash -# Multiple tests against different execution modes - -set -ex - -# JUNEST_BASE can be overridden for testing purposes. -# There is no need for doing it for normal usage. -JUNEST_BASE="${JUNEST_BASE:-$(readlink -f "$(dirname "$(readlink -f "$0")")"/../..)}" - -JUNEST_SCRIPT=${JUNEST_SCRIPT:-${JUNEST_BASE}/bin/junest} - -CHECK_SCRIPT=${JUNEST_BASE}/lib/checks/check.sh - -$JUNEST_SCRIPT proot --fakeroot -- "$CHECK_SCRIPT" --skip-aur-tests -$JUNEST_SCRIPT proot -- "$CHECK_SCRIPT" --skip-aur-tests --use-sudo -# Test the backend command option -$JUNEST_SCRIPT proot --backend-command "$JUNEST_HOME/usr/bin/proot-x86_64" -- exit -$JUNEST_SCRIPT ns --fakeroot -- "$CHECK_SCRIPT" --skip-aur-tests -$JUNEST_SCRIPT ns -- "$CHECK_SCRIPT" --use-sudo -# Test the backend command option -$JUNEST_SCRIPT ns --backend-command "$JUNEST_HOME/usr/bin/bwrap" -- exit -sudo -E "$JUNEST_SCRIPT" groot -- "$CHECK_SCRIPT" --run-root-tests --skip-aur-tests - -# Test the wrappers work -"$JUNEST_SCRIPT" create-bin-wrappers --force -"$JUNEST_HOME"/usr/bin_wrappers/pacman --help - -"$JUNEST_SCRIPT" create-bin-wrappers --force --bin-path /usr/bin/core_perl/ -"$JUNEST_HOME"/usr/bin/core_perl_wrappers/shasum --help - -"${JUNEST_BASE}/bin/sudoj" pacman -Syu diff --git a/lib/core/build.sh b/lib/core/build.sh index 65a9474..1406ed7 100644 --- a/lib/core/build.sh +++ b/lib/core/build.sh @@ -8,134 +8,100 @@ # # vim: ft=sh -function _install_pkg(){ - # This function allows to install packages from AUR. - # At the moment is not used. - local maindir=$1 - local pkgbuilddir=$2 - # Generate a working directory because sources will be downloaded to there - working_dir=$(TMPDIR=/tmp mktemp -d -t junest-wd.XXXXXXXXXX) - cp -R "$pkgbuilddir"/* "$working_dir" - builtin cd "${working_dir}" || return 1 - makepkg -sfcd - makepkg --printsrcinfo > "${pkgbuilddir}"/.SRCINFO - sudo pacman --noconfirm --root "${maindir}"/root -U ./*.pkg.tar.* +function _check_package(){ + if ! pacman -Qq $1 > /dev/null + then + die "Package $1 must be installed" + fi } -function _prepare() { - # ArchLinux System initialization - prepare_archlinux - # curl is used to download pacman.conf file - sudo pacman -S --noconfirm git arch-install-scripts haveged curl +function _install_pkg_from_aur(){ + local maindir=$1 + local pkgname=$2 + local installname=$3 + mkdir -p ${maindir}/packages/${pkgname} + builtin cd ${maindir}/packages/${pkgname} + $CURL "https://aur.archlinux.org/cgit/aur.git/plain/PKGBUILD?h=${pkgname}" + [ -z "${installname}" ] || $CURL "https://aur.archlinux.org/cgit/aur.git/plain/${installname}?h=${pkgname}" + makepkg -sfcd + sudo pacman --noconfirm --root ${maindir}/root -U ${pkgname}*.pkg.tar.xz +} + +function _install_pkg(){ + local maindir=$1 + local pkgbuilddir=$2 + builtin cd ${pkgbuilddir} + makepkg -sfcd + sudo pacman --noconfirm --root ${maindir}/root -U *.pkg.tar.xz } function build_image_env(){ - set -x umask 022 # The function must runs on ArchLinux with non-root privileges. - # This is because installing AUR packages can be done by normal users only. (( EUID == 0 )) && \ die "You cannot build with root privileges." - _prepare + _check_package arch-install-scripts + _check_package gcc local disable_validation=$1 - local maindir - maindir=$(TMPDIR=$JUNEST_TEMPDIR mktemp -d -t "${CMD}".XXXXXXXXXX) - sudo mkdir -p "${maindir}"/root - trap - QUIT EXIT ABRT TERM INT - # shellcheck disable=SC2064 - trap "sudo rm -rf ${maindir}; die \"Error occurred when installing ${NAME}\"" EXIT QUIT ABRT TERM INT + local maindir=$(TMPDIR=$JUNEST_TEMPDIR mktemp -d -t ${CMD}.XXXXXXXXXX) + sudo mkdir -p ${maindir}/root + trap - QUIT EXIT ABRT KILL TERM INT + trap "sudo rm -rf ${maindir}; die \"Error occurred when installing ${NAME}\"" EXIT QUIT ABRT KILL TERM INT info "Installing pacman and its dependencies..." + # The archlinux-keyring and libunistring are due to missing dependencies declaration in ARM archlinux # All the essential executables (ln, mkdir, chown, etc) are in coreutils - # bwrap command belongs to bubblewrap - sudo pacstrap -G -M "${maindir}"/root pacman coreutils bubblewrap + # unshare command belongs to util-linux + sudo pacstrap -G -M -d ${maindir}/root pacman coreutils libunistring archlinux-keyring util-linux + sudo bash -c "echo 'Server = $DEFAULT_MIRROR' >> ${maindir}/root/etc/pacman.d/mirrorlist" + sudo mkdir -p ${maindir}/root/run/lock - if [[ ${ARCH} != "arm" ]] - then - # x86_64 does not have any mirror set by default... - sudo bash -c "echo 'Server = $DEFAULT_MIRROR' >> ${maindir}/root/etc/pacman.d/mirrorlist" - fi - sudo mkdir -p "${maindir}"/root/run/lock + # AUR packages requires non-root user to be compiled. proot fakes the user to 10 + _install_pkg ${maindir} "$JUNEST_BASE/pkgs/sudo-fake" - # For some reasons, pacstrap does not create the pacman.conf file, - # I could not reproduce the issue locally though: - # https://app.travis-ci.com/github/fsquillace/junest/builds/268216346 - [[ -e "${maindir}"/root/etc/pacman.conf ]] || sudo curl "https://gitlab.archlinux.org/archlinux/packaging/packages/pacman/-/raw/main/pacman.conf" -o "${maindir}/root/etc/pacman.conf" - - # Pacman/pacstrap bug: https://gitlab.archlinux.org/archlinux/packaging/packages/arch-install-scripts/-/issues/3 - sudo sed -i '/^DownloadUser = alpm$/d' "${maindir}"/root/etc/pacman.conf - - sudo tee -a "${maindir}"/root/etc/pacman.conf < ${maindir}/root/etc/${CMD}/info" - # Related to: https://github.com/fsquillace/junest/issues/305 - sudo bash -c "echo 'export FAKEROOTDONTTRYCHOWN=true' > ${maindir}/root/etc/profile.d/junest.sh" + info "Install ${NAME} script..." + _install_pkg_from_aur ${maindir} "${CMD}-git" "${CMD}.install" info "Generating the locales..." - # sed command is required for locale-gen but it is required by fakeroot - # and cannot be removed - # localedef (called by locale-gen) requires gzip but it is supposed to be - # already installed as systemd already depends on it - sudo pacman --noconfirm --root "${maindir}"/root -S sed gzip - sudo ln -sf /usr/share/zoneinfo/posix/UTC "${maindir}"/root/etc/localtime + # sed command is required for locale-gen + # localedef (called by locale-gen) requires gzip + sudo pacman --noconfirm --root ${maindir}/root -S sed gzip + sudo ln -sf /usr/share/zoneinfo/posix/UTC ${maindir}/root/etc/localtime sudo bash -c "echo 'en_US.UTF-8 UTF-8' >> ${maindir}/root/etc/locale.gen" - sudo "${maindir}"/root/bin/groot "${maindir}"/root locale-gen + sudo ${maindir}/root/opt/junest/bin/groot ${maindir}/root locale-gen sudo bash -c "echo LANG=\"en_US.UTF-8\" >> ${maindir}/root/etc/locale.conf" + sudo pacman --noconfirm --root ${maindir}/root -Rsn sed gzip info "Setting up the pacman keyring (this might take a while!)..." - if [[ $(uname -m) == *"arm"* ]] - then - sudo pacman -S --noconfirm --root "${maindir}"/root archlinuxarm-keyring - else - sudo pacman -S --noconfirm --root "${maindir}"/root archlinux-keyring - fi - sudo mount --bind "${maindir}"/root "${maindir}"/root - sudo arch-chroot "${maindir}"/root bash -c ' - set -e - pacman-key --init; - for keyring_file in /usr/share/pacman/keyrings/*.gpg; - do - keyring=$(basename $keyring_file | cut -f 1 -d "."); - pacman-key --populate $keyring; - done;' - sudo umount "${maindir}"/root + sudo ${maindir}/root/opt/junest/bin/groot -b /dev ${maindir}/root bash -c \ + "pacman-key --init; pacman-key --populate archlinux; [ -e /etc/pacman.d/gnupg/S.gpg-agent ] && gpg-connect-agent -S /etc/pacman.d/gnupg/S.gpg-agent killagent /bye" - sudo rm "${maindir}"/root/var/cache/pacman/pkg/* + sudo rm ${maindir}/root/var/cache/pacman/pkg/* # This is needed on system with busybox tar command. # If the file does not have write permission, the tar command to extract files fails. - sudo chmod -R u+rw "${maindir}"/root/ + sudo chmod -R u+rw ${maindir}/root/etc/ca-certificates/extracted/cadir - mkdir -p "${maindir}"/output - builtin cd "${maindir}"/output || return 1 + mkdir -p ${maindir}/output + builtin cd ${maindir}/output local imagefile="${CMD}-${ARCH}.tar.gz" info "Compressing image to ${imagefile}..." - sudo "$TAR" -zcpf "${imagefile}" -C "${maindir}"/root . + sudo $TAR -zcpf ${imagefile} -C ${maindir}/root . if ! $disable_validation then - mkdir -p "${maindir}"/root_test - $TAR -zxpf "${imagefile}" -C "${maindir}/root_test" - JUNEST_HOME="${maindir}/root_test" "${JUNEST_BASE}"/lib/checks/check_all.sh + mkdir -p ${maindir}/root_test + $TAR -zxpf ${imagefile} -C "${maindir}/root_test" + JUNEST_HOME="${maindir}/root_test" ${JUNEST_BASE}/bin/${CMD} proot -f ${JUNEST_BASE}/lib/checks/check.sh + JUNEST_HOME="${maindir}/root_test" ${JUNEST_BASE}/bin/${CMD} ns ${JUNEST_BASE}/lib/checks/check.sh + JUNEST_HOME="${maindir}/root_test" sudo -E ${JUNEST_BASE}/bin/${CMD} groot ${JUNEST_BASE}/lib/checks/check.sh --run-root-tests fi - sudo cp "${maindir}"/output/"${imagefile}" "${ORIGIN_WD}" + sudo cp ${maindir}/output/${imagefile} ${ORIGIN_WD} - builtin cd "${ORIGIN_WD}" || return 1 + builtin cd ${ORIGIN_WD} trap - QUIT EXIT ABRT KILL TERM INT sudo rm -fr "$maindir" - - set +x } diff --git a/lib/core/chroot.sh b/lib/core/chroot.sh index c2237a9..eb584f0 100644 --- a/lib/core/chroot.sh +++ b/lib/core/chroot.sh @@ -18,23 +18,21 @@ function _run_env_as_xroot(){ local uid=$UID # SUDO_USER is more reliable compared to SUDO_UID - [[ -z $SUDO_USER ]] || uid=$SUDO_USER:$SUDO_GID + [ -z $SUDO_USER ] || uid=$SUDO_USER:$SUDO_GID - local args=() - [[ "$1" != "" ]] && args=("-c" "$(insert_quotes_on_spaces "${@}")") + local main_cmd="${SH[@]}" + [ "$1" != "" ] && main_cmd="$(insert_quotes_on_spaces "$@")" # With chown the ownership of the files is assigned to the real user trap - QUIT EXIT ABRT KILL TERM INT - # shellcheck disable=SC2064 - trap "[ -z $uid ] || chown_cmd -R ${uid} ${JUNEST_HOME};" EXIT QUIT ABRT TERM INT + trap "[ -z $uid ] || chown_cmd -R ${uid} ${JUNEST_HOME};" EXIT QUIT ABRT KILL TERM INT if ! $no_copy_files then copy_common_files fi - # shellcheck disable=SC2086 - JUNEST_ENV=1 $cmd $backend_args "$JUNEST_HOME" "${DEFAULT_SH[@]}" "${args[@]}" + JUNEST_ENV=1 $cmd $backend_args "$JUNEST_HOME" "${SH[@]}" "-c" "${main_cmd}" } ####################################### @@ -45,13 +43,13 @@ function _run_env_as_xroot(){ # UID (RO) : The user ID. # SUDO_USER (RO) : The sudo user ID. # SUDO_GID (RO) : The sudo group ID. -# DEFAULT_SH (RO) : Contains the default command to run in JuNest. +# SH (RO) : Contains the default command to run in JuNest. # Arguments: # backend_args ($1) : The arguments to pass to backend program # no_copy_files ($2?) : If false it will copy some files in /etc # from host to JuNest environment. # cmd ($3-?) : The command to run inside JuNest environment. -# Default command is defined by DEFAULT_SH variable. +# Default command is defined by SH variable. # Returns: # $ARCHITECTURE_MISMATCH : If host and JuNest architecture are different. # Output: @@ -60,16 +58,15 @@ function _run_env_as_xroot(){ function run_env_as_groot(){ check_nested_env - local backend_command="${1:-$GROOT}" - local backend_args="$2" - local no_copy_files="$3" - shift 3 + local backend_args="$1" + local no_copy_files="$2" + shift 2 provide_common_bindings local bindings=${RESULT} unset RESULT - _run_env_as_xroot "$backend_command $bindings" "$backend_args" "$no_copy_files" "$@" + _run_env_as_xroot "$GROOT $bindings" "$backend_args" "$no_copy_files" "$@" } ####################################### @@ -80,13 +77,13 @@ function run_env_as_groot(){ # UID (RO) : The user ID. # SUDO_USER (RO) : The sudo user ID. # SUDO_GID (RO) : The sudo group ID. -# DEFAULT_SH (RO) : Contains the default command to run in JuNest. +# SH (RO) : Contains the default command to run in JuNest. # Arguments: # backend_args ($1) : The arguments to pass to backend program # no_copy_files ($2?) : If false it will copy some files in /etc # from host to JuNest environment. # cmd ($3-?) : The command to run inside JuNest environment. -# Default command is defined by DEFAULT_SH variable. +# Default command is defined by SH variable. # Returns: # $ARCHITECTURE_MISMATCH : If host and JuNest architecture are different. # Output: @@ -95,10 +92,9 @@ function run_env_as_groot(){ function run_env_as_chroot(){ check_nested_env - local backend_command="${1:-chroot_cmd}" - local backend_args="$2" - local no_copy_files="$3" - shift 3 + local backend_args="$1" + local no_copy_files="$2" + shift 2 - _run_env_as_xroot "$backend_command" "$backend_args" "$no_copy_files" "$@" + _run_env_as_xroot chroot_cmd "$backend_args" "$no_copy_files" "$@" } diff --git a/lib/core/common.sh b/lib/core/common.sh index df79bec..996c24f 100644 --- a/lib/core/common.sh +++ b/lib/core/common.sh @@ -1,6 +1,4 @@ #!/usr/bin/env bash -# shellcheck disable=SC2034 -# shellcheck disable=SC1091 # # This module contains all common functionalities for JuNest. # @@ -23,29 +21,28 @@ NO_CONFIG_FOUND=108 UNPRIVILEGED_USERNS_DISABLED=109 JUNEST_HOME=${JUNEST_HOME:-~/.${CMD}} +JUNEST_BASE=${JUNEST_BASE:-${JUNEST_HOME}/opt/junest} JUNEST_TEMPDIR=${JUNEST_TEMPDIR:-/tmp} # The update of the variable PATH ensures that the executables are # found on different locations -PATH=/usr/bin:/bin:/usr/local/bin:/usr/sbin:/sbin:${HOME}/.local/bin:"$PATH" +PATH=$PATH:/usr/bin:/bin:/usr/sbin:/sbin # The executable uname is essential in order to get the architecture # of the host system, so a fallback mechanism cannot be used for it. -UNAME="uname" +UNAME=uname ARCH_LIST=('x86_64' 'x86' 'arm') HOST_ARCH=$($UNAME -m) -# To check all available architectures look here: -# https://wiki.archlinux.org/index.php/PKGBUILD#arch -if [[ $HOST_ARCH == "i686" ]] || [[ $HOST_ARCH == "i386" ]] +if [ $HOST_ARCH == "i686" ] || [ $HOST_ARCH == "i386" ] then ARCH="x86" LD_LIB="${JUNEST_HOME}/lib/ld-linux.so.2" -elif [[ $HOST_ARCH == "x86_64" ]] +elif [ $HOST_ARCH == "x86_64" ] then ARCH="x86_64" LD_LIB="${JUNEST_HOME}/lib64/ld-linux-x86-64.so.2" -elif [[ $HOST_ARCH =~ .*(arm).* ]] || [[ $HOST_ARCH == "aarch64" ]] +elif [[ $HOST_ARCH =~ .*(arm).* ]] then ARCH="arm" LD_LIB="${JUNEST_HOME}/lib/ld-linux-armhf.so.3" @@ -53,11 +50,9 @@ else die "Unknown architecture ${HOST_ARCH}" fi -MAIN_REPO=https://link.storjshare.io/s/jvb5tgarnjtt565fffa44spvyuga/junest-repo -MAIN_REPO=https://pub-a2af2344e8554f6c807bc3db355ae622.r2.dev +MAIN_REPO=https://s3-eu-west-1.amazonaws.com/${CMD}-repo ENV_REPO=${MAIN_REPO}/${CMD} -# shellcheck disable=SC2016 -DEFAULT_MIRROR='https://mirror.rackspace.com/archlinux/$repo/os/$arch' +DEFAULT_MIRROR='https://mirrors.kernel.org/archlinux/$repo/os/$arch' ORIGIN_WD=$(pwd) @@ -68,26 +63,24 @@ ORIGIN_WD=$(pwd) # different locations in the host OS. # List of executables that are run inside JuNest: -DEFAULT_SH=("/bin/sh" "--login") +SH=("/bin/sh" "--login") # List of executables that are run in the host OS: -BWRAP="${JUNEST_HOME}/usr/bin/bwrap" -PROOT="${JUNEST_HOME}/usr/bin/proot-${ARCH}" -GROOT="${JUNEST_HOME}/usr/bin/groot" +PROOT="${JUNEST_HOME}/opt/proot/proot-${ARCH}" +GROOT=${JUNEST_BASE}/bin/groot CLASSIC_CHROOT=chroot -WGET="wget --content-disposition --no-check-certificate" +WGET="wget --no-check-certificate" CURL="curl -L -J -O -k" -TAR="tar" +TAR=tar CHOWN="chown" -LN="ln" -RM="rm" -MKDIR="mkdir" -GETENT="getent" -CP="cp" -ID="id" +LN=ln +RM=rm +MKDIR=mkdir +GETENT=getent +CP=cp # Used for checking user namespace in config.gz file -ZGREP="zgrep" -UNSHARE="unshare" +ZGREP=zgrep +UNSHARE=unshare LD_EXEC="$LD_LIB --library-path ${JUNEST_HOME}/usr/lib:${JUNEST_HOME}/lib" @@ -96,32 +89,32 @@ LD_EXEC="$LD_LIB --library-path ${JUNEST_HOME}/usr/lib:${JUNEST_HOME}/lib" # image. function ln_cmd(){ - $LN "$@" || $LD_EXEC "${JUNEST_HOME}"/usr/bin/$LN "$@" + $LN "$@" || $LD_EXEC ${JUNEST_HOME}/usr/bin/$LN "$@" } function getent_cmd(){ - $GETENT "$@" || $LD_EXEC "${JUNEST_HOME}"/usr/bin/$GETENT "$@" + $GETENT "$@" || $LD_EXEC ${JUNEST_HOME}/usr/bin/$GETENT "$@" } function cp_cmd(){ - $CP "$@" || $LD_EXEC "${JUNEST_HOME}"/usr/bin/$CP "$@" + $CP "$@" || $LD_EXEC ${JUNEST_HOME}/usr/bin/$CP "$@" } function rm_cmd(){ - $RM "$@" || $LD_EXEC "${JUNEST_HOME}"/usr/bin/$RM "$@" + $RM "$@" || $LD_EXEC ${JUNEST_HOME}/usr/bin/$RM "$@" } function chown_cmd(){ - $CHOWN "$@" || $LD_EXEC "${JUNEST_HOME}"/usr/bin/$CHOWN "$@" + $CHOWN "$@" || $LD_EXEC ${JUNEST_HOME}/usr/bin/$CHOWN "$@" } function mkdir_cmd(){ - $MKDIR "$@" || $LD_EXEC "${JUNEST_HOME}"/usr/bin/$MKDIR "$@" + $MKDIR "$@" || $LD_EXEC ${JUNEST_HOME}/usr/bin/$MKDIR "$@" } function zgrep_cmd(){ # No need for LD_EXEC as zgrep is a POSIX shell script - $ZGREP "$@" || "${JUNEST_HOME}"/usr/bin/$ZGREP "$@" + $ZGREP "$@" || ${JUNEST_HOME}/usr/bin/$ZGREP "$@" } function download_cmd(){ @@ -129,7 +122,7 @@ function download_cmd(){ } function chroot_cmd(){ - $CLASSIC_CHROOT "$@" || $LD_EXEC "${JUNEST_HOME}"/usr/bin/$CLASSIC_CHROOT "$@" + $CLASSIC_CHROOT "$@" || $LD_EXEC ${JUNEST_HOME}/usr/bin/$CLASSIC_CHROOT "$@" } function unshare_cmd(){ @@ -137,40 +130,29 @@ function unshare_cmd(){ # with --user option available. # Hence, give priority to the `unshare` executable in JuNest image. # Also, unshare provides an environment in which /bin/sh maps to dash shell, - # therefore it ignores all the remaining DEFAULT_SH arguments (i.e. --login) as + # therefore it ignores all the remaining SH arguments (i.e. --login) as # they are not supported by dash. - if $LD_EXEC "${JUNEST_HOME}"/usr/bin/$UNSHARE --user "${DEFAULT_SH[0]}" "-c" ":" + if $LD_EXEC ${JUNEST_HOME}/usr/bin/$UNSHARE --user "${SH[0]}" "-c" ":" then - $LD_EXEC "${JUNEST_HOME}"/usr/bin/$UNSHARE "${@}" - elif $UNSHARE --user "${DEFAULT_SH[0]}" "-c" ":" + $LD_EXEC ${JUNEST_HOME}/usr/bin/$UNSHARE "${@}" + elif $UNSHARE --user "${SH[0]}" "-c" ":" then $UNSHARE "$@" else - die "Error: Something went wrong while executing unshare command. Exiting" - fi -} - -function bwrap_cmd(){ - if $LD_EXEC "$BWRAP" --dev-bind / / "${DEFAULT_SH[0]}" "-c" ":" - then - $LD_EXEC "$BWRAP" "${@}" - else - die "Error: Something went wrong while executing bwrap command. Exiting" + die "Error: Something went wrong with unshare command. Exiting" fi } function proot_cmd(){ local proot_args="$1" shift - # shellcheck disable=SC2086 - if ${PROOT} ${proot_args} "${DEFAULT_SH[@]}" "-c" ":" + if ${PROOT} ${proot_args} "${SH[@]}" "-c" ":" then - # shellcheck disable=SC2086 ${PROOT} ${proot_args} "${@}" - elif PROOT_NO_SECCOMP=1 ${PROOT} ${proot_args} "${DEFAULT_SH[@]}" "-c" ":" + elif PROOT_NO_SECCOMP=1 ${PROOT} ${proot_args} "${SH[@]}" "-c" ":" then warn "Warn: Proot is not properly working. Disabling SECCOMP and expect the application to run slowly in particular when it uses syscalls intensively." - warn "Try to use Linux namespace instead as it is more reliable: junest ns" + warn "Try to use Linux namespace instead as it is more reliable: junest -u" PROOT_NO_SECCOMP=1 ${PROOT} ${proot_args} "${@}" else die "Error: Something went wrong with proot command. Exiting" @@ -199,7 +181,7 @@ function check_nested_env() { if [[ $JUNEST_ENV == "1" ]] then die_on_status $NESTED_ENVIRONMENT "Error: Nested ${NAME} environments are not allowed" - elif [[ -n $JUNEST_ENV ]] && [[ $JUNEST_ENV != "0" ]] + elif [[ ! -z $JUNEST_ENV ]] && [[ $JUNEST_ENV != "0" ]] then die_on_status $VARIABLE_NOT_SET "The variable JUNEST_ENV is not properly set" fi @@ -221,7 +203,7 @@ function check_nested_env() { # None ####################################### function check_same_arch() { - source "${JUNEST_HOME}"/etc/junest/info + source ${JUNEST_HOME}/etc/junest/info [ "$JUNEST_ARCH" != "$ARCH" ] && \ die_on_status $ARCHITECTURE_MISMATCH "The host system architecture is not correct: $ARCH != $JUNEST_ARCH" return 0 @@ -246,7 +228,7 @@ function check_same_arch() { function provide_common_bindings(){ RESULT="" local re='(.*):.*' - for bind in "/dev" "/sys" "/proc" "/tmp" "$HOME" "/run/user/$($ID -u)" + for bind in "/dev" "/sys" "/proc" "/tmp" "$HOME" do if [[ $bind =~ $re ]] then @@ -279,26 +261,24 @@ function copy_passwd_and_group(){ # is configured. # Try to at least get the current user via `getent passwd $USER` since it uses # a more reliable and faster system call (getpwnam(3)). - if ! getent_cmd passwd > "${JUNEST_HOME}"/etc/passwd || \ - ! getent_cmd passwd "${USER}" >> "${JUNEST_HOME}"/etc/passwd + if ! getent_cmd passwd > ${JUNEST_HOME}/etc/passwd || \ + ! getent_cmd passwd ${USER} >> ${JUNEST_HOME}/etc/passwd then warn "getent command failed or does not exist. Binding directly from /etc/passwd." - copy_file /etc/passwd + copy_file /etc/passwd ${JUNEST_HOME}/etc/passwd fi - if ! getent_cmd group > "${JUNEST_HOME}"/etc/group + if ! getent_cmd group > ${JUNEST_HOME}/etc/group then warn "getent command failed or does not exist. Binding directly from /etc/group." - copy_file /etc/group + copy_file /etc/group ${JUNEST_HOME}/etc/group fi return 0 } function copy_file() { local file="${1}" - # -f option ensure to remove destination file if it cannot be opened - # https://github.com/fsquillace/junest/issues/284 - [[ -r "$file" ]] && cp_cmd -f "$file" "${JUNEST_HOME}/$file" + [[ -r "$file" ]] && cp_cmd "$file" "${JUNEST_HOME}/$file" return 0 } @@ -309,27 +289,3 @@ function copy_common_files() { copy_file /etc/resolv.conf return 0 } - -function prepare_archlinux() { - local sudo=${1:-sudo} - local pacman_options="--noconfirm --disable-download-timeout" - - # shellcheck disable=SC2086 - $sudo pacman $pacman_options -Syy - - $sudo pacman-key --init - - if [[ $(uname -m) == *"arm"* ]] - then - # shellcheck disable=SC2086 - $sudo pacman $pacman_options -S archlinuxarm-keyring - $sudo pacman-key --populate archlinuxarm - else - # shellcheck disable=SC2086 - $sudo pacman $pacman_options -S archlinux-keyring - $sudo pacman-key --populate archlinux - fi - - # shellcheck disable=SC2086 - $sudo pacman $pacman_options -Su -} diff --git a/lib/core/namespace.sh b/lib/core/namespace.sh index 70763bd..7943faa 100644 --- a/lib/core/namespace.sh +++ b/lib/core/namespace.sh @@ -1,8 +1,9 @@ #!/usr/bin/env bash # -# This module contains functionalities for accessing to JuNest via bubblewrap. +# This module contains all namespace functionalities for JuNest. # -# https://github.com/containers/bubblewrap +# http://man7.org/linux/man-pages/man7/namespaces.7.html +# http://man7.org/linux/man-pages/man2/unshare.2.html # # Dependencies: # - lib/utils/utils.sh @@ -10,29 +11,11 @@ # # vim: ft=sh -# shellcheck disable=SC2027 -COMMON_BWRAP_OPTION="--bind "$JUNEST_HOME" / --bind "$HOME" "$HOME" --bind /tmp /tmp --bind /sys /sys --bind /proc /proc --dev-bind-try /dev /dev --bind-try "/run/user/$($ID -u)" "/run/user/$($ID -u)" --unshare-user-try" CONFIG_PROC_FILE="/proc/config.gz" CONFIG_BOOT_FILE="/boot/config-$($UNAME -r)" PROC_USERNS_CLONE_FILE="/proc/sys/kernel/unprivileged_userns_clone" -PROC_USERNS_FILE="/proc/$$/ns/user" function _is_user_namespace_enabled() { - if [[ -L $PROC_USERNS_FILE ]] - then - return 0 - fi - - if [[ -e $PROC_USERNS_CLONE_FILE ]] - then - # `-q` option in zgrep may cause a gzip: stdout: Broken pipe - # Use redirect to /dev/null instead - if zgrep_cmd "1" "$PROC_USERNS_CLONE_FILE" > /dev/null - then - return 0 - fi - fi - local config_file="" if [[ -e $CONFIG_PROC_FILE ]] then @@ -41,101 +24,83 @@ function _is_user_namespace_enabled() { then config_file=$CONFIG_BOOT_FILE else - return "$NOT_EXISTING_FILE" + return $NOT_EXISTING_FILE fi - # `-q` option in zgrep may cause a gzip: stdout: Broken pipe - # Use redirect to /dev/null instead - if ! zgrep_cmd "CONFIG_USER_NS=y" "$config_file" > /dev/null + if ! zgrep_cmd -q "CONFIG_USER_NS=y" $config_file then - return "$NO_CONFIG_FOUND" + return $NO_CONFIG_FOUND fi - return "$UNPRIVILEGED_USERNS_DISABLED" + if [[ ! -e $PROC_USERNS_CLONE_FILE ]] + then + return 0 + fi + + if ! zgrep_cmd -q "1" $PROC_USERNS_CLONE_FILE + then + return $UNPRIVILEGED_USERNS_DISABLED + fi + + return 0 } function _check_user_namespace() { set +e _is_user_namespace_enabled case $? in - "$NOT_EXISTING_FILE") warn "Could not understand if user namespace is enabled. No config.gz file found. Proceeding anyway..." ;; - "$NO_CONFIG_FOUND") warn "Unprivileged user namespace is disabled at kernel compile time or kernel too old (<3.8). Proceeding anyway..." ;; - "$UNPRIVILEGED_USERNS_DISABLED") warn "Unprivileged user namespace disabled. Root permissions are required to enable it: sudo sysctl kernel.unprivileged_userns_clone=1" ;; + $NOT_EXISTING_FILE) warn "Could not understand if user namespace is enabled. No config.gz file found. Proceeding anyway..." ;; + $NO_CONFIG_FOUND) warn "Unprivileged user namespace is disabled at kernel compile time or kernel too old (<3.8). Proceeding anyway..." ;; + $UNPRIVILEGED_USERNS_DISABLED) warn "Unprivileged user namespace disabled. Root permissions are required to enable it: sudo sysctl kernel.unprivileged_userns_clone=1" ;; esac set -e } +function _run_env_with_namespace(){ + local backend_args="$1" + shift -####################################### -# Run JuNest as fakeroot via bwrap -# -# Globals: -# JUNEST_HOME (RO) : The JuNest home directory. -# DEFAULT_SH (RO) : Contains the default command to run in JuNest. -# BWRAP (RO): : The location of the bwrap binary. -# Arguments: -# backend_args ($1) : The arguments to pass to bwrap -# no_copy_files ($2?) : If false it will copy some files in /etc -# from host to JuNest environment. -# cmd ($3-?) : The command to run inside JuNest environment. -# Default command is defined by DEFAULT_SH variable. -# Returns: -# $ARCHITECTURE_MISMATCH : If host and JuNest architecture are different. -# $ROOT_ACCESS_ERROR : If the user is the real root. -# Output: -# - : The command output. -####################################### -function run_env_as_bwrap_fakeroot(){ - check_nested_env + provide_common_bindings + local bindings=${RESULT} + unset RESULT - local backend_command="${1:-$BWRAP}" - local backend_args="$2" - local no_copy_files="$3" - shift 3 - - _check_user_namespace - - check_same_arch - - if ! $no_copy_files + # Use option -n in groot because umount do not work sometimes. + # As soon as the process terminates, the namespace + # will terminate too with its own mounted directories. + if [[ "$1" != "" ]] then - copy_common_files + JUNEST_ENV=1 unshare_cmd --mount --user --map-root-user $GROOT --no-umount --recursive $bindings $backend_args "$JUNEST_HOME" "${SH[@]}" "-c" "$(insert_quotes_on_spaces "${@}")" + else + JUNEST_ENV=1 unshare_cmd --mount --user --map-root-user $GROOT --no-umount --recursive $bindings $backend_args "$JUNEST_HOME" "${SH[@]}" fi - - local args=() - [[ "$1" != "" ]] && args=("-c" "$(insert_quotes_on_spaces "${@}")") - - # Fix PATH to /usr/bin to make sudo working and avoid polluting with host related bin paths - # shellcheck disable=SC2086 - PATH="/usr/bin" BWRAP="${backend_command}" JUNEST_ENV=1 bwrap_cmd $COMMON_BWRAP_OPTION --cap-add ALL --uid 0 --gid 0 $backend_args sudo "${DEFAULT_SH[@]}" "${args[@]}" } ####################################### -# Run JuNest as normal user via bwrap. +# Run JuNest as fakeroot user via user namespace. # # Globals: # JUNEST_HOME (RO) : The JuNest home directory. -# DEFAULT_SH (RO) : Contains the default command to run in JuNest. -# BWRAP (RO): : The location of the bwrap binary. +# GROOT (RO) : The groot program. +# SH (RO) : Contains the default command to run in JuNest. # Arguments: -# backend_args ($1) : The arguments to pass to bwrap +# backend_args ($1) : The arguments to pass to groot # no_copy_files ($2?) : If false it will copy some files in /etc # from host to JuNest environment. # cmd ($3-?) : The command to run inside JuNest environment. -# Default command is defined by DEFAULT_SH variable. +# Default command is defined by SH variable. # Returns: # $ARCHITECTURE_MISMATCH : If host and JuNest architecture are different. +# Depends on the unshare command outcome. # Output: # - : The command output. ####################################### -function run_env_as_bwrap_user() { +function run_env_with_namespace() { check_nested_env - local backend_command="${1:-$BWRAP}" - local backend_args="$2" - local no_copy_files="$3" - shift 3 + local backend_args="$1" + local no_copy_files="$2" + shift 2 _check_user_namespace @@ -152,14 +117,5 @@ function run_env_as_bwrap_user() { copy_passwd_and_group fi - local args=() - [[ "$1" != "" ]] && args=("-c" "$(insert_quotes_on_spaces "${@}")") - - # Resets PATH to avoid polluting with host related bin paths - # shellcheck disable=SC2086 - PATH='' BWRAP="${backend_command}" JUNEST_ENV=1 bwrap_cmd $COMMON_BWRAP_OPTION $backend_args "${DEFAULT_SH[@]}" "${args[@]}" + _run_env_with_namespace "$backend_args" "$@" } - - - - diff --git a/lib/core/proot.sh b/lib/core/proot.sh index b6c1c8f..69502eb 100644 --- a/lib/core/proot.sh +++ b/lib/core/proot.sh @@ -1,5 +1,4 @@ #!/usr/bin/env bash -# shellcheck disable=SC1091 # # This module contains all proot functionalities for JuNest. # @@ -10,39 +9,35 @@ # vim: ft=sh function _run_env_with_proot(){ - local backend_command="${1:-$PROOT}" - local backend_args="$2" - shift 2 + local proot_args="$1" + shift - local args=() - [[ "$1" != "" ]] && args=("-c" "$(insert_quotes_on_spaces "${@}")") - - # Resets PATH to avoid polluting with host related bin paths - PATH='' PROOT="${backend_command}" JUNEST_ENV=1 proot_cmd "${backend_args}" "${DEFAULT_SH[@]}" "${args[@]}" + if [ "$1" != "" ] + then + JUNEST_ENV=1 proot_cmd "${proot_args}" "${SH[@]}" "-c" "$(insert_quotes_on_spaces "${@}")" + else + JUNEST_ENV=1 proot_cmd "${proot_args}" "${SH[@]}" + fi } function _run_env_with_qemu(){ - local backend_command="$1" - local backend_args="$2" - shift 2 - - source "${JUNEST_HOME}"/etc/junest/info + local proot_args="$1" + source ${JUNEST_HOME}/etc/junest/info if [ "$JUNEST_ARCH" != "$ARCH" ] then local qemu_bin="qemu-$JUNEST_ARCH-static-$ARCH" local qemu_symlink="/tmp/${qemu_bin}-$RANDOM" trap - QUIT EXIT ABRT KILL TERM INT - # shellcheck disable=SC2064 - trap "[ -e ${qemu_symlink} ] && rm_cmd -f ${qemu_symlink}" EXIT QUIT ABRT TERM INT + trap "[ -e ${qemu_symlink} ] && rm_cmd -f ${qemu_symlink}" EXIT QUIT ABRT KILL TERM INT warn "Emulating $NAME via QEMU..." - [[ -e ${qemu_symlink} ]] || \ - ln_cmd -s "${JUNEST_HOME}/bin/${qemu_bin}" "${qemu_symlink}" - backend_args="-q ${qemu_symlink} $backend_args" + [ -e ${qemu_symlink} ] || \ + ln_cmd -s ${JUNEST_HOME}/opt/qemu/${qemu_bin} ${qemu_symlink} + proot_args="-q ${qemu_symlink} $proot_args" fi - - _run_env_with_proot "${backend_command}" "$backend_args" "${@}" + shift + _run_env_with_proot "$proot_args" "${@}" } ####################################### @@ -51,27 +46,26 @@ function _run_env_with_qemu(){ # Globals: # JUNEST_HOME (RO) : The JuNest home directory. # EUID (RO) : The user ID. -# DEFAULT_SH (RO) : Contains the default command to run in JuNest. +# SH (RO) : Contains the default command to run in JuNest. # Arguments: # backend_args ($1) : The arguments to pass to proot # no_copy_files ($2?) : If false it will copy some files in /etc # from host to JuNest environment. # cmd ($3-?) : The command to run inside JuNest environment. -# Default command is defined by DEFAULT_SH variable. +# Default command is defined by SH variable. # Returns: # $ROOT_ACCESS_ERROR : If the user is the real root. # Output: # - : The command output. ####################################### -function run_env_as_proot_fakeroot(){ +function run_env_as_fakeroot(){ (( EUID == 0 )) && \ - die_on_status "$ROOT_ACCESS_ERROR" "You cannot access with root privileges. Use --groot option instead." + die_on_status $ROOT_ACCESS_ERROR "You cannot access with root privileges. Use --groot option instead." check_nested_env - local backend_command="$1" - local backend_args="$2" - local no_copy_files="$3" - shift 3 + local backend_args="$1" + local no_copy_files="$2" + shift 2 if ! $no_copy_files then @@ -84,7 +78,7 @@ function run_env_as_proot_fakeroot(){ # An alternative is via -S option: #_run_env_with_qemu "-S ${JUNEST_HOME} $1" "${@:2}" - _run_env_with_qemu "$backend_command" "-0 ${bindings} -r ${JUNEST_HOME} $backend_args" "$@" + _run_env_with_qemu "-0 ${bindings} -r ${JUNEST_HOME} $backend_args" "$@" } ####################################### @@ -93,27 +87,26 @@ function run_env_as_proot_fakeroot(){ # Globals: # JUNEST_HOME (RO) : The JuNest home directory. # EUID (RO) : The user ID. -# DEFAULT_SH (RO) : Contains the default command to run in JuNest. +# SH (RO) : Contains the default command to run in JuNest. # Arguments: # backend_args ($1) : The arguments to pass to proot # no_copy_files ($2?) : If false it will copy some files in /etc # from host to JuNest environment. # cmd ($3-?) : The command to run inside JuNest environment. -# Default command is defined by DEFAULT_SH variable. +# Default command is defined by SH variable. # Returns: # $ROOT_ACCESS_ERROR : If the user is the real root. # Output: # - : The command output. ####################################### -function run_env_as_proot_user(){ +function run_env_as_user(){ (( EUID == 0 )) && \ - die_on_status "$ROOT_ACCESS_ERROR" "You cannot access with root privileges. Use --groot option instead." + die_on_status $ROOT_ACCESS_ERROR "You cannot access with root privileges. Use --groot option instead." check_nested_env - local backend_command="$1" - local backend_args="$2" - local no_copy_files="$3" - shift 3 + local backend_args="$1" + local no_copy_files="$2" + shift 2 if ! $no_copy_files then @@ -134,5 +127,5 @@ function run_env_as_proot_user(){ local bindings=${RESULT} unset RESULT - _run_env_with_qemu "$backend_command" "${bindings} -r ${JUNEST_HOME} $backend_args" "$@" + _run_env_with_qemu "${bindings} -r ${JUNEST_HOME} $backend_args" "$@" } diff --git a/lib/core/setup.sh b/lib/core/setup.sh index 58c6122..2cbfdf1 100644 --- a/lib/core/setup.sh +++ b/lib/core/setup.sh @@ -22,7 +22,7 @@ # None ####################################### function is_env_installed(){ - [[ -d "$JUNEST_HOME" ]] && [[ "$(ls -A "$JUNEST_HOME")" ]] && return 0 + [ -d "$JUNEST_HOME" ] && [ "$(ls -A $JUNEST_HOME)" ] && return 0 return 1 } @@ -30,7 +30,7 @@ function is_env_installed(){ function _cleanup_build_directory(){ local maindir=$1 check_not_null "$maindir" - builtin cd "$ORIGIN_WD" || return 1 + builtin cd $ORIGIN_WD trap - QUIT EXIT ABRT KILL TERM INT rm_cmd -fr "$maindir" } @@ -40,8 +40,7 @@ function _prepare_build_directory(){ local maindir=$1 check_not_null "$maindir" trap - QUIT EXIT ABRT KILL TERM INT - # shellcheck disable=SC2064 - trap "rm_cmd -rf ${maindir}; die \"Error occurred when installing ${NAME}\"" EXIT QUIT ABRT TERM INT + trap "rm_cmd -rf ${maindir}; die \"Error occurred when installing ${NAME}\"" EXIT QUIT ABRT KILL TERM INT } @@ -52,18 +51,11 @@ function _setup_env(){ is_env_installed && die "Error: ${NAME} has been already installed in $JUNEST_HOME" mkdir_cmd -p "${JUNEST_HOME}" - $TAR -zxpf "${imagepath}" -C "${JUNEST_HOME}" - info "${NAME} installed successfully!" - echo - info "Default mirror URL set to: ${DEFAULT_MIRROR}" - info "You can change the pacman mirror URL in /etc/pacman.d/mirrorlist according to your location:" - info " \$EDITOR ${JUNEST_HOME}/etc/pacman.d/mirrorlist" - echo + $TAR -zxpf ${imagepath} -C ${JUNEST_HOME} + info "The default mirror URL is ${DEFAULT_MIRROR}." info "Remember to refresh the package databases from the server:" info " pacman -Syy" - echo - info "To install packages from AUR follow the wiki here:" - info "https://github.com/fsquillace/junest#install-packages-from-aur" + info "${NAME} installed successfully" } @@ -78,6 +70,7 @@ function _setup_env(){ # the JuNest system from the image. # ENV_REPO (RO) : URL of the site containing JuNest images. # NAME (RO) : The JuNest name. +# DEFAULT_MIRROR (RO) : Arch Linux URL mirror. # Arguments: # arch ($1?) : The JuNest architecture image to download. # Defaults to the host architecture @@ -88,22 +81,21 @@ function _setup_env(){ ####################################### function setup_env(){ local arch=${1:-$ARCH} - contains_element "$arch" "${ARCH_LIST[@]}" || \ - die_on_status "$NOT_AVAILABLE_ARCH" "The architecture is not one of: ${ARCH_LIST[*]}" + contains_element $arch "${ARCH_LIST[@]}" || \ + die_on_status $NOT_AVAILABLE_ARCH "The architecture is not one of: ${ARCH_LIST[@]}" - local maindir - maindir=$(TMPDIR=$JUNEST_TEMPDIR mktemp -d -t "${CMD}".XXXXXXXXXX) - _prepare_build_directory "$maindir" + local maindir=$(TMPDIR=$JUNEST_TEMPDIR mktemp -d -t ${CMD}.XXXXXXXXXX) + _prepare_build_directory $maindir info "Downloading ${NAME}..." - builtin cd "${maindir}" || return 1 + builtin cd ${maindir} local imagefile=${CMD}-${arch}.tar.gz - download_cmd "${ENV_REPO}/${imagefile}" + download_cmd ${ENV_REPO}/${imagefile} info "Installing ${NAME}..." - _setup_env "${maindir}/${imagefile}" + _setup_env ${maindir}/${imagefile} - _cleanup_build_directory "${maindir}" + _cleanup_build_directory ${maindir} } ####################################### @@ -113,6 +105,7 @@ function setup_env(){ # JUNEST_HOME (RO) : The JuNest home directory in which JuNest needs # to be installed. # NAME (RO) : The JuNest name. +# DEFAULT_MIRROR (RO) : Arch Linux URL mirror. # Arguments: # imagefile ($1) : The JuNest image file. # Returns: @@ -123,10 +116,10 @@ function setup_env(){ function setup_env_from_file(){ local imagefile=$1 check_not_null "$imagefile" - [[ ! -e ${imagefile} ]] && die_on_status "$NOT_EXISTING_FILE" "Error: The ${NAME} image file ${imagefile} does not exist" + [ ! -e ${imagefile} ] && die_on_status $NOT_EXISTING_FILE "Error: The ${NAME} image file ${imagefile} does not exist" info "Installing ${NAME} from ${imagefile}..." - _setup_env "${imagefile}" + _setup_env ${imagefile} } ####################################### @@ -143,18 +136,18 @@ function setup_env_from_file(){ ####################################### function delete_env(){ ! ask "Are you sure to delete ${NAME} located in ${JUNEST_HOME}" "N" && return - if mountpoint -q "${JUNEST_HOME}" + if mountpoint -q ${JUNEST_HOME} then info "There are mounted directories inside ${JUNEST_HOME}" - if ! umount --force "${JUNEST_HOME}" + if ! umount --force ${JUNEST_HOME} then error "Cannot umount directories in ${JUNEST_HOME}" die "Try to delete ${NAME} using root permissions" fi fi # the CA directories are read only and can be deleted only by changing the mod - chmod -R +w "${JUNEST_HOME}"/etc/ca-certificates - if rm_cmd -rf "${JUNEST_HOME}" + chmod -R +w ${JUNEST_HOME}/etc/ca-certificates + if rm_cmd -rf ${JUNEST_HOME} then info "${NAME} deleted in ${JUNEST_HOME}" else diff --git a/lib/core/wrappers.sh b/lib/core/wrappers.sh deleted file mode 100644 index 1fe955c..0000000 --- a/lib/core/wrappers.sh +++ /dev/null @@ -1,60 +0,0 @@ -#!/usr/bin/env bash -# -# Dependencies: -# None -# -# vim: ft=sh - -####################################### -# Create bin wrappers -# -# Globals: -# JUNEST_HOME (RO) : The JuNest home directory. -# Arguments: -# force ($1?) : Create bin wrappers even if the bin file exists. -# Defaults to false. -# Returns: -# None -# Output: -# None -####################################### -function create_wrappers() { - local force=${1:-false} - local bin_path=${2:-/usr/bin} - bin_path=${bin_path%/} - mkdir -p "${JUNEST_HOME}${bin_path}_wrappers" - # Arguments inside a variable (i.e. `JUNEST_ARGS`) separated by quotes - # are not recognized normally unless using `eval`. More info here: - # https://github.com/fsquillace/junest/issues/262 - # https://github.com/fsquillace/junest/pull/287 - cat < "${JUNEST_HOME}/usr/bin/junest_wrapper" -#!/usr/bin/env bash - -eval "junest_args_array=(\${JUNEST_ARGS:-ns})" -junest "\${junest_args_array[@]}" -- \$(basename \${0}) "\$@" -EOF - chmod +x "${JUNEST_HOME}/usr/bin/junest_wrapper" - - cd "${JUNEST_HOME}${bin_path}" || return 1 - for file in * - do - [[ -d $file ]] && continue - # Symlinks outside junest appear as broken even though they are correct - # within a junest session. The following do not skip broken symlinks: - [[ -x $file || -L $file ]] || continue - if [[ -e ${JUNEST_HOME}${bin_path}_wrappers/$file ]] && ! $force - then - continue - fi - rm -f "${JUNEST_HOME}${bin_path}_wrappers/$file" - ln -s "${JUNEST_HOME}/usr/bin/junest_wrapper" "${JUNEST_HOME}${bin_path}_wrappers/$file" - done - - # Remove wrappers no longer needed - cd "${JUNEST_HOME}${bin_path}_wrappers" || return 1 - for file in * - do - [[ -e ${JUNEST_HOME}${bin_path}/$file || -L ${JUNEST_HOME}${bin_path}/$file ]] || rm -f "$file" - done - -} diff --git a/lib/utils/utils.sh b/lib/utils/utils.sh index 5659568..00e2cb6 100644 --- a/lib/utils/utils.sh +++ b/lib/utils/utils.sh @@ -50,7 +50,7 @@ function echoerr() { # Message printed to stderr. ####################################### function die() { - error "$@" + error $@ exit 1 } @@ -70,8 +70,8 @@ function die() { function die_on_status() { status=$1 shift - error "$@" - exit "$status" + error $@ + exit $status } ####################################### @@ -87,7 +87,7 @@ function die_on_status() { # Message printed to stderr. ####################################### function error() { - echoerr -e "\033[1;31m$*\033[0m" + echoerr -e "\033[1;31m$@\033[0m" } ####################################### @@ -104,7 +104,7 @@ function error() { ####################################### function warn() { # $@: msg (mandatory) - str: Message to print - echoerr -e "\033[1;33m$*\033[0m" + echoerr -e "\033[1;33m$@\033[0m" } ####################################### @@ -120,7 +120,7 @@ function warn() { # Message printed to stdout. ####################################### function info(){ - echo -e "\033[1;36m$*\033[0m" + echo -e "\033[1;36m$@\033[0m" } ####################################### @@ -142,12 +142,12 @@ function info(){ function ask(){ local question=$1 local default_answer=$2 - check_not_null "$question" + check_not_null $question - if [ -n "$default_answer" ] + if [ ! -z "$default_answer" ] then local answers="Y y N n" - [[ "$answers" =~ $default_answer ]] || { error "The default answer: $default_answer is wrong."; return $WRONG_ANSWER; } + [[ "$answers" =~ "$default_answer" ]] || { error "The default answer: $default_answer is wrong."; return $WRONG_ANSWER; } fi local default="Y" @@ -156,13 +156,12 @@ function ask(){ local other="n" [ "$default" == "N" ] && other="y" - local prompt - prompt=$(info "$question (${default}/${other})> ") + local prompt=$(info "$question (${default}/${other})> ") local res="none" while [ "$res" != "Y" ] && [ "$res" != "N" ] && [ "$res" != "" ]; do - read -r -p "$prompt" res + read -p "$prompt" res res=$(echo "$res" | tr '[:lower:]' '[:upper:]') done @@ -171,31 +170,36 @@ function ask(){ [ "$res" == "Y" ] } +function check_and_trap() { + local sigs="${@:2:${#@}}" + local traps="$(trap -p $sigs)" + [[ $traps ]] && die "Attempting to overwrite existing $sigs trap: $traps" + trap $@ +} + +function check_and_force_trap() { + local sigs="${@:2:${#@}}" + local traps="$(trap -p $sigs)" + [[ $traps ]] && warn "Attempting to overwrite existing $sigs trap: $traps" + trap $@ +} + function insert_quotes_on_spaces(){ # It inserts quotes between arguments. # Useful to preserve quotes on command # to be used inside sh -c/bash -c - local C="" + C='' whitespace="[[:space:]]" for i in "$@" do if [[ $i =~ $whitespace ]] then - temp_C="\"$i\"" + C="$C \"$i\"" else - temp_C="$i" + C="$C $i" fi - - # Handle edge case when C is empty to avoid adding an extra space - if [[ -z $C ]] - then - C="$temp_C" - else - C="$C $temp_C" - fi - done - echo "$C" + echo $C } contains_element () { diff --git a/pkgs/sudo-fake/PKGBUILD b/pkgs/sudo-fake/PKGBUILD new file mode 100644 index 0000000..99fa18b --- /dev/null +++ b/pkgs/sudo-fake/PKGBUILD @@ -0,0 +1,45 @@ +# Maintainer: Filippo Squillace +# More details on how to change this file: +# https://wiki.archlinux.org/index.php/PKGBUILD +# https://wiki.archlinux.org/index.php/Creating_packages +# https://wiki.archlinux.org/index.php/Arch_User_Repository#Submitting_packages + +pkgname=sudo-fake +pkgver=0.1.0 +pkgrel=1 +pkgdesc="Simple script that bypasses sudo and execute the actual command. Useful for fakeroot environments." +arch=('any') +url="" +license=('GPL') +groups=() +depends=() +makedepends=() +provides=('sudo') +conflicts=('sudo') +backup=() +options=() +#install= +source=() +md5sums=() +noextract=() + +package() { + install -d -m 755 "${pkgdir}/usr/bin/" + cat < "${pkgdir}/usr/bin/sudo" +#!/bin/bash +for opt in "\$@" +do + case "\$1" in + --) shift ; break ;; + -*) shift ;; + *) break ;; + esac +done + +[[ -z "\${@}" ]] || "\${@}" +EOF + + chmod 755 "${pkgdir}/usr/bin/sudo" +} + +# vim:set ts=2 sw=2 et: diff --git a/tests/checkstyle/checkstyle.sh b/tests/checkstyle/checkstyle.sh index 4f71965..27cb82a 100755 --- a/tests/checkstyle/checkstyle.sh +++ b/tests/checkstyle/checkstyle.sh @@ -1,7 +1,6 @@ #!/usr/bin/env bash -# shellcheck disable=SC1091 -source "$(dirname "$0")/../utils/utils.sh" +source "$(dirname $0)/../utils/utils.sh" # Disable the exiterr set +e @@ -11,12 +10,12 @@ function oneTimeSetUp(){ } function test_check_no_tabs(){ - assertCommandFailOnStatus 1 grep -R "$(printf '\t')" "$(dirname "$0")"/../../bin/* - assertEquals "" "$(cat "$STDOUTF")" - assertEquals "" "$(cat "$STDERRF")" - assertCommandFailOnStatus 1 grep -R "$(printf '\t')" "$(dirname "$0")"/../../lib/* - assertEquals "" "$(cat "$STDOUTF")" - assertEquals "" "$(cat "$STDERRF")" + assertCommandFailOnStatus 1 grep -R "$(printf '\t')" $(dirname $0)/../../bin/* + assertEquals "" "$(cat $STDOUTF)" + assertEquals "" "$(cat $STDERRF)" + assertCommandFailOnStatus 1 grep -R "$(printf '\t')" $(dirname $0)/../../lib/* + assertEquals "" "$(cat $STDOUTF)" + assertEquals "" "$(cat $STDERRF)" } -source "$(dirname "$0")"/../utils/shunit2 +source $(dirname $0)/../utils/shunit2 diff --git a/tests/integ-tests/install-bash.sh b/tests/integ-tests/install-bash.sh new file mode 100755 index 0000000..575c9c5 --- /dev/null +++ b/tests/integ-tests/install-bash.sh @@ -0,0 +1,13 @@ +#!/bin/sh +set -ex + +VERSION=$1 + +cd /tmp +wget http://ftp.gnu.org/gnu/bash/bash-$VERSION.tar.gz + +tar -zxf bash-$VERSION.tar.gz +cd /tmp/bash-$VERSION* +./configure +make +sudo make install diff --git a/tests/unit-tests/test-chroot.sh b/tests/unit-tests/test-chroot.sh index 3739c58..b2e5e70 100755 --- a/tests/unit-tests/test-chroot.sh +++ b/tests/unit-tests/test-chroot.sh @@ -1,7 +1,6 @@ #!/bin/bash -# shellcheck disable=SC1091 -JUNEST_ROOT=$(readlink -f "$(dirname "$0")"/../..) +JUNEST_ROOT=$(readlink -f $(dirname $0)/../..) source "$JUNEST_ROOT/tests/utils/utils.sh" @@ -29,37 +28,25 @@ function tearDown(){ function init_mocks() { chroot_cmd() { - # shellcheck disable=SC2317 [ "$JUNEST_ENV" != "1" ] && return 1 - # shellcheck disable=SC2317 - echo "chroot_cmd $*" + echo "chroot_cmd $@" } - # shellcheck disable=SC2034 GROOT=chroot_cmd - mychroot() { - # shellcheck disable=SC2317 - echo mychroot "$*" - } } function test_run_env_as_groot_cmd(){ - assertCommandSuccess run_env_as_groot "" "" "false" pwd - assertEquals "chroot_cmd -b /run/user/$(id -u) -b $HOME -b /tmp -b /proc -b /sys -b /dev $JUNEST_HOME /bin/sh --login -c pwd" "$(cat "$STDOUTF")" + assertCommandSuccess run_env_as_groot "" "false" pwd + assertEquals "chroot_cmd -b $HOME -b /tmp -b /proc -b /sys -b /dev $JUNEST_HOME /bin/sh --login -c pwd" "$(cat $STDOUTF)" } function test_run_env_as_groot_no_cmd(){ - assertCommandSuccess run_env_as_groot "" "" "false" "" - assertEquals "chroot_cmd -b /run/user/$(id -u) -b $HOME -b /tmp -b /proc -b /sys -b /dev $JUNEST_HOME /bin/sh --login" "$(cat "$STDOUTF")" -} - -function test_run_env_as_groot_with_backend_command(){ - assertCommandSuccess run_env_as_groot "mychroot" "" "false" "" - assertEquals "mychroot -b /run/user/$(id -u) -b $HOME -b /tmp -b /proc -b /sys -b /dev $JUNEST_HOME /bin/sh --login" "$(cat "$STDOUTF")" + assertCommandSuccess run_env_as_groot "" "false" "" + assertEquals "chroot_cmd -b $HOME -b /tmp -b /proc -b /sys -b /dev $JUNEST_HOME /bin/sh --login -c /bin/sh --login" "$(cat $STDOUTF)" } function test_run_env_as_groot_no_copy(){ - assertCommandSuccess run_env_as_groot "" "" "true" pwd - assertEquals "chroot_cmd -b /run/user/$(id -u) -b $HOME -b /tmp -b /proc -b /sys -b /dev $JUNEST_HOME /bin/sh --login -c pwd" "$(cat "$STDOUTF")" + assertCommandSuccess run_env_as_groot "" "true" pwd + assertEquals "chroot_cmd -b $HOME -b /tmp -b /proc -b /sys -b /dev $JUNEST_HOME /bin/sh --login -c pwd" "$(cat $STDOUTF)" [[ ! -e ${JUNEST_HOME}/etc/hosts ]] assertEquals 0 $? @@ -73,33 +60,28 @@ function test_run_env_as_groot_no_copy(){ function test_run_env_as_groot_nested_env(){ JUNEST_ENV=1 - assertCommandFailOnStatus 106 run_env_as_groot "" "" "false" "" + assertCommandFailOnStatus 106 run_env_as_groot "" "false" "" unset JUNEST_ENV } function test_run_env_as_groot_cmd_with_backend_args(){ - assertCommandSuccess run_env_as_groot "" "-n -b /home/blah" "false" pwd - assertEquals "chroot_cmd -b /run/user/$(id -u) -b $HOME -b /tmp -b /proc -b /sys -b /dev -n -b /home/blah $JUNEST_HOME /bin/sh --login -c pwd" "$(cat "$STDOUTF")" + assertCommandSuccess run_env_as_groot "-n -b /home/blah" "false" pwd + assertEquals "chroot_cmd -b $HOME -b /tmp -b /proc -b /sys -b /dev -n -b /home/blah $JUNEST_HOME /bin/sh --login -c pwd" "$(cat $STDOUTF)" } function test_run_env_as_chroot_cmd(){ - assertCommandSuccess run_env_as_chroot "" "" "false" pwd - assertEquals "chroot_cmd $JUNEST_HOME /bin/sh --login -c pwd" "$(cat "$STDOUTF")" + assertCommandSuccess run_env_as_chroot "" "false" pwd + assertEquals "chroot_cmd $JUNEST_HOME /bin/sh --login -c pwd" "$(cat $STDOUTF)" } function test_run_env_as_chroot_no_cmd(){ - assertCommandSuccess run_env_as_chroot "" "" "false" "" - assertEquals "chroot_cmd $JUNEST_HOME /bin/sh --login" "$(cat "$STDOUTF")" -} - -function test_run_env_as_chroot_with_backend_command(){ - assertCommandSuccess run_env_as_chroot "mychroot" "" "false" "" - assertEquals "mychroot $JUNEST_HOME /bin/sh --login" "$(cat "$STDOUTF")" + assertCommandSuccess run_env_as_chroot "" "false" "" + assertEquals "chroot_cmd $JUNEST_HOME /bin/sh --login -c /bin/sh --login" "$(cat $STDOUTF)" } function test_run_env_as_chroot_no_copy(){ - assertCommandSuccess run_env_as_chroot "" "" "true" pwd - assertEquals "chroot_cmd $JUNEST_HOME /bin/sh --login -c pwd" "$(cat "$STDOUTF")" + assertCommandSuccess run_env_as_chroot "" "true" pwd + assertEquals "chroot_cmd $JUNEST_HOME /bin/sh --login -c pwd" "$(cat $STDOUTF)" [[ ! -e ${JUNEST_HOME}/etc/hosts ]] assertEquals 0 $? @@ -113,13 +95,13 @@ function test_run_env_as_chroot_no_copy(){ function test_run_env_as_choot_nested_env(){ JUNEST_ENV=1 - assertCommandFailOnStatus 106 run_env_as_chroot "" "" "false" "" + assertCommandFailOnStatus 106 run_env_as_chroot "" "false" "" unset JUNEST_ENV } function test_run_env_as_chroot_cmd_with_backend_args(){ - assertCommandSuccess run_env_as_chroot "" "-n -b /home/blah" "false" pwd - assertEquals "chroot_cmd -n -b /home/blah $JUNEST_HOME /bin/sh --login -c pwd" "$(cat "$STDOUTF")" + assertCommandSuccess run_env_as_chroot "-n -b /home/blah" "false" pwd + assertEquals "chroot_cmd -n -b /home/blah $JUNEST_HOME /bin/sh --login -c pwd" "$(cat $STDOUTF)" } -source "$JUNEST_ROOT"/tests/utils/shunit2 +source $JUNEST_ROOT/tests/utils/shunit2 diff --git a/tests/unit-tests/test-common.sh b/tests/unit-tests/test-common.sh index 89c1a1e..dfff6f4 100755 --- a/tests/unit-tests/test-common.sh +++ b/tests/unit-tests/test-common.sh @@ -1,7 +1,6 @@ #!/bin/bash -# shellcheck disable=SC1091 -JUNEST_ROOT=$(readlink -f "$(dirname "$0")"/../..) +JUNEST_ROOT=$(readlink -f $(dirname $0)/../..) source "$JUNEST_ROOT/tests/utils/utils.sh" @@ -22,59 +21,47 @@ function oneTimeTearDown(){ function setUp(){ ld_exec_mock() { - # shellcheck disable=SC2317 - echo "ld_exec $*" + echo "ld_exec $@" } - # shellcheck disable=SC2317 ld_exec_mock_false() { - echo "ld_exec $*" + echo "ld_exec $@" return 1 } - # shellcheck disable=SC2034 LD_EXEC=ld_exec_mock unshare_mock() { - # shellcheck disable=SC2317 - echo "unshare $*" + echo "unshare $@" } - # shellcheck disable=SC2034 UNSHARE=unshare_mock - # shellcheck disable=SC2317 - bwrap_mock() { - echo "bwrap $*" - } - # shellcheck disable=SC2034 - BWRAP=bwrap_mock - } function test_ln(){ - LN="echo" assertCommandSuccess ln_cmd -s ln_file new_file - assertEquals "-s ln_file new_file" "$(cat "$STDOUTF")" + LN=echo assertCommandSuccess ln_cmd -s ln_file new_file + assertEquals "-s ln_file new_file" "$(cat $STDOUTF)" LN=false assertCommandSuccess ln_cmd -s ln_file new_file - assertEquals "ld_exec ${JUNEST_HOME}/usr/bin/false -s ln_file new_file" "$(cat "$STDOUTF")" + assertEquals "ld_exec ${JUNEST_HOME}/usr/bin/false -s ln_file new_file" "$(cat $STDOUTF)" LN=false LD_EXEC=false assertCommandFail ln_cmd } function test_getent(){ - GETENT="echo" assertCommandSuccess getent_cmd passwd - assertEquals "passwd" "$(cat "$STDOUTF")" + GETENT=echo assertCommandSuccess getent_cmd passwd + assertEquals "passwd" "$(cat $STDOUTF)" - GETENT="false" assertCommandSuccess getent_cmd passwd - assertEquals "ld_exec ${JUNEST_HOME}/usr/bin/false passwd" "$(cat "$STDOUTF")" + GETENT=false assertCommandSuccess getent_cmd passwd + assertEquals "ld_exec ${JUNEST_HOME}/usr/bin/false passwd" "$(cat $STDOUTF)" GETENT=false LD_EXEC=false assertCommandFail getent_cmd } function test_cp(){ - CP="echo" assertCommandSuccess cp_cmd passwd - assertEquals "passwd" "$(cat "$STDOUTF")" + CP=echo assertCommandSuccess cp_cmd passwd + assertEquals "passwd" "$(cat $STDOUTF)" CP=false assertCommandSuccess cp_cmd passwd - assertEquals "ld_exec ${JUNEST_HOME}/usr/bin/false passwd" "$(cat "$STDOUTF")" + assertEquals "ld_exec ${JUNEST_HOME}/usr/bin/false passwd" "$(cat $STDOUTF)" CP=false LD_EXEC=false assertCommandFail cp_cmd } @@ -84,9 +71,7 @@ function test_download(){ CURL=/bin/false assertCommandSuccess download_cmd - # shellcheck disable=SC2034 WGET=/bin/false - # shellcheck disable=SC2034 CURL=/bin/true assertCommandSuccess download_cmd @@ -94,77 +79,69 @@ function test_download(){ } function test_rm(){ - RM="echo" assertCommandSuccess rm_cmd rm_file - assertEquals "rm_file" "$(cat "$STDOUTF")" + RM=echo assertCommandSuccess rm_cmd rm_file + assertEquals "rm_file" "$(cat $STDOUTF)" - RM="false" assertCommandSuccess rm_cmd rm_file - assertEquals "ld_exec ${JUNEST_HOME}/usr/bin/false rm_file" "$(cat "$STDOUTF")" + RM=false assertCommandSuccess rm_cmd rm_file + assertEquals "ld_exec ${JUNEST_HOME}/usr/bin/false rm_file" "$(cat $STDOUTF)" RM=false LD_EXEC=false assertCommandFail rm_cmd rm_file } function test_chown(){ - local id - id=$(id -u) + local id=$(id -u) - CHOWN="echo" assertCommandSuccess chown_cmd "$id" chown_file - assertEquals "$id chown_file" "$(cat "$STDOUTF")" + CHOWN=echo assertCommandSuccess chown_cmd $id chown_file + assertEquals "$id chown_file" "$(cat $STDOUTF)" - CHOWN="false" assertCommandSuccess chown_cmd "$id" chown_file - assertEquals "ld_exec ${JUNEST_HOME}/usr/bin/false $id chown_file" "$(cat "$STDOUTF")" + CHOWN=false assertCommandSuccess chown_cmd $id chown_file + assertEquals "ld_exec ${JUNEST_HOME}/usr/bin/false $id chown_file" "$(cat $STDOUTF)" - CHOWN=false LD_EXEC=false assertCommandFail chown_cmd "$id" chown_file + CHOWN=false LD_EXEC=false assertCommandFail chown_cmd $id chown_file } function test_mkdir(){ - MKDIR="echo" assertCommandSuccess mkdir_cmd -p new_dir/new_dir - assertEquals "-p new_dir/new_dir" "$(cat "$STDOUTF")" + MKDIR=echo assertCommandSuccess mkdir_cmd -p new_dir/new_dir + assertEquals "-p new_dir/new_dir" "$(cat $STDOUTF)" MKDIR=false assertCommandSuccess mkdir_cmd -p new_dir/new_dir - assertEquals "ld_exec ${JUNEST_HOME}/usr/bin/false -p new_dir/new_dir" "$(cat "$STDOUTF")" + assertEquals "ld_exec ${JUNEST_HOME}/usr/bin/false -p new_dir/new_dir" "$(cat $STDOUTF)" MKDIR=false LD_EXEC=false assertCommandFail mkdir_cmd -p new_dir/new_dir } function test_zgrep(){ - ZGREP="echo" assertCommandSuccess zgrep_cmd new_file - assertEquals "new_file" "$(cat "$STDOUTF")" + ZGREP=echo assertCommandSuccess zgrep_cmd new_file + assertEquals "new_file" "$(cat $STDOUTF)" - mkdir -p "${JUNEST_HOME}"/usr/bin - touch "${JUNEST_HOME}"/usr/bin/false - chmod +x "${JUNEST_HOME}"/usr/bin/false + mkdir -p ${JUNEST_HOME}/usr/bin + touch ${JUNEST_HOME}/usr/bin/false + chmod +x ${JUNEST_HOME}/usr/bin/false - echo -e "#!/bin/bash\necho zgrep" > "${JUNEST_HOME}"/usr/bin/false + echo -e "#!/bin/bash\necho zgrep" > ${JUNEST_HOME}/usr/bin/false ZGREP=false assertCommandSuccess zgrep_cmd new_file - assertEquals "zgrep" "$(cat "$STDOUTF")" + assertEquals "zgrep" "$(cat $STDOUTF)" - echo -e "#!/bin/bash\nexit 1" > "${JUNEST_HOME}"/usr/bin/false + echo -e "#!/bin/bash\nexit 1" > ${JUNEST_HOME}/usr/bin/false ZGREP=false assertCommandFail zgrep_cmd new_file } function test_unshare(){ assertCommandSuccess unshare_cmd new_program - assertEquals "$(echo -e "ld_exec ${JUNEST_HOME}/usr/bin/$UNSHARE --user /bin/sh -c :\nld_exec ${JUNEST_HOME}/usr/bin/$UNSHARE new_program")" "$(cat "$STDOUTF")" + assertEquals "$(echo -e "ld_exec ${JUNEST_HOME}/usr/bin/$UNSHARE --user /bin/sh -c :\nld_exec ${JUNEST_HOME}/usr/bin/$UNSHARE new_program")" "$(cat $STDOUTF)" LD_EXEC=ld_exec_mock_false assertCommandSuccess unshare_cmd new_program - assertEquals "$(echo -e "ld_exec ${JUNEST_HOME}/usr/bin/unshare_mock --user /bin/sh -c :\nunshare --user /bin/sh -c :\nunshare new_program")" "$(cat "$STDOUTF")" + assertEquals "$(echo -e "ld_exec ${JUNEST_HOME}/usr/bin/unshare_mock --user /bin/sh -c :\nunshare --user /bin/sh -c :\nunshare new_program")" "$(cat $STDOUTF)" UNSHARE=false LD_EXEC=false assertCommandFail unshare_cmd new_program } -function test_bwrap(){ - assertCommandSuccess bwrap_cmd new_program - assertEquals "$(echo -e "ld_exec $BWRAP --dev-bind / / /bin/sh -c :\nld_exec $BWRAP new_program")" "$(cat "$STDOUTF")" - - BWRAP=false LD_EXEC=false assertCommandFail bwrap_cmd new_program -} - function test_chroot(){ - CLASSIC_CHROOT="echo" assertCommandSuccess chroot_cmd root - assertEquals "root" "$(cat "$STDOUTF")" + CLASSIC_CHROOT=echo assertCommandSuccess chroot_cmd root + assertEquals "root" "$(cat $STDOUTF)" CLASSIC_CHROOT=false assertCommandSuccess chroot_cmd root - assertEquals "ld_exec $JUNEST_HOME/usr/bin/false root" "$(cat "$STDOUTF")" + assertEquals "ld_exec $JUNEST_HOME/usr/bin/false root" "$(cat $STDOUTF)" CLASSIC_CHROOT=false LD_EXEC=false assertCommandFail chroot_cmd root } @@ -177,43 +154,38 @@ function test_proot_cmd_compat(){ function test_proot_cmd_seccomp(){ envv(){ - # shellcheck disable=SC2317 env } PROOT=envv assertCommandSuccess proot_cmd cmd - assertEquals "" "$(grep "^PROOT_NO_SECCOMP" "$STDOUTF")" + assertEquals "" "$(cat $STDOUTF | grep "^PROOT_NO_SECCOMP")" envv(){ - # shellcheck disable=SC2317 env | grep "^PROOT_NO_SECCOMP" } - # shellcheck disable=SC2034 PROOT=envv assertCommandSuccess proot_cmd cmd # The variable PROOT_NO_SECCOMP will be produced # twice due to the fallback mechanism assertEquals "PROOT_NO_SECCOMP=1 -PROOT_NO_SECCOMP=1" "$(grep "^PROOT_NO_SECCOMP" "$STDOUTF")" +PROOT_NO_SECCOMP=1" "$(cat $STDOUTF | grep "^PROOT_NO_SECCOMP")" } function test_copy_passwd_and_group(){ getent_cmd_mock() { - # shellcheck disable=SC2317 - echo "$*" + echo $@ } GETENT=getent_cmd_mock assertCommandSuccess copy_passwd_and_group - assertEquals "$(echo -e "passwd\npasswd $USER")" "$(cat "$JUNEST_HOME"/etc/passwd)" - assertEquals "group" "$(cat "$JUNEST_HOME"/etc/group)" + assertEquals "$(echo -e "passwd\npasswd $USER")" "$(cat $JUNEST_HOME/etc/passwd)" + assertEquals "group" "$(cat $JUNEST_HOME/etc/group)" } function test_copy_passwd_and_group_fallback(){ cp_cmd_mock() { - # shellcheck disable=SC2317 - echo "$*" + echo $@ } CP=cp_cmd_mock GETENT=false LD_EXEC=false assertCommandSuccess copy_passwd_and_group - assertEquals "$(echo -e "-f /etc/passwd $JUNEST_HOME//etc/passwd\n-f /etc/group $JUNEST_HOME//etc/group")" "$(cat "$STDOUTF")" + assertEquals "$(echo -e "/etc/passwd $JUNEST_HOME//etc/passwd\n/etc/group $JUNEST_HOME//etc/group")" "$(cat $STDOUTF)" } function test_copy_passwd_and_group_failure(){ @@ -229,14 +201,14 @@ function test_nested_env_not_set_variable(){ } function test_check_same_arch_not_same(){ - echo "JUNEST_ARCH=XXX" > "${JUNEST_HOME}"/etc/junest/info + echo "JUNEST_ARCH=XXX" > ${JUNEST_HOME}/etc/junest/info assertCommandFailOnStatus 104 check_same_arch } function test_check_same_arch(){ - echo "JUNEST_ARCH=$ARCH" > "${JUNEST_HOME}"/etc/junest/info + echo "JUNEST_ARCH=$ARCH" > ${JUNEST_HOME}/etc/junest/info assertCommandSuccess check_same_arch } -source "$JUNEST_ROOT"/tests/utils/shunit2 +source $JUNEST_ROOT/tests/utils/shunit2 diff --git a/tests/unit-tests/test-groot.sh b/tests/unit-tests/test-groot.sh new file mode 100755 index 0000000..5fb2580 --- /dev/null +++ b/tests/unit-tests/test-groot.sh @@ -0,0 +1,248 @@ +#!/bin/bash +source "$(dirname $0)/../utils/utils.sh" + +JUNEST_BASE="$(readlink -f $(dirname $(readlink -f "$0"))/../..)" + +# Disable the exiterr +set +e + +function oneTimeSetUp(){ + setUpUnitTests +} + +function setUp(){ + # Attempt to source the files under test to revert variable overrides + source $JUNEST_BASE/bin/groot -h &> /dev/null + set +e + + cwdSetUp + mkdir -p chrootdir + + init_mocks +} + +function tearDown(){ + cwdTearDown +} + +## Mock functions ## +function init_mocks() { + function usage(){ + echo "usage" + } + function is_user_root() { + return 0 + } + function chroot() { + echo "chroot($@)" + } + function mountpoint() { + echo "mountpoint($@)" + # As default suppose the mountpoint does not exist + return 1 + } + function mountpoint_mock() { + echo "mountpoint($@)" + } + function mount() { + echo "mount($@)" + } + function umount() { + echo "umount($@)" + } + function check_and_trap() { + echo "check_and_trap($@)" + } + + # As default suppose the mountpoint "chrootdir" does not exist + echo -e "1 /home/mychroot/dev\n" > ./mounts + MOUNTS_FILE=./mounts +} + +function test_help(){ + assertCommandSuccess main -h + assertEquals "usage" "$(cat $STDOUTF)" + assertCommandSuccess main --help + assertEquals "usage" "$(cat $STDOUTF)" +} +function test_version(){ + assertCommandSuccess main -V + assertEquals "$NAME $(cat $JUNEST_BASE/VERSION)" "$(cat $STDOUTF)" + assertCommandSuccess main --version + assertEquals "$NAME $(cat $JUNEST_BASE/VERSION)" "$(cat $STDOUTF)" +} +function test_groot_no_root(){ + is_user_root() { + return 1 + } + assertCommandFailOnStatus $NO_ROOT_PRIVILEGES main +} +function test_groot_no_directory(){ + assertCommandFailOnStatus $NOT_EXISTING_FILE main no-directory +} +function test_groot_mountpoint_exist(){ + echo -e "1 /home/mychroot/dev\n1 chrootdir\n" > ./mounts + MOUNTS_FILE=./mounts + assertCommandSuccess main chrootdir + assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nchroot(chrootdir)")" "$(cat $STDOUTF)" +} +function test_groot_mountpoint_does_not_exist(){ + assertCommandSuccess main chrootdir + assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmount(--bind chrootdir chrootdir)\nchroot(chrootdir)")" "$(cat $STDOUTF)" +} +function test_groot_with_bind(){ + assertCommandSuccess main -b /tmp chrootdir + [[ -d chrootdir/tmp ]] + assertEquals 0 $? + assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmount(--bind chrootdir chrootdir)\nmount(--bind /tmp chrootdir/tmp)\nchroot(chrootdir)")" "$(cat $STDOUTF)" +} +function test_groot_with_bind_file(){ + touch file_src + assertCommandSuccess main -b ${PWD}/file_src:/file_src chrootdir + [[ -f chrootdir/file_src ]] + assertEquals 0 $? + assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmount(--bind chrootdir chrootdir)\nmount(--bind ${PWD}/file_src chrootdir/file_src)\nchroot(chrootdir)")" "$(cat $STDOUTF)" +} +function test_groot_with_bind_not_existing_node(){ + assertCommandFailOnStatus $NOT_EXISTING_FILE main -b ${PWD}/file_src:/file_src chrootdir + assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmount(--bind chrootdir chrootdir)")" "$(cat $STDOUTF)" +} +function test_groot_with_bind_not_absolute_path_node(){ + touch file_src + assertCommandFailOnStatus $NOT_ABSOLUTE_PATH main -b file_src:/file_src chrootdir + assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmount(--bind chrootdir chrootdir)")" "$(cat $STDOUTF)" +} +function test_groot_with_bind_guest_host(){ + assertCommandSuccess main -b /tmp:/home/tmp chrootdir + [[ -d chrootdir/home/tmp ]] + assertEquals 0 $? + assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmount(--bind chrootdir chrootdir)\nmount(--bind /tmp chrootdir/home/tmp)\nchroot(chrootdir)")" "$(cat $STDOUTF)" +} +function test_groot_with_multiple_bind(){ + assertCommandSuccess main -b /tmp:/home/tmp -b /dev chrootdir + [[ -d chrootdir/home/tmp ]] + assertEquals 0 $? + [[ -d chrootdir/dev ]] + assertEquals 0 $? + assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmount(--bind chrootdir chrootdir)\nmount(--bind /tmp chrootdir/home/tmp)\nmount(--bind /dev chrootdir/dev)\nchroot(chrootdir)")" "$(cat $STDOUTF)" +} +function test_groot_with_command(){ + assertCommandSuccess main chrootdir ls -la -h + assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmount(--bind chrootdir chrootdir)\nchroot(chrootdir ls -la -h)")" "$(cat $STDOUTF)" +} +function test_groot_with_bind_and_command(){ + assertCommandSuccess main -b /tmp:/home/tmp -b /dev chrootdir ls -la -h + [[ -d chrootdir/home/tmp ]] + assertEquals 0 $? + [[ -d chrootdir/dev ]] + assertEquals 0 $? + assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmount(--bind chrootdir chrootdir)\nmount(--bind /tmp chrootdir/home/tmp)\nmount(--bind /dev chrootdir/dev)\nchroot(chrootdir ls -la -h)")" "$(cat $STDOUTF)" +} +function test_groot_with_bind_no_umount(){ + assertCommandSuccess main -n chrootdir + assertEquals "$(echo -e "mount(--bind chrootdir chrootdir)\nchroot(chrootdir)")" "$(cat $STDOUTF)" +} +function test_groot_with_chroot_teardown(){ + echo -e "1 /home/mychroot/dev\n1 /home/mychroot/proc/fs1\n1 /home/mychroot\n1 /home/mychroot-no/dev\n1 /home/mychroot/dev/shm\n1 /home/mychroot/proc\n" > ./mounts + MOUNTS_FILE=./mounts + CHROOTDIR=/home/mychroot assertCommandSuccess chroot_teardown + assertEquals "$(echo -e "umount(/home/mychroot/proc/fs1) +umount(/home/mychroot/proc) +umount(/home/mychroot/dev/shm) +umount(/home/mychroot/dev) +umount(/home/mychroot)")" "$(cat $STDOUTF)" +} + +function test_groot_with_chroot_teardown_umount_failure(){ + function umount() { + echo "umount($@)" + [[ "$1" == "/home/mychroot/dev/shm" ]] && return 128 + return 0 + } + UMOUNT=umount + echo -e "1 /home/mychroot/dev\n1 /home/mychroot/proc/fs1\n1 /home/mychroot\n1 /home/mychroot-no/dev\n1 /home/mychroot/dev/shm\n1 /home/mychroot/proc\n" > ./mounts + MOUNTS_FILE=./mounts + CHROOTDIR=/home/mychroot assertCommandFailOnStatus 128 chroot_teardown + assertEquals "$(echo -e "umount(/home/mychroot/proc/fs1) +umount(/home/mychroot/proc) +umount(/home/mychroot/dev/shm) +umount(/home/mychroot/dev) +umount(/home/mychroot)")" "$(cat $STDOUTF)" +} +function test_groot_with_chroot_teardown_with_trailing_slash(){ + echo -e "1 /home/mychroot/dev\n1 /home/mychroot/proc/fs1\n1 /home/mychroot\n1 /home/mychroot-no/dev\n1 /home/mychroot/dev/shm\n1 /home/mychroot/proc\n" > ./mounts + MOUNTS_FILE=./mounts + CHROOTDIR=/home/mychroot assertCommandSuccess chroot_teardown + assertEquals "$(echo -e "umount(/home/mychroot/proc/fs1) +umount(/home/mychroot/proc) +umount(/home/mychroot/dev/shm) +umount(/home/mychroot/dev) +umount(/home/mychroot)")" "$(cat $STDOUTF)" +} +function test_groot_with_chroot_teardown_mountpoint_failure(){ + is_mountpoint() { + [[ $1 == "/home/mychroot/dev/shm" ]] && return 128 + return 0 + } + echo -e "1 /home/mychroot/dev\n1 /home/mychroot/proc/fs1\n1 /home/mychroot\n1 /home/mychroot-no/dev\n1 /home/mychroot/dev/shm\n1 /home/mychroot/proc\n" > ./mounts + MOUNTS_FILE=./mounts + CHROOTDIR=/home/mychroot assertCommandSuccess chroot_teardown + assertEquals "$(echo -e "umount(/home/mychroot/proc/fs1) +umount(/home/mychroot/proc) +umount(/home/mychroot/dev) +umount(/home/mychroot)")" "$(cat $STDOUTF)" +} + +function test_groot_with_rbind(){ + assertCommandSuccess main -r -b /tmp chrootdir + [[ -d chrootdir/tmp ]] + assertEquals 0 $? + assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmount(--bind chrootdir chrootdir)\nmount(--rbind /tmp chrootdir/tmp)\nchroot(chrootdir)")" "$(cat $STDOUTF)" +} + +function test_groot_with_avoid_bind_proc(){ + assertCommandSuccess main -i -b /proc chrootdir + [[ -d chrootdir/proc ]] + assertEquals 0 $? + assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmount(--bind chrootdir chrootdir)\nmount(proc chrootdir/proc -t proc)\nchroot(chrootdir)")" "$(cat $STDOUTF)" +} + +function test_groot_with_avoid_bind_dev(){ + assertCommandSuccess main -i -b /dev chrootdir + [[ -d chrootdir/dev ]] + assertEquals 0 $? + assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmount(--bind chrootdir chrootdir)\nmount(udev chrootdir/dev -t devtmpfs)\nmount(devpts /dev/pts -t devpts)\nmount(shm /dev/shm -t tmpfs)\nchroot(chrootdir)")" "$(cat $STDOUTF)" +} + +function test_groot_with_avoid_bind_sys(){ + assertCommandSuccess main -i -b /sys chrootdir + [[ -d chrootdir/sys ]] + assertEquals 0 $? + assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmount(--bind chrootdir chrootdir)\nmount(sys chrootdir/sys -t sysfs)\nchroot(chrootdir)")" "$(cat $STDOUTF)" +} + +function test_groot_with_avoid_bind_run(){ + assertCommandSuccess main -i -b /run chrootdir + [[ -d chrootdir/run ]] + assertEquals 0 $? + assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmount(--bind chrootdir chrootdir)\nmount(run chrootdir/run -t tmpfs)\nchroot(chrootdir)")" "$(cat $STDOUTF)" +} + +function test_groot_with_avoid_bind_tmp(){ + assertCommandSuccess main -i -b /tmp chrootdir + [[ -d chrootdir/tmp ]] + assertEquals 0 $? + assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmount(--bind chrootdir chrootdir)\nmount(tmp chrootdir/tmp -t tmpfs)\nchroot(chrootdir)")" "$(cat $STDOUTF)" +} + +function test_groot_with_avoid_bind_combined(){ + assertCommandSuccess main -i -b /tmp -b /usr chrootdir + cat $STDERRF + [[ -d chrootdir/tmp ]] + assertEquals 0 $? + [[ -d chrootdir/usr ]] + assertEquals 0 $? + assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmount(--bind chrootdir chrootdir)\nmount(tmp chrootdir/tmp -t tmpfs)\nmount(--bind /usr chrootdir/usr)\nchroot(chrootdir)")" "$(cat $STDOUTF)" +} + +source $(dirname $0)/../utils/shunit2 diff --git a/tests/unit-tests/test-junest.sh b/tests/unit-tests/test-junest.sh index 07a92b1..98c6cb2 100755 --- a/tests/unit-tests/test-junest.sh +++ b/tests/unit-tests/test-junest.sh @@ -1,10 +1,8 @@ #!/bin/bash -# shellcheck disable=SC1091 +source "$(dirname $0)/../utils/utils.sh" -source "$(dirname "$0")/../utils/utils.sh" - -JUNEST_BASE="$(dirname "$0")/../.." -source "$JUNEST_BASE"/bin/junest -h &> /dev/null +JUNEST_BASE="$(dirname $0)/../.." +source $JUNEST_BASE/bin/junest -h &> /dev/null # Disable the exiterr set +e @@ -14,143 +12,100 @@ function oneTimeSetUp(){ } function setUp(){ - ## Mock functions ## - # shellcheck disable=SC2317 - function usage(){ - echo "usage" - } - # shellcheck disable=SC2317 - function version(){ - echo "version" - } - # shellcheck disable=SC2317 - function build_image_env(){ - local disable_check=$1 - echo "build_image_env($disable_check)" - } - # shellcheck disable=SC2317 - function delete_env(){ - echo "delete_env" - } - # shellcheck disable=SC2317 - function setup_env_from_file(){ - echo "setup_env_from_file($1)" - } - # shellcheck disable=SC2317 - function setup_env(){ - echo "setup_env($1)" - } - # shellcheck disable=SC2317 - function run_env_as_proot_fakeroot(){ - local backend_command="$1" - local backend_args="$2" - local no_copy_files="$3" - shift 3 - echo "run_env_as_proot_fakeroot($backend_command,$backend_args,$no_copy_files,$*)" - } - # shellcheck disable=SC2317 - function run_env_as_groot(){ - local backend_command="$1" - local backend_args="$2" - local no_copy_files="$3" - shift 3 - echo "run_env_as_groot($backend_command,$backend_args,$no_copy_files,$*)" - } - # shellcheck disable=SC2317 - function run_env_as_chroot(){ - local backend_command="$1" - local backend_args="$2" - local no_copy_files="$3" - shift 3 - echo "run_env_as_chroot($backend_command,$backend_args,$no_copy_files,$*)" - } - # shellcheck disable=SC2317 - function run_env_as_proot_user(){ - local backend_command="$1" - local backend_args="$2" - local no_copy_files="$3" - shift 3 - echo "run_env_as_proot_user($backend_command,$backend_args,$no_copy_files,$*)" - } - # shellcheck disable=SC2317 - function run_env_as_bwrap_fakeroot(){ - local backend_command="$1" - local backend_args="$2" - local no_copy_files="$3" - shift 3 - echo "run_env_as_bwrap_fakeroot($backend_command,$backend_args,$no_copy_files,$*)" - } - # shellcheck disable=SC2317 - function run_env_as_bwrap_user(){ - local backend_command="$1" - local backend_args="$2" - local no_copy_files="$3" - shift 3 - echo "run_env_as_bwrap_user($backend_command,$backend_args,$no_copy_files,$*)" - } - # shellcheck disable=SC2317 function is_env_installed(){ return 0 } - # shellcheck disable=SC2317 - function create_wrappers(){ - : - } +} + +## Mock functions ## +function usage(){ + echo "usage" +} +function version(){ + echo "version" +} +function build_image_env(){ + local disable_check=$1 + echo "build_image_env($disable_check)" +} +function delete_env(){ + echo "delete_env" +} +function setup_env_from_file(){ + echo "setup_env_from_file($1)" +} +function setup_env(){ + echo "setup_env($1)" +} +function run_env_as_fakeroot(){ + local backend_args="$1" + local no_copy_files="$2" + shift 2 + echo "run_env_as_fakeroot($backend_args,$no_copy_files,$@)" +} +function run_env_as_groot(){ + local backend_args="$1" + local no_copy_files="$2" + shift 2 + echo "run_env_as_groot($backend_args,$no_copy_files,$@)" +} +function run_env_as_chroot(){ + local backend_args="$1" + local no_copy_files="$2" + shift 2 + echo "run_env_as_chroot($backend_args,$no_copy_files,$@)" +} +function run_env_as_user(){ + local backend_args="$1" + local no_copy_files="$2" + shift 2 + echo "run_env_as_user($backend_args,$no_copy_files,$@)" +} +function run_env_with_namespace(){ + local backend_args="$1" + local no_copy_files="$2" + shift 2 + echo "run_env_with_namespace($backend_args,$no_copy_files,$@)" } function test_help(){ assertCommandSuccess main -h - assertEquals "usage" "$(cat "$STDOUTF")" + assertEquals "usage" "$(cat $STDOUTF)" assertCommandSuccess main --help - assertEquals "usage" "$(cat "$STDOUTF")" + assertEquals "usage" "$(cat $STDOUTF)" } function test_version(){ assertCommandSuccess main -V - assertEquals "version" "$(cat "$STDOUTF")" + assertEquals "version" "$(cat $STDOUTF)" assertCommandSuccess main --version - assertEquals "version" "$(cat "$STDOUTF")" + assertEquals "version" "$(cat $STDOUTF)" } function test_build_image_env(){ assertCommandSuccess main b - assertEquals "build_image_env(false)" "$(cat "$STDOUTF")" + assertEquals "build_image_env(false)" "$(cat $STDOUTF)" assertCommandSuccess main build - assertEquals "build_image_env(false)" "$(cat "$STDOUTF")" + assertEquals "build_image_env(false)" "$(cat $STDOUTF)" assertCommandSuccess main b -n - assertEquals "build_image_env(true)" "$(cat "$STDOUTF")" + assertEquals "build_image_env(true)" "$(cat $STDOUTF)" assertCommandSuccess main build --disable-check - assertEquals "build_image_env(true)" "$(cat "$STDOUTF")" -} - -function test_create_wrappers(){ - # shellcheck disable=SC2317 - function create_wrappers(){ - local force=$1 - echo "create_wrappers($force)" - } - assertCommandSuccess main create-bin-wrappers - assertEquals "create_wrappers(false)" "$(cat "$STDOUTF")" - - assertCommandSuccess main create-bin-wrappers --force - assertEquals "create_wrappers(true)" "$(cat "$STDOUTF")" + assertEquals "build_image_env(true)" "$(cat $STDOUTF)" } function test_delete_env(){ assertCommandSuccess main s -d - assertEquals "delete_env" "$(cat "$STDOUTF")" + assertEquals "delete_env" "$(cat $STDOUTF)" assertCommandSuccess main setup --delete - assertEquals "delete_env" "$(cat "$STDOUTF")" + assertEquals "delete_env" "$(cat $STDOUTF)" } function test_setup_env_from_file(){ - # shellcheck disable=SC2317 is_env_installed(){ return 1 } assertCommandSuccess main s -i myimage - assertEquals "setup_env_from_file(myimage)" "$(cat "$STDOUTF")" + assertEquals "setup_env_from_file(myimage)" "$(cat $STDOUTF)" assertCommandSuccess main setup --from-file myimage - assertEquals "setup_env_from_file(myimage)" "$(cat "$STDOUTF")" + assertEquals "setup_env_from_file(myimage)" "$(cat $STDOUTF)" - # shellcheck disable=SC2317 is_env_installed(){ return 0 } @@ -158,49 +113,41 @@ function test_setup_env_from_file(){ } function test_setup_env(){ - # shellcheck disable=SC2317 is_env_installed(){ return 1 } assertCommandSuccess main s - assertEquals "setup_env()" "$(cat "$STDOUTF")" + assertEquals "setup_env()" "$(cat $STDOUTF)" assertCommandSuccess main setup - assertEquals "setup_env()" "$(cat "$STDOUTF")" + assertEquals "setup_env()" "$(cat $STDOUTF)" assertCommandSuccess main s -a arm - assertEquals "setup_env(arm)" "$(cat "$STDOUTF")" + assertEquals "setup_env(arm)" "$(cat $STDOUTF)" assertCommandSuccess main setup --arch arm - assertEquals "setup_env(arm)" "$(cat "$STDOUTF")" + assertEquals "setup_env(arm)" "$(cat $STDOUTF)" - # shellcheck disable=SC2317 is_env_installed(){ return 0 } assertCommandFail main setup -a arm } -function test_run_env_as_proot_fakeroot(){ +function test_run_env_as_fakeroot(){ assertCommandSuccess main p -f - assertEquals "run_env_as_proot_fakeroot(,,false,)" "$(cat "$STDOUTF")" + assertEquals "run_env_as_fakeroot(,false,)" "$(cat $STDOUTF)" assertCommandSuccess main proot --fakeroot - assertEquals "run_env_as_proot_fakeroot(,,false,)" "$(cat "$STDOUTF")" + assertEquals "run_env_as_fakeroot(,false,)" "$(cat $STDOUTF)" assertCommandSuccess main p -f -n - assertEquals "run_env_as_proot_fakeroot(,,true,)" "$(cat "$STDOUTF")" - - assertCommandSuccess main p -f --backend-command blah - assertEquals "run_env_as_proot_fakeroot(blah,,false,)" "$(cat "$STDOUTF")" - assertCommandSuccess main proot -f --backend-command blah - assertEquals "run_env_as_proot_fakeroot(blah,,false,)" "$(cat "$STDOUTF")" + assertEquals "run_env_as_fakeroot(,true,)" "$(cat $STDOUTF)" assertCommandSuccess main proot -f -b "-b arg" - assertEquals "run_env_as_proot_fakeroot(,-b arg,false,)" "$(cat "$STDOUTF")" + assertEquals "run_env_as_fakeroot(-b arg,false,)" "$(cat $STDOUTF)" assertCommandSuccess main proot -f -b "-b arg" -- command -kv - assertEquals "run_env_as_proot_fakeroot(,-b arg,false,command -kv)" "$(cat "$STDOUTF")" + assertEquals "run_env_as_fakeroot(-b arg,false,command -kv)" "$(cat $STDOUTF)" assertCommandSuccess main proot -f command --as - assertEquals "run_env_as_proot_fakeroot(,,false,command --as)" "$(cat "$STDOUTF")" + assertEquals "run_env_as_fakeroot(,false,command --as)" "$(cat $STDOUTF)" assertCommandSuccess main proot -f -- command --as - assertEquals "run_env_as_proot_fakeroot(,,false,command --as)" "$(cat "$STDOUTF")" + assertEquals "run_env_as_fakeroot(,false,command --as)" "$(cat $STDOUTF)" - # shellcheck disable=SC2317 is_env_installed(){ return 1 } @@ -209,25 +156,19 @@ function test_run_env_as_proot_fakeroot(){ function test_run_env_as_user(){ assertCommandSuccess main proot - assertEquals "run_env_as_proot_user(,,false,)" "$(cat "$STDOUTF")" + assertEquals "run_env_as_user(,false,)" "$(cat $STDOUTF)" assertCommandSuccess main p -n - assertEquals "run_env_as_proot_user(,,true,)" "$(cat "$STDOUTF")" - - assertCommandSuccess main p --backend-command blah - assertEquals "run_env_as_proot_user(blah,,false,)" "$(cat "$STDOUTF")" - assertCommandSuccess main proot --backend-command blah - assertEquals "run_env_as_proot_user(blah,,false,)" "$(cat "$STDOUTF")" + assertEquals "run_env_as_user(,true,)" "$(cat $STDOUTF)" assertCommandSuccess main proot -b "-b arg" - assertEquals "run_env_as_proot_user(,-b arg,false,)" "$(cat "$STDOUTF")" + assertEquals "run_env_as_user(-b arg,false,)" "$(cat $STDOUTF)" assertCommandSuccess main proot -b "-b arg" -- command -ll - assertEquals "run_env_as_proot_user(,-b arg,false,command -ll)" "$(cat "$STDOUTF")" + assertEquals "run_env_as_user(-b arg,false,command -ll)" "$(cat $STDOUTF)" assertCommandSuccess main proot command -ls - assertEquals "run_env_as_proot_user(,,false,command -ls)" "$(cat "$STDOUTF")" + assertEquals "run_env_as_user(,false,command -ls)" "$(cat $STDOUTF)" assertCommandSuccess main proot -- command -ls - assertEquals "run_env_as_proot_user(,,false,command -ls)" "$(cat "$STDOUTF")" + assertEquals "run_env_as_user(,false,command -ls)" "$(cat $STDOUTF)" - # shellcheck disable=SC2317 is_env_installed(){ return 1 } @@ -236,23 +177,16 @@ function test_run_env_as_user(){ function test_run_env_as_groot(){ assertCommandSuccess main g - assertEquals "run_env_as_groot(,,false,)" "$(cat "$STDOUTF")" + assertEquals "run_env_as_groot(,false,)" "$(cat $STDOUTF)" assertCommandSuccess main g -n - assertEquals "run_env_as_groot(,,true,)" "$(cat "$STDOUTF")" + assertEquals "run_env_as_groot(,true,)" "$(cat $STDOUTF)" assertCommandSuccess main g -b "-b arg" - assertEquals "run_env_as_groot(,-b arg,false,)" "$(cat "$STDOUTF")" - - assertCommandSuccess main g --backend-command blah - assertEquals "run_env_as_groot(blah,,false,)" "$(cat "$STDOUTF")" - assertCommandSuccess main groot --backend-command blah - assertEquals "run_env_as_groot(blah,,false,)" "$(cat "$STDOUTF")" - + assertEquals "run_env_as_groot(-b arg,false,)" "$(cat $STDOUTF)" assertCommandSuccess main groot command - assertEquals "run_env_as_groot(,,false,command)" "$(cat "$STDOUTF")" + assertEquals "run_env_as_groot(,false,command)" "$(cat $STDOUTF)" assertCommandSuccess main groot -- command - assertEquals "run_env_as_groot(,,false,command)" "$(cat "$STDOUTF")" + assertEquals "run_env_as_groot(,false,command)" "$(cat $STDOUTF)" - # shellcheck disable=SC2317 is_env_installed(){ return 1 } @@ -261,107 +195,51 @@ function test_run_env_as_groot(){ function test_run_env_as_chroot(){ assertCommandSuccess main r - assertEquals "run_env_as_chroot(,,false,)" "$(cat "$STDOUTF")" + assertEquals "run_env_as_chroot(,false,)" "$(cat $STDOUTF)" assertCommandSuccess main r -b "-b arg" - assertEquals "run_env_as_chroot(,-b arg,false,)" "$(cat "$STDOUTF")" - - assertCommandSuccess main r --backend-command blah - assertEquals "run_env_as_chroot(blah,,false,)" "$(cat "$STDOUTF")" - assertCommandSuccess main root --backend-command blah - assertEquals "run_env_as_chroot(blah,,false,)" "$(cat "$STDOUTF")" - + assertEquals "run_env_as_chroot(-b arg,false,)" "$(cat $STDOUTF)" assertCommandSuccess main root command - assertEquals "run_env_as_chroot(,,false,command)" "$(cat "$STDOUTF")" + assertEquals "run_env_as_chroot(,false,command)" "$(cat $STDOUTF)" assertCommandSuccess main root -- command - assertEquals "run_env_as_chroot(,,false,command)" "$(cat "$STDOUTF")" + assertEquals "run_env_as_chroot(,false,command)" "$(cat $STDOUTF)" - # shellcheck disable=SC2317 is_env_installed(){ return 1 } assertCommandFail main root -f } -function test_run_env_as_bwrap_fakeroot(){ - assertCommandSuccess main n -f - assertEquals "run_env_as_bwrap_fakeroot(,,false,)" "$(cat "$STDOUTF")" - assertCommandSuccess main ns -f - assertEquals "run_env_as_bwrap_fakeroot(,,false,)" "$(cat "$STDOUTF")" - assertCommandSuccess main ns -n -f - assertEquals "run_env_as_bwrap_fakeroot(,,true,)" "$(cat "$STDOUTF")" - - assertCommandSuccess main ns -f -b "-b arg" - assertEquals "run_env_as_bwrap_fakeroot(,-b arg,false,)" "$(cat "$STDOUTF")" - assertCommandSuccess main ns -f -b "-b arg" -- command -kv - assertEquals "run_env_as_bwrap_fakeroot(,-b arg,false,command -kv)" "$(cat "$STDOUTF")" - assertCommandSuccess main ns -f command --as - assertEquals "run_env_as_bwrap_fakeroot(,,false,command --as)" "$(cat "$STDOUTF")" - assertCommandSuccess main ns -f -- command --as - assertEquals "run_env_as_bwrap_fakeroot(,,false,command --as)" "$(cat "$STDOUTF")" - - assertCommandSuccess main ns -f --backend-command blah - assertEquals "run_env_as_bwrap_fakeroot(blah,,false,)" "$(cat "$STDOUTF")" - assertCommandSuccess main -f --backend-command blah - assertEquals "run_env_as_bwrap_fakeroot(blah,,false,)" "$(cat "$STDOUTF")" - - assertCommandSuccess main -f - assertEquals "run_env_as_bwrap_fakeroot(,,false,)" "$(cat "$STDOUTF")" - assertCommandSuccess main -f - assertEquals "run_env_as_bwrap_fakeroot(,,false,)" "$(cat "$STDOUTF")" - - assertCommandSuccess main -f -b "-b arg" - assertEquals "run_env_as_bwrap_fakeroot(,-b arg,false,)" "$(cat "$STDOUTF")" - assertCommandSuccess main -f -b "-b arg" -- command -kv - assertEquals "run_env_as_bwrap_fakeroot(,-b arg,false,command -kv)" "$(cat "$STDOUTF")" - assertCommandSuccess main -f command --as - assertEquals "run_env_as_bwrap_fakeroot(,,false,command --as)" "$(cat "$STDOUTF")" - assertCommandSuccess main -f -- command --as - assertEquals "run_env_as_bwrap_fakeroot(,,false,command --as)" "$(cat "$STDOUTF")" - - # shellcheck disable=SC2317 - is_env_installed(){ - return 1 - } - assertCommandFail main ns -f -} - -function test_run_env_as_bwrap_user(){ +function test_run_env_with_namespace(){ assertCommandSuccess main n - assertEquals "run_env_as_bwrap_user(,,false,)" "$(cat "$STDOUTF")" + assertEquals "run_env_with_namespace(,false,)" "$(cat $STDOUTF)" assertCommandSuccess main ns - assertEquals "run_env_as_bwrap_user(,,false,)" "$(cat "$STDOUTF")" + assertEquals "run_env_with_namespace(,false,)" "$(cat $STDOUTF)" assertCommandSuccess main ns -n - assertEquals "run_env_as_bwrap_user(,,true,)" "$(cat "$STDOUTF")" + assertEquals "run_env_with_namespace(,true,)" "$(cat $STDOUTF)" assertCommandSuccess main ns -b "-b arg" - assertEquals "run_env_as_bwrap_user(,-b arg,false,)" "$(cat "$STDOUTF")" + assertEquals "run_env_with_namespace(-b arg,false,)" "$(cat $STDOUTF)" assertCommandSuccess main ns -b "-b arg" -- command -kv - assertEquals "run_env_as_bwrap_user(,-b arg,false,command -kv)" "$(cat "$STDOUTF")" + assertEquals "run_env_with_namespace(-b arg,false,command -kv)" "$(cat $STDOUTF)" assertCommandSuccess main ns command --as - assertEquals "run_env_as_bwrap_user(,,false,command --as)" "$(cat "$STDOUTF")" + assertEquals "run_env_with_namespace(,false,command --as)" "$(cat $STDOUTF)" assertCommandSuccess main ns -- command --as - assertEquals "run_env_as_bwrap_user(,,false,command --as)" "$(cat "$STDOUTF")" - - assertCommandSuccess main ns --backend-command blah - assertEquals "run_env_as_bwrap_user(blah,,false,)" "$(cat "$STDOUTF")" - assertCommandSuccess main --backend-command blah - assertEquals "run_env_as_bwrap_user(blah,,false,)" "$(cat "$STDOUTF")" + assertEquals "run_env_with_namespace(,false,command --as)" "$(cat $STDOUTF)" assertCommandSuccess main - assertEquals "run_env_as_bwrap_user(,,false,)" "$(cat "$STDOUTF")" + assertEquals "run_env_with_namespace(,false,)" "$(cat $STDOUTF)" assertCommandSuccess main - assertEquals "run_env_as_bwrap_user(,,false,)" "$(cat "$STDOUTF")" + assertEquals "run_env_with_namespace(,false,)" "$(cat $STDOUTF)" assertCommandSuccess main -b "-b arg" - assertEquals "run_env_as_bwrap_user(,-b arg,false,)" "$(cat "$STDOUTF")" + assertEquals "run_env_with_namespace(-b arg,false,)" "$(cat $STDOUTF)" assertCommandSuccess main -b "-b arg" -- command -kv - assertEquals "run_env_as_bwrap_user(,-b arg,false,command -kv)" "$(cat "$STDOUTF")" + assertEquals "run_env_with_namespace(-b arg,false,command -kv)" "$(cat $STDOUTF)" assertCommandSuccess main command --as - assertEquals "run_env_as_bwrap_user(,,false,command --as)" "$(cat "$STDOUTF")" + assertEquals "run_env_with_namespace(,false,command --as)" "$(cat $STDOUTF)" assertCommandSuccess main -- command --as - assertEquals "run_env_as_bwrap_user(,,false,command --as)" "$(cat "$STDOUTF")" + assertEquals "run_env_with_namespace(,false,command --as)" "$(cat $STDOUTF)" - # shellcheck disable=SC2317 is_env_installed(){ return 1 } @@ -380,4 +258,4 @@ function test_invalid_option(){ assertCommandFail main s --no-option } -source "$(dirname "$0")"/../utils/shunit2 +source $(dirname $0)/../utils/shunit2 diff --git a/tests/unit-tests/test-namespace.sh b/tests/unit-tests/test-namespace.sh index 7a845aa..4ecc794 100755 --- a/tests/unit-tests/test-namespace.sh +++ b/tests/unit-tests/test-namespace.sh @@ -1,7 +1,6 @@ #!/bin/bash -# shellcheck disable=SC1091 -JUNEST_ROOT=$(readlink -f "$(dirname "$0")"/../..) +JUNEST_ROOT=$(readlink -f $(dirname $0)/../..) source "$JUNEST_ROOT/tests/utils/utils.sh" @@ -16,9 +15,8 @@ function oneTimeSetUp(){ ## Mock functions ## function init_mocks() { - # shellcheck disable=SC2317 - function bwrap_cmd(){ - echo "$BWRAP $*" + function unshare_cmd(){ + echo "unshare $@" } } @@ -41,16 +39,16 @@ function tearDown(){ } function _test_copy_common_files() { - [[ -e /etc/hosts ]] && assertEquals "$(cat /etc/hosts)" "$(cat "${JUNEST_HOME}"/etc/hosts)" - [[ -e /etc/host.conf ]] && assertEquals "$(cat /etc/host.conf)" "$(cat "${JUNEST_HOME}"/etc/host.conf)" - [[ -e /etc/nsswitch.conf ]] && assertEquals "$(cat /etc/nsswitch.conf)" "$(cat "${JUNEST_HOME}"/etc/nsswitch.conf)" - [[ -e /etc/resolv.conf ]] && assertEquals "$(cat /etc/resolv.conf)" "$(cat "${JUNEST_HOME}"/etc/resolv.conf)" + [[ -e /etc/hosts ]] && assertEquals "$(cat /etc/hosts)" "$(cat ${JUNEST_HOME}/etc/hosts)" + [[ -e /etc/host.conf ]] && assertEquals "$(cat /etc/host.conf)" "$(cat ${JUNEST_HOME}/etc/host.conf)" + [[ -e /etc/nsswitch.conf ]] && assertEquals "$(cat /etc/nsswitch.conf)" "$(cat ${JUNEST_HOME}/etc/nsswitch.conf)" + [[ -e /etc/resolv.conf ]] && assertEquals "$(cat /etc/resolv.conf)" "$(cat ${JUNEST_HOME}/etc/resolv.conf)" } function _test_copy_remaining_files() { - [[ -e /etc/hosts.equiv ]] && assertEquals "$(cat /etc/hosts.equiv)" "$(cat "${JUNEST_HOME}"/etc/hosts.equiv)" - [[ -e /etc/netgroup ]] && assertEquals "$(cat /etc/netgroup)" "$(cat "${JUNEST_HOME}"/etc/netgroup)" - [[ -e /etc/networks ]] && assertEquals "$(cat /etc/networks)" "$(cat "${JUNEST_HOME}"/etc/networks)" + [[ -e /etc/hosts.equiv ]] && assertEquals "$(cat /etc/hosts.equiv)" "$(cat ${JUNEST_HOME}/etc/hosts.equiv)" + [[ -e /etc/netgroup ]] && assertEquals "$(cat /etc/netgroup)" "$(cat ${JUNEST_HOME}/etc/netgroup)" + [[ -e /etc/networks ]] && assertEquals "$(cat /etc/networks)" "$(cat ${JUNEST_HOME}/etc/networks)" [[ -e ${JUNEST_HOME}/etc/passwd ]] assertEquals 0 $? @@ -59,78 +57,59 @@ function _test_copy_remaining_files() { } function test_is_user_namespace_enabled_no_config_file(){ - PROC_USERNS_FILE="blah" - PROC_USERNS_CLONE_FILE="blah" CONFIG_PROC_FILE="blah" CONFIG_BOOT_FILE="blah" - assertCommandFailOnStatus "$NOT_EXISTING_FILE" _is_user_namespace_enabled + assertCommandFailOnStatus $NOT_EXISTING_FILE _is_user_namespace_enabled } function test_is_user_namespace_enabled_no_config(){ - PROC_USERNS_FILE="blah" - PROC_USERNS_CLONE_FILE="blah" touch config gzip config - # shellcheck disable=SC2034 CONFIG_PROC_FILE="config.gz" - # shellcheck disable=SC2034 CONFIG_BOOT_FILE="blah" - assertCommandFailOnStatus "$NO_CONFIG_FOUND" _is_user_namespace_enabled + assertCommandFailOnStatus $NO_CONFIG_FOUND _is_user_namespace_enabled +} + +function test_is_user_namespace_enabled_with_config(){ + echo "CONFIG_USER_NS=y" > config + gzip config + CONFIG_PROC_FILE="config.gz" + CONFIG_BOOT_FILE="blah" + PROC_USERNS_CLONE_FILE="not-existing-file" + assertCommandSuccess _is_user_namespace_enabled } function test_is_user_namespace_enabled_with_userns_clone_file_disabled(){ - PROC_USERNS_FILE="blah" + echo "CONFIG_USER_NS=y" > config + gzip config + CONFIG_PROC_FILE="config.gz" + CONFIG_BOOT_FILE="blah" PROC_USERNS_CLONE_FILE="unprivileged_userns_clone" echo "0" > $PROC_USERNS_CLONE_FILE - assertCommandFailOnStatus "$UNPRIVILEGED_USERNS_DISABLED" _is_user_namespace_enabled + assertCommandFailOnStatus $UNPRIVILEGED_USERNS_DISABLED _is_user_namespace_enabled } function test_is_user_namespace_enabled_with_userns_clone_file_enabled(){ + echo "CONFIG_USER_NS=y" > config + gzip config + CONFIG_PROC_FILE="config.gz" + CONFIG_BOOT_FILE="blah" PROC_USERNS_CLONE_FILE="unprivileged_userns_clone" echo "1" > $PROC_USERNS_CLONE_FILE assertCommandSuccess _is_user_namespace_enabled } -function test_is_user_namespace_enabled_with_proc_userns_file_existing(){ - PROC_USERNS_FILE="user" - ln -s . $PROC_USERNS_FILE - PROC_USERNS_CLONE_FILE="blah" - assertCommandSuccess _is_user_namespace_enabled -} - -function test_run_env_as_bwrap_fakeroot() { - assertCommandSuccess run_env_as_bwrap_fakeroot "" "" "false" - assertEquals "$BWRAP $COMMON_BWRAP_OPTION --cap-add ALL --uid 0 --gid 0 sudo /bin/sh --login" "$(cat "$STDOUTF")" - - _test_copy_common_files -} - -function test_run_env_as_bwrap_fakeroot_with_backend_command() { - assertCommandSuccess run_env_as_bwrap_fakeroot "mybwrap" "" "false" - assertEquals "mybwrap $COMMON_BWRAP_OPTION --cap-add ALL --uid 0 --gid 0 sudo /bin/sh --login" "$(cat "$STDOUTF")" - - _test_copy_common_files -} - -function test_run_env_as_bwrap_user() { - assertCommandSuccess run_env_as_bwrap_user "" "" "false" - assertEquals "$BWRAP $COMMON_BWRAP_OPTION /bin/sh --login" "$(cat "$STDOUTF")" +function test_run_env_with_namespace() { + assertCommandSuccess run_env_with_namespace "" "false" "" + assertEquals "unshare --mount --user --map-root-user $GROOT --no-umount --recursive -b $HOME -b /tmp -b /proc -b /sys -b /dev $JUNEST_HOME /bin/sh --login" "$(cat $STDOUTF)" _test_copy_common_files _test_copy_remaining_files } -function test_run_env_as_bwrap_user_with_backend_command() { - assertCommandSuccess run_env_as_bwrap_user "mybwrap" "" "false" - assertEquals "mybwrap $COMMON_BWRAP_OPTION /bin/sh --login" "$(cat "$STDOUTF")" - - _test_copy_common_files - _test_copy_remaining_files -} - -function test_run_env_as_bwrap_fakeroot_no_copy() { - assertCommandSuccess run_env_as_bwrap_fakeroot "" "" "true" "" - assertEquals "$BWRAP $COMMON_BWRAP_OPTION --cap-add ALL --uid 0 --gid 0 sudo /bin/sh --login" "$(cat "$STDOUTF")" +function test_run_env_with_namespace_no_copy() { + assertCommandSuccess run_env_with_namespace "" "true" "" + assertEquals "unshare --mount --user --map-root-user $GROOT --no-umount --recursive -b $HOME -b /tmp -b /proc -b /sys -b /dev $JUNEST_HOME /bin/sh --login" "$(cat $STDOUTF)" [[ ! -e ${JUNEST_HOME}/etc/hosts ]] assertEquals 0 $? @@ -154,88 +133,34 @@ function test_run_env_as_bwrap_fakeroot_no_copy() { assertEquals 0 $? } -function test_run_env_as_bwrap_user_no_copy() { - assertCommandSuccess run_env_as_bwrap_user "" "" "true" "" - assertEquals "$BWRAP $COMMON_BWRAP_OPTION /bin/sh --login" "$(cat "$STDOUTF")" - - [[ ! -e ${JUNEST_HOME}/etc/hosts ]] - assertEquals 0 $? - [[ ! -e ${JUNEST_HOME}/etc/host.conf ]] - assertEquals 0 $? - [[ ! -e ${JUNEST_HOME}/etc/nsswitch.conf ]] - assertEquals 0 $? - [[ ! -e ${JUNEST_HOME}/etc/resolv.conf ]] - assertEquals 0 $? - - [[ ! -e ${JUNEST_HOME}/etc/hosts.equiv ]] - assertEquals 0 $? - [[ ! -e ${JUNEST_HOME}/etc/netgroup ]] - assertEquals 0 $? - [[ ! -e ${JUNEST_HOME}/etc/networks ]] - assertEquals 0 $? - - [[ ! -e ${JUNEST_HOME}/etc/passwd ]] - assertEquals 0 $? - [[ ! -e ${JUNEST_HOME}/etc/group ]] - assertEquals 0 $? -} - -function test_run_env_as_bwrap_fakeroot_with_backend_args() { - assertCommandSuccess run_env_as_bwrap_fakeroot "" "--bind /usr /usr" "false" - assertEquals "$BWRAP $COMMON_BWRAP_OPTION --cap-add ALL --uid 0 --gid 0 --bind /usr /usr sudo /bin/sh --login" "$(cat "$STDOUTF")" - - _test_copy_common_files -} - -function test_run_env_as_bwrap_user_with_backend_args() { - assertCommandSuccess run_env_as_bwrap_user "" "--bind /usr /usr" "false" - assertEquals "$BWRAP $COMMON_BWRAP_OPTION --bind /usr /usr /bin/sh --login" "$(cat "$STDOUTF")" +function test_run_env_with_namespace_with_bindings() { + assertCommandSuccess run_env_with_namespace "-b /usr -b /lib:/tmp/lib" "false" "" + assertEquals "unshare --mount --user --map-root-user $GROOT --no-umount --recursive -b $HOME -b /tmp -b /proc -b /sys -b /dev -b /usr -b /lib:/tmp/lib $JUNEST_HOME /bin/sh --login" "$(cat $STDOUTF)" _test_copy_common_files _test_copy_remaining_files } -function test_run_env_as_bwrap_fakeroot_with_command() { - assertCommandSuccess run_env_as_bwrap_fakeroot "" "" "false" "ls -la" - assertEquals "$BWRAP $COMMON_BWRAP_OPTION --cap-add ALL --uid 0 --gid 0 sudo /bin/sh --login -c \"ls -la\"" "$(cat "$STDOUTF")" - - _test_copy_common_files -} - -function test_run_env_as_bwrap_user_with_command() { - assertCommandSuccess run_env_as_bwrap_user "" "" "false" "ls -la" - assertEquals "$BWRAP $COMMON_BWRAP_OPTION /bin/sh --login -c \"ls -la\"" "$(cat "$STDOUTF")" +function test_run_env_with_namespace_with_command() { + assertCommandSuccess run_env_with_namespace "" "false" "ls -la" + assertEquals "unshare --mount --user --map-root-user $GROOT --no-umount --recursive -b $HOME -b /tmp -b /proc -b /sys -b /dev $JUNEST_HOME /bin/sh --login -c \"ls -la\"" "$(cat $STDOUTF)" _test_copy_common_files _test_copy_remaining_files } -function test_run_env_as_bwrap_fakeroot_with_backend_args_and_command() { - assertCommandSuccess run_env_as_bwrap_fakeroot "" "--bind /usr /usr" "false" "ls -la" - assertEquals "$BWRAP $COMMON_BWRAP_OPTION --cap-add ALL --uid 0 --gid 0 --bind /usr /usr sudo /bin/sh --login -c \"ls -la\"" "$(cat "$STDOUTF")" - - _test_copy_common_files -} - -function test_run_env_as_bwrap_user_with_backend_args_and_command() { - assertCommandSuccess run_env_as_bwrap_user "" "--bind /usr /usr" "false" "ls -la" - assertEquals "$BWRAP $COMMON_BWRAP_OPTION --bind /usr /usr /bin/sh --login -c \"ls -la\"" "$(cat "$STDOUTF")" +function test_run_env_with_namespace_with_bindings_and_command() { + assertCommandSuccess run_env_with_namespace "-b /usr -b /lib:/tmp/lib" "false" "ls -la" + assertEquals "unshare --mount --user --map-root-user $GROOT --no-umount --recursive -b $HOME -b /tmp -b /proc -b /sys -b /dev -b /usr -b /lib:/tmp/lib $JUNEST_HOME /bin/sh --login -c \"ls -la\"" "$(cat $STDOUTF)" _test_copy_common_files _test_copy_remaining_files } -function test_run_env_as_bwrap_fakeroot_nested_env(){ +function test_run_env_with_namespace_nested_env(){ JUNEST_ENV=1 - assertCommandFailOnStatus 106 run_env_as_bwrap_fakeroot "" "" "false" "" + assertCommandFailOnStatus 106 run_env_with_namespace "" "false" "" unset JUNEST_ENV } -function test_run_env_as_bwrap_user_nested_env(){ - # shellcheck disable=SC2034 - JUNEST_ENV=1 - assertCommandFailOnStatus 106 run_env_as_bwrap_user "" "" "false" "" - unset JUNEST_ENV -} - -source "$JUNEST_ROOT"/tests/utils/shunit2 +source $JUNEST_ROOT/tests/utils/shunit2 diff --git a/tests/unit-tests/test-proot.sh b/tests/unit-tests/test-proot.sh index 0f4f11a..a951cd6 100755 --- a/tests/unit-tests/test-proot.sh +++ b/tests/unit-tests/test-proot.sh @@ -1,7 +1,6 @@ #!/bin/bash -# shellcheck disable=SC1091 -JUNEST_ROOT=$(readlink -f "$(dirname "$0")"/../..) +JUNEST_ROOT=$(readlink -f $(dirname $0)/../..) source "$JUNEST_ROOT/tests/utils/utils.sh" @@ -31,16 +30,16 @@ function tearDown(){ } function _test_copy_common_files() { - [[ -e /etc/hosts ]] && assertEquals "$(cat /etc/hosts)" "$(cat "${JUNEST_HOME}"/etc/hosts)" - [[ -e /etc/host.conf ]] && assertEquals "$(cat /etc/host.conf)" "$(cat "${JUNEST_HOME}"/etc/host.conf)" - [[ -e /etc/nsswitch.conf ]] && assertEquals "$(cat /etc/nsswitch.conf)" "$(cat "${JUNEST_HOME}"/etc/nsswitch.conf)" - [[ -e /etc/resolv.conf ]] && assertEquals "$(cat /etc/resolv.conf)" "$(cat "${JUNEST_HOME}"/etc/resolv.conf)" + [[ -e /etc/hosts ]] && assertEquals "$(cat /etc/hosts)" "$(cat ${JUNEST_HOME}/etc/hosts)" + [[ -e /etc/host.conf ]] && assertEquals "$(cat /etc/host.conf)" "$(cat ${JUNEST_HOME}/etc/host.conf)" + [[ -e /etc/nsswitch.conf ]] && assertEquals "$(cat /etc/nsswitch.conf)" "$(cat ${JUNEST_HOME}/etc/nsswitch.conf)" + [[ -e /etc/resolv.conf ]] && assertEquals "$(cat /etc/resolv.conf)" "$(cat ${JUNEST_HOME}/etc/resolv.conf)" } function _test_copy_remaining_files() { - [[ -e /etc/hosts.equiv ]] && assertEquals "$(cat /etc/hosts.equiv)" "$(cat "${JUNEST_HOME}"/etc/hosts.equiv)" - [[ -e /etc/netgroup ]] && assertEquals "$(cat /etc/netgroup)" "$(cat "${JUNEST_HOME}"/etc/netgroup)" - [[ -e /etc/networks ]] && assertEquals "$(cat /etc/networks)" "$(cat "${JUNEST_HOME}"/etc/networks)" + [[ -e /etc/hosts.equiv ]] && assertEquals "$(cat /etc/hosts.equiv)" "$(cat ${JUNEST_HOME}/etc/hosts.equiv)" + [[ -e /etc/netgroup ]] && assertEquals "$(cat /etc/netgroup)" "$(cat ${JUNEST_HOME}/etc/netgroup)" + [[ -e /etc/networks ]] && assertEquals "$(cat /etc/networks)" "$(cat ${JUNEST_HOME}/etc/networks)" [[ -e ${JUNEST_HOME}/etc/passwd ]] assertEquals 0 $? @@ -48,51 +47,27 @@ function _test_copy_remaining_files() { assertEquals 0 $? } -function test_run_env_as_proot_user(){ - # shellcheck disable=SC2317 +function test_run_env_as_user(){ _run_env_with_qemu() { - # shellcheck disable=SC2086 - # shellcheck disable=SC2048 - echo $* + echo $@ } - assertCommandSuccess run_env_as_proot_user "" "-k 3.10" "false" "/usr/bin/mkdir" "-v" "/newdir2" - assertEquals "-b /run/user/$(id -u) -b $HOME -b /tmp -b /proc -b /sys -b /dev -r ${JUNEST_HOME} -k 3.10 /usr/bin/mkdir -v /newdir2" "$(cat "$STDOUTF")" + assertCommandSuccess run_env_as_user "-k 3.10" "false" "/usr/bin/mkdir" "-v" "/newdir2" + assertEquals "-b $HOME -b /tmp -b /proc -b /sys -b /dev -r ${JUNEST_HOME} -k 3.10 /usr/bin/mkdir -v /newdir2" "$(cat $STDOUTF)" SH=("/usr/bin/echo") - assertCommandSuccess run_env_as_proot_user "" "-k 3.10" "false" - assertEquals "-b /run/user/$(id -u) -b $HOME -b /tmp -b /proc -b /sys -b /dev -r ${JUNEST_HOME} -k 3.10" "$(cat "$STDOUTF")" + assertCommandSuccess run_env_as_user "-k 3.10" "false" + assertEquals "-b $HOME -b /tmp -b /proc -b /sys -b /dev -r ${JUNEST_HOME} -k 3.10" "$(cat $STDOUTF)" _test_copy_common_files _test_copy_remaining_files } -function test_run_env_as_proot_user_with_backend_command(){ - # shellcheck disable=SC2317 +function test_run_env_as_user_no_copy(){ _run_env_with_qemu() { - # shellcheck disable=SC2086 - # shellcheck disable=SC2048 - echo $* + echo $@ } - assertCommandSuccess run_env_as_proot_user "myproot" "-k 3.10" "false" "/usr/bin/mkdir" "-v" "/newdir2" - assertEquals "myproot -b /run/user/$(id -u) -b $HOME -b /tmp -b /proc -b /sys -b /dev -r ${JUNEST_HOME} -k 3.10 /usr/bin/mkdir -v /newdir2" "$(cat "$STDOUTF")" - - SH=("/usr/bin/echo") - assertCommandSuccess run_env_as_proot_user "myproot" "-k 3.10" "false" - assertEquals "myproot -b /run/user/$(id -u) -b $HOME -b /tmp -b /proc -b /sys -b /dev -r ${JUNEST_HOME} -k 3.10" "$(cat "$STDOUTF")" - - _test_copy_common_files - _test_copy_remaining_files -} - -function test_run_env_as_proot_user_no_copy(){ - # shellcheck disable=SC2317 - _run_env_with_qemu() { - # shellcheck disable=SC2086 - # shellcheck disable=SC2048 - echo $* - } - assertCommandSuccess run_env_as_proot_user "" "-k 3.10" "true" "/usr/bin/mkdir" "-v" "/newdir2" - assertEquals "-b /run/user/$(id -u) -b $HOME -b /tmp -b /proc -b /sys -b /dev -r ${JUNEST_HOME} -k 3.10 /usr/bin/mkdir -v /newdir2" "$(cat "$STDOUTF")" + assertCommandSuccess run_env_as_user "-k 3.10" "true" "/usr/bin/mkdir" "-v" "/newdir2" + assertEquals "-b $HOME -b /tmp -b /proc -b /sys -b /dev -r ${JUNEST_HOME} -k 3.10 /usr/bin/mkdir -v /newdir2" "$(cat $STDOUTF)" [[ ! -e ${JUNEST_HOME}/etc/hosts ]] assertEquals 0 $? @@ -116,105 +91,69 @@ function test_run_env_as_proot_user_no_copy(){ assertEquals 0 $? } -function test_run_env_as_proot_user_nested_env(){ +function test_run_env_as_user_nested_env(){ JUNEST_ENV=1 - assertCommandFailOnStatus 106 run_env_as_proot_user "" "" "false" + assertCommandFailOnStatus 106 run_env_as_user "" "false" unset JUNEST_ENV } -function test_run_env_as_proot_fakeroot(){ - # shellcheck disable=SC2317 +function test_run_env_as_fakeroot(){ _run_env_with_qemu() { - # shellcheck disable=SC2086 - # shellcheck disable=SC2048 - echo $* + echo $@ } - assertCommandSuccess run_env_as_proot_fakeroot "" "-k 3.10" "false" "/usr/bin/mkdir" "-v" "/newdir2" - assertEquals "-0 -b /run/user/$(id -u) -b ${HOME} -b /tmp -b /proc -b /sys -b /dev -r ${JUNEST_HOME} -k 3.10 /usr/bin/mkdir -v /newdir2" "$(cat "$STDOUTF")" + assertCommandSuccess run_env_as_fakeroot "-k 3.10" "false" "/usr/bin/mkdir" "-v" "/newdir2" + assertEquals "-0 -b ${HOME} -b /tmp -b /proc -b /sys -b /dev -r ${JUNEST_HOME} -k 3.10 /usr/bin/mkdir -v /newdir2" "$(cat $STDOUTF)" SH=("/usr/bin/echo") - assertCommandSuccess run_env_as_proot_fakeroot "" "-k 3.10" "false" - assertEquals "-0 -b /run/user/$(id -u) -b ${HOME} -b /tmp -b /proc -b /sys -b /dev -r ${JUNEST_HOME} -k 3.10" "$(cat "$STDOUTF")" + assertCommandSuccess run_env_as_fakeroot "-k 3.10" "false" + assertEquals "-0 -b ${HOME} -b /tmp -b /proc -b /sys -b /dev -r ${JUNEST_HOME} -k 3.10" "$(cat $STDOUTF)" _test_copy_common_files } -function test_run_env_as_proot_fakeroot_with_backend_command(){ - # shellcheck disable=SC2317 - _run_env_with_qemu() { - # shellcheck disable=SC2086 - # shellcheck disable=SC2048 - echo $* - } - assertCommandSuccess run_env_as_proot_fakeroot "myproot" "-k 3.10" "false" "/usr/bin/mkdir" "-v" "/newdir2" - assertEquals "myproot -0 -b /run/user/$(id -u) -b ${HOME} -b /tmp -b /proc -b /sys -b /dev -r ${JUNEST_HOME} -k 3.10 /usr/bin/mkdir -v /newdir2" "$(cat "$STDOUTF")" - - # shellcheck disable=SC2034 - SH=("/usr/bin/echo") - assertCommandSuccess run_env_as_proot_fakeroot "myproot" "-k 3.10" "false" - assertEquals "myproot -0 -b /run/user/$(id -u) -b ${HOME} -b /tmp -b /proc -b /sys -b /dev -r ${JUNEST_HOME} -k 3.10" "$(cat "$STDOUTF")" - - _test_copy_common_files -} - -function test_run_env_as_proot_fakeroot_nested_env(){ +function test_run_env_as_fakeroot_nested_env(){ JUNEST_ENV=1 - assertCommandFailOnStatus 106 run_env_as_proot_fakeroot "" "" "false" "" + assertCommandFailOnStatus 106 run_env_as_fakeroot "" "false" "" unset JUNEST_ENV } function test_run_env_with_quotes(){ - # shellcheck disable=SC2317 _run_env_with_qemu() { - # shellcheck disable=SC2086 - # shellcheck disable=SC2048 - echo $* + echo $@ } - assertCommandSuccess run_env_as_proot_user "" "-k 3.10" "false" "bash" "-c" "/usr/bin/mkdir -v /newdir2" - assertEquals "-b /run/user/$(id -u) -b ${HOME} -b /tmp -b /proc -b /sys -b /dev -r ${JUNEST_HOME} -k 3.10 bash -c /usr/bin/mkdir -v /newdir2" "$(cat "$STDOUTF")" + assertCommandSuccess run_env_as_user "-k 3.10" "false" "bash" "-c" "/usr/bin/mkdir -v /newdir2" + assertEquals "-b ${HOME} -b /tmp -b /proc -b /sys -b /dev -r ${JUNEST_HOME} -k 3.10 bash -c /usr/bin/mkdir -v /newdir2" "$(cat $STDOUTF)" } function test_run_env_with_proot_args(){ - # shellcheck disable=SC2317 proot_cmd() { [ "$JUNEST_ENV" != "1" ] && return 1 - # shellcheck disable=SC2086 - # shellcheck disable=SC2048 - echo $* + echo $@ } - assertCommandSuccess _run_env_with_proot "" "--help" - assertEquals "--help /bin/sh --login" "$(cat "$STDOUTF")" + assertCommandSuccess _run_env_with_proot --help + assertEquals "--help /bin/sh --login" "$(cat $STDOUTF)" - assertCommandSuccess _run_env_with_proot "" "--help" mycommand - assertEquals "--help /bin/sh --login -c mycommand" "$(cat "$STDOUTF")" + assertCommandSuccess _run_env_with_proot --help mycommand + assertEquals "--help /bin/sh --login -c mycommand" "$(cat $STDOUTF)" assertCommandFail _run_env_with_proot } function test_qemu() { - echo "JUNEST_ARCH=arm" > "${JUNEST_HOME}"/etc/junest/info - # shellcheck disable=SC2317 + echo "JUNEST_ARCH=arm" > ${JUNEST_HOME}/etc/junest/info rm_cmd() { - # shellcheck disable=SC2086 - # shellcheck disable=SC2048 - echo $* + echo $@ } - # shellcheck disable=SC2317 ln_cmd() { - # shellcheck disable=SC2086 - # shellcheck disable=SC2048 - echo $* + echo $@ } - # shellcheck disable=SC2317 _run_env_with_proot() { - # shellcheck disable=SC2086 - # shellcheck disable=SC2048 - echo $* + echo $@ } - RANDOM=100 ARCH=x86_64 assertCommandSuccess _run_env_with_qemu "" "" - assertEquals "$(echo -e "-s $JUNEST_HOME/bin/qemu-arm-static-x86_64 /tmp/qemu-arm-static-x86_64-100\n-q /tmp/qemu-arm-static-x86_64-100")" "$(cat "$STDOUTF")" + RANDOM=100 ARCH=x86_64 assertCommandSuccess _run_env_with_qemu "" + assertEquals "$(echo -e "-s $JUNEST_HOME/opt/qemu/qemu-arm-static-x86_64 /tmp/qemu-arm-static-x86_64-100\n-q /tmp/qemu-arm-static-x86_64-100")" "$(cat $STDOUTF)" } -source "$JUNEST_ROOT"/tests/utils/shunit2 +source $JUNEST_ROOT/tests/utils/shunit2 diff --git a/tests/unit-tests/test-setup.sh b/tests/unit-tests/test-setup.sh index de2df75..a15dbca 100755 --- a/tests/unit-tests/test-setup.sh +++ b/tests/unit-tests/test-setup.sh @@ -1,7 +1,6 @@ #!/bin/bash -# shellcheck disable=SC1091 -JUNEST_ROOT=$(readlink -f "$(dirname "$0")"/../..) +JUNEST_ROOT=$(readlink -f $(dirname $0)/../..) source "$JUNEST_ROOT/tests/utils/utils.sh" @@ -27,27 +26,24 @@ function tearDown(){ } function test_is_env_installed(){ - rm -rf "${JUNEST_HOME:?}"/* + rm -rf $JUNEST_HOME/* assertCommandFail is_env_installed - touch "$JUNEST_HOME"/just_file + touch $JUNEST_HOME/just_file assertCommandSuccess is_env_installed } function test_setup_env(){ - rm -rf "${JUNEST_HOME:?}"/* - # shellcheck disable=SC2317 + rm -rf $JUNEST_HOME/* wget_mock(){ # Proof that the setup is happening # inside $JUNEST_TEMPDIR - local cwd=${PWD#"${JUNEST_TEMPDIR}"} - local parent_dir=${PWD%"${cwd}"} + local cwd=${PWD#${JUNEST_TEMPDIR}} + local parent_dir=${PWD%${cwd}} assertEquals "$JUNEST_TEMPDIR" "${parent_dir}" touch file - tar -czvf "${CMD}-${ARCH}".tar.gz file + tar -czvf ${CMD}-${ARCH}.tar.gz file } - # shellcheck disable=SC2034 WGET=wget_mock - # shellcheck disable=SC2119 setup_env 1> /dev/null assertTrue "[ -e $JUNEST_HOME/file ]" @@ -56,10 +52,10 @@ function test_setup_env(){ function test_setup_env_from_file(){ - rm -rf "${JUNEST_HOME:?}"/* + rm -rf $JUNEST_HOME/* touch file - tar -czvf "${CMD}-${ARCH}".tar.gz file 1> /dev/null - assertCommandSuccess setup_env_from_file "${CMD}-${ARCH}.tar.gz" + tar -czvf ${CMD}-${ARCH}.tar.gz file 1> /dev/null + assertCommandSuccess setup_env_from_file ${CMD}-${ARCH}.tar.gz assertTrue "[ -e $JUNEST_HOME/file ]" } @@ -68,10 +64,10 @@ function test_setup_env_from_file_not_existing_file(){ } function test_setup_env_from_file_with_absolute_path(){ - rm -rf "${JUNEST_HOME:?}"/* + rm -rf $JUNEST_HOME/* touch file - tar -czf "${CMD}-${ARCH}".tar.gz file - assertCommandSuccess setup_env_from_file "${CMD}-${ARCH}.tar.gz" + tar -czf ${CMD}-${ARCH}.tar.gz file + assertCommandSuccess setup_env_from_file ${CMD}-${ARCH}.tar.gz assertTrue "[ -e $JUNEST_HOME/file ]" } @@ -82,4 +78,4 @@ function test_delete_env(){ assertCommandFail is_env_installed } -source "$JUNEST_ROOT"/tests/utils/shunit2 +source $JUNEST_ROOT/tests/utils/shunit2 diff --git a/tests/unit-tests/test-utils.sh b/tests/unit-tests/test-utils.sh index 03e602a..c0b1ebf 100755 --- a/tests/unit-tests/test-utils.sh +++ b/tests/unit-tests/test-utils.sh @@ -1,13 +1,10 @@ #!/bin/bash -# shellcheck disable=SC1091 - -source "$(dirname "$0")/../utils/utils.sh" +source "$(dirname $0)/../utils/utils.sh" unset HOME -export HOME -HOME=$(TMPDIR=/tmp mktemp -d -t pearl-user-home.XXXXXXX) +export HOME=$(TMPDIR=/tmp mktemp -d -t pearl-user-home.XXXXXXX) -source "$(dirname "$0")/../../lib/utils/utils.sh" +source "$(dirname $0)/../../lib/utils/utils.sh" # Disable the exiterr set +e @@ -23,42 +20,37 @@ function test_check_not_null(){ function test_echoerr(){ assertCommandSuccess echoerr "Test" - assertEquals "Test" "$(cat "$STDERRF")" + assertEquals "Test" "$(cat $STDERRF)" } function test_error(){ assertCommandSuccess error "Test" - local expected - expected=$(echo -e "\033[1;31mTest\033[0m") - assertEquals "$expected" "$(cat "$STDERRF")" + local expected=$(echo -e "\033[1;31mTest\033[0m") + assertEquals "$expected" "$(cat $STDERRF)" } function test_warn(){ assertCommandSuccess warn "Test" - local expected - expected=$(echo -e "\033[1;33mTest\033[0m") - assertEquals "$expected" "$(cat "$STDERRF")" + local expected=$(echo -e "\033[1;33mTest\033[0m") + assertEquals "$expected" "$(cat $STDERRF)" } function test_info(){ assertCommandSuccess info "Test" - local expected - expected=$(echo -e "\033[1;36mTest\033[0m") - assertEquals "$expected" "$(cat "$STDOUTF")" + local expected=$(echo -e "\033[1;36mTest\033[0m") + assertEquals "$expected" "$(cat $STDOUTF)" } function test_die(){ assertCommandFail die "Test" - local expected - expected=$(echo -e "\033[1;31mTest\033[0m") - assertEquals "$expected" "$(cat "$STDERRF")" + local expected=$(echo -e "\033[1;31mTest\033[0m") + assertEquals "$expected" "$(cat $STDERRF)" } function test_die_on_status(){ assertCommandFailOnStatus 222 die_on_status 222 "Test" - local expected - expected=$(echo -e "\033[1;31mTest\033[0m") - assertEquals "$expected" "$(cat "$STDERRF")" + local expected=$(echo -e "\033[1;31mTest\033[0m") + assertEquals "$expected" "$(cat $STDERRF)" } function test_ask_null_question(){ @@ -87,12 +79,34 @@ function test_ask_wrong_default_answer() { assertEquals 33 $? } +function test_check_and_trap_fail() { + trap echo EXIT + trap ls QUIT + assertCommandFailOnStatus 1 check_and_trap 'pwd' EXIT QUIT +} + +function test_check_and_trap() { + trap - EXIT QUIT + assertCommandSuccess check_and_trap 'echo' EXIT QUIT +} + +function test_check_and_force_trap_fail() { + trap echo EXIT + trap ls QUIT + assertCommandSuccess check_and_force_trap 'echo' EXIT QUIT +} + +function test_check_and_force_trap() { + trap - EXIT QUIT + assertCommandSuccess check_and_force_trap 'echo' EXIT QUIT +} + function test_insert_quotes_on_spaces(){ assertCommandSuccess insert_quotes_on_spaces this is "a test" - assertEquals "this is \"a test\"" "$(cat "$STDOUTF")" + assertEquals "this is \"a test\"" "$(cat $STDOUTF)" assertCommandSuccess insert_quotes_on_spaces this is 'a test' - assertEquals "this is \"a test\"" "$(cat "$STDOUTF")" + assertEquals "this is \"a test\"" "$(cat $STDOUTF)" } function test_contains_element(){ @@ -102,4 +116,4 @@ function test_contains_element(){ assertCommandFailOnStatus 1 contains_element "blabla" "${array[@]}" } -source "$(dirname "$0")"/../utils/shunit2 +source $(dirname $0)/../utils/shunit2 diff --git a/tests/unit-tests/test-wrappers.sh b/tests/unit-tests/test-wrappers.sh deleted file mode 100755 index ee9776f..0000000 --- a/tests/unit-tests/test-wrappers.sh +++ /dev/null @@ -1,139 +0,0 @@ -#!/bin/bash -# shellcheck disable=SC1091 - -source "$(dirname "$0")/../utils/utils.sh" - -source "$(dirname "$0")/../../lib/core/wrappers.sh" - -# Disable the exiterr -set +e - -function oneTimeSetUp(){ - setUpUnitTests -} - -function setUp(){ - junestSetUp -} - -function tearDown(){ - junestTearDown -} - -function test_create_wrappers_empty_bin(){ - assertCommandSuccess create_wrappers - assertEquals "" "$(cat "$STDOUTF")" - assertTrue "bin_wrappers does not exist" "[ -e $JUNEST_HOME/usr/bin_wrappers ]" -} - -function test_create_wrappers_not_executable_file(){ - touch "$JUNEST_HOME"/usr/bin/myfile - assertCommandSuccess create_wrappers - assertEquals "" "$(cat "$STDOUTF")" - assertTrue "bin_wrappers should exist" "[ -e $JUNEST_HOME/usr/bin_wrappers ]" - assertTrue "myfile wrapper should not exist" "[ ! -x $JUNEST_HOME/usr/bin_wrappers/myfile ]" -} - -function test_create_wrappers_directory(){ - mkdir -p "$JUNEST_HOME"/usr/bin/mydir - assertCommandSuccess create_wrappers - assertEquals "" "$(cat "$STDOUTF")" - assertTrue "bin_wrappers should exist" "[ -e $JUNEST_HOME/usr/bin_wrappers ]" - assertTrue "mydir wrapper should not exist" "[ ! -e $JUNEST_HOME/usr/bin_wrappers/mydir ]" -} - -function test_create_wrappers_broken_link(){ - ln -s /opt/myapp/bin/cmd "$JUNEST_HOME"/usr/bin/cmd - assertCommandSuccess create_wrappers - assertEquals "" "$(cat "$STDOUTF")" - assertTrue "bin_wrappers should exist" "[ -e $JUNEST_HOME/usr/bin_wrappers ]" - assertTrue "cmd wrapper should exist" "[ -x $JUNEST_HOME/usr/bin_wrappers/cmd ]" -} - -function test_create_wrappers_executable_file(){ - touch "$JUNEST_HOME"/usr/bin/myfile - chmod +x "$JUNEST_HOME"/usr/bin/myfile - assertCommandSuccess create_wrappers - assertEquals "" "$(cat "$STDOUTF")" - assertTrue "bin_wrappers should exist" "[ -e $JUNEST_HOME/usr/bin_wrappers ]" - assertTrue "myfile wrapper should exist" "[ -x $JUNEST_HOME/usr/bin_wrappers/myfile ]" -} - -function test_create_wrappers_verify_content(){ - # Test for: - # https://github.com/fsquillace/junest/issues/262 - # https://github.com/fsquillace/junest/issues/292 - touch "$JUNEST_HOME"/usr/bin/myfile - chmod +x "$JUNEST_HOME"/usr/bin/myfile - export JUNEST_ARGS="ns --fakeroot -b '--bind /run /run2'" - assertCommandSuccess create_wrappers - assertEquals "" "$(cat "$STDOUTF")" - - # Mock junest command to capture the actual output generated from myfile script - # shellcheck disable=SC2317 - junest(){ - for arg in "$@" - do - echo "$arg" - done - } - assertEquals "ns ---fakeroot --b ---bind /run /run2 --- -test-wrappers.sh -pacman --Rsn -neovim -new package" "$(source "$JUNEST_HOME"/usr/bin_wrappers/myfile pacman -Rsn neovim 'new package')" -} - -function test_create_wrappers_already_exist(){ - touch "$JUNEST_HOME"/usr/bin/myfile - chmod +x "$JUNEST_HOME"/usr/bin/myfile - mkdir -p "$JUNEST_HOME"/usr/bin_wrappers - echo "original" > "$JUNEST_HOME"/usr/bin_wrappers/myfile - chmod +x "$JUNEST_HOME"/usr/bin_wrappers/myfile - assertCommandSuccess create_wrappers false - assertEquals "" "$(cat "$STDOUTF")" - assertTrue "bin_wrappers should exist" "[ -e $JUNEST_HOME/usr/bin_wrappers ]" - assertTrue "myfile wrapper should exist" "[ -x $JUNEST_HOME/usr/bin_wrappers/myfile ]" - assertEquals "original" "$(cat "$JUNEST_HOME"/usr/bin_wrappers/myfile)" -} - -function test_create_wrappers_forced_already_exist(){ - echo "new" > "$JUNEST_HOME"/usr/bin/myfile - chmod +x "$JUNEST_HOME"/usr/bin/myfile - mkdir -p "$JUNEST_HOME"/usr/bin_wrappers - echo "original" > "$JUNEST_HOME"/usr/bin_wrappers/myfile - chmod +x "$JUNEST_HOME"/usr/bin_wrappers/myfile - assertCommandSuccess create_wrappers true - assertEquals "" "$(cat "$STDOUTF")" - assertTrue "bin_wrappers should exist" "[ -e $JUNEST_HOME/usr/bin_wrappers ]" - assertTrue "myfile wrapper should exist" "[ -x $JUNEST_HOME/usr/bin_wrappers/myfile ]" - assertNotEquals "original" "$(cat "$JUNEST_HOME"/usr/bin_wrappers/myfile)" -} - -function test_create_wrappers_executable_no_longer_exist(){ - mkdir -p "$JUNEST_HOME"/usr/bin_wrappers - touch "$JUNEST_HOME"/usr/bin_wrappers/myfile - chmod +x "$JUNEST_HOME"/usr/bin_wrappers/myfile - assertCommandSuccess create_wrappers - assertEquals "" "$(cat "$STDOUTF")" - assertTrue "bin_wrappers should exist" "[ -e $JUNEST_HOME/usr/bin_wrappers ]" - assertTrue "myfile wrapper should not exist" "[ ! -x $JUNEST_HOME/usr/bin_wrappers/myfile ]" -} - -function test_create_wrappers_custom_bin_path(){ - mkdir -p "$JUNEST_HOME"/usr/mybindir - touch "$JUNEST_HOME"/usr/mybindir/myfile - chmod +x "$JUNEST_HOME"/usr/mybindir/myfile - assertCommandSuccess create_wrappers false /usr/mybindir/ - assertEquals "" "$(cat "$STDOUTF")" - assertTrue "bin_wrappers should exist" "[ -e $JUNEST_HOME/usr/mybindir_wrappers ]" - assertTrue "myfile wrapper should exist" "[ -x $JUNEST_HOME/usr/mybindir_wrappers/myfile ]" -} - - -source "$(dirname "$0")"/../utils/shunit2 diff --git a/tests/unit-tests/unit-tests.sh b/tests/unit-tests/unit-tests.sh index e90ed22..acf1bba 100755 --- a/tests/unit-tests/unit-tests.sh +++ b/tests/unit-tests/unit-tests.sh @@ -1,7 +1,6 @@ #!/bin/bash tests_succeded=true -# shellcheck disable=SC2010 -for tst in $(ls "$(dirname "$0")"/test* | grep -v "$(basename "$0")") +for tst in $(ls $(dirname $0)/test* | grep -v $(basename $0)) do $tst || tests_succeded=false done diff --git a/tests/utils/shunit2 b/tests/utils/shunit2 index e4c719c..d6e7503 100644 --- a/tests/utils/shunit2 +++ b/tests/utils/shunit2 @@ -987,7 +987,7 @@ _shunit_extractTestFunctions() # extract the lines with test function names, strip of anything besides the # function name, and output everything on a single line. _shunit_regex_='^[ ]*(function )*test[A-Za-z0-9_]* *\(\)' - grep -E "${_shunit_regex_}" "${_shunit_script_}" \ + egrep "${_shunit_regex_}" "${_shunit_script_}" \ |sed 's/^[^A-Za-z0-9_]*//;s/^function //;s/\([A-Za-z0-9_]*\).*/\1/g' \ |xargs diff --git a/tests/utils/utils.sh b/tests/utils/utils.sh index ab37bd9..ed7cb8c 100644 --- a/tests/utils/utils.sh +++ b/tests/utils/utils.sh @@ -1,28 +1,25 @@ -#!/usr/bin/env bash - OLD_CWD=${PWD} function cwdSetUp(){ ORIGIN_CWD=$(TMPDIR=/tmp mktemp -d -t junest-cwd.XXXXXXXXXX) - cd "$ORIGIN_CWD" || return 1 + cd $ORIGIN_CWD } function cwdTearDown(){ - rm -rf "$ORIGIN_CWD" - cd "$OLD_CWD" || return 1 + rm -rf $ORIGIN_CWD + cd $OLD_CWD } function junestSetUp(){ JUNEST_HOME=$(TMPDIR=/tmp mktemp -d -t junest-home.XXXXXXXXXX) - mkdir -p "${JUNEST_HOME}/usr/bin" - mkdir -p "${JUNEST_HOME}/etc/junest" - echo "JUNEST_ARCH=x86_64" > "${JUNEST_HOME}/etc/junest/info" - mkdir -p "${JUNEST_HOME}/etc/ca-certificates" + mkdir -p ${JUNEST_HOME}/etc/junest + echo "JUNEST_ARCH=x86_64" > ${JUNEST_HOME}/etc/junest/info + mkdir -p ${JUNEST_HOME}/etc/ca-certificates } function junestTearDown(){ # the CA directories are read only and can be deleted only by changing the mod - [ -d "${JUNEST_HOME}/etc/ca-certificates" ] && chmod -R +w "${JUNEST_HOME}/etc/ca-certificates" - rm -rf "$JUNEST_HOME" + [ -d ${JUNEST_HOME}/etc/ca-certificates ] && chmod -R +w ${JUNEST_HOME}/etc/ca-certificates + rm -rf $JUNEST_HOME unset JUNEST_HOME } @@ -34,17 +31,15 @@ function setUpUnitTests(){ } function assertCommandSuccess(){ - # shellcheck disable=SC2091 $(set -e - "$@" > "$STDOUTF" 2> "$STDERRF" + "$@" > $STDOUTF 2> $STDERRF ) assertTrue "The command $1 did not return 0 exit status" $? } function assertCommandFail(){ - # shellcheck disable=SC2091 $(set -e - "$@" > "$STDOUTF" 2> "$STDERRF" + "$@" > $STDOUTF 2> $STDERRF ) assertFalse "The command $1 returned 0 exit status" $? } @@ -54,9 +49,8 @@ function assertCommandFail(){ function assertCommandFailOnStatus(){ local status=$1 shift - # shellcheck disable=SC2091 $(set -e - "$@" > "$STDOUTF" 2> "$STDERRF" + "$@" > $STDOUTF 2> $STDERRF ) - assertEquals "$status" $? + assertEquals $status $? }