X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;ds=sidebyside;f=bacula%2Fsrc%2Ffiled%2Faccurate.c;h=404756aa6c20e16e42b1880c2848877abc97e145;hb=f5e7d95ce741ea5c296d605b2f411805a65462d6;hp=90e7ff24d3138b99678a921e423b9e3387879bb2;hpb=6ce278e369e22cbd5556b3fec04a77b7a9d3eae1;p=bacula%2Fbacula diff --git a/bacula/src/filed/accurate.c b/bacula/src/filed/accurate.c index 90e7ff24d3..404756aa6c 100644 --- a/bacula/src/filed/accurate.c +++ b/bacula/src/filed/accurate.c @@ -1,12 +1,12 @@ /* Bacula® - The Network Backup Solution - Copyright (C) 2000-2009 Free Software Foundation Europe e.V. + Copyright (C) 2000-2011 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 + modify it under the terms of version three of the GNU Affero General Public License as published by the Free Software Foundation and included in the file LICENSE. @@ -15,7 +15,7 @@ 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 + You should have received a copy of the GNU Affero 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. @@ -40,6 +40,7 @@ typedef struct PrivateCurFile { char *fname; char *lstat; char *chksum; + int32_t delta_seq; bool seen; } CurFile; @@ -100,7 +101,7 @@ static bool accurate_send_base_file_list(JCR *jcr) FF_PKT *ff_pkt; int stream = STREAM_UNIX_ATTRIBUTES; - if (!jcr->accurate || jcr->get_JobLevel() != L_FULL) { + if (!jcr->accurate || jcr->getJobLevel() != L_FULL) { return true; } @@ -115,7 +116,7 @@ static bool accurate_send_base_file_list(JCR *jcr) if (elt->seen) { Dmsg2(dbglvl, "base file fname=%s seen=%i\n", elt->fname, elt->seen); /* TODO: skip the decode and use directly the lstat field */ - decode_stat(elt->lstat, &statc, &LinkFIc); /* decode catalog stat */ + decode_stat(elt->lstat, &statc, sizeof(statc), &LinkFIc); /* decode catalog stat */ ff_pkt->fname = elt->fname; ff_pkt->statp = statc; encode_and_send_attributes(jcr, ff_pkt, stream); @@ -157,7 +158,7 @@ static bool accurate_send_deleted_list(JCR *jcr) } Dmsg2(dbglvl, "deleted fname=%s seen=%i\n", elt->fname, elt->seen); /* TODO: skip the decode and use directly the lstat field */ - decode_stat(elt->lstat, &statc, &LinkFIc); /* decode catalog stat */ + decode_stat(elt->lstat, &statc, sizeof(statc), &LinkFIc); /* decode catalog stat */ ff_pkt->fname = elt->fname; ff_pkt->statp.st_mtime = statc.st_mtime; ff_pkt->statp.st_ctime = statc.st_ctime; @@ -181,35 +182,43 @@ void accurate_free(JCR *jcr) /* Send the deleted or the base file list and cleanup */ bool accurate_finish(JCR *jcr) { - bool ret=true; + bool ret = true; + + if (jcr->is_canceled() || jcr->is_incomplete()) { + accurate_free(jcr); + return ret; + } if (jcr->accurate) { - if (jcr->get_JobLevel() == L_FULL) { - ret = accurate_send_base_file_list(jcr); + if (jcr->is_JobLevel(L_FULL)) { + if (!jcr->rerunning) { + ret = accurate_send_base_file_list(jcr); + } } else { ret = accurate_send_deleted_list(jcr); } - accurate_free(jcr); - if (jcr->get_JobLevel() == L_FULL) { - Dmsg1(0, "Space saved with Base jobs: %lld MB\n", - jcr->base_size/(1024*1024)); + if (jcr->is_JobLevel(L_FULL)) { + Jmsg(jcr, M_INFO, 0, _("Space saved with Base jobs: %lld MB\n"), + jcr->base_size/(1024*1024)); } } return ret; } static bool accurate_add_file(JCR *jcr, uint32_t len, - char *fname, char *lstat, char *chksum) + char *fname, char *lstat, char *chksum, + int32_t delta) { bool ret = true; - CurFile elt; - elt.seen = 0; - CurFile *item; - /* we store CurFile, fname and ctime/mtime in the same chunk */ - item = (CurFile *)jcr->file_list->hash_malloc(sizeof(CurFile)+len+3); - memcpy(item, &elt, sizeof(CurFile)); + /* we store CurFile, fname and ctime/mtime in the same chunk + * we need one extra byte to handle an empty chksum + */ + item = (CurFile *)jcr->file_list->hash_malloc(sizeof(CurFile)+len+1); + item->seen = 0; + + /* TODO: see if we can optimize this part with memcpy instead of strcpy */ item->fname = (char *)item+sizeof(CurFile); strcpy(item->fname, fname); @@ -219,9 +228,12 @@ static bool accurate_add_file(JCR *jcr, uint32_t len, item->chksum = item->lstat+strlen(item->lstat)+1; strcpy(item->chksum, chksum); + item->delta_seq = delta; + jcr->file_list->insert(item->fname, item); - Dmsg3(dbglvl, "add fname=<%s> lstat=%s chksum=%s\n", fname, lstat, chksum); + Dmsg4(dbglvl, "add fname=<%s> lstat=%s delta_seq=%i chksum=%s\n", + fname, lstat, delta, chksum); return ret; } @@ -242,10 +254,13 @@ bool accurate_check_file(JCR *jcr, FF_PKT *ff_pkt) struct stat statc; int32_t LinkFIc; bool stat = false; + char *opts; char *fname; CurFile elt; - if (!jcr->accurate) { + ff_pkt->delta_seq = 0; + + if (!jcr->accurate && !jcr->rerunning) { return true; } @@ -263,18 +278,26 @@ bool accurate_check_file(JCR *jcr, FF_PKT *ff_pkt) goto bail_out; } + ff_pkt->delta_seq = elt.delta_seq; + if (elt.seen) { /* file has been seen ? */ Dmsg1(dbglvl, "accurate %s (already seen)\n", fname); goto bail_out; } - decode_stat(elt.lstat, &statc, &LinkFIc); /* decode catalog stat */ + decode_stat(elt.lstat, &statc, sizeof(statc), &LinkFIc); /* decode catalog stat */ + + if (!jcr->rerunning && (jcr->getJobLevel() == L_FULL)) { + opts = ff_pkt->BaseJobOpts; + } else { + opts = ff_pkt->AccurateOpts; + } /* * Loop over options supplied by user and verify the * fields he requests. */ - for (char *p=ff_pkt->AccurateOpts; !stat && *p; p++) { + for (char *p=opts; !stat && *p; p++) { char ed1[30], ed2[30]; switch (*p) { case 'i': /* compare INODEs */ @@ -287,6 +310,9 @@ bool accurate_check_file(JCR *jcr, FF_PKT *ff_pkt) } break; case 'p': /* permissions bits */ + /* TODO: If something change only in perm, user, group + * Backup only the attribute stream + */ if (statc.st_mode != ff_pkt->statp.st_mode) { Dmsg3(dbglvl-1, "%s st_mode differ. Cat: %x File: %x\n", fname, @@ -354,21 +380,31 @@ bool accurate_check_file(JCR *jcr, FF_PKT *ff_pkt) stat = true; } break; - + case 'A': /* Always backup a file */ + stat = true; + break; /* TODO: cleanup and factorise this function with verify.c */ case '5': /* compare MD5 */ - case '1': /* compare SHA1 */ + case '1': /* compare SHA1 */ /* * The remainder of the function is all about getting the checksum. * First we initialise, then we read files, other streams and Finder Info. */ - if (!stat && *elt.chksum && ff_pkt->type != FT_LNKSAVED && + if (!stat && ff_pkt->type != FT_LNKSAVED && (S_ISREG(ff_pkt->statp.st_mode) && ff_pkt->flags & (FO_MD5|FO_SHA1|FO_SHA256|FO_SHA512))) { + + if (!*elt.chksum && !jcr->rerunning) { + Jmsg(jcr, M_WARNING, 0, _("Cannot verify checksum for %s\n"), + ff_pkt->fname); + stat = true; + break; + } + /* - * Create our digest context. If this fails, the digest will be set to NULL - * and not used. + * Create our digest context. If this fails, the digest will be set + * to NULL and not used. */ if (ff_pkt->flags & FO_MD5) { digest = crypto_digest_new(jcr, CRYPTO_DIGEST_MD5); @@ -413,8 +449,9 @@ bool accurate_check_file(JCR *jcr, FF_PKT *ff_pkt) bin_to_base64(digest_buf, BASE64_SIZE(size), md, size, true); if (strcmp(digest_buf, elt.chksum)) { - Dmsg3(dbglvl-1, "%s chksum diff. Cat: %s File: %s\n", + Dmsg4(dbglvl,"%s %s chksum diff. Cat: %s File: %s\n", fname, + digest_name, elt.chksum, digest_buf); stat = true; @@ -428,6 +465,7 @@ bool accurate_check_file(JCR *jcr, FF_PKT *ff_pkt) break; case ':': + case 'J': case 'C': default: break; @@ -437,7 +475,7 @@ bool accurate_check_file(JCR *jcr, FF_PKT *ff_pkt) /* In Incr/Diff accurate mode, we mark all files as seen * When in Full+Base mode, we mark only if the file match exactly */ - if (jcr->get_JobLevel() == L_FULL) { + if (jcr->getJobLevel() == L_FULL) { if (!stat) { /* compute space saved with basefile */ jcr->base_size += ff_pkt->statp.st_size; @@ -460,6 +498,7 @@ int accurate_cmd(JCR *jcr) BSOCK *dir = jcr->dir_bsock; int lstat_pos, chksum_pos; int32_t nb; + uint16_t delta_seq; if (job_canceled(jcr)) { return true; @@ -475,7 +514,7 @@ int accurate_cmd(JCR *jcr) /* * buffer = sizeof(CurFile) + dirmsg - * dirmsg = fname + \0 + lstat + \0 + checksum + \0 + * dirmsg = fname + \0 + lstat + \0 + checksum + \0 + delta_seq + \0 */ /* get current files */ while (dir->recv() >= 0) { @@ -485,12 +524,18 @@ int accurate_cmd(JCR *jcr) if (chksum_pos >= dir->msglen) { chksum_pos = lstat_pos - 1; /* tweak: no checksum, point to the last \0 */ - } + delta_seq = 0; + } else { + delta_seq = str_to_int32(dir->msg + + chksum_pos + + strlen(dir->msg + chksum_pos) + 1); + } accurate_add_file(jcr, dir->msglen, dir->msg, /* Path */ dir->msg + lstat_pos, /* LStat */ - dir->msg + chksum_pos); /* CheckSum */ + dir->msg + chksum_pos, /* CheckSum */ + delta_seq); /* Delta Sequence */ } }