From: Kern Sibbald Date: Sun, 19 Sep 2004 18:56:29 +0000 (+0000) Subject: Massive SD calling sequence reorganization X-Git-Tag: Release-7.0.0~9182 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=1c31d780ff8befc9ef13c681d991bf235cb5f735;p=bacula%2Fbacula Massive SD calling sequence reorganization git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@1597 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/bacula/ChangeLog b/bacula/ChangeLog index 9f7b7306ff..967eaeb087 100644 --- a/bacula/ChangeLog +++ b/bacula/ChangeLog @@ -1,6 +1,69 @@ -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 diff --git a/bacula/ReleaseNotes b/bacula/ReleaseNotes index b840899197..d2c531623e 100644 --- a/bacula/ReleaseNotes +++ b/bacula/ReleaseNotes @@ -1,9 +1,9 @@ - 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 @@ -20,16 +20,87 @@ Items to note!!! - 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 @@ -40,12 +111,49 @@ Other Items: - 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). diff --git a/bacula/kernstodo b/bacula/kernstodo index 89f2f18b7c..963aadbf6c 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -1,5 +1,5 @@ Kern's ToDo List - 08 Septermber 2004 + 17 Septermber 2004 Major development: Project Developer @@ -11,16 +11,12 @@ Version 1.35 Kern (see below) ======================================================== 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. @@ -363,6 +359,11 @@ Wish list: 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 @@ -370,7 +371,6 @@ Wish list: 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 @@ -382,8 +382,8 @@ Wish list: 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. @@ -1346,5 +1346,9 @@ Block Position: 0 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. - diff --git a/bacula/src/cats/bdb.c b/bacula/src/cats/bdb.c index df980da160..143d32d995 100644 --- a/bacula/src/cats/bdb.c +++ b/bacula/src/cats/bdb.c @@ -14,7 +14,7 @@ /* - 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 @@ -103,7 +103,8 @@ int bdb_write_control_file(B_DB *mdb) */ 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 */ @@ -131,8 +132,9 @@ db_init_database(JCR *jcr, char *db_name, char *db_user, char *db_password, 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; } diff --git a/bacula/src/cats/mysql.c b/bacula/src/cats/mysql.c index d327927c44..1fd12e0157 100644 --- a/bacula/src/cats/mysql.c +++ b/bacula/src/cats/mysql.c @@ -57,7 +57,8 @@ static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; */ 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; @@ -67,12 +68,14 @@ db_init_database(JCR *jcr, const char *db_name, const char *db_user, const char } 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"); diff --git a/bacula/src/cats/postgresql.c b/bacula/src/cats/postgresql.c index a8779e8b66..d6b1a6567b 100644 --- a/bacula/src/cats/postgresql.c +++ b/bacula/src/cats/postgresql.c @@ -9,7 +9,7 @@ */ /* - 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 @@ -59,7 +59,8 @@ static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; */ 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; @@ -68,17 +69,19 @@ db_init_database(JCR *jcr, const char *db_name, const char *db_user, const char 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); diff --git a/bacula/src/cats/protos.h b/bacula/src/cats/protos.h index c5c41879eb..234ebe93d8 100644 --- a/bacula/src/cats/protos.h +++ b/bacula/src/cats/protos.h @@ -34,7 +34,8 @@ /* 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); @@ -51,7 +52,7 @@ int db_create_job_record(JCR *jcr, B_DB *db, JOB_DBR *jr); 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); diff --git a/bacula/src/cats/sqlite.c b/bacula/src/cats/sqlite.c index c98b571242..1df4ae151c 100644 --- a/bacula/src/cats/sqlite.c +++ b/bacula/src/cats/sqlite.c @@ -60,18 +60,21 @@ int QueryDB(const char *file, int line, JCR *jcr, B_DB *db, char *select_cmd); */ 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"); diff --git a/bacula/src/dird/Makefile.in b/bacula/src/dird/Makefile.in index 1ee51c39ba..704d1c2f77 100644 --- a/bacula/src/dird/Makefile.in +++ b/bacula/src/dird/Makefile.in @@ -26,7 +26,8 @@ SVRSRCS = dird.c admin.c authenticate.c \ 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 \ @@ -39,7 +40,8 @@ SVROBJS = dird.o admin.o authenticate.o \ 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 \ diff --git a/bacula/src/dird/authenticate.c b/bacula/src/dird/authenticate.c index ab680fdcd3..dd6787c9ba 100644 --- a/bacula/src/dird/authenticate.c +++ b/bacula/src/dird/authenticate.c @@ -52,7 +52,7 @@ static char Dir_sorry[] = "1999 You are not authorized.\n"; /* * 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]; @@ -63,15 +63,15 @@ int authenticate_storage_daemon(JCR *jcr) */ 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")); diff --git a/bacula/src/dird/backup.c b/bacula/src/dird/backup.c index 11ddbab5ac..9f7d07c7a9 100644 --- a/bacula/src/dird/backup.c +++ b/bacula/src/dird/backup.c @@ -67,6 +67,7 @@ int do_backup(JCR *jcr) BSOCK *fd; POOL_DBR pr; FILESET_DBR fsr; + STORE *store; since[0] = 0; @@ -80,7 +81,7 @@ int do_backup(JCR *jcr) 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 @@ -182,11 +183,12 @@ int do_backup(JCR *jcr) /* * 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; } diff --git a/bacula/src/dird/dird.c b/bacula/src/dird/dird.c index be64a25307..6e36523d4e 100644 --- a/bacula/src/dird/dird.c +++ b/bacula/src/dird/dird.c @@ -523,6 +523,9 @@ Without that I don't know who I am :-(\n"), configfile); } *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", @@ -533,6 +536,22 @@ Without that I don't know who I am :-(\n"), configfile); } *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 @@ -571,7 +590,7 @@ Without that I don't know who I am :-(\n"), configfile); 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; } @@ -593,7 +612,8 @@ Without that I don't know who I am :-(\n"), configfile); */ 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); diff --git a/bacula/src/dird/dird_conf.c b/bacula/src/dird/dird_conf.c index 6eef624496..a2f4a75e9d 100644 --- a/bacula/src/dird/dird_conf.c +++ b/bacula/src/dird/dird_conf.c @@ -8,14 +8,14 @@ * 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 * @@ -83,7 +83,7 @@ int res_all_size = sizeof(res_all); /* * 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}, @@ -108,7 +108,7 @@ static RES_ITEM dir_items[] = { /* * 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}, @@ -131,7 +131,7 @@ static RES_ITEM con_items[] = { /* * Client or File daemon resource * - * name handler value code flags default_value + * name handler value code flags default_value */ static RES_ITEM cli_items[] = { @@ -153,7 +153,7 @@ 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}, @@ -176,7 +176,7 @@ static RES_ITEM store_items[] = { /* * 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}, @@ -197,17 +197,17 @@ static RES_ITEM cat_items[] = { /* * 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}, @@ -244,7 +244,7 @@ RES_ITEM job_items[] = { /* 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}, @@ -252,13 +252,13 @@ static RES_ITEM fs_items[] = { {"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}, @@ -269,7 +269,7 @@ static RES_ITEM sch_items[] = { /* 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}, @@ -297,7 +297,7 @@ static RES_ITEM pool_items[] = { /* * 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}, @@ -320,7 +320,7 @@ extern RES_ITEM msgs_items[]; * 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}, @@ -335,13 +335,13 @@ RES_TABLE resources[] = { {"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}, @@ -356,19 +356,19 @@ struct s_jl joblevels[] = { {"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 @@ -378,7 +378,7 @@ static struct s_kw BakVerFields[] = { {"client", 'C'}, {"fileset", 'F'}, {"level", 'L'}, - {NULL, 0} + {NULL, 0} }; /* Keywords (RHS) permitted in Restore records */ @@ -389,7 +389,7 @@ static struct s_kw RestoreFields[] = { {"where", 'W'}, /* root of restore */ {"replace", 'R'}, /* replacement options */ {"bootstrap", 'B'}, /* bootstrap file */ - {NULL, 0} + {NULL, 0} }; #endif @@ -399,7 +399,7 @@ struct s_kw ReplaceOptions[] = { {"ifnewer", REPLACE_IFNEWER}, {"ifolder", REPLACE_IFOLDER}, {"never", REPLACE_NEVER}, - {NULL, 0} + {NULL, 0} }; const char *level_to_str(int level) @@ -411,8 +411,8 @@ 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; @@ -429,93 +429,93 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm 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)); @@ -535,34 +535,35 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm 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: @@ -570,151 +571,151 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm int i, j, k; sendit(sock, "FileSet: name=%s\n", res->res_fs.hdr.name); for (i=0; ires_fs.num_includes; i++) { - INCEXE *incexe = res->res_fs.include_items[i]; - for (j=0; jnum_opts; j++) { - FOPTS *fo = incexe->opts_list[j]; + INCEXE *incexe = res->res_fs.include_items[i]; + for (j=0; jnum_opts; j++) { + FOPTS *fo = incexe->opts_list[j]; sendit(sock, " O %s\n", fo->opts); - for (k=0; kregex.size(); k++) { + for (k=0; kregex.size(); k++) { sendit(sock, " R %s\n", fo->regex.get(k)); - } - for (k=0; kwild.size(); k++) { + } + for (k=0; kwild.size(); k++) { sendit(sock, " W %s\n", fo->wild.get(k)); - } - for (k=0; kbase.size(); k++) { + } + for (k=0; kbase.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; jname_list.size(); j++) { + } + for (j=0; jname_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; ires_fs.num_excludes; i++) { - INCEXE *incexe = res->res_fs.exclude_items[i]; - for (j=0; jname_list.size(); j++) { + INCEXE *incexe = res->res_fs.exclude_items[i]; + for (j=0; jname_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); @@ -744,10 +745,10 @@ static void free_incexe(INCEXE *incexe) 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); } @@ -767,7 +768,7 @@ static void free_incexe(INCEXE *incexe) 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) @@ -785,147 +786,152 @@ void free_resource(RES *sres, int type) 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; ires_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; @@ -961,16 +967,16 @@ void save_resource(int type, RES_ITEM *items, int pass) * 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]); - } + } } } @@ -989,74 +995,76 @@ void save_resource(int type, RES_ITEM *items, int pass) 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; } @@ -1110,22 +1118,22 @@ void save_resource(int type, RES_ITEM *items, int pass) 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); } } } @@ -1142,9 +1150,9 @@ void store_jobtype(LEX *lc, RES_ITEM *item, int index, int 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) { @@ -1166,9 +1174,9 @@ void store_level(LEX *lc, RES_ITEM *item, int index, int pass) /* 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) { @@ -1185,9 +1193,9 @@ void store_replace(LEX *lc, RES_ITEM *item, int index, int pass) /* 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) { @@ -1208,16 +1216,16 @@ void store_acl(LEX *lc, RES_ITEM *item, int index, int pass) 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; } diff --git a/bacula/src/dird/dird_conf.h b/bacula/src/dird/dird_conf.h index f3a45bca6a..bd864082b6 100644 --- a/bacula/src/dird/dird_conf.h +++ b/bacula/src/dird/dird_conf.h @@ -191,6 +191,8 @@ struct STORE { }; +#define MAX_STORE 2 /* Max storage directives in Job */ + /* * Job Resource */ @@ -198,7 +200,7 @@ struct JOB { 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 */ @@ -229,7 +231,7 @@ struct JOB { 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 */ diff --git a/bacula/src/dird/fd_cmds.c b/bacula/src/dird/fd_cmds.c index cb0175610c..ee2e89eda4 100644 --- a/bacula/src/dird/fd_cmds.c +++ b/bacula/src/dird/fd_cmds.c @@ -76,14 +76,18 @@ int connect_to_file_daemon(JCR *jcr, int retry_interval, int max_retry_time, { 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); diff --git a/bacula/src/dird/job.c b/bacula/src/dird/job.c index 7cae21469a..33935436d7 100644 --- a/bacula/src/dird/job.c +++ b/bacula/src/dird/job.c @@ -42,6 +42,7 @@ static bool job_check_maxruntime(JCR *control_jcr, JCR *jcr); 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); @@ -107,7 +108,8 @@ JobId_t run_job(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); @@ -229,6 +231,14 @@ static void *job_thread(void *arg) 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; @@ -328,6 +338,9 @@ int cancel_job(UAContext *ua, JCR *jcr) /* Cancel Storage daemon */ if (jcr->store_bsock) { ua->jcr->store = jcr->store; + for (int i=0; ijcr->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; @@ -727,11 +740,13 @@ void set_jcr_defaults(JCR *jcr, JOB *job) 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; istorage[i] = job->storage[i]; + } jcr->client = job->client; if (!jcr->client_name) { jcr->client_name = get_pool_memory(PM_NAME); diff --git a/bacula/src/dird/mac.c b/bacula/src/dird/mac.c new file mode 100644 index 0000000000..ee60359c51 --- /dev/null +++ b/bacula/src/dird/mac.c @@ -0,0 +1,415 @@ +/* + * + * 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"); +} diff --git a/bacula/src/dird/msgchan.c b/bacula/src/dird/msgchan.c index c92f07fb00..ee9fffb5a8 100644 --- a/bacula/src/dird/msgchan.c +++ b/bacula/src/dird/msgchan.c @@ -60,29 +60,34 @@ extern "C" void *msg_thread(void *arg); * 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; } /* @@ -94,7 +99,7 @@ int start_storage_daemon_job(JCR *jcr) 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; @@ -135,32 +140,24 @@ int start_storage_daemon_job(JCR *jcr) /* * 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; } diff --git a/bacula/src/dird/next_vol.c b/bacula/src/dird/next_vol.c index 0f95284cb0..5f58db8236 100644 --- a/bacula/src/dird/next_vol.c +++ b/bacula/src/dird/next_vol.c @@ -45,15 +45,16 @@ int find_next_volume_for_append(JCR *jcr, MEDIA_DBR *mr, bool create) 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 */ diff --git a/bacula/src/dird/protos.h b/bacula/src/dird/protos.h index 45101b08e3..f021ea54cb 100644 --- a/bacula/src/dird/protos.h +++ b/bacula/src/dird/protos.h @@ -24,7 +24,7 @@ */ /* 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); @@ -62,7 +62,7 @@ int variable_expansion(JCR *jcr, char *inp, POOLMEM **exp); /* 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); @@ -70,7 +70,7 @@ extern int send_level_command(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); @@ -95,8 +95,8 @@ extern void init_jcr_job_record(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); @@ -148,28 +148,28 @@ JCR *new_control_jcr(const char *base_name, int job_type); 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); diff --git a/bacula/src/dird/restore.c b/bacula/src/dird/restore.c index 731dad3ca6..fa541d84cd 100644 --- a/bacula/src/dird/restore.c +++ b/bacula/src/dird/restore.c @@ -111,7 +111,7 @@ int do_restore(JCR *jcr) 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; diff --git a/bacula/src/dird/ua_cmds.c b/bacula/src/dird/ua_cmds.c index 7ea798769f..fd55e82f79 100644 --- a/bacula/src/dird/ua_cmds.c +++ b/bacula/src/dird/ua_cmds.c @@ -1189,24 +1189,25 @@ static int update_pool(UAContext *ua) 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; } @@ -1820,9 +1821,9 @@ static void do_mount_cmd(UAContext *ua, const char *command) { STORE *store; BSOCK *sd; + JCR *jcr = ua->jcr; char dev_name[MAX_NAME_LENGTH]; - if (!open_db(ua)) { return; } @@ -1836,13 +1837,13 @@ static void do_mount_cmd(UAContext *ua, const char *command) 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) { @@ -1850,7 +1851,7 @@ static void do_mount_cmd(UAContext *ua, const char *command) } bnet_sig(sd, BNET_TERMINATE); bnet_close(sd); - ua->jcr->store_bsock = NULL; + jcr->store_bsock = NULL; } /* @@ -1996,7 +1997,8 @@ int open_db(UAContext *ua) 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); diff --git a/bacula/src/dird/ua_dotcmds.c b/bacula/src/dird/ua_dotcmds.c index 98c9c53de0..291613ccb7 100644 --- a/bacula/src/dird/ua_dotcmds.c +++ b/bacula/src/dird/ua_dotcmds.c @@ -253,13 +253,15 @@ static int defaultscmd(UAContext *ua, const char *cmd) 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); } diff --git a/bacula/src/dird/ua_output.c b/bacula/src/dird/ua_output.c index 69df08e6b3..9a1f11d2f2 100644 --- a/bacula/src/dird/ua_output.c +++ b/bacula/src/dird/ua_output.c @@ -586,7 +586,8 @@ int complete_jcr_for_job(JCR *jcr, JOB *job, POOL *pool) } 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); diff --git a/bacula/src/dird/ua_run.c b/bacula/src/dird/ua_run.c index fcf5acc76e..7078d2f95e 100644 --- a/bacula/src/dird/ua_run.c +++ b/bacula/src/dird/ua_run.c @@ -272,6 +272,10 @@ int run_cmd(UAContext *ua, const char *cmd) } 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) { @@ -283,13 +287,16 @@ int run_cmd(UAContext *ua, const char *cmd) 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) { @@ -303,6 +310,10 @@ int run_cmd(UAContext *ua, const char *cmd) } 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) { @@ -318,6 +329,10 @@ int run_cmd(UAContext *ua, const char *cmd) } 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) { @@ -331,6 +346,10 @@ int run_cmd(UAContext *ua, const char *cmd) } 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) { @@ -397,6 +416,11 @@ int run_cmd(UAContext *ua, const char *cmd) 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; diff --git a/bacula/src/dird/ua_server.c b/bacula/src/dird/ua_server.c index bfdc5ec885..afd32d6b6c 100644 --- a/bacula/src/dird/ua_server.c +++ b/bacula/src/dird/ua_server.c @@ -168,15 +168,13 @@ static void *handle_UA_client_request(void *arg) 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); diff --git a/bacula/src/dird/ua_status.c b/bacula/src/dird/ua_status.c index 70f0bc8054..d7ef5b6416 100644 --- a/bacula/src/dird/ua_status.c +++ b/bacula/src/dird/ua_status.c @@ -67,18 +67,18 @@ int qstatus_cmd(UAContext *ua, const char *cmd) 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 { @@ -449,7 +449,7 @@ static void list_scheduled_jobs(UAContext *ua) continue; } for (run=NULL; (run = find_next_run(run, job, runtime)); ) { - level = job->level; + level = job->JobLevel; if (run->level) { level = run->level; } diff --git a/bacula/src/dird/verify.c b/bacula/src/dird/verify.c index 997eff3e59..efa2f7ea01 100644 --- a/bacula/src/dird/verify.c +++ b/bacula/src/dird/verify.c @@ -379,10 +379,14 @@ static void verify_cleanup(JCR *jcr, int TermCode) 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; diff --git a/bacula/src/findlib/makepath.c b/bacula/src/findlib/makepath.c index a971373c80..c1d07223ff 100644 --- a/bacula/src/findlib/makepath.c +++ b/bacula/src/findlib/makepath.c @@ -133,7 +133,6 @@ make_dir(JCR *jcr, const char *dir, const char *dirpath, mode_t mode, int *creat } /* return non-zero if path is absolute or zero if relative. */ - int isAbsolute(const char *path) { diff --git a/bacula/src/findlib/match.c b/bacula/src/findlib/match.c index 62d3da7329..43a27a2b53 100644 --- a/bacula/src/findlib/match.c +++ b/bacula/src/findlib/match.c @@ -336,6 +336,10 @@ int file_is_excluded(FF_PKT *ff, const char *file) { const char *p; + /* + * ***NB*** this removes the drive from the exclude + * rule. Why????? + */ if (win32_client && file[1] == ':') { file += 2; } diff --git a/bacula/src/jcr.h b/bacula/src/jcr.h index 7c142ddd86..330d5f49ac 100644 --- a/bacula/src/jcr.h +++ b/bacula/src/jcr.h @@ -53,7 +53,9 @@ #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 */ @@ -104,6 +106,7 @@ struct JCR { 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 */ @@ -122,7 +125,6 @@ struct JCR { 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 */ @@ -139,6 +141,7 @@ struct JCR { /* 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 */ @@ -146,7 +149,8 @@ struct JCR { 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 */ @@ -218,18 +222,12 @@ struct JCR { 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 */ diff --git a/bacula/src/lib/attr.c b/bacula/src/lib/attr.c index aaf335d281..3aee618880 100644 --- a/bacula/src/lib/attr.c +++ b/bacula/src/lib/attr.c @@ -93,7 +93,7 @@ int unpack_attributes_record(JCR *jcr, int32_t stream, char *rec, ATTR *attr) 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; @@ -121,27 +121,27 @@ void build_attr_output_fnames(JCR *jcr, ATTR *attr) * 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 */ @@ -152,22 +152,21 @@ void build_attr_output_fnames(JCR *jcr, ATTR *attr) */ 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 */ } } } diff --git a/bacula/src/lib/berrno.h b/bacula/src/lib/berrno.h index 1879ded31a..0fb16426c8 100644 --- a/bacula/src/lib/berrno.h +++ b/bacula/src/lib/berrno.h @@ -41,6 +41,7 @@ * 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_; diff --git a/bacula/src/lib/bsys.c b/bacula/src/lib/bsys.c index bc5ae5834b..1aa87d9f60 100644 --- a/bacula/src/lib/bsys.c +++ b/bacula/src/lib/bsys.c @@ -45,6 +45,16 @@ char *bstrncpy(char *dest, const char *src, int maxlen) 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); @@ -52,6 +62,14 @@ char *bstrncat(char *dest, const char *src, int maxlen) 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) diff --git a/bacula/src/lib/daemon.c b/bacula/src/lib/daemon.c index b1c24c0ddb..fd87b12cd0 100644 --- a/bacula/src/lib/daemon.c +++ b/bacula/src/lib/daemon.c @@ -44,7 +44,11 @@ daemon_start() int i; pid_t cpid; mode_t oldmask; +#ifdef DEVELOPER + int low_fd = 2; +#else int low_fd = -1; +#endif /* * Become a daemon. */ diff --git a/bacula/src/lib/dlist.h b/bacula/src/lib/dlist.h index 1bb1b3c140..e0b35b7663 100644 --- a/bacula/src/lib/dlist.h +++ b/bacula/src/lib/dlist.h @@ -3,7 +3,7 @@ */ /* - 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 @@ -26,6 +26,8 @@ * * Doubly linked list -- dlist * + * Kern Sibbald, MMIV + * */ #define M_ABORT 1 diff --git a/bacula/src/lib/mem_pool.c b/bacula/src/lib/mem_pool.c index b10b8a65cc..439085110f 100644 --- a/bacula/src/lib/mem_pool.c +++ b/bacula/src/lib/mem_pool.c @@ -403,3 +403,108 @@ void print_memory_pool_stats() #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; +} diff --git a/bacula/src/lib/mem_pool.h b/bacula/src/lib/mem_pool.h index 839effc8ef..62b508f99f 100644 --- a/bacula/src/lib/mem_pool.h +++ b/bacula/src/lib/mem_pool.h @@ -1,12 +1,12 @@ /* * 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 @@ -66,6 +66,8 @@ extern void free_pool_memory(POOLMEM *buf); 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 */ @@ -73,4 +75,30 @@ extern void print_memory_pool_stats(); #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 diff --git a/bacula/src/lib/parse_conf.c b/bacula/src/lib/parse_conf.c index 273be9c122..80686bbcfa 100755 --- a/bacula/src/lib/parse_conf.c +++ b/bacula/src/lib/parse_conf.c @@ -12,7 +12,7 @@ * 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 @@ -439,21 +439,64 @@ void store_res(LEX *lc, RES_ITEM *item, int index, int pass) 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 diff --git a/bacula/src/lib/parse_conf.h b/bacula/src/lib/parse_conf.h index 92bb70f37d..1385e3e3bf 100644 --- a/bacula/src/lib/parse_conf.h +++ b/bacula/src/lib/parse_conf.h @@ -129,6 +129,7 @@ void store_password(LEX *lc, RES_ITEM *item, int index, int pass); 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); diff --git a/bacula/src/lib/protos.h b/bacula/src/lib/protos.h index 4d054e1ae8..b5957e19c1 100644 --- a/bacula/src/lib/protos.h +++ b/bacula/src/lib/protos.h @@ -26,101 +26,103 @@ 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(); @@ -134,36 +136,36 @@ void job_end_push(JCR *jcr, void job_end_cb(JCR *jcr,void *), void *ctx); /* 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); @@ -173,43 +175,41 @@ void free_getgroup_cache(); /* 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 */ diff --git a/bacula/src/lib/util.c b/bacula/src/lib/util.c index b1eec70438..261292956f 100644 --- a/bacula/src/lib/util.c +++ b/bacula/src/lib/util.c @@ -88,6 +88,11 @@ bash_spaces(char *str) } } +void bash_spaces(POOL_MEM &pm) +{ + bash_spaces(pm.c_str()); +} + /* Convert non-space characters (0x1) back into spaces */ void unbash_spaces(char *str) @@ -99,6 +104,14 @@ 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) { @@ -113,56 +126,6 @@ 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; -} - - - /* diff --git a/bacula/src/stored/acquire.c b/bacula/src/stored/acquire.c index bf739ac7ce..bce27ef00c 100644 --- a/bacula/src/stored/acquire.c +++ b/bacula/src/stored/acquire.c @@ -80,8 +80,8 @@ void free_dcr(DCR *dcr) * 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) { @@ -129,7 +129,6 @@ DCR *acquire_device_for_read(JCR *jcr) for (i=1; iCurVolume; i++) { vol = vol->next; } - pm_strcpy(&jcr->VolumeName, vol->VolumeName); bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName)); for (i=0; i<5; i++) { @@ -143,7 +142,7 @@ DCR *acquire_device_for_read(JCR *jcr) * 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)); @@ -157,7 +156,7 @@ DCR *acquire_device_for_read(JCR *jcr) */ 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 */ @@ -189,7 +188,7 @@ default_path: 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; @@ -214,11 +213,10 @@ default_path: 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); @@ -271,11 +269,10 @@ DCR *acquire_device_for_append(JCR *jcr) * 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; @@ -312,7 +309,7 @@ DCR *acquire_device_for_append(JCR *jcr) * 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")); @@ -330,7 +327,7 @@ DCR *acquire_device_for_append(JCR *jcr) } 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"), @@ -344,7 +341,6 @@ DCR *acquire_device_for_append(JCR *jcr) 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; @@ -389,8 +385,8 @@ bool release_device(JCR *jcr) 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)) { @@ -408,8 +404,8 @@ bool release_device(JCR *jcr) 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); } @@ -423,21 +419,21 @@ bool release_device(JCR *jcr) 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); diff --git a/bacula/src/stored/append.c b/bacula/src/stored/append.c index cff97bf8d3..1cd0780cf4 100644 --- a/bacula/src/stored/append.c +++ b/bacula/src/stored/append.c @@ -46,7 +46,6 @@ bool do_append_data(JCR *jcr) bool ok = true; DEVICE *dev; DEV_RECORD rec; - DEV_BLOCK *block; DCR *dcr; Dmsg0(10, "Start append data.\n"); @@ -70,7 +69,6 @@ bool do_append_data(JCR *jcr) return false; } dev = dcr->dev; - block = dcr->block; memset(&rec, 0, sizeof(rec)); Dmsg1(20, "Begin append device=%s\n", dev_name(dev)); @@ -82,7 +80,7 @@ bool do_append_data(JCR *jcr) /* * 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); @@ -180,10 +178,10 @@ bool do_append_data(JCR *jcr) 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"), @@ -238,7 +236,7 @@ bool do_append_data(JCR *jcr) * 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); @@ -246,7 +244,7 @@ bool do_append_data(JCR *jcr) } 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; diff --git a/bacula/src/stored/askdir.c b/bacula/src/stored/askdir.c index 4080802edb..9efc7b098f 100644 --- a/bacula/src/stored/askdir.c +++ b/bacula/src/stored/askdir.c @@ -70,7 +70,7 @@ bool dir_send_job_status(JCR *jcr) * 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) @@ -81,7 +81,6 @@ 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"); @@ -105,9 +104,7 @@ static bool do_get_volume_info(DCR *dcr) } 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", @@ -131,10 +128,10 @@ bool dir_get_volume_info(DCR *dcr, enum get_vol_info_rw writing) 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); } @@ -159,7 +156,7 @@ bool dir_find_next_appendable_volume(DCR *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 @@ -173,8 +170,8 @@ bool dir_find_next_appendable_volume(DCR *dcr) 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); @@ -213,11 +210,11 @@ bool dir_update_volume_info(DCR *dcr, bool label) 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; } @@ -243,12 +240,12 @@ bool dir_update_volume_info(DCR *dcr, bool label) 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; } @@ -272,14 +269,14 @@ bool dir_create_jobmedia_record(DCR *dcr) 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; @@ -320,7 +317,7 @@ bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec) * 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. * @@ -342,7 +339,7 @@ bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr) 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; } @@ -356,9 +353,9 @@ bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr) * 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; } @@ -367,9 +364,9 @@ bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr) 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; @@ -381,9 +378,9 @@ Please use the \"label\" command to create a new Volume for:\n\ 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; @@ -422,7 +419,7 @@ Please use the \"label\" command to create a new Volume for:\n\ 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\ @@ -451,13 +448,13 @@ volumes for Job=%s.\n"), jcr->Job); /* * 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) @@ -468,24 +465,24 @@ 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; @@ -517,7 +514,7 @@ bool dir_ask_sysop_to_mount_volume(DCR *dcr) } 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)); diff --git a/bacula/src/stored/autochanger.c b/bacula/src/stored/autochanger.c index 342619ad30..b9ef352b31 100644 --- a/bacula/src/stored/autochanger.c +++ b/bacula/src/stored/autochanger.c @@ -52,7 +52,7 @@ int autoload_device(DCR *dcr, int writing, BSOCK *dir) { 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 */ @@ -65,7 +65,7 @@ int autoload_device(DCR *dcr, int writing, BSOCK *dir) 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; } @@ -91,7 +91,7 @@ int autoload_device(DCR *dcr, int writing, BSOCK *dir) 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); @@ -111,7 +111,7 @@ int autoload_device(DCR *dcr, int writing, BSOCK *dir) 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); @@ -187,8 +187,8 @@ void invalid_slot_in_catalog(DCR *dcr) 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 */ @@ -224,8 +224,8 @@ bool autochanger_list(DCR *dcr, BSOCK *dir) 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) { @@ -234,7 +234,7 @@ bool autochanger_list(DCR *dcr, BSOCK *dir) 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 */ @@ -311,18 +311,18 @@ char *edit_device_codes(JCR *jcr, char *omsg, const char *imsg, const char *cmd) 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); diff --git a/bacula/src/stored/bcopy.c b/bacula/src/stored/bcopy.c index d4a5111987..430ade486d 100644 --- a/bacula/src/stored/bcopy.c +++ b/bacula/src/stored/bcopy.c @@ -31,7 +31,7 @@ #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 */ @@ -142,22 +142,28 @@ int main (int argc, char *argv[]) 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); @@ -170,7 +176,7 @@ int main (int argc, char *argv[]) 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")); } @@ -188,7 +194,7 @@ int main (int argc, char *argv[]) /* * 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"), @@ -202,7 +208,7 @@ static bool record_cb(JCR *in_jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *re 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: @@ -218,14 +224,14 @@ static bool record_cb(JCR *in_jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *re 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"), @@ -248,7 +254,7 @@ static bool record_cb(JCR *in_jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *re 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"), @@ -272,10 +278,9 @@ bool dir_send_job_status(JCR *jcr) {return 1;} 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; } diff --git a/bacula/src/stored/bextract.c b/bacula/src/stored/bextract.c index 72439b49a3..fb67da69ae 100644 --- a/bacula/src/stored/bextract.c +++ b/bacula/src/stored/bextract.c @@ -2,7 +2,7 @@ * * Dumb program to extract files from a Bacula backup. * - * Kern E. Sibbald, 2000 + * Kern E. Sibbald, MM * * Version $Id$ * @@ -38,7 +38,7 @@ int win32_client = 0; #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; @@ -79,6 +79,7 @@ static void usage() " -e exclude list\n" " -i include list\n" " -p proceed inspite of I/O errors\n" +" -v verbose\n" " -V specify Volume names (separated by |)\n" " -? print this message\n\n"); exit(1); @@ -100,7 +101,7 @@ int main (int argc, char *argv[]) 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); @@ -155,6 +156,10 @@ int main (int argc, char *argv[]) forge_on = true; break; + case 'v': + verbose++; + break; + case 'V': /* Volume name */ VolumeName = optarg; break; @@ -203,8 +208,11 @@ int main (int argc, char *argv[]) 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); } @@ -245,9 +253,10 @@ static void do_extract(char *devname) /* * 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 */ @@ -455,10 +464,9 @@ bool dir_send_job_status(JCR *jcr) {return 1;} 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; } diff --git a/bacula/src/stored/block.c b/bacula/src/stored/block.c index 5a59b29152..915cf6ee65 100644 --- a/bacula/src/stored/block.c +++ b/bacula/src/stored/block.c @@ -320,14 +320,14 @@ static bool unser_block_header(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) * : 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; } @@ -346,7 +346,7 @@ bool write_block_to_device(DCR *dcr, DEV_BLOCK *block) 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; @@ -360,11 +360,11 @@ bool write_block_to_device(DCR *dcr, DEV_BLOCK *block) } } - 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); } } @@ -381,7 +381,7 @@ bail_out: * 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 */ @@ -389,6 +389,7 @@ bool write_block_to_dev(DCR *dcr, DEV_BLOCK *block) bool ok = true; DEVICE *dev = dcr->dev; JCR *jcr = dcr->jcr; + DEV_BLOCK *block = dcr->block; #ifdef NO_TAPE_WRITE_TEST empty_block(block); @@ -634,7 +635,8 @@ bool write_block_to_dev(DCR *dcr, DEV_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) { @@ -646,6 +648,7 @@ bool write_block_to_dev(DCR *dcr, DEV_BLOCK *block) } } free_block(lblock); + dcr->block = block; } } #endif @@ -661,7 +664,7 @@ bool write_block_to_dev(DCR *dcr, DEV_BLOCK *block) 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; @@ -690,13 +693,13 @@ bool write_block_to_dev(DCR *dcr, DEV_BLOCK *block) * 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; @@ -707,7 +710,7 @@ bool read_block_from_device(DCR *dcr, DEV_BLOCK *block, bool check_block_numbers * 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; @@ -715,6 +718,7 @@ bool read_block_from_dev(DCR *dcr, DEV_BLOCK *block, bool check_block_numbers) int retry; JCR *jcr = dcr->jcr; DEVICE *dev = dcr->dev; + DEV_BLOCK *block = dcr->block; if (dev_state(dev, ST_EOT)) { return false; @@ -853,7 +857,7 @@ reread: 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; diff --git a/bacula/src/stored/bls.c b/bacula/src/stored/bls.c index 145c86079d..df7e674867 100644 --- a/bacula/src/stored/bls.c +++ b/bacula/src/stored/bls.c @@ -39,7 +39,7 @@ static void do_jobs(char *infname); 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; @@ -201,9 +201,12 @@ int main (int argc, char *argv[]) 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); } @@ -256,26 +259,26 @@ static void do_blocks(char *infname) 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) { @@ -317,10 +320,10 @@ static void do_blocks(char *infname) /* * 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; @@ -346,7 +349,7 @@ static void do_ls(char *infname) /* * 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); @@ -433,10 +436,9 @@ bool dir_send_job_status(JCR *jcr) {return 1;} 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; } diff --git a/bacula/src/stored/bscan.c b/bacula/src/stored/bscan.c index 45f53f5332..6e415d177a 100644 --- a/bacula/src/stored/bscan.c +++ b/bacula/src/stored/bscan.c @@ -36,7 +36,7 @@ /* 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); @@ -250,11 +250,11 @@ int main (int argc, char *argv[]) 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); @@ -262,7 +262,8 @@ int main (int argc, char *argv[]) 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)) { @@ -288,12 +289,13 @@ int main (int argc, char *argv[]) * 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; } @@ -301,11 +303,11 @@ static bool bscan_mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block 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"), @@ -316,7 +318,7 @@ static bool bscan_mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block * 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; @@ -341,7 +343,6 @@ static void do_scan() /* 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); } @@ -350,11 +351,13 @@ static void do_scan() * 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 */ @@ -502,13 +505,11 @@ static bool record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) 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"), diff --git a/bacula/src/stored/btape.c b/bacula/src/stored/btape.c index 65c6303e27..06dc096814 100644 --- a/bacula/src/stored/btape.c +++ b/bacula/src/stored/btape.c @@ -72,9 +72,9 @@ static void qfillcmd(); 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(); @@ -253,8 +253,11 @@ int main(int margc, char *margv[]) 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); } @@ -320,8 +323,8 @@ static bool open_the_device() 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); @@ -370,10 +373,8 @@ static void readlabelcmd() { 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"); @@ -404,7 +405,6 @@ static void readlabelcmd() debug_level = 20; dump_volume_label(dev); debug_level = save_debug_level; - free_block(block); } @@ -629,7 +629,7 @@ static void rectestcmd() */ static int re_read_block_test() { - DEV_BLOCK *block; + DEV_BLOCK *block = dcr->block; DEV_RECORD *rec; int stat = 0; int len; @@ -646,7 +646,6 @@ static int re_read_block_test() "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; @@ -655,7 +654,7 @@ static int re_read_block_test() 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 { @@ -666,7 +665,7 @@ static int re_read_block_test() 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 { @@ -677,7 +676,7 @@ static int re_read_block_test() 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 { @@ -703,7 +702,7 @@ static int re_read_block_test() 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; } @@ -724,7 +723,6 @@ static int re_read_block_test() 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" @@ -774,7 +772,7 @@ static int write_read_test() 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; } @@ -790,7 +788,7 @@ static int write_read_test() 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; } @@ -808,7 +806,7 @@ static int write_read_test() } 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; @@ -882,7 +880,7 @@ static int position_test() 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; } @@ -898,7 +896,7 @@ static int position_test() 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; } @@ -958,7 +956,7 @@ static int position_test() 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; @@ -1095,7 +1093,7 @@ static int autochanger_test() 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, @@ -1118,7 +1116,7 @@ try_again: } 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); @@ -1141,7 +1139,7 @@ try_again: */ 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"); @@ -1457,13 +1455,11 @@ static void fsrcmd() */ 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; @@ -1476,7 +1472,7 @@ static void wrcmd() 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 { @@ -1486,8 +1482,6 @@ static void wrcmd() bail_out: sm_check(__FILE__, __LINE__, false); - free_record(rec); - free_block(block); sm_check(__FILE__, __LINE__, false); } @@ -1612,7 +1606,7 @@ static void scan_blocks() 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) { @@ -1698,7 +1692,7 @@ static void statcmd() static void fillcmd() { DEV_RECORD rec; - DEV_BLOCK *block; + DEV_BLOCK *block = dcr->block; char ec1[50]; int fd; uint32_t i; @@ -1764,7 +1758,7 @@ This may take a long time -- hours! ...\n\n"); /* * 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)); @@ -1881,12 +1875,12 @@ This may take a long time -- hours! ...\n\n"); } 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; } @@ -1979,13 +1973,12 @@ static void unfillcmd() 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 */ @@ -2041,7 +2034,7 @@ static void do_unfill() 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; } @@ -2092,7 +2085,7 @@ static void do_unfill() 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; } @@ -2108,7 +2101,7 @@ static void do_unfill() 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; } @@ -2117,14 +2110,13 @@ static void do_unfill() } 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; @@ -2190,7 +2182,7 @@ static int flush_block(DEV_BLOCK *block, int dump) /* 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) { @@ -2231,7 +2223,7 @@ static int flush_block(DEV_BLOCK *block, int dump) 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); @@ -2268,8 +2260,8 @@ static int flush_block(DEV_BLOCK *block, int dump) */ 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"); @@ -2282,8 +2274,6 @@ static void qfillcmd() } sm_check(__FILE__, __LINE__, false); - block = new_block(dev); - rec = new_record(); i = block->buf_len - 100; ASSERT (i > 0); @@ -2301,7 +2291,7 @@ static void qfillcmd() 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; } @@ -2316,10 +2306,6 @@ static void qfillcmd() bail_out: sm_check(__FILE__, __LINE__, false); - free_record(rec); - free_block(block); - sm_check(__FILE__, __LINE__, false); - } /* @@ -2327,7 +2313,7 @@ bail_out: */ static void rawfill_cmd() { - DEV_BLOCK *block; + DEV_BLOCK *block = dcr->block; int stat; int fd; uint32_t block_num = 0; @@ -2335,7 +2321,6 @@ static void rawfill_cmd() 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); @@ -2370,7 +2355,6 @@ static void rawfill_cmd() printf("Write failed at block %u. stat=%d ERR=%s\n", block_num, stat, strerror(my_errno)); weofcmd(); - free_block(block); } @@ -2379,14 +2363,13 @@ static void rawfill_cmd() */ 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); @@ -2404,7 +2387,7 @@ static void bfill_cmd() *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) { @@ -2420,7 +2403,6 @@ static void bfill_cmd() printf("\n"); printf("Write failed at block %u.\n", block_num); weofcmd(); - free_block(block); } @@ -2553,9 +2535,8 @@ bool dir_update_volume_info(DCR *dcr, bool relabel) 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; } @@ -2568,17 +2549,15 @@ bool dir_create_jobmedia_record(DCR *dcr) 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 */ @@ -2587,12 +2566,12 @@ bool dir_ask_sysop_to_mount_volume(DCR *dcr) } 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; @@ -2602,7 +2581,6 @@ bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr) { 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); @@ -2620,19 +2598,21 @@ bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr) 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; @@ -2647,7 +2627,7 @@ static bool my_mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) 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; } @@ -2659,7 +2639,7 @@ static bool my_mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) 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 */ @@ -2670,11 +2650,8 @@ static void set_volume_name(const char *VolName, int volnum) 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; } diff --git a/bacula/src/stored/butil.c b/bacula/src/stored/butil.c index ada7ddacc0..183e2ff019 100644 --- a/bacula/src/stored/butil.c +++ b/bacula/src/stored/butil.c @@ -2,6 +2,8 @@ * * 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 @@ -10,7 +12,7 @@ * 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 @@ -32,6 +34,11 @@ #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; @@ -62,64 +69,143 @@ char *rec_state_to_str(DEV_RECORD *rec) } #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; } @@ -130,7 +216,7 @@ DEVICE *setup_to_access_device(JCR *jcr, int read_access) * 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; @@ -148,7 +234,7 @@ DEVRES *find_device_res(char *device_name, int read_access) 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) { @@ -170,89 +256,6 @@ DEVRES *find_device_res(char *device_name, int read_access) } - -/* - * 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 */ @@ -264,7 +267,7 @@ void display_tape_error_status(JCR *jcr, DEVICE *dev) 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")); diff --git a/bacula/src/stored/dev.c b/bacula/src/stored/dev.c index 02bb385680..b81b745e52 100644 --- a/bacula/src/stored/dev.c +++ b/bacula/src/stored/dev.c @@ -103,11 +103,12 @@ init_dev(DEVICE *dev, DEVRES *device) /* 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; @@ -178,28 +179,33 @@ init_dev(DEVICE *dev, DEVRES *device) *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); } @@ -786,7 +792,7 @@ fsf_dev(DEVICE *dev, int num) } 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) { @@ -807,11 +813,12 @@ fsf_dev(DEVICE *dev, int num) 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; } @@ -846,12 +853,13 @@ fsf_dev(DEVICE *dev, int num) 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; } @@ -902,7 +910,7 @@ fsf_dev(DEVICE *dev, int num) } 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; @@ -931,13 +939,13 @@ bsf_dev(DEVICE *dev, int num) 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; } @@ -950,7 +958,7 @@ bsf_dev(DEVICE *dev, int num) 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); @@ -971,7 +979,7 @@ fsr_dev(DEVICE *dev, int num) 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; } @@ -980,7 +988,7 @@ fsr_dev(DEVICE *dev, int num) 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; } @@ -1009,7 +1017,7 @@ fsr_dev(DEVICE *dev, int num) } } 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); @@ -1029,7 +1037,7 @@ bsr_dev(DEVICE *dev, int num) 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; } @@ -1039,7 +1047,7 @@ bsr_dev(DEVICE *dev, int num) } 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; } @@ -1051,7 +1059,7 @@ bsr_dev(DEVICE *dev, int num) 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); @@ -1068,7 +1076,7 @@ reposition_dev(DEVICE *dev, uint32_t file, uint32_t block) { 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; } @@ -1078,7 +1086,7 @@ reposition_dev(DEVICE *dev, uint32_t file, uint32_t block) 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; } @@ -1105,7 +1113,7 @@ reposition_dev(DEVICE *dev, uint32_t file, uint32_t block) 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); @@ -1128,7 +1136,7 @@ weof_dev(DEVICE *dev, int 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; } @@ -1146,10 +1154,11 @@ weof_dev(DEVICE *dev, int num) 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; diff --git a/bacula/src/stored/dev.h b/bacula/src/stored/dev.h index 4efe4bd7d4..4516c626c9 100644 --- a/bacula/src/stored/dev.h +++ b/bacula/src/stored/dev.h @@ -2,6 +2,8 @@ * Definitions for using the Device functions in Bacula * Tape and File storage access * + * Kern Sibbald, MM + * * Version $Id$ * */ @@ -87,6 +89,7 @@ enum { #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)) @@ -225,7 +228,8 @@ public: * 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 */ @@ -248,6 +252,10 @@ struct DCR { 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 */ }; diff --git a/bacula/src/stored/device.c b/bacula/src/stored/device.c index 8b4f39be4d..7d5a9af81b 100644 --- a/bacula/src/stored/device.c +++ b/bacula/src/stored/device.c @@ -62,11 +62,11 @@ extern int debug_level; * 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. @@ -76,11 +76,12 @@ extern int debug_level; * 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]; @@ -102,7 +103,7 @@ bool fixup_device_block_write_error(DCR *dcr, DEV_BLOCK *block) /* 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; @@ -124,6 +125,7 @@ bool fixup_device_block_write_error(DCR *dcr, DEV_BLOCK *block) 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"), @@ -131,8 +133,9 @@ bool fixup_device_block_write_error(DCR *dcr, DEV_BLOCK *block) 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 */ @@ -140,7 +143,7 @@ bool fixup_device_block_write_error(DCR *dcr, DEV_BLOCK *block) 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 @@ -149,14 +152,16 @@ bool fixup_device_block_write_error(DCR *dcr, DEV_BLOCK *block) * 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 @@ -171,8 +176,7 @@ bool fixup_device_block_write_error(DCR *dcr, DEV_BLOCK *block) } 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)); } } @@ -184,7 +188,7 @@ bool fixup_device_block_write_error(DCR *dcr, DEV_BLOCK *block) /* 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); @@ -302,8 +306,9 @@ bool first_open_device(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; @@ -312,10 +317,10 @@ bool open_device(JCR *jcr, DEVICE *dev) } 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; diff --git a/bacula/src/stored/dircmd.c b/bacula/src/stored/dircmd.c index 7adddf5465..edd1182153 100644 --- a/bacula/src/stored/dircmd.c +++ b/bacula/src/stored/dircmd.c @@ -58,22 +58,22 @@ static char illegal_cmd[] = "3997 Illegal command for a Director with Monitor di /* 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, @@ -81,7 +81,7 @@ static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *oldname, struct s_cmds { const char *cmd; - int (*func)(JCR *jcr); + bool (*func)(JCR *jcr); int monitoraccess; /* specify if monitors have access to this function */ }; @@ -89,18 +89,19 @@ struct s_cmds { * 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 */ }; @@ -140,7 +141,7 @@ void *handle_connection_request(void *arg) * 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; } @@ -155,15 +156,14 @@ void *handle_connection_request(void *arg) } 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"); @@ -173,8 +173,7 @@ void *handle_connection_request(void *arg) */ 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"); @@ -203,10 +202,10 @@ void *handle_connection_request(void *arg) } 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); @@ -217,7 +216,7 @@ void *handle_connection_request(void *arg) * 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; @@ -236,7 +235,7 @@ static int setdebug_cmd(JCR *jcr) /* * Cancel a Job */ -static int cancel_cmd(JCR *cjcr) +static bool cancel_cmd(JCR *cjcr) { BSOCK *dir = cjcr->dir_bsock; int oldStatus; @@ -278,38 +277,38 @@ static int cancel_cmd(JCR *cjcr) * 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; } } @@ -344,20 +343,19 @@ static int do_label(JCR *jcr, int relabel) } 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; } /* @@ -371,22 +369,21 @@ static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *oldname, 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; @@ -394,7 +391,8 @@ static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *oldname, } /* 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: @@ -417,7 +415,7 @@ static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *oldname, 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)); @@ -427,11 +425,11 @@ static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *oldname, 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; } @@ -442,36 +440,34 @@ bail_out: * * 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; @@ -480,7 +476,7 @@ static DEVICE *find_device(JCR *jcr, char *dname) 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; @@ -504,19 +500,17 @@ static DEVICE *find_device(JCR *jcr, char *dname) /* * 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: @@ -536,13 +530,11 @@ static int mount_cmd(JCR *jcr) 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"); @@ -588,7 +580,7 @@ static int mount_cmd(JCR *jcr) 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); @@ -606,28 +598,26 @@ static int mount_cmd(JCR *jcr) } 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 */ @@ -677,16 +667,15 @@ static int unmount_cmd(JCR *jcr) } 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; } /* @@ -696,14 +685,13 @@ static int unmount_cmd(JCR *jcr) * 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 */ @@ -735,21 +723,20 @@ static int release_cmd(JCR *jcr) } 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; } @@ -757,15 +744,14 @@ static int release_cmd(JCR *jcr) /* * 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) { @@ -792,30 +778,28 @@ static int autochanger_cmd(JCR *jcr) } 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 */ @@ -841,15 +825,14 @@ static int readlabel_cmd(JCR *jcr) } 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; } /* @@ -860,22 +843,20 @@ static int readlabel_cmd(JCR *jcr) 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; @@ -883,7 +864,7 @@ static void read_volume_label(JCR *jcr, DEVICE *dev, int Slot) } 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); @@ -896,7 +877,6 @@ static void read_volume_label(JCR *jcr, DEVICE *dev, int Slot) } bail_out: - free_block(block); give_back_device_lock(dev, &hold); return; } diff --git a/bacula/src/stored/fd_cmds.c b/bacula/src/stored/fd_cmds.c index 39961dbfae..b6d801cd7e 100644 --- a/bacula/src/stored/fd_cmds.c +++ b/bacula/src/stored/fd_cmds.c @@ -1,6 +1,8 @@ /* * 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 @@ -43,22 +45,21 @@ static char ferrmsg[] = "3900 Invalid command\n"; 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); }; /* @@ -105,7 +106,8 @@ static char Job_end[] = */ 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]; @@ -119,7 +121,7 @@ void run_job(JCR *jcr) 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 */ @@ -131,13 +133,13 @@ void run_job(JCR *jcr) continue; /* ignore signals and zero length msgs */ } Dmsg1(110, "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; } @@ -164,7 +166,7 @@ void run_job(JCR *jcr) * 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; @@ -173,27 +175,25 @@ static int append_data_cmd(JCR *jcr) Dmsg1(110, "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, "storemsg); 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); @@ -204,14 +204,14 @@ static int append_end_session(JCR *jcr) * 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)); @@ -221,7 +221,7 @@ static int append_open_session(JCR *jcr) bnet_fsend(fd, OK_open, jcr->VolSessionId); Dmsg1(110, ">filed: %s", fd->msg); - return 1; + return true; } /* @@ -229,14 +229,14 @@ static int append_open_session(JCR *jcr) * 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, "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); @@ -246,8 +246,8 @@ static int append_close_session(JCR *jcr) Dmsg1(110, "Append close session: %s\n", dev_name(jcr->device->dev)); - jcr->session_opened = FALSE; - return 1; + jcr->session_opened = false; + return true; } /* @@ -256,7 +256,7 @@ static int append_close_session(JCR *jcr) * 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; @@ -266,7 +266,7 @@ static int read_data_cmd(JCR *jcr) return do_read_data(jcr); } else { bnet_fsend(fd, NOT_opened); - return 0; + return false; } } @@ -276,25 +276,25 @@ static int read_data_cmd(JCR *jcr) * 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, @@ -310,15 +310,15 @@ static int read_open_session(JCR *jcr) 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); @@ -347,18 +347,17 @@ static int bootstrap_cmd(JCR *jcr) 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); } @@ -366,14 +365,14 @@ bail_out: * 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); @@ -382,5 +381,5 @@ static int read_close_session(JCR *jcr) bnet_sig(fd, BNET_EOD); /* send EOD to File daemon */ jcr->session_opened = FALSE; - return 1; + return true; } diff --git a/bacula/src/stored/job.c b/bacula/src/stored/job.c index 7eea25673b..e200cc9d2e 100644 --- a/bacula/src/stored/job.c +++ b/bacula/src/stored/job.c @@ -1,6 +1,8 @@ /* * Job control and execution for Storage Daemon * + * Kern Sibbald, MM + * * Version $Id$ * */ @@ -34,13 +36,13 @@ extern uint32_t VolSessionTime; 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"; @@ -49,8 +51,6 @@ static char NO_device[] = "3914 Device \"%s\" not in SD Device resources.\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: @@ -61,12 +61,12 @@ static char BAD_job[] = "3915 Bad Job command: %s\n"; * - 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; @@ -76,62 +76,47 @@ int job_cmd(JCR *jcr) /* * 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; @@ -150,7 +135,17 @@ int job_cmd(JCR *jcr) 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 */ @@ -181,7 +176,7 @@ int job_cmd(JCR *jcr) Dmsg1(100, "Running job %s\n", jcr->Job); run_job(jcr); /* Run the job */ } - return 0; + return false; } /* @@ -205,8 +200,10 @@ void handle_filed_connection(BSOCK *fd, char *job_name) 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; } /* @@ -239,64 +236,59 @@ void handle_filed_connection(BSOCK *fd, char *job_name) * 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); } @@ -304,11 +296,7 @@ static int use_device_cmd(JCR *jcr) 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 */ } /* @@ -321,18 +309,6 @@ void stored_free_jcr(JCR *jcr) 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); } diff --git a/bacula/src/stored/label.c b/bacula/src/stored/label.c index c4a431b0c8..aca6f901e6 100644 --- a/bacula/src/stored/label.c +++ b/bacula/src/stored/label.c @@ -39,9 +39,9 @@ extern int debug_level; /* * 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 * @@ -56,13 +56,14 @@ extern int debug_level; * 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); @@ -79,10 +80,10 @@ int read_dev_volume_label(DCR *dcr, DEV_BLOCK *block) 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 */ @@ -90,25 +91,31 @@ int read_dev_volume_label(DCR *dcr, DEV_BLOCK *block) 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; } @@ -117,11 +124,11 @@ int read_dev_volume_label(DCR *dcr, DEV_BLOCK *block) 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); @@ -136,7 +143,8 @@ int read_dev_volume_label(DCR *dcr, DEV_BLOCK *block) 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 @@ -145,7 +153,8 @@ int read_dev_volume_label(DCR *dcr, DEV_BLOCK *block) 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 */ @@ -155,6 +164,7 @@ int read_dev_volume_label(DCR *dcr, DEV_BLOCK *block) 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 @@ -162,7 +172,7 @@ int read_dev_volume_label(DCR *dcr, DEV_BLOCK *block) 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); @@ -170,7 +180,7 @@ int read_dev_volume_label(DCR *dcr, DEV_BLOCK *block) 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 @@ -243,19 +253,20 @@ bool unser_volume_label(DEVICE *dev, DEV_RECORD *rec) * 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); @@ -380,13 +391,12 @@ 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) { - 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)) { @@ -397,22 +407,19 @@ bool write_new_volume_label_to_dev(DCR *dcr, const char *VolName, const char *Po } } - 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; @@ -428,8 +435,6 @@ bool write_new_volume_label_to_dev(DCR *dcr, const char *VolName, const char *Po } bail_out: - free_block(block); - free_pool_memory(rec.data); return ok; } @@ -458,8 +463,8 @@ void create_session_label(DCR *dcr, DEV_RECORD *rec, int label) 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); @@ -491,11 +496,12 @@ void create_session_label(DCR *dcr, DEV_RECORD *rec, int label) * 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); @@ -534,8 +540,9 @@ bool write_session_label(DCR *dcr, DEV_BLOCK *block, int label) */ 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); diff --git a/bacula/src/stored/mount.c b/bacula/src/stored/mount.c index f03f9e6892..efb0ce602f 100644 --- a/bacula/src/stored/mount.c +++ b/bacula/src/stored/mount.c @@ -30,7 +30,7 @@ #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); /* @@ -45,13 +45,14 @@ static bool rewrite_volume_label(DCR *dcr, DEV_BLOCK *block, 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"); @@ -66,7 +67,7 @@ mount_next_vol: /* 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)); @@ -80,13 +81,13 @@ mount_next_vol: 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)) { @@ -100,7 +101,7 @@ mount_next_vol: 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 @@ -122,7 +123,7 @@ mount_next_vol: ask = false; } else { autochanger = false; - jcr->VolCatInfo.Slot = 0; + dcr->VolCatInfo.Slot = 0; } Dmsg1(100, "autoload_dev returns %d\n", autochanger); /* @@ -148,14 +149,14 @@ mount_next_vol: 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 { @@ -173,25 +174,25 @@ read_volume: */ 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: @@ -200,17 +201,17 @@ read_volume: /* 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; } /* @@ -219,9 +220,9 @@ read_volume: * 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" @@ -230,12 +231,12 @@ read_volume: 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 */ /* @@ -250,33 +251,33 @@ read_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. */ @@ -306,7 +307,7 @@ read_volume: * 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 { @@ -317,11 +318,11 @@ read_volume: */ 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 */ @@ -332,12 +333,12 @@ read_volume: */ 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; } } @@ -357,14 +358,14 @@ The number of files mismatch! Volume=%u Catalog=%u\n"), * 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; } /* @@ -384,7 +385,7 @@ static bool rewrite_volume_label(DCR *dcr, DEV_BLOCK *block, bool recycle) } } /* 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; @@ -411,10 +412,10 @@ static bool rewrite_volume_label(DCR *dcr, DEV_BLOCK *block, bool recycle) 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 @@ -427,21 +428,24 @@ static bool rewrite_volume_label(DCR *dcr, DEV_BLOCK *block, bool recycle) /* * 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) @@ -451,7 +455,7 @@ bool mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) 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 */ @@ -464,9 +468,11 @@ bool mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) * 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"); } /* @@ -475,11 +481,11 @@ void release_volume(JCR *jcr, DEVICE *dev) 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))) { diff --git a/bacula/src/stored/parse_bsr.c b/bacula/src/stored/parse_bsr.c index 10c05d3d9d..4ff019b30c 100755 --- a/bacula/src/stored/parse_bsr.c +++ b/bacula/src/stored/parse_bsr.c @@ -865,7 +865,7 @@ void create_vol_list(JCR *jcr) } } 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 */ diff --git a/bacula/src/stored/protos.h b/bacula/src/stored/protos.h index 6898968a29..4956dfa7ec 100644 --- a/bacula/src/stored/protos.h +++ b/bacula/src/stored/protos.h @@ -52,6 +52,12 @@ bool dir_create_jobmedia_record(DCR *dcr); 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); @@ -59,22 +65,21 @@ DEV_BLOCK *dup_block(DEV_BLOCK *eblock); 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 */ @@ -119,9 +124,9 @@ uint32_t dev_file(DEVICE *dev); 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); @@ -141,6 +146,7 @@ void *handle_connection_request(void *arg); /* From fd_cmds.c */ void run_job(JCR *jcr); +bool bootstrap_cmd(JCR *jcr); /* From job.c */ void stored_free_jcr(JCR *jcr); @@ -148,12 +154,12 @@ void connection_from_filed(void *arg); 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); @@ -168,17 +174,10 @@ BSR *find_next_bsr(BSR *root_bsr, DEVICE *dev); 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); @@ -192,16 +191,17 @@ void create_vol_list(JCR *jcr); /* 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); @@ -211,5 +211,5 @@ bool are_attributes_spooled (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); diff --git a/bacula/src/stored/read.c b/bacula/src/stored/read.c index bdf870052c..937ae4ba2d 100644 --- a/bacula/src/stored/read.c +++ b/bacula/src/stored/read.c @@ -29,7 +29,7 @@ #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 */ @@ -66,8 +66,6 @@ bool do_read_data(JCR *jcr) 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 */ @@ -97,8 +95,9 @@ bool do_read_data(JCR *jcr) * 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; diff --git a/bacula/src/stored/read_record.c b/bacula/src/stored/read_record.c index 5ecfdf7c4e..88f63f729b 100644 --- a/bacula/src/stored/read_record.c +++ b/bacula/src/stored/read_record.c @@ -42,12 +42,12 @@ static char *rec_state_to_str(DEV_RECORD *rec); #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; @@ -55,7 +55,6 @@ bool read_records(DCR *dcr, 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); @@ -64,13 +63,13 @@ bool read_records(DCR *dcr, 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; /* @@ -80,7 +79,7 @@ bool read_records(DCR *dcr, */ trec->FileIndex = EOT_LABEL; trec->File = dev->file; - ok = record_cb(jcr, dev, block, trec); + ok = record_cb(dcr, trec); free_record(trec); break; } @@ -89,10 +88,10 @@ bool read_records(DCR *dcr, * 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 */ @@ -101,10 +100,10 @@ bool read_records(DCR *dcr, } 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); @@ -190,7 +189,7 @@ bool read_records(DCR *dcr, /* 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); @@ -226,7 +225,7 @@ bool read_records(DCR *dcr, 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); @@ -250,7 +249,6 @@ bool read_records(DCR *dcr, } delete recs; print_block_read_errors(jcr, block); - free_block(block); return ok; } diff --git a/bacula/src/stored/record.c b/bacula/src/stored/record.c index c0c564c0be..d3bb44eab6 100644 --- a/bacula/src/stored/record.c +++ b/bacula/src/stored/record.c @@ -155,6 +155,15 @@ DEV_RECORD *new_record(void) 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 * @@ -174,8 +183,8 @@ void free_record(DEV_RECORD *rec) /* * 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. * @@ -185,7 +194,7 @@ void free_record(DEV_RECORD *rec) * 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; @@ -234,7 +243,7 @@ rem=%d remainder=%d\n", } } else { rec->remainder = rec->data_len + WRITE_RECHDR_LENGTH; - return 0; + return false; } } else { /* @@ -285,7 +294,7 @@ rem=%d remainder=%d\n", } } if (remlen == 0) { - return 0; /* partial transfer */ + return false; /* partial transfer */ } /* @@ -324,21 +333,21 @@ rem=%d remainder=%d\n", 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; @@ -348,27 +357,27 @@ int can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec) 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; @@ -427,7 +436,8 @@ int read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec) 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 @@ -441,7 +451,7 @@ int read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec) 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 */ @@ -481,7 +491,7 @@ int read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec) #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 */ @@ -517,5 +527,5 @@ int read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec) 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 */ } diff --git a/bacula/src/stored/record.h b/bacula/src/stored/record.h index dd3047d478..2267d8a473 100644 --- a/bacula/src/stored/record.h +++ b/bacula/src/stored/record.h @@ -2,11 +2,13 @@ * 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 diff --git a/bacula/src/stored/spool.c b/bacula/src/stored/spool.c index 5af270180b..7a41338b77 100644 --- a/bacula/src/stored/spool.c +++ b/bacula/src/stored/spool.c @@ -33,11 +33,11 @@ static void make_unique_data_spool_filename(JCR *jcr, POOLMEM **name); 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 */ @@ -214,7 +214,7 @@ static bool despool_data(DCR *dcr, bool commit) 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; @@ -223,7 +223,8 @@ static bool despool_data(DCR *dcr, bool commit) 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 */ @@ -233,16 +234,17 @@ static bool despool_data(DCR *dcr, bool commit) 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) { @@ -283,11 +285,12 @@ static bool despool_data(DCR *dcr, bool commit) * 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); @@ -334,10 +337,11 @@ static int read_block_from_spool_file(DCR *dcr, DEV_BLOCK *block) * 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? */ @@ -384,10 +388,10 @@ bool write_block_to_spool_file(DCR *dcr, DEV_BLOCK *block) } - 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; } @@ -396,10 +400,11 @@ bool write_block_to_spool_file(DCR *dcr, DEV_BLOCK *block) 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; @@ -435,9 +440,10 @@ static bool write_spool_header(DCR *dcr, DEV_BLOCK *block) 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++) { @@ -464,7 +470,7 @@ static bool write_spool_data(DCR *dcr, DEV_BLOCK *block) 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 */ @@ -538,7 +544,7 @@ bool commit_attribute_spool(JCR *jcr) } 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); diff --git a/bacula/src/stored/status.c b/bacula/src/stored/status.c index 14f99b2639..74398e7a42 100644 --- a/bacula/src/stored/status.c +++ b/bacula/src/stored/status.c @@ -41,7 +41,7 @@ extern int num_jobs_run; /* 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"; @@ -58,7 +58,7 @@ static const char *level_to_str(int level); /* * Status command from Director */ -int status_cmd(JCR *jcr) +bool status_cmd(JCR *jcr) { DEVRES *device; DEVICE *dev; @@ -153,12 +153,13 @@ int status_cmd(JCR *jcr) 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: @@ -170,7 +171,7 @@ static void send_blocked_status(JCR *jcr, DEVICE *dev) 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")); } @@ -251,7 +252,7 @@ static void list_running_jobs(BSOCK *user) 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) { @@ -422,53 +423,47 @@ static void sendit(const char *msg, int len, void *arg) /* * .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; } diff --git a/bacula/src/stored/stored.c b/bacula/src/stored/stored.c index e2133ee948..6f55cc4209 100644 --- a/bacula/src/stored/stored.c +++ b/bacula/src/stored/stored.c @@ -335,7 +335,7 @@ void *device_allocation(void *arg) } 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: diff --git a/bacula/src/stored/stored.h b/bacula/src/stored/stored.h index afe8a2075e..2933237cc0 100644 --- a/bacula/src/stored/stored.h +++ b/bacula/src/stored/stored.h @@ -51,6 +51,11 @@ #else #define uLongf uint32_t #endif +#ifdef HAVE_FNMATCH +#include +#else +#include "lib/fnmatch.h" +#endif extern STORES *me; /* "Global" daemon resource */ extern bool forge_on; /* proceed inspite of I/O errors */ diff --git a/bacula/src/stored/stored_conf.c b/bacula/src/stored/stored_conf.c index 16a370405d..8a8de08288 100644 --- a/bacula/src/stored/stored_conf.c +++ b/bacula/src/stored/stored_conf.c @@ -101,6 +101,7 @@ static RES_ITEM dev_items[] = { {"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}, diff --git a/bacula/src/stored/stored_conf.h b/bacula/src/stored/stored_conf.h index 457dce7335..2c4bc74bc7 100644 --- a/bacula/src/stored/stored_conf.h +++ b/bacula/src/stored/stored_conf.h @@ -29,7 +29,7 @@ enum { R_DEVICE, R_MSGS, R_FIRST = R_DIRECTOR, - R_LAST = R_MSGS /* keep this updated */ + R_LAST = R_MSGS /* keep this updated */ }; enum { @@ -43,7 +43,7 @@ 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 */ @@ -54,48 +54,48 @@ struct DIRRES { /* 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 { @@ -103,5 +103,5 @@ union URES { STORES res_store; DEVRES res_dev; MSGS res_msgs; - RES hdr; + RES hdr; }; diff --git a/bacula/src/tools/dbcheck.c b/bacula/src/tools/dbcheck.c index 0553ee4a2c..3dba7d8f5f 100644 --- a/bacula/src/tools/dbcheck.c +++ b/bacula/src/tools/dbcheck.c @@ -228,7 +228,7 @@ int main (int argc, char *argv[]) } /* 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; diff --git a/bacula/src/version.h b/bacula/src/version.h index c4c5ae0f1e..702c69730f 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -1,8 +1,8 @@ /* */ #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 @@ -10,6 +10,7 @@ #define TRACEBACK 1 #define SMCHECK #define TRACE_FILE 1 +#define DEVELOPER 1 /* Debug flags not normally turned on */