From 0db54946b43e04023134f6381b97b768894bfef0 Mon Sep 17 00:00:00 2001 From: Debarshi Ray Date: Thu, 20 Jun 2019 18:01:52 +0200 Subject: [PATCH] Don't use 'podman cp' to copy toolbox.sh to old containers Copying files into a running container is considered inherently hacky. Rootful Podman can pause a container using 'podman cp --pause ...' during the copy, but that's not possible when used rootless. Secondly 'podman cp' has suffered from a series of regressions lately. First there was the problem with how the --pause flag was handled [1], and then /etc/profile.d/toolbox.sh was getting created as a directory [2], not regular file, by: $ podman cp \ --pause=false \ /etc/profile.d/toolbox.sh \ "$container":/etc/profile.d Try to side-step all that by using $XDG_RUNTIME_DIR as a conduit to share the file with the container and using plain cp(1) to place it in the toolbox container's /etc/profile.d. [1] Commit e715ff2f9b231271 https://github.com/debarshiray/toolbox/pull/193 [2] https://github.com/containers/libpod/issues/3384 https://github.com/debarshiray/toolbox/issues/196 --- toolbox | 104 +++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 65 insertions(+), 39 deletions(-) diff --git a/toolbox b/toolbox index 232b6f7..6932af5 100755 --- a/toolbox +++ b/toolbox @@ -248,7 +248,36 @@ copy_etc_profile_d_toolbox_to_container() ( container="$1" - pause_false="" + 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 /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 container $container" >&3 + + if ! $prefix_sudo 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 /etc/profile.d/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 @@ -267,39 +296,10 @@ copy_etc_profile_d_toolbox_to_container() return 1 fi - echo "$base_toolbox_command: looking for /etc/profile.d/toolbox.sh in container $container" >&3 + echo "$base_toolbox_command: copying /etc/profile.d/toolbox.sh to $toolbox_runtime_directory" >&3 - if $prefix_sudo podman exec \ - --user "$USER" \ - "$container" \ - sh -c 'mount | grep /etc/profile.d/toolbox.sh >/dev/null 2>/dev/null' 2>&3; then - echo "$base_toolbox_command: /etc/profile.d/toolbox.sh already mounted in container $container" >&3 - return 0 - fi - - echo "$base_toolbox_command: checking if 'podman cp' supports --pause" >&3 - - if $prefix_sudo podman cp --help 2>&3 | grep "pause" >/dev/null 2>&3; then - echo "$base_toolbox_command: 'podman cp' supports --pause" >&3 - pause_false="--pause=false" - fi - - echo "$base_toolbox_command: copying /etc/profile.d/toolbox.sh to container $container" >&3 - - # shellcheck disable=SC2086 - if ! $prefix_sudo podman cp \ - $pause_false \ - /etc/profile.d/toolbox.sh \ - "$container":/etc/profile.d 2>&3; then - echo "$base_toolbox_command: unable to copy /etc/profile.d/toolbox.sh to container $container" >&2 - return 1 - fi - - if ! $prefix_sudo podman exec \ - --user root:root \ - "$container" \ - chown root:root /etc/profile.d/toolbox.sh 2>&3; then - echo "$base_toolbox_command: unable to chown /etc/profile.d/toolbox.sh in container $container" >&2 + 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 @@ -530,6 +530,17 @@ images_get_details() ) +is_etc_profile_d_toolbox_a_bind_mount() +{ + container="$1" + + $prefix_sudo 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=$($prefix_sudo podman ps \ @@ -1070,13 +1081,28 @@ run() echo "$base_toolbox_command: trying to start container $toolbox_container" >&3 - if ! $prefix_sudo podman start "$toolbox_container" >/dev/null 2>&3; then - echo "$base_toolbox_command: failed to start container $toolbox_container" >&2 - exit 1 - fi + 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 ! copy_etc_profile_d_toolbox_to_container "$toolbox_container"; then - exit 1 + if ! $prefix_sudo podman start "$toolbox_container" >/dev/null 2>&3; then + echo "$base_toolbox_command: failed to start container $toolbox_container" >&2 + 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 ! $prefix_sudo podman start "$toolbox_container" >/dev/null 2>&3; then + echo "$base_toolbox_command: failed to start container $toolbox_container" >&2 + exit 1 + fi + + if ! copy_etc_profile_d_toolbox_to_container "$toolbox_container"; then + exit 1 + fi fi if ! $prefix_sudo podman exec --user root:root "$toolbox_container" touch /run/.toolboxenv 2>&3; then