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