| 454 | } |
| 455 | |
| 456 | func copyFileWithSync(target, source string) error { |
| 457 | // The Go stdlib does not seem to have an efficient os.File.ReadFrom |
| 458 | // routine for other platforms like it does on Linux with |
| 459 | // copy_file_range. For Darwin at least we can use clonefile |
| 460 | // in its place, otherwise if we have a sparse file we'd have |
| 461 | // a fun surprise waiting below. |
| 462 | // |
| 463 | // TODO: Enlighten other platforms (windows?) |
| 464 | if runtime.GOOS == "darwin" { |
| 465 | return fs.CopyFile(target, source) |
| 466 | } |
| 467 | |
| 468 | src, err := os.Open(source) |
| 469 | if err != nil { |
| 470 | return fmt.Errorf("failed to open source %s: %w", source, err) |
| 471 | } |
| 472 | defer src.Close() |
| 473 | tgt, err := os.Create(target) |
| 474 | if err != nil { |
| 475 | return fmt.Errorf("failed to open target %s: %w", target, err) |
| 476 | } |
| 477 | defer tgt.Close() |
| 478 | defer tgt.Sync() |
| 479 | |
| 480 | _, err = io.Copy(tgt, src) |
| 481 | return err |
| 482 | } |