Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
| ... | ... |
@@ -322,7 +322,7 @@ func (a *Driver) Diff(id, parent string) (archive.Archive, error) {
|
| 322 | 322 |
// AUFS doesn't need the parent layer to produce a diff. |
| 323 | 323 |
return archive.TarWithOptions(path.Join(a.rootPath(), "diff", id), &archive.TarOptions{
|
| 324 | 324 |
Compression: archive.Uncompressed, |
| 325 |
- ExcludePatterns: []string{".wh..wh.*", "!.wh..wh..opq"},
|
|
| 325 |
+ ExcludePatterns: []string{archive.WhiteoutMetaPrefix + "*", "!" + archive.WhiteoutOpaqueDir},
|
|
| 326 | 326 |
}) |
| 327 | 327 |
} |
| 328 | 328 |
|
| ... | ... |
@@ -102,7 +102,7 @@ func Changes(layers []string, rw string) ([]Change, error) {
|
| 102 | 102 |
} |
| 103 | 103 |
|
| 104 | 104 |
// Skip AUFS metadata |
| 105 |
- if matched, err := filepath.Match(string(os.PathSeparator)+".wh..wh.*", path); err != nil || matched {
|
|
| 105 |
+ if matched, err := filepath.Match(string(os.PathSeparator)+WhiteoutMetaPrefix+"*", path); err != nil || matched {
|
|
| 106 | 106 |
return err |
| 107 | 107 |
} |
| 108 | 108 |
|
| ... | ... |
@@ -113,8 +113,8 @@ func Changes(layers []string, rw string) ([]Change, error) {
|
| 113 | 113 |
// Find out what kind of modification happened |
| 114 | 114 |
file := filepath.Base(path) |
| 115 | 115 |
// If there is a whiteout, then the file was removed |
| 116 |
- if strings.HasPrefix(file, ".wh.") {
|
|
| 117 |
- originalFile := file[len(".wh."):]
|
|
| 116 |
+ if strings.HasPrefix(file, WhiteoutPrefix) {
|
|
| 117 |
+ originalFile := file[len(WhiteoutPrefix):] |
|
| 118 | 118 |
change.Path = filepath.Join(filepath.Dir(path), originalFile) |
| 119 | 119 |
change.Kind = ChangeDelete |
| 120 | 120 |
} else {
|
| ... | ... |
@@ -362,7 +362,7 @@ func ExportChanges(dir string, changes []Change) (Archive, error) {
|
| 362 | 362 |
if change.Kind == ChangeDelete {
|
| 363 | 363 |
whiteOutDir := filepath.Dir(change.Path) |
| 364 | 364 |
whiteOutBase := filepath.Base(change.Path) |
| 365 |
- whiteOut := filepath.Join(whiteOutDir, ".wh."+whiteOutBase) |
|
| 365 |
+ whiteOut := filepath.Join(whiteOutDir, WhiteoutPrefix+whiteOutBase) |
|
| 366 | 366 |
timestamp := time.Now() |
| 367 | 367 |
hdr := &tar.Header{
|
| 368 | 368 |
Name: whiteOut[1:], |
| ... | ... |
@@ -83,11 +83,11 @@ func UnpackLayer(dest string, layer Reader) (size int64, err error) {
|
| 83 | 83 |
} |
| 84 | 84 |
|
| 85 | 85 |
// Skip AUFS metadata dirs |
| 86 |
- if strings.HasPrefix(hdr.Name, ".wh..wh.") {
|
|
| 86 |
+ if strings.HasPrefix(hdr.Name, WhiteoutMetaPrefix) {
|
|
| 87 | 87 |
// Regular files inside /.wh..wh.plnk can be used as hardlink targets |
| 88 | 88 |
// We don't want this directory, but we need the files in them so that |
| 89 | 89 |
// such hardlinks can be resolved. |
| 90 |
- if strings.HasPrefix(hdr.Name, ".wh..wh.plnk") && hdr.Typeflag == tar.TypeReg {
|
|
| 90 |
+ if strings.HasPrefix(hdr.Name, WhiteoutLinkDir) && hdr.Typeflag == tar.TypeReg {
|
|
| 91 | 91 |
basename := filepath.Base(hdr.Name) |
| 92 | 92 |
aufsHardlinks[basename] = hdr |
| 93 | 93 |
if aufsTempdir == "" {
|
| ... | ... |
@@ -101,7 +101,7 @@ func UnpackLayer(dest string, layer Reader) (size int64, err error) {
|
| 101 | 101 |
} |
| 102 | 102 |
} |
| 103 | 103 |
|
| 104 |
- if hdr.Name != ".wh..wh..opq" {
|
|
| 104 |
+ if hdr.Name != WhiteoutOpaqueDir {
|
|
| 105 | 105 |
continue |
| 106 | 106 |
} |
| 107 | 107 |
} |
| ... | ... |
@@ -117,10 +117,9 @@ func UnpackLayer(dest string, layer Reader) (size int64, err error) {
|
| 117 | 117 |
} |
| 118 | 118 |
base := filepath.Base(path) |
| 119 | 119 |
|
| 120 |
- if strings.HasPrefix(base, ".wh.") {
|
|
| 121 |
- originalBase := base[len(".wh."):]
|
|
| 120 |
+ if strings.HasPrefix(base, WhiteoutPrefix) {
|
|
| 122 | 121 |
dir := filepath.Dir(path) |
| 123 |
- if originalBase == ".wh..opq" {
|
|
| 122 |
+ if base == WhiteoutOpaqueDir {
|
|
| 124 | 123 |
fi, err := os.Lstat(dir) |
| 125 | 124 |
if err != nil && !os.IsNotExist(err) {
|
| 126 | 125 |
return 0, err |
| ... | ... |
@@ -132,6 +131,7 @@ func UnpackLayer(dest string, layer Reader) (size int64, err error) {
|
| 132 | 132 |
return 0, err |
| 133 | 133 |
} |
| 134 | 134 |
} else {
|
| 135 |
+ originalBase := base[len(WhiteoutPrefix):] |
|
| 135 | 136 |
originalPath := filepath.Join(dir, originalBase) |
| 136 | 137 |
if err := os.RemoveAll(originalPath); err != nil {
|
| 137 | 138 |
return 0, err |
| ... | ... |
@@ -156,7 +156,7 @@ func UnpackLayer(dest string, layer Reader) (size int64, err error) {
|
| 156 | 156 |
|
| 157 | 157 |
// Hard links into /.wh..wh.plnk don't work, as we don't extract that directory, so |
| 158 | 158 |
// we manually retarget these into the temporary files we extracted them into |
| 159 |
- if hdr.Typeflag == tar.TypeLink && strings.HasPrefix(filepath.Clean(hdr.Linkname), ".wh..wh.plnk") {
|
|
| 159 |
+ if hdr.Typeflag == tar.TypeLink && strings.HasPrefix(filepath.Clean(hdr.Linkname), WhiteoutLinkDir) {
|
|
| 160 | 160 |
linkBasename := filepath.Base(hdr.Linkname) |
| 161 | 161 |
srcHdr = aufsHardlinks[linkBasename] |
| 162 | 162 |
if srcHdr == nil {
|
| 163 | 163 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,23 @@ |
| 0 |
+package archive |
|
| 1 |
+ |
|
| 2 |
+// Whiteouts are files with a special meaning for the layered filesystem. |
|
| 3 |
+// Docker uses AUFS whiteout files inside exported archives. In other |
|
| 4 |
+// filesystems these files are generated/handled on tar creation/extraction. |
|
| 5 |
+ |
|
| 6 |
+// WhiteoutPrefix prefix means file is a whiteout. If this is followed by a |
|
| 7 |
+// filename this means that file has been removed from the base layer. |
|
| 8 |
+const WhiteoutPrefix = ".wh." |
|
| 9 |
+ |
|
| 10 |
+// WhiteoutMetaPrefix prefix means whiteout has a special meaning and is not |
|
| 11 |
+// for remoing an actaul file. Normally these files are excluded from exported |
|
| 12 |
+// archives. |
|
| 13 |
+const WhiteoutMetaPrefix = WhiteoutPrefix + WhiteoutPrefix |
|
| 14 |
+ |
|
| 15 |
+// WhiteoutLinkDir is a directory AUFS uses for storing hardlink links to other |
|
| 16 |
+// layers. Normally these should not go into exported archives and all changed |
|
| 17 |
+// hardlinks should be copied to the top layer. |
|
| 18 |
+const WhiteoutLinkDir = WhiteoutMetaPrefix + "plnk" |
|
| 19 |
+ |
|
| 20 |
+// WhiteoutOpaqueDir file means directory has been made opaque - meaning |
|
| 21 |
+// readdir calls to this directory do not follow to lower layers. |
|
| 22 |
+const WhiteoutOpaqueDir = WhiteoutMetaPrefix + ".opq" |