]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/btape.c
btape + doc updates for fixed block devices
[bacula/bacula] / bacula / src / stored / btape.c
1 /*
2  *
3  *   Bacula Tape manipulation program
4  *
5  *    Has various tape manipulation commands -- mostly for
6  *    use in determining how tapes really work.
7  *
8  *     Kern Sibbald, April MM
9  *
10  *   Note, this program reads stored.conf, and will only
11  *     talk to devices that are configured.
12  *
13  *   Version $Id$
14  *
15  */
16 /*
17    Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
18
19    This program is free software; you can redistribute it and/or
20    modify it under the terms of the GNU General Public License as
21    published by the Free Software Foundation; either version 2 of
22    the License, or (at your option) any later version.
23
24    This program is distributed in the hope that it will be useful,
25    but WITHOUT ANY WARRANTY; without even the implied warranty of
26    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27    General Public License for more details.
28
29    You should have received a copy of the GNU General Public
30    License along with this program; if not, write to the Free
31    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
32    MA 02111-1307, USA.
33
34  */
35
36 #include "bacula.h"
37 #include "stored.h"
38
39
40 /* External subroutines */
41 extern void free_config_resources();
42
43 /* Exported variables */
44 int quit = 0;
45 char buf[100000];
46 int bsize = TAPE_BSIZE;
47 char VolName[100];
48
49 DEVICE *dev = NULL;
50 DEVRES *device = NULL;
51
52             
53 /* Forward referenced subroutines */
54 static void do_tape_cmds();
55 static void helpcmd();
56 static void scancmd();
57 static void rewindcmd();
58 static void clearcmd();
59 static void wrcmd();
60 static void eodcmd();
61 static void fillcmd();
62 static void unfillcmd();
63 static int flush_block(DEV_BLOCK *block, int dump);
64 static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec);
65 static int my_mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
66 static void scan_blocks();
67
68
69 /* Static variables */
70 #define CONFIG_FILE "bacula-sd.conf"
71 char *configfile;
72
73 static BSR *bsr = NULL;
74 static char cmd[1000];
75 static int signals = TRUE;
76 static int ok;
77 static int stop;
78 static uint64_t vol_size;
79 static uint64_t VolBytes;
80 static time_t now;
81 static double kbs;
82 static long file_index;
83 static int verbose = 0;
84 static int end_of_tape = 0;
85 static uint32_t LastBlock = 0;
86 static uint32_t eot_block;
87 static uint32_t eot_block_len;
88 static uint32_t eot_FileIndex;
89 static int dumped = 0;
90
91 static char *VolumeName = NULL;
92
93 static JCR *jcr = NULL;
94
95
96 static void usage();
97 static void terminate_btape(int sig);
98 int get_cmd(char *prompt);
99
100
101 int write_dev(DEVICE *dev, char *buf, size_t len) 
102 {
103    Emsg0(M_ABORT, 0, "write_dev not implemented.\n");
104    return 0;
105 }
106
107 int read_dev(DEVICE *dev, char *buf, size_t len)
108 {
109    Emsg0(M_ABORT, 0, "read_dev not implemented.\n");
110    return 0;
111 }
112
113
114 /*********************************************************************
115  *
116  *         Main Bacula Pool Creation Program
117  *
118  */
119 int main(int argc, char *argv[])
120 {
121    int ch;
122    DEV_BLOCK *block;
123
124    /* Sanity checks */
125    if (TAPE_BSIZE % DEV_BSIZE != 0 || TAPE_BSIZE / DEV_BSIZE == 0) {
126       Emsg2(M_ABORT, 0, "Tape block size (%d) not multiple of system size (%d)\n",
127          TAPE_BSIZE, DEV_BSIZE);
128    }
129    if (TAPE_BSIZE != (1 << (ffs(TAPE_BSIZE)-1))) {
130       Emsg1(M_ABORT, 0, "Tape block size (%d) is not a power of 2\n", TAPE_BSIZE);
131    }
132
133    printf("Tape block granularity is %d bytes.\n", TAPE_BSIZE);
134
135    working_directory = "/tmp";
136    my_name_is(argc, argv, "btape");
137    init_msg(NULL, NULL);
138
139    while ((ch = getopt(argc, argv, "b:c:d:sv?")) != -1) {
140       switch (ch) {
141          case 'b':                    /* bootstrap file */
142             bsr = parse_bsr(NULL, optarg);
143 //          dump_bsr(bsr);
144             break;
145
146          case 'c':                    /* specify config file */
147             if (configfile != NULL) {
148                free(configfile);
149             }
150             configfile = bstrdup(optarg);
151             break;
152
153          case 'd':                    /* set debug level */
154             debug_level = atoi(optarg);
155             if (debug_level <= 0) {
156                debug_level = 1; 
157             }
158             break;
159
160          case 's':
161             signals = FALSE;
162             break;
163
164          case 'v':
165             verbose++;
166             break;
167
168          case '?':
169          default:
170             helpcmd();
171             exit(0);
172
173       }  
174    }
175    argc -= optind;
176    argv += optind;
177
178
179    
180    if (signals) {
181       init_signals(terminate_btape);
182    }
183
184    if (configfile == NULL) {
185       configfile = bstrdup(CONFIG_FILE);
186    }
187
188    daemon_start_time = time(NULL);
189
190    parse_config(configfile);
191
192
193    /* See if we can open a device */
194    if (argc == 0) {
195       Pmsg0(000, "No archive name specified.\n");
196       usage();
197       exit(1);
198    } else if (argc != 1) {
199       Pmsg0(000, "Improper number of arguments specified.\n");
200       usage();
201       exit(1);
202    }
203
204    jcr = setup_jcr("btape", argv[0], bsr);
205    dev = setup_to_access_device(jcr, 0);     /* acquire for write */
206    if (!dev) {
207       exit(1);
208    }
209    block = new_block(dev);
210    lock_device(dev);
211    if (!(dev->state & ST_OPENED)) {
212       Dmsg0(129, "Opening device.\n");
213       if (open_dev(dev, jcr->VolumeName, READ_WRITE) < 0) {
214          Emsg1(M_FATAL, 0, _("dev open failed: %s\n"), dev->errmsg);
215          unlock_device(dev);
216          free_block(block);
217          goto terminate;
218       }
219    }
220    Dmsg1(129, "open_dev %s OK\n", dev_name(dev));
221    unlock_device(dev);
222    free_block(block);
223
224    Dmsg0(200, "Do tape commands\n");
225    do_tape_cmds();
226   
227 terminate:
228    terminate_btape(0);
229    return 0;
230 }
231
232 static void terminate_btape(int stat)
233 {
234
235    sm_check(__FILE__, __LINE__, False);
236    if (configfile) {
237       free(configfile);
238    }
239    free_config_resources();
240
241    if (dev) {
242       term_dev(dev);
243    }
244
245    if (debug_level > 10)
246       print_memory_pool_stats(); 
247
248    free_jcr(jcr);
249    jcr = NULL;
250
251    if (bsr) {
252       free_bsr(bsr);
253    }
254
255    term_msg();
256    close_memory_pool();               /* free memory in pool */
257
258    sm_dump(False);
259    exit(stat);
260 }
261
262 void quitcmd()
263 {
264    quit = 1;
265 }
266
267 /*
268  * Write a label to the tape   
269  */
270 static void labelcmd()
271 {
272    DEVRES *device;
273    int found = 0;
274
275    LockRes();
276    for (device=NULL; (device=(DEVRES *)GetNextRes(R_DEVICE, (RES *)device)); ) {
277       if (strcmp(device->device_name, dev->dev_name) == 0) {
278          jcr->device = device;        /* Arggg a bit of duplication here */
279          device->dev = dev;
280          dev->device = device;
281          found = 1;
282          break;
283       }
284    } 
285    UnlockRes();
286    if (!found) {
287       Pmsg2(0, "Could not find device %s in %s\n", dev->dev_name, configfile);
288       return;
289    }
290
291    if (VolumeName) {
292       strcpy(cmd, VolumeName);
293    } else {
294       if (!get_cmd("Enter Volume Name: ")) {
295          return;
296       }
297    }
298          
299    if (!(dev->state & ST_OPENED)) {
300       if (!open_device(dev)) {
301          Pmsg1(0, "Device open failed. ERR=%s\n", strerror_dev(dev));
302       }
303    }
304    write_volume_label_to_dev(jcr, device, cmd, "Default");
305 }
306
307 /*
308  * Read the tape label   
309  */
310 static void readlabelcmd()
311 {
312    int save_debug_level = debug_level;
313    int stat;
314    DEV_BLOCK *block;
315
316    block = new_block(dev);
317    stat = read_dev_volume_label(jcr, dev, block);
318    switch (stat) {
319       case VOL_NO_LABEL:
320          Pmsg0(0, "Volume has no label.\n");
321          break;
322       case VOL_OK:
323          Pmsg0(0, "Volume label read correctly.\n");
324          break;
325       case VOL_IO_ERROR:
326          Pmsg1(0, "I/O error on device: ERR=%s", strerror_dev(dev));
327          break;
328       case VOL_NAME_ERROR:
329          Pmsg0(0, "Volume name error\n");
330          break;
331       case VOL_CREATE_ERROR:
332          Pmsg1(0, "Error creating label. ERR=%s", strerror_dev(dev));
333          break;
334       case VOL_VERSION_ERROR:
335          Pmsg0(0, "Volume version error.\n");
336          break;
337       case VOL_LABEL_ERROR:
338          Pmsg0(0, "Bad Volume label type.\n");
339          break;
340       default:
341          Pmsg0(0, "Unknown error.\n");
342          break;
343    }
344
345    debug_level = 20;
346    dump_volume_label(dev); 
347    debug_level = save_debug_level;
348    free_block(block);
349 }
350
351
352 /*
353  * Load the tape should have prevously been taken
354  * off line, otherwise this command is not necessary.
355  */
356 static void loadcmd()
357 {
358
359    if (!load_dev(dev)) {
360       Pmsg1(0, "Bad status from load. ERR=%s\n", strerror_dev(dev));
361    } else
362       Pmsg1(0, "Loaded %s\n", dev_name(dev));
363 }
364
365 /*
366  * Rewind the tape.   
367  */
368 static void rewindcmd()
369 {
370    if (!rewind_dev(dev)) {
371       Pmsg1(0, "Bad status from rewind. ERR=%s\n", strerror_dev(dev));
372       clrerror_dev(dev, -1);
373    } else {
374       Pmsg1(0, "Rewound %s\n", dev_name(dev));
375    }
376 }
377
378 /*
379  * Clear any tape error   
380  */
381 static void clearcmd()
382 {
383    clrerror_dev(dev, -1);
384 }
385
386 /*
387  * Write and end of file on the tape   
388  */
389 static void weofcmd()
390 {
391    int stat;
392
393    if ((stat = weof_dev(dev, 1)) < 0) {
394       Pmsg2(0, "Bad status from weof %d. ERR=%s\n", stat, strerror_dev(dev));
395       return;
396    } else {
397       Pmsg1(0, "Wrote EOF to %s\n", dev_name(dev));
398    }
399 }
400
401
402 /* Go to the end of the medium -- raw command   
403  * The idea was orginally that the end of the Bacula
404  * medium would be flagged differently. This is not
405  * currently the case. So, this is identical to the
406  * eodcmd().
407  */
408 static void eomcmd()
409 {
410    if (!eod_dev(dev)) {
411       Pmsg1(0, _("Bad status from eod. ERR=%s\n"), strerror_dev(dev));
412       return;
413    } else {
414       Pmsg0(0, _("Moved to end of media\n"));
415    }
416 }
417
418 /*
419  * Go to the end of the media (either hardware determined
420  *  or defined by two eofs.
421  */
422 static void eodcmd()
423 {
424    eomcmd();
425 }
426
427 /*
428  * Backspace file   
429  */
430 static void bsfcmd()
431 {
432    int stat;
433
434    if ((stat=bsf_dev(dev, 1)) < 0) {
435       Pmsg1(0, _("Bad status from bsf. ERR=%s\n"), strerror(errno));
436    } else {
437       Pmsg0(0, _("Back spaced one file.\n"));
438    }
439 }
440
441 /*
442  * Backspace record   
443  */
444 static void bsrcmd()
445 {
446    int stat;
447
448    if ((stat=bsr_dev(dev, 1)) < 0) {
449       Pmsg1(0, _("Bad status from bsr. ERR=%s\n"), strerror(errno));
450    } else {
451       Pmsg0(0, _("Back spaced one record.\n"));
452    }
453 }
454
455 /*
456  * List device capabilities as defined in the 
457  *  stored.conf file.
458  */
459 static void capcmd()
460 {
461    printf(_("Device capabilities:\n"));
462    printf("%sEOF ", dev->capabilities & CAP_EOF ? "" : "!");
463    printf("%sBSR ", dev->capabilities & CAP_BSR ? "" : "!");
464    printf("%sBSF ", dev->capabilities & CAP_BSF ? "" : "!");
465    printf("%sFSR ", dev->capabilities & CAP_FSR ? "" : "!");
466    printf("%sFSF ", dev->capabilities & CAP_FSF ? "" : "!");
467    printf("%sEOM ", dev->capabilities & CAP_EOM ? "" : "!");
468    printf("%sREM ", dev->capabilities & CAP_REM ? "" : "!");
469    printf("%sRACCESS ", dev->capabilities & CAP_RACCESS ? "" : "!");
470    printf("%sAUTOMOUNT ", dev->capabilities & CAP_AUTOMOUNT ? "" : "!");
471    printf("%sLABEL ", dev->capabilities & CAP_LABEL ? "" : "!");
472    printf("%sANONVOLS ", dev->capabilities & CAP_ANONVOLS ? "" : "!");
473    printf("%sALWAYSOPEN ", dev->capabilities & CAP_ALWAYSOPEN ? "" : "!");
474    printf("\n");
475
476    printf(_("Device status:\n"));
477    printf("%sOPENED ", dev->state & ST_OPENED ? "" : "!");
478    printf("%sTAPE ", dev->state & ST_TAPE ? "" : "!");
479    printf("%sLABEL ", dev->state & ST_LABEL ? "" : "!");
480    printf("%sMALLOC ", dev->state & ST_MALLOC ? "" : "!");
481    printf("%sAPPEND ", dev->state & ST_APPEND ? "" : "!");
482    printf("%sREAD ", dev->state & ST_READ ? "" : "!");
483    printf("%sEOT ", dev->state & ST_EOT ? "" : "!");
484    printf("%sWEOT ", dev->state & ST_WEOT ? "" : "!");
485    printf("%sEOF ", dev->state & ST_EOF ? "" : "!");
486    printf("%sNEXTVOL ", dev->state & ST_NEXTVOL ? "" : "!");
487    printf("%sSHORT ", dev->state & ST_SHORT ? "" : "!");
488    printf("\n");
489
490 }
491
492 /*
493  * Test writting larger and larger records.  
494  * This is a torture test for records.
495  */
496 static void rectestcmd()
497 {
498    DEV_BLOCK *block;
499    DEV_RECORD *rec;
500    int i, blkno = 0;
501
502    Pmsg0(0, "Test writting larger and larger records.\n\
503 This is a torture test for records.\nI am going to write\n\
504 larger and larger records. It will stop when the record size\n\
505 plus the header exceeds the block size (by default about 64K\n");
506
507
508    get_cmd("Do you want to continue? (y/n): ");
509    if (cmd[0] != 'y') {
510       Pmsg0(000, "Command aborted.\n");
511       return;
512    }
513
514    sm_check(__FILE__, __LINE__, False);
515    block = new_block(dev);
516    rec = new_record();
517
518    for (i=1; i<500000; i++) {
519       rec->data = check_pool_memory_size(rec->data, i);
520       memset(rec->data, i & 0xFF, i);
521       rec->data_len = i;
522       sm_check(__FILE__, __LINE__, False);
523       if (write_record_to_block(block, rec)) {
524          empty_block(block);
525          blkno++;
526          Pmsg2(0, "Block %d i=%d\n", blkno, i);
527       } else {
528          break;
529       }
530       sm_check(__FILE__, __LINE__, False);
531    }
532    free_record(rec);
533    free_block(block);
534    sm_check(__FILE__, __LINE__, False);
535 }
536
537 static int re_read_block_test()
538 {
539    DEV_BLOCK *block;
540    DEV_RECORD *rec;
541    int stat = 0;
542    int len;
543
544    if (!(dev->capabilities & CAP_EOM)) {
545       Pmsg0(-1, _("Skipping read backwards test because MT_EOM turned off.\n"));
546       return 0;
547    }
548
549    Pmsg0(-1, _("\nWrite, backup, and re-read test.\n\n"
550       "I'm going to write three records and two eof's\n"
551       "then backup over the eof's and re-read the last record.\n\n"));
552    rewindcmd();
553    block = new_block(dev);
554    rec = new_record();
555    rec->data = check_pool_memory_size(rec->data, block->buf_len);
556    len = rec->data_len = block->buf_len-100;
557    memset(rec->data, 1, rec->data_len);
558    if (!write_record_to_block(block, rec)) {
559       Pmsg0(0, _("Error writing record to block.\n")); 
560       goto bail_out;
561    }
562    if (!write_block_to_dev(jcr, dev, block)) {
563       Pmsg0(0, _("Error writing block to device.\n")); 
564       goto bail_out;
565    } else {
566       Pmsg1(0, _("Wrote first record of %d bytes.\n"), rec->data_len);
567    }
568    memset(rec->data, 2, rec->data_len);
569    if (!write_record_to_block(block, rec)) {
570       Pmsg0(0, _("Error writing record to block.\n")); 
571       goto bail_out;
572    }
573    if (!write_block_to_dev(jcr, dev, block)) {
574       Pmsg0(0, _("Error writing block to device.\n")); 
575       goto bail_out;
576    } else {
577       Pmsg1(0, _("Wrote second record of %d bytes.\n"), rec->data_len);
578    }
579    memset(rec->data, 3, rec->data_len);
580    if (!write_record_to_block(block, rec)) {
581       Pmsg0(0, _("Error writing record to block.\n")); 
582       goto bail_out;
583    }
584    if (!write_block_to_dev(jcr, dev, block)) {
585       Pmsg0(0, _("Error writing block to device.\n")); 
586       goto bail_out;
587    } else {
588       Pmsg1(0, _("Wrote fourth record of %d bytes.\n"), rec->data_len);
589    }
590    weofcmd();
591    weofcmd();
592    if (bsf_dev(dev, 1) != 0) {
593       Pmsg1(0, _("Back space file failed! ERR=%s\n"), strerror(dev->dev_errno));
594       goto bail_out;
595    }
596    if (bsf_dev(dev, 1) != 0) {
597       Pmsg1(0, _("Back space file failed! ERR=%s\n"), strerror(dev->dev_errno));
598       goto bail_out;
599    }
600    Pmsg0(0, "Backspaced over two EOFs OK.\n");
601    if (bsr_dev(dev, 1) != 0) {
602       Pmsg1(0, _("Back space record failed! ERR=%s\n"), strerror(dev->dev_errno));
603       goto bail_out;
604    }
605    Pmsg0(0, "Backspace record OK.\n");
606    if (!read_block_from_dev(dev, block)) {
607       Pmsg1(0, _("Read block failed! ERR=%s\n"), strerror(dev->dev_errno));
608       goto bail_out;
609    }
610    memset(rec->data, 0, rec->data_len);
611    if (!read_record_from_block(block, rec)) {
612       Pmsg1(0, _("Read block failed! ERR=%s\n"), strerror(dev->dev_errno));
613       goto bail_out;
614    }
615    for (int i=0; i<len; i++) {
616       if (rec->data[i] != 3) {
617          Pmsg0(0, _("Bad data in record. Test failed!\n"));
618          Pmsg0(0, _("You might try adding:\n\n"
619                "Hardware End of File = No\n\n"
620                "to your Storage daemon's Device resource definition.\n"));
621          goto bail_out;
622       }
623    }
624    Pmsg0(0, _("Re-read test succeeded!\n\n"));
625    stat = 1;
626
627 bail_out:
628    free_block(block);
629    free_record(rec);
630    return stat;
631 }
632
633 static int append_test()
634 {
635    Pmsg0(-1, _("\n\n=== Append files test. ===\n\n"
636 "I'm going to write one record  in file 0,\n"
637 "                   two records in file 1,\n"
638 "             and three records in file 2\n\n"));
639    rewindcmd();
640    wrcmd();
641    weofcmd();      /* end file 0 */
642    wrcmd();
643    wrcmd();
644    weofcmd();      /* end file 1 */
645    wrcmd();
646    wrcmd();
647    wrcmd();
648    weofcmd();     /* end file 2 */
649    rewindcmd();
650    Pmsg0(0, _("Now moving to end of media.\n"));
651    eodcmd();
652    Pmsg2(-1, _("End Append files test.\n\
653 We should be in file 3. I am at file %d. This is %s\n\n"), 
654       dev->file, dev->file == 3 ? "correct!" : "NOT correct!!!!");
655
656    if (dev->file != 3) {
657       Pmsg0(-1, _("To correct this problem, you might try adding:\n\n"
658             "Hardware End of Medium = No\n\n"
659             "to your Storage daemon's Device resource definition.\n"));
660       return 0;
661    }
662
663    Pmsg0(-1, _("\nNow I am going to attempt to append to the tape.\n"));
664    wrcmd(); 
665    weofcmd();
666    rewindcmd();
667    Pmsg0(0, _("Done writing, scanning results ...\n\n"));
668    scan_blocks();
669    Pmsg0(-1, _("End Append to the tape test.\n\
670 The above scan should have four files of:\n\
671 One record, two records, three records, and one record \n\
672 respectively each with 64,448 bytes.\n\n"));
673    Pmsg0(-1, _("If the above is not correct, you might try running Bacula\n"
674               "in fixed block mode by setting:\n\n"
675               "Minimum Block Size = nnn\n"
676               "Maximum Block Size = nnn\n\n"
677               "in your Storage daemon's Device definition.\n"
678               "nnn must match your tape driver's block size.\n"));
679
680    return 1;
681 }
682
683
684 /* 
685  * This is a general test of Bacula's functions
686  *   needed to read and write the tape.
687  */
688 static void testcmd()
689 {
690    re_read_block_test();
691
692    if (!append_test()) {
693       return;
694    }
695
696    Pmsg0(-1, "\n\n=== Append block test. ===\n\n\
697 I'm going to write a block, an EOF, rewind, go to EOM,\n\
698 then backspace over the EOF and attempt to append a second\n\
699 block in the first file.\n\n");
700    rewindcmd();
701    wrcmd();
702    weofcmd();
703    rewindcmd();
704    eodcmd();
705    Pmsg2(-1, _("We should be at file 1. I am at EOM File=%d. This is %s\n"),
706       dev->file, dev->file == 1 ? "correct!" : "NOT correct!!!!");
707    Pmsg0(0, "Doing backspace file.\n");
708    bsfcmd();
709    Pmsg0(0, _("Write second block, hoping to append to first file.\n"));
710    wrcmd();
711    weofcmd();
712    rewindcmd();
713    Pmsg0(0, _("Done writing, scanning results ...\n\n"));
714    scan_blocks();
715    Pmsg0(-1, _("\nThe above should have one file of two blocks 64,448 bytes each.\n"));
716 }
717
718
719 static void fsfcmd()
720 {
721    int stat;
722
723    if ((stat=fsf_dev(dev, 1)) < 0) {
724       Pmsg2(0, "Bad status from fsf %d. ERR=%s\n", stat, strerror_dev(dev));
725       return;
726    }
727    Pmsg0(0, "Forward spaced one file.\n");
728 }
729
730 static void fsrcmd()
731 {
732    int stat;
733
734    if ((stat=fsr_dev(dev, 1)) < 0) {
735       Pmsg2(0, "Bad status from fsr %d. ERR=%s\n", stat, strerror_dev(dev));
736       return;
737    }
738    Pmsg0(0, "Forward spaced one record.\n");
739 }
740
741 static void rdcmd()
742 {
743 #ifdef xxxxx
744    int stat;
745
746    if (!read_dev(dev, buf, 512*126)) {
747       Pmsg1(0, "Bad status from read. ERR=%s\n", strerror_dev(dev));
748       return;
749    }
750    Pmsg1(10, "Read %d bytes\n", stat);
751 #else
752    printf("Rdcmd no longer implemented.\n");
753 #endif
754 }
755
756
757 /*
758  * Write a Bacula block to the tape
759  */
760 static void wrcmd()
761 {
762    DEV_BLOCK *block;
763    DEV_RECORD *rec;
764    int i;
765
766    sm_check(__FILE__, __LINE__, False);
767    block = new_block(dev);
768    rec = new_record();
769    dump_block(block, "test");
770
771    i = block->buf_len - 100;
772    ASSERT (i > 0);
773    rec->data = check_pool_memory_size(rec->data, i);
774    memset(rec->data, i & 0xFF, i);
775    rec->data_len = i;
776    sm_check(__FILE__, __LINE__, False);
777    if (!write_record_to_block(block, rec)) {
778       Pmsg0(0, _("Error writing record to block.\n")); 
779       goto bail_out;
780    }
781    if (!write_block_to_dev(jcr, dev, block)) {
782       Pmsg0(0, _("Error writing block to device.\n")); 
783       goto bail_out;
784    } else {
785       Pmsg1(0, _("Wrote one record of %d bytes.\n"), i);
786    }
787    Pmsg0(0, _("Wrote block to device.\n"));
788
789 bail_out:
790    sm_check(__FILE__, __LINE__, False);
791    free_record(rec);
792    free_block(block);
793    sm_check(__FILE__, __LINE__, False);
794 }
795
796
797 /*
798  * Scan tape by reading block by block. Report what is
799  * on the tape.  Note, this command does raw reads, and as such
800  * will not work with fixed block size devices.
801  */
802 static void scancmd()
803 {
804    int stat;
805    int blocks, tot_blocks, tot_files;
806    int block_size;
807    uint64_t bytes;
808
809
810    blocks = block_size = tot_blocks = 0;
811    bytes = 0;
812    if (dev->state & ST_EOT) {
813       Pmsg0(0, "End of tape\n");
814       return; 
815    }
816    update_pos_dev(dev);
817    tot_files = dev->file;
818    for (;;) {
819       if ((stat = read(dev->fd, buf, sizeof(buf))) < 0) {
820          clrerror_dev(dev, -1);
821          Mmsg2(&dev->errmsg, "read error on %s. ERR=%s.\n",
822             dev->dev_name, strerror(dev->dev_errno));
823          Pmsg2(0, "Bad status from read %d. ERR=%s\n", stat, strerror_dev(dev));
824          if (blocks > 0)
825             printf("%d block%s of %d bytes in file %d\n",        
826                     blocks, blocks>1?"s":"", block_size, dev->file);
827          return;
828       }
829       Dmsg1(200, "read status = %d\n", stat);
830 /*    sleep(1); */
831       if (stat != block_size) {
832          update_pos_dev(dev);
833          if (blocks > 0) {
834             printf("%d block%s of %d bytes in file %d\n", 
835                  blocks, blocks>1?"s":"", block_size, dev->file);
836             blocks = 0;
837          }
838          block_size = stat;
839       }
840       if (stat == 0) {                /* EOF */
841          update_pos_dev(dev);
842          printf("End of File mark.\n");
843          /* Two reads of zero means end of tape */
844          if (dev->state & ST_EOF)
845             dev->state |= ST_EOT;
846          else {
847             dev->state |= ST_EOF;
848             dev->file++;
849          }
850          if (dev->state & ST_EOT) {
851             printf("End of tape\n");
852             break;
853          }
854       } else {                        /* Got data */
855          dev->state &= ~ST_EOF;
856          blocks++;
857          tot_blocks++;
858          bytes += stat;
859       }
860    }
861    update_pos_dev(dev);
862    tot_files = dev->file - tot_files;
863    printf("Total files=%d, blocks=%d, bytes = %" lld "\n", tot_files, tot_blocks, bytes);
864 }
865
866
867 /*
868  * Scan tape by reading Bacula block by block. Report what is
869  * on the tape.  This function reads Bacula blocks, so if your
870  * Device resource is correctly defined, it should work with
871  * either variable or fixed block sizes.
872  */
873 static void scan_blocks()
874 {
875    int blocks, tot_blocks, tot_files;
876    uint32_t block_size;
877    uint64_t bytes;
878    DEV_BLOCK *block;
879
880    block = new_block(dev);
881    blocks = block_size = tot_blocks = 0;
882    bytes = 0;
883
884    update_pos_dev(dev);
885    tot_files = dev->file;
886    for (;;) {
887       if (!read_block_from_device(dev, block)) {
888          Dmsg1(100, "!read_block(): ERR=%s\n", strerror_dev(dev));
889          if (dev->state & ST_EOT) {
890             if (blocks > 0) {
891                printf("%d block%s of %d bytes in file %d\n", 
892                     blocks, blocks>1?"s":"", block_size, dev->file);
893                blocks = 0;
894             }
895             goto bail_out;
896          }
897          if (dev->state & ST_EOF) {
898             if (blocks > 0) {
899                printf("%d block%s of %d bytes in file %d\n",        
900                        blocks, blocks>1?"s":"", block_size, dev->file);
901                blocks = 0;
902             }
903             printf(_("End of File mark.\n"));
904             continue;
905          }
906          if (dev->state & ST_SHORT) {
907             if (blocks > 0) {
908                printf("%d block%s of %d bytes in file %d\n",        
909                        blocks, blocks>1?"s":"", block_size, dev->file);
910                blocks = 0;
911             }
912             printf(_("Short block read.\n"));
913             continue;
914          }
915          printf(_("Error reading block. ERR=%s\n"), strerror_dev(dev));
916          goto bail_out;
917       }
918       if (block->block_len != block_size) {
919          if (blocks > 0) {
920             printf("%d block%s of %d bytes in file %d\n",        
921                     blocks, blocks>1?"s":"", block_size, dev->file);
922             blocks = 0;
923          }
924          block_size = block->block_len;
925       }
926       blocks++;
927       tot_blocks++;
928       bytes += block->block_len;
929       Dmsg5(100, "Blk=%u blen=%u bVer=%d SessId=%u SessTim=%u\n",
930          block->BlockNumber, block->block_len, block->BlockVer,
931          block->VolSessionId, block->VolSessionTime);
932       if (verbose == 1) {
933          DEV_RECORD *rec = new_record();
934          read_record_from_block(block, rec);
935          Pmsg7(-1, "Block: %u blen=%u First rec FI=%s SessId=%u SessTim=%u Strm=%s rlen=%d\n",
936               block->BlockNumber, block->block_len,
937               FI_to_ascii(rec->FileIndex), rec->VolSessionId, rec->VolSessionTime,
938               stream_to_ascii(rec->Stream, rec->FileIndex), rec->data_len);
939          rec->remainder = 0;
940          free_record(rec);
941       } else if (verbose > 1) {
942          dump_block(block, "");
943       }
944
945    }
946 bail_out:
947    free_block(block);
948    tot_files = dev->file - tot_files;
949    printf("Total files=%d, blocks=%d, bytes = %" lld "\n", tot_files, tot_blocks, bytes);
950 }
951
952
953 static void statcmd()
954 {
955    int stat = 0;
956    int debug;
957    uint32_t status;
958
959    debug = debug_level;
960    debug_level = 30;
961    if (!status_dev(dev, &status)) {
962       Pmsg2(0, "Bad status from status %d. ERR=%s\n", stat, strerror_dev(dev));
963    }
964 #ifdef xxxx
965    dump_volume_label(dev);
966 #endif
967    debug_level = debug;
968 }
969
970
971 /* 
972  * First we label the tape, then we fill
973  *  it with data get a new tape and write a few blocks.
974  */                            
975 static void fillcmd()
976 {
977    DEV_RECORD rec;
978    DEV_BLOCK  *block;
979    char ec1[50];
980    char *p;
981
982    ok = TRUE;
983    stop = FALSE;
984
985    Pmsg0(000, "\n\
986 This command simulates Bacula writing to a tape.\n\
987 It command requires two blank tapes, which it\n\
988 will label and write. It will print a status approximately\n\
989 every 322 MB, and write an EOF every 3.2 GB.  When the first tape\n\
990 fills, it will ask for a second, and after writing a few \n\
991 blocks, it will stop.  Then it will begin re-reading the\n\
992 This may take a long time. I.e. hours! ...\n\n");
993
994    get_cmd("Insert a blank tape then answer. Do you wish to continue? (y/n): ");
995    if (cmd[0] != 'y') {
996       Pmsg0(000, "Command aborted.\n");
997       return;
998    }
999
1000    VolumeName = "TestVolume1";
1001    labelcmd();
1002    VolumeName = NULL;
1003
1004    
1005    Dmsg1(20, "Begin append device=%s\n", dev_name(dev));
1006
1007    block = new_block(dev);
1008
1009    /* 
1010     * Acquire output device for writing.  Note, after acquiring a
1011     *   device, we MUST release it, which is done at the end of this
1012     *   subroutine.
1013     */
1014    Dmsg0(100, "just before acquire_device\n");
1015    if (!acquire_device_for_append(jcr, dev, block)) {
1016       jcr->JobStatus = JS_Cancelled;
1017       free_block(block);
1018       return;
1019    }
1020
1021    Dmsg0(100, "Just after acquire_device_for_append\n");
1022    /*
1023     * Write Begin Session Record
1024     */
1025    if (!write_session_label(jcr, block, SOS_LABEL)) {
1026       jcr->JobStatus = JS_Cancelled;
1027       Jmsg1(jcr, M_FATAL, 0, _("Write session label failed. ERR=%s\n"),
1028          strerror_dev(dev));
1029       ok = FALSE;
1030    }
1031
1032    memset(&rec, 0, sizeof(rec));
1033    rec.data = get_memory(100000);     /* max record size */
1034    /* 
1035     * Fill write buffer with random data
1036     */
1037 #define REC_SIZE 32768
1038    p = rec.data;
1039    for (int i=0; i < REC_SIZE; ) {
1040       makeSessionKey(p, NULL, 0);
1041       p += 16;
1042       i += 16;
1043    }
1044    rec.data_len = REC_SIZE;
1045
1046    /* 
1047     * Get Data from File daemon, write to device   
1048     */
1049    jcr->VolFirstFile = 0;
1050    time(&jcr->run_time);              /* start counting time for rates */
1051    for (file_index = 0; ok && !job_cancelled(jcr); ) {
1052       uint64_t *lp;
1053       rec.VolSessionId = jcr->VolSessionId;
1054       rec.VolSessionTime = jcr->VolSessionTime;
1055       rec.FileIndex = ++file_index;
1056       rec.Stream = STREAM_FILE_DATA;
1057       /* Write file_index at beginning of buffer */
1058       lp = (uint64_t *)rec.data;
1059       *lp = (uint64_t)file_index;
1060
1061       Dmsg4(250, "before writ_rec FI=%d SessId=%d Strm=%s len=%d\n",
1062          rec.FileIndex, rec.VolSessionId, stream_to_ascii(rec.Stream, rec.FileIndex), 
1063          rec.data_len);
1064        
1065       if (!write_record_to_block(block, &rec)) {
1066          Dmsg2(150, "!write_record_to_block data_len=%d rem=%d\n", rec.data_len,
1067                     rec.remainder);
1068
1069          /* Write block to tape */
1070          if (!flush_block(block, 1)) {
1071             return;
1072          }
1073
1074          /* Every 5000 blocks (approx 322MB) report where we are.
1075           */
1076          if ((block->BlockNumber % 5000) == 0) {
1077             now = time(NULL);
1078             now -= jcr->run_time;
1079             if (now <= 0) {
1080                now = 1;
1081             }
1082             kbs = (double)dev->VolCatInfo.VolCatBytes / (1000 * now);
1083             Pmsg3(000, "Wrote block=%u, VolBytes=%s rate=%.1f KB/s\n", block->BlockNumber,
1084                edit_uint64_with_commas(dev->VolCatInfo.VolCatBytes, ec1), (float)kbs);
1085          }
1086          /* Every 50000 blocks (approx 3.2MB) write an eof.
1087           */
1088          if ((block->BlockNumber % 50000) == 0) {
1089             Pmsg0(000, "Flush block, write EOF\n");
1090             flush_block(block, 0);
1091             weof_dev(dev, 1);
1092             /* The weof resets the block number */
1093          }
1094
1095          if (block->BlockNumber > 10 && stop) {      /* get out */
1096             break;
1097          }
1098       }
1099       if (!ok) {
1100          Pmsg0(000, "Not OK\n");
1101          break;
1102       }
1103       jcr->JobBytes += rec.data_len;   /* increment bytes this job */
1104       Dmsg4(190, "write_record FI=%s SessId=%d Strm=%s len=%d\n",
1105          FI_to_ascii(rec.FileIndex), rec.VolSessionId, 
1106          stream_to_ascii(rec.Stream, rec.FileIndex), rec.data_len);
1107    }
1108    Dmsg0(000, "Write_end_session_label()\n");
1109    /* Create Job status for end of session label */
1110    if (!job_cancelled(jcr) && ok) {
1111       jcr->JobStatus = JS_Terminated;
1112    } else if (!ok) {
1113       jcr->JobStatus = JS_ErrorTerminated;
1114    }
1115    if (!write_session_label(jcr, block, EOS_LABEL)) {
1116       Pmsg1(000, _("Error writting end session label. ERR=%s\n"), strerror_dev(dev));
1117       ok = FALSE;
1118    }
1119    /* Write out final block of this session */
1120    if (!write_block_to_device(jcr, dev, block)) {
1121       Pmsg0(000, "Set ok=FALSE after write_block_to_device.\n");
1122       ok = FALSE;
1123    }
1124
1125    /* Release the device */
1126    if (!release_device(jcr, dev)) {
1127       Pmsg0(000, "Error in release_device\n");
1128       ok = FALSE;
1129    }
1130
1131    free_block(block);
1132    free_memory(rec.data);
1133    Pmsg0(000, "Done with fill command. Now beginning re-read of tapes...\n");
1134
1135    unfillcmd();
1136 }
1137
1138 /*
1139  * Read two tapes written by the "fill" command and ensure
1140  *  that the data is valid.
1141  */
1142 static void unfillcmd()
1143 {
1144    DEV_BLOCK *block;
1145
1146    dumped = 0;
1147    VolBytes = 0;
1148    LastBlock = 0;
1149    block = new_block(dev);
1150
1151    dev->capabilities |= CAP_ANONVOLS; /* allow reading any volume */
1152    dev->capabilities &= ~CAP_LABEL;   /* don't label anything here */
1153
1154    end_of_tape = 0;
1155    get_cmd("Mount first of two tapes. Press enter when ready: "); 
1156    
1157    free_vol_list(jcr);
1158    pm_strcpy(&jcr->VolumeName, "TestVolume1");
1159    jcr->bsr = NULL;
1160    create_vol_list(jcr);
1161    close_dev(dev);
1162    dev->state &= ~ST_READ;
1163    if (!acquire_device_for_read(jcr, dev, block)) {
1164       Pmsg0(000, dev->errmsg);
1165       return;
1166    }
1167
1168    time(&jcr->run_time);              /* start counting time for rates */
1169    stop = 0;
1170    file_index = 0;
1171    read_records(jcr, dev, record_cb, my_mount_next_read_volume);
1172    free_block(block);
1173
1174    Pmsg0(000, "Done with unfillcmd.\n");
1175 }
1176
1177
1178 /* 
1179  * We are called here from "unfill" for each record on the
1180  *   tape.
1181  */
1182 static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
1183 {
1184
1185    SESSION_LABEL label;
1186    if (stop > 1) {                    /* on second tape */
1187       Pmsg4(000, "Blk: FileIndex=%d: block=%u size=%d vol=%s\n", 
1188            rec->FileIndex, block->BlockNumber, block->block_len, dev->VolHdr.VolName);
1189       Pmsg6(000, "   Rec: VId=%d VT=%d FI=%s Strm=%s len=%d state=%x\n",
1190            rec->VolSessionId, rec->VolSessionTime, 
1191            FI_to_ascii(rec->FileIndex), stream_to_ascii(rec->Stream, rec->FileIndex),
1192            rec->data_len, rec->state);
1193
1194       if (!dumped) {
1195          dumped = 1;
1196          dump_block(block, "Block not written to previous tape");
1197       }
1198    }
1199    if (rec->FileIndex < 0) {
1200       if (verbose > 1) {
1201          dump_label_record(dev, rec, 1);
1202       }
1203       switch (rec->FileIndex) {
1204          case PRE_LABEL:
1205             Pmsg0(000, "Volume is prelabeled. This tape cannot be scanned.\n");
1206             return;
1207          case VOL_LABEL:
1208             unser_volume_label(dev, rec);
1209             Pmsg3(000, "VOL_LABEL: block=%u size=%d vol=%s\n", block->BlockNumber, 
1210                block->block_len, dev->VolHdr.VolName);
1211             stop++;
1212             break;
1213          case SOS_LABEL:
1214             unser_session_label(&label, rec);
1215             Pmsg1(000, "SOS_LABEL: JobId=%u\n", label.JobId);
1216             break;
1217          case EOS_LABEL:
1218             unser_session_label(&label, rec);
1219             Pmsg2(000, "EOS_LABEL: block=%u JobId=%u\n", block->BlockNumber, 
1220                label.JobId);
1221             break;
1222          case EOM_LABEL:
1223             Pmsg0(000, "EOM_LABEL:\n");
1224             break;
1225          case EOT_LABEL:              /* end of all tapes */
1226             char ec1[50];
1227
1228             if (LastBlock != block->BlockNumber) {
1229                VolBytes += block->block_len;
1230             }
1231             LastBlock = block->BlockNumber;
1232             now = time(NULL);
1233             now -= jcr->run_time;
1234             if (now <= 0) {
1235                now = 1;
1236             }
1237             kbs = (double)VolBytes / (1000 * now);
1238             Pmsg3(000, "Read block=%u, VolBytes=%s rate=%.1f KB/s\n", block->BlockNumber,
1239                      edit_uint64_with_commas(VolBytes, ec1), (float)kbs);
1240
1241             Pmsg0(000, "End of all tapes.\n");
1242
1243             break;
1244          default:
1245             break;
1246       }
1247       return;
1248    }
1249    if (LastBlock != block->BlockNumber) {
1250       VolBytes += block->block_len;
1251    }
1252    if ((block->BlockNumber != LastBlock) && (block->BlockNumber % 50000) == 0) {
1253       char ec1[50];
1254       now = time(NULL);
1255       now -= jcr->run_time;
1256       if (now <= 0) {
1257          now = 1;
1258       }
1259       kbs = (double)VolBytes / (1000 * now);
1260       Pmsg3(000, "Read block=%u, VolBytes=%s rate=%.1f KB/s\n", block->BlockNumber,
1261                edit_uint64_with_commas(VolBytes, ec1), (float)kbs);
1262    }
1263    LastBlock = block->BlockNumber;
1264    if (end_of_tape) {
1265       Pmsg1(000, "End of all blocks. Block=%u\n", block->BlockNumber);
1266    }
1267 }
1268
1269
1270
1271 /*
1272  * Write current block to tape regardless of whether or
1273  *   not it is full. If the tape fills, attempt to
1274  *   acquire another tape.
1275  */
1276 static int flush_block(DEV_BLOCK *block, int dump)
1277 {
1278    char ec1[50];
1279    lock_device(dev);
1280    if (!write_block_to_dev(jcr, dev, block)) {
1281       Pmsg0(000, strerror_dev(dev));            
1282       Pmsg3(000, "Block not written: FileIndex=%u Block=%u Size=%u\n", 
1283          (unsigned)file_index, block->BlockNumber, block->block_len);
1284       if (dump) {
1285          dump_block(block, "Block not written");
1286       }
1287       if (!stop) {
1288          eot_block = block->BlockNumber;
1289          eot_block_len = block->block_len;
1290          eot_FileIndex = file_index;
1291       }
1292       now = time(NULL);
1293       now -= jcr->run_time;
1294       if (now <= 0) {
1295          now = 1;
1296       }
1297       kbs = (double)dev->VolCatInfo.VolCatBytes / (1000 * now);
1298       vol_size = dev->VolCatInfo.VolCatBytes;
1299       Pmsg2(000, "End of tape. VolumeCapacity=%s. Write rate = %.1f KB/s\n", 
1300          edit_uint64_with_commas(dev->VolCatInfo.VolCatBytes, ec1), kbs);
1301       if (!fixup_device_block_write_error(jcr, dev, block)) {
1302          Pmsg1(000, _("Cannot fixup device error. %s\n"), strerror_dev(dev));
1303          ok = FALSE;
1304          unlock_device(dev);
1305          return 0;
1306       }
1307       stop = 1;                                                     
1308       unlock_device(dev);
1309       return 1;     /* write one more block to next tape then stop */
1310    }
1311    unlock_device(dev);
1312    return 1;
1313 }
1314
1315
1316 struct cmdstruct { char *key; void (*func)(); char *help; }; 
1317 static struct cmdstruct commands[] = {
1318  {"bsf",        bsfcmd,       "backspace file"},
1319  {"bsr",        bsrcmd,       "backspace record"},
1320  {"cap",        capcmd,       "list device capabilities"},
1321  {"clear",      clearcmd,     "clear tape errors"},
1322  {"eod",        eodcmd,       "go to end of Bacula data for append"},
1323  {"test",       testcmd,      "General test Bacula tape functions"},
1324  {"eom",        eomcmd,       "go to the physical end of medium"},
1325  {"fill",       fillcmd,      "fill tape, write onto second volume"},
1326  {"unfill",     unfillcmd,    "read filled tape"},
1327  {"fsf",        fsfcmd,       "forward space a file"},
1328  {"fsr",        fsrcmd,       "forward space a record"},
1329  {"help",       helpcmd,      "print this command"},
1330  {"label",      labelcmd,     "write a Bacula label to the tape"},
1331  {"load",       loadcmd,      "load a tape"},
1332  {"quit",       quitcmd,      "quit btape"},   
1333  {"rd",         rdcmd,        "read tape"},
1334  {"readlabel",  readlabelcmd, "read and print the Bacula tape label"},
1335  {"rectest",    rectestcmd,   "test record handling functions"},
1336  {"rewind",     rewindcmd,    "rewind the tape"},
1337  {"scan",       scancmd,      "read tape block by block to EOT and report"}, 
1338  {"status",     statcmd,      "print tape status"},
1339  {"weof",       weofcmd,      "write an EOF on the tape"},
1340  {"wr",         wrcmd,        "write a single record of 2048 bytes"}, 
1341              };
1342 #define comsize (sizeof(commands)/sizeof(struct cmdstruct))
1343
1344 static void
1345 do_tape_cmds()
1346 {
1347    unsigned int i;
1348    int found;
1349
1350    while (get_cmd("*")) {
1351       sm_check(__FILE__, __LINE__, False);
1352       found = 0;
1353       for (i=0; i<comsize; i++)       /* search for command */
1354          if (fstrsch(cmd,  commands[i].key)) {
1355             (*commands[i].func)();    /* go execute command */
1356             found = 1;
1357             break;
1358          }
1359       if (!found)
1360          Pmsg1(0, _("%s is an illegal command\n"), cmd);
1361       if (quit)
1362          break;
1363    }
1364 }
1365
1366 static void helpcmd()
1367 {
1368    unsigned int i;
1369    usage();
1370    printf(_("  Command    Description\n  =======    ===========\n"));
1371    for (i=0; i<comsize; i++)
1372       printf("  %-10s %s\n", commands[i].key, commands[i].help);
1373    printf("\n");
1374 }
1375
1376 static void usage()
1377 {
1378    fprintf(stderr, _(
1379 "\nVersion: " VERSION " (" DATE ")\n\n"
1380 "Usage: btape [-c config_file] [-d debug_level] [device_name]\n"
1381 "       -c <file>   set configuration file to file\n"
1382 "       -dnn        set debug level to nn\n"
1383 "       -s          turn off signals\n"
1384 "       -t          open the default tape device\n"
1385 "       -?          print this message.\n"  
1386 "\n"));
1387
1388 }
1389
1390 /*      
1391  * Get next input command from terminal.  This
1392  * routine is REALLY primitive, and should be enhanced
1393  * to have correct backspacing, etc.
1394  */
1395 int 
1396 get_cmd(char *prompt)
1397 {
1398    int i = 0;
1399    int ch;
1400    fprintf(stdout, prompt);
1401
1402    /* We really should turn off echoing and pretty this
1403     * up a bit.
1404     */
1405    cmd[i] = 0;
1406    while ((ch = fgetc(stdin)) != EOF) { 
1407       if (ch == '\n') {
1408          strip_trailing_junk(cmd);
1409          return 1;
1410       } else if (ch == 4 || ch == 0xd3 || ch == 0x8) {
1411          if (i > 0)
1412             cmd[--i] = 0;
1413          continue;
1414       } 
1415          
1416       cmd[i++] = ch;
1417       cmd[i] = 0;
1418    }
1419    quit = 1;
1420    return 0;
1421 }
1422
1423 /* Dummies to replace askdir.c */
1424 int     dir_get_volume_info(JCR *jcr, int writing) { return 1;}
1425 int     dir_find_next_appendable_volume(JCR *jcr) { return 1;}
1426 int     dir_update_volume_info(JCR *jcr, VOLUME_CAT_INFO *vol, int relabel) { return 1; }
1427 int     dir_create_jobmedia_record(JCR *jcr) { return 1; }
1428 int     dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec) { return 1;}
1429 int     dir_send_job_status(JCR *jcr) {return 1;}
1430
1431
1432 int dir_ask_sysop_to_mount_volume(JCR *jcr, DEVICE *dev)
1433 {
1434    Pmsg0(000, dev->errmsg);           /* print reason */
1435    fprintf(stderr, "Mount Volume \"%s\" on device %s and press return when ready: ",
1436       jcr->VolumeName, dev_name(dev));
1437    getchar();   
1438    return 1;
1439 }
1440
1441 int dir_ask_sysop_to_mount_next_volume(JCR *jcr, DEVICE *dev)
1442 {
1443    fprintf(stderr, "Mount next Volume on device %s and press return when ready: ",
1444       dev_name(dev));
1445    getchar();   
1446    VolumeName = "TestVolume2";
1447    labelcmd();
1448    VolumeName = NULL;
1449    return 1;
1450 }
1451
1452 static int my_mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
1453 {
1454    char ec1[50];
1455
1456    Pmsg1(000, "End of Volume \"%s\"\n", jcr->VolumeName);
1457
1458    if (LastBlock != block->BlockNumber) {
1459       VolBytes += block->block_len;
1460    }
1461    LastBlock = block->BlockNumber;
1462    now = time(NULL);
1463    now -= jcr->run_time;
1464    if (now <= 0) {
1465       now = 1;
1466    }
1467    kbs = (double)VolBytes / (1000 * now);
1468    Pmsg3(000, "Read block=%u, VolBytes=%s rate=%.1f KB/s\n", block->BlockNumber,
1469             edit_uint64_with_commas(VolBytes, ec1), (float)kbs);
1470
1471    if (strcmp(jcr->VolumeName, "TestVolume2") == 0) {
1472       end_of_tape = 1;
1473       return 0;
1474    }
1475
1476    free_vol_list(jcr);
1477    pm_strcpy(&jcr->VolumeName, "TestVolume2");
1478    jcr->bsr = NULL;
1479    create_vol_list(jcr);
1480    close_dev(dev);
1481    dev->state &= ~ST_READ; 
1482    if (!acquire_device_for_read(jcr, dev, block)) {
1483       Pmsg2(0, "Cannot open Dev=%s, Vol=%s\n", dev_name(dev), jcr->VolumeName);
1484       return 0;
1485    }
1486    return 1;                       /* next volume mounted */
1487 }