]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/butil.c
Backport from BEE
[bacula/bacula] / bacula / src / stored / butil.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2014 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from many
7    others, a complete list can be found in the file AUTHORS.
8
9    You may use this file and others of this release according to the
10    license defined in the LICENSE file, which includes the Affero General
11    Public License, v3.0 ("AGPLv3") and some additional permissions and
12    terms pursuant to its AGPLv3 Section 7.
13
14    Bacula® is a registered trademark of Kern Sibbald.
15 */
16 /*
17  *
18  *  Utility routines for "tool" programs such as bscan, bls,
19  *    bextract, ...  Some routines also used by Bacula.
20  *
21  *    Kern Sibbald, MM
22  *
23  *  Normally nothing in this file is called by the Storage
24  *    daemon because we interact more directly with the user
25  *    i.e. printf, ...
26  *
27  */
28
29 #include "bacula.h"
30 #include "stored.h"
31
32 /* Forward referenced functions */
33 static DCR *setup_to_access_device(JCR *jcr, char *dev_name, const char *VolumeName, bool writing);
34 static DEVRES *find_device_res(char *device_name, bool writing);
35 static void my_free_jcr(JCR *jcr);
36
37 /* Imported variables -- eliminate some day */
38 extern char *configfile;
39
40 #ifdef DEBUG
41 char *rec_state_bits_to_str(DEV_RECORD *rec)
42 {
43    static char buf[200];
44    buf[0] = 0;
45    if (rec->state_bits & REC_NO_HEADER) {
46       strcat(buf, _("Nohdr,"));
47    }
48    if (is_partial_record(rec)) {
49       strcat(buf, _("partial,"));
50    }
51    if (rec->state_bits & REC_BLOCK_EMPTY) {
52       strcat(buf, _("empty,"));
53    }
54    if (rec->state_bits & REC_NO_MATCH) {
55       strcat(buf, _("Nomatch,"));
56    }
57    if (rec->state_bits & REC_CONTINUATION) {
58       strcat(buf, _("cont,"));
59    }
60    if (buf[0]) {
61       buf[strlen(buf)-1] = 0;
62    }
63    return buf;
64 }
65 #endif
66
67 /*
68  * Setup a pointer to my resource me
69  */
70 void setup_me()
71 {
72    LockRes();
73    me = (STORES *)GetNextRes(R_STORAGE, NULL);
74    if (!me) {
75       UnlockRes();
76       Emsg1(M_ERROR_TERM, 0, _("No Storage resource defined in %s. Cannot continue.\n"),
77          configfile);
78    }
79    UnlockRes();
80 }
81
82 /*
83  * Setup a "daemon" JCR for the various standalone
84  *  tools (e.g. bls, bextract, bscan, ...)
85  */
86 JCR *setup_jcr(const char *name, char *dev_name, BSR *bsr,
87                const char *VolumeName, bool writing)
88 {
89    DCR *dcr;
90    JCR *jcr = new_jcr(sizeof(JCR), my_free_jcr);
91    jcr->bsr = bsr;
92    jcr->VolSessionId = 1;
93    jcr->VolSessionTime = (uint32_t)time(NULL);
94    jcr->NumReadVolumes = 0;
95    jcr->NumWriteVolumes = 0;
96    jcr->JobId = 0;
97    jcr->setJobType(JT_CONSOLE);
98    jcr->setJobLevel(L_FULL);
99    jcr->JobStatus = JS_Terminated;
100    jcr->where = bstrdup("");
101    jcr->job_name = get_pool_memory(PM_FNAME);
102    pm_strcpy(jcr->job_name, "Dummy.Job.Name");
103    jcr->client_name = get_pool_memory(PM_FNAME);
104    pm_strcpy(jcr->client_name, "Dummy.Client.Name");
105    bstrncpy(jcr->Job, name, sizeof(jcr->Job));
106    jcr->fileset_name = get_pool_memory(PM_FNAME);
107    pm_strcpy(jcr->fileset_name, "Dummy.fileset.name");
108    jcr->fileset_md5 = get_pool_memory(PM_FNAME);
109    pm_strcpy(jcr->fileset_md5, "Dummy.fileset.md5");
110    init_autochangers();
111    create_volume_lists();
112
113    dcr = setup_to_access_device(jcr, dev_name, VolumeName, writing);
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, bool writing)
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, writing)) == 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, writing);
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 (!writing) {                      /* 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, bool write_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 (write_access) {
287       Pmsg1(0, _("Using device: \"%s\" for writing.\n"), device_name);
288    } else {
289       Pmsg1(0, _("Using device: \"%s\" for reading.\n"), device_name);
290    }
291    return device;
292 }
293
294
295 /*
296  * Device got an error, attempt to analyse it
297  */
298 void display_tape_error_status(JCR *jcr, DEVICE *dev)
299 {
300    uint32_t status;
301
302    status = status_dev(dev);
303    Dmsg1(20, "Device status: %x\n", status);
304    if (status & BMT_EOD)
305       Jmsg(jcr, M_ERROR, 0, _("Unexpected End of Data\n"));
306    else if (status & BMT_EOT)
307       Jmsg(jcr, M_ERROR, 0, _("Unexpected End of Tape\n"));
308    else if (status & BMT_EOF)
309       Jmsg(jcr, M_ERROR, 0, _("Unexpected End of File\n"));
310    else if (status & BMT_DR_OPEN)
311       Jmsg(jcr, M_ERROR, 0, _("Tape Door is Open\n"));
312    else if (!(status & BMT_ONLINE))
313       Jmsg(jcr, M_ERROR, 0, _("Unexpected Tape is Off-line\n"));
314 }