Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move mount/unmount to user package #211

Merged
merged 1 commit into from Apr 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 4 additions & 4 deletions internal/app/siftool/mount.go
Expand Up @@ -8,13 +8,13 @@ package siftool
import (
"context"

"github.com/sylabs/sif/v2/pkg/sif"
"github.com/sylabs/sif/v2/pkg/user"
)

// 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 sif.MountFUSE(ctx, path, mountPath,
sif.OptMountFUSEStdout(a.opts.out),
sif.OptMountFUSEStderr(a.opts.err),
return user.Mount(ctx, path, mountPath,
user.OptMountStdout(a.opts.out),
user.OptMountStderr(a.opts.err),
)
}
10 changes: 5 additions & 5 deletions internal/app/siftool/unmount.go
Expand Up @@ -8,13 +8,13 @@ package siftool
import (
"context"

"github.com/sylabs/sif/v2/pkg/sif"
"github.com/sylabs/sif/v2/pkg/user"
)

// Unmounts the FUSE mounted filesystem at mountPath.
// Unmounts the filesystem at mountPath.
func (a *App) Unmount(ctx context.Context, mountPath string) error {
return sif.UnmountFUSE(ctx, mountPath,
sif.OptUnmountFUSEStdout(a.opts.out),
sif.OptUnmountFUSEStderr(a.opts.err),
return user.Unmount(ctx, mountPath,
user.OptUnmountStdout(a.opts.out),
user.OptUnmountStderr(a.opts.err),
)
}
4 changes: 2 additions & 2 deletions pkg/siftool/unmount_test.go
Expand Up @@ -12,7 +12,7 @@ import (
"path/filepath"
"testing"

"github.com/sylabs/sif/v2/pkg/sif"
"github.com/sylabs/sif/v2/pkg/user"
)

func Test_command_getUnmount(t *testing.T) {
Expand All @@ -32,7 +32,7 @@ func Test_command_getUnmount(t *testing.T) {
})

testSIF := filepath.Join(corpus, "one-group.sif")
if err := sif.MountFUSE(context.Background(), testSIF, path); err != nil {
if err := user.Mount(context.Background(), testSIF, path); err != nil {
t.Fatal(err)
}

Expand Down
46 changes: 24 additions & 22 deletions pkg/sif/mount.go → pkg/user/mount.go
Expand Up @@ -3,7 +3,7 @@
// LICENSE file distributed with the sources of this project regarding your
// rights to use or distribute this software.

package sif
package user

import (
"context"
Expand All @@ -13,10 +13,12 @@ import (
"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 mountFUSEOpts) error {
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),
Expand All @@ -34,38 +36,38 @@ func mountSquashFS(ctx context.Context, offset int64, path, mountPath string, mo
return nil
}

// mountFUSEOpts accumulates mount options.
type mountFUSEOpts struct {
// mountOpts accumulates mount options.
type mountOpts struct {
stdout io.Writer
stderr io.Writer
squashfusePath string
}

// MountFUSEOpt are used to specify mount options.
type MountFUSEOpt func(*mountFUSEOpts) error
// MountOpt are used to specify mount options.
type MountOpt func(*mountOpts) error

// OptMountStdout writes standard output to w.
func OptMountFUSEStdout(w io.Writer) MountFUSEOpt {
return func(mo *mountFUSEOpts) error {
func OptMountStdout(w io.Writer) MountOpt {
return func(mo *mountOpts) error {
mo.stdout = w
return nil
}
}

// OptMountFUSEStderr writes standard error to w.
func OptMountFUSEStderr(w io.Writer) MountFUSEOpt {
return func(mo *mountFUSEOpts) error {
// OptMountStderr writes standard error to w.
func OptMountStderr(w io.Writer) MountOpt {
return func(mo *mountOpts) error {
mo.stderr = w
return nil
}
}

var errSquashfusePathInvalid = errors.New("squashfuse path must be relative or absolute")

// OptMountFUSESquashfusePath sets an explicit path to the squashfuse binary. The path must be an
// OptMountSquashfusePath sets an explicit path to the squashfuse binary. The path must be an
// absolute or relative path.
func OptMountFUSESquashfusePath(path string) MountFUSEOpt {
return func(mo *mountFUSEOpts) error {
func OptMountSquashfusePath(path string) MountOpt {
return func(mo *mountOpts) error {
if filepath.Base(path) == path {
return errSquashfusePathInvalid
}
Expand All @@ -76,16 +78,16 @@ func OptMountFUSESquashfusePath(path string) MountFUSEOpt {

var errUnsupportedFSType = errors.New("unrecognized filesystem type")

// MountFUSE mounts the primary system partition of the SIF file at path into mountPath.
// Mount mounts the primary system partition of the SIF file at path into mountPath.
//
// MountFUSE may start one or more underlying processes. By default, stdout and stderr of these
// 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.
//
// By default, MountFUSE searches for a squashfuse binary in the directories named by the PATH
// By default, Mount searches for a squashfuse binary in the directories named by the PATH
// environment variable. To override this behavior, consider using OptMountSquashfusePath().
func MountFUSE(ctx context.Context, path, mountPath string, opts ...MountFUSEOpt) error {
mo := mountFUSEOpts{
func Mount(ctx context.Context, path, mountPath string, opts ...MountOpt) error {
mo := mountOpts{
squashfusePath: "squashfuse",
}

Expand All @@ -95,13 +97,13 @@ func MountFUSE(ctx context.Context, path, mountPath string, opts ...MountFUSEOpt
}
}

f, err := LoadContainerFromPath(path, OptLoadWithFlag(os.O_RDONLY))
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(WithPartitionType(PartPrimSys))
d, err := f.GetDescriptor(sif.WithPartitionType(sif.PartPrimSys))
if err != nil {
return fmt.Errorf("failed to get partition descriptor: %w", err)
}
Expand All @@ -112,7 +114,7 @@ func MountFUSE(ctx context.Context, path, mountPath string, opts ...MountFUSEOpt
}

switch fs {
case FsSquash:
case sif.FsSquash:
return mountSquashFS(ctx, d.Offset(), path, mountPath, mo)
default:
return errUnsupportedFSType
Expand Down
40 changes: 20 additions & 20 deletions pkg/sif/unmount.go → pkg/user/unmount.go
Expand Up @@ -3,7 +3,7 @@
// LICENSE file distributed with the sources of this project regarding your
// rights to use or distribute this software.

package sif
package user

import (
"context"
Expand All @@ -15,7 +15,7 @@ import (
)

// unmountSquashFS unmounts the filesystem at mountPath.
func unmountSquashFS(ctx context.Context, mountPath string, uo unmountFUSEOpts) error {
func unmountSquashFS(ctx context.Context, mountPath string, uo unmountOpts) error {
args := []string{
"-u",
filepath.Clean(mountPath),
Expand All @@ -31,37 +31,37 @@ func unmountSquashFS(ctx context.Context, mountPath string, uo unmountFUSEOpts)
return nil
}

// unmountFUSEOpts accumulates unmount options.
type unmountFUSEOpts struct {
// unmountOpts accumulates unmount options.
type unmountOpts struct {
stdout io.Writer
stderr io.Writer
fusermountPath string
}

// UnmountFUSEOpt are used to specify unmount options.
type UnmountFUSEOpt func(*unmountFUSEOpts) error
// UnmountOpt are used to specify unmount options.
type UnmountOpt func(*unmountOpts) error

// OptUnmountFUSEStdout writes standard output to w.
func OptUnmountFUSEStdout(w io.Writer) UnmountFUSEOpt {
return func(mo *unmountFUSEOpts) error {
// OptUnmountStdout writes standard output to w.
func OptUnmountStdout(w io.Writer) UnmountOpt {
return func(mo *unmountOpts) error {
mo.stdout = w
return nil
}
}

// OptUnmountFUSEStderr writes standard error to w.
func OptUnmountFUSEStderr(w io.Writer) UnmountFUSEOpt {
return func(mo *unmountFUSEOpts) error {
// OptUnmountStderr writes standard error to w.
func OptUnmountStderr(w io.Writer) UnmountOpt {
return func(mo *unmountOpts) error {
mo.stderr = w
return nil
}
}

var errFusermountPathInvalid = errors.New("fusermount path must be relative or absolute")

// OptUnmountFUSEFusermountPath sets the path to the fusermount binary.
func OptUnmountFUSEFusermountPath(path string) UnmountFUSEOpt {
return func(mo *unmountFUSEOpts) error {
// OptUnmountFusermountPath sets the path to the fusermount binary.
func OptUnmountFusermountPath(path string) UnmountOpt {
return func(mo *unmountOpts) error {
if filepath.Base(path) == path {
return errFusermountPathInvalid
}
Expand All @@ -70,16 +70,16 @@ func OptUnmountFUSEFusermountPath(path string) UnmountFUSEOpt {
}
}

// UnmountFUSE unmounts the FUSE mounted filesystem at mountPath.
// Unmount unmounts the filesystem at mountPath.
//
// UnmountFUSE may start one or more underlying processes. By default, stdout and stderr of these
// Unmount may start one or more underlying processes. By default, stdout and stderr of these
// processes is discarded. To modify this behavior, consider using OptUnmountStdout and/or
// OptUnmountStderr.
//
// By default, UnmountFUSE searches for a fusermount binary in the directories named by the PATH
// By default, Unmount searches for a fusermount binary in the directories named by the PATH
// environment variable. To override this behavior, consider using OptUnmountFusermountPath().
func UnmountFUSE(ctx context.Context, mountPath string, opts ...UnmountFUSEOpt) error {
uo := unmountFUSEOpts{
func Unmount(ctx context.Context, mountPath string, opts ...UnmountOpt) error {
uo := unmountOpts{
fusermountPath: "fusermount",
}

Expand Down
16 changes: 9 additions & 7 deletions pkg/sif/unmount_test.go → pkg/user/unmount_test.go
Expand Up @@ -3,7 +3,7 @@
// LICENSE file distributed with the sources of this project regarding your
// rights to use or distribute this software.

package sif
package user

import (
"bufio"
Expand All @@ -17,7 +17,9 @@ import (
"testing"
)

func Test_UnmountFUSE(t *testing.T) {
var corpus = filepath.Join("..", "..", "test", "images")

func Test_Unmount(t *testing.T) {
if _, err := exec.LookPath("squashfuse"); err != nil {
t.Skip(" not found, skipping mount tests")
}
Expand All @@ -38,7 +40,7 @@ func Test_UnmountFUSE(t *testing.T) {
name string
mountSIF string
mountPath string
opts []UnmountFUSEOpt
opts []UnmountOpt
wantErr bool
wantUnmounted bool
}{
Expand All @@ -65,28 +67,28 @@ func Test_UnmountFUSE(t *testing.T) {
name: "FusermountBare",
mountSIF: "",
mountPath: path,
opts: []UnmountFUSEOpt{OptUnmountFUSEFusermountPath("fusermount")},
opts: []UnmountOpt{OptUnmountFusermountPath("fusermount")},
wantErr: true,
},
{
name: "FusermountValid",
mountSIF: filepath.Join(corpus, "one-group.sif"),
mountPath: path,
opts: []UnmountFUSEOpt{OptUnmountFUSEFusermountPath(fusermountPath)},
opts: []UnmountOpt{OptUnmountFusermountPath(fusermountPath)},
wantErr: false,
wantUnmounted: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.mountSIF != "" {
err := MountFUSE(context.Background(), tt.mountSIF, path)
err := Mount(context.Background(), tt.mountSIF, path)
if err != nil {
t.Fatal(err)
}
}

err := UnmountFUSE(context.Background(), tt.mountPath, tt.opts...)
err := Unmount(context.Background(), tt.mountPath, tt.opts...)

if err != nil && !tt.wantErr {
t.Errorf("Unexpected error: %s", err)
Expand Down