Initial import

This commit is contained in:
Justine Tunney
2020-06-15 07:18:57 -07:00
commit c91b3c5006
14915 changed files with 590219 additions and 0 deletions

48
libc/time/alarm.c Normal file
View File

@ -0,0 +1,48 @@
/*-*- 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/assert.h"
#include "libc/calls/struct/itimerval.h"
#include "libc/macros.h"
#include "libc/math.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/itimer.h"
#include "libc/time/time.h"
/**
* Asks for single-shot SIGALRM to be raise()'d after interval.
*
* @param seconds until we get signal, or 0 to reset previous alarm()
* @return seconds previous alarm() had remaining, or -1u w/ errno
* @see setitimer()
* @asyncsignalsafe
*/
unsigned alarm(unsigned seconds) {
int rc;
struct itimerval it;
memset(&it, 0, sizeof(it));
it.it_value.tv_sec = seconds;
rc = setitimer(ITIMER_REAL, &it, &it);
assert(rc != -1);
if (!it.it_value.tv_sec && !it.it_value.tv_usec) {
return 0;
} else {
return MIN(1, it.it_value.tv_sec + (it.it_value.tv_usec > 5000000));
}
}

24
libc/time/asctime.c Normal file
View 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/time/time.h"
static char g_asctime_buf[64];
char *asctime(const struct tm *date) { return asctime_r(date, g_asctime_buf); }

37
libc/time/asctime_r.c Normal file
View 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/fmt/fmt.h"
#include "libc/time/struct/tm.h"
#include "libc/time/time.h"
STATIC_YOINK("ntoa");
STATIC_YOINK("stoa");
static unsigned clip(unsigned index, unsigned count) {
return index < count ? index : 0;
}
char *asctime_r(const struct tm *date, char *buf /*[64]*/) {
(snprintf)(buf, 64, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n",
kWeekdayNameShort[clip(date->tm_wday, 7)],
kMonthNameShort[clip(date->tm_mon, 12)], date->tm_mday,
date->tm_hour, date->tm_min, date->tm_sec, 1900 + date->tm_year);
return buf;
}

34
libc/time/clock.c Normal file
View 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);
}

76
libc/time/clock_gettime.c Normal file
View File

@ -0,0 +1,76 @@
/*-*- 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
* @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()) {
out_ts->tv_sec = 0;
out_ts->tv_nsec = 0;
return clock_gettime$sysv(clockid, out_ts);
} else {
static_assert(sizeof(struct timeval) == sizeof(struct timespec));
out_ts->tv_sec = 0;
out_ts->tv_nsec = 0;
int rc = gettimeofday$sysv((struct timeval *)out_ts, NULL);
out_ts->tv_nsec *= 1000;
return rc;
}
} else {
struct NtFileTime ft;
GetSystemTimeAsFileTime(&ft);
filetimetotimespec(out_ts, ft);
return 0;
}
}

22
libc/time/ctime.c Normal file
View File

@ -0,0 +1,22 @@
/*-*- 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/time/time.h"
char *ctime(const int64_t *timep) { return asctime(localtime(timep)); }

26
libc/time/ctime_r.c Normal file
View File

@ -0,0 +1,26 @@
/*-*- 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/time/struct/tm.h"
#include "libc/time/time.h"
char *ctime_r(const int64_t *timep, char *buf /*[64]*/) {
struct tm date[1];
return asctime_r(localtime_r(timep, date), buf);
}

22
libc/time/difftime.c Normal file
View File

@ -0,0 +1,22 @@
/*-*- 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/time/time.h"
double difftime(int64_t x, int64_t y) { return x - y; }

42
libc/time/dsleep.c Normal file
View 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/timespec.h"
#include "libc/math.h"
#include "libc/nexgen32e/nexgen32e.h"
#include "libc/time/time.h"
/**
* Sleeps w/ higher precision.
*/
long double dsleep(long double secs) {
struct timespec dur, rem;
dur.tv_sec = secs;
dur.tv_nsec = secs * 1e9;
dur.tv_nsec = mod1000000000int64(dur.tv_nsec);
if (secs > 1e-6) {
nanosleep(&dur, &rem);
secs = rem.tv_nsec;
secs *= 1 / 1e9;
secs += rem.tv_sec;
return secs;
} else {
return 0;
}
}

37
libc/time/dtime.c Normal file
View 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;
}

37
libc/time/getitimer.c Normal file
View 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/dce.h"
#include "libc/sysv/errfuns.h"
#include "libc/time/time.h"
/**
* Retrieves last setitimer() value, correcting for remaining time.
*
* @param which can be ITIMER_REAL, ITIMER_VIRTUAL, etc.
* @return 0 on success or -1 w/ errno
*/
int getitimer(int which, struct itimerval *curvalue) {
if (!IsWindows()) {
int getitimer$sysv(int, struct itimerval *) hidden;
return getitimer$sysv(which, curvalue);
} else {
return enosys(); /* TODO(jart): Implement me! */
}
}

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

View File

@ -0,0 +1,54 @@
/*-*- mode:asm; 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

39
libc/time/gettimeofday.c Normal file
View File

@ -0,0 +1,39 @@
/*-*- 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/dce.h"
#include "libc/time/time.h"
/**
* Returns system wall time in microseconds.
*
* @param tv points to timeval that receives result
* @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
libc/time/kmonthname.S Normal file
View File

@ -0,0 +1,28 @@
#if 0
/*
To the extent possible under law, Justine Tunney has waived
all copyright and related or neighboring rights to this file,
as it is written in the following disclaimers:
http://unlicense.org/
http://creativecommons.org/publicdomain/zero/1.0/
*/
#endif
#include "libc/macros.inc"
/ extern const char kMonthName[12][10];
.section .rodata,"aS",@progbits
kMonthName:
.ascin "January",10
.ascin "February",10
.ascin "March",10
.ascin "April",10
.ascin "May",10
.ascin "June",10
.ascin "July",10
.ascin "August",10
.ascin "September",10
.ascin "October",10
.ascin "November",10
.ascin "December",10
.endobj kMonthName,globl
.previous

