]> git.sur5r.net Git - bacula/bacula/commitdiff
OK, ANSI labels seem to be working now
authorKern Sibbald <kern@sibbald.com>
Fri, 4 Feb 2005 11:06:08 +0000 (11:06 +0000)
committerKern Sibbald <kern@sibbald.com>
Fri, 4 Feb 2005 11:06:08 +0000 (11:06 +0000)
git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@1814 91ce42f0-d328-0410-95d8-f526ca767f89

14 files changed:
bacula/ReleaseNotes
bacula/src/dird/dird_conf.c
bacula/src/dird/protos.h
bacula/src/dird/ua_input.c
bacula/src/dird/ua_label.c
bacula/src/findlib/fstype.c
bacula/src/lib/parse_conf.c
bacula/src/lib/parse_conf.h
bacula/src/stored/dev.c
bacula/src/stored/dev.h
bacula/src/stored/label.c
bacula/src/stored/stored_conf.c
bacula/src/stored/stored_conf.h
bacula/src/version.h

index d8bd80297d9824c32411e739c28a7250bd140475..29c16fdff23f8688c54fa8f8631e12eb5d024d2b 100644 (file)
 
           Release Notes for Bacula 1.37.3
 
-  Bacula code: Total files = 411 Total lines = 121,855 (*.h *.c *.in)
+  Bacula code: Total files = 411 Total lines = 122,189 (*.h *.c *.in)
 
 
 Major Changes:
 - This version has a new database format that is not compatible
-  with previous databases. There are NO upgrade scripts yet.
-- Due to the massive changes made during the last two weeks, 
-  version 1.37.3 should be considered unstable.  It does, however,
-  pass the regression tests.
-- SQLite3 support.
+  with previous databases. The upgrade scripts should work, but
+  they are not yet tested.
+- SQLite3 support, but it seems to run at 1/2 to 1/4 the speed of
+  SQLite2.
 - First cut at ANSI labels.
 - New communications protocol between DIR and SD to reserve 
-  drives.
+  drives. The DIR and SD are no longer compatible with 1.36 or
+  lower versions.
+- Preliminary Python Event support has been added. See below for
+  configuration and details.
+- DVD writing support, using parts, and a lot of new directives in
+  the Device resource of the Storage configuration file.
+- Seven new options keywords in a FileSet resource:
+  ignorecase, fstype, hfsplussupport, wilddir, wildfile, regexdir,
+  and regexfile. See below for details.
+
+New Directives:
+- New Options keywords in a FileSet directive:
+  - WildDir xxx
+    Will do a wild card match against directories (files will not
+    be matched).
+  - WildFile xxx
+    Will do a wild card match against files (directories will not
+    be matched).
+  - RegexDir xxx
+    Will do a regular expression match against directories (files
+    will not be matched).
+  - RegexFile xxx
+    Will do a regular expression match against files( directories
+    will not be matched).
+  - IgnoreCase = yes | no
+    Will ignore case in wild card and regular expression matches.
+    This is handy for Windows where filename case is not significant.
+  - FsType = string
+    where string is a filesystem type: ext2, jfs, ntfs, proc,
+    reiserfs, xfs, usbdevfs, sysfs, smbfs, iso9660.  For ext3
+    systems, use ext2.  You may have multiple fstype directives
+    and thus permit multiple filesystem types.  If the type
+    specified on the fstype directive does not match the
+    filesystem for a particular directive, that directory will
+    not be backed up.  This directive can be used to prevent
+    backing up non-local filesystems.
+  - HFS Plus Support = yes | no 
+    If set, Mac OS X resource forks will be saved and restored.
+- Label Type = ANSI | IBM | Bacula   
+  Implemented in Director Pool resource and in SD Device resource.
+  If it is specified in the SD Device resource, it will take
+  precedence over the value passed from the Director to the SD.
+  IBM is not yet implemented.
+- Check Labels = yes | no
+  Implemented in the SD Device resource. If you intend to read
+  ANSI or IBM labels, this *must* be set. Even if the volume
+  is not ANSI labeled, you can set this to yes, and Bacula will
+  check the label type.
+- Scripts Directory = <directory> name.  Defines the directory from 
+  which Bacula scripts will be called for events. In fact, Bacula
+  appends this name to the standard Python list of search directories,
+  so the script could also be in any of the Python system directories.
+- In FileSet, you can exclude backing up of hardlinks (if you have
+  a lot, it can be very expensive), by using:
+    HardLinks = no
+  in the Options section. Patch supplied by David R Bosso. Thanks.
+- MaximumPartSize = bytes (SD, Device resource)
+  Defines the maximum part size.
+- Requires Mount = Yes/No (SD, Device resource)
+  Defines if the device require to be mounted to be read, and if it
+  must be written in a special way. If it set, the following directives 
+  must be defined in the same Device resource:
+  + Mount Point = directory
+    Directory where the device must be mounted. 
+  + Mount Command = name-string
+    Command that must be executed to mount the device. Before the command
+    is executed, %a is replaced with the Archive Device, and %m with the 
+    Mount Point.
+  + Unmount Command = name-string
+    Command that must be executed to unmount the device. Before the 
+    command is executed, %a is replaced with the Archive Device, and 
+    %m with the Mount Point.
+  + Write Part Command = name-string
+    Command that must be executed to write a part to the device. Before
+    the command is executed, %a is replaced with the Archive Device, %m 
+    with the Mount Point, %n with the current part number (0-based), 
+    and %v with the current part filename.
+  + Free Space Command = name-string
+    Command that must be executed to check how much free space is left 
+    on the device. Before the command is executed, %a is replaced with 
+    the Archive Device, %m with the Mount Point, %n with the current part
+    number (0-based), and %v with the current part filename.
+- Write Part After Job = Yes/No (DIR, Job Resource, and Schedule Resource)
+  If this directive is set to yes (default no), a new part file will be
+  created after the job is finished.
 
