Simplified Cmd trait, trimmed 600K from binary size

This commit is contained in:
Nathan Fisher 2023-01-13 01:08:32 -05:00
parent 76e7036da9
commit a8c8ba5819
27 changed files with 124 additions and 471 deletions

View File

@ -8,26 +8,10 @@ use std::{
};
use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor};
#[derive(Debug)]
pub struct Base32 {
name: &'static str,
path: Option<crate::Path>,
}
impl Default for Base32 {
fn default() -> Self {
Self {
name: "base32",
path: Some(crate::Path::UsrBin),
}
}
}
#[derive(Debug, Default)]
pub struct Base32;
impl Cmd for Base32 {
fn name(&self) -> &str {
self.name
}
fn cli(&self) -> clap::Command {
Command::new("base32")
.author("Nathan Fisher")
@ -121,7 +105,7 @@ impl Cmd for Base32 {
}
fn path(&self) -> Option<crate::Path> {
self.path
Some(crate::Path::UsrBin)
}
}

View File

@ -8,26 +8,10 @@ use std::{
};
use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor};
#[derive(Debug)]
pub struct Base64 {
name: &'static str,
path: Option<crate::Path>,
}
impl Default for Base64 {
fn default() -> Self {
Self {
name: "base64",
path: Some(crate::Path::UsrBin),
}
}
}
#[derive(Debug, Default)]
pub struct Base64;
impl Cmd for Base64 {
fn name(&self) -> &str {
self.name
}
fn cli(&self) -> Command {
Command::new("base64")
.author("Nathan Fisher")
@ -119,7 +103,7 @@ impl Cmd for Base64 {
}
fn path(&self) -> Option<crate::Path> {
self.path
Some(crate::Path::UsrBin)
}
}
@ -129,7 +113,7 @@ fn decode_base64(mut contents: String, ignore: bool) -> Result<(), Box<dyn Error
} else {
contents = contents.replace('\n', "");
}
let decoded = BASE64.decode(&contents.as_bytes())?;
let decoded = BASE64.decode(contents.as_bytes())?;
let output = String::from_utf8(decoded)?;
println!("{}\n", output.trim_end());
Ok(())

View File

