diff options
Diffstat (limited to 'vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/archive/diff.go')
-rw-r--r-- | vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/archive/diff.go | 279 |
1 files changed, 0 insertions, 279 deletions
diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/archive/diff.go b/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/archive/diff.go deleted file mode 100644 index 887dd54..0000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/archive/diff.go +++ /dev/null | |||
@@ -1,279 +0,0 @@ | |||
1 | package archive | ||
2 | |||
3 | import ( | ||
4 | "archive/tar" | ||
5 | "fmt" | ||
6 | "io" | ||
7 | "io/ioutil" | ||
8 | "os" | ||
9 | "path/filepath" | ||
10 | "runtime" | ||
11 | "strings" | ||
12 | |||
13 | "github.com/fsouza/go-dockerclient/external/github.com/Sirupsen/logrus" | ||
14 | "github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/idtools" | ||
15 | "github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/pools" | ||
16 | "github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/system" | ||
17 | ) | ||
18 | |||
19 | // UnpackLayer unpack `layer` to a `dest`. The stream `layer` can be | ||
20 | // compressed or uncompressed. | ||
21 | // Returns the size in bytes of the contents of the layer. | ||
22 | func UnpackLayer(dest string, layer Reader, options *TarOptions) (size int64, err error) { | ||
23 | tr := tar.NewReader(layer) | ||
24 | trBuf := pools.BufioReader32KPool.Get(tr) | ||
25 | defer pools.BufioReader32KPool.Put(trBuf) | ||
26 | |||
27 | var dirs []*tar.Header | ||
28 | unpackedPaths := make(map[string]struct{}) | ||
29 | |||
30 | if options == nil { | ||
31 | options = &TarOptions{} | ||
32 | } | ||
33 | if options.ExcludePatterns == nil { | ||
34 | options.ExcludePatterns = []string{} | ||
35 | } | ||
36 | remappedRootUID, remappedRootGID, err := idtools.GetRootUIDGID(options.UIDMaps, options.GIDMaps) | ||
37 | if err != nil { | ||
38 | return 0, err | ||
39 | } | ||
40 | |||
41 | aufsTempdir := "" | ||
42 | aufsHardlinks := make(map[string]*tar.Header) | ||
43 | |||
44 | if options == nil { | ||
45 | options = &TarOptions{} | ||
46 | } | ||
47 | // Iterate through the files in the archive. | ||
48 | for { | ||
49 | hdr, err := tr.Next() | ||
50 | if err == io.EOF { | ||
51 | // end of tar archive | ||
52 | break | ||
53 | } | ||
54 | if err != nil { | ||
55 | return 0, err | ||
56 | } | ||
57 | |||
58 | size += hdr.Size | ||
59 | |||
60 | // Normalize name, for safety and for a simple is-root check | ||
61 | hdr.Name = filepath.Clean(hdr.Name) | ||
62 | |||
63 | // Windows does not support filenames with colons in them. Ignore | ||
64 | // these files. This is not a problem though (although it might | ||
65 | // appear that it is). Let's suppose a client is running docker pull. | ||
66 | // The daemon it points to is Windows. Would it make sense for the | ||
67 | // client to be doing a docker pull Ubuntu for example (which has files | ||
68 | // with colons in the name under /usr/share/man/man3)? No, absolutely | ||
69 | // not as it would really only make sense that they were pulling a | ||
70 | // Windows image. However, for development, it is necessary to be able | ||
71 | // to pull Linux images which are in the repository. | ||
72 | // | ||
73 | // TODO Windows. Once the registry is aware of what images are Windows- | ||
74 | // specific or Linux-specific, this warning should be changed to an error | ||
75 | // to cater for the situation where someone does manage to upload a Linux | ||
76 | // image but have it tagged as Windows inadvertently. | ||
77 | if runtime.GOOS == "windows" { | ||
78 | if strings.Contains(hdr.Name, ":") { | ||
79 | logrus.Warnf("Windows: Ignoring %s (is this a Linux image?)", hdr.Name) | ||
80 | continue | ||
81 | } | ||
82 | } | ||
83 | |||
84 | // Note as these operations are platform specific, so must the slash be. | ||
85 | if !strings.HasSuffix(hdr.Name, string(os.PathSeparator)) { | ||
86 | // Not the root directory, ensure that the parent directory exists. | ||
87 | // This happened in some tests where an image had a tarfile without any | ||
88 | // parent directories. | ||
89 | parent := filepath.Dir(hdr.Name) | ||
90 | parentPath := filepath.Join(dest, parent) | ||
91 | |||
92 | if _, err := os.Lstat(parentPath); err != nil && os.IsNotExist(err) { | ||
93 | err = system.MkdirAll(parentPath, 0600) | ||
94 | if err != nil { | ||
95 | return 0, err | ||
96 | } | ||
97 | } | ||
98 | } | ||
99 | |||
100 | // Skip AUFS metadata dirs | ||
101 | if strings.HasPrefix(hdr.Name, WhiteoutMetaPrefix) { | ||
102 | // Regular files inside /.wh..wh.plnk can be used as hardlink targets | ||
103 | // We don't want this directory, but we need the files in them so that | ||
104 | // such hardlinks can be resolved. | ||
105 | if strings.HasPrefix(hdr.Name, WhiteoutLinkDir) && hdr.Typeflag == tar.TypeReg { | ||
106 | basename := filepath.Base(hdr.Name) | ||
107 | aufsHardlinks[basename] = hdr | ||
108 | if aufsTempdir == "" { | ||
109 | if aufsTempdir, err = ioutil.TempDir("", "dockerplnk"); err != nil { | ||
110 | return 0, err | ||
111 | } | ||
112 | defer os.RemoveAll(aufsTempdir) | ||
113 | } | ||
114 | if err := createTarFile(filepath.Join(aufsTempdir, basename), dest, hdr, tr, true, nil); err != nil { | ||
115 | return 0, err | ||
116 | } | ||
117 | } | ||
118 | |||
119 | if hdr.Name != WhiteoutOpaqueDir { | ||
120 | continue | ||
121 | } | ||
122 | } | ||
123 | path := filepath.Join(dest, hdr.Name) | ||
124 | rel, err := filepath.Rel(dest, path) | ||
125 | if err != nil { | ||
126 | return 0, err | ||
127 | } | ||
128 | |||
129 | // Note as these operations are platform specific, so must the slash be. | ||
130 | if strings.HasPrefix(rel, ".."+string(os.PathSeparator)) { | ||
131 | return 0, breakoutError(fmt.Errorf("%q is outside of %q", hdr.Name, dest)) | ||
132 | } | ||
133 | base := filepath.Base(path) | ||
134 | |||
135 | if strings.HasPrefix(base, WhiteoutPrefix) { | ||
136 | dir := filepath.Dir(path) | ||
137 | if base == WhiteoutOpaqueDir { | ||
138 | _, err := os.Lstat(dir) | ||
139 | if err != nil { | ||
140 | return 0, err | ||
141 | } | ||
142 | err = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { | ||
143 | if err != nil { | ||
144 | if os.IsNotExist(err) { | ||
145 | err = nil // parent was deleted | ||
146 | } | ||
147 | return err | ||
148 | } | ||
149 | if path == dir { | ||
150 | return nil | ||
151 | } | ||
152 | if _, exists := unpackedPaths[path]; !exists { | ||
153 | err := os.RemoveAll(path) | ||
154 | return err | ||
155 | } | ||
156 | return nil | ||
157 | }) | ||
158 | if err != nil { | ||
159 | return 0, err | ||
160 | } | ||
161 | } else { | ||
162 | originalBase := base[len(WhiteoutPrefix):] | ||
163 | originalPath := filepath.Join(dir, originalBase) | ||
164 | if err := os.RemoveAll(originalPath); err != nil { | ||
165 | return 0, err | ||
166 | } | ||
167 | } | ||
168 | } else { | ||
169 | // If path exits we almost always just want to remove and replace it. | ||
170 | // The only exception is when it is a directory *and* the file from | ||
171 | // the layer is also a directory. Then we want to merge them (i.e. | ||
172 | // just apply the metadata from the layer). | ||
173 | if fi, err := os.Lstat(path); err == nil { | ||
174 | if !(fi.IsDir() && hdr.Typeflag == tar.TypeDir) { | ||
175 | if err := os.RemoveAll(path); err != nil { | ||
176 | return 0, err | ||
177 | } | ||
178 | } | ||
179 | } | ||
180 | |||
181 | trBuf.Reset(tr) | ||
182 | srcData := io.Reader(trBuf) | ||
183 | srcHdr := hdr | ||
184 | |||
185 | // Hard links into /.wh..wh.plnk don't work, as we don't extract that directory, so | ||
186 | // we manually retarget these into the temporary files we extracted them into | ||
187 | if hdr.Typeflag == tar.TypeLink && strings.HasPrefix(filepath.Clean(hdr.Linkname), WhiteoutLinkDir) { | ||
188 | linkBasename := filepath.Base(hdr.Linkname) | ||
189 | srcHdr = aufsHardlinks[linkBasename] | ||
190 | if srcHdr == nil { | ||
191 | return 0, fmt.Errorf("Invalid aufs hardlink") | ||
192 | } | ||
193 | tmpFile, err := os.Open(filepath.Join(aufsTempdir, linkBasename)) | ||
194 | if err != nil { | ||
195 | return 0, err | ||
196 | } | ||
197 | defer tmpFile.Close() | ||
198 | srcData = tmpFile | ||
199 | } | ||
200 | |||
201 | // if the options contain a uid & gid maps, convert header uid/gid | ||
202 | // entries using the maps such that lchown sets the proper mapped | ||
203 | // uid/gid after writing the file. We only perform this mapping if | ||
204 | // the file isn't already owned by the remapped root UID or GID, as | ||
205 | // that specific uid/gid has no mapping from container -> host, and | ||
206 | // those files already have the proper ownership for inside the | ||
207 | // container. | ||
208 | if srcHdr.Uid != remappedRootUID { | ||
209 | xUID, err := idtools.ToHost(srcHdr.Uid, options.UIDMaps) | ||
210 | if err != nil { | ||
211 | return 0, err | ||
212 | } | ||
213 | srcHdr.Uid = xUID | ||
214 | } | ||
215 | if srcHdr.Gid != remappedRootGID { | ||
216 | xGID, err := idtools.ToHost(srcHdr.Gid, options.GIDMaps) | ||
217 | if err != nil { | ||
218 | return 0, err | ||
219 | } | ||
220 | srcHdr.Gid = xGID | ||
221 | } | ||
222 | if err := createTarFile(path, dest, srcHdr, srcData, true, nil); err != nil { | ||
223 | return 0, err | ||
224 | } | ||
225 | |||
226 | // Directory mtimes must be handled at the end to avoid further | ||
227 | // file creation in them to modify the directory mtime | ||
228 | if hdr.Typeflag == tar.TypeDir { | ||
229 | dirs = append(dirs, hdr) | ||
230 | } | ||
231 | unpackedPaths[path] = struct{}{} | ||
232 | } | ||
233 | } | ||
234 | |||
235 | for _, hdr := range dirs { | ||
236 | path := filepath.Join(dest, hdr.Name) | ||
237 | if err := system.Chtimes(path, hdr.AccessTime, hdr.ModTime); err != nil { | ||
238 | return 0, err | ||
239 | } | ||
240 | } | ||
241 | |||
242 | return size, nil | ||
243 | } | ||
244 | |||
245 | // ApplyLayer parses a diff in the standard layer format from `layer`, | ||
246 | // and applies it to the directory `dest`. The stream `layer` can be | ||
247 | // compressed or uncompressed. | ||
248 | // Returns the size in bytes of the contents of the layer. | ||
249 | func ApplyLayer(dest string, layer Reader) (int64, error) { | ||
250 | return applyLayerHandler(dest, layer, &TarOptions{}, true) | ||
251 | } | ||
252 | |||
253 | // ApplyUncompressedLayer parses a diff in the standard layer format from | ||
254 | // `layer`, and applies it to the directory `dest`. The stream `layer` | ||
255 | // can only be uncompressed. | ||
256 | // Returns the size in bytes of the contents of the layer. | ||
257 | func ApplyUncompressedLayer(dest string, layer Reader, options *TarOptions) (int64, error) { | ||
258 | return applyLayerHandler(dest, layer, options, false) | ||
259 | } | ||
260 | |||
261 | // do the bulk load of ApplyLayer, but allow for not calling DecompressStream | ||
262 | func applyLayerHandler(dest string, layer Reader, options *TarOptions, decompress bool) (int64, error) { | ||
263 | dest = filepath.Clean(dest) | ||
264 | |||
265 | // We need to be able to set any perms | ||
266 | oldmask, err := system.Umask(0) | ||
267 | if err != nil { | ||
268 | return 0, err | ||
269 | } | ||
270 | defer system.Umask(oldmask) // ignore err, ErrNotSupportedPlatform | ||
271 | |||
272 | if decompress { | ||
273 | layer, err = DecompressStream(layer) | ||
274 | if err != nil { | ||
275 | return 0, err | ||
276 | } | ||
277 | } | ||
278 | return UnpackLayer(dest, layer, options) | ||
279 | } | ||