Skip to content

Commit 4859270

Browse files
takuro-satohgarvison
authored andcommitted
Make tar2ext4 deterministic with files without parent dir in tar (microsoft#2270)
Make tar2ext4 deterministic with files without parent dir in tar Signed-off-by: Takuro Sato <[email protected]> Signed-off-by: Heather Garvison <[email protected]>
1 parent 0b833cc commit 4859270

File tree

2 files changed

+81
-4
lines changed

2 files changed

+81
-4
lines changed

ext4/internal/compactext4/compact.go

+5-4
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,7 @@ func (w *Writer) lookup(name string, mustExist bool) (*inode, *inode, string, er
538538
// with the same permissions as that of it's parent directory. It is expected that the a
539539
// call to make these parent directories will be made at a later point with the correct
540540
// permissions, at that time the permissions of these directories will be updated.
541+
// We treat Atime, Mtime, Ctime, and Crtime in the same way.
541542
func (w *Writer) MakeParents(name string) error {
542543
if err := w.finishInode(); err != nil {
543544
return err
@@ -556,10 +557,10 @@ func (w *Writer) MakeParents(name string) error {
556557
if _, ok := root.Children[dirname]; !ok {
557558
f := &File{
558559
Mode: root.Mode,
559-
Atime: time.Now(),
560-
Mtime: time.Now(),
561-
Ctime: time.Now(),
562-
Crtime: time.Now(),
560+
Atime: fsTimeToTime(root.Atime),
561+
Mtime: fsTimeToTime(root.Mtime),
562+
Ctime: fsTimeToTime(root.Ctime),
563+
Crtime: fsTimeToTime(root.Crtime),
563564
Size: 0,
564565
Uid: root.Uid,
565566
Gid: root.Gid,

ext4/tar2ext4/tar2ext4_test.go

+76
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package tar2ext4
22

33
import (
4+
"crypto/sha256"
5+
"fmt"
6+
"io"
47
"path/filepath"
58
"testing"
69

@@ -162,3 +165,76 @@ func Test_TarHardlinkToSymlink(t *testing.T) {
162165
t.Fatalf("failed to convert tar to layer vhd: %s", err)
163166
}
164167
}
168+
169+
func calcExt4Sha256(t *testing.T, layerTar *os.File) string {
170+
t.Helper()
171+
if _, err := layerTar.Seek(0, 0); err != nil {
172+
t.Fatalf("failed to seek file: %s", err)
173+
}
174+
175+
opts := []Option{ConvertWhiteout}
176+
177+
tmpExt4Path := filepath.Join(os.TempDir(), "test.ext4")
178+
layerVhd, err := os.Create(tmpExt4Path)
179+
if err != nil {
180+
t.Fatalf("failed to create output VHD: %s", err)
181+
}
182+
defer os.Remove(tmpExt4Path)
183+
184+
if err := Convert(layerTar, layerVhd, opts...); err != nil {
185+
t.Fatalf("failed to convert tar to layer vhd: %s", err)
186+
}
187+
188+
if _, err := layerVhd.Seek(0, 0); err != nil {
189+
t.Fatalf("failed to seek file: %s", err)
190+
}
191+
192+
hasher := sha256.New()
193+
if _, err = io.Copy(hasher, layerVhd); err != nil {
194+
t.Fatalf("filed to initialize hasher: %s", err)
195+
}
196+
197+
hash := hasher.Sum(nil)
198+
return fmt.Sprintf("%x", hash)
199+
}
200+
201+
// Test_MissingParentDirExpansion tests that we are correctly able to expand a layer tar file
202+
// even if its file does not include the parent directory in its file name.
203+
func Test_MissingParentDirExpansion(t *testing.T) {
204+
tmpTarFilePath := filepath.Join(os.TempDir(), "test-layer.tar")
205+
layerTar, err := os.Create(tmpTarFilePath)
206+
if err != nil {
207+
t.Fatalf("failed to create output file: %s", err)
208+
}
209+
defer os.Remove(tmpTarFilePath)
210+
211+
tw := tar.NewWriter(layerTar)
212+
var file = struct {
213+
path, body string
214+
}{"foo/bar.txt", "inside bar.txt"}
215+
hdr := &tar.Header{
216+
Name: file.path,
217+
Mode: 0777,
218+
Size: int64(len(file.body)),
219+
ModTime: time.Now(),
220+
AccessTime: time.Now(),
221+
ChangeTime: time.Now(),
222+
}
223+
if err := tw.WriteHeader(hdr); err != nil {
224+
t.Fatal(err)
225+
}
226+
if _, err := tw.Write([]byte(file.body)); err != nil {
227+
t.Fatal(err)
228+
}
229+
if err := tw.Close(); err != nil {
230+
t.Fatal(err)
231+
}
232+
233+
// Now import the tar file and check the conversion to ext4 is deterministic.
234+
hash1 := calcExt4Sha256(t, layerTar)
235+
hash2 := calcExt4Sha256(t, layerTar)
236+
237+
if hash1 != hash2 {
238+
t.Fatalf("hash doesn't match")
239+
}
240+
}

0 commit comments

Comments
 (0)