Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix docs for fs::rename() #1053

Open
riveroon opened this issue Jan 16, 2023 · 0 comments
Open

Fix docs for fs::rename() #1053

riveroon opened this issue Jan 16, 2023 · 0 comments

Comments

@riveroon
Copy link

Found another minor documentation error. Yay :)
Maybe I'm missing something, but fs::rename()'s docs also have the wrong behavior documented:

If a file or directory already exists at the target location, it will be overwritten by this operation.

However, async-std's rename() uses std's rename() internally, which currently MAY return an error if to exists:

replacing the original file if to already exists.

Platform-specific behavior

This function currently corresponds to the rename function on Unix and the MoveFileEx function with the MOVEFILE_REPLACE_EXISTING flag on Windows.

Because of this, the behavior when both from and to exist differs. On Unix, if from is a directory, to must also be an (empty) directory. If from is not a directory, to must also be not a directory. In contrast, on Windows, from can be anything, but to must not be a directory.

Therefore, the simple statement

If a file or directory already exists at the target location, it will be overwritten by this operation.

does not cover the cases where it WILL return an error, which is:

Unix (and Linux):

  • from and to is an existing directory and a file, or a file and a directory respectively.
  • from and to are both directories, but to is not empty.

Windows

  • from is a existing directory.

This behavior can be demonstrated with the following code:

fn main() -> io::Result<()> {
    async_std::task::block_on(async {
        let from = Path::new("./foo");

        //Create some directories...
        fs::create_dir_all(from).await?;
        fs::create_dir_all("./bar/baz").await?;

        //This should work... or does it?
        fs::rename(from, "./bar").await
    })
}

(Note that this uses fs::create_dir_all() to avoid returning an error if the directories already exist, see #1051)

Running the above code prints

Error: Custom { kind: PermissionDenied, error: VerboseError { source: Os { code: 5, kind: PermissionDenied, message: "Access is denied." }, message: "could not rename `./foo` to `./bar`" } }

for Windows, and

Error: Custom { kind: DirectoryNotEmpty, error: VerboseError { source: Os { code: 39, kind: DirectoryNotEmpty, message: "Directory not empty" }, message: "could not rename `./foo` to `./bar`" } }

for Linux.

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

No branches or pull requests

1 participant