diff --git a/vfs/dir.go b/vfs/dir.go index 79a8d6537..755fde807 100644 --- a/vfs/dir.go +++ b/vfs/dir.go @@ -843,6 +843,23 @@ func (d *Dir) Open(flags int) (fd Handle, err error) { // Create makes a new file node func (d *Dir) Create(name string, flags int) (*File, error) { // fs.Debugf(path, "Dir.Create") + // Return existing node if one exists + node, err := d.stat(name) + switch err { + case ENOENT: + // not found, carry on + case nil: + // found so check what it is + if node.IsFile() { + return node.(*File), err + } + return nil, EEXIST // EISDIR would be better but we don't have that + default: + // a different error - report + fs.Errorf(d, "Dir.Create stat failed: %v", err) + return nil, err + } + // node doesn't exist so create it if d.vfs.Opt.ReadOnly { return nil, EROFS } diff --git a/vfs/dir_test.go b/vfs/dir_test.go index 06c23cdc2..93c35c00d 100644 --- a/vfs/dir_test.go +++ b/vfs/dir_test.go @@ -375,6 +375,13 @@ func TestDirCreate(t *testing.T) { require.NoError(t, err) assert.Equal(t, int64(5), file2.Size()) + // Try creating the file again - make sure we get the same file node + file3, err := dir.Create("potato", os.O_RDWR|os.O_CREATE) + require.NoError(t, err) + assert.Equal(t, int64(5), file3.Size()) + assert.Equal(t, fmt.Sprintf("%p", file), fmt.Sprintf("%p", file3), "didn't return same node") + + // Test read only fs creating new vfs.Opt.ReadOnly = true _, err = dir.Create("sausage", os.O_WRONLY|os.O_CREATE) assert.Equal(t, EROFS, err)