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