swift-foundation icon indicating copy to clipboard operation
swift-foundation copied to clipboard

`Data.write(to:options:)` crashes if `[.atomic, .withoutOverwriting]` are passed together

Open weissi opened this issue 1 year ago • 1 comments

https://github.com/swiftlang/swift-foundation/blob/c0532f8c99491949d146fbd9b9f2bac5384e6dbd/Sources/FoundationEssentials/Data/Data.swift#L2445-L2447

Severe, source breaking bug here. In 5.10 and below, [.atomic, .withoutOverwriting] worked just fine (possibly not achieving the desired behaviour). We've got to back out this change because

  1. It's source breaking (works in 5.10, crashes in 6.0)
  2. The docs don't mention that .atomic and .withoutOverwriting are mutually exclusive
  3. They shouldn't be mutually exclusive 3.1. On Linux, the man page for open's example for O_TMPFILE contains how to implement [.atomic, .withoutOverwriting] 3.2. On systems that lack O_TMPFILE, this can still be approximated with write to .tmp_XXXXXX, then rename tmp file (and remove if that fails). That still prevents half-written files

weissi avatar Dec 16 '24 22:12 weissi

Hi! My idea is to remove the fatalError and make it safe to use .atomic and .withoutOverwriting together by:

  • Writing the data to a temporary file first (using .atomic)
  • If the destination file already exists, delete the temp file and throw a standard Cocoa error (NSFileWriteFileExistsError)
  • If it doesn't exist, move the temp file to the destination path

This should match the behavior we had in Swift 5.10 and keep things safe without overwriting files unexpectedly. Let me know if this direction works — I’ll send in a draft PR soon so we can review it together.

Thanks!

beltradini avatar Apr 22 '25 18:04 beltradini