diff --git a/.golangci.yml b/.golangci.yml index fb7edca7..93c9d2ee 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -46,7 +46,7 @@ linters: - typecheck - unconvert - unparam - - unused + # - unused - whitespace linters-settings: diff --git a/pkg/sif/create.go b/pkg/sif/create.go index 104e9ea1..5eec9a39 100644 --- a/pkg/sif/create.go +++ b/pkg/sif/create.go @@ -1,4 +1,4 @@ -// Copyright (c) 2018-2022, Sylabs Inc. All rights reserved. +// Copyright (c) 2018-2023, Sylabs Inc. All rights reserved. // Copyright (c) 2017, SingularityWare, LLC. All rights reserved. // Copyright (c) 2017, Yannick Cote All rights reserved. // This software is licensed under a 3-clause BSD license. Please consult the @@ -69,7 +69,7 @@ func (f *FileImage) writeDataObject(i int, di DescriptorInput, t time.Time) erro // If this is a primary partition, verify there isn't another primary partition, and update the // architecture in the global header. - if p, ok := di.opts.extra.(partition); ok && p.Parttype == PartPrimSys { + if p, ok := di.opts.md.(partition); ok && p.Parttype == PartPrimSys { if ds, err := f.GetDescriptors(WithPartitionType(PartPrimSys)); err == nil && len(ds) > 0 { return errPrimaryPartition } diff --git a/pkg/sif/descriptor.go b/pkg/sif/descriptor.go index 4d6cdf3c..19272824 100644 --- a/pkg/sif/descriptor.go +++ b/pkg/sif/descriptor.go @@ -45,6 +45,11 @@ type partition struct { Arch archType } +// MarshalBinary encodes p into binary format. +func (p partition) MarshalBinary() ([]byte, error) { + return binaryMarshaler{p}.MarshalBinary() +} + // signature represents the SIF signature data object descriptor. type signature struct { Hashtype hashType @@ -62,6 +67,26 @@ type sbom struct { Format SBOMFormat } +// The binaryMarshaler type is an adapter that allows a type suitable for use with the +// encoding/binary package to be used as an encoding.BinaryMarshaler. +type binaryMarshaler struct{ any } + +// MarshalBinary encodes m into binary format. +func (m binaryMarshaler) MarshalBinary() ([]byte, error) { + var b bytes.Buffer + err := binary.Write(&b, binary.LittleEndian, m.any) + return b.Bytes(), err +} + +// The binaryUnmarshaler type is an adapter that allows a type suitable for use with the +// encoding/binary package to be used as an encoding.BinaryUnmarshaler. +type binaryUnmarshaler struct{ any } + +// UnmarshalBinary decodes b into u. +func (u binaryUnmarshaler) UnmarshalBinary(b []byte) error { + return binary.Read(bytes.NewReader(b), binary.LittleEndian, u.any) +} + var errNameTooLarge = errors.New("name value too large") // setName encodes name into the name field of d. @@ -79,27 +104,15 @@ func (d *rawDescriptor) setName(name string) error { var errExtraTooLarge = errors.New("extra value too large") -// setExtra encodes v into the extra field of d. If the encoding.BinaryMarshaler interface is -// implemented by v, it is used for marshaling. Otherwise, binary.Write() is used. -func (d *rawDescriptor) setExtra(v any) error { - if v == nil { +// setExtra marshals metadata from md into the "extra" field of d. +func (d *rawDescriptor) setExtra(md encoding.BinaryMarshaler) error { + if md == nil { return nil } - var extra []byte - - if m, ok := v.(encoding.BinaryMarshaler); ok { - b, err := m.MarshalBinary() - if err != nil { - return err - } - extra = b - } else { - b := new(bytes.Buffer) - if err := binary.Write(b, binary.LittleEndian, v); err != nil { - return err - } - extra = b.Bytes() + extra, err := md.MarshalBinary() + if err != nil { + return err } if len(extra) > len(d.Extra) { @@ -113,13 +126,9 @@ func (d *rawDescriptor) setExtra(v any) error { return nil } -// getExtra decodes the extra fields of d into v. If the encoding.BinaryUnmarshaler interface is -// implemented by v, it is used for unmarshaling. Otherwise, binary.Read() is used. -func (d *rawDescriptor) getExtra(v any) error { - if u, ok := v.(encoding.BinaryUnmarshaler); ok { - return u.UnmarshalBinary(d.Extra[:]) - } - return binary.Read(bytes.NewReader(d.Extra[:]), binary.LittleEndian, v) +// getExtra unmarshals metadata from the "extra" field of d into md. +func (d *rawDescriptor) getExtra(md encoding.BinaryUnmarshaler) error { + return md.UnmarshalBinary(d.Extra[:]) } // getPartitionMetadata gets metadata for a partition data object. @@ -130,7 +139,7 @@ func (d rawDescriptor) getPartitionMetadata() (FSType, PartType, string, error) var p partition - if err := d.getExtra(&p); err != nil { + if err := d.getExtra(binaryUnmarshaler{&p}); err != nil { return 0, 0, "", err } @@ -189,10 +198,9 @@ func (d Descriptor) ModifiedAt() time.Time { return time.Unix(d.raw.ModifiedAt, // Name returns the name of the data object. func (d Descriptor) Name() string { return strings.TrimRight(string(d.raw.Name[:]), "\000") } -// GetMetadata reads metadata from d into v. If the encoding.BinaryUnmarshaler interface is -// implemented by v, it is used for unmarshaling. Otherwise, binary.Read() is used. -func (d Descriptor) GetMetadata(v any) error { - if err := d.raw.getExtra(v); err != nil { +// GetMetadata unmarshals metadata from the "extra" field of d into md. +func (d Descriptor) GetMetadata(md encoding.BinaryUnmarshaler) error { + if err := d.raw.getExtra(md); err != nil { return fmt.Errorf("%w", err) } return nil @@ -238,7 +246,7 @@ func (d Descriptor) SignatureMetadata() (ht crypto.Hash, fp []byte, err error) { var s signature - if err := d.raw.getExtra(&s); err != nil { + if err := d.raw.getExtra(binaryUnmarshaler{&s}); err != nil { return ht, fp, fmt.Errorf("%w", err) } @@ -265,7 +273,7 @@ func (d Descriptor) CryptoMessageMetadata() (FormatType, MessageType, error) { var m cryptoMessage - if err := d.raw.getExtra(&m); err != nil { + if err := d.raw.getExtra(binaryUnmarshaler{&m}); err != nil { return 0, 0, fmt.Errorf("%w", err) } @@ -280,7 +288,7 @@ func (d Descriptor) SBOMMetadata() (SBOMFormat, error) { var s sbom - if err := d.raw.getExtra(&s); err != nil { + if err := d.raw.getExtra(binaryUnmarshaler{&s}); err != nil { return 0, fmt.Errorf("%w", err) } diff --git a/pkg/sif/descriptor_input.go b/pkg/sif/descriptor_input.go index 5ee6bcd9..3cfe5c65 100644 --- a/pkg/sif/descriptor_input.go +++ b/pkg/sif/descriptor_input.go @@ -7,6 +7,7 @@ package sif import ( "crypto" + "encoding" "errors" "fmt" "io" @@ -19,7 +20,7 @@ type descriptorOpts struct { linkID uint32 alignment int name string - extra any + md encoding.BinaryMarshaler t time.Time } @@ -92,11 +93,10 @@ func OptObjectTime(t time.Time) DescriptorInputOpt { } } -// OptMetadata sets v as the metadata for a data object. If the encoding.BinaryMarshaler interface -// is implemented by v, it is used for marshaling. Otherwise, binary.Write() is used. -func OptMetadata(v any) DescriptorInputOpt { +// OptMetadata marshals metadata from md into the "extra" field of d. +func OptMetadata(md encoding.BinaryMarshaler) DescriptorInputOpt { return func(t DataType, opts *descriptorOpts) error { - opts.extra = v + opts.md = md return nil } } @@ -164,7 +164,7 @@ func OptCryptoMessageMetadata(ft FormatType, mt MessageType) DescriptorInputOpt Messagetype: mt, } - opts.extra = m + opts.md = binaryMarshaler{m} return nil } } @@ -193,7 +193,7 @@ func OptPartitionMetadata(fs FSType, pt PartType, arch string) DescriptorInputOp Arch: sifarch, } - opts.extra = p + opts.md = p return nil } } @@ -230,7 +230,7 @@ func OptSignatureMetadata(ht crypto.Hash, fp []byte) DescriptorInputOpt { } copy(s.Entity[:], fp) - opts.extra = s + opts.md = binaryMarshaler{s} return nil } } @@ -248,7 +248,7 @@ func OptSBOMMetadata(f SBOMFormat) DescriptorInputOpt { Format: f, } - opts.extra = s + opts.md = binaryMarshaler{s} return nil } } @@ -327,5 +327,5 @@ func (di DescriptorInput) fillDescriptor(t time.Time, d *rawDescriptor) error { return err } - return d.setExtra(di.opts.extra) + return d.setExtra(di.opts.md) } diff --git a/pkg/sif/descriptor_test.go b/pkg/sif/descriptor_test.go index ab859244..9712c595 100644 --- a/pkg/sif/descriptor_test.go +++ b/pkg/sif/descriptor_test.go @@ -129,7 +129,7 @@ func TestDescriptor_GetMetadata(t *testing.T) { tests := []struct { name string rd rawDescriptor - wantMD any + wantMD testMetadata wantErr error }{ { @@ -261,7 +261,7 @@ func TestDescriptor_SignatureMetadata(t *testing.T) { rd := rawDescriptor{ DataType: tt.dt, } - if err := rd.setExtra(sig); err != nil { + if err := rd.setExtra(binaryMarshaler{sig}); err != nil { t.Fatal(err) } @@ -295,7 +295,7 @@ func TestDescriptor_CryptoMessageMetadata(t *testing.T) { rd := rawDescriptor{ DataType: DataCryptoMessage, } - if err := rd.setExtra(m); err != nil { + if err := rd.setExtra(binaryMarshaler{m}); err != nil { t.Fatal(err) } @@ -351,7 +351,7 @@ func TestDescriptor_SBOMMetadata(t *testing.T) { rd := rawDescriptor{ DataType: DataSBOM, } - if err := rd.setExtra(m); err != nil { + if err := rd.setExtra(binaryMarshaler{m}); err != nil { t.Fatal(err) }