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