2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2017 Kern Sibbald
6 The original author of Bacula is Kern Sibbald, with contributions
7 from many others, a complete list can be found in the file AUTHORS.
9 You may use this file and others of this release according to the
10 license defined in the LICENSE file, which includes the Affero General
11 Public License, v3.0 ("AGPLv3") and some additional permissions and
12 terms pursuant to its AGPLv3 Section 7.
14 This notice must be preserved when any source code is
15 conveyed and/or propagated.
17 Bacula(R) is a registered trademark of Kern Sibbald.
21 * Utility routines for "tool" programs such as bscan, bls,
22 * bextract, ... Some routines also used by Bacula.
26 * Normally nothing in this file is called by the Storage
27 * daemon because we interact more directly with the user
34 /* Forward referenced functions */
35 static DCR *setup_to_access_device(JCR *jcr, char *dev_name,
36 const char *VolumeName, bool writing, bool read_dedup_data);
37 static DEVRES *find_device_res(char *device_name, bool writing);
38 static void my_free_jcr(JCR *jcr);
40 /* Imported variables -- eliminate some day */
41 extern char *configfile;
44 char *rec_state_bits_to_str(DEV_RECORD *rec)
48 if (rec->state_bits & REC_NO_HEADER) {
49 strcat(buf, _("Nohdr,"));
51 if (is_partial_record(rec)) {
52 strcat(buf, _("partial,"));
54 if (rec->state_bits & REC_BLOCK_EMPTY) {
55 strcat(buf, _("empty,"));
57 if (rec->state_bits & REC_NO_MATCH) {
58 strcat(buf, _("Nomatch,"));
60 if (rec->state_bits & REC_CONTINUATION) {
61 strcat(buf, _("cont,"));
64 buf[strlen(buf)-1] = 0;
71 * Setup a pointer to my resource me
76 me = (STORES *)GetNextRes(R_STORAGE, NULL);
79 Emsg1(M_ERROR_TERM, 0, _("No Storage resource defined in %s. Cannot continue.\n"),
86 * Setup a "daemon" JCR for the various standalone
87 * tools (e.g. bls, bextract, bscan, ...)
89 JCR *setup_jcr(const char *name, char *dev_name, BSR *bsr,
90 const char *VolumeName, bool writing, bool read_dedup_data)
93 JCR *jcr = new_jcr(sizeof(JCR), my_free_jcr);
95 jcr->VolSessionId = 1;
96 jcr->VolSessionTime = (uint32_t)time(NULL);
97 jcr->NumReadVolumes = 0;
98 jcr->NumWriteVolumes = 0;
100 jcr->setJobType(JT_CONSOLE);
101 jcr->setJobLevel(L_FULL);
102 jcr->JobStatus = JS_Terminated;
103 jcr->where = bstrdup("");
104 jcr->job_name = get_pool_memory(PM_FNAME);
105 pm_strcpy(jcr->job_name, "Dummy.Job.Name");
106 jcr->client_name = get_pool_memory(PM_FNAME);
107 pm_strcpy(jcr->client_name, "Dummy.Client.Name");
108 bstrncpy(jcr->Job, name, sizeof(jcr->Job));
109 jcr->fileset_name = get_pool_memory(PM_FNAME);
110 pm_strcpy(jcr->fileset_name, "Dummy.fileset.name");
111 jcr->fileset_md5 = get_pool_memory(PM_FNAME);
112 pm_strcpy(jcr->fileset_md5, "Dummy.fileset.md5");
114 create_volume_lists();
116 dcr = setup_to_access_device(jcr, dev_name, VolumeName, writing, read_dedup_data);
120 if (!bsr && VolumeName) {
121 bstrncpy(dcr->VolumeName, VolumeName, sizeof(dcr->VolumeName));
123 bstrncpy(dcr->pool_name, "Default", sizeof(dcr->pool_name));
124 bstrncpy(dcr->pool_type, "Backup", sizeof(dcr->pool_type));
129 * Setup device, jcr, and prepare to access device.
130 * If the caller wants read access, acquire the device, otherwise,
131 * the caller will do it.
133 static DCR *setup_to_access_device(JCR *jcr, char *dev_name,
134 const char *VolumeName, bool writing, bool read_dedup_data)
140 char VolName[MAX_NAME_LENGTH];
142 init_reservations_lock();
145 * If no volume name already given and no bsr, and it is a file,
146 * try getting name from Filename
149 bstrncpy(VolName, VolumeName, sizeof(VolName));
150 if (strlen(VolumeName) >= MAX_NAME_LENGTH) {
151 Jmsg0(jcr, M_ERROR, 0, _("Volume name or names is too long. Please use a .bsr file.\n"));
156 if (!jcr->bsr && VolName[0] == 0) {
157 if (strncmp(dev_name, "/dev/", 5) != 0) {
158 /* Try stripping file part */
159 p = dev_name + strlen(dev_name);
161 while (p >= dev_name && !IsPathSeparator(*p))
163 if (IsPathSeparator(*p)) {
164 bstrncpy(VolName, p+1, sizeof(VolName));
170 if ((device=find_device_res(dev_name, writing)) == NULL) {
171 Jmsg2(jcr, M_FATAL, 0, _("Cannot find device \"%s\" in config file %s.\n"),
172 dev_name, configfile);
176 dev = init_dev(jcr, device);
178 Jmsg1(jcr, M_FATAL, 0, _("Cannot init device %s\n"), dev_name);
182 jcr->dcr = dcr = new_dcr(jcr, NULL, dev, writing);
184 bstrncpy(dcr->VolumeName, VolName, sizeof(dcr->VolumeName));
186 bstrncpy(dcr->dev_name, device->device_name, sizeof(dcr->dev_name));
188 create_restore_volume_list(jcr, true);
190 if (!writing) { /* read only access? */
191 Dmsg0(100, "Acquire device for read\n");
192 if (!acquire_device_for_read(dcr)) {
197 if (!first_open_device(dcr)) {
198 Jmsg1(jcr, M_FATAL, 0, _("Cannot open %s\n"), dev->print_name());
201 jcr->dcr = dcr; /* write dcr */
208 * Called here when freeing JCR so that we can get rid
209 * of "daemon" specific memory allocated.
211 static void my_free_jcr(JCR *jcr)
214 free_pool_memory(jcr->job_name);
215 jcr->job_name = NULL;
217 if (jcr->client_name) {
218 free_pool_memory(jcr->client_name);
219 jcr->client_name = NULL;
221 if (jcr->fileset_name) {
222 free_pool_memory(jcr->fileset_name);
223 jcr->fileset_name = NULL;
225 if (jcr->fileset_md5) {
226 free_pool_memory(jcr->fileset_md5);
227 jcr->fileset_md5 = NULL;
230 free_pool_memory(jcr->comment);
234 free_restore_volume_list(jcr);
245 * Search for device resource that corresponds to
246 * device name on command line (or default).
248 * Returns: NULL on failure
249 * Device resource pointer on success
251 static DEVRES *find_device_res(char *device_name, bool write_access)
256 Dmsg0(900, "Enter find_device_res\n");
258 foreach_res(device, R_DEVICE) {
259 Dmsg2(900, "Compare %s and %s\n", device->device_name, device_name);
260 if (strcmp(device->device_name, device_name) == 0) {
266 /* Search for name of Device resource rather than archive name */
267 if (device_name[0] == '"') {
268 int len = strlen(device_name);
269 bstrncpy(device_name, device_name+1, len+1);
272 device_name[len-1] = 0; /* zap trailing " */
275 foreach_res(device, R_DEVICE) {
276 Dmsg2(900, "Compare %s and %s\n", device->hdr.name, device_name);
277 if (strcmp(device->hdr.name, device_name) == 0) {
285 Pmsg2(0, _("Could not find device \"%s\" in config file %s.\n"), device_name,
290 Pmsg1(0, _("Using device: \"%s\" for writing.\n"), device_name);
292 Pmsg1(0, _("Using device: \"%s\" for reading.\n"), device_name);
299 * Device got an error, attempt to analyse it
301 void display_tape_error_status(JCR *jcr, DEVICE *dev)
305 status = status_dev(dev);
306 Dmsg1(20, "Device status: %x\n", status);
307 if (status & BMT_EOD)
308 Jmsg(jcr, M_ERROR, 0, _("Unexpected End of Data\n"));
309 else if (status & BMT_EOT)
310 Jmsg(jcr, M_ERROR, 0, _("Unexpected End of Tape\n"));
311 else if (status & BMT_EOF)
312 Jmsg(jcr, M_ERROR, 0, _("Unexpected End of File\n"));
313 else if (status & BMT_DR_OPEN)
314 Jmsg(jcr, M_ERROR, 0, _("Tape Door is Open\n"));
315 else if (!(status & BMT_ONLINE))
316 Jmsg(jcr, M_ERROR, 0, _("Unexpected Tape is Off-line\n"));