diff --git a/lib/fs.c b/lib/fs.c index 7e3ad331..5fb14cc3 100644 --- a/lib/fs.c +++ b/lib/fs.c @@ -778,6 +778,61 @@ uc_fs_ftruncate(uc_vm_t *vm, size_t nargs) return ucv_boolean_new(true); } +/** + * Locks or unlocks a file. + * + * The mode argument specifies lock/unlock operation flags. + * + * | Flag | Description | + * |---------|------------------------------| + * | "s" | shared lock | + * | "x" | exclusive lock | + * | "n" | don't block when locking | + * | "u" | unlock | + * + * Returns `true` if the file was successfully locked/unlocked. + * + * Returns `null` if an error occurred. + * + * @function module:fs#flock + * + * @param {number} [fd] + * The file descriptor. + * + * @param {string} [op] + * The lock operation flags + * + * @returns {?boolean} + */ +static uc_value_t * +uc_fs_flock(uc_vm_t *vm, size_t nargs) +{ + uc_value_t *fd = uc_fn_arg(0); + uc_value_t *mode = uc_fn_arg(1); + int i, op = 0; + char *m; + + if (ucv_type(fd) != UC_INTEGER || + ucv_type(mode) != UC_STRING) + err_return(EINVAL); + + m = ucv_string_get(mode); + for (i = 0; m[i]; i++) { + switch (m[i]) { + case 's': op |= LOCK_SH; break; + case 'x': op |= LOCK_EX; break; + case 'n': op |= LOCK_NB; break; + case 'u': op |= LOCK_UN; break; + default: err_return(EINVAL); + } + } + + if (flock(ucv_int64_get(fd), op) < 0) + err_return(errno); + + return ucv_boolean_new(true); +} + /** * Obtain current read position. * @@ -2650,6 +2705,7 @@ static const uc_function_list_t global_fns[] = { { "realpath", uc_fs_realpath }, { "pipe", uc_fs_pipe }, { "ftruncate", uc_fs_ftruncate }, + { "flock", uc_fs_flock }, };