X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fdird%2Fbsr.c;h=eefce24c7e5b882dbd498a82de4704f65632f1d4;hb=59f9844d56f5876903b17e0e10072464947d7596;hp=ae4317c452fac02771976d7dc3cad667c2796f41;hpb=8e1a4eeb2bdc80c9ab45a822a8da1cfa0ece1a6d;p=bacula%2Fbacula diff --git a/bacula/src/dird/bsr.c b/bacula/src/dird/bsr.c index ae4317c452..eefce24c7e 100644 --- a/bacula/src/dird/bsr.c +++ b/bacula/src/dird/bsr.c @@ -1,3 +1,30 @@ +/* + Bacula® - The Network Backup Solution + + Copyright (C) 2002-2010 Free Software Foundation Europe e.V. + + 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 + 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., 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. +*/ /* * * Bacula Director -- Bootstrap Record routines. @@ -7,22 +34,6 @@ * * Kern Sibbald, July MMII * - * Version $Id$ - */ - -/* - Copyright (C) 2002-2006 Kern Sibbald - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - version 2 as amended with additional clauses defined in the - file LICENSE in the main source directory. - - 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 - the file LICENSE for additional details. - */ #include "bacula.h" @@ -30,8 +41,6 @@ /* Forward referenced functions */ static uint32_t write_bsr(UAContext *ua, RESTORE_CTX &rx, FILE *fd); -void print_bsr(UAContext *ua, RBSR *bsr); - /* * Create new FileIndex entry for BSR @@ -84,7 +93,7 @@ static bool get_storage_device(char *device, char *storage) * We are called here once for each JobMedia record * for each Volume. */ -static uint32_t write_findex(UAContext *ua, RBSR_FINDEX *fi, +static uint32_t write_findex(RBSR_FINDEX *fi, int32_t FirstIndex, int32_t LastIndex, FILE *fd) { uint32_t count = 0; @@ -125,21 +134,6 @@ static bool is_volume_selected(RBSR_FINDEX *fi, } - -static void print_findex(UAContext *ua, RBSR_FINDEX *fi) -{ - bsendmsg(ua, "fi=0x%lx\n", fi); - for ( ; fi; fi=fi->next) { - if (fi->findex == fi->findex2) { - bsendmsg(ua, "FileIndex=%d\n", fi->findex); - Dmsg1(1000, "FileIndex=%d\n", fi->findex); - } else { - bsendmsg(ua, "FileIndex=%d-%d\n", fi->findex, fi->findex2); - Dmsg2(1000, "FileIndex=%d-%d\n", fi->findex, fi->findex2); - } - } -} - /* Create a new bootstrap record */ RBSR *new_bsr() { @@ -157,6 +151,9 @@ void free_bsr(RBSR *bsr) if (bsr->VolParams) { free(bsr->VolParams); } + if (bsr->fileregex) { + free(bsr->fileregex); + } next = bsr->next; free(bsr); } @@ -173,14 +170,18 @@ bool complete_bsr(UAContext *ua, RBSR *bsr) memset(&jr, 0, sizeof(jr)); jr.JobId = bsr->JobId; if (!db_get_job_record(ua->jcr, ua->db, &jr)) { - bsendmsg(ua, _("Unable to get Job record. ERR=%s\n"), db_strerror(ua->db)); + ua->error_msg(_("Unable to get Job record. ERR=%s\n"), db_strerror(ua->db)); return false; } bsr->VolSessionId = jr.VolSessionId; bsr->VolSessionTime = jr.VolSessionTime; + if (jr.JobFiles == 0) { /* zero files is OK, not an error, but */ + bsr->VolCount = 0; /* there are no volumes */ + continue; + } if ((bsr->VolCount=db_get_job_volume_parameters(ua->jcr, ua->db, bsr->JobId, &(bsr->VolParams))) == 0) { - bsendmsg(ua, _("Unable to get Job Volume Parameters. ERR=%s\n"), db_strerror(ua->db)); + ua->error_msg(_("Unable to get Job Volume Parameters. ERR=%s\n"), db_strerror(ua->db)); if (bsr->VolParams) { free(bsr->VolParams); bsr->VolParams = NULL; @@ -194,7 +195,7 @@ bool complete_bsr(UAContext *ua, RBSR *bsr) static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; static uint32_t uniq = 0; -void make_unique_restore_filename(UAContext *ua, POOLMEM **fname) +static void make_unique_restore_filename(UAContext *ua, POOL_MEM &fname) { JCR *jcr = ua->jcr; int i = find_arg_with_value(ua, "bootstrap"); @@ -211,7 +212,7 @@ void make_unique_restore_filename(UAContext *ua, POOLMEM **fname) if (jcr->RestoreBootstrap) { free(jcr->RestoreBootstrap); } - jcr->RestoreBootstrap = bstrdup(*fname); + jcr->RestoreBootstrap = bstrdup(fname.c_str()); } /* @@ -220,78 +221,173 @@ void make_unique_restore_filename(UAContext *ua, POOLMEM **fname) uint32_t write_bsr_file(UAContext *ua, RESTORE_CTX &rx) { FILE *fd; - POOLMEM *fname = get_pool_memory(PM_MESSAGE); + POOL_MEM fname(PM_MESSAGE); uint32_t count = 0;; bool err; - char *p; - JobId_t JobId; - make_unique_restore_filename(ua, &fname); - fd = fopen(fname, "w+b"); + make_unique_restore_filename(ua, fname); + fd = fopen(fname.c_str(), "w+b"); if (!fd) { berrno be; - bsendmsg(ua, _("Unable to create bootstrap file %s. ERR=%s\n"), - fname, be.strerror()); + ua->error_msg(_("Unable to create bootstrap file %s. ERR=%s\n"), + fname.c_str(), be.bstrerror()); goto bail_out; } /* Write them to file */ count = write_bsr(ua, rx, fd); err = ferror(fd); fclose(fd); + if (count == 0) { + ua->info_msg(_("No files found to read. No bootstrap file written.\n")); + goto bail_out; + } if (err) { - bsendmsg(ua, _("Error writing bsr file.\n")); + ua->error_msg(_("Error writing bsr file.\n")); count = 0; goto bail_out; } + ua->send_msg(_("Bootstrap records written to %s\n"), fname.c_str()); - bsendmsg(ua, _("Bootstrap records written to %s\n"), fname); + if (debug_level >= 10) { + print_bsr(ua, rx); + } - /* Tell the user what he will need to mount */ - bsendmsg(ua, "\n"); - bsendmsg(ua, _("The job will require the following Volumes:\n")); - /* Create Unique list of Volumes using prompt list */ - start_prompt(ua, ""); - if (*rx.JobIds) { - /* Ensure that the volumes are printed in JobId order */ - for (p=rx.JobIds; get_next_jobid_from_list(&p, &JobId) > 0; ) { - for (RBSR *nbsr=rx.bsr; nbsr; nbsr=nbsr->next) { - if (JobId != nbsr->JobId) { - continue; +bail_out: + return count; +} + +static void display_vol_info(UAContext *ua, RESTORE_CTX &rx, JobId_t JobId) +{ + POOL_MEM volmsg(PM_MESSAGE); + char Device[MAX_NAME_LENGTH]; + char online; + RBSR *bsr; + + for (bsr=rx.bsr; bsr; bsr=bsr->next) { + if (JobId && JobId != bsr->JobId) { + continue; + } + + for (int i=0; i < bsr->VolCount; i++) { + if (bsr->VolParams[i].VolumeName[0]) { + if (!get_storage_device(Device, bsr->VolParams[i].Storage)) { + Device[0] = 0; } - for (int i=0; i < nbsr->VolCount; i++) { - if (nbsr->VolParams[i].VolumeName[0]) { - add_prompt(ua, nbsr->VolParams[i].VolumeName); - } + if (bsr->VolParams[i].InChanger && bsr->VolParams[i].Slot) { + online = '*'; + } else { + online = ' '; } + Mmsg(volmsg, "%c%-25.25s %-25.25s %-25.25s", + online, bsr->VolParams[i].VolumeName, + bsr->VolParams[i].Storage, Device); + add_prompt(ua, volmsg.c_str()); } } - } else { + } +} + +void display_bsr_info(UAContext *ua, RESTORE_CTX &rx) +{ + char *p; + JobId_t JobId; + + /* Tell the user what he will need to mount */ + ua->send_msg("\n"); + ua->send_msg(_("The job will require the following\n" + " Volume(s) Storage(s) SD Device(s)\n" + "===========================================================================\n")); + /* Create Unique list of Volumes using prompt list */ + start_prompt(ua, ""); + if (*rx.JobIds == 0) { /* Print Volumes in any order */ - for (RBSR *nbsr=rx.bsr; nbsr; nbsr=nbsr->next) { - for (int i=0; i < nbsr->VolCount; i++) { - if (nbsr->VolParams[i].VolumeName[0]) { - add_prompt(ua, nbsr->VolParams[i].VolumeName); - } - } + display_vol_info(ua, rx, 0); + } else { + /* Ensure that the volumes are printed in JobId order */ + for (p=rx.JobIds; get_next_jobid_from_list(&p, &JobId) > 0; ) { + display_vol_info(ua, rx, JobId); } } for (int i=0; i < ua->num_prompts; i++) { - bsendmsg(ua, " %s\n", ua->prompt[i]); + ua->send_msg(" %s\n", ua->prompt[i]); free(ua->prompt[i]); } if (ua->num_prompts == 0) { - bsendmsg(ua, _("No Volumes found to restore.\n")); - count = 0; + ua->send_msg(_("No Volumes found to restore.\n")); + } else { + ua->send_msg(_("\nVolumes marked with \"*\" are online.\n")); } ua->num_prompts = 0; - bsendmsg(ua, "\n"); + ua->send_msg("\n"); -bail_out: - free_pool_memory(fname); - return count; + return; } +/* + * Write bsr data for a single bsr record + */ +static uint32_t write_bsr_item(RBSR *bsr, UAContext *ua, + RESTORE_CTX &rx, FILE *fd, bool &first, uint32_t &LastIndex) +{ + char ed1[50], ed2[50]; + uint32_t count = 0; + uint32_t total_count = 0; + char device[MAX_NAME_LENGTH]; + + /* + * For a given volume, loop over all the JobMedia records. + * VolCount is the number of JobMedia records. + */ + for (int i=0; i < bsr->VolCount; i++) { + if (!is_volume_selected(bsr->fi, bsr->VolParams[i].FirstIndex, + bsr->VolParams[i].LastIndex)) { + bsr->VolParams[i].VolumeName[0] = 0; /* zap VolumeName */ + continue; + } + if (!rx.store) { + find_storage_resource(ua, rx, bsr->VolParams[i].Storage, + bsr->VolParams[i].MediaType); + } + fprintf(fd, "Storage=\"%s\"\n", bsr->VolParams[i].Storage); + fprintf(fd, "Volume=\"%s\"\n", bsr->VolParams[i].VolumeName); + fprintf(fd, "MediaType=\"%s\"\n", bsr->VolParams[i].MediaType); + if (bsr->fileregex) { + fprintf(fd, "FileRegex=%s\n", bsr->fileregex); + } + if (get_storage_device(device, bsr->VolParams[i].Storage)) { + fprintf(fd, "Device=\"%s\"\n", device); + } + if (bsr->VolParams[i].Slot > 0) { + fprintf(fd, "Slot=%d\n", bsr->VolParams[i].Slot); + } + fprintf(fd, "VolSessionId=%u\n", bsr->VolSessionId); + fprintf(fd, "VolSessionTime=%u\n", bsr->VolSessionTime); + fprintf(fd, "VolAddr=%s-%s\n", edit_uint64(bsr->VolParams[i].StartAddr, ed1), + edit_uint64(bsr->VolParams[i].EndAddr, ed2)); +// Dmsg2(100, "bsr VolParam FI=%u LI=%u\n", +// bsr->VolParams[i].FirstIndex, bsr->VolParams[i].LastIndex); + + count = write_findex(bsr->fi, bsr->VolParams[i].FirstIndex, + bsr->VolParams[i].LastIndex, fd); + if (count) { + fprintf(fd, "Count=%u\n", count); + } + total_count += count; + /* If the same file is present on two tapes or in two files + * on a tape, it is a continuation, and should not be treated + * twice in the totals. + */ + if (!first && LastIndex == bsr->VolParams[i].FirstIndex) { + total_count--; + } + first = false; + LastIndex = bsr->VolParams[i].LastIndex; + } + return total_count; +} + + /* * Here we actually write out the details of the bsr file. * Note, there is one bsr for each JobId, but the bsr may @@ -302,147 +398,31 @@ bail_out: */ static uint32_t write_bsr(UAContext *ua, RESTORE_CTX &rx, FILE *fd) { - uint32_t count = 0; - uint32_t total_count = 0; - uint32_t LastIndex = 0; bool first = true; + uint32_t LastIndex = 0; + uint32_t total_count = 0; char *p; JobId_t JobId; - char device[MAX_NAME_LENGTH]; RBSR *bsr; if (*rx.JobIds == 0) { for (bsr=rx.bsr; bsr; bsr=bsr->next) { - /* - * For a given volume, loop over all the JobMedia records. - * VolCount is the number of JobMedia records. - */ - for (int i=0; i < bsr->VolCount; i++) { - if (!is_volume_selected(bsr->fi, bsr->VolParams[i].FirstIndex, - bsr->VolParams[i].LastIndex)) { - bsr->VolParams[i].VolumeName[0] = 0; /* zap VolumeName */ - continue; - } - fprintf(fd, "Volume=\"%s\"\n", bsr->VolParams[i].VolumeName); - fprintf(fd, "MediaType=\"%s\"\n", bsr->VolParams[i].MediaType); - if (get_storage_device(device, bsr->VolParams[i].Storage)) { - fprintf(fd, "Device=\"%s\"\n", device); - } - if (bsr->VolParams[i].Slot > 0) { - fprintf(fd, "Slot=%d\n", bsr->VolParams[i].Slot); - } - fprintf(fd, "VolSessionId=%u\n", bsr->VolSessionId); - fprintf(fd, "VolSessionTime=%u\n", bsr->VolSessionTime); - if (bsr->VolParams[i].StartFile == bsr->VolParams[i].EndFile) { - fprintf(fd, "VolFile=%u\n", bsr->VolParams[i].StartFile); - } else { - fprintf(fd, "VolFile=%u-%u\n", bsr->VolParams[i].StartFile, - bsr->VolParams[i].EndFile); - } - if (bsr->VolParams[i].StartBlock == bsr->VolParams[i].EndBlock) { - fprintf(fd, "VolBlock=%u\n", bsr->VolParams[i].StartBlock); - } else { - fprintf(fd, "VolBlock=%u-%u\n", bsr->VolParams[i].StartBlock, - bsr->VolParams[i].EndBlock); - } - // Dmsg2(100, "bsr VolParam FI=%u LI=%u\n", - // bsr->VolParams[i].FirstIndex, bsr->VolParams[i].LastIndex); - - count = write_findex(ua, bsr->fi, bsr->VolParams[i].FirstIndex, - bsr->VolParams[i].LastIndex, fd); - if (count) { - fprintf(fd, "Count=%u\n", count); - } - total_count += count; - /* If the same file is present on two tapes or in two files - * on a tape, it is a continuation, and should not be treated - * twice in the totals. - */ - if (!first && LastIndex == bsr->VolParams[i].FirstIndex) { - total_count--; - } - first = false; - LastIndex = bsr->VolParams[i].LastIndex; - } + total_count += write_bsr_item(bsr, ua, rx, fd, first, LastIndex); } return total_count; } for (p=rx.JobIds; get_next_jobid_from_list(&p, &JobId) > 0; ) { for (bsr=rx.bsr; bsr; bsr=bsr->next) { - if (JobId != bsr->JobId) { - continue; - } - /* - * For a given volume, loop over all the JobMedia records. - * VolCount is the number of JobMedia records. - */ - for (int i=0; i < bsr->VolCount; i++) { - if (!is_volume_selected(bsr->fi, bsr->VolParams[i].FirstIndex, - bsr->VolParams[i].LastIndex)) { - bsr->VolParams[i].VolumeName[0] = 0; /* zap VolumeName */ - continue; - } - fprintf(fd, "Volume=\"%s\"\n", bsr->VolParams[i].VolumeName); - fprintf(fd, "MediaType=\"%s\"\n", bsr->VolParams[i].MediaType); - if (get_storage_device(device, bsr->VolParams[i].Storage)) { - fprintf(fd, "Device=\"%s\"\n", device); - } - if (bsr->VolParams[i].Slot > 0) { - fprintf(fd, "Slot=%d\n", bsr->VolParams[i].Slot); - } - fprintf(fd, "VolSessionId=%u\n", bsr->VolSessionId); - fprintf(fd, "VolSessionTime=%u\n", bsr->VolSessionTime); - if (bsr->VolParams[i].StartFile == bsr->VolParams[i].EndFile) { - fprintf(fd, "VolFile=%u\n", bsr->VolParams[i].StartFile); - } else { - fprintf(fd, "VolFile=%u-%u\n", bsr->VolParams[i].StartFile, - bsr->VolParams[i].EndFile); - } - if (bsr->VolParams[i].StartBlock == bsr->VolParams[i].EndBlock) { - fprintf(fd, "VolBlock=%u\n", bsr->VolParams[i].StartBlock); - } else { - fprintf(fd, "VolBlock=%u-%u\n", bsr->VolParams[i].StartBlock, - bsr->VolParams[i].EndBlock); - } - // Dmsg2(100, "bsr VolParam FI=%u LI=%u\n", - // bsr->VolParams[i].FirstIndex, bsr->VolParams[i].LastIndex); - - count = write_findex(ua, bsr->fi, bsr->VolParams[i].FirstIndex, - bsr->VolParams[i].LastIndex, fd); - if (count) { - fprintf(fd, "Count=%u\n", count); - } - total_count += count; - /* If the same file is present on two tapes or in two files - * on a tape, it is a continuation, and should not be treated - * twice in the totals. - */ - if (!first && LastIndex == bsr->VolParams[i].FirstIndex) { - total_count--; - } - first = false; - LastIndex = bsr->VolParams[i].LastIndex; + if (JobId == bsr->JobId) { + total_count += write_bsr_item(bsr, ua, rx, fd, first, LastIndex); } } } return total_count; } -void print_bsr(UAContext *ua, RBSR *bsr) +void print_bsr(UAContext *ua, RESTORE_CTX &rx) { - for ( ; bsr; bsr=bsr->next) { - for (int i=0; i < bsr->VolCount; i++) { - bsendmsg(ua, "Volume=\"%s\"\n", bsr->VolParams[i].VolumeName); - bsendmsg(ua, "MediaType\"%s\"\n", bsr->VolParams[i].MediaType); - bsendmsg(ua, "VolSessionId=%u\n", bsr->VolSessionId); - bsendmsg(ua, "VolSessionTime=%u\n", bsr->VolSessionTime); - bsendmsg(ua, "VolFile=%u-%u\n", bsr->VolParams[i].StartFile, - bsr->VolParams[i].EndFile); - bsendmsg(ua, "VolBlock=%u-%u\n", bsr->VolParams[i].StartBlock, - bsr->VolParams[i].EndBlock); - print_findex(ua, bsr->fi); - } - print_bsr(ua, bsr->next); - } + write_bsr(ua, rx, stdout); } @@ -452,6 +432,7 @@ void print_bsr(UAContext *ua, RBSR *bsr) * Add a FileIndex to the list of BootStrap records. * Here we are only dealing with JobId's and the FileIndexes * associated with those JobIds. + * We expect that JobId, FileIndex are sorted ascending. */ void add_findex(RBSR *bsr, uint32_t JobId, int32_t findex) { @@ -576,8 +557,15 @@ void add_findex_all(RBSR *bsr, uint32_t JobId) /* Add new JobId at end of chain */ for (nbsr=bsr; nbsr->next; nbsr=nbsr->next) { } + nbsr->next = new_bsr(); nbsr->next->JobId = JobId; + + /* If we use regexp to restore, set it for each jobid */ + if (bsr->fileregex) { + nbsr->next->fileregex = bstrdup(bsr->fileregex); + } + nbsr->next->fi = new_findex(); nbsr->next->fi->findex = 1; nbsr->next->fi->findex2 = INT32_MAX;