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