`File::create` may not be able to truncate on macOS SMB share
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
Reproduction:
use std::path::PathBuf;
fn main() {
let path = std::env::args().nth(1).expect("Expect a path on SMB share");
let long_data = vec![b'A'; 1000];
let short_data = vec![b'B'; 10];
// Step 1: write 1000 bytes
println!("[1] Writing {} bytes of 'A' ...", long_data.len());
if let Err(e) = std::fs::write(&path, &long_data) {
eprintln!(" FAILED to write: {e}");
std::process::exit(1);
}
// Step 1b: verify
match std::fs::read(&path) {
Ok(buf) => println!(" Read back: {} bytes", buf.len()),
Err(e) => {
eprintln!(" FAILED to read back: {e}");
std::process::exit(1);
}
}
// Step 2: overwrite with 10 bytes
println!("[2] Overwriting with {} bytes of 'B' ...", short_data.len());
if let Err(e) = std::fs::write(&path, &short_data) {
eprintln!(" FAILED to write: {e}");
std::process::exit(1);
}
// Step 3: read back and check
println!("[3] Reading back ...");
match std::fs::read(&path) {
Ok(buf) => {
println!(" File size: {} bytes", buf.len());
if buf.len() == short_data.len() {
println!(" PASS: file was correctly truncated.");
} else {
println!(" FAIL: expected {} bytes, got {} bytes.", short_data.len(), buf.len());
println!(" The file was NOT truncated -- stale tail data remains.");
println!();
println!(" First 10 bytes: {:?}", &buf[..10.min(buf.len())]);
if buf.len() > 10 {
println!(" Stale tail: {:?} ...", &buf[10..20.min(buf.len())]);
}
}
}
Err(e) => {
eprintln!(" FAILED to read back: {e}");
std::process::exit(1);
}
}
// Cleanup
let _ = std::fs::remove_file(&path);
}
This prints the following when a path on a normal filesystem is given:
[1] Writing 1000 bytes of 'A' ...
Read back: 1000 bytes
[2] Overwriting with 10 bytes of 'B' ...
[3] Reading back ...
File size: 10 bytes
PASS: file was correctly truncated.
However for the unclear reason, a path on macOS SMB share will fail:
[1] Writing 1000 bytes of 'A' ...
Read back: 1000 bytes
[2] Overwriting with 10 bytes of 'B' ...
[3] Reading back ...
File size: 1000 bytes
FAIL: expected 10 bytes, got 1000 bytes.
The file was NOT truncated -- stale tail data remains.
First 10 bytes: [66, 66, 66, 66, 66, 66, 66, 66, 66, 66]
Stale tail: [65, 65, 65, 65, 65, 65, 65, 65, 65, 65] ...
Ultimately this was traced back to #115745 where CREATE_ALWAYS is replaced with OPEN_ALWAYS, which macOS smbd doesn't seem to like (Notepad++ was also hit by the same bug: notepad-plus-plus/notepad-plus-plus#14300).
Meta
rustc 1.95.0 (59807616e 2026-04-14)
binary: rustc
commit-hash: 59807616e1fa2540724bfbac14d7976d7e4a3860
commit-date: 2026-04-14
host: x86_64-pc-windows-msvc
release: 1.95.0
LLVM version: 22.1.2
Since the relevant lines are still in the main branch, the precise version shouldn't matter much here though.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in library/std/src/sys/fs/windows.rs and review the change described in #115745 from CREATE_ALWAYS to OPEN_ALWAYS. Run the provided Rust reproduction against a macOS SMB share and compare it with a normal filesystem. Done means File::create or std::fs::write truncates an existing SMB file correctly without regressing other Windows filesystem behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- operating-systems
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100