-Changes to 1.35.2
+Changes to 1.35.3:
+09Sep04
+- Add "Multiple Connections = yes/no" in catalog record. Only
+ the variable is implemented, no code yet.
+- Close *all* FD unless debug on.
+08Sep04
+- Add first cut of UTF-8 support to conio. It "seems" to be working
+ pretty well. Moving by words will definitely not work though.
+- Improve detection and setting of gateway in the
+ network_start script.
+07Sep04
+- Modify scan code so that in most places scanning will
+ continue across the end of a line.
+05Sep04
+- Begin major phase of 1.35 documentation.
+- All outstanding bugs are fixed.
+- Implement changes and improvements to rescue scripts as
+ proposed by Gaurav.
+05Sep04
+- Add correction to Phil's previous patch.
+- Send all queued messages in SD and FD prior to closing down
+ the job.
+- Send queued messages in Jobs before terminating the job
+ so that the messages print before the job report.
+- Add a destructor so that the Console ACLs are properly
+ freed.
+04Sep04
+- Implement isolinux boot disk.
+- Integrate Phil Stracchino's code (thanks for Matt's help).
+ It permits lists and ranges of jobids on the delete as in:
+ delete job jobid=1,3,5,11-16
+03Sep04
+- Apply Mike Acar's suggestion when looking for the next volume
+ to check purged volumes for recycling before doing a purge.
+- Make some improvements to CDROM disk.
+- Take another crack at ignoring drive open() errors during
+ polling.
+02Sep04
+- Add eliminate orphaned job records; eliminate admin records,
+ and eliminate restore records to dbcheck.
+- replace sprintf by bsnprintf() in dbcheck.
+- Added scan target to makefile in rescue cd to print scsi
+ devices.
+- Added argument to berrno::strerror() to pass errno.
+- Cleaned up a few more old strerror() calls and eliminated a
+ few of the now unnecessary set_errno() calls.
+- Fixed a bug in the polling code that prevented more than 100
+ label reads (insanity check disabled if polling).
+- Ignore bad return from open_device() if polling.
+- Short circuit code if fatal error return from read_label() in
+ mount.c
01Sep04
+- Add index file to JobId field of File records for PostgreSQL.
+- Correct several bugs in the job queue scheduler concerning
+ rescheduled jobs: 1. The SD status was not cleared causing a
+ wrong status to be displayed by Dir after rescheduling. 2. All
+ rescheduled jobs became zombies because the jcr use_count was
+ not decremented properly.
+- Make the Catalog resource required in Client records.
+- Order the listing of where a file is (item 2 on the restore
+ menu) by StartTime.
+- Clarify when a filename only and a full path + filename must
+ be entered in items 2 and 8 of the restore menu.
- Fix logic error in resolution of names on IPv4 systems.
+
+Changes to 1.35.2 released 01Sep04:
30Aug04
- Inhibit printing of FileSet for a restore as it is misleading.
- Cleaned up a number of minor scripting problems with the CDROM
- Release Notes for Bacula 1.35.2
+ Release Notes for Bacula 1.35.3
Bacula code: Total files = 395 Total lines = 115,062 (*.h *.c *.in)
-Changes for 1.35.1
+Changes for 1.35.3
Major Changes:
- Tray monitor program
- Bacula Rescue CDROM
- Regular expressions are not implemented in the Win32 FD.
Other Items:
+- See below
+
+Changes to 1.35.3:
+09Sep04
+- Add "Multiple Connections = yes/no" in catalog record. Only
+ the variable is implemented, no code yet.
+- Close *all* FD unless debug on.
+08Sep04
+- Add first cut of UTF-8 support to conio. It "seems" to be working
+ pretty well. Moving by words will definitely not work though.
+- Improve detection and setting of gateway in the
+ network_start script.
+07Sep04
+- Modify scan code so that in most places scanning will
+ continue across the end of a line.
+05Sep04
+- Begin major phase of 1.35 documentation.
+- All outstanding bugs are fixed.
+- Implement changes and improvements to rescue scripts as
+ proposed by Gaurav.
+05Sep04
+- Add correction to Phil's previous patch.
+- Send all queued messages in SD and FD prior to closing down
+ the job.
+- Send queued messages in Jobs before terminating the job
+ so that the messages print before the job report.
+- Add a destructor so that the Console ACLs are properly
+ freed.
+04Sep04
+- Implement isolinux boot disk.
+- Integrate Phil Stracchino's code (thanks for Matt's help).
+ It permits lists and ranges of jobids on the delete as in:
+ delete job jobid=1,3,5,11-16
+03Sep04
+- Apply Mike Acar's suggestion when looking for the next volume
+ to check purged volumes for recycling before doing a purge.
+- Make some improvements to CDROM disk.
+- Take another crack at ignoring drive open() errors during
+ polling.
+02Sep04
+- Add eliminate orphaned job records; eliminate admin records,
+ and eliminate restore records to dbcheck.
+- replace sprintf by bsnprintf() in dbcheck.
+- Added scan target to makefile in rescue cd to print scsi
+ devices.
+- Added argument to berrno::strerror() to pass errno.
+- Cleaned up a few more old strerror() calls and eliminated a
+ few of the now unnecessary set_errno() calls.
+- Fixed a bug in the polling code that prevented more than 100
+ label reads (insanity check disabled if polling).
+- Ignore bad return from open_device() if polling.
+- Short circuit code if fatal error return from read_label() in
+ mount.c
+01Sep04
+- Add index file to JobId field of File records for PostgreSQL.
+- Correct several bugs in the job queue scheduler concerning
+ rescheduled jobs: 1. The SD status was not cleared causing a
+ wrong status to be displayed by Dir after rescheduling. 2. All
+ rescheduled jobs became zombies because the jcr use_count was
+ not decremented properly.
+- Make the Catalog resource required in Client records.
+- Order the listing of where a file is (item 2 on the restore
+ menu) by StartTime.
+- Clarify when a filename only and a full path + filename must
+ be entered in items 2 and 8 of the restore menu.
- Fix logic error in resolution of names on IPv4 systems.
+
+Changes to 1.35.2 released 01Sep04:
+30Aug04
- Inhibit printing of FileSet for a restore as it is misleading.
- Cleaned up a number of minor scripting problems with the CDROM
creation.
- Fixed a race condition causing a Director crash on termination,
if a large number of SIGHUPs were sent during a multiple concurrent
set of backups.
+28Aug04
- Completed integration of Rescue CD scripts with Bacula source.
+28Aug04
- Added Ignore FileSet Changes = yes
- Added more error checking to the spooling code.
+24Aug04
- Applied a patch from Peter Eriksson that removes a dynamic stack
allocation (replaced by alloca) and fixes some const problems.
- Fixed a free() of a static variable in the new IP code bnet.c
- Changed a Dmsgx(000, to Dmsgx(100 in dev.c that was dumping
debug output on a user.
- Integrated patch from 1.34.6 block.c to 1.35
+17Aug04
- Fix conio.c problem on Solaris.
- Add debug code to lock_jcr_chain().
- Lock jcr chain around less code.
- Implement call by reference for Mmsg() and pm_strxxx() to
simplify calls.
+- New IP address specification is used as follows:
+ [sdaddresses|diraddresses|fdaddresses] = { [[ip|ipv4|ipv6] = {
+ [[addr|port] = [^ ]+[\n;]+] }] }
+
+ so it could look for example like this:
+ SDaddresses = { ip = {
+ addr = 1.2.3.4; port = 1205; }
+ ipv4 = {
+ addr = 1.2.3.4; port = http; }
+ ipv6 = {
+ addr = 1.2.3.4;
+ port = 1205;
+ }
+ ip = {
+ addr = 1.2.3.4
+ port = 1205
+ }
+ ip = {
+ addr = 1.2.3.4
+ }
+ ip = {
+ addr = 2001:220:222::2
+ }
+ ip = {
+ addr = bluedot.thun.net
+ }
+ }
+ as a consequence, you can now specify multiple IP addresses and
+ ports to be used. In the case of a server, it will listen on
+ all those that you specify. In the case of connecting to the server,
+ Bacula will attempt connecting to one at a time until it succeeds.
+ And, in a few other special cases, Bacula will use only the first
+ address specified.
+ The default port numbers are still the same and the services and hosts
+ are also resolved by name. So now you could use the real names for the
+ port numbers.
Release 1.35.1 16 August 2004:
- Added Tape Alert feature (see Alert Command).
Kern's ToDo List
- 08 Septermber 2004
+ 17 Septermber 2004
Major development:
Project Developer
========================================================
1.35 Items to do for release:
-- Restore c: with a prefix into /prefix/c/ to prevent c: and d:
- files with the same name from overwritting each other.
-- Add new DCR calling sequences everywhere in SD. This will permit
- simultaneous use of multiple devices by a single job.
+- Backspace to beginning of line (conio) does not erase first char.
- Document a get out of jail procedure if everything breaks if
you lost/broke the Catalog -- do the same for "I know my
file is there how do I get it back?".
-- Add "Multiple connections = yes/no" to catalog resource.
- Add "Rerun failed levels = yes/no" to Job resource.
from one backup Volume to another.
- New Storage specifications:
+ - Want to write to multiple storage devices simultaneously
+ - Want to write to multiple storage devices sequentially (in one job)
+ - Want to read/write simultaneously
+ - Key is MediaType -- it must match
+
Passed to SD as a sort of BSR record called Storage Specification
Record or SSR.
SSR
MediaType -> Next MediaType
Pool -> Next Pool
Device -> Next Device
- Write Copy Resource that makes a copy of a resource.
Job Resource
Allow multiple Storage specifications
New flags
Storage
Allow Multiple Pool specifications (note, Pool currently
in Job resource).
- Allow Multiple MediaType specifications
- Allow Multiple Device specifications
+ Allow Multiple MediaType specifications in Dir conf
+ Allow Multiple Device specifications in Dir conf
Perhaps keep this in a single SSR
Tie a Volume to a specific device by using a MediaType that
is contained in only one device.
forces the resolution to be only ipv6.
- Fix silly restriction requiring Include { Options { xxx } } to be
on separate lines.
+- Restore c: with a prefix into /prefix/c/ to prevent c: and d:
+ files with the same name from overwritting each other.
+- Add "Multiple connections = yes/no" to catalog resource.
+- Add new DCR calling sequences everywhere in SD. This will permit
+ simultaneous use of multiple devices by a single job.
-
/*
- Copyright (C) 2000-2003 Kern Sibbald and John Walker
+ Copyright (C) 2001-2003 Kern Sibbald and John Walker
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
*/
B_DB *
db_init_database(JCR *jcr, char *db_name, char *db_user, char *db_password,
- char *db_address, int db_port, char *db_socket)
+ char *db_address, int db_port, char *db_socket,
+ int mult_db_connections)
{
B_DB *mdb;
P(mutex); /* lock DB queue */
Dmsg0(200, "Done db_open_database()\n");
mdb->cfd = -1;
V(mutex);
+ Jmsg(jcr, M_WARNING, 0, _("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"));
Jmsg(jcr, M_WARNING, 0, _("WARNING!!!! The Internal Database is for TESTING ONLY!\n"));
- Jmsg(jcr, M_WARNING, 0, _("You should use either SQLite or MySQL\n"));
+ Jmsg(jcr, M_WARNING, 0, _("You should use SQLite, PostgreSQL, or MySQL\n"));
return mdb;
}
*/
B_DB *
db_init_database(JCR *jcr, const char *db_name, const char *db_user, const char *db_password,
- const char *db_address, int db_port, const char *db_socket)
+ const char *db_address, int db_port, const char *db_socket,
+ int mult_db_connections)
{
B_DB *mdb;
}
P(mutex); /* lock DB queue */
/* Look to see if DB already open */
- for (mdb=NULL; (mdb=(B_DB *)qnext(&db_list, &mdb->bq)); ) {
- if (strcmp(mdb->db_name, db_name) == 0) {
- Dmsg2(100, "DB REopen %d %s\n", mdb->ref_count, db_name);
- mdb->ref_count++;
- V(mutex);
- return mdb; /* already open */
+ if (!mult_db_connections) {
+ for (mdb=NULL; (mdb=(B_DB *)qnext(&db_list, &mdb->bq)); ) {
+ if (strcmp(mdb->db_name, db_name) == 0) {
+ Dmsg2(100, "DB REopen %d %s\n", mdb->ref_count, db_name);
+ mdb->ref_count++;
+ V(mutex);
+ return mdb; /* already open */
+ }
}
}
Dmsg0(100, "db_open first time\n");
*/
/*
- Copyright (C) 2000-2004 Kern Sibbald and John Walker
+ Copyright (C) 2003-2004 Kern Sibbald and John Walker
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
*/
B_DB *
db_init_database(JCR *jcr, const char *db_name, const char *db_user, const char *db_password,
- const char *db_address, int db_port, const char *db_socket)
+ const char *db_address, int db_port, const char *db_socket,
+ int mult_db_connections)
{
B_DB *mdb;
return NULL;
}
P(mutex); /* lock DB queue */
- /* Look to see if DB already open */
- for (mdb=NULL; (mdb=(B_DB *)qnext(&db_list, &mdb->bq)); ) {
- if (strcmp(mdb->db_name, db_name) == 0) {
- Dmsg2(100, "DB REopen %d %s\n", mdb->ref_count, db_name);
- mdb->ref_count++;
- V(mutex);
- return mdb; /* already open */
+ if (!mult_db_connections) {
+ /* Look to see if DB already open */
+ for (mdb=NULL; (mdb=(B_DB *)qnext(&db_list, &mdb->bq)); ) {
+ if (strcmp(mdb->db_name, db_name) == 0) {
+ Dmsg2(100, "DB REopen %d %s\n", mdb->ref_count, db_name);
+ mdb->ref_count++;
+ V(mutex);
+ return mdb; /* already open */
+ }
}
}
Dmsg0(100, "db_open first time\n");
- mdb = (B_DB *) malloc(sizeof(B_DB));
+ mdb = (B_DB *)malloc(sizeof(B_DB));
memset(mdb, 0, sizeof(B_DB));
mdb->db_name = bstrdup(db_name);
mdb->db_user = bstrdup(db_user);
/* sql.c */
B_DB *db_init_database(JCR *jcr, const char *db_name, const char *db_user, const char *db_password,
- const char *db_address, int db_port, const char *db_socket);
+ const char *db_address, int db_port, const char *db_socket,
+ int mult_db_connections);
int db_open_database(JCR *jcr, B_DB *db);
void db_close_database(JCR *jcr, B_DB *db);
void db_escape_string(char *snew, char *old, int len);
int db_create_media_record(JCR *jcr, B_DB *db, MEDIA_DBR *media_dbr);
int db_create_client_record(JCR *jcr, B_DB *db, CLIENT_DBR *cr);
int db_create_fileset_record(JCR *jcr, B_DB *db, FILESET_DBR *fsr);
-int db_create_pool_record(JCR *jcr, B_DB *db, POOL_DBR *pool_dbr);
+int db_create_pool_record(JCR *jcr, B_DB *db, POOL_DBR *pool_dbr);
int db_create_jobmedia_record(JCR *jcr, B_DB *mdb, JOBMEDIA_DBR *jr);
int db_create_counter_record(JCR *jcr, B_DB *mdb, COUNTER_DBR *cr);
*/
B_DB *
db_init_database(JCR *jcr, const char *db_name, const char *db_user, const char *db_password,
- const char *db_address, int db_port, const char *db_socket)
+ const char *db_address, int db_port, const char *db_socket,
+ int mult_db_connections)
{
B_DB *mdb;
P(mutex); /* lock DB queue */
/* Look to see if DB already open */
- for (mdb=NULL; (mdb=(B_DB *)qnext(&db_list, &mdb->bq)); ) {
- if (strcmp(mdb->db_name, db_name) == 0) {
- Dmsg2(300, "DB REopen %d %s\n", mdb->ref_count, db_name);
- mdb->ref_count++;
- V(mutex);
- return mdb; /* already open */
+ if (!mult_db_connections) {
+ for (mdb=NULL; (mdb=(B_DB *)qnext(&db_list, &mdb->bq)); ) {
+ if (strcmp(mdb->db_name, db_name) == 0) {
+ Dmsg2(300, "DB REopen %d %s\n", mdb->ref_count, db_name);
+ mdb->ref_count++;
+ V(mutex);
+ return mdb; /* already open */
+ }
}
}
Dmsg0(300, "db_open first time\n");
autoprune.c backup.c bsr.c \
catreq.c dird_conf.c expand.c \
fd_cmds.c getmsg.c inc_conf.c job.c \
- jobq.c mountreq.c msgchan.c next_vol.c newvol.c \
+ jobq.c mac.c \
+ mountreq.c msgchan.c next_vol.c newvol.c \
recycle.c restore.c run_conf.c \
scheduler.c sql_cmds.c \
ua_acl.c ua_cmds.c ua_dotcmds.c \
autoprune.o backup.o bsr.o \
catreq.o dird_conf.o expand.o \
fd_cmds.o getmsg.o inc_conf.o job.o \
- jobq.o mountreq.o msgchan.o next_vol.o newvol.o \
+ jobq.o mac.o \
+ mountreq.o msgchan.o next_vol.o newvol.o \
recycle.o restore.o run_conf.o \
scheduler.o sql_cmds.o \
ua_acl.o ua_cmds.o ua_dotcmds.o \
/*
* Authenticate Storage daemon connection
*/
-int authenticate_storage_daemon(JCR *jcr)
+bool authenticate_storage_daemon(JCR *jcr, STORE *store)
{
BSOCK *sd = jcr->store_bsock;
char dirname[MAX_NAME_LENGTH];
*/
bstrncpy(dirname, director->hdr.name, sizeof(dirname));
bash_spaces(dirname);
- /* Timeout Hello after 5 mins */
- btimer_t *tid = start_bsock_timer(sd, 60 * 5);
+ /* Timeout Hello after 1 min */
+ btimer_t *tid = start_bsock_timer(sd, 60);
if (!bnet_fsend(sd, hello, dirname)) {
stop_bsock_timer(tid);
Jmsg(jcr, M_FATAL, 0, _("Error sending Hello to Storage daemon. ERR=%s\n"), bnet_strerror(sd));
return 0;
}
- if (!cram_md5_get_auth(sd, jcr->store->password, ssl_need) ||
- !cram_md5_auth(sd, jcr->store->password, ssl_need)) {
+ if (!cram_md5_get_auth(sd, store->password, ssl_need) ||
+ !cram_md5_auth(sd, store->password, ssl_need)) {
stop_bsock_timer(tid);
Jmsg0(jcr, M_FATAL, 0, _("Director and Storage daemon passwords or names not the same.\n"
"Please see http://www.bacula.org/html-manual/faq.html#AuthorizationErrors for help.\n"));
BSOCK *fd;
POOL_DBR pr;
FILESET_DBR fsr;
+ STORE *store;
since[0] = 0;
get_level_since_time(jcr, since, sizeof(since));
- jcr->fname = (char *)get_pool_memory(PM_FNAME);
+ jcr->fname = get_pool_memory(PM_FNAME);
/*
* Get the Pool record -- first apply any level defined pools
/*
* send Storage daemon address to the File daemon
*/
- if (jcr->store->SDDport == 0) {
- jcr->store->SDDport = jcr->store->SDport;
+ store = (STORE *)jcr->storage[0]->first();
+ if (store->SDDport == 0) {
+ store->SDDport = store->SDport;
}
- bnet_fsend(fd, storaddr, jcr->store->address, jcr->store->SDDport,
- jcr->store->enable_ssl);
+ bnet_fsend(fd, storaddr, store->address, store->SDDport,
+ store->enable_ssl);
if (!response(jcr, fd, OKstore, "Storage", DISPLAY_ERROR)) {
goto bail_out;
}
}
*svalue = bstrdup(*def_svalue);
set_bit(i, job->hdr.item_present);
+ /*
+ * Handle resources
+ */
} else if (job_items[i].handler == store_res) {
def_svalue = (char **)((char *)(job->jobdefs) + offset);
Dmsg4(400, "Job \"%s\", field \"%s\" item %d offset=%u\n",
}
*svalue = *def_svalue;
set_bit(i, job->hdr.item_present);
+ /*
+ * Handle alist resources
+ */
+ } else if (job_items[i].handler == store_alist_res) {
+ int count = job_items[i].default_value;
+ def_svalue = (char **)((char *)(job->jobdefs) + offset);
+ Dmsg4(400, "Job \"%s\", field \"%s\" item %d offset=%u\n",
+ job->hdr.name, job_items[i].name, i, offset);
+ svalue = (char **)((char *)job + offset);
+ if (*svalue) {
+ Pmsg1(000, "Hey something is wrong. p=0x%lu\n", *svalue);
+ }
+ while (count--) {
+ *svalue++ = *def_svalue++;
+ }
+ set_bit(i, job->hdr.item_present);
/*
* Handle integer fields
* Note, our store_yesno does not handle bitmaped fields
for (i=0; job_items[i].name; i++) {
if (job_items[i].flags & ITEM_REQUIRED) {
if (!bit_is_set(i, job->hdr.item_present)) {
- Jmsg(NULL, M_FATAL, 0, "Field \"%s\" in Job \"%s\" resource is required, but not found.\n",
+ Jmsg(NULL, M_FATAL, 0, "\"%s\" directive in Job \"%s\" resource is required, but not found.\n",
job_items[i].name, job->hdr.name);
OK = false;
}
*/
db = db_init_database(NULL, catalog->db_name, catalog->db_user,
catalog->db_password, catalog->db_address,
- catalog->db_port, catalog->db_socket);
+ catalog->db_port, catalog->db_socket,
+ catalog->mult_db_connections);
if (!db || !db_open_database(NULL, db)) {
Jmsg(NULL, M_FATAL, 0, _("Could not open database \"%s\".\n"),
catalog->db_name);
* 1. The generic lexical scanner in lib/lex.c and lib/lex.h
*
* 2. The generic config scanner in lib/parse_config.c and
- * lib/parse_config.h.
- * These files contain the parser code, some utility
- * routines, and the common store routines (name, int,
- * string).
+ * lib/parse_config.h.
+ * These files contain the parser code, some utility
+ * routines, and the common store routines (name, int,
+ * string).
*
* 3. The daemon specific file, which contains the Resource
- * definitions as well as any specific store routines
- * for the resource records.
+ * definitions as well as any specific store routines
+ * for the resource records.
*
* Kern Sibbald, January MM
*
/*
* Director Resource
*
- * name handler value code flags default_value
+ * name handler value code flags default_value
*/
static RES_ITEM dir_items[] = {
{"name", store_name, ITEM(res_dir.hdr.name), 0, ITEM_REQUIRED, 0},
/*
* Console Resource
*
- * name handler value code flags default_value
+ * name handler value code flags default_value
*/
static RES_ITEM con_items[] = {
{"name", store_name, ITEM(res_con.hdr.name), 0, ITEM_REQUIRED, 0},
/*
* Client or File daemon resource
*
- * name handler value code flags default_value
+ * name handler value code flags default_value
*/
static RES_ITEM cli_items[] = {
/* Storage daemon resource
*
- * name handler value code flags default_value
+ * name handler value code flags default_value
*/
static RES_ITEM store_items[] = {
{"name", store_name, ITEM(res_store.hdr.name), 0, ITEM_REQUIRED, 0},
/*
* Catalog Resource Directives
*
- * name handler value code flags default_value
+ * name handler value code flags default_value
*/
static RES_ITEM cat_items[] = {
{"name", store_name, ITEM(res_cat.hdr.name), 0, ITEM_REQUIRED, 0},
/*
* Job Resource Directives
*
- * name handler value code flags default_value
+ * name handler value code flags default_value
*/
RES_ITEM job_items[] = {
{"name", store_name, ITEM(res_job.hdr.name), 0, ITEM_REQUIRED, 0},
{"description", store_str, ITEM(res_job.hdr.desc), 0, 0, 0},
{"type", store_jobtype, ITEM(res_job.JobType), 0, ITEM_REQUIRED, 0},
- {"level", store_level, ITEM(res_job.level), 0, 0, 0},
+ {"level", store_level, ITEM(res_job.JobLevel), 0, 0, 0},
{"messages", store_res, ITEM(res_job.messages), R_MSGS, ITEM_REQUIRED, 0},
- {"storage", store_res, ITEM(res_job.storage), R_STORAGE, ITEM_REQUIRED, 0},
+ {"storage", store_alist_res, ITEM(res_job.storage), R_STORAGE, ITEM_REQUIRED, MAX_STORE},
{"pool", store_res, ITEM(res_job.pool), R_POOL, ITEM_REQUIRED, 0},
- {"fullbackuppool", store_res, ITEM(res_job.full_pool), R_POOL, 0, 0},
+ {"fullbackuppool", store_res, ITEM(res_job.full_pool), R_POOL, 0, 0},
{"incrementalbackuppool", store_res, ITEM(res_job.inc_pool), R_POOL, 0, 0},
{"differentialbackuppool", store_res, ITEM(res_job.dif_pool), R_POOL, 0, 0},
{"client", store_res, ITEM(res_job.client), R_CLIENT, ITEM_REQUIRED, 0},
/* FileSet resource
*
- * name handler value code flags default_value
+ * name handler value code flags default_value
*/
static RES_ITEM fs_items[] = {
{"name", store_name, ITEM(res_fs.hdr.name), 0, ITEM_REQUIRED, 0},
{"include", store_inc, NULL, 0, ITEM_NO_EQUALS, 0},
{"exclude", store_inc, NULL, 1, ITEM_NO_EQUALS, 0},
{"ignorefilesetchanges", store_yesno, ITEM(res_fs.ignore_fs_changes), 1, ITEM_DEFAULT, 0},
- {NULL, NULL, NULL, 0, 0, 0}
+ {NULL, NULL, NULL, 0, 0, 0}
};
/* Schedule -- see run_conf.c */
/* Schedule
*
- * name handler value code flags default_value
+ * name handler value code flags default_value
*/
static RES_ITEM sch_items[] = {
{"name", store_name, ITEM(res_sch.hdr.name), 0, ITEM_REQUIRED, 0},
/* Pool resource
*
- * name handler value code flags default_value
+ * name handler value code flags default_value
*/
static RES_ITEM pool_items[] = {
{"name", store_name, ITEM(res_pool.hdr.name), 0, ITEM_REQUIRED, 0},
/*
* Counter Resource
- * name handler value code flags default_value
+ * name handler value code flags default_value
*/
static RES_ITEM counter_items[] = {
{"name", store_name, ITEM(res_counter.hdr.name), 0, ITEM_REQUIRED, 0},
* NOTE!!! keep it in the same order as the R_codes
* or eliminate all resources[rindex].name
*
- * name items rcode res_head
+ * name items rcode res_head
*/
RES_TABLE resources[] = {
{"director", dir_items, R_DIRECTOR},
{"counter", counter_items, R_COUNTER},
{"console", con_items, R_CONSOLE},
{"jobdefs", job_items, R_JOBDEFS},
- {NULL, NULL, 0}
+ {NULL, NULL, 0}
};
/* Keywords (RHS) permitted in Job Level records
*
- * level_name level job_type
+ * level_name level job_type
*/
struct s_jl joblevels[] = {
{"Full", L_FULL, JT_BACKUP},
{"Data", L_VERIFY_DATA, JT_VERIFY},
{" ", L_NONE, JT_ADMIN},
{" ", L_NONE, JT_RESTORE},
- {NULL, 0, 0}
+ {NULL, 0, 0}
};
/* Keywords (RHS) permitted in Job type records
*
- * type_name job_type
+ * type_name job_type
*/
struct s_jt jobtypes[] = {
{"backup", JT_BACKUP},
{"admin", JT_ADMIN},
{"verify", JT_VERIFY},
{"restore", JT_RESTORE},
- {NULL, 0}
+ {NULL, 0}
};
#ifdef old_deprecated_code
{"client", 'C'},
{"fileset", 'F'},
{"level", 'L'},
- {NULL, 0}
+ {NULL, 0}
};
/* Keywords (RHS) permitted in Restore records */
{"where", 'W'}, /* root of restore */
{"replace", 'R'}, /* replacement options */
{"bootstrap", 'B'}, /* bootstrap file */
- {NULL, 0}
+ {NULL, 0}
};
#endif
{"ifnewer", REPLACE_IFNEWER},
{"ifolder", REPLACE_IFOLDER},
{"never", REPLACE_NEVER},
- {NULL, 0}
+ {NULL, 0}
};
const char *level_to_str(int level)
bsnprintf(level_no, sizeof(level_no), "%d", level); /* default if not found */
for (i=0; joblevels[i].level_name; i++) {
if (level == joblevels[i].level) {
- str = joblevels[i].level_name;
- break;
+ str = joblevels[i].level_name;
+ break;
}
}
return str;
sendit(sock, "No %s resource defined\n", res_to_str(type));
return;
}
- if (type < 0) { /* no recursion */
+ if (type < 0) { /* no recursion */
type = - type;
recurse = false;
}
switch (type) {
case R_DIRECTOR:
sendit(sock, "Director: name=%s MaxJobs=%d FDtimeout=%s SDtimeout=%s\n",
- reshdr->name, res->res_dir.MaxConcurrentJobs,
- edit_uint64(res->res_dir.FDConnectTimeout, ed1),
- edit_uint64(res->res_dir.SDConnectTimeout, ed2));
+ reshdr->name, res->res_dir.MaxConcurrentJobs,
+ edit_uint64(res->res_dir.FDConnectTimeout, ed1),
+ edit_uint64(res->res_dir.SDConnectTimeout, ed2));
if (res->res_dir.query_file) {
sendit(sock, " query_file=%s\n", res->res_dir.query_file);
}
if (res->res_dir.messages) {
sendit(sock, " --> ");
- dump_resource(-R_MSGS, (RES *)res->res_dir.messages, sendit, sock);
+ dump_resource(-R_MSGS, (RES *)res->res_dir.messages, sendit, sock);
}
break;
case R_CONSOLE:
sendit(sock, "Console: name=%s SSL=%d\n",
- res->res_con.hdr.name, res->res_con.enable_ssl);
+ res->res_con.hdr.name, res->res_con.enable_ssl);
break;
case R_COUNTER:
if (res->res_counter.WrapCounter) {
sendit(sock, "Counter: name=%s min=%d max=%d cur=%d wrapcntr=%s\n",
- res->res_counter.hdr.name, res->res_counter.MinValue,
- res->res_counter.MaxValue, res->res_counter.CurrentValue,
- res->res_counter.WrapCounter->hdr.name);
+ res->res_counter.hdr.name, res->res_counter.MinValue,
+ res->res_counter.MaxValue, res->res_counter.CurrentValue,
+ res->res_counter.WrapCounter->hdr.name);
} else {
sendit(sock, "Counter: name=%s min=%d max=%d\n",
- res->res_counter.hdr.name, res->res_counter.MinValue,
- res->res_counter.MaxValue);
+ res->res_counter.hdr.name, res->res_counter.MinValue,
+ res->res_counter.MaxValue);
}
if (res->res_counter.Catalog) {
sendit(sock, " --> ");
- dump_resource(-R_CATALOG, (RES *)res->res_counter.Catalog, sendit, sock);
+ dump_resource(-R_CATALOG, (RES *)res->res_counter.Catalog, sendit, sock);
}
break;
case R_CLIENT:
sendit(sock, "Client: name=%s address=%s FDport=%d MaxJobs=%u\n",
- res->res_client.hdr.name, res->res_client.address, res->res_client.FDport,
- res->res_client.MaxConcurrentJobs);
+ res->res_client.hdr.name, res->res_client.address, res->res_client.FDport,
+ res->res_client.MaxConcurrentJobs);
sendit(sock, " JobRetention=%s FileRetention=%s AutoPrune=%d\n",
- edit_utime(res->res_client.JobRetention, ed1, sizeof(ed1)),
- edit_utime(res->res_client.FileRetention, ed2, sizeof(ed2)),
- res->res_client.AutoPrune);
+ edit_utime(res->res_client.JobRetention, ed1, sizeof(ed1)),
+ edit_utime(res->res_client.FileRetention, ed2, sizeof(ed2)),
+ res->res_client.AutoPrune);
if (res->res_client.catalog) {
sendit(sock, " --> ");
- dump_resource(-R_CATALOG, (RES *)res->res_client.catalog, sendit, sock);
+ dump_resource(-R_CATALOG, (RES *)res->res_client.catalog, sendit, sock);
}
break;
case R_STORAGE:
sendit(sock, "Storage: name=%s address=%s SDport=%d MaxJobs=%u\n\
DeviceName=%s MediaType=%s\n",
- res->res_store.hdr.name, res->res_store.address, res->res_store.SDport,
- res->res_store.MaxConcurrentJobs,
- res->res_store.dev_name, res->res_store.media_type);
+ res->res_store.hdr.name, res->res_store.address, res->res_store.SDport,
+ res->res_store.MaxConcurrentJobs,
+ res->res_store.dev_name, res->res_store.media_type);
break;
case R_CATALOG:
sendit(sock, "Catalog: name=%s address=%s DBport=%d db_name=%s\n\
db_user=%s\n",
- res->res_cat.hdr.name, NPRT(res->res_cat.db_address),
- res->res_cat.db_port, res->res_cat.db_name, NPRT(res->res_cat.db_user));
+ res->res_cat.hdr.name, NPRT(res->res_cat.db_address),
+ res->res_cat.db_port, res->res_cat.db_name, NPRT(res->res_cat.db_user));
break;
case R_JOB:
case R_JOBDEFS:
sendit(sock, "%s: name=%s JobType=%d level=%s Priority=%d MaxJobs=%u\n",
type == R_JOB ? "Job" : "JobDefs",
- res->res_job.hdr.name, res->res_job.JobType,
- level_to_str(res->res_job.level), res->res_job.Priority,
- res->res_job.MaxConcurrentJobs);
+ res->res_job.hdr.name, res->res_job.JobType,
+ level_to_str(res->res_job.JobLevel), res->res_job.Priority,
+ res->res_job.MaxConcurrentJobs);
sendit(sock, " Resched=%d Times=%d Interval=%s Spool=%d\n",
- res->res_job.RescheduleOnError, res->res_job.RescheduleTimes,
- edit_uint64_with_commas(res->res_job.RescheduleInterval, ed1),
- res->res_job.spool_data);
+ res->res_job.RescheduleOnError, res->res_job.RescheduleTimes,
+ edit_uint64_with_commas(res->res_job.RescheduleInterval, ed1),
+ res->res_job.spool_data);
if (res->res_job.client) {
sendit(sock, " --> ");
- dump_resource(-R_CLIENT, (RES *)res->res_job.client, sendit, sock);
+ dump_resource(-R_CLIENT, (RES *)res->res_job.client, sendit, sock);
}
if (res->res_job.fileset) {
sendit(sock, " --> ");
- dump_resource(-R_FILESET, (RES *)res->res_job.fileset, sendit, sock);
+ dump_resource(-R_FILESET, (RES *)res->res_job.fileset, sendit, sock);
}
if (res->res_job.schedule) {
sendit(sock, " --> ");
- dump_resource(-R_SCHEDULE, (RES *)res->res_job.schedule, sendit, sock);
+ dump_resource(-R_SCHEDULE, (RES *)res->res_job.schedule, sendit, sock);
}
if (res->res_job.RestoreWhere) {
sendit(sock, " --> Where=%s\n", NPRT(res->res_job.RestoreWhere));
if (res->res_job.WriteBootstrap) {
sendit(sock, " --> WriteBootstrap=%s\n", NPRT(res->res_job.WriteBootstrap));
}
- if (res->res_job.storage) {
+ if (res->res_job.storage[0]) {
sendit(sock, " --> ");
- dump_resource(-R_STORAGE, (RES *)res->res_job.storage, sendit, sock);
+ /* ***FIXME*** */
+// dump_resource(-R_STORAGE, (RES *)res->res_job.storage, sendit, sock);
}
if (res->res_job.pool) {
sendit(sock, " --> ");
- dump_resource(-R_POOL, (RES *)res->res_job.pool, sendit, sock);
+ dump_resource(-R_POOL, (RES *)res->res_job.pool, sendit, sock);
}
if (res->res_job.full_pool) {
sendit(sock, " --> ");
- dump_resource(-R_POOL, (RES *)res->res_job.full_pool, sendit, sock);
+ dump_resource(-R_POOL, (RES *)res->res_job.full_pool, sendit, sock);
}
if (res->res_job.inc_pool) {
sendit(sock, " --> ");
- dump_resource(-R_POOL, (RES *)res->res_job.inc_pool, sendit, sock);
+ dump_resource(-R_POOL, (RES *)res->res_job.inc_pool, sendit, sock);
}
if (res->res_job.dif_pool) {
sendit(sock, " --> ");
- dump_resource(-R_POOL, (RES *)res->res_job.dif_pool, sendit, sock);
+ dump_resource(-R_POOL, (RES *)res->res_job.dif_pool, sendit, sock);
}
if (res->res_job.verify_job) {
sendit(sock, " --> ");
- dump_resource(-type, (RES *)res->res_job.verify_job, sendit, sock);
+ dump_resource(-type, (RES *)res->res_job.verify_job, sendit, sock);
}
break;
if (res->res_job.messages) {
sendit(sock, " --> ");
- dump_resource(-R_MSGS, (RES *)res->res_job.messages, sendit, sock);
+ dump_resource(-R_MSGS, (RES *)res->res_job.messages, sendit, sock);
}
break;
case R_FILESET:
int i, j, k;
sendit(sock, "FileSet: name=%s\n", res->res_fs.hdr.name);
for (i=0; i<res->res_fs.num_includes; i++) {
- INCEXE *incexe = res->res_fs.include_items[i];
- for (j=0; j<incexe->num_opts; j++) {
- FOPTS *fo = incexe->opts_list[j];
+ INCEXE *incexe = res->res_fs.include_items[i];
+ for (j=0; j<incexe->num_opts; j++) {
+ FOPTS *fo = incexe->opts_list[j];
sendit(sock, " O %s\n", fo->opts);
- for (k=0; k<fo->regex.size(); k++) {
+ for (k=0; k<fo->regex.size(); k++) {
sendit(sock, " R %s\n", fo->regex.get(k));
- }
- for (k=0; k<fo->wild.size(); k++) {
+ }
+ for (k=0; k<fo->wild.size(); k++) {
sendit(sock, " W %s\n", fo->wild.get(k));
- }
- for (k=0; k<fo->base.size(); k++) {
+ }
+ for (k=0; k<fo->base.size(); k++) {
sendit(sock, " B %s\n", fo->base.get(k));
- }
- if (fo->reader) {
+ }
+ if (fo->reader) {
sendit(sock, " D %s\n", fo->reader);
- }
- if (fo->writer) {
+ }
+ if (fo->writer) {
sendit(sock, " T %s\n", fo->writer);
- }
+ }
sendit(sock, " N\n");
- }
- for (j=0; j<incexe->name_list.size(); j++) {
+ }
+ for (j=0; j<incexe->name_list.size(); j++) {
sendit(sock, " I %s\n", incexe->name_list.get(j));
- }
- if (incexe->name_list.size()) {
+ }
+ if (incexe->name_list.size()) {
sendit(sock, " N\n");
- }
+ }
}
-
+
for (i=0; i<res->res_fs.num_excludes; i++) {
- INCEXE *incexe = res->res_fs.exclude_items[i];
- for (j=0; j<incexe->name_list.size(); j++) {
+ INCEXE *incexe = res->res_fs.exclude_items[i];
+ for (j=0; j<incexe->name_list.size(); j++) {
sendit(sock, " E %s\n", incexe->name_list.get(j));
- }
- if (incexe->name_list.size()) {
+ }
+ if (incexe->name_list.size()) {
sendit(sock, " N\n");
- }
+ }
}
break;
}
case R_SCHEDULE:
if (res->res_sch.run) {
- int i;
- RUN *run = res->res_sch.run;
- char buf[1000], num[30];
+ int i;
+ RUN *run = res->res_sch.run;
+ char buf[1000], num[30];
sendit(sock, "Schedule: name=%s\n", res->res_sch.hdr.name);
- if (!run) {
- break;
- }
+ if (!run) {
+ break;
+ }
next_run:
sendit(sock, " --> Run Level=%s\n", level_to_str(run->level));
bstrncpy(buf, " hour=", sizeof(buf));
- for (i=0; i<24; i++) {
- if (bit_is_set(i, run->hour)) {
+ for (i=0; i<24; i++) {
+ if (bit_is_set(i, run->hour)) {
bsnprintf(num, sizeof(num), "%d ", i);
- bstrncat(buf, num, sizeof(buf));
- }
- }
+ bstrncat(buf, num, sizeof(buf));
+ }
+ }
bstrncat(buf, "\n", sizeof(buf));
- sendit(sock, buf);
+ sendit(sock, buf);
bstrncpy(buf, " mday=", sizeof(buf));
- for (i=0; i<31; i++) {
- if (bit_is_set(i, run->mday)) {
+ for (i=0; i<31; i++) {
+ if (bit_is_set(i, run->mday)) {
bsnprintf(num, sizeof(num), "%d ", i);
- bstrncat(buf, num, sizeof(buf));
- }
- }
+ bstrncat(buf, num, sizeof(buf));
+ }
+ }
bstrncat(buf, "\n", sizeof(buf));
- sendit(sock, buf);
+ sendit(sock, buf);
bstrncpy(buf, " month=", sizeof(buf));
- for (i=0; i<12; i++) {
- if (bit_is_set(i, run->month)) {
+ for (i=0; i<12; i++) {
+ if (bit_is_set(i, run->month)) {
bsnprintf(num, sizeof(num), "%d ", i);
- bstrncat(buf, num, sizeof(buf));
- }
- }
+ bstrncat(buf, num, sizeof(buf));
+ }
+ }
bstrncat(buf, "\n", sizeof(buf));
- sendit(sock, buf);
+ sendit(sock, buf);
bstrncpy(buf, " wday=", sizeof(buf));
- for (i=0; i<7; i++) {
- if (bit_is_set(i, run->wday)) {
+ for (i=0; i<7; i++) {
+ if (bit_is_set(i, run->wday)) {
bsnprintf(num, sizeof(num), "%d ", i);
- bstrncat(buf, num, sizeof(buf));
- }
- }
+ bstrncat(buf, num, sizeof(buf));
+ }
+ }
bstrncat(buf, "\n", sizeof(buf));
- sendit(sock, buf);
+ sendit(sock, buf);
bstrncpy(buf, " wom=", sizeof(buf));
- for (i=0; i<5; i++) {
- if (bit_is_set(i, run->wom)) {
+ for (i=0; i<5; i++) {
+ if (bit_is_set(i, run->wom)) {
bsnprintf(num, sizeof(num), "%d ", i);
- bstrncat(buf, num, sizeof(buf));
- }
- }
+ bstrncat(buf, num, sizeof(buf));
+ }
+ }
bstrncat(buf, "\n", sizeof(buf));
- sendit(sock, buf);
+ sendit(sock, buf);
bstrncpy(buf, " woy=", sizeof(buf));
- for (i=0; i<54; i++) {
- if (bit_is_set(i, run->woy)) {
+ for (i=0; i<54; i++) {
+ if (bit_is_set(i, run->woy)) {
bsnprintf(num, sizeof(num), "%d ", i);
- bstrncat(buf, num, sizeof(buf));
- }
- }
+ bstrncat(buf, num, sizeof(buf));
+ }
+ }
bstrncat(buf, "\n", sizeof(buf));
- sendit(sock, buf);
+ sendit(sock, buf);
sendit(sock, " mins=%d\n", run->minute);
- if (run->pool) {
+ if (run->pool) {
sendit(sock, " --> ");
- dump_resource(-R_POOL, (RES *)run->pool, sendit, sock);
- }
- if (run->storage) {
+ dump_resource(-R_POOL, (RES *)run->pool, sendit, sock);
+ }
+ if (run->storage) {
sendit(sock, " --> ");
- dump_resource(-R_STORAGE, (RES *)run->storage, sendit, sock);
- }
- if (run->msgs) {
+ dump_resource(-R_STORAGE, (RES *)run->storage, sendit, sock);
+ }
+ if (run->msgs) {
sendit(sock, " --> ");
- dump_resource(-R_MSGS, (RES *)run->msgs, sendit, sock);
- }
- /* If another Run record is chained in, go print it */
- if (run->next) {
- run = run->next;
- goto next_run;
- }
+ dump_resource(-R_MSGS, (RES *)run->msgs, sendit, sock);
+ }
+ /* If another Run record is chained in, go print it */
+ if (run->next) {
+ run = run->next;
+ goto next_run;
+ }
} else {
sendit(sock, "Schedule: name=%s\n", res->res_sch.hdr.name);
}
break;
case R_POOL:
sendit(sock, "Pool: name=%s PoolType=%s\n", res->res_pool.hdr.name,
- res->res_pool.pool_type);
+ res->res_pool.pool_type);
sendit(sock, " use_cat=%d use_once=%d acpt_any=%d cat_files=%d\n",
- res->res_pool.use_catalog, res->res_pool.use_volume_once,
- res->res_pool.accept_any_volume, res->res_pool.catalog_files);
+ res->res_pool.use_catalog, res->res_pool.use_volume_once,
+ res->res_pool.accept_any_volume, res->res_pool.catalog_files);
sendit(sock, " max_vols=%d auto_prune=%d VolRetention=%s\n",
- res->res_pool.max_volumes, res->res_pool.AutoPrune,
- edit_utime(res->res_pool.VolRetention, ed1, sizeof(ed1)));
+ res->res_pool.max_volumes, res->res_pool.AutoPrune,
+ edit_utime(res->res_pool.VolRetention, ed1, sizeof(ed1)));
sendit(sock, " VolUse=%s recycle=%d LabelFormat=%s\n",
- edit_utime(res->res_pool.VolUseDuration, ed1, sizeof(ed1)),
- res->res_pool.Recycle,
- NPRT(res->res_pool.label_format));
+ edit_utime(res->res_pool.VolUseDuration, ed1, sizeof(ed1)),
+ res->res_pool.Recycle,
+ NPRT(res->res_pool.label_format));
sendit(sock, " CleaningPrefix=%s\n",
- NPRT(res->res_pool.cleaning_prefix));
+ NPRT(res->res_pool.cleaning_prefix));
sendit(sock, " recyleOldest=%d MaxVolJobs=%d MaxVolFiles=%d\n",
- res->res_pool.purge_oldest_volume,
- res->res_pool.MaxVolJobs, res->res_pool.MaxVolFiles);
+ res->res_pool.purge_oldest_volume,
+ res->res_pool.MaxVolJobs, res->res_pool.MaxVolFiles);
break;
case R_MSGS:
sendit(sock, "Messages: name=%s\n", res->res_msgs.hdr.name);
fopt->wild.destroy();
fopt->base.destroy();
if (fopt->reader) {
- free(fopt->reader);
+ free(fopt->reader);
}
if (fopt->writer) {
- free(fopt->writer);
+ free(fopt->writer);
}
free(fopt);
}
void free_resource(RES *sres, int type)
{
int num;
- RES *nres; /* next resource if linked */
+ RES *nres; /* next resource if linked */
URES *res = (URES *)sres;
if (res == NULL)
switch (type) {
case R_DIRECTOR:
if (res->res_dir.working_directory) {
- free(res->res_dir.working_directory);
+ free(res->res_dir.working_directory);
}
if (res->res_dir.pid_directory) {
- free(res->res_dir.pid_directory);
+ free(res->res_dir.pid_directory);
}
if (res->res_dir.subsys_directory) {
- free(res->res_dir.subsys_directory);
+ free(res->res_dir.subsys_directory);
}
if (res->res_dir.password) {
- free(res->res_dir.password);
+ free(res->res_dir.password);
}
if (res->res_dir.query_file) {
- free(res->res_dir.query_file);
+ free(res->res_dir.query_file);
}
if (res->res_dir.DIRaddrs) {
- free_addresses(res->res_dir.DIRaddrs);
+ free_addresses(res->res_dir.DIRaddrs);
}
break;
case R_COUNTER:
break;
case R_CONSOLE:
if (res->res_con.password) {
- free(res->res_con.password);
+ free(res->res_con.password);
}
for (int i=0; i<Num_ACL; i++) {
- if (res->res_con.ACL_lists[i]) {
- delete res->res_con.ACL_lists[i];
- res->res_con.ACL_lists[i] = NULL;
- }
+ if (res->res_con.ACL_lists[i]) {
+ delete res->res_con.ACL_lists[i];
+ res->res_con.ACL_lists[i] = NULL;
+ }
}
break;
case R_CLIENT:
if (res->res_client.address) {
- free(res->res_client.address);
+ free(res->res_client.address);
}
if (res->res_client.password) {
- free(res->res_client.password);
+ free(res->res_client.password);
}
break;
case R_STORAGE:
if (res->res_store.address) {
- free(res->res_store.address);
+ free(res->res_store.address);
}
if (res->res_store.password) {
- free(res->res_store.password);
+ free(res->res_store.password);
}
if (res->res_store.media_type) {
- free(res->res_store.media_type);
+ free(res->res_store.media_type);
}
if (res->res_store.dev_name) {
- free(res->res_store.dev_name);
+ free(res->res_store.dev_name);
}
break;
case R_CATALOG:
if (res->res_cat.db_address) {
- free(res->res_cat.db_address);
+ free(res->res_cat.db_address);
}
if (res->res_cat.db_socket) {
- free(res->res_cat.db_socket);
+ free(res->res_cat.db_socket);
}
if (res->res_cat.db_user) {
- free(res->res_cat.db_user);
+ free(res->res_cat.db_user);
}
if (res->res_cat.db_name) {
- free(res->res_cat.db_name);
+ free(res->res_cat.db_name);
}
if (res->res_cat.db_password) {
- free(res->res_cat.db_password);
+ free(res->res_cat.db_password);
}
break;
case R_FILESET:
if ((num=res->res_fs.num_includes)) {
- while (--num >= 0) {
- free_incexe(res->res_fs.include_items[num]);
- }
- free(res->res_fs.include_items);
+ while (--num >= 0) {
+ free_incexe(res->res_fs.include_items[num]);
+ }
+ free(res->res_fs.include_items);
}
res->res_fs.num_includes = 0;
if ((num=res->res_fs.num_excludes)) {
- while (--num >= 0) {
- free_incexe(res->res_fs.exclude_items[num]);
- }
- free(res->res_fs.exclude_items);
+ while (--num >= 0) {
+ free_incexe(res->res_fs.exclude_items[num]);
+ }
+ free(res->res_fs.exclude_items);
}
res->res_fs.num_excludes = 0;
break;
case R_POOL:
if (res->res_pool.pool_type) {
- free(res->res_pool.pool_type);
+ free(res->res_pool.pool_type);
}
if (res->res_pool.label_format) {
- free(res->res_pool.label_format);
+ free(res->res_pool.label_format);
}
if (res->res_pool.cleaning_prefix) {
- free(res->res_pool.cleaning_prefix);
+ free(res->res_pool.cleaning_prefix);
}
break;
case R_SCHEDULE:
if (res->res_sch.run) {
- RUN *nrun, *next;
- nrun = res->res_sch.run;
- while (nrun) {
- next = nrun->next;
- free(nrun);
- nrun = next;
- }
+ RUN *nrun, *next;
+ nrun = res->res_sch.run;
+ while (nrun) {
+ next = nrun->next;
+ free(nrun);
+ nrun = next;
+ }
}
break;
case R_JOB:
case R_JOBDEFS:
if (res->res_job.RestoreWhere) {
- free(res->res_job.RestoreWhere);
+ free(res->res_job.RestoreWhere);
}
if (res->res_job.RestoreBootstrap) {
- free(res->res_job.RestoreBootstrap);
+ free(res->res_job.RestoreBootstrap);
}
if (res->res_job.WriteBootstrap) {
- free(res->res_job.WriteBootstrap);
+ free(res->res_job.WriteBootstrap);
}
if (res->res_job.RunBeforeJob) {
- free(res->res_job.RunBeforeJob);
+ free(res->res_job.RunBeforeJob);
}
if (res->res_job.RunAfterJob) {
- free(res->res_job.RunAfterJob);
+ free(res->res_job.RunAfterJob);
}
if (res->res_job.RunAfterFailedJob) {
- free(res->res_job.RunAfterFailedJob);
+ free(res->res_job.RunAfterFailedJob);
}
if (res->res_job.ClientRunBeforeJob) {
- free(res->res_job.ClientRunBeforeJob);
+ free(res->res_job.ClientRunBeforeJob);
}
if (res->res_job.ClientRunAfterJob) {
- free(res->res_job.ClientRunAfterJob);
+ free(res->res_job.ClientRunAfterJob);
+ }
+ for (int i=0; i < MAX_STORE; i++) {
+ if (res->res_job.storage[i]) {
+ delete (alist *)res->res_job.storage[i];
+ }
}
break;
case R_MSGS:
if (res->res_msgs.mail_cmd) {
- free(res->res_msgs.mail_cmd);
+ free(res->res_msgs.mail_cmd);
}
if (res->res_msgs.operator_cmd) {
- free(res->res_msgs.operator_cmd);
+ free(res->res_msgs.operator_cmd);
}
free_msgs_res((MSGS *)res); /* free message resource */
res = NULL;
* Ensure that all required items are present
*/
for (i=0; items[i].name; i++) {
- if (items[i].flags & ITEM_REQUIRED) {
- if (!bit_is_set(i, res_all.res_dir.hdr.item_present)) {
+ if (items[i].flags & ITEM_REQUIRED) {
+ if (!bit_is_set(i, res_all.res_dir.hdr.item_present)) {
Emsg2(M_ERROR_TERM, 0, "%s item is required in %s resource, but not found.\n",
- items[i].name, resources[rindex]);
- }
- }
- /* If this triggers, take a look at lib/parse_conf.h */
- if (i >= MAX_RES_ITEMS) {
+ items[i].name, resources[rindex]);
+ }
+ }
+ /* If this triggers, take a look at lib/parse_conf.h */
+ if (i >= MAX_RES_ITEMS) {
Emsg1(M_ERROR_TERM, 0, "Too many items in %s resource\n", resources[rindex]);
- }
+ }
}
}
case R_POOL:
case R_MSGS:
case R_FILESET:
- break;
+ break;
/* Resources containing another resource */
case R_DIRECTOR:
- if ((res = (URES *)GetResWithName(R_DIRECTOR, res_all.res_dir.hdr.name)) == NULL) {
+ if ((res = (URES *)GetResWithName(R_DIRECTOR, res_all.res_dir.hdr.name)) == NULL) {
Emsg1(M_ERROR_TERM, 0, "Cannot find Director resource %s\n", res_all.res_dir.hdr.name);
- }
- res->res_dir.messages = res_all.res_dir.messages;
- break;
+ }
+ res->res_dir.messages = res_all.res_dir.messages;
+ break;
case R_JOB:
case R_JOBDEFS:
- if ((res = (URES *)GetResWithName(type, res_all.res_dir.hdr.name)) == NULL) {
+ if ((res = (URES *)GetResWithName(type, res_all.res_dir.hdr.name)) == NULL) {
Emsg1(M_ERROR_TERM, 0, "Cannot find Job resource %s\n",
- res_all.res_dir.hdr.name);
- }
- res->res_job.messages = res_all.res_job.messages;
- res->res_job.schedule = res_all.res_job.schedule;
- res->res_job.client = res_all.res_job.client;
- res->res_job.fileset = res_all.res_job.fileset;
- res->res_job.storage = res_all.res_job.storage;
- res->res_job.pool = res_all.res_job.pool;
- res->res_job.full_pool = res_all.res_job.full_pool;
- res->res_job.inc_pool = res_all.res_job.inc_pool;
- res->res_job.dif_pool = res_all.res_job.dif_pool;
- res->res_job.verify_job = res_all.res_job.verify_job;
- res->res_job.jobdefs = res_all.res_job.jobdefs;
- break;
+ res_all.res_dir.hdr.name);
+ }
+ res->res_job.messages = res_all.res_job.messages;
+ res->res_job.schedule = res_all.res_job.schedule;
+ res->res_job.client = res_all.res_job.client;
+ res->res_job.fileset = res_all.res_job.fileset;
+ for (int i=0; i < MAX_STORE; i++) {
+ res->res_job.storage[i] = res_all.res_job.storage[i];
+ }
+ res->res_job.pool = res_all.res_job.pool;
+ res->res_job.full_pool = res_all.res_job.full_pool;
+ res->res_job.inc_pool = res_all.res_job.inc_pool;
+ res->res_job.dif_pool = res_all.res_job.dif_pool;
+ res->res_job.verify_job = res_all.res_job.verify_job;
+ res->res_job.jobdefs = res_all.res_job.jobdefs;
+ break;
case R_COUNTER:
- if ((res = (URES *)GetResWithName(R_COUNTER, res_all.res_counter.hdr.name)) == NULL) {
+ if ((res = (URES *)GetResWithName(R_COUNTER, res_all.res_counter.hdr.name)) == NULL) {
Emsg1(M_ERROR_TERM, 0, "Cannot find Counter resource %s\n", res_all.res_counter.hdr.name);
- }
- res->res_counter.Catalog = res_all.res_counter.Catalog;
- res->res_counter.WrapCounter = res_all.res_counter.WrapCounter;
- break;
+ }
+ res->res_counter.Catalog = res_all.res_counter.Catalog;
+ res->res_counter.WrapCounter = res_all.res_counter.WrapCounter;
+ break;
case R_CLIENT:
- if ((res = (URES *)GetResWithName(R_CLIENT, res_all.res_client.hdr.name)) == NULL) {
+ if ((res = (URES *)GetResWithName(R_CLIENT, res_all.res_client.hdr.name)) == NULL) {
Emsg1(M_ERROR_TERM, 0, "Cannot find Client resource %s\n", res_all.res_client.hdr.name);
- }
- res->res_client.catalog = res_all.res_client.catalog;
- break;
+ }
+ res->res_client.catalog = res_all.res_client.catalog;
+ break;
case R_SCHEDULE:
- /*
- * Schedule is a bit different in that it contains a RUN record
+ /*
+ * Schedule is a bit different in that it contains a RUN record
* chain which isn't a "named" resource. This chain was linked
- * in by run_conf.c during pass 2, so here we jam the pointer
- * into the Schedule resource.
- */
- if ((res = (URES *)GetResWithName(R_SCHEDULE, res_all.res_client.hdr.name)) == NULL) {
+ * in by run_conf.c during pass 2, so here we jam the pointer
+ * into the Schedule resource.
+ */
+ if ((res = (URES *)GetResWithName(R_SCHEDULE, res_all.res_client.hdr.name)) == NULL) {
Emsg1(M_ERROR_TERM, 0, "Cannot find Schedule resource %s\n", res_all.res_client.hdr.name);
- }
- res->res_sch.run = res_all.res_sch.run;
- break;
+ }
+ res->res_sch.run = res_all.res_sch.run;
+ break;
default:
Emsg1(M_ERROR, 0, "Unknown resource type %d in save_resource.\n", type);
- error = 1;
- break;
+ error = 1;
+ break;
}
/* Note, the resource name was already saved during pass 1,
* so here, we can just release it.
*/
if (res_all.res_dir.hdr.name) {
- free(res_all.res_dir.hdr.name);
- res_all.res_dir.hdr.name = NULL;
+ free(res_all.res_dir.hdr.name);
+ res_all.res_dir.hdr.name = NULL;
}
if (res_all.res_dir.hdr.desc) {
- free(res_all.res_dir.hdr.desc);
- res_all.res_dir.hdr.desc = NULL;
+ free(res_all.res_dir.hdr.desc);
+ res_all.res_dir.hdr.desc = NULL;
}
return;
}
res = (URES *)malloc(size);
memcpy(res, &res_all, size);
if (!res_head[rindex]) {
- res_head[rindex] = (RES *)res; /* store first entry */
+ res_head[rindex] = (RES *)res; /* store first entry */
Dmsg3(900, "Inserting first %s res: %s index=%d\n", res_to_str(type),
- res->res_dir.hdr.name, rindex);
+ res->res_dir.hdr.name, rindex);
} else {
- RES *next;
- /* Add new res to end of chain */
- for (next=res_head[rindex]; next->next; next=next->next) {
- if (strcmp(next->name, res->res_dir.hdr.name) == 0) {
- Emsg2(M_ERROR_TERM, 0,
+ RES *next;
+ /* Add new res to end of chain */
+ for (next=res_head[rindex]; next->next; next=next->next) {
+ if (strcmp(next->name, res->res_dir.hdr.name) == 0) {
+ Emsg2(M_ERROR_TERM, 0,
_("Attempt to define second %s resource named \"%s\" is not permitted.\n"),
- resources[rindex].name, res->res_dir.hdr.name);
- }
- }
- next->next = (RES *)res;
+ resources[rindex].name, res->res_dir.hdr.name);
+ }
+ }
+ next->next = (RES *)res;
Dmsg4(900, "Inserting %s res: %s index=%d pass=%d\n", res_to_str(type),
- res->res_dir.hdr.name, rindex, pass);
+ res->res_dir.hdr.name, rindex, pass);
}
}
}
/* Store the type both pass 1 and pass 2 */
for (i=0; jobtypes[i].type_name; i++) {
if (strcasecmp(lc->str, jobtypes[i].type_name) == 0) {
- *(int *)(item->value) = jobtypes[i].job_type;
- i = 0;
- break;
+ *(int *)(item->value) = jobtypes[i].job_type;
+ i = 0;
+ break;
}
}
if (i != 0) {
/* Store the level pass 2 so that type is defined */
for (i=0; joblevels[i].level_name; i++) {
if (strcasecmp(lc->str, joblevels[i].level_name) == 0) {
- *(int *)(item->value) = joblevels[i].level;
- i = 0;
- break;
+ *(int *)(item->value) = joblevels[i].level;
+ i = 0;
+ break;
}
}
if (i != 0) {
/* Scan Replacement options */
for (i=0; ReplaceOptions[i].name; i++) {
if (strcasecmp(lc->str, ReplaceOptions[i].name) == 0) {
- *(int *)(item->value) = ReplaceOptions[i].token;
- i = 0;
- break;
+ *(int *)(item->value) = ReplaceOptions[i].token;
+ i = 0;
+ break;
}
}
if (i != 0) {
for (;;) {
token = lex_get_token(lc, T_NAME);
if (pass == 1) {
- if (((alist **)item->value)[item->code] == NULL) {
- ((alist **)item->value)[item->code] = New(alist(10, owned_by_alist));
+ if (((alist **)item->value)[item->code] == NULL) {
+ ((alist **)item->value)[item->code] = New(alist(10, owned_by_alist));
Dmsg1(900, "Defined new ACL alist at %d\n", item->code);
- }
- ((alist **)item->value)[item->code]->append(bstrdup(lc->str));
+ }
+ ((alist **)item->value)[item->code]->append(bstrdup(lc->str));
Dmsg2(900, "Appended to %d %s\n", item->code, lc->str);
}
token = lex_get_token(lc, T_ALL);
if (token == T_COMMA) {
- continue; /* get another ACL */
+ continue; /* get another ACL */
}
break;
}
};
+#define MAX_STORE 2 /* Max storage directives in Job */
+
/*
* Job Resource
*/
RES hdr;
int JobType; /* job type (backup, verify, restore */
- int level; /* default backup/verify level */
+ int JobLevel; /* default backup/verify level */
int Priority; /* Job priority */
int RestoreJobId; /* What -- JobId to restore */
char *RestoreWhere; /* Where on disk to restore -- directory */
SCHED *schedule; /* When -- Automatic schedule */
CLIENT *client; /* Who to backup */
FILESET *fileset; /* What to backup -- Fileset */
- STORE *storage; /* Where is device -- Storage daemon */
+ alist *storage[MAX_STORE]; /* Where is device -- Storage daemon */
POOL *pool; /* Where is media -- Media Pool */
POOL *full_pool; /* Pool for Full backups */
POOL *inc_pool; /* Pool for Incremental backups */
{
BSOCK *fd;
- fd = bnet_connect(jcr, retry_interval, max_retry_time,
- _("File daemon"), jcr->client->address,
- NULL, jcr->client->FDport, verbose);
- if (fd == NULL) {
- set_jcr_job_status(jcr, JS_ErrorTerminated);
- return 0;
+ if (!jcr->file_bsock) {
+ fd = bnet_connect(jcr, retry_interval, max_retry_time,
+ _("File daemon"), jcr->client->address,
+ NULL, jcr->client->FDport, verbose);
+ if (fd == NULL) {
+ set_jcr_job_status(jcr, JS_ErrorTerminated);
+ return 0;
+ }
+ Dmsg0(10, "Opened connection with File daemon\n");
+ } else {
+ fd = jcr->file_bsock; /* use existing connection */
}
- Dmsg0(10, "Opened connection with File daemon\n");
fd->res = (RES *)jcr->client; /* save resource in BSOCK */
jcr->file_bsock = fd;
set_jcr_job_status(jcr, JS_Running);
extern void term_scheduler();
extern void term_ua_server();
extern int do_backup(JCR *jcr);
+extern bool do_mac(JCR *jcr);
extern int do_admin(JCR *jcr);
extern int do_restore(JCR *jcr);
extern int do_verify(JCR *jcr);
Dmsg0(50, "Open database\n");
jcr->db=db_init_database(jcr, jcr->catalog->db_name, jcr->catalog->db_user,
jcr->catalog->db_password, jcr->catalog->db_address,
- jcr->catalog->db_port, jcr->catalog->db_socket);
+ jcr->catalog->db_port, jcr->catalog->db_socket,
+ jcr->catalog->mult_db_connections);
if (!jcr->db || !db_open_database(jcr, jcr->db)) {
Jmsg(jcr, M_FATAL, 0, _("Could not open database \"%s\".\n"),
jcr->catalog->db_name);
do_autoprune(jcr);
}
break;
+ case JT_MIGRATION:
+ case JT_COPY:
+ case JT_ARCHIVE:
+ do_mac(jcr); /* migration, archive, copy */
+ if (jcr->JobStatus == JS_Terminated) {
+ do_autoprune(jcr);
+ }
+ break;
default:
Pmsg1(0, "Unimplemented job type: %d\n", jcr->JobType);
break;
/* Cancel Storage daemon */
if (jcr->store_bsock) {
ua->jcr->store = jcr->store;
+ for (int i=0; i<MAX_STORE; i++) {
+ ua->jcr->storage[i] = jcr->storage[i];
+ }
if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
bsendmsg(ua, _("Failed to connect to Storage daemon.\n"));
return 0;
jcr->JobLevel = L_NONE;
break;
default:
- jcr->JobLevel = job->level;
+ jcr->JobLevel = job->JobLevel;
break;
}
jcr->JobPriority = job->Priority;
- jcr->store = job->storage;
+ for (int i=0; i<MAX_STORE; i++) {
+ jcr->storage[i] = job->storage[i];
+ }
jcr->client = job->client;
if (!jcr->client_name) {
jcr->client_name = get_pool_memory(PM_NAME);
--- /dev/null
+/*
+ *
+ * Bacula Director -- mac.c -- responsible for doing
+ * migration, archive, and copy jobs.
+ *
+ * Kern Sibbald, September MMIV
+ *
+ * Basic tasks done here:
+ * Open DB and create records for this job.
+ * Open Message Channel with Storage daemon to tell him a job will be starting.
+ * Open connection with File daemon and pass him commands
+ * to do the backup.
+ * When the File daemon finishes the job, update the DB.
+ *
+ * Version $Id$
+ */
+
+/*
+ Copyright (C) 2004 Kern Sibbald and John Walker
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA.
+
+ */
+
+#include "bacula.h"
+#include "dird.h"
+#include "ua.h"
+
+/* Forward referenced functions */
+static void mac_cleanup(JCR *jcr, int TermCode, char *since, FILESET_DBR *fsr,
+ const char *Type);
+
+/* External functions */
+
+/*
+ * Do a Migration, Archive, or Copy of a previous job
+ *
+ * Returns: false on failure
+ * true on success
+ */
+bool do_mac(JCR *jcr)
+{
+ char since[MAXSTRING];
+ int stat;
+ POOL_DBR pr;
+ JOB_DBR jr;
+ FILESET_DBR fsr;
+ JobId_t input_jobid;
+ char *Name;
+ const char *Type;
+
+ switch(jcr->JobType) {
+ case JT_MIGRATION:
+ Type = "Migration";
+ break;
+ case JT_ARCHIVE:
+ Type = "Archive";
+ break;
+ case JT_COPY:
+ Type = "Copy";
+ break;
+ default:
+ Type = "Unknown";
+ break;
+ }
+
+ if (!get_or_create_client_record(jcr)) {
+ goto bail_out;
+ }
+
+ if (!get_or_create_fileset_record(jcr, &fsr)) {
+ goto bail_out;
+ }
+
+ /*
+ * Find JobId of last job that ran.
+ */
+ memcpy(&jr, &jcr->jr, sizeof(jr));
+ Name = jcr->job->hdr.name;
+ Dmsg1(100, "find last jobid for: %s\n", NPRT(Name));
+ if (!db_find_last_jobid(jcr, jcr->db, Name, &jr)) {
+ Jmsg(jcr, M_FATAL, 0, _(
+ "Unable to find JobId of previous Job for this client.\n"));
+ goto bail_out;
+ }
+ input_jobid = jr.JobId;
+ jcr->JobLevel = jr.JobLevel;
+ Dmsg1(100, "Last jobid=%d\n", input_jobid);
+
+ jcr->fname = get_pool_memory(PM_FNAME);
+
+ /*
+ * Get the Pool record -- first apply any level defined pools
+ */
+ switch (jcr->JobLevel) {
+ case L_FULL:
+ if (jcr->full_pool) {
+ jcr->pool = jcr->full_pool;
+ }
+ break;
+ case L_INCREMENTAL:
+ if (jcr->inc_pool) {
+ jcr->pool = jcr->inc_pool;
+ }
+ break;
+ case L_DIFFERENTIAL:
+ if (jcr->dif_pool) {
+ jcr->pool = jcr->dif_pool;
+ }
+ break;
+ }
+ memset(&pr, 0, sizeof(pr));
+ bstrncpy(pr.Name, jcr->pool->hdr.name, sizeof(pr.Name));
+
+ while (!db_get_pool_record(jcr, jcr->db, &pr)) { /* get by Name */
+ /* Try to create the pool */
+ if (create_pool(jcr, jcr->db, jcr->pool, POOL_OP_CREATE) < 0) {
+ Jmsg(jcr, M_FATAL, 0, _("Pool %s not in database. %s"), pr.Name,
+ db_strerror(jcr->db));
+ goto bail_out;
+ } else {
+ Jmsg(jcr, M_INFO, 0, _("Pool %s created in database.\n"), pr.Name);
+ }
+ }
+ jcr->PoolId = pr.PoolId; /****FIXME**** this can go away */
+ jcr->jr.PoolId = pr.PoolId;
+
+
+ /* Print Job Start message */
+ Jmsg(jcr, M_INFO, 0, _("Start %s JobId %u, Job=%s\n"),
+ Type, jcr->JobId, jcr->Job);
+
+ set_jcr_job_status(jcr, JS_Running);
+ Dmsg2(100, "JobId=%d JobLevel=%c\n", jcr->jr.JobId, jcr->jr.JobLevel);
+ if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
+ Jmsg(jcr, M_ERROR, 0, "%s", db_strerror(jcr->db));
+ goto bail_out;
+ }
+
+
+ /*
+ * Open a message channel connection with the Storage
+ * daemon. This is to let him know that our client
+ * will be contacting him for a backup session.
+ *
+ */
+ Dmsg0(110, "Open connection with storage daemon\n");
+ set_jcr_job_status(jcr, JS_WaitSD);
+ /*
+ * Start conversation with Storage daemon
+ */
+ if (!connect_to_storage_daemon(jcr, 10, SDConnectTimeout, 1)) {
+ goto bail_out;
+ }
+ /*
+ * Now start a job with the Storage daemon
+ */
+ if (!start_storage_daemon_job(jcr)) {
+ goto bail_out;
+ }
+ /*
+ * Now start a Storage daemon message thread
+ */
+ if (!start_storage_daemon_message_thread(jcr)) {
+ goto bail_out;
+ }
+ Dmsg0(150, "Storage daemon connection OK\n");
+
+ /* Pickup Job termination data */
+ set_jcr_job_status(jcr, JS_Running);
+
+ /* Note, the SD stores in jcr->JobFiles/ReadBytes/JobBytes/Errors */
+ wait_for_storage_daemon_termination(jcr);
+
+ if (jcr->JobStatus != JS_Terminated) {
+ stat = jcr->JobStatus;
+ } else {
+ stat = jcr->SDJobStatus;
+ }
+ mac_cleanup(jcr, stat, since, &fsr, Type);
+ return true;
+
+bail_out:
+ mac_cleanup(jcr, JS_ErrorTerminated, since, &fsr, Type);
+ return false;
+}
+
+
+/*
+ * Release resources allocated during backup.
+ */
+static void mac_cleanup(JCR *jcr, int TermCode, char *since, FILESET_DBR *fsr,
+ const char *Type)
+{
+ char sdt[50], edt[50];
+ char ec1[30], ec2[30], ec3[30], ec4[30], ec5[30], compress[50];
+ char term_code[100], fd_term_msg[100], sd_term_msg[100];
+ const char *term_msg;
+ int msg_type;
+ MEDIA_DBR mr;
+ double kbps, compression;
+ utime_t RunTime;
+
+ Dmsg2(100, "Enter mac_cleanup %d %c\n", TermCode, TermCode);
+ dequeue_messages(jcr); /* display any queued messages */
+ memset(&mr, 0, sizeof(mr));
+ set_jcr_job_status(jcr, TermCode);
+
+ update_job_end_record(jcr); /* update database */
+
+ if (!db_get_job_record(jcr, jcr->db, &jcr->jr)) {
+ Jmsg(jcr, M_WARNING, 0, _("Error getting job record for stats: %s"),
+ db_strerror(jcr->db));
+ set_jcr_job_status(jcr, JS_ErrorTerminated);
+ }
+
+ bstrncpy(mr.VolumeName, jcr->VolumeName, sizeof(mr.VolumeName));
+ if (!db_get_media_record(jcr, jcr->db, &mr)) {
+ Jmsg(jcr, M_WARNING, 0, _("Error getting Media record for Volume \"%s\": ERR=%s"),
+ mr.VolumeName, db_strerror(jcr->db));
+ set_jcr_job_status(jcr, JS_ErrorTerminated);
+ }
+
+ /* Now update the bootstrap file if any */
+ if (jcr->JobStatus == JS_Terminated && jcr->jr.JobBytes &&
+ jcr->job->WriteBootstrap) {
+ FILE *fd;
+ BPIPE *bpipe = NULL;
+ int got_pipe = 0;
+ char *fname = jcr->job->WriteBootstrap;
+ VOL_PARAMS *VolParams = NULL;
+ int VolCount;
+
+ if (*fname == '|') {
+ fname++;
+ got_pipe = 1;
+ bpipe = open_bpipe(fname, 0, "w");
+ fd = bpipe ? bpipe->wfd : NULL;
+ } else {
+ /* ***FIXME*** handle BASE */
+ fd = fopen(fname, jcr->JobLevel==L_FULL?"w+":"a+");
+ }
+ if (fd) {
+ VolCount = db_get_job_volume_parameters(jcr, jcr->db, jcr->JobId,
+ &VolParams);
+ if (VolCount == 0) {
+ Jmsg(jcr, M_ERROR, 0, _("Could not get Job Volume Parameters to "
+ "update Bootstrap file. ERR=%s\n"), db_strerror(jcr->db));
+ if (jcr->SDJobFiles != 0) {
+ set_jcr_job_status(jcr, JS_ErrorTerminated);
+ }
+
+ }
+ for (int i=0; i < VolCount; i++) {
+ /* Write the record */
+ fprintf(fd, "Volume=\"%s\"\n", VolParams[i].VolumeName);
+ fprintf(fd, "VolSessionId=%u\n", jcr->VolSessionId);
+ fprintf(fd, "VolSessionTime=%u\n", jcr->VolSessionTime);
+ fprintf(fd, "VolFile=%u-%u\n", VolParams[i].StartFile,
+ VolParams[i].EndFile);
+ fprintf(fd, "VolBlock=%u-%u\n", VolParams[i].StartBlock,
+ VolParams[i].EndBlock);
+ fprintf(fd, "FileIndex=%d-%d\n", VolParams[i].FirstIndex,
+ VolParams[i].LastIndex);
+ }
+ if (VolParams) {
+ free(VolParams);
+ }
+ if (got_pipe) {
+ close_bpipe(bpipe);
+ } else {
+ fclose(fd);
+ }
+ } else {
+ berrno be;
+ Jmsg(jcr, M_ERROR, 0, _("Could not open WriteBootstrap file:\n"
+ "%s: ERR=%s\n"), fname, be.strerror());
+ set_jcr_job_status(jcr, JS_ErrorTerminated);
+ }
+ }
+
+ msg_type = M_INFO; /* by default INFO message */
+ switch (jcr->JobStatus) {
+ case JS_Terminated:
+ if (jcr->Errors || jcr->SDErrors) {
+ term_msg = _("Backup OK -- with warnings");
+ } else {
+ term_msg = _("Backup OK");
+ }
+ break;
+ case JS_FatalError:
+ case JS_ErrorTerminated:
+ term_msg = _("*** Backup Error ***");
+ msg_type = M_ERROR; /* Generate error message */
+ if (jcr->store_bsock) {
+ bnet_sig(jcr->store_bsock, BNET_TERMINATE);
+ if (jcr->SD_msg_chan) {
+ pthread_cancel(jcr->SD_msg_chan);
+ }
+ }
+ break;
+ case JS_Canceled:
+ term_msg = _("Backup Canceled");
+ if (jcr->store_bsock) {
+ bnet_sig(jcr->store_bsock, BNET_TERMINATE);
+ if (jcr->SD_msg_chan) {
+ pthread_cancel(jcr->SD_msg_chan);
+ }
+ }
+ break;
+ default:
+ term_msg = term_code;
+ sprintf(term_code, _("Inappropriate term code: %c\n"), jcr->JobStatus);
+ break;
+ }
+ bstrftime(sdt, sizeof(sdt), jcr->jr.StartTime);
+ bstrftime(edt, sizeof(edt), jcr->jr.EndTime);
+ RunTime = jcr->jr.EndTime - jcr->jr.StartTime;
+ if (RunTime <= 0) {
+ kbps = 0;
+ } else {
+ kbps = (double)jcr->jr.JobBytes / (1000 * RunTime);
+ }
+ if (!db_get_job_volume_names(jcr, jcr->db, jcr->jr.JobId, &jcr->VolumeName)) {
+ /*
+ * Note, if the job has erred, most likely it did not write any
+ * tape, so suppress this "error" message since in that case
+ * it is normal. Or look at it the other way, only for a
+ * normal exit should we complain about this error.
+ */
+ if (jcr->JobStatus == JS_Terminated && jcr->jr.JobBytes) {
+ Jmsg(jcr, M_ERROR, 0, "%s", db_strerror(jcr->db));
+ }
+ jcr->VolumeName[0] = 0; /* none */
+ }
+
+ if (jcr->ReadBytes == 0) {
+ bstrncpy(compress, "None", sizeof(compress));
+ } else {
+ compression = (double)100 - 100.0 * ((double)jcr->JobBytes / (double)jcr->ReadBytes);
+ if (compression < 0.5) {
+ bstrncpy(compress, "None", sizeof(compress));
+ } else {
+ bsnprintf(compress, sizeof(compress), "%.1f %%", (float)compression);
+ }
+ }
+ jobstatus_to_ascii(jcr->FDJobStatus, fd_term_msg, sizeof(fd_term_msg));
+ jobstatus_to_ascii(jcr->SDJobStatus, sd_term_msg, sizeof(sd_term_msg));
+
+// bmicrosleep(15, 0); /* for debugging SIGHUP */
+
+ Jmsg(jcr, msg_type, 0, _("Bacula " VERSION " (" LSMDATE "): %s\n\
+JobId: %d\n\
+Job: %s\n\
+Backup Level: %s%s\n\
+Client: %s\n\
+FileSet: \"%s\" %s\n\
+Pool: \"%s\"\n\
+Start time: %s\n\
+End time: %s\n\
+FD Files Written: %s\n\
+SD Files Written: %s\n\
+FD Bytes Written: %s\n\
+SD Bytes Written: %s\n\
+Rate: %.1f KB/s\n\
+Software Compression: %s\n\
+Volume name(s): %s\n\
+Volume Session Id: %d\n\
+Volume Session Time: %d\n\
+Last Volume Bytes: %s\n\
+Non-fatal FD errors: %d\n\
+SD Errors: %d\n\
+FD termination status: %s\n\
+SD termination status: %s\n\
+Termination: %s\n\n"),
+ edt,
+ jcr->jr.JobId,
+ jcr->jr.Job,
+ level_to_str(jcr->JobLevel), since,
+ jcr->client->hdr.name,
+ jcr->fileset->hdr.name, fsr->cCreateTime,
+ jcr->pool->hdr.name,
+ sdt,
+ edt,
+ edit_uint64_with_commas(jcr->jr.JobFiles, ec1),
+ edit_uint64_with_commas(jcr->SDJobFiles, ec4),
+ edit_uint64_with_commas(jcr->jr.JobBytes, ec2),
+ edit_uint64_with_commas(jcr->SDJobBytes, ec5),
+ (float)kbps,
+ compress,
+ jcr->VolumeName,
+ jcr->VolSessionId,
+ jcr->VolSessionTime,
+ edit_uint64_with_commas(mr.VolBytes, ec3),
+ jcr->Errors,
+ jcr->SDErrors,
+ fd_term_msg,
+ sd_term_msg,
+ term_msg);
+
+ Dmsg0(100, "Leave mac_cleanup()\n");
+}
* Establish a message channel connection with the Storage daemon
* and perform authentication.
*/
-int connect_to_storage_daemon(JCR *jcr, int retry_interval,
+bool connect_to_storage_daemon(JCR *jcr, int retry_interval,
int max_retry_time, int verbose)
{
BSOCK *sd;
+ STORE *store = jcr->store;
+ if (!store) {
+ store = (STORE *)jcr->storage[0]->first();
+ }
/*
* Open message channel with the Storage daemon
*/
- Dmsg2(200, "bnet_connect to Storage daemon %s:%d\n", jcr->store->address,
- jcr->store->SDport);
+ Dmsg2(200, "bnet_connect to Storage daemon %s:%d\n", store->address,
+ store->SDport);
sd = bnet_connect(jcr, retry_interval, max_retry_time,
- _("Storage daemon"), jcr->store->address,
- NULL, jcr->store->SDport, verbose);
+ _("Storage daemon"), store->address,
+ NULL, store->SDport, verbose);
if (sd == NULL) {
- return 0;
+ return false;
}
- sd->res = (RES *)jcr->store; /* save pointer to other end */
+ sd->res = (RES *)store; /* save pointer to other end */
jcr->store_bsock = sd;
+ jcr->store = store;
- if (!authenticate_storage_daemon(jcr)) {
- return 0;
+ if (!authenticate_storage_daemon(jcr, store)) {
+ return false;
}
- return 1;
+ return true;
}
/*
STORE *storage;
BSOCK *sd;
char auth_key[100];
- POOLMEM *device_name, *pool_name, *pool_type, *media_type;
+ POOL_MEM device_name, pool_name, pool_type, media_type;
storage = jcr->store;
sd = jcr->store_bsock;
/*
* Send use device = xxx media = yyy pool = zzz
*/
- device_name = get_pool_memory(PM_NAME);
- pool_name = get_pool_memory(PM_NAME);
- pool_type = get_pool_memory(PM_NAME);
- media_type = get_pool_memory(PM_NAME);
pm_strcpy(device_name, storage->dev_name);
pm_strcpy(media_type, storage->media_type);
pm_strcpy(pool_type, jcr->pool->pool_type);
pm_strcpy(pool_name, jcr->pool->hdr.name);
- bash_spaces(device_name);
- bash_spaces(media_type);
- bash_spaces(pool_type);
- bash_spaces(pool_name);
- bnet_fsend(sd, use_device, device_name, media_type, pool_name, pool_type);
+ bash_spaces(device_name.c_str());
+ bash_spaces(media_type.c_str());
+ bash_spaces(pool_type.c_str());
+ bash_spaces(pool_name.c_str());
+ bnet_fsend(sd, use_device, device_name.c_str(),
+ media_type.c_str(), pool_name.c_str(), pool_type.c_str());
Dmsg1(110, ">stored: %s", sd->msg);
status = response(jcr, sd, OK_device, "Use Device", NO_DISPLAY);
if (!status) {
pm_strcpy(pool_type, sd->msg); /* save message */
Jmsg(jcr, M_FATAL, 0, _("\n"
" Storage daemon didn't accept Device \"%s\" because:\n %s"),
- device_name, pool_type/* sd->msg */);
+ device_name.c_str(), pool_type.c_str()/* sd->msg */);
}
- free_memory(device_name);
- free_memory(media_type);
- free_memory(pool_name);
- free_memory(pool_type);
-
return status;
}
int retry = 0;
bool ok;
bool InChanger;
+ STORE *store = jcr->store;
mr->PoolId = jcr->PoolId;
- bstrncpy(mr->MediaType, jcr->store->media_type, sizeof(mr->MediaType));
+ bstrncpy(mr->MediaType, store->media_type, sizeof(mr->MediaType));
Dmsg2(120, "CatReq FindMedia: Id=%d, MediaType=%s\n", mr->PoolId, mr->MediaType);
/*
* If we are using an Autochanger, restrict Volume
* search to the Autochanger on the first pass
*/
- InChanger = jcr->store->autochanger;
+ InChanger = store->autochanger;
/*
* Find the Next Volume for Append
*/
*/
/* authenticate.c */
-extern int authenticate_storage_daemon(JCR *jcr);
+extern bool authenticate_storage_daemon(JCR *jcr, STORE *store);
extern int authenticate_file_daemon(JCR *jcr);
extern int authenticate_user_agent(UAContext *ua);
/* fd_cmds.c */
extern int connect_to_file_daemon(JCR *jcr, int retry_interval,
- int max_retry_time, int verbose);
+ int max_retry_time, int verbose);
extern int send_include_list(JCR *jcr);
extern int send_exclude_list(JCR *jcr);
extern int send_bootstrap_file(JCR *jcr);
extern int get_attributes_and_put_in_catalog(JCR *jcr);
extern int get_attributes_and_compare_to_catalog(JCR *jcr, JobId_t JobId);
extern int put_file_into_catalog(JCR *jcr, long file_index, char *fname,
- char *link, char *attr, int stream);
+ char *link, char *attr, int stream);
extern void get_level_since_time(JCR *jcr, char *since, int since_len);
extern int send_run_before_and_after_commands(JCR *jcr);
extern void mount_request(JCR *jcr, BSOCK *bs, char *buf);
/* msgchan.c */
-extern int connect_to_storage_daemon(JCR *jcr, int retry_interval,
- int max_retry_time, int verbose);
+extern bool connect_to_storage_daemon(JCR *jcr, int retry_interval,
+ int max_retry_time, int verbose);
extern int start_storage_daemon_job(JCR *jcr);
extern int start_storage_daemon_message_thread(JCR *jcr);
extern int bget_dirmsg(BSOCK *bs);
void free_ua_context(UAContext *ua);
/* ua_select.c */
-STORE *select_storage_resource(UAContext *ua);
-JOB *select_job_resource(UAContext *ua);
-JOB *select_restore_job_resource(UAContext *ua);
-CLIENT *select_client_resource(UAContext *ua);
+STORE *select_storage_resource(UAContext *ua);
+JOB *select_job_resource(UAContext *ua);
+JOB *select_restore_job_resource(UAContext *ua);
+CLIENT *select_client_resource(UAContext *ua);
FILESET *select_fileset_resource(UAContext *ua);
-int select_pool_and_media_dbr(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr);
-int select_media_dbr(UAContext *ua, MEDIA_DBR *mr);
-bool select_pool_dbr(UAContext *ua, POOL_DBR *pr);
-int select_client_dbr(UAContext *ua, CLIENT_DBR *cr);
-
-void start_prompt(UAContext *ua, const char *msg);
-void add_prompt(UAContext *ua, const char *prompt);
-int do_prompt(UAContext *ua, const char *automsg, const char *msg, char *prompt, int max_prompt);
-CAT *get_catalog_resource(UAContext *ua);
+int select_pool_and_media_dbr(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr);
+int select_media_dbr(UAContext *ua, MEDIA_DBR *mr);
+bool select_pool_dbr(UAContext *ua, POOL_DBR *pr);
+int select_client_dbr(UAContext *ua, CLIENT_DBR *cr);
+
+void start_prompt(UAContext *ua, const char *msg);
+void add_prompt(UAContext *ua, const char *prompt);
+int do_prompt(UAContext *ua, const char *automsg, const char *msg, char *prompt, int max_prompt);
+CAT *get_catalog_resource(UAContext *ua);
STORE *get_storage_resource(UAContext *ua, int use_default);
-int get_media_type(UAContext *ua, char *MediaType, int max_media);
-bool get_pool_dbr(UAContext *ua, POOL_DBR *pr);
-int get_client_dbr(UAContext *ua, CLIENT_DBR *cr);
+int get_media_type(UAContext *ua, char *MediaType, int max_media);
+bool get_pool_dbr(UAContext *ua, POOL_DBR *pr);
+int get_client_dbr(UAContext *ua, CLIENT_DBR *cr);
POOL *get_pool_resource(UAContext *ua);
POOL *select_pool_resource(UAContext *ua);
CLIENT *get_client_resource(UAContext *ua);
-int get_job_dbr(UAContext *ua, JOB_DBR *jr);
+int get_job_dbr(UAContext *ua, JOB_DBR *jr);
int find_arg_keyword(UAContext *ua, const char **list);
int find_arg(UAContext *ua, const char *keyword);
jcr->VolumeName[0] = 0;
if (!db_get_job_volume_names(jcr, jcr->db, rjr.JobId, &jcr->VolumeName) ||
jcr->VolumeName[0] == 0) {
- Jmsg(jcr, M_FATAL, 0, _("Cannot find Volume Name for restore Job %d. %s"),
+ Jmsg(jcr, M_FATAL, 0, _("Cannot find Volume names for restore Job %d. %s"),
rjr.JobId, db_strerror(jcr->db));
restore_cleanup(jcr, JS_ErrorTerminated);
return 0;
static void do_storage_setdebug(UAContext *ua, STORE *store, int level, int trace_flag)
{
BSOCK *sd;
+ JCR *jcr = ua->jcr;
- ua->jcr->store = store;
+ jcr->store = store;
/* Try connecting for up to 15 seconds */
bsendmsg(ua, _("Connecting to Storage daemon %s at %s:%d\n"),
store->hdr.name, store->address, store->SDport);
- if (!connect_to_storage_daemon(ua->jcr, 1, 15, 0)) {
+ if (!connect_to_storage_daemon(jcr, 1, 15, 0)) {
bsendmsg(ua, _("Failed to connect to Storage daemon.\n"));
return;
}
Dmsg0(120, _("Connected to storage daemon\n"));
- sd = ua->jcr->store_bsock;
+ sd = jcr->store_bsock;
bnet_fsend(sd, "setdebug=%d trace=%d\n", level, trace_flag);
if (bnet_recv(sd) >= 0) {
bsendmsg(ua, "%s", sd->msg);
}
bnet_sig(sd, BNET_TERMINATE);
bnet_close(sd);
- ua->jcr->store_bsock = NULL;
+ jcr->store_bsock = NULL;
return;
}
{
STORE *store;
BSOCK *sd;
+ JCR *jcr = ua->jcr;
char dev_name[MAX_NAME_LENGTH];
-
if (!open_db(ua)) {
return;
}
Dmsg2(120, "Found storage, MediaType=%s DevName=%s\n",
store->media_type, store->dev_name);
- ua->jcr->store = store;
- if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
+ jcr->store = store;
+ if (!connect_to_storage_daemon(jcr, 10, SDConnectTimeout, 1)) {
bsendmsg(ua, _("Failed to connect to Storage daemon.\n"));
return;
}
- sd = ua->jcr->store_bsock;
- strcpy(dev_name, store->dev_name);
+ sd = jcr->store_bsock;
+ bstrncpy(dev_name, store->dev_name, sizeof(dev_name));
bash_spaces(dev_name);
bnet_fsend(sd, "%s %s", command, dev_name);
while (bnet_recv(sd) >= 0) {
}
bnet_sig(sd, BNET_TERMINATE);
bnet_close(sd);
- ua->jcr->store_bsock = NULL;
+ jcr->store_bsock = NULL;
}
/*
Dmsg0(150, "Open database\n");
ua->db = db_init_database(ua->jcr, ua->catalog->db_name, ua->catalog->db_user,
ua->catalog->db_password, ua->catalog->db_address,
- ua->catalog->db_port, ua->catalog->db_socket);
+ ua->catalog->db_port, ua->catalog->db_socket,
+ ua->catalog->mult_db_connections);
if (!ua->db || !db_open_database(ua->jcr, ua->db)) {
bsendmsg(ua, _("Could not open database \"%s\".\n"),
ua->catalog->db_name);
if (ua->argc == 2 && strcmp(ua->argk[1], "job") == 0) {
job = (JOB *)GetResWithName(R_JOB, ua->argv[1]);
if (job) {
+ STORE *store;
bsendmsg(ua, "job=%s", job->hdr.name);
bsendmsg(ua, "pool=%s", job->pool->hdr.name);
bsendmsg(ua, "messages=%s", job->messages->hdr.name);
bsendmsg(ua, "client=%s", job->client->hdr.name);
- bsendmsg(ua, "storage=%s", job->storage->hdr.name);
+ store = (STORE *)job->storage[0]->first();
+ bsendmsg(ua, "storage=%s", store->hdr.name);
bsendmsg(ua, "where=%s", job->RestoreWhere?job->RestoreWhere:"");
- bsendmsg(ua, "level=%s", level_to_str(job->level));
+ bsendmsg(ua, "level=%s", level_to_str(job->JobLevel));
bsendmsg(ua, "type=%s", job_type_to_str(job->JobType));
bsendmsg(ua, "fileset=%s", job->fileset->hdr.name);
}
}
jcr->db = jcr->db=db_init_database(jcr, jcr->catalog->db_name, jcr->catalog->db_user,
jcr->catalog->db_password, jcr->catalog->db_address,
- jcr->catalog->db_port, jcr->catalog->db_socket);
+ jcr->catalog->db_port, jcr->catalog->db_socket,
+ jcr->catalog->mult_db_connections);
if (!jcr->db || !db_open_database(jcr, jcr->db)) {
Jmsg(jcr, M_FATAL, 0, _("Could not open database \"%s\".\n"),
jcr->catalog->db_name);
}
if (!job) {
return 1;
+ } else if (!acl_access_ok(ua, Job_ACL, job->hdr.name)) {
+ bsendmsg(ua, _("No authorization. Job \"%s\".\n"),
+ job->hdr.name);
+ return 1;
}
if (store_name) {
store = select_storage_resource(ua);
}
} else {
- store = job->storage; /* use default */
+ store = (STORE *)job->storage[0]->first(); /* use default */
}
if (!store) {
return 1;
+ } else if (!acl_access_ok(ua, Storage_ACL, store->hdr.name)) {
+ bsendmsg(ua, _("No authorization. Storage \"%s\".\n"),
+ store->hdr.name);
+ return 1;
}
-
if (pool_name) {
pool = (POOL *)GetResWithName(R_POOL, pool_name);
if (!pool) {
}
if (!pool) {
return 1;
+ } else if (!acl_access_ok(ua, Pool_ACL, store->hdr.name)) {
+ bsendmsg(ua, _("No authorization. Pool \"%s\".\n"),
+ pool->hdr.name);
+ return 1;
}
if (client_name) {
}
if (!client) {
return 1;
+ } else if (!acl_access_ok(ua, Client_ACL, store->hdr.name)) {
+ bsendmsg(ua, _("No authorization. Client \"%s\".\n"),
+ client->hdr.name);
+ return 1;
}
if (fileset_name) {
}
if (!fileset) {
return 1;
+ } else if (!acl_access_ok(ua, FileSet_ACL, store->hdr.name)) {
+ bsendmsg(ua, _("No authorization. FileSet \"%s\".\n"),
+ fileset->hdr.name);
+ return 1;
}
if (verify_job_name) {
if (Priority) {
jcr->JobPriority = Priority;
}
+
+ if (find_arg(ua, _("fdcalled")) > 0) {
+ jcr->file_bsock = dup_bsock(ua->UA_sock);
+ ua->quit = true;
+ }
try_again:
replace = ReplaceOptions[0].name;
bnet_sig(ua->UA_sock, BNET_EOD); /* send end of command */
}
} else if (is_bnet_stop(ua->UA_sock)) {
- ua->quit = TRUE;
- break;
+ ua->quit = true;
} else { /* signal */
bnet_sig(ua->UA_sock, BNET_POLL);
}
}
getout:
-
close_db(ua);
free_ua_context(ua);
free_jcr(jcr);
bsendmsg(ua, OKqstatus, ua->argk[2]);
lock_jcr_chain();
foreach_jcr(njcr) {
- if (njcr->JobId != 0) {
- bsendmsg(ua, DotStatusJob, njcr->JobId, njcr->JobStatus, njcr->JobErrors);
- }
- free_locked_jcr(njcr);
+ if (njcr->JobId != 0) {
+ bsendmsg(ua, DotStatusJob, njcr->JobId, njcr->JobStatus, njcr->JobErrors);
+ }
+ free_locked_jcr(njcr);
}
unlock_jcr_chain();
}
else if (strcasecmp(ua->argk[2], "last") == 0) {
bsendmsg(ua, OKqstatus, ua->argk[2]);
if ((last_jobs) && (last_jobs->size() > 0)) {
- job = (s_last_job*)last_jobs->last();
- bsendmsg(ua, DotStatusJob, job->JobId, job->JobStatus, job->Errors);
+ job = (s_last_job*)last_jobs->last();
+ bsendmsg(ua, DotStatusJob, job->JobId, job->JobStatus, job->Errors);
}
}
else {
continue;
}
for (run=NULL; (run = find_next_run(run, job, runtime)); ) {
- level = job->level;
+ level = job->JobLevel;
if (run->level) {
level = run->level;
}
case JS_Terminated:
term_msg = _("Verify OK");
break;
+ case JS_FatalError:
case JS_ErrorTerminated:
term_msg = _("*** Verify Error ***");
msg_type = M_ERROR; /* Generate error message */
break;
+ case JS_Error:
+ term_msg = _("Verify warnings");
+ break;
case JS_Canceled:
term_msg = _("Verify Canceled");
break;
}
/* return non-zero if path is absolute or zero if relative. */
-
int
isAbsolute(const char *path)
{
{
const char *p;
+ /*
+ * ***NB*** this removes the drive from the exclude
+ * rule. Why?????
+ */
if (win32_client && file[1] == ':') {
file += 2;
}
#define JT_CONSOLE 'C' /* console program */
#define JT_SYSTEM 'S' /* internal system "job" */
#define JT_ADMIN 'D' /* admin job */
-#define JT_ARCHIVE 'A'
+#define JT_ARCHIVE 'A' /* Archive Job */
+#define JT_COPY 'Y' /* Copy Job */
+#define JT_MIGRATION 'M' /* Migration Job */
/* Job Status. Some of these are stored in the DB */
#define JS_Created 'C' /* created but not yet running */
dlist *msg_queue; /* Queued messages */
alist job_end_push; /* Job end pushed calls */
bool dequeuing; /* dequeuing messages */
+ POOLMEM *VolumeName; /* Volume name desired -- pool_memory */
POOLMEM *errmsg; /* edited error message */
char Job[MAX_NAME_LENGTH]; /* Unique name of this Job */
uint32_t JobId; /* Director's JobId */
time_t start_time; /* when job actually started */
time_t run_time; /* used for computing speed */
time_t end_time; /* job end time */
- POOLMEM *VolumeName; /* Volume name desired -- pool_memory */
POOLMEM *client_name; /* client name */
POOLMEM *RestoreBootstrap; /* Bootstrap file to restore */
char *sd_auth_key; /* SD auth key */
/* This should be empty in the library */
#ifdef DIRECTOR_DAEMON
+#define MAX_STORE 2
/* Director Daemon specific part of JCR */
pthread_t SD_msg_chan; /* Message channel thread id */
pthread_cond_t term_wait; /* Wait for job termination */
volatile bool sd_msg_thread_done; /* Set when Storage message thread terms */
BSOCK *ua; /* User agent */
JOB *job; /* Job resource */
- STORE *store; /* Storage resource */
+ alist *storage[MAX_STORE]; /* Storage possibilities */
+ STORE *store; /* Storage daemon selected */
CLIENT *client; /* Client resource */
POOL *pool; /* Pool resource */
POOL *full_pool; /* Full backup pool resource */
int type;
DCR *dcr; /* device context record */
DEVRES *device; /* device resource to use */
- VOLUME_CAT_INFO VolCatInfo; /* Catalog info for desired volume */
POOLMEM *job_name; /* base Job name (not unique) */
POOLMEM *fileset_name; /* FileSet */
POOLMEM *fileset_md5; /* MD5 for FileSet */
- POOLMEM *pool_name; /* pool to use */
- POOLMEM *pool_type; /* pool type to use */
- POOLMEM *media_type; /* media type */
- POOLMEM *dev_name; /* device name */
VOL_LIST *VolList; /* list to read */
int32_t NumVolumes; /* number of volumes used */
int32_t CurVolume; /* current volume number */
- int label_status; /* device volume label status */
int label_errors; /* count of label errors */
bool session_opened;
long Ticket; /* ticket for this job */
attr->lname = p; /* set link position */
while (*p++ != 0) /* skip link */
{ }
- pm_strcpy(&attr->attrEx, p); /* copy extended attributes, if any */
+ pm_strcpy(attr->attrEx, p); /* copy extended attributes, if any */
if (attr->data_stream) {
int64_t val;
* files are put where the user wants.
*
* We do a little jig here to handle Win32 files with
- * a drive letter -- we simply strip the drive: from
+ * a drive letter -- we simply change the drive
+ * from, for example, c: to c/ for
* every filename if a prefix is supplied.
*
*/
if (jcr->where[0] == 0) {
- pm_strcpy(&attr->ofname, attr->fname);
- pm_strcpy(&attr->olname, attr->lname);
+ pm_strcpy(attr->ofname, attr->fname);
+ pm_strcpy(attr->olname, attr->lname);
} else {
const char *fn;
int wherelen = strlen(jcr->where);
- pm_strcpy(&attr->ofname, jcr->where); /* copy prefix */
+ pm_strcpy(attr->ofname, jcr->where); /* copy prefix */
if (win32_client && attr->fname[1] == ':') {
- fn = attr->fname+2; /* skip over drive: */
- } else {
- fn = attr->fname; /* take whole name */
+ attr->fname[1] = '/'; /* convert : to / */
}
+ fn = attr->fname; /* take whole name */
/* Ensure where is terminated with a slash */
if (jcr->where[wherelen-1] != '/' && fn[0] != '/') {
- pm_strcat(&attr->ofname, "/");
+ pm_strcat(attr->ofname, "/");
}
- pm_strcat(&attr->ofname, fn); /* copy rest of name */
+ pm_strcat(attr->ofname, fn); /* copy rest of name */
/*
* Fixup link name -- if it is an absolute path
*/
*/
if (attr->lname[0] == '/' &&
(attr->type == FT_LNKSAVED || jcr->prefix_links)) {
- pm_strcpy(&attr->olname, jcr->where);
+ pm_strcpy(attr->olname, jcr->where);
add_link = true;
} else {
mp_chr(attr->olname)[0] = 0;
add_link = false;
}
if (win32_client && attr->lname[1] == ':') {
- fn = attr->lname+2; /* skip over drive: */
- } else {
- fn = attr->lname; /* take whole name */
+ attr->lname[1] = '/'; /* turn : into / */
}
+ fn = attr->lname; /* take whole name */
/* Ensure where is terminated with a slash */
if (add_link && jcr->where[wherelen-1] != '/' && fn[0] != '/') {
- pm_strcat(&attr->olname, "/");
+ pm_strcat(attr->olname, "/");
}
- pm_strcat(&attr->olname, fn); /* copy rest of link */
+ pm_strcat(attr->olname, fn); /* copy rest of link */
}
}
}
* If bit 29 in berrno_ is set then it is a Win32 error, and we
* must to a GetLastError() to get the error code for formatting.
* If bit 29 in berrno_ is not set, then it is a Unix errno.
+ *
*/
class berrno : public SMARTALLOC {
POOLMEM *buf_;
return dest;
}
+/*
+ * Guarantee that the string is properly terminated */
+char *bstrncpy(char *dest, POOL_MEM &src, int maxlen)
+{
+ strncpy(dest, src.c_str(), maxlen-1);
+ dest[maxlen-1] = 0;
+ return dest;
+}
+
+
char *bstrncat(char *dest, const char *src, int maxlen)
{
strncat(dest, src, maxlen-1);
return dest;
}
+char *bstrncat(char *dest, POOL_MEM &src, int maxlen)
+{
+ strncat(dest, src.c_str(), maxlen-1);
+ dest[maxlen-1] = 0;
+ return dest;
+}
+
+
#ifndef DEBUG
void *bmalloc(size_t size)
int i;
pid_t cpid;
mode_t oldmask;
+#ifdef DEVELOPER
+ int low_fd = 2;
+#else
int low_fd = -1;
+#endif
/*
* Become a daemon.
*/
*/
/*
- Copyright (C) 2000-2004 Kern Sibbald and John Walker
+ Copyright (C) 2004 Kern Sibbald and John Walker
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
*
* Doubly linked list -- dlist
*
+ * Kern Sibbald, MMIV
+ *
*/
#define M_ABORT 1
#else
void print_memory_pool_stats() {}
#endif /* DEBUG */
+
+/*
+ * Concatenate a string (str) onto a pool memory buffer pm
+ * Returns: length of concatenated string
+ */
+int pm_strcat(POOLMEM **pm, const char *str)
+{
+ int pmlen = strlen(*pm);
+ int len = strlen(str) + 1;
+
+ *pm = check_pool_memory_size(*pm, pmlen + len);
+ memcpy(*pm+pmlen, str, len);
+ return pmlen + len - 1;
+}
+
+int pm_strcat(POOLMEM *&pm, const char *str)
+{
+ int pmlen = strlen(pm);
+ int len = strlen(str) + 1;
+
+ pm = check_pool_memory_size(pm, pmlen + len);
+ memcpy(pm+pmlen, str, len);
+ return pmlen + len - 1;
+}
+
+
+int pm_strcat(POOLMEM *&pm, POOL_MEM &str)
+{
+ int pmlen = strlen(pm);
+ int len = strlen(str.c_str()) + 1;
+
+ pm = check_pool_memory_size(pm, pmlen + len);
+ memcpy(pm+pmlen, str.c_str(), len);
+ return pmlen + len - 1;
+}
+
+int pm_strcat(POOL_MEM &pm, const char *str)
+{
+ int pmlen = strlen(pm.c_str());
+ int len = strlen(str) + 1;
+
+ pm.check_size(pmlen + len);
+ memcpy(pm.c_str()+pmlen, str, len);
+ return pmlen + len - 1;
+}
+
+
+/*
+ * Copy a string (str) into a pool memory buffer pm
+ * Returns: length of string copied
+ */
+int pm_strcpy(POOLMEM **pm, const char *str)
+{
+ int len = strlen(str) + 1;
+
+ *pm = check_pool_memory_size(*pm, len);
+ memcpy(*pm, str, len);
+ return len - 1;
+}
+
+int pm_strcpy(POOLMEM *&pm, const char *str)
+{
+ int len = strlen(str) + 1;
+
+ pm = check_pool_memory_size(pm, len);
+ memcpy(pm, str, len);
+ return len - 1;
+}
+
+int pm_strcpy(POOLMEM *&pm, POOL_MEM &str)
+{
+ int len = strlen(str.c_str()) + 1;
+
+ pm = check_pool_memory_size(pm, len);
+ memcpy(pm, str.c_str(), len);
+ return len - 1;
+}
+
+
+int pm_strcpy(POOL_MEM &pm, const char *str)
+{
+ int len = strlen(str) + 1;
+ pm.check_size(len);
+ memcpy(pm.c_str(), str, len);
+ return len - 1;
+}
+
+int POOL_MEM::strcat(const char *str)
+{
+ int pmlen = strlen(mem);
+ int len = strlen(str) + 1;
+
+ check_size(pmlen + len);
+ memcpy(mem+pmlen, str, len);
+ return pmlen + len - 1;
+}
+
+
+int POOL_MEM::strcpy(const char *str)
+{
+ int len = strlen(str) + 1;
+ check_size(len);
+ memcpy(mem, str, len);
+ return len - 1;
+}
/*
* Memory Pool prototypes
*
- * Kern Sibbald, 2000
+ * Kern Sibbald, MM
*
* Version $Id$
*/
/*
- Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
+ Copyright (C) 2000-2004 Kern Sibbald and John Walker
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
extern void close_memory_pool();
extern void print_memory_pool_stats();
+
+
#define PM_NOPOOL 0 /* nonpooled memory */
#define PM_NAME 1 /* Bacula name */
#define PM_FNAME 2 /* file name buffer */
#define PM_EMSG 4 /* error message */
#define PM_MAX PM_EMSG /* Number of types */
+class POOL_MEM {
+ char *mem;
+public:
+ POOL_MEM() { mem = get_pool_memory(PM_NAME); *mem = 0; }
+ POOL_MEM(int pool) { mem = get_pool_memory(pool); *mem = 0; }
+ ~POOL_MEM() { free_pool_memory(mem); mem = NULL; }
+ char *c_str() const { return mem; }
+ int size() const { return sizeof_pool_memory(mem); }
+ char *check_size(int32_t size) {
+ mem = check_pool_memory_size(mem, size);
+ return mem;
+ }
+ int strcpy(const char *str);
+ int strcat(const char *str);
+};
+
+int pm_strcat (POOLMEM **pm, const char *str);
+int pm_strcat (POOLMEM *&pm, const char *str);
+int pm_strcat (POOL_MEM &pm, const char *str);
+int pm_strcat (POOLMEM *&pm, POOL_MEM &str);
+int pm_strcpy (POOLMEM **pm, const char *str);
+int pm_strcpy (POOLMEM *&pm, const char *str);
+int pm_strcpy (POOL_MEM &pm, const char *str);
+int pm_strcpy (POOLMEM *&pm, POOL_MEM &str);
+
+
#endif
* lib/parse_conf.h.
* These files contain the parser code, some utility
* routines, and the common store routines (name, int,
- * string).
+ * string, time, int64, size, ...).
*
* 3. The daemon specific file, which contains the Resource
* definitions as well as any specific store routines
lex_get_token(lc, T_NAME);
if (pass == 2) {
- res = GetResWithName(item->code, lc->str);
- if (res == NULL) {
- scan_err3(lc, _("Could not find config Resource %s referenced on line %d : %s\n"),
- lc->str, lc->line_no, lc->line);
- }
- if (*(item->value)) {
- scan_err3(lc, _("Attempt to redefine resource \"%s\" referenced on line %d : %s\n"),
- lc->str, lc->line_no, lc->line);
- }
- *(item->value) = (char *)res;
+ res = GetResWithName(item->code, lc->str);
+ if (res == NULL) {
+ scan_err3(lc, _("Could not find config Resource %s referenced on line %d : %s\n"),
+ lc->str, lc->line_no, lc->line);
+ }
+ if (*(item->value)) {
+ scan_err3(lc, _("Attempt to redefine resource \"%s\" referenced on line %d : %s\n"),
+ item->name, lc->line_no, lc->line);
+ }
+ *(item->value) = (char *)res;
}
scan_to_eol(lc);
set_bit(index, res_all.hdr.item_present);
}
+/*
+ * Store a resource in an alist. default_value indicates how many
+ * times this routine can be called -- i.e. how many alists
+ * there are.
+ * If we are in pass 2, do a lookup of the
+ * resource.
+ */
+void store_alist_res(LEX *lc, RES_ITEM *item, int index, int pass)
+{
+ RES *res;
+ int count = item->default_value;
+ int i = 0;
+ alist *list;
+
+ if (pass == 2) {
+ /* Find empty place to store this directive */
+ while ((item->value)[i] != NULL && i++ < count) { }
+ if (i >= count) {
+ scan_err3(lc, _("Too many Storage directives. Max. is %d. line %d: %s\n"),
+ count, lc->line_no, lc->line);
+ }
+ list = New(alist(10, not_owned_by_alist));
+
+ for (;;) {
+ lex_get_token(lc, T_NAME); /* scan next item */
+ res = GetResWithName(item->code, lc->str);
+ if (res == NULL) {
+ scan_err3(lc, _("Could not find config Resource \"%s\" referenced on line %d : %s\n"),
+ lc->str, lc->line_no, lc->line);
+ }
+ list->append(res);
+ (item->value)[i] = (char *)list;
+ if (lc->ch != ',') { /* if no other item follows */
+ break; /* get out */
+ }
+ lex_get_token(lc, T_ALL); /* eat comma */
+ }
+ }
+ scan_to_eol(lc);
+ set_bit(index, res_all.hdr.item_present);
+}
+
+
/*
* Store default values for Resource from xxxDefs
* If we are in pass 2, do a lookup of the
void store_name(LEX *lc, RES_ITEM *item, int index, int pass);
void store_strname(LEX *lc, RES_ITEM *item, int index, int pass);
void store_res(LEX *lc, RES_ITEM *item, int index, int pass);
+void store_alist_res(LEX *lc, RES_ITEM *item, int index, int pass);
void store_int(LEX *lc, RES_ITEM *item, int index, int pass);
void store_pint(LEX *lc, RES_ITEM *item, int index, int pass);
void store_msgs(LEX *lc, RES_ITEM *item, int index, int pass);
struct JCR;
/* attr.c */
-ATTR *new_attr();
-void free_attr(ATTR *attr);
-int unpack_attributes_record(JCR *jcr, int32_t stream, char *rec, ATTR *attr);
-void build_attr_output_fnames(JCR *jcr, ATTR *attr);
-void print_ls_output(JCR *jcr, ATTR *attr);
+ATTR *new_attr();
+void free_attr(ATTR *attr);
+int unpack_attributes_record(JCR *jcr, int32_t stream, char *rec, ATTR *attr);
+void build_attr_output_fnames(JCR *jcr, ATTR *attr);
+void print_ls_output(JCR *jcr, ATTR *attr);
/* base64.c */
-void base64_init (void);
-int to_base64 (intmax_t value, char *where);
-int from_base64 (intmax_t *value, char *where);
-int bin_to_base64 (char *buf, char *bin, int len);
+void base64_init (void);
+int to_base64 (intmax_t value, char *where);
+int from_base64 (intmax_t *value, char *where);
+int bin_to_base64 (char *buf, char *bin, int len);
/* bsys.c */
-char *bstrncpy (char *dest, const char *src, int maxlen);
-char *bstrncat (char *dest, const char *src, int maxlen);
-void *b_malloc (const char *file, int line, size_t size);
+char *bstrncpy (char *dest, const char *src, int maxlen);
+char *bstrncpy (char *dest, POOL_MEM &src, int maxlen);
+char *bstrncat (char *dest, const char *src, int maxlen);
+char *bstrncat (char *dest, POOL_MEM &src, int maxlen);
+void *b_malloc (const char *file, int line, size_t size);
#ifndef DEBUG
-void *bmalloc (size_t size);
+void *bmalloc (size_t size);
#endif
-void *brealloc (void *buf, size_t size);
-void *bcalloc (size_t size1, size_t size2);
-int bsnprintf (char *str, int32_t size, const char *format, ...);
-int bvsnprintf (char *str, int32_t size, const char *format, va_list ap);
-int pool_sprintf (char *pool_buf, const char *fmt, ...);
-void create_pid_file (char *dir, const char *progname, int port);
-int delete_pid_file (char *dir, const char *progname, int port);
-void drop (char *uid, char *gid);
-int bmicrosleep (time_t sec, long usec);
-char *bfgets (char *s, int size, FILE *fd);
-void make_unique_filename (POOLMEM **name, int Id, char *what);
+void *brealloc (void *buf, size_t size);
+void *bcalloc (size_t size1, size_t size2);
+int bsnprintf (char *str, int32_t size, const char *format, ...);
+int bvsnprintf (char *str, int32_t size, const char *format, va_list ap);
+int pool_sprintf (char *pool_buf, const char *fmt, ...);
+void create_pid_file (char *dir, const char *progname, int port);
+int delete_pid_file (char *dir, const char *progname, int port);
+void drop (char *uid, char *gid);
+int bmicrosleep (time_t sec, long usec);
+char *bfgets (char *s, int size, FILE *fd);
+void make_unique_filename (POOLMEM **name, int Id, char *what);
#ifndef HAVE_STRTOLL
-long long int strtoll (const char *ptr, char **endptr, int base);
+long long int strtoll (const char *ptr, char **endptr, int base);
#endif
-void read_state_file(char *dir, const char *progname, int port);
-int bstrerror(int errnum, char *buf, size_t bufsiz);
+void read_state_file(char *dir, const char *progname, int port);
+int bstrerror(int errnum, char *buf, size_t bufsiz);
/* bnet.c */
-int32_t bnet_recv (BSOCK *bsock);
-bool bnet_send (BSOCK *bsock);
-bool bnet_fsend (BSOCK *bs, const char *fmt, ...);
-bool bnet_set_buffer_size (BSOCK *bs, uint32_t size, int rw);
-bool bnet_sig (BSOCK *bs, int sig);
-int bnet_ssl_server (BSOCK *bsock, char *password, int ssl_need, int ssl_has);
-int bnet_ssl_client (BSOCK *bsock, char *password, int ssl_need);
-BSOCK * bnet_connect (JCR *jcr, int retry_interval,
- int max_retry_time, const char *name, char *host, char *service,
- int port, int verbose);
-void bnet_close (BSOCK *bsock);
-BSOCK * init_bsock (JCR *jcr, int sockfd, const char *who, const char *ip,
- int port, struct sockaddr *client_addr);
-BSOCK * dup_bsock (BSOCK *bsock);
-void term_bsock (BSOCK *bsock);
-char * bnet_strerror (BSOCK *bsock);
-const char *bnet_sig_to_ascii (BSOCK *bsock);
-int bnet_wait_data (BSOCK *bsock, int sec);
-int bnet_wait_data_intr (BSOCK *bsock, int sec);
-int bnet_despool_to_bsock (BSOCK *bsock, void update(ssize_t size), ssize_t size);
-bool is_bnet_stop (BSOCK *bsock);
-int is_bnet_error (BSOCK *bsock);
-void bnet_suppress_error_messages(BSOCK *bsock, bool flag);
+int32_t bnet_recv (BSOCK *bsock);
+bool bnet_send (BSOCK *bsock);
+bool bnet_fsend (BSOCK *bs, const char *fmt, ...);
+bool bnet_set_buffer_size (BSOCK *bs, uint32_t size, int rw);
+bool bnet_sig (BSOCK *bs, int sig);
+int bnet_ssl_server (BSOCK *bsock, char *password, int ssl_need, int ssl_has);
+int bnet_ssl_client (BSOCK *bsock, char *password, int ssl_need);
+BSOCK * bnet_connect (JCR *jcr, int retry_interval,
+ int max_retry_time, const char *name, char *host, char *service,
+ int port, int verbose);
+void bnet_close (BSOCK *bsock);
+BSOCK * init_bsock (JCR *jcr, int sockfd, const char *who, const char *ip,
+ int port, struct sockaddr *client_addr);
+BSOCK * dup_bsock (BSOCK *bsock);
+void term_bsock (BSOCK *bsock);
+char * bnet_strerror (BSOCK *bsock);
+const char *bnet_sig_to_ascii (BSOCK *bsock);
+int bnet_wait_data (BSOCK *bsock, int sec);
+int bnet_wait_data_intr (BSOCK *bsock, int sec);
+int bnet_despool_to_bsock (BSOCK *bsock, void update(ssize_t size), ssize_t size);
+bool is_bnet_stop (BSOCK *bsock);
+int is_bnet_error (BSOCK *bsock);
+void bnet_suppress_error_messages(BSOCK *bsock, bool flag);
dlist *bnet_host2ipaddrs(const char *host, int family, const char **errstr);
/* bget_msg.c */
-int bget_msg(BSOCK *sock);
+int bget_msg(BSOCK *sock);
/* bpipe.c */
-BPIPE * open_bpipe(char *prog, int wait, const char *mode);
-int close_wpipe(BPIPE *bpipe);
-int close_bpipe(BPIPE *bpipe);
+BPIPE * open_bpipe(char *prog, int wait, const char *mode);
+int close_wpipe(BPIPE *bpipe);
+int close_bpipe(BPIPE *bpipe);
/* cram-md5.c */
int cram_md5_get_auth(BSOCK *bs, char *password, int ssl_need);
int cram_md5_auth(BSOCK *bs, char *password, int ssl_need);
void hmac_md5(uint8_t* text, int text_len, uint8_t* key,
- int key_len, uint8_t *hmac);
+ int key_len, uint8_t *hmac);
/* crc32.c */
uint32_t bcrc32(uint8_t *buf, int len);
/* daemon.c */
-void daemon_start ();
+void daemon_start ();
/* edit.c */
-uint64_t str_to_uint64(char *str);
-int64_t str_to_int64(char *str);
-char * edit_uint64_with_commas (uint64_t val, char *buf);
-char * add_commas (char *val, char *buf);
-char * edit_uint64 (uint64_t val, char *buf);
-int duration_to_utime (char *str, utime_t *value);
-int size_to_uint64(char *str, int str_len, uint64_t *rtn_value);
-char *edit_utime (utime_t val, char *buf, int buf_len);
-bool is_a_number (const char *num);
-bool is_an_integer (const char *n);
-bool is_name_valid (char *name, POOLMEM **msg);
+uint64_t str_to_uint64(char *str);
+int64_t str_to_int64(char *str);
+char * edit_uint64_with_commas (uint64_t val, char *buf);
+char * add_commas (char *val, char *buf);
+char * edit_uint64 (uint64_t val, char *buf);
+int duration_to_utime (char *str, utime_t *value);
+int size_to_uint64(char *str, int str_len, uint64_t *rtn_value);
+char *edit_utime (utime_t val, char *buf, int buf_len);
+bool is_a_number (const char *num);
+bool is_an_integer (const char *n);
+bool is_name_valid (char *name, POOLMEM **msg);
/* jcr.c (most definitions are in src/jcr.h) */
void init_last_jobs_list();
/* lex.c */
-LEX * lex_close_file (LEX *lf);
-LEX * lex_open_file (LEX *lf, const char *fname, LEX_ERROR_HANDLER *scan_error);
-int lex_get_char (LEX *lf);
-void lex_unget_char (LEX *lf);
-const char * lex_tok_to_str (int token);
-int lex_get_token (LEX *lf, int expect);
+LEX * lex_close_file (LEX *lf);
+LEX * lex_open_file (LEX *lf, const char *fname, LEX_ERROR_HANDLER *scan_error);
+int lex_get_char (LEX *lf);
+void lex_unget_char (LEX *lf);
+const char * lex_tok_to_str (int token);
+int lex_get_token (LEX *lf, int expect);
/* message.c */
-void my_name_is (int argc, char *argv[], const char *name);
-void init_msg (JCR *jcr, MSGS *msg);
-void term_msg (void);
-void close_msg (JCR *jcr);
-void add_msg_dest (MSGS *msg, int dest, int type, char *where, char *dest_code);
-void rem_msg_dest (MSGS *msg, int dest, int type, char *where);
-void Jmsg (JCR *jcr, int type, int level, const char *fmt, ...);
-void dispatch_message (JCR *jcr, int type, int level, char *buf);
-void init_console_msg (const char *wd);
-void free_msgs_res (MSGS *msgs);
-void dequeue_messages (JCR *jcr);
-void set_trace (int trace_flag);
-void set_exit_on_error (int value);
+void my_name_is (int argc, char *argv[], const char *name);
+void init_msg (JCR *jcr, MSGS *msg);
+void term_msg (void);
+void close_msg (JCR *jcr);
+void add_msg_dest (MSGS *msg, int dest, int type, char *where, char *dest_code);
+void rem_msg_dest (MSGS *msg, int dest, int type, char *where);
+void Jmsg (JCR *jcr, int type, int level, const char *fmt, ...);
+void dispatch_message (JCR *jcr, int type, int level, char *buf);
+void init_console_msg (const char *wd);
+void free_msgs_res (MSGS *msgs);
+void dequeue_messages (JCR *jcr);
+void set_trace (int trace_flag);
+void set_exit_on_error (int value);
/* bnet_server.c */
-void bnet_thread_server(dlist *addr, int max_clients, workq_t *client_wq,
- void *handle_client_request(void *bsock));
-void bnet_stop_thread_server(pthread_t tid);
-void bnet_server (int port, void handle_client_request(BSOCK *bsock));
-int net_connect (int port);
-BSOCK * bnet_bind (int port);
-BSOCK * bnet_accept (BSOCK *bsock, char *who);
+void bnet_thread_server(dlist *addr, int max_clients, workq_t *client_wq,
+ void *handle_client_request(void *bsock));
+void bnet_stop_thread_server(pthread_t tid);
+void bnet_server (int port, void handle_client_request(BSOCK *bsock));
+int net_connect (int port);
+BSOCK * bnet_bind (int port);
+BSOCK * bnet_accept (BSOCK *bsock, char *who);
/* idcache.c */
char *getuser(uid_t uid);
/* signal.c */
-void init_signals (void terminate(int sig));
-void init_stack_dump (void);
+void init_signals (void terminate(int sig));
+void init_stack_dump (void);
/* scan.c */
-void strip_trailing_junk (char *str);
-void strip_trailing_slashes (char *dir);
-bool skip_spaces (char **msg);
-bool skip_nonspaces (char **msg);
-int fstrsch (const char *a, const char *b);
-char *next_arg(char **s);
-int parse_args(POOLMEM *cmd, POOLMEM **args, int *argc,
- char **argk, char **argv, int max_args);
-void split_path_and_filename(const char *fname, POOLMEM **path,
- int *pnl, POOLMEM **file, int *fnl);
-int bsscanf(const char *buf, const char *fmt, ...);
+void strip_trailing_junk (char *str);
+void strip_trailing_slashes (char *dir);
+bool skip_spaces (char **msg);
+bool skip_nonspaces (char **msg);
+int fstrsch (const char *a, const char *b);
+char *next_arg(char **s);
+int parse_args(POOLMEM *cmd, POOLMEM **args, int *argc,
+ char **argk, char **argv, int max_args);
+void split_path_and_filename(const char *fname, POOLMEM **path,
+ int *pnl, POOLMEM **file, int *fnl);
+int bsscanf(const char *buf, const char *fmt, ...);
/* util.c */
-int is_buf_zero (char *buf, int len);
-void lcase (char *str);
-void bash_spaces (char *str);
-void unbash_spaces (char *str);
-char * encode_time (time_t time, char *buf);
-char * encode_mode (mode_t mode, char *buf);
-int do_shell_expansion (char *name, int name_len);
-void jobstatus_to_ascii (int JobStatus, char *msg, int maxlen);
-int pm_strcat (POOLMEM **pm, const char *str);
-int pm_strcat (POOLMEM *&pm, const char *str);
-int pm_strcpy (POOLMEM **pm, const char *str);
-int pm_strcpy (POOLMEM *&pm, const char *str);
-int run_program (char *prog, int wait, POOLMEM *results);
-const char * job_type_to_str (int type);
-const char * job_status_to_str (int stat);
-const char * job_level_to_str (int level);
-void make_session_key (char *key, char *seed, int mode);
-POOLMEM *edit_job_codes(JCR *jcr, char *omsg, char *imsg, const char *to);
-void set_working_directory(char *wd);
+int is_buf_zero (char *buf, int len);
+void lcase (char *str);
+void bash_spaces (char *str);
+void bash_spaces (POOL_MEM &pm);
+void unbash_spaces (char *str);
+void unbash_spaces (POOL_MEM &pm);
+char * encode_time (time_t time, char *buf);
+char * encode_mode (mode_t mode, char *buf);
+int do_shell_expansion (char *name, int name_len);
+void jobstatus_to_ascii (int JobStatus, char *msg, int maxlen);
+int run_program (char *prog, int wait, POOLMEM *results);
+const char * job_type_to_str (int type);
+const char * job_status_to_str (int stat);
+const char * job_level_to_str (int level);
+void make_session_key (char *key, char *seed, int mode);
+POOLMEM *edit_job_codes(JCR *jcr, char *omsg, char *imsg, const char *to);
+void set_working_directory(char *wd);
/* watchdog.c */
}
}
+void bash_spaces(POOL_MEM &pm)
+{
+ bash_spaces(pm.c_str());
+}
+
/* Convert non-space characters (0x1) back into spaces */
void
unbash_spaces(char *str)
}
}
+/* Convert non-space characters (0x1) back into spaces */
+void
+unbash_spaces(POOL_MEM &pm)
+{
+ unbash_spaces(pm.c_str());
+}
+
+
char *encode_time(time_t time, char *buf)
{
return buf+n;
}
-/*
- * Concatenate a string (str) onto a pool memory buffer pm
- * Returns: length of concatenated string
- */
-int pm_strcat(POOLMEM **pm, const char *str)
-{
- int pmlen = strlen(*pm);
- int len = strlen(str) + 1;
-
- *pm = check_pool_memory_size(*pm, pmlen + len);
- memcpy(*pm+pmlen, str, len);
- return pmlen + len - 1;
-}
-
-int pm_strcat(POOLMEM *&pm, const char *str)
-{
- int pmlen = strlen(pm);
- int len = strlen(str) + 1;
-
- pm = check_pool_memory_size(pm, pmlen + len);
- memcpy(pm+pmlen, str, len);
- return pmlen + len - 1;
-}
-
-
-
-/*
- * Copy a string (str) into a pool memory buffer pm
- * Returns: length of string copied
- */
-int pm_strcpy(POOLMEM **pm, const char *str)
-{
- int len = strlen(str) + 1;
-
- *pm = check_pool_memory_size(*pm, len);
- memcpy(*pm, str, len);
- return len - 1;
-}
-
-int pm_strcpy(POOLMEM *&pm, const char *str)
-{
- int len = strlen(str) + 1;
-
- pm = check_pool_memory_size(pm, len);
- memcpy(pm, str, len);
- return len - 1;
-}
-
-
-
/*
* only one reader. We read the Volume label from the block and
* leave the block pointers just after the label.
*
- * Returns: 0 if failed for any reason
- * 1 if successful
+ * Returns: NULL if failed for any reason
+ * dcr if successful
*/
DCR *acquire_device_for_read(JCR *jcr)
{
for (i=1; i<jcr->CurVolume; i++) {
vol = vol->next;
}
- pm_strcpy(&jcr->VolumeName, vol->VolumeName);
bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName));
for (i=0; i<5; i++) {
* If it is a tape, it checks the volume name
*/
for ( ; !(dev->state & ST_OPENED); ) {
- Dmsg1(120, "bstored: open vol=%s\n", jcr->VolumeName);
+ Dmsg1(120, "bstored: open vol=%s\n", dcr->VolumeName);
if (open_dev(dev, dcr->VolumeName, OPEN_READ_ONLY) < 0) {
Jmsg(jcr, M_FATAL, 0, _("Open device %s volume %s failed, ERR=%s\n"),
dev_name(dev), dcr->VolumeName, strerror_dev(dev));
*/
dcr->dev->state &= ~ST_LABEL; /* force reread of label */
Dmsg0(200, "calling read-vol-label\n");
- switch (read_dev_volume_label(dcr, dcr->block)) {
+ switch (read_dev_volume_label(dcr)) {
case VOL_OK:
vol_ok = true;
break; /* got it */
if (try_autochanger) {
int stat;
Dmsg2(200, "calling autoload Vol=%s Slot=%d\n",
- jcr->VolumeName, jcr->VolCatInfo.Slot);
+ dcr->VolumeName, dcr->VolCatInfo.Slot);
stat = autoload_device(dcr, 0, NULL);
if (stat > 0) {
try_autochanger = false;
dev->state &= ~ST_APPEND; /* clear any previous append mode */
dev->state |= ST_READ; /* set read mode */
-// attach_jcr_to_device(dev, jcr); /* attach jcr to device */
set_jcr_job_status(jcr, JS_Running);
dir_send_job_status(jcr);
Jmsg(jcr, M_INFO, 0, _("Ready to read from volume \"%s\" on device %s.\n"),
- jcr->VolumeName, dev_name(dev));
+ dcr->VolumeName, dev_name(dev));
get_out:
P(dev->mutex);
* otherwise mount desired volume obtained from
* dir_find_next_appendable_volume
*/
- pm_strcpy(&jcr->VolumeName, dev->VolHdr.VolName);
bstrncpy(dcr->VolumeName, dev->VolHdr.VolName, sizeof(dcr->VolumeName));
if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_WRITE) &&
!(dir_find_next_appendable_volume(dcr) &&
- strcmp(dev->VolHdr.VolName, jcr->VolumeName) == 0)) { /* wrong tape mounted */
+ strcmp(dev->VolHdr.VolName, dcr->VolumeName) == 0)) { /* wrong tape mounted */
if (dev->num_writers != 0) {
DEVICE *d = ((DEVRES *)dev->device)->dev;
uint32_t open_vols = 0;
* we do not need to do mount_next_write_volume(), unless
* we need to recycle the tape.
*/
- recycle = strcmp(jcr->VolCatInfo.VolCatStatus, "Recycle") == 0;
+ recycle = strcmp(dcr->VolCatInfo.VolCatStatus, "Recycle") == 0;
if (recycle && dev->num_writers != 0) {
Jmsg(jcr, M_FATAL, 0, _("Cannot recycle volume \"%s\""
" because it is in use by another job.\n"));
}
if (do_mount || recycle) {
- if (!mount_next_write_volume(dcr, dcr->block, release)) {
+ if (!mount_next_write_volume(dcr, release)) {
if (!job_canceled(jcr)) {
/* Reduce "noise" -- don't print if job canceled */
Jmsg(jcr, M_FATAL, 0, _("Could not ready device \"%s\" for append.\n"),
if (jcr->NumVolumes == 0) {
jcr->NumVolumes = 1;
}
-// attach_jcr_to_device(dev, jcr); /* attach jcr to device */
set_jcr_job_status(jcr, JS_Running);
dir_send_job_status(jcr);
goto ok_out;
if (dev_state(dev, ST_LABEL)) {
Dmsg0(100, "dir_create_jobmedia_record. Release\n");
if (!dir_create_jobmedia_record(dcr)) {
- Jmsg(jcr, M_ERROR, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
- jcr->VolCatInfo.VolCatName, jcr->Job);
+ Jmsg(jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
+ dcr->VolCatInfo.VolCatName, jcr->Job);
}
/* If no more writers, write an EOF */
if (!dev->num_writers && dev_can_write(dev)) {
close_dev(dev);
}
} else {
- Jmsg2(jcr, M_ERROR, 0, _("BAD ERROR: release_device %s, Volume \"%s\" not in use.\n"),
- dev_name(dev), NPRT(jcr->VolumeName));
+ Jmsg2(jcr, M_FATAL, 0, _("BAD ERROR: release_device %s, Volume \"%s\" not in use.\n"),
+ dev_name(dev), NPRT(dcr->VolumeName));
Jmsg2(jcr, M_ERROR, 0, _("num_writers=%d state=%x\n"), dev->num_writers, dev->state);
}
alert = edit_device_codes(jcr, alert, jcr->device->alert_command, "");
bpipe = open_bpipe(alert, 0, "r");
if (bpipe) {
- free_pool_memory(alert);
while (fgets(line, sizeof(line), bpipe->rfd)) {
Jmsg(jcr, M_INFO, 0, _("Alert: %s"), line);
}
status = close_bpipe(bpipe);
+ } else {
+ status = errno;
}
if (status != 0) {
- berrno be;
- be.set_errno(status);
+ berrno be(status);
Jmsg(jcr, M_INFO, 0, _("3997 Bad alert command: %s: ERR=%s.\n"),
alert, be.strerror());
}
Dmsg1(400, "alert status=%d\n", status);
-
+ free_pool_memory(alert);
}
if (dev->prev && !dev_state(dev, ST_READ) && !dev->num_writers) {
P(mutex);
bool ok = true;
DEVICE *dev;
DEV_RECORD rec;
- DEV_BLOCK *block;
DCR *dcr;
Dmsg0(10, "Start append data.\n");
return false;
}
dev = dcr->dev;
- block = dcr->block;
memset(&rec, 0, sizeof(rec));
Dmsg1(20, "Begin append device=%s\n", dev_name(dev));
/*
* Write Begin Session Record
*/
- if (!write_session_label(dcr, block, SOS_LABEL)) {
+ if (!write_session_label(dcr, SOS_LABEL)) {
Jmsg1(jcr, M_FATAL, 0, _("Write session label failed. ERR=%s\n"),
strerror_dev(dev));
set_jcr_job_status(jcr, JS_ErrorTerminated);
rec.FileIndex, rec.VolSessionId, stream_to_ascii(rec.Stream,rec.FileIndex),
rec.data_len);
- while (!write_record_to_block(block, &rec)) {
+ while (!write_record_to_block(dcr->block, &rec)) {
Dmsg2(150, "!write_record_to_block data_len=%d rem=%d\n", rec.data_len,
rec.remainder);
- if (!write_block_to_device(jcr->dcr, block)) {
+ if (!write_block_to_device(dcr)) {
Dmsg2(90, "Got write_block_to_dev error on device %s. %s\n",
dev_name(dev), strerror_dev(dev));
Jmsg(jcr, M_FATAL, 0, _("Fatal device error: ERR=%s\n"),
* if we are at the end of the tape or we got a fatal I/O error.
*/
if (ok || dev_can_write(dev)) {
- if (!write_session_label(dcr, block, EOS_LABEL)) {
+ if (!write_session_label(dcr, EOS_LABEL)) {
Jmsg1(jcr, M_FATAL, 0, _("Error writting end session label. ERR=%s\n"),
strerror_dev(dev));
set_jcr_job_status(jcr, JS_ErrorTerminated);
}
Dmsg0(90, "back from write_end_session_label()\n");
/* Flush out final partial block of this session */
- if (!write_block_to_device(dcr, block)) {
+ if (!write_block_to_device(dcr)) {
Dmsg0(100, _("Set ok=FALSE after write_block_to_device.\n"));
set_jcr_job_status(jcr, JS_ErrorTerminated);
ok = false;
* and
* dir_find_next_appendable_volume()
*
- * Returns: true on success and vol info in jcr->VolCatInfo
+ * Returns: true on success and vol info in dcr->VolCatInfo
* false on failure
*/
static bool do_get_volume_info(DCR *dcr)
int n;
int InChanger;
- jcr->VolumeName[0] = 0; /* No volume */
dcr->VolumeName[0] = 0; /* No volume */
if (bnet_recv(dir) <= 0) {
Dmsg0(200, "getvolname error bnet_recv\n");
}
vol.InChanger = InChanger; /* bool in structure */
unbash_spaces(vol.VolCatName);
- pm_strcpy(&jcr->VolumeName, vol.VolCatName); /* set desired VolumeName */
bstrncpy(dcr->VolumeName, vol.VolCatName, sizeof(dcr->VolumeName));
- memcpy(&jcr->VolCatInfo, &vol, sizeof(jcr->VolCatInfo));
memcpy(&dcr->VolCatInfo, &vol, sizeof(dcr->VolCatInfo));
Dmsg2(200, "do_reqest_vol_info got slot=%d Volume=%s\n",
JCR *jcr = dcr->jcr;
BSOCK *dir = jcr->dir_bsock;
- bstrncpy(jcr->VolCatInfo.VolCatName, jcr->VolumeName, sizeof(jcr->VolCatInfo.VolCatName));
- Dmsg1(200, "dir_get_volume_info=%s\n", jcr->VolCatInfo.VolCatName);
- bash_spaces(jcr->VolCatInfo.VolCatName);
- bnet_fsend(dir, Get_Vol_Info, jcr->Job, jcr->VolCatInfo.VolCatName,
+ bstrncpy(dcr->VolCatInfo.VolCatName, dcr->VolumeName, sizeof(dcr->VolCatInfo.VolCatName));
+ Dmsg1(200, "dir_get_volume_info=%s\n", dcr->VolCatInfo.VolCatName);
+ bash_spaces(dcr->VolCatInfo.VolCatName);
+ bnet_fsend(dir, Get_Vol_Info, jcr->Job, dcr->VolCatInfo.VolCatName,
writing==GET_VOL_INFO_FOR_WRITE?1:0);
return do_get_volume_info(dcr);
}
for (int vol_index=1; vol_index < 3; vol_index++) {
bnet_fsend(dir, Find_media, jcr->Job, vol_index);
if (do_get_volume_info(dcr)) {
- Dmsg2(200, "JobId=%d got possible Vol=%s\n", jcr->JobId, jcr->VolumeName);
+ Dmsg2(200, "JobId=%d got possible Vol=%s\n", jcr->JobId, dcr->VolumeName);
bool found = false;
/*
* Walk through all jobs and see if the volume is
free_locked_jcr(njcr);
continue; /* us */
}
- Dmsg2(200, "Compare to JobId=%d using Vol=%s\n", njcr->JobId, njcr->VolumeName);
- if (strcmp(jcr->VolumeName, njcr->VolumeName) == 0) {
+ Dmsg2(200, "Compare to JobId=%d using Vol=%s\n", njcr->JobId, njcr->dcr->VolumeName);
+ if (njcr->dcr && strcmp(dcr->VolumeName, njcr->dcr->VolumeName) == 0) {
found = true;
Dmsg1(200, "Vol in use by JobId=%u\n", njcr->JobId);
free_locked_jcr(njcr);
int InChanger;
if (vol->VolCatName[0] == 0) {
- Jmsg0(jcr, M_ERROR, 0, _("NULL Volume name. This shouldn't happen!!!\n"));
+ Jmsg0(jcr, M_FATAL, 0, _("NULL Volume name. This shouldn't happen!!!\n"));
return false;
}
if (dev_state(dev, ST_READ)) {
- Jmsg0(jcr, M_ERROR, 0, _("Attempt to update_volume_info in read mode!!!\n"));
+ Jmsg0(jcr, M_FATAL, 0, _("Attempt to update_volume_info in read mode!!!\n"));
return false;
}
unbash_spaces(vol->VolCatName);
if (!do_get_volume_info(dcr)) {
- Jmsg(jcr, M_ERROR, 0, "%s", jcr->errmsg);
+ Jmsg(jcr, M_FATAL, 0, "%s", jcr->errmsg);
return false;
}
Dmsg1(120, "get_volume_info(): %s", dir->msg);
/* Update dev Volume info in case something changed (e.g. expired) */
- memcpy(&dev->VolCatInfo, &jcr->VolCatInfo, sizeof(dev->VolCatInfo));
+ memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
return true;
}
Dmsg1(100, "create_jobmedia(): %s", dir->msg);
if (bnet_recv(dir) <= 0) {
Dmsg0(190, "create_jobmedia error bnet_recv\n");
- Jmsg(jcr, M_ERROR, 0, _("Error creating JobMedia record: ERR=%s\n"),
+ Jmsg(jcr, M_FATAL, 0, _("Error creating JobMedia record: ERR=%s\n"),
bnet_strerror(dir));
return false;
}
Dmsg1(120, "Create_jobmedia: %s", dir->msg);
if (strcmp(dir->msg, OK_create) != 0) {
Dmsg1(130, "Bad response from Dir: %s\n", dir->msg);
- Jmsg(jcr, M_ERROR, 0, _("Error creating JobMedia record: %s\n"), dir->msg);
+ Jmsg(jcr, M_FATAL, 0, _("Error creating JobMedia record: %s\n"), dir->msg);
return false;
}
return true;
* false on failure
* Note, must create dev->errmsg on error return.
*
- * On success, jcr->VolumeName and jcr->VolCatInfo contain
+ * On success, dcr->VolumeName and dcr->VolCatInfo contain
* information on suggested volume, but this may not be the
* same as what is actually mounted.
*
if (job_canceled(jcr)) {
Mmsg(dev->errmsg,
_("Job %s canceled while waiting for mount on Storage Device \"%s\".\n"),
- jcr->Job, jcr->dev_name);
+ jcr->Job, dcr->dev_name);
Jmsg(jcr, M_INFO, 0, "%s", dev->errmsg);
return false;
}
* Slot for an autochanger, otherwise wait
* for the operator to mount the media.
*/
- if (!unmounted && ((jcr->VolumeName[0] && !dev_cap(dev, CAP_REM) &&
+ if (!unmounted && ((dcr->VolumeName[0] && !dev_cap(dev, CAP_REM) &&
dev_cap(dev, CAP_LABEL)) ||
- (jcr->VolumeName[0] && jcr->VolCatInfo.Slot))) {
+ (dcr->VolumeName[0] && dcr->VolCatInfo.Slot))) {
Dmsg0(200, "Return 1 from mount without wait.\n");
return true;
}
Jmsg(jcr, M_MOUNT, 0, _(
"Please mount Volume \"%s\" on Storage Device \"%s\" for Job %s\n"
"Use \"mount\" command to release Job.\n"),
- jcr->VolumeName, jcr->dev_name, jcr->Job);
+ dcr->VolumeName, dcr->dev_name, jcr->Job);
Dmsg3(200, "Mount %s on %s for Job %s\n",
- jcr->VolumeName, jcr->dev_name, jcr->Job);
+ dcr->VolumeName, dcr->dev_name, jcr->Job);
}
} else {
jstat = JS_WaitMedia;
Media type: %s\n\
Pool: %s\n"),
jcr->Job,
- jcr->dev_name,
- jcr->media_type,
- jcr->pool_name);
+ dcr->dev_name,
+ dcr->media_type,
+ dcr->pool_name);
}
}
first = false;
Dmsg1(200, "Someone woke me for device %s\n", dev_name(dev));
/* If no VolumeName, and cannot get one, try again */
- if (jcr->VolumeName[0] == 0 && !job_canceled(jcr) &&
+ if (dcr->VolumeName[0] == 0 && !job_canceled(jcr) &&
!dir_find_next_appendable_volume(dcr)) {
Jmsg(jcr, M_MOUNT, 0, _(
"Someone woke me up, but I cannot find any appendable\n\
/*
* Request to mount specific Volume
*
- * Entered with device blocked and jcr->VolumeName is desired
+ * Entered with device blocked and dcr->VolumeName is desired
* volume.
* Leaves with device blocked.
*
- * Returns: 1 on success (operator issues a mount command)
- * 0 on failure
- * Note, must create dev->errmsg on error return.
+ * Returns: true on success (operator issues a mount command)
+ * false on failure
+ * Note, must create dev->errmsg on error return.
*
*/
bool dir_ask_sysop_to_mount_volume(DCR *dcr)
JCR *jcr = dcr->jcr;
Dmsg0(200, "enter dir_ask_sysop_to_mount_volume\n");
- if (!jcr->VolumeName[0]) {
+ if (!dcr->VolumeName[0]) {
Mmsg0(dev->errmsg, _("Cannot request another volume: no volume name given.\n"));
- return 0;
+ return false;
}
ASSERT(dev->dev_blocked);
for ( ;; ) {
if (job_canceled(jcr)) {
Mmsg(dev->errmsg, _("Job %s canceled while waiting for mount on Storage Device \"%s\".\n"),
- jcr->Job, jcr->dev_name);
+ jcr->Job, dcr->dev_name);
return false;
}
if (!dev->poll) {
msg = _("Please mount");
Jmsg(jcr, M_MOUNT, 0, _("%s Volume \"%s\" on Storage Device \"%s\" for Job %s\n"),
- msg, jcr->VolumeName, jcr->dev_name, jcr->Job);
- Dmsg3(200, "Mount %s on %s for Job %s\n",
- jcr->VolumeName, jcr->dev_name, jcr->Job);
+ msg, dcr->VolumeName, dcr->dev_name, jcr->Job);
+ Dmsg3(200, "Mount \"%s\" on device \"%s\" for Job %s\n",
+ dcr->VolumeName, dcr->dev_name, jcr->Job);
}
jcr->JobStatus = JS_WaitMount;
}
if (stat != 0) {
berrno be;
- Jmsg(jcr, M_ERROR, 0, _("pthread error in mount_next_volume stat=%d ERR=%s\n"), stat,
+ Jmsg(jcr, M_FATAL, 0, _("pthread error in mount_next_volume stat=%d ERR=%s\n"), stat,
be.strerror(stat));
}
Dmsg1(200, "Someone woke me for device %s\n", dev_name(dev));
{
JCR *jcr = dcr->jcr;
DEVICE *dev = dcr->dev;
- int slot = jcr->VolCatInfo.Slot;
+ int slot = dcr->VolCatInfo.Slot;
int drive = jcr->device->drive_index;
int rtn_stat = -1; /* error status */
return 0; /* For user, bail out right now */
}
if (dir_find_next_appendable_volume(dcr)) {
- slot = jcr->VolCatInfo.Slot;
+ slot = dcr->VolCatInfo.Slot;
} else {
slot = 0;
}
Jmsg(jcr, M_INFO, 0,
_("3303 Issuing autochanger \"unload slot %d, drive %d\" command.\n"),
loaded, drive);
- jcr->VolCatInfo.Slot = loaded; /* slot to be unloaded */
+ dcr->VolCatInfo.Slot = loaded; /* slot to be unloaded */
changer = edit_device_codes(jcr, changer,
jcr->device->changer_command, "unload");
status = run_program(changer, timeout, NULL);
Jmsg(jcr, M_INFO, 0,
_("3304 Issuing autochanger \"load slot %d, drive %d\" command.\n"),
slot, drive);
- jcr->VolCatInfo.Slot = slot; /* slot to be loaded */
+ dcr->VolCatInfo.Slot = slot; /* slot to be loaded */
changer = edit_device_codes(jcr, changer,
jcr->device->changer_command, "load");
status = run_program(changer, timeout, NULL);
DEVICE *dev = dcr->dev;
Jmsg(jcr, M_ERROR, 0, _("Autochanger Volume \"%s\" not found in slot %d.\n"
" Setting slot to zero in catalog.\n"),
- jcr->VolCatInfo.VolCatName, jcr->VolCatInfo.Slot);
- jcr->VolCatInfo.InChanger = false;
+ dcr->VolCatInfo.VolCatName, dcr->VolCatInfo.Slot);
+ dcr->VolCatInfo.InChanger = false;
dev->VolCatInfo.InChanger = false;
Dmsg0(100, "update vol info in mount\n");
dir_update_volume_info(dcr, true); /* set new status */
loaded = get_autochanger_loaded_slot(jcr);
if (loaded > 0) {
bnet_fsend(dir, _("3305 Issuing autochanger \"unload slot %d\" command.\n"), loaded);
- slot = jcr->VolCatInfo.Slot;
- jcr->VolCatInfo.Slot = loaded;
+ slot = dcr->VolCatInfo.Slot;
+ dcr->VolCatInfo.Slot = loaded;
changer = edit_device_codes(jcr, changer, jcr->device->changer_command, "unload");
int stat = run_program(changer, timeout, NULL);
if (stat != 0) {
Jmsg(jcr, M_INFO, 0, _("3995 Bad autochanger \"unload slot %d\" command: ERR=%s.\n"),
loaded, be.strerror());
}
- jcr->VolCatInfo.Slot = slot;
+ dcr->VolCatInfo.Slot = slot;
}
/* Now list slots occupied */
str = NPRT(cmd);
break;
case 's':
- sprintf(add, "%d", jcr->VolCatInfo.Slot - 1);
+ sprintf(add, "%d", jcr->dcr->VolCatInfo.Slot - 1);
str = add;
break;
case 'S':
- sprintf(add, "%d", jcr->VolCatInfo.Slot);
+ sprintf(add, "%d", jcr->dcr->VolCatInfo.Slot);
str = add;
break;
case 'j': /* Job name */
str = jcr->Job;
break;
case 'v':
- str = NPRT(jcr->VolumeName);
+ str = NPRT(jcr->dcr->VolumeName);
break;
case 'f':
str = NPRT(jcr->client_name);
#include "stored.h"
/* Forward referenced functions */
-static bool record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec);
+static bool record_cb(DCR *dcr, DEV_RECORD *rec);
/* Global variables */
parse_config(configfile);
/* Setup and acquire input device for reading */
- in_jcr = setup_jcr("bcopy", argv[0], bsr, iVolumeName);
+ in_jcr = setup_jcr("bcopy", argv[0], bsr, iVolumeName, 1); /* read device */
+ if (!in_jcr) {
+ exit(1);
+ }
in_jcr->ignore_label_errors = ignore_label_errors;
- in_dev = setup_to_access_device(in_jcr, 1); /* read device */
+ in_dev = in_jcr->dcr->dev;
if (!in_dev) {
exit(1);
}
/* Setup output device for writing */
- out_jcr = setup_jcr("bcopy", argv[1], bsr, oVolumeName);
- out_dev = setup_to_access_device(out_jcr, 0); /* no acquire */
+ out_jcr = setup_jcr("bcopy", argv[1], bsr, oVolumeName, 0); /* no acquire */
+ if (!out_jcr) {
+ exit(1);
+ }
+ out_dev = out_jcr->dcr->dev;
if (!out_dev) {
exit(1);
}
/* For we must now acquire the device for writing */
lock_device(out_dev);
- if (open_dev(out_dev, out_jcr->VolumeName, OPEN_READ_WRITE) < 0) {
+ if (open_dev(out_dev, out_jcr->dcr->VolumeName, OPEN_READ_WRITE) < 0) {
Emsg1(M_FATAL, 0, _("dev open failed: %s\n"), out_dev->errmsg);
unlock_device(out_dev);
exit(1);
out_block = out_jcr->dcr->block;
read_records(in_jcr->dcr, record_cb, mount_next_read_volume);
- if (!write_block_to_device(out_jcr->dcr, out_block)) {
+ if (!write_block_to_device(out_jcr->dcr)) {
Pmsg0(000, _("Write of last block failed.\n"));
}
/*
* read_records() calls back here for each record it gets
*/
-static bool record_cb(JCR *in_jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
+static bool record_cb(DCR *in_dcr, DEV_RECORD *rec)
{
if (list_records) {
Pmsg5(000, _("Record: SessId=%u SessTim=%u FileIndex=%d Stream=%d len=%u\n"),
if (rec->FileIndex < 0) {
if (verbose > 1) {
- dump_label_record(dev, rec, 1);
+ dump_label_record(in_dcr->dev, rec, 1);
}
switch (rec->FileIndex) {
case PRE_LABEL:
while (!write_record_to_block(out_block, rec)) {
Dmsg2(150, "!write_record_to_block data_len=%d rem=%d\n", rec->data_len,
rec->remainder);
- if (!write_block_to_device(out_jcr->dcr, out_block)) {
+ if (!write_block_to_device(out_jcr->dcr)) {
Dmsg2(90, "Got write_block_to_dev error on device %s. %s\n",
dev_name(out_dev), strerror_dev(out_dev));
Jmsg(out_jcr, M_FATAL, 0, _("Cannot fixup device error. %s\n"),
strerror_dev(out_dev));
}
}
- if (!write_block_to_device(out_jcr->dcr, out_block)) {
+ if (!write_block_to_device(out_jcr->dcr)) {
Dmsg2(90, "Got write_block_to_dev error on device %s. %s\n",
dev_name(out_dev), strerror_dev(out_dev));
Jmsg(out_jcr, M_FATAL, 0, _("Cannot fixup device error. %s\n"),
while (!write_record_to_block(out_block, rec)) {
Dmsg2(150, "!write_record_to_block data_len=%d rem=%d\n", rec->data_len,
rec->remainder);
- if (!write_block_to_device(out_jcr->dcr, out_block)) {
+ if (!write_block_to_device(out_jcr->dcr)) {
Dmsg2(90, "Got write_block_to_dev error on device %s. %s\n",
dev_name(out_dev), strerror_dev(out_dev));
Jmsg(out_jcr, M_FATAL, 0, _("Cannot fixup device error. %s\n"),
bool dir_ask_sysop_to_mount_volume(DCR *dcr)
{
- JCR *jcr = dcr->jcr;
DEVICE *dev = dcr->dev;
fprintf(stderr, "Mount Volume \"%s\" on device %s and press return when ready: ",
- jcr->VolumeName, dev_name(dev));
+ dcr->VolumeName, dev_name(dev));
getchar();
return true;
}
*
* Dumb program to extract files from a Bacula backup.
*
- * Kern E. Sibbald, 2000
+ * Kern E. Sibbald, MM
*
* Version $Id$
*
#endif
static void do_extract(char *fname);
-static bool record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec);
+static bool record_cb(DCR *dcr, DEV_RECORD *rec);
static DEVICE *dev = NULL;
static DCR *dcr;
" -e <file> exclude list\n"
" -i <file> include list\n"
" -p proceed inspite of I/O errors\n"
+" -v verbose\n"
" -V <volumes> specify Volume names (separated by |)\n"
" -? print this message\n\n");
exit(1);
init_include_exclude_files(ff);
binit(&bfd);
- while ((ch = getopt(argc, argv, "b:c:d:e:i:pV:?")) != -1) {
+ while ((ch = getopt(argc, argv, "b:c:d:e:i:pvV:?")) != -1) {
switch (ch) {
case 'b': /* bootstrap file */
bsr = parse_bsr(NULL, optarg);
forge_on = true;
break;
+ case 'v':
+ verbose++;
+ break;
+
case 'V': /* Volume name */
VolumeName = optarg;
break;
static void do_extract(char *devname)
{
struct stat statp;
- jcr = setup_jcr("bextract", devname, bsr, VolumeName);
- dev = setup_to_access_device(jcr, 1); /* acquire for read */
+ jcr = setup_jcr("bextract", devname, bsr, VolumeName, 1); /* acquire for read */
+ if (!jcr) {
+ exit(1);
+ }
+ dev = jcr->dcr->dev;
if (!dev) {
exit(1);
}
/*
* Called here for each record from read_records()
*/
-static bool record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
+static bool record_cb(DCR *dcr, DEV_RECORD *rec)
{
int stat;
+ JCR *jcr = dcr->jcr;
if (rec->FileIndex < 0) {
return true; /* we don't want labels */
bool dir_ask_sysop_to_mount_volume(DCR *dcr)
{
- JCR *jcr = dcr->jcr;
DEVICE *dev = dcr->dev;
fprintf(stderr, "Mount Volume \"%s\" on device %s and press return when ready: ",
- jcr->VolumeName, dev_name(dev));
+ dcr->VolumeName, dev_name(dev));
getchar();
return true;
}
* : false on failure
*
*/
-bool write_block_to_device(DCR *dcr, DEV_BLOCK *block)
+bool write_block_to_device(DCR *dcr)
{
bool stat = true;
DEVICE *dev = dcr->dev;
JCR *jcr = dcr->jcr;
if (dcr->spooling) {
- stat = write_block_to_spool_file(dcr, block);
+ stat = write_block_to_spool_file(dcr);
return stat;
}
if (!dir_create_jobmedia_record(dcr)) {
dev->dev_errno = EIO;
Jmsg(jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
- jcr->VolCatInfo.VolCatName, jcr->Job);
+ dcr->VolCatInfo.VolCatName, jcr->Job);
set_new_volume_parameters(dcr);
stat = false;
goto bail_out;
}
}
- if (!write_block_to_dev(dcr, block)) {
+ if (!write_block_to_dev(dcr)) {
if (job_canceled(jcr)) {
stat = 0;
} else {
- stat = fixup_device_block_write_error(dcr, block);
+ stat = fixup_device_block_write_error(dcr);
}
}
* Returns: true on success or EOT
* false on hard error
*/
-bool write_block_to_dev(DCR *dcr, DEV_BLOCK *block)
+bool write_block_to_dev(DCR *dcr)
{
ssize_t stat = 0;
uint32_t wlen; /* length to write */
bool ok = true;
DEVICE *dev = dcr->dev;
JCR *jcr = dcr->jcr;
+ DEV_BLOCK *block = dcr->block;
#ifdef NO_TAPE_WRITE_TEST
empty_block(block);
if (ok) {
DEV_BLOCK *lblock = new_block(dev);
/* Note, this can destroy dev->errmsg */
- if (!read_block_from_dev(dcr, lblock, NO_BLOCK_NUMBER_CHECK)) {
+ dcr->block = lblock;
+ if (!read_block_from_dev(dcr, NO_BLOCK_NUMBER_CHECK)) {
Jmsg(jcr, M_ERROR, 0, _("Re-read last block at EOT failed. ERR=%s"), dev->errmsg);
} else {
if (lblock->BlockNumber+1 == block->BlockNumber) {
}
}
free_block(lblock);
+ dcr->block = block;
}
}
#endif
dev->block_num++;
block->BlockNumber++;
- /* Update jcr values */
+ /* Update dcr values */
if (dev_state(dev, ST_TAPE)) {
dcr->EndBlock = dev->EndBlock;
dcr->EndFile = dev->EndFile;
* Read block with locking
*
*/
-bool read_block_from_device(DCR *dcr, DEV_BLOCK *block, bool check_block_numbers)
+bool read_block_from_device(DCR *dcr, bool check_block_numbers)
{
bool stat;
DEVICE *dev = dcr->dev;
Dmsg0(90, "Enter read_block_from_device\n");
lock_device(dev);
- stat = read_block_from_dev(dcr, block, check_block_numbers);
+ stat = read_block_from_dev(dcr, check_block_numbers);
unlock_device(dev);
Dmsg0(90, "Leave read_block_from_device\n");
return stat;
* the block header. For a file, the block may be partially
* or completely in the current buffer.
*/
-bool read_block_from_dev(DCR *dcr, DEV_BLOCK *block, bool check_block_numbers)
+bool read_block_from_dev(DCR *dcr, bool check_block_numbers)
{
ssize_t stat;
int looping;
int retry;
JCR *jcr = dcr->jcr;
DEVICE *dev = dcr->dev;
+ DEV_BLOCK *block = dcr->block;
if (dev_state(dev, ST_EOT)) {
return false;
dev->EndFile = dev->file;
dev->block_num++;
- /* Update jcr values */
+ /* Update dcr values */
if (dev->state & ST_TAPE) {
dcr->EndBlock = dev->EndBlock;
dcr->EndFile = dev->EndFile;
static void do_ls(char *fname);
static void do_close(JCR *jcr);
static void get_session_record(DEVICE *dev, DEV_RECORD *rec, SESSION_LABEL *sessrec);
-static bool record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec);
+static bool record_cb(DCR *dcr, DEV_RECORD *rec);
static DEVICE *dev;
static DCR *dcr;
if (bsrName) {
bsr = parse_bsr(NULL, bsrName);
}
- jcr = setup_jcr("bls", argv[i], bsr, VolumeName);
+ jcr = setup_jcr("bls", argv[i], bsr, VolumeName, 1); /* acquire for read */
+ if (!jcr) {
+ exit(1);
+ }
jcr->ignore_label_errors = ignore_label_errors;
- dev = setup_to_access_device(jcr, 1); /* acquire for read */
+ dev = jcr->dcr->dev;
if (!dev) {
exit(1);
}
rec = new_record();
}
for ( ;; ) {
- if (!read_block_from_device(dcr, block, NO_BLOCK_NUMBER_CHECK)) {
+ if (!read_block_from_device(dcr, NO_BLOCK_NUMBER_CHECK)) {
Dmsg1(100, "!read_block(): ERR=%s\n", strerror_dev(dev));
if (dev->state & ST_EOT) {
- if (!mount_next_read_volume(jcr, dev, block)) {
+ if (!mount_next_read_volume(dcr)) {
Jmsg(jcr, M_INFO, 0, _("Got EOM at file %u on device %s, Volume \"%s\"\n"),
- dev->file, dev_name(dev), jcr->VolumeName);
+ dev->file, dev_name(dev), dcr->VolumeName);
break;
}
/* Read and discard Volume label */
DEV_RECORD *record;
record = new_record();
- read_block_from_device(dcr, block, NO_BLOCK_NUMBER_CHECK);
+ read_block_from_device(dcr, NO_BLOCK_NUMBER_CHECK);
read_record_from_block(block, record);
get_session_record(dev, record, &sessrec);
free_record(record);
- Jmsg(jcr, M_INFO, 0, _("Mounted Volume \"%s\".\n"), jcr->VolumeName);
+ Jmsg(jcr, M_INFO, 0, _("Mounted Volume \"%s\".\n"), dcr->VolumeName);
} else if (dev->state & ST_EOF) {
Jmsg(jcr, M_INFO, 0, _("Got EOF at file %u on device %s, Volume \"%s\"\n"),
- dev->file, dev_name(dev), jcr->VolumeName);
+ dev->file, dev_name(dev), dcr->VolumeName);
Dmsg0(20, "read_record got eof. try again\n");
continue;
} else if (dev->state & ST_SHORT) {
/*
* We are only looking for labels or in particular Job Session records
*/
-static bool jobs_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
+static bool jobs_cb(DCR *dcr, DEV_RECORD *rec)
{
if (rec->FileIndex < 0) {
- dump_label_record(dev, rec, verbose);
+ dump_label_record(dcr->dev, rec, verbose);
}
rec->remainder = 0;
return true;
/*
* Called here for each record from read_records()
*/
-static bool record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
+static bool record_cb(DCR *dcr, DEV_RECORD *rec)
{
if (rec->FileIndex < 0) {
get_session_record(dev, rec, &sessrec);
bool dir_ask_sysop_to_mount_volume(DCR *dcr)
{
- JCR *jcr = dcr->jcr;
DEVICE *dev = dcr->dev;
fprintf(stderr, "Mount Volume \"%s\" on device %s and press return when ready: ",
- jcr->VolumeName, dev_name(dev));
+ dcr->VolumeName, dev_name(dev));
getchar();
return true;
}
/* Forward referenced functions */
static void do_scan(void);
-static bool record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec);
+static bool record_cb(DCR *dcr, DEV_RECORD *rec);
static int create_file_attributes_record(B_DB *db, JCR *mjcr,
char *fname, char *lname, int type,
char *ap, DEV_RECORD *rec);
working_directory);
}
- bjcr = setup_jcr("bscan", argv[0], bsr, VolumeName);
- dev = setup_to_access_device(bjcr, 1); /* read device */
- if (!dev) {
+ bjcr = setup_jcr("bscan", argv[0], bsr, VolumeName, 1); /* read device */
+ if (!bjcr) {
exit(1);
}
+ dev = bjcr->dcr->dev;
if (showProgress) {
struct stat sb;
fstat(dev->fd, &sb);
Pmsg1(000, _("Current Volume Size = %" llu "\n"), currentVolumeSize);
}
- if ((db=db_init_database(NULL, db_name, db_user, db_password, db_host, 0, NULL)) == NULL) {
+ if ((db=db_init_database(NULL, db_name, db_user, db_password,
+ db_host, 0, NULL, 0)) == NULL) {
Emsg0(M_ERROR_TERM, 0, _("Could not init Bacula database\n"));
}
if (!db_open_database(NULL, db)) {
* the end of writing a tape by wiffling through the attached
* jcrs creating jobmedia records.
*/
-static bool bscan_mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
+static bool bscan_mount_next_read_volume(DCR *dcr)
{
+ DEVICE *dev = dcr->dev;
+ DCR *mdcr;
Dmsg1(100, "Walk attached jcrs. Volume=%s\n", dev->VolCatInfo.VolCatName);
- DCR *dcr;
- foreach_dlist(dcr, dev->attached_dcrs) {
- JCR *mjcr = dcr->jcr;
+ foreach_dlist(mdcr, dev->attached_dcrs) {
+ JCR *mjcr = mdcr->jcr;
if (mjcr->JobId == 0) {
continue;
}
Pmsg1(000, _("Create JobMedia for Job %s\n"), mjcr->Job);
}
if (dev->state & ST_TAPE) {
- dcr->EndBlock = dev->EndBlock;
- dcr->EndFile = dev->EndFile;
+ mdcr->EndBlock = dev->EndBlock;
+ mdcr->EndFile = dev->EndFile;
} else {
- dcr->EndBlock = (uint32_t)dev->file_addr;
- dcr->EndFile = (uint32_t)(dev->file_addr >> 32);
+ mdcr->EndBlock = (uint32_t)dev->file_addr;
+ mdcr->EndFile = (uint32_t)(dev->file_addr >> 32);
}
if (!create_jobmedia_record(db, mjcr)) {
Pmsg2(000, _("Could not create JobMedia record for Volume=%s Job=%s\n"),
* we call mount_next... with bscan's jcr because that is where we
* have the Volume list, but we get attached.
*/
- bool stat = mount_next_read_volume(jcr, dev, block);
+ bool stat = mount_next_read_volume(dcr);
if (showProgress) {
struct stat sb;
/* Detach bscan's jcr as we are not a real Job on the tape */
read_records(bjcr->dcr, record_cb, bscan_mount_next_read_volume);
-// release_device(bjcr);
free_attr(attr);
}
* Returns: true if OK
* false if error
*/
-static bool record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
+static bool record_cb(DCR *dcr, DEV_RECORD *rec)
{
JCR *mjcr;
- DCR *dcr;
char ec1[30];
+ DEVICE *dev = dcr->dev;
+ JCR *bjcr = dcr->jcr;
+ DEV_BLOCK *block = dcr->block;
if (rec->data_len > 0) {
mr.VolBytes += rec->data_len + WRITE_RECHDR_LENGTH; /* Accumulate Volume bytes */
mjcr->JobLevel = jr.JobLevel;
mjcr->client_name = get_pool_memory(PM_FNAME);
- pm_strcpy(&mjcr->client_name, label.ClientName);
- mjcr->pool_type = get_pool_memory(PM_FNAME);
- pm_strcpy(&mjcr->pool_type, label.PoolType);
+ pm_strcpy(mjcr->client_name, label.ClientName);
mjcr->fileset_name = get_pool_memory(PM_FNAME);
- pm_strcpy(&mjcr->fileset_name, label.FileSetName);
- mjcr->pool_name = get_pool_memory(PM_FNAME);
- pm_strcpy(&mjcr->pool_name, label.PoolName);
+ pm_strcpy(mjcr->fileset_name, label.FileSetName);
+ bstrncpy(dcr->pool_type, label.PoolType, sizeof(dcr->pool_type));
+ bstrncpy(dcr->pool_name, label.PoolName, sizeof(dcr->pool_name));
if (rec->VolSessionId != jr.VolSessionId) {
Pmsg3(000, _("SOS_LABEL: VolSessId mismatch for JobId=%u. DB=%d Vol=%d\n"),
static void statcmd();
static void unfillcmd();
static int flush_block(DEV_BLOCK *block, int dump);
-static bool quickie_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec);
+static bool quickie_cb(DCR *dcr, DEV_RECORD *rec);
static bool compare_blocks(DEV_BLOCK *last_block, DEV_BLOCK *block);
-static bool my_mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+static bool my_mount_next_read_volume(DCR *dcr);
static void scan_blocks();
static void set_volume_name(const char *VolName, int volnum);
static void rawfill_cmd();
exit(1);
}
- jcr = setup_jcr("btape", margv[0], bsr, NULL);
- dev = setup_to_access_device(jcr, 0); /* acquire for write */
+ jcr = setup_jcr("btape", margv[0], bsr, NULL, 0); /* write */
+ if (!jcr) {
+ exit(1);
+ }
+ dev = jcr->dcr->dev;
if (!dev) {
exit(1);
}
block = new_block(dev);
lock_device(dev);
if (!(dev->state & ST_OPENED)) {
- Dmsg1(200, "Opening device %s\n", jcr->VolumeName);
- if (open_dev(dev, jcr->VolumeName, OPEN_READ_WRITE) < 0) {
+ Dmsg1(200, "Opening device %s\n", dcr->VolumeName);
+ if (open_dev(dev, dcr->VolumeName, OPEN_READ_WRITE) < 0) {
Emsg1(M_FATAL, 0, _("dev open failed: %s\n"), dev->errmsg);
unlock_device(dev);
free_block(block);
{
int save_debug_level = debug_level;
int stat;
- DEV_BLOCK *block;
- block = new_block(dev);
- stat = read_dev_volume_label(dcr, block);
+ stat = read_dev_volume_label(dcr);
switch (stat) {
case VOL_NO_LABEL:
Pmsg0(0, "Volume has no label.\n");
debug_level = 20;
dump_volume_label(dev);
debug_level = save_debug_level;
- free_block(block);
}
*/
static int re_read_block_test()
{
- DEV_BLOCK *block;
+ DEV_BLOCK *block = dcr->block;
DEV_RECORD *rec;
int stat = 0;
int len;
"tape to verify that the block was written correctly.\n\n"
"This is not an *essential* feature ...\n\n"));
rewindcmd();
- block = new_block(dev);
rec = new_record();
rec->data = check_pool_memory_size(rec->data, block->buf_len);
len = rec->data_len = block->buf_len-100;
Pmsg0(0, _("Error writing record to block.\n"));
goto bail_out;
}
- if (!write_block_to_dev(dcr, block)) {
+ if (!write_block_to_dev(dcr)) {
Pmsg0(0, _("Error writing block to device.\n"));
goto bail_out;
} else {
Pmsg0(0, _("Error writing record to block.\n"));
goto bail_out;
}
- if (!write_block_to_dev(dcr, block)) {
+ if (!write_block_to_dev(dcr)) {
Pmsg0(0, _("Error writing block to device.\n"));
goto bail_out;
} else {
Pmsg0(0, _("Error writing record to block.\n"));
goto bail_out;
}
- if (!write_block_to_dev(dcr, block)) {
+ if (!write_block_to_dev(dcr)) {
Pmsg0(0, _("Error writing block to device.\n"));
goto bail_out;
} else {
goto bail_out;
}
Pmsg0(0, "Backspace record OK.\n");
- if (!read_block_from_dev(dcr, block, NO_BLOCK_NUMBER_CHECK)) {
+ if (!read_block_from_dev(dcr, NO_BLOCK_NUMBER_CHECK)) {
Pmsg1(0, _("Read block failed! ERR=%s\n"), strerror(dev->dev_errno));
goto bail_out;
}
stat = 1;
bail_out:
- free_block(block);
free_record(rec);
if (stat == 0) {
Pmsg0(0, _("This is not terribly serious since Bacula only uses\n"
Pmsg0(0, _("Error writing record to block.\n"));
goto bail_out;
}
- if (!write_block_to_dev(dcr, block)) {
+ if (!write_block_to_dev(dcr)) {
Pmsg0(0, _("Error writing block to device.\n"));
goto bail_out;
}
Pmsg0(0, _("Error writing record to block.\n"));
goto bail_out;
}
- if (!write_block_to_dev(dcr, block)) {
+ if (!write_block_to_dev(dcr)) {
Pmsg0(0, _("Error writing block to device.\n"));
goto bail_out;
}
}
for (i=1; i<=2000; i++) {
read_again:
- if (!read_block_from_dev(dcr, block, NO_BLOCK_NUMBER_CHECK)) {
+ if (!read_block_from_dev(dcr, NO_BLOCK_NUMBER_CHECK)) {
if (dev_state(dev, ST_EOF)) {
Pmsg0(-1, _("Got EOF on tape.\n"));
goto read_again;
Pmsg0(0, _("Error writing record to block.\n"));
goto bail_out;
}
- if (!write_block_to_dev(dcr, block)) {
+ if (!write_block_to_dev(dcr)) {
Pmsg0(0, _("Error writing block to device.\n"));
goto bail_out;
}
Pmsg0(0, _("Error writing record to block.\n"));
goto bail_out;
}
- if (!write_block_to_dev(dcr, block)) {
+ if (!write_block_to_dev(dcr)) {
Pmsg0(0, _("Error writing block to device.\n"));
goto bail_out;
}
goto bail_out;
}
read_again:
- if (!read_block_from_dev(dcr, block, NO_BLOCK_NUMBER_CHECK)) {
+ if (!read_block_from_dev(dcr, NO_BLOCK_NUMBER_CHECK)) {
if (dev_state(dev, ST_EOF)) {
Pmsg0(-1, _("Got EOF on tape.\n"));
goto read_again;
try_again:
slot = 1;
- jcr->VolCatInfo.Slot = slot;
+ dcr->VolCatInfo.Slot = slot;
/* Find out what is loaded, zero means device is unloaded */
Pmsg0(-1, _("3301 Issuing autochanger \"loaded\" command.\n"));
changer = edit_device_codes(jcr, changer, jcr->device->changer_command,
}
Dmsg1(100, "Results from loaded query=%s\n", results);
if (loaded) {
- jcr->VolCatInfo.Slot = loaded;
+ dcr->VolCatInfo.Slot = loaded;
offline_or_rewind_dev(dev);
/* We are going to load a new tape, so close the device */
force_close_dev(dev);
*/
slot = 1;
- jcr->VolCatInfo.Slot = slot;
+ dcr->VolCatInfo.Slot = slot;
Pmsg2(-1, _("3303 Issuing autochanger \"load slot %d %d\" command.\n"),
slot, dev->drive_index);
changer = edit_device_codes(jcr, changer, jcr->device->changer_command, "load");
*/
static void wrcmd()
{
- DEV_BLOCK *block;
- DEV_RECORD *rec;
+ DEV_BLOCK *block = dcr->block;
+ DEV_RECORD *rec = dcr->rec;
int i;
sm_check(__FILE__, __LINE__, false);
- block = new_block(dev);
- rec = new_record();
dump_block(block, "test");
i = block->buf_len - 100;
Pmsg0(0, _("Error writing record to block.\n"));
goto bail_out;
}
- if (!write_block_to_dev(dcr, block)) {
+ if (!write_block_to_dev(dcr)) {
Pmsg0(0, _("Error writing block to device.\n"));
goto bail_out;
} else {
bail_out:
sm_check(__FILE__, __LINE__, false);
- free_record(rec);
- free_block(block);
sm_check(__FILE__, __LINE__, false);
}
update_pos_dev(dev);
tot_files = dev->file;
for (;;) {
- if (!read_block_from_device(dcr, block, NO_BLOCK_NUMBER_CHECK)) {
+ if (!read_block_from_device(dcr, NO_BLOCK_NUMBER_CHECK)) {
Dmsg1(100, "!read_block(): ERR=%s\n", strerror_dev(dev));
if (dev->state & ST_EOT) {
if (blocks > 0) {
static void fillcmd()
{
DEV_RECORD rec;
- DEV_BLOCK *block;
+ DEV_BLOCK *block = dcr->block;
char ec1[50];
int fd;
uint32_t i;
/*
* Write Begin Session Record
*/
- if (!write_session_label(dcr, block, SOS_LABEL)) {
+ if (!write_session_label(dcr, SOS_LABEL)) {
set_jcr_job_status(jcr, JS_ErrorTerminated);
Jmsg1(jcr, M_FATAL, 0, _("Write session label failed. ERR=%s\n"),
strerror_dev(dev));
} else if (!ok) {
set_jcr_job_status(jcr, JS_ErrorTerminated);
}
- if (!write_session_label(dcr, block, EOS_LABEL)) {
+ if (!write_session_label(dcr, EOS_LABEL)) {
Pmsg1(000, _("Error writting end session label. ERR=%s\n"), strerror_dev(dev));
ok = false;
}
/* Write out final block of this session */
- if (!write_block_to_device(dcr, block)) {
+ if (!write_block_to_device(dcr)) {
Pmsg0(-1, _("Set ok=false after write_block_to_device.\n"));
ok = false;
}
static void do_unfill()
{
- DEV_BLOCK *block;
+ DEV_BLOCK *block = dcr->block;
bool autochanger;
dumped = 0;
VolBytes = 0;
LastBlock = 0;
- block = new_block(dev);
Dmsg0(20, "Enter do_unfill\n");
dev->capabilities |= CAP_ANONVOLS; /* allow reading any volume */
Pmsg1(-1, "Reposition error. ERR=%s\n", strerror_dev(dev));
}
Pmsg1(-1, _("Reading block %u.\n"), last_block_num);
- if (!read_block_from_device(dcr, block, NO_BLOCK_NUMBER_CHECK)) {
+ if (!read_block_from_device(dcr, NO_BLOCK_NUMBER_CHECK)) {
Pmsg1(-1, _("Error reading block: ERR=%s\n"), strerror_dev(dev));
goto bail_out;
}
goto bail_out;
}
Pmsg1(-1, _("Reading block %d.\n"), dev->block_num);
- if (!read_block_from_device(dcr, block, NO_BLOCK_NUMBER_CHECK)) {
+ if (!read_block_from_device(dcr, NO_BLOCK_NUMBER_CHECK)) {
Pmsg1(-1, _("Error reading block: ERR=%s\n"), strerror_dev(dev));
goto bail_out;
}
goto bail_out;
}
Pmsg1(-1, _("Reading block %d.\n"), dev->block_num);
- if (!read_block_from_device(dcr, block, NO_BLOCK_NUMBER_CHECK)) {
+ if (!read_block_from_device(dcr, NO_BLOCK_NUMBER_CHECK)) {
Pmsg1(-1, _("Error reading block: ERR=%s\n"), strerror_dev(dev));
goto bail_out;
}
}
bail_out:
- free_block(block);
free_block(last_block1);
free_block(last_block2);
free_block(first_block);
}
/* Read 1000 records then stop */
-static bool quickie_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
+static bool quickie_cb(DCR *dcr, DEV_RECORD *rec)
{
quickie_count++;
return quickie_count <= 1000;
/* Copy block */
this_file = dev->file;
this_block_num = dev->block_num;
- if (!write_block_to_dev(dcr, block)) {
+ if (!write_block_to_dev(dcr)) {
Pmsg3(000, "Last block at: %u:%u this_dev_block_num=%d\n",
last_file, last_block_num, this_block_num);
if (vol_num == 1) {
stop = -1; /* stop, but do simplified test */
} else {
/* Full test in progress */
- if (!fixup_device_block_write_error(jcr->dcr, block)) {
+ if (!fixup_device_block_write_error(jcr->dcr)) {
Pmsg1(000, _("Cannot fixup device error. %s\n"), strerror_dev(dev));
ok = false;
unlock_device(dev);
*/
static void qfillcmd()
{
- DEV_BLOCK *block;
- DEV_RECORD *rec;
+ DEV_BLOCK *block = dcr->block;
+ DEV_RECORD *rec = dcr->rec;
int i, count;
Pmsg0(0, "Test writing blocks of 64512 bytes to tape.\n");
}
sm_check(__FILE__, __LINE__, false);
- block = new_block(dev);
- rec = new_record();
i = block->buf_len - 100;
ASSERT (i > 0);
Pmsg0(0, _("Error writing record to block.\n"));
goto bail_out;
}
- if (!write_block_to_dev(dcr, block)) {
+ if (!write_block_to_dev(dcr)) {
Pmsg0(0, _("Error writing block to device.\n"));
goto bail_out;
}
bail_out:
sm_check(__FILE__, __LINE__, false);
- free_record(rec);
- free_block(block);
- sm_check(__FILE__, __LINE__, false);
-
}
/*
*/
static void rawfill_cmd()
{
- DEV_BLOCK *block;
+ DEV_BLOCK *block = dcr->block;
int stat;
int fd;
uint32_t block_num = 0;
int my_errno;
uint32_t i;
- block = new_block(dev);
fd = open("/dev/urandom", O_RDONLY);
if (fd) {
read(fd, block->buf, block->buf_len);
printf("Write failed at block %u. stat=%d ERR=%s\n", block_num, stat,
strerror(my_errno));
weofcmd();
- free_block(block);
}
*/
static void bfill_cmd()
{
- DEV_BLOCK *block;
+ DEV_BLOCK *block = dcr->block;
uint32_t block_num = 0;
uint32_t *p;
int my_errno;
int fd;
uint32_t i;
- block = new_block(dev);
fd = open("/dev/urandom", O_RDONLY);
if (fd) {
read(fd, block->buf, block->buf_len);
*p = block_num;
block->binbuf = block->buf_len;
block->bufp = block->buf + block->binbuf;
- if (!write_block_to_dev(dcr, block)) {
+ if (!write_block_to_dev(dcr)) {
break;
}
if ((block_num++ % 100) == 0) {
printf("\n");
printf("Write failed at block %u.\n", block_num);
weofcmd();
- free_block(block);
}
bool dir_get_volume_info(DCR *dcr, enum get_vol_info_rw writing)
{
- JCR *jcr = dcr->jcr;
Dmsg0(20, "Enter dir_get_volume_info\n");
- bstrncpy(jcr->VolCatInfo.VolCatName, jcr->VolumeName, sizeof(jcr->VolCatInfo.VolCatName));
+ bstrncpy(dcr->VolCatInfo.VolCatName, dcr->VolumeName, sizeof(dcr->VolCatInfo.VolCatName));
return 1;
}
bool dir_find_next_appendable_volume(DCR *dcr)
{
- JCR *jcr = dcr->jcr;
Dmsg1(20, "Enter dir_find_next_appendable_volume. stop=%d\n", stop);
- return jcr->VolumeName[0] != 0;
+ return dcr->VolumeName[0] != 0;
}
bool dir_ask_sysop_to_mount_volume(DCR *dcr)
{
DEVICE *dev = dcr->dev;
- JCR *jcr = dcr->jcr;
Dmsg0(20, "Enter dir_ask_sysop_to_mount_volume\n");
- if (jcr->VolumeName[0] == 0) {
+ if (dcr->VolumeName[0] == 0) {
return dir_ask_sysop_to_create_appendable_volume(dcr);
}
/* Close device so user can use autochanger if desired */
}
force_close_dev(dev);
Pmsg1(-1, "%s", dev->errmsg); /* print reason */
- if (jcr->VolumeName[0] == 0 || strcmp(jcr->VolumeName, "TestVolume2") == 0) {
+ if (dcr->VolumeName[0] == 0 || strcmp(dcr->VolumeName, "TestVolume2") == 0) {
fprintf(stderr, "Mount second Volume on device %s and press return when ready: ",
dev_name(dev));
} else {
fprintf(stderr, "Mount Volume \"%s\" on device %s and press return when ready: ",
- jcr->VolumeName, dev_name(dev));
+ dcr->VolumeName, dev_name(dev));
}
getchar();
return true;
{
bool autochanger;
DEVICE *dev = dcr->dev;
- JCR *jcr = dcr->jcr;
Dmsg0(20, "Enter dir_ask_sysop_to_create_appendable_volume\n");
if (stop == 0) {
set_volume_name("TestVolume1", 1);
dev_name(dev));
getchar();
}
- open_device(jcr, dev);
+ open_device(dcr);
labelcmd();
VolumeName = NULL;
BlockNumber = 0;
return true;
}
-static bool my_mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
+static bool my_mount_next_read_volume(DCR *dcr)
{
char ec1[50];
+ JCR *jcr = dcr->jcr;
+ DEV_BLOCK *block = dcr->block;
Dmsg0(20, "Enter my_mount_next_read_volume\n");
- Pmsg1(000, "End of Volume \"%s\"\n", jcr->VolumeName);
+ Pmsg1(000, "End of Volume \"%s\"\n", dcr->VolumeName);
if (LastBlock != block->BlockNumber) {
VolBytes += block->block_len;
Pmsg3(-1, "Read block=%u, VolBytes=%s rate=%.1f KB/s\n", block->BlockNumber,
edit_uint64_with_commas(VolBytes, ec1), (float)kbs);
- if (strcmp(jcr->VolumeName, "TestVolume2") == 0) {
+ if (strcmp(dcr->VolumeName, "TestVolume2") == 0) {
end_of_tape = 1;
return false;
}
close_dev(dev);
dev->state &= ~ST_READ;
if (!acquire_device_for_read(jcr)) {
- Pmsg2(0, "Cannot open Dev=%s, Vol=%s\n", dev_name(dev), jcr->VolumeName);
+ Pmsg2(0, "Cannot open Dev=%s, Vol=%s\n", dev_name(dev), dcr->VolumeName);
return false;
}
return true; /* next volume mounted */
DCR *dcr = jcr->dcr;
VolumeName = VolName;
vol_num = volnum;
- pm_strcpy(&jcr->VolumeName, VolName);
bstrncpy(dev->VolCatInfo.VolCatName, VolName, sizeof(dev->VolCatInfo.VolCatName));
- bstrncpy(jcr->VolCatInfo.VolCatName, VolName, sizeof(jcr->VolCatInfo.VolCatName));
bstrncpy(dcr->VolCatInfo.VolCatName, VolName, sizeof(dcr->VolCatInfo.VolCatName));
bstrncpy(dcr->VolumeName, VolName, sizeof(dcr->VolumeName));
- jcr->VolCatInfo.Slot = volnum;
dcr->VolCatInfo.Slot = volnum;
}
*
* Utility routines for "tool" programs such as bscan, bls,
* bextract, ... Some routines also used by Bacula.
+ *
+ * Kern Sibbald, MM
*
* Normally nothing in this file is called by the Storage
* daemon because we interact more directly with the user
* Version $Id$
*/
/*
- Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
+ Copyright (C) 2000-2004 Kern Sibbald and John Walker
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
#include "bacula.h"
#include "stored.h"
+/* Forward referenced functions */
+static DCR *setup_to_access_device(JCR *jcr, char *dev_name, const char *VolumeName, int mode);
+static DEVRES *find_device_res(char *device_name, int mode);
+static void my_free_jcr(JCR *jcr);
+
/* Imported variables -- eliminate some day */
extern char *configfile;
}
#endif
+/*
+ * Setup a "daemon" JCR for the various standalone
+ * tools (e.g. bls, bextract, bscan, ...)
+ */
+JCR *setup_jcr(const char *name, char *dev_name, BSR *bsr,
+ const char *VolumeName, int mode)
+{
+ DCR *dcr;
+ JCR *jcr = new_jcr(sizeof(JCR), my_free_jcr);
+ jcr->bsr = bsr;
+ jcr->VolSessionId = 1;
+ jcr->VolSessionTime = (uint32_t)time(NULL);
+ jcr->NumVolumes = 0;
+ jcr->JobId = 0;
+ jcr->JobType = JT_CONSOLE;
+ jcr->JobLevel = L_FULL;
+ jcr->JobStatus = JS_Terminated;
+ jcr->where = bstrdup("");
+ jcr->job_name = get_pool_memory(PM_FNAME);
+ pm_strcpy(jcr->job_name, "Dummy.Job.Name");
+ jcr->client_name = get_pool_memory(PM_FNAME);
+ pm_strcpy(jcr->client_name, "Dummy.Client.Name");
+ bstrncpy(jcr->Job, name, sizeof(jcr->Job));
+ jcr->fileset_name = get_pool_memory(PM_FNAME);
+ pm_strcpy(jcr->fileset_name, "Dummy.fileset.name");
+ jcr->fileset_md5 = get_pool_memory(PM_FNAME);
+ pm_strcpy(jcr->fileset_md5, "Dummy.fileset.md5");
+
+ dcr = setup_to_access_device(jcr, dev_name, VolumeName, mode);
+ if (!dcr) {
+ return NULL;
+ }
+ if (!bsr && VolumeName) {
+ bstrncpy(dcr->VolumeName, VolumeName, sizeof(dcr->VolumeName));
+ }
+ strcpy(dcr->pool_name, "Default");
+ strcpy(dcr->pool_type, "Backup");
+ return jcr;
+}
/*
* Setup device, jcr, and prepare to access device.
* If the caller wants read access, acquire the device, otherwise,
* the caller will do it.
*/
-DEVICE *setup_to_access_device(JCR *jcr, int read_access)
+static DCR *setup_to_access_device(JCR *jcr, char *dev_name, const char *VolumeName, int mode)
{
DEVICE *dev;
char *p;
DEVRES *device;
+ DCR *dcr;
+ char VolName[MAX_NAME_LENGTH];
/*
* If no volume name already given and no bsr, and it is a file,
* try getting name from Filename
*/
- if (!jcr->bsr && jcr->VolumeName[0] == 0) {
- if (strncmp(jcr->dev_name, "/dev/", 5) != 0) {
+ VolName[0] = 0;
+ if (!jcr->bsr && VolumeName[0] == 0) {
+ if (strncmp(dev_name, "/dev/", 5) != 0) {
/* Try stripping file part */
- p = jcr->dev_name + strlen(jcr->dev_name);
- while (p >= jcr->dev_name && *p != '/')
+ p = dev_name + strlen(dev_name);
+
+ while (p >= dev_name && *p != '/')
p--;
if (*p == '/') {
- pm_strcpy(&jcr->VolumeName, p+1);
+ bstrncpy(VolName, p+1, sizeof(VolName));
*p = 0;
}
}
}
- if ((device=find_device_res(jcr->dev_name, read_access)) == NULL) {
+ if ((device=find_device_res(dev_name, mode)) == NULL) {
Jmsg2(jcr, M_FATAL, 0, _("Cannot find device \"%s\" in config file %s.\n"),
- jcr->dev_name, configfile);
+ dev_name, configfile);
return NULL;
}
jcr->device = device;
- pm_strcpy(&jcr->dev_name, device->device_name);
dev = init_dev(NULL, device);
if (!dev) {
- Jmsg1(jcr, M_FATAL, 0, _("Cannot init device %s\n"), jcr->dev_name);
+ Jmsg1(jcr, M_FATAL, 0, _("Cannot init device %s\n"), dev_name);
return NULL;
}
- jcr->device->dev = dev;
- new_dcr(jcr, dev);
- if (!dev || !first_open_device(dev)) {
- Jmsg1(jcr, M_FATAL, 0, _("Cannot open %s\n"), jcr->dev_name);
+ device->dev = dev;
+ dcr = new_dcr(jcr, dev);
+ if (VolName[0]) {
+ bstrncpy(dcr->VolumeName, VolName, sizeof(dcr->VolumeName));
+ }
+ bstrncpy(dcr->dev_name, device->device_name, sizeof(dcr->dev_name));
+ if (!first_open_device(dev)) {
+ Jmsg1(jcr, M_FATAL, 0, _("Cannot open %s\n"), dcr->dev_name);
return NULL;
}
Dmsg0(90, "Device opened for read.\n");
create_vol_list(jcr);
- if (read_access) {
+ if (mode) { /* read only access? */
if (!acquire_device_for_read(jcr)) {
return NULL;
}
}
- return dev;
+ return dcr;
+}
+
+
+/*
+ * Called here when freeing JCR so that we can get rid
+ * of "daemon" specific memory allocated.
+ */
+static void my_free_jcr(JCR *jcr)
+{
+ if (jcr->job_name) {
+ free_pool_memory(jcr->job_name);
+ jcr->job_name = NULL;
+ }
+ if (jcr->client_name) {
+ free_pool_memory(jcr->client_name);
+ jcr->client_name = NULL;
+ }
+ if (jcr->fileset_name) {
+ free_pool_memory(jcr->fileset_name);
+ jcr->fileset_name = NULL;
+ }
+ if (jcr->fileset_md5) {
+ free_pool_memory(jcr->fileset_md5);
+ jcr->fileset_md5 = NULL;
+ }
+ if (jcr->VolList) {
+ free_vol_list(jcr);
+ }
+ if (jcr->dcr) {
+ free_dcr(jcr->dcr);
+ jcr->dcr = NULL;
+ }
+ return;
}
* Returns: NULL on failure
* Device resource pointer on success
*/
-DEVRES *find_device_res(char *device_name, int read_access)
+static DEVRES *find_device_res(char *device_name, int read_access)
{
bool found = false;
DEVRES *device;
strcpy(device_name, device_name+1);
int len = strlen(device_name);
if (len > 0) {
- device_name[len-1] = 0;
+ device_name[len-1] = 0; /* zap trailing " */
}
}
foreach_res(device, R_DEVICE) {
}
-
-/*
- * Called here when freeing JCR so that we can get rid
- * of "daemon" specific memory allocated.
- */
-static void my_free_jcr(JCR *jcr)
-{
- if (jcr->pool_name) {
- free_pool_memory(jcr->pool_name);
- jcr->pool_name = NULL;
- }
- if (jcr->pool_type) {
- free_pool_memory(jcr->pool_type);
- jcr->pool_type = NULL;
- }
- if (jcr->job_name) {
- free_pool_memory(jcr->job_name);
- jcr->job_name = NULL;
- }
- if (jcr->client_name) {
- free_pool_memory(jcr->client_name);
- jcr->client_name = NULL;
- }
- if (jcr->fileset_name) {
- free_pool_memory(jcr->fileset_name);
- jcr->fileset_name = NULL;
- }
- if (jcr->fileset_md5) {
- free_pool_memory(jcr->fileset_md5);
- jcr->fileset_md5 = NULL;
- }
- if (jcr->dev_name) {
- free_pool_memory(jcr->dev_name);
- jcr->dev_name = NULL;
- }
- if (jcr->VolList) {
- free_vol_list(jcr);
- }
- if (jcr->dcr) {
- free_dcr(jcr->dcr);
- jcr->dcr = NULL;
- }
- return;
-}
-
-/*
- * Setup a "daemon" JCR for the various standalone
- * tools (e.g. bls, bextract, bscan, ...)
- */
-JCR *setup_jcr(const char *name, const char *device, BSR *bsr, const char *VolumeName)
-{
- JCR *jcr = new_jcr(sizeof(JCR), my_free_jcr);
- jcr->VolSessionId = 1;
- jcr->VolSessionTime = (uint32_t)time(NULL);
- jcr->bsr = bsr;
- jcr->NumVolumes = 0;
- jcr->pool_name = get_pool_memory(PM_FNAME);
- strcpy(jcr->pool_name, "Default");
- jcr->pool_type = get_pool_memory(PM_FNAME);
- strcpy(jcr->pool_type, "Backup");
- jcr->job_name = get_pool_memory(PM_FNAME);
- pm_strcpy(&jcr->job_name, "Dummy.Job.Name");
- jcr->client_name = get_pool_memory(PM_FNAME);
- pm_strcpy(&jcr->client_name, "Dummy.Client.Name");
- bstrncpy(jcr->Job, name, sizeof(jcr->Job));
- jcr->fileset_name = get_pool_memory(PM_FNAME);
- pm_strcpy(&jcr->fileset_name, "Dummy.fileset.name");
- jcr->fileset_md5 = get_pool_memory(PM_FNAME);
- pm_strcpy(&jcr->fileset_md5, "Dummy.fileset.md5");
- jcr->JobId = 0;
- jcr->JobType = JT_CONSOLE;
- jcr->JobLevel = L_FULL;
- jcr->JobStatus = JS_Terminated;
- jcr->dev_name = get_pool_memory(PM_FNAME);
- pm_strcpy(&jcr->dev_name, device);
- if (!bsr && VolumeName) {
- pm_strcpy(&jcr->VolumeName, VolumeName);
- }
- jcr->where = bstrdup("");
- return jcr;
-}
-
-
/*
* Device got an error, attempt to analyse it
*/
Dmsg1(20, "Device status: %x\n", status);
if (status & BMT_EOD)
Jmsg(jcr, M_ERROR, 0, _("Unexpected End of Data\n"));
- else if (status & BMT_EOT)
+ else if (status & BMT_EOT)
Jmsg(jcr, M_ERROR, 0, _("Unexpected End of Tape\n"));
else if (status & BMT_EOF)
Jmsg(jcr, M_ERROR, 0, _("Unexpected End of File\n"));
/* Check that device is available */
if (stat(device->device_name, &statp) < 0) {
+ berrno be;
if (dev) {
dev->dev_errno = errno;
}
Emsg2(M_FATAL, 0, "Unable to stat device %s : %s\n", device->device_name,
- strerror(errno));
+ be.strerror());
return NULL;
}
tape = false;
*dev->errmsg = 0;
if ((errstat = pthread_mutex_init(&dev->mutex, NULL)) != 0) {
+ berrno be;
dev->dev_errno = errstat;
- Mmsg1(&dev->errmsg, _("Unable to init mutex: ERR=%s\n"), strerror(errstat));
+ Mmsg1(dev->errmsg, _("Unable to init mutex: ERR=%s\n"), be.strerror(errstat));
Emsg0(M_FATAL, 0, dev->errmsg);
}
if ((errstat = pthread_cond_init(&dev->wait, NULL)) != 0) {
+ berrno be;
dev->dev_errno = errstat;
- Mmsg1(&dev->errmsg, _("Unable to init cond variable: ERR=%s\n"), strerror(errstat));
+ Mmsg1(dev->errmsg, _("Unable to init cond variable: ERR=%s\n"), be.strerror(errstat));
Emsg0(M_FATAL, 0, dev->errmsg);
}
if ((errstat = pthread_cond_init(&dev->wait_next_vol, NULL)) != 0) {
+ berrno be;
dev->dev_errno = errstat;
- Mmsg1(&dev->errmsg, _("Unable to init cond variable: ERR=%s\n"), strerror(errstat));
+ Mmsg1(dev->errmsg, _("Unable to init cond variable: ERR=%s\n"), be.strerror(errstat));
Emsg0(M_FATAL, 0, dev->errmsg);
}
if ((errstat = pthread_mutex_init(&dev->spool_mutex, NULL)) != 0) {
+ berrno be;
dev->dev_errno = errstat;
- Mmsg1(&dev->errmsg, _("Unable to init mutex: ERR=%s\n"), strerror(errstat));
+ Mmsg1(dev->errmsg, _("Unable to init mutex: ERR=%s\n"), be.strerror(errstat));
Emsg0(M_FATAL, 0, dev->errmsg);
}
if ((errstat = rwl_init(&dev->lock)) != 0) {
+ berrno be;
dev->dev_errno = errstat;
- Mmsg1(&dev->errmsg, _("Unable to init mutex: ERR=%s\n"), strerror(errstat));
+ Mmsg1(dev->errmsg, _("Unable to init mutex: ERR=%s\n"), be.strerror(errstat));
Emsg0(M_FATAL, 0, dev->errmsg);
}
}
if (dev->state & ST_EOT) {
dev->dev_errno = 0;
- Mmsg1(&dev->errmsg, _("Device %s at End of Tape.\n"), dev->dev_name);
+ Mmsg1(dev->errmsg, _("Device %s at End of Tape.\n"), dev->dev_name);
return false;
}
if (dev->state & ST_EOF) {
mt_com.mt_count = num;
stat = ioctl(dev->fd, MTIOCTOP, (char *)&mt_com);
if (stat < 0 || ioctl(dev->fd, MTIOCGET, (char *)&mt_stat) < 0) {
+ berrno be;
dev->state |= ST_EOT;
Dmsg0(200, "Set ST_EOT\n");
clrerror_dev(dev, MTFSF);
- Mmsg2(&dev->errmsg, _("ioctl MTFSF error on %s. ERR=%s.\n"),
- dev->dev_name, strerror(dev->dev_errno));
+ Mmsg2(dev->errmsg, _("ioctl MTFSF error on %s. ERR=%s.\n"),
+ dev->dev_name, be.strerror());
Dmsg1(200, "%s", dev->errmsg);
return false;
}
if (errno == ENOMEM) { /* tape record exceeds buf len */
stat = rbuf_len; /* This is OK */
} else {
+ berrno be;
dev->state |= ST_EOT;
clrerror_dev(dev, -1);
Dmsg2(200, "Set ST_EOT read errno=%d. ERR=%s\n", dev->dev_errno,
- strerror(dev->dev_errno));
- Mmsg2(&dev->errmsg, _("read error on %s. ERR=%s.\n"),
- dev->dev_name, strerror(dev->dev_errno));
+ be.strerror());
+ Mmsg2(dev->errmsg, _("read error on %s. ERR=%s.\n"),
+ dev->dev_name, be.strerror(dev->dev_errno));
Dmsg1(200, "%s", dev->errmsg);
break;
}
}
if (dev->state & ST_EOT) {
dev->dev_errno = 0;
- Mmsg1(&dev->errmsg, _("Device %s at End of Tape.\n"), dev->dev_name);
+ Mmsg1(dev->errmsg, _("Device %s at End of Tape.\n"), dev->dev_name);
stat = -1;
} else {
stat = 0;
if (dev->fd < 0) {
dev->dev_errno = EBADF;
- Mmsg0(&dev->errmsg, _("Bad call to bsf_dev. Archive device not open\n"));
+ Mmsg0(dev->errmsg, _("Bad call to bsf_dev. Archive device not open\n"));
Emsg0(M_FATAL, 0, dev->errmsg);
return false;
}
if (!(dev_state(dev, ST_TAPE))) {
- Mmsg1(&dev->errmsg, _("Device %s cannot BSF because it is not a tape.\n"),
+ Mmsg1(dev->errmsg, _("Device %s cannot BSF because it is not a tape.\n"),
dev->dev_name);
return false;
}
stat = ioctl(dev->fd, MTIOCTOP, (char *)&mt_com);
if (stat < 0) {
clrerror_dev(dev, MTBSF);
- Mmsg2(&dev->errmsg, _("ioctl MTBSF error on %s. ERR=%s.\n"),
+ Mmsg2(dev->errmsg, _("ioctl MTBSF error on %s. ERR=%s.\n"),
dev->dev_name, strerror(dev->dev_errno));
}
update_pos_dev(dev);
if (dev->fd < 0) {
dev->dev_errno = EBADF;
- Mmsg0(&dev->errmsg, _("Bad call to fsr_dev. Archive not open\n"));
+ Mmsg0(dev->errmsg, _("Bad call to fsr_dev. Archive not open\n"));
Emsg0(M_FATAL, 0, dev->errmsg);
return false;
}
return false;
}
if (!dev_cap(dev, CAP_FSR)) {
- Mmsg1(&dev->errmsg, _("ioctl MTFSR not permitted on %s.\n"), dev->dev_name);
+ Mmsg1(dev->errmsg, _("ioctl MTFSR not permitted on %s.\n"), dev->dev_name);
return false;
}
}
}
clrerror_dev(dev, MTFSR);
- Mmsg2(&dev->errmsg, _("ioctl MTFSR error on %s. ERR=%s.\n"),
+ Mmsg2(dev->errmsg, _("ioctl MTFSR error on %s. ERR=%s.\n"),
dev->dev_name, strerror(dev->dev_errno));
}
update_pos_dev(dev);
if (dev->fd < 0) {
dev->dev_errno = EBADF;
- Mmsg0(&dev->errmsg, _("Bad call to bsr_dev. Archive not open\n"));
+ Mmsg0(dev->errmsg, _("Bad call to bsr_dev. Archive not open\n"));
Emsg0(M_FATAL, 0, dev->errmsg);
return false;
}
}
if (!dev_cap(dev, CAP_BSR)) {
- Mmsg1(&dev->errmsg, _("ioctl MTBSR not permitted on %s.\n"), dev->dev_name);
+ Mmsg1(dev->errmsg, _("ioctl MTBSR not permitted on %s.\n"), dev->dev_name);
return false;
}
stat = ioctl(dev->fd, MTIOCTOP, (char *)&mt_com);
if (stat < 0) {
clrerror_dev(dev, MTBSR);
- Mmsg2(&dev->errmsg, _("ioctl MTBSR error on %s. ERR=%s.\n"),
+ Mmsg2(dev->errmsg, _("ioctl MTBSR error on %s. ERR=%s.\n"),
dev->dev_name, strerror(dev->dev_errno));
}
update_pos_dev(dev);
{
if (dev->fd < 0) {
dev->dev_errno = EBADF;
- Mmsg0(&dev->errmsg, _("Bad call to reposition_dev. Archive not open\n"));
+ Mmsg0(dev->errmsg, _("Bad call to reposition_dev. Archive not open\n"));
Emsg0(M_FATAL, 0, dev->errmsg);
return false;
}
Dmsg1(100, "===== lseek to %d\n", (int)pos);
if (lseek(dev->fd, pos, SEEK_SET) == (off_t)-1) {
dev->dev_errno = errno;
- Mmsg2(&dev->errmsg, _("lseek error on %s. ERR=%s.\n"),
+ Mmsg2(dev->errmsg, _("lseek error on %s. ERR=%s.\n"),
dev->dev_name, strerror(dev->dev_errno));
return false;
}
bsf_dev(dev, 1);
fsf_dev(dev, 1);
}
- if (block > dev->block_num) {
+ if (dev_cap(dev, CAP_POSITIONBLOCKS) && block > dev->block_num) {
/* Ignore errors as Bacula can read to the correct block */
Dmsg1(100, "fsr %d\n", block-dev->block_num);
return fsr_dev(dev, block-dev->block_num);
if (dev->fd < 0) {
dev->dev_errno = EBADF;
- Mmsg0(&dev->errmsg, _("Bad call to weof_dev. Archive drive not open\n"));
+ Mmsg0(dev->errmsg, _("Bad call to weof_dev. Archive drive not open\n"));
Emsg0(M_FATAL, 0, dev->errmsg);
return -1;
}
dev->file += num;
dev->file_addr = 0;
} else {
+ berrno be;
clrerror_dev(dev, MTWEOF);
if (stat == -1) {
- Mmsg2(&dev->errmsg, _("ioctl MTWEOF error on %s. ERR=%s.\n"),
- dev->dev_name, strerror(dev->dev_errno));
+ Mmsg2(dev->errmsg, _("ioctl MTWEOF error on %s. ERR=%s.\n"),
+ dev->dev_name, be.strerror());
}
}
return stat;
* Definitions for using the Device functions in Bacula
* Tape and File storage access
*
+ * Kern Sibbald, MM
+ *
* Version $Id$
*
*/
#define CAP_FASTFSF (1<<16) /* Fast forward space file */
#define CAP_TWOEOF (1<<17) /* Write two eofs for EOM */
#define CAP_CLOSEONPOLL (1<<18) /* Close device on polling */
+#define CAP_POSITIONBLOCKS (1<<19) /* Use block positioning */
/* Test state */
#define dev_state(dev, st_state) ((dev)->state & (st_state))
* the device. Items in this record are "local" to the Job and
* do not affect other Jobs.
*/
-struct DCR {
+class DCR {
+public:
dlink dev_link; /* link to attach to dev */
JCR *jcr; /* pointer to JCR */
DEVICE *dev; /* pointer to device */
int64_t spool_size; /* Current spool size */
int64_t max_spool_size; /* Max job spool size */
char VolumeName[MAX_NAME_LENGTH]; /* Volume name */
+ char pool_name[MAX_NAME_LENGTH]; /* pool name */
+ char pool_type[MAX_NAME_LENGTH]; /* pool type */
+ char media_type[MAX_NAME_LENGTH]; /* media type */
+ char dev_name[MAX_NAME_LENGTH]; /* dev name */
VOLUME_CAT_INFO VolCatInfo; /* Catalog info for desired volume */
};
* Attempt to "recover" by obtaining a new Volume.
*
* Here are a few things to know:
- * jcr->VolCatInfo contains the info on the "current" tape for this job.
+ * dcr->VolCatInfo contains the info on the "current" tape for this job.
* dev->VolCatInfo contains the info on the tape in the drive.
* The tape in the drive could have changed several times since
* the last time the job used it (jcr->VolCatInfo).
- * jcr->VolumeName is the name of the current/desired tape in the drive.
+ * dcr->VolumeName is the name of the current/desired tape in the drive.
*
* We enter with device locked, and
* exit with device locked.
* Returns: true on success
* false on failure
*/
-bool fixup_device_block_write_error(DCR *dcr, DEV_BLOCK *block)
+bool fixup_device_block_write_error(DCR *dcr)
{
uint32_t stat;
char PrevVolName[MAX_NAME_LENGTH];
DEV_BLOCK *label_blk;
+ DEV_BLOCK *block = dcr->block;
char b1[30], b2[30];
time_t wait_time;
char dt[MAX_TIME_LENGTH];
/* Create a jobmedia record for this job */
if (!dir_create_jobmedia_record(dcr)) {
Jmsg(jcr, M_ERROR, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
- jcr->VolCatInfo.VolCatName, jcr->Job);
+ dcr->VolCatInfo.VolCatName, jcr->Job);
P(dev->mutex);
unblock_device(dev);
return false;
bstrncpy(dev->VolHdr.PrevVolName, PrevVolName, sizeof(dev->VolHdr.PrevVolName));
label_blk = new_block(dev);
+ dcr->block = label_blk;
/* Inform User about end of medium */
Jmsg(jcr, M_INFO, 0, _("End of medium on Volume \"%s\" Bytes=%s Blocks=%s at %s.\n"),
edit_uint64_with_commas(dev->VolCatInfo.VolCatBlocks, b2),
bstrftime(dt, sizeof(dt), time(NULL)));
- if (!mount_next_write_volume(dcr, label_blk, 1)) {
+ if (!mount_next_write_volume(dcr, 1)) {
free_block(label_blk);
+ dcr->block = block;
P(dev->mutex);
unblock_device(dev);
return false; /* device locked */
P(dev->mutex); /* lock again */
Jmsg(jcr, M_INFO, 0, _("New volume \"%s\" mounted on device %s at %s.\n"),
- jcr->VolumeName, dev_name(dev), bstrftime(dt, sizeof(dt), time(NULL)));
+ dcr->VolumeName, dev_name(dev), bstrftime(dt, sizeof(dt), time(NULL)));
/*
* If this is a new tape, the label_blk will contain the
* empty label_blk, and nothing will be written.
*/
Dmsg0(190, "write label block to dev\n");
- if (!write_block_to_dev(dcr, label_blk)) {
+ if (!write_block_to_dev(dcr)) {
Pmsg1(0, "write_block_to_device Volume label failed. ERR=%s",
strerror_dev(dev));
free_block(label_blk);
+ dcr->block = block;
unblock_device(dev);
return false; /* device locked */
}
free_block(label_blk);
+ dcr->block = block;
/*
* Walk through all attached jcrs indicating the volume has changed
}
mdcr->NewVol = true;
if (jcr != mjcr) {
- pm_strcpy(&mjcr->VolumeName, jcr->VolumeName); /* get a copy of the new volume */
- bstrncpy(mdcr->VolumeName, jcr->VolumeName, sizeof(mdcr->VolumeName));
+ bstrncpy(mdcr->VolumeName, dcr->VolumeName, sizeof(mdcr->VolumeName));
}
}
/* Write overflow block to device */
Dmsg0(190, "Write overflow block to dev\n");
- if (!write_block_to_dev(dcr, block)) {
+ if (!write_block_to_dev(dcr)) {
Pmsg1(0, "write_block_to_device overflow block failed. ERR=%s",
strerror_dev(dev));
unblock_device(dev);
/*
* Make sure device is open, if not do so
*/
-bool open_device(JCR *jcr, DEVICE *dev)
+bool open_device(DCR *dcr)
{
+ DEVICE *dev = dcr->dev;
/* Open device */
if (!(dev_state(dev, ST_OPENED))) {
int mode;
} else {
mode = OPEN_READ_WRITE;
}
- if (open_dev(dev, jcr->VolCatInfo.VolCatName, mode) < 0) {
+ if (open_dev(dev, dcr->VolCatInfo.VolCatName, mode) < 0) {
/* If polling, ignore the error */
if (!dev->poll) {
- Jmsg2(jcr, M_FATAL, 0, _("Unable to open device %s. ERR=%s\n"),
+ Jmsg2(dcr->jcr, M_FATAL, 0, _("Unable to open device %s. ERR=%s\n"),
dev_name(dev), strerror_dev(dev));
}
return false;
/* Imported functions */
extern void terminate_child();
-extern int job_cmd(JCR *jcr);
-extern int status_cmd(JCR *sjcr);
-extern int qstatus_cmd(JCR *jcr);
+extern bool job_cmd(JCR *jcr);
+extern bool status_cmd(JCR *sjcr);
+extern bool qstatus_cmd(JCR *jcr);
/* Forward referenced functions */
-static int label_cmd(JCR *jcr);
-static int relabel_cmd(JCR *jcr);
-static int readlabel_cmd(JCR *jcr);
-static int release_cmd(JCR *jcr);
-static int setdebug_cmd(JCR *jcr);
-static int cancel_cmd(JCR *cjcr);
-static int mount_cmd(JCR *jcr);
-static int unmount_cmd(JCR *jcr);
-static int autochanger_cmd(JCR *sjcr);
-static int do_label(JCR *jcr, int relabel);
-static DEVICE *find_device(JCR *jcr, char *dname);
+static bool label_cmd(JCR *jcr);
+static bool relabel_cmd(JCR *jcr);
+static bool readlabel_cmd(JCR *jcr);
+static bool release_cmd(JCR *jcr);
+static bool setdebug_cmd(JCR *jcr);
+static bool cancel_cmd(JCR *cjcr);
+static bool mount_cmd(JCR *jcr);
+static bool unmount_cmd(JCR *jcr);
+static bool autochanger_cmd(JCR *sjcr);
+static bool do_label(JCR *jcr, int relabel);
+static DEVICE *find_device(JCR *jcr, POOL_MEM &dname);
static void read_volume_label(JCR *jcr, DEVICE *dev, int Slot);
static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *oldname,
char *newname, char *poolname,
struct s_cmds {
const char *cmd;
- int (*func)(JCR *jcr);
+ bool (*func)(JCR *jcr);
int monitoraccess; /* specify if monitors have access to this function */
};
* The following are the recognized commands from the Director.
*/
static struct s_cmds cmds[] = {
- {"JobId=", job_cmd, 0}, /* start Job */
- {"setdebug=", setdebug_cmd, 0}, /* set debug level */
- {"cancel", cancel_cmd, 0},
- {"label", label_cmd, 0}, /* label a tape */
- {"relabel", relabel_cmd, 0}, /* relabel a tape */
- {"mount", mount_cmd, 0},
- {"unmount", unmount_cmd, 0},
- {"status", status_cmd, 1},
- {".status", qstatus_cmd, 1},
+ {"JobId=", job_cmd, 0}, /* start Job */
{"autochanger", autochanger_cmd, 0},
- {"release", release_cmd, 0},
- {"readlabel", readlabel_cmd, 0},
+ {"bootstrap", bootstrap_cmd, 0},
+ {"cancel", cancel_cmd, 0},
+ {"label", label_cmd, 0}, /* label a tape */
+ {"mount", mount_cmd, 0},
+ {"readlabel", readlabel_cmd, 0},
+ {"release", release_cmd, 0},
+ {"relabel", relabel_cmd, 0}, /* relabel a tape */
+ {"setdebug=", setdebug_cmd, 0}, /* set debug level */
+ {"status", status_cmd, 1},
+ {".status", qstatus_cmd, 1},
+ {"unmount", unmount_cmd, 0},
{NULL, NULL} /* list terminator */
};
* Do a sanity check on the message received
*/
if (bs->msglen < 25 || bs->msglen > (int)sizeof(name)-25) {
- Emsg1(M_ERROR, 0, _("Invalid Dir connection. Len=%d\n"), bs->msglen);
+ Emsg1(M_ERROR, 0, _("Invalid connection. Len=%d\n"), bs->msglen);
bnet_close(bs);
return NULL;
}
}
Dmsg0(110, "Start Dir Job\n");
- jcr = new_jcr(sizeof(JCR), stored_free_jcr); /* create Job Control Record */
+ jcr = new_jcr(sizeof(JCR), stored_free_jcr); /* create Job Control Record */
jcr->dir_bsock = bs; /* save Director bsock */
jcr->dir_bsock->jcr = jcr;
/* Initialize FD start condition variable */
int errstat = pthread_cond_init(&jcr->job_start_wait, NULL);
if (errstat != 0) {
Jmsg1(jcr, M_FATAL, 0, _("Unable to init job cond variable: ERR=%s\n"), strerror(errstat));
- free_jcr(jcr);
- return NULL;
+ goto bail_out;
}
Dmsg0(1000, "stored in start_job\n");
*/
if (!authenticate_director(jcr)) {
Jmsg(jcr, M_FATAL, 0, _("Unable to authenticate Director\n"));
- free_jcr(jcr);
- return NULL;
+ goto bail_out;
}
Dmsg0(90, "Message channel init completed.\n");
}
if (!found) { /* command not found */
bnet_fsend(bs, derrmsg);
- quit = true;
break;
}
}
+bail_out:
dequeue_messages(jcr); /* send any queued messages */
bnet_sig(bs, BNET_TERMINATE);
free_jcr(jcr);
* Set debug level as requested by the Director
*
*/
-static int setdebug_cmd(JCR *jcr)
+static bool setdebug_cmd(JCR *jcr)
{
BSOCK *dir = jcr->dir_bsock;
int level, trace_flag;
/*
* Cancel a Job
*/
-static int cancel_cmd(JCR *cjcr)
+static bool cancel_cmd(JCR *cjcr)
{
BSOCK *dir = cjcr->dir_bsock;
int oldStatus;
* Label a tape
*
*/
-static int label_cmd(JCR *jcr)
+static bool label_cmd(JCR *jcr)
{
return do_label(jcr, 0);
}
-static int relabel_cmd(JCR *jcr)
+static bool relabel_cmd(JCR *jcr)
{
return do_label(jcr, 1);
}
-static int do_label(JCR *jcr, int relabel)
+static bool do_label(JCR *jcr, int relabel)
{
- POOLMEM *dname, *newname, *oldname, *poolname, *mtype;
+ POOLMEM *newname, *oldname, *poolname, *mtype;
+ POOL_MEM dname;
BSOCK *dir = jcr->dir_bsock;
DEVICE *dev;
bool ok = false;
int slot;
- dname = get_memory(dir->msglen+1);
newname = get_memory(dir->msglen+1);
oldname = get_memory(dir->msglen+1);
poolname = get_memory(dir->msglen+1);
mtype = get_memory(dir->msglen+1);
if (relabel) {
- if (sscanf(dir->msg, "relabel %s OldName=%s NewName=%s PoolName=%s MediaType=%s Slot=%d",
- dname, oldname, newname, poolname, mtype, &slot) == 6) {
+ if (sscanf(dir->msg, "relabel %127s OldName=%127s NewName=%127s PoolName=127%s MediaType=%127s Slot=%d",
+ dname.c_str(), oldname, newname, poolname, mtype, &slot) == 6) {
ok = true;
}
} else {
*oldname = 0;
- if (sscanf(dir->msg, "label %s VolumeName=%s PoolName=%s MediaType=%s Slot=%d",
- dname, newname, poolname, mtype, &slot) == 5) {
+ if (sscanf(dir->msg, "label %127s VolumeName=%127s PoolName=%127s MediaType=%127s Slot=%d",
+ dname.c_str(), newname, poolname, mtype, &slot) == 5) {
ok = true;
}
}
}
V(dev->mutex);
} else {
- bnet_fsend(dir, _("3999 Device %s not found\n"), dname);
+ bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), dname.c_str());
}
} else {
/* NB dir->msg gets clobbered in bnet_fsend, so save command */
- pm_strcpy(&jcr->errmsg, dir->msg);
+ pm_strcpy(jcr->errmsg, dir->msg);
bnet_fsend(dir, _("3903 Error scanning label command: %s\n"), jcr->errmsg);
}
- free_memory(dname);
free_memory(oldname);
free_memory(newname);
free_memory(poolname);
free_memory(mtype);
bnet_sig(dir, BNET_EOD);
- return 1;
+ return true;
}
/*
int slot, int relabel)
{
BSOCK *dir = jcr->dir_bsock;
- DEV_BLOCK *block;
bsteal_lock_t hold;
DCR *dcr = jcr->dcr;
+ int label_status;
steal_device_lock(dev, &hold, BST_WRITING_LABEL);
- block = new_block(dev);
- pm_strcpy(&jcr->VolumeName, newname);
- jcr->VolCatInfo.Slot = slot;
+ bstrncpy(dcr->VolumeName, newname, sizeof(dcr->VolumeName));
+ dcr->VolCatInfo.Slot = slot;
if (autoload_device(dcr, 0, dir) < 0) { /* autoload if possible */
goto bail_out;
}
/* Ensure that the device is open -- autoload_device() closes it */
for ( ; !(dev->state & ST_OPENED); ) {
- if (open_dev(dev, jcr->VolumeName, OPEN_READ_WRITE) < 0) {
+ if (open_dev(dev, dcr->VolumeName, OPEN_READ_WRITE) < 0) {
bnet_fsend(dir, _("3910 Unable to open device %s. ERR=%s\n"),
dev_name(dev), strerror_dev(dev));
goto bail_out;
}
/* See what we have for a Volume */
- switch (read_dev_volume_label(dcr, block)) {
+ label_status = read_dev_volume_label(dcr);
+ switch(label_status) {
case VOL_NAME_ERROR:
case VOL_VERSION_ERROR:
case VOL_LABEL_ERROR:
bnet_fsend(dir, _("3912 Failed to label Volume: ERR=%s\n"), strerror_dev(dev));
break;
}
- pm_strcpy(&jcr->VolumeName, newname);
+ bstrncpy(dcr->VolumeName, newname, sizeof(dcr->VolumeName));
/* The following 3000 OK label. string is scanned in ua_label.c */
bnet_fsend(dir, "3000 OK label. Volume=%s Device=%s\n",
newname, dev_name(dev));
break;
default:
bnet_fsend(dir, _("3913 Cannot label Volume. \
-Unknown status %d from read_volume_label()\n"), jcr->label_status);
+Unknown status %d from read_volume_label()\n"), label_status);
break;
}
+
bail_out:
- free_block(block);
give_back_device_lock(dev, &hold);
return;
}
*
* Enter with the mutex set
*/
-static int read_label(JCR *jcr, DEVICE *dev)
+static bool read_label(DCR *dcr)
{
- int stat;
+ int ok;
+ JCR *jcr = dcr->jcr;
BSOCK *dir = jcr->dir_bsock;
- DEV_BLOCK *block;
bsteal_lock_t hold;
- DCR *dcr = jcr->dcr;
+ DEVICE *dev = dcr->dev;
steal_device_lock(dev, &hold, BST_DOING_ACQUIRE);
- jcr->VolumeName[0] = 0;
- block = new_block(dev);
+ dcr->VolumeName[0] = 0;
dev->state &= ~ST_LABEL; /* force read of label */
- switch (read_dev_volume_label(dcr, block)) {
+ switch (read_dev_volume_label(dcr)) {
case VOL_OK:
bnet_fsend(dir, _("3001 Mounted Volume: %s\n"), dev->VolHdr.VolName);
- stat = 1;
+ ok = true;
break;
default:
bnet_fsend(dir, _("3902 Cannot mount Volume on Storage Device \"%s\" because:\n%s"),
dev_name(dev), jcr->errmsg);
- stat = 0;
+ ok = false;
break;
}
- free_block(block);
give_back_device_lock(dev, &hold);
- return stat;
+ return ok;
}
-static DEVICE *find_device(JCR *jcr, char *dname)
+static DEVICE *find_device(JCR *jcr, POOL_MEM &dname)
{
DEVRES *device;
bool found = false;
LockRes();
foreach_res(device, R_DEVICE) {
/* Find resource, and make sure we were able to open it */
- if (strcmp(device->hdr.name, dname) == 0 && device->dev) {
+ if (strcmp(device->hdr.name, dname.c_str()) == 0 && device->dev) {
Dmsg1(20, "Found device %s\n", device->hdr.name);
jcr->device = device;
found = true;
/*
* Mount command from Director
*/
-static int mount_cmd(JCR *jcr)
+static bool mount_cmd(JCR *jcr)
{
- POOLMEM *dname;
+ POOL_MEM dname;
BSOCK *dir = jcr->dir_bsock;
DEVICE *dev;
DCR *dcr;
- dname = get_memory(dir->msglen+1);
- if (sscanf(dir->msg, "mount %s", dname) == 1) {
+ if (sscanf(dir->msg, "mount %127s", dname.c_str()) == 1) {
dev = find_device(jcr, dname);
dcr = jcr->dcr;
if (dev) {
- DEV_BLOCK *block;
P(dev->mutex); /* Use P to avoid indefinite block */
switch (dev->dev_blocked) { /* device blocked? */
case BST_WAITING_FOR_SYSOP:
strerror_dev(dev));
break;
}
- block = new_block(dev);
- read_dev_volume_label(dcr, block);
- free_block(block);
+ read_dev_volume_label(dcr);
if (dev->dev_blocked == BST_UNMOUNTED) {
/* We blocked the device, so unblock it */
Dmsg0(100, "Unmounted. Unblocking device\n");
- read_label(jcr, dev); /* this should not be necessary */
+ read_label(dcr); /* this should not be necessary */
unblock_device(dev);
} else {
Dmsg0(100, "Unmounted waiting for mount. Attempting to wake thread\n");
strerror_dev(dev));
break;
}
- read_label(jcr, dev);
+ read_label(dcr);
if (dev_state(dev, ST_LABEL)) {
bnet_fsend(dir, _("3001 Device %s is already mounted with Volume \"%s\"\n"),
dev_name(dev), dev->VolHdr.VolName);
}
V(dev->mutex);
} else {
- bnet_fsend(dir, _("3999 Device %s not found\n"), dname);
+ bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), dname.c_str());
}
} else {
- pm_strcpy(&jcr->errmsg, dir->msg);
+ pm_strcpy(jcr->errmsg, dir->msg);
bnet_fsend(dir, _("3909 Error scanning mount command: %s\n"), jcr->errmsg);
}
- free_memory(dname);
bnet_sig(dir, BNET_EOD);
- return 1;
+ return true;
}
/*
* unmount command from Director
*/
-static int unmount_cmd(JCR *jcr)
+static bool unmount_cmd(JCR *jcr)
{
- POOLMEM *dname;
+ POOL_MEM dname;
BSOCK *dir = jcr->dir_bsock;
DEVICE *dev;
- dname = get_memory(dir->msglen+1);
- if (sscanf(dir->msg, "unmount %s", dname) == 1) {
+ if (sscanf(dir->msg, "unmount %127s", dname.c_str()) == 1) {
dev = find_device(jcr, dname);
if (dev) {
P(dev->mutex); /* Use P to avoid indefinite block */
}
V(dev->mutex);
} else {
- bnet_fsend(dir, _("3999 Device %s not found\n"), dname);
+ bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), dname.c_str());
}
} else {
/* NB dir->msg gets clobbered in bnet_fsend, so save command */
- pm_strcpy(&jcr->errmsg, dir->msg);
+ pm_strcpy(jcr->errmsg, dir->msg);
bnet_fsend(dir, _("3907 Error scanning unmount command: %s\n"), jcr->errmsg);
}
- free_memory(dname);
bnet_sig(dir, BNET_EOD);
- return 1;
+ return true;
}
/*
* the operator the chance to change the tape anytime before the
* next job starts.
*/
-static int release_cmd(JCR *jcr)
+static bool release_cmd(JCR *jcr)
{
- POOLMEM *dname;
+ POOL_MEM dname;
BSOCK *dir = jcr->dir_bsock;
DEVICE *dev;
- dname = get_memory(dir->msglen+1);
- if (sscanf(dir->msg, "release %s", dname) == 1) {
+ if (sscanf(dir->msg, "release %127s", dname.c_str()) == 1) {
dev = find_device(jcr, dname);
if (dev) {
P(dev->mutex); /* Use P to avoid indefinite block */
} else { /* device not being used */
Dmsg0(90, "Device not in use, unmounting\n");
- release_volume(jcr, dev);
+ release_volume(jcr->dcr);
bnet_fsend(dir, _("3012 Device %s released.\n"), dev_name(dev));
}
V(dev->mutex);
} else {
- bnet_fsend(dir, _("3999 Device %s not found\n"), dname);
+ bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), dname.c_str());
}
} else {
/* NB dir->msg gets clobbered in bnet_fsend, so save command */
- pm_strcpy(&jcr->errmsg, dir->msg);
+ pm_strcpy(jcr->errmsg, dir->msg);
bnet_fsend(dir, _("3917 Error scanning release command: %s\n"), jcr->errmsg);
}
- free_memory(dname);
bnet_sig(dir, BNET_EOD);
- return 1;
+ return true;
}
/*
* Autochanger command from Director
*/
-static int autochanger_cmd(JCR *jcr)
+static bool autochanger_cmd(JCR *jcr)
{
- POOLMEM *dname;
+ POOL_MEM dname;
BSOCK *dir = jcr->dir_bsock;
DEVICE *dev;
DCR *dcr;
- dname = get_memory(dir->msglen+1);
- if (sscanf(dir->msg, "autochanger list %s ", dname) == 1) {
+ if (sscanf(dir->msg, "autochanger list %127s ", dname.c_str()) == 1) {
dev = find_device(jcr, dname);
dcr = jcr->dcr;
if (dev) {
}
V(dev->mutex);
} else {
- bnet_fsend(dir, _("3999 Device %s not found\n"), dname);
+ bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), dname.c_str());
}
} else { /* error on scanf */
- pm_strcpy(&jcr->errmsg, dir->msg);
+ pm_strcpy(jcr->errmsg, dir->msg);
bnet_fsend(dir, _("3908 Error scanning autocharger list command: %s\n"),
jcr->errmsg);
}
- free_memory(dname);
bnet_sig(dir, BNET_EOD);
- return 1;
+ return true;
}
/*
* Read and return the Volume label
*/
-static int readlabel_cmd(JCR *jcr)
+static bool readlabel_cmd(JCR *jcr)
{
- POOLMEM *dname;
+ POOL_MEM dname;
BSOCK *dir = jcr->dir_bsock;
DEVICE *dev;
int Slot;
- dname = get_memory(dir->msglen+1);
- if (sscanf(dir->msg, "readlabel %s Slot=%d", dname, &Slot) == 2) {
+ if (sscanf(dir->msg, "readlabel %127s Slot=%d", dname.c_str(), &Slot) == 2) {
dev = find_device(jcr, dname);
if (dev) {
P(dev->mutex); /* Use P to avoid indefinite block */
}
V(dev->mutex);
} else {
- bnet_fsend(dir, _("3999 Device %s not found\n"), dname);
+ bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), dname.c_str());
}
} else {
- pm_strcpy(&jcr->errmsg, dir->msg);
+ pm_strcpy(jcr->errmsg, dir->msg);
bnet_fsend(dir, _("3909 Error scanning readlabel command: %s\n"), jcr->errmsg);
}
- free_memory(dname);
bnet_sig(dir, BNET_EOD);
- return 1;
+ return true;
}
/*
static void read_volume_label(JCR *jcr, DEVICE *dev, int Slot)
{
BSOCK *dir = jcr->dir_bsock;
- DEV_BLOCK *block;
bsteal_lock_t hold;
DCR *dcr = jcr->dcr;
steal_device_lock(dev, &hold, BST_WRITING_LABEL);
- block = new_block(dev);
- jcr->VolumeName[0] = 0;
- jcr->VolCatInfo.Slot = Slot;
+ dcr->VolumeName[0] = 0;
+ dcr->VolCatInfo.Slot = Slot;
if (autoload_device(dcr, 0, dir) < 0) { /* autoload if possible */
goto bail_out;
}
/* Ensure that the device is open -- autoload_device() closes it */
for ( ; !dev_state(dev, ST_OPENED); ) {
- if (open_dev(dev, jcr->VolumeName, OPEN_READ_WRITE) < 0) {
+ if (open_dev(dev, dcr->VolumeName, OPEN_READ_WRITE) < 0) {
bnet_fsend(dir, _("3910 Unable to open device \"%s\". ERR=%s\n"),
dev_name(dev), strerror_dev(dev));
goto bail_out;
}
dev->state &= ~ST_LABEL; /* force read of label */
- switch (read_dev_volume_label(dcr, block)) {
+ switch (read_dev_volume_label(dcr)) {
case VOL_OK:
/* DO NOT add quotes around the Volume name. It is scanned in the DIR */
bnet_fsend(dir, _("3001 Volume=%s Slot=%d\n"), dev->VolHdr.VolName, Slot);
}
bail_out:
- free_block(block);
give_back_device_lock(dev, &hold);
return;
}
/*
* This file handles commands from the File daemon.
*
+ * Kern Sibbald, MM
+ *
* We get here because the Director has initiated a Job with
* the Storage daemon, then done the same with the File daemon,
* then when the Storage daemon receives a proper connection from
extern bool do_append_data(JCR *jcr);
extern bool do_read_data(JCR *jcr);
-/* Forward referenced functions */
-
-
/* Forward referenced FD commands */
-static int append_open_session(JCR *jcr);
-static int append_close_session(JCR *jcr);
-static int append_data_cmd(JCR *jcr);
-static int append_end_session(JCR *jcr);
-static int read_open_session(JCR *jcr);
-static int read_data_cmd(JCR *jcr);
-static int read_close_session(JCR *jcr);
-static int bootstrap_cmd(JCR *jcr);
+static bool append_open_session(JCR *jcr);
+static bool append_close_session(JCR *jcr);
+static bool append_data_cmd(JCR *jcr);
+static bool append_end_session(JCR *jcr);
+static bool read_open_session(JCR *jcr);
+static bool read_data_cmd(JCR *jcr);
+static bool read_close_session(JCR *jcr);
+
+/* Exported function */
+bool bootstrap_cmd(JCR *jcr);
struct s_cmds {
const char *cmd;
- int (*func)(JCR *jcr);
+ bool (*func)(JCR *jcr);
};
/*
*/
void run_job(JCR *jcr)
{
- int i, found, quit;
+ int i;
+ bool found, quit;
BSOCK *fd = jcr->file_bsock;
BSOCK *dir = jcr->dir_bsock;
char ec1[30];
jcr->run_time = jcr->start_time;
set_jcr_job_status(jcr, JS_Running);
dir_send_job_status(jcr); /* update director */
- for (quit=0; !quit;) {
+ for (quit=false; !quit;) {
int stat;
/* Read command coming from the File daemon */
continue; /* ignore signals and zero length msgs */
}
Dmsg1(110, "<filed: %s", fd->msg);
- found = 0;
+ found = false;
for (i=0; fd_cmds[i].cmd; i++) {
if (strncmp(fd_cmds[i].cmd, fd->msg, strlen(fd_cmds[i].cmd)) == 0) {
- found = 1; /* indicate command found */
+ found = true; /* indicate command found */
if (!fd_cmds[i].func(jcr)) { /* do command */
set_jcr_job_status(jcr, JS_ErrorTerminated);
- quit = 1;
+ quit = true;
}
break;
}
* Open Data Channel and receive Data for archiving
* Write the Data to the archive device
*/
-static int append_data_cmd(JCR *jcr)
+static bool append_data_cmd(JCR *jcr)
{
BSOCK *fd = jcr->file_bsock;
Dmsg1(110, "<bfiled: %s", fd->msg);
jcr->JobType = JT_BACKUP;
if (do_append_data(jcr)) {
- bnet_fsend(fd, OK_append);
- return 1;
+ return bnet_fsend(fd, OK_append);
} else {
bnet_suppress_error_messages(fd, 1); /* ignore errors at this point */
bnet_fsend(fd, ERROR_append);
- return 0;
}
} else {
bnet_fsend(fd, NOT_opened);
- return 0;
}
+ return false;
}
-static int append_end_session(JCR *jcr)
+static bool append_end_session(JCR *jcr)
{
BSOCK *fd = jcr->file_bsock;
Dmsg1(120, "store<file: %s", fd->msg);
if (!jcr->session_opened) {
bnet_fsend(fd, NOT_opened);
- return 0;
+ return false;
}
set_jcr_job_status(jcr, JS_Terminated);
return bnet_fsend(fd, OK_end);
* Append Open session command
*
*/
-static int append_open_session(JCR *jcr)
+static bool append_open_session(JCR *jcr)
{
BSOCK *fd = jcr->file_bsock;
Dmsg1(120, "Append open session: %s", fd->msg);
if (jcr->session_opened) {
bnet_fsend(fd, NO_open);
- return 0;
+ return false;
}
Dmsg1(110, "Append open session: %s\n", dev_name(jcr->device->dev));
bnet_fsend(fd, OK_open, jcr->VolSessionId);
Dmsg1(110, ">filed: %s", fd->msg);
- return 1;
+ return true;
}
/*
* Close the append session and send back Statistics
* (need to fix statistics)
*/
-static int append_close_session(JCR *jcr)
+static bool append_close_session(JCR *jcr)
{
BSOCK *fd = jcr->file_bsock;
Dmsg1(120, "<filed: %s\n", fd->msg);
if (!jcr->session_opened) {
bnet_fsend(fd, NOT_opened);
- return 0;
+ return false;
}
/* Send final statistics to File daemon */
bnet_fsend(fd, OK_close, jcr->JobStatus);
Dmsg1(110, "Append close session: %s\n", dev_name(jcr->device->dev));
- jcr->session_opened = FALSE;
- return 1;
+ jcr->session_opened = false;
+ return true;
}
/*
* the archive device and send to File
* daemon.
*/
-static int read_data_cmd(JCR *jcr)
+static bool read_data_cmd(JCR *jcr)
{
BSOCK *fd = jcr->file_bsock;
return do_read_data(jcr);
} else {
bnet_fsend(fd, NOT_opened);
- return 0;
+ return false;
}
}
* We need to scan for the parameters of the job
* to be restored.
*/
-static int read_open_session(JCR *jcr)
+static bool read_open_session(JCR *jcr)
{
BSOCK *fd = jcr->file_bsock;
Dmsg1(120, "%s\n", fd->msg);
if (jcr->session_opened) {
bnet_fsend(fd, NO_open);
- return 0;
+ return false;
}
- if (sscanf(fd->msg, read_open, jcr->VolumeName, &jcr->read_VolSessionId,
+ if (sscanf(fd->msg, read_open, jcr->dcr->VolumeName, &jcr->read_VolSessionId,
&jcr->read_VolSessionTime, &jcr->read_StartFile, &jcr->read_EndFile,
&jcr->read_StartBlock, &jcr->read_EndBlock) == 7) {
if (jcr->session_opened) {
bnet_fsend(fd, NOT_opened);
- return 0;
+ return false;
}
Dmsg4(100, "read_open_session got: JobId=%d Vol=%s VolSessId=%ld VolSessT=%ld\n",
- jcr->JobId, jcr->VolumeName, jcr->read_VolSessionId,
+ jcr->JobId, jcr->dcr->VolumeName, jcr->read_VolSessionId,
jcr->read_VolSessionTime);
Dmsg4(100, " StartF=%ld EndF=%ld StartB=%ld EndB=%ld\n",
jcr->read_StartFile, jcr->read_EndFile, jcr->read_StartBlock,
bnet_fsend(fd, OK_open, jcr->VolSessionId);
Dmsg1(110, ">filed: %s", fd->msg);
- return 1;
+ return true;
}
-static int bootstrap_cmd(JCR *jcr)
+bool bootstrap_cmd(JCR *jcr)
{
BSOCK *fd = jcr->file_bsock;
POOLMEM *fname = get_pool_memory(PM_FNAME);
FILE *bs;
- int stat = 0;
+ bool ok = false;
if (jcr->RestoreBootstrap) {
unlink(jcr->RestoreBootstrap);
if (debug_level > 20) {
dump_bsr(jcr->bsr, true);
}
- stat = 1;
+ ok = true;
bail_out:
unlink(jcr->RestoreBootstrap);
free_pool_memory(jcr->RestoreBootstrap);
jcr->RestoreBootstrap = NULL;
- if (stat) {
- return bnet_fsend(fd, OK_bootstrap);
- } else {
+ if (!ok) {
bnet_fsend(fd, ERROR_bootstrap);
- return 0;
+ return false;
}
+ return bnet_fsend(fd, OK_bootstrap);
}
* Read Close session command
* Close the read session
*/
-static int read_close_session(JCR *jcr)
+static bool read_close_session(JCR *jcr)
{
BSOCK *fd = jcr->file_bsock;
Dmsg1(120, "Read close session: %s\n", fd->msg);
if (!jcr->session_opened) {
bnet_fsend(fd, NOT_opened);
- return 0;
+ return false;
}
/* Send final statistics to File daemon */
bnet_fsend(fd, OK_close);
bnet_sig(fd, BNET_EOD); /* send EOD to File daemon */
jcr->session_opened = FALSE;
- return 1;
+ return true;
}
/*
* Job control and execution for Storage Daemon
*
+ * Kern Sibbald, MM
+ *
* Version $Id$
*
*/
extern uint32_t newVolSessionId();
/* Forward referenced functions */
-static int use_device_cmd(JCR *jcr);
+static bool use_device_cmd(JCR *jcr);
/* Requests from the Director daemon */
-static char jobcmd[] = "JobId=%d job=%127s job_name=%127s client_name=%127s "
+static char jobcmd[] = "JobId=%d job=%127s job_name=%127s client_name=%127s "
"type=%d level=%d FileSet=%127s NoAttr=%d SpoolAttr=%d FileSetMD5=%127s "
"SpoolData=%d";
-static char use_device[] = "use device=%s media_type=%s pool_name=%s pool_type=%s\n";
+static char use_device[] = "use device=%127s media_type=%127s pool_name=%127s pool_type=%127s\n";
/* Responses sent to Director daemon */
static char OKjob[] = "3000 OK Job SDid=%u SDtime=%u Authorization=%s\n";
static char BAD_use[] = "3913 Bad use command: %s\n";
static char BAD_job[] = "3915 Bad Job command: %s\n";
-
-
/*
* Director requests us to start a job
* Basic tasks done here:
* - Return when the connection is terminated or
* there is an error.
*/
-int job_cmd(JCR *jcr)
+bool job_cmd(JCR *jcr)
{
int JobId, errstat;
char auth_key[100];
BSOCK *dir = jcr->dir_bsock;
- POOLMEM *job_name, *client_name, *job, *fileset_name, *fileset_md5;
+ POOL_MEM job_name, client_name, job, fileset_name, fileset_md5;
int JobType, level, spool_attributes, no_attributes, spool_data;
struct timeval tv;
struct timezone tz;
/*
* Get JobId and permissions from Director
*/
-
Dmsg1(100, "Job_cmd: %s\n", dir->msg);
- job = get_memory(dir->msglen);
- job_name = get_memory(dir->msglen);
- client_name = get_memory(dir->msglen);
- fileset_name = get_memory(dir->msglen);
- fileset_md5 = get_memory(dir->msglen);
- if (sscanf(dir->msg, jobcmd, &JobId, job, job_name, client_name,
- &JobType, &level, fileset_name, &no_attributes,
- &spool_attributes, fileset_md5, &spool_data) != 11) {
- pm_strcpy(&jcr->errmsg, dir->msg);
+ if (sscanf(dir->msg, jobcmd, &JobId, job.c_str(), job_name.c_str(),
+ client_name.c_str(),
+ &JobType, &level, fileset_name.c_str(), &no_attributes,
+ &spool_attributes, fileset_md5.c_str(), &spool_data) != 11) {
+ pm_strcpy(jcr->errmsg, dir->msg);
bnet_fsend(dir, BAD_job, jcr->errmsg);
Emsg1(M_FATAL, 0, _("Bad Job Command from Director: %s\n"), jcr->errmsg);
- free_memory(job);
- free_memory(job_name);
- free_memory(client_name);
- free_memory(fileset_name);
- free_memory(fileset_md5);
set_jcr_job_status(jcr, JS_ErrorTerminated);
- return 0;
+ return false;
}
/*
* Since this job could be rescheduled, we
* check to see if we have it already. If so
* free the old jcr and use the new one.
*/
- ojcr = get_jcr_by_full_name(job);
+ ojcr = get_jcr_by_full_name(job.c_str());
if (ojcr && !ojcr->authenticated) {
- Dmsg2(100, "Found ojcr=0x%x Job %s\n", (unsigned)(long)ojcr, job);
+ Dmsg2(100, "Found ojcr=0x%x Job %s\n", (unsigned)(long)ojcr, job.c_str());
free_jcr(ojcr);
}
jcr->JobId = JobId;
jcr->VolSessionId = newVolSessionId();
jcr->VolSessionTime = VolSessionTime;
- bstrncpy(jcr->Job, job, sizeof(jcr->Job));
- unbash_spaces(job_name);
+ bstrncpy(jcr->Job, job.c_str(), sizeof(jcr->Job));
+ unbash_spaces(job_name.c_str());
jcr->job_name = get_pool_memory(PM_NAME);
- pm_strcpy(&jcr->job_name, job_name);
- unbash_spaces(client_name);
+ pm_strcpy(jcr->job_name, job_name);
+ unbash_spaces(client_name.c_str());
jcr->client_name = get_pool_memory(PM_NAME);
- pm_strcpy(&jcr->client_name, client_name);
- unbash_spaces(fileset_name);
+ pm_strcpy(jcr->client_name, client_name);
+ unbash_spaces(fileset_name.c_str());
jcr->fileset_name = get_pool_memory(PM_NAME);
- pm_strcpy(&jcr->fileset_name, fileset_name);
+ pm_strcpy(jcr->fileset_name, fileset_name);
jcr->JobType = JobType;
jcr->JobLevel = level;
jcr->no_attributes = no_attributes;
jcr->spool_attributes = spool_attributes;
jcr->spool_data = spool_data;
jcr->fileset_md5 = get_pool_memory(PM_NAME);
- pm_strcpy(&jcr->fileset_md5, fileset_md5);
- free_memory(job);
- free_memory(job_name);
- free_memory(client_name);
- free_memory(fileset_name);
- free_memory(fileset_md5);
+ pm_strcpy(jcr->fileset_md5, fileset_md5);
jcr->authenticated = false;
if (!use_device_cmd(jcr)) {
set_jcr_job_status(jcr, JS_ErrorTerminated);
memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
- return 0;
+ return false;
+ }
+
+ /* The following jobs don't need the FD */
+ switch (jcr->JobType) {
+ case JT_MIGRATION:
+ case JT_COPY:
+ case JT_ARCHIVE:
+ jcr->authenticated = true;
+ run_job(jcr);
+ return false;
}
set_jcr_job_status(jcr, JS_WaitFD); /* wait for FD to connect */
Dmsg1(100, "Running job %s\n", jcr->Job);
run_job(jcr); /* Run the job */
}
- return 0;
+ return false;
}
/*
Dmsg1(110, "Found Job %s\n", job_name);
if (jcr->authenticated) {
- Pmsg2(000, "Hey!!!! JobId %u Job %s already authenticated.\n",
+ Jmsg2(jcr, M_FATAL, 0, "Hey!!!! JobId %u Job %s already authenticated.\n",
jcr->JobId, jcr->Job);
+ free_jcr(jcr);
+ return;
}
/*
* Ensure that the device exists and is opened, then store
* the media and pool info in the JCR.
*/
-static int use_device_cmd(JCR *jcr)
+static bool use_device_cmd(JCR *jcr)
{
- POOLMEM *dev_name, *media_type, *pool_name, *pool_type;
+ POOL_MEM dev_name, media_type, pool_name, pool_type;
BSOCK *dir = jcr->dir_bsock;
DEVRES *device;
if (bnet_recv(dir) <= 0) {
Jmsg0(jcr, M_FATAL, 0, _("No Device from Director\n"));
- return 0;
+ return false;
}
Dmsg1(120, "Use device: %s", dir->msg);
- dev_name = get_memory(dir->msglen);
- media_type = get_memory(dir->msglen);
- pool_name = get_memory(dir->msglen);
- pool_type = get_memory(dir->msglen);
- if (sscanf(dir->msg, use_device, dev_name, media_type, pool_name, pool_type) == 4) {
+ if (sscanf(dir->msg, use_device, dev_name.c_str(), media_type.c_str(),
+ pool_name.c_str(), pool_type.c_str()) == 4) {
unbash_spaces(dev_name);
unbash_spaces(media_type);
unbash_spaces(pool_name);
unbash_spaces(pool_type);
- device = NULL;
LockRes();
- while ((device=(DEVRES *)GetNextRes(R_DEVICE, (RES *)device))) {
+ foreach_res(device, R_DEVICE) {
/* Find resource, and make sure we were able to open it */
- if (strcmp(device->hdr.name, dev_name) == 0 && device->dev) {
+ if (fnmatch(dev_name.c_str(), device->hdr.name, 0) == 0 &&
+ device->dev && strcmp(device->media_type, media_type.c_str()) == 0) {
+ const int name_len = MAX_NAME_LENGTH;
+ DCR *dcr;
+ UnlockRes();
+ dcr = new_dcr(jcr, device->dev);
+ if (!dcr) {
+ return false;
+ }
Dmsg1(120, "Found device %s\n", device->hdr.name);
- jcr->pool_name = get_memory(strlen(pool_name) + 1);
- strcpy(jcr->pool_name, pool_name);
- jcr->pool_type = get_memory(strlen(pool_type) + 1);
- strcpy(jcr->pool_type, pool_type);
- jcr->media_type = get_memory(strlen(media_type) + 1);
- strcpy(jcr->media_type, media_type);
- jcr->dev_name = get_memory(strlen(dev_name) + 1);
- strcpy(jcr->dev_name, dev_name);
+ bstrncpy(dcr->pool_name, pool_name, name_len);
+ bstrncpy(dcr->pool_type, pool_type, name_len);
+ bstrncpy(dcr->media_type, media_type, name_len);
+ bstrncpy(dcr->dev_name, dev_name, name_len);
jcr->device = device;
- Dmsg4(120, use_device, dev_name, media_type, pool_name, pool_type);
- free_memory(dev_name);
- free_memory(media_type);
- free_memory(pool_name);
- free_memory(pool_type);
- UnlockRes();
+ Dmsg4(120, use_device, dev_name.c_str(), media_type.c_str(), pool_name.c_str(), pool_type.c_str());
return bnet_fsend(dir, OK_device);
}
}
UnlockRes();
if (verbose) {
unbash_spaces(dir->msg);
- pm_strcpy(&jcr->errmsg, dir->msg);
+ pm_strcpy(jcr->errmsg, dir->msg);
Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
}
Jmsg(jcr, M_FATAL, 0, _("\n"
- " Device \"%s\" requested by Dir not found in SD Device resources.\n"),
- dev_name);
- bnet_fsend(dir, NO_device, dev_name);
+ " Device \"%s\" with MediaType \"%s\" requested by Dir not found in SD Device resources.\n"),
+ dev_name.c_str(), media_type.c_str());
+ bnet_fsend(dir, NO_device, dev_name.c_str());
} else {
unbash_spaces(dir->msg);
- pm_strcpy(&jcr->errmsg, dir->msg);
+ pm_strcpy(jcr->errmsg, dir->msg);
if (verbose) {
Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
}
bnet_fsend(dir, BAD_use, jcr->errmsg);
}
- free_memory(dev_name);
- free_memory(media_type);
- free_memory(pool_name);
- free_memory(pool_type);
- return 0; /* ERROR return */
+ return false; /* ERROR return */
}
/*
bnet_close(jcr->file_bsock);
jcr->file_bsock = NULL;
}
- if (jcr->pool_name) {
- free_memory(jcr->pool_name);
- }
- if (jcr->pool_type) {
- free_memory(jcr->pool_type);
- }
- if (jcr->media_type) {
- free_memory(jcr->media_type);
- }
- if (jcr->dev_name) {
- free_memory(jcr->dev_name);
- }
if (jcr->job_name) {
free_pool_memory(jcr->job_name);
}
/*
* Read the volume label
*
- * If jcr->VolumeName == NULL, we accept any Bacula Volume
- * If jcr->VolumeName[0] == 0, we accept any Bacula Volume
- * otherwise jcr->VolumeName must match the Volume.
+ * If dcr->VolumeName == NULL, we accept any Bacula Volume
+ * If dcr->VolumeName[0] == 0, we accept any Bacula Volume
+ * otherwise dcr->VolumeName must match the Volume.
*
* If VolName given, ensure that it matches
*
* VOL_LABEL_ERROR
* VOL_NO_MEDIA
*/
-int read_dev_volume_label(DCR *dcr, DEV_BLOCK *block)
+int read_dev_volume_label(DCR *dcr)
{
JCR *jcr = dcr->jcr;
DEVICE *dev = dcr->dev;
- char *VolName = jcr->VolumeName;
+ char *VolName = dcr->VolumeName;
DEV_RECORD *record;
bool ok = false;
+ DEV_BLOCK *block = dcr->block;
Dmsg3(100, "Enter read_volume_label device=%s vol=%s dev_Vol=%s\n",
dev_name(dev), VolName, dev->VolHdr.VolName);
if (!dev->poll && jcr->label_errors++ > 100) {
Jmsg(jcr, M_FATAL, 0, "Too many tries: %s", jcr->errmsg);
}
- return jcr->label_status = VOL_NAME_ERROR;
+ return VOL_NAME_ERROR;
}
Dmsg0(30, "Leave read_volume_label() VOL_OK\n");
- return jcr->label_status = VOL_OK; /* label already read */
+ return VOL_OK; /* label already read */
}
dev->state &= ~(ST_LABEL|ST_APPEND|ST_READ); /* set no label, no append */
if (!rewind_dev(dev)) {
Mmsg(jcr->errmsg, _("Couldn't rewind device %s ERR=%s\n"), dev_name(dev),
strerror_dev(dev));
- return jcr->label_status = VOL_NO_MEDIA;
+ Dmsg1(30, "%s", jcr->errmsg);
+ return VOL_NO_MEDIA;
}
bstrncpy(dev->VolHdr.Id, "**error**", sizeof(dev->VolHdr.Id));
/* Read the Volume label block */
record = new_record();
+ empty_block(block);
Dmsg0(90, "Big if statement in read_volume_label\n");
- if (!read_block_from_dev(dcr, block, NO_BLOCK_NUMBER_CHECK)) {
+ if (!read_block_from_dev(dcr, NO_BLOCK_NUMBER_CHECK)) {
Mmsg(jcr->errmsg, _("Requested Volume \"%s\" on %s is not a Bacula "
"labeled Volume, because: ERR=%s"), NPRT(VolName), dev_name(dev),
strerror_dev(dev));
+ Dmsg1(30, "%s", jcr->errmsg);
} else if (!read_record_from_block(block, record)) {
Mmsg(jcr->errmsg, _("Could not read Volume label from block.\n"));
+ Dmsg1(30, "%s", jcr->errmsg);
} else if (!unser_volume_label(dev, record)) {
Mmsg(jcr->errmsg, _("Could not unserialize Volume label: ERR=%s\n"),
strerror_dev(dev));
+ Dmsg1(30, "%s", jcr->errmsg);
} else if (strcmp(dev->VolHdr.Id, BaculaId) != 0 &&
strcmp(dev->VolHdr.Id, OldBaculaId) != 0) {
Mmsg(jcr->errmsg, _("Volume Header Id bad: %s\n"), dev->VolHdr.Id);
+ Dmsg1(30, "%s", jcr->errmsg);
} else {
ok = true;
}
if (forge_on || jcr->ignore_label_errors) {
dev->state |= ST_LABEL; /* set has Bacula label */
Jmsg(jcr, M_ERROR, 0, "%s", jcr->errmsg);
- return jcr->label_status = VOL_OK;
+ return VOL_OK;
}
empty_block(block);
rewind_dev(dev);
- return jcr->label_status = VOL_NO_LABEL;
+ return VOL_NO_LABEL;
}
free_record(record);
dev->VolHdr.VerNum != OldCompatibleBaculaTapeVersion2) {
Mmsg(jcr->errmsg, _("Volume on %s has wrong Bacula version. Wanted %d got %d\n"),
dev_name(dev), BaculaTapeVersion, dev->VolHdr.VerNum);
- return jcr->label_status = VOL_VERSION_ERROR;
+ Dmsg1(30, "%s", jcr->errmsg);
+ return VOL_VERSION_ERROR;
}
/* We are looking for either an unused Bacula tape (PRE_LABEL) or
if (dev->VolHdr.LabelType != PRE_LABEL && dev->VolHdr.LabelType != VOL_LABEL) {
Mmsg(jcr->errmsg, _("Volume on %s has bad Bacula label type: %x\n"),
dev_name(dev), dev->VolHdr.LabelType);
- return jcr->label_status = VOL_LABEL_ERROR;
+ Dmsg1(30, "%s", jcr->errmsg);
+ return VOL_LABEL_ERROR;
}
dev->state |= ST_LABEL; /* set has Bacula label */
if (VolName && *VolName && *VolName != '*' && strcmp(dev->VolHdr.VolName, VolName) != 0) {
Mmsg(jcr->errmsg, _("Wrong Volume mounted on device %s: Wanted %s have %s\n"),
dev_name(dev), VolName, dev->VolHdr.VolName);
+ Dmsg1(30, "%s", jcr->errmsg);
/*
* Cancel Job if too many label errors
* => we are in a loop
if (!dev->poll && jcr->label_errors++ > 100) {
Jmsg(jcr, M_FATAL, 0, "Too many tries: %s", jcr->errmsg);
}
- return jcr->label_status = VOL_NAME_ERROR;
+ return VOL_NAME_ERROR;
}
Dmsg1(30, "Copy vol_name=%s\n", dev->VolHdr.VolName);
dump_volume_label(dev);
}
Dmsg0(30, "Leave read_volume_label() VOL_OK\n");
- return jcr->label_status = VOL_OK;
+ return VOL_OK;
}
/* unser_volume_label
* Returns: false on failure
* true on success
*/
-bool write_volume_label_to_block(DCR *dcr, DEV_BLOCK *block)
+bool write_volume_label_to_block(DCR *dcr)
{
DEV_RECORD rec;
DEVICE *dev = dcr->dev;
JCR *jcr = dcr->jcr;
+ DEV_BLOCK *block = dcr->block;
Dmsg0(20, "write Label in write_volume_label_to_block()\n");
memset(&rec, 0, sizeof(rec));
rec.data = get_memory(SER_LENGTH_Volume_Label);
+ empty_block(block); /* Volume label always at beginning */
create_volume_label_record(dcr, &rec);
- empty_block(block); /* Volume label always at beginning */
block->BlockNumber = 0;
if (!write_record_to_block(block, &rec)) {
free_pool_memory(rec.data);
*/
bool write_new_volume_label_to_dev(DCR *dcr, const char *VolName, const char *PoolName)
{
- DEV_RECORD rec;
- DEV_BLOCK *block;
bool ok = false;
DEVICE *dev = dcr->dev;
Dmsg0(99, "write_volume_label()\n");
+ empty_block(dcr->block);
create_volume_label(dev, VolName, PoolName);
if (!rewind_dev(dev)) {
}
}
- block = new_block(dev);
- memset(&rec, 0, sizeof(rec));
- rec.data = get_memory(SER_LENGTH_Volume_Label);
- create_volume_label_record(dcr, &rec);
- rec.Stream = 0;
+ create_volume_label_record(dcr, dcr->rec);
+ dcr->rec->Stream = 0;
- if (!write_record_to_block(block, &rec)) {
+ if (!write_record_to_block(dcr->block, dcr->rec)) {
Dmsg2(30, "Bad Label write on %s. ERR=%s\n", dev_name(dev), strerror_dev(dev));
memset(&dev->VolHdr, 0, sizeof(dev->VolHdr));
goto bail_out;
} else {
- Dmsg2(30, "Wrote label of %d bytes to %s\n", rec.data_len, dev_name(dev));
+ Dmsg2(30, "Wrote label of %d bytes to %s\n", dcr->rec->data_len, dev_name(dev));
}
Dmsg0(99, "Call write_block_to_dev()\n");
- if (!write_block_to_dev(dcr, block)) {
+ if (!write_block_to_dev(dcr)) {
memset(&dev->VolHdr, 0, sizeof(dev->VolHdr));
Dmsg2(30, "Bad Label write on %s. ERR=%s\n", dev_name(dev), strerror_dev(dev));
goto bail_out;
}
bail_out:
- free_block(block);
- free_pool_memory(rec.data);
return ok;
}
ser_btime(get_current_btime());
ser_float64(0);
- ser_string(jcr->pool_name);
- ser_string(jcr->pool_type);
+ ser_string(dcr->pool_name);
+ ser_string(dcr->pool_type);
ser_string(jcr->job_name); /* base Job name */
ser_string(jcr->client_name);
* Returns: false on failure
* true on success
*/
-bool write_session_label(DCR *dcr, DEV_BLOCK *block, int label)
+bool write_session_label(DCR *dcr, int label)
{
JCR *jcr = dcr->jcr;
DEVICE *dev = dcr->dev;
DEV_RECORD *rec;
+ DEV_BLOCK *block = dcr->block;
rec = new_record();
Dmsg1(90, "session_label record=%x\n", rec);
*/
if (!can_write_record_to_block(block, rec)) {
Dmsg0(100, "Cannot write session label to block.\n");
- if (!write_block_to_device(jcr->dcr, block)) {
+ if (!write_block_to_device(dcr)) {
Dmsg0(90, "Got session label write_block_to_dev error.\n");
+ /* ****FIXME***** errno is not set here */
Jmsg(jcr, M_FATAL, 0, _("Error writing Session label to %s: %s\n"),
dev_vol_name(dev), strerror(errno));
free_record(rec);
#include "bacula.h" /* pull in global headers */
#include "stored.h" /* pull in Storage Deamon headers */
-static bool rewrite_volume_label(DCR *dcr, DEV_BLOCK *block, bool recycle);
+static bool rewrite_volume_label(DCR *dcr, bool recycle);
/*
* impossible to get the requested Volume.
*
*/
-bool mount_next_write_volume(DCR *dcr, DEV_BLOCK *block, bool release)
+bool mount_next_write_volume(DCR *dcr, bool release)
{
int retry = 0;
bool ask = false, recycle, autochanger;
int vol_label_status;
DEVICE *dev = dcr->dev;
JCR *jcr = dcr->jcr;
+ DEV_BLOCK *block = dcr->block;
Dmsg0(100, "Enter mount_next_volume()\n");
/* Ignore retry if this is poll request */
if (!dev->poll && retry++ > 4) {
/* Last ditch effort before giving up, force operator to respond */
- jcr->VolCatInfo.Slot = 0;
+ dcr->VolCatInfo.Slot = 0;
if (!dir_ask_sysop_to_mount_volume(dcr)) {
Jmsg(jcr, M_FATAL, 0, _("Too many errors trying to mount device %s.\n"),
dev_name(dev));
recycle = false;
if (release) {
Dmsg0(100, "mount_next_volume release=1\n");
- release_volume(jcr, dev);
+ release_volume(dcr);
ask = true; /* ask operator to mount tape */
}
/*
* Get Director's idea of what tape we should have mounted.
- * in jcr->VolCatInfo
+ * in dcr->VolCatInfo
*/
Dmsg0(200, "Before dir_find_next_appendable_volume.\n");
while (!dir_find_next_appendable_volume(dcr)) {
return false;
}
Dmsg2(100, "After find_next_append. Vol=%s Slot=%d\n",
- jcr->VolCatInfo.VolCatName, jcr->VolCatInfo.Slot);
+ dcr->VolCatInfo.VolCatName, dcr->VolCatInfo.Slot);
/*
* Get next volume and ready it for append
ask = false;
} else {
autochanger = false;
- jcr->VolCatInfo.Slot = 0;
+ dcr->VolCatInfo.Slot = 0;
}
Dmsg1(100, "autoload_dev returns %d\n", autochanger);
/*
if (job_canceled(jcr)) {
return false;
}
- Dmsg1(100, "want vol=%s\n", jcr->VolumeName);
+ Dmsg1(100, "want vol=%s\n", dcr->VolumeName);
if (dev->poll && dev_cap(dev, CAP_CLOSEONPOLL)) {
force_close_dev(dev);
}
/* Ensure the device is open */
- if (!open_device(jcr, dev)) {
+ if (!open_device(dcr)) {
if (dev->poll) {
goto mount_next_vol;
} else {
*/
if (dev_cap(dev, CAP_STREAM)) {
vol_label_status = VOL_OK;
- create_volume_label(dev, jcr->VolumeName, "Default");
+ create_volume_label(dev, dcr->VolumeName, "Default");
dev->VolHdr.LabelType = PRE_LABEL;
} else {
- vol_label_status = read_dev_volume_label(jcr->dcr, block);
+ vol_label_status = read_dev_volume_label(dcr);
}
if (job_canceled(jcr)) {
return false;
}
- Dmsg2(100, "dirVol=%s dirStat=%s\n", jcr->VolumeName,
- jcr->VolCatInfo.VolCatStatus);
+ Dmsg2(100, "dirVol=%s dirStat=%s\n", dcr->VolumeName,
+ dcr->VolCatInfo.VolCatStatus);
/*
* At this point, dev->VolCatInfo has what is in the drive, if anything,
- * and jcr->VolCatInfo has what the Director wants.
+ * and dcr->VolCatInfo has what the Director wants.
*/
switch (vol_label_status) {
case VOL_OK:
- Dmsg1(100, "Vol OK name=%s\n", jcr->VolumeName);
- memcpy(&dev->VolCatInfo, &jcr->VolCatInfo, sizeof(jcr->VolCatInfo));
+ Dmsg1(100, "Vol OK name=%s\n", dcr->VolumeName);
+ memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
recycle = strcmp(dev->VolCatInfo.VolCatStatus, "Recycle") == 0;
break; /* got a Volume */
case VOL_NAME_ERROR:
/* If not removable, Volume is broken */
if (!dev_cap(dev, CAP_REM)) {
Jmsg(jcr, M_WARNING, 0, _("Volume \"%s\" not on device %s.\n"),
- jcr->VolumeName, dev_name(dev));
- mark_volume_in_error(jcr, dev);
+ dcr->VolumeName, dev_name(dev));
+ mark_volume_in_error(dcr);
goto mount_next_vol;
}
- Dmsg1(100, "Vol NAME Error Name=%s\n", jcr->VolumeName);
+ Dmsg1(100, "Vol NAME Error Name=%s\n", dcr->VolumeName);
/* If polling and got a previous bad name, ignore it */
if (dev->poll && strcmp(dev->BadVolName, dev->VolHdr.VolName) == 0) {
ask = true;
Dmsg1(200, "Vol Name error supress due to poll. Name=%s\n",
- jcr->VolumeName);
+ dcr->VolumeName);
goto mount_next_vol;
}
/*
* this volume is really OK. If not, put back the desired
* volume name and continue.
*/
- memcpy(&VolCatInfo, &jcr->VolCatInfo, sizeof(VolCatInfo));
+ memcpy(&VolCatInfo, &dcr->VolCatInfo, sizeof(VolCatInfo));
/* Check if this is a valid Volume in the pool */
- pm_strcpy(&jcr->VolumeName, dev->VolHdr.VolName);
+ bstrncpy(dcr->VolumeName, dev->VolHdr.VolName, sizeof(dcr->VolumeName));
if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_WRITE)) {
bstrncpy(dev->BadVolName, dev->VolHdr.VolName, sizeof(dev->BadVolName));
Jmsg(jcr, M_WARNING, 0, _("Director wanted Volume \"%s\".\n"
VolCatInfo.VolCatName, dev->VolHdr.VolName,
jcr->dir_bsock->msg);
/* Restore desired volume name, note device info out of sync */
- memcpy(&jcr->VolCatInfo, &VolCatInfo, sizeof(jcr->VolCatInfo));
+ memcpy(&dcr->VolCatInfo, &VolCatInfo, sizeof(dcr->VolCatInfo));
ask = true;
goto mount_next_vol;
}
- Dmsg1(100, "want new name=%s\n", jcr->VolumeName);
- memcpy(&dev->VolCatInfo, &jcr->VolCatInfo, sizeof(dev->VolCatInfo));
+ Dmsg1(100, "want new name=%s\n", dcr->VolumeName);
+ memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
recycle = strcmp(dev->VolCatInfo.VolCatStatus, "Recycle") == 0;
break; /* got a Volume */
/*
* blank tape with the same name. For disk, we go ahead and
* label it anyway, because the OS insures that there is only
* one Volume with that name.
- * As noted above, at this point jcr->VolCatInfo has what
+ * As noted above, at this point dcr->VolCatInfo has what
* the Director wants and dev->VolCatInfo has info on the
* previous tape (or nothing).
*/
- if (dev_cap(dev, CAP_LABEL) && (jcr->VolCatInfo.VolCatBytes == 0 ||
- (!dev_is_tape(dev) && strcmp(jcr->VolCatInfo.VolCatStatus,
+ if (dev_cap(dev, CAP_LABEL) && (dcr->VolCatInfo.VolCatBytes == 0 ||
+ (!dev_is_tape(dev) && strcmp(dcr->VolCatInfo.VolCatStatus,
"Recycle") == 0))) {
Dmsg0(100, "Create volume label\n");
/* Create a new Volume label and write it to the device */
- if (!write_new_volume_label_to_dev(jcr->dcr, jcr->VolumeName,
- jcr->pool_name)) {
+ if (!write_new_volume_label_to_dev(dcr, dcr->VolumeName,
+ dcr->pool_name)) {
Dmsg0(100, "!write_vol_label\n");
goto mount_next_vol;
}
Dmsg0(100, "dir_update_vol_info. Set Append\n");
/* Copy Director's info into the device info */
- memcpy(&dev->VolCatInfo, &jcr->VolCatInfo, sizeof(dev->VolCatInfo));
+ memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
dir_update_volume_info(dcr, true); /* indicate tape labeled */
Jmsg(jcr, M_INFO, 0, _("Labeled new Volume \"%s\" on device %s.\n"),
- jcr->VolumeName, dev_name(dev));
+ dcr->VolumeName, dev_name(dev));
goto read_volume; /* read label we just wrote */
}
/* If not removable, Volume is broken */
if (!dev_cap(dev, CAP_REM)) {
Jmsg(jcr, M_WARNING, 0, _("Volume \"%s\" not on device %s.\n"),
- jcr->VolumeName, dev_name(dev));
- mark_volume_in_error(jcr, dev);
+ dcr->VolumeName, dev_name(dev));
+ mark_volume_in_error(dcr);
goto mount_next_vol;
}
/* NOTE! Fall-through wanted. */
* If the tape is marked as Recycle, we rewrite the label.
*/
if (dev->VolHdr.LabelType == PRE_LABEL || recycle) {
- if (!rewrite_volume_label(jcr->dcr, block, recycle)) {
+ if (!rewrite_volume_label(dcr, recycle)) {
goto mount_next_vol;
}
} else {
*/
Dmsg0(200, "Device previously written, moving to end of data\n");
Jmsg(jcr, M_INFO, 0, _("Volume \"%s\" previously written, moving to end of data.\n"),
- jcr->VolumeName);
+ dcr->VolumeName);
if (!eod_dev(dev)) {
Jmsg(jcr, M_ERROR, 0, _("Unable to position to end of data on device \"%s\". ERR=%s\n"),
dev_name(dev), strerror_dev(dev));
- mark_volume_in_error(jcr, dev);
+ mark_volume_in_error(dcr);
goto mount_next_vol;
}
/* *****FIXME**** we should do some checking for files too */
*/
if (dev->VolCatInfo.VolCatFiles == dev_file(dev)) {
Jmsg(jcr, M_INFO, 0, _("Ready to append to end of Volume \"%s\" at file=%d.\n"),
- jcr->VolumeName, dev_file(dev));
+ dcr->VolumeName, dev_file(dev));
} else {
Jmsg(jcr, M_ERROR, 0, _("I canot write on Volume \"%s\" because:\n\
The number of files mismatch! Volume=%u Catalog=%u\n"),
- jcr->VolumeName, dev_file(dev), dev->VolCatInfo.VolCatFiles);
- mark_volume_in_error(jcr, dev);
+ dcr->VolumeName, dev_file(dev), dev->VolCatInfo.VolCatFiles);
+ mark_volume_in_error(dcr);
goto mount_next_vol;
}
}
* Returns: true if OK
* false if unable to write it
*/
-static bool rewrite_volume_label(DCR *dcr, DEV_BLOCK *block, bool recycle)
+static bool rewrite_volume_label(DCR *dcr, bool recycle)
{
DEVICE *dev = dcr->dev;
JCR *jcr = dcr->jcr;
Dmsg1(190, "ready_for_append found freshly labeled volume. dev=%x\n", dev);
dev->VolHdr.LabelType = VOL_LABEL; /* set Volume label */
- if (!write_volume_label_to_block(dcr, block)) {
+ if (!write_volume_label_to_block(dcr)) {
return false;
}
/*
}
}
/* Attempt write to check write permission */
- if (!write_block_to_dev(dcr, block)) {
+ if (!write_block_to_dev(dcr)) {
Jmsg2(jcr, M_ERROR, 0, _("Unable to write device \"%s\". ERR=%s\n"),
dev_name(dev), strerror_dev(dev));
return false;
dir_update_volume_info(dcr, true); /* indicate doing relabel */
if (recycle) {
Jmsg(jcr, M_INFO, 0, _("Recycled volume \"%s\" on device \"%s\", all previous data lost.\n"),
- jcr->VolumeName, dev_name(dev));
+ dcr->VolumeName, dev_name(dev));
} else {
Jmsg(jcr, M_INFO, 0, _("Wrote label to prelabeled Volume \"%s\" on device \"%s\"\n"),
- jcr->VolumeName, dev_name(dev));
+ dcr->VolumeName, dev_name(dev));
}
/*
* End writing real Volume label (from pre-labeled tape), or recycling
/*
* Mark volume in error in catalog
*/
-void mark_volume_in_error(JCR *jcr, DEVICE *dev)
+void mark_volume_in_error(DCR *dcr)
{
- Jmsg(jcr, M_INFO, 0, _("Marking Volume \"%s\" in Error in Catalog.\n"),
- jcr->VolumeName);
+ DEVICE *dev = dcr->dev;
+ Jmsg(dcr->jcr, M_INFO, 0, _("Marking Volume \"%s\" in Error in Catalog.\n"),
+ dcr->VolumeName);
bstrncpy(dev->VolCatInfo.VolCatStatus, "Error", sizeof(dev->VolCatInfo.VolCatStatus));
Dmsg0(100, "dir_update_vol_info. Set Error.\n");
- dir_update_volume_info(jcr->dcr, false);
+ dir_update_volume_info(dcr, false);
}
/*
* If we are reading, we come here at the end of the tape
* and see if there are more volumes to be mounted.
*/
-bool mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
+bool mount_next_read_volume(DCR *dcr)
{
+ DEVICE *dev = dcr->dev;
+ JCR *jcr = dcr->jcr;
Dmsg2(90, "NumVolumes=%d CurVolume=%d\n", jcr->NumVolumes, jcr->CurVolume);
/*
* End Of Tape -- mount next Volume (if another specified)
dev->state &= ~ST_READ;
if (!acquire_device_for_read(jcr)) {
Jmsg2(jcr, M_FATAL, 0, "Cannot open Dev=%s, Vol=%s\n", dev_name(dev),
- jcr->VolumeName);
+ dcr->VolumeName);
return false;
}
return true; /* next volume mounted */
* Either because we are going to hang a new volume, or because
* of explicit user request, we release the current volume.
*/
-void release_volume(JCR *jcr, DEVICE *dev)
+void release_volume(DCR *dcr)
{
- if (jcr->dcr->WroteVol) {
+ JCR *jcr = dcr->jcr;
+ DEVICE *dev = dcr->dev;
+ if (dcr->WroteVol) {
Jmsg0(jcr, M_ERROR, 0, "Hey!!!!! WroteVol non-zero !!!!!\n");
}
/*
dev->block_num = dev->file = 0;
dev->EndBlock = dev->EndFile = 0;
memset(&dev->VolCatInfo, 0, sizeof(dev->VolCatInfo));
- memset(&jcr->VolCatInfo, 0, sizeof(jcr->VolCatInfo));
+ memset(&dcr->VolCatInfo, 0, sizeof(dcr->VolCatInfo));
memset(&dev->VolHdr, 0, sizeof(dev->VolHdr));
/* Force re-read of label */
dev->state &= ~(ST_LABEL|ST_READ|ST_APPEND);
- jcr->VolumeName[0] = 0;
+ dcr->VolumeName[0] = 0;
if ((dev->state & ST_OPENED) &&
(!dev_is_tape(dev) || !dev_cap(dev, CAP_ALWAYSOPEN))) {
}
} else {
/* This is the old way -- deprecated */
- for (p = jcr->VolumeName; p && *p; ) {
+ for (p = jcr->dcr->VolumeName; p && *p; ) {
n = strchr(p, '|'); /* volume name separator */
if (n) {
*n++ = 0; /* Terminate name */
int authenticate_director(JCR *jcr);
int authenticate_filed(JCR *jcr);
+/* From autochanger.c */
+int autoload_device(DCR *dcr, int writing, BSOCK *dir);
+bool autochanger_list(DCR *dcr, BSOCK *dir);
+void invalidate_slot_in_catalog(DCR *dcr);
+char *edit_device_codes(JCR *jcr, char *omsg, const char *imsg, const char *cmd);
+
/* From block.c */
void dump_block(DEV_BLOCK *b, const char *msg);
DEV_BLOCK *new_block(DEVICE *dev);
void init_block_write(DEV_BLOCK *block);
void empty_block(DEV_BLOCK *block);
void free_block(DEV_BLOCK *block);
-bool write_block_to_device(DCR *dcr, DEV_BLOCK *block);
-bool write_block_to_dev(DCR *dcr, DEV_BLOCK *block);
+bool write_block_to_device(DCR *dcr);
+bool write_block_to_dev(DCR *dcr);
void print_block_read_errors(JCR *jcr, DEV_BLOCK *block);
void ser_block_header(DEV_BLOCK *block);
#define CHECK_BLOCK_NUMBERS true
#define NO_BLOCK_NUMBER_CHECK false
-bool read_block_from_device(DCR *dcr, DEV_BLOCK *block, bool check_block_numbers);
-bool read_block_from_dev(DCR *dcr, DEV_BLOCK *block, bool check_block_numbers);
+bool read_block_from_device(DCR *dcr, bool check_block_numbers);
+bool read_block_from_dev(DCR *dcr, bool check_block_numbers);
/* From butil.c -- utilities for SD tool programs */
void print_ls_output(const char *fname, const char *link, int type, struct stat *statp);
-JCR *setup_jcr(const char *name, const char * device, BSR *bsr, const char *VolumeName);
-DEVICE *setup_to_access_device(JCR *jcr, int read_access);
+JCR *setup_jcr(const char *name, char *dev_name, BSR *bsr,
+ const char *VolumeName, int mode);
void display_tape_error_status(JCR *jcr, DEVICE *dev);
-DEVRES *find_device_res(char *device_name, int read_access);
/* From dev.c */
bool dev_is_tape(DEVICE *dev);
/* From device.c */
-bool open_device(JCR *jcr, DEVICE *dev);
+bool open_device(DCR *dcr);
bool first_open_device(DEVICE *dev);
-bool fixup_device_block_write_error(DCR *dcr, DEV_BLOCK *block);
+bool fixup_device_block_write_error(DCR *dcr);
void _lock_device(const char *file, int line, DEVICE *dev);
void _unlock_device(const char *file, int line, DEVICE *dev);
void _block_device(const char *file, int line, DEVICE *dev, int state);
/* From fd_cmds.c */
void run_job(JCR *jcr);
+bool bootstrap_cmd(JCR *jcr);
/* From job.c */
void stored_free_jcr(JCR *jcr);
void handle_filed_connection(BSOCK *fd, char *job_name);
/* From label.c */
-int read_dev_volume_label(DCR *dcr, DEV_BLOCK *block);
+int read_dev_volume_label(DCR *dcr);
void create_session_label(DCR *dcr, DEV_RECORD *rec, int label);
void create_volume_label(DEVICE *dev, const char *VolName, const char *PoolName);
bool write_new_volume_label_to_dev(DCR *dcr, const char *VolName, const char *PoolName);
-bool write_session_label(DCR *dcr, DEV_BLOCK *block, int label);
-bool write_volume_label_to_block(DCR *dcr, DEV_BLOCK *block);
+bool write_session_label(DCR *dcr, int label);
+bool write_volume_label_to_block(DCR *dcr);
void dump_volume_label(DEVICE *dev);
void dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose);
bool unser_volume_label(DEVICE *dev, DEV_RECORD *rec);
bool match_set_eof(BSR *bsr, DEV_RECORD *rec);
/* From mount.c */
-bool mount_next_write_volume(DCR *dcr, DEV_BLOCK *block, bool release);
-bool mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-void release_volume(JCR *jcr, DEVICE *dev);
-void mark_volume_in_error(JCR *jcr, DEVICE *dev);
-
-/* From autochanger.c */
-int autoload_device(DCR *dcr, int writing, BSOCK *dir);
-bool autochanger_list(DCR *dcr, BSOCK *dir);
-void invalidate_slot_in_catalog(DCR *dcr);
-char *edit_device_codes(JCR *jcr, char *omsg, const char *imsg, const char *cmd);
-
+bool mount_next_write_volume(DCR *dcr, bool release);
+bool mount_next_read_volume(DCR *dcr);
+void release_volume(DCR *ddr);
+void mark_volume_in_error(DCR *dcr);
/* From parse_bsr.c */
BSR *parse_bsr(JCR *jcr, char *lf);
/* From record.c */
const char *FI_to_ascii(int fi);
const char *stream_to_ascii(int stream, int fi);
-int write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec);
-int can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec);
-int read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec);
+bool write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec);
+bool can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec);
+bool read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec);
DEV_RECORD *new_record();
-void free_record(DEV_RECORD *rec);
+void free_record(DEV_RECORD *rec);
+void empty_record(DEV_RECORD *rec);
/* From read_record.c */
bool read_records(DCR *dcr,
- bool record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec),
- bool mount_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block));
+ bool record_cb(DCR *dcr, DEV_RECORD *rec),
+ bool mount_cb(DCR *dcr));
/* From spool.c */
bool begin_data_spool (JCR *jcr);
bool begin_attribute_spool (JCR *jcr);
bool discard_attribute_spool (JCR *jcr);
bool commit_attribute_spool (JCR *jcr);
-bool write_block_to_spool_file (DCR *dcr, DEV_BLOCK *block);
+bool write_block_to_spool_file (DCR *dcr);
void list_spool_stats (BSOCK *bs);
#include "stored.h"
/* Forward referenced subroutines */
-static bool record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec);
+static bool record_cb(DCR *dcr, DEV_RECORD *rec);
/* Responses sent to the File daemon */
Dmsg2(200, "Found %d volumes names to restore. First=%s\n", jcr->NumVolumes,
jcr->VolList->VolumeName);
- pm_strcpy(&jcr->VolumeName, jcr->VolList->VolumeName);
-
/*
* Ready device for reading, and read records
*/
* Returns: true if OK
* false if error
*/
-static bool record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
+static bool record_cb(DCR *dcr, DEV_RECORD *rec)
{
+ JCR *jcr = dcr->jcr;
BSOCK *fd = jcr->file_bsock;
bool ok = true;
POOLMEM *save_msg;
#endif
bool read_records(DCR *dcr,
- bool record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec),
- bool mount_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block))
+ bool record_cb(DCR *dcr, DEV_RECORD *rec),
+ bool mount_cb(DCR *dcr))
{
JCR *jcr = dcr->jcr;
DEVICE *dev = dcr->dev;
- DEV_BLOCK *block;
+ DEV_BLOCK *block = dcr->block;
DEV_RECORD *rec = NULL;
uint32_t record;
bool ok = true;
SESSION_LABEL sessrec;
dlist *recs; /* linked list of rec packets open */
- block = new_block(dev);
recs = New(dlist(rec, &rec->link));
position_to_first_file(jcr, dev);
ok = false;
break;
}
- if (!read_block_from_device(dcr, block, CHECK_BLOCK_NUMBERS)) {
+ if (!read_block_from_device(dcr, CHECK_BLOCK_NUMBERS)) {
if (dev_state(dev, ST_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_name(dev), jcr->VolumeName);
- if (!mount_cb(jcr, dev, block)) {
+ dev->file, dev_name(dev), dcr->VolumeName);
+ if (!mount_cb(dcr)) {
Jmsg(jcr, M_INFO, 0, "End of all volumes.\n");
ok = false;
/*
*/
trec->FileIndex = EOT_LABEL;
trec->File = dev->file;
- ok = record_cb(jcr, dev, block, trec);
+ ok = record_cb(dcr, trec);
free_record(trec);
break;
}
* and pass it off to the callback routine, then continue
* most likely reading the previous record.
*/
- read_block_from_device(dcr, block, NO_BLOCK_NUMBER_CHECK);
+ read_block_from_device(dcr, NO_BLOCK_NUMBER_CHECK);
read_record_from_block(block, trec);
handle_session_record(dev, trec, &sessrec);
- ok = record_cb(jcr, dev, block, trec);
+ ok = record_cb(dcr, trec);
free_record(trec);
position_to_first_file(jcr, dev);
/* After reading label, we must read first data block */
} else if (dev_state(dev, ST_EOF)) {
if (verbose) {
Jmsg(jcr, M_INFO, 0, "Got EOF at file %u on device %s, Volume \"%s\"\n",
- dev->file, dev_name(dev), jcr->VolumeName);
+ dev->file, dev_name(dev), dcr->VolumeName);
}
Dmsg3(100, "Got EOF at file %u on device %s, Volume \"%s\"\n",
- dev->file, dev_name(dev), jcr->VolumeName);
+ dev->file, dev_name(dev), dcr->VolumeName);
continue;
} else if (dev_state(dev, ST_SHORT)) {
Jmsg1(jcr, M_ERROR, 0, "%s", dev->errmsg);
/* Some sort of label? */
if (rec->FileIndex < 0) {
handle_session_record(dev, rec, &sessrec);
- ok = record_cb(jcr, dev, block, rec);
+ ok = record_cb(dcr, rec);
if (rec->FileIndex == EOS_LABEL) {
Dmsg2(100, "Remove rec. SI=%d ST=%d\n", rec->VolSessionId,
rec->VolSessionTime);
rec->VolSessionId, rec->VolSessionTime, rec->FileIndex);
break; /* read second part of record */
}
- ok = record_cb(jcr, dev, block, rec);
+ ok = record_cb(dcr, rec);
if (rec->Stream == STREAM_MD5_SIGNATURE || rec->Stream == STREAM_SHA1_SIGNATURE) {
Dmsg3(100, "Done FI=%d before set_eof pos %d:%d\n", rec->FileIndex,
dev->file, dev->block_num);
}
delete recs;
print_block_read_errors(jcr, block);
- free_block(block);
return ok;
}
return rec;
}
+void empty_record(DEV_RECORD *rec)
+{
+ rec->File = rec->Block = 0;
+ rec->VolSessionId = rec->VolSessionTime = 0;
+ rec->FileIndex = rec->Stream = 0;
+ rec->data_len = rec->remainder = 0;
+ rec->state &= ~(REC_PARTIAL_RECORD|REC_BLOCK_EMPTY|REC_NO_MATCH|REC_CONTINUATION);
+}
+
/*
* Free the record entity
*
/*
* Write a Record to the block
*
- * Returns: 0 on failure (none or partially written)
- * 1 on success (all bytes written)
+ * Returns: false on failure (none or partially written)
+ * true on success (all bytes written)
*
* and remainder returned in packet.
*
* non-zero), and 2. The remaining bytes to write may not
* all fit into the block.
*/
-int write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec)
+bool write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec)
{
ser_declare;
uint32_t remlen;
}
} else {
rec->remainder = rec->data_len + WRITE_RECHDR_LENGTH;
- return 0;
+ return false;
}
} else {
/*
}
}
if (remlen == 0) {
- return 0; /* partial transfer */
+ return false; /* partial transfer */
}
/*
block->bufp += remlen;
block->binbuf += remlen;
rec->remainder -= remlen;
- return 0; /* did partial transfer */
+ return false; /* did partial transfer */
}
}
rec->remainder = 0; /* did whole transfer */
- return 1;
+ return true;
}
/*
* Test if we can write whole record to the block
*
- * Returns: 0 on failure
- * 1 on success (all bytes can be written)
+ * Returns: false on failure
+ * true on success (all bytes can be written)
*/
-int can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec)
+bool can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec)
{
uint32_t remlen;
remlen -= WRITE_RECHDR_LENGTH;
rec->remainder = rec->data_len;
} else {
- return 0;
+ return false;
}
} else {
- return 0;
+ return false;
}
if (rec->remainder > 0 && remlen < rec->remainder) {
- return 0;
+ return false;
}
- return 1;
+ return true;
}
/*
* Read a Record from the block
- * Returns: 0 if nothing read or if the continuation record does not match.
- * In both of these cases, a block read must be done.
- * 1 if at least the record header was read, this
- * routine may have to be called again with a new
- * block if the entire record was not read.
+ * Returns: false if nothing read or if the continuation record does not match.
+ * In both of these cases, a block read must be done.
+ * true if at least the record header was read, this
+ * routine may have to be called again with a new
+ * block if the entire record was not read.
*/
-int read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec)
+bool read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec)
{
ser_declare;
uint32_t remlen;
if (rec->remainder && (rec->VolSessionId != VolSessionId ||
rec->VolSessionTime != VolSessionTime)) {
rec->state |= REC_NO_MATCH;
- return 0; /* This is from some other Session */
+ Dmsg0(500, "remainder and VolSession doesn't match\n");
+ return false; /* This is from some other Session */
}
/* if Stream is negative, it means that this is a continuation
rec->data_len = 0; /* return data as if no continuation */
} else if (rec->Stream != -Stream) {
rec->state |= REC_NO_MATCH;
- return 0; /* This is from some other Session */
+ return false; /* This is from some other Session */
}
rec->Stream = -Stream; /* set correct Stream */
} else { /* Regular record */
#endif
rec->state |= (REC_NO_HEADER | REC_BLOCK_EMPTY);
empty_block(block); /* mark block empty */
- return 0;
+ return false;
}
ASSERT(data_bytes < MAX_BLOCK_LENGTH); /* temp sanity check */
Dmsg4(90, "Rtn full rd_rec_blk FI=%s SessId=%d Strm=%s len=%d\n",
FI_to_ascii(rec->FileIndex), rec->VolSessionId,
stream_to_ascii(rec->Stream, rec->FileIndex), rec->data_len);
- return 1; /* transferred full record */
+ return true; /* transferred full record */
}
* Record, and label definitions for Bacula
* media data format.
*
+ * Kern Sibbald, MM
+ *
* Version $Id$
*
*/
/*
- Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
+ Copyright (C) 2000-2004 Kern Sibbald and John Walker
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
static bool open_data_spool_file(JCR *jcr);
static bool close_data_spool_file(JCR *jcr);
static bool despool_data(DCR *dcr, bool commit);
-static int read_block_from_spool_file(DCR *dcr, DEV_BLOCK *block);
+static int read_block_from_spool_file(DCR *dcr);
static bool open_attr_spool_file(JCR *jcr, BSOCK *bs);
static bool close_attr_spool_file(JCR *jcr, BSOCK *bs);
-static bool write_spool_header(DCR *dcr, DEV_BLOCK *block);
-static bool write_spool_data(DCR *dcr, DEV_BLOCK *block);
+static bool write_spool_header(DCR *dcr);
+static bool write_spool_data(DCR *dcr);
struct spool_stats_t {
uint32_t data_jobs; /* current jobs spooling data */
rdev = (DEVICE *)malloc(sizeof(DEVICE));
memset(rdev, 0, sizeof(DEVICE));
rdev->dev_name = get_memory(strlen(spool_name)+1);
- strcpy(rdev->dev_name, spool_name);
+ bstrncpy(rdev->dev_name, spool_name, sizeof(rdev->dev_name));
rdev->errmsg = get_pool_memory(PM_EMSG);
*rdev->errmsg = 0;
rdev->max_block_size = dcr->dev->max_block_size;
rdcr = new_dcr(NULL, rdev);
rdcr->spool_fd = dcr->spool_fd;
rdcr->jcr = jcr; /* set a valid jcr */
- block = rdcr->block;
+ block = dcr->block; /* save block */
+ dcr->block = rdcr->block; /* make read and write block the same */
Dmsg1(800, "read/write block size = %d\n", block->buf_len);
lseek(rdcr->spool_fd, 0, SEEK_SET); /* rewind */
ok = false;
break;
}
- stat = read_block_from_spool_file(rdcr, block);
+ stat = read_block_from_spool_file(rdcr);
if (stat == RB_EOT) {
break;
} else if (stat == RB_ERROR) {
ok = false;
break;
}
- ok = write_block_to_device(dcr, block);
+ ok = write_block_to_device(dcr);
Dmsg3(100, "Write block ok=%d FI=%d LI=%d\n", ok, block->FirstIndex, block->LastIndex);
}
+ dcr->block = block; /* reset block */
lseek(rdcr->spool_fd, 0, SEEK_SET); /* rewind */
if (ftruncate(rdcr->spool_fd, 0) != 0) {
* RB_EOT when file done
* RB_ERROR on error
*/
-static int read_block_from_spool_file(DCR *dcr, DEV_BLOCK *block)
+static int read_block_from_spool_file(DCR *dcr)
{
uint32_t rlen;
ssize_t stat;
spool_hdr hdr;
+ DEV_BLOCK *block = dcr->block;
rlen = sizeof(hdr);
stat = read(dcr->spool_fd, (char *)&hdr, (size_t)rlen);
* Returns: true on success or EOT
* false on hard error
*/
-bool write_block_to_spool_file(DCR *dcr, DEV_BLOCK *block)
+bool write_block_to_spool_file(DCR *dcr)
{
uint32_t wlen, hlen; /* length to write */
bool despool = false;
+ DEV_BLOCK *block = dcr->block;
ASSERT(block->binbuf == ((uint32_t) (block->bufp - block->buf)));
if (block->binbuf <= WRITE_BLKHDR_LENGTH) { /* Does block have data in it? */
}
- if (!write_spool_header(dcr, block)) {
+ if (!write_spool_header(dcr)) {
return false;
}
- if (!write_spool_data(dcr, block)) {
+ if (!write_spool_data(dcr)) {
return false;
}
return true;
}
-static bool write_spool_header(DCR *dcr, DEV_BLOCK *block)
+static bool write_spool_header(DCR *dcr)
{
spool_hdr hdr;
ssize_t stat;
+ DEV_BLOCK *block = dcr->block;
hdr.FirstIndex = block->FirstIndex;
hdr.LastIndex = block->LastIndex;
return false;
}
-static bool write_spool_data(DCR *dcr, DEV_BLOCK *block)
+static bool write_spool_data(DCR *dcr)
{
ssize_t stat;
+ DEV_BLOCK *block = dcr->block;
/* Write data */
for (int retry=0; retry<=1; retry++) {
Jmsg(dcr->jcr, M_FATAL, 0, _("Fatal despooling error."));
return false;
}
- if (!write_spool_header(dcr, block)) {
+ if (!write_spool_header(dcr)) {
return false;
}
continue; /* try again */
}
spool_stats.attr_size += size;
V(mutex);
- Jmsg(jcr, M_INFO, 0, _("Sending spooled attrs to DIR. Despooling %s bytes ...\n"),
+ Jmsg(jcr, M_INFO, 0, _("Sending spooled attrs to the Director. Despooling %s bytes ...\n"),
edit_uint64_with_commas(size, ec1));
bnet_despool_to_bsock(jcr->dir_bsock, update_attr_spool_size, size);
return close_attr_spool_file(jcr, jcr->dir_bsock);
/* Static variables */
-static char qstatus[] = ".status %s\n";
+static char qstatus[] = ".status %127s\n";
static char OKqstatus[] = "3000 OK .status\n";
static char DotStatusJob[] = "JobId=%d JobStatus=%c JobErrors=%d\n";
/*
* Status command from Director
*/
-int status_cmd(JCR *jcr)
+bool status_cmd(JCR *jcr)
{
DEVRES *device;
DEVICE *dev;
list_spool_stats(user);
bnet_sig(user, BNET_EOD);
- return 1;
+ return true;
}
static void send_blocked_status(JCR *jcr, DEVICE *dev)
{
BSOCK *user = jcr->dir_bsock;
+ DCR *dcr = jcr->dcr;
switch (dev->dev_blocked) {
case BST_UNMOUNTED:
case BST_WAITING_FOR_SYSOP:
if (jcr->JobStatus == JS_WaitMount) {
bnet_fsend(user, _(" Device is BLOCKED waiting for mount of volume \"%s\".\n"),
- jcr->VolumeName);
+ dcr->VolumeName);
} else {
bnet_fsend(user, _(" Device is BLOCKED waiting for appendable media.\n"));
}
job_type_to_str(jcr->JobType),
JobName,
jcr->JobId,
- jcr->VolumeName,
+ jcr->dcr->VolumeName,
jcr->device->device_name);
sec = time(NULL) - jcr->run_time;
if (sec <= 0) {
/*
* .status command from Director
*/
-int qstatus_cmd(JCR *jcr)
+bool qstatus_cmd(JCR *jcr)
{
BSOCK *dir = jcr->dir_bsock;
- POOLMEM *time;
+ POOL_MEM time;
JCR *njcr;
s_last_job* job;
- time = get_memory(dir->msglen+1);
-
- if (sscanf(dir->msg, qstatus, time) != 1) {
- pm_strcpy(&jcr->errmsg, dir->msg);
+ if (sscanf(dir->msg, qstatus, time.c_str()) != 1) {
+ pm_strcpy(jcr->errmsg, dir->msg);
Jmsg1(jcr, M_FATAL, 0, _("Bad .status command: %s\n"), jcr->errmsg);
bnet_fsend(dir, "3900 Bad .status command, missing argument.\n");
bnet_sig(dir, BNET_EOD);
- free_memory(time);
- return 0;
+ return false;
}
unbash_spaces(time);
- if (strcmp(time, "current") == 0) {
- bnet_fsend(dir, OKqstatus, time);
+ if (strcmp(time.c_str(), "current") == 0) {
+ bnet_fsend(dir, OKqstatus, time.c_str());
lock_jcr_chain();
foreach_jcr(njcr) {
- if (njcr->JobId != 0) {
- bnet_fsend(dir, DotStatusJob, njcr->JobId, njcr->JobStatus, njcr->JobErrors);
- }
- free_locked_jcr(njcr);
+ if (njcr->JobId != 0) {
+ bnet_fsend(dir, DotStatusJob, njcr->JobId, njcr->JobStatus, njcr->JobErrors);
+ }
+ free_locked_jcr(njcr);
}
unlock_jcr_chain();
}
- else if (strcmp(time, "last") == 0) {
- bnet_fsend(dir, OKqstatus, time);
+ else if (strcmp(time.c_str(), "last") == 0) {
+ bnet_fsend(dir, OKqstatus, time.c_str());
if ((last_jobs) && (last_jobs->size() > 0)) {
- job = (s_last_job*)last_jobs->last();
- bnet_fsend(dir, DotStatusJob, job->JobId, job->JobStatus, job->Errors);
+ job = (s_last_job*)last_jobs->last();
+ bnet_fsend(dir, DotStatusJob, job->JobId, job->JobStatus, job->Errors);
}
}
else {
- pm_strcpy(&jcr->errmsg, dir->msg);
+ pm_strcpy(jcr->errmsg, dir->msg);
Jmsg1(jcr, M_FATAL, 0, _("Bad .status command: %s\n"), jcr->errmsg);
bnet_fsend(dir, "3900 Bad .status command, wrong argument.\n");
bnet_sig(dir, BNET_EOD);
- free_memory(time);
- return 0;
+ return false;
}
-
bnet_sig(dir, BNET_EOD);
- free_memory(time);
- return 1;
+ return true;
}
}
jcr->device = device;
dcr = new_dcr(jcr, device->dev);
- switch (read_dev_volume_label(dcr, dcr->block)) {
+ switch (read_dev_volume_label(dcr)) {
case VOL_OK:
break;
default:
#else
#define uLongf uint32_t
#endif
+#ifdef HAVE_FNMATCH
+#include <fnmatch.h>
+#else
+#include "lib/fnmatch.h"
+#endif
extern STORES *me; /* "Global" daemon resource */
extern bool forge_on; /* proceed inspite of I/O errors */
{"alwaysopen", store_yesno, ITEM(res_dev.cap_bits), CAP_ALWAYSOPEN, ITEM_DEFAULT, 1},
{"autochanger", store_yesno, ITEM(res_dev.cap_bits), CAP_AUTOCHANGER, ITEM_DEFAULT, 0},
{"closeonpoll", store_yesno, ITEM(res_dev.cap_bits), CAP_CLOSEONPOLL, ITEM_DEFAULT, 0},
+ {"blockpositioning", store_yesno, ITEM(res_dev.cap_bits), CAP_POSITIONBLOCKS, ITEM_DEFAULT, 1},
{"changerdevice", store_strname,ITEM(res_dev.changer_name), 0, 0, 0},
{"changercommand", store_strname,ITEM(res_dev.changer_command), 0, 0, 0},
{"alertcommand", store_strname,ITEM(res_dev.alert_command), 0, 0, 0},
R_DEVICE,
R_MSGS,
R_FIRST = R_DIRECTOR,
- R_LAST = R_MSGS /* keep this updated */
+ R_LAST = R_MSGS /* keep this updated */
};
enum {
/* Definition of the contents of each Resource */
struct DIRRES {
- RES hdr;
+ RES hdr;
char *password; /* Director password */
char *address; /* Director IP address or zero */
/* Storage daemon "global" definitions */
struct s_res_store {
- RES hdr;
+ RES hdr;
dlist *sdaddrs;
dlist *sddaddrs;
- char *working_directory; /* working directory for checkpoints */
+ char *working_directory; /* working directory for checkpoints */
char *pid_directory;
char *subsys_directory;
- int require_ssl; /* Require SSL on all connections */
+ int require_ssl; /* Require SSL on all connections */
uint32_t max_concurrent_jobs; /* maximum concurrent jobs to run */
- MSGS *messages; /* Daemon message handler */
- utime_t heartbeat_interval; /* Interval to send hb to FD */
+ MSGS *messages; /* Daemon message handler */
+ utime_t heartbeat_interval; /* Interval to send hb to FD */
};
typedef struct s_res_store STORES;
/* Device specific definitions */
struct DEVRES {
- RES hdr;
+ RES hdr;
- char *media_type; /* User assigned media type */
- char *device_name; /* Archive device name */
- char *changer_name; /* Changer device name */
- char *changer_command; /* Changer command -- external program */
- char *alert_command; /* Alert command -- external program */
- char *spool_directory; /* Spool file directory */
- uint32_t drive_index; /* Autochanger drive index */
- uint32_t cap_bits; /* Capabilities of this device */
- uint32_t max_changer_wait; /* Changer timeout */
- uint32_t max_rewind_wait; /* maximum secs to wait for rewind */
- uint32_t max_open_wait; /* maximum secs to wait for open */
- uint32_t max_open_vols; /* maximum simultaneous open volumes */
- uint32_t min_block_size; /* min block size */
- uint32_t max_block_size; /* max block size */
- uint32_t max_volume_jobs; /* max jobs to put on one volume */
+ char *media_type; /* User assigned media type */
+ char *device_name; /* Archive device name */
+ char *changer_name; /* Changer device name */
+ char *changer_command; /* Changer command -- external program */
+ char *alert_command; /* Alert command -- external program */
+ char *spool_directory; /* Spool file directory */
+ uint32_t drive_index; /* Autochanger drive index */
+ uint32_t cap_bits; /* Capabilities of this device */
+ uint32_t max_changer_wait; /* Changer timeout */
+ uint32_t max_rewind_wait; /* maximum secs to wait for rewind */
+ uint32_t max_open_wait; /* maximum secs to wait for open */
+ uint32_t max_open_vols; /* maximum simultaneous open volumes */
+ uint32_t min_block_size; /* min block size */
+ uint32_t max_block_size; /* max block size */
+ uint32_t max_volume_jobs; /* max jobs to put on one volume */
uint32_t max_network_buffer_size; /* max network buf size */
- utime_t vol_poll_interval; /* interval between polling volume during mount */
- int64_t max_volume_files; /* max files to put on one volume */
- int64_t max_volume_size; /* max bytes to put on one volume */
- int64_t max_file_size; /* max file size in bytes */
- int64_t volume_capacity; /* advisory capacity */
- int64_t max_spool_size; /* Max spool size for all jobs */
- int64_t max_job_spool_size; /* Max spool size for any single job */
- DEVICE *dev; /* Pointer to phyical dev -- set at runtime */
+ utime_t vol_poll_interval; /* interval between polling volume during mount */
+ int64_t max_volume_files; /* max files to put on one volume */
+ int64_t max_volume_size; /* max bytes to put on one volume */
+ int64_t max_file_size; /* max file size in bytes */
+ int64_t volume_capacity; /* advisory capacity */
+ int64_t max_spool_size; /* Max spool size for all jobs */
+ int64_t max_job_spool_size; /* Max spool size for any single job */
+ DEVICE *dev; /* Pointer to phyical dev -- set at runtime */
};
union URES {
STORES res_store;
DEVRES res_dev;
MSGS res_msgs;
- RES hdr;
+ RES hdr;
};
}
/* Open database */
- db = db_init_database(NULL, db_name, user, password, dbhost, 0, NULL);
+ db = db_init_database(NULL, db_name, user, password, dbhost, 0, NULL, 0);
if (!db_open_database(NULL, db)) {
Emsg1(M_FATAL, 0, "%s", db_strerror(db));
return 1;
/* */
#undef VERSION
#define VERSION "1.35.3"
-#define BDATE "09 September 2004"
-#define LSMDATE "09Sep04"
+#define BDATE "19 September 2004"
+#define LSMDATE "19Sep04"
/* Debug flags */
#undef DEBUG
#define TRACEBACK 1
#define SMCHECK
#define TRACE_FILE 1
+#define DEVELOPER 1
/* Debug flags not normally turned on */