]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/label.c
kes Apply dvd-handler patch from Richard Mortimer.
[bacula/bacula] / bacula / src / stored / label.c
1 /*
2  *
3  *  label.c  Bacula routines to handle labels
4  *
5  *   Kern Sibbald, MM
6  *
7  *
8  *   Version $Id$
9  */
10 /*
11    Copyright (C) 2000-2006 Kern Sibbald
12
13    This program is free software; you can redistribute it and/or
14    modify it under the terms of the GNU General Public License
15    version 2 as amended with additional clauses defined in the
16    file LICENSE in the main source directory.
17
18    This program is distributed in the hope that it will be useful,
19    but WITHOUT ANY WARRANTY; without even the implied warranty of
20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
21    the file LICENSE for additional details.
22
23  */
24
25 #include "bacula.h"                   /* pull in global headers */
26 #include "stored.h"                   /* pull in Storage Deamon headers */
27
28 /* Forward referenced functions */
29 static void create_volume_label_record(DCR *dcr, DEV_RECORD *rec);
30
31 /*
32  * Read the volume label
33  *
34  *  If dcr->VolumeName == NULL, we accept any Bacula Volume
35  *  If dcr->VolumeName[0] == 0, we accept any Bacula Volume
36  *  otherwise dcr->VolumeName must match the Volume.
37  *
38  *  If VolName given, ensure that it matches
39  *
40  *  Returns VOL_  code as defined in record.h
41  *    VOL_NOT_READ
42  *    VOL_OK                          good label found
43  *    VOL_NO_LABEL                    volume not labeled
44  *    VOL_IO_ERROR                    I/O error reading tape
45  *    VOL_NAME_ERROR                  label has wrong name
46  *    VOL_CREATE_ERROR                Error creating label
47  *    VOL_VERSION_ERROR               label has wrong version
48  *    VOL_LABEL_ERROR                 bad label type
49  *    VOL_NO_MEDIA                    no media in drive
50  *
51  *  The dcr block is emptied on return, and the Volume is
52  *    rewound.
53  */
54 int read_dev_volume_label(DCR *dcr)
55 {
56    JCR *jcr = dcr->jcr;
57    DEVICE *dev = dcr->dev;
58    char *VolName = dcr->VolumeName;
59    DEV_RECORD *record;
60    bool ok = false;
61    DEV_BLOCK *block = dcr->block;
62    int stat;
63    bool want_ansi_label;
64    bool have_ansi_label = false;
65
66    Dmsg4(100, "Enter read_volume_label res=%d device=%s vol=%s dev_Vol=%s\n",
67       dev->reserved_device, dev->print_name(), VolName, 
68       dev->VolHdr.VolumeName[0]?dev->VolHdr.VolumeName:"*NULL*");
69
70    if (!dev->is_open()) {
71       if (dev->open(dcr, OPEN_READ_ONLY) < 0) {
72          return VOL_IO_ERROR;
73       }
74    }
75    if (dev->is_labeled()) {              /* did we already read label? */
76       /* Compare Volume Names allow special wild card */
77       if (VolName && *VolName && *VolName != '*' && strcmp(dev->VolHdr.VolumeName, VolName) != 0) {
78          Mmsg(jcr->errmsg, _("Wrong Volume mounted on device %s: Wanted %s have %s\n"),
79             dev->print_name(), VolName, dev->VolHdr.VolumeName);
80          /*
81           * Cancel Job if too many label errors
82           *  => we are in a loop
83           */
84          if (!dev->poll && jcr->label_errors++ > 100) {
85             Jmsg(jcr, M_FATAL, 0, _("Too many tries: %s"), jcr->errmsg);
86          }
87          Dmsg0(150, "return VOL_NAME_ERROR\n");
88          stat = VOL_NAME_ERROR;
89          goto bail_out;
90       }
91       Dmsg0(30, "Leave read_volume_label() VOL_OK\n");
92       return VOL_OK;       /* label already read */
93    }
94
95    dev->clear_labeled();
96    dev->clear_append();
97    dev->clear_read();
98    dev->label_type = B_BACULA_LABEL;
99
100    if (!dev->rewind(dcr)) {
101       Mmsg(jcr->errmsg, _("Couldn't rewind device %s: ERR=%s\n"), 
102          dev->print_name(), dev->bstrerror());
103       Dmsg1(30, "return VOL_NO_MEDIA: %s", jcr->errmsg);
104       return VOL_NO_MEDIA;
105    }
106    bstrncpy(dev->VolHdr.Id, "**error**", sizeof(dev->VolHdr.Id));
107
108   /* Read ANSI/IBM label if so requested */
109   
110   want_ansi_label = dcr->VolCatInfo.LabelType != B_BACULA_LABEL ||
111                     dcr->device->label_type != B_BACULA_LABEL;
112   if (want_ansi_label || dev_cap(dev, CAP_CHECKLABELS)) {
113       stat = read_ansi_ibm_label(dcr);            
114       /* If we want a label and didn't find it, return error */
115       if (want_ansi_label && stat != VOL_OK) {
116          goto bail_out;
117       }
118       if (stat == VOL_NAME_ERROR || stat == VOL_LABEL_ERROR) {
119          Mmsg(jcr->errmsg, _("Wrong Volume mounted on device %s: Wanted %s have %s\n"),
120               dev->print_name(), VolName, dev->VolHdr.VolumeName);
121          if (!dev->poll && jcr->label_errors++ > 100) {
122             Jmsg(jcr, M_FATAL, 0, _("Too many tries: %s"), jcr->errmsg);
123          }
124          goto bail_out;
125       }
126       if (stat != VOL_OK) {           /* Not an ANSI/IBM label, so re-read */
127          dev->rewind(dcr);
128       } else {
129          have_ansi_label = true;
130       }
131    }
132   
133    /* Read the Bacula Volume label block */
134    record = new_record();
135    empty_block(block);
136
137    Dmsg0(90, "Big if statement in read_volume_label\n");
138    if (!read_block_from_dev(dcr, NO_BLOCK_NUMBER_CHECK)) {
139       Mmsg(jcr->errmsg, _("Requested Volume \"%s\" on %s is not a Bacula "
140            "labeled Volume, because: ERR=%s"), NPRT(VolName), 
141            dev->print_name(), dev->bstrerror());
142       Dmsg1(30, "%s", jcr->errmsg);
143    } else if (!read_record_from_block(block, record)) {
144       Mmsg(jcr->errmsg, _("Could not read Volume label from block.\n"));
145       Dmsg1(30, "%s", jcr->errmsg);
146    } else if (!unser_volume_label(dev, record)) {
147       Mmsg(jcr->errmsg, _("Could not unserialize Volume label: ERR=%s\n"),
148          dev->bstrerror());
149       Dmsg1(30, "%s", jcr->errmsg);
150    } else if (strcmp(dev->VolHdr.Id, BaculaId) != 0 &&
151               strcmp(dev->VolHdr.Id, OldBaculaId) != 0) {
152       Mmsg(jcr->errmsg, _("Volume Header Id bad: %s\n"), dev->VolHdr.Id);
153       Dmsg1(30, "%s", jcr->errmsg);
154    } else {
155       ok = true;
156    }
157    free_record(record);               /* finished reading Volume record */
158
159    if (!ok) {
160       if (forge_on || jcr->ignore_label_errors) {
161          dev->set_labeled();         /* set has Bacula label */
162          Jmsg(jcr, M_ERROR, 0, "%s", jcr->errmsg);
163          empty_block(block);
164          return VOL_OK;
165       }
166       Dmsg0(100, "No volume label - bailing out\n");
167       stat = VOL_NO_LABEL;
168       goto bail_out;
169    }
170
171    /* At this point, we have read the first Bacula block, and
172     * then read the Bacula Volume label. Now we need to
173     * make sure we have the right Volume.
174     */
175
176
177    if (dev->VolHdr.VerNum != BaculaTapeVersion &&
178        dev->VolHdr.VerNum != OldCompatibleBaculaTapeVersion1 &&
179        dev->VolHdr.VerNum != OldCompatibleBaculaTapeVersion2) {
180       Mmsg(jcr->errmsg, _("Volume on %s has wrong Bacula version. Wanted %d got %d\n"),
181          dev->print_name(), BaculaTapeVersion, dev->VolHdr.VerNum);
182       Dmsg1(30, "VOL_VERSION_ERROR: %s", jcr->errmsg);
183       stat = VOL_VERSION_ERROR;
184       goto bail_out;
185    }
186
187    /* We are looking for either an unused Bacula tape (PRE_LABEL) or
188     * a Bacula volume label (VOL_LABEL)
189     */
190    if (dev->VolHdr.LabelType != PRE_LABEL && dev->VolHdr.LabelType != VOL_LABEL) {
191       Mmsg(jcr->errmsg, _("Volume on %s has bad Bacula label type: %x\n"),
192           dev->print_name(), dev->VolHdr.LabelType);
193       Dmsg1(30, "%s", jcr->errmsg);
194       if (!dev->poll && jcr->label_errors++ > 100) {
195          Jmsg(jcr, M_FATAL, 0, _("Too many tries: %s"), jcr->errmsg);
196       }
197       Dmsg0(150, "return VOL_LABEL_ERROR\n");
198       stat = VOL_LABEL_ERROR;
199       goto bail_out;
200    }
201
202    dev->set_labeled();               /* set has Bacula label */
203    new_volume(dcr, dev->VolHdr.VolumeName);
204
205    /* Compare Volume Names */
206    Dmsg2(30, "Compare Vol names: VolName=%s hdr=%s\n", VolName?VolName:"*", dev->VolHdr.VolumeName);
207    if (VolName && *VolName && *VolName != '*' && strcmp(dev->VolHdr.VolumeName, VolName) != 0) {
208       Mmsg(jcr->errmsg, _("Wrong Volume mounted on device %s: Wanted %s have %s\n"),
209            dev->print_name(), VolName, dev->VolHdr.VolumeName);
210       Dmsg1(30, "%s", jcr->errmsg);
211       /*
212        * Cancel Job if too many label errors
213        *  => we are in a loop
214        */
215       if (!dev->poll && jcr->label_errors++ > 100) {
216          Jmsg(jcr, M_FATAL, 0, "Too many tries: %s", jcr->errmsg);
217       }
218       Dmsg0(150, "return VOL_NAME_ERROR\n");
219       stat = VOL_NAME_ERROR;
220       goto bail_out;
221    }
222    Dmsg1(30, "Copy vol_name=%s\n", dev->VolHdr.VolumeName);
223
224    if (debug_level >= 10) {
225       dump_volume_label(dev);
226    }
227    Dmsg0(30, "Leave read_volume_label() VOL_OK\n");
228    /* If we are a streaming device, we only get one chance to read */
229    if (!dev_cap(dev, CAP_STREAM)) {
230       dev->rewind(dcr);
231       if (have_ansi_label) {
232          stat = read_ansi_ibm_label(dcr);            
233          /* If we want a label and didn't find it, return error */
234          if (stat != VOL_OK) {
235             goto bail_out;
236          }
237       }
238    }
239    empty_block(block);
240    return VOL_OK;
241
242 bail_out:
243    empty_block(block);
244    dev->rewind(dcr);
245    Dmsg1(150, "return %d\n", stat);
246    return stat;
247 }
248
249 /*
250  * Put a volume label into the block
251  *
252  *  Returns: false on failure
253  *           true  on success
254  */
255 bool write_volume_label_to_block(DCR *dcr)
256 {
257    DEV_RECORD rec;
258    DEVICE *dev = dcr->dev;
259    JCR *jcr = dcr->jcr;
260    DEV_BLOCK *block = dcr->block;
261
262    Dmsg0(20, "write Label in write_volume_label_to_block()\n");
263    memset(&rec, 0, sizeof(rec));
264    rec.data = get_memory(SER_LENGTH_Volume_Label);
265    empty_block(block);                /* Volume label always at beginning */
266
267    create_volume_label_record(dcr, &rec);
268
269    block->BlockNumber = 0;
270    if (!write_record_to_block(block, &rec)) {
271       free_pool_memory(rec.data);
272       Jmsg1(jcr, M_FATAL, 0, _("Cannot write Volume label to block for device %s\n"),
273          dev->print_name());
274       return false;
275    } else {
276       Dmsg1(90, "Wrote label of %d bytes to block\n", rec.data_len);
277    }
278    free_pool_memory(rec.data);
279    return true;
280 }
281
282
283 /*
284  * Write a Volume Label
285  *  !!! Note, this is ONLY used for writing
286  *            a fresh volume label.  Any data
287  *            after the label will be destroyed,
288  *            in fact, we write the label 5 times !!!!
289  *
290  *  This routine should be used only when labeling a blank tape.
291  */
292 bool write_new_volume_label_to_dev(DCR *dcr, const char *VolName, 
293                                    const char *PoolName, bool dvdnow)
294 {
295    DEVICE *dev = dcr->dev;
296
297
298    Dmsg0(99, "write_volume_label()\n");
299    empty_block(dcr->block);
300
301    if (dev->open(dcr, OPEN_READ_WRITE) < 0) {
302       /* If device is not tape, attempt to create it */
303       if (dev->is_tape() || dev->open(dcr, CREATE_READ_WRITE) < 0) {
304          goto bail_out;
305       }
306    }
307    Dmsg1(150, "Label type=%d\n", dev->label_type);
308    if (!dev->rewind(dcr)) {
309       free_volume(dev);
310       memset(&dev->VolHdr, 0, sizeof(dev->VolHdr));
311       Dmsg2(30, "Bad status on %s from rewind: ERR=%s\n", dev->print_name(), dev->bstrerror());
312       if (!forge_on) {
313          goto bail_out;
314       }
315    }
316
317    /* Create PRE_LABEL or VOL_LABEL if DVD */
318    create_volume_label(dev, VolName, PoolName, dvdnow);
319
320    /*
321     * If we have already detected an ANSI label, re-read it
322     *   to skip past it. Otherwise, we write a new one if 
323     *   so requested.  
324     */
325    if (dev->label_type != B_BACULA_LABEL) {
326       if (read_ansi_ibm_label(dcr) != VOL_OK) {
327          dev->rewind(dcr);
328          goto bail_out;
329       }
330    } else if (!write_ansi_ibm_labels(dcr, ANSI_VOL_LABEL, VolName)) {
331       goto bail_out;
332    }
333
334    create_volume_label_record(dcr, dcr->rec);
335    dcr->rec->Stream = 0;
336
337    /* Temporarily mark in append state to enable writing */
338    dev->set_append();
339    if (!write_record_to_block(dcr->block, dcr->rec)) {
340       Dmsg2(30, "Bad Label write on %s: ERR=%s\n", dev->print_name(), dev->bstrerror());
341       goto bail_out;
342    } else {
343       Dmsg2(30, "Wrote label of %d bytes to %s\n", dcr->rec->data_len, dev->print_name());
344    }
345
346    Dmsg0(99, "Call write_block_to_dev()\n");
347    if (!write_block_to_dev(dcr)) {
348       Dmsg2(30, "Bad Label write on %s: ERR=%s\n", dev->print_name(), dev->bstrerror());
349       goto bail_out;
350    }
351
352    /* Now commit block to DVD if we should write now */
353    if (dev->is_dvd() && dvdnow) {
354       if (!dvd_write_part(dcr)) {
355          Dmsg2(30, "Bad DVD write on %s: ERR=%s\n", dev->print_name(), dev->bstrerror());
356          goto bail_out;
357       }
358    }
359
360    Dmsg0(99, " Wrote block to device\n");
361
362    if (dev->weof(1)) {
363       dev->set_labeled();
364       write_ansi_ibm_labels(dcr, ANSI_EOF_LABEL, dev->VolHdr.VolumeName);
365    }
366
367    if (debug_level >= 20)  {
368       dump_volume_label(dev);
369    }
370    new_volume(dcr, VolName);
371    dev->clear_append();               /* remove append since this is PRE_LABEL */
372    return true;
373
374 bail_out:
375    free_volume(dev);
376    memset(&dev->VolHdr, 0, sizeof(dev->VolHdr));
377    dev->clear_append();               /* remove append since this is PRE_LABEL */
378    return false;
379 }
380
381 /*
382  * Write a volume label. This is ONLY called if we have a valid Bacula
383  *   label of type PRE_LABEL;
384  *  Returns: true if OK
385  *           false if unable to write it
386  */
387 bool rewrite_volume_label(DCR *dcr, bool recycle)
388 {
389    DEVICE *dev = dcr->dev;
390    JCR *jcr = dcr->jcr;
391
392    if (dev->open(dcr, OPEN_READ_WRITE) < 0) {
393       return false;
394    }
395    Dmsg2(190, "set append found freshly labeled volume. fd=%d dev=%x\n", dev->fd, dev);
396    dev->VolHdr.LabelType = VOL_LABEL; /* set Volume label */
397    dev->set_append();
398    if (!write_volume_label_to_block(dcr)) {
399       Dmsg0(200, "Error from write volume label.\n");
400       return false;
401    }
402    /*
403     * If we are not dealing with a streaming device,
404     *  write the block now to ensure we have write permission.
405     *  It is better to find out now rather than later.
406     * We do not write the block now if this is an ANSI label. This
407     *  avoids re-writing the ANSI label, which we do not want to do.
408     */
409    if (!dev_cap(dev, CAP_STREAM)) {
410       if (!dev->rewind(dcr)) {
411          Jmsg2(jcr, M_FATAL, 0, _("Rewind error on device %s: ERR=%s\n"),
412                dev->print_name(), dev->bstrerror());
413          return false;
414       }
415       if (recycle) {
416          if (!dev->truncate(dcr)) {
417             Jmsg2(jcr, M_FATAL, 0, _("Truncate error on device %s: ERR=%s\n"),
418                   dev->print_name(), dev->bstrerror());
419             return false;
420          }
421       }
422
423       /*
424        * If we have already detected an ANSI label, re-read it
425        *   to skip past it. Otherwise, we write a new one if 
426        *   so requested.  
427        */
428       if (dev->label_type != B_BACULA_LABEL) {
429          if (read_ansi_ibm_label(dcr) != VOL_OK) {
430             dev->rewind(dcr);
431             return false;
432          }
433       } else if (!write_ansi_ibm_labels(dcr, ANSI_VOL_LABEL, dev->VolHdr.VolumeName)) {
434          return false;
435       }
436
437       /* Attempt write to check write permission */
438       Dmsg1(200, "Attempt to write to device fd=%d.\n", dev->fd);
439       if (!write_block_to_dev(dcr)) {
440          Jmsg2(jcr, M_ERROR, 0, _("Unable to write device %s: ERR=%s\n"),
441             dev->print_name(), dev->bstrerror());
442          Dmsg0(200, "===ERROR write block to dev\n");
443          return false;
444       }
445    }
446    /* Set or reset Volume statistics */
447    dev->VolCatInfo.VolCatJobs = 0;
448    dev->VolCatInfo.VolCatFiles = 0;
449    dev->VolCatInfo.VolCatBytes = 1;
450    dev->VolCatInfo.VolCatErrors = 0;
451    dev->VolCatInfo.VolCatBlocks = 0;
452    dev->VolCatInfo.VolCatRBytes = 0;
453    if (recycle) {
454       dev->VolCatInfo.VolCatMounts++;
455       dev->VolCatInfo.VolCatRecycles++;
456    } else {
457       dev->VolCatInfo.VolCatMounts = 1;
458       dev->VolCatInfo.VolCatRecycles = 0;
459       dev->VolCatInfo.VolCatWrites = 1;
460       dev->VolCatInfo.VolCatReads = 1;
461    }
462    Dmsg0(150, "dir_update_vol_info. Set Append\n");
463    bstrncpy(dev->VolCatInfo.VolCatStatus, "Append", sizeof(dev->VolCatInfo.VolCatStatus));
464    if (!dir_update_volume_info(dcr, true)) {  /* indicate doing relabel */
465       return false;
466    }
467    if (recycle) {
468       Jmsg(jcr, M_INFO, 0, _("Recycled volume \"%s\" on device %s, all previous data lost.\n"),
469          dcr->VolumeName, dev->print_name());
470    } else {
471       Jmsg(jcr, M_INFO, 0, _("Wrote label to prelabeled Volume \"%s\" on device %s\n"),
472          dcr->VolumeName, dev->print_name());
473    }
474    /*
475     * End writing real Volume label (from pre-labeled tape), or recycling
476     *  the volume.
477     */
478    Dmsg0(200, "OK from rewrite vol label.\n");
479    return true;
480 }
481
482
483 /*
484  *  create_volume_label_record
485  *   Serialize label (from dev->VolHdr structure) into device record.
486  *   Assumes that the dev->VolHdr structure is properly
487  *   initialized.
488 */
489 static void create_volume_label_record(DCR *dcr, DEV_RECORD *rec)
490 {
491    ser_declare;
492    struct date_time dt;
493    DEVICE *dev = dcr->dev;
494    JCR *jcr = dcr->jcr;
495    char buf[100];
496
497    /* Serialize the label into the device record. */
498
499    rec->data = check_pool_memory_size(rec->data, SER_LENGTH_Volume_Label);
500    ser_begin(rec->data, SER_LENGTH_Volume_Label);
501    ser_string(dev->VolHdr.Id);
502
503    ser_uint32(dev->VolHdr.VerNum);
504
505    if (dev->VolHdr.VerNum >= 11) {
506       ser_btime(dev->VolHdr.label_btime);
507       dev->VolHdr.write_btime = get_current_btime();
508       ser_btime(dev->VolHdr.write_btime);
509       dev->VolHdr.write_date = 0;
510       dev->VolHdr.write_time = 0;
511    } else {
512       /* OLD WAY DEPRECATED */
513       ser_float64(dev->VolHdr.label_date);
514       ser_float64(dev->VolHdr.label_time);
515       get_current_time(&dt);
516       dev->VolHdr.write_date = dt.julian_day_number;
517       dev->VolHdr.write_time = dt.julian_day_fraction;
518    }
519    ser_float64(dev->VolHdr.write_date);   /* 0 if VerNum >= 11 */
520    ser_float64(dev->VolHdr.write_time);   /* 0  if VerNum >= 11 */
521
522    ser_string(dev->VolHdr.VolumeName);
523    ser_string(dev->VolHdr.PrevVolumeName);
524    ser_string(dev->VolHdr.PoolName);
525    ser_string(dev->VolHdr.PoolType);
526    ser_string(dev->VolHdr.MediaType);
527
528    ser_string(dev->VolHdr.HostName);
529    ser_string(dev->VolHdr.LabelProg);
530    ser_string(dev->VolHdr.ProgVersion);
531    ser_string(dev->VolHdr.ProgDate);
532
533    ser_end(rec->data, SER_LENGTH_Volume_Label);
534    rec->data_len = ser_length(rec->data);
535    rec->FileIndex = dev->VolHdr.LabelType;
536    rec->VolSessionId = jcr->VolSessionId;
537    rec->VolSessionTime = jcr->VolSessionTime;
538    rec->Stream = jcr->NumVolumes;
539    Dmsg2(150, "Created Vol label rec: FI=%s len=%d\n", FI_to_ascii(buf, rec->FileIndex),
540       rec->data_len);
541 }
542
543
544 /*
545  * Create a volume label in memory
546  */
547 void create_volume_label(DEVICE *dev, const char *VolName, 
548                          const char *PoolName, bool dvdnow)
549 {
550    DEVRES *device = (DEVRES *)dev->device;
551
552    Dmsg0(90, "Start create_volume_label()\n");
553
554    ASSERT(dev != NULL);
555
556    free_volume(dev);         /* release any old volume */
557    memset(&dev->VolHdr, 0, sizeof(dev->VolHdr));
558
559    bstrncpy(dev->VolHdr.Id, BaculaId, sizeof(dev->VolHdr.Id));
560    dev->VolHdr.VerNum = BaculaTapeVersion;
561    if (dev->is_dvd()) {
562       /* We do not want to re-label a DVD so write VOL_LABEL now */
563       dev->VolHdr.LabelType = VOL_LABEL;
564    } else {
565       dev->VolHdr.LabelType = PRE_LABEL;  /* Mark tape as unused */
566    }
567    bstrncpy(dev->VolHdr.VolumeName, VolName, sizeof(dev->VolHdr.VolumeName));
568    bstrncpy(dev->VolHdr.PoolName, PoolName, sizeof(dev->VolHdr.PoolName));
569    bstrncpy(dev->VolHdr.MediaType, device->media_type, sizeof(dev->VolHdr.MediaType));
570
571    bstrncpy(dev->VolHdr.PoolType, "Backup", sizeof(dev->VolHdr.PoolType));
572
573    dev->VolHdr.label_btime = get_current_btime();
574    dev->VolHdr.label_date = 0;
575    dev->VolHdr.label_time = 0;
576
577    if (gethostname(dev->VolHdr.HostName, sizeof(dev->VolHdr.HostName)) != 0) {
578       dev->VolHdr.HostName[0] = 0;
579    }
580    bstrncpy(dev->VolHdr.LabelProg, my_name, sizeof(dev->VolHdr.LabelProg));
581    sprintf(dev->VolHdr.ProgVersion, "Ver. %s %s", VERSION, BDATE);
582    sprintf(dev->VolHdr.ProgDate, "Build %s %s", __DATE__, __TIME__);
583    dev->set_labeled();               /* set has Bacula label */
584    if (debug_level >= 90) {
585       dump_volume_label(dev);
586    }
587 }
588
589 /*
590  * Create session label
591  *  The pool memory must be released by the calling program
592  */
593 void create_session_label(DCR *dcr, DEV_RECORD *rec, int label)
594 {
595    JCR *jcr = dcr->jcr;
596    ser_declare;
597
598    rec->VolSessionId   = jcr->VolSessionId;
599    rec->VolSessionTime = jcr->VolSessionTime;
600    rec->Stream         = jcr->JobId;
601
602    rec->data = check_pool_memory_size(rec->data, SER_LENGTH_Session_Label);
603    ser_begin(rec->data, SER_LENGTH_Session_Label);
604    ser_string(BaculaId);
605    ser_uint32(BaculaTapeVersion);
606
607    ser_uint32(jcr->JobId);
608
609    /* Changed in VerNum 11 */
610    ser_btime(get_current_btime());
611    ser_float64(0);
612
613    ser_string(dcr->pool_name);
614    ser_string(dcr->pool_type);
615    ser_string(jcr->job_name);         /* base Job name */
616    ser_string(jcr->client_name);
617
618    /* Added in VerNum 10 */
619    ser_string(jcr->Job);              /* Unique name of this Job */
620    ser_string(jcr->fileset_name);
621    ser_uint32(jcr->JobType);
622    ser_uint32(jcr->JobLevel);
623    /* Added in VerNum 11 */
624    ser_string(jcr->fileset_md5);
625
626    if (label == EOS_LABEL) {
627       ser_uint32(jcr->JobFiles);
628       ser_uint64(jcr->JobBytes);
629       ser_uint32(dcr->StartBlock);
630       ser_uint32(dcr->EndBlock);
631       ser_uint32(dcr->StartFile);
632       ser_uint32(dcr->EndFile);
633       ser_uint32(jcr->JobErrors);
634
635       /* Added in VerNum 11 */
636       ser_uint32(jcr->JobStatus);
637    }
638    ser_end(rec->data, SER_LENGTH_Session_Label);
639    rec->data_len = ser_length(rec->data);
640 }
641
642 /* Write session label
643  *  Returns: false on failure
644  *           true  on success
645  */
646 bool write_session_label(DCR *dcr, int label)
647 {
648    JCR *jcr = dcr->jcr;
649    DEVICE *dev = dcr->dev;
650    DEV_RECORD *rec;
651    DEV_BLOCK *block = dcr->block;
652    char buf1[100], buf2[100];
653
654    rec = new_record();
655    Dmsg1(90, "session_label record=%x\n", rec);
656    switch (label) {
657    case SOS_LABEL:
658       if (dev->is_tape()) {
659          dcr->StartBlock = dev->block_num;
660          dcr->StartFile  = dev->file;
661       } else {
662          dcr->StartBlock = (uint32_t)dev->file_addr;
663          dcr->StartFile = (uint32_t)(dev->file_addr >> 32);
664       }
665       break;
666    case EOS_LABEL:
667       if (dev->is_tape()) {
668          dcr->EndBlock = dev->EndBlock;
669          dcr->EndFile  = dev->EndFile;
670       } else {
671          dcr->EndBlock = (uint32_t)dev->file_addr;
672          dcr->EndFile = (uint32_t)(dev->file_addr >> 32);
673       }
674       break;
675    default:
676       Jmsg1(jcr, M_ABORT, 0, _("Bad session label = %d\n"), label);
677       break;
678    }
679    create_session_label(dcr, rec, label);
680    rec->FileIndex = label;
681
682    /*
683     * We guarantee that the session record can totally fit
684     *  into a block. If not, write the block, and put it in
685     *  the next block. Having the sesssion record totally in
686     *  one block makes reading them much easier (no need to
687     *  read the next block).
688     */
689    if (!can_write_record_to_block(block, rec)) {
690       Dmsg0(150, "Cannot write session label to block.\n");
691       if (!write_block_to_device(dcr)) {
692          Dmsg0(90, "Got session label write_block_to_dev error.\n");
693          /* ****FIXME***** errno is not set here */
694          Jmsg(jcr, M_FATAL, 0, _("Error writing Session label to %s: %s\n"),
695                            dev_vol_name(dev), strerror(errno));
696          free_record(rec);
697          return false;
698       }
699    }
700    if (!write_record_to_block(block, rec)) {
701       Jmsg(jcr, M_FATAL, 0, _("Error writing Session label to %s: %s\n"),
702                         dev_vol_name(dev), strerror(errno));
703       free_record(rec);
704       return false;
705    }
706
707    Dmsg6(20, "Write sesson_label record JobId=%d FI=%s SessId=%d Strm=%s len=%d "
708              "remainder=%d\n", jcr->JobId,
709       FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId,
710       stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len,
711       rec->remainder);
712
713    free_record(rec);
714    Dmsg2(20, "Leave write_session_label Block=%d File=%d\n",
715       dev->block_num, dev->file);
716    return true;
717 }
718
719 /*  unser_volume_label
720  *
721  * Unserialize the Bacula Volume label into the device Volume_Label
722  * structure.
723  *
724  * Assumes that the record is already read.
725  *
726  * Returns: false on error
727  *          true  on success
728 */
729
730 bool unser_volume_label(DEVICE *dev, DEV_RECORD *rec)
731 {
732    ser_declare;
733    char buf1[100], buf2[100];
734
735    if (rec->FileIndex != VOL_LABEL && rec->FileIndex != PRE_LABEL) {
736       Mmsg3(dev->errmsg, _("Expecting Volume Label, got FI=%s Stream=%s len=%d\n"),
737               FI_to_ascii(buf1, rec->FileIndex),
738               stream_to_ascii(buf2, rec->Stream, rec->FileIndex),
739               rec->data_len);
740       if (!forge_on) {
741          return false;
742       }
743    }
744
745    dev->VolHdr.LabelType = rec->FileIndex;
746    dev->VolHdr.LabelSize = rec->data_len;
747
748
749    /* Unserialize the record into the Volume Header */
750    rec->data = check_pool_memory_size(rec->data, SER_LENGTH_Volume_Label);
751    ser_begin(rec->data, SER_LENGTH_Volume_Label);
752    unser_string(dev->VolHdr.Id);
753    unser_uint32(dev->VolHdr.VerNum);
754
755    if (dev->VolHdr.VerNum >= 11) {
756       unser_btime(dev->VolHdr.label_btime);
757       unser_btime(dev->VolHdr.write_btime);
758    } else { /* old way */
759       unser_float64(dev->VolHdr.label_date);
760       unser_float64(dev->VolHdr.label_time);
761    }
762    unser_float64(dev->VolHdr.write_date);    /* Unused with VerNum >= 11 */
763    unser_float64(dev->VolHdr.write_time);    /* Unused with VerNum >= 11 */
764
765    unser_string(dev->VolHdr.VolumeName);
766    unser_string(dev->VolHdr.PrevVolumeName);
767    unser_string(dev->VolHdr.PoolName);
768    unser_string(dev->VolHdr.PoolType);
769    unser_string(dev->VolHdr.MediaType);
770
771    unser_string(dev->VolHdr.HostName);
772    unser_string(dev->VolHdr.LabelProg);
773    unser_string(dev->VolHdr.ProgVersion);
774    unser_string(dev->VolHdr.ProgDate);
775
776    ser_end(rec->data, SER_LENGTH_Volume_Label);
777    Dmsg0(190, "unser_vol_label\n");
778    if (debug_level >= 190) {
779       dump_volume_label(dev);
780    }
781    return true;
782 }
783
784
785 bool unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec)
786 {
787    ser_declare;
788
789    rec->data = check_pool_memory_size(rec->data, SER_LENGTH_Session_Label);
790    unser_begin(rec->data, SER_LENGTH_Session_Label);
791    unser_string(label->Id);
792    unser_uint32(label->VerNum);
793    unser_uint32(label->JobId);
794    if (label->VerNum >= 11) {
795       unser_btime(label->write_btime);
796    } else {
797       unser_float64(label->write_date);
798    }
799    unser_float64(label->write_time);
800    unser_string(label->PoolName);
801    unser_string(label->PoolType);
802    unser_string(label->JobName);
803    unser_string(label->ClientName);
804    if (label->VerNum >= 10) {
805       unser_string(label->Job);          /* Unique name of this Job */
806       unser_string(label->FileSetName);
807       unser_uint32(label->JobType);
808       unser_uint32(label->JobLevel);
809    }
810    if (label->VerNum >= 11) {
811       unser_string(label->FileSetMD5);
812    } else {
813       label->FileSetMD5[0] = 0;
814    }
815    if (rec->FileIndex == EOS_LABEL) {
816       unser_uint32(label->JobFiles);
817       unser_uint64(label->JobBytes);
818       unser_uint32(label->StartBlock);
819       unser_uint32(label->EndBlock);
820       unser_uint32(label->StartFile);
821       unser_uint32(label->EndFile);
822       unser_uint32(label->JobErrors);
823       if (label->VerNum >= 11) {
824          unser_uint32(label->JobStatus);
825       } else {
826          label->JobStatus = JS_Terminated; /* kludge */
827       }
828    }
829    return true;
830 }
831
832 void dump_volume_label(DEVICE *dev)
833 {
834    int dbl = debug_level;
835    uint32_t File;
836    const char *LabelType;
837    char buf[30];
838    struct tm tm;
839    struct date_time dt;
840
841    debug_level = 1;
842    File = dev->file;
843    switch (dev->VolHdr.LabelType) {
844    case PRE_LABEL:
845       LabelType = "PRE_LABEL";
846       break;
847    case VOL_LABEL:
848       LabelType = "VOL_LABEL";
849       break;
850    case EOM_LABEL:
851       LabelType = "EOM_LABEL";
852       break;
853    case SOS_LABEL:
854       LabelType = "SOS_LABEL";
855       break;
856    case EOS_LABEL:
857       LabelType = "EOS_LABEL";
858       break;
859    case EOT_LABEL:
860       goto bail_out;
861    default:
862       LabelType = buf;
863       sprintf(buf, _("Unknown %d"), dev->VolHdr.LabelType);
864       break;
865    }
866
867    Pmsg11(-1, _("\nVolume Label:\n"
868 "Id                : %s"
869 "VerNo             : %d\n"
870 "VolName           : %s\n"
871 "PrevVolName       : %s\n"
872 "VolFile           : %d\n"
873 "LabelType         : %s\n"
874 "LabelSize         : %d\n"
875 "PoolName          : %s\n"
876 "MediaType         : %s\n"
877 "PoolType          : %s\n"
878 "HostName          : %s\n"
879 ""),
880              dev->VolHdr.Id, dev->VolHdr.VerNum,
881              dev->VolHdr.VolumeName, dev->VolHdr.PrevVolumeName,
882              File, LabelType, dev->VolHdr.LabelSize,
883              dev->VolHdr.PoolName, dev->VolHdr.MediaType,
884              dev->VolHdr.PoolType, dev->VolHdr.HostName);
885
886    if (dev->VolHdr.VerNum >= 11) {
887       char dt[50];
888       bstrftime(dt, sizeof(dt), btime_to_unix(dev->VolHdr.label_btime));
889       Pmsg1(-1, _("Date label written: %s\n"), dt);
890    } else {
891    dt.julian_day_number   = dev->VolHdr.label_date;
892    dt.julian_day_fraction = dev->VolHdr.label_time;
893    tm_decode(&dt, &tm);
894    Pmsg5(-1,
895 _("Date label written: %04d-%02d-%02d at %02d:%02d\n"),
896       tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min);
897    }
898
899 bail_out:
900    debug_level = dbl;
901 }
902
903
904 static void dump_session_label(DEV_RECORD *rec, const char *type)
905 {
906    int dbl;
907    struct date_time dt;
908    struct tm tm;
909    SESSION_LABEL label;
910    char ec1[30], ec2[30], ec3[30], ec4[30], ec5[30], ec6[30], ec7[30];
911
912    unser_session_label(&label, rec);
913    dbl = debug_level;
914    debug_level = 1;
915    Pmsg7(-1, _("\n%s Record:\n"
916 "JobId             : %d\n"
917 "VerNum            : %d\n"
918 "PoolName          : %s\n"
919 "PoolType          : %s\n"
920 "JobName           : %s\n"
921 "ClientName        : %s\n"
922 ""),    type, label.JobId, label.VerNum,
923       label.PoolName, label.PoolType,
924       label.JobName, label.ClientName);
925
926    if (label.VerNum >= 10) {
927       Pmsg4(-1, _(
928 "Job (unique name) : %s\n"
929 "FileSet           : %s\n"
930 "JobType           : %c\n"
931 "JobLevel          : %c\n"
932 ""), label.Job, label.FileSetName, label.JobType, label.JobLevel);
933    }
934
935    if (rec->FileIndex == EOS_LABEL) {
936       Pmsg8(-1, _(
937 "JobFiles          : %s\n"
938 "JobBytes          : %s\n"
939 "StartBlock        : %s\n"
940 "EndBlock          : %s\n"
941 "StartFile         : %s\n"
942 "EndFile           : %s\n"
943 "JobErrors         : %s\n"
944 "JobStatus         : %c\n"
945 ""),
946          edit_uint64_with_commas(label.JobFiles, ec1),
947          edit_uint64_with_commas(label.JobBytes, ec2),
948          edit_uint64_with_commas(label.StartBlock, ec3),
949          edit_uint64_with_commas(label.EndBlock, ec4),
950          edit_uint64_with_commas(label.StartFile, ec5),
951          edit_uint64_with_commas(label.EndFile, ec6),
952          edit_uint64_with_commas(label.JobErrors, ec7),
953          label.JobStatus);
954    }
955    if (label.VerNum >= 11) {
956       char dt[50];
957       bstrftime(dt, sizeof(dt), btime_to_unix(label.write_btime));
958       Pmsg1(-1, _("Date written      : %s\n"), dt);
959    } else {
960       dt.julian_day_number   = label.write_date;
961       dt.julian_day_fraction = label.write_time;
962       tm_decode(&dt, &tm);
963       Pmsg5(-1, _("Date written      : %04d-%02d-%02d at %02d:%02d\n"),
964       tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min);
965    }
966
967    debug_level = dbl;
968 }
969
970 void dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose)
971 {
972    const char *type;
973    int dbl;
974
975    if (rec->FileIndex == 0 && rec->VolSessionId == 0 && rec->VolSessionTime == 0) {
976       return;
977    }
978    dbl = debug_level;
979    debug_level = 1;
980    switch (rec->FileIndex) {
981    case PRE_LABEL:
982       type = _("Fresh Volume");
983       break;
984    case VOL_LABEL:
985       type = _("Volume");
986       break;
987    case SOS_LABEL:
988       type = _("Begin Job Session");
989       break;
990    case EOS_LABEL:
991       type = _("End Job Session");
992       break;
993    case EOM_LABEL:
994       type = _("End of Media");
995       break;
996    case EOT_LABEL:
997       type = _("End of Tape");
998       break;
999    default:
1000       type = _("Unknown");
1001       break;
1002    }
1003    if (verbose) {
1004       switch (rec->FileIndex) {
1005       case PRE_LABEL:
1006       case VOL_LABEL:
1007          unser_volume_label(dev, rec);
1008          dump_volume_label(dev);
1009          break;
1010       case SOS_LABEL:
1011          dump_session_label(rec, type);
1012          break;
1013       case EOS_LABEL:
1014          dump_session_label(rec, type);
1015          break;
1016       case EOM_LABEL:
1017          Pmsg7(-1, _("%s Record: File:blk=%u:%u SessId=%d SessTime=%d JobId=%d DataLen=%d\n"),
1018             type, dev->file, dev->block_num, rec->VolSessionId, 
1019             rec->VolSessionTime, rec->Stream, rec->data_len);
1020          break;
1021       case EOT_LABEL:
1022          Pmsg0(-1, _("End of physical tape.\n"));
1023          break;
1024       default:
1025          Pmsg7(-1, _("%s Record: File:blk=%u:%u SessId=%d SessTime=%d JobId=%d DataLen=%d\n"),
1026             type, dev->file, dev->block_num, rec->VolSessionId, 
1027             rec->VolSessionTime, rec->Stream, rec->data_len);
1028          break;
1029       }
1030    } else {
1031       SESSION_LABEL label;
1032       char dt[50];
1033       switch (rec->FileIndex) {
1034       case SOS_LABEL:
1035          unser_session_label(&label, rec);
1036          bstrftimes(dt, sizeof(dt), btime_to_unix(label.write_btime));
1037          Pmsg6(-1, _("%s Record: File:blk=%u:%u SessId=%d SessTime=%d JobId=%d\n"),
1038             type, dev->file, dev->block_num, rec->VolSessionId, rec->VolSessionTime, label.JobId);
1039          Pmsg4(-1, _("   Job=%s Date=%s Level=%c Type=%c\n"),
1040             label.Job, dt, label.JobLevel, label.JobType);
1041          break;
1042       case EOS_LABEL:
1043          char ed1[30], ed2[30];
1044          unser_session_label(&label, rec);
1045          bstrftimes(dt, sizeof(dt), btime_to_unix(label.write_btime));
1046          Pmsg6(-1, _("%s Record: File:blk=%u:%u SessId=%d SessTime=%d JobId=%d\n"),
1047             type, dev->file, dev->block_num, rec->VolSessionId, rec->VolSessionTime, label.JobId);
1048          Pmsg7(-1, _("   Date=%s Level=%c Type=%c Files=%s Bytes=%s Errors=%d Status=%c\n"),
1049             dt, label.JobLevel, label.JobType,
1050             edit_uint64_with_commas(label.JobFiles, ed1),
1051             edit_uint64_with_commas(label.JobBytes, ed2),
1052             label.JobErrors, (char)label.JobStatus);
1053          break;
1054       case EOM_LABEL:
1055       case PRE_LABEL:
1056       case VOL_LABEL:
1057       default:
1058          Pmsg7(-1, _("%s Record: File:blk=%u:%u SessId=%d SessTime=%d JobId=%d DataLen=%d\n"),
1059             type, dev->file, dev->block_num, rec->VolSessionId, rec->VolSessionTime, 
1060             rec->Stream, rec->data_len);
1061          break;
1062       case EOT_LABEL:
1063          break;
1064       }
1065    }
1066    debug_level = dbl;
1067 }