blob: 80745585de0dd134d4c8e2df2086f592b5bc9ed2 [file] [log] [blame]
// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package fsinfo
import (
"testing"
"unsafe"
"thinfs/fs/msdosfs/bootrecord"
"thinfs/fs/msdosfs/testutil"
)
// Tests the size of the FS Info structure
func TestFsInfoSize(t *testing.T) {
if sz := unsafe.Sizeof(fsInfo{}); sz != 512 {
t.Fatalf("fsInfo struct is %d byte, but it should be 512 bytes", sz)
}
info := &fsInfo{}
align := unsafe.Alignof(*info)
if align != 1 {
t.Fatalf("Expected fs info to have no alignment requirements, but Alignof is: %d", align)
}
fcOffset := unsafe.Offsetof(info.freeCountClusters)
if freeCountOffset != fcOffset {
t.Fatalf("Expected freeCountOffset of %d, but saw %d\n", freeCountOffset, fcOffset)
}
nfOffset := unsafe.Offsetof(info.nextFreeCluster)
if nextFreeClusterOffset != nfOffset {
t.Fatalf("Expected nextFreeClusterOffset of %d, but saw %d\n", nextFreeClusterOffset, nfOffset)
}
}
// Tests the FS Info structure can be read and written to.
func TestFsInfoFAT32ReadWrite(t *testing.T) {
fs := testutil.MkfsFAT(t, "1G", 2, 0, 4, 512)
defer fs.RmfsFAT()
d := fs.GetDevice()
defer d.Close()
// Read the bootrecord, get the offset of the FS Info
br, err := bootrecord.New(d)
if err != nil {
t.Fatal(err)
}
offset, err := br.FsInfoOffset()
if err != nil {
t.Fatal(err)
}
// Read the default hints
freeCount, nextFree, err := ReadHints(d, offset)
if err != nil {
t.Fatal(err)
} else if freeCount == 0 || freeCount == UnknownFlag {
t.Fatalf("Unexpected free count: %d", freeCount)
} else if nextFree != 2 {
t.Fatalf("Unexpected next free: %d (expected %d)", nextFree, 2)
}
// Write new hints
newFreeCount := uint32(10)
newNextFree := uint32(15)
if err := WriteFreeCount(d, offset, newFreeCount); err != nil {
t.Fatal(err)
} else if err := WriteNextFree(d, offset, newNextFree); err != nil {
t.Fatal(err)
}
// Check the hints we just wrote actually ended up in the right place
freeCount, nextFree, err = ReadHints(d, offset)
if err != nil {
t.Fatal(err)
} else if freeCount != newFreeCount {
t.Fatalf("Unexpected free count: %d (expected %d)", freeCount, newFreeCount)
} else if nextFree != newNextFree {
t.Fatalf("Unexpected next free: %d (expected %d)", nextFree, newNextFree)
}
// Write an unknown "next free" hint.
if err := WriteNextFree(d, offset, 0xFFFFFFFF); err != nil {
t.Fatal(err)
} else if _, _, err = ReadHints(d, offset); err == nil {
t.Fatal("Expected that an unknown 'next free' hint would cause an error")
}
// Put the "next free" hint back to a valid value, and then repeat the process with an invalid
// "free count" hint.
if err := WriteNextFree(d, offset, newNextFree); err != nil {
t.Fatal(err)
} else if err := WriteFreeCount(d, offset, 0xFFFFFFFF); err != nil {
t.Fatal(err)
} else if _, _, err = ReadHints(d, offset); err == nil {
t.Fatal("Expected that an unknown 'free count' hint would cause an error")
}
}
// Tests the FS Info structure validates signatures on FAT32
func TestFsInfoFAT32Invalid(t *testing.T) {
doTest := func(byteToModify int64, newVal byte) {
fs := testutil.MkfsFAT(t, "1G", 2, 0, 4, 512)
d := fs.GetDevice()
// Read the bootrecord, get the offset of the FS Info
br, err := bootrecord.New(d)
if err != nil {
t.Fatal(err)
}
offset, err := br.FsInfoOffset()
if err != nil {
t.Fatal(err)
}
// Mess up the fsInfo signature (make it invalid)
if _, err := d.WriteAt([]byte{0}, offset+byteToModify); err != nil {
t.Fatal(err)
}
if _, _, err := ReadHints(d, offset); err == nil {
t.Fatalf("Expected ReadHints to fail with modified byte at %d", byteToModify)
}
d.Close()
fs.RmfsFAT()
}
doTest(0, 0) // Mess up leading signature
doTest(484, 0) // Mess up inner signature
doTest(511, 0) // Mess up final signature
}
// Tests the FS Info structure is not accessible on FAT16
func TestFsInfoFAT16Invalid(t *testing.T) {
fs := testutil.MkfsFAT(t, "10M", 2, 0, 4, 512)
defer fs.RmfsFAT()
d := fs.GetDevice()
defer d.Close()
// Read the bootrecord, get the offset of the FS Info
br, err := bootrecord.New(d)
if err != nil {
t.Fatal(err)
}
_, err = br.FsInfoOffset()
if err == nil {
t.Fatal("Expected FS Info offset to fail for FAT 16")
}
}