#include "stored.h"
/* Forward referenced functions */
-static void do_scan(void);
static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec);
/* Global variables */
-static DEVICE *dev = NULL;
-static B_DB *db;
-static JCR *bjcr; /* jcr for bscan */
+static DEVICE *in_dev = NULL;
+static DEVICE *out_dev = NULL;
+static JCR *in_jcr; /* input jcr */
+static JCR *out_jcr; /* output jcr */
static BSR *bsr = NULL;
static char *wd = "/tmp";
static int verbose = 0;
+static int list_records = 0;
+static uint32_t records = 0;
+static uint32_t jobs = 0;
+static DEV_BLOCK *out_block;
#define CONFIG_FILE "bacula-sd.conf"
char *configfile;
parse_config(configfile);
- bjcr = setup_jcr("bcopy", argv[0], bsr);
- dev = setup_to_access_device(bjcr, 0); /* read device */
- if (!dev) {
+ /* Setup and acquire input device for reading */
+ in_jcr = setup_jcr("bcopy", argv[0], bsr);
+ in_dev = setup_to_access_device(in_jcr, 1); /* read device */
+ if (!in_dev) {
exit(1);
}
- do_copy();
+ /* Setup output device for writing */
+ out_jcr = setup_jcr("bcopy", argv[1], bsr);
+ out_dev = setup_to_access_device(out_jcr, 0); /* no acquire */
+ if (!out_dev) {
+ exit(1);
+ }
+ /* For we must now acquire the device for writing */
+ out_block = new_block(out_dev);
+ lock_device(out_dev);
+ if (open_dev(out_dev, out_jcr->VolumeName, READ_WRITE) < 0) {
+ Emsg1(M_FATAL, 0, _("dev open failed: %s\n"), out_dev->errmsg);
+ unlock_device(out_dev);
+ free_block(out_block);
+ exit(1);
+ }
+ unlock_device(out_dev);
+ if (!acquire_device_for_append(out_jcr, out_dev, out_block)) {
+ free_block(out_block);
+ free_jcr(in_jcr);
+ exit(1);
+ }
+
+ read_records(in_jcr, in_dev, record_cb, mount_next_read_volume);
+ if (!write_block_to_device(out_jcr, out_dev, out_block)) {
+ Pmsg0(000, _("Write of last block failed.\n"));
+ }
+
+ Pmsg2(000, _("%u Jobs copied. %u records copied.\n"), jobs, records);
- free_jcr(bjcr);
+ free_block(out_block);
+ term_dev(in_dev);
+ term_dev(out_dev);
+ free_jcr(in_jcr);
+ free_jcr(out_jcr);
return 0;
}
-static void do_copy()
-{
- detach_jcr_from_device(dev, bjcr);
-
- read_records(bjcr, dev, record_cb, mount_next_read_volume);
- release_device(bjcr, dev);
-
- term_dev(dev);
-}
-static void record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
+static void record_cb(JCR *in_jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
{
- JCR *mjcr;
- char ec1[30];
-
if (list_records) {
Pmsg5(000, _("Record: SessId=%u SessTim=%u FileIndex=%d Stream=%d len=%u\n"),
rec->VolSessionId, rec->VolSessionTime, rec->FileIndex,
case PRE_LABEL:
Pmsg0(000, "Volume is prelabeled. This volume cannot be copied.\n");
return;
- break;
case VOL_LABEL:
- Pmsg1(000, "VOL_LABEL: OK for Volume: %s\n", mr.VolumeName);
- break;
+ Pmsg0(000, "Volume label not copied.\n");
+ return;
case SOS_LABEL:
+ jobs++;
break;
case EOS_LABEL:
+ while (!write_record_to_block(out_block, rec)) {
+ Dmsg2(150, "!write_record_to_block data_len=%d rem=%d\n", rec->data_len,
+ rec->remainder);
+ if (!write_block_to_device(out_jcr, out_dev, out_block)) {
+ Dmsg2(90, "Got write_block_to_dev error on device %s. %s\n",
+ dev_name(out_dev), strerror_dev(out_dev));
+ Jmsg(out_jcr, M_FATAL, 0, _("Cannot fixup device error. %s\n"),
+ strerror_dev(out_dev));
+ }
+ }
+ if (!write_block_to_device(out_jcr, out_dev, out_block)) {
+ Dmsg2(90, "Got write_block_to_dev error on device %s. %s\n",
+ dev_name(out_dev), strerror_dev(out_dev));
+ Jmsg(out_jcr, M_FATAL, 0, _("Cannot fixup device error. %s\n"),
+ strerror_dev(out_dev));
+ }
break;
case EOM_LABEL:
- break;
+ Pmsg0(000, "EOM label not copied.\n");
+ return;
case EOT_LABEL: /* end of all tapes */
- break;
+ Pmsg0(000, "EOT label not copied.\n");
+ return;
default:
break;
}
- return;
}
/* Write record */
-
- return;
-}
-
-/*
- * Free the Job Control Record if no one is still using it.
- * Called from main free_jcr() routine in src/lib/jcr.c so
- * that we can do our Director specific cleanup of the jcr.
- */
-static void dird_free_jcr(JCR *jcr)
-{
- Dmsg0(200, "Start dird free_jcr\n");
-
- if (jcr->file_bsock) {
- Dmsg0(200, "Close File bsock\n");
- bnet_close(jcr->file_bsock);
- }
- if (jcr->store_bsock) {
- Dmsg0(200, "Close Store bsock\n");
- bnet_close(jcr->store_bsock);
- }
- if (jcr->RestoreBootstrap) {
- free(jcr->RestoreBootstrap);
+ records++;
+ while (!write_record_to_block(out_block, rec)) {
+ Dmsg2(150, "!write_record_to_block data_len=%d rem=%d\n", rec->data_len,
+ rec->remainder);
+ if (!write_block_to_device(out_jcr, out_dev, out_block)) {
+ Dmsg2(90, "Got write_block_to_dev error on device %s. %s\n",
+ dev_name(out_dev), strerror_dev(out_dev));
+ Jmsg(out_jcr, M_FATAL, 0, _("Cannot fixup device error. %s\n"),
+ strerror_dev(out_dev));
+ break;
+ }
}
- Dmsg0(200, "End dird free_jcr\n");
+ return;
}
-
-/*
- * Create a JCR as if we are really starting the job
- */
-static JCR *create_jcr(JOB_DBR *jr, DEV_RECORD *rec, uint32_t JobId)
-{
- JCR *jobjcr;
- /*
- * Transfer as much as possible to the Job JCR. Most important is
- * the JobId and the ClientId.
- */
- jobjcr = new_jcr(sizeof(JCR), dird_free_jcr);
- jobjcr->JobType = jr->Type;
- jobjcr->JobLevel = jr->Level;
- jobjcr->JobStatus = jr->JobStatus;
- strcpy(jobjcr->Job, jr->Job);
- jobjcr->JobId = JobId; /* this is JobId on tape */
- jobjcr->sched_time = jr->SchedTime;
- jobjcr->start_time = jr->StartTime;
- jobjcr->VolSessionId = rec->VolSessionId;
- jobjcr->VolSessionTime = rec->VolSessionTime;
- jobjcr->ClientId = jr->ClientId;
- attach_jcr_to_device(dev, jobjcr);
- return jobjcr;
-}
-
/* Dummies to replace askdir.c */
int dir_get_volume_info(JCR *jcr, int writing) { return 1;}
int dir_find_next_appendable_volume(JCR *jcr) { return 1;}
int dir_ask_sysop_to_mount_volume(JCR *jcr, DEVICE *dev)
{
- /*
- * We are at the end of reading a tape. Now, we simulate handling
- * the end of writing a tape by wiffling through the attached
- * jcrs creating jobmedia records.
- */
- Dmsg1(100, "Walk attached jcrs. Volume=%s\n", dev->VolCatInfo.VolCatName);
- for (JCR *mjcr=NULL; (mjcr=next_attached_jcr(dev, mjcr)); ) {
- if (verbose) {
- Pmsg1(000, "create JobMedia for Job %s\n", mjcr->Job);
- }
- if (dev->state & ST_TAPE) {
- mjcr->EndBlock = dev->block_num;
- mjcr->EndFile = dev->file;
- } else {
- mjcr->EndBlock = (uint32_t)dev->file_addr;
- mjcr->StartBlock = (uint32_t)(dev->file_addr >> 32);
- }
- if (!create_jobmedia_record(db, mjcr)) {
- Pmsg2(000, _("Could not create JobMedia record for Volume=%s Job=%s\n"),
- dev->VolCatInfo.VolCatName, mjcr->Job);
- }
- }
-
fprintf(stderr, "Mount Volume %s on device %s and press return when ready: ",
- jcr->VolumeName, dev_name(dev));
+ in_jcr->VolumeName, dev_name(dev));
getchar();
return 1;
}
}
}
- if ((device=find_device_res(jcr->dev_name)) == NULL) {
- Emsg2(M_FATAL, 0, "Cannot find device %s in config file %s.\n",
+ if ((device=find_device_res(jcr->dev_name, read_access)) == NULL) {
+ Emsg2(M_FATAL, 0, _("Cannot find device %s in config file %s.\n"),
jcr->dev_name, configfile);
return NULL;
}
dev = init_dev(NULL, device);
- if (!dev) {
- Emsg1(M_FATAL, 0, "Cannot open %s\n", jcr->dev_name);
- return NULL;
- }
- if (!open_device(dev)) {
- Emsg1(M_FATAL, 0, "Cannot open %s\n", jcr->dev_name);
+ if (!dev || !open_device(dev)) {
+ Emsg1(M_FATAL, 0, _("Cannot open %s\n"), jcr->dev_name);
return NULL;
}
Dmsg0(90, "Device opened for read.\n");
free_block(block);
return NULL;
}
- } else {
- lock_device(dev);
- if (!(dev->state & ST_OPENED)) {
- Dmsg0(129, "Opening device.\n");
- if (open_dev(dev, jcr->VolumeName, READ_WRITE) < 0) {
- Emsg1(M_FATAL, 0, _("dev open failed: %s\n"), dev->errmsg);
- unlock_device(dev);
- free_block(block);
- return NULL;
- }
- }
- Dmsg1(129, "open_dev %s OK\n", dev_name(dev));
- unlock_device(dev);
}
free_block(block);
return dev;
* Returns: NULL on failure
* Device resource pointer on success
*/
-DEVRES *find_device_res(char *device_name)
+DEVRES *find_device_res(char *device_name, int read_access)
{
int found = 0;
DEVRES *device;
}
UnlockRes();
if (!found) {
- Pmsg2(0, "Could not find device %s in config file %s.\n", device_name,
+ Pmsg2(0, _("Could not find device %s in config file %s.\n"), device_name,
configfile);
return NULL;
}
- Pmsg1(0, "Using device: %s\n", device_name);
+ Pmsg2(0, _("Using device: %s for %s.\n"), device_name,
+ read_access?"reading":"writing");
return device;
}
status_dev(dev, &status);
Dmsg1(20, "Device status: %x\n", status);
if (status & MT_EOD)
- Emsg0(M_ERROR_TERM, 0, "Unexpected End of Data\n");
+ Emsg0(M_ERROR_TERM, 0, _("Unexpected End of Data\n"));
else if (status & MT_EOT)
- Emsg0(M_ERROR_TERM, 0, "Unexpected End of Tape\n");
+ Emsg0(M_ERROR_TERM, 0, _("Unexpected End of Tape\n"));
else if (status & MT_EOF)
- Emsg0(M_ERROR_TERM, 0, "Unexpected End of File\n");
+ Emsg0(M_ERROR_TERM, 0, _("Unexpected End of File\n"));
else if (status & MT_DR_OPEN)
- Emsg0(M_ERROR_TERM, 0, "Tape Door is Open\n");
+ Emsg0(M_ERROR_TERM, 0, _("Tape Door is Open\n"));
else if (!(status & MT_ONLINE))
- Emsg0(M_ERROR_TERM, 0, "Unexpected Tape is Off-line\n");
+ Emsg0(M_ERROR_TERM, 0, _("Unexpected Tape is Off-line\n"));
else
- Emsg2(M_ERROR_TERM, 0, "Read error on Record Header %s: %s\n", dev_name(dev), strerror(errno));
+ Emsg2(M_ERROR_TERM, 0, _("Read error on Record Header %s: %s\n"), dev_name(dev), strerror(errno));
}