mirror of
https://github.com/valitydev/osquery-1.git
synced 2024-11-07 18:08:53 +00:00
Merge branch 'master' of github.com:facebook/osquery
This commit is contained in:
commit
adb8bf7602
@ -6,12 +6,6 @@ if(APPLE)
|
||||
set(OS_WHOLELINK_PRE "-Wl,-all_load")
|
||||
set(OS_WHOLELINK_POST "")
|
||||
else()
|
||||
if(EXISTS "/etc/redhat-release")
|
||||
set(CENTOS TRUE)
|
||||
else()
|
||||
set(UBUNTU TRUE)
|
||||
endif()
|
||||
|
||||
set(OS_COMPILE_FLAGS "-std=c++11")
|
||||
if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
|
||||
set(OS_COMPILE_FLAGS "${OS_COMPILE_FLAGS} -g")
|
||||
@ -20,13 +14,17 @@ else()
|
||||
set(OS_WHOLELINK_POST "-Wl,-no-whole-archive")
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
message("-- Building for OS X")
|
||||
elseif(UBUNTU)
|
||||
message("-- Building for Ubuntu")
|
||||
elseif(CENTOS)
|
||||
message("-- Building for CentOS")
|
||||
endif()
|
||||
# Use osquery language to set platform/os
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_SOURCE_DIR}/tools/provision.sh get_platform
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE PLATFORM
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
string(REPLACE "." "_" PLATFORM "${PLATFORM}")
|
||||
string(TOUPPER "${PLATFORM}" PLATFORM)
|
||||
list(GET PLATFORM 0 OSQUERY_BUILD_OS)
|
||||
list(GET PLATFORM 1 OSQUERY_BUILD_DISTRO)
|
||||
|
||||
# Make sure deps were built before compiling
|
||||
execute_process(
|
||||
@ -42,6 +40,16 @@ if(OSQUERY_DEPS_CHECK)
|
||||
message(WARNING "${Esc}[31m${OSQUERY_DEPS_MESSAGE}${Esc}[m")
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
message("-- Building for OS X")
|
||||
elseif(OSQUERY_BUILD_OS STREQUAL "UBUNTU")
|
||||
set(UBUNTU TRUE)
|
||||
message("-- Building for Ubuntu")
|
||||
elseif(OSQUERY_BUILD_OS STREQUAL "CENTOS")
|
||||
set(CENTOS TRUE)
|
||||
message("-- Building for CentOS")
|
||||
endif()
|
||||
|
||||
if(BUILD_SHARED_LIBS)
|
||||
set(USER_COMPILE_FLAGS "-fPIC")
|
||||
else()
|
||||
|
@ -90,7 +90,11 @@ execute_process(
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
ADD_DEFINITIONS("-DOSQUERY_BUILD_VERSION=${OSQUERY_BUILD_VERSION}")
|
||||
ADD_DEFINITIONS("
|
||||
-DOSQUERY_BUILD_VERSION=${OSQUERY_BUILD_VERSION}
|
||||
-D${OSQUERY_BUILD_OS}=1
|
||||
-D${OSQUERY_BUILD_OS}_${OSQUERY_BUILD_DISTRO}=1
|
||||
")
|
||||
|
||||
MACRO(ADD_OSQUERY_LINK LINK)
|
||||
list(APPEND OSQUERY_ADDITIONAL_LINKS ${LINK})
|
||||
|
@ -1,8 +1,8 @@
|
||||
table_name("suid_bin")
|
||||
schema([
|
||||
Column(name="path", type="std::string"),
|
||||
Column(name="unix_user", type="std::string"),
|
||||
Column(name="unix_group", type="std::string"),
|
||||
Column(name="username", type="std::string"),
|
||||
Column(name="groupname", type="std::string"),
|
||||
Column(name="permissions", type="std::string"),
|
||||
])
|
||||
implementation("suid_bin@genSuidBin")
|
||||
|
@ -1,27 +1,80 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#include <ctime>
|
||||
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <sys/stat.h>
|
||||
#include <boost/system/system_error.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <glog/logging.h>
|
||||
#include "osquery/database.h"
|
||||
|
||||
using std::string;
|
||||
using boost::lexical_cast;
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/system/system_error.hpp>
|
||||
|
||||
#include <glog/logging.h>
|
||||
|
||||
#include "osquery/database.h"
|
||||
|
||||
namespace osquery {
|
||||
namespace tables {
|
||||
|
||||
QueryData genSuidBin() {
|
||||
Row r;
|
||||
QueryData results;
|
||||
Status genBin(const boost::filesystem::path& path,
|
||||
int perms,
|
||||
QueryData& results) {
|
||||
struct stat info;
|
||||
// store user and group
|
||||
if (stat(path.c_str(), &info) != 0) {
|
||||
return Status(1, "stat failed");
|
||||
}
|
||||
|
||||
// store path
|
||||
Row r;
|
||||
r["path"] = path.string();
|
||||
|
||||
struct passwd *pw = getpwuid(info.st_uid);
|
||||
struct group *gr = getgrgid(info.st_gid);
|
||||
|
||||
// get user name + group
|
||||
std::string user;
|
||||
if (pw != nullptr) {
|
||||
user = std::string(pw->pw_name);
|
||||
} else {
|
||||
user = boost::lexical_cast<std::string>(info.st_uid);
|
||||
}
|
||||
|
||||
std::string group;
|
||||
if (gr != nullptr) {
|
||||
group = std::string(gr->gr_name);
|
||||
} else {
|
||||
group = boost::lexical_cast<std::string>(info.st_gid);
|
||||
}
|
||||
|
||||
r["username"] = user;
|
||||
r["groupname"] = group;
|
||||
|
||||
r["permissions"] = "";
|
||||
if ((perms & 04000) == 04000) {
|
||||
r["permissions"] += "S";
|
||||
}
|
||||
|
||||
if ((perms & 02000) == 02000) {
|
||||
r["permissions"] += "G";
|
||||
}
|
||||
|
||||
results.push_back(r);
|
||||
return Status(0, "OK");
|
||||
}
|
||||
|
||||
QueryData genSuidBin() {
|
||||
QueryData results;
|
||||
boost::system::error_code error;
|
||||
|
||||
#if defined(UBUNTU)
|
||||
// When building on supported Ubuntu systems, boost may ABRT.
|
||||
if (geteuid() != 0) {
|
||||
return results;
|
||||
}
|
||||
#endif
|
||||
|
||||
boost::filesystem::recursive_directory_iterator it =
|
||||
boost::filesystem::recursive_directory_iterator(
|
||||
boost::filesystem::path("/"), error);
|
||||
@ -35,32 +88,10 @@ QueryData genSuidBin() {
|
||||
while (it != end) {
|
||||
boost::filesystem::path path = *it;
|
||||
try {
|
||||
if (boost::filesystem::is_regular_file(path) &&
|
||||
((it.status().permissions() & 04000) == 04000 ||
|
||||
(it.status().permissions() & 02000) == 02000)) {
|
||||
// store path
|
||||
r["path"] = boost::lexical_cast<std::string>(path);
|
||||
|
||||
// store user and group
|
||||
if (stat(path.c_str(), &info) == 0) {
|
||||
struct passwd *pw = getpwuid(info.st_uid);
|
||||
struct group *gr = getgrgid(info.st_gid);
|
||||
// get user name
|
||||
r["unix_user"] = pw ? boost::lexical_cast<std::string>(pw->pw_name)
|
||||
: boost::lexical_cast<std::string>(info.st_uid);
|
||||
// get group
|
||||
r["unix_group"] = gr ? boost::lexical_cast<std::string>(gr->gr_name)
|
||||
: boost::lexical_cast<std::string>(info.st_gid);
|
||||
|
||||
// get permission
|
||||
r["permissions"] = "";
|
||||
r["permissions"] +=
|
||||
(it.status().permissions() & 04000) == 04000 ? "S" : "";
|
||||
r["permissions"] +=
|
||||
(it.status().permissions() & 02000) == 02000 ? "G" : "";
|
||||
|
||||
results.push_back(r);
|
||||
}
|
||||
int perms = it.status().permissions();
|
||||
if (boost::filesystem::is_regular_file(path) &&
|
||||
((perms & 04000) == 04000 || (perms & 02000) == 02000)) {
|
||||
genBin(path, perms, results);
|
||||
}
|
||||
} catch (...) {
|
||||
// handle invalid files like /dev/fd/3
|
||||
|
7
osquery/tables/templates/blacklist.cpp.in
Normal file
7
osquery/tables/templates/blacklist.cpp.in
Normal file
@ -0,0 +1,7 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
/*
|
||||
** This file is generated. Do not modify it manually!
|
||||
*/
|
||||
|
||||
void __blacklisted_{{table_name}}() {}
|
196
osquery/tables/templates/default.cpp.in
Normal file
196
osquery/tables/templates/default.cpp.in
Normal file
@ -0,0 +1,196 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
/*
|
||||
** This file is generated. Do not modify it manually!
|
||||
*/
|
||||
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include "osquery/database.h"
|
||||
#include "osquery/tables/base.h"
|
||||
#include "osquery/registry/registry.h"
|
||||
|
||||
namespace osquery { namespace tables {
|
||||
|
||||
{% if class_name == "" %}\
|
||||
osquery::QueryData {{function}}();
|
||||
{% else %}
|
||||
class {{class_name}} {
|
||||
public:
|
||||
static osquery::QueryData {{function}}();
|
||||
};
|
||||
{% endif %}\
|
||||
|
||||
struct sqlite3_{{table_name}} {
|
||||
int n;
|
||||
{% for col in schema %}\
|
||||
std::vector<{{col.type}}> {{col.name}};
|
||||
{% endfor %}\
|
||||
};
|
||||
|
||||
const std::string
|
||||
sqlite3_{{table_name}}_create_table_statement =
|
||||
"CREATE TABLE {{table_name}}("
|
||||
{% for col in schema %}\
|
||||
"{{col.name}} \
|
||||
{% if col.type == "std::string" %}VARCHAR{% endif %}\
|
||||
{% if col.type == "int" %}INTEGER{% endif %}\
|
||||
{% if col.type == "long long int" %}BIGINT{% endif %}\
|
||||
{% if not loop.last %}, {% endif %}"
|
||||
{% endfor %}\
|
||||
")";
|
||||
|
||||
int {{table_name_cc}}Create(
|
||||
sqlite3 *db,
|
||||
void *pAux,
|
||||
int argc,
|
||||
const char *const *argv,
|
||||
sqlite3_vtab **ppVtab,
|
||||
char **pzErr
|
||||
) {
|
||||
return xCreate<
|
||||
x_vtab<sqlite3_{{table_name}}>,
|
||||
sqlite3_{{table_name}}
|
||||
>(
|
||||
db, pAux, argc, argv, ppVtab, pzErr,
|
||||
sqlite3_{{table_name}}_create_table_statement.c_str()
|
||||
);
|
||||
}
|
||||
|
||||
int {{table_name_cc}}Column(
|
||||
sqlite3_vtab_cursor *cur,
|
||||
sqlite3_context *ctx,
|
||||
int col
|
||||
) {
|
||||
base_cursor *pCur = (base_cursor*)cur;
|
||||
x_vtab<sqlite3_{{table_name}}> *pVtab =
|
||||
(x_vtab<sqlite3_{{table_name}}>*)cur->pVtab;
|
||||
|
||||
if(pCur->row >= 0 && pCur->row < pVtab->pContent->n) {
|
||||
switch (col) {
|
||||
{% for col in schema %}\
|
||||
// {{ col.name }}
|
||||
case {{ loop.index0 }}:
|
||||
{% if col.type == "std::string" %}\
|
||||
sqlite3_result_text(
|
||||
ctx,
|
||||
(pVtab->pContent->{{col.name}}[pCur->row]).c_str(),
|
||||
-1,
|
||||
nullptr
|
||||
);
|
||||
{% endif %}\
|
||||
{% if col.type == "int" %}\
|
||||
sqlite3_result_int(
|
||||
ctx,
|
||||
(int)pVtab->pContent->{{col.name}}[pCur->row]
|
||||
);
|
||||
{% endif %}\
|
||||
{% if col.type == "long long int" %}\
|
||||
sqlite3_result_int64(
|
||||
ctx,
|
||||
(long long int)pVtab->pContent->{{col.name}}[pCur->row]
|
||||
);
|
||||
{% endif %}\
|
||||
break;
|
||||
{% endfor %}\
|
||||
}
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
int {{table_name_cc}}Filter(
|
||||
sqlite3_vtab_cursor *pVtabCursor,
|
||||
int idxNum,
|
||||
const char *idxStr,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
) {
|
||||
base_cursor *pCur = (base_cursor *)pVtabCursor;
|
||||
x_vtab<sqlite3_{{table_name}}> *pVtab =
|
||||
(x_vtab<sqlite3_{{table_name}}>*)pVtabCursor->pVtab;
|
||||
|
||||
pCur->row = 0;
|
||||
{% for col in schema %}\
|
||||
pVtab->pContent->{{col.name}}.clear();
|
||||
{% endfor %}\
|
||||
|
||||
{% if class_name != "" %}
|
||||
for (auto& row : osquery::tables::{{class_name}}::{{function}}()) {
|
||||
{% else %}
|
||||
for (auto& row : osquery::tables::{{function}}()) {
|
||||
{% endif %}
|
||||
{% for col in schema %}\
|
||||
{% if col.type == "std::string" %}\
|
||||
pVtab->pContent->{{col.name}}.push_back(row["{{col.name}}"]);
|
||||
{% endif %}\
|
||||
{% if col.type == "int" %}\
|
||||
try {
|
||||
pVtab->pContent->{{col.name}}\
|
||||
.push_back(boost::lexical_cast<int>(row["{{col.name}}"]));
|
||||
} catch (const boost::bad_lexical_cast& e) {
|
||||
LOG(WARNING) << "Error casting " << row["{{col.name}}"] << " to int";
|
||||
pVtab->pContent->{{col.name}}.push_back(-1);
|
||||
}
|
||||
{% endif %}\
|
||||
{% if col.type == "long long int" %}\
|
||||
try {
|
||||
pVtab->pContent->{{col.name}}\
|
||||
.push_back(boost::lexical_cast<long long>(row["{{col.name}}"]));
|
||||
} catch (const boost::bad_lexical_cast& e) {
|
||||
LOG(WARNING) << "Error casting " << row["{{col.name}}"] << " to long long int";
|
||||
pVtab->pContent->{{col.name}}.push_back(-1);
|
||||
}
|
||||
{% endif %}\
|
||||
{% endfor %}\
|
||||
}
|
||||
|
||||
pVtab->pContent->n = pVtab->pContent->{{schema[0].name}}.size();
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
static sqlite3_module {{table_name_cc}}Module = {
|
||||
0,
|
||||
{{table_name_cc}}Create,
|
||||
{{table_name_cc}}Create,
|
||||
xBestIndex,
|
||||
xDestroy<x_vtab<sqlite3_{{table_name}}>>,
|
||||
xDestroy<x_vtab<sqlite3_{{table_name}}>>,
|
||||
xOpen<base_cursor>,
|
||||
xClose<base_cursor>,
|
||||
{{table_name_cc}}Filter,
|
||||
xNext<base_cursor>,
|
||||
xEof<base_cursor, x_vtab<sqlite3_{{table_name}}>>,
|
||||
{{table_name_cc}}Column,
|
||||
xRowid<base_cursor>,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
};
|
||||
|
||||
class {{table_name_cc}}TablePlugin : public TablePlugin {
|
||||
public:
|
||||
{{table_name_cc}}TablePlugin() {}
|
||||
|
||||
int attachVtable(sqlite3 *db) {
|
||||
return sqlite3_attach_vtable<sqlite3_{{table_name}}>(
|
||||
db, "{{table_name}}", &{{table_name_cc}}Module);
|
||||
}
|
||||
|
||||
virtual ~{{table_name_cc}}TablePlugin() {}
|
||||
};
|
||||
|
||||
REGISTER_TABLE(
|
||||
"{{table_name}}",
|
||||
std::make_shared<{{table_name_cc}}TablePlugin>()
|
||||
);
|
||||
|
||||
}}
|
@ -18,218 +18,11 @@ DEVELOPING = False
|
||||
# the log format for the logging module
|
||||
LOG_FORMAT = "%(levelname)s [Line %(lineno)d]: %(message)s"
|
||||
|
||||
# BL_IMPL_TEMPLATE is the jinja template used to generate the virtual table
|
||||
# implementation file when the table is blacklisted in ./osquery/tables/specs
|
||||
BL_IMPL_TEMPLATE = """// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
# Read all implementation templates
|
||||
TEMPLATES = {}
|
||||
|
||||
/*
|
||||
** This file is generated. Do not modify it manually!
|
||||
*/
|
||||
|
||||
void __blacklisted_{{table_name}}() {}
|
||||
|
||||
"""
|
||||
|
||||
# IMPL_TEMPLATE is the jinja template used to generate the virtual table
|
||||
# implementation file
|
||||
IMPL_TEMPLATE = """// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
/*
|
||||
** This file is generated. Do not modify it manually!
|
||||
*/
|
||||
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include "osquery/database.h"
|
||||
#include "osquery/tables/base.h"
|
||||
#include "osquery/registry/registry.h"
|
||||
|
||||
namespace osquery { namespace tables {
|
||||
|
||||
{% if class_name == "" %}
|
||||
osquery::QueryData {{function}}();
|
||||
{% else %}
|
||||
class {{class_name}} {
|
||||
public:
|
||||
static osquery::QueryData {{function}}();
|
||||
};
|
||||
{% endif %}
|
||||
|
||||
struct sqlite3_{{table_name}} {
|
||||
int n;
|
||||
{% for col in schema %}\
|
||||
std::vector<{{col.type}}> {{col.name}};
|
||||
{% endfor %}\
|
||||
};
|
||||
|
||||
const std::string
|
||||
sqlite3_{{table_name}}_create_table_statement =
|
||||
"CREATE TABLE {{table_name}}("
|
||||
{% for col in schema %}\
|
||||
"{{col.name}} \
|
||||
{% if col.type == "std::string" %}VARCHAR{% endif %}\
|
||||
{% if col.type == "int" %}INTEGER{% endif %}\
|
||||
{% if col.type == "long long int" %}BIGINT{% endif %}\
|
||||
{% if not loop.last %}, {% endif %}"
|
||||
{% endfor %}\
|
||||
")";
|
||||
|
||||
int {{table_name_cc}}Create(
|
||||
sqlite3 *db,
|
||||
void *pAux,
|
||||
int argc,
|
||||
const char *const *argv,
|
||||
sqlite3_vtab **ppVtab,
|
||||
char **pzErr
|
||||
) {
|
||||
return xCreate<
|
||||
x_vtab<sqlite3_{{table_name}}>,
|
||||
sqlite3_{{table_name}}
|
||||
>(
|
||||
db, pAux, argc, argv, ppVtab, pzErr,
|
||||
sqlite3_{{table_name}}_create_table_statement.c_str()
|
||||
);
|
||||
}
|
||||
|
||||
int {{table_name_cc}}Column(
|
||||
sqlite3_vtab_cursor *cur,
|
||||
sqlite3_context *ctx,
|
||||
int col
|
||||
) {
|
||||
base_cursor *pCur = (base_cursor*)cur;
|
||||
x_vtab<sqlite3_{{table_name}}> *pVtab =
|
||||
(x_vtab<sqlite3_{{table_name}}>*)cur->pVtab;
|
||||
|
||||
if(pCur->row >= 0 && pCur->row < pVtab->pContent->n) {
|
||||
switch (col) {
|
||||
{% for col in schema %}\
|
||||
// {{ col.name }}
|
||||
case {{ loop.index0 }}:
|
||||
{% if col.type == "std::string" %}\
|
||||
sqlite3_result_text(
|
||||
ctx,
|
||||
(pVtab->pContent->{{col.name}}[pCur->row]).c_str(),
|
||||
-1,
|
||||
nullptr
|
||||
);
|
||||
{% endif %}\
|
||||
{% if col.type == "int" %}\
|
||||
sqlite3_result_int(
|
||||
ctx,
|
||||
(int)pVtab->pContent->{{col.name}}[pCur->row]
|
||||
);
|
||||
{% endif %}\
|
||||
{% if col.type == "long long int" %}\
|
||||
sqlite3_result_int64(
|
||||
ctx,
|
||||
(long long int)pVtab->pContent->{{col.name}}[pCur->row]
|
||||
);
|
||||
{% endif %}\
|
||||
break;
|
||||
{% endfor %}\
|
||||
}
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
int {{table_name_cc}}Filter(
|
||||
sqlite3_vtab_cursor *pVtabCursor,
|
||||
int idxNum,
|
||||
const char *idxStr,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
) {
|
||||
base_cursor *pCur = (base_cursor *)pVtabCursor;
|
||||
x_vtab<sqlite3_{{table_name}}> *pVtab =
|
||||
(x_vtab<sqlite3_{{table_name}}>*)pVtabCursor->pVtab;
|
||||
|
||||
pCur->row = 0;
|
||||
{% for col in schema %}\
|
||||
pVtab->pContent->{{col.name}}.clear();
|
||||
{% endfor %}\
|
||||
|
||||
{% if class_name != "" %}
|
||||
for (auto& row : osquery::tables::{{class_name}}::{{function}}()) {
|
||||
{% else %}
|
||||
for (auto& row : osquery::tables::{{function}}()) {
|
||||
{% endif %}
|
||||
{% for col in schema %}\
|
||||
{% if col.type == "std::string" %}\
|
||||
pVtab->pContent->{{col.name}}.push_back(row["{{col.name}}"]);
|
||||
{% endif %}\
|
||||
{% if col.type == "int" %}\
|
||||
try {
|
||||
pVtab->pContent->{{col.name}}\
|
||||
.push_back(boost::lexical_cast<int>(row["{{col.name}}"]));
|
||||
} catch (const boost::bad_lexical_cast& e) {
|
||||
LOG(WARNING) << "Error casting " << row["{{col.name}}"] << " to int";
|
||||
pVtab->pContent->{{col.name}}.push_back(-1);
|
||||
}
|
||||
{% endif %}\
|
||||
{% if col.type == "long long int" %}\
|
||||
try {
|
||||
pVtab->pContent->{{col.name}}\
|
||||
.push_back(boost::lexical_cast<long long>(row["{{col.name}}"]));
|
||||
} catch (const boost::bad_lexical_cast& e) {
|
||||
LOG(WARNING) << "Error casting " << row["{{col.name}}"] << " to long long int";
|
||||
pVtab->pContent->{{col.name}}.push_back(-1);
|
||||
}
|
||||
{% endif %}\
|
||||
{% endfor %}\
|
||||
}
|
||||
|
||||
pVtab->pContent->n = pVtab->pContent->{{schema[0].name}}.size();
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
static sqlite3_module {{table_name_cc}}Module = {
|
||||
0,
|
||||
{{table_name_cc}}Create,
|
||||
{{table_name_cc}}Create,
|
||||
xBestIndex,
|
||||
xDestroy<x_vtab<sqlite3_{{table_name}}>>,
|
||||
xDestroy<x_vtab<sqlite3_{{table_name}}>>,
|
||||
xOpen<base_cursor>,
|
||||
xClose<base_cursor>,
|
||||
{{table_name_cc}}Filter,
|
||||
xNext<base_cursor>,
|
||||
xEof<base_cursor, x_vtab<sqlite3_{{table_name}}>>,
|
||||
{{table_name_cc}}Column,
|
||||
xRowid<base_cursor>,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
};
|
||||
|
||||
class {{table_name_cc}}TablePlugin : public TablePlugin {
|
||||
public:
|
||||
{{table_name_cc}}TablePlugin() {}
|
||||
|
||||
int attachVtable(sqlite3 *db) {
|
||||
return sqlite3_attach_vtable<sqlite3_{{table_name}}>(
|
||||
db, "{{table_name}}", &{{table_name_cc}}Module);
|
||||
}
|
||||
|
||||
virtual ~{{table_name_cc}}TablePlugin() {}
|
||||
};
|
||||
|
||||
REGISTER_TABLE(
|
||||
"{{table_name}}",
|
||||
std::make_shared<{{table_name_cc}}TablePlugin>()
|
||||
);
|
||||
|
||||
}}
|
||||
|
||||
"""
|
||||
# Temporary reserved column names
|
||||
RESERVED = ["group"]
|
||||
|
||||
def usage():
|
||||
""" print program usage """
|
||||
@ -243,6 +36,35 @@ def to_camel_case(snake_case):
|
||||
def lightred(msg):
|
||||
return "\033[1;31m %s \033[0m" % str(msg)
|
||||
|
||||
def is_blacklisted(path, table_name):
|
||||
"""Allow blacklisting by tablename."""
|
||||
specs_path = os.path.dirname(os.path.dirname(path))
|
||||
blacklist_path = os.path.join(specs_path, "blacklist")
|
||||
if not os.path.exists(blacklist_path):
|
||||
return False
|
||||
try:
|
||||
with open(blacklist_path, "r") as fh:
|
||||
blacklist = [line.strip() for line in fh.read().split("\n")
|
||||
if len(line.strip()) > 0 and line.strip()[0] != "#"]
|
||||
if table_name in blacklist:
|
||||
return True
|
||||
except:
|
||||
# Blacklist is not readable.
|
||||
pass
|
||||
return False
|
||||
|
||||
def setup_templates(path):
|
||||
tables_path = os.path.dirname(os.path.dirname(os.path.dirname(path)))
|
||||
templates_path = os.path.join(tables_path, "templates")
|
||||
if not os.path.exists(templates_path):
|
||||
print ("Cannot read templates path: %s" % (templates_path))
|
||||
exit(1)
|
||||
for template in os.listdir(os.path.join(tables_path, "templates")):
|
||||
template_name = template.split(".", 1)[0]
|
||||
with open(os.path.join(templates_path, template), "rb") as fh:
|
||||
TEMPLATES[template_name] = fh.read().replace("\\\n", "")
|
||||
pass
|
||||
|
||||
class Singleton(object):
|
||||
"""
|
||||
Make sure that anything that subclasses Singleton can only be instantiated
|
||||
@ -278,10 +100,10 @@ class TableState(Singleton):
|
||||
def foreign_keys(self):
|
||||
return [i for i in self.schema if isinstance(i, ForeignKey)]
|
||||
|
||||
def generate(self, path, template=IMPL_TEMPLATE):
|
||||
def generate(self, path, template="default"):
|
||||
"""Generate the virtual table files"""
|
||||
logging.debug("TableState.generate")
|
||||
self.impl_content = jinja2.Template(template).render(
|
||||
self.impl_content = jinja2.Template(TEMPLATES[template]).render(
|
||||
table_name=self.table_name,
|
||||
table_name_cc=to_camel_case(self.table_name),
|
||||
schema=self.columns(),
|
||||
@ -291,6 +113,14 @@ class TableState(Singleton):
|
||||
class_name=self.class_name
|
||||
)
|
||||
|
||||
# Check for reserved column names
|
||||
for column in self.columns():
|
||||
if column.name in RESERVED:
|
||||
print (lightred(("Cannot use column name: %s in table: %s "
|
||||
"(the column name is reserved)" % (
|
||||
column.name, self.table_name))))
|
||||
exit(1)
|
||||
|
||||
path_bits = path.split("/")
|
||||
for i in range(1, len(path_bits)):
|
||||
dir_path = ""
|
||||
@ -305,7 +135,7 @@ class TableState(Singleton):
|
||||
def blacklist(self, path):
|
||||
print (lightred("Blacklisting generated %s" % path))
|
||||
logging.debug("blacklisting %s" % path)
|
||||
self.generate(path, template=BL_IMPL_TEMPLATE)
|
||||
self.generate(path, template="blacklist")
|
||||
|
||||
table = TableState()
|
||||
|
||||
@ -374,23 +204,6 @@ def implementation(impl_string):
|
||||
def description(text):
|
||||
table.description = text
|
||||
|
||||
def is_blacklisted(path, table_name):
|
||||
"""Allow blacklisting by tablename."""
|
||||
specs_path = os.path.dirname(os.path.dirname(path))
|
||||
blacklist_path = os.path.join(specs_path, "blacklist")
|
||||
if not os.path.exists(blacklist_path):
|
||||
return False
|
||||
try:
|
||||
with open(blacklist_path, "r") as fh:
|
||||
blacklist = [line.strip() for line in fh.read().split("\n")
|
||||
if len(line.strip()) > 0 and line.strip()[0] != "#"]
|
||||
if table_name in blacklist:
|
||||
return True
|
||||
except:
|
||||
# Blacklist is not readable.
|
||||
pass
|
||||
return False
|
||||
|
||||
def main(argc, argv):
|
||||
if DEVELOPING:
|
||||
logging.basicConfig(format=LOG_FORMAT, level=logging.DEBUG)
|
||||
@ -407,6 +220,7 @@ def main(argc, argv):
|
||||
# Adding a 3rd parameter will enable the blacklist
|
||||
disable_blacklist = argc > 3
|
||||
|
||||
setup_templates(filename)
|
||||
with open(filename, "rU") as file_handle:
|
||||
tree = ast.parse(file_handle.read())
|
||||
exec(compile(tree, "<string>", "exec"))
|
||||
|
16
tools/lib.sh
16
tools/lib.sh
@ -4,13 +4,26 @@ function platform() {
|
||||
local __resultvar=$1
|
||||
if [[ -f "/etc/redhat-release" ]]; then
|
||||
eval $__resultvar="centos"
|
||||
elif [[ -f "/etc/debian_version" ]]; then
|
||||
elif [[ -f "/etc/lsb-release" ]]; then
|
||||
eval $__resultvar="ubuntu"
|
||||
elif [[ -f "/etc/pf.conf" ]]; then
|
||||
eval $__resultvar="darwin"
|
||||
fi
|
||||
}
|
||||
|
||||
function distro() {
|
||||
local __resultvar=$2
|
||||
if [[ $1 = "centos" ]]; then
|
||||
eval $__resultvar="centos"`cat /etc/redhat-release | awk '{print $3}'`
|
||||
elif [[ $1 = "ubuntu" ]]; then
|
||||
eval $__resultvar=`cat /etc/*-release | grep DISTRIB_CODENAME | awk -F '=' '{print $2}'`
|
||||
elif [[ $1 = "darwin" ]]; then
|
||||
eval $__resultvar=`sw_vers -productVersion | awk -F '.' '{print $1 "." $2}'`
|
||||
else
|
||||
eval $__resultvar="unknown_version"
|
||||
fi
|
||||
}
|
||||
|
||||
function threads() {
|
||||
local __resultvar=$1
|
||||
platform OS
|
||||
@ -53,3 +66,4 @@ function contains_element() {
|
||||
for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 0; done
|
||||
return 1
|
||||
}
|
||||
|
||||
|
@ -241,13 +241,15 @@ function check() {
|
||||
HASH=`sha1sum $0 | awk '{print $1}'`
|
||||
fi
|
||||
|
||||
if [[ ! "$1" = "check" ]]; then
|
||||
if [[ "$1" = "build" ]]; then
|
||||
echo $HASH > "$2/.provision"
|
||||
return
|
||||
elif [[ ! "$1" = "check" ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ "$#" < 2 ]]; then
|
||||
echo "Usage: $0 check BUILD_PATH"
|
||||
echo "Usage: $0 (check|build) BUILD_PATH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@ -261,17 +263,22 @@ function check() {
|
||||
|
||||
function main() {
|
||||
platform OS
|
||||
distro $OS DISTRO
|
||||
|
||||
if [[ $1 = "get_platform" ]]; then
|
||||
echo "$OS;$DISTRO"
|
||||
return 0
|
||||
fi
|
||||
|
||||
mkdir -p "$WORKING_DIR"
|
||||
cd "$WORKING_DIR"
|
||||
|
||||
if [[ $OS = "centos" ]]; then
|
||||
log "detected centos"
|
||||
log "detected centos ($DISTRO)"
|
||||
elif [[ $OS = "ubuntu" ]]; then
|
||||
log "detected ubuntu"
|
||||
DISTRO=`cat /etc/*-release | grep DISTRIB_CODENAME | awk '{split($0,bits,"="); print bits[2]}'`
|
||||
log "detected ubuntu ($DISTRO)"
|
||||
elif [[ $OS = "darwin" ]]; then
|
||||
log "detected mac os x"
|
||||
log "detected mac os x ($DISTRO)"
|
||||
else
|
||||
fatal "could not detect the current operating system. exiting."
|
||||
fi
|
||||
@ -445,4 +452,4 @@ function main() {
|
||||
}
|
||||
|
||||
check $1 $2
|
||||
main
|
||||
main $1
|
||||
|
Loading…
Reference in New Issue
Block a user