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 {
node, ok := item.(vfs.Node)
if ok {
name := path.Base(node.DirEntry().Remote())
fill(name, nil, 0)
fill(node.Name(), nil, 0)
}
}
itemsRead = len(items)

View file

@ -4,7 +4,6 @@ package mount
import (
"os"
"path"
"time"
"bazil.org/fuse"
@ -93,23 +92,14 @@ func (d *Dir) ReadDirAll(ctx context.Context) (dirents []fuse.Dirent, err error)
if err != nil {
return nil, translateError(err)
}
for _, item := range items {
var dirent fuse.Dirent
switch x := item.DirEntry().(type) {
case fs.Object:
dirent = fuse.Dirent{
// Inode FIXME ???
Type: fuse.DT_File,
Name: path.Base(x.Remote()),
}
case fs.Directory:
dirent = fuse.Dirent{
// Inode FIXME ???
Type: fuse.DT_Dir,
Name: path.Base(x.Remote()),
}
default:
return nil, errors.Errorf("unknown type %T", item)
for _, node := range items {
var dirent = fuse.Dirent{
// Inode FIXME ???
Type: fuse.DT_File,
Name: node.Name(),
}
if node.IsDir() {
dirent.Type = fuse.DT_Dir
}
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
for _, node := range dirEntries {
obj := node.DirEntry()
remote := strings.Trim(obj.Remote(), "/")
leaf := path.Base(remote)
remote := node.Path()
leaf := node.Name()
urlRemote := leaf
if node.IsDir() {
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)
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)
// 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
}
// 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
func (d *Dir) Sys() interface{} {
return nil
@ -325,7 +330,7 @@ func (d *Dir) Create(name string) (*File, error) {
if d.vfs.Opt.ReadOnly {
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
}
@ -390,7 +395,7 @@ func (d *Dir) RemoveAll() error {
for _, node := range nodes {
err = node.RemoveAll()
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
}
}
@ -432,6 +437,9 @@ func (d *Dir) Rename(oldName, newName string, destDir *Dir) error {
return err
}
switch x := oldNode.DirEntry().(type) {
case nil:
fs.Errorf(oldPath, "Dir.Rename cant rename open file")
return EPERM
case fs.Object:
oldObject := x
// 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
if oldNode != nil {
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)
}
}
@ -472,7 +480,7 @@ func (d *Dir) Rename(oldName, newName string, destDir *Dir) error {
// Update the node with the new details
if oldNode != nil {
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)
}
}

View file

@ -46,6 +46,9 @@ func TestDirMethods(t *testing.T) {
// Name
assert.Equal(t, "dir", dir.Name())
// Path
assert.Equal(t, "dir", dir.Path())
// 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
func (f *File) String() string {
if f == nil {
return "<nil *File>"
}
return f.path()
return f.Path()
}
// IsFile returns true for File - satisfies Node interface
@ -66,6 +61,11 @@ func (f *File) Name() (name string) {
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
func (f *File) Sys() interface{} {
return nil
@ -197,7 +197,7 @@ func (f *File) setSize(n int64) {
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) {
f.mu.Lock()
defer f.mu.Unlock()
@ -259,7 +259,7 @@ func (f *File) OpenWrite() (fh *WriteFileHandle, err error) {
}
// fs.Debugf(o, "File.OpenWrite")
fh, err = newWriteFileHandle(f.d, f, f.path())
fh, err = newWriteFileHandle(f.d, f, f.Path())
if err != nil {
err = errors.Wrap(err, "open for write")
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")
fh, err = newRWFileHandle(f.d, f, f.path(), flags)
fh, err = newRWFileHandle(f.d, f, f.Path(), flags)
if err != nil {
err = errors.Wrap(err, "open for read write")
fs.Errorf(f, "File.OpenRW failed: %v", err)

View file

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

View file

@ -61,6 +61,7 @@ type Node interface {
VFS() *VFS
Open(flags int) (Handle, error)
Truncate(size int64) error
Path() string
}
// Check interfaces
@ -75,7 +76,7 @@ type Nodes []Node
// Sort functions
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) 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
type Noder interface {