diff --git a/src/burp/backup.epp b/src/burp/backup.epp index c764506619..e48458c924 100644 --- a/src/burp/backup.epp +++ b/src/burp/backup.epp @@ -47,6 +47,7 @@ #include "../jrd/align.h" #include "../jrd/gdsassert.h" #include "../jrd/thd.h" +#include "../jrd/constants.h" #include "../common/stuff.h" #include "../burp/backu_proto.h" #include "../burp/burp_proto.h" @@ -126,6 +127,7 @@ void write_functions(void); void write_function_args(GDS_NAME); void write_generators(void); void write_sql_roles(void); +void write_mapping(void); void write_global_fields(void); void write_procedures(void); void write_procedure_prms(GDS_NAME); @@ -158,13 +160,17 @@ enum backup_capabilities BCK_ods10 = 8192, // FIELD_PRECISION BCK_ods11 = 16384,// rdb$description in rdb$roles and rdb$generators // rdb$base_collation_name and rdb$specific_attributes in rdb$collations - BCK_ods11_1 = 32768 // rdb$relation_type in rdb$relations + BCK_ods11_1 = 32768,// rdb$relation_type in rdb$relations // rdb$procedure_type in rdb$procedures // rdb$valid_blr in rdb$triggers // rdb$valid_blr in rdb$procedures // rdb$default_value, rdb$default_source, rdb$collation_id, // rdb$null_flag and rdb$parameter_mechanism in rdb$procedure_parameters + BCK_ods11_2 = 65536 // rdb$field_name and rdb$relation_name in rdb$procedure_parameters + // rdb$admin system role }; +// ASF: Engine that works with ODS11.1 supports access to non-existent system fields. +// Reads returns NULL and writes do nothing. #ifdef DEBUG UCHAR debug_on = 0; // able to turn this on in debug mode @@ -217,6 +223,8 @@ const rfr_tab_t rfr_table[] = //{"RDB$PROCEDURE_PARAMETERS", "RDB$COLLATION_ID", BCK_ods11_1}, //{"RDB$PROCEDURE_PARAMETERS", "RDB$NULL_FLAG", BCK_ods11_1}, //{"RDB$PROCEDURE_PARAMETERS", "RDB$PARAMETER_MECHANISM", BCK_ods11_1}, + {"RDB$PROCEDURE_PARAMETERS", "RDB$FIELD_NAME", BCK_ods11_2}, + //{"RDB$PROCEDURE_PARAMETERS", "RDB$RELATION_NAME", BCK_ods11_2}, {0, 0, 0} }; @@ -333,7 +341,7 @@ int BACKUP_backup(const TEXT* dbb_file, const TEXT* file_name) tdgbl->action->act_file = fil; if (MVOL_split_hdr_write() == FALSE) { - BURP_error(269, true, tdgbl->action->act_file->fil_name); + BURP_error(269, true, tdgbl->action->act_file->fil_name.c_str()); // msg 269 can't write a header record to file %s } } @@ -500,6 +508,14 @@ int BACKUP_backup(const TEXT* dbb_file, const TEXT* file_name) write_sql_roles(); } + if (tdgbl->BCK_capabilities & BCK_ods11) + { + // Write names mapping + BURP_verbose(296); + // msg 296 writing mapping + write_mapping(); + } + // Finish up put(tdgbl, (UCHAR) (rec_end)); @@ -3438,7 +3454,8 @@ void write_procedures(void) BurpGlobals* tdgbl = BurpGlobals::getSpecific(); - if (tdgbl->BCK_capabilities & BCK_ods11_1) { + if (tdgbl->BCK_capabilities & BCK_ods11_1) + { FOR (REQUEST_HANDLE req_handle1) X IN RDB$PROCEDURES WITH X.RDB$SYSTEM_FLAG MISSING OR X.RDB$SYSTEM_FLAG NE 1 @@ -3521,7 +3538,7 @@ void write_procedure_prms( GDS_NAME procptr) BurpGlobals* tdgbl = BurpGlobals::getSpecific(); - if (tdgbl->BCK_capabilities & BCK_ods11) + if (tdgbl->BCK_capabilities & BCK_ods11_1) { FOR (REQUEST_HANDLE tdgbl->handles_write_procedure_prms_req_handle1) X IN RDB$PROCEDURE_PARAMETERS WITH X.RDB$PROCEDURE_NAME EQ procptr @@ -3544,6 +3561,13 @@ void write_procedure_prms( GDS_NAME procptr) put_numeric (att_procedureprm_null_flag, X.RDB$NULL_FLAG); if (!X.RDB$PARAMETER_MECHANISM.NULL) put_numeric (att_procedureprm_mechanism, X.RDB$PARAMETER_MECHANISM); + + // BCK_ods11_2 + if (!X.RDB$FIELD_NAME.NULL) + PUT_TEXT(att_procedureprm_field_name, X.RDB$FIELD_NAME); + if (!X.RDB$RELATION_NAME.NULL) + PUT_TEXT(att_procedureprm_relation_name, X.RDB$RELATION_NAME); + put(tdgbl, att_end); END_FOR; ON_ERROR @@ -3896,7 +3920,7 @@ void write_sql_roles(void) { FOR (REQUEST_HANDLE req_handle1) X IN RDB$ROLES - WITH X.RDB$SYSTEM_FLAG NE 1 OR X.RDB$SYSTEM_FLAG MISSING + WITH X.RDB$SYSTEM_FLAG EQ 0 OR X.RDB$SYSTEM_FLAG MISSING put(tdgbl, rec_sql_roles); const SSHORT l = PUT_TEXT(att_role_name, X.RDB$ROLE_NAME); @@ -3937,6 +3961,48 @@ void write_sql_roles(void) MISC_release_request_silent(req_handle1); } +void write_mapping(void) +{ +/************************************** + * + * w r i t e _ m a p p i n g + * + ************************************** + * + * Functional description + * write a record in the burp file for + * each names mapping. + * + **************************************/ + isc_req_handle req_handle = 0; + + BurpGlobals* tdgbl = BurpGlobals::getSpecific(); + + if (tdgbl->BCK_capabilities & BCK_ods11_2) + { + FOR (REQUEST_HANDLE req_handle) + X IN RDB$ROLES + WITH X.RDB$ROLE_NAME EQ ADMIN_ROLE + + if (X.RDB$SYSTEM_FLAG == (ROLE_FLAG_MAY_TRUST | ROLE_FLAG_DBO)) + { + put(tdgbl, rec_mapping); + put_text(att_map_os, DOMAIN_ADMINS, strlen(DOMAIN_ADMINS) + 1); + put_text(att_map_role, ADMIN_ROLE, strlen(ADMIN_ROLE) + 1); + put(tdgbl, att_end); + BURP_verbose (297, ADMIN_ROLE); + // msg 297 writing mapping for @1 + } + + END_FOR; + ON_ERROR + general_on_error(); + END_ERROR; + } + + MISC_release_request_silent(req_handle); +} + void write_triggers(void) { /************************************** diff --git a/src/burp/burp.cpp b/src/burp/burp.cpp index 0dbdcb8e0e..66412f8d4e 100644 --- a/src/burp/burp.cpp +++ b/src/burp/burp.cpp @@ -43,6 +43,7 @@ #include "../jrd/thd.h" #include "../jrd/ods.h" // to get MAX_PAGE_SIZE #include "../jrd/svc.h" +#include "../jrd/constants.h" #include "../burp/burp.h" #include "../burp/burpswi.h" #include "../burp/std_desc.h" @@ -61,27 +62,13 @@ #ifdef HAVE_CTYPE_H #include #endif - -#ifdef SERVICE_THREAD -#include "../utilities/common/cmd_util_proto.h" -#endif - #include "../common/utils_proto.h" #ifdef UNIX #include #endif -#ifdef VMS -#include -#include -#include -#include -#endif - -#ifndef VMS #include -#endif #ifdef WIN_NT #include @@ -94,22 +81,11 @@ using MsgFormat::SafeArg; - -// The following structure in only needed if we are building a local exe -// I've commented it out to make it clear since this global variable is -// defined in burp.cpp as well, and is not relevant for SERVICE_THREAD -// MOD 23-July-2002 - const char* fopen_write_type = "w"; const char* fopen_read_type = "r"; const int open_mask = 0666; - -#ifdef VMS -const char* switch_char = "/"; -#else const char* switch_char = "-"; -#endif const char* const output_suppress = "SUPPRESS"; @@ -130,51 +106,17 @@ static SLONG get_number(const SCHAR*); static ULONG get_size(const SCHAR*, burp_fil*); static gbak_action open_files(const TEXT *, const TEXT**, bool, USHORT, const Firebird::ClumpletWriter&); -static int common_main(int, char**, Jrd::pfn_svc_output, Jrd::Service*); -#ifndef SERVICE_THREAD -BurpGlobals* gdgbl; -static int output_main(Jrd::Service*, const UCHAR*); -static int api_gbak(int, char**, USHORT, TEXT*, TEXT*, TEXT *, bool, bool, bool); -#endif +static int api_gbak(Firebird::UtilSvc*); static void burp_output(const SCHAR*, ...) ATTRIBUTE_FORMAT(1,2); static void burp_usage(); +static in_sw_tab_t* findSwitch(Firebird::string, bool); // fil.fil_length is ULONG const ULONG KBYTE = 1024; const ULONG MBYTE = KBYTE * KBYTE; const ULONG GBYTE = MBYTE * KBYTE; -#if defined (WIN95) -static bool fAnsiCP = false; -static inline void translate_cp(SCHAR* a) -{ - if (!fAnsiCP) - AnsiToOem(a, a); -} -#else -static inline void translate_cp(SCHAR* a) -{ -} -#endif -static int output_svc(Jrd::Service* output_data, const UCHAR* output_buf) -{ -/************************************** - * - * o u t p u t _ s v c - * - ************************************** - * - * Functional description - * Routine which is passed to GBAK for calling back when there is output - * if gbak is run as a service - * - **************************************/ - fprintf(stdout, "%s", output_buf); - return 0; -} - -#ifdef SERVICE_THREAD THREAD_ENTRY_DECLARE BURP_main(THREAD_ENTRY_PARAM arg) { /************************************** @@ -187,195 +129,18 @@ THREAD_ENTRY_DECLARE BURP_main(THREAD_ENTRY_PARAM arg) * Entrypoint for GBAK via services manager. * **************************************/ - Jrd::Service* service = (Jrd::Service*)arg; - const int exit_code = common_main(service->svc_argc, - const_cast(service->svc_argv.begin()), - SVC_output, service); + Firebird::UtilSvc* uSvc = (Firebird::UtilSvc*) arg; + const int exit_code = gbak(uSvc); // Mark service thread as finished. // If service is detached, cleanup memory being used by service. - SVC_finish(service, Jrd::SVC_finished); + uSvc->finish(); - return (THREAD_ENTRY_RETURN)(IPTR)(exit_code); + return (THREAD_ENTRY_RETURN)(IPTR) exit_code; } -#else // SERVICE_THREAD - -int CLIB_ROUTINE main(int argc, char* argv[]) -{ -/************************************** - * - * m a i n - * - ************************************** - * - * Functional description - * Parse and interpret command line, then "do the right thing." - * - **************************************/ -// If a "-service" switch is specified then use Admin APIs -// The code will alter the command line. - TEXT** argvp = argv; - const TEXT* const* const end = argvp + argc; - argvp++; - -// Initialize data - USHORT total = 0; - bool flag_restore, flag_verbose, flag_trusted, err; - flag_restore = flag_verbose = flag_trusted = err = false; - - TEXT *sw_user, *sw_password, *sw_service; - TEXT *d_user, *d_password, *d_service; - sw_user = sw_password = sw_service = d_user = d_password = d_service = NULL; - -/* Parse the command line for the -USER, -PASSWORD, -SERVICE, - and -VERBOSE options. Calculate a length for the new command line to be - passed to a server using services APIs */ - - // This is to avoid overwriting literal strings later. Read the warning near - // the end of this function. - char none[] = "-*NONE*"; - - while (argvp < end && !err) - { - TEXT* string = *argvp++; - USHORT len = strlen(string); - - if (total > 0 && len > 0) - ++len; // space to separate the current argument from the previous - - if (*string != *switch_char) { - total += len; - continue; - } - if (!string[1]) - string = none; - const in_sw_tab_t* in_sw_tab = burp_in_sw_table; - const TEXT* q; - for (; q = in_sw_tab->in_sw_name; in_sw_tab++) - { - TEXT c; - for (const TEXT* p = string + 1; c = *p++;) { - if (UPPER(c) != *q++) - break; - } - if (!c) - break; - } - switch (in_sw_tab->in_sw) - { - case IN_SW_BURP_C: // create database - case IN_SW_BURP_R: // replace database - case IN_SW_BURP_RECREATE: // recreate database - total += len; - flag_restore = true; - break; - case IN_SW_BURP_USER: // default user name - if (argvp >= end) - err = true; - else { - sw_user = string; - d_user = *argvp++; - } - break; - case IN_SW_BURP_PASS: // default password - if (argvp >= end) - err = true; - else { - sw_password = string; - d_password = *argvp++; - } - break; - case IN_SW_BURP_SE: // service name - if (argvp >= end) { - err = true; - } - else { - sw_service = string; - d_service = *argvp++; - } - break; - case IN_SW_BURP_V: // verify actions - total += len; - flag_verbose = true; - break; -#ifdef TRUSTED_AUTH - case IN_SW_BURP_TRUSTED_USER: // use trusted auth - total += len; - flag_trusted = true; - break; -#endif - default: - total += len; - break; - } - } - - int exit_code; - if (sw_service && !err) - { - /* Backup/restore operations will be running as a service thread. - * To make this more efficiently the isc_spb_options is used. - * This allows us to skip a conversion from the gbak command line - * switches to service parameter block in here as well as vice versa - * conversion within svc.cpp - * - * If -USER and -PASSWORD switches are used by the user within - * the gbak command line then we have to eliminate them from there. The - * password will be encrypted and added along with the user name - * within SVC_start function later on. We shall also eliminate - * the -SERVER switch because the switch has already been processed. - */ - - // Warning: altering command line. - if (sw_user) - *sw_user = '\0'; - if (sw_password) - *sw_password = '\0'; - if (sw_service) - *sw_service = '\0'; - - char* new_pass = fb_utils::get_passwd(d_password); - if (d_password) - { - *d_password = 0; - } - exit_code = api_gbak(argc, argv, total, new_pass, d_user, d_service, - flag_restore, flag_verbose, flag_trusted); - } - else - exit_code = common_main(argc, argv, output_main, NULL); - - return exit_code; -} - - -static int output_main(Jrd::Service* output_data, const UCHAR* output_buf) -{ -/************************************** - * - * o u t p u t _ m a i n - * - ************************************** - * - * Functional description - * Routine which is passed to GBAK for calling back when there is output. - * - **************************************/ - fprintf(stderr, "%s", output_buf); - return 0; -} - -static int api_gbak(int argc, - char* argv[], - USHORT length, - TEXT* password, - TEXT* user, - TEXT* service, - bool restore, - bool verbose, - bool trusted) +static int api_gbak(Firebird::UtilSvc* uSvc) { /********************************************** * @@ -387,36 +152,95 @@ static int api_gbak(int argc, * Run gbak using services APIs * **********************************************/ - BurpGlobals ldgbl; - BurpGlobals* tdgbl = &ldgbl; - BurpGlobals::putSpecific(tdgbl); - tdgbl->output_proc = output_main; + Firebird::string usr, pswd, service; + bool flag_restore = false; + bool flag_verbose = false; +#ifdef TRUSTED_AUTH + bool flag_trusted = false; +#endif - Firebird::string usr; - if (!user) + int itr; + + Firebird::UtilSvc::ArgvType& argv = uSvc->argv; + int argc = uSvc->argv.getCount(); + + for (itr = 1; itr < argc; ++itr) { - if (!trusted) + in_sw_tab_t* inSw = findSwitch(argv[itr], false); + if (! inSw) + { + continue; + } + + switch (inSw->in_sw) + { + case IN_SW_BURP_C: // create database + case IN_SW_BURP_R: // replace database + case IN_SW_BURP_RECREATE: // recreate database + flag_restore = true; + break; + case IN_SW_BURP_USER: // default user name + case IN_SW_BURP_PASS: // default password + case IN_SW_BURP_SE: // service name + if (itr >= argc - 1) + { + // user name parameter missing + BURP_error(inSw->in_sw == IN_SW_BURP_USER ? 188 : + // password parameter missing + inSw->in_sw == IN_SW_BURP_PASS ? 189 : + // service name parameter missing + 273, true); + } + else + { + argv[itr++] = 0; + switch(inSw->in_sw) + { + case IN_SW_BURP_USER: // default user name + usr = argv[itr]; + break; + case IN_SW_BURP_PASS: // default password + pswd = argv[itr]; + uSvc->hidePasswd(argv, itr); + break; + case IN_SW_BURP_SE: // service name + service = argv[itr]; + break; + } + argv[itr] = 0; + } + break; + case IN_SW_BURP_V: // verify actions + flag_verbose = true; + break; +#ifdef TRUSTED_AUTH + case IN_SW_BURP_TRUSTED_USER: // use trusted auth + flag_trusted = true; + argv[itr] = 0; + break; +#endif + } + } + + if (usr.isEmpty()) + { +#ifdef TRUSTED_AUTH + if (!flag_trusted) +#endif { fb_utils::readenv("ISC_USER", usr); } } - else - { - usr = user; - } - Firebird::string pswd; - if (!password) + if (pswd.isEmpty()) { - if (!trusted) +#ifdef TRUSTED_AUTH + if (!flag_trusted) +#endif { fb_utils::readenv("ISC_PASSWORD", pswd); } } - else - { - pswd = password; - } ISC_STATUS_ARRAY status; FB_API_HANDLE svc_handle = 0; @@ -431,50 +255,39 @@ static int api_gbak(int argc, * isc_spb_options */ - if (usr.length()) + if (usr.hasData()) { spb.insertString(isc_spb_user_name, usr); - if (user) - { - *user = '\0'; - } } - - if (pswd.length()) + if (pswd.hasData()) { spb.insertString(isc_spb_password, pswd); } - - if (trusted) +#ifdef TRUSTED_AUTH + if (flag_trusted) +#endif { spb.insertTag(isc_spb_trusted_auth); } - - const Firebird::string svc_name(service ? service : ""); - if (service) - { - *service = 0; - } - // Fill command line options Firebird::string options; - - const TEXT* const* const end = argv + argc; - argv++; - - while (argv < end) + for (itr = 1; itr < argc; ++itr) { - if (**argv && options.length() > 0) + if (!argv[itr]) + { + continue; + } + if (options.hasData()) { options += ' '; } - options += *argv++; + options += argv[itr]; } spb.insertString(isc_spb_command_line, options); - if (isc_service_attach(status, 0, svc_name.c_str(), &svc_handle, + if (isc_service_attach(status, 0, service.c_str(), &svc_handle, spb.getBufferLength(), reinterpret_cast(spb.getBuffer()))) { BURP_print_status(status); @@ -488,12 +301,12 @@ static int api_gbak(int argc, // 'isc_spb_verbose' char *thd_ptr = thd; - if (restore) + if (flag_restore) *thd_ptr++ = isc_action_svc_restore; else *thd_ptr++ = isc_action_svc_backup; - if (verbose) + if (flag_verbose) *thd_ptr++ = isc_spb_verbose; USHORT thdlen = thd_ptr - thd; @@ -523,7 +336,7 @@ static int api_gbak(int argc, char* p = respbuf; sl = p; - if (*p++ == isc_info_svc_line) + if (*p++ == isc_info_svc_line) { const ISC_USHORT len = (ISC_USHORT) isc_vax_integer(p, sizeof(ISC_USHORT)); p += sizeof(ISC_USHORT); @@ -557,13 +370,75 @@ static int api_gbak(int argc, } -#endif // SERVICE_THREAD +static bool switchMatch(const Firebird::string& sw, const char* target) +{ +/************************************** + * + * s w i t c h M a t c h + * + ************************************** + * + * Functional description + * Returns true if switch matches target + * + **************************************/ + size_t n = strlen(target); + if (n < sw.length()) + { + return false; + } + n = sw.length(); + return memcmp(sw.c_str(), target, n) == 0; +} -int common_main(int argc, - char* argv[], - Jrd::pfn_svc_output output_proc, - Jrd::Service* output_data) +static in_sw_tab_t* findSwitch(Firebird::string sw, bool throwErrors) +{ +/************************************** + * + * f i n d S w i t c h + * + ************************************** + * + * Functional description + * Returns pointer to in_sw_tab entry for current switch + * If not a switch, returns 0. + * If no match, throws if throwErrors or returns 0. + * + **************************************/ + if (sw.isEmpty()) + { + return 0; + } + if (sw[0] != *switch_char) + { + return 0; + } + sw.erase(0, 1); + sw.upper(); + + for (in_sw_tab_t* in_sw_tab = burp_in_sw_table; in_sw_tab->in_sw_name; in_sw_tab++) + { + if (switchMatch(sw, in_sw_tab->in_sw_name)) + { + return in_sw_tab; + } + } + + if (throwErrors) + { + BURP_print(137, sw.c_str()); + // msg 137 unknown switch %s + burp_usage(); + BURP_error(1, true); + // msg 1: found unknown switch + } + + return 0; +} + + +int gbak(Firebird::UtilSvc* uSvc) { /************************************** * @@ -572,96 +447,50 @@ int common_main(int argc, ************************************** * * Functional description - * Routine called by command line utility, services API, and server manager. + * Routine called by command line utility and services API. * **************************************/ const TEXT* file2 = NULL; -// TMN: This variable should probably be removed, but I left it in -// in case some platform should redefine the BURP BurpGlobals::putSpecific. -//BurpGlobals thd_context; - gbak_action action = QUIT; - BurpGlobals sgbl; - BurpGlobals *tdgbl = &sgbl; + int exit_code = FINI_ERROR; + BurpGlobals sgbl(uSvc); + BurpGlobals *tdgbl = &sgbl; BurpGlobals::putSpecific(tdgbl); + tdgbl->burp_throw = true; tdgbl->file_desc = INVALID_HANDLE_VALUE; - tdgbl->output_proc = output_proc; - tdgbl->output_data = output_data; + + Firebird::UtilSvc::ArgvType& argv = uSvc->argv; + int argc = uSvc->argv.getCount(); in_sw_tab_t* in_sw_tab; // used in several parts below. - -// Initialize static data. - for (in_sw_tab = burp_in_sw_table; in_sw_tab->in_sw_name; in_sw_tab++) { + // Initialize static data. DANGER! MT issue in services! + for (in_sw_tab = burp_in_sw_table; in_sw_tab->in_sw_name; in_sw_tab++) + { in_sw_tab->in_sw_state = FALSE; } + // test for "-service" switch + for (int itr = 1; itr < argc; ++itr) + { + in_sw_tab_t* inSw = findSwitch(argv[itr], false); + + if (inSw && inSw->in_sw == IN_SW_BURP_SE) + { + return api_gbak(uSvc); + } + } try { -#ifdef VMS - argc = VMS_parse(&argv, argc); -#endif - -/* Perform some special handling when run as a Firebird service. The - first switch can be "-svc" (lower case!) or it can be "-svc_re" followed - by 3 file descriptors to use in re-directing stdin, stdout, and stderr. - - If this utility is started as a thread in the engine, then the first switch - will be "-svc_thd". -*/ - tdgbl->gbl_sw_service_gbak = false; - tdgbl->gbl_sw_service_thd = false; - tdgbl->service_blk = NULL; tdgbl->status = tdgbl->status_vector; - - if (argc > 1 && !strcmp(argv[1], "-svc")) { - tdgbl->gbl_sw_service_gbak = true; - argv++; - argc--; + if (uSvc->isService()) + { + tdgbl->status = uSvc->getStatus(); + uSvc->started(); } - else if (argc > 1 && !strcmp(argv[1], "-svc_thd")) { - tdgbl->gbl_sw_service_gbak = true; - tdgbl->gbl_sw_service_thd = true; - tdgbl->service_blk = (Jrd::Service*) output_data; - tdgbl->status = tdgbl->service_blk->svc_status; - tdgbl->service_blk->svc_started(); - argv++; - argc--; - } - else if (argc > 4 && !strcmp(argv[1], "-svc_re")) { - tdgbl->gbl_sw_service_gbak = true; - tdgbl->output_proc = output_svc; - long redir_in = atol(argv[2]); - long redir_out = atol(argv[3]); - long redir_err = atol(argv[4]); -#ifdef WIN_NT -#if defined (WIN95) - fAnsiCP = true; -#endif - redir_in = _open_osfhandle(redir_in, 0); - redir_out = _open_osfhandle(redir_out, 0); - redir_err = _open_osfhandle(redir_err, 0); -#endif - if (redir_in != 0) - if (dup2((int) redir_in, 0)) - close((int) redir_in); - if (redir_out != 1) - if (dup2((int) redir_out, 1)) - close((int) redir_out); - if (redir_err != 2) - if (dup2((int) redir_err, 2)) - close((int) redir_err); - argv += 4; - argc -= 4; - } - -#if defined (WIN95) - if (!fAnsiCP) - fAnsiCP = (GetConsoleCP() == GetACP()); -#endif if (argc <= 1) { burp_usage(); @@ -688,70 +517,55 @@ int common_main(int argc, // Avoid overwriting literal strings. char none[] = "-*NONE*"; - const TEXT* const* const end = argv + argc; - ++argv; + for (int itr = 1; itr < argc; ++itr) + { + Firebird::string str = argv[itr]; + if (str.isEmpty()) + { + continue; + } + if (str[str.length() - 1] == ',') + { + str.erase(str.length() - 1, 1); + } - while (argv < end) { - TEXT* string = *argv; - int temp = strlen(string) - 1; - if (string[temp] == ',') - string[temp] = '\0'; // Modifying argv elements - - if (*string != *switch_char) { - if (!file || file->fil_length || !get_size(*argv, file)) { + if (str[0] != *switch_char) + { + if (!file || file->fil_length || !get_size(argv[itr], file)) + { /* Miserable thing must be a filename (dummy in a length for the backup file */ - file = (burp_fil*) BURP_alloc_zero(FIL_LEN); - file->fil_name = string; - file->fil_fd = INVALID_HANDLE_VALUE; - if (!file_list) - file->fil_length = MAX_LENGTH; - else - file->fil_length = 0; + file = FB_NEW(*getDefaultMemoryPool()) burp_fil(*getDefaultMemoryPool()); + file->fil_name = str.ToPathName(); + file->fil_length = file_list ? 0 : MAX_LENGTH; file->fil_next = file_list; file_list = file; } - argv++; } - else { - ++argv; - if (!string[1]) - string = none; - const TEXT* q; - for (in_sw_tab = burp_in_sw_table; q = in_sw_tab->in_sw_name; - in_sw_tab++) + else + { + if (str.length() == 1) { - TEXT c; - for (const TEXT *p = string + 1; c = *p++;) - if (UPPER(c) != *q++) - break; - if (!c) - break; + str = none; } + + in_sw_tab = findSwitch(str, true); + fb_assert(in_sw_tab); in_sw_tab->in_sw_state = TRUE; - if (!in_sw_tab->in_sw) { - BURP_print(137, string + 1); - // msg 137 unknown switch %s - burp_usage(); - - BURP_error(1, true); - // msg 1: found unknown switch - } - else if (in_sw_tab->in_sw == IN_SW_BURP_RECREATE) { + if (in_sw_tab->in_sw == IN_SW_BURP_RECREATE) + { int real_sw = IN_SW_BURP_C; - if ((argv < end) && (**argv != *switch_char) ) { + if ((itr < argc - 1) && (*argv[itr + 1] != *switch_char)) + { // find optional BURP_SW_OVERWRITE parameter - TEXT c; - const TEXT* param_pattern = BURP_SW_OVERWRITE; - for (const TEXT *p = *argv; c = *p++;) - if (UPPER(c) != *param_pattern++) - break; - - if (!c) { + Firebird::string next(argv[itr + 1]); + next.upper(); + if (next == BURP_SW_OVERWRITE) + { real_sw = IN_SW_BURP_R; - argv++; + itr++; } } @@ -763,119 +577,154 @@ int common_main(int argc, ; real_sw_tab->in_sw_state = TRUE; } - else if (in_sw_tab->in_sw == IN_SW_BURP_S) { - if (argv >= end) + else if (in_sw_tab->in_sw == IN_SW_BURP_S) + { + if (++itr >= argc) + { BURP_error(200, true); - // msg 200: missing parameter for the number of bytes to be skipped - tdgbl->gbl_sw_skip_count = get_number(*argv); + // msg 200: missing parameter for the number of bytes to be skipped + } + tdgbl->gbl_sw_skip_count = get_number(argv[itr]); if (!tdgbl->gbl_sw_skip_count) - BURP_error(201, true, *argv); - // msg 201: expected number of bytes to be skipped, encountered "%s" - argv++; + { + BURP_error(201, true, argv[itr]); + // msg 201: expected number of bytes to be skipped, encountered "%s" + } } - else if (in_sw_tab->in_sw == IN_SW_BURP_P) { - if (argv >= end) + else if (in_sw_tab->in_sw == IN_SW_BURP_P) + { + if (++itr >= argc) + { BURP_error(2, true); // msg 2 page size parameter missing - tdgbl->gbl_sw_page_size = (USHORT) get_number(*argv); + } + tdgbl->gbl_sw_page_size = (USHORT) get_number(argv[itr]); if (!tdgbl->gbl_sw_page_size) - BURP_error(12, true, *argv); + { + BURP_error(12, true, argv[itr]); // msg 12 expected page size, encountered "%s" - argv++; + } } - else if (in_sw_tab->in_sw == IN_SW_BURP_BU) { - if (argv >= end) + else if (in_sw_tab->in_sw == IN_SW_BURP_BU) + { + if (++itr >= argc) + { BURP_error(258, true); // msg 258 page buffers parameter missing - tdgbl->gbl_sw_page_buffers = get_number(*argv); + } + tdgbl->gbl_sw_page_buffers = get_number(argv[itr]); if (!tdgbl->gbl_sw_page_buffers) - BURP_error(259, true, *argv); + { + BURP_error(259, true, argv[itr]); // msg 259 expected page buffers, encountered "%s" - argv++; + } } - else if (in_sw_tab->in_sw == IN_SW_BURP_MODE) { - if (argv >= end) + else if (in_sw_tab->in_sw == IN_SW_BURP_MODE) + { + if (++itr >= argc) + { BURP_error(279, true); // msg 279: "read_only" or "read_write" required - string = *argv++; - if (!strcmp(string, BURP_SW_MODE_RO)) + } + str = argv[itr]; + str.lower(); + if (str == BURP_SW_MODE_RO) tdgbl->gbl_sw_mode_val = true; - else if (!strcmp(string, BURP_SW_MODE_RW)) + else if (str == BURP_SW_MODE_RW) tdgbl->gbl_sw_mode_val = false; else + { BURP_error(279, true); // msg 279: "read_only" or "read_write" required + } tdgbl->gbl_sw_mode = true; } - else if (in_sw_tab->in_sw == IN_SW_BURP_PASS) { - if (argv >= end) + else if (in_sw_tab->in_sw == IN_SW_BURP_PASS) + { + if (++itr >= argc) + { BURP_error(189, true); // password parameter missing - tdgbl->gbl_sw_password = fb_utils::get_passwd(*argv++); + } + uSvc->hidePasswd(argv, itr); + tdgbl->gbl_sw_password = argv[itr]; } - else if (in_sw_tab->in_sw == IN_SW_BURP_USER) { - if (argv >= end) + else if (in_sw_tab->in_sw == IN_SW_BURP_USER) + { + if (++itr >= argc) + { BURP_error(188, true); // user name parameter missing - tdgbl->gbl_sw_user = *argv++; + } + tdgbl->gbl_sw_user = argv[itr]; } -#ifdef TRUSTED_SERVICES - else if (in_sw_tab->in_sw == IN_SW_BURP_TRUSTED_SVC) { - if (argv >= end) + else if (in_sw_tab->in_sw == IN_SW_BURP_TRUSTED_SVC) + { + uSvc->checkService(); + if (++itr >= argc) + { BURP_error(188, true); // trusted user name parameter missing - tdgbl->gbl_sw_tr_user = *argv++; + } + tdgbl->gbl_sw_tr_user = argv[itr]; } -#endif - else if (in_sw_tab->in_sw == IN_SW_BURP_ROLE) { - if (argv >= end) + else if (in_sw_tab->in_sw == IN_SW_BURP_ROLE) + { + if (++itr >= argc) + { BURP_error(253, true); - // SQL role parameter missing - tdgbl->gbl_sw_sql_role = *argv++; + // SQL role parameter missing + } + tdgbl->gbl_sw_sql_role = argv[itr]; } - else if (in_sw_tab->in_sw == IN_SW_BURP_FA) { - if (argv >= end) + else if (in_sw_tab->in_sw == IN_SW_BURP_FA) + { + if (++itr >= argc) + { BURP_error(182, true); // msg 182 blocking factor parameter missing - tdgbl->gbl_sw_blk_factor = get_number(*argv); + } + tdgbl->gbl_sw_blk_factor = get_number(argv[itr]); if (!tdgbl->gbl_sw_blk_factor) - BURP_error(183, true, *argv); + { + BURP_error(183, true, argv[itr]); // msg 183 expected blocking factor, encountered "%s" - argv++; + } } - else if (in_sw_tab->in_sw == IN_SW_BURP_SE) { - if (argv >= end) { + else if (in_sw_tab->in_sw == IN_SW_BURP_SE) + { + if (++itr >= argc) + { BURP_error(273, true); // msg 273: service name parameter missing } + // skip a service specification in_sw_tab->in_sw_state = FALSE; - ++argv; // skip a service specification } // want to do output redirect handling now instead of waiting - else if (in_sw_tab->in_sw == IN_SW_BURP_Y) { - const TEXT* redirect = *argv; - if (argv >= end) // redirect may equal NULL - redirect = NULL; - else if (*redirect == *switch_char) - redirect = NULL; - else - ++argv; - if (!redirect) - BURP_error(4, true); - // msg 4 redirect location for output is not specified - - const TEXT *p = redirect; - TEXT c; - const TEXT* q2 = output_suppress; - tdgbl->sw_redirect = NOOUTPUT; - while (c = *p++) { - if (UPPER(c) != *q2++) { - tdgbl->sw_redirect = REDIRECT; - break; + else if (in_sw_tab->in_sw == IN_SW_BURP_Y) + { + const TEXT* redirect = NULL; + if (++itr < argc) + { + redirect = argv[itr]; + if (*redirect == *switch_char) + { + redirect = NULL; } } - if (tdgbl->sw_redirect == REDIRECT) { // not NOREDIRECT, and not NOOUTPUT + if (!redirect) + { + BURP_error(4, true); + // msg 4 redirect location for output is not specified + } + Firebird::string up(redirect); + up.upper(); + tdgbl->sw_redirect = up == output_suppress ? NOOUTPUT : REDIRECT; + + if (tdgbl->sw_redirect == REDIRECT) // not NOREDIRECT, and not NOOUTPUT + { // Make sure the status file doesn't already exist FILE* tmp_outfile = fopen(redirect, fopen_read_type); if (tmp_outfile) { @@ -895,9 +744,9 @@ int common_main(int argc, } } //else if (in_sw_tab->in_sw == IN_SW_BURP_Y) } // else - } // while (argv < end) + } // for -// reverse the linked list of file blocks + // reverse the linked list of file blocks tdgbl->gbl_sw_files = NULL; @@ -908,20 +757,23 @@ int common_main(int argc, tdgbl->gbl_sw_files = file; } -// pop off the obviously boring ones, plus do some checking + // pop off the obviously boring ones, plus do some checking const TEXT* file1 = NULL; - for (file = tdgbl->gbl_sw_files; file; file = file->fil_next) { + for (file = tdgbl->gbl_sw_files; file; file = file->fil_next) + { if (!file1) - file1 = file->fil_name; + file1 = file->fil_name.c_str(); else if (!file2) - file2 = file->fil_name; + file2 = file->fil_name.c_str(); for (file_list = file->fil_next; file_list; file_list = file_list->fil_next) { - if (!strcmp(file->fil_name, file_list->fil_name)) + if (file->fil_name == file_list->fil_name) + { BURP_error(9, true); // msg 9 mutiple sources or destinations specified + } } } @@ -1008,7 +860,7 @@ int common_main(int argc, break; case (IN_SW_BURP_PASS): - dpb.insertString(tdgbl->gbl_sw_service_gbak ? + dpb.insertString(tdgbl->uSvc->isService() ? isc_dpb_password_enc : isc_dpb_password, tdgbl->gbl_sw_password, strlen(tdgbl->gbl_sw_password)); @@ -1046,17 +898,19 @@ int common_main(int argc, strlen(tdgbl->gbl_sw_user)); break; -#ifdef TRUSTED_SERVICES case (IN_SW_BURP_TRUSTED_SVC): - while (dpb.find(isc_dpb_trusted_auth)) - { - dpb.deleteClumplet(); - } + uSvc->checkService(); + dpb.deleteWithTag(isc_dpb_trusted_auth); dpb.insertString(isc_dpb_trusted_auth, tdgbl->gbl_sw_tr_user, strlen(tdgbl->gbl_sw_tr_user)); break; -#endif + + case (IN_SW_BURP_TRUSTED_ROLE): + uSvc->checkService(); + dpb.deleteWithTag(isc_dpb_trusted_role); + dpb.insertString(isc_dpb_trusted_role, ADMIN_ROLE, strlen(ADMIN_ROLE)); + break; #ifdef TRUSTED_AUTH case (IN_SW_BURP_TRUSTED_USER): if (!dpb.find(isc_dpb_trusted_auth)) @@ -1148,7 +1002,7 @@ int common_main(int argc, int result; - tdgbl->service_blk->svc_started(); + tdgbl->uSvc->started(); switch (action) { case (RESTORE): tdgbl->gbl_sw_overwrite = (sw_replace == IN_SW_BURP_R); @@ -1172,61 +1026,70 @@ int common_main(int argc, BURP_abort(); BURP_exit_local(result, tdgbl); - return result; } // try - catch (const Firebird::Exception&) + catch (const Firebird::LongJump&) { // All calls to exit_local(), normal and error exits, wind up here - tdgbl->burp_throw = false; - const int exit_code = tdgbl->exit_code; + exit_code = tdgbl->exit_code; + } - // Close the gbak file handles if they still open - for (burp_fil* file = tdgbl->gbl_sw_backup_files; file; file = file->fil_next) + catch (const Firebird::Exception& e) + { + // Non-burp exception was caught + tdgbl->burp_throw = false; + e.stuff_exception(tdgbl->status_vector); + BURP_print_status(tdgbl->status_vector); + BURP_print(83); // msg 83 Exiting before completion due to errors + } + + // Close the gbak file handles if they still open + for (burp_fil* file = tdgbl->gbl_sw_backup_files; file; file = file->fil_next) + { + if (file->fil_fd != INVALID_HANDLE_VALUE) + close_platf(file->fil_fd); + if (exit_code != FINI_OK && + (tdgbl->action->act_action == ACT_backup_split || + tdgbl->action->act_action == ACT_backup)) { - if (file->fil_fd != INVALID_HANDLE_VALUE) - close_platf(file->fil_fd); - if (exit_code != FINI_OK - && (tdgbl->action->act_action == ACT_backup_split - || tdgbl->action->act_action == ACT_backup)) - { - unlink_platf(file->fil_name); - } + unlink_platf(file->fil_name.c_str()); } + } - // Detach from database to release system resources - if (tdgbl->db_handle != 0) { - close_out_transaction(action, &tdgbl->tr_handle); - close_out_transaction(action, &tdgbl->global_trans); - if (isc_detach_database(tdgbl->status_vector, &tdgbl->db_handle)) - { - BURP_print_status(tdgbl->status_vector); - } + // Detach from database to release system resources + if (tdgbl->db_handle != 0) { + close_out_transaction(action, &tdgbl->tr_handle); + close_out_transaction(action, &tdgbl->global_trans); + if (isc_detach_database(tdgbl->status_vector, &tdgbl->db_handle)) + { + BURP_print_status(tdgbl->status_vector); } + } - // Close the status output file - if (tdgbl->sw_redirect == REDIRECT && tdgbl->output_file != NULL) { - fclose(tdgbl->output_file); - tdgbl->output_file = NULL; - } + // Close the status output file + if (tdgbl->sw_redirect == REDIRECT && tdgbl->output_file != NULL) { + fclose(tdgbl->output_file); + tdgbl->output_file = NULL; + } - // Free all unfreed memory used by Gbak itself - while (tdgbl->head_of_mem_list != NULL) { - UCHAR* mem = tdgbl->head_of_mem_list; - tdgbl->head_of_mem_list = *((UCHAR **) tdgbl->head_of_mem_list); - gds__free(mem); - } + // Free all unfreed memory used by GBAK itself + while (tdgbl->head_of_mem_list != NULL) { + UCHAR* mem = tdgbl->head_of_mem_list; + tdgbl->head_of_mem_list = *((UCHAR **) tdgbl->head_of_mem_list); + gds__free(mem); + } - BurpGlobals::restoreSpecific(); + BurpGlobals::restoreSpecific(); -#if defined(DEBUG_GDS_ALLOC) && !defined(SERVICE_THREAD) +#if defined(DEBUG_GDS_ALLOC) + if (!uSvc->isService()) + { gds_alloc_report(0, __FILE__, __LINE__); + } #endif - // All returns occur from this point - even normal returns - return exit_code; - } + return exit_code; } @@ -1248,7 +1111,7 @@ void BURP_abort(void) BURP_print(83); // msg 83 Exiting before completion due to errors - tdgbl->service_blk->svc_started(); + tdgbl->uSvc->started(); BURP_exit_local(FINI_ERROR, tdgbl); } @@ -1266,19 +1129,17 @@ void BURP_error(USHORT errcode, * Functional description * **************************************/ -#ifdef SERVICE_THREAD BurpGlobals* tdgbl = BurpGlobals::getSpecific(); - ISC_STATUS *status = tdgbl->service_blk->svc_status; + tdgbl->uSvc->stuffStatus(burp_msg_fac, errcode, arg); + tdgbl->uSvc->started(); - CMD_UTIL_put_svc_status(status, burp_msg_fac, errcode, arg); - - tdgbl->service_blk->svc_started(); -#endif BURP_msg_partial(256); // msg 256: gbak: ERROR: BURP_msg_put(errcode, arg); if (abort) + { BURP_abort(); + } } @@ -1367,7 +1228,6 @@ void BURP_msg_put( USHORT number, TEXT buffer[256]; fb_msg_format(NULL, burp_msg_fac, number, sizeof(buffer), buffer, arg); - translate_cp(buffer); burp_output("%s\n", buffer); } @@ -1470,27 +1330,15 @@ void BURP_print_status(const ISC_STATUS* status_vector) **************************************/ if (status_vector) { const ISC_STATUS* vector = status_vector; -#ifdef SERVICE_THREAD + BurpGlobals* tdgbl = BurpGlobals::getSpecific(); - ISC_STATUS* status = tdgbl->service_blk->svc_status; - if (status != status_vector) { - int i = 0; - if (status[1]) { - while (*status && (++i < ISC_STATUS_LENGTH)) - status++; - } - for (int j = 0; status_vector[j] && (i < ISC_STATUS_LENGTH); j++, i++) - *status++ = status_vector[j]; - } -#endif + tdgbl->uSvc->stuffStatus(vector); SCHAR s[1024]; if (fb_interpret(s, sizeof(s), &vector)) { - translate_cp(s); BURP_msg_partial(256); // msg 256: gbak: ERROR: burp_output("%s\n", s); while (fb_interpret(s, sizeof(s), &vector)) { - translate_cp(s); BURP_msg_partial(256); // msg 256: gbak: ERROR: burp_output(" %s\n", s); } @@ -1520,11 +1368,9 @@ void BURP_print_warning(const ISC_STATUS* status_vector) const ISC_STATUS* vector = &status_vector[2]; SCHAR s[1024]; if (fb_interpret(s, sizeof(s), &vector)) { - translate_cp(s); BURP_msg_partial(255); // msg 255: gbak: WARNING: burp_output("%s\n", s); while (fb_interpret(s, sizeof(s), &vector)) { - translate_cp(s); BURP_msg_partial(255); // msg 255: gbak: WARNING: burp_output(" %s\n", s); } @@ -1718,7 +1564,7 @@ static gbak_action open_files(const TEXT* file1, // Now it is safe to skip a db file tdgbl->gbl_sw_backup_files = tdgbl->gbl_sw_files->fil_next; tdgbl->gbl_sw_files = tdgbl->gbl_sw_files->fil_next; - fb_assert(strcmp(tdgbl->gbl_sw_files->fil_name, *file2) == 0); + fb_assert(tdgbl->gbl_sw_files->fil_name == *file2); gbak_action flag = BACKUP; tdgbl->action->act_action = ACT_backup; @@ -1739,7 +1585,7 @@ static gbak_action open_files(const TEXT* file1, fil->fil_length *= GBYTE; break; case size_e: - BURP_error(262, true, fil->fil_name); + BURP_error(262, true, fil->fil_name.c_str()); // msg 262 size specification either missing or incorrect for file %s break; default: @@ -1753,9 +1599,9 @@ static gbak_action open_files(const TEXT* file1, } if (sw_verbose) { - BURP_print(75, fil->fil_name); // msg 75 creating file %s + BURP_print(75, fil->fil_name.c_str()); // msg 75 creating file %s } - if (!strcmp(fil->fil_name, "stdout")) + if (fil->fil_name == "stdout") { if (tdgbl->action->act_total >= 2 || fil->fil_next) { @@ -1777,15 +1623,15 @@ static gbak_action open_files(const TEXT* file1, { #ifdef WIN_NT - if ((fil->fil_fd = MVOL_open(fil->fil_name, MODE_WRITE, + if ((fil->fil_fd = MVOL_open(fil->fil_name.c_str(), MODE_WRITE, CREATE_ALWAYS)) == INVALID_HANDLE_VALUE) #else - if ((fil->fil_fd = open(fil->fil_name, MODE_WRITE, open_mask)) == -1) + if ((fil->fil_fd = open(fil->fil_name.c_str(), MODE_WRITE, open_mask)) == -1) #endif // WIN_NT { - BURP_error(65, false, fil->fil_name); + BURP_error(65, false, fil->fil_name.c_str()); // msg 65 can't open backup file %s flag = QUIT; break; @@ -1796,7 +1642,7 @@ static gbak_action open_files(const TEXT* file1, { if (fil->fil_next) { - BURP_error(262, true, fil->fil_name); + BURP_error(262, true, fil->fil_name.c_str()); // msg 262 size specification either missing or incorrect for file %s flag = QUIT; break; @@ -1874,29 +1720,34 @@ static gbak_action open_files(const TEXT* file1, tdgbl->gbl_sw_backup_files = tdgbl->gbl_sw_files; tdgbl->action->act_action = ACT_restore; - if (!strcmp(fil->fil_name, "stdin")) { + if (fil->fil_name == "stdin") + { fil->fil_fd = GBAK_STDIN_DESC(); tdgbl->file_desc = fil->fil_fd; tdgbl->gbl_sw_files = fil->fil_next; } - else { + else + { // open first file #ifdef WIN_NT - if ((fil->fil_fd = MVOL_open(fil->fil_name, MODE_READ, OPEN_EXISTING)) + if ((fil->fil_fd = MVOL_open(fil->fil_name.c_str(), MODE_READ, OPEN_EXISTING)) == INVALID_HANDLE_VALUE) #else - if ((fil->fil_fd = open(fil->fil_name, MODE_READ)) == + if ((fil->fil_fd = open(fil->fil_name.c_str(), MODE_READ)) == INVALID_HANDLE_VALUE) #endif { - BURP_error(65, true, fil->fil_name); + BURP_error(65, true, fil->fil_name.c_str()); // msg 65 can't open backup file %s return QUIT; } if (sw_verbose) - BURP_print(100, fil->fil_name); + { + BURP_print(100, fil->fil_name.c_str()); // msg 100 opened file %s + } + // read and check a header record tdgbl->action->act_file = fil; int seq = 1; @@ -1904,8 +1755,9 @@ static gbak_action open_files(const TEXT* file1, tdgbl->action->act_action = ACT_restore_join; // number of files to be join const int total = tdgbl->action->act_total; - if (fil->fil_seq != seq || seq > total) { - BURP_error(263, true, fil->fil_name); + if (fil->fil_seq != seq || seq > total) + { + BURP_error(263, true, fil->fil_name.c_str()); // msg 263 file %s out of sequence return QUIT; } @@ -1913,45 +1765,51 @@ static gbak_action open_files(const TEXT* file1, for (++seq, fil = fil->fil_next; seq <= total; fil = fil->fil_next, seq++) { - if (!fil) { + if (!fil) + { BURP_error(264, true); // msg 264 can't join -- one of the files missing return QUIT; } - if (!strcmp(fil->fil_name, "stdin")) { + if (fil->fil_name == "stdin") + { BURP_error(265, true); // msg 265 standard input is not supported when using join operation return QUIT; } tdgbl->action->act_file = fil; #ifdef WIN_NT - if ((fil->fil_fd = MVOL_open(fil->fil_name, MODE_READ, + if ((fil->fil_fd = MVOL_open(fil->fil_name.c_str(), MODE_READ, OPEN_EXISTING)) == INVALID_HANDLE_VALUE) #else - if ((fil->fil_fd = open(fil->fil_name, MODE_READ)) + if ((fil->fil_fd = open(fil->fil_name.c_str(), MODE_READ)) == INVALID_HANDLE_VALUE) #endif { - BURP_error(65, false, fil->fil_name); + BURP_error(65, false, fil->fil_name.c_str()); // msg 65 can't open backup file %s return QUIT; } if (sw_verbose) - BURP_print(100, fil->fil_name); + { + BURP_print(100, fil->fil_name.c_str()); // msg 100 opened file %s - if (MVOL_split_hdr_read() == TRUE) { + } + if (MVOL_split_hdr_read() == TRUE) + { if ((total != tdgbl->action->act_total) || (seq != fil->fil_seq) || (seq > total)) { - BURP_error(263, true, fil->fil_name); + BURP_error(263, true, fil->fil_name.c_str()); // msg 263 file %s out of sequence return QUIT; } } - else { - BURP_error(267, true, fil->fil_name); + else + { + BURP_error(267, true, fil->fil_name.c_str()); // msg 267 backup file %s might be corrupt return QUIT; } @@ -1969,7 +1827,7 @@ static gbak_action open_files(const TEXT* file1, // assume -- this is a single backup file because we were // not able to read a split header record. #ifdef WIN_NT - if (strnicmp(fil->fil_name, "\\\\.\\tape", 8)) + if (strnicmp(fil->fil_name.c_str(), "\\\\.\\tape", 8)) SetFilePointer(fil->fil_fd, 0, NULL, FILE_BEGIN); else SetTapePosition(fil->fil_fd, TAPE_REWIND, 0, 0, 0, FALSE); @@ -1985,7 +1843,7 @@ static gbak_action open_files(const TEXT* file1, // If we got here, we've opened a backup file, and we're // thinking about creating or replacing a database. - *file2 = tdgbl->gbl_sw_files->fil_name; + *file2 = tdgbl->gbl_sw_files->fil_name.c_str(); if (tdgbl->gbl_sw_files->fil_size_code != size_n) BURP_error(262, true, *file2); // msg 262 size specification either missing or incorrect for file %s @@ -2037,14 +1895,17 @@ static gbak_action open_files(const TEXT* file1, * service will think that there is an error if isc_attach_database failed * like it should have (if creating a database). */ - if (tdgbl->gbl_sw_service_thd) + if (tdgbl->uSvc->isService()) memset(tdgbl->status, 0, sizeof(ISC_STATUS_ARRAY)); // check the file size specification - for (fil = tdgbl->gbl_sw_files; fil; fil = fil->fil_next) { + for (fil = tdgbl->gbl_sw_files; fil; fil = fil->fil_next) + { if (fil->fil_size_code != size_n) - BURP_error(262, true, fil->fil_name); + { + BURP_error(262, true, fil->fil_name.c_str()); // msg 262 size specification either missing or incorrect for file %s + } } return RESTORE; @@ -2064,34 +1925,28 @@ static void burp_output( const SCHAR* format, ...) * **************************************/ va_list arglist; - UCHAR buf[1000]; - int exit_code; BurpGlobals* tdgbl = BurpGlobals::getSpecific(); - if (tdgbl->sw_redirect == NOOUTPUT || format[0] == '\0') { - exit_code = - tdgbl->output_proc(tdgbl->output_data, - (UCHAR*)("")); + if (tdgbl->sw_redirect == NOOUTPUT || format[0] == '\0') + { + tdgbl->uSvc->output(""); } - else if (tdgbl->sw_redirect == REDIRECT && tdgbl->output_file != NULL) { + else if (tdgbl->sw_redirect == REDIRECT && tdgbl->output_file != NULL) + { va_start(arglist, format); vfprintf(tdgbl->output_file, format, arglist); va_end(arglist); - exit_code = - tdgbl->output_proc(tdgbl->output_data, - (UCHAR*)("")); + tdgbl->uSvc->output(""); } - else { + else + { va_start(arglist, format); - vsprintf((char *) buf, format, arglist); + Firebird::string buf; + buf.vprintf(format, arglist); va_end(arglist); - - exit_code = tdgbl->output_proc(tdgbl->output_data, buf); + tdgbl->uSvc->output(buf.c_str()); } - - if (exit_code != 0) - BURP_exit_local(exit_code, tdgbl); } diff --git a/src/burp/burp.h b/src/burp/burp.h index 3178be68c2..d1d77f7e32 100644 --- a/src/burp/burp.h +++ b/src/burp/burp.h @@ -35,8 +35,9 @@ #include "../jrd/dsc.h" #include "../burp/misc_proto.h" #include "../jrd/gds_proto.h" -#include "../jrd/thd.h" - +#include "../jrd/ThreadData.h" +#include "../common/UtilSvc.h" + #ifdef HAVE_UNISTD_H #include #endif @@ -109,7 +110,8 @@ enum rec_type { rec_chk_constraint, // Check constraints rec_charset, // Character sets rec_collation, // Collations - rec_sql_roles // SQL roles + rec_sql_roles, // SQL roles + rec_mapping // Mapping of security names }; @@ -474,6 +476,8 @@ enum att_type { att_procedureprm_collation_id, att_procedureprm_null_flag, att_procedureprm_mechanism, + att_procedureprm_field_name, + att_procedureprm_relation_name, // Exception attributes @@ -528,7 +532,12 @@ enum att_type { att_coll_description, att_coll_funct, att_coll_base_collation_name, - att_coll_specific_attr + att_coll_specific_attr, + + // Names mapping + att_map_os = SERIES, + att_map_user, + att_map_role }; @@ -731,16 +740,20 @@ enum SIZE_CODE { size_e // error }; -struct burp_fil { +class burp_fil +{ +public: burp_fil* fil_next; - TEXT* fil_name; + Firebird::PathName fil_name; ULONG fil_length; DESC fil_fd; USHORT fil_seq; SIZE_CODE fil_size_code; -}; -const size_t FIL_LEN = sizeof(burp_fil); +burp_fil(Firebird::MemoryPool& p) + : fil_next(0), fil_name(p), fil_length(0), + fil_fd(INVALID_HANDLE_VALUE), fil_seq(0), fil_size_code(size_n) { } +}; /* Split & Join stuff */ @@ -792,15 +805,12 @@ static const char HDR_SPLIT_TAG6[] = "InterBase/gbak, "; const unsigned int MIN_SPLIT_SIZE = 2048; // bytes // Global switches and data -#ifndef SERVICE_THREAD -class BurpGlobals; -extern BurpGlobals* gdgbl; -#endif class BurpGlobals : public ThreadData { public: - BurpGlobals() : ThreadData(ThreadData::tddGBL), flag_on_line(true) + BurpGlobals(Firebird::UtilSvc* us) + : ThreadData(ThreadData::tddGBL), flag_on_line(true), uSvc(us), firstMap(true) { // this is VERY dirty hack to keep current behaviour memset (&gbl_database_file_name, 0, @@ -828,8 +838,6 @@ public: USHORT gbl_sw_blk_factor; bool gbl_sw_no_reserve; bool gbl_sw_old_descriptions; - bool gbl_sw_service_gbak; - bool gbl_sw_service_thd; bool gbl_sw_convert_ext_tables; bool gbl_sw_mode; bool gbl_sw_mode_val; @@ -837,9 +845,7 @@ public: const SCHAR* gbl_sw_sql_role; const SCHAR* gbl_sw_user; const SCHAR* gbl_sw_password; -#ifdef TRUSTED_SERVICES const SCHAR* gbl_sw_tr_user; -#endif SLONG gbl_sw_skip_count; SLONG gbl_sw_page_buffers; burp_fil* gbl_sw_files; @@ -877,10 +883,8 @@ public: ISC_STATUS_ARRAY status_vector; int exit_code; UCHAR* head_of_mem_list; - Jrd::pfn_svc_output output_proc; - Jrd::Service* output_data; FILE* output_file; - Jrd::Service* service_blk; + /* * Link list of global fields that were converted from V3 sub_type * to V4 char_set_id/collate_id. Needed for local fields conversion. @@ -917,6 +921,7 @@ public: isc_req_handle handles_get_relation_req_handle1; isc_req_handle handles_get_security_class_req_handle1; isc_req_handle handles_get_sql_roles_req_handle1; + isc_req_handle handles_get_mapping_req_handle1; isc_req_handle handles_get_trigger_message_req_handle1; isc_req_handle handles_get_trigger_message_req_handle2; isc_req_handle handles_get_trigger_old_req_handle1; @@ -941,7 +946,6 @@ public: USHORT hdr_forced_writes; TEXT database_security_class[GDS_NAME_LEN]; // To save database security class for deferred update -#ifdef SERVICE_THREAD static inline BurpGlobals* getSpecific() { return (BurpGlobals*) ThreadData::getSpecific(); } @@ -951,21 +955,13 @@ public: static inline void restoreSpecific() { ThreadData::restoreSpecific(); } -#else - static inline BurpGlobals* getSpecific() { - return gdgbl; - } - static inline void putSpecific(BurpGlobals* tdgbl) { - gdgbl = tdgbl; - } - static inline void restoreSpecific() { - } -#endif char veryEnd; //starting after this members must be initialized in constructor explicitly bool flag_on_line; // indicates whether we will bring the database on-line + Firebird::UtilSvc* uSvc; + bool firstMap; // this is the first time we entered get_mapping() }; // CVC: This aux routine declared here to not force inclusion of burp.h with burp_proto.h @@ -1009,9 +1005,6 @@ inline static ULONG BURP_UP_TO_BLOCK(const ULONG size) #ifdef WIN_NT static const ULONG MODE_READ = GENERIC_READ; static const ULONG MODE_WRITE = GENERIC_WRITE; -#elif defined(VMS) -static const ULONG MODE_READ = O_RDONLY; -static const ULONG MODE_WRITE = O_WRONLY | O_CREAT | O_TRUNC; #else static const ULONG MODE_READ = O_RDONLY; static const ULONG MODE_WRITE = O_WRONLY | O_CREAT; diff --git a/src/burp/burpMain.cpp b/src/burp/burpMain.cpp new file mode 100644 index 0000000000..988282a4c7 --- /dev/null +++ b/src/burp/burpMain.cpp @@ -0,0 +1,48 @@ +/* + * PROGRAM: Firebird utilities + * MODULE: burpMain.cpp + * DESCRIPTION: Proxy for real gbak main function + * + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. + * + * Software distributed under the License is distributed AS IS, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. + * See the License for the specific language governing rights + * and limitations under the License. + * + * The Original Code was created by Alex Peshkov + * for the Firebird Open Source RDBMS project. + * + * Copyright (c) 2007 Alex Peshkov + * and all contributors signed below. + * + * All Rights Reserved. + * Contributor(s): ______________________________________. + * + * + */ + +#include "firebird.h" +#include "../burp/burp_proto.h" +#include "../common/classes/auto.h" + + +int CLIB_ROUTINE main( int argc, char* argv[]) +{ +/************************************** + * + * m a i n + * + ************************************** + * + * Functional description + * Invoke real gbak main function + * + **************************************/ + Firebird::AutoPtr uSvc(Firebird::UtilSvc::createStandalone(argc, argv)); + return gbak(uSvc); +} diff --git a/src/burp/burp_proto.h b/src/burp/burp_proto.h index 48275610fb..3b2de59547 100644 --- a/src/burp/burp_proto.h +++ b/src/burp/burp_proto.h @@ -24,12 +24,12 @@ #ifndef BURP_BURP_PROTO_H #define BURP_BURP_PROTO_H -#include "../jrd/thd.h" +#include "../jrd/ThreadData.h" #include "../common/classes/MsgPrint.h" +#include "../common/UtilSvc.h" -#ifdef SERVICE_THREAD THREAD_ENTRY_DECLARE BURP_main(THREAD_ENTRY_PARAM); -#endif +int gbak(Firebird::UtilSvc*); void BURP_abort(void); void BURP_error(USHORT, bool, const MsgFormat::SafeArg& arg = MsgFormat::SafeArg()); diff --git a/src/burp/burpswi.h b/src/burp/burpswi.h index 070a07a740..73a161ba1c 100644 --- a/src/burp/burpswi.h +++ b/src/burp/burpswi.h @@ -28,6 +28,7 @@ #define BURP_BURPSWI_H #include "../jrd/common.h" +#include "../jrd/constants.h" #include "../jrd/ibase.h" /* Local copies of global variables. They will be copied into @@ -84,9 +85,8 @@ const int IN_SW_BURP_NOD = 39; // do not run database triggers #ifdef TRUSTED_AUTH const int IN_SW_BURP_TRUSTED_USER = 40; // force trusted auth #endif -#ifdef TRUSTED_SERVICES const int IN_SW_BURP_TRUSTED_SVC = 41; // trusted user name to use on attach -#endif +const int IN_SW_BURP_TRUSTED_ROLE = 42; // use trusted role on attach /**************************************************************************/ // used 0BCDEFGILMNOPRSTUVYZ available AHJQWX @@ -156,9 +156,8 @@ static in_sw_tab_t burp_in_sw_table [] = {IN_SW_BURP_TRUSTED_USER, 0, "TRUSTED", 0, 0, 0, FALSE, 295, 0, NULL}, // msg 295: @1TRU(STED) use trusted authentication #endif -#ifdef TRUSTED_SERVICES - {IN_SW_BURP_TRUSTED_SVC, 0, "TRUSTED_SVC", 0, 0, 0, FALSE, 0, 0, NULL}, -#endif + {IN_SW_BURP_TRUSTED_SVC, 0, TRUSTED_USER_SWITCH, 0, 0, 0, FALSE, 0, 0, NULL}, + {IN_SW_BURP_TRUSTED_ROLE, 0, TRUSTED_ROLE_SWITCH, 0, 0, 0, FALSE, 0, 0, NULL}, /* {IN_SW_BURP_U, 0, "UNPROTECTED", 0, 0, 0, FALSE, 0, 0, NULL}, */ diff --git a/src/burp/canonical.cpp b/src/burp/canonical.cpp index fce4077529..a03689b95a 100644 --- a/src/burp/canonical.cpp +++ b/src/burp/canonical.cpp @@ -405,7 +405,7 @@ static bool_t burp_putlong(XDR* xdrs, const SLONG* lp) **************************************/ SLONG l = htonl(*lp); return (*xdrs->x_ops->x_putbytes) (xdrs, - reinterpret_cast(AOF32L(l)), + reinterpret_cast(&l), 4); } diff --git a/src/burp/misc.cpp b/src/burp/misc.cpp index 55c204d1f4..3c913aeada 100644 --- a/src/burp/misc.cpp +++ b/src/burp/misc.cpp @@ -31,10 +31,6 @@ #include "../burp/burp_proto.h" #include "../burp/misc_proto.h" -#ifdef SERVICE_THREAD -#include "../jrd/thd.h" -#endif - UCHAR *MISC_alloc_burp(ULONG size) { diff --git a/src/burp/mvol.cpp b/src/burp/mvol.cpp index f8c18837ef..158978f06d 100644 --- a/src/burp/mvol.cpp +++ b/src/burp/mvol.cpp @@ -45,13 +45,8 @@ #include "../jrd/gds_proto.h" #include "../jrd/gdsassert.h" #include "../jrd/thd.h" -#ifndef VMS #include #include -#else -#include -#include -#endif #if (defined WIN_NT) #include // isatty @@ -68,10 +63,6 @@ using MsgFormat::SafeArg; const int open_mask = 0666; -#ifdef VMS -const char* TERM_INPUT = "sys$input"; -const char* TERM_OUTPUT = "sys$error"; -#else #ifdef WIN_NT const char* TERM_INPUT = "CONIN$"; const char* TERM_OUTPUT = "CONOUT$"; @@ -79,7 +70,6 @@ const char* TERM_OUTPUT = "CONOUT$"; const char* TERM_INPUT = "/dev/tty"; const char* TERM_OUTPUT = "/dev/tty"; #endif -#endif const int MAX_HEADER_SIZE = 512; @@ -263,7 +253,7 @@ void MVOL_init_write(const char* database_name, // unused? { if (tdgbl->action->act_action == ACT_backup_split) { - BURP_error(269, true, tdgbl->action->act_file->fil_name); + BURP_error(269, true, tdgbl->action->act_file->fil_name.c_str()); // msg 269 can't write a header record to file %s } tdgbl->file_desc = next_volume(tdgbl->file_desc, MODE_WRITE, false); @@ -297,28 +287,25 @@ int MVOL_read(int* cnt, UCHAR** ptr) break; } + if (!tdgbl->mvol_io_cnt || errno == EIO) { - if (!tdgbl->mvol_io_cnt || errno == EIO) + tdgbl->file_desc = next_volume(tdgbl->file_desc, MODE_READ, false); + if (tdgbl->mvol_io_cnt > 0) { - tdgbl->file_desc = next_volume(tdgbl->file_desc, MODE_READ, false); - if (tdgbl->mvol_io_cnt > 0) - { - break; - } + break; } - - else if (!SYSCALL_INTERRUPTED(errno)) + } + else if (!SYSCALL_INTERRUPTED(errno)) + { + if (cnt) { - if (cnt) - { - BURP_error_redirect(0, 220); + BURP_error_redirect(0, 220); // msg 220 Unexpected I/O error while reading from backup file - } - else - { - BURP_error_redirect(0, 50); + } + else + { + BURP_error_redirect(0, 50); // msg 50 unexpected end of file on backup file - } } } } @@ -352,23 +339,21 @@ int MVOL_read(int* cnt, UCHAR** ptr) tdgbl->mvol_io_ptr = tdgbl->mvol_io_buffer; if (tdgbl->mvol_io_cnt > 0) break; - else + + if (!tdgbl->mvol_io_cnt) { - if (!tdgbl->mvol_io_cnt) - { - tdgbl->file_desc = next_volume(tdgbl->file_desc, MODE_READ, false); - if (tdgbl->mvol_io_cnt > 0) - break; - } - else if (GetLastError() != ERROR_HANDLE_EOF) - { - if (cnt) - BURP_error_redirect(NULL, 220); + tdgbl->file_desc = next_volume(tdgbl->file_desc, MODE_READ, false); + if (tdgbl->mvol_io_cnt > 0) + break; + } + else if (GetLastError() != ERROR_HANDLE_EOF) + { + if (cnt) + BURP_error_redirect(NULL, 220); // msg 220 Unexpected I/O error while reading from backup file - else - BURP_error_redirect(NULL, 50); + else + BURP_error_redirect(NULL, 50); // msg 50 unexpected end of file on backup file - } } } @@ -388,7 +373,7 @@ int MVOL_read(int* cnt, UCHAR** ptr) // Read a chunk of data from the IO buffer. // Return a pointer to the first position NOT read into. // -UCHAR* MVOL_read_block(BurpGlobals* tdgbl, UCHAR * ptr, ULONG count) +UCHAR* MVOL_read_block(BurpGlobals* tdgbl, UCHAR* ptr, ULONG count) { // To handle tape drives & Multi-volume boundaries, use the normal // read function, instead of doing a more optimal bulk read. @@ -405,7 +390,7 @@ UCHAR* MVOL_read_block(BurpGlobals* tdgbl, UCHAR * ptr, ULONG count) count--; } - ULONG n = MIN(count, (ULONG) tdgbl->io_cnt); + const ULONG n = MIN(count, (ULONG) tdgbl->io_cnt); // Copy data from the IO buffer @@ -445,7 +430,7 @@ void MVOL_skip_block( BurpGlobals* tdgbl, ULONG count) count--; } - ULONG n = MIN(count, (ULONG) tdgbl->io_cnt); + const ULONG n = MIN(count, (ULONG) tdgbl->io_cnt); // Skip ahead in current buffer @@ -462,7 +447,7 @@ void MVOL_skip_block( BurpGlobals* tdgbl, ULONG count) // detect if it's a tape, rewind if so // and set the buffer size // -DESC MVOL_open(const char * name, ULONG mode, ULONG create) +DESC MVOL_open(const char* name, ULONG mode, ULONG create) { HANDLE handle; TAPE_GET_MEDIA_PARAMETERS param; @@ -526,18 +511,17 @@ DESC MVOL_open(const char * name, ULONG mode, ULONG create) // // Write a buffer's worth of data. // -UCHAR MVOL_write(UCHAR c, int *io_cnt, UCHAR ** io_ptr) +UCHAR MVOL_write(const UCHAR c, int* io_cnt, UCHAR** io_ptr) { - UCHAR *ptr; - SLONG left, cnt; + const UCHAR* ptr; + SLONG cnt = 0; BurpGlobals* tdgbl = BurpGlobals::getSpecific(); - ULONG size_to_write = BURP_UP_TO_BLOCK(*io_ptr - tdgbl->mvol_io_buffer); + const ULONG size_to_write = BURP_UP_TO_BLOCK(*io_ptr - tdgbl->mvol_io_buffer); + ULONG left = size_to_write; - for (ptr = tdgbl->mvol_io_buffer, left = size_to_write; - left > 0; - ptr += cnt, left -= cnt) + for (ptr = tdgbl->mvol_io_buffer; left > 0; ptr += cnt, left -= cnt) { if (tdgbl->action->act_action == ACT_backup_split) { @@ -579,7 +563,7 @@ UCHAR MVOL_write(UCHAR c, int *io_cnt, UCHAR ** io_ptr) DWORD err = 0; // Assumes DWORD <==> ULONG if (!WriteFile(tdgbl->file_desc, ptr, nBytesToWrite, - reinterpret_cast (&cnt), NULL)) + reinterpret_cast(&cnt), NULL)) { err = GetLastError(); } @@ -624,9 +608,9 @@ UCHAR MVOL_write(UCHAR c, int *io_cnt, UCHAR ** io_ptr) tdgbl->action->act_file->fil_fd = INVALID_HANDLE_VALUE; BURP_print(272, SafeArg() << - tdgbl->action->act_file->fil_name << + tdgbl->action->act_file->fil_name.c_str() << tdgbl->action->act_file->fil_length << - tdgbl->action->act_file->fil_next->fil_name); + tdgbl->action->act_file->fil_next->fil_name.c_str()); // msg 272 Warning -- free disk space exhausted for file %s, // the rest of the bytes (%d) will be written to file %s tdgbl->action->act_file->fil_next->fil_length += @@ -644,7 +628,7 @@ UCHAR MVOL_write(UCHAR c, int *io_cnt, UCHAR ** io_ptr) continue; } - if (tdgbl->gbl_sw_service_gbak) + if (tdgbl->uSvc->isService()) { BURP_error(270, true); // msg 270 free disk space exhausted @@ -711,9 +695,9 @@ UCHAR MVOL_write(UCHAR c, int *io_cnt, UCHAR ** io_ptr) tdgbl->mvol_io_buffer_size = tdgbl->mvol_actual_buffer_size; - ptr = tdgbl->mvol_io_buffer + left; - *ptr++ = c; - *io_ptr = ptr; + UCHAR* newptr = tdgbl->mvol_io_buffer + left; + *newptr++ = c; + *io_ptr = newptr; *io_cnt = tdgbl->mvol_io_buffer_size - 1 - left; return c; @@ -725,7 +709,7 @@ UCHAR MVOL_write(UCHAR c, int *io_cnt, UCHAR ** io_ptr) // Write a chunk of data to the IO buffer. // Return a pointer to the first position NOT written from. // -const UCHAR *MVOL_write_block(BurpGlobals* tdgbl, const UCHAR * ptr, ULONG count) +const UCHAR* MVOL_write_block(BurpGlobals* tdgbl, const UCHAR* ptr, ULONG count) { // To handle tape drives & Multi-volume boundaries, use the normal // write function, instead of doing a more optimal bulk write. @@ -741,7 +725,7 @@ const UCHAR *MVOL_write_block(BurpGlobals* tdgbl, const UCHAR * ptr, ULONG count count--; } - ULONG n = MIN(count, (ULONG) tdgbl->io_cnt); + const ULONG n = MIN(count, (ULONG) tdgbl->io_cnt); // Copy data to the IO buffer @@ -964,15 +948,15 @@ static void prompt_for_name(SCHAR* name, int length) // Unless we are operating as a service, stdin can't necessarily be trusted. // Get a location to read from. + fb_assert(!tdgbl->uSvc->isService()); - if (tdgbl->gbl_sw_service_gbak || - isatty(fileno(stdout)) || + if (isatty(fileno(stdout)) || !(term_out = fopen(TERM_OUTPUT, "w"))) { term_out = stdout; } - if (tdgbl->gbl_sw_service_gbak || - isatty(fileno(stdin)) || + + if (isatty(fileno(stdin)) || !(term_in = fopen(TERM_INPUT, "r"))) { term_in = stdin; @@ -1003,10 +987,6 @@ static void prompt_for_name(SCHAR* name, int length) BURP_msg_get(228, msg); // " Name: " fprintf(term_out, msg); - if (tdgbl->gbl_sw_service_gbak) - { - putc('\001', term_out); - } fflush(term_out); if (fgets(name, length, term_in) == NULL) { @@ -1361,7 +1341,7 @@ bool MVOL_split_hdr_write(void) sprintf(buffer, "%s%.24s , file No. %4d of %4d, %-27.27s", HDR_SPLIT_TAG, ctime(&seconds), tdgbl->action->act_file->fil_seq, - tdgbl->action->act_total, tdgbl->action->act_file->fil_name); + tdgbl->action->act_total, tdgbl->action->act_file->fil_name.c_str()); #ifdef WIN_NT DWORD bytes_written = 0; @@ -1419,4 +1399,3 @@ bool MVOL_split_hdr_read(void) return false; } - diff --git a/src/burp/mvol_proto.h b/src/burp/mvol_proto.h index 1878eb4e13..26cdd57a41 100644 --- a/src/burp/mvol_proto.h +++ b/src/burp/mvol_proto.h @@ -37,7 +37,7 @@ bool MVOL_split_hdr_read(); int MVOL_read(int*, UCHAR**); UCHAR* MVOL_read_block(BurpGlobals*, UCHAR*, ULONG); void MVOL_skip_block(BurpGlobals*, ULONG); -UCHAR MVOL_write(UCHAR, int*, UCHAR**); +UCHAR MVOL_write(const UCHAR, int*, UCHAR**); const UCHAR* MVOL_write_block(BurpGlobals*, const UCHAR*, ULONG); #if defined WIN_NT diff --git a/src/burp/restore.epp b/src/burp/restore.epp index 8e9048f0c6..0fd54a88aa 100644 --- a/src/burp/restore.epp +++ b/src/burp/restore.epp @@ -77,10 +77,11 @@ const int DB_VERSION_DDL4 = 40; // ods4 db const int DB_VERSION_DDL5 = 50; // ods5 db const int DB_VERSION_DDL8 = 80; // ods8 db const int DB_VERSION_CURRENT = DB_VERSION_DDL8; // IB4.0 is ods8 -const int DB_VERSION_DDL9 = 90; // ods9 db, IB5 -const int DB_VERSION_DDL10 = 100; // ods10 db, IB6, FB1, FB1.5 -const int DB_VERSION_DDL11 = 110; // ods11 db, FB2 -const int DB_VERSION_DDL11_1 = 111; // ods11.1 db, FB2.1 +const int DB_VERSION_DDL9 = 90; // ods9 db, IB5 +const int DB_VERSION_DDL10 = 100; // ods10 db, IB6, FB1, FB1.5 +const int DB_VERSION_DDL11 = 110; // ods11 db, FB2 +const int DB_VERSION_DDL11_1 = 111; // ods11.1 db, FB2.1 +const int DB_VERSION_DDL11_2 = 112; // ods11.2 db, FB2.5 const int DEFERRED_ACTIVE = 3; /* RDB$INDEX_INACTIVE setting for Foreign Keys * This setting is used temporarily while @@ -141,6 +142,7 @@ bool get_rel_constraint(BurpGlobals* tdgbl); bool get_relation(BurpGlobals* tdgbl); bool get_relation_data(BurpGlobals* tdgbl); bool get_sql_roles(BurpGlobals* tdgbl); +bool get_mapping(BurpGlobals* tdgbl); bool get_security_class(BurpGlobals* tdgbl); void get_source_blob(BurpGlobals* tdgbl, ISC_QUAD&, bool); USHORT get_text (BurpGlobals* tdgbl, TEXT*, ULONG); @@ -603,7 +605,7 @@ int RESTORE_restore (const TEXT* file_name, if (tdgbl->gbl_sw_password) { - dpb.insertString(tdgbl->gbl_sw_service_gbak ? + dpb.insertString(tdgbl->uSvc->isService() ? isc_dpb_password_enc : isc_dpb_password, tdgbl->gbl_sw_password, strlen(tdgbl->gbl_sw_password)); @@ -648,7 +650,7 @@ int RESTORE_restore (const TEXT* file_name, } if (tdgbl->gbl_sw_password) { - dpb.insertString(tdgbl->gbl_sw_service_gbak ? + dpb.insertString(tdgbl->uSvc->isService() ? isc_dpb_password_enc : isc_dpb_password, tdgbl->gbl_sw_password, strlen(tdgbl->gbl_sw_password)); @@ -698,19 +700,19 @@ void add_files(BurpGlobals* tdgbl, for (burp_fil* file = tdgbl->gbl_sw_files; file; file = file->fil_next) { - if (strcmp (file->fil_name, file_name)) + if (file->fil_name != file_name) { count++; STORE (REQUEST_HANDLE req_handle1) X IN RDB$FILES - strcpy (X.RDB$FILE_NAME, file->fil_name); + strcpy (X.RDB$FILE_NAME, file->fil_name.c_str()); X.RDB$FILE_START = start; END_STORE; ON_ERROR general_on_error (); END_ERROR; MISC_release_request_silent(req_handle1); - BURP_verbose (57, SafeArg() << file->fil_name << start); + BURP_verbose (57, SafeArg() << file->fil_name.c_str() << start); // msg 57 adding file %s, starting at page %ld } else if (((SLONG) file->fil_length) >= start - 1) @@ -846,9 +848,10 @@ void check_db_version(BurpGlobals* tdgbl) const rel_field_t rel_fields[] = { - {"RDB$FIELDS", "RDB$FIELD_PRECISION", DB_VERSION_DDL10}, // FB1, FB1.5 - {"RDB$ROLES", "RDB$DESCRIPTION", DB_VERSION_DDL11}, // FB2 - {"RDB$RELATIONS", "RDB$RELATION_TYPE", DB_VERSION_DDL11_1}, // FB2.1 + {"RDB$FIELDS", "RDB$FIELD_PRECISION", DB_VERSION_DDL10}, // FB1, FB1.5 + {"RDB$ROLES", "RDB$DESCRIPTION", DB_VERSION_DDL11}, // FB2 + {"RDB$RELATIONS", "RDB$RELATION_TYPE", DB_VERSION_DDL11_1}, // FB2.1 + {"RDB$PROCEDURE_PARAMETERS", "RDB$FIELD_NAME", DB_VERSION_DDL11_2}, // FB2.5 {0, 0, 0} }; @@ -1002,7 +1005,7 @@ void create_database(BurpGlobals* tdgbl, } if (tdgbl->gbl_sw_password) { - dpb.insertString(tdgbl->gbl_sw_service_gbak ? + dpb.insertString(tdgbl->uSvc->isService() ? isc_dpb_password_enc : isc_dpb_password, tdgbl->gbl_sw_password, strlen(tdgbl->gbl_sw_password)); @@ -5012,6 +5015,16 @@ bool get_procedure_prm (BurpGlobals* tdgbl, GDS_NAME procptr) bad_attribute (scan_next_attr, attribute, 291); break; + // DB_VERSION_DDL11_2 + case att_procedureprm_field_name: + GET_TEXT(X.RDB$FIELD_NAME); + break; + + // DB_VERSION_DDL11_2 + case att_procedureprm_relation_name: + GET_TEXT(X.RDB$RELATION_NAME); + break; + default: bad_attribute (scan_next_attr, attribute, 291); // msg 291 procedure parameter @@ -5755,6 +5768,84 @@ bool get_sql_roles(BurpGlobals* tdgbl) return true; } +bool get_mapping(BurpGlobals* tdgbl) +{ +/************************************** + * + * g e t _ m a p p i n g + * + ************************************** + * + * Functional description + * Restore mapping to users and roles + * Restricted version - only single + * mapping is accepted + * + **************************************/ + ATT_TYPE attribute; + scan_attr_t scan_next_attr; + TEXT temp[GDS_NAME_LEN]; + SSHORT l; + Firebird::string role, os; + + if (tdgbl->RESTORE_ods >= DB_VERSION_DDL11_1) + { + skip_init(&scan_next_attr); + while (skip_scan(&scan_next_attr), get_attribute(&attribute, tdgbl) != att_end) + { + switch (attribute) + { + case att_map_role: + l = GET_TEXT(temp); + role.assign(temp, l); + break; + + case att_map_os: + l = GET_TEXT(temp); + os.assign(temp, l); + break; + + default: + // msg 299 name mapping + bad_attribute (scan_next_attr, attribute, 299); + break; + } + } + + if (tdgbl->RESTORE_ods < DB_VERSION_DDL11_2) + { + return true; // silently skip attributes on old server + } + + if (os != DOMAIN_ADMINS || role != ADMIN_ROLE) + { + BURP_error(300, false); + return true; + } + + if (tdgbl->firstMap) + { + tdgbl->firstMap = false; + BURP_verbose(301); + //msg 301, restoring names mapping + } + BURP_verbose(298, ADMIN_ROLE); + //msg 298, restoring map @1 + Firebird::string sql; + sql.printf("%s ('%s',%d) %s", + "UPDATE OR INSERT INTO RDB$ROLES(RDB$ROLE_NAME, RDB$SYSTEM_FLAG) VALUES", + ADMIN_ROLE, ROLE_FLAG_MAY_TRUST | ROLE_FLAG_DBO, + "MATCHING (RDB$ROLE_NAME)"); + isc_dsql_execute_immediate(tdgbl->status, &tdgbl->db_handle, &tdgbl->tr_handle, + sql.length(), sql.c_str(), 1, NULL); + if (tdgbl->status[1]) + { + general_on_error (); + } + } + return true; +} + bool is_ascii_name (const TEXT *name, const SSHORT len) { /************************************** @@ -7369,6 +7460,12 @@ bool restore(BurpGlobals* tdgbl, flag = true; break; + case rec_mapping: + if (!get_mapping(tdgbl)) + return false; + flag = true; + break; + default: BURP_error(43, true, SafeArg() << record); // msg 43 don't recognize record type %ld diff --git a/src/common/UtilSvc.cpp b/src/common/UtilSvc.cpp new file mode 100644 index 0000000000..ddbbf13de7 --- /dev/null +++ b/src/common/UtilSvc.cpp @@ -0,0 +1,109 @@ +/* + * PROGRAM: Firebird utilities interface + * MODULE: UtilSvc.cpp + * DESCRIPTION: Interface making it possible to use same code + * as both utility or service + * + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. + * + * Software distributed under the License is distributed AS IS, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. + * See the License for the specific language governing rights + * and limitations under the License. + * + * The Original Code was created by Alex Peshkov + * for the Firebird Open Source RDBMS project. + * + * Copyright (c) 2007 Alex Peshkov + * and all contributors signed below. + * + * All Rights Reserved. + * Contributor(s): ______________________________________. + * + * + */ + +#include "firebird.h" +#include "../common/UtilSvc.h" +#include "../common/classes/alloc.h" +#include "iberror.h" + +#include +#include + + +namespace Firebird { + +class StandaloneUtilityInterface : public UtilSvc +{ +public: + StandaloneUtilityInterface(Firebird::MemoryPool& p, int ac, char** av) + : UtilSvc(p) + { + while (ac--) + { + argv.push(*av++); + } + } + + virtual void printf(const SCHAR* format, ...) + { + va_list arglist; + va_start(arglist, format); + int rc = ::vprintf(format, arglist); + va_end(arglist); + + if (rc < 0) + { + Firebird::system_call_failed::raise( + "StandaloneUtilityInterface::printf()/vprintf()"); + } + } + + virtual void hidePasswd(ArgvType& argv, int pos) + { + const size_t l = strlen(argv[pos]); + char* data = FB_NEW(getPool()) char[l + 1]; + memcpy(data, argv[pos], l); + data[l] = 0; + + // here const-correctness is violated to make the rest 99.9% + // places of code much more clear + char* hide = const_cast(argv[pos]); + argv[pos] = data; + memset(hide, '*', l); + } + + virtual bool isService() + { + return false; + } + + virtual void checkService() + { + Firebird::status_exception::raise(isc_utl_trusted_switch, 0); + } + + // do nothing for non-service + virtual void finish() { } + virtual void started() { } + virtual void putLine(char, const char*) { } + virtual void putSLong(char, SLONG) { } + virtual void putChar(char, char) { } + virtual void stuffStatus(const ISC_STATUS*) { } + virtual void stuffStatus(const USHORT, const USHORT, const MsgFormat::SafeArg&) { } + virtual ISC_STATUS* getStatus() { return 0; } +}; + + +UtilSvc* UtilSvc::createStandalone(int ac, char** av) +{ + return FB_NEW(*getDefaultMemoryPool()) + StandaloneUtilityInterface(*getDefaultMemoryPool(), ac, av); +} + +} // namespace Firebird diff --git a/src/common/UtilSvc.h b/src/common/UtilSvc.h new file mode 100644 index 0000000000..fa96996350 --- /dev/null +++ b/src/common/UtilSvc.h @@ -0,0 +1,81 @@ +/* + * PROGRAM: Firebird utilities interface + * MODULE: UtilSvc.h + * DESCRIPTION: Interface making it possible to use same code + * as both utility or service + * + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. + * + * Software distributed under the License is distributed AS IS, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. + * See the License for the specific language governing rights + * and limitations under the License. + * + * The Original Code was created by Alex Peshkov + * for the Firebird Open Source RDBMS project. + * + * Copyright (c) 2007 Alex Peshkov + * and all contributors signed below. + * + * All Rights Reserved. + * Contributor(s): ______________________________________. + * + * + */ + +#ifndef FB_UTILFACE +#define FB_UTILFACE + +#include "../common/classes/alloc.h" +#include "../common/classes/array.h" + +namespace MsgFormat { + class SafeArg; +} + +namespace Firebird { + +class UtilSvc : public PermanentStorage +{ +public: + typedef Firebird::HalfStaticArray ArgvType; + +public: + explicit UtilSvc(Firebird::MemoryPool& p) : PermanentStorage(p), argv(getPool()) { } + + void output(const char* text) + { + printf("%s", text); + } + + virtual void printf(const SCHAR* format, ...) = 0; + virtual bool isService() = 0; + virtual void started() = 0; + virtual void finish() = 0; + virtual void putLine(char, const char*) = 0; + virtual void putSLong(char, SLONG) = 0; + virtual void putChar(char, char) = 0; + virtual void stuffStatus(const ISC_STATUS*) = 0; + virtual void stuffStatus(const USHORT, const USHORT, const MsgFormat::SafeArg&) = 0; + virtual void hidePasswd(ArgvType&, int) = 0; + virtual ISC_STATUS* getStatus() = 0; + virtual void checkService() = 0; + + + virtual ~UtilSvc() { } + + static UtilSvc* createStandalone(int ac, char** argv); + +public: + ArgvType argv; +}; + + +} // namespace Firebird + + +#endif // FB_UTILFACE diff --git a/src/common/utils.cpp b/src/common/utils.cpp index d01ab74007..8ec7abab36 100644 --- a/src/common/utils.cpp +++ b/src/common/utils.cpp @@ -25,6 +25,7 @@ // ===================================== // Utility functions +#include "firebird.h" #include "../jrd/common.h" #ifdef HAVE_SYS_TYPES_H @@ -285,6 +286,8 @@ int snprintf(char* buffer, size_t count, const char* format...) // Copy password to newly allocated place and replace existing one in argv with spaces. // Allocated space is released upon exit from utility. // This is planned leak of a few bytes of memory in utilities. +// This function is deprecated. Use UtilSvc::hidePasswd(ArgvType&, int) whenever possible. +// However, there are several usages through fb_utils::get_passwd(char* arg); char* cleanup_passwd(char* arg) { if (! arg) @@ -292,7 +295,7 @@ char* cleanup_passwd(char* arg) return arg; } - int lpass = strlen(arg); + const int lpass = strlen(arg); char* savePass = (char*) gds__alloc(lpass + 1); if (! savePass) { diff --git a/src/common/utils_proto.h b/src/common/utils_proto.h index 292622f105..5ae6bdf06f 100644 --- a/src/common/utils_proto.h +++ b/src/common/utils_proto.h @@ -48,21 +48,13 @@ namespace fb_utils bool readenv(const char* env_name, Firebird::PathName& env_value); int snprintf(char* buffer, size_t count, const char* format...); char* cleanup_passwd(char* arg); -#ifdef SERVICE_THREAD - inline const char* get_passwd(const char* arg) - { - return arg; - } - typedef const char* arg_string; -#else inline char* get_passwd(char* arg) { return cleanup_passwd(arg); } typedef char* arg_string; -#endif -// Warning: Only wrappers: + // Warning: Only wrappers: // ******************** // s t r i c m p