Skip to content

Commit 8519d9f

Browse files
bors[bot]orvij
and
orvij
authored
Merge #1471
1471: unistd: Add conversion from User to libc::passwd r=asomers a=orvij Add `From<User> for libc::passwd` trait implementation to convert a `User` into a `libc::passwd` Implementation consumes the `User` struct, giving ownership over the internal members to the `libc::passwd` struct Exposes the `User::gecos` field to 64-bit Android builds, since `libc::passwd::pw_gecos` is supported on those builds Co-authored-by: orvij <[email protected]>
2 parents e1351ab + 3f6151e commit 8519d9f

File tree

3 files changed

+70
-3
lines changed

3 files changed

+70
-3
lines changed

CHANGELOG.md

+8-1
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,23 @@ This project adheres to [Semantic Versioning](https://semver.org/).
88

99
- Added `TimeSpec::from_duration` and `TimeSpec::from_timespec`
1010
(#[1465](https://github.com/nix-rust/nix/pull/1465))
11-
1211
- Added `IPV6_V6ONLY` sockopt.
1312
(#[1470](https://github.com/nix-rust/nix/pull/1470))
13+
- Added `impl From<User> for libc::passwd` trait implementation to convert a `User`
14+
into a `libc::passwd`. Consumes the `User` struct to give ownership over
15+
the member pointers.
16+
(#[1471](https://github.com/nix-rust/nix/pull/1471))
1417
- Added `pthread_kill`.
1518
(#[1472](https://github.com/nix-rust/nix/pull/1472))
1619

1720
### Changed
1821

1922
- `FdSet::{contains, highest, fds}` no longer require a mutable reference.
2023
(#[1464](https://github.com/nix-rust/nix/pull/1464))
24+
- `User::gecos` and corresponding `libc::passwd::pw_gecos` are supported on
25+
64-bit Android, change conditional compilation to include the field in
26+
64-bit Android builds
27+
(#[1471](https://github.com/nix-rust/nix/pull/1471))
2128

2229
### Fixed
2330

src/unistd.rs

+54-2
Original file line numberDiff line numberDiff line change
@@ -2629,7 +2629,7 @@ pub struct User {
26292629
/// Group ID
26302630
pub gid: Gid,
26312631
/// User information
2632-
#[cfg(not(target_os = "android"))]
2632+
#[cfg(not(all(target_os = "android", target_pointer_width = "32")))]
26332633
pub gecos: CString,
26342634
/// Home directory
26352635
pub dir: PathBuf,
@@ -2665,7 +2665,7 @@ impl From<&libc::passwd> for User {
26652665
User {
26662666
name: CStr::from_ptr((*pw).pw_name).to_string_lossy().into_owned(),
26672667
passwd: CString::new(CStr::from_ptr((*pw).pw_passwd).to_bytes()).unwrap(),
2668-
#[cfg(not(target_os = "android"))]
2668+
#[cfg(not(all(target_os = "android", target_pointer_width = "32")))]
26692669
gecos: CString::new(CStr::from_ptr((*pw).pw_gecos).to_bytes()).unwrap(),
26702670
dir: PathBuf::from(OsStr::from_bytes(CStr::from_ptr((*pw).pw_dir).to_bytes())),
26712671
shell: PathBuf::from(OsStr::from_bytes(CStr::from_ptr((*pw).pw_shell).to_bytes())),
@@ -2694,6 +2694,58 @@ impl From<&libc::passwd> for User {
26942694
}
26952695
}
26962696

2697+
#[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd
2698+
impl From<User> for libc::passwd {
2699+
fn from(u: User) -> Self {
2700+
let name = match CString::new(u.name) {
2701+
Ok(n) => n.into_raw(),
2702+
Err(_) => CString::new("").unwrap().into_raw(),
2703+
};
2704+
let dir = match u.dir.into_os_string().into_string() {
2705+
Ok(s) => CString::new(s.as_str()).unwrap().into_raw(),
2706+
Err(_) => CString::new("").unwrap().into_raw(),
2707+
};
2708+
let shell = match u.shell.into_os_string().into_string() {
2709+
Ok(s) => CString::new(s.as_str()).unwrap().into_raw(),
2710+
Err(_) => CString::new("").unwrap().into_raw(),
2711+
};
2712+
Self {
2713+
pw_name: name,
2714+
pw_passwd: u.passwd.into_raw(),
2715+
#[cfg(not(all(target_os = "android", target_pointer_width = "32")))]
2716+
pw_gecos: u.gecos.into_raw(),
2717+
pw_dir: dir,
2718+
pw_shell: shell,
2719+
pw_uid: u.uid.0,
2720+
pw_gid: u.gid.0,
2721+
#[cfg(not(any(target_os = "android",
2722+
target_os = "fuchsia",
2723+
target_os = "illumos",
2724+
target_os = "linux",
2725+
target_os = "solaris")))]
2726+
pw_class: u.class.into_raw(),
2727+
#[cfg(not(any(target_os = "android",
2728+
target_os = "fuchsia",
2729+
target_os = "illumos",
2730+
target_os = "linux",
2731+
target_os = "solaris")))]
2732+
pw_change: u.change,
2733+
#[cfg(not(any(target_os = "android",
2734+
target_os = "fuchsia",
2735+
target_os = "illumos",
2736+
target_os = "linux",
2737+
target_os = "solaris")))]
2738+
pw_expire: u.expire,
2739+
#[cfg(target_os = "illumos")]
2740+
pw_age: CString::new("").unwrap().into_raw(),
2741+
#[cfg(target_os = "illumos")]
2742+
pw_comment: CString::new("").unwrap().into_raw(),
2743+
#[cfg(target_os = "freebsd")]
2744+
pw_fields: 0,
2745+
}
2746+
}
2747+
}
2748+
26972749
#[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd
26982750
impl User {
26992751
fn from_anything<F>(f: F) -> Result<Option<Self>>

test/test_unistd.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1025,6 +1025,14 @@ fn test_access_file_exists() {
10251025
assert!(access(&path, AccessFlags::R_OK | AccessFlags::W_OK).is_ok());
10261026
}
10271027

1028+
#[test]
1029+
fn test_user_into_passwd() {
1030+
// get the UID of the "nobody" user
1031+
let nobody = User::from_name("nobody").unwrap().unwrap();
1032+
let pwd: libc::passwd = nobody.into();
1033+
let _: User = (&pwd).into();
1034+
}
1035+
10281036
/// Tests setting the filesystem UID with `setfsuid`.
10291037
#[cfg(any(target_os = "linux", target_os = "android"))]
10301038
#[test]

0 commit comments

Comments
 (0)