treewide: port everything to blockdev
This gets rid of most ad-hoc block device code, using blockdev for
everything. It also gets rid of diskfs for everything but tests. This
enables Metropolis to be installed on non-512-byte block sizes.
Change-Id: I644b5b68bb7bed8106585df3179674789031687a
Reviewed-on: https://review.monogon.dev/c/monogon/+/1873
Tested-by: Jenkins CI
Reviewed-by: Serge Bazanski <serge@monogon.tech>
diff --git a/metropolis/pkg/blkio/BUILD.bazel b/metropolis/pkg/blkio/BUILD.bazel
new file mode 100644
index 0000000..8b071ec
--- /dev/null
+++ b/metropolis/pkg/blkio/BUILD.bazel
@@ -0,0 +1,8 @@
+load("@io_bazel_rules_go//go:def.bzl", "go_library")
+
+go_library(
+ name = "blkio",
+ srcs = ["blkio.go"],
+ importpath = "source.monogon.dev/metropolis/pkg/blkio",
+ visibility = ["//visibility:public"],
+)
diff --git a/metropolis/pkg/blkio/blkio.go b/metropolis/pkg/blkio/blkio.go
new file mode 100644
index 0000000..d0b7174
--- /dev/null
+++ b/metropolis/pkg/blkio/blkio.go
@@ -0,0 +1,83 @@
+package blkio
+
+import (
+ "fmt"
+ "io"
+ "os"
+)
+
+type ReaderWithSize struct {
+ io.Reader
+ size int64
+}
+
+// SizedReader is an io.Reader with a known size
+type SizedReader interface {
+ io.Reader
+ Size() int64
+}
+
+// NewSizedReader returns a SizedReader given a reader and a size.
+// The returned SizedReader is a ReaderWithSize.
+func NewSizedReader(r io.Reader, size int64) SizedReader {
+ return &ReaderWithSize{r, size}
+}
+
+func (r *ReaderWithSize) Size() int64 {
+ return r.size
+}
+
+// LazyFileReader implements a SizedReader which opens a file on first read
+// and closes it again after the reader has reached EOF.
+type LazyFileReader struct {
+ name string
+ size int64
+ f *os.File
+ done bool
+}
+
+func (r *LazyFileReader) init() error {
+ f, err := os.Open(r.name)
+ if err != nil {
+ return fmt.Errorf("failed to open file for reading: %w", err)
+ }
+ r.f = f
+ return nil
+}
+
+func (r *LazyFileReader) Size() int64 {
+ return r.size
+}
+
+func (r *LazyFileReader) Read(b []byte) (n int, err error) {
+ if r.done {
+ return 0, io.EOF
+ }
+ if r.f == nil {
+ if err = r.init(); err != nil {
+ return
+ }
+ }
+ n, err = r.f.Read(b)
+ if err == io.EOF {
+ r.done = true
+ r.f.Close()
+ }
+ return
+}
+
+func (r *LazyFileReader) Close() {
+ r.done = true
+ r.f.Close()
+}
+
+func NewFileReader(name string) (*LazyFileReader, error) {
+ info, err := os.Stat(name)
+ if err != nil {
+ return nil, fmt.Errorf("failed to stat: %w", err)
+ }
+ return &LazyFileReader{
+ size: info.Size(),
+ name: name,
+ }, nil
+}