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 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);
68 #define CONFIG_FILE "stored.conf"
70 static char *configfile;
71 static char cmd[1000];
72 static int signals = TRUE;
73 static int default_tape = FALSE;
76 static uint64_t vol_size;
77 static uint64_t VolBytes;
80 static long file_index;
81 static int verbose = 0;
82 static int end_of_tape = 0;
83 static uint32_t LastBlock = 0;
85 static char *VolumeName = NULL;
87 static JCR *jcr = NULL;
91 static void terminate_btape(int sig);
92 int get_cmd(char *prompt);
94 static void my_free_jcr(JCR *jcr)
97 free_pool_memory(jcr->pool_name);
98 jcr->pool_name = NULL;
100 if (jcr->pool_type) {
101 free_pool_memory(jcr->pool_type);
102 jcr->pool_type = NULL;
105 free_pool_memory(jcr->job_name);
106 jcr->job_name = NULL;
108 if (jcr->client_name) {
109 free_pool_memory(jcr->client_name);
110 jcr->client_name = NULL;
112 if (jcr->fileset_name) {
113 free_pool_memory(jcr->fileset_name);
114 jcr->fileset_name = NULL;
120 int write_dev(DEVICE *dev, char *buf, size_t len)
122 Emsg0(M_ABORT, 0, "write_dev not implemented.\n");
126 int read_dev(DEVICE *dev, char *buf, size_t len)
128 Emsg0(M_ABORT, 0, "read_dev not implemented.\n");
133 /*********************************************************************
135 * Main Bacula Pool Creation Program
138 int main(int argc, char *argv[])
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);
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);
151 printf("Tape block granularity is %d bytes.\n", TAPE_BSIZE);
153 working_directory = "/tmp";
154 my_name_is(argc, argv, "btape");
155 init_msg(NULL, NULL);
157 while ((ch = getopt(argc, argv, "c:d:stv?")) != -1) {
159 case 'c': /* specify config file */
160 if (configfile != NULL) {
163 configfile = bstrdup(optarg);
166 case 'd': /* set debug level */
167 debug_level = atoi(optarg);
168 if (debug_level <= 0) {
198 init_signals(terminate_btape);
201 if (configfile == NULL) {
202 configfile = bstrdup(CONFIG_FILE);
205 daemon_start_time = time(NULL);
207 parse_config(configfile);
210 /* See if we can open a device */
212 if (!(dev = init_dev(NULL, *argv))) {
218 /* Try default device */
219 if (!dev && default_tape) {
220 dev = init_dev(NULL, DEFAULT_TAPE_DRIVE);
224 if (!find_device_res()) {
227 if (!open_device(dev)) {
228 Pmsg1(0, "Warning could not open device. ERR=%s", strerror_dev(dev));
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);
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");
251 jcr->JobType = JT_BACKUP;
252 jcr->JobLevel = L_FULL;
253 jcr->JobStatus = JS_Terminated;
256 Dmsg0(200, "Do tape commands\n");
263 static void terminate_btape(int stat)
266 sm_check(__FILE__, __LINE__, False);
270 free_config_resources();
276 if (debug_level > 10)
277 print_memory_pool_stats();
283 close_memory_pool(); /* free memory in pool */
295 * Get a new device name
296 * Normally given on the command line
298 static void devicecmd()
304 if (!get_cmd("Enter Device Name: ")) {
307 dev = init_dev(NULL, cmd);
309 if (!find_device_res()) {
312 if (!open_device(dev)) {
313 Pmsg1(0, "Device open failed. ERR=%s\n", strerror_dev(dev));
316 Pmsg0(0, "Device init failed.\n");
321 * Write a label to the tape
323 static void labelcmd()
329 Pmsg0(0, "No device: Use device command.\n");
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 */
338 dev->device = device;
345 Pmsg2(0, "Could not find device %s in %s\n", dev->dev_name, configfile);
350 strcpy(cmd, VolumeName);
352 if (!get_cmd("Enter Volume Name: ")) {
357 if (!(dev->state & ST_OPENED)) {
358 if (!open_device(dev)) {
359 Pmsg1(0, "Device open failed. ERR=%s\n", strerror_dev(dev));
362 write_volume_label_to_dev(jcr, device, cmd, "Default");
366 * Read the tape label
368 static void readlabelcmd()
370 int save_debug_level = debug_level;
375 Pmsg0(0, "No device: Use device command.\n");
378 block = new_block(dev);
379 stat = read_dev_volume_label(jcr, dev, block);
382 Pmsg0(0, "Volume has no label.\n");
385 Pmsg0(0, "Volume label read correctly.\n");
388 Pmsg1(0, "I/O error on device: ERR=%s", strerror_dev(dev));
391 Pmsg0(0, "Volume name error\n");
393 case VOL_CREATE_ERROR:
394 Pmsg1(0, "Error creating label. ERR=%s", strerror_dev(dev));
396 case VOL_VERSION_ERROR:
397 Pmsg0(0, "Volume version error.\n");
399 case VOL_LABEL_ERROR:
400 Pmsg0(0, "Bad Volume label type.\n");
403 Pmsg0(0, "Unknown error.\n");
408 dump_volume_label(dev);
409 debug_level = save_debug_level;
415 * Search for device resource that corresponds to
416 * device name on command line (or default).
418 * Returns: 0 on failure
421 static int find_device_res()
426 for (device=NULL; (device=(DEVRES *)GetNextRes(R_DEVICE, (RES *)device)); ) {
427 if (strcmp(device->device_name, dev->dev_name) == 0) {
429 dev->capabilities = device->cap_bits;
436 Pmsg2(0, "Could not find device %s in %s\n", dev->dev_name, configfile);
439 Pmsg1(0, "Using device: %s\n", dev->dev_name);
444 * Load the tape should have prevously been taken
445 * off line, otherwise this command is not necessary.
447 static void loadcmd()
451 Pmsg0(0, "No device: Use device command.\n");
454 if (!load_dev(dev)) {
455 Pmsg1(0, "Bad status from load. ERR=%s\n", strerror_dev(dev));
457 Pmsg1(0, "Loaded %s\n", dev_name(dev));
463 static void rewindcmd()
466 Pmsg0(0, "No device: Use device command.\n");
469 if (!rewind_dev(dev)) {
470 Pmsg1(0, "Bad status from rewind. ERR=%s\n", strerror_dev(dev));
471 clrerror_dev(dev, -1);
473 Pmsg1(0, "Rewound %s\n", dev_name(dev));
477 * Clear any tape error
479 static void clearcmd()
482 Pmsg0(0, "No device: Use device command.\n");
485 clrerror_dev(dev, -1);
489 * Write and end of file on the tape
491 static void weofcmd()
496 Pmsg0(0, "No device: Use device command.\n");
499 if ((stat = weof_dev(dev, 1)) < 0) {
500 Pmsg2(0, "Bad status from weof %d. ERR=%s\n", stat, strerror_dev(dev));
503 Pmsg1(0, "Wrote EOF to %s\n", dev_name(dev));
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
517 Pmsg0(0, "No device: Use device command.\n");
521 Pmsg1(0, "Bad status from eod. ERR=%s\n", strerror_dev(dev));
524 Pmsg0(0, "Moved to end of media\n");
529 * Go to the end of the media (either hardware determined
530 * or defined by two eofs.
544 Pmsg0(0, "No device: Use device command.\n");
547 if ((stat=bsf_dev(dev, 1)) < 0) {
548 Pmsg1(0, "Bad status from bsf. ERR=%s\n", strerror(errno));
550 Pmsg0(0, "Back spaced one file.\n");
561 Pmsg0(0, "No device: Use device command.\n");
564 if ((stat=bsr_dev(dev, 1)) < 0) {
565 Pmsg1(0, "Bad status from bsr. ERR=%s\n", strerror(errno));
567 Pmsg0(0, "Back spaced one record.\n");
572 * List device capabilities as defined in the
578 Pmsg0(0, "No device: Use device command.\n");
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 ? "" : "!");
598 * Test writting larger and larger records.
599 * This is a torture test for records.
601 static void rectestcmd()
608 Pmsg0(0, "No device: Use device command.\n");
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");
618 get_cmd("Do you want to continue? (y/n): ");
620 Pmsg0(000, "Command aborted.\n");
624 sm_check(__FILE__, __LINE__, False);
625 block = new_block(dev);
628 for (i=1; i<500000; i++) {
629 rec->data = check_pool_memory_size(rec->data, i);
630 memset(rec->data, i & 0xFF, i);
632 sm_check(__FILE__, __LINE__, False);
633 if (write_record_to_block(block, rec)) {
636 Pmsg2(0, "Block %d i=%d\n", blkno, i);
640 sm_check(__FILE__, __LINE__, False);
644 sm_check(__FILE__, __LINE__, False);
648 * This is a general test of Bacula's functions
649 * needed to read and write the tape.
651 static void testcmd()
654 Pmsg0(0, "No device: Use device command.\n");
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");
663 weofcmd(); /* end file 0 */
666 weofcmd(); /* end file 1 */
670 weofcmd(); /* end file 2 */
673 Pmsg0(0, "Now moving to end of media.\n");
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!!!!");
679 Pmsg0(0, "\nNow I am going to attempt to append to the tape.\n");
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");
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");
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");
704 Pmsg0(0, "Write second block, hoping to append to first file.\n");
708 Pmsg0(0, "Done writing, scanning results\n");
710 Pmsg0(0, "The above should have one file of two blocks.\n");
718 Pmsg0(0, "No device: Use device command.\n");
721 if ((stat=fsf_dev(dev, 1)) < 0) {
722 Pmsg2(0, "Bad status from fsf %d. ERR=%s\n", stat, strerror_dev(dev));
725 Pmsg0(0, "Forward spaced one file.\n");
732 Pmsg0(0, "No device: Use device command.\n");
735 if ((stat=fsr_dev(dev, 1)) < 0) {
736 Pmsg2(0, "Bad status from fsr %d. ERR=%s\n", stat, strerror_dev(dev));
739 Pmsg0(0, "Forward spaced one record.\n");
748 Pmsg0(0, "No device: Use device command.\n");
751 if (!read_dev(dev, buf, 512*126)) {
752 Pmsg1(0, "Bad status from read. ERR=%s\n", strerror_dev(dev));
755 Pmsg1(10, "Read %d bytes\n", stat);
757 printf("Rdcmd no longer implemented.\n");
769 Pmsg0(0, "No device: Use device command.\n");
772 sm_check(__FILE__, __LINE__, False);
773 block = new_block(dev);
777 rec->data = (char *) check_pool_memory_size(rec->data, i);
778 memset(rec->data, i & 0xFF, i);
780 sm_check(__FILE__, __LINE__, False);
781 if (!write_record_to_block(block, rec)) {
782 Pmsg0(0, "Error writing record to block.\n");
785 if (!write_block_to_dev(dev, block)) {
786 Pmsg0(0, "Error writing block to device.\n");
789 Pmsg1(0, "Wrote one record of %d bytes.\n",
790 ((i+TAPE_BSIZE-1)/TAPE_BSIZE) * TAPE_BSIZE);
793 sm_check(__FILE__, __LINE__, False);
796 sm_check(__FILE__, __LINE__, False);
797 Pmsg0(0, "Wrote block to device.\n");
802 * Scan tape by reading block by block. Report what is
805 static void scancmd()
808 int blocks, tot_blocks, tot_files;
813 Pmsg0(0, "No device: Use device command.\n");
817 blocks = block_size = tot_blocks = 0;
819 if (dev->state & ST_EOT) {
820 Pmsg0(0, "End of tape\n");
824 tot_files = dev->file;
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));
832 printf("%d block%s of %d bytes in file %d\n",
833 blocks, blocks>1?"s":"", block_size, dev->file);
836 Dmsg1(200, "read status = %d\n", stat);
838 if (stat != block_size) {
841 printf("%d block%s of %d bytes in file %d\n",
842 blocks, blocks>1?"s":"", block_size, dev->file);
847 if (stat == 0) { /* EOF */
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;
854 dev->state |= ST_EOF;
857 if (dev->state & ST_EOT) {
858 printf("End of tape\n");
861 } else { /* Got data */
862 dev->state &= ~ST_EOF;
869 tot_files = dev->file - tot_files;
870 printf("Total files=%d, blocks=%d, bytes = %" lld "\n", tot_files, tot_blocks, bytes);
873 static void statcmd()
880 Pmsg0(0, "No device: Use device command.\n");
885 if (!status_dev(dev, &status)) {
886 Pmsg2(0, "Bad status from status %d. ERR=%s\n", stat, strerror_dev(dev));
889 dump_volume_label(dev);
896 * First we label the tape, then we fill
897 * it with data get a new tape and write a few blocks.
899 static void fillcmd()
907 Pmsg0(0, "No device: Use device command.\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");
923 get_cmd("Do you wish to continue? (y/n): ");
925 Pmsg0(000, "Command aborted.\n");
929 VolumeName = "TestVolume1";
934 Dmsg1(20, "Begin append device=%s\n", dev_name(dev));
936 block = new_block(dev);
939 * Acquire output device for writing. Note, after acquiring a
940 * device, we MUST release it, which is done at the end of this
943 Dmsg0(100, "just before acquire_device\n");
944 if (!acquire_device_for_append(jcr, dev, block)) {
945 jcr->JobStatus = JS_Cancelled;
950 Dmsg0(100, "Just after acquire_device_for_append\n");
952 * Write Begin Session Record
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"),
961 memset(&rec, 0, sizeof(rec));
962 rec.data = get_memory(100000); /* max record size */
964 * Fill write buffer with random data
966 #define REC_SIZE 32768
968 for (int i=0; i < REC_SIZE; ) {
969 makeSessionKey(p, NULL, 0);
973 rec.data_len = REC_SIZE;
976 * Get Data from File daemon, write to device
978 jcr->VolFirstFile = 0;
979 time(&jcr->run_time); /* start counting time for rates */
980 for (file_index = 0; ok && !job_cancelled(jcr); ) {
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;
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),
994 if (!write_record_to_block(block, &rec)) {
995 Dmsg2(150, "!write_record_to_block data_len=%d rem=%d\n", rec.data_len,
997 if (!flush_block(block)) {
1001 /* Every 5000 blocks (approx 322MB) report where we are.
1003 if ((block->BlockNumber % 5000) == 0) {
1005 now -= jcr->run_time;
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);
1013 /* Every 50000 blocks (approx 3.2MB) write an eof.
1015 if ((block->BlockNumber % 50000) == 0) {
1016 Pmsg0(000, "Flush block, write EOF\n");
1019 /* The weof resets the block number */
1022 if (block->BlockNumber > 10 && stop) { /* get out */
1027 Pmsg0(000, "Not OK\n");
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);
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;
1040 jcr->JobStatus = JS_ErrorTerminated;
1042 if (!write_session_label(jcr, block, EOS_LABEL)) {
1043 Pmsg1(000, _("Error writting end session label. ERR=%s\n"), strerror_dev(dev));
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");
1052 /* Release the device */
1053 if (!release_device(jcr, dev)) {
1054 Pmsg0(000, "Error in release_device\n");
1059 Pmsg0(000, "Done with fill command. Now beginning re-read of tapes...\n");
1065 * Read two tapes written by the "fill" command and ensure
1066 * that the data is valid.
1068 static void unfillcmd()
1074 block = new_block(dev);
1076 dev->capabilities |= CAP_ANONVOLS; /* allow reading any volume */
1077 dev->capabilities &= ~CAP_LABEL; /* don't label anything here */
1080 get_cmd("Mount first of two tapes. Press enter when ready: ");
1082 pm_strcpy(&jcr->VolumeName, "TestVolume1");
1084 dev->state &= ~ST_READ;
1085 if (!acquire_device_for_read(jcr, dev, block)) {
1086 Pmsg0(000, dev->errmsg);
1090 time(&jcr->run_time); /* start counting time for rates */
1091 read_records(jcr, dev, record_cb, my_mount_next_read_volume);
1094 Pmsg0(000, "Done with unfillcmd.\n");
1098 static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
1100 SESSION_LABEL label;
1101 if (rec->FileIndex < 0) {
1103 dump_label_record(dev, rec, 1);
1105 switch (rec->FileIndex) {
1107 Pmsg0(000, "Volume is prelabeled. This tape cannot be scanned.\n");
1110 unser_volume_label(dev, rec);
1111 Pmsg2(000, "VOL_LABEL: block=%u vol=%s\n", block->BlockNumber,
1112 dev->VolHdr.VolName);
1115 unser_session_label(&label, rec);
1116 Pmsg1(000, "SOS_LABEL: JobId=%u\n", label.JobId);
1119 unser_session_label(&label, rec);
1120 Pmsg2(000, "EOS_LABEL: block=%u JobId=%u\n", block->BlockNumber,
1124 Pmsg0(000, "EOM_LABEL:\n");
1126 case EOT_LABEL: /* end of all tapes */
1129 if (LastBlock != block->BlockNumber) {
1130 VolBytes += block->block_len;
1132 LastBlock = block->BlockNumber;
1134 now -= jcr->run_time;
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);
1142 Pmsg0(000, "End of all tapes.\n");
1150 if (LastBlock != block->BlockNumber) {
1151 VolBytes += block->block_len;
1153 if ((block->BlockNumber != LastBlock) && (block->BlockNumber % 50000) == 0) {
1156 now -= jcr->run_time;
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);
1164 LastBlock = block->BlockNumber;
1166 Pmsg1(000, "End of all blocks. Block=%u\n", block->BlockNumber);
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.
1177 static int flush_block(DEV_BLOCK *block)
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);
1185 now -= jcr->run_time;
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));
1199 Pmsg1(000, "Changed tapes. Block=%u\n", block->BlockNumber);
1202 return 1; /* write one more block to next tape then stop */
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"},
1236 #define comsize (sizeof(commands)/sizeof(struct cmdstruct))
1244 while (get_cmd("*")) {
1245 sm_check(__FILE__, __LINE__, False);
1247 for (i=0; i<comsize; i++) /* search for command */
1248 if (fstrsch(cmd, commands[i].key)) {
1249 (*commands[i].func)(); /* go execute command */
1254 Pmsg1(0, "%s is an illegal command\n", cmd);
1260 static void helpcmd()
1264 printf(" Command Description\n ======= ===========\n");
1265 for (i=0; i<comsize; i++)
1266 printf(" %-10s %s\n", commands[i].key, commands[i].help);
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"
1285 * Get next input command from terminal. This
1286 * routine is REALLY primitive, and should be enhanced
1287 * to have correct backspacing, etc.
1290 get_cmd(char *prompt)
1294 fprintf(stdout, prompt);
1296 /* We really should turn off echoing and pretty this
1300 while ((ch = fgetc(stdin)) != EOF) {
1302 strip_trailing_junk(cmd);
1304 } else if (ch == 4 || ch == 0xd3 || ch == 0x8) {
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;}
1326 int dir_ask_sysop_to_mount_volume(JCR *jcr, DEVICE *dev)
1328 fprintf(stderr, "Mount Volume \"%s\" on device %s and press return when ready: ",
1329 jcr->VolumeName, dev_name(dev));
1334 int dir_ask_sysop_to_mount_next_volume(JCR *jcr, DEVICE *dev)
1336 fprintf(stderr, "Mount next Volume on device %s and press return when ready: ",
1339 VolumeName = "TestVolume2";
1345 static int my_mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
1349 Pmsg1(000, "End of Volume \"%s\"\n", jcr->VolumeName);
1351 if (LastBlock != block->BlockNumber) {
1352 VolBytes += block->block_len;
1354 LastBlock = block->BlockNumber;
1356 now -= jcr->run_time;
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);
1364 if (strcmp(jcr->VolumeName, "TestVolume2") == 0) {
1368 pm_strcpy(&jcr->VolumeName, "TestVolume2");
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);
1375 return 1; /* next volume mounted */