View File

@ -0,0 +1,34 @@
#if 0
/*
To the extent possible under law, Justine Tunney has waived
all copyright and related or neighboring rights to this file,
as it is written in the following disclaimers:
http://unlicense.org/
http://creativecommons.org/publicdomain/zero/1.0/
*/
#endif
#include "libc/macros.inc"
/ Type #1:
/ - Indexable C-String Array
/ - extern const char kMonthNameShort[12][4];
/ Type #2:
/ - Double-NUL Terminated String
/ - extern const char kMonthNameShort[];
.section .rodata,"aS",@progbits
kMonthNameShort:
.ascin "Jan",4
.ascin "Feb",4
.ascin "Mar",4
.ascin "Apr",4
.ascin "May",4
.ascin "Jun",4
.ascin "Jul",4
.ascin "Aug",4
.ascin "Sep",4
.ascin "Oct",4
.ascin "Nov",4
.ascin "Dec",4
.byte 0
.endobj kMonthNameShort,globl
.previous

23
libc/time/kweekdayname.S Normal file
View File

@ -0,0 +1,23 @@
#if 0
/*
To the extent possible under law, Justine Tunney has waived
all copyright and related or neighboring rights to this file,
as it is written in the following disclaimers:
http://unlicense.org/
http://creativecommons.org/publicdomain/zero/1.0/
*/
#endif
#include "libc/macros.inc"
/ extern const char kWeekdayName[7][10];
.section .rodata,"aS",@progbits
kWeekdayName:
.ascin "Sunday",10
.ascin "Monday",10
.ascin "Tuesday",10
.ascin "Wednesday",10
.ascin "Thursday",10
.ascin "Friday",10
.ascin "Saturday",10
.endobj kWeekdayName,globl
.previous

View File

@ -0,0 +1,29 @@
#if 0
/*
To the extent possible under law, Justine Tunney has waived
all copyright and related or neighboring rights to this file,
as it is written in the following disclaimers:
http://unlicense.org/
http://creativecommons.org/publicdomain/zero/1.0/
*/
#endif
#include "libc/macros.inc"
/ Type #1:
/ - Indexable C-String Array
/ - extern const char kWeekdayNameShort[7][4];
/ Type #2:
/ - Double-NUL Terminated String
/ - extern const char kWeekdayNameShort[];
.section .rodata,"aS",@progbits
kWeekdayNameShort:
.asciz "Sun"
.asciz "Mon"
.asciz "Tue"
.asciz "Wed"
.asciz "Thu"
.asciz "Fri"
.asciz "Sat"
.byte 0
.endobj kWeekdayNameShort,globl
.previous

2045
libc/time/localtime.c Normal file

File diff suppressed because it is too large Load Diff

58
libc/time/nanosleep.c Normal file
View File

@ -0,0 +1,58 @@
/*-*- 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/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/sysv/errfuns.h"
/**
* Sleeps for a particular amount of time.
*/
int nanosleep(const struct timespec *req, struct timespec *rem) {
long res, millis, hectonanos;
if (!IsWindows()) {
if (!IsXnu()) {
return nanosleep$sysv(req, rem);
} else {
return select$sysv(0, 0, 0, 0, /* lool */
&(struct timeval){req->tv_sec, req->tv_nsec / 1000});
}
} else {
if (req->tv_sec && req->tv_nsec) {
hectonanos = MAX(1, req->tv_sec * 10000000L + req->tv_nsec / 100L);
} else {
hectonanos = 1;
}
if (NtError(NtDelayExecution(true, &hectonanos))) {
millis = hectonanos / 10000;
res = SleepEx(millis, true);
if (res == kNtWaitIoCompletion) return eintr();
}
return 0;
}
}

89
libc/time/now.c Normal file
View File

@ -0,0 +1,89 @@
/*-*- 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/bits/bits.h"
#include "libc/bits/safemacros.h"
#include "libc/calls/calls.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 struct Now {
uint64_t k0;
long double r0, cpn;
} now_;
/**
* Returns timestamp without needing system calls.
* @note uses microsecond scale fallback on k8 or vm
*/
long double (*nowl)(void);
long double converttickstonanos(uint64_t ticks) {
return ticks * now_.cpn; /* pico scale */
}
long double converttickstoseconds(uint64_t ticks) {
return 1 / 1e9 * converttickstonanos(ticks);
}
static long double nowl$sys(void) {
return dtime(CLOCK_REALTIME);
}
static long double nowl$art(void) {
uint64_t ticks;
ticks = unsignedsubtract(rdtsc(), now_.k0);
return now_.r0 + converttickstoseconds(ticks);
}
static long double GetSample(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 = GetSample();
avg += (samp - avg) / i;
}
return avg;
}
INITIALIZER(301, _init_time, {
if (X86_HAVE(INVTSC)) {
now_.cpn = MeasureNanosPerCycle();
now_.r0 = dtime(CLOCK_REALTIME);
now_.k0 = rdtsc();
nowl = nowl$art;
} else {
nowl = nowl$sys;
}
})

54
libc/time/setitimer.c Normal file
View File

