Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
Tonis Tiigi authored on 2015/09/30 02:18:28... | ... |
@@ -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" |