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