]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/label.c
Change some debug levels
[bacula/bacula] / bacula / src / stored / label.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2007 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 plus additions
11    that are listed 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   
123   want_ansi_label = dcr->VolCatInfo.LabelType != B_BACULA_LABEL ||
124                     dcr->device->label_type != B_BACULA_LABEL;
125   if (want_ansi_label || dev->has_cap(CAP_CHECKLABELS)) {
126       stat = read_ansi_ibm_label(dcr);            
127       /* If we want a label and didn't find it, return error */
128       if (want_ansi_label && stat != VOL_OK) {
129          goto bail_out;
130       }
131       if (stat == VOL_NAME_ERROR || stat == VOL_LABEL_ERROR) {
132          Mmsg(jcr->errmsg, _("Wrong Volume mounted on device %s: Wanted %s have %s\n"),
133               dev->print_name(), VolName, dev->VolHdr.VolumeName);
134          if (!dev->poll && jcr->label_errors++ > 100) {
135             Jmsg(jcr, M_FATAL, 0, _("Too many tries: %s"), jcr->errmsg);
136          }
137          goto bail_out;
138       }
139       if (stat != VOL_OK) {           /* Not an ANSI/IBM label, so re-read */
140          dev->rewind(dcr);
141       } else {
142          have_ansi_label = true;
143       }
144    }
145   
146    /* Read the Bacula Volume label block */
147    record = new_record();
148    empty_block(block);
149
150    Dmsg0(130, "Big if statement in read_volume_label\n");
151    if (!read_block_from_dev(dcr, NO_BLOCK_NUMBER_CHECK)) {
152       Mmsg(jcr->errmsg, _("Requested Volume \"%s\" on %s is not a Bacula "
153            "labeled Volume, because: ERR=%s"), NPRT(VolName), 
154            dev->print_name(), dev->print_errmsg());
155       Dmsg1(130, "%s", jcr->errmsg);
156    } else if (!read_record_from_block(dcr, block, record)) {
157       Mmsg(jcr->errmsg, _("Could not read Volume label from block.\n"));
158       Dmsg1(130, "%s", jcr->errmsg);
159    } else if (!unser_volume_label(dev, record)) {
160       Mmsg(jcr->errmsg, _("Could not unserialize Volume label: ERR=%s\n"),
161          dev->print_errmsg());
162       Dmsg1(130, "%s", jcr->errmsg);
163    } else if (strcmp(dev->VolHdr.Id, BaculaId) != 0 &&
164               strcmp(dev->VolHdr.Id, OldBaculaId) != 0) {
165       Mmsg(jcr->errmsg, _("Volume Header Id bad: %s\n"), dev->VolHdr.Id);
166       Dmsg1(130, "%s", jcr->errmsg);
167    } else {
168       ok = true;
169    }
170    free_record(record);               /* finished reading Volume record */
171
172    if (!ok) {
173       if (forge_on || jcr->ignore_label_errors) {
174          dev->set_labeled();         /* set has Bacula label */
175          Jmsg(jcr, M_ERROR, 0, "%s", jcr->errmsg);
176          empty_block(block);
177          return VOL_OK;
178       }
179       Dmsg0(100, "No volume label - bailing out\n");
180       stat = VOL_NO_LABEL;
181       goto bail_out;
182    }
183
184    /* At this point, we have read the first Bacula block, and
185     * then read the Bacula Volume label. Now we need to
186     * make sure we have the right Volume.
187     */
188
189
190    if (dev->VolHdr.VerNum != BaculaTapeVersion &&
191        dev->VolHdr.VerNum != OldCompatibleBaculaTapeVersion1 &&
192        dev->VolHdr.VerNum != OldCompatibleBaculaTapeVersion2) {
193       Mmsg(jcr->errmsg, _("Volume on %s has wrong Bacula version. Wanted %d got %d\n"),
194          dev->print_name(), BaculaTapeVersion, dev->VolHdr.VerNum);
195       Dmsg1(130, "VOL_VERSION_ERROR: %s", jcr->errmsg);
196       stat = VOL_VERSION_ERROR;
197       goto bail_out;
198    }
199
200    /* We are looking for either an unused Bacula tape (PRE_LABEL) or
201     * a Bacula volume label (VOL_LABEL)
202     */
203    if (dev->VolHdr.LabelType != PRE_LABEL && dev->VolHdr.LabelType != VOL_LABEL) {
204       Mmsg(jcr->errmsg, _("Volume on %s has bad Bacula label type: %x\n"),
205           dev->print_name(), dev->VolHdr.LabelType);
206       Dmsg1(130, "%s", jcr->errmsg);
207       if (!dev->poll && jcr->label_errors++ > 100) {
208          Jmsg(jcr, M_FATAL, 0, _("Too many tries: %s"), jcr->errmsg);
209       }
210       Dmsg0(150, "return VOL_LABEL_ERROR\n");
211       stat = VOL_LABEL_ERROR;
212       goto bail_out;
213    }
214
215    dev->set_labeled();               /* set has Bacula label */
216    if (reserve_volume(dcr, dev->VolHdr.VolumeName) == NULL) {
217       Mmsg2(jcr->errmsg, _("Could not reserve volume %s on %s\n"),
218            dev->VolHdr.VolumeName, dev->print_name());
219       stat = VOL_NAME_ERROR;
220       goto bail_out;
221    }
222
223    /* Compare Volume Names */
224    Dmsg2(130, "Compare Vol names: VolName=%s hdr=%s\n", VolName?VolName:"*", dev->VolHdr.VolumeName);
225    if (VolName && *VolName && *VolName != '*' && strcmp(dev->VolHdr.VolumeName, VolName) != 0) {
226       Mmsg(jcr->errmsg, _("Wrong Volume mounted on device %s: Wanted %s have %s\n"),
227            dev->print_name(), VolName, dev->VolHdr.VolumeName);
228       Dmsg1(130, "%s", jcr->errmsg);
229       /*
230        * Cancel Job if too many label errors
231        *  => we are in a loop
232        */
233       if (!dev->poll && jcr->label_errors++ > 100) {
234          Jmsg(jcr, M_FATAL, 0, "Too many tries: %s", jcr->errmsg);
235       }
236       Dmsg0(150, "return VOL_NAME_ERROR\n");
237       stat = VOL_NAME_ERROR;
238       goto bail_out;
239    }
240    Dmsg1(130, "Copy vol_name=%s\n", dev->VolHdr.VolumeName);
241
242    if (debug_level >= 10) {
243       dump_volume_label(dev);
244    }
245    Dmsg0(130, "Leave read_volume_label() VOL_OK\n");
246    /* If we are a streaming device, we only get one chance to read */
247    if (!dev->has_cap(CAP_STREAM)) {
248       dev->rewind(dcr);
249       if (have_ansi_label) {
250          stat = read_ansi_ibm_label(dcr);            
251          /* If we want a label and didn't find it, return error */
252          if (stat != VOL_OK) {
253             goto bail_out;
254          }
255       }
256    }
257    empty_block(block);
258    return VOL_OK;
259
260 bail_out:
261    empty_block(block);
262    dev->rewind(dcr);
263    Dmsg1(150, "return %d\n", stat);
264    return stat;
265 }
266
267 /*
268  * Put a volume label into the block
269  *
270  *  Returns: false on failure
271  *           true  on success
272  */
273 bool write_volume_label_to_block(DCR *dcr)
274 {
275    DEV_RECORD rec;
276    DEVICE *dev = dcr->dev;
277    JCR *jcr = dcr->jcr;
278    DEV_BLOCK *block = dcr->block;
279
280    Dmsg0(130, "write Label in write_volume_label_to_block()\n");
281    memset(&rec, 0, sizeof(rec));
282    rec.data = get_memory(SER_LENGTH_Volume_Label);
283    empty_block(block);                /* Volume label always at beginning */
284
285    create_volume_label_record(dcr, &rec);
286
287    block->BlockNumber = 0;
288    if (!write_record_to_block(block, &rec)) {
289       free_pool_memory(rec.data);
290       Jmsg1(jcr, M_FATAL, 0, _("Cannot write Volume label to block for device %s\n"),
291          dev->print_name());
292       return false;
293    } else {
294       Dmsg1(130, "Wrote label of %d bytes to block\n", rec.data_len);
295    }
296    free_pool_memory(rec.data);
297    return true;
298 }
299
300
301 /*
302  * Write a Volume Label
303  *  !!! Note, this is ONLY used for writing
304  *            a fresh volume label.  Any data
305  *            after the label will be destroyed,
306  *            in fact, we write the label 5 times !!!!
307  *
308  *  This routine should be used only when labeling a blank tape.
309  */
310 bool write_new_volume_label_to_dev(DCR *dcr, const char *VolName, 
311                                    const char *PoolName, bool relabel, bool dvdnow)
312 {
313    DEVICE *dev = dcr->dev;
314
315
316    Dmsg0(150, "write_volume_label()\n");
317    empty_block(dcr->block);
318
319    /* If relabeling, truncate the device */
320    if (relabel && !dev->truncate(dcr)) {
321       goto bail_out;
322    }
323
324    if (relabel && !dev->is_tape()) {
325       dev->close_part(dcr);              /* make sure DVD/file closed for rename */
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    /* Create PRE_LABEL or VOL_LABEL if DVD */
348    create_volume_label(dev, VolName, PoolName, dvdnow);
349
350    /*
351     * If we have already detected an ANSI label, re-read it
352     *   to skip past it. Otherwise, we write a new one if 
353     *   so requested.  
354     */
355    if (dev->label_type != B_BACULA_LABEL) {
356       if (read_ansi_ibm_label(dcr) != VOL_OK) {
357          dev->rewind(dcr);
358          goto bail_out;
359       }
360    } else if (!write_ansi_ibm_labels(dcr, ANSI_VOL_LABEL, VolName)) {
361       goto bail_out;
362    }
363
364    create_volume_label_record(dcr, dcr->rec);
365    dcr->rec->Stream = 0;
366
367    /* Temporarily mark in append state to enable writing */
368    dev->set_append();
369    if (!write_record_to_block(dcr->block, dcr->rec)) {
370       Dmsg2(130, "Bad Label write on %s: ERR=%s\n", dev->print_name(), dev->print_errmsg());
371       goto bail_out;
372    } else {
373       Dmsg2(130, "Wrote label of %d bytes to %s\n", dcr->rec->data_len, dev->print_name());
374    }
375
376    Dmsg0(130, "Call write_block_to_dev()\n");
377    if (!write_block_to_dev(dcr)) {
378       Dmsg2(130, "Bad Label write on %s: ERR=%s\n", dev->print_name(), dev->print_errmsg());
379       goto bail_out;
380    }
381
382    /* Now commit block to DVD if we should write now */
383    if (dev->is_dvd() && dvdnow) {
384       Dmsg1(150, "New VolName=%s\n", dev->VolCatInfo.VolCatName);
385       if (!dvd_write_part(dcr)) {
386          Dmsg2(130, "Bad DVD write on %s: ERR=%s\n", dev->print_name(), dev->print_errmsg());
387          goto bail_out;
388       }
389    }
390
391    Dmsg0(130, " Wrote block to device\n");
392
393    if (dev->weof(1)) {
394       dev->set_labeled();
395       write_ansi_ibm_labels(dcr, ANSI_EOF_LABEL, dev->VolHdr.VolumeName);
396    }
397
398    if (debug_level >= 20)  {
399       dump_volume_label(dev);
400    }
401    if (reserve_volume(dcr, VolName) == NULL) {
402       Mmsg2(dcr->jcr->errmsg, _("Could not reserve volume %s on %s\n"),
403            dev->VolHdr.VolumeName, dev->print_name());
404       goto bail_out;
405    }
406
407    dev->clear_append();               /* remove append since this is PRE_LABEL */
408    return true;
409
410 bail_out:
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;
419  *  Returns: true if OK
420  *           false if unable to write it
421  */
422 bool rewrite_volume_label(DCR *dcr, bool recycle)
423 {
424    DEVICE *dev = dcr->dev;
425    JCR *jcr = dcr->jcr;
426
427    if (dev->open(dcr, OPEN_READ_WRITE) < 0) {
428       return false;
429    }
430    Dmsg2(190, "set append found freshly labeled volume. fd=%d dev=%x\n", dev->fd(), dev);
431    dev->VolHdr.LabelType = VOL_LABEL; /* set Volume label */
432    dev->set_append();
433    if (!write_volume_label_to_block(dcr)) {
434       Dmsg0(200, "Error from write volume label.\n");
435       return false;
436    }
437
438    dev->VolCatInfo.VolCatBytes = 0;        /* reset byte count */
439
440    /*
441     * If we are not dealing with a streaming device,
442     *  write the block now to ensure we have write permission.
443     *  It is better to find out now rather than later.
444     * We do not write the block now if this is an ANSI label. This
445     *  avoids re-writing the ANSI label, which we do not want to do.
446     */
447    if (!dev->has_cap(CAP_STREAM)) {
448       if (!dev->rewind(dcr)) {
449          Jmsg2(jcr, M_FATAL, 0, _("Rewind error on device %s: ERR=%s\n"),
450                dev->print_name(), dev->print_errmsg());
451          return false;
452       }
453       if (recycle) {
454          if (!dev->truncate(dcr)) {
455             Jmsg2(jcr, M_FATAL, 0, _("Truncate error on device %s: ERR=%s\n"),
456                   dev->print_name(), dev->print_errmsg());
457             return false;
458          }
459          if (dev->open(dcr, OPEN_READ_WRITE) < 0) {
460             Jmsg2(jcr, M_FATAL, 0,
461                _("Failed to re-open DVD after truncate on device %s: ERR=%s\n"),
462                dev->print_name(), dev->print_errmsg());
463             return false;
464          }
465       }
466
467       /*
468        * If we have already detected an ANSI label, re-read it
469        *   to skip past it. Otherwise, we write a new one if 
470        *   so requested.  
471        */
472       if (dev->label_type != B_BACULA_LABEL) {
473          if (read_ansi_ibm_label(dcr) != VOL_OK) {
474             dev->rewind(dcr);
475             return false;
476          }
477       } else if (!write_ansi_ibm_labels(dcr, ANSI_VOL_LABEL, dev->VolHdr.VolumeName)) {
478          return false;
479       }
480
481       /* Attempt write to check write permission */
482       Dmsg1(200, "Attempt to write to device fd=%d.\n", dev->fd());
483       if (!write_block_to_dev(dcr)) {
484          Jmsg2(jcr, M_ERROR, 0, _("Unable to write device %s: ERR=%s\n"),
485             dev->print_name(), dev->print_errmsg());
486          Dmsg0(200, "===ERROR write block to dev\n");
487          return false;
488       }
489    }
490    dev->set_labeled();
491    /* Set or reset Volume statistics */
492    dev->VolCatInfo.VolCatJobs = 0;
493    dev->VolCatInfo.VolCatFiles = 0;
494    dev->VolCatInfo.VolCatErrors = 0;
495    dev->VolCatInfo.VolCatBlocks = 0;
496    dev->VolCatInfo.VolCatRBytes = 0;
497    if (recycle) {
498       dev->VolCatInfo.VolCatMounts++;
499       dev->VolCatInfo.VolCatRecycles++;
500    } else {
501       dev->VolCatInfo.VolCatMounts = 1;
502       dev->VolCatInfo.VolCatRecycles = 0;
503       dev->VolCatInfo.VolCatWrites = 1;
504       dev->VolCatInfo.VolCatReads = 1;
505    }
506    Dmsg0(150, "dir_update_vol_info. Set Append\n");
507    bstrncpy(dev->VolCatInfo.VolCatStatus, "Append", sizeof(dev->VolCatInfo.VolCatStatus));
508    if (!dir_update_volume_info(dcr, true)) {  /* indicate doing relabel */
509       return false;
510    }
511    if (recycle) {
512       Jmsg(jcr, M_INFO, 0, _("Recycled volume \"%s\" on device %s, all previous data lost.\n"),
513          dcr->VolumeName, dev->print_name());
514    } else {
515       Jmsg(jcr, M_INFO, 0, _("Wrote label to prelabeled Volume \"%s\" on device %s\n"),
516          dcr->VolumeName, dev->print_name());
517    }
518    /*
519     * End writing real Volume label (from pre-labeled tape), or recycling
520     *  the volume.
521     */
522    Dmsg0(200, "OK from rewrite vol label.\n");
523    return true;
524 }
525
526
527 /*
528  *  create_volume_label_record
529  *   Serialize label (from dev->VolHdr structure) into device record.
530  *   Assumes that the dev->VolHdr structure is properly
531  *   initialized.
532 */
533 static void create_volume_label_record(DCR *dcr, DEV_RECORD *rec)
534 {
535    ser_declare;
536    struct date_time dt;
537    DEVICE *dev = dcr->dev;
538    JCR *jcr = dcr->jcr;
539    char buf[100];
540
541    /* Serialize the label into the device record. */
542
543    rec->data = check_pool_memory_size(rec->data, SER_LENGTH_Volume_Label);
544    ser_begin(rec->data, SER_LENGTH_Volume_Label);
545    ser_string(dev->VolHdr.Id);
546
547    ser_uint32(dev->VolHdr.VerNum);
548
549    if (dev->VolHdr.VerNum >= 11) {
550       ser_btime(dev->VolHdr.label_btime);
551       dev->VolHdr.write_btime = get_current_btime();
552       ser_btime(dev->VolHdr.write_btime);
553       dev->VolHdr.write_date = 0;
554       dev->VolHdr.write_time = 0;
555    } else {
556       /* OLD WAY DEPRECATED */
557       ser_float64(dev->VolHdr.label_date);
558       ser_float64(dev->VolHdr.label_time);
559       get_current_time(&dt);
560       dev->VolHdr.write_date = dt.julian_day_number;
561       dev->VolHdr.write_time = dt.julian_day_fraction;
562    }
563    ser_float64(dev->VolHdr.write_date);   /* 0 if VerNum >= 11 */
564    ser_float64(dev->VolHdr.write_time);   /* 0  if VerNum >= 11 */
565
566    ser_string(dev->VolHdr.VolumeName);
567    ser_string(dev->VolHdr.PrevVolumeName);
568    ser_string(dev->VolHdr.PoolName);
569    ser_string(dev->VolHdr.PoolType);
570    ser_string(dev->VolHdr.MediaType);
571
572    ser_string(dev->VolHdr.HostName);
573    ser_string(dev->VolHdr.LabelProg);
574    ser_string(dev->VolHdr.ProgVersion);
575    ser_string(dev->VolHdr.ProgDate);
576
577    ser_end(rec->data, SER_LENGTH_Volume_Label);
578    rec->data_len = ser_length(rec->data);
579    rec->FileIndex = dev->VolHdr.LabelType;
580    rec->VolSessionId = jcr->VolSessionId;
581    rec->VolSessionTime = jcr->VolSessionTime;
582    rec->Stream = jcr->NumWriteVolumes;
583    Dmsg2(150, "Created Vol label rec: FI=%s len=%d\n", FI_to_ascii(buf, rec->FileIndex),
584       rec->data_len);
585 }
586
587
588 /*
589  * Create a volume label in memory
590  */
591 void create_volume_label(DEVICE *dev, const char *VolName, 
592                          const char *PoolName, bool dvdnow)
593 {
594    DEVRES *device = (DEVRES *)dev->device;
595
596    Dmsg0(130, "Start create_volume_label()\n");
597
598    ASSERT(dev != NULL);
599
600    dev->clear_volhdr();          /* release any old volume */
601
602    bstrncpy(dev->VolHdr.Id, BaculaId, sizeof(dev->VolHdr.Id));
603    dev->VolHdr.VerNum = BaculaTapeVersion;
604    if (dev->is_dvd() && dvdnow) {
605       /* We do not want to re-label a DVD so write VOL_LABEL now */
606       dev->VolHdr.LabelType = VOL_LABEL;
607    } else {
608       dev->VolHdr.LabelType = PRE_LABEL;  /* Mark tape as unused */
609    }
610    bstrncpy(dev->VolHdr.VolumeName, VolName, sizeof(dev->VolHdr.VolumeName));
611    bstrncpy(dev->VolHdr.PoolName, PoolName, sizeof(dev->VolHdr.PoolName));
612    bstrncpy(dev->VolHdr.MediaType, device->media_type, sizeof(dev->VolHdr.MediaType));
613
614    bstrncpy(dev->VolHdr.PoolType, "Backup", sizeof(dev->VolHdr.PoolType));
615
616    dev->VolHdr.label_btime = get_current_btime();
617    dev->VolHdr.label_date = 0;
618    dev->VolHdr.label_time = 0;
619
620    if (gethostname(dev->VolHdr.HostName, sizeof(dev->VolHdr.HostName)) != 0) {
621       dev->VolHdr.HostName[0] = 0;
622    }
623    bstrncpy(dev->VolHdr.LabelProg, my_name, sizeof(dev->VolHdr.LabelProg));
624    sprintf(dev->VolHdr.ProgVersion, "Ver. %s %s", VERSION, BDATE);
625    sprintf(dev->VolHdr.ProgDate, "Build %s %s", __DATE__, __TIME__);
626    dev->set_labeled();               /* set has Bacula label */
627    if (debug_level >= 90) {
628       dump_volume_label(dev);
629    }
630 }
631
632 /*
633  * Create session label
634  *  The pool memory must be released by the calling program
635  */
636 void create_session_label(DCR *dcr, DEV_RECORD *rec, int label)
637 {
638    JCR *jcr = dcr->jcr;
639    ser_declare;
640
641    rec->VolSessionId   = jcr->VolSessionId;
642    rec->VolSessionTime = jcr->VolSessionTime;
643    rec->Stream         = jcr->JobId;
644
645    rec->data = check_pool_memory_size(rec->data, SER_LENGTH_Session_Label);
646    ser_begin(rec->data, SER_LENGTH_Session_Label);
647    ser_string(BaculaId);
648    ser_uint32(BaculaTapeVersion);
649
650    ser_uint32(jcr->JobId);
651
652    /* Changed in VerNum 11 */
653    ser_btime(get_current_btime());
654    ser_float64(0);
655
656    ser_string(dcr->pool_name);
657    ser_string(dcr->pool_type);
658    ser_string(jcr->job_name);         /* base Job name */
659    ser_string(jcr->client_name);
660
661    /* Added in VerNum 10 */
662    ser_string(jcr->Job);              /* Unique name of this Job */
663    ser_string(jcr->fileset_name);
664    ser_uint32(jcr->JobType);
665    ser_uint32(jcr->JobLevel);
666    /* Added in VerNum 11 */
667    ser_string(jcr->fileset_md5);
668
669    if (label == EOS_LABEL) {
670       ser_uint32(jcr->JobFiles);
671       ser_uint64(jcr->JobBytes);
672       ser_uint32(dcr->StartBlock);
673       ser_uint32(dcr->EndBlock);
674       ser_uint32(dcr->StartFile);
675       ser_uint32(dcr->EndFile);
676       ser_uint32(jcr->JobErrors);
677
678       /* Added in VerNum 11 */
679       ser_uint32(jcr->JobStatus);
680    }
681    ser_end(rec->data, SER_LENGTH_Session_Label);
682    rec->data_len = ser_length(rec->data);
683 }
684
685 /* Write session label
686  *  Returns: false on failure
687  *           true  on success
688  */
689 bool write_session_label(DCR *dcr, int label)
690 {
691    JCR *jcr = dcr->jcr;
692    DEVICE *dev = dcr->dev;
693    DEV_RECORD *rec;
694    DEV_BLOCK *block = dcr->block;
695    char buf1[100], buf2[100];
696
697    rec = new_record();
698    Dmsg1(130, "session_label record=%x\n", rec);
699    switch (label) {
700    case SOS_LABEL:
701       if (dev->is_tape()) {
702          dcr->StartBlock = dev->block_num;
703          dcr->StartFile  = dev->file;
704       } else {
705          dcr->StartBlock = (uint32_t)dev->file_addr;
706          dcr->StartFile = (uint32_t)(dev->file_addr >> 32);
707       }
708       break;
709    case EOS_LABEL:
710       if (dev->is_tape()) {
711          dcr->EndBlock = dev->EndBlock;
712          dcr->EndFile  = dev->EndFile;
713       } else {
714          dcr->EndBlock = (uint32_t)dev->file_addr;
715          dcr->EndFile = (uint32_t)(dev->file_addr >> 32);
716       }
717       break;
718    default:
719       Jmsg1(jcr, M_ABORT, 0, _("Bad session label = %d\n"), label);
720       break;
721    }
722    create_session_label(dcr, rec, label);
723    rec->FileIndex = label;
724
725    /*
726     * We guarantee that the session record can totally fit
727     *  into a block. If not, write the block, and put it in
728     *  the next block. Having the sesssion record totally in
729     *  one block makes reading them much easier (no need to
730     *  read the next block).
731     */
732    if (!can_write_record_to_block(block, rec)) {
733       Dmsg0(150, "Cannot write session label to block.\n");
734       if (!write_block_to_device(dcr)) {
735          Dmsg0(130, "Got session label write_block_to_dev error.\n");
736          /* ****FIXME***** errno is not set here */
737          Jmsg(jcr, M_FATAL, 0, _("Error writing Session label to %s: %s\n"),
738                            dev_vol_name(dev), strerror(errno));
739          free_record(rec);
740          return false;
741       }
742    }
743    if (!write_record_to_block(block, rec)) {
744       Jmsg(jcr, M_FATAL, 0, _("Error writing Session label to %s: %s\n"),
745                         dev_vol_name(dev), strerror(errno));
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(), 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_unix(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_unix(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_unix(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_unix(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 }