]> git.sur5r.net Git - bacula/bacula/commitdiff
Massive SD calling sequence reorganization
authorKern Sibbald <kern@sibbald.com>
Sun, 19 Sep 2004 18:56:29 +0000 (18:56 +0000)
committerKern Sibbald <kern@sibbald.com>
Sun, 19 Sep 2004 18:56:29 +0000 (18:56 +0000)
git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@1597 91ce42f0-d328-0410-95d8-f526ca767f89

75 files changed:
bacula/ChangeLog
bacula/ReleaseNotes
bacula/kernstodo
bacula/src/cats/bdb.c
bacula/src/cats/mysql.c
bacula/src/cats/postgresql.c
bacula/src/cats/protos.h
bacula/src/cats/sqlite.c
bacula/src/dird/Makefile.in
bacula/src/dird/authenticate.c
bacula/src/dird/backup.c
bacula/src/dird/dird.c
bacula/src/dird/dird_conf.c
bacula/src/dird/dird_conf.h
bacula/src/dird/fd_cmds.c
bacula/src/dird/job.c
bacula/src/dird/mac.c [new file with mode: 0644]
bacula/src/dird/msgchan.c
bacula/src/dird/next_vol.c
bacula/src/dird/protos.h
bacula/src/dird/restore.c
bacula/src/dird/ua_cmds.c
bacula/src/dird/ua_dotcmds.c
bacula/src/dird/ua_output.c
bacula/src/dird/ua_run.c
bacula/src/dird/ua_server.c
bacula/src/dird/ua_status.c
bacula/src/dird/verify.c
bacula/src/findlib/makepath.c
bacula/src/findlib/match.c
bacula/src/jcr.h
bacula/src/lib/attr.c
bacula/src/lib/berrno.h
bacula/src/lib/bsys.c
bacula/src/lib/daemon.c
bacula/src/lib/dlist.h
bacula/src/lib/mem_pool.c
bacula/src/lib/mem_pool.h
bacula/src/lib/parse_conf.c
bacula/src/lib/parse_conf.h
bacula/src/lib/protos.h
bacula/src/lib/util.c
bacula/src/stored/acquire.c
bacula/src/stored/append.c
bacula/src/stored/askdir.c
bacula/src/stored/autochanger.c
bacula/src/stored/bcopy.c
bacula/src/stored/bextract.c
bacula/src/stored/block.c
bacula/src/stored/bls.c
bacula/src/stored/bscan.c
bacula/src/stored/btape.c
bacula/src/stored/butil.c
bacula/src/stored/dev.c
bacula/src/stored/dev.h
bacula/src/stored/device.c
bacula/src/stored/dircmd.c
bacula/src/stored/fd_cmds.c
bacula/src/stored/job.c
bacula/src/stored/label.c
bacula/src/stored/mount.c
bacula/src/stored/parse_bsr.c
bacula/src/stored/protos.h
bacula/src/stored/read.c
bacula/src/stored/read_record.c
bacula/src/stored/record.c
bacula/src/stored/record.h
bacula/src/stored/spool.c
bacula/src/stored/status.c
bacula/src/stored/stored.c
bacula/src/stored/stored.h
bacula/src/stored/stored_conf.c
bacula/src/stored/stored_conf.h
bacula/src/tools/dbcheck.c
bacula/src/version.h

index 9f7b7306ff14c4e14bd8c86e17b4998e2800e1c5..967eaeb087dd64baa37c845911c3feaa654b2101 100644 (file)
@@ -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
index b840899197948bb349faf7be10550eb1b69e6910..d2c531623e0dbc1fea404e32f8172c434ecd940d 100644 (file)
@@ -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).
index 89f2f18b7ce4bd335b980f115b0dd5a295c6af80..963aadbf6cacceab4e3f9e6c7f5c4e7f1c327d69 100644 (file)
@@ -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.
 
index df980da16045c81ea04159ee944fd327a7e7bf30..143d32d995c38792f7fbabb39349d97030a64a32 100644 (file)
@@ -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;
 }
index d327927c442bb6c81202fca03a8058981297946b..1fd12e0157aebc0fc773a8cc9f195e3874138256 100644 (file)
@@ -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");
index a8779e8b6606749040092e43f26d0d4a00710456..d6b1a6567b52d15cc1f272849b2091b9cc83534a 100644 (file)
@@ -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);
index c5c41879ebe716b2ce62c66c4660d711d57af01f..234ebe93d85f395c14589202e1d0ebc1c25dab88 100644 (file)
@@ -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);
 
