2014-07-31 00:35:19 +00:00
|
|
|
// Copyright 2004-present Facebook. All Rights Reserved.
|
|
|
|
|
2014-09-10 01:54:53 +00:00
|
|
|
#pragma once
|
2014-07-31 00:35:19 +00:00
|
|
|
|
2014-08-29 07:24:48 +00:00
|
|
|
#include <stdio.h>
|
2014-08-12 00:37:49 +00:00
|
|
|
#include <sqlite3.h>
|
2014-07-31 00:35:19 +00:00
|
|
|
|
2014-08-15 07:25:30 +00:00
|
|
|
namespace osquery {
|
|
|
|
namespace tables {
|
2014-07-31 00:35:19 +00:00
|
|
|
|
|
|
|
// Our cursor object
|
|
|
|
struct base_cursor {
|
|
|
|
// similarly to sqlite3_vtab, practical implementations will likely subclass
|
|
|
|
// this structure to add additional private fields.
|
|
|
|
sqlite3_vtab_cursor base;
|
|
|
|
|
|
|
|
// field that will be used to represent the current cursor position
|
|
|
|
int row;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Our virtual table object
|
|
|
|
template <class T_STRUCT>
|
|
|
|
struct x_vtab {
|
|
|
|
// virtual table implementations will normally subclass this structure to add
|
|
|
|
// additional private and implementation-specific fields
|
|
|
|
sqlite3_vtab base;
|
|
|
|
|
|
|
|
// to get custom functionality, add our own struct as well
|
|
|
|
T_STRUCT *pContent;
|
|
|
|
};
|
|
|
|
|
|
|
|
// This method releases a connection to a virtual table, just like the
|
|
|
|
// xDisconnect method, and it also destroys the underlying table
|
|
|
|
// implementation. This method undoes the work of xCreate.
|
|
|
|
template <class T_VTAB>
|
|
|
|
int xDestroy(sqlite3_vtab *p) {
|
2014-08-15 07:25:30 +00:00
|
|
|
T_VTAB *pVtab = (T_VTAB *)p;
|
2014-08-29 04:33:44 +00:00
|
|
|
delete pVtab->pContent;
|
|
|
|
delete pVtab;
|
2014-07-31 00:35:19 +00:00
|
|
|
return SQLITE_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Open a new cursor on the base table.
|
|
|
|
template <class T_CURSOR>
|
|
|
|
int xOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor) {
|
|
|
|
// this will get overwritten if pVtab was successfully allocated. if pVtab
|
|
|
|
// wasn't allocated, it means we have no memory
|
|
|
|
int rc = SQLITE_NOMEM;
|
|
|
|
|
|
|
|
// declare a value to be used as the virtual table's cursor
|
|
|
|
T_CURSOR *pCur;
|
|
|
|
|
|
|
|
// allocate the correct amount of memory for your virtual table cursor
|
|
|
|
pCur = new T_CURSOR;
|
|
|
|
|
|
|
|
// if the cursor was successfully allocated
|
2014-08-15 07:25:30 +00:00
|
|
|
if (pCur) {
|
2014-07-31 00:35:19 +00:00
|
|
|
// overwrite the entire memory that was allocated with zeros
|
|
|
|
memset(pCur, 0, sizeof(T_CURSOR));
|
|
|
|
|
|
|
|
// cast the cursor object back to type sqlite3_vtab_cursor and assign it to
|
|
|
|
// the address that was supplied by the function call
|
|
|
|
*ppCursor = (sqlite3_vtab_cursor *)pCur;
|
|
|
|
|
|
|
|
// if you've gotten this far, everything succeeded so we can set rc, which
|
|
|
|
// will be used as our return value, to SQLITE_OK
|
|
|
|
rc = SQLITE_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// return the value we set to rc, which can either be SQLITE_OK or
|
|
|
|
// SQLITE_NOMEM
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Close a base table cursor.
|
|
|
|
template <class T_CURSOR>
|
|
|
|
int xClose(sqlite3_vtab_cursor *cur) {
|
|
|
|
// the xClose interface accepts a sqlite3_vtab_cursor. if we need to do
|
|
|
|
// something specific to our virtual table to free it, cast it back to
|
|
|
|
// your own cursor type
|
|
|
|
T_CURSOR *pCur = (T_CURSOR *)cur;
|
|
|
|
|
|
|
|
// finally, free the structure using sqlite's built-in memory allocation
|
|
|
|
// function
|
|
|
|
// in C, we would use sqlite3_free(pCur);
|
|
|
|
delete pCur;
|
|
|
|
|
|
|
|
// return SQLITE_OK because everything succeeded
|
|
|
|
return SQLITE_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// This is executed when you query a virtual table with a WHERE claue.
|
2014-08-15 07:25:30 +00:00
|
|
|
static int xBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo) {
|
2014-07-31 00:35:19 +00:00
|
|
|
return SQLITE_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Advance the cursor to the next row.
|
|
|
|
template <class T_CURSOR>
|
|
|
|
int xNext(sqlite3_vtab_cursor *cur) {
|
|
|
|
T_CURSOR *pCur = (T_CURSOR *)cur;
|
|
|
|
// increment the value of i, so that xColumn knowns what value to return
|
|
|
|
pCur->row++;
|
|
|
|
return SQLITE_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Determine if the end of the table has been reached
|
|
|
|
template <class T_CURSOR, class T_VTAB>
|
|
|
|
int xEof(sqlite3_vtab_cursor *cur) {
|
|
|
|
T_CURSOR *pCur = (T_CURSOR *)cur;
|
|
|
|
T_VTAB *pVtab = (T_VTAB *)cur->pVtab;
|
|
|
|
return pCur->row >= pVtab->pContent->n;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Retrieve the current rowid
|
|
|
|
template <class T_CURSOR>
|
|
|
|
int xRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid) {
|
|
|
|
T_CURSOR *pCur = (T_CURSOR *)cur;
|
|
|
|
// return the value of i, which is set to 0 in xFilter and incremented in
|
|
|
|
// xNext
|
|
|
|
*pRowid = pCur->row;
|
|
|
|
return SQLITE_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Table constructor for the base module.
|
|
|
|
template <class T_VTAB, class T_STRUCT>
|
2014-08-15 07:25:30 +00:00
|
|
|
int xCreate(sqlite3 *db, /* Database where module is created */
|
|
|
|
void *pAux, /* clientdata for the module */
|
|
|
|
int argc, /* Number of arguments */
|
|
|
|
const char *const *argv, /* Value for all arguments */
|
|
|
|
sqlite3_vtab **ppVtab, /* Write the new virtual table obj here */
|
|
|
|
char **pzErr, /* Put error message text here */
|
|
|
|
const char *createTableStatement /* the vtables create table
|
|
|
|
statement */
|
|
|
|
) {
|
2014-07-31 00:35:19 +00:00
|
|
|
// this will get overwritten if pVtab was successfully allocated. if pVtab
|
|
|
|
// wasn't allocated, it means we have no memory
|
|
|
|
int rc = SQLITE_NOMEM;
|
|
|
|
|
|
|
|
// allocate the correct amount of memory for your virtual table structure
|
|
|
|
T_VTAB *pVtab = new T_VTAB;
|
|
|
|
|
|
|
|
// if the virtual table structure was successfully allocated
|
2014-08-15 07:25:30 +00:00
|
|
|
if (pVtab) {
|
2014-07-31 00:35:19 +00:00
|
|
|
// overwrite the entire memory that was allocated with zeros
|
|
|
|
memset(pVtab, 0, sizeof(T_VTAB));
|
|
|
|
|
|
|
|
// the pAux argument is the copy of the client data pointer that was the
|
|
|
|
// fourth argument to the sqlite3_create_module() or
|
|
|
|
// sqlite3_create_module_v2() call that registered the virtual table
|
|
|
|
// module. This sets the pContent value of the virtual table struct to
|
|
|
|
// whatever that value was
|
2014-08-29 04:33:44 +00:00
|
|
|
pVtab->pContent = new T_STRUCT;
|
2014-07-31 00:35:19 +00:00
|
|
|
|
|
|
|
// this interface is called to declare the format (the names and datatypes
|
|
|
|
// of the columns) of the virtual tables they implement
|
2014-08-15 07:25:30 +00:00
|
|
|
rc = sqlite3_declare_vtab(db, createTableStatement);
|
2014-07-31 00:35:19 +00:00
|
|
|
}
|
2014-10-30 08:27:00 +00:00
|
|
|
// cast your virtual table object back to type sqlite3_vtab and assign it to
|
2014-07-31 00:35:19 +00:00
|
|
|
// the address supplied by the function call
|
|
|
|
*ppVtab = (sqlite3_vtab *)pVtab;
|
|
|
|
|
|
|
|
// if all went well, sqlite3_declare_vtab will have returned SQLITE_OK and
|
|
|
|
// that is what will be returned
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Invoke this routine to create a specific instance of an example object.
|
|
|
|
// The new example object is returned by the 3rd parameter.
|
|
|
|
//
|
|
|
|
// Each vtable object corresponds to a virtual table in the TEMP table
|
|
|
|
// with a name of zName.
|
|
|
|
//
|
|
|
|
// Destroy the vtable object by dropping the virtual table. If not done
|
|
|
|
// explicitly by the application, the virtual table will be dropped implicitly
|
|
|
|
// by the system when the database connection is closed.
|
|
|
|
template <class T_STRUCT>
|
2014-08-15 07:25:30 +00:00
|
|
|
int sqlite3_attach_vtable(sqlite3 *db,
|
|
|
|
const char *zName,
|
|
|
|
const sqlite3_module *module) {
|
2014-07-31 00:35:19 +00:00
|
|
|
int rc = SQLITE_OK;
|
2014-08-29 04:33:44 +00:00
|
|
|
rc = sqlite3_create_module(db, zName, module, 0);
|
2014-07-31 00:35:19 +00:00
|
|
|
if (rc == SQLITE_OK) {
|
2014-08-29 07:24:48 +00:00
|
|
|
const char zFormat[] = "CREATE VIRTUAL TABLE temp.%s USING %s";
|
2014-08-30 11:06:21 +00:00
|
|
|
size_t zSize =
|
|
|
|
(((((sizeof(zFormat) + (sizeof(zName)) + 2) * 2)) + 1) * sizeof(char));
|
|
|
|
char *zSql = (char *)malloc(1024 * sizeof(char));
|
2014-08-29 07:24:48 +00:00
|
|
|
snprintf(zSql, zSize, zFormat, zName, zName);
|
2014-07-31 00:35:19 +00:00
|
|
|
rc = sqlite3_exec(db, zSql, 0, 0, 0);
|
2014-08-29 07:24:48 +00:00
|
|
|
free(zSql);
|
2014-07-31 00:35:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
2014-08-15 07:25:30 +00:00
|
|
|
}
|
|
|
|
}
|