+
+/*
+ * Write an ANSI or IBM 80 character tape label
+ * Assume we are positioned at the beginning of the tape.
+ * Returns: true of OK
+ * false if error
+ */
+bool write_ansi_ibm_label(DCR *dcr, const char *VolName)
+{
+ DEVICE *dev = dcr->dev;
+ JCR *jcr = dcr->jcr;
+ char label[80]; /* tape label */
+ char date[20]; /* ansi date buffer */
+ time_t now;
+ int len;
+ int stat;
+
+ switch (dcr->VolCatInfo.LabelType) {
+ case B_BACULA_LABEL:
+ return true;
+ case B_ANSI_LABEL:
+ case B_IBM_LABEL:
+ ser_declare;
+ Dmsg0(000, "Write ansi label.\n");
+ len = strlen(VolName);
+ if (len > 6) {
+ len = 6; /* max len ANSI label */
+ }
+ memset(label, ' ', sizeof(label));
+ ser_begin(label, sizeof(label));
+ ser_bytes("VOL1", 4);
+ ser_bytes(VolName, len);
+ label[79] = '1'; /* 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;
+ }
+ /* Now construct HDR1 label */
+ ser_begin(label, sizeof(label));
+ ser_bytes("HDR1", 4);
+ len = strlen(VolName);
+ if (len > 17) {
+ len = 17; /* Max filename len */
+ }
+ ser_bytes(VolName, len); /* stick Volume name in Filename field */
+ if (len > 6) {
+ len = 6;
+ }
+ ser_begin(&label[21], sizeof(label)-21);
+ ser_bytes(VolName, len); /* write Vol Ser No. */
+ ser_begin(&label[27], sizeof(label)-27);
+ ser_bytes("000100010001", 12); /* File section, File seq no, Generation no */
+ 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);
+ /* Write HDR1 label */
+ stat = write(dev->fd, 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;
+ }
+ /* 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));
+ if (stat != sizeof(label)) {
+ berrno be;
+ Jmsg1(jcr, M_FATAL, 0, _("Could not write ANSI HDR1 label. ERR=%s\n"),
+ be.strerror());
+ return false;
+ }
+ if (weof_dev(dev, 1) < 0) {
+ Jmsg(jcr, M_FATAL, 0, _("Error writing EOF to tape. ERR=%s"), dev->errmsg);
+ return false;
+ }
+ return true;
+ default:
+ Jmsg0(jcr, M_ABORT, 0, _("write_ansi_ibm_label called for non-ANSI/IBM type\n"));
+ return false; /* should not get here */
+ }
+}
+
+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;
+
+ 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(000, "Read ansi label.\n");
+ if (dev->state & ST_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);
+ if (stat < 0) {
+ berrno be;
+ clrerror_dev(dev, -1);
+ Dmsg1(200, "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->state & ST_EOF) { /* EOF just seen? */
+ dev->state |= ST_EOT; /* yes, error => EOT */
+ }
+ return VOL_IO_ERROR;
+ }
+ Dmsg1(000, "ANSI label=%80s\n", label);
+ }
+ return VOL_OK;
+}
+
+
+static char *ansi_date(time_t td, char *buf)
+{
+ struct tm *tm;
+
+ if (td == 0) {
+ td = time(NULL);
+ }
+ tm = gmtime(&td);
+ bsnprintf(buf, 6, "%d", 1000 * (tm->tm_year + 1900 - 2000) + tm->tm_yday);
+ return buf;
+}