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