summaryrefslogtreecommitdiff
path: root/libpod
diff options
context:
space:
mode:
Diffstat (limited to 'libpod')
-rw-r--r--libpod/container.go6
-rw-r--r--libpod/container_api.go5
-rw-r--r--libpod/container_copy_common.go213
-rw-r--r--libpod/container_copy_freebsd.go13
-rw-r--r--libpod/container_copy_linux.go222
-rw-r--r--libpod/container_copy_unsupported.go4
-rw-r--r--libpod/container_exec.go3
-rw-r--r--libpod/container_internal.go7
-rw-r--r--libpod/container_internal_common.go17
-rw-r--r--libpod/container_internal_test.go4
-rw-r--r--libpod/container_stat_common.go155
-rw-r--r--libpod/container_stat_freebsd.go13
-rw-r--r--libpod/container_stat_linux.go159
-rw-r--r--libpod/container_stat_unsupported.go4
-rw-r--r--libpod/events/logfile.go5
-rw-r--r--libpod/events/logfile_test.go17
-rw-r--r--libpod/healthcheck.go7
-rw-r--r--libpod/networking_linux.go5
-rw-r--r--libpod/networking_machine.go3
-rw-r--r--libpod/networking_slirp4netns.go11
-rw-r--r--libpod/oci_conmon_common.go13
-rw-r--r--libpod/oci_conmon_exec_common.go5
-rw-r--r--libpod/plugin/volume_api.go14
-rw-r--r--libpod/runtime_img.go3
-rw-r--r--libpod/runtime_migrate.go3
-rw-r--r--libpod/state_test.go3
26 files changed, 475 insertions, 439 deletions
diff --git a/libpod/container.go b/libpod/container.go
index cfffd8ea1..a4eb33c49 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -3,7 +3,7 @@ package libpod
import (
"bytes"
"fmt"
- "io/ioutil"
+ "io"
"net"
"os"
"strings"
@@ -351,7 +351,7 @@ func (c *Container) specFromState() (*spec.Spec, error) {
if f, err := os.Open(c.state.ConfigPath); err == nil {
returnSpec = new(spec.Spec)
- content, err := ioutil.ReadAll(f)
+ content, err := io.ReadAll(f)
if err != nil {
return nil, fmt.Errorf("reading container config: %w", err)
}
@@ -990,7 +990,7 @@ func (c *Container) cGroupPath() (string, error) {
// the lookup.
// See #10602 for more details.
procPath := fmt.Sprintf("/proc/%d/cgroup", c.state.PID)
- lines, err := ioutil.ReadFile(procPath)
+ lines, err := os.ReadFile(procPath)
if err != nil {
// If the file doesn't exist, it means the container could have been terminated
// so report it.
diff --git a/libpod/container_api.go b/libpod/container_api.go
index dd47b4d12..be0ca0128 100644
--- a/libpod/container_api.go
+++ b/libpod/container_api.go
@@ -5,7 +5,6 @@ import (
"errors"
"fmt"
"io"
- "io/ioutil"
"net/http"
"os"
"sync"
@@ -479,7 +478,7 @@ func (c *Container) AddArtifact(name string, data []byte) error {
return define.ErrCtrRemoved
}
- return ioutil.WriteFile(c.getArtifactPath(name), data, 0o740)
+ return os.WriteFile(c.getArtifactPath(name), data, 0o740)
}
// GetArtifact reads the specified artifact file from the container
@@ -488,7 +487,7 @@ func (c *Container) GetArtifact(name string) ([]byte, error) {
return nil, define.ErrCtrRemoved
}
- return ioutil.ReadFile(c.getArtifactPath(name))
+ return os.ReadFile(c.getArtifactPath(name))
}
// RemoveArtifact deletes the specified artifacts file
diff --git a/libpod/container_copy_common.go b/libpod/container_copy_common.go
new file mode 100644
index 000000000..d07b4c692
--- /dev/null
+++ b/libpod/container_copy_common.go
@@ -0,0 +1,213 @@
+//go:build linux || freebsd
+// +build linux freebsd
+
+package libpod
+
+import (
+ "errors"
+ "io"
+ "path/filepath"
+ "strings"
+
+ buildahCopiah "github.com/containers/buildah/copier"
+ "github.com/containers/buildah/pkg/chrootuser"
+ "github.com/containers/buildah/util"
+ "github.com/containers/podman/v4/libpod/define"
+ "github.com/containers/podman/v4/pkg/rootless"
+ "github.com/containers/storage/pkg/archive"
+ "github.com/containers/storage/pkg/idtools"
+ "github.com/opencontainers/runtime-spec/specs-go"
+ "github.com/sirupsen/logrus"
+)
+
+func (c *Container) copyFromArchive(path string, chown, noOverwriteDirNonDir bool, rename map[string]string, reader io.Reader) (func() error, error) {
+ var (
+ mountPoint string
+ resolvedRoot string
+ resolvedPath string
+ unmount func()
+ err error
+ )
+
+ // Make sure that "/" copies the *contents* of the mount point and not
+ // the directory.
+ if path == "/" {
+ path = "/."
+ }
+
+ // Optimization: only mount if the container is not already.
+ if c.state.Mounted {
+ mountPoint = c.state.Mountpoint
+ unmount = func() {}
+ } else {
+ // NOTE: make sure to unmount in error paths.
+ mountPoint, err = c.mount()
+ if err != nil {
+ return nil, err
+ }
+ unmount = func() {
+ if err := c.unmount(false); err != nil {
+ logrus.Errorf("Failed to unmount container: %v", err)
+ }
+ }
+ }
+
+ resolvedRoot, resolvedPath, err = c.resolveCopyTarget(mountPoint, path)
+ if err != nil {
+ unmount()
+ return nil, err
+ }
+
+ var idPair *idtools.IDPair
+ if chown {
+ // Make sure we chown the files to the container's main user and group ID.
+ user, err := getContainerUser(c, mountPoint)
+ if err != nil {
+ unmount()
+ return nil, err
+ }
+ idPair = &idtools.IDPair{UID: int(user.UID), GID: int(user.GID)}
+ }
+
+ decompressed, err := archive.DecompressStream(reader)
+ if err != nil {
+ unmount()
+ return nil, err
+ }
+
+ logrus.Debugf("Container copy *to* %q (resolved: %q) on container %q (ID: %s)", path, resolvedPath, c.Name(), c.ID())
+
+ return func() error {
+ defer unmount()
+ defer decompressed.Close()
+ putOptions := buildahCopiah.PutOptions{
+ UIDMap: c.config.IDMappings.UIDMap,
+ GIDMap: c.config.IDMappings.GIDMap,
+ ChownDirs: idPair,
+ ChownFiles: idPair,
+ NoOverwriteDirNonDir: noOverwriteDirNonDir,
+ NoOverwriteNonDirDir: noOverwriteDirNonDir,
+ Rename: rename,
+ }
+
+ return c.joinMountAndExec(
+ func() error {
+ return buildahCopiah.Put(resolvedRoot, resolvedPath, putOptions, decompressed)
+ },
+ )
+ }, nil
+}
+
+func (c *Container) copyToArchive(path string, writer io.Writer) (func() error, error) {
+ var (
+ mountPoint string
+ unmount func()
+ err error
+ )
+
+ // Optimization: only mount if the container is not already.
+ if c.state.Mounted {
+ mountPoint = c.state.Mountpoint
+ unmount = func() {}
+ } else {
+ // NOTE: make sure to unmount in error paths.
+ mountPoint, err = c.mount()
+ if err != nil {
+ return nil, err
+ }
+ unmount = func() {
+ if err := c.unmount(false); err != nil {
+ logrus.Errorf("Failed to unmount container: %v", err)
+ }
+ }
+ }
+
+ statInfo, resolvedRoot, resolvedPath, err := c.stat(mountPoint, path)
+ if err != nil {
+ unmount()
+ return nil, err
+ }
+
+ // We optimistically chown to the host user. In case of a hypothetical
+ // container-to-container copy, the reading side will chown back to the
+ // container user.
+ user, err := getContainerUser(c, mountPoint)
+ if err != nil {
+ unmount()
+ return nil, err
+ }
+ hostUID, hostGID, err := util.GetHostIDs(
+ idtoolsToRuntimeSpec(c.config.IDMappings.UIDMap),
+ idtoolsToRuntimeSpec(c.config.IDMappings.GIDMap),
+ user.UID,
+ user.GID,
+ )
+ if err != nil {
+ unmount()
+ return nil, err
+ }
+ idPair := idtools.IDPair{UID: int(hostUID), GID: int(hostGID)}
+
+ logrus.Debugf("Container copy *from* %q (resolved: %q) on container %q (ID: %s)", path, resolvedPath, c.Name(), c.ID())
+
+ return func() error {
+ defer unmount()
+ getOptions := buildahCopiah.GetOptions{
+ // Unless the specified points to ".", we want to copy the base directory.
+ KeepDirectoryNames: statInfo.IsDir && filepath.Base(path) != ".",
+ UIDMap: c.config.IDMappings.UIDMap,
+ GIDMap: c.config.IDMappings.GIDMap,
+ ChownDirs: &idPair,
+ ChownFiles: &idPair,
+ Excludes: []string{"dev", "proc", "sys"},
+ // Ignore EPERMs when copying from rootless containers
+ // since we cannot read TTY devices. Those are owned
+ // by the host's root and hence "nobody" inside the
+ // container's user namespace.
+ IgnoreUnreadable: rootless.IsRootless() && c.state.State == define.ContainerStateRunning,
+ }
+ return c.joinMountAndExec(
+ func() error {
+ return buildahCopiah.Get(resolvedRoot, "", getOptions, []string{resolvedPath}, writer)
+ },
+ )
+ }, nil
+}
+
+// getContainerUser returns the specs.User and ID mappings of the container.
+func getContainerUser(container *Container, mountPoint string) (specs.User, error) {
+ userspec := container.config.User
+
+ uid, gid, _, err := chrootuser.GetUser(mountPoint, userspec)
+ u := specs.User{
+ UID: uid,
+ GID: gid,
+ Username: userspec,
+ }
+
+ if !strings.Contains(userspec, ":") {
+ groups, err2 := chrootuser.GetAdditionalGroupsForUser(mountPoint, uint64(u.UID))
+ if err2 != nil {
+ if !errors.Is(err2, chrootuser.ErrNoSuchUser) && err == nil {
+ err = err2
+ }
+ } else {
+ u.AdditionalGids = groups
+ }
+ }
+
+ return u, err
+}
+
+// idtoolsToRuntimeSpec converts idtools ID mapping to the one of the runtime spec.
+func idtoolsToRuntimeSpec(idMaps []idtools.IDMap) (convertedIDMap []specs.LinuxIDMapping) {
+ for _, idmap := range idMaps {
+ tempIDMap := specs.LinuxIDMapping{
+ ContainerID: uint32(idmap.ContainerID),
+ HostID: uint32(idmap.HostID),
+ Size: uint32(idmap.Size),
+ }
+ convertedIDMap = append(convertedIDMap, tempIDMap)
+ }
+ return convertedIDMap
+}
diff --git a/libpod/container_copy_freebsd.go b/libpod/container_copy_freebsd.go
new file mode 100644
index 000000000..218f3917f
--- /dev/null
+++ b/libpod/container_copy_freebsd.go
@@ -0,0 +1,13 @@
+package libpod
+
+// On FreeBSD, the container's mounts are in the global mount
+// namespace so we can just execute the function directly.
+func (c *Container) joinMountAndExec(f func() error) error {
+ return f()
+}
+
+// Similarly, we can just use resolvePath for both running and stopped
+// containers.
+func (c *Container) resolveCopyTarget(mountPoint string, containerPath string) (string, string, error) {
+ return c.resolvePath(mountPoint, containerPath)
+}
diff --git a/libpod/container_copy_linux.go b/libpod/container_copy_linux.go
index 557fead1e..3b029f08f 100644
--- a/libpod/container_copy_linux.go
+++ b/libpod/container_copy_linux.go
@@ -1,226 +1,14 @@
-//go:build linux
-// +build linux
-
package libpod
import (
- "errors"
"fmt"
- "io"
"os"
- "path/filepath"
"runtime"
- "strings"
- buildahCopiah "github.com/containers/buildah/copier"
- "github.com/containers/buildah/pkg/chrootuser"
- "github.com/containers/buildah/util"
"github.com/containers/podman/v4/libpod/define"
- "github.com/containers/podman/v4/pkg/rootless"
- "github.com/containers/storage/pkg/archive"
- "github.com/containers/storage/pkg/idtools"
- "github.com/opencontainers/runtime-spec/specs-go"
- "github.com/sirupsen/logrus"
"golang.org/x/sys/unix"
)
-func (c *Container) copyFromArchive(path string, chown, noOverwriteDirNonDir bool, rename map[string]string, reader io.Reader) (func() error, error) {
- var (
- mountPoint string
- resolvedRoot string
- resolvedPath string
- unmount func()
- err error
- )
-
- // Make sure that "/" copies the *contents* of the mount point and not
- // the directory.
- if path == "/" {
- path = "/."
- }
-
- // Optimization: only mount if the container is not already.
- if c.state.Mounted {
- mountPoint = c.state.Mountpoint
- unmount = func() {}
- } else {
- // NOTE: make sure to unmount in error paths.
- mountPoint, err = c.mount()
- if err != nil {
- return nil, err
- }
- unmount = func() {
- if err := c.unmount(false); err != nil {
- logrus.Errorf("Failed to unmount container: %v", err)
- }
- }
- }
-
- if c.state.State == define.ContainerStateRunning {
- resolvedRoot = "/"
- resolvedPath = c.pathAbs(path)
- } else {
- resolvedRoot, resolvedPath, err = c.resolvePath(mountPoint, path)
- if err != nil {
- unmount()
- return nil, err
- }
- }
-
- var idPair *idtools.IDPair
- if chown {
- // Make sure we chown the files to the container's main user and group ID.
- user, err := getContainerUser(c, mountPoint)
- if err != nil {
- unmount()
- return nil, err
- }
- idPair = &idtools.IDPair{UID: int(user.UID), GID: int(user.GID)}
- }
-
- decompressed, err := archive.DecompressStream(reader)
- if err != nil {
- unmount()
- return nil, err
- }
-
- logrus.Debugf("Container copy *to* %q (resolved: %q) on container %q (ID: %s)", path, resolvedPath, c.Name(), c.ID())
-
- return func() error {
- defer unmount()
- defer decompressed.Close()
- putOptions := buildahCopiah.PutOptions{
- UIDMap: c.config.IDMappings.UIDMap,
- GIDMap: c.config.IDMappings.GIDMap,
- ChownDirs: idPair,
- ChownFiles: idPair,
- NoOverwriteDirNonDir: noOverwriteDirNonDir,
- NoOverwriteNonDirDir: noOverwriteDirNonDir,
- Rename: rename,
- }
-
- return c.joinMountAndExec(
- func() error {
- return buildahCopiah.Put(resolvedRoot, resolvedPath, putOptions, decompressed)
- },
- )
- }, nil
-}
-
-func (c *Container) copyToArchive(path string, writer io.Writer) (func() error, error) {
- var (
- mountPoint string
- unmount func()
- err error
- )
-
- // Optimization: only mount if the container is not already.
- if c.state.Mounted {
- mountPoint = c.state.Mountpoint
- unmount = func() {}
- } else {
- // NOTE: make sure to unmount in error paths.
- mountPoint, err = c.mount()
- if err != nil {
- return nil, err
- }
- unmount = func() {
- if err := c.unmount(false); err != nil {
- logrus.Errorf("Failed to unmount container: %v", err)
- }
- }
- }
-
- statInfo, resolvedRoot, resolvedPath, err := c.stat(mountPoint, path)
- if err != nil {
- unmount()
- return nil, err
- }
-
- // We optimistically chown to the host user. In case of a hypothetical
- // container-to-container copy, the reading side will chown back to the
- // container user.
- user, err := getContainerUser(c, mountPoint)
- if err != nil {
- unmount()
- return nil, err
- }
- hostUID, hostGID, err := util.GetHostIDs(
- idtoolsToRuntimeSpec(c.config.IDMappings.UIDMap),
- idtoolsToRuntimeSpec(c.config.IDMappings.GIDMap),
- user.UID,
- user.GID,
- )
- if err != nil {
- unmount()
- return nil, err
- }
- idPair := idtools.IDPair{UID: int(hostUID), GID: int(hostGID)}
-
- logrus.Debugf("Container copy *from* %q (resolved: %q) on container %q (ID: %s)", path, resolvedPath, c.Name(), c.ID())
-
- return func() error {
- defer unmount()
- getOptions := buildahCopiah.GetOptions{
- // Unless the specified points to ".", we want to copy the base directory.
- KeepDirectoryNames: statInfo.IsDir && filepath.Base(path) != ".",
- UIDMap: c.config.IDMappings.UIDMap,
- GIDMap: c.config.IDMappings.GIDMap,
- ChownDirs: &idPair,
- ChownFiles: &idPair,
- Excludes: []string{"dev", "proc", "sys"},
- // Ignore EPERMs when copying from rootless containers
- // since we cannot read TTY devices. Those are owned
- // by the host's root and hence "nobody" inside the
- // container's user namespace.
- IgnoreUnreadable: rootless.IsRootless() && c.state.State == define.ContainerStateRunning,
- }
- return c.joinMountAndExec(
- func() error {
- return buildahCopiah.Get(resolvedRoot, "", getOptions, []string{resolvedPath}, writer)
- },
- )
- }, nil
-}
-
-// getContainerUser returns the specs.User and ID mappings of the container.
-func getContainerUser(container *Container, mountPoint string) (specs.User, error) {
- userspec := container.config.User
-
- uid, gid, _, err := chrootuser.GetUser(mountPoint, userspec)
- u := specs.User{
- UID: uid,
- GID: gid,
- Username: userspec,
- }
-
- if !strings.Contains(userspec, ":") {
- groups, err2 := chrootuser.GetAdditionalGroupsForUser(mountPoint, uint64(u.UID))
- if err2 != nil {
- if !errors.Is(err2, chrootuser.ErrNoSuchUser) && err == nil {
- err = err2
- }
- } else {
- u.AdditionalGids = groups
- }
- }
-
- return u, err
-}
-
-// idtoolsToRuntimeSpec converts idtools ID mapping to the one of the runtime spec.
-func idtoolsToRuntimeSpec(idMaps []idtools.IDMap) (convertedIDMap []specs.LinuxIDMapping) {
- for _, idmap := range idMaps {
- tempIDMap := specs.LinuxIDMapping{
- ContainerID: uint32(idmap.ContainerID),
- HostID: uint32(idmap.HostID),
- Size: uint32(idmap.Size),
- }
- convertedIDMap = append(convertedIDMap, tempIDMap)
- }
- return convertedIDMap
-}
-
// joinMountAndExec executes the specified function `f` inside the container's
// mount and PID namespace. That allows for having the exact view on the
// container's file system.
@@ -288,3 +76,13 @@ func (c *Container) joinMountAndExec(f func() error) error {
}()
return <-errChan
}
+
+func (c *Container) resolveCopyTarget(mountPoint string, containerPath string) (string, string, error) {
+ // If the container is running, we will execute the copy
+ // inside the container's mount namespace so we return a path
+ // relative to the container's root.
+ if c.state.State == define.ContainerStateRunning {
+ return "/", c.pathAbs(containerPath), nil
+ }
+ return c.resolvePath(mountPoint, containerPath)
+}
diff --git a/libpod/container_copy_unsupported.go b/libpod/container_copy_unsupported.go
index 62937279a..703b0a74e 100644
--- a/libpod/container_copy_unsupported.go
+++ b/libpod/container_copy_unsupported.go
@@ -1,5 +1,5 @@
-//go:build !linux
-// +build !linux
+//go:build !linux && !freebsd
+// +build !linux,!freebsd
package libpod
diff --git a/libpod/container_exec.go b/libpod/container_exec.go
index 3a2cba52f..7896d1932 100644
--- a/libpod/container_exec.go
+++ b/libpod/container_exec.go
@@ -4,7 +4,6 @@ import (
"context"
"errors"
"fmt"
- "io/ioutil"
"net/http"
"os"
"path/filepath"
@@ -928,7 +927,7 @@ func (c *Container) readExecExitCode(sessionID string) (int, error) {
if err != nil {
return -1, err
}
- ec, err := ioutil.ReadFile(exitFile)
+ ec, err := os.ReadFile(exitFile)
if err != nil {
return -1, err
}
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index 994243805..9bf93412d 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -6,7 +6,6 @@ import (
"errors"
"fmt"
"io"
- "io/ioutil"
"os"
"path/filepath"
"strconv"
@@ -201,7 +200,7 @@ func (c *Container) waitForExitFileAndSync() error {
// This assumes the exit file already exists.
func (c *Container) handleExitFile(exitFile string, fi os.FileInfo) error {
c.state.FinishedTime = ctime.Created(fi)
- statusCodeStr, err := ioutil.ReadFile(exitFile)
+ statusCodeStr, err := os.ReadFile(exitFile)
if err != nil {
return fmt.Errorf("failed to read exit file for container %s: %w", c.ID(), err)
}
@@ -2089,7 +2088,7 @@ func (c *Container) saveSpec(spec *spec.Spec) error {
if err != nil {
return fmt.Errorf("exporting runtime spec for container %s to JSON: %w", c.ID(), err)
}
- if err := ioutil.WriteFile(jsonPath, fileJSON, 0644); err != nil {
+ if err := os.WriteFile(jsonPath, fileJSON, 0644); err != nil {
return fmt.Errorf("writing runtime spec JSON for container %s to disk: %w", c.ID(), err)
}
@@ -2343,7 +2342,7 @@ func (c *Container) extractSecretToCtrStorage(secr *ContainerSecret) error {
if err != nil {
return fmt.Errorf("unable to extract secret: %w", err)
}
- err = ioutil.WriteFile(secretFile, data, 0644)
+ err = os.WriteFile(secretFile, data, 0644)
if err != nil {
return fmt.Errorf("unable to create %s: %w", secretFile, err)
}
diff --git a/libpod/container_internal_common.go b/libpod/container_internal_common.go
index 9c4a3bb67..29107d4b6 100644
--- a/libpod/container_internal_common.go
+++ b/libpod/container_internal_common.go
@@ -8,7 +8,6 @@ import (
"errors"
"fmt"
"io"
- "io/ioutil"
"math"
"os"
"os/user"
@@ -110,7 +109,11 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
// If the flag to mount all devices is set for a privileged container, add
// all the devices from the host's machine into the container
if c.config.MountAllDevices {
- if err := util.AddPrivilegedDevices(&g); err != nil {
+ systemdMode := false
+ if c.config.Systemd != nil {
+ systemdMode = *c.config.Systemd
+ }
+ if err := util.AddPrivilegedDevices(&g, systemdMode); err != nil {
return nil, err
}
}
@@ -788,7 +791,7 @@ func (c *Container) createCheckpointImage(ctx context.Context, options Container
}
// Export checkpoint into temporary tar file
- tmpDir, err := ioutil.TempDir("", "checkpoint_image_")
+ tmpDir, err := os.MkdirTemp("", "checkpoint_image_")
if err != nil {
return err
}
@@ -2442,7 +2445,7 @@ func (c *Container) generatePasswdAndGroup() (string, string, error) {
if err != nil {
return "", "", fmt.Errorf("creating path to container %s /etc/passwd: %w", c.ID(), err)
}
- orig, err := ioutil.ReadFile(originPasswdFile)
+ orig, err := os.ReadFile(originPasswdFile)
if err != nil && !os.IsNotExist(err) {
return "", "", err
}
@@ -2488,7 +2491,7 @@ func (c *Container) generatePasswdAndGroup() (string, string, error) {
if err != nil {
return "", "", fmt.Errorf("creating path to container %s /etc/group: %w", c.ID(), err)
}
- orig, err := ioutil.ReadFile(originGroupFile)
+ orig, err := os.ReadFile(originGroupFile)
if err != nil && !os.IsNotExist(err) {
return "", "", err
}
@@ -2659,7 +2662,7 @@ func (c *Container) fixVolumePermissions(v *ContainerNamedVolume) error {
return nil
}
-func (c *Container) relabel(src, mountLabel string, recurse bool) error {
+func (c *Container) relabel(src, mountLabel string, shared bool) error {
if !selinux.GetEnabled() || mountLabel == "" {
return nil
}
@@ -2674,7 +2677,7 @@ func (c *Container) relabel(src, mountLabel string, recurse bool) error {
return nil
}
}
- return label.Relabel(src, mountLabel, recurse)
+ return label.Relabel(src, mountLabel, shared)
}
func (c *Container) ChangeHostPathOwnership(src string, recurse bool, uid, gid int) error {
diff --git a/libpod/container_internal_test.go b/libpod/container_internal_test.go
index 1b4e62e91..46a2da544 100644
--- a/libpod/container_internal_test.go
+++ b/libpod/container_internal_test.go
@@ -3,7 +3,7 @@ package libpod
import (
"context"
"fmt"
- "io/ioutil"
+ "os"
"path/filepath"
"runtime"
"testing"
@@ -60,7 +60,7 @@ func TestPostDeleteHooks(t *testing.T) {
for _, p := range []string{statePath, copyPath} {
path := p
t.Run(path, func(t *testing.T) {
- content, err := ioutil.ReadFile(path)
+ content, err := os.ReadFile(path)
if err != nil {
t.Fatal(err)
}
diff --git a/libpod/container_stat_common.go b/libpod/container_stat_common.go
new file mode 100644
index 000000000..e59a52ede
--- /dev/null
+++ b/libpod/container_stat_common.go
@@ -0,0 +1,155 @@
+//go:build linux || freebsd
+// +build linux freebsd
+
+package libpod
+
+import (
+ "errors"
+ "fmt"
+ "os"
+ "path/filepath"
+ "strings"
+
+ "github.com/containers/buildah/copier"
+ "github.com/containers/podman/v4/libpod/define"
+ "github.com/containers/podman/v4/pkg/copy"
+)
+
+// statOnHost stats the specified path *on the host*. It returns the file info
+// along with the resolved root and the resolved path. Both paths are absolute
+// to the host's root. Note that the paths may resolved outside the
+// container's mount point (e.g., to a volume or bind mount).
+func (c *Container) statOnHost(mountPoint string, containerPath string) (*copier.StatForItem, string, string, error) {
+ // Now resolve the container's path. It may hit a volume, it may hit a
+ // bind mount, it may be relative.
+ resolvedRoot, resolvedPath, err := c.resolvePath(mountPoint, containerPath)
+ if err != nil {
+ return nil, "", "", err
+ }
+
+ statInfo, err := secureStat(resolvedRoot, resolvedPath)
+ return statInfo, resolvedRoot, resolvedPath, err
+}
+
+func (c *Container) stat(containerMountPoint string, containerPath string) (*define.FileInfo, string, string, error) {
+ var (
+ resolvedRoot string
+ resolvedPath string
+ absContainerPath string
+ statInfo *copier.StatForItem
+ statErr error
+ )
+
+ // Make sure that "/" copies the *contents* of the mount point and not
+ // the directory.
+ if containerPath == "/" {
+ containerPath = "/."
+ }
+
+ // Wildcards are not allowed.
+ // TODO: it's now technically possible wildcards.
+ // We may consider enabling support in the future.
+ if strings.Contains(containerPath, "*") {
+ return nil, "", "", copy.ErrENOENT
+ }
+
+ statInfo, resolvedRoot, resolvedPath, statErr = c.statInContainer(containerMountPoint, containerPath)
+ if statErr != nil {
+ if statInfo == nil {
+ return nil, "", "", statErr
+ }
+ // Not all errors from secureStat map to ErrNotExist, so we
+ // have to look into the error string. Turning it into an
+ // ENOENT let's the API handlers return the correct status code
+ // which is crucial for the remote client.
+ if os.IsNotExist(statErr) || strings.Contains(statErr.Error(), "o such file or directory") {
+ statErr = copy.ErrENOENT
+ }
+ }
+
+ switch {
+ case statInfo.IsSymlink:
+ // Symlinks are already evaluated and always relative to the
+ // container's mount point.
+ absContainerPath = statInfo.ImmediateTarget
+ case strings.HasPrefix(resolvedPath, containerMountPoint):
+ // If the path is on the container's mount point, strip it off.
+ absContainerPath = strings.TrimPrefix(resolvedPath, containerMountPoint)
+ absContainerPath = filepath.Join("/", absContainerPath)
+ default:
+ // No symlink and not on the container's mount point, so let's
+ // move it back to the original input. It must have evaluated
+ // to a volume or bind mount but we cannot return host paths.
+ absContainerPath = containerPath
+ }
+
+ // Preserve the base path as specified by the user. The `filepath`
+ // packages likes to remove trailing slashes and dots that are crucial
+ // to the copy logic.
+ absContainerPath = copy.PreserveBasePath(containerPath, absContainerPath)
+ resolvedPath = copy.PreserveBasePath(containerPath, resolvedPath)
+
+ info := &define.FileInfo{
+ IsDir: statInfo.IsDir,
+ Name: filepath.Base(absContainerPath),
+ Size: statInfo.Size,
+ Mode: statInfo.Mode,
+ ModTime: statInfo.ModTime,
+ LinkTarget: absContainerPath,
+ }
+
+ return info, resolvedRoot, resolvedPath, statErr
+}
+
+// secureStat extracts file info for path in a chroot'ed environment in root.
+func secureStat(root string, path string) (*copier.StatForItem, error) {
+ var glob string
+ var err error
+
+ // If root and path are equal, then dir must be empty and the glob must
+ // be ".".
+ if filepath.Clean(root) == filepath.Clean(path) {
+ glob = "."
+ } else {
+ glob, err = filepath.Rel(root, path)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ globStats, err := copier.Stat(root, "", copier.StatOptions{}, []string{glob})
+ if err != nil {
+ return nil, err
+ }
+
+ if len(globStats) != 1 {
+ return nil, fmt.Errorf("internal error: secureStat: expected 1 item but got %d", len(globStats))
+ }
+ if len(globStats) != 1 {
+ return nil, fmt.Errorf("internal error: secureStat: expected 1 result but got %d", len(globStats[0].Results))
+ }
+
+ // NOTE: the key in the map differ from `glob` when hitting symlink.
+ // Hence, we just take the first (and only) key/value pair.
+ for _, stat := range globStats[0].Results {
+ var statErr error
+ if stat.Error != "" {
+ statErr = errors.New(stat.Error)
+ }
+ // If necessary evaluate the symlink
+ if stat.IsSymlink {
+ target, err := copier.Eval(root, path, copier.EvalOptions{})
+ if err != nil {
+ return nil, fmt.Errorf("evaluating symlink in container: %w", err)
+ }
+ // Need to make sure the symlink is relative to the root!
+ target = strings.TrimPrefix(target, root)
+ target = filepath.Join("/", target)
+ stat.ImmediateTarget = target
+ }
+ return stat, statErr
+ }
+
+ // Nothing found!
+ return nil, copy.ErrENOENT
+}
diff --git a/libpod/container_stat_freebsd.go b/libpod/container_stat_freebsd.go
new file mode 100644
index 000000000..d1e0db348
--- /dev/null
+++ b/libpod/container_stat_freebsd.go
@@ -0,0 +1,13 @@
+package libpod
+
+import (
+ "github.com/containers/buildah/copier"
+)
+
+// On FreeBSD, jails use the global mount namespace, filtered to only
+// the mounts the jail should see. This means that we can use
+// statOnHost whether the container is running or not.
+// container is running
+func (c *Container) statInContainer(mountPoint string, containerPath string) (*copier.StatForItem, string, string, error) {
+ return c.statOnHost(mountPoint, containerPath)
+}
diff --git a/libpod/container_stat_linux.go b/libpod/container_stat_linux.go
index dc3a524f5..5e5ef3c1a 100644
--- a/libpod/container_stat_linux.go
+++ b/libpod/container_stat_linux.go
@@ -1,18 +1,8 @@
-//go:build linux
-// +build linux
-
package libpod
import (
- "errors"
- "fmt"
- "os"
- "path/filepath"
- "strings"
-
"github.com/containers/buildah/copier"
"github.com/containers/podman/v4/libpod/define"
- "github.com/containers/podman/v4/pkg/copy"
)
// statInsideMount stats the specified path *inside* the container's mount and PID
@@ -34,150 +24,15 @@ func (c *Container) statInsideMount(containerPath string) (*copier.StatForItem,
return statInfo, resolvedRoot, resolvedPath, err
}
-// statOnHost stats the specified path *on the host*. It returns the file info
-// along with the resolved root and the resolved path. Both paths are absolute
-// to the host's root. Note that the paths may resolved outside the
-// container's mount point (e.g., to a volume or bind mount).
-func (c *Container) statOnHost(mountPoint string, containerPath string) (*copier.StatForItem, string, string, error) {
- // Now resolve the container's path. It may hit a volume, it may hit a
- // bind mount, it may be relative.
- resolvedRoot, resolvedPath, err := c.resolvePath(mountPoint, containerPath)
- if err != nil {
- return nil, "", "", err
- }
-
- statInfo, err := secureStat(resolvedRoot, resolvedPath)
- return statInfo, resolvedRoot, resolvedPath, err
-}
-
-func (c *Container) stat(containerMountPoint string, containerPath string) (*define.FileInfo, string, string, error) {
- var (
- resolvedRoot string
- resolvedPath string
- absContainerPath string
- statInfo *copier.StatForItem
- statErr error
- )
-
- // Make sure that "/" copies the *contents* of the mount point and not
- // the directory.
- if containerPath == "/" {
- containerPath = "/."
- }
-
- // Wildcards are not allowed.
- // TODO: it's now technically possible wildcards.
- // We may consider enabling support in the future.
- if strings.Contains(containerPath, "*") {
- return nil, "", "", copy.ErrENOENT
- }
-
+// Calls either statOnHost or statInsideMount depending on whether the
+// container is running
+func (c *Container) statInContainer(mountPoint string, containerPath string) (*copier.StatForItem, string, string, error) {
if c.state.State == define.ContainerStateRunning {
// If the container is running, we need to join it's mount namespace
// and stat there.
- statInfo, resolvedRoot, resolvedPath, statErr = c.statInsideMount(containerPath)
- } else {
- // If the container is NOT running, we need to resolve the path
- // on the host.
- statInfo, resolvedRoot, resolvedPath, statErr = c.statOnHost(containerMountPoint, containerPath)
- }
-
- if statErr != nil {
- if statInfo == nil {
- return nil, "", "", statErr
- }
- // Not all errors from secureStat map to ErrNotExist, so we
- // have to look into the error string. Turning it into an
- // ENOENT let's the API handlers return the correct status code
- // which is crucial for the remote client.
- if os.IsNotExist(statErr) || strings.Contains(statErr.Error(), "o such file or directory") {
- statErr = copy.ErrENOENT
- }
- }
-
- switch {
- case statInfo.IsSymlink:
- // Symlinks are already evaluated and always relative to the
- // container's mount point.
- absContainerPath = statInfo.ImmediateTarget
- case strings.HasPrefix(resolvedPath, containerMountPoint):
- // If the path is on the container's mount point, strip it off.
- absContainerPath = strings.TrimPrefix(resolvedPath, containerMountPoint)
- absContainerPath = filepath.Join("/", absContainerPath)
- default:
- // No symlink and not on the container's mount point, so let's
- // move it back to the original input. It must have evaluated
- // to a volume or bind mount but we cannot return host paths.
- absContainerPath = containerPath
+ return c.statInsideMount(containerPath)
}
-
- // Preserve the base path as specified by the user. The `filepath`
- // packages likes to remove trailing slashes and dots that are crucial
- // to the copy logic.
- absContainerPath = copy.PreserveBasePath(containerPath, absContainerPath)
- resolvedPath = copy.PreserveBasePath(containerPath, resolvedPath)
-
- info := &define.FileInfo{
- IsDir: statInfo.IsDir,
- Name: filepath.Base(absContainerPath),
- Size: statInfo.Size,
- Mode: statInfo.Mode,
- ModTime: statInfo.ModTime,
- LinkTarget: absContainerPath,
- }
-
- return info, resolvedRoot, resolvedPath, statErr
-}
-
-// secureStat extracts file info for path in a chroot'ed environment in root.
-func secureStat(root string, path string) (*copier.StatForItem, error) {
- var glob string
- var err error
-
- // If root and path are equal, then dir must be empty and the glob must
- // be ".".
- if filepath.Clean(root) == filepath.Clean(path) {
- glob = "."
- } else {
- glob, err = filepath.Rel(root, path)
- if err != nil {
- return nil, err
- }
- }
-
- globStats, err := copier.Stat(root, "", copier.StatOptions{}, []string{glob})
- if err != nil {
- return nil, err
- }
-
- if len(globStats) != 1 {
- return nil, fmt.Errorf("internal error: secureStat: expected 1 item but got %d", len(globStats))
- }
- if len(globStats) != 1 {
- return nil, fmt.Errorf("internal error: secureStat: expected 1 result but got %d", len(globStats[0].Results))
- }
-
- // NOTE: the key in the map differ from `glob` when hitting symlink.
- // Hence, we just take the first (and only) key/value pair.
- for _, stat := range globStats[0].Results {
- var statErr error
- if stat.Error != "" {
- statErr = errors.New(stat.Error)
- }
- // If necessary evaluate the symlink
- if stat.IsSymlink {
- target, err := copier.Eval(root, path, copier.EvalOptions{})
- if err != nil {
- return nil, fmt.Errorf("evaluating symlink in container: %w", err)
- }
- // Need to make sure the symlink is relative to the root!
- target = strings.TrimPrefix(target, root)
- target = filepath.Join("/", target)
- stat.ImmediateTarget = target
- }
- return stat, statErr
- }
-
- // Nothing found!
- return nil, copy.ErrENOENT
+ // If the container is NOT running, we need to resolve the path
+ // on the host.
+ return c.statOnHost(mountPoint, containerPath)
}
diff --git a/libpod/container_stat_unsupported.go b/libpod/container_stat_unsupported.go
index 2f1acd44d..e88b88bb1 100644
--- a/libpod/container_stat_unsupported.go
+++ b/libpod/container_stat_unsupported.go
@@ -1,5 +1,5 @@
-//go:build !linux
-// +build !linux
+//go:build !linux && !freebsd
+// +build !linux,!freebsd
package libpod
diff --git a/libpod/events/logfile.go b/libpod/events/logfile.go
index d749a0d4d..bb0f461e3 100644
--- a/libpod/events/logfile.go
+++ b/libpod/events/logfile.go
@@ -9,7 +9,6 @@ import (
"errors"
"fmt"
"io"
- "io/ioutil"
"os"
"path"
"path/filepath"
@@ -204,11 +203,11 @@ func truncate(filePath string) error {
size := origFinfo.Size()
threshold := size / 2
- tmp, err := ioutil.TempFile(path.Dir(filePath), "")
+ tmp, err := os.CreateTemp(path.Dir(filePath), "")
if err != nil {
// Retry in /tmp in case creating a tmp file in the same
// directory has failed.
- tmp, err = ioutil.TempFile("", "")
+ tmp, err = os.CreateTemp("", "")
if err != nil {
return err
}
diff --git a/libpod/events/logfile_test.go b/libpod/events/logfile_test.go
index 302533c12..50141168e 100644
--- a/libpod/events/logfile_test.go
+++ b/libpod/events/logfile_test.go
@@ -1,7 +1,6 @@
package events
import (
- "io/ioutil"
"os"
"testing"
@@ -29,7 +28,7 @@ func TestRotateLog(t *testing.T) {
}
for _, test := range tests {
- tmp, err := ioutil.TempFile("", "log-rotation-")
+ tmp, err := os.CreateTemp("", "log-rotation-")
require.NoError(t, err)
defer os.Remove(tmp.Name())
defer tmp.Close()
@@ -84,7 +83,7 @@ func TestTruncationOutput(t *testing.T) {
10
`
// Create dummy file
- tmp, err := ioutil.TempFile("", "log-rotation")
+ tmp, err := os.CreateTemp("", "log-rotation")
require.NoError(t, err)
defer os.Remove(tmp.Name())
defer tmp.Close()
@@ -94,11 +93,11 @@ func TestTruncationOutput(t *testing.T) {
require.NoError(t, err)
// Truncate the file
- beforeTruncation, err := ioutil.ReadFile(tmp.Name())
+ beforeTruncation, err := os.ReadFile(tmp.Name())
require.NoError(t, err)
err = truncate(tmp.Name())
require.NoError(t, err)
- afterTruncation, err := ioutil.ReadFile(tmp.Name())
+ afterTruncation, err := os.ReadFile(tmp.Name())
require.NoError(t, err)
// Test if rotation was successful
@@ -116,9 +115,9 @@ func TestRenameLog(t *testing.T) {
5
`
// Create two dummy files
- source, err := ioutil.TempFile("", "removing")
+ source, err := os.CreateTemp("", "removing")
require.NoError(t, err)
- target, err := ioutil.TempFile("", "renaming")
+ target, err := os.CreateTemp("", "renaming")
require.NoError(t, err)
// Write to source dummy file
@@ -126,11 +125,11 @@ func TestRenameLog(t *testing.T) {
require.NoError(t, err)
// Rename the files
- beforeRename, err := ioutil.ReadFile(source.Name())
+ beforeRename, err := os.ReadFile(source.Name())
require.NoError(t, err)
err = renameLog(source.Name(), target.Name())
require.NoError(t, err)
- afterRename, err := ioutil.ReadFile(target.Name())
+ afterRename, err := os.ReadFile(target.Name())
require.NoError(t, err)
// Test if renaming was successful
diff --git a/libpod/healthcheck.go b/libpod/healthcheck.go
index e835af9f0..a589f2787 100644
--- a/libpod/healthcheck.go
+++ b/libpod/healthcheck.go
@@ -5,7 +5,6 @@ import (
"context"
"errors"
"fmt"
- "io/ioutil"
"os"
"path/filepath"
"strings"
@@ -208,7 +207,7 @@ func (c *Container) updateHealthStatus(status string) error {
if err != nil {
return fmt.Errorf("unable to marshall healthchecks for writing status: %w", err)
}
- return ioutil.WriteFile(c.healthCheckLogPath(), newResults, 0700)
+ return os.WriteFile(c.healthCheckLogPath(), newResults, 0700)
}
// UpdateHealthCheckLog parses the health check results and writes the log
@@ -242,7 +241,7 @@ func (c *Container) updateHealthCheckLog(hcl define.HealthCheckLog, inStartPerio
if err != nil {
return fmt.Errorf("unable to marshall healthchecks for writing: %w", err)
}
- return ioutil.WriteFile(c.healthCheckLogPath(), newResults, 0700)
+ return os.WriteFile(c.healthCheckLogPath(), newResults, 0700)
}
// HealthCheckLogPath returns the path for where the health check log is
@@ -259,7 +258,7 @@ func (c *Container) getHealthCheckLog() (define.HealthCheckResults, error) {
if _, err := os.Stat(c.healthCheckLogPath()); os.IsNotExist(err) {
return healthCheck, nil
}
- b, err := ioutil.ReadFile(c.healthCheckLogPath())
+ b, err := os.ReadFile(c.healthCheckLogPath())
if err != nil {
return healthCheck, fmt.Errorf("failed to read health check log file: %w", err)
}
diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go
index e27ec8e9d..6ea56ade5 100644
--- a/libpod/networking_linux.go
+++ b/libpod/networking_linux.go
@@ -8,7 +8,6 @@ import (
"crypto/sha256"
"errors"
"fmt"
- "io/ioutil"
"net"
"os"
"os/exec"
@@ -303,7 +302,7 @@ func (r *RootlessNetNS) Cleanup(runtime *Runtime) error {
if err != nil {
logrus.Error(err)
}
- b, err := ioutil.ReadFile(r.getPath(rootlessNetNsSilrp4netnsPidFile))
+ b, err := os.ReadFile(r.getPath(rootlessNetNsSilrp4netnsPidFile))
if err == nil {
var i int
i, err = strconv.Atoi(string(b))
@@ -445,7 +444,7 @@ func (r *Runtime) GetRootlessNetNs(new bool) (*RootlessNetNS, error) {
// create pid file for the slirp4netns process
// this is need to kill the process in the cleanup
pid := strconv.Itoa(cmd.Process.Pid)
- err = ioutil.WriteFile(filepath.Join(rootlessNetNsDir, rootlessNetNsSilrp4netnsPidFile), []byte(pid), 0700)
+ err = os.WriteFile(filepath.Join(rootlessNetNsDir, rootlessNetNsSilrp4netnsPidFile), []byte(pid), 0700)
if err != nil {
return nil, fmt.Errorf("unable to write rootless-netns slirp4netns pid file: %w", err)
}
diff --git a/libpod/networking_machine.go b/libpod/networking_machine.go
index 7b8eb94df..dce335c0a 100644
--- a/libpod/networking_machine.go
+++ b/libpod/networking_machine.go
@@ -6,7 +6,6 @@ import (
"errors"
"fmt"
"io"
- "io/ioutil"
"net"
"net/http"
"strconv"
@@ -109,7 +108,7 @@ func makeMachineRequest(ctx context.Context, client *http.Client, url string, bu
}
func annotateGvproxyResponseError(r io.Reader) error {
- b, err := ioutil.ReadAll(r)
+ b, err := io.ReadAll(r)
if err == nil && len(b) > 0 {
return fmt.Errorf("something went wrong with the request: %q", string(b))
}
diff --git a/libpod/networking_slirp4netns.go b/libpod/networking_slirp4netns.go
index d4ec9082b..4026b6b48 100644
--- a/libpod/networking_slirp4netns.go
+++ b/libpod/networking_slirp4netns.go
@@ -8,7 +8,6 @@ import (
"errors"
"fmt"
"io"
- "io/ioutil"
"net"
"os"
"os/exec"
@@ -324,7 +323,7 @@ func (r *Runtime) setupSlirp4netns(ctr *Container, netns ns.NetNS) error {
// correct value assigned so DAD is disabled for it
// Also make sure to change this value back to the original after slirp4netns
// is ready in case users rely on this sysctl.
- orgValue, err := ioutil.ReadFile(ipv6ConfDefaultAcceptDadSysctl)
+ orgValue, err := os.ReadFile(ipv6ConfDefaultAcceptDadSysctl)
if err != nil {
netnsReadyWg.Done()
// on ipv6 disabled systems the sysctl does not exists
@@ -334,7 +333,7 @@ func (r *Runtime) setupSlirp4netns(ctr *Container, netns ns.NetNS) error {
}
return err
}
- err = ioutil.WriteFile(ipv6ConfDefaultAcceptDadSysctl, []byte("0"), 0644)
+ err = os.WriteFile(ipv6ConfDefaultAcceptDadSysctl, []byte("0"), 0644)
netnsReadyWg.Done()
if err != nil {
return err
@@ -342,7 +341,7 @@ func (r *Runtime) setupSlirp4netns(ctr *Container, netns ns.NetNS) error {
// wait until slirp4nets is ready before resetting this value
slirpReadyWg.Wait()
- return ioutil.WriteFile(ipv6ConfDefaultAcceptDadSysctl, orgValue, 0644)
+ return os.WriteFile(ipv6ConfDefaultAcceptDadSysctl, orgValue, 0644)
})
if err != nil {
logrus.Warnf("failed to set net.ipv6.conf.default.accept_dad sysctl: %v", err)
@@ -486,7 +485,7 @@ func waitForSync(syncR *os.File, cmd *exec.Cmd, logFile io.ReadSeeker, timeout t
if _, err := logFile.Seek(0, 0); err != nil {
logrus.Errorf("Could not seek log file: %q", err)
}
- logContent, err := ioutil.ReadAll(logFile)
+ logContent, err := io.ReadAll(logFile)
if err != nil {
return fmt.Errorf("%s failed: %w", prog, err)
}
@@ -730,7 +729,7 @@ func (c *Container) reloadRootlessRLKPortMapping() error {
if err != nil {
return fmt.Errorf("port reloading failed: %w", err)
}
- b, err := ioutil.ReadAll(conn)
+ b, err := io.ReadAll(conn)
if err != nil {
return fmt.Errorf("port reloading failed: %w", err)
}
diff --git a/libpod/oci_conmon_common.go b/libpod/oci_conmon_common.go
index 53dddd064..cbdbad02d 100644
--- a/libpod/oci_conmon_common.go
+++ b/libpod/oci_conmon_common.go
@@ -10,7 +10,6 @@ import (
"errors"
"fmt"
"io"
- "io/ioutil"
"net"
"net/http"
"os"
@@ -232,7 +231,7 @@ func (r *ConmonOCIRuntime) UpdateContainerStatus(ctr *Container) error {
}
if err := cmd.Start(); err != nil {
- out, err2 := ioutil.ReadAll(errPipe)
+ out, err2 := io.ReadAll(errPipe)
if err2 != nil {
return fmt.Errorf("getting container %s state: %w", ctr.ID(), err)
}
@@ -254,7 +253,7 @@ func (r *ConmonOCIRuntime) UpdateContainerStatus(ctr *Container) error {
if err := errPipe.Close(); err != nil {
return err
}
- out, err := ioutil.ReadAll(outPipe)
+ out, err := io.ReadAll(outPipe)
if err != nil {
return fmt.Errorf("reading stdout: %s: %w", ctr.ID(), err)
}
@@ -335,7 +334,7 @@ func generateResourceFile(res *spec.LinuxResources) (string, []string, error) {
return "", flags, nil
}
- f, err := ioutil.TempFile("", "podman")
+ f, err := os.CreateTemp("", "podman")
if err != nil {
return "", nil, err
}
@@ -1398,7 +1397,7 @@ func newPipe() (*os.File, *os.File, error) {
func readConmonPidFile(pidFile string) (int, error) {
// Let's try reading the Conmon pid at the same time.
if pidFile != "" {
- contents, err := ioutil.ReadFile(pidFile)
+ contents, err := os.ReadFile(pidFile)
if err != nil {
return -1, err
}
@@ -1447,7 +1446,7 @@ func readConmonPipeData(runtimeName string, pipe *os.File, ociLog string) (int,
case ss := <-ch:
if ss.err != nil {
if ociLog != "" {
- ociLogData, err := ioutil.ReadFile(ociLog)
+ ociLogData, err := os.ReadFile(ociLog)
if err == nil {
var ociErr ociError
if err := json.Unmarshal(ociLogData, &ociErr); err == nil {
@@ -1460,7 +1459,7 @@ func readConmonPipeData(runtimeName string, pipe *os.File, ociLog string) (int,
logrus.Debugf("Received: %d", ss.si.Data)
if ss.si.Data < 0 {
if ociLog != "" {
- ociLogData, err := ioutil.ReadFile(ociLog)
+ ociLogData, err := os.ReadFile(ociLog)
if err == nil {
var ociErr ociError
if err := json.Unmarshal(ociLogData, &ociErr); err == nil {
diff --git a/libpod/oci_conmon_exec_common.go b/libpod/oci_conmon_exec_common.go
index e5080942b..24113bd8d 100644
--- a/libpod/oci_conmon_exec_common.go
+++ b/libpod/oci_conmon_exec_common.go
@@ -3,7 +3,6 @@ package libpod
import (
"errors"
"fmt"
- "io/ioutil"
"net/http"
"os"
"os/exec"
@@ -665,7 +664,7 @@ func attachExecHTTP(c *Container, sessionID string, r *http.Request, w http.Resp
// prepareProcessExec returns the path of the process.json used in runc exec -p
// caller is responsible to close the returned *os.File if needed.
func (c *Container) prepareProcessExec(options *ExecOptions, env []string, sessionID string) (*os.File, error) {
- f, err := ioutil.TempFile(c.execBundlePath(sessionID), "exec-process-")
+ f, err := os.CreateTemp(c.execBundlePath(sessionID), "exec-process-")
if err != nil {
return nil, err
}
@@ -764,7 +763,7 @@ func (c *Container) prepareProcessExec(options *ExecOptions, env []string, sessi
return nil, err
}
- if err := ioutil.WriteFile(f.Name(), processJSON, 0644); err != nil {
+ if err := os.WriteFile(f.Name(), processJSON, 0644); err != nil {
return nil, err
}
return f, nil
diff --git a/libpod/plugin/volume_api.go b/libpod/plugin/volume_api.go
index 522895798..c595937ae 100644
--- a/libpod/plugin/volume_api.go
+++ b/libpod/plugin/volume_api.go
@@ -5,7 +5,7 @@ import (
"context"
"errors"
"fmt"
- "io/ioutil"
+ "io"
"net"
"net/http"
"os"
@@ -95,7 +95,7 @@ func validatePlugin(newPlugin *VolumePlugin) error {
}
// Read and decode the body so we can tell if this is a volume plugin.
- respBytes, err := ioutil.ReadAll(resp.Body)
+ respBytes, err := io.ReadAll(resp.Body)
if err != nil {
return fmt.Errorf("reading activation response body from plugin %s: %w", newPlugin.Name, err)
}
@@ -252,7 +252,7 @@ func (p *VolumePlugin) handleErrorResponse(resp *http.Response, endpoint, volNam
// Let's interpret anything other than 200 as an error.
// If there isn't an error, don't even bother decoding the response.
if resp.StatusCode != 200 {
- errResp, err := ioutil.ReadAll(resp.Body)
+ errResp, err := io.ReadAll(resp.Body)
if err != nil {
return fmt.Errorf("reading response body from volume plugin %s: %w", p.Name, err)
}
@@ -307,7 +307,7 @@ func (p *VolumePlugin) ListVolumes() ([]*volume.Volume, error) {
return nil, err
}
- volumeRespBytes, err := ioutil.ReadAll(resp.Body)
+ volumeRespBytes, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("reading response body from volume plugin %s: %w", p.Name, err)
}
@@ -342,7 +342,7 @@ func (p *VolumePlugin) GetVolume(req *volume.GetRequest) (*volume.Volume, error)
return nil, err
}
- getRespBytes, err := ioutil.ReadAll(resp.Body)
+ getRespBytes, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("reading response body from volume plugin %s: %w", p.Name, err)
}
@@ -398,7 +398,7 @@ func (p *VolumePlugin) GetVolumePath(req *volume.PathRequest) (string, error) {
return "", err
}
- pathRespBytes, err := ioutil.ReadAll(resp.Body)
+ pathRespBytes, err := io.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("reading response body from volume plugin %s: %w", p.Name, err)
}
@@ -435,7 +435,7 @@ func (p *VolumePlugin) MountVolume(req *volume.MountRequest) (string, error) {
return "", err
}
- mountRespBytes, err := ioutil.ReadAll(resp.Body)
+ mountRespBytes, err := io.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("reading response body from volume plugin %s: %w", p.Name, err)
}
diff --git a/libpod/runtime_img.go b/libpod/runtime_img.go
index dacbd752f..87b77c3eb 100644
--- a/libpod/runtime_img.go
+++ b/libpod/runtime_img.go
@@ -5,7 +5,6 @@ import (
"errors"
"fmt"
"io"
- "io/ioutil"
"os"
buildahDefine "github.com/containers/buildah/define"
@@ -105,7 +104,7 @@ func (r *Runtime) Build(ctx context.Context, options buildahDefine.BuildOptions,
// DownloadFromFile reads all of the content from the reader and temporarily
// saves in it $TMPDIR/importxyz, which is deleted after the image is imported
func DownloadFromFile(reader *os.File) (string, error) {
- outFile, err := ioutil.TempFile(util.Tmpdir(), "import")
+ outFile, err := os.CreateTemp(util.Tmpdir(), "import")
if err != nil {
return "", fmt.Errorf("creating file: %w", err)
}
diff --git a/libpod/runtime_migrate.go b/libpod/runtime_migrate.go
index 36901d4d0..df1a1f1cb 100644
--- a/libpod/runtime_migrate.go
+++ b/libpod/runtime_migrate.go
@@ -5,7 +5,6 @@ package libpod
import (
"fmt"
- "io/ioutil"
"os"
"path/filepath"
"strconv"
@@ -23,7 +22,7 @@ func (r *Runtime) stopPauseProcess() error {
if err != nil {
return fmt.Errorf("could not get pause process pid file path: %w", err)
}
- data, err := ioutil.ReadFile(pausePidPath)
+ data, err := os.ReadFile(pausePidPath)
if err != nil {
if os.IsNotExist(err) {
return nil
diff --git a/libpod/state_test.go b/libpod/state_test.go
index 3c1fe8f63..7664f7c00 100644
--- a/libpod/state_test.go
+++ b/libpod/state_test.go
@@ -1,7 +1,6 @@
package libpod
import (
- "io/ioutil"
"os"
"path/filepath"
"strings"
@@ -35,7 +34,7 @@ var (
// Get an empty BoltDB state for use in tests
func getEmptyBoltState() (_ State, _ string, _ lock.Manager, retErr error) {
- tmpDir, err := ioutil.TempDir("", tmpDirPrefix)
+ tmpDir, err := os.MkdirTemp("", tmpDirPrefix)
if err != nil {
return nil, "", nil, err
}