mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-05 02:38:31 +00:00
Get codebase completely working with LLVM
You can now build Cosmopolitan with Clang: make -j8 MODE=llvm o/llvm/examples/hello.com The assembler and linker code is now friendly to LLVM too. So it's not needed to configure Clang to use binutils under the hood. If you love LLVM then you can now use pure LLVM.
This commit is contained in:
parent
0e36cb3ac4
commit
e75ffde09e
4528 changed files with 7776 additions and 11640 deletions
|
@ -1,5 +1,6 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_CALLS_SYSCALLS_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_SYSCALLS_H_
|
||||
#include "libc/calls/struct/dirent.h"
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/calls/struct/rlimit.h"
|
||||
#include "libc/calls/struct/rusage.h"
|
||||
|
@ -62,7 +63,6 @@ COSMOPOLITAN_C_START_
|
|||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
typedef int sig_atomic_t;
|
||||
typedef struct dirstream DIR;
|
||||
|
||||
extern const struct sigset kSigsetFull;
|
||||
extern const struct sigset kSigsetEmpty;
|
||||
|
@ -102,7 +102,6 @@ int execvp(const char *, char *const[]) paramsnonnull();
|
|||
int execvpe(const char *, char *const[], char *const[]) paramsnonnull();
|
||||
int faccessat(int, const char *, int, uint32_t);
|
||||
int fadvise(int, uint64_t, uint64_t, int);
|
||||
int fallocate(int, int32_t, int64_t, int64_t);
|
||||
int fchmod(int, uint32_t) nothrow;
|
||||
int fchmodat(int, const char *, uint32_t, uint32_t);
|
||||
int fchown(int, uint32_t, uint32_t);
|
||||
|
@ -147,7 +146,6 @@ int personality(uint64_t);
|
|||
int pipe(int[hasatleast 2]);
|
||||
int pipe2(int[hasatleast 2], int);
|
||||
int posix_fadvise(int, uint64_t, uint64_t, int);
|
||||
int posix_fallocate(int, int64_t, int64_t);
|
||||
int posix_madvise(void *, uint64_t, int);
|
||||
int raise(int);
|
||||
int readlink(const char *, char *, size_t);
|
||||
|
|
|
@ -1,74 +0,0 @@
|
|||
/*-*- 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 2020 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/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/nt/enum/fsctl.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/struct/filezerodatainformation.h"
|
||||
#include "libc/sysv/consts/falloc.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Manipulates underlying physical medium of file.
|
||||
*
|
||||
* This system call generalizes to many powerful use cases on Linux,
|
||||
* such as creating gigantic sparse files that take up little space.
|
||||
* This API can polyfill a certain subset of parameters safely, e.g.
|
||||
* ones identical to ftruncate(), but errs on the side of caution.
|
||||
*
|
||||
* @param fd must be open for writing
|
||||
* @param mode can be 0, FALLOC_xxx
|
||||
* @param length is how much physical space to reserve / commit
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
* @note limited availability on rhel5 and openbsd
|
||||
* @see ftruncate()
|
||||
*/
|
||||
int fallocate(int fd, int32_t mode, int64_t offset, int64_t length) {
|
||||
int rc;
|
||||
uint32_t br;
|
||||
if (mode == -1 /* our sysvconsts definition */) return eopnotsupp();
|
||||
if (!mode && !length) return ftruncate(fd, offset);
|
||||
if (IsLinux()) {
|
||||
rc = sys_fallocate(fd, mode, offset, length);
|
||||
if (rc == 0x011d) rc = enosys(); /*RHEL5:CVE-2010-3301*/
|
||||
return rc;
|
||||
} else if (!IsWindows()) {
|
||||
return sys_posix_fallocate(fd, offset, length);
|
||||
} else {
|
||||
if (!__isfdkind(fd, kFdFile)) return ebadf();
|
||||
if (mode == FALLOC_FL_ZERO_RANGE) {
|
||||
if (DeviceIoControl(
|
||||
g_fds.p[fd].handle, kNtFsctlSetZeroData,
|
||||
&(struct NtFileZeroDataInformation){offset, offset + length},
|
||||
sizeof(struct NtFileZeroDataInformation), NULL, 0, &br, NULL)) {
|
||||
return 0;
|
||||
} else {
|
||||
return __winerr();
|
||||
}
|
||||
} else if (!mode && !offset) {
|
||||
/*
|
||||
* this should commit physical space
|
||||
* but not guaranteed zero'd like linux
|
||||
*/
|
||||
return sys_ftruncate_nt(fd, length);
|
||||
} else {
|
||||
return enosys();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -29,7 +29,6 @@
|
|||
* since the prior extends logically and the latter physically
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
* @asyncsignalsafe
|
||||
* @see fallocate()
|
||||
*/
|
||||
int ftruncate(int fd, int64_t length) {
|
||||
if (!IsWindows()) {
|
||||
|
|
|
@ -19,13 +19,13 @@
|
|||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
|
||||
/ Obtains WIN32 magic path, e.g. GetTempPathA.
|
||||
/
|
||||
/ @param rax is address of ANSI path provider function
|
||||
/ @param rdi is output buffer
|
||||
/ @param rdx is output buffer size in bytes that's >0
|
||||
/ @return eax is string length w/ NUL that's ≤ edx
|
||||
/ @return rdi is rdi+edx
|
||||
// Obtains WIN32 magic path, e.g. GetTempPathA.
|
||||
//
|
||||
// @param rax is address of ANSI path provider function
|
||||
// @param rdi is output buffer
|
||||
// @param rdx is output buffer size in bytes that's >0
|
||||
// @return eax is string length w/ NUL that's ≤ edx
|
||||
// @return rdi is rdi+edx
|
||||
.text.startup
|
||||
__getntsyspath:
|
||||
push %rbp
|
||||
|
@ -40,14 +40,14 @@ __getntsyspath:
|
|||
cmovbe %edx,%eax
|
||||
cmp $1,%eax # leave empty strings empty
|
||||
jbe 1f
|
||||
cmpb $'\\,-1(%rdi,%rax) # guarantee trailing slash
|
||||
cmpb $'\\',-1(%rdi,%rax) # guarantee trailing slash
|
||||
je 1f
|
||||
movw $'\\,(%rdi,%rax)
|
||||
movw $'\\',(%rdi,%rax)
|
||||
inc %eax
|
||||
1: inc %rdi # change backslash to slash
|
||||
cmpb $'\\,-1(%rdi)
|
||||
cmpb $'\\',-1(%rdi)
|
||||
jne 2f
|
||||
movb $'/,-1(%rdi)
|
||||
movb $'/',-1(%rdi)
|
||||
2: .loop 1b
|
||||
leave
|
||||
ret
|
||||
|
|
|
@ -22,8 +22,8 @@
|
|||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows int sys_getsetpriority_nt(int which, unsigned who, int value,
|
||||
int (*impl)(int)) {
|
||||
int (*impl)(int)) {
|
||||
if (which != PRIO_PROCESS && which != PRIO_PGRP) return einval();
|
||||
if (who && abs(who) != getpid() && abs(who) != gettid()) return eopnotsupp();
|
||||
if (who && who != getpid() && who != gettid()) return eopnotsupp();
|
||||
return impl(value);
|
||||
}
|
||||
|
|
|
@ -19,9 +19,9 @@
|
|||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
|
||||
/ Calls GetTempPathA() w/ different API.
|
||||
/
|
||||
/ @see GetSystemDirectoryA(), GetWindowsDirectoryA()
|
||||
// Calls GetTempPathA() w/ different API.
|
||||
//
|
||||
// @see GetSystemDirectoryA(), GetWindowsDirectoryA()
|
||||
GetTempPathA_flunk:
|
||||
xchg %rcx,%rdx
|
||||
jmp *__imp_GetTempPathA(%rip)
|
||||
|
|
|
@ -120,7 +120,6 @@ i32 sys_dup3(i32, i32, i32) hidden;
|
|||
i32 sys_execve(const char *, char *const[], char *const[]) hidden;
|
||||
i32 sys_faccessat(i32, const char *, i32, u32) hidden;
|
||||
i32 sys_fadvise(i32, i64, i64, i32) hidden;
|
||||
i32 sys_fallocate(i64, i32, i64, i64) hidden;
|
||||
i32 sys_fchdir(i32) hidden;
|
||||
i32 sys_fchmod(i32, u32) hidden;
|
||||
i32 sys_fchmodat(i32, const char *, u32, u32) hidden;
|
||||
|
@ -158,7 +157,6 @@ i32 sys_openat(i32, const char *, i32, ...) hidden;
|
|||
i32 sys_pause(void) hidden;
|
||||
i32 sys_pipe(i32[hasatleast 2]) hidden;
|
||||
i32 sys_pipe2(i32[hasatleast 2], u32) hidden;
|
||||
i32 sys_posix_fallocate(i64, i64, i64) hidden;
|
||||
i32 sys_posix_openpt(i32) hidden;
|
||||
i32 sys_renameat(i32, const char *, i32, const char *) hidden;
|
||||
i32 sys_sched_setaffinity(i32, u64, const void *) hidden;
|
||||
|
@ -277,7 +275,7 @@ ssize_t sys_write_nt(struct Fd *, const struct iovec *, size_t, ssize_t) hidden;
|
|||
int64_t ntreturn(uint32_t);
|
||||
void WinMainForked(void) hidden;
|
||||
void *GetProcAddressModule(const char *, const char *) hidden;
|
||||
int sys_getsetpriority_nt(int, unsigned, int, int (*)(int));
|
||||
int sys_getsetpriority_nt(int, int, int, int (*)(int));
|
||||
void ntcontext2linux(struct ucontext *, const struct NtContext *) hidden;
|
||||
struct NtOverlapped *offset2overlap(int64_t, struct NtOverlapped *) hidden;
|
||||
bool32 ntsetprivilege(i64, const char16_t *, u32) hidden;
|
||||
|
|
|
@ -22,9 +22,9 @@
|
|||
|
||||
#define BYTES 64
|
||||
|
||||
/ RII constant holding 'C:/WINDOWS/SYSTEM32' directory.
|
||||
/
|
||||
/ @note guarantees trailing slash if non-empty
|
||||
// RII constant holding 'C:/WINDOWS/SYSTEM32' directory.
|
||||
//
|
||||
// @note guarantees trailing slash if non-empty
|
||||
.initbss 300,_init_kNtSystemDirectory
|
||||
kNtSystemDirectory:
|
||||
.zero BYTES
|
||||
|
|
|
@ -22,9 +22,9 @@
|
|||
|
||||
#define BYTES 64
|
||||
|
||||
/ RII constant holding 'C:/WINDOWS' directory.
|
||||
/
|
||||
/ @note guarantees trailing slash if non-empty
|
||||
// RII constant holding 'C:/WINDOWS' directory.
|
||||
//
|
||||
// @note guarantees trailing slash if non-empty
|
||||
.initbss 300,_init_kNtWindowsDirectory
|
||||
kNtWindowsDirectory:
|
||||
.zero BYTES
|
||||
|
|
|
@ -22,10 +22,10 @@
|
|||
|
||||
#define kTmpPathMax 80
|
||||
|
||||
/ RII constant holding /tmp/ directory.
|
||||
/
|
||||
/ @note on win32 this is firstNonNull($TMP, $TEMP, $PWD)
|
||||
/ @note guarantees trailing slash if non-empty
|
||||
// RII constant holding /tmp/ directory.
|
||||
//
|
||||
// @note on win32 this is firstNonNull($TMP, $TEMP, $PWD)
|
||||
// @note guarantees trailing slash if non-empty
|
||||
.initbss 300,_init_kTmpPath
|
||||
kTmpPath:
|
||||
.zero kTmpPathMax
|
||||
|
@ -33,8 +33,8 @@ kTmpPath:
|
|||
.previous
|
||||
|
||||
.init.start 300,_init_kTmpPath
|
||||
movl $'/|'t<<010|'m<<020|'p<<030,(%rdi)
|
||||
movw $'/,4(%rdi)
|
||||
movl $'/'|'t'<<010|'m'<<020|'p'<<030,(%rdi)
|
||||
movw $'/',4(%rdi)
|
||||
#if SupportsWindows()
|
||||
pushpop kTmpPathMax,%rdx
|
||||
ezlea GetTempPathA_flunk,ax
|
||||
|
|
|
@ -19,10 +19,10 @@
|
|||
#include "libc/nexgen32e/x86feature.h"
|
||||
#include "libc/macros.h"
|
||||
|
||||
/ Returns timestamp without needing system calls.
|
||||
/
|
||||
/ @return seconds since unix epoch in %st0
|
||||
/ @note uses microsecond scale fallback on k8 or vm
|
||||
// Returns timestamp without needing system calls.
|
||||
//
|
||||
// @return seconds since unix epoch in %st0
|
||||
// @note uses microsecond scale fallback on k8 or vm
|
||||
.initbss 202,_init_nowl
|
||||
nowl: .quad 0
|
||||
.endobj nowl,globl
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
/*-*- 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 2020 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/dce.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Manipulates underlying physical medium of file, the POSIX way.
|
||||
*
|
||||
* @param fd must be open for writing
|
||||
* @param length is how much physical space to reserve
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
* @see fallocate(), ftruncate()
|
||||
*/
|
||||
int posix_fallocate(int fd, int64_t offset, int64_t length) {
|
||||
return fallocate(fd, 0, offset, length);
|
||||
}
|
|
@ -19,18 +19,19 @@
|
|||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
errno_t ptsname_r(int fd, char *buf, size_t size) {
|
||||
int pty;
|
||||
char tb[32];
|
||||
if (size) {
|
||||
if (!buf) return einval();
|
||||
if (ioctl(fd, TIOCGPTN, &pty) == -1) return errno;
|
||||
if (snprintf(buf, size, "/dev/pts/%d", pty) >= size) {
|
||||
return (errno = ERANGE);
|
||||
}
|
||||
int64toarray_radix10(pty, stpcpy(tb, "/dev/pts/"));
|
||||
if (strlen(tb) + 1 >= size) return (errno = ERANGE);
|
||||
stpcpy(buf, tb);
|
||||
/* TODO(jart): OpenBSD OMG */
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -19,10 +19,10 @@
|
|||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
|
||||
/ Sets effective group ID.
|
||||
/
|
||||
/ @param %edi is group id
|
||||
/ @see setgid(), getauxval(AT_SECURE)
|
||||
// Sets effective group ID.
|
||||
//
|
||||
// @param %edi is group id
|
||||
// @see setgid(), getauxval(AT_SECURE)
|
||||
setegid:push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
|
|
|
@ -19,10 +19,10 @@
|
|||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
|
||||
/ Sets effective user ID.
|
||||
/
|
||||
/ @param %edi is user id
|
||||
/ @see setuid(), getauxval(AT_SECURE)
|
||||
// Sets effective user ID.
|
||||
//
|
||||
// @param %edi is user id
|
||||
// @see setuid(), getauxval(AT_SECURE)
|
||||
seteuid:push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
|
@ -134,15 +135,15 @@ static void sigaction_native2cosmo(union metasigaction *sa) {
|
|||
* @vforksafe
|
||||
*/
|
||||
int(sigaction)(int sig, const struct sigaction *act, struct sigaction *oldact) {
|
||||
_Static_assert(sizeof(struct sigaction) > sizeof(struct sigaction_linux) &&
|
||||
sizeof(struct sigaction) > sizeof(struct sigaction_xnu_in) &&
|
||||
sizeof(struct sigaction) > sizeof(struct sigaction_xnu_out) &&
|
||||
sizeof(struct sigaction) > sizeof(struct sigaction_freebsd) &&
|
||||
sizeof(struct sigaction) > sizeof(struct sigaction_openbsd) &&
|
||||
sizeof(struct sigaction) > sizeof(struct sigaction_netbsd));
|
||||
int64_t arg4, arg5;
|
||||
int rc, rva, oldrva;
|
||||
struct sigaction *ap, copy;
|
||||
assert(sizeof(struct sigaction) > sizeof(struct sigaction_linux) &&
|
||||
sizeof(struct sigaction) > sizeof(struct sigaction_xnu_in) &&
|
||||
sizeof(struct sigaction) > sizeof(struct sigaction_xnu_out) &&
|
||||
sizeof(struct sigaction) > sizeof(struct sigaction_freebsd) &&
|
||||
sizeof(struct sigaction) > sizeof(struct sigaction_openbsd) &&
|
||||
sizeof(struct sigaction) > sizeof(struct sigaction_netbsd));
|
||||
if (IsMetal()) return enosys(); /* TODO: Signals on Metal */
|
||||
if (!(0 < sig && sig < NSIG)) return einval();
|
||||
if (sig == SIGKILL || sig == SIGSTOP) return einval();
|
||||
|
|
|
@ -20,16 +20,16 @@
|
|||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
|
||||
/ BSD signal handler.
|
||||
/
|
||||
/ This is needed because (1) a signal is allowed to trigger at
|
||||
/ just about any time, and leaf functions (e.g. memcpy) aren't
|
||||
/ required to leave Cosmopolitan's image base register alone.
|
||||
/
|
||||
/ @param %edi is the signal number
|
||||
/ @param %rsi will be passed for sigactions
|
||||
/ @param %rdx will be passed for sigactions
|
||||
/ @return true if handler was invoked
|
||||
// BSD signal handler.
|
||||
//
|
||||
// This is needed because (1) a signal is allowed to trigger at
|
||||
// just about any time, and leaf functions (e.g. memcpy) aren't
|
||||
// required to leave Cosmopolitan's image base register alone.
|
||||
//
|
||||
// @param %edi is the signal number
|
||||
// @param %rsi will be passed for sigactions
|
||||
// @param %rdx will be passed for sigactions
|
||||
// @return true if handler was invoked
|
||||
__sigenter:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
|
|
|
@ -10,5 +10,8 @@ struct dirent { /* linux getdents64 abi */
|
|||
char d_name[256]; /* NUL-terminated basename */
|
||||
};
|
||||
|
||||
struct dirstream;
|
||||
typedef struct dirstream DIR;
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_DIRENT_H_ */
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/nt/console.h"
|
||||
#include "libc/nt/enum/consolemodeflags.h"
|
||||
|
@ -58,7 +59,7 @@ static int ttyname_linux(int fd, char *buf, size_t size) {
|
|||
struct stat st1, st2;
|
||||
if (!isatty(fd)) return errno;
|
||||
char name[PATH_MAX];
|
||||
snprintf(name, sizeof(name), "/proc/self/fd/%d", fd);
|
||||
int64toarray_radix10(fd, stpcpy(name, "/proc/self/fd/"));
|
||||
ssize_t got;
|
||||
got = readlink(name, buf, size);
|
||||
if (got == -1) return errno;
|
||||
|
|
|
@ -4,7 +4,5 @@
|
|||
|
||||
typedef void (*sighandler_t)(int);
|
||||
|
||||
typedef void (*sighandler_t)(int);
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_TYPEDEF_SIGHANDLER_T_H_ */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue