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