2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2014 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from many
7 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 Bacula® is a registered trademark of Kern Sibbald.
18 * label.c Bacula routines to handle labels
24 #include "bacula.h" /* pull in global headers */
25 #include "stored.h" /* pull in Storage Deamon headers */
27 /* Forward referenced functions */
28 static void create_volume_label_record(DCR *dcr, DEVICE *dev, DEV_RECORD *rec, bool alt);
29 static bool sub_write_volume_label_to_block(DCR *dcr);
30 static bool sub_write_new_volume_label_to_dev(DCR *dcr, const char *VolName,
31 const char *PoolName, bool relabel, bool dvdnow);
34 * Read the volume label
36 * If dcr->VolumeName == NULL, we accept any Bacula Volume
37 * If dcr->VolumeName[0] == 0, we accept any Bacula Volume
38 * otherwise dcr->VolumeName must match the Volume.
40 * If VolName given, ensure that it matches
42 * Returns VOL_ code as defined in record.h
44 * VOL_OK good label found
45 * VOL_NO_LABEL volume not labeled
46 * VOL_IO_ERROR I/O error reading tape
47 * VOL_NAME_ERROR label has wrong name
48 * VOL_CREATE_ERROR Error creating label
49 * VOL_VERSION_ERROR label has wrong version
50 * VOL_LABEL_ERROR bad label type
51 * VOL_NO_MEDIA no media in drive
53 * The dcr block is emptied on return, and the Volume is
57 int read_dev_volume_label(DCR *dcr)
60 DEVICE * volatile dev = dcr->dev;
61 char *VolName = dcr->VolumeName;
64 DEV_BLOCK *block = dcr->block;
67 bool have_ansi_label = false;
70 Dmsg4(100, "Enter read_volume_label res=%d device=%s vol=%s dev_Vol=%s\n",
71 dev->num_reserved(), dev->print_name(), VolName,
72 dev->VolHdr.VolumeName[0]?dev->VolHdr.VolumeName:"*NULL*");
74 if (!dev->is_open()) {
75 if (!dev->open(dcr, OPEN_READ_ONLY)) {
84 dev->label_type = B_BACULA_LABEL;
86 if (!dev->rewind(dcr)) {
87 Mmsg(jcr->errmsg, _("Couldn't rewind %s device %s: ERR=%s\n"),
88 dev->print_type(), dev->print_name(), dev->print_errmsg());
89 Dmsg1(130, "return VOL_NO_MEDIA: %s", jcr->errmsg);
93 bstrncpy(dev->VolHdr.Id, "**error**", sizeof(dev->VolHdr.Id));
95 /* Read ANSI/IBM label if so requested */
96 want_ansi_label = dcr->VolCatInfo.LabelType != B_BACULA_LABEL ||
97 dcr->device->label_type != B_BACULA_LABEL;
98 if (want_ansi_label || dev->has_cap(CAP_CHECKLABELS)) {
99 stat = read_ansi_ibm_label(dcr);
100 /* If we want a label and didn't find it, return error */
101 if (want_ansi_label && stat != VOL_OK) {
104 if (stat == VOL_NAME_ERROR || stat == VOL_LABEL_ERROR) {
105 Mmsg(jcr->errmsg, _("Wrong Volume mounted on %s device %s: Wanted %s have %s\n"),
106 dev->print_type(), dev->print_name(), VolName, dev->VolHdr.VolumeName);
107 if (!dev->poll && jcr->label_errors++ > 100) {
108 Jmsg(jcr, M_FATAL, 0, _("Too many tries: %s"), jcr->errmsg);
112 if (stat != VOL_OK) { /* Not an ANSI/IBM label, so re-read */
115 have_ansi_label = true;
119 /* Read the Bacula Volume label block */
120 record = new_record();
123 Dmsg0(130, "Big if statement in read_volume_label\n");
124 if (!dcr->read_block_from_dev(NO_BLOCK_NUMBER_CHECK)) {
125 Mmsg(jcr->errmsg, _("Requested Volume \"%s\" on %s device %s is not a Bacula "
126 "labeled Volume, because: ERR=%s"), NPRT(VolName),
127 dev->print_type(), dev->print_name(), dev->print_errmsg());
128 Dmsg1(130, "%s", jcr->errmsg);
129 } else if (!read_record_from_block(dcr, record)) {
130 Mmsg(jcr->errmsg, _("Could not read Volume label from block.\n"));
131 Dmsg1(130, "%s", jcr->errmsg);
132 } else if (!unser_volume_label(dev, record)) {
133 Mmsg(jcr->errmsg, _("Could not unserialize Volume label: ERR=%s\n"),
134 dev->print_errmsg());
135 Dmsg1(130, "%s", jcr->errmsg);
136 } else if (strcmp(dev->VolHdr.Id, BaculaId) != 0 &&
137 strcmp(dev->VolHdr.Id, OldBaculaId) != 0) {
138 Mmsg(jcr->errmsg, _("Volume Header Id bad: %s\n"), dev->VolHdr.Id);
139 Dmsg1(130, "%s", jcr->errmsg);
143 free_record(record); /* finished reading Volume record */
145 if (!dev->is_volume_to_unload()) {
150 if (jcr->ignore_label_errors) {
151 dev->set_labeled(); /* set has Bacula label */
152 Jmsg(jcr, M_ERROR, 0, "%s", jcr->errmsg);
157 Dmsg0(100, "No volume label - bailing out\n");
162 /* At this point, we have read the first Bacula block, and
163 * then read the Bacula Volume label. Now we need to
164 * make sure we have the right Volume.
168 if (dev->VolHdr.VerNum != BaculaTapeVersion &&
169 dev->VolHdr.VerNum != OldCompatibleBaculaTapeVersion1 &&
170 dev->VolHdr.VerNum != OldCompatibleBaculaTapeVersion2) {
171 Mmsg(jcr->errmsg, _("Volume on %s device %s has wrong Bacula version. Wanted %d got %d\n"),
172 dev->print_type(), dev->print_name(), BaculaTapeVersion, dev->VolHdr.VerNum);
173 Dmsg1(130, "VOL_VERSION_ERROR: %s", jcr->errmsg);
174 stat = VOL_VERSION_ERROR;
178 /* We are looking for either an unused Bacula tape (PRE_LABEL) or
179 * a Bacula volume label (VOL_LABEL)
181 if (dev->VolHdr.LabelType != PRE_LABEL && dev->VolHdr.LabelType != VOL_LABEL) {
182 Mmsg(jcr->errmsg, _("Volume on %s device %s has bad Bacula label type: %x\n"),
183 dev->print_type(), dev->print_name(), dev->VolHdr.LabelType);
184 Dmsg1(130, "%s", jcr->errmsg);
185 if (!dev->poll && jcr->label_errors++ > 100) {
186 Jmsg(jcr, M_FATAL, 0, _("Too many tries: %s"), jcr->errmsg);
188 Dmsg0(150, "return VOL_LABEL_ERROR\n");
189 stat = VOL_LABEL_ERROR;
193 dev->set_labeled(); /* set has Bacula label */
195 /* Compare Volume Names */
196 Dmsg2(130, "Compare Vol names: VolName=%s hdr=%s\n", VolName?VolName:"*", dev->VolHdr.VolumeName);
197 if (VolName && *VolName && *VolName != '*' && strcmp(dev->VolHdr.VolumeName, VolName) != 0) {
198 Mmsg(jcr->errmsg, _("Wrong Volume mounted on %s device %s: Wanted %s have %s\n"),
199 dev->print_type(), dev->print_name(), VolName, dev->VolHdr.VolumeName);
200 Dmsg1(130, "%s", jcr->errmsg);
202 * Cancel Job if too many label errors
203 * => we are in a loop
205 if (!dev->poll && jcr->label_errors++ > 100) {
206 Jmsg(jcr, M_FATAL, 0, "Too many tries: %s", jcr->errmsg);
208 Dmsg0(150, "return VOL_NAME_ERROR\n");
209 stat = VOL_NAME_ERROR;
213 if (chk_dbglvl(100)) {
214 dump_volume_label(dev);
216 Dmsg0(130, "Leave read_volume_label() VOL_OK\n");
217 /* If we are a streaming device, we only get one chance to read */
218 if (!dev->has_cap(CAP_STREAM)) {
220 if (have_ansi_label) {
221 stat = read_ansi_ibm_label(dcr);
222 /* If we want a label and didn't find it, return error */
223 if (stat != VOL_OK) {
229 Dmsg1(100, "Call reserve_volume=%s\n", dev->VolHdr.VolumeName);
230 if (reserve_volume(dcr, dev->VolHdr.VolumeName) == NULL) {
231 if (!jcr->errmsg[0]) {
232 Mmsg3(jcr->errmsg, _("Could not reserve volume %s on %s device %s\n"),
233 dev->VolHdr.VolumeName, dev->print_type(), dev->print_name());
235 Dmsg2(150, "Could not reserve volume %s on %s\n", dev->VolHdr.VolumeName, dev->print_name());
236 stat = VOL_NAME_ERROR;
248 Dmsg1(150, "return %d\n", stat);
255 * Create and put a volume label into the block
257 * Returns: false on failure
261 static bool write_volume_label_to_block(DCR *dcr)
266 Dmsg0(130, "write Label in write_volume_label_to_block()\n");
268 Dmsg0(100, "Call sub_write_vol_label\n");
269 ok = sub_write_volume_label_to_block(dcr);
279 static bool sub_write_volume_label_to_block(DCR *dcr)
290 memset(&rec, 0, sizeof(rec));
291 rec.data = get_memory(SER_LENGTH_Volume_Label);
292 memset(rec.data, 0, SER_LENGTH_Volume_Label);
293 empty_block(block); /* Volume label always at beginning */
295 create_volume_label_record(dcr, dcr->dev, &rec, false);
297 block->BlockNumber = 0;
298 Dmsg0(100, "write_record_to_block\n");
299 if (!write_record_to_block(dcr, &rec)) {
300 free_pool_memory(rec.data);
301 Jmsg2(jcr, M_FATAL, 0, _("Cannot write Volume label to block for %s device %s\n"),
302 dev->print_type(), dev->print_name());
306 Dmsg3(100, "Wrote fd=%d label of %d bytes to block. Vol=%s\n",
307 dev->fd(), rec.data_len, dcr->VolumeName);
309 free_pool_memory(rec.data);
317 * Write a Volume Label
318 * !!! Note, this is ONLY used for writing
319 * a fresh volume label. Any data
320 * after the label will be destroyed,
321 * in fact, we write the label 5 times !!!!
323 * This routine should be used only when labeling a blank tape or
324 * when recylcing a volume.
327 bool write_new_volume_label_to_dev(DCR *dcr, const char *VolName,
328 const char *PoolName, bool relabel, bool dvdnow)
335 Dmsg0(150, "write_volume_label()\n");
337 Pmsg0(0, "=== ERROR: write_new_volume_label_to_dev called with NULL VolName\n");
342 volume_unused(dcr); /* mark current volume unused */
343 /* Truncate device */
344 if (!dev->truncate(dcr)) {
347 if (!dev->is_tape()) {
348 dev->close_part(dcr); /* make sure DVD/file closed for rename */
352 /* Set the new filename for open, ... */
353 dev->setVolCatName(VolName);
354 dcr->setVolCatName(VolName);
355 dev->clearVolCatBytes();
357 Dmsg1(100, "New VolName=%s\n", VolName);
358 if (!dev->open(dcr, OPEN_READ_WRITE)) {
359 /* If device is not tape, attempt to create it */
360 if (dev->is_tape() || !dev->open(dcr, CREATE_READ_WRITE)) {
361 Jmsg4(dcr->jcr, M_WARNING, 0, _("Open %s device %s Volume \"%s\" failed: ERR=%s\n"),
362 dev->print_type(), dev->print_name(), dcr->VolumeName, dev->bstrerror());
366 Dmsg1(150, "Label type=%d\n", dev->label_type);
368 if (!sub_write_new_volume_label_to_dev(dcr, VolName, PoolName, relabel, dvdnow)) {
373 write_ansi_ibm_labels(dcr, ANSI_EOF_LABEL, dev->VolHdr.VolumeName);
376 if (chk_dbglvl(100)) {
377 dump_volume_label(dev);
379 Dmsg0(50, "Call reserve_volume\n");
380 /**** ***FIXME*** if dev changes, dcr must be updated */
381 if (reserve_volume(dcr, VolName) == NULL) {
382 if (!dcr->jcr->errmsg[0]) {
383 Mmsg3(dcr->jcr->errmsg, _("Could not reserve volume %s on %s device %s\n"),
384 dev->VolHdr.VolumeName, dev->print_type(), dev->print_name());
386 Dmsg1(50, "%s", dcr->jcr->errmsg);
389 dev = dcr->dev; /* may have changed in reserve_volume */
390 dev->clear_append(); /* remove append since this is PRE_LABEL */
396 dcr->dev->clear_append(); /* remove append since this is PRE_LABEL */
401 static bool sub_write_new_volume_label_to_dev(DCR *dcr, const char *VolName,
402 const char *PoolName, bool relabel, bool dvdnow)
412 if (!dev->rewind(dcr)) {
413 Dmsg2(130, "Bad status on %s from rewind: ERR=%s\n", dev->print_name(), dev->print_errmsg());
417 /* Temporarily mark in append state to enable writing */
420 /* Create PRE_LABEL or VOL_LABEL if DVD */
421 create_volume_header(dev, VolName, PoolName, dvdnow);
424 * If we have already detected an ANSI label, re-read it
425 * to skip past it. Otherwise, we write a new one if
428 if (dev->label_type != B_BACULA_LABEL) {
429 if (read_ansi_ibm_label(dcr) != VOL_OK) {
433 } else if (!write_ansi_ibm_labels(dcr, ANSI_VOL_LABEL, VolName)) {
437 create_volume_label_record(dcr, dev, dcr->rec, false);
438 dcr->rec->Stream = 0;
439 dcr->rec->maskedStream = 0;
441 Dmsg1(100, "write_record_to_block FI=%d\n", dcr->rec->FileIndex);
443 if (!write_record_to_block(dcr, dcr->rec)) {
444 Dmsg2(40, "Bad Label write on %s: ERR=%s\n", dev->print_name(), dev->print_errmsg());
447 Dmsg2(100, "Wrote label=%d bytes block: %s\n", dcr->rec->data_len, dev->print_name());
449 Dmsg2(100, "New label VolCatBytes=%lld VolCatStatus=%s\n",
450 dev->VolCatInfo.VolCatBytes, dev->VolCatInfo.VolCatStatus);
452 Dmsg3(130, "Call write_block_to_dev() fd=%d block=%p Addr=%lld\n",
453 dcr->dev->fd(), dcr->block, block->dev->lseek(dcr, 0, SEEK_CUR));
454 Dmsg0(100, "write_record_to_dev\n");
455 /* Write block to device */
456 if (!dcr->write_block_to_dev()) {
457 Dmsg2(40, "Bad Label write on %s: ERR=%s\n", dev->print_name(), dev->print_errmsg());
460 Dmsg2(100, "New label VolCatBytes=%lld VolCatStatus=%s\n",
461 dev->VolCatInfo.VolCatBytes, dev->VolCatInfo.VolCatStatus);
471 * Write a volume label. This is ONLY called if we have a valid Bacula
472 * label of type PRE_LABEL or we are recyling an existing Volume.
474 * By calling write_volume_label_to_block
476 * Returns: true if OK
477 * false if unable to write it
479 bool DCR::rewrite_volume_label(bool recycle)
484 ASSERT(dcr->VolumeName[0]);
485 if (!dev->open(dcr, OPEN_READ_WRITE)) {
486 Jmsg4(jcr, M_WARNING, 0, _("Open %s device %s Volume \"%s\" failed: ERR=%s\n"),
487 dev->print_type(), dev->print_name(), dcr->VolumeName, dev->bstrerror());
491 Dmsg2(190, "set append found freshly labeled volume. fd=%d dev=%x\n", dev->fd(), dev);
492 dev->VolHdr.LabelType = VOL_LABEL; /* set Volume label */
494 Dmsg0(100, "Rewrite_volume_label set volcatbytes=0\n");
495 dev->clearVolCatBytes();
496 dev->setVolCatStatus("Append"); /* set append status */
498 if (!dev->has_cap(CAP_STREAM)) {
499 if (!dev->rewind(dcr)) {
500 Jmsg3(jcr, M_FATAL, 0, _("Rewind error on %s device %s: ERR=%s\n"),
501 dev->print_type(), dev->print_name(), dev->print_errmsg());
506 Dmsg1(150, "Doing recycle. Vol=%s\n", dcr->VolumeName);
507 if (!dev->truncate(dcr)) {
508 Jmsg3(jcr, M_FATAL, 0, _("Truncate error on %s device %s: ERR=%s\n"),
509 dev->print_type(), dev->print_name(), dev->print_errmsg());
513 if (!dev->open(dcr, OPEN_READ_WRITE)) {
514 Jmsg3(jcr, M_FATAL, 0,
515 _("Failed to re-open DVD after truncate on %s device %s: ERR=%s\n"),
516 dev->print_type(), dev->print_name(), dev->print_errmsg());
523 if (!write_volume_label_to_block(dcr)) {
524 Dmsg0(150, "Error from write volume label.\n");
528 Dmsg1(100, "wrote vol label to block. Vol=%s\n", dcr->VolumeName);
530 ASSERT(dcr->VolumeName[0]);
531 dev->setVolCatInfo(false);
534 * If we are not dealing with a streaming device,
535 * write the block now to ensure we have write permission.
536 * It is better to find out now rather than later.
537 * We do not write the block now if this is an ANSI label. This
538 * avoids re-writing the ANSI label, which we do not want to do.
540 if (!dev->has_cap(CAP_STREAM)) {
542 * If we have already detected an ANSI label, re-read it
543 * to skip past it. Otherwise, we write a new one if
546 if (dev->label_type != B_BACULA_LABEL) {
547 if (read_ansi_ibm_label(dcr) != VOL_OK) {
552 } else if (!write_ansi_ibm_labels(dcr, ANSI_VOL_LABEL, dev->VolHdr.VolumeName)) {
557 /* Attempt write to check write permission */
558 Dmsg1(200, "Attempt to write to device fd=%d.\n", dev->fd());
559 if (!dcr->write_block_to_dev()) {
560 Jmsg3(jcr, M_ERROR, 0, _("Unable to write %s device %s: ERR=%s\n"),
561 dev->print_type(), dev->print_name(), dev->print_errmsg());
562 Dmsg0(200, "===ERROR write block to dev\n");
568 /* Set or reset Volume statistics */
569 dev->VolCatInfo.VolCatJobs = 0;
570 dev->VolCatInfo.VolCatFiles = 0;
571 dev->VolCatInfo.VolCatErrors = 0;
572 dev->VolCatInfo.VolCatBlocks = 0;
573 dev->VolCatInfo.VolCatRBytes = 0;
575 dev->VolCatInfo.VolCatMounts++;
576 dev->VolCatInfo.VolCatRecycles++;
577 dir_create_jobmedia_record(dcr, true);
579 dev->VolCatInfo.VolCatMounts = 1;
580 dev->VolCatInfo.VolCatRecycles = 0;
581 dev->VolCatInfo.VolCatWrites = 1;
582 dev->VolCatInfo.VolCatReads = 1;
584 Dmsg1(100, "dir_update_vol_info. Set Append vol=%s\n", dcr->VolumeName);
585 dev->VolCatInfo.VolFirstWritten = time(NULL);
586 dev->setVolCatStatus("Append");
587 ASSERT(dcr->VolumeName[0]);
588 dev->setVolCatName(dcr->VolumeName);
589 if (!dir_update_volume_info(dcr, true, true)) { /* indicate doing relabel */
594 Jmsg(jcr, M_INFO, 0, _("Recycled volume \"%s\" on %s device %s, all previous data lost.\n"),
595 dcr->VolumeName, dev->print_type(), dev->print_name());
597 Jmsg(jcr, M_INFO, 0, _("Wrote label to prelabeled Volume \"%s\" on %s device %s\n"),
598 dcr->VolumeName, dev->print_type(), dev->print_name());
601 * End writing real Volume label (from pre-labeled tape), or recycling
604 Dmsg1(100, "OK from rewrite vol label. Vol=%s\n", dcr->VolumeName);
611 * create_volume_label_record
612 * Serialize label (from dev->VolHdr structure) into device record.
613 * Assumes that the dev->VolHdr structure is properly
616 static void create_volume_label_record(DCR *dcr, DEVICE *dev,
617 DEV_RECORD *rec, bool alt)
624 /* Serialize the label into the device record. */
627 rec->data = check_pool_memory_size(rec->data, SER_LENGTH_Volume_Label);
628 memset(rec->data, 0, SER_LENGTH_Volume_Label);
629 ser_begin(rec->data, SER_LENGTH_Volume_Label);
630 ser_string(dev->VolHdr.Id);
632 ser_uint32(dev->VolHdr.VerNum);
634 if (dev->VolHdr.VerNum >= 11) {
635 ser_btime(dev->VolHdr.label_btime);
636 dev->VolHdr.write_btime = get_current_btime();
637 ser_btime(dev->VolHdr.write_btime);
638 dev->VolHdr.write_date = 0;
639 dev->VolHdr.write_time = 0;
641 /* OLD WAY DEPRECATED */
642 ser_float64(dev->VolHdr.label_date);
643 ser_float64(dev->VolHdr.label_time);
644 get_current_time(&dt);
645 dev->VolHdr.write_date = dt.julian_day_number;
646 dev->VolHdr.write_time = dt.julian_day_fraction;
648 ser_float64(dev->VolHdr.write_date); /* 0 if VerNum >= 11 */
649 ser_float64(dev->VolHdr.write_time); /* 0 if VerNum >= 11 */
651 ser_string(dev->VolHdr.VolumeName);
652 ser_string(dev->VolHdr.PrevVolumeName);
653 ser_string(dev->VolHdr.PoolName);
654 ser_string(dev->VolHdr.PoolType);
655 ser_string(dev->VolHdr.MediaType);
657 ser_string(dev->VolHdr.HostName);
658 ser_string(dev->VolHdr.LabelProg);
659 ser_string(dev->VolHdr.ProgVersion);
660 ser_string(dev->VolHdr.ProgDate);
662 ser_end(rec->data, SER_LENGTH_Volume_Label);
663 bstrncpy(dcr->VolumeName, dev->VolHdr.VolumeName, sizeof(dcr->VolumeName));
664 ASSERT(dcr->VolumeName[0]);
665 rec->data_len = ser_length(rec->data);
666 rec->FileIndex = dev->VolHdr.LabelType;
667 Dmsg1(100, "LabelType=%d\n", dev->VolHdr.LabelType);
668 rec->VolSessionId = jcr->VolSessionId;
669 rec->VolSessionTime = jcr->VolSessionTime;
670 rec->Stream = jcr->NumWriteVolumes;
671 rec->maskedStream = jcr->NumWriteVolumes;
672 Dmsg2(100, "Created Vol label rec: FI=%s len=%d\n", FI_to_ascii(buf, rec->FileIndex),
674 Dmsg2(100, "reclen=%d recdata=%s\n", rec->data_len, rec->data);
680 * Create a volume header in memory
682 void create_volume_header(DEVICE *dev, const char *VolName,
683 const char *PoolName, bool dvdnow)
685 DEVRES *device = (DEVRES *)dev->device;
687 Dmsg0(130, "Start create_volume_header()\n");
691 bstrncpy(dev->VolHdr.Id, BaculaId, sizeof(dev->VolHdr.Id));
692 dev->VolHdr.VerNum = BaculaTapeVersion;
693 if (dev->is_dvd() && dvdnow) {
694 /* We do not want to re-label a DVD so write VOL_LABEL now */
695 dev->VolHdr.LabelType = VOL_LABEL;
697 dev->VolHdr.LabelType = PRE_LABEL; /* Mark tape as unused */
699 bstrncpy(dev->VolHdr.VolumeName, VolName, sizeof(dev->VolHdr.VolumeName));
700 bstrncpy(dev->VolHdr.PoolName, PoolName, sizeof(dev->VolHdr.PoolName));
701 bstrncpy(dev->VolHdr.MediaType, device->media_type, sizeof(dev->VolHdr.MediaType));
703 bstrncpy(dev->VolHdr.PoolType, "Backup", sizeof(dev->VolHdr.PoolType));
705 dev->VolHdr.label_btime = get_current_btime();
706 dev->VolHdr.label_date = 0;
707 dev->VolHdr.label_time = 0;
709 if (gethostname(dev->VolHdr.HostName, sizeof(dev->VolHdr.HostName)) != 0) {
710 dev->VolHdr.HostName[0] = 0;
712 bstrncpy(dev->VolHdr.LabelProg, my_name, sizeof(dev->VolHdr.LabelProg));
713 sprintf(dev->VolHdr.ProgVersion, "Ver. %s %s ", VERSION, BDATE);
714 sprintf(dev->VolHdr.ProgDate, "Build %s %s ", __DATE__, __TIME__);
715 dev->set_labeled(); /* set has Bacula label */
716 if (chk_dbglvl(100)) {
717 dump_volume_label(dev);
722 * Create session label
723 * The pool memory must be released by the calling program
725 void create_session_label(DCR *dcr, DEV_RECORD *rec, int label)
731 rec->VolSessionId = jcr->VolSessionId;
732 rec->VolSessionTime = jcr->VolSessionTime;
733 rec->Stream = jcr->JobId;
734 rec->maskedStream = jcr->JobId;
736 rec->data = check_pool_memory_size(rec->data, SER_LENGTH_Session_Label);
737 ser_begin(rec->data, SER_LENGTH_Session_Label);
738 ser_string(BaculaId);
739 ser_uint32(BaculaTapeVersion);
741 ser_uint32(jcr->JobId);
743 /* Changed in VerNum 11 */
744 ser_btime(get_current_btime());
747 ser_string(dcr->pool_name);
748 ser_string(dcr->pool_type);
749 ser_string(jcr->job_name); /* base Job name */
750 ser_string(jcr->client_name);
752 /* Added in VerNum 10 */
753 ser_string(jcr->Job); /* Unique name of this Job */
754 ser_string(jcr->fileset_name);
755 ser_uint32(jcr->getJobType());
756 ser_uint32(jcr->getJobLevel());
757 /* Added in VerNum 11 */
758 ser_string(jcr->fileset_md5);
760 if (label == EOS_LABEL) {
761 ser_uint32(jcr->JobFiles);
762 ser_uint64(jcr->JobBytes);
763 ser_uint32(dcr->StartBlock);
764 ser_uint32(dcr->EndBlock);
765 ser_uint32(dcr->StartFile);
766 ser_uint32(dcr->EndFile);
767 ser_uint32(jcr->JobErrors);
769 /* Added in VerNum 11 */
770 ser_uint32(jcr->JobStatus);
772 ser_end(rec->data, SER_LENGTH_Session_Label);
773 rec->data_len = ser_length(rec->data);
777 /* Write session label
778 * Returns: false on failure
781 bool write_session_label(DCR *dcr, int label)
784 DEVICE *dev = dcr->dev;
786 DEV_BLOCK *block = dcr->block;
787 char buf1[100], buf2[100];
791 Dmsg1(130, "session_label record=%x\n", rec);
794 set_start_vol_position(dcr);
797 if (dev->is_tape()) {
798 dcr->EndBlock = dev->EndBlock;
799 dcr->EndFile = dev->EndFile;
801 dcr->EndBlock = (uint32_t)dev->file_addr;
802 dcr->EndFile = (uint32_t)(dev->file_addr >> 32);
806 Jmsg1(jcr, M_ABORT, 0, _("Bad Volume session label request=%d\n"), label);
809 create_session_label(dcr, rec, label);
810 rec->FileIndex = label;
813 * We guarantee that the session record can totally fit
814 * into a block. If not, write the block, and put it in
815 * the next block. Having the sesssion record totally in
816 * one block makes reading them much easier (no need to
817 * read the next block).
819 if (!can_write_record_to_block(block, rec)) {
820 Dmsg0(150, "Cannot write session label to block.\n");
821 if (!dcr->write_block_to_device()) {
822 Dmsg0(130, "Got session label write_block_to_dev error.\n");
829 * We use write_record() because it handles the case that
830 * the maximum user size has been reached.
832 if (!dcr->write_record(rec)) {
833 Dmsg0(150, "Bad return from write_record\n");
839 Dmsg6(150, "Write sesson_label record JobId=%d FI=%s SessId=%d Strm=%s len=%d "
840 "remainder=%d\n", jcr->JobId,
841 FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId,
842 stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len,
846 Dmsg2(150, "Leave write_session_label Block=%ud File=%ud\n",
847 dev->get_block_num(), dev->get_file());
852 /* unser_volume_label
854 * Unserialize the Bacula Volume label into the device Volume_Label
857 * Assumes that the record is already read.
859 * Returns: false on error
863 bool unser_volume_label(DEVICE *dev, DEV_RECORD *rec)
866 char buf1[100], buf2[100];
869 if (rec->FileIndex != VOL_LABEL && rec->FileIndex != PRE_LABEL) {
870 Mmsg3(dev->errmsg, _("Expecting Volume Label, got FI=%s Stream=%s len=%d\n"),
871 FI_to_ascii(buf1, rec->FileIndex),
872 stream_to_ascii(buf2, rec->Stream, rec->FileIndex),
880 dev->VolHdr.LabelType = rec->FileIndex;
881 dev->VolHdr.LabelSize = rec->data_len;
884 /* Unserialize the record into the Volume Header */
885 Dmsg2(100, "reclen=%d recdata=%s\n", rec->data_len, rec->data);
886 rec->data = check_pool_memory_size(rec->data, SER_LENGTH_Volume_Label);
887 Dmsg2(100, "reclen=%d recdata=%s\n", rec->data_len, rec->data);
888 ser_begin(rec->data, SER_LENGTH_Volume_Label);
889 unser_string(dev->VolHdr.Id);
890 unser_uint32(dev->VolHdr.VerNum);
892 if (dev->VolHdr.VerNum >= 11) {
893 unser_btime(dev->VolHdr.label_btime);
894 unser_btime(dev->VolHdr.write_btime);
895 } else { /* old way */
896 unser_float64(dev->VolHdr.label_date);
897 unser_float64(dev->VolHdr.label_time);
899 unser_float64(dev->VolHdr.write_date); /* Unused with VerNum >= 11 */
900 unser_float64(dev->VolHdr.write_time); /* Unused with VerNum >= 11 */
902 unser_string(dev->VolHdr.VolumeName);
903 unser_string(dev->VolHdr.PrevVolumeName);
904 unser_string(dev->VolHdr.PoolName);
905 unser_string(dev->VolHdr.PoolType);
906 unser_string(dev->VolHdr.MediaType);
908 unser_string(dev->VolHdr.HostName);
909 unser_string(dev->VolHdr.LabelProg);
910 unser_string(dev->VolHdr.ProgVersion);
911 unser_string(dev->VolHdr.ProgDate);
913 ser_end(rec->data, SER_LENGTH_Volume_Label);
914 Dmsg0(190, "unser_vol_label\n");
915 if (chk_dbglvl(100)) {
916 dump_volume_label(dev);
923 bool unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec)
928 rec->data = check_pool_memory_size(rec->data, SER_LENGTH_Session_Label);
929 unser_begin(rec->data, SER_LENGTH_Session_Label);
930 unser_string(label->Id);
931 unser_uint32(label->VerNum);
932 unser_uint32(label->JobId);
933 if (label->VerNum >= 11) {
934 unser_btime(label->write_btime);
936 unser_float64(label->write_date);
938 unser_float64(label->write_time);
939 unser_string(label->PoolName);
940 unser_string(label->PoolType);
941 unser_string(label->JobName);
942 unser_string(label->ClientName);
943 if (label->VerNum >= 10) {
944 unser_string(label->Job); /* Unique name of this Job */
945 unser_string(label->FileSetName);
946 unser_uint32(label->JobType);
947 unser_uint32(label->JobLevel);
949 if (label->VerNum >= 11) {
950 unser_string(label->FileSetMD5);
952 label->FileSetMD5[0] = 0;
954 if (rec->FileIndex == EOS_LABEL) {
955 unser_uint32(label->JobFiles);
956 unser_uint64(label->JobBytes);
957 unser_uint32(label->StartBlock);
958 unser_uint32(label->EndBlock);
959 unser_uint32(label->StartFile);
960 unser_uint32(label->EndFile);
961 unser_uint32(label->JobErrors);
962 if (label->VerNum >= 11) {
963 unser_uint32(label->JobStatus);
965 label->JobStatus = JS_Terminated; /* kludge */
972 void dump_volume_label(DEVICE *dev)
974 int64_t dbl = debug_level;
976 const char *LabelType;
983 switch (dev->VolHdr.LabelType) {
985 LabelType = "PRE_LABEL";
988 LabelType = "VOL_LABEL";
991 LabelType = "EOM_LABEL";
994 LabelType = "SOS_LABEL";
997 LabelType = "EOS_LABEL";
1003 sprintf(buf, _("Unknown %d"), dev->VolHdr.LabelType);
1007 Pmsg11(-1, _("\nVolume Label:\n"
1011 "PrevVolName : %s\n"
1020 dev->VolHdr.Id, dev->VolHdr.VerNum,
1021 dev->VolHdr.VolumeName, dev->VolHdr.PrevVolumeName,
1022 File, LabelType, dev->VolHdr.LabelSize,
1023 dev->VolHdr.PoolName, dev->VolHdr.MediaType,
1024 dev->VolHdr.PoolType, dev->VolHdr.HostName);
1026 if (dev->VolHdr.VerNum >= 11) {
1028 bstrftime(dt, sizeof(dt), btime_to_utime(dev->VolHdr.label_btime));
1029 Pmsg1(-1, _("Date label written: %s\n"), dt);
1031 dt.julian_day_number = dev->VolHdr.label_date;
1032 dt.julian_day_fraction = dev->VolHdr.label_time;
1033 tm_decode(&dt, &tm);
1035 _("Date label written: %04d-%02d-%02d at %02d:%02d\n"),
1036 tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min);
1044 static void dump_session_label(DEV_RECORD *rec, const char *type)
1047 struct date_time dt;
1049 SESSION_LABEL label;
1050 char ec1[30], ec2[30], ec3[30], ec4[30], ec5[30], ec6[30], ec7[30];
1052 unser_session_label(&label, rec);
1055 Pmsg7(-1, _("\n%s Record:\n"
1062 ""), type, label.JobId, label.VerNum,
1063 label.PoolName, label.PoolType,
1064 label.JobName, label.ClientName);
1066 if (label.VerNum >= 10) {
1068 "Job (unique name) : %s\n"
1072 ""), label.Job, label.FileSetName, label.JobType, label.JobLevel);
1075 if (rec->FileIndex == EOS_LABEL) {
1086 edit_uint64_with_commas(label.JobFiles, ec1),
1087 edit_uint64_with_commas(label.JobBytes, ec2),
1088 edit_uint64_with_commas(label.StartBlock, ec3),
1089 edit_uint64_with_commas(label.EndBlock, ec4),
1090 edit_uint64_with_commas(label.StartFile, ec5),
1091 edit_uint64_with_commas(label.EndFile, ec6),
1092 edit_uint64_with_commas(label.JobErrors, ec7),
1095 if (label.VerNum >= 11) {
1097 bstrftime(dt, sizeof(dt), btime_to_utime(label.write_btime));
1098 Pmsg1(-1, _("Date written : %s\n"), dt);
1100 dt.julian_day_number = label.write_date;
1101 dt.julian_day_fraction = label.write_time;
1102 tm_decode(&dt, &tm);
1103 Pmsg5(-1, _("Date written : %04d-%02d-%02d at %02d:%02d\n"),
1104 tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min);
1110 void dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose)
1115 if (rec->FileIndex == 0 && rec->VolSessionId == 0 && rec->VolSessionTime == 0) {
1120 switch (rec->FileIndex) {
1122 type = _("Fresh Volume");
1128 type = _("Begin Job Session");
1131 type = _("End Job Session");
1134 type = _("End of Media");
1137 type = _("End of Tape");
1140 type = _("Unknown");
1144 switch (rec->FileIndex) {
1147 unser_volume_label(dev, rec);
1148 dump_volume_label(dev);
1151 dump_session_label(rec, type);
1154 dump_session_label(rec, type);
1157 Pmsg7(-1, _("%s Record: File:blk=%u:%u SessId=%d SessTime=%d JobId=%d DataLen=%d\n"),
1158 type, dev->file, dev->block_num, rec->VolSessionId,
1159 rec->VolSessionTime, rec->Stream, rec->data_len);
1162 Pmsg0(-1, _("Bacula \"End of Tape\" label found.\n"));
1165 Pmsg7(-1, _("%s Record: File:blk=%u:%u SessId=%d SessTime=%d JobId=%d DataLen=%d\n"),
1166 type, dev->file, dev->block_num, rec->VolSessionId,
1167 rec->VolSessionTime, rec->Stream, rec->data_len);
1171 SESSION_LABEL label;
1173 switch (rec->FileIndex) {
1175 unser_session_label(&label, rec);
1176 bstrftimes(dt, sizeof(dt), btime_to_utime(label.write_btime));
1177 Pmsg6(-1, _("%s Record: File:blk=%u:%u SessId=%d SessTime=%d JobId=%d\n"),
1178 type, dev->file, dev->block_num, rec->VolSessionId, rec->VolSessionTime, label.JobId);
1179 Pmsg4(-1, _(" Job=%s Date=%s Level=%c Type=%c\n"),
1180 label.Job, dt, label.JobLevel, label.JobType);
1183 char ed1[30], ed2[30];
1184 unser_session_label(&label, rec);
1185 bstrftimes(dt, sizeof(dt), btime_to_utime(label.write_btime));
1186 Pmsg6(-1, _("%s Record: File:blk=%u:%u SessId=%d SessTime=%d JobId=%d\n"),
1187 type, dev->file, dev->block_num, rec->VolSessionId, rec->VolSessionTime, label.JobId);
1188 Pmsg7(-1, _(" Date=%s Level=%c Type=%c Files=%s Bytes=%s Errors=%d Status=%c\n"),
1189 dt, label.JobLevel, label.JobType,
1190 edit_uint64_with_commas(label.JobFiles, ed1),
1191 edit_uint64_with_commas(label.JobBytes, ed2),
1192 label.JobErrors, (char)label.JobStatus);
1198 Pmsg7(-1, _("%s Record: File:blk=%u:%u SessId=%d SessTime=%d JobId=%d DataLen=%d\n"),
1199 type, dev->file, dev->block_num, rec->VolSessionId, rec->VolSessionTime,
1200 rec->Stream, rec->data_len);