whoami: Cleanup

- Use modern conventions
- Restrict the scope of unsafe
- Do not use deprecated `std::mem::unitialized()`
- Do not bake unicode into design
This commit is contained in:
Jan Verbeek 2021-08-27 20:36:26 +02:00
parent e9d63519dd
commit 4555c85564
5 changed files with 41 additions and 59 deletions

1
Cargo.lock generated
View file

@ -3222,6 +3222,7 @@ name = "uu_whoami"
version = "0.0.7"
dependencies = [
"clap",
"libc",
"uucore",
"uucore_procs",
"winapi 0.3.9",

View file

@ -16,12 +16,15 @@ path = "src/whoami.rs"
[dependencies]
clap = { version = "2.33", features = ["wrap_help"] }
uucore = { version=">=0.0.9", package="uucore", path="../../uucore", features=["entries", "wide"] }
uucore = { version=">=0.0.9", package="uucore", path="../../uucore", features=["entries"] }
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
[target.'cfg(target_os = "windows")'.dependencies]
winapi = { version = "0.3", features = ["lmcons"] }
[target.'cfg(unix)'.dependencies]
libc = "0.2.42"
[[bin]]
name = "whoami"
path = "src/main.rs"

View file

@ -8,14 +8,14 @@
* file that was distributed with this source code.
*/
// spell-checker:ignore (ToDO) getusername
use std::ffi::OsString;
use std::io;
use std::io::Result;
use uucore::entries::uid2usr;
use uucore::libc::geteuid;
pub unsafe fn get_username() -> Result<String> {
// Get effective user id
let uid = geteuid();
uid2usr(uid)
pub fn get_username() -> io::Result<OsString> {
// SAFETY: getuid() does nothing with memory and is always successful.
let uid = unsafe { libc::geteuid() };
// uid2usr should arguably return an OsString but currently doesn't
uid2usr(uid).map(Into::into)
}

View file

@ -7,22 +7,23 @@
* file that was distributed with this source code.
*/
extern crate winapi;
use std::ffi::OsString;
use std::io;
use std::os::windows::ffi::OsStringExt;
use self::winapi::shared::lmcons;
use self::winapi::shared::minwindef;
use self::winapi::um::{winbase, winnt};
use std::io::{Error, Result};
use std::mem;
use uucore::wide::FromWide;
use winapi::shared::lmcons;
use winapi::shared::minwindef::DWORD;
use winapi::um::winbase;
pub unsafe fn get_username() -> Result<String> {
#[allow(deprecated)]
let mut buffer: [winnt::WCHAR; lmcons::UNLEN as usize + 1] = mem::uninitialized();
let mut len = buffer.len() as minwindef::DWORD;
if winbase::GetUserNameW(buffer.as_mut_ptr(), &mut len) == 0 {
return Err(Error::last_os_error());
pub fn get_username() -> io::Result<OsString> {
const BUF_LEN: DWORD = lmcons::UNLEN + 1;
let mut buffer = [0_u16; BUF_LEN as usize];
let mut len = BUF_LEN;
// SAFETY: buffer.len() == len
unsafe {
if winbase::GetUserNameW(buffer.as_mut_ptr(), &mut len) == 0 {
return Err(io::Error::last_os_error());
}
}
let username = String::from_wide(&buffer[..len as usize - 1]);
Ok(username)
Ok(OsString::from_wide(&buffer[..len as usize - 1]))
}

View file

@ -1,5 +1,3 @@
use clap::App;
// * This file is part of the uutils coreutils package.
// *
// * (c) Jordi Boggiano <j.boggiano@seld.be>
@ -14,46 +12,25 @@ extern crate clap;
#[macro_use]
extern crate uucore;
use uucore::error::{UResult, USimpleError};
use clap::App;
use uucore::display::println_verbatim;
use uucore::error::{FromIo, UResult};
mod platform;
static ABOUT: &str = "Print the current username.";
#[uucore_procs::gen_uumain]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let app = uu_app();
if let Err(err) = app.get_matches_from_safe(args) {
if err.kind == clap::ErrorKind::HelpDisplayed
|| err.kind == clap::ErrorKind::VersionDisplayed
{
println!("{}", err);
Ok(())
} else {
return Err(USimpleError::new(1, format!("{}", err)));
}
} else {
exec()
}
uu_app().get_matches_from(args);
let username = platform::get_username().map_err_context(|| "failed to get username".into())?;
println_verbatim(&username).map_err_context(|| "failed to print username".into())?;
Ok(())
}
pub fn uu_app() -> App<'static, 'static> {
app_from_crate!()
}
pub fn exec() -> UResult<()> {
unsafe {
match platform::get_username() {
Ok(username) => {
println!("{}", username);
Ok(())
}
Err(err) => match err.raw_os_error() {
Some(0) | None => Err(USimpleError::new(1, "failed to get username")),
Some(_) => Err(USimpleError::new(
1,
format!("failed to get username: {}", err),
)),
},
}
}
App::new(uucore::util_name())
.version(crate_version!())
.about(ABOUT)
}