From 4e2d18db903e19c6cb56d75da0f69e42abe64c47 Mon Sep 17 00:00:00 2001
From: Matej Vasek <mvasek@redhat.com>
Date: Wed, 4 Nov 2020 20:18:02 +0100
Subject: Implement containers/{id or name}/archive

Signed-off-by: Matej Vasek <mvasek@redhat.com>
---
 pkg/api/handlers/compat/containers_archive.go | 341 +++++++++++++++++++++++++-
 1 file changed, 337 insertions(+), 4 deletions(-)

(limited to 'pkg/api/handlers/compat/containers_archive.go')

diff --git a/pkg/api/handlers/compat/containers_archive.go b/pkg/api/handlers/compat/containers_archive.go
index 293a17e0f..f42a821cd 100644
--- a/pkg/api/handlers/compat/containers_archive.go
+++ b/pkg/api/handlers/compat/containers_archive.go
@@ -1,12 +1,345 @@
 package compat
 
 import (
-	"errors"
-	"net/http"
-
+	"bytes"
+	"encoding/base64"
+	"encoding/json"
+	"fmt"
+	"github.com/containers/buildah/copier"
+	"github.com/containers/buildah/pkg/chrootuser"
+	"github.com/containers/podman/v2/libpod"
+	"github.com/containers/podman/v2/libpod/define"
 	"github.com/containers/podman/v2/pkg/api/handlers/utils"
+	"github.com/containers/storage/pkg/idtools"
+	"github.com/opencontainers/runtime-spec/specs-go"
+	"path/filepath"
+	"strings"
+
+	"github.com/gorilla/schema"
+	"github.com/pkg/errors"
+	"github.com/sirupsen/logrus"
+	"net/http"
+	"os"
+	"time"
 )
 
 func Archive(w http.ResponseWriter, r *http.Request) {
-	utils.Error(w, "not implemented", http.StatusNotImplemented, errors.New("not implemented"))
+	decoder := r.Context().Value("decoder").(*schema.Decoder)
+	runtime := r.Context().Value("runtime").(*libpod.Runtime)
+
+	switch r.Method {
+	case http.MethodPut:
+		handlePut(w, r, decoder, runtime)
+	case http.MethodGet, http.MethodHead:
+		handleHeadOrGet(w, r, decoder, runtime)
+	default:
+		utils.Error(w, fmt.Sprintf("not implemented, method: %v", r.Method), http.StatusNotImplemented, errors.New(fmt.Sprintf("not implemented, method: %v", r.Method)))
+	}
+}
+
+func handleHeadOrGet(w http.ResponseWriter, r *http.Request, decoder *schema.Decoder, runtime *libpod.Runtime) {
+	query := struct {
+		Path string `schema:"path"`
+	}{}
+
+	err := decoder.Decode(&query, r.URL.Query())
+	if err != nil {
+		utils.Error(w, "Bad Request.", http.StatusBadRequest, errors.Wrap(err, "couldn't decode the query"))
+		return
+	}
+	if query.Path == "" {
+		utils.Error(w, "Bad Request.", http.StatusBadRequest, errors.New("missing `path` parameter"))
+		return
+	}
+
+	containerName := utils.GetName(r)
+
+	ctr, err := runtime.LookupContainer(containerName)
+	if errors.Cause(err) == define.ErrNoSuchCtr {
+		utils.Error(w, "Not found.", http.StatusNotFound, errors.Wrap(err, "the container doesn't exists"))
+		return
+	} else if err != nil {
+		utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err)
+		return
+	}
+	mountPoint, err := ctr.Mount()
+	if err != nil {
+		utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to mount the container"))
+		return
+	}
+	defer func() {
+		if err := ctr.Unmount(true); err != nil {
+			logrus.Warnf("failed to unmount container %s: %q", containerName, err)
+		}
+	}()
+
+	opts := copier.StatOptions{}
+
+	mountPoint, path, err := fixUpMountPointAndPath(runtime, ctr, mountPoint, query.Path)
+	if err != nil {
+		utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err)
+		return
+	}
+
+	stats, err := copier.Stat(mountPoint, "", opts, []string{filepath.Join(mountPoint, path)})
+	if err != nil {
+		utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to get stats about file"))
+		return
+	}
+	if len(stats) <= 0 || len(stats[0].Globbed) <= 0 {
+		errs := make([]string, 0, len(stats))
+		for _, stat := range stats {
+			if stat.Error != "" {
+				errs = append(errs, stat.Error)
+			}
+		}
+		utils.Error(w, "Not found.", http.StatusNotFound, fmt.Errorf("file doesn't exist (errs: %q)", strings.Join(errs, ";")))
+		return
+	}
+
+	statHeader, err := statsToHeader(stats[0].Results[stats[0].Globbed[0]])
+	if err != nil {
+		utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err)
+		return
+	}
+
+	w.Header().Add("X-Docker-Container-Path-Stat", statHeader)
+
+	if r.Method == http.MethodGet {
+		idMappingOpts, err := ctr.IDMappings()
+		if err != nil {
+			utils.Error(w, "Not found.", http.StatusInternalServerError,
+				errors.Wrapf(err, "error getting IDMappingOptions"))
+			return
+		}
+		destOwner := idtools.IDPair{UID: os.Getuid(), GID: os.Getgid()}
+
+		opts := copier.GetOptions{
+			UIDMap:             idMappingOpts.UIDMap,
+			GIDMap:             idMappingOpts.GIDMap,
+			ChownDirs:          &destOwner,
+			ChownFiles:         &destOwner,
+			KeepDirectoryNames: true,
+		}
+
+		w.WriteHeader(http.StatusOK)
+		err = copier.Get(mountPoint, "", opts, []string{filepath.Join(mountPoint, path)}, w)
+		if err != nil {
+			logrus.Error(errors.Wrapf(err, "failed to copy from the %s container path %s", containerName, query.Path))
+			return
+		}
+	} else {
+		w.WriteHeader(http.StatusOK)
+	}
+
+}
+
+func handlePut(w http.ResponseWriter, r *http.Request, decoder *schema.Decoder, runtime *libpod.Runtime) {
+	query := struct {
+		Path string `schema:"path"`
+		// TODO handle params below
+		NoOverwriteDirNonDir bool `schema:"noOverwriteDirNonDir"`
+		CopyUIDGID           bool `schema:"copyUIDGID"`
+	}{}
+
+	err := decoder.Decode(&query, r.URL.Query())
+	if err != nil {
+		utils.Error(w, "Bad Request.", http.StatusBadRequest, errors.Wrap(err, "couldn't decode the query"))
+		return
+	}
+
+	ctrName := utils.GetName(r)
+
+	ctr, err := runtime.LookupContainer(ctrName)
+	if err != nil {
+		utils.Error(w, "Not found", http.StatusNotFound, errors.Wrapf(err, "the %s container doesn't exists", ctrName))
+		return
+	}
+	mountPoint, err := ctr.Mount()
+	if err != nil {
+		utils.Error(w, "Something went wrong", http.StatusInternalServerError, errors.Wrapf(err, "failed to mount the %s container", ctrName))
+		return
+	}
+	defer func() {
+		if err := ctr.Unmount(true); err != nil {
+			logrus.Warnf("failed to unmount container %s", ctrName)
+		}
+	}()
+
+	user, err := getUser(mountPoint, ctr.User())
+	if err != nil {
+		utils.Error(w, "Something went wrong", http.StatusInternalServerError, err)
+		return
+	}
+	idMappingOpts, err := ctr.IDMappings()
+	if err != nil {
+		utils.Error(w, "Something went wrong", http.StatusInternalServerError, errors.Wrapf(err, "error getting IDMappingOptions"))
+		return
+	}
+	destOwner := idtools.IDPair{UID: int(user.UID), GID: int(user.GID)}
+
+	opts := copier.PutOptions{
+		UIDMap:     idMappingOpts.UIDMap,
+		GIDMap:     idMappingOpts.GIDMap,
+		ChownDirs:  &destOwner,
+		ChownFiles: &destOwner,
+	}
+
+	mountPoint, path, err := fixUpMountPointAndPath(runtime, ctr, mountPoint, query.Path)
+	if err != nil {
+		utils.Error(w, "Something went wrong", http.StatusInternalServerError, err)
+		return
+	}
+
+	w.WriteHeader(http.StatusOK)
+	err = copier.Put(mountPoint, filepath.Join(mountPoint, path), opts, r.Body)
+	if err != nil {
+		logrus.Error(errors.Wrapf(err, "failed to copy to the %s container path %s", ctrName, query.Path))
+		return
+	}
+}
+
+func statsToHeader(stats *copier.StatForItem) (string, error) {
+	statsDTO := struct {
+		Name       string      `json:"name"`
+		Size       int64       `json:"size"`
+		Mode       os.FileMode `json:"mode"`
+		ModTime    time.Time   `json:"mtime"`
+		LinkTarget string      `json:"linkTarget"`
+	}{
+		Name:       filepath.Base(stats.Name),
+		Size:       stats.Size,
+		Mode:       stats.Mode,
+		ModTime:    stats.ModTime,
+		LinkTarget: stats.ImmediateTarget,
+	}
+
+	jsonBytes, err := json.Marshal(&statsDTO)
+	if err != nil {
+		return "", errors.Wrap(err, "failed to serialize file stats")
+	}
+
+	buff := bytes.NewBuffer(make([]byte, 0, 128))
+	base64encoder := base64.NewEncoder(base64.StdEncoding, buff)
+	_, err = base64encoder.Write(jsonBytes)
+	if err != nil {
+		return "", err
+	}
+	err = base64encoder.Close()
+	if err != nil {
+		return "", err
+	}
+
+	return buff.String(), nil
+}
+
+func getUser(mountPoint string, userspec string) (specs.User, error) {
+	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.Cause(err2) != chrootuser.ErrNoSuchUser && err == nil {
+				err = err2
+			}
+		} else {
+			u.AdditionalGids = groups
+		}
+
+	}
+	return u, err
+}
+
+func fixUpMountPointAndPath(runtime *libpod.Runtime, ctr *libpod.Container, mountPoint, ctrPath string) (string, string, error) {
+	if !filepath.IsAbs(ctrPath) {
+		endsWithSep := strings.HasSuffix(ctrPath, string(filepath.Separator))
+		ctrPath = filepath.Join(ctr.WorkingDir(), ctrPath)
+		if endsWithSep {
+			ctrPath = ctrPath + string(filepath.Separator)
+		}
+	}
+	if isVol, volDestName, volName := isVolumeDestName(ctrPath, ctr); isVol { //nolint(gocritic)
+		newMountPoint, path, err := pathWithVolumeMount(runtime, volDestName, volName, ctrPath)
+		if err != nil {
+			return "", "", errors.Wrapf(err, "error getting source path from volume %s", volDestName)
+		}
+		mountPoint = newMountPoint
+		ctrPath = path
+	} else if isBindMount, mount := isBindMountDestName(ctrPath, ctr); isBindMount { //nolint(gocritic)
+		newMountPoint, path, err := pathWithBindMountSource(mount, ctrPath)
+		if err != nil {
+			return "", "", errors.Wrapf(err, "error getting source path from bind mount %s", mount.Destination)
+		}
+		mountPoint = newMountPoint
+		ctrPath = path
+	}
+	return mountPoint, ctrPath, nil
+}
+
+func isVolumeDestName(path string, ctr *libpod.Container) (bool, string, string) {
+	separator := string(os.PathSeparator)
+	if filepath.IsAbs(path) {
+		path = strings.TrimPrefix(path, separator)
+	}
+	if path == "" {
+		return false, "", ""
+	}
+	for _, vol := range ctr.Config().NamedVolumes {
+		volNamePath := strings.TrimPrefix(vol.Dest, separator)
+		if matchVolumePath(path, volNamePath) {
+			return true, vol.Dest, vol.Name
+		}
+	}
+	return false, "", ""
+}
+
+func pathWithVolumeMount(runtime *libpod.Runtime, volDestName, volName, path string) (string, string, error) {
+	destVolume, err := runtime.GetVolume(volName)
+	if err != nil {
+		return "", "", errors.Wrapf(err, "error getting volume destination %s", volName)
+	}
+	if !filepath.IsAbs(path) {
+		path = filepath.Join(string(os.PathSeparator), path)
+	}
+	return destVolume.MountPoint(), strings.TrimPrefix(path, volDestName), err
+}
+
+func isBindMountDestName(path string, ctr *libpod.Container) (bool, specs.Mount) {
+	separator := string(os.PathSeparator)
+	if filepath.IsAbs(path) {
+		path = strings.TrimPrefix(path, string(os.PathSeparator))
+	}
+	if path == "" {
+		return false, specs.Mount{}
+	}
+	for _, m := range ctr.Config().Spec.Mounts {
+		if m.Type != "bind" {
+			continue
+		}
+		mDest := strings.TrimPrefix(m.Destination, separator)
+		if matchVolumePath(path, mDest) {
+			return true, m
+		}
+	}
+	return false, specs.Mount{}
+}
+
+func matchVolumePath(path, target string) bool {
+	pathStr := filepath.Clean(path)
+	target = filepath.Clean(target)
+	for len(pathStr) > len(target) && strings.Contains(pathStr, string(os.PathSeparator)) {
+		pathStr = pathStr[:strings.LastIndex(pathStr, string(os.PathSeparator))]
+	}
+	return pathStr == target
+}
+
+func pathWithBindMountSource(m specs.Mount, path string) (string, string, error) {
+	if !filepath.IsAbs(path) {
+		path = filepath.Join(string(os.PathSeparator), path)
+	}
+	return m.Source, strings.TrimPrefix(path, m.Destination), nil
 }
