From: Kern Sibbald Date: Fri, 4 Feb 2005 11:06:08 +0000 (+0000) Subject: OK, ANSI labels seem to be working now X-Git-Tag: Release-1.38.0~650 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=06f295c818e9b9506a2617877a78e331196ba92b;p=bacula%2Fbacula OK, ANSI labels seem to be working now git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@1814 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/bacula/ReleaseNotes b/bacula/ReleaseNotes index d8bd80297d..29c16fdff2 100644 --- a/bacula/ReleaseNotes +++ b/bacula/ReleaseNotes @@ -1,23 +1,127 @@ 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 = 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 = 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/). diff --git a/bacula/src/dird/dird_conf.c b/bacula/src/dird/dird_conf.c index 51cae84864..5b812ead8e 100644 --- a/bacula/src/dird/dird_conf.c +++ b/bacula/src/dird/dird_conf.c @@ -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; diff --git a/bacula/src/dird/protos.h b/bacula/src/dird/protos.h index 17658c3eab..07a3700353 100644 --- a/bacula/src/dird/protos.h +++ b/bacula/src/dird/protos.h @@ -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 */ diff --git a/bacula/src/dird/ua_input.c b/bacula/src/dird/ua_input.c index 658d5e8425..99a74ae6aa 100644 --- a/bacula/src/dird/ua_input.c +++ b/bacula/src/dird/ua_input.c @@ -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")); } diff --git a/bacula/src/dird/ua_label.c b/bacula/src/dird/ua_label.c index 6343ca2366..14d653ba97 100644 --- a/bacula/src/dird/ua_label.c +++ b/bacula/src/dird/ua_label.c @@ -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; diff --git a/bacula/src/findlib/fstype.c b/bacula/src/findlib/fstype.c index 9bd5d574bd..b455d4a079 100644 --- a/bacula/src/findlib/fstype.c +++ b/bacula/src/findlib/fstype.c @@ -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 */ diff --git a/bacula/src/lib/parse_conf.c b/bacula/src/lib/parse_conf.c index f8670f67b9..031f939d35 100755 --- a/bacula/src/lib/parse_conf.c +++ b/bacula/src/lib/parse_conf.c @@ -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 */ diff --git a/bacula/src/lib/parse_conf.h b/bacula/src/lib/parse_conf.h index f28a411b3e..1bb1684b70 100644 --- a/bacula/src/lib/parse_conf.h +++ b/bacula/src/lib/parse_conf.h @@ -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); diff --git a/bacula/src/stored/dev.c b/bacula/src/stored/dev.c index 1bdd4b9f85..666b86b426 100644 --- a/bacula/src/stored/dev.c +++ b/bacula/src/stored/dev.c @@ -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; } diff --git a/bacula/src/stored/dev.h b/bacula/src/stored/dev.h index e6fb96b11c..d63bf4cde0 100644 --- a/bacula/src/stored/dev.h +++ b/bacula/src/stored/dev.h @@ -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; } diff --git a/bacula/src/stored/label.c b/bacula/src/stored/label.c index d978330b05..50c9dcc7ff 100644 --- a/bacula/src/stored/label.c +++ b/bacula/src/stored/label.c @@ -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; } diff --git a/bacula/src/stored/stored_conf.c b/bacula/src/stored/stored_conf.c index 6169057ca1..90979fb3ea 100644 --- a/bacula/src/stored/stored_conf.c +++ b/bacula/src/stored/stored_conf.c @@ -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); } } } diff --git a/bacula/src/stored/stored_conf.h b/bacula/src/stored/stored_conf.h index 7f92e20d38..448f41a879 100644 --- a/bacula/src/stored/stored_conf.h +++ b/bacula/src/stored/stored_conf.h @@ -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 */ diff --git a/bacula/src/version.h b/bacula/src/version.h index 213bfb464a..7a381691bc 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -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