]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/ansi_label.c
Implement Plugin Directory and plugin events.
[bacula/bacula] / bacula / src / stored / ansi_label.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2005-2007 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version two of the GNU General Public
10    License as published by the Free Software Foundation and included
11    in the file LICENSE.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23    Bacula® is a registered trademark of John Walker.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28 /*
29  *
30  *  ansi_label.c routines to handle ANSI (and perhaps one day IBM)
31  *   tape labels.
32  *
33  *   Kern Sibbald, MMV
34  *
35  *
36  *
37  *   Version $Id$
38  */
39
40 #include "bacula.h"                   /* pull in global headers */
41 #include "stored.h"                   /* pull in Storage Deamon headers */
42
43 /* Imported functions */
44 void ascii_to_ebcdic(char *dst, char *src, int count);
45 void ebcdic_to_ascii(char *dst, char *src, int count);
46
47 /* Forward referenced functions */
48 static char *ansi_date(time_t td, char *buf);
49 static bool same_label_names(char *bacula_name, char *ansi_name);
50
51 /*
52  * We read an ANSI label and compare the Volume name. We require
53  * a VOL1 record of 80 characters followed by a HDR1 record containing
54  * BACULA.DATA in the filename field. We then read up to 3 more 
55  * header records (they are not required) and an EOF, at which
56  * point, all is good.
57  *
58  * Returns:
59  *    VOL_OK            Volume name OK
60  *    VOL_NO_LABEL      No ANSI label on Volume
61  *    VOL_IO_ERROR      I/O error on read
62  *    VOL_NAME_ERROR    Wrong name in VOL1 record
63  *    VOL_LABEL_ERROR   Probably an ANSI label, but something wrong
64  *      
65  */ 
66 int read_ansi_ibm_label(DCR *dcr) 
67 {
68    DEVICE *dev = dcr->dev;
69    JCR *jcr = dcr->jcr;
70    char label[80];                    /* tape label */
71    int stat, i;
72    char *VolName = dcr->VolumeName;
73    bool ok = false;
74
75    /*
76     * Read VOL1, HDR1, HDR2 labels, but ignore the data
77     *  If tape read the following EOF mark, on disk do
78     *  not read.
79     */
80    Dmsg0(100, "Read ansi label.\n");
81    if (!dev->is_tape()) {
82       return VOL_OK;
83    }
84
85    dev->label_type = B_BACULA_LABEL;  /* assume Bacula label */
86
87    /* Read a maximum of 5 records VOL1, HDR1, ... HDR4 */
88    for (i=0; i < 6; i++) {
89       do {
90          stat = dev->read(label, sizeof(label));
91       } while (stat == -1 && errno == EINTR);
92       if (stat < 0) {
93          berrno be;
94          dev->clrerror(-1);
95          Dmsg1(100, "Read device got: ERR=%s\n", be.bstrerror());
96          Mmsg2(jcr->errmsg, _("Read error on device %s in ANSI label. ERR=%s\n"),
97             dev->dev_name, be.bstrerror());
98          Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
99          dev->VolCatInfo.VolCatErrors++;
100          return VOL_IO_ERROR;
101       }
102       if (stat == 0) {
103          if (dev->at_eof()) {
104             dev->set_eot();           /* second eof, set eot bit */
105             Dmsg0(100, "EOM on ANSI label\n");
106             Mmsg0(jcr->errmsg, _("Insane! End of tape while reading ANSI label.\n"));
107             return VOL_LABEL_ERROR;   /* at EOM this shouldn't happen */
108          } else {
109             dev->set_ateof();        /* set eof state */
110          }
111       }
112       switch (i) {
113       case 0:                         /* Want VOL1 label */
114          if (stat == 80) {
115             if (strncmp("VOL1", label, 4) == 0) {
116                ok = true;
117                dev->label_type = B_ANSI_LABEL;
118                Dmsg0(100, "Got ANSI VOL1 label\n");
119             } else {
120                /* Try EBCDIC */
121                ebcdic_to_ascii(label, label, sizeof(label));
122                if (strncmp("VOL1", label, 4) == 0) {
123                   ok = true;;
124                   dev->label_type = B_IBM_LABEL;
125                   Dmsg0(100, "Found IBM label.\n");
126                   Dmsg0(100, "Got IBM VOL1 label\n");
127                }
128             }       
129          }
130          if (!ok) {
131             Dmsg0(100, "No VOL1 label\n");
132             Mmsg0(jcr->errmsg, _("No VOL1 label while reading ANSI/IBM label.\n"));
133             return VOL_NO_LABEL;   /* No ANSI label */
134          }
135
136
137          /* Compare Volume Names allow special wild card */
138          if (VolName && *VolName && *VolName != '*') { 
139             if (!same_label_names(VolName, &label[4])) {
140                char *p = &label[4];
141                char *q;  
142
143                free_volume(dev);
144                /* Store new Volume name */
145                q = dev->VolHdr.VolumeName;
146                for (int i=0; *p != ' ' && i < 6; i++) {
147                   *q++ = *p++;
148                }
149                *q = 0;
150                reserve_volume(dcr, dev->VolHdr.VolumeName);
151                Dmsg2(100, "Wanted ANSI Vol %s got %6s\n", VolName, dev->VolHdr.VolumeName);
152                Mmsg2(jcr->errmsg, _("Wanted ANSI Volume \"%s\" got \"%s\"\n"), VolName, dev->VolHdr.VolumeName);
153                return VOL_NAME_ERROR;
154             }
155          }
156          break;
157       case 1:
158          if (dev->label_type == B_IBM_LABEL) {
159             ebcdic_to_ascii(label, label, sizeof(label));
160          }
161          if (stat != 80 || strncmp("HDR1", label, 4) != 0) {
162             Dmsg0(100, "No HDR1 label\n");
163             Mmsg0(jcr->errmsg, _("No HDR1 label while reading ANSI label.\n"));
164             return VOL_LABEL_ERROR;
165          }
166          if (strncmp("BACULA.DATA", &label[4], 11) != 0) {
167             Dmsg1(100, "HD1 not Bacula label. Wanted  BACULA.DATA got %11s\n",
168                &label[4]);
169             Mmsg1(jcr->errmsg, _("ANSI/IBM Volume \"%s\" does not belong to Bacula.\n"),
170                dev->VolHdr.VolumeName);
171             return VOL_NAME_ERROR;     /* Not a Bacula label */
172          }
173          Dmsg0(100, "Got HDR1 label\n");
174          break;
175       case 2:
176          if (dev->label_type == B_IBM_LABEL) {
177             ebcdic_to_ascii(label, label, sizeof(label));
178          }
179          if (stat != 80 || strncmp("HDR2", label, 4) != 0) {
180             Dmsg0(100, "No HDR2 label\n");
181             Mmsg0(jcr->errmsg, _("No HDR2 label while reading ANSI/IBM label.\n"));
182             return VOL_LABEL_ERROR;
183          }
184          Dmsg0(100, "Got ANSI HDR2 label\n");
185          break;
186       default:
187          if (stat == 0) {
188             Dmsg0(100, "ANSI label OK\n");
189             return VOL_OK;
190          }
191          if (dev->label_type == B_IBM_LABEL) {
192             ebcdic_to_ascii(label, label, sizeof(label));
193          }
194          if (stat != 80 || strncmp("HDR", label, 3) != 0) {
195             Dmsg0(100, "Unknown or bad ANSI/IBM label record.\n");
196             Mmsg0(jcr->errmsg, _("Unknown or bad ANSI/IBM label record.\n"));
197             return VOL_LABEL_ERROR;
198          }
199          Dmsg0(100, "Got HDR label\n");
200          break;
201       }
202    }
203    Dmsg0(100, "Too many records in ANSI/IBM label.\n");
204    Mmsg0(jcr->errmsg, _("Too many records in while reading ANSI/IBM label.\n"));
205    return VOL_LABEL_ERROR;
206 }  
207
208 /*
209  * ANSI/IBM VOL1 label
210  *  80 characters blank filled
211  * Pos   count   Function      What Bacula puts
212  * 0-3     4     "VOL1"          VOL1
213  * 4-9     6     Volume name     Volume name
214  * 10-10   1     Access code 
215  * 11-36   26    Unused
216  *
217  * ANSI
218  * 37-50   14    Owner
219  * 51-78   28    reserved
220  * 79       1    ANSI level        3
221  *
222  * IBM
223  * 37-40   4     reserved
224  * 41-50   10    Owner
225  * 51-79   29    reserved
226
227  *
228  *
229  * ANSI/IBM HDR1 label
230  *  80 characters blank filled
231  * Pos   count   Function          What Bacula puts
232  * 0-3     4     "HDR1"               HDR1
233  * 4-20    17    File name           BACULA.DATA
234  * 21-26   6     Volume name          Volume name
235  * 27-30   4     Vol seq num           0001
236  * 31-34   4     file num              0001
237  * 35-38   4     Generation            0001
238  * 39-40   2     Gen version           00
239  * 41-46   6     Create date bYYDDD    yesterday
240  * 47-52   6     Expire date bYYDDD    today
241  * 53-53   1     Access
242  * 54-59   6     Block count           000000
243  * 60-72   13    Software name         Bacula
244  * 73-79   7     Reserved
245
246  * ANSI/IBM HDR2 label
247  *  80 characters blank filled
248  * Pos   count   Function          What Bacula puts
249  * 0-3     4     "HDR2"               HDR2
250  * 4-4     1     Record format        D   (V if IBM) => variable
251  * 5-9     5     Block length         32000
252  * 10-14   5     Rec length           32000
253  * 15-15   1     Density
254  * 16-16   1     Continued 
255  * 17-33   17    Job
256  * 34-35   2     Recording
257  * 36-36   1     cr/lf ctl
258  * 37-37   1     reserved
259  * 38-38   1     Blocked flag
260  * 39-49   11    reserved
261  * 50-51   2     offset
262  * 52-79   28    reserved
263
264  */ 
265
266 static const char *labels[] = {"HDR", "EOF", "EOV"};
267
268 /*
269  * Write an ANSI or IBM 80 character tape label
270  *   Type determines whether we are writing HDR, EOF, or EOV labels
271  *   Assume we are positioned to write the labels
272  *   Returns:  true of OK
273  *             false if error
274  */
275 bool write_ansi_ibm_labels(DCR *dcr, int type, const char *VolName)
276 {
277    DEVICE *dev = dcr->dev;
278    JCR *jcr = dcr->jcr;
279    char label[80];                    /* tape label */
280    char date[20];                     /* ansi date buffer */
281    time_t now;
282    int len, stat, label_type;
283
284    /*
285     * If the Device requires a specific label type use it,
286     * otherwise, use the type requested by the Director
287     */
288    if (dcr->device->label_type != B_BACULA_LABEL) {
289       label_type = dcr->device->label_type;   /* force label type */
290    } else {
291       label_type = dcr->VolCatInfo.LabelType; /* accept Dir type */
292    }
293
294    switch (label_type) {
295    case B_BACULA_LABEL:
296       return true;
297    case B_ANSI_LABEL:
298    case B_IBM_LABEL:
299       ser_declare;
300       Dmsg1(100, "Write ANSI label type=%d\n", label_type);
301       len = strlen(VolName);
302       if (len > 6) {
303          Jmsg1(jcr, M_FATAL, 0, _("ANSI Volume label name \"%s\" longer than 6 chars.\n"),
304             VolName);
305          return false;
306       }
307       if (type == ANSI_VOL_LABEL) {
308          ser_begin(label, sizeof(label));
309          ser_bytes("VOL1", 4);
310          ser_bytes(VolName, len);
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             Jmsg1(jcr, M_FATAL, 0,  _("Could not write ANSI VOL1 label. ERR=%s\n"),
321                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(VolName, len);        /* 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(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(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 }