5 unstable releases
0.3.2 | Jul 17, 2023 |
---|---|
0.3.1 | Feb 25, 2023 |
0.3.0 | Dec 9, 2022 |
0.2.0 | Dec 7, 2022 |
0.1.0 | Dec 6, 2022 |
#909 in Filesystem
3,945 downloads per month
Used in 2 crates
28KB
463 lines
Renamore
More ways to rename files.
Overview
The Rust standard library offers std::fs::rename
for renaming files.
Sometimes, that's not enough. Consider the example of renaming a file but
aborting the operation if something already exists at the destination path.
That can be achieved using the Rust standard library but ensuring that the
operation is atomic requires platform-specific APIs. Without using
platform-specific APIs, a TOCTTOU bug can be introduced. This library aims
to provide a cross-platform interface to these APIs.
Examples
Renaming a file without the possibility of accidentally overwriting anything
can be done using rename_exclusive
. It should be noted that this feature
is not supported by all combinations of operating system and file system.
rename_exclusive
will fail if it can't be done atomically.
use std::io::Result;
fn main() -> Result<()> {
renamore::rename_exclusive("old.txt", "new.txt")
}
Alternatively, rename_exclusive_fallback
can be used. This will try to
perform the operation atomically, and use a non-atomic fallback if that's
not supported. The return value will indicate what happened.
use std::io::Result;
fn main() -> Result<()> {
if renamore::rename_exclusive_fallback("old.txt", "new.txt")? {
// `new.txt` was definitely not overwritten.
println!("The operation was atomic");
} else {
// `new.txt` was probably not overwritten.
println!("The operation was not atomic");
}
Ok(())
}
Platform-specific behaviour
On Linux, the renameat2
syscall is used. A wrapper around this syscall is
provided by glibc since version 2.28 but not musl (yet?). The existence of
the wrapper is checked at build time and a wrapper is provided if one isn't
found. In case something goes wrong, there are two features that can be used
to bypass this mechanism.
always-supported
. Assume thatrenameat2
exists.always-fallback
. Assume thatrenameat2
doesn't exist.
Hopefully using these features shouldn't be necessary. If they do become necessary, then there might be a bug.
License
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
No runtime deps
~0–1.2MB
~18K SLoC