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