]> git.sur5r.net Git - bacula/bacula/commitdiff
SetIP command + CloseOnPoll + Full,Inc,Diff Pools + more access control checks
authorKern Sibbald <kern@sibbald.com>
Thu, 22 Jan 2004 22:59:31 +0000 (22:59 +0000)
committerKern Sibbald <kern@sibbald.com>
Thu, 22 Jan 2004 22:59:31 +0000 (22:59 +0000)
git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@1017 91ce42f0-d328-0410-95d8-f526ca767f89

28 files changed:
bacula/ReleaseNotes
bacula/autoconf/configure.in
bacula/configure
bacula/kernstodo
bacula/src/cats/drop_sqlite_database.in
bacula/src/cats/sql_find.c
bacula/src/cats/sql_get.c
bacula/src/cats/sql_list.c
bacula/src/dird/backup.c
bacula/src/dird/dird_conf.c
bacula/src/dird/dird_conf.h
bacula/src/dird/job.c
bacula/src/dird/protos.h
bacula/src/dird/run_conf.c
bacula/src/dird/scheduler.c
bacula/src/dird/sql_cmds.c
bacula/src/dird/ua_cmds.c
bacula/src/dird/ua_prune.c
bacula/src/dird/ua_restore.c
bacula/src/dird/ua_select.c
bacula/src/dird/ua_status.c
bacula/src/jcr.h
bacula/src/lib/parse_conf.c
bacula/src/stored/askdir.c
bacula/src/stored/dev.h
bacula/src/stored/mount.c
bacula/src/stored/stored_conf.c
bacula/src/version.h

index adad9773598e8cecd9f71adb9cd9d464f846263f..185f50dfb6ca4728068061963ea843c9bbb047bd 100644 (file)
@@ -1,9 +1,48 @@
 
           Release Notes for Bacula 1.33
 
-  Bacula code: Total files = 281 Total lines = 83,815 (*.h *.c *.in)
+  Bacula code: Total files = 283 Total lines = 84,818 (*.h *.c *.in)
+
+New directives:
+- "Close on Poll = yes/no" in SD Device resource.
+- "Volume Poll Interval = time-interval" in SD Device resource.
+- "Two EOF = yes/no" in SD Device resource.
+- "Close on Poll = yes/no" in SD Device resource.
+- "Maximum Network Buffer Size = size" in SD Device resource.
+- "Maximum Network Buffer Size = size" in FD FileDaemon (or Client) resource.
+- "Console" new resource in Director conf file.
+     New directives: Name, Description, Password, JobACL, ClientACL,
+        StorageACL, ScheduleACL, RunACL, PoolACL, CommandACL,
+        FileSetACL, CatalogACL.
+- "Max Run Time = duration" in Director Job resource.
+- "Max Wait Time = duration" in Director Job resource (not fully implemented).
+- "JobDefs = name-of-resource" in Director Job resource.
+- "Jobdefs" new resource in Director. Same directives as for a Job.
+- "Full Backup Pool = xxx" in Job resource in the Director.
+- "Incremental Backup Pool = xxx" in Job resource in the Director.
+- "Differential Backup Pool = xxx" in Job resource in the Director.
+- Three new options on the Run override statement in a Schedule resource:
+   FullPool=xxx
+   IncrementalPool=xxx
+   DifferentialPool=xxx
+
+New Commands:
+- "SetIP"
+- Added "pool=xxx" to restore command line.
+- Added "fileset=xxx" to restore command line.
+- Fixed "storage=xxx" on restore command line.
+- "markdir" command in restore tree.
+- "unmarkdir" command in restore tree.
+- "quit" command in restore tree.
 
 Most Significant Changes since 1.32d
+- The ability to ask the Storage daemon on a device by device basis
+  to "poll" the tape drive at a given interval (minimum 1 minute). If
+  a tape is found, its label is read and if appropriate it is used.
+  This eliminates the need to do "mount" commands.
+- The ability to close and re-open the device when a poll occurs. 
+  This permits dealing with certain recalcitrant autochangers that
+  invalidate devices (typically on FreeBSD).
 - Dan Langille has written a PostgreSQL driver for Bacula.
 - Implement "update slots scan" that reads the volume label(s).
 - The full form of the scan is "scan=1,2,4-5,7". With no specification,
index 2306ef015353745115c25d570d70a5d11c544661..b937190b9297e88e5bc1a115dae00d8f4a0362fc 100644 (file)
@@ -576,7 +576,7 @@ AC_ARG_WITH(tcp-wrappers,
 # ------------------------------------------
 # Where to place working dir
 # ------------------------------------------
-working_dir=`eval echo ${sysconfdir}/working`
+working_dir=`eval echo ${prefix}/var/bacula/working`
 AC_ARG_WITH(working-dir,
    [  --with-working-dir=PATH   specify path of Bacula working directory],
    [
@@ -1285,7 +1285,7 @@ WLDFLAGS=
 PFILES="platforms/Makefile"
 PSCMD="ps -e"
 WIN32=
-hostname=`uname -n`
+hostname=`uname -n | cut -d '.' -f 1`
 case "$DISTNAME" in
 aix)
        DISTVER=`uname -r`
@@ -1319,7 +1319,6 @@ bsdi)
            platforms/bsdi/bacula-fd \
            platforms/bsdi/bacula-sd \
            platforms/bsdi/bacula-dir"
-       hostname=`hostname -s`
        largefile_support="yes"
   ;;
 cygwin)
@@ -1333,7 +1332,6 @@ darwin)
        DISTVER=`uname -r`
        TAPEDRIVE="/dev/nst0"
        PSCMD="ps -e -o pid,command"
-       hostname=`hostname -s`
        PFILES="${PFILES} \
           platforms/darwin/Makefile"
   ;;
@@ -1341,7 +1339,6 @@ debian)
        DISTVER=`cat /etc/debian_version`
        TAPEDRIVE="/dev/nrst0"
        PSCMD="ps -e -o pid,command"
-       hostname=`hostname -s`
   ;;
 freebsd)
        DISTVER=`uname -a |awk '{print $3}'`
@@ -1359,7 +1356,6 @@ freebsd)
            platforms/freebsd/bacula-fd \
            platforms/freebsd/bacula-sd \
            platforms/freebsd/bacula-dir"
-       hostname=`hostname -s`
        largefile_support="yes"
   ;;
 hpux)
@@ -1431,7 +1427,6 @@ mandrake)
            platforms/mandrake/bacula-dir \
            platforms/mandrake/bacula.spec \
            "
-       hostname=`hostname -s`
   ;;
 gentoo)
        DISTVER=`awk '/version / {print $5}' < /etc/gentoo-release`
@@ -1442,14 +1437,12 @@ gentoo)
            platforms/gentoo/bacula-fd \
            platforms/gentoo/bacula-sd \
            platforms/gentoo/bacula-dir"
-       hostname=`hostname -s`
   ;;
 
 slackware)
        DISTVER=`cat /etc/slackware-version`
        TAPEDRIVE="/dev/nst0"
        PSCMD="ps -e -o pid,command"
-       hostname=`hostname -s`
   ;;
 solaris)
        DISTVER=`uname -r`
