2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2016 Kern Sibbald
6 The original author of Bacula is Kern Sibbald, with contributions
7 from many others, a complete list can be found in the file AUTHORS.
9 You may use this file and others of this release according to the
10 license defined in the LICENSE file, which includes the Affero General
11 Public License, v3.0 ("AGPLv3") and some additional permissions and
12 terms pursuant to its AGPLv3 Section 7.
14 This notice must be preserved when any source code is
15 conveyed and/or propagated.
17 Bacula(R) is a registered trademark of Kern Sibbald.
21 * ansi_label.c routines to handle ANSI (and perhaps one day IBM)
28 #include "bacula.h" /* pull in global headers */
29 #include "stored.h" /* pull in Storage Deamon headers */
31 /* Imported functions */
32 void ascii_to_ebcdic(char *dst, char *src, int count);
33 void ebcdic_to_ascii(char *dst, char *src, int count);
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);
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
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
54 int read_ansi_ibm_label(DCR *dcr)
56 DEVICE * volatile dev = dcr->dev;
58 char label[80]; /* tape label */
60 char *VolName = dcr->VolumeName;
64 * Read VOL1, HDR1, HDR2 labels, but ignore the data
65 * If tape read the following EOF mark, on disk do
68 Dmsg0(100, "Read ansi label.\n");
69 if (!dev->is_tape()) {
73 dev->label_type = B_BACULA_LABEL; /* assume Bacula label */
75 /* Read a maximum of 5 records VOL1, HDR1, ... HDR4 */
76 for (i=0; i < 6; i++) {
78 stat = dev->read(label, sizeof(label));
79 } while (stat == -1 && errno == EINTR);
83 Dmsg1(100, "Read device got: ERR=%s\n", be.bstrerror());
84 Mmsg2(jcr->errmsg, _("Read error on device %s in ANSI label. ERR=%s\n"),
85 dev->dev_name, be.bstrerror());
86 Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
87 dev->VolCatInfo.VolCatErrors++;
92 dev->set_eot(); /* second eof, set eot bit */
93 Dmsg0(100, "EOM on ANSI label\n");
94 Mmsg0(jcr->errmsg, _("Insane! End of tape while reading ANSI label.\n"));
95 return VOL_LABEL_ERROR; /* at EOM this shouldn't happen */
97 dev->set_ateof(); /* set eof state */
101 case 0: /* Want VOL1 label */
103 if (strncmp("VOL1", label, 4) == 0) {
105 dev->label_type = B_ANSI_LABEL;
106 Dmsg0(100, "Got ANSI VOL1 label\n");
109 ebcdic_to_ascii(label, label, sizeof(label));
110 if (strncmp("VOL1", label, 4) == 0) {
112 dev->label_type = B_IBM_LABEL;
113 Dmsg0(100, "Found IBM label.\n");
114 Dmsg0(100, "Got IBM VOL1 label\n");
119 Dmsg0(100, "No VOL1 label\n");
120 Mmsg0(jcr->errmsg, _("No VOL1 label while reading ANSI/IBM label.\n"));
121 return VOL_NO_LABEL; /* No ANSI label */
125 /* Compare Volume Names allow special wild card */
126 if (VolName && *VolName && *VolName != '*') {
127 if (!same_label_names(VolName, &label[4])) {
132 /* Store new Volume name */
133 q = dev->VolHdr.VolumeName;
134 for (int i=0; *p != ' ' && i < 6; i++) {
138 Dmsg0(100, "Call reserve_volume\n");
139 /* ***FIXME*** why is this reserve_volume() needed???? KES */
140 reserve_volume(dcr, dev->VolHdr.VolumeName);
141 dev = dcr->dev; /* may have changed in reserve_volume */
142 Dmsg2(100, "Wanted ANSI Vol %s got %6s\n", VolName, dev->VolHdr.VolumeName);
143 Mmsg2(jcr->errmsg, _("Wanted ANSI Volume \"%s\" got \"%s\"\n"), VolName, dev->VolHdr.VolumeName);
144 return VOL_NAME_ERROR;
149 if (dev->label_type == B_IBM_LABEL) {
150 ebcdic_to_ascii(label, label, sizeof(label));
152 if (stat != 80 || strncmp("HDR1", label, 4) != 0) {
153 Dmsg0(100, "No HDR1 label\n");
154 Mmsg0(jcr->errmsg, _("No HDR1 label while reading ANSI label.\n"));
155 return VOL_LABEL_ERROR;
157 if (strncmp("BACULA.DATA", &label[4], 11) != 0) {
158 Dmsg1(100, "HD1 not Bacula label. Wanted BACULA.DATA got %11s\n",
160 Mmsg1(jcr->errmsg, _("ANSI/IBM Volume \"%s\" does not belong to Bacula.\n"),
161 dev->VolHdr.VolumeName);
162 return VOL_NAME_ERROR; /* Not a Bacula label */
164 Dmsg0(100, "Got HDR1 label\n");
167 if (dev->label_type == B_IBM_LABEL) {
168 ebcdic_to_ascii(label, label, sizeof(label));
170 if (stat != 80 || strncmp("HDR2", label, 4) != 0) {
171 Dmsg0(100, "No HDR2 label\n");
172 Mmsg0(jcr->errmsg, _("No HDR2 label while reading ANSI/IBM label.\n"));
173 return VOL_LABEL_ERROR;
175 Dmsg0(100, "Got ANSI HDR2 label\n");
179 Dmsg0(100, "ANSI label OK\n");
182 if (dev->label_type == B_IBM_LABEL) {
183 ebcdic_to_ascii(label, label, sizeof(label));
185 if (stat != 80 || strncmp("HDR", label, 3) != 0) {
186 Dmsg0(100, "Unknown or bad ANSI/IBM label record.\n");
187 Mmsg0(jcr->errmsg, _("Unknown or bad ANSI/IBM label record.\n"));
188 return VOL_LABEL_ERROR;
190 Dmsg0(100, "Got HDR label\n");
194 Dmsg0(100, "Too many records in ANSI/IBM label.\n");
195 Mmsg0(jcr->errmsg, _("Too many records in while reading ANSI/IBM label.\n"));
196 return VOL_LABEL_ERROR;
200 * ANSI/IBM VOL1 label
201 * 80 characters blank filled
202 * Pos count Function What Bacula puts
204 * 4-9 6 Volume name Volume name
205 * 10-10 1 Access code
220 * ANSI/IBM HDR1 label
221 * 80 characters blank filled
222 * Pos count Function What Bacula puts
224 * 4-20 17 File name BACULA.DATA
225 * 21-26 6 Volume name Volume name
226 * 27-30 4 Vol seq num 0001
227 * 31-34 4 file num 0001
228 * 35-38 4 Generation 0001
229 * 39-40 2 Gen version 00
230 * 41-46 6 Create date bYYDDD yesterday
231 * 47-52 6 Expire date bYYDDD today
233 * 54-59 6 Block count 000000
234 * 60-72 13 Software name Bacula
237 * ANSI/IBM HDR2 label
238 * 80 characters blank filled
239 * Pos count Function What Bacula puts
241 * 4-4 1 Record format D (V if IBM) => variable
242 * 5-9 5 Block length 32000
243 * 10-14 5 Rec length 32000
250 * 38-38 1 Blocked flag
257 static const char *labels[] = {"HDR", "EOF", "EOV"};
260 * Write an ANSI or IBM 80 character tape label
261 * Type determines whether we are writing HDR, EOF, or EOV labels
262 * Assume we are positioned to write the labels
263 * Returns: true of OK
266 bool write_ansi_ibm_labels(DCR *dcr, int type, const char *VolName)
268 DEVICE *dev = dcr->dev;
270 char ansi_volname[7]; /* 6 char + \0 */
271 char label[80]; /* tape label */
272 char date[20]; /* ansi date buffer */
274 int len, stat, label_type;
277 * If the Device requires a specific label type use it,
278 * otherwise, use the type requested by the Director
280 if (dcr->device->label_type != B_BACULA_LABEL) {
281 label_type = dcr->device->label_type; /* force label type */
283 label_type = dcr->VolCatInfo.LabelType; /* accept Dir type */
286 switch (label_type) {
292 Dmsg1(100, "Write ANSI label type=%d\n", label_type);
293 len = strlen(VolName);
295 Jmsg1(jcr, M_FATAL, 0, _("ANSI Volume label name \"%s\" longer than 6 chars.\n"),
299 /* ANSI labels have 6 characters, and are padded with spaces
300 * 'vol1\0' => 'vol1 \0'
302 strcpy(ansi_volname, VolName);
303 for(int i=len; i < 6; i++) {
306 ansi_volname[6]='\0'; /* only for debug */
308 if (type == ANSI_VOL_LABEL) {
309 ser_begin(label, sizeof(label));
310 ser_bytes("VOL1", 4);
311 ser_bytes(ansi_volname, 6);
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 Jmsg3(jcr, M_FATAL, 0, _("Could not write ANSI VOL1 label. Wanted size=%d got=%d ERR=%s\n"),
322 sizeof(label), stat, be.bstrerror());
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(ansi_volname, 6); /* 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);