/*
Bacula® - The Network Backup Solution
- Copyright (C) 2001-2007 Free Software Foundation Europe e.V.
+ Copyright (C) 2001-2010 Free Software Foundation Europe e.V.
The main author of Bacula is Kern Sibbald, with contributions from
many others, a complete list can be found in the file AUTHORS.
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Bacula® is a registered trademark of John Walker.
+ Bacula® is a registered trademark of Kern Sibbald.
The licensor of Bacula is the Free Software Foundation Europe
(FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
Switzerland, email:ftf@fsfeurope.org.
*
* Kern E. Sibbald, December 2001
*
- *
- * Version $Id$
*/
#include "bacula.h"
/* Dummy functions */
int generate_daemon_event(JCR *jcr, const char *event) { return 1; }
+extern bool parse_sd_config(CONFIG *config, const char *configfile, int exit_code);
/* Forward referenced functions */
static void do_scan(void);
static time_t lasttime = 0;
+static const char *db_driver = "NULL";
static const char *db_name = "bacula";
static const char *db_user = "bacula";
static const char *db_password = "";
static const char *db_host = NULL;
+static int db_port = 0;
static const char *wd = NULL;
static bool update_db = false;
static bool update_vol_info = false;
static int num_media = 0;
static int num_files = 0;
+static CONFIG *config;
#define CONFIG_FILE "bacula-sd.conf"
char *configfile = NULL;
STORES *me = NULL; /* our Global resource */
" -d <nn> set debug level to <nn>\n"
" -dt print timestamp in debug output\n"
" -m update media info in database\n"
+" -D <driver name> specify the driver database name (default NULL)\n"
" -n <name> specify the database name (default bacula)\n"
" -u <user> specify database user name (default bacula)\n"
" -P <password> specify database password (default none)\n"
" -h <host> specify database host (default NULL)\n"
+" -t <port> specify database port (default 0)\n"
" -p proceed inspite of I/O errors\n"
" -r list records\n"
" -s synchronize or store in database\n"
bindtextdomain("bacula", LOCALEDIR);
textdomain("bacula");
init_stack_dump();
+ lmgr_init_thread();
my_name_is(argc, argv, "bscan");
init_msg(NULL, NULL);
OSDependentInit();
- while ((ch = getopt(argc, argv, "b:c:d:h:mn:pP:rsSu:vV:w:?")) != -1) {
+ while ((ch = getopt(argc, argv, "b:c:d:D:h:p:mn:pP:rsSt:u:vV:w:?")) != -1) {
switch (ch) {
case 'S' :
showProgress = true;
configfile = bstrdup(optarg);
break;
+ case 'D':
+ db_driver = optarg;
+ break;
+
case 'd': /* debug level */
if (*optarg == 't') {
dbg_timestamp = true;
case 'h':
db_host = optarg;
break;
+
+ case 't':
+ db_port = atoi(optarg);
+ break;
case 'm':
update_vol_info = true;
configfile = bstrdup(CONFIG_FILE);
}
- parse_config(configfile);
+ config = new_config_parser();
+ parse_sd_config(config, configfile, M_ERROR_TERM);
LockRes();
me = (STORES *)GetNextRes(R_STORAGE, NULL);
if (!me) {
struct stat sb;
fstat(dev->fd(), &sb);
currentVolumeSize = sb.st_size;
- Pmsg1(000, _("First Volume Size = %sn"),
+ Pmsg1(000, _("First Volume Size = %s\n"),
edit_uint64(currentVolumeSize, ed1));
}
- if ((db=db_init_database(NULL, db_name, db_user, db_password,
- db_host, 0, NULL, 0)) == NULL) {
+ if ((db=db_init(NULL, db_driver, db_name, db_user, db_password,
+ db_host, db_port, NULL, 0)) == NULL) {
Emsg0(M_ERROR_TERM, 0, _("Could not init Bacula database\n"));
}
if (!db_open_database(NULL, db)) {
if (update_db) {
printf("Records added or updated in the catalog:\n%7d Media\n%7d Pool\n%7d Job\n%7d File\n",
num_media, num_pools, num_jobs, num_files);
- }
- else {
+ } else {
printf("Records would have been added or updated in the catalog:\n%7d Media\n%7d Pool\n%7d Job\n%7d File\n",
num_media, num_pools, num_jobs, num_files);
}
{
DEVICE *dev = dcr->dev;
DCR *mdcr;
- Dmsg1(100, "Walk attached jcrs. Volume=%s\n", dev->VolCatInfo.VolCatName);
+ Dmsg1(100, "Walk attached jcrs. Volume=%s\n", dev->getVolCatName());
foreach_dlist(mdcr, dev->attached_dcrs) {
JCR *mjcr = mdcr->jcr;
Dmsg1(000, "========== JobId=%u ========\n", mjcr->JobId);
mjcr->read_dcr->VolLastIndex = dcr->VolLastIndex;
if (!create_jobmedia_record(db, mjcr)) {
Pmsg2(000, _("Could not create JobMedia record for Volume=%s Job=%s\n"),
- dev->VolCatInfo.VolCatName, mjcr->Job);
+ dev->getVolCatName(), mjcr->Job);
}
}
struct stat sb;
fstat(dev->fd(), &sb);
currentVolumeSize = sb.st_size;
- Pmsg1(000, _("First Volume Size = %sn"),
+ Pmsg1(000, _("First Volume Size = %s\n"),
edit_uint64(currentVolumeSize, ed1));
}
return stat;
update_db = save_update_db;
jr.PoolId = pr.PoolId;
-#ifdef xxx
- /* Set start positions into JCR */
- if (dev->is_tape()) {
- /*
- * Note, we have already advanced past current block,
- * so the correct number is block_num - 1
- */
- dcr->StartBlock = dev->block_num - 1;
- dcr->StartFile = dev->file;
- } else {
- dcr->StartBlock = (uint32_t)dev->file_addr;
- dcr->StartFile = (uint32_t)(dev->file_addr >> 32);
- }
-#endif
mjcr->start_time = jr.StartTime;
- mjcr->JobLevel = jr.JobLevel;
+ mjcr->set_JobLevel(jr.JobLevel);
mjcr->client_name = get_pool_memory(PM_FNAME);
pm_strcpy(mjcr->client_name, label.ClientName);
/* Create JobMedia record */
mjcr->read_dcr->VolLastIndex = dcr->VolLastIndex;
create_jobmedia_record(db, mjcr);
- detach_dcr_from_dev(mjcr->read_dcr);
+ free_dcr(mjcr->read_dcr);
free_jcr(mjcr);
break;
case STREAM_UNIX_ATTRIBUTES:
case STREAM_UNIX_ATTRIBUTES_EX:
- if (!unpack_attributes_record(bjcr, rec->Stream, rec->data, attr)) {
+ if (!unpack_attributes_record(bjcr, rec->Stream, rec->data, rec->data_len, attr)) {
Emsg0(M_ERROR_TERM, 0, _("Cannot continue.\n"));
}
- if (attr->file_index != rec->FileIndex) {
- Emsg2(M_ERROR_TERM, 0, _("Record header file index %ld not equal record index %ld\n"),
- rec->FileIndex, attr->file_index);
- }
-
if (verbose > 1) {
decode_stat(attr->attr, &attr->statp, &attr->LinkFI);
build_attr_output_fnames(bjcr, attr);
free_jcr(mjcr);
break;
+ case STREAM_RESTORE_OBJECT:
+ /* ****FIXME*****/
+ /* Implement putting into catalog */
+ break;
+
/* Data stream */
case STREAM_WIN32_DATA:
case STREAM_FILE_DATA:
}
break;
- case STREAM_UNIX_ATTRIBUTES_ACCESS_ACL: /* Standard ACL attributes on UNIX */
- case STREAM_UNIX_ATTRIBUTES_DEFAULT_ACL: /* Default ACL attributes on UNIX */
- /* Ignore Unix attributes */
+ case STREAM_UNIX_ACCESS_ACL: /* Deprecated Standard ACL attributes on UNIX */
+ case STREAM_UNIX_DEFAULT_ACL: /* Deprecated Default ACL attributes on UNIX */
+ case STREAM_ACL_AIX_TEXT:
+ case STREAM_ACL_DARWIN_ACCESS_ACL:
+ case STREAM_ACL_FREEBSD_DEFAULT_ACL:
+ case STREAM_ACL_FREEBSD_ACCESS_ACL:
+ case STREAM_ACL_HPUX_ACL_ENTRY:
+ case STREAM_ACL_IRIX_DEFAULT_ACL:
+ case STREAM_ACL_IRIX_ACCESS_ACL:
+ case STREAM_ACL_LINUX_DEFAULT_ACL:
+ case STREAM_ACL_LINUX_ACCESS_ACL:
+ case STREAM_ACL_TRU64_DEFAULT_ACL:
+ case STREAM_ACL_TRU64_DEFAULT_DIR_ACL:
+ case STREAM_ACL_TRU64_ACCESS_ACL:
+ case STREAM_ACL_SOLARIS_ACLENT:
+ case STREAM_ACL_SOLARIS_ACE:
+ /* Ignore Unix ACL attributes */
+ break;
+
+ case STREAM_XATTR_OPENBSD:
+ case STREAM_XATTR_SOLARIS_SYS:
+ case STREAM_XATTR_SOLARIS:
+ case STREAM_XATTR_DARWIN:
+ case STREAM_XATTR_FREEBSD:
+ case STREAM_XATTR_LINUX:
+ case STREAM_XATTR_NETBSD:
+ /* Ignore Unix Extended attributes */
break;
default:
ar.ClientId = mjcr->ClientId;
ar.JobId = mjcr->JobId;
ar.Stream = rec->Stream;
- ar.FileIndex = rec->FileIndex;
+ if (type == FT_DELETED) {
+ ar.FileIndex = 0;
+ } else {
+ ar.FileIndex = rec->FileIndex;
+ }
ar.attr = ap;
if (dcr->VolFirstIndex == 0) {
dcr->VolFirstIndex = rec->FileIndex;
mr->VolRetention = 365 * 3600 * 24; /* 1 year */
mr->Enabled = 1;
if (vl->VerNum >= 11) {
+ mr->set_first_written = true; /* Save FirstWritten during update_media */
mr->FirstWritten = btime_to_utime(vl->write_btime);
mr->LabelDate = btime_to_utime(vl->label_btime);
} else {
*/
static int create_client_record(B_DB *db, CLIENT_DBR *cr)
{
+ /*
+ * Note, update_db can temporarily be set false while
+ * updating the database, so we must ensure that ClientId is non-zero.
+ */
if (!update_db) {
+ cr->ClientId = 0;
+ if (!db_get_client_record(bjcr, db, cr)) {
+ Pmsg1(0, _("Could not get Client record. ERR=%s\n"), db_strerror(db));
+ return 0;
+ }
return 1;
}
if (!db_create_client_record(bjcr, db, cr)) {
}
if (verbose) {
Pmsg3(000, _("Updated Job termination record for JobId=%u Level=%s TermStat=%c\n"),
- jr->JobId, job_level_to_str(mjcr->JobLevel), jr->JobStatus);
+ jr->JobId, job_level_to_str(mjcr->getJobLevel()), jr->JobStatus);
}
if (verbose > 1) {
const char *term_msg;
case JS_Terminated:
term_msg = _("Backup OK");
break;
+ case JS_Warnings:
+ term_msg = _("Backup OK -- with warnings");
+ break;
case JS_FatalError:
case JS_ErrorTerminated:
term_msg = _("*** Backup Error ***");
mjcr->JobId,
mjcr->Job,
mjcr->fileset_name,
- job_level_to_str(mjcr->JobLevel),
+ job_level_to_str(mjcr->getJobLevel()),
mjcr->client_name,
sdt,
edt,
* the JobId and the ClientId.
*/
jobjcr = new_jcr(sizeof(JCR), bscan_free_jcr);
- jobjcr->JobType = jr->JobType;
- jobjcr->JobLevel = jr->JobLevel;
+ jobjcr->set_JobType(jr->JobType);
+ jobjcr->set_JobLevel(jr->JobLevel);
jobjcr->JobStatus = jr->JobStatus;
bstrncpy(jobjcr->Job, jr->Job, sizeof(jobjcr->Job));
jobjcr->JobId = JobId; /* this is JobId on tape */
/* Dummies to replace askdir.c */
bool dir_find_next_appendable_volume(DCR *dcr) { return 1;}
-bool dir_update_volume_info(DCR *dcr, bool relabel) { return 1; }
-bool dir_create_jobmedia_record(DCR *dcr) { return 1; }
+bool dir_update_volume_info(DCR *dcr, bool relabel, bool update_LastWritten) { return 1; }
+bool dir_create_jobmedia_record(DCR *dcr, bool zero) { return 1; }
bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr) { return 1; }
bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec) { return 1;}
bool dir_send_job_status(JCR *jcr) {return 1;}
int generate_job_event(JCR *jcr, const char *event) { return 1; }
-bool dir_ask_sysop_to_mount_volume(DCR *dcr)
+bool dir_ask_sysop_to_mount_volume(DCR *dcr, int /*mode*/)
{
DEVICE *dev = dcr->dev;
Dmsg0(20, "Enter dir_ask_sysop_to_mount_volume\n");
bool dir_get_volume_info(DCR *dcr, enum get_vol_info_rw writing)
{
Dmsg0(100, "Fake dir_get_volume_info\n");
- bstrncpy(dcr->VolCatInfo.VolCatName, dcr->VolumeName, sizeof(dcr->VolCatInfo.VolCatName));
+ dcr->setVolCatName(dcr->VolumeName);
dcr->VolCatInfo.VolCatParts = find_num_dvd_parts(dcr);
- Dmsg2(500, "Vol=%s num_parts=%d\n", dcr->VolCatInfo.VolCatName, dcr->VolCatInfo.VolCatParts);
+ Dmsg2(500, "Vol=%s num_parts=%d\n", dcr->getVolCatName(), dcr->VolCatInfo.VolCatParts);
return 1;
}