2001-05-23 15:26:42 +02:00
|
|
|
/*
|
|
|
|
* PROGRAM: JRD Backup and Restore Program
|
2003-09-25 13:49:12 +02:00
|
|
|
* MODULE: burp.cpp
|
2001-05-23 15:26:42 +02:00
|
|
|
* DESCRIPTION: Command line interpreter for backup/restore
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Interbase 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.Inprise.com/IPL.html
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an
|
|
|
|
* "AS IS" basis, 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 Inprise Corporation
|
|
|
|
* and its predecessors. Portions created by Inprise Corporation are
|
|
|
|
* Copyright (C) Inprise Corporation.
|
|
|
|
*
|
|
|
|
* All Rights Reserved.
|
|
|
|
* Contributor(s): ______________________________________.
|
2001-07-10 19:35:13 +02:00
|
|
|
* 2001.07.06 Sean Leyne - Code Cleanup, removed "#ifdef READONLY_DATABASE"
|
|
|
|
* conditionals, as the engine now fully supports
|
|
|
|
* readonly databases.
|
2002-02-16 03:21:35 +01:00
|
|
|
*
|
|
|
|
* 2002.02.15 Sean Leyne - Code Cleanup, removed obsolete "EPSON" defines
|
|
|
|
*
|
2002-10-30 07:40:58 +01:00
|
|
|
* 2002.10.29 Sean Leyne - Removed obsolete "Netware" port
|
|
|
|
*
|
2003-09-12 11:04:38 +02:00
|
|
|
* 2002.10.30 Sean Leyne - Removed support for obsolete "PC_PLATFORM" define
|
2001-05-23 15:26:42 +02:00
|
|
|
*/
|
|
|
|
|
2001-07-30 01:43:24 +02:00
|
|
|
#include "firebird.h"
|
2004-04-29 00:00:03 +02:00
|
|
|
#include <stdio.h>
|
2001-05-23 15:26:42 +02:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include "../jrd/common.h"
|
|
|
|
#include "../jrd/ibase.h"
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include "../jrd/ibsetjmp.h"
|
|
|
|
#include "../jrd/msg_encode.h"
|
|
|
|
#include "../jrd/ods.h" // to get MAX_PAGE_SIZE
|
2004-05-03 23:43:56 +02:00
|
|
|
#include "../jrd/svc.h"
|
2008-01-16 07:11:50 +01:00
|
|
|
#include "../jrd/constants.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../burp/burp.h"
|
|
|
|
#include "../burp/burpswi.h"
|
2003-05-02 18:04:56 +02:00
|
|
|
#include "../burp/std_desc.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../jrd/license.h"
|
|
|
|
|
2006-02-03 14:13:27 +01:00
|
|
|
#include "../common/classes/timestamp.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../burp/burp_proto.h"
|
|
|
|
#include "../burp/backu_proto.h"
|
|
|
|
#include "../burp/mvol_proto.h"
|
|
|
|
#include "../burp/resto_proto.h"
|
|
|
|
#include "../jrd/gds_proto.h"
|
|
|
|
#include "../jrd/gdsassert.h"
|
2004-12-09 20:19:47 +01:00
|
|
|
#include "../common/classes/ClumpletWriter.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2001-07-12 07:46:06 +02:00
|
|
|
#ifdef HAVE_CTYPE_H
|
|
|
|
#include <ctype.h>
|
|
|
|
#endif
|
2006-01-14 05:48:59 +01:00
|
|
|
#include "../common/utils_proto.h"
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
#ifdef UNIX
|
|
|
|
#include <unistd.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
2003-12-14 05:44:58 +01:00
|
|
|
#ifdef WIN_NT
|
|
|
|
#include <io.h>
|
|
|
|
#endif
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
#ifndef O_CREAT
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/file.h>
|
|
|
|
#endif
|
|
|
|
|
2007-03-28 06:20:36 +02:00
|
|
|
using MsgFormat::SafeArg;
|
|
|
|
|
2003-09-25 13:49:12 +02:00
|
|
|
const char* fopen_write_type = "w";
|
|
|
|
const char* fopen_read_type = "r";
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-05-23 15:27:47 +02:00
|
|
|
const int open_mask = 0666;
|
|
|
|
const char switch_char = '-';
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
|
2003-09-25 13:49:12 +02:00
|
|
|
const char* const output_suppress = "SUPPRESS";
|
|
|
|
const int burp_msg_fac = 12;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-09-12 11:04:38 +02:00
|
|
|
enum gbak_action
|
|
|
|
{
|
|
|
|
QUIT = 0,
|
|
|
|
BACKUP = 1 ,
|
|
|
|
RESTORE = 2,
|
|
|
|
FDESC = 3
|
|
|
|
};
|
|
|
|
|
2004-03-01 04:35:23 +01:00
|
|
|
static void close_out_transaction(gbak_action, isc_tr_handle*);
|
2003-03-01 20:06:54 +01:00
|
|
|
//static void enable_signals(void);
|
|
|
|
//static void excp_handler(void);
|
2004-01-13 10:52:19 +01:00
|
|
|
static SLONG get_number(const SCHAR*);
|
|
|
|
static ULONG get_size(const SCHAR*, burp_fil*);
|
2004-12-09 20:19:47 +01:00
|
|
|
static gbak_action open_files(const TEXT *, const TEXT**, bool, USHORT,
|
|
|
|
const Firebird::ClumpletWriter&);
|
2008-05-23 15:19:20 +02:00
|
|
|
static int api_gbak(Firebird::UtilSvc*, in_sw_tab_t* const in_sw_tab);
|
2003-11-03 02:12:14 +01:00
|
|
|
static void burp_output(const SCHAR*, ...) ATTRIBUTE_FORMAT(1,2);
|
2008-05-23 15:05:35 +02:00
|
|
|
static void burp_usage(const in_sw_tab_t* in_sw_tab);
|
2008-05-23 15:19:20 +02:00
|
|
|
static in_sw_tab_t* findSwitch(in_sw_tab_t* const in_sw_tab, Firebird::string, bool);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-09-12 11:04:38 +02:00
|
|
|
// fil.fil_length is ULONG
|
|
|
|
const ULONG KBYTE = 1024;
|
|
|
|
const ULONG MBYTE = KBYTE * KBYTE;
|
|
|
|
const ULONG GBYTE = MBYTE * KBYTE;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
|
2004-06-08 15:41:08 +02:00
|
|
|
THREAD_ENTRY_DECLARE BURP_main(THREAD_ENTRY_PARAM arg)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* m a i n _ g b a k
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
2003-09-15 15:13:45 +02:00
|
|
|
* Entrypoint for GBAK via services manager.
|
2001-05-23 15:26:42 +02:00
|
|
|
*
|
|
|
|
**************************************/
|
2008-01-16 07:11:50 +01:00
|
|
|
Firebird::UtilSvc* uSvc = (Firebird::UtilSvc*) arg;
|
2008-04-07 12:52:34 +02:00
|
|
|
int exit_code = FINI_OK;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-04-02 16:26:17 +02:00
|
|
|
try {
|
|
|
|
exit_code = gbak(uSvc);
|
|
|
|
}
|
|
|
|
catch (const Firebird::Exception& e)
|
|
|
|
{
|
|
|
|
e.stuff_exception(uSvc->getStatus());
|
|
|
|
exit_code = FB_FAILURE;
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-04-02 16:26:17 +02:00
|
|
|
uSvc->finish();
|
2008-01-16 07:11:50 +01:00
|
|
|
return (THREAD_ENTRY_RETURN)(IPTR) exit_code;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-05-23 15:19:20 +02:00
|
|
|
static int api_gbak(Firebird::UtilSvc* uSvc, in_sw_tab_t* const in_sw_tab)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2008-01-16 07:11:50 +01:00
|
|
|
/**********************************************
|
2001-05-23 15:26:42 +02:00
|
|
|
*
|
2008-01-16 07:11:50 +01:00
|
|
|
* a p i _ g b a k
|
2001-05-23 15:26:42 +02:00
|
|
|
*
|
2008-01-16 07:11:50 +01:00
|
|
|
**********************************************
|
2001-05-23 15:26:42 +02:00
|
|
|
*
|
|
|
|
* Functional description
|
2008-01-16 07:11:50 +01:00
|
|
|
* Run gbak using services APIs
|
2001-05-23 15:26:42 +02:00
|
|
|
*
|
2008-01-16 07:11:50 +01:00
|
|
|
**********************************************/
|
|
|
|
Firebird::string usr, pswd, service;
|
|
|
|
bool flag_restore = false;
|
|
|
|
bool flag_verbose = false;
|
|
|
|
#ifdef TRUSTED_AUTH
|
|
|
|
bool flag_trusted = false;
|
|
|
|
#endif
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-16 07:11:50 +01:00
|
|
|
int itr;
|
2005-11-17 12:32:38 +01:00
|
|
|
|
2008-01-16 07:11:50 +01:00
|
|
|
Firebird::UtilSvc::ArgvType& argv = uSvc->argv;
|
2008-02-02 17:57:15 +01:00
|
|
|
const int argc = uSvc->argv.getCount();
|
2005-11-17 12:32:38 +01:00
|
|
|
|
2008-01-16 07:11:50 +01:00
|
|
|
for (itr = 1; itr < argc; ++itr)
|
|
|
|
{
|
2008-05-23 15:05:35 +02:00
|
|
|
const in_sw_tab_t* inSw = findSwitch(in_sw_tab, argv[itr], false);
|
2008-01-16 07:11:50 +01:00
|
|
|
if (! inSw)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2008-01-16 07:11:50 +01:00
|
|
|
continue;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2008-01-16 07:11:50 +01:00
|
|
|
|
|
|
|
switch (inSw->in_sw)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2008-12-01 10:21:31 +01:00
|
|
|
case IN_SW_BURP_C: // create database
|
|
|
|
case IN_SW_BURP_R: // replace database
|
|
|
|
case IN_SW_BURP_RECREATE: // recreate database
|
2003-09-10 19:52:12 +02:00
|
|
|
flag_restore = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
2008-12-01 10:21:31 +01:00
|
|
|
case IN_SW_BURP_USER: // default user name
|
|
|
|
case IN_SW_BURP_PASS: // default password
|
|
|
|
case IN_SW_BURP_SE: // service name
|
2008-01-16 07:11:50 +01:00
|
|
|
if (itr >= argc - 1)
|
|
|
|
{
|
|
|
|
// user name parameter missing
|
2008-12-01 10:21:31 +01:00
|
|
|
BURP_error(inSw->in_sw == IN_SW_BURP_USER ? 188 :
|
2008-01-16 07:11:50 +01:00
|
|
|
// password parameter missing
|
2008-12-01 10:21:31 +01:00
|
|
|
inSw->in_sw == IN_SW_BURP_PASS ? 189 :
|
2008-01-16 07:11:50 +01:00
|
|
|
// service name parameter missing
|
|
|
|
273, true);
|
2003-12-22 11:00:59 +01:00
|
|
|
}
|
2008-12-01 10:21:31 +01:00
|
|
|
else
|
2008-01-16 07:11:50 +01:00
|
|
|
{
|
|
|
|
argv[itr++] = 0;
|
2008-12-02 08:09:49 +01:00
|
|
|
switch (inSw->in_sw)
|
2008-01-16 07:11:50 +01:00
|
|
|
{
|
2008-12-01 10:21:31 +01:00
|
|
|
case IN_SW_BURP_USER: // default user name
|
2008-01-16 07:11:50 +01:00
|
|
|
usr = argv[itr];
|
|
|
|
break;
|
2008-12-01 10:21:31 +01:00
|
|
|
case IN_SW_BURP_PASS: // default password
|
2008-01-16 07:11:50 +01:00
|
|
|
pswd = argv[itr];
|
|
|
|
uSvc->hidePasswd(argv, itr);
|
|
|
|
break;
|
2008-12-01 10:21:31 +01:00
|
|
|
case IN_SW_BURP_SE: // service name
|
2008-01-16 07:11:50 +01:00
|
|
|
service = argv[itr];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
argv[itr] = 0;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
break;
|
2008-12-01 10:21:31 +01:00
|
|
|
case IN_SW_BURP_V: // verify actions
|
2003-09-10 19:52:12 +02:00
|
|
|
flag_verbose = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
2007-04-07 10:47:58 +02:00
|
|
|
#ifdef TRUSTED_AUTH
|
|
|
|
case IN_SW_BURP_TRUSTED_USER: // use trusted auth
|
|
|
|
flag_trusted = true;
|
2008-01-16 07:11:50 +01:00
|
|
|
argv[itr] = 0;
|
2007-04-07 10:47:58 +02:00
|
|
|
break;
|
|
|
|
#endif
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-01-16 07:11:50 +01:00
|
|
|
if (usr.isEmpty())
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2008-01-16 07:11:50 +01:00
|
|
|
#ifdef TRUSTED_AUTH
|
|
|
|
if (!flag_trusted)
|
|
|
|
#endif
|
2007-04-07 10:47:58 +02:00
|
|
|
{
|
2008-05-19 15:58:37 +02:00
|
|
|
fb_utils::readenv(ISC_USER, usr);
|
2007-04-07 10:47:58 +02:00
|
|
|
}
|
|
|
|
}
|
2003-11-03 02:12:14 +01:00
|
|
|
|
2008-01-16 07:11:50 +01:00
|
|
|
if (pswd.isEmpty())
|
2007-04-07 10:47:58 +02:00
|
|
|
{
|
2008-01-16 07:11:50 +01:00
|
|
|
#ifdef TRUSTED_AUTH
|
|
|
|
if (!flag_trusted)
|
|
|
|
#endif
|
2007-04-07 10:47:58 +02:00
|
|
|
{
|
2008-05-19 15:58:37 +02:00
|
|
|
fb_utils::readenv(ISC_PASSWORD, pswd);
|
2007-04-07 10:47:58 +02:00
|
|
|
}
|
|
|
|
}
|
2003-11-03 02:12:14 +01:00
|
|
|
|
2003-12-22 11:00:59 +01:00
|
|
|
ISC_STATUS_ARRAY status;
|
2007-05-08 17:13:57 +02:00
|
|
|
FB_API_HANDLE svc_handle = 0;
|
2008-12-01 10:21:31 +01:00
|
|
|
|
2007-05-08 17:13:57 +02:00
|
|
|
try
|
2007-04-07 10:47:58 +02:00
|
|
|
{
|
2007-05-08 17:13:57 +02:00
|
|
|
Firebird::ClumpletWriter spb(Firebird::ClumpletWriter::SpbAttach, 4096, isc_spb_current_version);
|
2008-12-01 10:21:31 +01:00
|
|
|
/*
|
2007-05-08 17:13:57 +02:00
|
|
|
* isc_spb_user_name
|
|
|
|
* isc_spb_password
|
|
|
|
* isc_spb_trusted_auth
|
|
|
|
* isc_spb_options
|
|
|
|
*/
|
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
if (usr.hasData())
|
2007-05-08 17:13:57 +02:00
|
|
|
{
|
|
|
|
spb.insertString(isc_spb_user_name, usr);
|
|
|
|
}
|
2008-12-01 10:21:31 +01:00
|
|
|
if (pswd.hasData())
|
2007-05-08 17:13:57 +02:00
|
|
|
{
|
|
|
|
spb.insertString(isc_spb_password, pswd);
|
|
|
|
}
|
2008-01-16 07:11:50 +01:00
|
|
|
#ifdef TRUSTED_AUTH
|
|
|
|
if (flag_trusted)
|
|
|
|
#endif
|
2007-05-08 17:13:57 +02:00
|
|
|
{
|
|
|
|
spb.insertTag(isc_spb_trusted_auth);
|
|
|
|
}
|
2003-11-03 02:12:14 +01:00
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
// Fill command line options
|
2007-05-08 17:13:57 +02:00
|
|
|
Firebird::string options;
|
2008-01-16 07:11:50 +01:00
|
|
|
for (itr = 1; itr < argc; ++itr)
|
2007-05-08 17:13:57 +02:00
|
|
|
{
|
2008-01-16 07:11:50 +01:00
|
|
|
if (!argv[itr])
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
2008-05-16 16:08:45 +02:00
|
|
|
Firebird::UtilSvc::addStringWithSvcTrmntr(argv[itr], options);
|
2007-05-08 17:13:57 +02:00
|
|
|
}
|
2008-05-16 16:08:45 +02:00
|
|
|
options.rtrim();
|
2003-11-03 02:12:14 +01:00
|
|
|
|
2007-05-08 17:13:57 +02:00
|
|
|
spb.insertString(isc_spb_command_line, options);
|
2003-11-03 02:12:14 +01:00
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
if (isc_service_attach(status, 0, service.c_str(), &svc_handle,
|
2007-05-08 17:13:57 +02:00
|
|
|
spb.getBufferLength(), reinterpret_cast<const char*>(spb.getBuffer())))
|
|
|
|
{
|
|
|
|
BURP_print_status(status);
|
|
|
|
BURP_print(83);
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 83 Exiting before completion due to errors
|
2007-05-08 17:13:57 +02:00
|
|
|
return FINI_ERROR;
|
|
|
|
}
|
2003-11-03 02:12:14 +01:00
|
|
|
|
2007-05-08 17:13:57 +02:00
|
|
|
char thd[2];
|
|
|
|
// 'isc_action_svc_restore/isc_action_svc_backup'
|
|
|
|
// 'isc_spb_verbose'
|
2003-11-03 02:12:14 +01:00
|
|
|
|
2007-05-08 17:13:57 +02:00
|
|
|
char *thd_ptr = thd;
|
2008-01-16 07:11:50 +01:00
|
|
|
if (flag_restore)
|
2007-05-08 17:13:57 +02:00
|
|
|
*thd_ptr++ = isc_action_svc_restore;
|
|
|
|
else
|
|
|
|
*thd_ptr++ = isc_action_svc_backup;
|
2003-11-03 02:12:14 +01:00
|
|
|
|
2008-01-16 07:11:50 +01:00
|
|
|
if (flag_verbose)
|
2007-05-08 17:13:57 +02:00
|
|
|
*thd_ptr++ = isc_spb_verbose;
|
2003-11-03 02:12:14 +01:00
|
|
|
|
2008-05-23 15:05:35 +02:00
|
|
|
const USHORT thdlen = thd_ptr - thd;
|
2003-11-03 02:12:14 +01:00
|
|
|
|
2007-05-08 17:13:57 +02:00
|
|
|
if (isc_service_start(status, &svc_handle, NULL, thdlen, thd))
|
2003-11-03 02:12:14 +01:00
|
|
|
{
|
|
|
|
BURP_print_status(status);
|
2007-02-11 10:04:54 +01:00
|
|
|
isc_service_detach(status, &svc_handle);
|
2007-03-28 06:20:36 +02:00
|
|
|
BURP_print(83); // msg 83 Exiting before completion due to errors
|
2003-11-03 02:12:14 +01:00
|
|
|
return FINI_ERROR;
|
|
|
|
}
|
|
|
|
|
2007-05-08 17:13:57 +02:00
|
|
|
const char sendbuf[] = { isc_info_svc_line };
|
|
|
|
char respbuf[1024];
|
|
|
|
const char* sl;
|
|
|
|
do {
|
|
|
|
if (isc_service_query(status, &svc_handle, NULL, 0, NULL,
|
|
|
|
sizeof(sendbuf), sendbuf,
|
|
|
|
sizeof(respbuf), respbuf))
|
|
|
|
{
|
|
|
|
BURP_print_status(status);
|
|
|
|
isc_service_detach(status, &svc_handle);
|
|
|
|
BURP_print(83); // msg 83 Exiting before completion due to errors
|
|
|
|
return FINI_ERROR;
|
|
|
|
}
|
2003-11-03 02:12:14 +01:00
|
|
|
|
2007-05-08 17:13:57 +02:00
|
|
|
char* p = respbuf;
|
|
|
|
sl = p;
|
|
|
|
|
2008-01-16 07:11:50 +01:00
|
|
|
if (*p++ == isc_info_svc_line)
|
2003-11-03 02:12:14 +01:00
|
|
|
{
|
2007-05-08 17:13:57 +02:00
|
|
|
const ISC_USHORT len = (ISC_USHORT) isc_vax_integer(p, sizeof(ISC_USHORT));
|
|
|
|
p += sizeof(ISC_USHORT);
|
|
|
|
if (!len)
|
|
|
|
{
|
|
|
|
if (*p == isc_info_data_not_ready)
|
|
|
|
continue;
|
2008-05-23 15:05:35 +02:00
|
|
|
|
|
|
|
if (*p == isc_info_end)
|
2007-05-08 17:13:57 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
p[len] = '\0';
|
|
|
|
burp_output("%s\n", p);
|
2003-11-03 02:12:14 +01:00
|
|
|
}
|
2007-05-08 17:13:57 +02:00
|
|
|
} while (*sl == isc_info_svc_line);
|
2003-11-03 02:12:14 +01:00
|
|
|
|
2007-05-08 17:13:57 +02:00
|
|
|
isc_service_detach(status, &svc_handle);
|
|
|
|
return FINI_OK;
|
|
|
|
}
|
2007-05-09 04:03:49 +02:00
|
|
|
catch (const Firebird::Exception& e)
|
2007-05-08 17:13:57 +02:00
|
|
|
{
|
|
|
|
e.stuff_exception(status);
|
|
|
|
BURP_print_status(status);
|
|
|
|
if (svc_handle)
|
|
|
|
{
|
|
|
|
isc_service_detach(status, &svc_handle);
|
2003-11-03 02:12:14 +01:00
|
|
|
}
|
2007-05-08 17:13:57 +02:00
|
|
|
BURP_print(83); // msg 83 Exiting before completion due to errors
|
|
|
|
return FINI_ERROR;
|
|
|
|
}
|
2003-11-03 02:12:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-01-16 07:11:50 +01:00
|
|
|
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;
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
|
2008-05-23 15:19:20 +02:00
|
|
|
static in_sw_tab_t* findSwitch(in_sw_tab_t* const table, Firebird::string sw, bool throwErrors)
|
2008-01-16 07:11:50 +01:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* 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;
|
|
|
|
}
|
2008-05-23 15:27:47 +02:00
|
|
|
if (sw[0] != switch_char)
|
2008-01-16 07:11:50 +01:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
sw.erase(0, 1);
|
|
|
|
sw.upper();
|
|
|
|
|
2008-05-23 15:19:20 +02:00
|
|
|
for (in_sw_tab_t* in_sw_tab = table; in_sw_tab->in_sw_name; in_sw_tab++)
|
2008-01-16 07:11:50 +01:00
|
|
|
{
|
|
|
|
if (switchMatch(sw, in_sw_tab->in_sw_name))
|
|
|
|
{
|
|
|
|
return in_sw_tab;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (throwErrors)
|
|
|
|
{
|
|
|
|
BURP_print(137, sw.c_str());
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 137 unknown switch %s
|
2008-05-23 15:19:20 +02:00
|
|
|
burp_usage(table);
|
2008-01-16 07:11:50 +01:00
|
|
|
BURP_error(1, true);
|
|
|
|
// msg 1: found unknown switch
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int gbak(Firebird::UtilSvc* uSvc)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* B U R P _ g b a k
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
2008-01-16 07:11:50 +01:00
|
|
|
* Routine called by command line utility and services API.
|
2001-05-23 15:26:42 +02:00
|
|
|
*
|
|
|
|
**************************************/
|
2004-03-01 04:35:23 +01:00
|
|
|
gbak_action action = QUIT;
|
2008-01-16 07:11:50 +01:00
|
|
|
int exit_code = FINI_ERROR;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-16 07:11:50 +01:00
|
|
|
BurpGlobals sgbl(uSvc);
|
|
|
|
BurpGlobals *tdgbl = &sgbl;
|
2004-07-03 04:33:46 +02:00
|
|
|
BurpGlobals::putSpecific(tdgbl);
|
2008-01-16 07:11:50 +01:00
|
|
|
|
2006-02-23 06:08:26 +01:00
|
|
|
tdgbl->burp_throw = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
tdgbl->file_desc = INVALID_HANDLE_VALUE;
|
2008-01-16 07:11:50 +01:00
|
|
|
|
|
|
|
Firebird::UtilSvc::ArgvType& argv = uSvc->argv;
|
2008-04-21 14:14:16 +02:00
|
|
|
const int argc = uSvc->argv.getCount();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-05-23 15:05:35 +02:00
|
|
|
// Copy the static const table to a local array for processing.
|
|
|
|
in_sw_tab_t burp_in_sw_table[FB_NELEM(reference_burp_in_sw_table)];
|
|
|
|
|
2008-05-25 03:39:16 +02:00
|
|
|
for (size_t maxt = FB_NELEM(reference_burp_in_sw_table), iter = 0; iter < maxt; ++iter)
|
2008-01-16 07:11:50 +01:00
|
|
|
{
|
2008-05-23 15:05:35 +02:00
|
|
|
burp_in_sw_table[iter] = reference_burp_in_sw_table[iter];
|
2008-05-23 15:27:47 +02:00
|
|
|
burp_in_sw_table[iter].in_sw_state = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2008-01-16 07:11:50 +01:00
|
|
|
// test for "-service" switch
|
|
|
|
for (int itr = 1; itr < argc; ++itr)
|
|
|
|
{
|
2008-05-23 15:05:35 +02:00
|
|
|
const in_sw_tab_t* inSw = findSwitch(burp_in_sw_table, argv[itr], false);
|
2003-09-12 11:04:38 +02:00
|
|
|
|
2008-01-16 07:11:50 +01:00
|
|
|
if (inSw && inSw->in_sw == IN_SW_BURP_SE)
|
|
|
|
{
|
2008-05-23 15:05:35 +02:00
|
|
|
return api_gbak(uSvc, burp_in_sw_table);
|
2008-01-16 07:11:50 +01:00
|
|
|
}
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-16 07:11:50 +01:00
|
|
|
try {
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-05-23 15:05:35 +02:00
|
|
|
in_sw_tab_t* in_sw_tab;
|
|
|
|
|
2004-03-01 04:35:23 +01:00
|
|
|
tdgbl->status = tdgbl->status_vector;
|
2008-04-07 12:52:34 +02:00
|
|
|
uSvc->started();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2005-04-09 20:44:50 +02:00
|
|
|
if (argc <= 1) {
|
2008-05-23 15:05:35 +02:00
|
|
|
burp_usage(burp_in_sw_table);
|
2005-04-09 20:44:50 +02:00
|
|
|
BURP_exit_local(FINI_ERROR, tdgbl);
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-09-12 11:04:38 +02:00
|
|
|
USHORT sw_replace = FALSE;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-01-13 10:52:19 +01:00
|
|
|
tdgbl->gbl_sw_compress = true;
|
|
|
|
tdgbl->gbl_sw_convert_ext_tables = false;
|
|
|
|
tdgbl->gbl_sw_transportable = true;
|
|
|
|
tdgbl->gbl_sw_ignore_limbo = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
tdgbl->gbl_sw_blk_factor = 0;
|
2004-01-13 10:52:19 +01:00
|
|
|
tdgbl->gbl_sw_no_reserve = false;
|
|
|
|
tdgbl->gbl_sw_old_descriptions = false;
|
2003-09-13 01:25:16 +02:00
|
|
|
tdgbl->gbl_sw_mode = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
tdgbl->gbl_sw_skip_count = 0;
|
|
|
|
tdgbl->action = NULL;
|
2003-09-12 11:04:38 +02:00
|
|
|
|
2004-01-13 10:52:19 +01:00
|
|
|
burp_fil* file = NULL;
|
|
|
|
burp_fil* file_list = NULL;
|
2001-05-23 15:26:42 +02:00
|
|
|
tdgbl->io_buffer_size = GBAK_IO_BUFFER_SIZE;
|
2008-12-01 10:21:31 +01:00
|
|
|
|
2004-06-05 11:37:18 +02:00
|
|
|
// Avoid overwriting literal strings.
|
|
|
|
char none[] = "-*NONE*";
|
2008-12-01 10:21:31 +01:00
|
|
|
|
2008-01-16 07:11:50 +01:00
|
|
|
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);
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-05-23 15:27:47 +02:00
|
|
|
if (str[0] != switch_char)
|
2008-01-16 07:11:50 +01:00
|
|
|
{
|
2008-12-01 10:21:31 +01:00
|
|
|
if (!file || file->fil_length || !get_size(argv[itr], file))
|
2008-01-16 07:11:50 +01:00
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
/* Miserable thing must be a filename
|
|
|
|
(dummy in a length for the backup file */
|
|
|
|
|
2008-01-16 07:11:50 +01:00
|
|
|
file = FB_NEW(*getDefaultMemoryPool()) burp_fil(*getDefaultMemoryPool());
|
|
|
|
file->fil_name = str.ToPathName();
|
|
|
|
file->fil_length = file_list ? 0 : MAX_LENGTH;
|
2001-05-23 15:26:42 +02:00
|
|
|
file->fil_next = file_list;
|
|
|
|
file_list = file;
|
|
|
|
}
|
2008-05-23 15:27:47 +02:00
|
|
|
continue;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2008-05-23 15:27:47 +02:00
|
|
|
|
|
|
|
if (str.length() == 1)
|
2008-01-16 07:11:50 +01:00
|
|
|
{
|
2008-05-23 15:27:47 +02:00
|
|
|
str = none;
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-05-23 15:27:47 +02:00
|
|
|
in_sw_tab = findSwitch(burp_in_sw_table, str, true);
|
|
|
|
fb_assert(in_sw_tab);
|
|
|
|
in_sw_tab->in_sw_state = true;
|
2005-04-09 20:44:50 +02:00
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
if (in_sw_tab->in_sw == IN_SW_BURP_RECREATE)
|
2008-05-23 15:27:47 +02:00
|
|
|
{
|
|
|
|
int real_sw = IN_SW_BURP_C;
|
|
|
|
if ((itr < argc - 1) && (*argv[itr + 1] != switch_char))
|
2008-01-16 07:11:50 +01:00
|
|
|
{
|
2008-05-23 15:27:47 +02:00
|
|
|
// find optional BURP_SW_OVERWRITE parameter
|
|
|
|
Firebird::string next(argv[itr + 1]);
|
|
|
|
next.upper();
|
2008-12-19 13:43:30 +01:00
|
|
|
if (strstr(BURP_SW_OVERWRITE, next.c_str()) == BURP_SW_OVERWRITE)
|
2008-01-16 07:11:50 +01:00
|
|
|
{
|
2008-05-23 15:27:47 +02:00
|
|
|
real_sw = IN_SW_BURP_R;
|
|
|
|
itr++;
|
2005-04-09 20:44:50 +02:00
|
|
|
}
|
2008-05-23 15:27:47 +02:00
|
|
|
}
|
2005-04-09 20:44:50 +02:00
|
|
|
|
2008-05-23 15:27:47 +02:00
|
|
|
// replace IN_SW_BURP_RECREATE by IN_SW_BURP_R or IN_SW_BURP_C
|
|
|
|
in_sw_tab->in_sw_state = false;
|
2005-04-09 20:44:50 +02:00
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
in_sw_tab_t* real_sw_tab = burp_in_sw_table;
|
2008-05-23 15:27:47 +02:00
|
|
|
while (real_sw_tab->in_sw != real_sw)
|
|
|
|
++real_sw_tab;
|
2008-12-01 10:21:31 +01:00
|
|
|
|
2008-05-23 15:27:47 +02:00
|
|
|
real_sw_tab->in_sw_state = true;
|
|
|
|
}
|
2008-12-01 10:21:31 +01:00
|
|
|
else if (in_sw_tab->in_sw == IN_SW_BURP_S)
|
2008-05-23 15:27:47 +02:00
|
|
|
{
|
|
|
|
if (++itr >= argc)
|
|
|
|
{
|
|
|
|
BURP_error(200, true);
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 200: missing parameter for the number of bytes to be skipped
|
2005-04-09 20:44:50 +02:00
|
|
|
}
|
2008-05-23 15:27:47 +02:00
|
|
|
tdgbl->gbl_sw_skip_count = get_number(argv[itr]);
|
|
|
|
if (!tdgbl->gbl_sw_skip_count)
|
2008-01-16 07:11:50 +01:00
|
|
|
{
|
2008-05-23 15:27:47 +02:00
|
|
|
BURP_error(201, true, argv[itr]);
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 201: expected number of bytes to be skipped, encountered "%s"
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2008-05-23 15:27:47 +02:00
|
|
|
}
|
2008-12-01 10:21:31 +01:00
|
|
|
else if (in_sw_tab->in_sw == IN_SW_BURP_P)
|
2008-05-23 15:27:47 +02:00
|
|
|
{
|
|
|
|
if (++itr >= argc)
|
2008-01-16 07:11:50 +01:00
|
|
|
{
|
2008-05-23 15:27:47 +02:00
|
|
|
BURP_error(2, true);
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 2 page size parameter missing
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2008-05-23 15:27:47 +02:00
|
|
|
tdgbl->gbl_sw_page_size = (USHORT) get_number(argv[itr]);
|
|
|
|
if (!tdgbl->gbl_sw_page_size)
|
2008-01-16 07:11:50 +01:00
|
|
|
{
|
2008-05-23 15:27:47 +02:00
|
|
|
BURP_error(12, true, argv[itr]);
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 12 expected page size, encountered "%s"
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2008-05-23 15:27:47 +02:00
|
|
|
}
|
2008-12-01 10:21:31 +01:00
|
|
|
else if (in_sw_tab->in_sw == IN_SW_BURP_BU)
|
2008-05-23 15:27:47 +02:00
|
|
|
{
|
|
|
|
if (++itr >= argc)
|
2008-01-16 07:11:50 +01:00
|
|
|
{
|
2008-05-23 15:27:47 +02:00
|
|
|
BURP_error(258, true);
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 258 page buffers parameter missing
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2008-05-23 15:27:47 +02:00
|
|
|
tdgbl->gbl_sw_page_buffers = get_number(argv[itr]);
|
|
|
|
if (!tdgbl->gbl_sw_page_buffers)
|
2008-01-16 07:11:50 +01:00
|
|
|
{
|
2008-05-23 15:27:47 +02:00
|
|
|
BURP_error(259, true, argv[itr]);
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 259 expected page buffers, encountered "%s"
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2008-05-23 15:27:47 +02:00
|
|
|
}
|
2008-12-01 10:21:31 +01:00
|
|
|
else if (in_sw_tab->in_sw == IN_SW_BURP_MODE)
|
2008-05-23 15:27:47 +02:00
|
|
|
{
|
|
|
|
if (++itr >= argc)
|
2008-01-16 07:11:50 +01:00
|
|
|
{
|
2008-05-23 15:27:47 +02:00
|
|
|
BURP_error(279, true);
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 279: "read_only" or "read_write" required
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2008-05-23 15:27:47 +02:00
|
|
|
str = argv[itr];
|
|
|
|
str.lower();
|
|
|
|
if (str == BURP_SW_MODE_RO)
|
|
|
|
tdgbl->gbl_sw_mode_val = true;
|
|
|
|
else if (str == BURP_SW_MODE_RW)
|
|
|
|
tdgbl->gbl_sw_mode_val = false;
|
|
|
|
else
|
2008-01-16 07:11:50 +01:00
|
|
|
{
|
2008-05-23 15:27:47 +02:00
|
|
|
BURP_error(279, true);
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 279: "read_only" or "read_write" required
|
2006-12-08 19:38:15 +01:00
|
|
|
}
|
2008-05-23 15:27:47 +02:00
|
|
|
tdgbl->gbl_sw_mode = true;
|
|
|
|
}
|
2008-12-01 10:21:31 +01:00
|
|
|
else if (in_sw_tab->in_sw == IN_SW_BURP_PASS)
|
2008-05-23 15:27:47 +02:00
|
|
|
{
|
|
|
|
if (++itr >= argc)
|
2008-01-16 07:11:50 +01:00
|
|
|
{
|
2008-05-23 15:27:47 +02:00
|
|
|
BURP_error(189, true);
|
2008-12-01 10:21:31 +01:00
|
|
|
// password parameter missing
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2008-05-23 15:27:47 +02:00
|
|
|
uSvc->hidePasswd(argv, itr);
|
2008-11-24 18:22:44 +01:00
|
|
|
if (tdgbl->gbl_sw_password)
|
|
|
|
{
|
|
|
|
BURP_error(307, true);
|
|
|
|
// too many passwords provided
|
|
|
|
}
|
2008-05-23 15:27:47 +02:00
|
|
|
tdgbl->gbl_sw_password = argv[itr];
|
|
|
|
}
|
2008-12-02 08:09:49 +01:00
|
|
|
else if (in_sw_tab->in_sw == IN_SW_BURP_FETCHPASS)
|
2008-11-24 18:22:44 +01:00
|
|
|
{
|
|
|
|
if (++itr >= argc)
|
|
|
|
{
|
|
|
|
BURP_error(189, true);
|
2008-12-01 10:21:31 +01:00
|
|
|
// password parameter missing
|
2008-11-24 18:22:44 +01:00
|
|
|
}
|
|
|
|
if (tdgbl->gbl_sw_password)
|
|
|
|
{
|
|
|
|
BURP_error(307, true);
|
|
|
|
// too many passwords provided
|
|
|
|
}
|
2008-12-02 08:09:49 +01:00
|
|
|
switch (fb_utils::fetchPassword(argv[itr], tdgbl->gbl_sw_password))
|
2008-11-24 18:22:44 +01:00
|
|
|
{
|
2008-11-30 18:11:56 +01:00
|
|
|
case fb_utils::FETCH_PASS_OK:
|
|
|
|
break;
|
|
|
|
case fb_utils::FETCH_PASS_FILE_OPEN_ERROR:
|
2008-11-24 18:22:44 +01:00
|
|
|
BURP_error(308, true, MsgFormat::SafeArg() << argv[itr] << errno);
|
|
|
|
// error @2 opening password file @1
|
2008-11-30 18:11:56 +01:00
|
|
|
break;
|
|
|
|
case fb_utils::FETCH_PASS_FILE_READ_ERROR:
|
|
|
|
BURP_error(309, true, MsgFormat::SafeArg() << argv[itr] << errno);
|
|
|
|
// error @2 reading password file @1
|
|
|
|
break;
|
|
|
|
case fb_utils::FETCH_PASS_FILE_EMPTY:
|
|
|
|
BURP_error(310, true, MsgFormat::SafeArg() << argv[itr]);
|
|
|
|
// password file @1 is empty
|
|
|
|
break;
|
2008-11-24 18:22:44 +01:00
|
|
|
}
|
|
|
|
}
|
2008-12-01 10:21:31 +01:00
|
|
|
else if (in_sw_tab->in_sw == IN_SW_BURP_USER)
|
2008-05-23 15:27:47 +02:00
|
|
|
{
|
|
|
|
if (++itr >= argc)
|
2008-01-16 07:11:50 +01:00
|
|
|
{
|
2008-05-23 15:27:47 +02:00
|
|
|
BURP_error(188, true);
|
2008-12-01 10:21:31 +01:00
|
|
|
// user name parameter missing
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2008-05-23 15:27:47 +02:00
|
|
|
tdgbl->gbl_sw_user = argv[itr];
|
|
|
|
}
|
2008-12-01 10:21:31 +01:00
|
|
|
else if (in_sw_tab->in_sw == IN_SW_BURP_TRUSTED_SVC)
|
2008-05-23 15:27:47 +02:00
|
|
|
{
|
|
|
|
uSvc->checkService();
|
|
|
|
if (++itr >= argc)
|
2008-04-11 14:57:52 +02:00
|
|
|
{
|
2008-05-23 15:27:47 +02:00
|
|
|
BURP_error(188, true);
|
2008-12-01 10:21:31 +01:00
|
|
|
// trusted user name parameter missing
|
2008-04-11 14:57:52 +02:00
|
|
|
}
|
2008-05-23 15:27:47 +02:00
|
|
|
tdgbl->gbl_sw_tr_user = argv[itr];
|
|
|
|
#ifdef TRUSTED_AUTH
|
|
|
|
burp_in_sw_table[IN_SW_BURP_TRUSTED_USER].in_sw_state = true;
|
|
|
|
#endif
|
|
|
|
}
|
2008-12-01 10:21:31 +01:00
|
|
|
else if (in_sw_tab->in_sw == IN_SW_BURP_ROLE)
|
2008-05-23 15:27:47 +02:00
|
|
|
{
|
|
|
|
if (++itr >= argc)
|
2008-04-11 14:57:52 +02:00
|
|
|
{
|
2008-05-23 15:27:47 +02:00
|
|
|
BURP_error(253, true);
|
|
|
|
// SQL role parameter missing
|
2008-12-01 10:21:31 +01:00
|
|
|
}
|
2008-05-23 15:27:47 +02:00
|
|
|
tdgbl->gbl_sw_sql_role = argv[itr];
|
|
|
|
}
|
2008-12-01 10:21:31 +01:00
|
|
|
else if (in_sw_tab->in_sw == IN_SW_BURP_FA)
|
2008-05-23 15:27:47 +02:00
|
|
|
{
|
|
|
|
if (++itr >= argc)
|
|
|
|
{
|
|
|
|
BURP_error(182, true);
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 182 blocking factor parameter missing
|
2008-04-11 14:57:52 +02:00
|
|
|
}
|
2008-05-23 15:27:47 +02:00
|
|
|
tdgbl->gbl_sw_blk_factor = get_number(argv[itr]);
|
|
|
|
if (!tdgbl->gbl_sw_blk_factor)
|
2008-01-16 07:11:50 +01:00
|
|
|
{
|
2008-05-23 15:27:47 +02:00
|
|
|
BURP_error(183, true, argv[itr]);
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 183 expected blocking factor, encountered "%s"
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2008-05-23 15:27:47 +02:00
|
|
|
}
|
|
|
|
else if (in_sw_tab->in_sw == IN_SW_BURP_FIX_FSS_DATA)
|
|
|
|
{
|
|
|
|
if (++itr >= argc)
|
2008-01-16 07:11:50 +01:00
|
|
|
{
|
2008-05-23 15:27:47 +02:00
|
|
|
BURP_error(304, true);
|
|
|
|
// Character set parameter missing
|
2008-12-01 10:21:31 +01:00
|
|
|
}
|
2008-05-23 15:27:47 +02:00
|
|
|
tdgbl->gbl_sw_fix_fss_data = argv[itr];
|
|
|
|
}
|
|
|
|
else if (in_sw_tab->in_sw == IN_SW_BURP_FIX_FSS_METADATA)
|
|
|
|
{
|
|
|
|
if (++itr >= argc)
|
|
|
|
{
|
|
|
|
BURP_error(304, true);
|
|
|
|
// Character set parameter missing
|
2008-12-01 10:21:31 +01:00
|
|
|
}
|
2008-05-23 15:27:47 +02:00
|
|
|
tdgbl->gbl_sw_fix_fss_metadata = argv[itr];
|
|
|
|
}
|
2008-12-01 10:21:31 +01:00
|
|
|
else if (in_sw_tab->in_sw == IN_SW_BURP_SE)
|
2008-05-23 15:27:47 +02:00
|
|
|
{
|
|
|
|
if (++itr >= argc)
|
|
|
|
{
|
|
|
|
BURP_error(273, true);
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 273: service name parameter missing
|
2008-05-23 15:27:47 +02:00
|
|
|
}
|
2008-12-01 10:21:31 +01:00
|
|
|
// skip a service specification
|
2008-05-23 15:27:47 +02:00
|
|
|
in_sw_tab->in_sw_state = false;
|
|
|
|
}
|
|
|
|
// want to do output redirect handling now instead of waiting
|
2008-12-01 10:21:31 +01:00
|
|
|
else if (in_sw_tab->in_sw == IN_SW_BURP_Y)
|
2008-05-23 15:27:47 +02:00
|
|
|
{
|
|
|
|
const TEXT* redirect = NULL;
|
|
|
|
if (++itr < argc)
|
|
|
|
{
|
|
|
|
redirect = argv[itr];
|
|
|
|
if (*redirect == switch_char)
|
2008-01-16 07:11:50 +01:00
|
|
|
{
|
2008-05-23 15:27:47 +02:00
|
|
|
redirect = NULL;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2008-05-23 15:27:47 +02:00
|
|
|
}
|
|
|
|
if (!redirect)
|
|
|
|
{
|
|
|
|
BURP_error(4, true);
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 4 redirect location for output is not specified
|
2008-05-23 15:27:47 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-05-23 15:27:47 +02:00
|
|
|
Firebird::string up(redirect);
|
|
|
|
up.upper();
|
|
|
|
tdgbl->sw_redirect = (up == output_suppress) ? NOOUTPUT : REDIRECT;
|
2008-01-16 07:11:50 +01:00
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
if (tdgbl->sw_redirect == REDIRECT) // not NOREDIRECT, and not NOOUTPUT
|
2008-05-23 15:27:47 +02:00
|
|
|
{
|
2008-12-01 10:21:31 +01:00
|
|
|
// Make sure the status file doesn't already exist
|
2008-05-23 15:27:47 +02:00
|
|
|
FILE* tmp_outfile = fopen(redirect, fopen_read_type);
|
|
|
|
if (tmp_outfile) {
|
|
|
|
BURP_print(66, redirect);
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 66 can't open status and error output file %s
|
2008-05-23 15:27:47 +02:00
|
|
|
fclose(tmp_outfile);
|
|
|
|
BURP_exit_local(FINI_ERROR, tdgbl);
|
|
|
|
}
|
|
|
|
if (! (tdgbl->output_file = fopen(redirect, fopen_write_type)))
|
2008-01-16 07:11:50 +01:00
|
|
|
{
|
2008-05-23 15:27:47 +02:00
|
|
|
BURP_print(66, redirect);
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 66 can't open status and error output file %s
|
2008-05-23 15:27:47 +02:00
|
|
|
BURP_exit_local(FINI_ERROR, tdgbl);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2008-05-23 15:27:47 +02:00
|
|
|
}
|
2008-12-01 10:21:31 +01:00
|
|
|
} //else if (in_sw_tab->in_sw == IN_SW_BURP_Y)
|
2008-05-25 03:39:16 +02:00
|
|
|
} // for
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
// reverse the linked list of file blocks
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
tdgbl->gbl_sw_files = NULL;
|
|
|
|
|
2004-01-13 10:52:19 +01:00
|
|
|
burp_fil* next_file = NULL;
|
2001-05-23 15:26:42 +02:00
|
|
|
for (file = file_list; file; file = next_file) {
|
|
|
|
next_file = file->fil_next;
|
|
|
|
file->fil_next = tdgbl->gbl_sw_files;
|
|
|
|
tdgbl->gbl_sw_files = file;
|
|
|
|
}
|
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
// pop off the obviously boring ones, plus do some checking
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-10-29 11:53:47 +01:00
|
|
|
const TEXT* file1 = NULL;
|
2008-04-21 14:14:16 +02:00
|
|
|
const TEXT* file2 = NULL;
|
2008-12-01 10:21:31 +01:00
|
|
|
for (file = tdgbl->gbl_sw_files; file; file = file->fil_next)
|
2008-01-16 07:11:50 +01:00
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
if (!file1)
|
2008-01-16 07:11:50 +01:00
|
|
|
file1 = file->fil_name.c_str();
|
2001-05-23 15:26:42 +02:00
|
|
|
else if (!file2)
|
2008-01-16 07:11:50 +01:00
|
|
|
file2 = file->fil_name.c_str();
|
2001-05-23 15:26:42 +02:00
|
|
|
for (file_list = file->fil_next; file_list;
|
2003-09-14 03:08:18 +02:00
|
|
|
file_list = file_list->fil_next)
|
|
|
|
{
|
2008-01-16 07:11:50 +01:00
|
|
|
if (file->fil_name == file_list->fil_name)
|
|
|
|
{
|
2007-03-28 06:20:36 +02:00
|
|
|
BURP_error(9, true);
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 9 mutiple sources or destinations specified
|
2008-01-16 07:11:50 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2004-12-09 20:19:47 +01:00
|
|
|
// Initialize 'dpb'
|
2005-11-27 21:53:09 +01:00
|
|
|
Firebird::ClumpletWriter dpb(Firebird::ClumpletReader::Tagged, MAX_DPB_SIZE, isc_dpb_version1);
|
2004-12-09 20:19:47 +01:00
|
|
|
|
|
|
|
dpb.insertString(isc_dpb_gbak_attach, GDS_VERSION, strlen(GDS_VERSION));
|
2005-12-05 12:45:39 +01:00
|
|
|
dpb.insertByte(isc_dpb_gsec_attach, 1); // make it possible to have local security backups
|
2008-05-04 15:38:02 +02:00
|
|
|
uSvc->getAddressPath(dpb);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-05-23 15:27:47 +02:00
|
|
|
for (in_sw_tab = burp_in_sw_table; in_sw_tab->in_sw_name; in_sw_tab++)
|
|
|
|
{
|
|
|
|
if (!in_sw_tab->in_sw_state)
|
|
|
|
continue;
|
2008-12-01 10:21:31 +01:00
|
|
|
|
2008-05-23 15:27:47 +02:00
|
|
|
switch (in_sw_tab->in_sw)
|
|
|
|
{
|
2008-12-01 10:21:31 +01:00
|
|
|
case IN_SW_BURP_B:
|
2008-05-23 15:27:47 +02:00
|
|
|
if (sw_replace)
|
|
|
|
BURP_error(5, true);
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 5 conflicting switches for backup/restore
|
2008-05-23 15:27:47 +02:00
|
|
|
sw_replace = IN_SW_BURP_B;
|
|
|
|
break;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
case IN_SW_BURP_C:
|
2008-05-23 15:27:47 +02:00
|
|
|
if (sw_replace == IN_SW_BURP_B)
|
|
|
|
BURP_error(5, true);
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 5 conflicting switches for backup/restore
|
2008-05-23 15:27:47 +02:00
|
|
|
if (sw_replace != IN_SW_BURP_R)
|
|
|
|
sw_replace = IN_SW_BURP_C;
|
|
|
|
break;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
case IN_SW_BURP_CO:
|
2008-05-23 15:27:47 +02:00
|
|
|
tdgbl->gbl_sw_convert_ext_tables = true;
|
|
|
|
break;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
case IN_SW_BURP_E:
|
2008-05-23 15:27:47 +02:00
|
|
|
tdgbl->gbl_sw_compress = false;
|
|
|
|
break;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
case IN_SW_BURP_G:
|
2008-05-23 15:27:47 +02:00
|
|
|
dpb.insertTag(isc_dpb_no_garbage_collect);
|
|
|
|
break;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
case IN_SW_BURP_I:
|
2008-05-23 15:27:47 +02:00
|
|
|
tdgbl->gbl_sw_deactivate_indexes = true;
|
|
|
|
break;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
case IN_SW_BURP_IG:
|
2008-05-23 15:27:47 +02:00
|
|
|
dpb.insertByte(isc_dpb_damaged, 1);
|
|
|
|
break;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
case IN_SW_BURP_K:
|
2008-05-23 15:27:47 +02:00
|
|
|
tdgbl->gbl_sw_kill = true;
|
|
|
|
break;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
case IN_SW_BURP_L:
|
2008-05-23 15:27:47 +02:00
|
|
|
tdgbl->gbl_sw_ignore_limbo = true;
|
|
|
|
break;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
case IN_SW_BURP_M:
|
2008-05-23 15:27:47 +02:00
|
|
|
tdgbl->gbl_sw_meta = true;
|
|
|
|
break;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
case IN_SW_BURP_MODE:
|
2008-05-23 15:27:47 +02:00
|
|
|
tdgbl->gbl_sw_mode = true;
|
|
|
|
break;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
case IN_SW_BURP_N:
|
2008-05-23 15:27:47 +02:00
|
|
|
tdgbl->gbl_sw_novalidity = true;
|
|
|
|
break;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
case IN_SW_BURP_NOD:
|
2008-05-23 15:27:47 +02:00
|
|
|
tdgbl->gbl_sw_nodbtriggers = true;
|
|
|
|
dpb.insertByte(isc_dpb_no_db_triggers, 1);
|
|
|
|
break;
|
2006-11-05 19:30:36 +01:00
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
case IN_SW_BURP_NT: // Backup non-transportable format
|
2008-05-23 15:27:47 +02:00
|
|
|
tdgbl->gbl_sw_transportable = false;
|
|
|
|
break;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
case IN_SW_BURP_O:
|
2008-05-23 15:27:47 +02:00
|
|
|
tdgbl->gbl_sw_incremental = true;
|
|
|
|
break;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
case IN_SW_BURP_OL:
|
2008-05-23 15:27:47 +02:00
|
|
|
tdgbl->gbl_sw_old_descriptions = true;
|
|
|
|
break;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
case IN_SW_BURP_PASS:
|
|
|
|
case IN_SW_BURP_FETCHPASS:
|
2008-05-23 15:27:47 +02:00
|
|
|
dpb.insertString(tdgbl->uSvc->isService() ?
|
|
|
|
isc_dpb_password_enc : isc_dpb_password,
|
|
|
|
tdgbl->gbl_sw_password, strlen(tdgbl->gbl_sw_password));
|
|
|
|
break;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
case IN_SW_BURP_R:
|
2008-05-23 15:27:47 +02:00
|
|
|
if (sw_replace == IN_SW_BURP_B)
|
|
|
|
BURP_error(5, true);
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 5 conflicting switches for backup/restore
|
2008-05-23 15:27:47 +02:00
|
|
|
sw_replace = IN_SW_BURP_R;
|
|
|
|
break;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
case IN_SW_BURP_T:
|
2008-05-23 15:27:47 +02:00
|
|
|
tdgbl->gbl_sw_transportable = true;
|
|
|
|
break;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
case IN_SW_BURP_U:
|
2008-05-23 15:27:47 +02:00
|
|
|
BURP_error(7, true);
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 7 protection isn't there yet
|
2008-05-23 15:27:47 +02:00
|
|
|
break;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
case IN_SW_BURP_US:
|
2008-05-23 15:27:47 +02:00
|
|
|
tdgbl->gbl_sw_no_reserve = true;
|
|
|
|
break;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
case IN_SW_BURP_ROLE:
|
|
|
|
dpb.insertString(isc_dpb_sql_role_name,
|
2008-05-23 15:27:47 +02:00
|
|
|
tdgbl->gbl_sw_sql_role, strlen(tdgbl->gbl_sw_sql_role));
|
|
|
|
break;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
case IN_SW_BURP_USER:
|
|
|
|
dpb.insertString(isc_dpb_user_name,
|
2008-05-23 15:27:47 +02:00
|
|
|
tdgbl->gbl_sw_user, strlen(tdgbl->gbl_sw_user));
|
|
|
|
break;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
case IN_SW_BURP_TRUSTED_SVC:
|
2008-05-23 15:27:47 +02:00
|
|
|
uSvc->checkService();
|
|
|
|
dpb.deleteWithTag(isc_dpb_trusted_auth);
|
2008-12-01 10:21:31 +01:00
|
|
|
dpb.insertString(isc_dpb_trusted_auth,
|
2008-05-23 15:27:47 +02:00
|
|
|
tdgbl->gbl_sw_tr_user, strlen(tdgbl->gbl_sw_tr_user));
|
|
|
|
break;
|
2008-01-16 07:11:50 +01:00
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
case IN_SW_BURP_TRUSTED_ROLE:
|
2008-05-23 15:27:47 +02:00
|
|
|
uSvc->checkService();
|
|
|
|
dpb.deleteWithTag(isc_dpb_trusted_role);
|
|
|
|
dpb.insertString(isc_dpb_trusted_role, ADMIN_ROLE, strlen(ADMIN_ROLE));
|
|
|
|
break;
|
2007-04-07 10:47:58 +02:00
|
|
|
#ifdef TRUSTED_AUTH
|
2008-12-01 10:21:31 +01:00
|
|
|
case IN_SW_BURP_TRUSTED_USER:
|
2008-05-23 15:27:47 +02:00
|
|
|
if (!dpb.find(isc_dpb_trusted_auth))
|
|
|
|
{
|
|
|
|
dpb.insertTag(isc_dpb_trusted_auth);
|
|
|
|
}
|
|
|
|
break;
|
2006-12-08 19:38:15 +01:00
|
|
|
#endif
|
2008-12-01 10:21:31 +01:00
|
|
|
case IN_SW_BURP_V:
|
2008-05-23 15:27:47 +02:00
|
|
|
tdgbl->gbl_sw_verbose = true;
|
|
|
|
break;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
case IN_SW_BURP_Z:
|
2008-05-23 15:27:47 +02:00
|
|
|
BURP_print(91, GDS_VERSION);
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 91 gbak version %s
|
2008-05-23 15:27:47 +02:00
|
|
|
tdgbl->gbl_sw_version = true;
|
|
|
|
break;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-05-23 15:27:47 +02:00
|
|
|
default:
|
|
|
|
break;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!sw_replace)
|
|
|
|
sw_replace = IN_SW_BURP_B;
|
|
|
|
|
|
|
|
if (tdgbl->gbl_sw_page_size)
|
|
|
|
{
|
|
|
|
if (sw_replace == IN_SW_BURP_B)
|
2007-03-28 06:20:36 +02:00
|
|
|
BURP_error(8, true);
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 8 page size is allowed only on restore or create
|
2003-09-12 11:04:38 +02:00
|
|
|
int temp = tdgbl->gbl_sw_page_size;
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
int curr_pg_size = 1024;
|
|
|
|
while (curr_pg_size <= MAX_PAGE_SIZE) {
|
|
|
|
if (temp <= curr_pg_size) {
|
|
|
|
temp = curr_pg_size;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
curr_pg_size <<= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (temp > MAX_PAGE_SIZE)
|
|
|
|
{
|
2007-03-28 06:20:36 +02:00
|
|
|
BURP_error(3, true, SafeArg() << tdgbl->gbl_sw_page_size);
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 3 Page size specified (%ld) greater than limit (MAX_PAGE_SIZE bytes)
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
if (temp != tdgbl->gbl_sw_page_size) {
|
2007-03-28 06:20:36 +02:00
|
|
|
BURP_print(103, SafeArg() << tdgbl->gbl_sw_page_size << temp);
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 103 page size specified (%ld bytes) rounded up to %ld bytes
|
2001-05-23 15:26:42 +02:00
|
|
|
tdgbl->gbl_sw_page_size = temp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tdgbl->gbl_sw_page_buffers) {
|
|
|
|
if (sw_replace == IN_SW_BURP_B)
|
2007-03-28 06:20:36 +02:00
|
|
|
BURP_error(260, true);
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 260 page buffers is allowed only on restore or create
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!tdgbl->gbl_sw_blk_factor || sw_replace != IN_SW_BURP_B)
|
|
|
|
tdgbl->gbl_sw_blk_factor = 1;
|
|
|
|
|
|
|
|
if (!file2)
|
2007-03-28 06:20:36 +02:00
|
|
|
BURP_error(10, true);
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 10 requires both input and output filenames
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (!strcmp(file1, file2))
|
2007-03-28 06:20:36 +02:00
|
|
|
BURP_error(11, true);
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 11 input and output have the same name. Disallowed.
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-04-21 14:14:16 +02:00
|
|
|
{ // scope
|
|
|
|
// The string result produced by ctime contains exactly 26 characters and
|
|
|
|
// gbl_backup_start_time is TEXT[30], but let's make sure we don't overflow
|
|
|
|
// due to any change.
|
|
|
|
const time_t clock = time(NULL);
|
|
|
|
fb_utils::copy_terminate(tdgbl->gbl_backup_start_time, ctime(&clock),
|
|
|
|
sizeof(tdgbl->gbl_backup_start_time));
|
|
|
|
TEXT* nlp = tdgbl->gbl_backup_start_time + strlen(tdgbl->gbl_backup_start_time) - 1;
|
|
|
|
if (*nlp == '\n')
|
|
|
|
*nlp = 0;
|
|
|
|
} // scope
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-09-18 23:56:26 +02:00
|
|
|
tdgbl->action = (ACT) BURP_alloc_zero(ACT_LEN);
|
2001-05-23 15:26:42 +02:00
|
|
|
tdgbl->action->act_total = 0;
|
|
|
|
tdgbl->action->act_file = NULL;
|
|
|
|
tdgbl->action->act_action = ACT_unknown;
|
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
action = open_files(file1, &file2, tdgbl->gbl_sw_verbose,
|
2004-12-09 20:19:47 +01:00
|
|
|
sw_replace, dpb);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
MVOL_init(tdgbl->io_buffer_size);
|
2008-12-01 10:21:31 +01:00
|
|
|
|
2003-09-12 11:04:38 +02:00
|
|
|
int result;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-16 07:11:50 +01:00
|
|
|
tdgbl->uSvc->started();
|
2001-05-23 15:26:42 +02:00
|
|
|
switch (action) {
|
2008-12-01 10:21:31 +01:00
|
|
|
case RESTORE:
|
2005-04-09 20:44:50 +02:00
|
|
|
tdgbl->gbl_sw_overwrite = (sw_replace == IN_SW_BURP_R);
|
2001-05-23 15:26:42 +02:00
|
|
|
result = RESTORE_restore(file1, file2);
|
|
|
|
break;
|
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
case BACKUP:
|
2001-05-23 15:26:42 +02:00
|
|
|
result = BACKUP_backup(file1, file2);
|
|
|
|
break;
|
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
case QUIT:
|
2001-05-23 15:26:42 +02:00
|
|
|
BURP_abort();
|
2004-08-26 21:09:07 +02:00
|
|
|
return 0;
|
2008-12-01 10:21:31 +01:00
|
|
|
|
2004-08-26 21:09:07 +02:00
|
|
|
default:
|
|
|
|
// result undefined
|
|
|
|
fb_assert(false);
|
|
|
|
return 0;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
if (result != FINI_OK && result != FINI_DB_NOT_ONLINE)
|
|
|
|
BURP_abort();
|
|
|
|
|
2004-03-07 08:58:55 +01:00
|
|
|
BURP_exit_local(result, tdgbl);
|
2001-12-24 03:51:06 +01:00
|
|
|
} // try
|
|
|
|
|
2008-01-16 07:11:50 +01:00
|
|
|
catch (const Firebird::LongJump&)
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2008-12-01 10:21:31 +01:00
|
|
|
// All calls to exit_local(), normal and error exits, wind up here
|
2008-01-16 07:11:50 +01:00
|
|
|
tdgbl->burp_throw = false;
|
|
|
|
exit_code = tdgbl->exit_code;
|
|
|
|
}
|
2001-12-24 03:51:06 +01:00
|
|
|
|
2008-01-16 07:11:50 +01:00
|
|
|
catch (const Firebird::Exception& e)
|
|
|
|
{
|
|
|
|
// Non-burp exception was caught
|
2006-02-23 06:08:26 +01:00
|
|
|
tdgbl->burp_throw = false;
|
2008-01-16 07:11:50 +01:00
|
|
|
e.stuff_exception(tdgbl->status_vector);
|
2008-04-04 11:42:42 +02:00
|
|
|
BURP_print_status(tdgbl->status_vector, true);
|
2008-01-16 07:11:50 +01:00
|
|
|
BURP_print(83); // msg 83 Exiting before completion due to errors
|
2008-04-07 12:52:34 +02:00
|
|
|
exit_code = FINI_ERROR;
|
2008-01-16 07:11:50 +01:00
|
|
|
}
|
2001-12-24 03:51:06 +01:00
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
// Close the gbak file handles if they still open
|
2008-01-16 07:11:50 +01:00
|
|
|
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))
|
2003-09-12 11:04:38 +02:00
|
|
|
{
|
2008-01-16 07:11:50 +01:00
|
|
|
unlink_platf(file->fil_name.c_str());
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2008-01-16 07:11:50 +01:00
|
|
|
}
|
2001-12-24 03:51:06 +01:00
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
// Detach from database to release system resources
|
2008-01-16 07:11:50 +01:00
|
|
|
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))
|
|
|
|
{
|
2008-04-04 11:42:42 +02:00
|
|
|
BURP_print_status(tdgbl->status_vector, true);
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2008-01-16 07:11:50 +01:00
|
|
|
}
|
2001-12-24 03:51:06 +01:00
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
// Close the status output file
|
2008-01-16 07:11:50 +01:00
|
|
|
if (tdgbl->sw_redirect == REDIRECT && tdgbl->output_file != NULL) {
|
|
|
|
fclose(tdgbl->output_file);
|
|
|
|
tdgbl->output_file = NULL;
|
|
|
|
}
|
2001-12-24 03:51:06 +01:00
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
// Free all unfreed memory used by GBAK itself
|
2008-01-16 07:11:50 +01:00
|
|
|
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);
|
|
|
|
}
|
2001-12-24 03:51:06 +01:00
|
|
|
|
2008-01-16 07:11:50 +01:00
|
|
|
BurpGlobals::restoreSpecific();
|
2001-12-24 03:51:06 +01:00
|
|
|
|
2008-01-16 07:11:50 +01:00
|
|
|
#if defined(DEBUG_GDS_ALLOC)
|
|
|
|
if (!uSvc->isService())
|
|
|
|
{
|
2001-12-24 03:51:06 +01:00
|
|
|
gds_alloc_report(0, __FILE__, __LINE__);
|
2008-01-16 07:11:50 +01:00
|
|
|
}
|
2001-12-24 03:51:06 +01:00
|
|
|
#endif
|
|
|
|
|
2008-04-07 12:52:34 +02:00
|
|
|
if ((exit_code != FINI_OK) && uSvc->isService())
|
|
|
|
{
|
|
|
|
memcpy(uSvc->getStatus(), tdgbl->status, sizeof (ISC_STATUS_ARRAY));
|
|
|
|
}
|
|
|
|
|
2008-01-16 07:11:50 +01:00
|
|
|
return exit_code;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
void BURP_abort(void)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* B U R P _ a b o r t
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Abandon a failed operation.
|
|
|
|
*
|
|
|
|
**************************************/
|
2004-07-03 02:13:46 +02:00
|
|
|
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2007-03-28 06:20:36 +02:00
|
|
|
BURP_print(83);
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 83 Exiting before completion due to errors
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-16 07:11:50 +01:00
|
|
|
tdgbl->uSvc->started();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-01-13 10:52:19 +01:00
|
|
|
BURP_exit_local(FINI_ERROR, tdgbl);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2007-03-28 06:20:36 +02:00
|
|
|
void BURP_error(USHORT errcode,
|
|
|
|
bool abort,
|
|
|
|
const SafeArg& arg)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
2003-11-03 02:12:14 +01:00
|
|
|
* B U R P _ e r r o r
|
2001-05-23 15:26:42 +02:00
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
*
|
|
|
|
**************************************/
|
2004-07-03 02:13:46 +02:00
|
|
|
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
|
2003-11-03 02:12:14 +01:00
|
|
|
|
2008-09-11 13:51:25 +02:00
|
|
|
tdgbl->uSvc->setServiceStatus(burp_msg_fac, errcode, arg);
|
2008-01-16 07:11:50 +01:00
|
|
|
tdgbl->uSvc->started();
|
2003-11-03 02:12:14 +01:00
|
|
|
|
2007-03-28 06:20:36 +02:00
|
|
|
BURP_msg_partial(256); // msg 256: gbak: ERROR:
|
|
|
|
BURP_msg_put(errcode, arg);
|
2003-11-03 02:12:14 +01:00
|
|
|
if (abort)
|
2008-01-16 07:11:50 +01:00
|
|
|
{
|
2003-11-03 02:12:14 +01:00
|
|
|
BURP_abort();
|
2008-01-16 07:11:50 +01:00
|
|
|
}
|
2003-11-03 02:12:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-03-28 06:20:36 +02:00
|
|
|
void BURP_error(USHORT errcode,
|
|
|
|
bool abort,
|
|
|
|
const char* str)
|
2003-11-03 02:12:14 +01:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* B U R P _ e r r o r
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Format and print an error message, then punt.
|
|
|
|
*
|
|
|
|
**************************************/
|
2007-03-28 06:20:36 +02:00
|
|
|
|
|
|
|
BURP_error(errcode, abort, SafeArg() << str);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-09-25 13:49:12 +02:00
|
|
|
void BURP_error_redirect(const ISC_STATUS* status_vector,
|
2001-05-23 15:26:42 +02:00
|
|
|
USHORT errcode,
|
2007-03-28 06:20:36 +02:00
|
|
|
const SafeArg& arg)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* B U R P _ e r r o r _ r e d i r e c t
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Issue error message. Output messages then abort.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
2008-04-04 11:42:42 +02:00
|
|
|
BURP_print_status(status_vector, true);
|
2007-03-28 06:20:36 +02:00
|
|
|
BURP_error(errcode, true, arg);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-01-13 10:52:19 +01:00
|
|
|
// Raises an exception when the old SEH system would jump to another place.
|
2004-07-03 02:13:46 +02:00
|
|
|
void BURP_exit_local(int code, BurpGlobals* tdgbl)
|
2004-01-13 10:52:19 +01:00
|
|
|
{
|
2004-03-01 05:57:43 +01:00
|
|
|
tdgbl->exit_code = code;
|
2006-02-23 06:08:26 +01:00
|
|
|
if (tdgbl->burp_throw)
|
2006-05-19 17:17:02 +02:00
|
|
|
throw Firebird::LongJump();
|
2004-01-13 10:52:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
void BURP_msg_partial( USHORT number,
|
2007-03-28 06:20:36 +02:00
|
|
|
const SafeArg& arg)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* B U R P _ m s g _ p a r t i a l
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
2001-07-10 19:35:13 +02:00
|
|
|
* Retrieve a message from the error file,
|
2001-05-23 15:26:42 +02:00
|
|
|
* format it, and print it without a newline.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
TEXT buffer[256];
|
|
|
|
|
2007-03-28 06:20:36 +02:00
|
|
|
fb_msg_format(NULL, burp_msg_fac, number, sizeof(buffer), buffer, arg);
|
2001-05-23 15:26:42 +02:00
|
|
|
burp_output("%s", buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void BURP_msg_put( USHORT number,
|
2007-03-28 06:20:36 +02:00
|
|
|
const SafeArg& arg)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* B U R P _ m s g _ p u t
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Retrieve a message from the error file, format it, and print it.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
TEXT buffer[256];
|
|
|
|
|
2007-03-28 06:20:36 +02:00
|
|
|
fb_msg_format(NULL, burp_msg_fac, number, sizeof(buffer), buffer, arg);
|
2001-05-23 15:26:42 +02:00
|
|
|
burp_output("%s\n", buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void BURP_msg_get( USHORT number,
|
2003-09-12 11:04:38 +02:00
|
|
|
TEXT* output_msg,
|
2007-03-28 06:20:36 +02:00
|
|
|
const SafeArg& arg)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* B U R P _ m s g _ g e t
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Retrieve a message from the error file, format it and copy it to the buffer
|
|
|
|
*
|
|
|
|
**************************************/
|
2004-10-30 07:41:25 +02:00
|
|
|
TEXT buffer[BURP_MSG_GET_SIZE];
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2007-03-28 06:20:36 +02:00
|
|
|
fb_msg_format(NULL, burp_msg_fac, number, sizeof(buffer), buffer, arg);
|
2003-09-12 11:04:38 +02:00
|
|
|
strcpy(output_msg, buffer);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-12-22 11:00:59 +01:00
|
|
|
void BURP_output_version(void* arg1, const TEXT* arg2)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* B U R P _ o u t p u t _ v e r s i o n
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Callback routine for access method
|
|
|
|
* printing (specifically show version);
|
|
|
|
* will accept.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
2004-10-18 09:17:48 +02:00
|
|
|
burp_output(static_cast<const char*>(arg1), arg2);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void BURP_print(USHORT number,
|
2007-03-28 06:20:36 +02:00
|
|
|
const SafeArg& arg)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* B U R P _ p r i n t
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Display a formatted error message
|
|
|
|
* in a way that VMS or civilized systems
|
|
|
|
* will accept.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
2007-03-28 06:20:36 +02:00
|
|
|
BURP_msg_partial(169); // msg 169: gbak:
|
|
|
|
BURP_msg_put(number, arg);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void BURP_print(USHORT number,
|
|
|
|
const char* str)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* B U R P _ p r i n t
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Display a formatted error message
|
|
|
|
* in a way that VMS or civilized systems
|
|
|
|
* will accept.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
|
|
|
static const SafeArg dummy;
|
|
|
|
BURP_msg_partial(169, dummy); // msg 169: gbak:
|
|
|
|
BURP_msg_put(number, SafeArg() << str);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-04-04 11:42:42 +02:00
|
|
|
void BURP_print_status(const ISC_STATUS* status_vector, bool flagStuff)
|
2003-09-12 11:04:38 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* B U R P _ p r i n t _ s t a t u s
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
2004-11-28 02:03:05 +01:00
|
|
|
* Print error message. Use fb_interpret
|
2003-09-12 11:04:38 +02:00
|
|
|
* to allow redirecting output.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
if (status_vector) {
|
2003-12-22 11:00:59 +01:00
|
|
|
const ISC_STATUS* vector = status_vector;
|
2008-01-16 07:11:50 +01:00
|
|
|
|
2008-04-04 11:42:42 +02:00
|
|
|
if (flagStuff) {
|
|
|
|
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
|
2008-09-11 13:51:25 +02:00
|
|
|
tdgbl->uSvc->setServiceStatus(vector);
|
2008-04-04 11:42:42 +02:00
|
|
|
}
|
2003-09-12 11:04:38 +02:00
|
|
|
|
|
|
|
SCHAR s[1024];
|
2004-11-28 02:03:05 +01:00
|
|
|
if (fb_interpret(s, sizeof(s), &vector)) {
|
2007-03-28 06:20:36 +02:00
|
|
|
BURP_msg_partial(256); // msg 256: gbak: ERROR:
|
2003-09-12 11:04:38 +02:00
|
|
|
burp_output("%s\n", s);
|
2004-11-28 02:03:05 +01:00
|
|
|
while (fb_interpret(s, sizeof(s), &vector)) {
|
2007-03-28 06:20:36 +02:00
|
|
|
BURP_msg_partial(256); // msg 256: gbak: ERROR:
|
2003-09-12 11:04:38 +02:00
|
|
|
burp_output(" %s\n", s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-09-25 13:49:12 +02:00
|
|
|
void BURP_print_warning(const ISC_STATUS* status_vector)
|
2003-09-12 11:04:38 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* B U R P _ p r i n t _ w a r n i n g
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
2004-11-28 02:03:05 +01:00
|
|
|
* Print warning message. Use fb_interpret
|
2003-09-12 11:04:38 +02:00
|
|
|
* to allow redirecting output.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
if (status_vector) {
|
2008-12-01 10:21:31 +01:00
|
|
|
// skip the error, assert that one does not exist
|
2003-11-08 00:15:33 +01:00
|
|
|
fb_assert(status_vector[0] == isc_arg_gds);
|
2003-11-04 00:59:24 +01:00
|
|
|
fb_assert(status_vector[1] == 0);
|
2008-12-01 10:21:31 +01:00
|
|
|
// print the warning message
|
2003-09-25 13:49:12 +02:00
|
|
|
const ISC_STATUS* vector = &status_vector[2];
|
2003-09-12 11:04:38 +02:00
|
|
|
SCHAR s[1024];
|
2004-11-28 02:03:05 +01:00
|
|
|
if (fb_interpret(s, sizeof(s), &vector)) {
|
2007-03-28 06:20:36 +02:00
|
|
|
BURP_msg_partial(255); // msg 255: gbak: WARNING:
|
2003-09-12 11:04:38 +02:00
|
|
|
burp_output("%s\n", s);
|
2004-11-28 02:03:05 +01:00
|
|
|
while (fb_interpret(s, sizeof(s), &vector)) {
|
2007-03-28 06:20:36 +02:00
|
|
|
BURP_msg_partial(255); // msg 255: gbak: WARNING:
|
2003-09-12 11:04:38 +02:00
|
|
|
burp_output(" %s\n", s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
void BURP_verbose(USHORT number,
|
2007-03-28 06:20:36 +02:00
|
|
|
const SafeArg& arg)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* B U R P _ v e r b o s e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Calls BURP_print for displaying a formatted error message
|
|
|
|
* but only for verbose output. If not verbose then calls
|
|
|
|
* user defined yieding function.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
|
|
|
|
|
|
|
|
if (tdgbl->gbl_sw_verbose)
|
|
|
|
BURP_print(number, arg);
|
|
|
|
else
|
|
|
|
burp_output("%s", "");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void BURP_verbose(USHORT number,
|
|
|
|
const char* str)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* B U R P _ v e r b o s e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Calls BURP_print for displaying a formatted error message
|
|
|
|
* but only for verbose output. If not verbose then calls
|
|
|
|
* user defined yieding function.
|
|
|
|
*
|
|
|
|
**************************************/
|
2004-07-03 02:13:46 +02:00
|
|
|
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (tdgbl->gbl_sw_verbose)
|
2007-03-28 06:20:36 +02:00
|
|
|
BURP_print(number, str);
|
2001-05-23 15:26:42 +02:00
|
|
|
else
|
2004-06-29 06:37:59 +02:00
|
|
|
burp_output("%s", "");
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2003-09-12 11:04:38 +02:00
|
|
|
|
2004-03-11 06:44:32 +01:00
|
|
|
static void close_out_transaction(gbak_action action,
|
2001-05-23 15:26:42 +02:00
|
|
|
isc_tr_handle* handle)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* c l o s e _ o u t _ t r a n s a c t i o n
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Make a transaction go away. This is
|
|
|
|
* important as we need to detach from the
|
|
|
|
* database so all engine allocated memory is
|
|
|
|
* returned to the system.
|
|
|
|
*
|
|
|
|
**************************************/
|
2003-04-16 12:18:51 +02:00
|
|
|
ISC_STATUS_ARRAY status_vector;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (*handle != 0) {
|
|
|
|
if (action == RESTORE) {
|
|
|
|
/* Even if the restore failed, commit the transaction so that
|
|
|
|
* a partial database is at least recovered.
|
|
|
|
*/
|
|
|
|
isc_commit_transaction(status_vector, handle);
|
|
|
|
if (status_vector[1]) {
|
|
|
|
/* If we can't commit - have to roll it back, as
|
|
|
|
* we need to close all outstanding transactions before
|
|
|
|
* we can detach from the database.
|
|
|
|
*/
|
|
|
|
isc_rollback_transaction(status_vector, handle);
|
|
|
|
if (status_vector[1])
|
|
|
|
BURP_print_status(status_vector);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2001-07-10 19:35:13 +02:00
|
|
|
/* A backup shouldn't touch any data - we ensure that
|
2001-05-23 15:26:42 +02:00
|
|
|
* by never writing data during a backup, but let's double
|
|
|
|
* ensure it by doing a rollback
|
|
|
|
*/
|
|
|
|
if (isc_rollback_transaction(status_vector, handle))
|
|
|
|
BURP_print_status(status_vector);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-12-22 11:00:59 +01:00
|
|
|
static SLONG get_number( const SCHAR* string)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g e t _ n u m b e r
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Convert a string to binary, complaining bitterly if
|
|
|
|
* the string is bum.
|
2003-09-12 11:04:38 +02:00
|
|
|
* CVC: where does it complain? It does return zero, nothing else.
|
2001-05-23 15:26:42 +02:00
|
|
|
**************************************/
|
2003-09-12 11:04:38 +02:00
|
|
|
SCHAR c;
|
|
|
|
SLONG value = 0;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-12-22 11:00:59 +01:00
|
|
|
for (const SCHAR* p = string; c = *p++;) {
|
2001-05-23 15:26:42 +02:00
|
|
|
if (c < '0' || c > '9')
|
|
|
|
return 0;
|
|
|
|
value *= 10;
|
|
|
|
value += c - '0';
|
|
|
|
}
|
|
|
|
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-29 11:53:47 +01:00
|
|
|
static gbak_action open_files(const TEXT* file1,
|
|
|
|
const TEXT** file2,
|
2004-01-13 10:52:19 +01:00
|
|
|
bool sw_verbose,
|
2004-12-09 20:19:47 +01:00
|
|
|
USHORT sw_replace,
|
|
|
|
const Firebird::ClumpletWriter& dpb)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* o p e n _ f i l e s
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* from the input file names and
|
|
|
|
* positions, guess what the users
|
|
|
|
* intention was. Return the type
|
|
|
|
* of the first file, plus open file
|
|
|
|
* and db handle.
|
|
|
|
*
|
|
|
|
**************************************/
|
2004-07-03 02:13:46 +02:00
|
|
|
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
|
2005-05-14 15:45:01 +02:00
|
|
|
ISC_STATUS_ARRAY temp_status;
|
|
|
|
ISC_STATUS* status_vector = temp_status;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
// try to attach the database using the first file_name
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (sw_replace != IN_SW_BURP_C && sw_replace != IN_SW_BURP_R)
|
2008-06-03 08:14:59 +02:00
|
|
|
{
|
|
|
|
if (!isc_attach_database(status_vector,
|
2001-05-23 15:26:42 +02:00
|
|
|
(SSHORT) 0,
|
2003-10-29 11:53:47 +01:00
|
|
|
file1,
|
2001-05-23 15:26:42 +02:00
|
|
|
&tdgbl->db_handle,
|
2004-12-09 20:19:47 +01:00
|
|
|
dpb.getBufferLength(),
|
2008-06-03 08:14:59 +02:00
|
|
|
reinterpret_cast<const char*>(dpb.getBuffer())))
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
if (sw_replace != IN_SW_BURP_B) {
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 13 REPLACE specified, but the first file %s is a database
|
2007-03-28 06:20:36 +02:00
|
|
|
BURP_error(13, true, file1);
|
2001-05-23 15:26:42 +02:00
|
|
|
if (isc_detach_database(status_vector, &tdgbl->db_handle)) {
|
2008-04-04 11:42:42 +02:00
|
|
|
BURP_print_status(status_vector, true);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
return QUIT;
|
|
|
|
}
|
|
|
|
if (tdgbl->gbl_sw_version) {
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 139 Version(s) for database "%s"
|
2007-03-28 06:20:36 +02:00
|
|
|
BURP_print(139, file1);
|
2003-12-27 18:59:59 +01:00
|
|
|
isc_version(&tdgbl->db_handle, BURP_output_version, (void*) "\t%s\n");
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
if (sw_verbose)
|
2007-03-28 06:20:36 +02:00
|
|
|
BURP_print(166, file1);
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 166: readied database %s for backup
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
else if (sw_replace == IN_SW_BURP_B ||
|
2008-12-31 06:06:08 +01:00
|
|
|
(status_vector[1] != isc_io_error && status_vector[1] != isc_bad_db_format))
|
2004-12-24 09:52:39 +01:00
|
|
|
{
|
2008-04-04 11:42:42 +02:00
|
|
|
BURP_print_status(status_vector, true);
|
2001-05-23 15:26:42 +02:00
|
|
|
return QUIT;
|
|
|
|
}
|
2008-06-03 08:14:59 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-01-13 10:52:19 +01:00
|
|
|
burp_fil* fil = 0;
|
2001-05-23 15:26:42 +02:00
|
|
|
if (sw_replace == IN_SW_BURP_B) {
|
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
// Now it is safe to skip a db file
|
2001-05-23 15:26:42 +02:00
|
|
|
tdgbl->gbl_sw_backup_files = tdgbl->gbl_sw_files->fil_next;
|
|
|
|
tdgbl->gbl_sw_files = tdgbl->gbl_sw_files->fil_next;
|
2008-01-16 07:11:50 +01:00
|
|
|
fb_assert(tdgbl->gbl_sw_files->fil_name == *file2);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-09-12 11:04:38 +02:00
|
|
|
gbak_action flag = BACKUP;
|
2001-05-23 15:26:42 +02:00
|
|
|
tdgbl->action->act_action = ACT_backup;
|
|
|
|
for (fil = tdgbl->gbl_sw_files; fil; fil = fil->fil_next)
|
|
|
|
{
|
2008-12-01 10:21:31 +01:00
|
|
|
// adjust the file size first
|
2001-05-23 15:26:42 +02:00
|
|
|
switch (fil->fil_size_code)
|
|
|
|
{
|
|
|
|
case size_n:
|
|
|
|
break;
|
|
|
|
case size_k:
|
|
|
|
fil->fil_length *= KBYTE;
|
|
|
|
break;
|
|
|
|
case size_m:
|
|
|
|
fil->fil_length *= MBYTE;
|
|
|
|
break;
|
|
|
|
case size_g:
|
|
|
|
fil->fil_length *= GBYTE;
|
|
|
|
break;
|
|
|
|
case size_e:
|
2008-01-16 07:11:50 +01:00
|
|
|
BURP_error(262, true, fil->fil_name.c_str());
|
2003-09-12 11:04:38 +02:00
|
|
|
// msg 262 size specification either missing or incorrect for file %s
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
default:
|
2003-11-04 00:59:24 +01:00
|
|
|
fb_assert(FALSE);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2004-12-26 05:09:06 +01:00
|
|
|
if ((fil->fil_seq = ++tdgbl->action->act_total) >= 2)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
tdgbl->action->act_action = ACT_backup_split;
|
|
|
|
}
|
|
|
|
if (sw_verbose)
|
|
|
|
{
|
2008-01-16 07:11:50 +01:00
|
|
|
BURP_print(75, fil->fil_name.c_str()); // msg 75 creating file %s
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2008-01-16 07:11:50 +01:00
|
|
|
if (fil->fil_name == "stdout")
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
if (tdgbl->action->act_total >= 2 || fil->fil_next)
|
|
|
|
{
|
2007-03-28 06:20:36 +02:00
|
|
|
BURP_error(266, true);
|
2003-09-12 11:04:38 +02:00
|
|
|
// msg 266 standard output is not supported when using split operation
|
2001-05-23 15:26:42 +02:00
|
|
|
flag = QUIT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* We ignore SIGPIPE so that we can report an IO error when we
|
|
|
|
* try to write to the broken pipe.
|
|
|
|
*/
|
|
|
|
#ifndef WIN_NT
|
|
|
|
signal(SIGPIPE, SIG_IGN);
|
|
|
|
#endif
|
2006-01-09 20:57:32 +01:00
|
|
|
fil->fil_fd = GBAK_STDOUT_DESC();
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
|
|
|
|
#ifdef WIN_NT
|
2008-01-16 07:11:50 +01:00
|
|
|
if ((fil->fil_fd = MVOL_open(fil->fil_name.c_str(), MODE_WRITE,
|
2001-05-23 15:26:42 +02:00
|
|
|
CREATE_ALWAYS)) == INVALID_HANDLE_VALUE)
|
|
|
|
#else
|
2008-01-16 07:11:50 +01:00
|
|
|
if ((fil->fil_fd = open(fil->fil_name.c_str(), MODE_WRITE, open_mask)) == -1)
|
2008-12-01 10:21:31 +01:00
|
|
|
#endif // WIN_NT
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
{
|
|
|
|
|
2008-01-16 07:11:50 +01:00
|
|
|
BURP_error(65, false, fil->fil_name.c_str());
|
2003-09-12 11:04:38 +02:00
|
|
|
// msg 65 can't open backup file %s
|
2001-05-23 15:26:42 +02:00
|
|
|
flag = QUIT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fil->fil_length == 0)
|
|
|
|
{
|
|
|
|
if (fil->fil_next)
|
|
|
|
{
|
2008-01-16 07:11:50 +01:00
|
|
|
BURP_error(262, true, fil->fil_name.c_str());
|
2003-09-12 11:04:38 +02:00
|
|
|
// msg 262 size specification either missing or incorrect for file %s
|
2001-05-23 15:26:42 +02:00
|
|
|
flag = QUIT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2003-09-12 11:04:38 +02:00
|
|
|
fil->fil_length = MAX_LENGTH;
|
|
|
|
// Write as much as possible to the last file
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (fil->fil_length < MIN_SPLIT_SIZE)
|
|
|
|
{
|
2007-03-28 06:20:36 +02:00
|
|
|
BURP_error(271, true, SafeArg() << fil->fil_length << MIN_SPLIT_SIZE);
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg file size given (%d) is less than minimum allowed (%d)
|
2001-05-23 15:26:42 +02:00
|
|
|
flag = QUIT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flag == BACKUP)
|
|
|
|
{
|
|
|
|
tdgbl->action->act_file = tdgbl->gbl_sw_files;
|
|
|
|
tdgbl->file_desc = tdgbl->gbl_sw_files->fil_fd;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (isc_detach_database(status_vector, &tdgbl->db_handle))
|
|
|
|
{
|
|
|
|
BURP_print_status(status_vector);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return flag;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If we got to here, then we're really not backing up a database,
|
|
|
|
* so open a backup file.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* There are four possible cases such as:
|
|
|
|
*
|
|
|
|
* 1. restore single backup file to single db file
|
|
|
|
* 2. restore single backup file to multiple db files
|
|
|
|
* 3. restore multiple backup files (join operation) to single db file
|
|
|
|
* 4. restore multiple backup files (join operation) to multiple db files
|
|
|
|
*
|
|
|
|
* Just looking at the command line, we can't say for sure whether it is a
|
|
|
|
* specification of the last file to be join or it is a specification of the
|
|
|
|
* primary db file (case 4), for example:
|
|
|
|
*
|
|
|
|
* gbak -c gbk1 gbk2 gbk3 db1 200 db2 500 db3 -v
|
|
|
|
* ^^^
|
|
|
|
* db1 could be either the last file to be join or primary db file
|
|
|
|
*
|
|
|
|
* Since 'gbk' and 'gsplit' formats are different (gsplit file has its own
|
|
|
|
* header record) hence we can use it as follows:
|
|
|
|
*
|
|
|
|
* - open first file
|
|
|
|
* - read & check a header record
|
|
|
|
*
|
|
|
|
* If a header is identified as a 'gsplit' one then we know exactly how
|
|
|
|
* many files need to be join and in which order. We keep opening a file by
|
|
|
|
* file till we reach the last one to be join. During this step we check
|
|
|
|
* that the files are accessible and are in proper order. It gives us
|
|
|
|
* possibility to let silly customer know about an error as soon as possible.
|
|
|
|
* Besides we have to find out which file is going to be a db file.
|
|
|
|
*
|
|
|
|
* If header is not identified as a 'gsplit' record then we assume that
|
|
|
|
* we got a single backup file.
|
|
|
|
*/
|
|
|
|
|
|
|
|
fil = tdgbl->gbl_sw_files;
|
|
|
|
tdgbl->gbl_sw_backup_files = tdgbl->gbl_sw_files;
|
|
|
|
|
|
|
|
tdgbl->action->act_action = ACT_restore;
|
2008-12-01 10:21:31 +01:00
|
|
|
if (fil->fil_name == "stdin")
|
2008-01-16 07:11:50 +01:00
|
|
|
{
|
2006-01-09 20:57:32 +01:00
|
|
|
fil->fil_fd = GBAK_STDIN_DESC();
|
2001-05-23 15:26:42 +02:00
|
|
|
tdgbl->file_desc = fil->fil_fd;
|
|
|
|
tdgbl->gbl_sw_files = fil->fil_next;
|
|
|
|
}
|
2008-12-01 10:21:31 +01:00
|
|
|
else
|
2008-01-16 07:11:50 +01:00
|
|
|
{
|
2008-12-01 10:21:31 +01:00
|
|
|
// open first file
|
2001-05-23 15:26:42 +02:00
|
|
|
#ifdef WIN_NT
|
2008-01-16 07:11:50 +01:00
|
|
|
if ((fil->fil_fd = MVOL_open(fil->fil_name.c_str(), MODE_READ, OPEN_EXISTING))
|
2001-05-23 15:26:42 +02:00
|
|
|
== INVALID_HANDLE_VALUE)
|
|
|
|
#else
|
2008-01-16 07:11:50 +01:00
|
|
|
if ((fil->fil_fd = open(fil->fil_name.c_str(), MODE_READ)) ==
|
2001-05-23 15:26:42 +02:00
|
|
|
INVALID_HANDLE_VALUE)
|
|
|
|
#endif
|
|
|
|
{
|
2008-01-16 07:11:50 +01:00
|
|
|
BURP_error(65, true, fil->fil_name.c_str());
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 65 can't open backup file %s
|
2001-05-23 15:26:42 +02:00
|
|
|
return QUIT;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sw_verbose)
|
2008-01-16 07:11:50 +01:00
|
|
|
{
|
|
|
|
BURP_print(100, fil->fil_name.c_str());
|
2003-11-03 02:12:14 +01:00
|
|
|
// msg 100 opened file %s
|
2008-01-16 07:11:50 +01:00
|
|
|
}
|
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
// read and check a header record
|
2001-05-23 15:26:42 +02:00
|
|
|
tdgbl->action->act_file = fil;
|
2003-09-12 11:04:38 +02:00
|
|
|
int seq = 1;
|
2009-01-02 10:48:57 +01:00
|
|
|
if (MVOL_split_hdr_read())
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
tdgbl->action->act_action = ACT_restore_join;
|
2008-12-01 10:21:31 +01:00
|
|
|
// number of files to be join
|
2004-10-30 07:41:25 +02:00
|
|
|
const int total = tdgbl->action->act_total;
|
2008-12-01 10:21:31 +01:00
|
|
|
if (fil->fil_seq != seq || seq > total)
|
2008-01-16 07:11:50 +01:00
|
|
|
{
|
|
|
|
BURP_error(263, true, fil->fil_name.c_str());
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 263 file %s out of sequence
|
2001-05-23 15:26:42 +02:00
|
|
|
return QUIT;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (++seq, fil = fil->fil_next; seq <= total;
|
2003-09-12 11:04:38 +02:00
|
|
|
fil = fil->fil_next, seq++)
|
|
|
|
{
|
2008-12-01 10:21:31 +01:00
|
|
|
if (!fil)
|
2008-01-16 07:11:50 +01:00
|
|
|
{
|
2007-03-28 06:20:36 +02:00
|
|
|
BURP_error(264, true);
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 264 can't join -- one of the files missing
|
2001-05-23 15:26:42 +02:00
|
|
|
return QUIT;
|
|
|
|
}
|
2008-12-01 10:21:31 +01:00
|
|
|
if (fil->fil_name == "stdin")
|
2008-01-16 07:11:50 +01:00
|
|
|
{
|
2007-03-28 06:20:36 +02:00
|
|
|
BURP_error(265, true);
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 265 standard input is not supported when using join operation
|
2001-05-23 15:26:42 +02:00
|
|
|
return QUIT;
|
|
|
|
}
|
|
|
|
tdgbl->action->act_file = fil;
|
|
|
|
#ifdef WIN_NT
|
2008-01-16 07:11:50 +01:00
|
|
|
if ((fil->fil_fd = MVOL_open(fil->fil_name.c_str(), MODE_READ,
|
2001-05-23 15:26:42 +02:00
|
|
|
OPEN_EXISTING)) ==
|
|
|
|
INVALID_HANDLE_VALUE)
|
|
|
|
#else
|
2008-01-16 07:11:50 +01:00
|
|
|
if ((fil->fil_fd = open(fil->fil_name.c_str(), MODE_READ))
|
2001-05-23 15:26:42 +02:00
|
|
|
== INVALID_HANDLE_VALUE)
|
|
|
|
#endif
|
|
|
|
{
|
2008-01-16 07:11:50 +01:00
|
|
|
BURP_error(65, false, fil->fil_name.c_str());
|
2003-11-03 02:12:14 +01:00
|
|
|
// msg 65 can't open backup file %s
|
2001-05-23 15:26:42 +02:00
|
|
|
return QUIT;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sw_verbose)
|
2008-01-16 07:11:50 +01:00
|
|
|
{
|
|
|
|
BURP_print(100, fil->fil_name.c_str());
|
2003-11-03 02:12:14 +01:00
|
|
|
// msg 100 opened file %s
|
2008-01-16 07:11:50 +01:00
|
|
|
}
|
2009-01-02 10:48:57 +01:00
|
|
|
if (MVOL_split_hdr_read())
|
2008-01-16 07:11:50 +01:00
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
if ((total != tdgbl->action->act_total) ||
|
2003-11-03 02:12:14 +01:00
|
|
|
(seq != fil->fil_seq) || (seq > total))
|
|
|
|
{
|
2008-01-16 07:11:50 +01:00
|
|
|
BURP_error(263, true, fil->fil_name.c_str());
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 263 file %s out of sequence
|
2001-05-23 15:26:42 +02:00
|
|
|
return QUIT;
|
|
|
|
}
|
|
|
|
}
|
2008-12-01 10:21:31 +01:00
|
|
|
else
|
2008-01-16 07:11:50 +01:00
|
|
|
{
|
|
|
|
BURP_error(267, true, fil->fil_name.c_str());
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 267 backup file %s might be corrupt
|
2001-05-23 15:26:42 +02:00
|
|
|
return QUIT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
tdgbl->action->act_file = tdgbl->gbl_sw_files;
|
|
|
|
tdgbl->file_desc = tdgbl->action->act_file->fil_fd;
|
|
|
|
if ((tdgbl->gbl_sw_files = fil) == NULL) {
|
2007-03-28 06:20:36 +02:00
|
|
|
BURP_error(268, true);
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 268 database file specification missing
|
2001-05-23 15:26:42 +02:00
|
|
|
return QUIT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2003-11-03 02:12:14 +01:00
|
|
|
// Move pointer to the begining of the file. At this point we
|
|
|
|
// assume -- this is a single backup file because we were
|
|
|
|
// not able to read a split header record.
|
2001-05-23 15:26:42 +02:00
|
|
|
#ifdef WIN_NT
|
2008-01-16 07:11:50 +01:00
|
|
|
if (strnicmp(fil->fil_name.c_str(), "\\\\.\\tape", 8))
|
2001-05-23 15:26:42 +02:00
|
|
|
SetFilePointer(fil->fil_fd, 0, NULL, FILE_BEGIN);
|
|
|
|
else
|
|
|
|
SetTapePosition(fil->fil_fd, TAPE_REWIND, 0, 0, 0, FALSE);
|
|
|
|
#else
|
|
|
|
lseek(fil->fil_fd, 0, SEEK_SET);
|
|
|
|
#endif
|
|
|
|
tdgbl->file_desc = fil->fil_fd;
|
|
|
|
tdgbl->gbl_sw_files = fil->fil_next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-11-03 02:12:14 +01:00
|
|
|
// If we got here, we've opened a backup file, and we're
|
|
|
|
// thinking about creating or replacing a database.
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-16 07:11:50 +01:00
|
|
|
*file2 = tdgbl->gbl_sw_files->fil_name.c_str();
|
2001-05-23 15:26:42 +02:00
|
|
|
if (tdgbl->gbl_sw_files->fil_size_code != size_n)
|
2007-03-28 06:20:36 +02:00
|
|
|
BURP_error(262, true, *file2);
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 262 size specification either missing or incorrect for file %s
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if ((sw_replace == IN_SW_BURP_C || sw_replace == IN_SW_BURP_R) &&
|
|
|
|
!isc_attach_database(status_vector,
|
|
|
|
(SSHORT) 0,
|
|
|
|
*file2,
|
|
|
|
&tdgbl->db_handle,
|
2004-12-09 20:19:47 +01:00
|
|
|
dpb.getBufferLength(),
|
|
|
|
reinterpret_cast<const char*>(dpb.getBuffer())))
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
if (sw_replace == IN_SW_BURP_C) {
|
|
|
|
if (isc_detach_database(status_vector, &tdgbl->db_handle)) {
|
2008-04-04 11:42:42 +02:00
|
|
|
BURP_print_status(status_vector, true);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2007-03-28 06:20:36 +02:00
|
|
|
BURP_error(14, true, *file2);
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 14 database %s already exists. To replace it, use the -R switch
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2005-04-18 05:24:34 +02:00
|
|
|
else {
|
2001-05-23 15:26:42 +02:00
|
|
|
isc_drop_database(status_vector, &tdgbl->db_handle);
|
|
|
|
if (tdgbl->db_handle) {
|
2008-09-05 13:41:00 +02:00
|
|
|
tdgbl->uSvc->makePermanentVector(status_vector);
|
2003-04-16 12:18:51 +02:00
|
|
|
ISC_STATUS_ARRAY status_vector2;
|
2001-05-23 15:26:42 +02:00
|
|
|
if (isc_detach_database(status_vector2, &tdgbl->db_handle)) {
|
|
|
|
BURP_print_status(status_vector2);
|
|
|
|
}
|
|
|
|
|
2005-04-09 20:44:50 +02:00
|
|
|
// Complain only if the drop database entrypoint is available.
|
2008-12-01 10:21:31 +01:00
|
|
|
// If it isn't, the database will simply be overwritten.
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-08 00:15:33 +01:00
|
|
|
if (status_vector[1] != isc_unavailable)
|
2007-03-28 06:20:36 +02:00
|
|
|
BURP_error(233, true, *file2);
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 233 Cannot drop database %s, might be in use
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (sw_replace == IN_SW_BURP_R && status_vector[1] == isc_adm_task_denied) {
|
|
|
|
/* if we got an error from attach database and we have replace switch set
|
|
|
|
* then look for error from attach returned due to not owner, if we are
|
2001-07-10 19:35:13 +02:00
|
|
|
* not owner then return the error status back up
|
2001-05-23 15:26:42 +02:00
|
|
|
*/
|
2007-03-28 06:20:36 +02:00
|
|
|
BURP_error(274, true);
|
2001-05-23 15:26:42 +02:00
|
|
|
/* msg # 274 : Cannot restore over current database, must be sysdba
|
2001-07-10 19:35:13 +02:00
|
|
|
* or owner of the existing database.
|
2001-05-23 15:26:42 +02:00
|
|
|
*/
|
|
|
|
}
|
|
|
|
/* if we got here, then all is well, remove any error condition from the
|
|
|
|
* status vector when running as a service thread. If we don't then the
|
|
|
|
* service will think that there is an error if isc_attach_database failed
|
|
|
|
* like it should have (if creating a database).
|
|
|
|
*/
|
2008-01-16 07:11:50 +01:00
|
|
|
if (tdgbl->uSvc->isService())
|
2006-06-16 10:13:20 +02:00
|
|
|
memset(tdgbl->status, 0, sizeof(ISC_STATUS_ARRAY));
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
// check the file size specification
|
|
|
|
for (fil = tdgbl->gbl_sw_files; fil; fil = fil->fil_next)
|
2008-01-16 07:11:50 +01:00
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
if (fil->fil_size_code != size_n)
|
2008-01-16 07:11:50 +01:00
|
|
|
{
|
|
|
|
BURP_error(262, true, fil->fil_name.c_str());
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 262 size specification either missing or incorrect for file %s
|
2008-01-16 07:11:50 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return RESTORE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-29 11:53:47 +01:00
|
|
|
static void burp_output( const SCHAR* format, ...)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* b u r p _ o u t p u t
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Platform independent output routine.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
va_list arglist;
|
|
|
|
|
2004-07-03 02:13:46 +02:00
|
|
|
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-12-01 10:21:31 +01:00
|
|
|
if (tdgbl->sw_redirect == NOOUTPUT || format[0] == '\0')
|
2008-01-16 07:11:50 +01:00
|
|
|
{
|
|
|
|
tdgbl->uSvc->output("");
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2008-12-01 10:21:31 +01:00
|
|
|
else if (tdgbl->sw_redirect == REDIRECT && tdgbl->output_file != NULL)
|
2008-01-16 07:11:50 +01:00
|
|
|
{
|
2004-05-24 01:28:06 +02:00
|
|
|
va_start(arglist, format);
|
2004-04-29 00:00:03 +02:00
|
|
|
vfprintf(tdgbl->output_file, format, arglist);
|
2001-05-23 15:26:42 +02:00
|
|
|
va_end(arglist);
|
2008-01-16 07:11:50 +01:00
|
|
|
tdgbl->uSvc->output("");
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2008-12-01 10:21:31 +01:00
|
|
|
else
|
2008-01-16 07:11:50 +01:00
|
|
|
{
|
2004-05-24 01:28:06 +02:00
|
|
|
va_start(arglist, format);
|
2008-01-16 07:11:50 +01:00
|
|
|
Firebird::string buf;
|
|
|
|
buf.vprintf(format, arglist);
|
2001-05-23 15:26:42 +02:00
|
|
|
va_end(arglist);
|
2008-01-16 07:11:50 +01:00
|
|
|
tdgbl->uSvc->output(buf.c_str());
|
2008-01-19 14:30:46 +01:00
|
|
|
fflush(stdout);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-05-23 15:05:35 +02:00
|
|
|
static void burp_usage(const in_sw_tab_t* in_sw_tab)
|
2005-04-09 20:44:50 +02:00
|
|
|
{
|
|
|
|
/**********************************************
|
|
|
|
*
|
|
|
|
* b u r p _ u s a g e
|
|
|
|
*
|
|
|
|
**********************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* print usage information
|
|
|
|
*
|
|
|
|
**********************************************/
|
2007-03-28 06:20:36 +02:00
|
|
|
BURP_print(95);
|
2005-04-09 20:44:50 +02:00
|
|
|
// msg 95 legal switches are
|
|
|
|
|
2007-03-28 06:20:36 +02:00
|
|
|
SafeArg sa;
|
2008-05-23 15:27:47 +02:00
|
|
|
sa << switch_char;
|
2008-12-01 10:21:31 +01:00
|
|
|
|
2005-04-09 20:44:50 +02:00
|
|
|
for (; in_sw_tab->in_sw; in_sw_tab++)
|
2008-05-23 15:27:47 +02:00
|
|
|
{
|
|
|
|
if (in_sw_tab->in_sw_msg)
|
|
|
|
BURP_msg_put(in_sw_tab->in_sw_msg, sa);
|
|
|
|
}
|
2005-04-09 20:44:50 +02:00
|
|
|
|
2007-03-28 06:20:36 +02:00
|
|
|
BURP_print(132);
|
2008-12-01 10:21:31 +01:00
|
|
|
// msg 132 switches can be abbreviated to one character
|
2005-04-09 20:44:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-01-13 10:52:19 +01:00
|
|
|
static ULONG get_size( const SCHAR* string, burp_fil* file)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**********************************************
|
|
|
|
*
|
|
|
|
* g e t _ s i z e
|
|
|
|
*
|
|
|
|
**********************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Get size specification for either splitting or
|
|
|
|
* restoring to multiple files
|
|
|
|
*
|
|
|
|
**********************************************/
|
2003-09-12 11:04:38 +02:00
|
|
|
SCHAR c;
|
|
|
|
ULONG size = 0;
|
|
|
|
bool digit = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
file->fil_size_code = size_n;
|
2003-09-12 11:04:38 +02:00
|
|
|
for (const SCHAR *num = string; c = *num++;) {
|
2001-05-23 15:26:42 +02:00
|
|
|
if (isdigit(c)) {
|
|
|
|
size = size * 10 + (c - '0');
|
2003-09-10 19:52:12 +02:00
|
|
|
digit = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (isalpha(c)) {
|
|
|
|
if (!digit) {
|
|
|
|
file->fil_size_code = size_e;
|
|
|
|
size = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
switch (UPPER(c)) {
|
|
|
|
case 'K':
|
|
|
|
file->fil_size_code = size_k;
|
|
|
|
break;
|
|
|
|
case 'M':
|
|
|
|
file->fil_size_code = size_m;
|
|
|
|
break;
|
|
|
|
case 'G':
|
|
|
|
file->fil_size_code = size_g;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
file->fil_size_code = size_e;
|
|
|
|
size = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (*num) {
|
|
|
|
file->fil_size_code = size_e;
|
|
|
|
size = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-09-12 11:04:38 +02:00
|
|
|
file->fil_length = size;
|
|
|
|
return (size);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|