Skip to content

Commit

Permalink
Support direct filesystem (#2)
Browse files Browse the repository at this point in the history
* Support direct filesystem

* Add check filesystem

* Remove unnecessary code

* Add type var

* Add seek offset

* Rename func

* Add CheckFsFunc type

* test(disk): add direct filesystem tests

---------

Co-authored-by: masahiro331 <[email protected]>
  • Loading branch information
yusuke-koyoshi and masahiro331 authored Jun 25, 2024
1 parent c8da316 commit 56c9332
Show file tree
Hide file tree
Showing 9 changed files with 215 additions and 12 deletions.
21 changes: 20 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,26 @@
SECTORS = 32768
SECTOR_SIZE = 512
TARGET_MBR = mbr.bin
TARGET_IMG = linux.img
TARGET_FS = fs.bin

mbr.bin:
dd if=/dev/zero of=$(TARGET_MBR) seek=$(SECTORS) bs=$(SECTOR_SIZE) count=1
fdisk -i -y $(TARGET_MBR)
fdisk -i -y $(TARGET_MBR)

# Linux only and require admin authority
#!!! Extract xfs from gpt using cmd/main.go.
linux.img: main
$(eval DEVICE := $(shell losetup -f))
dd of=$(TARGET_IMG) count=0 seek=1 bs=41943040
losetup $(DEVICE) $(TARGET_IMG)
parted $(DEVICE) -s mklabel gpt -s mkpart primary xfs 0 100%
mkfs.xfs $(DEVICE)p1
losetup -d $(DEVICE)

main: cmd/main.go
go build -o main cmd/main.go

fs.bin: linux.img main
./main linux.img
mv primary0 $(TARGET_FS)
6 changes: 4 additions & 2 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ package main

import (
"fmt"
"github.com/masahiro331/go-disk"
"io"
"log"
"os"

"github.com/masahiro331/go-disk"
"github.com/masahiro331/go-xfs-filesystem/xfs"
)

func main() {
Expand All @@ -21,7 +23,7 @@ func main() {
log.Fatal(err)
}
r := io.NewSectionReader(f, 0, fi.Size())
driver, err := disk.NewDriver(r)
driver, err := disk.NewDriver(r, xfs.Check)
if err != nil {
log.Fatal(err)
}
Expand Down
18 changes: 12 additions & 6 deletions disk.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,25 @@ package disk
import (
"io"

"github.com/masahiro331/go-disk/fs"
"github.com/masahiro331/go-disk/gpt"
"github.com/masahiro331/go-disk/mbr"
"github.com/masahiro331/go-disk/types"
"golang.org/x/xerrors"
)

type Driver interface {
Next() (types.Partition, error)
}

func NewDriver(sr *io.SectionReader) (Driver, error) {
func NewDriver(sr *io.SectionReader, checkFsFuncs ...fs.CheckFsFunc) (types.Driver, error) {
m, err := mbr.NewMasterBootRecord(sr)
if err != nil {
if xerrors.Is(mbr.InvalidSignature, err) {
ok, err := fs.CheckFileSystems(sr, checkFsFuncs)
if err != nil {
return nil, xerrors.Errorf("failed to check filesystem: %w", err)
}
if ok {
return fs.NewDirectFileSystem(sr)
}
}
return nil, xerrors.Errorf("failed to new MBR: %w", err)
}

Expand All @@ -28,4 +34,4 @@ func NewDriver(sr *io.SectionReader) (Driver, error) {
}

return g, nil
}
}
57 changes: 57 additions & 0 deletions disk_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package disk_test

import (
"io"
"os"
"strings"
"testing"

"github.com/masahiro331/go-disk"
"github.com/masahiro331/go-disk/fs"
"github.com/masahiro331/go-xfs-filesystem/xfs"
)

func TestNewDriver(t *testing.T) {
tests := []struct {
name string
inputFile string
wantErr string
checkFsFuncs []fs.CheckFsFunc
}{
{
name: "Happy path, Direct filesystem",
inputFile: "testdata/fs.bin",
wantErr: "",
checkFsFuncs: []fs.CheckFsFunc{xfs.Check},
},
{
name: "Invalid path, Direct filesystem no check fs functions",
inputFile: "testdata/fs.bin",
wantErr: "Invalid master boot record signature",
checkFsFuncs: []fs.CheckFsFunc{},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
f, err := os.Open(tt.inputFile)
if err != nil {
t.Fatal(err)
}
defer f.Close()

info, err := f.Stat()
if err != nil {
t.Fatal(err)
}
sr := io.NewSectionReader(f, 0, info.Size())
_, err = disk.NewDriver(sr, tt.checkFsFuncs...)

if tt.wantErr == "" && err != nil {
t.Errorf("input: %s, required no error = %v", tt.inputFile, err)
} else if tt.wantErr != "" && !strings.HasSuffix(err.Error(), tt.wantErr) {
t.Errorf("input: %s, expected: %q, actual: %q", tt.inputFile, tt.wantErr, err.Error())
}
})
}
}
86 changes: 86 additions & 0 deletions fs/fs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package fs

import (
"io"

"github.com/masahiro331/go-disk/types"
"golang.org/x/xerrors"
)

var (
_ types.Driver = &DirectFileSystem{}
_ types.Partition = &DirectFileSystemPartition{}
)

type DirectFileSystem struct {
Partition *DirectFileSystemPartition
}

func (d *DirectFileSystem) Next() (types.Partition, error) {
if d.Partition == nil {
return nil, io.EOF
}
partition := d.Partition
d.Partition = nil

return partition, nil
}

type DirectFileSystemPartition struct {
sectionReader *io.SectionReader
}

func (p DirectFileSystemPartition) Name() string {
return "0"
}

func (p DirectFileSystemPartition) GetType() []byte {
return []byte{}
}

func (p DirectFileSystemPartition) GetStartSector() uint64 {
return uint64(0)
}

func (p DirectFileSystemPartition) Bootable() bool {
return false
}

func (p DirectFileSystemPartition) GetSize() uint64 {
return uint64(p.sectionReader.Size())
}

func (p DirectFileSystemPartition) GetSectionReader() io.SectionReader {
return *p.sectionReader
}

func (p DirectFileSystemPartition) IsSupported() bool {
return true
}

func NewDirectFileSystem(sr *io.SectionReader) (*DirectFileSystem, error) {
_, err := sr.Seek(0, io.SeekStart)
if err != nil {
return nil, xerrors.Errorf("failed to DirectFileSystem seek offset error: %w", err)
}
return &DirectFileSystem{
Partition: &DirectFileSystemPartition{
sectionReader: sr,
},
}, nil
}

type CheckFsFunc func(r io.Reader) bool

func CheckFileSystems(r *io.SectionReader, checkFsFuncs []CheckFsFunc) (bool, error) {
for _, checkFsFunc := range checkFsFuncs {
_, err := r.Seek(0, io.SeekStart)
if err != nil {
return false, xerrors.Errorf("failed to seek offset error: %w", err)
}
if checkFsFunc(r) {
return true, nil
}
}
return false, nil
}
11 changes: 10 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,13 @@ module github.com/masahiro331/go-disk

go 1.19

require golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1
require (
github.com/masahiro331/go-xfs-filesystem v0.0.0-20231205045356-1b22259a6c44
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2
)

require (
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.6.0 // indirect
go.uber.org/zap v1.23.0 // indirect
)
24 changes: 22 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,2 +1,22 @@
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/masahiro331/go-xfs-filesystem v0.0.0-20231205045356-1b22259a6c44 h1:VmSjn0UCyfXUNdePDr7uM/uZTnGSp+mKD5+cYkEoLx4=
github.com/masahiro331/go-xfs-filesystem v0.0.0-20231205045356-1b22259a6c44/go.mod h1:QKBZqdn6teT0LK3QhAf3K6xakItd1LonOShOEC44idQ=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/zap v1.23.0 h1:OjGQ5KQDEUawVHxNwQgPpiypGHOxo2mNZsOqTak4fFY=
go.uber.org/zap v1.23.0/go.mod h1:D+nX8jyLsMHMYrln8A0rJjFt/T/9/bGgIhAqxv5URuY=
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
Binary file added testdata/fs.bin
Binary file not shown.
4 changes: 4 additions & 0 deletions types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ package types

import "io"

type Driver interface {
Next() (Partition, error)
}

type Partition interface {
Bootable() bool
GetStartSector() uint64
Expand Down

0 comments on commit 56c9332

Please sign in to comment.