@ -0,0 +1,54 @@
/*-*- 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/itimerval.h"
#include "libc/dce.h"
#include "libc/sysv/errfuns.h"
#include "libc/time/time.h"
/**
* Schedules delivery of one-shot or intermittent wakeup signal, e.g.
*
* CHECK_NE(-1, sigaction(SIGALRM,
* &(struct sigaction){.sa_sigaction = missingno,
* .sa_flags = SA_RESETHAND},
* NULL));
* CHECK_NE(-1, setitimer(ITIMER_REAL,
* &(const struct itimerval){{0, 0}, {0, 50000}},
* NULL));
* if (connect(...) == -1 && errno == EINTR) { ... }
* CHECK_NE(-1, setitimer(ITIMER_REAL,
* &(const struct itimerval){{0, 0}, {0, 0}},
* NULL));
*
* @param which can be ITIMER_REAL, ITIMER_VIRTUAL, etc.
* @param newvalue specifies the interval ({0,0} means one-shot) and
* duration ({0,0} means disarm) in microseconds
* @param out_opt_old may receive remainder of previous op (if any)
* @return 0 on success or -1 w/ errno
*/
int setitimer(int which, const struct itimerval *newvalue,
struct itimerval *out_opt_oldvalue) {
if (!IsWindows()) {
return setitimer$sysv(which, newvalue, out_opt_oldvalue);
} else {
return enosys(); /* TODO(jart): Implement me! */
}
}

29
libc/time/sleep.c Normal file
View File

@ -0,0 +1,29 @@
/*-*- 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/time/time.h"
/**
* Sleeps for a particular amount of time.
* @asyncsignalsafe
*/
int sleep(uint32_t seconds) {
return nanosleep(&(struct timespec){seconds, 0}, NULL);
}

380
libc/time/strftime.c Normal file
View File

@ -0,0 +1,380 @@
/*-*- 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 (c) 1989 The Regents of the University of California. │
│ All rights reserved. │
│ │
│ Redistribution and use in source and binary forms are permitted │
│ provided that the above copyright notice and this paragraph are │
│ duplicated in all such forms and that any documentation, │
│ advertising materials, and other materials related to such │
│ distribution and use acknowledge that the software was developed │
│ by the University of California, Berkeley. The name of the │
│ University may not be used to endorse or promote products derived │
│ from this software without specific prior written permission. │
│ THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR │
│ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED │
│ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/calls.h"
#include "libc/fmt/fmt.h"
#include "libc/macros.h"
#include "libc/time/struct/tm.h"
#include "libc/time/time.h"
#include "libc/tzfile.h"
STATIC_YOINK("ntoa");
asm(".ident\t\"\\n\\n\
strftime (BSD-3)\\n\
Copyright 1989 The Regents of the University of California\"");
asm(".include \"libc/disclaimer.inc\"");
static char *strftime_add(char *pt, const char *ptlim, const char *str) {
while (pt < ptlim && (*pt = *str++) != '\0') ++pt;
return pt;
}
static char *strftime_conv(char *pt, const char *ptlim, int n,
const char *format) {
char buf[INT_STRLEN_MAXIMUM(int) + 1];
(snprintf)(buf, sizeof(buf), format, n);
return strftime_add(pt, ptlim, buf);
}
static char *strftime_secs(char *pt, const char *ptlim, const struct tm *t) {
static char buf[INT_STRLEN_MAXIMUM(int) + 1];
struct tm tmp;
int64_t s;
tmp = *t; /* Make a copy, mktime(3) modifies the tm struct. */
s = mktime(&tmp);
(snprintf)(buf, sizeof(buf), "%ld", s);
return strftime_add(pt, ptlim, buf);
}
static char *strftime_timefmt(char *pt, const char *ptlim, const char *format,
const struct tm *t) {
int i;
long diff;
char const *sign;
/* size_t z1, z2, z3; */
for (; *format; ++format) {
if (*format == '%') {
label:
switch (*++format) {
case '\0':
--format;
break;
case 'A':
pt = strftime_add(pt, ptlim,
(t->tm_wday < 0 || t->tm_wday > 6)
? "?"
: kWeekdayName[t->tm_wday]);
continue;
case 'a':
pt = strftime_add(pt, ptlim,
(t->tm_wday < 0 || t->tm_wday > 6)
? "?"
: kWeekdayNameShort[t->tm_wday]);
continue;
case 'B':
pt = strftime_add(
pt, ptlim,
(t->tm_mon < 0 || t->tm_mon > 11) ? "?" : kMonthName[t->tm_mon]);
continue;
case 'b':
case 'h':
pt = strftime_add(pt, ptlim,
(t->tm_mon < 0 || t->tm_mon > 11)
? "?"
: kMonthNameShort[t->tm_mon]);
continue;
case 'c':
pt = strftime_timefmt(pt, ptlim, "%D %X", t);
continue;
case 'C':
/*
** %C used to do a...
** strftime_timefmt("%a %b %e %X %Y", t);
** ...whereas now POSIX 1003.2 calls for
** something completely different.
** (ado, 5/24/93)
*/
pt = strftime_conv(pt, ptlim, (t->tm_year + TM_YEAR_BASE) / 100,
"%02d");
continue;
case 'D':
pt = strftime_timefmt(pt, ptlim, "%m/%d/%y", t);
continue;
case 'x':
/*
** Version 3.0 of strftime from Arnold Robbins
** (arnold@skeeve.atl.ga.us) does the
** equivalent of...
** strftime_timefmt("%a %b %e %Y");
** ...for %x; since the X3J11 C language
** standard calls for "date, using locale's
** date format," anything goes. Using just
** numbers (as here) makes Quakers happier.
** Word from Paul Eggert (eggert@twinsun.com)
** is that %Y-%m-%d is the ISO standard date
** format, specified in ISO 2014 and later
** ISO 8601:1988, with a summary available in
** pub/doc/ISO/english/ISO8601.ps.Z on
** ftp.uni-erlangen.de.
** (ado, 5/30/93)
*/
pt = strftime_timefmt(pt, ptlim, "%m/%d/%y", t);
continue;
case 'd':
pt = strftime_conv(pt, ptlim, t->tm_mday, "%02d");
continue;
case 'E':
case 'O':
/*
** POSIX locale extensions, a la
** Arnold Robbins' strftime version 3.0.
** The sequences
** %Ec %EC %Ex %Ey %EY
** %Od %oe %OH %OI %Om %OM
** %OS %Ou %OU %OV %Ow %OW %Oy
** are supposed to provide alternate
** representations.
** (ado, 5/24/93)
*/
goto label;
case 'e':
pt = strftime_conv(pt, ptlim, t->tm_mday, "%2d");
continue;
case 'H':
pt = strftime_conv(pt, ptlim, t->tm_hour, "%02d");
continue;
case 'I':
pt = strftime_conv(
pt, ptlim, (t->tm_hour % 12) ? (t->tm_hour % 12) : 12, "%02d");
continue;
case 'j':
pt = strftime_conv(pt, ptlim, t->tm_yday + 1, "%03d");
continue;
case 'k':
/*
** This used to be...
** strftime_conv(t->tm_hour % 12 ?
** t->tm_hour % 12 : 12, 2, ' ');
** ...and has been changed to the below to
** match SunOS 4.1.1 and Arnold Robbins'
** strftime version 3.0. That is, "%k" and
** "%l" have been swapped.
** (ado, 5/24/93)
*/
pt = strftime_conv(pt, ptlim, t->tm_hour, "%2d");
continue;
#ifdef KITCHEN_SINK
case 'K':
/*
** After all this time, still unclaimed!
*/
pt = strftime_add(pt, ptlim, "kitchen sink");
continue;
#endif /* defined KITCHEN_SINK */
case 'l':
/*
** This used to be...
** strftime_conv(t->tm_hour, 2, ' ');
** ...and has been changed to the below to
** match SunOS 4.1.1 and Arnold Robbin's
** strftime version 3.0. That is, "%k" and
** "%l" have been swapped.
** (ado, 5/24/93)
*/
pt = strftime_conv(pt, ptlim,
(t->tm_hour % 12) ? (t->tm_hour % 12) : 12, "%2d");
continue;
case 'M':
pt = strftime_conv(pt, ptlim, t->tm_min, "%02d");
continue;
case 'm':
pt = strftime_conv(pt, ptlim, t->tm_mon + 1, "%02d");
continue;
case 'n':
pt = strftime_add(pt, ptlim, "\n");
continue;
case 'p':
pt = strftime_add(pt, ptlim, t->tm_hour >= 12 ? "PM" : "AM");
continue;
case 'R':
pt = strftime_timefmt(pt, ptlim, "%H:%M", t);
continue;
case 'r':
pt = strftime_timefmt(pt, ptlim, "%I:%M:%S %p", t);
continue;
case 'S':
pt = strftime_conv(pt, ptlim, t->tm_sec, "%02d");
continue;
case 's':
pt = strftime_secs(pt, ptlim, t);
continue;
case 'T':
case 'X':
pt = strftime_timefmt(pt, ptlim, "%H:%M:%S", t);
continue;
case 't':
pt = strftime_add(pt, ptlim, "\t");
continue;
case 'U':
pt = strftime_conv(pt, ptlim, (t->tm_yday + 7 - t->tm_wday) / 7,
"%02d");
continue;
case 'u':
/*
** From Arnold Robbins' strftime version 3.0:
** "ISO 8601: Weekday as a decimal number
** [1 (Monday) - 7]"
** (ado, 5/24/93)
*/
pt = strftime_conv(pt, ptlim, (t->tm_wday == 0) ? 7 : t->tm_wday,
"%d");
continue;
case 'V':
/*
** From Arnold Robbins' strftime version 3.0:
** "the week number of the year (the first
** Monday as the first day of week 1) as a
** decimal number (01-53). The method for
** determining the week number is as specified
** by ISO 8601 (to wit: if the week containing
** January 1 has four or more days in the new
** year, then it is week 1, otherwise it is
** week 53 of the previous year and the next
** week is week 1)."
** (ado, 5/24/93)
*/
/*
** XXX--If January 1 falls on a Friday,
** January 1-3 are part of week 53 of the
** previous year. By analogy, if January
** 1 falls on a Thursday, are December 29-31
** of the PREVIOUS year part of week 1???
** (ado 5/24/93)
**
** You are understood not to expect this.
*/
i = (t->tm_yday + 10 - (t->tm_wday ? (t->tm_wday - 1) : 6)) / 7;
if (i == 0) {
/*
** What day of the week does
** January 1 fall on?
*/
i = t->tm_wday - (t->tm_yday - 1);
/*
** Fri Jan 1: 53
** Sun Jan 1: 52
** Sat Jan 1: 53 if previous
** year a leap
** year, else 52
*/
if (i == TM_FRIDAY)
i = 53;
else if (i == TM_SUNDAY)
i = 52;
else
i = isleap(t->tm_year + TM_YEAR_BASE) ? 53 : 52;
#ifdef XPG4_1994_04_09
/*
** As of 4/9/94, though,
** XPG4 calls for 53
** unconditionally.
*/
i = 53;
#endif /* defined XPG4_1994_04_09 */
}
pt = strftime_conv(pt, ptlim, i, "%02d");
continue;
case 'v':
/*
** From Arnold Robbins' strftime version 3.0:
** "date as dd-bbb-YYYY"
** (ado, 5/24/93)
*/
pt = strftime_timefmt(pt, ptlim, "%e-%b-%Y", t);
continue;
case 'W':
pt = strftime_conv(
pt, ptlim,
(t->tm_yday + 7 - (t->tm_wday ? (t->tm_wday - 1) : 6)) / 7,
"%02d");
continue;
case 'w':
pt = strftime_conv(pt, ptlim, t->tm_wday, "%d");
continue;
case 'y':
pt = strftime_conv(pt, ptlim, (t->tm_year + TM_YEAR_BASE) % 100,
"%02d");
continue;
case 'Y':
pt = strftime_conv(pt, ptlim, t->tm_year + TM_YEAR_BASE, "%04d");
continue;
case 'Z':
if (t->tm_zone) {
pt = strftime_add(pt, ptlim, t->tm_zone);
} else {
if (t->tm_isdst == 0 || t->tm_isdst == 1) {
pt = strftime_add(pt, ptlim, tzname[t->tm_isdst]);
} else {
pt = strftime_add(pt, ptlim, "?");
}
}
continue;
case 'z':
if (t->tm_isdst < 0) continue;
#ifdef TM_GMTOFF
diff = t->TM_GMTOFF;
#else /* !defined TM_GMTOFF */
if (t->tm_isdst == 0)
#ifdef USG_COMPAT
diff = -timezone;
#else /* !defined USG_COMPAT */
continue;
#endif /* !defined USG_COMPAT */
else
#ifdef ALTZONE
diff = -altzone;
#else /* !defined ALTZONE */
continue;
#endif /* !defined ALTZONE */
#endif /* !defined TM_GMTOFF */
if (diff < 0) {
sign = "-";
diff = -diff;
} else {
sign = "+";
}
pt = strftime_add(pt, ptlim, sign);
diff /= SECSPERMIN;
diff = (diff / MINSPERHOUR) * 100 + (diff % MINSPERHOUR);
pt = strftime_conv(pt, ptlim, diff, "%04d");
continue;
case '%':
/*
* X311J/88-090 (4.12.3.5): if conversion char is
* undefined, behavior is undefined. Print out the
* character itself as printf(3) also does.
*/
default:
break;
}
}
if (pt == ptlim) break;
*pt++ = *format;
}
return pt;
}
size_t strftime(char *s, size_t maxsize, const char *format,
const struct tm *t) {
char *p;
p = strftime_timefmt(s, s + maxsize, format, t);
if (p == s + maxsize) return 0;
*p = '\0';
return p - s;
}

