root/lib_io.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. io_tofilep
  2. io_tofile
  3. io_stdfile
  4. io_file_new
  5. io_file_open
  6. io_file_close
  7. io_file_readnum
  8. io_file_readline
  9. io_file_readall
  10. io_file_readlen
  11. io_file_read
  12. io_file_write
  13. io_file_iter
  14. io_file_lines
  15. LJLIB_CF
  16. LJLIB_CF
  17. LJLIB_CF
  18. LJLIB_CF
  19. LJLIB_CF
  20. LJLIB_CF
  21. LJLIB_CF
  22. LJLIB_CF
  23. LJLIB_CF
  24. LJLIB_PUSH
  25. LJLIB_CF
  26. LJLIB_CF
  27. LJLIB_CF
  28. LJLIB_CF
  29. LJLIB_CF
  30. LJLIB_CF
  31. io_std_getset
  32. LJLIB_CF
  33. LJLIB_CF
  34. LJLIB_CF
  35. LJLIB_CF
  36. io_std_new
  37. luaopen_io

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

/* [<][>][^][v][top][bottom][index][help] */