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-2006 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];
124 init_reservations_lock();
127 * If no volume name already given and no bsr, and it is a file,
128 * try getting name from Filename
131 bstrncpy(VolName, VolumeName, sizeof(VolName));
132 if (strlen(VolumeName) >= MAX_NAME_LENGTH) {
133 Jmsg0(jcr, M_ERROR, 0, _("Volume name or names is too long. Please use a .bsr file.\n"));
138 if (!jcr->bsr && VolName[0] == 0) {
139 if (strncmp(dev_name, "/dev/", 5) != 0) {
140 /* Try stripping file part */
141 p = dev_name + strlen(dev_name);
143 while (p >= dev_name && *p != '/')
146 bstrncpy(VolName, p+1, sizeof(VolName));
152 if ((device=find_device_res(dev_name, mode)) == NULL) {
153 Jmsg2(jcr, M_FATAL, 0, _("Cannot find device \"%s\" in config file %s.\n"),
154 dev_name, configfile);
158 dev = init_dev(jcr, device);
160 Jmsg1(jcr, M_FATAL, 0, _("Cannot init device %s\n"), dev_name);
164 dcr = new_dcr(jcr, dev);
167 bstrncpy(dcr->VolumeName, VolName, sizeof(dcr->VolumeName));
169 bstrncpy(dcr->dev_name, device->device_name, sizeof(dcr->dev_name));
171 create_restore_volume_list(jcr);
173 if (mode) { /* read only access? */
174 Dmsg0(100, "Acquire device for read\n");
175 if (!acquire_device_for_read(dcr)) {
180 if (!first_open_device(dcr)) {
181 Jmsg1(jcr, M_FATAL, 0, _("Cannot open %s\n"), dev->print_name());
184 jcr->dcr = dcr; /* write dcr */
191 * Called here when freeing JCR so that we can get rid
192 * of "daemon" specific memory allocated.
194 static void my_free_jcr(JCR *jcr)
197 free_pool_memory(jcr->job_name);
198 jcr->job_name = NULL;
200 if (jcr->client_name) {
201 free_pool_memory(jcr->client_name);
202 jcr->client_name = NULL;
204 if (jcr->fileset_name) {
205 free_pool_memory(jcr->fileset_name);
206 jcr->fileset_name = NULL;
208 if (jcr->fileset_md5) {
209 free_pool_memory(jcr->fileset_md5);
210 jcr->fileset_md5 = NULL;
213 free_restore_volume_list(jcr);
224 * Search for device resource that corresponds to
225 * device name on command line (or default).
227 * Returns: NULL on failure
228 * Device resource pointer on success
230 static DEVRES *find_device_res(char *device_name, int read_access)
235 Dmsg0(900, "Enter find_device_res\n");
237 foreach_res(device, R_DEVICE) {
238 Dmsg2(900, "Compare %s and %s\n", device->device_name, device_name);
239 if (strcmp(device->device_name, device_name) == 0) {
245 /* Search for name of Device resource rather than archive name */
246 if (device_name[0] == '"') {
247 int len = strlen(device_name);
248 bstrncpy(device_name, device_name+1, len+1);
251 device_name[len-1] = 0; /* zap trailing " */
254 foreach_res(device, R_DEVICE) {
255 Dmsg2(900, "Compare %s and %s\n", device->hdr.name, device_name);
256 if (strcmp(device->hdr.name, device_name) == 0) {
264 Pmsg2(0, _("Could not find device \"%s\" in config file %s.\n"), device_name,
269 Pmsg1(0, _("Using device: \"%s\" for reading.\n"), device_name);
272 Pmsg1(0, _("Using device: \"%s\" for writing.\n"), device_name);
279 * Device got an error, attempt to analyse it
281 void display_tape_error_status(JCR *jcr, DEVICE *dev)
285 status = status_dev(dev);
286 Dmsg1(20, "Device status: %x\n", status);
287 if (status & BMT_EOD)
288 Jmsg(jcr, M_ERROR, 0, _("Unexpected End of Data\n"));
289 else if (status & BMT_EOT)
290 Jmsg(jcr, M_ERROR, 0, _("Unexpected End of Tape\n"));
291 else if (status & BMT_EOF)
292 Jmsg(jcr, M_ERROR, 0, _("Unexpected End of File\n"));
293 else if (status & BMT_DR_OPEN)
294 Jmsg(jcr, M_ERROR, 0, _("Tape Door is Open\n"));
295 else if (!(status & BMT_ONLINE))
296 Jmsg(jcr, M_ERROR, 0, _("Unexpected Tape is Off-line\n"));