summaryrefslogtreecommitdiffstats
path: root/recipes-containers/oci-image-tools
diff options
context:
space:
mode:
authorBruce Ashfield <bruce.ashfield@windriver.com>2017-06-06 23:44:34 -0400
committerBruce Ashfield <bruce.ashfield@windriver.com>2017-06-06 23:44:34 -0400
commit3e1d16db4aa3a76aa4086de49f3b62337c7f4efa (patch)
treed7d8427a7b74f58a6068e549dd205959d9140447 /recipes-containers/oci-image-tools
parentdd49614c70364a11dc50798f32f1b2ffa3d0409e (diff)
downloadmeta-virtualization-3e1d16db4aa3a76aa4086de49f3b62337c7f4efa.tar.gz
oci-image-tools: update to latest and fix symlink issues
Updating to the latest oci-image-tools for better support in unpack/creating runtime bundles. With this update, we get a single tool with subcommands, versus separate commands previously. We also add two proposed (but not merged) patches that can deal with existing symlinks when unpacking layers. Without this, we fail to unpack many complex containers due to duplicate files in layers. Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>
Diffstat (limited to 'recipes-containers/oci-image-tools')
-rw-r--r--recipes-containers/oci-image-tools/files/0001-image-manifest-Recursively-remove-pre-existing-entri.patch78
-rw-r--r--recipes-containers/oci-image-tools/files/0002-image-manifest-Split-unpackLayerEntry-into-its-own-f.patch242
-rw-r--r--recipes-containers/oci-image-tools/oci-image-tools_git.bb14
3 files changed, 328 insertions, 6 deletions
diff --git a/recipes-containers/oci-image-tools/files/0001-image-manifest-Recursively-remove-pre-existing-entri.patch b/recipes-containers/oci-image-tools/files/0001-image-manifest-Recursively-remove-pre-existing-entri.patch
new file mode 100644
index 00000000..d2cacc2e
--- /dev/null
+++ b/recipes-containers/oci-image-tools/files/0001-image-manifest-Recursively-remove-pre-existing-entri.patch
@@ -0,0 +1,78 @@
1From 1f205c0aec5ea9e983d61a64e7ce871ae416bebd Mon Sep 17 00:00:00 2001
2From: "W. Trevor King" <wking@tremily.us>
3Date: Tue, 18 Oct 2016 02:16:46 -0700
4Subject: [PATCH 1/2] image/manifest: Recursively remove pre-existing entries
5 when unpacking
6
7Implementing the logic that is in-flight with [1], but using recursive
8removal [2]. GNU tar has a --recursive-unlink option that's not
9enabled by default, with the motivation being something like "folks
10would be mad if we blew away a full tree and replaced it with a broken
11symlink" [3]. That makes sense for working filesystems, but we're
12building the rootfs from scratch here so losing information is not a
13concern. This commit always uses recursive removal to get that old
14thing off the filesystem (whatever it takes ;).
15
16The exception to the removal is if both the tar entry and existing
17path occupant are directories. In this case we want to use GNU tar's
18default --overwrite-dir behavior, but unpackLayer's metadata handling
19is currently very weak so I've left it at "don't delete the old
20directory".
21
22The reworked directory case also fixes a minor bug from 44210d05
23(cmd/oci-image-tool: fix unpacking..., 2016-07-22, #177) where the:
24
25 if fi, err := os.Lstat(path); !(err == nil && fi.IsDir()) {
26
27block would not error out if the Lstat failed for a reason besides the
28acceptable IsNotExist. Instead, it would attempt to call MkdirAll,
29which would probably fail for the same reason that Lstat failed
30(e.g. ENOTDIR). But it's better to handle the Lstat errors directly.
31
32[1]: https://github.com/opencontainers/image-spec/pull/317
33[2]: https://github.com/opencontainers/image-spec/pull/317/files#r79214718
34[3]: https://www.gnu.org/software/tar/manual/html_node/Dealing-with-Old-Files.html
35
36Signed-off-by: W. Trevor King <wking@tremily.us>
37---
38 image/manifest.go | 22 +++++++++++++++++++---
39 1 file changed, 19 insertions(+), 3 deletions(-)
40
41diff --git a/image/manifest.go b/image/manifest.go
42index 8834c1e5f2f0..144bd4f62219 100644
43--- a/image/manifest.go
44+++ b/image/manifest.go
45@@ -253,11 +253,27 @@ loop:
46 continue loop
47 }
48
49+ if hdr.Typeflag != tar.TypeDir {
50+ err = os.RemoveAll(path)
51+ if err != nil && !os.IsNotExist(err) {
52+ return err
53+ }
54+ }
55+
56 switch hdr.Typeflag {
57 case tar.TypeDir:
58- if fi, err := os.Lstat(path); !(err == nil && fi.IsDir()) {
59- if err2 := os.MkdirAll(path, info.Mode()); err2 != nil {
60- return errors.Wrap(err2, "error creating directory")
61+ fi, err := os.Lstat(path)
62+ if err != nil && !os.IsNotExist(err) {
63+ return err
64+ }
65+ if os.IsNotExist(err) || !fi.IsDir() {
66+ err = os.RemoveAll(path)
67+ if err != nil && !os.IsNotExist(err) {
68+ return err
69+ }
70+ err = os.MkdirAll(path, info.Mode())
71+ if err != nil {
72+ return err
73 }
74 }
75
76--
772.4.0.53.g8440f74
78
diff --git a/recipes-containers/oci-image-tools/files/0002-image-manifest-Split-unpackLayerEntry-into-its-own-f.patch b/recipes-containers/oci-image-tools/files/0002-image-manifest-Split-unpackLayerEntry-into-its-own-f.patch
new file mode 100644
index 00000000..9cf513ec
--- /dev/null
+++ b/recipes-containers/oci-image-tools/files/0002-image-manifest-Split-unpackLayerEntry-into-its-own-f.patch
@@ -0,0 +1,242 @@
1From 1e55f2a83b1f644803b640b72171b4ae0d95217b Mon Sep 17 00:00:00 2001
2From: "W. Trevor King" <wking@tremily.us>
3Date: Thu, 20 Oct 2016 23:30:22 -0700
4Subject: [PATCH 2/2] image/manifest: Split unpackLayerEntry into its own
5 function
6
7To help address:
8
9 $ make lint
10 checking lint
11 image/manifest.go:140::warning: cyclomatic complexity 39 of function unpackLayer() is high (> 35) (gocyclo)
12 ...
13
14Signed-off-by: W. Trevor King <wking@tremily.us>
15---
16 image/manifest.go | 185 +++++++++++++++++++++++++++++-------------------------
17 1 file changed, 100 insertions(+), 85 deletions(-)
18
19diff --git a/image/manifest.go b/image/manifest.go
20index 144bd4f62219..dfd5a83f70e4 100644
21--- a/image/manifest.go
22+++ b/image/manifest.go
23@@ -218,116 +218,131 @@ loop:
24 return errors.Wrapf(err, "error advancing tar stream")
25 }
26
27- hdr.Name = filepath.Clean(hdr.Name)
28- if !strings.HasSuffix(hdr.Name, string(os.PathSeparator)) {
29- // Not the root directory, ensure that the parent directory exists
30- parent := filepath.Dir(hdr.Name)
31- parentPath := filepath.Join(dest, parent)
32- if _, err2 := os.Lstat(parentPath); err2 != nil && os.IsNotExist(err2) {
33- if err3 := os.MkdirAll(parentPath, 0755); err3 != nil {
34- return err3
35- }
36- }
37- }
38- path := filepath.Join(dest, hdr.Name)
39- if entries[path] {
40- return fmt.Errorf("duplicate entry for %s", path)
41- }
42- entries[path] = true
43- rel, err := filepath.Rel(dest, path)
44+ var whiteout bool
45+ whiteout, err = unpackLayerEntry(dest, hdr, tr, &entries)
46 if err != nil {
47 return err
48 }
49- info := hdr.FileInfo()
50- if strings.HasPrefix(rel, ".."+string(os.PathSeparator)) {
51- return fmt.Errorf("%q is outside of %q", hdr.Name, dest)
52+ if whiteout {
53+ continue loop
54 }
55
56- if strings.HasPrefix(info.Name(), ".wh.") {
57- path = strings.Replace(path, ".wh.", "", 1)
58+ // Directory mtimes must be handled at the end to avoid further
59+ // file creation in them to modify the directory mtime
60+ if hdr.Typeflag == tar.TypeDir {
61+ dirs = append(dirs, hdr)
62+ }
63+ }
64+ for _, hdr := range dirs {
65+ path := filepath.Join(dest, hdr.Name)
66
67- if err := os.RemoveAll(path); err != nil {
68- return errors.Wrap(err, "unable to delete whiteout path")
69+ finfo := hdr.FileInfo()
70+ // I believe the old version was using time.Now().UTC() to overcome an
71+ // invalid error from chtimes.....but here we lose hdr.AccessTime like this...
72+ if err := os.Chtimes(path, time.Now().UTC(), finfo.ModTime()); err != nil {
73+ return errors.Wrap(err, "error changing time")
74+ }
75+ }
76+ return nil
77+}
78+
79+// unpackLayerEntry unpacks a single entry from a layer.
80+func unpackLayerEntry(dest string, header *tar.Header, reader io.Reader, entries *map[string]bool) (whiteout bool, err error) {
81+ header.Name = filepath.Clean(header.Name)
82+ if !strings.HasSuffix(header.Name, string(os.PathSeparator)) {
83+ // Not the root directory, ensure that the parent directory exists
84+ parent := filepath.Dir(header.Name)
85+ parentPath := filepath.Join(dest, parent)
86+ if _, err2 := os.Lstat(parentPath); err2 != nil && os.IsNotExist(err2) {
87+ if err3 := os.MkdirAll(parentPath, 0755); err3 != nil {
88+ return false, err3
89 }
90+ }
91+ }
92+ path := filepath.Join(dest, header.Name)
93+ if (*entries)[path] {
94+ return false, fmt.Errorf("duplicate entry for %s", path)
95+ }
96+ (*entries)[path] = true
97+ rel, err := filepath.Rel(dest, path)
98+ if err != nil {
99+ return false, err
100+ }
101+ info := header.FileInfo()
102+ if strings.HasPrefix(rel, ".."+string(os.PathSeparator)) {
103+ return false, fmt.Errorf("%q is outside of %q", header.Name, dest)
104+ }
105
106- continue loop
107+ if strings.HasPrefix(info.Name(), ".wh.") {
108+ path = strings.Replace(path, ".wh.", "", 1)
109+
110+ if err = os.RemoveAll(path); err != nil {
111+ return true, errors.Wrap(err, "unable to delete whiteout path")
112 }
113
114- if hdr.Typeflag != tar.TypeDir {
115- err = os.RemoveAll(path)
116- if err != nil && !os.IsNotExist(err) {
117- return err
118- }
119+ return true, nil
120+ }
121+
122+ if header.Typeflag != tar.TypeDir {
123+ err = os.RemoveAll(path)
124+ if err != nil && !os.IsNotExist(err) {
125+ return false, err
126 }
127+ }
128
129- switch hdr.Typeflag {
130- case tar.TypeDir:
131- fi, err := os.Lstat(path)
132+ switch header.Typeflag {
133+ case tar.TypeDir:
134+ fi, err := os.Lstat(path)
135+ if err != nil && !os.IsNotExist(err) {
136+ return false, err
137+ }
138+ if os.IsNotExist(err) || !fi.IsDir() {
139+ err = os.RemoveAll(path)
140 if err != nil && !os.IsNotExist(err) {
141- return err
142- }
143- if os.IsNotExist(err) || !fi.IsDir() {
144- err = os.RemoveAll(path)
145- if err != nil && !os.IsNotExist(err) {
146- return err
147- }
148- err = os.MkdirAll(path, info.Mode())
149- if err != nil {
150- return err
151- }
152+ return false, err
153 }
154-
155- case tar.TypeReg, tar.TypeRegA:
156- f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, info.Mode())
157+ err = os.MkdirAll(path, info.Mode())
158 if err != nil {
159- return errors.Wrap(err, "unable to open file")
160+ return false, err
161 }
162+ }
163
164- if _, err := io.Copy(f, tr); err != nil {
165- f.Close()
166- return errors.Wrap(err, "unable to copy")
167- }
168- f.Close()
169+ case tar.TypeReg, tar.TypeRegA:
170+ f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, info.Mode())
171+ if err != nil {
172+ return false, errors.Wrap(err, "unable to open file")
173+ }
174
175- case tar.TypeLink:
176- target := filepath.Join(dest, hdr.Linkname)
177+ if _, err := io.Copy(f, reader); err != nil {
178+ f.Close()
179+ return false, errors.Wrap(err, "unable to copy")
180+ }
181+ f.Close()
182
183- if !strings.HasPrefix(target, dest) {
184- return fmt.Errorf("invalid hardlink %q -> %q", target, hdr.Linkname)
185- }
186+ case tar.TypeLink:
187+ target := filepath.Join(dest, header.Linkname)
188
189- if err := os.Link(target, path); err != nil {
190- return err
191- }
192+ if !strings.HasPrefix(target, dest) {
193+ return false, fmt.Errorf("invalid hardlink %q -> %q", target, header.Linkname)
194+ }
195
196- case tar.TypeSymlink:
197- target := filepath.Join(filepath.Dir(path), hdr.Linkname)
198+ if err := os.Link(target, path); err != nil {
199+ return false, err
200+ }
201
202- if !strings.HasPrefix(target, dest) {
203- return fmt.Errorf("invalid symlink %q -> %q", path, hdr.Linkname)
204- }
205+ case tar.TypeSymlink:
206+ target := filepath.Join(filepath.Dir(path), header.Linkname)
207
208- if err := os.Symlink(hdr.Linkname, path); err != nil {
209- return err
210- }
211- case tar.TypeXGlobalHeader:
212- return nil
213+ if !strings.HasPrefix(target, dest) {
214+ return false, fmt.Errorf("invalid symlink %q -> %q", path, header.Linkname)
215 }
216- // Directory mtimes must be handled at the end to avoid further
217- // file creation in them to modify the directory mtime
218- if hdr.Typeflag == tar.TypeDir {
219- dirs = append(dirs, hdr)
220- }
221- }
222- for _, hdr := range dirs {
223- path := filepath.Join(dest, hdr.Name)
224
225- finfo := hdr.FileInfo()
226- // I believe the old version was using time.Now().UTC() to overcome an
227- // invalid error from chtimes.....but here we lose hdr.AccessTime like this...
228- if err := os.Chtimes(path, time.Now().UTC(), finfo.ModTime()); err != nil {
229- return errors.Wrap(err, "error changing time")
230+ if err := os.Symlink(header.Linkname, path); err != nil {
231+ return false, err
232 }
233+ case tar.TypeXGlobalHeader:
234+ return false, nil
235 }
236- return nil
237+
238+ return false, nil
239 }
240--
2412.4.0.53.g8440f74
242
diff --git a/recipes-containers/oci-image-tools/oci-image-tools_git.bb b/recipes-containers/oci-image-tools/oci-image-tools_git.bb
index 29a89266..393bd7b8 100644
--- a/recipes-containers/oci-image-tools/oci-image-tools_git.bb
+++ b/recipes-containers/oci-image-tools/oci-image-tools_git.bb
@@ -12,8 +12,11 @@ DEPENDS = "\
12 spf13-pflag \ 12 spf13-pflag \
13 " 13 "
14 14
15SRC_URI = "git://github.com/opencontainers/image-tools.git" 15SRC_URI = "git://github.com/opencontainers/image-tools.git \
16SRCREV = "a358e03fde4e3628bf9fb7656bf643b63f975636" 16 file://0001-image-manifest-Recursively-remove-pre-existing-entri.patch \
17 file://0002-image-manifest-Split-unpackLayerEntry-into-its-own-f.patch"
18
19SRCREV = "d0c8533b0a2c68344ff2c8aff03d7fc2dff3a108"
17PV = "0.1.0+git${SRCPV}" 20PV = "0.1.0+git${SRCPV}"
18 21
19S = "${WORKDIR}/git" 22S = "${WORKDIR}/git"
@@ -38,6 +41,7 @@ do_compile() {
38 ln -sfn . "${S}/vendor/src" 41 ln -sfn . "${S}/vendor/src"
39 mkdir -p "${S}/vendor/src/github.com/opencontainers/image-tools/" 42 mkdir -p "${S}/vendor/src/github.com/opencontainers/image-tools/"
40 ln -sfn "${S}/image" "${S}/vendor/src/github.com/opencontainers/image-tools/image" 43 ln -sfn "${S}/image" "${S}/vendor/src/github.com/opencontainers/image-tools/image"
44 ln -sfn "${S}/version" "${S}/vendor/src/github.com/opencontainers/image-tools/version"
41 export GOPATH="${S}/vendor" 45 export GOPATH="${S}/vendor"
42 46
43 # Pass the needed cflags/ldflags so that cgo 47 # Pass the needed cflags/ldflags so that cgo
@@ -48,14 +52,12 @@ do_compile() {
48 export CGO_CFLAGS="${BUILDSDK_CFLAGS} --sysroot=${STAGING_DIR_TARGET}" 52 export CGO_CFLAGS="${BUILDSDK_CFLAGS} --sysroot=${STAGING_DIR_TARGET}"
49 export CGO_LDFLAGS="${BUILDSDK_LDFLAGS} --sysroot=${STAGING_DIR_TARGET}" 53 export CGO_LDFLAGS="${BUILDSDK_LDFLAGS} --sysroot=${STAGING_DIR_TARGET}"
50 54
51 oe_runmake tools 55 oe_runmake tool
52} 56}
53 57
54do_install() { 58do_install() {
55 install -d ${D}/${sbindir} 59 install -d ${D}/${sbindir}
56 install ${S}/oci-create-runtime-bundle ${D}/${sbindir}/ 60 install ${S}/oci-image-tool ${D}/${sbindir}/
57 install ${S}/oci-image-validate ${D}/${sbindir}/
58 install ${S}/oci-unpack ${D}/${sbindir}/
59} 61}
60 62
61INSANE_SKIP_${PN} += "ldflags" 63INSANE_SKIP_${PN} += "ldflags"