implemented sys::flock() with fcntl()

This commit is contained in:
hyung-hwan 2020-02-10 08:36:01 +00:00
parent 388e576ad9
commit fb1084a045

View File

@ -65,6 +65,10 @@
#define CLOSE_KEEPFD (1 << 0) #define CLOSE_KEEPFD (1 << 0)
/* these must not conflict with F_RDLCK, F_WRLCK, F_UNLCK */
#define FLOCK_GET (1 << 30)
#define FLOCK_WAIT (1 << 31)
/* /*
* IMPLEMENTATION NOTE: * IMPLEMENTATION NOTE:
* - hard failure only if it cannot make a final return value. (e.g. fnc_errmsg, fnc_fork, fnc_getpid) * - hard failure only if it cannot make a final return value. (e.g. fnc_errmsg, fnc_fork, fnc_getpid)
@ -909,6 +913,128 @@ done:
hawk_rtx_setretval (rtx, retv); hawk_rtx_setretval (rtx, retv);
return 0; return 0;
} }
/*
BEGIN {
f1 = sys::open("/tmp/x", sys::O_RDWR | sys::O_CREAT | sys::O_TRUNC, 0644);
if (sys::flock(f1, sys::FLOCK_WRITE | sys::FLOCK_GET, 0, 0, sys::SEEK_SET, pid) != sys::FLOCK_UNLOCK) print "locked by", pid;
sys::flock(f1, sys::FLOCK_WRITE | sys::FLOCK_WAIT, 0, 0, sys::SEEK_SET);
sys::sleep(ARGV[1]);
sys::flock(f1, sys::FLOCK_UNLOCK | sys::FLOCK_WAIT, 0, 0, sys::SEEK_SET);
sys::sleep(ARGV[1]);
sys::close (f1);
}
*/
static int fnc_flock (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
{
sys_list_t* sys_list;
sys_node_t* sys_node;
hawk_int_t rx;
hawk_val_t* retv;
HAWK_STATIC_ASSERT (FLOCK_GET != F_RDLCK);
HAWK_STATIC_ASSERT (FLOCK_GET != F_WRLCK);
HAWK_STATIC_ASSERT (FLOCK_GET != F_UNLCK);
HAWK_STATIC_ASSERT (FLOCK_WAIT != F_RDLCK);
HAWK_STATIC_ASSERT (FLOCK_WAIT != F_WRLCK);
HAWK_STATIC_ASSERT (FLOCK_WAIT != F_UNLCK);
sys_list = rtx_to_sys_list(rtx, fi);
sys_node = get_sys_list_node_with_arg(rtx, sys_list, hawk_rtx_getarg(rtx, 0), SYS_NODE_DATA_TYPE_FILE, &rx);
if (sys_node)
{
hawk_int_t type, start, len, whence;
int wait, get;
struct flock fl;
if (hawk_rtx_valtoint(rtx, hawk_rtx_getarg(rtx, 1), &type) <= -1 ||
hawk_rtx_valtoint(rtx, hawk_rtx_getarg(rtx, 2), &start) <= -1 ||
hawk_rtx_valtoint(rtx, hawk_rtx_getarg(rtx, 3), &len) <= -1 ||
hawk_rtx_valtoint(rtx, hawk_rtx_getarg(rtx, 4), &whence) <= -1)
{
fail:
rx = copy_error_to_sys_list(rtx, sys_list);
goto done;
}
wait = !!(type & FLOCK_WAIT);
get = !!(type & FLOCK_GET);
type &= ~(FLOCK_WAIT | FLOCK_GET);
HAWK_MEMSET (&fl, 0, HAWK_SIZEOF(fl));
fl.l_type = type;
fl.l_whence = whence;
fl.l_start = start;
fl.l_len = len;
rx = fcntl(sys_node->ctx.u.file.fd, (get? F_GETLK: (wait? F_SETLKW: F_SETLK)), &fl);
if (rx <= -1)
{
set_error_on_sys_list_with_errno(rtx, sys_list, HAWK_NULL);
goto done;
}
if (get && hawk_rtx_getnargs(rtx) >= 6)
{
hawk_val_t* sv;
int x;
sv = hawk_rtx_makeintval(rtx, fl.l_pid);
if (!sv) goto fail;
hawk_rtx_refupval (rtx, sv);
x = hawk_rtx_setrefval(rtx, (hawk_val_ref_t*)hawk_rtx_getarg(rtx, 5), sv);
hawk_rtx_refdownval (rtx, sv);
if (x <= -1) goto fail;
rx = fl.l_type; /* for get, it returns the lock type */
}
}
done:
retv = hawk_rtx_makeintval(rtx, rx);
if (!retv) return -1; /* hard failure. unable to make a return value */
hawk_rtx_setretval (rtx, retv);
return 0;
}
static int fnc_fseek (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) /* this is actually lseek */
{
sys_list_t* sys_list;
sys_node_t* sys_node;
hawk_int_t rx;
hawk_val_t* retv;
sys_list = rtx_to_sys_list(rtx, fi);
sys_node = get_sys_list_node_with_arg(rtx, sys_list, hawk_rtx_getarg(rtx, 0), SYS_NODE_DATA_TYPE_FILE, &rx);
if (sys_node)
{
hawk_int_t offset, whence;
if (hawk_rtx_valtoint(rtx, hawk_rtx_getarg(rtx, 1), &offset) <= -1 ||
hawk_rtx_valtoint(rtx, hawk_rtx_getarg(rtx, 2), &whence) <= -1)
{
rx = copy_error_to_sys_list(rtx, sys_list);
goto done;
}
rx = lseek(sys_node->ctx.u.file.fd, offset, whence);
if (rx <= -1)
{
set_error_on_sys_list_with_errno(rtx, sys_list, HAWK_NULL);
goto done;
}
}
done:
retv = hawk_rtx_makeintval(rtx, rx);
if (!retv) return -1; /* hard failure. unable to make a return value */
hawk_rtx_setretval (rtx, retv);
return 0;
}
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
/* /*
@ -4107,7 +4233,9 @@ static fnctab_t fnctab[] =
{ HAWK_T("fchmod"), { { 2, 2, HAWK_NULL }, fnc_fchmod, 0 } }, { HAWK_T("fchmod"), { { 2, 2, HAWK_NULL }, fnc_fchmod, 0 } },
{ HAWK_T("fchown"), { { 3, 3, HAWK_NULL }, fnc_fchown, 0 } }, { HAWK_T("fchown"), { { 3, 3, HAWK_NULL }, fnc_fchown, 0 } },
{ HAWK_T("fcntl"), { { 2, 3, HAWK_NULL }, fnc_fcntl, 0 } }, { HAWK_T("fcntl"), { { 2, 3, HAWK_NULL }, fnc_fcntl, 0 } },
{ HAWK_T("flock"), { { 5, 6, HAWK_T("vvvvvr")}, fnc_flock, 0 } },
{ HAWK_T("fork"), { { 0, 0, HAWK_NULL }, fnc_fork, 0 } }, { HAWK_T("fork"), { { 0, 0, HAWK_NULL }, fnc_fork, 0 } },
{ HAWK_T("fseek"), { { 3, 3, HAWK_NULL }, fnc_fseek, 0 } },
{ HAWK_T("getegid"), { { 0, 0, HAWK_NULL }, fnc_getegid, 0 } }, { HAWK_T("getegid"), { { 0, 0, HAWK_NULL }, fnc_getegid, 0 } },
{ HAWK_T("getenv"), { { 2, 2, HAWK_T("vr") }, fnc_getenv, 0 } }, { HAWK_T("getenv"), { { 2, 2, HAWK_T("vr") }, fnc_getenv, 0 } },
{ HAWK_T("geteuid"), { { 0, 0, HAWK_NULL }, fnc_geteuid, 0 } }, { HAWK_T("geteuid"), { { 0, 0, HAWK_NULL }, fnc_geteuid, 0 } },
@ -4194,6 +4322,12 @@ static inttab_t inttab[] =
{ HAWK_T("FD_CLOEXEC"), { FD_CLOEXEC } }, { HAWK_T("FD_CLOEXEC"), { FD_CLOEXEC } },
{ HAWK_T("FLOCK_GET"), { FLOCK_GET } }, /* bitwise-OR with another FLOCK_READ/WRITE/WAIT value */
{ HAWK_T("FLOCK_READ"), { F_RDLCK } },
{ HAWK_T("FLOCK_UNLOCK"), { F_UNLCK } },
{ HAWK_T("FLOCK_WAIT"), { FLOCK_WAIT } }, /* bitwise-OR with another FLOCK_READ/WRITE/WAIT value */
{ HAWK_T("FLOCK_WRITE"), { F_WRLCK } },
{ HAWK_T("F_GETFD"), { F_GETFD } }, { HAWK_T("F_GETFD"), { F_GETFD } },
{ HAWK_T("F_GETFL"), { F_GETFL } }, { HAWK_T("F_GETFL"), { F_GETFL } },
{ HAWK_T("F_SETFD"), { F_SETFD } }, { HAWK_T("F_SETFD"), { F_SETFD } },
@ -4322,6 +4456,10 @@ static inttab_t inttab[] =
{ HAWK_T("RC_ESYSERR"), { -HAWK_ESYSERR } }, { HAWK_T("RC_ESYSERR"), { -HAWK_ESYSERR } },
{ HAWK_T("RC_ETMOUT"), { -HAWK_ETMOUT } }, { HAWK_T("RC_ETMOUT"), { -HAWK_ETMOUT } },
{ HAWK_T("SEEK_CUR"), { SEEK_CUR } },
{ HAWK_T("SEEK_END"), { SEEK_END } },
{ HAWK_T("SEEK_SET"), { SEEK_SET } },
{ HAWK_T("SHUT_RD"), { SHUT_RD } }, { HAWK_T("SHUT_RD"), { SHUT_RD } },
{ HAWK_T("SHUT_RDWR"), { SHUT_RDWR } }, { HAWK_T("SHUT_RDWR"), { SHUT_RDWR } },
{ HAWK_T("SHUT_WR"), { SHUT_WR } }, { HAWK_T("SHUT_WR"), { SHUT_WR } },