+New Commands:
+- "python restart" restarts the Python interpreter. Rather brutal, make
+   sure no Python scripts are running. This permits you to change
+   a Python script and get Bacula to use the new script.
 
-- Preliminary Python Event support has been added. See below for
-  configuration.
+Items to note!!!
+- You must add --with-python=[DIR] to the configure command line
+  if you want Python support.  Python 2.2 and 2.3 should be automatically
+  detected if in the standard place.
+- With Python 2.2 version, the link of the Director gets a few linker
+  warnings due to the fact that Python pulls in some old non-secure
+  libraries.
+- With Python 2.3, there are a few compiler warnings.
+- You must either create a new catalog database or upgrade your
+  old database (upgrade scripts not yet tested).
+
+Other Items:
+- 2 new scripts, dvd-writepart and dvd-freespace, in the scripts directory,
+  which are designed to be used as parameters to Write Part Command and
+  Free Space Command. They need the dvd+rw-tools to be installed
+  (http://fy.chalmers.se/~appro/linux/DVD+RW/).
+- Part files support: File volumes can now be splitted in multiple
+  files, called "parts".
+- Python scripting support:
   A Python script will be called at particular points or conditions
   in Bacula called Events. The currently defined Events are called:
 
@@ -97,66 +201,5 @@ def NewVolume(j):
     bacula.set(jcr=j, VolumeName="TestA-001")
     return 1
 ====
-- Part files support: File volumes can now be splitted in multiple
-  files, called "parts".
-- DVD writing support, using parts, and a lot of new directives in
-  the Device resource of the Storage configuration file.
-
-New Directives:
-- Scripts Directory = <directory> name.  Defines the directory from 
-  which Bacula scripts will be called for events. In fact, Bacula
-  appends this name to the standard Python list of search directories,
-  so the script could also be in any of the Python system directories.
-- In FileSet, you can exclude backing up of hardlinks (if you have
-  a lot, it can be very expensive), by using:
-    HardLinks = no
-  in the Options section. Patch supplied by David R Bosso. Thanks.
-- MaximumPartSize = bytes (SD, Device resource)
-  Defines the maximum part size.
-- Requires Mount = Yes/No (SD, Device resource)
-  Defines if the device require to be mounted to be read, and if it
-  must be written in a special way. If it set, the following directives 
-  must be defined in the same Device resource:
-  + Mount Point = directory
-    Directory where the device must be mounted. 
-  + Mount Command = name-string
-    Command that must be executed to mount the device. Before the command
-    is executed, %a is replaced with the Archive Device, and %m with the 
-    Mount Point.
-  + Unmount Command = name-string
-    Command that must be executed to unmount the device. Before the 
-    command is executed, %a is replaced with the Archive Device, and 
-    %m with the Mount Point.
-  + Write Part Command = name-string
-    Command that must be executed to write a part to the device. Before
-    the command is executed, %a is replaced with the Archive Device, %m 
-    with the Mount Point, %n with the current part number (0-based), 
-    and %v with the current part filename.
-  + Free Space Command = name-string
-    Command that must be executed to check how much free space is left 
-    on the device. Before the command is executed, %a is replaced with 
-    the Archive Device, %m with the Mount Point, %n with the current part
-    number (0-based), and %v with the current part filename.
-- Write Part After Job = Yes/No (DIR, Job Resource, and Schedule Resource)
-  If this directive is set to yes (default no), a new part file will be
-  created after the job is finished.
 
-New Commands:
-- "python restart" restarts the Python interpreter. Rather brutal, make
-   sure no Python scripts are running. This permits you to change
-   a Python script and get Bacula to use the new script.
 
-Items to note!!!
-- You must add --with-python=[DIR] to the configure command line
-  if you want Python support.  Python 2.2 and 2.3 should be automatically
-  detected if in the standard place.
-- With Python 2.2 version, the link of the Director gets a few linker
-  warnings due to the fact that Python pulls in some old non-secure
-  libraries.
-- With Python 2.3, there are a few compiler warnings.
-
-Other Items:
-- 2 new scripts, dvd-writepart and dvd-freespace, in the scripts directory,
-  which are designed to be used as parameters to Write Part Command and
-  Free Space Command. They need the dvd+rw-tools to be installed
-  (http://fy.chalmers.se/~appro/linux/DVD+RW/).
index 51cae8486440c5b9064a038c76cf32459c2b186d..5b812ead8eeedc653427de8256c7404ecce41940 100644 (file)
@@ -63,7 +63,6 @@ extern void store_inc(LEX *lc, RES_ITEM *item, int index, int pass);
 
 void store_jobtype(LEX *lc, RES_ITEM *item, int index, int pass);
 void store_level(LEX *lc, RES_ITEM *item, int index, int pass);
-void store_label(LEX *lc, RES_ITEM *item, int index, int pass);
 void store_replace(LEX *lc, RES_ITEM *item, int index, int pass);
 void store_acl(LEX *lc, RES_ITEM *item, int index, int pass);
 static void store_device(LEX *lc, RES_ITEM *item, int index, int pass);
@@ -377,40 +376,6 @@ struct s_jt jobtypes[] = {
    {NULL,           0}
 };
 
-/* 
- * Tape Label types permitted in Pool records 
- *
- *   tape label      label code = token
- */
-struct s_kw tapelabels[] = {
-   {"bacula",        B_BACULA_LABEL},
-   {"ansi",          B_ANSI_LABEL},
-   {"ibm",           B_IBM_LABEL},
-   {NULL,           0}
-};
-
-
-#ifdef old_deprecated_code
-
-/* Keywords (RHS) permitted in Backup and Verify records */
-static struct s_kw BakVerFields[] = {
-   {"client",        'C'},
-   {"fileset",       'F'},
-   {"level",         'L'},
-   {NULL,           0}
-};
-
-/* Keywords (RHS) permitted in Restore records */
-static struct s_kw RestoreFields[] = {
-   {"client",        'C'},
-   {"fileset",       'F'},
-   {"jobid",         'J'},            /* JobId to restore */
-   {"where",         'W'},            /* root of restore */
-   {"replace",       'R'},            /* replacement options */
-   {"bootstrap",     'B'},            /* bootstrap file */
-   {NULL,             0}
-};
-#endif
 
 /* Options permitted in Restore replace= */
 struct s_kw ReplaceOptions[] = {
@@ -1300,32 +1265,6 @@ void store_level(LEX *lc, RES_ITEM *item, int index, int pass)
 }
 
 
-/*
- * Store Tape Label Type (Bacula, ANSI, IBM)
- *
- */
-void store_label(LEX *lc, RES_ITEM *item, int index, int pass)
-{
-   int token, i;
-
-   token = lex_get_token(lc, T_NAME);
-   /* Store the label pass 2 so that type is defined */
-   for (i=0; tapelabels[i].name; i++) {
-      if (strcasecmp(lc->str, tapelabels[i].name) == 0) {
-        *(int *)(item->value) = tapelabels[i].token;
-        i = 0;
-        break;
-      }
-   }
-   if (i != 0) {
-      scan_err1(lc, "Expected a Tape Label keyword, got: %s", lc->str);
-   }
-   scan_to_eol(lc);
-   set_bit(index, res_all.hdr.item_present);
-}
-
-
-
 void store_replace(LEX *lc, RES_ITEM *item, int index, int pass)
 {
    int token, i;
index 17658c3eab36002d1aa1841de2256b9367507e58..07a37003531fc463201f5c23c3229074bd6adce7 100644 (file)
@@ -131,8 +131,8 @@ void set_pool_dbr_defaults_in_media_dbr(MEDIA_DBR *mr, POOL_DBR *pr);
 
 /* ua_input.c */
 int get_cmd(UAContext *ua, const char *prompt);
-int get_pint(UAContext *ua, const char *prompt);
-int get_yesno(UAContext *ua, const char *prompt);
+bool get_pint(UAContext *ua, const char *prompt);
+bool get_yesno(UAContext *ua, const char *prompt);
 void parse_ua_args(UAContext *ua);
 
 /* ua_label.c */
index 658d5e8425d9ee3991560b235a62b6c222517073..99a74ae6aad736639368309d362a9152a334350f 100644 (file)
@@ -71,46 +71,52 @@ int get_cmd(UAContext *ua, const char *prompt)
 
 /*
  * Get a positive integer
- *  Returns:  0 if failure
- *           1 if success => value in ua->pint32_val
+ *  Returns:  false if failure
+ *           true  if success => value in ua->pint32_val
  */
-int get_pint(UAContext *ua, const char *prompt)
+bool get_pint(UAContext *ua, const char *prompt)
 {
    double dval;
    ua->pint32_val = 0;
    for (;;) {
+      ua->cmd[0] = 0;
       if (!get_cmd(ua, prompt)) {
-        return 0;
+        return false;
+      }
+      /* Kludge for slots blank line => 0 */
+      if (ua->cmd[0] == 0 && strncmp(prompt, "Enter slot", 10) == 0) {
+        ua->pint32_val = 0;
+        return true;
       }
       if (!is_a_number(ua->cmd)) {
-        bsendmsg(ua, "Expected a positive integer, got: %s\n", ua->cmd);
+         bsendmsg(ua, "Expected a positive integer, got: %s\n", ua->cmd);
         continue;
       }
       errno = 0;
       dval = strtod(ua->cmd, NULL);
       if (errno != 0 || dval < 0) {
-        bsendmsg(ua, "Expected a positive integer, got: %s\n", ua->cmd);
+         bsendmsg(ua, "Expected a positive integer, got: %s\n", ua->cmd);
         continue;
       }
       ua->pint32_val = (uint32_t)dval;
-      return 1;
+      return true;
    }
 }
 
 /*
  * Gets a yes or no response
- *  Returns:  0 if failure
- *           1 if success => ua->pint32_val == 1 for yes
- *                           ua->pint32_val == 0 for no
+ *  Returns:  false if failure
+ *           true  if success => ua->pint32_val == 1 for yes
+ *                               ua->pint32_val == 0 for no
  */
-int get_yesno(UAContext *ua, const char *prompt)
+bool get_yesno(UAContext *ua, const char *prompt)
 {
    int len;
 
    ua->pint32_val = 0;
    for (;;) {
       if (!get_cmd(ua, prompt)) {
-        return 0;
+        return false;
       }
       len = strlen(ua->cmd);
       if (len < 1 || len > 3) {
@@ -118,10 +124,10 @@ int get_yesno(UAContext *ua, const char *prompt)
       }
       if (strncasecmp(ua->cmd, _("yes"), len) == 0) {
         ua->pint32_val = 1;
-        return 1;
+        return true;
       }
       if (strncasecmp(ua->cmd, _("no"), len) == 0) {
-        return 1;
+        return true;
       }
       bsendmsg(ua, _("Invalid response. You must answer yes or no.\n"));
    }
index 6343ca2366deb108f96b3f46539f3b72f52af456..14d653ba976470c008931fd5fd3c7e37f3e5e977 100644 (file)
@@ -366,7 +366,7 @@ checkName:
       i = find_arg_with_value(ua, "slot");
       if (i >= 0) {
         mr.Slot = atoi(ua->argv[i]);
-      } else if (!get_pint(ua, _("Enter slot (0 for none): "))) {
+      } else if (!get_pint(ua, _("Enter slot (0 or Enter for none): "))) {
         return 1;
       } else {
         mr.Slot = ua->pint32_val;
index 9bd5d574bdb744b3d9ac633e70203a7a6242d508..b455d4a0792605ee2f82ccf73516dc8ee0bb9134 100644 (file)
@@ -122,6 +122,8 @@ bool fstype(const char *fname, char *fs, int fslen)
       case 0x58465342:     bstrncpy(fs, "xfs", fslen); return true;           /* XFS_SB_MAGIC */
       case 0x9fa2:         bstrncpy(fs, "usbdevfs", fslen); return true;      /* USBDEVICE_SUPER_MAGIC */
       case 0x62656572:     bstrncpy(fs, "sysfs", fslen); return true;         /* SYSFS_MAGIC */
+      case 0x517B:         bstrncpy(fs, "smbfs", fslen); return true;         /* SMB_SUPER_MAGIC */
+      case 0x9660:         bstrncpy(fs, "iso9660", fslen); return true;       /* ISOFS_SUPER_MAGIC */
 
 #if 0      /* These need confirmation */
       case 0xadf5:         bstrncpy(fs, "adfs", fslen); return true;          /* ADFS_SUPER_MAGIC */
@@ -151,7 +153,6 @@ bool fstype(const char *fname, char *fs, int fslen)
       case 0x958458f6:     bstrncpy(fs, "hugetlbfs", fslen); return true;     /* HUGETLBFS_MAGIC */
       case 0x12061983:     bstrncpy(fs, "hwgfs", fslen); return true;         /* HWGFS_MAGIC */
       case 0x66726f67:     bstrncpy(fs, "ibmasmfs", fslen); return true;      /* IBMASMFS_MAGIC */
-      case 0x9660:         bstrncpy(fs, "iso9660", fslen); return true;       /* ISOFS_SUPER_MAGIC */
       case 0x9660:         bstrncpy(fs, "isofs", fslen); return true;         /* ISOFS_SUPER_MAGIC */
       case 0x07c0:         bstrncpy(fs, "jffs", fslen); return true;          /* JFFS_MAGIC_SB_BITMASK */
       case 0x72b6:         bstrncpy(fs, "jffs2", fslen); return true;         /* JFFS2_SUPER_MAGIC */
@@ -172,7 +173,6 @@ bool fstype(const char *fname, char *fs, int fslen)
       case 0x7275:         bstrncpy(fs, "romfs", fslen); return true;         /* ROMFS_MAGIC */
       case 0x858458f6:     bstrncpy(fs, "rootfs", fslen); return true;        /* RAMFS_MAGIC */
       case 0x67596969:     bstrncpy(fs, "rpc_pipefs", fslen); return true;    /* RPCAUTH_GSSMAGIC */
-      case 0x517B:         bstrncpy(fs, "smbfs", fslen); return true;         /* SMB_SUPER_MAGIC */
       case 0x534F434B:     bstrncpy(fs, "sockfs", fslen); return true;        /* SOCKFS_MAGIC */
       case 0x012ff7b6:     bstrncpy(fs, "sysv2", fslen); return true;         /* SYSV2_SUPER_MAGIC */
       case 0x012ff7b5:     bstrncpy(fs, "sysv4", fslen); return true;         /* SYSV4_SUPER_MAGIC */
index f8670f67b9b81107c5c68b8ce80a29d800bfb0cb..031f939d354233ffc02ea6c278c296e87d4abc68 100755 (executable)
@@ -34,7 +34,7 @@
  */
 
 /*
-   Copyright (C) 2000-2004 Kern Sibbald and John Walker
+   Copyright (C) 2000-2005 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
@@ -132,6 +132,24 @@ static struct s_mtypes msg_types[] = {
    {NULL,           0}
 };
 
+/* Used for certain KeyWord tables */
+struct s_kw {
+   const char *name;
+   int token;
+};
+
+/*
+ * Tape Label types permitted in Pool records 
+ *
+ *   tape label      label code = token
+ */
+struct s_kw tapelabels[] = {
+   {"bacula",        B_BACULA_LABEL},
+   {"ansi",          B_ANSI_LABEL},
+   {"ibm",           B_IBM_LABEL},
+   {NULL,           0}
+};
+
 
 /* Simply print a message */
 static void prtmsg(void *sock, const char *fmt, ...)
@@ -658,6 +676,30 @@ void store_yesno(LEX *lc, RES_ITEM *item, int index, int pass)
    set_bit(index, res_all.hdr.item_present);
 }
 
+/*
+ * Store Tape Label Type (Bacula, ANSI, IBM)
+ *
+ */
+void store_label(LEX *lc, RES_ITEM *item, int index, int pass)
+{
+   int token, i;
+
+   token = lex_get_token(lc, T_NAME);
+   /* Store the label pass 2 so that type is defined */
+   for (i=0; tapelabels[i].name; i++) {
+      if (strcasecmp(lc->str, tapelabels[i].name) == 0) {
+        *(int *)(item->value) = tapelabels[i].token;
+        i = 0;
+        break;
+      }
+   }
+   if (i != 0) {
+      scan_err1(lc, "Expected a Tape Label keyword, got: %s", lc->str);
+   }
+   scan_to_eol(lc);
+   set_bit(index, res_all.hdr.item_present);
+}
+
 
 /* #define TRACE_RES */
 
index f28a411b3e3bce5e3ce47ddcf01e9e0aef6a9e97..1bb1684b709854531bb913aec6b8087f76e31f91 100644 (file)
@@ -138,3 +138,4 @@ void store_yesno(LEX *lc, RES_ITEM *item, int index, int pass);
 void store_time(LEX *lc, RES_ITEM *item, int index, int pass);
 void store_size(LEX *lc, RES_ITEM *item, int index, int pass);
 void store_defs(LEX *lc, RES_ITEM *item, int index, int pass);
+void store_label(LEX *lc, RES_ITEM *item, int index, int pass);
index 1bdd4b9f8589626a7dc40540f1008c662aafb643..666b86b426846c09ff7d463ebb1eabe9212fee4b 100644 (file)
@@ -159,6 +159,7 @@ init_dev(DEVICE *dev, DEVRES *device)
    dev->vol_poll_interval = device->vol_poll_interval;
    dev->max_spool_size = device->max_spool_size;
    dev->drive_index = device->drive_index;
+   dev->label_type = device->label_type;
    if (tape) { /* No parts on tapes */
       dev->max_part_size = 0;
    }
index e6fb96b11c966dea7acff7efed88b8e99f2900c1..d63bf4cde0eb4f225b2bd91e34a33089f9ed8087 100644 (file)
@@ -92,6 +92,7 @@ enum {
 #define CAP_POSITIONBLOCKS (1<<19)    /* Use block positioning */
 #define CAP_MTIOCGET       (1<<20)    /* Basic support for fileno and blkno */
 #define CAP_REQMOUNT       (1<<21)    /* Require mount to read files back (typically: DVD) */
+#define CAP_CHECKLABELS    (1<<22)    /* Check for ANSI/IBM labels */
 
 /* Test state */
 #define dev_state(dev, st_state) ((dev)->state & (st_state))
@@ -192,6 +193,7 @@ public:
    int dev_errno;                     /* Our own errno */
    int mode;                          /* read/write modes */
    int openmode;                      /* parameter passed to open_dev (useful to reopen the device) */
+   int label_type;                    /* Bacula/ANSI/IBM label types */
    uint32_t drive_index;              /* Autochanger drive index */
    POOLMEM *dev_name;                 /* device name */
    char *errmsg;                      /* nicely edited error message */
@@ -248,6 +250,7 @@ public:
    int is_labeled() const;
    int at_eof() const;
    int at_eom() const;
+   int at_eot() const;
    int can_append() const;
    int can_read() const;
    const char *strerror() const;
@@ -263,6 +266,7 @@ inline int DEVICE::is_open() const { return state & ST_OPENED; }
 inline int DEVICE::is_labeled() const { return state & ST_LABEL; }
 inline int DEVICE::at_eof() const { return state & ST_EOF; }
 inline int DEVICE::at_eom() const { return state & ST_EOT; }
+inline int DEVICE::at_eot() const { return state & ST_EOT; }
 inline int DEVICE::can_append() const { return state & ST_APPEND; }
 inline int DEVICE::can_read() const { return state & ST_READ; }
 inline const char *DEVICE::strerror() const { return errmsg; }
index d978330b055520a01850e133cef849cb9f7b1326..50c9dcc7ff09c9474967c4a12b28004e9e4e4203 100644 (file)
@@ -66,6 +66,8 @@ int read_dev_volume_label(DCR *dcr)
    DEV_RECORD *record;
    bool ok = false;
    DEV_BLOCK *block = dcr->block;
+   int stat;
+   bool want_ansi_ibm_label;
 
    Dmsg3(100, "Enter read_volume_label device=%s vol=%s dev_Vol=%s\n",
       dev_name(dev), VolName, dev->VolHdr.VolName);
@@ -102,12 +104,23 @@ int read_dev_volume_label(DCR *dcr)
    bstrncpy(dev->VolHdr.Id, "**error**", sizeof(dev->VolHdr.Id));
 
   /* Read ANSI/IBM label if so requested */
-  int stat = read_ansi_ibm_label(dcr);           
-  if (stat != VOL_OK) {
-      return stat;
+  
+  want_ansi_ibm_label = dcr->VolCatInfo.LabelType != B_BACULA_LABEL ||
+                       dcr->device->label_type != B_BACULA_LABEL;
+  if (want_ansi_ibm_label || dev_cap(dev, CAP_CHECKLABELS)) {
+      stat = read_ansi_ibm_label(dcr);           
+      /* If we want a label and didn't find it, return error */
+      if (want_ansi_ibm_label && stat != VOL_OK) {
+        empty_block(block);
+        rewind_dev(dev);
+        return stat;
+      }
+      if (stat != VOL_OK) {          /* Not an ANSI/IBM label, so re-read */
+        rewind_dev(dev);
+      }
    }
   
-   /* Read the Volume label block */
+   /* Read the Bacula Volume label block */
    record = new_record();
    empty_block(block);
    Dmsg0(90, "Big if statement in read_volume_label\n");
@@ -512,6 +525,7 @@ bool write_new_volume_label_to_dev(DCR *dcr, const char *VolName, const char *Po
 
    /* Write ANSI/IBM label if so requested */
    if (!write_ansi_ibm_label(dcr, VolName)) {
+      memset(&dev->VolHdr, 0, sizeof(dev->VolHdr));
       goto bail_out;
    }
 
@@ -968,17 +982,25 @@ bool write_ansi_ibm_label(DCR *dcr, const char *VolName)
    char label[80];                   /* tape label */
    char date[20];                    /* ansi date buffer */
    time_t now;
-   int len;
-   int stat;
+   int len, stat, label_type;
 
-   Dmsg1(100, "LabelType=%d\n", dcr->VolCatInfo.LabelType); 
-   switch (dcr->VolCatInfo.LabelType) {
+   /*
+    * If the Device requires a specific label type use it,
+    * otherwise, use the type requested by the Director
+    */
+   if (dcr->device->label_type != B_BACULA_LABEL) {
+      label_type = dcr->device->label_type;   /* force label type */
+   } else {
+      label_type = dcr->VolCatInfo.LabelType; /* accept Dir type */
+   }
+
+   switch (label_type) {
    case B_BACULA_LABEL:
       return true;
    case B_ANSI_LABEL:
    case B_IBM_LABEL:
       ser_declare;
-      Dmsg0(100, "Write ansi label.\n");
+      Dmsg1(000, "Write ANSI label type=%d\n", label_type);
       len = strlen(VolName);
       if (len > 6) {
         len = 6;                        /* max len ANSI label */
@@ -1014,7 +1036,7 @@ bool write_ansi_ibm_label(DCR *dcr, const char *VolName)
       now = time(NULL);
       ser_bytes(ansi_date(now, date), 6); /* current date */
       ser_bytes(ansi_date(now - 24 * 3600, date), 6); /* created yesterday */
-      ser_bytes(" 000000BACULA              ", 27);
+      ser_bytes(" 000000Bacula              ", 27);
       /* Write HDR1 label */
       stat = write(dev->fd, label, sizeof(label));
       if (stat != sizeof(label)) {
@@ -1051,43 +1073,71 @@ static int read_ansi_ibm_label(DCR *dcr)
    DEVICE *dev = dcr->dev;
    JCR *jcr = dcr->jcr;
    char label[80];                   /* tape label */
-   int retry, stat, i, num_rec;
+   int stat, i, num_rec;
 
-   if (dcr->VolCatInfo.LabelType == B_BACULA_LABEL) {
-      return VOL_OK;
-   }
    /*
     * Read VOL1, HDR1, HDR2 labels, but ignore the data
     *  If tape read the following EOF mark, on disk do
     *  not read.
     */
-   Dmsg0(100, "Read ansi label.\n");
+   Dmsg0(000, "Read ansi label.\n");
    if (dev->is_tape()) {
       num_rec = 4;
    } else {
       num_rec = 3;
    }
    for (i=0; i < num_rec; i++) {
-      retry = 0;
       do {
         stat = read(dev->fd, label, sizeof(label));
-        if (retry == 1) {
-           dev->VolCatInfo.VolCatErrors++;
-        }
-      } while (stat == -1 && (errno == EINTR || errno == EIO) && retry++ < 11);
+      } while (stat == -1 && errno == EINTR);
       if (stat < 0) {
         berrno be;
         clrerror_dev(dev, -1);
-         Dmsg1(200, "Read device got: ERR=%s\n", be.strerror());
+         Dmsg1(000, "Read device got: ERR=%s\n", be.strerror());
          Mmsg2(dev->errmsg, _("Read error on device %s in ANSI/IBM label. ERR=%s\n"),
            dev->dev_name, be.strerror());
          Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
-        if (dev->at_eof()) {        /* EOF just seen? */
-           dev->state |= ST_EOT;    /* yes, error => EOT */
-        }
+        dev->VolCatInfo.VolCatErrors++;
         return VOL_IO_ERROR;
       }
+      if (stat == 0) {
+        if (dev->at_eof()) {
+           dev->state |= ST_EOT;
+           return VOL_NO_LABEL;
+        } else {
+           dev->state |= ST_EOF;
+        }
+      }
+      switch (i) {
+      case 0:                        /* Want VOL1 label */
+         if (stat != 80 || strncmp("VOL1", label, 4) != 0) {
+            Dmsg0(000, "No VOL1 label\n");
+           return VOL_NO_LABEL;
+        }
+        break;
+      case 1:
+         if (stat != 80 || strncmp("HDR1", label, 4) != 0) {
+            Dmsg0(000, "No HDR1 label\n");
+           return VOL_NO_LABEL;
+        }
+        break;
+      case 2:
+         if (stat != 80 || strncmp("HDR2", label, 4) != 0) {
+            Dmsg0(000, "No HDR2 label\n");
+           return VOL_NO_LABEL;
+        }
+        break;
+      case 3:                        /* Should get EOF here */
+        if (stat != 0) {
+            Dmsg0(000, "No EOF\n");
+           return VOL_IO_ERROR;
+        }
+        break;
+      }
    }
+   /* ***FIXME*** add detection of IBM labels */
+   dev->label_type = B_ANSI_LABEL;
+   Dmsg0(000, "ANSI label OK\n");
    return VOL_OK;
 }  
 
index 6169057ca145a96d7f630b0ad3a5b9f475e17278..90979fb3eaa266eff4c9cffb13660851e96b8cd3 100644 (file)
@@ -103,6 +103,7 @@ static RES_ITEM dev_items[] = {
    {"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},
    {"usemtiocget",           store_yesno,  ITEM(res_dev.cap_bits), CAP_MTIOCGET, ITEM_DEFAULT, 1},
+   {"checklabels",           store_yesno,  ITEM(res_dev.cap_bits), CAP_CHECKLABELS, 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},
    {"alertcommand",          store_strname,ITEM(res_dev.alert_command), 0, 0, 0},
@@ -129,6 +130,7 @@ static RES_ITEM dev_items[] = {
    {"unmountcommand",        store_strname,ITEM(res_dev.unmount_command), 0, 0, 0},
    {"writepartcommand",      store_strname,ITEM(res_dev.write_part_command), 0, 0, 0},
    {"freespacecommand",      store_strname,ITEM(res_dev.free_space_command), 0, 0, 0},
+   {"labeltype",             store_label,  ITEM(res_dev.label_type), 0, 0, 0},
    {NULL, NULL, 0, 0, 0, 0}
 };
 
@@ -157,7 +159,7 @@ RES_TABLE resources[] = {
    {"device",        dev_items,     R_DEVICE},
    {"messages",      msgs_items,    R_MSGS},
    {"autochanger",   changer_items, R_AUTOCHANGER},
-   {NULL,           NULL,          0}
+   {NULL,            NULL,          0}
 };
 
 
@@ -175,7 +177,7 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm
       return;
    }
    sendit(sock, "dump_resource type=%d\n", type);
-   if (type < 0) {                   /* no recursion */
+   if (type < 0) {                    /* no recursion */
       type = - type;
       recurse = 0;
    }
@@ -185,35 +187,36 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm
       break;
    case R_STORAGE:
       sendit(sock, "Storage: name=%s SDaddr=%s SDport=%d SDDport=%d HB=%s\n",
-          res->res_store.hdr.name,
-          NPRT(get_first_address(res->res_store.sdaddrs, buf, sizeof(buf))),
-          get_first_port_host_order(res->res_store.sdaddrs),
-          get_first_port_host_order(res->res_store.sddaddrs),
-          edit_utime(res->res_store.heartbeat_interval, buf, sizeof(buf)));
-         foreach_dlist(p, res->res_store.sdaddrs) {
+           res->res_store.hdr.name,
+           NPRT(get_first_address(res->res_store.sdaddrs, buf, sizeof(buf))),
+           get_first_port_host_order(res->res_store.sdaddrs),
+           get_first_port_host_order(res->res_store.sddaddrs),
+           edit_utime(res->res_store.heartbeat_interval, buf, sizeof(buf)));
+          foreach_dlist(p, res->res_store.sdaddrs) {
                 sendit(sock, "        SDaddr=%s SDport=%d\n",
-                            p->get_address(buf, sizeof(buf)), p->get_port_host_order());
-         }
-         foreach_dlist(p, res->res_store.sddaddrs) {
+                             p->get_address(buf, sizeof(buf)), p->get_port_host_order());
+          }
+          foreach_dlist(p, res->res_store.sddaddrs) {
                 sendit(sock, "        SDDaddr=%s SDDport=%d\n",
-                            p->get_address(buf, sizeof(buf)), p->get_port_host_order());
-         }
+                             p->get_address(buf, sizeof(buf)), p->get_port_host_order());
+          }
       break;
    case R_DEVICE:
-      sendit(sock, "Device: name=%s MediaType=%s Device=%s\n",
-        res->res_dev.hdr.name,
-        res->res_dev.media_type, res->res_dev.device_name);
+      sendit(sock, "Device: name=%s MediaType=%s Device=%s LabelType=%d\n",
+         res->res_dev.hdr.name,
+         res->res_dev.media_type, res->res_dev.device_name,
+         res->res_dev.label_type);
       sendit(sock, "        rew_wait=%d min_bs=%d max_bs=%d\n",
-        res->res_dev.max_rewind_wait, res->res_dev.min_block_size,
-        res->res_dev.max_block_size);
+         res->res_dev.max_rewind_wait, res->res_dev.min_block_size,
+         res->res_dev.max_block_size);
       sendit(sock, "        max_jobs=%d max_files=%" lld " max_size=%" lld "\n",
-        res->res_dev.max_volume_jobs, res->res_dev.max_volume_files,
-        res->res_dev.max_volume_size);
+         res->res_dev.max_volume_jobs, res->res_dev.max_volume_files,
+         res->res_dev.max_volume_size);
       sendit(sock, "        max_file_size=%" lld " capacity=%" lld "\n",
-        res->res_dev.max_file_size, res->res_dev.volume_capacity);
+         res->res_dev.max_file_size, res->res_dev.volume_capacity);
       sendit(sock, "         spool_directory=%s\n", NPRT(res->res_dev.spool_directory));
       sendit(sock, "         max_spool_size=%" lld " max_job_spool_size=%" lld "\n",
-        res->res_dev.max_spool_size, res->res_dev.max_job_spool_size);
+         res->res_dev.max_spool_size, res->res_dev.max_job_spool_size);
       bstrncpy(buf, "        ", sizeof(buf));
       if (res->res_dev.cap_bits & CAP_EOF) {
          bstrncat(buf, "CAP_EOF ", sizeof(buf));
@@ -251,14 +254,17 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm
       if (res->res_dev.cap_bits & CAP_ALWAYSOPEN) {
          bstrncat(buf, "CAP_ALWAYSOPEN ", sizeof(buf));
       }
+      if (res->res_dev.cap_bits & CAP_CHECKLABELS) {
+         bstrncat(buf, "CAP_CHECKLABELS ", sizeof(buf));
+      }
       bstrncat(buf, "\n", sizeof(buf));
       sendit(sock, buf);
       break;
    case R_AUTOCHANGER:
       DEVRES *dev;
       sendit(sock, "Changer: name=%s Changer_devname=%s Changer_cmd=%s\n",
-        res->res_changer.hdr.name,
-        res->res_changer.changer_name, res->res_changer.changer_command);
+         res->res_changer.hdr.name,
+         res->res_changer.changer_name, res->res_changer.changer_command);
       foreach_alist(dev, res->res_changer.device) {
          sendit(sock, "   --->Device: name=%s\n", dev->hdr.name);
       }
@@ -308,77 +314,77 @@ void free_resource(RES *sres, int type)
    switch (type) {
    case R_DIRECTOR:
       if (res->res_dir.password) {
-        free(res->res_dir.password);
+         free(res->res_dir.password);
       }
       if (res->res_dir.address) {
-        free(res->res_dir.address);
+         free(res->res_dir.address);
       }
       break;
    case R_AUTOCHANGER:
       if (res->res_changer.changer_name) {
-        free(res->res_changer.changer_name);
+         free(res->res_changer.changer_name);
       }
       if (res->res_changer.changer_command) {
-        free(res->res_changer.changer_command);
+         free(res->res_changer.changer_command);
       }
    case R_STORAGE:
       if (res->res_store.sdaddrs) {
-        free_addresses(res->res_store.sdaddrs);
+         free_addresses(res->res_store.sdaddrs);
       }
       if (res->res_store.sddaddrs) {
-        free_addresses(res->res_store.sddaddrs);
+         free_addresses(res->res_store.sddaddrs);
       }
       if (res->res_store.working_directory) {
-        free(res->res_store.working_directory);
+         free(res->res_store.working_directory);
       }
       if (res->res_store.pid_directory) {
-        free(res->res_store.pid_directory);
+         free(res->res_store.pid_directory);
       }
       if (res->res_store.subsys_directory) {
-        free(res->res_store.subsys_directory);
+         free(res->res_store.subsys_directory);
       }
       break;
    case R_DEVICE:
       if (res->res_dev.media_type) {
-        free(res->res_dev.media_type);
+         free(res->res_dev.media_type);
       }
       if (res->res_dev.device_name) {
-        free(res->res_dev.device_name);
+         free(res->res_dev.device_name);
       }
       if (res->res_dev.changer_name) {
-        free(res->res_dev.changer_name);
+         free(res->res_dev.changer_name);
       }
       if (res->res_dev.changer_command) {
-        free(res->res_dev.changer_command);
+         free(res->res_dev.changer_command);
       }
       if (res->res_dev.alert_command) {
-        free(res->res_dev.alert_command);
+         free(res->res_dev.alert_command);
       }
       if (res->res_dev.spool_directory) {
-        free(res->res_dev.spool_directory);
+         free(res->res_dev.spool_directory);
       }
       if (res->res_dev.mount_point) {
-        free(res->res_dev.mount_point);
+         free(res->res_dev.mount_point);
       }
       if (res->res_dev.mount_command) {
-        free(res->res_dev.mount_command);
+         free(res->res_dev.mount_command);
       }
       if (res->res_dev.unmount_command) {
-        free(res->res_dev.unmount_command);
+         free(res->res_dev.unmount_command);
       }
       if (res->res_dev.write_part_command) {
-        free(res->res_dev.write_part_command);
+         free(res->res_dev.write_part_command);
       }
       if (res->res_dev.free_space_command) {
-        free(res->res_dev.free_space_command);
+         free(res->res_dev.free_space_command);
       }
       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;
@@ -412,10 +418,10 @@ void save_resource(int type, RES_ITEM *items, int pass)
     */
    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 (!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]);
-         }
+              items[i].name, resources[rindex]);
+          }
       }
       /* If this triggers, take a look at lib/parse_conf.h */
       if (i >= MAX_RES_ITEMS) {
@@ -434,37 +440,37 @@ void save_resource(int type, RES_ITEM *items, int pass)
       case R_DIRECTOR:
       case R_DEVICE:
       case R_MSGS:
-        break;
+         break;
 
       /* Resources containing a resource or an alist */
       case R_STORAGE:
-        if ((res = (URES *)GetResWithName(R_STORAGE, res_all.res_dir.hdr.name)) == NULL) {
+         if ((res = (URES *)GetResWithName(R_STORAGE, res_all.res_dir.hdr.name)) == NULL) {
             Emsg1(M_ERROR_TERM, 0, "Cannot find Storage resource \"%s\"\n", res_all.res_dir.hdr.name);
-        }
-        res->res_store.messages = res_all.res_store.messages;
-        break;
+         }
+         res->res_store.messages = res_all.res_store.messages;
+         break;
       case R_AUTOCHANGER:
-        if ((res = (URES *)GetResWithName(type, res_all.res_changer.hdr.name)) == NULL) {
+         if ((res = (URES *)GetResWithName(type, res_all.res_changer.hdr.name)) == NULL) {
             Emsg1(M_ERROR_TERM, 0, "Cannot find AutoChanger resource %s\n",
-                 res_all.res_changer.hdr.name);
-        }
-        /* we must explicitly copy the device alist pointer */
-        res->res_changer.device   = res_all.res_changer.device;
-        break;
+                  res_all.res_changer.hdr.name);
+         }
+         /* we must explicitly copy the device alist pointer */
+         res->res_changer.device   = res_all.res_changer.device;
+         break;
       default:
          printf("Unknown resource type %d\n", type);
