mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-23 22:02:27 +00:00
Make improvements
- Invent openatemp() API - Invent O_UNLINK open flag - Introduce getenv_secure() API - Remove `git pull` from cosmocc - Fix utimes() when path is NULL - Fix mktemp() to never return NULL - Fix utimensat() UTIME_OMIT on XNU - Improve utimensat() code for RHEL5 - Turn `argv[0]` C:/ to /C/ on Windows - Introduce tmpnam() and tmpnam_r() APIs - Fix more const issues with internal APIs - Permit utimes() on WIN32 in O_RDONLY mode - Fix fdopendir() to check fd is a directory - Fix recent crash regression in landlock make - Fix futimens(AT_FDCWD, NULL) to return EBADF - Use workaround so `make -j` doesn't fork bomb - Rename dontdiscard to __wur (just like glibc) - Fix st_size for WIN32 symlinks containing UTF-8 - Introduce stdio ext APIs needed by GNU coreutils - Fix lstat() on WIN32 for symlinks to directories - Move some constants from normalize.inc to limits.h - Fix segv with memchr() and memcmp() overlapping page - Implement POSIX fflush() behavior for reader streams - Implement AT_SYMLINK_NOFOLLOW for utimensat() on WIN32 - Don't change read-only status of existing files on WIN32 - Correctly handle `0x[^[:xdigit:]]` case in strtol() functions
This commit is contained in:
parent
8596e83cce
commit
f531acc8f9
297 changed files with 1920 additions and 1681 deletions
|
@ -44,7 +44,7 @@ TEST(clock_gettime, test) {
|
|||
#ifndef __aarch64__
|
||||
bool isfast;
|
||||
// we support vdso on aarch64 but qemu-aarch64 won't let us test it
|
||||
if (__is_linux_2_6_23()) {
|
||||
if (IsLinux() && __is_linux_2_6_23()) {
|
||||
ASSERT_GT((intptr_t)__clock_gettime_get(&isfast),
|
||||
getauxval(AT_SYSINFO_EHDR));
|
||||
ASSERT_TRUE(isfast);
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "libc/errno.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/intrin/safemacros.internal.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/mem/gc.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
|
|
|
@ -25,8 +25,8 @@
|
|||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/temp.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/temp.h"
|
||||
#include "libc/testlib/ezbench.h"
|
||||
#include "libc/testlib/subprocess.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
@ -69,8 +69,8 @@ TEST(execve, testArgPassing) {
|
|||
}
|
||||
|
||||
TEST(execve, ziposELF) {
|
||||
if (IsFreebsd()) return; // TODO: fixme on freebsd
|
||||
if (!__is_linux_2_6_23()) return; // TODO: fixme on old linux
|
||||
if (IsFreebsd()) return; // TODO: fixme on freebsd
|
||||
if (IsLinux() && !__is_linux_2_6_23()) return; // TODO: fixme on old linux
|
||||
if (!IsLinux() && !IsFreebsd()) {
|
||||
EXPECT_SYS(ENOSYS, -1,
|
||||
execve("/zip/life.elf", (char *const[]){0}, (char *const[]){0}));
|
||||
|
@ -83,8 +83,8 @@ TEST(execve, ziposELF) {
|
|||
}
|
||||
|
||||
TEST(execve, ziposAPE) {
|
||||
if (IsFreebsd()) return; // TODO: fixme on freebsd
|
||||
if (!__is_linux_2_6_23()) return; // TODO: fixme on old linux
|
||||
if (IsFreebsd()) return; // TODO: fixme on freebsd
|
||||
if (IsLinux() && !__is_linux_2_6_23()) return; // TODO: fixme on old linux
|
||||
if (!IsLinux() && !IsFreebsd()) {
|
||||
EXPECT_EQ(-1, execve("/zip/life-nomod.com", (char *const[]){0},
|
||||
(char *const[]){0}));
|
||||
|
|
|
@ -37,7 +37,7 @@ char testlib_enable_tmp_setup_teardown;
|
|||
|
||||
void SetUp(void) {
|
||||
if (IsFreebsd()) exit(0); // TODO: fixme on freebsd
|
||||
if (!__is_linux_2_6_23()) exit(0); // TODO: fixme on old linux
|
||||
if (IsLinux() && !__is_linux_2_6_23()) exit(0); // TODO: fixme on old linux
|
||||
}
|
||||
|
||||
TEST(execve, elfIsUnreadable_mayBeExecuted) {
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/calls/calls.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/fmt/libgen.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/mem/gc.internal.h"
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/macros.internal.h"
|
||||
|
@ -26,7 +28,12 @@
|
|||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
#include "libc/sysv/consts/fd.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/s.h"
|
||||
#include "libc/testlib/subprocess.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "libc/x/xasprintf.h"
|
||||
|
@ -36,7 +43,7 @@
|
|||
char testlib_enable_tmp_setup_teardown;
|
||||
|
||||
void SetUpOnce(void) {
|
||||
ASSERT_SYS(0, 0, pledge("stdio rpath wpath cpath fattr", 0));
|
||||
ASSERT_SYS(0, 0, pledge("stdio rpath wpath cpath fattr proc id", 0));
|
||||
}
|
||||
|
||||
TEST(open, efault) {
|
||||
|
@ -72,6 +79,18 @@ TEST(open, doubleSlash_worksAndGetsNormalizedOnWindows) {
|
|||
ASSERT_SYS(0, 0, close(3));
|
||||
}
|
||||
|
||||
TEST(open, fdWillBeInheritedByExecutedPrograms) {
|
||||
ASSERT_SYS(0, 3, open("x", O_RDWR | O_CREAT | O_TRUNC, 0666));
|
||||
ASSERT_SYS(0, 0, fcntl(3, F_GETFD));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
}
|
||||
|
||||
TEST(open, fdWillBeClosedByExecveAutomatically) {
|
||||
ASSERT_SYS(0, 3, open("x", O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, 0666));
|
||||
ASSERT_SYS(0, FD_CLOEXEC, fcntl(3, F_GETFD));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
}
|
||||
|
||||
TEST(open, enametoolong) {
|
||||
size_t n = 260;
|
||||
char *s = gc(xcalloc(1, n + 1));
|
||||
|
@ -320,3 +339,159 @@ TEST(open, drive) {
|
|||
ASSERT_SYS(0, 3, open("/", O_RDONLY));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
}
|
||||
|
||||
TEST(open, readOnlyCreatMode) {
|
||||
char buf[8];
|
||||
struct stat st;
|
||||
ASSERT_SYS(0, 3, open("x", O_RDWR | O_CREAT | O_TRUNC, 0500));
|
||||
ASSERT_SYS(0, 2, pwrite(3, "hi", 2, 0));
|
||||
ASSERT_SYS(0, 2, pread(3, buf, 8, 0));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
ASSERT_SYS(0, 0, stat("x", &st));
|
||||
ASSERT_EQ(0100500, st.st_mode);
|
||||
if (getuid()) {
|
||||
ASSERT_SYS(EACCES, -1, open("x", O_RDWR));
|
||||
ASSERT_SYS(EACCES, -1, open("x", O_RDWR | O_CREAT));
|
||||
} else {
|
||||
// root is invulnerable to eacces
|
||||
ASSERT_SYS(0, 3, open("x", O_RDWR));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
ASSERT_SYS(0, 3, open("x", O_RDWR | O_CREAT));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
SPAWN(fork);
|
||||
setuid(1000);
|
||||
setgid(1000);
|
||||
ASSERT_SYS(EACCES, -1, open("x", O_RDWR));
|
||||
ASSERT_SYS(EACCES, -1, open("x", O_RDWR | O_CREAT));
|
||||
EXITS(0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(open, parentSymlink) {
|
||||
struct stat st;
|
||||
ASSERT_SYS(0, 0, mkdir("parent", 0755));
|
||||
// create directory symlink
|
||||
ASSERT_SYS(0, 0, symlink("parent", "parent-link"));
|
||||
// test the symlink we just made is a symlink
|
||||
ASSERT_SYS(0, 0, lstat("parent-link", &st));
|
||||
ASSERT_TRUE(S_ISLNK(st.st_mode));
|
||||
// create regular file when parent component is symlink dir
|
||||
ASSERT_SYS(0, 0, touch("parent-link/regular", 0644));
|
||||
// test stat works
|
||||
ASSERT_SYS(0, 0, stat("parent-link/regular", &st));
|
||||
ASSERT_TRUE(S_ISREG(st.st_mode));
|
||||
// test open works
|
||||
ASSERT_SYS(0, 3, open("parent-link/regular", O_RDONLY));
|
||||
ASSERT_SYS(0, 0, fstat(3, &st));
|
||||
ASSERT_TRUE(S_ISREG(st.st_mode));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
// test O_NOFOLLOW doesn't apply to parent components
|
||||
ASSERT_SYS(0, 3, open("parent-link/regular", O_RDONLY | O_NOFOLLOW));
|
||||
ASSERT_SYS(0, 0, fstat(3, &st));
|
||||
ASSERT_TRUE(S_ISREG(st.st_mode));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
// create regular symlink
|
||||
ASSERT_SYS(0, 0, symlink("regular", "parent-link/regular-link"));
|
||||
// test stat works
|
||||
ASSERT_SYS(0, 0, stat("parent-link/regular-link", &st));
|
||||
ASSERT_TRUE(S_ISREG(st.st_mode));
|
||||
ASSERT_SYS(0, 0, lstat("parent-link/regular-link", &st));
|
||||
ASSERT_TRUE(S_ISLNK(st.st_mode));
|
||||
// test open works
|
||||
ASSERT_SYS(0, 3, open("parent-link/regular-link", O_RDONLY));
|
||||
ASSERT_SYS(0, 0, fstat(3, &st));
|
||||
ASSERT_TRUE(S_ISREG(st.st_mode));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
// test O_NOFOLLOW applies to last component
|
||||
ASSERT_SYS(ELOOP, -1,
|
||||
open("parent-link/regular-link", O_RDONLY | O_NOFOLLOW));
|
||||
}
|
||||
|
||||
TEST(open, readonlyCreateMode_dontChangeStatusIfExists) {
|
||||
char buf[8];
|
||||
struct stat st;
|
||||
ASSERT_SYS(0, 3, creat("wut", 0700));
|
||||
ASSERT_SYS(0, 2, pwrite(3, "hi", 2, 0));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
// since the file already exists, unix doesn't change read-only
|
||||
ASSERT_SYS(0, 3, open("wut", O_CREAT | O_TRUNC | O_RDWR, 0500));
|
||||
ASSERT_SYS(0, 0, pread(3, buf, 8, 0));
|
||||
ASSERT_SYS(0, 0, fstat(3, &st));
|
||||
ASSERT_EQ(0100700, st.st_mode);
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
}
|
||||
|
||||
TEST(open, creatRdonly) {
|
||||
char buf[8];
|
||||
ASSERT_SYS(EINVAL, -1, open("foo", O_CREAT | O_TRUNC | O_RDONLY, 0700));
|
||||
ASSERT_SYS(0, 3, open("foo", O_CREAT | O_RDONLY, 0700));
|
||||
ASSERT_SYS(EBADF, -1, pwrite(3, "hi", 2, 0));
|
||||
ASSERT_SYS(0, 0, pread(3, buf, 8, 0));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
}
|
||||
|
||||
TEST(open, sequentialRandom_EINVAL) {
|
||||
if (!IsWindows()) return;
|
||||
ASSERT_SYS(
|
||||
EINVAL, -1,
|
||||
open("foo", O_CREAT | O_TRUNC | O_RDWR | O_SEQUENTIAL | O_RANDOM, 0700));
|
||||
}
|
||||
|
||||
// "If O_CREAT is set and the file did not previously exist, upon
|
||||
// successful completion, open() shall mark for update the last data
|
||||
// access, last data modification, and last file status change
|
||||
// timestamps of the file and the last data modification and last
|
||||
// file status change timestamps of the parent directory." -POSIX
|
||||
TEST(open, creatFile_touchesDirectory) {
|
||||
struct stat st;
|
||||
struct timespec birth;
|
||||
ASSERT_SYS(0, 0, mkdir("dir", 0755));
|
||||
ASSERT_SYS(0, 0, stat("dir", &st));
|
||||
birth = st.st_ctim;
|
||||
// check we can read time without changing it
|
||||
sleep(1);
|
||||
ASSERT_SYS(0, 0, stat("dir", &st));
|
||||
EXPECT_EQ(0, timespec_cmp(st.st_ctim, birth));
|
||||
EXPECT_EQ(0, timespec_cmp(st.st_mtim, birth));
|
||||
EXPECT_EQ(0, timespec_cmp(st.st_atim, birth));
|
||||
// check that the directory time changes when file is made
|
||||
sleep(1);
|
||||
ASSERT_SYS(0, 0, touch("dir/file", 0644));
|
||||
ASSERT_SYS(0, 0, stat("dir", &st));
|
||||
EXPECT_EQ(1, timespec_cmp(st.st_ctim, birth));
|
||||
EXPECT_EQ(1, timespec_cmp(st.st_mtim, birth));
|
||||
// TODO: Maybe statfs() for noatime / relative?
|
||||
// EXPECT_EQ(1, timespec_cmp(st.st_atim, birth));
|
||||
}
|
||||
|
||||
// "If O_TRUNC is set and the file did previously exist, upon successful
|
||||
// completion, open() shall mark for update the last data modification
|
||||
// and last file status change timestamps of the file." -POSIX
|
||||
TEST(open, trunc_touchesMtimCtim) {
|
||||
struct stat st;
|
||||
struct timespec birth;
|
||||
ASSERT_SYS(0, 0, touch("regular", 0755));
|
||||
ASSERT_SYS(0, 0, stat("regular", &st));
|
||||
birth = st.st_ctim;
|
||||
sleep(1);
|
||||
ASSERT_SYS(0, 3, open("regular", O_RDWR | O_TRUNC));
|
||||
ASSERT_SYS(0, 0, fstat(3, &st));
|
||||
EXPECT_EQ(1, timespec_cmp(st.st_ctim, birth));
|
||||
EXPECT_EQ(1, timespec_cmp(st.st_mtim, birth));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
}
|
||||
|
||||
TEST(open, mereOpen_doesntTouch) {
|
||||
struct stat st;
|
||||
struct timespec birth;
|
||||
ASSERT_SYS(0, 0, touch("regular", 0755));
|
||||
ASSERT_SYS(0, 0, stat("regular", &st));
|
||||
birth = st.st_ctim;
|
||||
sleep(1);
|
||||
ASSERT_SYS(0, 3, open("regular", O_RDWR));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
ASSERT_SYS(0, 0, stat("regular", &st));
|
||||
EXPECT_EQ(0, timespec_cmp(st.st_ctim, birth));
|
||||
EXPECT_EQ(0, timespec_cmp(st.st_mtim, birth));
|
||||
EXPECT_EQ(0, timespec_cmp(st.st_atim, birth));
|
||||
}
|
||||
|
|
115
test/libc/calls/openatemp_test.c
Normal file
115
test/libc/calls/openatemp_test.c
Normal file
|
@ -0,0 +1,115 @@
|
|||
/*-*- 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 2023 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 "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/mem/gc.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/temp.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
char testlib_enable_tmp_setup_teardown;
|
||||
|
||||
TEST(openatemp, test) {
|
||||
char path[] = "foo.XXXXXX";
|
||||
ASSERT_SYS(0, 3, openatemp(AT_FDCWD, path, 0, O_CLOEXEC, 0));
|
||||
ASSERT_NE(0, strcmp(path, "foo.XXXXXX"));
|
||||
EXPECT_TRUE(fileexists(path));
|
||||
EXPECT_SYS(0, 0, close(3));
|
||||
}
|
||||
|
||||
TEST(openatemp, dirfd) {
|
||||
ASSERT_SYS(0, 3, open(kTmpPath, O_RDONLY | O_DIRECTORY));
|
||||
char path[] = "foo.XXXXXX.txt";
|
||||
ASSERT_SYS(0, 4, openatemp(3, path, 4, 0, 0));
|
||||
EXPECT_TRUE(fileexists(gc(xjoinpaths(kTmpPath, path))));
|
||||
EXPECT_SYS(0, 0, close(4));
|
||||
EXPECT_SYS(0, 0, close(3));
|
||||
}
|
||||
|
||||
TEST(openatemp, unlink) {
|
||||
char path[] = "foo.XXXXXX";
|
||||
ASSERT_SYS(0, 3, openatemp(AT_FDCWD, path, 0, O_UNLINK, 0));
|
||||
EXPECT_SYS(0, 0, close(3));
|
||||
EXPECT_FALSE(fileexists(path));
|
||||
}
|
||||
|
||||
TEST(openatemp, mode) {
|
||||
if (IsWindows()) return;
|
||||
unsigned omask = umask(0);
|
||||
char path[] = "foo.XXXXXX";
|
||||
ASSERT_SYS(0, 3, openatemp(AT_FDCWD, path, 0, 0, 0764));
|
||||
struct stat st;
|
||||
ASSERT_SYS(0, 0, stat(path, &st));
|
||||
ASSERT_SYS(0, 0, fstat(3, &st));
|
||||
EXPECT_EQ(0100764, st.st_mode);
|
||||
EXPECT_SYS(0, 0, close(3));
|
||||
umask(omask);
|
||||
}
|
||||
|
||||
TEST(openatemp, tooFewX_EINVAL) {
|
||||
char path[] = "foo.XXXXX";
|
||||
ASSERT_SYS(EINVAL, -1, openatemp(AT_FDCWD, path, 0, O_CLOEXEC, 0));
|
||||
}
|
||||
|
||||
TEST(openatemp, suffixTooFewX_EINVAL) {
|
||||
char path[] = "foo.XXXXX.txt";
|
||||
ASSERT_SYS(EINVAL, -1, openatemp(AT_FDCWD, path, 4, O_CLOEXEC, 0));
|
||||
}
|
||||
|
||||
TEST(openatemp, badSuffixLen_EINVAL) {
|
||||
char path[] = "foo.XXXXXX";
|
||||
ASSERT_SYS(EINVAL, -1, openatemp(AT_FDCWD, path, -1, O_CLOEXEC, 0));
|
||||
ASSERT_SYS(EINVAL, -1, openatemp(AT_FDCWD, path, -6, O_CLOEXEC, 0));
|
||||
ASSERT_SYS(EINVAL, -1, openatemp(AT_FDCWD, path, 11, O_CLOEXEC, 0));
|
||||
ASSERT_SYS(EINVAL, -1, openatemp(AT_FDCWD, path, 99, O_CLOEXEC, 0));
|
||||
}
|
||||
|
||||
TEST(openatemp, missingDir_ENOENT) {
|
||||
char path[] = "missing/foo.XXXXXX";
|
||||
ASSERT_SYS(ENOENT, -1, openatemp(AT_FDCWD, path, 0, O_CLOEXEC, 0));
|
||||
}
|
||||
|
||||
TEST(openatemp, notDir_ENOTDIR) {
|
||||
char path[] = "regular/foo.XXXXXX";
|
||||
ASSERT_SYS(0, 0, touch("regular", 0644));
|
||||
ASSERT_SYS(ENOTDIR, -1, openatemp(AT_FDCWD, path, 0, O_CLOEXEC, 0));
|
||||
}
|
||||
|
||||
TEST(mktemp, fails_returnsEmptyString) {
|
||||
char path[] = "regular/foo.XXXXXX";
|
||||
ASSERT_SYS(0, 0, touch("regular", 0644));
|
||||
ASSERT_STREQ("", mktemp(path));
|
||||
ASSERT_STREQ("", path);
|
||||
ASSERT_EQ(ENOTDIR, errno);
|
||||
errno = 0;
|
||||
}
|
||||
|
||||
TEST(mkstemp, fails_returnsNull) {
|
||||
char path[] = "regular/foo.XXXXXX";
|
||||
ASSERT_SYS(0, 0, touch("regular", 0644));
|
||||
ASSERT_SYS(ENOTDIR, -1, mkstemp(path));
|
||||
ASSERT_STREQ("regular/foo.XXXXXX", path);
|
||||
}
|
|
@ -28,8 +28,8 @@
|
|||
char testlib_enable_tmp_setup_teardown;
|
||||
|
||||
void CheckPlatform(void) {
|
||||
if (IsOpenbsd()) return;
|
||||
if (__is_linux_2_6_23()) return;
|
||||
if (IsOpenbsd()) return; // openbsd is ok
|
||||
if (IsLinux() && __is_linux_2_6_23()) return; // non-ancient linux is ok
|
||||
kprintf("skipping openbsd_test\n");
|
||||
exit(0);
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ void OnSig(int sig) {
|
|||
gotsig = true;
|
||||
}
|
||||
|
||||
dontdiscard char *FormatPollFd(struct pollfd p[2]) {
|
||||
__wur char *FormatPollFd(struct pollfd p[2]) {
|
||||
return xasprintf("fd:%d revents:%s\n"
|
||||
"fd:%d revents:%s\n",
|
||||
p[0].fd, "<TODO:kPollNames>", p[1].fd, "<TODO:kPollNames>");
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/mem/gc.h"
|
||||
#include "libc/mem/gc.internal.h"
|
||||
|
@ -96,10 +97,10 @@ TEST(readlinkat, frootloop) {
|
|||
|
||||
TEST(readlinkat, statReadsNameLength) {
|
||||
struct stat st;
|
||||
ASSERT_SYS(0, 0, symlink("froot", "froot"));
|
||||
ASSERT_SYS(0, 0, fstatat(AT_FDCWD, "froot", &st, AT_SYMLINK_NOFOLLOW));
|
||||
ASSERT_SYS(0, 0, symlink("froÒt", "froÒt"));
|
||||
ASSERT_SYS(0, 0, fstatat(AT_FDCWD, "froÒt", &st, AT_SYMLINK_NOFOLLOW));
|
||||
EXPECT_TRUE(S_ISLNK(st.st_mode));
|
||||
EXPECT_EQ(5, st.st_size);
|
||||
EXPECT_EQ(6, st.st_size);
|
||||
}
|
||||
|
||||
TEST(readlinkat, realpathReturnsLongPath) {
|
||||
|
|
|
@ -75,7 +75,7 @@ TEST(reservefd, testGrowthOfFdsDataStructure) {
|
|||
for (i = 0; i < n; ++i) {
|
||||
ASSERT_SYS(0, i + 3, open("/zip/usr/share/zoneinfo/UTC", O_RDONLY));
|
||||
}
|
||||
ASSERT_GT(g_fds.n, OPEN_MAX);
|
||||
ASSERT_GT(g_fds.n, 16);
|
||||
for (i = 0; i < n; ++i) {
|
||||
ASSERT_SYS(0, 0, close(i + 3));
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ bool CanUseSeccomp(void) {
|
|||
}
|
||||
|
||||
void SetUp(void) {
|
||||
if (!__is_linux_2_6_23() || !CanUseSeccomp()) {
|
||||
if (!IsLinux() || !__is_linux_2_6_23() || !CanUseSeccomp()) {
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/intrin/directmap.internal.h"
|
||||
#include "libc/intrin/safemacros.internal.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/rand.h"
|
||||
#include "libc/sysv/consts/auxv.h"
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "libc/errno.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/rand.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
|
|
|
@ -18,11 +18,13 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/calls/struct/stat.macros.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/calls/syscall_support-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/utime.h"
|
||||
|
@ -70,15 +72,6 @@ TEST(futimes, test) {
|
|||
EXPECT_SYS(0, 0, close(3));
|
||||
}
|
||||
|
||||
TEST(futimes, rhel5_enosys) {
|
||||
if (IsLinux() && !__is_linux_2_6_23()) {
|
||||
struct timeval tv[2] = {{1655455857}, {827727928}};
|
||||
EXPECT_SYS(0, 3, creat("boop", 0644));
|
||||
EXPECT_SYS(ENOSYS, -1, futimes(3, tv));
|
||||
EXPECT_SYS(0, 0, close(3));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(utimensat, test) {
|
||||
struct stat st;
|
||||
struct timespec ts[2] = {
|
||||
|
@ -127,3 +120,39 @@ TEST(utimensat, testOmit) {
|
|||
EXPECT_NE(123, st.st_atim.tv_sec);
|
||||
EXPECT_NE(123, st.st_mtim.tv_sec);
|
||||
}
|
||||
|
||||
TEST(futimens, test2) {
|
||||
struct timespec ts[2];
|
||||
int fd = creat("foo", 0600);
|
||||
if (fd < 0) exit(1);
|
||||
struct stat st;
|
||||
int64_t birth;
|
||||
ASSERT_SYS(0, 0, fstat(fd, &st));
|
||||
ASSERT_EQ(st.st_ctime, st.st_atime);
|
||||
ASSERT_EQ(st.st_ctime, st.st_mtime);
|
||||
birth = st.st_ctime;
|
||||
ts[0].tv_sec = 1;
|
||||
ts[0].tv_nsec = UTIME_OMIT;
|
||||
ts[1].tv_sec = 1;
|
||||
ts[1].tv_nsec = UTIME_NOW;
|
||||
errno = 0;
|
||||
ASSERT_SYS(EBADF, -1, futimens(AT_FDCWD, NULL));
|
||||
ASSERT_SYS(0, 0, futimens(fd, ts));
|
||||
sleep(1);
|
||||
ts[0].tv_nsec = UTIME_NOW; // change access time
|
||||
ts[1].tv_nsec = UTIME_OMIT; // don't change modified time
|
||||
close(fd);
|
||||
fd = open("foo", O_RDONLY);
|
||||
ASSERT_SYS(0, 0, futimens(fd, ts));
|
||||
ASSERT_SYS(0, 0, fstat(fd, &st));
|
||||
// check time of last status change equals access time
|
||||
ASSERT_GT(st.st_atime, birth);
|
||||
ASSERT_EQ(st.st_mtime, birth);
|
||||
// NetBSD doesn't appear to change ctime even though it says it does
|
||||
if (!IsNetbsd()) {
|
||||
ASSERT_GT(st.st_ctime, birth);
|
||||
ASSERT_EQ(st.st_ctime, st.st_atime);
|
||||
ASSERT_GT(st.st_ctime, st.st_mtime);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
|
|
@ -512,6 +512,18 @@ TEST(wcstoumax, testIBM) {
|
|||
ASSERT_STREQ(L"f", e);
|
||||
}
|
||||
|
||||
TEST(strtol, term) {
|
||||
static char const input[2][3] = {"0x", "0b"};
|
||||
static int const base[] = {0, 2, 10};
|
||||
for (int i = 0; i < 2; i++) {
|
||||
for (int j = 0; j < 3; j++) {
|
||||
char *term;
|
||||
strtoll(input[i], &term, base[j]);
|
||||
ASSERT_EQ(input[i] + 1, term);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(strtoul, testoverflow) {
|
||||
errno = 0;
|
||||
char *e = 0;
|
||||
|
@ -521,20 +533,41 @@ TEST(strtoul, testoverflow) {
|
|||
ASSERT_STREQ("", e);
|
||||
}
|
||||
|
||||
TEST(strtol, invalidHex_consistentWithBsd) {
|
||||
TEST(strtol, invalidHex1) {
|
||||
char *c = 0;
|
||||
long x = strtol("0xz", &c, 16);
|
||||
ASSERT_EQ(0, x);
|
||||
ASSERT_STREQ("z", c);
|
||||
ASSERT_STREQ("xz", c);
|
||||
}
|
||||
|
||||
TEST(strtol, invalidHex_consistentWithBsd2) {
|
||||
TEST(strtol, invalidHex2) {
|
||||
char *c = 0;
|
||||
long x = strtol("0xez", &c, 16);
|
||||
ASSERT_EQ(0xe, x);
|
||||
ASSERT_STREQ("z", c);
|
||||
}
|
||||
|
||||
TEST(strtol, invalidHex3) {
|
||||
char *c = 0;
|
||||
long x = strtol("0xez", &c, 0);
|
||||
ASSERT_EQ(0xe, x);
|
||||
ASSERT_STREQ("z", c);
|
||||
}
|
||||
|
||||
TEST(strtol, invalidBin1) {
|
||||
char *c = 0;
|
||||
long x = strtol("0b2", &c, 2);
|
||||
ASSERT_EQ(0, x);
|
||||
ASSERT_STREQ("b2", c);
|
||||
}
|
||||
|
||||
TEST(strtol, invalidBin2) {
|
||||
char *c = 0;
|
||||
long x = strtol("0b2", &c, 0);
|
||||
ASSERT_EQ(0, x);
|
||||
ASSERT_STREQ("b2", c);
|
||||
}
|
||||
|
||||
BENCH(atoi, bench) {
|
||||
EZBENCH2("atoi 10⁸", donothing,
|
||||
__expropriate(atoi(__veil("r", "100000000"))));
|
||||
|
|
|
@ -16,11 +16,12 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/intrin/popcnt.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/mem/gc.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/testlib/ezbench.h"
|
||||
#include "libc/testlib/hyperion.h"
|
||||
|
|
39
test/libc/intrin/memchr_test.c
Normal file
39
test/libc/intrin/memchr_test.c
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*-*- 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 2023 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 "libc/runtime/runtime.h"
|
||||
#include "libc/runtime/sysconf.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
TEST(memchr, test) {
|
||||
const char *s = "hello";
|
||||
ASSERT_EQ(s + 1, memchr(s, 'e', 5));
|
||||
}
|
||||
|
||||
TEST(memchr, pageOverlapTorture) {
|
||||
long pagesz = sysconf(_SC_PAGESIZE);
|
||||
char *map = mmap(0, pagesz * 2, PROT_READ | PROT_WRITE,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
||||
ASSERT_SYS(0, 0, mprotect(map + pagesz, pagesz, PROT_NONE));
|
||||
strcpy(map + pagesz - 9, "12345678");
|
||||
EXPECT_EQ(map + pagesz - 1, memchr(map + pagesz - 9, 0, 79));
|
||||
EXPECT_SYS(0, 0, munmap(map, pagesz * 2));
|
||||
}
|
|
@ -18,9 +18,13 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/mem/gc.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/runtime/sysconf.h"
|
||||
#include "libc/stdio/rand.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/testlib/ezbench.h"
|
||||
#include "libc/testlib/fastrandomstring.h"
|
||||
#include "libc/testlib/hyperion.h"
|
||||
|
@ -109,100 +113,67 @@ TEST(memcmp, fuzz) {
|
|||
}
|
||||
}
|
||||
|
||||
TEST(memcmp, pageOverlapTorture) {
|
||||
long pagesz = sysconf(_SC_PAGESIZE);
|
||||
char *map = mmap(0, pagesz * 2, PROT_READ | PROT_WRITE,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
||||
char *map2 = mmap(0, pagesz * 2, PROT_READ | PROT_WRITE,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
||||
ASSERT_SYS(0, 0, mprotect(map + pagesz, pagesz, PROT_NONE));
|
||||
ASSERT_SYS(0, 0, mprotect(map2 + pagesz, pagesz, PROT_NONE));
|
||||
strcpy(map + pagesz - 9, "12345678");
|
||||
strcpy(map2 + pagesz - 9, "12345679");
|
||||
EXPECT_LT(memcmp(map + pagesz - 9, map2 + pagesz - 9, 79), 0);
|
||||
EXPECT_SYS(0, 0, munmap(map2, pagesz * 2));
|
||||
EXPECT_SYS(0, 0, munmap(map, pagesz * 2));
|
||||
}
|
||||
|
||||
int buncmp(const void *, const void *, size_t) asm("bcmp");
|
||||
int funcmp(const void *, const void *, size_t) asm("memcmp");
|
||||
|
||||
#if 0
|
||||
BENCH(bcmp, bench) {
|
||||
volatile int v;
|
||||
const char *volatile a;
|
||||
const char *volatile b;
|
||||
b = a = "123456789123456789123456789123456789123456789123456789";
|
||||
b = gc(strdup(b));
|
||||
EZBENCH_N("bcmp", 0, v = buncmp(a, b, 0));
|
||||
EZBENCH_N("bcmp", 1, v = buncmp(a, b, 1));
|
||||
EZBENCH_N("bcmp", 2, v = buncmp(a, b, 2));
|
||||
EZBENCH_N("bcmp", 3, v = buncmp(a, b, 3));
|
||||
EZBENCH_N("𝗯𝗰𝗺𝗽", 4, v = buncmp(a, b, 4));
|
||||
EZBENCH_N("bcmp", 5, v = buncmp(a, b, 5));
|
||||
EZBENCH_N("bcmp", 6, v = buncmp(a, b, 6));
|
||||
EZBENCH_N("bcmp", 7, v = buncmp(a, b, 7));
|
||||
EZBENCH_N("𝗯𝗰𝗺𝗽", 8, v = buncmp(a, b, 8));
|
||||
EZBENCH_N("bcmp", 9, v = buncmp(a, b, 9));
|
||||
EZBENCH_N("bcmp", 15, v = buncmp(a, b, 15));
|
||||
EZBENCH_N("𝗯𝗰𝗺𝗽", 16, v = buncmp(a, b, 16));
|
||||
EZBENCH_N("bcmp", 17, v = buncmp(a, b, 17));
|
||||
EZBENCH_N("bcmp", 31, v = buncmp(a, b, 31));
|
||||
EZBENCH_N("bcmp", 32, v = buncmp(a, b, 32));
|
||||
a = kHyperion;
|
||||
b = gc(strdup(kHyperion));
|
||||
EZBENCH_N("bcmp", 33, v = buncmp(a, b, 33));
|
||||
EZBENCH_N("bcmp", 79, v = buncmp(a, b, 79));
|
||||
EZBENCH_N("𝗯𝗰𝗺𝗽", 80, v = buncmp(a, b, 80));
|
||||
EZBENCH_N("bcmp", 128, v = buncmp(a, b, 128));
|
||||
EZBENCH_N("bcmp", 256, v = buncmp(a, b, 256));
|
||||
a = gc(malloc(16 * 1024));
|
||||
b = gc(malloc(16 * 1024));
|
||||
rngset(a, 16 * 1024, lemur64, -1);
|
||||
memcpy(b, a, 16 * 1024);
|
||||
EZBENCH_N("bcmp", 16384, v = buncmp(a, b, 16384));
|
||||
a = gc(malloc(32 * 1024));
|
||||
b = gc(malloc(32 * 1024));
|
||||
rngset(a, 32 * 1024, lemur64, -1);
|
||||
memcpy(b, a, 32 * 1024);
|
||||
EZBENCH_N("bcmp", 32768, v = buncmp(a, b, 32768));
|
||||
a = gc(malloc(128 * 1024));
|
||||
b = gc(malloc(128 * 1024));
|
||||
rngset(a, 128 * 1024, lemur64, -1);
|
||||
memcpy(b, a, 128 * 1024);
|
||||
EZBENCH_N("bcmp", 131072, v = buncmp(a, b, 131072));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#if 1
|
||||
BENCH(memcmp, bench) {
|
||||
volatile int v;
|
||||
const char *volatile a;
|
||||
const char *volatile b;
|
||||
char *volatile a;
|
||||
char *volatile b;
|
||||
b = a = "123456789123456789123456789123456789123456789123456789";
|
||||
b = gc(strdup(b));
|
||||
EZBENCH_N("memcmp", 0, v = funcmp(a, b, 0));
|
||||
EZBENCH_N("memcmp", 1, v = funcmp(a, b, 1));
|
||||
EZBENCH_N("memcmp", 2, v = funcmp(a, b, 2));
|
||||
EZBENCH_N("memcmp", 3, v = funcmp(a, b, 3));
|
||||
EZBENCH_N("𝗺𝗲𝗺𝗰𝗺𝗽", 4, v = funcmp(a, b, 4));
|
||||
EZBENCH_N("memcmp", 5, v = funcmp(a, b, 5));
|
||||
EZBENCH_N("memcmp", 6, v = funcmp(a, b, 6));
|
||||
EZBENCH_N("memcmp", 7, v = funcmp(a, b, 7));
|
||||
EZBENCH_N("𝗺𝗲𝗺𝗰𝗺𝗽", 8, v = funcmp(a, b, 8));
|
||||
EZBENCH_N("memcmp", 9, v = funcmp(a, b, 9));
|
||||
EZBENCH_N("memcmp", 15, v = funcmp(a, b, 15));
|
||||
EZBENCH_N("𝗺𝗲𝗺𝗰𝗺𝗽", 16, v = funcmp(a, b, 16));
|
||||
EZBENCH_N("memcmp", 17, v = funcmp(a, b, 17));
|
||||
EZBENCH_N("memcmp", 31, v = funcmp(a, b, 31));
|
||||
EZBENCH_N("memcmp", 32, v = funcmp(a, b, 32));
|
||||
EZBENCH_N("memcmp", 0, __expropriate(funcmp(a, b, 0)));
|
||||
EZBENCH_N("memcmp", 1, __expropriate(funcmp(a, b, 1)));
|
||||
EZBENCH_N("memcmp", 2, __expropriate(funcmp(a, b, 2)));
|
||||
EZBENCH_N("memcmp", 3, __expropriate(funcmp(a, b, 3)));
|
||||
EZBENCH_N("𝗺𝗲𝗺𝗰𝗺𝗽", 4, __expropriate(funcmp(a, b, 4)));
|
||||
EZBENCH_N("memcmp", 5, __expropriate(funcmp(a, b, 5)));
|
||||
EZBENCH_N("memcmp", 6, __expropriate(funcmp(a, b, 6)));
|
||||
EZBENCH_N("memcmp", 7, __expropriate(funcmp(a, b, 7)));
|
||||
EZBENCH_N("𝗺𝗲𝗺𝗰𝗺𝗽", 8, __expropriate(funcmp(a, b, 8)));
|
||||
EZBENCH_N("memcmp", 9, __expropriate(funcmp(a, b, 9)));
|
||||
EZBENCH_N("memcmp", 15, __expropriate(funcmp(a, b, 15)));
|
||||
EZBENCH_N("𝗺𝗲𝗺𝗰𝗺𝗽", 16, __expropriate(funcmp(a, b, 16)));
|
||||
EZBENCH_N("memcmp", 17, __expropriate(funcmp(a, b, 17)));
|
||||
EZBENCH_N("memcmp", 31, __expropriate(funcmp(a, b, 31)));
|
||||
EZBENCH_N("memcmp", 32, __expropriate(funcmp(a, b, 32)));
|
||||
a = kHyperion;
|
||||
b = gc(strdup(kHyperion));
|
||||
EZBENCH_N("memcmp", 33, v = funcmp(a, b, 33));
|
||||
EZBENCH_N("memcmp", 79, v = funcmp(a, b, 79));
|
||||
EZBENCH_N("𝗺𝗲𝗺𝗰𝗺𝗽", 80, v = funcmp(a, b, 80));
|
||||
EZBENCH_N("memcmp", 128, v = funcmp(a, b, 128));
|
||||
EZBENCH_N("memcmp", 256, v = funcmp(a, b, 256));
|
||||
EZBENCH_N("memcmp", 33, __expropriate(funcmp(a, b, 33)));
|
||||
EZBENCH_N("memcmp", 79, __expropriate(funcmp(a, b, 79)));
|
||||
EZBENCH_N("𝗺𝗲𝗺𝗰𝗺𝗽", 80, __expropriate(funcmp(a, b, 80)));
|
||||
EZBENCH_N("memcmp", 128, __expropriate(funcmp(a, b, 128)));
|
||||
EZBENCH_N("memcmp", 256, __expropriate(funcmp(a, b, 256)));
|
||||
a = gc(malloc(16 * 1024));
|
||||
b = gc(malloc(16 * 1024));
|
||||
rngset(a, 16 * 1024, lemur64, -1);
|
||||
memcpy(b, a, 16 * 1024);
|
||||
EZBENCH_N("memcmp", 16384, v = funcmp(a, b, 16384));
|
||||
EZBENCH_N("memcmp", 16384, __expropriate(funcmp(a, b, 16384)));
|
||||
a = gc(malloc(32 * 1024));
|
||||
b = gc(malloc(32 * 1024));
|
||||
rngset(a, 32 * 1024, lemur64, -1);
|
||||
memcpy(b, a, 32 * 1024);
|
||||
EZBENCH_N("memcmp", 32768, v = funcmp(a, b, 32768));
|
||||
EZBENCH_N("memcmp", 32768, __expropriate(funcmp(a, b, 32768)));
|
||||
a = gc(malloc(128 * 1024));
|
||||
b = gc(malloc(128 * 1024));
|
||||
rngset(a, 128 * 1024, lemur64, -1);
|
||||
memcpy(b, a, 128 * 1024);
|
||||
EZBENCH_N("memcmp", 131072, v = funcmp(a, b, 131072));
|
||||
EZBENCH_N("memcmp", 131072, __expropriate(funcmp(a, b, 131072)));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -253,53 +224,6 @@ BENCH(timingsafe_memcmp, bench) {
|
|||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
BENCH(timingsafe_bcmp, bench) {
|
||||
volatile int v;
|
||||
const char *volatile a;
|
||||
const char *volatile b;
|
||||
b = a = "123456789123456789123456789123456789123456789123456789";
|
||||
b = gc(strdup(b));
|
||||
EZBENCH_N("timingsafe_bcmp", 0, v = timingsafe_bcmp(a, b, 0));
|
||||
EZBENCH_N("timingsafe_bcmp", 1, v = timingsafe_bcmp(a, b, 1));
|
||||
EZBENCH_N("timingsafe_bcmp", 2, v = timingsafe_bcmp(a, b, 2));
|
||||
EZBENCH_N("timingsafe_bcmp", 3, v = timingsafe_bcmp(a, b, 3));
|
||||
EZBENCH_N("𝘁𝗶𝗺𝗶𝗻𝗴𝘀𝗮𝗳𝗲_𝗯𝗰𝗺𝗽", 4, v = timingsafe_bcmp(a, b, 4));
|
||||
EZBENCH_N("timingsafe_bcmp", 5, v = timingsafe_bcmp(a, b, 5));
|
||||
EZBENCH_N("timingsafe_bcmp", 6, v = timingsafe_bcmp(a, b, 6));
|
||||
EZBENCH_N("timingsafe_bcmp", 7, v = timingsafe_bcmp(a, b, 7));
|
||||
EZBENCH_N("𝘁𝗶𝗺𝗶𝗻𝗴𝘀𝗮𝗳𝗲_𝗯𝗰𝗺𝗽", 8, v = timingsafe_bcmp(a, b, 8));
|
||||
EZBENCH_N("timingsafe_bcmp", 9, v = timingsafe_bcmp(a, b, 9));
|
||||
EZBENCH_N("timingsafe_bcmp", 15, v = timingsafe_bcmp(a, b, 15));
|
||||
EZBENCH_N("𝘁𝗶𝗺𝗶𝗻𝗴𝘀𝗮𝗳𝗲_𝗯𝗰𝗺𝗽", 16, v = timingsafe_bcmp(a, b, 16));
|
||||
EZBENCH_N("timingsafe_bcmp", 17, v = timingsafe_bcmp(a, b, 17));
|
||||
EZBENCH_N("timingsafe_bcmp", 31, v = timingsafe_bcmp(a, b, 31));
|
||||
EZBENCH_N("timingsafe_bcmp", 32, v = timingsafe_bcmp(a, b, 32));
|
||||
a = kHyperion;
|
||||
b = gc(strdup(kHyperion));
|
||||
EZBENCH_N("timingsafe_bcmp", 33, v = timingsafe_bcmp(a, b, 33));
|
||||
EZBENCH_N("timingsafe_bcmp", 79, v = timingsafe_bcmp(a, b, 79));
|
||||
EZBENCH_N("𝘁𝗶𝗺𝗶𝗻𝗴𝘀𝗮𝗳𝗲_𝗯𝗰𝗺𝗽", 80, v = timingsafe_bcmp(a, b, 80));
|
||||
EZBENCH_N("timingsafe_bcmp", 128, v = timingsafe_bcmp(a, b, 128));
|
||||
EZBENCH_N("timingsafe_bcmp", 256, v = timingsafe_bcmp(a, b, 256));
|
||||
a = gc(malloc(16 * 1024));
|
||||
b = gc(malloc(16 * 1024));
|
||||
rngset(a, 16 * 1024, lemur64, -1);
|
||||
memcpy(b, a, 16 * 1024);
|
||||
EZBENCH_N("timingsafe_bcmp", 16384, v = timingsafe_bcmp(a, b, 16384));
|
||||
a = gc(malloc(32 * 1024));
|
||||
b = gc(malloc(32 * 1024));
|
||||
rngset(a, 32 * 1024, lemur64, -1);
|
||||
memcpy(b, a, 32 * 1024);
|
||||
EZBENCH_N("timingsafe_bcmp", 32768, v = timingsafe_bcmp(a, b, 32768));
|
||||
a = gc(malloc(128 * 1024));
|
||||
b = gc(malloc(128 * 1024));
|
||||
rngset(a, 128 * 1024, lemur64, -1);
|
||||
memcpy(b, a, 128 * 1024);
|
||||
EZBENCH_N("timingsafe_bcmp", 131072, v = timingsafe_bcmp(a, b, 131072));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
BENCH(memcasecmp, bench) {
|
||||
volatile int v;
|
||||
|
|
|
@ -33,7 +33,7 @@ struct Bog {
|
|||
const char *p[];
|
||||
};
|
||||
|
||||
static dontdiscard struct Bog *NewBog(unsigned n) {
|
||||
static __wur struct Bog *NewBog(unsigned n) {
|
||||
struct Bog *res = malloc(sizeof(struct Bog) + sizeof(const char *) * n);
|
||||
res->i = 0;
|
||||
res->n = n;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
#include "libc/str/str.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
#define OPEN_MAX 16
|
||||
|
||||
#define I(x, y) \
|
||||
{ x, y, 0, (y - x) * FRAMESIZE + FRAMESIZE }
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "libc/intrin/bits.h"
|
||||
#include "libc/intrin/safemacros.internal.h"
|
||||
#include "libc/intrin/xchg.internal.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/mem/gc.h"
|
||||
#include "libc/mem/mem.h"
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/mem/critbit0.h"
|
||||
#include "libc/mem/gc.h"
|
||||
#include "libc/mem/gc.internal.h"
|
||||
|
@ -95,6 +96,13 @@ TEST(opendir, openRealDirEntry) {
|
|||
EXPECT_EQ(0, closedir(dir));
|
||||
}
|
||||
|
||||
TEST(fdopendir, test) {
|
||||
ASSERT_SYS(0, 0, touch("foo", 0644));
|
||||
ASSERT_SYS(0, 3, open("foo", O_RDONLY));
|
||||
ASSERT_SYS(ENOTDIR, 0, fdopendir(3));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
}
|
||||
|
||||
TEST(dirstream, testDots) {
|
||||
int hasdot = 0;
|
||||
int hasdotdot = 0;
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include "libc/mem/gc.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/stdio/temp.h"
|
||||
#include "libc/temp.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
TEST(fmemopen, testWriteRewindRead) {
|
||||
|
|
|
@ -21,12 +21,13 @@
|
|||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/calls/syscall_support-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/mem/gc.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/stdio/temp.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/temp.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/x/xasprintf.h"
|
||||
|
||||
|
@ -79,7 +80,7 @@ TEST(tmpfile, test) {
|
|||
#ifndef __aarch64__
|
||||
// TODO(jart): Find way to detect qemu-aarch64
|
||||
TEST(tmpfile, renameToRealFile) {
|
||||
if (!IsLinux() || !__is_linux_2_6_23()) return;
|
||||
if (!(IsLinux() && __is_linux_2_6_23())) return; // need non-ancient linux
|
||||
FILE *f;
|
||||
f = tmpfile();
|
||||
ASSERT_EQ(2, fputs("hi", f));
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/nexgen32e/crc32.h"
|
||||
#include "libc/stdio/rand.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/testlib/hyperion.h"
|
||||
|
@ -68,3 +71,28 @@ TEST(ungetwc, testGetWideChar_canBeUndoneWithinReason) {
|
|||
EXPECT_STREQ("𐌰𐌱\n", buf);
|
||||
EXPECT_EQ(0, fclose(f));
|
||||
}
|
||||
|
||||
TEST(ungetc, io) {
|
||||
static char b1[BUFSIZ * 2];
|
||||
static char b2[BUFSIZ * 2];
|
||||
for (int i = 0; i < sizeof(b1); ++i) {
|
||||
b1[i] = rand();
|
||||
}
|
||||
FILE *f = tmpfile();
|
||||
fwrite(b1, 1, sizeof(b1), f);
|
||||
rewind(f);
|
||||
for (int i = 0; i < sizeof(b1); ++i) {
|
||||
int c;
|
||||
ASSERT_NE(EOF, (c = fgetc(f)));
|
||||
ASSERT_EQ(c, ungetc(c, f));
|
||||
ASSERT_EQ(c, fgetc(f));
|
||||
b2[i] = c;
|
||||
if (rand() % 10 == 0) {
|
||||
ASSERT_NE(EOF, fflush(f));
|
||||
ASSERT_NE(i, lseek(fileno(f), 0, SEEK_CUR));
|
||||
}
|
||||
}
|
||||
ASSERT_EQ(EOF, fgetc(f));
|
||||
fclose(f);
|
||||
ASSERT_EQ(crc32c(0, b1, sizeof(b1)), crc32c(0, b2, sizeof(b2)));
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include "libc/mem/gc.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/temp.h"
|
||||
#include "libc/temp.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
|
|
|
@ -6,7 +6,7 @@ COSMOPOLITAN_C_START_
|
|||
int ild(const char16_t *codez);
|
||||
int ildreal(const char16_t *codez);
|
||||
int ildlegacy(const char16_t *codez);
|
||||
uint8_t *unbingx86op(const char16_t *codez) dontdiscard;
|
||||
uint8_t *unbingx86op(const char16_t *codez) __wur;
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include "test/libc/xed/lib.h"
|
||||
#include "third_party/xed/x86.h"
|
||||
|
||||
dontdiscard uint8_t *unbingx86op(const char16_t *codez) {
|
||||
__wur uint8_t *unbingx86op(const char16_t *codez) {
|
||||
size_t len;
|
||||
len = strlen16(codez);
|
||||
return unbingbuf(xmalloc(ROUNDUP(len, 16)), len, codez, 0x90);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue