Skip to content

Commit

Permalink
Ensure 'sudo' hint is printed when rmest is run without root
Browse files Browse the repository at this point in the history
In the previous change this was fixed, however, the hint printing
was embedded in lib.rs which would be inherited by other programs
that may embed rmesg.

This change gives it a proper enum in
RMesgError::OperationNotPermitted and allows callers to know when
an operation has failed due to permissions, allowing
every consumer to implement their appropriate logic to surface
that error.
  • Loading branch information
archis-polyverse committed Jul 2, 2021
1 parent 81291d1 commit f30d5de
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 30 deletions.
5 changes: 1 addition & 4 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,7 @@ impl Display for RMesgError {
"Failed to add a Duration to SystemTime".to_owned(),
Self::KLogTimestampsDisabled => "Kernel Log timestamps are disabled".to_owned(),
Self::DevKMsgFileOpenError(s) => s.to_owned(),
Self::OperationNotPermitted(s) => format!(
"OperationNotPermitted: {}\nHint: Try running with 'sudo' or as root.",
s
),
Self::OperationNotPermitted(s) => format!("OperationNotPermitted: {}", s),
}
)
}
Expand Down
13 changes: 9 additions & 4 deletions src/klogctl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -424,10 +424,15 @@ pub fn safely_wrapped_klogctl(klogtype: KLogType, buf_u8: &mut [u8]) -> Result<u

if response_cint < 0 {
let err = errno();
return Err(RMesgError::InternalError(format!(
"Request ({}) to klogctl failed. errno={}",
klogtype, err
)));

if err.0 == libc::EPERM {
return Err(RMesgError::OperationNotPermitted(format!("{}", klogtype)));
} else {
return Err(RMesgError::InternalError(format!(
"Request ({}) to klogctl failed. errno={}",
klogtype, err
)));
}
}

let response = match usize::try_from(response_cint) {
Expand Down
47 changes: 34 additions & 13 deletions src/kmsgfile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,17 @@ impl KMsgEntriesIter {
let file = match stdfs::File::open(path) {
Ok(fc) => fc,
Err(e) => {
return Err(RMesgError::DevKMsgFileOpenError(format!(
"Unable to open file {}: {}",
path, e
)))
if e.raw_os_error() == Some(libc::EPERM) {
return Err(RMesgError::OperationNotPermitted(format!(
"Open File {}",
path
)));
} else {
return Err(RMesgError::DevKMsgFileOpenError(format!(
"Unable to open file {}: {}",
path, e
)));
}
}
};

Expand Down Expand Up @@ -148,10 +155,17 @@ impl KMsgEntriesStream {
let file = match tokiofs::File::open(path).await {
Ok(fc) => fc,
Err(e) => {
return Err(RMesgError::DevKMsgFileOpenError(format!(
"Unable to open file {}: {}",
path, e
)))
if e.raw_os_error() == Some(libc::EPERM) {
return Err(RMesgError::OperationNotPermitted(format!(
"Open File {}",
path
)));
} else {
return Err(RMesgError::DevKMsgFileOpenError(format!(
"Unable to open file {}: {}",
path, e
)));
}
}
};

Expand Down Expand Up @@ -209,7 +223,7 @@ pub fn kmsg_raw(file_override: Option<String>) -> Result<String, RMesgError> {
let file = match stdfs::File::open(path) {
Ok(fc) => fc,
Err(e) => {
if std::io::Error::last_os_error().raw_os_error() == Some(libc::EPERM) {
if e.raw_os_error() == Some(libc::EPERM) {
return Err(RMesgError::OperationNotPermitted(format!(
"Open File {}",
path
Expand All @@ -229,10 +243,17 @@ pub fn kmsg_raw(file_override: Option<String>) -> Result<String, RMesgError> {
match noblock_file.read_available_to_string(&mut file_contents) {
Ok(_) => {}
Err(e) => {
return Err(RMesgError::DevKMsgFileOpenError(format!(
"Unable to read from file {}: {}",
path, e
)))
if e.raw_os_error() == Some(libc::EPERM) {
return Err(RMesgError::OperationNotPermitted(format!(
"Read from File {}",
path
)));
} else {
return Err(RMesgError::DevKMsgFileOpenError(format!(
"Unable to read from file {}: {}",
path, e
)));
}
}
}

Expand Down
60 changes: 51 additions & 9 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
/// This CLI builds on top of the eponymous crate and provides a command-line utility.
///
use clap::{App, Arg};
use futures_util::stream::TryStreamExt;
use futures_util::stream::StreamExt;
use std::error::Error;

#[derive(Debug)]
Expand All @@ -20,10 +20,32 @@ async fn main() -> Result<(), Box<dyn Error>> {
if !opts.follow {
nofollow(opts);
} else {
let mut entries = rmesg::logs_stream(opts.backend, opts.clear, opts.raw).await?;
let mut entries = match rmesg::logs_stream(opts.backend, opts.clear, opts.raw).await {
Ok(entries) => entries,
Err(e) => {
eprintln!("Unable to get logs stream: {}", e);

while let Some(entry) = entries.try_next().await? {
println!("{}", entry);
if let rmesg::error::RMesgError::OperationNotPermitted(_) = e {
eprintln!("\nHint: Try using 'sudo' or run the program as root/superuser.");
}

return Ok(());
}
};

while let Some(result) = entries.next().await {
match result {
Ok(entry) => println!("{}", entry),
Err(e) => {
eprintln!("Unable to get logs stream: {}", e);

if let rmesg::error::RMesgError::OperationNotPermitted(_) = e {
eprintln!("\nHint: Try using 'sudo' or run the program as root/superuser.");
}

return Ok(());
}
}
}
}

Expand All @@ -32,12 +54,32 @@ async fn main() -> Result<(), Box<dyn Error>> {

fn nofollow(opts: Options) {
if opts.raw {
let raw = rmesg::logs_raw(opts.backend, opts.clear).unwrap();
print!("{}", raw)
match rmesg::logs_raw(opts.backend, opts.clear) {
Ok(raw) => {
print!("{}", raw)
}
Err(e) => {
eprintln!("Unable to get raw logs: {}", e);

if let rmesg::error::RMesgError::OperationNotPermitted(_) = e {
eprintln!("\nHint: Try using 'sudo' or run the program as root/superuser.");
}
}
}
} else {
let entries = rmesg::log_entries(opts.backend, opts.clear).unwrap();
for entry in entries {
println!("{}", entry)
match rmesg::log_entries(opts.backend, opts.clear) {
Ok(entries) => {
for entry in entries {
println!("{}", entry)
}
}
Err(e) => {
eprintln!("Unable to get log entries: {}", e);

if let rmesg::error::RMesgError::OperationNotPermitted(_) = e {
eprintln!("\nHint: Try using 'sudo' or run the program as root/superuser.");
}
}
}
}
}
Expand Down

0 comments on commit f30d5de

Please sign in to comment.