sn_cli/files/
upload.rs

1// Copyright 2024 MaidSafe.net limited.
2//
3// This SAFE Network Software is licensed to you under The General Public License (GPL), version 3.
4// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
5// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
6// KIND, either express or implied. Please review the Licences for the specific language governing
7// permissions and limitations relating to use of the SAFE Network Software.
8
9use bytes::Bytes;
10use color_eyre::Result;
11use serde::Deserialize;
12use sn_client::protocol::storage::ChunkAddress;
13use std::{ffi::OsString, path::Path};
14use tracing::{error, warn};
15
16/// Subdir for storing uploaded file into
17pub const UPLOADED_FILES: &str = "uploaded_files";
18
19/// The metadata related to file that has been uploaded.
20/// This is written during upload and read during downloads.
21#[derive(Clone, Debug, Deserialize)]
22pub struct UploadedFile {
23    pub filename: OsString,
24    pub data_map: Option<Bytes>,
25}
26
27impl UploadedFile {
28    /// Write an UploadedFile to a path identified by the hex of the head ChunkAddress.
29    /// If you want to update the data_map to None, calling this function will overwrite the previous value.
30    pub fn write(&self, root_dir: &Path, head_chunk_address: &ChunkAddress) -> Result<()> {
31        let uploaded_files = root_dir.join(UPLOADED_FILES);
32
33        if !uploaded_files.exists() {
34            if let Err(error) = std::fs::create_dir_all(&uploaded_files) {
35                error!("Failed to create {uploaded_files:?} because {error:?}");
36            }
37        }
38
39        let uploaded_file_path = uploaded_files.join(head_chunk_address.to_hex());
40
41        if self.data_map.is_none() {
42            warn!(
43                "No data-map being written for {:?} as it is empty",
44                self.filename
45            );
46        }
47        let serialized =
48            rmp_serde::to_vec(&(&self.filename, &self.data_map)).inspect_err(|_err| {
49                error!("Failed to serialize UploadedFile");
50            })?;
51
52        std::fs::write(&uploaded_file_path, serialized).inspect_err(|_err| {
53            error!(
54                "Could not write UploadedFile of {:?} to {uploaded_file_path:?}",
55                self.filename
56            );
57        })?;
58
59        Ok(())
60    }
61
62    pub fn read(path: &Path) -> Result<Self> {
63        let bytes = std::fs::read(path).inspect_err(|_err| {
64            error!("Error while reading the UploadedFile from {path:?}");
65        })?;
66        let metadata = rmp_serde::from_slice(&bytes).inspect_err(|_err| {
67            error!("Error while deserializing UploadedFile for {path:?}");
68        })?;
69        Ok(metadata)
70    }
71}