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:
35 * - FreeBSD (Extended Attributes)
36 * - Darwin (Extended Attributes)
37 * - Linux (Extended Attributes)
38 * - NetBSD (Extended Attributes)
39 * - Solaris (Extended Attributes and Extensible Attributes)
41 * Written by Marco van Wieringen, November MMVIII
43 * Version $Id: xattr.c 7879 2008-10-23 10:12:36Z kerns $
51 * List of supported OSs. Everything outside that gets stub functions.
52 * Also when XATTR support is explicitly disabled.
54 #if !defined(HAVE_XATTR) /* Extended Attributes support is required, of course */ \
55 || !( defined(HAVE_DARWIN_OS) /* OSX has XATTR support using getxattr etc. */ \
56 || defined(HAVE_FREEBSD_OS) /* FreeBSD has XATTR support using lgetxattr etc. */ \
57 || defined(HAVE_LINUX_OS) /* Linux has XATTR support using the lgetxattr etc. */ \
58 || defined(HAVE_NETBSD_OS) /* NetBSD has XATTR support using the lgetxattr etc. */ \
59 || defined(HAVE_SUN_OS) /* Solaris has XATTR support using attropen etc. */ \
62 bool build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
64 Jmsg(jcr, M_FATAL, 0, _("XATTR support not configured for your machine.\n"));
68 bool parse_xattr_stream(JCR *jcr, int stream)
70 Jmsg(jcr, M_FATAL, 0, _("XATTR support not configured for your machine.\n"));
77 * This is a supported OS, See what kind of interface we should use.
78 * Start with the generic interface used by most OS-es.
80 #if defined(HAVE_DARWIN_OS) \
81 || defined(HAVE_FREEBSD_OS) \
82 || defined(HAVE_LINUX_OS) \
83 || defined(HAVE_NETBSD_OS)
85 #ifdef HAVE_SYS_XATTR_H
86 #include <sys/xattr.h>
90 * OSX doesn't have llistxattr, lgetxattr and lsetxattr but has
91 * listxattr, getxattr and setxattr with an extra options argument
92 * which mimics the l variants of the functions when we specify
93 * XATTR_NOFOLLOW as the options value.
95 #if defined(HAVE_DARWIN_OS)
96 #define llistxattr(path, list, size) listxattr((path), (list), (size), XATTR_NOFOLLOW)
97 #define lgetxattr(path, name, value, size) getxattr((path), (name), (value), (size), 0, XATTR_NOFOLLOW)
98 #define lsetxattr(path, name, value, size, flags) setxattr((path), (name), (value), (size), (flags), XATTR_NOFOLLOW)
101 * Fallback to the non l-functions when those are not available.
103 #if defined(HAVE_GETXATTR) && !defined(HAVE_LGETXATTR)
104 #define lgetxattr getxattr
106 #if defined(HAVE_SETXATTR) && !defined(HAVE_LSETXATTR)
107 #define lsetxattr setxattr
109 #if defined(HAVE_LISTXATTR) && !defined(HAVE_LLISTXATTR)
110 #define llistxattr listxattr
115 * Send a XATTR stream to the SD.
117 static bool send_xattr_stream(JCR *jcr, int stream, int len)
119 BSOCK *sd = jcr->store_bsock;
121 #ifdef FD_NO_SEND_TEST
128 if (!sd->fsend("%ld %d 0", jcr->JobFiles, stream)) {
129 Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
136 * Send the buffer to the storage deamon
138 Dmsg1(400, "Backing up XATTR <%s>\n", jcr->xattr_data);
140 sd->msg = jcr->xattr_data;
145 Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
151 jcr->JobBytes += sd->msglen;
153 if (!sd->signal(BNET_EOD)) {
154 Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
160 Dmsg1(200, "XATTR of file: %s successfully backed up!\n", jcr->last_fname);
165 static void xattr_drop_internal_table(xattr_t *xattr_value_list)
167 xattr_t *current_xattr;
170 * Walk the list of xattrs and free allocated memory on traversing.
172 for (current_xattr = xattr_value_list;
173 current_xattr != (xattr_t *)NULL;
176 * See if we can shortcut.
178 if (current_xattr->magic != XATTR_MAGIC)
181 free(current_xattr->name);
183 if (current_xattr->value_length > 0)
184 free(current_xattr->value);
188 * Free the array of control structs.
190 free(xattr_value_list);
194 static uint32_t serialize_xattr_stream(JCR *jcr, uint32_t expected_serialize_len, xattr_t *xattr_value_list)
196 xattr_t *current_xattr;
200 * Make sure the serialized stream fits in the poolmem buffer.
201 * We allocate some more to be sure the stream is gonna fit.
203 jcr->xattr_data = check_pool_memory_size(jcr->xattr_data, expected_serialize_len + 10);
204 ser_begin(jcr->xattr_data, expected_serialize_len + 10);
207 * Walk the list of xattrs and serialize the data.
209 for (current_xattr = xattr_value_list; current_xattr != (xattr_t *)NULL; current_xattr++) {
211 * See if we can shortcut.
213 if (current_xattr->magic != XATTR_MAGIC)
216 ser_uint32(current_xattr->magic);
217 ser_uint32(current_xattr->name_length);
218 ser_bytes(current_xattr->name, current_xattr->name_length);
220 ser_uint32(current_xattr->value_length);
221 ser_bytes(current_xattr->value, current_xattr->value_length);
224 ser_end(jcr->xattr_data, expected_serialize_len + 10);
226 return ser_length(jcr->xattr_data);
229 static bool generic_xattr_build_streams(JCR *jcr, FF_PKT *ff_pkt, int stream)
232 int32_t xattr_list_len,
234 expected_serialize_len = 0,
236 char *xattr_list, *bp;
237 xattr_t *xattr_value_list, *current_xattr;
240 * First get the length of the available list with extended attributes.
242 xattr_list_len = llistxattr(jcr->last_fname, NULL, 0);
243 if (xattr_list_len < 0) {
245 Jmsg2(jcr, M_ERROR, 0, _("llistxattr error on file \"%s\": ERR=%s\n"),
246 jcr->last_fname, be.bstrerror());
247 Dmsg2(100, "llistxattr error file=%s ERR=%s\n",
248 jcr->last_fname, be.bstrerror());
250 } else if (xattr_list_len == 0) {
255 * Allocate room for the extented attribute list.
257 if ((xattr_list = (char *)malloc(xattr_list_len + 1)) == (char *)NULL) {
258 Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), xattr_list_len + 1);
262 memset((caddr_t)xattr_list, 0, xattr_list_len + 1);
265 * Get the actual list of extended attributes names for a file.
267 xattr_list_len = llistxattr(jcr->last_fname, xattr_list, xattr_list_len);
268 if (xattr_list_len < 0) {
270 Jmsg2(jcr, M_ERROR, 0, _("llistxattr error on file \"%s\": ERR=%s\n"),
271 jcr->last_fname, be.bstrerror());
272 Dmsg2(100, "llistxattr error file=%s ERR=%s\n",
273 jcr->last_fname, be.bstrerror());
278 xattr_list[xattr_list_len] = '\0';
281 * Count the number of extended attributes on a file.
284 while ((bp - xattr_list) + 1 < xattr_list_len) {
287 bp = strchr(bp, '\0') + 1;
291 * Allocate enough room to hold all extended attributes.
292 * After allocating the storage make sure its empty by zeroing it.
294 if ((xattr_value_list = (xattr_t *)malloc(count * sizeof(xattr_t))) == (xattr_t *)NULL) {
295 Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), count * sizeof(xattr_t));
299 memset((caddr_t)xattr_value_list, 0, count * sizeof(xattr_t));
302 * Walk the list of extended attributes names and retrieve the data.
303 * We already count the bytes needed for serializing the stream later on.
305 current_xattr = xattr_value_list;
307 while ((bp - xattr_list) + 1 < xattr_list_len) {
308 #if defined(HAVE_LINUX_OS)
310 * On Linux you also get the acls in the extented attribute list.
311 * So we check if we are already backing up acls and if we do we
312 * don't store the extended attribute with the same info.
314 if (ff_pkt->flags & FO_ACL && !strcmp(bp, "system.posix_acl_access")) {
315 bp = strchr(bp, '\0') + 1;
322 * Each xattr valuepair starts with a magic so we can parse it easier.
324 current_xattr->magic = XATTR_MAGIC;
325 expected_serialize_len += sizeof(current_xattr->magic);
328 * Allocate space for storing the name.
330 current_xattr->name_length = strlen(bp);
331 if ((current_xattr->name = (char *)malloc(current_xattr->name_length)) == (char *)NULL) {
332 Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), current_xattr->name_length);
336 memcpy((caddr_t)current_xattr->name, (caddr_t)bp, current_xattr->name_length);
338 expected_serialize_len += sizeof(current_xattr->name_length) + current_xattr->name_length;
341 * First see how long the value is for the extended attribute.
343 xattr_value_len = lgetxattr(jcr->last_fname, bp, NULL, 0);
344 if (xattr_value_len < 0) {
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());
355 * Allocate space for storing the value.
357 if ((current_xattr->value = (char *)malloc(xattr_value_len)) == (char *)NULL) {
358 Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), xattr_value_len);
362 memset((caddr_t)current_xattr->value, 0, xattr_value_len);
364 xattr_value_len = lgetxattr(jcr->last_fname, bp, current_xattr->value, xattr_value_len);
365 if (xattr_value_len < 0) {
367 Jmsg2(jcr, M_ERROR, 0, _("lgetxattr error on file \"%s\": ERR=%s\n"),
368 jcr->last_fname, be.bstrerror());
369 Dmsg2(100, "lgetxattr error file=%s ERR=%s\n",
370 jcr->last_fname, be.bstrerror());
376 * Store the actual length of the value.
378 current_xattr->value_length = xattr_value_len;
380 expected_serialize_len += sizeof(current_xattr->value_length) + current_xattr->value_length;
386 bp = strchr(bp, '\0') + 1;
390 * Serialize the datastream.
392 if ((serialize_len = serialize_xattr_stream(jcr, expected_serialize_len,
393 xattr_value_list)) < expected_serialize_len) {
394 Jmsg1(jcr, M_ERROR, 0, _("failed to serialize extended attributes on file \"%s\"\n"),
400 xattr_drop_internal_table(xattr_value_list);
404 * Send the datastream to the SD.
406 return send_xattr_stream(jcr, stream, serialize_len);
409 xattr_drop_internal_table(xattr_value_list);
415 static bool generic_xattr_parse_streams(JCR *jcr)
418 xattr_t current_xattr;
422 * Parse the stream and perform the setxattr calls on the file.
424 * Start unserializing the data. We keep on looping while we have not
425 * unserialized all bytes in the stream.
427 unser_begin(jcr->xattr_data, jcr->xattr_data_len);
428 while (unser_length(jcr->xattr_data) < jcr->xattr_data_len) {
430 * First make sure the magic is present. This way we can easily catch corruption.
431 * Any missing MAGIC is fatal we do NOT try to continue.
433 unser_uint32(current_xattr.magic);
434 if (current_xattr.magic != XATTR_MAGIC) {
435 Jmsg1(jcr, M_ERROR, 0, _("Illegal xattr stream, no XATTR_MAGIC on file \"%s\"\n"),
442 * Decode the valuepair. First decode the length of the name.
444 unser_uint32(current_xattr.name_length);
447 * Allocate room for the name and decode its content.
449 if ((current_xattr.name = (char *)malloc(current_xattr.name_length + 1)) == (char *)NULL) {
450 Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), current_xattr.name_length + 1);
454 unser_bytes(current_xattr.name, current_xattr.name_length);
457 * The xattr_name needs to be null terminated for lsetxattr.
459 current_xattr.name[current_xattr.name_length] = '\0';
462 * Decode the value length.
464 unser_uint32(current_xattr.value_length);
467 * Allocate room for the value and decode its content.
469 if ((current_xattr.value = (char *)malloc(current_xattr.value_length)) == (char *)NULL) {
470 Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), current_xattr.value_length);
474 unser_bytes(current_xattr.value, current_xattr.value_length);
477 * Try to set the extended attribute on the file.
478 * If we fail to set this attribute we flag the error but its not fatal,
479 * we try to restore the other extended attributes too.
481 if (lsetxattr(jcr->last_fname, current_xattr.name, current_xattr.value,
482 current_xattr.value_length, 0) != 0) {
484 Jmsg2(jcr, M_ERROR, 0, _("lsetxattr error on file \"%s\": ERR=%s\n"),
485 jcr->last_fname, be.bstrerror());
486 Dmsg2(100, "lsetxattr error file=%s ERR=%s\n",
487 jcr->last_fname, be.bstrerror());
490 * Reset the return flag to false to indicate one or more extended attributes
491 * could not be restored.
497 * Free the temporary buffers.
499 free(current_xattr.name);
500 free(current_xattr.value);
503 unser_end(jcr->xattr_data, jcr->xattr_data_len);
507 #if defined(HAVE_DARWIN_OS)
508 static bool darwin_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
510 return generic_xattr_build_streams(jcr, ff_pkt, STREAM_XATTR_DARWIN);
513 static bool darwin_parse_xattr_stream(JCR *jcr, int stream)
516 case STREAM_XATTR_DARWIN:
517 return generic_xattr_parse_streams(jcr);
522 #elif defined(HAVE_FREEBSD_OS)
523 static bool freebsd_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
525 return generic_xattr_build_streams(jcr, ff_pkt, STREAM_XATTR_FREEBSD);
528 static bool freebsd_parse_xattr_stream(JCR *jcr, int stream)
531 case STREAM_XATTR_FREEBSD:
532 return generic_xattr_parse_streams(jcr);
537 #elif defined(HAVE_LINUX_OS)
538 static bool linux_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
540 return generic_xattr_build_streams(jcr, ff_pkt, STREAM_XATTR_LINUX);
543 static bool linux_parse_xattr_stream(JCR *jcr, int stream)
546 case STREAM_XATTR_LINUX:
547 return generic_xattr_parse_streams(jcr);
552 #elif defined(HAVE_NETBSD_OS)
553 static bool netbsd_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
555 return generic_xattr_build_streams(jcr, ff_pkt, STREAM_XATTR_NETBSD);
558 static bool netbsd_parse_xattr_stream(JCR *jcr, int stream)
561 case STREAM_XATTR_NETBSD:
562 return generic_xattr_parse_streams(jcr);
568 #elif defined(HAVE_SUN_OS)
570 static bool solaris_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
575 static bool solaris_parse_xattr_stream(JCR *jcr, int stream)
578 case STREAM_XATTR_SOLARIS:
587 bool build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
589 #if defined(HAVE_SUN_OS)
590 return solaris_build_xattr_streams(jcr, ff_pkt);
591 #elif defined(HAVE_DARWIN_OS)
592 return darwin_build_xattr_streams(jcr, ff_pkt);
593 #elif defined(HAVE_FREEBSD_OS)
594 return freebsd_build_xattr_streams(jcr, ff_pkt);
595 #elif defined(HAVE_LINUX_OS)
596 return linux_build_xattr_streams(jcr, ff_pkt);
597 #elif defined(HAVE_NETBSD_OS)
598 return netbsd_build_xattr_streams(jcr, ff_pkt);
602 bool parse_xattr_stream(JCR *jcr, int stream)
605 * Based on the stream being passed in dispatch to the right function
606 * for parsing and restoring a specific xattr. The platform determines
607 * which streams are recognized and parsed and which are handled by
608 * the default case and ignored. As only one of the platform defines
609 * is true per compile we never end up with duplicate switch values.
612 #if defined(HAVE_SUN_OS)
613 case STREAM_XATTR_SOLARIS:
614 return solaris_parse_xattr_stream(jcr, stream);
615 #elif defined(HAVE_DARWIN_OS)
616 case STREAM_XATTR_DARWIN:
617 return darwin_parse_xattr_stream(jcr, stream);
618 #elif defined(HAVE_FREEBSD_OS)
619 case STREAM_XATTR_FREEBSD:
620 return freebsd_parse_xattr_stream(jcr, stream);
621 #elif defined(HAVE_LINUX_OS)
622 case STREAM_XATTR_LINUX:
623 return linux_parse_xattr_stream(jcr, stream);
624 #elif defined(HAVE_NETBSD_OS)
625 case STREAM_XATTR_NETBSD:
626 return netbsd_parse_xattr_stream(jcr, stream);
630 * Issue a warning and discard the message. But pretend the restore was ok.
632 Qmsg2(jcr, M_WARNING, 0,
633 _("Can't restore Extended Attributes of %s - incompatible xattr stream encountered - %d\n"),
634 jcr->last_fname, stream);
636 } /* end switch (stream) */