3 * Utility routines for "tool" programs such as bscan, bls,
4 * bextract, ... Some routines also used by Bacula.
8 * Normally nothing in this file is called by the Storage
9 * daemon because we interact more directly with the user
15 Bacula® - The Network Backup Solution
17 Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
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.
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.
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
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.
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);
50 /* Imported variables -- eliminate some day */
51 extern char *configfile;
54 char *rec_state_to_str(DEV_RECORD *rec)
58 if (rec->state & REC_NO_HEADER) {
59 strcat(buf, _("Nohdr,"));
61 if (is_partial_record(rec)) {
62 strcat(buf, _("partial,"));
64 if (rec->state & REC_BLOCK_EMPTY) {
65 strcat(buf, _("empty,"));
67 if (rec->state & REC_NO_MATCH) {
68 strcat(buf, _("Nomatch,"));
70 if (rec->state & REC_CONTINUATION) {
71 strcat(buf, _("cont,"));
74 buf[strlen(buf)-1] = 0;
81 * Setup a "daemon" JCR for the various standalone
82 * tools (e.g. bls, bextract, bscan, ...)
84 JCR *setup_jcr(const char *name, char *dev_name, BSR *bsr,
85 const char *VolumeName, int mode)
88 JCR *jcr = new_jcr(sizeof(JCR), my_free_jcr);
90 jcr->VolSessionId = 1;
91 jcr->VolSessionTime = (uint32_t)time(NULL);
94 jcr->JobType = JT_CONSOLE;
95 jcr->JobLevel = L_FULL;
96 jcr->JobStatus = JS_Terminated;
97 jcr->where = bstrdup("");
98 jcr->job_name = get_pool_memory(PM_FNAME);
99 pm_strcpy(jcr->job_name, "Dummy.Job.Name");
100 jcr->client_name = get_pool_memory(PM_FNAME);
101 pm_strcpy(jcr->client_name, "Dummy.Client.Name");
102 bstrncpy(jcr->Job, name, sizeof(jcr->Job));
103 jcr->fileset_name = get_pool_memory(PM_FNAME);
104 pm_strcpy(jcr->fileset_name, "Dummy.fileset.name");
105 jcr->fileset_md5 = get_pool_memory(PM_FNAME);
106 pm_strcpy(jcr->fileset_md5, "Dummy.fileset.md5");
109 create_volume_list();
111 dcr = setup_to_access_device(jcr, dev_name, VolumeName, mode);
115 if (!bsr && VolumeName) {
116 bstrncpy(dcr->VolumeName, VolumeName, sizeof(dcr->VolumeName));
118 bstrncpy(dcr->pool_name, "Default", sizeof(dcr->pool_name));
119 bstrncpy(dcr->pool_type, "Backup", sizeof(dcr->pool_type));
124 * Setup device, jcr, and prepare to access device.
125 * If the caller wants read access, acquire the device, otherwise,
126 * the caller will do it.
128 static DCR *setup_to_access_device(JCR *jcr, char *dev_name,
129 const char *VolumeName, int mode)
135 char VolName[MAX_NAME_LENGTH];
137 init_reservations_lock();
140 * If no volume name already given and no bsr, and it is a file,
141 * try getting name from Filename
144 bstrncpy(VolName, VolumeName, sizeof(VolName));
145 if (strlen(VolumeName) >= MAX_NAME_LENGTH) {
146 Jmsg0(jcr, M_ERROR, 0, _("Volume name or names is too long. Please use a .bsr file.\n"));
151 if (!jcr->bsr && VolName[0] == 0) {
152 if (strncmp(dev_name, "/dev/", 5) != 0) {
153 /* Try stripping file part */
154 p = dev_name + strlen(dev_name);
156 while (p >= dev_name && !IsPathSeparator(*p))
158 if (IsPathSeparator(*p)) {
159 bstrncpy(VolName, p+1, sizeof(VolName));
165 if ((device=find_device_res(dev_name, mode)) == NULL) {
166 Jmsg2(jcr, M_FATAL, 0, _("Cannot find device \"%s\" in config file %s.\n"),
167 dev_name, configfile);
171 dev = init_dev(jcr, device);
173 Jmsg1(jcr, M_FATAL, 0, _("Cannot init device %s\n"), dev_name);
177 dcr = new_dcr(jcr, dev);
180 bstrncpy(dcr->VolumeName, VolName, sizeof(dcr->VolumeName));
182 bstrncpy(dcr->dev_name, device->device_name, sizeof(dcr->dev_name));
184 create_restore_volume_list(jcr);
186 if (mode) { /* read only access? */
187 Dmsg0(100, "Acquire device for read\n");
188 if (!acquire_device_for_read(dcr)) {
193 if (!first_open_device(dcr)) {
194 Jmsg1(jcr, M_FATAL, 0, _("Cannot open %s\n"), dev->print_name());
197 jcr->dcr = dcr; /* write dcr */
204 * Called here when freeing JCR so that we can get rid
205 * of "daemon" specific memory allocated.
207 static void my_free_jcr(JCR *jcr)
210 free_pool_memory(jcr->job_name);
211 jcr->job_name = NULL;
213 if (jcr->client_name) {
214 free_pool_memory(jcr->client_name);
215 jcr->client_name = NULL;
217 if (jcr->fileset_name) {
218 free_pool_memory(jcr->fileset_name);
219 jcr->fileset_name = NULL;
221 if (jcr->fileset_md5) {
222 free_pool_memory(jcr->fileset_md5);
223 jcr->fileset_md5 = NULL;
226 free_restore_volume_list(jcr);
237 * Search for device resource that corresponds to
238 * device name on command line (or default).
240 * Returns: NULL on failure
241 * Device resource pointer on success
243 static DEVRES *find_device_res(char *device_name, int read_access)
248 Dmsg0(900, "Enter find_device_res\n");
250 foreach_res(device, R_DEVICE) {
251 Dmsg2(900, "Compare %s and %s\n", device->device_name, device_name);
252 if (strcmp(device->device_name, device_name) == 0) {
258 /* Search for name of Device resource rather than archive name */
259 if (device_name[0] == '"') {
260 int len = strlen(device_name);
261 bstrncpy(device_name, device_name+1, len+1);
264 device_name[len-1] = 0; /* zap trailing " */
267 foreach_res(device, R_DEVICE) {
268 Dmsg2(900, "Compare %s and %s\n", device->hdr.name, device_name);
269 if (strcmp(device->hdr.name, device_name) == 0) {
277 Pmsg2(0, _("Could not find device \"%s\" in config file %s.\n"), device_name,
282 Pmsg1(0, _("Using device: \"%s\" for reading.\n"), device_name);
285 Pmsg1(0, _("Using device: \"%s\" for writing.\n"), device_name);
292 * Device got an error, attempt to analyse it
294 void display_tape_error_status(JCR *jcr, DEVICE *dev)
298 status = status_dev(dev);
299 Dmsg1(20, "Device status: %x\n", status);
300 if (status & BMT_EOD)
301 Jmsg(jcr, M_ERROR, 0, _("Unexpected End of Data\n"));
302 else if (status & BMT_EOT)
303 Jmsg(jcr, M_ERROR, 0, _("Unexpected End of Tape\n"));
304 else if (status & BMT_EOF)
305 Jmsg(jcr, M_ERROR, 0, _("Unexpected End of File\n"));
306 else if (status & BMT_DR_OPEN)
307 Jmsg(jcr, M_ERROR, 0, _("Tape Door is Open\n"));
308 else if (!(status & BMT_ONLINE))
309 Jmsg(jcr, M_ERROR, 0, _("Unexpected Tape is Off-line\n"));