3 * Program to copy a Bacula from one volume to another.
5 * Kern E. Sibbald, October 2002
11 Copyright (C) 2001, 2002 Kern Sibbald and John Walker
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of
16 the License, or (at your option) any later version.
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
23 You should have received a copy of the GNU General Public
24 License along with this program; if not, write to the Free
25 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
33 /* Forward referenced functions */
34 static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec);
37 /* Global variables */
38 static DEVICE *in_dev = NULL;
39 static DEVICE *out_dev = NULL;
40 static JCR *in_jcr; /* input jcr */
41 static JCR *out_jcr; /* output jcr */
42 static BSR *bsr = NULL;
43 static char *wd = "/tmp";
44 static int verbose = 0;
45 static int list_records = 0;
46 static uint32_t records = 0;
47 static uint32_t jobs = 0;
48 static DEV_BLOCK *out_block;
50 #define CONFIG_FILE "bacula-sd.conf"
57 "\nVersion: " VERSION " (" BDATE ")\n\n"
58 "Usage: bcopy [-d debug_level] <input-archive> <output-archive>\n"
59 " -b bootstrap specify a bootstrap file\n"
60 " -c <file> specify configuration file\n"
61 " -dnn set debug level to nn\n"
63 " -i specify input Volume names (separated by |)\n"
64 " -o specify output Volume names (separated by |)\n"
65 " -w dir specify working directory (default /tmp)\n"
66 " -? print this message\n\n"));
70 int main (int argc, char *argv[])
73 char *iVolumeName = NULL;
74 char *oVolumeName = NULL;
76 my_name_is(argc, argv, "bscan");
79 while ((ch = getopt(argc, argv, "b:c:d:mn:p:rsu:vV:w:?")) != -1) {
82 bsr = parse_bsr(NULL, optarg);
85 case 'c': /* specify config file */
86 if (configfile != NULL) {
89 configfile = bstrdup(optarg);
92 case 'd': /* debug level */
93 debug_level = atoi(optarg);
102 case 'i': /* input Volume name */
103 iVolumeName = optarg;
106 case 'o': /* output Volume name */
107 oVolumeName = optarg;
125 Pmsg0(0, _("Wrong number of arguments: \n"));
129 working_directory = wd;
131 if (configfile == NULL) {
132 configfile = bstrdup(CONFIG_FILE);
135 parse_config(configfile);
137 /* Setup and acquire input device for reading */
138 in_jcr = setup_jcr("bcopy", argv[0], bsr, iVolumeName);
139 in_dev = setup_to_access_device(in_jcr, 1); /* read device */
144 /* Setup output device for writing */
145 out_jcr = setup_jcr("bcopy", argv[1], bsr, oVolumeName);
146 out_dev = setup_to_access_device(out_jcr, 0); /* no acquire */
150 /* For we must now acquire the device for writing */
151 out_block = new_block(out_dev);
152 lock_device(out_dev);
153 if (open_dev(out_dev, out_jcr->VolumeName, READ_WRITE) < 0) {
154 Emsg1(M_FATAL, 0, _("dev open failed: %s\n"), out_dev->errmsg);
155 unlock_device(out_dev);
156 free_block(out_block);
159 unlock_device(out_dev);
160 if (!(out_dev=acquire_device_for_append(out_jcr, out_dev, out_block))) {
161 free_block(out_block);
166 read_records(in_jcr, in_dev, record_cb, mount_next_read_volume);
167 if (!write_block_to_device(out_jcr, out_dev, out_block)) {
168 Pmsg0(000, _("Write of last block failed.\n"));
171 Pmsg2(000, _("%u Jobs copied. %u records copied.\n"), jobs, records);
173 free_block(out_block);
183 static void record_cb(JCR *in_jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
186 Pmsg5(000, _("Record: SessId=%u SessTim=%u FileIndex=%d Stream=%d len=%u\n"),
187 rec->VolSessionId, rec->VolSessionTime, rec->FileIndex,
188 rec->Stream, rec->data_len);
191 * Check for Start or End of Session Record
194 if (rec->FileIndex < 0) {
197 dump_label_record(dev, rec, 1);
199 switch (rec->FileIndex) {
201 Pmsg0(000, "Volume is prelabeled. This volume cannot be copied.\n");
204 Pmsg0(000, "Volume label not copied.\n");
210 while (!write_record_to_block(out_block, rec)) {
211 Dmsg2(150, "!write_record_to_block data_len=%d rem=%d\n", rec->data_len,
213 if (!write_block_to_device(out_jcr, out_dev, out_block)) {
214 Dmsg2(90, "Got write_block_to_dev error on device %s. %s\n",
215 dev_name(out_dev), strerror_dev(out_dev));
216 Jmsg(out_jcr, M_FATAL, 0, _("Cannot fixup device error. %s\n"),
217 strerror_dev(out_dev));
220 if (!write_block_to_device(out_jcr, out_dev, out_block)) {
221 Dmsg2(90, "Got write_block_to_dev error on device %s. %s\n",
222 dev_name(out_dev), strerror_dev(out_dev));
223 Jmsg(out_jcr, M_FATAL, 0, _("Cannot fixup device error. %s\n"),
224 strerror_dev(out_dev));
228 Pmsg0(000, "EOM label not copied.\n");
230 case EOT_LABEL: /* end of all tapes */
231 Pmsg0(000, "EOT label not copied.\n");
240 while (!write_record_to_block(out_block, rec)) {
241 Dmsg2(150, "!write_record_to_block data_len=%d rem=%d\n", rec->data_len,
243 if (!write_block_to_device(out_jcr, out_dev, out_block)) {
244 Dmsg2(90, "Got write_block_to_dev error on device %s. %s\n",
245 dev_name(out_dev), strerror_dev(out_dev));
246 Jmsg(out_jcr, M_FATAL, 0, _("Cannot fixup device error. %s\n"),
247 strerror_dev(out_dev));
255 /* Dummies to replace askdir.c */
256 int dir_get_volume_info(JCR *jcr, int writing) { return 1;}
257 int dir_find_next_appendable_volume(JCR *jcr) { return 1;}
258 int dir_update_volume_info(JCR *jcr, VOLUME_CAT_INFO *vol, int relabel) { return 1; }
259 int dir_create_jobmedia_record(JCR *jcr) { return 1; }
260 int dir_ask_sysop_to_mount_next_volume(JCR *jcr, DEVICE *dev) { return 1; }
261 int dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec) { return 1;}
262 int dir_send_job_status(JCR *jcr) {return 1;}
265 int dir_ask_sysop_to_mount_volume(JCR *jcr, DEVICE *dev)
267 fprintf(stderr, "Mount Volume %s on device %s and press return when ready: ",
268 in_jcr->VolumeName, dev_name(dev));