Merge branch 'socketpair' into 'master'
Various socket-related changes and other See merge request redox-os/relibc!289
This commit is contained in:
+119
-10
@@ -1,6 +1,10 @@
|
||||
use crate::platform::{self, types::*};
|
||||
use crate::{
|
||||
io::{self, Write},
|
||||
platform::{self, WriteByte, types::*},
|
||||
};
|
||||
use core::{
|
||||
cmp,
|
||||
fmt,
|
||||
iter::IntoIterator,
|
||||
mem,
|
||||
ops::{Deref, DerefMut},
|
||||
@@ -53,8 +57,13 @@ impl<T> CVec<T> {
|
||||
}
|
||||
unsafe fn resize(&mut self, cap: usize) -> Result<(), AllocError> {
|
||||
let size = Self::check_mul(cap, mem::size_of::<T>())?;
|
||||
let ptr = NonNull::new(platform::realloc(self.ptr.as_ptr() as *mut c_void, size) as *mut T)
|
||||
.ok_or(AllocError)?;
|
||||
let ptr = if cap == 0 {
|
||||
NonNull::dangling()
|
||||
} else if self.cap > 0 {
|
||||
NonNull::new(platform::realloc(self.ptr.as_ptr() as *mut c_void, size) as *mut T).ok_or(AllocError)?
|
||||
} else {
|
||||
NonNull::new((platform::alloc(size)) as *mut T).ok_or(AllocError)?
|
||||
};
|
||||
self.ptr = ptr;
|
||||
self.cap = cap;
|
||||
Ok(())
|
||||
@@ -67,14 +76,17 @@ impl<T> CVec<T> {
|
||||
start = start.add(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Push stuff
|
||||
|
||||
pub fn reserve(&mut self, required: usize) -> Result<(), AllocError> {
|
||||
let reserved_len = self
|
||||
let required_len = self
|
||||
.len
|
||||
.checked_add(required)
|
||||
.ok_or(AllocError)
|
||||
.and_then(Self::check_bounds)?;
|
||||
let new_cap = cmp::min(reserved_len.next_power_of_two(), core::isize::MAX as usize);
|
||||
if new_cap > self.cap {
|
||||
if required_len > self.cap {
|
||||
let new_cap = cmp::min(required_len.next_power_of_two(), core::isize::MAX as usize);
|
||||
unsafe {
|
||||
self.resize(new_cap)?;
|
||||
}
|
||||
@@ -82,8 +94,8 @@ impl<T> CVec<T> {
|
||||
Ok(())
|
||||
}
|
||||
pub fn push(&mut self, elem: T) -> Result<(), AllocError> {
|
||||
self.reserve(1)?;
|
||||
unsafe {
|
||||
self.reserve(1)?;
|
||||
ptr::write(self.ptr.as_ptr().add(self.len), elem);
|
||||
}
|
||||
self.len += 1; // no need to bounds check, as new len <= cap
|
||||
@@ -93,21 +105,26 @@ impl<T> CVec<T> {
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
self.reserve(elems.len())?;
|
||||
unsafe {
|
||||
self.reserve(elems.len())?;
|
||||
ptr::copy_nonoverlapping(elems.as_ptr(), self.ptr.as_ptr().add(self.len), elems.len());
|
||||
}
|
||||
self.len += elems.len(); // no need to bounds check, as new len <= cap
|
||||
Ok(())
|
||||
}
|
||||
pub fn append(&mut self, other: &mut Self) -> Result<(), AllocError> {
|
||||
let len = other.len;
|
||||
other.len = 0; // move
|
||||
self.reserve(len)?;
|
||||
unsafe {
|
||||
self.reserve(other.len())?;
|
||||
ptr::copy_nonoverlapping(other.as_ptr(), self.ptr.as_ptr().add(self.len), other.len());
|
||||
ptr::copy_nonoverlapping(other.as_ptr(), self.ptr.as_ptr().add(self.len), len);
|
||||
}
|
||||
self.len += other.len(); // no need to bounds check, as new len <= cap
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Pop stuff
|
||||
|
||||
pub fn truncate(&mut self, len: usize) {
|
||||
if len < self.len {
|
||||
unsafe {
|
||||
@@ -126,6 +143,18 @@ impl<T> CVec<T> {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
pub fn pop(&mut self) -> Option<T> {
|
||||
if self.is_empty() {
|
||||
None
|
||||
} else {
|
||||
let elem = unsafe { ptr::read(self.as_ptr().add(self.len - 1)) };
|
||||
self.len -= 1;
|
||||
Some(elem)
|
||||
}
|
||||
}
|
||||
|
||||
// Misc stuff
|
||||
|
||||
pub fn capacity(&self) -> usize {
|
||||
self.cap
|
||||
}
|
||||
@@ -176,3 +205,83 @@ impl<'a, T> IntoIterator for &'a mut CVec<T> {
|
||||
<&mut [T]>::into_iter(&mut *self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for CVec<u8> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.extend_from_slice(buf).map_err(|err| io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
"AllocStringWriter::write failed to allocate",
|
||||
))?;
|
||||
Ok(buf.len())
|
||||
}
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
impl fmt::Write for CVec<u8> {
|
||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||
self.write(s.as_bytes()).map_err(|_| fmt::Error)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
impl WriteByte for CVec<u8> {
|
||||
fn write_u8(&mut self, byte: u8) -> fmt::Result {
|
||||
self.write(&[byte]).map_err(|_| fmt::Error)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::CVec;
|
||||
|
||||
#[test]
|
||||
fn push_pop() {
|
||||
let mut vec = CVec::new();
|
||||
vec.push(1).unwrap();
|
||||
vec.push(2).unwrap();
|
||||
vec.push(3).unwrap();
|
||||
assert_eq!(&vec[..], &[1, 2, 3]);
|
||||
assert_eq!(vec.pop().unwrap(), 3);
|
||||
assert_eq!(&vec[..], &[1, 2]);
|
||||
}
|
||||
#[test]
|
||||
fn extend_from_slice() {
|
||||
use core_io::Write;
|
||||
|
||||
let mut vec = CVec::new();
|
||||
vec.extend_from_slice(&[1, 2, 3]).unwrap();
|
||||
vec.extend_from_slice(&[4, 5, 6]).unwrap();
|
||||
assert_eq!(&vec[..], &[1, 2, 3, 4, 5, 6]);
|
||||
assert_eq!(vec.write(&[7, 8, 9]).unwrap(), 3);
|
||||
assert_eq!(&vec[..], &[1, 2, 3, 4, 5, 6, 7, 8, 9]);
|
||||
}
|
||||
#[test]
|
||||
fn dropped() {
|
||||
use alloc::rc::Rc;
|
||||
|
||||
let counter = Rc::new(());
|
||||
let mut vec = CVec::with_capacity(3).unwrap();
|
||||
vec.push(Rc::clone(&counter)).unwrap();
|
||||
vec.push(Rc::clone(&counter)).unwrap();
|
||||
vec.push(Rc::clone(&counter)).unwrap();
|
||||
assert_eq!(Rc::strong_count(&counter), 4);
|
||||
|
||||
let popped = vec.pop().unwrap();
|
||||
assert_eq!(Rc::strong_count(&counter), 4);
|
||||
drop(popped);
|
||||
assert_eq!(Rc::strong_count(&counter), 3);
|
||||
|
||||
vec.push(Rc::clone(&counter)).unwrap();
|
||||
vec.push(Rc::clone(&counter)).unwrap();
|
||||
vec.push(Rc::clone(&counter)).unwrap();
|
||||
|
||||
assert_eq!(vec.len(), 5);
|
||||
assert_eq!(Rc::strong_count(&counter), 6);
|
||||
vec.truncate(1);
|
||||
assert_eq!(Rc::strong_count(&counter), 2);
|
||||
|
||||
drop(vec);
|
||||
assert_eq!(Rc::strong_count(&counter), 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
sys_includes = []
|
||||
include_guard = "_AIO_H"
|
||||
include_guard = "_RELIBC_AIO_H"
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
no_includes = true
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
sys_includes = ["stdint.h", "sys/types.h"]
|
||||
include_guard = "_FENV_H"
|
||||
include_guard = "_RELIBC_FENV_H"
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
no_includes = true
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
sys_includes = []
|
||||
include_guard = "_TEMPLATE_H"
|
||||
include_guard = "_RELIBC_TEMPLATE_H"
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
no_includes = true
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
sys_includes = []
|
||||
include_guard = "_WCTYPE_H"
|
||||
include_guard = "_RELIBC_WCTYPE_H"
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
no_includes = true
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
sys_includes = ["bits/assert.h"]
|
||||
include_guard = "_ASSERT_H"
|
||||
include_guard = "_RELIBC_ASSERT_H"
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
no_includes = true
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
sys_includes = ["bits/ctype.h"]
|
||||
include_guard = "_CTYPE_H"
|
||||
include_guard = "_RELIBC_CTYPE_H"
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
no_includes = true
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
sys_includes = ["sys/types.h"]
|
||||
include_guard = "_DIRENT_H"
|
||||
include_guard = "_RELIBC_DIRENT_H"
|
||||
language = "C"
|
||||
style = "Both"
|
||||
trailer = "#include <bits/dirent.h>"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
sys_includes = []
|
||||
include_guard = "_DLFCN_H"
|
||||
include_guard = "_RELIBC_DLFCN_H"
|
||||
language = "C"
|
||||
style = "Type"
|
||||
no_includes = true
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
sys_includes = ["bits/errno.h"]
|
||||
include_guard = "_ERRNO_H"
|
||||
include_guard = "_RELIBC_ERRNO_H"
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
no_includes = true
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
sys_includes = ["stdarg.h", "sys/types.h"]
|
||||
include_guard = "_FCNTL_H"
|
||||
include_guard = "_RELIBC_FCNTL_H"
|
||||
trailer = "#include <bits/fcntl.h>"
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
sys_includes = ["sys/types.h", "bits/float.h"]
|
||||
include_guard = "_FLOAT_H"
|
||||
include_guard = "_RELIBC_FLOAT_H"
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
no_includes = true
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
include_guard = "_FNMATCH_H"
|
||||
include_guard = "_RELIBC_FNMATCH_H"
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
no_includes = true
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
sys_includes = ["unistd.h"]
|
||||
include_guard = "_GETOPT_H"
|
||||
include_guard = "_RELIBC_GETOPT_H"
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
no_includes = true
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
sys_includes = []
|
||||
include_guard = "_GRP_H"
|
||||
include_guard = "_RELIBC_GRP_H"
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
no_includes = true
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
sys_includes = ["stdint.h", "wchar.h"]
|
||||
include_guard = "_INTTYPES_H"
|
||||
include_guard = "_RELIBC_INTTYPES_H"
|
||||
trailer = "#include <bits/inttypes.h>"
|
||||
language = "C"
|
||||
style = "Type"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
sys_includes = []
|
||||
include_guard = "_LIBGEN_H"
|
||||
include_guard = "_RELIBC_LIBGEN_H"
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
no_includes = true
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
sys_includes = []
|
||||
include_guard = "_LIMITS_H"
|
||||
include_guard = "_RELIBC_LIMITS_H"
|
||||
trailer = "#include <bits/limits.h>"
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
include_guard = "_LOCALE_H"
|
||||
include_guard = "_RELIBC_LOCALE_H"
|
||||
trailer = "#include <bits/locale.h>"
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
sys_includes = ["sys/socket.h", "netinet/in.h"]
|
||||
include_guard = "_NETDB_H"
|
||||
include_guard = "_RELIBC_NETDB_H"
|
||||
trailer = "#include <bits/netdb.h>"
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
sys_includes = []
|
||||
include_guard = "_POLL_H"
|
||||
include_guard = "_RELIBC_POLL_H"
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
no_includes = true
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
sys_includes = ["stddef.h", "sys/types.h"]
|
||||
include_guard = "_PWD_H"
|
||||
include_guard = "_RELIBC_PWD_H"
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
no_includes = true
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
sys_includes = ["sys/types.h"]
|
||||
include_guard = "_REGEX_H"
|
||||
include_guard = "_RELIBC_REGEX_H"
|
||||
language = "C"
|
||||
style = "Type"
|
||||
no_includes = true
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
sys_includes = []
|
||||
include_guard = "_SEMAPHORE_H"
|
||||
include_guard = "_RELIBC_SEMAPHORE_H"
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
no_includes = true
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
sys_includes = ["sys/ioctl.h"]
|
||||
include_guard = "_SGTTY_H"
|
||||
include_guard = "_RELIBC_SGTTY_H"
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
no_includes = true
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
sys_includes = ["stdint.h", "sys/types.h"]
|
||||
include_guard = "_SIGNAL_H"
|
||||
include_guard = "_RELIBC_SIGNAL_H"
|
||||
trailer = "#include <bits/signal.h>"
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
sys_includes = ["stdarg.h", "stddef.h", "stdint.h", "sys/types.h"]
|
||||
include_guard = "_STDIO_H"
|
||||
include_guard = "_RELIBC_STDIO_H"
|
||||
trailer = "#include <bits/stdio.h>"
|
||||
language = "C"
|
||||
style = "Type"
|
||||
|
||||
@@ -16,6 +16,7 @@ use core::{
|
||||
|
||||
use crate::{
|
||||
c_str::CStr,
|
||||
c_vec::CVec,
|
||||
fs::File,
|
||||
header::{
|
||||
errno::{self, STR_ERROR},
|
||||
@@ -1021,9 +1022,11 @@ pub unsafe extern "C" fn vasprintf(
|
||||
format: *const c_char,
|
||||
ap: va_list,
|
||||
) -> c_int {
|
||||
let mut alloc_writer = platform::AllocStringWriter(ptr::null_mut(), 0);
|
||||
let mut alloc_writer = CVec::new();
|
||||
let ret = printf::printf(&mut alloc_writer, format, ap);
|
||||
*strp = alloc_writer.0 as *mut c_char;
|
||||
alloc_writer.push(0).unwrap();
|
||||
alloc_writer.shrink_to_fit().unwrap();
|
||||
*strp = alloc_writer.leak() as *mut c_char;
|
||||
ret
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
sys_includes = ["stddef.h", "alloca.h"]
|
||||
include_guard = "_STDLIB_H"
|
||||
include_guard = "_RELIBC_STDLIB_H"
|
||||
trailer = "#include <bits/stdlib.h>"
|
||||
language = "C"
|
||||
style = "Type"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
sys_includes = ["stddef.h", "stdint.h", "strings.h"]
|
||||
include_guard = "_STRING_H"
|
||||
include_guard = "_RELIBC_STRING_H"
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
no_includes = true
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
sys_includes = ["stddef.h", "stdint.h"]
|
||||
include_guard = "_STRINGS_H"
|
||||
include_guard = "_RELIBC_STRINGS_H"
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
no_includes = true
|
||||
|
||||
@@ -5,3 +5,12 @@ pub struct sockaddr_un {
|
||||
pub sun_family: sa_family_t,
|
||||
pub sun_path: [c_char; 108],
|
||||
}
|
||||
|
||||
impl sockaddr_un {
|
||||
pub fn path_offset(&self) -> usize {
|
||||
let base = self as *const _ as usize;
|
||||
let path = &self.sun_path as *const _ as usize;
|
||||
trace!("base: {:#X}, path: {:#X}", base, path);
|
||||
path - base
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
sys_includes = ["stdint.h"]
|
||||
include_guard = "_TERMIOS_H"
|
||||
include_guard = "_RELIBC_TERMIOS_H"
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
no_includes = true
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
sys_includes = ["sys/types.h", "stdint.h", "stddef.h"]
|
||||
include_guard = "_TIME_H"
|
||||
include_guard = "_RELIBC_TIME_H"
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
no_includes = true
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
sys_includes = ["stddef.h", "stdint.h", "sys/types.h"]
|
||||
include_guard = "_UNISTD_H"
|
||||
include_guard = "_RELIBC_UNISTD_H"
|
||||
trailer = "#include <bits/fcntl.h>\n#include <bits/unistd.h>"
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
sys_includes = []
|
||||
include_guard = "_UTIME_H"
|
||||
include_guard = "_RELIBC_UTIME_H"
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
no_includes = true
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
sys_includes = ["stddef.h", "stdint.h", "time.h", "stdio.h" ]
|
||||
include_guard = "_WCHAR_H"
|
||||
include_guard = "_RELIBC_WCHAR_H"
|
||||
header = "#include <bits/wchar.h>"
|
||||
language = "C"
|
||||
style = "Type"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
sys_includes = ["stddef.h", "stdint.h", "time.h", "stdio.h" ]
|
||||
include_guard = "_WCTYPE_H"
|
||||
include_guard = "_RELIBC_WCTYPE_H"
|
||||
header = "#include <bits/wctype.h>"
|
||||
language = "C"
|
||||
style = "Type"
|
||||
|
||||
+7
-43
@@ -104,45 +104,6 @@ impl Read for FileReader {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AllocStringWriter(pub *mut u8, pub usize);
|
||||
impl Write for AllocStringWriter {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
let ptr = unsafe { realloc(self.0 as *mut c_void, self.1 + buf.len() + 1) as *mut u8 };
|
||||
if ptr.is_null() {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
"AllocStringWriter::write failed to allocate",
|
||||
));
|
||||
}
|
||||
self.0 = ptr;
|
||||
|
||||
unsafe {
|
||||
ptr::copy_nonoverlapping(buf.as_ptr(), self.0.add(self.1), buf.len());
|
||||
self.1 += buf.len();
|
||||
*self.0.add(self.1) = 0;
|
||||
}
|
||||
|
||||
Ok(buf.len())
|
||||
}
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
impl fmt::Write for AllocStringWriter {
|
||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||
// can't fail
|
||||
self.write(s.as_bytes()).unwrap();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
impl WriteByte for AllocStringWriter {
|
||||
fn write_u8(&mut self, byte: u8) -> fmt::Result {
|
||||
// can't fail
|
||||
self.write(&[byte]).unwrap();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct StringWriter(pub *mut u8, pub usize);
|
||||
impl Write for StringWriter {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
@@ -155,11 +116,14 @@ impl Write for StringWriter {
|
||||
self.0 = self.0.add(copy_size);
|
||||
*self.0 = 0;
|
||||
}
|
||||
|
||||
Ok(copy_size)
|
||||
} else {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
// Pretend the entire slice was written. This is because many functions
|
||||
// (like snprintf) expects a return value that reflects how many bytes
|
||||
// *would have* been written. So keeping track of this information is
|
||||
// good, and then if we want the *actual* written size we can just go
|
||||
// `cmp::min(written, maxlen)`.
|
||||
Ok(buf.len())
|
||||
}
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
|
||||
@@ -29,9 +29,9 @@ impl PalEpoll for Sys {
|
||||
id: fd as usize,
|
||||
flags: syscall::EventFlags::from_bits(unsafe { (*event).events as usize })
|
||||
.expect("epoll: invalid bit pattern"),
|
||||
// NOTE: Danger when using non 64-bit systems. If this is
|
||||
// needed, use a box or something
|
||||
data: unsafe { mem::transmute((*event).data) },
|
||||
// NOTE: Danger when using something smaller than 64-bit
|
||||
// systems. If this is needed, use a box or something
|
||||
data: unsafe { (*event).data.u64 as usize },
|
||||
},
|
||||
) as c_int
|
||||
}
|
||||
@@ -102,7 +102,7 @@ impl PalEpoll for Sys {
|
||||
if bytes_read == -1 {
|
||||
return -1;
|
||||
}
|
||||
let read = bytes_read as usize / mem::size_of::<epoll_event>();
|
||||
let read = bytes_read as usize / mem::size_of::<syscall::Event>();
|
||||
|
||||
let mut count = 0;
|
||||
for i in 0..read {
|
||||
@@ -117,7 +117,7 @@ impl PalEpoll for Sys {
|
||||
}
|
||||
*event_ptr = epoll_event {
|
||||
events: event.flags.bits() as _,
|
||||
data: mem::transmute(event.data),
|
||||
data: epoll_data { u64: event.data as u64, },
|
||||
..Default::default()
|
||||
};
|
||||
count += 1;
|
||||
|
||||
@@ -9,6 +9,7 @@ use super::{
|
||||
use crate::header::{
|
||||
arpa_inet::inet_aton,
|
||||
netinet_in::{in_port_t, sockaddr_in, in_addr},
|
||||
string::strnlen,
|
||||
sys_socket::{constants::*, sa_family_t, sockaddr, socklen_t},
|
||||
sys_time::timeval,
|
||||
sys_un::sockaddr_un,
|
||||
@@ -32,13 +33,17 @@ macro_rules! bind_or_connect {
|
||||
0
|
||||
}};
|
||||
($mode:ident copy, $socket:expr, $address:expr, $address_len:expr) => {{
|
||||
if ($address_len as usize) < mem::size_of::<sockaddr>() {
|
||||
if ($address_len as usize) < mem::size_of::<sa_family_t>() {
|
||||
errno = syscall::EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
let path = match (*$address).sa_family as c_int {
|
||||
AF_INET => {
|
||||
if ($address_len as usize) != mem::size_of::<sockaddr_in>() {
|
||||
errno = syscall::EINVAL;
|
||||
return -1;
|
||||
}
|
||||
let data = &*($address as *const sockaddr_in);
|
||||
let addr = slice::from_raw_parts(
|
||||
&data.sin_addr.s_addr as *const _ as *const u8,
|
||||
@@ -58,14 +63,32 @@ macro_rules! bind_or_connect {
|
||||
},
|
||||
AF_UNIX => {
|
||||
let data = &*($address as *const sockaddr_un);
|
||||
|
||||
// NOTE: It's UB to access data in given address that exceeds
|
||||
// the given address length.
|
||||
|
||||
let maxlen = cmp::min(
|
||||
// Max path length of the full-sized struct
|
||||
data.sun_path.len(),
|
||||
// Length inferred from given addrlen
|
||||
$address_len as usize - data.path_offset()
|
||||
);
|
||||
let len = cmp::min(
|
||||
// The maximum length of the address
|
||||
maxlen,
|
||||
// The first NUL byte, if any
|
||||
strnlen(&data.sun_path as *const _, maxlen as size_t),
|
||||
);
|
||||
|
||||
let addr = slice::from_raw_parts(
|
||||
&data.sun_path as *const _ as *const u8,
|
||||
mem::size_of_val(&data.sun_path),
|
||||
len,
|
||||
);
|
||||
let path = format!(
|
||||
"{}",
|
||||
str::from_utf8(addr).unwrap()
|
||||
);
|
||||
trace!("path: {:?}", path);
|
||||
|
||||
path
|
||||
},
|
||||
@@ -91,7 +114,7 @@ unsafe fn inner_af_unix(buf: &[u8], address: *mut sockaddr, address_len: *mut so
|
||||
|
||||
let path = slice::from_raw_parts_mut(
|
||||
&mut data.sun_path as *mut _ as *mut u8,
|
||||
mem::size_of_val(&data.sun_path),
|
||||
data.sun_path.len(),
|
||||
);
|
||||
|
||||
let len = cmp::min(path.len(), buf.len());
|
||||
@@ -165,6 +188,19 @@ unsafe fn inner_get_name(
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn socket_kind(mut kind: c_int) -> (c_int, usize) {
|
||||
let mut flags = O_RDWR;
|
||||
if kind & SOCK_NONBLOCK == SOCK_NONBLOCK {
|
||||
kind &= !SOCK_NONBLOCK;
|
||||
flags |= O_NONBLOCK;
|
||||
}
|
||||
if kind & SOCK_CLOEXEC == SOCK_CLOEXEC {
|
||||
kind &= !SOCK_CLOEXEC;
|
||||
flags |= O_CLOEXEC;
|
||||
}
|
||||
(kind, flags)
|
||||
}
|
||||
|
||||
impl PalSocket for Sys {
|
||||
unsafe fn accept(socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int {
|
||||
let stream = e(syscall::dup(socket as usize, b"listen")) as c_int;
|
||||
@@ -357,7 +393,7 @@ impl PalSocket for Sys {
|
||||
e(Err(syscall::Error::new(syscall::ENOSYS))) as c_int
|
||||
}
|
||||
|
||||
unsafe fn socket(domain: c_int, mut kind: c_int, protocol: c_int) -> c_int {
|
||||
unsafe fn socket(domain: c_int, kind: c_int, protocol: c_int) -> c_int {
|
||||
if domain != AF_INET && domain != AF_UNIX {
|
||||
errno = syscall::EAFNOSUPPORT;
|
||||
return -1;
|
||||
@@ -367,15 +403,7 @@ impl PalSocket for Sys {
|
||||
// return -1;
|
||||
// }
|
||||
|
||||
let mut flags = O_RDWR;
|
||||
if kind & SOCK_NONBLOCK == SOCK_NONBLOCK {
|
||||
kind &= !SOCK_NONBLOCK;
|
||||
flags |= O_NONBLOCK;
|
||||
}
|
||||
if kind & SOCK_CLOEXEC == SOCK_CLOEXEC {
|
||||
kind &= !SOCK_CLOEXEC;
|
||||
flags |= O_CLOEXEC;
|
||||
}
|
||||
let (kind, flags) = socket_kind(kind);
|
||||
|
||||
// The tcp: and udp: schemes allow using no path,
|
||||
// and later specifying one using `dup`.
|
||||
@@ -386,19 +414,52 @@ impl PalSocket for Sys {
|
||||
_ => {
|
||||
errno = syscall::EPROTONOSUPPORT;
|
||||
-1
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn socketpair(domain: c_int, kind: c_int, protocol: c_int, sv: &mut [c_int; 2]) -> c_int {
|
||||
eprintln!(
|
||||
"socketpair({}, {}, {}, {:p})",
|
||||
domain,
|
||||
kind,
|
||||
protocol,
|
||||
sv.as_mut_ptr()
|
||||
);
|
||||
unsafe { errno = syscall::ENOSYS };
|
||||
return -1;
|
||||
let (kind, flags) = socket_kind(kind);
|
||||
|
||||
match (domain, kind) {
|
||||
(AF_UNIX, SOCK_STREAM) => {
|
||||
let listener = e(syscall::open("chan:", flags | O_CREAT));
|
||||
if listener == !0 {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// For now, chan: lets connects be instant, and instead blocks
|
||||
// on any I/O performed. So we don't need to mark this as
|
||||
// nonblocking.
|
||||
|
||||
let fd0 = e(syscall::dup(listener, b"connect"));
|
||||
if fd0 == !0 {
|
||||
let _ = syscall::close(listener);
|
||||
return -1;
|
||||
}
|
||||
|
||||
let fd1 = e(syscall::dup(listener, b"listen"));
|
||||
if fd1 == !0 {
|
||||
let _ = syscall::close(fd0);
|
||||
let _ = syscall::close(listener);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sv[0] = fd0 as c_int;
|
||||
sv[1] = fd1 as c_int;
|
||||
0
|
||||
},
|
||||
_ => unsafe {
|
||||
eprintln!(
|
||||
"socketpair({}, {}, {}, {:p})",
|
||||
domain,
|
||||
kind,
|
||||
protocol,
|
||||
sv.as_mut_ptr()
|
||||
);
|
||||
errno = syscall::EPROTONOSUPPORT;
|
||||
-1
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,3 +60,7 @@ Non-finite float madness:
|
||||
%F: INF -INF NAN -NAN
|
||||
%g: inf -inf nan -nan
|
||||
%G: INF -INF NAN -NAN
|
||||
Testing asprintf...
|
||||
printed: test string, value: 11
|
||||
printed: test string 2, value: 13
|
||||
printed: test string 2, value: 13
|
||||
|
||||
@@ -74,4 +74,16 @@ int main(void) {
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
puts("Testing asprintf...");
|
||||
char *s = NULL;
|
||||
int res = asprintf(&s, "test string");
|
||||
printf("printed: %s, value: %d\n", s, res);
|
||||
free(s);
|
||||
res = asprintf(&s, "test string %d", 2);
|
||||
printf("printed: %s, value: %d\n", s, res);
|
||||
free(s);
|
||||
res = asprintf(&s, "test %s %d", "string", 2);
|
||||
printf("printed: %s, value: %d\n", s, res);
|
||||
free(s);
|
||||
}
|
||||
|
||||
@@ -40,6 +40,5 @@ do
|
||||
if [ "${status}" != "0" ]
|
||||
then
|
||||
echo "# ${name}: failed with status ${status} #"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
Reference in New Issue
Block a user