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