Signed-off-by: Daniel Nephin <dnephin@docker.com>
Daniel Nephin authored on 2017/06/01 06:18:04... | ... |
@@ -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 |