Signed-off-by: Daniel Nephin <dnephin@docker.com>
Daniel Nephin authored on 2017/05/25 03:10:15... | ... |
@@ -345,9 +345,8 @@ type tarAppender struct { |
345 | 345 |
Buffer *bufio.Writer |
346 | 346 |
|
347 | 347 |
// for hardlink mapping |
348 |
- SeenFiles map[uint64]string |
|
349 |
- UIDMaps []idtools.IDMap |
|
350 |
- GIDMaps []idtools.IDMap |
|
348 |
+ SeenFiles map[uint64]string |
|
349 |
+ IDMappings *idtools.IDMappings |
|
351 | 350 |
|
352 | 351 |
// For packing and unpacking whiteout files in the |
353 | 352 |
// non standard format. The whiteout files defined |
... | ... |
@@ -356,6 +355,15 @@ type tarAppender struct { |
356 | 356 |
WhiteoutConverter tarWhiteoutConverter |
357 | 357 |
} |
358 | 358 |
|
359 |
+func newTarAppender(idMapping *idtools.IDMappings, writer io.Writer) *tarAppender { |
|
360 |
+ return &tarAppender{ |
|
361 |
+ SeenFiles: make(map[uint64]string), |
|
362 |
+ TarWriter: tar.NewWriter(writer), |
|
363 |
+ Buffer: pools.BufioWriter32KPool.Get(nil), |
|
364 |
+ IDMappings: idMapping, |
|
365 |
+ } |
|
366 |
+} |
|
367 |
+ |
|
359 | 368 |
// canonicalTarName provides a platform-independent and consistent posix-style |
360 | 369 |
//path for files and directories to be archived regardless of the platform. |
361 | 370 |
func canonicalTarName(name string, isDir bool) (string, error) { |
... | ... |
@@ -404,21 +412,19 @@ func (ta *tarAppender) addTarFile(path, name string) error { |
404 | 404 |
//handle re-mapping container ID mappings back to host ID mappings before |
405 | 405 |
//writing tar headers/files. We skip whiteout files because they were written |
406 | 406 |
//by the kernel and already have proper ownership relative to the host |
407 |
- if !strings.HasPrefix(filepath.Base(hdr.Name), WhiteoutPrefix) && (ta.UIDMaps != nil || ta.GIDMaps != nil) { |
|
407 |
+ if !strings.HasPrefix(filepath.Base(hdr.Name), WhiteoutPrefix) && !ta.IDMappings.Empty() { |
|
408 | 408 |
uid, gid, err := getFileUIDGID(fi.Sys()) |
409 | 409 |
if err != nil { |
410 | 410 |
return err |
411 | 411 |
} |
412 |
- xUID, err := idtools.ToContainer(uid, ta.UIDMaps) |
|
412 |
+ hdr.Uid, err = ta.IDMappings.UIDToContainer(uid) |
|
413 | 413 |
if err != nil { |
414 | 414 |
return err |
415 | 415 |
} |
416 |
- xGID, err := idtools.ToContainer(gid, ta.GIDMaps) |
|
416 |
+ hdr.Gid, err = ta.IDMappings.GIDToContainer(gid) |
|
417 | 417 |
if err != nil { |
418 | 418 |
return err |
419 | 419 |
} |
420 |
- hdr.Uid = xUID |
|
421 |
- hdr.Gid = xGID |
|
422 | 420 |
} |
423 | 421 |
|
424 | 422 |
if ta.WhiteoutConverter != nil { |
... | ... |
@@ -640,14 +646,11 @@ func TarWithOptions(srcPath string, options *TarOptions) (io.ReadCloser, error) |
640 | 640 |
} |
641 | 641 |
|
642 | 642 |
go func() { |
643 |
- ta := &tarAppender{ |
|
644 |
- TarWriter: tar.NewWriter(compressWriter), |
|
645 |
- Buffer: pools.BufioWriter32KPool.Get(nil), |
|
646 |
- SeenFiles: make(map[uint64]string), |
|
647 |
- UIDMaps: options.UIDMaps, |
|
648 |
- GIDMaps: options.GIDMaps, |
|
649 |
- WhiteoutConverter: getWhiteoutConverter(options.WhiteoutFormat), |
|
650 |
- } |
|
643 |
+ ta := newTarAppender( |
|
644 |
+ idtools.NewIDMappingsFromMaps(options.UIDMaps, options.GIDMaps), |
|
645 |
+ compressWriter, |
|
646 |
+ ) |
|
647 |
+ ta.WhiteoutConverter = getWhiteoutConverter(options.WhiteoutFormat) |
|
651 | 648 |
|
652 | 649 |
defer func() { |
653 | 650 |
// Make sure to check the error on Close. |
... | ... |
@@ -394,13 +394,8 @@ func ChangesSize(newDir string, changes []Change) int64 { |
394 | 394 |
func ExportChanges(dir string, changes []Change, uidMaps, gidMaps []idtools.IDMap) (io.ReadCloser, error) { |
395 | 395 |
reader, writer := io.Pipe() |
396 | 396 |
go func() { |
397 |
- ta := &tarAppender{ |
|
398 |
- TarWriter: tar.NewWriter(writer), |
|
399 |
- Buffer: pools.BufioWriter32KPool.Get(nil), |
|
400 |
- SeenFiles: make(map[uint64]string), |
|
401 |
- UIDMaps: uidMaps, |
|
402 |
- GIDMaps: gidMaps, |
|
403 |
- } |
|
397 |
+ ta := newTarAppender(idtools.NewIDMappingsFromMaps(uidMaps, gidMaps), writer) |
|
398 |
+ |
|
404 | 399 |
// this buffer is needed for the duration of this piped stream |
405 | 400 |
defer pools.BufioWriter32KPool.Put(ta.Buffer) |
406 | 401 |
|
... | ... |
@@ -99,10 +99,10 @@ func GetRootUIDGID(uidMap, gidMap []IDMap) (int, int, error) { |
99 | 99 |
return uid, gid, nil |
100 | 100 |
} |
101 | 101 |
|
102 |
-// ToContainer takes an id mapping, and uses it to translate a |
|
102 |
+// toContainer takes an id mapping, and uses it to translate a |
|
103 | 103 |
// host ID to the remapped ID. If no map is provided, then the translation |
104 | 104 |
// assumes a 1-to-1 mapping and returns the passed in id |
105 |
-func ToContainer(hostID int, idMap []IDMap) (int, error) { |
|
105 |
+func toContainer(hostID int, idMap []IDMap) (int, error) { |
|
106 | 106 |
if idMap == nil { |
107 | 107 |
return hostID, nil |
108 | 108 |
} |
... | ... |
@@ -169,6 +169,12 @@ func NewIDMappings(username, groupname string) (*IDMappings, error) { |
169 | 169 |
}, nil |
170 | 170 |
} |
171 | 171 |
|
172 |
+// NewIDMappingsFromMaps creates a new mapping from two slices |
|
173 |
+// Deprecated: this is a temporary shim while transitioning to IDMapping |
|
174 |
+func NewIDMappingsFromMaps(uids []IDMap, gids []IDMap) *IDMappings { |
|
175 |
+ return &IDMappings{uids: uids, gids: gids} |
|
176 |
+} |
|
177 |
+ |
|
172 | 178 |
// RootPair returns a uid and gid pair for the root user |
173 | 179 |
func (i *IDMappings) RootPair() (IDPair, error) { |
174 | 180 |
uid, gid, err := GetRootUIDGID(i.uids, i.gids) |
... | ... |
@@ -185,6 +191,21 @@ func (i *IDMappings) GIDToHost(gid int) (int, error) { |
185 | 185 |
return ToHost(gid, i.gids) |
186 | 186 |
} |
187 | 187 |
|
188 |
+// UIDToContainer returns the container UID for the host uid |
|
189 |
+func (i *IDMappings) UIDToContainer(uid int) (int, error) { |
|
190 |
+ return toContainer(uid, i.uids) |
|
191 |
+} |
|
192 |
+ |
|
193 |
+// GIDToContainer returns the container GID for the host gid |
|
194 |
+func (i *IDMappings) GIDToContainer(gid int) (int, error) { |
|
195 |
+ return toContainer(gid, i.gids) |
|
196 |
+} |
|
197 |
+ |
|
198 |
+// Empty returns true if there are no id mappings |
|
199 |
+func (i *IDMappings) Empty() bool { |
|
200 |
+ return len(i.uids) == 0 && len(i.gids) == 0 |
|
201 |
+} |
|
202 |
+ |
|
188 | 203 |
// UIDs return the UID mapping |
189 | 204 |
// TODO: remove this once everything has been refactored to use pairs |
190 | 205 |
func (i *IDMappings) UIDs() []IDMap { |