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

@ -12,6 +12,7 @@
#include "libc/errno.h"
#include "libc/fmt/fmt.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/runtime/gc.h"
#include "libc/stdio/stdio.h"
#include "libc/x/x.h"
@ -35,18 +36,22 @@ void PrintFileMetadata(const char *pathname, struct stat *st) {
"%-32s%d\n"
"%-32s%d\n"
"%-32s%d\n"
"%-32s%d\n"
"%-32s%ld\n"
"%-32s%ld\n"
"%-32s%s\n"
"%-32s%s\n"
"%-32s%s\n"
"%-32s%s\n",
"bytes in file", st->st_size, "physical bytes", st->st_blocks * 512,
"device id w/ file", st->st_dev, "inode", st->st_ino,
"hard link count", st->st_nlink, "mode / permissions", st->st_mode,
"owner id", st->st_uid, "group id", st->st_gid,
"device id (if special)", st->st_rdev, "block size", st->st_blksize,
"access time", _gc(xiso8601(&st->st_atim)), "modified time",
_gc(xiso8601(&st->st_mtim)), "c[omplicated]time",
_gc(xiso8601(&st->st_ctim)));
"owner id", st->st_uid, "group id", st->st_gid, "flags", st->st_flags,
"gen", st->st_gen, "device id (if special)", st->st_rdev, "block size",
st->st_blksize, "access time", _gc(xiso8601(&st->st_atim)),
"modified time", _gc(xiso8601(&st->st_mtim)), "c[omplicated]time",
_gc(xiso8601(&st->st_ctim)), "birthtime",
_gc(xiso8601(&st->st_birthtim)));
}
int main(int argc, char *argv[]) {

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));
}
}

View file

@ -1,7 +0,0 @@
#ifndef COSMOPOLITAN_LIBC_ISYSTEM_STAT_H_
#define COSMOPOLITAN_LIBC_ISYSTEM_STAT_H_
#include "libc/calls/calls.h"
#include "libc/calls/struct/stat.h"
#include "libc/calls/weirdtypes.h"
#include "libc/sysv/consts/s.h"
#endif /* COSMOPOLITAN_LIBC_ISYSTEM_STAT_H_ */

View file

@ -1,5 +1,10 @@
#ifndef LIBC_ISYSTEM_SYS_STAT_H_
#define LIBC_ISYSTEM_SYS_STAT_H_
#include "libc/calls/calls.h"
#include "libc/calls/struct/stat.h"
#include "libc/calls/struct/stat.macros.h"
#include "libc/calls/weirdtypes.h"
#include "libc/sysv/consts/s.h"
#include "libc/sysv/consts/utime.h"
#include "libc/time/time.h"
#endif

View file

