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 *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 Dmsg2(100, "Wanted ANSI Vol %s got %6s\n", VolName, dev->VolHdr.VolumeName);
152 Mmsg2(jcr->errmsg, _("Wanted ANSI Volume \"%s\" got \"%s\"\n"), VolName, dev->VolHdr.VolumeName);
153 return VOL_NAME_ERROR;
158 if (dev->label_type == B_IBM_LABEL) {
159 ebcdic_to_ascii(label, label, sizeof(label));
161 if (stat != 80 || strncmp("HDR1", label, 4) != 0) {
162 Dmsg0(100, "No HDR1 label\n");
163 Mmsg0(jcr->errmsg, _("No HDR1 label while reading ANSI label.\n"));
164 return VOL_LABEL_ERROR;
166 if (strncmp("BACULA.DATA", &label[4], 11) != 0) {
167 Dmsg1(100, "HD1 not Bacula label. Wanted BACULA.DATA got %11s\n",
169 Mmsg1(jcr->errmsg, _("ANSI/IBM Volume \"%s\" does not belong to Bacula.\n"),
170 dev->VolHdr.VolumeName);
171 return VOL_NAME_ERROR; /* Not a Bacula label */
173 Dmsg0(100, "Got HDR1 label\n");
176 if (dev->label_type == B_IBM_LABEL) {
177 ebcdic_to_ascii(label, label, sizeof(label));
179 if (stat != 80 || strncmp("HDR2", label, 4) != 0) {
180 Dmsg0(100, "No HDR2 label\n");
181 Mmsg0(jcr->errmsg, _("No HDR2 label while reading ANSI/IBM label.\n"));
182 return VOL_LABEL_ERROR;
184 Dmsg0(100, "Got ANSI HDR2 label\n");
188 Dmsg0(100, "ANSI label OK\n");
191 if (dev->label_type == B_IBM_LABEL) {
192 ebcdic_to_ascii(label, label, sizeof(label));
194 if (stat != 80 || strncmp("HDR", label, 3) != 0) {
195 Dmsg0(100, "Unknown or bad ANSI/IBM label record.\n");
196 Mmsg0(jcr->errmsg, _("Unknown or bad ANSI/IBM label record.\n"));
197 return VOL_LABEL_ERROR;
199 Dmsg0(100, "Got HDR label\n");
203 Dmsg0(100, "Too many records in ANSI/IBM label.\n");
204 Mmsg0(jcr->errmsg, _("Too many records in while reading ANSI/IBM label.\n"));
205 return VOL_LABEL_ERROR;
209 * ANSI/IBM VOL1 label
210 * 80 characters blank filled
211 * Pos count Function What Bacula puts
213 * 4-9 6 Volume name Volume name
214 * 10-10 1 Access code
229 * ANSI/IBM HDR1 label
230 * 80 characters blank filled
231 * Pos count Function What Bacula puts
233 * 4-20 17 File name BACULA.DATA
234 * 21-26 6 Volume name Volume name
235 * 27-30 4 Vol seq num 0001
236 * 31-34 4 file num 0001
237 * 35-38 4 Generation 0001
238 * 39-40 2 Gen version 00
239 * 41-46 6 Create date bYYDDD yesterday
240 * 47-52 6 Expire date bYYDDD today
242 * 54-59 6 Block count 000000
243 * 60-72 13 Software name Bacula
246 * ANSI/IBM HDR2 label
247 * 80 characters blank filled
248 * Pos count Function What Bacula puts
250 * 4-4 1 Record format D (V if IBM) => variable
251 * 5-9 5 Block length 32000
252 * 10-14 5 Rec length 32000
259 * 38-38 1 Blocked flag
266 static const char *labels[] = {"HDR", "EOF", "EOV"};
269 * Write an ANSI or IBM 80 character tape label
270 * Type determines whether we are writing HDR, EOF, or EOV labels
271 * Assume we are positioned to write the labels
272 * Returns: true of OK
275 bool write_ansi_ibm_labels(DCR *dcr, int type, const char *VolName)
277 DEVICE *dev = dcr->dev;
279 char label[80]; /* tape label */
280 char date[20]; /* ansi date buffer */
282 int len, stat, label_type;
285 * If the Device requires a specific label type use it,
286 * otherwise, use the type requested by the Director
288 if (dcr->device->label_type != B_BACULA_LABEL) {
289 label_type = dcr->device->label_type; /* force label type */
291 label_type = dcr->VolCatInfo.LabelType; /* accept Dir type */
294 switch (label_type) {
300 Dmsg1(100, "Write ANSI label type=%d\n", label_type);
301 len = strlen(VolName);
303 Jmsg1(jcr, M_FATAL, 0, _("ANSI Volume label name \"%s\" longer than 6 chars.\n"),
307 if (type == ANSI_VOL_LABEL) {
308 ser_begin(label, sizeof(label));
309 ser_bytes("VOL1", 4);
310 ser_bytes(VolName, len);
311 /* Write VOL1 label */
312 if (label_type == B_IBM_LABEL) {
313 ascii_to_ebcdic(label, label, sizeof(label));
315 label[79] = '3'; /* ANSI label flag */
317 stat = dev->write(label, sizeof(label));
318 if (stat != sizeof(label)) {
320 Jmsg1(jcr, M_FATAL, 0, _("Could not write ANSI VOL1 label. ERR=%s\n"),
326 /* Now construct HDR1 label */
327 memset(label, ' ', sizeof(label));
328 ser_begin(label, sizeof(label));
329 ser_bytes(labels[type], 3);
331 ser_bytes("BACULA.DATA", 11); /* Filename field */
332 ser_begin(&label[21], sizeof(label)-21); /* fileset field */
333 ser_bytes(VolName, len); /* write Vol Ser No. */
334 ser_begin(&label[27], sizeof(label)-27);
335 ser_bytes("00010001000100", 14); /* File section, File seq no, Generation no */
337 ser_bytes(ansi_date(now, date), 6); /* current date */
338 ser_bytes(ansi_date(now - 24 * 3600, date), 6); /* created yesterday */
339 ser_bytes(" 000000Bacula ", 27);
340 /* Write HDR1 label */
341 if (label_type == B_IBM_LABEL) {
342 ascii_to_ebcdic(label, label, sizeof(label));
346 * This could come at the end of a tape, ignore
349 stat = dev->write(label, sizeof(label));
350 if (stat != sizeof(label)) {
354 if (dev->dev_errno == 0) {
355 dev->dev_errno = ENOSPC; /* out of space */
357 if (dev->dev_errno != ENOSPC) {
358 Jmsg1(jcr, M_FATAL, 0, _("Could not write ANSI HDR1 label. ERR=%s\n"),
363 Jmsg(jcr, M_FATAL, 0, _("Could not write ANSI HDR1 label.\n"));
368 /* Now construct HDR2 label */
369 memset(label, ' ', sizeof(label));
370 ser_begin(label, sizeof(label));
371 ser_bytes(labels[type], 3);
372 ser_bytes("2D3200032000", 12);
373 /* Write HDR2 label */
374 if (label_type == B_IBM_LABEL) {
376 ascii_to_ebcdic(label, label, sizeof(label));
378 stat = dev->write(label, sizeof(label));
379 if (stat != sizeof(label)) {
383 if (dev->dev_errno == 0) {
384 dev->dev_errno = ENOSPC; /* out of space */
386 if (dev->dev_errno != ENOSPC) {
387 Jmsg1(jcr, M_FATAL, 0, _("Could not write ANSI HDR1 label. ERR=%s\n"),
394 Jmsg(jcr, M_FATAL, 0, _("Could not write ANSI HDR1 label.\n"));
399 Jmsg(jcr, M_FATAL, 0, _("Error writing EOF to tape. ERR=%s"), dev->errmsg);
404 Jmsg0(jcr, M_ABORT, 0, _("write_ansi_ibm_label called for non-ANSI/IBM type\n"));
405 return false; /* should not get here */
409 /* Check a Bacula Volume name against an ANSI Volume name */
410 static bool same_label_names(char *bacula_name, char *ansi_name)
413 char *b = bacula_name;
414 /* Six characters max */
415 for (int i=0; i < 6; i++) {
421 /* ANSI labels are blank filled, Bacula's are zero terminated */
422 if (*a == ' ' && *b == 0) {
427 /* Reached 6 characters */
439 static char *ansi_date(time_t td, char *buf)
447 bsnprintf(buf, 10, " %05d ", 1000 * (tm->tm_year + 1900 - 2000) + tm->tm_yday);