Skip to content

Commit 3f49889

Browse files
committed
Make important improvements
- Fix preadv() and pwritev() for old distros - Introduce _npassert() and _unassert() macros - Prove that file locks work properly on Windows - Support fcntl(F_DUPFD_CLOEXEC) on more systems
1 parent 1ad2f53 commit 3f49889

File tree

130 files changed

+1210
-416
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

130 files changed

+1210
-416
lines changed

build/config.mk

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,10 @@ CONFIG_CCFLAGS += \
152152
-fomit-frame-pointer \
153153
-momit-leaf-frame-pointer \
154154
-foptimize-sibling-calls
155+
CONFIG_OFLAGS += \
156+
-g0
157+
CONFIG_LDFLAGS += \
158+
-S
155159
TARGET_ARCH ?= \
156160
-msse3
157161
PYFLAGS += \
@@ -180,6 +184,10 @@ CONFIG_CPPFLAGS += \
180184
-DSUPPORT_VECTOR=1
181185
DEFAULT_COPTS += \
182186
-mred-zone
187+
CONFIG_OFLAGS += \
188+
-g0
189+
CONFIG_LDFLAGS += \
190+
-S
183191
CONFIG_CCFLAGS += \
184192
-Os \
185193
-fno-align-functions \
@@ -212,6 +220,10 @@ CONFIG_CPPFLAGS += \
212220
-DSUPPORT_VECTOR=113
213221
DEFAULT_COPTS += \
214222
-mred-zone
223+
CONFIG_OFLAGS += \
224+
-g0
225+
CONFIG_LDFLAGS += \
226+
-S
215227
CONFIG_CCFLAGS += \
216228
-Os \
217229
-fno-align-functions \
@@ -249,6 +261,10 @@ CONFIG_CCFLAGS += \
249261
-fno-align-jumps \
250262
-fno-align-labels \
251263
-fno-align-loops
264+
CONFIG_OFLAGS += \
265+
-g0
266+
CONFIG_LDFLAGS += \
267+
-S
252268
TARGET_ARCH ?= \
253269
-msse3
254270
endif
@@ -278,6 +294,10 @@ CONFIG_CCFLAGS += \
278294
-fno-align-jumps \
279295
-fno-align-labels \
280296
-fno-align-loops
297+
CONFIG_OFLAGS += \
298+
-g0
299+
CONFIG_LDFLAGS += \
300+
-S
281301
TARGET_ARCH ?= \
282302
-msse3
283303
endif

examples/clock_getres.c

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#if 0
2+
/*─────────────────────────────────────────────────────────────────╗
3+
│ To the extent possible under law, Justine Tunney has waived │
4+
│ all copyright and related or neighboring rights to this file, │
5+
│ as it is written in the following disclaimers: │
6+
│ • http://unlicense.org/ │
7+
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
8+
╚─────────────────────────────────────────────────────────────────*/
9+
#endif
10+
#include "libc/calls/struct/timespec.h"
11+
#include "libc/errno.h"
12+
#include "libc/intrin/describeflags.internal.h"
13+
#include "libc/intrin/kprintf.h"
14+
#include "libc/str/str.h"
15+
#include "libc/sysv/consts/clock.h"
16+
17+
int n;
18+
int shown[64];
19+
20+
void show(int clock) {
21+
int i;
22+
struct timespec ts;
23+
if (clock == 127) return;
24+
for (i = 0; i < n; ++i) {
25+
if (shown[i] == clock) {
26+
return;
27+
}
28+
}
29+
shown[n++] = clock;
30+
if (clock_getres(clock, &ts) != -1) {
31+
kprintf("%s %'ld ns\n", DescribeClockName(clock), _timespec_tonanos(ts));
32+
} else {
33+
kprintf("%s %s\n", DescribeClockName(clock), _strerrno(errno));
34+
}
35+
}
36+
37+
int main(int argc, char *argv[]) {
38+
show(CLOCK_REALTIME);
39+
show(CLOCK_REALTIME_FAST);
40+
show(CLOCK_REALTIME_PRECISE);
41+
show(CLOCK_MONOTONIC);
42+
show(CLOCK_MONOTONIC_RAW);
43+
show(CLOCK_MONOTONIC_FAST);
44+
show(CLOCK_MONOTONIC_PRECISE);
45+
show(CLOCK_PROCESS_CPUTIME_ID);
46+
show(CLOCK_THREAD_CPUTIME_ID);
47+
show(CLOCK_PROF);
48+
show(CLOCK_BOOTTIME);
49+
show(CLOCK_REALTIME_ALARM);
50+
show(CLOCK_BOOTTIME_ALARM);
51+
show(CLOCK_TAI);
52+
show(CLOCK_UPTIME);
53+
show(CLOCK_UPTIME_PRECISE);
54+
show(CLOCK_UPTIME_FAST);
55+
show(CLOCK_SECOND);
56+
}

