ljx

FORK: LuaJIT with native 5.2 and 5.3 support
git clone https://git.neptards.moe/neptards/ljx.git
Log | Files | Refs | README

lib_os.c (6505B)


      1 /*
      2 ** OS library.
      3 ** Copyright (C) 2005-2016 Mike Pall. See Copyright Notice in luajit.h
      4 **
      5 ** Major portions taken verbatim or adapted from the Lua interpreter.
      6 ** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
      7 */
      8 
      9 #include <errno.h>
     10 #include <time.h>
     11 
     12 #define lib_os_c
     13 #define LUA_LIB
     14 
     15 #include "lua.h"
     16 #include "lauxlib.h"
     17 #include "lualib.h"
     18 
     19 #include "lj_obj.h"
     20 #include "lj_gc.h"
     21 #include "lj_err.h"
     22 #include "lj_buf.h"
     23 #include "lj_str.h"
     24 #include "lj_lib.h"
     25 
     26 #if LJ_TARGET_POSIX
     27 #include <unistd.h>
     28 #else
     29 #include <stdio.h>
     30 #endif
     31 
     32 #if !LJ_TARGET_PSVITA
     33 #include <locale.h>
     34 #endif
     35 
     36 /* ------------------------------------------------------------------------ */
     37 
     38 #define LJLIB_MODULE_os
     39 
     40 LJLIB_CF(os_execute)
     41 {
     42 #if LJ_NO_SYSTEM
     43 #if !LJ_51
     44   errno = ENOSYS;
     45   return luaL_fileresult(L, 0, NULL);
     46 #else
     47     lua_pushinteger(L, -1);
     48       return 1;
     49 #endif
     50 #else
     51   const char *cmd = luaL_optstring(L, 1, NULL);
     52   int stat = system(cmd);
     53 #if !LJ_51
     54   if (cmd)
     55     return luaL_execresult(L, stat);
     56   setboolV(L->top++, 1);
     57 #else
     58   setintV(L->top++, stat);
     59 #endif
     60   return 1;
     61 #endif
     62 }
     63 
     64 LJLIB_CF(os_remove)
     65 {
     66   const char *filename = luaL_checkstring(L, 1);
     67   return luaL_fileresult(L, remove(filename) == 0, filename);
     68 }
     69 
     70 LJLIB_CF(os_rename)
     71 {
     72   const char *fromname = luaL_checkstring(L, 1);
     73   const char *toname = luaL_checkstring(L, 2);
     74   return luaL_fileresult(L, rename(fromname, toname) == 0, fromname);
     75 }
     76 
     77 LJLIB_CF(os_tmpname)
     78 {
     79 #if LJ_TARGET_PS3 || LJ_TARGET_PS4 || LJ_TARGET_PSVITA
     80   lj_err_caller(L, LJ_ERR_OSUNIQF);
     81   return 0;
     82 #else
     83 #if LJ_TARGET_POSIX
     84   char buf[15+1];
     85   int fp;
     86   strcpy(buf, "/tmp/lua_XXXXXX");
     87   fp = mkstemp(buf);
     88   if (fp != -1)
     89     close(fp);
     90   else
     91     lj_err_caller(L, LJ_ERR_OSUNIQF);
     92 #else
     93   char buf[L_tmpnam];
     94   if (tmpnam(buf) == NULL)
     95     lj_err_caller(L, LJ_ERR_OSUNIQF);
     96 #endif
     97   lua_pushstring(L, buf);
     98   return 1;
     99 #endif
    100 }
    101 
    102 LJLIB_CF(os_getenv)
    103 {
    104 #if LJ_TARGET_CONSOLE
    105   lua_pushnil(L);
    106 #else
    107   lua_pushstring(L, getenv(luaL_checkstring(L, 1)));  /* if NULL push nil */
    108 #endif
    109   return 1;
    110 }
    111 
    112 LJLIB_CF(os_exit)
    113 {
    114   int status;
    115   if (L->base < L->top && tvisbool(L->base))
    116     status = boolV(L->base) ? EXIT_SUCCESS : EXIT_FAILURE;
    117   else
    118     status = lj_lib_optint(L, 1, EXIT_SUCCESS);
    119   if (L->base+1 < L->top && tvistruecond(L->base+1))
    120     lua_close(L);
    121   exit(status);
    122   return 0;  /* Unreachable. */
    123 }
    124 
    125 LJLIB_CF(os_clock)
    126 {
    127   setnumV(L->top++, ((lua_Number)clock())*(1.0/(lua_Number)CLOCKS_PER_SEC));
    128   return 1;
    129 }
    130 
    131 /* ------------------------------------------------------------------------ */
    132 
    133 static void setfield(lua_State *L, const char *key, int value)
    134 {
    135   lua_pushinteger(L, value);
    136   lua_setfield(L, -2, key);
    137 }
    138 
    139 static void setboolfield(lua_State *L, const char *key, int value)
    140 {
    141   if (value < 0)  /* undefined? */
    142     return;  /* does not set field */
    143   lua_pushboolean(L, value);
    144   lua_setfield(L, -2, key);
    145 }
    146 
    147 static int getboolfield(lua_State *L, const char *key)
    148 {
    149   int res;
    150   lua_getfield(L, -1, key);
    151   res = lua_isnil(L, -1) ? -1 : lua_toboolean(L, -1);
    152   lua_pop(L, 1);
    153   return res;
    154 }
    155 
    156 static int getfield(lua_State *L, const char *key, int d)
    157 {
    158   int res;
    159   lua_getfield(L, -1, key);
    160   if (lua_isnumber(L, -1)) {
    161     res = (int)lua_tointeger(L, -1);
    162   } else {
    163     if (d < 0)
    164       lj_err_callerv(L, LJ_ERR_OSDATEF, key);
    165     res = d;
    166   }
    167   lua_pop(L, 1);
    168   return res;
    169 }
    170 
    171 LJLIB_CF(os_date)
    172 {
    173   const char *s = luaL_optstring(L, 1, "%c");
    174   time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL));
    175   struct tm *stm;
    176 #if LJ_TARGET_POSIX
    177   struct tm rtm;
    178 #endif
    179   if (*s == '!') {  /* UTC? */
    180     s++;  /* Skip '!' */
    181 #if LJ_TARGET_POSIX
    182     stm = gmtime_r(&t, &rtm);
    183 #else
    184     stm = gmtime(&t);
    185 #endif
    186   } else {
    187 #if LJ_TARGET_POSIX
    188     stm = localtime_r(&t, &rtm);
    189 #else
    190     stm = localtime(&t);
    191 #endif
    192   }
    193   if (stm == NULL) {  /* Invalid date? */
    194     setnilV(L->top++);
    195   } else if (strcmp(s, "*t") == 0) {
    196     lua_createtable(L, 0, 9);  /* 9 = number of fields */
    197     setfield(L, "sec", stm->tm_sec);
    198     setfield(L, "min", stm->tm_min);
    199     setfield(L, "hour", stm->tm_hour);
    200     setfield(L, "day", stm->tm_mday);
    201     setfield(L, "month", stm->tm_mon+1);
    202     setfield(L, "year", stm->tm_year+1900);
    203     setfield(L, "wday", stm->tm_wday+1);
    204     setfield(L, "yday", stm->tm_yday+1);
    205     setboolfield(L, "isdst", stm->tm_isdst);
    206   } else if (*s) {
    207     SBuf *sb = &G(L)->tmpbuf;
    208     MSize sz = 0;
    209     const char *q;
    210     for (q = s; *q; q++)
    211       sz += (*q == '%') ? 30 : 1;  /* Overflow doesn't matter. */
    212     setsbufL(sb, L);
    213     for (;;) {
    214       char *buf = lj_buf_need(sb, sz);
    215       size_t len = strftime(buf, sbufsz(sb), s, stm);
    216       if (len) {
    217 	setstrV(L, L->top++, lj_str_new(L, buf, len));
    218 	lj_gc_check(L);
    219 	break;
    220       }
    221       sz += (sz|1);
    222     }
    223   } else {
    224     setstrV(L, L->top++, &G(L)->strempty);
    225   }
    226   return 1;
    227 }
    228 
    229 LJLIB_CF(os_time)
    230 {
    231   time_t t;
    232   if (lua_isnoneornil(L, 1)) {  /* called without args? */
    233     t = time(NULL);  /* get current time */
    234   } else {
    235     struct tm ts;
    236     luaL_checktype(L, 1, LUA_TTABLE);
    237     lua_settop(L, 1);  /* make sure table is at the top */
    238     ts.tm_sec = getfield(L, "sec", 0);
    239     ts.tm_min = getfield(L, "min", 0);
    240     ts.tm_hour = getfield(L, "hour", 12);
    241     ts.tm_mday = getfield(L, "day", -1);
    242     ts.tm_mon = getfield(L, "month", -1) - 1;
    243     ts.tm_year = getfield(L, "year", -1) - 1900;
    244     ts.tm_isdst = getboolfield(L, "isdst");
    245     t = mktime(&ts);
    246   }
    247   if (t == (time_t)(-1))
    248     lua_pushnil(L);
    249   else
    250     lua_pushnumber(L, (lua_Number)t);
    251   return 1;
    252 }
    253 
    254 LJLIB_CF(os_difftime)
    255 {
    256   lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)),
    257 			     (time_t)(luaL_optnumber(L, 2, (lua_Number)0))));
    258   return 1;
    259 }
    260 
    261 /* ------------------------------------------------------------------------ */
    262 
    263 LJLIB_CF(os_setlocale)
    264 {
    265 #if LJ_TARGET_PSVITA
    266   lua_pushliteral(L, "C");
    267 #else
    268   GCstr *s = lj_lib_optstr(L, 1);
    269   const char *str = s ? strdata(s) : NULL;
    270   int opt = lj_lib_checkopt(L, 2, 6,
    271     "\5ctype\7numeric\4time\7collate\10monetary\1\377\3all");
    272   if (opt == 0) opt = LC_CTYPE;
    273   else if (opt == 1) opt = LC_NUMERIC;
    274   else if (opt == 2) opt = LC_TIME;
    275   else if (opt == 3) opt = LC_COLLATE;
    276   else if (opt == 4) opt = LC_MONETARY;
    277   else if (opt == 6) opt = LC_ALL;
    278   lua_pushstring(L, setlocale(opt, str));
    279 #endif
    280   return 1;
    281 }
    282 
    283 /* ------------------------------------------------------------------------ */
    284 
    285 #include "lj_libdef.h"
    286 
    287 LUALIB_API int luaopen_os(lua_State *L)
    288 {
    289   LJ_LIB_REG(L, LUA_OSLIBNAME, os);
    290   return 1;
    291 }
    292