mirror of
https://github.com/zeek/zeek.git
synced 2025-10-01 22:28:20 +00:00
Remove ghc::filesystem submodule, switch to std::filesystem
This commit is contained in:
parent
a843521e78
commit
770bc0491e
13 changed files with 38 additions and 69 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -58,9 +58,6 @@
|
||||||
[submodule "auxil/spicy"]
|
[submodule "auxil/spicy"]
|
||||||
path = auxil/spicy
|
path = auxil/spicy
|
||||||
url = https://github.com/zeek/spicy
|
url = https://github.com/zeek/spicy
|
||||||
[submodule "auxil/filesystem"]
|
|
||||||
path = auxil/filesystem
|
|
||||||
url = https://github.com/gulrak/filesystem.git
|
|
||||||
[submodule "auxil/zeek-af_packet-plugin"]
|
[submodule "auxil/zeek-af_packet-plugin"]
|
||||||
path = auxil/zeek-af_packet-plugin
|
path = auxil/zeek-af_packet-plugin
|
||||||
url = https://github.com/zeek/zeek-af_packet-plugin.git
|
url = https://github.com/zeek/zeek-af_packet-plugin.git
|
||||||
|
|
|
@ -1057,9 +1057,6 @@ include(BuiltInSpicyAnalyzer)
|
||||||
include_directories(BEFORE ${PCAP_INCLUDE_DIR} ${BIND_INCLUDE_DIR} ${BinPAC_INCLUDE_DIR}
|
include_directories(BEFORE ${PCAP_INCLUDE_DIR} ${BIND_INCLUDE_DIR} ${BinPAC_INCLUDE_DIR}
|
||||||
${ZLIB_INCLUDE_DIR} ${JEMALLOC_INCLUDE_DIR})
|
${ZLIB_INCLUDE_DIR} ${JEMALLOC_INCLUDE_DIR})
|
||||||
|
|
||||||
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/auxil/filesystem/include/ghc
|
|
||||||
DESTINATION include/zeek/3rdparty/)
|
|
||||||
|
|
||||||
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/auxil/prometheus-cpp/core/include/prometheus
|
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/auxil/prometheus-cpp/core/include/prometheus
|
||||||
DESTINATION include/zeek/3rdparty/prometheus-cpp/include)
|
DESTINATION include/zeek/3rdparty/prometheus-cpp/include)
|
||||||
|
|
||||||
|
@ -1069,15 +1066,8 @@ install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/auxil/prometheus-cpp/core/include/
|
||||||
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/auxil/expected-lite/include/nonstd
|
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/auxil/expected-lite/include/nonstd
|
||||||
DESTINATION include/zeek/3rdparty/)
|
DESTINATION include/zeek/3rdparty/)
|
||||||
|
|
||||||
# Create 3rdparty/ghc within the build directory so that the include for
|
|
||||||
# "zeek/3rdparty/ghc/filesystem.hpp" works within the build tree.
|
|
||||||
execute_process(COMMAND "${CMAKE_COMMAND}" -E make_directory
|
execute_process(COMMAND "${CMAKE_COMMAND}" -E make_directory
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/3rdparty/")
|
"${CMAKE_CURRENT_BINARY_DIR}/3rdparty/")
|
||||||
execute_process(
|
|
||||||
COMMAND
|
|
||||||
"${CMAKE_COMMAND}" -E create_symlink
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/auxil/filesystem/include/ghc"
|
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/3rdparty/ghc")
|
|
||||||
|
|
||||||
# Do the same for nonstd.
|
# Do the same for nonstd.
|
||||||
execute_process(
|
execute_process(
|
||||||
|
|
|
@ -533,32 +533,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
|
|
||||||
%%% auxil/filesystem
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
|
|
||||||
Copyright (c) 2018, Steffen Schümann <s.schuemann@pobox.com>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
|
|
||||||
%%% auxil/highwayhash
|
%%% auxil/highwayhash
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
|
|
6
NEWS
6
NEWS
|
@ -333,6 +333,12 @@ Deprecated Functionality
|
||||||
tuples. The ConnTuple struct, used by this deprecated Connection constructor,
|
tuples. The ConnTuple struct, used by this deprecated Connection constructor,
|
||||||
is now deprecated as well.
|
is now deprecated as well.
|
||||||
|
|
||||||
|
- The ``zeek::filesystem`` namespace alias is deprecated in favor of using
|
||||||
|
``std::filesystem`` directly. Similarly, the ``ghc::filesystem`` submodule stored in
|
||||||
|
``auxil/filessytem`` has been removed and the files included from it in the Zeek
|
||||||
|
installation will no longer be installed. Builds won't warn about the deprecation of
|
||||||
|
``zeek::filesystem`` due to limitations of how we can mark deprecations in C++.
|
||||||
|
|
||||||
Zeek 7.2.0
|
Zeek 7.2.0
|
||||||
==========
|
==========
|
||||||
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit 72a76d774e4c7c605141fd6d11c33cc211209ed9
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include "zeek/Val.h"
|
#include "zeek/Val.h"
|
||||||
|
|
||||||
namespace zeek {
|
namespace zeek {
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "zeek/ScannedFile.h"
|
#include "zeek/ScannedFile.h"
|
||||||
|
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
#include "zeek/DebugLogger.h"
|
#include "zeek/DebugLogger.h"
|
||||||
#include "zeek/Reporter.h"
|
#include "zeek/Reporter.h"
|
||||||
|
@ -22,7 +23,7 @@ ScannedFile::ScannedFile(int arg_include_level, std::string arg_name, bool arg_s
|
||||||
canonical_path = canonical_stdin_path;
|
canonical_path = canonical_stdin_path;
|
||||||
else if ( ! arg_is_canonical ) {
|
else if ( ! arg_is_canonical ) {
|
||||||
std::error_code ec;
|
std::error_code ec;
|
||||||
auto canon = filesystem::canonical(name, ec);
|
auto canon = std::filesystem::canonical(name, ec);
|
||||||
if ( ec )
|
if ( ec )
|
||||||
zeek::reporter->FatalError("failed to get canonical path of %s: %s", name.data(), ec.message().c_str());
|
zeek::reporter->FatalError("failed to get canonical path of %s: %s", name.data(), ec.message().c_str());
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
#include <filesystem>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -88,7 +89,7 @@ struct LeftoverLog {
|
||||||
* Return the "path" (logging framework parlance) of the log without the
|
* Return the "path" (logging framework parlance) of the log without the
|
||||||
* directory or file extension. E.g. the "path" of "logs/conn.log" is just "conn".
|
* directory or file extension. E.g. the "path" of "logs/conn.log" is just "conn".
|
||||||
*/
|
*/
|
||||||
std::string Path() const { return zeek::filesystem::path(filename).stem().string(); }
|
std::string Path() const { return std::filesystem::path(filename).stem().string(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes the shadow file and returns whether it succeeded.
|
* Deletes the shadow file and returns whether it succeeded.
|
||||||
|
@ -102,7 +103,7 @@ struct LeftoverLog {
|
||||||
* prefix_basename_with("logs/conn.log", ".shadow") -> logs/.shadow.conn.log"
|
* prefix_basename_with("logs/conn.log", ".shadow") -> logs/.shadow.conn.log"
|
||||||
*/
|
*/
|
||||||
static std::string prefix_basename_with(const std::string& path, const std::string& prefix) {
|
static std::string prefix_basename_with(const std::string& path, const std::string& prefix) {
|
||||||
auto fspath = zeek::filesystem::path(path);
|
auto fspath = std::filesystem::path(path);
|
||||||
auto new_filename = prefix + fspath.filename().string();
|
auto new_filename = prefix + fspath.filename().string();
|
||||||
return (fspath.parent_path() / new_filename).string();
|
return (fspath.parent_path() / new_filename).string();
|
||||||
}
|
}
|
||||||
|
@ -440,7 +441,7 @@ bool Ascii::DoInit(const WriterInfo& info, int num_fields, const threading::Fiel
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( fname.front() != '/' && ! logdir.empty() )
|
if ( fname.front() != '/' && ! logdir.empty() )
|
||||||
fname = (zeek::filesystem::path(logdir) / fname).string();
|
fname = (std::filesystem::path(logdir) / fname).string();
|
||||||
|
|
||||||
fname += ext;
|
fname += ext;
|
||||||
|
|
||||||
|
@ -679,10 +680,10 @@ static std::vector<LeftoverLog> find_leftover_logs() {
|
||||||
|
|
||||||
// Find any .shadow files within Log::default_logdir or otherwise search in
|
// Find any .shadow files within Log::default_logdir or otherwise search in
|
||||||
// the current working directory.
|
// the current working directory.
|
||||||
auto logdir = zeek::filesystem::current_path();
|
auto logdir = std::filesystem::current_path();
|
||||||
|
|
||||||
if ( ! default_logdir.empty() )
|
if ( ! default_logdir.empty() )
|
||||||
logdir = zeek::filesystem::absolute(default_logdir);
|
logdir = std::filesystem::absolute(default_logdir);
|
||||||
|
|
||||||
auto d = opendir(logdir.string().c_str());
|
auto d = opendir(logdir.string().c_str());
|
||||||
struct dirent* dp;
|
struct dirent* dp;
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "zeek/logging/writers/sqlite/SQLite.h"
|
#include "zeek/logging/writers/sqlite/SQLite.h"
|
||||||
|
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
|
#include <filesystem>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "zeek/Desc.h"
|
#include "zeek/Desc.h"
|
||||||
|
@ -111,7 +112,7 @@ bool SQLite::DoInit(const WriterInfo& info, int arg_num_fields, const Field* con
|
||||||
num_fields = arg_num_fields;
|
num_fields = arg_num_fields;
|
||||||
fields = arg_fields;
|
fields = arg_fields;
|
||||||
|
|
||||||
auto fullpath = zeek::filesystem::path(zeek::id::find_const<StringVal>("Log::default_logdir")->ToStdString());
|
auto fullpath = std::filesystem::path(zeek::id::find_const<StringVal>("Log::default_logdir")->ToStdString());
|
||||||
|
|
||||||
fullpath /= info.path;
|
fullpath /= info.path;
|
||||||
fullpath += ".sqlite";
|
fullpath += ".sqlite";
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
#include <climits>
|
#include <climits>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
@ -504,7 +505,7 @@ when return TOK_WHEN;
|
||||||
// confused by any ZEEKPATH settings. Also, plugin files
|
// confused by any ZEEKPATH settings. Also, plugin files
|
||||||
// containing any relative @loads themselves will work.
|
// containing any relative @loads themselves will work.
|
||||||
std::error_code ec;
|
std::error_code ec;
|
||||||
auto canonical = zeek::filesystem::canonical(input_files[0]);
|
auto canonical = std::filesystem::canonical(input_files[0]);
|
||||||
if ( ec )
|
if ( ec )
|
||||||
zeek::reporter->FatalError("plugin script %s not found: %s",
|
zeek::reporter->FatalError("plugin script %s not found: %s",
|
||||||
input_files[0], ec.message().c_str());
|
input_files[0], ec.message().c_str());
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include "zeek/storage/backend/sqlite/SQLite.h"
|
#include "zeek/storage/backend/sqlite/SQLite.h"
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#include "zeek/3rdparty/sqlite3.h"
|
#include "zeek/3rdparty/sqlite3.h"
|
||||||
|
@ -81,7 +82,7 @@ OperationResult SQLite::DoOpen(OpenResultCallback* cb, RecordValPtr options) {
|
||||||
|
|
||||||
RecordValPtr backend_options = options->GetField<RecordVal>("sqlite");
|
RecordValPtr backend_options = options->GetField<RecordVal>("sqlite");
|
||||||
StringValPtr path = backend_options->GetField<StringVal>("database_path");
|
StringValPtr path = backend_options->GetField<StringVal>("database_path");
|
||||||
full_path = zeek::filesystem::path(path->ToStdString()).string();
|
full_path = std::filesystem::path(path->ToStdString()).string();
|
||||||
table_name = backend_options->GetField<StringVal>("table_name")->ToStdString();
|
table_name = backend_options->GetField<StringVal>("table_name")->ToStdString();
|
||||||
|
|
||||||
auto busy_timeout = backend_options->GetField<IntervalVal>("busy_timeout")->Get();
|
auto busy_timeout = backend_options->GetField<IntervalVal>("busy_timeout")->Get();
|
||||||
|
|
21
src/util.cc
21
src/util.cc
|
@ -25,7 +25,6 @@
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
#if defined(HAVE_MALLINFO) || defined(HAVE_MALLINFO2)
|
#if defined(HAVE_MALLINFO) || defined(HAVE_MALLINFO2)
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
|
@ -40,7 +39,9 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <filesystem>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -601,7 +602,7 @@ string normalize_path(std::string_view path) {
|
||||||
if ( stringPath._Starts_with("//") ) {
|
if ( stringPath._Starts_with("//") ) {
|
||||||
stringPath.erase(0, 2);
|
stringPath.erase(0, 2);
|
||||||
}
|
}
|
||||||
return zeek::filesystem::path(stringPath).lexically_normal().string();
|
return std::filesystem::path(stringPath).lexically_normal().string();
|
||||||
#else
|
#else
|
||||||
if ( path.find("/.") == std::string_view::npos && path.find("//") == std::string_view::npos ) {
|
if ( path.find("/.") == std::string_view::npos && path.find("//") == std::string_view::npos ) {
|
||||||
// no need to normalize anything
|
// no need to normalize anything
|
||||||
|
@ -691,7 +692,7 @@ string without_zeekpath_component(std::string_view path) {
|
||||||
std::string get_exe_path(const std::string& invocation) {
|
std::string get_exe_path(const std::string& invocation) {
|
||||||
if ( invocation.empty() )
|
if ( invocation.empty() )
|
||||||
return "";
|
return "";
|
||||||
zeek::filesystem::path invocation_path(invocation);
|
std::filesystem::path invocation_path(invocation);
|
||||||
|
|
||||||
if ( invocation_path.is_absolute() || invocation_path.root_directory() == "~" )
|
if ( invocation_path.is_absolute() || invocation_path.root_directory() == "~" )
|
||||||
// Absolute path
|
// Absolute path
|
||||||
|
@ -706,7 +707,7 @@ std::string get_exe_path(const std::string& invocation) {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (zeek::filesystem::path(cwd) / invocation_path).string();
|
return (std::filesystem::path(cwd) / invocation_path).string();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto path = getenv("PATH");
|
auto path = getenv("PATH");
|
||||||
|
@ -1719,7 +1720,7 @@ static string find_file_in_path(const string& filename, const string& path, cons
|
||||||
if ( filename.empty() )
|
if ( filename.empty() )
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
zeek::filesystem::path filepath(filename);
|
std::filesystem::path filepath(filename);
|
||||||
|
|
||||||
// If file name is an absolute path, searching within *path* is pointless.
|
// If file name is an absolute path, searching within *path* is pointless.
|
||||||
if ( filepath.is_absolute() ) {
|
if ( filepath.is_absolute() ) {
|
||||||
|
@ -1729,7 +1730,7 @@ static string find_file_in_path(const string& filename, const string& path, cons
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto abs_path = (zeek::filesystem::path(path) / filepath).string();
|
auto abs_path = (std::filesystem::path(path) / filepath).string();
|
||||||
|
|
||||||
if ( ! opt_ext.empty() ) {
|
if ( ! opt_ext.empty() ) {
|
||||||
for ( const string& ext : opt_ext ) {
|
for ( const string& ext : opt_ext ) {
|
||||||
|
@ -2425,19 +2426,19 @@ TEST_CASE("util filesystem") {
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
// TODO: adapt these tests to Windows paths
|
// TODO: adapt these tests to Windows paths
|
||||||
#else
|
#else
|
||||||
zeek::filesystem::path path1("/a/b");
|
std::filesystem::path path1("/a/b");
|
||||||
CHECK(path1.is_absolute());
|
CHECK(path1.is_absolute());
|
||||||
CHECK(! path1.is_relative());
|
CHECK(! path1.is_relative());
|
||||||
CHECK(path1.filename() == "b");
|
CHECK(path1.filename() == "b");
|
||||||
CHECK(path1.parent_path() == "/a");
|
CHECK(path1.parent_path() == "/a");
|
||||||
|
|
||||||
zeek::filesystem::path path2("/a//b//conn.log");
|
std::filesystem::path path2("/a//b//conn.log");
|
||||||
CHECK(path2.lexically_normal() == "/a/b/conn.log");
|
CHECK(path2.lexically_normal() == "/a/b/conn.log");
|
||||||
|
|
||||||
zeek::filesystem::path path3("a//b//");
|
std::filesystem::path path3("a//b//");
|
||||||
CHECK(path3.lexically_normal() == "a/b/");
|
CHECK(path3.lexically_normal() == "a/b/");
|
||||||
|
|
||||||
auto info = zeek::filesystem::space(".");
|
auto info = std::filesystem::space(".");
|
||||||
CHECK(info.capacity > 0);
|
CHECK(info.capacity > 0);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
15
src/util.h
15
src/util.h
|
@ -21,6 +21,7 @@
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <filesystem> // Remove in v8.1.
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -79,18 +80,8 @@ extern "C" {
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <filesystem>
|
|
||||||
namespace zeek {
|
|
||||||
namespace filesystem = std::filesystem;
|
|
||||||
}
|
|
||||||
inline constexpr std::string_view path_list_separator = ";";
|
inline constexpr std::string_view path_list_separator = ";";
|
||||||
#else
|
#else
|
||||||
// Expose ghc::filesystem as zeek::filesystem until we can
|
|
||||||
// switch to std::filesystem on all platforms.
|
|
||||||
#include "zeek/3rdparty/ghc/filesystem.hpp"
|
|
||||||
namespace zeek {
|
|
||||||
namespace filesystem = ghc::filesystem;
|
|
||||||
}
|
|
||||||
inline constexpr std::string_view path_list_separator = ":";
|
inline constexpr std::string_view path_list_separator = ":";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -109,6 +100,10 @@ constexpr int UID_POOL_CUSTOM_SCRIPT = 10; // First available custom script leve
|
||||||
|
|
||||||
namespace zeek {
|
namespace zeek {
|
||||||
|
|
||||||
|
// This alias is deprecated and should be removed in v8.1. There isn't a way to mark
|
||||||
|
// it so the compiler will flag it.
|
||||||
|
namespace filesystem = std::filesystem;
|
||||||
|
|
||||||
class ODesc;
|
class ODesc;
|
||||||
class RecordVal;
|
class RecordVal;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue