X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;ds=sidebyside;f=bacula%2Fsrc%2Fdird%2Fbsr.c;h=61de96ddfe77a622ae7ef3e10a3020e5ad7333c0;hb=10cfd798ced2d27f61ead2de6fe9b1bcc8e3468d;hp=f8b75989309318bdbeeaa6fe8c076fc1c8272710;hpb=9ceb97149541fc42d33514740d94c2009f18ddf6;p=bacula%2Fbacula diff --git a/bacula/src/dird/bsr.c b/bacula/src/dird/bsr.c index f8b7598930..61de96ddfe 100644 --- a/bacula/src/dird/bsr.c +++ b/bacula/src/dird/bsr.c @@ -1,29 +1,20 @@ /* - Bacula® - The Network Backup Solution - - Copyright (C) 2002-2008 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(R) - The Network Backup Solution + + Copyright (C) 2000-2018 Kern Sibbald + + The original author of Bacula is Kern Sibbald, with contributions + from many others, a complete list can be found in the file AUTHORS. + + You may use this file and others of this release according to the + license defined in the LICENSE file, which includes the Affero General + Public License, v3.0 ("AGPLv3") and some additional permissions and + terms pursuant to its AGPLv3 Section 7. + + This notice must be preserved when any source code is + conveyed and/or propagated. + + Bacula(R) is a registered trademark of Kern Sibbald. */ /* * @@ -34,7 +25,6 @@ * * Kern Sibbald, July MMII * - * Version $Id$ */ #include "bacula.h" @@ -53,17 +43,7 @@ RBSR_FINDEX *new_findex() return fi; } -/* Free all BSR FileIndex entries */ -static void free_findex(RBSR_FINDEX *fi) -{ - RBSR_FINDEX *next; - for ( ; fi; fi=next) { - next = fi->next; - free(fi); - } -} - -/* +/* * Get storage device name from Storage resource */ static bool get_storage_device(char *device, char *storage) @@ -72,7 +52,7 @@ static bool get_storage_device(char *device, char *storage) if (storage[0] == 0) { return false; } - store = (STORE *)GetResWithName(R_STORAGE, storage); + store = (STORE *)GetResWithName(R_STORAGE, storage); if (!store) { return false; } @@ -94,17 +74,48 @@ 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(RBSR_FINDEX *fi, +static uint32_t write_findex(rblist *fi_list, int32_t FirstIndex, int32_t LastIndex, FILE *fd) { + RBSR_FINDEX *fi; uint32_t count = 0; - for ( ; fi; fi=fi->next) { + + fi = (RBSR_FINDEX *) fi_list->first(); + while (fi) { int32_t findex, findex2; - if ((fi->findex >= FirstIndex && fi->findex <= LastIndex) || - (fi->findex2 >= FirstIndex && fi->findex2 <= LastIndex) || - (fi->findex < FirstIndex && fi->findex2 > LastIndex)) { - findex = fi->findex < FirstIndex ? FirstIndex : fi->findex; - findex2 = fi->findex2 > LastIndex ? LastIndex : fi->findex2; + + /* fi points to the first item of the list, or the next item that is not + * contigous to the previous group + */ + findex = fi->findex; + findex2 = fi->findex2; + + /* Sometime (with the restore command for example), the fi_list can + * contain false gaps (1-10, 11-11, 12-20 instead of 1-20). The for loop + * is here to merge blocks and reduce the bsr output. The next while(fi) + * iteration will use the next_fi that points to the last merged element. + */ + RBSR_FINDEX *next_fi; + for (next_fi = (RBSR_FINDEX*) fi_list->next(fi); + next_fi && next_fi->findex == (findex2+1); + next_fi = (RBSR_FINDEX *) fi_list->next(next_fi)) + { + findex2 = next_fi->findex2; + } + + /* next_fi points after the current block (or to the end of the list), so + * the next while() iteration will use the next value + */ + fi = next_fi; + + /* We look if the current FI block match the volume information */ + if ((findex >= FirstIndex && findex <= LastIndex) || + (findex2 >= FirstIndex && findex2 <= LastIndex) || + (findex < FirstIndex && findex2 > LastIndex)) { + + findex = findex < FirstIndex ? FirstIndex : findex; + findex2 = findex2 > LastIndex ? LastIndex : findex2; + if (findex == findex2) { fprintf(fd, "FileIndex=%d\n", findex); count++; @@ -114,6 +125,7 @@ static uint32_t write_findex(RBSR_FINDEX *fi, } } } + return count; } @@ -121,10 +133,11 @@ static uint32_t write_findex(RBSR_FINDEX *fi, * Find out if Volume defined with FirstIndex and LastIndex * falls within the range of selected files in the bsr. */ -static bool is_volume_selected(RBSR_FINDEX *fi, +static bool is_volume_selected(rblist *fi_list, int32_t FirstIndex, int32_t LastIndex) { - for ( ; fi; fi=fi->next) { + RBSR_FINDEX *fi; + foreach_rblist(fi, fi_list) { if ((fi->findex >= FirstIndex && fi->findex <= LastIndex) || (fi->findex2 >= FirstIndex && fi->findex2 <= LastIndex) || (fi->findex < FirstIndex && fi->findex2 > LastIndex)) { @@ -138,35 +151,40 @@ static bool is_volume_selected(RBSR_FINDEX *fi, /* Create a new bootstrap record */ RBSR *new_bsr() { + RBSR_FINDEX *fi=NULL; RBSR *bsr = (RBSR *)bmalloc(sizeof(RBSR)); memset(bsr, 0, sizeof(RBSR)); + bsr->fi_list = New(rblist(fi, &fi->link)); return bsr; } /* Free the entire BSR */ -void free_bsr(RBSR *bsr) +void free_bsr(rblist *bsr_list) { - RBSR *next; - for ( ; bsr; bsr=next) { - free_findex(bsr->fi); + RBSR *bsr; + foreach_rblist(bsr, bsr_list) { + delete bsr->fi_list; if (bsr->VolParams) { free(bsr->VolParams); } if (bsr->fileregex) { free(bsr->fileregex); } - next = bsr->next; - free(bsr); + if (bsr->m_fi) { + free(bsr->m_fi); + } } + delete bsr_list; } /* * Complete the BSR by filling in the VolumeName and * VolSessionId and VolSessionTime using the JobId */ -bool complete_bsr(UAContext *ua, RBSR *bsr) +bool complete_bsr(UAContext *ua, rblist *bsr_list) { - for ( ; bsr; bsr=bsr->next) { + RBSR *bsr; + foreach_rblist(bsr, bsr_list) { JOB_DBR jr; memset(&jr, 0, sizeof(jr)); jr.JobId = bsr->JobId; @@ -176,6 +194,10 @@ bool complete_bsr(UAContext *ua, RBSR *bsr) } 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) { ua->error_msg(_("Unable to get Job Volume Parameters. ERR=%s\n"), db_strerror(ua->db)); @@ -197,7 +219,7 @@ static void make_unique_restore_filename(UAContext *ua, POOL_MEM &fname) JCR *jcr = ua->jcr; int i = find_arg_with_value(ua, "bootstrap"); if (i >= 0) { - Mmsg(fname, "%s", ua->argv[i]); + Mmsg(fname, "%s", ua->argv[i]); jcr->unlink_bsr = false; } else { P(mutex); @@ -223,7 +245,7 @@ uint32_t write_bsr_file(UAContext *ua, RESTORE_CTX &rx) bool err; make_unique_restore_filename(ua, fname); - fd = fopen(fname.c_str(), "w+b"); + fd = bfopen(fname.c_str(), "w+b"); if (!fd) { berrno be; ua->error_msg(_("Unable to create bootstrap file %s. ERR=%s\n"), @@ -244,9 +266,7 @@ uint32_t write_bsr_file(UAContext *ua, RESTORE_CTX &rx) goto bail_out; } - ua->send_msg(_("Bootstrap records written to %s\n"), fname.c_str()); - - if (debug_level >= 10) { + if (chk_dbglvl(10)) { print_bsr(ua, rx); } @@ -261,7 +281,7 @@ static void display_vol_info(UAContext *ua, RESTORE_CTX &rx, JobId_t JobId) char online; RBSR *bsr; - for (bsr=rx.bsr; bsr; bsr=bsr->next) { + foreach_rblist(bsr, rx.bsr_list) { if (JobId && JobId != bsr->JobId) { continue; } @@ -276,10 +296,9 @@ static void display_vol_info(UAContext *ua, RESTORE_CTX &rx, JobId_t JobId) } else { online = ' '; } - Mmsg(volmsg, "%c%-25.25s %-25.25s %-25.25s", + Mmsg(volmsg, "%c%-25s %-25s %-25s", online, bsr->VolParams[i].VolumeName, - bsr->VolParams[i].Storage, - Device); + bsr->VolParams[i].Storage, Device); add_prompt(ua, volmsg.c_str()); } } @@ -293,7 +312,7 @@ void display_bsr_info(UAContext *ua, RESTORE_CTX &rx) /* Tell the user what he will need to mount */ ua->send_msg("\n"); - ua->send_msg(_("The job will require the following\n" + ua->send_msg(_("The Job will require the following (*=>InChanger):\n" " Volume(s) Storage(s) SD Device(s)\n" "===========================================================================\n")); /* Create Unique list of Volumes using prompt list */ @@ -310,11 +329,12 @@ void display_bsr_info(UAContext *ua, RESTORE_CTX &rx) for (int i=0; i < ua->num_prompts; i++) { ua->send_msg(" %s\n", ua->prompt[i]); free(ua->prompt[i]); + if (ua->unique[i]) free(ua->unique[i]); } if (ua->num_prompts == 0) { ua->send_msg(_("No Volumes found to restore.\n")); } else { - ua->send_msg(_("\nVolumes marked with \"*\" are online.\n")); + ua->send_msg(_("\nVolumes marked with \"*\" are in the Autochanger.\n")); } ua->num_prompts = 0; ua->send_msg("\n"); @@ -325,7 +345,7 @@ void display_bsr_info(UAContext *ua, RESTORE_CTX &rx) /* * Write bsr data for a single bsr record */ -static uint32_t write_bsr_item(RBSR *bsr, UAContext *ua, +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]; @@ -338,7 +358,7 @@ static uint32_t write_bsr_item(RBSR *bsr, UAContext *ua, * 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, + if (!is_volume_selected(bsr->fi_list, bsr->VolParams[i].FirstIndex, bsr->VolParams[i].LastIndex)) { bsr->VolParams[i].VolumeName[0] = 0; /* zap VolumeName */ continue; @@ -363,10 +383,10 @@ static uint32_t write_bsr_item(RBSR *bsr, UAContext *ua, 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); + 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, + count = write_findex(bsr->fi_list, bsr->VolParams[i].FirstIndex, bsr->VolParams[i].LastIndex, fd); if (count) { fprintf(fd, "Count=%u\n", count); @@ -390,7 +410,7 @@ static uint32_t write_bsr_item(RBSR *bsr, UAContext *ua, * Here we actually write out the details of the bsr file. * Note, there is one bsr for each JobId, but the bsr may * have multiple volumes, which have been entered in the - * order they were written. + * order they were written. * The bsrs must be written out in the order the JobIds * are found in the jobid list. */ @@ -403,13 +423,13 @@ static uint32_t write_bsr(UAContext *ua, RESTORE_CTX &rx, FILE *fd) JobId_t JobId; RBSR *bsr; if (*rx.JobIds == 0) { - for (bsr=rx.bsr; bsr; bsr=bsr->next) { + foreach_rblist(bsr, rx.bsr_list) { 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) { + foreach_rblist(bsr, rx.bsr_list) { if (JobId == bsr->JobId) { total_count += write_bsr_item(bsr, ua, rx, fd, first, LastIndex); } @@ -423,105 +443,123 @@ void print_bsr(UAContext *ua, RESTORE_CTX &rx) write_bsr(ua, rx, stdout); } +static int search_rbsr(void *elt1, void *elt2) +{ + RBSR *bsr1 = (RBSR *)elt1; + RBSR *bsr = (RBSR *)elt2; + + /* We might replace by a simple JobId - JobId */ + if (bsr->JobId == bsr1->JobId) { + return 0; + + } else if (bsr->JobId < bsr1->JobId) { + return 1; + } + + return -1; +} + +static int search_fi(void *elt1, void *elt2) +{ + RBSR_FINDEX *f1 = (RBSR_FINDEX *) elt1; + RBSR_FINDEX *f2 = (RBSR_FINDEX *) elt2; + + if (f1->findex == (f2->findex - 1)) { + return 0; + + } else if (f1->findex2 == (f2->findex2 + 1)) { + return 0; + + } else if (f1->findex >= f2->findex && f1->findex2 <= f2->findex2) { + return 0; + } + + return (f1->findex > f2->findex) ? 1 : -1; +} + +rblist *create_bsr_list(uint32_t JobId, int findex, int findex2) +{ + RBSR *bsr = NULL; + RBSR_FINDEX *fi = NULL; + rblist *bsr_list = New(rblist(bsr, &bsr->link)); + + bsr = new_bsr(); + bsr->JobId = JobId; + + bsr_list->insert(bsr, search_rbsr); + + fi = new_findex(); + fi->findex = findex; + fi->findex2 = findex2; + bsr->fi_list->insert(fi, search_fi); + return bsr_list; +} /* * 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. + * + * When doing restore from tree, FileIndex are not sorted, so it can + * create gaps. */ -void add_findex(RBSR *bsr, uint32_t JobId, int32_t findex) +void add_findex(rblist *bsr_list, uint32_t JobId, int32_t findex) { - RBSR *nbsr; - RBSR_FINDEX *fi, *lfi; + RBSR *bsr, bsr2; + RBSR_FINDEX *fi, *nfi; if (findex == 0) { return; /* probably a dummy directory */ } - if (bsr->fi == NULL) { /* if no FI add one */ - /* This is the first FileIndex item in the chain */ - bsr->fi = new_findex(); - bsr->JobId = JobId; - bsr->fi->findex = findex; - bsr->fi->findex2 = findex; - return; - } + bsr2.JobId = JobId; /* Walk down list of bsrs until we find the JobId */ - if (bsr->JobId != JobId) { - for (nbsr=bsr->next; nbsr; nbsr=nbsr->next) { - if (nbsr->JobId == JobId) { - bsr = nbsr; - break; - } - } + bsr = (RBSR *)bsr_list->search(&bsr2, search_rbsr); - if (!nbsr) { /* Must add new JobId */ - /* Add new JobId at end of chain */ - for (nbsr=bsr; nbsr->next; nbsr=nbsr->next) - { } - nbsr->next = new_bsr(); - nbsr->next->JobId = JobId; - nbsr->next->fi = new_findex(); - nbsr->next->fi->findex = findex; - nbsr->next->fi->findex2 = findex; - return; - } + /* The list is empty, or the JobId is not already in, + * Must add new JobId + */ + if (!bsr) { + bsr = new_bsr(); + bsr->JobId = JobId; + bsr_list->insert(bsr, search_rbsr); } - /* - * At this point, bsr points to bsr containing this JobId, - * and we are sure that there is at least one fi record. - */ - lfi = fi = bsr->fi; - /* Check if this findex is smaller than first item */ - if (findex < fi->findex) { - if ((findex+1) == fi->findex) { - fi->findex = findex; /* extend down */ - return; - } - fi = new_findex(); /* yes, insert before first item */ - fi->findex = findex; - fi->findex2 = findex; - fi->next = lfi; - bsr->fi = fi; - return; + if (bsr->m_fi) { + fi = bsr->m_fi; + + } else { + fi = bsr->m_fi = new_findex(); } - /* Walk down fi chain and find where to insert insert new FileIndex */ - for ( ; fi; fi=fi->next) { - if (findex == (fi->findex2 + 1)) { /* extend up */ - RBSR_FINDEX *nfi; - fi->findex2 = findex; - /* - * If the following record contains one higher, merge its - * file index by extending it up. - */ - if (fi->next && ((findex+1) == fi->next->findex)) { - nfi = fi->next; - fi->findex2 = nfi->findex2; - fi->next = nfi->next; - free(nfi); - } - return; - } - if (findex < fi->findex) { /* add before */ - if ((findex+1) == fi->findex) { - fi->findex = findex; - return; - } - break; + + fi->findex = findex; + fi->findex2 = findex; + + Dmsg1(1000, "Trying to insert %ld\n", findex); + /* try to insert our fi */ + nfi = (RBSR_FINDEX*) bsr->fi_list->insert((void *)fi, search_fi); + + /* We found an existing one, extend it */ + if (nfi != fi) { + if (findex == (nfi->findex2 + 1)) { + Dmsg2(1000, "Extend %ld-%ld\n", nfi->findex, findex); + nfi->findex2 = findex; + + } else if (findex == (nfi->findex - 1)) { + Dmsg2(1000, "Extend %ld-%ld\n", findex, nfi->findex2); + nfi->findex = findex; + + } else { + Dmsg2(1000, "Found the same values? %ld-%ld\n", nfi->findex, nfi->findex2); } - lfi = fi; + + } else { + Dmsg2(1000, "Inserted %ld-%ld\n", fi->findex, fi->findex2); + bsr->m_fi = NULL; /* comsumed */ } - /* Add to last place found */ - fi = new_findex(); - fi->findex = findex; - fi->findex2 = findex; - fi->next = lfi->next; - lfi->next = fi; - return; } /* @@ -529,47 +567,194 @@ void add_findex(RBSR *bsr, uint32_t JobId, int32_t findex) * Here we are only dealing with JobId's and the FileIndexes * associated with those JobIds. */ -void add_findex_all(RBSR *bsr, uint32_t JobId) +void add_findex_all(rblist *bsr_list, uint32_t JobId, const char *fileregex) { - RBSR *nbsr; + RBSR *bsr, bsr2; RBSR_FINDEX *fi; - if (bsr->fi == NULL) { /* if no FI add one */ - /* This is the first FileIndex item in the chain */ - bsr->fi = new_findex(); - bsr->JobId = JobId; - bsr->fi->findex = 1; - bsr->fi->findex2 = INT32_MAX; - return; - } + bsr2.JobId = JobId; /* Walk down list of bsrs until we find the JobId */ - if (bsr->JobId != JobId) { - for (nbsr=bsr->next; nbsr; nbsr=nbsr->next) { - if (nbsr->JobId == JobId) { - bsr = nbsr; - break; - } - } + bsr = (RBSR *)bsr_list->search(&bsr2, search_rbsr); + + if (!bsr) { /* Must add new JobId */ + fi = new_findex(); + fi->findex = 1; + fi->findex2 = INT32_MAX; + + bsr = new_bsr(); + bsr->JobId = JobId; + bsr->fi_list->insert(fi, search_fi); + bsr_list->insert(bsr, search_rbsr); - if (!nbsr) { /* Must add new JobId */ - /* Add new JobId at end of chain */ - for (nbsr=bsr; nbsr->next; nbsr=nbsr->next) - { } - nbsr->next = new_bsr(); - nbsr->next->JobId = JobId; - nbsr->next->fi = new_findex(); - nbsr->next->fi->findex = 1; - nbsr->next->fi->findex2 = INT32_MAX; - return; + if (fileregex) { + /* If we use regexp to restore, set it for each jobid */ + bsr->fileregex = bstrdup(fileregex); } + return; } /* * At this point, bsr points to bsr containing this JobId, - * and we are sure that there is at least one fi record. */ - fi = bsr->fi; + fi = new_findex(); fi->findex = 1; fi->findex2 = INT32_MAX; + bsr->fi_list->insert(fi, search_fi); + return; +} + +#ifdef needed +/* Foreach files in currrent list, send "/path/fname\0LStat\0MD5\0Delta" to FD + * row[0]=Path, row[1]=Filename, row[2]=FileIndex + * row[3]=JobId row[4]=LStat row[5]=DeltaSeq row[6]=MD5 + */ +static int sendit(void *arg, int num_fields, char **row) +{ + JCR *jcr = (JCR *)arg; + + if (job_canceled(jcr)) { + return 1; + } + + if (row[2][0] == '0') { /* discard when file_index == 0 */ + return 0; + } + + /* sending with checksum */ + if (num_fields == 7 + && row[6][0] /* skip checksum = '0' */ + && row[6][1]) + { + jcr->file_bsock->fsend("%s%s%c%s%c%s%c%s", + row[0], row[1], 0, row[4], 0, row[6], 0, row[5]); + } else { + jcr->file_bsock->fsend("%s%s%c%s%c%c%s", + row[0], row[1], 0, row[4], 0, 0, row[5]); + } + return 0; +} +#endif + +/* We list all files for a given FI structure */ +static void scan_findex(JCR *jcr, RBSR *bsr, + int32_t FirstIndex, int32_t LastIndex, + int32_t &lastFileIndex, uint32_t &lastJobId) +{ + RBSR_FINDEX *fi; + FILE_DBR fdbr; + memset(&fdbr, 0, sizeof(fdbr)); + + fi = (RBSR_FINDEX *) bsr->fi_list->first(); + while (fi) { + int32_t findex, findex2; + + /* fi points to the first item of the list, or the next item that is not + * contigous to the previous group + */ + findex = fi->findex; + findex2 = fi->findex2; + + /* Sometime (with the restore command for example), the fi_list can + * contain false gaps (1-10, 11-11, 12-20 instead of 1-20). The for loop + * is here to merge blocks and reduce the bsr output. The next while(fi) + * iteration will use the next_fi that points to the last merged element. + */ + RBSR_FINDEX *next_fi; + for (next_fi = (RBSR_FINDEX*) bsr->fi_list->next(fi); + next_fi && next_fi->findex == (findex2+1); + next_fi = (RBSR_FINDEX *) bsr->fi_list->next(next_fi)) + { + findex2 = next_fi->findex2; + } + + /* next_fi points after the current block (or to the end of the list), so + * the next while() iteration will use the next value + */ + fi = next_fi; + + /* We look if the current FI block match the volume information */ + if ((findex >= FirstIndex && findex <= LastIndex) || + (findex2 >= FirstIndex && findex2 <= LastIndex) || + (findex < FirstIndex && findex2 > LastIndex)) { + + findex = findex < FirstIndex ? FirstIndex : findex; + findex2 = findex2 > LastIndex ? LastIndex : findex2; + + bool dolist=false; + /* Display only new files */ + if (findex != lastFileIndex || bsr->JobId != lastJobId) { + /* Not the same file, or not the same job */ + fdbr.FileIndex = findex; + //dolist = true; + + } else if (findex2 != lastFileIndex) { + /* We are in the same job, and the first index was already generated */ + fdbr.FileIndex = findex + 1; + //dolist = true; + } + + /* Keep the current values for the next loop */ + lastJobId = bsr->JobId; + lastFileIndex = findex2; + + /* Generate if needed the list of files */ + if (dolist) { + fdbr.FileIndex2 = findex2; + fdbr.JobId = bsr->JobId; + /* New code not working */ + //db_list_files(jcr, jcr->db, &fdbr, sendit, jcr); + } + } + } +} + +/* + * Scan bsr data for a single bsr record + */ +static void scan_bsr_item(JCR *jcr, RBSR *bsr) +{ + int32_t lastFileIndex=0; + uint32_t lastJobId=0; + /* + * 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_list, + bsr->VolParams[i].FirstIndex, + bsr->VolParams[i].LastIndex)) + { + continue; + } + + scan_findex(jcr, bsr, + bsr->VolParams[i].FirstIndex, + bsr->VolParams[i].LastIndex, + lastFileIndex, lastJobId); + } +} + +/* + * We need to find all files from the BSR. All files are listed, this is used + * to send the list of the files to be restored to a plugin for example. + */ +void scan_bsr(JCR *jcr) +{ + char *p; + JobId_t JobId; + RBSR *bsr; + if (!jcr->JobIds || *jcr->JobIds == 0) { + foreach_rblist(bsr, jcr->bsr_list) { + scan_bsr_item(jcr, bsr); + } + return; + } + for (p=jcr->JobIds; get_next_jobid_from_list(&p, &JobId) > 0; ) { + foreach_rblist(bsr, jcr->bsr_list) { + if (JobId == bsr->JobId) { + scan_bsr_item(jcr, bsr); + } + } + } return; }