From 750690503eec706f2a2eea2c7d6623fcb1233f0c Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Wed, 25 Oct 2017 10:00:26 +0100 Subject: [PATCH] mountlib: make Node satisfy os.FileInfo interface --- cmd/cmount/fs.go | 13 +++------ cmd/mount/file.go | 7 +++-- cmd/mountlib/dir.go | 30 +++++++++++++++++++++ cmd/mountlib/file.go | 63 +++++++++++++++++++++++++++++++++----------- cmd/mountlib/fs.go | 8 ++++++ 5 files changed, 93 insertions(+), 28 deletions(-) diff --git a/cmd/cmount/fs.go b/cmd/cmount/fs.go index f776ef6a2..1273679f7 100644 --- a/cmd/cmount/fs.go +++ b/cmd/cmount/fs.go @@ -203,11 +203,9 @@ func (fsys *FS) stat(node mountlib.Node, stat *fuse.Stat_t) (errc int) { modTime = x.ModTime() Mode = mountlib.DirPerms | fuse.S_IFDIR case *mountlib.File: - var err error - modTime, Size, Blocks, err = x.Attr(mountlib.NoModTime) - if err != nil { - return translateError(err) - } + modTime = x.ModTime() + Size = uint64(x.Size()) + Blocks = (Size + 511) / 512 Mode = mountlib.FilePerms | fuse.S_IFREG } //stat.Dev = 1 @@ -392,10 +390,7 @@ func (fsys *FS) Truncate(path string, size int64, fh uint64) (errc int) { return -fuse.EIO } // Read the size so far - _, currentSize, _, err := file.Attr(true) - if err != nil { - return translateError(err) - } + currentSize := file.Size() fs.Debugf(path, "truncate to %d, currentSize %d", size, currentSize) if int64(currentSize) != size { fs.Errorf(path, "Can't truncate files") diff --git a/cmd/mount/file.go b/cmd/mount/file.go index f185dd1cc..5ae48d283 100644 --- a/cmd/mount/file.go +++ b/cmd/mount/file.go @@ -30,10 +30,9 @@ 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, Size, Blocks, err := f.File.Attr(mountlib.NoModTime) - if err != nil { - return translateError(err) - } + modTime := f.File.ModTime() + Size := uint64(f.File.Size()) + Blocks := (Size + 511) / 512 a.Gid = mountlib.GID a.Uid = mountlib.UID a.Mode = mountlib.FilePerms diff --git a/cmd/mountlib/dir.go b/cmd/mountlib/dir.go index d10520c01..2e99f1ba0 100644 --- a/cmd/mountlib/dir.go +++ b/cmd/mountlib/dir.go @@ -1,6 +1,7 @@ package mountlib import ( + "os" "path" "strings" "sync" @@ -55,6 +56,30 @@ func (d *Dir) IsFile() bool { return false } +// IsDir returns true for Dir - satisfies Node interface +func (d *Dir) IsDir() bool { + return true +} + +// Mode bits of the directory - satisfies Node interface +func (d *Dir) Mode() (mode os.FileMode) { + return os.ModeDir | 0777 +} + +// Name (base) of the directory - satisfies Node interface +func (d *Dir) Name() (name string) { + name = path.Base(d.path) + if name == "." { + name = "/" + } + return name +} + +// Sys returns underlying data source (can be nil) - satisfies Node interface +func (d *Dir) Sys() interface{} { + return nil +} + // Inode returns the inode number - satisfies Node interface func (d *Dir) Inode() uint64 { return d.inode @@ -242,6 +267,11 @@ func (d *Dir) ModTime() time.Time { return d.modTime } +// Size of the directory +func (d *Dir) Size() int64 { + return 0 +} + // SetModTime sets the modTime for this dir func (d *Dir) SetModTime(modTime time.Time) error { if d.fsys.readOnly { diff --git a/cmd/mountlib/file.go b/cmd/mountlib/file.go index 9881e4d77..a01282812 100644 --- a/cmd/mountlib/file.go +++ b/cmd/mountlib/file.go @@ -1,6 +1,7 @@ package mountlib import ( + "os" "path" "sync" "sync/atomic" @@ -45,6 +46,26 @@ func (f *File) IsFile() bool { return true } +// IsDir returns false for File - satisfies Node interface +func (f *File) IsDir() bool { + return false +} + +// Mode bits of the file or directory - satisfies Node interface +func (f *File) Mode() (mode os.FileMode) { + return 0666 +} + +// Name (base) of the directory - satisfies Node interface +func (f *File) Name() (name string) { + return path.Base(f.o.Remote()) +} + +// Sys returns underlying data source (can be nil) - satisfies Node interface +func (f *File) Sys() interface{} { + return nil +} + // Inode returns the inode number - satisfies Node interface func (f *File) Inode() uint64 { return f.inode @@ -70,25 +91,37 @@ func (f *File) addWriters(n int) { f.mu.Unlock() } -// Attr fills out the attributes for the file -func (f *File) Attr(noModTime bool) (modTime time.Time, Size, Blocks uint64, err error) { +// ModTime returns the modified time of the file +// +// if NoModTime is set then it returns the mod time of the directory +func (f *File) ModTime() (modTime time.Time) { f.mu.Lock() defer f.mu.Unlock() - // if o is nil it isn't valid yet or there are writers, so return the size so far - if f.o == nil || f.writers != 0 { - Size = uint64(atomic.LoadInt64(&f.size)) - if !noModTime && !f.pendingModTime.IsZero() { - modTime = f.pendingModTime - } - } else { - Size = uint64(f.o.Size()) - if !noModTime { - modTime = f.o.ModTime() + + if !f.d.fsys.noModTime { + // if o is nil it isn't valid yet or there are writers, so return the size so far + if f.o == nil || f.writers != 0 { + if !f.pendingModTime.IsZero() { + return f.pendingModTime + } + } else { + return f.o.ModTime() } } - Blocks = (Size + 511) / 512 - // fs.Debugf(f.o, "File.Attr modTime=%v, Size=%d, Blocks=%v", modTime, Size, Blocks) - return + + return f.d.modTime +} + +// Size of the file +func (f *File) Size() int64 { + f.mu.Lock() + defer f.mu.Unlock() + + // if o is nil it isn't valid yet or there are writers, so return the size so far + if f.o == nil || f.writers != 0 { + return atomic.LoadInt64(&f.size) + } + return f.o.Size() } // SetModTime sets the modtime for the file diff --git a/cmd/mountlib/fs.go b/cmd/mountlib/fs.go index d41e77232..e00a691f6 100644 --- a/cmd/mountlib/fs.go +++ b/cmd/mountlib/fs.go @@ -2,6 +2,7 @@ package mountlib import ( "fmt" + "os" "strings" "sync/atomic" "time" @@ -11,8 +12,11 @@ import ( // Node represents either a *Dir or a *File type Node interface { + os.FileInfo IsFile() bool Inode() uint64 + SetModTime(modTime time.Time) error + Fsync() error } var ( @@ -40,6 +44,7 @@ type FS struct { noSeek bool // don't allow seeking if set noChecksum bool // don't check checksums if set readOnly bool // if set FS is read only + noModTime bool // don't read mod times for files dirCacheTime time.Duration // how long to consider directory listing cache valid } @@ -59,6 +64,9 @@ func NewFS(f fs.Fs) *FS { if ReadOnly { fsys.readOnly = true } + if NoModTime { + fsys.noModTime = true + } fsys.dirCacheTime = DirCacheTime fsys.root = newDir(fsys, f, fsDir)