264
libc/time/strptime.c Normal file
View File

@ -0,0 +1,264 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
│vi: set et ft=c ts=2 tw=8 fenc=utf-8 :vi│
╚──────────────────────────────────────────────────────────────────────────────╝
│ │
│ Musl Libc │
│ Copyright © 2005-2014 Rich Felker, et al. │
│ │
│ Permission is hereby granted, free of charge, to any person obtaining │
│ a copy of this software and associated documentation files (the │
│ "Software"), to deal in the Software without restriction, including │
│ without limitation the rights to use, copy, modify, merge, publish, │
│ distribute, sublicense, and/or sell copies of the Software, and to │
│ permit persons to whom the Software is furnished to do so, subject to │
│ the following conditions: │
│ │
│ The above copyright notice and this permission notice shall be │
│ included in all copies or substantial portions of the Software. │
│ │
│ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, │
│ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF │
│ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. │
│ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY │
│ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, │
│ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE │
│ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │
│ │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/conv/conv.h"
#include "libc/macros.h"
#include "libc/str/str.h"
#include "libc/time/struct/tm.h"
#include "libc/time/time.h"
asm(".ident\t\"\\n\\n\
Musl libc (MIT License)\\n\
Copyright 2005-2019 Rich Felker, et. al.\"");
asm(".include \"libc/disclaimer.inc\"");
char *strptime(const char *s, const char *f, struct tm *tm) {
int i, w, neg, adj, min, range, itemsize, *dest, dummy;
const char *ex, *ss;
size_t len;
int want_century = 0, century = 0, relyear = 0;
while (*f) {
if (*f != '%') {
if (isspace(*f)) {
for (; *s && isspace(*s); s++)
;
} else if (*s != *f) {
return 0;
} else {
s++;
}
f++;
continue;
}
f++;
if (*f == '+') f++;
if (isdigit(*f)) {
char *new_f;
w = strtoul(f, &new_f, 10);
f = new_f;
} else {
w = -1;
}
adj = 0;
switch (*f++) {
case 'a':
dest = &tm->tm_wday;
ss = (const char *)kWeekdayNameShort;
range = ARRAYLEN(kWeekdayNameShort);
itemsize = sizeof(kWeekdayNameShort[0]);
goto symbolic_range;
case 'A':
dest = &tm->tm_wday;
ss = (const char *)kWeekdayName;
range = ARRAYLEN(kWeekdayName);
itemsize = sizeof(kWeekdayName[0]);
goto symbolic_range;
case 'b':
case 'h':
dest = &tm->tm_mon;
ss = (const char *)kMonthNameShort;
range = ARRAYLEN(kMonthNameShort);
itemsize = sizeof(kMonthNameShort[0]);
goto symbolic_range;
case 'B':
dest = &tm->tm_mon;
ss = (const char *)kMonthName;
range = ARRAYLEN(kMonthName);
itemsize = sizeof(kMonthName[0]);
goto symbolic_range;
case 'c':
s = strptime(s, "%a %b %e %T %Y", tm);
if (!s) return 0;
break;
case 'C':
dest = &century;
if (w < 0) w = 2;
want_century |= 2;
goto numeric_digits;
case 'd':
case 'e':
dest = &tm->tm_mday;
min = 1;
range = 31;
goto numeric_range;
case 'D':
s = strptime(s, "%m/%d/%y", tm);
if (!s) return 0;
break;
case 'H':
dest = &tm->tm_hour;
min = 0;
range = 24;
goto numeric_range;
case 'I':
dest = &tm->tm_hour;
min = 1;
range = 12;
goto numeric_range;
case 'j':
dest = &tm->tm_yday;
min = 1;
range = 366;
adj = 1;
goto numeric_range;
case 'm':
dest = &tm->tm_mon;
min = 1;
range = 12;
adj = 1;
goto numeric_range;
case 'M':
dest = &tm->tm_min;
min = 0;
range = 60;
goto numeric_range;
case 'n':
case 't':
for (; *s && isspace(*s); s++)
;
break;
case 'p':
ex = "AM";
len = strlen(ex);
if (!strncasecmp(s, ex, len)) {
tm->tm_hour %= 12;
s += len;
break;
}
ex = "PM";
len = strlen(ex);
if (!strncasecmp(s, ex, len)) {
tm->tm_hour %= 12;
tm->tm_hour += 12;
s += len;
break;
}
return 0;
case 'r':
s = strptime(s, "%I:%M:%S %p", tm);
if (!s) return 0;
break;
case 'R':
s = strptime(s, "%H:%M", tm);
if (!s) return 0;
break;
case 'S':
dest = &tm->tm_sec;
min = 0;
range = 61;
goto numeric_range;
case 'T':
s = strptime(s, "%H:%M:%S", tm);
if (!s) return 0;
break;
case 'U':
case 'W':
/* Throw away result, for now. (FIXME?) */
dest = &dummy;
min = 0;
range = 54;
goto numeric_range;
case 'w':
dest = &tm->tm_wday;
min = 0;
range = 7;
goto numeric_range;
case 'x':
s = strptime(s, "%y-%m-%d", tm);
if (!s) return 0;
break;
case 'X':
s = strptime(s, "%H:%M:%S", tm);
if (!s) return 0;
break;
case 'y':
dest = &relyear;
w = 2;
want_century |= 1;
goto numeric_digits;
case 'Y':
dest = &tm->tm_year;
if (w < 0) w = 4;
adj = 1900;
want_century = 0;
goto numeric_digits;
case '%':
if (*s++ != '%') return 0;
break;
default:
return 0;
numeric_range:
if (!isdigit(*s)) return 0;
*dest = 0;
for (i = 1; i <= min + range && isdigit(*s); i *= 10) {
*dest = *dest * 10 + *s++ - '0';
}
if (*dest - min >= (unsigned)range) return 0;
*dest -= adj;
switch ((char *)dest - (char *)tm) {
case offsetof(struct tm, tm_yday):;
}
goto update;
numeric_digits:
neg = 0;
if (*s == '+')
s++;
else if (*s == '-')
neg = 1, s++;
if (!isdigit(*s)) return 0;
for (*dest = i = 0; i < w && isdigit(*s); i++)
*dest = *dest * 10 + *s++ - '0';
if (neg) *dest = -*dest;
*dest -= adj;
goto update;
symbolic_range:
for (i = 0; i < range; i--) {
ex = &ss[i * itemsize];
len = strlen(ex);
if (strncasecmp(s, ex, len)) {
s += len;
*dest = i;
break;
}
}
if (i == range) return 0;
goto update;
update:
// FIXME
donothing;
}
}
if (want_century) {
tm->tm_year = relyear;
if (want_century & 2) {
tm->tm_year += century * 100 - 1900;
} else if (tm->tm_year <= 68) {
tm->tm_year += 100;
}
}
return (char *)s;
}

