Skip to content

use NtSetInformationFile if os.Rename fails - #220

Open
karman-docker wants to merge 1 commit into
moby:mainfrom
karman-docker:add_retry_for_rename
Open

use NtSetInformationFile if os.Rename fails#220
karman-docker wants to merge 1 commit into
moby:mainfrom
karman-docker:add_retry_for_rename

Conversation

@karman-docker

Copy link
Copy Markdown

This PR adds atomicwriterRenameAt which uses NtSetInformationFile to rename a file on Windows.

Comment thread atomicwriter/atomicwriter_unix.go Outdated
@kolyshkin

Copy link
Copy Markdown
Collaborator

This obviously needs some windows-specific tests.

@kolyshkin kolyshkin left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: you've introduced atomicwriterRenameAt in the first commit, and then rename it to atomicwriterRename in the second commit. Why not use the right name from the start?

nit: stuttering at the name (atomicwriter.atomicwriterRename).

@karman-docker

Copy link
Copy Markdown
Author

nit: you've introduced atomicwriterRenameAt in the first commit, and then rename it to atomicwriterRename in the second commit. Why not use the right name from the start?

nit: stuttering at the name (atomicwriter.atomicwriterRename).

sorry I thought in your initial review comment, you suggested to remove 'At' ?

@kolyshkin

Copy link
Copy Markdown
Collaborator

nit: you've introduced atomicwriterRenameAt in the first commit, and then rename it to atomicwriterRename in the second commit. Why not use the right name from the start?
nit: stuttering at the name (atomicwriter.atomicwriterRename).

sorry I thought in your initial review comment, you suggested to remove 'At' ?

Yes, but here I'm not saying At should be back, I am saying the right name should be introduced from the start, i.e. in the first commit.

@thaJeztah
thaJeztah force-pushed the add_retry_for_rename branch 2 times, most recently from e0379f6 to 88cf225 Compare September 9, 2026 13:34
Signed-off-by: Manju Karikatti <manju.karikatti@docker.com>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The Windows fallback mishandles some paths, fails under pointer checking, and lacks targeted fallback coverage.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds a Windows-specific rename fallback using NtSetInformationFile for atomic file replacement.

Changes:

  • Routes atomic writer renames through platform-specific implementations.
  • Adds Windows native rename handling and Unix compatibility.
  • Adds basic rename tests and promotes x/sys to a direct dependency.
File summaries
File Description
atomicwriter/go.mod Makes x/sys a direct dependency.
atomicwriter/atomicwriter.go Uses the platform rename helper.
atomicwriter/atomicwriter_windows.go Implements the Windows fallback.
atomicwriter/atomicwriter_unix.go Retains standard Unix rename behavior.
atomicwriter/atomicwriter_test.go Tests basic rename behavior.
Review details
  • Files reviewed: 5/5 changed files
  • Comments generated: 4
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

infoEx := (*fileRenameInformationEx)(unsafe.Pointer(&bufferEx[0]))
infoEx.Flags = renameInfoEx.Flags
infoEx.FileNameLength = uint32(fileNameLen)
copy((*[windows.MAX_LONG_PATH]uint16)(unsafe.Pointer(&infoEx.FileName[0]))[:fileNameLen/2:fileNameLen/2], newPathUTF16)
info := (*fileRenameInformation)(unsafe.Pointer(&buffer[0]))
info.ReplaceIfExists = windows.FILE_RENAME_REPLACE_IF_EXISTS | windows.FILE_RENAME_POSIX_SEMANTICS
info.FileNameLength = uint32(fileNameLen)
copy((*[windows.MAX_LONG_PATH]uint16)(unsafe.Pointer(&info.FileName[0]))[:fileNameLen/2:fileNameLen/2], newPathUTF16)

// NtSetInformationFile requires an absolute NT path (\??\C:\...) when
// RootDirectory is NULL.
ntNewPath := `\??\` + newpath
Comment on lines +294 to +300
if err := os.WriteFile(dstPath, []byte("original content"), fileMode); err != nil {
t.Fatalf("Error writing destination file: %v", err)
}

if err := atomicwriterRename(srcPath, dstPath); err != nil {
t.Fatalf("Error renaming file: %v", err)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants