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