diff --git a/src/runtime/src/config.rs b/src/runtime/src/config.rs index 18c1898..d9278c7 100644 --- a/src/runtime/src/config.rs +++ b/src/runtime/src/config.rs @@ -1,7 +1,7 @@ use crate::sd_reader; use core::fmt; use alloc::{string::FromUtf8Error, string::String, vec::Vec}; -use core_io::{self as io, BufRead, BufReader, Read, Write, ErrorKind}; +use core_io::{self as io, BufRead, BufReader, Read, Write, Seek, ErrorKind, SeekFrom}; use libboard_zynq::sdio; @@ -61,6 +61,39 @@ fn parse_config<'a>( } Err(Error::KeyNotFoundError(key)) } +fn delete_old_entry<'a>( + key: &str, + file: fatfs::File, + mut file_tmp: fatfs::File, +) -> Result<'a, ()> { + let prefix = [key, "="].concat(); + let buf_reader = BufReader::new(file); + + for line in buf_reader.lines() { + let line = line?; + if !line.starts_with(&prefix) { + file_tmp.write_all(&[line.as_str(), "\n"].concat().as_bytes())?; + } + } + Ok(()) +} + +fn rename_file<'a>(dir: &fatfs::Dir, old_file_name: &str, new_file_name: &str) -> Result<'a, ()>{ + { + let old_file = dir.open_file(old_file_name)?; + let mut new_file = dir.create_file(new_file_name)?; + new_file.truncate()?; + + for line in BufReader::new(old_file).lines() { + let line = line?; + new_file.write_all(&[line.as_str(), "\n"].concat().as_bytes())?; + } + } + + dir.remove(old_file_name)?; + + Ok(()) +} pub struct Config { fs: Option>, @@ -108,26 +141,27 @@ impl Config { if let Some(fs) = &self.fs { let root_dir = fs.root_dir(); - let use_config_txt = data.is_ascii() & (data.len() <= 100); - let file_path; let config_key_bin = &["/CONFIG/", key, ".BIN"].concat(); + let config_txt_tmp = "/CONFIG.TMP"; - if use_config_txt { - file_path = "/CONFIG.TXT"; - } else { - file_path = config_key_bin; - } + if data.is_ascii() & (data.len() <= 100) { + match root_dir.create_file("/CONFIG.TXT") { + Ok(file) => { + let mut file_tmp = root_dir.create_file(config_txt_tmp)?; + file_tmp.truncate()?; + delete_old_entry(key, file, file_tmp)?; + }, + Err(e) => { + return Err(Error::IoError(e)); + } + }; - let mut file = match root_dir.create_file(file_path) { - Ok(f) => f, - Err(_) => root_dir.open_file("/CONFIG.TXT")? - }; + rename_file(&root_dir, config_txt_tmp, "/CONFIG.TXT")?; - file.truncate()?; - file.write_all(&[key,"="].concat().as_bytes())?; - file.write_all(data.as_bytes())?; + let mut file = root_dir.open_file("/CONFIG.TXT")?; + file.seek(SeekFrom::End(0))?; + file.write_all(&["\n", key, "=", data, "\n"].concat().as_bytes())?; - if use_config_txt { match root_dir.remove(config_key_bin) { Ok(_) => {}, Err(e) => match e.kind() { @@ -137,6 +171,36 @@ impl Config { } } }; + } else { + root_dir.create_dir("/CONFIG")?; + match root_dir.create_file(config_key_bin) { + Ok(mut file) => { + file.truncate()?; + file.write_all(&[data, "\n"].concat().as_bytes())?; + }, + Err(e) => { + return Err(Error::IoError(e)); + } + }; + + let mut need_to_rename = false; + match root_dir.open_file("/CONFIG.TXT") { + Ok(file) => { + need_to_rename = true; + let mut file_tmp = root_dir.create_file(config_txt_tmp)?; + file_tmp.truncate()?; + delete_old_entry(key, file, file_tmp)?; + }, + Err(e) => match e.kind() { + ErrorKind::NotFound => {}, + _ => { + return Err(Error::IoError(e)); + } + } + }; + if need_to_rename { // docs: ensure no ref to files + rename_file(&root_dir, config_txt_tmp, "/CONFIG.TXT")?; + } } Ok(())