summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Lerche <me@carllerche.com>2014-08-17 03:07:38 -0700
committerCarl Lerche <me@carllerche.com>2014-08-17 03:07:38 -0700
commitf85e9bfbe5bfef4d8ce5985d29d9a173aa4d5fb0 (patch)
tree69abaf785d30e7aa8335fb7af4f7074a01629bb4
parent86b960d04ce31abd70d4922e364a7e8be1a6d6c5 (diff)
downloadnix-f85e9bfbe5bfef4d8ce5985d29d9a173aa4d5fb0.zip
More socket APIs
-rw-r--r--src/fcntl.rs7
-rw-r--r--src/features.rs1
-rw-r--r--src/lib.rs1
-rw-r--r--src/sys/mod.rs1
-rw-r--r--src/sys/socket.rs107
-rw-r--r--src/unistd.rs34
6 files changed, 141 insertions, 10 deletions
diff --git a/src/fcntl.rs b/src/fcntl.rs
index f4f0fded..486b95fe 100644
--- a/src/fcntl.rs
+++ b/src/fcntl.rs
@@ -34,7 +34,7 @@ bitflags!(
)
mod ffi {
- pub use libc::{open, close};
+ pub use libc::open;
}
pub fn open(path: &Path, oflag: OFlag, mode: FilePermission) -> SysResult<Fd> {
@@ -46,8 +46,3 @@ pub fn open(path: &Path, oflag: OFlag, mode: FilePermission) -> SysResult<Fd> {
Ok(fd)
}
-
-pub fn close(fd: Fd) -> SysResult<()> {
- let res = unsafe { ffi::close(fd) };
- from_ffi(res)
-}
diff --git a/src/features.rs b/src/features.rs
new file mode 100644
index 00000000..8b137891
--- /dev/null
+++ b/src/features.rs
@@ -0,0 +1 @@
+
diff --git a/src/lib.rs b/src/lib.rs
index e2ad38b1..e215605e 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -6,6 +6,7 @@ extern crate libc;
pub use errno::{SysResult, SysError};
pub mod errno;
+pub mod features;
pub mod fcntl;
pub mod mount;
pub mod sched;
diff --git a/src/sys/mod.rs b/src/sys/mod.rs
index 9d19e35d..5023cce8 100644
--- a/src/sys/mod.rs
+++ b/src/sys/mod.rs
@@ -1,3 +1,4 @@
pub mod epoll;
+pub mod socket;
pub mod stat;
pub mod utsname;
diff --git a/src/sys/socket.rs b/src/sys/socket.rs
new file mode 100644
index 00000000..66ee48e2
--- /dev/null
+++ b/src/sys/socket.rs
@@ -0,0 +1,107 @@
+#![cfg(target_os = "linux")]
+
+use std::{mem, ptr};
+use libc::{c_int, sockaddr, sockaddr_in, sockaddr_in6, sockaddr_un, socklen_t};
+use fcntl::Fd;
+use errno::{SysResult, SysError, from_ffi};
+
+mod ffi {
+ use libc::{c_int, sockaddr, socklen_t};
+
+ extern {
+ pub fn socket(domain: c_int, ty: c_int, proto: c_int) -> c_int;
+
+ pub fn listen(sockfd: c_int, backlog: c_int) -> c_int;
+
+ pub fn bind(sockfd: c_int, addr: *const sockaddr, addrlen: socklen_t) -> c_int;
+
+ pub fn accept(
+ sockfd: c_int,
+ addr: *const sockaddr,
+ addrlen: *mut socklen_t) -> c_int;
+
+ pub fn accept4(
+ sockfd: c_int,
+ addr: *const sockaddr,
+ addrlen: *mut socklen_t,
+ flags: c_int) -> c_int;
+ }
+}
+
+pub type AddressFamily = c_int;
+
+pub static AF_UNIX: AddressFamily = 1;
+pub static AF_LOCAL: AddressFamily = AF_UNIX;
+pub static AF_INET: AddressFamily = 2;
+pub static AF_INET6: AddressFamily = 10;
+
+pub type SockType = c_int;
+
+pub static SOCK_STREAM: SockType = 1;
+pub static SOCK_DGRAM: SockType = 1;
+pub static SOCK_SEQPACKET: SockType = 1;
+pub static SOCK_RAW: SockType = 1;
+pub static SOCK_RDM: SockType = 1;
+
+// Extra flags - Linux 2.6.27
+bitflags!(
+ flags SockFlag: c_int {
+ static SOCK_NONBLOCK = 0o0004000,
+ static SOCK_CLOEXEC = 0o2000000
+ }
+)
+
+pub fn socket(domain: AddressFamily, ty: SockType, flags: SockFlag) -> SysResult<Fd> {
+ // TODO: Check the kernel version
+ let res = unsafe { ffi::socket(domain, ty | flags.bits(), 0) };
+
+ if res < 0 {
+ return Err(SysError::last());
+ }
+
+ Ok(res)
+}
+
+pub fn listen(sockfd: Fd, backlog: uint) -> SysResult<()> {
+ let res = unsafe { ffi::listen(sockfd, backlog as c_int) };
+ from_ffi(res)
+}
+
+pub enum BindAddr<'a> {
+ BindIpV4(&'a sockaddr_in),
+ BindIpV6(&'a sockaddr_in6),
+ BindUnix(&'a sockaddr_un)
+}
+
+pub fn bind(sockfd: Fd, addr: BindAddr) -> SysResult<()> {
+ let res = unsafe {
+ match addr {
+ BindIpV4(addr) => ffi::bind(sockfd, mem::transmute(addr), mem::size_of::<sockaddr_in>() as socklen_t),
+ BindIpV6(addr) => ffi::bind(sockfd, mem::transmute(addr), mem::size_of::<sockaddr_in6>() as socklen_t),
+ BindUnix(addr) => ffi::bind(sockfd, mem::transmute(addr), mem::size_of::<sockaddr_un>() as socklen_t)
+ }
+ };
+
+ from_ffi(res)
+}
+
+pub fn accept(sockfd: Fd) -> SysResult<Fd> {
+ let res = unsafe { ffi::accept(sockfd, ptr::null(), ptr::mut_null()) };
+
+ if res < 0 {
+ return Err(SysError::last());
+ }
+
+ Ok(res)
+}
+
+pub fn accept4(sockfd: Fd, flags: SockFlag) -> SysResult<Fd> {
+ // TODO: Check the kernel version
+ let res = unsafe { ffi::accept4(sockfd, ptr::null(), ptr::mut_null(), flags.bits) };
+
+ if res < 0 {
+ return Err(SysError::last());
+ }
+
+ Ok(res)
+}
diff --git a/src/unistd.rs b/src/unistd.rs
index f4c4daa1..4b141f17 100644
--- a/src/unistd.rs
+++ b/src/unistd.rs
@@ -3,19 +3,20 @@
use std::ptr;
use std::c_str::{CString, ToCStr};
use std::path::Path;
-use libc::{c_char};
+use libc::{c_char, c_void, size_t};
use fcntl::{Fd, OFlag};
use syscall::{syscall, SysPivotRoot};
-use {SysResult, SysError};
+use errno::{SysResult, SysError, from_ffi};
mod ffi {
use libc::{c_char, c_int};
+ pub use libc::{close, read, write};
extern {
+ // duplicate a file descriptor
+ // doc: http://man7.org/linux/man-pages/man2/dup.2.html
pub fn dup(oldfd: c_int) -> c_int;
-
pub fn dup2(oldfd: c_int, newfd: c_int) -> c_int;
-
pub fn dup3(oldfd: c_int, newfd: c_int, flags: c_int) -> c_int;
// change working directory
@@ -107,3 +108,28 @@ pub fn pivot_root(new_root: &Path, put_old: &Path) -> SysResult<()> {
Ok(())
}
+
+pub fn close(fd: Fd) -> SysResult<()> {
+ let res = unsafe { ffi::close(fd) };
+ from_ffi(res)
+}
+
+pub fn read(fd: Fd, buf: &mut [u8]) -> SysResult<uint> {
+ let res = unsafe { ffi::read(fd, buf.as_mut_ptr() as *mut c_void, buf.len() as size_t) };
+
+ if res < 0 {
+ return Err(SysError::last());
+ }
+
+ return Ok(res as uint)
+}
+
+pub fn write(fd: Fd, buf: &[u8]) -> SysResult<uint> {
+ let res = unsafe { ffi::write(fd, buf.as_ptr() as *const c_void, buf.len() as size_t) };
+
+ if res < 0 {
+ return Err(SysError::last());
+ }
+
+ return Ok(res as uint)
+}