mirror of
https://github.com/rclone/rclone.git
synced 2024-12-23 15:38:57 +01:00
vfs: read directory and check for a file before mkdir
Before this change when doing Mkdir the VFS layer could add the new item to an unread directory which caused confusion. It could also do mkdir on a file when run on a bucket based remote which would temporarily overwrite the file with a directory. Fixes #2993
This commit is contained in:
parent
e3bceb9083
commit
173dfbd051
19
vfs/dir.go
19
vfs/dir.go
@ -458,8 +458,23 @@ func (d *Dir) Mkdir(name string) (*Dir, error) {
|
|||||||
return nil, EROFS
|
return nil, EROFS
|
||||||
}
|
}
|
||||||
path := path.Join(d.path, name)
|
path := path.Join(d.path, name)
|
||||||
|
node, err := d.stat(name)
|
||||||
|
switch err {
|
||||||
|
case ENOENT:
|
||||||
|
// not found, carry on
|
||||||
|
case nil:
|
||||||
|
// found so check what it is
|
||||||
|
if node.IsDir() {
|
||||||
|
return node.(*Dir), err
|
||||||
|
}
|
||||||
|
return nil, EEXIST
|
||||||
|
default:
|
||||||
|
// a different error - report
|
||||||
|
fs.Errorf(d, "Dir.Mkdir failed to read directory: %v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
// fs.Debugf(path, "Dir.Mkdir")
|
// fs.Debugf(path, "Dir.Mkdir")
|
||||||
err := d.f.Mkdir(path)
|
err = d.f.Mkdir(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fs.Errorf(d, "Dir.Mkdir failed to create directory: %v", err)
|
fs.Errorf(d, "Dir.Mkdir failed to create directory: %v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -600,7 +615,7 @@ func (d *Dir) Rename(oldName, newName string, destDir *Dir) error {
|
|||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
err = errors.Errorf("unknown type %T", oldNode)
|
err = errors.Errorf("unknown type %T", oldNode)
|
||||||
fs.Errorf(d.path, "Dir.ReadDirAll error: %v", err)
|
fs.Errorf(d.path, "Dir.Rename error: %v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -353,6 +353,33 @@ func TestDirMkdir(t *testing.T) {
|
|||||||
assert.Equal(t, EROFS, err)
|
assert.Equal(t, EROFS, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDirMkdirSub(t *testing.T) {
|
||||||
|
r := fstest.NewRun(t)
|
||||||
|
defer r.Finalise()
|
||||||
|
vfs, dir, file1 := dirCreate(t, r)
|
||||||
|
|
||||||
|
_, err := dir.Mkdir("file1")
|
||||||
|
assert.Error(t, err)
|
||||||
|
|
||||||
|
sub, err := dir.Mkdir("sub")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
subsub, err := sub.Mkdir("subsub")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
// check the vfs
|
||||||
|
checkListing(t, dir, []string{"file1,14,false", "sub,0,true"})
|
||||||
|
checkListing(t, sub, []string{"subsub,0,true"})
|
||||||
|
checkListing(t, subsub, []string(nil))
|
||||||
|
|
||||||
|
// check the underlying r.Fremote
|
||||||
|
fstest.CheckListingWithPrecision(t, r.Fremote, []fstest.Item{file1}, []string{"dir", "dir/sub", "dir/sub/subsub"}, r.Fremote.Precision())
|
||||||
|
|
||||||
|
vfs.Opt.ReadOnly = true
|
||||||
|
_, err = dir.Mkdir("sausage")
|
||||||
|
assert.Equal(t, EROFS, err)
|
||||||
|
}
|
||||||
|
|
||||||
func TestDirRemove(t *testing.T) {
|
func TestDirRemove(t *testing.T) {
|
||||||
r := fstest.NewRun(t)
|
r := fstest.NewRun(t)
|
||||||
defer r.Finalise()
|
defer r.Finalise()
|
||||||
|
Loading…
Reference in New Issue
Block a user