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