-- 
cgit v1.2.3-54-g00ecf


From 430729a391824774dcf11d93e7211c5785eb17c0 Mon Sep 17 00:00:00 2001
From: Matej Vasek <mvasek@redhat.com>
Date: Wed, 4 Nov 2020 22:03:53 +0100
Subject: fix lint

Signed-off-by: Matej Vasek <mvasek@redhat.com>
---
 pkg/api/handlers/compat/containers_archive.go | 23 ++++++++++-------------
 1 file changed, 10 insertions(+), 13 deletions(-)

(limited to 'pkg/api/handlers/compat/containers_archive.go')

diff --git a/pkg/api/handlers/compat/containers_archive.go b/pkg/api/handlers/compat/containers_archive.go
index f42a821cd..870e681de 100644
--- a/pkg/api/handlers/compat/containers_archive.go
+++ b/pkg/api/handlers/compat/containers_archive.go
@@ -5,6 +5,9 @@ import (
 	"encoding/base64"
 	"encoding/json"
 	"fmt"
+	"path/filepath"
+	"strings"
+
 	"github.com/containers/buildah/copier"
 	"github.com/containers/buildah/pkg/chrootuser"
 	"github.com/containers/podman/v2/libpod"
@@ -12,15 +15,14 @@ import (
 	"github.com/containers/podman/v2/pkg/api/handlers/utils"
 	"github.com/containers/storage/pkg/idtools"
 	"github.com/opencontainers/runtime-spec/specs-go"
-	"path/filepath"
-	"strings"
 
-	"github.com/gorilla/schema"
-	"github.com/pkg/errors"
-	"github.com/sirupsen/logrus"
 	"net/http"
 	"os"
 	"time"
+
+	"github.com/gorilla/schema"
+	"github.com/pkg/errors"
+	"github.com/sirupsen/logrus"
 )
 
 func Archive(w http.ResponseWriter, r *http.Request) {
@@ -131,7 +133,6 @@ func handleHeadOrGet(w http.ResponseWriter, r *http.Request, decoder *schema.Dec
 	} else {
 		w.WriteHeader(http.StatusOK)
 	}
-
 }
 
 func handlePut(w http.ResponseWriter, r *http.Request, decoder *schema.Decoder, runtime *libpod.Runtime) {
@@ -249,7 +250,6 @@ func getUser(mountPoint string, userspec string) (specs.User, error) {
 		} else {
 			u.AdditionalGids = groups
 		}
-
 	}
 	return u, err
 }
