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