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