]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/butil.c
- Fix mode change open in btape.c
[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    Dmsg0(900, "Enter find_device_res\n");
228    LockRes();
229    foreach_res(device, R_DEVICE) {
230       Dmsg2(900, "Compare %s and %s\n", device->device_name, device_name);
231       if (strcmp(device->device_name, device_name) == 0) {
232          found = true;
233          break;
234       }
235    }
236    if (!found) {
237       /* Search for name of Device resource rather than archive name */
238       if (device_name[0] == '"') {
239          int len = strlen(device_name);
240          bstrncpy(device_name, device_name+1, len+1);
241          len--;
242          if (len > 0) {
243             device_name[len-1] = 0;   /* zap trailing " */
244          }
245       }
246       foreach_res(device, R_DEVICE) {
247          Dmsg2(900, "Compare %s and %s\n", device->hdr.name, device_name);
248          if (strcmp(device->hdr.name, device_name) == 0) {
249             found = true;
250             break;
251          }
252       }
253    }
254    UnlockRes();
255    if (!found) {
256       Pmsg2(0, _("Could not find device \"%s\" in config file %s.\n"), device_name,
257             configfile);
258       return NULL;
259    }
260    if (read_access) {
261       Pmsg1(0, _("Using device: \"%s\" for reading.\n"), device_name);
262    }
263    else {
264       Pmsg1(0, _("Using device: \"%s\" for writing.\n"), device_name);
265    }
266    return device;
267 }
268
269
270 /*
271  * Device got an error, attempt to analyse it
272  */
273 void display_tape_error_status(JCR *jcr, DEVICE *dev)
274 {
275    uint32_t status;
276
277    status = status_dev(dev);
278    Dmsg1(20, "Device status: %x\n", status);
279    if (status & BMT_EOD)
280       Jmsg(jcr, M_ERROR, 0, _("Unexpected End of Data\n"));
281    else if (status & BMT_EOT)
282       Jmsg(jcr, M_ERROR, 0, _("Unexpected End of Tape\n"));
283    else if (status & BMT_EOF)
284       Jmsg(jcr, M_ERROR, 0, _("Unexpected End of File\n"));
285    else if (status & BMT_DR_OPEN)
286       Jmsg(jcr, M_ERROR, 0, _("Tape Door is Open\n"));
287    else if (!(status & BMT_ONLINE))
288       Jmsg(jcr, M_ERROR, 0, _("Unexpected Tape is Off-line\n"));
289 }