mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 11:37:44 +00:00
Merge pull request #968 from knight42/uucore-entries
Add uucore::entries to get passwd/group file entry
This commit is contained in:
commit
8781df81fb
24 changed files with 588 additions and 663 deletions
|
@ -8,19 +8,18 @@ name = "uu_chown"
|
|||
path = "chown.rs"
|
||||
|
||||
[dependencies]
|
||||
getopts = "*"
|
||||
glob = "*"
|
||||
libc = "*"
|
||||
uucore = { path="../uucore" }
|
||||
walkdir = "0.1"
|
||||
|
||||
[dependencies.uucore]
|
||||
path = "../uucore"
|
||||
default-features = false
|
||||
features = ["entries"]
|
||||
|
||||
[dependencies.clippy]
|
||||
version = "*"
|
||||
optional = true
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
||||
[[bin]]
|
||||
name = "chown"
|
||||
path = "main.rs"
|
||||
|
|
|
@ -11,20 +11,14 @@
|
|||
#![cfg_attr(feature="clippy", feature(plugin))]
|
||||
#![cfg_attr(feature="clippy", plugin(clippy))]
|
||||
|
||||
extern crate libc;
|
||||
use libc::{uid_t, gid_t, c_char, c_int};
|
||||
|
||||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
extern crate getopts;
|
||||
use getopts::Options;
|
||||
use uucore::libc::{self, uid_t, gid_t, lchown};
|
||||
pub use uucore::entries::{self, Locate, Passwd, Group};
|
||||
|
||||
extern crate walkdir;
|
||||
use walkdir::WalkDir;
|
||||
|
||||
pub mod passwd;
|
||||
|
||||
use std::fs::{self, Metadata};
|
||||
use std::os::unix::fs::MetadataExt;
|
||||
|
||||
|
@ -37,21 +31,15 @@ use std::convert::AsRef;
|
|||
use std::ffi::CString;
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
|
||||
static NAME: &'static str = "chown";
|
||||
static VERSION: &'static str = env!("CARGO_PKG_VERSION");
|
||||
static SYNTAX: &'static str = "[OPTION]... [OWNER][:[GROUP]] FILE...\n chown [OPTION]... --reference=RFILE FILE...";
|
||||
static SUMMARY: &'static str = "change file owner and group";
|
||||
|
||||
const FTS_COMFOLLOW: u8 = 1;
|
||||
const FTS_PHYSICAL: u8 = 1 << 1;
|
||||
const FTS_LOGICAL: u8 = 1 << 2;
|
||||
|
||||
extern "C" {
|
||||
#[cfg_attr(all(target_os = "macos", target_arch = "x86"), link_name = "lchown$UNIX2003")]
|
||||
pub fn lchown(path: *const c_char, uid: uid_t, gid: gid_t) -> c_int;
|
||||
}
|
||||
|
||||
pub fn uumain(args: Vec<String>) -> i32 {
|
||||
let mut opts = Options::new();
|
||||
|
||||
let mut opts = new_coreopts!(SYNTAX, SUMMARY, "");
|
||||
opts.optflag("c",
|
||||
"changes",
|
||||
"like verbose but report only when a change is made");
|
||||
|
@ -85,16 +73,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
"traverse every symbolic link to a directory encountered");
|
||||
opts.optflag("P", "", "do not traverse any symbolic links (default)");
|
||||
|
||||
opts.optflag("", "help", "display this help and exit");
|
||||
opts.optflag("", "version", "output version information and exit");
|
||||
|
||||
let matches = match opts.parse(&args[1..]) {
|
||||
Ok(m) => m,
|
||||
Err(f) => {
|
||||
disp_err!("{}", f);
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
let matches = opts.parse(args.clone());
|
||||
|
||||
let mut bit_flag = FTS_PHYSICAL;
|
||||
let mut preserve_root = false;
|
||||
|
@ -121,13 +100,6 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
}
|
||||
}
|
||||
|
||||
if matches.opt_present("help") {
|
||||
return help();
|
||||
} else if matches.opt_present("version") {
|
||||
println!("{} {}", NAME, VERSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
let recursive = matches.opt_present("recursive");
|
||||
if recursive {
|
||||
if bit_flag == FTS_PHYSICAL {
|
||||
|
@ -222,25 +194,25 @@ fn parse_spec(spec: &str) -> Result<(Option<u32>, Option<u32>), String> {
|
|||
let usr_grp = args.len() == 2 && !args[0].is_empty() && !args[1].is_empty();
|
||||
|
||||
if usr_only {
|
||||
Ok((Some(match passwd::getuid(args[0]) {
|
||||
Ok(uid) => uid,
|
||||
Err(_) => return Err(format!("invalid user: ‘{}’", spec)),
|
||||
Ok((Some(match Passwd::locate(args[0]) {
|
||||
Ok(v) => v.uid(),
|
||||
_ => return Err(format!("invalid user: ‘{}’", spec)),
|
||||
}),
|
||||
None))
|
||||
} else if grp_only {
|
||||
Ok((None,
|
||||
Some(match passwd::getgid(args[1]) {
|
||||
Ok(gid) => gid,
|
||||
Err(_) => return Err(format!("invalid group: ‘{}’", spec)),
|
||||
Some(match Group::locate(args[1]) {
|
||||
Ok(v) => v.gid(),
|
||||
_ => return Err(format!("invalid group: ‘{}’", spec)),
|
||||
})))
|
||||
} else if usr_grp {
|
||||
Ok((Some(match passwd::getuid(args[0]) {
|
||||
Ok(uid) => uid,
|
||||
Err(_) => return Err(format!("invalid user: ‘{}’", spec)),
|
||||
Ok((Some(match Passwd::locate(args[0]) {
|
||||
Ok(v) => v.uid(),
|
||||
_ => return Err(format!("invalid user: ‘{}’", spec)),
|
||||
}),
|
||||
Some(match passwd::getgid(args[1]) {
|
||||
Ok(gid) => gid,
|
||||
Err(_) => return Err(format!("invalid group: ‘{}’", spec)),
|
||||
Some(match Group::locate(args[1]) {
|
||||
Ok(v) => v.gid(),
|
||||
_ => return Err(format!("invalid group: ‘{}’", spec)),
|
||||
})))
|
||||
} else {
|
||||
Ok((None, None))
|
||||
|
@ -401,10 +373,10 @@ impl Chowner {
|
|||
if self.verbosity == Verbose {
|
||||
println!("failed to change ownership of {} from {}:{} to {}:{}",
|
||||
path.display(),
|
||||
passwd::uid2usr(meta.uid()).unwrap(),
|
||||
passwd::gid2grp(meta.gid()).unwrap(),
|
||||
passwd::uid2usr(dest_uid).unwrap(),
|
||||
passwd::gid2grp(dest_gid).unwrap());
|
||||
entries::uid2usr(meta.uid()).unwrap(),
|
||||
entries::gid2grp(meta.gid()).unwrap(),
|
||||
entries::uid2usr(dest_uid).unwrap(),
|
||||
entries::gid2grp(dest_gid).unwrap());
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -416,18 +388,18 @@ impl Chowner {
|
|||
Changes | Verbose => {
|
||||
println!("changed ownership of {} from {}:{} to {}:{}",
|
||||
path.display(),
|
||||
passwd::uid2usr(meta.uid()).unwrap(),
|
||||
passwd::gid2grp(meta.gid()).unwrap(),
|
||||
passwd::uid2usr(dest_uid).unwrap(),
|
||||
passwd::gid2grp(dest_gid).unwrap());
|
||||
entries::uid2usr(meta.uid()).unwrap(),
|
||||
entries::gid2grp(meta.gid()).unwrap(),
|
||||
entries::uid2usr(dest_uid).unwrap(),
|
||||
entries::gid2grp(dest_gid).unwrap());
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
} else if self.verbosity == Verbose {
|
||||
println!("ownership of {} retained as {}:{}",
|
||||
path.display(),
|
||||
passwd::uid2usr(dest_uid).unwrap(),
|
||||
passwd::gid2grp(dest_gid).unwrap());
|
||||
entries::uid2usr(dest_uid).unwrap(),
|
||||
entries::gid2grp(dest_gid).unwrap());
|
||||
}
|
||||
}
|
||||
ret
|
||||
|
@ -444,54 +416,3 @@ impl Chowner {
|
|||
}
|
||||
}
|
||||
|
||||
fn help() -> i32 {
|
||||
println!(r#"
|
||||
Usage: {0} [OPTION]... [OWNER][:[GROUP]] FILE...
|
||||
or: {0} [OPTION]... --reference=RFILE FILE...
|
||||
Change the owner and/or group of each FILE to OWNER and/or GROUP.
|
||||
With --reference, change the owner and group of each FILE to those of RFILE.
|
||||
|
||||
-c, --changes like verbose but report only when a change is made
|
||||
-f, --silent, --quiet suppress most error messages
|
||||
-v, --verbose output a diagnostic for every file processed
|
||||
--dereference affect the referent of each symbolic link (this is
|
||||
the default), rather than the symbolic link itself
|
||||
-h, --no-dereference affect symbolic links instead of any referenced file
|
||||
(useful only on systems that can change the
|
||||
ownership of a symlink)
|
||||
--from=CURRENT_OWNER:CURRENT_GROUP
|
||||
change the owner and/or group of each file only if
|
||||
its current owner and/or group match those specified
|
||||
here. Either may be omitted, in which case a match
|
||||
is not required for the omitted attribute
|
||||
--no-preserve-root do not treat '/' specially (the default)
|
||||
--preserve-root fail to operate recursively on '/'
|
||||
--reference=RFILE use RFILE's owner and group rather than
|
||||
specifying OWNER:GROUP values
|
||||
-R, --recursive operate on files and directories recursively
|
||||
|
||||
The following options modify how a hierarchy is traversed when the -R
|
||||
option is also specified. If more than one is specified, only the final
|
||||
one takes effect.
|
||||
|
||||
-H if a command line argument is a symbolic link
|
||||
to a directory, traverse it
|
||||
-L traverse every symbolic link to a directory
|
||||
encountered
|
||||
-P do not traverse any symbolic links (default)
|
||||
|
||||
--help display this help and exit
|
||||
--version output version information and exit
|
||||
|
||||
Owner is unchanged if missing. Group is unchanged if missing, but changed
|
||||
to login group if implied by a ':' following a symbolic OWNER.
|
||||
OWNER and GROUP may be numeric as well as symbolic.
|
||||
|
||||
Examples:
|
||||
chown root /u Change the owner of /u to "root".
|
||||
chown root:staff /u Likewise, but also change its group to "staff".
|
||||
chown -hR root /u Change the owner of /u and subfiles to "root".
|
||||
"#,
|
||||
NAME);
|
||||
0
|
||||
}
|
||||
|
|
|
@ -1,59 +0,0 @@
|
|||
// (c) Jian Zeng <Anonymousknight96@gmail.com>
|
||||
|
||||
extern crate uucore;
|
||||
use self::uucore::c_types::{getpwuid, getpwnam, getgrgid, getgrnam};
|
||||
|
||||
use std::ptr;
|
||||
use std::ffi::{CString, CStr};
|
||||
use std::io::Result as IOResult;
|
||||
use std::io::{ErrorKind, Error};
|
||||
|
||||
macro_rules! gen_func {
|
||||
($fun:ident, $getid:ident, $getnm:ident, $field:ident) => (
|
||||
pub fn $fun(name_or_id: &str) -> IOResult<u32> {
|
||||
if let Ok(id) = name_or_id.parse::<u32>() {
|
||||
let data = unsafe {
|
||||
$getid(id)
|
||||
};
|
||||
if !data.is_null() {
|
||||
return Ok(id);
|
||||
} else {
|
||||
// last_os_error() returns success
|
||||
return Err(Error::new(ErrorKind::NotFound, format!("No such id `{}`", id)));
|
||||
}
|
||||
} else {
|
||||
let name = CString::new(name_or_id).unwrap();
|
||||
let data = unsafe {
|
||||
$getnm(name.as_ptr())
|
||||
};
|
||||
if !data.is_null() {
|
||||
return Ok(unsafe {
|
||||
ptr::read(data).$field
|
||||
});
|
||||
} else {
|
||||
// last_os_error() returns success
|
||||
return Err(Error::new(ErrorKind::NotFound, format!("No such name `{}`", name_or_id)));
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
($fun:ident, $getid:ident, $field:ident) => (
|
||||
pub fn $fun(id: u32) -> IOResult<String> {
|
||||
let data = unsafe {
|
||||
$getid(id)
|
||||
};
|
||||
if !data.is_null() {
|
||||
Ok(unsafe {
|
||||
CStr::from_ptr(ptr::read(data).$field).to_string_lossy().into_owned()
|
||||
})
|
||||
} else {
|
||||
Err(Error::new(ErrorKind::NotFound, format!("No such id `{}`", id)))
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
gen_func!(getuid, getpwuid, getpwnam, pw_uid);
|
||||
gen_func!(getgid, getgrgid, getgrnam, gr_gid);
|
||||
gen_func!(uid2usr, getpwuid, pw_name);
|
||||
gen_func!(gid2grp, getgrgid, gr_name);
|
|
@ -9,8 +9,11 @@ path = "chroot.rs"
|
|||
|
||||
[dependencies]
|
||||
getopts = "*"
|
||||
libc = "*"
|
||||
uucore = { path="../uucore" }
|
||||
|
||||
[dependencies.uucore]
|
||||
path = "../uucore"
|
||||
default-features = false
|
||||
features = ["entries"]
|
||||
|
||||
[[bin]]
|
||||
name = "chroot"
|
||||
|
|
|
@ -4,39 +4,25 @@
|
|||
* This file is part of the uutils coreutils package.
|
||||
*
|
||||
* (c) Vsevolod Velichko <torkvemada@sorokdva.net>
|
||||
* (c) Jian Zeng <anonymousknight96 AT gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
extern crate getopts;
|
||||
extern crate libc;
|
||||
|
||||
#[macro_use]
|
||||
extern crate uucore;
|
||||
use uucore::libc::{self, setgid, setuid, chroot, setgroups};
|
||||
use uucore::entries;
|
||||
|
||||
use getopts::Options;
|
||||
use libc::{setgid, setuid};
|
||||
use std::ffi::CString;
|
||||
use std::io::{Error, Write};
|
||||
use std::iter::FromIterator;
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
use uucore::c_types::{get_pw_from_args, get_group};
|
||||
|
||||
extern {
|
||||
fn chroot(path: *const libc::c_char) -> libc::c_int;
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "macos", target_os = "freebsd"))]
|
||||
extern {
|
||||
fn setgroups(size: libc::c_int, list: *const libc::gid_t) -> libc::c_int;
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
extern {
|
||||
fn setgroups(size: libc::size_t, list: *const libc::gid_t) -> libc::c_int;
|
||||
}
|
||||
|
||||
static NAME: &'static str = "chroot";
|
||||
static VERSION: &'static str = env!("CARGO_PKG_VERSION");
|
||||
|
@ -146,9 +132,9 @@ fn enter_chroot(root: &Path) {
|
|||
|
||||
fn set_main_group(group: &str) {
|
||||
if !group.is_empty() {
|
||||
let group_id = match get_group(group) {
|
||||
None => crash!(1, "no such group: {}", group),
|
||||
Some(g) => g.gr_gid
|
||||
let group_id = match entries::grp2gid(group) {
|
||||
Ok(g) => g,
|
||||
_ => crash!(1, "no such group: {}", group),
|
||||
};
|
||||
let err = unsafe { setgid(group_id) };
|
||||
if err != 0 {
|
||||
|
@ -177,9 +163,9 @@ fn set_groups_from_str(groups: &str) {
|
|||
if !groups.is_empty() {
|
||||
let groups_vec: Vec<libc::gid_t> = FromIterator::from_iter(
|
||||
groups.split(',').map(
|
||||
|x| match get_group(x) {
|
||||
None => crash!(1, "no such group: {}", x),
|
||||
Some(g) => g.gr_gid
|
||||
|x| match entries::grp2gid(x) {
|
||||
Ok(g) => g,
|
||||
_ => crash!(1, "no such group: {}", x),
|
||||
})
|
||||
);
|
||||
let err = set_groups(groups_vec);
|
||||
|
@ -191,7 +177,7 @@ fn set_groups_from_str(groups: &str) {
|
|||
|
||||
fn set_user(user: &str) {
|
||||
if !user.is_empty() {
|
||||
let user_id = get_pw_from_args(&vec!(user.to_owned())).unwrap().pw_uid;
|
||||
let user_id = entries::usr2uid(user).unwrap();
|
||||
let err = unsafe { setuid(user_id as libc::uid_t) };
|
||||
if err != 0 {
|
||||
crash!(1, "cannot set user to {}: {}", user, Error::last_os_error())
|
||||
|
|
|
@ -9,8 +9,11 @@ path = "id.rs"
|
|||
|
||||
[dependencies]
|
||||
getopts = "*"
|
||||
libc = "*"
|
||||
uucore = { path="../uucore" }
|
||||
|
||||
[dependencies.uucore]
|
||||
path = "../uucore"
|
||||
default-features = false
|
||||
features = ["entries", "process"]
|
||||
|
||||
[[bin]]
|
||||
name = "id"
|
||||
|
|
413
src/id/id.rs
413
src/id/id.rs
|
@ -1,54 +1,51 @@
|
|||
#![crate_name = "uu_id"]
|
||||
|
||||
/*
|
||||
* This file is part of the uutils coreutils package.
|
||||
*
|
||||
* (c) Alan Andrade <alan.andradec@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* Synced with:
|
||||
* http://ftp-archive.freebsd.org/mirror/FreeBSD-Archive/old-releases/i386/1.0-RELEASE/ports/shellutils/src/id.c
|
||||
* http://www.opensource.apple.com/source/shell_cmds/shell_cmds-118/id/id.c
|
||||
*/
|
||||
// This file is part of the uutils coreutils package.
|
||||
//
|
||||
// (c) Alan Andrade <alan.andradec@gmail.com>
|
||||
// (c) Jian Zeng <anonymousknight96 AT gmail.com>
|
||||
//
|
||||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
//
|
||||
// Synced with:
|
||||
// http://ftp-archive.freebsd.org/mirror/FreeBSD-Archive/old-releases/i386/1.0-RELEASE/ports/shellutils/src/id.c
|
||||
// http://www.opensource.apple.com/source/shell_cmds/shell_cmds-118/id/id.c
|
||||
//
|
||||
|
||||
#![allow(non_camel_case_types)]
|
||||
extern crate getopts;
|
||||
extern crate libc;
|
||||
#![allow(dead_code)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
use libc::{getgid, getuid, uid_t, getegid, geteuid, getlogin};
|
||||
use std::ffi::CStr;
|
||||
pub use uucore::libc;
|
||||
use uucore::libc::{getlogin, uid_t};
|
||||
use uucore::entries::{self, Passwd, Group, Locate};
|
||||
use uucore::process::{getgid, getuid, getegid, geteuid};
|
||||
use std::io::Write;
|
||||
use std::ptr::read;
|
||||
use uucore::c_types::{
|
||||
c_passwd,
|
||||
c_group,
|
||||
get_groups,
|
||||
get_group_list,
|
||||
get_pw_from_args,
|
||||
getpwuid,
|
||||
group
|
||||
};
|
||||
use std::ffi::CStr;
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
macro_rules! cstr2cow {
|
||||
($v:expr) => (
|
||||
unsafe { CStr::from_ptr($v).to_string_lossy() }
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "linu"))]
|
||||
mod audit {
|
||||
pub use std::mem::uninitialized;
|
||||
use libc::{uid_t, pid_t, c_int, c_uint, uint64_t, dev_t};
|
||||
use super::libc::{uid_t, pid_t, c_int, c_uint, uint64_t, dev_t};
|
||||
|
||||
pub type au_id_t = uid_t;
|
||||
pub type au_asid_t = pid_t;
|
||||
pub type au_id_t = uid_t;
|
||||
pub type au_asid_t = pid_t;
|
||||
pub type au_event_t = c_uint;
|
||||
pub type au_emod_t = c_uint;
|
||||
pub type au_emod_t = c_uint;
|
||||
pub type au_class_t = c_int;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct au_mask {
|
||||
pub am_success: c_uint,
|
||||
pub am_failure: c_uint
|
||||
pub am_failure: c_uint,
|
||||
}
|
||||
pub type au_mask_t = au_mask;
|
||||
|
||||
|
@ -60,56 +57,52 @@ mod audit {
|
|||
|
||||
#[repr(C)]
|
||||
pub struct c_auditinfo_addr {
|
||||
pub ai_auid: au_id_t, /* Audit user ID */
|
||||
pub ai_mask: au_mask_t, /* Audit masks. */
|
||||
pub ai_termid: au_tid_addr_t, /* Terminal ID. */
|
||||
pub ai_asid: au_asid_t, /* Audit session ID. */
|
||||
pub ai_flags: uint64_t /* Audit session flags */
|
||||
pub ai_auid: au_id_t, // Audit user ID
|
||||
pub ai_mask: au_mask_t, // Audit masks.
|
||||
pub ai_termid: au_tid_addr_t, // Terminal ID.
|
||||
pub ai_asid: au_asid_t, // Audit session ID.
|
||||
pub ai_flags: uint64_t, // Audit session flags
|
||||
}
|
||||
pub type c_auditinfo_addr_t = c_auditinfo_addr;
|
||||
|
||||
extern {
|
||||
extern "C" {
|
||||
pub fn getaudit(auditinfo_addr: *mut c_auditinfo_addr_t) -> c_int;
|
||||
}
|
||||
}
|
||||
|
||||
extern {
|
||||
fn getgrgid(gid: uid_t) -> *const c_group;
|
||||
}
|
||||
|
||||
static NAME: &'static str = "id";
|
||||
static SYNTAX: &'static str = "[OPTION]... [USER]";
|
||||
static SUMMARY: &'static str = "Print user and group information for the specified USER,\n or (when USER omitted) for the current user.";
|
||||
|
||||
pub fn uumain(args: Vec<String>) -> i32 {
|
||||
let mut opts = getopts::Options::new();
|
||||
opts.optflag("h", "", "Show help");
|
||||
opts.optflag("A", "", "Display the process audit (not available on Linux)");
|
||||
let mut opts = new_coreopts!(SYNTAX, SUMMARY, "");
|
||||
opts.optflag("A",
|
||||
"",
|
||||
"Display the process audit (not available on Linux)");
|
||||
opts.optflag("G", "", "Display the different group IDs");
|
||||
opts.optflag("g", "", "Display the effective group ID as a number");
|
||||
opts.optflag("n", "", "Display the name of the user or group ID for the -G, -g and -u options");
|
||||
opts.optflag("n",
|
||||
"",
|
||||
"Display the name of the user or group ID for the -G, -g and -u options");
|
||||
opts.optflag("P", "", "Display the id as a password file entry");
|
||||
opts.optflag("p", "", "Make the output human-readable");
|
||||
opts.optflag("r", "", "Display the real ID for the -g and -u options");
|
||||
opts.optflag("u", "", "Display the effective user ID as a number");
|
||||
|
||||
let matches = match opts.parse(&args[1..]) {
|
||||
Ok(m) => { m },
|
||||
Err(_) => {
|
||||
println!("{}", opts.usage(NAME));
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
if matches.opt_present("h") {
|
||||
println!("{}", opts.usage(NAME));
|
||||
return 0;
|
||||
}
|
||||
let matches = opts.parse(args);
|
||||
|
||||
if matches.opt_present("A") {
|
||||
auditid();
|
||||
return 0;
|
||||
}
|
||||
|
||||
let possible_pw = get_pw_from_args(&matches.free);
|
||||
let possible_pw = if matches.free.is_empty() {
|
||||
None
|
||||
} else {
|
||||
match Passwd::locate(matches.free[0].as_str()) {
|
||||
Ok(p) => Some(p),
|
||||
Err(_) => crash!(1, "No such user/group: {}", matches.free[0]),
|
||||
}
|
||||
};
|
||||
|
||||
let nflag = matches.opt_present("n");
|
||||
let uflag = matches.opt_present("u");
|
||||
|
@ -117,55 +110,57 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
let rflag = matches.opt_present("r");
|
||||
|
||||
if gflag {
|
||||
let id = if possible_pw.is_some() {
|
||||
possible_pw.unwrap().pw_gid
|
||||
let id = possible_pw.map(|p| p.gid()).unwrap_or(if rflag {
|
||||
getgid()
|
||||
} else {
|
||||
if rflag {
|
||||
unsafe { getgid() }
|
||||
} else {
|
||||
unsafe { getegid() }
|
||||
}
|
||||
};
|
||||
let gr = unsafe { getgrgid(id) };
|
||||
|
||||
if nflag && !gr.is_null() {
|
||||
let gr_name = unsafe { String::from_utf8_lossy(CStr::from_ptr(read(gr).gr_name).to_bytes()).to_string() };
|
||||
println!("{}", gr_name);
|
||||
} else {
|
||||
println!("{}", id);
|
||||
}
|
||||
getegid()
|
||||
});
|
||||
println!("{}",
|
||||
if nflag {
|
||||
entries::gid2grp(id).unwrap_or(id.to_string())
|
||||
} else {
|
||||
id.to_string()
|
||||
});
|
||||
return 0;
|
||||
}
|
||||
|
||||
if uflag {
|
||||
let id = if possible_pw.is_some() {
|
||||
possible_pw.unwrap().pw_uid
|
||||
} else if rflag {
|
||||
unsafe { getuid() }
|
||||
let id = possible_pw.map(|p| p.uid()).unwrap_or(if rflag {
|
||||
getuid()
|
||||
} else {
|
||||
unsafe { geteuid() }
|
||||
};
|
||||
|
||||
let pw = unsafe { getpwuid(id) };
|
||||
if nflag && !pw.is_null() {
|
||||
let pw_name = unsafe {
|
||||
String::from_utf8_lossy(CStr::from_ptr(read(pw).pw_name).to_bytes()).to_string()
|
||||
};
|
||||
println!("{}", pw_name);
|
||||
} else {
|
||||
println!("{}", id);
|
||||
}
|
||||
|
||||
geteuid()
|
||||
});
|
||||
println!("{}",
|
||||
if nflag {
|
||||
entries::uid2usr(id).unwrap_or(id.to_string())
|
||||
} else {
|
||||
id.to_string()
|
||||
});
|
||||
return 0;
|
||||
}
|
||||
|
||||
if matches.opt_present("G") {
|
||||
group(possible_pw, nflag);
|
||||
println!("{}",
|
||||
if nflag {
|
||||
possible_pw.map(|p| p.belongs_to())
|
||||
.unwrap_or(entries::get_groups().unwrap())
|
||||
.iter()
|
||||
.map(|&id| entries::gid2grp(id).unwrap())
|
||||
.collect::<Vec<_>>()
|
||||
.join(" ")
|
||||
} else {
|
||||
possible_pw.map(|p| p.belongs_to())
|
||||
.unwrap_or(entries::get_groups().unwrap())
|
||||
.iter()
|
||||
.map(|&id| id.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join(" ")
|
||||
});
|
||||
return 0;
|
||||
}
|
||||
|
||||
if matches.opt_present("P") {
|
||||
pline(possible_pw);
|
||||
pline(possible_pw.map(|v| v.uid()));
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
@ -183,126 +178,92 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
0
|
||||
}
|
||||
|
||||
fn pretty(possible_pw: Option<c_passwd>) {
|
||||
if possible_pw.is_some() {
|
||||
let pw = possible_pw.unwrap();
|
||||
|
||||
let pw_name = unsafe { String::from_utf8_lossy(CStr::from_ptr(pw.pw_name).to_bytes()).to_string() };
|
||||
print!("uid\t{}\ngroups\t", pw_name);
|
||||
group(possible_pw, true);
|
||||
fn pretty(possible_pw: Option<Passwd>) {
|
||||
if let Some(p) = possible_pw {
|
||||
print!("uid\t{}\ngroups\t", p.name());
|
||||
println!("{}",
|
||||
p.belongs_to().iter().map(|&gr| entries::gid2grp(gr).unwrap()).collect::<Vec<_>>().join(" "));
|
||||
} else {
|
||||
let login = unsafe { String::from_utf8_lossy(CStr::from_ptr((getlogin() as *const _)).to_bytes()).to_string() };
|
||||
let rid = unsafe { getuid() };
|
||||
let pw = unsafe { getpwuid(rid) };
|
||||
|
||||
let is_same_user = unsafe {
|
||||
String::from_utf8_lossy(CStr::from_ptr(read(pw).pw_name).to_bytes()) == login
|
||||
};
|
||||
|
||||
if pw.is_null() || is_same_user {
|
||||
println!("login\t{}", login);
|
||||
}
|
||||
|
||||
if !pw.is_null() {
|
||||
println!(
|
||||
"uid\t{}",
|
||||
unsafe { String::from_utf8_lossy(CStr::from_ptr(read(pw).pw_name).to_bytes()).to_string() })
|
||||
let login = cstr2cow!(getlogin() as *const _);
|
||||
let rid = getuid();
|
||||
if let Ok(p) = Passwd::locate(rid) {
|
||||
if login == p.name() {
|
||||
println!("login\t{}", login);
|
||||
}
|
||||
println!("uid\t{}", p.name());
|
||||
} else {
|
||||
println!("uid\t{}\n", rid);
|
||||
println!("uid\t{}", rid);
|
||||
}
|
||||
|
||||
let eid = unsafe { getegid() };
|
||||
let eid = getegid();
|
||||
if eid == rid {
|
||||
let pw = unsafe { getpwuid(eid) };
|
||||
if !pw.is_null() {
|
||||
println!(
|
||||
"euid\t{}",
|
||||
unsafe { String::from_utf8_lossy(CStr::from_ptr(read(pw).pw_name).to_bytes()).to_string() });
|
||||
if let Ok(p) = Passwd::locate(eid) {
|
||||
println!("euid\t{}", p.name());
|
||||
} else {
|
||||
println!("euid\t{}", eid);
|
||||
}
|
||||
}
|
||||
|
||||
let rid = unsafe { getgid() };
|
||||
|
||||
let rid = getgid();
|
||||
if rid != eid {
|
||||
let gr = unsafe { getgrgid(rid) };
|
||||
if !gr.is_null() {
|
||||
println!(
|
||||
"rgid\t{}",
|
||||
unsafe { String::from_utf8_lossy(CStr::from_ptr(read(gr).gr_name).to_bytes()).to_string() });
|
||||
if let Ok(g) = Group::locate(rid) {
|
||||
println!("euid\t{}", g.name());
|
||||
} else {
|
||||
println!("rgid\t{}", rid);
|
||||
println!("euid\t{}", rid);
|
||||
}
|
||||
}
|
||||
|
||||
print!("groups\t");
|
||||
group(None, true);
|
||||
println!("groups\t{}",
|
||||
entries::get_groups()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.map(|&gr| entries::gid2grp(gr).unwrap())
|
||||
.collect::<Vec<_>>()
|
||||
.join(" "));
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "macos", target_os = "freebsd"))]
|
||||
fn pline(possible_pw: Option<c_passwd>) {
|
||||
let pw = if possible_pw.is_none() {
|
||||
unsafe { read(getpwuid(getuid())) }
|
||||
} else {
|
||||
possible_pw.unwrap()
|
||||
};
|
||||
fn pline(possible_uid: Option<uid_t>) {
|
||||
let uid = possible_uid.unwrap_or(getuid());
|
||||
let pw = Passwd::locate(uid).unwrap();
|
||||
|
||||
let pw_name = unsafe { String::from_utf8_lossy(CStr::from_ptr(pw.pw_name ).to_bytes()).to_string()};
|
||||
let pw_passwd = unsafe { String::from_utf8_lossy(CStr::from_ptr(pw.pw_passwd).to_bytes()).to_string()};
|
||||
let pw_class = unsafe { String::from_utf8_lossy(CStr::from_ptr(pw.pw_class ).to_bytes()).to_string()};
|
||||
let pw_gecos = unsafe { String::from_utf8_lossy(CStr::from_ptr(pw.pw_gecos ).to_bytes()).to_string()};
|
||||
let pw_dir = unsafe { String::from_utf8_lossy(CStr::from_ptr(pw.pw_dir ).to_bytes()).to_string()};
|
||||
let pw_shell = unsafe { String::from_utf8_lossy(CStr::from_ptr(pw.pw_shell ).to_bytes()).to_string()};
|
||||
|
||||
println!(
|
||||
"{}:{}:{}:{}:{}:{}:{}:{}:{}:{}",
|
||||
pw_name,
|
||||
pw_passwd,
|
||||
pw.pw_uid,
|
||||
pw.pw_gid,
|
||||
pw_class,
|
||||
pw.pw_change,
|
||||
pw.pw_expire,
|
||||
pw_gecos,
|
||||
pw_dir,
|
||||
pw_shell);
|
||||
println!("{}:{}:{}:{}:{}:{}:{}:{}:{}:{}",
|
||||
pw.name(),
|
||||
pw.user_passwd(),
|
||||
pw.uid(),
|
||||
pw.gid(),
|
||||
pw.user_access_class(),
|
||||
pw.passwd_change_time(),
|
||||
pw.expiration(),
|
||||
pw.user_info(),
|
||||
pw.user_dir(),
|
||||
pw.user_shell());
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn pline(possible_pw: Option<c_passwd>) {
|
||||
let pw = if possible_pw.is_none() {
|
||||
unsafe { read(getpwuid(getuid())) }
|
||||
} else {
|
||||
possible_pw.unwrap()
|
||||
};
|
||||
fn pline(possible_uid: Option<uid_t>) {
|
||||
let uid = possible_uid.unwrap_or(getuid());
|
||||
let pw = Passwd::locate(uid).unwrap();
|
||||
|
||||
let pw_name = unsafe { String::from_utf8_lossy(CStr::from_ptr(pw.pw_name ).to_bytes()).to_string()};
|
||||
let pw_passwd = unsafe { String::from_utf8_lossy(CStr::from_ptr(pw.pw_passwd).to_bytes()).to_string()};
|
||||
let pw_gecos = unsafe { String::from_utf8_lossy(CStr::from_ptr(pw.pw_gecos ).to_bytes()).to_string()};
|
||||
let pw_dir = unsafe { String::from_utf8_lossy(CStr::from_ptr(pw.pw_dir ).to_bytes()).to_string()};
|
||||
let pw_shell = unsafe { String::from_utf8_lossy(CStr::from_ptr(pw.pw_shell ).to_bytes()).to_string()};
|
||||
|
||||
println!(
|
||||
"{}:{}:{}:{}:{}:{}:{}",
|
||||
pw_name,
|
||||
pw_passwd,
|
||||
pw.pw_uid,
|
||||
pw.pw_gid,
|
||||
pw_gecos,
|
||||
pw_dir,
|
||||
pw_shell);
|
||||
println!("{}:{}:{}:{}:{}:{}:{}",
|
||||
pw.name(),
|
||||
pw.user_passwd(),
|
||||
pw.uid(),
|
||||
pw.gid(),
|
||||
pw.user_info(),
|
||||
pw.user_dir(),
|
||||
pw.user_shell());
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn auditid() { }
|
||||
fn auditid() {}
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
fn auditid() {
|
||||
let mut auditinfo: audit::c_auditinfo_addr_t = unsafe { audit::uninitialized() };
|
||||
let address = &mut auditinfo as *mut audit::c_auditinfo_addr_t;
|
||||
if unsafe { audit::getaudit(address) } < 0 {
|
||||
if unsafe { audit::getaudit(address) } < 0 {
|
||||
println!("couldn't retrieve information");
|
||||
return;
|
||||
}
|
||||
|
@ -314,83 +275,27 @@ fn auditid() {
|
|||
println!("asid={}", auditinfo.ai_asid);
|
||||
}
|
||||
|
||||
fn id_print(possible_pw: Option<c_passwd>, p_euid: bool, p_egid: bool) {
|
||||
let uid;
|
||||
let gid;
|
||||
fn id_print(possible_pw: Option<Passwd>, p_euid: bool, p_egid: bool) {
|
||||
let (uid, gid) = possible_pw.map(|p| (p.uid(), p.gid())).unwrap_or((getuid(), getgid()));;
|
||||
|
||||
if possible_pw.is_some() {
|
||||
uid = possible_pw.unwrap().pw_uid;
|
||||
gid = possible_pw.unwrap().pw_gid;
|
||||
} else {
|
||||
uid = unsafe { getuid() };
|
||||
gid = unsafe { getgid() };
|
||||
}
|
||||
let groups = Passwd::locate(uid).unwrap().belongs_to();
|
||||
|
||||
let groups = match possible_pw {
|
||||
Some(pw) => Ok(get_group_list(pw.pw_name, pw.pw_gid)),
|
||||
None => get_groups(),
|
||||
};
|
||||
print!("uid={}({})", uid, entries::uid2usr(uid).unwrap());
|
||||
print!(" gid={}({})", gid, entries::gid2grp(gid).unwrap());
|
||||
|
||||
let groups = groups.unwrap_or_else(|errno| {
|
||||
crash!(1, "failed to get group list (errno={})", errno);
|
||||
});
|
||||
|
||||
if possible_pw.is_some() {
|
||||
print!(
|
||||
"uid={}({})",
|
||||
uid,
|
||||
unsafe { String::from_utf8_lossy(CStr::from_ptr(possible_pw.unwrap().pw_name).to_bytes()).to_string() });
|
||||
} else {
|
||||
print!("uid={}", unsafe { getuid() });
|
||||
}
|
||||
|
||||
print!(" gid={}", gid);
|
||||
let gr = unsafe { getgrgid(gid) };
|
||||
if !gr.is_null() {
|
||||
print!(
|
||||
"({})",
|
||||
unsafe { String::from_utf8_lossy(CStr::from_ptr(read(gr).gr_name).to_bytes()).to_string() });
|
||||
}
|
||||
|
||||
let euid = unsafe { geteuid() };
|
||||
let euid = geteuid();
|
||||
if p_euid && (euid != uid) {
|
||||
print!(" euid={}", euid);
|
||||
let pw = unsafe { getpwuid(euid) };
|
||||
if !pw.is_null() {
|
||||
print!(
|
||||
"({})",
|
||||
unsafe { String::from_utf8_lossy(CStr::from_ptr(read(pw).pw_name).to_bytes()).to_string() });
|
||||
}
|
||||
print!(" euid={}({})", euid, entries::uid2usr(euid).unwrap());
|
||||
}
|
||||
|
||||
let egid = unsafe { getegid() };
|
||||
let egid = getegid();
|
||||
if p_egid && (egid != gid) {
|
||||
print!(" egid={}", egid);
|
||||
unsafe {
|
||||
let grp = getgrgid(egid);
|
||||
if !grp.is_null() {
|
||||
print!("({})", String::from_utf8_lossy(CStr::from_ptr(read(grp).gr_name).to_bytes()).to_string());
|
||||
}
|
||||
}
|
||||
print!(" egid={}({})", euid, entries::gid2grp(egid).unwrap());
|
||||
}
|
||||
|
||||
if !groups.is_empty() {
|
||||
print!(" groups=");
|
||||
|
||||
let mut first = true;
|
||||
for &gr in &groups {
|
||||
if !first { print!(",") }
|
||||
print!("{}", gr);
|
||||
let group = unsafe { getgrgid(gr) };
|
||||
if !group.is_null() {
|
||||
let name = unsafe {
|
||||
String::from_utf8_lossy(CStr::from_ptr(read(group).gr_name).to_bytes()).to_string()
|
||||
};
|
||||
print!("({})", name);
|
||||
}
|
||||
first = false
|
||||
}
|
||||
}
|
||||
|
||||
println!("");
|
||||
println!(" groups={}",
|
||||
groups.iter()
|
||||
.map(|&gr| format!("{}({})", gr, entries::gid2grp(gr).unwrap()))
|
||||
.collect::<Vec<_>>()
|
||||
.join(","));
|
||||
}
|
||||
|
|
|
@ -9,8 +9,6 @@ path = "ls.rs"
|
|||
|
||||
[dependencies]
|
||||
getopts = "*"
|
||||
libc = "*"
|
||||
uucore = { path="../uucore" }
|
||||
pretty-bytes = "0.1.0"
|
||||
term_grid = "*"
|
||||
termsize = "*"
|
||||
|
@ -18,6 +16,11 @@ time = "*"
|
|||
lazy_static = "*"
|
||||
unicode-width = "*"
|
||||
|
||||
[dependencies.uucore]
|
||||
path = "../uucore"
|
||||
default-features = false
|
||||
features = ["entries"]
|
||||
|
||||
[[bin]]
|
||||
name = "ls"
|
||||
path = "main.rs"
|
||||
|
|
32
src/ls/ls.rs
32
src/ls/ls.rs
|
@ -23,11 +23,9 @@ extern crate lazy_static;
|
|||
|
||||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
extern crate libc;
|
||||
#[cfg(unix)]
|
||||
use self::libc::{S_ISUID, S_ISGID, S_ISVTX, S_IRUSR, S_IWUSR, S_IXUSR, S_IRGRP, S_IWGRP, S_IXGRP,
|
||||
S_IROTH, S_IWOTH, S_IXOTH, mode_t, c_char};
|
||||
use uucore::libc::{S_ISUID, S_ISGID, S_ISVTX, S_IRUSR, S_IWUSR, S_IXUSR, S_IRGRP, S_IWGRP, S_IXGRP,
|
||||
S_IROTH, S_IWOTH, S_IXOTH, mode_t};
|
||||
|
||||
use getopts::Options;
|
||||
use std::fs;
|
||||
|
@ -41,10 +39,6 @@ use std::os::unix::fs::MetadataExt;
|
|||
#[cfg(unix)]
|
||||
use std::os::unix::fs::FileTypeExt;
|
||||
#[cfg(unix)]
|
||||
use std::ptr;
|
||||
#[cfg(unix)]
|
||||
use std::ffi::CStr;
|
||||
#[cfg(unix)]
|
||||
use unicode_width::UnicodeWidthStr;
|
||||
|
||||
#[cfg(windows)]
|
||||
|
@ -407,32 +401,16 @@ fn display_item_long(item: &PathBuf,
|
|||
// Currently getpwuid is `linux` target only. If it's broken out into
|
||||
// a posix-compliant attribute this can be updated...
|
||||
#[cfg(unix)]
|
||||
use uucore::c_types::{getpwuid, getgrgid};
|
||||
|
||||
// Only used in `display_uname` and `display_group`
|
||||
#[cfg(unix)]
|
||||
fn cstr2string(cstr: *const c_char) -> String {
|
||||
unsafe { CStr::from_ptr(cstr).to_string_lossy().into_owned() }
|
||||
}
|
||||
use uucore::entries;
|
||||
|
||||
#[cfg(unix)]
|
||||
fn display_uname(metadata: &Metadata) -> String {
|
||||
let pw = unsafe { getpwuid(metadata.uid()) };
|
||||
if !pw.is_null() {
|
||||
cstr2string(unsafe { ptr::read(pw).pw_name })
|
||||
} else {
|
||||
metadata.uid().to_string()
|
||||
}
|
||||
entries::uid2usr(metadata.uid()).unwrap_or(metadata.uid().to_string())
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn display_group(metadata: &Metadata) -> String {
|
||||
let ent = unsafe { getgrgid(metadata.gid()) };
|
||||
if !ent.is_null() {
|
||||
cstr2string(unsafe { ptr::read(ent).gr_name })
|
||||
} else {
|
||||
metadata.gid().to_string()
|
||||
}
|
||||
entries::gid2grp(metadata.gid()).unwrap_or(metadata.gid().to_string())
|
||||
}
|
||||
|
||||
#[cfg(not(unix))]
|
||||
|
|
|
@ -10,7 +10,7 @@ path = "pinky.rs"
|
|||
[dependencies.uucore]
|
||||
path = "../uucore"
|
||||
default-features = false
|
||||
features = ["utmpx", "c_types"]
|
||||
features = ["utmpx", "entries"]
|
||||
|
||||
[[bin]]
|
||||
name = "pinky"
|
||||
|
|
|
@ -12,9 +12,9 @@
|
|||
|
||||
#[macro_use]
|
||||
extern crate uucore;
|
||||
use uucore::c_types::getpwnam;
|
||||
use uucore::utmpx::{self, time, Utmpx};
|
||||
use uucore::libc::{uid_t, gid_t, c_char, S_IWGRP};
|
||||
use uucore::libc::S_IWGRP;
|
||||
use uucore::entries::{Locate, Passwd};
|
||||
|
||||
use std::io::prelude::*;
|
||||
use std::io::BufReader;
|
||||
|
@ -23,14 +23,11 @@ use std::io::Result as IOResult;
|
|||
use std::fs::File;
|
||||
use std::os::unix::fs::MetadataExt;
|
||||
|
||||
use std::ptr;
|
||||
use std::ffi::{CStr, CString};
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
static SYNTAX: &'static str = "[OPTION]... [USER]...";
|
||||
static SUMMARY: &'static str = "A lightweight 'finger' program; print user information.";
|
||||
|
||||
|
||||
const BUFSIZE: usize = 1024;
|
||||
|
||||
pub fn uumain(args: Vec<String>) -> i32 {
|
||||
|
@ -152,52 +149,6 @@ struct Pinky {
|
|||
names: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Passwd {
|
||||
pw_name: String,
|
||||
pw_passwd: String,
|
||||
pw_uid: uid_t,
|
||||
pw_gid: gid_t,
|
||||
pw_gecos: String,
|
||||
pw_dir: String,
|
||||
pw_shell: String,
|
||||
}
|
||||
|
||||
trait FromChars {
|
||||
fn from_chars(*const c_char) -> Self;
|
||||
}
|
||||
|
||||
impl FromChars for String {
|
||||
#[inline]
|
||||
fn from_chars(ptr: *const c_char) -> Self {
|
||||
if ptr.is_null() {
|
||||
return "".to_owned();
|
||||
}
|
||||
let s = unsafe { CStr::from_ptr(ptr) };
|
||||
s.to_string_lossy().into_owned()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getpw(u: &str) -> Option<Passwd> {
|
||||
let pw = unsafe {
|
||||
getpwnam(CString::new(u).unwrap().as_ptr())
|
||||
};
|
||||
if !pw.is_null() {
|
||||
let data = unsafe { ptr::read(pw) };
|
||||
Some(Passwd {
|
||||
pw_name: String::from_chars(data.pw_name),
|
||||
pw_passwd: String::from_chars(data.pw_passwd),
|
||||
pw_uid: data.pw_uid,
|
||||
pw_gid: data.pw_gid,
|
||||
pw_dir: String::from_chars(data.pw_dir),
|
||||
pw_gecos: String::from_chars(data.pw_gecos),
|
||||
pw_shell: String::from_chars(data.pw_shell),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Capitalize {
|
||||
fn capitalize(&self) -> String;
|
||||
}
|
||||
|
@ -267,12 +218,12 @@ impl Pinky {
|
|||
print!("{1:<8.0$}", utmpx::UT_NAMESIZE, ut.user());
|
||||
|
||||
if self.include_fullname {
|
||||
if let Some(pw) = getpw(ut.user().as_ref()) {
|
||||
let mut gecos = pw.pw_gecos;
|
||||
if let Ok(pw) = Passwd::locate(ut.user().as_ref()) {
|
||||
let mut gecos = pw.user_info().into_owned();
|
||||
if let Some(n) = gecos.find(',') {
|
||||
gecos.truncate(n + 1);
|
||||
}
|
||||
print!(" {:<19.19}", gecos.replace("&", &pw.pw_name.capitalize()));
|
||||
print!(" {:<19.19}", gecos.replace("&", &pw.name().capitalize()));
|
||||
} else {
|
||||
print!(" {:19}", " ???");
|
||||
}
|
||||
|
@ -344,14 +295,14 @@ impl Pinky {
|
|||
fn long_pinky(&self) -> i32 {
|
||||
for u in &self.names {
|
||||
print!("Login name: {:<28}In real life: ", u);
|
||||
if let Some(pw) = getpw(u) {
|
||||
println!(" {}", pw.pw_gecos.replace("&", &pw.pw_name.capitalize()));
|
||||
if let Ok(pw) = Passwd::locate(u.as_str()) {
|
||||
println!(" {}", pw.user_info().replace("&", &pw.name().capitalize()));
|
||||
if self.include_home_and_shell {
|
||||
print!("Directory: {:<29}", pw.pw_dir);
|
||||
println!("Shell: {}", pw.pw_shell);
|
||||
print!("Directory: {:<29}", pw.user_dir());
|
||||
println!("Shell: {}", pw.user_shell());
|
||||
}
|
||||
if self.include_project {
|
||||
let mut p = PathBuf::from(&pw.pw_dir);
|
||||
let mut p = PathBuf::from(pw.user_dir().as_ref());
|
||||
p.push(".project");
|
||||
if let Ok(f) = File::open(p) {
|
||||
print!("Project: ");
|
||||
|
@ -359,7 +310,7 @@ impl Pinky {
|
|||
}
|
||||
}
|
||||
if self.include_plan {
|
||||
let mut p = PathBuf::from(&pw.pw_dir);
|
||||
let mut p = PathBuf::from(pw.user_dir().as_ref());
|
||||
p.push(".plan");
|
||||
if let Ok(f) = File::open(p) {
|
||||
println!("Plan:");
|
||||
|
|
|
@ -9,9 +9,12 @@ path = "stat.rs"
|
|||
|
||||
[dependencies]
|
||||
getopts = "*"
|
||||
libc = "^0.2"
|
||||
time = "*"
|
||||
uucore = { path="../uucore" }
|
||||
|
||||
[dependencies.uucore]
|
||||
path = "../uucore"
|
||||
default-features = false
|
||||
features = ["entries"]
|
||||
|
||||
[[bin]]
|
||||
name = "stat"
|
||||
|
|
|
@ -6,13 +6,13 @@
|
|||
// that was distributed with this source code.
|
||||
//
|
||||
|
||||
extern crate libc;
|
||||
pub use super::uucore::libc;
|
||||
extern crate time;
|
||||
|
||||
use self::time::Timespec;
|
||||
pub use self::libc::{S_IFMT, S_IFDIR, S_IFCHR, S_IFBLK, S_IFREG, S_IFIFO, S_IFLNK, S_IFSOCK, S_ISUID, S_ISGID,
|
||||
S_ISVTX, S_IRUSR, S_IWUSR, S_IXUSR, S_IRGRP, S_IWGRP, S_IXGRP, S_IROTH, S_IWOTH, S_IXOTH, mode_t,
|
||||
c_int, strerror};
|
||||
pub use libc::{S_IFMT, S_IFDIR, S_IFCHR, S_IFBLK, S_IFREG, S_IFIFO, S_IFLNK, S_IFSOCK, S_ISUID, S_ISGID, S_ISVTX,
|
||||
S_IRUSR, S_IWUSR, S_IXUSR, S_IRGRP, S_IWGRP, S_IXGRP, S_IROTH, S_IWOTH, S_IXOTH, mode_t, c_int,
|
||||
strerror};
|
||||
|
||||
pub trait BirthTime {
|
||||
fn pretty_birth(&self) -> String;
|
||||
|
@ -176,12 +176,12 @@ use std::error::Error;
|
|||
use std::io::Error as IOError;
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "android"))]
|
||||
use self::libc::statfs as Sstatfs;
|
||||
use libc::statfs as Sstatfs;
|
||||
// #[cfg(any(target_os = "openbsd", target_os = "netbsd", target_os = "openbsd", target_os = "bitrig", target_os = "dragonfly"))]
|
||||
// use self::libc::statvfs as Sstatfs;
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "android"))]
|
||||
use self::libc::statfs as statfs_fn;
|
||||
use libc::statfs as statfs_fn;
|
||||
// #[cfg(any(target_os = "openbsd", target_os = "netbsd", target_os = "openbsd", target_os = "bitrig", target_os = "dragonfly"))]
|
||||
// use self::libc::statvfs as statfs_fn;
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ pub use fsext::*;
|
|||
|
||||
#[macro_use]
|
||||
extern crate uucore;
|
||||
use uucore::entries;
|
||||
|
||||
use std::{fs, iter, cmp};
|
||||
use std::fs::File;
|
||||
|
@ -319,31 +320,6 @@ fn print_it(arg: &str, otype: OutputType, flag: u8, width: usize, precision: i32
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
use std::ptr;
|
||||
use std::ffi::CStr;
|
||||
use uucore::c_types::{getpwuid, getgrgid};
|
||||
fn get_grp_name(gid: u32) -> String {
|
||||
let p = unsafe { getgrgid(gid) };
|
||||
if !p.is_null() {
|
||||
unsafe { CStr::from_ptr(ptr::read(p).gr_name).to_string_lossy().into_owned() }
|
||||
} else {
|
||||
"UNKNOWN".to_owned()
|
||||
}
|
||||
}
|
||||
fn get_usr_name(uid: u32) -> String {
|
||||
let p = unsafe { getpwuid(uid) };
|
||||
if !p.is_null() {
|
||||
unsafe {
|
||||
CStr::from_ptr(ptr::read(p).pw_name)
|
||||
.to_string_lossy()
|
||||
.into_owned()
|
||||
}
|
||||
} else {
|
||||
"UNKNOWN".to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
impl Stater {
|
||||
pub fn generate_tokens(fmtstr: &str, use_printf: bool) -> Result<Vec<Token>, String> {
|
||||
|
||||
|
@ -613,7 +589,7 @@ impl Stater {
|
|||
}
|
||||
// group name of owner
|
||||
'G' => {
|
||||
arg = get_grp_name(meta.gid());
|
||||
arg = entries::gid2grp(meta.gid()).unwrap_or("UNKNOWN".to_owned());
|
||||
otype = OutputType::Str;
|
||||
}
|
||||
// number of hard links
|
||||
|
@ -683,7 +659,7 @@ impl Stater {
|
|||
}
|
||||
// user name of owner
|
||||
'U' => {
|
||||
arg = get_usr_name(meta.uid());
|
||||
arg = entries::uid2usr(meta.uid()).unwrap_or("UNKNOWN".to_owned());
|
||||
otype = OutputType::Str;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,8 +21,9 @@ utmpx = ["time", "libc"]
|
|||
c_types = ["libc"]
|
||||
process = ["libc"]
|
||||
signals = []
|
||||
entries = ["libc"]
|
||||
wide = []
|
||||
default = ["fs", "libc", "utf8", "encoding", "parse_time", "utmpx", "c_types", "process", "signals", "wide"]
|
||||
default = ["fs", "libc", "utf8", "encoding", "parse_time", "utmpx", "c_types", "process", "entries", "signals", "wide"]
|
||||
|
||||
[lib]
|
||||
path = "lib.rs"
|
||||
|
|
|
@ -44,11 +44,11 @@ impl<'a> CoreOptions<'a> {
|
|||
crash!(1, "{}", f);
|
||||
}
|
||||
}.unwrap();
|
||||
if matches.opt_present("help") {
|
||||
if matches.opt_present("help") {
|
||||
let usage_str = if self.help_text.display_usage {
|
||||
format!("\n {}\n\n Reference\n",
|
||||
format!("\n {}\n\n Reference\n",
|
||||
self.options.usage(self.help_text.summary)
|
||||
).replace("Options:", " Options:")
|
||||
).replace("Options:", " Options:")
|
||||
} else { String::new() };
|
||||
print!("
|
||||
{0} {1}
|
||||
|
@ -66,7 +66,7 @@ impl<'a> CoreOptions<'a> {
|
|||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! new_coreopts {
|
||||
macro_rules! new_coreopts {
|
||||
($syntax: expr, $summary: expr, $long_help: expr) => (
|
||||
uucore::coreopts::CoreOptions::new(uucore::coreopts::HelpText {
|
||||
name: executable!(),
|
||||
|
@ -87,4 +87,4 @@ macro_rules! new_coreopts {
|
|||
display_usage: $display_usage
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
245
src/uucore/entries.rs
Normal file
245
src/uucore/entries.rs
Normal file
|
@ -0,0 +1,245 @@
|
|||
// This file is part of the uutils coreutils package.
|
||||
//
|
||||
// (c) Jian Zeng <anonymousknight96@gmail.com>
|
||||
//
|
||||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
|
||||
//! Get password/group file entry
|
||||
//!
|
||||
//! # Examples:
|
||||
//!
|
||||
//! ```
|
||||
//! use uucore::entries::{self, Locate};
|
||||
//! assert_eq!("root", entries::uid2usr(0).unwrap());
|
||||
//! assert_eq!(0, entries::usr2uid("root").unwrap());
|
||||
//! assert!(entries::gid2grp(0).is_ok());
|
||||
//! assert!(entries::grp2gid("root").is_ok());
|
||||
//!
|
||||
//! assert!(entries::Passwd::locate(0).is_ok());
|
||||
//! assert!(entries::Passwd::locate("0").is_ok());
|
||||
//! assert!(entries::Passwd::locate("root").is_ok());
|
||||
//!
|
||||
//! assert!(entries::Group::locate(0).is_ok());
|
||||
//! assert!(entries::Group::locate("0").is_ok());
|
||||
//! assert!(entries::Group::locate("root").is_ok());
|
||||
//! ```
|
||||
|
||||
#[cfg(any(target_os = "freebsd", target_os = "macos"))]
|
||||
use libc::time_t;
|
||||
use libc::{uid_t, gid_t, c_char, c_int};
|
||||
use libc::{passwd, group, getpwnam, getpwuid, getgrnam, getgrgid, getgroups};
|
||||
|
||||
use ::std::ptr;
|
||||
use ::std::io::ErrorKind;
|
||||
use ::std::io::Error as IOError;
|
||||
use ::std::io::Result as IOResult;
|
||||
use ::std::ffi::{CStr, CString};
|
||||
use ::std::borrow::Cow;
|
||||
|
||||
extern "C" {
|
||||
fn getgrouplist(name: *const c_char, gid: gid_t, groups: *mut gid_t, ngroups: *mut c_int) -> c_int;
|
||||
}
|
||||
|
||||
pub fn get_groups() -> IOResult<Vec<gid_t>> {
|
||||
let ngroups = unsafe { getgroups(0, ptr::null_mut()) };
|
||||
if ngroups == -1 {
|
||||
return Err(IOError::last_os_error())
|
||||
}
|
||||
let mut groups = Vec::with_capacity(ngroups as usize);
|
||||
let ngroups = unsafe { getgroups(ngroups, groups.as_mut_ptr()) };
|
||||
if ngroups == -1 {
|
||||
Err(IOError::last_os_error())
|
||||
} else {
|
||||
unsafe {
|
||||
groups.set_len(ngroups as usize);
|
||||
}
|
||||
Ok(groups)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Passwd {
|
||||
inner: passwd,
|
||||
}
|
||||
|
||||
macro_rules! cstr2cow {
|
||||
($v:expr) => (
|
||||
unsafe { CStr::from_ptr($v).to_string_lossy() }
|
||||
)
|
||||
}
|
||||
|
||||
impl Passwd {
|
||||
/// AKA passwd.pw_name
|
||||
pub fn name(&self) -> Cow<str> {
|
||||
cstr2cow!(self.inner.pw_name)
|
||||
}
|
||||
|
||||
/// AKA passwd.pw_uid
|
||||
pub fn uid(&self) -> uid_t {
|
||||
self.inner.pw_uid
|
||||
}
|
||||
|
||||
/// AKA passwd.pw_gid
|
||||
pub fn gid(&self) -> gid_t {
|
||||
self.inner.pw_gid
|
||||
}
|
||||
|
||||
/// AKA passwd.pw_gecos
|
||||
pub fn user_info(&self) -> Cow<str> {
|
||||
cstr2cow!(self.inner.pw_gecos)
|
||||
}
|
||||
|
||||
/// AKA passwd.pw_shell
|
||||
pub fn user_shell(&self) -> Cow<str> {
|
||||
cstr2cow!(self.inner.pw_shell)
|
||||
}
|
||||
|
||||
/// AKA passwd.pw_dir
|
||||
pub fn user_dir(&self) -> Cow<str> {
|
||||
cstr2cow!(self.inner.pw_dir)
|
||||
}
|
||||
|
||||
/// AKA passwd.pw_passwd
|
||||
pub fn user_passwd(&self) -> Cow<str> {
|
||||
cstr2cow!(self.inner.pw_passwd)
|
||||
}
|
||||
|
||||
/// AKA passwd.pw_class
|
||||
#[cfg(any(target_os = "freebsd", target_os = "macos"))]
|
||||
pub fn user_access_class(&self) -> Cow<str> {
|
||||
cstr2cow!(self.inner.pw_class)
|
||||
}
|
||||
|
||||
/// AKA passwd.pw_change
|
||||
#[cfg(any(target_os = "freebsd", target_os = "macos"))]
|
||||
pub fn passwd_change_time(&self) -> time_t {
|
||||
self.inner.pw_change
|
||||
}
|
||||
|
||||
/// AKA passwd.pw_expire
|
||||
#[cfg(any(target_os = "freebsd", target_os = "macos"))]
|
||||
pub fn expiration(&self) -> time_t {
|
||||
self.inner.pw_expire
|
||||
}
|
||||
|
||||
pub fn as_inner(&self) -> &passwd {
|
||||
&self.inner
|
||||
}
|
||||
|
||||
pub fn into_inner(self) -> passwd {
|
||||
self.inner
|
||||
}
|
||||
|
||||
pub fn belongs_to(&self) -> Vec<gid_t> {
|
||||
let mut ngroups: c_int = 8;
|
||||
let mut groups = Vec::with_capacity(ngroups as usize);
|
||||
let gid = self.inner.pw_gid;
|
||||
let name = self.inner.pw_name;
|
||||
unsafe {
|
||||
if getgrouplist(name, gid, groups.as_mut_ptr(), &mut ngroups) == -1 {
|
||||
groups.resize(ngroups as usize, 0);
|
||||
getgrouplist(name, gid, groups.as_mut_ptr(), &mut ngroups);
|
||||
}
|
||||
groups.set_len(ngroups as usize);
|
||||
}
|
||||
groups.truncate(ngroups as usize);
|
||||
groups
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Group {
|
||||
inner: group,
|
||||
}
|
||||
|
||||
impl Group {
|
||||
/// AKA group.gr_name
|
||||
pub fn name(&self) -> Cow<str> {
|
||||
cstr2cow!(self.inner.gr_name)
|
||||
}
|
||||
|
||||
/// AKA group.gr_gid
|
||||
pub fn gid(&self) -> gid_t {
|
||||
self.inner.gr_gid
|
||||
}
|
||||
|
||||
pub fn as_inner(&self) -> &group {
|
||||
&self.inner
|
||||
}
|
||||
|
||||
pub fn into_inner(self) -> group {
|
||||
self.inner
|
||||
}
|
||||
}
|
||||
|
||||
/// Fetch desired entry.
|
||||
pub trait Locate<K> {
|
||||
fn locate(key: K) -> IOResult<Self> where Self: ::std::marker::Sized;
|
||||
}
|
||||
|
||||
macro_rules! f {
|
||||
($fnam:ident, $fid:ident, $t:ident, $st:ident) => (
|
||||
impl Locate<$t> for $st {
|
||||
fn locate(k: $t) -> IOResult<Self> {
|
||||
unsafe {
|
||||
let data = $fid(k);
|
||||
if !data.is_null() {
|
||||
Ok($st {
|
||||
inner: ptr::read(data as *const _)
|
||||
})
|
||||
} else {
|
||||
Err(IOError::new(ErrorKind::NotFound, format!("No such id: {}", k)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Locate<&'a str> for $st {
|
||||
fn locate(k: &'a str) -> IOResult<Self> {
|
||||
if let Ok(id) = k.parse::<$t>() {
|
||||
let data = unsafe { $fid(id) };
|
||||
if !data.is_null() {
|
||||
Ok($st {
|
||||
inner: unsafe {ptr::read(data as *const _)}
|
||||
})
|
||||
} else {
|
||||
Err(IOError::new(ErrorKind::NotFound, format!("No such id: {}", id)))
|
||||
}
|
||||
} else {
|
||||
unsafe {
|
||||
let data = $fnam(CString::new(k).unwrap().as_ptr());
|
||||
if !data.is_null() {
|
||||
Ok($st {
|
||||
inner: ptr::read(data as *const _)
|
||||
})
|
||||
} else {
|
||||
Err(IOError::new(ErrorKind::NotFound, format!("Not found: {}", k)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
f!(getpwnam, getpwuid, uid_t, Passwd);
|
||||
f!(getgrnam, getgrgid, gid_t, Group);
|
||||
|
||||
#[inline]
|
||||
pub fn uid2usr(id: uid_t) -> IOResult<String> {
|
||||
Passwd::locate(id).map(|p| p.name().into_owned())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn gid2grp(id: gid_t) -> IOResult<String> {
|
||||
Group::locate(id).map(|p| p.name().into_owned())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn usr2uid(name: &str) -> IOResult<uid_t> {
|
||||
Passwd::locate(name).map(|p| p.uid())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn grp2gid(name: &str) -> IOResult<gid_t> {
|
||||
Group::locate(name).map(|p| p.gid())
|
||||
}
|
|
@ -20,6 +20,8 @@ pub mod parse_time;
|
|||
pub mod utmpx;
|
||||
#[cfg(all(unix, feature = "c_types"))]
|
||||
pub mod c_types;
|
||||
#[cfg(all(unix, feature = "entries"))]
|
||||
pub mod entries;
|
||||
#[cfg(all(unix, feature = "process"))]
|
||||
pub mod process;
|
||||
#[cfg(all(unix, feature = "signals"))]
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
/*
|
||||
* This file is part of the uutils coreutils package.
|
||||
*
|
||||
* (c) Maciej Dziardziel <fiedzia@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE file
|
||||
* that was distributed with this source code.
|
||||
*/
|
||||
// This file is part of the uutils coreutils package.
|
||||
//
|
||||
// (c) Maciej Dziardziel <fiedzia@gmail.com>
|
||||
// (c) Jian Zeng <anonymousknight96 AT gmail.com>
|
||||
//
|
||||
// For the full copyright and license information, please view the LICENSE file
|
||||
// that was distributed with this source code.
|
||||
//
|
||||
|
||||
extern crate libc;
|
||||
|
||||
use libc::{c_int, pid_t};
|
||||
use super::libc;
|
||||
use libc::{c_int, pid_t, uid_t, gid_t};
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
use std::process::Child;
|
||||
|
@ -17,6 +16,30 @@ use std::sync::{Arc, Condvar, Mutex};
|
|||
use std::thread;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
pub fn geteuid() -> uid_t {
|
||||
unsafe {
|
||||
libc::geteuid()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getegid() -> gid_t {
|
||||
unsafe {
|
||||
libc::getegid()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getgid() -> gid_t {
|
||||
unsafe {
|
||||
libc::getgid()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getuid() -> uid_t {
|
||||
unsafe {
|
||||
libc::getuid()
|
||||
}
|
||||
}
|
||||
|
||||
// This is basically sys::unix::process::ExitStatus
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
pub enum ExitStatus {
|
||||
|
@ -26,7 +49,8 @@ pub enum ExitStatus {
|
|||
|
||||
impl ExitStatus {
|
||||
fn from_status(status: c_int) -> ExitStatus {
|
||||
if status & 0x7F != 0 { // WIFSIGNALED(status)
|
||||
if status & 0x7F != 0 {
|
||||
// WIFSIGNALED(status)
|
||||
ExitStatus::Signal(status & 0x7F)
|
||||
} else {
|
||||
ExitStatus::Code(status & 0xFF00 >> 8)
|
||||
|
@ -75,8 +99,7 @@ pub trait ChildExt {
|
|||
|
||||
impl ChildExt for Child {
|
||||
fn send_signal(&mut self, signal: usize) -> io::Result<()> {
|
||||
if unsafe { libc::kill(self.id() as pid_t,
|
||||
signal as i32) } != 0 {
|
||||
if unsafe { libc::kill(self.id() as pid_t, signal as i32) } != 0 {
|
||||
Err(io::Error::last_os_error())
|
||||
} else {
|
||||
Ok(())
|
||||
|
@ -86,10 +109,7 @@ impl ChildExt for Child {
|
|||
fn wait_or_timeout(&mut self, timeout: Duration) -> io::Result<Option<ExitStatus>> {
|
||||
// The result will be written to that Option, protected by a Mutex
|
||||
// Then the Condvar will be signaled
|
||||
let state = Arc::new((
|
||||
Mutex::new(Option::None::<io::Result<ExitStatus>>),
|
||||
Condvar::new(),
|
||||
));
|
||||
let state = Arc::new((Mutex::new(Option::None::<io::Result<ExitStatus>>), Condvar::new()));
|
||||
|
||||
// Start the waiting thread
|
||||
let state_th = state.clone();
|
||||
|
@ -121,7 +141,7 @@ impl ChildExt for Child {
|
|||
return exitstatus.map(Some);
|
||||
}
|
||||
if start.elapsed() >= timeout {
|
||||
return Ok(None)
|
||||
return Ok(None);
|
||||
}
|
||||
let cvar_timeout = timeout - start.elapsed();
|
||||
exitstatus = cvar.wait_timeout(exitstatus, cvar_timeout).unwrap().0;
|
||||
|
|
|
@ -1,7 +1,3 @@
|
|||
//! Aim to provide platform-independent methods to obtain login records
|
||||
//!
|
||||
//! **ONLY** support linux, macos and freebsd for the time being
|
||||
|
||||
// This file is part of the uutils coreutils package.
|
||||
//
|
||||
// (c) Jian Zeng <anonymousknight96@gmail.com>
|
||||
|
@ -9,6 +5,31 @@
|
|||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
//
|
||||
//! Aims to provide platform-independent methods to obtain login records
|
||||
//!
|
||||
//! **ONLY** support linux, macos and freebsd for the time being
|
||||
//!
|
||||
//! # Examples:
|
||||
//!
|
||||
//! ```
|
||||
//! use uucore::utmpx::Utmpx;
|
||||
//! for ut in Utmpx::iter_all_records() {
|
||||
//! if ut.is_user_process() {
|
||||
//! println!("{}: {}", ut.host(), ut.user())
|
||||
//! }
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! Specifying the path to login record:
|
||||
//!
|
||||
//! ```
|
||||
//! use uucore::utmpx::Utmpx;
|
||||
//! for ut in Utmpx::iter_all_records().read_from("/some/where/else") {
|
||||
//! if ut.is_user_process() {
|
||||
//! println!("{}: {}", ut.host(), ut.user())
|
||||
//! }
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
use super::libc;
|
||||
pub extern crate time;
|
||||
|
@ -107,28 +128,6 @@ mod ut {
|
|||
pub use libc::SHUTDOWN_TIME;
|
||||
}
|
||||
|
||||
/// Login records
|
||||
///
|
||||
/// Examples:
|
||||
/// ---------
|
||||
///
|
||||
/// ```
|
||||
/// for ut in Utmpx::iter_all_records() {
|
||||
/// if ut.is_user_process() {
|
||||
/// println!("{}: {}", ut.host(), ut.user())
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Specifying the path to login record:
|
||||
///
|
||||
/// ```
|
||||
/// for ut in Utmpx::iter_all_records().read_from("/some/where/else") {
|
||||
/// if ut.is_user_process() {
|
||||
/// println!("{}: {}", ut.host(), ut.user())
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
pub struct Utmpx {
|
||||
inner: utmpx,
|
||||
}
|
||||
|
|
|
@ -9,10 +9,13 @@ path = "whoami.rs"
|
|||
|
||||
[dependencies]
|
||||
getopts = "*"
|
||||
libc = "*"
|
||||
winapi = "*"
|
||||
advapi32-sys = "*"
|
||||
uucore = { path="../uucore" }
|
||||
|
||||
[dependencies.uucore]
|
||||
path = "../uucore"
|
||||
default-features = false
|
||||
features = ["entries"]
|
||||
|
||||
[[bin]]
|
||||
name = "whoami"
|
||||
|
|
|
@ -2,31 +2,18 @@
|
|||
* This file is part of the uutils coreutils package.
|
||||
*
|
||||
* (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||
* (c) Jian Zeng <anonymousknight96 AT gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use std::io::{Result, Error};
|
||||
use ::libc;
|
||||
use uucore::c_types::{c_passwd, getpwuid};
|
||||
|
||||
extern {
|
||||
pub fn geteuid() -> libc::uid_t;
|
||||
}
|
||||
use std::io::Result;
|
||||
use uucore::libc::geteuid;
|
||||
use uucore::entries::uid2usr;
|
||||
|
||||
pub unsafe fn getusername() -> Result<String> {
|
||||
// Get effective user id
|
||||
let uid = geteuid();
|
||||
|
||||
// Try to find username for uid
|
||||
let passwd: *const c_passwd = getpwuid(uid);
|
||||
if passwd.is_null() {
|
||||
return Err(Error::last_os_error())
|
||||
}
|
||||
|
||||
// Extract username from passwd struct
|
||||
let pw_name: *const libc::c_char = (*passwd).pw_name;
|
||||
let username = String::from_utf8_lossy(::std::ffi::CStr::from_ptr(pw_name).to_bytes()).to_string();
|
||||
Ok(username)
|
||||
uid2usr(uid)
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
/* last synced with: whoami (GNU coreutils) 8.21 */
|
||||
|
||||
extern crate getopts;
|
||||
extern crate libc;
|
||||
|
||||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
|
|
@ -9,25 +9,25 @@ fn new_ucmd() -> UCommand {
|
|||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_passwd {
|
||||
use super::passwd::*;
|
||||
mod test_passgrp {
|
||||
use super::uu_chown::entries::{usr2uid,grp2gid,uid2usr,gid2grp};
|
||||
|
||||
#[test]
|
||||
fn test_getuid() {
|
||||
assert_eq!(0, getuid("root").unwrap());
|
||||
assert!(getuid("88888888").is_err());
|
||||
assert!(getuid("auserthatdoesntexist").is_err());
|
||||
fn test_usr2uid() {
|
||||
assert_eq!(0, usr2uid("root").unwrap());
|
||||
assert!(usr2uid("88888888").is_err());
|
||||
assert!(usr2uid("auserthatdoesntexist").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_getgid() {
|
||||
fn test_grp2gid() {
|
||||
if cfg!(target_os = "macos") {
|
||||
assert_eq!(0, getgid("wheel").unwrap());
|
||||
assert_eq!(0, grp2gid("wheel").unwrap());
|
||||
} else {
|
||||
assert_eq!(0, getgid("root").unwrap());
|
||||
assert_eq!(0, grp2gid("root").unwrap());
|
||||
}
|
||||
assert!(getgid("88888888").is_err());
|
||||
assert!(getgid("agroupthatdoesntexist").is_err());
|
||||
assert!(grp2gid("88888888").is_err());
|
||||
assert!(grp2gid("agroupthatdoesntexist").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue