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);
92 jcr->NumReadVolumes = 0;
93 jcr->NumWriteVolumes = 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");
110 create_volume_list();
112 dcr = setup_to_access_device(jcr, dev_name, VolumeName, mode);
116 if (!bsr && VolumeName) {
117 bstrncpy(dcr->VolumeName, VolumeName, sizeof(dcr->VolumeName));
119 bstrncpy(dcr->pool_name, "Default", sizeof(dcr->pool_name));
120 bstrncpy(dcr->pool_type, "Backup", sizeof(dcr->pool_type));
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.
129 static DCR *setup_to_access_device(JCR *jcr, char *dev_name,
130 const char *VolumeName, int mode)
136 char VolName[MAX_NAME_LENGTH];
138 init_reservations_lock();
141 * If no volume name already given and no bsr, and it is a file,
142 * try getting name from Filename
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"));
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);
157 while (p >= dev_name && !IsPathSeparator(*p))
159 if (IsPathSeparator(*p)) {
160 bstrncpy(VolName, p+1, sizeof(VolName));
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);
172 dev = init_dev(jcr, device);
174 Jmsg1(jcr, M_FATAL, 0, _("Cannot init device %s\n"), dev_name);
178 dcr = new_dcr(jcr, dev);
181 bstrncpy(dcr->VolumeName, VolName, sizeof(dcr->VolumeName));
183 bstrncpy(dcr->dev_name, device->device_name, sizeof(dcr->dev_name));
185 create_restore_volume_list(jcr);
187 if (mode) { /* read only access? */
188 Dmsg0(100, "Acquire device for read\n");
189 if (!acquire_device_for_read(dcr)) {
194 if (!first_open_device(dcr)) {
195 Jmsg1(jcr, M_FATAL, 0, _("Cannot open %s\n"), dev->print_name());
198 jcr->dcr = dcr; /* write dcr */
205 * Called here when freeing JCR so that we can get rid
206 * of "daemon" specific memory allocated.
208 static void my_free_jcr(JCR *jcr)
211 free_pool_memory(jcr->job_name);
212 jcr->job_name = NULL;
214 if (jcr->client_name) {
215 free_pool_memory(jcr->client_name);
216 jcr->client_name = NULL;
218 if (jcr->fileset_name) {
219 free_pool_memory(jcr->fileset_name);
220 jcr->fileset_name = NULL;
222 if (jcr->fileset_md5) {
223 free_pool_memory(jcr->fileset_md5);
224 jcr->fileset_md5 = NULL;
227 free_restore_volume_list(jcr);
238 * Search for device resource that corresponds to
239 * device name on command line (or default).
241 * Returns: NULL on failure
242 * Device resource pointer on success
244 static DEVRES *find_device_res(char *device_name, int read_access)
249 Dmsg0(900, "Enter find_device_res\n");
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) {
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);
265 device_name[len-1] = 0; /* zap trailing " */
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) {
278 Pmsg2(0, _("Could not find device \"%s\" in config file %s.\n"), device_name,
283 Pmsg1(0, _("Using device: \"%s\" for reading.\n"), device_name);
286 Pmsg1(0, _("Using device: \"%s\" for writing.\n"), device_name);
293 * Device got an error, attempt to analyse it
295 void display_tape_error_status(JCR *jcr, DEVICE *dev)
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"));