message: cli/deadend: rework errors with relevant context
  This improves error messages by adding the faulty filepath and
  avoiding duplicating the underlying error kind.
  It also massages the surrounding code introducing constants for
  paths and if-let bindings.
diff: @@ -5,9 +5,14 @@ use std::fs::Permissions;
  use std::io::Write;
  use std::os::unix::fs::PermissionsExt;
  +/// Absolute path to the MOTD fragments directory.
  +static MOTD_FRAGMENTS_DIR: &str = "/run/motd.d/";
  +/// Absolute path to the MOTD fragment with deadend state.
  +static DEADEND_MOTD_PATH: &str = "/run/motd.d/85-zincati-deadend.motd";
  +
  /// Deadend subcommand entry point.
  pub(crate) fn run_deadend(reason: Option<String>) -> Fallible<()> {
  - if reason.is_some() {
  + if let Some(content) = reason {
  // Avoid showing partially-written messages using tempfile and
  // persist (rename).
  let mut f = tempfile::Builder::new()
  @@ -16,27 +21,40 @@ pub(crate) fn run_deadend(reason: Option<String>) -> Fallible<()> {
  // Create the tempfile in the same directory as the final MOTD,
  // to ensure proper SELinux labels are applied to the tempfile
  // before renaming.
  - .tempfile_in("/run/motd.d")
  - .with_context(|e| format!("failed to create temporary MOTD file: {}", e))?;
  + .tempfile_in(MOTD_FRAGMENTS_DIR)
  + .context(format!(
  + "failed to create temporary MOTD file under '{}'",
  + MOTD_FRAGMENTS_DIR
  + ))?;
  // Set correct permissions of the temporary file, before moving to
  // the destination (`tempfile` creates files with mode 0600).
  - std::fs::set_permissions(f.path(), Permissions::from_mode(0o644))
  - .with_context(|e| format!("failed to set permissions of temporary MOTD file: {}", e))?;
  + std::fs::set_permissions(f.path(), Permissions::from_mode(0o644)).context(format!(
  + "failed to set permissions of temporary MOTD file at '{}'",
  + f.path().display()
  + ))?;
  - if let Some(reason) = reason {
  writeln!(
  f,
  - "This release is a dead-end and won't auto-update: {}",
  - reason
  + "This release is a dead-end and will not further auto-update: {}",
  + content
  )
  - .with_context(|e| format!("failed to write MOTD: {}", e))?;
  - }
  + .and_then(|_| f.flush())
  + .context(format!(
  + "failed to write MOTD content to '{}'",
  + f.path().display()
  + ))?;
  - f.persist("/run/motd.d/85-zincati-deadend.motd")
  - .with_context(|e| format!("failed to persist temporary MOTD file: {}", e))?;
  - } else if let Err(e) = std::fs::remove_file("/run/motd.d/85-zincati-deadend.motd") {
  + f.persist(DEADEND_MOTD_PATH).context(format!(
  + "failed to persist MOTD fragment to '{}'",
  + DEADEND_MOTD_PATH
  + ))?;
  + } else if let Err(e) = std::fs::remove_file(DEADEND_MOTD_PATH) {
  if e.kind() != std::io::ErrorKind::NotFound {
  - bail!("failed to remove dead-end release info file: {}", e);
  + bail!(
  + "failed to remove MOTD fragment at '{}': {}",
  + DEADEND_MOTD_PATH,
  + e
  + );
  }
  }
  Ok(())
  