lib_io.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551
  1. /*
  2. ** I/O library.
  3. ** Copyright (C) 2005-2023 Mike Pall. See Copyright Notice in luajit.h
  4. **
  5. ** Major portions taken verbatim or adapted from the Lua interpreter.
  6. ** Copyright (C) 1994-2011 Lua.org, PUC-Rio. See Copyright Notice in lua.h
  7. */
  8. #include <errno.h>
  9. #include <stdio.h>
  10. #define lib_io_c
  11. #define LUA_LIB
  12. #include "lua.h"
  13. #include "lauxlib.h"
  14. #include "lualib.h"
  15. #include "lj_obj.h"
  16. #include "lj_gc.h"
  17. #include "lj_err.h"
  18. #include "lj_buf.h"
  19. #include "lj_str.h"
  20. #include "lj_state.h"
  21. #include "lj_strfmt.h"
  22. #include "lj_ff.h"
  23. #include "lj_lib.h"
  24. /* Userdata payload for I/O file. */
  25. typedef struct IOFileUD {
  26. FILE *fp; /* File handle. */
  27. uint32_t type; /* File type. */
  28. } IOFileUD;
  29. #define IOFILE_TYPE_FILE 0 /* Regular file. */
  30. #define IOFILE_TYPE_PIPE 1 /* Pipe. */
  31. #define IOFILE_TYPE_STDF 2 /* Standard file handle. */
  32. #define IOFILE_TYPE_MASK 3
  33. #define IOFILE_FLAG_CLOSE 4 /* Close after io.lines() iterator. */
  34. #define IOSTDF_UD(L, id) (&gcref(G(L)->gcroot[(id)])->ud)
  35. #define IOSTDF_IOF(L, id) ((IOFileUD *)uddata(IOSTDF_UD(L, (id))))
  36. /* -- Open/close helpers -------------------------------------------------- */
  37. static IOFileUD *io_tofilep(lua_State *L)
  38. {
  39. if (!(L->base < L->top && tvisudata(L->base) &&
  40. udataV(L->base)->udtype == UDTYPE_IO_FILE))
  41. lj_err_argtype(L, 1, "FILE*");
  42. return (IOFileUD *)uddata(udataV(L->base));
  43. }
  44. static IOFileUD *io_tofile(lua_State *L)
  45. {
  46. IOFileUD *iof = io_tofilep(L);
  47. if (iof->fp == NULL)
  48. lj_err_caller(L, LJ_ERR_IOCLFL);
  49. return iof;
  50. }
  51. static IOFileUD *io_stdfile(lua_State *L, ptrdiff_t id)
  52. {
  53. IOFileUD *iof = IOSTDF_IOF(L, id);
  54. if (iof->fp == NULL)
  55. lj_err_caller(L, LJ_ERR_IOSTDCL);
  56. return iof;
  57. }
  58. static IOFileUD *io_file_new(lua_State *L)
  59. {
  60. IOFileUD *iof = (IOFileUD *)lua_newuserdata(L, sizeof(IOFileUD));
  61. GCudata *ud = udataV(L->top-1);
  62. ud->udtype = UDTYPE_IO_FILE;
  63. /* NOBARRIER: The GCudata is new (marked white). */
  64. setgcrefr(ud->metatable, curr_func(L)->c.env);
  65. iof->fp = NULL;
  66. iof->type = IOFILE_TYPE_FILE;
  67. return iof;
  68. }
  69. static IOFileUD *io_file_open(lua_State *L, const char *mode)
  70. {
  71. const char *fname = strdata(lj_lib_checkstr(L, 1));
  72. IOFileUD *iof = io_file_new(L);
  73. iof->fp = fopen(fname, mode);
  74. if (iof->fp == NULL)
  75. luaL_argerror(L, 1, lj_strfmt_pushf(L, "%s: %s", fname, strerror(errno)));
  76. return iof;
  77. }
  78. static int io_file_close(lua_State *L, IOFileUD *iof)
  79. {
  80. int ok;
  81. if ((iof->type & IOFILE_TYPE_MASK) == IOFILE_TYPE_FILE) {
  82. ok = (fclose(iof->fp) == 0);
  83. } else if ((iof->type & IOFILE_TYPE_MASK) == IOFILE_TYPE_PIPE) {
  84. int stat = -1;
  85. #if LJ_TARGET_POSIX
  86. stat = pclose(iof->fp);
  87. #elif LJ_TARGET_WINDOWS && !LJ_TARGET_XBOXONE && !LJ_TARGET_UWP
  88. stat = _pclose(iof->fp);
  89. #endif
  90. #if LJ_52
  91. iof->fp = NULL;
  92. return luaL_execresult(L, stat);
  93. #else
  94. ok = (stat != -1);
  95. #endif
  96. } else {
  97. lj_assertL((iof->type & IOFILE_TYPE_MASK) == IOFILE_TYPE_STDF,
  98. "close of unknown FILE* type");
  99. setnilV(L->top++);
  100. lua_pushliteral(L, "cannot close standard file");
  101. return 2;
  102. }
  103. iof->fp = NULL;
  104. return luaL_fileresult(L, ok, NULL);
  105. }
  106. /* -- Read/write helpers -------------------------------------------------- */
  107. static int io_file_readnum(lua_State *L, FILE *fp)
  108. {
  109. lua_Number d;
  110. if (fscanf(fp, LUA_NUMBER_SCAN, &d) == 1) {
  111. if (LJ_DUALNUM) {
  112. int32_t i = lj_num2int(d);
  113. if (d == (lua_Number)i && !tvismzero((cTValue *)&d)) {
  114. setintV(L->top++, i);
  115. return 1;
  116. }
  117. }
  118. setnumV(L->top++, d);
  119. return 1;
  120. } else {
  121. setnilV(L->top++);
  122. return 0;
  123. }
  124. }
  125. static int io_file_readline(lua_State *L, FILE *fp, MSize chop)
  126. {
  127. MSize m = LUAL_BUFFERSIZE, n = 0, ok = 0;
  128. char *buf;
  129. for (;;) {
  130. buf = lj_buf_tmp(L, m);
  131. if (fgets(buf+n, m-n, fp) == NULL) break;
  132. n += (MSize)strlen(buf+n);
  133. ok |= n;
  134. if (n && buf[n-1] == '\n') { n -= chop; break; }
  135. if (n >= m - 64) m += m;
  136. }
  137. setstrV(L, L->top++, lj_str_new(L, buf, (size_t)n));
  138. lj_gc_check(L);
  139. return (int)ok;
  140. }
  141. static void io_file_readall(lua_State *L, FILE *fp)
  142. {
  143. MSize m, n;
  144. for (m = LUAL_BUFFERSIZE, n = 0; ; m += m) {
  145. char *buf = lj_buf_tmp(L, m);
  146. n += (MSize)fread(buf+n, 1, m-n, fp);
  147. if (n != m) {
  148. setstrV(L, L->top++, lj_str_new(L, buf, (size_t)n));
  149. lj_gc_check(L);
  150. return;
  151. }
  152. }
  153. }
  154. static int io_file_readlen(lua_State *L, FILE *fp, MSize m)
  155. {
  156. if (m) {
  157. char *buf = lj_buf_tmp(L, m);
  158. MSize n = (MSize)fread(buf, 1, m, fp);
  159. setstrV(L, L->top++, lj_str_new(L, buf, (size_t)n));
  160. lj_gc_check(L);
  161. return n > 0;
  162. } else {
  163. int c = getc(fp);
  164. ungetc(c, fp);
  165. setstrV(L, L->top++, &G(L)->strempty);
  166. return (c != EOF);
  167. }
  168. }
  169. static int io_file_read(lua_State *L, IOFileUD *iof, int start)
  170. {
  171. FILE *fp = iof->fp;
  172. int ok, n, nargs = (int)(L->top - L->base) - start;
  173. clearerr(fp);
  174. if (nargs == 0) {
  175. ok = io_file_readline(L, fp, 1);
  176. n = start+1; /* Return 1 result. */
  177. } else {
  178. /* The results plus the buffers go on top of the args. */
  179. luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments");
  180. ok = 1;
  181. for (n = start; nargs-- && ok; n++) {
  182. if (tvisstr(L->base+n)) {
  183. const char *p = strVdata(L->base+n);
  184. if (p[0] == '*') p++;
  185. if (p[0] == 'n')
  186. ok = io_file_readnum(L, fp);
  187. else if ((p[0] & ~0x20) == 'L')
  188. ok = io_file_readline(L, fp, (p[0] == 'l'));
  189. else if (p[0] == 'a')
  190. io_file_readall(L, fp);
  191. else
  192. lj_err_arg(L, n+1, LJ_ERR_INVFMT);
  193. } else if (tvisnumber(L->base+n)) {
  194. ok = io_file_readlen(L, fp, (MSize)lj_lib_checkint(L, n+1));
  195. } else {
  196. lj_err_arg(L, n+1, LJ_ERR_INVOPT);
  197. }
  198. }
  199. }
  200. if (ferror(fp))
  201. return luaL_fileresult(L, 0, NULL);
  202. if (!ok)
  203. setnilV(L->top-1); /* Replace last result with nil. */
  204. return n - start;
  205. }
  206. static int io_file_write(lua_State *L, IOFileUD *iof, int start)
  207. {
  208. FILE *fp = iof->fp;
  209. cTValue *tv;
  210. int status = 1;
  211. for (tv = L->base+start; tv < L->top; tv++) {
  212. MSize len;
  213. const char *p = lj_strfmt_wstrnum(L, tv, &len);
  214. if (!p)
  215. lj_err_argt(L, (int)(tv - L->base) + 1, LUA_TSTRING);
  216. status = status && (fwrite(p, 1, len, fp) == len);
  217. }
  218. if (LJ_52 && status) {
  219. L->top = L->base+1;
  220. if (start == 0)
  221. setudataV(L, L->base, IOSTDF_UD(L, GCROOT_IO_OUTPUT));
  222. return 1;
  223. }
  224. return luaL_fileresult(L, status, NULL);
  225. }
  226. static int io_file_iter(lua_State *L)
  227. {
  228. GCfunc *fn = curr_func(L);
  229. IOFileUD *iof = uddata(udataV(&fn->c.upvalue[0]));
  230. int n = fn->c.nupvalues - 1;
  231. if (iof->fp == NULL)
  232. lj_err_caller(L, LJ_ERR_IOCLFL);
  233. L->top = L->base;
  234. if (n) { /* Copy upvalues with options to stack. */
  235. lj_state_checkstack(L, (MSize)n);
  236. memcpy(L->top, &fn->c.upvalue[1], n*sizeof(TValue));
  237. L->top += n;
  238. }
  239. n = io_file_read(L, iof, 0);
  240. if (ferror(iof->fp))
  241. lj_err_callermsg(L, strVdata(L->top-2));
  242. if (tvisnil(L->base) && (iof->type & IOFILE_FLAG_CLOSE)) {
  243. io_file_close(L, iof); /* Return values are ignored. */
  244. return 0;
  245. }
  246. return n;
  247. }
  248. static int io_file_lines(lua_State *L)
  249. {
  250. int n = (int)(L->top - L->base);
  251. if (n > LJ_MAX_UPVAL)
  252. lj_err_caller(L, LJ_ERR_UNPACK);
  253. lua_pushcclosure(L, io_file_iter, n);
  254. return 1;
  255. }
  256. /* -- I/O file methods ---------------------------------------------------- */
  257. #define LJLIB_MODULE_io_method
  258. LJLIB_CF(io_method_close)
  259. {
  260. IOFileUD *iof;
  261. if (L->base < L->top) {
  262. iof = io_tofile(L);
  263. } else {
  264. iof = IOSTDF_IOF(L, GCROOT_IO_OUTPUT);
  265. if (iof->fp == NULL)
  266. lj_err_caller(L, LJ_ERR_IOCLFL);
  267. }
  268. return io_file_close(L, iof);
  269. }
  270. LJLIB_CF(io_method_read)
  271. {
  272. return io_file_read(L, io_tofile(L), 1);
  273. }
  274. LJLIB_CF(io_method_write) LJLIB_REC(io_write 0)
  275. {
  276. return io_file_write(L, io_tofile(L), 1);
  277. }
  278. LJLIB_CF(io_method_flush) LJLIB_REC(io_flush 0)
  279. {
  280. return luaL_fileresult(L, fflush(io_tofile(L)->fp) == 0, NULL);
  281. }
  282. #if LJ_32 && defined(__ANDROID__) && __ANDROID_API__ < 24
  283. /* The Android NDK is such an unmatched marvel of engineering. */
  284. extern int fseeko32(FILE *, long int, int) __asm__("fseeko");
  285. extern long int ftello32(FILE *) __asm__("ftello");
  286. #define fseeko(fp, pos, whence) (fseeko32((fp), (pos), (whence)))
  287. #define ftello(fp) (ftello32((fp)))
  288. #endif
  289. LJLIB_CF(io_method_seek)
  290. {
  291. FILE *fp = io_tofile(L)->fp;
  292. int opt = lj_lib_checkopt(L, 2, 1, "\3set\3cur\3end");
  293. int64_t ofs = 0;
  294. cTValue *o;
  295. int res;
  296. if (opt == 0) opt = SEEK_SET;
  297. else if (opt == 1) opt = SEEK_CUR;
  298. else if (opt == 2) opt = SEEK_END;
  299. o = L->base+2;
  300. if (o < L->top) {
  301. if (tvisint(o))
  302. ofs = (int64_t)intV(o);
  303. else if (tvisnum(o))
  304. ofs = (int64_t)numV(o);
  305. else if (!tvisnil(o))
  306. lj_err_argt(L, 3, LUA_TNUMBER);
  307. }
  308. #if LJ_TARGET_POSIX
  309. res = fseeko(fp, ofs, opt);
  310. #elif _MSC_VER >= 1400
  311. res = _fseeki64(fp, ofs, opt);
  312. #elif defined(__MINGW32__)
  313. res = fseeko64(fp, ofs, opt);
  314. #else
  315. res = fseek(fp, (long)ofs, opt);
  316. #endif
  317. if (res)
  318. return luaL_fileresult(L, 0, NULL);
  319. #if LJ_TARGET_POSIX
  320. ofs = ftello(fp);
  321. #elif _MSC_VER >= 1400
  322. ofs = _ftelli64(fp);
  323. #elif defined(__MINGW32__)
  324. ofs = ftello64(fp);
  325. #else
  326. ofs = (int64_t)ftell(fp);
  327. #endif
  328. setint64V(L->top-1, ofs);
  329. return 1;
  330. }
  331. LJLIB_CF(io_method_setvbuf)
  332. {
  333. FILE *fp = io_tofile(L)->fp;
  334. int opt = lj_lib_checkopt(L, 2, -1, "\4full\4line\2no");
  335. size_t sz = (size_t)lj_lib_optint(L, 3, LUAL_BUFFERSIZE);
  336. if (opt == 0) opt = _IOFBF;
  337. else if (opt == 1) opt = _IOLBF;
  338. else if (opt == 2) opt = _IONBF;
  339. return luaL_fileresult(L, setvbuf(fp, NULL, opt, sz) == 0, NULL);
  340. }
  341. LJLIB_CF(io_method_lines)
  342. {
  343. io_tofile(L);
  344. return io_file_lines(L);
  345. }
  346. LJLIB_CF(io_method___gc)
  347. {
  348. IOFileUD *iof = io_tofilep(L);
  349. if (iof->fp != NULL && (iof->type & IOFILE_TYPE_MASK) != IOFILE_TYPE_STDF)
  350. io_file_close(L, iof);
  351. return 0;
  352. }
  353. LJLIB_CF(io_method___tostring)
  354. {
  355. IOFileUD *iof = io_tofilep(L);
  356. if (iof->fp != NULL)
  357. lua_pushfstring(L, "file (%p)", iof->fp);
  358. else
  359. lua_pushliteral(L, "file (closed)");
  360. return 1;
  361. }
  362. LJLIB_PUSH(top-1) LJLIB_SET(__index)
  363. #include "lj_libdef.h"
  364. /* -- I/O library functions ----------------------------------------------- */
  365. #define LJLIB_MODULE_io
  366. LJLIB_PUSH(top-2) LJLIB_SET(!) /* Set environment. */
  367. LJLIB_CF(io_open)
  368. {
  369. const char *fname = strdata(lj_lib_checkstr(L, 1));
  370. GCstr *s = lj_lib_optstr(L, 2);
  371. const char *mode = s ? strdata(s) : "r";
  372. IOFileUD *iof = io_file_new(L);
  373. iof->fp = fopen(fname, mode);
  374. return iof->fp != NULL ? 1 : luaL_fileresult(L, 0, fname);
  375. }
  376. LJLIB_CF(io_popen)
  377. {
  378. #if LJ_TARGET_POSIX || (LJ_TARGET_WINDOWS && !LJ_TARGET_XBOXONE && !LJ_TARGET_UWP)
  379. const char *fname = strdata(lj_lib_checkstr(L, 1));
  380. GCstr *s = lj_lib_optstr(L, 2);
  381. const char *mode = s ? strdata(s) : "r";
  382. IOFileUD *iof = io_file_new(L);
  383. iof->type = IOFILE_TYPE_PIPE;
  384. #if LJ_TARGET_POSIX
  385. fflush(NULL);
  386. iof->fp = popen(fname, mode);
  387. #else
  388. iof->fp = _popen(fname, mode);
  389. #endif
  390. return iof->fp != NULL ? 1 : luaL_fileresult(L, 0, fname);
  391. #else
  392. return luaL_error(L, LUA_QL("popen") " not supported");
  393. #endif
  394. }
  395. LJLIB_CF(io_tmpfile)
  396. {
  397. IOFileUD *iof = io_file_new(L);
  398. #if LJ_TARGET_PS3 || LJ_TARGET_PS4 || LJ_TARGET_PS5 || LJ_TARGET_PSVITA || LJ_TARGET_NX
  399. iof->fp = NULL; errno = ENOSYS;
  400. #else
  401. iof->fp = tmpfile();
  402. #endif
  403. return iof->fp != NULL ? 1 : luaL_fileresult(L, 0, NULL);
  404. }
  405. LJLIB_CF(io_close)
  406. {
  407. return lj_cf_io_method_close(L);
  408. }
  409. LJLIB_CF(io_read)
  410. {
  411. return io_file_read(L, io_stdfile(L, GCROOT_IO_INPUT), 0);
  412. }
  413. LJLIB_CF(io_write) LJLIB_REC(io_write GCROOT_IO_OUTPUT)
  414. {
  415. return io_file_write(L, io_stdfile(L, GCROOT_IO_OUTPUT), 0);
  416. }
  417. LJLIB_CF(io_flush) LJLIB_REC(io_flush GCROOT_IO_OUTPUT)
  418. {
  419. return luaL_fileresult(L, fflush(io_stdfile(L, GCROOT_IO_OUTPUT)->fp) == 0, NULL);
  420. }
  421. static int io_std_getset(lua_State *L, ptrdiff_t id, const char *mode)
  422. {
  423. if (L->base < L->top && !tvisnil(L->base)) {
  424. if (tvisudata(L->base)) {
  425. io_tofile(L);
  426. L->top = L->base+1;
  427. } else {
  428. io_file_open(L, mode);
  429. }
  430. /* NOBARRIER: The standard I/O handles are GC roots. */
  431. setgcref(G(L)->gcroot[id], gcV(L->top-1));
  432. } else {
  433. setudataV(L, L->top++, IOSTDF_UD(L, id));
  434. }
  435. return 1;
  436. }
  437. LJLIB_CF(io_input)
  438. {
  439. return io_std_getset(L, GCROOT_IO_INPUT, "r");
  440. }
  441. LJLIB_CF(io_output)
  442. {
  443. return io_std_getset(L, GCROOT_IO_OUTPUT, "w");
  444. }
  445. LJLIB_CF(io_lines)
  446. {
  447. if (L->base == L->top) setnilV(L->top++);
  448. if (!tvisnil(L->base)) { /* io.lines(fname) */
  449. IOFileUD *iof = io_file_open(L, "r");
  450. iof->type = IOFILE_TYPE_FILE|IOFILE_FLAG_CLOSE;
  451. L->top--;
  452. setudataV(L, L->base, udataV(L->top));
  453. } else { /* io.lines() iterates over stdin. */
  454. setudataV(L, L->base, IOSTDF_UD(L, GCROOT_IO_INPUT));
  455. }
  456. return io_file_lines(L);
  457. }
  458. LJLIB_CF(io_type)
  459. {
  460. cTValue *o = lj_lib_checkany(L, 1);
  461. if (!(tvisudata(o) && udataV(o)->udtype == UDTYPE_IO_FILE))
  462. setnilV(L->top++);
  463. else if (((IOFileUD *)uddata(udataV(o)))->fp != NULL)
  464. lua_pushliteral(L, "file");
  465. else
  466. lua_pushliteral(L, "closed file");
  467. return 1;
  468. }
  469. #include "lj_libdef.h"
  470. /* ------------------------------------------------------------------------ */
  471. static GCobj *io_std_new(lua_State *L, FILE *fp, const char *name)
  472. {
  473. IOFileUD *iof = (IOFileUD *)lua_newuserdata(L, sizeof(IOFileUD));
  474. GCudata *ud = udataV(L->top-1);
  475. ud->udtype = UDTYPE_IO_FILE;
  476. /* NOBARRIER: The GCudata is new (marked white). */
  477. setgcref(ud->metatable, gcV(L->top-3));
  478. iof->fp = fp;
  479. iof->type = IOFILE_TYPE_STDF;
  480. lua_setfield(L, -2, name);
  481. return obj2gco(ud);
  482. }
  483. LUALIB_API int luaopen_io(lua_State *L)
  484. {
  485. LJ_LIB_REG(L, NULL, io_method);
  486. copyTV(L, L->top, L->top-1); L->top++;
  487. lua_setfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE);
  488. LJ_LIB_REG(L, LUA_IOLIBNAME, io);
  489. setgcref(G(L)->gcroot[GCROOT_IO_INPUT], io_std_new(L, stdin, "stdin"));
  490. setgcref(G(L)->gcroot[GCROOT_IO_OUTPUT], io_std_new(L, stdout, "stdout"));
  491. io_std_new(L, stderr, "stderr");
  492. return 1;
  493. }