forked from TrueCloudLab/rclone
c1aaff220d
This is an OS style file system abstraction with directory caching used in mount, cmount, serve webdav and serve http.
111 lines
2.9 KiB
Go
111 lines
2.9 KiB
Go
// +build linux darwin freebsd
|
|
|
|
package mount
|
|
|
|
import (
|
|
"time"
|
|
|
|
"bazil.org/fuse"
|
|
fusefs "bazil.org/fuse/fs"
|
|
"github.com/ncw/rclone/fs"
|
|
"github.com/ncw/rclone/vfs"
|
|
"github.com/pkg/errors"
|
|
"golang.org/x/net/context"
|
|
)
|
|
|
|
// File represents a file
|
|
type File struct {
|
|
*vfs.File
|
|
}
|
|
|
|
// Check interface satisfied
|
|
var _ fusefs.Node = (*File)(nil)
|
|
|
|
// Attr fills out the attributes for the file
|
|
func (f *File) Attr(ctx context.Context, a *fuse.Attr) (err error) {
|
|
defer fs.Trace(f, "")("a=%+v, err=%v", a, &err)
|
|
modTime := f.File.ModTime()
|
|
Size := uint64(f.File.Size())
|
|
Blocks := (Size + 511) / 512
|
|
a.Gid = vfs.GID
|
|
a.Uid = vfs.UID
|
|
a.Mode = vfs.FilePerms
|
|
a.Size = Size
|
|
a.Atime = modTime
|
|
a.Mtime = modTime
|
|
a.Ctime = modTime
|
|
a.Crtime = modTime
|
|
a.Blocks = Blocks
|
|
return nil
|
|
}
|
|
|
|
// Check interface satisfied
|
|
var _ fusefs.NodeSetattrer = (*File)(nil)
|
|
|
|
// Setattr handles attribute changes from FUSE. Currently supports ModTime only.
|
|
func (f *File) Setattr(ctx context.Context, req *fuse.SetattrRequest, resp *fuse.SetattrResponse) (err error) {
|
|
defer fs.Trace(f, "a=%+v", req)("err=%v", &err)
|
|
if vfs.NoModTime {
|
|
return nil
|
|
}
|
|
if req.Valid.MtimeNow() {
|
|
err = f.File.SetModTime(time.Now())
|
|
} else if req.Valid.Mtime() {
|
|
err = f.File.SetModTime(req.Mtime)
|
|
}
|
|
return translateError(err)
|
|
}
|
|
|
|
// Check interface satisfied
|
|
var _ fusefs.NodeOpener = (*File)(nil)
|
|
|
|
// Open the file for read or write
|
|
func (f *File) Open(ctx context.Context, req *fuse.OpenRequest, resp *fuse.OpenResponse) (fh fusefs.Handle, err error) {
|
|
defer fs.Trace(f, "flags=%v", req.Flags)("fh=%v, err=%v", &fh, &err)
|
|
switch {
|
|
case req.Flags.IsReadOnly():
|
|
if vfs.NoSeek {
|
|
resp.Flags |= fuse.OpenNonSeekable
|
|
}
|
|
var rfh *vfs.ReadFileHandle
|
|
rfh, err = f.File.OpenRead()
|
|
fh = &ReadFileHandle{rfh}
|
|
case req.Flags.IsWriteOnly() || (req.Flags.IsReadWrite() && (req.Flags&fuse.OpenTruncate) != 0):
|
|
resp.Flags |= fuse.OpenNonSeekable
|
|
var wfh *vfs.WriteFileHandle
|
|
wfh, err = f.File.OpenWrite()
|
|
fh = &WriteFileHandle{wfh}
|
|
case req.Flags.IsReadWrite():
|
|
err = errors.New("can't open for read and write simultaneously")
|
|
default:
|
|
err = errors.Errorf("can't figure out how to open with flags %v", req.Flags)
|
|
}
|
|
|
|
/*
|
|
// File was opened in append-only mode, all writes will go to end
|
|
// of file. OS X does not provide this information.
|
|
OpenAppend OpenFlags = syscall.O_APPEND
|
|
OpenCreate OpenFlags = syscall.O_CREAT
|
|
OpenDirectory OpenFlags = syscall.O_DIRECTORY
|
|
OpenExclusive OpenFlags = syscall.O_EXCL
|
|
OpenNonblock OpenFlags = syscall.O_NONBLOCK
|
|
OpenSync OpenFlags = syscall.O_SYNC
|
|
OpenTruncate OpenFlags = syscall.O_TRUNC
|
|
*/
|
|
|
|
if err != nil {
|
|
return nil, translateError(err)
|
|
}
|
|
return fh, nil
|
|
}
|
|
|
|
// Check interface satisfied
|
|
var _ fusefs.NodeFsyncer = (*File)(nil)
|
|
|
|
// Fsync the file
|
|
//
|
|
// Note that we don't do anything except return OK
|
|
func (f *File) Fsync(ctx context.Context, req *fuse.FsyncRequest) (err error) {
|
|
defer fs.Trace(f, "")("err=%v", &err)
|
|
return nil
|
|
}
|