diff options
Diffstat (limited to 'pkg/siftool')
36 files changed, 331 insertions, 58 deletions
diff --git a/pkg/siftool/add.go b/pkg/siftool/add.go index 941f9b0..75f11df 100644 --- a/pkg/siftool/add.go +++ b/pkg/siftool/add.go @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2021, Sylabs Inc. All rights reserved. +// Copyright (c) 2019-2022, Sylabs Inc. All rights reserved. // Copyright (c) 2017, SingularityWare, LLC. All rights reserved. // Copyright (c) 2017, Yannick Cote <yhcote@gmail.com> All rights reserved. // This software is licensed under a 3-clause BSD license. Please consult the @@ -27,6 +27,7 @@ var ( partArch *int32 signHash *int32 signEntity *string + sbomFormat *string groupID *uint32 linkID *uint32 alignment *int @@ -50,9 +51,9 @@ func getAddExamples(rootPath string) string { func addFlags(fs *pflag.FlagSet) { dataType = fs.Int("datatype", 0, `the type of data to add [NEEDED, no default]: - 1-Deffile, 2-EnvVar, 3-Labels, - 4-Partition, 5-Signature, 6-GenericJSON, - 7-Generic, 8-CryptoMessage`) + 1-Deffile, 2-EnvVar, 3-Labels, + 4-Partition, 5-Signature, 6-GenericJSON, + 7-Generic, 8-CryptoMessage, 9-SBOM`) partType = fs.Int32("parttype", 0, `the type of partition (with -datatype 4-Partition) [NEEDED, no default]: 1-System, 2-PrimSys, 3-Data, @@ -66,7 +67,7 @@ func addFlags(fs *pflag.FlagSet) { 1-386, 2-amd64, 3-arm, 4-arm64, 5-ppc64, 6-ppc64le, 7-mips, 8-mipsle, 9-mips64, - 10-mips64le, 11-s390x`) + 10-mips64le, 11-s390x, 12-riscv64`) signHash = fs.Int32("signhash", 0, `the signature hash used (with -datatype 5-Signature) [NEEDED, no default]: 1-SHA256, 2-SHA384, 3-SHA512, @@ -74,9 +75,13 @@ func addFlags(fs *pflag.FlagSet) { signEntity = fs.String("signentity", "", `the entity that signs (with -datatype 5-Signature) [NEEDED, no default]: example: 433FE984155206BD962725E20E8713472A879943`) + sbomFormat = fs.String("sbomformat", "", `the SBOM format (with -datatype 9-sbom): + cyclonedx-json, cyclonedx-xml, github-json, + spdx-json, spdx-rdf, spdx-tag-value, + spdx-yaml, syft-json`) groupID = fs.Uint32("groupid", 0, "set groupid [default: 0]") linkID = fs.Uint32("link", 0, "set link pointer [default: 0]") - alignment = fs.Int("alignment", 0, "set alignment constraint [default: aligned on page size]") + alignment = fs.Int("alignment", 0, "set alignment [default: 4096 with -datatype 4-Partition, 0 otherwise]") name = fs.String("filename", "", "set logical filename/handle [default: input filename]") } @@ -101,6 +106,8 @@ func getDataType() (sif.DataType, error) { return sif.DataGeneric, nil case 8: return sif.DataCryptoMessage, nil + case 9: + return sif.DataSBOM, nil default: return 0, errDataTypeRequired } @@ -130,6 +137,8 @@ func getArch() string { return "mips64le" case 11: return "s390x" + case 12: + return "riscv64" default: return "unknown" } @@ -154,9 +163,35 @@ func getHashType() (crypto.Hash, error) { } } +var errInvalidSBOMFormat = errors.New("invalid SBOM format") + +func getSBOMFormat() (sif.SBOMFormat, error) { + switch *sbomFormat { + case "cyclonedx-json": + return sif.SBOMFormatCycloneDXJSON, nil + case "cyclonedx-xml": + return sif.SBOMFormatCycloneDXXML, nil + case "github", "github-json": + return sif.SBOMFormatGitHubJSON, nil + case "spdx-json": + return sif.SBOMFormatSPDXJSON, nil + case "spdx-rdf": + return sif.SBOMFormatSPDXRDF, nil + case "spdx-tag-value": + return sif.SBOMFormatSPDXTagValue, nil + case "spdx-yaml": + return sif.SBOMFormatSPDXYAML, nil + case "syft-json": + return sif.SBOMFormatSyftJSON, nil + default: + return 0, fmt.Errorf("%w: %v", errInvalidSBOMFormat, *sbomFormat) + } +} + var ( errPartitionArgs = errors.New("with partition datatype, -partfs, -parttype and -partarch must be passed") errInvalidFingerprintLength = errors.New("invalid signing entity fingerprint length") + errSBOMArgs = errors.New("with SBOM datatype, -sbomformat must be passed") ) func getOptions(dt sif.DataType, fs *pflag.FlagSet) ([]sif.DescriptorInputOpt, error) { @@ -180,7 +215,8 @@ func getOptions(dt sif.DataType, fs *pflag.FlagSet) ([]sif.DescriptorInputOpt, e opts = append(opts, sif.OptObjectName(*name)) } - if dt == sif.DataPartition { + switch dt { + case sif.DataPartition: if *partType == 0 || *partFS == 0 || *partArch == 0 { return nil, errPartitionArgs } @@ -188,9 +224,8 @@ func getOptions(dt sif.DataType, fs *pflag.FlagSet) ([]sif.DescriptorInputOpt, e opts = append(opts, sif.OptPartitionMetadata(sif.FSType(*partFS), sif.PartType(*partType), getArch()), ) - } - if dt == sif.DataSignature { + case sif.DataSignature: b, err := hex.DecodeString(*signEntity) if err != nil { return nil, fmt.Errorf("failed to decode signing entity fingerprint: %w", err) @@ -208,6 +243,18 @@ func getOptions(dt sif.DataType, fs *pflag.FlagSet) ([]sif.DescriptorInputOpt, e copy(fp, b) opts = append(opts, sif.OptSignatureMetadata(ht, fp)) + + case sif.DataSBOM: + if *sbomFormat == "" { + return nil, errSBOMArgs + } + + f, err := getSBOMFormat() + if err != nil { + return nil, err + } + + opts = append(opts, sif.OptSBOMMetadata(f)) } return opts, nil diff --git a/pkg/siftool/add_test.go b/pkg/siftool/add_test.go index 6d51a33..ccbb5b3 100644 --- a/pkg/siftool/add_test.go +++ b/pkg/siftool/add_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2021, Sylabs Inc. All rights reserved. +// Copyright (c) 2021-2022, Sylabs Inc. All rights reserved. // This software is licensed under a 3-clause BSD license. Please consult the // LICENSE file distributed with the sources of this project regarding your // rights to use or distribute this software. @@ -46,7 +46,7 @@ func Test_command_getAdd(t *testing.T) { } args = append(args, tt.flags...) - runCommand(t, cmd, args) + runCommand(t, cmd, args, nil) }) } } diff --git a/pkg/siftool/del_test.go b/pkg/siftool/del_test.go index 13fad07..070d609 100644 --- a/pkg/siftool/del_test.go +++ b/pkg/siftool/del_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2021, Sylabs Inc. All rights reserved. +// Copyright (c) 2021-2022, Sylabs Inc. All rights reserved. // This software is licensed under a 3-clause BSD license. Please consult the // LICENSE file distributed with the sources of this project regarding your // rights to use or distribute this software. @@ -24,7 +24,7 @@ func Test_command_getDel(t *testing.T) { cmd := c.getDel() - runCommand(t, cmd, []string{"1", makeTestSIF(t, true)}) + runCommand(t, cmd, []string{"1", makeTestSIF(t, true)}, nil) }) } } diff --git a/pkg/siftool/dump_test.go b/pkg/siftool/dump_test.go index 20362b8..fb13eb4 100644 --- a/pkg/siftool/dump_test.go +++ b/pkg/siftool/dump_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2021, Sylabs Inc. All rights reserved. +// Copyright (c) 2021-2022, Sylabs Inc. All rights reserved. // This software is licensed under a 3-clause BSD license. Please consult the // LICENSE file distributed with the sources of this project regarding your // rights to use or distribute this software. @@ -39,7 +39,7 @@ func Test_command_getDump(t *testing.T) { cmd := c.getDump() - runCommand(t, cmd, []string{tt.id, tt.path}) + runCommand(t, cmd, []string{tt.id, tt.path}, nil) }) } } diff --git a/pkg/siftool/header_test.go b/pkg/siftool/header_test.go index 5c19498..7aeb615 100644 --- a/pkg/siftool/header_test.go +++ b/pkg/siftool/header_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2021, Sylabs Inc. All rights reserved. +// Copyright (c) 2021-2022, Sylabs Inc. All rights reserved. // This software is licensed under a 3-clause BSD license. Please consult the // LICENSE file distributed with the sources of this project regarding your // rights to use or distribute this software. @@ -68,7 +68,7 @@ func Test_command_getHeader(t *testing.T) { cmd := c.getHeader() - runCommand(t, cmd, []string{tt.path}) + runCommand(t, cmd, []string{tt.path}, nil) }) } } diff --git a/pkg/siftool/info_test.go b/pkg/siftool/info_test.go index 87f3a46..963b00a 100644 --- a/pkg/siftool/info_test.go +++ b/pkg/siftool/info_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2021, Sylabs Inc. All rights reserved. +// Copyright (c) 2021-2022, Sylabs Inc. All rights reserved. // This software is licensed under a 3-clause BSD license. Please consult the // LICENSE file distributed with the sources of this project regarding your // rights to use or distribute this software. @@ -39,7 +39,7 @@ func Test_command_getInfo(t *testing.T) { cmd := c.getInfo() - runCommand(t, cmd, []string{tt.id, tt.path}) + runCommand(t, cmd, []string{tt.id, tt.path}, nil) }) } } diff --git a/pkg/siftool/list_test.go b/pkg/siftool/list_test.go index b7c1d32..5a4a47b 100644 --- a/pkg/siftool/list_test.go +++ b/pkg/siftool/list_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2021, Sylabs Inc. All rights reserved. +// Copyright (c) 2021-2022, Sylabs Inc. All rights reserved. // This software is licensed under a 3-clause BSD license. Please consult the // LICENSE file distributed with the sources of this project regarding your // rights to use or distribute this software. @@ -68,7 +68,7 @@ func Test_command_getList(t *testing.T) { cmd := c.getList() - runCommand(t, cmd, []string{tt.path}) + runCommand(t, cmd, []string{tt.path}, nil) }) } } diff --git a/pkg/siftool/mount.go b/pkg/siftool/mount.go new file mode 100644 index 0000000..6b59557 --- /dev/null +++ b/pkg/siftool/mount.go @@ -0,0 +1,27 @@ +// Copyright (c) 2022, Sylabs Inc. All rights reserved. +// This software is licensed under a 3-clause BSD license. Please consult the +// LICENSE file distributed with the sources of this project regarding your +// rights to use or distribute this software. + +package siftool + +import ( + "github.com/spf13/cobra" +) + +// getMount returns a command that mounts the primary system partition of a SIF image. +func (c *command) getMount() *cobra.Command { + return &cobra.Command{ + Use: "mount <sif_path> <mount_path>", + Short: "Mount primary system partition", + Long: "Mount the primary system partition of a SIF image", + Example: c.opts.rootPath + " mount image.sif path/", + Args: cobra.ExactArgs(2), + PreRunE: c.initApp, + RunE: func(cmd *cobra.Command, args []string) error { + return c.app.Mount(cmd.Context(), args[0], args[1]) + }, + DisableFlagsInUseLine: true, + Hidden: true, // hide while command is experimental + } +} diff --git a/pkg/siftool/mount_test.go b/pkg/siftool/mount_test.go new file mode 100644 index 0000000..3b2848e --- /dev/null +++ b/pkg/siftool/mount_test.go @@ -0,0 +1,61 @@ +// Copyright (c) 2022, Sylabs Inc. All rights reserved. +// This software is licensed under a 3-clause BSD license. Please consult the +// LICENSE file distributed with the sources of this project regarding your +// rights to use or distribute this software. + +package siftool + +import ( + "os" + "os/exec" + "path/filepath" + "testing" + + "github.com/sylabs/sif/v2/pkg/sif" +) + +func Test_command_getMount(t *testing.T) { + if _, err := exec.LookPath("squashfuse"); err != nil { + t.Skip("squashfuse not found, skipping mount tests") + } + + tests := []struct { + name string + opts commandOpts + path string + wantErr error + }{ + { + name: "Empty", + path: filepath.Join(corpus, "empty.sif"), + wantErr: sif.ErrNoObjects, + }, + { + name: "OneGroup", + path: filepath.Join(corpus, "one-group.sif"), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + path, err := os.MkdirTemp("", "siftool-mount-*") + if err != nil { + t.Fatal(err) + } + t.Cleanup(func() { + cmd := exec.Command("fusermount", "-u", path) + + if err := cmd.Run(); err != nil { + t.Log(err) + } + + os.RemoveAll(path) + }) + + c := &command{opts: tt.opts} + + cmd := c.getMount() + + runCommand(t, cmd, []string{tt.path, path}, tt.wantErr) + }) + } +} diff --git a/pkg/siftool/new_test.go b/pkg/siftool/new_test.go index af4cd75..81bcd58 100644 --- a/pkg/siftool/new_test.go +++ b/pkg/siftool/new_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2021, Sylabs Inc. All rights reserved. +// Copyright (c) 2021-2022, Sylabs Inc. All rights reserved. // This software is licensed under a 3-clause BSD license. Please consult the // LICENSE file distributed with the sources of this project regarding your // rights to use or distribute this software. @@ -32,7 +32,7 @@ func Test_command_getNew(t *testing.T) { cmd := c.getNew() - runCommand(t, cmd, []string{tf.Name()}) + runCommand(t, cmd, []string{tf.Name()}, nil) }) } } diff --git a/pkg/siftool/setprim_test.go b/pkg/siftool/setprim_test.go index e37b240..13cd0e3 100644 --- a/pkg/siftool/setprim_test.go +++ b/pkg/siftool/setprim_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2021, Sylabs Inc. All rights reserved. +// Copyright (c) 2021-2022, Sylabs Inc. All rights reserved. // This software is licensed under a 3-clause BSD license. Please consult the // LICENSE file distributed with the sources of this project regarding your // rights to use or distribute this software. @@ -24,7 +24,7 @@ func Test_command_getSetPrim(t *testing.T) { cmd := c.getSetPrim() - runCommand(t, cmd, []string{"1", makeTestSIF(t, true)}) + runCommand(t, cmd, []string{"1", makeTestSIF(t, true)}, nil) }) } } diff --git a/pkg/siftool/siftool.go b/pkg/siftool/siftool.go index 4e624f1..aa59f61 100644 --- a/pkg/siftool/siftool.go +++ b/pkg/siftool/siftool.go @@ -1,4 +1,4 @@ -// Copyright (c) 2018-2021, Sylabs Inc. All rights reserved. +// Copyright (c) 2018-2022, Sylabs Inc. All rights reserved. // Copyright (c) 2017, SingularityWare, LLC. All rights reserved. // Copyright (c) 2017, Yannick Cote <yhcote@gmail.com> All rights reserved. // This software is licensed under a 3-clause BSD license. Please consult the @@ -23,6 +23,7 @@ type command struct { func (c *command) initApp(cmd *cobra.Command, args []string) error { app, err := siftool.New( siftool.OptAppOutput(cmd.OutOrStdout()), + siftool.OptAppError(cmd.ErrOrStderr()), ) c.app = app @@ -31,12 +32,21 @@ func (c *command) initApp(cmd *cobra.Command, args []string) error { // commandOpts contains configured options. type commandOpts struct { - rootPath string + rootPath string + experimental bool } // CommandOpt are used to configure optional command behavior. type CommandOpt func(*commandOpts) error +// OptWithExperimental enables/disables experimental commands. +func OptWithExperimental(b bool) CommandOpt { + return func(co *commandOpts) error { + co.experimental = b + return nil + } +} + // AddCommands adds siftool commands to cmd according to opts. // // A set of commands are provided to display elements such as the SIF global @@ -66,5 +76,10 @@ func AddCommands(cmd *cobra.Command, opts ...CommandOpt) error { c.getSetPrim(), ) + if c.opts.experimental { + cmd.AddCommand(c.getMount()) + cmd.AddCommand(c.getUnmount()) + } + return nil } diff --git a/pkg/siftool/siftool_test.go b/pkg/siftool/siftool_test.go index 5236254..606d6eb 100644 --- a/pkg/siftool/siftool_test.go +++ b/pkg/siftool/siftool_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2021, Sylabs Inc. All rights reserved. +// Copyright (c) 2021-2022, Sylabs Inc. All rights reserved. // This software is licensed under a 3-clause BSD license. Please consult the // LICENSE file distributed with the sources of this project regarding your // rights to use or distribute this software. @@ -6,6 +6,7 @@ package siftool import ( "bytes" + "errors" "os" "path/filepath" "testing" @@ -47,7 +48,7 @@ func makeTestSIF(t *testing.T, withDataObject bool) string { return tf.Name() } -func runCommand(t *testing.T, cmd *cobra.Command, args []string) { +func runCommand(t *testing.T, cmd *cobra.Command, args []string, wantErr error) { t.Helper() var out, err bytes.Buffer @@ -56,8 +57,8 @@ func runCommand(t *testing.T, cmd *cobra.Command, args []string) { cmd.SetArgs(args) - if err := cmd.Execute(); err != nil { - t.Fatal(err) + if got, want := cmd.Execute(), wantErr; !errors.Is(got, want) { + t.Fatalf("got error %v, want %v", got, want) } g := goldie.New(t, @@ -79,6 +80,11 @@ func TestAddCommands(t *testing.T) { args: []string{"help"}, }, { + name: "SifToolExperimental", + opts: []CommandOpt{OptWithExperimental(true)}, + args: []string{"help"}, + }, + { name: "Add", args: []string{"help", "add"}, }, @@ -110,6 +116,11 @@ func TestAddCommands(t *testing.T) { name: "SetPrim", args: []string{"help", "setprim"}, }, + { + name: "Mount", + opts: []CommandOpt{OptWithExperimental(true)}, + args: []string{"help", "mount"}, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -121,7 +132,7 @@ func TestAddCommands(t *testing.T) { t.Fatal(err) } - runCommand(t, cmd, tt.args) + runCommand(t, cmd, tt.args, nil) }) } } diff --git a/pkg/siftool/testdata/TestAddCommands/Add/out.golden b/pkg/siftool/testdata/TestAddCommands/Add/out.golden index 16c47e5..3f39697 100644 --- a/pkg/siftool/testdata/TestAddCommands/Add/out.golden +++ b/pkg/siftool/testdata/TestAddCommands/Add/out.golden @@ -9,12 +9,12 @@ siftool add image.sif rootfs.squashfs --datatype 4 --parttype 1 --partfs 1 ----p siftool add image.sif signature.bin -datatype 5 --signentity 433FE984155206BD962725E20E8713472A879943 --signhash 1 Flags: - --alignment int set alignment constraint [default: aligned on page size] + --alignment int set alignment [default: 4096 with -datatype 4-Partition, 0 otherwise] --datatype int the type of data to add [NEEDED, no default]: - 1-Deffile, 2-EnvVar, 3-Labels, - 4-Partition, 5-Signature, 6-GenericJSON, - 7-Generic, 8-CryptoMessage + 1-Deffile, 2-EnvVar, 3-Labels, + 4-Partition, 5-Signature, 6-GenericJSON, + 7-Generic, 8-CryptoMessage, 9-SBOM --filename string set logical filename/handle [default: input filename] --groupid uint32 set groupid [default: 0] -h, --help help for add @@ -24,7 +24,7 @@ Flags: 1-386, 2-amd64, 3-arm, 4-arm64, 5-ppc64, 6-ppc64le, 7-mips, 8-mipsle, 9-mips64, - 10-mips64le, 11-s390x + 10-mips64le, 11-s390x, 12-riscv64 --partfs int32 the filesystem used (with -datatype 4-Partition) [NEEDED, no default]: 1-Squash, 2-Ext3, 3-ImmuObj, @@ -33,6 +33,10 @@ Flags: [NEEDED, no default]: 1-System, 2-PrimSys, 3-Data, 4-Overlay + --sbomformat string the SBOM format (with -datatype 9-sbom): + cyclonedx-json, cyclonedx-xml, github-json, + spdx-json, spdx-rdf, spdx-tag-value, + spdx-yaml, syft-json --signentity string the entity that signs (with -datatype 5-Signature) [NEEDED, no default]: example: 433FE984155206BD962725E20E8713472A879943 diff --git a/pkg/siftool/testdata/TestAddCommands/Mount/err.golden b/pkg/siftool/testdata/TestAddCommands/Mount/err.golden new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/pkg/siftool/testdata/TestAddCommands/Mount/err.golden diff --git a/pkg/siftool/testdata/TestAddCommands/Mount/out.golden b/pkg/siftool/testdata/TestAddCommands/Mount/out.golden new file mode 100644 index 0000000..3df015d --- /dev/null +++ b/pkg/siftool/testdata/TestAddCommands/Mount/out.golden @@ -0,0 +1,10 @@ +Mount the primary system partition of a SIF image + +Usage: + siftool mount <sif_path> <mount_path> + +Examples: +siftool mount image.sif path/ + +Flags: + -h, --help help for mount diff --git a/pkg/siftool/testdata/TestAddCommands/SifToolExperimental/err.golden b/pkg/siftool/testdata/TestAddCommands/SifToolExperimental/err.golden new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/pkg/siftool/testdata/TestAddCommands/SifToolExperimental/err.golden diff --git a/pkg/siftool/testdata/TestAddCommands/SifToolExperimental/out.golden b/pkg/siftool/testdata/TestAddCommands/SifToolExperimental/out.golden new file mode 100644 index 0000000..2d8532f --- /dev/null +++ b/pkg/siftool/testdata/TestAddCommands/SifToolExperimental/out.golden @@ -0,0 +1,19 @@ +Usage: + siftool [command] + +Available Commands: + add Add data object + completion Generate the autocompletion script for the specified shell + del Delete data object + dump Dump data object + header Display global header + help Help about any command + info Display data object info + list List data objects + new Create SIF image + setprim Set primary system partition + +Flags: + -h, --help help for siftool + +Use "siftool [command] --help" for more information about a command. diff --git a/pkg/siftool/testdata/Test_command_getDump/Three/out.golden b/pkg/siftool/testdata/Test_command_getDump/Three/out.golden index 0299536..4e354d9 100644 --- a/pkg/siftool/testdata/Test_command_getDump/Three/out.golden +++ b/pkg/siftool/testdata/Test_command_getDump/Three/out.golden @@ -1,15 +1,15 @@ -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256 -{"version":1,"header":{"digest":"sha256:635fa0a14a8ef0c0351ed3e985799ed1d4f75ce973dea3cc76c99710795cc3f1"},"objects":[{"relativeId":0,"descriptorDigest":"sha256:3634ad01db0dd5482ecf685267b53d6201690438ca27c3d7ea91c971a1f41f92","objectDigest":"sha256:004dfc8da678c309de28b5386a1e9efd57f536b150c40d29b31506aa0fb17ec2"},{"relativeId":1,"descriptorDigest":"sha256:db74cb63348414def73535c9f0f83e8ad7df61229ed2806f4da8b69d6d7464d6","objectDigest":"sha256:5f78c33274e43fa9de5659265c1d917e25c03722dcb0b8d27db8d5feaa813953"}]} +{"version":1,"header":{"digest":"sha256:635fa0a14a8ef0c0351ed3e985799ed1d4f75ce973dea3cc76c99710795cc3f1"},"objects":[{"relativeId":0,"descriptorDigest":"sha256:3634ad01db0dd5482ecf685267b53d6201690438ca27c3d7ea91c971a1f41f92","objectDigest":"sha256:004dfc8da678c309de28b5386a1e9efd57f536b150c40d29b31506aa0fb17ec2"},{"relativeId":1,"descriptorDigest":"sha256:04b5f87c9692a54f80d10fb6af00c779763aeca29d610348854bd97cd8bf66fd","objectDigest":"sha256:9f9c4e5e131934969b4ac8f495691c70b8c6c8e3f489c2c9ab5f1af82bce0604"}]} -----BEGIN PGP SIGNATURE----- -wsBzBAEBCAAnBQJe+oD0CZCiDCfuf/e6hBahBBIEXIwLEATQWN5L7aIMJ+5/97qE -AABQ4QgAkWcLNLcghZ96VnJ9+67qbsdwp51rfERCKN0dZLBTHKN5Qjn1BWM/XbPj -Qnl0F6D6YBId7c/KO0sbb3EHUdpmMEQlouQYFOTHWtdyvwO6spRLBx5EQA7Iv0rF -jREz/jC7GaREK94u+hXRr94+FH5gEnHUL+Vg7pW/+cGiwLY1ddoL8ELgYhxqxd9J -sET+vU1E4GJ3TyYFhVFsMsNeW7dQauqjQSJxMLTwXNphxTH19ePbJ2uDE2UJ3fn7 -up5ruugRyEe5qgRICGxRSDp8/INGRvoDUi32T9uLORzS+umRX5YW0b6RWD+5R72V -0ewbMTJIx2lpfQGPMWROwcF7nkLdWQ== -=WWGX +wsBzBAEBCAAnBQJe+oD0CZCiDCfuf/e6hBYhBBIEXIwLEATQWN5L7aIMJ+5/97qE +AAC46gf/VXyzZ649nttrX13JkM5kRVPlAIblBQxfoUxA1xwIXdRoM5ceDY0Em+YD +8b6Xl1w2sDTqo0R15cJSh8sf0ClFOvYpDQRNCwKx17k1Wd0gHcW4QVu6gJnlbNvN +o/EJdEN2TkbCM2aFvj34DAIfErRBIEsCeDDvJ/6WUSySWbnydfNU2pCsnK4A7l2H +KOXFzSaPijG9L/pU3O3vNZ+fXPffqHL9JVhs5Mt/Yo3oeoEnoVaKvJLGx/fyl+Gj +7qsfWFyHWzRCww9VFg/TCBeUku0CYRfXhxOgo4OuHNr8oo82rKDZU6+l3UZ2Sw8T ++kLe/zUkaILocGOvhvKdi630OGGb/Q== +=3Jq2 -----END PGP SIGNATURE-----
\ No newline at end of file diff --git a/pkg/siftool/testdata/Test_command_getDump/Two/out.golden b/pkg/siftool/testdata/Test_command_getDump/Two/out.golden Binary files differindex 7d174b1..cf6539a 100644 --- a/pkg/siftool/testdata/Test_command_getDump/Two/out.golden +++ b/pkg/siftool/testdata/Test_command_getDump/Two/out.golden diff --git a/pkg/siftool/testdata/Test_command_getHeader/OneGroup/out.golden b/pkg/siftool/testdata/Test_command_getHeader/OneGroup/out.golden index bc631d6..a2941c1 100644 --- a/pkg/siftool/testdata/Test_command_getHeader/OneGroup/out.golden +++ b/pkg/siftool/testdata/Test_command_getHeader/OneGroup/out.golden @@ -5,4 +5,4 @@ Descriptors Total: 48 Descriptors Offset: 4096 Descriptors Size: 27 KiB Data Offset: 32176 -Data Size: 5 KiB +Data Size: 9 KiB diff --git a/pkg/siftool/testdata/Test_command_getHeader/TwoGroups/out.golden b/pkg/siftool/testdata/Test_command_getHeader/TwoGroups/out.golden index 0db18f0..c16ef18 100644 --- a/pkg/siftool/testdata/Test_command_getHeader/TwoGroups/out.golden +++ b/pkg/siftool/testdata/Test_command_getHeader/TwoGroups/out.golden @@ -5,4 +5,4 @@ Descriptors Total: 48 Descriptors Offset: 4096 Descriptors Size: 27 KiB Data Offset: 32176 -Data Size: 9 KiB +Data Size: 265 KiB diff --git a/pkg/siftool/testdata/Test_command_getHeader/TwoGroupsSigned/out.golden b/pkg/siftool/testdata/Test_command_getHeader/TwoGroupsSigned/out.golden index acf8b17..44854c9 100644 --- a/pkg/siftool/testdata/Test_command_getHeader/TwoGroupsSigned/out.golden +++ b/pkg/siftool/testdata/Test_command_getHeader/TwoGroupsSigned/out.golden @@ -5,4 +5,4 @@ Descriptors Total: 48 Descriptors Offset: 4096 Descriptors Size: 27 KiB Data Offset: 32176 -Data Size: 17 KiB +Data Size: 266 KiB diff --git a/pkg/siftool/testdata/Test_command_getInfo/Two/out.golden b/pkg/siftool/testdata/Test_command_getInfo/Two/out.golden index f34651f..f49a554 100644 --- a/pkg/siftool/testdata/Test_command_getInfo/Two/out.golden +++ b/pkg/siftool/testdata/Test_command_getInfo/Two/out.golden @@ -3,7 +3,7 @@ Group ID: 1 Linked ID: NONE Offset: 36864 - Size: 4 + Size: 4096 Filesystem Type: Squashfs Partition Type: *System Architecture: 386 diff --git a/pkg/siftool/testdata/Test_command_getList/OneGroup/out.golden b/pkg/siftool/testdata/Test_command_getList/OneGroup/out.golden index fe78f62..01400f9 100644 --- a/pkg/siftool/testdata/Test_command_getList/OneGroup/out.golden +++ b/pkg/siftool/testdata/Test_command_getList/OneGroup/out.golden @@ -2,4 +2,4 @@ ID |GROUP |LINK |SIF POSITION (start-end) |TYPE ------------------------------------------------------------------------------ 1 |1 |NONE |32768-32772 |FS (Raw/System/386) -2 |1 |NONE |36864-36868 |FS (Squashfs/*System/386) +2 |1 |NONE |36864-40960 |FS (Squashfs/*System/386) diff --git a/pkg/siftool/testdata/Test_command_getList/OneGroupSigned/out.golden b/pkg/siftool/testdata/Test_command_getList/OneGroupSigned/out.golden index 98030e3..5b663d3 100644 --- a/pkg/siftool/testdata/Test_command_getList/OneGroupSigned/out.golden +++ b/pkg/siftool/testdata/Test_command_getList/OneGroupSigned/out.golden @@ -2,5 +2,5 @@ ID |GROUP |LINK |SIF POSITION (start-end) |TYPE ------------------------------------------------------------------------------ 1 |1 |NONE |32768-32772 |FS (Raw/System/386) -2 |1 |NONE |36864-36868 |FS (Squashfs/*System/386) +2 |1 |NONE |36864-40960 |FS (Squashfs/*System/386) 3 |NONE |1 (G) |40960-42014 |Signature (SHA-256) diff --git a/pkg/siftool/testdata/Test_command_getList/TwoGroups/out.golden b/pkg/siftool/testdata/Test_command_getList/TwoGroups/out.golden index 648c280..1eca2ab 100644 --- a/pkg/siftool/testdata/Test_command_getList/TwoGroups/out.golden +++ b/pkg/siftool/testdata/Test_command_getList/TwoGroups/out.golden @@ -2,5 +2,5 @@ ID |GROUP |LINK |SIF POSITION (start-end) |TYPE ------------------------------------------------------------------------------ 1 |1 |NONE |32768-32772 |FS (Raw/System/386) -2 |1 |NONE |36864-36868 |FS (Squashfs/*System/386) -3 |2 |NONE |40960-40964 |FS (Ext3/System/amd64) +2 |1 |NONE |36864-40960 |FS (Squashfs/*System/386) +3 |2 |NONE |40960-303104 |FS (Ext3/System/amd64) diff --git a/pkg/siftool/testdata/Test_command_getList/TwoGroupsSigned/out.golden b/pkg/siftool/testdata/Test_command_getList/TwoGroupsSigned/out.golden index f21bf6d..17240ba 100644 --- a/pkg/siftool/testdata/Test_command_getList/TwoGroupsSigned/out.golden +++ b/pkg/siftool/testdata/Test_command_getList/TwoGroupsSigned/out.golden @@ -2,7 +2,7 @@ ID |GROUP |LINK |SIF POSITION (start-end) |TYPE ------------------------------------------------------------------------------ 1 |1 |NONE |32768-32772 |FS (Raw/System/386) -2 |1 |NONE |36864-36868 |FS (Squashfs/*System/386) -3 |2 |NONE |40960-40964 |FS (Ext3/System/amd64) -4 |NONE |1 (G) |45056-46110 |Signature (SHA-256) -5 |NONE |2 (G) |49152-50007 |Signature (SHA-256) +2 |1 |NONE |36864-40960 |FS (Squashfs/*System/386) +3 |2 |NONE |40960-303104 |FS (Ext3/System/amd64) +4 |NONE |1 (G) |303104-304158 |Signature (SHA-256) +5 |NONE |2 (G) |304158-305013 |Signature (SHA-256) diff --git a/pkg/siftool/testdata/Test_command_getMount/Empty/err.golden b/pkg/siftool/testdata/Test_command_getMount/Empty/err.golden new file mode 100644 index 0000000..cd860b8 --- /dev/null +++ b/pkg/siftool/testdata/Test_command_getMount/Empty/err.golden @@ -0,0 +1 @@ +Error: failed to get partition descriptor: no objects in image diff --git a/pkg/siftool/testdata/Test_command_getMount/Empty/out.golden b/pkg/siftool/testdata/Test_command_getMount/Empty/out.golden new file mode 100644 index 0000000..f22522a --- /dev/null +++ b/pkg/siftool/testdata/Test_command_getMount/Empty/out.golden @@ -0,0 +1,9 @@ +Usage: + mount <sif_path> <mount_path> + +Examples: + mount image.sif path/ + +Flags: + -h, --help help for mount + diff --git a/pkg/siftool/testdata/Test_command_getMount/OneGroup/err.golden b/pkg/siftool/testdata/Test_command_getMount/OneGroup/err.golden new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/pkg/siftool/testdata/Test_command_getMount/OneGroup/err.golden diff --git a/pkg/siftool/testdata/Test_command_getMount/OneGroup/out.golden b/pkg/siftool/testdata/Test_command_getMount/OneGroup/out.golden new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/pkg/siftool/testdata/Test_command_getMount/OneGroup/out.golden diff --git a/pkg/siftool/testdata/Test_command_getUnmount/err.golden b/pkg/siftool/testdata/Test_command_getUnmount/err.golden new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/pkg/siftool/testdata/Test_command_getUnmount/err.golden diff --git a/pkg/siftool/testdata/Test_command_getUnmount/out.golden b/pkg/siftool/testdata/Test_command_getUnmount/out.golden new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/pkg/siftool/testdata/Test_command_getUnmount/out.golden diff --git a/pkg/siftool/unmount.go b/pkg/siftool/unmount.go new file mode 100644 index 0000000..8814182 --- /dev/null +++ b/pkg/siftool/unmount.go @@ -0,0 +1,27 @@ +// Copyright (c) 2022, Sylabs Inc. All rights reserved. +// This software is licensed under a 3-clause BSD license. Please consult the +// LICENSE file distributed with the sources of this project regarding your +// rights to use or distribute this software. + +package siftool + +import ( + "github.com/spf13/cobra" +) + +// getUnmount returns a command that unmounts the primary system partition of a SIF image. +func (c *command) getUnmount() *cobra.Command { + return &cobra.Command{ + Use: "unmount <mount_path>", + Short: "Unmount primary system partition", + Long: "Unmount a primary system partition of a SIF image", + Example: c.opts.rootPath + " unmount path/", + Args: cobra.ExactArgs(1), + PreRunE: c.initApp, + RunE: func(cmd *cobra.Command, args []string) error { + return c.app.Unmount(cmd.Context(), args[0]) + }, + DisableFlagsInUseLine: true, + Hidden: true, // hide while command is experimental + } +} diff --git a/pkg/siftool/unmount_test.go b/pkg/siftool/unmount_test.go new file mode 100644 index 0000000..2cf8160 --- /dev/null +++ b/pkg/siftool/unmount_test.go @@ -0,0 +1,42 @@ +// Copyright (c) 2022, Sylabs Inc. All rights reserved. +// This software is licensed under a 3-clause BSD license. Please consult the +// LICENSE file distributed with the sources of this project regarding your +// rights to use or distribute this software. + +package siftool + +import ( + "context" + "os" + "os/exec" + "path/filepath" + "testing" + + "github.com/sylabs/sif/v2/pkg/user" +) + +func Test_command_getUnmount(t *testing.T) { + if _, err := exec.LookPath("squashfuse"); err != nil { + t.Skip(" not found, skipping unmount tests") + } + if _, err := exec.LookPath("fusermount"); err != nil { + t.Skip(" not found, skipping unmount tests") + } + + path, err := os.MkdirTemp("", "siftool-unmount-*") + if err != nil { + t.Fatal(err) + } + t.Cleanup(func() { + os.RemoveAll(path) + }) + + testSIF := filepath.Join(corpus, "one-group.sif") + if err := user.Mount(context.Background(), testSIF, path); err != nil { + t.Fatal(err) + } + + c := &command{} + cmd := c.getUnmount() + runCommand(t, cmd, []string{path}, nil) +} |