]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/ansi_label.c
Tweak debug + code indenting
[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                reserve_volume(dcr, dev->VolHdr.VolumeName);
151                dev = dcr->dev;            /* may have changed in reserve_volume */
152                Dmsg2(100, "Wanted ANSI Vol %s got %6s\n", VolName, dev->VolHdr.VolumeName);
153                Mmsg2(jcr->errmsg, _("Wanted ANSI Volume \"%s\" got \"%s\"\n"), VolName, dev->VolHdr.VolumeName);
154                return VOL_NAME_ERROR;
155             }
156          }
157          break;
158       case 1:
159          if (dev->label_type == B_IBM_LABEL) {
160             ebcdic_to_ascii(label, label, sizeof(label));
161          }
162          if (stat != 80 || strncmp("HDR1", label, 4) != 0) {
163             Dmsg0(100, "No HDR1 label\n");
164             Mmsg0(jcr->errmsg, _("No HDR1 label while reading ANSI label.\n"));
165             return VOL_LABEL_ERROR;
166          }
167          if (strncmp("BACULA.DATA", &label[4], 11) != 0) {
168             Dmsg1(100, "HD1 not Bacula label. Wanted  BACULA.DATA got %11s\n",
169                &label[4]);
170             Mmsg1(jcr->errmsg, _("ANSI/IBM Volume \"%s\" does not belong to Bacula.\n"),
171                dev->VolHdr.VolumeName);
172             return VOL_NAME_ERROR;     /* Not a Bacula label */
173          }
174          Dmsg0(100, "Got HDR1 label\n");
175          break;
176       case 2:
177          if (dev->label_type == B_IBM_LABEL) {
178             ebcdic_to_ascii(label, label, sizeof(label));
179          }
180          if (stat != 80 || strncmp("HDR2", label, 4) != 0) {
181             Dmsg0(100, "No HDR2 label\n");
182             Mmsg0(jcr->errmsg, _("No HDR2 label while reading ANSI/IBM label.\n"));
183             return VOL_LABEL_ERROR;
184          }
185          Dmsg0(100, "Got ANSI HDR2 label\n");
186          break;
187       default:
188          if (stat == 0) {
189             Dmsg0(100, "ANSI label OK\n");
190             return VOL_OK;
191          }
192          if (dev->label_type == B_IBM_LABEL) {
193             ebcdic_to_ascii(label, label, sizeof(label));
194          }
195          if (stat != 80 || strncmp("HDR", label, 3) != 0) {
196             Dmsg0(100, "Unknown or bad ANSI/IBM label record.\n");
197             Mmsg0(jcr->errmsg, _("Unknown or bad ANSI/IBM label record.\n"));
198             return VOL_LABEL_ERROR;
199          }
200          Dmsg0(100, "Got HDR label\n");
201          break;
202       }
203    }
204    Dmsg0(100, "Too many records in ANSI/IBM label.\n");
205    Mmsg0(jcr->errmsg, _("Too many records in while reading ANSI/IBM label.\n"));
206    return VOL_LABEL_ERROR;
207 }  
208
209 /*
210  * ANSI/IBM VOL1 label
211  *  80 characters blank filled
212  * Pos   count   Function      What Bacula puts
213  * 0-3     4     "VOL1"          VOL1
214  * 4-9     6     Volume name     Volume name
215  * 10-10   1     Access code 
216  * 11-36   26    Unused
217  *
218  * ANSI
219  * 37-50   14    Owner
220  * 51-78   28    reserved
221  * 79       1    ANSI level        3
222  *
223  * IBM
224  * 37-40   4     reserved
225  * 41-50   10    Owner
226  * 51-79   29    reserved
227
228  *
229  *
230  * ANSI/IBM HDR1 label
231  *  80 characters blank filled
232  * Pos   count   Function          What Bacula puts
233  * 0-3     4     "HDR1"               HDR1
234  * 4-20    17    File name           BACULA.DATA
235  * 21-26   6     Volume name          Volume name
236  * 27-30   4     Vol seq num           0001
237  * 31-34   4     file num              0001
238  * 35-38   4     Generation            0001
239  * 39-40   2     Gen version           00
240  * 41-46   6     Create date bYYDDD    yesterday
241  * 47-52   6     Expire date bYYDDD    today
242  * 53-53   1     Access
243  * 54-59   6     Block count           000000
244  * 60-72   13    Software name         Bacula
245  * 73-79   7     Reserved
246
247  * ANSI/IBM HDR2 label
248  *  80 characters blank filled
249  * Pos   count   Function          What Bacula puts
250  * 0-3     4     "HDR2"               HDR2
251  * 4-4     1     Record format        D   (V if IBM) => variable
252  * 5-9     5     Block length         32000
253  * 10-14   5     Rec length           32000
254  * 15-15   1     Density
255  * 16-16   1     Continued 
256  * 17-33   17    Job
257  * 34-35   2     Recording
258  * 36-36   1     cr/lf ctl
259  * 37-37   1     reserved
260  * 38-38   1     Blocked flag
261  * 39-49   11    reserved
262  * 50-51   2     offset
263  * 52-79   28    reserved
264
265  */ 
266
267 static const char *labels[] = {"HDR", "EOF", "EOV"};
268
269 /*
270  * Write an ANSI or IBM 80 character tape label
271  *   Type determines whether we are writing HDR, EOF, or EOV labels
272  *   Assume we are positioned to write the labels
273  *   Returns:  true of OK
274  *             false if error
275  */
276 bool write_ansi_ibm_labels(DCR *dcr, int type, const char *VolName)
277 {
278    DEVICE *dev = dcr->dev;
279    JCR *jcr = dcr->jcr;
280    char label[80];                    /* tape label */
281    char date[20];                     /* ansi date buffer */
282    time_t now;
283    int len, stat, label_type;
284
285    /*
286     * If the Device requires a specific label type use it,
287     * otherwise, use the type requested by the Director
288     */
289    if (dcr->device->label_type != B_BACULA_LABEL) {
290       label_type = dcr->device->label_type;   /* force label type */
291    } else {
292       label_type = dcr->VolCatInfo.LabelType; /* accept Dir type */
293    }
294
295    switch (label_type) {
296    case B_BACULA_LABEL:
297       return true;
298    case B_ANSI_LABEL:
299    case B_IBM_LABEL:
300       ser_declare;
301       Dmsg1(100, "Write ANSI label type=%d\n", label_type);
302       len = strlen(VolName);
303       if (len > 6) {
304          Jmsg1(jcr, M_FATAL, 0, _("ANSI Volume label name \"%s\" longer than 6 chars.\n"),
305             VolName);
306          return false;
307       }
308       if (type == ANSI_VOL_LABEL) {
309          ser_begin(label, sizeof(label));
310          ser_bytes("VOL1", 4);
311          ser_bytes(VolName, len);
312          /* Write VOL1 label */
313          if (label_type == B_IBM_LABEL) {
314             ascii_to_ebcdic(label, label, sizeof(label));
315          } else {
316             label[79] = '3';                /* ANSI label flag */
317          }
318          stat = dev->write(label, sizeof(label));
319          if (stat != sizeof(label)) {
320             berrno be;
321             Jmsg1(jcr, M_FATAL, 0,  _("Could not write ANSI VOL1 label. ERR=%s\n"),
322                be.bstrerror());
323             return false;
324          }
325       }
326
327       /* Now construct HDR1 label */
328       memset(label, ' ', sizeof(label));
329       ser_begin(label, sizeof(label));
330       ser_bytes(labels[type], 3);
331       ser_bytes("1", 1);
332       ser_bytes("BACULA.DATA", 11);            /* Filename field */
333       ser_begin(&label[21], sizeof(label)-21); /* fileset field */
334       ser_bytes(VolName, len);        /* write Vol Ser No. */
335       ser_begin(&label[27], sizeof(label)-27);
336       ser_bytes("00010001000100", 14);  /* File section, File seq no, Generation no */
337       now = time(NULL);
338       ser_bytes(ansi_date(now, date), 6); /* current date */
339       ser_bytes(ansi_date(now - 24 * 3600, date), 6); /* created yesterday */
340       ser_bytes(" 000000Bacula              ", 27);
341       /* Write HDR1 label */
342       if (label_type == B_IBM_LABEL) {
343          ascii_to_ebcdic(label, label, sizeof(label));
344       }
345
346       /*
347        * This could come at the end of a tape, ignore
348        *  EOT errors.
349        */
350       stat = dev->write(label, sizeof(label));
351       if (stat != sizeof(label)) {
352          berrno be;
353          if (stat == -1) {
354             dev->clrerror(-1);
355             if (dev->dev_errno == 0) {
356                dev->dev_errno = ENOSPC; /* out of space */
357             }
358             if (dev->dev_errno != ENOSPC) {
359                Jmsg1(jcr, M_FATAL, 0, _("Could not write ANSI HDR1 label. ERR=%s\n"),
360                be.bstrerror());
361                return false;
362             }
363          } else {
364             Jmsg(jcr, M_FATAL, 0, _("Could not write ANSI HDR1 label.\n"));
365             return false;
366          }
367       }
368
369       /* Now construct HDR2 label */
370       memset(label, ' ', sizeof(label));
371       ser_begin(label, sizeof(label));
372       ser_bytes(labels[type], 3);
373       ser_bytes("2D3200032000", 12);
374       /* Write HDR2 label */
375       if (label_type == B_IBM_LABEL) {
376          label[4] = 'V';
377          ascii_to_ebcdic(label, label, sizeof(label));
378       }
379       stat = dev->write(label, sizeof(label));
380       if (stat != sizeof(label)) {
381          berrno be;
382          if (stat == -1) {
383             dev->clrerror(-1);
384             if (dev->dev_errno == 0) {
385                dev->dev_errno = ENOSPC; /* out of space */
386             }
387             if (dev->dev_errno != ENOSPC) {
388                Jmsg1(jcr, M_FATAL, 0, _("Could not write ANSI HDR1 label. ERR=%s\n"),
389                be.bstrerror());
390                return false;
391             }
392             dev->weof(1);
393             return true;
394          } else {
395             Jmsg(jcr, M_FATAL, 0, _("Could not write ANSI HDR1 label.\n"));
396             return false;
397          }
398       }
399       if (!dev->weof(1)) {
400          Jmsg(jcr, M_FATAL, 0, _("Error writing EOF to tape. ERR=%s"), dev->errmsg);
401          return false;
402       }
403       return true;
404    default:
405       Jmsg0(jcr, M_ABORT, 0, _("write_ansi_ibm_label called for non-ANSI/IBM type\n"));
406       return false; /* should not get here */
407    }
408 }
409
410 /* Check a Bacula Volume name against an ANSI Volume name */
411 static bool same_label_names(char *bacula_name, char *ansi_name)
412 {
413    char *a = ansi_name;
414    char *b = bacula_name;
415    /* Six characters max */
416    for (int i=0; i < 6; i++) {
417       if (*a == *b) {
418          a++;
419          b++;
420          continue;
421       }
422       /* ANSI labels are blank filled, Bacula's are zero terminated */
423       if (*a == ' ' && *b == 0) {
424          return true;
425       }
426       return false;
427    }
428    /* Reached 6 characters */
429    b++;
430    if (*b == 0) {
431       return true;
432    }
433    return false;
434 }
435
436 /*
437  * ANSI date
438  *  ' 'YYDDD
439  */
440 static char *ansi_date(time_t td, char *buf)
441 {
442    struct tm *tm;
443
444    if (td == 0) {
445       td = time(NULL);
446    }
447    tm = gmtime(&td);
448    bsnprintf(buf, 10, " %05d ", 1000 * (tm->tm_year + 1900 - 2000) + tm->tm_yday);
449    return buf;
450 }