Skip to content

Commit 4b927ff

Browse files
authored
Merge pull request #38 from Freaky/handle-erange
Retry lookups with larger buffer sizes on ERANGE
2 parents 0bfda43 + 43ed211 commit 4b927ff

File tree

1 file changed

+48
-12
lines changed

1 file changed

+48
-12
lines changed

src/base.rs

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -322,14 +322,23 @@ unsafe fn members(groups: *mut *mut c_char) -> Vec<OsString> {
322322
/// ```
323323
pub fn get_user_by_uid(uid: uid_t) -> Option<User> {
324324
let mut passwd = unsafe { mem::zeroed::<c_passwd>() };
325-
let mut buf = vec![0; 2048]; // TODO: Retry with larger buffer sizes
325+
let mut buf = vec![0; 2048];
326326
let mut result = ptr::null_mut::<c_passwd>();
327327

328328
#[cfg(feature = "logging")]
329329
trace!("Running getpwuid_r for user #{}", uid);
330330

331-
unsafe {
332-
libc::getpwuid_r(uid, &mut passwd, buf.as_mut_ptr(), buf.len(), &mut result);
331+
loop {
332+
let r = unsafe {
333+
libc::getpwuid_r(uid, &mut passwd, buf.as_mut_ptr(), buf.len(), &mut result)
334+
};
335+
336+
if r != libc::ERANGE {
337+
break;
338+
}
339+
340+
let newsize = buf.len().checked_mul(2)?;
341+
buf.resize(newsize, 0);
333342
}
334343

335344
if result.is_null() {
@@ -375,14 +384,23 @@ pub fn get_user_by_name<S: AsRef<OsStr> + ?Sized>(username: &S) -> Option<User>
375384
};
376385

377386
let mut passwd = unsafe { mem::zeroed::<c_passwd>() };
378-
let mut buf = vec![0; 2048]; // TODO: Retry with larger buffer sizes
387+
let mut buf = vec![0; 2048];
379388
let mut result = ptr::null_mut::<c_passwd>();
380389

381390
#[cfg(feature = "logging")]
382391
trace!("Running getpwnam_r for user {:?}", username.as_ref());
383392

384-
unsafe {
385-
libc::getpwnam_r(username.as_ptr(), &mut passwd, buf.as_mut_ptr(), buf.len(), &mut result);
393+
loop {
394+
let r = unsafe {
395+
libc::getpwnam_r(username.as_ptr(), &mut passwd, buf.as_mut_ptr(), buf.len(), &mut result)
396+
};
397+
398+
if r != libc::ERANGE {
399+
break;
400+
}
401+
402+
let newsize = buf.len().checked_mul(2)?;
403+
buf.resize(newsize, 0);
386404
}
387405

388406
if result.is_null() {
@@ -419,14 +437,23 @@ pub fn get_user_by_name<S: AsRef<OsStr> + ?Sized>(username: &S) -> Option<User>
419437
/// ```
420438
pub fn get_group_by_gid(gid: gid_t) -> Option<Group> {
421439
let mut passwd = unsafe { mem::zeroed::<c_group>() };
422-
let mut buf = vec![0; 2048]; // TODO: Retry with larger buffer sizes
440+
let mut buf = vec![0; 2048];
423441
let mut result = ptr::null_mut::<c_group>();
424442

425443
#[cfg(feature = "logging")]
426444
trace!("Running getgruid_r for group #{}", gid);
427445

428-
unsafe {
429-
libc::getgrgid_r(gid, &mut passwd, buf.as_mut_ptr(), buf.len(), &mut result);
446+
loop {
447+
let r = unsafe {
448+
libc::getgrgid_r(gid, &mut passwd, buf.as_mut_ptr(), buf.len(), &mut result)
449+
};
450+
451+
if r != libc::ERANGE {
452+
break;
453+
}
454+
455+
let newsize = buf.len().checked_mul(2)?;
456+
buf.resize(newsize, 0);
430457
}
431458

432459
if result.is_null() {
@@ -472,14 +499,23 @@ pub fn get_group_by_name<S: AsRef<OsStr> + ?Sized>(groupname: &S) -> Option<Grou
472499
};
473500

474501
let mut group = unsafe { mem::zeroed::<c_group>() };
475-
let mut buf = vec![0; 2048]; // TODO: Retry with larger buffer sizes
502+
let mut buf = vec![0; 2048];
476503
let mut result = ptr::null_mut::<c_group>();
477504

478505
#[cfg(feature = "logging")]
479506
trace!("Running getgrnam_r for group {:?}", groupname.as_ref());
480507

481-
unsafe {
482-
libc::getgrnam_r(groupname.as_ptr(), &mut group, buf.as_mut_ptr(), buf.len(), &mut result);
508+
loop {
509+
let r = unsafe {
510+
libc::getgrnam_r(groupname.as_ptr(), &mut group, buf.as_mut_ptr(), buf.len(), &mut result)
511+
};
512+
513+
if r != libc::ERANGE {
514+
break;
515+
}
516+
517+
let newsize = buf.len().checked_mul(2)?;
518+
buf.resize(newsize, 0);
483519
}
484520

485521
if result.is_null() {

0 commit comments

Comments
 (0)