index c98b571242d547ad49277bcc7f6961a0f9cfce2b..1df4ae151cfaeb8ebc1317f150d0994599ce3f2b 100644 (file)
@@ -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");
index 1ee51c39ba6502fdd760d5701adf009f8b364635..704d1c2f777b638a9b5b76bbb5dfd80319dd9019 100644 (file)
@@ -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 \
index ab680fdcd305239070cec4aa1a96487ef2c0591f..dd6787c9ba4c7ffdab88629e398f0669058dc846 100644 (file)
@@ -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"));
index 11ddbab5acdcc6fe0e1f7ef5a382640ad42120ae..9f7d07c7a90dc9bd8842c92638546229742dc19c 100644 (file)
@@ -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;
    }
index be64a25307f1c10adee67b3c955b30a76ef0f131..6e36523d4e24cfa5eeaaf990d0dbd1f095580a8e 100644 (file)
@@ -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);
index 6eef624496846afffc9d604be2c68959ec96dee9..a2f4a75e9d5f51d695e227b56ad451a93c42bfda 100644 (file)
@@ -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; i<res->res_fs.num_includes; i++) {
-        INCEXE *incexe = res->res_fs.include_items[i];
-        for (j=0; j<incexe->num_opts; j++) {
-           FOPTS *fo = incexe->opts_list[j];
+         INCEXE *incexe = res->res_fs.include_items[i];
+         for (j=0; j<incexe->num_opts; j++) {
+            FOPTS *fo = incexe->opts_list[j];
             sendit(sock, "      O %s\n", fo->opts);
-           for (k=0; k<fo->regex.size(); k++) {
+            for (k=0; k<fo->regex.size(); k++) {
                sendit(sock, "      R %s\n", fo->regex.get(k));
-           }
-           for (k=0; k<fo->wild.size(); k++) {
+            }
+            for (k=0; k<fo->wild.size(); k++) {
                sendit(sock, "      W %s\n", fo->wild.get(k));
-           }
-           for (k=0; k<fo->base.size(); k++) {
+            }
+            for (k=0; k<fo->base.size(); k++) {
                sendit(sock, "      B %s\n", fo->base.get(k));
-           }
-           if (fo->reader) {
+            }
+            if (fo->reader) {
                sendit(sock, "      D %s\n", fo->reader);
-           }
-           if (fo->writer) {
+            }
+            if (fo->writer) {
                sendit(sock, "      T %s\n", fo->writer);
-           }
+            }
             sendit(sock, "      N\n");
-        }
-        for (j=0; j<incexe->name_list.size(); j++) {
+         }
+         for (j=0; j<incexe->name_list.size(); j++) {
             sendit(sock, "      I %s\n", incexe->name_list.get(j));
-        }
-        if (incexe->name_list.size()) {
+         }
+         if (incexe->name_list.size()) {
             sendit(sock, "      N\n");
-        }
+         }
       }
-        
+         
       for (i=0; i<res->res_fs.num_excludes; i++) {
-        INCEXE *incexe = res->res_fs.exclude_items[i];
-        for (j=0; j<incexe->name_list.size(); j++) {
+         INCEXE *incexe = res->res_fs.exclude_items[i];
+         for (j=0; j<incexe->name_list.size(); j++) {
             sendit(sock, "      E %s\n", incexe->name_list.get(j));
-        }
-        if (incexe->name_list.size()) {
+         }
+         if (incexe->name_list.size()) {
             sendit(sock, "      N\n");
-        }
+         }
       }
       break;
    }
    case R_SCHEDULE:
       if (res->res_sch.run) {
-        int i;
-        RUN *run = res->res_sch.run;
-        char buf[1000], num[30];
+         int i;
+         RUN *run = res->res_sch.run;
+         char buf[1000], num[30];
          sendit(sock, "Schedule: name=%s\n", res->res_sch.hdr.name);
-        if (!run) {
-           break;
-        }
+         if (!run) {
+            break;
+         }
 next_run:
          sendit(sock, "  --> Run Level=%s\n", level_to_str(run->level));
          bstrncpy(buf, "      hour=", sizeof(buf));
-        for (i=0; i<24; i++) {
-           if (bit_is_set(i, run->hour)) {
+         for (i=0; i<24; i++) {
+            if (bit_is_set(i, run->hour)) {
                bsnprintf(num, sizeof(num), "%d ", i);
-              bstrncat(buf, num, sizeof(buf));
-           }
-        }
+               bstrncat(buf, num, sizeof(buf));
+            }
+         }
          bstrncat(buf, "\n", sizeof(buf));
-        sendit(sock, buf);
+         sendit(sock, buf);
          bstrncpy(buf, "      mday=", sizeof(buf));
-        for (i=0; i<31; i++) {
-           if (bit_is_set(i, run->mday)) {
+         for (i=0; i<31; i++) {
+            if (bit_is_set(i, run->mday)) {
                bsnprintf(num, sizeof(num), "%d ", i);
-              bstrncat(buf, num, sizeof(buf));
-           }
-        }
+               bstrncat(buf, num, sizeof(buf));
+            }
+         }
          bstrncat(buf, "\n", sizeof(buf));
-        sendit(sock, buf);
+         sendit(sock, buf);
          bstrncpy(buf, "      month=", sizeof(buf));
-        for (i=0; i<12; i++) {
-           if (bit_is_set(i, run->month)) {
+         for (i=0; i<12; i++) {
+            if (bit_is_set(i, run->month)) {
                bsnprintf(num, sizeof(num), "%d ", i);
-              bstrncat(buf, num, sizeof(buf));
-           }
-        }
+               bstrncat(buf, num, sizeof(buf));
+            }
+         }
          bstrncat(buf, "\n", sizeof(buf));
-        sendit(sock, buf);
+         sendit(sock, buf);
          bstrncpy(buf, "      wday=", sizeof(buf));
-        for (i=0; i<7; i++) {
-           if (bit_is_set(i, run->wday)) {
+         for (i=0; i<7; i++) {
+            if (bit_is_set(i, run->wday)) {
                bsnprintf(num, sizeof(num), "%d ", i);
-              bstrncat(buf, num, sizeof(buf));
-           }
-        }
+               bstrncat(buf, num, sizeof(buf));
+            }
+         }
          bstrncat(buf, "\n", sizeof(buf));
-        sendit(sock, buf);
+         sendit(sock, buf);
          bstrncpy(buf, "      wom=", sizeof(buf));
-        for (i=0; i<5; i++) {
-           if (bit_is_set(i, run->wom)) {
+         for (i=0; i<5; i++) {
+            if (bit_is_set(i, run->wom)) {
                bsnprintf(num, sizeof(num), "%d ", i);
-              bstrncat(buf, num, sizeof(buf));
-           }
-        }
+               bstrncat(buf, num, sizeof(buf));
+            }
+         }
          bstrncat(buf, "\n", sizeof(buf));
-        sendit(sock, buf);
+         sendit(sock, buf);
          bstrncpy(buf, "      woy=", sizeof(buf));
-        for (i=0; i<54; i++) {
-           if (bit_is_set(i, run->woy)) {
+         for (i=0; i<54; i++) {
+            if (bit_is_set(i, run->woy)) {
                bsnprintf(num, sizeof(num), "%d ", i);
-              bstrncat(buf, num, sizeof(buf));
-           }
-        }
+               bstrncat(buf, num, sizeof(buf));
+            }
+         }
          bstrncat(buf, "\n", sizeof(buf));
-        sendit(sock, buf);
+         sendit(sock, buf);
          sendit(sock, "      mins=%d\n", run->minute);
-        if (run->pool) {
+         if (run->pool) {
             sendit(sock, "     --> ");
-           dump_resource(-R_POOL, (RES *)run->pool, sendit, sock);
-        }
-        if (run->storage) {
+            dump_resource(-R_POOL, (RES *)run->pool, sendit, sock);
+         }
+         if (run->storage) {
             sendit(sock, "     --> ");
-           dump_resource(-R_STORAGE, (RES *)run->storage, sendit, sock);
-        }
-        if (run->msgs) {
+            dump_resource(-R_STORAGE, (RES *)run->storage, sendit, sock);
+         }
+         if (run->msgs) {
             sendit(sock, "     --> ");
-           dump_resource(-R_MSGS, (RES *)run->msgs, sendit, sock);
-        }
-        /* If another Run record is chained in, go print it */
-        if (run->next) {
-           run = run->next;
-           goto next_run;
-        }
+            dump_resource(-R_MSGS, (RES *)run->msgs, sendit, sock);
+         }
+         /* If another Run record is chained in, go print it */
+         if (run->next) {
+            run = run->next;
+            goto next_run;
+         }
       } else {
          sendit(sock, "Schedule: name=%s\n", res->res_sch.hdr.name);
       }
       break;
    case R_POOL:
       sendit(sock, "Pool: name=%s PoolType=%s\n", res->res_pool.hdr.name,
-             res->res_pool.pool_type);
+              res->res_pool.pool_type);
       sendit(sock, "      use_cat=%d use_once=%d acpt_any=%d cat_files=%d\n",
-             res->res_pool.use_catalog, res->res_pool.use_volume_once,
-             res->res_pool.accept_any_volume, res->res_pool.catalog_files);
+              res->res_pool.use_catalog, res->res_pool.use_volume_once,
+              res->res_pool.accept_any_volume, res->res_pool.catalog_files);
       sendit(sock, "      max_vols=%d auto_prune=%d VolRetention=%s\n",
-             res->res_pool.max_volumes, res->res_pool.AutoPrune,
-             edit_utime(res->res_pool.VolRetention, ed1, sizeof(ed1)));
+              res->res_pool.max_volumes, res->res_pool.AutoPrune,
+              edit_utime(res->res_pool.VolRetention, ed1, sizeof(ed1)));
       sendit(sock, "      VolUse=%s recycle=%d LabelFormat=%s\n", 
-             edit_utime(res->res_pool.VolUseDuration, ed1, sizeof(ed1)),
-             res->res_pool.Recycle,
-             NPRT(res->res_pool.label_format));
+              edit_utime(res->res_pool.VolUseDuration, ed1, sizeof(ed1)),
+              res->res_pool.Recycle,
+              NPRT(res->res_pool.label_format));
       sendit(sock, "      CleaningPrefix=%s\n",
-             NPRT(res->res_pool.cleaning_prefix));
+              NPRT(res->res_pool.cleaning_prefix));
       sendit(sock, "      recyleOldest=%d MaxVolJobs=%d MaxVolFiles=%d\n",
-             res->res_pool.purge_oldest_volume, 
-             res->res_pool.MaxVolJobs, res->res_pool.MaxVolFiles);
+              res->res_pool.purge_oldest_volume, 
+              res->res_pool.MaxVolJobs, res->res_pool.MaxVolFiles);
       break;
    case R_MSGS:
       sendit(sock, "Messages: name=%s\n", res->res_msgs.hdr.name);
@@ -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; i<Num_ACL; i++) {
-        if (res->res_con.ACL_lists[i]) {
-           delete res->res_con.ACL_lists[i];
-           res->res_con.ACL_lists[i] = NULL;
-        }
+         if (res->res_con.ACL_lists[i]) {
+            delete res->res_con.ACL_lists[i];
+            res->res_con.ACL_lists[i] = NULL;
+         }
       }
       break;
    case R_CLIENT:
       if (res->res_client.address) {
-        free(res->res_client.address);
+         free(res->res_client.address);
       }
       if (res->res_client.password) {
-        free(res->res_client.password);
+         free(res->res_client.password);
       }
       break;
    case R_STORAGE:
       if (res->res_store.address) {
-        free(res->res_store.address);
+         free(res->res_store.address);
       }
       if (res->res_store.password) {
-        free(res->res_store.password);
+         free(res->res_store.password);
       }
       if (res->res_store.media_type) {
-        free(res->res_store.media_type);
+         free(res->res_store.media_type);
       }
       if (res->res_store.dev_name) {
-        free(res->res_store.dev_name);
+         free(res->res_store.dev_name);
       }
       break;
    case R_CATALOG:
       if (res->res_cat.db_address) {
-        free(res->res_cat.db_address);
+         free(res->res_cat.db_address);
       }
       if (res->res_cat.db_socket) {
-        free(res->res_cat.db_socket);
+         free(res->res_cat.db_socket);
       }
       if (res->res_cat.db_user) {
-        free(res->res_cat.db_user);
+         free(res->res_cat.db_user);
       }
       if (res->res_cat.db_name) {
-        free(res->res_cat.db_name);
+         free(res->res_cat.db_name);
       }
       if (res->res_cat.db_password) {
-        free(res->res_cat.db_password);
+         free(res->res_cat.db_password);
       }
       break;
    case R_FILESET:
       if ((num=res->res_fs.num_includes)) {
-        while (--num >= 0) {   
-           free_incexe(res->res_fs.include_items[num]);
-        }
-        free(res->res_fs.include_items);
+         while (--num >= 0) {   
+            free_incexe(res->res_fs.include_items[num]);
+         }
+         free(res->res_fs.include_items);
       }
       res->res_fs.num_includes = 0;
       if ((num=res->res_fs.num_excludes)) {
-        while (--num >= 0) {   
-           free_incexe(res->res_fs.exclude_items[num]);
-        }
-        free(res->res_fs.exclude_items);
+         while (--num >= 0) {   
+            free_incexe(res->res_fs.exclude_items[num]);
+         }
+         free(res->res_fs.exclude_items);
       }
       res->res_fs.num_excludes = 0;
       break;
    case R_POOL:
       if (res->res_pool.pool_type) {
-        free(res->res_pool.pool_type);
+         free(res->res_pool.pool_type);
       }
       if (res->res_pool.label_format) {
-        free(res->res_pool.label_format);
+         free(res->res_pool.label_format);
       }
       if (res->res_pool.cleaning_prefix) {
-        free(res->res_pool.cleaning_prefix);
+         free(res->res_pool.cleaning_prefix);
       }
       break;
    case R_SCHEDULE:
       if (res->res_sch.run) {
-        RUN *nrun, *next;
-        nrun = res->res_sch.run;
-        while (nrun) {
-           next = nrun->next;
-           free(nrun);
-           nrun = next;
-        }
+         RUN *nrun, *next;
+         nrun = res->res_sch.run;
+         while (nrun) {
+            next = nrun->next;
+            free(nrun);
+            nrun = next;
+         }
       }
       break;
    case R_JOB:
    case R_JOBDEFS:
       if (res->res_job.RestoreWhere) {
-        free(res->res_job.RestoreWhere);
+         free(res->res_job.RestoreWhere);
       }
       if (res->res_job.RestoreBootstrap) {
-        free(res->res_job.RestoreBootstrap);
+         free(res->res_job.RestoreBootstrap);
       }
       if (res->res_job.WriteBootstrap) {
-        free(res->res_job.WriteBootstrap);
+         free(res->res_job.WriteBootstrap);
       }
       if (res->res_job.RunBeforeJob) {
-        free(res->res_job.RunBeforeJob);
+         free(res->res_job.RunBeforeJob);
       }
       if (res->res_job.RunAfterJob) {
-        free(res->res_job.RunAfterJob);
+         free(res->res_job.RunAfterJob);
       }
       if (res->res_job.RunAfterFailedJob) {
-        free(res->res_job.RunAfterFailedJob);
+         free(res->res_job.RunAfterFailedJob);
       }
       if (res->res_job.ClientRunBeforeJob) {
-        free(res->res_job.ClientRunBeforeJob);
+         free(res->res_job.ClientRunBeforeJob);
       }
       if (res->res_job.ClientRunAfterJob) {
-        free(res->res_job.ClientRunAfterJob);
+         free(res->res_job.ClientRunAfterJob);
+      }
+      for (int i=0; i < MAX_STORE; i++) {
+         if (res->res_job.storage[i]) {
+            delete (alist *)res->res_job.storage[i];
+         }
       }
       break;
    case R_MSGS:
       if (res->res_msgs.mail_cmd) {
-        free(res->res_msgs.mail_cmd);
+         free(res->res_msgs.mail_cmd);
       }
       if (res->res_msgs.operator_cmd) {
-        free(res->res_msgs.operator_cmd);
+         free(res->res_msgs.operator_cmd);
       }
       free_msgs_res((MSGS *)res);  /* free message resource */
       res = NULL;
