/* Define to 1 if you have the `fork' function. */
#undef HAVE_FORK
+/* Define to 1 if you have the `fseeko' function. */
+#undef HAVE_FSEEKO
+
/* Define to 1 if you have the `getcwd' function. */
#undef HAVE_GETCWD
AC_CHECK_FUNCS(chflags)
-AC_CHECK_FUNCS(snprintf vsnprintf gethostid)
+AC_CHECK_FUNCS(snprintf vsnprintf gethostid fseeko)
dnl# --------------------------------------------------------------------------
dnl# CHECKING FOR THREAD SAFE FUNCTIONS
-for ac_func in snprintf vsnprintf gethostid
+
+for ac_func in snprintf vsnprintf gethostid fseeko
do
as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
echo "$as_me:$LINENO: checking for $ac_func" >&5
+++ /dev/null
-#
-# Kerns Production Bacula Director Daemon Configuration file
-#
-
-Director {
- Name = HeadMan
- DIRport = 9101 # where we listen for UA connections
- QueryFile = "/home/bacula/bin/query.sql"
- WorkingDirectory = "/home/bacula/bin/working"
- PidDirectory = "/home/bacula/bin/working"
- SubSysDirectory = "/home/bacula/bin/working"
- Maximum Concurrent Jobs = 1
- Password =
-}
-
-Schedule {
- Name = "PolyMatouWeeklyCycle"
- Run = Level=Full sun at 1:05
- Run = Level=Incremental mon-sat at 1:05
-}
-
-Schedule {
- Name = "MatouWeeklyCycle"
- Run = Level=Full 1st sat at 1:05
- Run = Level=Differential 2nd-5th sat at 1:05
- Run = Level=Incremental sun-fri at 1:05
-}
-
-Schedule {
- Name = "VerifyCycle"
- Run = Level=Catalog sun-sat at 5:05
-}
-
-
-Schedule {
- Name = "MinimatouWeeklyCycle"
- Run = Level=Full fri at 1:05
- Run = Level=Incremental sat-thu at 1:05
-}
-
-Schedule {
- Name = "MinouWeeklyCycle"
- Run = Level=Full thu at 1:05
- Run = Level=Incremental fri-wed at 1:05
-}
-
-Schedule {
- Name = "RufusWeeklyCycle"
- Run = Level=Full 1st mon at 1:05
- Run = Level=Differential 2nd-5th mon at 1:05
- Run = Level=Incremental tue-sun at 1:05
-}
-
-Schedule {
- Name = "CatalogSched"
- Run = Level=Full sun-sat at 1:10
-}
-
-Schedule {
- Name = "Watchdog"
- Run = Level=Full sun-sat at 6:05
-}
-
-
-Job {
- Name = "Matou"
- Type = Backup
- Level = Incremental
- Client=Matou
- FileSet="Matou Set"
- Messages = Standard
- Storage = DLTDrive
- Pool = Default
- Schedule = "MatouWeeklyCycle"
- Write Bootstrap = "/mnt/deuter/files/backup/matou.bsr"
- Priority = 10
-}
-
-Job {
- Name = "Polymatou"
- Type = Backup
- Level = Incremental
- Client=Polymatou
- FileSet="Full Set"
- Messages = Standard
- Storage = DLTDrive
- Pool = Default
- Schedule = "PolyMatouWeeklyCycle"
- Write Bootstrap = "/mnt/deuter/files/backup/pmatou.bsr"
- Priority = 10
-}
-
-Job {
- Name = "Rufus"
- Type = Backup
- Level = Incremental
- Client=Rufus
- FileSet="RufusAll"
- Messages = Standard
- Storage = DLTDrive
- Pool = Default
- Schedule = "RufusWeeklyCycle"
- Write Bootstrap = "/mnt/deuter/files/backup/rufus.bsr"
- Priority = 10
-}
-
-Job {
- Name = "Minimatou"
- Type = Backup
- Level = Incremental
- Client=Minimatou
- FileSet="Win32 Full Set"
- Messages = Standard
- Storage = DLTDrive
- Pool = Default
- Schedule = "MinimatouWeeklyCycle"
- Write Bootstrap = "/mnt/deuter/files/backup/mmatou.bsr"
- Priority = 11
-}
-
-Job {
- Name = "Minou"
- Type = Backup
- Level = Incremental
- Client=Minou
- FileSet="Minou Full Set"
- Messages = Standard
- Storage = DLTDrive
- Pool = Default
- Schedule = "MinouWeeklyCycle"
- Write Bootstrap = "/mnt/deuter/files/backup/minou.bsr"
- Priority = 11
-}
-
-Job {
- Name = "PmatouVerify"
- Type = Verify
- Level = Catalog
- Client=PmatouVerify
- FileSet="Verify Set"
- Messages = Standard
- Storage = DLTDrive
- Pool = Default
- Schedule = "VerifyCycle"
- Priority = 20 # run after backups
-}
-
-Job {
- Name = "MatouVerify"
- Type = Verify
- Level = Catalog
- Client=MatouVerify
- FileSet="Verify Set"
- Messages = Standard
- Storage = DLTDrive
- Pool = Default
- Schedule = "VerifyCycle"
- Priority = 20
-}
-
-Job {
- Name = "RufusVerify"
- Type = Verify
- Level = Catalog
- Client=RufusVerify
- FileSet="Verify Set"
- Messages = Standard
- Storage = DLTDrive
- Pool = Default
- Schedule = "VerifyCycle"
- Priority = 20
-}
-
-Job {
- Name = "CatalogBackup"
- Type = Backup
- Level = Full
- Client = Polymatou
- FileSet = "CatalogFile"
- Messages = Standard
- Storage = DLTDrive
- Pool = Default
- Schedule = "CatalogSched"
- RunBeforeJob = "/home/bacula/bin/make_catalog_backup"
- RunAfterJob = "/home/bacula/bin/delete_catalog_backup"
- Write Bootstrap = "/mnt/deuter/files/backup/catalog.bsr"
- Priority = 15 # run after backups, but before Verifies
-}
-
-Job {
- Name = "Watchdog"
- Type = Admin
- Client=Watchdog
- FileSet="Verify Set"
- Messages = Standard
- Storage = DLTDrive
- Pool = Default
- Schedule = "Watchdog"
- RunAfterJob = "/home/bacula/bin/watchdog"
- Priority = 99 # last job to run
-}
-
-# Standard Restore template, to be changed by Console program
-Job {
- Name = "RestoreFiles"
- Type = Restore
- Client=Rufus
- FileSet="Full Set"
- Storage = DLTDrive
- Messages = Standard
- Pool = Default
- Where = /tmp/bacula-restores
-}
-
-
-FileSet {
- Name = "Matou Set"
- Include = signature=MD5 {
- /
- /home
- /usr
- /files
- }
- Exclude = { /tmp/* }
-}
-
-
-FileSet {
- Name = "Full Set"
- Include = signature=MD5 {
- @/etc/backup.list
- }
- Exclude = { }
-}
-
-FileSet {
- Name = "RufusAll"
- Include = signature=MD5 {
- /
- /boot
- /home
- /usr
- }
- Exclude = { }
-}
-
-# Backup the copy of the catalog
-FileSet {
- Name = "CatalogFile"
- Include = signature=MD5 {
- /home/bacula/bin/working/bacula.sql
- }
-}
-
-
-FileSet {
- Name = "Verify Set"
- Include = verify=pins5 signature=MD5 {
- /boot
- /bin
- /sbin
- /usr/bin
- /lib
- /root/.ssh
- /home/kern/.ssh
- /var/named
- /etc/sysconfig
- /etc/ssh
- /etc/security
- /etc/exports
- /etc/rc.d/init.d
- /etc/sendmail.cf
- /etc/sysctl.conf
- /etc/services
- /etc/xinetd.d
- /etc/hosts.allow
- /etc/hosts.deny
- /etc/hosts
- /etc/modules.conf
- /etc/named.conf
- /etc/pam.d
- /etc/resolv.conf
- }
- Exclude = { }
-}
-
-
-FileSet {
- Name = "Win32 Full Set"
- Include = signature=MD5 {
- "c:/My Documents"
- }
- Exclude = { }
-}
-
-FileSet {
- Name = "Minou Full Set"
- Include = signature=MD5 {
- "d:/My Documents"
- }
- Exclude = { }
-}
-
-# Definition of tape storage device
-Storage {
- Name = DLTDrive
- Address = lpmatou
- SDPort = 9103
- Password =
- Device = "HP DLT 80" # must be same as Device in Storage daemon
- Media Type = DLT8000 # must be same as MediaType in Storage daemon
-}
-
-#Storage {
-# Name = "8mmDrive"
-# Address = lpmatou
-# SDPort = 9103
-# Password =
-# Device = "Exabyte 8mm"
-# MediaType = "8mm"
-#}
-
-Client {
- Name = Matou
- Address = lmatou
- FDPort = 9102
- Catalog = BackupDB
- Password =
- File Retention = 30d # 80 days
- Job Retention = 1y # one year
- AutoPrune = yes # Prune expired Jobs/Files
-}
-
-Client {
- Name = Polymatou
- Address = lpmatou
- FDPort = 9102
- Catalog = BackupDB
- Password =
- File Retention = 30d # 80 days
- Job Retention = 1y # one year
- AutoPrune = yes # Prune expired Jobs/Files
-}
-
-Client {
- Name = Rufus
- Address = rufus
- FDPort = 9102
- Catalog = BackupDB
- Password =
- File Retention = 30d # 80 days
- Job Retention = 1y # one year
- AutoPrune = yes # Prune expired Jobs/Files
-}
-
-Client {
- Name = Minimatou
- Address = minimatou
- FDPort = 9102
- Catalog = BackupDB
- Password =
- File Retention = 30d # 80 days
- Job Retention = 1y # one year
- AutoPrune = yes # Prune expired Jobs/Files
-}
-
-Client {
- Name = Minou
- Address = minou
- FDPort = 9102
- Catalog = BackupDB
- Password =
- File Retention = 30d # 80 days
- Job Retention = 1y # one year
- AutoPrune = yes # Prune expired Jobs/Files
-}
-
-Client {
- Name = MatouVerify
- Address = lmatou
- FDPort = 9102
- Catalog = Verify
- Password =
- File Retention = 30d # 30 days
- Job Retention = 30d # 30 days
- AutoPrune = yes # Prune expired Jobs/Files
-}
-
-Client {
- Name = PmatouVerify
- Address = lpmatou
- FDPort = 9102
- Catalog = Verify
- Password =
- File Retention = 30d # 30 days
- Job Retention = 30d # 30 days
- AutoPrune = yes # Prune expired Jobs/Files
-}
-
-Client {
- Name = RufusVerify
- Address = rufus
- FDPort = 9102
- Catalog = Verify
- Password =
- File Retention = 30d # 30 days
- Job Retention = 30d # 30 days
- AutoPrune = yes # Prune expired Jobs/Files
-}
-
-Client {
- Name = Watchdog
- Address = rufus
- FDPort = 9102
- Catalog = Verify
- Password =
- File Retention = 1d # 1 days
- Job Retention = 1m # 1 month
- AutoPrune = yes # Prune expired Jobs/Files
-}
-
-Catalog {
- Name = BackupDB
- dbname = bacula; user = bacula; password = ""
-}
-
-Catalog {
- Name = Verify
- dbname = verify; user = bacula; password = ""
-}
-
-Messages {
- Name = Standard
- mailcommand = "/home/bacula/bin/smtp -h mail.sibbald.com -f \"\(Bacula\) %r\" -s \"Bacula: %t %e of %c %l\" %r"
- operatorcommand = "/home/bacula/bin/smtp -h YOUR-SMTP_SERVER.com -f \"\(Bacula\) %r\" -s \"Bacula: Intervention needed for %j\" %r"
- MailOnError = YOUR-EMAIL@YOU.com = all
- append = "/home/bacula/bin/log" = all
- operator = YOUR-EMAIL@YOU.com = mount
- console = all
-}
-
-
-Pool {
- Name = Default
- Pool Type = Backup
- Recycle = yes # Bacula can automatically recycle Volumes
- AutoPrune = yes # Prune expired volumes
- Volume Retention = 1y # one year
-}
+++ /dev/null
-#
-# Kern's Production Bacula File Daemon Configuration file
-#
-#
-# "Global" File daemon configuration specifications
-#
-Client { # this is me
- Name = "PolymatouFD"
- FDport = 9102 # where we listen for the director
- WorkingDirectory = "/home/bacula/bin/working"
- PidDirectory = "/home/bacula/bin/working"
- SubSysDirectory = "/home/bacula/bin/working"
-}
-
-#
-# List Directors who are permitted to contact the File daemon
-#
-Director {
- Name = HeadMan
- Password = ""
-}
-
-Director {
- Name = RightHandMan
- Password = xxxxx
-}
-
-Messages {
- Name = Standard
- director = HeadMan = all, !skipped
-}
+++ /dev/null
-#
-# Kern's Production Bacula Storage Daemon Configuration file
-#
-
-#
-# "Global" Storage daemon configuration specifications
-#
-Storage {
- Name = "MainSD"
- SDPort = 9103 # Directors port
- WorkingDirectory = "/home/bacula/bin/working"
- PidDirectory = "/home/bacula/bin/working"
- SubSysDirectory = "/home/bacula/bin/working"
-}
-
-#
-# List Directors who are permitted to contact Storage daemon
-#
-Director {
- Name = HeadMan
- Password = ""
-}
-
-#
-# Devices supported by this Storage daemon
-# To connect, the Director must have the same Name and MediaType,
-# which are sent to the File daemon
-#
-Device {
- Name = "HP DLT 80"
- Media Type = DLT8000
- Archive Device = /dev/nst0
- AutomaticMount = yes; # when device opened, read it
- AlwaysOpen = yes;
- RemovableMedia = yes;
-}
-
-#Device {
-# Name = "Exabyte 8mm"
-# Media Type = "8mm"
-# Archive Device = /dev/nst1
-# Hardware end of medium = No;
-## LabelMedia = yes; # lets Bacula label unlabelled media
-# AutomaticMount = yes; # when device opened, read it
-# AlwaysOpen = Yes;
-# RemovableMedia = yes;
-#}
-
-Messages {
- Name = Standard
- director = HeadMan = all
- operator = root = mount
-}
For 1.37:
- Add disk seeking on restore.
+- Make "update slots" when pointing to Autochanger, remove
+ all Volumes from other drives.
- Don't start a second file job if one is already running.
- Add Python writable variable for changing the Priority,
Client, Storage, JobStatus (error), ...
1.37 Possibilities:
+- A HOLD command to stop all jobs from starting.
+- A PAUSE command to pause all running jobs ==> release the
+ drive.
=== From Carsten Menke <bootsy52@gmx.net>
Following is a list of what I think in the situations where I'm faced with,
#define bmalloc(size) b_malloc(__FILE__, __LINE__, (size))
#endif
+/*
+ * Replace codes needed in both file routines and non-file routines
+ * Job replace codes -- in "replace"
+ */
+#define REPLACE_ALWAYS 'a'
+#define REPLACE_IFNEWER 'w'
+#define REPLACE_NEVER 'n'
+#define REPLACE_IFOLDER 'o'
+
+/* This probably should be done on a machine by machine basic, but it works */
+/* This is critical for the smartalloc routines to properly align memory */
+#define ALIGN_SIZE (sizeof(double))
+#define BALIGN(x) (((x) + ALIGN_SIZE - 1) & ~(ALIGN_SIZE -1))
+
+
+/* =============================================================
+ * OS Dependent defines
+ * =============================================================
+ */
+
+#ifndef HAVE_FSEEKO
+/* Bad news. This OS cannot handle 64 bit fseeks and ftells */
+#define fseeko fseek
+#define ftello ftell
+#endif
+
#ifdef __alpha__
#define OSF 1
#endif
extern "C" long gethostid(void);
#endif
-/* This probably should be done on a machine by machine basic, but it works */
-#define ALIGN_SIZE (sizeof(double))
-#define BALIGN(x) (((x) + ALIGN_SIZE - 1) & ~(ALIGN_SIZE -1))
-
/* Added by KES to deal with Win32 systems */
#ifndef S_ISWIN32
#define S_ISWIN32 020000
#endif
-/*
- * Replace codes needed in both file routines and non-file routines
- * Job replace codes -- in "replace"
- */
-#define REPLACE_ALWAYS 'a'
-#define REPLACE_IFNEWER 'w'
-#define REPLACE_NEVER 'n'
-#define REPLACE_IFOLDER 'o'
#undef HAVE_SETLOCALE
#ifdef HAVE_SETLOCALE
for ( ;; ) {
if (at_prompt) { /* don't prompt multiple times */
- prompt = "";
+ prompt = "";
} else {
- prompt = "*";
+ prompt = "*";
at_prompt = true;
}
if (tty_input) {
if (stat < 0) {
break; /* error or interrupt */
} else if (stat == 0) { /* timeout */
- if (strcmp(prompt, "*") == 0) {
- bnet_fsend(UA_sock, ".messages");
+ if (strcmp(prompt, "*") == 0) {
+ bnet_fsend(UA_sock, ".messages");
} else {
continue;
}
} else {
at_prompt = FALSE;
/* @ => internal command for us */
- if (UA_sock->msg[0] == '@') {
+ if (UA_sock->msg[0] == '@') {
parse_args(UA_sock->msg, &args, &argc, argk, argv, MAX_CMD_ARGS);
if (!do_a_command(input, UA_sock)) {
break;
while ((stat = bnet_recv(UA_sock)) >= 0) {
if (at_prompt) {
if (!stop) {
- sendit("\n");
+ sendit("\n");
}
at_prompt = false;
}
if (UA_sock->msglen == BNET_PROMPT) {
at_prompt = true;
}
- Dmsg1(100, "Got poll %s\n", bnet_sig_to_ascii(UA_sock));
+ Dmsg1(100, "Got poll %s\n", bnet_sig_to_ascii(UA_sock));
}
}
}
LockRes();
ndir = 0;
foreach_res(dir, R_DIRECTOR) {
- senditf( _("%d %s at %s:%d\n"), 1+ndir++, dir->hdr.name, dir->address,
+ senditf( _("%d %s at %s:%d\n"), 1+ndir++, dir->hdr.name, dir->address,
dir->DIRport);
}
UnlockRes();
}
item = atoi(UA_sock->msg);
if (item < 0 || item > ndir) {
- senditf(_("You must enter a number between 1 and %d\n"), ndir);
+ senditf(_("You must enter a number between 1 and %d\n"), ndir);
goto try_again;
}
LockRes();
if (output == stdout || tee) {
char *p, *q;
/*
- * Here, we convert every \n into \r\n because the
+ * Here, we convert every \n into \r\n because the
* terminal is in raw mode when we are using
* conio.
*/
if (p-q > 0) {
t_sendl(q, p-q);
}
- t_sendl("\r\n", 2);
- q = ++p; /* point after \n */
+ t_sendl("\r\n", 2);
+ q = ++p; /* point after \n */
}
if (*q) {
t_send(q);
}
#else
fputs(buf, output);
+ fflush(output);
if (tee) {
fputs(buf, stdout);
}
- if (output == stdout || tee) {
+ if (output != stdout || tee) {
fflush(stdout);
}
#endif
/* Pickup Job termination data */
stat = wait_for_job_termination(jcr);
- backup_cleanup(jcr, stat);
- return stat == JS_Terminated;
+ if (stat == JS_Terminated) {
+ backup_cleanup(jcr, stat);
+ return true;
+ }
+ return false;
}
* Insanity check for VolFiles get set to a smaller value
*/
if (sdmr.VolFiles < mr.VolFiles) {
- Jmsg(jcr, M_ERROR, 0, _("ERROR!! Volume Files at %u being set to %u. This is probably wrong.\n"),
- mr.VolFiles, sdmr.VolFiles);
+ Jmsg(jcr, M_FATAL, 0, _("Volume Files at %u being set to %u"
+ " for Volume \"%s\". This is incorrect.\n"),
+ mr.VolFiles, sdmr.VolFiles, mr.VolumeName);
+ bnet_fsend(bs, "1992 Update Media error\n");
+ db_unlock(jcr->db);
+ return;
}
}
Dmsg2(400, "Update media: BefVolJobs=%u After=%u\n", mr.VolJobs, sdmr.VolJobs);
{"user", store_str, ITEM(res_cat.db_user), 0, 0, 0},
{"dbname", store_str, ITEM(res_cat.db_name), 0, ITEM_REQUIRED, 0},
{"dbsocket", store_str, ITEM(res_cat.db_socket), 0, 0, 0},
- {"multipleconnections", store_yesno, ITEM(res_cat.mult_db_connections), 1, 0, 0},
+ /* Turned off for the moment */
+ {"multipleconnections", store_yesno, ITEM(res_cat.mult_db_connections), 0, 0, 0},
{NULL, NULL, NULL, 0, 0, 0}
};
} else {
stat = jcr->SDJobStatus;
}
- mac_cleanup(jcr, stat);
- return jcr->JobStatus == JS_Terminated;
+ if (stat == JS_Terminated) {
+ mac_cleanup(jcr, stat);
+ return true;
+ }
+ return false;
}
* Version $Id$
*/
/*
- Copyright (C) 2001-2004 Kern Sibbald and John Walker
+ Copyright (C) 2001-2005 Kern Sibbald
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
set_pool_dbr_defaults_in_media_dbr(mr, &pr);
jcr->VolumeName[0] = 0;
bstrncpy(mr->MediaType, jcr->store->media_type, sizeof(mr->MediaType));
- if (generate_event(jcr, "NewVolume") == 1 && jcr->VolumeName[0]) {
+ if (generate_event(jcr, "NewVolume") == 1 && jcr->VolumeName[0]) {
bstrncpy(mr->VolumeName, jcr->VolumeName, sizeof(mr->VolumeName));
/* Check for special characters */
} else if (is_volume_name_legal(NULL, pr.LabelFormat)) {
goto bail_out;
}
if (!is_volume_name_legal(NULL, mr->VolumeName)) {
- Jmsg(jcr, M_ERROR, 0, _("Illegal character in Volume name \"%s\"\n"),
+ Jmsg(jcr, M_ERROR, 0, _("Illegal character in Volume name \"%s\"\n"),
mr->VolumeName);
goto bail_out;
}
if (db_create_media_record(jcr, jcr->db, mr) &&
db_update_pool_record(jcr, jcr->db, &pr)) {
db_unlock(jcr->db);
- Jmsg(jcr, M_INFO, 0, _("Created new Volume \"%s\" in catalog.\n"), mr->VolumeName);
- Dmsg1(90, "Created new Volume=%s\n", mr->VolumeName);
+ Jmsg(jcr, M_INFO, 0, _("Created new Volume \"%s\" in catalog.\n"), mr->VolumeName);
+ Dmsg1(90, "Created new Volume=%s\n", mr->VolumeName);
return true;
} else {
- Jmsg(jcr, M_ERROR, 0, "%s", db_strerror(jcr->db));
+ Jmsg(jcr, M_ERROR, 0, "%s", db_strerror(jcr->db));
}
}
}
bstrncat(tmr.VolumeName, num, sizeof(tmr.VolumeName));
if (db_get_media_record(jcr, jcr->db, &tmr)) {
Jmsg(jcr, M_WARNING, 0,
- _("Wanted to create Volume \"%s\", but it already exists. Trying again.\n"),
+ _("Wanted to create Volume \"%s\", but it already exists. Trying again.\n"),
tmr.VolumeName);
continue;
}
*/
if (!connect_to_storage_daemon(jcr, 10, SDConnectTimeout, 1)) {
restore_cleanup(jcr, JS_ErrorTerminated);
- return 0;
+ return false;
}
/*
* Now start a job with the Storage daemon
}
stat = wait_for_job_termination(jcr);
- verify_cleanup(jcr, stat);
- return true;
+ if (stat == JS_Terminated) {
+ verify_cleanup(jcr, stat);
+ return true;
+ }
+ return false;
}
*/
#if defined(HAVE_DARWIN_OS) \
|| defined(HAVE_FREEBSD_OS ) \
- || defined(HAVE_NETBSD_OS) \
|| defined(HAVE_OPENBSD_OS)
#include <sys/param.h>
Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
return false;
}
+#elif defined(HAVE_NETBSD_OS)
+#include <sys/param.h>
+#include <sys/mount.h>
+bool fstype(const char *fname, char *fs, int fslen)
+{
+ struct statvfs st;
+ if (statvfs(fname, &st) == 0) {
+ bstrncpy(fs, st.f_fstypename, fslen);
+ return true;
+ }
+ Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
+ return false;
+}
#elif defined(HAVE_HPUX_OS) \
|| defined(HAVE_IRIX_OS)
/* Parmaters for Open Read Session */
BSR *bsr; /* Bootstrap record -- has everything */
+ bool mount_next_volume; /* set to cause next volume mount */
uint32_t read_VolSessionId;
uint32_t read_VolSessionTime;
uint32_t read_StartFile;
break;
}
- Jmsg(jcr, M_FATAL, 0, _("Open device %s volume %s failed, ERR=%s\n"),
+ Jmsg(jcr, M_FATAL, 0, _("Open device %s Volume \"%s\" failed: ERR=%s\n"),
dev->print_name(), dcr->VolumeName, strerror_dev(dev));
goto get_out;
}
*/
bool release_device(DCR *dcr)
{
+ bool ok = true;
JCR *jcr = dcr->jcr;
DEVICE *dev = dcr->dev;
if (!dir_create_jobmedia_record(dcr)) {
Jmsg(jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
dcr->VolCatInfo.VolCatName, jcr->Job);
+ ok = false;
}
/* If no more writers, write an EOF */
if (!dev->num_writers && dev_can_write(dev)) {
Jmsg2(jcr, M_FATAL, 0, _("BAD ERROR: release_device %s, Volume \"%s\" not in use.\n"),
dev->print_name(), NPRT(dcr->VolumeName));
Jmsg2(jcr, M_ERROR, 0, _("num_writers=%d state=%x\n"), dev->num_writers, dev->state);
+ ok = false;
}
/* Fire off Alert command and include any output */
unlock_device(dev);
free_dcr(dcr);
jcr->dcr = NULL;
- return true;
+ return ok;
}
* is set to yes, open the next part, so, in case of a device
* that requires mount, it will be written to the device.
*/
- if (dev->is_dvd() && jcr->write_part_after_job && (dev->part_size > 0)) {
+ if (ok && dev->is_dvd() && jcr->write_part_after_job && (dev->part_size > 0)) {
Dmsg0(100, "Writing last part because write_part_after_job is set.\n");
if (dev->part < dev->num_parts) {
Jmsg3(jcr, M_FATAL, 0, _("Error while writing, current part number is less than the total number of parts (%d/%d, device=%s)\n"),
int slot;
int drive = dev->device->drive_index;
int rtn_stat = -1; /* error status */
+ POOLMEM *changer;
slot = dcr->VolCatInfo.InChanger ? dcr->VolCatInfo.Slot : 0;
/*
}
Dmsg1(400, "Want changer slot=%d\n", slot);
+ changer = get_pool_memory(PM_FNAME);
if (slot > 0 && dcr->device->changer_name && dcr->device->changer_command) {
uint32_t timeout = dcr->device->max_changer_wait;
- POOLMEM *changer;
int loaded, status;
- changer = get_pool_memory(PM_FNAME);
-
loaded = get_autochanger_loaded_slot(dcr);
/* If tape we want is not loaded, load it. */
if (status != 0) {
berrno be;
be.set_errno(status);
- Jmsg(jcr, M_INFO, 0, _("3992 Bad autochanger \"unload slot %d, drive %d\": ERR=%s.\n"),
+ Jmsg(jcr, M_FATAL, 0, _("3992 Bad autochanger \"unload slot %d, drive %d\": ERR=%s.\n"),
slot, drive, be.strerror());
+ goto bail_out;
}
Dmsg1(400, "unload status=%d\n", status);
} else {
berrno be;
be.set_errno(status);
- Jmsg(jcr, M_INFO, 0, _("3992 Bad autochanger \"load slot %d, drive %d\": ERR=%s.\n"),
+ Jmsg(jcr, M_FATAL, 0, _("3992 Bad autochanger \"load slot %d, drive %d\": ERR=%s.\n"),
slot, drive, be.strerror());
+ goto bail_out;
}
unlock_changer(dcr);
Dmsg2(400, "load slot %d status=%d\n", slot, status);
} else {
status = 0; /* we got what we want */
}
- free_pool_memory(changer);
Dmsg1(400, "After changer, status=%d\n", status);
if (status == 0) { /* did we succeed? */
rtn_stat = 1; /* tape loaded by changer */
} else {
rtn_stat = 0; /* no changer found */
}
+ free_pool_memory(changer);
return rtn_stat;
+
+bail_out:
+ free_pool_memory(changer);
+ unlock_changer(dcr);
+ return -1;
+
}
static int get_autochanger_loaded_slot(DCR *dcr)
if (dev->dev_errno == ENOSPC) {
Jmsg(jcr, M_INFO, 0, _("End of Volume \"%s\" at %u:%u on device %s. Write of %u bytes got %d.\n"),
dev->VolCatInfo.VolCatName,
- dev->file, dev->block_num, dev->dev_name, wlen, stat);
+ dev->file, dev->block_num, dev->print_name(), wlen, stat);
}
Dmsg6(100, "=== Write error. size=%u rtn=%d dev_blk=%d blk_blk=%d errno=%d: ERR=%s\n",
wlen, stat, dev->block_num, block->BlockNumber, dev->dev_errno, strerror(dev->dev_errno));
Dmsg1(10, "Cannot get free space on the device ERR=%s.\n", dev->errmsg);
Jmsg(jcr, M_FATAL, 0, _("End of Volume \"%s\" at %u:%u on device %s (part_size=%s, free_space=%s, free_space_errno=%d, errmsg=%s).\n"),
dev->VolCatInfo.VolCatName,
- dev->file, dev->block_num, dev->dev_name,
+ dev->file, dev->block_num, dev->print_name(),
edit_uint64_with_commas(dev->part_size, ed1), edit_uint64_with_commas(dev->free_space, ed2),
dev->free_space_errno, dev->errmsg);
dev->dev_errno = -dev->free_space_errno;
Dmsg0(10, "==== Just enough free space on the device to write the current part...\n");
Jmsg(jcr, M_INFO, 0, _("End of Volume \"%s\" at %u:%u on device %s (part_size=%s, free_space=%s, free_space_errno=%d).\n"),
dev->VolCatInfo.VolCatName,
- dev->file, dev->block_num, dev->dev_name,
+ dev->file, dev->block_num, dev->print_name(),
edit_uint64_with_commas(dev->part_size, ed1), edit_uint64_with_commas(dev->free_space, ed2),
dev->free_space_errno);
terminate_writing_volume(dcr);
*/
bool read_block_from_device(DCR *dcr, bool check_block_numbers)
{
- bool stat;
+ bool ok;
DEVICE *dev = dcr->dev;
Dmsg0(200, "Enter read_block_from_device\n");
lock_device(dev);
- stat = read_block_from_dev(dcr, check_block_numbers);
+ ok = read_block_from_dev(dcr, check_block_numbers);
unlock_device(dev);
Dmsg0(200, "Leave read_block_from_device\n");
- return stat;
+ return ok;
}
/*
DEVICE *dev = dcr->dev;
DEV_BLOCK *block = dcr->block;
- if (dev_state(dev, ST_EOT)) {
+ if (dev->at_eot()) {
return false;
}
looping = 0;
dev->min_block_size = dev->max_block_size;
set_volume_name("TestVolume1", 1);
- rewind_dev(dev);
- weof_dev(dev, 1);
+ if (!dev->rewind()) {
+ Pmsg0(000, "Rewind failed.\n");
+ }
+ if (!dev->weof()) {
+ Pmsg0(000, "Write EOF failed.\n");
+ }
labelcmd();
- dev->state &= ~ST_APPEND; /* force volume to be relabeled */
+ dev->set_append(); /* force volume to be relabeled */
/*
* Acquire output device for writing. Note, after acquiring a
simple?"":"s", jcr->dcr->dev->file, jcr->dcr->dev->block_num, simple?"":"first ");
jcr->dcr->block = block;
- /* Release the device if multiple tapes being used */
-// if (!simple && !release_device(dcr)) {
-// Pmsg0(-1, _("Error in release_device\n"));
-// ok = false;
-// }
-
do_unfill();
dev->min_block_size = min_block_size;
if (!rewind_dev(dev)) { /* get to a known place on tape */
goto bail_out;
}
- /* Read the first 1000 records */
- Pmsg0(-1, _("Reading the first 1000 records.\n"));
+ /* Read the first 10000 records */
+ Pmsg0(-1, _("Reading the first 10000 records.\n"));
quickie_count = 0;
read_records(dcr, quickie_cb, my_mount_next_read_volume);
Pmsg4(-1, _("Reposition from %u:%u to %u:%u\n"), dev->file, dev->block_num,
free_block(first_block);
}
-/* Read 1000 records then stop */
+/* Read 10000 records then stop */
static bool quickie_cb(DCR *dcr, DEV_RECORD *rec)
{
DEVICE *dev = dcr->dev;
return false;
}
quickie_count++;
- if (quickie_count == 1000) {
+ if (quickie_count == 10000) {
Pmsg2(-1, "1000 records read now at %d:%d\n", dev->file, dev->block_num);
}
- return quickie_count < 1000;
+ return quickie_count < 10000;
}
static bool compare_blocks(DEV_BLOCK *last_block, DEV_BLOCK *block)
/*
- * Fill a tape using raw write() command
+ * Fill a tape using Bacula block writes
*/
static void bfill_cmd()
{
continue;
}
dev->dev_errno = errno;
- Mmsg2(&dev->errmsg, _("stored: unable to open device %s: ERR=%s\n"),
- dev->dev_name, be.strerror());
+ Mmsg2(&dev->errmsg, _("Unable to open device %s: ERR=%s\n"),
+ dev->print_name(), be.strerror(dev->dev_errno));
/* Stop any open timer we set */
if (dev->tid) {
stop_thread_timer(dev->tid);
} bsteal_lock_t;
struct DEVRES; /* Device resource defined in stored_conf.h */
+int weof_dev(DEVICE *dev, int num);
+bool rewind_dev(DEVICE *dev);
/*
* Device structure definition. There is one of these for
int at_eot() const;
int can_append() const;
int can_read() const;
+ bool can_steal_lock() const { return dev_blocked &&
+ (dev_blocked == BST_UNMOUNTED ||
+ dev_blocked == BST_WAITING_FOR_SYSOP ||
+ dev_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP); };
+
+ bool weof() { return !weof_dev(this, 1); };
+ bool rewind() { return rewind_dev(this); };
const char *strerror() const;
const char *archive_name() const;
const char *name() const;
const char *print_name() const; /* Name for display purposes */
- void set_eof();
- void set_eot();
- void set_append();
- void set_read();
- void set_offline();
+ void set_eof(); /* in dev.c */
+ void set_eot(); /* in dev.c */
+ void set_append() { state |= ST_APPEND; };
+ void set_read() { state |= ST_READ; };
+ void set_offline() { state |= ST_OFFLINE; };
void clear_append();
void clear_read();
void clear_label();
void clear_offline();
+ void clear_eot() { state &= ~ST_EOT; };
};
/* Note, these return int not bool! */
inline int DEVICE::at_eot() const { return state & ST_EOT; }
inline int DEVICE::can_append() const { return state & ST_APPEND; }
inline int DEVICE::can_read() const { return state & ST_READ; }
-inline void DEVICE::set_append() { state |= ST_APPEND; }
-inline void DEVICE::set_read() { state |= ST_READ; }
-inline void DEVICE::set_offline() { state |= ST_OFFLINE; }
inline void DEVICE::clear_append() { state &= ~ST_APPEND; }
inline void DEVICE::clear_read() { state &= ~ST_READ; }
inline void DEVICE::clear_label() { state &= ~ST_LABEL; }
if (open_dev(dev, dcr->VolCatInfo.VolCatName, mode) < 0) {
/* If polling, ignore the error */
if (!dev->poll) {
- Jmsg2(dcr->jcr, M_FATAL, 0, _("Unable to open archive %s: ERR=%s\n"),
+ Jmsg2(dcr->jcr, M_FATAL, 0, _("Unable to open device %s: ERR=%s\n"),
dev->print_name(), strerror_dev(dev));
Pmsg2(000, "Unable to open archive %s: ERR=%s\n",
dev->print_name(), strerror_dev(dev));
label_volume_if_ok(jcr, dev, oldname, newname, poolname, slot, relabel);
force_close_dev(dev);
/* Under certain "safe" conditions, we can steal the lock */
- } else if (dev->dev_blocked &&
- (dev->dev_blocked == BST_UNMOUNTED ||
- dev->dev_blocked == BST_WAITING_FOR_SYSOP ||
- dev->dev_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP)) {
+ } else if (dev->can_steal_lock()) {
label_volume_if_ok(jcr, dev, oldname, newname, poolname, slot, relabel);
} else if (dev->is_busy()) {
send_dir_busy_message(dir, dev);
} else if (!dev->is_open()) {
autochanger_cmd(dcr, dir, cmd);
/* Under certain "safe" conditions, we can steal the lock */
- } else if (dev->dev_blocked &&
- (dev->dev_blocked == BST_UNMOUNTED ||
- dev->dev_blocked == BST_WAITING_FOR_SYSOP ||
- dev->dev_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP)) {
+ } else if (dev->can_steal_lock()) {
autochanger_cmd(dcr, dir, cmd);
} else if (dev->is_busy()) {
send_dir_busy_message(dir, dev);
read_volume_label(jcr, dev, Slot);
force_close_dev(dev);
/* Under certain "safe" conditions, we can steal the lock */
- } else if (dev->dev_blocked &&
- (dev->dev_blocked == BST_UNMOUNTED ||
- dev->dev_blocked == BST_WAITING_FOR_SYSOP ||
- dev->dev_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP)) {
+ } else if (dev->can_steal_lock()) {
read_volume_label(jcr, dev, Slot);
} else if (dev->is_busy()) {
send_dir_busy_message(dir, dev);
/* Return an empty block */
empty_block(block); /* we used it for reading so set for write */
}
- dev->state |= ST_APPEND;
+ dev->set_append();
Dmsg0(100, "set APPEND, normal return from read_dev_for_append\n");
return true;
}
*/
if (jcr->NumVolumes > 1 && jcr->CurVolume < jcr->NumVolumes) {
close_dev(dev);
- dev->state &= ~ST_READ;
+ dev->clear_read();
if (!acquire_device_for_read(jcr, dev)) {
Jmsg2(jcr, M_FATAL, 0, "Cannot open Dev=%s, Vol=%s\n", dev->print_name(),
dcr->VolumeName);
* archive. It uses a callback to pass you each record in turn,
* as well as a callback for mounting the next tape. It takes
* care of reading blocks, applying the bsr, ...
+ * Note, this routine is really the heart of the restore routines,
+ * and we are *really* bit pushing here so be careful about making
+ * any modifications.
*
* Kern E. Sibbald, August MMII
*
recs = New(dlist(rec, &rec->link));
position_to_first_file(jcr, dev);
+ jcr->mount_next_volume = false;
for ( ; ok && !done; ) {
if (job_canceled(jcr)) {
if (!read_block_from_device(dcr, CHECK_BLOCK_NUMBERS)) {
if (dev->at_eot()) {
DEV_RECORD *trec = new_record();
-
Jmsg(jcr, M_INFO, 0, "End of Volume at file %u on device %s, Volume \"%s\"\n",
dev->file, dev->print_name(), dcr->VolumeName);
if (!mount_cb(dcr)) {
Jmsg(jcr, M_INFO, 0, "End of all volumes.\n");
- ok = false;
+ ok = false; /* Stop everything */
/*
* Create EOT Label so that Media record may
* be properly updated because this is the last
trec->File = dev->file;
ok = record_cb(dcr, trec);
free_record(trec);
+ if (jcr->mount_next_volume) {
+ jcr->mount_next_volume = false;
+ dev->clear_eot();
+ }
break;
}
+ jcr->mount_next_volume = false;
/*
* We just have a new tape up, now read the label (first record)
* and pass it off to the callback routine, then continue
Pmsg0(000, "Did fsr\n");
continue; /* try to continue */
}
- ok = false;
+ ok = false; /* stop everything */
break;
}
}
Dmsg2(300, "Current postion (file:block) %d:%d\n",
dev->file, dev->block_num);
jcr->bsr->mount_next_volume = false;
-// dev->state |= ST_EOT;
+ if (!dev->at_eot()) {
+ /* Set EOT flag to force mount of next Volume */
+ jcr->mount_next_volume = true;
+ dev->state |= ST_EOT;
+ }
rec->Block = 0;
return 1;
}
char ec1[30];
if (are_attributes_spooled(jcr)) {
- if (fseek(jcr->dir_bsock->spool_fd, 0, SEEK_END) != 0) {
+ if (fseeko(jcr->dir_bsock->spool_fd, 0, SEEK_END) != 0) {
berrno be;
Jmsg(jcr, M_FATAL, 0, _("Fseek on attributes file failed: ERR=%s\n"),
be.strerror());
+ goto bail_out;
+ }
+ size = ftello(jcr->dir_bsock->spool_fd);
+ if (size < 0) {
+ berrno be;
+ Jmsg(jcr, M_FATAL, 0, _("Fseek on attributes file failed: ERR=%s\n"),
+ be.strerror());
+ goto bail_out;
}
- size = ftell(jcr->dir_bsock->spool_fd);
P(mutex);
- if (size > 0) {
- if (spool_stats.attr_size + size > spool_stats.max_attr_size) {
- spool_stats.max_attr_size = spool_stats.attr_size + size;
- }
+ if (spool_stats.attr_size + size > spool_stats.max_attr_size) {
+ spool_stats.max_attr_size = spool_stats.attr_size + size;
}
spool_stats.attr_size += size;
V(mutex);
return close_attr_spool_file(jcr, jcr->dir_bsock);
}
return true;
+
+bail_out:
+ close_attr_spool_file(jcr, jcr->dir_bsock);
+ return false;
}
static void make_unique_spool_filename(JCR *jcr, POOLMEM **name, int fd)
/* */
#undef VERSION
-#define VERSION "1.37.7"
-#define BDATE "14 March 2005"
-#define LSMDATE "14Mar05"
+#define VERSION "1.37.8"
+#define BDATE "17 March 2005"
+#define LSMDATE "17Mar05"
/* Debug flags */
#undef DEBUG