]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/xattr.c
Kludge Darwin build
[bacula/bacula] / bacula / src / filed / xattr.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2008-2008 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version two of the GNU 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    General Public License for more details.
17
18    You should have received a copy of the GNU 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    Bacula® is a registered trademark of Kern Sibbald.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28 /*
29  * Functions to handle Extended Attributes for bacula.
30  *
31  * Extended Attributes are so OS specific we only restore Extended Attributes if
32  * they were saved using a filed on the same platform.
33  *
34  * Currently we support the following OSes:
35  *   - FreeBSD
36  *   - Darwin
37  *   - Linux
38  *   - NetBSD
39  *
40  *   Written by Marco van Wieringen, November MMVIII
41  *
42  *   Version $Id: xattr.c 7879 2008-10-23 10:12:36Z kerns $
43  */
44
45 #include "bacula.h"
46 #include "filed.h"
47 #include "xattr.h"
48
49 /* Klude to fix Darwin build -- KES */
50 #ifdef HAVE_DARWIN_OS
51 #undef HAVE_XATTR
52 #endif
53
54
55 /*
56  * List of supported OSs.
57  */
58 #if !defined(HAVE_XATTR)            /* Extended Attributes support is required, of course */ \
59    || !( defined(HAVE_DARWIN_OS) \
60       || defined(HAVE_FREEBSD_OS) \
61       || defined(HAVE_LINUX_OS) \
62       || defined(HAVE_NETBSD_OS) \
63         )
64
65 bool build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
66 {
67    Jmsg(jcr, M_FATAL, 0, _("XATTR support not configured for your machine.\n"));
68    return false;
69 }
70
71 bool parse_xattr_stream(JCR *jcr, int stream)
72 {
73    Jmsg(jcr, M_FATAL, 0, _("XATTR support not configured for your machine.\n"));
74    return false;
75 }
76
77 #else
78
79 #ifdef HAVE_SYS_XATTR_H
80 #include <sys/xattr.h>
81 #endif
82
83 #if defined(HAVE_GETXATTR) && !defined(HAVE_LGETXATTR)
84 #define lgetxattr getxattr
85 #endif
86 #if defined(HAVE_SETXATTR) && !defined(HAVE_LSETXATTR)
87 #define lsetxattr setxattr
88 #endif
89 #if defined(HAVE_LISTXATTR) && !defined(HAVE_LLISTXATTR)
90 #define llistxattr listxattr
91 #endif
92
93 /*
94  * Send a XATTR stream to the SD.
95  */
96 static bool send_xattr_stream(JCR *jcr, int stream, int len)
97 {
98    BSOCK *sd = jcr->store_bsock;
99    POOLMEM *msgsave;
100 #ifdef FD_NO_SEND_TEST
101    return true;
102 #endif
103
104    /*
105     * Send header
106     */
107    if (!sd->fsend("%ld %d 0", jcr->JobFiles, stream)) {
108       Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
109             sd->bstrerror());
110
111       return false;
112    }
113
114    /*
115     * Send the buffer to the storage deamon
116     */
117    Dmsg1(400, "Backing up XATTR <%s>\n", jcr->xattr_data);
118    msgsave = sd->msg;
119    sd->msg = jcr->xattr_data;
120    sd->msglen = len;
121    if (!sd->send()) {
122       sd->msg = msgsave;
123       sd->msglen = 0;
124       Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
125             sd->bstrerror());
126
127       return false;
128    }
129
130    jcr->JobBytes += sd->msglen;
131    sd->msg = msgsave;
132    if (!sd->signal(BNET_EOD)) {
133       Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
134             sd->bstrerror());
135
136       return false;
137    }
138
139    Dmsg1(200, "XATTR of file: %s successfully backed up!\n", jcr->last_fname);
140
141    return true;
142 }
143
144 static void xattr_drop_internal_table(xattr_t *xattr_value_list)
145 {
146    xattr_t *current_xattr;
147
148    /*
149     * Walk the list of xattrs and free allocated memory on traversing.
150     */
151    for (current_xattr = xattr_value_list;
152         current_xattr != (xattr_t *)NULL;
153         current_xattr++) {
154       /*
155        * See if we can shortcut.
156        */
157       if (current_xattr->magic != XATTR_MAGIC)
158          break;
159
160       free(current_xattr->name);
161
162       if (current_xattr->value_length > 0)
163          free(current_xattr->value);
164    }
165
166    /*
167     * Free the array of control structs.
168     */
169    free(xattr_value_list);
170 }
171
172
173 static uint32_t serialize_xattr_stream(JCR *jcr, uint32_t expected_serialize_len, xattr_t *xattr_value_list)
174 {
175    xattr_t *current_xattr;
176    ser_declare;
177
178    /*
179     * Make sure the serialized stream fits in the poolmem buffer.
180     * We allocate some more to be sure the stream is gonna fit.
181     */
182    jcr->xattr_data = check_pool_memory_size(jcr->xattr_data, expected_serialize_len + 10);
183    ser_begin(jcr->xattr_data, expected_serialize_len + 10);
184
185    /*
186     * Walk the list of xattrs and serialize the data.
187     */
188    for (current_xattr = xattr_value_list; current_xattr != (xattr_t *)NULL; current_xattr++) {
189       /*
190        * See if we can shortcut.
191        */
192       if (current_xattr->magic != XATTR_MAGIC)
193          break;
194
195       ser_uint32(current_xattr->magic);
196       ser_uint32(current_xattr->name_length);
197       ser_bytes(current_xattr->name, current_xattr->name_length);
198
199       ser_uint32(current_xattr->value_length);
200       ser_bytes(current_xattr->value, current_xattr->value_length);
201    }
202
203    ser_end(jcr->xattr_data, expected_serialize_len + 10);
204
205    return ser_length(jcr->xattr_data);
206 }
207
208 static bool generic_xattr_build_streams(JCR *jcr, FF_PKT *ff_pkt, int stream)
209 {
210    int count = 0;
211    int32_t xattr_list_len,
212            xattr_value_len,
213            expected_serialize_len = 0,
214            serialize_len = 0;
215    char *xattr_list, *bp;
216    xattr_t *xattr_value_list, *current_xattr;
217
218    /*
219     * First get the length of the available list with extended attributes.
220     */
221    xattr_list_len = llistxattr(jcr->last_fname, NULL, 0);
222    if (xattr_list_len < 0) {
223       berrno be;
224       Jmsg2(jcr, M_ERROR, 0, _("llistxattr error on file \"%s\": ERR=%s\n"),
225          jcr->last_fname, be.bstrerror());
226       Dmsg2(100, "llistxattr error file=%s ERR=%s\n",
227          jcr->last_fname, be.bstrerror());
228       return false;
229    } else if (xattr_list_len == 0) {
230       return true;
231    }
232
233    /*
234     * Allocate room for the extented attribute list.
235     */
236    if ((xattr_list = (char *)malloc(xattr_list_len + 1)) == (char *)NULL) {
237       Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), xattr_list_len + 1);
238
239       return false;
240    }
241    memset((caddr_t)xattr_list, 0, xattr_list_len + 1);
242
243    /*
244     * Get the actual list of extended attributes names for a file.
245     */
246    xattr_list_len = llistxattr(jcr->last_fname, xattr_list, xattr_list_len);
247    if (xattr_list_len < 0) {
248       berrno be;
249       Jmsg2(jcr, M_ERROR, 0, _("llistxattr error on file \"%s\": ERR=%s\n"),
250          jcr->last_fname, be.bstrerror());
251       Dmsg2(100, "llistxattr error file=%s ERR=%s\n",
252          jcr->last_fname, be.bstrerror());
253
254       free(xattr_list);
255       return false;
256    }
257    xattr_list[xattr_list_len] = '\0';
258
259    /*
260     * Count the number of extended attributes on a file.
261     */
262    bp = xattr_list;
263    while ((bp - xattr_list) + 1 < xattr_list_len) {
264       count++;
265
266       bp = strchr(bp, '\0') + 1;
267    }
268
269    /*
270     * Allocate enough room to hold all extended attributes.
271     * After allocating the storage make sure its empty by zeroing it.
272     */
273    if ((xattr_value_list = (xattr_t *)malloc(count * sizeof(xattr_t))) == (xattr_t *)NULL) {
274       Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), count * sizeof(xattr_t));
275
276       return false;
277    }
278    memset((caddr_t)xattr_value_list, 0, count * sizeof(xattr_t));
279
280    /*
281     * Walk the list of extended attributes names and retrieve the data.
282     * We already count the bytes needed for serializing the stream later on.
283     */
284    current_xattr = xattr_value_list;
285    bp = xattr_list;
286    while ((bp - xattr_list) + 1 < xattr_list_len) {
287 #if defined(HAVE_LINUX_OS)
288       /*
289        * On Linux you also get the acls in the extented attribute list.
290        * So we check if we are already backing up acls and if we do we
291        * don't store the extended attribute with the same info.
292        */
293       if (ff_pkt->flags & FO_ACL && !strcmp(bp, "system.posix_acl_access")) {
294          bp = strchr(bp, '\0') + 1;
295
296          continue;
297       }
298 #endif
299
300       /*
301        * Each xattr valuepair starts with a magic so we can parse it easier.
302        */
303       current_xattr->magic = XATTR_MAGIC;
304       expected_serialize_len += sizeof(current_xattr->magic);
305
306       /*
307        * Allocate space for storing the name.
308        */
309       current_xattr->name_length = strlen(bp);
310       if ((current_xattr->name = (char *)malloc(current_xattr->name_length)) == (char *)NULL) {
311          Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), current_xattr->name_length);
312
313          goto bail_out;
314       }
315       memcpy((caddr_t)current_xattr->name, (caddr_t)bp, current_xattr->name_length);
316
317       expected_serialize_len += sizeof(current_xattr->name_length) + current_xattr->name_length;
318
319       /*
320        * First see how long the value is for the extended attribute.
321        */
322       xattr_value_len = lgetxattr(jcr->last_fname, bp, NULL, 0);
323       if (xattr_value_len < 0) {
324          berrno be;
325          Jmsg2(jcr, M_ERROR, 0, _("lgetxattr error on file \"%s\": ERR=%s\n"),
326             jcr->last_fname, be.bstrerror());
327          Dmsg2(100, "lgetxattr error file=%s ERR=%s\n",
328             jcr->last_fname, be.bstrerror());
329
330          goto bail_out;
331       }
332
333       /*
334        * Allocate space for storing the value.
335        */
336       if ((current_xattr->value = (char *)malloc(xattr_value_len)) == (char *)NULL) {
337          Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), xattr_value_len);
338
339          goto bail_out;
340       }
341       memset((caddr_t)current_xattr->value, 0, xattr_value_len);
342
343       xattr_value_len = lgetxattr(jcr->last_fname, bp, current_xattr->value, xattr_value_len);
344       if (xattr_value_len < 0) {
345          berrno be;
346          Jmsg2(jcr, M_ERROR, 0, _("lgetxattr error on file \"%s\": ERR=%s\n"),
347             jcr->last_fname, be.bstrerror());
348          Dmsg2(100, "lgetxattr error file=%s ERR=%s\n",
349             jcr->last_fname, be.bstrerror());
350
351          goto bail_out;
352       }
353
354       /*
355        * Store the actual length of the value.
356        */
357       current_xattr->value_length = xattr_value_len;
358
359       expected_serialize_len += sizeof(current_xattr->value_length) + current_xattr->value_length;
360       
361       /*
362        * Next attribute.
363        */
364       current_xattr++;
365       bp = strchr(bp, '\0') + 1;
366    }
367
368    /*
369     * Serialize the datastream.
370     */
371    if ((serialize_len = serialize_xattr_stream(jcr, expected_serialize_len,
372          xattr_value_list)) < expected_serialize_len) {
373       Jmsg1(jcr, M_ERROR, 0, _("failed to serialize extended attributes on file \"%s\"\n"),
374          jcr->last_fname);
375
376       goto bail_out;
377    }
378
379    xattr_drop_internal_table(xattr_value_list);
380    free(xattr_list);
381
382    /*
383     * Send the datastream to the SD.
384     */
385    return send_xattr_stream(jcr, stream, serialize_len);
386
387 bail_out:
388    xattr_drop_internal_table(xattr_value_list);
389    free(xattr_list);
390
391    return false;
392 }
393
394 static bool generic_xattr_parse_streams(JCR *jcr)
395 {
396    unser_declare;
397    xattr_t current_xattr;
398    bool retval = true;
399
400    /*
401     * Parse the stream and perform the setxattr calls on the file.
402     *
403     * Start unserializing the data. We keep on looping while we have not
404     * unserialized all bytes in the stream.
405     */
406    unser_begin(jcr->xattr_data, jcr->xattr_data_len);
407    while (unser_length(jcr->xattr_data) < jcr->xattr_data_len) {
408       /*
409        * First make sure the magic is present. This way we can easily catch corruption.
410        * Any missing MAGIC is fatal we do NOT try to continue.
411        */
412       unser_uint32(current_xattr.magic);
413       if (current_xattr.magic != XATTR_MAGIC) {
414          Jmsg1(jcr, M_ERROR, 0, _("Illegal xattr stream, no XATTR_MAGIC on file \"%s\"\n"),
415             jcr->last_fname);
416
417          return false;
418       }
419
420       /*
421        * Decode the valuepair. First decode the length of the name.
422        */
423       unser_uint32(current_xattr.name_length);
424       
425       /*
426        * Allocate room for the name and decode its content.
427        */
428       if ((current_xattr.name = (char *)malloc(current_xattr.name_length + 1)) == (char *)NULL) {
429          Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), current_xattr.name_length + 1);
430
431          return false;
432       }
433       unser_bytes(current_xattr.name, current_xattr.name_length);
434
435       /*
436        * The xattr_name needs to be null terminated for lsetxattr.
437        */
438       current_xattr.name[current_xattr.name_length] = '\0';
439
440       /*
441        * Decode the value length.
442        */
443       unser_uint32(current_xattr.value_length);
444
445       /*
446        * Allocate room for the value and decode its content.
447        */
448       if ((current_xattr.value = (char *)malloc(current_xattr.value_length)) == (char *)NULL) {
449          Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), current_xattr.value_length);
450
451          return false;
452       }
453       unser_bytes(current_xattr.value, current_xattr.value_length);
454
455       /*
456        * Try to set the extended attribute on the file.
457        * If we fail to set this attribute we flag the error but its not fatal,
458        * we try to restore the other extended attributes too.
459        */
460       if (lsetxattr(jcr->last_fname, current_xattr.name, current_xattr.value,
461          current_xattr.value_length, 0) != 0) {
462          berrno be;
463          Jmsg2(jcr, M_ERROR, 0, _("lsetxattr error on file \"%s\": ERR=%s\n"),
464             jcr->last_fname, be.bstrerror());
465          Dmsg2(100, "lsetxattr error file=%s ERR=%s\n",
466             jcr->last_fname, be.bstrerror());
467
468          /*
469           * Reset the return flag to false to indicate one or more extended attributes
470           * could not be restored.
471           */
472          retval = false;
473       }
474
475       /*
476        * Free the temporary buffers.
477        */
478       free(current_xattr.name);
479       free(current_xattr.value);
480    }
481
482    unser_end(jcr->xattr_data, jcr->xattr_data_len);
483    return retval;
484 }
485
486 #if defined(HAVE_DARWIN_OS)
487 static bool darwin_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
488 {
489    return generic_xattr_build_streams(jcr, ff_pkt, STREAM_XATTR_DARWIN);
490 }
491
492 static bool darwin_parse_xattr_stream(JCR *jcr, int stream)
493 {
494    switch (stream) {
495    case STREAM_XATTR_DARWIN:
496       return generic_xattr_parse_streams(jcr);
497    }
498 }
499 #elif defined(HAVE_FREEBSD_OS)
500 static bool freebsd_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
501 {
502    return generic_xattr_build_streams(jcr, ff_pkt, STREAM_XATTR_FREEBSD);
503 }
504
505 static bool freebsd_parse_xattr_stream(JCR *jcr, int stream)
506 {
507    switch (stream) {
508    case STREAM_XATTR_FREEBSD:
509       return generic_xattr_parse_streams(jcr);
510    }
511 }
512 #elif defined(HAVE_LINUX_OS)
513 static bool linux_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
514 {
515    return generic_xattr_build_streams(jcr, ff_pkt, STREAM_XATTR_LINUX);
516 }
517
518 static bool linux_parse_xattr_stream(JCR *jcr, int stream)
519 {
520    switch (stream) {
521    case STREAM_XATTR_LINUX:
522       return generic_xattr_parse_streams(jcr);
523    }
524    return false;
525 }
526 #elif defined(HAVE_NETBSD_OS)
527 static bool netbsd_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
528 {
529    return generic_xattr_build_streams(jcr, ff_pkt, STREAM_XATTR_NETBSD);
530 }
531
532 static bool netbsd_parse_xattr_stream(JCR *jcr, int stream)
533 {
534    switch (stream) {
535    case STREAM_XATTR_NETBSD:
536       return generic_xattr_parse_streams(jcr);
537    }
538    return false;
539 }
540 #endif
541
542 bool build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
543 {
544 #if defined(HAVE_DARWIN_OS)
545    return darwin_build_xattr_streams(jcr, ff_pkt);
546 #elif defined(HAVE_FREEBSD_OS)
547    return freebsd_build_xattr_streams(jcr, ff_pkt);
548 #elif defined(HAVE_LINUX_OS)
549    return linux_build_xattr_streams(jcr, ff_pkt);
550 #elif defined(HAVE_NETBSD_OS)
551    return netbsd_build_xattr_streams(jcr, ff_pkt);
552 #endif
553 }
554
555 bool parse_xattr_stream(JCR *jcr, int stream)
556 {
557    /*
558     * Based on the stream being passed in dispatch to the right function
559     * for parsing and restoring a specific xattr. The platform determines
560     * which streams are recognized and parsed and which are handled by
561     * the default case and ignored. As only one of the platform defines
562     * is true per compile we never end up with duplicate switch values.
563     */
564    switch (stream) {
565 #if defined(HAVE_DARWIN_OS)
566    case STREAM_XATTR_DARWIN:
567       return darwin_parse_xattr_stream(jcr, stream);
568 #elif defined(HAVE_FREEBSD_OS)
569    case STREAM_XATTR_FREEBSD:
570       return freebsd_parse_xattr_stream(jcr, stream);
571 #elif defined(HAVE_LINUX_OS)
572    case STREAM_XATTR_LINUX:
573       return linux_parse_xattr_stream(jcr, stream);
574 #elif defined(HAVE_NETBSD_OS)
575    case STREAM_XATTR_NETBSD:
576       return netbsd_parse_xattr_stream(jcr, stream);
577 #endif
578    default:
579       /*
580        * Issue a warning and discard the message. But pretend the restore was ok.
581        */
582       Qmsg2(jcr, M_WARNING, 0,
583          _("Can't restore Extended Attributes of %s - incompatible xattr stream encountered - %d\n"),
584          jcr->last_fname, stream);
585       return true;
586    } /* end switch (stream) */
587 }
588
589 #endif