@@ -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;
    }
index f3a45bca6ac6664556a7f8e286af8260bb567334..bd864082b600a601a4c1fe34b442c289fd1032a5 100644 (file)
@@ -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 */
index cb0175610c429096e7526aaa09e48ae5da140606..ee2e89eda405d34161cad03b70048510ac5bdd26 100644 (file)
@@ -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);
index 7cae21469ae099b982b72fe4daf76863d899ef2a..33935436d76bae0f8c2b6c9eed44c2299fc2f7e9 100644 (file)
@@ -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; i<MAX_STORE; i++) {
+           ua->jcr->storage[i] = jcr->storage[i];
+        }
         if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
             bsendmsg(ua, _("Failed to connect to Storage daemon.\n"));
            return 0;
@@ -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; i<MAX_STORE; i++) {
+      jcr->storage[i] = job->storage[i];
+   }
    jcr->client = job->client;
    if (!jcr->client_name) {
       jcr->client_name = get_pool_memory(PM_NAME);
diff --git a/bacula/src/dird/mac.c b/bacula/src/dird/mac.c
new file mode 100644 (file)
index 0000000..ee60359
--- /dev/null
@@ -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");
+}
index c92f07fb00b837bf8f8031270ccf81452d42bc6e..ee9fffb5a855780e44017f5ac473d55b50b29be1 100644 (file)
@@ -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;
 }
 
