]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/label.c
Back out more code
[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    dev->VolCatInfo.VolCatBytes = 0;        /* reset byte count */
404
405    /*
406     * If we are not dealing with a streaming device,
407     *  write the block now to ensure we have write permission.
408     *  It is better to find out now rather than later.
409     * We do not write the block now if this is an ANSI label. This
410     *  avoids re-writing the ANSI label, which we do not want to do.
411     */
412    if (!dev_cap(dev, CAP_STREAM)) {
413       if (!dev->rewind(dcr)) {
414          Jmsg2(jcr, M_FATAL, 0, _("Rewind error on device %s: ERR=%s\n"),
415                dev->print_name(), dev->bstrerror());
416          return false;
417       }
418       if (recycle) {
419          if (!dev->truncate(dcr)) {
420             Jmsg2(jcr, M_FATAL, 0, _("Truncate error on device %s: ERR=%s\n"),
421                   dev->print_name(), dev->bstrerror());
422             return false;
423          }
424       }
425
426       /*
427        * If we have already detected an ANSI label, re-read it
428        *   to skip past it. Otherwise, we write a new one if 
429        *   so requested.  
430        */
431       if (dev->label_type != B_BACULA_LABEL) {
432          if (read_ansi_ibm_label(dcr) != VOL_OK) {
433             dev->rewind(dcr);
434             return false;
435          }
436       } else if (!write_ansi_ibm_labels(dcr, ANSI_VOL_LABEL, dev->VolHdr.VolumeName)) {
437          return false;
438       }
439
440       /* Attempt write to check write permission */
441       Dmsg1(200, "Attempt to write to device fd=%d.\n", dev->fd);
442       if (!write_block_to_dev(dcr)) {
443          Jmsg2(jcr, M_ERROR, 0, _("Unable to write device %s: ERR=%s\n"),
444             dev->print_name(), dev->bstrerror());
445          Dmsg0(200, "===ERROR write block to dev\n");
446          return false;
447       }
448    }
449    /* Set or reset Volume statistics */
450    dev->VolCatInfo.VolCatJobs = 0;
451    dev->VolCatInfo.VolCatFiles = 0;
452    dev->VolCatInfo.VolCatErrors = 0;
453    dev->VolCatInfo.VolCatBlocks = 0;
454    dev->VolCatInfo.VolCatRBytes = 0;
455    if (recycle) {
456       dev->VolCatInfo.VolCatMounts++;
457       dev->VolCatInfo.VolCatRecycles++;
458    } else {
459       dev->VolCatInfo.VolCatMounts = 1;
460       dev->VolCatInfo.VolCatRecycles = 0;
461       dev->VolCatInfo.VolCatWrites = 1;
462       dev->VolCatInfo.VolCatReads = 1;
463    }
464    Dmsg0(150, "dir_update_vol_info. Set Append\n");
465    bstrncpy(dev->VolCatInfo.VolCatStatus, "Append", sizeof(dev->VolCatInfo.VolCatStatus));
466    if (!dir_update_volume_info(dcr, true)) {  /* indicate doing relabel */
467       return false;
468    }
469    if (recycle) {
470       Jmsg(jcr, M_INFO, 0, _("Recycled volume \"%s\" on device %s, all previous data lost.\n"),
471          dcr->VolumeName, dev->print_name());
472    } else {
473       Jmsg(jcr, M_INFO, 0, _("Wrote label to prelabeled Volume \"%s\" on device %s\n"),
474          dcr->VolumeName, dev->print_name());
475    }
476    /*
477     * End writing real Volume label (from pre-labeled tape), or recycling
478     *  the volume.
479     */
480    Dmsg0(200, "OK from rewrite vol label.\n");
481    return true;
482 }
483
484
485 /*
486  *  create_volume_label_record
487  *   Serialize label (from dev->VolHdr structure) into device record.
488  *   Assumes that the dev->VolHdr structure is properly
489  *   initialized.
490 */
491 static void create_volume_label_record(DCR *dcr, DEV_RECORD *rec)
492 {
493    ser_declare;
494    struct date_time dt;
495    DEVICE *dev = dcr->dev;
496    JCR *jcr = dcr->jcr;
497    char buf[100];
498
499    /* Serialize the label into the device record. */
500
501    rec->data = check_pool_memory_size(rec->data, SER_LENGTH_Volume_Label);
502    ser_begin(rec->data, SER_LENGTH_Volume_Label);
503    ser_string(dev->VolHdr.Id);
504
505    ser_uint32(dev->VolHdr.VerNum);
506
507    if (dev->VolHdr.VerNum >= 11) {
508       ser_btime(dev->VolHdr.label_btime);
509       dev->VolHdr.write_btime = get_current_btime();
510       ser_btime(dev->VolHdr.write_btime);
511       dev->VolHdr.write_date = 0;
512       dev->VolHdr.write_time = 0;
513    } else {
514       /* OLD WAY DEPRECATED */
515       ser_float64(dev->VolHdr.label_date);
516       ser_float64(dev->VolHdr.label_time);
517       get_current_time(&dt);
518       dev->VolHdr.write_date = dt.julian_day_number;
519       dev->VolHdr.write_time = dt.julian_day_fraction;
520    }
521    ser_float64(dev->VolHdr.write_date);   /* 0 if VerNum >= 11 */
522    ser_float64(dev->VolHdr.write_time);   /* 0  if VerNum >= 11 */
523
524    ser_string(dev->VolHdr.VolumeName);
525    ser_string(dev->VolHdr.PrevVolumeName);
526    ser_string(dev->VolHdr.PoolName);
527    ser_string(dev->VolHdr.PoolType);
528    ser_string(dev->VolHdr.MediaType);
529
530    ser_string(dev->VolHdr.HostName);
531    ser_string(dev->VolHdr.LabelProg);
532    ser_string(dev->VolHdr.ProgVersion);
533    ser_string(dev->VolHdr.ProgDate);
534
535    ser_end(rec->data, SER_LENGTH_Volume_Label);
536    rec->data_len = ser_length(rec->data);
537    rec->FileIndex = dev->VolHdr.LabelType;
538    rec->VolSessionId = jcr->VolSessionId;
539    rec->VolSessionTime = jcr->VolSessionTime;
540    rec->Stream = jcr->NumVolumes;
541    Dmsg2(150, "Created Vol label rec: FI=%s len=%d\n", FI_to_ascii(buf, rec->FileIndex),
542       rec->data_len);
543 }
544
545
546 /*
547  * Create a volume label in memory
548  */
549 void create_volume_label(DEVICE *dev, const char *VolName, 
550                          const char *PoolName, bool dvdnow)
551 {
552    DEVRES *device = (DEVRES *)dev->device;
553
554    Dmsg0(90, "Start create_volume_label()\n");
555
556    ASSERT(dev != NULL);
557
558    free_volume(dev);         /* release any old volume */
559    memset(&dev->VolHdr, 0, sizeof(dev->VolHdr));
560
561    bstrncpy(dev->VolHdr.Id, BaculaId, sizeof(dev->VolHdr.Id));
562    dev->VolHdr.VerNum = BaculaTapeVersion;
563    if (dev->is_dvd() && dvdnow) {
564       /* We do not want to re-label a DVD so write VOL_LABEL now */
565       dev->VolHdr.LabelType = VOL_LABEL;
566    } else {
567       dev->VolHdr.LabelType = PRE_LABEL;  /* Mark tape as unused */
568    }
569    bstrncpy(dev->VolHdr.VolumeName, VolName, sizeof(dev->VolHdr.VolumeName));
570    bstrncpy(dev->VolHdr.PoolName, PoolName, sizeof(dev->VolHdr.PoolName));
571    bstrncpy(dev->VolHdr.MediaType, device->media_type, sizeof(dev->VolHdr.MediaType));
572
573    bstrncpy(dev->VolHdr.PoolType, "Backup", sizeof(dev->VolHdr.PoolType));
574
575    dev->VolHdr.label_btime = get_current_btime();
576    dev->VolHdr.label_date = 0;
577    dev->VolHdr.label_time = 0;
578
579    if (gethostname(dev->VolHdr.HostName, sizeof(dev->VolHdr.HostName)) != 0) {
580       dev->VolHdr.HostName[0] = 0;
581    }
582    bstrncpy(dev->VolHdr.LabelProg, my_name, sizeof(dev->VolHdr.LabelProg));
583    sprintf(dev->VolHdr.ProgVersion, "Ver. %s %s", VERSION, BDATE);
584    sprintf(dev->VolHdr.ProgDate, "Build %s %s", __DATE__, __TIME__);
585    dev->set_labeled();               /* set has Bacula label */
586    if (debug_level >= 90) {
587       dump_volume_label(dev);
588    }
589 }
590
591 /*
592  * Create session label
593  *  The pool memory must be released by the calling program
594  */
595 void create_session_label(DCR *dcr, DEV_RECORD *rec, int label)
596 {
597    JCR *jcr = dcr->jcr;
598    ser_declare;
599
600    rec->VolSessionId   = jcr->VolSessionId;
601    rec->VolSessionTime = jcr->VolSessionTime;
602    rec->Stream         = jcr->JobId;
603
604    rec->data = check_pool_memory_size(rec->data, SER_LENGTH_Session_Label);
605    ser_begin(rec->data, SER_LENGTH_Session_Label);
606    ser_string(BaculaId);
607    ser_uint32(BaculaTapeVersion);
608
609    ser_uint32(jcr->JobId);
610
611    /* Changed in VerNum 11 */
612    ser_btime(get_current_btime());
613    ser_float64(0);
614
615    ser_string(dcr->pool_name);
616    ser_string(dcr->pool_type);
617    ser_string(jcr->job_name);         /* base Job name */
618    ser_string(jcr->client_name);
619
620    /* Added in VerNum 10 */
621    ser_string(jcr->Job);              /* Unique name of this Job */
622    ser_string(jcr->fileset_name);
623    ser_uint32(jcr->JobType);
624    ser_uint32(jcr->JobLevel);
625    /* Added in VerNum 11 */
626    ser_string(jcr->fileset_md5);
627
628    if (label == EOS_LABEL) {
629       ser_uint32(jcr->JobFiles);
630       ser_uint64(jcr->JobBytes);
631       ser_uint32(dcr->StartBlock);
632       ser_uint32(dcr->EndBlock);
633       ser_uint32(dcr->StartFile);
634       ser_uint32(dcr->EndFile);
635       ser_uint32(jcr->JobErrors);
636
637       /* Added in VerNum 11 */
638       ser_uint32(jcr->JobStatus);
639    }
640    ser_end(rec->data, SER_LENGTH_Session_Label);
641    rec->data_len = ser_length(rec->data);
642 }
643
644 /* Write session label
645  *  Returns: false on failure
646  *           true  on success
647  */
648 bool write_session_label(DCR *dcr, int label)
649 {
650    JCR *jcr = dcr->jcr;
651    DEVICE *dev = dcr->dev;
652    DEV_RECORD *rec;
653    DEV_BLOCK *block = dcr->block;
654    char buf1[100], buf2[100];
655
656    rec = new_record();
657    Dmsg1(90, "session_label record=%x\n", rec);
658    switch (label) {
659    case SOS_LABEL:
660       if (dev->is_tape()) {
661          dcr->StartBlock = dev->block_num;
662          dcr->StartFile  = dev->file;
663       } else {
664          dcr->StartBlock = (uint32_t)dev->file_addr;
665          dcr->StartFile = (uint32_t)(dev->file_addr >> 32);
666       }
667       break;
668    case EOS_LABEL:
669       if (dev->is_tape()) {
670          dcr->EndBlock = dev->EndBlock;
671          dcr->EndFile  = dev->EndFile;
672       } else {
673          dcr->EndBlock = (uint32_t)dev->file_addr;
674          dcr->EndFile = (uint32_t)(dev->file_addr >> 32);
675       }
676       break;
677    default:
678       Jmsg1(jcr, M_ABORT, 0, _("Bad session label = %d\n"), label);
679       break;
680    }
681    create_session_label(dcr, rec, label);
682    rec->FileIndex = label;
683
684    /*
685     * We guarantee that the session record can totally fit
686     *  into a block. If not, write the block, and put it in
687     *  the next block. Having the sesssion record totally in
688     *  one block makes reading them much easier (no need to
689     *  read the next block).
690     */
691    if (!can_write_record_to_block(block, rec)) {
692       Dmsg0(150, "Cannot write session label to block.\n");
693       if (!write_block_to_device(dcr)) {
694          Dmsg0(90, "Got session label write_block_to_dev error.\n");
695          /* ****FIXME***** errno is not set here */
696          Jmsg(jcr, M_FATAL, 0, _("Error writing Session label to %s: %s\n"),
697                            dev_vol_name(dev), strerror(errno));
698          free_record(rec);
699          return false;
700       }
701    }
702    if (!write_record_to_block(block, rec)) {
703       Jmsg(jcr, M_FATAL, 0, _("Error writing Session label to %s: %s\n"),
704                         dev_vol_name(dev), strerror(errno));
705       free_record(rec);
706       return false;
707    }
708
709    Dmsg6(50, "Write sesson_label record JobId=%d FI=%s SessId=%d Strm=%s len=%d "
710              "remainder=%d\n", jcr->JobId,
711       FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId,
712       stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len,
713       rec->remainder);
714
715    free_record(rec);
716    Dmsg2(50, "Leave write_session_label Block=%ud File=%ud\n",
717       dev->get_block(), dev->get_file());
718    return true;
719 }
720
721 /*  unser_volume_label
722  *
723  * Unserialize the Bacula Volume label into the device Volume_Label
724  * structure.
725  *
726  * Assumes that the record is already read.
727  *
728  * Returns: false on error
729  *          true  on success
730 */
731
732 bool unser_volume_label(DEVICE *dev, DEV_RECORD *rec)
733 {
734    ser_declare;
735    char buf1[100], buf2[100];
736
737    if (rec->FileIndex != VOL_LABEL && rec->FileIndex != PRE_LABEL) {
738       Mmsg3(dev->errmsg, _("Expecting Volume Label, got FI=%s Stream=%s len=%d\n"),
739               FI_to_ascii(buf1, rec->FileIndex),
740               stream_to_ascii(buf2, rec->Stream, rec->FileIndex),
741               rec->data_len);
742       if (!forge_on) {
743          return false;
744       }
745    }
746
747    dev->VolHdr.LabelType = rec->FileIndex;
748    dev->VolHdr.LabelSize = rec->data_len;
749
750
751    /* Unserialize the record into the Volume Header */
752    rec->data = check_pool_memory_size(rec->data, SER_LENGTH_Volume_Label);
753    ser_begin(rec->data, SER_LENGTH_Volume_Label);
754    unser_string(dev->VolHdr.Id);
755    unser_uint32(dev->VolHdr.VerNum);
756
757    if (dev->VolHdr.VerNum >= 11) {
758       unser_btime(dev->VolHdr.label_btime);
759       unser_btime(dev->VolHdr.write_btime);
760    } else { /* old way */
761       unser_float64(dev->VolHdr.label_date);
762       unser_float64(dev->VolHdr.label_time);
763    }
764    unser_float64(dev->VolHdr.write_date);    /* Unused with VerNum >= 11 */
765    unser_float64(dev->VolHdr.write_time);    /* Unused with VerNum >= 11 */
766
767    unser_string(dev->VolHdr.VolumeName);
768    unser_string(dev->VolHdr.PrevVolumeName);
769    unser_string(dev->VolHdr.PoolName);
770    unser_string(dev->VolHdr.PoolType);
771    unser_string(dev->VolHdr.MediaType);
772
773    unser_string(dev->VolHdr.HostName);
774    unser_string(dev->VolHdr.LabelProg);
775    unser_string(dev->VolHdr.ProgVersion);
776    unser_string(dev->VolHdr.ProgDate);
777
778    ser_end(rec->data, SER_LENGTH_Volume_Label);
779    Dmsg0(190, "unser_vol_label\n");
780    if (debug_level >= 190) {
781       dump_volume_label(dev);
782    }
783    return true;
784 }
785
786
787 bool unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec)
788 {
789    ser_declare;
790
791    rec->data = check_pool_memory_size(rec->data, SER_LENGTH_Session_Label);
792    unser_begin(rec->data, SER_LENGTH_Session_Label);
793    unser_string(label->Id);
794    unser_uint32(label->VerNum);
795    unser_uint32(label->JobId);
796    if (label->VerNum >= 11) {
797       unser_btime(label->write_btime);
798    } else {
799       unser_float64(label->write_date);
800    }
801    unser_float64(label->write_time);
802    unser_string(label->PoolName);
803    unser_string(label->PoolType);
804    unser_string(label->JobName);
805    unser_string(label->ClientName);
806    if (label->VerNum >= 10) {
807       unser_string(label->Job);          /* Unique name of this Job */
808       unser_string(label->FileSetName);
809       unser_uint32(label->JobType);
810       unser_uint32(label->JobLevel);
811    }
812    if (label->VerNum >= 11) {
813       unser_string(label->FileSetMD5);
814    } else {
815       label->FileSetMD5[0] = 0;
816    }
817    if (rec->FileIndex == EOS_LABEL) {
818       unser_uint32(label->JobFiles);
819       unser_uint64(label->JobBytes);
820       unser_uint32(label->StartBlock);
821       unser_uint32(label->EndBlock);
822       unser_uint32(label->StartFile);
823       unser_uint32(label->EndFile);
824       unser_uint32(label->JobErrors);
825       if (label->VerNum >= 11) {
826          unser_uint32(label->JobStatus);
827       } else {
828          label->JobStatus = JS_Terminated; /* kludge */
829       }
830    }
831    return true;
832 }
833
834 void dump_volume_label(DEVICE *dev)
835 {
836    int dbl = debug_level;
837    uint32_t File;
838    const char *LabelType;
839    char buf[30];
840    struct tm tm;
841    struct date_time dt;
842
843    debug_level = 1;
844    File = dev->file;
845    switch (dev->VolHdr.LabelType) {
846    case PRE_LABEL:
847       LabelType = "PRE_LABEL";
848       break;
849    case VOL_LABEL:
850       LabelType = "VOL_LABEL";
851       break;
852    case EOM_LABEL:
853       LabelType = "EOM_LABEL";
854       break;
855    case SOS_LABEL:
856       LabelType = "SOS_LABEL";
857       break;
858    case EOS_LABEL:
859       LabelType = "EOS_LABEL";
860       break;
861    case EOT_LABEL:
862       goto bail_out;
863    default:
864       LabelType = buf;
865       sprintf(buf, _("Unknown %d"), dev->VolHdr.LabelType);
866       break;
867    }
868
869    Pmsg11(-1, _("\nVolume Label:\n"
870 "Id                : %s"
871 "VerNo             : %d\n"
872 "VolName           : %s\n"
873 "PrevVolName       : %s\n"
874 "VolFile           : %d\n"
875 "LabelType         : %s\n"
876 "LabelSize         : %d\n"
877 "PoolName          : %s\n"
878 "MediaType         : %s\n"
879 "PoolType          : %s\n"
880 "HostName          : %s\n"
881 ""),
882              dev->VolHdr.Id, dev->VolHdr.VerNum,
883              dev->VolHdr.VolumeName, dev->VolHdr.PrevVolumeName,
884              File, LabelType, dev->VolHdr.LabelSize,
885              dev->VolHdr.PoolName, dev->VolHdr.MediaType,
886              dev->VolHdr.PoolType, dev->VolHdr.HostName);
887
888    if (dev->VolHdr.VerNum >= 11) {
889       char dt[50];
890       bstrftime(dt, sizeof(dt), btime_to_unix(dev->VolHdr.label_btime));
891       Pmsg1(-1, _("Date label written: %s\n"), dt);
892    } else {
893    dt.julian_day_number   = dev->VolHdr.label_date;
894    dt.julian_day_fraction = dev->VolHdr.label_time;
895    tm_decode(&dt, &tm);
896    Pmsg5(-1,
897 _("Date label written: %04d-%02d-%02d at %02d:%02d\n"),
898       tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min);
899    }
900
901 bail_out:
902    debug_level = dbl;
903 }
904
905
906 static void dump_session_label(DEV_RECORD *rec, const char *type)
907 {
908    int dbl;
909    struct date_time dt;
910    struct tm tm;
911    SESSION_LABEL label;
912    char ec1[30], ec2[30], ec3[30], ec4[30], ec5[30], ec6[30], ec7[30];
913
914    unser_session_label(&label, rec);
915    dbl = debug_level;
916    debug_level = 1;
917    Pmsg7(-1, _("\n%s Record:\n"
918 "JobId             : %d\n"
919 "VerNum            : %d\n"
920 "PoolName          : %s\n"
921 "PoolType          : %s\n"
922 "JobName           : %s\n"
923 "ClientName        : %s\n"
924 ""),    type, label.JobId, label.VerNum,
925       label.PoolName, label.PoolType,
926       label.JobName, label.ClientName);
927
928    if (label.VerNum >= 10) {
929       Pmsg4(-1, _(
930 "Job (unique name) : %s\n"
931 "FileSet           : %s\n"
932 "JobType           : %c\n"
933 "JobLevel          : %c\n"
934 ""), label.Job, label.FileSetName, label.JobType, label.JobLevel);
935    }
936
937    if (rec->FileIndex == EOS_LABEL) {
938       Pmsg8(-1, _(
939 "JobFiles          : %s\n"
940 "JobBytes          : %s\n"
941 "StartBlock        : %s\n"
942 "EndBlock          : %s\n"
943 "StartFile         : %s\n"
944 "EndFile           : %s\n"
945 "JobErrors         : %s\n"
946 "JobStatus         : %c\n"
947 ""),
948          edit_uint64_with_commas(label.JobFiles, ec1),
949          edit_uint64_with_commas(label.JobBytes, ec2),
950          edit_uint64_with_commas(label.StartBlock, ec3),
951          edit_uint64_with_commas(label.EndBlock, ec4),
952          edit_uint64_with_commas(label.StartFile, ec5),
953          edit_uint64_with_commas(label.EndFile, ec6),
954          edit_uint64_with_commas(label.JobErrors, ec7),
955          label.JobStatus);
956    }
957    if (label.VerNum >= 11) {
958       char dt[50];
959       bstrftime(dt, sizeof(dt), btime_to_unix(label.write_btime));
960       Pmsg1(-1, _("Date written      : %s\n"), dt);
961    } else {
962       dt.julian_day_number   = label.write_date;
963       dt.julian_day_fraction = label.write_time;
964       tm_decode(&dt, &tm);
965       Pmsg5(-1, _("Date written      : %04d-%02d-%02d at %02d:%02d\n"),
966       tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min);
967    }
968
969    debug_level = dbl;
970 }
971
972 void dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose)
973 {
974    const char *type;
975    int dbl;
976
977    if (rec->FileIndex == 0 && rec->VolSessionId == 0 && rec->VolSessionTime == 0) {
978       return;
979    }
980    dbl = debug_level;
981    debug_level = 1;
982    switch (rec->FileIndex) {
983    case PRE_LABEL:
984       type = _("Fresh Volume");
985       break;
986    case VOL_LABEL:
987       type = _("Volume");
988       break;
989    case SOS_LABEL:
990       type = _("Begin Job Session");
991       break;
992    case EOS_LABEL:
993       type = _("End Job Session");
994       break;
995    case EOM_LABEL:
996       type = _("End of Media");
997       break;
998    case EOT_LABEL:
999       type = _("End of Tape");
1000       break;
1001    default:
1002       type = _("Unknown");
1003       break;
1004    }
1005    if (verbose) {
1006       switch (rec->FileIndex) {
1007       case PRE_LABEL:
1008       case VOL_LABEL:
1009          unser_volume_label(dev, rec);
1010          dump_volume_label(dev);
1011          break;
1012       case SOS_LABEL:
1013          dump_session_label(rec, type);
1014          break;
1015       case EOS_LABEL:
1016          dump_session_label(rec, type);
1017          break;
1018       case EOM_LABEL:
1019          Pmsg7(-1, _("%s Record: File:blk=%u:%u SessId=%d SessTime=%d JobId=%d DataLen=%d\n"),
1020             type, dev->file, dev->block_num, rec->VolSessionId, 
1021             rec->VolSessionTime, rec->Stream, rec->data_len);
1022          break;
1023       case EOT_LABEL:
1024          Pmsg0(-1, _("End of physical tape.\n"));
1025          break;
1026       default:
1027          Pmsg7(-1, _("%s Record: File:blk=%u:%u SessId=%d SessTime=%d JobId=%d DataLen=%d\n"),
1028             type, dev->file, dev->block_num, rec->VolSessionId, 
1029             rec->VolSessionTime, rec->Stream, rec->data_len);
1030          break;
1031       }
1032    } else {
1033       SESSION_LABEL label;
1034       char dt[50];
1035       switch (rec->FileIndex) {
1036       case SOS_LABEL:
1037          unser_session_label(&label, rec);
1038          bstrftimes(dt, sizeof(dt), btime_to_unix(label.write_btime));
1039          Pmsg6(-1, _("%s Record: File:blk=%u:%u SessId=%d SessTime=%d JobId=%d\n"),
1040             type, dev->file, dev->block_num, rec->VolSessionId, rec->VolSessionTime, label.JobId);
1041          Pmsg4(-1, _("   Job=%s Date=%s Level=%c Type=%c\n"),
1042             label.Job, dt, label.JobLevel, label.JobType);
1043          break;
1044       case EOS_LABEL:
1045          char ed1[30], ed2[30];
1046          unser_session_label(&label, rec);
1047          bstrftimes(dt, sizeof(dt), btime_to_unix(label.write_btime));
1048          Pmsg6(-1, _("%s Record: File:blk=%u:%u SessId=%d SessTime=%d JobId=%d\n"),
1049             type, dev->file, dev->block_num, rec->VolSessionId, rec->VolSessionTime, label.JobId);
1050          Pmsg7(-1, _("   Date=%s Level=%c Type=%c Files=%s Bytes=%s Errors=%d Status=%c\n"),
1051             dt, label.JobLevel, label.JobType,
1052             edit_uint64_with_commas(label.JobFiles, ed1),
1053             edit_uint64_with_commas(label.JobBytes, ed2),
1054             label.JobErrors, (char)label.JobStatus);
1055          break;
1056       case EOM_LABEL:
1057       case PRE_LABEL:
1058       case VOL_LABEL:
1059       default:
1060          Pmsg7(-1, _("%s Record: File:blk=%u:%u SessId=%d SessTime=%d JobId=%d DataLen=%d\n"),
1061             type, dev->file, dev->block_num, rec->VolSessionId, rec->VolSessionTime, 
1062             rec->Stream, rec->data_len);
1063          break;
1064       case EOT_LABEL:
1065          break;
1066       }
1067    }
1068    debug_level = dbl;
1069 }