]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/ansi_label.c
- Modify open() for tape so nonblocking really works.
[bacula/bacula] / bacula / src / stored / ansi_label.c
1 /*
2  *
3  *  ansi_label.c routines to handle ANSI (and perhaps one day IBM)
4  *   tape labels.
5  *
6  *   Kern Sibbald, MMV
7  *
8  *
9  *
10  *   Version $Id$
11  */
12 /*
13    Copyright (C) 2005 Kern Sibbald
14
15    This program is free software; you can redistribute it and/or
16    modify it under the terms of the GNU General Public License
17    version 2 as amended with additional clauses defined in the
18    file LICENSE in the main source directory.
19
20    This program is distributed in the hope that it will be useful,
21    but WITHOUT ANY WARRANTY; without even the implied warranty of
22    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
23    the file LICENSE for additional details.
24
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 *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 = read(dev->fd, label, sizeof(label));
78       } while (stat == -1 && errno == EINTR);
79       if (stat < 0) {
80          berrno be;
81          clrerror_dev(dev, -1);
82          Dmsg1(100, "Read device got: ERR=%s\n", be.strerror());
83          Mmsg2(jcr->errmsg, _("Read error on device %s in ANSI label. ERR=%s\n"),
84             dev->dev_name, be.strerror());
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             } else {
106                /* Try EBCDIC */
107                ebcdic_to_ascii(label, label, sizeof(label));
108                if (strncmp("VOL1", label, 4) == 0) {
109                   ok = true;;
110                   dev->label_type = B_IBM_LABEL;
111                   Dmsg0(100, "Found IBM label.\n");
112                }
113             }       
114          }
115          if (!ok) {
116             Dmsg0(100, "No VOL1 label\n");
117             Mmsg0(jcr->errmsg, _("No VOL1 label while reading ANSI/IBM label.\n"));
118             return VOL_NO_LABEL;   /* No ANSI label */
119          }
120
121
122          /* Compare Volume Names allow special wild card */
123          if (VolName && *VolName && *VolName != '*') { 
124             if (!same_label_names(VolName, &label[4])) {
125                char *p = &label[4];
126                char *q;  
127
128                free_volume(dev);
129                /* Store new Volume name */
130                q = dev->VolHdr.VolumeName;
131                for (int i=0; *p != ' ' && i < 6; i++) {
132                   *q++ = *p++;
133                }
134                *q = 0;
135                new_volume(dcr, dev->VolHdr.VolumeName);
136                Dmsg2(100, "Wanted ANSI Vol %s got %6s\n", VolName, dev->VolHdr.VolumeName);
137                Mmsg2(jcr->errmsg, "Wanted ANSI Volume \"%s\" got \"%s\"\n", VolName, dev->VolHdr.VolumeName);
138                return VOL_NAME_ERROR;
139             }
140          }
141          break;
142       case 1:
143          if (dev->label_type == B_IBM_LABEL) {
144             ebcdic_to_ascii(label, label, sizeof(label));
145          }
146          if (stat != 80 || strncmp("HDR1", label, 4) != 0) {
147             Dmsg0(100, "No HDR1 label\n");
148             Mmsg0(jcr->errmsg, _("No HDR1 label while reading ANSI label.\n"));
149             return VOL_LABEL_ERROR;
150          }
151          if (strncmp("BACULA.DATA", &label[4], 11) != 0) {
152             Dmsg1(100, "HD1 not Bacula label. Wanted  BACULA.DATA got %11s\n",
153                &label[4]);
154             Mmsg1(jcr->errmsg, _("ANSI/IBM Volume \"%s\" does not belong to Bacula.\n"),
155                dev->VolHdr.VolumeName);
156             return VOL_NAME_ERROR;     /* Not a Bacula label */
157          }
158          break;
159       case 2:
160          if (dev->label_type == B_IBM_LABEL) {
161             ebcdic_to_ascii(label, label, sizeof(label));
162          }
163          if (stat != 80 || strncmp("HDR2", label, 4) != 0) {
164             Dmsg0(100, "No HDR2 label\n");
165             Mmsg0(jcr->errmsg, _("No HDR2 label while reading ANSI/IBM label.\n"));
166             return VOL_LABEL_ERROR;
167          }
168          break;
169       default:
170          if (stat == 0) {
171             Dmsg0(100, "ANSI label OK\n");
172             return VOL_OK;
173          }
174          if (dev->label_type == B_IBM_LABEL) {
175             ebcdic_to_ascii(label, label, sizeof(label));
176          }
177          if (stat != 80 || strncmp("HDR", label, 3) != 0) {
178             Dmsg0(100, "Unknown or bad ANSI/IBM label record.\n");
179             Mmsg0(jcr->errmsg, _("Unknown or bad ANSI/IBM label record.\n"));
180             return VOL_LABEL_ERROR;
181          }
182          break;
183       }
184    }
185    Dmsg0(100, "Too many records in ANSI/IBM label.\n");
186    Mmsg0(jcr->errmsg, _("Too many records in while reading ANSI/IBM label.\n"));
187    return VOL_LABEL_ERROR;
188 }  
189
190 /*
191  * ANSI/IBM VOL1 label
192  *  80 characters blank filled
193  * Pos   count   Function      What Bacula puts
194  * 0-3     4     "VOL1"          VOL1
195  * 4-9     6     Volume name     Volume name
196  * 10-10   1     Access code 
197  * 11-36   26    Unused
198  *
199  * ANSI
200  * 37-50   14    Owner
201  * 51-78   28    reserved
202  * 79       1    ANSI level        3
203  *
204  * IBM
205  * 37-40   4     reserved
206  * 41-50   10    Owner
207  * 51-79   29    reserved
208
209  *
210  *
211  * ANSI/IBM HDR1 label
212  *  80 characters blank filled
213  * Pos   count   Function          What Bacula puts
214  * 0-3     4     "HDR1"               HDR1
215  * 4-20    17    File name           BACULA.DATA
216  * 21-26   6     Volume name          Volume name
217  * 27-30   4     Vol seq num           0001
218  * 31-34   4     file num              0001
219  * 35-38   4     Generation            0001
220  * 39-40   2     Gen version           00
221  * 41-46   6     Create date bYYDDD    yesterday
222  * 47-52   6     Expire date bYYDDD    today
223  * 53-53   1     Access
224  * 54-59   6     Block count           000000
225  * 60-72   13    Software name         Bacula
226  * 73-79   7     Reserved
227
228  * ANSI/IBM HDR2 label
229  *  80 characters blank filled
230  * Pos   count   Function          What Bacula puts
231  * 0-3     4     "HDR2"               HDR2
232  * 4-4     1     Record format        D   (V if IBM) => variable
233  * 5-9     5     Block length         32000
234  * 10-14   5     Rec length           32000
235  * 15-15   1     Density
236  * 16-16   1     Continued 
237  * 17-33   17    Job
238  * 34-35   2     Recording
239  * 36-36   1     cr/lf ctl
240  * 37-37   1     reserved
241  * 38-38   1     Blocked flag
242  * 39-49   11    reserved
243  * 50-51   2     offset
244  * 52-79   28    reserved
245
246  */ 
247
248 static const char *labels[] = {"HDR", "EOF", "EOV"};
249
250 /*
251  * Write an ANSI or IBM 80 character tape label
252  *   Type determines whether we are writing HDR, EOF, or EOV labels
253  *   Assume we are positioned to write the labels
254  *   Returns:  true of OK
255  *             false if error
256  */
257 bool write_ansi_ibm_labels(DCR *dcr, int type, const char *VolName)
258 {
259    DEVICE *dev = dcr->dev;
260    JCR *jcr = dcr->jcr;
261    char label[80];                    /* tape label */
262    char date[20];                     /* ansi date buffer */
263    time_t now;
264    int len, stat, label_type;
265
266    /*
267     * If the Device requires a specific label type use it,
268     * otherwise, use the type requested by the Director
269     */
270    if (dcr->device->label_type != B_BACULA_LABEL) {
271       label_type = dcr->device->label_type;   /* force label type */
272    } else {
273       label_type = dcr->VolCatInfo.LabelType; /* accept Dir type */
274    }
275
276    switch (label_type) {
277    case B_BACULA_LABEL:
278       return true;
279    case B_ANSI_LABEL:
280    case B_IBM_LABEL:
281       ser_declare;
282       Dmsg1(100, "Write ANSI label type=%d\n", label_type);
283       len = strlen(VolName);
284       if (len > 6) {
285          Jmsg1(jcr, M_FATAL, 0, _("ANSI Volume label name \"%s\" longer than 6 chars.\n"),
286             VolName);
287          return false;
288       }
289       if (type == ANSI_VOL_LABEL) {
290          ser_begin(label, sizeof(label));
291          ser_bytes("VOL1", 4);
292          ser_bytes(VolName, len);
293          /* Write VOL1 label */
294          if (label_type == B_IBM_LABEL) {
295             ascii_to_ebcdic(label, label, sizeof(label));
296          } else {
297             label[79] = '3';                /* ANSI label flag */
298          }
299          stat = write(dev->fd, label, sizeof(label));
300          if (stat != sizeof(label)) {
301             berrno be;
302             Jmsg1(jcr, M_FATAL, 0,  _("Could not write ANSI VOL1 label. ERR=%s\n"),
303                be.strerror());
304             return false;
305          }
306       }
307
308       /* Now construct HDR1 label */
309       memset(label, ' ', sizeof(label));
310       ser_begin(label, sizeof(label));
311       ser_bytes(labels[type], 3);
312       ser_bytes("1", 1);
313       ser_bytes("BACULA.DATA", 11);            /* Filename field */
314       ser_begin(&label[21], sizeof(label)-21); /* fileset field */
315       ser_bytes(VolName, len);        /* write Vol Ser No. */
316       ser_begin(&label[27], sizeof(label)-27);
317       ser_bytes("00010001000100", 14);  /* File section, File seq no, Generation no */
318       now = time(NULL);
319       ser_bytes(ansi_date(now, date), 6); /* current date */
320       ser_bytes(ansi_date(now - 24 * 3600, date), 6); /* created yesterday */
321       ser_bytes(" 000000Bacula              ", 27);
322       /* Write HDR1 label */
323       if (label_type == B_IBM_LABEL) {
324          ascii_to_ebcdic(label, label, sizeof(label));
325       }
326
327       /*
328        * This could come at the end of a tape, ignore
329        *  EOT errors.
330        */
331       stat = write(dev->fd, label, sizeof(label));
332       if (stat != sizeof(label)) {
333          berrno be;
334          if (stat == -1) {
335             clrerror_dev(dev, -1);
336             if (dev->dev_errno == 0) {
337                dev->dev_errno = ENOSPC; /* out of space */
338             }
339             if (dev->dev_errno != ENOSPC) {
340                Jmsg1(jcr, M_FATAL, 0, _("Could not write ANSI HDR1 label. ERR=%s\n"),
341                be.strerror());
342                return false;
343             }
344          } else {
345             Jmsg(jcr, M_FATAL, 0, _("Could not write ANSI HDR1 label.\n"));
346             return false;
347          }
348       }
349
350       /* Now construct HDR2 label */
351       memset(label, ' ', sizeof(label));
352       ser_begin(label, sizeof(label));
353       ser_bytes(labels[type], 3);
354       ser_bytes("2D3200032000", 12);
355       /* Write HDR2 label */
356       if (label_type == B_IBM_LABEL) {
357          label[4] = 'V';
358          ascii_to_ebcdic(label, label, sizeof(label));
359       }
360       stat = write(dev->fd, label, sizeof(label));
361       if (stat != sizeof(label)) {
362          berrno be;
363          if (stat == -1) {
364             clrerror_dev(dev, -1);
365             if (dev->dev_errno == 0) {
366                dev->dev_errno = ENOSPC; /* out of space */
367             }
368             if (dev->dev_errno != ENOSPC) {
369                Jmsg1(jcr, M_FATAL, 0, _("Could not write ANSI HDR1 label. ERR=%s\n"),
370                be.strerror());
371                return false;
372             }
373             weof_dev(dev, 1);
374             return true;
375          } else {
376             Jmsg(jcr, M_FATAL, 0, _("Could not write ANSI HDR1 label.\n"));
377             return false;
378          }
379       }
380       if (weof_dev(dev, 1) < 0) {
381          Jmsg(jcr, M_FATAL, 0, _("Error writing EOF to tape. ERR=%s"), dev->errmsg);
382          return false;
383       }
384       return true;
385    default:
386       Jmsg0(jcr, M_ABORT, 0, _("write_ansi_ibm_label called for non-ANSI/IBM type\n"));
387       return false; /* should not get here */
388    }
389 }
390
391 /* Check a Bacula Volume name against an ANSI Volume name */
392 static bool same_label_names(char *bacula_name, char *ansi_name)
393 {
394    char *a = ansi_name;
395    char *b = bacula_name;
396    /* Six characters max */
397    for (int i=0; i < 6; i++) {
398       if (*a == *b) {
399          a++;
400          b++;
401          continue;
402       }
403       /* ANSI labels are blank filled, Bacula's are zero terminated */
404       if (*a == ' ' && *b == 0) {
405          return true;
406       }
407       return false;
408    }
409    /* Reached 6 characters */
410    b++;
411    if (*b == 0) {
412       return true;
413    }
414    return false;
415 }
416
417 /*
418  * ANSI date
419  *  ' 'YYDDD
420  */
421 static char *ansi_date(time_t td, char *buf)
422 {
423    struct tm *tm;
424
425    if (td == 0) {
426       td = time(NULL);
427    }
428    tm = gmtime(&td);
429    bsnprintf(buf, 10, " %05d ", 1000 * (tm->tm_year + 1900 - 2000) + tm->tm_yday);
430    return buf;
431 }