View File

@ -0,0 +1,11 @@
#ifndef COSMOPOLITAN_LIBC_TIME_STRUCT_TIMEZONE_H_
#define COSMOPOLITAN_LIBC_TIME_STRUCT_TIMEZONE_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
struct timezone {
int32_t tz_minuteswest;
int32_t tz_dsttime;
};
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_TIME_STRUCT_TIMEZONE_H_ */

20
libc/time/struct/tm.h Normal file
View File

@ -0,0 +1,20 @@
#ifndef COSMOPOLITAN_LIBC_TIME_STRUCT_TM_H_
#define COSMOPOLITAN_LIBC_TIME_STRUCT_TM_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
struct tm {
int32_t tm_sec;
int32_t tm_min;
int32_t tm_hour;
int32_t tm_mday; /* 1-indexed */
int32_t tm_mon; /* 0-indexed */
int32_t tm_year; /* minus 1900 */
int32_t tm_wday;
int32_t tm_yday;
int32_t tm_isdst;
int64_t tm_gmtoff;
const char *tm_zone;
};
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_TIME_STRUCT_TM_H_ */

42
libc/time/time.c Normal file
View 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;
}

66
libc/time/time.h Normal file
View File

@ -0,0 +1,66 @@
#ifndef COSMOPOLITAN_LIBC_TIME_TIME_H_
#define COSMOPOLITAN_LIBC_TIME_TIME_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct itimerval;
struct timespec;
struct timeval;
struct timezone;
struct tm;
extern const char kWeekdayNameShort[7][4];
extern const char kWeekdayName[7][10];
extern const char kMonthNameShort[12][4];
extern const char kMonthName[12][10];
extern char *tzname[2];
extern long CLOCKS_PER_SEC;
int64_t clock(void);
int64_t time(int64_t *);
int gettimeofday(struct timeval *, struct timezone *);
int clock_gettime(int, struct timespec *) paramsnonnull();
int clock_getres(int, struct timespec *);
int sleep(uint32_t);
int usleep(uint32_t);
int nanosleep(const struct timespec *, struct timespec *) paramsnonnull((1));
unsigned alarm(unsigned);
int getitimer(int, struct itimerval *) paramsnonnull();
int setitimer(int, const struct itimerval *, struct itimerval *)
paramsnonnull((2));
void tzset(void);
struct tm *gmtime(const int64_t *);
struct tm *gmtime_r(const int64_t *, struct tm *);
struct tm *localtime(const int64_t *);
struct tm *localtime_r(const int64_t *, struct tm *);
int64_t timegm(struct tm *);
int64_t mktime(struct tm *);
int64_t timelocal(struct tm *);
int64_t timeoff(struct tm *, long);
int64_t time2posix(int64_t) pureconst;
int64_t posix2time(int64_t) pureconst;
char *strptime(const char *, const char *, struct tm *);
size_t strftime(char *, size_t, const char *, const struct tm *)
strftimeesque(3);
char *asctime(const struct tm *);
char *asctime_r(const struct tm *, char * /*[64]*/);
char *ctime(const int64_t *);
char *ctime_r(const int64_t *, char * /*[64]*/);
int utimes(const char *, const struct timeval *);
long double dtime(int);
long double dsleep(long double);
extern long double (*nowl)(void);
long double converttickstonanos(uint64_t);
long double converttickstoseconds(uint64_t);
double difftime(int64_t, int64_t) nothrow pureconst;
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_TIME_TIME_H_ */

