]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/butil.c
kes Clarify some stored/acquire messages to indicate if the
[bacula/bacula] / bacula / src / stored / butil.c
1 /*
2  *
3  *  Utility routines for "tool" programs such as bscan, bls,
4  *    bextract, ...  Some routines also used by Bacula.
5  *
6  *    Kern Sibbald, MM
7  *
8  *  Normally nothing in this file is called by the Storage
9  *    daemon because we interact more directly with the user
10  *    i.e. printf, ...
11  *
12  *   Version $Id$
13  */
14 /*
15    Bacula® - The Network Backup Solution
16
17    Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
18
19    The main author of Bacula is Kern Sibbald, with contributions from
20    many others, a complete list can be found in the file AUTHORS.
21    This program is Free Software; you can redistribute it and/or
22    modify it under the terms of version two of the GNU General Public
23    License as published by the Free Software Foundation plus additions
24    that are listed in the file LICENSE.
25
26    This program is distributed in the hope that it will be useful, but
27    WITHOUT ANY WARRANTY; without even the implied warranty of
28    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
29    General Public License for more details.
30
31    You should have received a copy of the GNU General Public License
32    along with this program; if not, write to the Free Software
33    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
34    02110-1301, USA.
35
36    Bacula® is a registered trademark of John Walker.
37    The licensor of Bacula is the Free Software Foundation Europe
38    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
39    Switzerland, email:ftf@fsfeurope.org.
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_to_str(DEV_RECORD *rec)
55 {
56    static char buf[200];
57    buf[0] = 0;
58    if (rec->state & REC_NO_HEADER) {
59       strcat(buf, _("Nohdr,"));
60    }
61    if (is_partial_record(rec)) {
62       strcat(buf, _("partial,"));
63    }
64    if (rec->state & REC_BLOCK_EMPTY) {
65       strcat(buf, _("empty,"));
66    }
67    if (rec->state & REC_NO_MATCH) {
68       strcat(buf, _("Nomatch,"));
69    }
70    if (rec->state & 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->JobType = JT_CONSOLE;
96    jcr->JobLevel = 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
109    init_autochangers();
110    create_volume_list();
111
112    dcr = setup_to_access_device(jcr, dev_name, VolumeName, mode);
113    if (!dcr) {
114       return NULL;
115    }
116    if (!bsr && VolumeName) {
117       bstrncpy(dcr->VolumeName, VolumeName, sizeof(dcr->VolumeName));
118    }
119    bstrncpy(dcr->pool_name, "Default", sizeof(dcr->pool_name));
120    bstrncpy(dcr->pool_type, "Backup", sizeof(dcr->pool_type));
121    return jcr;
122 }
123
124 /*
125  * Setup device, jcr, and prepare to access device.
126  *   If the caller wants read access, acquire the device, otherwise,
127  *     the caller will do it.
128  */
129 static DCR *setup_to_access_device(JCR *jcr, char *dev_name, 
130               const char *VolumeName, int mode)
131 {
132    DEVICE *dev;
133    char *p;
134    DEVRES *device;
135    DCR *dcr;
136    char VolName[MAX_NAME_LENGTH];
137
138    init_reservations_lock();
139
140    /*
141     * If no volume name already given and no bsr, and it is a file,
142     * try getting name from Filename
143     */
144    if (VolumeName) {
145       bstrncpy(VolName, VolumeName, sizeof(VolName));
146       if (strlen(VolumeName) >= MAX_NAME_LENGTH) {
147          Jmsg0(jcr, M_ERROR, 0, _("Volume name or names is too long. Please use a .bsr file.\n"));
148       }
149    } else {
150       VolName[0] = 0;
151    }
152    if (!jcr->bsr && VolName[0] == 0) {
153       if (strncmp(dev_name, "/dev/", 5) != 0) {
154          /* Try stripping file part */
155          p = dev_name + strlen(dev_name);
156
157          while (p >= dev_name && !IsPathSeparator(*p))
158             p--;
159          if (IsPathSeparator(*p)) {
160             bstrncpy(VolName, p+1, sizeof(VolName));
161             *p = 0;
162          }
163       }
164    }
165
166    if ((device=find_device_res(dev_name, mode)) == NULL) {
167       Jmsg2(jcr, M_FATAL, 0, _("Cannot find device \"%s\" in config file %s.\n"),
168            dev_name, configfile);
169       return NULL;
170    }
171
172    dev = init_dev(jcr, device);
173    if (!dev) {
174       Jmsg1(jcr, M_FATAL, 0, _("Cannot init device %s\n"), dev_name);
175       return NULL;
176    }
177    device->dev = dev;
178    dcr = new_dcr(jcr, dev);
179    jcr->dcr = dcr;
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->VolList) {
227       free_restore_volume_list(jcr);
228    }
229    if (jcr->dcr) {
230       free_dcr(jcr->dcr);
231       jcr->dcr = NULL;
232    }
233    return;
234 }
235
236
237 /*
238  * Search for device resource that corresponds to
239  * device name on command line (or default).
240  *
241  * Returns: NULL on failure
242  *          Device resource pointer on success
243  */
244 static DEVRES *find_device_res(char *device_name, int read_access)
245 {
246    bool found = false;
247    DEVRES *device;
248
249    Dmsg0(900, "Enter find_device_res\n");
250    LockRes();
251    foreach_res(device, R_DEVICE) {
252       Dmsg2(900, "Compare %s and %s\n", device->device_name, device_name);
253       if (strcmp(device->device_name, device_name) == 0) {
254          found = true;
255          break;
256       }
257    }
258    if (!found) {
259       /* Search for name of Device resource rather than archive name */
260       if (device_name[0] == '"') {
261          int len = strlen(device_name);
262          bstrncpy(device_name, device_name+1, len+1);
263          len--;
264          if (len > 0) {
265             device_name[len-1] = 0;   /* zap trailing " */
266          }
267       }
268       foreach_res(device, R_DEVICE) {
269          Dmsg2(900, "Compare %s and %s\n", device->hdr.name, device_name);
270          if (strcmp(device->hdr.name, device_name) == 0) {
271             found = true;
272             break;
273          }
274       }
275    }
276    UnlockRes();
277    if (!found) {
278       Pmsg2(0, _("Could not find device \"%s\" in config file %s.\n"), device_name,
279             configfile);
280       return NULL;
281    }
282    if (read_access) {
283       Pmsg1(0, _("Using device: \"%s\" for reading.\n"), device_name);
284    }
285    else {
286       Pmsg1(0, _("Using device: \"%s\" for writing.\n"), device_name);
287    }
288    return device;
289 }
290
291
292 /*
293  * Device got an error, attempt to analyse it
294  */
295 void display_tape_error_status(JCR *jcr, DEVICE *dev)
296 {
297    uint32_t status;
298
299    status = status_dev(dev);
300    Dmsg1(20, "Device status: %x\n", status);
301    if (status & BMT_EOD)
302       Jmsg(jcr, M_ERROR, 0, _("Unexpected End of Data\n"));
303    else if (status & BMT_EOT)
304       Jmsg(jcr, M_ERROR, 0, _("Unexpected End of Tape\n"));
305    else if (status & BMT_EOF)
306       Jmsg(jcr, M_ERROR, 0, _("Unexpected End of File\n"));
307    else if (status & BMT_DR_OPEN)
308       Jmsg(jcr, M_ERROR, 0, _("Tape Door is Open\n"));
309    else if (!(status & BMT_ONLINE))
310       Jmsg(jcr, M_ERROR, 0, _("Unexpected Tape is Off-line\n"));
311 }