mirror of
https://github.com/containers/podman
synced 2024-10-20 01:03:51 +00:00
archive: move stat-header handling into copy package
Move handling the stat header into `pkg/copy`. All copy-related should ideally be located in this package to increase locality and reduce scattering where possible. Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
This commit is contained in:
parent
8472efdbd1
commit
c2a5011c0d
|
@ -1,13 +1,8 @@
|
|||
package compat
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/containers/podman/v2/libpod"
|
||||
"github.com/containers/podman/v2/libpod/define"
|
||||
|
@ -71,12 +66,12 @@ func handleHeadAndGet(w http.ResponseWriter, r *http.Request, decoder *schema.De
|
|||
utils.Error(w, "Not found.", http.StatusNotFound, errors.Wrapf(err, "error stating container path %q", query.Path))
|
||||
return
|
||||
}
|
||||
statHeader, err := fileInfoToDockerStats(info)
|
||||
statHeader, err := copy.EncodeFileInfo(info)
|
||||
if err != nil {
|
||||
utils.Error(w, "Something went wrong", http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
w.Header().Add("X-Docker-Container-Path-Stat", statHeader)
|
||||
w.Header().Add(copy.XDockerContainerPathStatHeader, statHeader)
|
||||
|
||||
// Our work is done when the user is interested in the header only.
|
||||
if r.Method == http.MethodHead {
|
||||
|
@ -98,42 +93,6 @@ func handleHeadAndGet(w http.ResponseWriter, r *http.Request, decoder *schema.De
|
|||
}
|
||||
}
|
||||
|
||||
func fileInfoToDockerStats(info *copy.FileInfo) (string, error) {
|
||||
dockerStats := struct {
|
||||
Name string `json:"name"`
|
||||
Size int64 `json:"size"`
|
||||
Mode os.FileMode `json:"mode"`
|
||||
ModTime time.Time `json:"mtime"`
|
||||
LinkTarget string `json:"linkTarget"`
|
||||
}{
|
||||
Name: info.Name,
|
||||
Size: info.Size,
|
||||
Mode: info.Mode,
|
||||
ModTime: info.ModTime,
|
||||
LinkTarget: info.LinkTarget,
|
||||
}
|
||||
|
||||
jsonBytes, err := json.Marshal(&dockerStats)
|
||||
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 handlePut(w http.ResponseWriter, r *http.Request, decoder *schema.Decoder, runtime *libpod.Runtime) {
|
||||
query := struct {
|
||||
Path string `schema:"path"`
|
||||
|
|
|
@ -114,7 +114,6 @@ func enforceCopyRules(source, destination *CopyItem) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Source is a *stream*.
|
||||
if source.info.IsStream {
|
||||
if !(destination.info.IsDir || destination.info.IsStream) {
|
||||
return errors.New("destination must be a directory or stream when copying from a stream")
|
||||
|
|
56
pkg/copy/fileinfo.go
Normal file
56
pkg/copy/fileinfo.go
Normal file
|
@ -0,0 +1,56 @@
|
|||
package copy
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// XDockerContainerPathStatHeader is the *key* in http headers pointing to the
|
||||
// base64 encoded JSON payload of stating a path in a container.
|
||||
const XDockerContainerPathStatHeader = "X-Docker-Container-Path-Stat"
|
||||
|
||||
// FileInfo describes a file or directory and is returned by
|
||||
// (*CopyItem).Stat().
|
||||
type FileInfo struct {
|
||||
Name string `json:"name"`
|
||||
Size int64 `json:"size"`
|
||||
Mode os.FileMode `json:"mode"`
|
||||
ModTime time.Time `json:"mtime"`
|
||||
IsDir bool `json:"isDir"`
|
||||
IsStream bool `json:"isStream"`
|
||||
LinkTarget string `json:"linkTarget"`
|
||||
}
|
||||
|
||||
// EncodeFileInfo serializes the specified FileInfo as a base64 encoded JSON
|
||||
// payload. Intended for Docker compat.
|
||||
func EncodeFileInfo(info *FileInfo) (string, error) {
|
||||
buf, err := json.Marshal(&info)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "failed to serialize file stats")
|
||||
}
|
||||
return base64.URLEncoding.EncodeToString(buf), nil
|
||||
}
|
||||
|
||||
// ExtractFileInfoFromHeader extracts a base64 encoded JSON payload of a
|
||||
// FileInfo in the http header. If no such header entry is found, nil is
|
||||
// returned. Intended for Docker compat.
|
||||
func ExtractFileInfoFromHeader(header *http.Header) (*FileInfo, error) {
|
||||
rawData := header.Get(XDockerContainerPathStatHeader)
|
||||
if len(rawData) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
info := FileInfo{}
|
||||
base64Decoder := base64.NewDecoder(base64.URLEncoding, strings.NewReader(rawData))
|
||||
if err := json.NewDecoder(base64Decoder).Decode(&info); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &info, nil
|
||||
}
|
|
@ -5,7 +5,6 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
buildahCopiah "github.com/containers/buildah/copier"
|
||||
"github.com/containers/buildah/pkg/chrootuser"
|
||||
|
@ -75,18 +74,6 @@ type CopyItem struct {
|
|||
// deferFunc allows for returning functions that must be deferred at call sites.
|
||||
type deferFunc func()
|
||||
|
||||
// FileInfo describes a file or directory and is returned by
|
||||
// (*CopyItem).Stat().
|
||||
type FileInfo struct {
|
||||
Name string `json:"name"`
|
||||
Size int64 `json:"size"`
|
||||
Mode os.FileMode `json:"mode"`
|
||||
ModTime time.Time `json:"mtime"`
|
||||
IsDir bool `json:"isDir"`
|
||||
IsStream bool `json:"isStream"`
|
||||
LinkTarget string `json:"linkTarget"`
|
||||
}
|
||||
|
||||
// Stat returns the FileInfo.
|
||||
func (item *CopyItem) Stat() (*FileInfo, error) {
|
||||
return &item.info, item.statError
|
||||
|
|
Loading…
Reference in a new issue