]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/butil.c
- Merge changes made to 1.38.3 into HEAD
[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    jcr->dcr = dcr;
163    if (VolName[0]) {
164       bstrncpy(dcr->VolumeName, VolName, sizeof(dcr->VolumeName));
165    }
166    bstrncpy(dcr->dev_name, device->device_name, sizeof(dcr->dev_name));
167
168    create_restore_volume_list(jcr);
169
170    if (mode) {                        /* read only access? */
171       Dmsg0(100, "Acquire device for read\n");
172       if (!acquire_device_for_read(dcr)) {
173          return NULL;
174       }
175       jcr->read_dcr = dcr;
176    } else {
177       if (!first_open_device(dcr)) {
178          Jmsg1(jcr, M_FATAL, 0, _("Cannot open %s\n"), dev->print_name());
179          return NULL;
180       }
181       jcr->dcr = dcr;        /* write dcr */
182    }
183    return dcr;
184 }
185
186
187 /*
188  * Called here when freeing JCR so that we can get rid
189  *  of "daemon" specific memory allocated.
190  */
191 static void my_free_jcr(JCR *jcr)
192 {
193    if (jcr->job_name) {
194       free_pool_memory(jcr->job_name);
195       jcr->job_name = NULL;
196    }
197    if (jcr->client_name) {
198       free_pool_memory(jcr->client_name);
199       jcr->client_name = NULL;
200    }
201    if (jcr->fileset_name) {
202       free_pool_memory(jcr->fileset_name);
203       jcr->fileset_name = NULL;
204    }
205    if (jcr->fileset_md5) {
206       free_pool_memory(jcr->fileset_md5);
207       jcr->fileset_md5 = NULL;
208    }
209    if (jcr->VolList) {
210       free_restore_volume_list(jcr);
211    }
212    if (jcr->dcr) {
213       free_dcr(jcr->dcr);
214       jcr->dcr = NULL;
215    }
216    return;
217 }
218
219
220 /*
221  * Search for device resource that corresponds to
222  * device name on command line (or default).
223  *
224  * Returns: NULL on failure
225  *          Device resource pointer on success
226  */
227 static DEVRES *find_device_res(char *device_name, int read_access)
228 {
229    bool found = false;
230    DEVRES *device;
231
232    Dmsg0(900, "Enter find_device_res\n");
233    LockRes();
234    foreach_res(device, R_DEVICE) {
235       Dmsg2(900, "Compare %s and %s\n", device->device_name, device_name);
236       if (strcmp(device->device_name, device_name) == 0) {
237          found = true;
238          break;
239       }
240    }
241    if (!found) {
242       /* Search for name of Device resource rather than archive name */
243       if (device_name[0] == '"') {
244          int len = strlen(device_name);
245          bstrncpy(device_name, device_name+1, len+1);
246          len--;
247          if (len > 0) {
248             device_name[len-1] = 0;   /* zap trailing " */
249          }
250       }
251       foreach_res(device, R_DEVICE) {
252          Dmsg2(900, "Compare %s and %s\n", device->hdr.name, device_name);
253          if (strcmp(device->hdr.name, device_name) == 0) {
254             found = true;
255             break;
256          }
257       }
258    }
259    UnlockRes();
260    if (!found) {
261       Pmsg2(0, _("Could not find device \"%s\" in config file %s.\n"), device_name,
262             configfile);
263       return NULL;
264    }
265    if (read_access) {
266       Pmsg1(0, _("Using device: \"%s\" for reading.\n"), device_name);
267    }
268    else {
269       Pmsg1(0, _("Using device: \"%s\" for writing.\n"), device_name);
270    }
271    return device;
272 }
273
274
275 /*
276  * Device got an error, attempt to analyse it
277  */
278 void display_tape_error_status(JCR *jcr, DEVICE *dev)
279 {
280    uint32_t status;
281
282    status = status_dev(dev);
283    Dmsg1(20, "Device status: %x\n", status);
284    if (status & BMT_EOD)
285       Jmsg(jcr, M_ERROR, 0, _("Unexpected End of Data\n"));
286    else if (status & BMT_EOT)
287       Jmsg(jcr, M_ERROR, 0, _("Unexpected End of Tape\n"));
288    else if (status & BMT_EOF)
289       Jmsg(jcr, M_ERROR, 0, _("Unexpected End of File\n"));
290    else if (status & BMT_DR_OPEN)
291       Jmsg(jcr, M_ERROR, 0, _("Tape Door is Open\n"));
292    else if (!(status & BMT_ONLINE))
293       Jmsg(jcr, M_ERROR, 0, _("Unexpected Tape is Off-line\n"));
294 }