2 * Bacula File Daemon backup.c send file attributes and data
3 * to the Storage daemon.
5 * Kern Sibbald, March MM
11 Copyright (C) 2000-2005 Kern Sibbald
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License
15 version 2 as amended with additional clauses defined in the
16 file LICENSE in the main source directory.
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 the file LICENSE for additional details.
28 /* Forward referenced functions */
29 static int save_file(FF_PKT *ff_pkt, void *pkt, bool top_level);
30 static int send_data(JCR *jcr, int stream, FF_PKT *ff_pkt, DIGEST *digest, DIGEST *signature_digest);
31 static bool encode_and_send_attributes(JCR *jcr, FF_PKT *ff_pkt, int &data_stream);
32 static bool read_and_send_acl(JCR *jcr, int acltype, int stream);
35 * Find all the requested files and send them
36 * to the Storage daemon.
38 * Note, we normally carry on a one-way
39 * conversation from this point on with the SD, simply blasting
40 * data to him. To properly know what is going on, we
41 * also run a "heartbeat" monitor which reads the socket and
42 * reacts accordingly (at the moment it has nothing to do
43 * except echo the heartbeat to the Director).
46 bool blast_data_to_storage_daemon(JCR *jcr, char *addr)
50 // TODO landonf: Allow user to specify encryption algorithm
51 crypto_cipher_t cipher = CRYPTO_CIPHER_AES_128_CBC;
53 sd = jcr->store_bsock;
55 set_jcr_job_status(jcr, JS_Running);
57 Dmsg1(300, "bfiled: opened data connection %d to stored\n", sd->fd);
60 CLIENT *client = (CLIENT *)GetNextRes(R_CLIENT, NULL);
64 buf_size = client->max_network_buffer_size;
66 buf_size = 0; /* use default */
68 if (!bnet_set_buffer_size(sd, buf_size, BNET_SETBUF_WRITE)) {
69 set_jcr_job_status(jcr, JS_ErrorTerminated);
70 Jmsg(jcr, M_FATAL, 0, _("Cannot set buffer size FD->SD.\n"));
74 jcr->buf_size = sd->msglen;
75 /* Adjust for compression so that output buffer is
76 * 12 bytes + 0.1% larger than input buffer plus 18 bytes.
77 * This gives a bit extra plus room for the sparse addr if any.
78 * Note, we adjust the read size to be smaller so that the
79 * same output buffer can be used without growing it.
81 jcr->compress_buf_size = jcr->buf_size + ((jcr->buf_size+999) / 1000) + 30;
82 jcr->compress_buf = get_memory(jcr->compress_buf_size);
84 if (jcr->pki_encrypt) {
85 /* Create per-job session encryption context */
86 jcr->pki_recipients = crypto_recipients_new(cipher, jcr->pki_readers);
89 Dmsg1(300, "set_find_options ff=%p\n", jcr->ff);
90 set_find_options((FF_PKT *)jcr->ff, jcr->incremental, jcr->mtime);
91 Dmsg0(300, "start find files\n");
93 start_heartbeat_monitor(jcr);
95 jcr->acl_text = get_pool_memory(PM_MESSAGE);
97 /* Subroutine save_file() is called for each file */
98 if (!find_files(jcr, (FF_PKT *)jcr->ff, save_file, (void *)jcr)) {
99 ok = false; /* error */
100 set_jcr_job_status(jcr, JS_ErrorTerminated);
101 // Jmsg(jcr, M_FATAL, 0, _("Find files error.\n"));
104 free_pool_memory(jcr->acl_text);
106 stop_heartbeat_monitor(jcr);
108 bnet_sig(sd, BNET_EOD); /* end of sending data */
114 if (jcr->compress_buf) {
115 free_pool_memory(jcr->compress_buf);
116 jcr->compress_buf = NULL;
119 if (jcr->pki_recipients) {
120 crypto_recipients_free(jcr->pki_recipients);
123 Dmsg1(100, "end blast_data ok=%d\n", ok);
128 * Called here by find() for each file included.
129 * This is a callback. The original is find_files() above.
131 * Send the file and its data to the Storage daemon.
135 * -1 to ignore file/directory (not used here)
137 static int save_file(FF_PKT *ff_pkt, void *vjcr, bool top_level)
139 int stat, data_stream;
140 DIGEST *digest = NULL;
141 DIGEST *signing_digest = NULL;
142 int digest_stream = STREAM_NONE;
143 // TODO landonf: Allow the user to specify the digest algorithm
145 crypto_digest_t signing_algorithm = CRYPTO_DIGEST_SHA256;
147 crypto_digest_t signing_algorithm = CRYPTO_DIGEST_SHA1;
150 JCR *jcr = (JCR *)vjcr;
152 if (job_canceled(jcr)) {
156 sd = jcr->store_bsock;
157 jcr->num_files_examined++; /* bump total file count */
159 switch (ff_pkt->type) {
160 case FT_LNKSAVED: /* Hard linked, file already saved */
161 Dmsg2(130, "FT_LNKSAVED hard link: %s => %s\n", ff_pkt->fname, ff_pkt->link);
164 Dmsg1(130, "FT_REGE saving: %s\n", ff_pkt->fname);
167 Dmsg1(130, "FT_REG saving: %s\n", ff_pkt->fname);
170 Dmsg2(130, "FT_LNK saving: %s -> %s\n", ff_pkt->fname, ff_pkt->link);
173 return 1; /* not used */
175 Jmsg(jcr, M_INFO, 1, _(" Recursion turned off. Will not descend into %s\n"),
177 ff_pkt->type = FT_DIREND; /* Backup only the directory entry */
180 /* Suppress message for /dev filesystems */
181 if (strncmp(ff_pkt->fname, "/dev/", 5) != 0) {
182 Jmsg(jcr, M_INFO, 1, _(" Filesystem change prohibited. Will not descend into %s\n"),
185 ff_pkt->type = FT_DIREND; /* Backup only the directory entry */
188 Jmsg(jcr, M_INFO, 1, _(" Disallowed filesystem. Will not descend into %s\n"),
190 ff_pkt->type = FT_DIREND; /* Backup only the directory entry */
193 Dmsg1(130, "FT_DIREND: %s\n", ff_pkt->link);
196 Dmsg1(130, "FT_SPEC saving: %s\n", ff_pkt->fname);
199 Dmsg1(130, "FT_RAW saving: %s\n", ff_pkt->fname);
202 Dmsg1(130, "FT_FIFO saving: %s\n", ff_pkt->fname);
206 Jmsg(jcr, M_NOTSAVED, 0, _(" Could not access %s: ERR=%s\n"), ff_pkt->fname,
207 be.strerror(ff_pkt->ff_errno));
213 Jmsg(jcr, M_NOTSAVED, 0, _(" Could not follow link %s: ERR=%s\n"), ff_pkt->fname,
214 be.strerror(ff_pkt->ff_errno));
220 Jmsg(jcr, M_NOTSAVED, 0, _(" Could not stat %s: ERR=%s\n"), ff_pkt->fname,
221 be.strerror(ff_pkt->ff_errno));
227 Jmsg(jcr, M_SKIPPED, 1, _(" Unchanged file skipped: %s\n"), ff_pkt->fname);
230 Jmsg(jcr, M_NOTSAVED, 0, _(" Archive file not saved: %s\n"), ff_pkt->fname);
234 Jmsg(jcr, M_NOTSAVED, 0, _(" Could not open directory %s: ERR=%s\n"), ff_pkt->fname,
235 be.strerror(ff_pkt->ff_errno));
240 Jmsg(jcr, M_NOTSAVED, 0, _(" Unknown file type %d; not saved: %s\n"), ff_pkt->type, ff_pkt->fname);
245 Dmsg1(130, "bfiled: sending %s to stored\n", ff_pkt->fname);
248 * Setup for digest handling. If this fails, the digest will be set to NULL
251 if (ff_pkt->flags & FO_MD5) {
252 digest = crypto_digest_new(CRYPTO_DIGEST_MD5);
253 digest_stream = STREAM_MD5_DIGEST;
255 } else if (ff_pkt->flags & FO_SHA1) {
256 digest = crypto_digest_new(CRYPTO_DIGEST_SHA1);
257 digest_stream = STREAM_SHA1_DIGEST;
259 } else if (ff_pkt->flags & FO_SHA256) {
260 digest = crypto_digest_new(CRYPTO_DIGEST_SHA256);
261 digest_stream = STREAM_SHA256_DIGEST;
263 } else if (ff_pkt->flags & FO_SHA512) {
264 digest = crypto_digest_new(CRYPTO_DIGEST_SHA512);
265 digest_stream = STREAM_SHA512_DIGEST;
268 /* Did digest initialization fail? */
269 if (digest_stream != STREAM_NONE && digest == NULL) {
270 Jmsg(jcr, M_WARNING, 0, _("%s digest initialization failed\n"),
271 stream_to_ascii(digest_stream));
275 * Set up signature digest handling. If this fails, the signature digest will be set to
278 // TODO landonf: We should really only calculate the digest once, for both verification and signing.
280 signing_digest = crypto_digest_new(signing_algorithm);
283 /* Full-stop if a failure occured initializing the signature digest */
284 if (jcr->pki_sign && signing_digest == NULL) {
285 Jmsg(jcr, M_NOTSAVED, 0, _("%s signature digest initialization failed\n"),
286 stream_to_ascii(signing_algorithm));
291 /* Initialise the file descriptor we use for data and other streams. */
293 if (ff_pkt->flags & FO_PORTABLE) {
294 set_portable_backup(&ff_pkt->bfd); /* disable Win32 BackupRead() */
296 if (ff_pkt->reader) {
297 if (!set_prog(&ff_pkt->bfd, ff_pkt->reader, jcr)) {
298 Jmsg(jcr, M_FATAL, 0, _("Python reader program \"%s\" not found.\n"),
304 /* Send attributes -- must be done after binit() */
305 if (!encode_and_send_attributes(jcr, ff_pkt, data_stream)) {
310 * Open any file with data that we intend to save, then save it.
312 * Note, if is_win32_backup, we must open the Directory so that
313 * the BackupRead will save its permissions and ownership streams.
315 if (ff_pkt->type != FT_LNKSAVED && (S_ISREG(ff_pkt->statp.st_mode) &&
316 ff_pkt->statp.st_size > 0) ||
317 ff_pkt->type == FT_RAW || ff_pkt->type == FT_FIFO ||
318 (!is_portable_backup(&ff_pkt->bfd) && ff_pkt->type == FT_DIREND)) {
320 if (ff_pkt->type == FT_FIFO) {
321 tid = start_thread_timer(pthread_self(), 60);
325 if (bopen(&ff_pkt->bfd, ff_pkt->fname, O_RDONLY | O_BINARY, 0) < 0) {
326 ff_pkt->ff_errno = errno;
328 Jmsg(jcr, M_NOTSAVED, 0, _(" Cannot open %s: ERR=%s.\n"), ff_pkt->fname,
332 stop_thread_timer(tid);
338 stop_thread_timer(tid);
341 stat = send_data(jcr, data_stream, ff_pkt, digest, signing_digest);
342 bclose(&ff_pkt->bfd);
348 #ifdef HAVE_DARWIN_OS
349 /* Regular files can have resource forks and Finder Info */
350 if (ff_pkt->type != FT_LNKSAVED && (S_ISREG(ff_pkt->statp.st_mode) &&
351 ff_pkt->flags & FO_HFSPLUS)) {
352 if (ff_pkt->hfsinfo.rsrclength > 0) {
354 if (!bopen_rsrc(&ff_pkt->bfd, ff_pkt->fname, O_RDONLY | O_BINARY, 0) < 0) {
355 ff_pkt->ff_errno = errno;
357 Jmsg(jcr, M_NOTSAVED, -1, _(" Cannot open resource fork for %s: ERR=%s.\n"), ff_pkt->fname,
360 if (is_bopen(&ff_pkt->bfd)) {
361 bclose(&ff_pkt->bfd);
365 flags = ff_pkt->flags;
366 ff_pkt->flags &= ~(FO_GZIP|FO_SPARSE);
367 stat = send_data(jcr, STREAM_MACOS_FORK_DATA, ff_pkt, digest);
368 ff_pkt->flags = flags;
369 bclose(&ff_pkt->bfd);
375 Dmsg1(300, "Saving Finder Info for \"%s\"\n", ff_pkt->fname);
376 bnet_fsend(sd, "%ld %d 0", jcr->JobFiles, STREAM_HFSPLUS_ATTRIBUTES);
377 Dmsg1(300, "bfiled>stored:header %s\n", sd->msg);
378 memcpy(sd->msg, ff_pkt->hfsinfo.fndrinfo, 32);
381 crypto_digest_update(digest, sd->msg, sd->msglen);
383 if (signature_digest) {
384 crypto_digest_update(signature_digest, sd->msg, sd->msglen);
387 bnet_sig(sd, BNET_EOD);
391 if (ff_pkt->flags & FO_ACL) {
392 /* Read access ACLs for files, dirs and links */
393 if (!read_and_send_acl(jcr, BACL_TYPE_ACCESS, STREAM_UNIX_ATTRIBUTES_ACCESS_ACL)) {
396 /* Directories can have default ACLs too */
397 if (ff_pkt->type == FT_DIREND && (BACL_CAP & BACL_CAP_DEFAULTS_DIR)) {
398 if (!read_and_send_acl(jcr, BACL_TYPE_DEFAULT, STREAM_UNIX_ATTRIBUTES_DEFAULT_ACL)) {
404 /* Terminate the signing digest and send it to the Storage daemon */
405 if (signing_digest) {
410 if ((sig = crypto_sign_new()) == NULL) {
411 Jmsg(jcr, M_FATAL, 0, _("Failed to allocate memory for stream signature.\n"));
415 if (crypto_sign_add_signer(sig, signing_digest, jcr->pki_keypair) == false) {
416 Jmsg(jcr, M_FATAL, 0, _("An error occured while signing the stream.\n"));
420 /* Get signature size */
421 if (crypto_sign_encode(sig, NULL, &size) == false) {
422 Jmsg(jcr, M_FATAL, 0, _("An error occured while signing the stream.\n"));
426 /* Allocate signature data buffer */
433 /* Encode signature data */
434 if (crypto_sign_encode(sig, buf, &size) == false) {
435 Jmsg(jcr, M_FATAL, 0, _("An error occured while signing the stream.\n"));
439 /* Send our header */
440 bnet_fsend(sd, "%ld %d 0", jcr->JobFiles, STREAM_SIGNED_DIGEST);
441 Dmsg1(300, "bfiled>stored:header %s\n", sd->msg);
443 /* Grow the bsock buffer to fit our message if necessary */
444 if ((size_t) sizeof_pool_memory(sd->msg) < size) {
445 sd->msg = realloc_pool_memory(sd->msg, size);
448 /* Copy our message over and send it */
449 memcpy(sd->msg, buf, size);
452 bnet_sig(sd, BNET_EOD); /* end of checksum */
454 crypto_digest_free(signing_digest);
455 crypto_sign_free(sig);
459 /* Terminate any digest and send it to Storage daemon and the Director */
461 char md[CRYPTO_DIGEST_MAX_SIZE];
466 if (crypto_digest_finalize(digest, &md, &size)) {
467 bnet_fsend(sd, "%ld %d 0", jcr->JobFiles, digest_stream);
468 Dmsg1(300, "bfiled>stored:header %s\n", sd->msg);
469 memcpy(sd->msg, md, size);
472 bnet_sig(sd, BNET_EOD); /* end of checksum */
475 crypto_digest_free(digest);
482 * Send data read from an already open file descriptor.
484 * We return 1 on sucess and 0 on errors.
487 * We use ff_pkt->statp.st_size when FO_SPARSE.
488 * Currently this is not a problem as the only other stream, resource forks,
489 * are not handled as sparse files.
491 int send_data(JCR *jcr, int stream, FF_PKT *ff_pkt, DIGEST *digest, DIGEST *signing_digest)
493 BSOCK *sd = jcr->store_bsock;
494 uint64_t fileAddr = 0; /* file address */
496 int rsize = jcr->buf_size; /* read buffer size */
498 #ifdef FD_NO_SEND_TEST
503 rbuf = sd->msg; /* read buffer */
504 wbuf = sd->msg; /* write buffer */
507 Dmsg1(300, "Saving data, type=%d\n", ff_pkt->type);
511 uLong compress_len, max_compress_len = 0;
512 const Bytef *cbuf = NULL;
514 if (ff_pkt->flags & FO_GZIP) {
515 if (ff_pkt->flags & FO_SPARSE) {
516 cbuf = (Bytef *)jcr->compress_buf + SPARSE_FADDR_SIZE;
517 max_compress_len = jcr->compress_buf_size - SPARSE_FADDR_SIZE;
519 cbuf = (Bytef *)jcr->compress_buf;
520 max_compress_len = jcr->compress_buf_size; /* set max length */
522 wbuf = jcr->compress_buf; /* compressed output here */
527 * Send Data header to Storage daemon
528 * <file-index> <stream> <info>
530 if (!bnet_fsend(sd, "%ld %d 0", jcr->JobFiles, stream)) {
531 Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
535 Dmsg1(300, ">stored: datahdr %s\n", sd->msg);
538 * Make space at beginning of buffer for fileAddr because this
539 * same buffer will be used for writing if compression if off.
541 if (ff_pkt->flags & FO_SPARSE) {
542 rbuf += SPARSE_FADDR_SIZE;
543 rsize -= SPARSE_FADDR_SIZE;
544 #ifdef HAVE_FREEBSD_OS
546 * To read FreeBSD partitions, the read size must be
549 rsize = (rsize/512) * 512;
553 /* a RAW device read on win32 only works if the buffer is a multiple of 512 */
555 if (S_ISBLK(ff_pkt->statp.st_mode))
556 rsize = (rsize/512) * 512;
562 while ((sd->msglen=(uint32_t)bread(&ff_pkt->bfd, rbuf, rsize)) > 0) {
565 /* Check for sparse blocks */
566 if (ff_pkt->flags & FO_SPARSE) {
568 if (sd->msglen == rsize &&
569 fileAddr+sd->msglen < (uint64_t)ff_pkt->statp.st_size ||
570 ((ff_pkt->type == FT_RAW || ff_pkt->type == FT_FIFO) &&
571 (uint64_t)ff_pkt->statp.st_size == 0)) {
572 sparseBlock = is_buf_zero(rbuf, rsize);
575 ser_begin(wbuf, SPARSE_FADDR_SIZE);
576 ser_uint64(fileAddr); /* store fileAddr in begin of buffer */
579 jcr->ReadBytes += sd->msglen; /* count bytes read */
580 fileAddr += sd->msglen;
582 /* Update checksum if requested */
584 crypto_digest_update(digest, rbuf, sd->msglen);
587 /* Update signing digest if requested */
588 if (signing_digest) {
589 crypto_digest_update(signing_digest, rbuf, sd->msglen);
593 /* Do compression if turned on */
594 if (!sparseBlock && ff_pkt->flags & FO_GZIP) {
596 compress_len = max_compress_len;
597 Dmsg4(400, "cbuf=0x%x len=%u rbuf=0x%x len=%u\n", cbuf, compress_len,
599 /* NOTE! This call modifies compress_len !!! */
600 if ((zstat=compress2((Bytef *)cbuf, &compress_len,
601 (const Bytef *)rbuf, (uLong)sd->msglen,
602 ff_pkt->GZIP_level)) != Z_OK) {
603 Jmsg(jcr, M_FATAL, 0, _("Compression error: %d\n"), zstat);
606 set_jcr_job_status(jcr, JS_ErrorTerminated);
609 Dmsg2(400, "compressed len=%d uncompressed len=%d\n",
610 compress_len, sd->msglen);
612 sd->msglen = compress_len; /* set compressed length */
616 /* Send the buffer to the Storage daemon */
618 if (ff_pkt->flags & FO_SPARSE) {
619 sd->msglen += SPARSE_FADDR_SIZE; /* include fileAddr in size */
621 sd->msg = wbuf; /* set correct write buffer */
622 if (!bnet_send(sd)) {
623 Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
625 sd->msg = msgsave; /* restore bnet buffer */
630 Dmsg1(130, "Send data to SD len=%d\n", sd->msglen);
632 jcr->JobBytes += sd->msglen; /* count bytes saved possibly compressed */
633 sd->msg = msgsave; /* restore read buffer */
635 } /* end while read file data */
638 if (sd->msglen < 0) {
640 Jmsg(jcr, M_ERROR, 0, _("Read error on file %s. ERR=%s\n"),
641 ff_pkt->fname, be.strerror(ff_pkt->bfd.berrno));
642 if (jcr->Errors++ > 1000) { /* insanity check */
643 Jmsg(jcr, M_FATAL, 0, _("Too many errors.\n"));
648 if (!bnet_sig(sd, BNET_EOD)) { /* indicate end of file data */
649 Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
658 * Read and send an ACL for the last encountered file.
660 static bool read_and_send_acl(JCR *jcr, int acltype, int stream)
663 BSOCK *sd = jcr->store_bsock;
666 #ifdef FD_NO_SEND_TEST
670 len = bacl_get(jcr, acltype);
672 Jmsg1(jcr, M_WARNING, 0, _("Error reading ACL of %s\n"), jcr->last_fname);
676 return true; /* no ACL */
680 if (!bnet_fsend(sd, "%ld %d 0", jcr->JobFiles, stream)) {
681 Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
686 /* Send the buffer to the storage deamon */
687 Dmsg2(400, "Backing up ACL type 0x%2x <%s>\n", acltype, jcr->acl_text);
689 sd->msg = jcr->acl_text;
690 sd->msglen = len + 1;
691 if (!bnet_send(sd)) {
694 Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
699 jcr->JobBytes += sd->msglen;
701 if (!bnet_sig(sd, BNET_EOD)) {
702 Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
707 Dmsg1(200, "ACL of file: %s successfully backed up!\n", jcr->last_fname);
712 static bool encode_and_send_attributes(JCR *jcr, FF_PKT *ff_pkt, int &data_stream)
714 BSOCK *sd = jcr->store_bsock;
715 char attribs[MAXSTRING];
716 char attribsEx[MAXSTRING];
719 #ifdef FD_NO_SEND_TEST
723 /* Find what data stream we will use, then encode the attributes */
724 data_stream = select_data_stream(ff_pkt);
725 encode_stat(attribs, ff_pkt, data_stream);
727 /* Now possibly extend the attributes */
728 attr_stream = encode_attribsEx(jcr, attribsEx, ff_pkt);
730 Dmsg3(300, "File %s\nattribs=%s\nattribsEx=%s\n", ff_pkt->fname, attribs, attribsEx);
733 jcr->JobFiles++; /* increment number of files sent */
734 ff_pkt->FileIndex = jcr->JobFiles; /* return FileIndex */
735 pm_strcpy(jcr->last_fname, ff_pkt->fname);
739 * Send Attributes header to Storage daemon
740 * <file-index> <stream> <info>
742 if (!bnet_fsend(sd, "%ld %d 0", jcr->JobFiles, attr_stream)) {
743 Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
747 Dmsg1(300, ">stored: attrhdr %s\n", sd->msg);
750 * Send file attributes to Storage daemon
753 * Filename (full path)
755 * Link name (if type==FT_LNK or FT_LNKSAVED)
756 * Encoded extended-attributes (for Win32)
758 * For a directory, link is the same as fname, but with trailing
759 * slash. For a linked file, link is the link.
761 if (ff_pkt->type == FT_LNK || ff_pkt->type == FT_LNKSAVED) {
762 Dmsg2(300, "Link %s to %s\n", ff_pkt->fname, ff_pkt->link);
763 stat = bnet_fsend(sd, "%ld %d %s%c%s%c%s%c%s%c", jcr->JobFiles,
764 ff_pkt->type, ff_pkt->fname, 0, attribs, 0, ff_pkt->link, 0,
766 } else if (ff_pkt->type == FT_DIREND) {
767 /* Here link is the canonical filename (i.e. with trailing slash) */
768 stat = bnet_fsend(sd, "%ld %d %s%c%s%c%c%s%c", jcr->JobFiles,
769 ff_pkt->type, ff_pkt->link, 0, attribs, 0, 0, attribsEx, 0);
771 stat = bnet_fsend(sd, "%ld %d %s%c%s%c%c%s%c", jcr->JobFiles,
772 ff_pkt->type, ff_pkt->fname, 0, attribs, 0, 0, attribsEx, 0);
775 Dmsg2(300, ">stored: attr len=%d: %s\n", sd->msglen, sd->msg);
777 Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
781 bnet_sig(sd, BNET_EOD); /* indicate end of attributes data */