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