]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/ansi_label.c
85fb30538daa35531a174ac0364fea829a5a78dd
[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 /* Forward referenced functions */
36 static char *ansi_date(time_t td, char *buf);
37 static bool same_label_names(char *bacula_name, char *ansi_name);
38
39 /*
40  * We read an ANSI label and compare the Volume name. We require
41  * a VOL1 record of 80 characters followed by a HDR1 record containing
42  * BACULA.DATA in the filename field. We then read up to 3 more 
43  * header records (they are not required) and an EOF, at which
44  * point, all is good.
45  *
46  * Returns:
47  *    VOL_OK            Volume name OK
48  *    VOL_NO_LABEL      No ANSI label on Volume
49  *    VOL_IO_ERROR      I/O error on read
50  *    VOL_NAME_ERROR    Wrong name in VOL1 record
51  *    VOL_LABEL_ERROR   Probably an ANSI label, but something wrong
52  *      
53  */ 
54 int read_ansi_ibm_label(DCR *dcr) 
55 {
56    DEVICE *dev = dcr->dev;
57    JCR *jcr = dcr->jcr;
58    char label[80];                    /* tape label */
59    int stat, i;
60    char *VolName = dcr->VolumeName;
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(000, "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(000, "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->state |= ST_EOT;
92             Dmsg0(000, "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_eof();
97          }
98       }
99       switch (i) {
100       case 0:                         /* Want VOL1 label */
101          if (stat != 80 || strncmp("VOL1", label, 4) != 0) {
102             Dmsg0(000, "No VOL1 label\n");
103             Mmsg0(jcr->errmsg, _("No VOL1 label while reading ANSI label.\n"));
104             return VOL_NO_LABEL;   /* No ANSI label */
105          }
106
107          dev->label_type = B_ANSI_LABEL;
108
109          /* Compare Volume Names allow special wild card */
110          if (VolName && *VolName && *VolName != '*') { 
111             if (!same_label_names(VolName, &label[4])) {
112                char *p = &label[4];
113                char *q = dev->VolHdr.VolName;
114                for (int i=0; *p != ' ' && i < 6; i++) {
115                   *q++ = *p++;
116                }
117                *q = 0;
118                Dmsg2(000, "Wanted ANSI Vol %s got %6s\n", VolName, dev->VolHdr.VolName);
119                Mmsg2(jcr->errmsg, "Wanted ANSI Volume \"%s\" got \"%s\"\n", VolName, dev->VolHdr.VolName);
120                return VOL_NAME_ERROR;
121             }
122          }
123          break;
124       case 1:
125          if (stat != 80 || strncmp("HDR1", label, 4) != 0) {
126             Dmsg0(000, "No HDR1 label\n");
127             Mmsg0(jcr->errmsg, _("No HDR1 label while reading ANSI label.\n"));
128             return VOL_LABEL_ERROR;
129          }
130          if (strncmp("BACULA.DATA", &label[4], 11) != 0) {
131             Dmsg1(000, "HD1 not Bacula label. Wanted  BACULA.DATA got %11s\n",
132                &label[4]);
133             Mmsg1(jcr->errmsg, _("ANSI Volume \"%s\" does not belong to Bacula.\n"),
134                dev->VolHdr.VolName);
135             return VOL_NAME_ERROR;     /* Not a Bacula label */
136          }
137          break;
138       case 2:
139          if (stat != 80 || strncmp("HDR2", label, 4) != 0) {
140             Dmsg0(000, "No HDR2 label\n");
141             Mmsg0(jcr->errmsg, _("No HDR2 label while reading ANSI label.\n"));
142             return VOL_LABEL_ERROR;
143          }
144          break;
145       default:
146          if (stat == 0) {
147             Dmsg0(000, "ANSI label OK\n");
148             return VOL_OK;
149          }
150          if (stat != 80 || strncmp("HDR", label, 3) != 0) {
151             Dmsg0(000, "Unknown or bad ANSI label record.\n");
152             Mmsg0(jcr->errmsg, _("Unknown or bad ANSI label record.\n"));
153             return VOL_LABEL_ERROR;
154          }
155          break;
156       }
157    }
158    Dmsg0(000, "Too many records in ANSI label.\n");
159    Mmsg0(jcr->errmsg, _("Too many records in while reading ANSI label.\n"));
160    return VOL_LABEL_ERROR;
161 }  
162
163 /*
164  * Write an ANSI or IBM 80 character tape label
165  *   Assume we are positioned at the beginning of the tape.
166  *   Returns:  true of OK
167  *             false if error
168  */
169 bool write_ansi_ibm_label(DCR *dcr, const char *VolName)
170 {
171    DEVICE *dev = dcr->dev;
172    JCR *jcr = dcr->jcr;
173    char label[80];                    /* tape label */
174    char date[20];                     /* ansi date buffer */
175    time_t now;
176    int len, stat, label_type;
177
178    /*
179     * If the Device requires a specific label type use it,
180     * otherwise, use the type requested by the Director
181     */
182    if (dcr->device->label_type != B_BACULA_LABEL) {
183       label_type = dcr->device->label_type;   /* force label type */
184    } else {
185       label_type = dcr->VolCatInfo.LabelType; /* accept Dir type */
186    }
187
188    switch (label_type) {
189    case B_BACULA_LABEL:
190       return true;
191    case B_ANSI_LABEL:
192    case B_IBM_LABEL:
193       ser_declare;
194       Dmsg1(000, "Write ANSI label type=%d\n", label_type);
195       len = strlen(VolName);
196       if (len > 6) {
197          Jmsg1(jcr, M_FATAL, 0, _("ANSI Volume label name \"%s\" longer than 6 chars.\n"),
198             VolName);
199          return false;
200       }
201       memset(label, ' ', sizeof(label));
202       ser_begin(label, sizeof(label));
203       ser_bytes("VOL1", 4);
204       ser_bytes(VolName, len);
205       label[79] = '3';                /* ANSI label flag */
206       /* Write VOL1 label */
207       stat = write(dev->fd, label, sizeof(label));
208       if (stat != sizeof(label)) {
209          berrno be;
210          Jmsg1(jcr, M_FATAL, 0,  _("Could not write ANSI VOL1 label. ERR=%s\n"),
211             be.strerror());
212          return false;
213       }
214       /* Now construct HDR1 label */
215       ser_begin(label, sizeof(label));
216       ser_bytes("HDR1", 4);
217       ser_bytes("BACULA.DATA", 11);            /* Filename field */
218       ser_begin(&label[21], sizeof(label)-21); /* fileset field */
219       ser_bytes(VolName, len);        /* write Vol Ser No. */
220       ser_begin(&label[27], sizeof(label)-27);
221       ser_bytes("00010001000100", 14);  /* File section, File seq no, Generation no */
222       now = time(NULL);
223       ser_bytes(ansi_date(now, date), 6); /* current date */
224       ser_bytes(ansi_date(now - 24 * 3600, date), 6); /* created yesterday */
225       ser_bytes(" 000000Bacula              ", 27);
226       /* Write HDR1 label */
227       stat = write(dev->fd, label, sizeof(label));
228       if (stat != sizeof(label)) {
229          berrno be;
230          Jmsg1(jcr, M_FATAL, 0, _("Could not write ANSI HDR1 label. ERR=%s\n"),
231             be.strerror());
232          return false;
233       }
234       /* Now construct HDR2 label */
235       memset(label, ' ', sizeof(label));
236       ser_begin(label, sizeof(label));
237       ser_bytes("HDR2F3200032000", 15);
238       /* Write HDR1 label */
239       stat = write(dev->fd, label, sizeof(label));
240       if (stat != sizeof(label)) {
241          berrno be;
242          Jmsg1(jcr, M_FATAL, 0, _("Could not write ANSI HDR1 label. ERR=%s\n"),
243             be.strerror());
244          return false;
245       }
246       if (weof_dev(dev, 1) < 0) {
247          Jmsg(jcr, M_FATAL, 0, _("Error writing EOF to tape. ERR=%s"), dev->errmsg);
248          return false;
249       }
250       return true;
251    default:
252       Jmsg0(jcr, M_ABORT, 0, _("write_ansi_ibm_label called for non-ANSI/IBM type\n"));
253       return false; /* should not get here */
254    }
255 }
256
257 /* Check a Bacula Volume name against an ANSI Volume name */
258 static bool same_label_names(char *bacula_name, char *ansi_name)
259 {
260    char *a = ansi_name;
261    char *b = bacula_name;
262    /* Six characters max */
263    for (int i=0; i < 6; i++) {
264       if (*a == *b) {
265          a++;
266          b++;
267          continue;
268       }
269       /* ANSI labels are blank filled, Bacula's are zero terminated */
270       if (*a == ' ' && *b == 0) {
271          return true;
272       }
273       return false;
274    }
275    /* Reached 6 characters */
276    b++;
277    if (*b == 0) {
278       return true;
279    }
280    return false;
281 }
282
283
284 static char *ansi_date(time_t td, char *buf)
285 {
286    struct tm *tm;
287
288    if (td == 0) {
289       td = time(NULL);
290    }
291    tm = gmtime(&td);
292    bsnprintf(buf, 10, " %05d ", 1000 * (tm->tm_year + 1900 - 2000) + tm->tm_yday);
293    return buf;
294 }