Signed-off-by: Daniel Nephin <dnephin@docker.com>
| ... | ... |
@@ -413,15 +413,11 @@ func (ta *tarAppender) addTarFile(path, name string) error {
|
| 413 | 413 |
//writing tar headers/files. We skip whiteout files because they were written |
| 414 | 414 |
//by the kernel and already have proper ownership relative to the host |
| 415 | 415 |
if !strings.HasPrefix(filepath.Base(hdr.Name), WhiteoutPrefix) && !ta.IDMappings.Empty() {
|
| 416 |
- uid, gid, err := getFileUIDGID(fi.Sys()) |
|
| 416 |
+ fileIDPair, err := getFileUIDGID(fi.Sys()) |
|
| 417 | 417 |
if err != nil {
|
| 418 | 418 |
return err |
| 419 | 419 |
} |
| 420 |
- hdr.Uid, err = ta.IDMappings.UIDToContainer(uid) |
|
| 421 |
- if err != nil {
|
|
| 422 |
- return err |
|
| 423 |
- } |
|
| 424 |
- hdr.Gid, err = ta.IDMappings.GIDToContainer(gid) |
|
| 420 |
+ hdr.Uid, hdr.Gid, err = ta.IDMappings.ToContainer(fileIDPair) |
|
| 425 | 421 |
if err != nil {
|
| 426 | 422 |
return err |
| 427 | 423 |
} |
| ... | ... |
@@ -806,7 +802,8 @@ func Unpack(decompressedArchive io.Reader, dest string, options *TarOptions) err |
| 806 | 806 |
defer pools.BufioReader32KPool.Put(trBuf) |
| 807 | 807 |
|
| 808 | 808 |
var dirs []*tar.Header |
| 809 |
- remappedRootUID, remappedRootGID, err := idtools.GetRootUIDGID(options.UIDMaps, options.GIDMaps) |
|
| 809 |
+ idMappings := idtools.NewIDMappingsFromMaps(options.UIDMaps, options.GIDMaps) |
|
| 810 |
+ rootIDs, err := idMappings.RootPair() |
|
| 810 | 811 |
if err != nil {
|
| 811 | 812 |
return err |
| 812 | 813 |
} |
| ... | ... |
@@ -843,7 +840,7 @@ loop: |
| 843 | 843 |
parent := filepath.Dir(hdr.Name) |
| 844 | 844 |
parentPath := filepath.Join(dest, parent) |
| 845 | 845 |
if _, err := os.Lstat(parentPath); err != nil && os.IsNotExist(err) {
|
| 846 |
- err = idtools.MkdirAllNewAs(parentPath, 0777, remappedRootUID, remappedRootGID) |
|
| 846 |
+ err = idtools.MkdirAllAndChownNew(parentPath, 0777, rootIDs) |
|
| 847 | 847 |
if err != nil {
|
| 848 | 848 |
return err |
| 849 | 849 |
} |
| ... | ... |
@@ -888,26 +885,8 @@ loop: |
| 888 | 888 |
} |
| 889 | 889 |
trBuf.Reset(tr) |
| 890 | 890 |
|
| 891 |
- // if the options contain a uid & gid maps, convert header uid/gid |
|
| 892 |
- // entries using the maps such that lchown sets the proper mapped |
|
| 893 |
- // uid/gid after writing the file. We only perform this mapping if |
|
| 894 |
- // the file isn't already owned by the remapped root UID or GID, as |
|
| 895 |
- // that specific uid/gid has no mapping from container -> host, and |
|
| 896 |
- // those files already have the proper ownership for inside the |
|
| 897 |
- // container. |
|
| 898 |
- if hdr.Uid != remappedRootUID {
|
|
| 899 |
- xUID, err := idtools.ToHost(hdr.Uid, options.UIDMaps) |
|
| 900 |
- if err != nil {
|
|
| 901 |
- return err |
|
| 902 |
- } |
|
| 903 |
- hdr.Uid = xUID |
|
| 904 |
- } |
|
| 905 |
- if hdr.Gid != remappedRootGID {
|
|
| 906 |
- xGID, err := idtools.ToHost(hdr.Gid, options.GIDMaps) |
|
| 907 |
- if err != nil {
|
|
| 908 |
- return err |
|
| 909 |
- } |
|
| 910 |
- hdr.Gid = xGID |
|
| 891 |
+ if err := remapIDs(idMappings, hdr); err != nil {
|
|
| 892 |
+ return err |
|
| 911 | 893 |
} |
| 912 | 894 |
|
| 913 | 895 |
if whiteoutConverter != nil {
|
| ... | ... |
@@ -1083,26 +1062,10 @@ func (archiver *Archiver) CopyFileWithTar(src, dst string) (err error) {
|
| 1083 | 1083 |
hdr.Name = filepath.Base(dst) |
| 1084 | 1084 |
hdr.Mode = int64(chmodTarEntry(os.FileMode(hdr.Mode))) |
| 1085 | 1085 |
|
| 1086 |
- remappedRootIDs, err := archiver.IDMappings.RootPair() |
|
| 1087 |
- if err != nil {
|
|
| 1086 |
+ if err := remapIDs(archiver.IDMappings, hdr); err != nil {
|
|
| 1088 | 1087 |
return err |
| 1089 | 1088 |
} |
| 1090 | 1089 |
|
| 1091 |
- // only perform mapping if the file being copied isn't already owned by the |
|
| 1092 |
- // uid or gid of the remapped root in the container |
|
| 1093 |
- if remappedRootIDs.UID != hdr.Uid {
|
|
| 1094 |
- hdr.Uid, err = archiver.IDMappings.UIDToHost(hdr.Uid) |
|
| 1095 |
- if err != nil {
|
|
| 1096 |
- return err |
|
| 1097 |
- } |
|
| 1098 |
- } |
|
| 1099 |
- if remappedRootIDs.GID != hdr.Gid {
|
|
| 1100 |
- hdr.Gid, err = archiver.IDMappings.GIDToHost(hdr.Gid) |
|
| 1101 |
- if err != nil {
|
|
| 1102 |
- return err |
|
| 1103 |
- } |
|
| 1104 |
- } |
|
| 1105 |
- |
|
| 1106 | 1090 |
tw := tar.NewWriter(w) |
| 1107 | 1091 |
defer tw.Close() |
| 1108 | 1092 |
if err := tw.WriteHeader(hdr); err != nil {
|
| ... | ... |
@@ -1126,6 +1089,12 @@ func (archiver *Archiver) CopyFileWithTar(src, dst string) (err error) {
|
| 1126 | 1126 |
return err |
| 1127 | 1127 |
} |
| 1128 | 1128 |
|
| 1129 |
+func remapIDs(idMappings *idtools.IDMappings, hdr *tar.Header) error {
|
|
| 1130 |
+ ids, err := idMappings.ToHost(idtools.IDPair{UID: hdr.Uid, GID: hdr.Gid})
|
|
| 1131 |
+ hdr.Uid, hdr.Gid = ids.UID, ids.GID |
|
| 1132 |
+ return err |
|
| 1133 |
+} |
|
| 1134 |
+ |
|
| 1129 | 1135 |
// cmdStream executes a command, and returns its stdout as a stream. |
| 1130 | 1136 |
// If the command fails to run or doesn't complete successfully, an error |
| 1131 | 1137 |
// will be returned, including anything written on stderr. |
| ... | ... |
@@ -9,6 +9,7 @@ import ( |
| 9 | 9 |
"path/filepath" |
| 10 | 10 |
"syscall" |
| 11 | 11 |
|
| 12 |
+ "github.com/docker/docker/pkg/idtools" |
|
| 12 | 13 |
"github.com/docker/docker/pkg/system" |
| 13 | 14 |
rsystem "github.com/opencontainers/runc/libcontainer/system" |
| 14 | 15 |
) |
| ... | ... |
@@ -72,13 +73,13 @@ func getInodeFromStat(stat interface{}) (inode uint64, err error) {
|
| 72 | 72 |
return |
| 73 | 73 |
} |
| 74 | 74 |
|
| 75 |
-func getFileUIDGID(stat interface{}) (int, int, error) {
|
|
| 75 |
+func getFileUIDGID(stat interface{}) (idtools.IDPair, error) {
|
|
| 76 | 76 |
s, ok := stat.(*syscall.Stat_t) |
| 77 | 77 |
|
| 78 | 78 |
if !ok {
|
| 79 |
- return -1, -1, errors.New("cannot convert stat value to syscall.Stat_t")
|
|
| 79 |
+ return idtools.IDPair{}, errors.New("cannot convert stat value to syscall.Stat_t")
|
|
| 80 | 80 |
} |
| 81 |
- return int(s.Uid), int(s.Gid), nil |
|
| 81 |
+ return idtools.IDPair{UID: int(s.Uid), GID: int(s.Gid)}, nil
|
|
| 82 | 82 |
} |
| 83 | 83 |
|
| 84 | 84 |
func major(device uint64) uint64 {
|
| ... | ... |
@@ -9,6 +9,7 @@ import ( |
| 9 | 9 |
"path/filepath" |
| 10 | 10 |
"strings" |
| 11 | 11 |
|
| 12 |
+ "github.com/docker/docker/pkg/idtools" |
|
| 12 | 13 |
"github.com/docker/docker/pkg/longpath" |
| 13 | 14 |
) |
| 14 | 15 |
|
| ... | ... |
@@ -72,7 +73,7 @@ func handleLChmod(hdr *tar.Header, path string, hdrInfo os.FileInfo) error {
|
| 72 | 72 |
return nil |
| 73 | 73 |
} |
| 74 | 74 |
|
| 75 |
-func getFileUIDGID(stat interface{}) (int, int, error) {
|
|
| 75 |
+func getFileUIDGID(stat interface{}) (idtools.IDPair, error) {
|
|
| 76 | 76 |
// no notion of file ownership mapping yet on Windows |
| 77 |
- return 0, 0, nil |
|
| 77 |
+ return idtools.IDPair{0, 0}, nil
|
|
| 78 | 78 |
} |
| ... | ... |
@@ -33,10 +33,7 @@ func UnpackLayer(dest string, layer io.Reader, options *TarOptions) (size int64, |
| 33 | 33 |
if options.ExcludePatterns == nil {
|
| 34 | 34 |
options.ExcludePatterns = []string{}
|
| 35 | 35 |
} |
| 36 |
- remappedRootUID, remappedRootGID, err := idtools.GetRootUIDGID(options.UIDMaps, options.GIDMaps) |
|
| 37 |
- if err != nil {
|
|
| 38 |
- return 0, err |
|
| 39 |
- } |
|
| 36 |
+ idMappings := idtools.NewIDMappingsFromMaps(options.UIDMaps, options.GIDMaps) |
|
| 40 | 37 |
|
| 41 | 38 |
aufsTempdir := "" |
| 42 | 39 |
aufsHardlinks := make(map[string]*tar.Header) |
| ... | ... |
@@ -195,27 +192,10 @@ func UnpackLayer(dest string, layer io.Reader, options *TarOptions) (size int64, |
| 195 | 195 |
srcData = tmpFile |
| 196 | 196 |
} |
| 197 | 197 |
|
| 198 |
- // if the options contain a uid & gid maps, convert header uid/gid |
|
| 199 |
- // entries using the maps such that lchown sets the proper mapped |
|
| 200 |
- // uid/gid after writing the file. We only perform this mapping if |
|
| 201 |
- // the file isn't already owned by the remapped root UID or GID, as |
|
| 202 |
- // that specific uid/gid has no mapping from container -> host, and |
|
| 203 |
- // those files already have the proper ownership for inside the |
|
| 204 |
- // container. |
|
| 205 |
- if srcHdr.Uid != remappedRootUID {
|
|
| 206 |
- xUID, err := idtools.ToHost(srcHdr.Uid, options.UIDMaps) |
|
| 207 |
- if err != nil {
|
|
| 208 |
- return 0, err |
|
| 209 |
- } |
|
| 210 |
- srcHdr.Uid = xUID |
|
| 211 |
- } |
|
| 212 |
- if srcHdr.Gid != remappedRootGID {
|
|
| 213 |
- xGID, err := idtools.ToHost(srcHdr.Gid, options.GIDMaps) |
|
| 214 |
- if err != nil {
|
|
| 215 |
- return 0, err |
|
| 216 |
- } |
|
| 217 |
- srcHdr.Gid = xGID |
|
| 198 |
+ if err := remapIDs(idMappings, srcHdr); err != nil {
|
|
| 199 |
+ return 0, err |
|
| 218 | 200 |
} |
| 201 |
+ |
|
| 219 | 202 |
if err := createTarFile(path, dest, srcHdr, srcData, true, nil, options.InUserNS); err != nil {
|
| 220 | 203 |
return 0, err |
| 221 | 204 |
} |
| ... | ... |
@@ -80,21 +80,13 @@ func MkdirAllAndChownNew(path string, mode os.FileMode, ids IDPair) error {
|
| 80 | 80 |
// GetRootUIDGID retrieves the remapped root uid/gid pair from the set of maps. |
| 81 | 81 |
// If the maps are empty, then the root uid/gid will default to "real" 0/0 |
| 82 | 82 |
func GetRootUIDGID(uidMap, gidMap []IDMap) (int, int, error) {
|
| 83 |
- var uid, gid int |
|
| 84 |
- |
|
| 85 |
- if uidMap != nil {
|
|
| 86 |
- xUID, err := ToHost(0, uidMap) |
|
| 87 |
- if err != nil {
|
|
| 88 |
- return -1, -1, err |
|
| 89 |
- } |
|
| 90 |
- uid = xUID |
|
| 83 |
+ uid, err := toHost(0, uidMap) |
|
| 84 |
+ if err != nil {
|
|
| 85 |
+ return -1, -1, err |
|
| 91 | 86 |
} |
| 92 |
- if gidMap != nil {
|
|
| 93 |
- xGID, err := ToHost(0, gidMap) |
|
| 94 |
- if err != nil {
|
|
| 95 |
- return -1, -1, err |
|
| 96 |
- } |
|
| 97 |
- gid = xGID |
|
| 87 |
+ gid, err := toHost(0, gidMap) |
|
| 88 |
+ if err != nil {
|
|
| 89 |
+ return -1, -1, err |
|
| 98 | 90 |
} |
| 99 | 91 |
return uid, gid, nil |
| 100 | 92 |
} |
| ... | ... |
@@ -115,11 +107,10 @@ func toContainer(hostID int, idMap []IDMap) (int, error) {
|
| 115 | 115 |
return -1, fmt.Errorf("Host ID %d cannot be mapped to a container ID", hostID)
|
| 116 | 116 |
} |
| 117 | 117 |
|
| 118 |
-// ToHost takes an id mapping and a remapped ID, and translates the |
|
| 118 |
+// toHost takes an id mapping and a remapped ID, and translates the |
|
| 119 | 119 |
// ID to the mapped host ID. If no map is provided, then the translation |
| 120 | 120 |
// assumes a 1-to-1 mapping and returns the passed in id # |
| 121 |
-// Depercated: use IDMappings.UIDToHost and IDMappings.GIDToHost |
|
| 122 |
-func ToHost(contID int, idMap []IDMap) (int, error) {
|
|
| 121 |
+func toHost(contID int, idMap []IDMap) (int, error) {
|
|
| 123 | 122 |
if idMap == nil {
|
| 124 | 123 |
return contID, nil |
| 125 | 124 |
} |
| ... | ... |
@@ -181,24 +172,35 @@ func (i *IDMappings) RootPair() (IDPair, error) {
|
| 181 | 181 |
return IDPair{UID: uid, GID: gid}, err
|
| 182 | 182 |
} |
| 183 | 183 |
|
| 184 |
-// UIDToHost returns the host UID for the container uid |
|
| 185 |
-func (i *IDMappings) UIDToHost(uid int) (int, error) {
|
|
| 186 |
- return ToHost(uid, i.uids) |
|
| 187 |
-} |
|
| 184 |
+// ToHost returns the host UID and GID for the container uid, gid. |
|
| 185 |
+// Remapping is only performed if the ids aren't already the remapped root ids |
|
| 186 |
+func (i *IDMappings) ToHost(pair IDPair) (IDPair, error) {
|
|
| 187 |
+ target, err := i.RootPair() |
|
| 188 |
+ if err != nil {
|
|
| 189 |
+ return IDPair{}, err
|
|
| 190 |
+ } |
|
| 188 | 191 |
|
| 189 |
-// GIDToHost returns the host GID for the container gid |
|
| 190 |
-func (i *IDMappings) GIDToHost(gid int) (int, error) {
|
|
| 191 |
- return ToHost(gid, i.gids) |
|
| 192 |
-} |
|
| 192 |
+ if pair.UID != target.UID {
|
|
| 193 |
+ target.UID, err = toHost(pair.UID, i.uids) |
|
| 194 |
+ if err != nil {
|
|
| 195 |
+ return target, err |
|
| 196 |
+ } |
|
| 197 |
+ } |
|
| 193 | 198 |
|
| 194 |
-// UIDToContainer returns the container UID for the host uid |
|
| 195 |
-func (i *IDMappings) UIDToContainer(uid int) (int, error) {
|
|
| 196 |
- return toContainer(uid, i.uids) |
|
| 199 |
+ if pair.GID != target.GID {
|
|
| 200 |
+ target.GID, err = toHost(pair.GID, i.gids) |
|
| 201 |
+ } |
|
| 202 |
+ return target, err |
|
| 197 | 203 |
} |
| 198 | 204 |
|
| 199 |
-// GIDToContainer returns the container GID for the host gid |
|
| 200 |
-func (i *IDMappings) GIDToContainer(gid int) (int, error) {
|
|
| 201 |
- return toContainer(gid, i.gids) |
|
| 205 |
+// ToContainer returns the container UID and GID for the host uid and gid |
|
| 206 |
+func (i *IDMappings) ToContainer(pair IDPair) (int, int, error) {
|
|
| 207 |
+ uid, err := toContainer(pair.UID, i.uids) |
|
| 208 |
+ if err != nil {
|
|
| 209 |
+ return -1, -1, err |
|
| 210 |
+ } |
|
| 211 |
+ gid, err := toContainer(pair.GID, i.gids) |
|
| 212 |
+ return uid, gid, err |
|
| 202 | 213 |
} |
| 203 | 214 |
|
| 204 | 215 |
// Empty returns true if there are no id mappings |