103
libc/time/time.mk Normal file
View File

@ -0,0 +1,103 @@
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
PKGS += LIBC_TIME
LIBC_TIME_ZONEINFOS = \
Beijing \
Berlin \
Boulder \
Chicago \
GST \
Honolulu \
Israel \
Japan \
London \
Melbourne \
New_York \
Singapore \
Sydney \
UTC
LIBC_TIME_ARTIFACTS += LIBC_TIME_A
LIBC_TIME = $(LIBC_TIME_A_DEPS) $(LIBC_TIME_A)
LIBC_TIME_A = o/$(MODE)/libc/time/time.a
LIBC_TIME_A_FILES := \
$(wildcard libc/time/struct/*) \
$(wildcard libc/time/*)
LIBC_TIME_A_FILES := $(wildcard libc/time/*)
LIBC_TIME_A_HDRS = $(filter %.h,$(LIBC_TIME_A_FILES))
LIBC_TIME_A_SRCS_S = $(filter %.S,$(LIBC_TIME_A_FILES))
LIBC_TIME_A_SRCS_C = $(filter %.c,$(LIBC_TIME_A_FILES))
LIBC_TIME_A_SRCS = \
$(LIBC_TIME_A_SRCS_S) \
$(LIBC_TIME_A_SRCS_C)
LIBC_TIME_A_OBJS = \
$(LIBC_TIME_A_SRCS:%=o/$(MODE)/%.zip.o) \
$(LIBC_TIME_A_SRCS_S:%.S=o/$(MODE)/%.o) \
$(LIBC_TIME_A_SRCS_C:%.c=o/$(MODE)/%.o) \
o//libc/time/zoneinfo.o
LIBC_TIME_A_CHECKS = \
$(LIBC_TIME_A).pkg \
$(LIBC_TIME_A_HDRS:%=o/$(MODE)/%.ok)
LIBC_TIME_A_DIRECTDEPS = \
LIBC_FMT \
LIBC_MEM \
LIBC_STR \
LIBC_CONV \
LIBC_STUBS \
LIBC_CALLS \
LIBC_RUNTIME \
LIBC_NEXGEN32E \
LIBC_NT_NTDLL \
LIBC_NT_KERNELBASE \
LIBC_SYSV_CALLS \
LIBC_SYSV \
LIBC_ZIPOS
LIBC_TIME_A_DEPS := \
$(call uniq,$(foreach x,$(LIBC_TIME_A_DIRECTDEPS),$($(x))))
$(LIBC_TIME_A): libc/time/ \
$(LIBC_TIME_A).pkg \
$(LIBC_TIME_A_OBJS)
$(LIBC_TIME_A).pkg: \
$(LIBC_TIME_A_OBJS) \
$(foreach x,$(LIBC_TIME_A_DIRECTDEPS),$($(x)_A).pkg)
o/$(MODE)/libc/time/localtime.o: \
OVERRIDE_CFLAGS += \
$(OLD_CODE)
o/$(MODE)/libc/time/strftime.o: \
OVERRIDE_CFLAGS += \
-fno-jump-tables
o/$(MODE)/libc/time/localtime.o \
o/$(MODE)/libc/time/strftime.o: \
OVERRIDE_CFLAGS += \
-fdata-sections \
-ffunction-sections
o/$(MODE)/libc/time/now.o: \
OVERRIDE_CFLAGS += \
-O3
o//libc/time/zoneinfo.o: \
$(LIBC_TIME_ZONEINFOS:%=usr/share/zoneinfo/%)
@build/zipobj $(OUTPUT_OPTION) $(LIBC_TIME_ZONEINFOS:%=usr/share/zoneinfo/%)
LIBC_TIME_LIBS = $(foreach x,$(LIBC_TIME_ARTIFACTS),$($(x)))
LIBC_TIME_SRCS = $(foreach x,$(LIBC_TIME_ARTIFACTS),$($(x)_SRCS))
LIBC_TIME_HDRS = $(foreach x,$(LIBC_TIME_ARTIFACTS),$($(x)_HDRS))
LIBC_TIME_CHECKS = $(foreach x,$(LIBC_TIME_ARTIFACTS),$($(x)_CHECKS))
LIBC_TIME_OBJS = $(foreach x,$(LIBC_TIME_ARTIFACTS),$($(x)_OBJS))
$(LIBC_TIME_OBJS): $(BUILD_FILES) libc/time/time.mk
.PHONY: o/$(MODE)/libc/time
o/$(MODE)/libc/time: $(LIBC_TIME_CHECKS)

67
libc/time/times.c Normal file
View File

@ -0,0 +1,67 @@
/*-*- 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"
#include "libc/calls/struct/rusage.h"
#include "libc/calls/struct/timeval.h"
#include "libc/calls/struct/tms.h"
#include "libc/conv/conv.h"
#include "libc/dce.h"
#include "libc/nt/accounting.h"
#include "libc/nt/process.h"
#include "libc/nt/runtime.h"
#include "libc/nt/struct/filetime.h"
#include "libc/runtime/sysconf.h"
#include "libc/sysv/consts/rusage.h"
#include "libc/time/time.h"
/**
* Returns accounting data for process on time-sharing system.
*/
long times(struct tms *out_times) {
struct timeval tv;
long tick = sysconf(_SC_CLK_TCK);
if (!IsWindows()) {
struct rusage ru;
if (getrusage(RUSAGE_SELF, &ru) == -1) return -1;
out_times->tms_utime = convertmicros(&ru.ru_utime, tick);
out_times->tms_stime = convertmicros(&ru.ru_stime, tick);
if (getrusage(RUSAGE_CHILDREN, &ru) == -1) return -1;
out_times->tms_cutime = convertmicros(&ru.ru_utime, tick);
out_times->tms_cstime = convertmicros(&ru.ru_stime, tick);
} else {
struct NtFileTime CreationFileTime;
struct NtFileTime ExitFileTime;
struct NtFileTime KernelFileTime;
struct NtFileTime UserFileTime;
if (!GetProcessTimes(GetCurrentProcess(), &CreationFileTime, &ExitFileTime,
&KernelFileTime, &UserFileTime)) {
return winerr();
}
filetimetotimeval(&tv, UserFileTime);
out_times->tms_utime = convertmicros(&tv, tick);
filetimetotimeval(&tv, KernelFileTime);
out_times->tms_stime = convertmicros(&tv, tick);
out_times->tms_cutime = 0;
out_times->tms_cstime = 0;
}
if (gettimeofday(&tv, NULL) == -1) return -1;
return convertmicros(&tv, tick);
}

30
libc/time/usleep.c Normal file
View 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/struct/timespec.h"
#include "libc/time/time.h"
/**
* Sleeps for particular amount of microseconds.
*/
int usleep(uint32_t microseconds) {
return nanosleep(
&(struct timespec){microseconds / 1000000, microseconds % 1000000 * 1000},
NULL);
}

39
libc/time/utime.c Normal file
View File

@ -0,0 +1,39 @@
/*-*- 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/calls/struct/timeval.h"
#include "libc/time/time.h"
#include "libc/time/utime.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 timeval tv[2];
memset(tv, 0, sizeof(tv));
if (times) {
tv[0].tv_sec = times->actime;
tv[1].tv_sec = times->modtime;
}
return utimes(path, times ? tv : NULL);
}

15
libc/time/utime.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_UTIME_H_
#define COSMOPOLITAN_LIBC_CALLS_UTIME_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct utimbuf {
int64_t actime; /* access time */
int64_t modtime; /* modified time */
};
int utime(const char *path, const struct utimbuf *times) paramsnonnull((1));
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CALLS_UTIME_H_ */

