Skip to content

Commit 5c23f2e

Browse files
committed
Fuchsia support for std::process via liblaunchpad.
1 parent 0491a23 commit 5c23f2e

File tree

7 files changed

+426
-5
lines changed

7 files changed

+426
-5
lines changed

src/libstd/build.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ fn main() {
6060
println!("cargo:rustc-link-lib=shell32");
6161
} else if target.contains("fuchsia") {
6262
println!("cargo:rustc-link-lib=magenta");
63+
println!("cargo:rustc-link-lib=mxio");
64+
println!("cargo:rustc-link-lib=launchpad"); // for std::process
6365
}
6466
}
6567

src/libstd/process.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -780,6 +780,8 @@ impl Child {
780780
///
781781
#[stable(feature = "process", since = "1.0.0")]
782782
pub fn wait_with_output(mut self) -> io::Result<Output> {
783+
//use io::ErrorKind;
784+
783785
drop(self.stdin.take());
784786

785787
let (mut stdout, mut stderr) = (Vec::new(), Vec::new());
@@ -794,8 +796,15 @@ impl Child {
794796
res.unwrap();
795797
}
796798
(Some(out), Some(err)) => {
797-
let res = read2(out.inner, &mut stdout, err.inner, &mut stderr);
798-
res.unwrap();
799+
match read2(out.inner, &mut stdout, err.inner, &mut stderr) {
800+
Ok(()) => { },
801+
#[cfg(not(target_os = "fuchsia"))]
802+
Err(ref e) => { panic!("Failed to read child's stdout and stderr: {:?}", e); },
803+
#[cfg(target_os = "fuchsia")]
804+
Err(_) => {
805+
// FIXME: Right now there's a bug in magenta's pipes implementation
806+
},
807+
}
799808
}
800809
}
801810

src/libstd/sys/unix/fd.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ impl FileDesc {
110110
#[cfg(not(any(target_env = "newlib",
111111
target_os = "solaris",
112112
target_os = "emscripten",
113+
target_os = "fuchsia",
113114
target_os = "haiku")))]
114115
pub fn set_cloexec(&self) -> io::Result<()> {
115116
unsafe {
@@ -120,6 +121,7 @@ impl FileDesc {
120121
#[cfg(any(target_env = "newlib",
121122
target_os = "solaris",
122123
target_os = "emscripten",
124+
target_os = "fuchsia",
123125
target_os = "haiku"))]
124126
pub fn set_cloexec(&self) -> io::Result<()> {
125127
unsafe {

src/libstd/sys/unix/magenta.rs

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![allow(non_camel_case_types)]
12+
13+
use os::raw::c_char;
14+
use u64;
15+
16+
use libc::{c_int, c_void};
17+
18+
pub type mx_handle_t = i32;
19+
pub type mx_vaddr_t = usize;
20+
pub type mx_rights_t = u32;
21+
pub type mx_status_t = i32;
22+
23+
pub type mx_size_t = usize;
24+
pub type mx_ssize_t = isize;
25+
26+
pub const MX_HANDLE_INVALID: mx_handle_t = 0;
27+
28+
pub type mx_time_t = u64;
29+
pub const MX_TIME_INFINITE : mx_time_t = u64::MAX;
30+
31+
pub const NO_ERROR : mx_status_t = 0;
32+
33+
pub type mx_signals_t = u32;
34+
35+
pub const MX_OBJECT_SIGNAL_3 : mx_signals_t = 1 << 3;
36+
37+
pub const MX_TASK_TERMINATED : mx_signals_t = MX_OBJECT_SIGNAL_3;
38+
39+
pub const MX_RIGHT_SAME_RIGHTS : mx_rights_t = 1 << 31;
40+
41+
pub type mx_object_info_topic_t = u32;
42+
43+
pub const MX_INFO_PROCESS : mx_object_info_topic_t = 3;
44+
45+
pub const MX_HND_TYPE_JOB: u32 = 6;
46+
47+
// Common MX_INFO header
48+
#[derive(Default)]
49+
#[repr(C)]
50+
pub struct mx_info_header_t {
51+
pub topic: u32, // identifies the info struct
52+
pub avail_topic_size: u16, // “native” size of the struct
53+
pub topic_size: u16, // size of the returned struct (<=topic_size)
54+
pub avail_count: u32, // number of records the kernel has
55+
pub count: u32, // number of records returned (limited by buffer size)
56+
}
57+
58+
#[derive(Default)]
59+
#[repr(C)]
60+
pub struct mx_record_process_t {
61+
pub return_code: c_int,
62+
}
63+
64+
// Returned for topic MX_INFO_PROCESS
65+
#[derive(Default)]
66+
#[repr(C)]
67+
pub struct mx_info_process_t {
68+
pub hdr: mx_info_header_t,
69+
pub rec: mx_record_process_t,
70+
}
71+
72+
#[link(name = "magenta")]
73+
extern {
74+
pub fn mx_handle_close(handle: mx_handle_t) -> mx_status_t;
75+
76+
pub fn mx_handle_duplicate(handle: mx_handle_t, rights: mx_rights_t,
77+
out: *const mx_handle_t) -> mx_handle_t;
78+
79+
pub fn mx_handle_wait_one(handle: mx_handle_t, signals: mx_signals_t, timeout: mx_time_t,
80+
pending: *mut mx_signals_t) -> mx_status_t;
81+
82+
pub fn mx_object_get_info(handle: mx_handle_t, topic: u32, buffer: *mut c_void,
83+
buffer_size: mx_size_t, actual_size: *mut mx_size_t,
84+
avail: *mut mx_size_t) -> mx_status_t;
85+
}
86+
87+
// Handle Info entries associate a type and optional
88+
// argument with each handle included in the process
89+
// arguments message.
90+
pub fn mx_hnd_info(hnd_type: u32, arg: u32) -> u32 {
91+
(hnd_type & 0xFFFF) | ((arg & 0xFFFF) << 16)
92+
}
93+
94+
#[link(name="mxio")]
95+
extern {
96+
pub fn mxio_get_startup_handle(id: u32) -> mx_handle_t;
97+
}
98+
99+
// From `enum special_handles` in system/ulib/launchpad/launchpad.c
100+
#[allow(unused)] pub const HND_LOADER_SVC: usize = 0;
101+
// HND_EXEC_VMO = 1
102+
#[allow(unused)] pub const HND_SPECIAL_COUNT: usize = 2;
103+
104+
#[repr(C)]
105+
pub struct launchpad_t {
106+
argc: u32,
107+
envc: u32,
108+
args: *const c_char,
109+
args_len: usize,
110+
env: *const c_char,
111+
env_len: usize,
112+
113+
handles: *mut mx_handle_t,
114+
handles_info: *mut u32,
115+
handle_count: usize,
116+
handle_alloc: usize,
117+
118+
entry: mx_vaddr_t,
119+
base: mx_vaddr_t,
120+
vdso_base: mx_vaddr_t,
121+
122+
stack_size: usize,
123+
124+
special_handles: [mx_handle_t; HND_SPECIAL_COUNT],
125+
loader_message: bool,
126+
}
127+
128+
#[link(name="launchpad")]
129+
extern {
130+
pub fn launchpad_create(job: mx_handle_t, name: *const c_char,
131+
lp: *mut *mut launchpad_t) -> mx_status_t;
132+
133+
pub fn launchpad_start(lp: *mut launchpad_t) -> mx_status_t;
134+
135+
pub fn launchpad_destroy(lp: *mut launchpad_t);
136+
137+
pub fn launchpad_arguments(lp: *mut launchpad_t, argc: c_int,
138+
argv: *const *const c_char) -> mx_status_t;
139+
140+
pub fn launchpad_environ(lp: *mut launchpad_t, envp: *const *const c_char) -> mx_status_t;
141+
142+
pub fn launchpad_clone_mxio_root(lp: *mut launchpad_t) -> mx_status_t;
143+
144+
pub fn launchpad_clone_mxio_cwd(lp: *mut launchpad_t) -> mx_status_t;
145+
146+
pub fn launchpad_clone_fd(lp: *mut launchpad_t, fd: c_int, target_fd: c_int) -> mx_status_t;
147+
148+
pub fn launchpad_transfer_fd(lp: *mut launchpad_t, fd: c_int, target_fd: c_int) -> mx_status_t;
149+
150+
pub fn launchpad_elf_load(lp: *mut launchpad_t, vmo: mx_handle_t) -> mx_status_t;
151+
152+
pub fn launchpad_add_vdso_vmo(lp: *mut launchpad_t) -> mx_status_t;
153+
154+
pub fn launchpad_load_vdso(lp: *mut launchpad_t, vmo: mx_handle_t) -> mx_status_t;
155+
156+
pub fn launchpad_vmo_from_file(filename: *const c_char) -> mx_handle_t;
157+
}

src/libstd/sys/unix/mod.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@
1313
use io::{self, ErrorKind};
1414
use libc;
1515

16+
#[cfg(target_os = "fuchsia")]
17+
use convert::TryInto;
18+
#[cfg(target_os = "fuchsia")]
19+
pub use self::magenta::mx_status_t;
20+
1621
#[cfg(target_os = "android")] pub use os::android as platform;
1722
#[cfg(target_os = "bitrig")] pub use os::bitrig as platform;
1823
#[cfg(target_os = "dragonfly")] pub use os::dragonfly as platform;
@@ -41,6 +46,8 @@ pub mod ext;
4146
pub mod fast_thread_local;
4247
pub mod fd;
4348
pub mod fs;
49+
#[cfg(target_os = "fuchsia")]
50+
pub mod magenta;
4451
pub mod memchr;
4552
pub mod mutex;
4653
pub mod net;
@@ -164,6 +171,19 @@ pub fn cvt_r<T, F>(mut f: F) -> io::Result<T>
164171
}
165172
}
166173

174+
#[cfg(target_os = "fuchsia")]
175+
pub fn mx_cvt<T>(t: T) -> io::Result<T> where T: TryInto<mx_status_t>+Copy {
176+
if let Ok(status) = TryInto::try_into(t) {
177+
if status < 0 {
178+
Err(io::Error::from_raw_os_error(status))
179+
} else {
180+
Ok(t)
181+
}
182+
} else {
183+
Err(io::Error::last_os_error())
184+
}
185+
}
186+
167187
// On Unix-like platforms, libc::abort will unregister signal handlers
168188
// including the SIGABRT handler, preventing the abort from being blocked, and
169189
// fclose streams, with the side effect of flushing them so libc bufferred

src/libstd/sys/unix/pipe.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ pub fn read2(p1: AnonPipe,
7777
v1: &mut Vec<u8>,
7878
p2: AnonPipe,
7979
v2: &mut Vec<u8>) -> io::Result<()> {
80+
8081
// Set both pipes into nonblocking mode as we're gonna be reading from both
8182
// in the `select` loop below, and we wouldn't want one to block the other!
8283
let p1 = p1.into_fd();

0 commit comments

Comments
 (0)