Merge branch 'master' of https://github.com/redox-os/relibc
This commit is contained in:
@@ -5,6 +5,7 @@ cache: cargo
|
||||
before_script:
|
||||
- rustup component add rustfmt-preview
|
||||
- rustup target add x86_64-unknown-redox
|
||||
- rustup target add aarch64-unknown-linux-gnu
|
||||
script:
|
||||
- bash ./ci.sh
|
||||
notifications:
|
||||
|
||||
Generated
+17
-7
@@ -31,6 +31,11 @@ dependencies = [
|
||||
"toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.2"
|
||||
@@ -105,11 +110,6 @@ name = "fuchsia-zircon-sys"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "gcc"
|
||||
version = "0.3.54"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "grp"
|
||||
version = "0.1.0"
|
||||
@@ -258,6 +258,7 @@ dependencies = [
|
||||
"mman 0.1.0",
|
||||
"platform 0.1.0",
|
||||
"semaphore 0.1.0",
|
||||
"stat 0.1.0",
|
||||
"stdio 0.1.0",
|
||||
"stdlib 0.1.0",
|
||||
"string 0.1.0",
|
||||
@@ -440,6 +441,14 @@ dependencies = [
|
||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stat"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"cbindgen 0.5.0",
|
||||
"platform 0.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stdio"
|
||||
version = "0.1.0"
|
||||
@@ -456,6 +465,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"cbindgen 0.5.0",
|
||||
"ctype 0.1.0",
|
||||
"errno 0.1.0",
|
||||
"platform 0.1.0",
|
||||
"ralloc 1.0.0",
|
||||
]
|
||||
@@ -576,7 +586,7 @@ dependencies = [
|
||||
name = "va_list-helper"
|
||||
version = "0.0.2"
|
||||
dependencies = [
|
||||
"gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -625,13 +635,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b3568b48b7cefa6b8ce125f9bb4989e52fbcc29ebea88df04cc7c5f12f70455"
|
||||
"checksum atty 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8352656fd42c30a0c3c89d26dea01e3b77c0ab2af18230835c15e2e13cd51859"
|
||||
"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf"
|
||||
"checksum cc 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "9be26b24e988625409b19736d130f0c7d224f01d06454b5f81d8d23d6c1a618f"
|
||||
"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
|
||||
"checksum clap 2.30.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1c07b9257a00f3fc93b7f3c417fc15607ec7a56823bc2c37ec744e266387de5b"
|
||||
"checksum compiler_builtins 0.1.0 (git+https://github.com/rust-lang-nursery/compiler-builtins.git)" = "<none>"
|
||||
"checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
|
||||
"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
|
||||
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
|
||||
"checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb"
|
||||
"checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c"
|
||||
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||
"checksum libc 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)" = "56aebce561378d99a0bb578f8cb15b6114d2a1814a6c7949bbe646d968bb4fa9"
|
||||
|
||||
@@ -19,6 +19,7 @@ fcntl = { path = "src/fcntl" }
|
||||
grp = { path = "src/grp" }
|
||||
semaphore = { path = "src/semaphore" }
|
||||
mman = { path = "src/mman" }
|
||||
stat = { path = "src/stat" }
|
||||
stdio = { path = "src/stdio" }
|
||||
stdlib = { path = "src/stdlib" }
|
||||
string = { path = "src/string" }
|
||||
|
||||
@@ -5,3 +5,13 @@ The motivation for this project is twofold: Reduce issues the redox crew was hav
|
||||
|
||||
## Contributing
|
||||
Just search for any invocation of the `unimplemented` macro, and hop in! The ci server checks builds for linux and redox, checks formatting (via rustfmt), and runs the test suite. Run `ci.sh` locally to check that your changes will pass travis. Use `fmt.sh` to format your code and `test.sh` to run the C test suite.
|
||||
|
||||
## Supported OSes
|
||||
|
||||
- RedoxOS
|
||||
- Linux
|
||||
|
||||
## Supported architectures
|
||||
|
||||
- x86\_64
|
||||
- Aarch64
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
sed -i 's/::std::os::raw::/libc::/g' $1
|
||||
sed -i 's/::std::os::raw:://g' $1
|
||||
perl -i -p0e 's/extern "C" \{\n pub fn/#[no_mangle]\npub extern "C" fn/g' $1
|
||||
perl -i -p0e 's/;\n\}/ {\n unimplemented!();\n\}\n/g' $1
|
||||
rustfmt $1
|
||||
|
||||
@@ -4,3 +4,9 @@ set -ex
|
||||
./fmt.sh -- --write-mode=diff
|
||||
./test.sh
|
||||
cargo build --target=x86_64-unknown-redox
|
||||
if [ $(arch) == "x86_64" ]
|
||||
then
|
||||
cargo build --target=aarch64-unknown-linux-gnu
|
||||
else
|
||||
cargo build --target=x86_64-unknown-linux-gnu
|
||||
fi
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
#ifndef _STAT_H
|
||||
#define _STAT_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
struct stat {
|
||||
dev_t st_dev;
|
||||
ino_t st_ino;
|
||||
nlink_t st_nlink;
|
||||
mode_t st_mode;
|
||||
uid_t st_uid;
|
||||
gid_t st_gid;
|
||||
dev_t st_rdev;
|
||||
off_t st_size;
|
||||
blksize_t st_blksize;
|
||||
time_t st_atim;
|
||||
time_t st_mtim;
|
||||
time_t st_ctim;
|
||||
};
|
||||
|
||||
int chmod(const char *path, mode_t mode);
|
||||
|
||||
int fchmod(int fildes, mode_t mode);
|
||||
|
||||
int fstat(int fildes, struct stat *buf);
|
||||
|
||||
int lstat(const char *path, struct stat *buf);
|
||||
|
||||
int mkdir(const char *path, mode_t mode);
|
||||
|
||||
int mkfifo(const char *path, mode_t mode);
|
||||
|
||||
int mknod(const char *path, mode_t mode, dev_t dev);
|
||||
|
||||
int stat(const char *file, struct stat *buf);
|
||||
|
||||
mode_t umask(mode_t mask);
|
||||
|
||||
#endif /* _STAT_H */
|
||||
@@ -1,17 +1,27 @@
|
||||
#ifndef _SYS_TYPES_H
|
||||
#define _SYS_TYPES_H
|
||||
|
||||
typedef long blksize_t;
|
||||
|
||||
typedef long dev_t;
|
||||
|
||||
typedef unsigned long ino_t;
|
||||
|
||||
typedef int gid_t;
|
||||
typedef int uid_t;
|
||||
|
||||
typedef int mode_t;
|
||||
|
||||
typedef unsigned long nlink_t;
|
||||
|
||||
typedef long off_t;
|
||||
|
||||
typedef int pid_t;
|
||||
|
||||
typedef long ssize_t;
|
||||
|
||||
typedef long time_t;
|
||||
|
||||
typedef int useconds_t;
|
||||
|
||||
#endif /* _SYS_TYPES_H */
|
||||
|
||||
@@ -10,6 +10,7 @@ extern crate fcntl;
|
||||
extern crate grp;
|
||||
extern crate mman;
|
||||
extern crate semaphore;
|
||||
extern crate stat;
|
||||
extern crate stdio;
|
||||
extern crate stdlib;
|
||||
extern crate string;
|
||||
|
||||
@@ -4,6 +4,7 @@ use errno;
|
||||
use types::*;
|
||||
|
||||
const AT_FDCWD: c_int = -100;
|
||||
const AT_REMOVEDIR: c_int = 0x200;
|
||||
|
||||
pub fn e(sys: usize) -> usize {
|
||||
if (sys as isize) < 0 && (sys as isize) >= -256 {
|
||||
@@ -67,7 +68,7 @@ pub fn fcntl(fildes: c_int, cmd: c_int, arg: c_int) -> c_int {
|
||||
}
|
||||
|
||||
pub fn fork() -> pid_t {
|
||||
e(unsafe { syscall!(FORK) }) as pid_t
|
||||
e(unsafe { syscall!(CLONE, 17, 0) }) as pid_t
|
||||
}
|
||||
|
||||
pub fn fsync(fildes: c_int) -> c_int {
|
||||
@@ -115,7 +116,11 @@ pub fn getuid() -> uid_t {
|
||||
}
|
||||
|
||||
pub fn link(path1: *const c_char, path2: *const c_char) -> c_int {
|
||||
e(unsafe { syscall!(LINKAT, AT_FDCWD, path1, path2) }) as c_int
|
||||
e(unsafe { syscall!(LINKAT, AT_FDCWD, path1, AT_FDCWD, path2, 0) }) as c_int
|
||||
}
|
||||
|
||||
pub fn mkdir(path: *const c_char, mode: mode_t) -> c_int {
|
||||
e(unsafe { syscall!(MKDIRAT, AT_FDCWD, path, mode) }) as c_int
|
||||
}
|
||||
|
||||
pub fn open(path: *const c_char, oflag: c_int, mode: mode_t) -> c_int {
|
||||
@@ -130,6 +135,26 @@ pub fn read(fildes: c_int, buf: &mut [u8]) -> ssize_t {
|
||||
e(unsafe { syscall!(READ, fildes, buf.as_mut_ptr(), buf.len()) }) as ssize_t
|
||||
}
|
||||
|
||||
pub fn rmdir(path: *const c_char) -> c_int {
|
||||
e(unsafe { syscall!(UNLINKAT, AT_FDCWD, path, AT_REMOVEDIR) }) as c_int
|
||||
}
|
||||
|
||||
pub fn setpgid(pid: pid_t, pgid: pid_t) -> c_int {
|
||||
e(unsafe { syscall!(SETPGID, pid, pgid) }) as c_int
|
||||
}
|
||||
|
||||
pub fn setregid(rgid: gid_t, egid: gid_t) -> c_int {
|
||||
e(unsafe { syscall!(SETREGID, rgid, egid) }) as c_int
|
||||
}
|
||||
|
||||
pub fn setreuid(ruid: uid_t, euid: uid_t) -> c_int {
|
||||
e(unsafe { syscall!(SETREUID, ruid, euid) }) as c_int
|
||||
}
|
||||
|
||||
pub fn unlink(path: *const c_char) -> c_int {
|
||||
e(unsafe { syscall!(UNLINKAT, AT_FDCWD, path, 0) }) as c_int
|
||||
}
|
||||
|
||||
pub fn write(fildes: c_int, buf: &[u8]) -> ssize_t {
|
||||
e(unsafe { syscall!(WRITE, fildes, buf.as_ptr(), buf.len()) }) as ssize_t
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use core::ptr;
|
||||
use core::slice;
|
||||
use syscall;
|
||||
use syscall::flag::*;
|
||||
|
||||
use c_str;
|
||||
use errno;
|
||||
@@ -122,6 +123,18 @@ pub fn link(path1: *const c_char, path2: *const c_char) -> c_int {
|
||||
e(unsafe { syscall::link(path1.as_ptr(), path2.as_ptr()) }) as c_int
|
||||
}
|
||||
|
||||
pub fn mkdir(path: *const c_char, mode: mode_t) -> c_int {
|
||||
let flags = O_CREAT | O_EXCL | O_CLOEXEC | O_DIRECTORY | mode as usize & 0o777;
|
||||
let path = unsafe { c_str(path) };
|
||||
match syscall::open(path, flags) {
|
||||
Ok(fd) => {
|
||||
syscall::close(fd);
|
||||
0
|
||||
}
|
||||
Err(err) => e(Err(err)) as c_int,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn open(path: *const c_char, oflag: c_int, mode: mode_t) -> c_int {
|
||||
let path = unsafe { c_str(path) };
|
||||
e(syscall::open(path, (oflag as usize) | (mode as usize))) as c_int
|
||||
@@ -139,6 +152,28 @@ pub fn read(fd: c_int, buf: &mut [u8]) -> ssize_t {
|
||||
e(syscall::read(fd as usize, buf)) as ssize_t
|
||||
}
|
||||
|
||||
pub fn rmdir(path: *const c_char) -> c_int {
|
||||
let path = unsafe { c_str(path) };
|
||||
e(syscall::rmdir(path)) as c_int
|
||||
}
|
||||
|
||||
pub fn setpgid(pid: pid_t, pgid: pid_t) -> c_int {
|
||||
e(syscall::setpgid(pid as usize, pgid as usize)) as c_int
|
||||
}
|
||||
|
||||
pub fn setregid(rgid: gid_t, egid: gid_t) -> c_int {
|
||||
e(syscall::setregid(rgid as usize, egid as usize)) as c_int
|
||||
}
|
||||
|
||||
pub fn setreuid(ruid: uid_t, euid: uid_t) -> c_int {
|
||||
e(syscall::setreuid(ruid as usize, euid as usize)) as c_int
|
||||
}
|
||||
|
||||
pub fn unlink(path: *const c_char) -> c_int {
|
||||
let path = unsafe { c_str(path) };
|
||||
e(syscall::unlink(path)) as c_int
|
||||
}
|
||||
|
||||
pub fn write(fd: c_int, buf: &[u8]) -> ssize_t {
|
||||
e(syscall::write(fd as usize, buf)) as ssize_t
|
||||
}
|
||||
|
||||
@@ -52,6 +52,10 @@ pub type time_t = i64;
|
||||
pub type pid_t = usize;
|
||||
pub type gid_t = usize;
|
||||
pub type uid_t = usize;
|
||||
pub type dev_t = usize;
|
||||
pub type ino_t = usize;
|
||||
pub type nlink_t = usize;
|
||||
pub type blksize_t = isize;
|
||||
|
||||
pub type useconds_t = i32;
|
||||
pub type suseconds_t = i64;
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
[package]
|
||||
name = "stat"
|
||||
version = "0.1.0"
|
||||
authors = ["Jeremy Soller <jackpot51@gmail.com>"]
|
||||
build = "build.rs"
|
||||
|
||||
[build-dependencies]
|
||||
cbindgen = { path = "../../cbindgen" }
|
||||
|
||||
[dependencies]
|
||||
platform = { path = "../platform" }
|
||||
@@ -0,0 +1,13 @@
|
||||
extern crate cbindgen;
|
||||
|
||||
use std::{env, fs};
|
||||
|
||||
fn main() {
|
||||
/*
|
||||
*let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
|
||||
*fs::create_dir_all("../../target/include").expect("failed to create include directory");
|
||||
*cbindgen::generate(crate_dir)
|
||||
* .expect("failed to generate bindings")
|
||||
* .write_to_file("../../target/include/sys/stat.h");
|
||||
*/
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
sys_includes = ["sys/types.h"]
|
||||
include_guard = "_SYS_STAT_H"
|
||||
language = "C"
|
||||
|
||||
[enum]
|
||||
prefix_with_name = true
|
||||
@@ -0,0 +1,75 @@
|
||||
//! stat implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/sysstat.h.html
|
||||
|
||||
#![no_std]
|
||||
|
||||
extern crate platform;
|
||||
|
||||
use platform::types::*;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct stat {
|
||||
pub st_dev: dev_t,
|
||||
pub st_ino: ino_t,
|
||||
pub st_nlink: nlink_t,
|
||||
pub st_mode: mode_t,
|
||||
pub st_uid: uid_t,
|
||||
pub st_gid: gid_t,
|
||||
pub st_rdev: dev_t,
|
||||
pub st_size: off_t,
|
||||
pub st_blksize: blksize_t,
|
||||
pub st_atim: time_t,
|
||||
pub st_mtim: time_t,
|
||||
pub st_ctim: time_t,
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn chmod(path: *const c_char, mode: mode_t) -> c_int {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn fchmod(fildes: c_int, mode: mode_t) -> c_int {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn fstat(fildes: c_int, buf: *mut stat) -> c_int {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn lstat(path: *const c_char, buf: *mut stat) -> c_int {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn mkdir(path: *const c_char, mode: mode_t) -> c_int {
|
||||
platform::mkdir(path, mode)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn mkfifo(path: *const c_char, mode: mode_t) -> c_int {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn mknod(path: *const c_char, mode: mode_t, dev: dev_t) -> c_int {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn stat(file: *const c_char, buf: *mut stat) -> c_int {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn umask(mask: mode_t) -> mode_t {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
/*
|
||||
#[no_mangle]
|
||||
pub extern "C" fn func(args) -> c_int {
|
||||
unimplemented!();
|
||||
}
|
||||
*/
|
||||
+15
-5
@@ -1,13 +1,9 @@
|
||||
use core::fmt;
|
||||
use core::{fmt, mem, slice, str};
|
||||
|
||||
use platform::types::*;
|
||||
use vl::VaList;
|
||||
|
||||
pub unsafe fn printf<W: fmt::Write>(mut w: W, format: *const c_char, mut ap: VaList) -> c_int {
|
||||
use core::fmt::Write;
|
||||
use core::slice;
|
||||
use core::str;
|
||||
|
||||
extern "C" {
|
||||
fn strlen(s: *const c_char) -> size_t;
|
||||
}
|
||||
@@ -39,6 +35,13 @@ pub unsafe fn printf<W: fmt::Write>(mut w: W, format: *const c_char, mut ap: VaL
|
||||
|
||||
found_percent = false;
|
||||
}
|
||||
'f' | 'F' => {
|
||||
let a = ap.get::<f64>();
|
||||
|
||||
w.write_fmt(format_args!("{}", a));
|
||||
|
||||
found_percent = false;
|
||||
}
|
||||
'n' => {
|
||||
let _a = ap.get::<c_int>();
|
||||
|
||||
@@ -82,6 +85,13 @@ pub unsafe fn printf<W: fmt::Write>(mut w: W, format: *const c_char, mut ap: VaL
|
||||
|
||||
found_percent = false;
|
||||
}
|
||||
'o' => {
|
||||
let a = ap.get::<c_uint>();
|
||||
|
||||
w.write_fmt(format_args!("{:o}", a));
|
||||
|
||||
found_percent = false;
|
||||
}
|
||||
'-' => {}
|
||||
'+' => {}
|
||||
' ' => {}
|
||||
|
||||
@@ -11,3 +11,4 @@ cbindgen = { path = "../../cbindgen" }
|
||||
platform = { path = "../platform" }
|
||||
ralloc = { path = "../../ralloc", default-features = false }
|
||||
ctype = { path = "../ctype" }
|
||||
errno = { path = "../errno" }
|
||||
|
||||
+205
-6
@@ -5,9 +5,13 @@
|
||||
#![feature(global_allocator)]
|
||||
|
||||
extern crate ctype;
|
||||
extern crate errno;
|
||||
extern crate platform;
|
||||
extern crate ralloc;
|
||||
|
||||
use core::{ptr, str};
|
||||
|
||||
use errno::*;
|
||||
use platform::types::*;
|
||||
|
||||
#[global_allocator]
|
||||
@@ -52,8 +56,8 @@ pub unsafe extern "C" fn atexit(func: Option<extern "C" fn()>) -> c_int {
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn atof(s: *const c_char) -> c_double {
|
||||
unimplemented!();
|
||||
pub unsafe extern "C" fn atof(s: *const c_char) -> c_double {
|
||||
strtod(s, ptr::null_mut())
|
||||
}
|
||||
|
||||
macro_rules! dec_num_from_ascii {
|
||||
@@ -396,13 +400,208 @@ pub extern "C" fn srandom(seed: c_uint) {
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn strtod(s: *const c_char, endptr: *mut *mut c_char) -> c_double {
|
||||
unimplemented!();
|
||||
pub unsafe extern "C" fn strtod(s: *const c_char, endptr: *mut *mut c_char) -> c_double {
|
||||
//TODO: endptr
|
||||
|
||||
use core::str::FromStr;
|
||||
|
||||
let s_str = str::from_utf8_unchecked(platform::c_str(s));
|
||||
match f64::from_str(s_str) {
|
||||
Ok(ok) => ok as c_double,
|
||||
Err(_err) => {
|
||||
platform::errno = EINVAL;
|
||||
0.0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn strtol(s: *const c_char, endptr: *mut *mut c_char, base: c_int) -> c_long {
|
||||
unimplemented!();
|
||||
pub unsafe extern "C" fn strtol(
|
||||
s: *const c_char,
|
||||
endptr: *mut *const c_char,
|
||||
base: c_int,
|
||||
) -> c_long {
|
||||
let set_endptr = |idx: isize| {
|
||||
if !endptr.is_null() {
|
||||
*endptr = s.offset(idx);
|
||||
}
|
||||
};
|
||||
|
||||
let invalid_input = || {
|
||||
platform::errno = EINVAL;
|
||||
set_endptr(0);
|
||||
};
|
||||
|
||||
// only valid bases are 2 through 36
|
||||
if base != 0 && (base < 2 || base > 36) {
|
||||
invalid_input();
|
||||
return 0;
|
||||
}
|
||||
|
||||
let mut idx = 0;
|
||||
|
||||
// skip any whitespace at the beginning of the string
|
||||
while ctype::isspace(*s.offset(idx) as c_int) != 0 {
|
||||
idx += 1;
|
||||
}
|
||||
|
||||
// check for +/-
|
||||
let positive = match is_positive(*s.offset(idx)) {
|
||||
Some((pos, i)) => {
|
||||
idx += i;
|
||||
pos
|
||||
}
|
||||
None => {
|
||||
invalid_input();
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
// convert the string to a number
|
||||
let num_str = s.offset(idx);
|
||||
let res = match base {
|
||||
0 => detect_base(num_str).and_then(|(base, i)| convert_integer(num_str.offset(i), base)),
|
||||
8 => convert_octal(num_str),
|
||||
16 => convert_hex(num_str),
|
||||
_ => convert_integer(num_str, base),
|
||||
};
|
||||
|
||||
// check for error parsing octal/hex prefix
|
||||
// also check to ensure a number was indeed parsed
|
||||
let (num, i, _) = match res {
|
||||
Some(res) => res,
|
||||
None => {
|
||||
invalid_input();
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
idx += i;
|
||||
|
||||
// account for the sign
|
||||
let mut num = num as c_long;
|
||||
num = if num.is_negative() {
|
||||
platform::errno = ERANGE;
|
||||
if positive {
|
||||
c_long::max_value()
|
||||
} else {
|
||||
c_long::min_value()
|
||||
}
|
||||
} else {
|
||||
if positive {
|
||||
num
|
||||
} else {
|
||||
-num
|
||||
}
|
||||
};
|
||||
|
||||
set_endptr(idx);
|
||||
|
||||
num
|
||||
}
|
||||
|
||||
fn is_positive(ch: c_char) -> Option<(bool, isize)> {
|
||||
match ch {
|
||||
0 => None,
|
||||
ch if ch == b'+' as c_char => Some((true, 1)),
|
||||
ch if ch == b'-' as c_char => Some((false, 1)),
|
||||
_ => Some((true, 0)),
|
||||
}
|
||||
}
|
||||
|
||||
fn detect_base(s: *const c_char) -> Option<(c_int, isize)> {
|
||||
let first = unsafe { *s } as u8;
|
||||
match first {
|
||||
0 => None,
|
||||
b'0' => {
|
||||
let second = unsafe { *s.offset(1) } as u8;
|
||||
if second == b'X' || second == b'x' {
|
||||
Some((16, 2))
|
||||
} else if second >= b'0' && second <= b'7' {
|
||||
Some((8, 1))
|
||||
} else {
|
||||
// in this case, the prefix (0) is going to be the number
|
||||
Some((8, 0))
|
||||
}
|
||||
}
|
||||
_ => Some((10, 0)),
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn convert_octal(s: *const c_char) -> Option<(c_ulong, isize, bool)> {
|
||||
if *s != 0 && *s == b'0' as c_char {
|
||||
if let Some((val, idx, overflow)) = convert_integer(s.offset(1), 8) {
|
||||
Some((val, idx + 1, overflow))
|
||||
} else {
|
||||
// in case the prefix is not actually a prefix
|
||||
Some((0, 1, false))
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn convert_hex(s: *const c_char) -> Option<(c_ulong, isize, bool)> {
|
||||
if (*s != 0 && *s == b'0' as c_char)
|
||||
&& (*s.offset(1) != 0 && (*s.offset(1) == b'x' as c_char || *s.offset(1) == b'X' as c_char))
|
||||
{
|
||||
convert_integer(s.offset(2), 16).map(|(val, idx, overflow)| (val, idx + 2, overflow))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_integer(s: *const c_char, base: c_int) -> Option<(c_ulong, isize, bool)> {
|
||||
// -1 means the character is invalid
|
||||
#[cfg_attr(rustfmt, rustfmt_skip)]
|
||||
const LOOKUP_TABLE: [c_long; 256] = [
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
|
||||
-1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
|
||||
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
|
||||
-1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
|
||||
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
];
|
||||
|
||||
let mut num: c_ulong = 0;
|
||||
let mut idx = 0;
|
||||
let mut overflowed = false;
|
||||
|
||||
loop {
|
||||
let val = unsafe { LOOKUP_TABLE[*s.offset(idx) as usize] };
|
||||
if val == -1 || val as c_int >= base {
|
||||
break;
|
||||
} else {
|
||||
if let Some(res) = num.checked_mul(base as c_ulong)
|
||||
.and_then(|num| num.checked_add(val as c_ulong))
|
||||
{
|
||||
num = res;
|
||||
} else {
|
||||
unsafe {
|
||||
platform::errno = ERANGE;
|
||||
}
|
||||
num = c_ulong::max_value();
|
||||
overflowed = true;
|
||||
}
|
||||
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if idx > 0 {
|
||||
Some((num, idx, overflowed))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
||||
@@ -225,7 +225,7 @@ pub extern "C" fn getpgid(pid: pid_t) -> pid_t {
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn getpgrp() -> pid_t {
|
||||
unimplemented!();
|
||||
platform::getpgid(platform::getpid())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -336,7 +336,7 @@ pub extern "C" fn readlink(path: *const c_char, buf: *mut c_char, bufsize: size_
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn rmdir(path: *const c_char) -> c_int {
|
||||
unimplemented!();
|
||||
platform::rmdir(path)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -351,7 +351,7 @@ pub extern "C" fn setgid(gid: gid_t) -> c_int {
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn setpgid(pid: pid_t, pgid: pid_t) -> c_int {
|
||||
unimplemented!();
|
||||
platform::setpgid(pid, pgid)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -361,12 +361,12 @@ pub extern "C" fn setpgrp() -> pid_t {
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn setregid(rgid: gid_t, egid: gid_t) -> c_int {
|
||||
unimplemented!();
|
||||
platform::setregid(rgid, egid)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn setreuid(ruid: uid_t, euid: uid_t) -> c_int {
|
||||
unimplemented!();
|
||||
platform::setreuid(ruid, euid)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -436,7 +436,7 @@ pub extern "C" fn ualarm(useconds: useconds_t, interval: useconds_t) -> useconds
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn unlink(path: *const c_char) -> c_int {
|
||||
unimplemented!();
|
||||
platform::unlink(path)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
/gen/
|
||||
/alloc
|
||||
/args
|
||||
/atof
|
||||
/atoi
|
||||
/brk
|
||||
/chdir
|
||||
@@ -10,6 +12,7 @@
|
||||
/dup.out
|
||||
/error
|
||||
/fchdir
|
||||
/fcntl
|
||||
/fsync
|
||||
/ftruncate
|
||||
/ftruncate.out
|
||||
@@ -19,4 +22,8 @@
|
||||
/math
|
||||
/pipe
|
||||
/printf
|
||||
/rmdir
|
||||
/setid
|
||||
/unlink
|
||||
/stdlib/strtol
|
||||
/write
|
||||
|
||||
+32
-1
@@ -1,5 +1,6 @@
|
||||
BINS=\
|
||||
alloc \
|
||||
atof \
|
||||
atoi \
|
||||
brk \
|
||||
args \
|
||||
@@ -17,6 +18,10 @@ BINS=\
|
||||
math \
|
||||
pipe \
|
||||
printf \
|
||||
rmdir \
|
||||
setid \
|
||||
unlink \
|
||||
stdlib/strtol \
|
||||
write
|
||||
|
||||
all: $(BINS)
|
||||
@@ -25,7 +30,33 @@ clean:
|
||||
rm -f $(BINS) *.out
|
||||
|
||||
run: $(BINS)
|
||||
for bin in $(BINS); do echo "# $${bin} #"; "./$${bin}" test args; done
|
||||
for bin in $(BINS); \
|
||||
do \
|
||||
echo "# $${bin} #"; \
|
||||
"./$${bin}" test args; \
|
||||
done
|
||||
|
||||
expected: $(BINS)
|
||||
rm -rf expected
|
||||
mkdir -p expected
|
||||
for bin in $(BINS); \
|
||||
do \
|
||||
echo "# $${bin} #"; \
|
||||
mkdir -p expected/`dirname $${bin}`; \
|
||||
"./$${bin}" test args > "expected/$${bin}.stdout" 2> "expected/$${bin}.stderr"; \
|
||||
done
|
||||
|
||||
verify: $(BINS)
|
||||
rm -rf gen
|
||||
mkdir -p gen
|
||||
for bin in $(BINS); \
|
||||
do \
|
||||
echo "# $${bin} #"; \
|
||||
mkdir -p gen/`dirname $${bin}`; \
|
||||
"./$${bin}" test args > "gen/$${bin}.stdout" 2> "gen/$${bin}.stderr"; \
|
||||
diff -u "gen/$${bin}.stdout" "expected/$${bin}.stdout"; \
|
||||
diff -u "gen/$${bin}.stderr" "expected/$${bin}.stderr"; \
|
||||
done
|
||||
|
||||
GCCHEAD=\
|
||||
-nostdinc \
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
double d = atof("-3.14");
|
||||
printf("%f\n", d);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
malloc 0x55ac6c472618
|
||||
calloc 0x55ac6c472618
|
||||
@@ -0,0 +1 @@
|
||||
./args test args
|
||||
@@ -0,0 +1 @@
|
||||
-3.14
|
||||
@@ -0,0 +1,6 @@
|
||||
-42
|
||||
555
|
||||
1234567890
|
||||
-42
|
||||
555
|
||||
1234567890
|
||||
@@ -0,0 +1 @@
|
||||
brk exited with status code 0
|
||||
@@ -0,0 +1,2 @@
|
||||
initial cwd: /home/jeremy/Projects/relibc/tests
|
||||
final cwd: /home/jeremy/Projects/relibc
|
||||
@@ -0,0 +1 @@
|
||||
Success: 0
|
||||
@@ -0,0 +1 @@
|
||||
fd 4 duped into fd 5
|
||||
@@ -0,0 +1 @@
|
||||
perror: No such file or directory
|
||||
@@ -0,0 +1 @@
|
||||
errno: 2 = No such file or directory
|
||||
@@ -0,0 +1 @@
|
||||
fchdir exited with status code 0
|
||||
@@ -0,0 +1 @@
|
||||
fd 4 duped into fd 5
|
||||
@@ -0,0 +1 @@
|
||||
fsync exited with status code 0
|
||||
@@ -0,0 +1 @@
|
||||
ftruncate exited with status code 0
|
||||
@@ -0,0 +1 @@
|
||||
egid: 1000, euid: 1000, gid: 1000, pgid: 23916, pid: 23933, ppid 23918, uid 1000
|
||||
@@ -0,0 +1,8 @@
|
||||
percent: %
|
||||
string: String
|
||||
char: c
|
||||
int: -16
|
||||
uint: 32
|
||||
hex: beef
|
||||
HEX: C0FFEE
|
||||
string: end
|
||||
@@ -0,0 +1 @@
|
||||
rmdir exited with status code 0
|
||||
@@ -0,0 +1 @@
|
||||
Hello World!
|
||||
BIN
Binary file not shown.
+2
-1
@@ -1,5 +1,6 @@
|
||||
#include <unistd.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int status = link("link.c", "link.out");
|
||||
link("./link.c", "./link.out");
|
||||
perror("link");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
mkdir("foo", 0);
|
||||
int status = rmdir("foo");
|
||||
printf("rmdir exited with status code %d\n", status);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* The process joins process group 0.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main( void )
|
||||
{
|
||||
if( setpgid( getpid(), 0 ) == -1 ) {
|
||||
perror( "setpgid" );
|
||||
}
|
||||
printf( "%d belongs to process group %d\n",
|
||||
getpid(), getpgrp() );
|
||||
|
||||
if( setregid(-1, -1) == -1 ) {
|
||||
perror( "setregid" );
|
||||
}
|
||||
printf("%d has egid %d and gid %d\n", getpid(), getegid(), getgid());
|
||||
|
||||
if( setreuid(-1, -1) == -1 ) {
|
||||
perror( "setreuid" );
|
||||
}
|
||||
printf("%d has euid %d and uid %d\n", getpid(), geteuid(), getuid());
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
printf("%ld\n", strtol(" -42", NULL, 0));
|
||||
printf("%ld\n", strtol(" +555", NULL, 0));
|
||||
printf("%ld\n", strtol(" 1234567890 ", NULL, 0));
|
||||
|
||||
printf("%ld\n", strtol(" -42", NULL, 10));
|
||||
printf("%ld\n", strtol(" +555", NULL, 10));
|
||||
printf("%ld\n", strtol(" 1234567890 ", NULL, 10));
|
||||
|
||||
printf("%lx\n", strtol(" 0x38Acfg", NULL, 0));
|
||||
printf("%lx\n", strtol("0Xabcdef12", NULL, 16));
|
||||
|
||||
printf("%lo\n", strtol(" 073189", NULL, 0));
|
||||
printf("%lo\n", strtol(" 073189", NULL, 8));
|
||||
|
||||
printf("%lo\n", strtol(" 0b", NULL, 8));
|
||||
if(errno != 0) {
|
||||
printf("errno is not 0 (%d), something went wrong\n", errno);
|
||||
}
|
||||
printf("%lo\n", strtol(" 0b", NULL, 0));
|
||||
if(errno != 0) {
|
||||
printf("errno is not 0 (%d), something went wrong\n", errno);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
link("./unlink.c", "./unlink.out");
|
||||
perror("unlink");
|
||||
}
|
||||
+1
-1
Submodule va_list updated: 4762a18450...ba5a07a744
Reference in New Issue
Block a user