Skip to content

Commit 44210d0

Browse files
committed
cmd/oci-image-tool: fix unpacking...
Signed-off-by: Antonio Murdaca <[email protected]>
1 parent 6541392 commit 44210d0

File tree

3 files changed

+49
-15
lines changed

3 files changed

+49
-15
lines changed

image/config.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ type config struct {
5151

5252
func findConfig(w walker, d *descriptor) (*config, error) {
5353
var c config
54-
cpath := filepath.Join("blobs", d.getDigest())
54+
cpath := filepath.Join("blobs", d.normalizeDigest())
5555

5656
f := func(path string, info os.FileInfo, r io.Reader) error {
5757
if info.IsDir() {
@@ -97,13 +97,15 @@ func (c *config) runtimeSpec(rootfs string) (*specs.Spec, error) {
9797

9898
var s specs.Spec
9999
s.Version = "0.5.0"
100+
// we should at least apply the default spec, otherwise this is totally useless
101+
s.Process.Terminal = true
100102
s.Root.Path = rootfs
101103
s.Process.Cwd = "/"
102104
if c.Config.WorkingDir != "" {
103105
s.Process.Cwd = c.Config.WorkingDir
104106
}
105107
s.Process.Env = append(s.Process.Env, c.Config.Env...)
106-
s.Process.Args = append(s.Process.Env, c.Config.Entrypoint...)
108+
s.Process.Args = append(s.Process.Args, c.Config.Entrypoint...)
107109
s.Process.Args = append(s.Process.Args, c.Config.Cmd...)
108110

109111
if len(s.Process.Args) == 0 {

image/descriptor.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ type descriptor struct {
3333
Size int64 `json:"size"`
3434
}
3535

36-
func (d *descriptor) getDigest() string {
36+
func (d *descriptor) normalizeDigest() string {
3737
return strings.Replace(d.Digest, ":", "-", -1)
3838
}
3939

@@ -76,7 +76,7 @@ func (d *descriptor) validate(w walker) error {
7676
}
7777

7878
digest, err := filepath.Rel("blobs", filepath.Clean(path))
79-
if err != nil || d.getDigest() != digest {
79+
if err != nil || d.normalizeDigest() != digest {
8080
return nil // ignore
8181
}
8282

@@ -89,11 +89,11 @@ func (d *descriptor) validate(w walker) error {
8989

9090
switch err := w.walk(f); err {
9191
case nil:
92-
return fmt.Errorf("%s: not found", d.getDigest())
92+
return fmt.Errorf("%s: not found", d.normalizeDigest())
9393
case errEOW:
9494
// found, continue below
9595
default:
96-
return errors.Wrapf(err, "%s: validation failed", d.getDigest())
96+
return errors.Wrapf(err, "%s: validation failed", d.normalizeDigest())
9797
}
9898

9999
return nil

image/manifest.go

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ type manifest struct {
3838

3939
func findManifest(w walker, d *descriptor) (*manifest, error) {
4040
var m manifest
41-
mpath := filepath.Join("blobs", d.getDigest())
41+
mpath := filepath.Join("blobs", d.normalizeDigest())
4242

4343
f := func(path string, info os.FileInfo, r io.Reader) error {
4444
if info.IsDir() {
@@ -107,7 +107,7 @@ func (m *manifest) unpack(w walker, dest string) error {
107107
}
108108

109109
dd, err := filepath.Rel("blobs", filepath.Clean(path))
110-
if err != nil || d.Digest != dd {
110+
if err != nil || d.normalizeDigest() != dd {
111111
return nil // ignore
112112
}
113113

@@ -134,6 +134,7 @@ func unpackLayer(dest string, r io.Reader) error {
134134
}
135135
defer gz.Close()
136136

137+
var dirs []*tar.Header
137138
tr := tar.NewReader(gz)
138139

139140
loop:
@@ -148,8 +149,26 @@ loop:
148149
return errors.Wrapf(err, "error advancing tar stream")
149150
}
150151

151-
path := filepath.Join(dest, filepath.Clean(hdr.Name))
152+
hdr.Name = filepath.Clean(hdr.Name)
153+
if !strings.HasSuffix(hdr.Name, string(os.PathSeparator)) {
154+
// Not the root directory, ensure that the parent directory exists
155+
parent := filepath.Dir(hdr.Name)
156+
parentPath := filepath.Join(dest, parent)
157+
if _, err := os.Lstat(parentPath); err != nil && os.IsNotExist(err) {
158+
if err2 := os.MkdirAll(parentPath, 0777); err2 != nil {
159+
return err2
160+
}
161+
}
162+
}
163+
path := filepath.Join(dest, hdr.Name)
164+
rel, err := filepath.Rel(dest, path)
165+
if err != nil {
166+
return err
167+
}
152168
info := hdr.FileInfo()
169+
if strings.HasPrefix(rel, ".."+string(os.PathSeparator)) {
170+
return fmt.Errorf("%q is outside of %q", hdr.Name, dest)
171+
}
153172

154173
if strings.HasPrefix(info.Name(), ".wh.") {
155174
path = strings.Replace(path, ".wh.", "", 1)
@@ -163,12 +182,14 @@ loop:
163182

164183
switch hdr.Typeflag {
165184
case tar.TypeDir:
166-
if err := os.MkdirAll(path, info.Mode()); err != nil {
167-
return errors.Wrap(err, "error creating directory")
185+
if fi, err := os.Lstat(path); !(err == nil && fi.IsDir()) {
186+
if err2 := os.MkdirAll(path, info.Mode()); err2 != nil {
187+
return errors.Wrap(err2, "error creating directory")
188+
}
168189
}
169190

170191
case tar.TypeReg, tar.TypeRegA:
171-
f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, info.Mode())
192+
f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, info.Mode())
172193
if err != nil {
173194
return errors.Wrap(err, "unable to open file")
174195
}
@@ -200,13 +221,24 @@ loop:
200221
if err := os.Symlink(hdr.Linkname, path); err != nil {
201222
return err
202223
}
203-
224+
case tar.TypeXGlobalHeader:
225+
return nil
226+
}
227+
// Directory mtimes must be handled at the end to avoid further
228+
// file creation in them to modify the directory mtime
229+
if hdr.Typeflag == tar.TypeDir {
230+
dirs = append(dirs, hdr)
204231
}
232+
}
233+
for _, hdr := range dirs {
234+
path := filepath.Join(dest, hdr.Name)
205235

206-
if err := os.Chtimes(path, time.Now().UTC(), info.ModTime()); err != nil {
236+
finfo := hdr.FileInfo()
237+
// I believe the old version was using time.Now().UTC() to overcome an
238+
// invalid error from chtimes.....but here we lose hdr.AccessTime like this...
239+
if err := os.Chtimes(path, time.Now().UTC(), finfo.ModTime()); err != nil {
207240
return errors.Wrap(err, "error changing time")
208241
}
209242
}
210-
211243
return nil
212244
}

0 commit comments

Comments
 (0)