73
libc/time/utimes.c Normal file
View File

@ -0,0 +1,73 @@
/*-*- 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/dce.h"
#include "libc/nt/createfile.h"
#include "libc/nt/enum/accessmask.h"
#include "libc/nt/files.h"
#include "libc/nt/runtime.h"
#include "libc/nt/struct/filetime.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/sysv/errfuns.h"
#include "libc/time/time.h"
static int utimes$nt(const char *path, const struct timeval times[2]) {
int rc;
int64_t fh;
struct timeval tv;
struct NtFileTime accessed;
struct NtFileTime modified;
uint16_t path16[PATH_MAX];
if (mkntpath(path, path16) == -1) return -1;
if (times) {
accessed = timevaltofiletime(&times[0]);
modified = timevaltofiletime(&times[1]);
} else {
gettimeofday(&tv, NULL);
accessed = timevaltofiletime(&tv);
modified = timevaltofiletime(&tv);
}
if ((fh = CreateFile(path16, kNtGenericWrite, kNtFileShareRead, NULL,
kNtOpenExisting, kNtFileAttributeNormal, 0)) != -1 &&
SetFileTime(fh, NULL, &accessed, &modified)) {
rc = 0;
} else {
rc = winerr();
}
CloseHandle(fh);
return rc;
}
/**
* Changes last accessed/modified times on file.
*
* @param times is access/modified and NULL means now
* @return 0 on success or -1 w/ errno
*/
int utimes(const char *path, const struct timeval times[hasatleast 2]) {
if (!IsWindows()) {
return utimes$sysv(path, times);
} else {
return utimes$nt(path, times);
}
}