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
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);
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;
Dmsg2(130, "FT_LNK saving: %s -> %s\n", ff_pkt->fname, ff_pkt->link);
break;
case FT_RESTORE_FIRST:
- Dmsg1(00, "FT_RESTORE_FIRST saving: %s\n", ff_pkt->fname);
+ Dmsg1(100, "FT_RESTORE_FIRST saving: %s\n", ff_pkt->fname);
break;
case FT_DIRBEGIN:
jcr->num_files_examined--; /* correct file count */
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) {
do_read = true;
}
- if (ff_pkt->cmd_plugin && ff_pkt->type != FT_RESTORE_FIRST) {
+ if (ff_pkt->cmd_plugin) {
do_read = true;
}
- Dmsg2(000, "type=%d do_read=%d\n", ff_pkt->type, do_read);
+ Dmsg2(150, "type=%d do_read=%d\n", ff_pkt->type, do_read);
if (do_read) {
btimer_t *tid;
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);
}
BSOCK *sd = jcr->store_bsock;
char attribs[MAXSTRING];
char attribsExBuf[MAXSTRING];
- char *attribsEx;
+ char *attribsEx = NULL;
int attr_stream;
+ int comp_len;
bool stat;
#ifdef FD_NO_SEND_TEST
return true;
/** Now possibly extend the attributes */
if (ff_pkt->type == FT_RESTORE_FIRST) {
- /**
- * For restore objects, we return the object in the extended
- * attributes.
- */
- attribsEx = ff_pkt->object;
- attr_stream = STREAM_UNIX_ATTRIBUTES_EX;
+ attr_stream = STREAM_RESTORE_OBJECT;
} else {
attribsEx = attribsExBuf;
attr_stream = encode_attribsEx(jcr, attribsEx, ff_pkt);
* 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.
*/
ff_pkt->type, ff_pkt->link, 0, attribs, 0, 0, attribsEx, 0);
break;
case FT_RESTORE_FIRST:
- /**
- * Note, we edit everything as we do for the default case, but the
- * object is tacked on to the end in place of the extended attributes,
- * but we do a memcpy so that the object can be a binary object.
- */
- Dmsg6(000, "Type=%d DataStream=%d attrStream=%d File=%s\nattribs=%s\nattribsEx=%s",
- ff_pkt->type, data_stream, STREAM_UNIX_ATTRIBUTES_EX,
- ff_pkt->fname, attribs, ff_pkt->object);
- sd->msglen = Mmsg(sd->msg, "%ld %d %s%c%s%c%c",
- jcr->JobFiles, ff_pkt->type, ff_pkt->fname, 0, attribs, 0, 0);
- sd->msg = check_pool_memory_size(sd->msg, sd->msglen + ff_pkt->object_len + 1);
- memcpy(sd->msg + sd->msglen, ff_pkt->object, ff_pkt->object_len);
- sd->msglen += ff_pkt->object_len;
+ 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);
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
+}