From e0bab40c85780f765bed78bd2e67f376b6883594 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 17 Jun 2024 11:12:43 +0200 Subject: fs: add truncate() file method Trunates the file referenced by a file handle Signed-off-by: Felix Fietkau --- lib/fs.c | 38 ++++++++++++++++++++++++++++++++++++++ tests/custom/03_stdlib/40_proto | 1 + 2 files changed, 39 insertions(+) diff --git a/lib/fs.c b/lib/fs.c index 4d9695e..f237102 100644 --- a/lib/fs.c +++ b/lib/fs.c @@ -738,6 +738,43 @@ uc_fs_seek(uc_vm_t *vm, size_t nargs) return ucv_boolean_new(true); } +/** + * Truncate file to a given size + * + * Returns `true` if the file was successfully truncated. + * + * Returns `null` if an error occurred. + * + * @function module:fs.file#truncate + * + * @param {number} [offset=0] + * The offset in bytes. + * + * @returns {?boolean} + */ +static uc_value_t * +uc_fs_truncate(uc_vm_t *vm, size_t nargs) +{ + FILE *fp = uc_fn_thisval("fs.file"); + uc_value_t *ofs = uc_fn_arg(0); + off_t offset; + + if (!fp) + err_return(EBADF); + + if (!ofs) + offset = 0; + else if (ucv_type(ofs) != UC_INTEGER) + err_return(EINVAL); + else + offset = (off_t)ucv_int64_get(ofs); + + if (ftruncate(fileno(fp), offset) < 0) + err_return(errno); + + return ucv_boolean_new(true); +} + /** * Obtain current read position. * @@ -2571,6 +2608,7 @@ static const uc_function_list_t file_fns[] = { { "fileno", uc_fs_fileno }, { "error", uc_fs_error }, { "isatty", uc_fs_isatty }, + { "truncate", uc_fs_truncate }, }; static const uc_function_list_t dir_fns[] = { diff --git a/tests/custom/03_stdlib/40_proto b/tests/custom/03_stdlib/40_proto index 2a12966..6fed529 100644 --- a/tests/custom/03_stdlib/40_proto +++ b/tests/custom/03_stdlib/40_proto @@ -38,6 +38,7 @@ When invoked with two arguments, returns the given value. Hello, World! [ { + "truncate": "function truncate(...) { [native code] }", "isatty": "function isatty(...) { [native code] }", "error": "function error(...) { [native code] }", "fileno": "function fileno(...) { [native code] }", -- cgit v1.2.3 From 5d305cfb2ab7b997dc1314cb6d4483683275680c Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 17 Jun 2024 12:05:23 +0200 Subject: fs: add lock() file method Implements file based locking on a given file handle. Signed-off-by: Felix Fietkau --- lib/fs.c | 56 +++++++++++++++++++++++++++++++++++++++++ tests/custom/03_stdlib/40_proto | 1 + 2 files changed, 57 insertions(+) diff --git a/lib/fs.c b/lib/fs.c index f237102..d0d97ac 100644 --- a/lib/fs.c +++ b/lib/fs.c @@ -53,6 +53,7 @@ #include #include #include +#include #include #include #include @@ -775,6 +776,60 @@ uc_fs_truncate(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.file#lock + * + * @param {string} [op] + * The lock operation flags + * + * @returns {?boolean} + */ +static uc_value_t * +uc_fs_lock(uc_vm_t *vm, size_t nargs) +{ + FILE *fp = uc_fn_thisval("fs.file"); + uc_value_t *mode = uc_fn_arg(0); + int i, op = 0; + char *m; + + if (!fp) + err_return(EBADF); + + if (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(fileno(fp), op) < 0) + err_return(errno); + + return ucv_boolean_new(true); +} + /** * Obtain current read position. * @@ -2609,6 +2664,7 @@ static const uc_function_list_t file_fns[] = { { "error", uc_fs_error }, { "isatty", uc_fs_isatty }, { "truncate", uc_fs_truncate }, + { "lock", uc_fs_lock }, }; static const uc_function_list_t dir_fns[] = { diff --git a/tests/custom/03_stdlib/40_proto b/tests/custom/03_stdlib/40_proto index 6fed529..d96d124 100644 --- a/tests/custom/03_stdlib/40_proto +++ b/tests/custom/03_stdlib/40_proto @@ -38,6 +38,7 @@ When invoked with two arguments, returns the given value. Hello, World! [ { + "lock": "function lock(...) { [native code] }", "truncate": "function truncate(...) { [native code] }", "isatty": "function isatty(...) { [native code] }", "error": "function error(...) { [native code] }", -- cgit v1.2.3