@ -1516,24 +1516,24 @@ syscon termios CS6 0b0000000000010000 0b0000000100000000 0b0000000100000000
syscon termios CS7 0b0000000000100000 0b0000001000000000 0b0000001000000000 0b0000001000000000 0b0000001000000000 0b0000000000100000 # termios.c_cflag flag for 7-bit characters
syscon termios CS8 0b0000000000110000 0b0000001100000000 0b0000001100000000 0b0000001100000000 0b0000001100000000 0b0000000000110000 # termios.c_cflag flag for 8-bit characters
syscon termios CSIZE 0b0000000000110000 0b0000001100000000 0b0000001100000000 0b0000001100000000 0b0000001100000000 0b0000000000110000 # mask for CS𝑥 flags
syscon termios NCCS 32 32 32 32 20 32 # ARRAYLEN(termios.c_cc); faked xnu/freebsd/openbsd (originally 20) and faked nt
syscon termios VINTR 0 8 8 8 8 0 # termios.c_cc[VINTR]=𝑥
syscon termios VQUIT 1 9 9 9 9 1 # termios.c_cc[VQUIT]=𝑥
syscon termios VERASE 2 3 3 3 3 2 # termios.c_cc[VERASE]=𝑥
syscon termios VKILL 3 5 5 5 5 3 # termios.c_cc[VKILL]=𝑥
syscon termios VEOF 4 0 0 0 0 4 # termios.c_cc[VEOF]=𝑥
syscon termios VTIME 5 17 17 17 17 5 # termios.c_cc[VTIME]=𝑥 sets non-canonical read timeout to 𝑥×𝟷𝟶𝟶ms which is needed when entering escape sequences manually with the escape key
syscon termios VMIN 6 16 16 16 16 6 # termios.c_cc[VMIN]=𝑥 in non-canonical mode can be set to 0 for non-blocking reads, 1 for single character raw mode reads, or higher to buffer
syscon termios VSWTC 7 0 0 0 0 7 # termios.c_cc[VSWTC]=𝑥
syscon termios VSTART 8 12 12 12 12 8 # termios.c_cc[VSTART]=𝑥
syscon termios VSTOP 9 13 13 13 13 9 # termios.c_cc[VSTOP]=𝑥
syscon termios VSUSP 10 10 10 10 10 10 # termios.c_cc[VSUSP]=𝑥 defines suspend, i.e. Ctrl-Z (a.k.a. →, ^Z, SUB, 26, 032, 0x1A, ord('Z')^0b01000000); unix consensus
syscon termios VEOL 11 1 1 1 1 11 # termios.c_cc[VEOL]=𝑥
syscon termios VEOL2 16 2 2 2 2 16 # termios.c_cc[VEOL2]=𝑥
syscon termios VREPRINT 12 6 6 6 6 12 # termios.c_cc[VREPRINT]=𝑥
syscon termios VDISCARD 13 15 15 15 15 13 # termios.c_cc[VDISCARD]=𝑥
syscon termios VWERASE 14 4 4 4 4 14 # termios.c_cc[VWERASE]=𝑥
syscon termios VLNEXT 15 14 14 14 14 15 # termios.c_cc[VLNEXT]=𝑥
syscon termios NCCS 20 20 20 20 20 20 # ARRAYLEN(termios.c_cc); we schlep c_line into c_cc on linux
syscon termios VINTR 0+1 8 8 8 8 0 # termios.c_cc[VINTR]=𝑥
syscon termios VQUIT 1+1 9 9 9 9 1 # termios.c_cc[VQUIT]=𝑥
syscon termios VERASE 2+1 3 3 3 3 2 # termios.c_cc[VERASE]=𝑥
syscon termios VKILL 3+1 5 5 5 5 3 # termios.c_cc[VKILL]=𝑥
syscon termios VEOF 4+1 0 0 0 0 4 # termios.c_cc[VEOF]=𝑥
syscon termios VTIME 5+1 17 17 17 17 5 # termios.c_cc[VTIME]=𝑥 sets non-canonical read timeout to 𝑥×𝟷𝟶𝟶ms which is needed when entering escape sequences manually with the escape key
syscon termios VMIN 6+1 16 16 16 16 6 # termios.c_cc[VMIN]=𝑥 in non-canonical mode can be set to 0 for non-blocking reads, 1 for single character raw mode reads, or higher to buffer
syscon termios VSWTC 7+1 0 0 0 0 7 # termios.c_cc[VSWTC]=𝑥
syscon termios VSTART 8+1 12 12 12 12 8 # termios.c_cc[VSTART]=𝑥
syscon termios VSTOP 9+1 13 13 13 13 9 # termios.c_cc[VSTOP]=𝑥
syscon termios VSUSP 10+1 10 10 10 10 10 # termios.c_cc[VSUSP]=𝑥 defines suspend, i.e. Ctrl-Z (a.k.a. →, ^Z, SUB, 26, 032, 0x1A, ord('Z')^0b01000000); unix consensus
syscon termios VEOL 11+1 1 1 1 1 11 # termios.c_cc[VEOL]=𝑥
syscon termios VREPRINT 12+1 6 6 6 6 12 # termios.c_cc[VREPRINT]=𝑥
syscon termios VDISCARD 13+1 15 15 15 15 13 # termios.c_cc[VDISCARD]=𝑥
syscon termios VWERASE 14+1 4 4 4 4 14 # termios.c_cc[VWERASE]=𝑥
syscon termios VLNEXT 15+1 14 14 14 14 15 # termios.c_cc[VLNEXT]=𝑥
syscon termios VEOL2 16+1 2 2 2 2 16 # termios.c_cc[VEOL2]=𝑥
syscon termios TIOCSERGETLSR 0x5459 0 0 0 0 0 #
syscon termios TIOCSERGETMULTI 0x545a 0 0 0 0 0 #
syscon termios TIOCSERSETMULTI 0x545b 0 0 0 0 0 #

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,NCCS,32,32,32,32,20,32
.syscon termios,NCCS,20,20,20,20,20,20

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,VDISCARD,13,15,15,15,15,13
.syscon termios,VDISCARD,13+1,15,15,15,15,13

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,VEOF,4,0,0,0,0,4
.syscon termios,VEOF,4+1,0,0,0,0,4

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,VEOL,11,1,1,1,1,11
.syscon termios,VEOL,11+1,1,1,1,1,11

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,VEOL2,16,2,2,2,2,16
.syscon termios,VEOL2,16+1,2,2,2,2,16

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,VERASE,2,3,3,3,3,2
.syscon termios,VERASE,2+1,3,3,3,3,2

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,VINTR,0,8,8,8,8,0
.syscon termios,VINTR,0+1,8,8,8,8,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,VKILL,3,5,5,5,5,3
.syscon termios,VKILL,3+1,5,5,5,5,3

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,VLNEXT,15,14,14,14,14,15
.syscon termios,VLNEXT,15+1,14,14,14,14,15

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,VMIN,6,16,16,16,16,6
.syscon termios,VMIN,6+1,16,16,16,16,6

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,VQUIT,1,9,9,9,9,1
.syscon termios,VQUIT,1+1,9,9,9,9,1

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,VREPRINT,12,6,6,6,6,12
.syscon termios,VREPRINT,12+1,6,6,6,6,12

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,VSTART,8,12,12,12,12,8
.syscon termios,VSTART,8+1,12,12,12,12,8

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,VSTOP,9,13,13,13,13,9
.syscon termios,VSTOP,9+1,13,13,13,13,9

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,VSUSP,10,10,10,10,10,10
.syscon termios,VSUSP,10+1,10,10,10,10,10

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,VSWTC,7,0,0,0,0,7
.syscon termios,VSWTC,7+1,0,0,0,0,7

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,VTIME,5,17,17,17,17,5
.syscon termios,VTIME,5+1,17,17,17,17,5

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon termios,VWERASE,14,4,4,4,4,14
.syscon termios,VWERASE,14+1,4,4,4,4,14

