From 7cad7edc1e79c4827e4bc00cb1700ac48e7971ad Mon Sep 17 00:00:00 2001 From: Dalibor Kricka Date: Wed, 22 Apr 2026 16:58:12 +0200 Subject: [PATCH 1/3] pkg/shell: Preserve error types in shell command execution The existing RunContextWithExitCode() wraps all errors from exec.Command in generic "failed to invoke" messages, which prevents callers from distinguishing between actual error types. Add RunContextWithExitCode2() and RunWithExitCode2() that return errors with their original types intact, including for ExitError. This allows callers to use errors.Is() and errors.As() to handle specific failure modes. For example, detecting a missing skopeo binary (exec.ErrNotFound) or an ENOEXEC error from inside non native containers, when an emulator is not set correctly. These new functions are meant to replace its original versions in the future. https://github.com/containers/toolbox/pull/1780 Signed-off-by: Dalibor Kricka --- src/pkg/shell/shell.go | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/pkg/shell/shell.go b/src/pkg/shell/shell.go index 00fa36997..6c9cfcacd 100644 --- a/src/pkg/shell/shell.go +++ b/src/pkg/shell/shell.go @@ -81,8 +81,49 @@ func RunContextWithExitCode(ctx context.Context, return 0, nil } +func RunContextWithExitCode2(ctx context.Context, + name string, + stdin io.Reader, + stdout, stderr io.Writer, + arg ...string) (int, error) { + + logLevel := logrus.GetLevel() + if stderr == nil && logLevel >= logrus.DebugLevel { + stderr = os.Stderr + } + + cmd := exec.CommandContext(ctx, name, arg...) + cmd.Stdin = stdin + cmd.Stdout = stdout + cmd.Stderr = stderr + + if err := cmd.Run(); err != nil { + exitCode := 1 + + if ctxErr := ctx.Err(); ctxErr != nil { + return 1, ctxErr + } + + var exitErr *exec.ExitError + if errors.As(err, &exitErr) { + exitCode = exitErr.ExitCode() + return exitCode, err + } + + return exitCode, err + } + + return 0, nil +} + func RunWithExitCode(name string, stdin io.Reader, stdout, stderr io.Writer, arg ...string) (int, error) { ctx := context.Background() exitCode, err := RunContextWithExitCode(ctx, name, stdin, stdout, stderr, arg...) return exitCode, err } + +func RunWithExitCode2(name string, stdin io.Reader, stdout, stderr io.Writer, arg ...string) (int, error) { + ctx := context.Background() + exitCode, err := RunContextWithExitCode2(ctx, name, stdin, stdout, stderr, arg...) + return exitCode, err +} From fae8f4a0614dc549fe832e343d9bc8ebc43f72a4 Mon Sep 17 00:00:00 2001 From: Dalibor Kricka Date: Wed, 22 Apr 2026 23:21:55 +0200 Subject: [PATCH 2/3] cmd/create: Extract spinner setup into helper functions In /src/cmd/create.go, the same pattern of spinner creation and nil-safe stopping is repeated. Extract this into startSpinner() and stopSpinner() helper functions so that future callers can use spinners without duplicating the code. Replace the existing inline spinner code in createContainer() and pullImage() with calls to these new helpers. https://github.com/containers/toolbox/pull/1781 Signed-off-by: Dalibor Kricka --- src/cmd/create.go | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/src/cmd/create.go b/src/cmd/create.go index bdd86be37..13345289d 100644 --- a/src/cmd/create.go +++ b/src/cmd/create.go @@ -486,19 +486,15 @@ func createContainer(container, image, release, authFile string, showCommandToEn logrus.Debugf("%s", arg) } - s := spinner.New(spinner.CharSets[9], 500*time.Millisecond, spinner.WithWriterFile(os.Stdout)) - if logLevel := logrus.GetLevel(); logLevel < logrus.DebugLevel { - s.Prefix = fmt.Sprintf("Creating container %s: ", container) - s.Start() - defer s.Stop() - } + s := startSpinner(fmt.Sprintf("Creating container %s: ", container)) + defer stopSpinner(s) if err := shell.Run("podman", nil, nil, nil, createArgs...); err != nil { return fmt.Errorf("failed to create container %s", container) } // The spinner must be stopped before showing the 'enter' hint below. - s.Stop() + stopSpinner(s) if showCommandToEnter { fmt.Printf("Created container: %s\n", container) @@ -735,12 +731,8 @@ func pullImage(image, release, authFile string) (bool, error) { logrus.Debugf("Pulling image %s", imageFull) - if logLevel := logrus.GetLevel(); logLevel < logrus.DebugLevel { - s := spinner.New(spinner.CharSets[9], 500*time.Millisecond, spinner.WithWriterFile(os.Stdout)) - s.Prefix = fmt.Sprintf("Pulling %s: ", imageFull) - s.Start() - defer s.Stop() - } + s := startSpinner(fmt.Sprintf("Pulling %s: ", imageFull)) + defer stopSpinner(s) if err := podman.Pull(imageFull, authFile); err != nil { var builder strings.Builder @@ -963,6 +955,22 @@ func showPromptForDownload(imageFull string) bool { return shouldPullImage } +func startSpinner(message string) *spinner.Spinner { + if logLevel := logrus.GetLevel(); logLevel < logrus.DebugLevel { + s := spinner.New(spinner.CharSets[9], 500*time.Millisecond, spinner.WithWriterFile(os.Stdout)) + s.Prefix = message + s.Start() + return s + } + return nil +} + +func stopSpinner(s *spinner.Spinner) { + if s != nil { + s.Stop() + } +} + // systemdNeedsEscape checks whether a byte in a potential dbus ObjectPath needs to be escaped func systemdNeedsEscape(i int, b byte) bool { // Escape everything that is not a-z-A-Z-0-9 From ddebd00b7edb62abb32f17ba81fdec387b1f5e18 Mon Sep 17 00:00:00 2001 From: Dalibor Kricka Date: Wed, 22 Apr 2026 23:30:29 +0200 Subject: [PATCH 3/3] pkg/utils: Add IsSupportedDistroImage for image to supported distro matching Add IsSupportedDistroImage(), which iterates over all supported distros and checks if the image basename matches any of them. This will be used by the architecture resolution code to decide whether to parse architecture suffixes from image tags, as this should be done only for natively supported images [1]. [1] Toolbx supported distributions: https://containertoolbx.org/distros/ https://github.com/containers/toolbox/pull/1781 Signed-off-by: Dalibor Kricka --- src/pkg/utils/utils.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/pkg/utils/utils.go b/src/pkg/utils/utils.go index f3de23b1b..c88f8ef67 100644 --- a/src/pkg/utils/utils.go +++ b/src/pkg/utils/utils.go @@ -664,6 +664,20 @@ func IsP11KitClientPresent() (bool, error) { return false, err } +func IsSupportedDistroImage(image string) bool { + basename := ImageReferenceGetBasename(image) + if basename == "" { + return false + } + + for _, distroObj := range supportedDistros { + if distroObj.ImageBasename == basename { + return true + } + } + return false +} + func SetUpConfiguration() error { logrus.Debug("Setting up configuration")