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