]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/butil.c
7a8da3571c60c9f5681510db1e31d4b046eafca2
[bacula/bacula] / bacula / src / stored / butil.c
1 /*
2  *
3  *  Utility routines for "tool" programs such as bscan, bls,
4  *    bextract, ...  Some routines also used by Bacula.
5  *
6  *    Kern Sibbald, MM
7  *
8  *  Normally nothing in this file is called by the Storage
9  *    daemon because we interact more directly with the user
10  *    i.e. printf, ...
11  *
12  *   Version $Id$
13  */
14 /*
15    Copyright (C) 2000-2005 Kern Sibbald
16
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.
21
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.
26
27  */
28
29 #include "bacula.h"
30 #include "stored.h"
31
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);
36
37 /* Imported variables -- eliminate some day */
38 extern char *configfile;
39
40 #ifdef DEBUG
41 char *rec_state_to_str(DEV_RECORD *rec)
42 {
43    static char buf[200];
44    buf[0] = 0;
45    if (rec->state & REC_NO_HEADER) {
46       strcat(buf, _("Nohdr,"));
47    }
48    if (is_partial_record(rec)) {
49       strcat(buf, _("partial,"));
50    }
51    if (rec->state & REC_BLOCK_EMPTY) {
52       strcat(buf, _("empty,"));
53    }
54    if (rec->state & REC_NO_MATCH) {
55       strcat(buf, _("Nomatch,"));
56    }
57    if (rec->state & REC_CONTINUATION) {
58       strcat(buf, _("cont,"));
59    }
60    if (buf[0]) {
61       buf[strlen(buf)-1] = 0;
62    }
63    return buf;
64 }
65 #endif
66
67 /*
68  * Setup a "daemon" JCR for the various standalone
69  *  tools (e.g. bls, bextract, bscan, ...)
70  */
71 JCR *setup_jcr(const char *name, char *dev_name, BSR *bsr,
72                const char *VolumeName, int mode)
73 {
74    DCR *dcr;
75    JCR *jcr = new_jcr(sizeof(JCR), my_free_jcr);
76    jcr->bsr = bsr;
77    jcr->VolSessionId = 1;
78    jcr->VolSessionTime = (uint32_t)time(NULL);
79    jcr->NumVolumes = 0;
80    jcr->JobId = 0;
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");
94
95    init_autochangers();
96
97    dcr = setup_to_access_device(jcr, dev_name, VolumeName, mode);
98    if (!dcr) {
99       return NULL;
100    }
101    if (!bsr && VolumeName) {
102       bstrncpy(dcr->VolumeName, VolumeName, sizeof(dcr->VolumeName));
103    }
104    bstrncpy(dcr->pool_name, "Default", sizeof(dcr->pool_name));
105    bstrncpy(dcr->pool_type, "Backup", sizeof(dcr->pool_type));
106    return jcr;
107 }
108
109 /*
110  * Setup device, jcr, and prepare to access device.
111  *   If the caller wants read access, acquire the device, otherwise,
112  *     the caller will do it.
113  */
114 static DCR *setup_to_access_device(JCR *jcr, char *dev_name, 
115               const char *VolumeName, int mode)
116 {
117    DEVICE *dev;
118    char *p;
119    DEVRES *device;
120    DCR *dcr;
121    char VolName[MAX_NAME_LENGTH];
122
123    /*
124     * If no volume name already given and no bsr, and it is a file,
125     * try getting name from Filename
126     */
127    if (VolumeName) {
128       bstrncpy(VolName, VolumeName, sizeof(VolName));
129       if (strlen(VolumeName) >= MAX_NAME_LENGTH) {
130          Jmsg0(jcr, M_ERROR, 0, _("Volume name or names is too long. Please use a .bsr file.\n"));
131       }
132    } else {
133       VolName[0] = 0;
134    }
135    if (!jcr->bsr && VolName[0] == 0) {
136       if (strncmp(dev_name, "/dev/", 5) != 0) {
137          /* Try stripping file part */
138          p = dev_name + strlen(dev_name);
139
140          while (p >= dev_name && *p != '/')
141             p--;
142          if (*p == '/') {
143             bstrncpy(VolName, p+1, sizeof(VolName));
144             *p = 0;
145          }
146       }
147    }
148
149    if ((device=find_device_res(dev_name, mode)) == NULL) {
150       Jmsg2(jcr, M_FATAL, 0, _("Cannot find device \"%s\" in config file %s.\n"),
151            dev_name, configfile);
152       return NULL;
153    }
154
155    dev = init_dev(jcr, device);
156    if (!dev) {
157       Jmsg1(jcr, M_FATAL, 0, _("Cannot init device %s\n"), dev_name);
158       return NULL;
159    }
160    device->dev = dev;
161    dcr = new_dcr(jcr, dev);
162    if (VolName[0]) {
163       bstrncpy(dcr->VolumeName, VolName, sizeof(dcr->VolumeName));
164    }
165    bstrncpy(dcr->dev_name, device->device_name, sizeof(dcr->dev_name));
166
167    create_restore_volume_list(jcr);
168
169    if (mode) {                        /* read only access? */
170       Dmsg0(100, "Acquire device for read\n");
171       if (!acquire_device_for_read(dcr)) {
172          return NULL;
173       }
174       jcr->read_dcr = dcr;
175    } else {
176       if (!first_open_device(dcr)) {
177          Jmsg1(jcr, M_FATAL, 0, _("Cannot open %s\n"), dev->print_name());
178          return NULL;
179       }
180       jcr->dcr = dcr;        /* write dcr */
181    }
182    return dcr;
183 }
184
185
186 /*
187  * Called here when freeing JCR so that we can get rid
188  *  of "daemon" specific memory allocated.
189  */
190 static void my_free_jcr(JCR *jcr)
191 {
192    if (jcr->job_name) {
193       free_pool_memory(jcr->job_name);
194       jcr->job_name = NULL;
195    }
196    if (jcr->client_name) {
197       free_pool_memory(jcr->client_name);
198       jcr->client_name = NULL;
199    }
200    if (jcr->fileset_name) {
201       free_pool_memory(jcr->fileset_name);
202       jcr->fileset_name = NULL;
203    }
204    if (jcr->fileset_md5) {
205       free_pool_memory(jcr->fileset_md5);
206       jcr->fileset_md5 = NULL;
207    }
208    if (jcr->VolList) {
209       free_restore_volume_list(jcr);
210    }
211    if (jcr->dcr) {
212       free_dcr(jcr->dcr);
213       jcr->dcr = NULL;
214    }
215    return;
216 }
217
218
219 /*
220  * Search for device resource that corresponds to
221  * device name on command line (or default).
222  *
223  * Returns: NULL on failure
224  *          Device resource pointer on success
225  */
226 static DEVRES *find_device_res(char *device_name, int read_access)
227 {
228    bool found = false;
229    DEVRES *device;
230
231    Dmsg0(900, "Enter find_device_res\n");
232    LockRes();
233    foreach_res(device, R_DEVICE) {
234       Dmsg2(900, "Compare %s and %s\n", device->device_name, device_name);
235       if (strcmp(device->device_name, device_name) == 0) {
236          found = true;
237          break;
238       }
239    }
240    if (!found) {
241       /* Search for name of Device resource rather than archive name */
242       if (device_name[0] == '"') {
243          int len = strlen(device_name);
244          bstrncpy(device_name, device_name+1, len+1);
245          len--;
246          if (len > 0) {
247             device_name[len-1] = 0;   /* zap trailing " */
248          }
249       }
250       foreach_res(device, R_DEVICE) {
251          Dmsg2(900, "Compare %s and %s\n", device->hdr.name, device_name);
252          if (strcmp(device->hdr.name, device_name) == 0) {
253             found = true;
254             break;
255          }
256       }
257    }
258    UnlockRes();
259    if (!found) {
260       Pmsg2(0, _("Could not find device \"%s\" in config file %s.\n"), device_name,
261             configfile);
262       return NULL;
263    }
264    if (read_access) {
265       Pmsg1(0, _("Using device: \"%s\" for reading.\n"), device_name);
266    }
267    else {
268       Pmsg1(0, _("Using device: \"%s\" for writing.\n"), device_name);
269    }
270    return device;
271 }
272
273
274 /*
275  * Device got an error, attempt to analyse it
276  */
277 void display_tape_error_status(JCR *jcr, DEVICE *dev)
278 {
279    uint32_t status;
280
281    status = status_dev(dev);
282    Dmsg1(20, "Device status: %x\n", status);
283    if (status & BMT_EOD)
284       Jmsg(jcr, M_ERROR, 0, _("Unexpected End of Data\n"));
285    else if (status & BMT_EOT)
286       Jmsg(jcr, M_ERROR, 0, _("Unexpected End of Tape\n"));
287    else if (status & BMT_EOF)
288       Jmsg(jcr, M_ERROR, 0, _("Unexpected End of File\n"));
289    else if (status & BMT_DR_OPEN)
290       Jmsg(jcr, M_ERROR, 0, _("Tape Door is Open\n"));
291    else if (!(status & BMT_ONLINE))
292       Jmsg(jcr, M_ERROR, 0, _("Unexpected Tape is Off-line\n"));
293 }