]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/ansi_label.c
Apply patches from bugs #2325 and #2326 to fix FIFO bugs
[bacula/bacula] / bacula / src / stored / ansi_label.c
1 /*
2    Bacula(R) - The Network Backup Solution
3
4    Copyright (C) 2000-2017 Kern Sibbald
5
6    The original author of Bacula is Kern Sibbald, with contributions
7    from many others, a complete list can be found in the file AUTHORS.
8
9    You may use this file and others of this release according to the
10    license defined in the LICENSE file, which includes the Affero General
11    Public License, v3.0 ("AGPLv3") and some additional permissions and
12    terms pursuant to its AGPLv3 Section 7.
13
14    This notice must be preserved when any source code is
15    conveyed and/or propagated.
16
17    Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19 /*
20  *
21  *  ansi_label.c routines to handle ANSI (and perhaps one day IBM)
22  *   tape labels.
23  *
24  *   Kern Sibbald, MMV
25  */
26
27 #include "bacula.h"                   /* pull in global headers */
28 #include "stored.h"                   /* pull in Storage Deamon headers */
29
30 /* Imported functions */
31 void ascii_to_ebcdic(char *dst, char *src, int count);
32 void ebcdic_to_ascii(char *dst, char *src, int count);
33
34 /* Forward referenced functions */
35 static char *ansi_date(time_t td, char *buf);
36 static bool same_label_names(char *bacula_name, char *ansi_name);
37
38 /*
39  * We read an ANSI label and compare the Volume name. We require
40  * a VOL1 record of 80 characters followed by a HDR1 record containing
41  * BACULA.DATA in the filename field. We then read up to 3 more
42  * header records (they are not required) and an EOF, at which
43  * point, all is good.
44  *
45  * Returns:
46  *    VOL_OK            Volume name OK
47  *    VOL_NO_LABEL      No ANSI label on Volume
48  *    VOL_IO_ERROR      I/O error on read
49  *    VOL_NAME_ERROR    Wrong name in VOL1 record
50  *    VOL_LABEL_ERROR   Probably an ANSI label, but something wrong
51  *
52  */
53 int read_ansi_ibm_label(DCR *dcr)
54 {
55    DEVICE * volatile dev = dcr->dev;
56    JCR *jcr = dcr->jcr;
57    char label[80];                    /* tape label */
58    int stat, i;
59    char *VolName = dcr->VolumeName;
60    bool ok = false;
61
62    /*
63     * Read VOL1, HDR1, HDR2 labels, but ignore the data
64     *  If tape read the following EOF mark, on disk do
65     *  not read.
66     */
67    Dmsg0(100, "Read ansi label.\n");
68    if (!dev->is_tape()) {
69       return VOL_OK;
70    }
71
72    dev->label_type = B_BACULA_LABEL;  /* assume Bacula label */
73
74    /* Read a maximum of 5 records VOL1, HDR1, ... HDR4 */
75    for (i=0; i < 6; i++) {
76       do {
77          stat = dev->read(label, sizeof(label));
78       } while (stat == -1 && errno == EINTR);
79       if (stat < 0) {
80          berrno be;
81          dev->clrerror(-1);
82          Dmsg1(100, "Read device got: ERR=%s\n", be.bstrerror());
83          Mmsg2(jcr->errmsg, _("Read error on device %s in ANSI label. ERR=%s\n"),
84             dev->dev_name, be.bstrerror());
85          Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
86          dev->VolCatInfo.VolCatErrors++;
87          return VOL_IO_ERROR;
88       }
89       if (stat == 0) {
90          if (dev->at_eof()) {
91             dev->set_eot();           /* second eof, set eot bit */
92             Dmsg0(100, "EOM on ANSI label\n");
93             Mmsg0(jcr->errmsg, _("Insane! End of tape while reading ANSI label.\n"));
94             return VOL_LABEL_ERROR;   /* at EOM this shouldn't happen */
95          } else {
96             dev->set_ateof();        /* set eof state */
97          }
98       }
99       switch (i) {
100       case 0:                         /* Want VOL1 label */
101          if (stat == 80) {
102             if (strncmp("VOL1", label, 4) == 0) {
103                ok = true;
104                dev->label_type = B_ANSI_LABEL;
105                Dmsg0(100, "Got ANSI VOL1 label\n");
106             } else {
107                /* Try EBCDIC */
108                ebcdic_to_ascii(label, label, sizeof(label));
109                if (strncmp("VOL1", label, 4) == 0) {
110                   ok = true;;
111                   dev->label_type = B_IBM_LABEL;
112                   Dmsg0(100, "Found IBM label.\n");
113                   Dmsg0(100, "Got IBM VOL1 label\n");
114                }
115             }
116          }
117          if (!ok) {
118             Dmsg0(100, "No VOL1 label\n");
119             Mmsg0(jcr->errmsg, _("No VOL1 label while reading ANSI/IBM label.\n"));
120             return VOL_NO_LABEL;   /* No ANSI label */
121          }
122
123
124          /* Compare Volume Names allow special wild card */
125          if (VolName && *VolName && *VolName != '*') {
126             if (!same_label_names(VolName, &label[4])) {
127                char *p = &label[4];
128                char *q;
129
130                free_volume(dev);
131                /* Store new Volume name */
132                q = dev->VolHdr.VolumeName;
133                for (int i=0; *p != ' ' && i < 6; i++) {
134                   *q++ = *p++;
135                }
136                *q = 0;
137                Dmsg0(100, "Call reserve_volume\n");
138                /* ***FIXME***  why is this reserve_volume() needed???? KES */
139                reserve_volume(dcr, dev->VolHdr.VolumeName);
140                dev = dcr->dev;            /* may have changed in reserve_volume */
141                Dmsg2(100, "Wanted ANSI Vol %s got %6s\n", VolName, dev->VolHdr.VolumeName);
142                Mmsg2(jcr->errmsg, _("Wanted ANSI Volume \"%s\" got \"%s\"\n"), VolName, dev->VolHdr.VolumeName);
143                return VOL_NAME_ERROR;
144             }
145          }
146          break;
147       case 1:
148          if (dev->label_type == B_IBM_LABEL) {
149             ebcdic_to_ascii(label, label, sizeof(label));
150          }
151          if (stat != 80 || strncmp("HDR1", label, 4) != 0) {
152             Dmsg0(100, "No HDR1 label\n");
153             Mmsg0(jcr->errmsg, _("No HDR1 label while reading ANSI label.\n"));
154             return VOL_LABEL_ERROR;
155          }
156          if (strncmp("BACULA.DATA", &label[4], 11) != 0) {
157             Dmsg1(100, "HD1 not Bacula label. Wanted  BACULA.DATA got %11s\n",
158                &label[4]);
159             Mmsg1(jcr->errmsg, _("ANSI/IBM Volume \"%s\" does not belong to Bacula.\n"),
160                dev->VolHdr.VolumeName);
161             return VOL_NAME_ERROR;     /* Not a Bacula label */
162          }
163          Dmsg0(100, "Got HDR1 label\n");
164          break;
165       case 2:
166          if (dev->label_type == B_IBM_LABEL) {
167             ebcdic_to_ascii(label, label, sizeof(label));
168          }
169          if (stat != 80 || strncmp("HDR2", label, 4) != 0) {
170             Dmsg0(100, "No HDR2 label\n");
171             Mmsg0(jcr->errmsg, _("No HDR2 label while reading ANSI/IBM label.\n"));
172             return VOL_LABEL_ERROR;
173          }
174          Dmsg0(100, "Got ANSI HDR2 label\n");
175          break;
176       default:
177          if (stat == 0) {
178             Dmsg0(100, "ANSI label OK\n");
179             return VOL_OK;
180          }
181          if (dev->label_type == B_IBM_LABEL) {
182             ebcdic_to_ascii(label, label, sizeof(label));
183          }
184          if (stat != 80 || strncmp("HDR", label, 3) != 0) {
185             Dmsg0(100, "Unknown or bad ANSI/IBM label record.\n");
186             Mmsg0(jcr->errmsg, _("Unknown or bad ANSI/IBM label record.\n"));
187             return VOL_LABEL_ERROR;
188          }
189          Dmsg0(100, "Got HDR label\n");
190          break;
191       }
192    }
193    Dmsg0(100, "Too many records in ANSI/IBM label.\n");
194    Mmsg0(jcr->errmsg, _("Too many records in while reading ANSI/IBM label.\n"));
195    return VOL_LABEL_ERROR;
196 }
197
198 /*
199  * ANSI/IBM VOL1 label
200  *  80 characters blank filled
201  * Pos   count   Function      What Bacula puts
202  * 0-3     4     "VOL1"          VOL1
203  * 4-9     6     Volume name     Volume name
204  * 10-10   1     Access code
205  * 11-36   26    Unused
206  *
207  * ANSI
208  * 37-50   14    Owner
209  * 51-78   28    reserved
210  * 79       1    ANSI level        3
211  *
212  * IBM
213  * 37-40   4     reserved
214  * 41-50   10    Owner
215  * 51-79   29    reserved
216
217  *
218  *
219  * ANSI/IBM HDR1 label
220  *  80 characters blank filled
221  * Pos   count   Function          What Bacula puts
222  * 0-3     4     "HDR1"               HDR1
223  * 4-20    17    File name           BACULA.DATA
224  * 21-26   6     Volume name          Volume name
225  * 27-30   4     Vol seq num           0001
226  * 31-34   4     file num              0001
227  * 35-38   4     Generation            0001
228  * 39-40   2     Gen version           00
229  * 41-46   6     Create date bYYDDD    yesterday
230  * 47-52   6     Expire date bYYDDD    today
231  * 53-53   1     Access
232  * 54-59   6     Block count           000000
233  * 60-72   13    Software name         Bacula
234  * 73-79   7     Reserved
235
236  * ANSI/IBM HDR2 label
237  *  80 characters blank filled
238  * Pos   count   Function          What Bacula puts
239  * 0-3     4     "HDR2"               HDR2
240  * 4-4     1     Record format        D   (V if IBM) => variable
241  * 5-9     5     Block length         32000
242  * 10-14   5     Rec length           32000
243  * 15-15   1     Density
244  * 16-16   1     Continued
245  * 17-33   17    Job
246  * 34-35   2     Recording
247  * 36-36   1     cr/lf ctl
248  * 37-37   1     reserved
249  * 38-38   1     Blocked flag
250  * 39-49   11    reserved
251  * 50-51   2     offset
252  * 52-79   28    reserved
253
254  */
255
256 static const char *labels[] = {"HDR", "EOF", "EOV"};
257
258 /*
259  * Write an ANSI or IBM 80 character tape label
260  *   Type determines whether we are writing HDR, EOF, or EOV labels
261  *   Assume we are positioned to write the labels
262  *   Returns:  true of OK
263  *             false if error
264  */
265 bool write_ansi_ibm_labels(DCR *dcr, int type, const char *VolName)
266 {
267    DEVICE *dev = dcr->dev;
268    JCR *jcr = dcr->jcr;
269    char ansi_volname[7];              /* 6 char + \0 */
270    char label[80];                    /* tape label */
271    char date[20];                     /* ansi date buffer */
272    time_t now;
273    int len, stat, label_type;
274
275    /*
276     * If the Device requires a specific label type use it,
277     * otherwise, use the type requested by the Director
278     */
279    if (dcr->device->label_type != B_BACULA_LABEL) {
280       label_type = dcr->device->label_type;   /* force label type */
281    } else {
282       label_type = dcr->VolCatInfo.LabelType; /* accept Dir type */
283    }
284
285    switch (label_type) {
286    case B_BACULA_LABEL:
287       return true;
288    case B_ANSI_LABEL:
289    case B_IBM_LABEL:
290       ser_declare;
291       Dmsg1(100, "Write ANSI label type=%d\n", label_type);
292       len = strlen(VolName);
293       if (len > 6) {
294          Jmsg1(jcr, M_FATAL, 0, _("ANSI Volume label name \"%s\" longer than 6 chars.\n"),
295             VolName);
296          return false;
297       }
298       /* ANSI labels have 6 characters, and are padded with spaces
299        * 'vol1\0' => 'vol1   \0'
300        */
301       strcpy(ansi_volname, VolName);
302       for(int i=len; i < 6; i++) {
303          ansi_volname[i]=' ';
304       }
305       ansi_volname[6]='\0';     /* only for debug */
306
307       if (type == ANSI_VOL_LABEL) {
308          ser_begin(label, sizeof(label));
309          ser_bytes("VOL1", 4);
310          ser_bytes(ansi_volname, 6);
311          /* Write VOL1 label */
312          if (label_type == B_IBM_LABEL) {
313             ascii_to_ebcdic(label, label, sizeof(label));
314          } else {
315             label[79] = '3';                /* ANSI label flag */
316          }
317          stat = dev->write(label, sizeof(label));
318          if (stat != sizeof(label)) {
319             berrno be;
320             Jmsg3(jcr, M_FATAL, 0,  _("Could not write ANSI VOL1 label. Wanted size=%d got=%d ERR=%s\n"),
321                sizeof(label), stat, be.bstrerror());
322             return false;
323          }
324       }
325
326       /* Now construct HDR1 label */
327       memset(label, ' ', sizeof(label));
328       ser_begin(label, sizeof(label));
329       ser_bytes(labels[type], 3);
330       ser_bytes("1", 1);
331       ser_bytes("BACULA.DATA", 11);            /* Filename field */
332       ser_begin(&label[21], sizeof(label)-21); /* fileset field */
333       ser_bytes(ansi_volname, 6);              /* write Vol Ser No. */
334       ser_begin(&label[27], sizeof(label)-27);
335       ser_bytes("00010001000100", 14);  /* File section, File seq no, Generation no */
336       now = time(NULL);
337       ser_bytes(ansi_date(now, date), 6); /* current date */
338       ser_bytes(ansi_date(now - 24 * 3600, date), 6); /* created yesterday */
339       ser_bytes(" 000000Bacula              ", 27);
340       /* Write HDR1 label */
341       if (label_type == B_IBM_LABEL) {
342          ascii_to_ebcdic(label, label, sizeof(label));
343       }
344
345       /*
346        * This could come at the end of a tape, ignore
347        *  EOT errors.
348        */
349       stat = dev->write(label, sizeof(label));
350       if (stat != sizeof(label)) {
351          berrno be;
352          if (stat == -1) {
353             dev->clrerror(-1);
354             if (dev->dev_errno == 0) {
355                dev->dev_errno = ENOSPC; /* out of space */
356             }
357             if (dev->dev_errno != ENOSPC) {
358                Jmsg1(jcr, M_FATAL, 0, _("Could not write ANSI HDR1 label. ERR=%s\n"),
359                be.bstrerror());
360                return false;
361             }
362          } else {
363             Jmsg(jcr, M_FATAL, 0, _("Could not write ANSI HDR1 label.\n"));
364             return false;
365          }
366       }
367
368       /* Now construct HDR2 label */
369       memset(label, ' ', sizeof(label));
370       ser_begin(label, sizeof(label));
371       ser_bytes(labels[type], 3);
372       ser_bytes("2D3200032000", 12);
373       /* Write HDR2 label */
374       if (label_type == B_IBM_LABEL) {
375          label[4] = 'V';
376          ascii_to_ebcdic(label, label, sizeof(label));
377       }
378       stat = dev->write(label, sizeof(label));
379       if (stat != sizeof(label)) {
380          berrno be;
381          if (stat == -1) {
382             dev->clrerror(-1);
383             if (dev->dev_errno == 0) {
384                dev->dev_errno = ENOSPC; /* out of space */
385             }
386             if (dev->dev_errno != ENOSPC) {
387                Jmsg1(jcr, M_FATAL, 0, _("Could not write ANSI HDR1 label. ERR=%s\n"),
388                be.bstrerror());
389                return false;
390             }
391             dev->weof(NULL, 1);
392             return true;
393          } else {
394             Jmsg(jcr, M_FATAL, 0, _("Could not write ANSI HDR1 label.\n"));
395             return false;
396          }
397       }
398       if (!dev->weof(NULL, 1)) {
399          Jmsg(jcr, M_FATAL, 0, _("Error writing EOF to tape. ERR=%s"), dev->errmsg);
400          return false;
401       }
402       return true;
403    default:
404       Jmsg0(jcr, M_ABORT, 0, _("write_ansi_ibm_label called for non-ANSI/IBM type\n"));
405       return false; /* should not get here */
406    }
407 }
408
409 /* Check a Bacula Volume name against an ANSI Volume name */
410 static bool same_label_names(char *bacula_name, char *ansi_name)
411 {
412    char *a = ansi_name;
413    char *b = bacula_name;
414    /* Six characters max */
415    for (int i=0; i < 6; i++) {
416       if (*a == *b) {
417          a++;
418          b++;
419          continue;
420       }
421       /* ANSI labels are blank filled, Bacula's are zero terminated */
422       if (*a == ' ' && *b == 0) {
423          return true;
424       }
425       return false;
426    }
427    /* Reached 6 characters */
428    b++;
429    if (*b == 0) {
430       return true;
431    }
432    return false;
433 }
434
435 /*
436  * ANSI date
437  *  ' 'YYDDD
438  */
439 static char *ansi_date(time_t td, char *buf)
440 {
441    struct tm *tm;
442
443    if (td == 0) {
444       td = time(NULL);
445    }
446    tm = gmtime(&td);
447    bsnprintf(buf, 10, " %05d ", 1000 * (tm->tm_year + 1900 - 2000) + tm->tm_yday);
448    return buf;
449 }