]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/btape.c
new version
[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 int find_device_res();
62
63
64 #define CONFIG_FILE "stored.conf"
65
66 static char *configfile;
67 static char cmd[1000];
68 static int signals = TRUE;
69 static int default_tape = FALSE;
70
71 static JCR *jcr;
72
73
74 static void usage();
75 static void terminate_btape(int sig);
76 int get_cmd(char *prompt);
77
78 static void my_free_jcr(JCR *jcr)
79 {
80    return;
81 }
82
83 int write_dev(DEVICE *dev, char *buf, size_t len) 
84 {
85    Emsg0(M_ABORT, 0, "write_dev not implemented.\n");
86    return 0;
87 }
88
89 int read_dev(DEVICE *dev, char *buf, size_t len)
90 {
91    Emsg0(M_ABORT, 0, "read_dev not implemented.\n");
92    return 0;
93 }
94
95
96 /*********************************************************************
97  *
98  *         Main Bacula Pool Creation Program
99  *
100  */
101 int main(int argc, char *argv[])
102 {
103    int ch;
104
105    /* Sanity checks */
106    if (TAPE_BSIZE % DEV_BSIZE != 0 || TAPE_BSIZE / DEV_BSIZE == 0) {
107       Emsg2(M_ABORT, 0, "Tape block size (%d) not multiple of system size (%d)\n",
108          TAPE_BSIZE, DEV_BSIZE);
109    }
110    if (TAPE_BSIZE != (1 << (ffs(TAPE_BSIZE)-1))) {
111       Emsg1(M_ABORT, 0, "Tape block size (%d) is not a power of 2\n", TAPE_BSIZE);
112    }
113
114    printf("Tape block size is %d bytes.\n", TAPE_BSIZE);
115
116    while ((ch = getopt(argc, argv, "c:d:st?")) != -1) {
117       switch (ch) {
118          case 'c':                    /* specify config file */
119             if (configfile != NULL) {
120                free(configfile);
121             }
122             configfile = bstrdup(optarg);
123             break;
124
125          case 'd':                    /* set debug level */
126             debug_level = atoi(optarg);
127             if (debug_level <= 0) {
128                debug_level = 1; 
129             }
130             break;
131
132          case 't':
133             default_tape = TRUE;
134             break;
135
136          case 's':
137             signals = FALSE;
138             break;
139
140          case '?':
141          default:
142             helpcmd();
143             exit(0);
144
145       }  
146    }
147    argc -= optind;
148    argv += optind;
149
150
151    my_name_is(argc, argv, "btape");
152    init_msg(NULL, NULL);
153    
154    if (signals) {
155       init_signals(terminate_btape);
156    }
157
158    if (configfile == NULL) {
159       configfile = bstrdup(CONFIG_FILE);
160    }
161
162    daemon_start_time = time(NULL);
163
164    parse_config(configfile);
165
166
167    /* See if we can open a device */
168    if (argc) {
169       if (!(dev = init_dev(NULL, *argv))) {
170          usage();
171          exit(1);
172       }
173    }
174
175    /* Try default device */
176    if (!dev && default_tape) {
177       dev = init_dev(NULL, DEFAULT_TAPE_DRIVE);
178    }
179
180    if (dev) {
181       if (!find_device_res()) {
182          exit(1);
183       }
184       if (!open_device(dev)) {
185          Pmsg1(0, "Warning could not open device. ERR=%s", strerror_dev(dev));
186          term_dev(dev);
187          dev = NULL;
188       }
189    }
190
191    jcr = new_jcr(sizeof(JCR), my_free_jcr);
192    jcr->VolSessionId = 1;
193    jcr->VolSessionTime = (uint32_t)time(NULL);
194    jcr->NumVolumes = 1;
195
196
197    Dmsg0(200, "Do tape commands\n");
198    do_tape_cmds();
199   
200    terminate_btape(0);
201    return 0;
202 }
203
204 static void terminate_btape(int stat)
205 {
206
207    sm_check(__FILE__, __LINE__, False);
208    if (configfile) {
209       free(configfile);
210    }
211    free_config_resources();
212
213    if (dev) {
214       term_dev(dev);
215    }
216
217    if (debug_level > 10)
218       print_memory_pool_stats(); 
219
220    free_jcr(jcr);
221    jcr = NULL;
222
223    term_msg();
224    close_memory_pool();               /* free memory in pool */
225
226    sm_dump(False);
227    exit(stat);
228 }
229
230 void quitcmd()
231 {
232    quit = 1;
233 }
234
235 /*
236  * Get a new device name 
237  *  Normally given on the command line
238  */
239 static void devicecmd()
240 {
241    if (dev) {
242       term_dev(dev);
243       dev = NULL;
244    }
245    if (!get_cmd("Enter Device Name: ")) {
246       return;
247    }
248    dev = init_dev(NULL, cmd);
249    if (dev) {
250       if (!find_device_res()) {
251          return;
252       }
253       if (!open_device(dev)) {
254          Pmsg1(0, "Device open failed. ERR=%s\n", strerror_dev(dev));
255       }
256    } else {
257       Pmsg0(0, "Device init failed.\n");                          
258    }
259 }
260
261 /*
262  * Write a label to the tape   
263  */
264 static void labelcmd()
265 {
266    DEVRES *device;
267    int found = 0;
268
269    if (!dev) {
270       Pmsg0(0, "No device: Use device command.\n");
271       return;
272    }
273
274    LockRes();
275    for (device=NULL; (device=(DEVRES *)GetNextRes(R_DEVICE, (RES *)device)); ) {
276       if (strcmp(device->device_name, dev->dev_name) == 0) {
277          jcr->device = device;        /* Arggg a bit of duplication here */
278          device->dev = dev;
279          dev->device = device;
280          found = 1;
281          break;
282       }
283    } 
284    UnlockRes();
285    if (!found) {
286       Pmsg2(0, "Could not find device %s in %s\n", dev->dev_name, configfile);
287       return;
288    }
289
290    if (!get_cmd("Enter Volume Name: ")) {
291       return;
292    }
293          
294    if (!(dev->state & ST_OPENED)) {
295       if (!open_device(dev)) {
296          Pmsg1(0, "Device open failed. ERR=%s\n", strerror_dev(dev));
297       }
298    }
299    write_volume_label_to_dev(jcr, device, cmd, "Default");
300 }
301
302 /*
303  * Read the tape label   
304  */
305 static void readlabelcmd()
306 {
307    int save_debug_level = debug_level;
308    int stat;
309    DEV_BLOCK *block;
310
311    if (!dev) {
312       Pmsg0(0, "No device: Use device command.\n");
313       return;
314    }
315    block = new_block(dev);
316    stat = read_dev_volume_label(jcr, dev, block);
317    switch (stat) {
318       case VOL_NO_LABEL:
319          Pmsg0(0, "Volume has no label.\n");
320          break;
321       case VOL_OK:
322          Pmsg0(0, "Volume label read correctly.\n");
323          break;
324       case VOL_IO_ERROR:
325          Pmsg1(0, "I/O error on device: ERR=%s", strerror_dev(dev));
326          break;
327       case VOL_NAME_ERROR:
328          Pmsg0(0, "Volume name error\n");
329          break;
330       case VOL_CREATE_ERROR:
331          Pmsg1(0, "Error creating label. ERR=%s", strerror_dev(dev));
332          break;
333       case VOL_VERSION_ERROR:
334          Pmsg0(0, "Volume version error.\n");
335          break;
336       case VOL_LABEL_ERROR:
337          Pmsg0(0, "Bad Volume label type.\n");
338          break;
339       default:
340          Pmsg0(0, "Unknown error.\n");
341          break;
342    }
343
344    debug_level = 20;
345    dump_volume_label(dev); 
346    debug_level = save_debug_level;
347    free_block(block);
348 }
349
350
351 /*
352  * Search for device resource that corresponds to 
353  * device name on command line (or default).
354  *       
355  * Returns: 0 on failure
356  *          1 on success
357  */
358 static int find_device_res()
359 {
360    int found = 0;
361
362    LockRes();
363    for (device=NULL; (device=(DEVRES *)GetNextRes(R_DEVICE, (RES *)device)); ) {
364       if (strcmp(device->device_name, dev->dev_name) == 0) {
365          device->dev = dev;
366          dev->capabilities = device->cap_bits;
367          found = 1;
368          break;
369       }
370    } 
371    UnlockRes();
372    if (!found) {
373       Pmsg2(0, "Could not find device %s in %s\n", dev->dev_name, configfile);
374       return 0;
375    }
376    Pmsg1(0, "Using device: %s\n", dev->dev_name);
377    return 1;
378 }
379
380 /*
381  * Load the tape should have prevously been taken
382  * off line, otherwise this command is not necessary.
383  */
384 static void loadcmd()
385 {
386
387    if (!dev) {
388       Pmsg0(0, "No device: Use device command.\n");
389       return;
390    }
391    if (!load_dev(dev)) {
392       Pmsg1(0, "Bad status from load. ERR=%s\n", strerror_dev(dev));
393    } else
394       Pmsg1(0, "Loaded %s\n", dev_name(dev));
395 }
396
397 /*
398  * Rewind the tape.   
399  */
400 static void rewindcmd()
401 {
402    if (!dev) {
403       Pmsg0(0, "No device: Use device command.\n");
404       return;
405    }
406    if (!rewind_dev(dev)) {
407       Pmsg1(0, "Bad status from rewind. ERR=%s\n", strerror_dev(dev));
408       clrerror_dev(dev, -1);
409    } else
410       Pmsg1(0, "Rewound %s\n", dev_name(dev));
411 }
412
413 /*
414  * Clear any tape error   
415  */
416 static void clearcmd()
417 {
418    if (!dev) {
419       Pmsg0(0, "No device: Use device command.\n");
420       return;
421    }
422    clrerror_dev(dev, -1);
423 }
424
425 /*
426  * Write and end of file on the tape   
427  */
428 static void weofcmd()
429 {
430    int stat;
431
432    if (!dev) {
433       Pmsg0(0, "No device: Use device command.\n");
434       return;
435    }
436    if ((stat = weof_dev(dev, 1)) < 0) {
437       Pmsg2(0, "Bad status from weof %d. ERR=%s\n", stat, strerror_dev(dev));
438       return;
439    } else {
440       Pmsg1(0, "Wrote EOF to %s\n", dev_name(dev));
441    }
442 }
443
444 /*
445  * Test on uninitialized tape 
446  *  Destroys tape contents !!!! Including Bacula label.
447  */
448 static void rawtestcmd()
449 {
450 #ifdef xxxx
451    int i, j, k;
452
453    if (!dev) {
454       Pmsg0(0, "No device: Use device command.\n");
455       return;
456    }
457    if (!rewind_dev(dev)) {
458       Pmsg1(0, "Bad status from rewind. ERR=%s\n", strerror_dev(dev));
459       return;
460    }
461    Pmsg0(0, "Rewound, now writing 100 blocks\n");
462    for (i=0; i<100; i++) {
463       j = 10000 + i;
464       memset(buf, i, j);
465       if (!write_dev(dev, buf, j)) {
466          Pmsg1(0, "Bad status from write. ERR=%s\n", strerror_dev(dev));
467          return;
468       }
469      Pmsg2(10, "Wrote %d bytes of %d\n", j, i);
470    }
471    Pmsg0(0, "100 Blocks written, flushing buffers and writing EOF\n");
472    if (flush_dev(dev) != 0) {
473       Pmsg1(0, "Error writing flushing. ERR=%s\n", strerror(errno));
474       return;
475    }
476    if (weof_dev(dev, 1) != 0) {
477       Pmsg1(0, "Error writing eof. ERR=%s\n", strerror(errno));
478       return;
479    }
480    Pmsg0(0, "Rewinding ...\n");
481    if (!rewind_dev(dev)) {
482       Pmsg1(0, "Bad status from rewind. ERR=%s\n", strerror_dev(dev));
483       return;
484    }
485
486
487    Pmsg0(0, "Read and verify data ...\n");
488    for (i=0; i<100; i++) {
489       j = 10000 + i;
490       if (!read_dev(dev, buf, j)) {
491          Pmsg1(0, "Bad status from read. ERR=%s\n", strerror_dev(dev));
492          return;
493       }
494       for (k=0; k<j; k++) {
495          if (buf[k] != i) {
496             Pmsg5(0, "Data read expected %d got %d at byte %d, block %d size %d\n", 
497              i, buf[k], k, i, j);
498             return;
499          }
500       }     
501       Dmsg3(10, "Successful read block %d of %d bytes of %d\n", i, j, i);   
502    }
503    Pmsg0(0, "Read OK!\n");
504    Pmsg0(0, "Rewinding ...\n");
505    if (!rewind_dev(dev)) {
506       Pmsg1(0, "Bad status from rewind. ERR=%s\n", strerror_dev(dev));
507       return;
508    }
509 #else
510    printf("Rawtest command no longer implemented.\n");
511 #endif
512 }
513
514 /* Go to the end of the medium -- raw command   
515  * The idea was orginally that the end of the Bacula
516  * medium would be flagged differently. This is not
517  * currently the case. So, this is identical to the
518  * eodcmd().
519  */
520 static void eomcmd()
521 {
522    if (!dev) {
523       Pmsg0(0, "No device: Use device command.\n");
524       return;
525    }
526    if (!eod_dev(dev)) {
527       Pmsg1(0, "Bad status from eod. ERR=%s\n", strerror_dev(dev));
528       return;
529    } else {
530       Pmsg0(0, "Moved to end of media\n");
531    }
532 }
533
534 /*
535  * Go to the end of the media (either hardware determined
536  *  or defined by two eofs.
537  */
538 static void eodcmd()
539 {
540    eomcmd();
541 }
542
543 /*
544  * Backspace file   
545  */
546 static void bsfcmd()
547 {
548    int stat;
549    if (!dev) {
550       Pmsg0(0, "No device: Use device command.\n");
551       return;
552    }
553    if ((stat=bsf_dev(dev, 1)) < 0) {
554       Pmsg1(0, "Bad status from bsf. ERR=%s\n", strerror(errno));
555    } else {
556       Pmsg0(0, "Back spaced one file.\n");
557    }
558 }
559
560 /*
561  * Backspace record   
562  */
563 static void bsrcmd()
564 {
565    int stat;
566    if (!dev) {
567       Pmsg0(0, "No device: Use device command.\n");
568       return;
569    }
570    if ((stat=bsr_dev(dev, 1)) < 0) {
571       Pmsg1(0, "Bad status from bsr. ERR=%s\n", strerror(errno));
572    } else {
573       Pmsg0(0, "Back spaced one record.\n");
574    }
575 }
576
577 /*
578  * List device capabilities as defined in the 
579  *  stored.conf file.
580  */
581 static void capcmd()
582 {
583    if (!dev) {
584       Pmsg0(0, "No device: Use device command.\n");
585       return;
586    }
587    Pmsg0(0, "Device capabilities: ");
588    printf("%sEOF ", dev->capabilities & CAP_EOF ? "" : "!");
589    printf("%sBSR ", dev->capabilities & CAP_BSR ? "" : "!");
590    printf("%sBSF ", dev->capabilities & CAP_BSF ? "" : "!");
591    printf("%sFSR ", dev->capabilities & CAP_FSR ? "" : "!");
592    printf("%sFSF ", dev->capabilities & CAP_FSF ? "" : "!");
593    printf("%sEOM ", dev->capabilities & CAP_EOM ? "" : "!");
594    printf("%sREM ", dev->capabilities & CAP_REM ? "" : "!");
595    printf("%sRACCESS ", dev->capabilities & CAP_RACCESS ? "" : "!");
596    printf("%sAUTOMOUNT ", dev->capabilities & CAP_AUTOMOUNT ? "" : "!");
597    printf("%sLABEL ", dev->capabilities & CAP_LABEL ? "" : "!");
598    printf("%sANONVOLS ", dev->capabilities & CAP_ANONVOLS ? "" : "!");
599    printf("%sALWAYSOPEN ", dev->capabilities & CAP_ALWAYSOPEN ? "" : "!");
600    printf("\n");
601 }
602
603 /*
604  * Test writting larger and larger records.  
605  * This is a torture test for records.
606  */
607 static void rectestcmd()
608 {
609    DEV_BLOCK *block;
610    DEV_RECORD *rec;
611    int i, blkno = 0;
612
613    if (!dev) {
614       Pmsg0(0, "No device: Use device command.\n");
615       return;
616    }
617
618    Pmsg0(0, "Test writting larger and larger records.\n\
619 This is a torture test for records. \n");
620
621    sm_check(__FILE__, __LINE__, False);
622    block = new_block(dev);
623    rec = new_record();
624
625    for (i=1; i<500000; i++) {
626       rec->data = (char *) check_pool_memory_size(rec->data, i);
627       memset(rec->data, i & 0xFF, i);
628       rec->data_len = i;
629       sm_check(__FILE__, __LINE__, False);
630       while (!write_record_to_block(block, rec)) {
631          empty_block(block);
632          blkno++;
633          Pmsg2(0, "Block %d i=%d\n", blkno, i);
634       }
635       sm_check(__FILE__, __LINE__, False);
636    }
637    free_record(rec);
638    free_block(block);
639    sm_check(__FILE__, __LINE__, False);
640 }
641
642 /* 
643  * This is a general test of Bacula's functions
644  *   needed to read and write the tape.
645  */
646 static void testcmd()
647 {
648    if (!dev) {
649       Pmsg0(0, "No device: Use device command.\n");
650       return;
651    }
652    Pmsg0(0, "Append files test.\n\n\
653 I'm going to write one record  in file 0,\n\
654                    two records in file 1,\n\
655              and three records in file 2\n\n");
656    rewindcmd();
657    wrcmd();
658    weofcmd();      /* end file 0 */
659    wrcmd();
660    wrcmd();
661    weofcmd();      /* end file 1 */
662    wrcmd();
663    wrcmd();
664    wrcmd();
665    weofcmd();     /* end file 2 */
666 //   weofcmd();
667    rewindcmd();
668    Pmsg0(0, "Now moving to end of media.\n");
669    eodcmd();
670    Pmsg2(0, "\nWe should be in file 3. I am at file %d. This is %s\n\n", 
671       dev->file, dev->file == 3 ? "correct!" : "NOT correct!!!!");
672
673    Pmsg0(0, "\nNow I am going to attempt to append to the tape.\n");
674    wrcmd(); 
675    weofcmd();
676 //   weofcmd();
677    rewindcmd();
678    scancmd();
679    Pmsg0(0, "The above scan should have four files of:\n\
680 One record, two records, three records, and one record respectively.\n\n");
681
682
683    Pmsg0(0, "Append block test.\n\n\
684 I'm going to write a block, an EOF, rewind, go to EOM,\n\
685 then backspace over the EOF and attempt to append a\
686 second block in the first file.\n\n");
687    rewindcmd();
688    wrcmd();
689    weofcmd();
690 //   weofcmd();
691    rewindcmd();
692    eodcmd();
693    Pmsg2(0, "We should be at file 1. I am at EOM File=%d. This is %s\n",
694       dev->file, dev->file == 1 ? "correct!" : "NOT correct!!!!");
695    Pmsg0(0, "Doing backspace file.\n");
696    bsfcmd();
697    Pmsg0(0, "Write second block, hoping to append to first file.\n");
698    wrcmd();
699    weofcmd();
700    rewindcmd();
701    Pmsg0(0, "Done writing, scanning results\n");
702    scancmd();
703    Pmsg0(0, "The above should have one file of two blocks.\n");
704 }
705
706
707 static void fsfcmd()
708 {
709    int stat;
710    if (!dev) {
711       Pmsg0(0, "No device: Use device command.\n");
712       return;
713    }
714    if ((stat=fsf_dev(dev, 1)) < 0) {
715       Pmsg2(0, "Bad status from fsf %d. ERR=%s\n", stat, strerror_dev(dev));
716       return;
717    }
718    Pmsg0(0, "Forward spaced one file.\n");
719 }
720
721 static void fsrcmd()
722 {
723    int stat;
724    if (!dev) {
725       Pmsg0(0, "No device: Use device command.\n");
726       return;
727    }
728    if ((stat=fsr_dev(dev, 1)) < 0) {
729       Pmsg2(0, "Bad status from fsr %d. ERR=%s\n", stat, strerror_dev(dev));
730       return;
731    }
732    Pmsg0(0, "Forward spaced one record.\n");
733 }
734
735 static void rdcmd()
736 {
737 #ifdef xxxxx
738    int stat;
739
740    if (!dev) {
741       Pmsg0(0, "No device: Use device command.\n");
742       return;
743    }
744    if (!read_dev(dev, buf, 512*126)) {
745       Pmsg1(0, "Bad status from read. ERR=%s\n", strerror_dev(dev));
746       return;
747    }
748    Pmsg1(10, "Read %d bytes\n", stat);
749 #else
750    printf("Rdcmd no longer implemented.\n");
751 #endif
752 }
753
754
755 static void wrcmd()
756 {
757    DEV_BLOCK *block;
758    DEV_RECORD *rec;
759    int i;
760
761    if (!dev) {
762       Pmsg0(0, "No device: Use device command.\n");
763       return;
764    }
765    sm_check(__FILE__, __LINE__, False);
766    block = new_block(dev);
767    rec = new_record();
768
769    i = 32001;
770    rec->data = (char *) check_pool_memory_size(rec->data, i);
771    memset(rec->data, i & 0xFF, i);
772    rec->data_len = i;
773    sm_check(__FILE__, __LINE__, False);
774    if (!write_record_to_block(block, rec)) {
775       Pmsg0(0, "Error writing record to block.\n"); 
776       return;
777    }
778    if (!write_block_to_dev(dev, block)) {
779       Pmsg0(0, "Error writing block to device.\n"); 
780       return;
781    } else {
782       Pmsg1(0, "Wrote one record of %d bytes.\n",
783          ((i+TAPE_BSIZE-1)/TAPE_BSIZE) * TAPE_BSIZE);
784    }
785
786    sm_check(__FILE__, __LINE__, False);
787    free_record(rec);
788    free_block(block);
789    sm_check(__FILE__, __LINE__, False);
790    Pmsg0(0, "Wrote block to device.\n");
791 }
792
793
794 /*
795  * Scan tape by reading block by block. Report what is
796  * on the tape.
797  */
798 static void scancmd()
799 {
800    int stat;
801    int blocks, tot_blocks, tot_files;
802    int block_size;
803    uint64_t bytes;
804
805    if (!dev) {
806       Pmsg0(0, "No device: Use device command.\n");
807       return;
808    }
809    blocks = block_size = tot_blocks = 0;
810    bytes = 0;
811    if (dev->state & ST_EOT) {
812       Pmsg0(0, "End of tape\n");
813       return; 
814    }
815    update_pos_dev(dev);
816    tot_files = dev->file;
817    for (;;) {
818       if ((stat = read(dev->fd, buf, sizeof(buf))) < 0) {
819          clrerror_dev(dev, -1);
820          Mmsg2(&dev->errmsg, "read error on %s. ERR=%s.\n",
821             dev->dev_name, strerror(dev->dev_errno));
822          Pmsg2(0, "Bad status from read %d. ERR=%s\n", stat, strerror_dev(dev));
823          if (blocks > 0)
824             printf("%d block%s of %d bytes in file %d\n",        
825                     blocks, blocks>1?"s":"", block_size, dev->file);
826          return;
827       }
828       Dmsg1(200, "read status = %d\n", stat);
829 /*    sleep(1); */
830       if (stat != block_size) {
831          update_pos_dev(dev);
832          if (blocks > 0) {
833             printf("%d block%s of %d bytes in file %d\n", 
834                  blocks, blocks>1?"s":"", block_size, dev->file);
835             blocks = 0;
836          }
837          block_size = stat;
838       }
839       if (stat == 0) {                /* EOF */
840          update_pos_dev(dev);
841          printf("End of File mark.\n");
842          /* Two reads of zero means end of tape */
843          if (dev->state & ST_EOF)
844             dev->state |= ST_EOT;
845          else {
846             dev->state |= ST_EOF;
847             dev->file++;
848          }
849          if (dev->state & ST_EOT) {
850             printf("End of tape\n");
851             break;
852          }
853       } else {                        /* Got data */
854          dev->state &= ~ST_EOF;
855          blocks++;
856          tot_blocks++;
857          bytes += stat;
858       }
859    }
860    update_pos_dev(dev);
861    tot_files = dev->file - tot_files;
862    printf("Total files=%d, blocks=%d, bytes = %" lld "\n", tot_files, tot_blocks, bytes);
863 }
864
865 static void statcmd()
866 {
867    int stat = 0;
868    int debug;
869    uint32_t status;
870
871    if (!dev) {
872       Pmsg0(0, "No device: Use device command.\n");
873       return;
874    }
875    debug = debug_level;
876    debug_level = 30;
877    if (!status_dev(dev, &status)) {
878       Pmsg2(0, "Bad status from status %d. ERR=%s\n", stat, strerror_dev(dev));
879    }
880 #ifdef xxxx
881    dump_volume_label(dev);
882 #endif
883    debug_level = debug;
884 }
885
886
887 /*
888  * Test on labeled tape. Preserves Bacula label.
889  */
890 static void appendcmd()
891 {
892
893 #ifdef xxxx_this_code_turned_off
894
895    int i, j, k;
896    int file;
897    DEV_BLOCK *block;
898
899    if (!dev) {
900       Pmsg0(0, "No device: Use device command.\n");
901       return;
902    }
903
904    block = new_block(dev);
905
906    if (!ready_device_for_append(jcr, dev, block, VolName)) {
907       Pmsg0(0, "Cannot append, not a Bacula tape.\n");
908       return;
909    }
910
911    file = dev_file(dev);
912    Pmsg1(0, "Begin write test data in file %d\n", file);
913
914    /* Write our test data */
915    for (i=0; i<100; i++) {
916       j = 10000 + i;
917       memset(buf, i, j);
918       if (!write_dev(dev, buf, j)) {
919          Pmsg1(0, "Bad status from write. ERR=%s\n", strerror_dev(dev));
920          return;
921       }
922      Pmsg2(10, "Wrote %d bytes of %d\n", j, i);
923    }
924
925    if (flush_dev(dev) != 0) {                  /* ensure written to tape */
926       Pmsg1(0, "Flush error: %s\n", strerror(errno));
927    }
928    if (weof_dev(dev, 1) != 0) { 
929       Pmsg1(0, "EOF error: %s\n", strerror(errno));
930    }
931
932    Pmsg0(0, "Rewind and reread label\n");
933    if (read_dev_volume_label(dev, VolName) != VOL_OK) {
934       return;
935    }
936
937    if (file != 0) { 
938       Pmsg1(0, "FSF %d files\n", file);
939       fsf_dev(dev, file);
940    }
941       
942    file = dev_file(dev);
943    Pmsg1(0, "Begin read/test from file %d\n", file);
944    /* Now read our test data and make sure it is what we wrote */
945    for (i=0; i<100; i++) {
946       j = 10000 + i;
947       if (!read_dev(dev, buf, j)) {
948          Pmsg1(0, "Bad status from read. ERR=%s\n", strerror_dev(dev));
949          return;
950       }
951       for (k=0; k<j; k++) {
952          if (buf[k] != i) {
953             Pmsg5(0, "Data read expected %d got %d at byte %d, block %d size %d\n", 
954              i, buf[k], k, i, j);
955             return;
956          }
957       }     
958       Pmsg3(10, "Successful read block %d of %d bytes of %d\n", i, j, i);
959    }
960
961    Pmsg0(0, "Reread test data successfully.\n");
962 #else 
963    printf("append command no longer implemented.\n");
964 #endif
965 }
966
967
968
969 struct cmdstruct { char *key; void (*func)(); char *help; }; 
970 static struct cmdstruct commands[] = {
971  {"append",     appendcmd,    "append and read test data on a Bacula labeled tape"},
972  {"bsf",        bsfcmd,       "backspace file"},
973  {"bsr",        bsrcmd,       "backspace record"},
974  {"cap",        capcmd,       "list device capabilities"},
975  {"clear",      clearcmd,     "clear tape errors"},
976  {"device",     devicecmd,    "specify the tape device name"},
977  {"eod",        eodcmd,       "go to end of Bacula data for append"},
978  {"test",       testcmd,      "General test Bacula tape functions"},
979  {"eom",        eomcmd,       "go to the physical end of medium"},
980  {"fsf",        fsfcmd,       "forward space a file"},
981  {"fsr",        fsrcmd,       "forward space a record"},
982  {"help",       helpcmd,      "print this command"},
983  {"label",      labelcmd,     "write a Bacula label to the tape"},
984  {"load",       loadcmd,      "load a tape"},
985  {"quit",       quitcmd,      "quit btape"},   
986  {"rawtest",    rawtestcmd,   "write and read test data on unlabeled tape"},     
987  {"rd",         rdcmd,        "read tape"},
988  {"readlabel",  readlabelcmd, "read and print the Bacula tape label"},
989  {"rectest",    rectestcmd,   "test record handling functions"},
990  {"rewind",     rewindcmd,    "rewind the tape"},
991  {"scan",       scancmd,      "read tape block by block to EOT and report"}, 
992  {"status",     statcmd,      "print tape status"},
993  {"weof",       weofcmd,      "write an EOF on the tape"},
994  {"wr",         wrcmd,        "write a single record of 2048 bytes"}, 
995              };
996 #define comsize (sizeof(commands)/sizeof(struct cmdstruct))
997
998 static void
999 do_tape_cmds()
1000 {
1001    unsigned int i;
1002    int found;
1003
1004    while (get_cmd("*")) {
1005       sm_check(__FILE__, __LINE__, False);
1006       found = 0;
1007       for (i=0; i<comsize; i++)       /* search for command */
1008          if (fstrsch(cmd,  commands[i].key)) {
1009             (*commands[i].func)();    /* go execute command */
1010             found = 1;
1011             break;
1012          }
1013       if (!found)
1014          Pmsg1(0, "%s is an illegal command\n", cmd);
1015       if (quit)
1016          break;
1017    }
1018 }
1019
1020 static void helpcmd()
1021 {
1022    unsigned int i;
1023    usage();
1024    printf("  Command    Description\n  =======    ===========\n");
1025    for (i=0; i<comsize; i++)
1026       printf("  %-10s %s\n", commands[i].key, commands[i].help);
1027    printf("\n");
1028 }
1029
1030 static void usage()
1031 {
1032    fprintf(stderr,
1033 "\n"
1034 "Usage: btape [-c config_file] [-d debug_level] [device_name]\n"
1035 "       -c <file>   set configuration file to file\n"
1036 "       -dnn        set debug level to nn\n"
1037 "       -s          turn off signals\n"
1038 "       -t          open the default tape device\n"
1039 "       -?          print this message.\n"  
1040 "\n");
1041
1042 }
1043
1044 /*      
1045  * Get next input command from terminal.  This
1046  * routine is REALLY primitive, and should be enhanced
1047  * to have correct backspacing, etc.
1048  */
1049 int 
1050 get_cmd(char *prompt)
1051 {
1052    int i = 0;
1053    int ch;
1054    fprintf(stdout, prompt);
1055
1056    /* We really should turn off echoing and pretty this
1057     * up a bit.
1058     */
1059    cmd[i] = 0;
1060    while ((ch = fgetc(stdin)) != EOF) { 
1061       if (ch == '\n') {
1062          strip_trailing_junk(cmd);
1063          return 1;
1064       } else if (ch == 4 || ch == 0xd3 || ch == 0x8) {
1065          if (i > 0)
1066             cmd[--i] = 0;
1067          continue;
1068       } 
1069          
1070       cmd[i++] = ch;
1071       cmd[i] = 0;
1072    }
1073    quit = 1;
1074    return 0;
1075 }