Fix termios struct on Linux

The termios::c_cc field turned out to be incorrectly defined on Linux
due to some confusion between the glibc and kernel definitions. We'll
be using the kernel definition, since it has the strongest consensus.

Fields have been have been added to struct stat for BSD compatibility
such as st_birthtim, plus the GLIBC compatibility of isystem/sys/stat
has been improved.
This commit is contained in:
Justine Tunney 2021-09-03 22:19:41 -07:00
parent 0584684a82
commit 5b60e5a37d
52 changed files with 358 additions and 296 deletions

View file

@ -67,6 +67,8 @@ o/$(MODE)/libc/calls/raise.o: \
OVERRIDE_COPTS += \
$(NO_MAGIC)
o/$(MODE)/libc/calls/termios2linux.o \
o/$(MODE)/libc/calls/termios2host.o \
o/$(MODE)/libc/calls/sigenter-freebsd.o \
o/$(MODE)/libc/calls/sigenter-netbsd.o \
o/$(MODE)/libc/calls/sigenter-openbsd.o \

View file

@ -19,6 +19,7 @@
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/metastat.internal.h"
#include "libc/calls/struct/stat.h"
#include "libc/dce.h"
#include "libc/errno.h"
@ -43,13 +44,13 @@
*/
bool fileexists(const char *path) {
int e;
struct stat st;
union metastat st;
struct ZiposUri zipname;
uint16_t path16[PATH_MAX];
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
if (weaken(__zipos_open) && weaken(__zipos_parseuri)(path, &zipname) != -1) {
e = errno;
if (weaken(__zipos_stat)(&zipname, &st) != -1) {
if (weaken(__zipos_stat)(&zipname, &st.cosmo) != -1) {
return true;
} else {
errno = e;

View file

@ -87,6 +87,7 @@ textwindows int sys_fstat_nt(int64_t handle, struct stat *st) {
case kNtFileTypeDisk:
if (GetFileInformationByHandle(handle, &wst)) {
st->st_mode = 0555;
st->st_flags = wst.dwFileAttributes;
if (!(wst.dwFileAttributes & kNtFileAttributeReadonly)) {
st->st_mode |= 0200;
}
@ -100,6 +101,7 @@ textwindows int sys_fstat_nt(int64_t handle, struct stat *st) {
st->st_atim = FileTimeToTimeSpec(wst.ftLastAccessFileTime);
st->st_mtim = FileTimeToTimeSpec(wst.ftLastWriteFileTime);
st->st_ctim = FileTimeToTimeSpec(wst.ftCreationFileTime);
st->st_birthtim = st->st_ctim;
st->st_size = (uint64_t)wst.nFileSizeHigh << 32 | wst.nFileSizeLow;
st->st_blksize = PAGESIZE;
st->st_dev = wst.dwVolumeSerialNumber;

View file

@ -17,15 +17,30 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/errfuns.h"
/**
* Supports fstat(), etc. implementations.
* @asyncsignalsafe
*/
textstartup int32_t sys_fstat(int32_t fd, struct stat *st) {
int res;
if ((res = __sys_fstat(fd, st)) != -1) {
__stat2linux(st);
int32_t sys_fstat(int32_t fd, struct stat *st) {
void *p;
union metastat ms;
if (IsLinux()) {
_Static_assert(sizeof(*st) == sizeof(ms.linux), "assumption broken");
if (IsAsan() && !__asan_is_valid(st, sizeof(*st))) return efault();
p = st;
} else if (st) {
p = &ms;
} else {
p = 0;
}
if (__sys_fstat(fd, p) != -1) {
__stat2cosmo(st, &ms);
return 0;
} else {
return -1;
}
return res;
}

View file

@ -29,7 +29,6 @@
* @asyncsignalsafe
*/
int fstat(int fd, struct stat *st) {
if (IsAsan() && !__asan_is_valid(st, sizeof(*st))) return efault();
if (__isfdkind(fd, kFdZip)) {
return weaken(__zipos_fstat)(
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, st);

View file

@ -17,16 +17,33 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/calls/struct/metastat.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/errfuns.h"
/**
* Supports stat(), lstat(), fstatat(), etc. implementations.
* @asyncsignalsafe
*/
int32_t sys_fstatat(int32_t dirfd, const char *pathname, struct stat *st,
int32_t sys_fstatat(int32_t dirfd, const char *path, struct stat *st,
int32_t flags) {
int32_t rc;
if ((rc = __sys_fstatat(dirfd, pathname, st, flags)) != -1) {
__stat2linux(st);
void *p;
union metastat ms;
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
if (IsLinux()) {
_Static_assert(sizeof(*st) == sizeof(ms.linux), "assumption broken");
if (IsAsan() && !__asan_is_valid(st, sizeof(*st))) return efault();
p = st;
} else if (st) {
p = &ms;
} else {
p = 0;
}
if (__sys_fstatat(dirfd, path, p, flags) != -1) {
__stat2cosmo(st, &ms);
return 0;
} else {
return -1;
}
return rc;
}

View file

@ -41,10 +41,6 @@
*/
int fstatat(int dirfd, const char *path, struct stat *st, int flags) {
struct ZiposUri zipname;
if (IsAsan() && (!__asan_is_valid(path, 1) ||
(st && !__asan_is_valid(st, sizeof(*st))))) {
return efault();
}
if (__isfdkind(dirfd, kFdZip)) return einval(); /* TODO(jart): implement me */
if (weaken(__zipos_stat) && weaken(__zipos_parseuri)(path, &zipname) != -1) {
return weaken(__zipos_stat)(&zipname, st);

View file

@ -4,10 +4,12 @@
#include "libc/calls/internal.h"
#include "libc/calls/struct/iovec.h"
#include "libc/calls/struct/itimerval.h"
#include "libc/calls/struct/metastat.internal.h"
#include "libc/calls/struct/rusage.h"
#include "libc/calls/struct/sigaction-xnu.internal.h"
#include "libc/calls/struct/siginfo.h"
#include "libc/calls/struct/sigval.h"
#include "libc/calls/struct/stat.h"
#include "libc/calls/struct/timespec.h"
#include "libc/calls/struct/timeval.h"
#include "libc/dce.h"
@ -222,7 +224,7 @@ u32 __prot2nt(i32, i32) privileged;
void __restore_rt() hidden;
int sys_utimensat_xnu(int, const char *, const struct timespec *, int) hidden;
int sys_nanosleep_xnu(const struct timespec *, struct timespec *) hidden;
void __stat2linux(void *) hidden;
void __stat2cosmo(struct stat *restrict, const union metastat *) hidden;
void __restore_rt_netbsd(void) hidden;
void __sigenter_xnu(void *, i32, i32, struct __darwin_siginfo *,
struct __darwin_ucontext *) hidden;

View file

@ -20,6 +20,7 @@
#include "libc/calls/ioctl.h"
#include "libc/calls/struct/metatermios.internal.h"
#include "libc/calls/termios.internal.h"
#include "libc/calls/ttydefaults.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sysv/consts/termios.h"
@ -27,13 +28,33 @@
int ioctl_tcgets_nt(int, struct termios *) hidden;
static int ioctl_tcgets_metal(int fd, struct termios *tio) {
memset(tio, 0, sizeof(*tio));
tio->c_iflag = TTYDEF_IFLAG;
tio->c_oflag = TTYDEF_OFLAG;
tio->c_lflag = TTYDEF_LFLAG;
tio->c_cflag = TTYDEF_CFLAG;
return 0;
}
static int ioctl_tcgets_sysv(int fd, struct termios *tio) {
int rc;
union metatermios t;
if ((rc = sys_ioctl(fd, TCGETS, &t)) != -1) {
__termios2linux(tio, &t);
union metatermios mt;
if (IsLinux()) {
if (IsAsan() && !__asan_is_valid(tio, sizeof(*tio))) return efault();
return sys_ioctl(fd, TCGETS, tio);
} else {
if ((rc = sys_ioctl(fd, TCGETS, &mt)) != -1) {
if (IsXnu()) {
COPY_TERMIOS(tio, &mt.xnu);
} else if (IsFreebsd() || IsOpenbsd() || IsNetbsd()) {
COPY_TERMIOS(tio, &mt.bsd);
} else {
unreachable;
}
}
return rc;
}
return rc;
}
/**
@ -51,9 +72,10 @@ int ioctl_tcgets(int fd, ...) {
va_end(va);
if (fd >= 0) {
if (!tio) return efault();
if (IsAsan() && !__asan_is_valid(tio, sizeof(*tio))) return efault();
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
return enotty();
} else if (IsMetal()) {
return ioctl_tcgets_metal(fd, tio);
} else if (!IsWindows()) {
return ioctl_tcgets_sysv(fd, tio);
} else {

View file

@ -27,10 +27,29 @@
int ioctl_tcsets_nt(int, uint64_t, const struct termios *);
static int ioctl_tcsets_metal(int fd, uint64_t request,
const struct termios *tio) {
return 0;
}
static inline void *__termios2host(union metatermios *mt,
const struct termios *lt) {
if (!IsXnu() && !IsFreebsd() && !IsOpenbsd() && !IsNetbsd()) {
return lt;
} else if (IsXnu()) {
COPY_TERMIOS(&mt->xnu, lt);
return &mt->xnu;
} else {
COPY_TERMIOS(&mt->bsd, lt);
return &mt->bsd;
}
}
static int ioctl_tcsets_sysv(int fd, uint64_t request,
const struct termios *tio) {
union metatermios t;
return sys_ioctl(fd, request, __termios2host(&t, tio));
union metatermios mt;
if (IsAsan() && !__asan_is_valid(tio, sizeof(*tio))) return efault();
return sys_ioctl(fd, request, __termios2host(&mt, tio));
}
/**
@ -47,10 +66,11 @@ int ioctl_tcsets(int fd, uint64_t request, ...) {
tio = va_arg(va, const struct termios *);
va_end(va);
if (!tio) return efault();
if (IsAsan() && !__asan_is_valid(tio, sizeof(*tio))) return efault();
if (fd >= 0) {
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
return enotty();
} else if (IsMetal()) {
return ioctl_tcsets_metal(fd, request, tio);
} else if (!IsWindows()) {
return ioctl_tcsets_sysv(fd, request, tio);
} else {

View file

@ -46,9 +46,9 @@ bool32 ischardev(int fd) {
if (__isfdkind(fd, kFdZip)) {
e = errno;
if (weaken(__zipos_fstat)(
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, &st.linux) !=
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, &st.cosmo) !=
-1) {
return S_ISCHR(st.linux.st_mode);
return S_ISCHR(st.cosmo.st_mode);
} else {
errno = e;
return false;

View file

@ -49,8 +49,8 @@ bool isdirectory(const char *path) {
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
if (weaken(__zipos_open) && weaken(__zipos_parseuri)(path, &zipname) != -1) {
e = errno;
if (weaken(__zipos_stat)(&zipname, &st.linux) != -1) {
return S_ISDIR(st.linux.st_mode);
if (weaken(__zipos_stat)(&zipname, &st.cosmo) != -1) {
return S_ISDIR(st.cosmo.st_mode);
} else {
errno = e;
return false;

View file

@ -46,8 +46,8 @@ bool isregularfile(const char *path) {
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
if (weaken(__zipos_open) && weaken(__zipos_parseuri)(path, &zipname) != -1) {
e = errno;
if (weaken(__zipos_stat)(&zipname, &st.linux) != -1) {
return S_ISREG(st.linux.st_mode);
if (weaken(__zipos_stat)(&zipname, &st.cosmo) != -1) {
return S_ISREG(st.cosmo.st_mode);
} else {
errno = e;
return false;

View file

@ -17,6 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/str/thompike.h"
#include "libc/sysv/errfuns.h"
@ -108,6 +109,7 @@ ssize_t readansi(int fd, char *buf, size_t size) {
case 'O':
t = kSs;
break;
case '\e':
case 0x20 ... 0x2F:
break;
default:

97
libc/calls/stat2cosmo.c Normal file
View file

@ -0,0 +1,97 @@
/*-*- 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/calls/struct/metastat.internal.h"
#include "libc/dce.h"
void __stat2cosmo(struct stat *restrict st, const union metastat *ms) {
if (st) {
if (IsLinux()) {
st->st_birthtim = st->st_ctim;
} else if (IsXnu()) {
st->st_dev = ms->xnu.st_dev;
st->st_ino = ms->xnu.st_ino;
st->st_nlink = ms->xnu.st_nlink;
st->st_mode = ms->xnu.st_mode;
st->st_uid = ms->xnu.st_uid;
st->st_gid = ms->xnu.st_gid;
st->st_flags = ms->xnu.st_flags;
st->st_rdev = ms->xnu.st_rdev;
st->st_size = ms->xnu.st_size;
st->st_blksize = ms->xnu.st_blksize;
st->st_blocks = ms->xnu.st_blocks;
st->st_gen = ms->xnu.st_gen;
st->st_atim = ms->xnu.st_atim;
st->st_mtim = ms->xnu.st_mtim;
st->st_ctim = ms->xnu.st_ctim;
st->st_birthtim = ms->xnu.st_birthtim;
} else if (IsFreebsd()) {
st->st_dev = ms->freebsd.st_dev;
st->st_ino = ms->freebsd.st_ino;
st->st_nlink = ms->freebsd.st_nlink;
st->st_mode = ms->freebsd.st_mode;
st->st_uid = ms->freebsd.st_uid;
st->st_gid = ms->freebsd.st_gid;
st->st_flags = ms->freebsd.st_flags;
st->st_rdev = ms->freebsd.st_rdev;
st->st_size = ms->freebsd.st_size;
st->st_blksize = ms->freebsd.st_blksize;
st->st_blocks = ms->freebsd.st_blocks;
st->st_gen = ms->freebsd.st_gen;
st->st_atim = ms->freebsd.st_atim;
st->st_mtim = ms->freebsd.st_mtim;
st->st_ctim = ms->freebsd.st_ctim;
st->st_birthtim = ms->freebsd.st_birthtim;
} else if (IsOpenbsd()) {
st->st_dev = ms->openbsd.st_dev;
st->st_ino = ms->openbsd.st_ino;
st->st_nlink = ms->openbsd.st_nlink;
st->st_mode = ms->openbsd.st_mode;
st->st_uid = ms->openbsd.st_uid;
st->st_gid = ms->openbsd.st_gid;
st->st_flags = ms->openbsd.st_flags;
st->st_rdev = ms->openbsd.st_rdev;
st->st_size = ms->openbsd.st_size;
st->st_blksize = ms->openbsd.st_blksize;
st->st_blocks = ms->openbsd.st_blocks;
st->st_gen = ms->openbsd.st_gen;
st->st_atim = ms->openbsd.st_atim;
st->st_mtim = ms->openbsd.st_mtim;
st->st_ctim = ms->openbsd.st_ctim;
st->st_birthtim = ms->openbsd.st_ctim;
} else if (IsNetbsd()) {
st->st_dev = ms->netbsd.st_dev;
st->st_ino = ms->netbsd.st_ino;
st->st_nlink = ms->netbsd.st_nlink;
st->st_mode = ms->netbsd.st_mode;
st->st_uid = ms->netbsd.st_uid;
st->st_gid = ms->netbsd.st_gid;
st->st_flags = ms->netbsd.st_flags;
st->st_rdev = ms->netbsd.st_rdev;
st->st_size = ms->netbsd.st_size;
st->st_blksize = ms->netbsd.st_blksize;
st->st_blocks = ms->netbsd.st_blocks;
st->st_gen = ms->netbsd.st_gen;
st->st_atim = ms->netbsd.st_atim;
st->st_mtim = ms->netbsd.st_mtim;
st->st_ctim = ms->netbsd.st_ctim;
st->st_birthtim = ms->netbsd.st_birthtim;
}
}
}

View file

@ -1,95 +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/calls/struct/metastat.internal.h"
#include "libc/dce.h"
#ifndef SWITCHEROO
#define SWITCHEROO(S1, S2, A, B, C, D, E, F, G, H, I, J, K, L, M) \
do { \
autotype((S2).A) a = (typeof((S2).A))(S1).A; \
autotype((S2).B) b = (typeof((S2).B))(S1).B; \
autotype((S2).C) c = (typeof((S2).C))(S1).C; \
autotype((S2).D) d = (typeof((S2).D))(S1).D; \
autotype((S2).E) e = (typeof((S2).E))(S1).E; \
autotype((S2).F) f = (typeof((S2).F))(S1).F; \
autotype((S2).G) g = (typeof((S2).G))(S1).G; \
autotype((S2).H) h = (typeof((S2).H))(S1).H; \
autotype((S2).I) i = (typeof((S2).I))(S1).I; \
autotype((S2).J) j = (typeof((S2).J))(S1).J; \
autotype((S2).K) k = (typeof((S2).K))(S1).K; \
autotype((S2).L) l = (typeof((S2).L))(S1).L; \
autotype((S2).M) m = (typeof((S2).M))(S1).M; \
(S2).A = a; \
(S2).B = b; \
(S2).C = c; \
(S2).D = d; \
(S2).E = e; \
(S2).F = f; \
(S2).G = g; \
(S2).H = h; \
(S2).I = i; \
(S2).J = j; \
(S2).K = k; \
(S2).L = l; \
(S2).M = m; \
} while (0);
#endif
static textstartup void __stat2linux_xnu(union metastat *ms) {
SWITCHEROO(ms->xnu, ms->linux, st_dev, st_ino, st_nlink, st_mode, st_uid,
st_gid, st_rdev, st_size, st_blksize, st_blocks, st_atim, st_mtim,
st_ctim);
}
static textstartup void __stat2linux_freebsd(union metastat *ms) {
SWITCHEROO(ms->freebsd, ms->linux, st_dev, st_ino, st_nlink, st_mode, st_uid,
st_gid, st_rdev, st_size, st_blksize, st_blocks, st_atim, st_mtim,
st_ctim);
}
static textstartup void __stat2linux_openbsd(union metastat *ms) {
SWITCHEROO(ms->openbsd, ms->linux, st_dev, st_ino, st_nlink, st_mode, st_uid,
st_gid, st_rdev, st_size, st_blksize, st_blocks, st_atim, st_mtim,
st_ctim);
}
static textstartup void __stat2linux_netbsd(union metastat *ms) {
SWITCHEROO(ms->netbsd, ms->linux, st_dev, st_ino, st_nlink, st_mode, st_uid,
st_gid, st_rdev, st_size, st_blksize, st_blocks, st_atim, st_mtim,
st_ctim);
}
/**
* Transcodes The Dismal Data Structure from BSDLinux ABI.
* @asyncsignalsafe
*/
textstartup void __stat2linux(void *ms) {
if (ms) {
if (IsXnu()) {
__stat2linux_xnu((union metastat *)ms);
} else if (IsFreebsd()) {
__stat2linux_freebsd((union metastat *)ms);
} else if (IsOpenbsd()) {
__stat2linux_openbsd((union metastat *)ms);
} else if (IsNetbsd()) {
__stat2linux_netbsd((union metastat *)ms);
}
}
}

View file

@ -1,7 +1,7 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_METASTAT_H_
#define COSMOPOLITAN_LIBC_CALLS_STRUCT_METASTAT_H_
#ifndef __STRICT_ANSI__
#include "libc/calls/struct/stat.h"
#include "libc/calls/struct/timespec.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
@ -13,6 +13,24 @@ COSMOPOLITAN_C_START_
: IsNetbsd() ? x.netbsd.field \
: 0)
struct stat_linux {
uint64_t st_dev;
uint64_t st_ino;
uint64_t st_nlink;
uint32_t st_mode;
uint32_t st_uid;
uint32_t st_gid;
uint32_t __pad0;
uint64_t st_rdev;
int64_t st_size;
int64_t st_blksize;
int64_t st_blocks;
struct timespec st_atim;
struct timespec st_mtim;
struct timespec st_ctim;
int64_t __unused[3];
};
struct stat_xnu {
int32_t st_dev;
uint16_t st_mode, st_nlink;
@ -52,7 +70,7 @@ struct stat_openbsd {
int64_t st_size, st_blocks;
int32_t st_blksize;
uint32_t st_flags, st_gen;
struct timespec __st_birthtim;
struct timespec st_birthtim;
};
struct stat_netbsd {
@ -68,7 +86,8 @@ struct stat_netbsd {
};
union metastat {
struct stat linux;
struct stat cosmo;
struct stat_linux linux;
struct stat_xnu xnu;
struct stat_freebsd freebsd;
struct stat_openbsd openbsd;
@ -77,5 +96,4 @@ union metastat {
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* !ANSI */
#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_METASTAT_H_ */

View file

@ -3,25 +3,23 @@
#include "libc/calls/struct/timespec.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
struct stat { /* linux abi */
int64_t st_dev; /* 0: id of device with file */
int64_t st_ino; /* 8: inode number in disk b-tree */
int64_t st_nlink; /* 16: hard link count */
int32_t st_mode; /* 24: octal file mask thing */
int32_t st_uid; /* 28: user id of owner */
int32_t st_gid; /* group id of owning group */
int32_t __pad; /* ignore this */
int64_t st_rdev; /* id of device if a special file */
int64_t st_size; /* bytes in file */
int64_t st_blksize; /* preferred chunking for underlying filesystem */
int64_t st_blocks; /* number of 512-byte pages allocated to file */
struct timespec st_atim; /* access time (consider noatime) */
struct timespec st_mtim; /* modified time */
struct timespec st_ctim; /* complicated time */
int64_t __future[3 + 10]; /* reserved for future use */
#define st_atime st_atim.tv_sec
#define st_mtime st_mtim.tv_sec
#define st_ctime st_ctim.tv_sec
struct stat { /* cosmo abi */
uint64_t st_dev; /* 0: id of device with file */
uint64_t st_ino; /* 8: inode number in disk b-tree */
uint64_t st_nlink; /* 16: hard link count */
uint32_t st_mode; /* 24: octal file mask thing */
uint32_t st_uid; /* 28: user id of owner */
uint32_t st_gid; /* group id of owning group */
uint32_t st_flags; /* flags (bsd-only) */
uint64_t st_rdev; /* id of device if a special file */
int64_t st_size; /* bytes in file */
int64_t st_blksize; /* preferred chunking for underlying filesystem */
int64_t st_blocks; /* number of 512-byte pages allocated to file */
struct timespec st_atim; /* access time */
struct timespec st_mtim; /* modified time */
struct timespec st_ctim; /* complicated time */
struct timespec st_birthtim;
uint64_t st_gen;
};
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -0,0 +1,24 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_STAT_MACROS_H_
#define COSMOPOLITAN_LIBC_CALLS_STRUCT_STAT_MACROS_H_
#define STAT_HAVE_NSEC 1
#define st_atime st_atim.tv_sec
#define st_mtime st_mtim.tv_sec
#define st_ctime st_ctim.tv_sec
#define st_atime_nsec st_atim.tv_nsec
#define st_mtime_nsec st_mtim.tv_nsec
#define st_ctime_nsec st_ctim.tv_nsec
#define st_atimensec st_atim.tv_nsec
#define st_mtimensec st_mtim.tv_nsec
#define st_ctimensec st_ctim.tv_nsec
#define st_birthtime st_birthtim.tv_sec
#define st_birthtimensec st_birthtim.tv_nsec
#define st_file_attributes st_flags
#define INIT_STRUCT_STAT_PADDING(st) (void)st
#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_STAT_MACROS_H_ */

View file

@ -8,11 +8,13 @@ struct termios { /* GNU/Systemd ABI */
uint32_t c_oflag; /* output modes */
uint32_t c_cflag; /* control modes */
uint32_t c_lflag; /* local modes */
uint8_t c_cc[32]; /* code mappings */
uint8_t c_cc[20]; /* code mappings */
uint32_t c_ispeed; /* input speed */
uint32_t c_ospeed; /* output speed */
};
#define c_line c_cc[0] /* line discipline */
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_TERMIOS_H_ */

View file

@ -1,30 +1,30 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_TERMIOS_INTERNAL_H_
#define COSMOPOLITAN_LIBC_CALLS_TERMIOS_INTERNAL_H_
#ifndef __STRICT_ANSI__
#include "libc/bits/safemacros.internal.h"
#include "libc/calls/struct/metatermios.internal.h"
#include "libc/calls/struct/termios.h"
#include "libc/str/str.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
#define COPY_TERMIOS(TO, FROM) \
do { \
memset((TO), 0, sizeof(*(TO))); \
(TO)->c_iflag = (FROM)->c_iflag; \
(TO)->c_oflag = (FROM)->c_oflag; \
(TO)->c_cflag = (FROM)->c_cflag; \
(TO)->c_lflag = (FROM)->c_lflag; \
memcpy((TO)->c_cc, (FROM)->c_cc, \
min(sizeof((TO)->c_cc), sizeof((FROM)->c_cc))); \
(TO)->c_ispeed = (FROM)->c_ispeed; \
(TO)->c_ospeed = (FROM)->c_ospeed; \
#define COPY_TERMIOS(TO, FROM) \
do { \
uint32_t Cc3; \
uint64_t Cc1, Cc2; \
autotype((TO)->c_iflag) c_iflag = (FROM)->c_iflag; \
autotype((TO)->c_oflag) c_oflag = (FROM)->c_oflag; \
autotype((TO)->c_cflag) c_cflag = (FROM)->c_cflag; \
autotype((TO)->c_lflag) c_lflag = (FROM)->c_lflag; \
__builtin_memcpy(&Cc1, (FROM)->c_cc + 000, 8); \
__builtin_memcpy(&Cc2, (FROM)->c_cc + 010, 8); \
__builtin_memcpy(&Cc3, (FROM)->c_cc + 020, 4); \
autotype((TO)->c_ispeed) c_ispeed = (FROM)->c_ispeed; \
autotype((TO)->c_ospeed) c_ospeed = (FROM)->c_ospeed; \
(TO)->c_iflag = c_iflag; \
(TO)->c_oflag = c_oflag; \
(TO)->c_cflag = c_cflag; \
(TO)->c_lflag = c_lflag; \
__builtin_memcpy((TO)->c_cc + 000, &Cc1, 8); \
__builtin_memcpy((TO)->c_cc + 010, &Cc2, 8); \
__builtin_memcpy((TO)->c_cc + 020, &Cc3, 4); \
(TO)->c_ispeed = c_ispeed; \
(TO)->c_ospeed = c_ospeed; \
} while (0)
void *__termios2host(union metatermios *, const struct termios *) hidden;
void __termios2linux(struct termios *, const union metatermios *) hidden;
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* !ANSI */
#endif /* COSMOPOLITAN_LIBC_CALLS_TERMIOS_INTERNAL_H_ */

View file

@ -1,35 +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/ioctl.h"
#include "libc/calls/struct/metatermios.internal.h"
#include "libc/calls/termios.h"
#include "libc/calls/termios.internal.h"
#include "libc/dce.h"
void *__termios2host(union metatermios *t, const struct termios *lt) {
if (!IsXnu() && !IsFreebsd() && !IsOpenbsd() && !IsNetbsd()) {
return lt;
} else if (IsXnu()) {
COPY_TERMIOS(&t->xnu, lt);
return &t->xnu;
} else {
COPY_TERMIOS(&t->bsd, lt);
return &t->bsd;
}
}

View file

@ -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/ioctl.h"
#include "libc/calls/struct/metatermios.internal.h"
#include "libc/calls/termios.h"
#include "libc/calls/termios.internal.h"
#include "libc/dce.h"
void __termios2linux(struct termios *lt, const union metatermios *t) {
if (IsXnu()) {
COPY_TERMIOS(lt, &t->xnu);
} else if (IsFreebsd() || IsOpenbsd() || IsNetbsd()) {
COPY_TERMIOS(lt, &t->bsd);
} else {
memcpy(lt, &t->linux, sizeof(*lt));
}
}