From f2d86aff965491ff1060ea998ded3bda04e043bf Mon Sep 17 00:00:00 2001 From: Caleb Gardner Date: Wed, 4 Jan 2023 05:41:43 -0600 Subject: [PATCH] Fixed a race condition with mounts that caused them to fail --- fuse.go | 32 +++++++++++++++++++++++++++----- reader.go | 2 ++ squashfs_test.go | 6 +++--- 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/fuse.go b/fuse.go index a18d9e5..81e572d 100644 --- a/fuse.go +++ b/fuse.go @@ -3,6 +3,7 @@ package squashfs import ( "bytes" "context" + "errors" "io" "github.com/CalebQ42/fuse" @@ -10,17 +11,38 @@ import ( "github.com/CalebQ42/squashfs/internal/inode" ) -// Creates a fuse mount, then mounts the archive on a seperate goroutine. -// If waiting for the mount to end, simply do <-con.Ready. -func (r *Reader) Mount(mountpoint string) (con *fuse.Conn, err error) { - con, err = fuse.Mount(mountpoint, fuse.ReadOnly()) +// Mounts the archive to the given mountpoint using fuse3. +// Blocks until the arhive is unmounted. +// Hightly suggested to run in a goroutine. +// Will take a moment before MountWait and Unmount will work correctly. +func (r *Reader) Mount(mountpoint string) (err error) { + if r.con != nil { + return errors.New("squashfs archive already mounted") + } + r.con, err = fuse.Mount(mountpoint, fuse.ReadOnly()) if err != nil { return } - go fs.Serve(con, &squashFuse{r: r}) + err = fs.Serve(r.con, &squashFuse{r: r}) return } +// Blocks until the mount ends. +func (r *Reader) MountWait() { + if r.con != nil { + <-r.con.Ready + } +} + +// Unmounts the archive. +func (r *Reader) Unmount() error { + if r.con != nil { + defer func() { r.con = nil }() + return r.con.Close() + } + return errors.New("squashfs archive is not mounted") +} + type squashFuse struct { r *Reader } diff --git a/reader.go b/reader.go index b2547fa..d702766 100644 --- a/reader.go +++ b/reader.go @@ -7,6 +7,7 @@ import ( "math" "time" + "github.com/CalebQ42/fuse" "github.com/CalebQ42/squashfs/internal/decompress" "github.com/CalebQ42/squashfs/internal/directory" "github.com/CalebQ42/squashfs/internal/inode" @@ -16,6 +17,7 @@ import ( type Reader struct { *FS + con *fuse.Conn d decompress.Decompressor r io.ReaderAt fragEntries []fragEntry diff --git a/squashfs_test.go b/squashfs_test.go index a341c1a..054543c 100644 --- a/squashfs_test.go +++ b/squashfs_test.go @@ -196,11 +196,11 @@ func TestFuse(t *testing.T) { if err != nil { t.Fatal(err) } - con, err := rdr.Mount("testing/fuseTest") + err = rdr.Mount("testing/fuseTest") if err != nil { t.Fatal(err) } - defer con.Close() - <-con.Ready + defer rdr.Unmount() + rdr.MountWait() t.Fatal("testing") }