vfs: add Path method to Node and use it to stop reading nil DirEntry

All DirEntry calls now have been checked for nil or converted to use Path.
This commit is contained in:
Nick Craig-Wood 2017-11-18 11:47:21 +00:00
parent 7c3584f4e6
commit c560017934
8 changed files with 46 additions and 38 deletions

View file

@ -245,8 +245,7 @@ func (fsys *FS) Readdir(dirPath string,
for _, item := range items { for _, item := range items {
node, ok := item.(vfs.Node) node, ok := item.(vfs.Node)
if ok { if ok {
name := path.Base(node.DirEntry().Remote()) fill(node.Name(), nil, 0)
fill(name, nil, 0)
} }
} }
itemsRead = len(items) itemsRead = len(items)

View file

@ -4,7 +4,6 @@ package mount
import ( import (
"os" "os"
"path"
"time" "time"
"bazil.org/fuse" "bazil.org/fuse"
@ -93,23 +92,14 @@ func (d *Dir) ReadDirAll(ctx context.Context) (dirents []fuse.Dirent, err error)
if err != nil { if err != nil {
return nil, translateError(err) return nil, translateError(err)
} }
for _, item := range items { for _, node := range items {
var dirent fuse.Dirent var dirent = fuse.Dirent{
switch x := item.DirEntry().(type) {
case fs.Object:
dirent = fuse.Dirent{
// Inode FIXME ??? // Inode FIXME ???
Type: fuse.DT_File, Type: fuse.DT_File,
Name: path.Base(x.Remote()), Name: node.Name(),
} }
case fs.Directory: if node.IsDir() {
dirent = fuse.Dirent{ dirent.Type = fuse.DT_Dir
// Inode FIXME ???
Type: fuse.DT_Dir,
Name: path.Base(x.Remote()),
}
default:
return nil, errors.Errorf("unknown type %T", item)
} }
dirents = append(dirents, dirent) dirents = append(dirents, dirent)
} }

View file

@ -171,9 +171,8 @@ func (s *server) serveDir(w http.ResponseWriter, r *http.Request, dirRemote stri
var out entries var out entries
for _, node := range dirEntries { for _, node := range dirEntries {
obj := node.DirEntry() remote := node.Path()
remote := strings.Trim(obj.Remote(), "/") leaf := node.Name()
leaf := path.Base(remote)
urlRemote := leaf urlRemote := leaf
if node.IsDir() { if node.IsDir() {
leaf += "/" leaf += "/"
@ -212,7 +211,12 @@ func (s *server) serveFile(w http.ResponseWriter, r *http.Request, remote string
http.Error(w, "Not a file", http.StatusNotFound) http.Error(w, "Not a file", http.StatusNotFound)
return return
} }
obj := node.DirEntry().(fs.Object) entry := node.DirEntry()
if entry == nil {
http.Error(w, "Can't open file being written", http.StatusNotFound)
return
}
obj := entry.(fs.Object)
file := node.(*vfs.File) file := node.(*vfs.File)
// Set content length since we know how long the object is // Set content length since we know how long the object is

View file

@ -70,6 +70,11 @@ func (d *Dir) Name() (name string) {
return name return name
} }
// Path of the directory - satisfies Node interface
func (d *Dir) Path() (name string) {
return d.path
}
// Sys returns underlying data source (can be nil) - satisfies Node interface // Sys returns underlying data source (can be nil) - satisfies Node interface
func (d *Dir) Sys() interface{} { func (d *Dir) Sys() interface{} {
return nil return nil
@ -325,7 +330,7 @@ func (d *Dir) Create(name string) (*File, error) {
if d.vfs.Opt.ReadOnly { if d.vfs.Opt.ReadOnly {
return nil, EROFS return nil, EROFS
} }
// This gets added to the directory when the file is written // This gets added to the directory when the file is opened for write
return newFile(d, nil, name), nil return newFile(d, nil, name), nil
} }
@ -390,7 +395,7 @@ func (d *Dir) RemoveAll() error {
for _, node := range nodes { for _, node := range nodes {
err = node.RemoveAll() err = node.RemoveAll()
if err != nil { if err != nil {
fs.Errorf(node.DirEntry(), "Dir.RemoveAll failed to remove: %v", err) fs.Errorf(node.Path(), "Dir.RemoveAll failed to remove: %v", err)
return err return err
} }
} }
@ -432,6 +437,9 @@ func (d *Dir) Rename(oldName, newName string, destDir *Dir) error {
return err return err
} }
switch x := oldNode.DirEntry().(type) { switch x := oldNode.DirEntry().(type) {
case nil:
fs.Errorf(oldPath, "Dir.Rename cant rename open file")
return EPERM
case fs.Object: case fs.Object:
oldObject := x oldObject := x
// FIXME: could Copy then Delete if Move not available // FIXME: could Copy then Delete if Move not available
@ -450,7 +458,7 @@ func (d *Dir) Rename(oldName, newName string, destDir *Dir) error {
// Update the node with the new details // Update the node with the new details
if oldNode != nil { if oldNode != nil {
if oldFile, ok := oldNode.(*File); ok { if oldFile, ok := oldNode.(*File); ok {
fs.Debugf(oldNode.DirEntry(), "Updating file with %v %p", newObject, oldFile) fs.Debugf(x, "Updating file with %v %p", newObject, oldFile)
oldFile.rename(destDir, newObject) oldFile.rename(destDir, newObject)
} }
} }
@ -472,7 +480,7 @@ func (d *Dir) Rename(oldName, newName string, destDir *Dir) error {
// Update the node with the new details // Update the node with the new details
if oldNode != nil { if oldNode != nil {
if oldDir, ok := oldNode.(*Dir); ok { if oldDir, ok := oldNode.(*Dir); ok {
fs.Debugf(oldNode.DirEntry(), "Updating dir with %v %p", newDir, oldDir) fs.Debugf(x, "Updating dir with %v %p", newDir, oldDir)
oldDir.rename(destDir, newDir) oldDir.rename(destDir, newDir)
} }
} }

View file

@ -46,6 +46,9 @@ func TestDirMethods(t *testing.T) {
// Name // Name
assert.Equal(t, "dir", dir.Name()) assert.Equal(t, "dir", dir.Name())
// Path
assert.Equal(t, "dir", dir.Path())
// Sys // Sys
assert.Equal(t, nil, dir.Sys()) assert.Equal(t, nil, dir.Sys())

View file

@ -33,17 +33,12 @@ func newFile(d *Dir, o fs.Object, leaf string) *File {
} }
} }
// path returns the full path of the file
func (f *File) path() string {
return path.Join(f.d.path, f.leaf)
}
// String converts it to printable // String converts it to printable
func (f *File) String() string { func (f *File) String() string {
if f == nil { if f == nil {
return "<nil *File>" return "<nil *File>"
} }
return f.path() return f.Path()
} }
// IsFile returns true for File - satisfies Node interface // IsFile returns true for File - satisfies Node interface
@ -66,6 +61,11 @@ func (f *File) Name() (name string) {
return f.leaf return f.leaf
} }
// Path returns the full path of the file
func (f *File) Path() string {
return path.Join(f.d.path, f.leaf)
}
// Sys returns underlying data source (can be nil) - satisfies Node interface // Sys returns underlying data source (can be nil) - satisfies Node interface
func (f *File) Sys() interface{} { func (f *File) Sys() interface{} {
return nil return nil
@ -197,7 +197,7 @@ func (f *File) setSize(n int64) {
atomic.StoreInt64(&f.size, n) atomic.StoreInt64(&f.size, n)
} }
// Update the object when written // Update the object when written and add it to the directory
func (f *File) setObject(o fs.Object) { func (f *File) setObject(o fs.Object) {
f.mu.Lock() f.mu.Lock()
defer f.mu.Unlock() defer f.mu.Unlock()
@ -259,7 +259,7 @@ func (f *File) OpenWrite() (fh *WriteFileHandle, err error) {
} }
// fs.Debugf(o, "File.OpenWrite") // fs.Debugf(o, "File.OpenWrite")
fh, err = newWriteFileHandle(f.d, f, f.path()) fh, err = newWriteFileHandle(f.d, f, f.Path())
if err != nil { if err != nil {
err = errors.Wrap(err, "open for write") err = errors.Wrap(err, "open for write")
fs.Errorf(f, "File.OpenWrite failed: %v", err) fs.Errorf(f, "File.OpenWrite failed: %v", err)
@ -277,7 +277,7 @@ func (f *File) OpenRW(flags int) (fh *RWFileHandle, err error) {
} }
// fs.Debugf(o, "File.OpenRW") // fs.Debugf(o, "File.OpenRW")
fh, err = newRWFileHandle(f.d, f, f.path(), flags) fh, err = newRWFileHandle(f.d, f, f.Path(), flags)
if err != nil { if err != nil {
err = errors.Wrap(err, "open for read write") err = errors.Wrap(err, "open for read write")
fs.Errorf(f, "File.OpenRW failed: %v", err) fs.Errorf(f, "File.OpenRW failed: %v", err)

View file

@ -44,6 +44,9 @@ func TestFileMethods(t *testing.T) {
// Name // Name
assert.Equal(t, "file1", file.Name()) assert.Equal(t, "file1", file.Name())
// Path
assert.Equal(t, "dir/file1", file.Path())
// Sys // Sys
assert.Equal(t, nil, file.Sys()) assert.Equal(t, nil, file.Sys())

View file

@ -61,6 +61,7 @@ type Node interface {
VFS() *VFS VFS() *VFS
Open(flags int) (Handle, error) Open(flags int) (Handle, error)
Truncate(size int64) error Truncate(size int64) error
Path() string
} }
// Check interfaces // Check interfaces
@ -75,7 +76,7 @@ type Nodes []Node
// Sort functions // Sort functions
func (ns Nodes) Len() int { return len(ns) } func (ns Nodes) Len() int { return len(ns) }
func (ns Nodes) Swap(i, j int) { ns[i], ns[j] = ns[j], ns[i] } func (ns Nodes) Swap(i, j int) { ns[i], ns[j] = ns[j], ns[i] }
func (ns Nodes) Less(i, j int) bool { return ns[i].DirEntry().Remote() < ns[j].DirEntry().Remote() } func (ns Nodes) Less(i, j int) bool { return ns[i].Path() < ns[j].Path() }
// Noder represents something which can return a node // Noder represents something which can return a node
type Noder interface { type Noder interface {