-        error = 1;
-        break;
+         error = 1;
+         break;
       }
 
 
       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;
    }
@@ -472,45 +478,45 @@ void save_resource(int type, RES_ITEM *items, int pass)
    /* The following code is only executed on pass 1 */
    switch (type) {
       case R_DIRECTOR:
-        size = sizeof(DIRRES);
-        break;
+         size = sizeof(DIRRES);
+         break;
       case R_STORAGE:
-        size = sizeof(STORES);
-        break;
+         size = sizeof(STORES);
+         break;
       case R_DEVICE:
-        size = sizeof(DEVRES);
-        break;
+         size = sizeof(DEVRES);
+         break;
       case R_MSGS:
-        size = sizeof(MSGS);
-        break;
+         size = sizeof(MSGS);
+         break;
       case R_AUTOCHANGER:
-        size = sizeof(AUTOCHANGER);
-        break;
+         size = sizeof(AUTOCHANGER);
+         break;
       default:
          printf("Unknown resource type %d\n", type);
-        error = 1;
-        size = 1;
-        break;
+         error = 1;
+         size = 1;
+         break;
    }
    /* Common */
    if (!error) {
       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 */
       } 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;
          Dmsg2(90, "Inserting %s res: %s\n", res_to_str(type),
-              res->res_dir.hdr.name);
+               res->res_dir.hdr.name);
       }
    }
 }
index 7f92e20d3885c8ef72833986955a13f43a1a20bd..448f41a879fb14dbe20e313575f3f1e5b9a41316 100644 (file)
@@ -82,6 +82,7 @@ public:
    char *changer_command;             /* Changer command  -- external program */
    char *alert_command;               /* Alert command -- external program */
    char *spool_directory;             /* Spool file directory */
+   int   label_type;                  /* label type */
    uint32_t drive_index;              /* Autochanger drive index */
    uint32_t cap_bits;                 /* Capabilities of this device */
    uint32_t max_changer_wait;         /* Changer timeout */
index 213bfb464a2b0a534e0b0e90c40d20933cf3da7b..7a381691bc3ea7ad1f2e7797f67ceb388c013333 100644 (file)
@@ -1,8 +1,8 @@
 /* */
 #undef  VERSION
 #define VERSION "1.37.3"
-#define BDATE   "30 January 2005"
-#define LSMDATE "30Jan05"
+#define BDATE   "04 February 2005"
+#define LSMDATE "04Feb05"
 
 /* Debug flags */
 #undef  DEBUG