X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fstored%2Fansi_label.c;h=e688f5fd20613a9b30105b4eb05f3096c2331004;hb=ecf33f65329d2ac71403eb26962800c9c2f4664e;hp=0ee7ad0f8a63addc4cdf25ecb02de71629c70f0a;hpb=4cd366933e81266268f69441dc0ff5f305cb897d;p=bacula%2Fbacula diff --git a/bacula/src/stored/ansi_label.c b/bacula/src/stored/ansi_label.c index 0ee7ad0f8a..e688f5fd20 100644 --- a/bacula/src/stored/ansi_label.c +++ b/bacula/src/stored/ansi_label.c @@ -10,28 +10,40 @@ * Version $Id$ */ /* - Copyright (C) 2005 Kern Sibbald + Bacula® - The Network Backup Solution - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of - the License, or (at your option) any later version. + Copyright (C) 2005-2006 Free Software Foundation Europe e.V. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + The main author of Bacula is Kern Sibbald, with contributions from + many others, a complete list can be found in the file AUTHORS. + This program is Free Software; you can redistribute it and/or + modify it under the terms of version two of the GNU General Public + License as published by the Free Software Foundation plus additions + that are listed in the file LICENSE. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public - License along with this program; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. - */ + Bacula® is a registered trademark of John Walker. + The licensor of Bacula is the Free Software Foundation Europe + (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, + Switzerland, email:ftf@fsfeurope.org. +*/ #include "bacula.h" /* pull in global headers */ #include "stored.h" /* pull in Storage Deamon headers */ +/* Imported functions */ +void ascii_to_ebcdic(char *dst, char *src, int count); +void ebcdic_to_ascii(char *dst, char *src, int count); + /* Forward referenced functions */ static char *ansi_date(time_t td, char *buf); static bool same_label_names(char *bacula_name, char *ansi_name); @@ -44,27 +56,28 @@ static bool same_label_names(char *bacula_name, char *ansi_name); * point, all is good. * * Returns: - * VOL_OK Volume name OK - * VOL_NO_LABEL No ANSI label on Volume - * VOL_IO_ERROR I/O error on read - * VOL_NAME_ERROR Wrong name in VOL1 record - * VOL_LABEL_ERROR Probably an ANSI label, but something wrong - * + * VOL_OK Volume name OK + * VOL_NO_LABEL No ANSI label on Volume + * VOL_IO_ERROR I/O error on read + * VOL_NAME_ERROR Wrong name in VOL1 record + * VOL_LABEL_ERROR Probably an ANSI label, but something wrong + * */ int read_ansi_ibm_label(DCR *dcr) { DEVICE *dev = dcr->dev; JCR *jcr = dcr->jcr; - char label[80]; /* tape label */ + char label[80]; /* tape label */ int stat, i; char *VolName = dcr->VolumeName; + bool ok = false; /* * Read VOL1, HDR1, HDR2 labels, but ignore the data * If tape read the following EOF mark, on disk do * not read. */ - Dmsg0(000, "Read ansi label.\n"); + Dmsg0(100, "Read ansi label.\n"); if (!dev->is_tape()) { return VOL_OK; } @@ -74,95 +87,192 @@ int read_ansi_ibm_label(DCR *dcr) /* Read a maximum of 5 records VOL1, HDR1, ... HDR4 */ for (i=0; i < 6; i++) { do { - stat = read(dev->fd, label, sizeof(label)); + stat = dev->read(label, sizeof(label)); } while (stat == -1 && errno == EINTR); if (stat < 0) { - berrno be; - clrerror_dev(dev, -1); - 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()); + berrno be; + dev->clrerror(-1); + Dmsg1(100, "Read device got: ERR=%s\n", be.bstrerror()); + Mmsg2(jcr->errmsg, _("Read error on device %s in ANSI label. ERR=%s\n"), + dev->dev_name, be.bstrerror()); Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); - dev->VolCatInfo.VolCatErrors++; - return VOL_IO_ERROR; + dev->VolCatInfo.VolCatErrors++; + return VOL_IO_ERROR; } if (stat == 0) { - if (dev->at_eof()) { - dev->state |= ST_EOT; - Dmsg0(000, "EOM on ANSI label\n"); + if (dev->at_eof()) { + dev->set_eot(); /* second eof, set eot bit */ + Dmsg0(100, "EOM on ANSI label\n"); + Mmsg0(jcr->errmsg, _("Insane! End of tape while reading ANSI label.\n")); return VOL_LABEL_ERROR; /* at EOM this shouldn't happen */ - } else { - dev->set_eof(); - } + } else { + dev->set_ateof(); /* set eof state */ + } } 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; /* No ANSI label */ - } + case 0: /* Want VOL1 label */ + if (stat == 80) { + if (strncmp("VOL1", label, 4) == 0) { + ok = true; + dev->label_type = B_ANSI_LABEL; + } else { + /* Try EBCDIC */ + ebcdic_to_ascii(label, label, sizeof(label)); + if (strncmp("VOL1", label, 4) == 0) { + ok = true;; + dev->label_type = B_IBM_LABEL; + Dmsg0(100, "Found IBM label.\n"); + } + } + } + if (!ok) { + Dmsg0(100, "No VOL1 label\n"); + Mmsg0(jcr->errmsg, _("No VOL1 label while reading ANSI/IBM label.\n")); + return VOL_NO_LABEL; /* No ANSI label */ + } - dev->label_type = B_ANSI_LABEL; - /* Compare Volume Names allow special wild card */ + /* Compare Volume Names allow special wild card */ if (VolName && *VolName && *VolName != '*') { - if (!same_label_names(VolName, &label[4])) { - char *p = &label[4]; - char *q = dev->VolHdr.VolName; + if (!same_label_names(VolName, &label[4])) { + char *p = &label[4]; + char *q; + + free_volume(dev); + /* Store new Volume name */ + q = dev->VolHdr.VolumeName; for (int i=0; *p != ' ' && i < 6; i++) { - *q++ = *p++; - } - *q = 0; - Dmsg2(000, "Wanted ANSI Vol %s got %6s\n", VolName, dev->VolHdr.VolName); - return VOL_NAME_ERROR; - } - } - break; + *q++ = *p++; + } + *q = 0; + reserve_volume(dcr, dev->VolHdr.VolumeName); + Dmsg2(100, "Wanted ANSI Vol %s got %6s\n", VolName, dev->VolHdr.VolumeName); + Mmsg2(jcr->errmsg, _("Wanted ANSI Volume \"%s\" got \"%s\"\n"), VolName, dev->VolHdr.VolumeName); + return VOL_NAME_ERROR; + } + } + break; case 1: + if (dev->label_type == B_IBM_LABEL) { + ebcdic_to_ascii(label, label, sizeof(label)); + } if (stat != 80 || strncmp("HDR1", label, 4) != 0) { - Dmsg0(000, "No HDR1 label\n"); - return VOL_LABEL_ERROR; - } + Dmsg0(100, "No HDR1 label\n"); + Mmsg0(jcr->errmsg, _("No HDR1 label while reading ANSI label.\n")); + return VOL_LABEL_ERROR; + } if (strncmp("BACULA.DATA", &label[4], 11) != 0) { - Dmsg1(000, "HD1 not Bacula label. Wanted BACULA.DATA got %11s\n", - &label[4]); - return VOL_NAME_ERROR; /* Not a Bacula label */ - } - break; + Dmsg1(100, "HD1 not Bacula label. Wanted BACULA.DATA got %11s\n", + &label[4]); + Mmsg1(jcr->errmsg, _("ANSI/IBM Volume \"%s\" does not belong to Bacula.\n"), + dev->VolHdr.VolumeName); + return VOL_NAME_ERROR; /* Not a Bacula label */ + } + break; case 2: + if (dev->label_type == B_IBM_LABEL) { + ebcdic_to_ascii(label, label, sizeof(label)); + } if (stat != 80 || strncmp("HDR2", label, 4) != 0) { - Dmsg0(000, "No HDR2 label\n"); - return VOL_LABEL_ERROR; - } - break; + Dmsg0(100, "No HDR2 label\n"); + Mmsg0(jcr->errmsg, _("No HDR2 label while reading ANSI/IBM label.\n")); + return VOL_LABEL_ERROR; + } + break; default: - if (stat == 0) { - Dmsg0(000, "ANSI label OK\n"); - return VOL_OK; - } + if (stat == 0) { + Dmsg0(100, "ANSI label OK\n"); + return VOL_OK; + } + if (dev->label_type == B_IBM_LABEL) { + ebcdic_to_ascii(label, label, sizeof(label)); + } if (stat != 80 || strncmp("HDR", label, 3) != 0) { - Dmsg0(000, "Unknown or bad ANSI label record.\n"); - return VOL_LABEL_ERROR; - } - break; + Dmsg0(100, "Unknown or bad ANSI/IBM label record.\n"); + Mmsg0(jcr->errmsg, _("Unknown or bad ANSI/IBM label record.\n")); + return VOL_LABEL_ERROR; + } + break; } } - Dmsg0(000, "Too many records in ANSI label.\n"); + Dmsg0(100, "Too many records in ANSI/IBM label.\n"); + Mmsg0(jcr->errmsg, _("Too many records in while reading ANSI/IBM label.\n")); return VOL_LABEL_ERROR; } +/* + * ANSI/IBM VOL1 label + * 80 characters blank filled + * Pos count Function What Bacula puts + * 0-3 4 "VOL1" VOL1 + * 4-9 6 Volume name Volume name + * 10-10 1 Access code + * 11-36 26 Unused + * + * ANSI + * 37-50 14 Owner + * 51-78 28 reserved + * 79 1 ANSI level 3 + * + * IBM + * 37-40 4 reserved + * 41-50 10 Owner + * 51-79 29 reserved + + * + * + * ANSI/IBM HDR1 label + * 80 characters blank filled + * Pos count Function What Bacula puts + * 0-3 4 "HDR1" HDR1 + * 4-20 17 File name BACULA.DATA + * 21-26 6 Volume name Volume name + * 27-30 4 Vol seq num 0001 + * 31-34 4 file num 0001 + * 35-38 4 Generation 0001 + * 39-40 2 Gen version 00 + * 41-46 6 Create date bYYDDD yesterday + * 47-52 6 Expire date bYYDDD today + * 53-53 1 Access + * 54-59 6 Block count 000000 + * 60-72 13 Software name Bacula + * 73-79 7 Reserved + + * ANSI/IBM HDR2 label + * 80 characters blank filled + * Pos count Function What Bacula puts + * 0-3 4 "HDR2" HDR2 + * 4-4 1 Record format D (V if IBM) => variable + * 5-9 5 Block length 32000 + * 10-14 5 Rec length 32000 + * 15-15 1 Density + * 16-16 1 Continued + * 17-33 17 Job + * 34-35 2 Recording + * 36-36 1 cr/lf ctl + * 37-37 1 reserved + * 38-38 1 Blocked flag + * 39-49 11 reserved + * 50-51 2 offset + * 52-79 28 reserved + + */ + +static const char *labels[] = {"HDR", "EOF", "EOV"}; + /* * Write an ANSI or IBM 80 character tape label - * Assume we are positioned at the beginning of the tape. + * Type determines whether we are writing HDR, EOF, or EOV labels + * Assume we are positioned to write the labels * Returns: true of OK - * false if error + * false if error */ -bool write_ansi_ibm_label(DCR *dcr, const char *VolName) +bool write_ansi_ibm_labels(DCR *dcr, int type, const char *VolName) { DEVICE *dev = dcr->dev; JCR *jcr = dcr->jcr; - char label[80]; /* tape label */ - char date[20]; /* ansi date buffer */ + char label[80]; /* tape label */ + char date[20]; /* ansi date buffer */ time_t now; int len, stat, label_type; @@ -182,32 +292,40 @@ bool write_ansi_ibm_label(DCR *dcr, const char *VolName) case B_ANSI_LABEL: case B_IBM_LABEL: ser_declare; - Dmsg1(000, "Write ANSI label type=%d\n", label_type); + Dmsg1(100, "Write ANSI label type=%d\n", label_type); len = strlen(VolName); if (len > 6) { Jmsg1(jcr, M_FATAL, 0, _("ANSI Volume label name \"%s\" longer than 6 chars.\n"), - VolName); - return false; + VolName); + return false; } - memset(label, ' ', sizeof(label)); - ser_begin(label, sizeof(label)); - ser_bytes("VOL1", 4); - ser_bytes(VolName, len); - label[79] = '3'; /* ANSI label flag */ - /* Write VOL1 label */ - stat = write(dev->fd, label, sizeof(label)); - if (stat != sizeof(label)) { - berrno be; - Jmsg1(jcr, M_FATAL, 0, _("Could not write ANSI VOL1 label. ERR=%s\n"), - be.strerror()); - return false; + if (type == ANSI_VOL_LABEL) { + ser_begin(label, sizeof(label)); + ser_bytes("VOL1", 4); + ser_bytes(VolName, len); + /* Write VOL1 label */ + if (label_type == B_IBM_LABEL) { + ascii_to_ebcdic(label, label, sizeof(label)); + } else { + label[79] = '3'; /* ANSI label flag */ + } + stat = dev->write(label, sizeof(label)); + if (stat != sizeof(label)) { + berrno be; + Jmsg1(jcr, M_FATAL, 0, _("Could not write ANSI VOL1 label. ERR=%s\n"), + be.bstrerror()); + return false; + } } + /* Now construct HDR1 label */ + memset(label, ' ', sizeof(label)); ser_begin(label, sizeof(label)); - ser_bytes("HDR1", 4); + ser_bytes(labels[type], 3); + ser_bytes("1", 1); ser_bytes("BACULA.DATA", 11); /* Filename field */ ser_begin(&label[21], sizeof(label)-21); /* fileset field */ - ser_bytes(VolName, len); /* write Vol Ser No. */ + ser_bytes(VolName, len); /* write Vol Ser No. */ ser_begin(&label[27], sizeof(label)-27); ser_bytes("00010001000100", 14); /* File section, File seq no, Generation no */ now = time(NULL); @@ -215,28 +333,66 @@ bool write_ansi_ibm_label(DCR *dcr, const char *VolName) ser_bytes(ansi_date(now - 24 * 3600, date), 6); /* created yesterday */ ser_bytes(" 000000Bacula ", 27); /* Write HDR1 label */ - stat = write(dev->fd, label, sizeof(label)); + if (label_type == B_IBM_LABEL) { + ascii_to_ebcdic(label, label, sizeof(label)); + } + + /* + * This could come at the end of a tape, ignore + * EOT errors. + */ + stat = dev->write(label, sizeof(label)); if (stat != sizeof(label)) { - berrno be; - Jmsg1(jcr, M_FATAL, 0, _("Could not write ANSI HDR1 label. ERR=%s\n"), - be.strerror()); - return false; + berrno be; + if (stat == -1) { + dev->clrerror(-1); + if (dev->dev_errno == 0) { + dev->dev_errno = ENOSPC; /* out of space */ + } + if (dev->dev_errno != ENOSPC) { + Jmsg1(jcr, M_FATAL, 0, _("Could not write ANSI HDR1 label. ERR=%s\n"), + be.bstrerror()); + return false; + } + } else { + Jmsg(jcr, M_FATAL, 0, _("Could not write ANSI HDR1 label.\n")); + return false; + } } + /* Now construct HDR2 label */ memset(label, ' ', sizeof(label)); ser_begin(label, sizeof(label)); - ser_bytes("HDR2F3200032000", 15); - /* Write HDR1 label */ - stat = write(dev->fd, label, sizeof(label)); + ser_bytes(labels[type], 3); + ser_bytes("2D3200032000", 12); + /* Write HDR2 label */ + if (label_type == B_IBM_LABEL) { + label[4] = 'V'; + ascii_to_ebcdic(label, label, sizeof(label)); + } + stat = dev->write(label, sizeof(label)); if (stat != sizeof(label)) { - berrno be; - Jmsg1(jcr, M_FATAL, 0, _("Could not write ANSI HDR1 label. ERR=%s\n"), - be.strerror()); - return false; + berrno be; + if (stat == -1) { + dev->clrerror(-1); + if (dev->dev_errno == 0) { + dev->dev_errno = ENOSPC; /* out of space */ + } + if (dev->dev_errno != ENOSPC) { + Jmsg1(jcr, M_FATAL, 0, _("Could not write ANSI HDR1 label. ERR=%s\n"), + be.bstrerror()); + return false; + } + dev->weof(1); + return true; + } else { + Jmsg(jcr, M_FATAL, 0, _("Could not write ANSI HDR1 label.\n")); + return false; + } } - if (weof_dev(dev, 1) < 0) { + if (!dev->weof(1)) { Jmsg(jcr, M_FATAL, 0, _("Error writing EOF to tape. ERR=%s"), dev->errmsg); - return false; + return false; } return true; default: @@ -253,13 +409,13 @@ static bool same_label_names(char *bacula_name, char *ansi_name) /* Six characters max */ for (int i=0; i < 6; i++) { if (*a == *b) { - a++; - b++; - continue; + a++; + b++; + continue; } /* ANSI labels are blank filled, Bacula's are zero terminated */ if (*a == ' ' && *b == 0) { - return true; + return true; } return false; } @@ -271,7 +427,10 @@ static bool same_label_names(char *bacula_name, char *ansi_name) return false; } - +/* + * ANSI date + * ' 'YYDDD + */ static char *ansi_date(time_t td, char *buf) { struct tm *tm;