diff options
author | Jo-Philipp Wich <jo@mein.io> | 2020-09-09 09:16:22 +0200 |
---|---|---|
committer | Jo-Philipp Wich <jo@mein.io> | 2020-09-09 09:16:22 +0200 |
commit | 0a8f4cb47099d1b82f3ec7b27d3530ed0ecea407 (patch) | |
tree | c71130b851a608ac75c50107970158f65a923fe2 /lib/fs.c | |
parent | 72f4a6ee1fcb22a6ad407e9e0d9969de820985fe (diff) |
fs: implement popen()
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
Diffstat (limited to 'lib/fs.c')
-rw-r--r-- | lib/fs.c | 119 |
1 files changed, 100 insertions, 19 deletions
@@ -29,6 +29,7 @@ static const struct ut_ops *ops; +static struct json_object *proc_proto; static struct json_object *file_proto; static struct json_object *dir_proto; @@ -48,23 +49,8 @@ ut_fs_error(struct ut_state *s, uint32_t off, struct json_object *args) return errmsg; } - static struct json_object * -ut_fs_close(struct ut_state *s, uint32_t off, struct json_object *args) -{ - FILE **fp = (FILE **)ops->get_type(s->ctx, "fs.file"); - - if (!fp || !*fp) - err_return(EBADF); - - fclose(*fp); - *fp = NULL; - - return json_object_new_boolean(true); -} - -static struct json_object * -ut_fs_read(struct ut_state *s, uint32_t off, struct json_object *args) +ut_fs_read_common(struct ut_state *s, uint32_t off, struct json_object *args, const char *type) { struct json_object *limit = json_object_array_get_idx(args, 0); struct json_object *rv = NULL; @@ -73,7 +59,7 @@ ut_fs_read(struct ut_state *s, uint32_t off, struct json_object *args) const char *lstr; int64_t lsize; - FILE **fp = (FILE **)ops->get_type(s->ctx, "fs.file"); + FILE **fp = (FILE **)ops->get_type(s->ctx, type); if (!fp || !*fp) err_return(EBADF); @@ -156,13 +142,13 @@ ut_fs_read(struct ut_state *s, uint32_t off, struct json_object *args) } static struct json_object * -ut_fs_write(struct ut_state *s, uint32_t off, struct json_object *args) +ut_fs_write_common(struct ut_state *s, uint32_t off, struct json_object *args, const char *type) { struct json_object *data = json_object_array_get_idx(args, 0); size_t len, wsize; const char *str; - FILE **fp = (FILE **)ops->get_type(s->ctx, "fs.file"); + FILE **fp = (FILE **)ops->get_type(s->ctx, type); if (!fp || !*fp) err_return(EBADF); @@ -184,6 +170,87 @@ ut_fs_write(struct ut_state *s, uint32_t off, struct json_object *args) return json_object_new_int64(wsize); } + +static struct json_object * +ut_fs_pclose(struct ut_state *s, uint32_t off, struct json_object *args) +{ + FILE **fp = (FILE **)ops->get_type(s->ctx, "fs.proc"); + + if (!fp || !*fp) + err_return(EBADF); + + pclose(*fp); + *fp = NULL; + + return json_object_new_boolean(true); +} + +static struct json_object * +ut_fs_pread(struct ut_state *s, uint32_t off, struct json_object *args) +{ + return ut_fs_read_common(s, off, args, "fs.proc"); +} + +static struct json_object * +ut_fs_pwrite(struct ut_state *s, uint32_t off, struct json_object *args) +{ + return ut_fs_write_common(s, off, args, "fs.proc"); +} + +static struct json_object * +ut_fs_popen(struct ut_state *s, uint32_t off, struct json_object *args) +{ + struct json_object *comm = json_object_array_get_idx(args, 0); + struct json_object *mode = json_object_array_get_idx(args, 1); + struct json_object *fo; + FILE *fp; + + if (!json_object_is_type(comm, json_type_string)) + err_return(EINVAL); + + fp = popen(json_object_get_string(comm), + json_object_is_type(mode, json_type_string) ? json_object_get_string(mode) : "r"); + + if (!fp) + err_return(errno); + + fo = json_object_new_object(); + + if (!fo) { + pclose(fp); + err_return(ENOMEM); + } + + return ops->set_type(s, fo, proc_proto, "fs.proc", fp); +} + + +static struct json_object * +ut_fs_close(struct ut_state *s, uint32_t off, struct json_object *args) +{ + FILE **fp = (FILE **)ops->get_type(s->ctx, "fs.file"); + + if (!fp || !*fp) + err_return(EBADF); + + fclose(*fp); + *fp = NULL; + + return json_object_new_boolean(true); +} + +static struct json_object * +ut_fs_read(struct ut_state *s, uint32_t off, struct json_object *args) +{ + return ut_fs_read_common(s, off, args, "fs.file"); +} + +static struct json_object * +ut_fs_write(struct ut_state *s, uint32_t off, struct json_object *args) +{ + return ut_fs_write_common(s, off, args, "fs.file"); +} + static struct json_object * ut_fs_seek(struct ut_state *s, uint32_t off, struct json_object *args) { @@ -560,6 +627,7 @@ static const struct { const char *name; ut_c_fn *func; } functions[] = { { "error", ut_fs_error }, { "open", ut_fs_open }, { "opendir", ut_fs_opendir }, + { "popen", ut_fs_popen }, { "readlink", ut_fs_readlink }, { "stat", ut_fs_stat }, { "lstat", ut_fs_lstat }, @@ -570,6 +638,10 @@ static const struct { const char *name; ut_c_fn *func; } functions[] = { }; +static void close_proc(void *ud) { + pclose((FILE *)ud); +} + static void close_file(void *ud) { fclose((FILE *)ud); } @@ -583,12 +655,21 @@ void ut_module_init(const struct ut_ops *ut, struct ut_state *s, struct json_obj int i; ops = ut; + ops->register_type("fs.proc", close_proc); ops->register_type("fs.file", close_file); ops->register_type("fs.dir", close_dir); for (i = 0; i < ARRAY_SIZE(functions); i++) ops->register_function(s, scope, functions[i].name, functions[i].func); + proc_proto = ops->new_object(s, NULL); + + if (proc_proto) { + ops->register_function(s, proc_proto, "read", ut_fs_pread); + ops->register_function(s, proc_proto, "write", ut_fs_pwrite); + ops->register_function(s, proc_proto, "close", ut_fs_pclose); + } + file_proto = ops->new_object(s, NULL); if (file_proto) { |