Skip to content

Commit 3b75439

Browse files
committed
Handle ERANGE
Signed-off-by: Otavio Salvador <[email protected]>
1 parent 51d39cf commit 3b75439

File tree

1 file changed

+48
-26
lines changed

1 file changed

+48
-26
lines changed

src/unistd.rs

Lines changed: 48 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2465,25 +2465,36 @@ impl User {
24652465
*mut *mut libc::passwd) -> libc::c_int)
24662466
-> Option<Result<Self>>
24672467
{
2468-
let mut cbuf = Vec::with_capacity(PWGRP_BUFSIZE);
2468+
let bufsize = match sysconf(SysconfVar::GETPW_R_SIZE_MAX) {
2469+
Ok(Some(n)) => n as usize,
2470+
Ok(None) | Err(_) => 1024 as usize,
2471+
};
2472+
2473+
let mut cbuf = Vec::with_capacity(bufsize);
24692474
let mut pwd = mem::MaybeUninit::<libc::passwd>::uninit();
24702475
let mut res = ptr::null_mut();
24712476

2472-
let error = unsafe {
2473-
Errno::clear();
2474-
f(pwd.as_mut_ptr(), cbuf.as_mut_ptr(), cbuf.capacity(), &mut res)
2475-
};
2476-
2477-
let pwd = unsafe { pwd.assume_init() };
2477+
loop {
2478+
let error = unsafe {
2479+
Errno::clear();
2480+
f(pwd.as_mut_ptr(), cbuf.as_mut_ptr(), cbuf.capacity(), &mut res)
2481+
};
24782482

2479-
if error == 0 {
2480-
if ! res.is_null() {
2481-
Some(Ok(User::from(&pwd)))
2483+
if error == 0 {
2484+
if res.is_null() {
2485+
return None;
2486+
} else {
2487+
let pwd = unsafe { pwd.assume_init() };
2488+
return Some(Ok(User::from(&pwd)));
2489+
}
2490+
} else if Errno::last() == Errno::ERANGE {
2491+
// Trigger the internal buffer resizing logic of `Vec` by requiring
2492+
// more space than the current capacity.
2493+
unsafe { cbuf.set_len(cbuf.capacity()); }
2494+
cbuf.reserve(1);
24822495
} else {
2483-
None
2496+
return Some(Err(Error::Sys(Errno::last())));
24842497
}
2485-
} else {
2486-
Some(Err(Error::Sys(Errno::last())))
24872498
}
24882499
}
24892500

@@ -2573,25 +2584,36 @@ impl Group {
25732584
*mut *mut libc::group) -> libc::c_int)
25742585
-> Option<Result<Self>>
25752586
{
2576-
let mut cbuf = Vec::with_capacity(PWGRP_BUFSIZE);
2587+
let bufsize = match sysconf(SysconfVar::GETGR_R_SIZE_MAX) {
2588+
Ok(Some(n)) => n as usize,
2589+
Ok(None) | Err(_) => 1024 as usize,
2590+
};
2591+
2592+
let mut cbuf = Vec::with_capacity(bufsize);
25772593
let mut grp = mem::MaybeUninit::<libc::group>::uninit();
25782594
let mut res = ptr::null_mut();
25792595

2580-
let error = unsafe {
2581-
Errno::clear();
2582-
f(grp.as_mut_ptr(), cbuf.as_mut_ptr(), cbuf.capacity(), &mut res)
2583-
};
2584-
2585-
let grp = unsafe { grp.assume_init() };
2596+
loop {
2597+
let error = unsafe {
2598+
Errno::clear();
2599+
f(grp.as_mut_ptr(), cbuf.as_mut_ptr(), cbuf.capacity(), &mut res)
2600+
};
25862601

2587-
if error == 0 {
2588-
if !res.is_null() {
2589-
Some(Ok(Group::from(&grp)))
2602+
if error == 0 {
2603+
if res.is_null() {
2604+
return None;
2605+
} else {
2606+
let grp = unsafe { grp.assume_init() };
2607+
return Some(Ok(Group::from(&grp)));
2608+
}
2609+
} else if Errno::last() == Errno::ERANGE {
2610+
// Trigger the internal buffer resizing logic of `Vec` by requiring
2611+
// more space than the current capacity.
2612+
unsafe { cbuf.set_len(cbuf.capacity()); }
2613+
cbuf.reserve(1);
25902614
} else {
2591-
None
2615+
return Some(Err(Error::Sys(Errno::last())));
25922616
}
2593-
} else {
2594-
Some(Err(Error::Sys(Errno::last())))
25952617
}
25962618
}
25972619

0 commit comments

Comments
 (0)