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");
98 dcr = setup_to_access_device(jcr, dev_name, VolumeName, mode);
102 if (!bsr && VolumeName) {
103 bstrncpy(dcr->VolumeName, VolumeName, sizeof(dcr->VolumeName));
105 bstrncpy(dcr->pool_name, "Default", sizeof(dcr->pool_name));
106 bstrncpy(dcr->pool_type, "Backup", sizeof(dcr->pool_type));
111 * Setup device, jcr, and prepare to access device.
112 * If the caller wants read access, acquire the device, otherwise,
113 * the caller will do it.
115 static DCR *setup_to_access_device(JCR *jcr, char *dev_name,
116 const char *VolumeName, int mode)
122 char VolName[MAX_NAME_LENGTH];
125 * If no volume name already given and no bsr, and it is a file,
126 * try getting name from Filename
129 bstrncpy(VolName, VolumeName, sizeof(VolName));
130 if (strlen(VolumeName) >= MAX_NAME_LENGTH) {
131 Jmsg0(jcr, M_ERROR, 0, _("Volume name or names is too long. Please use a .bsr file.\n"));
136 if (!jcr->bsr && VolName[0] == 0) {
137 if (strncmp(dev_name, "/dev/", 5) != 0) {
138 /* Try stripping file part */
139 p = dev_name + strlen(dev_name);
141 while (p >= dev_name && *p != '/')
144 bstrncpy(VolName, p+1, sizeof(VolName));
150 if ((device=find_device_res(dev_name, mode)) == NULL) {
151 Jmsg2(jcr, M_FATAL, 0, _("Cannot find device \"%s\" in config file %s.\n"),
152 dev_name, configfile);
156 dev = init_dev(jcr, device);
158 Jmsg1(jcr, M_FATAL, 0, _("Cannot init device %s\n"), dev_name);
162 dcr = new_dcr(jcr, dev);
165 bstrncpy(dcr->VolumeName, VolName, sizeof(dcr->VolumeName));
167 bstrncpy(dcr->dev_name, device->device_name, sizeof(dcr->dev_name));
169 create_restore_volume_list(jcr);
171 if (mode) { /* read only access? */
172 Dmsg0(100, "Acquire device for read\n");
173 if (!acquire_device_for_read(dcr)) {
178 if (!first_open_device(dcr)) {
179 Jmsg1(jcr, M_FATAL, 0, _("Cannot open %s\n"), dev->print_name());
182 jcr->dcr = dcr; /* write dcr */
189 * Called here when freeing JCR so that we can get rid
190 * of "daemon" specific memory allocated.
192 static void my_free_jcr(JCR *jcr)
195 free_pool_memory(jcr->job_name);
196 jcr->job_name = NULL;
198 if (jcr->client_name) {
199 free_pool_memory(jcr->client_name);
200 jcr->client_name = NULL;
202 if (jcr->fileset_name) {
203 free_pool_memory(jcr->fileset_name);
204 jcr->fileset_name = NULL;
206 if (jcr->fileset_md5) {
207 free_pool_memory(jcr->fileset_md5);
208 jcr->fileset_md5 = NULL;
211 free_restore_volume_list(jcr);
222 * Search for device resource that corresponds to
223 * device name on command line (or default).
225 * Returns: NULL on failure
226 * Device resource pointer on success
228 static DEVRES *find_device_res(char *device_name, int read_access)
233 Dmsg0(900, "Enter find_device_res\n");
235 foreach_res(device, R_DEVICE) {
236 Dmsg2(900, "Compare %s and %s\n", device->device_name, device_name);
237 if (strcmp(device->device_name, device_name) == 0) {
243 /* Search for name of Device resource rather than archive name */
244 if (device_name[0] == '"') {
245 int len = strlen(device_name);
246 bstrncpy(device_name, device_name+1, len+1);
249 device_name[len-1] = 0; /* zap trailing " */
252 foreach_res(device, R_DEVICE) {
253 Dmsg2(900, "Compare %s and %s\n", device->hdr.name, device_name);
254 if (strcmp(device->hdr.name, device_name) == 0) {
262 Pmsg2(0, _("Could not find device \"%s\" in config file %s.\n"), device_name,
267 Pmsg1(0, _("Using device: \"%s\" for reading.\n"), device_name);
270 Pmsg1(0, _("Using device: \"%s\" for writing.\n"), device_name);
277 * Device got an error, attempt to analyse it
279 void display_tape_error_status(JCR *jcr, DEVICE *dev)
283 status = status_dev(dev);
284 Dmsg1(20, "Device status: %x\n", status);
285 if (status & BMT_EOD)
286 Jmsg(jcr, M_ERROR, 0, _("Unexpected End of Data\n"));
287 else if (status & BMT_EOT)
288 Jmsg(jcr, M_ERROR, 0, _("Unexpected End of Tape\n"));
289 else if (status & BMT_EOF)
290 Jmsg(jcr, M_ERROR, 0, _("Unexpected End of File\n"));
291 else if (status & BMT_DR_OPEN)
292 Jmsg(jcr, M_ERROR, 0, _("Tape Door is Open\n"));
293 else if (!(status & BMT_ONLINE))
294 Jmsg(jcr, M_ERROR, 0, _("Unexpected Tape is Off-line\n"));