Add sync applet

This commit is contained in:
Nathan Fisher 2023-01-13 12:09:10 -05:00
parent a8c8ba5819
commit 5560cf55a9
2 changed files with 82 additions and 4 deletions

View File

@ -33,7 +33,7 @@ mod rm;
mod rmdir;
pub mod shitbox;
pub mod sleep;
mod sync;
pub mod sync;
pub mod r#true;
pub mod which;
pub mod whoami;
@ -43,8 +43,8 @@ pub use {
self::hostname::Hostname, base32::Base32, base64::Base64, basename::Basename,
bootstrap::Bootstrap, clear::Clear, dirname::Dirname, echo::Echo, factor::Factor, fold::Fold,
groups::Groups, head::Head, link::Link, mountpoint::Mountpoint, nologin::Nologin, nproc::Nproc,
r#false::False, r#true::True, rev::Rev, shitbox::Shitbox, sleep::Sleep, which::Which,
whoami::Whoami, yes::Yes,
r#false::False, r#true::True, rev::Rev, shitbox::Shitbox, sleep::Sleep, sync::SYnc,
which::Which, whoami::Whoami, yes::Yes,
};
pub trait Cmd: fmt::Debug + Sync {
@ -75,6 +75,7 @@ pub fn get(name: &str) -> Option<Box<dyn Cmd>> {
"rev" => Some(Box::new(Rev::default())),
"shitbox" => Some(Box::new(Shitbox::default())),
"sleep" => Some(Box::new(Sleep::default())),
"sync" => Some(Box::new(SYnc::default())),
"true" => Some(Box::new(True::default())),
"which" => Some(Box::new(Which::default())),
"whoami" => Some(Box::new(Whoami::default())),
@ -83,7 +84,7 @@ pub fn get(name: &str) -> Option<Box<dyn Cmd>> {
}
}
pub static COMMANDS: [&'static str; 24] = [
pub static COMMANDS: [&'static str; 25] = [
"base32",
"base64",
"basename",
@ -104,6 +105,7 @@ pub static COMMANDS: [&'static str; 24] = [
"rev",
"sleep",
"shitbox",
"sync",
"true",
"which",
"whoami",

View File

@ -1 +1,77 @@
use super::Cmd;
use clap::{Arg, ArgAction, Command};
use std::{error::Error, io, ffi::CString};
#[derive(Debug, Default)]
pub struct SYnc;
impl Cmd for SYnc {
fn cli(&self) -> clap::Command {
Command::new("sync")
.about("force completion of pending disk writes (flush cache)")
.author("Nathan Fisher")
.version(env!("CARGO_PKG_VERSION"))
.args([
Arg::new("data")
.short('d')
.long("data")
.help("sync only file data, no unneeded metadata")
.conflicts_with("fs")
.action(ArgAction::SetTrue),
Arg::new("fs")
.short('f')
.long("file-system")
.help("sync the file systems that contain the files")
.action(ArgAction::SetTrue),
Arg::new("FILE")
.help(
"If one or more files are specified, sync only them, or \
their containing file systems.",
)
.num_args(0..),
])
}
fn run(&self, matches: Option<&clap::ArgMatches>) -> Result<(), Box<dyn Error>> {
let Some(matches) = matches else {
return Err(Box::new(io::Error::new(io::ErrorKind::Other, "no input")));
};
if let Some(files) = matches.get_many::<String>("FILE") {
for f in files {
let file = CString::new(f.as_bytes())?;
if matches.get_flag("data") {
let rc = unsafe {
let fd = libc::open(file.as_ptr(), libc::O_RDWR | libc::O_NOATIME);
libc::fdatasync(fd)
};
if rc != 0 {
return Err(Box::new(io::Error::last_os_error()));
}
} else if matches.get_flag("fs") {
let rc = unsafe {
let fd = libc::open(file.as_ptr(), libc::O_RDWR | libc::O_NOATIME);
libc::syncfs(fd)
};
if rc != 0 {
return Err(Box::new(io::Error::last_os_error()));
}
} else {
let rc = unsafe {
let fd = libc::open(file.as_ptr(), libc::O_RDWR | libc::O_NOATIME);
libc::fsync(fd)
};
if rc != 0 {
return Err(Box::new(io::Error::last_os_error()));
}
}
}
} else {
unsafe { libc::sync(); }
}
Ok(())
}
fn path(&self) -> Option<crate::Path> {
Some(crate::Path::Bin)
}
}