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