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