mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-07 19:58:30 +00:00
Make more improvements
This change includes many bug fixes, for the NT polyfills, strings, memory, boot, and math libraries which were discovered by adding more tools for recreational programming, such as PC emulation. Lemon has also been vendored because it works so well at parsing languages.
This commit is contained in:
parent
416fd86676
commit
23d333c090
201 changed files with 14558 additions and 3082 deletions
|
@ -84,7 +84,6 @@ char *get_current_dir_name(void) nodiscard;
|
|||
char *getcwd(char *, size_t);
|
||||
char *realpath(const char *, char *);
|
||||
char *replaceuser(const char *) nodiscard;
|
||||
char *slurp(const char *, size_t *) nodiscard;
|
||||
char *ttyname(int);
|
||||
char *commandv(const char *, char[hasatleast PATH_MAX]);
|
||||
int access(const char *, int) nothrow;
|
||||
|
|
34
libc/calls/clock.c
Normal file
34
libc/calls/clock.c
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
/**
|
||||
* Returns how much CPU program has consumed on time-sharing system.
|
||||
*
|
||||
* @return value that can be divided by CLOCKS_PER_SEC, or -1 w/ errno
|
||||
*/
|
||||
int64_t clock(void) {
|
||||
struct timespec ts;
|
||||
if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts) == -1) return -1;
|
||||
return ts.tv_sec * CLOCKS_PER_SEC +
|
||||
ts.tv_nsec / (1000000000 / CLOCKS_PER_SEC);
|
||||
}
|
83
libc/calls/clock_gettime.c
Normal file
83
libc/calls/clock_gettime.c
Normal file
|
@ -0,0 +1,83 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/conv/conv.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/mach.h"
|
||||
#include "libc/nt/struct/filetime.h"
|
||||
#include "libc/nt/struct/systemtime.h"
|
||||
#include "libc/nt/synchronization.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
/**
|
||||
* Returns nanosecond time.
|
||||
*
|
||||
* This is a high-precision timer that supports multiple definitions of
|
||||
* time. Among the more popular is CLOCK_MONOTONIC. This function has a
|
||||
* zero syscall implementation of that on modern x86.
|
||||
*
|
||||
* @param clockid can be CLOCK_REALTIME, CLOCK_MONOTONIC, etc. noting
|
||||
* that on Linux CLOCK_MONOTONIC is redefined to use the monotonic
|
||||
* clock that's actually monotonic lool
|
||||
* @param out_ts is where the nanoseconds are stored if non-NULL
|
||||
* @return 0 on success or -1 w/ errno on error
|
||||
* @error ENOSYS if clockid isn't available; in which case this function
|
||||
* guarantees an ordinary timestamp is still stored to out_ts; and
|
||||
* errno isn't restored to its original value, to detect prec. loss
|
||||
* @see strftime(), gettimeofday()
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
int clock_gettime(int clockid, struct timespec *out_ts) {
|
||||
/* TODO(jart): Just ignore O/S for MONOTONIC and measure RDTSC on start */
|
||||
if (!IsWindows()) {
|
||||
if (!IsXnu()) {
|
||||
if (out_ts) {
|
||||
out_ts->tv_sec = 0;
|
||||
out_ts->tv_nsec = 0;
|
||||
}
|
||||
return clock_gettime$sysv(clockid, out_ts);
|
||||
} else {
|
||||
int rc;
|
||||
static_assert(sizeof(struct timeval) == sizeof(struct timespec));
|
||||
if (out_ts) {
|
||||
out_ts->tv_sec = 0;
|
||||
out_ts->tv_nsec = 0;
|
||||
}
|
||||
rc = gettimeofday$sysv((struct timeval *)out_ts, NULL);
|
||||
if (out_ts) {
|
||||
out_ts->tv_nsec *= 1000;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
} else {
|
||||
struct NtFileTime ft;
|
||||
GetSystemTimeAsFileTime(&ft);
|
||||
*out_ts = filetimetotimespec(ft);
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
textwindows int close$nt(int fd) {
|
||||
bool32 ok;
|
||||
if (isfdindex(fd)) {
|
||||
if (isfdopen(fd)) {
|
||||
if (g_fds.p[fd].kind == kFdFile) {
|
||||
/*
|
||||
* Like Linux, closing a file on Windows doesn't guarantee it's
|
||||
|
|
37
libc/calls/dtime.c
Normal file
37
libc/calls/dtime.c
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
/**
|
||||
* Returns seconds since epoch w/ high-precision.
|
||||
* @param clockid can be CLOCK_{REALTIME,MONOTONIC}, etc.
|
||||
*/
|
||||
long double dtime(int clockid) {
|
||||
long double secs;
|
||||
struct timespec tv;
|
||||
clock_gettime(clockid, &tv);
|
||||
secs = tv.tv_nsec;
|
||||
secs *= 1 / 1e9;
|
||||
secs += tv.tv_sec;
|
||||
return secs;
|
||||
}
|
|
@ -34,13 +34,13 @@ textwindows int dup$nt(int oldfd, int newfd, int flags) {
|
|||
if (newfd == -1) {
|
||||
if ((newfd = createfd()) == -1) return -1;
|
||||
} else if (isfdindex(newfd)) {
|
||||
close(newfd);
|
||||
} else if (isfdlegal(newfd)) {
|
||||
if (g_fds.p[newfd].kind != kFdEmpty) {
|
||||
close(newfd);
|
||||
}
|
||||
} else {
|
||||
do {
|
||||
if (growfds() == -1) return -1;
|
||||
} while (newfd >= g_fds.n);
|
||||
} else {
|
||||
return ebadf();
|
||||
}
|
||||
if (DuplicateHandle(GetCurrentProcess(), g_fds.p[oldfd].handle,
|
||||
GetCurrentProcess(), &g_fds.p[newfd].handle, 0,
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows int fcntl$nt(int fd, int cmd, unsigned arg) {
|
||||
if (!isfdindex(fd)) return ebadf();
|
||||
if (!isfdkind(fd, kFdFile)) return ebadf();
|
||||
switch (cmd) {
|
||||
case F_GETFD:
|
||||
return GetHandleInformation(g_fds.p[fd].handle, &arg) ? (arg ^ FD_CLOEXEC)
|
||||
|
|
|
@ -33,7 +33,10 @@ uint32_t fprot2nt(int prot, int flags) {
|
|||
return (HAS(prot, PROT_READ) ? kNtFileMapRead : 0) |
|
||||
(HAS(prot, PROT_WRITE) ? kNtFileMapWrite : 0) |
|
||||
(HAS(prot, PROT_EXEC) ? kNtFileMapExecute : 0) |
|
||||
(HAS(flags, MAP_PRIVATE) ? kNtFileMapCopy : 0) |
|
||||
(HAS(flags, kNtSecLargePages) ? kNtFileMapLargePages : 0) |
|
||||
(HAS(flags, kNtSecReserve) ? kNtFileMapReserve : 0);
|
||||
(HAS(flags, kNtSecReserve) ? kNtFileMapReserve : 0) |
|
||||
((HAS(flags, MAP_PRIVATE) && HAS(prot, PROT_READ) &&
|
||||
HAS(prot, PROT_WRITE))
|
||||
? kNtFileMapCopy
|
||||
: 0);
|
||||
}
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
* @see libc/sysv/consts.sh
|
||||
*/
|
||||
int getrlimit(int resource, struct rlimit *rlim) {
|
||||
/* TODO(jart): Windows */
|
||||
if (resource == -1) return einval();
|
||||
return getrlimit$sysv(resource, rlim);
|
||||
}
|
||||
|
|
35
libc/calls/gettimeofday-nt.c
Normal file
35
libc/calls/gettimeofday-nt.c
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/conv/conv.h"
|
||||
#include "libc/nt/struct/filetime.h"
|
||||
#include "libc/nt/struct/systemtime.h"
|
||||
#include "libc/nt/synchronization.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/time/struct/timezone.h"
|
||||
|
||||
int gettimeofday$nt(struct timeval *tv, struct timezone *tz) {
|
||||
struct NtFileTime ft;
|
||||
GetSystemTimeAsFileTime(&ft);
|
||||
filetimetotimeval(tv, ft);
|
||||
if (tz) memset(tz, 0, sizeof(*tz));
|
||||
return 0;
|
||||
}
|
54
libc/calls/gettimeofday-sysv.S
Normal file
54
libc/calls/gettimeofday-sysv.S
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/macros.h"
|
||||
|
||||
/ Returns system wall time in microseconds.
|
||||
/
|
||||
/ @param rdi points to timeval that receives result
|
||||
/ @param rsi receives UTC timezone if non-NULL
|
||||
/ @return always zero
|
||||
/ @see clock_gettime() for nanosecond precision
|
||||
/ @see strftime() for string formatting
|
||||
gettimeofday$sysv:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
test %rsi,%rsi
|
||||
jz 1f
|
||||
push $0
|
||||
pop (%rsi)
|
||||
1: xor %esi,%esi # no one zones this way.
|
||||
xor %edx,%edx # i64*mach_absolute_time
|
||||
call __gettimeofday$sysv
|
||||
#if SupportsXnu()
|
||||
testb IsXnu() # XNU might do %rax:%rdx
|
||||
jz 1f
|
||||
test %rdi,%rdi
|
||||
jz 1f
|
||||
test %rax,%rax
|
||||
jz 1f
|
||||
mov %rax,(%rdi)
|
||||
mov %rdx,8(%rdi)
|
||||
#endif
|
||||
1: xor %eax,%eax # nevar fail
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn gettimeofday$sysv,globl,hidden
|
41
libc/calls/gettimeofday.c
Normal file
41
libc/calls/gettimeofday.c
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/time/struct/timezone.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
/**
|
||||
* Returns system wall time in microseconds.
|
||||
*
|
||||
* @param tv points to timeval that receives result if non-NULL
|
||||
* @param tz receives UTC timezone if non-NULL
|
||||
* @return always zero
|
||||
* @see clock_gettime() for nanosecond precision
|
||||
* @see strftime() for string formatting
|
||||
*/
|
||||
int gettimeofday(struct timeval *tv, struct timezone *tz) {
|
||||
if (!IsWindows()) {
|
||||
return gettimeofday$sysv(tv, tz);
|
||||
} else {
|
||||
return gettimeofday$nt(tv, tz);
|
||||
}
|
||||
}
|
|
@ -28,7 +28,7 @@ int growfds(void) {
|
|||
struct Fd *p;
|
||||
if (weaken(realloc)) {
|
||||
if ((p = weaken(realloc)(g_fds.p != g_fds.__init_p ? g_fds.p : NULL,
|
||||
(n = ((i = g_fds.n) * 2)) * sizeof(*p)))) {
|
||||
(n = (i = g_fds.n) << 1) * sizeof(*p)))) {
|
||||
do {
|
||||
p[i++].kind = kFdEmpty;
|
||||
} while (i < n);
|
||||
|
|
|
@ -46,8 +46,7 @@ LIBC_CALLS_HEFTY_A_DIRECTDEPS = \
|
|||
LIBC_STR \
|
||||
LIBC_STUBS \
|
||||
LIBC_SYSV \
|
||||
LIBC_SYSV_CALLS \
|
||||
LIBC_TIME
|
||||
LIBC_SYSV_CALLS
|
||||
|
||||
LIBC_CALLS_HEFTY_A_DEPS := \
|
||||
$(call uniq,$(foreach x,$(LIBC_CALLS_HEFTY_A_DIRECTDEPS),$($(x))))
|
||||
|
|
|
@ -1,22 +1,3 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#ifndef COSMOPOLITAN_LIBC_CALLS_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_INTERNAL_H_
|
||||
#ifndef __STRICT_ANSI__
|
||||
|
@ -54,15 +35,8 @@ struct IoctlPtmGet {
|
|||
char workername[16];
|
||||
};
|
||||
|
||||
/**
|
||||
* List of open handles on Windows NT.
|
||||
*
|
||||
* The array is indexed by the sysv-style file descriptor numbers that
|
||||
* we assign. It's needed to make file descriptors only require 32bits
|
||||
* and helps us abstract peculiarities like close() vs. closesocket().
|
||||
*/
|
||||
struct Fds {
|
||||
size_t f; // length
|
||||
size_t f; // arbitrary free slot start search index
|
||||
size_t n; // capacity
|
||||
struct Fd {
|
||||
int64_t handle;
|
||||
|
@ -82,34 +56,27 @@ struct Fds {
|
|||
|
||||
extern const struct Fd kEmptyFd;
|
||||
|
||||
hidden extern int g_sighandrvas[NSIG];
|
||||
hidden extern struct Fds g_fds;
|
||||
hidden extern struct NtSystemInfo g_ntsysteminfo;
|
||||
hidden extern struct NtStartupInfo g_ntstartupinfo;
|
||||
hidden extern const struct NtSecurityAttributes kNtIsInheritable;
|
||||
|
||||
forceinline bool isfdlegal(int fd) {
|
||||
if (!IsTrustworthy()) {
|
||||
return (0 <= fd && fd <= INT_MAX);
|
||||
} else {
|
||||
return fd;
|
||||
}
|
||||
}
|
||||
|
||||
forceinline bool isfdindex(int fd) {
|
||||
if (!IsTrustworthy()) {
|
||||
return (0 <= fd && fd < g_fds.n);
|
||||
} else {
|
||||
return fd;
|
||||
}
|
||||
}
|
||||
extern int g_sighandrvas[NSIG] hidden;
|
||||
extern struct Fds g_fds hidden;
|
||||
extern struct NtSystemInfo g_ntsysteminfo hidden;
|
||||
extern struct NtStartupInfo g_ntstartupinfo hidden;
|
||||
extern const struct NtSecurityAttributes kNtIsInheritable hidden;
|
||||
|
||||
ssize_t createfd(void) hidden;
|
||||
int growfds(void) hidden;
|
||||
void removefd(int) hidden;
|
||||
enum FdKind fdkind(int) hidden nosideeffect;
|
||||
bool isfdopen(int) hidden nosideeffect;
|
||||
bool isfdkind(int, enum FdKind) hidden nosideeffect;
|
||||
|
||||
forceinline bool isfdindex(int fd) {
|
||||
if (!IsTrustworthy()) {
|
||||
return (0 <= fd && fd < g_fds.n);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
forceinline size_t clampio(size_t size) {
|
||||
if (!IsTrustworthy()) {
|
||||
return MIN(size, 0x7ffff000);
|
||||
|
|
|
@ -29,8 +29,8 @@ int ioctl$default(int fd, uint64_t request, void *memory) {
|
|||
int64_t handle;
|
||||
if (!IsWindows()) {
|
||||
return ioctl$sysv(fd, request, memory);
|
||||
} else if (isfdindex(fd)) {
|
||||
if (isfdkind(fd, kFdSocket)) {
|
||||
} else if (isfdopen(fd)) {
|
||||
if (g_fds.p[fd].kind == kFdSocket) {
|
||||
handle = g_fds.p[fd].handle;
|
||||
if ((rc = weaken(__ioctlsocket$nt)(handle, request, memory)) != -1) {
|
||||
return rc;
|
||||
|
|
|
@ -20,9 +20,5 @@
|
|||
#include "libc/calls/internal.h"
|
||||
|
||||
bool isfdkind(int fd, enum FdKind kind) {
|
||||
if (isfdindex(fd)) {
|
||||
return g_fds.p[fd].kind == kind;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return isfdindex(fd) && g_fds.p[fd].kind == kind;
|
||||
}
|
||||
|
|
24
libc/calls/isfdopen.c
Normal file
24
libc/calls/isfdopen.c
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
|
||||
bool isfdopen(int fd) {
|
||||
return isfdindex(fd) && g_fds.p[fd].kind != kFdEmpty;
|
||||
}
|
|
@ -39,5 +39,4 @@ kTmpPath:
|
|||
ezlea GetTempPathA$flunk,ax
|
||||
call __getntsyspath
|
||||
.init.end 300,_init_kTmpPath
|
||||
|
||||
.source __FILE__
|
||||
|
|
64
libc/calls/nanosleep.c
Normal file
64
libc/calls/nanosleep.c
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/conv/conv.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/nexgen32e/nexgen32e.h"
|
||||
#include "libc/nt/enum/status.h"
|
||||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/nt/time.h"
|
||||
#include "libc/nt/synchronization.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Sleeps for a particular amount of time.
|
||||
*/
|
||||
int nanosleep(const struct timespec *req, struct timespec *rem) {
|
||||
long res, millis, hectonanos;
|
||||
if (!req) return efault();
|
||||
if (!IsWindows()) {
|
||||
if (!IsXnu()) {
|
||||
return nanosleep$sysv(req, rem);
|
||||
} else {
|
||||
return select$sysv(
|
||||
0, 0, 0, 0, /* lool */
|
||||
&(struct timeval){req->tv_sec, div1000int64(req->tv_nsec)});
|
||||
}
|
||||
} else {
|
||||
if (rem) memcpy(rem, req, sizeof(*rem));
|
||||
if (req->tv_sec && req->tv_nsec) {
|
||||
hectonanos = MAX(1, req->tv_sec * 10000000L + div100int64(req->tv_nsec));
|
||||
} else {
|
||||
hectonanos = 1;
|
||||
}
|
||||
if (NtError(NtDelayExecution(true, &hectonanos))) {
|
||||
millis = div10000int64(hectonanos);
|
||||
res = SleepEx(millis, true);
|
||||
if (res == kNtWaitIoCompletion) return eintr();
|
||||
}
|
||||
if (rem) memset(rem, 0, sizeof(*rem));
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -17,73 +17,81 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/alg/arraylist2.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/initializer.h"
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/madv.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/nexgen32e/rdtsc.h"
|
||||
#include "libc/nexgen32e/x86feature.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
static size_t getfilesize(int fd) {
|
||||
struct stat st;
|
||||
st.st_size = 0;
|
||||
fstat(fd, &st);
|
||||
return st.st_size;
|
||||
}
|
||||
|
||||
static size_t smudgefilesize(size_t size) {
|
||||
return roundup(size, PAGESIZE) + PAGESIZE;
|
||||
}
|
||||
static struct Now {
|
||||
bool once;
|
||||
uint64_t k0;
|
||||
long double r0, cpn;
|
||||
} now_;
|
||||
|
||||
/**
|
||||
* Reads entire file into memory.
|
||||
*
|
||||
* This function is fantastic for being lazy. It may waste space if the
|
||||
* file is large, but it's implemented in a conscientious way that won't
|
||||
* bomb the systemwide page cache. It means performance too, naturally.
|
||||
*
|
||||
* @return contents which must be free()'d or NULL w/ errno
|
||||
* Returns timestamp without needing system calls.
|
||||
* @note uses microsecond scale fallback on k8 or vm
|
||||
*/
|
||||
char *slurp(const char *path, size_t *opt_out_readlength) {
|
||||
int fd;
|
||||
ssize_t rc;
|
||||
char *res, *p;
|
||||
size_t i, n, got, want;
|
||||
res = NULL;
|
||||
if ((fd = open(path, O_RDONLY)) == -1) goto Failure;
|
||||
n = getfilesize(fd);
|
||||
/* TODO(jart): Fix this, it's totally broken */
|
||||
if (!(res = valloc(smudgefilesize(n)))) goto Failure;
|
||||
if (n > FRAMESIZE) fadvise(fd, 0, n, MADV_SEQUENTIAL);
|
||||
i = 0;
|
||||
for (;;) {
|
||||
want = smudgefilesize(n - i);
|
||||
TryAgain:
|
||||
if ((rc = read(fd, &res[i], want)) == -1) {
|
||||
if (errno == EINTR) goto TryAgain;
|
||||
goto Failure;
|
||||
}
|
||||
got = (size_t)rc;
|
||||
if (i + 1 >= n) {
|
||||
if ((p = realloc(res, smudgefilesize((n += n >> 1))))) {
|
||||
res = p;
|
||||
} else {
|
||||
goto Failure;
|
||||
}
|
||||
}
|
||||
i += got;
|
||||
if (got == 0) break;
|
||||
if (got > want) abort();
|
||||
}
|
||||
if (opt_out_readlength) *opt_out_readlength = i;
|
||||
res[i] = '\0';
|
||||
close(fd);
|
||||
return res;
|
||||
Failure:
|
||||
free(res);
|
||||
close(fd);
|
||||
return NULL;
|
||||
long double (*nowl)(void);
|
||||
|
||||
static long double GetTimeSample(void) {
|
||||
uint64_t tick1, tick2;
|
||||
long double time1, time2;
|
||||
sched_yield();
|
||||
time1 = dtime(CLOCK_MONOTONIC);
|
||||
tick1 = rdtsc();
|
||||
nanosleep(&(struct timespec){0, 100000}, NULL);
|
||||
time2 = dtime(CLOCK_MONOTONIC);
|
||||
tick2 = rdtsc();
|
||||
return (time2 - time1) * 1e9 / (tick2 - tick1);
|
||||
}
|
||||
|
||||
static long double MeasureNanosPerCycle(void) {
|
||||
int i;
|
||||
long double avg, samp;
|
||||
for (avg = 1.0L, i = 1; i < 5; ++i) {
|
||||
samp = GetTimeSample();
|
||||
avg += (samp - avg) / i;
|
||||
}
|
||||
return avg;
|
||||
}
|
||||
|
||||
static void InitTime(void) {
|
||||
now_.cpn = MeasureNanosPerCycle();
|
||||
now_.r0 = dtime(CLOCK_REALTIME);
|
||||
now_.k0 = rdtsc();
|
||||
now_.once = true;
|
||||
}
|
||||
|
||||
long double converttickstonanos(uint64_t ticks) {
|
||||
if (!now_.once) InitTime();
|
||||
return ticks * now_.cpn; /* pico scale */
|
||||
}
|
||||
|
||||
long double converttickstoseconds(uint64_t ticks) {
|
||||
return 1 / 1e9 * converttickstonanos(ticks);
|
||||
}
|
||||
|
||||
long double nowl$sys(void) {
|
||||
return dtime(CLOCK_REALTIME);
|
||||
}
|
||||
|
||||
long double nowl$art(void) {
|
||||
uint64_t ticks;
|
||||
if (!now_.once) InitTime();
|
||||
ticks = unsignedsubtract(rdtsc(), now_.k0);
|
||||
return now_.r0 + converttickstoseconds(ticks);
|
||||
}
|
||||
|
||||
INITIALIZER(301, _init_nowl, {
|
||||
if (X86_HAVE(INVTSC)) {
|
||||
nowl = nowl$art;
|
||||
} else {
|
||||
nowl = nowl$sys;
|
||||
}
|
||||
})
|
|
@ -22,6 +22,7 @@
|
|||
#include "libc/calls/ntmagicpaths.h"
|
||||
#include "libc/nexgen32e/tinystrcmp.h"
|
||||
#include "libc/nt/createfile.h"
|
||||
#include "libc/nt/enum/filesharemode.h"
|
||||
#include "libc/nt/enum/filetype.h"
|
||||
#include "libc/nt/enum/fsctl.h"
|
||||
#include "libc/nt/errors.h"
|
||||
|
@ -38,7 +39,10 @@ static textwindows int64_t open$nt$impl(const char *file, uint32_t flags,
|
|||
char16_t file16[PATH_MAX];
|
||||
if (mkntpath2(file, flags, file16) == -1) return -1;
|
||||
if ((handle = CreateFile(
|
||||
file16, (flags & 0xf000000f),
|
||||
file16,
|
||||
(flags & 0xf000000f) | (/* this is needed if we mmap(rwx+cow)
|
||||
nt is choosy about open() access */
|
||||
kNtGenericExecute | kNtFileGenericWrite),
|
||||
(flags & O_EXCL)
|
||||
? kNtFileShareExclusive
|
||||
: kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete,
|
||||
|
|
|
@ -37,7 +37,7 @@ privileged uint32_t prot2nt(int prot, int flags) {
|
|||
: HAS(prot, PROT_READ | PROT_WRITE)
|
||||
? (HAS(flags, MAP_SHARED) || HAS(flags, MAP_ANONYMOUS))
|
||||
? kNtPageReadwrite
|
||||
: kNtPageWritecopy
|
||||
: kNtPageReadwrite /* kNtPageWritecopy */
|
||||
: HAS(prot, PROT_READ | PROT_EXEC)
|
||||
? kNtPageExecuteRead
|
||||
: HAS(prot, PROT_EXEC)
|
||||
|
|
|
@ -17,12 +17,12 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/macros.h"
|
||||
|
||||
void removefd(int fd) {
|
||||
if (isfdindex(fd)) {
|
||||
if (isfdopen(fd)) {
|
||||
g_fds.p[fd].kind = kFdEmpty;
|
||||
g_fds.f = min(g_fds.f, fd);
|
||||
g_fds.f = MIN(g_fds.f, fd);
|
||||
}
|
||||
}
|
||||
|
|
42
libc/calls/time.c
Normal file
42
libc/calls/time.c
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
/**
|
||||
* Returns time as seconds from UNIX epoch.
|
||||
*
|
||||
* @param opt_out_ret can receive return value on success
|
||||
* @return seconds since epoch, or -1 w/ errno
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
int64_t time(int64_t *opt_out_ret) {
|
||||
int64_t rc;
|
||||
struct timeval tv;
|
||||
if (gettimeofday(&tv, NULL) == -1) {
|
||||
rc = -1;
|
||||
} else {
|
||||
rc = tv.tv_sec;
|
||||
}
|
||||
if (opt_out_ret) {
|
||||
*opt_out_ret = rc;
|
||||
}
|
||||
return rc;
|
||||
}
|
42
libc/calls/utime.c
Normal file
42
libc/calls/utime.c
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/time/struct/utimbuf.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
/**
|
||||
* Changes last accessed/modified times on file.
|
||||
*
|
||||
* @param times if NULL means now
|
||||
* @return 0 on success or -1 w/ errno
|
||||
*/
|
||||
int utime(const char *path, const struct utimbuf *times) {
|
||||
struct timespec ts[2];
|
||||
if (times) {
|
||||
ts[0].tv_sec = times->actime;
|
||||
ts[0].tv_nsec = 0;
|
||||
ts[1].tv_sec = times->modtime;
|
||||
ts[1].tv_nsec = 0;
|
||||
return utimensat(AT_FDCWD, path, ts, 0);
|
||||
} else {
|
||||
return utimensat(AT_FDCWD, path, NULL, 0);
|
||||
}
|
||||
}
|
83
libc/calls/utimensat-nt.c
Normal file
83
libc/calls/utimensat-nt.c
Normal file
|
@ -0,0 +1,83 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/conv/conv.h"
|
||||
#include "libc/nt/createfile.h"
|
||||
#include "libc/nt/enum/creationdisposition.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/synchronization.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/consts/utime.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
textwindows int utimensat$nt(int dirfd, const char *path,
|
||||
const struct timespec ts[2], int flags) {
|
||||
int i, rc;
|
||||
int64_t fh;
|
||||
bool closeme;
|
||||
uint16_t path16[PATH_MAX];
|
||||
struct NtFileTime ft[2], *ftp[2];
|
||||
if (flags) return einval();
|
||||
if (path) {
|
||||
if (dirfd == AT_FDCWD) {
|
||||
if (mkntpath(path, path16) == -1) return -1;
|
||||
if ((fh = CreateFile(path16, kNtFileWriteAttributes, kNtFileShareRead,
|
||||
NULL, kNtOpenExisting, kNtFileAttributeNormal, 0)) !=
|
||||
-1) {
|
||||
closeme = true;
|
||||
} else {
|
||||
return winerr();
|
||||
}
|
||||
} else {
|
||||
return einval();
|
||||
}
|
||||
} else {
|
||||
return ebadf();
|
||||
}
|
||||
if (!ts || ts[0].tv_nsec == UTIME_NOW || ts[1].tv_nsec == UTIME_NOW) {
|
||||
GetSystemTimeAsFileTime(ft);
|
||||
}
|
||||
if (ts) {
|
||||
for (i = 0; i < 2; ++i) {
|
||||
if (ts[i].tv_nsec == UTIME_NOW) {
|
||||
ftp[i] = ft;
|
||||
} else if (ts[i].tv_nsec == UTIME_OMIT) {
|
||||
ftp[i] = NULL;
|
||||
} else {
|
||||
ft[i] = timespectofiletime(ts[i]);
|
||||
ftp[i] = &ft[i];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ftp[0] = ft;
|
||||
ftp[1] = ft;
|
||||
}
|
||||
if (SetFileTime(fh, NULL, ftp[0], ftp[1])) {
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = winerr();
|
||||
}
|
||||
if (closeme) {
|
||||
CloseHandle(fh);
|
||||
}
|
||||
return rc;
|
||||
}
|
30
libc/calls/utimensat-sysv.c
Normal file
30
libc/calls/utimensat-sysv.c
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
int utimensat$sysv(int dirfd, const char *path, const struct timespec ts[2],
|
||||
int flags) {
|
||||
if (!IsXnu()) {
|
||||
return __utimensat$sysv(dirfd, path, ts, flags);
|
||||
} else {
|
||||
return utimensat$xnu(dirfd, path, ts, flags);
|
||||
}
|
||||
}
|
63
libc/calls/utimensat-xnu.c
Normal file
63
libc/calls/utimensat-xnu.c
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/nexgen32e/nexgen32e.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/consts/utime.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
int utimensat$xnu(int dirfd, const char *path, const struct timespec ts[2],
|
||||
int flags) {
|
||||
int i;
|
||||
struct timeval now, tv[2];
|
||||
if (flags) return einval();
|
||||
if (!ts || ts[0].tv_nsec == UTIME_NOW || ts[1].tv_nsec == UTIME_NOW) {
|
||||
gettimeofday(&now, NULL);
|
||||
}
|
||||
if (ts) {
|
||||
for (i = 0; i < 2; ++i) {
|
||||
if (ts[i].tv_nsec == UTIME_NOW) {
|
||||
tv[i] = now;
|
||||
} else if (ts[i].tv_nsec == UTIME_OMIT) {
|
||||
return einval();
|
||||
} else {
|
||||
tv[i].tv_sec = ts[i].tv_sec;
|
||||
tv[i].tv_usec = div1000int64(ts[i].tv_nsec);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tv[0] = now;
|
||||
tv[1] = now;
|
||||
}
|
||||
if (path) {
|
||||
if (dirfd == AT_FDCWD) {
|
||||
return utimes$sysv(path, tv);
|
||||
} else {
|
||||
return enosys();
|
||||
}
|
||||
} else {
|
||||
if (dirfd != AT_FDCWD) {
|
||||
return futimes$sysv(dirfd, tv);
|
||||
} else {
|
||||
return einval();
|
||||
}
|
||||
}
|
||||
}
|
37
libc/calls/utimensat.c
Normal file
37
libc/calls/utimensat.c
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
|
||||
/**
|
||||
* Sets atime/mtime on file, the modern way.
|
||||
*
|
||||
* @param ts is atime/mtime, or null for current time
|
||||
* @param flags can have AT_SYMLINK_NOFOLLOW
|
||||
* @note no rhel5 support
|
||||
*/
|
||||
int utimensat(int dirfd, const char *path,
|
||||
const struct timespec ts[hasatleast 2], int flags) {
|
||||
if (!IsWindows()) {
|
||||
return utimensat$sysv(dirfd, path, ts, flags);
|
||||
} else {
|
||||
return utimensat$nt(dirfd, path, ts, flags);
|
||||
}
|
||||
}
|
41
libc/calls/utimes.c
Normal file
41
libc/calls/utimes.c
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
/**
|
||||
* Changes last accessed/modified times on file.
|
||||
*
|
||||
* @param times is access/modified and NULL means now
|
||||
* @return 0 on success or -1 w/ errno
|
||||
* @see stat()
|
||||
*/
|
||||
int utimes(const char *path, const struct timeval tv[hasatleast 2]) {
|
||||
struct timespec ts[2];
|
||||
if (tv) {
|
||||
ts[0].tv_sec = tv[0].tv_sec;
|
||||
ts[0].tv_nsec = tv[0].tv_usec * 1000;
|
||||
ts[1].tv_sec = tv[1].tv_sec;
|
||||
ts[1].tv_nsec = tv[1].tv_usec * 1000;
|
||||
return utimensat(AT_FDCWD, path, ts, 0);
|
||||
} else {
|
||||
return utimensat(AT_FDCWD, path, NULL, 0);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue