/*
* POSIX library for Lua 5.1, 5.2 & 5.3.
* (c) Gary V. Vaughan <gary@vaughan.pe>, 2013-2015
* (c) Reuben Thomas <rrt@sc3d.org> 2010-2013
* (c) Natanael Copa <natanael.copa@gmail.com> 2008-2010
* 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
*/
/***
File Control.
Low-level control over file descriptors, including creating new file
descriptors with `open`.
@module posix.fcntl
*/
#include <config.h>
#include <fcntl.h>
#include "_helpers.c"
/* Darwin fails to define O_RSYNC. */
#ifndef O_RSYNC
#define O_RSYNC 0
#endif
/* FreeBSD 10 fails to define O_DSYNC. */
#ifndef O_DSYNC
#define O_DSYNC 0
#endif
/***
Manipulate file descriptor.
@function fcntl
@int fd file descriptor to act on
@int cmd operation to perform
@tparam[opt=0] int|flock arg when *cmd* is `F_GETLK`, `F_SETLK` or `F_SETLKW`,
then *arg* is a @{flock} table, otherwise an integer with meaning dependent
upon the value of *cmd*.
@return[1] integer return value depending on *cmd*, if successful
@return[2] nil
@treturn[2] string error message
@treturn[2] int errnum
@see fcntl(2)
@see lock.lua
@usage
local flag = P.fcntl (fd, P.F_GETFL)
*/
static int
Pfcntl(lua_State *L)
{
int fd = checkint(L, 1);
int cmd = checkint(L, 2);
int arg;
struct flock lockinfo;
int r;
checknargs(L, 3);
switch (cmd)
{
case F_SETLK:
case F_SETLKW:
case F_GETLK:
luaL_checktype(L, 3, LUA_TTABLE);
/* Copy fields to flock struct */
lua_getfield(L, 3, "l_type");
lockinfo.l_type = (short)lua_tointeger(L, -1);
lua_getfield(L, 3, "l_whence");
lockinfo.l_whence = (short)lua_tointeger(L, -1);
lua_getfield(L, 3, "l_start");
lockinfo.l_start = (off_t)lua_tointeger(L, -1);
lua_getfield(L, 3, "l_len");
lockinfo.l_len = (off_t)lua_tointeger(L, -1);
/* Lock */
r = fcntl(fd, cmd, &lockinfo);
/* Copy fields from flock struct */
lua_pushinteger(L, lockinfo.l_type);
lua_setfield(L, 3, "l_type");
lua_pushinteger(L, lockinfo.l_whence);
lua_setfield(L, 3, "l_whence");
lua_pushinteger(L, lockinfo.l_start);
lua_setfield(L, 3, "l_start");
lua_pushinteger(L, lockinfo.l_len);
lua_setfield(L, 3, "l_len");
lua_pushinteger(L, lockinfo.l_pid);
lua_setfield(L, 3, "l_pid");
break;
default:
arg = optint(L, 3, 0);
r = fcntl(fd, cmd, arg);
break;
}
return pushresult(L, r, "fcntl");
}
/***
Open a file.
@function open
@string path
@int oflags bitwise OR of zero or more of `O_RDONLY`, `O_WRONLY`, `O_RDWR`,
`O_APPEND`, `O_CREAT`, `O_DSYNC`, `O_EXCL`, `O_NOCTTY`, `O_NONBLOCK`,
`O_RSYNC`, `O_SYNC`, `O_TRUNC`
@int[opt=511] mode access modes used by `O_CREAT`
@treturn[1] int file descriptor for *path*, if successful
@return[2] nil
@treturn[2] string error message
@treturn[2] int errnum
@see open(2)
@usage
fd = P.open ("data", bit.bor (P.O_CREAT, P.O_RDWR), bit.bor (P.S_IRWXU, P.S_IRGRP))
*/
static int
Popen(lua_State *L)
{
const char *path = luaL_checkstring(L, 1);
int oflags = checkint(L, 2);
checknargs(L, 3);
return pushresult(L, open(path, oflags, (mode_t) optint(L, 3, 511)), path);
}
#if HAVE_POSIX_FADVISE
/***
Instruct kernel on appropriate cache behaviour for a file or file segment.
@function posix_fadvise
@int fd open file descriptor
@int offset start of region
@int len number of bytes in region
@int advice one of `POSIX_FADV_NORMAL`, `POSIX_FADV_SEQUENTIAL`,
`POSIX_FADV_RANDOM`, `POSIX_FADV_NOREUSE`, `POSIX_FADV_WILLNEED` or
`POSIX_FADV_DONTNEED`
@treturn[1] int `0`, if successful
@return[2] nil
@treturn[2] string error message
@treturn[2] int errnum
@see posix_fadvise(2)
*/
static int
Pposix_fadvise(lua_State *L)
{
int fd = checkint(L, 1);
int offset = checkint(L, 2);
int len = checkint(L, 3);
int advice = checkint(L, 4);
int r;
checknargs(L, 4);
r = posix_fadvise(fd, offset, len, advice);
return pushresult(L, r == 0 ? 0 : -1, "posix_fadvise");
}
#endif
static const luaL_Reg posix_fcntl_fns[] =
{
LPOSIX_FUNC( Pfcntl ),
LPOSIX_FUNC( Popen ),
#if HAVE_POSIX_FADVISE
LPOSIX_FUNC( Pposix_fadvise ),
#endif
{NULL, NULL}
};
/***
Constants.
@section constants
*/
/***
Fcntl constants.
Any constants not available in the underlying system will be `nil` valued.
@table posix.fcntl
@int F_DUPFD duplicate file descriptor
@int F_GETFD get file descriptor flags
@int F_SETFD set file descriptor flags
@int F_GETFL get file status flags
@int F_SETFL set file status flags
@int F_GETLK get record locking information
@int F_SETLK set record locking information
@int F_SETLKW set lock, and wait if blocked
@int F_GETOWN get SIGIO/SIGURG process owner
@int F_SETOWN set SIGIO/SIGURG process owner
@int F_RDLCK shared or read lock
@int F_WRLCK exclusive or write lock
@int F_UNLCK unlock
@int O_RDONLY open for reading only
@int O_WRONLY open for writing only
@int O_RDWR open for reading and writing
@int O_APPEND set append mode
@int O_CREAT create if nonexistent
@int O_DSYNC synchronise io data integrity
@int O_EXCL error if file already exists
@int O_NOCTTY don't assign controlling terminal
@int O_NONBLOCK no delay
@int O_RSYNC synchronise file read integrity
@int O_SYNC synchronise file write integrity
@int O_TRUNC truncate to zero length
@int POSIX_FADV_NORMAL no advice
@int POSIX_FADV_SEQUENTIAL expecting to access data sequentially
@int POSIX_FADV_RANDOM expecting to access data randomly
@int POSIX_FADV_NOREUSE expecting to access data once only
@int POSIX_FADV_WILLNEED expecting to access data in the near future
@int POSIX_FADV_DONTNEED not expecting to access the data in the near future
@usage
-- Print fcntl constants supported on this host.
for name, value in pairs (require "posix.fcntl") do
if type (value) == "number" then
print (name, value)
end
end
*/
LUALIB_API int
luaopen_posix_fcntl(lua_State *L)
{
luaL_register(L, "posix.fcntl", posix_fcntl_fns);
lua_pushliteral(L, "posix.fcntl for " LUA_VERSION " / " PACKAGE_STRING);
lua_setfield(L, -2, "version");
/* fcntl flags */
LPOSIX_CONST( F_DUPFD );
LPOSIX_CONST( F_GETFD );
LPOSIX_CONST( F_SETFD );
LPOSIX_CONST( F_GETFL );
LPOSIX_CONST( F_SETFL );
LPOSIX_CONST( F_GETLK );
LPOSIX_CONST( F_SETLK );
LPOSIX_CONST( F_SETLKW );
LPOSIX_CONST( F_GETOWN );
LPOSIX_CONST( F_SETOWN );
LPOSIX_CONST( F_RDLCK );
LPOSIX_CONST( F_WRLCK );
LPOSIX_CONST( F_UNLCK );
/* file creation & status flags */
LPOSIX_CONST( O_RDONLY );
LPOSIX_CONST( O_WRONLY );
LPOSIX_CONST( O_RDWR );
LPOSIX_CONST( O_APPEND );
LPOSIX_CONST( O_CREAT );
LPOSIX_CONST( O_DSYNC );
LPOSIX_CONST( O_EXCL );
LPOSIX_CONST( O_NOCTTY );
LPOSIX_CONST( O_NONBLOCK );
LPOSIX_CONST( O_RSYNC );
LPOSIX_CONST( O_SYNC );
LPOSIX_CONST( O_TRUNC );
/* posix_fadvise flags */
#ifdef POSIX_FADV_NORMAL
LPOSIX_CONST( POSIX_FADV_NORMAL );
#endif
#ifdef POSIX_FADV_SEQUENTIAL
LPOSIX_CONST( POSIX_FADV_SEQUENTIAL );
#endif
#ifdef POSIX_FADV_RANDOM
LPOSIX_CONST( POSIX_FADV_RANDOM );
#endif
#ifdef POSIX_FADV_NOREUSE
LPOSIX_CONST( POSIX_FADV_NOREUSE );
#endif
#ifdef POSIX_FADV_WILLNEED
LPOSIX_CONST( POSIX_FADV_WILLNEED );
#endif
#ifdef POSIX_FADV_DONTNEED
LPOSIX_CONST( POSIX_FADV_DONTNEED );
#endif
return 1;
}
/***
Tables.
@section tables
*/
/***
Advisory file locks.
Passed as *arg* to @{fcntl} when *cmd* is `F_GETLK`, `F_SETLK` or `F_SETLKW`.
@table flock
@int l_start starting offset
@int l_len len = 0 means until end of file
@int l_pid lock owner
@int l_type lock type
@int l_whence one of `SEEK_SET`, `SEEK_CUR` or `SEEK_END`
*/