From b8fbf19e9ad3d7bb36876a674da18887b3c49c08 Mon Sep 17 00:00:00 2001 From: chrislu Date: Tue, 11 Jan 2022 03:23:03 -0800 Subject: [PATCH] mount: rename follow POSIX --- weed/filesys/dir_rename.go | 24 ++++++++++++++---------- weed/server/filer_grpc_server_rename.go | 15 +++++++++++++++ 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/weed/filesys/dir_rename.go b/weed/filesys/dir_rename.go index a18ed8243..01a8df175 100644 --- a/weed/filesys/dir_rename.go +++ b/weed/filesys/dir_rename.go @@ -3,13 +3,13 @@ package filesys import ( "context" "github.com/chrislusf/seaweedfs/weed/filer" - "github.com/seaweedfs/fuse" - "github.com/seaweedfs/fuse/fs" - "io" - "github.com/chrislusf/seaweedfs/weed/glog" "github.com/chrislusf/seaweedfs/weed/pb/filer_pb" "github.com/chrislusf/seaweedfs/weed/util" + "github.com/seaweedfs/fuse" + "github.com/seaweedfs/fuse/fs" + "io" + "strings" ) func (dir *Dir) Rename(ctx context.Context, req *fuse.RenameRequest, newDirectory fs.Node) error { @@ -37,7 +37,7 @@ func (dir *Dir) Rename(ctx context.Context, req *fuse.RenameRequest, newDirector stream, err := client.StreamRenameEntry(ctx, request) if err != nil { glog.Errorf("dir AtomicRenameEntry %s => %s : %v", oldPath, newPath, err) - return fuse.EXDEV + return fuse.EIO } for { @@ -46,11 +46,19 @@ func (dir *Dir) Rename(ctx context.Context, req *fuse.RenameRequest, newDirector if recvErr == io.EOF { break } else { + glog.V(0).Infof("dir Rename %s => %s receive: %v", oldPath, newPath, recvErr) + if strings.Contains(recvErr.Error(), "not empty") { + return fuse.EEXIST + } + if strings.Contains(recvErr.Error(), "not directory") { + return fuse.ENOTDIR + } return recvErr } } if err = dir.handleRenameResponse(ctx, resp); err != nil { + glog.V(0).Infof("dir Rename %s => %s : %v", oldPath, newPath, err) return err } @@ -59,12 +67,8 @@ func (dir *Dir) Rename(ctx context.Context, req *fuse.RenameRequest, newDirector return nil }) - if err != nil { - glog.V(0).Infof("dir Rename %s => %s : %v", oldPath, newPath, err) - return fuse.EIO - } - return nil + return err } func (dir *Dir) handleRenameResponse(ctx context.Context, resp *filer_pb.StreamRenameEntryResponse) error { diff --git a/weed/server/filer_grpc_server_rename.go b/weed/server/filer_grpc_server_rename.go index 62bcccabb..d70df5db7 100644 --- a/weed/server/filer_grpc_server_rename.go +++ b/weed/server/filer_grpc_server_rename.go @@ -72,6 +72,21 @@ func (fs *FilerServer) StreamRenameEntry(req *filer_pb.StreamRenameEntryRequest, return fmt.Errorf("%s/%s not found: %v", req.OldDirectory, req.OldName, err) } + // follow https://pubs.opengroup.org/onlinepubs/000095399/functions/rename.html + if oldEntry.IsDirectory() { + targetDir := newParent.Child(req.NewName) + newEntry, err := fs.filer.FindEntry(ctx, targetDir) + if err == nil { + if !newEntry.IsDirectory() { + fs.filer.RollbackTransaction(ctx) + return fmt.Errorf("%s is not directory", targetDir) + } + if entries, _, _ := fs.filer.ListDirectoryEntries(context.Background(), targetDir, "", false, 1, "", "", ""); len(entries) > 0 { + return fmt.Errorf("%s is not empty", targetDir) + } + } + } + moveErr := fs.moveEntry(ctx, stream, oldParent, oldEntry, newParent, req.NewName, req.Signatures) if moveErr != nil { fs.filer.RollbackTransaction(ctx)