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:
parent
7c3584f4e6
commit
c560017934
8 changed files with 46 additions and 38 deletions
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
16
vfs/dir.go
16
vfs/dir.go
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
|
||||
|
|
18
vfs/file.go
18
vfs/file.go
|
@ -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)
|
||||
|
|
|
@ -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())
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue