diff --git a/Cargo.lock b/Cargo.lock index 7103310a61..d0be2734d2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -463,9 +463,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f3fe0889e69e2ae9e41f4d6c4c0181701d00e4697b356fb1f74173a5e0ee27" +checksum = "6d94dd2f7cd932d4dc02cc8b2b50dfd38bd079a4e5d79198b99743d7fcf9a4b4" dependencies = [ "bitflags", ] diff --git a/Makefile b/Makefile index bdb822d45c..3361676211 100644 --- a/Makefile +++ b/Makefile @@ -137,9 +137,7 @@ $(BUILD)/$(PROFILE)/ld_so: $(BUILD)/$(PROFILE)/ld_so.o $(BUILD)/$(PROFILE)/crti. # TODO: merge ld.so with libc.so: --dynamic-list=dynamic-list-file $(LD) --shared -Bsymbolic --no-relax -T ld_so/ld_script/$(TARGET).ld --allow-multiple-definition --gc-sections $^ -o $@ -# Debug targets - -$(BUILD)/debug/libc.a: $(BUILD)/debug/librelibc.a $(BUILD)/openlibm/libopenlibm.a +$(BUILD)/$(PROFILE)/libc.a: $(BUILD)/$(PROFILE)/librelibc.a $(BUILD)/openlibm/libopenlibm.a echo "create $@" > "$@.mri" for lib in $^; do\ echo "addlib $$lib" >> "$@.mri"; \ @@ -148,6 +146,8 @@ $(BUILD)/debug/libc.a: $(BUILD)/debug/librelibc.a $(BUILD)/openlibm/libopenlibm. echo "end" >> "$@.mri" $(AR) -M < "$@.mri" +# Debug targets + $(BUILD)/debug/librelibc.a: $(SRC) $(CARGO) rustc $(CARGOFLAGS) -- --emit link=$@ -g -C debug-assertions=no $(RUSTCFLAGS) ./renamesyms.sh "$@" "$(BUILD)/debug/deps/" @@ -172,15 +172,6 @@ $(BUILD)/debug/ld_so.o: $(SRC) # Release targets -$(BUILD)/release/libc.a: $(BUILD)/release/librelibc.a $(BUILD)/openlibm/libopenlibm.a - echo "create $@" > "$@.mri" - for lib in $^; do\ - echo "addlib $$lib" >> "$@.mri"; \ - done - echo "save" >> "$@.mri" - echo "end" >> "$@.mri" - $(AR) -M < "$@.mri" - $(BUILD)/release/librelibc.a: $(SRC) $(CARGO) rustc --release $(CARGOFLAGS) -- --emit link=$@ $(RUSTCFLAGS) @# TODO: Better to only allow a certain whitelisted set of symbols? Perhaps diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index 42392bfc48..e0b040d24d 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -4,13 +4,14 @@ use core::{ num::NonZeroU64, ptr, slice, str, }; +use object::bytes_of_slice_mut; use redox_rt::{ RtTcb, protocol::{WaitFlags, wifstopped}, sys::{Resugid, WaitpidTarget}, }; use syscall::{ - self, EILSEQ, Error, MODE_PERM, + self, EILSEQ, ESRCH, Error, MODE_PERM, StdFsCallKind, StdFsCallMeta, data::{Map, TimeSpec as redox_timespec}, dirent::{DirentHeader, DirentKind}, }; @@ -30,7 +31,10 @@ use crate::{ EBADF, EBADFD, EBADR, EEXIST, EFAULT, EFBIG, EINTR, EINVAL, EIO, ENAMETOOLONG, ENOENT, ENOMEM, ENOSYS, EOPNOTSUPP, EPERM, ERANGE, }, - fcntl::{self, AT_EMPTY_PATH, AT_FDCWD, AT_SYMLINK_NOFOLLOW}, + fcntl::{ + self, AT_EMPTY_PATH, AT_FDCWD, AT_SYMLINK_NOFOLLOW, F_GETLK, F_OFD_GETLK, F_OFD_SETLK, + F_RDLCK, F_SETLK, F_SETLKW, F_UNLCK, F_WRLCK, flock, + }, limits, pthread::{pthread_cancel, pthread_create}, signal::{NSIG, SIGEV_NONE, SIGEV_SIGNAL, SIGEV_THREAD, SIGRTMIN, sigevent}, @@ -293,6 +297,116 @@ impl Pal for Sys { } fn fcntl(fd: c_int, cmd: c_int, args: c_ulonglong) -> Result { + match cmd { + F_SETLK | F_OFD_SETLK => { + let is_ofd = cmd == F_OFD_SETLK; + let flock = unsafe { &mut *(args as *mut flock) }; + + let (start, len) = Self::relative_to_absolute_foffset( + fd as usize, + flock.l_whence, + flock.l_start, + flock.l_len, + )?; + + let start = start as u64 | if is_ofd { 1 << 63 } else { 0 }; + let len = len as u64; + + match flock.l_type as i32 { + F_UNLCK => { + let meta = StdFsCallMeta::new(StdFsCallKind::Unlock, start, len); + syscall::std_fs_call(fd as usize, &mut [], &meta)?; + return Ok(0); + } + + F_RDLCK | F_WRLCK => { + let meta = StdFsCallMeta::new( + StdFsCallKind::Lock, + start, + len | if flock.l_type as i32 == F_WRLCK { + 1 << 63 + } else { + 0 + }, + ); + syscall::std_fs_call(fd as usize, &mut [], &meta)?; + return Ok(0); + } + + _ => return Err(Errno(EINVAL)), + }; + } + + F_GETLK | F_OFD_GETLK => { + let is_ofd = cmd == F_OFD_GETLK; + let flock = unsafe { &mut *(args as *mut flock) }; + + if is_ofd && flock.l_pid != 0 { + log::warn!("POSIX requires `l_pid` to be 0 on input for `F_OFD_GETLK`"); + return Err(Errno(EINVAL)); + } + + let (start, len) = Self::relative_to_absolute_foffset( + fd as usize, + flock.l_whence, + flock.l_start, + flock.l_len, + )?; + + let mut start = start as u64; + if is_ofd { + start |= 1 << 63; + } + + let mut len = len as u64; + if flock.l_type as i32 == F_WRLCK { + len |= 1 << 63; + } + + let meta = StdFsCallMeta::new(StdFsCallKind::GetLock, 0, 0); + let payload = &mut [start, len]; + // `pid` if traditional POSIX otherwise 0 + let val = + match syscall::std_fs_call(fd as usize, bytes_of_slice_mut(payload), &meta) { + // According to POSIX Issue 8: + // > If no lock is found that would prevent this lock from being created, then + // > the structure shall be left unchanged except for the lock type in `l_type` + // > which shall be set to F_UNLCK. + Err(err) if err.errno == ESRCH => { + flock.l_type = F_UNLCK as i16; + return Ok(0); + } + + Ok(val) => val, + Err(err) => return Err(Errno(err.errno)), + }; + + debug_assert_ne!(payload[0] & (1 << 63), 1 << 63); + + if is_ofd { + flock.l_pid = -1; + } else { + flock.l_pid = val as i32; + } + + let len = payload[1] & !(1 << 63); + if payload[1] & (1 << 63) == (1 << 63) { + flock.l_type = F_WRLCK as i16; + } else { + flock.l_type = F_RDLCK as i16; + } + + flock.l_whence = SEEK_SET as _; + flock.l_start = start as i64; + flock.l_len = len as i64; + return Ok(0); + } + + F_SETLKW => log::warn!("F_SETLKW: not yet implemented"), + + _ => {} + } + Ok(syscall::fcntl(fd as usize, cmd as usize, args as usize)? as c_int) } @@ -1490,3 +1604,37 @@ impl Pal for Sys { unsafe { redox_rt::thread::exit_this_thread(stack_base, stack_size) } } } + +impl Sys { + fn relative_to_absolute_foffset( + fd: usize, + whence: c_short, + start: off_t, + len: off_t, + ) -> Result<(off_t, off_t)> { + // let file_off = Self::lseek(fd, 0, SEEK_SET)?; + match whence as i32 { + SEEK_SET => { + let (start, len) = if len < 0 { + (start + len, -len) + } else { + (start, len) + }; + + if start < 0 { + return Err(Errno(EINVAL)); + } + + assert!(len >= 0); + Ok((start, len)) + } + // FIXME: andypython: SEEK_CUR, SEEK_END + c => { + log::warn!( + "Sys::relative_to_absolute_foffset: whence={whence} not yet implemented" + ); + Ok((0, 0)) + } + } + } +} diff --git a/tests/Makefile b/tests/Makefile index 40b90dca1f..c7d4d70e1d 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -303,6 +303,7 @@ VARIED_NAMES=\ pthread/rwlock_randtest \ pthread/mutex_recursive \ pthread/timeout \ + pthread/tls \ grp/getgrouplist \ grp/getgrgid_r \ grp/getgrnam_r \