src/lib_io.c - luajit-2.0-src

Data types defined

Functions defined

Macros defined

Source code

  1. /*
  2. ** I/O library.
  3. ** Copyright (C) 2005-2015 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 FILE *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->fp;
  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
  88.     stat = _pclose(iof->fp);
  89. #else
  90.     lua_assert(0);
  91.     return 0;
  92. #endif
  93. #if LJ_52
  94.     iof->fp = NULL;
  95.     return luaL_execresult(L, stat);
  96. #else
  97.     ok = (stat != -1);
  98. #endif
  99.   } else {
  100.     lua_assert((iof->type & IOFILE_TYPE_MASK) == IOFILE_TYPE_STDF);
  101.     setnilV(L->top++);
  102.     lua_pushliteral(L, "cannot close standard file");
  103.     return 2;
  104.   }
  105.   iof->fp = NULL;
  106.   return luaL_fileresult(L, ok, NULL);
  107. }

  108. /* -- Read/write helpers -------------------------------------------------- */

  109. static int io_file_readnum(lua_State *L, FILE *fp)
  110. {
  111.   lua_Number d;
  112.   if (fscanf(fp, LUA_NUMBER_SCAN, &d) == 1) {
  113.     if (LJ_DUALNUM) {
  114.       int32_t i = lj_num2int(d);
  115.       if (d == (lua_Number)i && !tvismzero((cTValue *)&d)) {
  116.         setintV(L->top++, i);
  117.         return 1;
  118.       }
  119.     }
  120.     setnumV(L->top++, d);
  121.     return 1;
  122.   } else {
  123.     setnilV(L->top++);
  124.     return 0;
  125.   }
  126. }

  127. static int io_file_readline(lua_State *L, FILE *fp, MSize chop)
  128. {
  129.   MSize m = LUAL_BUFFERSIZE, n = 0, ok = 0;
  130.   char *buf;
  131.   for (;;) {
  132.     buf = lj_buf_tmp(L, m);
  133.     if (fgets(buf+n, m-n, fp) == NULL) break;
  134.     n += (MSize)strlen(buf+n);
  135.     ok |= n;
  136.     if (n && buf[n-1] == '\n') { n -= chop; break; }
  137.     if (n >= m - 64) m += m;
  138.   }
  139.   setstrV(L, L->top++, lj_str_new(L, buf, (size_t)n));
  140.   lj_gc_check(L);
  141.   return (int)ok;
  142. }

  143. static void io_file_readall(lua_State *L, FILE *fp)
  144. {
  145.   MSize m, n;
  146.   for (m = LUAL_BUFFERSIZE, n = 0; ; m += m) {
  147.     char *buf = lj_buf_tmp(L, m);
  148.     n += (MSize)fread(buf+n, 1, m-n, fp);
  149.     if (n != m) {
  150.       setstrV(L, L->top++, lj_str_new(L, buf, (size_t)n));
  151.       lj_gc_check(L);
  152.       return;
  153.     }
  154.   }
  155. }

  156. static int io_file_readlen(lua_State *L, FILE *fp, MSize m)
  157. {
  158.   if (m) {
  159.     char *buf = lj_buf_tmp(L, m);
  160.     MSize n = (MSize)fread(buf, 1, m, fp);
  161.     setstrV(L, L->top++, lj_str_new(L, buf, (size_t)n));
  162.     lj_gc_check(L);
  163.     return (n > 0 || m == 0);
  164.   } else {
  165.     int c = getc(fp);
  166.     ungetc(c, fp);
  167.     setstrV(L, L->top++, &G(L)->strempty);
  168.     return (c != EOF);
  169.   }
  170. }

  171. static int io_file_read(lua_State *L, FILE *fp, int start)
  172. {
  173.   int ok, n, nargs = (int)(L->top - L->base) - start;
  174.   clearerr(fp);
  175.   if (nargs == 0) {
  176.     ok = io_file_readline(L, fp, 1);
  177.     n = start+1/* Return 1 result. */
  178.   } else {
  179.     /* The results plus the buffers go on top of the args. */
  180.     luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments");
  181.     ok = 1;
  182.     for (n = start; nargs-- && ok; n++) {
  183.       if (tvisstr(L->base+n)) {
  184.         const char *p = strVdata(L->base+n);
  185.         if (p[0] != '*')
  186.           lj_err_arg(L, n+1, LJ_ERR_INVOPT);
  187.         if (p[1] == 'n')
  188.           ok = io_file_readnum(L, fp);
  189.         else if ((p[1] & ~0x20) == 'L')
  190.           ok = io_file_readline(L, fp, (p[1] == 'l'));
  191.         else if (p[1] == 'a')
  192.           io_file_readall(L, fp);
  193.         else
  194.           lj_err_arg(L, n+1, LJ_ERR_INVFMT);
  195.       } else if (tvisnumber(L->base+n)) {
  196.         ok = io_file_readlen(L, fp, (MSize)lj_lib_checkint(L, n+1));
  197.       } else {
  198.         lj_err_arg(L, n+1, LJ_ERR_INVOPT);
  199.       }
  200.     }
  201.   }
  202.   if (ferror(fp))
  203.     return luaL_fileresult(L, 0, NULL);
  204.   if (!ok)
  205.     setnilV(L->top-1);  /* Replace last result with nil. */
  206.   return n - start;
  207. }

  208. static int io_file_write(lua_State *L, FILE *fp, int start)
  209. {
  210.   cTValue *tv;
  211.   int status = 1;
  212.   for (tv = L->base+start; tv < L->top; tv++) {
  213.     char buf[STRFMT_MAXBUF_NUM];
  214.     MSize len;
  215.     const char *p = lj_strfmt_wstrnum(buf, tv, &len);
  216.     if (!p)
  217.       lj_err_argt(L, (int)(tv - L->base) + 1, LUA_TSTRING);
  218.     status = status && (fwrite(p, 1, len, fp) == len);
  219.   }
  220.   if (LJ_52 && status) {
  221.     L->top = L->base+1;
  222.     if (start == 0)
  223.       setudataV(L, L->base, IOSTDF_UD(L, GCROOT_IO_OUTPUT));
  224.     return 1;
  225.   }
  226.   return luaL_fileresult(L, status, NULL);
  227. }

  228. static int io_file_iter(lua_State *L)
  229. {
  230.   GCfunc *fn = curr_func(L);
  231.   IOFileUD *iof = uddata(udataV(&fn->c.upvalue[0]));
  232.   int n = fn->c.nupvalues - 1;
  233.   if (iof->fp == NULL)
  234.     lj_err_caller(L, LJ_ERR_IOCLFL);
  235.   L->top = L->base;
  236.   if (n) {  /* Copy upvalues with options to stack. */
  237.     if (n > LUAI_MAXCSTACK)
  238.       lj_err_caller(L, LJ_ERR_STKOV);
  239.     lj_state_checkstack(L, (MSize)n);
  240.     memcpy(L->top, &fn->c.upvalue[1], n*sizeof(TValue));
  241.     L->top += n;
  242.   }
  243.   n = io_file_read(L, iof->fp, 0);
  244.   if (ferror(iof->fp))
  245.     lj_err_callermsg(L, strVdata(L->top-2));
  246.   if (tvisnil(L->base) && (iof->type & IOFILE_FLAG_CLOSE)) {
  247.     io_file_close(L, iof);  /* Return values are ignored. */
  248.     return 0;
  249.   }
  250.   return n;
  251. }

  252. /* -- I/O file methods ---------------------------------------------------- */

  253. #define LJLIB_MODULE_io_method

  254. LJLIB_CF(io_method_close)
  255. {
  256.   IOFileUD *iof = L->base < L->top ? io_tofile(L) :
  257.                   IOSTDF_IOF(L, GCROOT_IO_OUTPUT);
  258.   return io_file_close(L, iof);
  259. }

  260. LJLIB_CF(io_method_read)
  261. {
  262.   return io_file_read(L, io_tofile(L)->fp, 1);
  263. }

  264. LJLIB_CF(io_method_write)                LJLIB_REC(io_write 0)
  265. {
  266.   return io_file_write(L, io_tofile(L)->fp, 1);
  267. }

  268. LJLIB_CF(io_method_flush)                LJLIB_REC(io_flush 0)
  269. {
  270.   return luaL_fileresult(L, fflush(io_tofile(L)->fp) == 0, NULL);
  271. }

  272. LJLIB_CF(io_method_seek)
  273. {
  274.   FILE *fp = io_tofile(L)->fp;
  275.   int opt = lj_lib_checkopt(L, 2, 1, "\3set\3cur\3end");
  276.   int64_t ofs = 0;
  277.   cTValue *o;
  278.   int res;
  279.   if (opt == 0) opt = SEEK_SET;
  280.   else if (opt == 1) opt = SEEK_CUR;
  281.   else if (opt == 2) opt = SEEK_END;
  282.   o = L->base+2;
  283.   if (o < L->top) {
  284.     if (tvisint(o))
  285.       ofs = (int64_t)intV(o);
  286.     else if (tvisnum(o))
  287.       ofs = (int64_t)numV(o);
  288.     else if (!tvisnil(o))
  289.       lj_err_argt(L, 3, LUA_TNUMBER);
  290.   }
  291. #if LJ_TARGET_POSIX
  292.   res = fseeko(fp, ofs, opt);
  293. #elif _MSC_VER >= 1400
  294.   res = _fseeki64(fp, ofs, opt);
  295. #elif defined(__MINGW32__)
  296.   res = fseeko64(fp, ofs, opt);
  297. #else
  298.   res = fseek(fp, (long)ofs, opt);
  299. #endif
  300.   if (res)
  301.     return luaL_fileresult(L, 0, NULL);
  302. #if LJ_TARGET_POSIX
  303.   ofs = ftello(fp);
  304. #elif _MSC_VER >= 1400
  305.   ofs = _ftelli64(fp);
  306. #elif defined(__MINGW32__)
  307.   ofs = ftello64(fp);
  308. #else
  309.   ofs = (int64_t)ftell(fp);
  310. #endif
  311.   setint64V(L->top-1, ofs);
  312.   return 1;
  313. }

  314. LJLIB_CF(io_method_setvbuf)
  315. {
  316.   FILE *fp = io_tofile(L)->fp;
  317.   int opt = lj_lib_checkopt(L, 2, -1, "\4full\4line\2no");
  318.   size_t sz = (size_t)lj_lib_optint(L, 3, LUAL_BUFFERSIZE);
  319.   if (opt == 0) opt = _IOFBF;
  320.   else if (opt == 1) opt = _IOLBF;
  321.   else if (opt == 2) opt = _IONBF;
  322.   return luaL_fileresult(L, setvbuf(fp, NULL, opt, sz) == 0, NULL);
  323. }

  324. LJLIB_CF(io_method_lines)
  325. {
  326.   io_tofile(L);
  327.   lua_pushcclosure(L, io_file_iter, (int)(L->top - L->base));
  328.   return 1;
  329. }

  330. LJLIB_CF(io_method___gc)
  331. {
  332.   IOFileUD *iof = io_tofilep(L);
  333.   if (iof->fp != NULL && (iof->type & IOFILE_TYPE_MASK) != IOFILE_TYPE_STDF)
  334.     io_file_close(L, iof);
  335.   return 0;
  336. }

  337. LJLIB_CF(io_method___tostring)
  338. {
  339.   IOFileUD *iof = io_tofilep(L);
  340.   if (iof->fp != NULL)
  341.     lua_pushfstring(L, "file (%p)", iof->fp);
  342.   else
  343.     lua_pushliteral(L, "file (closed)");
  344.   return 1;
  345. }

  346. LJLIB_PUSH(top-1) LJLIB_SET(__index)

  347. #include "lj_libdef.h"

  348. /* -- I/O library functions ----------------------------------------------- */

  349. #define LJLIB_MODULE_io

  350. LJLIB_PUSH(top-2) LJLIB_SET(!)  /* Set environment. */

  351. LJLIB_CF(io_open)
  352. {
  353.   const char *fname = strdata(lj_lib_checkstr(L, 1));
  354.   GCstr *s = lj_lib_optstr(L, 2);
  355.   const char *mode = s ? strdata(s) : "r";
  356.   IOFileUD *iof = io_file_new(L);
  357.   iof->fp = fopen(fname, mode);
  358.   return iof->fp != NULL ? 1 : luaL_fileresult(L, 0, fname);
  359. }

  360. LJLIB_CF(io_popen)
  361. {
  362. #if LJ_TARGET_POSIX || LJ_TARGET_WINDOWS
  363.   const char *fname = strdata(lj_lib_checkstr(L, 1));
  364.   GCstr *s = lj_lib_optstr(L, 2);
  365.   const char *mode = s ? strdata(s) : "r";
  366.   IOFileUD *iof = io_file_new(L);
  367.   iof->type = IOFILE_TYPE_PIPE;
  368. #if LJ_TARGET_POSIX
  369.   fflush(NULL);
  370.   iof->fp = popen(fname, mode);
  371. #else
  372.   iof->fp = _popen(fname, mode);
  373. #endif
  374.   return iof->fp != NULL ? 1 : luaL_fileresult(L, 0, fname);
  375. #else
  376.   return luaL_error(L, LUA_QL("popen") " not supported");
  377. #endif
  378. }

  379. LJLIB_CF(io_tmpfile)
  380. {
  381.   IOFileUD *iof = io_file_new(L);
  382. #if LJ_TARGET_PS3 || LJ_TARGET_PS4 || LJ_TARGET_PSVITA
  383.   iof->fp = NULL; errno = ENOSYS;
  384. #else
  385.   iof->fp = tmpfile();
  386. #endif
  387.   return iof->fp != NULL ? 1 : luaL_fileresult(L, 0, NULL);
  388. }

  389. LJLIB_CF(io_close)
  390. {
  391.   return lj_cf_io_method_close(L);
  392. }

  393. LJLIB_CF(io_read)
  394. {
  395.   return io_file_read(L, io_stdfile(L, GCROOT_IO_INPUT), 0);
  396. }

  397. LJLIB_CF(io_write)                LJLIB_REC(io_write GCROOT_IO_OUTPUT)
  398. {
  399.   return io_file_write(L, io_stdfile(L, GCROOT_IO_OUTPUT), 0);
  400. }

  401. LJLIB_CF(io_flush)                LJLIB_REC(io_flush GCROOT_IO_OUTPUT)
  402. {
  403.   return luaL_fileresult(L, fflush(io_stdfile(L, GCROOT_IO_OUTPUT)) == 0, NULL);
  404. }

  405. static int io_std_getset(lua_State *L, ptrdiff_t id, const char *mode)
  406. {
  407.   if (L->base < L->top && !tvisnil(L->base)) {
  408.     if (tvisudata(L->base)) {
  409.       io_tofile(L);
  410.       L->top = L->base+1;
  411.     } else {
  412.       io_file_open(L, mode);
  413.     }
  414.     /* NOBARRIER: The standard I/O handles are GC roots. */
  415.     setgcref(G(L)->gcroot[id], gcV(L->top-1));
  416.   } else {
  417.     setudataV(L, L->top++, IOSTDF_UD(L, id));
  418.   }
  419.   return 1;
  420. }

  421. LJLIB_CF(io_input)
  422. {
  423.   return io_std_getset(L, GCROOT_IO_INPUT, "r");
  424. }

  425. LJLIB_CF(io_output)
  426. {
  427.   return io_std_getset(L, GCROOT_IO_OUTPUT, "w");
  428. }

  429. LJLIB_CF(io_lines)
  430. {
  431.   if (L->base == L->top) setnilV(L->top++);
  432.   if (!tvisnil(L->base)) {  /* io.lines(fname) */
  433.     IOFileUD *iof = io_file_open(L, "r");
  434.     iof->type = IOFILE_TYPE_FILE|IOFILE_FLAG_CLOSE;
  435.     L->top--;
  436.     setudataV(L, L->base, udataV(L->top));
  437.   } else/* io.lines() iterates over stdin. */
  438.     setudataV(L, L->base, IOSTDF_UD(L, GCROOT_IO_INPUT));
  439.   }
  440.   lua_pushcclosure(L, io_file_iter, (int)(L->top - L->base));
  441.   return 1;
  442. }

  443. LJLIB_CF(io_type)
  444. {
  445.   cTValue *o = lj_lib_checkany(L, 1);
  446.   if (!(tvisudata(o) && udataV(o)->udtype == UDTYPE_IO_FILE))
  447.     setnilV(L->top++);
  448.   else if (((IOFileUD *)uddata(udataV(o)))->fp != NULL)
  449.     lua_pushliteral(L, "file");
  450.   else
  451.     lua_pushliteral(L, "closed file");
  452.   return 1;
  453. }

  454. #include "lj_libdef.h"

  455. /* ------------------------------------------------------------------------ */

  456. static GCobj *io_std_new(lua_State *L, FILE *fp, const char *name)
  457. {
  458.   IOFileUD *iof = (IOFileUD *)lua_newuserdata(L, sizeof(IOFileUD));
  459.   GCudata *ud = udataV(L->top-1);
  460.   ud->udtype = UDTYPE_IO_FILE;
  461.   /* NOBARRIER: The GCudata is new (marked white). */
  462.   setgcref(ud->metatable, gcV(L->top-3));
  463.   iof->fp = fp;
  464.   iof->type = IOFILE_TYPE_STDF;
  465.   lua_setfield(L, -2, name);
  466.   return obj2gco(ud);
  467. }

  468. LUALIB_API int luaopen_io(lua_State *L)
  469. {
  470.   LJ_LIB_REG(L, NULL, io_method);
  471.   copyTV(L, L->top, L->top-1); L->top++;
  472.   lua_setfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE);
  473.   LJ_LIB_REG(L, LUA_IOLIBNAME, io);
  474.   setgcref(G(L)->gcroot[GCROOT_IO_INPUT], io_std_new(L, stdin, "stdin"));
  475.   setgcref(G(L)->gcroot[GCROOT_IO_OUTPUT], io_std_new(L, stdout, "stdout"));
  476.   io_std_new(L, stderr, "stderr");
  477.   return 1;
  478. }