From c560017934b2373146c05becfecdd31eb9c7faf8 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Sat, 18 Nov 2017 11:47:21 +0000 Subject: [PATCH] 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. --- cmd/cmount/fs.go | 3 +-- cmd/mount/dir.go | 26 ++++++++------------------ cmd/serve/http/http.go | 12 ++++++++---- vfs/dir.go | 16 ++++++++++++---- vfs/dir_test.go | 3 +++ vfs/file.go | 18 +++++++++--------- vfs/file_test.go | 3 +++ vfs/vfs.go | 3 ++- 8 files changed, 46 insertions(+), 38 deletions(-) diff --git a/cmd/cmount/fs.go b/cmd/cmount/fs.go index 01bfc0fcd..fb502e43e 100644 --- a/cmd/cmount/fs.go +++ b/cmd/cmount/fs.go @@ -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) diff --git a/cmd/mount/dir.go b/cmd/mount/dir.go index 4a4079240..9e301d62d 100644 --- a/cmd/mount/dir.go +++ b/cmd/mount/dir.go @@ -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) } diff --git a/cmd/serve/http/http.go b/cmd/serve/http/http.go index 25d690548..9708ad9c1 100644 --- a/cmd/serve/http/http.go +++ b/cmd/serve/http/http.go @@ -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 diff --git a/vfs/dir.go b/vfs/dir.go index 4af06ca6b..962aa460d 100644 --- a/vfs/dir.go +++ b/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) } } diff --git a/vfs/dir_test.go b/vfs/dir_test.go index c79d5db5a..5c9fc0bc6 100644 --- a/vfs/dir_test.go +++ b/vfs/dir_test.go @@ -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()) diff --git a/vfs/file.go b/vfs/file.go index 728babbb0..d403d4b4c 100644 --- a/vfs/file.go +++ b/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 "" } - 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) diff --git a/vfs/file_test.go b/vfs/file_test.go index 43c856583..3c6e206f3 100644 --- a/vfs/file_test.go +++ b/vfs/file_test.go @@ -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()) diff --git a/vfs/vfs.go b/vfs/vfs.go index 0afa293f9..74c478514 100644 --- a/vfs/vfs.go +++ b/vfs/vfs.go @@ -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 {