Add hash command (#554)

* Add hash command

* Fix globbing without dir

* Add missing file
This commit is contained in:
Vincent Ollivier 2023-11-30 00:43:10 +01:00 committed by GitHub
parent 9086221bac
commit ae6d47aec7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 97 additions and 8 deletions

83
src/usr/hash.rs Normal file
View File

@ -0,0 +1,83 @@
use crate::api;
use crate::api::console::Style;
use crate::api::process::ExitCode;
use crate::api::syscall;
use alloc::format;
use alloc::string::String;
use alloc::vec::Vec;
use core::str;
use sha2::{Digest, Sha256};
pub fn main(args: &[&str]) -> Result<(), ExitCode> {
let mut i = 1;
let n = args.len();
let mut paths = Vec::new();
let mut full = false;
while i < n {
match args[i] {
"-h" | "--help" => {
help();
return Ok(());
}
"-f" | "--full" => {
full = true;
}
arg => {
if arg.starts_with('-') {
error!("Unknown option '{}'", arg);
return Err(ExitCode::UsageError);
}
paths.push(arg);
}
}
i += 1;
}
paths.sort();
for path in paths {
if let Err(code) = print_hash(path, full) {
return Err(code);
}
}
Ok(())
}
pub fn print_hash(path: &str, full: bool) -> Result<(), ExitCode> {
let n = if full { 32 } else { 16 };
if let Some(info) = syscall::info(path) {
if info.is_file() {
if let Ok(bytes) = api::fs::read_to_bytes(path) {
let mut hasher = Sha256::new();
hasher.update(bytes);
let res = hasher.finalize();
let hex = res.iter().map(|byte|
format!("{:02X}", byte)
).take(n).collect::<Vec<String>>().join("");
let pink = Style::color("Pink");
let reset = Style::reset();
println!("{}{}{} {}", pink, hex, reset, path);
Ok(())
} else {
error!("Could not read '{}'", path);
Err(ExitCode::Failure)
}
} else {
error!("Could not read '{}'", path);
Err(ExitCode::Failure)
}
} else {
error!("Could not find file '{}'", path);
Err(ExitCode::Failure)
}
}
fn help() {
let csi_option = Style::color("LightCyan");
let csi_title = Style::color("Yellow");
let csi_reset = Style::reset();
println!("{}Usage:{} hash {}<file>{}", csi_title, csi_reset, csi_option, csi_reset);
println!();
println!("{}Options:{}", csi_title, csi_reset);
println!(" {0}-f{1}, {0}--full{1} Show full hash", csi_option, csi_reset);
}

View File

@ -11,6 +11,7 @@ pub mod editor;
pub mod elf;
pub mod env;
pub mod find;
pub mod hash;
pub mod help;
pub mod hex;
pub mod host;

View File

@ -14,11 +14,11 @@ use alloc::vec::Vec;
use alloc::string::{String, ToString};
// TODO: Scan /bin
const AUTOCOMPLETE_COMMANDS: [&str; 35] = [
const AUTOCOMPLETE_COMMANDS: [&str; 36] = [
"2048", "base64", "calc", "copy", "date", "delete", "dhcp", "disk", "edit", "elf", "env",
"goto", "help", "hex", "host", "http", "httpd", "install", "keyboard", "life", "lisp",
"list", "memory", "move", "net", "pci", "quit", "read", "shell", "socket", "tcp",
"time", "user", "vga", "write"
"goto", "hash", "help", "hex", "host", "http", "httpd", "install", "keyboard", "life", "lisp",
"list", "memory", "move", "net", "pci", "quit", "read", "shell", "socket", "tcp", "time",
"user", "vga", "write"
];
struct Config {
@ -142,10 +142,10 @@ fn glob_to_regex(pattern: &str) -> String {
fn glob(arg: &str) -> Vec<String> {
let mut matches = Vec::new();
if is_globbing(arg) {
let (dir, pattern) = if arg.contains('/') {
(fs::dirname(arg).to_string(), fs::filename(arg).to_string())
let (dir, pattern, show_dir) = if arg.contains('/') {
(fs::dirname(arg).to_string(), fs::filename(arg).to_string(), true)
} else {
(sys::process::dir(), arg.to_string())
(sys::process::dir(), arg.to_string(), false)
};
let re = Regex::new(&glob_to_regex(&pattern));
@ -155,7 +155,11 @@ fn glob(arg: &str) -> Vec<String> {
for file in files {
let name = file.name();
if re.is_match(&name) {
matches.push(format!("{}{}{}", dir, sep, name));
if show_dir {
matches.push(format!("{}{}{}", dir, sep, name));
} else {
matches.push(name);
}
}
}
}
@ -454,6 +458,7 @@ fn exec_with_config(cmd: &str, config: &mut Config) -> Result<(), ExitCode> {
"env" => usr::env::main(&args),
"find" => usr::find::main(&args),
"goto" => cmd_change_dir(&args, config), // TODO: Remove this
"hash" => usr::hash::main(&args),
"help" => usr::help::main(&args),
"hex" => usr::hex::main(&args),
"host" => usr::host::main(&args),