+
+/*
+ * Read and send an ACL for the last encountered file.
+ */
+static bool read_and_send_acl(JCR *jcr, int acltype, int stream)
+{
+#ifdef HAVE_ACL
+ BSOCK *sd = jcr->store_bsock;
+ POOLMEM *msgsave;
+ int len;
+#ifdef FD_NO_SEND_TEST
+ return true;
+#endif
+
+ len = bacl_get(jcr, acltype);
+ if (len < 0) {
+ Jmsg1(jcr, M_WARNING, 0, _("Error reading ACL of %s\n"), jcr->last_fname);
+ return true;
+ }
+ if (len == 0) {
+ return true; /* no ACL */
+ }
+
+ /* Send header */
+ if (!bnet_fsend(sd, "%ld %d 0", jcr->JobFiles, stream)) {
+ Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
+ bnet_strerror(sd));
+ return false;
+ }
+
+ /* Send the buffer to the storage deamon */
+ Dmsg2(400, "Backing up ACL type 0x%2x <%s>\n", acltype, jcr->acl_text);
+ msgsave = sd->msg;
+ sd->msg = jcr->acl_text;
+ sd->msglen = len + 1;
+ if (!bnet_send(sd)) {
+ sd->msg = msgsave;
+ sd->msglen = 0;
+ Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
+ bnet_strerror(sd));
+ return false;
+ }
+
+ jcr->JobBytes += sd->msglen;
+ sd->msg = msgsave;
+ if (!bnet_sig(sd, BNET_EOD)) {
+ Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
+ bnet_strerror(sd));
+ return false;
+ }
+
+ Dmsg1(200, "ACL of file: %s successfully backed up!\n", jcr->last_fname);
+#endif
+ return true;
+}
+
+static 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];
+ int attr_stream;
+ int stat;
+#ifdef FD_NO_SEND_TEST
+ return true;
+#endif
+
+ /* Find what data stream we will use, then encode the attributes */
+ data_stream = select_data_stream(ff_pkt);
+ encode_stat(attribs, ff_pkt, data_stream);
+
+ /* Now possibly extend the attributes */
+ attr_stream = encode_attribsEx(jcr, attribsEx, ff_pkt);
+
+ Dmsg3(300, "File %s\nattribs=%s\nattribsEx=%s\n", ff_pkt->fname, attribs, attribsEx);
+
+ P(jcr->mutex);
+ jcr->JobFiles++; /* increment number of files sent */
+ ff_pkt->FileIndex = jcr->JobFiles; /* return FileIndex */
+ pm_strcpy(jcr->last_fname, ff_pkt->fname);
+ V(jcr->mutex);
+
+ /*
+ * Send Attributes header to Storage daemon
+ * <file-index> <stream> <info>
+ */
+ if (!bnet_fsend(sd, "%ld %d 0", jcr->JobFiles, attr_stream)) {
+ Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
+ bnet_strerror(sd));
+ return false;
+ }
+ Dmsg1(300, ">stored: attrhdr %s\n", sd->msg);
+
+ /*
+ * Send file attributes to Storage daemon
+ * File_index
+ * File type
+ * Filename (full path)
+ * Encoded attributes
+ * Link name (if type==FT_LNK or FT_LNKSAVED)
+ * Encoded extended-attributes (for Win32)
+ *
+ * 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_LNK || ff_pkt->type == FT_LNKSAVED) {
+ Dmsg2(300, "Link %s to %s\n", ff_pkt->fname, ff_pkt->link);
+ stat = bnet_fsend(sd, "%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) {
+ /* Here link is the canonical filename (i.e. with trailing slash) */
+ stat = bnet_fsend(sd, "%ld %d %s%c%s%c%c%s%c", jcr->JobFiles,
+ ff_pkt->type, ff_pkt->link, 0, attribs, 0, 0, attribsEx, 0);
+ } else {
+ stat = bnet_fsend(sd, "%ld %d %s%c%s%c%c%s%c", jcr->JobFiles,
+ ff_pkt->type, ff_pkt->fname, 0, attribs, 0, 0, attribsEx, 0);
+ }
+
+ Dmsg2(300, ">stored: attr len=%d: %s\n", sd->msglen, sd->msg);
+ if (!stat) {
+ Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
+ bnet_strerror(sd));
+ return false;
+ }
+ bnet_sig(sd, BNET_EOD); /* indicate end of attributes data */
+ return true;
+}