Skip to content

Commit

Permalink
squashfs: fix directory listings
Browse files Browse the repository at this point in the history
This fixes directory listings sometimes giving the error

    could not parse directory header: header was 3 bytes, less than minimum 12

This appears to be because empty directories can indeed have no
entries despite what the spec says.

This introduces a test checking that we can recurse the test squashfs
file correctly - this fails without this patch.
  • Loading branch information
ncw committed Dec 14, 2023
1 parent 3e68808 commit ad4ab19
Show file tree
Hide file tree
Showing 5 changed files with 591 additions and 4 deletions.
1 change: 1 addition & 0 deletions filesystem/squashfs/const_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
const (
Squashfsfile = "./testdata/file.sqs"
SquashfsUncompressedfile = "./testdata/file_uncompressed.sqs"
SquashfsfileListing = "./testdata/list.txt"
)

// first header
Expand Down
8 changes: 4 additions & 4 deletions filesystem/squashfs/directory.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,10 @@ type directoryEntryGroup struct {

// parse raw bytes of a directory to get the contents
func parseDirectory(b []byte) (*directory, error) {
// must have at least one header
if _, err := parseDirectoryHeader(b); err != nil {
return nil, fmt.Errorf("could not parse directory header: %v", err)
}
// must have at least one header - this doesn't appear to be true
// if _, err := parseDirectoryHeader(b); err != nil {
// return nil, fmt.Errorf("could not parse directory header: %v", err)
// }
entries := make([]*directoryEntryRaw, 0)
for pos := 0; pos+dirHeaderSize < len(b); {
directoryHeader, err := parseDirectoryHeader(b[pos:])
Expand Down
67 changes: 67 additions & 0 deletions filesystem/squashfs/squashfs_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package squashfs_test

import (
"bufio"
"fmt"
"io"
"os"
Expand Down Expand Up @@ -294,6 +295,72 @@ func TestSquashfsRead(t *testing.T) {
}
}

// Check the directory listing is correct
func TestSquashfsCheckListing(t *testing.T) {
// read the directory listing in
var listing = map[string]struct{}{}
flist, err := os.Open(squashfs.SquashfsfileListing)
if err != nil {
t.Fatal(err)
}
defer flist.Close()
scanner := bufio.NewScanner(flist)
for scanner.Scan() {
line := scanner.Text()
line = strings.TrimPrefix(line, ".")
if line == "/" {
continue
}
listing[line] = struct{}{}
}
if err := scanner.Err(); err != nil {
t.Fatal(err)
}

// Open the squash file
f, err := os.Open(squashfs.Squashfsfile)
if err != nil {
t.Fatal(err)
}
defer f.Close()
fi, err := f.Stat()
if err != nil {
t.Fatal(err)
}
// create the filesystem
fs, err := squashfs.Read(f, fi.Size(), 0, 0)
if err != nil {
t.Fatal(err)
}

var list func(dir string)
list = func(dir string) {
fis, err := fs.ReadDir(dir)
if err != nil {
t.Fatal(err)
}
for _, fi := range fis {
p := path.Join(dir, fi.Name())
if _, found := listing[p]; found {
delete(listing, p)
} else {
t.Errorf("Found unexpected path %q in listing", p)
}
if fi.IsDir() {
list(p)
}
}
}

list("/")

// listing should be empty now
for p := range listing {
t.Errorf("Didn't find %q in listing", p)
}

}

func TestSquashfsCreate(t *testing.T) {
tests := []struct {
blocksize int64
Expand Down
3 changes: 3 additions & 0 deletions filesystem/squashfs/testdata/buildtestsqs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,7 @@ mksquashfs . /data/file.sqs
# uncompressed version
mksquashfs . /data/file_uncompressed.sqs -noI -noD -noF
# create listing to check
find . > /data/list.txt
EOF
Loading

0 comments on commit ad4ab19

Please sign in to comment.