mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-23 13:52:28 +00:00
Perform some code cleanup
This commit is contained in:
parent
174d288e66
commit
fe3216e961
14 changed files with 803 additions and 312 deletions
|
@ -41,7 +41,6 @@
|
||||||
* @param size in range [1..0x7ffff000] is reasonable
|
* @param size in range [1..0x7ffff000] is reasonable
|
||||||
* @return [1..size] bytes on success, 0 on EOF, or -1 w/ errno; with
|
* @return [1..size] bytes on success, 0 on EOF, or -1 w/ errno; with
|
||||||
* exception of size==0, in which case return zero means no error
|
* exception of size==0, in which case return zero means no error
|
||||||
* @see write(), pread(), readv()
|
|
||||||
* @asyncsignalsafe
|
* @asyncsignalsafe
|
||||||
* @restartable
|
* @restartable
|
||||||
* @vforksafe
|
* @vforksafe
|
||||||
|
@ -49,7 +48,7 @@
|
||||||
ssize_t read(int fd, void *buf, size_t size) {
|
ssize_t read(int fd, void *buf, size_t size) {
|
||||||
ssize_t rc;
|
ssize_t rc;
|
||||||
if (fd >= 0) {
|
if (fd >= 0) {
|
||||||
if (IsAsan() && !__asan_is_valid(buf, size)) {
|
if ((!buf && size) || (IsAsan() && !__asan_is_valid(buf, size))) {
|
||||||
rc = efault();
|
rc = efault();
|
||||||
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||||
rc = _weaken(__zipos_read)(
|
rc = _weaken(__zipos_read)(
|
||||||
|
@ -65,7 +64,7 @@ ssize_t read(int fd, void *buf, size_t size) {
|
||||||
rc = sys_readv_nt(g_fds.p + fd, &(struct iovec){buf, size}, 1);
|
rc = sys_readv_nt(g_fds.p + fd, &(struct iovec){buf, size}, 1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rc = einval();
|
rc = ebadf();
|
||||||
}
|
}
|
||||||
DATATRACE("read(%d, [%#.*hhs%s], %'zu) → %'zd% m", fd, MAX(0, MIN(40, rc)),
|
DATATRACE("read(%d, [%#.*hhs%s], %'zu) → %'zd% m", fd, MAX(0, MIN(40, rc)),
|
||||||
buf, rc > 40 ? "..." : "", size, rc);
|
buf, rc > 40 ? "..." : "", size, rc);
|
||||||
|
|
|
@ -46,8 +46,8 @@
|
||||||
* @restartable
|
* @restartable
|
||||||
*/
|
*/
|
||||||
ssize_t readv(int fd, const struct iovec *iov, int iovlen) {
|
ssize_t readv(int fd, const struct iovec *iov, int iovlen) {
|
||||||
int i;
|
|
||||||
ssize_t rc;
|
ssize_t rc;
|
||||||
|
|
||||||
if (fd >= 0 && iovlen >= 0) {
|
if (fd >= 0 && iovlen >= 0) {
|
||||||
if (IsAsan() && !__asan_is_valid_iov(iov, iovlen)) {
|
if (IsAsan() && !__asan_is_valid_iov(iov, iovlen)) {
|
||||||
rc = efault();
|
rc = efault();
|
||||||
|
@ -67,9 +67,12 @@ ssize_t readv(int fd, const struct iovec *iov, int iovlen) {
|
||||||
} else {
|
} else {
|
||||||
rc = sys_readv_nt(g_fds.p + fd, iov, iovlen);
|
rc = sys_readv_nt(g_fds.p + fd, iov, iovlen);
|
||||||
}
|
}
|
||||||
|
} else if (fd < 0) {
|
||||||
|
rc = ebadf();
|
||||||
} else {
|
} else {
|
||||||
rc = einval();
|
rc = einval();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(SYSDEBUG) && _DATATRACE
|
#if defined(SYSDEBUG) && _DATATRACE
|
||||||
if (UNLIKELY(__strace > 0)) {
|
if (UNLIKELY(__strace > 0)) {
|
||||||
if (rc == -1 && errno == EFAULT) {
|
if (rc == -1 && errno == EFAULT) {
|
||||||
|
@ -81,5 +84,6 @@ ssize_t readv(int fd, const struct iovec *iov, int iovlen) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,11 +18,11 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/assert.h"
|
#include "libc/assert.h"
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/intrin/strace.internal.h"
|
|
||||||
#include "libc/calls/struct/rlimit.internal.h"
|
#include "libc/calls/struct/rlimit.internal.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/intrin/asan.internal.h"
|
#include "libc/intrin/asan.internal.h"
|
||||||
#include "libc/intrin/describeflags.internal.h"
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
|
#include "libc/intrin/strace.internal.h"
|
||||||
#include "libc/sysv/consts/rlimit.h"
|
#include "libc/sysv/consts/rlimit.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
|
@ -43,6 +43,8 @@
|
||||||
* - `RLIMIT_FSIZE` causes `SIGXFSZ` to sent to the process when the
|
* - `RLIMIT_FSIZE` causes `SIGXFSZ` to sent to the process when the
|
||||||
* soft limit on file size is exceeded and the process is destroyed
|
* soft limit on file size is exceeded and the process is destroyed
|
||||||
* when the hard limit is exceeded. It works everywhere but Windows
|
* when the hard limit is exceeded. It works everywhere but Windows
|
||||||
|
* and it also causes `EFBIG` to be returned by i/o functions after
|
||||||
|
* the `SIGXFSZ` signal is delivered or ignored
|
||||||
*
|
*
|
||||||
* - `RLIMIT_NPROC` limits the number of simultaneous processes and it
|
* - `RLIMIT_NPROC` limits the number of simultaneous processes and it
|
||||||
* should work on all platforms except Windows. Please be advised it
|
* should work on all platforms except Windows. Please be advised it
|
||||||
|
|
|
@ -17,10 +17,10 @@
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/intrin/strace.internal.h"
|
|
||||||
#include "libc/calls/syscall-sysv.internal.h"
|
#include "libc/calls/syscall-sysv.internal.h"
|
||||||
#include "libc/calls/syscall_support-nt.internal.h"
|
#include "libc/calls/syscall_support-nt.internal.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
|
#include "libc/intrin/strace.internal.h"
|
||||||
#include "libc/nt/enum/threadaccess.h"
|
#include "libc/nt/enum/threadaccess.h"
|
||||||
#include "libc/nt/runtime.h"
|
#include "libc/nt/runtime.h"
|
||||||
#include "libc/nt/thread.h"
|
#include "libc/nt/thread.h"
|
||||||
|
@ -48,6 +48,7 @@ static textwindows int sys_tkill_nt(int tid, int sig) {
|
||||||
* @param tid is thread id
|
* @param tid is thread id
|
||||||
* @param sig does nothing on xnu
|
* @param sig does nothing on xnu
|
||||||
* @return 0 on success, or -1 w/ errno
|
* @return 0 on success, or -1 w/ errno
|
||||||
|
* @asyncsignalsafe
|
||||||
*/
|
*/
|
||||||
int tkill(int tid, int sig) {
|
int tkill(int tid, int sig) {
|
||||||
int rc;
|
int rc;
|
||||||
|
|
|
@ -34,12 +34,27 @@
|
||||||
* This function changes the current file position. For documentation
|
* This function changes the current file position. For documentation
|
||||||
* on file position behaviors and gotchas, see the lseek() function.
|
* on file position behaviors and gotchas, see the lseek() function.
|
||||||
*
|
*
|
||||||
* @param fd is something open()'d earlier
|
* @param fd is open file descriptor
|
||||||
* @param buf is copied from, cf. copy_file_range(), sendfile(), etc.
|
* @param buf is copied from, cf. copy_file_range(), sendfile(), etc.
|
||||||
* @param size in range [1..0x7ffff000] is reasonable
|
|
||||||
* @return [1..size] bytes on success, or -1 w/ errno; noting zero is
|
* @return [1..size] bytes on success, or -1 w/ errno; noting zero is
|
||||||
* impossible unless size was passed as zero to do an error check
|
* impossible unless size was passed as zero to do an error check
|
||||||
* @see read(), pwrite(), writev(), SIGPIPE
|
* @raise EBADF if `fd` is negative or not an open file descriptor
|
||||||
|
* @raise EBADF if `fd` wasn't opened with `O_WRONLY` or `O_RDWR`
|
||||||
|
* @raise EPIPE if `fd` is a pipe whose other reader end was closed,
|
||||||
|
* after the `SIGPIPE` signal was delivered, blocked, or ignored
|
||||||
|
* @raise EFBIG if `RLIMIT_FSIZE` soft limit was exceeded, after the
|
||||||
|
* `SIGXFSZ` signal was either delivered, blocked, or ignored
|
||||||
|
* @raise EFAULT if `size` is nonzero and `buf` points to bad memory
|
||||||
|
* @raise EPERM if pledge() is in play without the stdio promise
|
||||||
|
* @raise ENOSPC if device containing `fd` is full
|
||||||
|
* @raise EIO if low-level i/o error happened
|
||||||
|
* @raise EINTR if signal was delivered instead
|
||||||
|
* @raise EAGAIN if `O_NONBLOCK` is in play and write needs to block
|
||||||
|
* @raise ENOBUFS if kernel lacked internal resources; which FreeBSD
|
||||||
|
* and XNU say could happen with sockets, and OpenBSD documents it
|
||||||
|
* as a general possibility; whereas other system don't specify it
|
||||||
|
* @raise ENXIO is specified only by POSIX and XNU when a request is
|
||||||
|
* made of a nonexistent device or outside device capabilities
|
||||||
* @asyncsignalsafe
|
* @asyncsignalsafe
|
||||||
* @restartable
|
* @restartable
|
||||||
* @vforksafe
|
* @vforksafe
|
||||||
|
@ -47,7 +62,7 @@
|
||||||
ssize_t write(int fd, const void *buf, size_t size) {
|
ssize_t write(int fd, const void *buf, size_t size) {
|
||||||
ssize_t rc;
|
ssize_t rc;
|
||||||
if (fd >= 0) {
|
if (fd >= 0) {
|
||||||
if (IsAsan() && !__asan_is_valid(buf, size)) {
|
if ((!buf && size) || (IsAsan() && !__asan_is_valid(buf, size))) {
|
||||||
rc = efault();
|
rc = efault();
|
||||||
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||||
rc = _weaken(__zipos_write)(
|
rc = _weaken(__zipos_write)(
|
||||||
|
@ -63,7 +78,7 @@ ssize_t write(int fd, const void *buf, size_t size) {
|
||||||
rc = sys_writev_nt(fd, &(struct iovec){buf, size}, 1);
|
rc = sys_writev_nt(fd, &(struct iovec){buf, size}, 1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rc = einval();
|
rc = ebadf();
|
||||||
}
|
}
|
||||||
DATATRACE("write(%d, %#.*hhs%s, %'zu) → %'zd% m", fd, MAX(0, MIN(40, rc)),
|
DATATRACE("write(%d, %#.*hhs%s, %'zu) → %'zd% m", fd, MAX(0, MIN(40, rc)),
|
||||||
buf, rc > 40 ? "..." : "", size, rc);
|
buf, rc > 40 ? "..." : "", size, rc);
|
||||||
|
|
|
@ -50,7 +50,6 @@
|
||||||
* @restartable
|
* @restartable
|
||||||
*/
|
*/
|
||||||
ssize_t writev(int fd, const struct iovec *iov, int iovlen) {
|
ssize_t writev(int fd, const struct iovec *iov, int iovlen) {
|
||||||
int i;
|
|
||||||
ssize_t rc;
|
ssize_t rc;
|
||||||
|
|
||||||
if (fd >= 0 && iovlen >= 0) {
|
if (fd >= 0 && iovlen >= 0) {
|
||||||
|
@ -72,6 +71,8 @@ ssize_t writev(int fd, const struct iovec *iov, int iovlen) {
|
||||||
} else {
|
} else {
|
||||||
rc = sys_writev_nt(fd, iov, iovlen);
|
rc = sys_writev_nt(fd, iov, iovlen);
|
||||||
}
|
}
|
||||||
|
} else if (fd < 0) {
|
||||||
|
rc = ebadf();
|
||||||
} else {
|
} else {
|
||||||
rc = einval();
|
rc = einval();
|
||||||
}
|
}
|
||||||
|
|
|
@ -488,13 +488,11 @@ static int CloneLinux(int (*func)(void *arg, int tid), char *stk, size_t stksz,
|
||||||
// COSMOPOLITAN
|
// COSMOPOLITAN
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates thread without malloc being linked, e.g.
|
* Creates thread without malloc being linked.
|
||||||
*
|
*
|
||||||
* int worker(void *arg) {
|
* If you use clone() you're on you're own, e.g.
|
||||||
* return 0;
|
|
||||||
* }
|
|
||||||
*
|
*
|
||||||
* // NOTE: See _mktls() for _Thread_local support.
|
* int worker(void *arg) { return 0; }
|
||||||
* struct CosmoTib tib = {.tib_self = &tib, .tib_tid = -1};
|
* struct CosmoTib tib = {.tib_self = &tib, .tib_tid = -1};
|
||||||
* char *stk = _mapstack();
|
* char *stk = _mapstack();
|
||||||
* tid = clone(worker, stk, GetStackSize() - 16,
|
* tid = clone(worker, stk, GetStackSize() - 16,
|
||||||
|
|
|
@ -100,4 +100,7 @@ void _wait0(const atomic_int *ctid) {
|
||||||
_wait0_poll(&ts);
|
_wait0_poll(&ts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (IsOpenbsd()) {
|
||||||
|
sched_yield(); // TODO(jart): whhhy?
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@ bool IsMulticastIp(uint32_t);
|
||||||
bool IsAnonymousIp(uint32_t);
|
bool IsAnonymousIp(uint32_t);
|
||||||
int CategorizeIp(uint32_t);
|
int CategorizeIp(uint32_t);
|
||||||
const char *GetIpCategoryName(int);
|
const char *GetIpCategoryName(int);
|
||||||
|
bool IsCloudflareIp(uint32_t);
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
|
42
net/http/iscloudflare.c
Normal file
42
net/http/iscloudflare.c
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "net/http/ip.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if `x` is Cloudflare IPv4 address.
|
||||||
|
*
|
||||||
|
* @see https://www.cloudflare.com/ips/ (April 8, 2021)
|
||||||
|
*/
|
||||||
|
bool IsCloudflareIp(uint32_t x) {
|
||||||
|
return (x & 0xfffffc00) == 0x6715f400 || // 103.21.244.0/22
|
||||||
|
(x & 0xfffffc00) == 0x6716c800 || // 103.22.200.0/22
|
||||||
|
(x & 0xfffffc00) == 0x671f0400 || // 103.31.4.0/22
|
||||||
|
(x & 0xfff80000) == 0x68100000 || // 104.16.0.0/13
|
||||||
|
(x & 0xfffc0000) == 0x68180000 || // 104.24.0.0/14
|
||||||
|
(x & 0xffffc000) == 0x6ca2c000 || // 108.162.192.0/18
|
||||||
|
(x & 0xfffffc00) == 0x83004800 || // 131.0.72.0/22
|
||||||
|
(x & 0xffffc000) == 0x8d654000 || // 141.101.64.0/18
|
||||||
|
(x & 0xfffe0000) == 0xa29e0000 || // 162.158.0.0/15
|
||||||
|
(x & 0xfff80000) == 0xac400000 || // 172.64.0.0/13
|
||||||
|
(x & 0xfffff000) == 0xadf53000 || // 173.245.48.0/20
|
||||||
|
(x & 0xfffff000) == 0xbc726000 || // 188.114.96.0/20
|
||||||
|
(x & 0xfffff000) == 0xbe5df000 || // 190.93.240.0/20
|
||||||
|
(x & 0xfffffc00) == 0xc5eaf000 || // 197.234.240.0/22
|
||||||
|
(x & 0xffff8000) == 0xc6298000; // 198.41.128.0/17
|
||||||
|
}
|
File diff suppressed because it is too large
Load diff
|
@ -20,13 +20,81 @@
|
||||||
#include "libc/calls/internal.h"
|
#include "libc/calls/internal.h"
|
||||||
#include "libc/calls/struct/iovec.h"
|
#include "libc/calls/struct/iovec.h"
|
||||||
#include "libc/calls/struct/iovec.internal.h"
|
#include "libc/calls/struct/iovec.internal.h"
|
||||||
|
#include "libc/calls/struct/rlimit.h"
|
||||||
|
#include "libc/calls/struct/sigaction.h"
|
||||||
|
#include "libc/calls/struct/sigset.h"
|
||||||
#include "libc/calls/syscall-sysv.internal.h"
|
#include "libc/calls/syscall-sysv.internal.h"
|
||||||
|
#include "libc/dce.h"
|
||||||
|
#include "libc/errno.h"
|
||||||
#include "libc/sock/internal.h"
|
#include "libc/sock/internal.h"
|
||||||
#include "libc/sysv/consts/nr.h"
|
#include "libc/sysv/consts/nr.h"
|
||||||
#include "libc/sysv/consts/o.h"
|
#include "libc/sysv/consts/o.h"
|
||||||
|
#include "libc/sysv/consts/rlimit.h"
|
||||||
|
#include "libc/sysv/consts/sig.h"
|
||||||
#include "libc/testlib/ezbench.h"
|
#include "libc/testlib/ezbench.h"
|
||||||
|
#include "libc/testlib/subprocess.h"
|
||||||
#include "libc/testlib/testlib.h"
|
#include "libc/testlib/testlib.h"
|
||||||
|
|
||||||
|
char testlib_enable_tmp_setup_teardown;
|
||||||
|
|
||||||
|
TEST(write, notOpen_ebadf) {
|
||||||
|
ASSERT_SYS(EBADF, -1, write(-1, 0, 0));
|
||||||
|
ASSERT_SYS(EBADF, -1, write(+3, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(write, readOnlyFd_ebadf) {
|
||||||
|
ASSERT_SYS(0, 0, touch("foo", 0644));
|
||||||
|
ASSERT_SYS(0, 3, open("foo", O_RDONLY));
|
||||||
|
ASSERT_SYS(EBADF, -1, write(3, "x", 1));
|
||||||
|
ASSERT_SYS(0, 0, close(3));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(write, badMemory_efault) {
|
||||||
|
ASSERT_SYS(EFAULT, -1, write(1, 0, 1));
|
||||||
|
if (!IsAsan()) return;
|
||||||
|
ASSERT_SYS(EFAULT, -1, write(1, (void *)1, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(write, brokenPipe_sigpipeIgnored_returnsEpipe) {
|
||||||
|
int fds[2];
|
||||||
|
SPAWN(fork);
|
||||||
|
signal(SIGPIPE, SIG_IGN);
|
||||||
|
ASSERT_SYS(0, 0, pipe(fds));
|
||||||
|
ASSERT_SYS(0, 1, write(4, "x", 1));
|
||||||
|
ASSERT_SYS(0, 0, close(3));
|
||||||
|
ASSERT_SYS(EPIPE, -1, write(4, "x", 1));
|
||||||
|
ASSERT_SYS(0, 0, close(4));
|
||||||
|
EXITS(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(write, brokenPipe_sigpipeBlocked_returnsEpipe) {
|
||||||
|
int fds[2];
|
||||||
|
sigset_t mask;
|
||||||
|
SPAWN(fork);
|
||||||
|
signal(SIGPIPE, SIG_DFL);
|
||||||
|
sigemptyset(&mask);
|
||||||
|
sigaddset(&mask, SIGPIPE);
|
||||||
|
sigprocmask(SIG_BLOCK, &mask, 0);
|
||||||
|
ASSERT_SYS(0, 0, pipe(fds));
|
||||||
|
ASSERT_SYS(0, 0, close(3));
|
||||||
|
ASSERT_SYS(EPIPE, -1, write(4, "x", 1));
|
||||||
|
ASSERT_SYS(0, 0, close(4));
|
||||||
|
EXITS(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(write, rlimitFsizeExceeded_raisesEfbig) {
|
||||||
|
if (IsWindows()) return; // not supported
|
||||||
|
struct rlimit rl = {1, 10};
|
||||||
|
SPAWN(fork);
|
||||||
|
signal(SIGXFSZ, SIG_IGN);
|
||||||
|
ASSERT_SYS(0, 0, setrlimit(RLIMIT_FSIZE, &rl));
|
||||||
|
ASSERT_SYS(0, 3, creat("foo", 0644));
|
||||||
|
ASSERT_SYS(0, 1, write(3, "x", 1));
|
||||||
|
ASSERT_SYS(EFBIG, -1, write(3, "x", 1));
|
||||||
|
ASSERT_SYS(0, 0, close(3));
|
||||||
|
EXITS(0);
|
||||||
|
}
|
||||||
|
|
||||||
static long Write(long fd, const void *data, unsigned long size) {
|
static long Write(long fd, const void *data, unsigned long size) {
|
||||||
long ax, di, si, dx;
|
long ax, di, si, dx;
|
||||||
asm volatile("syscall"
|
asm volatile("syscall"
|
||||||
|
|
|
@ -20,12 +20,15 @@
|
||||||
#include "libc/calls/struct/iovec.h"
|
#include "libc/calls/struct/iovec.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
|
#include "libc/limits.h"
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
#include "libc/mem/mem.h"
|
#include "libc/mem/gc.h"
|
||||||
#include "libc/mem/gc.internal.h"
|
#include "libc/mem/gc.internal.h"
|
||||||
|
#include "libc/mem/mem.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
#include "libc/sock/sock.h"
|
#include "libc/sock/sock.h"
|
||||||
#include "libc/sysv/consts/auxv.h"
|
#include "libc/sysv/consts/auxv.h"
|
||||||
|
#include "libc/sysv/consts/iov.h"
|
||||||
#include "libc/sysv/consts/o.h"
|
#include "libc/sysv/consts/o.h"
|
||||||
#include "libc/testlib/testlib.h"
|
#include "libc/testlib/testlib.h"
|
||||||
|
|
||||||
|
@ -35,6 +38,32 @@ void SetUpOnce(void) {
|
||||||
ASSERT_SYS(0, 0, pledge("stdio rpath wpath cpath fattr", 0));
|
ASSERT_SYS(0, 0, pledge("stdio rpath wpath cpath fattr", 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(writev, negativeFd_ebadf) {
|
||||||
|
ASSERT_SYS(EBADF, -1, writev(-1, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(writev, negativeCount_einval) {
|
||||||
|
ASSERT_SYS(EINVAL, -1, writev(1, 0, -1));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(writev, negative_einvalOrEfault) {
|
||||||
|
struct iovec v[] = {{"", -1}};
|
||||||
|
ASSERT_EQ(-1, writev(1, v, 1));
|
||||||
|
ASSERT_TRUE(errno == EINVAL || errno == EFAULT);
|
||||||
|
errno = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(writev, exceedsIovMax_einval) {
|
||||||
|
if (IsWindows()) return; // it's complicated
|
||||||
|
int i, n = IOV_MAX + 1;
|
||||||
|
struct iovec *v = _gc(malloc(sizeof(struct iovec) * n));
|
||||||
|
for (i = 0; i < n; ++i) {
|
||||||
|
v[i].iov_base = "x";
|
||||||
|
v[i].iov_len = 1;
|
||||||
|
}
|
||||||
|
ASSERT_SYS(EINVAL, -1, writev(1, v, n));
|
||||||
|
}
|
||||||
|
|
||||||
TEST(writev, test) {
|
TEST(writev, test) {
|
||||||
int fd;
|
int fd;
|
||||||
char ba[1] = "a";
|
char ba[1] = "a";
|
||||||
|
|
|
@ -20,8 +20,8 @@
|
||||||
#include "libc/atomic.h"
|
#include "libc/atomic.h"
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
#include "libc/intrin/atomic.h"
|
#include "libc/intrin/atomic.h"
|
||||||
#include "libc/mem/mem.h"
|
|
||||||
#include "libc/mem/gc.internal.h"
|
#include "libc/mem/gc.internal.h"
|
||||||
|
#include "libc/mem/mem.h"
|
||||||
#include "libc/testlib/testlib.h"
|
#include "libc/testlib/testlib.h"
|
||||||
#include "libc/thread/spawn.h"
|
#include "libc/thread/spawn.h"
|
||||||
#include "libc/thread/thread.h"
|
#include "libc/thread/thread.h"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue