-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* cmd/p9: Begin working on FUSE-based 9P mounting. * cmd/p9: Get basic, read-only mount working. * p9: Clunk intermediary FIDs created by Remote.Stat(). * cmd/p9: Cleaner Node and Handle stuff and handle closing.
- Loading branch information
1 parent
655eb25
commit 5eb85dc
Showing
4 changed files
with
213 additions
and
18 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,178 @@ | ||
package main | ||
|
||
import ( | ||
"context" | ||
"flag" | ||
"fmt" | ||
"path" | ||
|
||
"bazil.org/fuse" | ||
"bazil.org/fuse/fs" | ||
"github.com/DeedleFake/p9" | ||
"github.com/DeedleFake/p9/internal/util" | ||
) | ||
|
||
type mountCmd struct { | ||
} | ||
|
||
func (cmd *mountCmd) Name() string { | ||
return "mount" | ||
} | ||
|
||
func (cmd *mountCmd) Desc() string { | ||
return "Mount a 9P filesystem." | ||
} | ||
|
||
func (cmd *mountCmd) Run(options GlobalOptions, args []string) error { | ||
fset := flag.NewFlagSet(cmd.Name(), flag.ExitOnError) | ||
fset.Usage = func() { | ||
fmt.Fprintf(fset.Output(), "%v mounts a 9P filesystem.\n", cmd.Name()) | ||
fmt.Fprintf(fset.Output(), "\n") | ||
fmt.Fprintf(fset.Output(), "Usage: %v <mount point>\n", cmd.Name()) | ||
fset.PrintDefaults() | ||
} | ||
err := fset.Parse(args[1:]) | ||
if err != nil { | ||
return util.Errorf("parse flags: %w", err) | ||
} | ||
|
||
args = fset.Args() | ||
if len(args) != 1 { | ||
return flag.ErrHelp | ||
} | ||
|
||
return attach(options, func(a *p9.Remote) error { | ||
c, err := fuse.Mount( | ||
args[0], | ||
fuse.FSName("9p!"+options.Address), | ||
fuse.Subtype("9p"), | ||
fuse.VolumeName("9p!"+options.Address), | ||
) | ||
if err != nil { | ||
return util.Errorf("mount: %w", err) | ||
} | ||
defer c.Close() | ||
|
||
err = fs.Serve(c, &fuseFS{root: a}) | ||
if err != nil { | ||
return util.Errorf("serve: %w", err) | ||
} | ||
|
||
<-c.Ready | ||
if err := c.MountError; err != nil { | ||
return util.Errorf("ready: %w", err) | ||
} | ||
|
||
return nil | ||
}) | ||
} | ||
|
||
type fuseFS struct { | ||
root *p9.Remote | ||
} | ||
|
||
func (fs *fuseFS) Root() (fs.Node, error) { | ||
return &fuseNode{n: fs.root}, nil | ||
} | ||
|
||
type fuseNode struct { | ||
n *p9.Remote | ||
p string | ||
} | ||
|
||
func (node *fuseNode) flags(f fuse.OpenFlags) (flags uint8) { | ||
switch { | ||
case f.IsReadOnly(): | ||
flags = p9.OREAD | ||
case f.IsWriteOnly(): | ||
flags = p9.OWRITE | ||
case f.IsReadWrite(): | ||
flags = p9.ORDWR | ||
} | ||
if f&fuse.OpenTruncate != 0 { | ||
flags |= p9.OTRUNC | ||
} | ||
|
||
return flags | ||
} | ||
|
||
func (node *fuseNode) Attr(ctx context.Context, attr *fuse.Attr) error { | ||
s, err := node.n.Stat(node.p) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
attr.Inode = s.Path | ||
attr.Size = s.Length | ||
attr.Blocks = s.Length / 512 | ||
attr.Atime = s.ATime | ||
attr.Mtime = s.MTime | ||
attr.Mode = s.FileMode.OS() | ||
|
||
return nil | ||
} | ||
|
||
func (node *fuseNode) Lookup(ctx context.Context, name string) (fs.Node, error) { | ||
p := path.Join(node.p, name) | ||
_, err := node.n.Stat(p) | ||
if err != nil { | ||
return nil, fuse.ENOENT | ||
} | ||
|
||
return &fuseNode{node.n, p}, nil | ||
} | ||
|
||
func (node *fuseNode) Open(ctx context.Context, req *fuse.OpenRequest, rsp *fuse.OpenResponse) (fs.Handle, error) { | ||
n, err := node.n.Open(node.p, node.flags(req.Flags)) | ||
return &fuseNode{n: n}, err | ||
} | ||
|
||
func (node *fuseNode) direntType(m p9.FileMode) fuse.DirentType { | ||
switch { | ||
case m&p9.ModeDir != 0: | ||
return fuse.DT_Dir | ||
case m&p9.ModeSymlink != 0: | ||
return fuse.DT_Link | ||
case m&p9.ModeSocket != 0: | ||
return fuse.DT_Socket | ||
default: | ||
return fuse.DT_Unknown | ||
} | ||
} | ||
|
||
func (node *fuseNode) Read(ctx context.Context, req *fuse.ReadRequest, rsp *fuse.ReadResponse) error { | ||
if req.Dir { | ||
return fmt.Errorf("%#v", req) | ||
} | ||
|
||
buf := make([]byte, req.Size) | ||
n, err := node.n.ReadAt(buf, req.Offset) | ||
rsp.Data = buf[:n] | ||
return err | ||
} | ||
|
||
func (node *fuseNode) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) { | ||
e, err := node.n.Readdir() | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
r := make([]fuse.Dirent, len(e)) | ||
for i := range e { | ||
r[i] = fuse.Dirent{ | ||
Inode: e[i].Path, | ||
Type: node.direntType(e[i].FileMode), | ||
Name: e[i].EntryName, | ||
} | ||
} | ||
|
||
return r, nil | ||
} | ||
|
||
func (node *fuseNode) Release(ctx context.Context, req *fuse.ReleaseRequest) error { | ||
return node.n.Close() | ||
} | ||
|
||
func init() { | ||
RegisterCommand(&mountCmd{}) | ||
} |
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 |
---|---|---|
@@ -1,3 +1,8 @@ | ||
module github.com/DeedleFake/p9 | ||
|
||
go 1.13 | ||
|
||
require ( | ||
bazil.org/fuse v0.0.0-20180421153158-65cc252bf669 | ||
golang.org/x/net v0.0.0-20191014212845-da9a3fd4c582 // indirect | ||
) |
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,8 @@ | ||
bazil.org/fuse v0.0.0-20180421153158-65cc252bf669 h1:FNCRpXiquG1aoyqcIWVFmpTSKVcx2bQD38uZZeGtdlw= | ||
bazil.org/fuse v0.0.0-20180421153158-65cc252bf669/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= | ||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | ||
golang.org/x/net v0.0.0-20191014212845-da9a3fd4c582 h1:p9xBe/w/OzkeYVKm234g55gMdD1nSIooTir5kV11kfA= | ||
golang.org/x/net v0.0.0-20191014212845-da9a3fd4c582/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | ||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= | ||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= |
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