mod.rs 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259
  1. //! stdlib implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/stdlib.h.html
  2. use core::{convert::TryFrom, intrinsics, iter, mem, ptr, slice};
  3. use rand::{
  4. distributions::{Alphanumeric, Distribution, Uniform},
  5. prng::XorShiftRng,
  6. rngs::JitterRng,
  7. Rng, SeedableRng,
  8. };
  9. use crate::{
  10. c_str::CStr,
  11. fs::File,
  12. header::{
  13. ctype,
  14. errno::{self, *},
  15. fcntl::*,
  16. limits,
  17. stdio::flush_io_streams,
  18. string::*,
  19. time::constants::CLOCK_MONOTONIC,
  20. unistd::{self, sysconf, _SC_PAGESIZE},
  21. wchar::*,
  22. },
  23. ld_so,
  24. platform::{self, types::*, Pal, Sys},
  25. };
  26. mod rand48;
  27. mod random;
  28. mod sort;
  29. pub const EXIT_FAILURE: c_int = 1;
  30. pub const EXIT_SUCCESS: c_int = 0;
  31. pub const RAND_MAX: c_int = 2_147_483_647;
  32. //Maximum number of bytes in a multibyte character for the current locale
  33. pub const MB_CUR_MAX: c_int = 4;
  34. //Maximum number of bytes in a multibyte characters for any locale
  35. pub const MB_LEN_MAX: c_int = 4;
  36. static mut ATEXIT_FUNCS: [Option<extern "C" fn()>; 32] = [None; 32];
  37. static mut L64A_BUFFER: [c_char; 7] = [0; 7]; // up to 6 digits plus null terminator
  38. static mut RNG: Option<XorShiftRng> = None;
  39. lazy_static! {
  40. static ref RNG_SAMPLER: Uniform<c_int> = Uniform::new_inclusive(0, RAND_MAX);
  41. }
  42. #[no_mangle]
  43. pub extern "C" fn _Exit(status: c_int) {
  44. unistd::_exit(status);
  45. }
  46. #[no_mangle]
  47. pub unsafe extern "C" fn a64l(s: *const c_char) -> c_long {
  48. // Early return upon null pointer argument
  49. if s.is_null() {
  50. return 0;
  51. }
  52. // POSIX says only the low-order 32 bits are used.
  53. let mut l: i32 = 0;
  54. // Handle up to 6 input characters (excl. null terminator)
  55. for i in 0..6 {
  56. let digit_char = *s.offset(i);
  57. let digit_value = match digit_char {
  58. 0 => break, // Null terminator encountered
  59. 46..=57 => {
  60. // ./0123456789 represents values 0 to 11. b'.' == 46
  61. digit_char - 46
  62. }
  63. 65..=90 => {
  64. // A-Z for values 12 to 37. b'A' == 65, 65-12 == 53
  65. digit_char - 53
  66. }
  67. 97..=122 => {
  68. // a-z for values 38 to 63. b'a' == 97, 97-38 == 59
  69. digit_char - 59
  70. }
  71. _ => return 0, // Early return for anything else
  72. };
  73. l |= i32::from(digit_value) << 6 * i;
  74. }
  75. c_long::from(l)
  76. }
  77. #[no_mangle]
  78. pub unsafe extern "C" fn abort() -> ! {
  79. eprintln!("Abort");
  80. intrinsics::abort();
  81. }
  82. #[no_mangle]
  83. pub extern "C" fn abs(i: c_int) -> c_int {
  84. i.abs()
  85. }
  86. #[no_mangle]
  87. pub unsafe extern "C" fn aligned_alloc(alignment: size_t, size: size_t) -> *mut c_void {
  88. if size % alignment == 0 {
  89. /* The size-is-multiple-of-alignment requirement is the only
  90. * difference between aligned_alloc() and memalign(). */
  91. memalign(alignment, size)
  92. } else {
  93. platform::errno = EINVAL;
  94. ptr::null_mut()
  95. }
  96. }
  97. #[no_mangle]
  98. pub unsafe extern "C" fn atexit(func: Option<extern "C" fn()>) -> c_int {
  99. for i in 0..ATEXIT_FUNCS.len() {
  100. if ATEXIT_FUNCS[i] == None {
  101. ATEXIT_FUNCS[i] = func;
  102. return 0;
  103. }
  104. }
  105. 1
  106. }
  107. #[no_mangle]
  108. pub unsafe extern "C" fn atof(s: *const c_char) -> c_double {
  109. strtod(s, ptr::null_mut())
  110. }
  111. macro_rules! dec_num_from_ascii {
  112. ($s:expr, $t:ty) => {
  113. unsafe {
  114. let mut s = $s;
  115. // Iterate past whitespace
  116. while ctype::isspace(*s as c_int) != 0 {
  117. s = s.offset(1);
  118. }
  119. // Find out if there is a - sign
  120. let neg_sign = match *s {
  121. 0x2d => {
  122. s = s.offset(1);
  123. true
  124. }
  125. // '+' increment s and continue parsing
  126. 0x2b => {
  127. s = s.offset(1);
  128. false
  129. }
  130. _ => false,
  131. };
  132. let mut n: $t = 0;
  133. while ctype::isdigit(*s as c_int) != 0 {
  134. n = 10 * n - (*s as $t - 0x30);
  135. s = s.offset(1);
  136. }
  137. if neg_sign {
  138. n
  139. } else {
  140. -n
  141. }
  142. }
  143. };
  144. }
  145. #[no_mangle]
  146. pub extern "C" fn atoi(s: *const c_char) -> c_int {
  147. dec_num_from_ascii!(s, c_int)
  148. }
  149. #[no_mangle]
  150. pub extern "C" fn atol(s: *const c_char) -> c_long {
  151. dec_num_from_ascii!(s, c_long)
  152. }
  153. #[no_mangle]
  154. pub extern "C" fn atoll(s: *const c_char) -> c_longlong {
  155. dec_num_from_ascii!(s, c_longlong)
  156. }
  157. unsafe extern "C" fn void_cmp(a: *const c_void, b: *const c_void) -> c_int {
  158. *(a as *const i32) - *(b as *const i32) as c_int
  159. }
  160. #[no_mangle]
  161. pub unsafe extern "C" fn bsearch(
  162. key: *const c_void,
  163. base: *const c_void,
  164. nel: size_t,
  165. width: size_t,
  166. compar: Option<unsafe extern "C" fn(*const c_void, *const c_void) -> c_int>,
  167. ) -> *mut c_void {
  168. let mut start = base;
  169. let mut len = nel;
  170. let cmp_fn = compar.unwrap_or(void_cmp);
  171. while len > 0 {
  172. let med = (start as size_t + (len >> 1) * width) as *const c_void;
  173. let diff = cmp_fn(key, med);
  174. if diff == 0 {
  175. return med as *mut c_void;
  176. } else if diff > 0 {
  177. start = (med as usize + width) as *const c_void;
  178. len -= 1;
  179. }
  180. len >>= 1;
  181. }
  182. ptr::null_mut()
  183. }
  184. #[no_mangle]
  185. pub unsafe extern "C" fn calloc(nelem: size_t, elsize: size_t) -> *mut c_void {
  186. //Handle possible integer overflow in size calculation
  187. match nelem.checked_mul(elsize) {
  188. Some(size) => {
  189. /* If allocation fails here, errno setting will be handled
  190. * by malloc() */
  191. let ptr = malloc(size);
  192. if !ptr.is_null() {
  193. intrinsics::write_bytes(ptr as *mut u8, 0, size);
  194. }
  195. ptr
  196. }
  197. None => {
  198. // For overflowing multiplication, we have to set errno here
  199. platform::errno = ENOMEM;
  200. ptr::null_mut()
  201. }
  202. }
  203. }
  204. #[repr(C)]
  205. pub struct div_t {
  206. quot: c_int,
  207. rem: c_int,
  208. }
  209. #[no_mangle]
  210. pub extern "C" fn div(numer: c_int, denom: c_int) -> div_t {
  211. div_t {
  212. quot: numer / denom,
  213. rem: numer % denom,
  214. }
  215. }
  216. #[no_mangle]
  217. pub unsafe extern "C" fn drand48() -> c_double {
  218. let new_xsubi_value = rand48::generator_step(&mut rand48::DEFAULT_XSUBI);
  219. rand48::f64_from_x(new_xsubi_value)
  220. }
  221. // #[no_mangle]
  222. pub extern "C" fn ecvt(
  223. value: c_double,
  224. ndigit: c_int,
  225. decpt: *mut c_int,
  226. sign: *mut c_int,
  227. ) -> *mut c_char {
  228. unimplemented!();
  229. }
  230. #[no_mangle]
  231. pub unsafe extern "C" fn erand48(xsubi: *mut c_ushort) -> c_double {
  232. let new_xsubi_value = rand48::generator_step(&mut *(xsubi as *mut [c_ushort; 3]));
  233. rand48::f64_from_x(new_xsubi_value)
  234. }
  235. #[no_mangle]
  236. pub unsafe extern "C" fn exit(status: c_int) {
  237. extern "C" {
  238. static __fini_array_start: extern "C" fn();
  239. static __fini_array_end: extern "C" fn();
  240. fn pthread_terminate();
  241. fn _fini();
  242. }
  243. for i in (0..ATEXIT_FUNCS.len()).rev() {
  244. if let Some(func) = ATEXIT_FUNCS[i] {
  245. (func)();
  246. }
  247. }
  248. // Look for the neighbor functions in memory until the end
  249. let mut f = &__fini_array_end as *const _;
  250. #[allow(clippy::op_ref)]
  251. while f > &__fini_array_start {
  252. f = f.offset(-1);
  253. (*f)();
  254. }
  255. _fini();
  256. ld_so::fini();
  257. pthread_terminate();
  258. flush_io_streams();
  259. Sys::exit(status);
  260. }
  261. // #[no_mangle]
  262. pub extern "C" fn fcvt(
  263. value: c_double,
  264. ndigit: c_int,
  265. decpt: *mut c_int,
  266. sign: *mut c_int,
  267. ) -> *mut c_char {
  268. unimplemented!();
  269. }
  270. #[no_mangle]
  271. pub unsafe extern "C" fn free(ptr: *mut c_void) {
  272. platform::free(ptr);
  273. }
  274. // #[no_mangle]
  275. pub extern "C" fn gcvt(value: c_double, ndigit: c_int, buf: *mut c_char) -> *mut c_char {
  276. unimplemented!();
  277. }
  278. unsafe fn find_env(search: *const c_char) -> Option<(usize, *mut c_char)> {
  279. for (i, mut item) in platform::environ_iter().enumerate() {
  280. let mut search = search;
  281. loop {
  282. let end_of_query = *search == 0 || *search == b'=' as c_char;
  283. assert_ne!(*item, 0, "environ has an item without value");
  284. if *item == b'=' as c_char || end_of_query {
  285. if *item == b'=' as c_char && end_of_query {
  286. // Both keys env here
  287. return Some((i, item.add(1)));
  288. } else {
  289. break;
  290. }
  291. }
  292. if *item != *search {
  293. break;
  294. }
  295. item = item.add(1);
  296. search = search.add(1);
  297. }
  298. }
  299. None
  300. }
  301. #[no_mangle]
  302. pub unsafe extern "C" fn getenv(name: *const c_char) -> *mut c_char {
  303. find_env(name).map(|val| val.1).unwrap_or(ptr::null_mut())
  304. }
  305. // #[no_mangle]
  306. pub extern "C" fn getsubopt(
  307. optionp: *mut *mut c_char,
  308. tokens: *const *mut c_char,
  309. valuep: *mut *mut c_char,
  310. ) -> c_int {
  311. unimplemented!();
  312. }
  313. // #[no_mangle]
  314. pub extern "C" fn grantpt(fildes: c_int) -> c_int {
  315. unimplemented!();
  316. }
  317. #[no_mangle]
  318. pub unsafe extern "C" fn initstate(seed: c_uint, state: *mut c_char, size: size_t) -> *mut c_char {
  319. // Ported from musl
  320. if size < 8 {
  321. ptr::null_mut()
  322. } else {
  323. // TODO: lock?
  324. let old_state = random::save_state();
  325. random::N = match size {
  326. 0..=7 => unreachable!(), // ensured above
  327. 8..=31 => 0,
  328. 32..=63 => 7,
  329. 64..=127 => 15,
  330. 128..=255 => 31,
  331. _ => 63,
  332. };
  333. random::X_PTR = (state.cast::<[u8; 4]>()).offset(1);
  334. random::seed(seed);
  335. random::save_state();
  336. // TODO: unlock?
  337. old_state.cast::<_>()
  338. }
  339. }
  340. #[no_mangle]
  341. pub unsafe extern "C" fn jrand48(xsubi: *mut c_ushort) -> c_long {
  342. let new_xsubi_value = rand48::generator_step(&mut *(xsubi as *mut [c_ushort; 3]));
  343. rand48::i32_from_x(new_xsubi_value)
  344. }
  345. #[no_mangle]
  346. pub unsafe extern "C" fn l64a(value: c_long) -> *mut c_char {
  347. // POSIX says we should only consider the lower 32 bits of value.
  348. let value_as_i32 = value as i32;
  349. /* If we pretend to extend the 32-bit value with 4 binary zeros, we
  350. * would get a 36-bit integer. The number of base-64 digits to be
  351. * left unused can then be found by taking the number of leading
  352. * zeros, dividing by 6 and rounding down (i.e. using integer
  353. * division). */
  354. let num_output_digits = usize::try_from(6 - (value_as_i32.leading_zeros() + 4) / 6).unwrap();
  355. // Reset buffer (and have null terminator in place for any result)
  356. L64A_BUFFER = [0; 7];
  357. for i in 0..num_output_digits {
  358. // Conversion to c_char always succeeds for the range 0..=63
  359. let digit_value = c_char::try_from((value_as_i32 >> 6 * i) & 63).unwrap();
  360. L64A_BUFFER[i] = match digit_value {
  361. 0..=11 => {
  362. // ./0123456789 for values 0 to 11. b'.' == 46
  363. 46 + digit_value
  364. }
  365. 12..=37 => {
  366. // A-Z for values 12 to 37. b'A' == 65, 65-12 == 53
  367. 53 + digit_value
  368. }
  369. 38..=63 => {
  370. // a-z for values 38 to 63. b'a' == 97, 97-38 == 59
  371. 59 + digit_value
  372. }
  373. _ => unreachable!(), // Guaranteed by taking "& 63" above
  374. };
  375. }
  376. L64A_BUFFER.as_mut_ptr()
  377. }
  378. #[no_mangle]
  379. pub extern "C" fn labs(i: c_long) -> c_long {
  380. i.abs()
  381. }
  382. #[no_mangle]
  383. pub unsafe extern "C" fn lcong48(param: *mut c_ushort) {
  384. // Set DEFAULT_XSUBI buffer from elements 0-2
  385. let xsubi_value = rand48::u48_from_ushort_arr3(&*(param as *const [c_ushort; 3]));
  386. rand48::DEFAULT_XSUBI = rand48::ushort_arr3_from_u48(xsubi_value);
  387. // Set multiplier from elements 3-5
  388. rand48::A = rand48::u48_from_ushort_arr3(&*(param.offset(3) as *const [c_ushort; 3]));
  389. /* Set addend from element 6. Note that c_ushort may be more than 16
  390. * bits, thus the cast. */
  391. rand48::C = *param.offset(6) as u16;
  392. }
  393. #[repr(C)]
  394. pub struct ldiv_t {
  395. quot: c_long,
  396. rem: c_long,
  397. }
  398. #[no_mangle]
  399. pub extern "C" fn ldiv(numer: c_long, denom: c_long) -> ldiv_t {
  400. ldiv_t {
  401. quot: numer / denom,
  402. rem: numer % denom,
  403. }
  404. }
  405. #[no_mangle]
  406. pub extern "C" fn llabs(i: c_longlong) -> c_longlong {
  407. i.abs()
  408. }
  409. #[repr(C)]
  410. pub struct lldiv_t {
  411. quot: c_longlong,
  412. rem: c_longlong,
  413. }
  414. #[no_mangle]
  415. pub extern "C" fn lldiv(numer: c_longlong, denom: c_longlong) -> lldiv_t {
  416. lldiv_t {
  417. quot: numer / denom,
  418. rem: numer % denom,
  419. }
  420. }
  421. #[no_mangle]
  422. pub unsafe extern "C" fn lrand48() -> c_long {
  423. let new_xsubi_value = rand48::generator_step(&mut rand48::DEFAULT_XSUBI);
  424. rand48::u31_from_x(new_xsubi_value)
  425. }
  426. #[no_mangle]
  427. pub unsafe extern "C" fn malloc(size: size_t) -> *mut c_void {
  428. let ptr = platform::alloc(size);
  429. if ptr.is_null() {
  430. platform::errno = ENOMEM;
  431. }
  432. ptr
  433. }
  434. #[no_mangle]
  435. pub unsafe extern "C" fn memalign(alignment: size_t, size: size_t) -> *mut c_void {
  436. if alignment.is_power_of_two() {
  437. let ptr = platform::alloc_align(size, alignment);
  438. if ptr.is_null() {
  439. platform::errno = ENOMEM;
  440. }
  441. ptr
  442. } else {
  443. platform::errno = EINVAL;
  444. ptr::null_mut()
  445. }
  446. }
  447. #[no_mangle]
  448. pub unsafe extern "C" fn mblen(s: *const c_char, n: size_t) -> c_int {
  449. let mut wc: wchar_t = 0;
  450. let mut state: mbstate_t = mbstate_t {};
  451. let result: usize = mbrtowc(&mut wc, s, n, &mut state);
  452. if result == -1isize as usize {
  453. return -1;
  454. }
  455. if result == -2isize as usize {
  456. return -1;
  457. }
  458. result as i32
  459. }
  460. #[no_mangle]
  461. pub unsafe extern "C" fn mbstowcs(pwcs: *mut wchar_t, mut s: *const c_char, n: size_t) -> size_t {
  462. let mut state: mbstate_t = mbstate_t {};
  463. mbsrtowcs(pwcs, &mut s, n, &mut state)
  464. }
  465. #[no_mangle]
  466. pub unsafe extern "C" fn mbtowc(pwc: *mut wchar_t, s: *const c_char, n: size_t) -> c_int {
  467. let mut state: mbstate_t = mbstate_t {};
  468. mbrtowc(pwc, s, n, &mut state) as c_int
  469. }
  470. fn inner_mktemp<T, F>(name: *mut c_char, suffix_len: c_int, mut attempt: F) -> Option<T>
  471. where
  472. F: FnMut() -> Option<T>,
  473. {
  474. let len = unsafe { strlen(name) as c_int };
  475. if len < 6 || suffix_len > len - 6 {
  476. unsafe { platform::errno = errno::EINVAL };
  477. return None;
  478. }
  479. for i in (len - suffix_len - 6)..(len - suffix_len) {
  480. if unsafe { *name.offset(i as isize) } != b'X' as c_char {
  481. unsafe { platform::errno = errno::EINVAL };
  482. return None;
  483. }
  484. }
  485. let mut rng = JitterRng::new_with_timer(get_nstime);
  486. let _ = rng.test_timer();
  487. for _ in 0..100 {
  488. let char_iter = iter::repeat(())
  489. .map(|()| rng.sample(Alphanumeric))
  490. .take(6)
  491. .enumerate();
  492. unsafe {
  493. for (i, c) in char_iter {
  494. *name.offset((len as isize) - (suffix_len as isize) - (i as isize) - 1) =
  495. c as c_char
  496. }
  497. }
  498. if let result @ Some(_) = attempt() {
  499. return result;
  500. }
  501. }
  502. unsafe { platform::errno = errno::EEXIST }
  503. None
  504. }
  505. #[no_mangle]
  506. pub unsafe extern "C" fn mktemp(name: *mut c_char) -> *mut c_char {
  507. if inner_mktemp(name, 0, || {
  508. let name = CStr::from_ptr(name);
  509. if Sys::access(name, 0) != 0 && platform::errno == ENOENT {
  510. Some(())
  511. } else {
  512. None
  513. }
  514. })
  515. .is_none()
  516. {
  517. *name = 0;
  518. }
  519. name
  520. }
  521. fn get_nstime() -> u64 {
  522. let mut ts = mem::MaybeUninit::uninit();
  523. Sys::clock_gettime(CLOCK_MONOTONIC, ts.as_mut_ptr());
  524. unsafe { ts.assume_init() }.tv_nsec as u64
  525. }
  526. #[no_mangle]
  527. pub extern "C" fn mkostemps(name: *mut c_char, suffix_len: c_int, mut flags: c_int) -> c_int {
  528. flags &= !O_ACCMODE;
  529. flags |= O_RDWR | O_CREAT | O_EXCL;
  530. inner_mktemp(name, suffix_len, || {
  531. let name = unsafe { CStr::from_ptr(name) };
  532. let fd = Sys::open(name, flags, 0o600);
  533. if fd >= 0 {
  534. Some(fd)
  535. } else {
  536. None
  537. }
  538. })
  539. .unwrap_or(-1)
  540. }
  541. #[no_mangle]
  542. pub extern "C" fn mkstemp(name: *mut c_char) -> c_int {
  543. mkostemps(name, 0, 0)
  544. }
  545. #[no_mangle]
  546. pub extern "C" fn mkostemp(name: *mut c_char, flags: c_int) -> c_int {
  547. mkostemps(name, 0, flags)
  548. }
  549. #[no_mangle]
  550. pub extern "C" fn mkstemps(name: *mut c_char, suffix_len: c_int) -> c_int {
  551. mkostemps(name, suffix_len, 0)
  552. }
  553. #[no_mangle]
  554. pub unsafe extern "C" fn mrand48() -> c_long {
  555. let new_xsubi_value = rand48::generator_step(&mut rand48::DEFAULT_XSUBI);
  556. rand48::i32_from_x(new_xsubi_value)
  557. }
  558. #[no_mangle]
  559. pub unsafe extern "C" fn nrand48(xsubi: *mut c_ushort) -> c_long {
  560. let new_xsubi_value = rand48::generator_step(&mut *(xsubi as *mut [c_ushort; 3]));
  561. rand48::u31_from_x(new_xsubi_value)
  562. }
  563. #[no_mangle]
  564. pub unsafe extern "C" fn posix_memalign(
  565. memptr: *mut *mut c_void,
  566. alignment: size_t,
  567. size: size_t,
  568. ) -> c_int {
  569. const VOID_PTR_SIZE: usize = mem::size_of::<*mut c_void>();
  570. if alignment % VOID_PTR_SIZE == 0 && alignment.is_power_of_two() {
  571. let ptr = platform::alloc_align(size, alignment);
  572. *memptr = ptr;
  573. if ptr.is_null() {
  574. ENOMEM
  575. } else {
  576. 0
  577. }
  578. } else {
  579. *memptr = ptr::null_mut();
  580. EINVAL
  581. }
  582. }
  583. // #[no_mangle]
  584. pub extern "C" fn ptsname(fildes: c_int) -> *mut c_char {
  585. unimplemented!();
  586. }
  587. unsafe fn put_new_env(insert: *mut c_char) {
  588. // XXX: Another problem is that `environ` can be set to any pointer, which means there is a
  589. // chance of a memory leak. But we can check if it was the same as before, like musl does.
  590. if platform::environ == platform::OUR_ENVIRON.as_mut_ptr() {
  591. *platform::OUR_ENVIRON.last_mut().unwrap() = insert;
  592. platform::OUR_ENVIRON.push(core::ptr::null_mut());
  593. // Likely a no-op but is needed due to Stacked Borrows.
  594. platform::environ = platform::OUR_ENVIRON.as_mut_ptr();
  595. } else {
  596. platform::OUR_ENVIRON.clear();
  597. platform::OUR_ENVIRON.extend(platform::environ_iter());
  598. platform::OUR_ENVIRON.push(insert);
  599. platform::OUR_ENVIRON.push(core::ptr::null_mut());
  600. platform::environ = platform::OUR_ENVIRON.as_mut_ptr();
  601. }
  602. }
  603. #[no_mangle]
  604. pub unsafe extern "C" fn putenv(insert: *mut c_char) -> c_int {
  605. assert_ne!(insert, ptr::null_mut(), "putenv(NULL)");
  606. if let Some((i, _)) = find_env(insert) {
  607. // XXX: The POSIX manual states that environment variables can be *set* via the `environ`
  608. // global variable. While we can check if a pointer belongs to our allocator, or check
  609. // `environ` against a vector which we control, it is likely not worth the effort.
  610. platform::environ.add(i).write(insert);
  611. } else {
  612. put_new_env(insert);
  613. }
  614. 0
  615. }
  616. #[no_mangle]
  617. pub extern "C" fn qsort(
  618. base: *mut c_void,
  619. nel: size_t,
  620. width: size_t,
  621. compar: Option<extern "C" fn(*const c_void, *const c_void) -> c_int>,
  622. ) {
  623. if let Some(comp) = compar {
  624. // XXX: check width too? not specified
  625. if nel > 0 {
  626. // XXX: maybe try to do mergesort/timsort first and fallback to introsort if memory
  627. // allocation fails? not sure what is ideal
  628. sort::introsort(base as *mut c_char, nel, width, comp);
  629. }
  630. }
  631. }
  632. #[no_mangle]
  633. pub unsafe extern "C" fn rand() -> c_int {
  634. match RNG {
  635. Some(ref mut rng) => RNG_SAMPLER.sample(rng),
  636. None => {
  637. let mut rng = XorShiftRng::from_seed([1; 16]);
  638. let ret = RNG_SAMPLER.sample(&mut rng);
  639. RNG = Some(rng);
  640. ret
  641. }
  642. }
  643. }
  644. #[no_mangle]
  645. pub unsafe extern "C" fn rand_r(seed: *mut c_uint) -> c_int {
  646. if seed.is_null() {
  647. errno::EINVAL
  648. } else {
  649. // set the type explicitly so this will fail if the array size for XorShiftRng changes
  650. let seed_arr: [u8; 16] = mem::transmute([*seed; 16 / mem::size_of::<c_uint>()]);
  651. let mut rng = XorShiftRng::from_seed(seed_arr);
  652. let ret = RNG_SAMPLER.sample(&mut rng);
  653. *seed = ret as _;
  654. ret
  655. }
  656. }
  657. #[no_mangle]
  658. pub unsafe extern "C" fn random() -> c_long {
  659. // Ported from musl
  660. let k: u32;
  661. // TODO: lock?
  662. random::ensure_x_ptr_init();
  663. if random::N == 0 {
  664. let x_old = u32::from_ne_bytes(*random::X_PTR);
  665. let x_new = random::lcg31_step(x_old);
  666. *random::X_PTR = x_new.to_ne_bytes();
  667. k = x_new;
  668. } else {
  669. // The non-u32-aligned way of saying x[i] += x[j]...
  670. let x_i_old = u32::from_ne_bytes(*random::X_PTR.add(usize::from(random::I)));
  671. let x_j = u32::from_ne_bytes(*random::X_PTR.add(usize::from(random::J)));
  672. let x_i_new = x_i_old.wrapping_add(x_j);
  673. *random::X_PTR.add(usize::from(random::I)) = x_i_new.to_ne_bytes();
  674. k = x_i_new >> 1;
  675. random::I += 1;
  676. if random::I == random::N {
  677. random::I = 0;
  678. }
  679. random::J += 1;
  680. if random::J == random::N {
  681. random::J = 0;
  682. }
  683. }
  684. // TODO: unlock?
  685. /* Both branches of this function result in a "u31", which will
  686. * always fit in a c_long. */
  687. c_long::try_from(k).unwrap()
  688. }
  689. #[no_mangle]
  690. pub unsafe extern "C" fn realloc(ptr: *mut c_void, size: size_t) -> *mut c_void {
  691. let new_ptr = platform::realloc(ptr, size);
  692. if new_ptr.is_null() {
  693. platform::errno = ENOMEM;
  694. }
  695. new_ptr
  696. }
  697. #[no_mangle]
  698. pub unsafe extern "C" fn reallocarray(ptr: *mut c_void, m: size_t, n: size_t) -> *mut c_void {
  699. //Handle possible integer overflow in size calculation
  700. match m.checked_mul(n) {
  701. Some(size) => {
  702. realloc(ptr, size)
  703. }
  704. None => {
  705. // For overflowing multiplication, we have to set errno here
  706. platform::errno = ENOMEM;
  707. ptr::null_mut()
  708. }
  709. }
  710. }
  711. #[no_mangle]
  712. pub unsafe extern "C" fn realpath(pathname: *const c_char, resolved: *mut c_char) -> *mut c_char {
  713. let ptr = if resolved.is_null() {
  714. malloc(limits::PATH_MAX) as *mut c_char
  715. } else {
  716. resolved
  717. };
  718. let out = slice::from_raw_parts_mut(ptr as *mut u8, limits::PATH_MAX);
  719. {
  720. let file = match File::open(&CStr::from_ptr(pathname), O_PATH | O_CLOEXEC) {
  721. Ok(file) => file,
  722. Err(_) => return ptr::null_mut(),
  723. };
  724. let len = out.len();
  725. let read = Sys::fpath(*file, &mut out[..len - 1]);
  726. if read < 0 {
  727. return ptr::null_mut();
  728. }
  729. out[read as usize] = 0;
  730. }
  731. ptr
  732. }
  733. #[no_mangle]
  734. pub unsafe extern "C" fn seed48(seed16v: *mut c_ushort) -> *mut c_ushort {
  735. rand48::reset_a_and_c();
  736. // Stash current DEFAULT_XSUBI value in SEED48_XSUBI
  737. rand48::SEED48_XSUBI = rand48::DEFAULT_XSUBI;
  738. // Set DEFAULT_XSUBI from the argument provided
  739. let xsubi_value = rand48::u48_from_ushort_arr3(&*(seed16v as *const [c_ushort; 3]));
  740. rand48::DEFAULT_XSUBI = rand48::ushort_arr3_from_u48(xsubi_value);
  741. // Return the stashed value
  742. rand48::SEED48_XSUBI.as_mut_ptr()
  743. }
  744. unsafe fn copy_kv(
  745. existing: *mut c_char,
  746. key: *const c_char,
  747. value: *const c_char,
  748. key_len: usize,
  749. value_len: usize,
  750. ) {
  751. core::ptr::copy_nonoverlapping(key, existing, key_len);
  752. core::ptr::write(existing.add(key_len), b'=' as c_char);
  753. core::ptr::copy_nonoverlapping(value, existing.add(key_len + 1), value_len);
  754. core::ptr::write(existing.add(key_len + 1 + value_len), 0);
  755. }
  756. #[no_mangle]
  757. pub unsafe extern "C" fn setenv(
  758. key: *const c_char,
  759. value: *const c_char,
  760. overwrite: c_int,
  761. ) -> c_int {
  762. let key_len = strlen(key);
  763. let value_len = strlen(value);
  764. if let Some((i, existing)) = find_env(key) {
  765. if overwrite == 0 {
  766. return 0;
  767. }
  768. let existing_len = strlen(existing);
  769. if existing_len >= value_len {
  770. // Reuse existing element's allocation
  771. core::ptr::copy_nonoverlapping(value, existing, value_len);
  772. //TODO: fill to end with zeroes
  773. core::ptr::write(existing.add(value_len), 0);
  774. } else {
  775. // Reuse platform::environ slot, but allocate a new pointer.
  776. let ptr = platform::alloc(key_len as usize + 1 + value_len as usize + 1) as *mut c_char;
  777. copy_kv(ptr, key, value, key_len, value_len);
  778. platform::environ.add(i).write(ptr);
  779. }
  780. } else {
  781. // Expand platform::environ and allocate a new pointer.
  782. let ptr = platform::alloc(key_len as usize + 1 + value_len as usize + 1) as *mut c_char;
  783. copy_kv(ptr, key, value, key_len, value_len);
  784. put_new_env(ptr);
  785. }
  786. //platform::free(platform::inner_environ[index] as *mut c_void);
  787. 0
  788. }
  789. // #[no_mangle]
  790. pub extern "C" fn setkey(key: *const c_char) {
  791. unimplemented!();
  792. }
  793. #[no_mangle]
  794. pub unsafe extern "C" fn setstate(state: *mut c_char) -> *mut c_char {
  795. /* Ported from musl. The state parameter is no longer const in newer
  796. * versions of POSIX. */
  797. // TODO: lock?
  798. let old_state = random::save_state();
  799. random::load_state(state.cast::<_>());
  800. // TODO: unlock?
  801. old_state.cast::<_>()
  802. }
  803. #[no_mangle]
  804. pub unsafe extern "C" fn srand(seed: c_uint) {
  805. RNG = Some(XorShiftRng::from_seed([seed as u8; 16]));
  806. }
  807. #[no_mangle]
  808. pub unsafe extern "C" fn srand48(seedval: c_long) {
  809. rand48::reset_a_and_c();
  810. /* Set the high 32 bits of the 48-bit X_i value to the lower 32 bits
  811. * of the input argument, and the lower 16 bits to 0x330e, as
  812. * specified in POSIX. */
  813. let xsubi_value = (u64::from(seedval as u32) << 16) | 0x330e;
  814. rand48::DEFAULT_XSUBI = rand48::ushort_arr3_from_u48(xsubi_value);
  815. }
  816. #[no_mangle]
  817. pub unsafe extern "C" fn srandom(seed: c_uint) {
  818. // Ported from musl
  819. // TODO: lock?
  820. random::seed(seed);
  821. // TODO: unlock?
  822. }
  823. #[no_mangle]
  824. pub unsafe extern "C" fn strtod(s: *const c_char, endptr: *mut *mut c_char) -> c_double {
  825. strto_float_impl!(c_double, s, endptr)
  826. }
  827. #[no_mangle]
  828. pub unsafe extern "C" fn strtof(s: *const c_char, endptr: *mut *mut c_char) -> c_float {
  829. strto_float_impl!(c_float, s, endptr)
  830. }
  831. pub fn is_positive(ch: c_char) -> Option<(bool, isize)> {
  832. match ch {
  833. 0 => None,
  834. ch if ch == b'+' as c_char => Some((true, 1)),
  835. ch if ch == b'-' as c_char => Some((false, 1)),
  836. _ => Some((true, 0)),
  837. }
  838. }
  839. pub unsafe fn detect_base(s: *const c_char) -> Option<(c_int, isize)> {
  840. let first = *s as u8;
  841. match first {
  842. 0 => None,
  843. b'0' => {
  844. let second = *s.offset(1) as u8;
  845. if second == b'X' || second == b'x' {
  846. Some((16, 2))
  847. } else if second >= b'0' && second <= b'7' {
  848. Some((8, 1))
  849. } else {
  850. // in this case, the prefix (0) is going to be the number
  851. Some((8, 0))
  852. }
  853. }
  854. _ => Some((10, 0)),
  855. }
  856. }
  857. pub unsafe fn convert_octal(s: *const c_char) -> Option<(c_ulong, isize, bool)> {
  858. if *s != 0 && *s == b'0' as c_char {
  859. if let Some((val, idx, overflow)) = convert_integer(s.offset(1), 8) {
  860. Some((val, idx + 1, overflow))
  861. } else {
  862. // in case the prefix is not actually a prefix
  863. Some((0, 1, false))
  864. }
  865. } else {
  866. None
  867. }
  868. }
  869. pub unsafe fn convert_hex(s: *const c_char) -> Option<(c_ulong, isize, bool)> {
  870. if (*s != 0 && *s == b'0' as c_char)
  871. && (*s.offset(1) != 0 && (*s.offset(1) == b'x' as c_char || *s.offset(1) == b'X' as c_char))
  872. {
  873. convert_integer(s.offset(2), 16).map(|(val, idx, overflow)| (val, idx + 2, overflow))
  874. } else {
  875. convert_integer(s, 16).map(|(val, idx, overflow)| (val, idx, overflow))
  876. }
  877. }
  878. pub unsafe fn convert_integer(s: *const c_char, base: c_int) -> Option<(c_ulong, isize, bool)> {
  879. // -1 means the character is invalid
  880. #[rustfmt::skip]
  881. const LOOKUP_TABLE: [c_long; 256] = [
  882. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  883. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  884. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  885. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
  886. -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
  887. 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
  888. -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
  889. 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
  890. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  891. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  892. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  893. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  894. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  895. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  896. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  897. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  898. ];
  899. let mut num: c_ulong = 0;
  900. let mut idx = 0;
  901. let mut overflowed = false;
  902. loop {
  903. // `-1 as usize` is usize::MAX
  904. // `-1 as u8 as usize` is u8::MAX
  905. // It extends by the sign bit unless we cast it to unsigned first.
  906. let val = LOOKUP_TABLE[*s.offset(idx) as u8 as usize];
  907. if val == -1 || val as c_int >= base {
  908. break;
  909. } else {
  910. if let Some(res) = num
  911. .checked_mul(base as c_ulong)
  912. .and_then(|num| num.checked_add(val as c_ulong))
  913. {
  914. num = res;
  915. } else {
  916. platform::errno = ERANGE;
  917. num = c_ulong::max_value();
  918. overflowed = true;
  919. }
  920. idx += 1;
  921. }
  922. }
  923. if idx > 0 {
  924. Some((num, idx, overflowed))
  925. } else {
  926. None
  927. }
  928. }
  929. #[no_mangle]
  930. pub unsafe extern "C" fn strtoul(
  931. s: *const c_char,
  932. endptr: *mut *mut c_char,
  933. base: c_int,
  934. ) -> c_ulong {
  935. strto_impl!(
  936. c_ulong,
  937. false,
  938. c_ulong::max_value(),
  939. c_ulong::min_value(),
  940. s,
  941. endptr,
  942. base
  943. )
  944. }
  945. #[no_mangle]
  946. pub unsafe extern "C" fn strtol(s: *const c_char, endptr: *mut *mut c_char, base: c_int) -> c_long {
  947. strto_impl!(
  948. c_long,
  949. true,
  950. c_long::max_value(),
  951. c_long::min_value(),
  952. s,
  953. endptr,
  954. base
  955. )
  956. }
  957. #[no_mangle]
  958. pub unsafe extern "C" fn strtoull(
  959. s: *const c_char,
  960. endptr: *mut *mut c_char,
  961. base: c_int,
  962. ) -> c_ulonglong {
  963. strto_impl!(
  964. c_ulonglong,
  965. false,
  966. c_ulonglong::max_value(),
  967. c_ulonglong::min_value(),
  968. s,
  969. endptr,
  970. base
  971. )
  972. }
  973. #[no_mangle]
  974. pub unsafe extern "C" fn strtoll(
  975. s: *const c_char,
  976. endptr: *mut *mut c_char,
  977. base: c_int,
  978. ) -> c_longlong {
  979. strto_impl!(
  980. c_longlong,
  981. true,
  982. c_longlong::max_value(),
  983. c_longlong::min_value(),
  984. s,
  985. endptr,
  986. base
  987. )
  988. }
  989. #[no_mangle]
  990. pub unsafe extern "C" fn system(command: *const c_char) -> c_int {
  991. //TODO: share code with popen
  992. let child_pid = unistd::fork();
  993. if child_pid == 0 {
  994. let command_nonnull = if command.is_null() {
  995. "exit 0\0".as_ptr()
  996. } else {
  997. command as *const u8
  998. };
  999. let shell = "/bin/sh\0".as_ptr();
  1000. let args = [
  1001. "sh\0".as_ptr(),
  1002. "-c\0".as_ptr(),
  1003. command_nonnull,
  1004. ptr::null(),
  1005. ];
  1006. unistd::execv(shell as *const c_char, args.as_ptr() as *const *mut c_char);
  1007. exit(127);
  1008. unreachable!();
  1009. } else if child_pid > 0 {
  1010. let mut wstatus = 0;
  1011. if Sys::waitpid(child_pid, &mut wstatus, 0) == !0 {
  1012. return -1;
  1013. }
  1014. wstatus
  1015. } else {
  1016. -1
  1017. }
  1018. }
  1019. // #[no_mangle]
  1020. pub extern "C" fn ttyslot() -> c_int {
  1021. unimplemented!();
  1022. }
  1023. // #[no_mangle]
  1024. pub extern "C" fn unlockpt(fildes: c_int) -> c_int {
  1025. unimplemented!();
  1026. }
  1027. #[no_mangle]
  1028. pub unsafe extern "C" fn unsetenv(key: *const c_char) -> c_int {
  1029. if let Some((i, _)) = find_env(key) {
  1030. if platform::environ == platform::OUR_ENVIRON.as_mut_ptr() {
  1031. // No need to worry about updating the pointer, this does not
  1032. // reallocate in any way. And the final null is already shifted back.
  1033. platform::OUR_ENVIRON.remove(i);
  1034. // My UB paranoia.
  1035. platform::environ = platform::OUR_ENVIRON.as_mut_ptr();
  1036. } else {
  1037. platform::OUR_ENVIRON.clear();
  1038. platform::OUR_ENVIRON.extend(
  1039. platform::environ_iter()
  1040. .enumerate()
  1041. .filter(|&(j, _)| j != i)
  1042. .map(|(_, v)| v),
  1043. );
  1044. platform::OUR_ENVIRON.push(core::ptr::null_mut());
  1045. platform::environ = platform::OUR_ENVIRON.as_mut_ptr();
  1046. }
  1047. }
  1048. 0
  1049. }
  1050. #[no_mangle]
  1051. pub unsafe extern "C" fn valloc(size: size_t) -> *mut c_void {
  1052. /* sysconf(_SC_PAGESIZE) is a c_long and may in principle not
  1053. * convert correctly to a size_t. */
  1054. match size_t::try_from(sysconf(_SC_PAGESIZE)) {
  1055. Ok(page_size) => {
  1056. /* valloc() is not supposed to be able to set errno to
  1057. * EINVAL, hence no call to memalign(). */
  1058. let ptr = platform::alloc_align(size, page_size);
  1059. if ptr.is_null() {
  1060. platform::errno = ENOMEM;
  1061. }
  1062. ptr
  1063. }
  1064. Err(_) => {
  1065. // A corner case. No errno setting.
  1066. ptr::null_mut()
  1067. }
  1068. }
  1069. }
  1070. #[no_mangle]
  1071. pub extern "C" fn wcstombs(s: *mut c_char, mut pwcs: *const wchar_t, n: size_t) -> size_t {
  1072. let mut state: mbstate_t = mbstate_t {};
  1073. wcsrtombs(s, &mut pwcs, n, &mut state)
  1074. }
  1075. #[no_mangle]
  1076. pub unsafe extern "C" fn wctomb(s: *mut c_char, wc: wchar_t) -> c_int {
  1077. let mut state: mbstate_t = mbstate_t {};
  1078. let result: usize = wcrtomb(s, wc, &mut state);
  1079. if result == -1isize as usize {
  1080. return -1;
  1081. }
  1082. if result == -2isize as usize {
  1083. return -1;
  1084. }
  1085. result as c_int
  1086. }