Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add fs module utility functions #207

Merged
merged 2 commits into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions lib/fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/file.h>
#include <grp.h>
#include <pwd.h>
#include <glob.h>
Expand Down Expand Up @@ -738,6 +739,97 @@ 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);
}

/**
* 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.
*
Expand Down Expand Up @@ -2571,6 +2663,8 @@ static const uc_function_list_t file_fns[] = {
{ "fileno", uc_fs_fileno },
{ "error", uc_fs_error },
{ "isatty", uc_fs_isatty },
{ "truncate", uc_fs_truncate },
{ "lock", uc_fs_lock },
};

static const uc_function_list_t dir_fns[] = {
Expand Down
2 changes: 2 additions & 0 deletions tests/custom/03_stdlib/40_proto
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ 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] }",
"fileno": "function fileno(...) { [native code] }",
Expand Down
Loading