github.com/10XDev/rclone@v1.52.3-0.20200626220027-16af9ab76b2a/cmd/mount/file.go (about) 1 // +build linux,go1.13 darwin,go1.13 freebsd,go1.13 2 3 package mount 4 5 import ( 6 "context" 7 "time" 8 9 "bazil.org/fuse" 10 fusefs "bazil.org/fuse/fs" 11 "github.com/rclone/rclone/cmd/mountlib" 12 "github.com/rclone/rclone/fs/log" 13 "github.com/rclone/rclone/vfs" 14 ) 15 16 // File represents a file 17 type File struct { 18 *vfs.File 19 } 20 21 // Check interface satisfied 22 var _ fusefs.Node = (*File)(nil) 23 24 // Attr fills out the attributes for the file 25 func (f *File) Attr(ctx context.Context, a *fuse.Attr) (err error) { 26 defer log.Trace(f, "")("a=%+v, err=%v", a, &err) 27 a.Valid = mountlib.AttrTimeout 28 modTime := f.File.ModTime() 29 Size := uint64(f.File.Size()) 30 Blocks := (Size + 511) / 512 31 a.Gid = f.VFS().Opt.GID 32 a.Uid = f.VFS().Opt.UID 33 a.Mode = f.VFS().Opt.FilePerms 34 a.Size = Size 35 a.Atime = modTime 36 a.Mtime = modTime 37 a.Ctime = modTime 38 a.Crtime = modTime 39 a.Blocks = Blocks 40 return nil 41 } 42 43 // Check interface satisfied 44 var _ fusefs.NodeSetattrer = (*File)(nil) 45 46 // Setattr handles attribute changes from FUSE. Currently supports ModTime and Size only 47 func (f *File) Setattr(ctx context.Context, req *fuse.SetattrRequest, resp *fuse.SetattrResponse) (err error) { 48 defer log.Trace(f, "a=%+v", req)("err=%v", &err) 49 if !f.VFS().Opt.NoModTime { 50 if req.Valid.Mtime() { 51 err = f.File.SetModTime(req.Mtime) 52 } else if req.Valid.MtimeNow() { 53 err = f.File.SetModTime(time.Now()) 54 } 55 } 56 if req.Valid.Size() { 57 err = f.File.Truncate(int64(req.Size)) 58 } 59 return translateError(err) 60 } 61 62 // Check interface satisfied 63 var _ fusefs.NodeOpener = (*File)(nil) 64 65 // Open the file for read or write 66 func (f *File) Open(ctx context.Context, req *fuse.OpenRequest, resp *fuse.OpenResponse) (fh fusefs.Handle, err error) { 67 defer log.Trace(f, "flags=%v", req.Flags)("fh=%v, err=%v", &fh, &err) 68 69 // fuse flags are based off syscall flags as are os flags, so 70 // should be compatible 71 handle, err := f.File.Open(int(req.Flags)) 72 if err != nil { 73 return nil, translateError(err) 74 } 75 76 // If size unknown then use direct io to read 77 if entry := handle.Node().DirEntry(); entry != nil && entry.Size() < 0 { 78 resp.Flags |= fuse.OpenDirectIO 79 } 80 81 return &FileHandle{handle}, nil 82 } 83 84 // Check interface satisfied 85 var _ fusefs.NodeFsyncer = (*File)(nil) 86 87 // Fsync the file 88 // 89 // Note that we don't do anything except return OK 90 func (f *File) Fsync(ctx context.Context, req *fuse.FsyncRequest) (err error) { 91 defer log.Trace(f, "")("err=%v", &err) 92 return nil 93 } 94 95 // Getxattr gets an extended attribute by the given name from the 96 // node. 97 // 98 // If there is no xattr by that name, returns fuse.ErrNoXattr. 99 func (f *File) Getxattr(ctx context.Context, req *fuse.GetxattrRequest, resp *fuse.GetxattrResponse) error { 100 return fuse.ENOSYS // we never implement this 101 } 102 103 var _ fusefs.NodeGetxattrer = (*File)(nil) 104 105 // Listxattr lists the extended attributes recorded for the node. 106 func (f *File) Listxattr(ctx context.Context, req *fuse.ListxattrRequest, resp *fuse.ListxattrResponse) error { 107 return fuse.ENOSYS // we never implement this 108 } 109 110 var _ fusefs.NodeListxattrer = (*File)(nil) 111 112 // Setxattr sets an extended attribute with the given name and 113 // value for the node. 114 func (f *File) Setxattr(ctx context.Context, req *fuse.SetxattrRequest) error { 115 return fuse.ENOSYS // we never implement this 116 } 117 118 var _ fusefs.NodeSetxattrer = (*File)(nil) 119 120 // Removexattr removes an extended attribute for the name. 121 // 122 // If there is no xattr by that name, returns fuse.ErrNoXattr. 123 func (f *File) Removexattr(ctx context.Context, req *fuse.RemovexattrRequest) error { 124 return fuse.ENOSYS // we never implement this 125 } 126 127 var _ fusefs.NodeRemovexattrer = (*File)(nil)