index 0f95284cb04beea8476e4dbc9381f42dab7ed4cc..5f58db8236d0cba4f02e8593f9c2abbbc9f7fb89 100644 (file)
@@ -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
     */
index 45101b08e346d34dd9c4a51d8801a3b94e24ef05..f021ea54cb7fe5d169a08c8d739242008060dbcc 100644 (file)
@@ -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);
index 731dad3ca66affd022dc7d48c815aab04b2cd32a..fa541d84cdade1f613a0a021e9372c517155820b 100644 (file)
@@ -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;
index 7ea798769fdcf0dafc74afbaa7cc900d08b81b1a..fd55e82f79b94d53432ee1b4bc80ef35c576d98b 100644 (file)
@@ -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);
index 98c9c53de091797bcf4cff8519bb8042c1419606..291613ccb79950b6ec6023dd943a26177d7bad05 100644 (file)
@@ -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);
       }
index 69df08e6b31955dce07c4166bbc3a2e27e0c564b..9a1f11d2f2fad2bbaf9f0f68c8a91d0998b52757 100644 (file)
@@ -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);
index fcf5acc76e22a908807bc42c33e9079501a8aae5..7078d2f95e4eb26cdd73077a481a0240e7652476 100644 (file)
@@ -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;
index bfdc5ec88580526c4a79f7886ae589a36f9fd9fb..afd32d6b6c1a6de38e47eb9118a5c659f2b672a5 100644 (file)
@@ -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);
index 70f0bc8054735fde431f36e8df350efbef838ca2..d7ef5b6416ac8f9d7224d37da667517e34d35856 100644 (file)
@@ -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;
         }
index 997eff3e5999f67cc17e6987cd352907b63b4c7e..efa2f7ea01473904d2c51d725f1021089446edd6 100644 (file)
@@ -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;
index a971373c80cacc2468e4dcc7ab24c9cf5431841e..c1d07223ff6a1bc75e72792b66da9977600dba44 100644 (file)
@@ -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)
 {
index 62d3da7329bfb3beecb8c48cb4d8ed0d3fb379e6..43a27a2b5300cdd7b462e146c826b1babfa8c068 100644 (file)
@@ -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;
    }
index 7c142ddd864ded3a397f1411cf8115d3c0da43e6..330d5f49ac0b55e1e46ac287636338cefd2020a5 100644 (file)
@@ -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 */
index aaf335d281b0cb18c14e85a397b2c3d70f48864f..3aee618880df32d60c4699e1c3ad430f3ba50464 100644 (file)
@@ -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 */
       }
    }
 }
index 1879ded31ab475d1bb688564ac118293cbe76163..0fb16426c80f455717dd48c73e64919121999512 100644 (file)
@@ -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_;
index bc5ae5834bd5d900a07e0b84eb20705cc3313700..1aa87d9f6020db5c1a6e5c55f3b6dbf012091cd7 100644 (file)
@@ -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)
index b1c24c0ddb773f847e413e4379864f2ab57e5510..fd87b12cd0a9c5392e773ff21b557c10cc73b6fb 100644 (file)
@@ -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.
     */
index 1bb1b3c14086fc017ef4ca987cf84e4ed9bab04f..e0b35b7663269914afc82344b8dde6263c653da1 100644 (file)
@@ -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
index b10b8a65cc3cece336280c526d150165669fa468..439085110ffeef15fb8a9348dbd7b4214c9cb09e 100644 (file)
@@ -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;
+}
index 839effc8ef8737e89dac91d1a0df99339bb9f828..62b508f99f610e61d54d7eb6c4b957e2ac1500ce 100644 (file)
@@ -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
index 273be9c122ac0ef48f0755ca6240d54f092cac2e..80686bbcfad810380e82f9d30505615b4b47a142 100755 (executable)
@@ -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 
index 92bb70f37d42a2a012030894095c28b631aaa4a8..1385e3e3bf165a40e26b3052b020be722bbdf99e 100644 (file)
@@ -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);
index 4d054e1ae86f470e1be71ac7618d9c93cbe72c85..b5957e19c1606f11589bc298bd7818a1dabc2907 100644 (file)
 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 */
