]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/ansi_label.c
Reservation tweaks + more debug output
[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 * volatile 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                Dmsg0(100, "Call reserve_volume\n");
151                reserve_volume(dcr, dev->VolHdr.VolumeName);
152                dev = dcr->dev;            /* may have changed in reserve_volume */
153                Dmsg2(100, "Wanted ANSI Vol %s got %6s\n", VolName, dev->VolHdr.VolumeName);
154                Mmsg2(jcr->errmsg, _("Wanted ANSI Volume \"%s\" got \"%s\"\n"), VolName, dev->VolHdr.VolumeName);
155                return VOL_NAME_ERROR;
156             }
157          }
158          break;
159       case 1:
160          if (dev->label_type == B_IBM_LABEL) {
161             ebcdic_to_ascii(label, label, sizeof(label));
162          }
163          if (stat != 80 || strncmp("HDR1", label, 4) != 0) {
164             Dmsg0(100, "No HDR1 label\n");
165             Mmsg0(jcr->errmsg, _("No HDR1 label while reading ANSI label.\n"));
166             return VOL_LABEL_ERROR;
167          }
168          if (strncmp("BACULA.DATA", &label[4], 11) != 0) {
169             Dmsg1(100, "HD1 not Bacula label. Wanted  BACULA.DATA got %11s\n",
170                &label[4]);
171             Mmsg1(jcr->errmsg, _("ANSI/IBM Volume \"%s\" does not belong to Bacula.\n"),
172                dev->VolHdr.VolumeName);
173             return VOL_NAME_ERROR;     /* Not a Bacula label */
174          }
175          Dmsg0(100, "Got HDR1 label\n");
176          break;
177       case 2:
178          if (dev->label_type == B_IBM_LABEL) {
179             ebcdic_to_ascii(label, label, sizeof(label));
180          }
181          if (stat != 80 || strncmp("HDR2", label, 4) != 0) {
182             Dmsg0(100, "No HDR2 label\n");
183             Mmsg0(jcr->errmsg, _("No HDR2 label while reading ANSI/IBM label.\n"));
184             return VOL_LABEL_ERROR;
185          }
186          Dmsg0(100, "Got ANSI HDR2 label\n");
187          break;
188       default:
189          if (stat == 0) {
190             Dmsg0(100, "ANSI label OK\n");
191             return VOL_OK;
192          }
193          if (dev->label_type == B_IBM_LABEL) {
194             ebcdic_to_ascii(label, label, sizeof(label));
195          }
196          if (stat != 80 || strncmp("HDR", label, 3) != 0) {
197             Dmsg0(100, "Unknown or bad ANSI/IBM label record.\n");
198             Mmsg0(jcr->errmsg, _("Unknown or bad ANSI/IBM label record.\n"));
199             return VOL_LABEL_ERROR;
200          }
201          Dmsg0(100, "Got HDR label\n");
202          break;
203       }
204    }
205    Dmsg0(100, "Too many records in ANSI/IBM label.\n");
206    Mmsg0(jcr->errmsg, _("Too many records in while reading ANSI/IBM label.\n"));
207    return VOL_LABEL_ERROR;
208 }  
209
210 /*
211  * ANSI/IBM VOL1 label
212  *  80 characters blank filled
213  * Pos   count   Function      What Bacula puts
214  * 0-3     4     "VOL1"          VOL1
215  * 4-9     6     Volume name     Volume name
216  * 10-10   1     Access code 
217  * 11-36   26    Unused
218  *
219  * ANSI
220  * 37-50   14    Owner
221  * 51-78   28    reserved
222  * 79       1    ANSI level        3
223  *
224  * IBM
225  * 37-40   4     reserved
226  * 41-50   10    Owner
227  * 51-79   29    reserved
228
229  *
230  *
231  * ANSI/IBM HDR1 label
232  *  80 characters blank filled
233  * Pos   count   Function          What Bacula puts
234  * 0-3     4     "HDR1"               HDR1
235  * 4-20    17    File name           BACULA.DATA
236  * 21-26   6     Volume name          Volume name
237  * 27-30   4     Vol seq num           0001
238  * 31-34   4     file num              0001
239  * 35-38   4     Generation            0001
240  * 39-40   2     Gen version           00
241  * 41-46   6     Create date bYYDDD    yesterday
242  * 47-52   6     Expire date bYYDDD    today
243  * 53-53   1     Access
244  * 54-59   6     Block count           000000
245  * 60-72   13    Software name         Bacula
246  * 73-79   7     Reserved
247
248  * ANSI/IBM HDR2 label
249  *  80 characters blank filled
250  * Pos   count   Function          What Bacula puts
251  * 0-3     4     "HDR2"               HDR2
252  * 4-4     1     Record format        D   (V if IBM) => variable
253  * 5-9     5     Block length         32000
254  * 10-14   5     Rec length           32000
255  * 15-15   1     Density
256  * 16-16   1     Continued 
257  * 17-33   17    Job
258  * 34-35   2     Recording
259  * 36-36   1     cr/lf ctl
260  * 37-37   1     reserved
261  * 38-38   1     Blocked flag
262  * 39-49   11    reserved
263  * 50-51   2     offset
264  * 52-79   28    reserved
265
266  */ 
267
268 static const char *labels[] = {"HDR", "EOF", "EOV"};
269
270 /*
271  * Write an ANSI or IBM 80 character tape label
272  *   Type determines whether we are writing HDR, EOF, or EOV labels
273  *   Assume we are positioned to write the labels
274  *   Returns:  true of OK
275  *             false if error
276  */
277 bool write_ansi_ibm_labels(DCR *dcr, int type, const char *VolName)
278 {
279    DEVICE *dev = dcr->dev;
280    JCR *jcr = dcr->jcr;
281    char label[80];                    /* tape label */
282    char date[20];                     /* ansi date buffer */
283    time_t now;
284    int len, stat, label_type;
285
286    /*
287     * If the Device requires a specific label type use it,
288     * otherwise, use the type requested by the Director
289     */
290    if (dcr->device->label_type != B_BACULA_LABEL) {
291       label_type = dcr->device->label_type;   /* force label type */
292    } else {
293       label_type = dcr->VolCatInfo.LabelType; /* accept Dir type */
294    }
295
296    switch (label_type) {
297    case B_BACULA_LABEL:
298       return true;
299    case B_ANSI_LABEL:
300    case B_IBM_LABEL:
301       ser_declare;
302       Dmsg1(100, "Write ANSI label type=%d\n", label_type);
303       len = strlen(VolName);
304       if (len > 6) {
305          Jmsg1(jcr, M_FATAL, 0, _("ANSI Volume label name \"%s\" longer than 6 chars.\n"),
306             VolName);
307          return false;
308       }
309       if (type == ANSI_VOL_LABEL) {
310          ser_begin(label, sizeof(label));
311          ser_bytes("VOL1", 4);
312          ser_bytes(VolName, len);
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             Jmsg1(jcr, M_FATAL, 0,  _("Could not write ANSI VOL1 label. ERR=%s\n"),
323                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(VolName, len);        /* 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 }