summaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
Diffstat (limited to 'pkg')
-rw-r--r--pkg/api/handlers/compat/containers_archive.go11
-rw-r--r--pkg/bindings/containers/archive.go12
-rw-r--r--pkg/bindings/containers/types.go8
-rw-r--r--pkg/bindings/containers/types_copy_options.go37
-rw-r--r--pkg/bindings/internal/util/util.go10
-rw-r--r--pkg/domain/entities/containers.go7
-rw-r--r--pkg/domain/entities/engine_container.go2
-rw-r--r--pkg/domain/infra/abi/archive.go4
-rw-r--r--pkg/domain/infra/tunnel/containers.go4
-rw-r--r--pkg/machine/qemu/machine.go22
-rw-r--r--pkg/rootless/rootless_linux.go8
-rw-r--r--pkg/servicereaper/service.go64
12 files changed, 169 insertions, 20 deletions
diff --git a/pkg/api/handlers/compat/containers_archive.go b/pkg/api/handlers/compat/containers_archive.go
index e119dc7cb..a9d74e5f4 100644
--- a/pkg/api/handlers/compat/containers_archive.go
+++ b/pkg/api/handlers/compat/containers_archive.go
@@ -9,6 +9,7 @@ import (
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
"github.com/containers/podman/v3/pkg/copy"
+ "github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/domain/infra/abi"
"github.com/gorilla/schema"
"github.com/pkg/errors"
@@ -92,11 +93,13 @@ func handleHeadAndGet(w http.ResponseWriter, r *http.Request, decoder *schema.De
func handlePut(w http.ResponseWriter, r *http.Request, decoder *schema.Decoder, runtime *libpod.Runtime) {
query := struct {
- Path string `schema:"path"`
+ Path string `schema:"path"`
+ Chown bool `schema:"copyUIDGID"`
// TODO handle params below
NoOverwriteDirNonDir bool `schema:"noOverwriteDirNonDir"`
- CopyUIDGID bool `schema:"copyUIDGID"`
- }{}
+ }{
+ Chown: utils.IsLibpodRequest(r), // backward compatibility
+ }
err := decoder.Decode(&query, r.URL.Query())
if err != nil {
@@ -107,7 +110,7 @@ func handlePut(w http.ResponseWriter, r *http.Request, decoder *schema.Decoder,
containerName := utils.GetName(r)
containerEngine := abi.ContainerEngine{Libpod: runtime}
- copyFunc, err := containerEngine.ContainerCopyFromArchive(r.Context(), containerName, query.Path, r.Body)
+ copyFunc, err := containerEngine.ContainerCopyFromArchive(r.Context(), containerName, query.Path, r.Body, entities.CopyOptions{Chown: query.Chown})
if errors.Cause(err) == define.ErrNoSuchCtr || os.IsNotExist(err) {
// 404 is returned for an absent container and path. The
// clients must deal with it accordingly.
diff --git a/pkg/bindings/containers/archive.go b/pkg/bindings/containers/archive.go
index 0178f63c3..52b73662b 100644
--- a/pkg/bindings/containers/archive.go
+++ b/pkg/bindings/containers/archive.go
@@ -50,11 +50,21 @@ func Stat(ctx context.Context, nameOrID string, path string) (*entities.Containe
}
func CopyFromArchive(ctx context.Context, nameOrID string, path string, reader io.Reader) (entities.ContainerCopyFunc, error) {
+ return CopyFromArchiveWithOptions(ctx, nameOrID, path, reader, nil)
+}
+
+// CopyFromArchiveWithOptions FIXME: remove this function and make CopyFromArchive accept the option as the last parameter in podman 4.0
+func CopyFromArchiveWithOptions(ctx context.Context, nameOrID string, path string, reader io.Reader, options *CopyOptions) (entities.ContainerCopyFunc, error) {
conn, err := bindings.GetClient(ctx)
if err != nil {
return nil, err
}
- params := url.Values{}
+
+ params, err := options.ToParams()
+ if err != nil {
+ return nil, err
+ }
+
params.Set("path", path)
return func() error {
diff --git a/pkg/bindings/containers/types.go b/pkg/bindings/containers/types.go
index 80f382926..1058c7a48 100644
--- a/pkg/bindings/containers/types.go
+++ b/pkg/bindings/containers/types.go
@@ -256,3 +256,11 @@ type ExistsOptions struct {
// External checks for containers created outside of Podman
External *bool
}
+
+//go:generate go run ../generator/generator.go CopyOptions
+// CopyOptions are options for copying to containers.
+type CopyOptions struct {
+ // If used with CopyFromArchive and set to true it will change ownership of files from the source tar archive
+ // to the primary uid/gid of the target container.
+ Chown *bool `schema:"copyUIDGID"`
+}
diff --git a/pkg/bindings/containers/types_copy_options.go b/pkg/bindings/containers/types_copy_options.go
new file mode 100644
index 000000000..12ad085fd
--- /dev/null
+++ b/pkg/bindings/containers/types_copy_options.go
@@ -0,0 +1,37 @@
+package containers
+
+import (
+ "net/url"
+
+ "github.com/containers/podman/v3/pkg/bindings/internal/util"
+)
+
+/*
+This file is generated automatically by go generate. Do not edit.
+*/
+
+// Changed
+func (o *CopyOptions) Changed(fieldName string) bool {
+ return util.Changed(o, fieldName)
+}
+
+// ToParams
+func (o *CopyOptions) ToParams() (url.Values, error) {
+ return util.ToParams(o)
+}
+
+// WithChown
+func (o *CopyOptions) WithChown(value bool) *CopyOptions {
+ v := &value
+ o.Chown = v
+ return o
+}
+
+// GetChown
+func (o *CopyOptions) GetChown() bool {
+ var chown bool
+ if o.Chown == nil {
+ return chown
+ }
+ return *o.Chown
+}
diff --git a/pkg/bindings/internal/util/util.go b/pkg/bindings/internal/util/util.go
index ef93d6e25..bcf6959f2 100644
--- a/pkg/bindings/internal/util/util.go
+++ b/pkg/bindings/internal/util/util.go
@@ -72,14 +72,18 @@ func ToParams(o interface{}) (url.Values, error) {
if reflect.Ptr == f.Kind() {
f = f.Elem()
}
+ paramName := fieldName
+ if pn, ok := sType.Field(i).Tag.Lookup("schema"); ok {
+ paramName = pn
+ }
switch {
case IsSimpleType(f):
- params.Set(fieldName, SimpleTypeToParam(f))
+ params.Set(paramName, SimpleTypeToParam(f))
case f.Kind() == reflect.Slice:
for i := 0; i < f.Len(); i++ {
elem := f.Index(i)
if IsSimpleType(elem) {
- params.Add(fieldName, SimpleTypeToParam(elem))
+ params.Add(paramName, SimpleTypeToParam(elem))
} else {
return nil, errors.New("slices must contain only simple types")
}
@@ -95,7 +99,7 @@ func ToParams(o interface{}) (url.Values, error) {
return nil, err
}
- params.Set(fieldName, s)
+ params.Set(paramName, s)
}
}
return params, nil
diff --git a/pkg/domain/entities/containers.go b/pkg/domain/entities/containers.go
index 8ed9b9b61..302b35a47 100644
--- a/pkg/domain/entities/containers.go
+++ b/pkg/domain/entities/containers.go
@@ -160,6 +160,13 @@ type CommitOptions struct {
Writer io.Writer
}
+type CopyOptions struct {
+ // If used with ContainerCopyFromArchive and set to true
+ // it will change ownership of files from the source tar archive
+ // to the primary uid/gid of the destination container.
+ Chown bool
+}
+
type CommitReport struct {
Id string //nolint
}
diff --git a/pkg/domain/entities/engine_container.go b/pkg/domain/entities/engine_container.go
index ec17d7ce3..28e5160db 100644
--- a/pkg/domain/entities/engine_container.go
+++ b/pkg/domain/entities/engine_container.go
@@ -20,7 +20,7 @@ type ContainerEngine interface {
ContainerCheckpoint(ctx context.Context, namesOrIds []string, options CheckpointOptions) ([]*CheckpointReport, error)
ContainerCleanup(ctx context.Context, namesOrIds []string, options ContainerCleanupOptions) ([]*ContainerCleanupReport, error)
ContainerCommit(ctx context.Context, nameOrID string, options CommitOptions) (*CommitReport, error)
- ContainerCopyFromArchive(ctx context.Context, nameOrID string, path string, reader io.Reader) (ContainerCopyFunc, error)
+ ContainerCopyFromArchive(ctx context.Context, nameOrID, path string, reader io.Reader, options CopyOptions) (ContainerCopyFunc, error)
ContainerCopyToArchive(ctx context.Context, nameOrID string, path string, writer io.Writer) (ContainerCopyFunc, error)
ContainerCreate(ctx context.Context, s *specgen.SpecGenerator) (*ContainerCreateReport, error)
ContainerExec(ctx context.Context, nameOrID string, options ExecOptions, streams define.AttachStreams) (int, error)
diff --git a/pkg/domain/infra/abi/archive.go b/pkg/domain/infra/abi/archive.go
index 2ea63aa5e..1a5bb6dc4 100644
--- a/pkg/domain/infra/abi/archive.go
+++ b/pkg/domain/infra/abi/archive.go
@@ -7,12 +7,12 @@ import (
"github.com/containers/podman/v3/pkg/domain/entities"
)
-func (ic *ContainerEngine) ContainerCopyFromArchive(ctx context.Context, nameOrID string, containerPath string, reader io.Reader) (entities.ContainerCopyFunc, error) {
+func (ic *ContainerEngine) ContainerCopyFromArchive(ctx context.Context, nameOrID, containerPath string, reader io.Reader, options entities.CopyOptions) (entities.ContainerCopyFunc, error) {
container, err := ic.Libpod.LookupContainer(nameOrID)
if err != nil {
return nil, err
}
- return container.CopyFromArchive(ctx, containerPath, reader)
+ return container.CopyFromArchive(ctx, containerPath, options.Chown, reader)
}
func (ic *ContainerEngine) ContainerCopyToArchive(ctx context.Context, nameOrID string, containerPath string, writer io.Writer) (entities.ContainerCopyFunc, error) {
diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go
index 1bee521cf..56315f46f 100644
--- a/pkg/domain/infra/tunnel/containers.go
+++ b/pkg/domain/infra/tunnel/containers.go
@@ -843,8 +843,8 @@ func (ic *ContainerEngine) ContainerPort(ctx context.Context, nameOrID string, o
return reports, nil
}
-func (ic *ContainerEngine) ContainerCopyFromArchive(ctx context.Context, nameOrID string, path string, reader io.Reader) (entities.ContainerCopyFunc, error) {
- return containers.CopyFromArchive(ic.ClientCtx, nameOrID, path, reader)
+func (ic *ContainerEngine) ContainerCopyFromArchive(ctx context.Context, nameOrID, path string, reader io.Reader, options entities.CopyOptions) (entities.ContainerCopyFunc, error) {
+ return containers.CopyFromArchiveWithOptions(ic.ClientCtx, nameOrID, path, reader, new(containers.CopyOptions).WithChown(options.Chown))
}
func (ic *ContainerEngine) ContainerCopyToArchive(ctx context.Context, nameOrID string, path string, writer io.Writer) (entities.ContainerCopyFunc, error) {
diff --git a/pkg/machine/qemu/machine.go b/pkg/machine/qemu/machine.go
index 22fb78a5c..42ae23c43 100644
--- a/pkg/machine/qemu/machine.go
+++ b/pkg/machine/qemu/machine.go
@@ -15,9 +15,8 @@ import (
"strings"
"time"
- "github.com/containers/podman/v3/pkg/rootless"
-
"github.com/containers/podman/v3/pkg/machine"
+ "github.com/containers/podman/v3/pkg/rootless"
"github.com/containers/podman/v3/utils"
"github.com/containers/storage/pkg/homedir"
"github.com/digitalocean/go-qemu/qmp"
@@ -248,7 +247,23 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
if err := v.startHostNetworking(); err != nil {
return errors.Errorf("unable to start host networking: %q", err)
}
+
+ rtPath, err := getRuntimeDir()
+ if err != nil {
+ return err
+ }
+
+ // If the temporary podman dir is not created, create it
+ podmanTempDir := filepath.Join(rtPath, "podman")
+ if _, err := os.Stat(podmanTempDir); os.IsNotExist(err) {
+ if mkdirErr := os.MkdirAll(podmanTempDir, 0755); mkdirErr != nil {
+ return err
+ }
+ }
qemuSocketPath, _, err := v.getSocketandPid()
+ if err != nil {
+ return err
+ }
for i := 0; i < 6; i++ {
qemuSocketConn, err = net.Dial("unix", qemuSocketPath)
@@ -258,9 +273,6 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
time.Sleep(wait)
wait++
}
- if err != nil {
- return err
- }
fd, err := qemuSocketConn.(*net.UnixConn).File()
if err != nil {
diff --git a/pkg/rootless/rootless_linux.go b/pkg/rootless/rootless_linux.go
index 6eff25eb9..f76eab0e3 100644
--- a/pkg/rootless/rootless_linux.go
+++ b/pkg/rootless/rootless_linux.go
@@ -268,7 +268,9 @@ func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (_ boo
}
if retErr != nil && pid > 0 {
if err := unix.Kill(pid, unix.SIGKILL); err != nil {
- logrus.Errorf("failed to kill %d", pid)
+ if err != unix.ESRCH {
+ logrus.Errorf("failed to cleanup process %d: %v", pid, err)
+ }
}
C.reexec_in_user_namespace_wait(C.int(pid), 0)
}
@@ -394,7 +396,9 @@ func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (_ boo
}
if err := unix.Kill(int(pidC), s.(unix.Signal)); err != nil {
- logrus.Errorf("failed to kill %d", int(pidC))
+ if err != unix.ESRCH {
+ logrus.Errorf("failed to propagate signal to child process %d: %v", int(pidC), err)
+ }
}
}
}()
diff --git a/pkg/servicereaper/service.go b/pkg/servicereaper/service.go
new file mode 100644
index 000000000..e9c4fe908
--- /dev/null
+++ b/pkg/servicereaper/service.go
@@ -0,0 +1,64 @@
+//+build linux
+
+package servicereaper
+
+import (
+ "os"
+ "os/signal"
+ "sync"
+ "syscall"
+
+ "github.com/sirupsen/logrus"
+)
+
+type service struct {
+ pidMap map[int]bool
+ mutex *sync.Mutex
+}
+
+var s = service{
+ pidMap: map[int]bool{},
+ mutex: &sync.Mutex{},
+}
+
+func AddPID(pid int) {
+ s.mutex.Lock()
+ s.pidMap[pid] = true
+ s.mutex.Unlock()
+}
+
+func Start() {
+ // create signal channel and only wait for SIGCHLD
+ sigc := make(chan os.Signal, 1)
+ signal.Notify(sigc, syscall.SIGCHLD)
+ // wait and reap in an extra goroutine
+ go reaper(sigc)
+}
+
+func reaper(sigc chan os.Signal) {
+ for {
+ // block until we receive SIGCHLD
+ <-sigc
+ s.mutex.Lock()
+ for pid := range s.pidMap {
+ var status syscall.WaitStatus
+ waitpid, err := syscall.Wait4(pid, &status, syscall.WNOHANG, nil)
+ if err != nil {
+ // do not log error for ECHILD
+ if err != syscall.ECHILD {
+ logrus.Warnf("wait for pid %d failed: %v ", pid, err)
+ }
+ delete(s.pidMap, pid)
+ continue
+ }
+ // if pid == 0 nothing happened
+ if waitpid == 0 {
+ continue
+ }
+ if status.Exited() {
+ delete(s.pidMap, pid)
+ }
+ }
+ s.mutex.Unlock()
+ }
+}