index b1eec7043897a8181bdcd49e1e89b57657b2c53d..261292956f7bb1c6243df25b49b71cbe669bfbdd 100644 (file)
@@ -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;
-}
-
-
 
 
 /*
index bf739ac7ce9447abaae3ec51dcc5b3b1aeaf6874..bce27ef00cd2063a84cd6da0b3fde66b07921ede 100644 (file)
@@ -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; i<jcr->CurVolume; i++) {
       vol = vol->next;
    }
-   pm_strcpy(&jcr->VolumeName, vol->VolumeName);
    bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName));
 
    for (i=0; i<5; i++) {
@@ -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);
index cff97bf8d3e705aa3aa5c7ee722bbec4dc7700ec..1cd0780cf464cde1e01c842dbba55b69e411b763 100644 (file)
@@ -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;
index 4080802edbf1f9bc7c73c4c72ed356dffd1c8af9..9efc7b098f072504a8915c8a867e00c05c20767b 100644 (file)
@@ -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));
index 342619ad304eaa00b6c9e497f8172dc27c825109..b9ef352b31f24478f40e34a1320cdcd981b61a3e 100644 (file)
@@ -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);
index d4a511198796c66c98f06b003166f9f4d9601b9e..430ade486db28825bdcddeec368cb7e32dbfbac0 100644 (file)
@@ -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;
 }
index 72439b49a3f1de518798171281fcf17139e67e35..fb67da69ae724324b30a3474c2b9b3ef6c1e6100 100644 (file)
@@ -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 <file>       exclude list\n"
 "       -i <file>       include list\n"
 "       -p              proceed inspite of I/O errors\n"
+"       -v              verbose\n"
 "       -V <volumes>    specify Volume names (separated by |)\n"
 "       -?              print this message\n\n");
    exit(1);
@@ -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;
 }
index 5a59b2915234d1b9b9e780388c52bb33704d4305..915cf6ee65b649a1da733e7f6fa849918e02b883 100644 (file)
@@ -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;
index 145c86079d94c18f3b26355800c6fafbd671f347..df7e674867fe181d13454777efc4484eaf4fc54b 100644 (file)
@@ -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;
 }
index 45f53f5332e447bc80d1323f1d9625fef7ef8203..6e415d177aa516b51b4905b559dcda435026deba 100644 (file)
@@ -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"),
index 65c6303e27b146e2f55ec557be2b651b932602f5..06dc096814113cfc0a6bc0594b956505bf2633db 100644 (file)
@@ -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;
 }
index ada7ddacc0abf75b441efc3a874f9f0f03ecf7d1..183e2ff019d374828066727a66d82c7dc24af682 100644 (file)
@@ -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
 #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"));
index 02bb38568090cf5868285f6571ea2a0525fa2a80..b81b745e52eb8d63e119804366667dfec9d72b02 100644 (file)
@@ -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;
index 4efe4bd7d40948b700cceebd5c00e655d9a77e1e..4516c626c90e3252583b050ec604b650d8b49f15 100644 (file)
@@ -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 */
 };
 
index 8b4f39be4d5110b3ad47fbcca908d0f3c20d9f97..7d5a9af81bf2e4ebace9dd2583ec056ebd96a9dd 100644 (file)
@@ -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;
index 7adddf5465fd3c1f646f51488dfe17a2f7ca3da2..edd11821535874d6d6e89ed37019c1d0c006ecb0 100644 (file)
@@ -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;
 }
index 39961dbfaedfaea11c5a9f02241a8aaec0ba78fe..b6d801cd7e31f19ab7aba7588568e81dded53010 100644 (file)
@@ -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, "<filed: %s", fd->msg);
-      found = 0;
+      found = false;
       for (i=0; fd_cmds[i].cmd; i++) {
         if (strncmp(fd_cmds[i].cmd, fd->msg, strlen(fd_cmds[i].cmd)) == 0) {
-           found = 1;               /* indicate command found */
+           found = true;               /* indicate command found */
            if (!fd_cmds[i].func(jcr)) {    /* do command */
               set_jcr_job_status(jcr, JS_ErrorTerminated);
-              quit = 1;
+              quit = true;
            }
            break;
         }
@@ -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, "<bfiled: %s", fd->msg);
       jcr->JobType = JT_BACKUP;
       if (do_append_data(jcr)) {
-        bnet_fsend(fd, OK_append);
-        return 1;
+        return bnet_fsend(fd, OK_append);
       } else {
         bnet_suppress_error_messages(fd, 1); /* ignore errors at this point */
         bnet_fsend(fd, ERROR_append);
-        return 0;
       }
    } else {
       bnet_fsend(fd, NOT_opened);
-      return 0;
    }
