-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add experimental 'mount' command
Add experimental support for rootless mount of SIF images.
- Loading branch information
Adam Hughes
committed
Apr 4, 2022
1 parent
c5ac0f2
commit a31c3cd
Showing
7 changed files
with
170 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// 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" | ||
|
||
"github.com/sylabs/sif/v2/internal/pkg/exp" | ||
) | ||
|
||
// Mount mounts the primary system partition of the SIF file at path into mountPath. | ||
func (a *App) Mount(ctx context.Context, path, mountPath string) error { | ||
return exp.Mount(ctx, path, mountPath, | ||
exp.OptMountStdout(a.opts.out), | ||
exp.OptMountStderr(a.opts.err), | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
// 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 exp contains experimental functionality that is not sufficiently mature to be exported | ||
// as part of the module API. | ||
package exp | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"fmt" | ||
"io" | ||
"os" | ||
"os/exec" | ||
"path/filepath" | ||
|
||
"github.com/sylabs/sif/v2/pkg/sif" | ||
) | ||
|
||
// mountSquashFS mounts the SquashFS filesystem from path at offset into mountPath. | ||
func mountSquashFS(ctx context.Context, offset int64, path, mountPath string, mo mountOpts) error { | ||
args := []string{ | ||
"-o", fmt.Sprintf("ro,offset=%d", offset), | ||
filepath.Clean(path), | ||
filepath.Clean(mountPath), | ||
} | ||
|
||
cmd := exec.CommandContext(ctx, "squashfuse", args...) | ||
cmd.Stdout = mo.stdout | ||
cmd.Stderr = mo.stderr | ||
|
||
if err := cmd.Run(); err != nil { | ||
return fmt.Errorf("failed to mount: %w", err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// mountOpts accumulates mount options. | ||
type mountOpts struct { | ||
stdout io.Writer | ||
stderr io.Writer | ||
} | ||
|
||
// MountOpt are used to specify mount options. | ||
type MountOpt func(*mountOpts) error | ||
|
||
// OptMountStdout writes standard output to w. | ||
func OptMountStdout(w io.Writer) MountOpt { | ||
return func(mo *mountOpts) error { | ||
mo.stdout = w | ||
return nil | ||
} | ||
} | ||
|
||
// OptMountStderr writes standard error to w. | ||
func OptMountStderr(w io.Writer) MountOpt { | ||
return func(mo *mountOpts) error { | ||
mo.stderr = w | ||
return nil | ||
} | ||
} | ||
|
||
var errUnsupportedFSType = errors.New("unrecognized filesystem type") | ||
|
||
// Mount mounts the primary system partition of the SIF file at path into mountPath. | ||
// | ||
// Mount may start one or more underlying processes. By default, stdout and stderr of these | ||
// processes is discarded. To modify this behavior, consider using OptMountStdout and/or | ||
// OptMountStderr. | ||
func Mount(ctx context.Context, path, mountPath string, opts ...MountOpt) error { | ||
mo := mountOpts{} | ||
|
||
for _, opt := range opts { | ||
if err := opt(&mo); err != nil { | ||
return fmt.Errorf("%w", err) | ||
} | ||
} | ||
|
||
f, err := sif.LoadContainerFromPath(path, sif.OptLoadWithFlag(os.O_RDONLY)) | ||
if err != nil { | ||
return fmt.Errorf("failed to load image: %w", err) | ||
} | ||
defer func() { _ = f.UnloadContainer() }() | ||
|
||
d, err := f.GetDescriptor(sif.WithPartitionType(sif.PartPrimSys)) | ||
if err != nil { | ||
return fmt.Errorf("failed to get partition descriptor: %w", err) | ||
} | ||
|
||
fs, _, _, err := d.PartitionMetadata() | ||
if err != nil { | ||
return fmt.Errorf("failed to get partition metadata: %w", err) | ||
} | ||
|
||
switch fs { | ||
case sif.FsSquash: | ||
return mountSquashFS(ctx, d.Offset(), path, mountPath, mo) | ||
default: | ||
return errUnsupportedFSType | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |