X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fstored%2Fbtape.c;h=f0649111835a67f081249b0ab163b32519978599;hb=908d0c5a7c352c4473409fd01cab16d968c41b43;hp=ee09cb4929a9d13075c3fad948785f86a73d5031;hpb=377a71f98559788828c6cded7a9cd96d2606c6c1;p=bacula%2Fbacula diff --git a/bacula/src/stored/btape.c b/bacula/src/stored/btape.c index ee09cb4929..f064911183 100644 --- a/bacula/src/stored/btape.c +++ b/bacula/src/stored/btape.c @@ -1,3 +1,30 @@ +/* + Bacula® - The Network Backup Solution + + Copyright (C) 2000-2008 Free Software Foundation Europe e.V. + + The main author of Bacula is Kern Sibbald, with contributions from + many others, a complete list can be found in the file AUTHORS. + This program is Free Software; you can redistribute it and/or + modify it under the terms of version two of the GNU General Public + License as published by the Free Software Foundation and included + in the file LICENSE. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. + + Bacula® is a registered trademark of Kern Sibbald. + The licensor of Bacula is the Free Software Foundation Europe + (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, + Switzerland, email:ftf@fsfeurope.org. +*/ /* * * Bacula Tape manipulation program @@ -13,29 +40,17 @@ * Version $Id$ * */ -/* - Copyright (C) 2000-2005 Kern Sibbald - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of - the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public - License along with this program; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA. - - */ #include "bacula.h" #include "stored.h" +#ifdef USE_VTAPE +#include "vtape.h" +#endif + +/* Dummy functions */ +int generate_daemon_event(JCR *jcr, const char *event) { return 1; } +extern bool parse_sd_config(CONFIG *config, const char *configfile, int exit_code); /* External subroutines */ extern void free_config_resources(); @@ -69,6 +84,7 @@ static void rewindcmd(); static void clearcmd(); static void wrcmd(); static void rrcmd(); +static void rbcmd(); static void eodcmd(); static void fillcmd(); static void qfillcmd(); @@ -81,15 +97,15 @@ static bool my_mount_next_read_volume(DCR *dcr); static void scan_blocks(); static void set_volume_name(const char *VolName, int volnum); static void rawfill_cmd(); -static void bfill_cmd(); static bool open_the_device(); static void autochangercmd(); static void do_unfill(); /* Static variables */ +static CONFIG *config; #define CONFIG_FILE "bacula-sd.conf" -char *configfile; +char *configfile = NULL; #define MAX_CMD_ARGS 30 static POOLMEM *cmd; @@ -99,6 +115,7 @@ static char *argv[MAX_CMD_ARGS]; static int argc; static int quickie_count = 0; +static uint64_t write_count = 0; static BSR *bsr = NULL; static int signals = TRUE; static bool ok; @@ -141,7 +158,7 @@ int get_cmd(const char *prompt); /********************************************************************* * - * Main Bacula Pool Creation Program + * Bacula tape testing program * */ int main(int margc, char *margv[]) @@ -150,24 +167,29 @@ int main(int margc, char *margv[]) uint32_t x32, y32; uint64_t x64, y64; char buf[1000]; + + setlocale(LC_ALL, ""); + bindtextdomain("bacula", LOCALEDIR); + textdomain("bacula"); + init_stack_dump(); /* Sanity checks */ if (TAPE_BSIZE % B_DEV_BSIZE != 0 || TAPE_BSIZE / B_DEV_BSIZE == 0) { - Emsg2(M_ABORT, 0, "Tape block size (%d) not multiple of system size (%d)\n", + Emsg2(M_ABORT, 0, _("Tape block size (%d) not multiple of system size (%d)\n"), TAPE_BSIZE, B_DEV_BSIZE); } if (TAPE_BSIZE != (1 << (ffs(TAPE_BSIZE)-1))) { - Emsg1(M_ABORT, 0, "Tape block size (%d) is not a power of 2\n", TAPE_BSIZE); + Emsg1(M_ABORT, 0, _("Tape block size (%d) is not a power of 2\n"), TAPE_BSIZE); } - if (sizeof(off_t) < 8) { - Pmsg1(-1, "\n\n!!!! Warning large disk addressing disabled. off_t=%d should be 8 or more !!!!!\n\n\n", - sizeof(off_t)); + if (sizeof(boffset_t) < 8) { + Pmsg1(-1, _("\n\n!!!! Warning large disk addressing disabled. boffset_t=%d should be 8 or more !!!!!\n\n\n"), + sizeof(boffset_t)); } x32 = 123456789; bsnprintf(buf, sizeof(buf), "%u", x32); - i = bsscanf(buf, "%u", &y32); + i = bsscanf(buf, "%lu", &y32); if (i != 1 || x32 != y32) { - Pmsg3(-1, "32 bit printf/scanf problem. i=%d x32=%u y32=%u\n", i, x32, y32); + Pmsg3(-1, _("32 bit printf/scanf problem. i=%d x32=%u y32=%u\n"), i, x32, y32); exit(1); } x64 = 123456789; @@ -176,16 +198,19 @@ int main(int margc, char *margv[]) bsnprintf(buf, sizeof(buf), "%" llu, x64); i = bsscanf(buf, "%llu", &y64); if (i != 1 || x64 != y64) { - Pmsg3(-1, "64 bit printf/scanf problem. i=%d x64=%" llu " y64=%" llu "\n", i, x64, y64); + Pmsg3(-1, _("64 bit printf/scanf problem. i=%d x64=%" llu " y64=%" llu "\n"), + i, x64, y64); exit(1); } - printf("Tape block granularity is %d bytes.\n", TAPE_BSIZE); + printf(_("Tape block granularity is %d bytes.\n"), TAPE_BSIZE); working_directory = "/tmp"; my_name_is(margc, margv, "btape"); init_msg(NULL, NULL); + OSDependentInit(); + while ((ch = getopt(margc, margv, "b:c:d:psv?")) != -1) { switch (ch) { case 'b': /* bootstrap file */ @@ -201,9 +226,13 @@ int main(int margc, char *margv[]) break; case 'd': /* set debug level */ - debug_level = atoi(optarg); - if (debug_level <= 0) { - debug_level = 1; + if (*optarg == 't') { + dbg_timestamp = true; + } else { + debug_level = atoi(optarg); + if (debug_level <= 0) { + debug_level = 1; + } } break; @@ -242,16 +271,16 @@ int main(int margc, char *margv[]) daemon_start_time = time(NULL); - parse_config(configfile); - + config = new_config_parser(); + parse_sd_config(config, configfile, M_ERROR_TERM); /* See if we can open a device */ if (margc == 0) { - Pmsg0(000, "No archive name specified.\n"); + Pmsg0(000, _("No archive name specified.\n")); usage(); exit(1); } else if (margc != 1) { - Pmsg0(000, "Improper number of arguments specified.\n"); + Pmsg0(000, _("Improper number of arguments specified.\n")); usage(); exit(1); } @@ -264,6 +293,16 @@ int main(int margc, char *margv[]) if (!dev) { exit(1); } + if (dev->is_dvd()) { + Pmsg0(000, _("btape does not work with DVD storage.\n")); + usage(); + exit(1); + } + if (!dev->is_tape()) { + Pmsg0(000, _("btape only works with tape storage.\n")); + usage(); + exit(1); + } dcr = jcr->dcr; if (!open_the_device()) { goto terminate; @@ -284,7 +323,11 @@ static void terminate_btape(int stat) if (configfile) { free(configfile); } - free_config_resources(); + if (config) { + config->free_resources(); + free(config); + config = NULL; + } if (args) { free_pool_memory(args); args = NULL; @@ -302,9 +345,11 @@ static void terminate_btape(int stat) jcr = NULL; if (dev) { - term_dev(dev); + dev->term(); } + free_volume_list(); + if (debug_level > 10) print_memory_pool_stats(); @@ -315,6 +360,7 @@ static void terminate_btape(int stat) stop_watchdog(); term_msg(); close_memory_pool(); /* free memory in pool */ + term_last_jobs_list(); sm_dump(false); exit(stat); @@ -323,23 +369,23 @@ static void terminate_btape(int stat) static bool open_the_device() { DEV_BLOCK *block; + bool ok = true; block = new_block(dev); - lock_device(dev); - if (!dev->is_open()) { - Dmsg1(200, "Opening device %s\n", dcr->VolumeName); - if (open_dev(dev, dcr->VolumeName, OPEN_READ_WRITE) < 0) { - Emsg1(M_FATAL, 0, _("dev open failed: %s\n"), dev->errmsg); - unlock_device(dev); - free_block(block); - return false; - } + dev->r_dlock(); + Dmsg1(200, "Opening device %s\n", dcr->VolumeName); + if (dev->open(dcr, OPEN_READ_WRITE) < 0) { + Emsg1(M_FATAL, 0, _("dev open failed: %s\n"), dev->errmsg); + ok = false; + goto bail_out; } - Pmsg1(000, "open_dev %s OK\n", dev->print_name()); + Pmsg1(000, _("open device %s: OK\n"), dev->print_name()); dev->set_append(); /* put volume in append mode */ - unlock_device(dev); + +bail_out: + dev->dunlock(); free_block(block); - return true; + return ok; } @@ -356,19 +402,20 @@ static void labelcmd() if (VolumeName) { pm_strcpy(cmd, VolumeName); } else { - if (!get_cmd("Enter Volume Name: ")) { + if (!get_cmd(_("Enter Volume Name: "))) { return; } } if (!dev->is_open()) { - if (!first_open_device(dev)) { - Pmsg1(0, "Device open failed. ERR=%s\n", strerror_dev(dev)); + if (!first_open_device(dcr)) { + Pmsg1(0, _("Device open failed. ERR=%s\n"), dev->bstrerror()); } } - rewind_dev(dev); - write_new_volume_label_to_dev(dcr, cmd, "Default"); - Pmsg1(-1, "Wrote Volume label for volume \"%s\".\n", cmd); + dev->rewind(dcr); + dev->weof(1); + write_new_volume_label_to_dev(dcr, cmd, "Default", false,/*no relabel*/ true /* label dvd now */); + Pmsg1(-1, _("Wrote Volume label for volume \"%s\".\n"), cmd); } /* @@ -382,28 +429,28 @@ static void readlabelcmd() stat = read_dev_volume_label(dcr); switch (stat) { case VOL_NO_LABEL: - Pmsg0(0, "Volume has no label.\n"); + Pmsg0(0, _("Volume has no label.\n")); break; case VOL_OK: - Pmsg0(0, "Volume label read correctly.\n"); + Pmsg0(0, _("Volume label read correctly.\n")); break; case VOL_IO_ERROR: - Pmsg1(0, "I/O error on device: ERR=%s", strerror_dev(dev)); + Pmsg1(0, _("I/O error on device: ERR=%s"), dev->bstrerror()); break; case VOL_NAME_ERROR: - Pmsg0(0, "Volume name error\n"); + Pmsg0(0, _("Volume name error\n")); break; case VOL_CREATE_ERROR: - Pmsg1(0, "Error creating label. ERR=%s", strerror_dev(dev)); + Pmsg1(0, _("Error creating label. ERR=%s"), dev->bstrerror()); break; case VOL_VERSION_ERROR: - Pmsg0(0, "Volume version error.\n"); + Pmsg0(0, _("Volume version error.\n")); break; case VOL_LABEL_ERROR: - Pmsg0(0, "Bad Volume label type.\n"); + Pmsg0(0, _("Bad Volume label type.\n")); break; default: - Pmsg0(0, "Unknown error.\n"); + Pmsg0(0, _("Unknown error.\n")); break; } @@ -421,9 +468,9 @@ static void loadcmd() { if (!load_dev(dev)) { - Pmsg1(0, "Bad status from load. ERR=%s\n", strerror_dev(dev)); + Pmsg1(0, _("Bad status from load. ERR=%s\n"), dev->bstrerror()); } else - Pmsg1(0, "Loaded %s\n", dev->print_name()); + Pmsg1(0, _("Loaded %s\n"), dev->print_name()); } /* @@ -431,11 +478,11 @@ static void loadcmd() */ static void rewindcmd() { - if (!rewind_dev(dev)) { - Pmsg1(0, "Bad status from rewind. ERR=%s\n", strerror_dev(dev)); - clrerror_dev(dev, -1); + if (!dev->rewind(dcr)) { + Pmsg1(0, _("Bad status from rewind. ERR=%s\n"), dev->bstrerror()); + dev->clrerror(-1); } else { - Pmsg1(0, "Rewound %s\n", dev->print_name()); + Pmsg1(0, _("Rewound %s\n"), dev->print_name()); } } @@ -444,7 +491,7 @@ static void rewindcmd() */ static void clearcmd() { - clrerror_dev(dev, -1); + dev->clrerror(-1); } /* @@ -452,7 +499,6 @@ static void clearcmd() */ static void weofcmd() { - int stat; int num = 1; if (argc > 1) { num = atoi(argk[1]); @@ -461,11 +507,16 @@ static void weofcmd() num = 1; } - if ((stat = weof_dev(dev, num)) < 0) { - Pmsg2(0, "Bad status from weof %d. ERR=%s\n", stat, strerror_dev(dev)); + if (!dev->weof(num)) { + Pmsg1(0, _("Bad status from weof. ERR=%s\n"), dev->bstrerror()); return; } else { - Pmsg3(0, "Wrote %d EOF%s to %s\n", num, num==1?"":"s", dev->print_name()); + if (num==1) { + Pmsg1(0, _("Wrote 1 EOF to %s\n"), dev->print_name()); + } + else { + Pmsg2(0, _("Wrote %d EOFs to %s\n"), num, dev->print_name()); + } } } @@ -478,8 +529,8 @@ static void weofcmd() */ static void eomcmd() { - if (!eod_dev(dev)) { - Pmsg1(0, "%s", strerror_dev(dev)); + if (!dev->eod(dcr)) { + Pmsg1(0, "%s", dev->bstrerror()); return; } else { Pmsg0(0, _("Moved to end of medium.\n")); @@ -508,8 +559,8 @@ static void bsfcmd() num = 1; } - if (!bsf_dev(dev, num)) { - Pmsg1(0, _("Bad status from bsf. ERR=%s\n"), strerror_dev(dev)); + if (!dev->bsf(num)) { + Pmsg1(0, _("Bad status from bsf. ERR=%s\n"), dev->bstrerror()); } else { Pmsg2(0, _("Backspaced %d file%s.\n"), num, num==1?"":"s"); } @@ -527,8 +578,8 @@ static void bsrcmd() if (num <= 0) { num = 1; } - if (!bsr_dev(dev, num)) { - Pmsg1(0, _("Bad status from bsr. ERR=%s\n"), strerror_dev(dev)); + if (!dev->bsr(num)) { + Pmsg1(0, _("Bad status from bsr. ERR=%s\n"), dev->bstrerror()); } else { Pmsg2(0, _("Backspaced %d record%s.\n"), num, num==1?"":"s"); } @@ -577,7 +628,7 @@ static void capcmd() printf("File=%u block=%u\n", dev->file, dev->block_num); printf("Min block=%u Max block=%u\n", dev->min_block_size, dev->max_block_size); - printf("Status:\n"); + printf(_("Status:\n")); statcmd(); } @@ -592,15 +643,15 @@ static void rectestcmd() DEV_RECORD *rec; int i, blkno = 0; - Pmsg0(0, "Test writting larger and larger records.\n" + Pmsg0(0, _("Test writting larger and larger records.\n" "This is a torture test for records.\nI am going to write\n" "larger and larger records. It will stop when the record size\n" -"plus the header exceeds the block size (by default about 64K)\n"); +"plus the header exceeds the block size (by default about 64K)\n")); - get_cmd("Do you want to continue? (y/n): "); + get_cmd(_("Do you want to continue? (y/n): ")); if (cmd[0] != 'y') { - Pmsg0(000, "Command aborted.\n"); + Pmsg0(000, _("Command aborted.\n")); return; } @@ -616,7 +667,7 @@ static void rectestcmd() if (write_record_to_block(block, rec)) { empty_block(block); blkno++; - Pmsg2(0, "Block %d i=%d\n", blkno, i); + Pmsg2(0, _("Block %d i=%d\n"), blkno, i); } else { break; } @@ -691,34 +742,34 @@ static int re_read_block_test() Pmsg1(0, _("Wrote third record of %d bytes.\n"), rec->data_len); } weofcmd(); - if (dev_cap(dev, CAP_TWOEOF)) { + if (dev->has_cap(CAP_TWOEOF)) { weofcmd(); } - if (!bsf_dev(dev, 1)) { - Pmsg1(0, _("Backspace file failed! ERR=%s\n"), strerror_dev(dev)); + if (!dev->bsf(1)) { + Pmsg1(0, _("Backspace file failed! ERR=%s\n"), dev->bstrerror()); goto bail_out; } - if (dev_cap(dev, CAP_TWOEOF)) { - if (!bsf_dev(dev, 1)) { - Pmsg1(0, _("Backspace file failed! ERR=%s\n"), strerror_dev(dev)); + if (dev->has_cap(CAP_TWOEOF)) { + if (!dev->bsf(1)) { + Pmsg1(0, _("Backspace file failed! ERR=%s\n"), dev->bstrerror()); goto bail_out; } } - Pmsg0(0, "Backspaced over EOF OK.\n"); - if (!bsr_dev(dev, 1)) { - Pmsg1(0, _("Backspace record failed! ERR=%s\n"), strerror_dev(dev)); + Pmsg0(0, _("Backspaced over EOF OK.\n")); + if (!dev->bsr(1)) { + Pmsg1(0, _("Backspace record failed! ERR=%s\n"), dev->bstrerror()); goto bail_out; } - Pmsg0(0, "Backspace record OK.\n"); + Pmsg0(0, _("Backspace record OK.\n")); if (!read_block_from_dev(dcr, NO_BLOCK_NUMBER_CHECK)) { berrno be; - Pmsg1(0, _("Read block failed! ERR=%s\n"), be.strerror(dev->dev_errno)); + Pmsg1(0, _("Read block failed! ERR=%s\n"), be.bstrerror(dev->dev_errno)); goto bail_out; } memset(rec->data, 0, rec->data_len); - if (!read_record_from_block(block, rec)) { + if (!read_record_from_block(dcr, block, rec)) { berrno be; - Pmsg1(0, _("Read block failed! ERR=%s\n"), be.strerror(dev->dev_errno)); + Pmsg1(0, _("Read block failed! ERR=%s\n"), be.bstrerror(dev->dev_errno)); goto bail_out; } for (int i=0; iblock; rec = new_record(); - if (!rewind_dev(dev)) { - Pmsg1(0, "Bad status from rewind. ERR=%s\n", strerror_dev(dev)); + if (!dev->rewind(dcr)) { + Pmsg1(0, _("Bad status from rewind. ERR=%s\n"), dev->bstrerror()); goto bail_out; } rec->data = check_pool_memory_size(rec->data, block->buf_len); @@ -805,14 +856,14 @@ static int write_read_test() } Pmsg1(0, _("Wrote 1000 blocks of %d bytes.\n"), rec->data_len); weofcmd(); - if (dev_cap(dev, CAP_TWOEOF)) { + if (dev->has_cap(CAP_TWOEOF)) { weofcmd(); } - if (!rewind_dev(dev)) { - Pmsg1(0, "Bad status from rewind. ERR=%s\n", strerror_dev(dev)); + if (!dev->rewind(dcr)) { + Pmsg1(0, _("Bad status from rewind. ERR=%s\n"), dev->bstrerror()); goto bail_out; } else { - Pmsg0(0, "Rewind OK.\n"); + Pmsg0(0, _("Rewind OK.\n")); } for (i=1; i<=2000; i++) { read_again: @@ -824,13 +875,13 @@ read_again: goto read_again; } } - Pmsg2(0, _("Read block %d failed! ERR=%s\n"), i, be.strerror(dev->dev_errno)); + Pmsg2(0, _("Read block %d failed! ERR=%s\n"), i, be.bstrerror(dev->dev_errno)); goto bail_out; } memset(rec->data, 0, rec->data_len); - if (!read_record_from_block(block, rec)) { + if (!read_record_from_block(dcr, block, rec)) { berrno be; - Pmsg2(0, _("Read record failed. Block %d! ERR=%s\n"), i, be.strerror(dev->dev_errno)); + Pmsg2(0, _("Read record failed. Block %d! ERR=%s\n"), i, be.bstrerror(dev->dev_errno)); goto bail_out; } p = (int *)rec->data; @@ -878,8 +929,8 @@ static int position_test() "This is an *essential* feature ...\n\n")); empty_block(block); rec = new_record(); - if (!rewind_dev(dev)) { - Pmsg1(0, "Bad status from rewind. ERR=%s\n", strerror_dev(dev)); + if (!dev->rewind(dcr)) { + Pmsg1(0, _("Bad status from rewind. ERR=%s\n"), dev->bstrerror()); goto bail_out; } rec->data = check_pool_memory_size(rec->data, block->buf_len); @@ -917,14 +968,14 @@ static int position_test() } Pmsg1(0, _("Wrote 1000 blocks of %d bytes.\n"), rec->data_len); weofcmd(); - if (dev_cap(dev, CAP_TWOEOF)) { + if (dev->has_cap(CAP_TWOEOF)) { weofcmd(); } - if (!rewind_dev(dev)) { - Pmsg1(0, "Bad status from rewind. ERR=%s\n", strerror_dev(dev)); + if (!dev->rewind(dcr)) { + Pmsg1(0, _("Bad status from rewind. ERR=%s\n"), dev->bstrerror()); goto bail_out; } else { - Pmsg0(0, "Rewind OK.\n"); + Pmsg0(0, _("Rewind OK.\n")); } while(ok) { @@ -964,9 +1015,9 @@ static int position_test() ok = false; continue; } - Pmsg2(-1, "Reposition to file:block %d:%d\n", file, blk); - if (!reposition_dev(dev, file, blk)) { - Pmsg0(0, "Reposition error.\n"); + Pmsg2(-1, _("Reposition to file:block %d:%d\n"), file, blk); + if (!dev->reposition(dcr, file, blk)) { + Pmsg0(0, _("Reposition error.\n")); goto bail_out; } read_again: @@ -980,7 +1031,7 @@ read_again: } } Pmsg4(0, _("Read block %d failed! file=%d blk=%d. ERR=%s\n\n"), - recno, file, blk, be.strerror(dev->dev_errno)); + recno, file, blk, be.bstrerror(dev->dev_errno)); Pmsg0(0, _("This may be because the tape drive block size is not\n" " set to variable blocking as normally used by Bacula.\n" " Please see the Tape Testing chapter in the manual and \n" @@ -995,9 +1046,9 @@ read_again: goto bail_out; } memset(rec->data, 0, rec->data_len); - if (!read_record_from_block(block, rec)) { + if (!read_record_from_block(dcr, block, rec)) { berrno be; - Pmsg1(0, _("Read record failed! ERR=%s\n"), be.strerror(dev->dev_errno)); + Pmsg1(0, _("Read record failed! ERR=%s\n"), be.bstrerror(dev->dev_errno)); goto bail_out; } p = (int *)rec->data; @@ -1045,18 +1096,18 @@ static int append_test() wrcmd(); wrcmd(); weofcmd(); /* end file 2 */ - if (dev_cap(dev, CAP_TWOEOF)) { + if (dev->has_cap(CAP_TWOEOF)) { weofcmd(); } - force_close_dev(dev); /* release device */ + dev->close(); /* release device */ if (!open_the_device()) { return -1; } rewindcmd(); Pmsg0(0, _("Now moving to end of medium.\n")); eodcmd(); - Pmsg2(-1, _("We should be in file 3. I am at file %d. This is %s\n"), - dev->file, dev->file == 3 ? "correct!" : "NOT correct!!!!"); + Pmsg2(-1, _("We should be in file 3. I am at file %d. %s\n"), + dev->file, dev->file == 3 ? _("This is correct!") : _("This is NOT correct!!!!")); if (dev->file != 3) { return -1; @@ -1065,16 +1116,16 @@ static int append_test() Pmsg0(-1, _("\nNow the important part, I am going to attempt to append to the tape.\n\n")); wrcmd(); weofcmd(); - if (dev_cap(dev, CAP_TWOEOF)) { + if (dev->has_cap(CAP_TWOEOF)) { weofcmd(); } rewindcmd(); Pmsg0(-1, _("Done appending, there should be no I/O errors\n\n")); - Pmsg0(-1, "Doing Bacula scan of blocks:\n"); + Pmsg0(-1, _("Doing Bacula scan of blocks:\n")); scan_blocks(); Pmsg0(-1, _("End scanning the tape.\n")); - Pmsg2(-1, _("We should be in file 4. I am at file %d. This is %s\n"), - dev->file, dev->file == 4 ? "correct!" : "NOT correct!!!!"); + Pmsg2(-1, _("We should be in file 4. I am at file %d. %s\n"), + dev->file, dev->file == 4 ? _("This is correct!") : _("This is NOT correct!!!!")); if (dev->file != 4) { return -2; @@ -1094,18 +1145,18 @@ static int autochanger_test() int sleep_time = 0; Dmsg1(100, "Max changer wait = %d sec\n", timeout); - if (!dev_cap(dev, CAP_AUTOCHANGER)) { + if (!dev->has_cap(CAP_AUTOCHANGER)) { return 1; } if (!(dcr->device && dcr->device->changer_name && dcr->device->changer_command)) { - Pmsg0(-1, "\nAutochanger enabled, but no name or no command device specified.\n"); + Pmsg0(-1, _("\nAutochanger enabled, but no name or no command device specified.\n")); return 1; } - Pmsg0(-1, "\nAh, I see you have an autochanger configured.\n" + Pmsg0(-1, _("\nAh, I see you have an autochanger configured.\n" "To test the autochanger you must have a blank tape\n" - " that I can write on in Slot 1.\n"); - if (!get_cmd("\nDo you wish to continue with the Autochanger test? (y/n): ")) { + " that I can write on in Slot 1.\n")); + if (!get_cmd(_("\nDo you wish to continue with the Autochanger test? (y/n): "))) { return 0; } if (cmd[0] != 'y' && cmd[0] != 'Y') { @@ -1122,7 +1173,8 @@ try_again: dcr->VolCatInfo.Slot = slot; /* Find out what is loaded, zero means device is unloaded */ Pmsg0(-1, _("3301 Issuing autochanger \"loaded\" command.\n")); - changer = edit_device_codes(dcr, changer, "loaded"); + changer = edit_device_codes(dcr, changer, + dcr->device->changer_command, "loaded"); status = run_program(changer, timeout, results); Dmsg3(100, "run_prog: %s stat=%d result=\"%s\"\n", changer, status, results); if (status == 0) { @@ -1130,29 +1182,29 @@ try_again: } else { berrno be; Pmsg1(-1, _("3991 Bad autochanger command: %s\n"), changer); - Pmsg2(-1, _("3991 result=\"%s\": ERR=%s\n"), results, be.strerror(status)); + Pmsg2(-1, _("3991 result=\"%s\": ERR=%s\n"), results, be.bstrerror(status)); goto bail_out; } if (loaded) { - Pmsg1(-1, "Slot %d loaded. I am going to unload it.\n", loaded); + Pmsg1(-1, _("Slot %d loaded. I am going to unload it.\n"), loaded); } else { - Pmsg0(-1, "Nothing loaded in the drive. OK.\n"); + Pmsg0(-1, _("Nothing loaded in the drive. OK.\n")); } Dmsg1(100, "Results from loaded query=%s\n", results); if (loaded) { dcr->VolCatInfo.Slot = loaded; - offline_or_rewind_dev(dev); /* We are going to load a new tape, so close the device */ - force_close_dev(dev); + dev->close(); Pmsg2(-1, _("3302 Issuing autochanger \"unload %d %d\" command.\n"), loaded, dev->drive_index); - changer = edit_device_codes(dcr, changer, "unload"); + changer = edit_device_codes(dcr, changer, + dcr->device->changer_command, "unload"); status = run_program(changer, timeout, results); - Pmsg2(-1, "unload status=%s %d\n", status==0?"OK":"Bad", status); + Pmsg2(-1, _("unload status=%s %d\n"), status==0?_("OK"):_("Bad"), status); if (status != 0) { berrno be; Pmsg1(-1, _("3992 Bad autochanger command: %s\n"), changer); - Pmsg2(-1, _("3992 result=\"%s\": ERR=%s\n"), results, be.strerror(status)); + Pmsg2(-1, _("3992 result=\"%s\": ERR=%s\n"), results, be.bstrerror(status)); } } @@ -1162,19 +1214,20 @@ try_again: slot = 1; dcr->VolCatInfo.Slot = slot; - Pmsg2(-1, _("3303 Issuing autochanger \"load slot %d %d\" command.\n"), + Pmsg2(-1, _("3303 Issuing autochanger \"load %d %d\" command.\n"), slot, dev->drive_index); - changer = edit_device_codes(dcr, changer, "load"); + changer = edit_device_codes(dcr, changer, + dcr->device->changer_command, "load"); Dmsg1(100, "Changer=%s\n", changer); - force_close_dev(dev); + dev->close(); status = run_program(changer, timeout, results); if (status == 0) { - Pmsg2(-1, _("3303 Autochanger \"load slot %d %d\" status is OK.\n"), + Pmsg2(-1, _("3303 Autochanger \"load %d %d\" status is OK.\n"), slot, dev->drive_index); } else { berrno be; Pmsg1(-1, _("3993 Bad autochanger command: %s\n"), changer); - Pmsg2(-1, _("3993 result=\"%s\": ERR=%s\n"), results, be.strerror(status)); + Pmsg2(-1, _("3993 result=\"%s\": ERR=%s\n"), results, be.bstrerror(status)); goto bail_out; } @@ -1186,32 +1239,32 @@ try_again: * a failure. */ bmicrosleep(sleep_time, 0); - if (!rewind_dev(dev) || weof_dev(dev,1) < 0) { - Pmsg1(0, "Bad status from rewind. ERR=%s\n", strerror_dev(dev)); - clrerror_dev(dev, -1); - Pmsg0(-1, "\nThe test failed, probably because you need to put\n" + if (!dev->rewind(dcr) || !dev->weof(1)) { + Pmsg1(0, _("Bad status from rewind. ERR=%s\n"), dev->bstrerror()); + dev->clrerror(-1); + Pmsg0(-1, _("\nThe test failed, probably because you need to put\n" "a longer sleep time in the mtx-script in the load) case.\n" - "Adding a 30 second sleep and trying again ...\n"); + "Adding a 30 second sleep and trying again ...\n")); sleep_time += 30; goto try_again; } else { - Pmsg1(0, "Rewound %s\n", dev->print_name()); + Pmsg1(0, _("Rewound %s\n"), dev->print_name()); } - if ((status = weof_dev(dev, 1)) < 0) { - Pmsg2(0, "Bad status from weof %d. ERR=%s\n", status, strerror_dev(dev)); + if (!dev->weof(1)) { + Pmsg1(0, _("Bad status from weof. ERR=%s\n"), dev->bstrerror()); goto bail_out; } else { - Pmsg1(0, "Wrote EOF to %s\n", dev->print_name()); + Pmsg1(0, _("Wrote EOF to %s\n"), dev->print_name()); } if (sleep_time) { - Pmsg1(-1, "\nThe test worked this time. Please add:\n\n" + Pmsg1(-1, _("\nThe test worked this time. Please add:\n\n" " sleep %d\n\n" - "to your mtx-changer script in the load) case.\n\n", + "to your mtx-changer script in the load) case.\n\n"), sleep_time); } else { - Pmsg0(-1, "\nThe test autochanger worked!!\n\n"); + Pmsg0(-1, _("\nThe test autochanger worked!!\n\n")); } free_pool_memory(changer); @@ -1222,7 +1275,7 @@ try_again: bail_out: free_pool_memory(changer); free_pool_memory(results); - Pmsg0(-1, "You must correct this error or the Autochanger will not work.\n"); + Pmsg0(-1, _("You must correct this error or the Autochanger will not work.\n")); return -2; } @@ -1259,31 +1312,31 @@ static int fsf_test() weofcmd(); /* end file 3 */ wrcmd(); weofcmd(); /* end file 4 */ - if (dev_cap(dev, CAP_TWOEOF)) { + if (dev->has_cap(CAP_TWOEOF)) { weofcmd(); } test_again: rewindcmd(); Pmsg0(0, _("Now forward spacing 1 file.\n")); - if (!fsf_dev(dev, 1)) { - Pmsg1(0, "Bad status from fsr. ERR=%s\n", strerror_dev(dev)); + if (!dev->fsf(1)) { + Pmsg1(0, _("Bad status from fsr. ERR=%s\n"), dev->bstrerror()); goto bail_out; } - Pmsg2(-1, _("We should be in file 1. I am at file %d. This is %s\n"), - dev->file, dev->file == 1 ? "correct!" : "NOT correct!!!!"); + Pmsg2(-1, _("We should be in file 1. I am at file %d. %s\n"), + dev->file, dev->file == 1 ? _("This is correct!") : _("This is NOT correct!!!!")); if (dev->file != 1) { goto bail_out; } Pmsg0(0, _("Now forward spacing 2 files.\n")); - if (!fsf_dev(dev, 2)) { - Pmsg1(0, "Bad status from fsr. ERR=%s\n", strerror_dev(dev)); + if (!dev->fsf(2)) { + Pmsg1(0, _("Bad status from fsr. ERR=%s\n"), dev->bstrerror()); goto bail_out; } - Pmsg2(-1, _("We should be in file 3. I am at file %d. This is %s\n"), - dev->file, dev->file == 3 ? "correct!" : "NOT correct!!!!"); + Pmsg2(-1, _("We should be in file 3. I am at file %d. %s\n"), + dev->file, dev->file == 3 ? _("This is correct!") : _("This is NOT correct!!!!")); if (dev->file != 3) { goto bail_out; @@ -1291,29 +1344,29 @@ test_again: rewindcmd(); Pmsg0(0, _("Now forward spacing 4 files.\n")); - if (!fsf_dev(dev, 4)) { - Pmsg1(0, "Bad status from fsr. ERR=%s\n", strerror_dev(dev)); + if (!dev->fsf(4)) { + Pmsg1(0, _("Bad status from fsr. ERR=%s\n"), dev->bstrerror()); goto bail_out; } - Pmsg2(-1, _("We should be in file 4. I am at file %d. This is %s\n"), - dev->file, dev->file == 4 ? "correct!" : "NOT correct!!!!"); + Pmsg2(-1, _("We should be in file 4. I am at file %d. %s\n"), + dev->file, dev->file == 4 ? _("This is correct!") : _("This is NOT correct!!!!")); if (dev->file != 4) { goto bail_out; } if (set_off) { - Pmsg0(-1, "The test worked this time. Please add:\n\n" + Pmsg0(-1, _("The test worked this time. Please add:\n\n" " Fast Forward Space File = no\n\n" - "to your Device resource for this drive.\n"); + "to your Device resource for this drive.\n")); } Pmsg0(-1, "\n"); Pmsg0(0, _("Now forward spacing 1 more file.\n")); - if (!fsf_dev(dev, 1)) { - Pmsg1(0, "Bad status from fsr. ERR=%s\n", strerror_dev(dev)); + if (!dev->fsf(1)) { + Pmsg1(0, _("Bad status from fsr. ERR=%s\n"), dev->bstrerror()); } - Pmsg2(-1, _("We should be in file 5. I am at file %d. This is %s\n"), - dev->file, dev->file == 5 ? "correct!" : "NOT correct!!!!"); + Pmsg2(-1, _("We should be in file 5. I am at file %d. %s\n"), + dev->file, dev->file == 5 ? _("This is correct!") : _("This is NOT correct!!!!")); if (dev->file != 5) { goto bail_out; } @@ -1322,17 +1375,17 @@ test_again: bail_out: Pmsg0(-1, _("\nThe forward space file test failed.\n")); - if (dev_cap(dev, CAP_FASTFSF)) { - Pmsg0(-1, "You have Fast Forward Space File enabled.\n" - "I am turning it off then retrying the test.\n"); - dev->capabilities &= ~CAP_FASTFSF; + if (dev->has_cap(CAP_FASTFSF)) { + Pmsg0(-1, _("You have Fast Forward Space File enabled.\n" + "I am turning it off then retrying the test.\n")); + dev->clear_cap(CAP_FASTFSF); set_off = true; goto test_again; } - Pmsg0(-1, "You must correct this error or Bacula will not work.\n" + Pmsg0(-1, _("You must correct this error or Bacula will not work.\n" "Some systems, e.g. OpenBSD, require you to set\n" " Use MTIOCGET= no\n" - "in your device resource. Use with caution.\n"); + "in your device resource. Use with caution.\n")); return -2; } @@ -1360,48 +1413,48 @@ static void testcmd() goto all_done; } if (stat == -1) { /* first test failed */ - if (dev_cap(dev, CAP_EOM) || dev_cap(dev, CAP_FASTFSF)) { - Pmsg0(-1, "\nAppend test failed. Attempting again.\n" + if (dev->has_cap(CAP_EOM) || dev->has_cap(CAP_FASTFSF)) { + Pmsg0(-1, _("\nAppend test failed. Attempting again.\n" "Setting \"Hardware End of Medium = no\n" " and \"Fast Forward Space File = no\n" - "and retrying append test.\n\n"); - dev->capabilities &= ~CAP_EOM; /* turn off eom */ - dev->capabilities &= ~CAP_FASTFSF; /* turn off fast fsf */ + "and retrying append test.\n\n")); + dev->clear_cap(CAP_EOM); /* turn off eom */ + dev->clear_cap(CAP_FASTFSF); /* turn off fast fsf */ stat = append_test(); if (stat == 1) { - Pmsg0(-1, "\n\nIt looks like the test worked this time, please add:\n\n" + Pmsg0(-1, _("\n\nIt looks like the test worked this time, please add:\n\n" " Hardware End of Medium = No\n\n" " Fast Forward Space File = No\n" - "to your Device resource in the Storage conf file.\n"); + "to your Device resource in the Storage conf file.\n")); goto all_done; } if (stat == -1) { - Pmsg0(-1, "\n\nThat appears *NOT* to have corrected the problem.\n"); + Pmsg0(-1, _("\n\nThat appears *NOT* to have corrected the problem.\n")); goto failed; } /* Wrong count after append */ if (stat == -2) { - Pmsg0(-1, "\n\nIt looks like the append failed. Attempting again.\n" - "Setting \"BSF at EOM = yes\" and retrying append test.\n"); + Pmsg0(-1, _("\n\nIt looks like the append failed. Attempting again.\n" + "Setting \"BSF at EOM = yes\" and retrying append test.\n")); dev->capabilities |= CAP_BSFATEOM; /* backspace on eom */ stat = append_test(); if (stat == 1) { - Pmsg0(-1, "\n\nIt looks like the test worked this time, please add:\n\n" + Pmsg0(-1, _("\n\nIt looks like the test worked this time, please add:\n\n" " Hardware End of Medium = No\n" " Fast Forward Space File = No\n" " BSF at EOM = yes\n\n" - "to your Device resource in the Storage conf file.\n"); + "to your Device resource in the Storage conf file.\n")); goto all_done; } } } failed: - Pmsg0(-1, "\nAppend test failed.\n\n"); - Pmsg0(-1, "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" + Pmsg0(-1, _("\nAppend test failed.\n\n" + "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" "Unable to correct the problem. You MUST fix this\n" - "problem before Bacula can use your tape drive correctly\n"); - Pmsg0(-1, "\nPerhaps running Bacula in fixed block mode will work.\n" + "problem before Bacula can use your tape drive correctly\n" + "\nPerhaps running Bacula in fixed block mode will work.\n" "Do so by setting:\n\n" "Minimum Block Size = nnn\n" "Maximum Block Size = nnn\n\n" @@ -1413,7 +1466,7 @@ failed: "\n" "Some systems, e.g. OpenBSD, require you to set\n" " Use MTIOCGET= no\n" - "in your device resource. Use with caution.\n"); + "in your device resource. Use with caution.\n")); return; } @@ -1430,12 +1483,11 @@ all_done: "1 block of 64448 bytes in file 4\n" "End of File mark.\n" "Total files=4, blocks=7, bytes = 451,136\n" - "=== End sample correct output ===\n\n")); - - Pmsg0(-1, _("If the above scan output is not identical to the\n" - "sample output, you MUST correct the problem\n" - "or Bacula will not be able to write multiple Jobs to \n" - "the tape.\n\n")); + "=== End sample correct output ===\n\n" + "If the above scan output is not identical to the\n" + "sample output, you MUST correct the problem\n" + "or Bacula will not be able to write multiple Jobs to \n" + "the tape.\n\n")); if (stat == 1) { re_read_block_test(); @@ -1457,11 +1509,16 @@ static void fsfcmd() if (num <= 0) { num = 1; } - if (!fsf_dev(dev, num)) { - Pmsg1(0, "Bad status from fsf. ERR=%s\n", strerror_dev(dev)); + if (!dev->fsf(num)) { + Pmsg1(0, _("Bad status from fsf. ERR=%s\n"), dev->bstrerror()); return; } - Pmsg2(0, "Forward spaced %d file%s.\n", num, num==1?"":"s"); + if (num == 1) { + Pmsg0(0, _("Forward spaced 1 file.\n")); + } + else { + Pmsg1(0, _("Forward spaced %d files.\n"), num); + } } /* Forward space a record */ @@ -1475,12 +1532,25 @@ static void fsrcmd() num = 1; } if (!dev->fsr(num)) { - Pmsg1(0, "Bad status from fsr. ERR=%s\n", strerror_dev(dev)); + Pmsg1(0, _("Bad status from fsr. ERR=%s\n"), dev->bstrerror()); return; } - Pmsg2(0, "Forward spaced %d record%s.\n", num, num==1?"":"s"); + if (num == 1) { + Pmsg0(0, _("Forward spaced 1 record.\n")); + } + else { + Pmsg1(0, _("Forward spaced %d records.\n"), num); + } } +/* + * Read a Bacula block from the tape + */ +static void rbcmd() +{ + dev->open(dcr, OPEN_READ_ONLY); + read_block_from_dev(dcr, NO_BLOCK_NUMBER_CHECK); +} /* * Write a Bacula block to the tape @@ -1491,6 +1561,9 @@ static void wrcmd() DEV_RECORD *rec = dcr->rec; int i; + if (!dev->is_open()) { + open_the_device(); + } sm_check(__FILE__, __LINE__, false); empty_block(block); if (verbose > 1) { @@ -1528,7 +1601,7 @@ static void rrcmd() char *buf; int stat, len; - if (!get_cmd("Enter length to read: ")) { + if (!get_cmd(_("Enter length to read: "))) { return; } len = atoi(cmd); @@ -1537,13 +1610,13 @@ static void rrcmd() len = 1024; } buf = (char *)malloc(len); - stat = read(dev->fd, buf, len); + stat = read(dev->fd(), buf, len); if (stat > 0 && stat <= len) { errno = 0; } berrno be; Pmsg3(0, _("Read of %d bytes gives stat=%d. ERR=%s\n"), - len, stat, be.strerror()); + len, stat, be.bstrerror()); free(buf); } @@ -1565,38 +1638,47 @@ static void scancmd() blocks = block_size = tot_blocks = 0; bytes = 0; if (dev->state & ST_EOT) { - Pmsg0(0, "End of tape\n"); + Pmsg0(0, _("End of tape\n")); return; } - update_pos_dev(dev); + dev->update_pos(dcr); tot_files = dev->file; Pmsg1(0, _("Starting scan at file %u\n"), dev->file); for (;;) { - if ((stat = read(dev->fd, buf, sizeof(buf))) < 0) { + if ((stat = read(dev->fd(), buf, sizeof(buf))) < 0) { berrno be; - clrerror_dev(dev, -1); - Mmsg2(dev->errmsg, "read error on %s. ERR=%s.\n", - dev->dev_name, be.strerror()); - Pmsg2(0, "Bad status from read %d. ERR=%s\n", stat, strerror_dev(dev)); - if (blocks > 0) - printf("%d block%s of %d bytes in file %d\n", - blocks, blocks>1?"s":"", block_size, dev->file); + dev->clrerror(-1); + Mmsg2(dev->errmsg, _("read error on %s. ERR=%s.\n"), + dev->dev_name, be.bstrerror()); + Pmsg2(0, _("Bad status from read %d. ERR=%s\n"), stat, dev->bstrerror()); + if (blocks > 0) { + if (blocks==1) { + printf(_("1 block of %d bytes in file %d\n"), block_size, dev->file); + } + else { + printf(_("%d blocks of %d bytes in file %d\n"), blocks, block_size, dev->file); + } + } return; } Dmsg1(200, "read status = %d\n", stat); /* sleep(1); */ if (stat != block_size) { - update_pos_dev(dev); + dev->update_pos(dcr); if (blocks > 0) { - printf("%d block%s of %d bytes in file %d\n", - blocks, blocks>1?"s":"", block_size, dev->file); + if (blocks==1) { + printf(_("1 block of %d bytes in file %d\n"), block_size, dev->file); + } + else { + printf(_("%d blocks of %d bytes in file %d\n"), blocks, block_size, dev->file); + } blocks = 0; } block_size = stat; } if (stat == 0) { /* EOF */ - update_pos_dev(dev); - printf("End of File mark.\n"); + dev->update_pos(dcr); + printf(_("End of File mark.\n")); /* Two reads of zero means end of tape */ if (dev->state & ST_EOF) dev->state |= ST_EOT; @@ -1605,7 +1687,7 @@ static void scancmd() dev->file++; } if (dev->state & ST_EOT) { - printf("End of tape\n"); + printf(_("End of tape\n")); break; } } else { /* Got data */ @@ -1615,9 +1697,9 @@ static void scancmd() bytes += stat; } } - update_pos_dev(dev); + dev->update_pos(dcr); tot_files = dev->file - tot_files; - printf("Total files=%d, blocks=%d, bytes = %s\n", tot_files, tot_blocks, + printf(_("Total files=%d, blocks=%d, bytes = %s\n"), tot_files, tot_blocks, edit_uint64_with_commas(bytes, ec1)); } @@ -1635,28 +1717,37 @@ static void scan_blocks() uint64_t bytes; DEV_BLOCK *block = dcr->block; char ec1[50]; + char buf1[100], buf2[100]; blocks = block_size = tot_blocks = 0; bytes = 0; empty_block(block); - update_pos_dev(dev); + dev->update_pos(dcr); tot_files = dev->file; for (;;) { if (!read_block_from_device(dcr, NO_BLOCK_NUMBER_CHECK)) { - Dmsg1(100, "!read_block(): ERR=%s\n", strerror_dev(dev)); + Dmsg1(100, "!read_block(): ERR=%s\n", dev->bstrerror()); if (dev->state & ST_EOT) { if (blocks > 0) { - printf("%d block%s of %d bytes in file %d\n", - blocks, blocks>1?"s":"", block_size, dev->file); + if (blocks==1) { + printf(_("1 block of %d bytes in file %d\n"), block_size, dev->file); + } + else { + printf(_("%d blocks of %d bytes in file %d\n"), blocks, block_size, dev->file); + } blocks = 0; } goto bail_out; } if (dev->state & ST_EOF) { if (blocks > 0) { - printf("%d block%s of %d bytes in file %d\n", - blocks, blocks>1?"s":"", block_size, dev->file); + if (blocks==1) { + printf(_("1 block of %d bytes in file %d\n"), block_size, dev->file); + } + else { + printf(_("%d blocks of %d bytes in file %d\n"), blocks, block_size, dev->file); + } blocks = 0; } printf(_("End of File mark.\n")); @@ -1664,20 +1755,28 @@ static void scan_blocks() } if (dev->state & ST_SHORT) { if (blocks > 0) { - printf("%d block%s of %d bytes in file %d\n", - blocks, blocks>1?"s":"", block_size, dev->file); + if (blocks==1) { + printf(_("1 block of %d bytes in file %d\n"), block_size, dev->file); + } + else { + printf(_("%d blocks of %d bytes in file %d\n"), blocks, block_size, dev->file); + } blocks = 0; } printf(_("Short block read.\n")); continue; } - printf(_("Error reading block. ERR=%s\n"), strerror_dev(dev)); + printf(_("Error reading block. ERR=%s\n"), dev->bstrerror()); goto bail_out; } if (block->block_len != block_size) { if (blocks > 0) { - printf("%d block%s of %d bytes in file %d\n", - blocks, blocks>1?"s":"", block_size, dev->file); + if (blocks==1) { + printf(_("1 block of %d bytes in file %d\n"), block_size, dev->file); + } + else { + printf(_("%d blocks of %d bytes in file %d\n"), blocks, block_size, dev->file); + } blocks = 0; } block_size = block->block_len; @@ -1690,11 +1789,11 @@ static void scan_blocks() block->VolSessionId, block->VolSessionTime); if (verbose == 1) { DEV_RECORD *rec = new_record(); - read_record_from_block(block, rec); - Pmsg8(-1, "Blk_block: %u dev_blk=%u blen=%u First rec FI=%s SessId=%u SessTim=%u Strm=%s rlen=%d\n", + read_record_from_block(dcr, block, rec); + Pmsg8(-1, _("Blk_block: %u dev_blk=%u blen=%u First rec FI=%s SessId=%u SessTim=%u Strm=%s rlen=%d\n"), block->BlockNumber, dev->block_num, block->block_len, - FI_to_ascii(rec->FileIndex), rec->VolSessionId, rec->VolSessionTime, - stream_to_ascii(rec->Stream, rec->FileIndex), rec->data_len); + FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId, rec->VolSessionTime, + stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len); rec->remainder = 0; free_record(rec); } else if (verbose > 1) { @@ -1704,7 +1803,7 @@ static void scan_blocks() } bail_out: tot_files = dev->file - tot_files; - printf("Total files=%d, blocks=%d, bytes = %s\n", tot_files, tot_blocks, + printf(_("Total files=%d, blocks=%d, bytes = %s\n"), tot_files, tot_blocks, edit_uint64_with_commas(bytes, ec1)); } @@ -1713,7 +1812,7 @@ static void statcmd() { int debug = debug_level; debug_level = 30; - Pmsg2(0, "Device status: %u. ERR=%s\n", status_dev(dev), strerror_dev(dev)); + Pmsg2(0, _("Device status: %u. ERR=%s\n"), status_dev(dev), dev->bstrerror()); #ifdef xxxx dump_volume_label(dev); #endif @@ -1730,9 +1829,11 @@ static void fillcmd() DEV_RECORD rec; DEV_BLOCK *block = dcr->block; char ec1[50]; + char buf1[100], buf2[100]; int fd; uint32_t i; uint32_t min_block_size; + struct tm tm; ok = true; stop = 0; @@ -1741,7 +1842,7 @@ static void fillcmd() last_block_num = 0; BlockNumber = 0; - Pmsg0(-1, "\n" + Pmsg0(-1, _("\n" "This command simulates Bacula writing to a tape.\n" "It requires either one or two blank tapes, which it\n" "will label and write.\n\n" @@ -1756,18 +1857,18 @@ static void fillcmd() "fills, it will ask for a second, and after writing a few more \n" "blocks, it will stop. Then it will begin re-reading the\n" "two tapes.\n\n" -"This may take a long time -- hours! ...\n\n"); +"This may take a long time -- hours! ...\n\n")); - get_cmd("Do you want to run the simplified test (s) with one tape\n" - "or the complete multiple tape (m) test: (s/m) "); + get_cmd(_("Do you want to run the simplified test (s) with one tape\n" + "or the complete multiple tape (m) test: (s/m) ")); if (cmd[0] == 's') { - Pmsg0(-1, "Simple test (single tape) selected.\n"); + Pmsg0(-1, _("Simple test (single tape) selected.\n")); simple = true; } else if (cmd[0] == 'm') { - Pmsg0(-1, "Multiple tape test selected.\n"); + Pmsg0(-1, _("Multiple tape test selected.\n")); simple = false; } else { - Pmsg0(000, "Command aborted.\n"); + Pmsg0(000, _("Command aborted.\n")); return; } @@ -1778,14 +1879,7 @@ static void fillcmd() min_block_size = dev->min_block_size; dev->min_block_size = dev->max_block_size; set_volume_name("TestVolume1", 1); - - if (!dev->rewind()) { - Pmsg0(000, "Rewind failed.\n"); - } - if (!dev->weof()) { - Pmsg0(000, "Write EOF failed.\n"); - } - labelcmd(); + dir_ask_sysop_to_create_appendable_volume(dcr); dev->set_append(); /* force volume to be relabeled */ /* @@ -1807,10 +1901,10 @@ static void fillcmd() if (!write_session_label(dcr, SOS_LABEL)) { set_jcr_job_status(jcr, JS_ErrorTerminated); Jmsg1(jcr, M_FATAL, 0, _("Write session label failed. ERR=%s\n"), - strerror_dev(dev)); + dev->bstrerror()); ok = false; } - Pmsg0(-1, "Wrote Start of Session label.\n"); + Pmsg0(-1, _("Wrote Start of Session label.\n")); memset(&rec, 0, sizeof(rec)); rec.data = get_memory(100000); /* max record size */ @@ -1822,7 +1916,7 @@ static void fillcmd() * Put some random data in the record */ fd = open("/dev/urandom", O_RDONLY); - if (fd) { + if (fd != -1) { read(fd, rec.data, rec.data_len); close(fd); } else { @@ -1838,10 +1932,12 @@ static void fillcmd() */ jcr->dcr->VolFirstIndex = 0; time(&jcr->run_time); /* start counting time for rates */ + (void)localtime_r(&jcr->run_time, &tm); + strftime(buf1, sizeof(buf1), "%H:%M:%S", &tm); if (simple) { - Pmsg0(-1, "Begin writing Bacula records to tape ...\n"); + Pmsg1(-1, _("%s Begin writing Bacula records to tape ...\n"), buf1); } else { - Pmsg0(-1, "Begin writing Bacula records to first tape ...\n"); + Pmsg1(-1, _("%s Begin writing Bacula records to first tape ...\n"), buf1); } for (file_index = 0; ok && !job_canceled(jcr); ) { rec.VolSessionId = jcr->VolSessionId; @@ -1857,7 +1953,8 @@ static void fillcmd() } Dmsg4(250, "before write_rec FI=%d SessId=%d Strm=%s len=%d\n", - rec.FileIndex, rec.VolSessionId, stream_to_ascii(rec.Stream, rec.FileIndex), + rec.FileIndex, rec.VolSessionId, + stream_to_ascii(buf1, rec.Stream, rec.FileIndex), rec.data_len); while (!write_record_to_block(block, &rec)) { @@ -1881,16 +1978,19 @@ static void fillcmd() now = 1; /* prevent divide error */ } kbs = (double)dev->VolCatInfo.VolCatBytes / (1000.0 * (double)now); - Pmsg4(-1, "Wrote blk_block=%u, dev_blk_num=%u VolBytes=%s rate=%.1f KB/s\n", + Pmsg4(-1, _("Wrote blk_block=%u, dev_blk_num=%u VolBytes=%s rate=%.1f KB/s\n"), block->BlockNumber, dev->block_num, edit_uint64_with_commas(dev->VolCatInfo.VolCatBytes, ec1), (float)kbs); } - /* Every 15000 blocks (approx 1GB) write an EOF. + /* Every 32000 blocks (approx 2GB) write an EOF. */ - if ((block->BlockNumber % 15000) == 0) { - Pmsg0(-1, "Flush block, write EOF\n"); + if ((block->BlockNumber % 32000) == 0) { + now = time(NULL); + (void)localtime_r(&now, &tm); + strftime(buf1, sizeof(buf1), "%H:%M:%S", &tm); + Pmsg1(-1, _("%s Flush block, write EOF\n"), buf1); flush_block(block, 0); - weof_dev(dev, 1); + dev->weof(1); } /* Get out after writing 10 blocks to the second tape */ @@ -1904,12 +2004,14 @@ static void fillcmd() } jcr->JobBytes += rec.data_len; /* increment bytes this job */ Dmsg4(190, "write_record FI=%s SessId=%d Strm=%s len=%d\n", - FI_to_ascii(rec.FileIndex), rec.VolSessionId, - stream_to_ascii(rec.Stream, rec.FileIndex), rec.data_len); + FI_to_ascii(buf1, rec.FileIndex), rec.VolSessionId, + stream_to_ascii(buf2, rec.Stream, rec.FileIndex), rec.data_len); /* Get out after writing 10 blocks to the second tape */ if (BlockNumber > 10 && stop != 0) { /* get out */ - Pmsg0(-1, "Done writing ...\n"); + char ed1[50]; + Pmsg1(-1, "Done writing %s records ...\n", + edit_uint64_with_commas(write_count, ed1)); break; } } @@ -1922,7 +2024,7 @@ static void fillcmd() set_jcr_job_status(jcr, JS_ErrorTerminated); } if (!write_session_label(dcr, EOS_LABEL)) { - Pmsg1(000, _("Error writting end session label. ERR=%s\n"), strerror_dev(dev)); + Pmsg1(000, _("Error writting end session label. ERR=%s\n"), dev->bstrerror()); ok = false; } /* Write out final block of this session */ @@ -1954,16 +2056,25 @@ static void fillcmd() write(fd, last_block2->buf, last_block2->buf_len); write(fd, first_block->buf, first_block->buf_len); close(fd); - Pmsg2(-1, "Wrote state file last_block_num1=%d last_block_num2=%d\n", + Pmsg2(-1, _("Wrote state file last_block_num1=%d last_block_num2=%d\n"), last_block_num1, last_block_num2); } else { berrno be; Pmsg2(-1, _("Could not create state file: %s ERR=%s\n"), buf, - be.strerror()); + be.bstrerror()); } - Pmsg4(-1, _("\n\nDone filling tape%s at %d:%d. Now beginning re-read of %stape ...\n"), - simple?"":"s", jcr->dcr->dev->file, jcr->dcr->dev->block_num, simple?"":"first "); + now = time(NULL); + (void)localtime_r(&now, &tm); + strftime(buf1, sizeof(buf1), "%H:%M:%S", &tm); + if (simple) { + Pmsg3(-1, _("\n\n%s Done filling tape at %d:%d. Now beginning re-read of tape ...\n"), + buf1, jcr->dcr->dev->file, jcr->dcr->dev->block_num); + } + else { + Pmsg3(-1, _("\n\n%s Done filling tapes at %d:%d. Now beginning re-read of first tape ...\n"), + buf1, jcr->dcr->dev->file, jcr->dcr->dev->block_num); + } jcr->dcr->block = block; do_unfill(); @@ -2000,14 +2111,14 @@ static void unfillcmd() read(fd, first_block->buf, first_block->buf_len); close(fd); if (state_level != btape_state_level) { - Pmsg0(-1, "\nThe state file level has changed. You must redo\n" - "the fill command.\n"); + Pmsg0(-1, _("\nThe state file level has changed. You must redo\n" + "the fill command.\n")); return; } } else { berrno be; - Pmsg2(-1, "\nCould not find the state file: %s ERR=%s\n" - "You must redo the fill command.\n", buf, be.strerror()); + Pmsg2(-1, _("\nCould not find the state file: %s ERR=%s\n" + "You must redo the fill command.\n"), buf, be.bstrerror()); return; } do_unfill(); @@ -2017,15 +2128,15 @@ static void unfillcmd() static void do_unfill() { DEV_BLOCK *block = dcr->block; - bool autochanger; + int autochanger; dumped = 0; VolBytes = 0; LastBlock = 0; Dmsg0(20, "Enter do_unfill\n"); - dev->capabilities |= CAP_ANONVOLS; /* allow reading any volume */ - dev->capabilities &= ~CAP_LABEL; /* don't label anything here */ + dev->set_cap(CAP_ANONVOLS); /* allow reading any volume */ + dev->clear_cap(CAP_LABEL); /* don't label anything here */ end_of_tape = 0; @@ -2034,56 +2145,67 @@ static void do_unfill() file_index = 0; if (last_block) { free_block(last_block); + last_block = NULL; } last_block_num = last_block_num1; last_file = last_file1; last_block = last_block1; + free_restore_volume_list(jcr); + jcr->bsr = NULL; + bstrncpy(dcr->VolumeName, "TestVolume1|TestVolume2", sizeof(dcr->VolumeName)); + create_restore_volume_list(jcr); + if (jcr->VolList != NULL) { + jcr->VolList->Slot = 1; + if (jcr->VolList->next != NULL) { + jcr->VolList->next->Slot = 2; + } + } + + set_volume_name("TestVolume1", 1); + if (!simple) { /* Multiple Volume tape */ /* Close device so user can use autochanger if desired */ - if (dev_cap(dev, CAP_OFFLINEUNMOUNT)) { - offline_dev(dev); + if (dev->has_cap(CAP_OFFLINEUNMOUNT)) { + dev->offline(); } autochanger = autoload_device(dcr, 1, NULL); - if (!autochanger) { - force_close_dev(dev); + if (autochanger != 1) { + dev->close(); get_cmd(_("Mount first tape. Press enter when ready: ")); } - free_vol_list(jcr); - jcr->dcr = new_dcr(jcr, dev); - set_volume_name("TestVolume1", 1); - jcr->bsr = NULL; - create_vol_list(jcr); - close_dev(dev); - dev->state &= ~(ST_READ|ST_APPEND); - dev->num_writers = 0; - if (!acquire_device_for_read(dcr)) { - Pmsg1(-1, "%s", dev->errmsg); - goto bail_out; - } + } + + dev->close(); + dev->num_writers = 0; + if (!acquire_device_for_read(dcr)) { + Pmsg1(-1, "%s", dev->errmsg); + goto bail_out; } /* * We now have the first tape mounted. * Note, re-reading last block may have caused us to * loose track of where we are (block number unknown). */ - if (!rewind_dev(dev)) { /* get to a known place on tape */ + Pmsg0(-1, _("Rewinding.\n")); + if (!dev->rewind(dcr)) { /* get to a known place on tape */ goto bail_out; } /* Read the first 10000 records */ - Pmsg0(-1, _("Reading the first 10000 records.\n")); + Pmsg2(-1, _("Reading the first 10000 records from %u:%u.\n"), + dev->file, dev->block_num); quickie_count = 0; read_records(dcr, quickie_cb, my_mount_next_read_volume); Pmsg4(-1, _("Reposition from %u:%u to %u:%u\n"), dev->file, dev->block_num, last_file, last_block_num); - if (!reposition_dev(dev, last_file, last_block_num)) { - Pmsg1(-1, "Reposition error. ERR=%s\n", strerror_dev(dev)); + if (!dev->reposition(dcr, last_file, last_block_num)) { + Pmsg1(-1, _("Reposition error. ERR=%s\n"), dev->bstrerror()); goto bail_out; } Pmsg1(-1, _("Reading block %u.\n"), last_block_num); if (!read_block_from_device(dcr, NO_BLOCK_NUMBER_CHECK)) { - Pmsg1(-1, _("Error reading block: ERR=%s\n"), strerror_dev(dev)); + Pmsg1(-1, _("Error reading block: ERR=%s\n"), dev->bstrerror()); goto bail_out; } if (compare_blocks(last_block, block)) { @@ -2104,17 +2226,15 @@ static void do_unfill() /* Multiple Volume tape */ /* Close device so user can use autochanger if desired */ - if (dev_cap(dev, CAP_OFFLINEUNMOUNT)) { - offline_dev(dev); + if (dev->has_cap(CAP_OFFLINEUNMOUNT)) { + dev->offline(); } - free_vol_list(jcr); set_volume_name("TestVolume2", 2); - jcr->bsr = NULL; - create_vol_list(jcr); + autochanger = autoload_device(dcr, 1, NULL); - if (!autochanger) { - force_close_dev(dev); + if (autochanger != 1) { + dev->close(); get_cmd(_("Mount second tape. Press enter when ready: ")); } @@ -2128,13 +2248,13 @@ static void do_unfill() * on the previous tape. */ Pmsg2(-1, _("Reposition from %u:%u to 0:1\n"), dev->file, dev->block_num); - if (!reposition_dev(dev, 0, 1)) { - Pmsg1(-1, "Reposition error. ERR=%s\n", strerror_dev(dev)); + if (!dev->reposition(dcr, 0, 1)) { + Pmsg1(-1, _("Reposition error. ERR=%s\n"), dev->bstrerror()); goto bail_out; } Pmsg1(-1, _("Reading block %d.\n"), dev->block_num); if (!read_block_from_device(dcr, NO_BLOCK_NUMBER_CHECK)) { - Pmsg1(-1, _("Error reading block: ERR=%s\n"), strerror_dev(dev)); + Pmsg1(-1, _("Error reading block: ERR=%s\n"), dev->bstrerror()); goto bail_out; } if (compare_blocks(first_block, block)) { @@ -2144,13 +2264,13 @@ static void do_unfill() /* Now find and compare the last block */ Pmsg4(-1, _("Reposition from %u:%u to %u:%u\n"), dev->file, dev->block_num, last_file, last_block_num); - if (!reposition_dev(dev, last_file, last_block_num)) { - Pmsg1(-1, "Reposition error. ERR=%s\n", strerror_dev(dev)); + if (!dev->reposition(dcr, last_file, last_block_num)) { + Pmsg1(-1, _("Reposition error. ERR=%s\n"), dev->bstrerror()); goto bail_out; } Pmsg1(-1, _("Reading block %d.\n"), dev->block_num); if (!read_block_from_device(dcr, NO_BLOCK_NUMBER_CHECK)) { - Pmsg1(-1, _("Error reading block: ERR=%s\n"), strerror_dev(dev)); + Pmsg1(-1, _("Error reading block: ERR=%s\n"), dev->bstrerror()); goto bail_out; } if (compare_blocks(last_block, block)) { @@ -2167,14 +2287,9 @@ bail_out: static bool quickie_cb(DCR *dcr, DEV_RECORD *rec) { DEVICE *dev = dcr->dev; - if (dev->file != 0) { - Pmsg3(-1, "ERROR! device at %d:%d count=%d\n", dev->file, dev->block_num, - quickie_count); - return false; - } quickie_count++; if (quickie_count == 10000) { - Pmsg2(-1, "1000 records read now at %d:%d\n", dev->file, dev->block_num); + Pmsg2(-1, _("10000 records read now at %d:%d\n"), dev->file, dev->block_num); } return quickie_count < 10000; } @@ -2200,11 +2315,11 @@ static bool compare_blocks(DEV_BLOCK *last_block, DEV_BLOCK *block) dump_block(last_block, _("Last block written")); Pmsg0(-1, "\n"); dump_block(block, _("Block read back")); - Pmsg1(-1, "\n\nThe blocks differ at byte %u\n", p - last_block->buf); - Pmsg0(-1, "\n\n!!!! The last block written and the block\n" + Pmsg1(-1, _("\n\nThe blocks differ at byte %u\n"), p - last_block->buf); + Pmsg0(-1, _("\n\n!!!! The last block written and the block\n" "that was read back differ. The test FAILED !!!!\n" "This must be corrected before you use Bacula\n" - "to write multi-tape Volumes.!!!!\n"); + "to write multi-tape Volumes.!!!!\n")); return false; } if (verbose) { @@ -2229,7 +2344,7 @@ static int flush_block(DEV_BLOCK *block, int dump) DEV_BLOCK *tblock; uint32_t this_file, this_block_num; - lock_device(dev); + dev->r_dlock(); if (!this_block) { this_block = new_block(dev); } @@ -2240,7 +2355,7 @@ static int flush_block(DEV_BLOCK *block, int dump) this_file = dev->file; this_block_num = dev->block_num; if (!write_block_to_dev(dcr)) { - Pmsg3(000, "Last block at: %u:%u this_dev_block_num=%d\n", + Pmsg3(000, _("Last block at: %u:%u this_dev_block_num=%d\n"), last_file, last_block_num, this_block_num); if (vol_num == 1) { /* @@ -2254,11 +2369,11 @@ static int flush_block(DEV_BLOCK *block, int dump) first_block = dup_block(block); /* first block second tape */ } if (verbose) { - Pmsg3(000, "Block not written: FileIndex=%u blk_block=%u Size=%u\n", + Pmsg3(000, _("Block not written: FileIndex=%u blk_block=%u Size=%u\n"), (unsigned)file_index, block->BlockNumber, block->block_len); - dump_block(last_block, "Last block written"); + dump_block(last_block, _("Last block written")); Pmsg0(-1, "\n"); - dump_block(block, "Block not written"); + dump_block(block, _("Block not written")); } if (stop == 0) { eot_block = block->BlockNumber; @@ -2273,7 +2388,7 @@ static int flush_block(DEV_BLOCK *block, int dump) } kbs = (double)dev->VolCatInfo.VolCatBytes / (1000 * now); vol_size = dev->VolCatInfo.VolCatBytes; - Pmsg4(000, "End of tape %d:%d. VolumeCapacity=%s. Write rate = %.1f KB/s\n", + Pmsg4(000, _("End of tape %d:%d. VolumeCapacity=%s. Write rate = %.1f KB/s\n"), dev->file, dev->block_num, edit_uint64_with_commas(dev->VolCatInfo.VolCatBytes, ec1), kbs); @@ -2282,14 +2397,14 @@ static int flush_block(DEV_BLOCK *block, int dump) } else { /* Full test in progress */ if (!fixup_device_block_write_error(jcr->dcr)) { - Pmsg1(000, _("Cannot fixup device error. %s\n"), strerror_dev(dev)); + Pmsg1(000, _("Cannot fixup device error. %s\n"), dev->bstrerror()); ok = false; - unlock_device(dev); + dev->dunlock(); return 0; } BlockNumber = 0; /* start counting for second tape */ } - unlock_device(dev); + dev->dunlock(); return 1; /* end of tape reached */ } @@ -2308,7 +2423,7 @@ static int flush_block(DEV_BLOCK *block, int dump) last_file = this_file; last_block_num = this_block_num; - unlock_device(dev); + dev->dunlock(); return 1; } @@ -2323,9 +2438,9 @@ static void qfillcmd() DEV_RECORD *rec = dcr->rec; int i, count; - Pmsg0(0, "Test writing blocks of 64512 bytes to tape.\n"); + Pmsg0(0, _("Test writing blocks of 64512 bytes to tape.\n")); - get_cmd("How many blocks do you want to write? (1000): "); + get_cmd(_("How many blocks do you want to write? (1000): ")); count = atoi(cmd); if (count <= 0) { @@ -2340,7 +2455,7 @@ static void qfillcmd() memset(rec->data, i & 0xFF, i); rec->data_len = i; rewindcmd(); - Pmsg1(0, "Begin writing %d Bacula blocks to tape ...\n", count); + Pmsg1(0, _("Begin writing %d Bacula blocks to tape ...\n"), count); for (i=0; i < count; i++) { if (i % 100 == 0) { printf("+"); @@ -2357,7 +2472,7 @@ static void qfillcmd() } printf("\n"); weofcmd(); - if (dev_cap(dev, CAP_TWOEOF)) { + if (dev->has_cap(CAP_TWOEOF)) { weofcmd(); } rewindcmd(); @@ -2392,10 +2507,10 @@ static void rawfill_cmd() } } p = (uint32_t *)block->buf; - Pmsg1(0, "Begin writing raw blocks of %u bytes.\n", block->buf_len); + Pmsg1(0, _("Begin writing raw blocks of %u bytes.\n"), block->buf_len); for ( ;; ) { *p = block_num; - stat = write(dev->fd, block->buf, block->buf_len); + stat = dev->d_write(dev->fd(), block->buf, block->buf_len); if (stat == (int)block->buf_len) { if ((block_num++ % 100) == 0) { printf("+"); @@ -2412,90 +2527,43 @@ static void rawfill_cmd() my_errno = errno; printf("\n"); berrno be; - printf("Write failed at block %u. stat=%d ERR=%s\n", block_num, stat, - be.strerror(my_errno)); + printf(_("Write failed at block %u. stat=%d ERR=%s\n"), block_num, stat, + be.bstrerror(my_errno)); weofcmd(); } -/* - * Fill a tape using Bacula block writes - */ -static void bfill_cmd() -{ - DEV_BLOCK *block = dcr->block; - uint32_t block_num = 0; - uint32_t *p; - int my_errno; - int fd; - uint32_t i; - - fd = open("/dev/urandom", O_RDONLY); - if (fd) { - read(fd, block->buf, block->buf_len); - close(fd); - } else { - uint32_t *p = (uint32_t *)block->buf; - srandom(time(NULL)); - for (i=0; ibuf_len/sizeof(uint32_t); i++) { - p[i] = random(); - } - } - p = (uint32_t *)block->buf; - Pmsg1(0, "Begin writing Bacula blocks of %u bytes.\n", block->buf_len); - for ( ;; ) { - *p = block_num; - block->binbuf = block->buf_len; - block->bufp = block->buf + block->binbuf; - if (!write_block_to_dev(dcr)) { - break; - } - if ((block_num++ % 100) == 0) { - printf("+"); - fflush(stdout); - } - p[0] += p[13]; - for (i=1; i<(block->buf_len/sizeof(uint32_t)-1); i++) { - p[i] += p[i-1]; - } - } - my_errno = errno; - printf("\n"); - printf("Write failed at block %u.\n", block_num); - weofcmd(); -} - struct cmdstruct { const char *key; void (*func)(); const char *help; }; static struct cmdstruct commands[] = { - {"autochanger", autochangercmd, "test autochanger"}, - {"bsf", bsfcmd, "backspace file"}, - {"bsr", bsrcmd, "backspace record"}, - {"bfill", bfill_cmd, "fill tape using Bacula writes"}, - {"cap", capcmd, "list device capabilities"}, - {"clear", clearcmd, "clear tape errors"}, - {"eod", eodcmd, "go to end of Bacula data for append"}, - {"eom", eomcmd, "go to the physical end of medium"}, - {"fill", fillcmd, "fill tape, write onto second volume"}, - {"unfill", unfillcmd, "read filled tape"}, - {"fsf", fsfcmd, "forward space a file"}, - {"fsr", fsrcmd, "forward space a record"}, - {"help", helpcmd, "print this command"}, - {"label", labelcmd, "write a Bacula label to the tape"}, - {"load", loadcmd, "load a tape"}, - {"quit", quitcmd, "quit btape"}, - {"rawfill", rawfill_cmd, "use write() to fill tape"}, - {"readlabel", readlabelcmd, "read and print the Bacula tape label"}, - {"rectest", rectestcmd, "test record handling functions"}, - {"rewind", rewindcmd, "rewind the tape"}, - {"scan", scancmd, "read() tape block by block to EOT and report"}, - {"scanblocks", scan_blocks, "Bacula read block by block to EOT and report"}, - {"status", statcmd, "print tape status"}, - {"test", testcmd, "General test Bacula tape functions"}, - {"weof", weofcmd, "write an EOF on the tape"}, - {"wr", wrcmd, "write a single Bacula block"}, - {"rr", rrcmd, "read a single record"}, - {"qfill", qfillcmd, "quick fill command"}, + {NT_("autochanger"),autochangercmd, _("test autochanger")}, + {NT_("bsf"), bsfcmd, _("backspace file")}, + {NT_("bsr"), bsrcmd, _("backspace record")}, + {NT_("cap"), capcmd, _("list device capabilities")}, + {NT_("clear"), clearcmd, _("clear tape errors")}, + {NT_("eod"), eodcmd, _("go to end of Bacula data for append")}, + {NT_("eom"), eomcmd, _("go to the physical end of medium")}, + {NT_("fill"), fillcmd, _("fill tape, write onto second volume")}, + {NT_("unfill"), unfillcmd, _("read filled tape")}, + {NT_("fsf"), fsfcmd, _("forward space a file")}, + {NT_("fsr"), fsrcmd, _("forward space a record")}, + {NT_("help"), helpcmd, _("print this command")}, + {NT_("label"), labelcmd, _("write a Bacula label to the tape")}, + {NT_("load"), loadcmd, _("load a tape")}, + {NT_("quit"), quitcmd, _("quit btape")}, + {NT_("rawfill"), rawfill_cmd, _("use write() to fill tape")}, + {NT_("readlabel"), readlabelcmd, _("read and print the Bacula tape label")}, + {NT_("rectest"), rectestcmd, _("test record handling functions")}, + {NT_("rewind"), rewindcmd, _("rewind the tape")}, + {NT_("scan"), scancmd, _("read() tape block by block to EOT and report")}, + {NT_("scanblocks"),scan_blocks, _("Bacula read block by block to EOT and report")}, + {NT_("status"), statcmd, _("print tape status")}, + {NT_("test"), testcmd, _("General test Bacula tape functions")}, + {NT_("weof"), weofcmd, _("write an EOF on the tape")}, + {NT_("wr"), wrcmd, _("write a single Bacula block")}, + {NT_("rr"), rrcmd, _("read a single record")}, + {NT_("rb"), rbcmd, _("read a single Bacula block")}, + {NT_("qfill"), qfillcmd, _("quick fill command")} }; #define comsize (sizeof(commands)/sizeof(struct cmdstruct)) @@ -2505,7 +2573,7 @@ do_tape_cmds() unsigned int i; bool found; - while (get_cmd("*")) { + while (!quit && get_cmd("*")) { sm_check(__FILE__, __LINE__, false); found = false; parse_args(cmd, &args, &argc, argk, argv, MAX_CMD_ARGS); @@ -2515,10 +2583,9 @@ do_tape_cmds() found = true; break; } - if (!found) - Pmsg1(0, _("%s is an illegal command\n"), cmd); - if (quit) - break; + if (!found) { + Pmsg1(0, _("\"%s\" is an invalid command\n"), cmd); + } } } @@ -2536,17 +2603,18 @@ static void helpcmd() static void usage() { fprintf(stderr, _( -"Copyright (C) 2000-2005 Kern Sibbald.\n" -"\nVersion: " VERSION " (" BDATE ")\n\n" +PROG_COPYRIGHT +"\nVersion: %s (%s)\n\n" "Usage: btape \n" " -b specify bootstrap file\n" " -c set configuration file to file\n" -" -d set debug level to nn\n" +" -d set debug level to \n" +" -dt print timestamp in debug output\n" " -p proceed inspite of I/O errors\n" " -s turn off signals\n" " -v be verbose\n" " -? print this message.\n" -"\n")); +"\n"), 2000, VERSION, BDATE); } @@ -2587,7 +2655,7 @@ get_cmd(const char *prompt) bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec) { return 1;} bool dir_send_job_status(JCR *jcr) {return 1;} -bool dir_update_volume_info(DCR *dcr, bool relabel) +bool dir_update_volume_info(DCR *dcr, bool relabel, bool update_LastWritten) { return 1; } @@ -2613,33 +2681,29 @@ bool dir_find_next_appendable_volume(DCR *dcr) return dcr->VolumeName[0] != 0; } -bool dir_ask_sysop_to_mount_volume(DCR *dcr) +bool dir_ask_sysop_to_mount_volume(DCR *dcr, int /* mode */) { DEVICE *dev = dcr->dev; Dmsg0(20, "Enter dir_ask_sysop_to_mount_volume\n"); if (dcr->VolumeName[0] == 0) { return dir_ask_sysop_to_create_appendable_volume(dcr); } - /* Close device so user can use autochanger if desired */ - if (dev_cap(dev, CAP_OFFLINEUNMOUNT)) { - offline_dev(dev); - } - force_close_dev(dev); Pmsg1(-1, "%s", dev->errmsg); /* print reason */ if (dcr->VolumeName[0] == 0 || strcmp(dcr->VolumeName, "TestVolume2") == 0) { - fprintf(stderr, "Mount second Volume on device %s and press return when ready: ", + fprintf(stderr, _("Mount second Volume on device %s and press return when ready: "), dev->print_name()); } else { - fprintf(stderr, "Mount Volume \"%s\" on device %s and press return when ready: ", + fprintf(stderr, _("Mount Volume \"%s\" on device %s and press return when ready: "), dcr->VolumeName, dev->print_name()); } + dev->close(); getchar(); return true; } bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr) { - bool autochanger; + int autochanger; DEVICE *dev = dcr->dev; Dmsg0(20, "Enter dir_ask_sysop_to_create_appendable_volume\n"); if (stop == 0) { @@ -2648,17 +2712,16 @@ bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr) set_volume_name("TestVolume2", 2); } /* Close device so user can use autochanger if desired */ - if (dev_cap(dev, CAP_OFFLINEUNMOUNT)) { - offline_dev(dev); + if (dev->has_cap(CAP_OFFLINEUNMOUNT)) { + dev->offline(); } autochanger = autoload_device(dcr, 1, NULL); - if (!autochanger) { - force_close_dev(dev); - fprintf(stderr, "Mount blank Volume on device %s and press return when ready: ", + if (autochanger != 1) { + fprintf(stderr, _("Mount blank Volume on device %s and press return when ready: "), dev->print_name()); + dev->close(); getchar(); } - open_device(dcr); labelcmd(); VolumeName = NULL; BlockNumber = 0; @@ -2672,8 +2735,10 @@ static bool my_mount_next_read_volume(DCR *dcr) DEV_BLOCK *block = dcr->block; Dmsg0(20, "Enter my_mount_next_read_volume\n"); - Pmsg1(000, "End of Volume \"%s\"\n", dcr->VolumeName); + Pmsg2(000, _("End of Volume \"%s\" %d records.\n"), dcr->VolumeName, + quickie_count); + volume_unused(dcr); /* release current volume */ if (LastBlock != block->BlockNumber) { VolBytes += block->block_len; } @@ -2684,7 +2749,7 @@ static bool my_mount_next_read_volume(DCR *dcr) now = 1; } kbs = (double)VolBytes / (1000.0 * (double)now); - Pmsg3(-1, "Read block=%u, VolBytes=%s rate=%.1f KB/s\n", block->BlockNumber, + Pmsg3(-1, _("Read block=%u, VolBytes=%s rate=%.1f KB/s\n"), block->BlockNumber, edit_uint64_with_commas(VolBytes, ec1), (float)kbs); if (strcmp(dcr->VolumeName, "TestVolume2") == 0) { @@ -2692,14 +2757,11 @@ static bool my_mount_next_read_volume(DCR *dcr) return false; } - free_vol_list(jcr); set_volume_name("TestVolume2", 2); - jcr->bsr = NULL; - create_vol_list(jcr); - close_dev(dev); - dev->clear_read(); + + dev->close(); if (!acquire_device_for_read(dcr)) { - Pmsg2(0, "Cannot open Dev=%s, Vol=%s\n", dev->print_name(), dcr->VolumeName); + Pmsg2(0, _("Cannot open Dev=%s, Vol=%s\n"), dev->print_name(), dcr->VolumeName); return false; } return true; /* next volume mounted */ @@ -2714,4 +2776,5 @@ static void set_volume_name(const char *VolName, int volnum) bstrncpy(dcr->VolCatInfo.VolCatName, VolName, sizeof(dcr->VolCatInfo.VolCatName)); bstrncpy(dcr->VolumeName, VolName, sizeof(dcr->VolumeName)); dcr->VolCatInfo.Slot = volnum; + dcr->VolCatInfo.InChanger = true; }