View file

@ -59,7 +59,6 @@ extern const long IUTF8;
extern const long IXANY;
extern const long IXOFF;
extern const long IXON;
extern const long NCCS;
extern const long NETGRAPHDISC;
extern const long NL1;
extern const long NL2;
@ -257,7 +256,7 @@ COSMOPOLITAN_C_END_
#define IUTF8 SYMBOLIC(IUTF8)
#define IXOFF SYMBOLIC(IXOFF)
#define IXON SYMBOLIC(IXON)
#define NCCS LITERALLY(32)
#define NCCS LITERALLY(20)
#define NETGRAPHDISC SYMBOLIC(NETGRAPHDISC)
#define NMEADISC SYMBOLIC(NMEADISC)
#define NOFLSH SYMBOLIC(NOFLSH)

View file

@ -39,6 +39,7 @@ int __zipos_stat_impl(struct Zipos *zipos, size_t cf, struct stat *st) {
roundup(GetZipLfileCompressedSize(zipos->map + lf), 512) / 512;
GetZipCfileTimestamps(zipos->map + cf, &st->st_mtim, &st->st_atim,
&st->st_ctim, 0);
st->st_birthtim = st->st_ctim;
return 0;
} else {
return einval();

View file

@ -890,7 +890,7 @@ static Token *timestamp_macro(Token *tmpl) {
if (stat(tmpl->file->name, &st) != 0)
return new_str_token("??? ??? ?? ??:??:?? ????", tmpl);
char buf[64];
ctime_r(&st.st_mtime, buf);
ctime_r(&st.st_mtim.tv_sec, buf);
buf[24] = '\0';
return new_str_token(buf, tmpl);
}

View file

@ -280,7 +280,7 @@ UTIL_STATIC int UTIL_setFileStat(const char *filename, struct stat *statbuf)
return -1;
timebuf.actime = time(NULL);
timebuf.modtime = statbuf->st_mtime;
timebuf.modtime = statbuf->st_mtim.tv_sec;
res += utime(filename, &timebuf); /* set access and modification times */
#if !defined(_WIN32)

View file

@ -333,6 +333,8 @@ PyMODINIT_FUNC PyInit__sqlite3(void)
PyObject *tmp_obj;
int i;
sqlite3_initialize();
module = PyModule_Create(&_sqlite3module);
if (!module ||

View file

@ -11,6 +11,7 @@
#include "libc/calls/internal.h"
#include "libc/calls/makedev.h"
#include "libc/calls/struct/dirent.h"
#include "libc/calls/struct/stat.macros.h"
#include "libc/calls/struct/winsize.h"
#include "libc/calls/termios.h"
#include "libc/calls/weirdtypes.h"

View file

@ -805,7 +805,7 @@
#define HAVE_STRUCT_PASSWD_PW_PASSWD 1
/* Define to 1 if `st_birthtime' is a member of `struct stat'. */
/* #undef HAVE_STRUCT_STAT_ST_BIRTHTIME */
#define HAVE_STRUCT_STAT_ST_BIRTHTIME 1
/* Define to 1 if `st_blksize' is a member of `struct stat'. */
#define HAVE_STRUCT_STAT_ST_BLKSIZE 1
@ -814,14 +814,16 @@
#define HAVE_STRUCT_STAT_ST_BLOCKS 1
/* Define to 1 if `st_flags' is a member of `struct stat'. */
/* #undef HAVE_STRUCT_STAT_ST_FLAGS */
#define HAVE_STRUCT_STAT_ST_FLAGS 1
/* Define to 1 if `st_gen' is a member of `struct stat'. */
/* #undef HAVE_STRUCT_STAT_ST_GEN */
#define HAVE_STRUCT_STAT_ST_GEN 1
/* Define to 1 if `st_rdev' is a member of `struct stat'. */
#define HAVE_STRUCT_STAT_ST_RDEV 1
#define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1
/* Define to 1 if `tm_zone' is a member of `struct tm'. */
#define HAVE_STRUCT_TM_TM_ZONE 1