cli/
io.rs

1// SPDX-License-Identifier: GPL-3-0-or-later
2// Copyright (c) 2025 Opinsys Oy
3// Copyright (c) 2024-2025 Jarkko Sakkinen
4
5use crate::{
6    command::{CommandError, OutputEncoding},
7    key::TpmKey,
8};
9use std::{
10    fs,
11    io::{self, Read, Write},
12    path::Path,
13};
14
15/// Reads data from a file path or from stdin if the path is not provided.
16///
17/// # Errors
18///
19/// Returns a `std::io::Error` on failure.
20pub fn read_file_input(input: Option<&Path>) -> io::Result<Vec<u8>> {
21    let mut input_bytes = Vec::new();
22    match input {
23        Some(path) => {
24            input_bytes = std::fs::read(path)?;
25        }
26        None => {
27            io::stdin().read_to_end(&mut input_bytes)?;
28        }
29    }
30    Ok(input_bytes)
31}
32
33/// Handles the output of a `TpmKey`, choosing PEM or DER format based on the
34/// URI.
35///
36/// It will either save it to a file or print it to stdout as PEM, based on the
37/// provided output string.
38///
39/// # Errors
40///
41/// Returns `CommandError` on failure.
42pub fn write_key_data(
43    writer: &mut dyn Write,
44    tpm_key: &TpmKey,
45    output: Option<&Path>,
46    encoding: OutputEncoding,
47) -> Result<(), CommandError> {
48    let output_bytes = match encoding {
49        OutputEncoding::Der => tpm_key.to_der().map_err(CommandError::Key)?,
50        OutputEncoding::Pem => tpm_key.to_pem().map_err(CommandError::Key)?.into_bytes(),
51    };
52
53    write_data(writer, output, &output_bytes)
54}
55
56fn write_data(
57    writer: &mut dyn Write,
58    output_path: Option<&Path>,
59    data: &[u8],
60) -> Result<(), CommandError> {
61    if let Some(path) = output_path {
62        if path.to_str() == Some("-") {
63            writer.write_all(data)?;
64        } else {
65            fs::write(path, data)?;
66            writeln!(writer, "file:{}", path.to_string_lossy())?;
67        }
68    } else {
69        writer.write_all(data)?;
70    }
71    Ok(())
72}