mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 18:43:02 +01:00
Frontported protection against orphan dbb, fixed return-else style, misc code simplifications
This commit is contained in:
parent
b7059827cd
commit
ffdb0bc40f
172
src/jrd/jrd.cpp
172
src/jrd/jrd.cpp
@ -818,7 +818,7 @@ namespace
|
||||
AutoResultSet rs(ps->executeQuery(tdbb, transaction));
|
||||
rs->fetch(tdbb);
|
||||
|
||||
UserId* u = attachment->att_user;
|
||||
const UserId* const u = attachment->att_user;
|
||||
Arg::Gds err(isc_adm_task_denied);
|
||||
err << Arg::Gds(isc_miss_prvlg) << missPriv;
|
||||
if (u && u->testFlag(USR_mapdown))
|
||||
@ -1960,10 +1960,11 @@ JAttachment* JProvider::internalAttach(CheckStatusWrapper* user_status, const ch
|
||||
|
||||
if (dbb->dbb_ast_flags & DBB_shutdown)
|
||||
ERR_post(Arg::Gds(isc_shutdown) << Arg::Str(org_filename));
|
||||
else if (err)
|
||||
|
||||
if (err)
|
||||
ERR_post(Arg::Gds(isc_att_shutdown) << Arg::Gds(err));
|
||||
else
|
||||
ERR_post(Arg::Gds(isc_att_shutdown));
|
||||
|
||||
ERR_post(Arg::Gds(isc_att_shutdown));
|
||||
}
|
||||
|
||||
if (!attachment_succeeded)
|
||||
@ -2890,58 +2891,54 @@ JAttachment* JProvider::createDatabase(CheckStatusWrapper* user_status, const ch
|
||||
}
|
||||
catch (const status_exception&)
|
||||
{
|
||||
if (options.dpb_overwrite)
|
||||
if (!options.dpb_overwrite)
|
||||
throw;
|
||||
|
||||
// isc_dpb_no_db_triggers is required for 2 reasons
|
||||
// - it disables non-DBA attaches with isc_adm_task_denied or isc_miss_prvlg error
|
||||
// - it disables any user code to be executed when we later lock
|
||||
// databases_mutex with OverwriteHolder
|
||||
ClumpletWriter dpbWriter(ClumpletReader::dpbList, MAX_DPB_SIZE, dpb, dpb_length);
|
||||
dpbWriter.insertByte(isc_dpb_no_db_triggers, 1);
|
||||
dpb = dpbWriter.getBuffer();
|
||||
dpb_length = dpbWriter.getBufferLength();
|
||||
|
||||
OverwriteHolder overwriteCheckHolder(dbb);
|
||||
|
||||
JAttachment* attachment2 = internalAttach(user_status, filename, dpb_length,
|
||||
dpb, &userId);
|
||||
switch (user_status->getErrors()[1])
|
||||
{
|
||||
// isc_dpb_no_db_triggers is required for 2 reasons
|
||||
// - it disables non-DBA attaches with isc_adm_task_denied or isc_miss_prvlg error
|
||||
// - it disables any user code to be executed when we later lock
|
||||
// databases_mutex with OverwriteHolder
|
||||
ClumpletWriter dpbWriter(ClumpletReader::dpbList, MAX_DPB_SIZE, dpb, dpb_length);
|
||||
dpbWriter.insertByte(isc_dpb_no_db_triggers, 1);
|
||||
dpb = dpbWriter.getBuffer();
|
||||
dpb_length = dpbWriter.getBufferLength();
|
||||
case isc_adm_task_denied:
|
||||
case isc_miss_prvlg:
|
||||
throw;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
OverwriteHolder overwriteCheckHolder(dbb);
|
||||
bool allow_overwrite = false;
|
||||
|
||||
JAttachment* attachment2 = internalAttach(user_status, filename, dpb_length,
|
||||
dpb, &userId);
|
||||
switch (user_status->getErrors()[1])
|
||||
{
|
||||
case isc_adm_task_denied:
|
||||
case isc_miss_prvlg:
|
||||
throw;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
bool allow_overwrite = false;
|
||||
|
||||
if (attachment2)
|
||||
{
|
||||
allow_overwrite = attachment2->getHandle()->locksmith(tdbb, DROP_DATABASE);
|
||||
attachment2->detach(user_status);
|
||||
}
|
||||
else
|
||||
{
|
||||
// clear status after failed attach
|
||||
user_status->init();
|
||||
allow_overwrite = true;
|
||||
}
|
||||
|
||||
if (allow_overwrite)
|
||||
{
|
||||
// file is a database and the user (SYSDBA or owner) has right to overwrite
|
||||
pageSpace->file = PIO_create(tdbb, expanded_name, options.dpb_overwrite, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
ERR_post(Arg::Gds(isc_no_priv) << Arg::Str("overwrite") <<
|
||||
Arg::Str("database") <<
|
||||
Arg::Str(expanded_name));
|
||||
}
|
||||
if (attachment2)
|
||||
{
|
||||
allow_overwrite = attachment2->getHandle()->locksmith(tdbb, DROP_DATABASE);
|
||||
attachment2->detach(user_status);
|
||||
}
|
||||
else
|
||||
throw;
|
||||
{
|
||||
// clear status after failed attach
|
||||
user_status->init();
|
||||
allow_overwrite = true;
|
||||
}
|
||||
|
||||
if (!allow_overwrite)
|
||||
{
|
||||
ERR_post(Arg::Gds(isc_no_priv) << Arg::Str("overwrite") <<
|
||||
Arg::Str("database") <<
|
||||
Arg::Str(expanded_name));
|
||||
}
|
||||
|
||||
// file is a database and the user (SYSDBA or owner) has right to overwrite
|
||||
pageSpace->file = PIO_create(tdbb, expanded_name, options.dpb_overwrite, false);
|
||||
}
|
||||
|
||||
#ifdef WIN_NT
|
||||
@ -3262,16 +3259,15 @@ void JAttachment::freeEngineData(CheckStatusWrapper* user_status, bool forceFree
|
||||
catch (const Exception& ex)
|
||||
{
|
||||
ex.stuffException(user_status);
|
||||
|
||||
if (user_status->getErrors()[1] != isc_att_shutdown)
|
||||
return;
|
||||
else
|
||||
|
||||
user_status->init();
|
||||
if (att)
|
||||
{
|
||||
user_status->init();
|
||||
if (att)
|
||||
{
|
||||
att->release();
|
||||
att = NULL;
|
||||
}
|
||||
att->release();
|
||||
att = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3326,11 +3322,12 @@ void JAttachment::dropDatabase(CheckStatusWrapper* user_status)
|
||||
|
||||
if (dbb->dbb_ast_flags & DBB_shutdown)
|
||||
ERR_post(Arg::Gds(isc_shutdown) << Arg::Str(file_name));
|
||||
else if (err)
|
||||
|
||||
if (err)
|
||||
ERR_post(Arg::Gds(isc_att_shutdown) << Arg::Gds(err));
|
||||
else
|
||||
ERR_post(Arg::Gds(isc_att_shutdown));
|
||||
}
|
||||
|
||||
ERR_post(Arg::Gds(isc_att_shutdown));
|
||||
}
|
||||
|
||||
if (!CCH_exclusive(tdbb, LCK_PW, WAIT_PERIOD, NULL))
|
||||
{
|
||||
@ -6494,14 +6491,13 @@ static void check_database(thread_db* tdbb, bool async)
|
||||
const PathName& filename = attachment->att_filename;
|
||||
status_exception::raise(Arg::Gds(isc_shutdown) << Arg::Str(filename));
|
||||
}
|
||||
else
|
||||
{
|
||||
Arg::Gds err(isc_att_shutdown);
|
||||
if (attachment->getStable() && attachment->getStable()->getShutError())
|
||||
err << Arg::Gds(attachment->getStable()->getShutError());
|
||||
|
||||
err.raise();
|
||||
}
|
||||
Arg::Gds err(isc_att_shutdown);
|
||||
|
||||
if (attachment->getStable() && attachment->getStable()->getShutError())
|
||||
err << Arg::Gds(attachment->getStable()->getShutError());
|
||||
|
||||
err.raise();
|
||||
}
|
||||
|
||||
// No further checks for the async calls
|
||||
@ -6617,8 +6613,8 @@ static void find_intl_charset(thread_db* tdbb, Jrd::Attachment* attachment, cons
|
||||
ERR_post(Arg::Gds(isc_bad_dpb_content) <<
|
||||
Arg::Gds(isc_invalid_attachment_charset) << Arg::Str(options->dpb_lc_ctype));
|
||||
}
|
||||
else
|
||||
attachment->att_client_charset = attachment->att_charset = id & 0xFF;
|
||||
|
||||
attachment->att_client_charset = attachment->att_charset = id & 0xFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -7697,11 +7693,21 @@ bool JRD_shutdown_database(Database* dbb, const unsigned flags)
|
||||
|
||||
fb_assert(!dbb->locked());
|
||||
|
||||
try
|
||||
{
|
||||
#ifdef SUPERSERVER_V2
|
||||
TRA_header_write(tdbb, dbb, 0); // Update transaction info on header page.
|
||||
TRA_header_write(tdbb, dbb, 0); // Update transaction info on header page.
|
||||
#endif
|
||||
if (flags & SHUT_DBB_RELEASE_POOLS)
|
||||
TRA_update_counters(tdbb, dbb);
|
||||
if (flags & SHUT_DBB_RELEASE_POOLS)
|
||||
TRA_update_counters(tdbb, dbb);
|
||||
}
|
||||
catch (const Exception&)
|
||||
{
|
||||
// Swallow exception raised from the physical I/O layer
|
||||
// (e.g. due to database file being inaccessible).
|
||||
// User attachment is already destroyed, so there's no chance
|
||||
// this dbb can be cleaned up after raising an exception.
|
||||
}
|
||||
|
||||
// Disable AST delivery as we're about to release all locks
|
||||
|
||||
@ -8127,7 +8133,11 @@ static void purge_attachment(thread_db* tdbb, StableAttachmentPart* sAtt, unsign
|
||||
if (!sAtt->getHandle())
|
||||
return;
|
||||
|
||||
bool overwriteCheck = attachment->att_flags & ATT_overwrite_check;
|
||||
unsigned shutdownFlags = SHUT_DBB_RELEASE_POOLS;
|
||||
if (flags & PURGE_LINGER)
|
||||
shutdownFlags |= SHUT_DBB_LINGER;
|
||||
if (attachment->att_flags & ATT_overwrite_check)
|
||||
shutdownFlags |= SHUT_DBB_OVERWRITE_CHECK;
|
||||
|
||||
// Unlink attachment from database
|
||||
release_attachment(tdbb, attachment);
|
||||
@ -8137,8 +8147,7 @@ static void purge_attachment(thread_db* tdbb, StableAttachmentPart* sAtt, unsign
|
||||
MutexUnlockGuard coutBlocking(*sAtt->getBlockingMutex(), FB_FUNCTION);
|
||||
|
||||
// Try to close database if there are no attachments
|
||||
JRD_shutdown_database(dbb, SHUT_DBB_RELEASE_POOLS | (flags & PURGE_LINGER ? SHUT_DBB_LINGER : 0) |
|
||||
(overwriteCheck ? SHUT_DBB_OVERWRITE_CHECK : 0));
|
||||
JRD_shutdown_database(dbb, shutdownFlags);
|
||||
}
|
||||
|
||||
|
||||
@ -8284,9 +8293,7 @@ static void getUserInfo(UserId& user, const DatabaseOptions& options, const char
|
||||
mapping.needAuthBlock(user.usr_auth_block);
|
||||
|
||||
if (mapping.mapUser(name, trusted_role) & Mapping::MAP_DOWN)
|
||||
{
|
||||
user.setFlag(USR_mapdown);
|
||||
}
|
||||
|
||||
if (creating && config) // when config is NULL we are in error handler
|
||||
{
|
||||
@ -8536,16 +8543,13 @@ static THREAD_ENTRY_DECLARE shutdown_thread(THREAD_ENTRY_PARAM arg)
|
||||
MutexLockGuard guard(databases_mutex, FB_FUNCTION);
|
||||
|
||||
for (Database* dbb = databases; dbb; dbb = dbb->dbb_next)
|
||||
{
|
||||
dbArray.push(dbb);
|
||||
}
|
||||
|
||||
// No need in databases_mutex any more
|
||||
}
|
||||
|
||||
for (unsigned n = 0; n < dbArray.getCount(); ++n)
|
||||
{
|
||||
JRD_shutdown_database(dbArray[n], SHUT_DBB_RELEASE_POOLS);
|
||||
}
|
||||
|
||||
// Extra shutdown operations
|
||||
Service::shutdownServices();
|
||||
@ -8557,9 +8561,7 @@ static THREAD_ENTRY_DECLARE shutdown_thread(THREAD_ENTRY_PARAM arg)
|
||||
}
|
||||
|
||||
if (success && semaphore)
|
||||
{
|
||||
semaphore->release();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -347,8 +347,7 @@ public:
|
||||
unset(n);
|
||||
return SEL_READY;
|
||||
}
|
||||
else
|
||||
return SEL_NO_DATA;
|
||||
return SEL_NO_DATA;
|
||||
#elif defined(HAVE_POLL)
|
||||
pollfd* pf = nullptr;
|
||||
FB_SIZE_T pos;
|
||||
@ -371,8 +370,8 @@ public:
|
||||
unset(n);
|
||||
return SEL_READY;
|
||||
}
|
||||
else
|
||||
return SEL_NO_DATA;
|
||||
|
||||
return SEL_NO_DATA;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -934,11 +933,9 @@ rem_port* INET_connect(const TEXT* name,
|
||||
port->port_connection = nullptr;
|
||||
port->port_connection = REMOTE_make_string(host.c_str());
|
||||
}
|
||||
else {
|
||||
if (packet)
|
||||
{
|
||||
host = port->port_host->str_data;
|
||||
}
|
||||
else if (packet)
|
||||
{
|
||||
host = port->port_host->str_data;
|
||||
}
|
||||
|
||||
if (protocol.isEmpty())
|
||||
@ -1030,36 +1027,31 @@ rem_port* INET_connect(const TEXT* name,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (packet)
|
||||
if (!packet) // server
|
||||
return listener_socket(port, flag, pai);
|
||||
|
||||
// client
|
||||
int optval = 1;
|
||||
n = setsockopt(port->port_handle, SOL_SOCKET, SO_KEEPALIVE, (SCHAR*) &optval, sizeof(optval));
|
||||
if (n == -1)
|
||||
{
|
||||
// client
|
||||
int optval = 1;
|
||||
n = setsockopt(port->port_handle, SOL_SOCKET, SO_KEEPALIVE, (SCHAR*) &optval, sizeof(optval));
|
||||
if (n == -1)
|
||||
{
|
||||
gds__log("setsockopt: error setting SO_KEEPALIVE");
|
||||
}
|
||||
|
||||
if (!setNoNagleOption(port))
|
||||
gds__log("setsockopt: error setting TCP_NODELAY");
|
||||
else
|
||||
{
|
||||
setFastLoopbackOption(port);
|
||||
|
||||
n = connect(port->port_handle, pai->ai_addr, pai->ai_addrlen);
|
||||
if (n != -1)
|
||||
{
|
||||
port->port_peer_name = host;
|
||||
get_peer_info(port);
|
||||
if (send_full(port, packet))
|
||||
return port;
|
||||
}
|
||||
}
|
||||
gds__log("setsockopt: error setting SO_KEEPALIVE");
|
||||
}
|
||||
|
||||
if (!setNoNagleOption(port))
|
||||
gds__log("setsockopt: error setting TCP_NODELAY");
|
||||
else
|
||||
{
|
||||
// server
|
||||
return listener_socket(port, flag, pai);
|
||||
setFastLoopbackOption(port);
|
||||
|
||||
n = connect(port->port_handle, pai->ai_addr, pai->ai_addrlen);
|
||||
if (n != -1)
|
||||
{
|
||||
port->port_peer_name = host;
|
||||
get_peer_info(port);
|
||||
if (send_full(port, packet))
|
||||
return port;
|
||||
}
|
||||
}
|
||||
|
||||
SOCLOSE(port->port_handle);
|
||||
@ -1521,17 +1513,13 @@ static rem_port* aux_connect(rem_port* port, PACKET* packet)
|
||||
if (count != -1 || !INTERRUPT_ERROR(inetErrNo))
|
||||
{
|
||||
if (count == 1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
const ISC_STATUS error_code =
|
||||
(count == 0) ? isc_net_event_connect_timeout : isc_net_event_connect_err;
|
||||
int savedError = inetErrNo;
|
||||
SOCLOSE(port->port_channel);
|
||||
inet_error(false, port, "select", error_code, savedError);
|
||||
}
|
||||
|
||||
const ISC_STATUS error_code =
|
||||
(count == 0) ? isc_net_event_connect_timeout : isc_net_event_connect_err;
|
||||
int savedError = inetErrNo;
|
||||
SOCLOSE(port->port_channel);
|
||||
inet_error(false, port, "select", error_code, savedError);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user