diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 17:44:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 17:44:55 +0000 |
commit | 5068d34c08f951a7ea6257d305a1627b09a95817 (patch) | |
tree | 08213e2be853396a3b07ce15dbe222644dcd9a89 /src/static_file_vtab.cc | |
parent | Initial commit. (diff) | |
download | lnav-upstream.tar.xz lnav-upstream.zip |
Adding upstream version 0.11.1.upstream/0.11.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | src/static_file_vtab.cc | 333 |
1 files changed, 333 insertions, 0 deletions
diff --git a/src/static_file_vtab.cc b/src/static_file_vtab.cc new file mode 100644 index 0000000..f884cb3 --- /dev/null +++ b/src/static_file_vtab.cc @@ -0,0 +1,333 @@ +/** + * Copyright (c) 2022, Timothy Stack + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of Timothy Stack nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <map> + +#include "static_file_vtab.hh" + +#include <stdlib.h> +#include <string.h> + +#include "base/auto_mem.hh" +#include "base/fs_util.hh" +#include "base/lnav_log.hh" +#include "base/paths.hh" +#include "config.h" +#include "ghc/filesystem.hpp" +#include "lnav.hh" +#include "vtab_module.hh" + +const char* const STATIC_FILE_CREATE_STMT = R"( +-- Access static files in the lnav configuration directories +CREATE TABLE lnav_static_files ( + name TEXT PRIMARY KEY, + filepath TEXT, + content BLOB HIDDEN +); +)"; + +struct static_file_vtab { + sqlite3_vtab base; + sqlite3* db; +}; + +struct static_file_info { + ghc::filesystem::path sfi_path; +}; + +struct sf_vtab_cursor { + sqlite3_vtab_cursor base; + std::map<std::string, static_file_info>::iterator vc_files_iter; + std::map<std::string, static_file_info> vc_files; +}; + +static int sfvt_destructor(sqlite3_vtab* p_svt); + +static int +sfvt_create(sqlite3* db, + void* pAux, + int argc, + const char* const* argv, + sqlite3_vtab** pp_vt, + char** pzErr) +{ + static_file_vtab* p_vt; + + /* Allocate the sqlite3_vtab/vtab structure itself */ + p_vt = (static_file_vtab*) sqlite3_malloc(sizeof(*p_vt)); + + if (p_vt == nullptr) { + return SQLITE_NOMEM; + } + + memset(&p_vt->base, 0, sizeof(sqlite3_vtab)); + p_vt->db = db; + + *pp_vt = &p_vt->base; + + int rc = sqlite3_declare_vtab(db, STATIC_FILE_CREATE_STMT); + + return rc; +} + +static int +sfvt_destructor(sqlite3_vtab* p_svt) +{ + static_file_vtab* p_vt = (static_file_vtab*) p_svt; + + /* Free the SQLite structure */ + sqlite3_free(p_vt); + + return SQLITE_OK; +} + +static int +sfvt_connect(sqlite3* db, + void* p_aux, + int argc, + const char* const* argv, + sqlite3_vtab** pp_vt, + char** pzErr) +{ + return sfvt_create(db, p_aux, argc, argv, pp_vt, pzErr); +} + +static int +sfvt_disconnect(sqlite3_vtab* pVtab) +{ + return sfvt_destructor(pVtab); +} + +static int +sfvt_destroy(sqlite3_vtab* p_vt) +{ + return sfvt_destructor(p_vt); +} + +static int sfvt_next(sqlite3_vtab_cursor* cur); + +static void +find_static_files(sf_vtab_cursor* p_cur, const ghc::filesystem::path& dir) +{ + auto& file_map = p_cur->vc_files; + std::error_code ec; + + for (const auto& format_dir_entry : + ghc::filesystem::directory_iterator(dir, ec)) + { + if (!format_dir_entry.is_directory()) { + continue; + } + auto format_static_files_dir = format_dir_entry.path() / "static-files"; + log_debug("format static files: %s", format_static_files_dir.c_str()); + for (const auto& static_file_entry : + ghc::filesystem::recursive_directory_iterator( + format_static_files_dir, ec)) + { + auto rel_path = ghc::filesystem::relative(static_file_entry.path(), + format_static_files_dir); + + file_map[rel_path.string()] = {static_file_entry.path()}; + } + } +} + +static int +sfvt_open(sqlite3_vtab* p_svt, sqlite3_vtab_cursor** pp_cursor) +{ + static_file_vtab* p_vt = (static_file_vtab*) p_svt; + + p_vt->base.zErrMsg = NULL; + + sf_vtab_cursor* p_cur = (sf_vtab_cursor*) new sf_vtab_cursor(); + + if (p_cur == nullptr) { + return SQLITE_NOMEM; + } + + *pp_cursor = (sqlite3_vtab_cursor*) p_cur; + + p_cur->base.pVtab = p_svt; + + for (const auto& config_path : lnav_data.ld_config_paths) { + auto formats_root = config_path / "formats"; + log_debug("format root: %s", formats_root.c_str()); + find_static_files(p_cur, formats_root); + auto configs_root = config_path / "configs"; + log_debug("configs root: %s", configs_root.c_str()); + find_static_files(p_cur, configs_root); + } + + return SQLITE_OK; +} + +static int +sfvt_close(sqlite3_vtab_cursor* cur) +{ + sf_vtab_cursor* p_cur = (sf_vtab_cursor*) cur; + + p_cur->vc_files_iter = p_cur->vc_files.end(); + /* Free cursor struct. */ + delete p_cur; + + return SQLITE_OK; +} + +static int +sfvt_eof(sqlite3_vtab_cursor* cur) +{ + sf_vtab_cursor* vc = (sf_vtab_cursor*) cur; + + return vc->vc_files_iter == vc->vc_files.end(); +} + +static int +sfvt_next(sqlite3_vtab_cursor* cur) +{ + sf_vtab_cursor* vc = (sf_vtab_cursor*) cur; + + if (vc->vc_files_iter != vc->vc_files.end()) { + ++vc->vc_files_iter; + } + + return SQLITE_OK; +} + +static int +sfvt_column(sqlite3_vtab_cursor* cur, sqlite3_context* ctx, int col) +{ + sf_vtab_cursor* vc = (sf_vtab_cursor*) cur; + + switch (col) { + case 0: + to_sqlite(ctx, vc->vc_files_iter->first); + break; + case 1: { + sqlite3_result_text(ctx, + vc->vc_files_iter->second.sfi_path.c_str(), + -1, + SQLITE_TRANSIENT); + break; + } + case 2: { + auto read_res = lnav::filesystem::read_file( + vc->vc_files_iter->second.sfi_path); + if (read_res.isErr()) { + auto um = lnav::console::user_message::error( + "unable to read static file") + .with_reason(read_res.unwrapErr()); + + to_sqlite(ctx, um); + } else { + auto str = read_res.unwrap(); + + sqlite3_result_blob( + ctx, str.c_str(), str.size(), SQLITE_TRANSIENT); + } + break; + } + } + + return SQLITE_OK; +} + +static int +sfvt_rowid(sqlite3_vtab_cursor* cur, sqlite_int64* p_rowid) +{ + sf_vtab_cursor* p_cur = (sf_vtab_cursor*) cur; + + *p_rowid = std::distance(p_cur->vc_files.begin(), p_cur->vc_files_iter); + + return SQLITE_OK; +} + +static int +sfvt_best_index(sqlite3_vtab* tab, sqlite3_index_info* p_info) +{ + return SQLITE_OK; +} + +static int +sfvt_filter(sqlite3_vtab_cursor* cur, + int idxNum, + const char* idxStr, + int argc, + sqlite3_value** argv) +{ + sf_vtab_cursor* p_cur = (sf_vtab_cursor*) cur; + + p_cur->vc_files_iter = p_cur->vc_files.begin(); + return SQLITE_OK; +} + +static sqlite3_module static_file_vtab_module = { + 0, /* iVersion */ + sfvt_create, /* xCreate - create a vtable */ + sfvt_connect, /* xConnect - associate a vtable with a connection */ + sfvt_best_index, /* xBestIndex - best index */ + sfvt_disconnect, /* xDisconnect - disassociate a vtable with a connection + */ + sfvt_destroy, /* xDestroy - destroy a vtable */ + sfvt_open, /* xOpen - open a cursor */ + sfvt_close, /* xClose - close a cursor */ + sfvt_filter, /* xFilter - configure scan constraints */ + sfvt_next, /* xNext - advance a cursor */ + sfvt_eof, /* xEof - inidicate end of result set*/ + sfvt_column, /* xColumn - read data */ + sfvt_rowid, /* xRowid - read data */ + nullptr, /* xUpdate - write data */ + nullptr, /* xBegin - begin transaction */ + nullptr, /* xSync - sync transaction */ + nullptr, /* xCommit - commit transaction */ + nullptr, /* xRollback - rollback transaction */ + nullptr, /* xFindFunction - function overloading */ +}; + +int +register_static_file_vtab(sqlite3* db) +{ + auto_mem<char, sqlite3_free> errmsg; + int rc; + rc = sqlite3_create_module( + db, "lnav_static_file_vtab_impl", &static_file_vtab_module, nullptr); + ensure(rc == SQLITE_OK); + if ((rc = sqlite3_exec(db, + "CREATE VIRTUAL TABLE lnav_static_files USING " + "lnav_static_file_vtab_impl()", + nullptr, + nullptr, + errmsg.out())) + != SQLITE_OK) + { + fprintf(stderr, + "unable to create lnav_static_file table %s\n", + errmsg.in()); + } + return rc; +} |