From ce0f5b1af63a7879d37f3e738031aeaf36d99339 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedrich=20Sch=C3=B6ller?= Date: Sat, 9 Mar 2024 08:39:35 +0100 Subject: [PATCH] Change UtunIfname sockopt type to CString (#2329) * Implement GetCString for use with sockopt * Change UtunIfname sockopt type to CString --- src/sys/socket/sockopt.rs | 35 ++++++++++++++++++++++++++++++++--- test/sys/test_sockopt.rs | 2 +- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/sys/socket/sockopt.rs b/src/sys/socket/sockopt.rs index 708775c11b..09e5fd3b86 100644 --- a/src/sys/socket/sockopt.rs +++ b/src/sys/socket/sockopt.rs @@ -5,7 +5,7 @@ use crate::sys::time::TimeVal; use crate::Result; use cfg_if::cfg_if; use libc::{self, c_int, c_void, socklen_t}; -use std::ffi::{OsStr, OsString}; +use std::ffi::{CStr, CString, OsStr, OsString}; use std::mem::{self, MaybeUninit}; use std::os::unix::ffi::OsStrExt; use std::os::unix::io::{AsFd, AsRawFd}; @@ -1073,8 +1073,8 @@ sockopt_impl!( GetOnly, libc::SYSPROTO_CONTROL, libc::UTUN_OPT_IFNAME, - OsString, - GetOsString<[u8; libc::IFNAMSIZ]> + CString, + GetCString<[u8; libc::IFNAMSIZ]> ); #[allow(missing_docs)] @@ -1579,3 +1579,32 @@ impl<'a> Set<'a, OsString> for SetOsString<'a> { } } +/// Getter for a `CString` value. +struct GetCString> { + len: socklen_t, + val: MaybeUninit, +} + +impl> Get for GetCString { + fn uninit() -> Self { + GetCString { + len: mem::size_of::() as socklen_t, + val: MaybeUninit::uninit(), + } + } + + fn ffi_ptr(&mut self) -> *mut c_void { + self.val.as_mut_ptr().cast() + } + + fn ffi_len(&mut self) -> *mut socklen_t { + &mut self.len + } + + unsafe fn assume_init(self) -> CString { + let mut v = unsafe { self.val.assume_init() }; + CStr::from_bytes_until_nul(v.as_mut()) + .expect("string should be null-terminated") + .to_owned() + } +} diff --git a/test/sys/test_sockopt.rs b/test/sys/test_sockopt.rs index 61108f2603..22812acf22 100644 --- a/test/sys/test_sockopt.rs +++ b/test/sys/test_sockopt.rs @@ -856,6 +856,6 @@ fn test_utun_ifname() { let name = getsockopt(&fd, sockopt::UtunIfname) .expect("getting UTUN_OPT_IFNAME on a utun interface should succeed"); - let expected_name = format!("utun{}\0", unit - 1); + let expected_name = format!("utun{}", unit - 1); assert_eq!(name.into_string(), Ok(expected_name)); }