]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/bcopy.c
e8265ded204349f0851ec5d0f2c5068962c39751
[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 do_scan(void);
35 static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec);
36
37
38 /* Global variables */
39 static DEVICE *dev = NULL;
40 static B_DB *db;
41 static JCR *bjcr;                     /* jcr for bscan */
42 static BSR *bsr = NULL;
43 static char *wd = "/tmp";
44 static int verbose = 0;
45
46 #define CONFIG_FILE "bacula-sd.conf"
47 char *configfile;
48
49
50 static void usage()
51 {
52    fprintf(stderr, _(
53 "\nVersion: " VERSION " (" DATE ")\n\n"
54 "Usage: bcopy [-d debug_level] <input-archive> <output-archive>\n"
55 "       -b bootstrap      specify a bootstrap file\n"
56 "       -c <file>         specify configuration file\n"
57 "       -dnn              set debug level to nn\n"
58 "       -v                verbose\n"
59 "       -w dir            specify working directory (default /tmp)\n"
60 "       -?                print this message\n\n"));
61    exit(1);
62 }
63
64 int main (int argc, char *argv[])
65 {
66    int ch;
67
68    my_name_is(argc, argv, "bscan");
69    init_msg(NULL, NULL);
70
71    fprintf(stderr, "\n\nPlease don't use this program.\n\
72 It is currently under development and does not work.\n\n");
73
74    while ((ch = getopt(argc, argv, "b:c:d:mn:p:rsu:vw:?")) != -1) {
75       switch (ch) {
76          case 'b':
77             bsr = parse_bsr(NULL, optarg);
78             break;
79
80          case 'c':                    /* specify config file */
81             if (configfile != NULL) {
82                free(configfile);
83             }
84             configfile = bstrdup(optarg);
85             break;
86
87          case 'd':                    /* debug level */
88             debug_level = atoi(optarg);
89             if (debug_level <= 0)
90                debug_level = 1; 
91             break;
92
93          case 'v':
94             verbose++;
95             break;
96
97          case 'w':
98             wd = optarg;
99             break;
100
101          case '?':
102          default:
103             usage();
104
105       }  
106    }
107    argc -= optind;
108    argv += optind;
109
110    if (argc != 2) {
111       Pmsg0(0, _("Wrong number of arguments: \n"));
112       usage();
113    }
114
115    working_directory = wd;
116
117    if (configfile == NULL) {
118       configfile = bstrdup(CONFIG_FILE);
119    }
120
121    parse_config(configfile);
122
123    bjcr = setup_jcr("bcopy", argv[0], bsr);
124    dev = setup_to_access_device(bjcr, 0);   /* read device */
125    if (!dev) { 
126       exit(1);
127    }
128
129    do_copy();
130
131    free_jcr(bjcr);
132    return 0;
133 }
134   
135
136 static void do_copy()             
137 {
138    detach_jcr_from_device(dev, bjcr);
139
140    read_records(bjcr, dev, record_cb, mount_next_read_volume);
141    release_device(bjcr, dev);
142
143    term_dev(dev);
144 }
145
146 static void record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
147 {
148    JCR *mjcr;
149    char ec1[30];
150
151    if (list_records) {
152       Pmsg5(000, _("Record: SessId=%u SessTim=%u FileIndex=%d Stream=%d len=%u\n"),
153             rec->VolSessionId, rec->VolSessionTime, rec->FileIndex, 
154             rec->Stream, rec->data_len);
155    }
156    /* 
157     * Check for Start or End of Session Record 
158     *
159     */
160    if (rec->FileIndex < 0) {
161
162       if (verbose > 1) {
163          dump_label_record(dev, rec, 1);
164       }
165       switch (rec->FileIndex) {
166          case PRE_LABEL:
167             Pmsg0(000, "Volume is prelabeled. This volume cannot be copied.\n");
168             return;
169             break;
170          case VOL_LABEL:
171             Pmsg1(000, "VOL_LABEL: OK for Volume: %s\n", mr.VolumeName);
172             break;
173          case SOS_LABEL:
174             break;
175          case EOS_LABEL:
176             break;
177          case EOM_LABEL:
178             break;
179          case EOT_LABEL:              /* end of all tapes */
180             break;
181          default:
182             break;
183       }
184       return;
185    }
186
187    /*  Write record */
188
189    return;
190 }
191
192 /*
193  * Free the Job Control Record if no one is still using it.
194  *  Called from main free_jcr() routine in src/lib/jcr.c so
195  *  that we can do our Director specific cleanup of the jcr.
196  */
197 static void dird_free_jcr(JCR *jcr)
198 {
199    Dmsg0(200, "Start dird free_jcr\n");
200
201    if (jcr->file_bsock) {
202       Dmsg0(200, "Close File bsock\n");
203       bnet_close(jcr->file_bsock);
204    }
205    if (jcr->store_bsock) {
206       Dmsg0(200, "Close Store bsock\n");
207       bnet_close(jcr->store_bsock);
208    }
209    if (jcr->RestoreBootstrap) {
210       free(jcr->RestoreBootstrap);
211    }
212    Dmsg0(200, "End dird free_jcr\n");
213 }
214
215
216
217 /* 
218  * Create a JCR as if we are really starting the job
219  */
220 static JCR *create_jcr(JOB_DBR *jr, DEV_RECORD *rec, uint32_t JobId)
221 {
222    JCR *jobjcr;
223    /*
224     * Transfer as much as possible to the Job JCR. Most important is
225     *   the JobId and the ClientId.
226     */
227    jobjcr = new_jcr(sizeof(JCR), dird_free_jcr);
228    jobjcr->JobType = jr->Type;
229    jobjcr->JobLevel = jr->Level;
230    jobjcr->JobStatus = jr->JobStatus;
231    strcpy(jobjcr->Job, jr->Job);
232    jobjcr->JobId = JobId;      /* this is JobId on tape */
233    jobjcr->sched_time = jr->SchedTime;
234    jobjcr->start_time = jr->StartTime;
235    jobjcr->VolSessionId = rec->VolSessionId;
236    jobjcr->VolSessionTime = rec->VolSessionTime;
237    jobjcr->ClientId = jr->ClientId;
238    attach_jcr_to_device(dev, jobjcr);
239    return jobjcr;
240 }
241
242 /* Dummies to replace askdir.c */
243 int     dir_get_volume_info(JCR *jcr, int writing) { return 1;}
244 int     dir_find_next_appendable_volume(JCR *jcr) { return 1;}
245 int     dir_update_volume_info(JCR *jcr, VOLUME_CAT_INFO *vol, int relabel) { return 1; }
246 int     dir_create_jobmedia_record(JCR *jcr) { return 1; }
247 int     dir_ask_sysop_to_mount_next_volume(JCR *jcr, DEVICE *dev) { return 1; }
248 int     dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec) { return 1;}
249 int     dir_send_job_status(JCR *jcr) {return 1;}
250
251
252 int dir_ask_sysop_to_mount_volume(JCR *jcr, DEVICE *dev)
253 {
254    /*  
255     * We are at the end of reading a tape. Now, we simulate handling
256     *   the end of writing a tape by wiffling through the attached
257     *   jcrs creating jobmedia records.
258     */
259    Dmsg1(100, "Walk attached jcrs. Volume=%s\n", dev->VolCatInfo.VolCatName);
260    for (JCR *mjcr=NULL; (mjcr=next_attached_jcr(dev, mjcr)); ) {
261       if (verbose) {
262          Pmsg1(000, "create JobMedia for Job %s\n", mjcr->Job);
263       }
264       if (dev->state & ST_TAPE) {
265          mjcr->EndBlock = dev->block_num;
266          mjcr->EndFile = dev->file;
267       } else {
268          mjcr->EndBlock = (uint32_t)dev->file_addr;
269          mjcr->StartBlock = (uint32_t)(dev->file_addr >> 32);
270       }
271       if (!create_jobmedia_record(db, mjcr)) {
272          Pmsg2(000, _("Could not create JobMedia record for Volume=%s Job=%s\n"),
273             dev->VolCatInfo.VolCatName, mjcr->Job);
274       }
275    }
276
277    fprintf(stderr, "Mount Volume %s on device %s and press return when ready: ",
278       jcr->VolumeName, dev_name(dev));
279    getchar();   
280    return 1;
281 }