]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/backup.c
This commit was manufactured by cvs2svn to create tag
[bacula/bacula] / bacula / src / filed / backup.c
1 /*
2  *  Bacula File Daemon  backup.c  send file attributes and data
3  *   to the Storage daemon.
4  *
5  *    Kern Sibbald, March MM
6  *
7  *   Version $Id$
8  *
9  */
10 /*
11    Copyright (C) 2000-2004 Kern Sibbald and John Walker
12
13    This program is free software; you can redistribute it and/or
14    modify it under the terms of the GNU General Public License as
15    published by the Free Software Foundation; either version 2 of
16    the License, or (at your option) any later version.
17
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 GNU
21    General Public License for more details.
22
23    You should have received a copy of the GNU General Public
24    License along with this program; if not, write to the Free
25    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
26    MA 02111-1307, USA.
27
28  */
29
30 #include "bacula.h"
31 #include "filed.h"
32
33 #ifdef HAVE_ACL
34 #include <sys/acl.h>
35 #include <acl/libacl.h>
36 #endif
37
38 static int save_file(FF_PKT *ff_pkt, void *pkt);
39
40 /*** FIXME ***/
41 #ifdef HAVE_ACL
42 static int read_send_acl(JCR *jcr, BSOCK *sd, int acltype, int stream);
43 #endif
44
45 /* 
46  * Find all the requested files and send them
47  * to the Storage daemon. 
48  *
49  * Note, we normally carry on a one-way
50  * conversation from this point on with the SD, simply blasting
51  * data to him.  To properly know what is going on, we
52  * also run a "heartbeat" monitor which reads the socket and
53  * reacts accordingly (at the moment it has nothing to do
54  * except echo the heartbeat to the Director).
55  * 
56  */
57 bool blast_data_to_storage_daemon(JCR *jcr, char *addr) 
58 {
59    BSOCK *sd;
60    bool ok = true;
61
62    sd = jcr->store_bsock;
63
64    set_jcr_job_status(jcr, JS_Running);
65
66    Dmsg1(300, "bfiled: opened data connection %d to stored\n", sd->fd);
67
68    LockRes();
69    CLIENT *client = (CLIENT *)GetNextRes(R_CLIENT, NULL);
70    UnlockRes();
71    uint32_t buf_size;
72    if (client) {
73       buf_size = client->max_network_buffer_size;
74    } else {
75       buf_size = 0;                   /* use default */
76    }
77    if (!bnet_set_buffer_size(sd, buf_size, BNET_SETBUF_WRITE)) {
78       set_jcr_job_status(jcr, JS_ErrorTerminated);
79       Jmsg(jcr, M_FATAL, 0, _("Cannot set buffer size FD->SD.\n"));
80       return false;
81    }
82
83    jcr->buf_size = sd->msglen;             
84    /* Adjust for compression so that output buffer is
85     * 12 bytes + 0.1% larger than input buffer plus 18 bytes.
86     * This gives a bit extra plus room for the sparse addr if any.
87     * Note, we adjust the read size to be smaller so that the
88     * same output buffer can be used without growing it.
89     */
90    jcr->compress_buf_size = jcr->buf_size + ((jcr->buf_size+999) / 1000) + 30;
91    jcr->compress_buf = get_memory(jcr->compress_buf_size);
92
93    Dmsg1(300, "set_find_options ff=%p\n", jcr->ff);
94    set_find_options((FF_PKT *)jcr->ff, jcr->incremental, jcr->mtime);
95    Dmsg0(300, "start find files\n");
96
97    start_heartbeat_monitor(jcr);
98
99    /* Subroutine save_file() is called for each file */
100    if (!find_files(jcr, (FF_PKT *)jcr->ff, save_file, (void *)jcr)) {
101       ok = false;                     /* error */
102       set_jcr_job_status(jcr, JS_ErrorTerminated);
103 //    Jmsg(jcr, M_FATAL, 0, _("Find files error.\n"));
104    }
105
106    stop_heartbeat_monitor(jcr);
107
108    bnet_sig(sd, BNET_EOD);            /* end data connection */
109
110    if (jcr->big_buf) {
111       free(jcr->big_buf);
112       jcr->big_buf = NULL;
113    }
114    if (jcr->compress_buf) {
115       free_pool_memory(jcr->compress_buf);
116       jcr->compress_buf = NULL;
117    }
118    Dmsg1(300, "end blast_data stat=%d\n", ok);
119    return ok;
120 }          
121
122 /* 
123  * Called here by find() for each file included.
124  *
125  *  *****FIXME*****   add FSMs File System Modules
126  *
127  *  Send the file and its data to the Storage daemon.
128  *
129  *  Returns: 1 if OK
130  *           0 if error
131  *          -1 to ignore file/directory (not used here)
132  */
133 static int save_file(FF_PKT *ff_pkt, void *vjcr)
134 {
135    char attribs[MAXSTRING];
136    char attribsEx[MAXSTRING];
137    int stat, attr_stream, data_stream;
138    struct MD5Context md5c;
139    struct SHA1Context sha1c;
140    int gotMD5 = 0;
141    int gotSHA1 = 0;
142    unsigned char signature[30];       /* large enough for either signature */
143    BSOCK *sd;
144    JCR *jcr = (JCR *)vjcr;
145    POOLMEM *msgsave;
146
147    if (job_canceled(jcr)) {
148       return 0;
149    }
150
151    sd = jcr->store_bsock;
152    jcr->num_files_examined++;         /* bump total file count */
153
154    switch (ff_pkt->type) {
155    case FT_LNKSAVED:                  /* Hard linked, file already saved */
156       Dmsg2(130, "FT_LNKSAVED hard link: %s => %s\n", ff_pkt->fname, ff_pkt->link);
157       break;
158    case FT_REGE:
159       Dmsg1(130, "FT_REGE saving: %s\n", ff_pkt->fname);
160       break;
161    case FT_REG:
162       Dmsg1(130, "FT_REG saving: %s\n", ff_pkt->fname);
163       break;
164    case FT_LNK:
165       Dmsg2(130, "FT_LNK saving: %s -> %s\n", ff_pkt->fname, ff_pkt->link);
166       break;
167    case FT_DIRBEGIN:
168       return 1;                       /* not used */
169    case FT_DIREND:
170       Dmsg1(130, "FT_DIR saving: %s\n", ff_pkt->link);
171       break;
172    case FT_SPEC:
173       Dmsg1(130, "FT_SPEC saving: %s\n", ff_pkt->fname);
174       break;
175    case FT_RAW:
176       Dmsg1(130, "FT_RAW saving: %s\n", ff_pkt->fname);
177       break;
178    case FT_FIFO:
179       Dmsg1(130, "FT_FIFO saving: %s\n", ff_pkt->fname);
180       break;
181    case FT_NOACCESS: {
182       berrno be;
183       be.set_errno(ff_pkt->ff_errno);
184       Jmsg(jcr, M_NOTSAVED, 0, _("     Could not access %s: ERR=%s\n"), ff_pkt->fname, 
185          be.strerror());
186       jcr->Errors++;
187       return 1;
188    }
189    case FT_NOFOLLOW: {
190       berrno be;
191       be.set_errno(ff_pkt->ff_errno);
192       Jmsg(jcr, M_NOTSAVED, 0, _("     Could not follow link %s: ERR=%s\n"), ff_pkt->fname, 
193          be.strerror());
194       jcr->Errors++;
195       return 1;
196    }
197    case FT_NOSTAT: {
198       berrno be;
199       be.set_errno(ff_pkt->ff_errno);
200       Jmsg(jcr, M_NOTSAVED, 0, _("     Could not stat %s: ERR=%s\n"), ff_pkt->fname, 
201          be.strerror());
202       jcr->Errors++;
203       return 1;
204    }
205    case FT_DIRNOCHG:
206    case FT_NOCHG:
207       Jmsg(jcr, M_SKIPPED, 1, _("     Unchanged file skipped: %s\n"), ff_pkt->fname);
208       return 1;
209    case FT_ISARCH:
210       Jmsg(jcr, M_NOTSAVED, 0, _("     Archive file not saved: %s\n"), ff_pkt->fname);
211       return 1;
212    case FT_NORECURSE:
213       Jmsg(jcr, M_SKIPPED, 1, _("     Recursion turned off. Directory skipped: %s\n"), 
214          ff_pkt->fname);
215       return 1;
216    case FT_NOFSCHG:
217       Jmsg(jcr, M_SKIPPED, 1, _("     File system change prohibited. Directory skipped. %s\n"), 
218          ff_pkt->fname);
219       return 1;
220    case FT_NOOPEN: {
221       berrno be;
222       be.set_errno(ff_pkt->ff_errno);
223       Jmsg(jcr, M_NOTSAVED, 0, _("     Could not open directory %s: ERR=%s\n"), ff_pkt->fname, 
224          be.strerror());
225       jcr->Errors++;
226       return 1;
227    }
228    default:
229       Jmsg(jcr, M_NOTSAVED, 0,  _("     Unknown file type %d; not saved: %s\n"), ff_pkt->type, ff_pkt->fname);
230       jcr->Errors++;
231       return 1;
232    }
233
234    binit(&ff_pkt->bfd);
235    if (ff_pkt->flags & FO_PORTABLE) {
236       set_portable_backup(&ff_pkt->bfd); /* disable Win32 BackupRead() */
237    }
238    if (ff_pkt->reader) {
239       set_prog(&ff_pkt->bfd, ff_pkt->reader, jcr);
240    }
241
242    /* 
243     * Open any file with data that we intend to save.  
244     * Note, if is_win32_backup, we must open the Directory so that
245     * the BackupRead will save its permissions and ownership streams.
246     */
247    if (ff_pkt->type != FT_LNKSAVED && (S_ISREG(ff_pkt->statp.st_mode) && 
248          ff_pkt->statp.st_size > 0) || 
249          ff_pkt->type == FT_RAW || ff_pkt->type == FT_FIFO ||
250          (!is_portable_backup(&ff_pkt->bfd) && ff_pkt->type == FT_DIREND)) {
251       btimer_t *tid;    
252       if (ff_pkt->type == FT_FIFO) {
253          tid = start_thread_timer(pthread_self(), 60);
254       } else {
255          tid = NULL;
256       }
257       if (bopen(&ff_pkt->bfd, ff_pkt->fname, O_RDONLY | O_BINARY, 0) < 0) {
258          ff_pkt->ff_errno = errno;
259          berrno be;
260          Jmsg(jcr, M_NOTSAVED, 0, _("     Cannot open %s: ERR=%s.\n"), ff_pkt->fname, 
261               be.strerror());
262          jcr->Errors++;
263          if (tid) {
264             stop_thread_timer(tid);
265             tid = NULL;
266          }
267          return 1;
268       }
269       if (tid) {
270          stop_thread_timer(tid);
271          tid = NULL;
272       }
273    }
274
275    Dmsg1(130, "bfiled: sending %s to stored\n", ff_pkt->fname);
276
277    /* Find what data stream we will use, then encode the attributes */
278    data_stream = select_data_stream(ff_pkt);
279    encode_stat(attribs, ff_pkt, data_stream);
280
281    /* Now possibly extend the attributes */
282    attr_stream = encode_attribsEx(jcr, attribsEx, ff_pkt);
283
284    Dmsg3(300, "File %s\nattribs=%s\nattribsEx=%s\n", ff_pkt->fname, attribs, attribsEx);
285      
286    P(jcr->mutex);
287    jcr->JobFiles++;                    /* increment number of files sent */
288    ff_pkt->FileIndex = jcr->JobFiles;  /* return FileIndex */
289    pm_strcpy(jcr->last_fname, ff_pkt->fname);
290    V(jcr->mutex);
291     
292    /*
293     * Send Attributes header to Storage daemon
294     *    <file-index> <stream> <info>
295     */
296    if (!bnet_fsend(sd, "%ld %d 0", jcr->JobFiles, attr_stream)) {
297       berrno be;
298       if (is_bopen(&ff_pkt->bfd)) {
299          bclose(&ff_pkt->bfd);
300       }
301       Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
302             bnet_strerror(sd));
303       return 0;
304    }
305    Dmsg1(300, ">stored: attrhdr %s\n", sd->msg);
306
307    /*
308     * Send file attributes to Storage daemon
309     *   File_index
310     *   File type
311     *   Filename (full path)
312     *   Encoded attributes
313     *   Link name (if type==FT_LNK or FT_LNKSAVED)
314     *   Encoded extended-attributes (for Win32)
315     *
316     * For a directory, link is the same as fname, but with trailing
317     * slash. For a linked file, link is the link.
318     */
319    if (ff_pkt->type == FT_LNK || ff_pkt->type == FT_LNKSAVED) {
320       Dmsg2(300, "Link %s to %s\n", ff_pkt->fname, ff_pkt->link);
321       stat = bnet_fsend(sd, "%ld %d %s%c%s%c%s%c%s%c", jcr->JobFiles, 
322                ff_pkt->type, ff_pkt->fname, 0, attribs, 0, ff_pkt->link, 0,
323                attribsEx, 0);
324    } else if (ff_pkt->type == FT_DIREND) {
325       /* Here link is the canonical filename (i.e. with trailing slash) */
326       stat = bnet_fsend(sd, "%ld %d %s%c%s%c%c%s%c", jcr->JobFiles, 
327                ff_pkt->type, ff_pkt->link, 0, attribs, 0, 0, attribsEx, 0);
328    } else {
329       stat = bnet_fsend(sd, "%ld %d %s%c%s%c%c%s%c", jcr->JobFiles, 
330                ff_pkt->type, ff_pkt->fname, 0, attribs, 0, 0, attribsEx, 0);
331    }
332
333    Dmsg2(300, ">stored: attr len=%d: %s\n", sd->msglen, sd->msg);
334    if (!stat) {
335       berrno be;
336       if (is_bopen(&ff_pkt->bfd)) {
337          bclose(&ff_pkt->bfd);
338       }
339       Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
340             bnet_strerror(sd));
341       return 0;
342    }
343    bnet_sig(sd, BNET_EOD);            /* indicate end of attributes data */
344
345    /* 
346     * If the file has data, read it and send to the Storage daemon
347     *
348     */
349    if (is_bopen(&ff_pkt->bfd)) {
350       uint64_t fileAddr = 0;          /* file address */
351       char *rbuf, *wbuf;
352       int rsize = jcr->buf_size;      /* read buffer size */
353
354       msgsave = sd->msg;
355       rbuf = sd->msg;                 /* read buffer */             
356       wbuf = sd->msg;                 /* write buffer */
357
358
359       Dmsg1(300, "Saving data, type=%d\n", ff_pkt->type);
360
361
362 #ifdef HAVE_LIBZ
363       uLong compress_len, max_compress_len = 0;
364       const Bytef *cbuf = NULL;
365
366       if (ff_pkt->flags & FO_GZIP) {
367          if (ff_pkt->flags & FO_SPARSE) {
368             cbuf = (Bytef *)jcr->compress_buf + SPARSE_FADDR_SIZE;
369             max_compress_len = jcr->compress_buf_size - SPARSE_FADDR_SIZE;
370          } else {
371             cbuf = (Bytef *)jcr->compress_buf;
372             max_compress_len = jcr->compress_buf_size; /* set max length */
373          }
374          wbuf = jcr->compress_buf;    /* compressed output here */
375       }
376 #endif
377
378       /*
379        * Send Data header to Storage daemon
380        *    <file-index> <stream> <info>
381        */
382       if (!bnet_fsend(sd, "%ld %d 0", jcr->JobFiles, data_stream)) {
383          berrno be;
384          bclose(&ff_pkt->bfd);
385          Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
386                bnet_strerror(sd));
387          return 0;
388       }
389       Dmsg1(300, ">stored: datahdr %s\n", sd->msg);
390
391       if (ff_pkt->flags & FO_MD5) {
392          MD5Init(&md5c);
393       } else if (ff_pkt->flags & FO_SHA1) {
394          SHA1Init(&sha1c);
395       }
396
397       /*
398        * Make space at beginning of buffer for fileAddr because this
399        *   same buffer will be used for writing if compression if off. 
400        */
401       if (ff_pkt->flags & FO_SPARSE) {
402          rbuf += SPARSE_FADDR_SIZE;
403          rsize -= SPARSE_FADDR_SIZE;
404 #ifdef HAVE_FREEBSD_OS
405          /* 
406           * To read FreeBSD partitions, the read size must be
407           *  a multiple of 512.
408           */
409          rsize = (rsize/512) * 512;
410 #endif
411       }
412
413       /* 
414        * Read the file data
415        */
416       while ((sd->msglen=(uint32_t)bread(&ff_pkt->bfd, rbuf, rsize)) > 0) {
417          int sparseBlock = 0;
418
419          /* Check for sparse blocks */
420          if (ff_pkt->flags & FO_SPARSE) {
421             ser_declare;
422             if (sd->msglen == rsize && 
423                 (fileAddr+sd->msglen < (uint64_t)ff_pkt->statp.st_size)) {
424                sparseBlock = is_buf_zero(rbuf, rsize);
425             }
426                
427             ser_begin(wbuf, SPARSE_FADDR_SIZE);
428             ser_uint64(fileAddr);     /* store fileAddr in begin of buffer */
429          } 
430
431          jcr->ReadBytes += sd->msglen;      /* count bytes read */
432          fileAddr += sd->msglen;
433
434          /* Update MD5 if requested */
435          if (ff_pkt->flags & FO_MD5) {
436             MD5Update(&md5c, (unsigned char *)rbuf, sd->msglen);
437             gotMD5 = 1;
438          } else if (ff_pkt->flags & FO_SHA1) {
439             SHA1Update(&sha1c, (unsigned char *)rbuf, sd->msglen);
440             gotSHA1 = 1;
441          }
442
443 #ifdef HAVE_LIBZ
444          /* Do compression if turned on */
445          if (!sparseBlock && ff_pkt->flags & FO_GZIP) {
446             int zstat;
447             compress_len = max_compress_len;
448             Dmsg4(400, "cbuf=0x%x len=%u rbuf=0x%x len=%u\n", cbuf, compress_len,
449                rbuf, sd->msglen);
450             /* NOTE! This call modifies compress_len !!! */
451             if ((zstat=compress2((Bytef *)cbuf, &compress_len, 
452                   (const Bytef *)rbuf, (uLong)sd->msglen,
453                   ff_pkt->GZIP_level)) != Z_OK) {
454                Jmsg(jcr, M_FATAL, 0, _("Compression error: %d\n"), zstat);
455                sd->msg = msgsave;
456                sd->msglen = 0;
457                bclose(&ff_pkt->bfd);
458                set_jcr_job_status(jcr, JS_ErrorTerminated);
459                return 0;
460             }
461             Dmsg2(400, "compressed len=%d uncompressed len=%d\n", 
462                compress_len, sd->msglen);
463
464             sd->msglen = compress_len;   /* set compressed length */
465          }
466 #endif
467
468          /* Send the buffer to the Storage daemon */
469          if (!sparseBlock) {
470             if (ff_pkt->flags & FO_SPARSE) {
471                sd->msglen += SPARSE_FADDR_SIZE; /* include fileAddr in size */
472             }
473             sd->msg = wbuf;           /* set correct write buffer */
474             if (!bnet_send(sd)) {
475                berrno be;
476                Jmsg2(jcr, M_FATAL, 0, _("Network send error %d to SD. ERR=%s\n"),
477                      sd->msglen, bnet_strerror(sd));
478                sd->msg = msgsave;     /* restore bnet buffer */
479                sd->msglen = 0;
480                bclose(&ff_pkt->bfd);
481                return 0;
482             }
483          }
484          Dmsg1(130, "Send data to SD len=%d\n", sd->msglen);
485          /*       #endif */
486          jcr->JobBytes += sd->msglen;   /* count bytes saved possibly compressed */
487          sd->msg = msgsave;             /* restore read buffer */
488
489       } /* end while read file data */
490
491
492       if (sd->msglen < 0) {
493          berrno be;
494          be.set_errno(ff_pkt->bfd.berrno);
495          Jmsg(jcr, M_ERROR, 0, _("Read error on file %s. ERR=%s\n"),
496             ff_pkt->fname, be.strerror());
497       }
498
499       bclose(&ff_pkt->bfd);              /* close file */
500       if (!bnet_sig(sd, BNET_EOD)) {     /* indicate end of file data */
501          berrno be;
502          Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
503                bnet_strerror(sd));
504          return 0;
505       }
506    }
507    
508 #ifdef HAVE_ACL
509    /*** FIXME ***/
510    if (ff_pkt->flags & FO_ACL) {   
511       /* Storing of ACLs for Links is not needed, because: ACL of link == ACL of original */
512       if(ff_pkt->type != FT_LNK) {
513          /* Read access ACLs for files, dirs and links */
514          if (!read_send_acl(jcr, sd, ACL_TYPE_ACCESS, STREAM_UNIX_ATTRIBUTES_ACCESS_ACL)) {
515             return 0;
516          }
517          /* Directories can have also default ACLs*/
518          if (ff_pkt->type == FT_DIREND) {
519             if (!read_send_acl(jcr, sd, ACL_TYPE_DEFAULT, STREAM_UNIX_ATTRIBUTES_DEFAULT_ACL)) {
520                return 0;
521             }
522          }
523       } else {
524          Dmsg1(200, "No need to store ACLs from Links!\n", jcr->last_fname);
525       }
526    }
527    
528 #endif
529
530    /* Terminate any MD5 signature and send it to Storage daemon and the Director */
531    if (gotMD5 && ff_pkt->flags & FO_MD5) {
532       MD5Final(signature, &md5c);
533       bnet_fsend(sd, "%ld %d 0", jcr->JobFiles, STREAM_MD5_SIGNATURE);
534       Dmsg1(300, "bfiled>stored:header %s\n", sd->msg);
535       memcpy(sd->msg, signature, 16);
536       sd->msglen = 16;
537       bnet_send(sd);
538       bnet_sig(sd, BNET_EOD);         /* end of MD5 */
539       gotMD5 = 0;
540
541    } else if (gotSHA1 && ff_pkt->flags & FO_SHA1) {
542    /* Terminate any SHA1 signature and send it to Storage daemon and the Director */
543       SHA1Final(&sha1c, signature);
544       bnet_fsend(sd, "%ld %d 0", jcr->JobFiles, STREAM_SHA1_SIGNATURE);
545       Dmsg1(300, "bfiled>stored:header %s\n", sd->msg);
546       memcpy(sd->msg, signature, 20);
547       sd->msglen = 20;
548       bnet_send(sd);
549       bnet_sig(sd, BNET_EOD);         /* end of SHA1 */
550       gotMD5 = 0;
551    }
552    return 1;
553 }
554
555 #ifdef HAVE_ACL
556 /*
557 * Read and send an ACL for the last encountered file.
558 */
559 int read_send_acl(JCR *jcr, BSOCK *sd, int acltype, int stream)
560 {
561    POOLMEM *msgsave;
562    char *acl_text = NULL;
563    acl_t acl;
564
565    /* Read access ACLs for files, dirs and links */
566    acl = acl_get_file(jcr->last_fname, acltype);
567    if (!acl) {
568       Jmsg1(jcr, M_WARNING, 0, "Error while trying to get ACL of %s!\n", jcr->last_fname);
569       return 0;
570    }
571    
572    acl_text = acl_to_any_text(acl, NULL, ',', TEXT_ABBREVIATE);
573    
574    /* Check if ACL is valid */
575    if ((acl_valid(acl) != 0) && (acltype != ACL_TYPE_DEFAULT)) {
576       Jmsg1(jcr, M_WARNING, 0, "Failure in the ACL of %s! FD is not able to back it up!\n", jcr->last_fname);
577       Dmsg1(200, "ACL of file/dir: %s is not valid!\n", jcr->last_fname);
578       Dmsg1(200, "ACL value=%s\n", acl_text);
579    } else if (acl_valid(acl) == 0) {
580       Dmsg1(200, "ACL of file/dir: %s is valid!\n", jcr->last_fname);
581       Dmsg1(200, "ACL value=%s\n", acl_text);
582    } else {
583       Dmsg1(200, "Directory: %s has no Default ACL, there is nothing to do from here!\n", jcr->last_fname);
584       acl_free(acl);
585       return 0;
586    }
587    acl_free(acl);
588    
589    if (acl_text == NULL) {
590    /* ***FIXME*** Can this happen? */
591       Jmsg1(jcr, M_WARNING, 0, "Error decoding ACL of %s!\n", jcr->last_fname);
592       return 0;
593    }
594
595    if (!bnet_fsend(sd, "%ld %d 0", jcr->JobFiles, stream)) {
596       berrno be;
597       Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"), bnet_strerror(sd));
598       return 0;
599    }
600
601    /* Send the buffer to the storage deamon */
602    msgsave = sd->msg;
603    sd->msg = acl_text;
604    sd->msglen = strlen(acl_text) + 1;
605    if (!bnet_send(sd)) {
606       berrno be;
607       sd->msg = msgsave;
608       sd->msglen = 0;
609       Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"), bnet_strerror(sd));
610       return 0;
611    }
612
613    jcr->JobBytes += sd->msglen;
614    sd->msg = msgsave;
615    if (!bnet_sig(sd, BNET_EOD)) {
616    berrno be;
617    Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"), bnet_strerror(sd));
618    return 0;
619    }
620
621    Dmsg1(200, "ACL of file: %s successfully backed up!\n", jcr->last_fname);
622    return 1;
623    }
624 #endif