File: stdio.c

package info (click to toggle)
lua-posix 36.3-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,720 kB
  • sloc: ansic: 5,462; makefile: 21; sh: 6
file content (197 lines) | stat: -rw-r--r-- 4,953 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
/*
 * POSIX library for Lua 5.1, 5.2, 5.3 & 5.4.
 * Copyright (C) 2013-2025 Gary V. Vaughan
 * Copyright (C) 2010-2013 Reuben Thomas <rrt@sc3d.org>
 * Copyright (C) 2008-2010 Natanael Copa <natanael.copa@gmail.com>
 * Clean up and bug fixes by Leo Razoumov <slonik.az@gmail.com> 2006-10-11
 * Luiz Henrique de Figueiredo <lhf@tecgraf.puc-rio.br> 07 Apr 2006 23:17:49
 * Based on original by Claudio Terra for Lua 3.x.
 * With contributions by Roberto Ierusalimschy.
 * With documentation from Steve Donovan 2012
 */
/***
 A few Standard I/O functions not already in Lua core.

@module posix.stdio
*/

#include <stdio.h>

#include "_helpers.c"

/***
Name of controlling terminal.
@function ctermid
@treturn string controlling terminal for current process
@see ctermid(3)
*/
static int
Pctermid(lua_State *L)
{
	char b[L_ctermid];
	checknargs(L, 0);
	return pushstringresult(ctermid(b));
}


/***
File descriptor corresponding to a Lua file object.
@function fileno
@tparam file file Lua file object
@treturn[1] int file descriptor for *file*, if successful
@return[2] nil
@treturn[2] string error message
@treturn[2] int errnum
@see fileno(3)
@usage
local stdio = require "posix.stdio"
local unistd = require "posix.unistd"
assert (stdio.fileno (io.stdout) == unistd.STDOUT_FILENO)
*/
static int
Pfileno(lua_State *L)
{
	FILE *f = *(FILE**) luaL_checkudata(L, 1, LUA_FILEHANDLE);
	checknargs(L, 1);
	return pushresult(L, fileno(f), NULL);
}


/* This helper function is adapted from Lua 5.3's liolib.c */
static int
stdio_fclose (lua_State *L) {
	int res = -1;    
	luaL_Stream *p = ((luaL_Stream *)luaL_checkudata(L, 1, LUA_FILEHANDLE));
	if (p->f == NULL)
		return 0;
	res = fclose(p->f);
	p->f = NULL;
	return luaL_fileresult(L, (res == 0), NULL);
}

/* This function could be used more generally; see */
static int
pushfile (lua_State *L, int fd, const char *mode) {
	luaL_Stream *p = (luaL_Stream *)lua_newuserdata(L, sizeof(luaL_Stream));
	luaL_getmetatable(L, LUA_FILEHANDLE);
	lua_setmetatable(L, -2);
#if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM == 501
	/* PUC-Rio Lua uses lconfig_h as include guard for luaconf.h,
	   LuaJIT uses luaconf_h. If you use PUC-Rio's include files
	   but LuaJIT's library, you're on your own here!  */
#  if !defined(luaconf_h)
	lua_createtable(L, 0, 1);
	lua_pushcfunction(L, stdio_fclose);
	lua_setfield(L, -2, "__close");
	lua_setfenv(L, -2);  /* set fenv for 'fdopen' */
#  endif
#endif
	p->closef = stdio_fclose;
	p->f = fdopen(fd, mode);
	return p->f != NULL;
}

/***
Create a Lua file object from a file descriptor.
@function fdopen
@tparam int fd file descriptor
@tparam string mode the mode in which to open the file descriptor
@treturn[1] file Lua file object *fd*, if successful
@return[2] nil
@treturn[2] string error message
@treturn[2] int errnum
@see fdopen(3)
@usage
local fdopen = require "posix.stdio".fdopen
local STDOUT_FILENO = require "posix.unistd".STDOUT_FILENO
stdout = fdopen (STDOUT_FILENO, "w")
*/
static int
Pfdopen(lua_State *L)	/** fdopen(fd, mode) */
{
	int fd = checkint(L, 1);
	const char *mode = luaL_checkstring(L, 2);
	checknargs(L, 2);
	if (!pushfile(L, fd, mode))
		return pusherror(L, "fdopen");
	return 1;
}

/***
Change the name or location of a file
@function rename
@tparam string oldpath
@tparam string newpath
@treturn[1] int `0`, if successful
@return[2] nil
@treturn[2] string error message
@treturn[2] int errnum
@see rename(2)
@usage
local ok, errmsg = P.rename (oldpath, newpath)
if not ok then error (errmsg) end
*/
static int
Prename(lua_State *L)	/** rename(oldpath, newpath) */
{
	const char *oldpath = luaL_checkstring(L, 1);
	const char *newpath = luaL_checkstring(L, 2);
	checknargs(L, 2);
	return pushresult(L, rename(oldpath, newpath), NULL);
}


static const luaL_Reg posix_stdio_fns[] =
{
	LPOSIX_FUNC( Pctermid		),
	LPOSIX_FUNC( Pfileno		),
	LPOSIX_FUNC( Pfdopen		),
	LPOSIX_FUNC( Prename		),
	{NULL, NULL}
};


/***
Constants.
@section constants
*/

/***
Stdio constants.
Any constants not available in the underlying system will be `nil` valued.
@table posix.stdio
@int _IOFBF fully buffered
@int _IOLBF line buffered
@int _IONBF unbuffered
@int BUFSIZ size of buffer
@int EOF end of file
@int FOPEN_MAX maximum number of open files
@int FILENAME_MAX maximum length of filename
@usage
  -- Print stdio constants supported on this host.
  for name, value in pairs (require "posix.stdio") do
    if type (value) == "number" then
      print (name, value)
     end
  end
*/

LUALIB_API int
luaopen_posix_stdio(lua_State *L)
{
	luaL_newlib(L, posix_stdio_fns);
	lua_pushstring(L, LPOSIX_VERSION_STRING("stdio"));
	lua_setfield(L, -2, "version");

	/* stdio.h constants */
	/* Those that are omitted already have a Lua interface, or alternative. */
	LPOSIX_CONST( _IOFBF		);
	LPOSIX_CONST( _IOLBF		);
	LPOSIX_CONST( _IONBF		);
	LPOSIX_CONST( BUFSIZ		);
	LPOSIX_CONST( EOF		);
	LPOSIX_CONST( FOPEN_MAX		);
	LPOSIX_CONST( FILENAME_MAX	);

	return 1;
}