2 Bacula® - The Network Backup Solution
4 Copyright (C) 2008-2008 Free Software Foundation Europe e.V.
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
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.
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
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.
29 * Functions to handle Extended Attributes for bacula.
31 * Extended Attributes are so OS specific we only restore Extended Attributes if
32 * they were saved using a filed on the same platform.
34 * Currently we support the following OSes:
40 * Written by Marco van Wieringen, November MMVIII
42 * Version $Id: xattr.c 7879 2008-10-23 10:12:36Z kerns $
50 * List of supported OSs.
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) \
59 bool build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
61 Jmsg(jcr, M_FATAL, 0, _("XATTR support not configured for your machine.\n"));
65 bool parse_xattr_stream(JCR *jcr, int stream)
67 Jmsg(jcr, M_FATAL, 0, _("XATTR support not configured for your machine.\n"));
73 #ifdef HAVE_SYS_XATTR_H
74 #include <sys/xattr.h>
78 * OSX doesn't have llistxattr, lgetxattr and lsetxattr but has
79 * listxattr, getxattr and setxattr with an extra options argument
80 * which mimics the l variants of the functions when we specify
81 * XATTR_NOFOLLOW as the options value.
83 #if defined(HAVE_DARWIN_OS)
84 #define llistxattr(path, list, size) listxattr((path), (list), (size), XATTR_NOFOLLOW)
85 #define lgetxattr(path, name, value, size) getxattr((path), (name), (value), (size), 0, XATTR_NOFOLLOW)
86 #define lsetxattr(path, name, value, size, flags) setxattr((path), (name), (value), (size), (flags), XATTR_NOFOLLOW)
89 * Fallback to the non l-functions when those are not available.
91 #if defined(HAVE_GETXATTR) && !defined(HAVE_LGETXATTR)
92 #define lgetxattr getxattr
94 #if defined(HAVE_SETXATTR) && !defined(HAVE_LSETXATTR)
95 #define lsetxattr setxattr
97 #if defined(HAVE_LISTXATTR) && !defined(HAVE_LLISTXATTR)
98 #define llistxattr listxattr
103 * Send a XATTR stream to the SD.
105 static bool send_xattr_stream(JCR *jcr, int stream, int len)
107 BSOCK *sd = jcr->store_bsock;
109 #ifdef FD_NO_SEND_TEST
116 if (!sd->fsend("%ld %d 0", jcr->JobFiles, stream)) {
117 Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
124 * Send the buffer to the storage deamon
126 Dmsg1(400, "Backing up XATTR <%s>\n", jcr->xattr_data);
128 sd->msg = jcr->xattr_data;
133 Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
139 jcr->JobBytes += sd->msglen;
141 if (!sd->signal(BNET_EOD)) {
142 Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
148 Dmsg1(200, "XATTR of file: %s successfully backed up!\n", jcr->last_fname);
153 static void xattr_drop_internal_table(xattr_t *xattr_value_list)
155 xattr_t *current_xattr;
158 * Walk the list of xattrs and free allocated memory on traversing.
160 for (current_xattr = xattr_value_list;
161 current_xattr != (xattr_t *)NULL;
164 * See if we can shortcut.
166 if (current_xattr->magic != XATTR_MAGIC)
169 free(current_xattr->name);
171 if (current_xattr->value_length > 0)
172 free(current_xattr->value);
176 * Free the array of control structs.
178 free(xattr_value_list);
182 static uint32_t serialize_xattr_stream(JCR *jcr, uint32_t expected_serialize_len, xattr_t *xattr_value_list)
184 xattr_t *current_xattr;
188 * Make sure the serialized stream fits in the poolmem buffer.
189 * We allocate some more to be sure the stream is gonna fit.
191 jcr->xattr_data = check_pool_memory_size(jcr->xattr_data, expected_serialize_len + 10);
192 ser_begin(jcr->xattr_data, expected_serialize_len + 10);
195 * Walk the list of xattrs and serialize the data.
197 for (current_xattr = xattr_value_list; current_xattr != (xattr_t *)NULL; current_xattr++) {
199 * See if we can shortcut.
201 if (current_xattr->magic != XATTR_MAGIC)
204 ser_uint32(current_xattr->magic);
205 ser_uint32(current_xattr->name_length);
206 ser_bytes(current_xattr->name, current_xattr->name_length);
208 ser_uint32(current_xattr->value_length);
209 ser_bytes(current_xattr->value, current_xattr->value_length);
212 ser_end(jcr->xattr_data, expected_serialize_len + 10);
214 return ser_length(jcr->xattr_data);
217 static bool generic_xattr_build_streams(JCR *jcr, FF_PKT *ff_pkt, int stream)
220 int32_t xattr_list_len,
222 expected_serialize_len = 0,
224 char *xattr_list, *bp;
225 xattr_t *xattr_value_list, *current_xattr;
228 * First get the length of the available list with extended attributes.
230 xattr_list_len = llistxattr(jcr->last_fname, NULL, 0);
231 if (xattr_list_len < 0) {
233 Jmsg2(jcr, M_ERROR, 0, _("llistxattr error on file \"%s\": ERR=%s\n"),
234 jcr->last_fname, be.bstrerror());
235 Dmsg2(100, "llistxattr error file=%s ERR=%s\n",
236 jcr->last_fname, be.bstrerror());
238 } else if (xattr_list_len == 0) {
243 * Allocate room for the extented attribute list.
245 if ((xattr_list = (char *)malloc(xattr_list_len + 1)) == (char *)NULL) {
246 Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), xattr_list_len + 1);
250 memset((caddr_t)xattr_list, 0, xattr_list_len + 1);
253 * Get the actual list of extended attributes names for a file.
255 xattr_list_len = llistxattr(jcr->last_fname, xattr_list, xattr_list_len);
256 if (xattr_list_len < 0) {
258 Jmsg2(jcr, M_ERROR, 0, _("llistxattr error on file \"%s\": ERR=%s\n"),
259 jcr->last_fname, be.bstrerror());
260 Dmsg2(100, "llistxattr error file=%s ERR=%s\n",
261 jcr->last_fname, be.bstrerror());
266 xattr_list[xattr_list_len] = '\0';
269 * Count the number of extended attributes on a file.
272 while ((bp - xattr_list) + 1 < xattr_list_len) {
275 bp = strchr(bp, '\0') + 1;
279 * Allocate enough room to hold all extended attributes.
280 * After allocating the storage make sure its empty by zeroing it.
282 if ((xattr_value_list = (xattr_t *)malloc(count * sizeof(xattr_t))) == (xattr_t *)NULL) {
283 Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), count * sizeof(xattr_t));
287 memset((caddr_t)xattr_value_list, 0, count * sizeof(xattr_t));
290 * Walk the list of extended attributes names and retrieve the data.
291 * We already count the bytes needed for serializing the stream later on.
293 current_xattr = xattr_value_list;
295 while ((bp - xattr_list) + 1 < xattr_list_len) {
296 #if defined(HAVE_LINUX_OS)
298 * On Linux you also get the acls in the extented attribute list.
299 * So we check if we are already backing up acls and if we do we
300 * don't store the extended attribute with the same info.
302 if (ff_pkt->flags & FO_ACL && !strcmp(bp, "system.posix_acl_access")) {
303 bp = strchr(bp, '\0') + 1;
310 * Each xattr valuepair starts with a magic so we can parse it easier.
312 current_xattr->magic = XATTR_MAGIC;
313 expected_serialize_len += sizeof(current_xattr->magic);
316 * Allocate space for storing the name.
318 current_xattr->name_length = strlen(bp);
319 if ((current_xattr->name = (char *)malloc(current_xattr->name_length)) == (char *)NULL) {
320 Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), current_xattr->name_length);
324 memcpy((caddr_t)current_xattr->name, (caddr_t)bp, current_xattr->name_length);
326 expected_serialize_len += sizeof(current_xattr->name_length) + current_xattr->name_length;
329 * First see how long the value is for the extended attribute.
331 xattr_value_len = lgetxattr(jcr->last_fname, bp, NULL, 0);
332 if (xattr_value_len < 0) {
334 Jmsg2(jcr, M_ERROR, 0, _("lgetxattr error on file \"%s\": ERR=%s\n"),
335 jcr->last_fname, be.bstrerror());
336 Dmsg2(100, "lgetxattr error file=%s ERR=%s\n",
337 jcr->last_fname, be.bstrerror());
343 * Allocate space for storing the value.
345 if ((current_xattr->value = (char *)malloc(xattr_value_len)) == (char *)NULL) {
346 Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), xattr_value_len);
350 memset((caddr_t)current_xattr->value, 0, xattr_value_len);
352 xattr_value_len = lgetxattr(jcr->last_fname, bp, current_xattr->value, xattr_value_len);
353 if (xattr_value_len < 0) {
355 Jmsg2(jcr, M_ERROR, 0, _("lgetxattr error on file \"%s\": ERR=%s\n"),
356 jcr->last_fname, be.bstrerror());
357 Dmsg2(100, "lgetxattr error file=%s ERR=%s\n",
358 jcr->last_fname, be.bstrerror());
364 * Store the actual length of the value.
366 current_xattr->value_length = xattr_value_len;
368 expected_serialize_len += sizeof(current_xattr->value_length) + current_xattr->value_length;
374 bp = strchr(bp, '\0') + 1;
378 * Serialize the datastream.
380 if ((serialize_len = serialize_xattr_stream(jcr, expected_serialize_len,
381 xattr_value_list)) < expected_serialize_len) {
382 Jmsg1(jcr, M_ERROR, 0, _("failed to serialize extended attributes on file \"%s\"\n"),
388 xattr_drop_internal_table(xattr_value_list);
392 * Send the datastream to the SD.
394 return send_xattr_stream(jcr, stream, serialize_len);
397 xattr_drop_internal_table(xattr_value_list);
403 static bool generic_xattr_parse_streams(JCR *jcr)
406 xattr_t current_xattr;
410 * Parse the stream and perform the setxattr calls on the file.
412 * Start unserializing the data. We keep on looping while we have not
413 * unserialized all bytes in the stream.
415 unser_begin(jcr->xattr_data, jcr->xattr_data_len);
416 while (unser_length(jcr->xattr_data) < jcr->xattr_data_len) {
418 * First make sure the magic is present. This way we can easily catch corruption.
419 * Any missing MAGIC is fatal we do NOT try to continue.
421 unser_uint32(current_xattr.magic);
422 if (current_xattr.magic != XATTR_MAGIC) {
423 Jmsg1(jcr, M_ERROR, 0, _("Illegal xattr stream, no XATTR_MAGIC on file \"%s\"\n"),
430 * Decode the valuepair. First decode the length of the name.
432 unser_uint32(current_xattr.name_length);
435 * Allocate room for the name and decode its content.
437 if ((current_xattr.name = (char *)malloc(current_xattr.name_length + 1)) == (char *)NULL) {
438 Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), current_xattr.name_length + 1);
442 unser_bytes(current_xattr.name, current_xattr.name_length);
445 * The xattr_name needs to be null terminated for lsetxattr.
447 current_xattr.name[current_xattr.name_length] = '\0';
450 * Decode the value length.
452 unser_uint32(current_xattr.value_length);
455 * Allocate room for the value and decode its content.
457 if ((current_xattr.value = (char *)malloc(current_xattr.value_length)) == (char *)NULL) {
458 Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), current_xattr.value_length);
462 unser_bytes(current_xattr.value, current_xattr.value_length);
465 * Try to set the extended attribute on the file.
466 * If we fail to set this attribute we flag the error but its not fatal,
467 * we try to restore the other extended attributes too.
469 if (lsetxattr(jcr->last_fname, current_xattr.name, current_xattr.value,
470 current_xattr.value_length, 0) != 0) {
472 Jmsg2(jcr, M_ERROR, 0, _("lsetxattr error on file \"%s\": ERR=%s\n"),
473 jcr->last_fname, be.bstrerror());
474 Dmsg2(100, "lsetxattr error file=%s ERR=%s\n",
475 jcr->last_fname, be.bstrerror());
478 * Reset the return flag to false to indicate one or more extended attributes
479 * could not be restored.
485 * Free the temporary buffers.
487 free(current_xattr.name);
488 free(current_xattr.value);
491 unser_end(jcr->xattr_data, jcr->xattr_data_len);
495 #if defined(HAVE_DARWIN_OS)
496 static bool darwin_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
498 return generic_xattr_build_streams(jcr, ff_pkt, STREAM_XATTR_DARWIN);
501 static bool darwin_parse_xattr_stream(JCR *jcr, int stream)
504 case STREAM_XATTR_DARWIN:
505 return generic_xattr_parse_streams(jcr);
508 #elif defined(HAVE_FREEBSD_OS)
509 static bool freebsd_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
511 return generic_xattr_build_streams(jcr, ff_pkt, STREAM_XATTR_FREEBSD);
514 static bool freebsd_parse_xattr_stream(JCR *jcr, int stream)
517 case STREAM_XATTR_FREEBSD:
518 return generic_xattr_parse_streams(jcr);
521 #elif defined(HAVE_LINUX_OS)
522 static bool linux_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
524 return generic_xattr_build_streams(jcr, ff_pkt, STREAM_XATTR_LINUX);
527 static bool linux_parse_xattr_stream(JCR *jcr, int stream)
530 case STREAM_XATTR_LINUX:
531 return generic_xattr_parse_streams(jcr);
535 #elif defined(HAVE_NETBSD_OS)
536 static bool netbsd_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
538 return generic_xattr_build_streams(jcr, ff_pkt, STREAM_XATTR_NETBSD);
541 static bool netbsd_parse_xattr_stream(JCR *jcr, int stream)
544 case STREAM_XATTR_NETBSD:
545 return generic_xattr_parse_streams(jcr);
551 bool build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
553 #if defined(HAVE_DARWIN_OS)
554 return darwin_build_xattr_streams(jcr, ff_pkt);
555 #elif defined(HAVE_FREEBSD_OS)
556 return freebsd_build_xattr_streams(jcr, ff_pkt);
557 #elif defined(HAVE_LINUX_OS)
558 return linux_build_xattr_streams(jcr, ff_pkt);
559 #elif defined(HAVE_NETBSD_OS)
560 return netbsd_build_xattr_streams(jcr, ff_pkt);
564 bool parse_xattr_stream(JCR *jcr, int stream)
567 * Based on the stream being passed in dispatch to the right function
568 * for parsing and restoring a specific xattr. The platform determines
569 * which streams are recognized and parsed and which are handled by
570 * the default case and ignored. As only one of the platform defines
571 * is true per compile we never end up with duplicate switch values.
574 #if defined(HAVE_DARWIN_OS)
575 case STREAM_XATTR_DARWIN:
576 return darwin_parse_xattr_stream(jcr, stream);
577 #elif defined(HAVE_FREEBSD_OS)
578 case STREAM_XATTR_FREEBSD:
579 return freebsd_parse_xattr_stream(jcr, stream);
580 #elif defined(HAVE_LINUX_OS)
581 case STREAM_XATTR_LINUX:
582 return linux_parse_xattr_stream(jcr, stream);
583 #elif defined(HAVE_NETBSD_OS)
584 case STREAM_XATTR_NETBSD:
585 return netbsd_parse_xattr_stream(jcr, stream);
589 * Issue a warning and discard the message. But pretend the restore was ok.
591 Qmsg2(jcr, M_WARNING, 0,
592 _("Can't restore Extended Attributes of %s - incompatible xattr stream encountered - %d\n"),
593 jcr->last_fname, stream);
595 } /* end switch (stream) */