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