diff options
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | src/vy_adapter.cpp | 262 | ||||
-rw-r--r-- | src/vy_adapter.h | 33 |
3 files changed, 297 insertions, 0 deletions
diff --git a/Makefile.am b/Makefile.am index 2170f95..6ef8d64 100644 --- a/Makefile.am +++ b/Makefile.am @@ -52,6 +52,7 @@ src_libvyatta_cfg_la_SOURCES += src/cnode/cnode-algorithm.cpp src_libvyatta_cfg_la_SOURCES += src/cparse/cparse.cpp src_libvyatta_cfg_la_SOURCES += src/cparse/cparse_lex.c src_libvyatta_cfg_la_SOURCES += src/commit/commit-algorithm.cpp +src_libvyatta_cfg_la_SOURCES += src/vy_adapter.cpp CLEANFILES = src/cli_parse.c src/cli_parse.h src/cli_def.c src/cli_val.c CLEANFILES += src/cparse/cparse.cpp src/cparse/cparse.h CLEANFILES += src/cparse/cparse_lex.c @@ -61,6 +62,7 @@ LDADD += $(GOBJECT_LIBS) vincludedir = $(includedir)/vyatta-cfg vinclude_HEADERS = src/cli_cstore.h +vinclude_HEADERS += src/vy_adapter.h vcincdir = $(vincludedir)/cstore vcinc_HEADERS = src/cstore/cstore-c.h diff --git a/src/vy_adapter.cpp b/src/vy_adapter.cpp new file mode 100644 index 0000000..cf2f50e --- /dev/null +++ b/src/vy_adapter.cpp @@ -0,0 +1,262 @@ +/* Copyright 2024 VyOS maintainers and contributors <maintainers@vyos.io> + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <cstring> +#include <cstdlib> +#include <vector> +#include <string> +#include <sstream> +#include <iostream> +#include <cstdint> +#include <cassert> +#include <algorithm> +#include <list> +#include <fcntl.h> +#include <unistd.h> + +#include <cstore/cstore.hpp> +#include <vy_adapter.h> + +using namespace cstore; + +enum PIPES { READ, WRITE }; + +extern FILE *out_stream; + +class stdout_redirect { + public: + stdout_redirect(): old_stdout(0), redirecting(false) { + out_pipe[READ] = 0; + out_pipe[WRITE] = 0; + if (pipe(out_pipe) == -1) { + return; + } + + old_stdout = dup(fileno(stdout)); + setbuf(stdout, NULL); + dup2(out_pipe[WRITE], fileno(stdout)); + + redirecting = true; + } + + std::string get_redirected_output() { + if (!redirecting) { + return ""; + } + + char buffer[1024]; + ssize_t bytesRead = 0; + std::string redirected_output = "\n"; + fcntl(out_pipe[READ], F_SETFL, O_NONBLOCK); + while ((bytesRead = read(out_pipe[READ], buffer, sizeof(buffer))) > 0) { + redirected_output.append(buffer, bytesRead); + } + + return redirected_output; + } + + ~stdout_redirect() { + if (!redirecting) { + return; + } + + dup2(old_stdout, fileno(stdout)); + + if (old_stdout > 0) { + close(old_stdout); + } + if (out_pipe[READ] > 0) { + close(out_pipe[READ]); + } + if (out_pipe[WRITE] > 0) { + close(out_pipe[WRITE]); + } + } + + private: + int out_pipe[2]; + int old_stdout; + bool redirecting; +}; + +struct cstore_obj { + Cstore *cstore; + std::list<char *> output; +}; + +static struct cstore_obj* create_handle() { + struct cstore_obj *h = new cstore_obj; + h->cstore = Cstore::createCstore(false); + return h; +}; + +const char *out_data_copy(std::string msg, cstore_obj *o) +{ + size_t len = msg.length(); + char *out_data = (char *) malloc(len + 1); + o->output.push_back(out_data); + msg.copy(out_data, len); + out_data[len] = '\0'; + return out_data; +} + +static uint64_t uint_of_voidptr(void* p) +{ + assert (((uintptr_t) p & 1) == 0); + return (uint64_t) p | 1; +} + +static void *voidptr_of_uint(uint64_t v) +{ + return (void *)(uintptr_t)(v & ~1); +} + +static cstore_obj *cstore_obj_of_handle(uint64_t handle) +{ + return (cstore_obj *) voidptr_of_uint(handle); +} + +uint64_t +vy_cstore_init(void) +{ + cstore_obj *handle = create_handle(); + return uint_of_voidptr(handle); +} + +void +vy_cstore_free(uint64_t handle) +{ + cstore_obj *h = cstore_obj_of_handle(handle); + for (char * x: h->output) { + free(x); + } + delete h->cstore; + delete h; +} + +int +vy_in_session(uint64_t handle) +{ + Cstore *h = cstore_obj_of_handle(handle)->cstore; + return h->inSession() ? 1 : 0; +} + +const char * +vy_validate_path(uint64_t handle, const void** path_ptr, size_t len) +{ + cstore_obj *obj = cstore_obj_of_handle(handle); + Cstore *cstore = obj->cstore; + const char **path = (const char **) path_ptr; + Cpath path_comps = Cpath(path, len); + const char *out_data; + std::string out_str = ""; + int res; + + out_stream = stdout; + stdout_redirect redirect = stdout_redirect(); + + res = cstore->validateSetPath(path_comps); + if (!res) { + out_str = "\nInvalid set path: " + path_comps.to_string() + "\n"; + out_str.append(redirect.get_redirected_output()); + } + + out_data = out_data_copy(out_str, obj); + out_stream = NULL; + return out_data; +} + +const char * +vy_set_path(uint64_t handle, const void** path_ptr, size_t len) +{ + cstore_obj *obj = cstore_obj_of_handle(handle); + Cstore *cstore = obj->cstore; + const char **path = (const char **) path_ptr; + Cpath path_comps = Cpath(path, len); + const char *out_data; + std::string out_str = ""; + int res; + + out_stream = stdout; + stdout_redirect redirect = stdout_redirect(); + + res = cstore->setCfgPath(path_comps); + if (!res) { + out_str = "\nSet config path failed: " + path_comps.to_string() + "\n"; + out_str.append(redirect.get_redirected_output()); + } + + out_data = out_data_copy(out_str, obj); + out_stream = NULL; + return out_data; +} + +const char * +vy_legacy_set_path(uint64_t handle, const void** path_ptr, size_t len) +{ + cstore_obj *obj = cstore_obj_of_handle(handle); + Cstore *cstore = obj->cstore; + const char **path = (const char **) path_ptr; + Cpath path_comps = Cpath(path, len); + const char *out_data; + std::string out_str = ""; + int res; + + out_stream = stdout; + stdout_redirect redirect = stdout_redirect(); + + res = cstore->validateSetPath(path_comps); + if (!res) { + out_str = "\nInvalid set path: " + path_comps.to_string() + "\n"; + out_str.append(redirect.get_redirected_output()); + goto out; + } + + res = cstore->setCfgPath(path_comps); + if (!res) { + out_str = "\nSet config path failed: " + path_comps.to_string() + "\n"; + out_str.append(redirect.get_redirected_output()); + } + +out: + out_data = out_data_copy(out_str, obj); + out_stream = NULL; + return out_data; +} + +const char * +vy_delete_path(uint64_t handle, const void** path_ptr, size_t len) +{ + cstore_obj *obj = cstore_obj_of_handle(handle); + Cstore *cstore = obj->cstore; + const char **path = (const char **) path_ptr; + Cpath path_comps = Cpath(path, len); + const char *out_data; + std::string out_str = ""; + int res; + + out_stream = stdout; + stdout_redirect redirect = stdout_redirect(); + + res = cstore->deleteCfgPath(path_comps); + if (!res) { + out_str = "\nDelete failed: " + path_comps.to_string() + "\n"; + out_str.append(redirect.get_redirected_output()); + } + + out_data = out_data_copy(out_str, obj); + out_stream = NULL; + return out_data; +} diff --git a/src/vy_adapter.h b/src/vy_adapter.h new file mode 100644 index 0000000..636c303 --- /dev/null +++ b/src/vy_adapter.h @@ -0,0 +1,33 @@ +/* Copyright 2024 VyOS maintainers and contributors <maintainers@vyos.io> + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _VY_ADAPTER_H_ +#define _VY_ADAPTER_H_ +#ifdef __cplusplus +extern "C" { +#endif + +uint64_t vy_cstore_init(void); +void vy_cstore_free(uint64_t); +int vy_in_session(uint64_t); +const char *vy_validate_path(uint64_t, const void **, size_t); +const char *vy_set_path(uint64_t, const void **, size_t); +const char *vy_legacy_set_path(uint64_t, const void **, size_t); +const char *vy_delete_path(uint64_t, const void **, size_t); + +#ifdef __cplusplus +} +#endif +#endif |