@@ -270,10 +270,7 @@ func fixUpMountPointAndPath(runtime *libpod.Runtime, ctr *libpod.Container, moun
 		mountPoint = newMountPoint
 		ctrPath = path
 	} else if isBindMount, mount := isBindMountDestName(ctrPath, ctr); isBindMount { //nolint(gocritic)
-		newMountPoint, path, err := pathWithBindMountSource(mount, ctrPath)
-		if err != nil {
-			return "", "", errors.Wrapf(err, "error getting source path from bind mount %s", mount.Destination)
-		}
+		newMountPoint, path := pathWithBindMountSource(mount, ctrPath)
 		mountPoint = newMountPoint
 		ctrPath = path
 	}
@@ -337,9 +334,9 @@ func matchVolumePath(path, target string) bool {
 	return pathStr == target
 }
 
-func pathWithBindMountSource(m specs.Mount, path string) (string, string, error) {
+func pathWithBindMountSource(m specs.Mount, path string) (string, string) {
 	if !filepath.IsAbs(path) {
 		path = filepath.Join(string(os.PathSeparator), path)
 	}
-	return m.Source, strings.TrimPrefix(path, m.Destination), nil
+	return m.Source, strings.TrimPrefix(path, m.Destination)
 }
-- 
cgit v1.2.3-54-g00ecf


From 7da4083549eb73d2b45b04db08a38db478ab2c11 Mon Sep 17 00:00:00 2001
From: Matej Vasek <mvasek@redhat.com>
Date: Wed, 4 Nov 2020 22:24:04 +0100
Subject: style: wsl

Signed-off-by: Matej Vasek <mvasek@redhat.com>
---
 pkg/api/handlers/compat/containers_archive.go | 35 +++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

(limited to 'pkg/api/handlers/compat/containers_archive.go')

diff --git a/pkg/api/handlers/compat/containers_archive.go b/pkg/api/handlers/compat/containers_archive.go
index 870e681de..1d57cb59a 100644
--- a/pkg/api/handlers/compat/containers_archive.go
+++ b/pkg/api/handlers/compat/containers_archive.go
@@ -49,6 +49,7 @@ func handleHeadOrGet(w http.ResponseWriter, r *http.Request, decoder *schema.Dec
 		utils.Error(w, "Bad Request.", http.StatusBadRequest, errors.Wrap(err, "couldn't decode the query"))
 		return
 	}
+
 	if query.Path == "" {
 		utils.Error(w, "Bad Request.", http.StatusBadRequest, errors.New("missing `path` parameter"))
 		return
@@ -64,11 +65,13 @@ func handleHeadOrGet(w http.ResponseWriter, r *http.Request, decoder *schema.Dec
 		utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err)
 		return
 	}
+
 	mountPoint, err := ctr.Mount()
 	if err != nil {
 		utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to mount the container"))
 		return
 	}
+
 	defer func() {
 		if err := ctr.Unmount(true); err != nil {
 			logrus.Warnf("failed to unmount container %s: %q", containerName, err)
@@ -88,14 +91,18 @@ func handleHeadOrGet(w http.ResponseWriter, r *http.Request, decoder *schema.Dec
 		utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to get stats about file"))
 		return
 	}
+
 	if len(stats) <= 0 || len(stats[0].Globbed) <= 0 {
 		errs := make([]string, 0, len(stats))
+
 		for _, stat := range stats {
 			if stat.Error != "" {
 				errs = append(errs, stat.Error)
 			}
 		}
+
 		utils.Error(w, "Not found.", http.StatusNotFound, fmt.Errorf("file doesn't exist (errs: %q)", strings.Join(errs, ";")))
+
 		return
 	}
 
@@ -114,6 +121,7 @@ func handleHeadOrGet(w http.ResponseWriter, r *http.Request, decoder *schema.Dec
 				errors.Wrapf(err, "error getting IDMappingOptions"))
 			return
 		}
+
 		destOwner := idtools.IDPair{UID: os.Getuid(), GID: os.Getgid()}
 
 		opts := copier.GetOptions{
@@ -125,6 +133,7 @@ func handleHeadOrGet(w http.ResponseWriter, r *http.Request, decoder *schema.Dec
 		}
 
 		w.WriteHeader(http.StatusOK)
+
 		err = copier.Get(mountPoint, "", opts, []string{filepath.Join(mountPoint, path)}, w)
 		if err != nil {
 			logrus.Error(errors.Wrapf(err, "failed to copy from the %s container path %s", containerName, query.Path))
@@ -156,11 +165,13 @@ func handlePut(w http.ResponseWriter, r *http.Request, decoder *schema.Decoder,
 		utils.Error(w, "Not found", http.StatusNotFound, errors.Wrapf(err, "the %s container doesn't exists", ctrName))
 		return
 	}
+
 	mountPoint, err := ctr.Mount()
 	if err != nil {
 		utils.Error(w, "Something went wrong", http.StatusInternalServerError, errors.Wrapf(err, "failed to mount the %s container", ctrName))
 		return
 	}
+
 	defer func() {
 		if err := ctr.Unmount(true); err != nil {
 			logrus.Warnf("failed to unmount container %s", ctrName)
@@ -172,11 +183,13 @@ func handlePut(w http.ResponseWriter, r *http.Request, decoder *schema.Decoder,
 		utils.Error(w, "Something went wrong", http.StatusInternalServerError, err)
 		return
 	}
+
 	idMappingOpts, err := ctr.IDMappings()
 	if err != nil {
 		utils.Error(w, "Something went wrong", http.StatusInternalServerError, errors.Wrapf(err, "error getting IDMappingOptions"))
 		return
 	}
+
 	destOwner := idtools.IDPair{UID: int(user.UID), GID: int(user.GID)}
 
 	opts := copier.PutOptions{
@@ -193,6 +206,7 @@ func handlePut(w http.ResponseWriter, r *http.Request, decoder *schema.Decoder,
 	}
 
 	w.WriteHeader(http.StatusOK)
+
 	err = copier.Put(mountPoint, filepath.Join(mountPoint, path), opts, r.Body)
 	if err != nil {
 		logrus.Error(errors.Wrapf(err, "failed to copy to the %s container path %s", ctrName, query.Path))
@@ -222,10 +236,12 @@ func statsToHeader(stats *copier.StatForItem) (string, error) {
 
 	buff := bytes.NewBuffer(make([]byte, 0, 128))
 	base64encoder := base64.NewEncoder(base64.StdEncoding, buff)
+
 	_, err = base64encoder.Write(jsonBytes)
 	if err != nil {
 		return "", err
 	}
+
 	err = base64encoder.Close()
 	if err != nil {
 		return "", err
@@ -241,6 +257,7 @@ func getUser(mountPoint string, userspec string) (specs.User, error) {
 		GID:      gid,
 		Username: userspec,
 	}
+
 	if !strings.Contains(userspec, ":") {
 		groups, err2 := chrootuser.GetAdditionalGroupsForUser(mountPoint, uint64(u.UID))
 		if err2 != nil {
@@ -251,6 +268,7 @@ func getUser(mountPoint string, userspec string) (specs.User, error) {
 			u.AdditionalGids = groups
 		}
 	}
+
 	return u, err
 }
 
@@ -258,6 +276,7 @@ func fixUpMountPointAndPath(runtime *libpod.Runtime, ctr *libpod.Container, moun
 	if !filepath.IsAbs(ctrPath) {
 		endsWithSep := strings.HasSuffix(ctrPath, string(filepath.Separator))
 		ctrPath = filepath.Join(ctr.WorkingDir(), ctrPath)
+
 		if endsWithSep {
 			ctrPath = ctrPath + string(filepath.Separator)
 		}
@@ -267,6 +286,7 @@ func fixUpMountPointAndPath(runtime *libpod.Runtime, ctr *libpod.Container, moun
 		if err != nil {
 			return "", "", errors.Wrapf(err, "error getting source path from volume %s", volDestName)
 		}
+
 		mountPoint = newMountPoint
 		ctrPath = path
 	} else if isBindMount, mount := isBindMountDestName(ctrPath, ctr); isBindMount { //nolint(gocritic)
@@ -274,23 +294,28 @@ func fixUpMountPointAndPath(runtime *libpod.Runtime, ctr *libpod.Container, moun
 		mountPoint = newMountPoint
 		ctrPath = path
 	}
+
 	return mountPoint, ctrPath, nil
 }
 
 func isVolumeDestName(path string, ctr *libpod.Container) (bool, string, string) {
 	separator := string(os.PathSeparator)
+
 	if filepath.IsAbs(path) {
 		path = strings.TrimPrefix(path, separator)
 	}
+
 	if path == "" {
 		return false, "", ""
 	}
+
 	for _, vol := range ctr.Config().NamedVolumes {
 		volNamePath := strings.TrimPrefix(vol.Dest, separator)
 		if matchVolumePath(path, volNamePath) {
 			return true, vol.Dest, vol.Name
 		}
 	}
+
 	return false, "", ""
 }
 
@@ -299,38 +324,47 @@ func pathWithVolumeMount(runtime *libpod.Runtime, volDestName, volName, path str
 	if err != nil {
 		return "", "", errors.Wrapf(err, "error getting volume destination %s", volName)
 	}
+
 	if !filepath.IsAbs(path) {
 		path = filepath.Join(string(os.PathSeparator), path)
 	}
+
 	return destVolume.MountPoint(), strings.TrimPrefix(path, volDestName), err
 }
 
 func isBindMountDestName(path string, ctr *libpod.Container) (bool, specs.Mount) {
 	separator := string(os.PathSeparator)
+
 	if filepath.IsAbs(path) {
 		path = strings.TrimPrefix(path, string(os.PathSeparator))
 	}
+
 	if path == "" {
 		return false, specs.Mount{}
 	}
+
 	for _, m := range ctr.Config().Spec.Mounts {
 		if m.Type != "bind" {
 			continue
 		}
+
 		mDest := strings.TrimPrefix(m.Destination, separator)
 		if matchVolumePath(path, mDest) {
 			return true, m
 		}
 	}
+
 	return false, specs.Mount{}
 }
 
 func matchVolumePath(path, target string) bool {
 	pathStr := filepath.Clean(path)
 	target = filepath.Clean(target)
+
 	for len(pathStr) > len(target) && strings.Contains(pathStr, string(os.PathSeparator)) {
 		pathStr = pathStr[:strings.LastIndex(pathStr, string(os.PathSeparator))]
 	}
+
 	return pathStr == target
 }
 
@@ -338,5 +372,6 @@ func pathWithBindMountSource(m specs.Mount, path string) (string, string) {
 	if !filepath.IsAbs(path) {
 		path = filepath.Join(string(os.PathSeparator), path)
 	}
+
 	return m.Source, strings.TrimPrefix(path, m.Destination)
 }
-- 
cgit v1.2.3-54-g00ecf


From 6ad2f1d2482ff156257c74a2b4bcd75d5b12d95d Mon Sep 17 00:00:00 2001
From: Matej Vasek <mvasek@redhat.com>
Date: Thu, 19 Nov 2020 00:40:11 +0100
Subject: fix: unmount container without force

Signed-off-by: Matej Vasek <mvasek@redhat.com>
---
 pkg/api/handlers/compat/containers_archive.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'pkg/api/handlers/compat/containers_archive.go')

diff --git a/pkg/api/handlers/compat/containers_archive.go b/pkg/api/handlers/compat/containers_archive.go
index 1d57cb59a..337b1787c 100644
--- a/pkg/api/handlers/compat/containers_archive.go
+++ b/pkg/api/handlers/compat/containers_archive.go
@@ -73,7 +73,7 @@ func handleHeadOrGet(w http.ResponseWriter, r *http.Request, decoder *schema.Dec
 	}
 
 	defer func() {
-		if err := ctr.Unmount(true); err != nil {
+		if err := ctr.Unmount(false); err != nil {
 			logrus.Warnf("failed to unmount container %s: %q", containerName, err)
 		}
 	}()
-- 
cgit v1.2.3-54-g00ecf


From be7e9f63f241c826e3a5772da355a3d66d254c6c Mon Sep 17 00:00:00 2001
From: Matej Vasek <mvasek@redhat.com>
Date: Thu, 19 Nov 2020 00:52:27 +0100
Subject: add comment

Signed-off-by: Matej Vasek <mvasek@redhat.com>
---
 pkg/api/handlers/compat/containers_archive.go | 2 ++
 1 file changed, 2 insertions(+)

(limited to 'pkg/api/handlers/compat/containers_archive.go')

diff --git a/pkg/api/handlers/compat/containers_archive.go b/pkg/api/handlers/compat/containers_archive.go
index 337b1787c..10f755a59 100644
--- a/pkg/api/handlers/compat/containers_archive.go
+++ b/pkg/api/handlers/compat/containers_archive.go
@@ -250,6 +250,8 @@ func statsToHeader(stats *copier.StatForItem) (string, error) {
 	return buff.String(), nil
 }
 
+// the utility functions below are copied from abi/cp.go
+
 func getUser(mountPoint string, userspec string) (specs.User, error) {
 	uid, gid, _, err := chrootuser.GetUser(mountPoint, userspec)
 	u := specs.User{
-- 
cgit v1.2.3-54-g00ecf


From 4d0346c028589737591615a308f69736a9fa0534 Mon Sep 17 00:00:00 2001
From: Matej Vasek <mvasek@redhat.com>
Date: Thu, 19 Nov 2020 19:27:00 +0100
Subject: not forcing unmount

Signed-off-by: Matej Vasek <mvasek@redhat.com>
---
 pkg/api/handlers/compat/containers_archive.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'pkg/api/handlers/compat/containers_archive.go')

diff --git a/pkg/api/handlers/compat/containers_archive.go b/pkg/api/handlers/compat/containers_archive.go
index 10f755a59..1dd563393 100644
--- a/pkg/api/handlers/compat/containers_archive.go
+++ b/pkg/api/handlers/compat/containers_archive.go
@@ -173,7 +173,7 @@ func handlePut(w http.ResponseWriter, r *http.Request, decoder *schema.Decoder,
 	}
 
 	defer func() {
-		if err := ctr.Unmount(true); err != nil {
+		if err := ctr.Unmount(false); err != nil {
 			logrus.Warnf("failed to unmount container %s", ctrName)
 		}
 	}()
-- 
cgit v1.2.3-54-g00ecf