diff options
author | Jo-Philipp Wich <jo@mein.io> | 2022-01-04 13:58:12 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-01-04 13:58:12 +0100 |
commit | 8907ce41a36f8d42097d884550fb3cfbba62e6c5 (patch) | |
tree | 4768df7c3d81b542c0cde1711050d9ccc0f8aa4f /lib | |
parent | 70c87cd08da5a42a30c3a039565530f28803385e (diff) | |
parent | 5c77dd53a5c4f383e699220be4c177cb727e659c (diff) |
Merge pull request #29 from jow-/fs-fileno-support
fs: implement fdopen(), file.fileno() and proc.fileno()
Diffstat (limited to 'lib')
-rw-r--r-- | lib/fs.c | 64 |
1 files changed, 63 insertions, 1 deletions
@@ -26,6 +26,7 @@ #include <pwd.h> #include <glob.h> #include <fnmatch.h> +#include <limits.h> #include "ucode/module.h" @@ -171,6 +172,24 @@ uc_fs_write_common(uc_vm_t *vm, size_t nargs, const char *type) return ucv_int64_new(wsize); } +static uc_value_t * +uc_fs_fileno_common(uc_vm_t *vm, size_t nargs, const char *type) +{ + int fd; + + FILE **fp = uc_fn_this(type); + + if (!fp || !*fp) + err_return(EBADF); + + fd = fileno(*fp); + + if (fd == -1) + err_return(errno); + + return ucv_int64_new(fd); +} + static uc_value_t * uc_fs_pclose(uc_vm_t *vm, size_t nargs) @@ -209,6 +228,12 @@ uc_fs_pwrite(uc_vm_t *vm, size_t nargs) } static uc_value_t * +uc_fs_pfileno(uc_vm_t *vm, size_t nargs) +{ + return uc_fs_fileno_common(vm, nargs, "fs.proc"); +} + +static uc_value_t * uc_fs_popen(uc_vm_t *vm, size_t nargs) { uc_value_t *comm = uc_fn_arg(0); @@ -308,6 +333,12 @@ uc_fs_tell(uc_vm_t *vm, size_t nargs) } static uc_value_t * +uc_fs_fileno(uc_vm_t *vm, size_t nargs) +{ + return uc_fs_fileno_common(vm, nargs, "fs.file"); +} + +static uc_value_t * uc_fs_open(uc_vm_t *vm, size_t nargs) { uc_value_t *path = uc_fn_arg(0); @@ -326,6 +357,31 @@ uc_fs_open(uc_vm_t *vm, size_t nargs) return uc_resource_new(file_type, fp); } +static uc_value_t * +uc_fs_fdopen(uc_vm_t *vm, size_t nargs) +{ + uc_value_t *fdno = uc_fn_arg(0); + uc_value_t *mode = uc_fn_arg(1); + int64_t n; + FILE *fp; + + if (ucv_type(fdno) != UC_INTEGER) + err_return(EINVAL); + + n = ucv_int64_get(fdno); + + if (n < 0 || n > INT_MAX) + err_return(EBADF); + + fp = fdopen((int)n, + ucv_type(mode) == UC_STRING ? ucv_string_get(mode) : "r"); + + if (!fp) + err_return(errno); + + return uc_resource_new(file_type, fp); +} + static uc_value_t * uc_fs_readdir(uc_vm_t *vm, size_t nargs) @@ -960,6 +1016,7 @@ static const uc_function_list_t proc_fns[] = { { "read", uc_fs_pread }, { "write", uc_fs_pwrite }, { "close", uc_fs_pclose }, + { "fileno", uc_fs_pfileno }, { "error", uc_fs_error }, }; @@ -969,6 +1026,7 @@ static const uc_function_list_t file_fns[] = { { "seek", uc_fs_seek }, { "tell", uc_fs_tell }, { "close", uc_fs_close }, + { "fileno", uc_fs_fileno }, { "error", uc_fs_error }, }; @@ -983,6 +1041,7 @@ static const uc_function_list_t dir_fns[] = { static const uc_function_list_t global_fns[] = { { "error", uc_fs_error }, { "open", uc_fs_open }, + { "fdopen", uc_fs_fdopen }, { "opendir", uc_fs_opendir }, { "popen", uc_fs_popen }, { "readlink", uc_fs_readlink }, @@ -1015,8 +1074,11 @@ static void close_proc(void *ud) static void close_file(void *ud) { FILE *fp = ud; + int n; + + n = fp ? fileno(fp) : -1; - if (fp && fp != stdin && fp != stdout && fp != stderr) + if (n > 2) fclose(fp); } |