@ -2,28 +2,12 @@ use super::Cmd;
use clap::{Arg, ArgMatches, Command};
use std::io;
#[derive(Debug)]
pub struct Basename {
name: &'static str,
path: Option<crate::Path>,
}
impl Default for Basename {
fn default() -> Self {
Self {
name: "basename",
path: Some(crate::Path::UsrBin),
}
}
}
#[derive(Debug, Default)]
pub struct Basename;
impl Cmd for Basename {
fn name(&self) -> &str {
self.name
}
fn cli(&self) -> clap::Command {
Command::new(self.name)
Command::new("basename")
.about("Print NAME with any leading directory components removed.")
.long_about(
"Print NAME with any leading directory components removed.\n\
@ -62,6 +46,6 @@ impl Cmd for Basename {
}
fn path(&self) -> Option<crate::Path> {
self.path
Some(crate::Path::UsrBin)
}
}

View File

@ -11,20 +11,8 @@ use std::{
path::{Path, PathBuf},
};
#[derive(Debug)]
pub struct Bootstrap {
name: &'static str,
path: Option<crate::Path>,
}
impl Default for Bootstrap {
fn default() -> Self {
Self {
name: "bootstrap",
path: None,
}
}
}
#[derive(Debug, Default)]
pub struct Bootstrap;
impl Bootstrap {
fn all() -> clap::Command {
@ -127,12 +115,8 @@ impl Bootstrap {
}
impl Cmd for Bootstrap {
fn name(&self) -> &str {
self.name
}
fn cli(&self) -> clap::Command {
Command::new(self.name)
Command::new("bootstrap")
.version(env!("CARGO_PKG_VERSION"))
.author("Nathan Fisher")
.about("Install shitbox into the filesystem")
@ -212,7 +196,7 @@ impl Cmd for Bootstrap {
}
fn path(&self) -> Option<crate::Path> {
self.path
None
}
}
@ -225,7 +209,8 @@ pub trait BootstrapCmd {
impl BootstrapCmd for dyn Cmd {
fn completion(&self, outdir: &Path, gen: &str) -> Result<(), io::Error> {
let name = self.name();
let cmd = self.cli();
let name = cmd.get_name();
let mut cmd = self.cli();
if !outdir.exists() {
fs::create_dir_all(outdir)?;
@ -249,7 +234,7 @@ impl BootstrapCmd for dyn Cmd {
Some(p) => path.push(p.to_str(usr)),
None => return None,
}
path.push(self.name());
path.push(self.cli().get_name());
Some(path)
}
@ -289,7 +274,7 @@ impl BootstrapCmd for dyn Cmd {
fn manpage(&self, prefix: &str) -> Result<(), io::Error> {
let command = self.cli();
let fname = match self.name() {
let fname = match command.get_name() {
"bootstrap" => "shitbox-bootstrap.1".to_string(),
s => format!("{s}.1"),
};

View File

@ -5,10 +5,6 @@ use clap::Command;
pub struct Clear;
impl Cmd for Clear {
fn name(&self) -> &str {
"clear"
}
fn cli(&self) -> Command {
Command::new("clear")
.about("clear the terminal's screen")

View File

@ -2,26 +2,10 @@ use super::Cmd;
use clap::{Arg, ArgAction, Command};
use std::path::Path;
#[derive(Debug)]
pub struct Dirname {
name: &'static str,
path: Option<crate::Path>,
}
impl Default for Dirname {
fn default() -> Self {
Self {
name: "dirname",
path: Some(crate::Path::UsrBin),
}
}
}
#[derive(Debug, Default)]
pub struct Dirname;
impl Cmd for Dirname {
fn name(&self) -> &str {
self.name
}
fn cli(&self) -> clap::Command {
Command::new("dirname")
.about("strip last component from file name")
@ -61,6 +45,6 @@ impl Cmd for Dirname {
}
fn path(&self) -> Option<crate::Path> {
self.path
Some(crate::Path::UsrBin)
}
}

View File

@ -1,30 +1,13 @@
use super::Cmd;
use crate::Path;
use clap::{Arg, Command};
use std::{env, error::Error};
#[derive(Debug)]
pub struct Echo {
name: &'static str,
path: Option<Path>,
}
impl Default for Echo {
fn default() -> Self {
Self {
name: "echo",
path: Some(crate::Path::Bin),
}
}
}
#[derive(Debug, Default)]
pub struct Echo;
impl Cmd for Echo {
fn name(&self) -> &str {
self.name
}
fn cli(&self) -> clap::Command {
Command::new(self.name)
Command::new("echo")
.about("Display a line of text")
.long_about("Echo the STRING(s) to standard output")
.author("Nathan Fisher")
@ -39,7 +22,7 @@ impl Cmd for Echo {
fn run(&self, _matches: Option<&clap::ArgMatches>) -> Result<(), Box<dyn Error>> {
let args: Vec<String> = env::args().collect();
let idx = match crate::progname() {
Some(s) if s.as_str() == self.name() => 1,
Some(s) if s.as_str() == "echo" => 1,
Some(_) => 2,
None => unreachable!(),
};
@ -60,6 +43,6 @@ impl Cmd for Echo {
}
fn path(&self) -> Option<crate::Path> {
self.path
Some(crate::Path::Bin)
}
}

View File

@ -1,30 +1,14 @@
use crate::Cmd;
use super::Cmd;
use clap::{value_parser, Arg, ArgMatches, Command};
use std::{
error::Error,
io::{self, BufRead},
};
#[derive(Debug)]
pub struct Factor {
name: &'static str,
path: Option<crate::Path>,
}
impl Default for Factor {
fn default() -> Self {
Self {
name: "factor",
path: Some(crate::Path::UsrBin),
}
}
}
#[derive(Debug, Default)]
pub struct Factor;
impl Cmd for Factor {
fn name(&self) -> &str {
self.name
}
fn cli(&self) -> Command {
Command::new("factor")
.about("factor numbers")
@ -59,7 +43,7 @@ impl Cmd for Factor {
}
fn path(&self) -> Option<crate::Path> {
self.path
Some(crate::Path::UsrBin)
}
}

View File

@ -1,30 +1,13 @@
use super::Cmd;
use crate::Path;
use clap::Command;
use std::{error::Error, process};
#[derive(Debug)]
pub struct False {
name: &'static str,
path: Option<Path>,
}
impl Default for False {
fn default() -> Self {
Self {
name: "false",
path: Some(crate::Path::Bin),
}
}
}
#[derive(Debug, Default)]
pub struct False;
impl Cmd for False {
fn name(&self) -> &str {
self.name
}
fn cli(&self) -> clap::Command {
Command::new(self.name)
Command::new("false")
.about("Does nothing unsuccessfully")
.long_about("Exit with a status code indicating failure")
.author("Nathan Fisher")
@ -34,7 +17,7 @@ impl Cmd for False {
process::exit(1);
}
fn path(&self) -> Option<Path> {
self.path
fn path(&self) -> Option<crate::Path> {
Some(crate::Path::Bin)
}
}

View File

@ -6,28 +6,12 @@ use std::{
};
use textwrap::{fill, wrap_algorithms::WrapAlgorithm};
#[derive(Debug)]
pub struct Fold {
name: &'static str,
path: Option<crate::Path>,
}
impl Default for Fold {
fn default() -> Self {
Self {
name: "fold",
path: Some(crate::Path::UsrBin),
}
}
}
#[derive(Debug, Default)]
pub struct Fold;
impl Cmd for Fold {
fn name(&self) -> &str {
self.name
}
fn cli(&self) -> Command {
Command::new(self.name)
Command::new("fold")
.about("Wrap each input line to fit in specified width")
.author("Nathan Fisher")
.after_long_help("With no FILE, or when FILE is -, read standard input")
@ -84,12 +68,12 @@ impl Cmd for Fold {
}
fn path(&self) -> Option<crate::Path> {
self.path
Some(crate::Path::UsrBin)
}
}
fn wrap_line(line: &str, args: &ArgMatches) {
let width = args.get_one("WIDTH").map(|x| *x).unwrap_or(80);
let width = args.get_one("WIDTH").map_or(80, |x| *x);
if args.get_flag("OPTIMAL") {
let line = line.replace('\t', " ");
let opts = textwrap::Options::new(width).wrap_algorithm(WrapAlgorithm::new_optimal_fit());

View File

@ -7,10 +7,6 @@ use std::io;
pub struct Groups;
impl Cmd for Groups {
fn name(&self) -> &str {
"groups"
}
fn cli(&self) -> clap::Command {
Command::new("groups")
.about("display current group names")

View File

@ -9,28 +9,12 @@ use std::{
};
use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor};
#[derive(Debug)]
pub struct Head {
name: &'static str,
path: Option<Path>,
}
impl Default for Head {
fn default() -> Self {
Self {
name: "head",
path: Some(crate::Path::Bin),
}
}
}
#[derive(Debug, Default)]
pub struct Head;
impl Cmd for Head {
fn name(&self) -> &str {
self.name
}
fn cli(&self) -> Command {
Command::new(self.name)
Command::new("head")
.author("Nathan Fisher")
.about("Display first lines of a file")
.long_about(
@ -133,7 +117,7 @@ impl Cmd for Head {
}
fn path(&self) -> Option<Path> {
self.path
Some(crate::Path::Bin)
}
}

View File

@ -1,27 +1,14 @@
use super::Cmd;
use crate::Path;
use clap::{Arg, ArgAction, ArgMatches, Command};
use std::{error::Error, io};
#[derive(Debug)]
pub struct Hostname {
name: &'static str,
path: Option<Path>,
}
pub const HOSTNAME: Hostname = Hostname {
name: "hostname",
path: Some(Path::Bin),
};
#[derive(Debug, Default)]
pub struct Hostname;
impl Cmd for Hostname {
fn name(&self) -> &str {
self.name
}
fn cli(&self) -> clap::Command {
Command::new(self.name)
.author("The JeanG3nie <jeang3nie@hitchhiker-linux.org>")
Command::new("hostname")
.author("Nathan Fisher")
.about("Prints the name of the current host. The super-user can set the host name by supplying an argument.")
.args([
Arg::new("NAME")
@ -62,6 +49,6 @@ impl Cmd for Hostname {
}
fn path(&self) -> Option<crate::Path> {
self.path
Some(crate::Path::Bin)
}
}

View File

@ -6,10 +6,6 @@ use std::{fs, io};
pub struct Link;
impl Cmd for Link {
fn name(&self) -> &str {
"link"
}
fn cli(&self) -> clap::Command {
Command::new("link")
.about("call the link function to create a link to a file")
@ -29,23 +25,17 @@ impl Cmd for Link {
let Some(matches) = matches else {
return Err(Box::new(io::Error::new(io::ErrorKind::Other, "no input")));
};
let f1 = match matches.get_one::<String>("file1") {
Some(s) => s,
None => {
return Err(Box::new(io::Error::new(
io::ErrorKind::Other,
"missing file 1",
)))
}
let Some(f1) = matches.get_one::<String>("file1") else {
return Err(Box::new(io::Error::new(
io::ErrorKind::Other,
"missing file 1",
)))
};
let f2 = match matches.get_one::<String>("file2") {
Some(s) => s,
None => {
return Err(Box::new(io::Error::new(
io::ErrorKind::Other,
"missing file 2",
)))
}
let Some(f2) = matches.get_one::<String>("file2") else {
return Err(Box::new(io::Error::new(
io::ErrorKind::Other,
"missing file 2",
)))
};
fs::hard_link(f1, f2)?;
if matches.get_flag("verbose") {

View File

@ -48,12 +48,12 @@ pub use {
};
pub trait Cmd: fmt::Debug + Sync {
fn name(&self) -> &str;
fn cli(&self) -> clap::Command;
fn run(&self, matches: Option<&ArgMatches>) -> Result<(), Box<dyn Error>>;
fn path(&self) -> Option<crate::Path>;
}
#[must_use]
pub fn get(name: &str) -> Option<Box<dyn Cmd>> {
match name {
"base64" => Some(Box::new(Base64::default())),

View File

@ -9,28 +9,12 @@ use std::{
process,
};
#[derive(Debug)]
pub struct Mountpoint {
name: &'static str,
path: Option<crate::Path>,
}
impl Default for Mountpoint {
fn default() -> Self {
Self {
name: "mountpoint",
path: Some(crate::Path::Bin),
}
}
}
#[derive(Debug, Default)]
pub struct Mountpoint;
impl Cmd for Mountpoint {
fn name(&self) -> &str {
self.name
}
fn cli(&self) -> clap::Command {
Command::new(self.name)
Command::new("mountpoint")
.about("see if a directory or file is a mountpoint")
.author("Nathan Fisher")
.after_long_help(
@ -77,12 +61,11 @@ impl Cmd for Mountpoint {
};
let file = matches.get_one::<String>("file").unwrap();
if matches.get_flag("fs-devno") {
match fs_devno(file)? {
Some(maj_min) => println!("{maj_min}"),
None => {
println!("{file} is not a mountpoint");
process::exit(32);
}
if let Some(maj_min) = fs_devno(file)? {
println!("{maj_min}");
} else {
println!("{file} is not a mountpoint");
process::exit(32);
}
} else if matches.get_flag("devno") {
let devno = devno(file)?;
@ -94,18 +77,16 @@ impl Cmd for Mountpoint {
println!("{file} is a mountpoint");
}
return Ok(());
} else {
if !matches.get_flag("quiet") {
println!("{file} is not a mountpoint");
}
process::exit(32);
} else if !matches.get_flag("quiet") {
println!("{file} is not a mountpoint");
}
process::exit(32);
}
Ok(())
}
fn path(&self) -> Option<crate::Path> {
self.path
Some(crate::Path::Bin)
}
}
@ -114,7 +95,7 @@ fn is_mountpoint(path: &str) -> Result<bool, Box<dyn Error>> {
let reader = BufReader::new(fd);
for line in reader.lines() {
let line = line?;
if let Some(mntpt) = line.split_whitespace().skip(1).next() {
if let Some(mntpt) = line.split_whitespace().nth(1) {
if mntpt == path {
return Ok(true);
}
@ -135,7 +116,7 @@ fn fs_devno(path: &str) -> Result<Option<String>, Box<dyn Error>> {
let line = line?;
let mut line = line.split_whitespace().skip(2);
if let Some(maj_min) = line.next() {
if let Some(mntpt) = line.skip(1).next() {
if let Some(mntpt) = line.nth(1) {
if mntpt == path {
return Ok(Some(String::from(maj_min)));
}

View File

@ -2,28 +2,12 @@ use super::Cmd;
use clap::Command;
use std::process;
#[derive(Debug)]
pub struct Nologin {
name: &'static str,
path: Option<crate::Path>,
}
impl Default for Nologin {
fn default() -> Self {
Self {
name: "nologin",
path: Some(crate::Path::Sbin),
}
}
}
#[derive(Debug, Default)]
pub struct Nologin;
impl Cmd for Nologin {
fn name(&self) -> &str {
self.name
}
fn cli(&self) -> clap::Command {
Command::new(self.name)
Command::new("nologin")
.author("Nathan Fisher")
.about("Denies a user account login ability")
}
@ -34,6 +18,6 @@ impl Cmd for Nologin {
}
fn path(&self) -> Option<crate::Path> {
self.path
Some(crate::Path::Sbin)
}
}

View File

@ -2,28 +2,12 @@ use super::Cmd;
use clap::{Arg, ArgAction, Command};
use std::io;
#[derive(Debug)]
pub struct Nproc {
name: &'static str,
path: Option<crate::Path>,
}
impl Default for Nproc {
fn default() -> Self {
Self {
name: "nproc",
path: Some(crate::Path::UsrBin),
}
}
}
#[derive(Debug, Default)]
pub struct Nproc;
impl Cmd for Nproc {
fn name(&self) -> &str {
self.name
}
fn cli(&self) -> clap::Command {
Command::new(self.name)
Command::new("nproc")
.author("Nathan Fisher")
.about("Print the number of processing units available")
.arg(
@ -48,6 +32,6 @@ impl Cmd for Nproc {
}
fn path(&self) -> Option<crate::Path> {
self.path
Some(crate::Path::UsrBin)
}
}

View File

@ -1,4 +1,4 @@
use crate::Cmd;
use super::Cmd;
use clap::{Arg, ArgAction, Command};
use std::{
fs::File,
@ -6,28 +6,12 @@ use std::{
};
use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor};
#[derive(Debug)]
pub struct Rev {
name: &'static str,
path: Option<crate::Path>,
}
impl Default for Rev {
fn default() -> Self {
Self {
name: "rev",
path: Some(crate::Path::UsrBin),
}
}
}
#[derive(Debug, Default)]
pub struct Rev;
impl Cmd for Rev {
fn name(&self) -> &str {
self.name
}
fn cli(&self) -> clap::Command {
Command::new(self.name)
Command::new("rev")
.about("reverse lines characterwise")
.author("Nathan Fisher")
.args([
@ -82,7 +66,7 @@ impl Cmd for Rev {
}
fn path(&self) -> Option<crate::Path> {
self.path
Some(crate::Path::UsrBin)
}
}

View File

@ -6,31 +6,10 @@ use std::{
process,
};
#[derive(Debug)]
pub struct Shitbox {
name: &'static str,
path: Option<crate::Path>,
}
impl Default for Shitbox {
fn default() -> Self {
Self {
name: "shitbox",
path: None,
}
}
}
pub const SHITBOX: Shitbox = Shitbox {
name: "shitbox",
path: None,
};
#[derive(Debug, Default)]
pub struct Shitbox;
impl Cmd for Shitbox {
fn name(&self) -> &str {
self.name
}
fn cli(&self) -> clap::Command {
let subcommands: Vec<Command> = {
let mut s = vec![];
@ -44,7 +23,7 @@ impl Cmd for Shitbox {
}
s
};
Command::new(self.name)
Command::new("shitbox")
.about("The box store multitool of embedded Linux")
.version(env!("CARGO_PKG_VERSION"))
.propagate_version(true)
@ -70,6 +49,6 @@ impl Cmd for Shitbox {
}
fn path(&self) -> Option<crate::Path> {
self.path
None
}
}

View File

@ -1,30 +1,13 @@
use super::Cmd;
use crate::Path;
use clap::{value_parser, Arg, ArgAction, ArgMatches, Command};
use std::{env, error::Error, thread, time::Duration};
#[derive(Debug)]
pub struct Sleep {
name: &'static str,
path: Option<Path>,
}
impl Default for Sleep {
fn default() -> Self {
Self {
name: "sleep",
path: Some(crate::Path::Bin),
}
}
}
#[derive(Debug, Default)]
pub struct Sleep;
impl Cmd for Sleep {
fn name(&self) -> &str {
self.name
}
fn cli(&self) -> clap::Command {
Command::new(self.name)
Command::new("sleep")
.about("Suspend execution for an interval of time")
.long_about(
"The sleep utility suspends execution for a minimum of the specified number of seconds.\n\
@ -54,7 +37,7 @@ impl Cmd for Sleep {
Ok(())
}
fn path(&self) -> Option<Path> {
self.path
fn path(&self) -> Option<crate::Path> {
Some(crate::Path::Bin)
}
}

View File

@ -1,30 +1,13 @@
use super::Cmd;
use crate::Path;
use clap::Command;
use std::{error::Error, process};
#[derive(Debug)]
pub struct True {
name: &'static str,
path: Option<Path>,
}
impl Default for True {
fn default() -> Self {
Self {
name: "true",
path: Some(crate::Path::Bin),
}
}
}
#[derive(Debug, Default)]
pub struct True;
impl Cmd for True {
fn name(&self) -> &str {
self.name
}
fn cli(&self) -> clap::Command {
Command::new(self.name)
Command::new("true")
.about("Does nothing successfully")
.long_about("Exit with a status code indicating success")
.author("Nathan Fisher")
@ -34,7 +17,7 @@ impl Cmd for True {
process::exit(0);
}
fn path(&self) -> Option<Path> {
self.path
fn path(&self) -> Option<crate::Path> {
Some(crate::Path::Bin)
}
}

View File

@ -6,10 +6,6 @@ use std::{env, fs::File, io, os::unix::prelude::MetadataExt, path::PathBuf, proc
pub struct Which;
impl Cmd for Which {
fn name(&self) -> &str {
"which"
}
fn cli(&self) -> clap::Command {
Command::new("which")
.about("Write the full path of COMMAND(s) to standard output")
@ -31,12 +27,11 @@ impl Cmd for Which {
let mut failures = 0;
if let Some(commands) = matches.get_many::<String>("COMMAND") {
for command in commands {
match which(command, &path) {
Some(p) => println!("{p}"),
None => {
println!("{}: no {} in ({})", self.name(), command, &rawpath);
failures += 1;
}
if let Some(p) = which(command, &path) {
println!("{p}");
} else {
println!("which: no {} in ({})", command, &rawpath);
failures += 1;
}
}
} else {

View File

@ -1,19 +1,14 @@
use std::ffi::CStr;
use {
super::Cmd,
clap::Command,
libc::{geteuid, getpwuid},
std::ffi::CStr,
};
#[derive(Debug, Default)]
pub struct Whoami;
impl Cmd for Whoami {
fn name(&self) -> &str {
"whoami"
}
fn cli(&self) -> clap::Command {
Command::new("whoami")
.about("print effective user name")

View File

@ -2,28 +2,12 @@ use super::Cmd;
use clap::{Arg, Command};
use std::io;
#[derive(Debug)]
pub struct Yes {
name: &'static str,
path: Option<crate::Path>,
}
impl Default for Yes {
fn default() -> Self {
Self {
name: "yes",
path: Some(crate::Path::UsrBin),
}
}
}
#[derive(Debug, Default)]
pub struct Yes;
impl Cmd for Yes {
fn name(&self) -> &str {
self.name
}
fn cli(&self) -> clap::Command {
Command::new(self.name)
Command::new("yes")
.about("output a string repeatedly until killed")
.author("Nathan Fisher")
.arg(Arg::new("msg").num_args(1).default_value("y"))
@ -40,6 +24,6 @@ impl Cmd for Yes {
}
fn path(&self) -> Option<crate::Path> {
self.path
Some(crate::Path::UsrBin)
}
}

View File

@ -16,14 +16,13 @@ pub enum Path {
}
impl Path {
#[must_use]
pub fn to_str(&self, usr: bool) -> &'static str {
match self {
Self::Bin => "bin",
Self::UsrBin if usr => "usr/bin",
Self::UsrBin => "bin",
Self::Sbin => "sbin",
Self::UsrSbin if usr => "usr/sbin",
Self::UsrSbin => "sbin",
Self::Bin | Self::UsrBin => "bin",
Self::Sbin | Self::UsrSbin => "sbin",
}
}
}

View File

@ -25,35 +25,28 @@ pub fn get_eusername<'a>() -> Result<&'a str, std::str::Utf8Error> {
}
pub fn get_uid_for_name(name: &str) -> Option<u32> {
let user = match CString::new(name.as_bytes()) {
Ok(n) => n,
Err(_) => return None,
};
let uid = unsafe {
let Ok(user) = CString::new(name.as_bytes()) else { return None };
unsafe {
let pw = libc::getpwnam(user.as_ptr());
if pw.is_null() {
None
} else {
Some((*pw).pw_uid)
}
};
uid
}
}
#[must_use]
pub fn get_pgid_for_name(name: &str) -> Option<u32> {
let user = match CString::new(name.as_bytes()) {
Ok(n) => n,
Err(_) => return None,
};
let gid = unsafe {
let Ok(user) = CString::new(name.as_bytes()) else { return None };
unsafe {
let pw = libc::getpwnam(user.as_ptr());
if pw.is_null() {
None
} else {
Some((*pw).pw_gid)
}
};
gid
}
}
pub fn get_grpname<'a>() -> Result<&'a str, std::str::Utf8Error> {
@ -89,6 +82,7 @@ pub fn get_gids() -> Result<Vec<u32>, num::TryFromIntError> {
Ok(buf)
}
#[allow(clippy::cast_sign_loss)]
pub fn get_gids_for_name(name: &str) -> Result<Vec<u32>, Box<dyn Error>> {
let gid = match get_pgid_for_name(name) {
Some(g) => g as libc::gid_t,
@ -111,7 +105,7 @@ pub fn get_gids_for_name(name: &str) -> Result<Vec<u32>, Box<dyn Error>> {
)));
}
}
Ok(buf[0..ct as usize].iter().map(|x| *x as u32).collect())
Ok(buf[0..ct as usize].to_vec())
}
pub fn get_group_names() -> Result<Vec<String>, Box<dyn Error>> {