Use unsafe blocks in netdb.h implementation

This commit is contained in:
sourceturner
2026-01-18 21:01:15 +01:00
parent 2d149b51ae
commit e57ef36d3c
2 changed files with 277 additions and 232 deletions
+50 -41
View File
@@ -1,3 +1,6 @@
// TODO: set this for entire crate when possible
#![deny(unsafe_op_in_unsafe_fn)]
use alloc::{boxed::Box, str::SplitWhitespace, vec::Vec};
use core::{mem, ptr};
@@ -37,87 +40,93 @@ pub static mut HOST_STAYOPEN: c_int = 0;
#[unsafe(no_mangle)]
pub unsafe extern "C" fn endhostent() {
if HOSTDB >= 0 {
Sys::close(HOSTDB);
if unsafe { HOSTDB } >= 0 {
Sys::close(unsafe { HOSTDB });
}
HOSTDB = -1;
unsafe { HOSTDB = -1 };
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn sethostent(stayopen: c_int) {
HOST_STAYOPEN = stayopen;
if HOSTDB < 0 {
HOSTDB = Sys::open(c"/etc/hosts".into(), O_RDONLY, 0).or_minus_one_errno()
unsafe { HOST_STAYOPEN = stayopen };
if unsafe { HOSTDB } < 0 {
unsafe { HOSTDB = Sys::open(c"/etc/hosts".into(), O_RDONLY, 0).or_minus_one_errno() }
} else {
Sys::lseek(HOSTDB, 0, SEEK_SET);
Sys::lseek(unsafe { HOSTDB }, 0, SEEK_SET);
}
H_POS = 0;
unsafe { H_POS = 0 };
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn gethostent() -> *mut hostent {
if HOSTDB < 0 {
HOSTDB = Sys::open(c"/etc/hosts".into(), O_RDONLY, 0).or_minus_one_errno();
if unsafe { HOSTDB } < 0 {
unsafe { HOSTDB = Sys::open(c"/etc/hosts".into(), O_RDONLY, 0).or_minus_one_errno() };
}
let mut rlb = RawLineBuffer::new(HOSTDB);
rlb.seek(H_POS);
let mut rlb = RawLineBuffer::new(unsafe { HOSTDB });
rlb.seek(unsafe { H_POS });
let mut r: Box<str> = Box::default();
while r.is_empty() || r.split_whitespace().next() == None || r.starts_with('#') {
r = match rlb.next() {
Line::Some(s) => bytes_to_box_str(s),
_ => {
if HOST_STAYOPEN == 0 {
endhostent();
if unsafe { HOST_STAYOPEN } == 0 {
unsafe { endhostent() };
}
return ptr::null_mut();
}
};
}
rlb.next();
H_POS = rlb.line_pos();
unsafe { H_POS = rlb.line_pos() };
let mut iter: SplitWhitespace = r.split_whitespace();
let addr_vec: Vec<u8> = iter.next().unwrap().bytes().chain(Some(b'\0')).collect();
let addr_cstr = addr_vec.as_slice().as_ptr() as *const c_char;
let mut addr = mem::MaybeUninit::uninit();
inet_aton(addr_cstr, addr.as_mut_ptr());
let addr = addr.assume_init();
unsafe { inet_aton(addr_cstr, addr.as_mut_ptr()) };
let addr = unsafe { addr.assume_init() };
_HOST_ADDR_LIST = addr.s_addr.to_ne_bytes();
HOST_ADDR_LIST = [&raw mut _HOST_ADDR_LIST as *mut c_char, ptr::null_mut()];
unsafe {
_HOST_ADDR_LIST = addr.s_addr.to_ne_bytes();
HOST_ADDR_LIST = [&raw mut _HOST_ADDR_LIST as *mut c_char, ptr::null_mut()];
HOST_ADDR = Some(addr);
HOST_ADDR = Some(addr);
}
let host_name = iter.next().unwrap().bytes().chain(Some(b'\0')).collect();
let mut _host_aliases: Vec<Vec<u8>> = iter
.map(|alias| alias.bytes().chain(Some(b'\0')).collect())
.collect();
HOST_ALIASES.unsafe_set(Some(_host_aliases));
unsafe { HOST_ALIASES.unsafe_set(Some(_host_aliases)) };
let mut host_aliases: Vec<*mut c_char> = HOST_ALIASES
.unsafe_mut()
.as_mut()
.unwrap()
.iter_mut()
.map(|x| x.as_mut_ptr() as *mut c_char)
.chain([ptr::null_mut(), ptr::null_mut()])
.collect();
HOST_NAME.unsafe_set(Some(host_name));
HOST_ENTRY = hostent {
h_name: HOST_NAME.unsafe_mut().as_mut().unwrap().as_mut_ptr() as *mut c_char,
h_aliases: host_aliases.as_mut_slice().as_mut_ptr(),
h_addrtype: AF_INET,
h_length: 4,
h_addr_list: &raw mut HOST_ADDR_LIST as *mut _,
let mut host_aliases: Vec<*mut c_char> = unsafe {
HOST_ALIASES
.unsafe_mut()
.as_mut()
.unwrap()
.iter_mut()
.map(|x| x.as_mut_ptr() as *mut c_char)
.chain([ptr::null_mut(), ptr::null_mut()])
.collect()
};
_HOST_ALIASES.unsafe_set(Some(host_aliases));
if HOST_STAYOPEN == 0 {
endhostent();
unsafe { HOST_NAME.unsafe_set(Some(host_name)) };
unsafe {
HOST_ENTRY = hostent {
h_name: HOST_NAME.unsafe_mut().as_mut().unwrap().as_mut_ptr() as *mut c_char,
h_aliases: host_aliases.as_mut_slice().as_mut_ptr(),
h_addrtype: AF_INET,
h_length: 4,
h_addr_list: &raw mut HOST_ADDR_LIST as *mut _,
};
_HOST_ALIASES.unsafe_set(Some(host_aliases));
}
if unsafe { HOST_STAYOPEN } == 0 {
unsafe { endhostent() };
}
&raw mut HOST_ENTRY as *mut hostent
}
+227 -191
View File
@@ -2,6 +2,9 @@
//!
//! See <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/netdb.h.html>.
// TODO: set this for entire crate when possible
#![deny(unsafe_op_in_unsafe_fn)]
mod dns;
use core::{
@@ -188,22 +191,22 @@ fn bytes_to_box_str(bytes: &[u8]) -> Box<str> {
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/endnetent.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn endnetent() {
Sys::close(NETDB);
NETDB = 0;
Sys::close(unsafe { NETDB });
unsafe { NETDB = 0 };
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/endprotoent.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn endprotoent() {
Sys::close(PROTODB);
PROTODB = 0;
Sys::close(unsafe { PROTODB });
unsafe { PROTODB = 0 };
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/endservent.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn endservent() {
Sys::close(SERVDB);
SERVDB = 0;
Sys::close(unsafe { SERVDB });
unsafe { SERVDB = 0 };
}
/// See <https://pubs.opengroup.org/onlinepubs/009696799/functions/gethostbyaddr.html>.
@@ -245,31 +248,31 @@ pub unsafe extern "C" fn gethostbyaddr(
H_ERRNO.set(NO_RECOVERY);
return ptr::null_mut();
}
let addr: in_addr = *(v as *mut in_addr);
let addr: in_addr = unsafe { *(v as *mut in_addr) };
// check the hosts file first
let mut p: *mut hostent;
sethostent(HOST_STAYOPEN);
unsafe { sethostent(HOST_STAYOPEN) };
while {
p = gethostent();
p = unsafe { gethostent() };
!p.is_null()
} {
let mut cp = (*p).h_addr_list;
let mut cp = unsafe { (*p).h_addr_list };
loop {
if cp.is_null() {
break;
}
if (*cp).is_null() {
if (unsafe { *cp }).is_null() {
break;
}
let mut cp_slice: [c_char; 4] = [0; 4];
(*cp).copy_to(cp_slice.as_mut_ptr(), 4);
let cp_s_addr = mem::transmute::<[c_char; 4], u32>(cp_slice);
unsafe { (*cp).copy_to(cp_slice.as_mut_ptr(), 4) };
let cp_s_addr = unsafe { mem::transmute::<[c_char; 4], u32>(cp_slice) };
if cp_s_addr == addr.s_addr {
sethostent(HOST_STAYOPEN);
unsafe { sethostent(HOST_STAYOPEN) };
return p;
}
cp = cp.offset(1);
cp = unsafe { cp.offset(1) };
}
}
@@ -278,19 +281,21 @@ pub unsafe extern "C" fn gethostbyaddr(
_host_aliases.push(vec![b'\0']);
let mut host_aliases: Vec<*mut c_char> = Vec::new();
host_aliases.push(ptr::null_mut());
HOST_ALIASES.unsafe_set(Some(_host_aliases));
unsafe { HOST_ALIASES.unsafe_set(Some(_host_aliases)) };
match lookup_addr(addr).map(|host_names| host_names.into_iter().next()) {
Ok(Some(host_name)) => {
_HOST_ADDR_LIST = addr.s_addr.to_ne_bytes();
HOST_ADDR_LIST = [&raw mut _HOST_ADDR_LIST as *mut c_char, ptr::null_mut()];
HOST_NAME.unsafe_set(Some(host_name));
HOST_ENTRY = hostent {
h_name: HOST_NAME.unsafe_mut().as_mut().unwrap().as_mut_ptr() as *mut c_char,
h_aliases: host_aliases.as_mut_slice().as_mut_ptr(),
h_addrtype: format,
h_length: length as i32,
h_addr_list: &raw mut HOST_ADDR_LIST as *mut _,
unsafe { _HOST_ADDR_LIST = addr.s_addr.to_ne_bytes() };
unsafe { HOST_ADDR_LIST = [&raw mut _HOST_ADDR_LIST as *mut c_char, ptr::null_mut()] };
unsafe { HOST_NAME.unsafe_set(Some(host_name)) };
unsafe {
HOST_ENTRY = hostent {
h_name: HOST_NAME.unsafe_mut().as_mut().unwrap().as_mut_ptr() as *mut c_char,
h_aliases: host_aliases.as_mut_slice().as_mut_ptr(),
h_addrtype: format,
h_length: length as i32,
h_addr_list: &raw mut HOST_ADDR_LIST as *mut _,
}
};
&raw mut HOST_ENTRY
}
@@ -327,8 +332,9 @@ pub unsafe extern "C" fn gethostbyaddr(
#[unsafe(no_mangle)]
#[deprecated]
pub unsafe extern "C" fn gethostbyname(name: *const c_char) -> *mut hostent {
let name_cstr =
CStr::from_nullable_ptr(name).expect("gethostbyname() called with a NULL pointer");
let name_cstr = unsafe {
CStr::from_nullable_ptr(name).expect("gethostbyname() called with a NULL pointer")
};
let Ok(name_str) = str::from_utf8(name_cstr.to_bytes()) else {
H_ERRNO.set(NO_RECOVERY);
return ptr::null_mut();
@@ -339,33 +345,33 @@ pub unsafe extern "C" fn gethostbyname(name: *const c_char) -> *mut hostent {
// Some implementations just skip resolution and copy the address to h_name
if let Some(s_addr) = parse_ipv4_string(name_str) {
let addr = in_addr { s_addr };
return gethostbyaddr(&addr as *const _ as *const c_void, 4, AF_INET);
return unsafe { gethostbyaddr(&addr as *const _ as *const c_void, 4, AF_INET) };
}
// check the hosts file first
let mut p: *mut hostent;
sethostent(HOST_STAYOPEN);
unsafe { sethostent(HOST_STAYOPEN) };
while {
p = gethostent();
p = unsafe { gethostent() };
!p.is_null()
} {
if strcasecmp((*p).h_name, name) == 0 {
sethostent(HOST_STAYOPEN);
if unsafe { strcasecmp((*p).h_name, name) } == 0 {
unsafe { sethostent(HOST_STAYOPEN) };
return p;
}
let mut cp = (*p).h_aliases;
let mut cp = unsafe { (*p).h_aliases };
loop {
if cp.is_null() {
break;
}
if (*cp).is_null() {
if (unsafe { *cp }).is_null() {
break;
}
if strcasecmp(*cp, name) == 0 {
sethostent(HOST_STAYOPEN);
if unsafe { strcasecmp(*cp, name) } == 0 {
unsafe { sethostent(HOST_STAYOPEN) };
return p;
}
cp = cp.offset(1);
cp = unsafe { cp.offset(1) };
}
}
@@ -385,10 +391,10 @@ pub unsafe extern "C" fn gethostbyname(name: *const c_char) -> *mut hostent {
};
let host_name: Vec<u8> = name_cstr.to_bytes().to_vec();
HOST_NAME.unsafe_set(Some(host_name));
_HOST_ADDR_LIST = host_addr.s_addr.to_ne_bytes();
HOST_ADDR_LIST = [&raw mut _HOST_ADDR_LIST as *mut c_char, ptr::null_mut()];
HOST_ADDR = Some(host_addr);
unsafe { HOST_NAME.unsafe_set(Some(host_name)) };
unsafe { _HOST_ADDR_LIST = host_addr.s_addr.to_ne_bytes() };
unsafe { HOST_ADDR_LIST = [&raw mut _HOST_ADDR_LIST as *mut c_char, ptr::null_mut()] };
unsafe { HOST_ADDR = Some(host_addr) };
//TODO actually get aliases
let mut _host_aliases: Vec<Vec<u8>> = Vec::new();
@@ -396,16 +402,18 @@ pub unsafe extern "C" fn gethostbyname(name: *const c_char) -> *mut hostent {
let mut host_aliases: Vec<*mut c_char> = Vec::new();
host_aliases.push(ptr::null_mut());
host_aliases.push(ptr::null_mut());
HOST_ALIASES.unsafe_set(Some(_host_aliases));
unsafe { HOST_ALIASES.unsafe_set(Some(_host_aliases)) };
HOST_ENTRY = hostent {
h_name: HOST_NAME.unsafe_mut().as_mut().unwrap().as_mut_ptr() as *mut c_char,
h_aliases: host_aliases.as_mut_slice().as_mut_ptr(),
h_addrtype: AF_INET,
h_length: 4,
h_addr_list: &raw mut HOST_ADDR_LIST as *mut _,
unsafe {
HOST_ENTRY = hostent {
h_name: unsafe { HOST_NAME.unsafe_mut().as_mut().unwrap().as_mut_ptr() } as *mut c_char,
h_aliases: host_aliases.as_mut_slice().as_mut_ptr(),
h_addrtype: AF_INET,
h_length: 4,
h_addr_list: &raw mut HOST_ADDR_LIST as *mut _,
}
};
sethostent(HOST_STAYOPEN);
unsafe { sethostent(HOST_STAYOPEN) };
&raw mut HOST_ENTRY as *mut hostent
}
@@ -418,17 +426,17 @@ pub unsafe extern "C" fn getnetbyaddr(net: u32, net_type: c_int) -> *mut netent
#[unsafe(no_mangle)]
pub unsafe extern "C" fn getnetbyname(name: *const c_char) -> *mut netent {
let mut n: *mut netent;
setnetent(NET_STAYOPEN);
unsafe { setnetent(NET_STAYOPEN) };
while {
n = getnetent();
n = unsafe { getnetent() };
!n.is_null()
} {
if strcasecmp((*n).n_name, name) == 0 {
setnetent(NET_STAYOPEN);
if unsafe { strcasecmp((*n).n_name, name) } == 0 {
unsafe { setnetent(NET_STAYOPEN) };
return n;
}
}
setnetent(NET_STAYOPEN);
unsafe { setnetent(NET_STAYOPEN) };
platform::ERRNO.set(ENOENT);
ptr::null_mut() as *mut netent
@@ -439,39 +447,39 @@ pub unsafe extern "C" fn getnetbyname(name: *const c_char) -> *mut netent {
pub unsafe extern "C" fn getnetent() -> *mut netent {
// TODO: Rustify implementation
if NETDB == 0 {
NETDB = Sys::open(c"/etc/networks".into(), O_RDONLY, 0).or_minus_one_errno();
if unsafe { NETDB } == 0 {
unsafe { NETDB = Sys::open(c"/etc/networks".into(), O_RDONLY, 0).or_minus_one_errno() };
}
let mut rlb = RawLineBuffer::new(NETDB);
rlb.seek(N_POS);
let mut rlb = RawLineBuffer::new(unsafe { NETDB });
rlb.seek(unsafe { N_POS });
let mut r: Box<str> = Box::default();
while r.is_empty() || r.split_whitespace().next() == None || r.starts_with('#') {
r = match rlb.next() {
Line::Some(s) => bytes_to_box_str(s),
_ => {
if NET_STAYOPEN == 0 {
endnetent();
if unsafe { NET_STAYOPEN } == 0 {
unsafe { endnetent() };
}
return ptr::null_mut();
}
};
}
rlb.next();
N_POS = rlb.line_pos();
unsafe { N_POS = rlb.line_pos() };
let mut iter: SplitWhitespace = r.split_whitespace();
let net_name = iter.next().unwrap().bytes().chain(Some(b'\0')).collect();
NET_NAME.unsafe_set(Some(net_name));
unsafe { NET_NAME.unsafe_set(Some(net_name)) };
let addr_vec: Vec<u8> = iter.next().unwrap().bytes().chain(Some(b'\0')).collect();
let addr_cstr = addr_vec.as_slice().as_ptr() as *const c_char;
let mut addr = mem::MaybeUninit::uninit();
inet_aton(addr_cstr, addr.as_mut_ptr());
let addr = addr.assume_init();
NET_ADDR = Some(ntohl(addr.s_addr));
unsafe { inet_aton(addr_cstr, addr.as_mut_ptr()) };
let addr = unsafe { addr.assume_init() };
unsafe { NET_ADDR = Some(ntohl(addr.s_addr)) };
let mut _net_aliases: Vec<Vec<u8>> = iter
.map(|alias| alias.bytes().chain(Some(b'\0')).collect())
@@ -481,13 +489,18 @@ pub unsafe extern "C" fn getnetent() -> *mut netent {
.map(|x| x.as_mut_ptr() as *mut c_char)
.chain(Some(ptr::null_mut()))
.collect();
NET_ALIASES.unsafe_set(Some(_net_aliases));
unsafe { NET_ALIASES.unsafe_set(Some(_net_aliases)) };
NET_ENTRY = netent {
n_name: NET_NAME.unsafe_mut().as_mut().unwrap().as_mut_ptr() as *mut c_char,
n_aliases: net_aliases.as_mut_slice().as_mut_ptr(),
n_addrtype: AF_INET,
n_net: NET_ADDR.unwrap() as c_ulong,
unsafe {
NET_ENTRY = netent {
n_name: unsafe { NET_NAME.unsafe_mut() }
.as_mut()
.unwrap()
.as_mut_ptr() as *mut c_char,
n_aliases: net_aliases.as_mut_slice().as_mut_ptr(),
n_addrtype: AF_INET,
n_net: NET_ADDR.unwrap() as c_ulong,
}
};
&raw mut NET_ENTRY as *mut netent
}
@@ -496,34 +509,34 @@ pub unsafe extern "C" fn getnetent() -> *mut netent {
#[unsafe(no_mangle)]
pub unsafe extern "C" fn getprotobyname(name: *const c_char) -> *mut protoent {
let mut p: *mut protoent;
setprotoent(PROTO_STAYOPEN);
unsafe { setprotoent(PROTO_STAYOPEN) };
while {
p = getprotoent();
p = unsafe { getprotoent() };
!p.is_null()
} {
if strcasecmp((*p).p_name, name) == 0 {
setprotoent(PROTO_STAYOPEN);
if unsafe { strcasecmp((*p).p_name, name) } == 0 {
unsafe { setprotoent(PROTO_STAYOPEN) };
return p;
}
let mut cp = (*p).p_aliases;
let mut cp = unsafe { (*p).p_aliases };
loop {
if cp.is_null() {
setprotoent(PROTO_STAYOPEN);
unsafe { setprotoent(PROTO_STAYOPEN) };
break;
}
if (*cp).is_null() {
setprotoent(PROTO_STAYOPEN);
if (unsafe { *cp }).is_null() {
unsafe { setprotoent(PROTO_STAYOPEN) };
break;
}
if strcasecmp(*cp, name) == 0 {
setprotoent(PROTO_STAYOPEN);
if unsafe { strcasecmp(*cp, name) } == 0 {
unsafe { setprotoent(PROTO_STAYOPEN) };
return p;
}
cp = cp.offset(1);
cp = unsafe { cp.offset(1) };
}
}
setprotoent(PROTO_STAYOPEN);
unsafe { setprotoent(PROTO_STAYOPEN) };
platform::ERRNO.set(ENOENT);
ptr::null_mut() as *mut protoent
@@ -532,18 +545,18 @@ pub unsafe extern "C" fn getprotobyname(name: *const c_char) -> *mut protoent {
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/endprotoent.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn getprotobynumber(number: c_int) -> *mut protoent {
setprotoent(PROTO_STAYOPEN);
unsafe { setprotoent(PROTO_STAYOPEN) };
let mut p: *mut protoent;
while {
p = getprotoent();
p = unsafe { getprotoent() };
!p.is_null()
} {
if (*p).p_proto == number {
setprotoent(PROTO_STAYOPEN);
if unsafe { (*p).p_proto } == number {
unsafe { setprotoent(PROTO_STAYOPEN) };
return p;
}
}
setprotoent(PROTO_STAYOPEN);
unsafe { setprotoent(PROTO_STAYOPEN) };
platform::ERRNO.set(ENOENT);
ptr::null_mut() as *mut protoent
}
@@ -551,27 +564,27 @@ pub unsafe extern "C" fn getprotobynumber(number: c_int) -> *mut protoent {
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/endprotoent.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn getprotoent() -> *mut protoent {
if PROTODB == 0 {
PROTODB = Sys::open(c"/etc/protocols".into(), O_RDONLY, 0).or_minus_one_errno();
if unsafe { PROTODB } == 0 {
unsafe { PROTODB = Sys::open(c"/etc/protocols".into(), O_RDONLY, 0).or_minus_one_errno() };
}
let mut rlb = RawLineBuffer::new(PROTODB);
rlb.seek(P_POS);
let mut rlb = RawLineBuffer::new(unsafe { PROTODB });
rlb.seek(unsafe { P_POS });
let mut r: Box<str> = Box::default();
while r.is_empty() || r.split_whitespace().next() == None || r.starts_with('#') {
r = match rlb.next() {
Line::Some(s) => bytes_to_box_str(s),
_ => {
if PROTO_STAYOPEN == 0 {
endprotoent();
if unsafe { PROTO_STAYOPEN } == 0 {
unsafe { endprotoent() };
}
return ptr::null_mut();
}
};
}
rlb.next();
P_POS = rlb.line_pos();
unsafe { P_POS = rlb.line_pos() };
let mut iter: SplitWhitespace = r.split_whitespace();
@@ -580,7 +593,7 @@ pub unsafe extern "C" fn getprotoent() -> *mut protoent {
let mut num = iter.next().unwrap().as_bytes().to_vec();
num.push(b'\0');
PROTO_NUM = Some(atoi(num.as_mut_slice().as_mut_ptr() as *mut c_char));
unsafe { PROTO_NUM = Some(atoi(num.as_mut_slice().as_mut_ptr() as *mut c_char)) };
let mut _proto_aliases: Vec<Vec<u8>> = iter
.map(|alias| alias.bytes().chain(Some(b'\0')).collect())
@@ -591,21 +604,25 @@ pub unsafe extern "C" fn getprotoent() -> *mut protoent {
.chain(Some(ptr::null_mut()))
.collect();
PROTO_ALIASES.unsafe_set(Some(_proto_aliases));
PROTO_NAME.unsafe_set(Some(proto_name));
unsafe { PROTO_ALIASES.unsafe_set(Some(_proto_aliases)) };
unsafe { PROTO_NAME.unsafe_set(Some(proto_name)) };
PROTO_ENTRY = protoent {
p_name: PROTO_NAME
.unsafe_mut()
.as_mut()
.unwrap()
.as_mut_slice()
.as_mut_ptr() as *mut c_char,
p_aliases: proto_aliases.as_mut_slice().as_mut_ptr() as *mut *mut c_char,
p_proto: PROTO_NUM.unwrap(),
unsafe {
PROTO_ENTRY = protoent {
p_name: unsafe {
PROTO_NAME
.unsafe_mut()
.as_mut()
.unwrap()
.as_mut_slice()
.as_mut_ptr()
} as *mut c_char,
p_aliases: proto_aliases.as_mut_slice().as_mut_ptr() as *mut *mut c_char,
p_proto: unsafe { PROTO_NUM }.unwrap(),
}
};
if PROTO_STAYOPEN == 0 {
endprotoent();
if unsafe { PROTO_STAYOPEN } == 0 {
unsafe { endprotoent() };
}
&raw mut PROTO_ENTRY as *mut protoent
}
@@ -613,30 +630,32 @@ pub unsafe extern "C" fn getprotoent() -> *mut protoent {
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/endservent.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn getservbyname(name: *const c_char, proto: *const c_char) -> *mut servent {
setservent(SERV_STAYOPEN);
unsafe { setservent(SERV_STAYOPEN) };
let mut p: *mut servent;
if proto.is_null() {
while {
p = getservent();
p = unsafe { getservent() };
!p.is_null()
} {
if strcasecmp((*p).s_name, name) == 0 {
setservent(SERV_STAYOPEN);
if unsafe { strcasecmp((*p).s_name, name) } == 0 {
unsafe { setservent(SERV_STAYOPEN) };
return p;
}
}
} else {
while {
p = getservent();
p = unsafe { getservent() };
!p.is_null()
} {
if strcasecmp((*p).s_name, name) == 0 && strcasecmp((*p).s_proto, proto) == 0 {
setservent(SERV_STAYOPEN);
if unsafe { strcasecmp((*p).s_name, name) } == 0
&& unsafe { strcasecmp((*p).s_proto, proto) } == 0
{
unsafe { setservent(SERV_STAYOPEN) };
return p;
}
}
}
setservent(SERV_STAYOPEN);
unsafe { setservent(SERV_STAYOPEN) };
platform::ERRNO.set(ENOENT);
ptr::null_mut() as *mut servent
}
@@ -644,30 +663,30 @@ pub unsafe extern "C" fn getservbyname(name: *const c_char, proto: *const c_char
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/endservent.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn getservbyport(port: c_int, proto: *const c_char) -> *mut servent {
setservent(SERV_STAYOPEN);
unsafe { setservent(SERV_STAYOPEN) };
let mut p: *mut servent;
if proto.is_null() {
while {
p = getservent();
p = unsafe { getservent() };
!p.is_null()
} {
if (*p).s_port == port {
setservent(SERV_STAYOPEN);
if unsafe { (*p).s_port } == port {
unsafe { setservent(SERV_STAYOPEN) };
return p;
}
}
} else {
while {
p = getservent();
p = unsafe { getservent() };
!p.is_null()
} {
if (*p).s_port == port && strcasecmp((*p).s_proto, proto) == 0 {
setservent(SERV_STAYOPEN);
if unsafe { (*p).s_port } == port && unsafe { strcasecmp((*p).s_proto, proto) } == 0 {
unsafe { setservent(SERV_STAYOPEN) };
return p;
}
}
}
setservent(SERV_STAYOPEN);
unsafe { setservent(SERV_STAYOPEN) };
platform::ERRNO.set(ENOENT);
ptr::null_mut()
}
@@ -675,12 +694,12 @@ pub unsafe extern "C" fn getservbyport(port: c_int, proto: *const c_char) -> *mu
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/endservent.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn getservent() -> *mut servent {
if SERVDB == 0 {
if unsafe { SERVDB } == 0 {
// TODO: Rustify
SERVDB = Sys::open(c"/etc/services".into(), O_RDONLY, 0).or_minus_one_errno();
unsafe { SERVDB = Sys::open(c"/etc/services".into(), O_RDONLY, 0).or_minus_one_errno() };
}
let mut rlb = RawLineBuffer::new(SERVDB);
rlb.seek(S_POS);
let mut rlb = RawLineBuffer::new(unsafe { SERVDB });
rlb.seek(unsafe { S_POS });
let r: Box<str> = Box::default();
@@ -688,8 +707,8 @@ pub unsafe extern "C" fn getservent() -> *mut servent {
let r = match rlb.next() {
Line::Some(s) => bytes_to_box_str(s),
_ => {
if SERV_STAYOPEN == 0 {
endservent();
if unsafe { SERV_STAYOPEN } == 0 {
unsafe { endservent() };
}
return ptr::null_mut();
}
@@ -709,15 +728,18 @@ pub unsafe extern "C" fn getservent() -> *mut servent {
Some(port) => port.bytes().chain(Some(b'\0')).collect(),
None => continue,
};
SERV_PORT =
Some(htons(atoi(port.as_mut_slice().as_mut_ptr() as *mut c_char) as u16) as u32 as i32);
unsafe {
SERV_PORT = Some(
htons(atoi(port.as_mut_slice().as_mut_ptr() as *mut c_char) as u16) as u32 as i32,
)
};
let proto = match split.next() {
Some(proto) => proto.bytes().chain(Some(b'\0')).collect(),
None => continue,
};
rlb.next();
S_POS = rlb.line_pos();
unsafe { S_POS = rlb.line_pos() };
/*
*let mut _serv_aliases: Vec<Vec<u8>> = Vec::new();
@@ -739,29 +761,31 @@ pub unsafe extern "C" fn getservent() -> *mut servent {
serv_aliases.push(ptr::null_mut());
serv_aliases.push(ptr::null_mut());
SERV_ALIASES.unsafe_set(Some(_serv_aliases));
SERV_NAME.unsafe_set(Some(serv_name));
SERV_PROTO.unsafe_set(Some(proto));
unsafe { SERV_ALIASES.unsafe_set(Some(_serv_aliases)) };
unsafe { SERV_NAME.unsafe_set(Some(serv_name)) };
unsafe { SERV_PROTO.unsafe_set(Some(proto)) };
SERV_ENTRY = servent {
s_name: SERV_NAME
.unsafe_mut()
.as_mut()
.unwrap()
.as_mut_slice()
.as_mut_ptr() as *mut c_char,
s_aliases: serv_aliases.as_mut_slice().as_mut_ptr() as *mut *mut c_char,
s_port: SERV_PORT.unwrap(),
s_proto: SERV_PROTO
.unsafe_mut()
.as_mut()
.unwrap()
.as_mut_slice()
.as_mut_ptr() as *mut c_char,
unsafe {
SERV_ENTRY = servent {
s_name: SERV_NAME
.unsafe_mut()
.as_mut()
.unwrap()
.as_mut_slice()
.as_mut_ptr() as *mut c_char,
s_aliases: serv_aliases.as_mut_slice().as_mut_ptr() as *mut *mut c_char,
s_port: SERV_PORT.unwrap(),
s_proto: SERV_PROTO
.unsafe_mut()
.as_mut()
.unwrap()
.as_mut_slice()
.as_mut_ptr() as *mut c_char,
}
};
if SERV_STAYOPEN == 0 {
endservent();
if unsafe { SERV_STAYOPEN } == 0 {
unsafe { endservent() };
}
break &raw mut SERV_ENTRY as *mut servent;
}
@@ -770,36 +794,36 @@ pub unsafe extern "C" fn getservent() -> *mut servent {
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/endnetent.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn setnetent(stayopen: c_int) {
NET_STAYOPEN = stayopen;
if NETDB == 0 {
NETDB = Sys::open(c"/etc/networks".into(), O_RDONLY, 0).or_minus_one_errno()
unsafe { NET_STAYOPEN = stayopen };
if unsafe { NETDB } == 0 {
unsafe { NETDB = Sys::open(c"/etc/networks".into(), O_RDONLY, 0).or_minus_one_errno() }
} else {
Sys::lseek(NETDB, 0, SEEK_SET);
N_POS = 0;
Sys::lseek(unsafe { NETDB }, 0, SEEK_SET);
unsafe { N_POS = 0 };
}
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/endprotoent.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn setprotoent(stayopen: c_int) {
PROTO_STAYOPEN = stayopen;
if PROTODB == 0 {
PROTODB = Sys::open(c"/etc/protocols".into(), O_RDONLY, 0).or_minus_one_errno()
unsafe { PROTO_STAYOPEN = stayopen };
if unsafe { PROTODB } == 0 {
unsafe { PROTODB = Sys::open(c"/etc/protocols".into(), O_RDONLY, 0).or_minus_one_errno() }
} else {
Sys::lseek(PROTODB, 0, SEEK_SET);
P_POS = 0;
Sys::lseek(unsafe { PROTODB }, 0, SEEK_SET);
unsafe { P_POS = 0 };
}
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/endservent.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn setservent(stayopen: c_int) {
SERV_STAYOPEN = stayopen;
if SERVDB == 0 {
SERVDB = Sys::open(c"/etc/services".into(), O_RDONLY, 0).or_minus_one_errno()
unsafe { SERV_STAYOPEN = stayopen };
if unsafe { SERVDB } == 0 {
unsafe { SERVDB = Sys::open(c"/etc/services".into(), O_RDONLY, 0).or_minus_one_errno() }
} else {
Sys::lseek(SERVDB, 0, SEEK_SET);
S_POS = 0;
Sys::lseek(unsafe { SERVDB }, 0, SEEK_SET);
unsafe { S_POS = 0 };
}
}
@@ -811,15 +835,19 @@ pub unsafe extern "C" fn getaddrinfo(
hints: *const addrinfo,
res: *mut *mut addrinfo,
) -> c_int {
let node_opt = CStr::from_nullable_ptr(node);
let service_opt = CStr::from_nullable_ptr(service);
let node_opt = unsafe { CStr::from_nullable_ptr(node) };
let service_opt = unsafe { CStr::from_nullable_ptr(service) };
let hints_opt = if hints.is_null() { None } else { Some(&*hints) };
let hints_opt = if hints.is_null() {
None
} else {
Some(unsafe { &*hints })
};
trace!(
"getaddrinfo({:?}, {:?}, {:?})",
node_opt.map(|c| str::from_utf8_unchecked(c.to_bytes())),
service_opt.map(|c| str::from_utf8_unchecked(c.to_bytes())),
node_opt.map(|c| unsafe { str::from_utf8_unchecked(c.to_bytes()) }),
service_opt.map(|c| unsafe { str::from_utf8_unchecked(c.to_bytes()) }),
hints_opt
);
@@ -829,12 +857,12 @@ pub unsafe extern "C" fn getaddrinfo(
let ai_socktype = hints_opt.map_or(0, |hints| hints.ai_socktype);
let mut ai_protocol; // = hints_opt.map_or(0, |hints| hints.ai_protocol);
*res = ptr::null_mut();
unsafe { *res = ptr::null_mut() };
let mut port = 0;
if let Some(service) = service_opt {
//TODO: Support other service definitions as well as AI_NUMERICSERV
match str::from_utf8_unchecked(service.to_bytes()).parse::<u16>() {
match unsafe { str::from_utf8_unchecked(service.to_bytes()) }.parse::<u16>() {
Ok(ok) => port = ok,
Err(_err) => (),
}
@@ -849,14 +877,14 @@ pub unsafe extern "C" fn getaddrinfo(
});
let lookuphost = if ai_flags & AI_NUMERICHOST > 0 {
match parse_ipv4_string(str::from_utf8_unchecked(node.to_bytes())) {
match parse_ipv4_string(unsafe { str::from_utf8_unchecked(node.to_bytes()) }) {
Some(s_addr) => s_addr.into(),
None => {
return EAI_NONAME;
}
}
} else {
match lookup_host(str::from_utf8_unchecked(node.to_bytes())) {
match lookup_host(unsafe { str::from_utf8_unchecked(node.to_bytes()) }) {
Ok(lookuphost) => lookuphost,
Err(e) => {
platform::ERRNO.set(e);
@@ -900,10 +928,10 @@ pub unsafe extern "C" fn getaddrinfo(
});
let mut indirect = res;
while !(*indirect).is_null() {
indirect = &mut (**indirect).ai_next;
while !(unsafe { *indirect }).is_null() {
indirect = &mut unsafe { (**indirect).ai_next };
}
*indirect = Box::into_raw(addrinfo);
unsafe { *indirect = Box::into_raw(addrinfo) };
}
0
@@ -924,7 +952,7 @@ pub unsafe extern "C" fn getnameinfo(
return EAI_FAMILY;
}
let sa = &*(addr as *const sockaddr_in);
let sa = unsafe { &*(addr as *const sockaddr_in) };
if !serv.is_null() && servlen > 0 {
if flags & NI_NUMERICSERV != 0 {
@@ -933,11 +961,17 @@ pub unsafe extern "C" fn getnameinfo(
if (servlen as usize) <= port_bytes.len() {
return EAI_MEMORY; // Buffer too small
}
ptr::copy_nonoverlapping(port_bytes.as_ptr() as *const c_char, serv, port_bytes.len());
*serv.add(port_bytes.len()) = 0;
unsafe {
ptr::copy_nonoverlapping(
port_bytes.as_ptr() as *const c_char,
serv,
port_bytes.len(),
)
};
unsafe { *serv.add(port_bytes.len()) = 0 };
} else {
// TODO: Implement service name lookup (e.g., from /etc/services)
*serv = 0;
unsafe { *serv = 0 };
}
}
@@ -949,8 +983,10 @@ pub unsafe extern "C" fn getnameinfo(
if (hostlen as usize) <= ip_bytes.len() {
return EAI_MEMORY; // Buffer too small
}
ptr::copy_nonoverlapping(ip_bytes.as_ptr() as *const c_char, host, ip_bytes.len());
*host.add(ip_bytes.len()) = 0;
unsafe {
ptr::copy_nonoverlapping(ip_bytes.as_ptr() as *const c_char, host, ip_bytes.len())
};
unsafe { *host.add(ip_bytes.len()) = 0 };
} else {
match lookup_addr(sa.sin_addr.clone()).map(|host_names| host_names.into_iter().next()) {
Ok(Some(hostname)) => {
@@ -1002,15 +1038,15 @@ pub unsafe extern "C" fn getnameinfo(
pub unsafe extern "C" fn freeaddrinfo(res: *mut addrinfo) {
let mut ai = res;
while !ai.is_null() {
let bai = Box::from_raw(ai);
let bai = unsafe { Box::from_raw(ai) };
if !bai.ai_canonname.is_null() {
drop(CString::from_raw(bai.ai_canonname));
drop(unsafe { CString::from_raw(bai.ai_canonname) });
}
if !bai.ai_addr.is_null() {
if bai.ai_addrlen == mem::size_of::<sockaddr_in>() as socklen_t {
Box::from_raw(bai.ai_addr as *mut sockaddr_in);
unsafe { Box::from_raw(bai.ai_addr as *mut sockaddr_in) };
} else if bai.ai_addrlen == mem::size_of::<sockaddr_in6>() as socklen_t {
Box::from_raw(bai.ai_addr as *mut sockaddr_in6);
unsafe { Box::from_raw(bai.ai_addr as *mut sockaddr_in6) };
} else {
eprintln!("freeaddrinfo: unknown ai_addrlen {}", bai.ai_addrlen);
}