]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/ansi_label.c
Apply Joao's patch to SQLite tables to make chars work.
[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 Kern Sibbald.
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 ansi_volname[7];              /* 6 char + \0 */
282    char label[80];                    /* tape label */
283    char date[20];                     /* ansi date buffer */
284    time_t now;
285    int len, stat, label_type;
286
287    /*
288     * If the Device requires a specific label type use it,
289     * otherwise, use the type requested by the Director
290     */
291    if (dcr->device->label_type != B_BACULA_LABEL) {
292       label_type = dcr->device->label_type;   /* force label type */
293    } else {
294       label_type = dcr->VolCatInfo.LabelType; /* accept Dir type */
295    }
296
297    switch (label_type) {
298    case B_BACULA_LABEL:
299       return true;
300    case B_ANSI_LABEL:
301    case B_IBM_LABEL:
302       ser_declare;
303       Dmsg1(100, "Write ANSI label type=%d\n", label_type);
304       len = strlen(VolName);
305       if (len > 6) {
306          Jmsg1(jcr, M_FATAL, 0, _("ANSI Volume label name \"%s\" longer than 6 chars.\n"),
307             VolName);
308          return false;
309       }
310       /* ANSI labels have 6 characters, and are padded with spaces
311        * 'vol1\0' => 'vol1   \0'
312        */
313       strcpy(ansi_volname, VolName);
314       for(int i=len; i < 6; i++) {
315          ansi_volname[i]=' ';
316       }
317       ansi_volname[6]='\0';     /* only for debug */
318
319       if (type == ANSI_VOL_LABEL) {
320          ser_begin(label, sizeof(label));
321          ser_bytes("VOL1", 4);
322          ser_bytes(ansi_volname, 6);
323          /* Write VOL1 label */
324          if (label_type == B_IBM_LABEL) {
325             ascii_to_ebcdic(label, label, sizeof(label));
326          } else {
327             label[79] = '3';                /* ANSI label flag */
328          }
329          stat = dev->write(label, sizeof(label));
330          if (stat != sizeof(label)) {
331             berrno be;
332             Jmsg1(jcr, M_FATAL, 0,  _("Could not write ANSI VOL1 label. ERR=%s\n"),
333                be.bstrerror());
334             return false;
335          }
336       }
337
338       /* Now construct HDR1 label */
339       memset(label, ' ', sizeof(label));
340       ser_begin(label, sizeof(label));
341       ser_bytes(labels[type], 3);
342       ser_bytes("1", 1);
343       ser_bytes("BACULA.DATA", 11);            /* Filename field */
344       ser_begin(&label[21], sizeof(label)-21); /* fileset field */
345       ser_bytes(ansi_volname, 6);              /* write Vol Ser No. */
346       ser_begin(&label[27], sizeof(label)-27);
347       ser_bytes("00010001000100", 14);  /* File section, File seq no, Generation no */
348       now = time(NULL);
349       ser_bytes(ansi_date(now, date), 6); /* current date */
350       ser_bytes(ansi_date(now - 24 * 3600, date), 6); /* created yesterday */
351       ser_bytes(" 000000Bacula              ", 27);
352       /* Write HDR1 label */
353       if (label_type == B_IBM_LABEL) {
354          ascii_to_ebcdic(label, label, sizeof(label));
355       }
356
357       /*
358        * This could come at the end of a tape, ignore
359        *  EOT errors.
360        */
361       stat = dev->write(label, sizeof(label));
362       if (stat != sizeof(label)) {
363          berrno be;
364          if (stat == -1) {
365             dev->clrerror(-1);
366             if (dev->dev_errno == 0) {
367                dev->dev_errno = ENOSPC; /* out of space */
368             }
369             if (dev->dev_errno != ENOSPC) {
370                Jmsg1(jcr, M_FATAL, 0, _("Could not write ANSI HDR1 label. ERR=%s\n"),
371                be.bstrerror());
372                return false;
373             }
374          } else {
375             Jmsg(jcr, M_FATAL, 0, _("Could not write ANSI HDR1 label.\n"));
376             return false;
377          }
378       }
379
380       /* Now construct HDR2 label */
381       memset(label, ' ', sizeof(label));
382       ser_begin(label, sizeof(label));
383       ser_bytes(labels[type], 3);
384       ser_bytes("2D3200032000", 12);
385       /* Write HDR2 label */
386       if (label_type == B_IBM_LABEL) {
387          label[4] = 'V';
388          ascii_to_ebcdic(label, label, sizeof(label));
389       }
390       stat = dev->write(label, sizeof(label));
391       if (stat != sizeof(label)) {
392          berrno be;
393          if (stat == -1) {
394             dev->clrerror(-1);
395             if (dev->dev_errno == 0) {
396                dev->dev_errno = ENOSPC; /* out of space */
397             }
398             if (dev->dev_errno != ENOSPC) {
399                Jmsg1(jcr, M_FATAL, 0, _("Could not write ANSI HDR1 label. ERR=%s\n"),
400                be.bstrerror());
401                return false;
402             }
403             dev->weof(1);
404             return true;
405          } else {
406             Jmsg(jcr, M_FATAL, 0, _("Could not write ANSI HDR1 label.\n"));
407             return false;
408          }
409       }
410       if (!dev->weof(1)) {
411          Jmsg(jcr, M_FATAL, 0, _("Error writing EOF to tape. ERR=%s"), dev->errmsg);
412          return false;
413       }
414       return true;
415    default:
416       Jmsg0(jcr, M_ABORT, 0, _("write_ansi_ibm_label called for non-ANSI/IBM type\n"));
417       return false; /* should not get here */
418    }
419 }
420
421 /* Check a Bacula Volume name against an ANSI Volume name */
422 static bool same_label_names(char *bacula_name, char *ansi_name)
423 {
424    char *a = ansi_name;
425    char *b = bacula_name;
426    /* Six characters max */
427    for (int i=0; i < 6; i++) {
428       if (*a == *b) {
429          a++;
430          b++;
431          continue;
432       }
433       /* ANSI labels are blank filled, Bacula's are zero terminated */
434       if (*a == ' ' && *b == 0) {
435          return true;
436       }
437       return false;
438    }
439    /* Reached 6 characters */
440    b++;
441    if (*b == 0) {
442       return true;
443    }
444    return false;
445 }
446
447 /*
448  * ANSI date
449  *  ' 'YYDDD
450  */
451 static char *ansi_date(time_t td, char *buf)
452 {
453    struct tm *tm;
454
455    if (td == 0) {
456       td = time(NULL);
457    }
458    tm = gmtime(&td);
459    bsnprintf(buf, 10, " %05d ", 1000 * (tm->tm_year + 1900 - 2000) + tm->tm_yday);
460    return buf;
461 }