liblua: Implement write support
Write support (even if it only works on UFS) will be needed for nextboot functionality. Reviewed by: cem, imp Differential Revision: https://reviews.freebsd.org/D14478
This commit is contained in:
parent
061577c5fe
commit
82c85a42b4
@ -35,13 +35,32 @@ FILE *
|
|||||||
fopen(const char *filename, const char *mode)
|
fopen(const char *filename, const char *mode)
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
int fd;
|
int fd, m, o;
|
||||||
FILE *f;
|
FILE *f;
|
||||||
|
|
||||||
if (mode == NULL || mode[0] != 'r')
|
if (mode == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
fd = open(filename, O_RDONLY);
|
switch (*mode++) {
|
||||||
|
case 'r': /* open for reading */
|
||||||
|
m = O_RDONLY;
|
||||||
|
o = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'w': /* open for writing */
|
||||||
|
m = O_WRONLY;
|
||||||
|
/* These are not actually implemented yet */
|
||||||
|
o = O_CREAT | O_TRUNC;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: /* illegal mode */
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*mode == '+')
|
||||||
|
m = O_RDWR;
|
||||||
|
|
||||||
|
fd = open(filename, m | o);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@ -85,6 +104,21 @@ fread(void *ptr, size_t size, size_t count, FILE *stream)
|
|||||||
return (r);
|
return (r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
fwrite(const void *ptr, size_t size, size_t count, FILE *stream)
|
||||||
|
{
|
||||||
|
ssize_t w;
|
||||||
|
|
||||||
|
if (stream == NULL || ptr == NULL)
|
||||||
|
return (0);
|
||||||
|
w = write(stream->fd, ptr, size * count);
|
||||||
|
if (w == -1)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
stream->offset += w;
|
||||||
|
return ((size_t)w);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
fclose(FILE *stream)
|
fclose(FILE *stream)
|
||||||
{
|
{
|
||||||
|
@ -51,6 +51,7 @@ typedef struct DIR
|
|||||||
FILE *fopen(const char *filename, const char *mode);
|
FILE *fopen(const char *filename, const char *mode);
|
||||||
FILE *freopen( const char *filename, const char *mode, FILE *stream);
|
FILE *freopen( const char *filename, const char *mode, FILE *stream);
|
||||||
size_t fread(void *ptr, size_t size, size_t count, FILE *stream);
|
size_t fread(void *ptr, size_t size, size_t count, FILE *stream);
|
||||||
|
size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream);
|
||||||
int fclose(FILE *stream);
|
int fclose(FILE *stream);
|
||||||
int ferror(FILE *stream);
|
int ferror(FILE *stream);
|
||||||
int feof(FILE *stream);
|
int feof(FILE *stream);
|
||||||
|
@ -165,15 +165,24 @@ lua_printc(lua_State *L)
|
|||||||
static int
|
static int
|
||||||
lua_openfile(lua_State *L)
|
lua_openfile(lua_State *L)
|
||||||
{
|
{
|
||||||
const char *str;
|
const char *mode, *str;
|
||||||
|
int nargs;
|
||||||
|
|
||||||
if (lua_gettop(L) != 1) {
|
nargs = lua_gettop(L);
|
||||||
|
if (nargs < 1 || nargs > 2) {
|
||||||
lua_pushnil(L);
|
lua_pushnil(L);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
str = lua_tostring(L, 1);
|
str = lua_tostring(L, 1);
|
||||||
|
mode = "r";
|
||||||
FILE * f = fopen(str, "r");
|
if (nargs > 1) {
|
||||||
|
mode = lua_tostring(L, 2);
|
||||||
|
if (mode == NULL) {
|
||||||
|
lua_pushnil(L);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FILE * f = fopen(str, mode);
|
||||||
if (f != NULL) {
|
if (f != NULL) {
|
||||||
FILE ** ptr = (FILE**)lua_newuserdata(L, sizeof(FILE**));
|
FILE ** ptr = (FILE**)lua_newuserdata(L, sizeof(FILE**));
|
||||||
*ptr = f;
|
*ptr = f;
|
||||||
@ -237,6 +246,61 @@ lua_readfile(lua_State *L)
|
|||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Implements io.write(file, ...)
|
||||||
|
* Any number of string and number arguments may be passed to it,
|
||||||
|
* and it will return the number of bytes written, or nil, an error string, and
|
||||||
|
* the errno.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
lua_writefile(lua_State *L)
|
||||||
|
{
|
||||||
|
FILE **f;
|
||||||
|
const char *buf;
|
||||||
|
int i, nargs;
|
||||||
|
size_t bufsz, w, wrsz;
|
||||||
|
|
||||||
|
buf = NULL;
|
||||||
|
bufsz = 0;
|
||||||
|
w = 0;
|
||||||
|
wrsz = 0;
|
||||||
|
nargs = lua_gettop(L);
|
||||||
|
if (nargs < 2) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return luaL_fileresult(L, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
f = (FILE**)lua_touserdata(L, 1);
|
||||||
|
|
||||||
|
if (f == NULL || *f == NULL) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return luaL_fileresult(L, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do a validation pass first */
|
||||||
|
for (i = 0; i < nargs - 1; i++) {
|
||||||
|
/*
|
||||||
|
* With Lua's API, lua_isstring really checks if the argument
|
||||||
|
* is a string or a number. The latter will be implicitly
|
||||||
|
* converted to a string by our later call to lua_tolstring.
|
||||||
|
*/
|
||||||
|
if (!lua_isstring(L, i + 2)) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return luaL_fileresult(L, 0, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i = 0; i < nargs - 1; i++) {
|
||||||
|
/* We've already validated; there's no chance of failure */
|
||||||
|
buf = lua_tolstring(L, i + 2, &bufsz);
|
||||||
|
wrsz = fwrite(buf, 1, bufsz, *f);
|
||||||
|
if (wrsz < bufsz)
|
||||||
|
return luaL_fileresult(L, 0, NULL);
|
||||||
|
w += wrsz;
|
||||||
|
}
|
||||||
|
lua_pushinteger(L, w);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
#define REG_SIMPLE(n) { #n, lua_ ## n }
|
#define REG_SIMPLE(n) { #n, lua_ ## n }
|
||||||
static const struct luaL_Reg loaderlib[] = {
|
static const struct luaL_Reg loaderlib[] = {
|
||||||
REG_SIMPLE(delay),
|
REG_SIMPLE(delay),
|
||||||
@ -257,6 +321,7 @@ static const struct luaL_Reg iolib[] = {
|
|||||||
REG_SIMPLE(ischar),
|
REG_SIMPLE(ischar),
|
||||||
{ "open", lua_openfile },
|
{ "open", lua_openfile },
|
||||||
{ "read", lua_readfile },
|
{ "read", lua_readfile },
|
||||||
|
{ "write", lua_writefile },
|
||||||
{ NULL, NULL },
|
{ NULL, NULL },
|
||||||
};
|
};
|
||||||
#undef REG_SIMPLE
|
#undef REG_SIMPLE
|
||||||
|
@ -286,6 +286,9 @@ extern int open(const char *, int);
|
|||||||
#define O_RDONLY 0x0
|
#define O_RDONLY 0x0
|
||||||
#define O_WRONLY 0x1
|
#define O_WRONLY 0x1
|
||||||
#define O_RDWR 0x2
|
#define O_RDWR 0x2
|
||||||
|
/* NOT IMPLEMENTED */
|
||||||
|
#define O_CREAT 0x0200 /* create if nonexistent */
|
||||||
|
#define O_TRUNC 0x0400 /* truncate to zero length */
|
||||||
extern int close(int);
|
extern int close(int);
|
||||||
extern void closeall(void);
|
extern void closeall(void);
|
||||||
extern ssize_t read(int, void *, size_t);
|
extern ssize_t read(int, void *, size_t);
|
||||||
|
Loading…
Reference in New Issue
Block a user