]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/stored/ansi_label.c
kes Merge patch from Sergey Svishchev <svs@ropnet.ru> that preserves
[bacula/bacula] / bacula / src / stored / ansi_label.c
index 46bb03f05a36f6f4c94d568e7796eb12c6ed1c72..e688f5fd20613a9b30105b4eb05f3096c2331004 100644 (file)
  *   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 */
@@ -48,18 +56,18 @@ 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;
@@ -79,106 +87,112 @@ 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(100, "Read device got: ERR=%s\n", 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.strerror());
+            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;
+         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) {
+      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));
+               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;
-              }
-           }       
-        }
-        if (!ok) {
+                  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 */
-        }
+            return VOL_NO_LABEL;   /* No 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(100, "Wanted ANSI Vol %s got %6s\n", VolName, dev->VolHdr.VolName);
-               Mmsg2(jcr->errmsg, "Wanted ANSI Volume \"%s\" got \"%s\"\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 (dev->label_type == B_IBM_LABEL) {
+            ebcdic_to_ascii(label, label, sizeof(label));
+         }
          if (stat != 80 || strncmp("HDR1", label, 4) != 0) {
             Dmsg0(100, "No HDR1 label\n");
             Mmsg0(jcr->errmsg, _("No HDR1 label while reading ANSI label.\n"));
-           return VOL_LABEL_ERROR;
-        }
+            return VOL_LABEL_ERROR;
+         }
          if (strncmp("BACULA.DATA", &label[4], 11) != 0) {
             Dmsg1(100, "HD1 not Bacula label. Wanted  BACULA.DATA got %11s\n",
-              &label[4]);
+               &label[4]);
             Mmsg1(jcr->errmsg, _("ANSI/IBM Volume \"%s\" does not belong to Bacula.\n"),
-              dev->VolHdr.VolName);
-           return VOL_NAME_ERROR;     /* Not a Bacula label */
-        }
-        break;
+               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 (dev->label_type == B_IBM_LABEL) {
+            ebcdic_to_ascii(label, label, sizeof(label));
+         }
          if (stat != 80 || strncmp("HDR2", label, 4) != 0) {
             Dmsg0(100, "No HDR2 label\n");
             Mmsg0(jcr->errmsg, _("No HDR2 label while reading ANSI/IBM label.\n"));
-           return VOL_LABEL_ERROR;
-        }
-        break;
+            return VOL_LABEL_ERROR;
+         }
+         break;
       default:
-        if (stat == 0) {
+         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));
-        }
+            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(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;
+            return VOL_LABEL_ERROR;
+         }
+         break;
       }
    }
    Dmsg0(100, "Too many records in ANSI/IBM label.\n");
@@ -189,58 +203,58 @@ int read_ansi_ibm_label(DCR *dcr)
 /*
  * ANSI/IBM VOL1 label
  *  80 characters blank filled
- * Pos  count   Function      What Bacula puts
+ * 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
+ * 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
+ * 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
+ * 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
+ * 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
+ * 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
+ * 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
+ * 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
 
  */ 
 
@@ -251,14 +265,14 @@ static const char *labels[] = {"HDR", "EOF", "EOV"};
  *   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_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;
 
@@ -282,26 +296,26 @@ bool write_ansi_ibm_labels(DCR *dcr, int type, const char *VolName)
       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;
       }
       if (type == ANSI_VOL_LABEL) {
-        ser_begin(label, sizeof(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 {
+         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 = write(dev->fd, label, sizeof(label));
-        if (stat != sizeof(label)) {
-           berrno be;
+         }
+         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.strerror());
-           return false;
-        }
+               be.bstrerror());
+            return false;
+         }
       }
 
       /* Now construct HDR1 label */
@@ -311,7 +325,7 @@ bool write_ansi_ibm_labels(DCR *dcr, int type, const char *VolName)
       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);
@@ -320,17 +334,32 @@ bool write_ansi_ibm_labels(DCR *dcr, int type, const char *VolName)
       ser_bytes(" 000000Bacula              ", 27);
       /* Write HDR1 label */
       if (label_type == B_IBM_LABEL) {
-        ascii_to_ebcdic(label, label, sizeof(label));
+         ascii_to_ebcdic(label, label, sizeof(label));
       }
-      stat = write(dev->fd, 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));
@@ -339,18 +368,31 @@ bool write_ansi_ibm_labels(DCR *dcr, int type, const char *VolName)
       /* Write HDR2 label */
       if (label_type == B_IBM_LABEL) {
          label[4] = 'V';
-        ascii_to_ebcdic(label, label, sizeof(label));
+         ascii_to_ebcdic(label, label, sizeof(label));
       }
-      stat = write(dev->fd, 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:
@@ -367,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;
    }