mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-05-12 11:02:30 -04:00
merged upstream/master
This commit is contained in:
commit
6419b03a2a
131 changed files with 6081 additions and 1473 deletions
|
@ -3,7 +3,8 @@
|
|||
* *
|
||||
* libretroshare: retroshare core library *
|
||||
* *
|
||||
* Copyright 2012 Christopher Evi-Parker <retroshare@lunamutt.com> *
|
||||
* Copyright (C) 2012 Christopher Evi-Parker <retroshare@lunamutt.com> *
|
||||
* Copyright (C) 2019 Gioacchino Mazzurco <gio@altermundi.net> *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
|
@ -22,106 +23,143 @@
|
|||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <memory.h>
|
||||
#include "util/rstime.h"
|
||||
#include <inttypes.h>
|
||||
#include <memory>
|
||||
#include <cstdint>
|
||||
#include <cerrno>
|
||||
|
||||
#include "retrodb.h"
|
||||
#include "rsdbbind.h"
|
||||
#include "util/rstime.h"
|
||||
#include "util/retrodb.h"
|
||||
#include "util/rsdbbind.h"
|
||||
#include "util/stacktrace.h"
|
||||
#include "util/rsdir.h"
|
||||
|
||||
//#define RETRODB_DEBUG
|
||||
|
||||
#ifndef NO_SQLCIPHER
|
||||
#define ENABLE_ENCRYPTED_DB
|
||||
#endif
|
||||
|
||||
const int RetroDb::OPEN_READONLY = SQLITE_OPEN_READONLY;
|
||||
const int RetroDb::OPEN_READWRITE = SQLITE_OPEN_READWRITE;
|
||||
const int RetroDb::OPEN_READWRITE_CREATE = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
|
||||
|
||||
RetroDb::RetroDb(const std::string &dbPath, int flags, const std::string& key) : mDb(NULL), mKey(key) {
|
||||
RetroDb::RetroDb(const std::string& dbPath, int flags, const std::string& key):
|
||||
mDb(nullptr), mKey(key)
|
||||
{
|
||||
bool alreadyExists = RsDirUtil::fileExists(dbPath);
|
||||
|
||||
int rc = sqlite3_open_v2(dbPath.c_str(), &mDb, flags, NULL);
|
||||
|
||||
if(rc){
|
||||
std::cerr << "Can't open database, Error code: " << sqlite3_errmsg(mDb)
|
||||
<< std::endl;
|
||||
sqlite3_close(mDb);
|
||||
mDb = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_ENCRYPTED_DB
|
||||
if(!mKey.empty())
|
||||
{
|
||||
rc = sqlite3_key(mDb, mKey.c_str(), mKey.size());
|
||||
|
||||
if(rc){
|
||||
std::cerr << "Can't key database: " << sqlite3_errmsg(mDb)
|
||||
<< std::endl;
|
||||
|
||||
sqlite3_close(mDb);
|
||||
mDb = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
char *err = NULL;
|
||||
rc = sqlite3_exec(mDb, "PRAGMA cipher_migrate;", NULL, NULL, &err);
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
std::cerr << "RetroDb::RetroDb(): Error upgrading database, error code: " << rc;
|
||||
if (err)
|
||||
{
|
||||
std::cerr << ", " << err;
|
||||
}
|
||||
std::cerr << std::endl;
|
||||
sqlite3_free(err);
|
||||
}
|
||||
|
||||
//Test DB for correct sqlcipher version
|
||||
if (sqlite3_exec(mDb, "PRAGMA user_version;", NULL, NULL, NULL) != SQLITE_OK)
|
||||
int rc = sqlite3_open_v2(dbPath.c_str(), &mDb, flags, nullptr);
|
||||
if(rc)
|
||||
{
|
||||
std::cerr << "RetroDb::RetroDb(): Failed to open database: " << dbPath << std::endl << "Trying with settings for sqlcipher version 3...";
|
||||
//Reopening the database with correct settings
|
||||
rc = sqlite3_close(mDb);
|
||||
mDb = NULL;
|
||||
if(!rc)
|
||||
rc = sqlite3_open_v2(dbPath.c_str(), &mDb, flags, NULL);
|
||||
if(!rc && !mKey.empty())
|
||||
rc = sqlite3_key(mDb, mKey.c_str(), mKey.size());
|
||||
if(!rc)
|
||||
rc = sqlite3_exec(mDb, "PRAGMA kdf_iter = 64000;", NULL, NULL, NULL);
|
||||
if (!rc && (sqlite3_exec(mDb, "PRAGMA user_version;", NULL, NULL, NULL) == SQLITE_OK))
|
||||
RsErr() << __PRETTY_FUNCTION__ << " Can't open database, Error: "
|
||||
<< rc << " " << sqlite3_errmsg(mDb) << std::endl;
|
||||
closeDb();
|
||||
print_stacktrace();
|
||||
return;
|
||||
}
|
||||
|
||||
if(alreadyExists)
|
||||
{
|
||||
/* If the database has been created by a RetroShare compiled without
|
||||
* SQLCipher, open it as a plain SQLite database instead of failing
|
||||
* miserably. If RetroShare has been compiled without SQLCipher but the
|
||||
* database seems encrypted print a meaningful error message instead of
|
||||
* crashing miserably.
|
||||
* At some point we could implement a migration SQLite <-> SQLCipher
|
||||
* mecanism and suggest it to the user, or give the option to the user
|
||||
* to choice between plain SQLite or SQLCipher database, is some cases
|
||||
* such as encrypted FS it might make sense to keep SQLite even if
|
||||
* SQLCipher is availble for performance, as encryption is already
|
||||
* provided at FS level. */
|
||||
|
||||
rc = sqlite3_exec( mDb, "PRAGMA schema_version;",
|
||||
nullptr, nullptr, nullptr );
|
||||
if( rc == SQLITE_OK )
|
||||
{
|
||||
std::cerr << "\tSuccess" << std::endl;
|
||||
} else {
|
||||
std::cerr << "\tFailed, giving up" << std::endl;
|
||||
sqlite3_close(mDb);
|
||||
mDb = NULL;
|
||||
#ifndef NO_SQLCIPHER
|
||||
RsWarn() << __PRETTY_FUNCTION__ << " The database is not encrypted: "
|
||||
<< dbPath << std::endl;
|
||||
#endif // ndef NO_SQLCIPHER
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef NO_SQLCIPHER
|
||||
RsErr() << __PRETTY_FUNCTION__ << " Error quering schema version."
|
||||
<< " Are you trying to open an encrypted database without "
|
||||
<< "compiling SQLCipher support?" << std::endl << std::endl;
|
||||
print_stacktrace();
|
||||
closeDb();
|
||||
#else // def NO_SQLCIPHER
|
||||
RsInfo() << __PRETTY_FUNCTION__ << " The database seems encrypted: "
|
||||
<< dbPath << std::endl;
|
||||
#endif // def NO_SQLCIPHER
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NO_SQLCIPHER
|
||||
if(!mKey.empty())
|
||||
{
|
||||
rc = sqlite3_key(mDb, mKey.c_str(), static_cast<int>(mKey.size()));
|
||||
|
||||
if(rc)
|
||||
{
|
||||
RsErr() << __PRETTY_FUNCTION__ << " Can't key database: " << rc
|
||||
<< " " << sqlite3_errmsg(mDb) << std::endl;
|
||||
closeDb();
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
char* err = nullptr;
|
||||
rc = sqlite3_exec(mDb, "PRAGMA cipher_migrate;", nullptr, nullptr, &err);
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
RsErr() << __PRETTY_FUNCTION__ << " Error upgrading database, error "
|
||||
<< "code: " << rc << " " << err << std::endl;
|
||||
sqlite3_free(err);
|
||||
}
|
||||
|
||||
// Test DB for correct sqlcipher version
|
||||
if(sqlite3_exec(
|
||||
mDb, "PRAGMA user_version;",
|
||||
nullptr, nullptr, nullptr ) != SQLITE_OK)
|
||||
{
|
||||
RsWarn() << __PRETTY_FUNCTION__ << " Failed to open database: "
|
||||
<< dbPath << std::endl;
|
||||
|
||||
//Reopening the database with correct settings
|
||||
closeDb();
|
||||
if(!rc) rc = sqlite3_open_v2(dbPath.c_str(), &mDb, flags, nullptr);
|
||||
if(!rc && !mKey.empty())
|
||||
rc = sqlite3_key(mDb, mKey.c_str(), static_cast<int>(mKey.size()));
|
||||
if(!rc)
|
||||
rc = sqlite3_exec( mDb, "PRAGMA kdf_iter = 64000;",
|
||||
nullptr, nullptr, nullptr );
|
||||
if (!rc && (sqlite3_exec( mDb, "PRAGMA user_version;",
|
||||
nullptr, nullptr, nullptr ) == SQLITE_OK))
|
||||
{
|
||||
RsInfo() << __PRETTY_FUNCTION__ << " Re-trying with settings for "
|
||||
<< "sqlcipher version 3 successed" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
RsErr() << __PRETTY_FUNCTION__ << " Re-trying with settings for "
|
||||
<< "sqlcipher version 3 failed, giving up" << std::endl;
|
||||
closeDb();
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif // ndef NO_SQLCIPHER
|
||||
}
|
||||
|
||||
RetroDb::~RetroDb(){
|
||||
RetroDb::~RetroDb() { closeDb(); }
|
||||
|
||||
sqlite3_close(mDb); // no-op if mDb is NULL (https://www.sqlite.org/c3ref/close.html)
|
||||
mDb = NULL ;
|
||||
}
|
||||
|
||||
void RetroDb::closeDb(){
|
||||
|
||||
int rc= sqlite3_close(mDb);
|
||||
mDb = NULL ;
|
||||
|
||||
#ifdef RETRODB_DEBUG
|
||||
std::cerr << "RetroDb::closeDb(): Error code on close: " << rc << std::endl;
|
||||
#else
|
||||
(void)rc;
|
||||
#endif
|
||||
void RetroDb::closeDb()
|
||||
{
|
||||
// no-op if mDb is nullptr (https://www.sqlite.org/c3ref/close.html)
|
||||
int rc = sqlite3_close(mDb);
|
||||
mDb = nullptr;
|
||||
|
||||
Dbg2() << __PRETTY_FUNCTION__ << " sqlite3_close return: " << rc
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
#define TIME_LIMIT 3
|
||||
|
|
|
@ -19,8 +19,7 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
#ifndef RSSQLITE_H
|
||||
#define RSSQLITE_H
|
||||
#pragma once
|
||||
|
||||
#ifdef NO_SQLCIPHER
|
||||
#include <sqlite3.h>
|
||||
|
@ -32,9 +31,10 @@
|
|||
#include <set>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include "rsdbbind.h"
|
||||
|
||||
#include "contentvalue.h"
|
||||
#include "util/rsdebug.h"
|
||||
#include "util/rsdbbind.h"
|
||||
#include "util/contentvalue.h"
|
||||
|
||||
class RetroCursor;
|
||||
|
||||
|
@ -202,6 +202,8 @@ private:
|
|||
|
||||
sqlite3* mDb;
|
||||
const std::string mKey;
|
||||
|
||||
RS_SET_CONTEXT_DEBUG_LEVEL(3)
|
||||
};
|
||||
|
||||
/*!
|
||||
|
@ -318,5 +320,3 @@ public:
|
|||
private:
|
||||
sqlite3_stmt* mStmt;
|
||||
};
|
||||
|
||||
#endif // RSSQLITE_H
|
||||
|
|
|
@ -242,6 +242,10 @@ RsTickingThread::RsTickingThread()
|
|||
#endif
|
||||
}
|
||||
|
||||
RsTickingThread::~RsTickingThread()
|
||||
{
|
||||
fullstop();
|
||||
}
|
||||
void RsSingleJobThread::runloop()
|
||||
{
|
||||
run() ;
|
||||
|
|
|
@ -287,6 +287,7 @@ class RsTickingThread: public RsThread
|
|||
{
|
||||
public:
|
||||
RsTickingThread();
|
||||
virtual ~RsTickingThread();
|
||||
|
||||
void shutdown();
|
||||
void fullstop();
|
||||
|
|
|
@ -23,12 +23,10 @@
|
|||
#include <cstdio>
|
||||
#include <csignal>
|
||||
#include <cstdlib>
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined(__linux__) && defined(__GLIBC__)
|
||||
|
||||
#include <execinfo.h>
|
||||
#include <cxxabi.h>
|
||||
#ifdef __ANDROID__
|
||||
# include "util/rsdebug.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Print a backtrace to FILE* out.
|
||||
|
@ -40,7 +38,16 @@
|
|||
* @param[in] maxFrames maximum number of stack frames you want to bu printed
|
||||
*/
|
||||
static inline void print_stacktrace(
|
||||
bool demangle = true, FILE *out = stderr, unsigned int maxFrames = 63 )
|
||||
bool demangle = true, FILE *out = stderr, unsigned int maxFrames = 63 );
|
||||
|
||||
|
||||
#if defined(__linux__) && defined(__GLIBC__)
|
||||
|
||||
#include <execinfo.h>
|
||||
#include <cxxabi.h>
|
||||
|
||||
static inline void print_stacktrace(
|
||||
bool demangle, FILE* out, unsigned int maxFrames )
|
||||
{
|
||||
if(!out)
|
||||
{
|
||||
|
@ -140,15 +147,111 @@ static inline void print_stacktrace(
|
|||
free(funcname);
|
||||
free(symbollist);
|
||||
}
|
||||
#elif defined(__ANDROID__) // defined(__linux__) && defined(__GLIBC__)
|
||||
|
||||
/* Inspired by the solution proposed by Louis Semprini on this thread
|
||||
* https://stackoverflow.com/questions/8115192/android-ndk-getting-the-backtrace/35586148
|
||||
*/
|
||||
|
||||
#include <unwind.h>
|
||||
#include <dlfcn.h>
|
||||
#include <cxxabi.h>
|
||||
|
||||
struct RsAndroidBacktraceState
|
||||
{
|
||||
void** current;
|
||||
void** end;
|
||||
};
|
||||
|
||||
static inline _Unwind_Reason_Code android_unwind_callback(
|
||||
struct _Unwind_Context* context, void* arg )
|
||||
{
|
||||
RsAndroidBacktraceState* state = static_cast<RsAndroidBacktraceState*>(arg);
|
||||
uintptr_t pc = _Unwind_GetIP(context);
|
||||
if(pc)
|
||||
{
|
||||
if (state->current == state->end) return _URC_END_OF_STACK;
|
||||
|
||||
*state->current++ = reinterpret_cast<void*>(pc);
|
||||
}
|
||||
return _URC_NO_REASON;
|
||||
}
|
||||
|
||||
static inline void print_stacktrace(
|
||||
bool demangle, FILE* /*out*/, unsigned int /*maxFrames*/)
|
||||
{
|
||||
constexpr int max = 5000;
|
||||
void* buffer[max];
|
||||
|
||||
RsAndroidBacktraceState state;
|
||||
state.current = buffer;
|
||||
state.end = buffer + max;
|
||||
|
||||
_Unwind_Backtrace(android_unwind_callback, &state);
|
||||
|
||||
RsDbg() << std::endl << std::endl
|
||||
<< 0 << " " << buffer[0] << " " << __PRETTY_FUNCTION__ << std::endl;
|
||||
|
||||
// Skip first frame which is print_stacktrace
|
||||
int count = static_cast<int>(state.current - buffer);
|
||||
for(int idx = 1; idx < count; ++idx)
|
||||
{
|
||||
const void* addr = buffer[idx];
|
||||
|
||||
/* Ignore null addresses.
|
||||
* They sometimes happen when using _Unwind_Backtrace()
|
||||
* with compiler optimizations, when the Link Register is overwritten by
|
||||
* the inner stack frames. */
|
||||
if(!addr) continue;
|
||||
|
||||
/* Ignore duplicate addresses.
|
||||
* They sometimes happen when using _Unwind_Backtrace() with compiler
|
||||
* optimizations. */
|
||||
if(addr == buffer[idx-1]) continue;
|
||||
|
||||
Dl_info info;
|
||||
if( !(dladdr(addr, &info) && info.dli_sname) )
|
||||
{
|
||||
RsDbg() << idx << " " << addr << " " << info.dli_fname
|
||||
<< " symbol not found" << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(demangle)
|
||||
{
|
||||
int status = 0;
|
||||
char* demangled = __cxxabiv1::__cxa_demangle(
|
||||
info.dli_sname, nullptr, nullptr, &status );
|
||||
|
||||
if(demangled && (status == 0))
|
||||
RsDbg() << idx << " " << addr << " " << demangled << std::endl;
|
||||
else
|
||||
RsDbg() << idx << " " << addr << " "
|
||||
<< (info.dli_sname ? info.dli_sname : info.dli_fname)
|
||||
<< " __cxa_demangle failed with: " << status
|
||||
<< std::endl;
|
||||
|
||||
free(demangled);
|
||||
}
|
||||
else RsDbg() << idx << " " << addr << " "
|
||||
<< (info.dli_sname ? info.dli_sname : info.dli_fname)
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
RsDbg() << std::endl << std::endl;
|
||||
}
|
||||
|
||||
#else // defined(__linux__) && defined(__GLIBC__)
|
||||
static inline void print_stacktrace(
|
||||
bool demangle = true, FILE *out = stderr, unsigned int max_frames = 63 )
|
||||
{
|
||||
(void) demangle;
|
||||
(void) max_frames;
|
||||
|
||||
fprintf(out, "TODO: 2016/01/01 print_stacktrace not implemented yet for WINDOWS_SYS and ANDROID\n");
|
||||
static inline void print_stacktrace(
|
||||
bool /*demangle*/, FILE* out, unsigned int /*max_frames*/ )
|
||||
{
|
||||
/** Notify the user which signal was caught. We use printf, because this
|
||||
* is the most basic output function. Once you get a crash, it is
|
||||
* possible that more complex output systems like streams and the like
|
||||
* may be corrupted. So we make the most basic call possible to the
|
||||
* lowest level, most standard print function. */
|
||||
fprintf(out, "print_stacktrace Not implemented yet for this platform\n");
|
||||
}
|
||||
#endif // defined(__linux__) && defined(__GLIBC__)
|
||||
|
||||
|
@ -169,6 +272,7 @@ struct CrashStackTrace
|
|||
#endif
|
||||
}
|
||||
|
||||
[[ noreturn ]]
|
||||
static void abortHandler(int signum)
|
||||
{
|
||||
// associate each signal with a signal name string.
|
||||
|
@ -184,6 +288,7 @@ struct CrashStackTrace
|
|||
#endif
|
||||
}
|
||||
|
||||
#ifndef __ANDROID__
|
||||
/** Notify the user which signal was caught. We use printf, because this
|
||||
* is the most basic output function. Once you get a crash, it is
|
||||
* possible that more complex output systems like streams and the like
|
||||
|
@ -193,6 +298,11 @@ struct CrashStackTrace
|
|||
fprintf(stderr, "Caught signal %d (%s)\n", signum, name);
|
||||
else
|
||||
fprintf(stderr, "Caught signal %d\n", signum);
|
||||
#else // ndef __ANDROID__
|
||||
/** On Android the best we can to is to rely on RS debug utils */
|
||||
RsFatal() << __PRETTY_FUNCTION__ << " Caught signal " << signum << " "
|
||||
<< (name ? name : "") << std::endl;
|
||||
#endif
|
||||
|
||||
print_stacktrace(false);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue