1 /*
2 Bacula(R) - The Network Backup Solution
3
4 Copyright (C) 2000-2020 Kern Sibbald
5
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.
8
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.
13
14 This notice must be preserved when any source code is
15 conveyed and/or propagated.
16
17 Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19 /*
20 *
21 * label.c Bacula routines to handle labels
22 *
23 * Kern Sibbald, MM
24 *
25 */
26
27 #include "bacula.h" /* pull in global headers */
28 #include "stored.h" /* pull in Storage Deamon headers */
29
30 static const int dbglvl = 100;
31
32 /* Forward referenced functions */
33 static void create_volume_label_record(DCR *dcr, DEVICE *dev, DEV_RECORD *rec, bool adata);
34
35 /*
36 * Read the volume label
37 *
38 * If dcr->VolumeName == NULL, we accept any Bacula Volume
39 * If dcr->VolumeName[0] == 0, we accept any Bacula Volume
40 * otherwise dcr->VolumeName must match the Volume.
41 *
42 * If VolName given, ensure that it matches
43 *
44 * Returns VOL_ code as defined in record.h
45 * VOL_NOT_READ
46 * VOL_OK good label found
47 * VOL_NO_LABEL volume not labeled
48 * VOL_IO_ERROR I/O error reading tape
49 * VOL_NAME_ERROR label has wrong name
50 * VOL_CREATE_ERROR Error creating label
51 * VOL_VERSION_ERROR label has wrong version
52 * VOL_LABEL_ERROR bad label type
53 * VOL_NO_MEDIA no media in drive
54 * VOL_TYPE_ERROR aligned/non-aligned/dedup error
55 *
56 * The dcr block is emptied on return, and the Volume is
57 * rewound.
58 *
59 * Handle both the ameta and adata volumes.
60 */
read_dev_volume_label(DCR * dcr)61 int DEVICE::read_dev_volume_label(DCR *dcr)
62 {
63 JCR *jcr = dcr->jcr;
64 char *VolName = dcr->VolumeName;
65 DEV_RECORD *record;
66 bool ok = false;
67 int stat;
68 bool want_ansi_label;
69 bool have_ansi_label = false;
70
71 Enter(dbglvl);
72 Dmsg5(dbglvl, "Enter read_volume_label adata=%d res=%d device=%s vol=%s dev_Vol=%s\n",
73 dcr->block->adata, num_reserved(), print_name(), VolName,
74 VolHdr.VolumeName[0]?VolHdr.VolumeName:"*NULL*");
75
76
77 if (!is_open()) {
78 if (!open_device(dcr, OPEN_READ_ONLY)) {
79 Leave(dbglvl);
80 return VOL_IO_ERROR;
81 }
82 }
83
84 clear_labeled();
85 clear_append();
86 clear_read();
87 label_type = B_BACULA_LABEL;
88 set_worm(get_tape_worm(dcr));
89 Dmsg1(dbglvl, "==== worm=%d ====\n", is_worm());
90
91 if (!rewind(dcr)) {
92 Mmsg(jcr->errmsg, _("Couldn't rewind %s device %s: ERR=%s\n"),
93 print_type(), print_name(), print_errmsg());
94 Dmsg1(dbglvl, "return VOL_NO_MEDIA: %s", jcr->errmsg);
95 Leave(dbglvl);
96 return VOL_NO_MEDIA;
97 }
98 bstrncpy(VolHdr.Id, "**error**", sizeof(VolHdr.Id));
99
100 /* Read ANSI/IBM label if so requested */
101 want_ansi_label = dcr->VolCatInfo.LabelType != B_BACULA_LABEL ||
102 dcr->device->label_type != B_BACULA_LABEL;
103 if (want_ansi_label || has_cap(CAP_CHECKLABELS)) {
104 stat = read_ansi_ibm_label(dcr);
105 /* If we want a label and didn't find it, return error */
106 if (want_ansi_label && stat != VOL_OK) {
107 goto bail_out;
108 }
109 if (stat == VOL_NAME_ERROR || stat == VOL_LABEL_ERROR) {
110 Mmsg(jcr->errmsg, _("Wrong Volume mounted on %s device %s: Wanted %s have %s\n"),
111 print_type(), print_name(), VolName, VolHdr.VolumeName);
112 if (!poll && jcr->label_errors++ > 100) {
113 Jmsg(jcr, M_FATAL, 0, _("Too many tries: %s"), jcr->errmsg);
114 }
115 goto bail_out;
116 }
117 if (stat != VOL_OK) { /* Not an ANSI/IBM label, so re-read */
118 rewind(dcr);
119 } else {
120 have_ansi_label = true;
121 }
122 }
123
124 /* Read the Bacula Volume label block */
125 record = new_record();
126 empty_block(dcr->block);
127
128 Dmsg0(130, "Big if statement in read_volume_label\n");
129 dcr->reading_label = true;
130 if (!dcr->read_block_from_dev(NO_BLOCK_NUMBER_CHECK)) {
131 Mmsg(jcr->errmsg, _("Read label block failed: requested Volume \"%s\" on %s device %s is not a Bacula "
132 "labeled Volume, because: ERR=%s"), NPRT(VolName),
133 print_type(), print_name(), print_errmsg());
134 Dmsg1(dbglvl, "%s", jcr->errmsg);
135 } else if (!read_record_from_block(dcr, record)) {
136 Mmsg(jcr->errmsg, _("Could not read Volume label from block.\n"));
137 Dmsg1(dbglvl, "%s", jcr->errmsg);
138 } else if (!unser_volume_label(this, record)) {
139 Mmsg(jcr->errmsg, _("Could not unserialize Volume label: ERR=%s\n"),
140 print_errmsg());
141 Dmsg1(dbglvl, "%s", jcr->errmsg);
142 } else if (strcmp(VolHdr.Id, BaculaId) != 0 &&
143 strcmp(VolHdr.Id, OldBaculaId) != 0 &&
144 strcmp(VolHdr.Id, BaculaMetaDataId) != 0 &&
145 strcmp(VolHdr.Id, BaculaAlignedDataId) != 0 &&
146 strcmp(VolHdr.Id, BaculaDedupMetaDataId) != 0 &&
147 strcmp(VolHdr.Id, BaculaS3CloudId) != 0) {
148 Mmsg(jcr->errmsg, _("Volume Header Id bad: %s\n"), VolHdr.Id);
149 Dmsg1(dbglvl, "%s", jcr->errmsg);
150 } else {
151 ok = true;
152 Dmsg1(dbglvl, "VolHdr.Id OK: %s\n", VolHdr.Id);
153 }
154 dcr->reading_label = false;
155 free_record(record); /* finished reading Volume record */
156
157 if (!is_volume_to_unload()) {
158 clear_unload();
159 }
160
161 if (!ok) {
162 if (jcr->ignore_label_errors) {
163 set_labeled(); /* set has Bacula label */
164 if (jcr->errmsg[0]) {
165 Jmsg(jcr, M_ERROR, 0, "%s", jcr->errmsg);
166 }
167 empty_block(dcr->block);
168 Leave(dbglvl);
169 return VOL_OK;
170 }
171 Dmsg0(dbglvl, "No volume label - bailing out\n");
172 stat = VOL_NO_LABEL;
173 goto bail_out;
174 }
175
176 /* At this point, we have read the first Bacula block, and
177 * then read the Bacula Volume label. Now we need to
178 * make sure we have the right Volume.
179 */
180 if (VolHdr.VerNum != BaculaTapeVersion &&
181 VolHdr.VerNum != BaculaMetaDataVersion &&
182 VolHdr.VerNum != BaculaDedupMetaDataVersion &&
183 VolHdr.VerNum != BaculaS3CloudVersion &&
184 VolHdr.VerNum != OldCompatibleBaculaTapeVersion1 &&
185 VolHdr.VerNum != OldCompatibleBaculaTapeVersion2) {
186 Mmsg(jcr->errmsg, _("Volume on %s device %s has wrong Bacula version. Wanted %d got %d\n"),
187 print_type(), print_name(), BaculaTapeVersion, VolHdr.VerNum);
188 Dmsg1(dbglvl, "VOL_VERSION_ERROR: %s", jcr->errmsg);
189 stat = VOL_VERSION_ERROR;
190 goto bail_out;
191 }
192 Dmsg1(dbglvl, "VolHdr.VerNum=%ld OK.\n", VolHdr.VerNum);
193
194 /* We are looking for either an unused Bacula tape (PRE_LABEL) or
195 * a Bacula volume label (VOL_LABEL)
196 */
197 if (VolHdr.LabelType != PRE_LABEL && VolHdr.LabelType != VOL_LABEL) {
198 Mmsg(jcr->errmsg, _("Volume on %s device %s has bad Bacula label type: %ld\n"),
199 print_type(), print_name(), VolHdr.LabelType);
200 Dmsg1(dbglvl, "%s", jcr->errmsg);
201 if (!poll && jcr->label_errors++ > 100) {
202 Jmsg(jcr, M_FATAL, 0, _("Too many tries: %s"), jcr->errmsg);
203 }
204 Dmsg0(dbglvl, "return VOL_LABEL_ERROR\n");
205 stat = VOL_LABEL_ERROR;
206 goto bail_out;
207 }
208
209 set_labeled(); /* set has Bacula label */
210
211 /* Compare Volume Names */
212 Dmsg2(130, "Compare Vol names: VolName=%s hdr=%s\n", VolName?VolName:"*", VolHdr.VolumeName);
213 if (VolName && *VolName && *VolName != '*' && strcmp(VolHdr.VolumeName, VolName) != 0) {
214 Mmsg(jcr->errmsg, _("Wrong Volume mounted on %s device %s: Wanted %s have %s\n"),
215 print_type(), print_name(), VolName, VolHdr.VolumeName);
216 Dmsg1(dbglvl, "%s", jcr->errmsg);
217 /*
218 * Cancel Job if too many label errors
219 * => we are in a loop
220 */
221 if (!poll && jcr->label_errors++ > 100) {
222 Jmsg(jcr, M_FATAL, 0, "Too many tries: %s", jcr->errmsg);
223 }
224 Dmsg0(dbglvl, "return VOL_NAME_ERROR\n");
225 stat = VOL_NAME_ERROR;
226 goto bail_out;
227 }
228
229 /* Compare VolType to Device Type */
230 switch (dev_type) {
231 case B_DEDUP_DEV:
232 if (strcmp(VolHdr.Id, BaculaDedupMetaDataId) != 0) {
233 Mmsg(jcr->errmsg, _("Wrong Volume Type. Wanted a Dedup Volume %s on device %s, but got: %s\n"),
234 VolHdr.VolumeName, print_name(), VolHdr.Id);
235 stat = VOL_TYPE_ERROR;
236 goto bail_out;
237 }
238 break;
239 case B_FILE_DEV:
240 if (strcmp(VolHdr.Id, BaculaId) != 0) {
241 Mmsg(jcr->errmsg, _("Wrong Volume Type. Wanted a File or Tape Volume %s on device %s, but got: %s\n"),
242 VolHdr.VolumeName, print_name(), VolHdr.Id);
243 stat = VOL_TYPE_ERROR;
244 goto bail_out;
245 }
246 break;
247 case B_ALIGNED_DEV:
248 case B_ADATA_DEV:
249 if (strcmp(VolHdr.Id, BaculaMetaDataId) != 0) {
250 Mmsg(jcr->errmsg, _("Wrong Volume Type. Wanted an Aligned Volume %s on device %s, but got: %s\n"),
251 VolHdr.VolumeName, print_name(), VolHdr.Id);
252 stat = VOL_TYPE_ERROR;
253 goto bail_out;
254 }
255 break;
256 case B_CLOUD_DEV:
257 if (strcmp(VolHdr.Id, BaculaS3CloudId) != 0) {
258 Mmsg(jcr->errmsg, _("Wrong Volume Type. Wanted a Cloud Volume %s on device %s, but got: %s\n"),
259 VolHdr.VolumeName, print_name(), VolHdr.Id);
260 stat = VOL_TYPE_ERROR;
261 goto bail_out;
262 }
263 default:
264 break;
265 }
266
267 if (chk_dbglvl(100)) {
268 dump_volume_label();
269 }
270 Dmsg0(dbglvl, "Leave read_volume_label() VOL_OK\n");
271 /* If we are a streaming device, we only get one chance to read */
272 if (!has_cap(CAP_STREAM)) {
273 rewind(dcr);
274 if (have_ansi_label) {
275 stat = read_ansi_ibm_label(dcr);
276 /* If we want a label and didn't find it, return error */
277 if (stat != VOL_OK) {
278 goto bail_out;
279 }
280 }
281 }
282
283 Dmsg1(100, "Call reserve_volume=%s\n", VolHdr.VolumeName);
284 if (reserve_volume(dcr, VolHdr.VolumeName) == NULL) {
285 if (!jcr->errmsg[0]) {
286 Mmsg3(jcr->errmsg, _("Could not reserve volume %s on %s device %s\n"),
287 VolHdr.VolumeName, print_type(), print_name());
288 }
289 Dmsg2(dbglvl, "Could not reserve volume %s on %s\n", VolHdr.VolumeName, print_name());
290 stat = VOL_NAME_ERROR;
291 goto bail_out;
292 }
293
294 if (dcr->is_writing()) {
295 empty_block(dcr->block);
296 }
297
298 Leave(dbglvl);
299 return VOL_OK;
300
301 bail_out:
302 empty_block(dcr->block);
303 rewind(dcr);
304 Dmsg2(dbglvl, "return stat=%d %s", stat, jcr->errmsg);
305 Leave(dbglvl);
306 return stat;
307 }
308
309
310 /*
311 * Create and put a volume label into the block
312 *
313 * Returns: false on failure
314 * true on success
315 *
316 * Handle both the ameta and adata volumes.
317 */
write_volume_label_to_block(DCR * dcr)318 bool DEVICE::write_volume_label_to_block(DCR *dcr)
319 {
320 DEVICE *dev;
321 DEV_RECORD rec;
322 JCR *jcr = dcr->jcr;
323 bool ok = true;
324
325 Enter(100);
326 dev = dcr->dev;
327 memset(&rec, 0, sizeof(rec));
328 rec.data = get_memory(SER_LENGTH_Volume_Label);
329 memset(rec.data, 0, SER_LENGTH_Volume_Label);
330 empty_block(dcr->block); /* Volume label always at beginning */
331
332 create_volume_label_record(dcr, dcr->dev, &rec, dcr->block->adata);
333
334 dcr->block->BlockNumber = 0;
335 /* Note for adata this also writes to disk */
336 Dmsg1(100, "write_record_to_block adata=%d\n", dcr->dev->adata);
337 if (!write_record_to_block(dcr, &rec)) {
338 free_pool_memory(rec.data);
339 Jmsg2(jcr, M_FATAL, 0, _("Cannot write Volume label to block for %s device %s\n"),
340 dev->print_type(), dev->print_name());
341 ok = false;
342 goto get_out;
343 } else {
344 Dmsg4(100, "Wrote fd=%d adata=%d label of %d bytes to block. Vol=%s\n",
345 dev->fd(), dcr->block->adata, rec.data_len, dcr->VolumeName);
346 }
347 free_pool_memory(rec.data);
348
349 get_out:
350 Leave(100);
351 return ok;
352 }
353
354 /*
355 * Write a Volume Label
356 * !!! Note, this is ONLY used for writing
357 * a fresh volume label. Any data
358 * after the label will be destroyed,
359 * in fact, we write the label 5 times !!!!
360 *
361 * This routine should be used only when labeling a blank tape or
362 * when recylcing a volume.
363 *
364 * Handle both the ameta and adata volumes.
365 */
write_volume_label(DCR * dcr,const char * VolName,const char * PoolName,bool relabel,bool no_prelabel)366 bool DEVICE::write_volume_label(DCR *dcr, const char *VolName,
367 const char *PoolName, bool relabel, bool no_prelabel)
368 {
369 DEVICE *dev;
370
371 Enter(100);
372 Dmsg4(230, "Write: block=%p ameta=%p dev=%p ameta_dev=%p\n",
373 dcr->block, dcr->ameta_block, dcr->dev, dcr->ameta_dev);
374 dcr->set_ameta();
375 dev = dcr->dev;
376
377 Dmsg0(150, "write_volume_label()\n");
378 if (*VolName == 0) {
379 if (dcr->jcr) {
380 Mmsg(dcr->jcr->errmsg, "ERROR: new_volume_label_to_dev called with NULL VolName\n");
381 }
382 Pmsg0(0, "=== ERROR: write_volume_label called with NULL VolName\n");
383 goto bail_out;
384 }
385
386 if (relabel) {
387 volume_unused(dcr); /* mark current volume unused */
388 /* Truncate device */
389 if (!dev->truncate(dcr)) {
390 goto bail_out;
391 }
392 dev->close_part(dcr); /* make sure closed for rename */
393 }
394
395 /* Set the new filename for open, ... */
396 dev->setVolCatName(VolName);
397 dcr->setVolCatName(VolName);
398 dev->clearVolCatBytes();
399
400 Dmsg1(100, "New VolName=%s\n", VolName);
401 if (!dev->open_device(dcr, OPEN_READ_WRITE)) {
402 /* If device is not tape, attempt to create it */
403 if (dev->is_tape() || !dev->open_device(dcr, CREATE_READ_WRITE)) {
404 Jmsg4(dcr->jcr, M_WARNING, 0, _("Open %s device %s Volume \"%s\" failed: ERR=%s"),
405 dev->print_type(), dev->print_name(), dcr->VolumeName, dev->bstrerror());
406 goto bail_out;
407 }
408 }
409 Dmsg1(150, "Label type=%d\n", dev->label_type);
410
411 if (!write_volume_label_to_dev(dcr, VolName, PoolName, relabel, no_prelabel)) {
412 goto bail_out;
413 }
414
415 if (!dev->is_aligned()) {
416 /* Not aligned data */
417 if (dev->weof(dcr, 1)) {
418 dev->set_labeled();
419 }
420
421 if (chk_dbglvl(100)) {
422 dev->dump_volume_label();
423 }
424 Dmsg0(50, "Call reserve_volume\n");
425 /**** ***FIXME*** if dev changes, dcr must be updated */
426 if (reserve_volume(dcr, VolName) == NULL) {
427 if (!dcr->jcr->errmsg[0]) {
428 Mmsg3(dcr->jcr->errmsg, _("Could not reserve volume %s on %s device %s\n"),
429 dev->VolHdr.VolumeName, dev->print_type(), dev->print_name());
430 }
431 Dmsg1(50, "%s", dcr->jcr->errmsg);
432 goto bail_out;
433 }
434 dev = dcr->dev; /* may have changed in reserve_volume */
435 }
436 dev->clear_append(); /* remove append since this is PRE_LABEL */
437 Leave(100);
438 return true;
439
440 bail_out:
441 dcr->adata_label = false;
442 dcr->set_ameta();
443 volume_unused(dcr);
444 dcr->dev->clear_append(); /* remove append since this is PRE_LABEL */
445 Leave(100);
446 return false;
447 }
448
write_volume_label_to_dev(DCR * dcr,const char * VolName,const char * PoolName,bool relabel,bool no_prelabel)449 bool DEVICE::write_volume_label_to_dev(DCR *dcr, const char *VolName,
450 const char *PoolName, bool relabel, bool no_prelabel)
451 {
452 DEVICE *dev, *ameta_dev;
453 DEV_RECORD *rec = new_record();
454 bool rtn = false;
455
456 Enter(100);
457 dev = dcr->dev;
458 ameta_dev = dcr->ameta_dev;
459
460 empty_block(dcr->block);
461 if (!dev->rewind(dcr)) {
462 Dmsg2(130, "Bad status on %s from rewind: ERR=%s\n", dev->print_name(), dev->print_errmsg());
463 goto bail_out;
464 }
465
466 /* Temporarily mark in append state to enable writing */
467 dev->set_append();
468
469 /* Create PRE_LABEL or VOL_LABEL */
470 create_volume_header(dev, VolName, PoolName, no_prelabel);
471
472 /*
473 * If we have already detected an ANSI label, re-read it
474 * to skip past it. Otherwise, we write a new one if
475 * so requested.
476 */
477 if (!dcr->block->adata) {
478 if (dev->label_type != B_BACULA_LABEL) {
479 if (read_ansi_ibm_label(dcr) != VOL_OK) {
480 dev->rewind(dcr);
481 goto bail_out;
482 }
483 } else if (!write_ansi_ibm_labels(dcr, ANSI_VOL_LABEL, VolName)) {
484 goto bail_out;
485 }
486 }
487
488 create_volume_label_record(dcr, dev, rec, dcr->block->adata);
489 rec->Stream = 0;
490 rec->maskedStream = 0;
491
492 Dmsg2(100, "write_record_to_block adata=%d FI=%d\n", dcr->dev->adata,
493 rec->FileIndex);
494
495 /* For adata label this also writes to disk */
496 if (!write_record_to_block(dcr, rec)) {
497 Dmsg2(40, "Bad Label write on %s: ERR=%s\n", dev->print_name(), dev->print_errmsg());
498 goto bail_out;
499 } else {
500 Dmsg3(100, "Wrote label=%d bytes adata=%d block: %s\n", rec->data_len, dcr->block->adata, dev->print_name());
501 }
502 Dmsg3(100, "New label adata=%d VolCatBytes=%lld VolCatStatus=%s\n",
503 dev->adata, ameta_dev->VolCatInfo.VolCatBytes, ameta_dev->VolCatInfo.VolCatStatus);
504
505 if (dcr->block->adata) {
506 /* Empty block and set data start address */
507 empty_block(dcr->adata_block);
508 } else {
509 Dmsg4(130, "Call write_block_to_dev() fd=%d adata=%d block=%p Addr=%lld\n",
510 dcr->dev->fd(), dcr->block->adata, dcr->block, dcr->block->dev->lseek(dcr, 0, SEEK_CUR));
511 Dmsg1(100, "write_record_to_dev adata=%d\n", dcr->dev->adata);
512 /* Write ameta block to device */
513 if (!dcr->write_block_to_dev()) {
514 Dmsg2(40, "Bad Label write on %s: ERR=%s\n", dev->print_name(), dev->print_errmsg());
515 goto bail_out;
516 }
517 }
518 Dmsg3(100, "Wrote new Vol label adata=%d VolCatBytes=%lld VolCatStatus=%s\n",
519 dev->adata, ameta_dev->VolCatInfo.VolCatBytes, ameta_dev->VolCatInfo.VolCatStatus);
520 rtn = true;
521
522 bail_out:
523 free_record(rec);
524 Leave(100);
525 return rtn;
526 }
527
528 /*
529 * Write a volume label. This is ONLY called if we have a valid Bacula
530 * label of type PRE_LABEL or we are recyling an existing Volume.
531 *
532 * By calling write_volume_label_to_block, both ameta and adata
533 * are updated.
534 *
535 * Returns: true if OK
536 * false if unable to write it
537 */
rewrite_volume_label(DCR * dcr,bool recycle)538 bool DEVICE::rewrite_volume_label(DCR *dcr, bool recycle)
539 {
540 char ed1[50];
541 JCR *jcr = dcr->jcr;
542
543 Enter(100);
544 ASSERT2(dcr->VolumeName[0], "Empty Volume name");
545 ASSERT(!dcr->block->adata);
546 if (is_worm()) {
547 Jmsg3(jcr, M_FATAL, 0, _("Cannot relabel worm %s device %s Volume \"%s\"\n"),
548 print_type(), print_name(), dcr->VolumeName);
549 Leave(100);
550 return false;
551 }
552 if (!open_device(dcr, OPEN_READ_WRITE)) {
553 Jmsg4(jcr, M_WARNING, 0, _("Open %s device %s Volume \"%s\" failed: ERR=%s\n"),
554 print_type(), print_name(), dcr->VolumeName, bstrerror());
555 Leave(100);
556 return false;
557 }
558 Dmsg2(190, "set append found freshly labeled volume. fd=%d dev=%x\n", fd(), this);
559 VolHdr.LabelType = VOL_LABEL; /* set Volume label */
560 set_append();
561 Dmsg0(100, "Rewrite_volume_label set volcatbytes=0\n");
562 clearVolCatBytes(); /* resets both ameta and adata byte counts */
563 setVolCatStatus("Append"); /* set append status */
564
565 if (!has_cap(CAP_STREAM)) {
566 if (!rewind(dcr)) {
567 Jmsg3(jcr, M_FATAL, 0, _("Rewind error on %s device %s: ERR=%s\n"),
568 print_type(), print_name(), print_errmsg());
569 Leave(100);
570 return false;
571 }
572 if (recycle) {
573 Dmsg1(150, "Doing recycle. Vol=%s\n", dcr->VolumeName);
574 if (!truncate(dcr)) {
575 Jmsg3(jcr, M_FATAL, 0, _("Truncate error on %s device %s: ERR=%s\n"),
576 print_type(), print_name(), print_errmsg());
577 Leave(100);
578 return false;
579 }
580 if (!open_device(dcr, OPEN_READ_WRITE)) {
581 Jmsg3(jcr, M_FATAL, 0,
582 _("Failed to re-open device after truncate on %s device %s: ERR=%s"),
583 print_type(), print_name(), print_errmsg());
584 Leave(100);
585 return false;
586 }
587 }
588 }
589
590 if (!write_volume_label_to_block(dcr)) {
591 Dmsg0(150, "Error from write volume label.\n");
592 Leave(100);
593 return false;
594 }
595 Dmsg2(100, "wrote vol label to block. adata=%d Vol=%s\n", dcr->block->adata, dcr->VolumeName);
596
597 ASSERT2(dcr->VolumeName[0], "Empty Volume name");
598 setVolCatInfo(false);
599
600 /*
601 * If we are not dealing with a streaming device,
602 * write the block now to ensure we have write permission.
603 * It is better to find out now rather than later.
604 * We do not write the block now if this is an ANSI label. This
605 * avoids re-writing the ANSI label, which we do not want to do.
606 */
607 if (!has_cap(CAP_STREAM)) {
608 /*
609 * If we have already detected an ANSI label, re-read it
610 * to skip past it. Otherwise, we write a new one if
611 * so requested.
612 */
613 if (label_type != B_BACULA_LABEL) {
614 if (read_ansi_ibm_label(dcr) != VOL_OK) {
615 rewind(dcr);
616 Leave(100);
617 return false;
618 }
619 } else if (!write_ansi_ibm_labels(dcr, ANSI_VOL_LABEL, VolHdr.VolumeName)) {
620 Leave(100);
621 return false;
622 }
623
624 /* Attempt write to check write permission */
625 Dmsg1(200, "Attempt to write to device fd=%d.\n", fd());
626 if (!dcr->write_block_to_dev()) {
627 Jmsg3(jcr, M_ERROR, 0, _("Unable to write %s device %s: ERR=%s\n"),
628 print_type(), print_name(), print_errmsg());
629 Dmsg0(200, "===ERROR write block to dev\n");
630 Leave(100);
631 return false;
632 }
633 }
634 ASSERT2(dcr->VolumeName[0], "Empty Volume name");
635 setVolCatName(dcr->VolumeName);
636 if (!dir_get_volume_info(dcr, dcr->VolumeName, GET_VOL_INFO_FOR_WRITE)) {
637 Leave(100);
638 return false;
639 }
640 set_labeled();
641 /* Set or reset Volume statistics */
642 VolCatInfo.VolCatJobs = 0;
643 VolCatInfo.VolCatFiles = 0;
644 VolCatInfo.VolCatErrors = 0;
645 VolCatInfo.VolCatBlocks = 0;
646 VolCatInfo.VolCatRBytes = 0;
647 VolCatInfo.VolCatCloudParts = 0;
648 VolCatInfo.VolLastPartBytes = 0;
649 VolCatInfo.VolCatType = 0; /* Will be set by dir_update_volume_info() */
650 if (recycle) {
651 VolCatInfo.VolCatMounts++;
652 VolCatInfo.VolCatRecycles++;
653 } else {
654 VolCatInfo.VolCatMounts = 1;
655 VolCatInfo.VolCatRecycles = 0;
656 VolCatInfo.VolCatWrites = 1;
657 VolCatInfo.VolCatReads = 1;
658 }
659 dcr->VolMediaId = dcr->VolCatInfo.VolMediaId; /* make create_jobmedia work */
660 dir_create_jobmedia_record(dcr, true);
661 Dmsg1(100, "dir_update_vol_info. Set Append vol=%s\n", dcr->VolumeName);
662 VolCatInfo.VolFirstWritten = time(NULL);
663 setVolCatStatus("Append");
664 if (!dir_update_volume_info(dcr, true, true)) { /* indicate relabel */
665 Leave(100);
666 return false;
667 }
668 if (recycle) {
669 Jmsg(jcr, M_INFO, 0, _("Recycled volume \"%s\" on %s device %s, all previous data lost.\n"),
670 dcr->VolumeName, print_type(), print_name());
671 } else {
672 Jmsg(jcr, M_INFO, 0, _("Wrote label to prelabeled Volume \"%s\" on %s device %s\n"),
673 dcr->VolumeName, print_type(), print_name());
674 }
675 /*
676 * End writing real Volume label (from pre-labeled tape), or recycling
677 * the volume.
678 */
679 Dmsg4(100, "OK rewrite vol label. Addr=%s adata=%d slot=%d Vol=%s\n",
680 print_addr(ed1, sizeof(ed1)), dcr->block->adata, VolCatInfo.Slot, dcr->VolumeName);
681 Leave(100);
682 return true;
683 }
684
685
686 /*
687 * create_volume_label_record
688 * Note: it is assumed that you have created the volume_header
689 * (label) prior to calling this subroutine.
690 * Serialize label (from dev->VolHdr structure) into device record.
691 * Assumes that the dev->VolHdr structure is properly
692 * initialized.
693 */
create_volume_label_record(DCR * dcr,DEVICE * dev,DEV_RECORD * rec,bool adata)694 static void create_volume_label_record(DCR *dcr, DEVICE *dev,
695 DEV_RECORD *rec, bool adata)
696 {
697 ser_declare;
698 struct date_time dt;
699 JCR *jcr = dcr->jcr;
700 char buf[100];
701
702 /* Serialize the label into the device record. */
703
704 Enter(100);
705 rec->data = check_pool_memory_size(rec->data, SER_LENGTH_Volume_Label);
706 memset(rec->data, 0, SER_LENGTH_Volume_Label);
707 ser_begin(rec->data, SER_LENGTH_Volume_Label);
708 ser_string(dev->VolHdr.Id);
709
710 ser_uint32(dev->VolHdr.VerNum);
711
712 if (dev->VolHdr.VerNum >= 11) {
713 ser_btime(dev->VolHdr.label_btime);
714 dev->VolHdr.write_btime = get_current_btime();
715 ser_btime(dev->VolHdr.write_btime);
716 dev->VolHdr.write_date = 0;
717 dev->VolHdr.write_time = 0;
718 } else {
719 /* OLD WAY DEPRECATED */
720 ser_float64(dev->VolHdr.label_date);
721 ser_float64(dev->VolHdr.label_time);
722 get_current_time(&dt);
723 dev->VolHdr.write_date = dt.julian_day_number;
724 dev->VolHdr.write_time = dt.julian_day_fraction;
725 }
726 ser_float64(dev->VolHdr.write_date); /* 0 if VerNum >= 11 */
727 ser_float64(dev->VolHdr.write_time); /* 0 if VerNum >= 11 */
728
729 ser_string(dev->VolHdr.VolumeName);
730 ser_string(dev->VolHdr.PrevVolumeName);
731 ser_string(dev->VolHdr.PoolName);
732 ser_string(dev->VolHdr.PoolType);
733 ser_string(dev->VolHdr.MediaType);
734
735 ser_string(dev->VolHdr.HostName);
736 ser_string(dev->VolHdr.LabelProg);
737 ser_string(dev->VolHdr.ProgVersion);
738 ser_string(dev->VolHdr.ProgDate);
739 /* ***FIXME*** */
740 dev->VolHdr.AlignedVolumeName[0] = 0;
741 ser_string(dev->VolHdr.AlignedVolumeName);
742
743 /* This is adata Volume information */
744 ser_uint64(dev->VolHdr.FirstData);
745 ser_uint32(dev->VolHdr.FileAlignment);
746 ser_uint32(dev->VolHdr.PaddingSize);
747 /* adata and dedup volumes */
748 ser_uint32(dev->VolHdr.BlockSize);
749
750 ser_end(rec->data, SER_LENGTH_Volume_Label);
751 if (!adata) {
752 bstrncpy(dcr->VolumeName, dev->VolHdr.VolumeName, sizeof(dcr->VolumeName));
753 }
754 ASSERT2(dcr->VolumeName[0], "Empty Volume name");
755 rec->data_len = ser_length(rec->data);
756 rec->FileIndex = dev->VolHdr.LabelType;
757 Dmsg2(100, "LabelType=%d adata=%d\n", dev->VolHdr.LabelType, dev->adata);
758 rec->VolSessionId = jcr->VolSessionId;
759 rec->VolSessionTime = jcr->VolSessionTime;
760 rec->Stream = jcr->NumWriteVolumes;
761 rec->maskedStream = jcr->NumWriteVolumes;
762 Dmsg3(100, "Created adata=%d Vol label rec: FI=%s len=%d\n", adata, FI_to_ascii(buf, rec->FileIndex),
763 rec->data_len);
764 Dmsg2(100, "reclen=%d recdata=%s", rec->data_len, rec->data);
765 Leave(100);
766 }
767
768
769 /*
770 * Create a volume header (label) in memory
771 * The volume record is created after this header (label)
772 * is created.
773 */
create_volume_header(DEVICE * dev,const char * VolName,const char * PoolName,bool no_prelabel)774 void create_volume_header(DEVICE *dev, const char *VolName,
775 const char *PoolName, bool no_prelabel)
776 {
777 DEVRES *device = (DEVRES *)dev->device;
778
779 Enter(130);
780
781 ASSERT2(dev != NULL, "dev ptr is NULL");
782
783 if (dev->is_aligned()) {
784 bstrncpy(dev->VolHdr.Id, BaculaMetaDataId, sizeof(dev->VolHdr.Id));
785 dev->VolHdr.VerNum = BaculaMetaDataVersion;
786 dev->VolHdr.FirstData = dev->file_alignment;
787 dev->VolHdr.FileAlignment = dev->file_alignment;
788 dev->VolHdr.PaddingSize = dev->padding_size;
789 dev->VolHdr.BlockSize = dev->adata_size;
790 } else if (dev->is_adata()) {
791 bstrncpy(dev->VolHdr.Id, BaculaAlignedDataId, sizeof(dev->VolHdr.Id));
792 dev->VolHdr.VerNum = BaculaAlignedDataVersion;
793 dev->VolHdr.FirstData = dev->file_alignment;
794 dev->VolHdr.FileAlignment = dev->file_alignment;
795 dev->VolHdr.PaddingSize = dev->padding_size;
796 dev->VolHdr.BlockSize = dev->adata_size;
797 } else if (dev->is_dedup()) {
798 bstrncpy(dev->VolHdr.Id, BaculaDedupMetaDataId, sizeof(dev->VolHdr.Id));
799 dev->VolHdr.VerNum = BaculaDedupMetaDataVersion;
800 dev->VolHdr.BlockSize = dev->max_block_size;
801 } else if (dev->is_cloud()) {
802 bstrncpy(dev->VolHdr.Id, BaculaS3CloudId, sizeof(dev->VolHdr.Id));
803 dev->VolHdr.VerNum = BaculaS3CloudVersion;
804 dev->VolHdr.BlockSize = dev->max_block_size;
805 dev->VolHdr.MaxPartSize = dev->max_part_size;
806 } else {
807 bstrncpy(dev->VolHdr.Id, BaculaId, sizeof(dev->VolHdr.Id));
808 dev->VolHdr.VerNum = BaculaTapeVersion;
809 dev->VolHdr.BlockSize = dev->max_block_size;
810 }
811
812 if ((dev->has_cap(CAP_STREAM) && no_prelabel) || dev->is_worm()) {
813 /* We do not want to re-label so write VOL_LABEL now */
814 dev->VolHdr.LabelType = VOL_LABEL;
815 } else {
816 dev->VolHdr.LabelType = PRE_LABEL; /* Mark Volume as unused */
817 }
818 bstrncpy(dev->VolHdr.VolumeName, VolName, sizeof(dev->VolHdr.VolumeName));
819 bstrncpy(dev->VolHdr.PoolName, PoolName, sizeof(dev->VolHdr.PoolName));
820 bstrncpy(dev->VolHdr.MediaType, device->media_type, sizeof(dev->VolHdr.MediaType));
821
822 bstrncpy(dev->VolHdr.PoolType, "Backup", sizeof(dev->VolHdr.PoolType));
823
824 dev->VolHdr.label_btime = get_current_btime();
825 dev->VolHdr.label_date = 0;
826 dev->VolHdr.label_time = 0;
827
828 if (gethostname(dev->VolHdr.HostName, sizeof(dev->VolHdr.HostName)) != 0) {
829 dev->VolHdr.HostName[0] = 0;
830 }
831 bstrncpy(dev->VolHdr.LabelProg, my_name, sizeof(dev->VolHdr.LabelProg));
832 sprintf(dev->VolHdr.ProgVersion, "Ver. %s %s ", VERSION, BDATE);
833 sprintf(dev->VolHdr.ProgDate, "Build %s %s ", __DATE__, __TIME__);
834 dev->set_labeled(); /* set has Bacula label */
835 if (chk_dbglvl(100)) {
836 dev->dump_volume_label();
837 }
838 }
839
840 /*
841 * Create session (Job) label
842 * The pool memory must be released by the calling program
843 */
create_session_label(DCR * dcr,DEV_RECORD * rec,int label)844 void create_session_label(DCR *dcr, DEV_RECORD *rec, int label)
845 {
846 JCR *jcr = dcr->jcr;
847 ser_declare;
848
849 Enter(100);
850 rec->VolSessionId = jcr->VolSessionId;
851 rec->VolSessionTime = jcr->VolSessionTime;
852 rec->Stream = jcr->JobId;
853 rec->maskedStream = jcr->JobId;
854
855 rec->data = check_pool_memory_size(rec->data, SER_LENGTH_Session_Label);
856 ser_begin(rec->data, SER_LENGTH_Session_Label);
857 ser_string(BaculaId);
858 ser_uint32(BaculaTapeVersion);
859
860 ser_uint32(jcr->JobId);
861
862 /* Changed in VerNum 11 */
863 ser_btime(get_current_btime());
864 ser_float64(0);
865
866 ser_string(dcr->pool_name);
867 ser_string(dcr->pool_type);
868 ser_string(jcr->job_name); /* base Job name */
869 ser_string(jcr->client_name);
870
871 /* Added in VerNum 10 */
872 ser_string(jcr->Job); /* Unique name of this Job */
873 ser_string(jcr->fileset_name);
874 ser_uint32(jcr->getJobType());
875 ser_uint32(jcr->getJobLevel());
876 /* Added in VerNum 11 */
877 ser_string(jcr->fileset_md5);
878
879 if (label == EOS_LABEL) {
880 ser_uint32(jcr->JobFiles);
881 ser_uint64(jcr->JobBytes);
882 ser_uint32((uint32_t)dcr->StartAddr); /* Start Block */
883 ser_uint32((uint32_t)dcr->EndAddr); /* End Block */
884 ser_uint32((uint32_t)(dcr->StartAddr>>32)); /* Start File */
885 ser_uint32((uint32_t)(dcr->EndAddr>>32)); /* End File */
886 ser_uint32(jcr->JobErrors);
887
888 /* Added in VerNum 11 */
889 ser_uint32(jcr->JobStatus);
890 }
891 ser_end(rec->data, SER_LENGTH_Session_Label);
892 rec->data_len = ser_length(rec->data);
893 Leave(100);
894 }
895
896 /* Write session (Job) label
897 * Returns: false on failure
898 * true on success
899 */
write_session_label(DCR * dcr,int label)900 bool write_session_label(DCR *dcr, int label)
901 {
902 JCR *jcr = dcr->jcr;
903 DEVICE *dev = dcr->dev;
904 DEV_RECORD *rec;
905 DEV_BLOCK *block = dcr->block;
906 char buf1[100], buf2[100];
907
908 Enter(100);
909 dev->Lock();
910 Dmsg2(140, "=== write_session_label label=%d Vol=%s.\n", label, dev->getVolCatName());
911 if (!check_for_newvol_or_newfile(dcr)) {
912 Pmsg0(000, "ERR: !check_for_new_vol_or_newfile\n");
913 dev->Unlock();
914 return false;
915 }
916
917 rec = new_record();
918 Dmsg1(130, "session_label record=%x\n", rec);
919 switch (label) {
920 case SOS_LABEL:
921 set_start_vol_position(dcr);
922 break;
923 case EOS_LABEL:
924 dcr->EndAddr = dev->get_full_addr();
925 break;
926 default:
927 Jmsg1(jcr, M_ABORT, 0, _("Bad Volume session label request=%d\n"), label);
928 break;
929 }
930
931 create_session_label(dcr, rec, label);
932 rec->FileIndex = label;
933 dev->Unlock();
934
935 /*
936 * We guarantee that the session record can totally fit
937 * into a block. If not, write the block, and put it in
938 * the next block. Having the sesssion record totally in
939 * one block makes reading them much easier (no need to
940 * read the next block).
941 */
942 if (!can_write_record_to_block(block, rec)) {
943 Dmsg0(150, "Cannot write session label to block.\n");
944 if (!dcr->write_block_to_device()) {
945 Dmsg0(130, "Got session label write_block_to_dev error.\n");
946 free_record(rec);
947 Leave(100);
948 return false;
949 }
950 }
951 /*
952 * We use write_record() because it handles the case that
953 * the maximum user size has been reached.
954 */
955 if (!dcr->write_record(rec)) {
956 Dmsg0(150, "Bad return from write_record\n");
957 free_record(rec);
958 Leave(100);
959 return false;
960 }
961
962 Dmsg6(150, "Write sesson_label record JobId=%d FI=%s SessId=%d Strm=%s len=%d "
963 "remainder=%d\n", jcr->JobId,
964 FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId,
965 stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len,
966 rec->remainder);
967
968 free_record(rec);
969 Dmsg2(150, "Leave write_session_label Block=%u File=%u\n",
970 dev->get_block_num(), dev->get_file());
971 Leave(100);
972 return true;
973 }
974
975 /* unser_volume_label
976 *
977 * Unserialize the Bacula Volume label into the device Volume_Label
978 * structure.
979 *
980 * Assumes that the record is already read.
981 *
982 * Returns: false on error
983 * true on success
984 */
985
unser_volume_label(DEVICE * dev,DEV_RECORD * rec)986 bool unser_volume_label(DEVICE *dev, DEV_RECORD *rec)
987 {
988 ser_declare;
989 char buf1[100], buf2[100];
990
991 Enter(100);
992 if (rec->FileIndex != VOL_LABEL && rec->FileIndex != PRE_LABEL) {
993 Mmsg3(dev->errmsg, _("Expecting Volume Label, got FI=%s Stream=%s len=%d\n"),
994 FI_to_ascii(buf1, rec->FileIndex),
995 stream_to_ascii(buf2, rec->Stream, rec->FileIndex),
996 rec->data_len);
997 if (!forge_on) {
998 Leave(100);
999 return false;
1000 }
1001 }
1002
1003 dev->VolHdr.LabelType = rec->FileIndex;
1004 dev->VolHdr.LabelSize = rec->data_len;
1005
1006
1007 /* Unserialize the record into the Volume Header */
1008 Dmsg2(100, "reclen=%d recdata=%s", rec->data_len, rec->data);
1009 rec->data = check_pool_memory_size(rec->data, SER_LENGTH_Volume_Label);
1010 Dmsg2(100, "reclen=%d recdata=%s", rec->data_len, rec->data);
1011 ser_begin(rec->data, SER_LENGTH_Volume_Label);
1012 unser_string(dev->VolHdr.Id);
1013 unser_uint32(dev->VolHdr.VerNum);
1014
1015 if (dev->VolHdr.VerNum >= 11) {
1016 unser_btime(dev->VolHdr.label_btime);
1017 unser_btime(dev->VolHdr.write_btime);
1018 } else { /* old way */
1019 unser_float64(dev->VolHdr.label_date);
1020 unser_float64(dev->VolHdr.label_time);
1021 }
1022 unser_float64(dev->VolHdr.write_date); /* Unused with VerNum >= 11 */
1023 unser_float64(dev->VolHdr.write_time); /* Unused with VerNum >= 11 */
1024
1025 unser_string(dev->VolHdr.VolumeName);
1026 unser_string(dev->VolHdr.PrevVolumeName);
1027 unser_string(dev->VolHdr.PoolName);
1028 unser_string(dev->VolHdr.PoolType);
1029 unser_string(dev->VolHdr.MediaType);
1030
1031 unser_string(dev->VolHdr.HostName);
1032 unser_string(dev->VolHdr.LabelProg);
1033 unser_string(dev->VolHdr.ProgVersion);
1034 unser_string(dev->VolHdr.ProgDate);
1035
1036 // unser_string(dev->VolHdr.AlignedVolumeName);
1037 dev->VolHdr.AlignedVolumeName[0] = 0;
1038 unser_uint64(dev->VolHdr.FirstData);
1039 unser_uint32(dev->VolHdr.FileAlignment);
1040 unser_uint32(dev->VolHdr.PaddingSize);
1041 unser_uint32(dev->VolHdr.BlockSize);
1042
1043 ser_end(rec->data, SER_LENGTH_Volume_Label);
1044 Dmsg0(190, "unser_vol_label\n");
1045 if (chk_dbglvl(100)) {
1046 dev->dump_volume_label();
1047 }
1048 Leave(100);
1049 return true;
1050 }
1051
1052
unser_session_label(SESSION_LABEL * label,DEV_RECORD * rec)1053 bool unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec)
1054 {
1055 ser_declare;
1056
1057 Enter(100);
1058 rec->data = check_pool_memory_size(rec->data, SER_LENGTH_Session_Label);
1059 unser_begin(rec->data, SER_LENGTH_Session_Label);
1060 unser_string(label->Id);
1061 unser_uint32(label->VerNum);
1062 unser_uint32(label->JobId);
1063 if (label->VerNum >= 11) {
1064 unser_btime(label->write_btime);
1065 } else {
1066 unser_float64(label->write_date);
1067 }
1068 unser_float64(label->write_time);
1069 unser_string(label->PoolName);
1070 unser_string(label->PoolType);
1071 unser_string(label->JobName);
1072 unser_string(label->ClientName);
1073 if (label->VerNum >= 10) {
1074 unser_string(label->Job); /* Unique name of this Job */
1075 unser_string(label->FileSetName);
1076 unser_uint32(label->JobType);
1077 unser_uint32(label->JobLevel);
1078 }
1079 if (label->VerNum >= 11) {
1080 unser_string(label->FileSetMD5);
1081 } else {
1082 label->FileSetMD5[0] = 0;
1083 }
1084 if (rec->FileIndex == EOS_LABEL) {
1085 unser_uint32(label->JobFiles);
1086 unser_uint64(label->JobBytes);
1087 unser_uint32(label->StartBlock);
1088 unser_uint32(label->EndBlock);
1089 unser_uint32(label->StartFile);
1090 unser_uint32(label->EndFile);
1091 unser_uint32(label->JobErrors);
1092 if (label->VerNum >= 11) {
1093 unser_uint32(label->JobStatus);
1094 } else {
1095 label->JobStatus = JS_Terminated; /* kludge */
1096 }
1097 }
1098 Leave(100);
1099 return true;
1100 }
1101
dump_volume_label()1102 void DEVICE::dump_volume_label()
1103 {
1104 int64_t dbl = debug_level;
1105 uint32_t File;
1106 const char *LabelType;
1107 char buf[30];
1108 struct tm tm;
1109 struct date_time dt;
1110
1111 debug_level = 1;
1112 File = file;
1113 switch (VolHdr.LabelType) {
1114 case PRE_LABEL:
1115 LabelType = "PRE_LABEL";
1116 break;
1117 case VOL_LABEL:
1118 LabelType = "VOL_LABEL";
1119 break;
1120 case EOM_LABEL:
1121 LabelType = "EOM_LABEL";
1122 break;
1123 case SOS_LABEL:
1124 LabelType = "SOS_LABEL";
1125 break;
1126 case EOS_LABEL:
1127 LabelType = "EOS_LABEL";
1128 break;
1129 case EOT_LABEL:
1130 goto bail_out;
1131 default:
1132 LabelType = buf;
1133 sprintf(buf, _("Unknown %d"), VolHdr.LabelType);
1134 break;
1135 }
1136
1137 Pmsg12(-1, _("\nVolume Label:\n"
1138 "Adata : %d\n"
1139 "Id : %s"
1140 "VerNo : %d\n"
1141 "VolName : %s\n"
1142 "PrevVolName : %s\n"
1143 "VolFile : %d\n"
1144 "LabelType : %s\n"
1145 "LabelSize : %d\n"
1146 "PoolName : %s\n"
1147 "MediaType : %s\n"
1148 "PoolType : %s\n"
1149 "HostName : %s\n"
1150 ""),
1151 adata,
1152 VolHdr.Id, VolHdr.VerNum,
1153 VolHdr.VolumeName, VolHdr.PrevVolumeName,
1154 File, LabelType, VolHdr.LabelSize,
1155 VolHdr.PoolName, VolHdr.MediaType,
1156 VolHdr.PoolType, VolHdr.HostName);
1157
1158 if (VolHdr.VerNum >= 11) {
1159 char dt[50];
1160 bstrftime(dt, sizeof(dt), btime_to_utime(VolHdr.label_btime));
1161 Pmsg1(-1, _("Date label written: %s\n"), dt);
1162 } else {
1163 dt.julian_day_number = VolHdr.label_date;
1164 dt.julian_day_fraction = VolHdr.label_time;
1165 tm_decode(&dt, &tm);
1166 Pmsg5(-1,
1167 _("Date label written: %04d-%02d-%02d at %02d:%02d\n"),
1168 tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min);
1169 }
1170
1171 bail_out:
1172 debug_level = dbl;
1173 }
1174
1175
dump_session_label(DEV_RECORD * rec,const char * type)1176 static void dump_session_label(DEV_RECORD *rec, const char *type)
1177 {
1178 int64_t dbl;
1179 struct date_time dt;
1180 struct tm tm;
1181 SESSION_LABEL label;
1182 char ec1[30], ec2[30], ec3[30], ec4[30], ec5[30], ec6[30], ec7[30];
1183
1184 unser_session_label(&label, rec);
1185 dbl = debug_level;
1186 debug_level = 1;
1187 Pmsg7(-1, _("\n%s Record:\n"
1188 "JobId : %d\n"
1189 "VerNum : %d\n"
1190 "PoolName : %s\n"
1191 "PoolType : %s\n"
1192 "JobName : %s\n"
1193 "ClientName : %s\n"
1194 ""), type, label.JobId, label.VerNum,
1195 label.PoolName, label.PoolType,
1196 label.JobName, label.ClientName);
1197
1198 if (label.VerNum >= 10) {
1199 Pmsg4(-1, _(
1200 "Job (unique name) : %s\n"
1201 "FileSet : %s\n"
1202 "JobType : %c\n"
1203 "JobLevel : %c\n"
1204 ""), label.Job, label.FileSetName, label.JobType, label.JobLevel);
1205 }
1206
1207 if (rec->FileIndex == EOS_LABEL) {
1208 Pmsg8(-1, _(
1209 "JobFiles : %s\n"
1210 "JobBytes : %s\n"
1211 "StartBlock : %s\n"
1212 "EndBlock : %s\n"
1213 "StartFile : %s\n"
1214 "EndFile : %s\n"
1215 "JobErrors : %s\n"
1216 "JobStatus : %c\n"
1217 ""),
1218 edit_uint64_with_commas(label.JobFiles, ec1),
1219 edit_uint64_with_commas(label.JobBytes, ec2),
1220 edit_uint64_with_commas(label.StartBlock, ec3),
1221 edit_uint64_with_commas(label.EndBlock, ec4),
1222 edit_uint64_with_commas(label.StartFile, ec5),
1223 edit_uint64_with_commas(label.EndFile, ec6),
1224 edit_uint64_with_commas(label.JobErrors, ec7),
1225 label.JobStatus);
1226 }
1227 if (label.VerNum >= 11) {
1228 char dt[50];
1229 bstrftime(dt, sizeof(dt), btime_to_utime(label.write_btime));
1230 Pmsg1(-1, _("Date written : %s\n"), dt);
1231 } else {
1232 dt.julian_day_number = label.write_date;
1233 dt.julian_day_fraction = label.write_time;
1234 tm_decode(&dt, &tm);
1235 Pmsg5(-1, _("Date written : %04d-%02d-%02d at %02d:%02d\n"),
1236 tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min);
1237 }
1238
1239 debug_level = dbl;
1240 }
1241
check_label(SESSION_LABEL * label)1242 static int check_label(SESSION_LABEL *label)
1243 {
1244 int errors = 0;
1245
1246 if (label->JobId > 10000000 || label->JobId < 0) {
1247 Pmsg0(-1, _("***** ERROR ****** : Found error with the JobId\n"));
1248 errors++;
1249 }
1250
1251 if (!errors) {
1252 switch (label->JobLevel) {
1253 case L_FULL:
1254 case L_INCREMENTAL:
1255 case L_DIFFERENTIAL:
1256 case L_SINCE:
1257 case L_VERIFY_CATALOG:
1258 case L_VERIFY_INIT:
1259 case L_VERIFY_VOLUME_TO_CATALOG:
1260 case L_VERIFY_DISK_TO_CATALOG:
1261 case L_VERIFY_DATA:
1262 case L_BASE:
1263 case L_NONE:
1264 case L_VIRTUAL_FULL:
1265 break;
1266 default:
1267 Pmsg0(-1, _("***** ERROR ****** : Found error with the JobLevel\n"));
1268 errors++;
1269 }
1270 }
1271 if (!errors) {
1272 switch (label->JobType) {
1273 case JT_BACKUP:
1274 case JT_MIGRATED_JOB:
1275 case JT_VERIFY:
1276 case JT_RESTORE:
1277 case JT_CONSOLE:
1278 case JT_SYSTEM:
1279 case JT_ADMIN:
1280 case JT_ARCHIVE:
1281 case JT_JOB_COPY:
1282 case JT_COPY:
1283 case JT_MIGRATE:
1284 case JT_SCAN:
1285 break;
1286 default:
1287 Pmsg0(-1, _("***** ERROR ****** : Found error with the JobType\n"));
1288 errors++;
1289 }
1290 }
1291 if (!errors) {
1292 POOLMEM *err = get_pool_memory(PM_EMSG);
1293 if (!is_name_valid(label->Job, &err)) {
1294 Pmsg1(-1, _("***** ERROR ****** : Found error with the Job name %s\n"), err);
1295 errors++;
1296 }
1297 free_pool_memory(err);
1298 }
1299 return errors;
1300 }
1301
dump_label_record(DEVICE * dev,DEV_RECORD * rec,int verbose,bool check_err)1302 int dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose, bool check_err)
1303 {
1304 const char *type;
1305 int64_t dbl;
1306 int errors = 0;
1307
1308 if (rec->FileIndex == 0 && rec->VolSessionId == 0 && rec->VolSessionTime == 0) {
1309 return 0;
1310 }
1311 dbl = debug_level;
1312 debug_level = 1;
1313 switch (rec->FileIndex) {
1314 case PRE_LABEL:
1315 type = _("Fresh Volume");
1316 break;
1317 case VOL_LABEL:
1318 type = _("Volume");
1319 break;
1320 case SOS_LABEL:
1321 type = _("Begin Job Session");
1322 break;
1323 case EOS_LABEL:
1324 type = _("End Job Session");
1325 break;
1326 case EOM_LABEL:
1327 type = _("End of Media");
1328 break;
1329 case EOT_LABEL:
1330 type = _("End of Tape");
1331 break;
1332 default:
1333 type = _("Unknown");
1334 break;
1335 }
1336 if (verbose) {
1337 switch (rec->FileIndex) {
1338 case PRE_LABEL:
1339 case VOL_LABEL:
1340 unser_volume_label(dev, rec);
1341 dev->dump_volume_label();
1342 break;
1343
1344 case EOS_LABEL:
1345 case SOS_LABEL:
1346 dump_session_label(rec, type);
1347 break;
1348 case EOM_LABEL:
1349 Pmsg7(-1, _("%s Record: File:blk=%u:%u SessId=%d SessTime=%d JobId=%d DataLen=%d\n"),
1350 type, dev->file, dev->block_num, rec->VolSessionId,
1351 rec->VolSessionTime, rec->Stream, rec->data_len);
1352 break;
1353 case EOT_LABEL:
1354 Pmsg0(-1, _("Bacula \"End of Tape\" label found.\n"));
1355 break;
1356 default:
1357 Pmsg7(-1, _("%s Record: File:blk=%u:%u SessId=%d SessTime=%d JobId=%d DataLen=%d\n"),
1358 type, dev->file, dev->block_num, rec->VolSessionId,
1359 rec->VolSessionTime, rec->Stream, rec->data_len);
1360 break;
1361 }
1362 } else {
1363 SESSION_LABEL label;
1364 char dt[50];
1365 switch (rec->FileIndex) {
1366 case SOS_LABEL:
1367 unser_session_label(&label, rec);
1368 bstrftimes(dt, sizeof(dt), btime_to_utime(label.write_btime));
1369 Pmsg6(-1, _("%s Record: File:blk=%u:%u SessId=%d SessTime=%d JobId=%d\n"),
1370 type, dev->file, dev->block_num, rec->VolSessionId, rec->VolSessionTime, label.JobId);
1371 Pmsg4(-1, _(" Job=%s Date=%s Level=%c Type=%c\n"),
1372 label.Job, dt, label.JobLevel, label.JobType);
1373 if (check_err) {
1374 errors += check_label(&label);
1375 }
1376 break;
1377 case EOS_LABEL:
1378 char ed1[30], ed2[30];
1379 unser_session_label(&label, rec);
1380 bstrftimes(dt, sizeof(dt), btime_to_utime(label.write_btime));
1381 Pmsg6(-1, _("%s Record: File:blk=%u:%u SessId=%d SessTime=%d JobId=%d\n"),
1382 type, dev->file, dev->block_num, rec->VolSessionId, rec->VolSessionTime, label.JobId);
1383 Pmsg7(-1, _(" Date=%s Level=%c Type=%c Files=%s Bytes=%s Errors=%d Status=%c\n"),
1384 dt, label.JobLevel, label.JobType,
1385 edit_uint64_with_commas(label.JobFiles, ed1),
1386 edit_uint64_with_commas(label.JobBytes, ed2),
1387 label.JobErrors, (char)label.JobStatus);
1388 if (check_err) {
1389 errors += check_label(&label);
1390 }
1391 break;
1392 case EOM_LABEL:
1393 case PRE_LABEL:
1394 case VOL_LABEL:
1395 default:
1396 Pmsg7(-1, _("%s Record: File:blk=%u:%u SessId=%d SessTime=%d JobId=%d DataLen=%d\n"),
1397 type, dev->file, dev->block_num, rec->VolSessionId, rec->VolSessionTime,
1398 rec->Stream, rec->data_len);
1399 break;
1400 case EOT_LABEL:
1401 break;
1402 }
1403 }
1404 debug_level = dbl;
1405 return errors;
1406 }
1407