From cf2eb2d83bda5f0db3cc76f07d083bfcf039fc2a Mon Sep 17 00:00:00 2001 From: Filipe Azevedo Date: Wed, 14 Dec 2022 22:14:20 +0100 Subject: [PATCH] mount: introduce symlink support #2975 --- cmd/mount/dir.go | 28 ++++++++++++++++++++++++---- cmd/mount/file.go | 10 +++++++++- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/cmd/mount/dir.go b/cmd/mount/dir.go index 1252177b9..e32c9c941 100644 --- a/cmd/mount/dir.go +++ b/cmd/mount/dir.go @@ -7,6 +7,7 @@ import ( "fmt" "io" "os" + "path" "syscall" "time" @@ -33,7 +34,7 @@ func (d *Dir) Attr(ctx context.Context, a *fuse.Attr) (err error) { a.Valid = time.Duration(d.fsys.opt.AttrTimeout) a.Gid = d.VFS().Opt.GID a.Uid = d.VFS().Opt.UID - a.Mode = os.ModeDir | os.FileMode(d.VFS().Opt.DirPerms) + a.Mode = d.Mode() modTime := d.ModTime() a.Atime = modTime a.Mtime = modTime @@ -140,11 +141,13 @@ var _ fusefs.NodeCreater = (*Dir)(nil) // Create makes a new file func (d *Dir) Create(ctx context.Context, req *fuse.CreateRequest, resp *fuse.CreateResponse) (node fusefs.Node, handle fusefs.Handle, err error) { defer log.Trace(d, "name=%q", req.Name)("node=%v, handle=%v, err=%v", &node, &handle, &err) - file, err := d.Dir.Create(req.Name, int(req.Flags)) + // translate the fuse flags to os flags + osFlags := int(req.Flags) | os.O_CREATE + file, err := d.Dir.Create(req.Name, osFlags) if err != nil { return nil, nil, translateError(err) } - fh, err := file.Open(int(req.Flags) | os.O_CREATE) + fh, err := file.Open(osFlags) if err != nil { return nil, nil, translateError(err) } @@ -200,7 +203,6 @@ func (d *Dir) Rename(ctx context.Context, req *fuse.RenameRequest, newDir fusefs if !ok { return fmt.Errorf("unknown Dir type %T", newDir) } - err = d.Dir.Rename(req.OldName, req.NewName, destDir.Dir) if err != nil { return translateError(err) @@ -239,6 +241,24 @@ func (d *Dir) Link(ctx context.Context, req *fuse.LinkRequest, old fusefs.Node) return nil, syscall.ENOSYS } +var _ fusefs.NodeSymlinker = (*Dir)(nil) + +// Symlink create a symbolic link. +func (d *Dir) Symlink(ctx context.Context, req *fuse.SymlinkRequest) (node fusefs.Node, err error) { + defer log.Trace(d, "newname=%v, target=%v", req.NewName, req.Target)("node=%v, err=%v", &node, &err) + + newName := path.Join(d.Path(), req.NewName) + target := req.Target + + n, err := d.VFS().CreateSymlink(target, newName) + if err != nil { + return nil, err + } + + node = &File{n.(*vfs.File), d.fsys} + return node, nil +} + // Check interface satisfied var _ fusefs.NodeMknoder = (*Dir)(nil) diff --git a/cmd/mount/file.go b/cmd/mount/file.go index bc9883443..713ae3a9e 100644 --- a/cmd/mount/file.go +++ b/cmd/mount/file.go @@ -32,7 +32,7 @@ func (f *File) Attr(ctx context.Context, a *fuse.Attr) (err error) { Blocks := (Size + 511) / 512 a.Gid = f.VFS().Opt.GID a.Uid = f.VFS().Opt.UID - a.Mode = os.FileMode(f.VFS().Opt.FilePerms) + a.Mode = f.File.Mode() &^ os.ModeAppend a.Size = Size a.Atime = modTime a.Mtime = modTime @@ -129,3 +129,11 @@ func (f *File) Removexattr(ctx context.Context, req *fuse.RemovexattrRequest) er } var _ fusefs.NodeRemovexattrer = (*File)(nil) + +var _ fusefs.NodeReadlinker = (*File)(nil) + +// Readlink read symbolic link target. +func (f *File) Readlink(ctx context.Context, req *fuse.ReadlinkRequest) (ret string, err error) { + defer log.Trace(f, "")("ret=%v, err=%v", &ret, &err) + return f.VFS().Readlink(f.Path()) +}