atomic-write-file

Latest version: 0.2.3 registry icon
Maintenance score
100
Safety score
100
Popularity score
71
Check your open source dependency risks. Get immediate insight about security, stability and licensing risks.
Security
  Vulnerabilities
Version Suggest Low Medium High Critical
0.2.3 0 0 0 0 0
0.2.2 0 0 0 0 0
0.2.1 0 0 0 0 0
0.2.0 0 0 0 0 0
0.1.4 0 0 0 0 0
0.1.3 0 0 0 0 0
0.1.2 0 0 0 0 0
0.1.1 0 0 0 0 0
0.1.0 0 0 0 0 0

Stability
Latest release:

0.2.3 - This version is safe to use because it has no known security vulnerabilities at this time. Find out if your coding project uses this component and get notified of any reported security vulnerabilities with Meterian-X Open Source Security Platform

Licensing

Maintain your licence declarations and avoid unwanted licences to protect your IP the way you intended.

BSD-3-Clause   -   BSD 3-Clause "New" or "Revised" License

Not a wildcard

Not proprietary

OSI Compliant



Atomic Write File

Crate Documentation Build Status Crash Tests Status License

This is a Rust crate that offers functionality to write and overwrite files atomically, that is: without leaving the file in an intermediate state. Either the new contents of the files are written to the filesystem, or the old contents (if any) are preserved.

This crate implements two main structs: AtomicWriteFile and OpenOptions, which mimic the standard std::fs::File and std::fs::OpenOptions as much as possible.

This crate supports all major platforms, including: Unix systems, Windows, and WASI.

This crate is throughly tested to ensure the integrity of the files it creates. In particular, it ships with tests that simulate kernel panics on Linux and check the file contents afterwards. You can see those tests in action on the dedicated GitHub workflow.

Motivation and Example

Consider the following snippet of code to write a configuration file in JSON format:

use std::io::Write;
use std::fs::File;

let mut file = File::options()
                    .write(true)
                    .create(true)
                    .open("config.json")?;

writeln!(file, "{{")?;
writeln!(file, "  \"key1\": \"value1\",")?;
writeln!(file, "  \"key2\": \"value2\"")?;
writeln!(file, "}}")?;

This code opens a file named config.json, truncates its contents (if the file already existed), and writes the JSON content line-by-line.

If the code is interrupted before all of the writeln! calls are completed (because of a panic, or a signal is received, or the process is killed, or a filesystem error occurs), then the file will be left in a broken state: it will not contain valid JSON data, and the original contents (if any) will be lost.

AtomicWriteFile solves this problem by placing the new contents into the destination file only after it has been completely written to the filesystem. The snippet above can be rewritten using AtomicWriteFile instead of File as follows:

use std::io::Write;
use atomic_write_file::AtomicWriteFile;

let mut file = AtomicWriteFile::options()
                               .open("config.json")?;

writeln!(file, "{{")?;
writeln!(file, "  \"key1\": \"value1\",")?;
writeln!(file, "  \"key2\": \"value2\"")?;
writeln!(file, "}}")?;

file.commit()?;

Note that this code is almost the same as the original, except that it now uses AtomicWriteFile instead of File and there's an additional call to commit().

If the code is interrupted early, before the call to commit(), the original file config.json will be left untouched. Only if the new contents are fully written to the filesystem, config.json will get them.

Documentation

Reference, examples, internal details, and limitations are all available on docs.rs/atomic-write-file.