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 Copyright (C) 2000-2005 Kern Sibbald
17 This program is free software; you can redistribute it and/or
18 modify it under the terms of the GNU General Public License
19 version 2 as amended with additional clauses defined in the
20 file LICENSE in the main source directory.
22 This program is distributed in the hope that it will be useful,
23 but WITHOUT ANY WARRANTY; without even the implied warranty of
24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 the file LICENSE for additional details.
32 /* Forward referenced functions */
33 static DCR *setup_to_access_device(JCR *jcr, char *dev_name, const char *VolumeName, int mode);
34 static DEVRES *find_device_res(char *device_name, int mode);
35 static void my_free_jcr(JCR *jcr);
37 /* Imported variables -- eliminate some day */
38 extern char *configfile;
41 char *rec_state_to_str(DEV_RECORD *rec)
45 if (rec->state & REC_NO_HEADER) {
46 strcat(buf, _("Nohdr,"));
48 if (is_partial_record(rec)) {
49 strcat(buf, _("partial,"));
51 if (rec->state & REC_BLOCK_EMPTY) {
52 strcat(buf, _("empty,"));
54 if (rec->state & REC_NO_MATCH) {
55 strcat(buf, _("Nomatch,"));
57 if (rec->state & REC_CONTINUATION) {
58 strcat(buf, _("cont,"));
61 buf[strlen(buf)-1] = 0;
68 * Setup a "daemon" JCR for the various standalone
69 * tools (e.g. bls, bextract, bscan, ...)
71 JCR *setup_jcr(const char *name, char *dev_name, BSR *bsr,
72 const char *VolumeName, int mode)
75 JCR *jcr = new_jcr(sizeof(JCR), my_free_jcr);
77 jcr->VolSessionId = 1;
78 jcr->VolSessionTime = (uint32_t)time(NULL);
81 jcr->JobType = JT_CONSOLE;
82 jcr->JobLevel = L_FULL;
83 jcr->JobStatus = JS_Terminated;
84 jcr->where = bstrdup("");
85 jcr->job_name = get_pool_memory(PM_FNAME);
86 pm_strcpy(jcr->job_name, "Dummy.Job.Name");
87 jcr->client_name = get_pool_memory(PM_FNAME);
88 pm_strcpy(jcr->client_name, "Dummy.Client.Name");
89 bstrncpy(jcr->Job, name, sizeof(jcr->Job));
90 jcr->fileset_name = get_pool_memory(PM_FNAME);
91 pm_strcpy(jcr->fileset_name, "Dummy.fileset.name");
92 jcr->fileset_md5 = get_pool_memory(PM_FNAME);
93 pm_strcpy(jcr->fileset_md5, "Dummy.fileset.md5");
97 dcr = setup_to_access_device(jcr, dev_name, VolumeName, mode);
101 if (!bsr && VolumeName) {
102 bstrncpy(dcr->VolumeName, VolumeName, sizeof(dcr->VolumeName));
104 bstrncpy(dcr->pool_name, "Default", sizeof(dcr->pool_name));
105 bstrncpy(dcr->pool_type, "Backup", sizeof(dcr->pool_type));
110 * Setup device, jcr, and prepare to access device.
111 * If the caller wants read access, acquire the device, otherwise,
112 * the caller will do it.
114 static DCR *setup_to_access_device(JCR *jcr, char *dev_name,
115 const char *VolumeName, int mode)
121 char VolName[MAX_NAME_LENGTH];
124 * If no volume name already given and no bsr, and it is a file,
125 * try getting name from Filename
128 bstrncpy(VolName, VolumeName, sizeof(VolName));
129 if (strlen(VolumeName) >= MAX_NAME_LENGTH) {
130 Jmsg0(jcr, M_ERROR, 0, _("Volume name or names is too long. Please use a .bsr file.\n"));
135 if (!jcr->bsr && VolName[0] == 0) {
136 if (strncmp(dev_name, "/dev/", 5) != 0) {
137 /* Try stripping file part */
138 p = dev_name + strlen(dev_name);
140 while (p >= dev_name && *p != '/')
143 bstrncpy(VolName, p+1, sizeof(VolName));
149 if ((device=find_device_res(dev_name, mode)) == NULL) {
150 Jmsg2(jcr, M_FATAL, 0, _("Cannot find device \"%s\" in config file %s.\n"),
151 dev_name, configfile);
155 dev = init_dev(jcr, device);
157 Jmsg1(jcr, M_FATAL, 0, _("Cannot init device %s\n"), dev_name);
161 dcr = new_dcr(jcr, dev);
164 bstrncpy(dcr->VolumeName, VolName, sizeof(dcr->VolumeName));
166 bstrncpy(dcr->dev_name, device->device_name, sizeof(dcr->dev_name));
168 create_restore_volume_list(jcr);
170 if (mode) { /* read only access? */
171 Dmsg0(100, "Acquire device for read\n");
172 if (!acquire_device_for_read(dcr)) {
177 if (!first_open_device(dcr)) {
178 Jmsg1(jcr, M_FATAL, 0, _("Cannot open %s\n"), dev->print_name());
181 jcr->dcr = dcr; /* write dcr */
188 * Called here when freeing JCR so that we can get rid
189 * of "daemon" specific memory allocated.
191 static void my_free_jcr(JCR *jcr)
194 free_pool_memory(jcr->job_name);
195 jcr->job_name = NULL;
197 if (jcr->client_name) {
198 free_pool_memory(jcr->client_name);
199 jcr->client_name = NULL;
201 if (jcr->fileset_name) {
202 free_pool_memory(jcr->fileset_name);
203 jcr->fileset_name = NULL;
205 if (jcr->fileset_md5) {
206 free_pool_memory(jcr->fileset_md5);
207 jcr->fileset_md5 = NULL;
210 free_restore_volume_list(jcr);
221 * Search for device resource that corresponds to
222 * device name on command line (or default).
224 * Returns: NULL on failure
225 * Device resource pointer on success
227 static DEVRES *find_device_res(char *device_name, int read_access)
232 Dmsg0(900, "Enter find_device_res\n");
234 foreach_res(device, R_DEVICE) {
235 Dmsg2(900, "Compare %s and %s\n", device->device_name, device_name);
236 if (strcmp(device->device_name, device_name) == 0) {
242 /* Search for name of Device resource rather than archive name */
243 if (device_name[0] == '"') {
244 int len = strlen(device_name);
245 bstrncpy(device_name, device_name+1, len+1);
248 device_name[len-1] = 0; /* zap trailing " */
251 foreach_res(device, R_DEVICE) {
252 Dmsg2(900, "Compare %s and %s\n", device->hdr.name, device_name);
253 if (strcmp(device->hdr.name, device_name) == 0) {
261 Pmsg2(0, _("Could not find device \"%s\" in config file %s.\n"), device_name,
266 Pmsg1(0, _("Using device: \"%s\" for reading.\n"), device_name);
269 Pmsg1(0, _("Using device: \"%s\" for writing.\n"), device_name);
276 * Device got an error, attempt to analyse it
278 void display_tape_error_status(JCR *jcr, DEVICE *dev)
282 status = status_dev(dev);
283 Dmsg1(20, "Device status: %x\n", status);
284 if (status & BMT_EOD)
285 Jmsg(jcr, M_ERROR, 0, _("Unexpected End of Data\n"));
286 else if (status & BMT_EOT)
287 Jmsg(jcr, M_ERROR, 0, _("Unexpected End of Tape\n"));
288 else if (status & BMT_EOF)
289 Jmsg(jcr, M_ERROR, 0, _("Unexpected End of File\n"));
290 else if (status & BMT_DR_OPEN)
291 Jmsg(jcr, M_ERROR, 0, _("Tape Door is Open\n"));
292 else if (!(status & BMT_ONLINE))
293 Jmsg(jcr, M_ERROR, 0, _("Unexpected Tape is Off-line\n"));