]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/label.c
Change dev->open() to return bool
[bacula/bacula] / bacula / src / stored / label.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2012 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)) {
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)) {
326       /* If device is not tape, attempt to create it */
327       if (dev->is_tape() || !dev->open(dcr, CREATE_READ_WRITE)) {
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)) {
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)) {
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    dev->VolCatInfo.VolFirstWritten = time(NULL);
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    rec->maskedStream = jcr->NumWriteVolumes;
595    Dmsg2(150, "Created Vol label rec: FI=%s len=%d\n", FI_to_ascii(buf, rec->FileIndex),
596       rec->data_len);
597 }
598
599
600 /*
601  * Create a volume label in memory
602  */
603 void create_volume_label(DEVICE *dev, const char *VolName, 
604                          const char *PoolName, bool dvdnow)
605 {
606    DEVRES *device = (DEVRES *)dev->device;
607
608    Dmsg0(130, "Start create_volume_label()\n");
609
610    ASSERT(dev != NULL);
611
612    dev->clear_volhdr();          /* clear any old volume info */
613
614    bstrncpy(dev->VolHdr.Id, BaculaId, sizeof(dev->VolHdr.Id));
615    dev->VolHdr.VerNum = BaculaTapeVersion;
616    if (dev->is_dvd() && dvdnow) {
617       /* We do not want to re-label a DVD so write VOL_LABEL now */
618       dev->VolHdr.LabelType = VOL_LABEL;
619    } else {
620       dev->VolHdr.LabelType = PRE_LABEL;  /* Mark tape as unused */
621    }
622    bstrncpy(dev->VolHdr.VolumeName, VolName, sizeof(dev->VolHdr.VolumeName));
623    bstrncpy(dev->VolHdr.PoolName, PoolName, sizeof(dev->VolHdr.PoolName));
624    bstrncpy(dev->VolHdr.MediaType, device->media_type, sizeof(dev->VolHdr.MediaType));
625
626    bstrncpy(dev->VolHdr.PoolType, "Backup", sizeof(dev->VolHdr.PoolType));
627
628    dev->VolHdr.label_btime = get_current_btime();
629    dev->VolHdr.label_date = 0;
630    dev->VolHdr.label_time = 0;
631
632    if (gethostname(dev->VolHdr.HostName, sizeof(dev->VolHdr.HostName)) != 0) {
633       dev->VolHdr.HostName[0] = 0;
634    }
635    bstrncpy(dev->VolHdr.LabelProg, my_name, sizeof(dev->VolHdr.LabelProg));
636    sprintf(dev->VolHdr.ProgVersion, "Ver. %s %s", VERSION, BDATE);
637    sprintf(dev->VolHdr.ProgDate, "Build %s %s", __DATE__, __TIME__);
638    dev->set_labeled();               /* set has Bacula label */
639    if (debug_level >= 90) {
640       dump_volume_label(dev);
641    }
642 }
643
644 /*
645  * Create session label
646  *  The pool memory must be released by the calling program
647  */
648 void create_session_label(DCR *dcr, DEV_RECORD *rec, int label)
649 {
650    JCR *jcr = dcr->jcr;
651    ser_declare;
652
653    rec->VolSessionId   = jcr->VolSessionId;
654    rec->VolSessionTime = jcr->VolSessionTime;
655    rec->Stream         = jcr->JobId;
656    rec->maskedStream   = jcr->JobId;
657
658    rec->data = check_pool_memory_size(rec->data, SER_LENGTH_Session_Label);
659    ser_begin(rec->data, SER_LENGTH_Session_Label);
660    ser_string(BaculaId);
661    ser_uint32(BaculaTapeVersion);
662
663    ser_uint32(jcr->JobId);
664
665    /* Changed in VerNum 11 */
666    ser_btime(get_current_btime());
667    ser_float64(0);
668
669    ser_string(dcr->pool_name);
670    ser_string(dcr->pool_type);
671    ser_string(jcr->job_name);         /* base Job name */
672    ser_string(jcr->client_name);
673
674    /* Added in VerNum 10 */
675    ser_string(jcr->Job);              /* Unique name of this Job */
676    ser_string(jcr->fileset_name);
677    ser_uint32(jcr->getJobType());
678    ser_uint32(jcr->getJobLevel());
679    /* Added in VerNum 11 */
680    ser_string(jcr->fileset_md5);
681
682    if (label == EOS_LABEL) {
683       ser_uint32(jcr->JobFiles);
684       ser_uint64(jcr->JobBytes);
685       ser_uint32(dcr->StartBlock);
686       ser_uint32(dcr->EndBlock);
687       ser_uint32(dcr->StartFile);
688       ser_uint32(dcr->EndFile);
689       ser_uint32(jcr->JobErrors);
690
691       /* Added in VerNum 11 */
692       ser_uint32(jcr->JobStatus);
693    }
694    ser_end(rec->data, SER_LENGTH_Session_Label);
695    rec->data_len = ser_length(rec->data);
696 }
697
698 /* Write session label
699  *  Returns: false on failure
700  *           true  on success
701  */
702 bool write_session_label(DCR *dcr, int label)
703 {
704    JCR *jcr = dcr->jcr;
705    DEVICE *dev = dcr->dev;
706    DEV_RECORD *rec;
707    DEV_BLOCK *block = dcr->block;
708    char buf1[100], buf2[100];
709
710    rec = new_record();
711    Dmsg1(130, "session_label record=%x\n", rec);
712    switch (label) {
713    case SOS_LABEL:
714       set_start_vol_position(dcr);
715       break;
716    case EOS_LABEL:
717       if (dev->is_tape()) {
718          dcr->EndBlock = dev->EndBlock;
719          dcr->EndFile  = dev->EndFile;
720       } else {
721          dcr->EndBlock = (uint32_t)dev->file_addr;
722          dcr->EndFile = (uint32_t)(dev->file_addr >> 32);
723       }
724       break;
725    default:
726       Jmsg1(jcr, M_ABORT, 0, _("Bad Volume session label = %d\n"), label);
727       break;
728    }
729    create_session_label(dcr, rec, label);
730    rec->FileIndex = label;
731
732    /*
733     * We guarantee that the session record can totally fit
734     *  into a block. If not, write the block, and put it in
735     *  the next block. Having the sesssion record totally in
736     *  one block makes reading them much easier (no need to
737     *  read the next block).
738     */
739    if (!can_write_record_to_block(block, rec)) {
740       Dmsg0(150, "Cannot write session label to block.\n");
741       if (!write_block_to_device(dcr)) {
742          Dmsg0(130, "Got session label write_block_to_dev error.\n");
743          free_record(rec);
744          return false;
745       }
746    }
747    if (!write_record_to_block(block, rec)) {
748       free_record(rec);
749       return false;
750    }
751
752    Dmsg6(150, "Write sesson_label record JobId=%d FI=%s SessId=%d Strm=%s len=%d "
753              "remainder=%d\n", jcr->JobId,
754       FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId,
755       stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len,
756       rec->remainder);
757
758    free_record(rec);
759    Dmsg2(150, "Leave write_session_label Block=%ud File=%ud\n",
760       dev->get_block_num(), dev->get_file());
761    return true;
762 }
763
764 /*  unser_volume_label
765  *
766  * Unserialize the Bacula Volume label into the device Volume_Label
767  * structure.
768  *
769  * Assumes that the record is already read.
770  *
771  * Returns: false on error
772  *          true  on success
773 */
774
775 bool unser_volume_label(DEVICE *dev, DEV_RECORD *rec)
776 {
777    ser_declare;
778    char buf1[100], buf2[100];
779
780    if (rec->FileIndex != VOL_LABEL && rec->FileIndex != PRE_LABEL) {
781       Mmsg3(dev->errmsg, _("Expecting Volume Label, got FI=%s Stream=%s len=%d\n"),
782               FI_to_ascii(buf1, rec->FileIndex),
783               stream_to_ascii(buf2, rec->Stream, rec->FileIndex),
784               rec->data_len);
785       if (!forge_on) {
786          return false;
787       }
788    }
789
790    dev->VolHdr.LabelType = rec->FileIndex;
791    dev->VolHdr.LabelSize = rec->data_len;
792
793
794    /* Unserialize the record into the Volume Header */
795    rec->data = check_pool_memory_size(rec->data, SER_LENGTH_Volume_Label);
796    ser_begin(rec->data, SER_LENGTH_Volume_Label);
797    unser_string(dev->VolHdr.Id);
798    unser_uint32(dev->VolHdr.VerNum);
799
800    if (dev->VolHdr.VerNum >= 11) {
801       unser_btime(dev->VolHdr.label_btime);
802       unser_btime(dev->VolHdr.write_btime);
803    } else { /* old way */
804       unser_float64(dev->VolHdr.label_date);
805       unser_float64(dev->VolHdr.label_time);
806    }
807    unser_float64(dev->VolHdr.write_date);    /* Unused with VerNum >= 11 */
808    unser_float64(dev->VolHdr.write_time);    /* Unused with VerNum >= 11 */
809
810    unser_string(dev->VolHdr.VolumeName);
811    unser_string(dev->VolHdr.PrevVolumeName);
812    unser_string(dev->VolHdr.PoolName);
813    unser_string(dev->VolHdr.PoolType);
814    unser_string(dev->VolHdr.MediaType);
815
816    unser_string(dev->VolHdr.HostName);
817    unser_string(dev->VolHdr.LabelProg);
818    unser_string(dev->VolHdr.ProgVersion);
819    unser_string(dev->VolHdr.ProgDate);
820
821    ser_end(rec->data, SER_LENGTH_Volume_Label);
822    Dmsg0(190, "unser_vol_label\n");
823    if (debug_level >= 190) {
824       dump_volume_label(dev);
825    }
826    return true;
827 }
828
829
830 bool unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec)
831 {
832    ser_declare;
833
834    rec->data = check_pool_memory_size(rec->data, SER_LENGTH_Session_Label);
835    unser_begin(rec->data, SER_LENGTH_Session_Label);
836    unser_string(label->Id);
837    unser_uint32(label->VerNum);
838    unser_uint32(label->JobId);
839    if (label->VerNum >= 11) {
840       unser_btime(label->write_btime);
841    } else {
842       unser_float64(label->write_date);
843    }
844    unser_float64(label->write_time);
845    unser_string(label->PoolName);
846    unser_string(label->PoolType);
847    unser_string(label->JobName);
848    unser_string(label->ClientName);
849    if (label->VerNum >= 10) {
850       unser_string(label->Job);          /* Unique name of this Job */
851       unser_string(label->FileSetName);
852       unser_uint32(label->JobType);
853       unser_uint32(label->JobLevel);
854    }
855    if (label->VerNum >= 11) {
856       unser_string(label->FileSetMD5);
857    } else {
858       label->FileSetMD5[0] = 0;
859    }
860    if (rec->FileIndex == EOS_LABEL) {
861       unser_uint32(label->JobFiles);
862       unser_uint64(label->JobBytes);
863       unser_uint32(label->StartBlock);
864       unser_uint32(label->EndBlock);
865       unser_uint32(label->StartFile);
866       unser_uint32(label->EndFile);
867       unser_uint32(label->JobErrors);
868       if (label->VerNum >= 11) {
869          unser_uint32(label->JobStatus);
870       } else {
871          label->JobStatus = JS_Terminated; /* kludge */
872       }
873    }
874    return true;
875 }
876
877 void dump_volume_label(DEVICE *dev)
878 {
879    int dbl = debug_level;
880    uint32_t File;
881    const char *LabelType;
882    char buf[30];
883    struct tm tm;
884    struct date_time dt;
885
886    debug_level = 1;
887    File = dev->file;
888    switch (dev->VolHdr.LabelType) {
889    case PRE_LABEL:
890       LabelType = "PRE_LABEL";
891       break;
892    case VOL_LABEL:
893       LabelType = "VOL_LABEL";
894       break;
895    case EOM_LABEL:
896       LabelType = "EOM_LABEL";
897       break;
898    case SOS_LABEL:
899       LabelType = "SOS_LABEL";
900       break;
901    case EOS_LABEL:
902       LabelType = "EOS_LABEL";
903       break;
904    case EOT_LABEL:
905       goto bail_out;
906    default:
907       LabelType = buf;
908       sprintf(buf, _("Unknown %d"), dev->VolHdr.LabelType);
909       break;
910    }
911
912    Pmsg11(-1, _("\nVolume Label:\n"
913 "Id                : %s"
914 "VerNo             : %d\n"
915 "VolName           : %s\n"
916 "PrevVolName       : %s\n"
917 "VolFile           : %d\n"
918 "LabelType         : %s\n"
919 "LabelSize         : %d\n"
920 "PoolName          : %s\n"
921 "MediaType         : %s\n"
922 "PoolType          : %s\n"
923 "HostName          : %s\n"
924 ""),
925              dev->VolHdr.Id, dev->VolHdr.VerNum,
926              dev->VolHdr.VolumeName, dev->VolHdr.PrevVolumeName,
927              File, LabelType, dev->VolHdr.LabelSize,
928              dev->VolHdr.PoolName, dev->VolHdr.MediaType,
929              dev->VolHdr.PoolType, dev->VolHdr.HostName);
930
931    if (dev->VolHdr.VerNum >= 11) {
932       char dt[50];
933       bstrftime(dt, sizeof(dt), btime_to_utime(dev->VolHdr.label_btime));
934       Pmsg1(-1, _("Date label written: %s\n"), dt);
935    } else {
936       dt.julian_day_number   = dev->VolHdr.label_date;
937       dt.julian_day_fraction = dev->VolHdr.label_time;
938       tm_decode(&dt, &tm);
939       Pmsg5(-1,
940             _("Date label written: %04d-%02d-%02d at %02d:%02d\n"),
941               tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min);
942    }
943
944 bail_out:
945    debug_level = dbl;
946 }
947
948
949 static void dump_session_label(DEV_RECORD *rec, const char *type)
950 {
951    int dbl;
952    struct date_time dt;
953    struct tm tm;
954    SESSION_LABEL label;
955    char ec1[30], ec2[30], ec3[30], ec4[30], ec5[30], ec6[30], ec7[30];
956
957    unser_session_label(&label, rec);
958    dbl = debug_level;
959    debug_level = 1;
960    Pmsg7(-1, _("\n%s Record:\n"
961 "JobId             : %d\n"
962 "VerNum            : %d\n"
963 "PoolName          : %s\n"
964 "PoolType          : %s\n"
965 "JobName           : %s\n"
966 "ClientName        : %s\n"
967 ""),    type, label.JobId, label.VerNum,
968       label.PoolName, label.PoolType,
969       label.JobName, label.ClientName);
970
971    if (label.VerNum >= 10) {
972       Pmsg4(-1, _(
973 "Job (unique name) : %s\n"
974 "FileSet           : %s\n"
975 "JobType           : %c\n"
976 "JobLevel          : %c\n"
977 ""), label.Job, label.FileSetName, label.JobType, label.JobLevel);
978    }
979
980    if (rec->FileIndex == EOS_LABEL) {
981       Pmsg8(-1, _(
982 "JobFiles          : %s\n"
983 "JobBytes          : %s\n"
984 "StartBlock        : %s\n"
985 "EndBlock          : %s\n"
986 "StartFile         : %s\n"
987 "EndFile           : %s\n"
988 "JobErrors         : %s\n"
989 "JobStatus         : %c\n"
990 ""),
991          edit_uint64_with_commas(label.JobFiles, ec1),
992          edit_uint64_with_commas(label.JobBytes, ec2),
993          edit_uint64_with_commas(label.StartBlock, ec3),
994          edit_uint64_with_commas(label.EndBlock, ec4),
995          edit_uint64_with_commas(label.StartFile, ec5),
996          edit_uint64_with_commas(label.EndFile, ec6),
997          edit_uint64_with_commas(label.JobErrors, ec7),
998          label.JobStatus);
999    }
1000    if (label.VerNum >= 11) {
1001       char dt[50];
1002       bstrftime(dt, sizeof(dt), btime_to_utime(label.write_btime));
1003       Pmsg1(-1, _("Date written      : %s\n"), dt);
1004    } else {
1005       dt.julian_day_number   = label.write_date;
1006       dt.julian_day_fraction = label.write_time;
1007       tm_decode(&dt, &tm);
1008       Pmsg5(-1, _("Date written      : %04d-%02d-%02d at %02d:%02d\n"),
1009       tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min);
1010    }
1011
1012    debug_level = dbl;
1013 }
1014
1015 void dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose)
1016 {
1017    const char *type;
1018    int dbl;
1019
1020    if (rec->FileIndex == 0 && rec->VolSessionId == 0 && rec->VolSessionTime == 0) {
1021       return;
1022    }
1023    dbl = debug_level;
1024    debug_level = 1;
1025    switch (rec->FileIndex) {
1026    case PRE_LABEL:
1027       type = _("Fresh Volume");
1028       break;
1029    case VOL_LABEL:
1030       type = _("Volume");
1031       break;
1032    case SOS_LABEL:
1033       type = _("Begin Job Session");
1034       break;
1035    case EOS_LABEL:
1036       type = _("End Job Session");
1037       break;
1038    case EOM_LABEL:
1039       type = _("End of Media");
1040       break;
1041    case EOT_LABEL:
1042       type = _("End of Tape");
1043       break;
1044    default:
1045       type = _("Unknown");
1046       break;
1047    }
1048    if (verbose) {
1049       switch (rec->FileIndex) {
1050       case PRE_LABEL:
1051       case VOL_LABEL:
1052          unser_volume_label(dev, rec);
1053          dump_volume_label(dev);
1054          break;
1055       case SOS_LABEL:
1056          dump_session_label(rec, type);
1057          break;
1058       case EOS_LABEL:
1059          dump_session_label(rec, type);
1060          break;
1061       case EOM_LABEL:
1062          Pmsg7(-1, _("%s Record: File:blk=%u:%u SessId=%d SessTime=%d JobId=%d DataLen=%d\n"),
1063             type, dev->file, dev->block_num, rec->VolSessionId, 
1064             rec->VolSessionTime, rec->Stream, rec->data_len);
1065          break;
1066       case EOT_LABEL:
1067          Pmsg0(-1, _("End of physical tape.\n"));
1068          break;
1069       default:
1070          Pmsg7(-1, _("%s Record: File:blk=%u:%u SessId=%d SessTime=%d JobId=%d DataLen=%d\n"),
1071             type, dev->file, dev->block_num, rec->VolSessionId, 
1072             rec->VolSessionTime, rec->Stream, rec->data_len);
1073          break;
1074       }
1075    } else {
1076       SESSION_LABEL label;
1077       char dt[50];
1078       switch (rec->FileIndex) {
1079       case SOS_LABEL:
1080          unser_session_label(&label, rec);
1081          bstrftimes(dt, sizeof(dt), btime_to_utime(label.write_btime));
1082          Pmsg6(-1, _("%s Record: File:blk=%u:%u SessId=%d SessTime=%d JobId=%d\n"),
1083             type, dev->file, dev->block_num, rec->VolSessionId, rec->VolSessionTime, label.JobId);
1084          Pmsg4(-1, _("   Job=%s Date=%s Level=%c Type=%c\n"),
1085             label.Job, dt, label.JobLevel, label.JobType);
1086          break;
1087       case EOS_LABEL:
1088          char ed1[30], ed2[30];
1089          unser_session_label(&label, rec);
1090          bstrftimes(dt, sizeof(dt), btime_to_utime(label.write_btime));
1091          Pmsg6(-1, _("%s Record: File:blk=%u:%u SessId=%d SessTime=%d JobId=%d\n"),
1092             type, dev->file, dev->block_num, rec->VolSessionId, rec->VolSessionTime, label.JobId);
1093          Pmsg7(-1, _("   Date=%s Level=%c Type=%c Files=%s Bytes=%s Errors=%d Status=%c\n"),
1094             dt, label.JobLevel, label.JobType,
1095             edit_uint64_with_commas(label.JobFiles, ed1),
1096             edit_uint64_with_commas(label.JobBytes, ed2),
1097             label.JobErrors, (char)label.JobStatus);
1098          break;
1099       case EOM_LABEL:
1100       case PRE_LABEL:
1101       case VOL_LABEL:
1102       default:
1103          Pmsg7(-1, _("%s Record: File:blk=%u:%u SessId=%d SessTime=%d JobId=%d DataLen=%d\n"),
1104             type, dev->file, dev->block_num, rec->VolSessionId, rec->VolSessionTime, 
1105             rec->Stream, rec->data_len);
1106          break;
1107       case EOT_LABEL:
1108          break;
1109       }
1110    }
1111    debug_level = dbl;
1112 }