Skip to content

Commit 51d39cf

Browse files
committed
Reduce code duplication
Signed-off-by: Otavio Salvador <[email protected]>
1 parent de1ed63 commit 51d39cf

File tree

2 files changed

+68
-114
lines changed

2 files changed

+68
-114
lines changed

src/unistd.rs

Lines changed: 68 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -2459,33 +2459,19 @@ impl From<&libc::passwd> for User {
24592459
}
24602460

24612461
impl User {
2462-
/// Get a user by UID.
2463-
///
2464-
/// Internally, this function calls
2465-
/// [getpwuid_r(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html)
2466-
///
2467-
/// # Examples
2468-
///
2469-
/// ```
2470-
/// use nix::unistd::{Uid, User};
2471-
/// // Returns an Option<Result<User>>, thus the double unwrap.
2472-
/// let res = User::from_uid(Uid::from_raw(0), Some(2048)).unwrap().unwrap();
2473-
/// assert!(res.name == "root");
2474-
/// ```
2475-
pub fn from_uid(uid: Uid, bufsize: Option<usize>) -> Option<Result<Self>> {
2476-
let mut cbuf = Vec::with_capacity(bufsize.unwrap_or(PWGRP_BUFSIZE));
2462+
fn from_anything(f: impl Fn(*mut libc::passwd,
2463+
*mut libc::c_char,
2464+
libc::size_t,
2465+
*mut *mut libc::passwd) -> libc::c_int)
2466+
-> Option<Result<Self>>
2467+
{
2468+
let mut cbuf = Vec::with_capacity(PWGRP_BUFSIZE);
24772469
let mut pwd = mem::MaybeUninit::<libc::passwd>::uninit();
24782470
let mut res = ptr::null_mut();
24792471

24802472
let error = unsafe {
24812473
Errno::clear();
2482-
libc::getpwuid_r(
2483-
uid.0,
2484-
pwd.as_mut_ptr(),
2485-
cbuf.as_mut_ptr(),
2486-
cbuf.capacity(),
2487-
&mut res
2488-
)
2474+
f(pwd.as_mut_ptr(), cbuf.as_mut_ptr(), cbuf.capacity(), &mut res)
24892475
};
24902476

24912477
let pwd = unsafe { pwd.assume_init() };
@@ -2500,6 +2486,25 @@ impl User {
25002486
Some(Err(Error::Sys(Errno::last())))
25012487
}
25022488
}
2489+
2490+
/// Get a user by UID.
2491+
///
2492+
/// Internally, this function calls
2493+
/// [getpwuid_r(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html)
2494+
///
2495+
/// # Examples
2496+
///
2497+
/// ```
2498+
/// use nix::unistd::{Uid, User};
2499+
/// // Returns an Option<Result<User>>, thus the double unwrap.
2500+
/// let res = User::from_uid(Uid::from_raw(0)).unwrap().unwrap();
2501+
/// assert!(res.name == "root");
2502+
/// ```
2503+
pub fn from_uid(uid: Uid) -> Option<Result<Self>> {
2504+
User::from_anything(|pwd, cbuf, cap, res| {
2505+
unsafe { libc::getpwuid_r(uid.0, pwd, cbuf, cap, res) }
2506+
})
2507+
}
25032508

25042509
/// Get a user by name.
25052510
///
@@ -2511,36 +2516,14 @@ impl User {
25112516
/// ```
25122517
/// use nix::unistd::User;
25132518
/// // Returns an Option<Result<User>>, thus the double unwrap.
2514-
/// let res = User::from_name("root", Some(2048)).unwrap().unwrap();
2519+
/// let res = User::from_name("root").unwrap().unwrap();
25152520
/// assert!(res.name == "root");
25162521
/// ```
2517-
pub fn from_name(name: &str, bufsize: Option<usize>) -> Option<Result<Self>> {
2518-
let mut cbuf = Vec::with_capacity(bufsize.unwrap_or(PWGRP_BUFSIZE));
2519-
let mut pwd = mem::MaybeUninit::<libc::passwd>::uninit();
2520-
let mut res = ptr::null_mut();
2521-
2522-
let error = unsafe {
2523-
Errno::clear();
2524-
libc::getpwnam_r(
2525-
CString::new(name).unwrap().as_ptr(),
2526-
pwd.as_mut_ptr(),
2527-
cbuf.as_mut_ptr(),
2528-
cbuf.capacity(),
2529-
&mut res
2530-
)
2531-
};
2532-
2533-
let pwd = unsafe { pwd.assume_init() };
2534-
2535-
if error == 0 {
2536-
if ! res.is_null() {
2537-
Some(Ok(User::from(&pwd)))
2538-
} else {
2539-
None
2540-
}
2541-
} else {
2542-
Some(Err(Error::Sys(Errno::last())))
2543-
}
2522+
pub fn from_name(name: &str) -> Option<Result<Self>> {
2523+
let name = CString::new(name).unwrap();
2524+
User::from_anything(|pwd, cbuf, cap, res| {
2525+
unsafe { libc::getpwnam_r(name.as_ptr(), pwd, cbuf, cap, res) }
2526+
})
25442527
}
25452528
}
25462529

@@ -2584,35 +2567,19 @@ impl Group {
25842567
ret
25852568
}
25862569

2587-
/// Get a group by GID.
2588-
///
2589-
/// Internally, this function calls
2590-
/// [getgrgid_r(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html)
2591-
///
2592-
/// # Examples
2593-
///
2594-
// Disable this test on all OS except Linux as root group may not exist.
2595-
#[cfg_attr(not(target_os = "linux"), doc = " ```no_run")]
2596-
#[cfg_attr(target_os = "linux", doc = " ```")]
2597-
/// use nix::unistd::{Gid, Group};
2598-
/// // Returns an Option<Result<Group>>, thus the double unwrap.
2599-
/// let res = Group::from_gid(Gid::from_raw(0), Some(2048)).unwrap().unwrap();
2600-
/// assert!(res.name == "root");
2601-
/// ```
2602-
pub fn from_gid(gid: Gid, bufsize: Option<usize>) -> Option<Result<Self>> {
2603-
let mut cbuf = Vec::with_capacity(bufsize.unwrap_or(PWGRP_BUFSIZE));
2570+
fn from_anything(f: impl Fn(*mut libc::group,
2571+
*mut libc::c_char,
2572+
libc::size_t,
2573+
*mut *mut libc::group) -> libc::c_int)
2574+
-> Option<Result<Self>>
2575+
{
2576+
let mut cbuf = Vec::with_capacity(PWGRP_BUFSIZE);
26042577
let mut grp = mem::MaybeUninit::<libc::group>::uninit();
26052578
let mut res = ptr::null_mut();
26062579

26072580
let error = unsafe {
26082581
Errno::clear();
2609-
libc::getgrgid_r(
2610-
gid.0,
2611-
grp.as_mut_ptr(),
2612-
cbuf.as_mut_ptr(),
2613-
cbuf.capacity(),
2614-
&mut res
2615-
)
2582+
f(grp.as_mut_ptr(), cbuf.as_mut_ptr(), cbuf.capacity(), &mut res)
26162583
};
26172584

26182585
let grp = unsafe { grp.assume_init() };
@@ -2628,6 +2595,27 @@ impl Group {
26282595
}
26292596
}
26302597

2598+
/// Get a group by GID.
2599+
///
2600+
/// Internally, this function calls
2601+
/// [getgrgid_r(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html)
2602+
///
2603+
/// # Examples
2604+
///
2605+
// Disable this test on all OS except Linux as root group may not exist.
2606+
#[cfg_attr(not(target_os = "linux"), doc = " ```no_run")]
2607+
#[cfg_attr(target_os = "linux", doc = " ```")]
2608+
/// use nix::unistd::{Gid, Group};
2609+
/// // Returns an Option<Result<Group>>, thus the double unwrap.
2610+
/// let res = Group::from_gid(Gid::from_raw(0)).unwrap().unwrap();
2611+
/// assert!(res.name == "root");
2612+
/// ```
2613+
pub fn from_gid(gid: Gid) -> Option<Result<Self>> {
2614+
Group::from_anything(|grp, cbuf, cap, res| {
2615+
unsafe { libc::getgrgid_r(gid.0, grp, cbuf, cap, res) }
2616+
})
2617+
}
2618+
26312619
/// Get a group by name.
26322620
///
26332621
/// Internally, this function calls
@@ -2640,36 +2628,14 @@ impl Group {
26402628
#[cfg_attr(target_os = "linux", doc = " ```")]
26412629
/// use nix::unistd::Group;
26422630
/// // Returns an Option<Result<Group>>, thus the double unwrap.
2643-
/// let res = Group::from_name("root", Some(2048)).unwrap().unwrap();
2631+
/// let res = Group::from_name("root").unwrap().unwrap();
26442632
/// assert!(res.name == "root");
26452633
/// ```
2646-
pub fn from_name(name: &str, bufsize: Option<usize>) -> Option<Result<Self>> {
2647-
let mut cbuf = Vec::with_capacity(bufsize.unwrap_or(PWGRP_BUFSIZE));
2648-
let mut grp = mem::MaybeUninit::<libc::group>::uninit();
2649-
let mut res = ptr::null_mut();
2650-
2651-
let error = unsafe {
2652-
Errno::clear();
2653-
libc::getgrnam_r(
2654-
CString::new(name).unwrap().as_ptr(),
2655-
grp.as_mut_ptr(),
2656-
cbuf.as_mut_ptr(),
2657-
cbuf.capacity(),
2658-
&mut res
2659-
)
2660-
};
2661-
2662-
let grp = unsafe { grp.assume_init() };
2663-
2664-
if error == 0 {
2665-
if !res.is_null() {
2666-
Some(Ok(Group::from(&grp)))
2667-
} else {
2668-
None
2669-
}
2670-
} else {
2671-
Some(Err(Error::Sys(Errno::last())))
2672-
}
2634+
pub fn from_name(name: &str) -> Option<Result<Self>> {
2635+
let name = CString::new(name).unwrap();
2636+
Group::from_anything(|grp, cbuf, cap, res| {
2637+
unsafe { libc::getgrnam_r(name.as_ptr(), grp, cbuf, cap, res) }
2638+
})
26732639
}
26742640
}
26752641

test/test_unistd.rs

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -600,18 +600,6 @@ fn test_symlinkat() {
600600
);
601601
}
602602

603-
#[test]
604-
fn test_getpwuid() {
605-
let res = User::from_uid(Uid::from_raw(0), None).unwrap();
606-
assert!(res.unwrap().uid == Uid::from_raw(0));
607-
}
608-
609-
#[test]
610-
fn test_getgrgid() {
611-
let res = Group::from_gid(Gid::from_raw(0), None).unwrap();
612-
assert!(res.unwrap().gid == Gid::from_raw(0));
613-
}
614-
615603
#[cfg(not(any(target_os = "android",
616604
target_os = "ios",
617605
target_os = "macos",

0 commit comments

Comments
 (0)