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));
127 if (strlen(VolumeName) >= MAX_NAME_LENGTH) {
128 Jmsg0(jcr, M_ERROR, 0, _("Volume name or names is too long. Please use a .bsr file.\n"));
133 if (!jcr->bsr && VolName[0] == 0) {
134 if (strncmp(dev_name, "/dev/", 5) != 0) {
135 /* Try stripping file part */
136 p = dev_name + strlen(dev_name);
138 while (p >= dev_name && *p != '/')
141 bstrncpy(VolName, p+1, sizeof(VolName));
147 if ((device=find_device_res(dev_name, mode)) == NULL) {
148 Jmsg2(jcr, M_FATAL, 0, _("Cannot find device \"%s\" in config file %s.\n"),
149 dev_name, configfile);
153 dev = init_dev(jcr, device);
155 Jmsg1(jcr, M_FATAL, 0, _("Cannot init device %s\n"), dev_name);
159 dcr = new_dcr(jcr, dev);
161 bstrncpy(dcr->VolumeName, VolName, sizeof(dcr->VolumeName));
163 bstrncpy(dcr->dev_name, device->device_name, sizeof(dcr->dev_name));
165 create_restore_volume_list(jcr);
167 if (mode) { /* read only access? */
168 if (!acquire_device_for_read(dcr)) {
172 if (!first_open_device(dev)) {
173 Jmsg1(jcr, M_FATAL, 0, _("Cannot open %s\n"), dcr->dev_name);
182 * Called here when freeing JCR so that we can get rid
183 * of "daemon" specific memory allocated.
185 static void my_free_jcr(JCR *jcr)
188 free_pool_memory(jcr->job_name);
189 jcr->job_name = NULL;
191 if (jcr->client_name) {
192 free_pool_memory(jcr->client_name);
193 jcr->client_name = NULL;
195 if (jcr->fileset_name) {
196 free_pool_memory(jcr->fileset_name);
197 jcr->fileset_name = NULL;
199 if (jcr->fileset_md5) {
200 free_pool_memory(jcr->fileset_md5);
201 jcr->fileset_md5 = NULL;
204 free_restore_volume_list(jcr);
215 * Search for device resource that corresponds to
216 * device name on command line (or default).
218 * Returns: NULL on failure
219 * Device resource pointer on success
221 static DEVRES *find_device_res(char *device_name, int read_access)
227 foreach_res(device, R_DEVICE) {
228 if (strcmp(device->device_name, device_name) == 0) {
234 /* Search for name of Device resource rather than archive name */
235 if (device_name[0] == '"') {
236 int len = strlen(device_name);
237 bstrncpy(device_name, device_name+1, len+1);
240 device_name[len-1] = 0; /* zap trailing " */
243 foreach_res(device, R_DEVICE) {
244 if (strcmp(device->hdr.name, device_name) == 0) {
252 Pmsg2(0, _("Could not find device \"%s\" in config file %s.\n"), device_name,
256 Pmsg2(0, _("Using device: \"%s\" for %s.\n"), device_name,
257 read_access?"reading":"writing");
263 * Device got an error, attempt to analyse it
265 void display_tape_error_status(JCR *jcr, DEVICE *dev)
269 status = status_dev(dev);
270 Dmsg1(20, "Device status: %x\n", status);
271 if (status & BMT_EOD)
272 Jmsg(jcr, M_ERROR, 0, _("Unexpected End of Data\n"));
273 else if (status & BMT_EOT)
274 Jmsg(jcr, M_ERROR, 0, _("Unexpected End of Tape\n"));
275 else if (status & BMT_EOF)
276 Jmsg(jcr, M_ERROR, 0, _("Unexpected End of File\n"));
277 else if (status & BMT_DR_OPEN)
278 Jmsg(jcr, M_ERROR, 0, _("Tape Door is Open\n"));
279 else if (!(status & BMT_ONLINE))
280 Jmsg(jcr, M_ERROR, 0, _("Unexpected Tape is Off-line\n"));