|
Packit |
437b5e |
/*
|
|
Packit |
437b5e |
* POSIX library for Lua 5.1, 5.2 & 5.3.
|
|
Packit |
437b5e |
* (c) Gary V. Vaughan <gary@vaughan.pe>, 2013-2015
|
|
Packit |
437b5e |
* (c) Reuben Thomas <rrt@sc3d.org> 2010-2013
|
|
Packit |
437b5e |
* (c) Natanael Copa <natanael.copa@gmail.com> 2008-2010
|
|
Packit |
437b5e |
* Clean up and bug fixes by Leo Razoumov <slonik.az@gmail.com> 2006-10-11
|
|
Packit |
437b5e |
* Luiz Henrique de Figueiredo <lhf@tecgraf.puc-rio.br> 07 Apr 2006 23:17:49
|
|
Packit |
437b5e |
* Based on original by Claudio Terra for Lua 3.x.
|
|
Packit |
437b5e |
* With contributions by Roberto Ierusalimschy.
|
|
Packit |
437b5e |
* With documentation from Steve Donovan 2012
|
|
Packit |
437b5e |
*/
|
|
Packit |
437b5e |
/***
|
|
Packit |
437b5e |
Time and Clock Functions.
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
@module posix.time
|
|
Packit |
437b5e |
*/
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
#include <config.h>
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
#include <sys/time.h>
|
|
Packit |
437b5e |
#include <time.h>
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
#include "_helpers.c"
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
static const char *Stimespec_fields[] = { "tv_sec", "tv_nsec" };
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
static void
|
|
Packit |
437b5e |
totimespec(lua_State *L, int index, struct timespec *ts)
|
|
Packit |
437b5e |
{
|
|
Packit |
437b5e |
luaL_checktype(L, index, LUA_TTABLE);
|
|
Packit |
437b5e |
ts->tv_sec = optintfield(L, index, "tv_sec", 0);
|
|
Packit |
437b5e |
ts->tv_nsec = optintfield(L, index, "tv_nsec", 0);
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
checkfieldnames(L, index, Stimespec_fields);
|
|
Packit |
437b5e |
}
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
/***
|
|
Packit |
437b5e |
Timespec record.
|
|
Packit |
437b5e |
@table PosixTimespec
|
|
Packit |
437b5e |
@int tv_sec seconds
|
|
Packit |
437b5e |
@int tv_nsec nanoseconds
|
|
Packit |
437b5e |
@see posix.sys.time.PosixTimeval
|
|
Packit |
437b5e |
*/
|
|
Packit |
437b5e |
static int
|
|
Packit |
437b5e |
pushtimespec(lua_State *L, struct timespec *ts)
|
|
Packit |
437b5e |
{
|
|
Packit |
437b5e |
if (!ts)
|
|
Packit |
437b5e |
return lua_pushnil(L), 1;
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
lua_createtable(L, 0, 2);
|
|
Packit |
437b5e |
setintegerfield(ts, tv_sec);
|
|
Packit |
437b5e |
setintegerfield(ts, tv_nsec);
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
settypemetatable("PosixTimespec");
|
|
Packit |
437b5e |
return 1;
|
|
Packit |
437b5e |
}
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
static const char *Stm_fields[] = {
|
|
Packit |
437b5e |
"tm_sec", "tm_min", "tm_hour", "tm_mday", "tm_mon", "tm_year", "tm_wday",
|
|
Packit |
437b5e |
"tm_yday", "tm_isdst",
|
|
Packit |
437b5e |
};
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
static void
|
|
Packit |
437b5e |
totm(lua_State *L, int index, struct tm *t)
|
|
Packit |
437b5e |
{
|
|
Packit |
437b5e |
luaL_checktype(L, index, LUA_TTABLE);
|
|
Packit |
437b5e |
t->tm_sec = optintfield(L, index, "tm_sec", 0);
|
|
Packit |
437b5e |
t->tm_min = optintfield(L, index, "tm_min", 0);
|
|
Packit |
437b5e |
t->tm_hour = optintfield(L, index, "tm_hour", 0);
|
|
Packit |
437b5e |
t->tm_mday = optintfield(L, index, "tm_mday", 0);
|
|
Packit |
437b5e |
t->tm_mon = optintfield(L, index, "tm_mon", 0);
|
|
Packit |
437b5e |
t->tm_year = optintfield(L, index, "tm_year", 0);
|
|
Packit |
437b5e |
t->tm_wday = optintfield(L, index, "tm_wday", 0);
|
|
Packit |
437b5e |
t->tm_yday = optintfield(L, index, "tm_yday", 0);
|
|
Packit |
437b5e |
t->tm_isdst = optintfield(L, index, "tm_isdst", 0);
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
checkfieldnames(L, index, Stm_fields);
|
|
Packit |
437b5e |
}
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
/***
|
|
Packit |
437b5e |
Datetime record.
|
|
Packit |
437b5e |
@table PosixTm
|
|
Packit |
437b5e |
@int tm_sec second [0,60]
|
|
Packit |
437b5e |
@int tm_min minute [0,59]
|
|
Packit |
437b5e |
@int tm_hour hour [0,23]
|
|
Packit |
437b5e |
@int tm_mday day of month [1, 31]
|
|
Packit |
437b5e |
@int tm_mon month of year [0,11]
|
|
Packit |
437b5e |
@int tm_year years since 1900
|
|
Packit |
437b5e |
@int tm_wday day of week [0=Sunday,6]
|
|
Packit |
437b5e |
@int tm_yday day of year [0,365[
|
|
Packit |
437b5e |
@int tm_isdst 0 if daylight savings time is not in effect
|
|
Packit |
437b5e |
*/
|
|
Packit |
437b5e |
static int
|
|
Packit |
437b5e |
pushtm(lua_State *L, struct tm *t)
|
|
Packit |
437b5e |
{
|
|
Packit |
437b5e |
if (!t)
|
|
Packit |
437b5e |
return lua_pushnil(L), 1;
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
lua_createtable(L, 0, 9);
|
|
Packit |
437b5e |
setintegerfield(t, tm_sec);
|
|
Packit |
437b5e |
setintegerfield(t, tm_min);
|
|
Packit |
437b5e |
setintegerfield(t, tm_hour);
|
|
Packit |
437b5e |
setintegerfield(t, tm_mday);
|
|
Packit |
437b5e |
setintegerfield(t, tm_mday);
|
|
Packit |
437b5e |
setintegerfield(t, tm_mon);
|
|
Packit |
437b5e |
setintegerfield(t, tm_year);
|
|
Packit |
437b5e |
setintegerfield(t, tm_wday);
|
|
Packit |
437b5e |
setintegerfield(t, tm_yday);
|
|
Packit |
437b5e |
setintegerfield(t, tm_isdst);
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
settypemetatable("PosixTm");
|
|
Packit |
437b5e |
return 1;
|
|
Packit |
437b5e |
}
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
#if defined _XOPEN_REALTIME && _XOPEN_REALTIME != -1
|
|
Packit |
437b5e |
/***
|
|
Packit |
437b5e |
Find the precision of a clock.
|
|
Packit |
437b5e |
@function clock_getres
|
|
Packit |
437b5e |
@int clk name of clock, one of `CLOCK_REALTIME`, `CLOCK_PROCESS_CPUTIME_ID`,
|
|
Packit |
437b5e |
`CLOCK_MONOTONIC` or `CLOCK_THREAD_CPUTIME_ID`
|
|
Packit |
437b5e |
@treturn[1] PosixTimespec resolution of *clk*, if successful
|
|
Packit |
437b5e |
@return[2] nil
|
|
Packit |
437b5e |
@treturn[2] string error message
|
|
Packit |
437b5e |
@treturn[2] int errnum
|
|
Packit |
437b5e |
@see clock_getres(3)
|
|
Packit |
437b5e |
*/
|
|
Packit |
437b5e |
static int
|
|
Packit |
437b5e |
Pclock_getres(lua_State *L)
|
|
Packit |
437b5e |
{
|
|
Packit |
437b5e |
struct timespec resolution;
|
|
Packit |
437b5e |
int clk = checkint(L, 1);
|
|
Packit |
437b5e |
checknargs(L, 1);
|
|
Packit |
437b5e |
if (clock_getres(clk, &resolution) == -1)
|
|
Packit |
437b5e |
return pusherror(L, "clock_getres");
|
|
Packit |
437b5e |
return pushtimespec(L, &resolution);
|
|
Packit |
437b5e |
}
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
/***
|
|
Packit |
437b5e |
Read a clock.
|
|
Packit |
437b5e |
@function clock_gettime
|
|
Packit |
437b5e |
@int clk name of clock, one of `CLOCK_REALTIME`, `CLOCK_PROCESS_CPUTIME_ID`,
|
|
Packit |
437b5e |
`CLOCK_MONOTONIC` or `CLOCK_THREAD_CPUTIME_ID`
|
|
Packit |
437b5e |
@treturn[1] PosixTimespec current value of *clk*, if successful
|
|
Packit |
437b5e |
@return[2] nil
|
|
Packit |
437b5e |
@treturn[2] string error message
|
|
Packit |
437b5e |
@treturn[2] int errnum
|
|
Packit |
437b5e |
@see clock_gettime(3)
|
|
Packit |
437b5e |
*/
|
|
Packit |
437b5e |
static int
|
|
Packit |
437b5e |
Pclock_gettime(lua_State *L)
|
|
Packit |
437b5e |
{
|
|
Packit |
437b5e |
struct timespec ts;
|
|
Packit |
437b5e |
int clk = checkint(L, 1);
|
|
Packit |
437b5e |
checknargs(L, 1);
|
|
Packit |
437b5e |
if (clock_gettime(clk, &ts) == -1)
|
|
Packit |
437b5e |
return pusherror(L, "clock_gettime");
|
|
Packit |
437b5e |
return pushtimespec(L, &ts);
|
|
Packit |
437b5e |
}
|
|
Packit |
437b5e |
#endif
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
/***
|
|
Packit |
437b5e |
Convert epoch time value to a broken-down UTC time.
|
|
Packit |
437b5e |
@function gmtime
|
|
Packit |
437b5e |
@int t seconds since epoch
|
|
Packit |
437b5e |
@treturn PosixTm broken-down time
|
|
Packit |
437b5e |
@see gmtime(3)
|
|
Packit |
437b5e |
*/
|
|
Packit |
437b5e |
static int
|
|
Packit |
437b5e |
Pgmtime(lua_State *L)
|
|
Packit |
437b5e |
{
|
|
Packit |
437b5e |
struct tm t;
|
|
Packit |
437b5e |
time_t epoch = checkint(L, 1);
|
|
Packit |
437b5e |
checknargs(L, 1);
|
|
Packit |
437b5e |
if (gmtime_r(&epoch, &t) == NULL)
|
|
Packit |
437b5e |
return pusherror(L, "gmtime");
|
|
Packit |
437b5e |
return pushtm(L, &t);
|
|
Packit |
437b5e |
}
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
/***
|
|
Packit |
437b5e |
Convert epoch time value to a broken-down local time.
|
|
Packit |
437b5e |
@function localtime
|
|
Packit |
437b5e |
@int t seconds since epoch
|
|
Packit |
437b5e |
@treturn PosixTm broken-down time
|
|
Packit |
437b5e |
@see localtime(3)
|
|
Packit |
437b5e |
@see mktime
|
|
Packit |
437b5e |
*/
|
|
Packit |
437b5e |
static int
|
|
Packit |
437b5e |
Plocaltime(lua_State *L)
|
|
Packit |
437b5e |
{
|
|
Packit |
437b5e |
struct tm t;
|
|
Packit |
437b5e |
time_t epoch = checkint(L, 1);
|
|
Packit |
437b5e |
checknargs(L, 1);
|
|
Packit |
437b5e |
if (localtime_r(&epoch, &t) == NULL)
|
|
Packit |
437b5e |
return pusherror(L, "localtime");
|
|
Packit |
437b5e |
return pushtm(L, &t);
|
|
Packit |
437b5e |
}
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
/***
|
|
Packit |
437b5e |
Convert a broken-down localtime table into an epoch time.
|
|
Packit |
437b5e |
@function mktime
|
|
Packit |
437b5e |
@tparam PosixTm broken-down localtime
|
|
Packit |
437b5e |
@treturn int seconds since epoch
|
|
Packit |
437b5e |
@see mktime(3)
|
|
Packit |
437b5e |
@see localtime
|
|
Packit |
437b5e |
*/
|
|
Packit |
437b5e |
static int
|
|
Packit |
437b5e |
Pmktime(lua_State *L)
|
|
Packit |
437b5e |
{
|
|
Packit |
437b5e |
struct tm t;
|
|
Packit |
437b5e |
time_t epoch;
|
|
Packit |
437b5e |
checknargs(L, 1);
|
|
Packit |
437b5e |
totm(L, 1, &t);
|
|
Packit |
437b5e |
if ((epoch = mktime(&t)) < 0)
|
|
Packit |
437b5e |
return 0;
|
|
Packit |
437b5e |
return pushintresult(epoch);
|
|
Packit |
437b5e |
}
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
/***
|
|
Packit |
437b5e |
Sleep with nanosecond precision.
|
|
Packit |
437b5e |
@function nanosleep
|
|
Packit |
437b5e |
@tparam PosixTimespec requested sleep time
|
|
Packit |
437b5e |
@treturn[1] int `0` if requested time has elapsed
|
|
Packit |
437b5e |
@return[2] nil
|
|
Packit |
437b5e |
@treturn[2] string error message
|
|
Packit |
437b5e |
@treturn[2] int errnum
|
|
Packit |
437b5e |
@treturn[2] PosixTimespec unslept time remaining, if interrupted
|
|
Packit |
437b5e |
@see nanosleep(2)
|
|
Packit |
437b5e |
@see posix.unistd.sleep
|
|
Packit |
437b5e |
*/
|
|
Packit |
437b5e |
static int
|
|
Packit |
437b5e |
Pnanosleep(lua_State *L)
|
|
Packit |
437b5e |
{
|
|
Packit |
437b5e |
struct timespec req;
|
|
Packit |
437b5e |
struct timespec rem;
|
|
Packit |
437b5e |
int r;
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
totimespec(L, 1, &req;;
|
|
Packit |
437b5e |
checknargs(L, 1);
|
|
Packit |
437b5e |
r = pushresult (L, nanosleep(&req, &rem), "nanosleep");
|
|
Packit |
437b5e |
if (r == 3 && errno == EINTR)
|
|
Packit |
437b5e |
r = r + pushtimespec (L, &rem;;
|
|
Packit |
437b5e |
return r;
|
|
Packit |
437b5e |
}
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
/***
|
|
Packit |
437b5e |
Write a time out according to a format.
|
|
Packit |
437b5e |
@function strftime
|
|
Packit |
437b5e |
@string format specifier with `%` place-holders
|
|
Packit |
437b5e |
@tparam PosixTm tm broken-down local time
|
|
Packit |
437b5e |
@treturn string *format* with place-holders plugged with *tm* values
|
|
Packit |
437b5e |
@see strftime(3)
|
|
Packit |
437b5e |
*/
|
|
Packit |
437b5e |
static int
|
|
Packit |
437b5e |
Pstrftime(lua_State *L)
|
|
Packit |
437b5e |
{
|
|
Packit |
437b5e |
char tmp[256];
|
|
Packit |
437b5e |
const char *fmt = luaL_checkstring(L, 1);
|
|
Packit |
437b5e |
struct tm t;
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
totm(L, 2, &t);
|
|
Packit |
437b5e |
checknargs(L, 2);
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
strftime(tmp, sizeof(tmp), fmt, &t);
|
|
Packit |
437b5e |
return pushstringresult(tmp);
|
|
Packit |
437b5e |
}
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
/***
|
|
Packit |
437b5e |
Parse a date string.
|
|
Packit |
437b5e |
@function strptime
|
|
Packit |
437b5e |
@string s
|
|
Packit |
437b5e |
@string format same as for `strftime`
|
|
Packit |
437b5e |
@usage posix.strptime('20','%d').monthday == 20
|
|
Packit |
437b5e |
@treturn[1] PosixTm broken-down local time
|
|
Packit |
437b5e |
@treturn[1] int next index of first character not parsed as part of the date
|
|
Packit |
437b5e |
@return[2] nil
|
|
Packit |
437b5e |
@see strptime(3)
|
|
Packit |
437b5e |
*/
|
|
Packit |
437b5e |
static int
|
|
Packit |
437b5e |
Pstrptime(lua_State *L)
|
|
Packit |
437b5e |
{
|
|
Packit |
437b5e |
struct tm t;
|
|
Packit |
437b5e |
const char *s = luaL_checkstring(L, 1);
|
|
Packit |
437b5e |
const char *fmt = luaL_checkstring(L, 2);
|
|
Packit |
437b5e |
char *r;
|
|
Packit |
437b5e |
checknargs(L, 2);
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
memset(&t, 0, sizeof(struct tm));
|
|
Packit |
437b5e |
r = strptime(s, fmt, &t);
|
|
Packit |
437b5e |
if (r)
|
|
Packit |
437b5e |
{
|
|
Packit |
437b5e |
pushtm(L, &t);
|
|
Packit |
437b5e |
lua_pushinteger(L, r - s + 1);
|
|
Packit |
437b5e |
return 2;
|
|
Packit |
437b5e |
} else
|
|
Packit |
437b5e |
return 0;
|
|
Packit |
437b5e |
}
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
/***
|
|
Packit |
437b5e |
Get current time.
|
|
Packit |
437b5e |
@function time
|
|
Packit |
437b5e |
@see time(2)
|
|
Packit |
437b5e |
@return time in seconds since epoch
|
|
Packit |
437b5e |
*/
|
|
Packit |
437b5e |
static int
|
|
Packit |
437b5e |
Ptime(lua_State *L)
|
|
Packit |
437b5e |
{
|
|
Packit |
437b5e |
time_t t = time(NULL);
|
|
Packit |
437b5e |
checknargs(L, 0);
|
|
Packit |
437b5e |
if ((time_t) -1 == t)
|
|
Packit |
437b5e |
return pusherror(L, "time");
|
|
Packit |
437b5e |
lua_pushinteger(L, t);
|
|
Packit |
437b5e |
return 1;
|
|
Packit |
437b5e |
}
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
static const luaL_Reg posix_time_fns[] =
|
|
Packit |
437b5e |
{
|
|
Packit |
437b5e |
#if defined _XOPEN_REALTIME && _XOPEN_REALTIME != -1
|
|
Packit |
437b5e |
LPOSIX_FUNC( Pclock_getres ),
|
|
Packit |
437b5e |
LPOSIX_FUNC( Pclock_gettime ),
|
|
Packit |
437b5e |
#endif
|
|
Packit |
437b5e |
LPOSIX_FUNC( Pgmtime ),
|
|
Packit |
437b5e |
LPOSIX_FUNC( Plocaltime ),
|
|
Packit |
437b5e |
LPOSIX_FUNC( Pmktime ),
|
|
Packit |
437b5e |
LPOSIX_FUNC( Pnanosleep ),
|
|
Packit |
437b5e |
LPOSIX_FUNC( Pstrftime ),
|
|
Packit |
437b5e |
LPOSIX_FUNC( Pstrptime ),
|
|
Packit |
437b5e |
LPOSIX_FUNC( Ptime ),
|
|
Packit |
437b5e |
{NULL, NULL}
|
|
Packit |
437b5e |
};
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
LUALIB_API int
|
|
Packit |
437b5e |
luaopen_posix_time(lua_State *L)
|
|
Packit |
437b5e |
{
|
|
Packit |
437b5e |
luaL_register(L, "posix.time", posix_time_fns);
|
|
Packit |
437b5e |
lua_pushliteral(L, "posix.time for " LUA_VERSION " / " PACKAGE_STRING);
|
|
Packit |
437b5e |
lua_setfield(L, -2, "version");
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
#if defined _XOPEN_REALTIME && _XOPEN_REALTIME != -1
|
|
Packit |
437b5e |
LPOSIX_CONST( CLOCK_MONOTONIC );
|
|
Packit |
437b5e |
LPOSIX_CONST( CLOCK_PROCESS_CPUTIME_ID );
|
|
Packit |
437b5e |
LPOSIX_CONST( CLOCK_REALTIME );
|
|
Packit |
437b5e |
LPOSIX_CONST( CLOCK_THREAD_CPUTIME_ID );
|
|
Packit |
437b5e |
#endif
|
|
Packit |
437b5e |
|
|
Packit |
437b5e |
return 1;
|
|
Packit |
437b5e |
}
|