github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/kbfs/libfuse/symlink.go (about) 1 // Copyright 2016 Keybase Inc. All rights reserved. 2 // Use of this source code is governed by a BSD 3 // license that can be found in the LICENSE file. 4 // 5 //go:build !windows 6 // +build !windows 7 8 package libfuse 9 10 import ( 11 "os" 12 "syscall" 13 14 "bazil.org/fuse" 15 "bazil.org/fuse/fs" 16 "github.com/keybase/client/go/kbfs/data" 17 "github.com/keybase/client/go/kbfs/idutil" 18 "github.com/keybase/client/go/kbfs/libkbfs" 19 "github.com/keybase/client/go/libkb" 20 "golang.org/x/net/context" 21 ) 22 23 // Symlink represents KBFS symlinks. 24 type Symlink struct { 25 // The directory this symlink is in. This should be safe to store 26 // here, without fear of Renames etc making it stale, because we 27 // never persist a Symlink into Folder.nodes; it has no 28 // libkbfs.Node, so that's impossible. This should make FUSE 29 // Lookup etc always get new nodes, limiting the lifetime of a 30 // single Symlink value. 31 parent *Dir 32 name string 33 inode uint64 34 } 35 36 var _ fs.Node = (*Symlink)(nil) 37 38 // Attr implements the fs.Node interface for Symlink 39 func (s *Symlink) Attr(ctx context.Context, a *fuse.Attr) (err error) { 40 s.parent.folder.fs.vlog.CLogf(ctx, libkb.VLog1, "Symlink Attr") 41 defer func() { err = s.parent.folder.processError(ctx, libkbfs.ReadMode, err) }() 42 43 _, de, err := s.parent.folder.fs.config.KBFSOps().Lookup( 44 ctx, s.parent.node, s.parent.node.ChildName(s.name)) 45 if err != nil { 46 if _, ok := err.(idutil.NoSuchNameError); ok { 47 return fuse.ESTALE 48 } 49 return err 50 } 51 52 err = s.parent.folder.fillAttrWithUIDAndWritePerm( 53 ctx, s.parent.node, &de, a) 54 if err != nil { 55 return err 56 } 57 a.Mode = os.ModeSymlink | a.Mode | 0500 58 a.Inode = s.inode 59 return nil 60 } 61 62 var _ fs.NodeReadlinker = (*Symlink)(nil) 63 64 // Readlink implements the fs.NodeReadlinker interface for Symlink 65 func (s *Symlink) Readlink(ctx context.Context, req *fuse.ReadlinkRequest) (link string, err error) { 66 s.parent.folder.fs.vlog.CLogf(ctx, libkb.VLog1, "Symlink Readlink") 67 defer func() { err = s.parent.folder.processError(ctx, libkbfs.ReadMode, err) }() 68 69 _, de, err := s.parent.folder.fs.config.KBFSOps().Lookup( 70 ctx, s.parent.node, s.parent.node.ChildName(s.name)) 71 if err != nil { 72 return "", err 73 } 74 75 if de.Type != data.Sym { 76 return "", fuse.Errno(syscall.EINVAL) 77 } 78 return de.SymPath, nil 79 }