shithub: mntgen

Download patch

ref: 1833a59599bf67892606916c56da3503be0a1c0a
author: Alex Musolino <alex@musolino.id.au>
date: Thu Dec 29 17:37:11 EST 2022

initial commit

--- /dev/null
+++ b/go.mod
@@ -1,0 +1,8 @@
+module musolino.id.au/mntgen
+
+go 1.19
+
+require (
+	bazil.org/fuse v0.0.0-20221210232012-5a1c75a4f691 // indirect
+	golang.org/x/sys v0.0.0-20191210023423-ac6580df4449 // indirect
+)
--- /dev/null
+++ b/go.sum
@@ -1,0 +1,4 @@
+bazil.org/fuse v0.0.0-20221210232012-5a1c75a4f691 h1:dxU4G/I97qxiXCYzKo9IJBrYUNDjBODU6cTpXMlPb7Y=
+bazil.org/fuse v0.0.0-20221210232012-5a1c75a4f691/go.mod h1:eX+feLR06AMFrTGQBzFnMMDz1vjBv2yHZBFlI9RJeaQ=
+golang.org/x/sys v0.0.0-20191210023423-ac6580df4449 h1:gSbV7h1NRL2G1xTg/owz62CST1oJBmxy4QpMMregXVQ=
+golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
--- /dev/null
+++ b/mntgen.go
@@ -1,0 +1,125 @@
+package main
+
+import (
+	"bazil.org/fuse"
+	"bazil.org/fuse/fs"
+	"context"
+	"flag"
+	"fmt"
+	"log"
+	"os"
+	"os/signal"
+	"sync/atomic"
+	"syscall"
+	"time"
+)
+
+var inodeCount uint64
+
+type Node interface {
+	fs.Node
+	GetDirentType() fuse.DirentType
+}
+
+type Dir struct {
+	Fs *FS
+	Name string
+	Attributes fuse.Attr
+	Entries    map[string]*Dir
+}
+
+func NewDir(fs *FS, name string) *Dir {
+	atomic.AddUint64(&inodeCount, 1)
+	return &Dir{
+		Fs: fs,
+		Name: name,
+		Attributes: fuse.Attr{
+			Inode: inodeCount,
+			Atime: time.Now(),
+			Mtime: time.Now(),
+			Ctime: time.Now(),
+			Mode:  os.ModeDir | 0o755,
+		},
+		Entries: make(map[string]*Dir),
+	}
+}
+
+func (d *Dir) Attr(ctx context.Context, a *fuse.Attr) error {
+	*a = d.Attributes
+	return nil
+}
+
+func (d *Dir) Lookup(ctx context.Context, name string) (fs.Node, error) {
+	if d == d.Fs.RootDir {
+		if node, ok := d.Entries[name]; ok {
+			return node, nil
+		} else {
+			nd := NewDir(d.Fs, name)
+			d.Entries[name] = nd
+			return nd, nil
+		}
+	}
+	return nil, syscall.ENOENT
+}
+
+func (d *Dir) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
+	var entries []fuse.Dirent
+	for k, v := range d.Entries {
+		var a fuse.Attr
+		v.Attr(ctx, &a)
+		entries = append(entries, fuse.Dirent{
+			Inode: a.Inode,
+			Type:  fuse.DT_Dir,
+			Name:  k,
+		})
+	}
+	return entries, nil
+}
+
+type FS struct {
+	RootDir *Dir
+}
+
+func NewFS() *FS {
+	fs := &FS{}
+	fs.RootDir = NewDir(fs, "")
+	return fs
+}
+
+func (fs FS) Root() (fs.Node, error) {
+	return fs.RootDir, nil
+}
+
+func main() {
+	flag.Usage = func () {
+		fmt.Fprintf(os.Stderr, "usage: %s [ mnt ]\n", os.Args[0])
+		os.Exit(1)
+	}
+	flag.Parse()
+	if flag.NArg() >= 2 {
+		flag.Usage()
+	}
+	mtpt := "/n"
+	if flag.NArg() == 1 {
+		mtpt = flag.Arg(0)
+	}
+	c, err := fuse.Mount(mtpt, fuse.FSName("mntgen"), fuse.Subtype("mntgen"))
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer c.Close()
+	sigc := make(chan os.Signal, 1)
+	signal.Notify(sigc, syscall.SIGTERM, syscall.SIGINT)
+	go func() {
+		for {
+			<-sigc
+			if err := fuse.Unmount(mtpt); err != nil {
+				log.Print("unmount failed: ", err)
+			}
+		}
+	}()
+	err = fs.Serve(c, NewFS())
+	if err != nil {
+		log.Fatal(err)
+	}
+}