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