package squashfs // import ( // "crypto/md5" // "fmt" // "io" // "os" // "testing" // "time" // "github.com/google/go-cmp/cmp" // ) // func cmpFileInfo(got os.FileInfo, want FileInfo) error { // if got, want := got.Name(), want.name; got != want { // return fmt.Errorf("unexpected file name: got %q, want %q", got, want) // } // if got, want := got.Size(), want.size; got != want { // return fmt.Errorf("unexpected size: got %d, want %d", got, want) // } // if got, want := got.IsDir(), want.mode.IsDir(); got != want { // return fmt.Errorf("IsDir: got %v, want %v", got, want) // } // // TODO: re-enable when it’s no longer just a change detector // // if got, want := got.ModTime(), want.modTime; !got.Equal(want) { // // return fmt.Errorf("IsDir: got %v, want %v", got, want) // // } // return nil // } // func TestReaddir(t *testing.T) { // t.Parallel() // // TODO: ship testdata files generated by mksquashfs // pwd, err := os.Getwd() // if err != nil { // t.Fatal(err) // } // fmt.Println(pwd + "/testdata/testing.squashfs") // f, err := os.Open(pwd + "/testdata/testing.squashfs") // if err != nil { // t.Fatal(err) // } // defer f.Close() // rd, err := NewReader(f) // if err != nil { // t.Fatal(err) // } // fis, err := rd.Readdir(rd.RootInode()) // if err != nil { // t.Fatal(err) // } // for _, fi := range fis { // fmt.Println(fi.Name()) // } // rdr, err := rd.FileReader(fis[0].Sys().(*FileInfo).Inode) // if err != nil { // t.Fatal(err) // } // err = os.Remove(pwd + "/testdata/Magisk.zip") // if !os.IsNotExist(err) && err != nil { // t.Fatal(err) // } // // rdrzlib, err := zlib.NewReader(rdr) // magFil, err := os.Create(pwd + "/testdata/Magisk.zip") // io.Copy(magFil, rdr) // if got, want := len(fis), 3; got != want { // t.Fatalf("unexpected number of directory entries: got %d, want %d", got, want) // } // if err := cmpFileInfo(fis[0], FileInfo{ // name: "bin", // size: 26, // mode: 0555 | os.ModeDir, // modTime: time.Unix(1581275131, 0), // stat -c %Y /ro/ack-amd64-2.24/bin // }); err != nil { // t.Fatal(err) // } // if err := cmpFileInfo(fis[1], FileInfo{ // name: "lib", // size: 3, // mode: 0555 | os.ModeDir, // modTime: time.Unix(1581275131, 0), // stat -c %Y /ro/ack-amd64-2.24/lib // }); err != nil { // t.Fatal(err) // } // if err := cmpFileInfo(fis[2], FileInfo{ // name: "out", // size: 48, // mode: 0555 | os.ModeDir, // modTime: time.Unix(1581275130, 0), // stat -c %Y /ro/ack-amd64-2.24/out // }); err != nil { // t.Fatal(err) // } // fis, err = rd.Readdir(fis[0].Sys().(*FileInfo).Inode) // if err != nil { // t.Fatal(err) // } // if got, want := len(fis), 1; got != want { // t.Fatalf("unexpected number of directory entries: got %d, want %d", got, want) // } // if err := cmpFileInfo(fis[0], FileInfo{ // name: "ack", // size: 38400, // mode: 0755, // modTime: time.Unix(1581275131, 0), // stat -c %Y /ro/ack-amd64-2.24/bin/ack // }); err != nil { // t.Fatal(err) // } // } // // TestReaddirSmoke is a smoke-test, reading the root directories of SquashFS // // images which are known to trigger code paths which were buggy. // func TestReaddirSmoke(t *testing.T) { // t.Parallel() // for _, fn := range []string{ // // bash exercises the code path where an inode is split across metadata // // blocks. // "/home/michael/distri/_build/distri/pkg/bash-amd64-5.0-4.squashfs", // // cmake exercises the code path where the root directory entries are // // located outside of the first block. // "/home/michael/distri/_build/distri/pkg/cmake-amd64-3.12.4-8.squashfs", // } { // // TODO: ship testdata files generated by mksquashfs // f, err := os.Open(fn) // if err != nil { // t.Fatal(err) // } // defer f.Close() // rd, err := NewReader(f) // if err != nil { // t.Fatal(err) // } // fis, err := rd.Readdir(rd.RootInode()) // if err != nil { // t.Fatal(err) // } // if got, want := len(fis), 4; got != want { // t.Fatalf("unexpected number of directory entries: got %d, want %d", got, want) // } // } // } // func TestReaddirEmpty(t *testing.T) { // t.Parallel() // // TODO: ship testdata files generated by mksquashfs // f, err := os.Open("/home/michael/distri/_build/distri/pkg/zlib-amd64-1.2.11-4.squashfs") // if err != nil { // t.Fatal(err) // } // defer f.Close() // rd, err := NewReader(f) // if err != nil { // t.Fatal(err) // } // fis, err := rd.Readdir(rd.RootInode()) // if err != nil { // t.Fatal(err) // } // if got, want := len(fis), 4; got != want { // t.Fatalf("unexpected number of directory entries: got %d, want %d", got, want) // } // if err := cmpFileInfo(fis[0], FileInfo{ // name: "bin", // size: 3, // mode: 0555 | os.ModeDir, // modTime: time.Unix(1583085224, 0), // stat -c %Y /ro/zlib-amd64-1.2.11/bin // }); err != nil { // t.Fatal(err) // } // fis, err = rd.Readdir(fis[0].Sys().(*FileInfo).Inode) // if err != nil { // t.Fatal(err) // } // if got, want := len(fis), 0; got != want { // t.Fatalf("unexpected number of directory entries: got %d, want %d", got, want) // } // } // func TestReaddirSymlink(t *testing.T) { // t.Parallel() // // TODO: ship testdata files generated by mksquashfs // f, err := os.Open("/home/michael/distri/_build/distri/pkg/zlib-amd64-1.2.11-4.squashfs") // if err != nil { // t.Fatal(err) // } // defer f.Close() // rd, err := NewReader(f) // if err != nil { // t.Fatal(err) // } // fis, err := rd.Readdir(rd.RootInode()) // if err != nil { // t.Fatal(err) // } // if got, want := len(fis), 4; got != want { // t.Fatalf("unexpected number of directory entries: got %d, want %d", got, want) // } // if err := cmpFileInfo(fis[3], FileInfo{ // name: "out", // size: 54, // mode: 0555 | os.ModeDir, // modTime: time.Unix(1583085224, 0), // stat -c %Y /ro/zlib-amd64-1.2.11/out // }); err != nil { // t.Fatal(err) // } // fis, err = rd.Readdir(fis[3].Sys().(*FileInfo).Inode) // if err != nil { // t.Fatal(err) // } // if got, want := len(fis), 3; got != want { // t.Fatalf("unexpected number of directory entries: got %d, want %d", got, want) // } // if err := cmpFileInfo(fis[1], FileInfo{ // name: "lib", // size: 83, // mode: 0555 | os.ModeDir, // modTime: time.Unix(1583085224, 0), // stat -c %Y /ro/zlib-amd64-1.2.11/out/lib // }); err != nil { // t.Fatal(err) // } // fis, err = rd.Readdir(fis[1].Sys().(*FileInfo).Inode) // if err != nil { // t.Fatal(err) // } // if got, want := len(fis), 4; got != want { // t.Fatalf("unexpected number of directory entries: got %d, want %d", got, want) // } // if err := cmpFileInfo(fis[1], FileInfo{ // name: "libz.so", // size: 9, // mode: 0555 | os.ModeSymlink, // modTime: time.Unix(1583085223, 0), // stat -c %Y /ro/zlib-amd64-1.2.11/out/lib/libz.so // }); err != nil { // t.Fatal(err) // } // // TODO: readlink // target, err := rd.ReadLink(fis[1].Sys().(*FileInfo).Inode) // if err != nil { // t.Fatal(err) // } // if got, want := target, "libz.so.1"; got != want { // t.Fatalf("ReadLink(libz.so): got %q, want %q", got, want) // } // } // func TestReadfile(t *testing.T) { // t.Parallel() // // TODO: ship testdata files generated by mksquashfs // f, err := os.Open("/home/michael/distri/_build/distri/pkg/ack-amd64-3.3.1-7.squashfs") // if err != nil { // t.Fatal(err) // } // defer f.Close() // rd, err := NewReader(f) // if err != nil { // t.Fatal(err) // } // fis, err := rd.Readdir(rd.RootInode()) // if err != nil { // t.Fatal(err) // } // if got, want := len(fis), 3; got != want { // t.Fatalf("unexpected number of directory entries: got %d, want %d", got, want) // } // fis, err = rd.Readdir(fis[0].Sys().(*FileInfo).Inode) // if err != nil { // t.Fatal(err) // } // if got, want := len(fis), 1; got != want { // t.Fatalf("unexpected number of directory entries: got %d, want %d", got, want) // } // r, err := rd.FileReader(fis[0].Sys().(*FileInfo).Inode) // if err != nil { // t.Fatal(err) // } // for i := 0; i < 2; i++ { // if _, err := r.Seek(0, io.SeekStart); err != nil { // t.Fatal(err) // } // h := md5.New() // if _, err := io.Copy(h, r); err != nil { // t.Fatal(err) // } // sum := fmt.Sprintf("%x", h.Sum(nil)) // if got, want := sum, "c6c9b5d4d2a49f1b8b5e501f0f827a5c"; got != want { // t.Fatalf("md5(bin/ack): got %s, want %s", got, want) // } // } // } // // TODO: add test exercising ldirInodeHeader, e.g. '/mnt/loop/ca-certificates-3.39/buildoutput/etc/ssl' // func TestReadXattr(t *testing.T) { // t.Parallel() // // TODO: generate a smaller version of this file // f, err := os.Open("testdata/xattr.squashfs") // if err != nil { // t.Fatal(err) // } // defer f.Close() // rd, err := NewReader(f) // if err != nil { // t.Fatal(err) // } // for _, tt := range []struct { // Path string // Want []Xattr // }{ // { // Path: "mtr-packet", // Want: []Xattr{ // { // Type: XattrTypeSecurity, // FullName: "security.capability", // Value: []byte{1, 0, 0, 2, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, // }, // }, // { // Path: "gnome-keyring-daemon", // Want: []Xattr{ // { // Type: XattrTypeSecurity, // FullName: "security.capability", // Value: []byte{1, 0, 0, 2, 0, 0x40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, // }, // }, // } { // inode, err := rd.LookupPath(tt.Path) // if err != nil { // t.Fatal(err) // } // xattrs, err := rd.ReadXattrs(inode) // if err != nil { // t.Fatalf("ReadXattrs(%v): %v", inode, err) // } // if diff := cmp.Diff(tt.Want, xattrs); diff != "" { // t.Fatalf("unexpected ReadXattrs result: diff (-want +got):\n%s", diff) // } // } // }