Closed prasad83 closed 4 months ago
main.go
package main
import (
"context"
"fmt"
"os"
"os/exec"
"os/signal"
"syscall"
"time"
"bazil.org/fuse"
"bazil.org/fuse/fs"
)
type EntryGetter interface {
GetDirentType() fuse.DirentType
}
type myFS struct {
}
func (mfs *myFS) Root() (fs.Node, error) {
return newDir()
}
type myNode struct {
Type fuse.DirentType
Attrs fuse.Attr
}
func (n *myNode) GetDirentType() fuse.DirentType {
return n.Type
}
func (n *myNode) Attr(ctx context.Context, a *fuse.Attr) error {
*a = n.Attrs
return nil
}
type myDir struct {
myNode
Entries map[string]interface{}
}
func (d *myDir) Lookup(ctx context.Context, name string) (fs.Node, error) {
if node, ok := d.Entries[name]; ok {
return node.(fs.Node), nil
}
return nil, syscall.ENOENT
}
func (d *myDir) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
var entries []fuse.Dirent
for k, v := range d.Entries {
var a fuse.Attr
v.(fs.Node).Attr(ctx, &a)
entries = append(entries, fuse.Dirent{
Name: k,
Inode: a.Inode,
Type: v.(EntryGetter).GetDirentType(),
})
}
return entries, nil
}
type myFile struct {
myNode
content []byte
}
func (f *myFile) ReadAll(ctx context.Context) ([]byte, error) {
return f.content, nil
}
func newFS() fs.FS {
return &myFS{}
}
func newDir() (fs.Node, error) {
filenames := []string{
"ABC",
"ABC/def",
}
dir := &myDir{
myNode: myNode{
Type: fuse.DT_Dir,
Attrs: fuse.Attr{
Inode: 1,
Atime: time.Now(),
Mtime: time.Now(),
Ctime: time.Now(),
Mode: os.ModeDir | 0o777,
},
},
Entries: make(map[string]interface{}),
}
for findex, fname := range filenames {
fcontent := []byte(fname)
dir.Entries[fname] = &myFile{
myNode: myNode{
Type: fuse.DT_File,
Attrs: fuse.Attr{
Inode: uint64(findex + 1),
Mode: 0o644,
Size: uint64(len(fcontent)),
Atime: time.Now(),
Mtime: time.Now(),
Ctime: time.Now(),
},
},
content: fcontent,
}
}
return dir, nil
}
func main() {
mountpoint := "/mnt"
c, err := fuse.Mount(mountpoint, fuse.FSName("myfs"), fuse.Subtype("myfs"))
if err != nil {
panic(err)
}
defer c.Close()
sigc := make(chan os.Signal, 1)
signal.Notify(sigc, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
go func() {
switch <-sigc {
case syscall.SIGHUP:
println("signal: hangup")
case syscall.SIGINT:
println("signal: interrupt")
case syscall.SIGTERM:
println("signal: terminate")
case syscall.SIGQUIT:
println("signal: quit")
}
// unmount safely
if err := exec.Command("fusermount3", "-u", mountpoint).Run(); err != nil {
println("error: could not unmount, use [sudo fusermount -u " + mountpoint + "]")
}
os.Exit(0)
}()
fmt.Println("filesystem mounted at " + mountpoint + ", use CRTL+C to stop")
server := fs.New(c, &fs.Config{
Debug: func(msg interface{}) {
fmt.Printf("[DEBUG] %v\n", msg)
},
})
if err := server.Serve(newFS()); err != nil {
panic(err)
}
}
go build main.go
sudo ./main
ls /mnt
ls: reading directory '/mnt': Input/output error
ABC
ABC/def is not listed.
Linux/UNIX directory entry names cannot contain slashes. I do not expect the IO errors to be "random", at all, but very consistent.
What are you trying to do here?
This seems to be a misunderstanding of UNIX filesystems, with nothing actionable here.
When Directory has filename with "/" - results of
ls
randomly shows input/output error.