X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fstored%2Fbutil.c;h=034a4c100e96328b3f35252ec74ff4bc7986308a;hb=562570f93a8dc0f9a2ebed286e8eed9ffd23a058;hp=318408428ab6d22dc5e3da0f09645413ee140374;hpb=e98e361785ed4d4f6c3e7d8049825addbdf52f31;p=bacula%2Fbacula diff --git a/bacula/src/stored/butil.c b/bacula/src/stored/butil.c index 318408428a..034a4c100e 100644 --- a/bacula/src/stored/butil.c +++ b/bacula/src/stored/butil.c @@ -1,59 +1,74 @@ /* - * - * Utility routines for "tool" programs such as bscan, bls, - * bextract, ... - * - * Normally nothing in this file is called by the Storage - * daemon because we interact more directly with the user - * i.e. printf, ... - * - * Version $Id$ - */ -/* - Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker + Bacula® - The Network Backup Solution + + Copyright (C) 2000-2007 Free Software Foundation Europe e.V. - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of - the License, or (at your option) any later version. + The main author of Bacula is Kern Sibbald, with contributions from + many others, a complete list can be found in the file AUTHORS. + This program is Free Software; you can redistribute it and/or + modify it under the terms of version two of the GNU General Public + License as published by the Free Software Foundation and included + in the file LICENSE. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public - License along with this program; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. + Bacula® is a registered trademark of Kern Sibbald. + The licensor of Bacula is the Free Software Foundation Europe + (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, + Switzerland, email:ftf@fsfeurope.org. +*/ +/* + * + * Utility routines for "tool" programs such as bscan, bls, + * bextract, ... Some routines also used by Bacula. + * + * Kern Sibbald, MM + * + * Normally nothing in this file is called by the Storage + * daemon because we interact more directly with the user + * i.e. printf, ... + * + * Version $Id$ */ #include "bacula.h" #include "stored.h" +/* Forward referenced functions */ +static DCR *setup_to_access_device(JCR *jcr, char *dev_name, const char *VolumeName, int mode); +static DEVRES *find_device_res(char *device_name, int mode); +static void my_free_jcr(JCR *jcr); + /* Imported variables -- eliminate some day */ extern char *configfile; #ifdef DEBUG char *rec_state_to_str(DEV_RECORD *rec) { - static char buf[200]; + static char buf[200]; buf[0] = 0; if (rec->state & REC_NO_HEADER) { - strcat(buf, "Nohdr,"); + strcat(buf, _("Nohdr,")); } if (is_partial_record(rec)) { - strcat(buf, "partial,"); + strcat(buf, _("partial,")); } if (rec->state & REC_BLOCK_EMPTY) { - strcat(buf, "empty,"); + strcat(buf, _("empty,")); } if (rec->state & REC_NO_MATCH) { - strcat(buf, "Nomatch,"); + strcat(buf, _("Nomatch,")); } if (rec->state & REC_CONTINUATION) { - strcat(buf, "cont,"); + strcat(buf, _("cont,")); } if (buf[0]) { buf[strlen(buf)-1] = 0; @@ -62,106 +77,135 @@ char *rec_state_to_str(DEV_RECORD *rec) } #endif +/* + * Setup a "daemon" JCR for the various standalone + * tools (e.g. bls, bextract, bscan, ...) + */ +JCR *setup_jcr(const char *name, char *dev_name, BSR *bsr, + const char *VolumeName, int mode) +{ + DCR *dcr; + JCR *jcr = new_jcr(sizeof(JCR), my_free_jcr); + jcr->bsr = bsr; + jcr->VolSessionId = 1; + jcr->VolSessionTime = (uint32_t)time(NULL); + jcr->NumReadVolumes = 0; + jcr->NumWriteVolumes = 0; + jcr->JobId = 0; + jcr->set_JobType(JT_CONSOLE); + jcr->set_JobLevel(L_FULL); + jcr->JobStatus = JS_Terminated; + jcr->where = bstrdup(""); + jcr->job_name = get_pool_memory(PM_FNAME); + pm_strcpy(jcr->job_name, "Dummy.Job.Name"); + jcr->client_name = get_pool_memory(PM_FNAME); + pm_strcpy(jcr->client_name, "Dummy.Client.Name"); + bstrncpy(jcr->Job, name, sizeof(jcr->Job)); + jcr->fileset_name = get_pool_memory(PM_FNAME); + pm_strcpy(jcr->fileset_name, "Dummy.fileset.name"); + jcr->fileset_md5 = get_pool_memory(PM_FNAME); + pm_strcpy(jcr->fileset_md5, "Dummy.fileset.md5"); + + init_autochangers(); + create_volume_list(); + + dcr = setup_to_access_device(jcr, dev_name, VolumeName, mode); + if (!dcr) { + return NULL; + } + if (!bsr && VolumeName) { + bstrncpy(dcr->VolumeName, VolumeName, sizeof(dcr->VolumeName)); + } + bstrncpy(dcr->pool_name, "Default", sizeof(dcr->pool_name)); + bstrncpy(dcr->pool_type, "Backup", sizeof(dcr->pool_type)); + return jcr; +} /* * Setup device, jcr, and prepare to access device. * If the caller wants read access, acquire the device, otherwise, * the caller will do it. */ -DEVICE *setup_to_access_device(JCR *jcr, int read_access) +static DCR *setup_to_access_device(JCR *jcr, char *dev_name, + const char *VolumeName, int mode) { DEVICE *dev; - DEV_BLOCK *block; char *p; DEVRES *device; + DCR *dcr; + char VolName[MAX_NAME_LENGTH]; - jcr->VolumeName[0] = 0; - if (strncmp(jcr->dev_name, "/dev/", 5) != 0) { - /* Try stripping file part */ - p = jcr->dev_name + strlen(jcr->dev_name); - while (p >= jcr->dev_name && *p != '/') - p--; - if (*p == '/') { - strcpy(jcr->VolumeName, p+1); - *p = 0; + init_reservations_lock(); + + /* + * If no volume name already given and no bsr, and it is a file, + * try getting name from Filename + */ + if (VolumeName) { + bstrncpy(VolName, VolumeName, sizeof(VolName)); + if (strlen(VolumeName) >= MAX_NAME_LENGTH) { + Jmsg0(jcr, M_ERROR, 0, _("Volume name or names is too long. Please use a .bsr file.\n")); } + } else { + VolName[0] = 0; } + if (!jcr->bsr && VolName[0] == 0) { + if (strncmp(dev_name, "/dev/", 5) != 0) { + /* Try stripping file part */ + p = dev_name + strlen(dev_name); - if ((device=find_device_res(jcr->dev_name, read_access)) == NULL) { - Emsg2(M_FATAL, 0, _("Cannot find device %s in config file %s.\n"), - jcr->dev_name, configfile); - return NULL; + while (p >= dev_name && !IsPathSeparator(*p)) + p--; + if (IsPathSeparator(*p)) { + bstrncpy(VolName, p+1, sizeof(VolName)); + *p = 0; + } + } } - - dev = init_dev(NULL, device); - if (!dev || !open_device(dev)) { - Emsg1(M_FATAL, 0, _("Cannot open %s\n"), jcr->dev_name); + + if ((device=find_device_res(dev_name, mode)) == NULL) { + Jmsg2(jcr, M_FATAL, 0, _("Cannot find device \"%s\" in config file %s.\n"), + dev_name, configfile); return NULL; } - Dmsg0(90, "Device opened for read.\n"); - - block = new_block(dev); - create_vol_list(jcr); - - if (read_access) { - if (!acquire_device_for_read(jcr, dev, block)) { - Emsg0(M_ERROR, 0, dev->errmsg); - free_block(block); - return NULL; - } + dev = init_dev(jcr, device); + if (!dev) { + Jmsg1(jcr, M_FATAL, 0, _("Cannot init device %s\n"), dev_name); + return NULL; } - free_block(block); - return dev; -} + device->dev = dev; + jcr->dcr = dcr = new_dcr(jcr, NULL, dev); + if (VolName[0]) { + bstrncpy(dcr->VolumeName, VolName, sizeof(dcr->VolumeName)); + } + bstrncpy(dcr->dev_name, device->device_name, sizeof(dcr->dev_name)); + create_restore_volume_list(jcr); -/* - * Search for device resource that corresponds to - * device name on command line (or default). - * - * Returns: NULL on failure - * Device resource pointer on success - */ -DEVRES *find_device_res(char *device_name, int read_access) -{ - int found = 0; - DEVRES *device; - - LockRes(); - for (device=NULL; (device=(DEVRES *)GetNextRes(R_DEVICE, (RES *)device)); ) { - if (strcmp(device->device_name, device_name) == 0) { - found = 1; - break; + if (mode) { /* read only access? */ + Dmsg0(100, "Acquire device for read\n"); + if (!acquire_device_for_read(dcr)) { + return NULL; } - } - UnlockRes(); - if (!found) { - Pmsg2(0, _("Could not find device %s in config file %s.\n"), device_name, - configfile); - return NULL; + jcr->read_dcr = dcr; + } else { + if (!first_open_device(dcr)) { + Jmsg1(jcr, M_FATAL, 0, _("Cannot open %s\n"), dev->print_name()); + return NULL; + } + jcr->dcr = dcr; /* write dcr */ } - Pmsg2(0, _("Using device: %s for %s.\n"), device_name, - read_access?"reading":"writing"); - return device; + return dcr; } - /* - * Called here when freeing JCR so that we can get rid + * Called here when freeing JCR so that we can get rid * of "daemon" specific memory allocated. */ static void my_free_jcr(JCR *jcr) { - if (jcr->pool_name) { - free_pool_memory(jcr->pool_name); - jcr->pool_name = NULL; - } - if (jcr->pool_type) { - free_pool_memory(jcr->pool_type); - jcr->pool_type = NULL; - } if (jcr->job_name) { free_pool_memory(jcr->job_name); jcr->job_name = NULL; @@ -174,107 +218,93 @@ static void my_free_jcr(JCR *jcr) free_pool_memory(jcr->fileset_name); jcr->fileset_name = NULL; } - if (jcr->dev_name) { - free_pool_memory(jcr->dev_name); - jcr->dev_name = NULL; + if (jcr->fileset_md5) { + free_pool_memory(jcr->fileset_md5); + jcr->fileset_md5 = NULL; } if (jcr->VolList) { - free_vol_list(jcr); - } - + free_restore_volume_list(jcr); + } + if (jcr->dcr) { + free_dcr(jcr->dcr); + jcr->dcr = NULL; + } return; } + /* - * Setup a "daemon" JCR for the various standalone - * tools (e.g. bls, bextract, bscan, ...) + * Search for device resource that corresponds to + * device name on command line (or default). + * + * Returns: NULL on failure + * Device resource pointer on success */ -JCR *setup_jcr(char *name, char *device, BSR *bsr) +static DEVRES *find_device_res(char *device_name, int read_access) { - JCR *jcr = new_jcr(sizeof(JCR), my_free_jcr); - jcr->VolSessionId = 1; - jcr->VolSessionTime = (uint32_t)time(NULL); - jcr->bsr = bsr; - jcr->NumVolumes = 1; - jcr->pool_name = get_pool_memory(PM_FNAME); - strcpy(jcr->pool_name, "Default"); - jcr->pool_type = get_pool_memory(PM_FNAME); - strcpy(jcr->pool_type, "Backup"); - jcr->job_name = get_pool_memory(PM_FNAME); - strcpy(jcr->job_name, "Dummy.Job.Name"); - jcr->client_name = get_pool_memory(PM_FNAME); - strcpy(jcr->client_name, "Dummy.Client.Name"); - strcpy(jcr->Job, name); - jcr->fileset_name = get_pool_memory(PM_FNAME); - strcpy(jcr->fileset_name, "Dummy.fileset.name"); - jcr->JobId = 1; - jcr->JobType = JT_BACKUP; - jcr->JobLevel = L_FULL; - jcr->JobStatus = JS_Terminated; - jcr->dev_name = get_pool_memory(PM_FNAME); - pm_strcpy(&jcr->dev_name, device); - return jcr; + bool found = false; + DEVRES *device; + + Dmsg0(900, "Enter find_device_res\n"); + LockRes(); + foreach_res(device, R_DEVICE) { + Dmsg2(900, "Compare %s and %s\n", device->device_name, device_name); + if (strcmp(device->device_name, device_name) == 0) { + found = true; + break; + } + } + if (!found) { + /* Search for name of Device resource rather than archive name */ + if (device_name[0] == '"') { + int len = strlen(device_name); + bstrncpy(device_name, device_name+1, len+1); + len--; + if (len > 0) { + device_name[len-1] = 0; /* zap trailing " */ + } + } + foreach_res(device, R_DEVICE) { + Dmsg2(900, "Compare %s and %s\n", device->hdr.name, device_name); + if (strcmp(device->hdr.name, device_name) == 0) { + found = true; + break; + } + } + } + UnlockRes(); + if (!found) { + Pmsg2(0, _("Could not find device \"%s\" in config file %s.\n"), device_name, + configfile); + return NULL; + } + if (read_access) { + Pmsg1(0, _("Using device: \"%s\" for reading.\n"), device_name); + } + else { + Pmsg1(0, _("Using device: \"%s\" for writing.\n"), device_name); + } + return device; } /* * Device got an error, attempt to analyse it */ -void display_error_status(DEVICE *dev) +void display_tape_error_status(JCR *jcr, DEVICE *dev) { uint32_t status; - Emsg0(M_ERROR, 0, dev->errmsg); - status_dev(dev, &status); + status = status_dev(dev); Dmsg1(20, "Device status: %x\n", status); - if (status & MT_EOD) - Emsg0(M_ERROR_TERM, 0, _("Unexpected End of Data\n")); - else if (status & MT_EOT) - Emsg0(M_ERROR_TERM, 0, _("Unexpected End of Tape\n")); - else if (status & MT_EOF) - Emsg0(M_ERROR_TERM, 0, _("Unexpected End of File\n")); - else if (status & MT_DR_OPEN) - Emsg0(M_ERROR_TERM, 0, _("Tape Door is Open\n")); - else if (!(status & MT_ONLINE)) - Emsg0(M_ERROR_TERM, 0, _("Unexpected Tape is Off-line\n")); - else - Emsg2(M_ERROR_TERM, 0, _("Read error on Record Header %s: %s\n"), dev_name(dev), strerror(errno)); -} - - -extern char *getuser(uid_t uid); -extern char *getgroup(gid_t gid); - -void print_ls_output(char *fname, char *link, int type, struct stat *statp) -{ - char buf[1000]; - char ec1[30]; - char *p, *f; - int n; - - p = encode_mode(statp->st_mode, buf); - n = sprintf(p, " %2d ", (uint32_t)statp->st_nlink); - p += n; - n = sprintf(p, "%-8.8s %-8.8s", getuser(statp->st_uid), getgroup(statp->st_gid)); - p += n; - n = sprintf(p, "%8.8s ", edit_uint64(statp->st_size, ec1)); - p += n; - p = encode_time(statp->st_ctime, p); - *p++ = ' '; - *p++ = ' '; - /* Copy file name */ - for (f=fname; *f && (p-buf) < (int)sizeof(buf); ) - *p++ = *f++; - if (type == FT_LNK) { - *p++ = ' '; - *p++ = '-'; - *p++ = '>'; - *p++ = ' '; - /* Copy link name */ - for (f=link; *f && (p-buf) < (int)sizeof(buf); ) - *p++ = *f++; - } - *p++ = '\n'; - *p = 0; - fputs(buf, stdout); + if (status & BMT_EOD) + Jmsg(jcr, M_ERROR, 0, _("Unexpected End of Data\n")); + else if (status & BMT_EOT) + Jmsg(jcr, M_ERROR, 0, _("Unexpected End of Tape\n")); + else if (status & BMT_EOF) + Jmsg(jcr, M_ERROR, 0, _("Unexpected End of File\n")); + else if (status & BMT_DR_OPEN) + Jmsg(jcr, M_ERROR, 0, _("Tape Door is Open\n")); + else if (!(status & BMT_ONLINE)) + Jmsg(jcr, M_ERROR, 0, _("Unexpected Tape is Off-line\n")); }