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()
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")

View File

@ -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

View File

@ -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 {

View File

@ -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 !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 {
Size = uint64(atomic.LoadInt64(&f.size))
if !noModTime && !f.pendingModTime.IsZero() {
modTime = f.pendingModTime
if !f.pendingModTime.IsZero() {
return f.pendingModTime
}
} else {
Size = uint64(f.o.Size())
if !noModTime {
modTime = f.o.ModTime()
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

View File

@ -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)