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