Skip to content
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 10 additions & 85 deletions src/http/SendFile.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
#[cfg(all(unix, not(any(target_os = "linux", target_os = "android"))))]
use core::ptr;

use bun_core::feature_flags;
use bun_sys::{self, Fd};
use bun_url::URL;
Expand All @@ -25,32 +22,21 @@ impl SendFile {
// Takes the resolved fd directly rather than the socket; callers pass
// `socket.fd()`.
pub(crate) fn write(&mut self, socket_fd: Fd) -> Status {
// Clamp `remain` so the signed sendfile count cannot overflow.
let adjusted_count_temporary: u64 = (self.remain as u64).min(i64::MAX as u64);
let adjusted_count: u64 = adjusted_count_temporary;

// Android: same kernel `sendfile(2)` ABI, dispatched via `bun_sys::linux`'s
// raw-syscall thunk (no libc difference matters here).
#[cfg(any(target_os = "linux", target_os = "android"))]
#[cfg(not(windows))]
{
let _ = adjusted_count; // unused on Linux path
let mut signed_offset: i64 = i64::try_from(self.offset).expect("int cast");
let begin = self.offset;
// this does the syscall directly, without libc
// SAFETY: fds are valid open descriptors owned by `self`/caller; offset ptr is a
// live stack local.
let val = unsafe {
bun_sys::linux::sendfile(
socket_fd.native(),
self.fd.native(),
&raw mut signed_offset,
self.remain,
)
#[cfg(any(target_os = "linux", target_os = "android"))]
let result =
bun_sys::sendfile(self.fd, socket_fd, Some(&mut signed_offset), self.remain);
#[cfg(not(any(target_os = "linux", target_os = "android")))]
let result = bun_sys::sendfile(self.fd, socket_fd, &mut signed_offset, self.remain);
let (val, errcode) = match result {
Ok(sent) => (sent, bun_sys::E::SUCCESS),
Err(err) => (0, err.get_errno()),
};
self.offset = u64::try_from(signed_offset).expect("int cast") as usize;

let errcode = bun_sys::get_errno(val);

self.remain = (self.remain as u64)
.saturating_sub((self.offset as u64).saturating_sub(begin as u64))
as usize;
Expand All @@ -64,70 +50,9 @@ impl SendFile {
}
}

#[cfg(target_os = "freebsd")]
{
let mut sbytes: i64 = 0; // C off_t
// Same-width signedness flip; `as` is a bit-reinterpret here.
let signed_offset: i64 = self.offset as u64 as i64;
// FreeBSD: sendfile(fd, s, offset, nbytes, hdtr, *sbytes, flags)
// SAFETY: fds valid; sbytes is a live stack local; hdtr is null (no headers).
let errcode = bun_sys::get_errno(unsafe {
bun_sys::c::sendfile(
self.fd.native(),
socket_fd.native(),
signed_offset,
adjusted_count as usize,
ptr::null_mut(),
&mut sbytes,
0,
)
});
let wrote: u64 = u64::try_from(sbytes).expect("int cast");
self.offset = (self.offset as u64).saturating_add(wrote) as usize;
self.remain = (self.remain as u64).saturating_sub(wrote) as usize;
if errcode != bun_sys::E::EAGAIN || self.remain == 0 || sbytes == 0 {
if errcode == bun_sys::E::SUCCESS {
return Status::Done;
}
return Status::Err(bun_errno::from_errno(errcode as i32).into());
}
}

#[cfg(all(
unix,
not(any(target_os = "linux", target_os = "android")),
not(target_os = "freebsd")
))]
{
let mut sbytes: i64 = i64::try_from(adjusted_count).expect("int cast"); // C off_t
// Same-width signedness flip; `as` is a bit-reinterpret here.
let signed_offset: i64 = self.offset as u64 as i64;
// SAFETY: fds valid; sbytes is a live stack local; hdtr is null (no headers).
let errcode = bun_sys::get_errno(unsafe {
bun_sys::c::sendfile(
self.fd.native(),
socket_fd.native(),
signed_offset,
&raw mut sbytes,
ptr::null_mut(),
0,
)
});
let wrote: u64 = u64::try_from(sbytes).expect("int cast");
self.offset = (self.offset as u64).saturating_add(wrote) as usize;
self.remain = (self.remain as u64).saturating_sub(wrote) as usize;
if errcode != bun_sys::E::EAGAIN || self.remain == 0 || sbytes == 0 {
if errcode == bun_sys::E::SUCCESS {
return Status::Done;
}

return Status::Err(bun_errno::from_errno(errcode as i32).into());
}
}

#[cfg(windows)]
{
let _ = (socket_fd, adjusted_count);
let _ = socket_fd;
}

Status::Again
Expand Down
11 changes: 9 additions & 2 deletions src/jsc/bindings/c-bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,22 @@ extern "C" bool is_executable_file(const char* path)
{
#if defined(O_EXEC) && !OS(LINUX)
// musl defines O_EXEC as O_PATH, which opens any file.
int fd = open(path, O_EXEC | O_CLOEXEC | O_NONBLOCK | O_NOCTTY, 0);
int fd;
do {
fd = open(path, O_EXEC | O_CLOEXEC | O_NONBLOCK | O_NOCTTY, 0);
} while (fd < 0 && errno == EINTR);
if (fd < 0)
return false;
close(fd);
return true;
#endif // defined(O_EXEC) && !OS(LINUX)

struct stat st;
if (stat(path, &st) != 0)
int rc;
do {
rc = stat(path, &st);
} while (rc != 0 && errno == EINTR);
if (rc != 0)
return false;

// regular file and user can execute
Expand Down
Loading
Loading