libc/assert.h

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,29 @@ extern bool __assert_disable;
77
void __assert_fail(const char *, const char *, int) hidden relegated;
88

99
#ifdef NDEBUG
10-
#define assert(EXPR) ((void)0)
10+
#define assert(x) ((void)0)
1111
#else
12-
#define assert(EXPR) \
13-
((void)((EXPR) || (__assert_fail(#EXPR, __FILE__, __LINE__), 0)))
12+
#define assert(x) ((void)((x) || (__assert_fail(#x, __FILE__, __LINE__), 0)))
1413
#endif
1514

1615
#ifndef __cplusplus
1716
#define static_assert _Static_assert
1817
#endif
1918

19+
#define _unassert(x) \
20+
do { \
21+
if (__builtin_expect(!(x), 0)) { \
22+
unreachable; \
23+
} \
24+
} while (0)
25+
26+
#define _npassert(x) \
27+
do { \
28+
if (__builtin_expect(!(x), 0)) { \
29+
notpossible; \
30+
} \
31+
} while (0)
32+
2033
COSMOPOLITAN_C_END_
2134
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
2235
#endif /* COSMOPOLITAN_LIBC_ASSERT_H_ */

libc/calls/chdir-nt.c

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,35 +26,36 @@
2626
#include "libc/nt/synchronization.h"
2727
#include "libc/sysv/errfuns.h"
2828

29-
textwindows int sys_chdir_nt(const char *path) {
29+
textwindows int sys_chdir_nt_impl(char16_t path[hasatleast PATH_MAX],
30+
uint32_t len) {
3031
uint32_t n;
31-
int e, ms, err, len;
32-
char16_t path16[PATH_MAX], var[4];
33-
if ((len = __mkntpath(path, path16)) == -1) return -1;
34-
if (!len) return enoent();
35-
if (len && path16[len - 1] != u'\\') {
32+
int e, ms, err;
33+
char16_t var[4];
34+
35+
if (len && path[len - 1] != u'\\') {
3636
if (len + 2 > PATH_MAX) return enametoolong();
37-
path16[len + 0] = u'\\';
38-
path16[len + 1] = u'\0';
37+
path[len + 0] = u'\\';
38+
path[len + 1] = u'\0';
3939
}
40+
4041
/*
4142
* chdir() seems flaky on windows 7
4243
* in a similar way to rmdir() sigh
4344
*/
4445
for (err = errno, ms = 1;; ms *= 2) {
45-
if (SetCurrentDirectory(path16)) {
46+
if (SetCurrentDirectory(path)) {
4647
/*
4748
* Now we need to set a magic environment variable.
4849
*/
49-
if ((n = GetCurrentDirectory(ARRAYLEN(path16), path16))) {
50-
if (n < ARRAYLEN(path16)) {
51-
if (!((path16[0] == '/' && path16[1] == '/') ||
52-
(path16[0] == '\\' && path16[1] == '\\'))) {
50+
if ((n = GetCurrentDirectory(PATH_MAX, path))) {
51+
if (n < PATH_MAX) {
52+
if (!((path[0] == '/' && path[1] == '/') ||
53+
(path[0] == '\\' && path[1] == '\\'))) {
5354
var[0] = '=';
54-
var[1] = path16[0];
55+
var[1] = path[0];
5556
var[2] = ':';
5657
var[3] = 0;
57-
if (!SetEnvironmentVariable(var, path16)) {
58+
if (!SetEnvironmentVariable(var, path)) {
5859
return __winerr();
5960
}
6061
}
@@ -77,5 +78,13 @@ textwindows int sys_chdir_nt(const char *path) {
7778
}
7879
}
7980
}
80-
return __fix_enotdir(-1, path16);
81+
return __fix_enotdir(-1, path);
82+
}
83+
84+
textwindows int sys_chdir_nt(const char *path) {
85+
int len;
86+
char16_t path16[PATH_MAX];
87+
if ((len = __mkntpath(path, path16)) == -1) return -1;
88+
if (!len) return enoent();
89+
return sys_chdir_nt_impl(path16, len);
8190
}

libc/calls/dup-nt.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
1717
│ PERFORMANCE OF THIS SOFTWARE. │
1818
╚─────────────────────────────────────────────────────────────────────────────*/
19+
#include "libc/assert.h"
1920
#include "libc/calls/calls.h"
2021
#include "libc/calls/internal.h"
2122
#include "libc/calls/state.internal.h"
@@ -32,10 +33,9 @@
3233
*/
3334
textwindows int sys_dup_nt(int oldfd, int newfd, int flags, int start) {
3435
int64_t rc, proc, handle;
35-
36-
// validate the api usage
37-
if (oldfd < 0) return ebadf();
38-
if (flags & ~O_CLOEXEC) return einval();
36+
_unassert(oldfd >= 0);
37+
_unassert(newfd >= -1);
38+
_unassert(!(flags & ~O_CLOEXEC));
3939

4040
__fds_lock();
4141

libc/calls/dup3-sysv.c

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,41 +16,52 @@
1616
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
1717
│ PERFORMANCE OF THIS SOFTWARE. │
1818
╚─────────────────────────────────────────────────────────────────────────────*/
19-
#include "libc/intrin/strace.internal.h"
19+
#include "libc/assert.h"
2020
#include "libc/calls/syscall-sysv.internal.h"
2121
#include "libc/calls/syscall_support-sysv.internal.h"
2222
#include "libc/dce.h"
2323
#include "libc/errno.h"
24+
#include "libc/intrin/strace.internal.h"
2425
#include "libc/sysv/consts/o.h"
2526
#include "libc/sysv/errfuns.h"
27+
#include "libc/thread/thread.h"
2628

2729
#define F_DUP2FD 10
2830
#define F_DUP2FD_CLOEXEC 18
2931

32+
static struct Dup3 {
33+
pthread_once_t once;
34+
bool demodernize;
35+
} g_dup3;
36+
37+
static void sys_dup3_test(void) {
38+
int e = errno;
39+
__sys_dup3(-1, -1, 0);
40+
if ((g_dup3.demodernize = errno == ENOSYS)) {
41+
STRACE("demodernizing %s() due to %s", "dup3", "ENOSYS");
42+
}
43+
errno = e;
44+
}
45+
3046
int32_t sys_dup3(int32_t oldfd, int32_t newfd, int flags) {
31-
static bool once;
32-
static bool demodernize;
33-
int olderr, how, fd;
34-
if (!once) {
35-
olderr = errno;
36-
fd = __sys_dup3(oldfd, newfd, flags);
37-
if (fd == -1 && errno == ENOSYS) {
38-
STRACE("demodernizing %s() due to %s", "dup3", "RHEL5:CVE-2010-3301");
39-
demodernize = true;
40-
once = true;
41-
errno = olderr;
47+
int how;
48+
_unassert(oldfd >= 0);
49+
_unassert(newfd >= 0);
50+
_unassert(!(flags & ~O_CLOEXEC));
51+
52+
if (IsFreebsd()) {
53+
if (flags & O_CLOEXEC) {
54+
how = F_DUP2FD_CLOEXEC;
4255
} else {
43-
once = true;
44-
return fd;
56+
how = F_DUP2FD;
4557
}
46-
} else if (!demodernize) {
47-
return __sys_dup3(oldfd, newfd, flags);
48-
}
49-
if (oldfd == newfd) return einval();
50-
if (flags & ~O_CLOEXEC) return einval();
51-
if (IsFreebsd()) {
52-
how = flags & O_CLOEXEC ? F_DUP2FD_CLOEXEC : F_DUP2FD;
5358
return __sys_fcntl(oldfd, how, newfd);
59+
}
60+
61+
pthread_once(&g_dup3.once, sys_dup3_test);
62+
63+
if (!g_dup3.demodernize) {
64+
return __sys_dup3(oldfd, newfd, flags);
5465
} else {
5566
return __fixupnewfd(sys_dup2(oldfd, newfd), flags);
5667
}

libc/calls/dup3.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@
1818
╚─────────────────────────────────────────────────────────────────────────────*/
1919
#include "libc/calls/calls.h"
2020
#include "libc/calls/internal.h"
21-
#include "libc/intrin/strace.internal.h"
2221
#include "libc/calls/syscall-nt.internal.h"
2322
#include "libc/calls/syscall-sysv.internal.h"
2423
#include "libc/dce.h"
24+
#include "libc/intrin/strace.internal.h"
25+
#include "libc/sysv/consts/o.h"
2526
#include "libc/sysv/errfuns.h"
2627

2728
/**
@@ -46,14 +47,14 @@
4647
*/
4748
int dup3(int oldfd, int newfd, int flags) {
4849
int rc;
49-
if (__isfdkind(oldfd, kFdZip)) {
50+
if (oldfd == newfd || (flags & ~O_CLOEXEC)) {
51+
rc = einval(); // NetBSD doesn't do this
52+
} else if (oldfd < 0 || newfd < 0) {
53+
rc = ebadf();
54+
} else if (__isfdkind(oldfd, kFdZip)) {
5055
rc = eopnotsupp();
51-
} else if (oldfd == newfd) {
52-
rc = einval();
5356
} else if (!IsWindows()) {
5457
rc = sys_dup3(oldfd, newfd, flags);
55-
} else if (newfd < 0) {
56-
rc = ebadf();
5758
} else {
5859
rc = sys_dup_nt(oldfd, newfd, flags, -1);
5960
}

libc/calls/fchdir-nt.c

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,12 @@
2323
#include "libc/nt/files.h"
2424
#include "libc/sysv/errfuns.h"
2525

26+
int sys_chdir_nt_impl(char16_t[hasatleast PATH_MAX], uint32_t);
27+
2628
textwindows int sys_fchdir_nt(int dirfd) {
27-
uint32_t len;
2829
char16_t dir[PATH_MAX];
2930
if (!__isfdkind(dirfd, kFdFile)) return ebadf();
30-
len = GetFinalPathNameByHandle(g_fds.p[dirfd].handle, dir, ARRAYLEN(dir),
31-
kNtFileNameNormalized | kNtVolumeNameDos);
32-
if (len + 1 + 1 > ARRAYLEN(dir)) return enametoolong();
33-
if (dir[len - 1] != u'\\') {
34-
dir[len + 0] = u'\\';
35-
dir[len + 1] = u'\0';
36-
}
37-
if (SetCurrentDirectory(dir)) {
38-
return 0;
39-
} else {
40-
return __winerr();
41-
}
31+
return sys_chdir_nt_impl(
32+
dir, GetFinalPathNameByHandle(g_fds.p[dirfd].handle, dir, ARRAYLEN(dir),
33+
kNtFileNameNormalized | kNtVolumeNameDos));
4234
}

0 commit comments

Comments
 (0)