@@ -1469,7 +1462,6 @@ suse)
            cut -f 3 -d ' '`
        TAPEDRIVE="/dev/nst0"
        PSCMD="ps -e -o pid,command"
-       hostname=`hostname -s`
        PFILES="${PFILES} \
            platforms/suse/Makefile \
            platforms/suse/bacula-fd \
@@ -1481,7 +1473,6 @@ suse5)
        DISTVER=5.x
        TAPEDRIVE="/dev/nst0"
        PSCMD="ps -e -o pid,command"
-       hostname=`hostname -s`
        PFILES="${PFILES} \
            platforms/suse/Makefile \
            platforms/suse/bacula-fd \
index 354cc14ec98a1be3661956d9382d4180a71fc2c4..0f814c75485db514f89ca4fb0c8aa6556fae3926 100755 (executable)
@@ -6685,7 +6685,7 @@ fi;
 # ------------------------------------------
 # Where to place working dir
 # ------------------------------------------
-working_dir=`eval echo ${sysconfdir}/working`
+working_dir=`eval echo ${prefix}/var/bacula/working`
 
 # Check whether --with-working-dir or --without-working-dir was given.
 if test "${with_working_dir+set}" = set; then
@@ -17956,7 +17956,6 @@ slackware)
        DISTVER=`cat /etc/slackware-version`
        TAPEDRIVE="/dev/nst0"
        PSCMD="ps -e -o pid,command"
-       hostname=`hostname -s`
   ;;
 solaris)
        DISTVER=`uname -r`
index 1851d9feb51f34f5766d8f0299ab9dc5501a1391..89de4c46fa1179cda54d3087125a31ad662e5a27 100644 (file)
@@ -35,6 +35,7 @@ Testing to do: (painful)
 - Test cancel at EOM.       
 
 For 1.33 Testing/Documentation:
+- Newly labeled tapes are chosen before ones already in use.
 - Document new alias records in Director. SDAddress SDDeviceName, SDPassword.
   FDPassword, FDAddress, DBAddress, DBPort, DBPassword.
 - Document new Include/Exclude ...
@@ -56,9 +57,37 @@ For 1.33 Testing/Documentation:
   purge, ...
 - Add subsections to the Disaster Recovery index section.
 - Document Pool keyword for restore.
-                
+- If you use restore replace=never, the directory attributes for
+  non-existent directories will not be restored properly.
+- In the Bacula User Guide you write:"Note, one major disadvantage of
+  writing to a NFS mounted volume as I do isthat if the other machine goes
+  down, the OS will wait forever on the fopen()call that Bacula makes.  As
+  a consequence, Bacula will completely stall untilthe machine exporting
+  the NSF mounts comes back up.  If someone knows a wayaround this, please
+  let me know."I haven't tried using NFS in years, but I think that the
+  "soft" and "intr"remount options may well help you.  The only way of
+  being sure would be totry it.See, for example,
+     http://howtos.linux.com/guides/nag2/x-087-2-nfs.mountd.shtml
+
 For 1.33
-- Fix restore to only pull in last Differential and later Incrementals.
+- Rescue builds incorrect script files on Rufus.
+- Write a Qmsg() to be used in bnet.c to prevent recursion. Queue the
+  message. If dequeueing toss the messages. Lock while dequeuing so that
+  it cannot be called recursively and set dequeuing flag.
+- Look at ASSERT() at 384 src/lib/bnet.c
+- Add all pools in Dir conf to DB.
+- Symbolic link a directory to another one, then backup the symbolic
+  link.
+- Build console in client-only build.
+- Restore attributes of directory if replace=never set but directory
+  did not exist.
+- Check why Phil's Verify exclude does not work.
+- Phil says that Windows file sizes mismatch in Verify when they should,
+  and that either the file size or the catalog size was zero.
+- Fix option 2 of restore -- list where file is backed up -- require Client,
+  then list last 20 backups.
+- Allow browsing the catalog to see all versions of a file (with 
+  stat data on each file).
 - Finish code passing files=nnn to restore start.
 - Add level to estimate command.
 - Check time/dates printed during restore when using Win32 API.
@@ -131,6 +160,67 @@ For 1.33
   F Number         Number of filenames to follow
   <file-name>
   ...
+
+- Spooling ideas taken from Volker Sauer's and other's emails:
+   > IMHO job spooling should be turned on
+   > 
+   > 1) by job
+   > 2) by schedule
+   > 3) by sd
+   > 
+   > where and 2) overrides 1) and 3) is independent.
+
+   Yes, this is the minimum that I think is necessary.
+
+   > 
+   > Reason(s):
+   > It should be switched by job, because the job that backs up the machine 
+   > with the bacula-sd on doesn't need spooling.
+   > It should be switched by schedule, because for full-backups I don't need 
+   > spooling, so I can switch it off (because the network faster then the 
+   > tapedrive) 
+
+   True, with the exception that if you have enough disk spool space,
+   and you want to run concurrent jobs, spooling can eliminate the block
+   interleaving restore inefficiencies.
+
+   > And you should be able to turn it of by sd for sd-machines with low disk 
+   > capacity or if you just don't need or want this feature.
+   > 
+   > There should be:
+   > - definitly the possibility for multipe spool direcories
+
+   Having multiple directories is no problem -- having different maximum
+   sizes creates specification problems.  At some point, I will probably
+   have a common SD pool of spool directories as well as a set of
+   private spool directories for each device.  The first implementation
+   will be a set of private spool directories for each device since
+   managing a global pool with a bunch of threads writing into the same
+   directory is *much* more complicated and prone to error.
+
+   > - the ability to spool parts of a backup (not the whole client)
+
+   This may change in the future, but for the moment, it will spool
+   either to a job high water mark, or until the directory is full
+   (reaches max spool size or I/O error).  It will then write to tape,
+   truncate the spool file, and begin spooling again.
+
+   > - spooling while writing to tape
+
+   Not within a job, but yes, if you run concurrent jobs -- each is a
+   different thread.  Within a job could be a feature, but *much* later.
+
+   > - parallel spooling (like parallel jobs/ concurrent jobs) of clients
+
+   Yes, this is one of my main motivations for doing it (aside from
+   eliminating tape "shoe shine" during incremental backups.
+
+   > - flushing a backup that only went to disk (like amflush in amanda)
+
+   This will be a future feature, since spooling is different from backing
+   up to disk. The future feature will be "migration" which will move a job
+   from one backup Volume to another.
+
 - New Storage specifications:
   Passed to SD as a sort of BSR record called Storage Specification
     Record or SSR.
@@ -215,13 +305,6 @@ Ideas from Jerry Scharf:
   Job report (Volker Sauer).
 - Client does not show busy during Estimate command.
 - Implement Console mtx commands.
-- Implement 3 Pools for a Job:
-   Job {
-     Name = ...
-     Full Backup Pool = xxx
-     Incremental Backup Pool = yyy
-     Differential Backup Pool = zzz
-   }
 - Add a default DB password to MySQL.  
   GRANT all privileges ON bacula.* TO bacula@localhost IDENTIFIED BY 
      'bacula_password';
@@ -1119,3 +1202,11 @@ Done: (see kernsdone for more)
   directories, setting them to be restored.
 - Figure out a way to set restore on a directory without recursively
   decending.  (recurse off?).
+- Fix restore to only pull in last Differential and later Incrementals.
+- Implement 3 Pools for a Job:
+   Job {
+     Name = ...
+     Full Backup Pool = xxx
+     Incremental Backup Pool = yyy
+     Differential Backup Pool = zzz
+   }
index c10f3ca6ed13ae97fadc2bc71e8c5ae4b0d715e7..ece801c9b68cdf5ae76adc9a188995b47b23e7a4 100644 (file)
@@ -2,10 +2,5 @@
 #
 # shell script to drop Bacula SQLite tables
 
-bindir=@SQL_BINDIR@
 cd @working_dir@
-
-# how do we drop an sqlite database?
-#$bindir/sqlite $* bacula.db <<END-OF-DATA
-#END-OF-DATA
-exit 0
+rm -rf bacula.db
index c7050f8a3c107917068f5c25f528c605c9e19ee4..c7cb8d136950b8b9d414e0e326fd048441c69218 100644 (file)
@@ -301,7 +301,6 @@ db_find_next_volume(JCR *jcr, B_DB *mdb, int item, bool InChanger, MEDIA_DBR *mr
    bstrncpy(mr->cLastWritten, row[18]!=NULL?row[18]:"", sizeof(mr->cLastWritten));
    mr->LastWritten = (time_t)str_to_utime(mr->cLastWritten);
    bstrncpy(mr->VolStatus, row[19], sizeof(mr->VolStatus));
-
    sql_free_result(mdb);
 
    db_unlock(mdb);
index d4469845b8820ad388b7e0371e2d6c4a21c7b51c..34dcb299f0311f4cfec3f9793b4fae2b2e928435 100644 (file)
@@ -322,7 +322,7 @@ int db_get_job_volume_names(JCR *jcr, B_DB *mdb, uint32_t JobId, POOLMEM **Volum
    db_lock(mdb);
    Mmsg(&mdb->cmd, 
         "SELECT DISTINCT VolumeName FROM JobMedia,Media WHERE "
-        "JobMedia.JobId=%u AND JobMedia.MediaId=Media.MediaId ",
+        "JobMedia.JobId=%u AND JobMedia.MediaId=Media.MediaId",
        JobId);
 
    Dmsg1(130, "VolNam=%s\n", mdb->cmd);
index b084d5890df10d280ccc5770e3bc9293b0a0e868..6541f3a27f4c45e05bfac10f5b32509619f6c21b 100644 (file)
@@ -139,14 +139,14 @@ db_list_media_records(JCR *jcr, B_DB *mdb, MEDIA_DBR *mdbr,
             "MediaType,FirstWritten,LastWritten,LabelDate,VolJobs,"
             "VolFiles,VolBlocks,VolMounts,VolBytes,VolErrors,VolWrites,"
             "VolCapacityBytes,VolStatus,Recycle,VolRetention,"
-            "VolUseDuration,MaxVolJobs,MaxVolFiles,MaxVolBytes "
+            "VolUseDuration,MaxVolJobs,MaxVolFiles,MaxVolBytes,InChanger "
             "FROM Media WHERE Media.VolumeName='%s'", mdbr->VolumeName);
       } else {
          Mmsg(&mdb->cmd, "SELECT MediaId,VolumeName,Slot,PoolId,"
             "MediaType,FirstWritten,LastWritten,LabelDate,VolJobs,"
             "VolFiles,VolBlocks,VolMounts,VolBytes,VolErrors,VolWrites,"
             "VolCapacityBytes,VolStatus,Recycle,VolRetention,"
-            "VolUseDuration,MaxVolJobs,MaxVolFiles,MaxVolBytes "
+            "VolUseDuration,MaxVolJobs,MaxVolFiles,MaxVolBytes,InChanger "
             "FROM Media WHERE Media.PoolId=%u ORDER BY MediaId", mdbr->PoolId);
       }
    } else {
index 0fe51441a94e64faf09373ced7eb3c3460a8bcd2..d570e274eedfebdc39fb090ee4a5066efc514dba 100644 (file)
@@ -120,10 +120,28 @@ int do_backup(JCR *jcr)
        jcr->JobId, jcr->Job);
 
    /* 
-    * Get the Pool record  
+    * 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) {
index f41dce96e5d31066b13b56fc92fe985a9b6761e6..ebea539c103a9fe523509e4eca9f661ec15e777e 100644 (file)
@@ -205,6 +205,9 @@ struct res_items job_items[] = {
    {"messages",  store_res,     ITEM(res_job.messages), R_MSGS, ITEM_REQUIRED, 0},
    {"storage",   store_res,     ITEM(res_job.storage),  R_STORAGE, ITEM_REQUIRED, 0},
    {"pool",      store_res,     ITEM(res_job.pool),     R_POOL, ITEM_REQUIRED, 0},
+   {"fullbackuppool",  store_res,     ITEM(res_job.full_pool),   R_POOL, 0, 0},
+   {"incrementalbackuppool",  store_res, ITEM(res_job.inc_pool), R_POOL, 0, 0},
+   {"differentialbackuppool", store_res, ITEM(res_job.dif_pool), R_POOL, 0, 0},
    {"client",    store_res,     ITEM(res_job.client),   R_CLIENT, ITEM_REQUIRED, 0},
    {"fileset",   store_res,     ITEM(res_job.fileset),  R_FILESET, ITEM_REQUIRED, 0},
    {"schedule",  store_res,     ITEM(res_job.schedule), R_SCHEDULE, 0, 0},
@@ -534,8 +537,18 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, char *fmt, ...
       if (res->res_job.pool) {
          sendit(sock, "  --> ");
         dump_resource(-R_POOL, (RES *)res->res_job.pool, sendit, sock);
-      } else {
-         sendit(sock, "!!! No Pool resource\n");
+      }
+      if (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);
+      }
+      if (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, "  --> ");
@@ -959,6 +972,9 @@ void save_resource(int type, struct res_items *items, int pass)
         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;
index ee2f15847d55fbdfb0f62c327ed948d3d4988b0a..6ab7688f3bbf95261217206d49c5c3de36edf7da 100644 (file)
@@ -228,6 +228,9 @@ struct JOB {
    FILESET   *fileset;                /* What to backup -- Fileset */
    STORE     *storage;                /* 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 */
+   POOL      *dif_pool;               /* Pool for Differental backups */
    JOB       *verify_job;             /* Job name to verify */
    JOB       *jobdefs;                /* Job defaults */
    uint32_t NumConcurrentJobs;        /* number of concurrent jobs running */
@@ -348,6 +351,9 @@ struct RUN {
    int Priority;                      /* priority override */
    int job_type;  
    POOL *pool;                        /* Pool override */
+   POOL *full_pool;                   /* Pool override */
+   POOL *inc_pool;                    /* Pool override */
+   POOL *dif_pool;                    /* Pool override */
    STORE *storage;                    /* Storage override */
    MSGS *msgs;                        /* Messages override */
    char *since;
index 71d15ff44ad054bd33d5fda2684450667df05018..73eff3e13a7fd8a01ce9abe1ad36d1f211349cd1 100644 (file)
@@ -680,6 +680,9 @@ void set_jcr_defaults(JCR *jcr, JOB *job)
    }
    pm_strcpy(&jcr->client_name, jcr->client->hdr.name);
    jcr->pool = job->pool;
+   jcr->full_pool = job->full_pool;
+   jcr->inc_pool = job->inc_pool;
+   jcr->dif_pool = job->dif_pool;
    jcr->catalog = job->client->catalog;
    jcr->fileset = job->fileset;
    jcr->messages = job->messages; 
index 87bc67d8e521a8d7ba6658b2f12635c9a4793b42..cbfe5b7fee236b86f70553911db355adc7269180 100644 (file)
@@ -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);
 
@@ -94,7 +94,7 @@ 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);
+                              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);
@@ -146,28 +146,28 @@ JCR *create_control_jcr(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);
-int    select_pool_dbr(UAContext *ua, POOL_DBR *pr);
-int    select_client_dbr(UAContext *ua, CLIENT_DBR *cr);
-
-void   start_prompt(UAContext *ua, char *msg);
-void   add_prompt(UAContext *ua, char *prompt);
-int    do_prompt(UAContext *ua, char *automsg, 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);
+int     select_pool_dbr(UAContext *ua, POOL_DBR *pr);
+int     select_client_dbr(UAContext *ua, CLIENT_DBR *cr);
+
+void    start_prompt(UAContext *ua, char *msg);
+void    add_prompt(UAContext *ua, char *prompt);
+int     do_prompt(UAContext *ua, char *automsg, 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);
-int    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);
+int     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, char **list);
 int find_arg(UAContext *ua, char *keyword);
index faabf7c9fa63e58522ed723b990b9d0edef4b86e..e4a54ae41109f4ccd3a852d1881b6e84136c38b6 100644 (file)
@@ -150,12 +150,15 @@ static void set_defaults()
 
 /* Keywords (RHS) permitted in Run records */
 static struct s_kw RunFields[] = {
-   {"pool",     'P'},
-   {"level",    'L'},
-   {"storage",  'S'},
-   {"messages", 'M'},
-   {"priority", 'p'},
-   {NULL,       0}
+   {"pool",             'P'},
+   {"fullpool",         'f'},
+   {"incrementalpool",  'i'},
+   {"differentialpool", 'd'},
+   {"level",            'L'},
+   {"storage",          'S'},
+   {"messages",         'M'},
+   {"priority",         'p'},
+   {NULL,                0}
 };
 
 /* 
@@ -222,6 +225,9 @@ void store_run(LEX *lc, struct res_items *item, int index, int pass)
               }
               break;
             case 'P':                 /* Pool */
+            case 'f':                 /* FullPool */
+            case 'i':                 /* IncPool */
+            case 'd':                 /* DifPool */
               token = lex_get_token(lc, T_NAME);
               if (pass == 2) {
                  res = GetResWithName(R_POOL, lc->str);
@@ -230,7 +236,20 @@ void store_run(LEX *lc, struct res_items *item, int index, int pass)
                                lc->str);
                     /* NOT REACHED */
                  }
-                 lrun.pool = (POOL *)res;
+                 switch(RunFields[i].token) {
+                  case 'P':
+                    lrun.pool = (POOL *)res;
+                    break;
+                  case 'f':
+                    lrun.full_pool = (POOL *)res;
+                    break;
+                  case 'i':
+                    lrun.inc_pool = (POOL *)res;
+                    break;
+                  case 'd':
+                    lrun.dif_pool = (POOL *)res;
+                    break;
+                 }
               }
               break;
             case 'S':                 /* storage */
index 974783556719bb4b454c94d5d64416fe8b37646d..3c7f52721d69d50f0cd85ce7049499db37f9b9a7 100644 (file)
@@ -146,6 +146,15 @@ JCR *wait_for_next_job(char *one_shot_job_to_run)
    if (run->pool) {
       jcr->pool = run->pool;         /* override pool */
    }
+   if (run->full_pool) {
+      jcr->pool = run->full_pool;     /* override full pool */
+   }
+   if (run->inc_pool) {
+      jcr->pool = run->inc_pool;      /* override inc pool */
+   }
+   if (run->dif_pool) {
+      jcr->pool = run->dif_pool;      /* override dif pool */
+   }
    if (run->storage) {
       jcr->store = run->storage;      /* override storage */
    }
index 6ba625abec1fb8043e9a0ec1c371a1e057e764a3..6ba94f151c74fff24151f074d3d1b5d9ef9ea1ca 100644 (file)
@@ -243,7 +243,7 @@ char *uar_full =
    "AND JobMedia.JobId=Job.JobId "
    "AND JobMedia.MediaId=Media.MediaId";
 
-char *uar_dec = 
+char *uar_dif = 
    "INSERT INTO temp SELECT Job.JobId,Job.JobTDate,Job.ClientId,"
    "Job.Level,Job.JobFiles,Job.StartTime,Media.VolumeName,JobMedia.StartFile,"
    "Job.VolSessionId,Job.VolSessionTime "
index b5ac957074701a0b482dffa27317921c41ded0a3..350631b88d52304f75a5c03a78e1bb15a2ba0d27 100644 (file)
@@ -80,6 +80,7 @@ static int mount_cmd(UAContext *ua, char *cmd);
 static int release_cmd(UAContext *ua, char *cmd);
 static int update_cmd(UAContext *ua, char *cmd);
 static int wait_cmd(UAContext *ua, char *cmd);
+static int setip_cmd(UAContext *ua, char *cmd);
 
 int quit_cmd(UAContext *ua, char *cmd);
 
@@ -110,6 +111,7 @@ static struct cmdstruct commands[] = {
  { N_("run"),        run_cmd,       _("run <job-name>")},
  { N_("status"),     status_cmd,    _("status [storage | client]=<name>")},
  { N_("setdebug"),   setdebug_cmd,  _("sets debug level")},
+ { N_("setip"),      setip_cmd,     _("sets new client address -- if authorized")},
  { N_("show"),       show_cmd,      _("show (resource records) [jobs | pools | ... | all]")},
  { N_("sqlquery"),   sqlquerycmd,   _("use SQL to query catalog")}, 
  { N_("time"),       time_cmd,      _("print current time")},
@@ -528,8 +530,8 @@ static int create_cmd(UAContext *ua, char *cmd)
 
    switch (create_pool(ua->jcr, ua->db, pool, POOL_OP_CREATE)) {
    case 0:
-      bsendmsg(ua, _("Error: Pool %s already exists.\n\
-Use update to change it.\n"), pool->hdr.name);
+      bsendmsg(ua, _("Error: Pool %s already exists.\n"
+               "Use update to change it.\n"), pool->hdr.name);
       break;
 
    case -1:
@@ -544,6 +546,34 @@ Use update to change it.\n"), pool->hdr.name);
 }
 
 
+/*
+ * Set a new address in a Client resource. We do this only
+ *  if the Console name is the same as the Client name 
+ *  and the Console can access the client.
+ */
+static int setip_cmd(UAContext *ua, char *cmd) 
+{
+   CLIENT *client;
+   if (!ua->cons && acl_access_ok(ua, Client_ACL, ua->cons->hdr.name)) {
+      bsendmsg(ua, _("Illegal command from this console.\n"));
+      return 1;
+   }
+   client = (CLIENT *)GetResWithName(R_CLIENT, ua->cons->hdr.name);
+
+   if (!client) {
+      bsendmsg(ua, _("Client \"%s\" not found.\n"), ua->cons->hdr.name);
+      return 1;
+   }
+   LockRes();
+   if (client->address) {
+      free(client->address);
+   }
+   client->address = bstrdup(inet_ntoa(ua->UA_sock->client_addr.sin_addr));
+   bsendmsg(ua, _("Client \"%s\" address set to %s\n"),
+           client->hdr.name, client->address);
+   UnlockRes();
+   return 1;
+}
 
 
 /*
index 2278405d8007e1169ba40b7bb68b577e3a7674a1..cccd7c86205654c9befa7bf32eef32f5d08d694b 100644 (file)
@@ -501,7 +501,7 @@ int prune_volume(UAContext *ua, MEDIA_DBR *mr)
       
    if (cnt.count == 0) {
       if (ua->verbose) {
-         bsendmsg(ua, "There are no Jobs associated with Volume %s. Marking it purged.\n",
+         bsendmsg(ua, "There are no Jobs associated with Volume \"%s\". Marking it purged.\n",
            mr->VolumeName);
       }
       stat = mark_media_purged(ua, mr);
@@ -558,7 +558,7 @@ int prune_volume(UAContext *ua, MEDIA_DBR *mr)
       free(del.JobId);
    }
    if (ua->verbose && del.num_del != 0) {
-      bsendmsg(ua, _("Pruned %d %s on Volume %s from catalog.\n"), del.num_del,
+      bsendmsg(ua, _("Pruned %d %s on Volume \"%s\" from catalog.\n"), del.num_del,
          del.num_del == 1 ? "Job" : "Jobs", mr->VolumeName);
    }
 
index dc4e15b27925c8891579dffcdd46f28b061aa4ce..137bd848837642435f62c3abc98dba8acd19a46b 100644 (file)
@@ -47,7 +47,7 @@ extern char *uar_del_temp,     *uar_del_temp1,   *uar_create_temp;
 extern char *uar_create_temp1,  *uar_last_full,   *uar_full;
 extern char *uar_inc,           *uar_list_temp,   *uar_sel_jobid_temp;
 extern char *uar_sel_all_temp1,  *uar_sel_fileset, *uar_mediatype;
-extern char *uar_jobid_fileindex, *uar_dec,       *uar_sel_all_temp;
+extern char *uar_jobid_fileindex, *uar_dif,       *uar_sel_all_temp;
 
 
 struct NAME_LIST {
@@ -115,11 +115,10 @@ static int get_date(UAContext *ua, char *date, int date_len);
 int restore_cmd(UAContext *ua, char *cmd)
 {
    RESTORE_CTX rx;                   /* restore context */
-   JOB *job = NULL;
+   JOB *job;
    int i;
 
    memset(&rx, 0, sizeof(rx));
-
    rx.path = get_pool_memory(PM_FNAME);
    rx.fname = get_pool_memory(PM_FNAME);
    rx.JobIds = get_pool_memory(PM_FNAME);
@@ -137,7 +136,7 @@ int restore_cmd(UAContext *ua, char *cmd)
 
    /* Ensure there is at least one Restore Job */
    LockRes();
-   while ( (job = (JOB *)GetNextRes(R_JOB, (RES *)job)) ) {
+   foreach_res(job, R_JOB) {
       if (job->JobType == JT_RESTORE) {
         if (!rx.restore_job) {
            rx.restore_job = job;
@@ -368,7 +367,7 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx)
       break;
    case 5:                           /* pool specified */
       i = find_arg_with_value(ua, "pool");
-      if (i >= 0) {
+      if (i >= 0 && acl_access_ok(ua, Pool_ACL, ua->argv[i])) {
         rx->pool = (POOL *)GetResWithName(R_POOL, ua->argv[i]);
       } else {
          bsendmsg(ua, _("Error: Pool resource \"%s\" does not exist.\n"), ua->argv[i]);
@@ -520,6 +519,11 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx)
            JobId, db_strerror(ua->db));
         return 0;
       }
+      if (!acl_access_ok(ua, Job_ACL, jr.Name)) {
+         bsendmsg(ua, _("No authorization. Job \"%s\" not selected.\n"), 
+           jr.Name);
+        continue; 
+      }
       rx->TotalFiles += jr.JobFiles;
    }
    return 1;
@@ -839,13 +843,13 @@ static int select_backups_before_date(UAContext *ua, RESTORE_CTX *rx, char *date
       goto bail_out;
    }
 
-   /* Now find most recent Decremental Job after Full save, if any */
-   Mmsg(&rx->query, uar_dec, edit_uint64(rx->JobTDate, ed1), date,
+   /* Now find most recent Differental Job after Full save, if any */
+   Mmsg(&rx->query, uar_dif, edit_uint64(rx->JobTDate, ed1), date,
        cr.ClientId, fsr.FileSet, pool_select);
    if (!db_sql_query(ua->db, rx->query, NULL, NULL)) {
       bsendmsg(ua, "%s\n", db_strerror(ua->db));
    }
-   /* Now update JobTDate to lock onto Decremental, if any */
+   /* Now update JobTDate to lock onto Differental, if any */
    rx->JobTDate = 0;
    if (!db_sql_query(ua->db, uar_sel_all_temp, last_full_handler, (void *)rx)) {
       bsendmsg(ua, "%s\n", db_strerror(ua->db));
@@ -855,7 +859,7 @@ static int select_backups_before_date(UAContext *ua, RESTORE_CTX *rx, char *date
       goto bail_out;
    }
 
-   /* Now find all Incremental Jobs after Full/Dec save */
+   /* Now find all Incremental Jobs after Full/dif save */
    Mmsg(&rx->query, uar_inc, edit_uint64(rx->JobTDate, ed1), date,
        cr.ClientId, fsr.FileSet, pool_select);
    if (!db_sql_query(ua->db, rx->query, NULL, NULL)) {
index c667a8f7d0801c29131293c49cd71b624e8d51ed..99df0d3a73a9827eed515bf4ef7cea5398424eff 100644 (file)
@@ -495,6 +495,10 @@ int select_pool_and_media_dbr(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr)
       bsendmsg(ua, "%s", db_strerror(ua->db));
       return 0;
    }
+   if (!acl_access_ok(ua, Pool_ACL, pr->Name)) {
+      bsendmsg(ua, _("No access to Pool \"%s\"\n"), pr->Name);
+      return 0;
+   }
    return 1;
 }
 
index 766c6cda6319607345b811e8c0c6740bce2bb4d2..796f9fc50699d0a3603167a73f55b15ec7a710df 100644 (file)
@@ -136,6 +136,9 @@ static void do_all_status(UAContext *ua, char *cmd)
    i = 0;
    foreach_res(store, R_STORAGE) {
       found = false;
+      if (!acl_access_ok(ua, Storage_ACL, store->hdr.name)) {
+        continue;
+      }
       for (j=0; j<i; j++) {
         if (strcmp(unique_store[j]->address, store->address) == 0 &&
             unique_store[j]->SDport == store->SDport) {
@@ -167,6 +170,9 @@ static void do_all_status(UAContext *ua, char *cmd)
    i = 0;
    foreach_res(client, R_CLIENT) {
       found = false;
+      if (!acl_access_ok(ua, Client_ACL, client->hdr.name)) {
+        continue;
+      }
       for (j=0; j<i; j++) {
         if (strcmp(unique_client[j]->address, client->address) == 0 &&
             unique_client[j]->FDport == client->FDport) {
@@ -348,6 +354,9 @@ static void list_scheduled_jobs(UAContext *ua)
    /* Loop through all jobs */
    LockRes();
    foreach_res(job, R_JOB) {
+      if (!acl_access_ok(ua, Job_ACL, job->hdr.name)) {
+        continue;
+      }
       for (run=NULL; (run = find_next_run(run, job, runtime)); ) {
         level = job->level;   
         if (run->level) {
@@ -404,6 +413,9 @@ static void list_running_jobs(UAContext *ua)
    bsendmsg(ua, _("Level JobId  Job                        Status\n"));
    bsendmsg(ua, _("====================================================================\n"));
    for (jcr=NULL; (jcr=get_next_jcr(jcr)); njobs++) {
+      if (!acl_access_ok(ua, Job_ACL, jcr->job->hdr.name)) {
+        continue;
+      }
       if (jcr->JobId == 0) {     /* this is us */
         njobs--;
         free_locked_jcr(jcr);
index 3cd1702fe5ff0dac0c1777db21204a77b597f4b4..74518b63d126622914e8a833acb8d359a4da539e 100644 (file)
@@ -141,6 +141,9 @@ struct JCR {
    STORE *store;                      /* Storage resource */
    CLIENT *client;                    /* Client resource */
    POOL *pool;                        /* Pool resource */
+   POOL *full_pool;                   /* Full backup pool resource */
+   POOL *inc_pool;                    /* Incremental backup pool resource */
+   POOL *dif_pool;                    /* Differential backup pool resource */
    FILESET *fileset;                  /* FileSet resource */
    CAT *catalog;                      /* Catalog resource */
    MSGS *messages;                    /* Default message handler */
index 692ec0d219106fc81dc62eee17cf3dd1e6e4bfd8..b403d8294a102f3073543967d28ac0cdcdb14793 100755 (executable)
@@ -69,7 +69,7 @@ extern struct s_res resources[];
 extern CURES res_all;
 extern int res_all_size;
 
-static int res_locked = 0;            /* set when resource chains locked */
+static bool res_locked = false;        /* set when resource chains locked */
 
 /* Forward referenced subroutines */
 static void scan_types(LEX *lc, MSGS *msg, int dest, char *where, char *cmd);
@@ -579,12 +579,12 @@ void store_yesno(LEX *lc, struct res_items *item, int index, int pass)
 void LockRes()
 {
    P(res_mutex);
-   res_locked = 1;
+   res_locked = true;
 }
 
 void UnlockRes()
 {
-   res_locked = 0;
+   res_locked = false;
    V(res_mutex);
 }
 
index 5ab474a756786620b900c027c64c36cf2c32c192..7573f56a936a16c9595a3bf181642427e8554dd1 100644 (file)
@@ -262,7 +262,6 @@ int dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec)
 }
 
 
-
 /*
  *   Request the sysop to create an appendable volume
  *
@@ -285,6 +284,7 @@ int dir_ask_sysop_to_create_appendable_volume(JCR *jcr, DEVICE *dev)
 {
    int stat = 0, jstat;
    bool unmounted;
+   bool first = true;
 
    Dmsg0(130, "enter dir_ask_sysop_to_create_appendable_volume\n");
    ASSERT(dev->dev_blocked);
@@ -296,7 +296,8 @@ int dir_ask_sysop_to_create_appendable_volume(JCR *jcr, DEVICE *dev)
          Jmsg(jcr, M_INFO, 0, "%s", dev->errmsg);
         return 0;
       }
-      if (dir_find_next_appendable_volume(jcr)) {    /* get suggested volume */
+      /* First pass, we *know* there are no appendable volumes, so no need to call */
+      if (!first && dir_find_next_appendable_volume(jcr)) { /* get suggested volume */
         jstat = JS_WaitMount;
         unmounted = (dev->dev_blocked == BST_UNMOUNTED) ||
                     (dev->dev_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP);
@@ -312,12 +313,14 @@ int dir_ask_sysop_to_create_appendable_volume(JCR *jcr, DEVICE *dev)
             Dmsg0(100, "Return 1 from mount without wait.\n");
            return 1;
         }
-        Jmsg(jcr, M_MOUNT, 0, _(
+        if (!dev->poll) {
+           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);
-         Dmsg3(190, "Mount %s on %s for Job %s\n",
-               jcr->VolumeName, jcr->dev_name, jcr->Job);
+            Dmsg3(190, "Mount %s on %s for Job %s\n",
+                 jcr->VolumeName, jcr->dev_name, jcr->Job);
+        }
       } else {
         jstat = JS_WaitMedia;
         if (!dev->poll) {
@@ -333,6 +336,7 @@ Please use the \"label\"  command to create a new Volume for:\n\
               jcr->pool_name);
         }
       }
+      first = false;
 
       jcr->JobStatus = jstat;
       dir_send_job_status(jcr);
index c1ffd586681057f65e3a787ec52a6ad8be2726fc..b41fa72c2887970bbddaea5f0ddae7b5a70ae26b 100644 (file)
@@ -31,9 +31,9 @@
 
 /* #define NEW_LOCK 1 */
 
-#define new_lock_device(dev)            _new_lock_device(__FILE__, __LINE__, (dev)) 
+#define new_lock_device(dev)             _new_lock_device(__FILE__, __LINE__, (dev)) 
 #define new_lock_device_state(dev,state) _new_lock_device(__FILE__, __LINE__, (dev), (state))
-#define new_unlock_device(dev)          _new_unlock_device(__FILE__, __LINE__, (dev))
+#define new_unlock_device(dev)           _new_unlock_device(__FILE__, __LINE__, (dev))
 
 #define lock_device(d) _lock_device(__FILE__, __LINE__, (d))
 #define unlock_device(d) _unlock_device(__FILE__, __LINE__, (d))
 #define give_back_device_lock(d, p) _give_back_device_lock(__FILE__, __LINE__, (d), (p))
 
 /* Arguments to open_dev() */
-#define READ_WRITE      0
-#define READ_ONLY       1
+#define READ_WRITE       0
+#define READ_ONLY        1
 #define OPEN_READ_WRITE  0
-#define OPEN_READ_ONLY  1
+#define OPEN_READ_ONLY   1
 #define OPEN_WRITE_ONLY  2
 
 /* Generic status bits returned from status_dev() */
-#define BMT_TAPE          (1<<0)     /* is tape device */
-#define BMT_EOF           (1<<1)     /* just read EOF */
-#define BMT_BOT           (1<<2)     /* at beginning of tape */
-#define BMT_EOT           (1<<3)     /* end of tape reached */
-#define BMT_SM            (1<<4)     /* DDS setmark */
-#define BMT_EOD           (1<<5)     /* DDS at end of data */
-#define BMT_WR_PROT       (1<<6)     /* tape write protected */
-#define BMT_ONLINE        (1<<7)     /* tape online */
-#define BMT_DR_OPEN       (1<<8)     /* tape door open */
-#define BMT_IM_REP_EN     (1<<9)     /* immediate report enabled */
+#define BMT_TAPE           (1<<0)     /* is tape device */
+#define BMT_EOF            (1<<1)     /* just read EOF */
+#define BMT_BOT            (1<<2)     /* at beginning of tape */
+#define BMT_EOT            (1<<3)     /* end of tape reached */
+#define BMT_SM             (1<<4)     /* DDS setmark */
+#define BMT_EOD            (1<<5)     /* DDS at end of data */
+#define BMT_WR_PROT        (1<<6)     /* tape write protected */
+#define BMT_ONLINE         (1<<7)     /* tape online */
+#define BMT_DR_OPEN        (1<<8)     /* tape door open */
+#define BMT_IM_REP_EN      (1<<9)     /* immediate report enabled */
 
 
 /* Test capabilities */
 #define dev_cap(dev, cap) ((dev)->capabilities & (cap))
 
 /* Bits for device capabilities */
-#define CAP_EOF           (1<<0)     /* has MTWEOF */
-#define CAP_BSR           (1<<1)     /* has MTBSR */
-#define CAP_BSF           (1<<2)     /* has MTBSF */
-#define CAP_FSR           (1<<3)     /* has MTFSR */
-#define CAP_FSF           (1<<4)     /* has MTFSF */
-#define CAP_EOM           (1<<5)     /* has MTEOM */
-#define CAP_REM           (1<<6)     /* is removable media */
-#define CAP_RACCESS       (1<<7)     /* is random access device */
-#define CAP_AUTOMOUNT     (1<<8)     /* Read device at start to see what is there */
-#define CAP_LABEL         (1<<9)     /* Label blank tapes */
-#define CAP_ANONVOLS      (1<<10)    /* Mount without knowing volume name */
-#define CAP_ALWAYSOPEN    (1<<11)    /* always keep device open */
+#define CAP_EOF            (1<<0)     /* has MTWEOF */
+#define CAP_BSR            (1<<1)     /* has MTBSR */
+#define CAP_BSF            (1<<2)     /* has MTBSF */
+#define CAP_FSR            (1<<3)     /* has MTFSR */
+#define CAP_FSF            (1<<4)     /* has MTFSF */
+#define CAP_EOM            (1<<5)     /* has MTEOM */
+#define CAP_REM            (1<<6)     /* is removable media */
+#define CAP_RACCESS        (1<<7)     /* is random access device */
+#define CAP_AUTOMOUNT      (1<<8)     /* Read device at start to see what is there */
+#define CAP_LABEL          (1<<9)     /* Label blank tapes */
+#define CAP_ANONVOLS       (1<<10)    /* Mount without knowing volume name */
+#define CAP_ALWAYSOPEN     (1<<11)    /* always keep device open */
 #define CAP_AUTOCHANGER    (1<<12)    /* AutoChanger */
 #define CAP_OFFLINEUNMOUNT (1<<13)    /* Offline before unmount */
-#define CAP_STREAM        (1<<14)    /* Stream device */
-#define CAP_BSFATEOM      (1<<15)    /* Backspace file at EOM */
-#define CAP_FASTFSF       (1<<16)    /* Fast forward space file */
-#define CAP_TWOEOF        (1<<17)    /* Write two eofs for EOM */
+#define CAP_STREAM         (1<<14)    /* Stream device */
+#define CAP_BSFATEOM       (1<<15)    /* Backspace file at EOM */
+#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 */
 
 /* Test state */
 #define dev_state(dev, st_state) ((dev)->state & (st_state))
 
 /* Device state bits */
-#define ST_OPENED         (1<<0)     /* set when device opened */
-#define ST_TAPE           (1<<1)     /* is a tape device */  
-#define ST_FILE           (1<<2)     /* is a file device */
-#define ST_FIFO           (1<<3)     /* is a fifo device */
-#define ST_PROG           (1<<4)     /* is a program device */
-#define ST_LABEL          (1<<5)     /* label found */
+#define ST_OPENED          (1<<0)     /* set when device opened */
+#define ST_TAPE            (1<<1)     /* is a tape device */  
+#define ST_FILE            (1<<2)     /* is a file device */
+#define ST_FIFO            (1<<3)     /* is a fifo device */
+#define ST_PROG            (1<<4)     /* is a program device */
+#define ST_LABEL           (1<<5)     /* label found */
 #define ST_MALLOC          (1<<6)     /* dev packet malloc'ed in init_dev() */
-#define ST_APPEND         (1<<7)     /* ready for Bacula append */
-#define ST_READ           (1<<8)     /* ready for Bacula read */
-#define ST_EOT            (1<<9)     /* at end of tape */
-#define ST_WEOT           (1<<10)    /* Got EOT on write */
-#define ST_EOF            (1<<11)    /* Read EOF i.e. zero bytes */
-#define ST_NEXTVOL        (1<<12)    /* Start writing on next volume */
-#define ST_SHORT          (1<<13)    /* Short block read */
+#define ST_APPEND          (1<<7)     /* ready for Bacula append */
+#define ST_READ            (1<<8)     /* ready for Bacula read */
+#define ST_EOT             (1<<9)     /* at end of tape */
+#define ST_WEOT            (1<<10)    /* Got EOT on write */
+#define ST_EOF             (1<<11)    /* Read EOF i.e. zero bytes */
+#define ST_NEXTVOL         (1<<12)    /* Start writing on next volume */
+#define ST_SHORT           (1<<13)    /* Short block read */
 
 /* dev_blocked states (mutually exclusive) */
 #define BST_NOT_BLOCKED       0       /* not blocked */
-#define BST_UNMOUNTED        1       /* User unmounted device */
+#define BST_UNMOUNTED         1       /* User unmounted device */
 #define BST_WAITING_FOR_SYSOP 2       /* Waiting for operator to mount tape */
 #define BST_DOING_ACQUIRE     3       /* Opening/validating/moving tape */
 #define BST_WRITING_LABEL     4       /* Labeling a tape */  
 #define BST_UNMOUNTED_WAITING_FOR_SYSOP 5 /* Closed by user during mount request */
-#define BST_MOUNT            6       /* Mount request */
+#define BST_MOUNT             6       /* Mount request */
 
 /* Volume Catalog Information structure definition */
 struct VOLUME_CAT_INFO {
    /* Media info for the current Volume */
-   uint32_t VolCatJobs;              /* number of jobs on this Volume */
-   uint32_t VolCatFiles;             /* Number of files */
-   uint32_t VolCatBlocks;            /* Number of blocks */
-   uint64_t VolCatBytes;             /* Number of bytes written */
-   uint32_t VolCatMounts;            /* Number of mounts this volume */
-   uint32_t VolCatErrors;            /* Number of errors this volume */
-   uint32_t VolCatWrites;            /* Number of writes this volume */
-   uint32_t VolCatReads;             /* Number of reads this volume */
-   uint64_t VolCatRBytes;            /* Number of bytes read */
-   uint32_t VolCatRecycles;          /* Number of recycles this volume */
-   int32_t  Slot;                    /* Slot in changer */
-   bool     InChanger;               /* Set if vol in current magazine */
-   uint32_t VolCatMaxJobs;           /* Maximum Jobs to write to volume */
-   uint32_t VolCatMaxFiles;          /* Maximum files to write to volume */
-   uint64_t VolCatMaxBytes;          /* Max bytes to write to volume */
+   uint32_t VolCatJobs;               /* number of jobs on this Volume */
+   uint32_t VolCatFiles;              /* Number of files */
+   uint32_t VolCatBlocks;             /* Number of blocks */
+   uint64_t VolCatBytes;              /* Number of bytes written */
+   uint32_t VolCatMounts;             /* Number of mounts this volume */
+   uint32_t VolCatErrors;             /* Number of errors this volume */
+   uint32_t VolCatWrites;             /* Number of writes this volume */
+   uint32_t VolCatReads;              /* Number of reads this volume */
+   uint64_t VolCatRBytes;             /* Number of bytes read */
+   uint32_t VolCatRecycles;           /* Number of recycles this volume */
+   int32_t  Slot;                     /* Slot in changer */
+   bool     InChanger;                /* Set if vol in current magazine */
+   uint32_t VolCatMaxJobs;            /* Maximum Jobs to write to volume */
+   uint32_t VolCatMaxFiles;           /* Maximum files to write to volume */
+   uint64_t VolCatMaxBytes;           /* Max bytes to write to volume */
    uint64_t VolCatCapacityBytes;      /* capacity estimate */
-   uint64_t VolReadTime;             /* time spent reading */
-   uint64_t VolWriteTime;            /* time spent writing this Volume */
-   char VolCatStatus[20];            /* Volume status */
+   uint64_t VolReadTime;              /* time spent reading */
+   uint64_t VolWriteTime;             /* time spent writing this Volume */
+   char VolCatStatus[20];             /* Volume status */
    char VolCatName[MAX_NAME_LENGTH];  /* Desired volume to mount */
-};               
+};                
 
 
 typedef struct s_steal_lock {
-   pthread_t        no_wait_id;      /* id of no wait thread */
-   int              dev_blocked;     /* state */
-   int              dev_prev_blocked; /* previous blocked state */
+   pthread_t         no_wait_id;      /* id of no wait thread */
+   int               dev_blocked;     /* state */
+   int               dev_prev_blocked; /* previous blocked state */
 } bsteal_lock_t;
 
-struct DEVRES;                       /* Device resource defined in stored_conf.h */
+struct DEVRES;                        /* Device resource defined in stored_conf.h */
 
 /* Device structure definition */
 struct DEVICE {
 public:
-   DEVICE *next;                     /* pointer to next open device */
-   DEVICE *prev;                     /* pointer to prev open device */
-   JCR *attached_jcrs;               /* attached JCR list */
-   pthread_mutex_t mutex;            /* access control */
-   pthread_cond_t wait;              /* thread wait variable */
+   DEVICE *next;                      /* pointer to next open device */
+   DEVICE *prev;                      /* pointer to prev open device */
+   JCR *attached_jcrs;                /* attached JCR list */
+   pthread_mutex_t mutex;             /* access control */
+   pthread_cond_t wait;               /* thread wait variable */
    pthread_cond_t wait_next_vol;      /* wait for tape to be mounted */
-   pthread_t no_wait_id;             /* this thread must not wait */
-   int dev_blocked;                  /* set if we must wait (i.e. change tape) */
-   int dev_prev_blocked;             /* previous blocked state */
-   int num_waiting;                  /* number of threads waiting */
-   int num_writers;                  /* number of writing threads */
-   int use_count;                    /* usage count on this device */
-   int fd;                           /* file descriptor */
-   int capabilities;                 /* capabilities mask */
-   int state;                        /* state mask */
-   int dev_errno;                    /* Our own errno */
-   int mode;                         /* read/write modes */
-   char *dev_name;                   /* device name */
-   char *errmsg;                     /* nicely edited error message */
-   uint32_t block_num;               /* current block number base 0 */
-   uint32_t file;                    /* current file number base 0 */
-   uint64_t file_addr;               /* Current file read/write address */
-   uint32_t EndBlock;                /* last block written */
-   uint32_t EndFile;                 /* last file written */
-   uint32_t min_block_size;          /* min block size */
-   uint32_t max_block_size;          /* max block size */
-   uint64_t max_volume_size;         /* max bytes to put on one volume */
-   uint64_t max_file_size;           /* max file size to put in one file on volume */
-   uint64_t volume_capacity;         /* advisory capacity */
-   uint32_t max_rewind_wait;         /* max secs to allow for rewind */
-   uint32_t max_open_wait;           /* max secs to allow for open */
-   uint32_t max_open_vols;           /* max simultaneous open volumes */
-   utime_t  vol_poll_interval;       /* interval between polling Vol mount */
-   DEVRES *device;                   /* pointer to Device Resource */
-   btimer_id tid;                    /* timer id */
-
-   VOLUME_CAT_INFO VolCatInfo;       /* Volume Catalog Information */
-   VOLUME_LABEL VolHdr;              /* Actual volume label */
+   pthread_t no_wait_id;              /* this thread must not wait */
+   int dev_blocked;                   /* set if we must wait (i.e. change tape) */
+   int dev_prev_blocked;              /* previous blocked state */
+   int num_waiting;                   /* number of threads waiting */
+   int num_writers;                   /* number of writing threads */
+   int use_count;                     /* usage count on this device */
+   int fd;                            /* file descriptor */
+   int capabilities;                  /* capabilities mask */
+   int state;                         /* state mask */
+   int dev_errno;                     /* Our own errno */
+   int mode;                          /* read/write modes */
+   char *dev_name;                    /* device name */
+   char *errmsg;                      /* nicely edited error message */
+   uint32_t block_num;                /* current block number base 0 */
+   uint32_t file;                     /* current file number base 0 */
+   uint64_t file_addr;                /* Current file read/write address */
+   uint32_t EndBlock;                 /* last block written */
+   uint32_t EndFile;                  /* last file written */
+   uint32_t min_block_size;           /* min block size */
+   uint32_t max_block_size;           /* max block size */
+   uint64_t max_volume_size;          /* max bytes to put on one volume */
+   uint64_t max_file_size;            /* max file size to put in one file on volume */
+   uint64_t volume_capacity;          /* advisory capacity */
+   uint32_t max_rewind_wait;          /* max secs to allow for rewind */
+   uint32_t max_open_wait;            /* max secs to allow for open */
+   uint32_t max_open_vols;            /* max simultaneous open volumes */
+   utime_t  vol_poll_interval;        /* interval between polling Vol mount */
+   DEVRES *device;                    /* pointer to Device Resource */
+   btimer_id tid;                     /* timer id */
+
+   VOLUME_CAT_INFO VolCatInfo;        /* Volume Catalog Information */
+   VOLUME_LABEL VolHdr;               /* Actual volume label */
    
    /* Device wait times ***FIXME*** look at durations */
    char BadVolName[MAX_NAME_LENGTH];  /* Last wrong Volume mounted */
-   bool poll;                        /* set to poll Volume */
+   bool poll;                         /* set to poll Volume */
    int min_wait;
    int max_wait;
    int max_num_wait;
@@ -206,7 +207,7 @@ public:
  *  dependent. Arrgggg!
  */
 #ifndef MTEOM
-#ifdef MTSEOD
+#ifdef  MTSEOD
 #define MTEOM MTSEOD
 #endif
 #ifdef MTEOD
index 90c96bdd595f7ee959f845cc5d91b6ce674d005e..3f70d8d174e9dddd278d07d6a26b144fa0726745 100644 (file)
@@ -80,12 +80,13 @@ mount_next_vol:
     * Get Director's idea of what tape we should have mounted. 
     *   in jcr->VolCatInfo
     */
-   Dmsg0(100, "Before dir_find_next\n");
+   Dmsg0(200, "Before dir_find_next_appendable_volume.\n");
    while (!dir_find_next_appendable_volume(jcr)) {
-       Dmsg0(100, "not dir_find_next\n");
+       Dmsg0(200, "not dir_find_next\n");
        if (!dir_ask_sysop_to_create_appendable_volume(jcr, dev)) {
         return 0;
        }
+       Dmsg0(200, "Again dir_find_next_append...\n");
    }
    if (job_canceled(jcr)) {
       return 0;
@@ -131,6 +132,10 @@ mount_next_vol:
    }
    Dmsg1(100, "want vol=%s\n", jcr->VolumeName);
 
+   if (dev->poll && dev_cap(dev, CAP_CLOSEONPOLL)) {
+      force_close_dev(dev);
+   }
+
    /* Open device */
    if  (!(dev_state(dev, ST_OPENED))) {
        int mode;
index eb2ede2a4143218729a1b73fa6281268e6fb316c..206b0cb4416b758e69ff68b97b5cb3784ea9e5b8 100644 (file)
@@ -100,6 +100,7 @@ static struct res_items dev_items[] = {
    {"labelmedia",            store_yesno,  ITEM(res_dev.cap_bits), CAP_LABEL,      ITEM_DEFAULT, 0},
    {"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},
    {"changerdevice",         store_strname,ITEM(res_dev.changer_name), 0, 0, 0},
    {"changercommand",        store_strname,ITEM(res_dev.changer_command), 0, 0, 0},
    {"maximumchangerwait",    store_pint,   ITEM(res_dev.max_changer_wait), 0, ITEM_DEFAULT, 5 * 60},
index 54ae8eb9b13621133646ff043a18d96f7368a5d6..1718eaff352008cbf88c94781585cee97549aff4 100644 (file)
@@ -2,8 +2,8 @@
 #undef  VERSION
 #define VERSION "1.33"
 #define VSTRING "1"
-#define BDATE   "16 Jan 2004"
-#define LSMDATE "16Jan04"
+#define BDATE   "22 Jan 2004"
+#define LSMDATE "22Jan04"
 
 /* Debug flags */
 #undef  DEBUG