Create a backup copy of a config file before modifying it. The backup itself is written atomically: content is first written to a staging file (`.bak.new`), then renamed to `.bak`. This ensures the `.bak` file is never half-written even if the process is killed. Returns `Ok(Some(backup_path))` when a backup was created, or `Ok(None)` when the file did not exist (nothing to back up). # Error con
(path: &Path)
| 495 | /// - Staging file cannot be written (disk full, permissions). |
| 496 | /// - Staging file cannot be renamed to `.bak` (cross-device, permissions). |
| 497 | pub fn backup_config_file(path: &Path) -> Result<Option<PathBuf>> { |
| 498 | if !path.exists() { |
| 499 | return Ok(None); |
| 500 | } |
| 501 | let backup_path = PathBuf::from(format!("{}.bak", path.display())); |
| 502 | let staging_path = PathBuf::from(format!("{}.bak.new", path.display())); |
| 503 | |
| 504 | // Read original content |
| 505 | let content = std::fs::read(path).map_err(|e| TraceDecayError::Config { |
| 506 | message: format!( |
| 507 | "failed to read {} for backup: {e}\n \ |
| 508 | Hint: check file permissions", |
| 509 | path.display() |
| 510 | ), |
| 511 | })?; |
| 512 | |
| 513 | // Write to staging file |
| 514 | std::fs::write(&staging_path, &content).map_err(|e| { |
| 515 | std::fs::remove_file(&staging_path).ok(); |
| 516 | TraceDecayError::Config { |
| 517 | message: format!( |
| 518 | "failed to write backup staging file {}: {e}\n \ |
| 519 | Hint: check available disk space and permissions", |
| 520 | staging_path.display() |
| 521 | ), |
| 522 | } |
| 523 | })?; |
| 524 | |
| 525 | // Atomic rename staging → .bak |
| 526 | std::fs::rename(&staging_path, &backup_path).map_err(|e| { |
| 527 | std::fs::remove_file(&staging_path).ok(); |
| 528 | TraceDecayError::Config { |
| 529 | message: format!( |
| 530 | "failed to create backup {}: {e}\n \ |
| 531 | Hint: check file permissions", |
| 532 | backup_path.display() |
| 533 | ), |
| 534 | } |
| 535 | })?; |
| 536 | |
| 537 | Ok(Some(backup_path)) |
| 538 | } |
| 539 | |
| 540 | /// Restore a config file from its backup. Prints instructions for manual |
| 541 | /// recovery if the restore itself fails. |