mountlib: make Node satisfy os.FileInfo interface

This commit is contained in:
Nick Craig-Wood 2017-10-25 10:00:26 +01:00
parent 54950d3423
commit 750690503e
5 changed files with 93 additions and 28 deletions

View File

@ -203,11 +203,9 @@ func (fsys *FS) stat(node mountlib.Node, stat *fuse.Stat_t) (errc int) {
modTime = x.ModTime() modTime = x.ModTime()
Mode = mountlib.DirPerms | fuse.S_IFDIR Mode = mountlib.DirPerms | fuse.S_IFDIR
case *mountlib.File: case *mountlib.File:
var err error modTime = x.ModTime()
modTime, Size, Blocks, err = x.Attr(mountlib.NoModTime) Size = uint64(x.Size())
if err != nil { Blocks = (Size + 511) / 512
return translateError(err)
}
Mode = mountlib.FilePerms | fuse.S_IFREG Mode = mountlib.FilePerms | fuse.S_IFREG
} }
//stat.Dev = 1 //stat.Dev = 1
@ -392,10 +390,7 @@ func (fsys *FS) Truncate(path string, size int64, fh uint64) (errc int) {
return -fuse.EIO return -fuse.EIO
} }
// Read the size so far // Read the size so far
_, currentSize, _, err := file.Attr(true) currentSize := file.Size()
if err != nil {
return translateError(err)
}
fs.Debugf(path, "truncate to %d, currentSize %d", size, currentSize) fs.Debugf(path, "truncate to %d, currentSize %d", size, currentSize)
if int64(currentSize) != size { if int64(currentSize) != size {
fs.Errorf(path, "Can't truncate files") fs.Errorf(path, "Can't truncate files")

View File

@ -30,10 +30,9 @@ var _ fusefs.Node = (*File)(nil)
// Attr fills out the attributes for the file // Attr fills out the attributes for the file
func (f *File) Attr(ctx context.Context, a *fuse.Attr) (err error) { func (f *File) Attr(ctx context.Context, a *fuse.Attr) (err error) {
defer fs.Trace(f, "")("a=%+v, err=%v", a, &err) defer fs.Trace(f, "")("a=%+v, err=%v", a, &err)
modTime, Size, Blocks, err := f.File.Attr(mountlib.NoModTime) modTime := f.File.ModTime()
if err != nil { Size := uint64(f.File.Size())
return translateError(err) Blocks := (Size + 511) / 512
}
a.Gid = mountlib.GID a.Gid = mountlib.GID
a.Uid = mountlib.UID a.Uid = mountlib.UID
a.Mode = mountlib.FilePerms a.Mode = mountlib.FilePerms

View File

@ -1,6 +1,7 @@
package mountlib package mountlib
import ( import (
"os"
"path" "path"
"strings" "strings"
"sync" "sync"
@ -55,6 +56,30 @@ func (d *Dir) IsFile() bool {
return false 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 // Inode returns the inode number - satisfies Node interface
func (d *Dir) Inode() uint64 { func (d *Dir) Inode() uint64 {
return d.inode return d.inode
@ -242,6 +267,11 @@ func (d *Dir) ModTime() time.Time {
return d.modTime return d.modTime
} }
// Size of the directory
func (d *Dir) Size() int64 {
return 0
}
// SetModTime sets the modTime for this dir // SetModTime sets the modTime for this dir
func (d *Dir) SetModTime(modTime time.Time) error { func (d *Dir) SetModTime(modTime time.Time) error {
if d.fsys.readOnly { if d.fsys.readOnly {

View File

@ -1,6 +1,7 @@
package mountlib package mountlib
import ( import (
"os"
"path" "path"
"sync" "sync"
"sync/atomic" "sync/atomic"
@ -45,6 +46,26 @@ func (f *File) IsFile() bool {
return true 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 // Inode returns the inode number - satisfies Node interface
func (f *File) Inode() uint64 { func (f *File) Inode() uint64 {
return f.inode return f.inode
@ -70,25 +91,37 @@ func (f *File) addWriters(n int) {
f.mu.Unlock() f.mu.Unlock()
} }
// Attr fills out the attributes for the file // ModTime returns the modified time of the file
func (f *File) Attr(noModTime bool) (modTime time.Time, Size, Blocks uint64, err error) { //
// if NoModTime is set then it returns the mod time of the directory
func (f *File) ModTime() (modTime time.Time) {
f.mu.Lock() f.mu.Lock()
defer f.mu.Unlock() 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 { if !f.d.fsys.noModTime {
Size = uint64(atomic.LoadInt64(&f.size)) // if o is nil it isn't valid yet or there are writers, so return the size so far
if !noModTime && !f.pendingModTime.IsZero() { if f.o == nil || f.writers != 0 {
modTime = f.pendingModTime if !f.pendingModTime.IsZero() {
} return f.pendingModTime
} else { }
Size = uint64(f.o.Size()) } else {
if !noModTime { return f.o.ModTime()
modTime = f.o.ModTime()
} }
} }
Blocks = (Size + 511) / 512
// fs.Debugf(f.o, "File.Attr modTime=%v, Size=%d, Blocks=%v", modTime, Size, Blocks) return f.d.modTime
return }
// 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 // SetModTime sets the modtime for the file

View File

@ -2,6 +2,7 @@ package mountlib
import ( import (
"fmt" "fmt"
"os"
"strings" "strings"
"sync/atomic" "sync/atomic"
"time" "time"
@ -11,8 +12,11 @@ import (
// Node represents either a *Dir or a *File // Node represents either a *Dir or a *File
type Node interface { type Node interface {
os.FileInfo
IsFile() bool IsFile() bool
Inode() uint64 Inode() uint64
SetModTime(modTime time.Time) error
Fsync() error
} }
var ( var (
@ -40,6 +44,7 @@ type FS struct {
noSeek bool // don't allow seeking if set noSeek bool // don't allow seeking if set
noChecksum bool // don't check checksums if set noChecksum bool // don't check checksums if set
readOnly bool // if set FS is read only 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 dirCacheTime time.Duration // how long to consider directory listing cache valid
} }
@ -59,6 +64,9 @@ func NewFS(f fs.Fs) *FS {
if ReadOnly { if ReadOnly {
fsys.readOnly = true fsys.readOnly = true
} }
if NoModTime {
fsys.noModTime = true
}
fsys.dirCacheTime = DirCacheTime fsys.dirCacheTime = DirCacheTime
fsys.root = newDir(fsys, f, fsDir) fsys.root = newDir(fsys, f, fsDir)