]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/bcopy.c
58cec0eb69189c605dfbc3372400ae1f687f78ea
[bacula/bacula] / bacula / src / stored / bcopy.c
1 /*
2  *
3  *  Program to copy a Bacula from one volume to another.
4  *
5  *   Kern E. Sibbald, October 2002
6  *
7  *
8  *   Version $Id$
9  */
10 /*
11    Copyright (C) 2001, 2002 Kern Sibbald and John Walker
12
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.
17
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.
22
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,
26    MA 02111-1307, USA.
27
28  */
29
30 #include "bacula.h"
31 #include "stored.h"
32
33 /* Forward referenced functions */
34 static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec);
35
36
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;
49
50 #define CONFIG_FILE "bacula-sd.conf"
51 char *configfile;
52
53
54 static void usage()
55 {
56    fprintf(stderr, _(
57 "\nVersion: " VERSION " (" DATE ")\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"
62 "       -v                verbose\n"
63 "       -w dir            specify working directory (default /tmp)\n"
64 "       -?                print this message\n\n"));
65    exit(1);
66 }
67
68 int main (int argc, char *argv[])
69 {
70    int ch;
71
72    my_name_is(argc, argv, "bscan");
73    init_msg(NULL, NULL);
74
75    fprintf(stderr, "\n\nPlease don't use this program.\n\
76 It is currently under development and does not work.\n\n");
77
78    while ((ch = getopt(argc, argv, "b:c:d:mn:p:rsu:vw:?")) != -1) {
79       switch (ch) {
80          case 'b':
81             bsr = parse_bsr(NULL, optarg);
82             break;
83
84          case 'c':                    /* specify config file */
85             if (configfile != NULL) {
86                free(configfile);
87             }
88             configfile = bstrdup(optarg);
89             break;
90
91          case 'd':                    /* debug level */
92             debug_level = atoi(optarg);
93             if (debug_level <= 0)
94                debug_level = 1; 
95             break;
96
97          case 'v':
98             verbose++;
99             break;
100
101          case 'w':
102             wd = optarg;
103             break;
104
105          case '?':
106          default:
107             usage();
108
109       }  
110    }
111    argc -= optind;
112    argv += optind;
113
114    if (argc != 2) {
115       Pmsg0(0, _("Wrong number of arguments: \n"));
116       usage();
117    }
118
119    working_directory = wd;
120
121    if (configfile == NULL) {
122       configfile = bstrdup(CONFIG_FILE);
123    }
124
125    parse_config(configfile);
126
127    /* Setup and acquire input device for reading */
128    in_jcr = setup_jcr("bcopy", argv[0], bsr);
129    in_dev = setup_to_access_device(in_jcr, 1);   /* read device */
130    if (!in_dev) { 
131       exit(1);
132    }
133
134    /* Setup output device for writing */
135    out_jcr = setup_jcr("bcopy", argv[1], bsr);
136    out_dev = setup_to_access_device(out_jcr, 0);   /* no acquire */  
137    if (!out_dev) { 
138       exit(1);      
139    }
140    /* For we must now acquire the device for writing */
141    out_block = new_block(out_dev);
142    lock_device(out_dev);
143    if (open_dev(out_dev, out_jcr->VolumeName, READ_WRITE) < 0) {
144       Emsg1(M_FATAL, 0, _("dev open failed: %s\n"), out_dev->errmsg);
145       unlock_device(out_dev);
146       free_block(out_block);
147       exit(1);
148    }
149    unlock_device(out_dev);
150    if (!acquire_device_for_append(out_jcr, out_dev, out_block)) {
151       free_block(out_block);
152       free_jcr(in_jcr);
153       exit(1);
154    }
155
156    read_records(in_jcr, in_dev, record_cb, mount_next_read_volume);
157    if (!write_block_to_device(out_jcr, out_dev, out_block)) {
158       Pmsg0(000, _("Write of last block failed.\n"));
159    }
160
161    Pmsg2(000, _("%u Jobs copied. %u records copied.\n"), jobs, records);
162
163    free_block(out_block);
164    term_dev(in_dev);
165    term_dev(out_dev);
166    free_jcr(in_jcr);
167    free_jcr(out_jcr);
168    return 0;
169 }
170   
171
172
173 static void record_cb(JCR *in_jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
174 {
175    if (list_records) {
176       Pmsg5(000, _("Record: SessId=%u SessTim=%u FileIndex=%d Stream=%d len=%u\n"),
177             rec->VolSessionId, rec->VolSessionTime, rec->FileIndex, 
178             rec->Stream, rec->data_len);
179    }
180    /* 
181     * Check for Start or End of Session Record 
182     *
183     */
184    if (rec->FileIndex < 0) {
185
186       if (verbose > 1) {
187          dump_label_record(dev, rec, 1);
188       }
189       switch (rec->FileIndex) {
190          case PRE_LABEL:
191             Pmsg0(000, "Volume is prelabeled. This volume cannot be copied.\n");
192             return;
193          case VOL_LABEL:
194             Pmsg0(000, "Volume label not copied.\n");
195             return;
196          case SOS_LABEL:
197             jobs++;
198             break;
199          case EOS_LABEL:
200             while (!write_record_to_block(out_block, rec)) {
201                Dmsg2(150, "!write_record_to_block data_len=%d rem=%d\n", rec->data_len,
202                           rec->remainder);
203                if (!write_block_to_device(out_jcr, out_dev, out_block)) {
204                   Dmsg2(90, "Got write_block_to_dev error on device %s. %s\n",
205                      dev_name(out_dev), strerror_dev(out_dev));
206                   Jmsg(out_jcr, M_FATAL, 0, _("Cannot fixup device error. %s\n"),
207                         strerror_dev(out_dev));
208                }
209             }
210             if (!write_block_to_device(out_jcr, out_dev, out_block)) {
211                Dmsg2(90, "Got write_block_to_dev error on device %s. %s\n",
212                   dev_name(out_dev), strerror_dev(out_dev));
213                Jmsg(out_jcr, M_FATAL, 0, _("Cannot fixup device error. %s\n"),
214                      strerror_dev(out_dev));
215             }
216             break;
217          case EOM_LABEL:
218             Pmsg0(000, "EOM label not copied.\n");
219             return;
220          case EOT_LABEL:              /* end of all tapes */
221             Pmsg0(000, "EOT label not copied.\n");
222             return;
223          default:
224             break;
225       }
226    }
227
228    /*  Write record */
229    records++;
230    while (!write_record_to_block(out_block, rec)) {
231       Dmsg2(150, "!write_record_to_block data_len=%d rem=%d\n", rec->data_len,
232                  rec->remainder);
233       if (!write_block_to_device(out_jcr, out_dev, out_block)) {
234          Dmsg2(90, "Got write_block_to_dev error on device %s. %s\n",
235             dev_name(out_dev), strerror_dev(out_dev));
236          Jmsg(out_jcr, M_FATAL, 0, _("Cannot fixup device error. %s\n"),
237                strerror_dev(out_dev));
238          break;
239       }
240    }
241    return;
242 }
243
244
245 /* Dummies to replace askdir.c */
246 int     dir_get_volume_info(JCR *jcr, int writing) { return 1;}
247 int     dir_find_next_appendable_volume(JCR *jcr) { return 1;}
248 int     dir_update_volume_info(JCR *jcr, VOLUME_CAT_INFO *vol, int relabel) { return 1; }
249 int     dir_create_jobmedia_record(JCR *jcr) { return 1; }
250 int     dir_ask_sysop_to_mount_next_volume(JCR *jcr, DEVICE *dev) { return 1; }
251 int     dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec) { return 1;}
252 int     dir_send_job_status(JCR *jcr) {return 1;}
253
254
255 int dir_ask_sysop_to_mount_volume(JCR *jcr, DEVICE *dev)
256 {
257    fprintf(stderr, "Mount Volume %s on device %s and press return when ready: ",
258       in_jcr->VolumeName, dev_name(dev));
259    getchar();   
260    return 1;
261 }