From d8730416ed4056b69d4a016bef7af1f1344f3331 Mon Sep 17 00:00:00 2001 From: Artem Chernyshev Date: Fri, 19 Nov 2021 18:19:22 +0300 Subject: [PATCH] fix: return partition table not exist when trying to read an empty dev Fixes: https://github.com/talos-systems/go-blockdevice/issues/51 Signed-off-by: Artem Chernyshev --- blockdevice/blockdevice_linux.go | 4 ++++ blockdevice/options.go | 9 +++++++++ blockdevice/partition/gpt/gpt.go | 10 +++++++--- blockdevice/partition/gpt/gpt_test.go | 24 +++++++++++++++++++++++- 4 files changed, 43 insertions(+), 4 deletions(-) diff --git a/blockdevice/blockdevice_linux.go b/blockdevice/blockdevice_linux.go index d8b771a..d761f31 100644 --- a/blockdevice/blockdevice_linux.go +++ b/blockdevice/blockdevice_linux.go @@ -74,6 +74,10 @@ func Open(devname string, setters ...Option) (bd *BlockDevice, err error) { } } + if opts.IgnoreGPT { + return bd, nil + } + if opts.CreateGPT { var g *gpt.GPT diff --git a/blockdevice/options.go b/blockdevice/options.go index 9ef5509..e7ec3aa 100644 --- a/blockdevice/options.go +++ b/blockdevice/options.go @@ -7,6 +7,7 @@ package blockdevice // Options is the functional options struct. type Options struct { CreateGPT bool + IgnoreGPT bool ExclusiveLock bool Mode int } @@ -35,10 +36,18 @@ func WithMode(value int) Option { } } +// WithoutGPT opens blockdevice ignoring GPT. +func WithoutGPT(value bool) Option { + return func(args *Options) { + args.IgnoreGPT = value + } +} + // NewDefaultOptions initializes a Options struct with default values. func NewDefaultOptions(setters ...Option) *Options { opts := &Options{ CreateGPT: false, + IgnoreGPT: false, Mode: DefaultMode, } diff --git a/blockdevice/partition/gpt/gpt.go b/blockdevice/partition/gpt/gpt.go index c9cf452..640d055 100644 --- a/blockdevice/partition/gpt/gpt.go +++ b/blockdevice/partition/gpt/gpt.go @@ -26,11 +26,11 @@ const ( var ( // ErrPartitionTableDoesNotExist indicates that the partition table does not exist. - ErrPartitionTableDoesNotExist = errors.New("does not exist") + ErrPartitionTableDoesNotExist = errors.New("block device partition table does not exist") // ErrHeaderCRCMismatch indicates that the header CRC does not match what is on disk. - ErrHeaderCRCMismatch = errors.New("header CRC mismatch") + ErrHeaderCRCMismatch = errors.New("block device partition table header CRC mismatch") // ErrEntriesCRCMismatch indicates that the partitions array CRC does not match what is on disk. - ErrEntriesCRCMismatch = errors.New("entries CRC mismatch") + ErrEntriesCRCMismatch = errors.New("block device partition table entries CRC mismatch") ) type outOfSpaceError struct { @@ -84,6 +84,10 @@ func Open(f *os.File) (g *GPT, err error) { markMBRBootable: buf[0] == 0x80, } + if err = h.DeserializeSignature(); err != nil { + return nil, ErrPartitionTableDoesNotExist + } + return g, nil } diff --git a/blockdevice/partition/gpt/gpt_test.go b/blockdevice/partition/gpt/gpt_test.go index 7e73db6..21f1844 100644 --- a/blockdevice/partition/gpt/gpt_test.go +++ b/blockdevice/partition/gpt/gpt_test.go @@ -7,6 +7,7 @@ package gpt_test import ( "encoding/binary" "os" + "os/exec" "testing" "github.com/stretchr/testify/suite" @@ -35,7 +36,28 @@ func (suite *GPTSuite) SetupTest() { func (suite *GPTSuite) TestEmpty() { _, err := gpt.Open(suite.Dev) - suite.Require().Error(err) + suite.Require().EqualError(err, gpt.ErrPartitionTableDoesNotExist.Error()) +} + +func (suite *GPTSuite) TestWiped() { + g, err := gpt.New(suite.Dev) + suite.Require().NoError(err) + + _, err = g.Add(1048576, gpt.WithPartitionName("boot")) + suite.Require().NoError(err) + + _, err = g.Add(1048576, gpt.WithPartitionName("efi")) + suite.Require().NoError(err) + + suite.Require().NoError(g.Write()) + + suite.validatePMBR(0x00) + + cmd := exec.Command("wipefs", "-a", suite.Dev.Name()) + suite.Require().NoError(cmd.Run()) + + g, err = gpt.Open(suite.Dev) + suite.Require().EqualError(err, gpt.ErrPartitionTableDoesNotExist.Error()) } func (suite *GPTSuite) TestReset() {