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