1 /*
2 BAREOS® - Backup Archiving REcovery Open Sourced
3
4 Copyright (C) 2000-2011 Free Software Foundation Europe e.V.
5 Copyright (C) 2011-2012 Planets Communications B.V.
6 Copyright (C) 2013-2020 Bareos GmbH & Co. KG
7
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version three of the GNU Affero General Public
10 License as published by the Free Software Foundation and included
11 in the file LICENSE.
12
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Affero General Public License for more details.
17
18 You should have received a copy of the GNU Affero General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 02110-1301, USA.
22 */
23 /*
24 * Kern Sibbald, March MM
25 */
26 /**
27 * @file
28 * Bareos File Daemon backup.c send file attributes and data to the Storage
29 * daemon.
30 */
31
32 #include "include/bareos.h"
33 #include "filed/filed.h"
34 #include "filed/filed_globals.h"
35 #include "filed/accurate.h"
36 #include "filed/compression.h"
37 #include "filed/crypto.h"
38 #include "filed/heartbeat.h"
39 #include "filed/backup.h"
40 #include "filed/jcr_private.h"
41 #include "include/ch.h"
42 #include "findlib/attribs.h"
43 #include "findlib/hardlink.h"
44 #include "findlib/find_one.h"
45 #include "lib/berrno.h"
46 #include "lib/bsock.h"
47 #include "lib/btimers.h"
48 #include "lib/parse_conf.h"
49 #include "lib/util.h"
50 #include "include/make_unique.h"
51
52 namespace filedaemon {
53
54 #ifdef HAVE_DARWIN_OS
55 const bool have_darwin_os = true;
56 #else
57 const bool have_darwin_os = false;
58 #endif
59
60 #if defined(HAVE_ACL)
61 const bool have_acl = true;
62 #else
63 const bool have_acl = false;
64 #endif
65
66 #if defined(HAVE_XATTR)
67 const bool have_xattr = true;
68 #else
69 const bool have_xattr = false;
70 #endif
71
72 #ifndef compressBound
73 # define compressBound(sourceLen) \
74 (sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + (sourceLen >> 25) + 13)
75 #endif
76
77 /* Forward referenced functions */
78 int SaveFile(JobControlRecord* jcr, FindFilesPacket* ff_pkt, bool top_level);
79 static int send_data(JobControlRecord* jcr,
80 int stream,
81 FindFilesPacket* ff_pkt,
82 DIGEST* digest,
83 DIGEST* signature_digest);
84 bool EncodeAndSendAttributes(JobControlRecord* jcr,
85 FindFilesPacket* ff_pkt,
86 int& data_stream);
87 static void CloseVssBackupSession(JobControlRecord* jcr);
88
89 /**
90 * Find all the requested files and send them
91 * to the Storage daemon.
92 *
93 * Note, we normally carry on a one-way
94 * conversation from this point on with the SD, simply blasting
95 * data to him. To properly know what is going on, we
96 * also run a "heartbeat" monitor which reads the socket and
97 * reacts accordingly (at the moment it has nothing to do
98 * except echo the heartbeat to the Director).
99 */
BlastDataToStorageDaemon(JobControlRecord * jcr,char * addr,crypto_cipher_t cipher)100 bool BlastDataToStorageDaemon(JobControlRecord* jcr,
101 char* addr,
102 crypto_cipher_t cipher)
103 {
104 BareosSocket* sd;
105 bool ok = true;
106
107 sd = jcr->store_bsock;
108
109 jcr->setJobStatus(JS_Running);
110
111 Dmsg1(300, "filed: opened data connection %d to stored\n", sd->fd_);
112
113 LockRes(my_config);
114 ClientResource* client
115 = (ClientResource*)my_config->GetNextRes(R_CLIENT, NULL);
116 UnlockRes(my_config);
117 uint32_t buf_size;
118 if (client) {
119 buf_size = client->max_network_buffer_size;
120 } else {
121 buf_size = 0; /* use default */
122 }
123 if (!sd->SetBufferSize(buf_size, BNET_SETBUF_WRITE)) {
124 jcr->setJobStatus(JS_ErrorTerminated);
125 Jmsg(jcr, M_FATAL, 0, _("Cannot set buffer size FD->SD.\n"));
126 return false;
127 }
128
129 jcr->buf_size = sd->message_length;
130
131 if (!AdjustCompressionBuffers(jcr)) { return false; }
132
133 if (!CryptoSessionStart(jcr, cipher)) { return false; }
134
135 SetFindOptions((FindFilesPacket*)jcr->impl->ff, jcr->impl->incremental,
136 jcr->impl->since_time);
137
138 /**
139 * In accurate mode, we overload the find_one check function
140 */
141 if (jcr->accurate) {
142 SetFindChangedFunction((FindFilesPacket*)jcr->impl->ff, AccurateCheckFile);
143 }
144
145 StartHeartbeatMonitor(jcr);
146
147 if (have_acl) {
148 jcr->impl->acl_data = std::make_unique<AclData>();
149 jcr->impl->acl_data->u.build
150 = (acl_build_data_t*)malloc(sizeof(acl_build_data_t));
151 memset(jcr->impl->acl_data->u.build, 0, sizeof(acl_build_data_t));
152 jcr->impl->acl_data->u.build->content = GetPoolMemory(PM_MESSAGE);
153 }
154
155 if (have_xattr) {
156 jcr->impl->xattr_data = std::make_unique<XattrData>();
157 jcr->impl->xattr_data->u.build
158 = (xattr_build_data_t*)malloc(sizeof(xattr_build_data_t));
159 memset(jcr->impl->xattr_data->u.build, 0, sizeof(xattr_build_data_t));
160 jcr->impl->xattr_data->u.build->content = GetPoolMemory(PM_MESSAGE);
161 }
162
163 /**
164 * Subroutine SaveFile() is called for each file
165 */
166 if (!FindFiles(jcr, (FindFilesPacket*)jcr->impl->ff, SaveFile, PluginSave)) {
167 ok = false; /* error */
168 jcr->setJobStatus(JS_ErrorTerminated);
169 }
170
171 if (have_acl && jcr->impl->acl_data->u.build->nr_errors > 0) {
172 Jmsg(jcr, M_WARNING, 0,
173 _("Encountered %ld acl errors while doing backup\n"),
174 jcr->impl->acl_data->u.build->nr_errors);
175 }
176 if (have_xattr && jcr->impl->xattr_data->u.build->nr_errors > 0) {
177 Jmsg(jcr, M_WARNING, 0,
178 _("Encountered %ld xattr errors while doing backup\n"),
179 jcr->impl->xattr_data->u.build->nr_errors);
180 }
181
182 CloseVssBackupSession(jcr);
183
184 AccurateFinish(jcr); /* send deleted or base file list to SD */
185
186 StopHeartbeatMonitor(jcr);
187
188 sd->signal(BNET_EOD); /* end of sending data */
189
190 if (have_acl && jcr->impl->acl_data) {
191 FreePoolMemory(jcr->impl->acl_data->u.build->content);
192 free(jcr->impl->acl_data->u.build);
193 }
194
195 if (have_xattr && jcr->impl->xattr_data) {
196 FreePoolMemory(jcr->impl->xattr_data->u.build->content);
197 free(jcr->impl->xattr_data->u.build);
198 }
199
200 if (jcr->impl->big_buf) {
201 free(jcr->impl->big_buf);
202 jcr->impl->big_buf = NULL;
203 }
204
205 CleanupCompression(jcr);
206 CryptoSessionEnd(jcr);
207
208 Dmsg1(100, "end blast_data ok=%d\n", ok);
209 return ok;
210 }
211
212 /**
213 * Save OSX specific resource forks and finder info.
214 */
SaveRsrcAndFinder(b_save_ctx & bsctx)215 static inline bool SaveRsrcAndFinder(b_save_ctx& bsctx)
216 {
217 char flags[FOPTS_BYTES];
218 int rsrc_stream;
219 BareosSocket* sd = bsctx.jcr->store_bsock;
220 bool retval = false;
221
222 if (bsctx.ff_pkt->hfsinfo.rsrclength > 0) {
223 if (BopenRsrc(&bsctx.ff_pkt->bfd, bsctx.ff_pkt->fname, O_RDONLY | O_BINARY,
224 0)
225 < 0) {
226 bsctx.ff_pkt->ff_errno = errno;
227 BErrNo be;
228 Jmsg(bsctx.jcr, M_NOTSAVED, -1,
229 _(" Cannot open resource fork for \"%s\": ERR=%s.\n"),
230 bsctx.ff_pkt->fname, be.bstrerror());
231 bsctx.jcr->JobErrors++;
232 if (IsBopen(&bsctx.ff_pkt->bfd)) { bclose(&bsctx.ff_pkt->bfd); }
233 } else {
234 int status;
235
236 memcpy(flags, bsctx.ff_pkt->flags, sizeof(flags));
237 ClearBit(FO_COMPRESS, bsctx.ff_pkt->flags);
238 ClearBit(FO_SPARSE, bsctx.ff_pkt->flags);
239 ClearBit(FO_OFFSETS, bsctx.ff_pkt->flags);
240 rsrc_stream = BitIsSet(FO_ENCRYPT, flags)
241 ? STREAM_ENCRYPTED_MACOS_FORK_DATA
242 : STREAM_MACOS_FORK_DATA;
243
244 status = send_data(bsctx.jcr, rsrc_stream, bsctx.ff_pkt, bsctx.digest,
245 bsctx.signing_digest);
246
247 memcpy(bsctx.ff_pkt->flags, flags, sizeof(flags));
248 bclose(&bsctx.ff_pkt->bfd);
249 if (!status) { goto bail_out; }
250 }
251 }
252
253 Dmsg1(300, "Saving Finder Info for \"%s\"\n", bsctx.ff_pkt->fname);
254 sd->fsend("%ld %d 0", bsctx.jcr->JobFiles, STREAM_HFSPLUS_ATTRIBUTES);
255 Dmsg1(300, "filed>stored:header %s", sd->msg);
256 PmMemcpy(sd->msg, bsctx.ff_pkt->hfsinfo.fndrinfo, 32);
257 sd->message_length = 32;
258 if (bsctx.digest) {
259 CryptoDigestUpdate(bsctx.digest, (uint8_t*)sd->msg, sd->message_length);
260 }
261 if (bsctx.signing_digest) {
262 CryptoDigestUpdate(bsctx.signing_digest, (uint8_t*)sd->msg,
263 sd->message_length);
264 }
265 sd->send();
266 sd->signal(BNET_EOD);
267
268 retval = true;
269
270 bail_out:
271 return retval;
272 }
273
274 /**
275 * Setup for digest handling. If this fails, the digest will be set to NULL
276 * and not used. Note, the digest (file hash) can be any one of the four
277 * algorithms below.
278 *
279 * The signing digest is a single algorithm depending on
280 * whether or not we have SHA2.
281 * ****FIXME**** the signing algorithm should really be
282 * determined a different way!!!!!! What happens if
283 * sha2 was available during backup but not restore?
284 */
SetupEncryptionDigests(b_save_ctx & bsctx)285 static inline bool SetupEncryptionDigests(b_save_ctx& bsctx)
286 {
287 bool retval = false;
288 // TODO landonf: Allow the user to specify the digest algorithm
289 #ifdef HAVE_SHA2
290 crypto_digest_t signing_algorithm = CRYPTO_DIGEST_SHA256;
291 #else
292 crypto_digest_t signing_algorithm = CRYPTO_DIGEST_SHA1;
293 #endif
294
295 if (BitIsSet(FO_MD5, bsctx.ff_pkt->flags)) {
296 bsctx.digest = crypto_digest_new(bsctx.jcr, CRYPTO_DIGEST_MD5);
297 bsctx.digest_stream = STREAM_MD5_DIGEST;
298 } else if (BitIsSet(FO_SHA1, bsctx.ff_pkt->flags)) {
299 bsctx.digest = crypto_digest_new(bsctx.jcr, CRYPTO_DIGEST_SHA1);
300 bsctx.digest_stream = STREAM_SHA1_DIGEST;
301 } else if (BitIsSet(FO_SHA256, bsctx.ff_pkt->flags)) {
302 bsctx.digest = crypto_digest_new(bsctx.jcr, CRYPTO_DIGEST_SHA256);
303 bsctx.digest_stream = STREAM_SHA256_DIGEST;
304 } else if (BitIsSet(FO_SHA512, bsctx.ff_pkt->flags)) {
305 bsctx.digest = crypto_digest_new(bsctx.jcr, CRYPTO_DIGEST_SHA512);
306 bsctx.digest_stream = STREAM_SHA512_DIGEST;
307 }
308
309 /*
310 * Did digest initialization fail?
311 */
312 if (bsctx.digest_stream != STREAM_NONE && bsctx.digest == NULL) {
313 Jmsg(bsctx.jcr, M_WARNING, 0, _("%s digest initialization failed\n"),
314 stream_to_ascii(bsctx.digest_stream));
315 }
316
317 /**
318 * Set up signature digest handling. If this fails, the signature digest
319 * will be set to NULL and not used.
320 */
321 /* TODO landonf: We should really only calculate the digest once, for
322 * both verification and signing.
323 */
324 if (bsctx.jcr->impl->crypto.pki_sign) {
325 bsctx.signing_digest = crypto_digest_new(bsctx.jcr, signing_algorithm);
326
327 /*
328 * Full-stop if a failure occurred initializing the signature digest
329 */
330 if (bsctx.signing_digest == NULL) {
331 Jmsg(bsctx.jcr, M_NOTSAVED, 0,
332 _("%s signature digest initialization failed\n"),
333 stream_to_ascii(signing_algorithm));
334 bsctx.jcr->JobErrors++;
335 goto bail_out;
336 }
337 }
338
339 /*
340 * Enable encryption
341 */
342 if (bsctx.jcr->impl->crypto.pki_encrypt) {
343 SetBit(FO_ENCRYPT, bsctx.ff_pkt->flags);
344 }
345 retval = true;
346
347 bail_out:
348 return retval;
349 }
350
351 /**
352 * Terminate the signing digest and send it to the Storage daemon
353 */
TerminateSigningDigest(b_save_ctx & bsctx)354 static inline bool TerminateSigningDigest(b_save_ctx& bsctx)
355 {
356 uint32_t size = 0;
357 bool retval = false;
358 SIGNATURE* signature = NULL;
359 BareosSocket* sd = bsctx.jcr->store_bsock;
360
361 if ((signature = crypto_sign_new(bsctx.jcr)) == NULL) {
362 Jmsg(bsctx.jcr, M_FATAL, 0,
363 _("Failed to allocate memory for crypto signature.\n"));
364 goto bail_out;
365 }
366
367 if (!CryptoSignAddSigner(signature, bsctx.signing_digest,
368 bsctx.jcr->impl->crypto.pki_keypair)) {
369 Jmsg(bsctx.jcr, M_FATAL, 0,
370 _("An error occurred while signing the stream.\n"));
371 goto bail_out;
372 }
373
374 /*
375 * Get signature size
376 */
377 if (!CryptoSignEncode(signature, NULL, &size)) {
378 Jmsg(bsctx.jcr, M_FATAL, 0,
379 _("An error occurred while signing the stream.\n"));
380 goto bail_out;
381 }
382
383 /*
384 * Grow the bsock buffer to fit our message if necessary
385 */
386 if (SizeofPoolMemory(sd->msg) < (int32_t)size) {
387 sd->msg = ReallocPoolMemory(sd->msg, size);
388 }
389
390 /*
391 * Send our header
392 */
393 sd->fsend("%ld %ld 0", bsctx.jcr->JobFiles, STREAM_SIGNED_DIGEST);
394 Dmsg1(300, "filed>stored:header %s", sd->msg);
395
396 /*
397 * Encode signature data
398 */
399 if (!CryptoSignEncode(signature, (uint8_t*)sd->msg, &size)) {
400 Jmsg(bsctx.jcr, M_FATAL, 0,
401 _("An error occurred while signing the stream.\n"));
402 goto bail_out;
403 }
404
405 sd->message_length = size;
406 sd->send();
407 sd->signal(BNET_EOD); /* end of checksum */
408 retval = true;
409
410 bail_out:
411 if (signature) { CryptoSignFree(signature); }
412 return retval;
413 }
414
415 /**
416 * Terminate any digest and send it to Storage daemon
417 */
TerminateDigest(b_save_ctx & bsctx)418 static inline bool TerminateDigest(b_save_ctx& bsctx)
419 {
420 uint32_t size;
421 bool retval = false;
422 BareosSocket* sd = bsctx.jcr->store_bsock;
423
424 sd->fsend("%ld %d 0", bsctx.jcr->JobFiles, bsctx.digest_stream);
425 Dmsg1(300, "filed>stored:header %s", sd->msg);
426
427 size = CRYPTO_DIGEST_MAX_SIZE;
428
429 /*
430 * Grow the bsock buffer to fit our message if necessary
431 */
432 if (SizeofPoolMemory(sd->msg) < (int32_t)size) {
433 sd->msg = ReallocPoolMemory(sd->msg, size);
434 }
435
436 if (!CryptoDigestFinalize(bsctx.digest, (uint8_t*)sd->msg, &size)) {
437 Jmsg(bsctx.jcr, M_FATAL, 0,
438 _("An error occurred finalizing signing the stream.\n"));
439 goto bail_out;
440 }
441
442 /*
443 * Keep the checksum if this file is a hardlink
444 */
445 if (bsctx.ff_pkt->linked) {
446 FfPktSetLinkDigest(bsctx.ff_pkt, bsctx.digest_stream, sd->msg, size);
447 }
448
449 sd->message_length = size;
450 sd->send();
451 sd->signal(BNET_EOD); /* end of checksum */
452 retval = true;
453
454 bail_out:
455 return retval;
456 }
457
DoBackupAcl(JobControlRecord * jcr,FindFilesPacket * ff_pkt)458 static inline bool DoBackupAcl(JobControlRecord* jcr, FindFilesPacket* ff_pkt)
459 {
460 bacl_exit_code retval;
461
462 jcr->impl->acl_data->filetype = ff_pkt->type;
463 jcr->impl->acl_data->last_fname = jcr->impl->last_fname;
464
465 if (jcr->IsPlugin()) {
466 retval = PluginBuildAclStreams(jcr, jcr->impl->acl_data.get(), ff_pkt);
467 } else {
468 retval = BuildAclStreams(jcr, jcr->impl->acl_data.get(), ff_pkt);
469 }
470
471 switch (retval) {
472 case bacl_exit_fatal:
473 return false;
474 case bacl_exit_error:
475 Jmsg(jcr, M_ERROR, 0, "%s", jcr->errmsg);
476 jcr->impl->acl_data->u.build->nr_errors++;
477 break;
478 case bacl_exit_ok:
479 break;
480 }
481
482 return true;
483 }
484
DoBackupXattr(JobControlRecord * jcr,FindFilesPacket * ff_pkt)485 static inline bool DoBackupXattr(JobControlRecord* jcr, FindFilesPacket* ff_pkt)
486 {
487 BxattrExitCode retval;
488
489 jcr->impl->xattr_data->last_fname = jcr->impl->last_fname;
490
491 if (jcr->IsPlugin()) {
492 retval = PluginBuildXattrStreams(jcr, jcr->impl->xattr_data.get(), ff_pkt);
493 } else {
494 retval = BuildXattrStreams(jcr, jcr->impl->xattr_data.get(), ff_pkt);
495 }
496
497 switch (retval) {
498 case BxattrExitCode::kErrorFatal:
499 return false;
500 case BxattrExitCode::kWarning:
501 Jmsg(jcr, M_WARNING, 0, "%s", jcr->errmsg);
502 break;
503 case BxattrExitCode::kError:
504 Jmsg(jcr, M_ERROR, 0, "%s", jcr->errmsg);
505 jcr->impl->xattr_data->u.build->nr_errors++;
506 break;
507 case BxattrExitCode::kSuccess:
508 break;
509 }
510
511 return true;
512 }
513
514 /**
515 * Called here by find() for each file included.
516 * This is a callback. The original is FindFiles() above.
517 *
518 * Send the file and its data to the Storage daemon.
519 *
520 * Returns: 1 if OK
521 * 0 if error
522 * -1 to ignore file/directory (not used here)
523 */
SaveFile(JobControlRecord * jcr,FindFilesPacket * ff_pkt,bool top_level)524 int SaveFile(JobControlRecord* jcr, FindFilesPacket* ff_pkt, bool top_level)
525 {
526 bool do_read = false;
527 bool plugin_started = false;
528 bool do_plugin_set = false;
529 int status, data_stream;
530 int rtnstat = 0;
531 b_save_ctx bsctx;
532 bool has_file_data = false;
533 struct save_pkt sp; /* use by option plugin */
534 BareosSocket* sd = jcr->store_bsock;
535
536 if (jcr->IsCanceled() || jcr->IsIncomplete()) { return 0; }
537
538 jcr->impl->num_files_examined++; /* bump total file count */
539
540 switch (ff_pkt->type) {
541 case FT_LNKSAVED: /* Hard linked, file already saved */
542 Dmsg2(130, "FT_LNKSAVED hard link: %s => %s\n", ff_pkt->fname,
543 ff_pkt->link);
544 break;
545 case FT_REGE:
546 Dmsg1(130, "FT_REGE saving: %s\n", ff_pkt->fname);
547 has_file_data = true;
548 break;
549 case FT_REG:
550 Dmsg1(130, "FT_REG saving: %s\n", ff_pkt->fname);
551 has_file_data = true;
552 break;
553 case FT_LNK:
554 Dmsg2(130, "FT_LNK saving: %s -> %s\n", ff_pkt->fname, ff_pkt->link);
555 break;
556 case FT_RESTORE_FIRST:
557 Dmsg1(100, "FT_RESTORE_FIRST saving: %s\n", ff_pkt->fname);
558 break;
559 case FT_PLUGIN_CONFIG:
560 Dmsg1(100, "FT_PLUGIN_CONFIG saving: %s\n", ff_pkt->fname);
561 break;
562 case FT_DIRBEGIN:
563 jcr->impl->num_files_examined--; /* correct file count */
564 return 1; /* not used */
565 case FT_NORECURSE:
566 Jmsg(jcr, M_INFO, 1,
567 _(" Recursion turned off. Will not descend from %s into %s\n"),
568 ff_pkt->top_fname, ff_pkt->fname);
569 ff_pkt->type = FT_DIREND; /* Backup only the directory entry */
570 break;
571 case FT_NOFSCHG:
572 /* Suppress message for /dev filesystems */
573 if (!IsInFileset(ff_pkt)) {
574 Jmsg(jcr, M_INFO, 1,
575 _(" %s is a different filesystem. Will not descend from %s "
576 "into it.\n"),
577 ff_pkt->fname, ff_pkt->top_fname);
578 }
579 ff_pkt->type = FT_DIREND; /* Backup only the directory entry */
580 break;
581 case FT_INVALIDFS:
582 Jmsg(jcr, M_INFO, 1,
583 _(" Disallowed filesystem. Will not descend from %s into %s\n"),
584 ff_pkt->top_fname, ff_pkt->fname);
585 ff_pkt->type = FT_DIREND; /* Backup only the directory entry */
586 break;
587 case FT_INVALIDDT:
588 Jmsg(jcr, M_INFO, 1,
589 _(" Disallowed drive type. Will not descend into %s\n"),
590 ff_pkt->fname);
591 break;
592 case FT_REPARSE:
593 case FT_JUNCTION:
594 case FT_DIREND:
595 Dmsg1(130, "FT_DIREND: %s\n", ff_pkt->link);
596 break;
597 case FT_SPEC:
598 Dmsg1(130, "FT_SPEC saving: %s\n", ff_pkt->fname);
599 if (S_ISSOCK(ff_pkt->statp.st_mode)) {
600 Jmsg(jcr, M_SKIPPED, 1, _(" Socket file skipped: %s\n"),
601 ff_pkt->fname);
602 return 1;
603 }
604 break;
605 case FT_RAW:
606 Dmsg1(130, "FT_RAW saving: %s\n", ff_pkt->fname);
607 has_file_data = true;
608 break;
609 case FT_FIFO:
610 Dmsg1(130, "FT_FIFO saving: %s\n", ff_pkt->fname);
611 break;
612 case FT_NOACCESS: {
613 BErrNo be;
614 Jmsg(jcr, M_NOTSAVED, 0, _(" Could not access \"%s\": ERR=%s\n"),
615 ff_pkt->fname, be.bstrerror(ff_pkt->ff_errno));
616 jcr->JobErrors++;
617 return 1;
618 }
619 case FT_NOFOLLOW: {
620 BErrNo be;
621 Jmsg(jcr, M_NOTSAVED, 0, _(" Could not follow link \"%s\": ERR=%s\n"),
622 ff_pkt->fname, be.bstrerror(ff_pkt->ff_errno));
623 jcr->JobErrors++;
624 return 1;
625 }
626 case FT_NOSTAT: {
627 BErrNo be;
628 Jmsg(jcr, M_NOTSAVED, 0, _(" Could not stat \"%s\": ERR=%s\n"),
629 ff_pkt->fname, be.bstrerror(ff_pkt->ff_errno));
630 jcr->JobErrors++;
631 return 1;
632 }
633 case FT_DIRNOCHG:
634 case FT_NOCHG:
635 Jmsg(jcr, M_SKIPPED, 1, _(" Unchanged file skipped: %s\n"),
636 ff_pkt->fname);
637 return 1;
638 case FT_ISARCH:
639 Jmsg(jcr, M_NOTSAVED, 0, _(" Archive file not saved: %s\n"),
640 ff_pkt->fname);
641 return 1;
642 case FT_NOOPEN: {
643 BErrNo be;
644 Jmsg(jcr, M_NOTSAVED, 0,
645 _(" Could not open directory \"%s\": ERR=%s\n"), ff_pkt->fname,
646 be.bstrerror(ff_pkt->ff_errno));
647 jcr->JobErrors++;
648 return 1;
649 }
650 case FT_DELETED:
651 Dmsg1(130, "FT_DELETED: %s\n", ff_pkt->fname);
652 break;
653 default:
654 Jmsg(jcr, M_NOTSAVED, 0, _(" Unknown file type %d; not saved: %s\n"),
655 ff_pkt->type, ff_pkt->fname);
656 jcr->JobErrors++;
657 return 1;
658 }
659
660 Dmsg1(130, "filed: sending %s to stored\n", ff_pkt->fname);
661
662 /*
663 * Setup backup signing context.
664 */
665 memset(&bsctx, 0, sizeof(b_save_ctx));
666 bsctx.digest_stream = STREAM_NONE;
667 bsctx.jcr = jcr;
668 bsctx.ff_pkt = ff_pkt;
669
670 /*
671 * Digests and encryption are only useful if there's file data
672 */
673 if (has_file_data) {
674 if (!SetupEncryptionDigests(bsctx)) { goto good_rtn; }
675 }
676
677 /*
678 * Initialize the file descriptor we use for data and other streams.
679 */
680 binit(&ff_pkt->bfd);
681 if (BitIsSet(FO_PORTABLE, ff_pkt->flags)) {
682 SetPortableBackup(&ff_pkt->bfd); /* disable Win32 BackupRead() */
683 }
684
685 /*
686 * Option and cmd plugin are not compatible together
687 */
688 if (ff_pkt->cmd_plugin) {
689 do_plugin_set = true;
690 } else if (ff_pkt->opt_plugin) {
691 /*
692 * Ask the option plugin what to do with this file
693 */
694 switch (PluginOptionHandleFile(jcr, ff_pkt, &sp)) {
695 case bRC_OK:
696 Dmsg2(10, "Option plugin %s will be used to backup %s\n",
697 ff_pkt->plugin, ff_pkt->fname);
698 jcr->opt_plugin = true;
699 jcr->impl->plugin_sp = &sp;
700 PluginUpdateFfPkt(ff_pkt, &sp);
701 do_plugin_set = true;
702 break;
703 case bRC_Skip:
704 Dmsg2(10, "Option plugin %s decided to skip %s\n", ff_pkt->plugin,
705 ff_pkt->fname);
706 goto good_rtn;
707 case bRC_Core:
708 Dmsg2(10, "Option plugin %s decided to let bareos handle %s\n",
709 ff_pkt->plugin, ff_pkt->fname);
710 break;
711 default:
712 goto bail_out;
713 }
714 }
715
716 if (do_plugin_set) {
717 /*
718 * Tell bfile that it needs to call plugin
719 */
720 if (!SetCmdPlugin(&ff_pkt->bfd, jcr)) { goto bail_out; }
721 SendPluginName(jcr, sd, true); /* signal start of plugin data */
722 plugin_started = true;
723 }
724
725 /*
726 * Send attributes -- must be done after binit()
727 */
728 if (!EncodeAndSendAttributes(jcr, ff_pkt, data_stream)) { goto bail_out; }
729
730 /*
731 * Meta data only for restore object
732 */
733 if (IS_FT_OBJECT(ff_pkt->type)) { goto good_rtn; }
734
735 /*
736 * Meta data only for deleted files
737 */
738 if (ff_pkt->type == FT_DELETED) { goto good_rtn; }
739
740 /*
741 * Set up the encryption context and send the session data to the SD
742 */
743 if (has_file_data && jcr->impl->crypto.pki_encrypt) {
744 if (!CryptoSessionSend(jcr, sd)) { goto bail_out; }
745 }
746
747 /*
748 * For a command plugin use the setting from the plugins savepkt no_read field
749 * which is saved in the ff_pkt->no_read variable. do_read is the inverted
750 * value of this variable as no_read == TRUE means do_read == FALSE
751 */
752 if (ff_pkt->cmd_plugin) {
753 do_read = !ff_pkt->no_read;
754 } else {
755 /*
756 * Open any file with data that we intend to save, then save it.
757 *
758 * Note, if is_win32_backup, we must open the Directory so that
759 * the BackupRead will save its permissions and ownership streams.
760 */
761 if (ff_pkt->type != FT_LNKSAVED && S_ISREG(ff_pkt->statp.st_mode)) {
762 #ifdef HAVE_WIN32
763 do_read = !IsPortableBackup(&ff_pkt->bfd) || ff_pkt->statp.st_size > 0;
764 #else
765 do_read = ff_pkt->statp.st_size > 0;
766 #endif
767 } else if (ff_pkt->type == FT_RAW || ff_pkt->type == FT_FIFO
768 || ff_pkt->type == FT_REPARSE || ff_pkt->type == FT_JUNCTION
769 || (!IsPortableBackup(&ff_pkt->bfd)
770 && ff_pkt->type == FT_DIREND)) {
771 do_read = true;
772 }
773 }
774
775 Dmsg2(150, "type=%d do_read=%d\n", ff_pkt->type, do_read);
776 if (do_read) {
777 btimer_t* tid;
778 int noatime;
779
780 if (ff_pkt->type == FT_FIFO) {
781 tid = start_thread_timer(jcr, pthread_self(), 60);
782 } else {
783 tid = NULL;
784 }
785
786 noatime = BitIsSet(FO_NOATIME, ff_pkt->flags) ? O_NOATIME : 0;
787 ff_pkt->bfd.reparse_point
788 = (ff_pkt->type == FT_REPARSE || ff_pkt->type == FT_JUNCTION);
789
790 if (bopen(&ff_pkt->bfd, ff_pkt->fname, O_RDONLY | O_BINARY | noatime, 0,
791 ff_pkt->statp.st_rdev)
792 < 0) {
793 ff_pkt->ff_errno = errno;
794 BErrNo be;
795 Jmsg(jcr, M_NOTSAVED, 0, _(" Cannot open \"%s\": ERR=%s.\n"),
796 ff_pkt->fname, be.bstrerror());
797 jcr->JobErrors++;
798 if (tid) {
799 StopThreadTimer(tid);
800 tid = NULL;
801 }
802 goto good_rtn;
803 }
804
805 if (tid) {
806 StopThreadTimer(tid);
807 tid = NULL;
808 }
809
810 status = send_data(jcr, data_stream, ff_pkt, bsctx.digest,
811 bsctx.signing_digest);
812
813 if (BitIsSet(FO_CHKCHANGES, ff_pkt->flags)) { HasFileChanged(jcr, ff_pkt); }
814
815 bclose(&ff_pkt->bfd);
816
817 if (!status) { goto bail_out; }
818 }
819
820 if (have_darwin_os) {
821 /*
822 * Regular files can have resource forks and Finder Info
823 */
824 if (ff_pkt->type != FT_LNKSAVED
825 && (S_ISREG(ff_pkt->statp.st_mode)
826 && BitIsSet(FO_HFSPLUS, ff_pkt->flags))) {
827 if (!SaveRsrcAndFinder(bsctx)) { goto bail_out; }
828 }
829 }
830
831 /*
832 * Save ACLs when requested and available for anything not being a symlink.
833 */
834 if (have_acl) {
835 if (BitIsSet(FO_ACL, ff_pkt->flags) && ff_pkt->type != FT_LNK) {
836 if (!DoBackupAcl(jcr, ff_pkt)) { goto bail_out; }
837 }
838 }
839
840 /*
841 * Save Extended Attributes when requested and available for all files.
842 */
843 if (have_xattr) {
844 if (BitIsSet(FO_XATTR, ff_pkt->flags)) {
845 if (!DoBackupXattr(jcr, ff_pkt)) { goto bail_out; }
846 }
847 }
848
849 /*
850 * Terminate the signing digest and send it to the Storage daemon
851 */
852 if (bsctx.signing_digest) {
853 if (!TerminateSigningDigest(bsctx)) { goto bail_out; }
854 }
855
856 /*
857 * Terminate any digest and send it to Storage daemon
858 */
859 if (bsctx.digest) {
860 if (!TerminateDigest(bsctx)) { goto bail_out; }
861 }
862
863 /*
864 * Check if original file has a digest, and send it
865 */
866 if (ff_pkt->type == FT_LNKSAVED && ff_pkt->digest) {
867 Dmsg2(300, "Link %s digest %d\n", ff_pkt->fname, ff_pkt->digest_len);
868 sd->fsend("%ld %d 0", jcr->JobFiles, ff_pkt->digest_stream);
869
870 sd->msg = CheckPoolMemorySize(sd->msg, ff_pkt->digest_len);
871 memcpy(sd->msg, ff_pkt->digest, ff_pkt->digest_len);
872 sd->message_length = ff_pkt->digest_len;
873 sd->send();
874
875 sd->signal(BNET_EOD); /* end of hardlink record */
876 }
877
878 good_rtn:
879 rtnstat = jcr->IsCanceled() ? 0 : 1; /* good return if not canceled */
880
881 bail_out:
882 if (jcr->IsIncomplete() || jcr->IsCanceled()) { rtnstat = 0; }
883 if (plugin_started) {
884 SendPluginName(jcr, sd, false); /* signal end of plugin data */
885 }
886 if (ff_pkt->opt_plugin) {
887 jcr->impl->plugin_sp = NULL; /* sp is local to this function */
888 jcr->opt_plugin = false;
889 }
890 if (bsctx.digest) { CryptoDigestFree(bsctx.digest); }
891 if (bsctx.signing_digest) { CryptoDigestFree(bsctx.signing_digest); }
892
893 return rtnstat;
894 }
895
896 /**
897 * Handle the data just read and send it to the SD after doing any
898 * postprocessing needed.
899 */
SendDataToSd(b_ctx * bctx)900 static inline bool SendDataToSd(b_ctx* bctx)
901 {
902 BareosSocket* sd = bctx->jcr->store_bsock;
903 bool need_more_data;
904
905 /*
906 * Check for sparse blocks
907 */
908 if (BitIsSet(FO_SPARSE, bctx->ff_pkt->flags)) {
909 bool allZeros;
910 ser_declare;
911
912 allZeros = false;
913 if ((sd->message_length == bctx->rsize
914 && (bctx->fileAddr + sd->message_length
915 < (uint64_t)bctx->ff_pkt->statp.st_size))
916 || ((bctx->ff_pkt->type == FT_RAW || bctx->ff_pkt->type == FT_FIFO)
917 && ((uint64_t)bctx->ff_pkt->statp.st_size == 0))) {
918 allZeros = IsBufZero(bctx->rbuf, bctx->rsize);
919 }
920
921 if (!allZeros) {
922 /*
923 * Put file address as first data in buffer
924 */
925 SerBegin(bctx->wbuf, OFFSET_FADDR_SIZE);
926 ser_uint64(bctx->fileAddr); /* store fileAddr in begin of buffer */
927 }
928
929 bctx->fileAddr += sd->message_length; /* update file address */
930
931 /*
932 * Skip block of all zeros
933 */
934 if (allZeros) { return true; }
935 } else if (BitIsSet(FO_OFFSETS, bctx->ff_pkt->flags)) {
936 ser_declare;
937 SerBegin(bctx->wbuf, OFFSET_FADDR_SIZE);
938 ser_uint64(bctx->ff_pkt->bfd.offset); /* store offset in begin of buffer */
939 }
940
941 bctx->jcr->ReadBytes += sd->message_length; /* count bytes read */
942
943 /*
944 * Uncompressed cipher input length
945 */
946 bctx->cipher_input_len = sd->message_length;
947
948 /*
949 * Update checksum if requested
950 */
951 if (bctx->digest) {
952 CryptoDigestUpdate(bctx->digest, (uint8_t*)bctx->rbuf, sd->message_length);
953 }
954
955 /*
956 * Update signing digest if requested
957 */
958 if (bctx->signing_digest) {
959 CryptoDigestUpdate(bctx->signing_digest, (uint8_t*)bctx->rbuf,
960 sd->message_length);
961 }
962
963 /*
964 * Compress the data.
965 */
966 if (BitIsSet(FO_COMPRESS, bctx->ff_pkt->flags)) {
967 if (!CompressData(bctx->jcr, bctx->ff_pkt->Compress_algo, bctx->rbuf,
968 bctx->jcr->store_bsock->message_length, bctx->cbuf,
969 bctx->max_compress_len, &bctx->compress_len)) {
970 return false;
971 }
972
973 /*
974 * See if we need to generate a compression header.
975 */
976 if (bctx->chead) {
977 ser_declare;
978
979 /*
980 * Complete header
981 */
982 SerBegin(bctx->chead, sizeof(comp_stream_header));
983 ser_uint32(bctx->ch.magic);
984 ser_uint32(bctx->compress_len);
985 ser_uint16(bctx->ch.level);
986 ser_uint16(bctx->ch.version);
987 SerEnd(bctx->chead, sizeof(comp_stream_header));
988
989 bctx->compress_len += sizeof(comp_stream_header); /* add size of header */
990 }
991
992 bctx->jcr->store_bsock->message_length
993 = bctx->compress_len; /* set compressed length */
994 bctx->cipher_input_len = bctx->compress_len;
995 }
996
997 /*
998 * Encrypt the data.
999 */
1000 need_more_data = false;
1001 if (BitIsSet(FO_ENCRYPT, bctx->ff_pkt->flags)
1002 && !EncryptData(bctx, &need_more_data)) {
1003 if (need_more_data) { return true; }
1004 return false;
1005 }
1006
1007 /*
1008 * Send the buffer to the Storage daemon
1009 */
1010 if (BitIsSet(FO_SPARSE, bctx->ff_pkt->flags)
1011 || BitIsSet(FO_OFFSETS, bctx->ff_pkt->flags)) {
1012 sd->message_length += OFFSET_FADDR_SIZE; /* include fileAddr in size */
1013 }
1014 sd->msg = bctx->wbuf; /* set correct write buffer */
1015
1016 if (!sd->send()) {
1017 if (!bctx->jcr->IsJobCanceled()) {
1018 Jmsg1(bctx->jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
1019 sd->bstrerror());
1020 }
1021 return false;
1022 }
1023
1024 Dmsg1(130, "Send data to SD len=%d\n", sd->message_length);
1025 bctx->jcr->JobBytes += sd->message_length; /* count bytes saved possibly
1026 compressed/encrypted */
1027 sd->msg = bctx->msgsave; /* restore read buffer */
1028
1029 return true;
1030 }
1031
1032 #ifdef HAVE_WIN32
1033 /**
1034 * Callback method for ReadEncryptedFileRaw()
1035 */
send_efs_data(PBYTE pbData,PVOID pvCallbackContext,ULONG ulLength)1036 static DWORD WINAPI send_efs_data(PBYTE pbData,
1037 PVOID pvCallbackContext,
1038 ULONG ulLength)
1039 {
1040 b_ctx* bctx = (b_ctx*)pvCallbackContext;
1041 BareosSocket* sd = bctx->jcr->store_bsock;
1042
1043 if (ulLength == 0) { return ERROR_SUCCESS; }
1044
1045 /*
1046 * See if we can fit the data into the current bctx->rbuf which can hold
1047 * bctx->rsize bytes.
1048 */
1049 if (ulLength <= (ULONG)bctx->rsize) {
1050 sd->message_length = ulLength;
1051 memcpy(bctx->rbuf, pbData, ulLength);
1052 if (!SendDataToSd(bctx)) { return ERROR_NET_WRITE_FAULT; }
1053 } else {
1054 /*
1055 * Need to chunk the data into pieces.
1056 */
1057 ULONG offset = 0;
1058
1059 while (ulLength > 0) {
1060 sd->message_length = MIN((ULONG)bctx->rsize, ulLength);
1061 memcpy(bctx->rbuf, pbData + offset, sd->message_length);
1062 if (!SendDataToSd(bctx)) { return ERROR_NET_WRITE_FAULT; }
1063
1064 offset += sd->message_length;
1065 ulLength -= sd->message_length;
1066 }
1067 }
1068
1069 return ERROR_SUCCESS;
1070 }
1071
1072 /**
1073 * Send the content of an Encrypted file on an EFS filesystem.
1074 */
SendEncryptedData(b_ctx & bctx)1075 static inline bool SendEncryptedData(b_ctx& bctx)
1076 {
1077 bool retval = false;
1078
1079 if (!p_ReadEncryptedFileRaw) {
1080 Jmsg0(bctx.jcr, M_FATAL, 0,
1081 _("Encrypted file but no EFS support functions\n"));
1082 }
1083
1084 /*
1085 * The EFS read function, ReadEncryptedFileRaw(), works in a specific way.
1086 * You have to give it a function that it calls repeatedly every time the
1087 * read buffer is filled.
1088 *
1089 * So ReadEncryptedFileRaw() will not return until it has read the whole file.
1090 */
1091 if (p_ReadEncryptedFileRaw((PFE_EXPORT_FUNC)send_efs_data, &bctx,
1092 bctx.ff_pkt->bfd.pvContext)) {
1093 goto bail_out;
1094 }
1095 retval = true;
1096
1097 bail_out:
1098 return retval;
1099 }
1100 #endif
1101
1102 /**
1103 * Send the content of a file on anything but an EFS filesystem.
1104 */
SendPlainData(b_ctx & bctx)1105 static inline bool SendPlainData(b_ctx& bctx)
1106 {
1107 bool retval = false;
1108 BareosSocket* sd = bctx.jcr->store_bsock;
1109
1110 /*
1111 * Read the file data
1112 */
1113 while ((sd->message_length
1114 = (uint32_t)bread(&bctx.ff_pkt->bfd, bctx.rbuf, bctx.rsize))
1115 > 0) {
1116 if (!SendDataToSd(&bctx)) { goto bail_out; }
1117 }
1118 retval = true;
1119
1120 bail_out:
1121 return retval;
1122 }
1123
1124 /**
1125 * Send data read from an already open file descriptor.
1126 *
1127 * We return 1 on sucess and 0 on errors.
1128 *
1129 * ***FIXME***
1130 * We use ff_pkt->statp.st_size when FO_SPARSE to know when to stop reading.
1131 * Currently this is not a problem as the only other stream, resource forks,
1132 * are not handled as sparse files.
1133 */
send_data(JobControlRecord * jcr,int stream,FindFilesPacket * ff_pkt,DIGEST * digest,DIGEST * signing_digest)1134 static int send_data(JobControlRecord* jcr,
1135 int stream,
1136 FindFilesPacket* ff_pkt,
1137 DIGEST* digest,
1138 DIGEST* signing_digest)
1139 {
1140 b_ctx bctx;
1141 BareosSocket* sd = jcr->store_bsock;
1142 #ifdef FD_NO_SEND_TEST
1143 return 1;
1144 #endif
1145
1146 /*
1147 * Setup backup context.
1148 */
1149 memset(&bctx, 0, sizeof(b_ctx));
1150 bctx.jcr = jcr;
1151 bctx.ff_pkt = ff_pkt;
1152 bctx.msgsave = sd->msg; /* save the original sd buffer */
1153 bctx.rbuf = sd->msg; /* read buffer */
1154 bctx.wbuf = sd->msg; /* write buffer */
1155 bctx.rsize = jcr->buf_size; /* read buffer size */
1156 bctx.cipher_input = (uint8_t*)bctx.rbuf; /* encrypt uncompressed data */
1157 bctx.digest = digest; /* encryption digest */
1158 bctx.signing_digest = signing_digest; /* signing digest */
1159
1160 Dmsg1(300, "Saving data, type=%d\n", ff_pkt->type);
1161
1162 if (!SetupCompressionContext(bctx)) { goto bail_out; }
1163
1164 if (!SetupEncryptionContext(bctx)) { goto bail_out; }
1165
1166 /*
1167 * Send Data header to Storage daemon
1168 * <file-index> <stream> <info>
1169 */
1170 if (!sd->fsend("%ld %d 0", jcr->JobFiles, stream)) {
1171 if (!jcr->IsJobCanceled()) {
1172 Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
1173 sd->bstrerror());
1174 }
1175 goto bail_out;
1176 }
1177 Dmsg1(300, ">stored: datahdr %s", sd->msg);
1178
1179 /*
1180 * Make space at beginning of buffer for fileAddr because this
1181 * same buffer will be used for writing if compression is off.
1182 */
1183 if (BitIsSet(FO_SPARSE, ff_pkt->flags)
1184 || BitIsSet(FO_OFFSETS, ff_pkt->flags)) {
1185 bctx.rbuf += OFFSET_FADDR_SIZE;
1186 bctx.rsize -= OFFSET_FADDR_SIZE;
1187 #ifdef HAVE_FREEBSD_OS
1188 /*
1189 * To read FreeBSD partitions, the read size must be a multiple of 512.
1190 */
1191 bctx.rsize = (bctx.rsize / 512) * 512;
1192 #endif
1193 }
1194
1195 /*
1196 * A RAW device read on win32 only works if the buffer is a multiple of 512
1197 */
1198 #ifdef HAVE_WIN32
1199 if (S_ISBLK(ff_pkt->statp.st_mode)) { bctx.rsize = (bctx.rsize / 512) * 512; }
1200
1201 if (ff_pkt->statp.st_rdev & FILE_ATTRIBUTE_ENCRYPTED) {
1202 if (!SendEncryptedData(bctx)) { goto bail_out; }
1203 } else {
1204 if (!SendPlainData(bctx)) { goto bail_out; }
1205 }
1206 #else
1207 if (!SendPlainData(bctx)) { goto bail_out; }
1208 #endif
1209
1210 if (sd->message_length < 0) { /* error */
1211 BErrNo be;
1212 Jmsg(jcr, M_ERROR, 0, _("Read error on file %s. ERR=%s\n"), ff_pkt->fname,
1213 be.bstrerror(ff_pkt->bfd.BErrNo));
1214 if (jcr->JobErrors++ > 1000) { /* insanity check */
1215 Jmsg(jcr, M_FATAL, 0, _("Too many errors. JobErrors=%d.\n"),
1216 jcr->JobErrors);
1217 }
1218 } else if (BitIsSet(FO_ENCRYPT, ff_pkt->flags)) {
1219 /*
1220 * For encryption, we must call finalize to push out any buffered data.
1221 */
1222 if (!CryptoCipherFinalize(bctx.cipher_ctx,
1223 (uint8_t*)jcr->impl->crypto.crypto_buf,
1224 &bctx.encrypted_len)) {
1225 /*
1226 * Padding failed. Shouldn't happen.
1227 */
1228 Jmsg(jcr, M_FATAL, 0, _("Encryption padding error\n"));
1229 goto bail_out;
1230 }
1231
1232 /*
1233 * Note, on SSL pre-0.9.7, there is always some output
1234 */
1235 if (bctx.encrypted_len > 0) {
1236 sd->message_length = bctx.encrypted_len; /* set encrypted length */
1237 sd->msg = jcr->impl->crypto.crypto_buf; /* set correct write buffer */
1238 if (!sd->send()) {
1239 if (!jcr->IsJobCanceled()) {
1240 Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
1241 sd->bstrerror());
1242 }
1243 goto bail_out;
1244 }
1245 Dmsg1(130, "Send data to SD len=%d\n", sd->message_length);
1246 jcr->JobBytes += sd->message_length; /* count bytes saved possibly
1247 compressed/encrypted */
1248 sd->msg = bctx.msgsave; /* restore bnet buffer */
1249 }
1250 }
1251
1252 if (!sd->signal(BNET_EOD)) { /* indicate end of file data */
1253 if (!jcr->IsJobCanceled()) {
1254 Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
1255 sd->bstrerror());
1256 }
1257 goto bail_out;
1258 }
1259
1260 /*
1261 * Free the cipher context
1262 */
1263 if (bctx.cipher_ctx) { CryptoCipherFree(bctx.cipher_ctx); }
1264
1265 return 1;
1266
1267 bail_out:
1268 /*
1269 * Free the cipher context
1270 */
1271 if (bctx.cipher_ctx) { CryptoCipherFree(bctx.cipher_ctx); }
1272
1273 sd->msg = bctx.msgsave; /* restore bnet buffer */
1274 sd->message_length = 0;
1275
1276 return 0;
1277 }
1278
EncodeAndSendAttributes(JobControlRecord * jcr,FindFilesPacket * ff_pkt,int & data_stream)1279 bool EncodeAndSendAttributes(JobControlRecord* jcr,
1280 FindFilesPacket* ff_pkt,
1281 int& data_stream)
1282 {
1283 BareosSocket* sd = jcr->store_bsock;
1284 PoolMem attribs(PM_NAME), attribsExBuf(PM_NAME);
1285 char* attribsEx = NULL;
1286 int attr_stream;
1287 int comp_len;
1288 bool status;
1289 int hangup = GetHangup();
1290 #ifdef FD_NO_SEND_TEST
1291 return true;
1292 #endif
1293
1294 Dmsg1(300, "encode_and_send_attrs fname=%s\n", ff_pkt->fname);
1295 /** Find what data stream we will use, then encode the attributes */
1296 if ((data_stream = SelectDataStream(ff_pkt, me->compatible)) == STREAM_NONE) {
1297 /* This should not happen */
1298 Jmsg0(jcr, M_FATAL, 0,
1299 _("Invalid file flags, no supported data stream type.\n"));
1300 return false;
1301 }
1302 EncodeStat(attribs.c_str(), &ff_pkt->statp, sizeof(ff_pkt->statp),
1303 ff_pkt->LinkFI, data_stream);
1304
1305 /** Now possibly extend the attributes */
1306 if (IS_FT_OBJECT(ff_pkt->type)) {
1307 attr_stream = STREAM_RESTORE_OBJECT;
1308 } else {
1309 attribsEx = attribsExBuf.c_str();
1310 attr_stream = encode_attribsEx(jcr, attribsEx, ff_pkt);
1311 }
1312
1313 Dmsg3(300, "File %s\nattribs=%s\nattribsEx=%s\n", ff_pkt->fname,
1314 attribs.c_str(), attribsEx);
1315
1316 jcr->lock();
1317 jcr->JobFiles++; /* increment number of files sent */
1318 ff_pkt->FileIndex = jcr->JobFiles; /* return FileIndex */
1319 PmStrcpy(jcr->impl->last_fname, ff_pkt->fname);
1320 jcr->unlock();
1321
1322 /*
1323 * Debug code: check if we must hangup
1324 */
1325 if (hangup && (jcr->JobFiles > (uint32_t)hangup)) {
1326 jcr->setJobStatus(JS_Incomplete);
1327 Jmsg1(jcr, M_FATAL, 0, "Debug hangup requested after %d files.\n", hangup);
1328 SetHangup(0);
1329 return false;
1330 }
1331
1332 /**
1333 * Send Attributes header to Storage daemon
1334 * <file-index> <stream> <info>
1335 */
1336 if (!sd->fsend("%ld %d 0", jcr->JobFiles, attr_stream)) {
1337 if (!jcr->IsCanceled() && !jcr->IsIncomplete()) {
1338 Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
1339 sd->bstrerror());
1340 }
1341 return false;
1342 }
1343 Dmsg1(300, ">stored: attrhdr %s", sd->msg);
1344
1345 /**
1346 * Send file attributes to Storage daemon
1347 * File_index
1348 * File type
1349 * Filename (full path)
1350 * Encoded attributes
1351 * Link name (if type==FT_LNK or FT_LNKSAVED)
1352 * Encoded extended-attributes (for Win32)
1353 * Delta Sequence Number
1354 *
1355 * or send Restore Object to Storage daemon
1356 * File_index
1357 * File_type
1358 * Object_index
1359 * Object_len (possibly compressed)
1360 * Object_full_len (not compressed)
1361 * Object_compression
1362 * Plugin_name
1363 * Object_name
1364 * Binary Object data
1365 *
1366 * For a directory, link is the same as fname, but with trailing
1367 * slash. For a linked file, link is the link.
1368 */
1369 if (!IS_FT_OBJECT(ff_pkt->type)
1370 && ff_pkt->type != FT_DELETED) { /* already stripped */
1371 StripPath(ff_pkt);
1372 }
1373 switch (ff_pkt->type) {
1374 case FT_JUNCTION:
1375 case FT_LNK:
1376 case FT_LNKSAVED:
1377 Dmsg3(300, "Link %d %s to %s\n", jcr->JobFiles, ff_pkt->fname,
1378 ff_pkt->link);
1379 status = sd->fsend("%ld %d %s%c%s%c%s%c%s%c%u%c", jcr->JobFiles,
1380 ff_pkt->type, ff_pkt->fname, 0, attribs.c_str(), 0,
1381 ff_pkt->link, 0, attribsEx, 0, ff_pkt->delta_seq, 0);
1382 break;
1383 case FT_DIREND:
1384 case FT_REPARSE:
1385 /* Here link is the canonical filename (i.e. with trailing slash) */
1386 status = sd->fsend("%ld %d %s%c%s%c%c%s%c%u%c", jcr->JobFiles,
1387 ff_pkt->type, ff_pkt->link, 0, attribs.c_str(), 0, 0,
1388 attribsEx, 0, ff_pkt->delta_seq, 0);
1389 break;
1390 case FT_PLUGIN_CONFIG:
1391 case FT_RESTORE_FIRST:
1392 comp_len = ff_pkt->object_len;
1393 ff_pkt->object_compression = 0;
1394
1395 if (ff_pkt->object_len > 1000) {
1396 /*
1397 * Big object, compress it
1398 */
1399 comp_len = compressBound(ff_pkt->object_len);
1400 POOLMEM* comp_obj = GetMemory(comp_len);
1401 /*
1402 * FIXME: check Zdeflate error
1403 */
1404 Zdeflate(ff_pkt->object, ff_pkt->object_len, comp_obj, comp_len);
1405 if (comp_len < ff_pkt->object_len) {
1406 ff_pkt->object = comp_obj;
1407 ff_pkt->object_compression = 1; /* zlib level 9 compression */
1408 } else {
1409 /*
1410 * Uncompressed object smaller, use it
1411 */
1412 comp_len = ff_pkt->object_len;
1413 }
1414 Dmsg2(100, "Object compressed from %d to %d bytes\n",
1415 ff_pkt->object_len, comp_len);
1416 }
1417
1418 sd->message_length = Mmsg(
1419 sd->msg, "%d %d %d %d %d %d %s%c%s%c", jcr->JobFiles, ff_pkt->type,
1420 ff_pkt->object_index, comp_len, ff_pkt->object_len,
1421 ff_pkt->object_compression, ff_pkt->fname, 0, ff_pkt->object_name, 0);
1422 sd->msg = CheckPoolMemorySize(sd->msg, sd->message_length + comp_len + 2);
1423 memcpy(sd->msg + sd->message_length, ff_pkt->object, comp_len);
1424
1425 /*
1426 * Note we send one extra byte so Dir can store zero after object
1427 */
1428 sd->message_length += comp_len + 1;
1429 status = sd->send();
1430 if (ff_pkt->object_compression) { FreeAndNullPoolMemory(ff_pkt->object); }
1431 break;
1432 case FT_REG:
1433 status = sd->fsend("%ld %d %s%c%s%c%c%s%c%d%c", jcr->JobFiles,
1434 ff_pkt->type, ff_pkt->fname, 0, attribs.c_str(), 0, 0,
1435 attribsEx, 0, ff_pkt->delta_seq, 0);
1436 break;
1437 default:
1438 status = sd->fsend("%ld %d %s%c%s%c%c%s%c%u%c", jcr->JobFiles,
1439 ff_pkt->type, ff_pkt->fname, 0, attribs.c_str(), 0, 0,
1440 attribsEx, 0, ff_pkt->delta_seq, 0);
1441 break;
1442 }
1443
1444 if (!IS_FT_OBJECT(ff_pkt->type) && ff_pkt->type != FT_DELETED) {
1445 UnstripPath(ff_pkt);
1446 }
1447
1448 Dmsg2(300, ">stored: attr len=%d: %s\n", sd->message_length, sd->msg);
1449 if (!status && !jcr->IsJobCanceled()) {
1450 Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
1451 sd->bstrerror());
1452 }
1453
1454 sd->signal(BNET_EOD); /* indicate end of attributes data */
1455
1456 return status;
1457 }
1458
1459 /**
1460 * Do in place strip of path
1461 */
do_strip(int count,char * in)1462 static bool do_strip(int count, char* in)
1463 {
1464 char* out = in;
1465 int stripped;
1466 int numsep = 0;
1467
1468 /**
1469 * Copy to first path separator -- Win32 might have c: ...
1470 */
1471 while (*in && !IsPathSeparator(*in)) {
1472 out++;
1473 in++;
1474 }
1475 if (*in) { /* Not at the end of the string */
1476 out++;
1477 in++;
1478 numsep++; /* one separator seen */
1479 }
1480 for (stripped = 0; stripped < count && *in; stripped++) {
1481 while (*in && !IsPathSeparator(*in)) { in++; /* skip chars */ }
1482 if (*in) {
1483 numsep++; /* count separators seen */
1484 in++; /* skip separator */
1485 }
1486 }
1487
1488 /*
1489 * Copy to end
1490 */
1491 while (*in) { /* copy to end */
1492 if (IsPathSeparator(*in)) { numsep++; }
1493 *out++ = *in++;
1494 }
1495 *out = 0;
1496 Dmsg4(500, "stripped=%d count=%d numsep=%d sep>count=%d\n", stripped, count,
1497 numsep, numsep > count);
1498 return stripped == count && numsep > count;
1499 }
1500
1501 /**
1502 * If requested strip leading components of the path so that we can
1503 * save file as if it came from a subdirectory. This is most useful
1504 * for dealing with snapshots, by removing the snapshot directory, or
1505 * in handling vendor migrations where files have been restored with
1506 * a vendor product into a subdirectory.
1507 */
StripPath(FindFilesPacket * ff_pkt)1508 void StripPath(FindFilesPacket* ff_pkt)
1509 {
1510 if (!BitIsSet(FO_STRIPPATH, ff_pkt->flags) || ff_pkt->StripPath <= 0) {
1511 Dmsg1(200, "No strip for %s\n", ff_pkt->fname);
1512 return;
1513 }
1514
1515 if (!ff_pkt->fname_save) {
1516 ff_pkt->fname_save = GetPoolMemory(PM_FNAME);
1517 ff_pkt->link_save = GetPoolMemory(PM_FNAME);
1518 }
1519
1520 PmStrcpy(ff_pkt->fname_save, ff_pkt->fname);
1521 if (ff_pkt->type != FT_LNK && ff_pkt->fname != ff_pkt->link) {
1522 PmStrcpy(ff_pkt->link_save, ff_pkt->link);
1523 Dmsg2(500, "strcpy link_save=%d link=%d\n", strlen(ff_pkt->link_save),
1524 strlen(ff_pkt->link));
1525 }
1526
1527 /**
1528 * Strip path. If it doesn't succeed put it back. If it does, and there
1529 * is a different link string, attempt to strip the link. If it fails,
1530 * back them both back. Do not strip symlinks. I.e. if either stripping
1531 * fails don't strip anything.
1532 */
1533 if (!do_strip(ff_pkt->StripPath, ff_pkt->fname)) {
1534 UnstripPath(ff_pkt);
1535 goto rtn;
1536 }
1537
1538 /**
1539 * Strip links but not symlinks
1540 */
1541 if (ff_pkt->type != FT_LNK && ff_pkt->fname != ff_pkt->link) {
1542 if (!do_strip(ff_pkt->StripPath, ff_pkt->link)) { UnstripPath(ff_pkt); }
1543 }
1544
1545 rtn:
1546 Dmsg3(100, "fname=%s stripped=%s link=%s\n", ff_pkt->fname_save,
1547 ff_pkt->fname, ff_pkt->link);
1548 }
1549
UnstripPath(FindFilesPacket * ff_pkt)1550 void UnstripPath(FindFilesPacket* ff_pkt)
1551 {
1552 if (!BitIsSet(FO_STRIPPATH, ff_pkt->flags) || ff_pkt->StripPath <= 0) {
1553 return;
1554 }
1555
1556 strcpy(ff_pkt->fname, ff_pkt->fname_save);
1557 if (ff_pkt->type != FT_LNK && ff_pkt->fname != ff_pkt->link) {
1558 Dmsg2(500, "strcpy link=%s link_save=%s\n", ff_pkt->link,
1559 ff_pkt->link_save);
1560 strcpy(ff_pkt->link, ff_pkt->link_save);
1561 Dmsg2(500, "strcpy link=%d link_save=%d\n", strlen(ff_pkt->link),
1562 strlen(ff_pkt->link_save));
1563 }
1564 }
1565
CloseVssBackupSession(JobControlRecord * jcr)1566 static void CloseVssBackupSession(JobControlRecord* jcr)
1567 {
1568 #if defined(WIN32_VSS)
1569 /*
1570 * STOP VSS ON WIN32
1571 * Tell vss to close the backup session
1572 */
1573 if (jcr->impl->pVSSClient) {
1574 /*
1575 * We are about to call the BackupComplete VSS method so let all plugins
1576 * know that by raising the bEventVssBackupComplete event.
1577 */
1578 GeneratePluginEvent(jcr, bEventVssBackupComplete);
1579 if (jcr->impl->pVSSClient->CloseBackup()) {
1580 /*
1581 * Inform user about writer states
1582 */
1583 for (size_t i = 0; i < jcr->impl->pVSSClient->GetWriterCount(); i++) {
1584 int msg_type = M_INFO;
1585 if (jcr->impl->pVSSClient->GetWriterState(i) < 1) {
1586 msg_type = M_WARNING;
1587 jcr->JobErrors++;
1588 }
1589 Jmsg(jcr, msg_type, 0, _("VSS Writer (BackupComplete): %s\n"),
1590 jcr->impl->pVSSClient->GetWriterInfo(i));
1591 }
1592 }
1593
1594 /*
1595 * Generate Job global writer metadata
1596 */
1597 wchar_t* metadata = jcr->impl->pVSSClient->GetMetadata();
1598 if (metadata) {
1599 FindFilesPacket* ff_pkt = jcr->impl->ff;
1600 ff_pkt->fname = (char*)"*all*"; /* for all plugins */
1601 ff_pkt->type = FT_RESTORE_FIRST;
1602 ff_pkt->LinkFI = 0;
1603 ff_pkt->object_name = (char*)"job_metadata.xml";
1604 ff_pkt->object = BSTR_2_str(metadata);
1605 ff_pkt->object_len = (wcslen(metadata) + 1) * sizeof(wchar_t);
1606 ff_pkt->object_index = (int)time(NULL);
1607 SaveFile(jcr, ff_pkt, true);
1608 }
1609 }
1610 #endif
1611 }
1612 } /* namespace filedaemon */
1613