+   return false;
 }
 
-static int append_end_session(JCR *jcr)
+static bool append_end_session(JCR *jcr)
 {
    BSOCK *fd = jcr->file_bsock;
 
    Dmsg1(120, "store<file: %s", fd->msg);
    if (!jcr->session_opened) {
       bnet_fsend(fd, NOT_opened);
-      return 0;
+      return false;
    }
    set_jcr_job_status(jcr, JS_Terminated);
    return bnet_fsend(fd, OK_end);
@@ -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, "<filed: %s\n", fd->msg);
    if (!jcr->session_opened) {
       bnet_fsend(fd, NOT_opened);
-      return 0;
+      return false;
    }
    /* Send final statistics to File daemon */
    bnet_fsend(fd, OK_close, jcr->JobStatus);
@@ -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;
 }
index 7eea25673bd8a5579278fc4c49cf39e43ce67e20..e200cc9d2ec7d5da9f7c9468af6da3f4a3d47a92 100644 (file)
@@ -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);
    }
index c4a431b0c8066d71f33cf290b42309f88c3c6f59..aca6f901e65bcbed59dd3f3534895e428b055047 100644 (file)
@@ -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);
index f03f9e68925e9f777c7e3be8ab284d5e71799f35..efb0ce602fbdb2780128cc286ebe8b52982897d7 100644 (file)
@@ -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))) {
index 10c05d3d9d3ddd78b13de4b845dd75758b9ac8a4..4ff019b30c51ef272ebfef784fd06f822c736c10 100755 (executable)
@@ -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 */
index 6898968a29311199d8f2627c68c9e2d6e6c16dc3..4956dfa7ec4690125b0199c52b5574136eff593f 100644 (file)
@@ -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);
index bdf870052c742e8e4a80a32d62c287e746e42b9d..937ae4ba2d26f5b278c084449fcd4824328dfd84 100644 (file)
@@ -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;
index 5ecfdf7c4e8ecd15363dd820be5cb86c9f77e9e1..88f63f729b70e7b5060d0d9b6751dadbd19f43b1 100644 (file)
@@ -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;
 }
 
index c0c564c0be5f1375b430d74005803308b49fc8cb..d3bb44eab6c35b45128c9ffb28bea864a7e15d52 100644 (file)
@@ -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 */
 }
index dd3047d478af6b6e1bfa893ffd9a9cda292fc2e8..2267d8a4733579c802fd7f2bad7ce3a5c963a738 100644 (file)
@@ -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
index 5af270180ba6a58cbc9e1f91f9a2412a74e3637a..7a41338b7727cdfedcec865833bb02e0f0439eab 100644 (file)
@@ -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);
index 14f99b2639f957e286f7cd2e603d505267bad410..74398e7a427de87b5d2ad0856374a1e1ca715258 100644 (file)
@@ -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;
 }
index e2133ee9481df6d097a22d63d3b1dc8eda38e48e..6f55cc42090f6939e0042a25fb7cecd8fa5e9232 100644 (file)
@@ -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:
index afe8a2075e59a43280d779645d5c9c1bbad52ff6..2933237cc0e21b73f1a47052dd47f86883002032 100644 (file)
 #else
 #define uLongf uint32_t
 #endif
+#ifdef HAVE_FNMATCH
+#include <fnmatch.h>
+#else
+#include "lib/fnmatch.h"
+#endif
 
 extern STORES *me;                    /* "Global" daemon resource */
 extern bool forge_on;                 /* proceed inspite of I/O errors */
index 16a370405db79066a80ad728adfe31c97e3f349f..8a8de08288f6630e1a2e8c84d2f659de92921cd3 100644 (file)
@@ -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},
index 457dce7335afb2f61f81afcc4219b41ee04b3c80..2c4bc74bc756c4e8511880f9955c40148c9e69ae 100644 (file)
@@ -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;
 };
index 0553ee4a2c727b9b8e213c21d80e98b741a382ac..3dba7d8f5f9325bc9c6ae6f1b516a4c36aabe0c0 100644 (file)
@@ -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;
index c4c5ae0f1ebe01309c3db0a4719881214cf5e886..702c69730f8b0d9589992ef8ef5ad21b50220c13 100644 (file)
@@ -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 */