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