]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/butil.c
backport code from master
[bacula/bacula] / bacula / src / stored / butil.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2010 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version three of the GNU Affero General Public
10    License as published by the Free Software Foundation and included
11    in the file LICENSE.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU Affero General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23    Bacula® is a registered trademark of Kern Sibbald.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28 /*
29  *
30  *  Utility routines for "tool" programs such as bscan, bls,
31  *    bextract, ...  Some routines also used by Bacula.
32  *
33  *    Kern Sibbald, MM
34  *
35  *  Normally nothing in this file is called by the Storage
36  *    daemon because we interact more directly with the user
37  *    i.e. printf, ...
38  *
39  *   Version $Id$
40  */
41
42 #include "bacula.h"
43 #include "stored.h"
44
45 /* Forward referenced functions */
46 static DCR *setup_to_access_device(JCR *jcr, char *dev_name, const char *VolumeName, int mode);
47 static DEVRES *find_device_res(char *device_name, int mode);
48 static void my_free_jcr(JCR *jcr);
49
50 /* Imported variables -- eliminate some day */
51 extern char *configfile;
52
53 #ifdef DEBUG
54 char *rec_state_bits_to_str(DEV_RECORD *rec)
55 {
56    static char buf[200];
57    buf[0] = 0;
58    if (rec->state_bits & REC_NO_HEADER) {
59       strcat(buf, _("Nohdr,"));
60    }
61    if (is_partial_record(rec)) {
62       strcat(buf, _("partial,"));
63    }
64    if (rec->state_bits & REC_BLOCK_EMPTY) {
65       strcat(buf, _("empty,"));
66    }
67    if (rec->state_bits & REC_NO_MATCH) {
68       strcat(buf, _("Nomatch,"));
69    }
70    if (rec->state_bits & REC_CONTINUATION) {
71       strcat(buf, _("cont,"));
72    }
73    if (buf[0]) {
74       buf[strlen(buf)-1] = 0;
75    }
76    return buf;
77 }
78 #endif
79
80 /*
81  * Setup a "daemon" JCR for the various standalone
82  *  tools (e.g. bls, bextract, bscan, ...)
83  */
84 JCR *setup_jcr(const char *name, char *dev_name, BSR *bsr,
85                const char *VolumeName, int mode)
86 {
87    DCR *dcr;
88    JCR *jcr = new_jcr(sizeof(JCR), my_free_jcr);
89    jcr->bsr = bsr;
90    jcr->VolSessionId = 1;
91    jcr->VolSessionTime = (uint32_t)time(NULL);
92    jcr->NumReadVolumes = 0;
93    jcr->NumWriteVolumes = 0;
94    jcr->JobId = 0;
95    jcr->setJobType(JT_CONSOLE);
96    jcr->setJobLevel(L_FULL);
97    jcr->JobStatus = JS_Terminated;
98    jcr->where = bstrdup("");
99    jcr->job_name = get_pool_memory(PM_FNAME);
100    pm_strcpy(jcr->job_name, "Dummy.Job.Name");
101    jcr->client_name = get_pool_memory(PM_FNAME);
102    pm_strcpy(jcr->client_name, "Dummy.Client.Name");
103    bstrncpy(jcr->Job, name, sizeof(jcr->Job));
104    jcr->fileset_name = get_pool_memory(PM_FNAME);
105    pm_strcpy(jcr->fileset_name, "Dummy.fileset.name");
106    jcr->fileset_md5 = get_pool_memory(PM_FNAME);
107    pm_strcpy(jcr->fileset_md5, "Dummy.fileset.md5");
108    jcr->comment = get_pool_memory(PM_MESSAGE);
109    *jcr->comment = '\0';
110    init_autochangers();
111    create_volume_lists();
112
113    dcr = setup_to_access_device(jcr, dev_name, VolumeName, mode);
114    if (!dcr) {
115       return NULL;
116    }
117    if (!bsr && VolumeName) {
118       bstrncpy(dcr->VolumeName, VolumeName, sizeof(dcr->VolumeName));
119    }
120    bstrncpy(dcr->pool_name, "Default", sizeof(dcr->pool_name));
121    bstrncpy(dcr->pool_type, "Backup", sizeof(dcr->pool_type));
122    return jcr;
123 }
124
125 /*
126  * Setup device, jcr, and prepare to access device.
127  *   If the caller wants read access, acquire the device, otherwise,
128  *     the caller will do it.
129  */
130 static DCR *setup_to_access_device(JCR *jcr, char *dev_name, 
131               const char *VolumeName, int mode)
132 {
133    DEVICE *dev;
134    char *p;
135    DEVRES *device;
136    DCR *dcr;
137    char VolName[MAX_NAME_LENGTH];
138
139    init_reservations_lock();
140
141    /*
142     * If no volume name already given and no bsr, and it is a file,
143     * try getting name from Filename
144     */
145    if (VolumeName) {
146       bstrncpy(VolName, VolumeName, sizeof(VolName));
147       if (strlen(VolumeName) >= MAX_NAME_LENGTH) {
148          Jmsg0(jcr, M_ERROR, 0, _("Volume name or names is too long. Please use a .bsr file.\n"));
149       }
150    } else {
151       VolName[0] = 0;
152    }
153    if (!jcr->bsr && VolName[0] == 0) {
154       if (strncmp(dev_name, "/dev/", 5) != 0) {
155          /* Try stripping file part */
156          p = dev_name + strlen(dev_name);
157
158          while (p >= dev_name && !IsPathSeparator(*p))
159             p--;
160          if (IsPathSeparator(*p)) {
161             bstrncpy(VolName, p+1, sizeof(VolName));
162             *p = 0;
163          }
164       }
165    }
166
167    if ((device=find_device_res(dev_name, mode)) == NULL) {
168       Jmsg2(jcr, M_FATAL, 0, _("Cannot find device \"%s\" in config file %s.\n"),
169            dev_name, configfile);
170       return NULL;
171    }
172
173    dev = init_dev(jcr, device);
174    if (!dev) {
175       Jmsg1(jcr, M_FATAL, 0, _("Cannot init device %s\n"), dev_name);
176       return NULL;
177    }
178    device->dev = dev;
179    jcr->dcr = dcr = new_dcr(jcr, NULL, dev);
180    if (VolName[0]) {
181       bstrncpy(dcr->VolumeName, VolName, sizeof(dcr->VolumeName));
182    }
183    bstrncpy(dcr->dev_name, device->device_name, sizeof(dcr->dev_name));
184
185    create_restore_volume_list(jcr);
186
187    if (mode) {                        /* read only access? */
188       Dmsg0(100, "Acquire device for read\n");
189       if (!acquire_device_for_read(dcr)) {
190          return NULL;
191       }
192       jcr->read_dcr = dcr;
193    } else {
194       if (!first_open_device(dcr)) {
195          Jmsg1(jcr, M_FATAL, 0, _("Cannot open %s\n"), dev->print_name());
196          return NULL;
197       }
198       jcr->dcr = dcr;        /* write dcr */
199    }
200    return dcr;
201 }
202
203
204 /*
205  * Called here when freeing JCR so that we can get rid
206  *  of "daemon" specific memory allocated.
207  */
208 static void my_free_jcr(JCR *jcr)
209 {
210    if (jcr->job_name) {
211       free_pool_memory(jcr->job_name);
212       jcr->job_name = NULL;
213    }
214    if (jcr->client_name) {
215       free_pool_memory(jcr->client_name);
216       jcr->client_name = NULL;
217    }
218    if (jcr->fileset_name) {
219       free_pool_memory(jcr->fileset_name);
220       jcr->fileset_name = NULL;
221    }
222    if (jcr->fileset_md5) {
223       free_pool_memory(jcr->fileset_md5);
224       jcr->fileset_md5 = NULL;
225    }
226    if (jcr->comment) {
227       free_pool_memory(jcr->comment);
228       jcr->comment = NULL;
229    }
230    if (jcr->VolList) {
231       free_restore_volume_list(jcr);
232    }
233    if (jcr->dcr) {
234       free_dcr(jcr->dcr);
235       jcr->dcr = NULL;
236    }
237    return;
238 }
239
240
241 /*
242  * Search for device resource that corresponds to
243  * device name on command line (or default).
244  *
245  * Returns: NULL on failure
246  *          Device resource pointer on success
247  */
248 static DEVRES *find_device_res(char *device_name, int read_access)
249 {
250    bool found = false;
251    DEVRES *device;
252
253    Dmsg0(900, "Enter find_device_res\n");
254    LockRes();
255    foreach_res(device, R_DEVICE) {
256       Dmsg2(900, "Compare %s and %s\n", device->device_name, device_name);
257       if (strcmp(device->device_name, device_name) == 0) {
258          found = true;
259          break;
260       }
261    }
262    if (!found) {
263       /* Search for name of Device resource rather than archive name */
264       if (device_name[0] == '"') {
265          int len = strlen(device_name);
266          bstrncpy(device_name, device_name+1, len+1);
267          len--;
268          if (len > 0) {
269             device_name[len-1] = 0;   /* zap trailing " */
270          }
271       }
272       foreach_res(device, R_DEVICE) {
273          Dmsg2(900, "Compare %s and %s\n", device->hdr.name, device_name);
274          if (strcmp(device->hdr.name, device_name) == 0) {
275             found = true;
276             break;
277          }
278       }
279    }
280    UnlockRes();
281    if (!found) {
282       Pmsg2(0, _("Could not find device \"%s\" in config file %s.\n"), device_name,
283             configfile);
284       return NULL;
285    }
286    if (read_access) {
287       Pmsg1(0, _("Using device: \"%s\" for reading.\n"), device_name);
288    }
289    else {
290       Pmsg1(0, _("Using device: \"%s\" for writing.\n"), device_name);
291    }
292    return device;
293 }
294
295
296 /*
297  * Device got an error, attempt to analyse it
298  */
299 void display_tape_error_status(JCR *jcr, DEVICE *dev)
300 {
301    uint32_t status;
302
303    status = status_dev(dev);
304    Dmsg1(20, "Device status: %x\n", status);
305    if (status & BMT_EOD)
306       Jmsg(jcr, M_ERROR, 0, _("Unexpected End of Data\n"));
307    else if (status & BMT_EOT)
308       Jmsg(jcr, M_ERROR, 0, _("Unexpected End of Tape\n"));
309    else if (status & BMT_EOF)
310       Jmsg(jcr, M_ERROR, 0, _("Unexpected End of File\n"));
311    else if (status & BMT_DR_OPEN)
312       Jmsg(jcr, M_ERROR, 0, _("Tape Door is Open\n"));
313    else if (!(status & BMT_ONLINE))
314       Jmsg(jcr, M_ERROR, 0, _("Unexpected Tape is Off-line\n"));
315 }