]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/butil.c
b7fcb2a5f8d56762aa6491f103a8f9849ecea48c
[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    dcr = setup_to_access_device(jcr, dev_name, VolumeName, mode);
96    if (!dcr) {
97       return NULL;
98    }
99    if (!bsr && VolumeName) {
100       bstrncpy(dcr->VolumeName, VolumeName, sizeof(dcr->VolumeName));
101    }
102    bstrncpy(dcr->pool_name, "Default", sizeof(dcr->pool_name));
103    bstrncpy(dcr->pool_type, "Backup", sizeof(dcr->pool_type));
104    return jcr;
105 }
106
107 /*
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.
111  */
112 static DCR *setup_to_access_device(JCR *jcr, char *dev_name, 
113               const char *VolumeName, int mode)
114 {
115    DEVICE *dev;
116    char *p;
117    DEVRES *device;
118    DCR *dcr;
119    char VolName[MAX_NAME_LENGTH];
120
121    /*
122     * If no volume name already given and no bsr, and it is a file,
123     * try getting name from Filename
124     */
125    if (VolumeName) {
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"));
129       }
130    } else {
131       VolName[0] = 0;
132    }
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);
137
138          while (p >= dev_name && *p != '/')
139             p--;
140          if (*p == '/') {
141             bstrncpy(VolName, p+1, sizeof(VolName));
142             *p = 0;
143          }
144       }
145    }
146
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);
150       return NULL;
151    }
152
153    dev = init_dev(jcr, device);
154    if (!dev) {
155       Jmsg1(jcr, M_FATAL, 0, _("Cannot init device %s\n"), dev_name);
156       return NULL;
157    }
158    device->dev = dev;
159    dcr = new_dcr(jcr, dev);
160    if (VolName[0]) {
161       bstrncpy(dcr->VolumeName, VolName, sizeof(dcr->VolumeName));
162    }
163    bstrncpy(dcr->dev_name, device->device_name, sizeof(dcr->dev_name));
164
165    create_restore_volume_list(jcr);
166
167    if (mode) {                        /* read only access? */
168       Dmsg0(100, "Acquire device for read\n");
169       if (!acquire_device_for_read(dcr)) {
170          return NULL;
171       }
172    } else {
173       if (!first_open_device(dcr)) {
174          Jmsg1(jcr, M_FATAL, 0, _("Cannot open %s\n"), dev->print_name());
175          return NULL;
176       }
177    }
178    return dcr;
179 }
180
181
182 /*
183  * Called here when freeing JCR so that we can get rid
184  *  of "daemon" specific memory allocated.
185  */
186 static void my_free_jcr(JCR *jcr)
187 {
188    if (jcr->job_name) {
189       free_pool_memory(jcr->job_name);
190       jcr->job_name = NULL;
191    }
192    if (jcr->client_name) {
193       free_pool_memory(jcr->client_name);
194       jcr->client_name = NULL;
195    }
196    if (jcr->fileset_name) {
197       free_pool_memory(jcr->fileset_name);
198       jcr->fileset_name = NULL;
199    }
200    if (jcr->fileset_md5) {
201       free_pool_memory(jcr->fileset_md5);
202       jcr->fileset_md5 = NULL;
203    }
204    if (jcr->VolList) {
205       free_restore_volume_list(jcr);
206    }
207    if (jcr->dcr) {
208       free_dcr(jcr->dcr);
209       jcr->dcr = NULL;
210    }
211    return;
212 }
213
214
215 /*
216  * Search for device resource that corresponds to
217  * device name on command line (or default).
218  *
219  * Returns: NULL on failure
220  *          Device resource pointer on success
221  */
222 static DEVRES *find_device_res(char *device_name, int read_access)
223 {
224    bool found = false;
225    DEVRES *device;
226
227    LockRes();
228    foreach_res(device, R_DEVICE) {
229       if (strcmp(device->device_name, device_name) == 0) {
230          found = true;
231          break;
232       }
233    }
234    if (!found) {
235       /* Search for name of Device resource rather than archive name */
236       if (device_name[0] == '"') {
237          int len = strlen(device_name);
238          bstrncpy(device_name, device_name+1, len+1);
239          len--;
240          if (len > 0) {
241             device_name[len-1] = 0;   /* zap trailing " */
242          }
243       }
244       foreach_res(device, R_DEVICE) {
245          if (strcmp(device->hdr.name, device_name) == 0) {
246             found = true;
247             break;
248          }
249       }
250    }
251    UnlockRes();
252    if (!found) {
253       Pmsg2(0, _("Could not find device \"%s\" in config file %s.\n"), device_name,
254             configfile);
255       return NULL;
256    }
257    if (read_access) {
258       Pmsg1(0, _("Using device: \"%s\" for reading.\n"), device_name);
259    }
260    else {
261       Pmsg1(0, _("Using device: \"%s\" for writing.\n"), device_name);
262    }
263    return device;
264 }
265
266
267 /*
268  * Device got an error, attempt to analyse it
269  */
270 void display_tape_error_status(JCR *jcr, DEVICE *dev)
271 {
272    uint32_t status;
273
274    status = status_dev(dev);
275    Dmsg1(20, "Device status: %x\n", status);
276    if (status & BMT_EOD)
277       Jmsg(jcr, M_ERROR, 0, _("Unexpected End of Data\n"));
278    else if (status & BMT_EOT)
279       Jmsg(jcr, M_ERROR, 0, _("Unexpected End of Tape\n"));
280    else if (status & BMT_EOF)
281       Jmsg(jcr, M_ERROR, 0, _("Unexpected End of File\n"));
282    else if (status & BMT_DR_OPEN)
283       Jmsg(jcr, M_ERROR, 0, _("Tape Door is Open\n"));
284    else if (!(status & BMT_ONLINE))
285       Jmsg(jcr, M_ERROR, 0, _("Unexpected Tape is Off-line\n"));
286 }