2 Bacula® - The Network Backup Solution
4 Copyright (C) 2005-2007 Free Software Foundation Europe e.V.
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
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.
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
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.
30 * ansi_label.c routines to handle ANSI (and perhaps one day IBM)
40 #include "bacula.h" /* pull in global headers */
41 #include "stored.h" /* pull in Storage Deamon headers */
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);
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);
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
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
66 int read_ansi_ibm_label(DCR *dcr)
68 DEVICE * volatile dev = dcr->dev;
70 char label[80]; /* tape label */
72 char *VolName = dcr->VolumeName;
76 * Read VOL1, HDR1, HDR2 labels, but ignore the data
77 * If tape read the following EOF mark, on disk do
80 Dmsg0(100, "Read ansi label.\n");
81 if (!dev->is_tape()) {
85 dev->label_type = B_BACULA_LABEL; /* assume Bacula label */
87 /* Read a maximum of 5 records VOL1, HDR1, ... HDR4 */
88 for (i=0; i < 6; i++) {
90 stat = dev->read(label, sizeof(label));
91 } while (stat == -1 && errno == EINTR);
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++;
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 */
109 dev->set_ateof(); /* set eof state */
113 case 0: /* Want VOL1 label */
115 if (strncmp("VOL1", label, 4) == 0) {
117 dev->label_type = B_ANSI_LABEL;
118 Dmsg0(100, "Got ANSI VOL1 label\n");
121 ebcdic_to_ascii(label, label, sizeof(label));
122 if (strncmp("VOL1", label, 4) == 0) {
124 dev->label_type = B_IBM_LABEL;
125 Dmsg0(100, "Found IBM label.\n");
126 Dmsg0(100, "Got IBM VOL1 label\n");
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 */
137 /* Compare Volume Names allow special wild card */
138 if (VolName && *VolName && *VolName != '*') {
139 if (!same_label_names(VolName, &label[4])) {
144 /* Store new Volume name */
145 q = dev->VolHdr.VolumeName;
146 for (int i=0; *p != ' ' && i < 6; i++) {
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;
159 if (dev->label_type == B_IBM_LABEL) {
160 ebcdic_to_ascii(label, label, sizeof(label));
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;
167 if (strncmp("BACULA.DATA", &label[4], 11) != 0) {
168 Dmsg1(100, "HD1 not Bacula label. Wanted BACULA.DATA got %11s\n",
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 */
174 Dmsg0(100, "Got HDR1 label\n");
177 if (dev->label_type == B_IBM_LABEL) {
178 ebcdic_to_ascii(label, label, sizeof(label));
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;
185 Dmsg0(100, "Got ANSI HDR2 label\n");
189 Dmsg0(100, "ANSI label OK\n");
192 if (dev->label_type == B_IBM_LABEL) {
193 ebcdic_to_ascii(label, label, sizeof(label));
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;
200 Dmsg0(100, "Got HDR label\n");
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;
210 * ANSI/IBM VOL1 label
211 * 80 characters blank filled
212 * Pos count Function What Bacula puts
214 * 4-9 6 Volume name Volume name
215 * 10-10 1 Access code
230 * ANSI/IBM HDR1 label
231 * 80 characters blank filled
232 * Pos count Function What Bacula puts
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
243 * 54-59 6 Block count 000000
244 * 60-72 13 Software name Bacula
247 * ANSI/IBM HDR2 label
248 * 80 characters blank filled
249 * Pos count Function What Bacula puts
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
260 * 38-38 1 Blocked flag
267 static const char *labels[] = {"HDR", "EOF", "EOV"};
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
276 bool write_ansi_ibm_labels(DCR *dcr, int type, const char *VolName)
278 DEVICE *dev = dcr->dev;
280 char label[80]; /* tape label */
281 char date[20]; /* ansi date buffer */
283 int len, stat, label_type;
286 * If the Device requires a specific label type use it,
287 * otherwise, use the type requested by the Director
289 if (dcr->device->label_type != B_BACULA_LABEL) {
290 label_type = dcr->device->label_type; /* force label type */
292 label_type = dcr->VolCatInfo.LabelType; /* accept Dir type */
295 switch (label_type) {
301 Dmsg1(100, "Write ANSI label type=%d\n", label_type);
302 len = strlen(VolName);
304 Jmsg1(jcr, M_FATAL, 0, _("ANSI Volume label name \"%s\" longer than 6 chars.\n"),
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));
316 label[79] = '3'; /* ANSI label flag */
318 stat = dev->write(label, sizeof(label));
319 if (stat != sizeof(label)) {
321 Jmsg1(jcr, M_FATAL, 0, _("Could not write ANSI VOL1 label. ERR=%s\n"),
327 /* Now construct HDR1 label */
328 memset(label, ' ', sizeof(label));
329 ser_begin(label, sizeof(label));
330 ser_bytes(labels[type], 3);
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 */
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));
347 * This could come at the end of a tape, ignore
350 stat = dev->write(label, sizeof(label));
351 if (stat != sizeof(label)) {
355 if (dev->dev_errno == 0) {
356 dev->dev_errno = ENOSPC; /* out of space */
358 if (dev->dev_errno != ENOSPC) {
359 Jmsg1(jcr, M_FATAL, 0, _("Could not write ANSI HDR1 label. ERR=%s\n"),
364 Jmsg(jcr, M_FATAL, 0, _("Could not write ANSI HDR1 label.\n"));
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) {
377 ascii_to_ebcdic(label, label, sizeof(label));
379 stat = dev->write(label, sizeof(label));
380 if (stat != sizeof(label)) {
384 if (dev->dev_errno == 0) {
385 dev->dev_errno = ENOSPC; /* out of space */
387 if (dev->dev_errno != ENOSPC) {
388 Jmsg1(jcr, M_FATAL, 0, _("Could not write ANSI HDR1 label. ERR=%s\n"),
395 Jmsg(jcr, M_FATAL, 0, _("Could not write ANSI HDR1 label.\n"));
400 Jmsg(jcr, M_FATAL, 0, _("Error writing EOF to tape. ERR=%s"), dev->errmsg);
405 Jmsg0(jcr, M_ABORT, 0, _("write_ansi_ibm_label called for non-ANSI/IBM type\n"));
406 return false; /* should not get here */
410 /* Check a Bacula Volume name against an ANSI Volume name */
411 static bool same_label_names(char *bacula_name, char *ansi_name)
414 char *b = bacula_name;
415 /* Six characters max */
416 for (int i=0; i < 6; i++) {
422 /* ANSI labels are blank filled, Bacula's are zero terminated */
423 if (*a == ' ' && *b == 0) {
428 /* Reached 6 characters */
440 static char *ansi_date(time_t td, char *buf)
448 bsnprintf(buf, 10, " %05d ", 1000 * (tm->tm_year + 1900 - 2000) + tm->tm_yday);