X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Ffiled%2Fbackup.c;h=60beddb80c8e233f3062f3e8ee3d0e0825f02545;hb=7fc5fe1b10047210db9c20ccb415d9ac87f6eee1;hp=b2fad4c3028a10ed961840f37445f52bab588bfb;hpb=f510b3985e8f8f6dcfdb95b0bf6a12a18bdeb85b;p=bacula%2Fbacula diff --git a/bacula/src/filed/backup.c b/bacula/src/filed/backup.c index b2fad4c302..60beddb80c 100644 --- a/bacula/src/filed/backup.c +++ b/bacula/src/filed/backup.c @@ -6,7 +6,7 @@ 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. @@ -61,6 +61,7 @@ bool encode_and_send_attributes(JCR *jcr, FF_PKT *ff_pkt, int &data_stream); static bool crypto_session_start(JCR *jcr); static void crypto_session_end(JCR *jcr); static bool crypto_session_send(JCR *jcr, BSOCK *sd); +static void close_vss_backup_session(JCR *jcr); /** * Find all the requested files and send them @@ -172,6 +173,8 @@ bool blast_data_to_storage_daemon(JCR *jcr, char *addr) jcr->xattr_data->nr_errors); } + close_vss_backup_session(jcr); + accurate_finish(jcr); /* send deleted or base file list to SD */ stop_heartbeat_monitor(jcr); @@ -299,6 +302,7 @@ static bool crypto_session_send(JCR *jcr, BSOCK *sd) int save_file(JCR *jcr, FF_PKT *ff_pkt, bool top_level) { bool do_read = false; + bool plugin_started = false; int stat, data_stream; int rtnstat = 0; DIGEST *digest = NULL; @@ -314,7 +318,7 @@ int save_file(JCR *jcr, FF_PKT *ff_pkt, bool top_level) #endif BSOCK *sd = jcr->store_bsock; - if (job_canceled(jcr)) { + if (jcr->is_job_canceled()) { return 0; } @@ -335,6 +339,9 @@ int save_file(JCR *jcr, FF_PKT *ff_pkt, bool top_level) case FT_LNK: Dmsg2(130, "FT_LNK saving: %s -> %s\n", ff_pkt->fname, ff_pkt->link); break; + case FT_RESTORE_FIRST: + Dmsg1(100, "FT_RESTORE_FIRST saving: %s\n", ff_pkt->fname); + break; case FT_DIRBEGIN: jcr->num_files_examined--; /* correct file count */ return 1; /* not used */ @@ -346,8 +353,13 @@ int save_file(JCR *jcr, FF_PKT *ff_pkt, bool top_level) case FT_NOFSCHG: /* Suppress message for /dev filesystems */ if (!is_in_fileset(ff_pkt)) { - Jmsg(jcr, M_INFO, 1, _(" %s is a different filesystem. Will not descend from %s into %s\n"), - ff_pkt->fname, ff_pkt->top_fname, ff_pkt->fname); +#ifdef HAVE_WIN32 + Jmsg(jcr, M_INFO, 1, _(" %s is a junction point or a different filesystem. Will not descend from %s into it.\n"), + ff_pkt->fname, ff_pkt->top_fname); +#else + Jmsg(jcr, M_INFO, 1, _(" %s is a different filesystem. Will not descend from %s into it.\n"), + ff_pkt->fname, ff_pkt->top_fname); +#endif } ff_pkt->type = FT_DIREND; /* Backup only the directory entry */ break; @@ -489,16 +501,22 @@ int save_file(JCR *jcr, FF_PKT *ff_pkt, bool top_level) set_portable_backup(&ff_pkt->bfd); /* disable Win32 BackupRead() */ } if (ff_pkt->cmd_plugin) { + /* Tell bfile that it needs to call plugin */ if (!set_cmd_plugin(&ff_pkt->bfd, jcr)) { goto bail_out; } send_plugin_name(jcr, sd, true); /* signal start of plugin data */ + plugin_started = true; } /** Send attributes -- must be done after binit() */ if (!encode_and_send_attributes(jcr, ff_pkt, data_stream)) { goto bail_out; } + /** Meta data only for restore object */ + if (ff_pkt->type == FT_RESTORE_FIRST) { + goto good_rtn; + } /** Set up the encryption context and send the session data to the SD */ if (has_file_data && jcr->crypto.pki_encrypt) { @@ -524,11 +542,12 @@ int save_file(JCR *jcr, FF_PKT *ff_pkt, bool top_level) (!is_portable_backup(&ff_pkt->bfd) && ff_pkt->type == FT_DIREND)) { do_read = true; } + if (ff_pkt->cmd_plugin) { do_read = true; } - Dmsg1(400, "do_read=%d\n", do_read); + Dmsg2(150, "type=%d do_read=%d\n", ff_pkt->type, do_read); if (do_read) { btimer_t *tid; @@ -729,14 +748,14 @@ int save_file(JCR *jcr, FF_PKT *ff_pkt, bool top_level) sd->send(); sd->signal(BNET_EOD); /* end of checksum */ } - if (ff_pkt->cmd_plugin) { - send_plugin_name(jcr, sd, false); /* signal end of plugin data */ - } good_rtn: rtnstat = 1; /* good return */ bail_out: + if (ff_pkt->cmd_plugin && plugin_started) { + send_plugin_name(jcr, sd, false); /* signal end of plugin data */ + } if (digest) { crypto_digest_free(digest); } @@ -853,7 +872,7 @@ static int send_data(JCR *jcr, int stream, FF_PKT *ff_pkt, DIGEST *digest, * */ if (!sd->fsend("%ld %d 0", jcr->JobFiles, stream)) { - if (!job_canceled(jcr)) { + if (!jcr->is_job_canceled()) { Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"), sd->bstrerror()); } @@ -1013,7 +1032,7 @@ static int send_data(JCR *jcr, int stream, FF_PKT *ff_pkt, DIGEST *digest, } sd->msg = wbuf; /* set correct write buffer */ if (!sd->send()) { - if (!job_canceled(jcr)) { + if (!jcr->is_job_canceled()) { Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"), sd->bstrerror()); } @@ -1050,7 +1069,7 @@ static int send_data(JCR *jcr, int stream, FF_PKT *ff_pkt, DIGEST *digest, sd->msglen = encrypted_len; /* set encrypted length */ sd->msg = jcr->crypto.crypto_buf; /* set correct write buffer */ if (!sd->send()) { - if (!job_canceled(jcr)) { + if (!jcr->is_job_canceled()) { Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"), sd->bstrerror()); } @@ -1063,7 +1082,7 @@ static int send_data(JCR *jcr, int stream, FF_PKT *ff_pkt, DIGEST *digest, } if (!sd->signal(BNET_EOD)) { /* indicate end of file data */ - if (!job_canceled(jcr)) { + if (!jcr->is_job_canceled()) { Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"), sd->bstrerror()); } @@ -1091,9 +1110,11 @@ bool encode_and_send_attributes(JCR *jcr, FF_PKT *ff_pkt, int &data_stream) { BSOCK *sd = jcr->store_bsock; char attribs[MAXSTRING]; - char attribsEx[MAXSTRING]; + char attribsExBuf[MAXSTRING]; + char *attribsEx = NULL; int attr_stream; - int stat; + int comp_len; + bool stat; #ifdef FD_NO_SEND_TEST return true; #endif @@ -1108,7 +1129,12 @@ bool encode_and_send_attributes(JCR *jcr, FF_PKT *ff_pkt, int &data_stream) encode_stat(attribs, &ff_pkt->statp, ff_pkt->LinkFI, data_stream); /** Now possibly extend the attributes */ - attr_stream = encode_attribsEx(jcr, attribsEx, ff_pkt); + if (ff_pkt->type == FT_RESTORE_FIRST) { + attr_stream = STREAM_RESTORE_OBJECT; + } else { + attribsEx = attribsExBuf; + attr_stream = encode_attribsEx(jcr, attribsEx, ff_pkt); + } Dmsg3(300, "File %s\nattribs=%s\nattribsEx=%s\n", ff_pkt->fname, attribs, attribsEx); @@ -1123,7 +1149,7 @@ bool encode_and_send_attributes(JCR *jcr, FF_PKT *ff_pkt, int &data_stream) * */ if (!sd->fsend("%ld %d 0", jcr->JobFiles, attr_stream)) { - if (!job_canceled(jcr)) { + if (!jcr->is_job_canceled()) { Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"), sd->bstrerror()); } @@ -1140,39 +1166,84 @@ bool encode_and_send_attributes(JCR *jcr, FF_PKT *ff_pkt, int &data_stream) * Link name (if type==FT_LNK or FT_LNKSAVED) * Encoded extended-attributes (for Win32) * + * or send Restore Object to Storage daemon + * File_index + * File_type + * Object_index + * Object_len (possibly compressed) + * Object_full_len (not compressed) + * Object_compression + * Plugin_name + * Object_name + * Binary Object data + * * For a directory, link is the same as fname, but with trailing * slash. For a linked file, link is the link. */ if (ff_pkt->type != FT_DELETED) { /* already stripped */ strip_path(ff_pkt); } - if (ff_pkt->type == FT_LNK || ff_pkt->type == FT_LNKSAVED) { + switch (ff_pkt->type) { + case FT_LNK: + case FT_LNKSAVED: Dmsg2(300, "Link %s to %s\n", ff_pkt->fname, ff_pkt->link); stat = sd->fsend("%ld %d %s%c%s%c%s%c%s%c", jcr->JobFiles, ff_pkt->type, ff_pkt->fname, 0, attribs, 0, ff_pkt->link, 0, attribsEx, 0); - } else if (ff_pkt->type == FT_DIREND || ff_pkt->type == FT_REPARSE) { + break; + case FT_DIREND: + case FT_REPARSE: /* Here link is the canonical filename (i.e. with trailing slash) */ stat = sd->fsend("%ld %d %s%c%s%c%c%s%c", jcr->JobFiles, ff_pkt->type, ff_pkt->link, 0, attribs, 0, 0, attribsEx, 0); - } else { + break; + case FT_RESTORE_FIRST: + comp_len = ff_pkt->object_len; + ff_pkt->object_compression = 0; + if (ff_pkt->object_len > 1000) { + /* Big object, compress it */ + int stat; + comp_len = ff_pkt->object_len + 1000; + POOLMEM *comp_obj = get_memory(comp_len); + stat = Zdeflate(ff_pkt->object, ff_pkt->object_len, comp_obj, comp_len); + if (comp_len < ff_pkt->object_len) { + ff_pkt->object = comp_obj; + ff_pkt->object_compression = 1; /* zlib level 9 compression */ + } else { + /* Uncompressed object smaller, use it */ + comp_len = ff_pkt->object_len; + } + Dmsg2(100, "Object compressed from %d to %d bytes\n", ff_pkt->object_len, comp_len); + } + sd->msglen = Mmsg(sd->msg, "%d %d %d %d %d %d %s%c%s%c", + jcr->JobFiles, ff_pkt->type, ff_pkt->object_index, + comp_len, ff_pkt->object_len, ff_pkt->object_compression, + ff_pkt->fname, 0, ff_pkt->object_name, 0); + sd->msg = check_pool_memory_size(sd->msg, sd->msglen + comp_len + 2); + memcpy(sd->msg + sd->msglen, ff_pkt->object, comp_len); + /* Note we send one extra byte so Dir can store zero after object */ + sd->msglen += comp_len + 1; + stat = sd->send(); + if (ff_pkt->object_compression) { + free_and_null_pool_memory(ff_pkt->object); + } + break; + default: stat = sd->fsend("%ld %d %s%c%s%c%c%s%c", jcr->JobFiles, ff_pkt->type, ff_pkt->fname, 0, attribs, 0, 0, attribsEx, 0); + break; } if (ff_pkt->type != FT_DELETED) { unstrip_path(ff_pkt); } Dmsg2(300, ">stored: attr len=%d: %s\n", sd->msglen, sd->msg); - if (!stat) { - if (!job_canceled(jcr)) { - Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"), - sd->bstrerror()); - } - return false; + if (!stat && !jcr->is_job_canceled()) { + Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"), + sd->bstrerror()); } sd->signal(BNET_EOD); /* indicate end of attributes data */ - return true; + return stat; } /** @@ -1276,3 +1347,35 @@ void unstrip_path(FF_PKT *ff_pkt) sm_check(__FILE__, __LINE__, true); } } + +static void close_vss_backup_session(JCR *jcr) +{ +#if defined(WIN32_VSS) + /* STOP VSS ON WIN32 */ + /* tell vss to close the backup session */ + if (jcr->VSS) { + if (g_pVSSClient->CloseBackup()) { + /* inform user about writer states */ + for (int i=0; i<(int)g_pVSSClient->GetWriterCount(); i++) { + int msg_type = M_INFO; + if (g_pVSSClient->GetWriterState(i) < 1) { + msg_type = M_WARNING; + jcr->JobErrors++; + } + Jmsg(jcr, msg_type, 0, _("VSS Writer (BackupComplete): %s\n"), g_pVSSClient->GetWriterInfo(i)); + } + } + WCHAR *metadata = g_pVSSClient->GetMetadata(); + if (metadata) { + FF_PKT *ff_pkt = jcr->ff; + ff_pkt->fname = "job"; + ff_pkt->type = FT_RESTORE_FIRST; + ff_pkt->LinkFI = 0; + ff_pkt->object_name = "job_metadata.xml"; + ff_pkt->object = (char *)metadata; + ff_pkt->object_len = (wcslen(metadata) + 1) * sizeof(WCHAR); + save_file(jcr, ff_pkt, true); + } + } +#endif +}