diff --git a/Documents/bin/toolbox b/Documents/bin/toolbox deleted file mode 100755 index 16a4483dda05a98ab227c8d5d82b23a7d4a3703e..0000000000000000000000000000000000000000 --- a/Documents/bin/toolbox +++ /dev/null @@ -1,2498 +0,0 @@ -#!/bin/sh -# -# Copyright © 2018 – 2019 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - - -exec 3>/dev/null - -arguments="" -assume_yes=false -base_toolbox_command=$(basename "$0" 2>&3) -base_toolbox_image="" -cgroups_version="" - -# Based on the nameRegex value in: -# https://github.com/containers/libpod/blob/master/libpod/options.go -container_name_regexp="[a-zA-Z0-9][a-zA-Z0-9_.-]*" - -environment=$(set) -environment_variables="COLORTERM \ - COLUMNS \ - DBUS_SESSION_BUS_ADDRESS \ - DBUS_SYSTEM_BUS_ADDRESS \ - DESKTOP_SESSION \ - DISPLAY \ - LANG \ - LINES \ - SHELL \ - SSH_AUTH_SOCK \ - TERM \ - TOOLBOX_PATH \ - VTE_VERSION \ - WAYLAND_DISPLAY \ - XDG_CURRENT_DESKTOP \ - XDG_DATA_DIRS \ - XDG_MENU_PREFIX \ - XDG_RUNTIME_DIR \ - XDG_SEAT \ - XDG_SESSION_DESKTOP \ - XDG_SESSION_ID \ - XDG_SESSION_TYPE \ - XDG_VTNR" -fgc="" - -registry="registry.fedoraproject.org" -registry_candidate="candidate-registry.fedoraproject.org" -release="" -release_default="" -spinner_animation="[>----] [=>---] [==>--] [===>-] [====>] [----<] [---<=] [--<==] [-<===] [<====]" -spinner_template="toolbox-spinner-XXXXXXXXXX" -tab="$(printf '\t')" -toolbox_command_path="" -toolbox_container="" -toolbox_container_default="" -toolbox_container_old_v1="" -toolbox_container_old_v2="" -toolbox_container_prefix_default="" -toolbox_image="" -toolbox_runtime_directory="$XDG_RUNTIME_DIR"/toolbox -user_id_real=$(id -ru 2>&3) -verbose=false - - -LGC='\033[1;32m' # Light Green Color -NC='\033[0m' # No Color - - -has_prefix() -( - str="$1" - prefix="$2" - - ret_val=1 - - case "$str" in - "$prefix"* ) - ret_val=0 - ;; - * ) - ret_val=1 - ;; - esac - - return "$ret_val" -) - - -has_substring() -( - haystack="$1" - needle="$2" - - ret_val=1 - - case "$haystack" in - *"$needle"* ) - ret_val=0 - ;; - * ) - ret_val=1 - ;; - esac - - return "$ret_val" -) - - -is_integer() -{ - [ "$1" != "" ] && [ "$1" -eq "$1" ] 2>&3 - return "$?" -} - - -save_positional_parameters() -{ - for i; do - printf "%s\\n" "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" 2>&3 - done - echo " " -} - - -spinner_start() -( - directory="$1" - message="$2" - - if $verbose; then - rm --force --recursive "$directory" 2>&3 - return 0 - fi - - if ! touch "$directory/spinner-start" 2>&3; then - echo "$base_toolbox_command: unable to start spinner: spinner start file couldn't be created" >&2 - return 1 - fi - - printf "%s" "$message" - tput civis 2>&3 - - exec 4>"$directory/spinner-start" - if ! flock 4 2>&3; then - echo "$base_toolbox_command: unable to start spinner: spinner lock couldn't be acquired" >&2 - return 1 - fi - - ( - while [ -f "$directory/spinner-start" ]; do - echo "$spinner_animation" | sed "s/ /\n/g" 2>&3 | while read -r frame; do - if ! [ -f "$directory/spinner-start" ] 2>&3; then - break - fi - - printf "%s" "$frame" - - frame_len=${#frame} - i=0 - while [ "$i" -lt "$frame_len" ]; do - printf "\b" - i=$((i + 1)) - done - - sleep 1 - done - done - - printf "\033[2K" # delete entire line regardless of cursor position - printf "\r" - tput cnorm 2>&3 - ) & - - return 0 -) - - -spinner_stop() -( - $verbose && return - directory="$1" - - exec 4>"$directory/spinner-start" - - if ! rm "$directory/spinner-start" 2>&3; then - echo "$base_toolbox_command: unable to stop spinner: spinner start file couldn't be removed" >&2 - return - fi - - if ! flock 4 2>&3; then - echo "$base_toolbox_command: unable to stop spinner: spinner lock couldn't be acquired" >&2 - return - fi - - rm --force --recursive "$directory" 2>&3 -) - - -ask_for_confirmation() -( - default_response="$1" - prompt="$2" - ret_val=0 - - while :; do - printf "%s " "$prompt" - read -r user_response - - if [ "$user_response" = "" ] 2>&3; then - user_response="$default_response" - else - user_response=$(echo "$user_response" | tr "[:upper:]" "[:lower:]" 2>&3) - fi - - if [ "$user_response" = "no" ] 2>&3 || [ "$user_response" = "n" ] 2>&3; then - ret_val=1 - break - elif [ "$user_response" = "yes" ] 2>&3 || [ "$user_response" = "y" ] 2>&3; then - ret_val=0 - break - fi - done - - return "$ret_val" -) - - -container_name_is_valid() -( - name="$1" - - echo "$name" | grep "^$container_name_regexp$" >/dev/null 2>&3 - return "$?" -) - - -container_start() -( - container="$1" - - error_message=$( (podman start "$container" >/dev/null) 2>&1) - ret_val="$?" - [ "$error_message" != "" ] 2>&3 && echo "$error_message" >&3 - - if [ "$ret_val" -ne 0 ] 2>&3; then - if echo "$error_message" | grep "use system migrate to mitigate" >/dev/null 2>&3; then - echo "$base_toolbox_command: checking if 'podman system migrate' supports --new-runtime" >&3 - - if ! (podman system migrate --help 2>&3 | grep "new-runtime" >/dev/null 2>&3); then - echo "$base_toolbox_command: container $container doesn't support cgroups v$cgroups_version" >&2 - echo "Update Podman to version 1.6.2 or newer." >&2 - return 1 - else - echo "$base_toolbox_command: 'podman system migrate' supports --new-runtime" >&3 - - oci_runtime_required="runc" - [ "$cgroups_version" -eq 2 ] 2>&3 && oci_runtime_required="crun" - - echo "$base_toolbox_command: migrating containers to OCI runtime $oci_runtime_required" >&3 - - if ! podman system migrate --new-runtime "$oci_runtime_required" >/dev/null 2>&3; then - echo "$base_toolbox_command: failed to migrate containers to OCI runtime $oci_runtime_required" >&2 - echo "Factory reset with: toolbox reset" >&2 - echo "Try '$base_toolbox_command --help' for more information." >&2 - return 1 - fi - - if ! podman start "$container" >/dev/null 2>&3; then - echo "$base_toolbox_command: container $container doesn't support cgroups v$cgroups_version" >&2 - echo "Factory reset with: toolbox reset" >&2 - echo "Try '$base_toolbox_command --help' for more information." >&2 - return 1 - fi - fi - else - echo "$base_toolbox_command: failed to start container $container" >&2 - return 1 - fi - fi - - return 0 -) - - -copy_etc_profile_d_toolbox_to_container() -( - container="$1" - - profile_d_lock="$toolbox_runtime_directory"/profile.d-toolbox.lock - - # shellcheck disable=SC2174 - if ! mkdir --mode 700 --parents "$toolbox_runtime_directory" 2>&3; then - echo "$base_toolbox_command: unable to copy $toolbox_runtime_directory/toolbox.sh: runtime directory not created" >&2 - return 1 - fi - - exec 5>"$profile_d_lock" - if ! flock 5 2>&3; then - echo "$base_toolbox_command: unable to copy $toolbox_runtime_directory/toolbox.sh: copy lock not acquired" >&2 - return 1 - fi - - if ! [ -f "$toolbox_runtime_directory"/toolbox.sh ] 2>&3; then - echo "$base_toolbox_command: $toolbox_runtime_directory/toolbox.sh not found" >&2 - return 0 - fi - - echo "$base_toolbox_command: copying $toolbox_runtime_directory/toolbox.sh to container $container" >&3 - - if ! podman exec \ - --user root:root \ - "$container" \ - sh -c "cp $toolbox_runtime_directory/toolbox.sh /etc/profile.d" sh 2>&3; then - echo "$base_toolbox_command: unable to copy $toolbox_runtime_directory/toolbox.sh to container $container" >&2 - return 1 - fi - - return 0 -) - - -copy_etc_profile_d_toolbox_to_runtime_directory() -( - profile_d_lock="$toolbox_runtime_directory"/profile.d-toolbox.lock - - if ! [ -f /etc/profile.d/toolbox.sh ] 2>&3; then - echo "$base_toolbox_command: /etc/profile.d/toolbox.sh not found" >&2 - return 0 - fi - - # shellcheck disable=SC2174 - if ! mkdir --mode 700 --parents "$toolbox_runtime_directory" 2>&3; then - echo "$base_toolbox_command: unable to copy /etc/profile.d/toolbox.sh: runtime directory not created" >&2 - return 1 - fi - - exec 5>"$profile_d_lock" - if ! flock 5 2>&3; then - echo "$base_toolbox_command: unable to copy /etc/profile.d/toolbox.sh: copy lock not acquired" >&2 - return 1 - fi - - echo "$base_toolbox_command: copying /etc/profile.d/toolbox.sh to $toolbox_runtime_directory" >&3 - - if ! cp /etc/profile.d/toolbox.sh "$toolbox_runtime_directory" 2>&3; then - echo "$base_toolbox_command: unable to copy /etc/profile.d/toolbox.sh to $toolbox_runtime_directory" >&2 - return 1 - fi - - return 0 -) - - -create_enter_command() -( - container="$1" - - if [ "$container" = "$toolbox_container_default" ] 2>&3; then - echo "$base_toolbox_command enter" - elif [ "$container" = "$toolbox_container_prefix_default-$release" ] 2>&3; then - echo "$base_toolbox_command enter --release $release" - else - echo "$base_toolbox_command enter --container $container" - fi -) - - -create_environment_options() -( - columns="" - lines="" - - if terminal_size=$(stty size 2>&3); then - columns=$(echo "$terminal_size" | cut --delimiter " " --fields 2 2>&3) - if ! is_integer "$columns"; then - echo "$base_toolbox_command: failed to parse the number of columns from the terminal size" >&3 - columns="" - fi - - lines=$(echo "$terminal_size" | cut --delimiter " " --fields 1 2>&3) - if ! is_integer "$lines"; then - echo "$base_toolbox_command: failed to parse the number of lines from the terminal size" >&3 - lines="" - fi - else - echo "$base_toolbox_command: failed to read terminal size" >&3 - fi - - echo "$environment_variables" \ - | sed "s/ \+/\n/g" 2>&3 \ - | { - environment_options="" - echo "$base_toolbox_command: creating list of environment variables to forward" >&3 - value="" - while read -r variable; do - if echo "$environment" | grep "^$variable" >/dev/null 2>&3; then - eval value="$""$variable" - echo "$base_toolbox_command: $variable=$value" >&3 - environment_options="$environment_options --env=$variable=$value" - else - echo "$base_toolbox_command: $variable is unset" >&3 - fi - done - - if ! (echo "$environment_options" | grep COLUMNS >/dev/null 2>&3) && [ "$columns" != "" ] 2>&3; then - environment_options="$environment_options --env=COLUMNS=$columns" - fi - - if ! (echo "$environment_options" | grep LINES >/dev/null 2>&3) && [ "$lines" != "" ] 2>&3; then - environment_options="$environment_options --env=LINES=$lines" - fi - - environment_options=${environment_options#" "} - echo "$base_toolbox_command: created options for environment variables to forward" >&3 - echo "$environment_options" >&3 - echo "$environment_options" - } -) - - -create_toolbox_container_name() -( - image="$1" - - basename=$(image_reference_get_basename "$image") - if [ "$basename" = "" ] 2>&3; then - return 100 - fi - - tag=$(image_reference_get_tag "$image") - if [ "$tag" = "" ] 2>&3; then - return 101 - fi - - echo "$basename-$tag" - return 0 -) - - -create_toolbox_image_name() -( - # Based on the ResolveName function implemented in: - # https://github.com/containers/buildah/blob/master/util/util.go - - if image_reference_can_be_id "$base_toolbox_image"; then - if base_toolbox_image_id=$(podman inspect \ - --format "{{.Id}}" \ - --type image \ - "$base_toolbox_image" 2>&3); then - if has_prefix "$base_toolbox_image_id" "$base_toolbox_image"; then - echo "$base_toolbox_image-$USER:latest" - return 0 - fi - fi - fi - - basename=$(image_reference_get_basename "$base_toolbox_image") - if [ "$basename" = "" ] 2>&3; then - return 100 - fi - - tag=$(image_reference_get_tag "$base_toolbox_image") - if [ "$tag" = "" ] 2>&3; then - echo "$basename-$USER:latest" - else - echo "$basename-$USER:$tag" - fi - - return 0 -) - - -enter_print_container_not_found() -( - container="$1" - - echo "$base_toolbox_command: container $container not found" >&2 - echo "Use the 'create' command to create a toolbox." >&2 - echo "Try '$base_toolbox_command --help' for more information." >&2 -) - - -get_cgroups_version() -( - version=1 - - if ! mounts=$(mount 2>&3); then - echo "$base_toolbox_command: failed to detect cgroups version: couldn't list mount points" >&2 - return 1 - fi - - if ! (echo "$mounts" | grep "^cgroup " >/dev/null 2>&3) && (echo "$mounts" | grep "^cgroup2 " >/dev/null 2>&3); then - version=2 - fi - - echo "$version" - return 0 -) - - -get_group_for_sudo() -( - group="" - if getent group sudo >/dev/null 2>&3; then - group="sudo" - elif getent group wheel >/dev/null 2>&3; then - group="wheel" - else - return 1 - fi - - echo "$group" - return 0 -) - - -get_host_id() -( - # shellcheck disable=SC1091 - . /usr/lib/os-release - echo "$ID" -) - - -get_host_variant_id() -( - # shellcheck disable=SC1091 - . /usr/lib/os-release - echo "$VARIANT_ID" -) - - -get_host_version_id() -( - # shellcheck disable=SC1091 - . /usr/lib/os-release - echo "$VERSION_ID" -) - - -image_reference_can_be_id() -( - image="$1" - - echo "$image" | grep "^[a-f0-9]\{6,64\}$" >/dev/null 2>&3 - return "$?" -) - - -image_reference_get_basename() -( - image="$1" - - domain=$(image_reference_get_domain "$image") - remainder=${image#$domain} - path=${remainder%:*} - basename=${path##*/} - echo "$basename" -) - - -image_reference_get_domain() -( - image="$1" - - image_reference_has_domain "$image" && domain=${image%%/*} - echo "$domain" -) - - -image_reference_get_tag() -( - image="$1" - - domain=$(image_reference_get_domain "$image") - remainder=${image#$domain} - - tag="" - if (echo "$remainder" | grep ":" >/dev/null 2>&3); then - tag=${remainder#*:} - fi - - echo "$tag" -) - - -image_reference_has_domain() -( - # Based on the splitDockerDomain function implemented in: - # https://github.com/docker/distribution/blob/master/reference/normalize.go - - image="$1" - - if ! (echo "$image" | grep "/" >/dev/null 2>&3); then - return 1 - fi - - prefix=${image%%/*} - if ! (echo "$prefix" | grep "[.:]" >/dev/null 2>&3) && [ "$prefix" != "localhost" ] 2>&3; then - return 1 - fi - - return 0 -) - - -images_get_details() -( - images="$1" - - if ! echo "$images" | while read -r image; do - [ "$image" = "" ] 2>&3 && continue - - if ! podman images \ - --format "{{.ID}} {{.Repository}}:{{.Tag}} {{.Created}}" \ - --noheading \ - "$image" 2>&3; then - echo "$base_toolbox_command: failed to get details for image $image" >&2 - return 1 - fi - echo - done; then - return 1 - fi - - return 0 -) - - -is_etc_profile_d_toolbox_a_bind_mount() -{ - container="$1" - - podman inspect --format "[{{range .Mounts}}{{.Dst}} {{end}}]" --type container "$container" 2>&3 \ - | grep /etc/profile.d/toolbox.sh >/dev/null 2>/dev/null 2>&3 - - return "$?" -} - - -list_container_names() -( - if ! containers_old=$(podman ps \ - --all \ - --filter "label=com.redhat.component=fedora-toolbox" \ - --format "{{.Names}}" 2>&3); then - echo "$base_toolbox_command: failed to list containers with com.redhat.component=fedora-toolbox" >&2 - return 1 - fi - - if ! containers=$(podman ps \ - --all \ - --filter "label=com.github.debarshiray.toolbox=true" \ - --format "{{.Names}}" 2>&3); then - echo "$base_toolbox_command: failed to list containers with com.github.debarshiray.toolbox=true" >&2 - return 1 - fi - - printf "%s\n%s\n" "$containers_old" "$containers" | sort 2>&3 | uniq 2>&3 - return 0 -) - - -pull_base_toolbox_image() -( - domain="" - has_domain=false - prompt_for_download=true - pull_image=false - - if image_reference_can_be_id "$base_toolbox_image"; then - echo "$base_toolbox_command: looking for image $base_toolbox_image" >&3 - - if podman image exists "$base_toolbox_image" >/dev/null 2>&3; then - return 0 - fi - fi - - image_reference_has_domain "$base_toolbox_image" && has_domain=true - - if ! $has_domain; then - echo "$base_toolbox_command: looking for image localhost/$base_toolbox_image" >&3 - - if podman image exists localhost/$base_toolbox_image >/dev/null 2>&3; then - return 0 - fi - fi - - if $has_domain; then - base_toolbox_image_full="$base_toolbox_image" - else - base_toolbox_image_full="$registry/$fgc/$base_toolbox_image" - fi - - echo "$base_toolbox_command: looking for image $base_toolbox_image_full" >&3 - - if podman image exists "$base_toolbox_image_full" >/dev/null 2>&3; then - return 0 - fi - - domain=$(image_reference_get_domain "$base_toolbox_image_full") - if $assume_yes || [ "$domain" = "localhost" ] 2>&3; then - prompt_for_download=false - pull_image=true - fi - - if $prompt_for_download; then - echo "Image required to create toolbox container." - - prompt=$(printf "Download %s (500MB)? [y/N]:" "$base_toolbox_image_full") - if ask_for_confirmation "n" "$prompt"; then - pull_image=true - else - pull_image=false - fi - fi - - if ! $pull_image; then - return 1 - fi - - echo "$base_toolbox_command: pulling image $base_toolbox_image_full" >&3 - - if spinner_directory=$(mktemp --directory --tmpdir $spinner_template 2>&3); then - spinner_message="Pulling $base_toolbox_image_full: " - if ! spinner_start "$spinner_directory" "$spinner_message"; then - spinner_directory="" - fi - else - echo "$base_toolbox_command: unable to start spinner: spinner directory not created" >&2 - spinner_directory="" - fi - - podman pull $base_toolbox_image_full >/dev/null 2>&3 - ret_val=$? - - if [ "$spinner_directory" != "" ]; then - spinner_stop "$spinner_directory" - fi - - if [ "$ret_val" -ne 0 ] 2>&3; then - echo "$base_toolbox_command: failed to pull base image $base_toolbox_image" >&2 - fi - - return $ret_val -) - - -unshare_userns_rm() -( - path="$1" - - if ! unshare_directory=$(mktemp --directory --tmpdir "toolbox-unshare-userns-rm-XXXXXXXXXX" 2>&3); then - echo "$base_toolbox_command: failed to enter user namespace: directory couldn't be created" >&2 - return 1 - fi - - if ! touch "$unshare_directory/map" 2>&3; then - echo "$base_toolbox_command: failed to enter user namespace: file couldn't be created" >&2 - return 1 - fi - - exec 4>"$unshare_directory/map" - if ! flock 4 2>&3; then - echo "$base_toolbox_command: failed to enter user namespace: lock couldn't be acquired" >&2 - return 1 - fi - - echo "$base_toolbox_command: parsing /etc/subgid" >&3 - - if ! subgid_entry=$(grep "^$USER:" /etc/subgid 2>&3); then - echo "$base_toolbox_command: failed to enter user namespace: no entry in /etc/subgid" >&2 - return 1 - fi - - userns_gid_start=$(echo "$subgid_entry" | cut --delimiter ":" --fields 2 2>&3) - if ! is_integer "$userns_gid_start"; then - echo "$base_toolbox_command: failed to enter user namespace: cannot parse the first sub-GID" >&2 - return 1 - fi - - userns_gid_len=$(echo "$subgid_entry" | cut --delimiter ":" --fields 3 2>&3) - if ! is_integer "$userns_gid_len"; then - echo "$base_toolbox_command: failed to enter user namespace: cannot parse the sub-GID count" >&2 - return 1 - fi - - echo "$base_toolbox_command: parsing /etc/subuid" >&3 - - if ! subuid_entry=$(grep "^$USER:" /etc/subuid 2>&3); then - echo "$base_toolbox_command: failed to enter user namespace: no entry in /etc/subuid" >&2 - return 1 - fi - - userns_uid_start=$(echo "$subuid_entry" | cut --delimiter ":" --fields 2 2>&3) - if ! is_integer "$userns_uid_start"; then - echo "$base_toolbox_command: failed to enter user namespace: cannot parse the first sub-UID" >&2 - return 1 - fi - - userns_uid_len=$(echo "$subuid_entry" | cut --delimiter ":" --fields 3 2>&3) - if ! is_integer "$userns_uid_len"; then - echo "$base_toolbox_command: failed to enter user namespace: cannot parse the sub-UID count" >&2 - return 1 - fi - - echo "$base_toolbox_command: unsharing user namespace" >&3 - - unshare --user sh -c "flock $unshare_directory/map rm --force --recursive $path" 2>&3 & - unshare_pid="$!" - - echo "$base_toolbox_command: setting GID and UID map of user namespace" >&3 - - if ! newgidmap "$unshare_pid" 0 "$user_id_real" 1 1 "$userns_gid_start" "$userns_gid_len" 2>&3; then - echo "$base_toolbox_command: failed to set GID mapping of user namespace" >&2 - kill -9 "$unshare_pid" 2>&3 - return 1 - fi - - if ! newuidmap "$unshare_pid" 0 "$user_id_real" 1 1 "$userns_uid_start" "$userns_uid_len" 2>&3; then - echo "$base_toolbox_command: failed to set UID mapping of user namespace" >&2 - kill -9 "$unshare_pid" 2>&3 - return 1 - fi - - echo "$base_toolbox_command: GID map of user namespace:" >&3 - cat /proc/"$unshare_pid"/gid_map 1>&3 2>&3 - - echo "$base_toolbox_command: UID map of user namespace:" >&3 - cat /proc/"$unshare_pid"/uid_map 1>&3 2>&3 - - if ! flock --unlock 4 2>&3; then - echo "$base_toolbox_command: failed to remove $path: lock couldn't be unlocked" >&2 - kill -9 "$unshare_pid" 2>&3 - return 1 - fi - - if ! wait "$unshare_pid" 2>&3; then - echo "$base_toolbox_command: failed to remove $path" >&2 - return 1 - fi - - rm --force --recursive "$unshare_directory" 2>&3 - - return 0 -) - - -create() -( - enter_command_skip="$1" - - dbus_system_bus_address="unix:path=/var/run/dbus/system_bus_socket" - home_link="" - flatpak_system_directory_bind="" - kcm_socket="" - kcm_socket_bind="" - libvirt_system_directory_bind="" - run_media_path_bind="" - toolbox_profile_bind="" - ulimit_host="" - usr_mount_destination_flags="ro" - - # shellcheck disable=SC2153 - if [ "$DBUS_SYSTEM_BUS_ADDRESS" != "" ]; then - dbus_system_bus_address=$DBUS_SYSTEM_BUS_ADDRESS - fi - dbus_system_bus_path=$(echo "$dbus_system_bus_address" | cut --delimiter = --fields 2 2>&3) - dbus_system_bus_path=$(readlink --canonicalize "$dbus_system_bus_path" 2>&3) - - if [ -d /var/lib/flatpak ] 2>&3; then - flatpak_system_directory_bind="--volume /var/lib/flatpak:/var/lib/flatpak:ro" - fi - - # Note that 'systemctl show ...' doesn't terminate with a non-zero exit - # code when used with an unknown unit. eg.: - # $ systemctl show --value --property Listen foo - # $ echo $? - # 0 - if ! kcm_socket_listen=$(systemctl show --value --property Listen sssd-kcm.socket 2>&3); then - echo "$base_toolbox_command: failed to use 'systemctl show'" >&3 - kcm_socket_listen="" - elif [ "$kcm_socket_listen" = "" ] 2>&3; then - echo "$base_toolbox_command: failed to read property Listen from sssd-kcm.socket" >&3 - else - echo "$base_toolbox_command: checking value $kcm_socket_listen of property Listen in sssd-kcm.socket" >&3 - - if ! (echo "$kcm_socket_listen" | grep " (Stream)$" >/dev/null 2>&3); then - echo "$base_toolbox_command: unknown socket in sssd-kcm.socket" >&2 - echo "$base_toolbox_command: expected SOCK_STREAM" >&2 - kcm_socket_listen="" - elif ! (echo "$kcm_socket_listen" | grep "^/" >/dev/null 2>&3); then - echo "$base_toolbox_command: unknown socket in sssd-kcm.socket" >&2 - echo "$base_toolbox_command: expected file system socket in the AF_UNIX family" >&2 - kcm_socket_listen="" - fi - fi - - echo "$base_toolbox_command: parsing value $kcm_socket_listen of property Listen in sssd-kcm.socket" >&3 - - if [ "$kcm_socket_listen" != "" ] 2>&3; then - kcm_socket=${kcm_socket_listen%" (Stream)"} - kcm_socket_bind="--volume $kcm_socket:$kcm_socket" - fi - - if [ -d /run/libvirt ] 2>&3; then - libvirt_system_directory_bind="--volume /run/libvirt:/run/libvirt" - fi - - echo "$base_toolbox_command: checking if 'podman create' supports --ulimit host" >&3 - - if man podman-create 2>&3 | grep "You can pass host" >/dev/null 2>&3; then - echo "$base_toolbox_command: 'podman create' supports --ulimit host" >&3 - - ulimit_host="--ulimit host" - fi - - if ! pull_base_toolbox_image; then - return 1 - fi - - if image_reference_has_domain "$base_toolbox_image"; then - base_toolbox_image_full="$base_toolbox_image" - else - if ! base_toolbox_image_full=$(podman inspect \ - --format "{{index .RepoTags 0}}" \ - --type image \ - "$base_toolbox_image" 2>&3); then - echo "$base_toolbox_command: failed to get RepoTag for base image $base_toolbox_image" >&2 - return 1 - fi - - echo "$base_toolbox_command: base image $base_toolbox_image resolved to $base_toolbox_image_full" >&3 - fi - - echo "$base_toolbox_command: checking if container $toolbox_container already exists" >&3 - - enter_command=$(create_enter_command "$toolbox_container") - if podman container exists $toolbox_container >/dev/null 2>&3; then - echo "$base_toolbox_command: container $toolbox_container already exists" >&2 - echo "Enter with: $enter_command" >&2 - echo "Try '$base_toolbox_command --help' for more information." >&2 - return 1 - fi - - if ! group_for_sudo=$(get_group_for_sudo); then - echo "$base_toolbox_command: failed to create container $toolbox_container: group for sudo not found" >&2 - return 1 - fi - - if [ -f /etc/profile.d/toolbox.sh ] 2>&3; then - toolbox_profile_bind="--volume /etc/profile.d/toolbox.sh:/etc/profile.d/toolbox.sh:ro" - fi - - if [ -d /run/media ] 2>&3; then - run_media_path_bind="--volume /run/media:/run/media:rslave" - fi - - echo "$base_toolbox_command: checking if /usr is mounted read-only or read-write" >&3 - - if ! usr_mount_point=$(df --output=target /usr | tail --lines 1 2>&3); then - echo "$base_toolbox_command: failed to get the mount-point of /usr" >&2 - else - echo "$base_toolbox_command: mount-point of /usr is $usr_mount_point" >&3 - - if ! usr_mount_source_flags=$(findmnt --noheadings --output OPTIONS "$usr_mount_point" 2>&3); then - echo "$base_toolbox_command: failed to get the mount options of $usr_mount_point" >&2 - else - echo "$base_toolbox_command: mount flags of /usr on the host are $usr_mount_source_flags" >&3 - - if echo "$usr_mount_source_flags" | grep --invert-match "ro" >/dev/null 2>&3; then - usr_mount_destination_flags="rw" - fi - fi - fi - - if ! home_canonical=$(readlink --canonicalize "$HOME" 2>&3); then - echo "$base_toolbox_command: failed to canonicalize $HOME" >&2 - return 1 - fi - - echo "$base_toolbox_command: $HOME canonicalized to $home_canonical" >&3 - - echo "$base_toolbox_command: checking if /home is a symbolic link to /var/home" >&3 - - if [ "$(readlink /home)" = var/home ] 2>&3; then - echo "$base_toolbox_command: /home is a symbolic link to /var/home" >&3 - home_link="--home-link" - fi - - echo "$base_toolbox_command: calling org.freedesktop.Flatpak.SessionHelper.RequestSession" >&3 - - if ! gdbus call \ - --session \ - --dest org.freedesktop.Flatpak \ - --object-path /org/freedesktop/Flatpak/SessionHelper \ - --method org.freedesktop.Flatpak.SessionHelper.RequestSession >/dev/null 2>&3; then - echo "$base_toolbox_command: failed to call org.freedesktop.Flatpak.SessionHelper.RequestSession" >&2 - exit 1 - fi - - echo "$base_toolbox_command: creating container $toolbox_container" >&3 - - if spinner_directory=$(mktemp --directory --tmpdir $spinner_template 2>&3); then - spinner_message="Creating container $toolbox_container: " - if ! spinner_start "$spinner_directory" "$spinner_message"; then - spinner_directory="" - fi - else - echo "$base_toolbox_command: unable to start spinner: spinner directory not created" >&2 - spinner_directory="" - fi - - # shellcheck disable=SC2086 - podman create \ - --dns none \ - --env TOOLBOX_PATH="$TOOLBOX_PATH" \ - --group-add "$group_for_sudo" \ - --hostname toolbox \ - --ipc host \ - --label "com.github.containers.toolbox=true" \ - --label "com.github.debarshiray.toolbox=true" \ - --name $toolbox_container \ - --network host \ - --no-hosts \ - --pid host \ - --privileged \ - --security-opt label=disable \ - $ulimit_host \ - --userns=keep-id \ - --user root:root \ - $flatpak_system_directory_bind \ - $kcm_socket_bind \ - $libvirt_system_directory_bind \ - $run_media_path_bind \ - $toolbox_profile_bind \ - --volume "$TOOLBOX_PATH":/usr/bin/toolbox:ro \ - --volume "$XDG_RUNTIME_DIR":"$XDG_RUNTIME_DIR" \ - --volume "$XDG_RUNTIME_DIR"/.flatpak-helper/monitor:/run/host/monitor \ - --volume "$dbus_system_bus_path":"$dbus_system_bus_path" \ - --volume "$home_canonical":"$home_canonical":rslave \ - --volume /etc:/run/host/etc \ - --volume /dev:/dev:rslave \ - --volume /media:/media:rslave \ - --volume /mnt:/mnt:rslave \ - --volume /run:/run/host/run:rslave \ - --volume /tmp:/run/host/tmp:rslave \ - --volume /usr:/run/host/usr:"$usr_mount_destination_flags",rslave \ - --volume /var:/run/host/var:rslave \ - "$base_toolbox_image_full" \ - toolbox --verbose init-container \ - --home "$HOME" \ - $home_link \ - --monitor-host \ - --shell "$SHELL" \ - --uid "$user_id_real" \ - --user "$USER" >/dev/null 2>&3 - ret_val=$? - - if [ "$spinner_directory" != "" ]; then - spinner_stop "$spinner_directory" - fi - - if [ $ret_val -ne 0 ]; then - echo "$base_toolbox_command: failed to create container $toolbox_container" >&2 - return 1 - fi - - if ! $enter_command_skip; then - echo "Created container: $toolbox_container" - echo "Enter with: $enter_command" - fi - - return 0 -) - - -enter() -( - emit_escape_sequence=false - host_id=$(get_host_id) - host_variant_id=$(get_host_variant_id) - - if [ "$host_id" = "fedora" ] 2>&3 \ - && { [ "$host_variant_id" = "silverblue" ] 2>&3 || [ "$host_variant_id" = "workstation" ] 2>&3; }; then - emit_escape_sequence=true - fi - - run "$emit_escape_sequence" true false "$SHELL" -l -) - - -init_container() -{ - init_container_home="$1" - init_container_home_link="$2" - init_container_monitor_host="$3" - init_container_shell="$4" - init_container_uid="$5" - init_container_user="$6" - - if [ "$XDG_RUNTIME_DIR" = "" ] 2>&3; then - echo "$base_toolbox_command: XDG_RUNTIME_DIR is unset" >&3 - - XDG_RUNTIME_DIR=/run/user/"$init_container_uid" - echo "$base_toolbox_command: XDG_RUNTIME_DIR set to $XDG_RUNTIME_DIR" >&3 - - toolbox_runtime_directory="$XDG_RUNTIME_DIR"/toolbox - fi - - init_container_initialized_stamp="$toolbox_runtime_directory"/container-initialized-"$$" - - echo "$base_toolbox_command: creating /run/.toolboxenv" >&3 - - if ! touch /run/.toolboxenv 2>&3; then - echo "$base_toolbox_command: failed to create /run/.toolboxenv" >&2 - return 1 - fi - - if $init_container_monitor_host; then - working_directory="$PWD" - - if [ -d /run/host/etc ] 2>&3; then - if ! readlink /etc/host.conf >/dev/null 2>&3; then - echo "$base_toolbox_command: redirecting /etc/host.conf to /run/host/etc/host.conf" >&3 - - if ! (cd /etc 2>&3 \ - && rm --force host.conf 2>&3 \ - && ln --symbolic /run/host/etc/host.conf host.conf 2>&3); then - echo "$base_toolbox_command: failed to redirect /etc/host.conf to /run/host/etc/host.conf" >&2 - return 1 - fi - fi - - if ! readlink /etc/hosts >/dev/null 2>&3; then - echo "$base_toolbox_command: redirecting /etc/hosts to /run/host/etc/hosts" >&3 - - if ! (cd /etc 2>&3 \ - && rm --force hosts 2>&3 \ - && ln --symbolic /run/host/etc/hosts hosts 2>&3); then - echo "$base_toolbox_command: failed to redirect /etc/hosts to /run/host/etc/hosts" >&2 - return 1 - fi - fi - - if ! readlink /etc/resolv.conf >/dev/null 2>&3; then - echo "$base_toolbox_command: redirecting /etc/resolv.conf to /run/host/etc/resolv.conf" >&3 - - if ! (cd /etc 2>&3 \ - && rm --force resolv.conf 2>&3 \ - && ln --symbolic /run/host/etc/resolv.conf resolv.conf 2>&3); then - echo "$base_toolbox_command: failed to redirect /etc/resolv.conf to /run/host/etc/resolv.conf" \ - >&2 - return 1 - fi - fi - fi - - if [ -d /run/host/monitor ] 2>&3; then - if ! localtime_target=$(readlink /etc/localtime >/dev/null 2>&3) \ - || [ "$localtime_target" != "/run/host/monitor/localtime" ] 2>&3; then - echo "$base_toolbox_command: redirecting /etc/localtime to /run/host/monitor/localtime" >&3 - - if ! (cd /etc 2>&3 \ - && rm --force localtime 2>&3 \ - && ln --symbolic /run/host/monitor/localtime localtime 2>&3); then - echo "$base_toolbox_command: failed to redirect /etc/localtime to /run/host/monitor/localtime" \ - >&2 - return 1 - fi - fi - - if ! readlink /etc/timezone >/dev/null 2>&3; then - echo "$base_toolbox_command: redirecting /etc/timezone to /run/host/monitor/timezone" >&3 - - if ! (cd /etc 2>&3 \ - && rm --force timezone 2>&3 \ - && ln --symbolic /run/host/monitor/timezone timezone 2>&3); then - echo "$base_toolbox_command: failed to redirect /etc/timezone to /run/host/monitor/timezone" >&2 - return 1 - fi - fi - fi - - if ! cd "$working_directory" 2>&3; then - echo "$base_toolbox_command: failed to restore working directory" >&2 - fi - fi - - if ! id -u "$init_container_user" >/dev/null 2>&3; then - if $init_container_home_link ; then - echo "$base_toolbox_command: making /home a symlink" >&3 - - # shellcheck disable=SC2174 - if ! (rmdir /home 2>&3 \ - && mkdir --mode 0755 --parents /var/home 2>&3 \ - && ln --symbolic var/home /home 2>&3); then - echo "$base_toolbox_command: failed to make /home a symlink" >&2 - return 1 - fi - fi - - if ! groups=$(get_group_for_sudo); then - echo "$base_toolbox_command: failed to add user $init_container_user: group for sudo not found" >&2 - return 1 - fi - - echo "$base_toolbox_command: adding user $init_container_user with UID $init_container_uid" >&3 - - if ! useradd \ - --home-dir "$init_container_home" \ - --no-create-home \ - --shell "$init_container_shell" \ - --uid "$init_container_uid" \ - --groups "$groups" \ - "$init_container_user" >/dev/null 2>&3; then - echo "$base_toolbox_command: failed to add user $init_container_user with UID $init_container_uid" >&2 - return 1 - fi - - echo "$base_toolbox_command: removing password for user $init_container_user" >&3 - - if ! passwd --delete "$init_container_user" >/dev/null 2>&3; then - echo "$base_toolbox_command: failed to remove password for user $init_container_user" >&2 - return 1 - fi - - echo "$base_toolbox_command: removing password for user root" >&3 - - if ! passwd --delete root >/dev/null 2>&3; then - echo "$base_toolbox_command: failed to remove password for user root" >&2 - return 1 - fi - - fi - - if [ -d /etc/krb5.conf.d ] 2>&3 && ! [ -f /etc/krb5.conf.d/kcm_default_ccache ] 2>&3; then - echo "$base_toolbox_command: setting KCM as the default Kerberos credential cache" >&3 - - cat <<EOF >/etc/krb5.conf.d/kcm_default_ccache 2>&3 -# Written by Toolbox -# https://github.com/debarshiray/toolbox -# -# # To disable the KCM credential cache, comment out the following lines. - -[libdefaults] - default_ccache_name = KCM: -EOF - ret_val=$? - - if [ "$ret_val" -ne 0 ] 2>&3; then - echo "$base_toolbox_command: failed to set KCM as the default Kerberos credential cache" >&2 - return 1 - fi - fi - - echo "$base_toolbox_command: finished initializing container" >&3 - - if ! touch "$init_container_initialized_stamp" 2>&3; then - echo "$base_toolbox_command: failed to create initialization stamp" >&2 - return 1 - fi - - echo "$base_toolbox_command: going to sleep" >&3 - - exec sleep +Inf -} - - -run() -( - emit_escape_sequence="$1" - fallback_to_bash="$2" - pedantic="$3" - program="$4" - shift 4 - - create_toolbox_container=false - prompt_for_create=true - - echo "$base_toolbox_command: checking if container $toolbox_container exists" >&3 - - if ! podman container exists "$toolbox_container" 2>&3; then - echo "$base_toolbox_command: container $toolbox_container not found" >&3 - - if podman container exists "$toolbox_container_old_v1" 2>&3; then - echo "$base_toolbox_command: container $toolbox_container_old_v1 found" >&3 - - # shellcheck disable=SC2030 - toolbox_container="$toolbox_container_old_v1" - elif podman container exists "$toolbox_container_old_v2" 2>&3; then - echo "$base_toolbox_command: container $toolbox_container_old_v2 found" >&3 - - # shellcheck disable=SC2030 - toolbox_container="$toolbox_container_old_v2" - else - if $pedantic; then - enter_print_container_not_found "$toolbox_container" - exit 1 - fi - - if ! containers=$(list_container_names); then - enter_print_container_not_found "$toolbox_container" - exit 1 - fi - - containers_count=$(echo "$containers" | grep --count . 2>&3) - if ! is_integer "$containers_count"; then - enter_print_container_not_found "$toolbox_container" - exit 1 - fi - - echo "$base_toolbox_command: found $containers_count containers" >&3 - - if [ "$containers_count" -eq 0 ] 2>&3; then - if $assume_yes; then - create_toolbox_container=true - prompt_for_create=false - fi - - if $prompt_for_create; then - prompt="No toolbox containers found. Create now? [y/N]" - if ask_for_confirmation "n" "$prompt"; then - create_toolbox_container=true - else - create_toolbox_container=false - fi - fi - - if ! $create_toolbox_container; then - echo "A container can be created later with the 'create' command." >&2 - echo "Try '$base_toolbox_command --help' for more information." >&2 - exit 1 - fi - - if ! update_container_and_image_names; then - exit 1 - fi - - if ! create true; then - exit 1 - fi - elif [ "$containers_count" -eq 1 ] 2>&3 \ - && [ "$toolbox_container" = "$toolbox_container_default" ] 2>&3; then - echo "$base_toolbox_command: container $toolbox_container not found" >&2 - - toolbox_container=$(echo "$containers" | grep . 2>&3 | head --lines 1 2>&3) - echo "Entering container $toolbox_container instead." >&2 - echo "Use the 'create' command to create a different toolbox." >&2 - echo "Try '$base_toolbox_command --help' for more information." >&2 - else - echo "$base_toolbox_command: container $toolbox_container not found" >&2 - echo "Use the '--container' option to select a toolbox." >&2 - echo "Try '$base_toolbox_command --help' for more information." >&2 - exit 1 - fi - fi - fi - - echo "$base_toolbox_command: calling org.freedesktop.Flatpak.SessionHelper.RequestSession" >&3 - - if ! gdbus call \ - --session \ - --dest org.freedesktop.Flatpak \ - --object-path /org/freedesktop/Flatpak/SessionHelper \ - --method org.freedesktop.Flatpak.SessionHelper.RequestSession >/dev/null 2>&3; then - echo "$base_toolbox_command: failed to call org.freedesktop.Flatpak.SessionHelper.RequestSession" >&2 - exit 1 - fi - - echo "$base_toolbox_command: starting container $toolbox_container" >&3 - - if is_etc_profile_d_toolbox_a_bind_mount "$toolbox_container"; then - echo "$base_toolbox_command: /etc/profile.d/toolbox.sh already mounted in container $toolbox_container" >&3 - - if ! container_start "$toolbox_container"; then - exit 1 - fi - else - echo "$base_toolbox_command: /etc/profile.d/toolbox.sh not mounted in container $toolbox_container" >&3 - - if ! copy_etc_profile_d_toolbox_to_runtime_directory; then - exit 1 - fi - - if ! container_start "$toolbox_container"; then - exit 1 - fi - - if ! copy_etc_profile_d_toolbox_to_container "$toolbox_container"; then - exit 1 - fi - fi - - echo "$base_toolbox_command: inspecting entry point of container $toolbox_container" >&3 - - if ! entry_point=$(podman inspect --format "{{index .Config.Cmd 0}}" --type container "$toolbox_container" 2>&3); then - echo "$base_toolbox_command: failed to inspect entry point of container $toolbox_container" >&2 - exit 1 - fi - - echo "$base_toolbox_command: entry point of container $toolbox_container is $entry_point" >&3 - - if [ "$entry_point" = "toolbox" ] 2>&3; then - echo "$base_toolbox_command: waiting for container $toolbox_container to finish initializing" >&3 - - if ! entry_point_pid=$(podman inspect --format "{{.State.Pid}}" --type container "$toolbox_container" 2>&3); then - echo "$base_toolbox_command: failed to inspect entry point PID of container $toolbox_container" >&2 - exit 1 - fi - - if ! is_integer "$entry_point_pid"; then - echo "$base_toolbox_command: failed to parse entry point PID of container $toolbox_container" >&2 - exit 1 - fi - - if [ "$entry_point_pid" -le 0 ] 2>&3; then - echo "$base_toolbox_command: invalid entry point PID of container $toolbox_container" >&2 - exit 1 - fi - - container_initialized_stamp="$toolbox_runtime_directory/container-initialized-$entry_point_pid" - container_initialized_timeout=25 #s - - i=0 - while ! [ -f "$container_initialized_stamp" ] 2>&3; do - sleep 1 2>&3 - - i=$((i + 1)) - if [ "$i" -eq "$container_initialized_timeout" ] 2>&3; then - echo "$base_toolbox_command: failed to initialize container $toolbox_container" >&2 - exit 1 - fi - done - fi - - if ! podman exec --user root:root "$toolbox_container" touch /run/.toolboxenv 2>&3; then - echo "$base_toolbox_command: failed to create /run/.toolboxenv in container $toolbox_container" >&2 - exit 1 - fi - - set_environment=$(create_environment_options) - - echo "$base_toolbox_command: looking for $program in container $toolbox_container" >&3 - - # shellcheck disable=SC2016 - if ! podman exec \ - --user "$USER" \ - "$toolbox_container" \ - sh -c 'command -v "$1"' sh "$program" >/dev/null 2>&3; then - if $fallback_to_bash; then - echo "$base_toolbox_command: $program not found in $toolbox_container; using /bin/bash instead" >&3 - program=/bin/bash - else - echo "$base_toolbox_command: command '$program' not found in container $toolbox_container" >&2 - exit 127 - fi - fi - - echo "$base_toolbox_command: running in container $toolbox_container:" >&3 - echo "$base_toolbox_command: $program" >&3 - for i in "$@"; do - echo "$base_toolbox_command: $i" >&3 - done - - $emit_escape_sequence && printf "\033]777;container;push;%s;toolbox\033\\" "$toolbox_container" - - # shellcheck disable=SC2016 - # for the command passed to capsh - # shellcheck disable=SC2086 - podman exec \ - --interactive \ - --tty \ - --user "$USER" \ - --workdir "$PWD" \ - $set_environment \ - "$toolbox_container" \ - capsh --caps="" -- -c 'exec "$@"' /bin/sh "$program" "$@" 2>&3 - ret_val="$?" - - $emit_escape_sequence && printf "\033]777;container;pop;;\033\\" - - exit "$ret_val" -) - - -help() -( - to_help_command="$1" - - if [ "$to_help_command" = "" ] 2>&3 || [ "$to_help_command" = "$base_toolbox_command" ] 2>&3; then - exec man toolbox 2>&1 - fi - - exec man toolbox-"$to_help_command" 2>&1 -) - - -list_images() -( - output="" - - if ! images_old=$(podman images \ - --filter "label=com.redhat.component=fedora-toolbox" \ - --format "{{.Repository}}:{{.Tag}}" 2>&3); then - echo "$base_toolbox_command: failed to list images with com.redhat.component=fedora-toolbox" >&2 - return 1 - fi - - if ! images=$(podman images \ - --filter "label=com.github.debarshiray.toolbox=true" \ - --format "{{.Repository}}:{{.Tag}}" 2>&3); then - echo "$base_toolbox_command: failed to list images with com.github.debarshiray.toolbox=true" >&2 - return 1 - fi - - images=$(printf "%s\n%s\n" "$images_old" "$images" | sort 2>&3 | uniq 2>&3) - if ! details=$(images_get_details "$images"); then - return 1 - fi - - if [ "$details" != "" ] 2>&3; then - table_data=$(printf "%s\t%s\t%s\n" "IMAGE ID" "IMAGE NAME" "CREATED"; echo "$details") - if ! output=$(echo "$table_data" | sed "s/ \{2,\}/\t/g" 2>&3 | column -s "$tab" -t 2>&3); then - echo "$base_toolbox_command: failed to parse list of images" >&2 - return 1 - fi - fi - - if [ "$output" != "" ]; then - echo "$output" - fi - - return 0 -) - - -containers_get_details() -( - containers="$1" - - if ! echo "$containers" | while read -r container; do - [ "$container" = "" ] 2>&3 && continue - - if ! podman ps --all \ - --filter "name=$container" \ - --format "{{.ID}} {{.Names}} {{.Created}} {{.Status}} {{.Image}}" 2>&3; then - echo "$base_toolbox_command: failed to get details for container $container" >&2 - return 1 - fi - done; then - return 1 - fi - - return 0 -) - - -list_containers() -( - output="" - - if ! containers=$(list_container_names); then - return 1 - fi - - if ! details=$(containers_get_details "$containers"); then - return 1 - fi - - if [ "$details" != "" ] 2>&3; then - table_data=$(printf "%s\t%s\t%s\t%s\t%s\n" "CONTAINER ID" "CONTAINER NAME" "CREATED" "STATUS" "IMAGE NAME" - echo "$details") - if ! output=$(echo "$table_data" | sed "s/ \{2,\}/\t/g" 2>&3 | column -s "$tab" -t 2>&3); then - echo "$base_toolbox_command: failed to parse list of containers" >&2 - return 1 - fi - fi - - if [ "$output" != "" ]; then - echo "$output" | head --lines 1 2>&3 - - echo "$output" | tail --lines +2 2>&3 \ - | ( - while read -r container; do - id=$(echo "$container" | cut --delimiter " " --fields 1 2>&3) - is_running=$(podman inspect "$id" --format "{{.State.Running}}" 2>&3) - if $is_running; then - # shellcheck disable=SC2059 - printf "${LGC}$container${NC}\n" - else - echo "$container" - fi - done - ) - fi - - return 0 -) - - -migrate() -( - configuration_directory="$HOME/.config/toolbox" - migrate_stamp="$configuration_directory/podman-system-migrate" - - migrate_lock="$toolbox_runtime_directory"/migrate.lock - - if ! version=$(podman version --format "{{.Version}}" 2>&3); then - echo "$base_toolbox_command: unable to migrate containers: Podman version couldn't be read" >&2 - return 1 - fi - - echo "$base_toolbox_command: current Podman version is $version" >&3 - - if ! mkdir --parents "$configuration_directory" 2>&3; then - echo "$base_toolbox_command: unable to migrate containers: configuration directory not created" >&2 - return 1 - fi - - # shellcheck disable=SC2174 - if ! mkdir --mode 700 --parents "$toolbox_runtime_directory" 2>&3; then - echo "$base_toolbox_command: unable to migrate containers: runtime directory not created" >&2 - return 1 - fi - - exec 5>"$migrate_lock" - if ! flock 5 2>&3; then - echo "$base_toolbox_command: unable to migrate containers: migration lock not acquired" >&3 - return 1 - fi - - if [ -f "$migrate_stamp" ] 2>&3; then - if grep "$version" "$migrate_stamp" >/dev/null 2>&3; then - echo "$base_toolbox_command: migration not needed: Podman version $version is unchanged" >&3 - return 0 - fi - - if ! version_old=$(printf "%s\n" "$version" \ - | cat "$migrate_stamp" - 2>&3 \ - | sort --version-sort 2>&3 \ - | head --lines 1 2>&3); then - echo "$base_toolbox_command: unable to migrate containers: Podman versions couldn't be sorted" >&2 - return 1 - fi - - if [ "$version" = "$version_old" ] 2>&3; then - echo "$base_toolbox_command: migration not needed: Podman version $version is old" >&3 - return 0 - fi - fi - - if ! podman system migrate >/dev/null 2>&3; then - echo "$base_toolbox_command: unable to migrate containers" >&2 - return 1 - fi - - echo "$version" >"$migrate_stamp" - return 0 -) - - -remove_containers() -( - ids=$1 - all=$2 - force=$3 - - ret_val=0 - - $force && force_option="--force" - - if $all; then - if ! ids_old=$(podman ps \ - --all \ - --filter "label=com.redhat.component=fedora-toolbox" \ - --format "{{.ID}}" 2>&3); then - echo "$base_toolbox_command: failed to list containers with com.redhat.component=fedora-toolbox" >&2 - return 1 - fi - - if ! ids=$(podman ps \ - --all \ - --filter "label=com.github.debarshiray.toolbox=true" \ - --format "{{.ID}}" 2>&3); then - echo "$base_toolbox_command: failed to list containers with com.github.debarshiray.toolbox=true" >&2 - return 1 - fi - - ids=$(printf "%s\n%s\n" "$ids_old" "$ids" | sort 2>&3 | uniq 2>&3) - if [ "$ids" != "" ]; then - ret_val=$(echo "$ids" \ - | ( - while read -r id; do - if ! podman rm $force_option "$id" >/dev/null 2>&3; then - echo "$base_toolbox_command: failed to remove container $id" >&2 - ret_val=1 - fi - done - - echo "$ret_val" - ) - ) - fi - else - ret_val=$(echo "$ids" \ - | sed "s/ \+/\n/g" 2>&3 \ - | ( - while read -r id; do - if ! labels=$(podman inspect \ - --format "{{.Config.Labels}}" \ - --type container \ - "$id" 2>&3); then - echo "$base_toolbox_command: failed to inspect $id" >&2 - ret_val=1 - continue - fi - - if ! has_substring "$labels" "com.github.debarshiray.toolbox" \ - && ! has_substring "$labels" "com.redhat.component:fedora-toolbox"; then - echo "$base_toolbox_command: $id is not a toolbox container" >&2 - ret_val=1 - continue - fi - - if ! podman rm $force_option "$id" >/dev/null 2>&3; then - echo "$base_toolbox_command: failed to remove container $id" >&2 - ret_val=1 - fi - done - - echo "$ret_val" - ) - ) - fi - - return "$ret_val" -) - - -remove_images() -( - ids=$1 - all=$2 - force=$3 - - ret_val=0 - - $force && force_option="--force" - - if $all; then - if ! ids_old=$(podman images \ - --filter "label=com.redhat.component=fedora-toolbox" \ - --format "{{.ID}}" 2>&3); then - echo "$0: failed to list images with com.redhat.component=fedora-toolbox" >&2 - return 1 - fi - - if ! ids=$(podman images \ - --all \ - --filter "label=com.github.debarshiray.toolbox=true" \ - --format "{{.ID}}" 2>&3); then - echo "$0: failed to list images with com.github.debarshiray.toolbox=true" >&2 - return 1 - fi - - ids=$(printf "%s\n%s\n" "$ids_old" "$ids" | sort 2>&3 | uniq 2>&3) - if [ "$ids" != "" ]; then - ret_val=$(echo "$ids" \ - | ( - while read -r id; do - if ! podman rmi $force_option "$id" >/dev/null 2>&3; then - echo "$base_toolbox_command: failed to remove image $id" >&2 - ret_val=1 - fi - done - - echo "$ret_val" - ) - ) - fi - else - ret_val=$(echo "$ids" \ - | sed "s/ \+/\n/g" 2>&3 \ - | ( - while read -r id; do - if ! labels=$(podman inspect \ - --format "{{.Labels}}" \ - --type image \ - "$id" 2>&3); then - echo "$base_toolbox_command: failed to inspect $id" >&2 - ret_val=1 - continue - fi - - if ! has_substring "$labels" "com.github.debarshiray.toolbox" \ - && ! has_substring "$labels" "com.redhat.component:fedora-toolbox"; then - echo "$base_toolbox_command: $id is not a toolbox image" >&2 - ret_val=1 - continue - fi - - if ! podman rmi $force_option "$id" >/dev/null 2>&3; then - echo "$base_toolbox_command: failed to remove image $id" >&2 - ret_val=1 - fi - done - - echo "$ret_val" - ) - ) - fi - - return "$ret_val" -) - - -reset() -( - do_reset=false - prompt_for_reset=true - ret_val=0 - - if [ "$user_id_real" -eq 0 ] 2>&3; then - if [ -d /run/containers ] 2>&3; then - echo "$base_toolbox_command: The 'reset' command cannot be used after other commands" >&2 - echo "Reboot the system before using it again." >&2 - echo "Try '$base_toolbox_command --help' for more information." >&2 - return 1 - fi - else - if [ -d "$XDG_RUNTIME_DIR"/overlay-containers ] 2>&3 \ - || [ -d "$XDG_RUNTIME_DIR"/overlay-layers ] 2>&3 \ - || [ -d "$XDG_RUNTIME_DIR"/overlay-locks ] 2>&3; then - echo "$base_toolbox_command: The 'reset' command cannot be used after other commands" >&2 - echo "Reboot the system before using it again." >&2 - echo "Try '$base_toolbox_command --help' for more information." >&2 - return 1 - fi - fi - - if $assume_yes; then - do_reset=true - prompt_for_reset=false - fi - - if $prompt_for_reset; then - echo "All existing podman (and toolbox) containers and images will be removed." - - prompt=$(printf "Continue? [y/N]:") - if ask_for_confirmation "n" "$prompt"; then - do_reset=true - else - do_reset=false - fi - fi - - if ! $do_reset; then - return 1 - fi - - echo "$base_toolbox_command: resetting local state" >&3 - - if [ "$user_id_real" -eq 0 ] 2>&3; then - if ! rm --force --recursive /var/lib/containers/cache >/dev/null 2>&3; then - echo "$base_toolbox_command: failed to remove /var/lib/containers/cache" >&2 - ret_val=1 - fi - - if ! rm --force --recursive /var/lib/containers/sigstore/* >/dev/null 2>&3; then - echo "$base_toolbox_command: failed to remove the contents of /var/lib/containers/sigstore" >&2 - ret_val=1 - fi - - if ! rm --force --recursive /var/lib/containers/storage >/dev/null 2>&3; then - echo "$base_toolbox_command: failed to remove /var/lib/containers/storage" >&2 - ret_val=1 - fi - else - if ! unshare_userns_rm "$HOME/.local/share/containers"; then - ret_val=1 - fi - - if ! rm --force --recursive "$HOME/.config/containers" >/dev/null 2>&3; then - echo "$base_toolbox_command: failed to remove $HOME/.config/containers" >&2 - ret_val=1 - fi - fi - - if ! rm --force --recursive "$HOME/.config/toolbox" >/dev/null 2>&3; then - echo "$base_toolbox_command: failed to remove $HOME/.config/toolbox" >&2 - ret_val=1 - fi - - return "$ret_val" -) - - -exit_if_extra_operand() -{ - if [ "$1" != "" ]; then - echo "$base_toolbox_command: extra operand '$1'" >&2 - echo "Try '$base_toolbox_command --help' for more information." >&2 - exit 1 - fi -} - - -exit_if_missing_argument() -{ - if [ "$2" = "" ]; then - echo "$base_toolbox_command: missing argument for '$1'" >&2 - echo "Try '$base_toolbox_command --help' for more information." >&2 - exit 1 - fi -} - - -exit_if_non_positive_argument() -{ - if ! is_integer "$2"; then - echo "$base_toolbox_command: invalid argument for '$1'" >&2 - echo "Try '$base_toolbox_command --help' for more information." >&2 - exit 1 - fi - if [ "$2" -le 0 ] 2>&3; then - echo "$base_toolbox_command: invalid argument for '$1'" >&2 - echo "Try '$base_toolbox_command --help' for more information." >&2 - exit 1 - fi -} - - -exit_if_unrecognized_option() -{ - echo "$base_toolbox_command: unrecognized option '$1'" >&2 - echo "Try '$base_toolbox_command --help' for more information." >&2 - exit 1 -} - - -# shellcheck disable=SC2120 -forward_to_host() -( - if ! command -v flatpak-spawn >/dev/null 2>&3; then - echo "$base_toolbox_command: flatpak-spawn not found" >&2 - return 1 - fi - - eval "set -- $arguments" - - set_environment=$(create_environment_options) - - echo "$base_toolbox_command: forwarding to host:" >&3 - echo "$base_toolbox_command: $TOOLBOX_PATH" >&3 - for i in "$@"; do - echo "$base_toolbox_command: $i" >&3 - done - - # shellcheck disable=SC2086 - flatpak-spawn $set_environment --host "$TOOLBOX_PATH" "$@" 2>&3 - ret_val="$?" - - return "$ret_val" -) - - -update_container_and_image_names() -{ - [ "$release" = "" ] 2>&3 && release="$release_default" - - if [ "$base_toolbox_image" = "" ] 2>&3; then - base_toolbox_image="fedora-toolbox:$release" - else - release=$(image_reference_get_tag "$base_toolbox_image") - [ "$release" = "" ] 2>&3 && release="$release_default" - fi - - fgc="f$release" - echo "$base_toolbox_command: Fedora generational core is $fgc" >&3 - - echo "$base_toolbox_command: base image is $base_toolbox_image" >&3 - - toolbox_image=$(create_toolbox_image_name) - if ! ( - ret_val=$? - if [ "$ret_val" -ne 0 ] 2>&3; then - if [ "$ret_val" -eq 100 ] 2>&3; then - echo "$base_toolbox_command: failed to get the basename of base image $base_toolbox_image" >&2 - else - echo "$base_toolbox_command: failed to create an ID for the customized user-specific image" >&2 - fi - - exit 1 - fi - - exit 0 - ); then - return 1 - fi - - # shellcheck disable=SC2031 - if [ "$toolbox_container" = "" ]; then - toolbox_container=$(create_toolbox_container_name "$base_toolbox_image") - if ! ( - ret_val=$? - if [ "$ret_val" -ne 0 ] 2>&3; then - if [ "$ret_val" -eq 100 ] 2>&3; then - echo "$base_toolbox_command: failed to get the basename of image $base_toolbox_image" >&2 - elif [ "$ret_val" -eq 101 ] 2>&3; then - echo "$base_toolbox_command: failed to get the tag of image $base_toolbox_image" >&2 - else - echo "$base_toolbox_command: failed to create a name for the toolbox container" >&2 - fi - - exit 1 - fi - - exit 0 - ); then - return 1 - fi - - if ! container_name_is_valid "$toolbox_container"; then - echo "$base_toolbox_command: generated container name $toolbox_container is invalid" >&2 - echo "Container names must match '$container_name_regexp'." >&2 - echo "Try '$base_toolbox_command --help' for more information." >&2 - return 1 - fi - - toolbox_container_old_v1=$(create_toolbox_container_name "$toolbox_image") - if ! ( - ret_val=$? - if [ "$ret_val" -ne 0 ] 2>&3; then - if [ "$ret_val" -eq 100 ] 2>&3; then - echo "$base_toolbox_command: failed to get the basename of image $toolbox_image" >&2 - elif [ "$ret_val" -eq 101 ] 2>&3; then - echo "$base_toolbox_command: failed to get the tag of image $toolbox_image" >&2 - else - echo "$base_toolbox_command: failed to create a name for the toolbox container" >&2 - fi - - exit 1 - fi - - exit 0 - ); then - return 1 - fi - - toolbox_container_old_v2="$toolbox_image" - fi - - echo "$base_toolbox_command: container is $toolbox_container" >&3 - return 0 -} - - -arguments=$(save_positional_parameters "$@") - -host_id=$(get_host_id) -if [ "$host_id" = "fedora" ] 2>&3; then - release_default=$(get_host_version_id) -else - release_default="30" -fi -toolbox_container_prefix_default="fedora-toolbox" -toolbox_container_default="$toolbox_container_prefix_default-$release_default" - -while has_prefix "$1" -; do - case $1 in - --assumeyes | -y ) - assume_yes=true - ;; - -h | --help ) - if [ -f /run/.containerenv ] 2>&3; then - if ! [ -f /run/.toolboxenv ] 2>&3; then - echo "$base_toolbox_command: this is not a toolbox container" >&2 - exit 1 - fi - - # shellcheck disable=SC2119 - forward_to_host - exit - fi - - help "$2" - exit - ;; - -v | --verbose ) - exec 3>&2 - verbose=true - ;; - * ) - exit_if_unrecognized_option "$1" - esac - shift -done - -echo "$base_toolbox_command: running as real user ID $user_id_real" >&3 - -if ! toolbox_command_path=$(realpath "$0" 2>&3); then - echo "$base_toolbox_command: failed to resolve absolute path to $0" >&2 - exit 1 -fi - -echo "$base_toolbox_command: resolved absolute path for $0 to $toolbox_command_path" >&3 - -if [ -f /run/.containerenv ] 2>&3; then - if [ "$TOOLBOX_PATH" = "" ] 2>&3; then - echo "$base_toolbox_command: TOOLBOX_PATH not set" >&2 - exit 1 - fi -else - if [ "$user_id_real" -ne 0 ] 2>&3; then - echo "$base_toolbox_command: checking if /etc/subgid and /etc/subuid have entries for user $USER" >&3 - - if ! grep "^$USER:" /etc/subgid >/dev/null 2>&3 || ! grep "^$USER:" /etc/subuid >/dev/null 2>&3; then - echo "$base_toolbox_command: /etc/subgid and /etc/subuid don't have entries for user $USER" >&2 - echo "See the podman(1), subgid(5), subuid(5) and usermod(8) manuals for more" >&2 - echo "information." >&2 - exit 1 - fi - fi - - if [ "$TOOLBOX_PATH" = "" ] 2>&3; then - TOOLBOX_PATH="$toolbox_command_path" - fi -fi - -echo "$base_toolbox_command: TOOLBOX_PATH is $TOOLBOX_PATH" >&3 - -if [ "$1" = "" ]; then - echo "$base_toolbox_command: missing command" >&2 - echo >&2 - echo "These are some common commands:" >&2 - echo "create Create a new toolbox container" >&2 - echo "enter Enter an existing toolbox container" >&2 - echo "list List all existing toolbox containers and images" >&2 - echo >&2 - echo "Try '$base_toolbox_command --help' for more information." >&2 - exit 1 -fi - -op=$1 -shift - -if [ -f /run/.containerenv ] 2>&3; then - case $op in - create | enter | list | rm | rmi | run | help ) - if ! [ -f /run/.toolboxenv ] 2>&3; then - echo "$base_toolbox_command: this is not a toolbox container" >&2 - exit 1 - fi - - # shellcheck disable=SC2119 - forward_to_host - exit "$?" - ;; - init-container ) - init_container_home_link=false - init_container_monitor_host=false - while has_prefix "$1" -; do - case $1 in - -h | --help ) - # shellcheck disable=SC2119 - forward_to_host - exit - ;; - --home ) - shift - exit_if_missing_argument --home "$1" - init_container_home="$1" - ;; - --home-link ) - init_container_home_link=true - ;; - --monitor-host ) - init_container_monitor_host=true - ;; - --shell ) - shift - exit_if_missing_argument --shell "$1" - init_container_shell="$1" - ;; - --uid ) - shift - exit_if_missing_argument --uid "$1" - init_container_uid="$1" - ;; - --user ) - shift - exit_if_missing_argument --user "$1" - init_container_user="$1" - ;; - * ) - exit_if_unrecognized_option "$1" - esac - shift - done - init_container \ - "$init_container_home" \ - "$init_container_home_link" \ - "$init_container_monitor_host" \ - "$init_container_shell" \ - "$init_container_uid" \ - "$init_container_user" - exit "$?" - ;; - reset ) - echo "$base_toolbox_command: The 'reset' command cannot be used inside containers" >&2 - echo "Try '$base_toolbox_command --help' for more information." >&2 - exit 1 - ;; - * ) - echo "$base_toolbox_command: unrecognized command '$op'" >&2 - echo "Try '$base_toolbox_command --help' for more information." >&2 - exit 1 - ;; - esac -fi - -if ! cgroups_version=$(get_cgroups_version); then - exit 1 -fi - -echo "$base_toolbox_command: running on a cgroups v$cgroups_version host" >&3 - -if [ "$op" != "reset" ] 2>&3; then - if ! migrate; then - exit 1 - fi -fi - -case $op in - create ) - while has_prefix "$1" -; do - case $1 in - --candidate-registry ) - registry=$registry_candidate - ;; - -c | --container ) - shift - exit_if_missing_argument --container "$1" - arg=$1 - if ! container_name_is_valid "$arg"; then - echo "$base_toolbox_command: invalid argument for '--container'" >&2 - echo "Container names must match '$container_name_regexp'." >&2 - echo "Try '$base_toolbox_command --help' for more information." >&2 - exit 1 - fi - toolbox_container="$arg" - ;; - -h | --help ) - help "$op" - exit - ;; - -i | --image ) - shift - exit_if_missing_argument --image "$1" - base_toolbox_image=$1 - ;; - -r | --release ) - shift - exit_if_missing_argument --release "$1" - arg=$(echo "$1" | sed "s/^F\|^f//" 2>&3) - exit_if_non_positive_argument --release "$arg" - release=$arg - ;; - * ) - exit_if_unrecognized_option "$1" - esac - shift - done - exit_if_extra_operand "$1" - if ! update_container_and_image_names; then - exit 1 - fi - if ! create false; then - exit 1 - fi - exit - ;; - enter ) - while has_prefix "$1" -; do - case $1 in - -c | --container ) - shift - exit_if_missing_argument --container "$1" - toolbox_container=$1 - ;; - -h | --help ) - help "$op" - exit - ;; - -r | --release ) - shift - exit_if_missing_argument --release "$1" - arg=$(echo "$1" | sed "s/^F\|^f//" 2>&3) - exit_if_non_positive_argument --release "$arg" - release=$arg - ;; - * ) - exit_if_unrecognized_option "$1" - esac - shift - done - exit_if_extra_operand "$1" - if ! update_container_and_image_names; then - exit 1 - fi - enter - exit - ;; - help ) - while has_prefix "$1" -; do - case $1 in - -h | --help ) - help "$op" - exit - ;; - * ) - exit_if_unrecognized_option "$1" - esac - shift - done - help "$1" - exit - ;; - init-container ) - while has_prefix "$1" -; do - case $1 in - -h | --help ) - help "$op" - exit - esac - shift - done - echo "$base_toolbox_command: The 'init-container' command can only be used inside containers" >&2 - echo "Try '$base_toolbox_command --help' for more information." >&2 - exit 1 - ;; - list ) - ls_add_empty_line=false - ls_images=false - ls_containers=false - while has_prefix "$1" -; do - case $1 in - -c | --containers ) - ls_containers=true - ;; - -h | --help ) - help "$op" - exit - ;; - -i | --images ) - ls_images=true - ;; - * ) - exit_if_unrecognized_option "$1" - esac - shift - done - exit_if_extra_operand "$1" - - if ! $ls_containers && ! $ls_images; then - ls_containers=true - ls_images=true - fi - - if $ls_images; then - if ! images=$(list_images); then - exit 1 - fi - fi - - if $ls_containers; then - if ! containers=$(list_containers); then - exit 1 - fi - fi - - if $ls_images && [ "$images" != "" ] 2>&3; then - echo "$images" - ls_add_empty_line=true - fi - - if $ls_containers && [ "$containers" != "" ] 2>&3; then - $ls_add_empty_line && echo "" - echo "$containers" - fi - - exit - ;; - reset ) - while has_prefix "$1" -; do - case $1 in - -h | --help ) - help "$op" - exit - ;; - * ) - exit_if_unrecognized_option "$1" - esac - shift - done - exit_if_extra_operand "$1" - - reset - exit "$?" - ;; - rm | rmi ) - rm_all=false - rm_force=false - while has_prefix "$1" -; do - case $1 in - -a | --all ) - rm_all=true - ;; - -f | --force ) - rm_force=true - ;; - -h | --help ) - help "$op" - exit - ;; - * ) - exit_if_unrecognized_option "$1" - esac - shift - done - - rm_ids="" - if $rm_all; then - exit_if_extra_operand "$1" - else - exit_if_missing_argument "$op" "$1" - while [ "$1" != "" ]; do - rm_ids="$rm_ids $1" - shift - done - fi - - rm_ids=$(echo "$rm_ids" | sed "s/^ \+//" 2>&3) - - if [ "$op" = "rm" ]; then - remove_containers "$rm_ids" "$rm_all" "$rm_force" - else - remove_images "$rm_ids" "$rm_all" "$rm_force" - fi - exit - ;; - run ) - while has_prefix "$1" -; do - case $1 in - -c | --container ) - shift - exit_if_missing_argument --container "$1" - toolbox_container=$1 - ;; - -h | --help ) - help "$op" - exit - ;; - -r | --release ) - shift - exit_if_missing_argument --release "$1" - arg=$(echo "$1" | sed "s/^F\|^f//" 2>&3) - exit_if_non_positive_argument --release "$arg" - release=$arg - ;; - * ) - exit_if_unrecognized_option "$1" - esac - shift - done - if ! update_container_and_image_names; then - exit 1 - fi - run false false true "$@" - exit - ;; - * ) - echo "$base_toolbox_command: unrecognized command '$op'" >&2 - echo "Try '$base_toolbox_command --help' for more information." >&2 - exit 1 -esac diff --git a/Makefile b/Makefile index 4a0f6065a0a356134cae239fd447bf3329b56c37..2415541e5e36afa524f9c6307b8a89cd795b48b1 100644 --- a/Makefile +++ b/Makefile @@ -165,11 +165,6 @@ Documents/bin/rabbitmqadmin: .bash_completion.d/toolbox: $(download) https://raw.githubusercontent.com/containers/toolbox/0.0.16/completion/bash/toolbox -Documents/bin/toolbox: - mkdir -p $$(dirname $@) - $(download) https://raw.githubusercontent.com/containers/toolbox/0.0.16/toolbox - chmod +x $@ - ## Generated files