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