copier.Stat(): return owner UID and GID if available
Return owner information for items that we've stat'ed. Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
This commit is contained in:
parent
f42946075a
commit
4fe68bc9b3
|
@ -201,7 +201,7 @@ func (req *request) UIDMap() []idtools.IDMap {
|
|||
case requestEval:
|
||||
return nil
|
||||
case requestStat:
|
||||
return nil
|
||||
return req.StatOptions.UIDMap
|
||||
case requestGet:
|
||||
return req.GetOptions.UIDMap
|
||||
case requestPut:
|
||||
|
@ -226,7 +226,7 @@ func (req *request) GIDMap() []idtools.IDMap {
|
|||
case requestEval:
|
||||
return nil
|
||||
case requestStat:
|
||||
return nil
|
||||
return req.StatOptions.GIDMap
|
||||
case requestGet:
|
||||
return req.GetOptions.GIDMap
|
||||
case requestPut:
|
||||
|
@ -284,6 +284,7 @@ type StatForItem struct {
|
|||
Size int64 // dereferenced value for symlinks
|
||||
Mode os.FileMode // dereferenced value for symlinks
|
||||
ModTime time.Time // dereferenced value for symlinks
|
||||
UID, GID int64 // usually in the uint32 range, set to -1 if unknown
|
||||
IsSymlink bool
|
||||
IsDir bool // dereferenced value for symlinks
|
||||
IsRegular bool // dereferenced value for symlinks
|
||||
|
@ -342,8 +343,9 @@ func Eval(root string, directory string, _ EvalOptions) (string, error) {
|
|||
|
||||
// StatOptions controls parts of Stat()'s behavior.
|
||||
type StatOptions struct {
|
||||
CheckForArchives bool // check for and populate the IsArchive bit in returned values
|
||||
Excludes []string // contents to pretend don't exist, using the OS-specific path separator
|
||||
UIDMap, GIDMap []idtools.IDMap // map from hostIDs to containerIDs when returning results
|
||||
CheckForArchives bool // check for and populate the IsArchive bit in returned values
|
||||
Excludes []string // contents to pretend don't exist, using the OS-specific path separator
|
||||
}
|
||||
|
||||
// Stat globs the specified pattern in the specified directory and returns its
|
||||
|
@ -975,7 +977,7 @@ func copierHandler(bulkReader io.Reader, bulkWriter io.Writer, req request) (*re
|
|||
resp := copierHandlerEval(req)
|
||||
return resp, nil, nil
|
||||
case requestStat:
|
||||
resp := copierHandlerStat(req, pm)
|
||||
resp := copierHandlerStat(req, pm, idMappings)
|
||||
return resp, nil, nil
|
||||
case requestGet:
|
||||
return copierHandlerGet(bulkWriter, req, pm, idMappings)
|
||||
|
@ -1102,7 +1104,7 @@ func copierHandlerEval(req request) *response {
|
|||
return &response{Eval: evalResponse{Evaluated: filepath.Join(req.rootPrefix, resolvedTarget)}}
|
||||
}
|
||||
|
||||
func copierHandlerStat(req request, pm *fileutils.PatternMatcher) *response {
|
||||
func copierHandlerStat(req request, pm *fileutils.PatternMatcher, idMappings *idtools.IDMappings) *response {
|
||||
errorResponse := func(fmtspec string, args ...any) *response {
|
||||
return &response{Error: fmt.Sprintf(fmtspec, args...), Stat: statResponse{}}
|
||||
}
|
||||
|
@ -1160,6 +1162,17 @@ func copierHandlerStat(req request, pm *fileutils.PatternMatcher) *response {
|
|||
}
|
||||
result.Size = linfo.Size()
|
||||
result.Mode = linfo.Mode()
|
||||
result.UID, result.GID = -1, -1
|
||||
if uid, gid, err := owner(linfo); err == nil {
|
||||
if idMappings != nil && !idMappings.Empty() {
|
||||
hostPair := idtools.IDPair{UID: uid, GID: gid}
|
||||
uid, gid, err = idMappings.ToContainer(hostPair)
|
||||
if err != nil {
|
||||
return errorResponse("copier: stat: mapping host filesystem owners %#v to container filesystem owners: %w", hostPair, err)
|
||||
}
|
||||
}
|
||||
result.UID, result.GID = int64(uid), int64(gid)
|
||||
}
|
||||
result.ModTime = linfo.ModTime()
|
||||
result.IsDir = linfo.IsDir()
|
||||
result.IsRegular = result.Mode.IsRegular()
|
||||
|
@ -1272,7 +1285,7 @@ func checkLinks(item string, req request, info os.FileInfo) (string, os.FileInfo
|
|||
func copierHandlerGet(bulkWriter io.Writer, req request, pm *fileutils.PatternMatcher, idMappings *idtools.IDMappings) (*response, func() error, error) {
|
||||
statRequest := req
|
||||
statRequest.Request = requestStat
|
||||
statResponse := copierHandlerStat(req, pm)
|
||||
statResponse := copierHandlerStat(req, pm, idMappings)
|
||||
errorResponse := func(fmtspec string, args ...any) (*response, func() error, error) {
|
||||
return &response{Error: fmt.Sprintf(fmtspec, args...), Stat: statResponse.Stat, Get: getResponse{}}, nil, nil
|
||||
}
|
||||
|
@ -2270,7 +2283,7 @@ type EnsurePath struct {
|
|||
|
||||
// EnsureOptions controls parts of Ensure()'s behavior.
|
||||
type EnsureOptions struct {
|
||||
UIDMap, GIDMap []idtools.IDMap // map from hostIDs to containerIDs in the chroot
|
||||
UIDMap, GIDMap []idtools.IDMap // map from containerIDs to hostIDs in the chroot
|
||||
Paths []EnsurePath
|
||||
}
|
||||
|
||||
|
@ -2437,7 +2450,7 @@ type ConditionalRemovePath struct {
|
|||
|
||||
// ConditionalRemoveOptions controls parts of ConditionalRemove()'s behavior.
|
||||
type ConditionalRemoveOptions struct {
|
||||
UIDMap, GIDMap []idtools.IDMap // map from hostIDs to containerIDs in the chroot
|
||||
UIDMap, GIDMap []idtools.IDMap // map from containerIDs to hostIDs in the chroot
|
||||
Paths []ConditionalRemovePath
|
||||
}
|
||||
|
||||
|
|
|
@ -716,6 +716,7 @@ func testStat(t *testing.T) {
|
|||
if actualContent, ok := testArchive.contents[testItem.Name]; ok {
|
||||
testItem.Size = int64(len(actualContent))
|
||||
}
|
||||
checkStatInfoOwnership(t, result)
|
||||
require.Equal(t, testItem.Size, result.Size, "unexpected size difference for %q", name)
|
||||
require.True(t, result.IsRegular, "expected %q.IsRegular to be true", glob)
|
||||
require.False(t, result.IsDir, "expected %q.IsDir to be false", glob)
|
||||
|
|
|
@ -5,6 +5,8 @@ package copier
|
|||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -101,3 +103,9 @@ func TestConditionalRemoveChroot(t *testing.T) {
|
|||
testConditionalRemove(t)
|
||||
canChroot = couldChroot
|
||||
}
|
||||
|
||||
func checkStatInfoOwnership(t *testing.T, result *StatForItem) {
|
||||
t.Helper()
|
||||
require.EqualValues(t, 0, result.UID, "expected the owning user to be reported")
|
||||
require.EqualValues(t, 0, result.GID, "expected the owning group to be reported")
|
||||
}
|
||||
|
|
|
@ -2,7 +2,14 @@
|
|||
|
||||
package copier
|
||||
|
||||
const (
|
||||
testModeMask = int64(0o600)
|
||||
testIgnoreSymlinkDates = true
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func checkStatInfoOwnership(t *testing.T, result *StatForItem) {
|
||||
t.Helper()
|
||||
require.EqualValues(t, -1, result.UID, "expected the owning user to not be supported")
|
||||
require.EqualValues(t, -1, result.GID, "expected the owning group to not be supported")
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue