3 * Bacula Tape manipulation program
5 * Has various tape manipulation commands -- mostly for
6 * use in determining how tapes really work.
8 * Kern Sibbald, April MM
10 * Note, this program reads stored.conf, and will only
11 * talk to devices that are configured.
17 Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
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.
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.
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,
40 /* External subroutines */
41 extern void free_config_resources();
43 /* Exported variables */
46 int bsize = TAPE_BSIZE;
50 DEVRES *device = NULL;
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();
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);
68 /* Static variables */
69 #define CONFIG_FILE "bacula-sd.conf"
72 static BSR *bsr = NULL;
73 static char cmd[1000];
74 static int signals = TRUE;
77 static uint64_t vol_size;
78 static uint64_t VolBytes;
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;
90 static char *VolumeName = NULL;
92 static JCR *jcr = NULL;
96 static void terminate_btape(int sig);
97 int get_cmd(char *prompt);
100 int write_dev(DEVICE *dev, char *buf, size_t len)
102 Emsg0(M_ABORT, 0, "write_dev not implemented.\n");
106 int read_dev(DEVICE *dev, char *buf, size_t len)
108 Emsg0(M_ABORT, 0, "read_dev not implemented.\n");
113 /*********************************************************************
115 * Main Bacula Pool Creation Program
118 int main(int argc, char *argv[])
124 if (TAPE_BSIZE % DEV_BSIZE != 0 || TAPE_BSIZE / DEV_BSIZE == 0) {
125 Emsg2(M_ABORT, 0, "Tape block size (%d) not multiple of system size (%d)\n",
126 TAPE_BSIZE, DEV_BSIZE);
128 if (TAPE_BSIZE != (1 << (ffs(TAPE_BSIZE)-1))) {
129 Emsg1(M_ABORT, 0, "Tape block size (%d) is not a power of 2\n", TAPE_BSIZE);
132 printf("Tape block granularity is %d bytes.\n", TAPE_BSIZE);
134 working_directory = "/tmp";
135 my_name_is(argc, argv, "btape");
136 init_msg(NULL, NULL);
138 while ((ch = getopt(argc, argv, "b:c:d:sv?")) != -1) {
140 case 'b': /* bootstrap file */
141 bsr = parse_bsr(NULL, optarg);
145 case 'c': /* specify config file */
146 if (configfile != NULL) {
149 configfile = bstrdup(optarg);
152 case 'd': /* set debug level */
153 debug_level = atoi(optarg);
154 if (debug_level <= 0) {
180 init_signals(terminate_btape);
183 if (configfile == NULL) {
184 configfile = bstrdup(CONFIG_FILE);
187 daemon_start_time = time(NULL);
189 parse_config(configfile);
192 /* See if we can open a device */
194 Pmsg0(000, "No archive name specified.\n");
197 } else if (argc != 1) {
198 Pmsg0(000, "Improper number of arguments specified.\n");
203 jcr = setup_jcr("btape", argv[0], bsr);
204 dev = setup_to_access_device(jcr, 0); /* acquire for write */
208 block = new_block(dev);
210 if (!(dev->state & ST_OPENED)) {
211 Dmsg0(129, "Opening device.\n");
212 if (open_dev(dev, jcr->VolumeName, READ_WRITE) < 0) {
213 Emsg1(M_FATAL, 0, _("dev open failed: %s\n"), dev->errmsg);
219 Dmsg1(129, "open_dev %s OK\n", dev_name(dev));
223 Dmsg0(200, "Do tape commands\n");
231 static void terminate_btape(int stat)
234 sm_check(__FILE__, __LINE__, False);
238 free_config_resources();
244 if (debug_level > 10)
245 print_memory_pool_stats();
255 close_memory_pool(); /* free memory in pool */
267 * Write a label to the tape
269 static void labelcmd()
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 */
279 dev->device = device;
286 Pmsg2(0, "Could not find device %s in %s\n", dev->dev_name, configfile);
291 strcpy(cmd, VolumeName);
293 if (!get_cmd("Enter Volume Name: ")) {
298 if (!(dev->state & ST_OPENED)) {
299 if (!open_device(dev)) {
300 Pmsg1(0, "Device open failed. ERR=%s\n", strerror_dev(dev));
303 write_volume_label_to_dev(jcr, device, cmd, "Default");
307 * Read the tape label
309 static void readlabelcmd()
311 int save_debug_level = debug_level;
315 block = new_block(dev);
316 stat = read_dev_volume_label(jcr, dev, block);
319 Pmsg0(0, "Volume has no label.\n");
322 Pmsg0(0, "Volume label read correctly.\n");
325 Pmsg1(0, "I/O error on device: ERR=%s", strerror_dev(dev));
328 Pmsg0(0, "Volume name error\n");
330 case VOL_CREATE_ERROR:
331 Pmsg1(0, "Error creating label. ERR=%s", strerror_dev(dev));
333 case VOL_VERSION_ERROR:
334 Pmsg0(0, "Volume version error.\n");
336 case VOL_LABEL_ERROR:
337 Pmsg0(0, "Bad Volume label type.\n");
340 Pmsg0(0, "Unknown error.\n");
345 dump_volume_label(dev);
346 debug_level = save_debug_level;
352 * Load the tape should have prevously been taken
353 * off line, otherwise this command is not necessary.
355 static void loadcmd()
358 if (!load_dev(dev)) {
359 Pmsg1(0, "Bad status from load. ERR=%s\n", strerror_dev(dev));
361 Pmsg1(0, "Loaded %s\n", dev_name(dev));
367 static void rewindcmd()
369 if (!rewind_dev(dev)) {
370 Pmsg1(0, "Bad status from rewind. ERR=%s\n", strerror_dev(dev));
371 clrerror_dev(dev, -1);
373 Pmsg1(0, "Rewound %s\n", dev_name(dev));
378 * Clear any tape error
380 static void clearcmd()
382 clrerror_dev(dev, -1);
386 * Write and end of file on the tape
388 static void weofcmd()
392 if ((stat = weof_dev(dev, 1)) < 0) {
393 Pmsg2(0, "Bad status from weof %d. ERR=%s\n", stat, strerror_dev(dev));
396 Pmsg1(0, "Wrote EOF to %s\n", dev_name(dev));
401 /* Go to the end of the medium -- raw command
402 * The idea was orginally that the end of the Bacula
403 * medium would be flagged differently. This is not
404 * currently the case. So, this is identical to the
410 Pmsg1(0, _("Bad status from eod. ERR=%s\n"), strerror_dev(dev));
413 Pmsg0(0, _("Moved to end of media\n"));
418 * Go to the end of the media (either hardware determined
419 * or defined by two eofs.
433 if ((stat=bsf_dev(dev, 1)) < 0) {
434 Pmsg1(0, _("Bad status from bsf. ERR=%s\n"), strerror(errno));
436 Pmsg0(0, _("Back spaced one file.\n"));
447 if ((stat=bsr_dev(dev, 1)) < 0) {
448 Pmsg1(0, _("Bad status from bsr. ERR=%s\n"), strerror(errno));
450 Pmsg0(0, _("Back spaced one record.\n"));
455 * List device capabilities as defined in the
460 printf(_("Device capabilities:\n"));
461 printf("%sEOF ", dev->capabilities & CAP_EOF ? "" : "!");
462 printf("%sBSR ", dev->capabilities & CAP_BSR ? "" : "!");
463 printf("%sBSF ", dev->capabilities & CAP_BSF ? "" : "!");
464 printf("%sFSR ", dev->capabilities & CAP_FSR ? "" : "!");
465 printf("%sFSF ", dev->capabilities & CAP_FSF ? "" : "!");
466 printf("%sEOM ", dev->capabilities & CAP_EOM ? "" : "!");
467 printf("%sREM ", dev->capabilities & CAP_REM ? "" : "!");
468 printf("%sRACCESS ", dev->capabilities & CAP_RACCESS ? "" : "!");
469 printf("%sAUTOMOUNT ", dev->capabilities & CAP_AUTOMOUNT ? "" : "!");
470 printf("%sLABEL ", dev->capabilities & CAP_LABEL ? "" : "!");
471 printf("%sANONVOLS ", dev->capabilities & CAP_ANONVOLS ? "" : "!");
472 printf("%sALWAYSOPEN ", dev->capabilities & CAP_ALWAYSOPEN ? "" : "!");
475 printf(_("Device status:\n"));
476 printf("%sOPENED ", dev->state & ST_OPENED ? "" : "!");
477 printf("%sTAPE ", dev->state & ST_TAPE ? "" : "!");
478 printf("%sLABEL ", dev->state & ST_LABEL ? "" : "!");
479 printf("%sMALLOC ", dev->state & ST_MALLOC ? "" : "!");
480 printf("%sAPPEND ", dev->state & ST_APPEND ? "" : "!");
481 printf("%sREAD ", dev->state & ST_READ ? "" : "!");
482 printf("%sEOT ", dev->state & ST_EOT ? "" : "!");
483 printf("%sWEOT ", dev->state & ST_WEOT ? "" : "!");
484 printf("%sEOF ", dev->state & ST_EOF ? "" : "!");
485 printf("%sNEXTVOL ", dev->state & ST_NEXTVOL ? "" : "!");
486 printf("%sSHORT ", dev->state & ST_SHORT ? "" : "!");
492 * Test writting larger and larger records.
493 * This is a torture test for records.
495 static void rectestcmd()
501 Pmsg0(0, "Test writting larger and larger records.\n\
502 This is a torture test for records.\nI am going to write\n\
503 larger and larger records. It will stop when the record size\n\
504 plus the header exceeds the block size (by default about 64K\n");
507 get_cmd("Do you want to continue? (y/n): ");
509 Pmsg0(000, "Command aborted.\n");
513 sm_check(__FILE__, __LINE__, False);
514 block = new_block(dev);
517 for (i=1; i<500000; i++) {
518 rec->data = check_pool_memory_size(rec->data, i);
519 memset(rec->data, i & 0xFF, i);
521 sm_check(__FILE__, __LINE__, False);
522 if (write_record_to_block(block, rec)) {
525 Pmsg2(0, "Block %d i=%d\n", blkno, i);
529 sm_check(__FILE__, __LINE__, False);
533 sm_check(__FILE__, __LINE__, False);
537 * This is a general test of Bacula's functions
538 * needed to read and write the tape.
540 static void testcmd()
542 Pmsg0(0, "Append files test.\n\n\
543 I'm going to write one record in file 0,\n\
544 two records in file 1,\n\
545 and three records in file 2\n\n");
548 weofcmd(); /* end file 0 */
551 weofcmd(); /* end file 1 */
555 weofcmd(); /* end file 2 */
558 Pmsg0(0, "Now moving to end of media.\n");
560 Pmsg2(0, "End Append files test.\n\
561 We should be in file 3. I am at file %d. This is %s\n\n",
562 dev->file, dev->file == 3 ? "correct!" : "NOT correct!!!!");
564 Pmsg0(0, "\nNow I am going to attempt to append to the tape.\n");
570 Pmsg0(0, "End Append to the tape test.\n\
571 The above scan should have four files of:\n\
572 One record, two records, three records, and one record respectively.\n\n");
575 Pmsg0(0, "Append block test.\n\
576 I'm going to write a block, an EOF, rewind, go to EOM,\n\
577 then backspace over the EOF and attempt to append a second\n\
578 block in the first file.\n\n");
585 Pmsg2(0, "We should be at file 1. I am at EOM File=%d. This is %s\n",
586 dev->file, dev->file == 1 ? "correct!" : "NOT correct!!!!");
587 Pmsg0(0, "Doing backspace file.\n");
589 Pmsg0(0, "Write second block, hoping to append to first file.\n");
593 Pmsg0(0, "Done writing, scanning results\n");
595 Pmsg0(0, "The above should have one file of two blocks.\n");
603 if ((stat=fsf_dev(dev, 1)) < 0) {
604 Pmsg2(0, "Bad status from fsf %d. ERR=%s\n", stat, strerror_dev(dev));
607 Pmsg0(0, "Forward spaced one file.\n");
614 if ((stat=fsr_dev(dev, 1)) < 0) {
615 Pmsg2(0, "Bad status from fsr %d. ERR=%s\n", stat, strerror_dev(dev));
618 Pmsg0(0, "Forward spaced one record.\n");
626 if (!read_dev(dev, buf, 512*126)) {
627 Pmsg1(0, "Bad status from read. ERR=%s\n", strerror_dev(dev));
630 Pmsg1(10, "Read %d bytes\n", stat);
632 printf("Rdcmd no longer implemented.\n");
643 sm_check(__FILE__, __LINE__, False);
644 block = new_block(dev);
646 dump_block(block, "test");
648 i = block->buf_len - 100;
650 rec->data = check_pool_memory_size(rec->data, i);
651 memset(rec->data, i & 0xFF, i);
653 sm_check(__FILE__, __LINE__, False);
654 if (!write_record_to_block(block, rec)) {
655 Pmsg0(0, "Error writing record to block.\n");
658 if (!write_block_to_dev(dev, block)) {
659 Pmsg0(0, "Error writing block to device.\n");
662 Pmsg1(0, "Wrote one record of %d bytes.\n",
663 ((i+TAPE_BSIZE-1)/TAPE_BSIZE) * TAPE_BSIZE);
665 Pmsg0(0, "Wrote block to device.\n");
668 sm_check(__FILE__, __LINE__, False);
671 sm_check(__FILE__, __LINE__, False);
676 * Scan tape by reading block by block. Report what is
679 static void scancmd()
682 int blocks, tot_blocks, tot_files;
687 blocks = block_size = tot_blocks = 0;
689 if (dev->state & ST_EOT) {
690 Pmsg0(0, "End of tape\n");
694 tot_files = dev->file;
696 if ((stat = read(dev->fd, buf, sizeof(buf))) < 0) {
697 clrerror_dev(dev, -1);
698 Mmsg2(&dev->errmsg, "read error on %s. ERR=%s.\n",
699 dev->dev_name, strerror(dev->dev_errno));
700 Pmsg2(0, "Bad status from read %d. ERR=%s\n", stat, strerror_dev(dev));
702 printf("%d block%s of %d bytes in file %d\n",
703 blocks, blocks>1?"s":"", block_size, dev->file);
706 Dmsg1(200, "read status = %d\n", stat);
708 if (stat != block_size) {
711 printf("%d block%s of %d bytes in file %d\n",
712 blocks, blocks>1?"s":"", block_size, dev->file);
717 if (stat == 0) { /* EOF */
719 printf("End of File mark.\n");
720 /* Two reads of zero means end of tape */
721 if (dev->state & ST_EOF)
722 dev->state |= ST_EOT;
724 dev->state |= ST_EOF;
727 if (dev->state & ST_EOT) {
728 printf("End of tape\n");
731 } else { /* Got data */
732 dev->state &= ~ST_EOF;
739 tot_files = dev->file - tot_files;
740 printf("Total files=%d, blocks=%d, bytes = %" lld "\n", tot_files, tot_blocks, bytes);
743 static void statcmd()
751 if (!status_dev(dev, &status)) {
752 Pmsg2(0, "Bad status from status %d. ERR=%s\n", stat, strerror_dev(dev));
755 dump_volume_label(dev);
762 * First we label the tape, then we fill
763 * it with data get a new tape and write a few blocks.
765 static void fillcmd()
776 This command simulates Bacula writing to a tape.\n\
777 It command requires two blank tapes, which it\n\
778 will label and write. It will print a status approximately\n\
779 every 322 MB, and write an EOF every 3.2 GB. When the first tape\n\
780 fills, it will ask for a second, and after writing a few \n\
781 blocks, it will stop. Then it will begin re-reading the\n\
782 This may take a long time. I.e. hours! ...\n\n");
784 get_cmd("Insert a blank tape then answer. Do you wish to continue? (y/n): ");
786 Pmsg0(000, "Command aborted.\n");
790 VolumeName = "TestVolume1";
795 Dmsg1(20, "Begin append device=%s\n", dev_name(dev));
797 block = new_block(dev);
800 * Acquire output device for writing. Note, after acquiring a
801 * device, we MUST release it, which is done at the end of this
804 Dmsg0(100, "just before acquire_device\n");
805 if (!acquire_device_for_append(jcr, dev, block)) {
806 jcr->JobStatus = JS_Cancelled;
811 Dmsg0(100, "Just after acquire_device_for_append\n");
813 * Write Begin Session Record
815 if (!write_session_label(jcr, block, SOS_LABEL)) {
816 jcr->JobStatus = JS_Cancelled;
817 Jmsg1(jcr, M_FATAL, 0, _("Write session label failed. ERR=%s\n"),
822 memset(&rec, 0, sizeof(rec));
823 rec.data = get_memory(100000); /* max record size */
825 * Fill write buffer with random data
827 #define REC_SIZE 32768
829 for (int i=0; i < REC_SIZE; ) {
830 makeSessionKey(p, NULL, 0);
834 rec.data_len = REC_SIZE;
837 * Get Data from File daemon, write to device
839 jcr->VolFirstFile = 0;
840 time(&jcr->run_time); /* start counting time for rates */
841 for (file_index = 0; ok && !job_cancelled(jcr); ) {
843 rec.VolSessionId = jcr->VolSessionId;
844 rec.VolSessionTime = jcr->VolSessionTime;
845 rec.FileIndex = ++file_index;
846 rec.Stream = STREAM_FILE_DATA;
847 /* Write file_index at beginning of buffer */
848 lp = (uint64_t *)rec.data;
849 *lp = (uint64_t)file_index;
851 Dmsg4(250, "before writ_rec FI=%d SessId=%d Strm=%s len=%d\n",
852 rec.FileIndex, rec.VolSessionId, stream_to_ascii(rec.Stream, rec.FileIndex),
855 if (!write_record_to_block(block, &rec)) {
856 Dmsg2(150, "!write_record_to_block data_len=%d rem=%d\n", rec.data_len,
859 /* Write block to tape */
860 if (!flush_block(block, 1)) {
864 /* Every 5000 blocks (approx 322MB) report where we are.
866 if ((block->BlockNumber % 5000) == 0) {
868 now -= jcr->run_time;
872 kbs = (double)dev->VolCatInfo.VolCatBytes / (1000 * now);
873 Pmsg3(000, "Wrote block=%u, VolBytes=%s rate=%.1f KB/s\n", block->BlockNumber,
874 edit_uint64_with_commas(dev->VolCatInfo.VolCatBytes, ec1), (float)kbs);
876 /* Every 50000 blocks (approx 3.2MB) write an eof.
878 if ((block->BlockNumber % 50000) == 0) {
879 Pmsg0(000, "Flush block, write EOF\n");
880 flush_block(block, 0);
882 /* The weof resets the block number */
885 if (block->BlockNumber > 10 && stop) { /* get out */
890 Pmsg0(000, "Not OK\n");
893 jcr->JobBytes += rec.data_len; /* increment bytes this job */
894 Dmsg4(190, "write_record FI=%s SessId=%d Strm=%s len=%d\n",
895 FI_to_ascii(rec.FileIndex), rec.VolSessionId,
896 stream_to_ascii(rec.Stream, rec.FileIndex), rec.data_len);
898 Dmsg0(000, "Write_end_session_label()\n");
899 /* Create Job status for end of session label */
900 if (!job_cancelled(jcr) && ok) {
901 jcr->JobStatus = JS_Terminated;
903 jcr->JobStatus = JS_ErrorTerminated;
905 if (!write_session_label(jcr, block, EOS_LABEL)) {
906 Pmsg1(000, _("Error writting end session label. ERR=%s\n"), strerror_dev(dev));
909 /* Write out final block of this session */
910 if (!write_block_to_device(jcr, dev, block)) {
911 Pmsg0(000, "Set ok=FALSE after write_block_to_device.\n");
915 /* Release the device */
916 if (!release_device(jcr, dev)) {
917 Pmsg0(000, "Error in release_device\n");
922 free_memory(rec.data);
923 Pmsg0(000, "Done with fill command. Now beginning re-read of tapes...\n");
929 * Read two tapes written by the "fill" command and ensure
930 * that the data is valid.
932 static void unfillcmd()
939 block = new_block(dev);
941 dev->capabilities |= CAP_ANONVOLS; /* allow reading any volume */
942 dev->capabilities &= ~CAP_LABEL; /* don't label anything here */
945 get_cmd("Mount first of two tapes. Press enter when ready: ");
948 pm_strcpy(&jcr->VolumeName, "TestVolume1");
950 create_vol_list(jcr);
952 dev->state &= ~ST_READ;
953 if (!acquire_device_for_read(jcr, dev, block)) {
954 Pmsg0(000, dev->errmsg);
958 time(&jcr->run_time); /* start counting time for rates */
961 read_records(jcr, dev, record_cb, my_mount_next_read_volume);
964 Pmsg0(000, "Done with unfillcmd.\n");
969 * We are called here from "unfill" for each record on the
972 static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
976 if (stop > 1) { /* on second tape */
977 Pmsg4(000, "Blk: FileIndex=%d: block=%u size=%d vol=%s\n",
978 rec->FileIndex, block->BlockNumber, block->block_len, dev->VolHdr.VolName);
979 Pmsg6(000, " Rec: VId=%d VT=%d FI=%s Strm=%s len=%d state=%x\n",
980 rec->VolSessionId, rec->VolSessionTime,
981 FI_to_ascii(rec->FileIndex), stream_to_ascii(rec->Stream, rec->FileIndex),
982 rec->data_len, rec->state);
986 dump_block(block, "Block not written to previous tape");
989 if (rec->FileIndex < 0) {
991 dump_label_record(dev, rec, 1);
993 switch (rec->FileIndex) {
995 Pmsg0(000, "Volume is prelabeled. This tape cannot be scanned.\n");
998 unser_volume_label(dev, rec);
999 Pmsg3(000, "VOL_LABEL: block=%u size=%d vol=%s\n", block->BlockNumber,
1000 block->block_len, dev->VolHdr.VolName);
1004 unser_session_label(&label, rec);
1005 Pmsg1(000, "SOS_LABEL: JobId=%u\n", label.JobId);
1008 unser_session_label(&label, rec);
1009 Pmsg2(000, "EOS_LABEL: block=%u JobId=%u\n", block->BlockNumber,
1013 Pmsg0(000, "EOM_LABEL:\n");
1015 case EOT_LABEL: /* end of all tapes */
1018 if (LastBlock != block->BlockNumber) {
1019 VolBytes += block->block_len;
1021 LastBlock = block->BlockNumber;
1023 now -= jcr->run_time;
1027 kbs = (double)VolBytes / (1000 * now);
1028 Pmsg3(000, "Read block=%u, VolBytes=%s rate=%.1f KB/s\n", block->BlockNumber,
1029 edit_uint64_with_commas(VolBytes, ec1), (float)kbs);
1031 Pmsg0(000, "End of all tapes.\n");
1039 if (LastBlock != block->BlockNumber) {
1040 VolBytes += block->block_len;
1042 if ((block->BlockNumber != LastBlock) && (block->BlockNumber % 50000) == 0) {
1045 now -= jcr->run_time;
1049 kbs = (double)VolBytes / (1000 * now);
1050 Pmsg3(000, "Read block=%u, VolBytes=%s rate=%.1f KB/s\n", block->BlockNumber,
1051 edit_uint64_with_commas(VolBytes, ec1), (float)kbs);
1053 LastBlock = block->BlockNumber;
1055 Pmsg1(000, "End of all blocks. Block=%u\n", block->BlockNumber);
1062 * Write current block to tape regardless of whether or
1063 * not it is full. If the tape fills, attempt to
1064 * acquire another tape.
1066 static int flush_block(DEV_BLOCK *block, int dump)
1070 if (!write_block_to_dev(dev, block)) {
1071 Pmsg0(000, strerror_dev(dev));
1072 Pmsg3(000, "Block not written: FileIndex=%u Block=%u Size=%u\n",
1073 (unsigned)file_index, block->BlockNumber, block->block_len);
1075 dump_block(block, "Block not written");
1078 eot_block = block->BlockNumber;
1079 eot_block_len = block->block_len;
1080 eot_FileIndex = file_index;
1083 now -= jcr->run_time;
1087 kbs = (double)dev->VolCatInfo.VolCatBytes / (1000 * now);
1088 vol_size = dev->VolCatInfo.VolCatBytes;
1089 Pmsg2(000, "End of tape. VolumeCapacity=%s. Write rate = %.1f KB/s\n",
1090 edit_uint64_with_commas(dev->VolCatInfo.VolCatBytes, ec1), kbs);
1091 if (!fixup_device_block_write_error(jcr, dev, block)) {
1092 Pmsg1(000, _("Cannot fixup device error. %s\n"), strerror_dev(dev));
1099 return 1; /* write one more block to next tape then stop */
1106 struct cmdstruct { char *key; void (*func)(); char *help; };
1107 static struct cmdstruct commands[] = {
1108 {"bsf", bsfcmd, "backspace file"},
1109 {"bsr", bsrcmd, "backspace record"},
1110 {"cap", capcmd, "list device capabilities"},
1111 {"clear", clearcmd, "clear tape errors"},
1112 {"eod", eodcmd, "go to end of Bacula data for append"},
1113 {"test", testcmd, "General test Bacula tape functions"},
1114 {"eom", eomcmd, "go to the physical end of medium"},
1115 {"fill", fillcmd, "fill tape, write onto second volume"},
1116 {"unfill", unfillcmd, "read filled tape"},
1117 {"fsf", fsfcmd, "forward space a file"},
1118 {"fsr", fsrcmd, "forward space a record"},
1119 {"help", helpcmd, "print this command"},
1120 {"label", labelcmd, "write a Bacula label to the tape"},
1121 {"load", loadcmd, "load a tape"},
1122 {"quit", quitcmd, "quit btape"},
1123 {"rd", rdcmd, "read tape"},
1124 {"readlabel", readlabelcmd, "read and print the Bacula tape label"},
1125 {"rectest", rectestcmd, "test record handling functions"},
1126 {"rewind", rewindcmd, "rewind the tape"},
1127 {"scan", scancmd, "read tape block by block to EOT and report"},
1128 {"status", statcmd, "print tape status"},
1129 {"weof", weofcmd, "write an EOF on the tape"},
1130 {"wr", wrcmd, "write a single record of 2048 bytes"},
1132 #define comsize (sizeof(commands)/sizeof(struct cmdstruct))
1140 while (get_cmd("*")) {
1141 sm_check(__FILE__, __LINE__, False);
1143 for (i=0; i<comsize; i++) /* search for command */
1144 if (fstrsch(cmd, commands[i].key)) {
1145 (*commands[i].func)(); /* go execute command */
1150 Pmsg1(0, _("%s is an illegal command\n"), cmd);
1156 static void helpcmd()
1160 printf(_(" Command Description\n ======= ===========\n"));
1161 for (i=0; i<comsize; i++)
1162 printf(" %-10s %s\n", commands[i].key, commands[i].help);
1169 "\nVersion: " VERSION " (" DATE ")\n\n"
1170 "Usage: btape [-c config_file] [-d debug_level] [device_name]\n"
1171 " -c <file> set configuration file to file\n"
1172 " -dnn set debug level to nn\n"
1173 " -s turn off signals\n"
1174 " -t open the default tape device\n"
1175 " -? print this message.\n"
1181 * Get next input command from terminal. This
1182 * routine is REALLY primitive, and should be enhanced
1183 * to have correct backspacing, etc.
1186 get_cmd(char *prompt)
1190 fprintf(stdout, prompt);
1192 /* We really should turn off echoing and pretty this
1196 while ((ch = fgetc(stdin)) != EOF) {
1198 strip_trailing_junk(cmd);
1200 } else if (ch == 4 || ch == 0xd3 || ch == 0x8) {
1213 /* Dummies to replace askdir.c */
1214 int dir_get_volume_info(JCR *jcr, int writing) { return 1;}
1215 int dir_find_next_appendable_volume(JCR *jcr) { return 1;}
1216 int dir_update_volume_info(JCR *jcr, VOLUME_CAT_INFO *vol, int relabel) { return 1; }
1217 int dir_create_jobmedia_record(JCR *jcr) { return 1; }
1218 int dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec) { return 1;}
1219 int dir_send_job_status(JCR *jcr) {return 1;}
1222 int dir_ask_sysop_to_mount_volume(JCR *jcr, DEVICE *dev)
1224 Pmsg0(000, dev->errmsg); /* print reason */
1225 fprintf(stderr, "Mount Volume \"%s\" on device %s and press return when ready: ",
1226 jcr->VolumeName, dev_name(dev));
1231 int dir_ask_sysop_to_mount_next_volume(JCR *jcr, DEVICE *dev)
1233 fprintf(stderr, "Mount next Volume on device %s and press return when ready: ",
1236 VolumeName = "TestVolume2";
1242 static int my_mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
1246 Pmsg1(000, "End of Volume \"%s\"\n", jcr->VolumeName);
1248 if (LastBlock != block->BlockNumber) {
1249 VolBytes += block->block_len;
1251 LastBlock = block->BlockNumber;
1253 now -= jcr->run_time;
1257 kbs = (double)VolBytes / (1000 * now);
1258 Pmsg3(000, "Read block=%u, VolBytes=%s rate=%.1f KB/s\n", block->BlockNumber,
1259 edit_uint64_with_commas(VolBytes, ec1), (float)kbs);
1261 if (strcmp(jcr->VolumeName, "TestVolume2") == 0) {
1267 pm_strcpy(&jcr->VolumeName, "TestVolume2");
1269 create_vol_list(jcr);
1271 dev->state &= ~ST_READ;
1272 if (!acquire_device_for_read(jcr, dev, block)) {
1273 Pmsg2(0, "Cannot open Dev=%s, Vol=%s\n", dev_name(dev), jcr->VolumeName);
1276 return 1; /* next volume mounted */