Add utilbox
binary and umount
applet; Move blkid
mountpoint
and
`clear` applets into `utilbox`
This commit is contained in:
parent
06b88d2c24
commit
39c3803acb
@ -14,6 +14,10 @@ path = "corebox/main.rs"
|
|||||||
name = "hashbox"
|
name = "hashbox"
|
||||||
path = "hashbox/main.rs"
|
path = "hashbox/main.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "utilbox"
|
||||||
|
path = "utilbox/main.rs"
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
sc = "0.2"
|
sc = "0.2"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use super::Cmd;
|
use super::Cmd;
|
||||||
use shitbox::args;
|
|
||||||
use clap::{value_parser, Arg, ArgAction, Command};
|
use clap::{value_parser, Arg, ArgAction, Command};
|
||||||
use data_encoding::BASE32;
|
use data_encoding::BASE32;
|
||||||
|
use shitbox::args;
|
||||||
use std::{
|
use std::{
|
||||||
error::Error,
|
error::Error,
|
||||||
fs,
|
fs,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use super::{Cmd, Feedback};
|
use super::{Cmd, Feedback};
|
||||||
use shitbox::args;
|
|
||||||
use clap::{Arg, ArgAction, Command};
|
use clap::{Arg, ArgAction, Command};
|
||||||
use mode::{Mode, Parser};
|
use mode::{Mode, Parser};
|
||||||
|
use shitbox::args;
|
||||||
use std::{
|
use std::{
|
||||||
error::Error,
|
error::Error,
|
||||||
fs::{self, File, Permissions},
|
fs::{self, File, Permissions},
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use super::{Feedback, Group, Recurse, Traversal};
|
use super::{Feedback, Group, Recurse, Traversal};
|
||||||
use shitbox::Cmd;
|
|
||||||
use clap::{Arg, ArgGroup, Command, ValueHint};
|
use clap::{Arg, ArgGroup, Command, ValueHint};
|
||||||
|
use shitbox::Cmd;
|
||||||
use std::{
|
use std::{
|
||||||
error::Error,
|
error::Error,
|
||||||
fs::File,
|
fs::File,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use super::{Cmd, Feedback};
|
use super::{Cmd, Feedback};
|
||||||
use shitbox::args;
|
|
||||||
use clap::{Arg, ArgAction, ArgGroup, ArgMatches, Command, ValueHint};
|
use clap::{Arg, ArgAction, ArgGroup, ArgMatches, Command, ValueHint};
|
||||||
|
use shitbox::args;
|
||||||
use std::{
|
use std::{
|
||||||
error::Error,
|
error::Error,
|
||||||
fs::File,
|
fs::File,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use super::Cmd;
|
use super::Cmd;
|
||||||
use shitbox::{args, Path};
|
|
||||||
use clap::{value_parser, Arg, ArgAction, ArgMatches, Command};
|
use clap::{value_parser, Arg, ArgAction, ArgMatches, Command};
|
||||||
|
use shitbox::{args, Path};
|
||||||
use std::{
|
use std::{
|
||||||
env,
|
env,
|
||||||
error::Error,
|
error::Error,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use super::Cmd;
|
use super::Cmd;
|
||||||
use shitbox::args;
|
|
||||||
use clap::{Arg, Command};
|
use clap::{Arg, Command};
|
||||||
|
use shitbox::args;
|
||||||
use std::{fs, io};
|
use std::{fs, io};
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use super::Cmd;
|
use super::Cmd;
|
||||||
use shitbox::{args, stat};
|
|
||||||
use clap::{Arg, ArgMatches, Command};
|
use clap::{Arg, ArgMatches, Command};
|
||||||
use mode::Parser;
|
use mode::Parser;
|
||||||
|
use shitbox::{args, stat};
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use super::Cmd;
|
use super::Cmd;
|
||||||
use shitbox::{args, stat};
|
|
||||||
use clap::{value_parser, Arg, ArgMatches, Command};
|
use clap::{value_parser, Arg, ArgMatches, Command};
|
||||||
use mode::{get_umask, Parser};
|
use mode::{get_umask, Parser};
|
||||||
|
use shitbox::{args, stat};
|
||||||
use std::{convert::Infallible, error::Error, io, str::FromStr};
|
use std::{convert::Infallible, error::Error, io, str::FromStr};
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use clap::ArgMatches;
|
use clap::ArgMatches;
|
||||||
use shitbox::Cmd;
|
use shitbox::Cmd;
|
||||||
|
|
||||||
mod corebox;
|
|
||||||
mod base32;
|
mod base32;
|
||||||
mod base64;
|
mod base64;
|
||||||
mod basename;
|
mod basename;
|
||||||
@ -10,7 +9,7 @@ mod cat;
|
|||||||
mod chmod;
|
mod chmod;
|
||||||
mod chown;
|
mod chown;
|
||||||
mod chroot;
|
mod chroot;
|
||||||
mod clear;
|
mod corebox;
|
||||||
mod cp;
|
mod cp;
|
||||||
mod cut;
|
mod cut;
|
||||||
mod date;
|
mod date;
|
||||||
@ -33,7 +32,6 @@ mod ls;
|
|||||||
mod mkfifo;
|
mod mkfifo;
|
||||||
mod mknod;
|
mod mknod;
|
||||||
mod mktemp;
|
mod mktemp;
|
||||||
mod mountpoint;
|
|
||||||
mod mv;
|
mod mv;
|
||||||
mod nologin;
|
mod nologin;
|
||||||
mod nproc;
|
mod nproc;
|
||||||
@ -66,7 +64,6 @@ pub fn get(name: &str) -> Option<Box<dyn Cmd>> {
|
|||||||
"chgrp" => Some(Box::new(chown::Chgrp::default())),
|
"chgrp" => Some(Box::new(chown::Chgrp::default())),
|
||||||
"chown" => Some(Box::new(chown::Chown::default())),
|
"chown" => Some(Box::new(chown::Chown::default())),
|
||||||
"chroot" => Some(Box::new(chroot::Chroot::default())),
|
"chroot" => Some(Box::new(chroot::Chroot::default())),
|
||||||
"clear" => Some(Box::new(clear::Clear::default())),
|
|
||||||
"corebox" => Some(Box::new(corebox::Corebox::default())),
|
"corebox" => Some(Box::new(corebox::Corebox::default())),
|
||||||
"cut" => Some(Box::new(cut::Cut::default())),
|
"cut" => Some(Box::new(cut::Cut::default())),
|
||||||
"dirname" => Some(Box::new(dirname::Dirname::default())),
|
"dirname" => Some(Box::new(dirname::Dirname::default())),
|
||||||
@ -84,7 +81,6 @@ pub fn get(name: &str) -> Option<Box<dyn Cmd>> {
|
|||||||
"mkfifo" => Some(Box::new(mkfifo::MkFifo::default())),
|
"mkfifo" => Some(Box::new(mkfifo::MkFifo::default())),
|
||||||
"mknod" => Some(Box::new(mknod::MkNod::default())),
|
"mknod" => Some(Box::new(mknod::MkNod::default())),
|
||||||
"mktemp" => Some(Box::new(mktemp::MkTemp::default())),
|
"mktemp" => Some(Box::new(mktemp::MkTemp::default())),
|
||||||
"mountpoint" => Some(Box::new(mountpoint::Mountpoint::default())),
|
|
||||||
"nologin" => Some(Box::new(nologin::Nologin::default())),
|
"nologin" => Some(Box::new(nologin::Nologin::default())),
|
||||||
"nproc" => Some(Box::new(nproc::Nproc::default())),
|
"nproc" => Some(Box::new(nproc::Nproc::default())),
|
||||||
"printenv" => Some(Box::new(printenv::Printenv::default())),
|
"printenv" => Some(Box::new(printenv::Printenv::default())),
|
||||||
@ -106,7 +102,7 @@ pub fn get(name: &str) -> Option<Box<dyn Cmd>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub static COMMANDS: [&str; 44] = [
|
pub static COMMANDS: [&str; 42] = [
|
||||||
"base32",
|
"base32",
|
||||||
"base64",
|
"base64",
|
||||||
"basename",
|
"basename",
|
||||||
@ -115,7 +111,6 @@ pub static COMMANDS: [&str; 44] = [
|
|||||||
"chmod",
|
"chmod",
|
||||||
"chown",
|
"chown",
|
||||||
"chroot",
|
"chroot",
|
||||||
"clear",
|
|
||||||
"corebox",
|
"corebox",
|
||||||
"cut",
|
"cut",
|
||||||
"dirname",
|
"dirname",
|
||||||
@ -133,7 +128,6 @@ pub static COMMANDS: [&str; 44] = [
|
|||||||
"mkfifo",
|
"mkfifo",
|
||||||
"mknod",
|
"mknod",
|
||||||
"mktemp",
|
"mktemp",
|
||||||
"mountpoint",
|
|
||||||
"nologin",
|
"nologin",
|
||||||
"nproc",
|
"nproc",
|
||||||
"printenv",
|
"printenv",
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use shitbox::Cmd;
|
|
||||||
use clap::{Arg, ArgAction, ArgMatches, Command, ValueHint};
|
use clap::{Arg, ArgAction, ArgMatches, Command, ValueHint};
|
||||||
|
use shitbox::Cmd;
|
||||||
use std::{fs, path::PathBuf};
|
use std::{fs, path::PathBuf};
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use super::Cmd;
|
use super::Cmd;
|
||||||
use shitbox::args;
|
|
||||||
use clap::Command;
|
use clap::Command;
|
||||||
|
use shitbox::args;
|
||||||
use std::{
|
use std::{
|
||||||
fs::File,
|
fs::File,
|
||||||
io::{self, BufRead, BufReader, Write},
|
io::{self, BufRead, BufReader, Write},
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use super::Cmd;
|
use super::Cmd;
|
||||||
use shitbox::{args, fs::FileType};
|
|
||||||
use clap::{Arg, ArgAction, ArgGroup, ArgMatches, Command, ValueHint};
|
use clap::{Arg, ArgAction, ArgGroup, ArgMatches, Command, ValueHint};
|
||||||
|
use shitbox::{args, fs::FileType};
|
||||||
use std::{
|
use std::{
|
||||||
error::Error,
|
error::Error,
|
||||||
fmt,
|
fmt,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use super::Cmd;
|
use super::Cmd;
|
||||||
use shitbox::args;
|
|
||||||
use clap::{Arg, ArgAction, Command, ValueHint};
|
use clap::{Arg, ArgAction, Command, ValueHint};
|
||||||
|
use shitbox::args;
|
||||||
use std::{error::Error, fs, path::Path};
|
use std::{error::Error, fs, path::Path};
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use super::Cmd;
|
use super::Cmd;
|
||||||
use shitbox::args;
|
|
||||||
use clap::{Arg, Command};
|
use clap::{Arg, Command};
|
||||||
|
use shitbox::args;
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct Unlink;
|
pub struct Unlink;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use sc::*;
|
use sc::*;
|
||||||
use std::{io, ffi::CString};
|
use std::{ffi::CString, io};
|
||||||
|
|
||||||
mod mntent;
|
mod mntent;
|
||||||
mod mntentries;
|
mod mntentries;
|
||||||
@ -54,3 +54,12 @@ pub fn swapon(dev: &str, flags: usize) -> io::Result<()> {
|
|||||||
Err(io::Error::last_os_error())
|
Err(io::Error::last_os_error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn umount(special: &str, flags: u32) -> io::Result<()> {
|
||||||
|
let ret = unsafe { syscall!(UMOUNT2, CString::new(special)?.as_ptr(), flags) };
|
||||||
|
if ret == 0 {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(io::Error::last_os_error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -15,6 +15,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// The information for a mount broken out into a struct
|
/// The information for a mount broken out into a struct
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct MntEntry {
|
pub struct MntEntry {
|
||||||
pub fsname: String,
|
pub fsname: String,
|
||||||
pub dir: String,
|
pub dir: String,
|
||||||
@ -29,7 +30,8 @@ impl MntEntry {
|
|||||||
pub fn mount(&self) -> io::Result<()> {
|
pub fn mount(&self) -> io::Result<()> {
|
||||||
let dev = self.device()?;
|
let dev = self.device()?;
|
||||||
let dev = dev.to_string_lossy();
|
let dev = dev.to_string_lossy();
|
||||||
let (flags, opts) = self.parse_opts()
|
let (flags, opts) = self
|
||||||
|
.parse_opts()
|
||||||
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
|
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
|
||||||
super::mount(&dev, &self.dir, &self.fstype, flags, Some(&opts))?;
|
super::mount(&dev, &self.dir, &self.fstype, flags, Some(&opts))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use clap::ArgMatches;
|
use clap::ArgMatches;
|
||||||
use std::{error::Error, fmt};
|
use std::{error::Error, fmt};
|
||||||
|
|
||||||
|
|
||||||
/// Defines a command or applet, it's cli interface, and it's installation directory
|
/// Defines a command or applet, it's cli interface, and it's installation directory
|
||||||
/// relative to the binary
|
/// relative to the binary
|
||||||
pub trait Cmd: fmt::Debug + Sync {
|
pub trait Cmd: fmt::Debug + Sync {
|
||||||
|
1
utilbox/commands/blkid/mod.rs
Normal file
1
utilbox/commands/blkid/mod.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
|
23
utilbox/commands/mod.rs
Normal file
23
utilbox/commands/mod.rs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
use shitbox::Cmd;
|
||||||
|
|
||||||
|
mod blkid;
|
||||||
|
mod clear;
|
||||||
|
mod mount;
|
||||||
|
mod mountpoint;
|
||||||
|
mod umount;
|
||||||
|
mod utilbox;
|
||||||
|
///
|
||||||
|
/// Parses a string into a command to run
|
||||||
|
#[must_use]
|
||||||
|
#[allow(clippy::box_default)]
|
||||||
|
pub fn get(name: &str) -> Option<Box<dyn Cmd>> {
|
||||||
|
match name {
|
||||||
|
"clear" => Some(Box::new(clear::Clear::default())),
|
||||||
|
"mountpoint" => Some(Box::new(mountpoint::Mountpoint::default())),
|
||||||
|
"umount" => Some(Box::new(umount::Umount::default())),
|
||||||
|
"utilbox" => Some(Box::new(utilbox::Utilbox::default())),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub static COMMANDS: [&str; 4] = ["clear", "mountpoint", "umount", "utilbox"];
|
19
utilbox/commands/mount/mod.rs
Normal file
19
utilbox/commands/mount/mod.rs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
use clap::{Arg, ArgAction, ArgMatches, Command};
|
||||||
|
use shitbox::Cmd;
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct Mount;
|
||||||
|
|
||||||
|
impl Cmd for Mount {
|
||||||
|
fn cli(&self) -> Command {
|
||||||
|
Command::new("mount")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(&self, matches: &ArgMatches) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
|
Some(shitbox::Path::Bin)
|
||||||
|
}
|
||||||
|
}
|
0
utilbox/commands/swaplabel/mod.rs
Normal file
0
utilbox/commands/swaplabel/mod.rs
Normal file
0
utilbox/commands/swapoff/mod.rs
Normal file
0
utilbox/commands/swapoff/mod.rs
Normal file
0
utilbox/commands/swapon/mod.rs
Normal file
0
utilbox/commands/swapon/mod.rs
Normal file
140
utilbox/commands/umount/mod.rs
Normal file
140
utilbox/commands/umount/mod.rs
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
use std::io;
|
||||||
|
use clap::{Arg, ArgAction, ArgMatches, Command, ValueHint};
|
||||||
|
use mount::MntEntries;
|
||||||
|
use shitbox::{args, Cmd};
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct Umount;
|
||||||
|
|
||||||
|
impl Cmd for Umount {
|
||||||
|
fn cli(&self) -> Command {
|
||||||
|
Command::new("umount")
|
||||||
|
.about("unmount filesystems")
|
||||||
|
.author("Nathan Fisher")
|
||||||
|
.version(env!("CARGO_PKG_VERSION"))
|
||||||
|
.args([
|
||||||
|
Arg::new("all")
|
||||||
|
.help(
|
||||||
|
"All of the filesystems described in /proc/self/mountinfo \
|
||||||
|
are unmounted, except the proc, devfs, devpts, sysfs, rpc_pipefs \
|
||||||
|
and nfsd filesystems.",
|
||||||
|
)
|
||||||
|
.short('a')
|
||||||
|
.long("all")
|
||||||
|
.action(ArgAction::SetTrue),
|
||||||
|
Arg::new("force")
|
||||||
|
.help("Force an unmount (in case of an unreachable NFS system).")
|
||||||
|
.short('f')
|
||||||
|
.long("force")
|
||||||
|
.action(ArgAction::SetTrue),
|
||||||
|
Arg::new("types")
|
||||||
|
.help(
|
||||||
|
"Indicate that the actions should only be taken on filesystems \
|
||||||
|
of the specified type.",
|
||||||
|
)
|
||||||
|
.long_help(
|
||||||
|
"Indicate that the actions should only be taken on filesystems \
|
||||||
|
of the specified type. More than one type may be specified in a \
|
||||||
|
comma-separated list. The list of filesystem types can be prefixed \
|
||||||
|
with no to indicate that no action should be taken for all of the \
|
||||||
|
mentioned types.",
|
||||||
|
)
|
||||||
|
.short('t')
|
||||||
|
.long("types")
|
||||||
|
.value_delimiter(',')
|
||||||
|
.value_name("type")
|
||||||
|
.requires("all")
|
||||||
|
.num_args(1..),
|
||||||
|
args::verbose(),
|
||||||
|
Arg::new("spec")
|
||||||
|
.value_name("directory|device")
|
||||||
|
.value_hint(ValueHint::AnyPath)
|
||||||
|
.num_args(0..)
|
||||||
|
.required_unless_present("all"),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(&self, matches: &ArgMatches) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
let flags = if matches.get_flag("force") {
|
||||||
|
libc::MNT_FORCE
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
if matches.get_flag("all") {
|
||||||
|
let mut mntpts: Vec<mount::MntEntry> = MntEntries::new("/proc/mounts")?
|
||||||
|
.filter(|x| {
|
||||||
|
x.fstype != "proc"
|
||||||
|
&& x.fstype != "sysfs"
|
||||||
|
&& x.fstype != "devfs"
|
||||||
|
&& x.fstype != "devpts"
|
||||||
|
&& x.fstype != "rpc_pipefs"
|
||||||
|
&& x.fstype != "nfsd"
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
if let Some(types) = matches.get_many::<String>("types") {
|
||||||
|
for t in types {
|
||||||
|
if t.starts_with("no") {
|
||||||
|
let t = t.strip_prefix("no").unwrap();
|
||||||
|
mntpts = mntpts
|
||||||
|
.iter()
|
||||||
|
.filter(|x| x.fstype != t)
|
||||||
|
.map(|x| x.clone())
|
||||||
|
.collect();
|
||||||
|
} else {
|
||||||
|
mntpts = mntpts
|
||||||
|
.iter()
|
||||||
|
.filter(|x| &x.fstype == t)
|
||||||
|
.map(|x| x.clone())
|
||||||
|
.collect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(spec) = matches.get_many::<String>("spec") {
|
||||||
|
for s in spec {
|
||||||
|
for p in &mntpts {
|
||||||
|
if &p.dir == s {
|
||||||
|
mount::umount(s, flags as u32)?;
|
||||||
|
if matches.get_flag("verbose") {
|
||||||
|
println!("umount: {s} unmounted");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for p in &mntpts {
|
||||||
|
mount::umount(&p.dir, flags as u32)?;
|
||||||
|
if matches.get_flag("verbose") {
|
||||||
|
println!("umount: {} unmounted", &p.dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if let Some(spec) = matches.get_many::<String>("spec") {
|
||||||
|
for s in spec {
|
||||||
|
let mntpt = get_mntpt(s)?;
|
||||||
|
mount::umount(&mntpt, flags as u32)?;
|
||||||
|
if matches.get_flag("verbose") {
|
||||||
|
println!("umount: {mntpt} unmounted");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
|
Some(shitbox::Path::Bin)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_mntpt(spec: &str) -> io::Result<String> {
|
||||||
|
let entries = MntEntries::new("/proc/mounts")?;
|
||||||
|
for e in entries {
|
||||||
|
if e.fsname == spec {
|
||||||
|
return Ok(e.dir.clone());
|
||||||
|
} else if e.dir == spec {
|
||||||
|
return Ok(spec.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(io::Error::new(io::ErrorKind::Other, "no such mount"))
|
||||||
|
}
|
48
utilbox/commands/utilbox/mod.rs
Normal file
48
utilbox/commands/utilbox/mod.rs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
use super::COMMANDS;
|
||||||
|
use clap::Command;
|
||||||
|
use shitbox::Cmd;
|
||||||
|
use std::{error::Error, process};
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct Utilbox;
|
||||||
|
|
||||||
|
impl Cmd for Utilbox {
|
||||||
|
fn cli(&self) -> clap::Command {
|
||||||
|
let subcommands: Vec<Command> = {
|
||||||
|
let mut s = vec![];
|
||||||
|
for c in COMMANDS {
|
||||||
|
if c == "utilbox" {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if let Some(cmd) = crate::commands::get(c) {
|
||||||
|
s.push(cmd.cli());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s
|
||||||
|
};
|
||||||
|
Command::new("utilbox")
|
||||||
|
.about("The box store multitool of embedded Linux")
|
||||||
|
.version(env!("CARGO_PKG_VERSION"))
|
||||||
|
.propagate_version(true)
|
||||||
|
.arg_required_else_help(true)
|
||||||
|
.subcommand_value_name("APPLET")
|
||||||
|
.subcommand_help_heading("APPLETS")
|
||||||
|
.subcommands(&subcommands)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(&self, matches: &clap::ArgMatches) -> Result<(), Box<dyn Error>> {
|
||||||
|
if let Some((name, matches)) = matches.subcommand() {
|
||||||
|
if let Some(command) = crate::commands::get(name) {
|
||||||
|
if let Err(e) = command.run(matches) {
|
||||||
|
eprintln!("Error: {name}: {e}");
|
||||||
|
process::exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
18
utilbox/main.rs
Normal file
18
utilbox/main.rs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
use std::process;
|
||||||
|
|
||||||
|
mod commands;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
if let Some(progname) = shitbox::progname() {
|
||||||
|
if let Some(command) = commands::get(&progname) {
|
||||||
|
let cli = command.cli();
|
||||||
|
if let Err(e) = command.run(&cli.get_matches()) {
|
||||||
|
eprintln!("{progname}: Error: {e}");
|
||||||
|
process::exit(1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
eprintln!("shitbox: Error: unknown command {progname}");
|
||||||
|
process::exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user