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