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