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 ammended 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) {
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");
95 dcr = setup_to_access_device(jcr, dev_name, VolumeName, mode);
99 if (!bsr && VolumeName) {
100 bstrncpy(dcr->VolumeName, VolumeName, sizeof(dcr->VolumeName));
102 bstrncpy(dcr->pool_name, "Default", sizeof(dcr->pool_name));
103 bstrncpy(dcr->pool_type, "Backup", sizeof(dcr->pool_type));
108 * Setup device, jcr, and prepare to access device.
109 * If the caller wants read access, acquire the device, otherwise,
110 * the caller will do it.
112 static DCR *setup_to_access_device(JCR *jcr, char *dev_name,
113 const char *VolumeName, int mode)
119 char VolName[MAX_NAME_LENGTH];
122 * If no volume name already given and no bsr, and it is a file,
123 * try getting name from Filename
126 bstrncpy(VolName, VolumeName, sizeof(VolName));
130 if (!jcr->bsr && VolName[0] == 0) {
131 if (strncmp(dev_name, "/dev/", 5) != 0) {
132 /* Try stripping file part */
133 p = dev_name + strlen(dev_name);
135 while (p >= dev_name && *p != '/')
138 bstrncpy(VolName, p+1, sizeof(VolName));
144 if ((device=find_device_res(dev_name, mode)) == NULL) {
145 Jmsg2(jcr, M_FATAL, 0, _("Cannot find device \"%s\" in config file %s.\n"),
146 dev_name, configfile);
150 dev = init_dev(jcr, NULL, device);
152 Jmsg1(jcr, M_FATAL, 0, _("Cannot init device %s\n"), dev_name);
156 dcr = new_dcr(jcr, dev);
158 bstrncpy(dcr->VolumeName, VolName, sizeof(dcr->VolumeName));
160 bstrncpy(dcr->dev_name, device->device_name, sizeof(dcr->dev_name));
162 create_vol_list(jcr);
164 if (mode) { /* read only access? */
165 if (!acquire_device_for_read(dcr)) {
169 if (!first_open_device(dev)) {
170 Jmsg1(jcr, M_FATAL, 0, _("Cannot open %s\n"), dcr->dev_name);
179 * Called here when freeing JCR so that we can get rid
180 * of "daemon" specific memory allocated.
182 static void my_free_jcr(JCR *jcr)
185 free_pool_memory(jcr->job_name);
186 jcr->job_name = NULL;
188 if (jcr->client_name) {
189 free_pool_memory(jcr->client_name);
190 jcr->client_name = NULL;
192 if (jcr->fileset_name) {
193 free_pool_memory(jcr->fileset_name);
194 jcr->fileset_name = NULL;
196 if (jcr->fileset_md5) {
197 free_pool_memory(jcr->fileset_md5);
198 jcr->fileset_md5 = NULL;
212 * Search for device resource that corresponds to
213 * device name on command line (or default).
215 * Returns: NULL on failure
216 * Device resource pointer on success
218 static DEVRES *find_device_res(char *device_name, int read_access)
224 foreach_res(device, R_DEVICE) {
225 if (strcmp(device->device_name, device_name) == 0) {
231 /* Search for name of Device resource rather than archive name */
232 if (device_name[0] == '"') {
233 int len = strlen(device_name);
234 bstrncpy(device_name, device_name+1, len+1);
237 device_name[len-1] = 0; /* zap trailing " */
240 foreach_res(device, R_DEVICE) {
241 if (strcmp(device->hdr.name, device_name) == 0) {
249 Pmsg2(0, _("Could not find device \"%s\" in config file %s.\n"), device_name,
253 Pmsg2(0, _("Using device: \"%s\" for %s.\n"), device_name,
254 read_access?"reading":"writing");
260 * Device got an error, attempt to analyse it
262 void display_tape_error_status(JCR *jcr, DEVICE *dev)
266 status = status_dev(dev);
267 Dmsg1(20, "Device status: %x\n", status);
268 if (status & BMT_EOD)
269 Jmsg(jcr, M_ERROR, 0, _("Unexpected End of Data\n"));
270 else if (status & BMT_EOT)
271 Jmsg(jcr, M_ERROR, 0, _("Unexpected End of Tape\n"));
272 else if (status & BMT_EOF)
273 Jmsg(jcr, M_ERROR, 0, _("Unexpected End of File\n"));
274 else if (status & BMT_DR_OPEN)
275 Jmsg(jcr, M_ERROR, 0, _("Tape Door is Open\n"));
276 else if (!(status & BMT_ONLINE))
277 Jmsg(jcr, M_ERROR, 0, _("Unexpected Tape is Off-line\n"));