2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2015 Kern Sibbald
5 Copyright (C) 2008-2014 Free Software Foundation Europe e.V.
7 The original author of Bacula is Kern Sibbald, with contributions
8 from many others, a complete list can be found in the file AUTHORS.
10 You may use this file and others of this release according to the
11 license defined in the LICENSE file, which includes the Affero General
12 Public License, v3.0 ("AGPLv3") and some additional permissions and
13 terms pursuant to its AGPLv3 Section 7.
15 This notice must be preserved when any source code is
16 conveyed and/or propagated.
18 Bacula(R) is a registered trademark of Kern Sibbald.
21 * Functions to handle Extended Attributes for bacula.
23 * Extended Attributes are so OS specific we only restore Extended Attributes if
24 * they were saved using a filed on the same platform.
26 * Currently we support the following OSes:
27 * - AIX (Extended Attributes)
28 * - Darwin (Extended Attributes)
29 * - FreeBSD (Extended Attributes)
30 * - GNU HURD (Extended Attributes)
31 * - IRIX (Extended Attributes)
32 * - Linux (Extended Attributes)
33 * - NetBSD (Extended Attributes)
34 * - OpenBSD (Extended Attributes)
35 * (As it seems either they never implemented xattr or they are removed
36 * the support as it stated it was in version 3.1 but the current syscall
37 * tabled shows the extattr_ functions are not implemented. So as such we
38 * might eventually support xattr on OpenBSD when they implemented them using
39 * the same interface as FreeBSD and NetBSD.
40 * - Solaris (Extended Attributes and Extensible Attributes)
41 * - Tru64 (Extended Attributes)
43 * Written by Marco van Wieringen, November 2008
44 * Major overhaul January 2012 + June 2012
45 * Simplfied by Kern Sibbald, June 2015
53 * Entry points when compiled without support for XATTRs or on an unsupported platform.
55 bool backup_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
57 Jmsg(jcr, M_FATAL, 0, "XATTR backup requested but not configured in Bacula.\n");
61 bxattr_rtn_code restore_xattr_streams(JCR *jcr, int stream, char *content,
62 uint32_t content_length)
64 return bxattr_rtn_fatal;
68 * Send a XATTR stream to the SD.
70 static bxattr_rtn_code send_xattr_stream(JCR *jcr, int stream)
72 BSOCK *sd = jcr->store_bsock;
75 #ifdef FD_NO_SEND_TEST
82 if (jcr->xattr_ctx->content_length <= 0) {
89 if (!sd->fsend("%ld %d 0", jcr->JobFiles, stream)) {
90 Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
92 return bxattr_rtn_fatal;
96 * Send the buffer to the storage deamon
98 Dmsg1(400, "Backing up XATTR <%s>\n", jcr->xattr_ctx->content);
100 sd->msg = jcr->xattr_ctx->content;
101 sd->msglen = jcr->xattr_ctx->content_length;
105 Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
107 return bxattr_rtn_fatal;
110 jcr->JobBytes += sd->msglen;
112 if (!sd->signal(BNET_EOD)) {
113 Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
115 return bxattr_rtn_fatal;
117 Dmsg1(200, "XATTR of file: %s successfully backed up!\n", jcr->last_fname);
118 return bxattr_rtn_ok;
122 * First some generic functions for OSes that use the same xattr encoding scheme.
123 * Currently for all OSes except for Solaris.
126 static void xattr_drop_internal_table(alist *xattr_value_list)
128 xattr_t *current_xattr;
130 if (!xattr_value_list) {
133 /* Walk the list of xattrs and free allocated memory. */
134 foreach_alist(current_xattr, xattr_value_list) {
135 if (current_xattr->magic != XATTR_MAGIC) {
138 if (current_xattr->name) {
139 free(current_xattr->name);
141 if (current_xattr->value && current_xattr->value_length > 0) {
142 free(current_xattr->value);
146 delete xattr_value_list;
150 * The xattr stream for OSX, FreeBSD, Linux and NetBSD is a serialized stream of bytes
151 * which encodes one or more xattr_t structures.
153 * The Serialized stream consists of the following elements:
154 * magic - A magic string which makes it easy to detect any binary incompatabilites
155 * name_length - The length of the following xattr name
156 * name - The name of the extended attribute
157 * value_length - The length of the following xattr data
158 * value - The actual content of the extended attribute
160 * This is repeated 1 or more times.
163 static uint32_t serialize_xattr_stream(JCR *jcr, uint32_t expected_serialize_len,
164 alist *xattr_value_list)
166 xattr_t *current_xattr;
170 * Make sure the serialized stream fits in the poolmem buffer.
171 * We allocate some more to be sure the stream is gonna fit.
173 jcr->xattr_ctx->content =
174 check_pool_memory_size(jcr->xattr_ctx->content, expected_serialize_len + 10);
175 ser_begin(jcr->xattr_ctx->content, expected_serialize_len + 10);
178 * Walk the list of xattrs and serialize the data.
180 foreach_alist(current_xattr, xattr_value_list) {
181 if (current_xattr->magic != XATTR_MAGIC) {
182 continue; /* Don't write invalid xattr */
185 ser_uint32(current_xattr->magic);
186 ser_uint32(current_xattr->name_length);
187 ser_bytes(current_xattr->name, current_xattr->name_length);
189 ser_uint32(current_xattr->value_length);
190 if (current_xattr->value_length > 0 && current_xattr->value) {
191 ser_bytes(current_xattr->value, current_xattr->value_length);
192 Dmsg3(100, "Backup xattr named %s, value %*s\n",
193 current_xattr->name, current_xattr->value, current_xattr->value);
195 Dmsg1(100, "Backup empty xattr named %s\n", current_xattr->name);
199 ser_end(jcr->xattr_ctx->content, expected_serialize_len + 10);
200 jcr->xattr_ctx->content_length = ser_length(jcr->xattr_ctx->content);
201 return jcr->xattr_ctx->content_length;
204 static bxattr_rtn_code unserialize_xattr_stream(JCR *jcr,
206 uint32_t content_length,
207 alist *xattr_value_list)
210 xattr_t *current_xattr;
213 * Restore the stream and call restore_xattr_on_file for each extended attribute.
215 * Start unserializing the data. We keep on looping while we have not
216 * unserialized all bytes in the stream.
218 unser_begin(content, content_length);
219 while (unser_length(content) < content_length) {
221 * First make sure the magic is present. This way we can easily catch corruption.
222 * Any missing MAGIC is fatal we do NOT try to continue.
224 current_xattr = (xattr_t *)malloc(sizeof(xattr_t));
225 unser_uint32(current_xattr->magic);
226 if (current_xattr->magic != XATTR_MAGIC) {
227 Mmsg1(jcr->errmsg, _("Invalid xattr stream, no XATTR_MAGIC on file \"%s\"\n"),
229 Dmsg1(100, "%s", jcr->errmsg);
231 return bxattr_rtn_error;
235 * Decode the valuepair. First decode the length of the name.
237 unser_uint32(current_xattr->name_length);
238 if (current_xattr->name_length == 0) {
239 Mmsg1(jcr->errmsg, _("Invalid xattr stream, xattr name length <= 0 on file \"%s\"\n"),
241 Dmsg1(100, "%s", jcr->errmsg);
243 return bxattr_rtn_error;
247 * Allocate room for the name and decode its content.
249 current_xattr->name = (char *)malloc(current_xattr->name_length + 1);
250 unser_bytes(current_xattr->name, current_xattr->name_length);
253 * The xattr_name needs to be null terminated.
255 current_xattr->name[current_xattr->name_length] = '\0';
258 * Decode the value length.
260 unser_uint32(current_xattr->value_length);
262 if (current_xattr->value_length > 0) {
264 * Allocate room for the value and decode its content.
266 current_xattr->value = (char *)malloc(current_xattr->value_length);
267 unser_bytes(current_xattr->value, current_xattr->value_length);
269 Dmsg3(100, "Restoring xattr named %s, value %*s\n",
270 current_xattr->name, current_xattr->value, current_xattr->value);
272 current_xattr->value = NULL;
273 Dmsg1(100, "Restoring empty xattr named %s\n", current_xattr->name);
276 xattr_value_list->append(current_xattr);
279 unser_end(content, content_length);
280 return bxattr_rtn_ok;
285 * This is a supported OS, See what kind of interface we should use.
287 #if defined(HAVE_AIX_OS)
289 #if (!defined(HAVE_LISTEA) && !defined(HAVE_LLISTEA)) || \
290 (!defined(HAVE_GETEA) && !defined(HAVE_LGETEA)) || \
291 (!defined(HAVE_SETEA) && !defined(HAVE_LSETEA))
292 #error "Missing full support for the Extended Attributes (EA) functions."
298 #error "Missing sys/ea.h header file"
302 * Define the supported XATTR streams for this OS
304 static int os_default_xattr_streams[1] = {
309 * Fallback to the non l-functions when those are not available.
311 #if defined(HAVE_GETEA) && !defined(HAVE_LGETEA)
314 #if defined(HAVE_SETEA) && !defined(HAVE_LSETEA)
317 #if defined(HAVE_LISTEA) && !defined(HAVE_LLISTEA)
318 #define llistea listea
321 static bxattr_rtn_code aix_xattr_build_streams(JCR *jcr, FF_PKT *ff_pkt)
325 char *xattr_list = NULL;
326 int cnt, xattr_count = 0;
327 uint32_t name_length;
328 int32_t xattr_list_len, xattr_value_len;
329 uint32_t expected_serialize_len = 0;
330 xattr_t *current_xattr;
331 alist *xattr_value_list = NULL;
332 bxattr_rtn_code retval = bxattr_rtn_error;
335 * First get the length of the available list with extended attributes.
337 xattr_list_len = llistea(jcr->last_fname, NULL, 0);
338 if (xattr_list_len < 0) {
340 if (errno == ENOENT || errno == EFORMAT) {
341 retval = bxattr_rtn_ok;
342 } else if (errno == ENOTSUP) {
344 * If the filesystem reports it doesn't support XATTRs we clear the
345 * BXATTR_FLAG_SAVE_NATIVE flag so we skip XATTR saves on all other files
346 * on the same filesystem. The BXATTR_FLAG_SAVE_NATIVE flags gets sets again
347 * when we change from one filesystem to an other.
349 jcr->xattr_ctx->flags &= ~BXATTR_FLAG_SAVE_NATIVE;
350 retval = bxattr_rtn_ok;
352 Mmsg2(jcr->errmsg, _("XATTR llistea error on file \"%s\": ERR=%s\n"),
353 jcr->last_fname, be.bstrerror());
354 Dmsg1(100, "%s", jcr->errmsg);
357 } else if (xattr_list_len == 0) {
358 retval = bxattr_rtn_ok;
363 * Allocate room for the extented attribute list.
365 xattr_list = (char *)malloc(xattr_list_len + 1);
366 memset(xattr_list, 0, xattr_list_len + 1);
369 * Get the actual list of extended attributes names for a file.
371 xattr_list_len = llistea(jcr->last_fname, xattr_list, xattr_list_len);
372 if (xattr_list_len < 0) {
374 if (errno == ENOENT || errno == EFORMAT) {
375 retval = bxattr_rtn_ok;
377 Mmsg2(jcr->errmsg, _("XATTR llistea error on file \"%s\": ERR=%s\n"),
378 jcr->last_fname, be.bstrerror());
379 Dmsg1(100, "%s", jcr->errmsg);
383 xattr_list[xattr_list_len] = '\0';
386 * Walk the list of extended attributes names and retrieve the data.
387 * We already count the bytes needed for serializing the stream later on.
389 for (bp = xattr_list; (bp - xattr_list) + 1 < xattr_list_len;
390 bp = strchr(bp, '\0') + 1) {
394 * We want to skip certain xattrs which start with a 0xF8 character on AIX.
400 name_length = strlen(bp);
401 if (skip_xattr || name_length == 0) {
402 Dmsg1(100, "Skipping xattr named %s\n", bp);
407 * First see how long the value is for the extended attribute.
409 xattr_value_len = lgetea(jcr->last_fname, bp, NULL, 0);
410 if (xattr_value_len < 0) {
412 if (errno == ENOENT || errno == EFORMAT) {
413 retval = bxattr_rtn_ok;
415 Mmsg2(jcr->errmsg, _("XATTR lgetea error on file \"%s\": ERR=%s\n"),
416 jcr->last_fname, be.bstrerror());
417 Dmsg1(100, "%s", jcr->errmsg);
423 * Each xattr valuepair starts with a magic so we can restore it easier.
425 current_xattr = (xattr_t *)malloc(sizeof(xattr_t));
426 memset(current_xattr, 0, sizeof(xattr_t));
427 current_xattr->magic = XATTR_MAGIC;
428 expected_serialize_len += sizeof(current_xattr->magic);
431 * Allocate space for storing the name.
433 current_xattr->name_length = name_length;
434 current_xattr->name = (char *)malloc(current_xattr->name_length);
435 memcpy(current_xattr->name, bp, current_xattr->name_length);
437 expected_serialize_len += sizeof(current_xattr->name_length) +
438 current_xattr->name_length;
440 if (xattr_value_len == 0) {
441 current_xattr->value = NULL;
442 current_xattr->value_length = 0;
443 expected_serialize_len += sizeof(current_xattr->value_length);
446 * Allocate space for storing the value.
448 current_xattr->value = (char *)malloc(xattr_value_len);
449 memset(current_xattr->value, 0, xattr_value_len);
451 xattr_value_len = lgetea(jcr->last_fname, bp, current_xattr->value, xattr_value_len);
452 if (xattr_value_len < 0) {
454 if (errno == ENOENT || errno == EFORMAT) {
455 retval = bxattr_rtn_ok;
457 Mmsg2(jcr->errmsg, _("XATTR lgetea error on file \"%s\": ERR=%s\n"),
458 jcr->last_fname, be.bstrerror());
459 Dmsg1(100, "%s", jcr->errmsg);
463 * Default failure path out when retrieval of attr fails.
465 free(current_xattr->value);
466 free(current_xattr->name);
471 * Store the actual length of the value.
473 current_xattr->value_length = xattr_value_len;
474 expected_serialize_len += sizeof(current_xattr->value_length) +
475 current_xattr->value_length;
478 if (xattr_value_list == NULL) {
479 xattr_value_list = New(alist(10, not_owned_by_alist));
482 xattr_value_list->append(current_xattr);
486 * Protect ourself against things getting out of hand.
488 if (expected_serialize_len >= MAX_XATTR_LENGTH) {
490 _("Xattr stream on file \"%s\" exceeds maximum size of %d bytes\n"),
491 jcr->last_fname, MAX_XATTR_LENGTH);
497 xattr_list = (char *)NULL;
500 * If we found any xattr send them to the SD.
502 if (xattr_count > 0) {
503 /* Serialize the datastream. */
504 if (serialize_xattr_stream(jcr, expected_serialize_len,
505 xattr_value_list) < expected_serialize_len) {
506 Mmsg1(jcr->errmsg, _("Failed to serialize extended attributes on file \"%s\"\n"),
508 Dmsg1(100, "%s", jcr->errmsg);
513 * Send the datastream to the SD.
515 retval = send_xattr_stream(jcr, os_default_xattr_streams[0]);
517 retval = bxattr_rtn_ok;
521 if (xattr_list != NULL) {
524 if (xattr_value_list != NULL) {
525 xattr_drop_internal_table(xattr_value_list);
531 static bxattr_rtn_code aix_restore_xattr_streams(JCR *jcr, int stream, char *content,
532 uint32_t content_length)
534 xattr_t *current_xattr;
535 alist *xattr_value_list;
536 bxattr_rtn_code retval = bxattr_rtn_error;
538 xattr_value_list = New(alist(10, not_owned_by_alist));
540 if (unserialize_xattr_stream(jcr, content, content_length,
541 xattr_value_list) != bxattr_rtn_ok) {
545 foreach_alist(current_xattr, xattr_value_list) {
546 if (lsetea(jcr->last_fname, current_xattr->name, current_xattr->value,
547 current_xattr->value_length, 0) != 0) {
555 * If the filesystem reports it doesn't support XATTRs we clear
556 * the BXATTR_FLAG_RESTORE_NATIVE flag so we skip XATTR restores
557 * on all other files on the same filesystem. The
558 * BXATTR_FLAG_RESTORE_NATIVE flags gets sets again when we
559 * change from one filesystem to an other.
561 jcr->xattr_ctx->flags &= ~BXATTR_FLAG_RESTORE_NATIVE;
562 /* Failback wanted */
564 MmsgD2(100, jcr->errmsg,
565 _("XATTR lsetea error on file \"%s\": ERR=%s\n"),
566 jcr->last_fname, be.bstrerror());
572 retval = bxattr_rtn_ok;
575 xattr_drop_internal_table(xattr_value_list);
581 * Function pointers to the build and restore function to use for these xattrs.
583 static bxattr_rtn_code (*os_backup_xattr_streams)
584 (JCR *jcr, FF_PKT *ff_pkt) =
585 aix_xattr_build_streams;
586 static bxattr_rtn_code (*os_restore_xattr_streams)
587 (JCR *jcr, int stream, char *content, uint32_t content_length) =
588 aix_restore_xattr_streams;
590 #elif defined(HAVE_IRIX_OS)
592 #include <sys/attributes.h>
595 * Define the supported XATTR streams for this OS
597 static int os_default_xattr_streams[1] = {
600 static const char *xattr_acl_skiplist[1] = {
603 static const char *xattr_skiplist[1] = {
607 struct xattr_naming_space {
612 static xattr_naming_space xattr_naming_spaces[] = {
618 ATTR_ROOT | ATTR_DONTFOLLOW
625 static bxattr_rtn_code irix_xattr_build_streams(JCR *jcr, FF_PKT *ff_pkt)
628 int cnt, length, xattr_count = 0;
629 attrlist_cursor_t cursor;
630 attrlist_t *attrlist;
631 attrlist_ent_t *attrlist_ent;
632 xattr_t *current_xattr;
633 alist *xattr_value_list = NULL;
634 uint32_t expected_serialize_len = 0;
635 bxattr_rtn_code retval = bxattr_rtn_error;
636 POOLMEM *xattrbuf = get_memory(ATTR_MAX_VALUELEN);
638 for (cnt = 0; xattr_naming_spaces[cnt].name != NULL; cnt++) {
639 memset(&cursor, 0, sizeof(attrlist_cursor_t));
641 if (attr_list(jcr->last_fname, xattrbuf, ATTR_MAX_VALUELEN,
642 xattr_naming_spaces[cnt].flags, &cursor) != 0) {
646 retval = bxattr_rtn_ok;
649 Mmsg2(jcr->errmsg, _("XATTR attr_list error on file \"%s\": ERR=%s\n"),
650 jcr->last_fname, be.bstrerror());
651 Dmsg1(100, "%s", jcr->errmsg);
656 attrlist = (attrlist_t *)xattrbuf;
659 * Walk the available attributes.
661 for (cnt = 0; cnt < attrlist->al_count; cnt++) {
662 attrlist_ent = ATTR_ENTRY(xattrbuf, cnt);
665 * First determine if we can retrieve the xattr and how big it really is.
667 length = sizeof(dummy);
668 if (attr_get(jcr->last_fname, attrlist_ent->a_name, dummy,
669 &length, xattr_naming_spaces[cnt].flags) != 0) {
674 retval = bxattr_rtn_ok;
678 * Size of the xattr is bigger then the 32 bytes dummy which is
679 * likely. As length now contains its actual length we can allocate
680 * a properly size buffer for the real retrieval.
684 Mmsg2(jcr->errmsg, _("XATTR attr_list error on file \"%s\": ERR=%s\n"),
685 jcr->last_fname, be.bstrerror());
686 Dmsg1(100, "%s", jcr->errmsg);
692 * Each xattr valuepair starts with a magic so we can restore it easier.
694 current_xattr = (xattr_t *)malloc(sizeof(xattr_t));
695 memset(current_xattr, 0, sizeof(xattr_t));
696 current_xattr->magic = XATTR_MAGIC;
697 expected_serialize_len += sizeof(current_xattr->magic);
700 * Allocate space for storing the name.
701 * We store the name as <naming_space_name><xattr_name>
703 current_xattr->name_length = strlen(xattr_naming_spaces[cnt].name) +
704 strlen(attrlist_ent->a_name) + 1;
705 current_xattr->name = (char *)malloc(current_xattr->name_length);
706 bsnprintf(current_xattr->name, current_xattr->name_length, "%s%s",
707 xattr_naming_spaces[cnt].name, attrlist_ent->a_name);
709 expected_serialize_len += sizeof(current_xattr->name_length) +
710 current_xattr->name_length;
712 current_xattr->value_length = length;
713 current_xattr->value = (char *)malloc(current_xattr->value_length);
716 * Retrieve the actual value of the xattr.
718 if (attr_get(jcr->last_fname, attrlist_ent->a_name, current_xattr->value,
719 &length, xattr_naming_spaces[cnt].flags) != 0) {
725 retval = bxattr_rtn_ok;
729 * The buffer for the xattr isn't big enough. the value of
730 * current_xattr->value_length is updated with the actual size
731 * of the xattr. So we free the old buffer and create a new one
732 * and try again. Normally this cannot happen as we size the
733 * buffer using a call to attr_get before but in case of an
734 * race condition it might happen.
736 free(current_xattr->value);
737 current_xattr->value = (char *)malloc(length);
738 if (attr_get(jcr->last_fname, attrlist_ent->a_name, current_xattr->value,
739 &length, xattr_naming_spaces[cnt].flags) != 0) {
743 retval = bxattr_rtn_ok;
747 _("attr_list error on file \"%s\": ERR=%s\n"),
748 jcr->last_fname, be.bstrerror(errno));
749 Dmsg2(100, "attr_list error file=%s ERR=%s\n",
750 jcr->last_fname, be.bstrerror());
758 Mmsg2(jcr->errmsg, _("XATTR attr_list error on file \"%s\": ERR=%s\n"),
759 jcr->last_fname, be.bstrerror());
760 Dmsg1(100, "%s", jcr->errmsg);
765 * Default failure path out when retrieval of attr fails.
767 free(current_xattr->value);
768 free(current_xattr->name);
774 current_xattr->value_length = length;
775 expected_serialize_len += sizeof(current_xattr->value_length) +
776 current_xattr->value_length;
778 if (xattr_value_list == NULL) {
779 xattr_value_list = New(alist(10, not_owned_by_alist));
782 xattr_value_list->append(current_xattr);
786 * Protect ourself against things getting out of hand.
788 if (expected_serialize_len >= MAX_XATTR_LENGTH) {
790 _("XATTR stream on file \"%s\" exceeds maximum size of %d bytes\n"),
791 jcr->last_fname, MAX_XATTR_LENGTH);
797 * See if there are more attributes available for a next run of attr_list.
799 if (attrlist->al_more == 0) {
806 * If we found any xattr send them to the SD.
808 if (xattr_count > 0) {
809 /* Serialize the XATTR */
810 if (serialize_xattr_stream(jcr, expected_serialize_len,
811 xattr_value_list) < expected_serialize_len) {
812 Mmsg1(jcr->errmsg, _("Failed to serialize extended attributes on file \"%s\"\n"),
814 Dmsg1(100, "%s", jcr->errmsg);
818 /* Send the XATTR to the SD. */
819 retval = send_xattr_stream(jcr, os_default_xattr_streams[0]);
821 retval = bxattr_rtn_ok;
825 free_pool_memory(xattrbuf);
827 if (xattr_value_list != NULL) {
828 xattr_drop_internal_table(xattr_value_list);
834 static bxattr_rtn_code irix_restore_xattr_streams(JCR *jcr,
837 uint32_t content_length)
840 int cnt, cmp_size, name_space_index, flags;
841 xattr_t *current_xattr;
842 alist *xattr_value_list;
843 bxattr_rtn_code retval = bxattr_rtn_error;
845 xattr_value_list = New(alist(10, not_owned_by_alist));
847 if (unserialize_xattr_stream(jcr,
850 xattr_value_list) != bxattr_rtn_ok) {
854 foreach_alist(current_xattr, xattr_value_list) {
856 * See to what namingspace this xattr belongs to.
858 name_space_index = 0;
859 for (cnt = 0; xattr_naming_spaces[cnt].name != NULL; cnt++) {
860 cmp_size = strlen(xattr_naming_spaces[cnt].name);
861 if (!strncasecmp(current_xattr->name,
862 xattr_naming_spaces[cnt].name,
864 name_space_index = cnt;
870 * If we got a xattr that doesn't belong to an valid namespace complain.
872 if (name_space_index == 0) {
874 _("Received invalid xattr named %s on file \"%s\"\n"),
875 current_xattr->name, jcr->last_fname);
876 Dmsg1(100, "%s", jcr->errmsg);
881 * Restore the xattr first try to create the attribute from scratch.
883 flags = xattr_naming_spaces[name_space_index].flags | ATTR_CREATE;
884 bp = strchr(current_xattr->name, '.');
885 if (attr_set(jcr->last_fname, ++bp, current_xattr->value,
886 current_xattr->value_length, flags) != 0) {
891 retval = bxattr_rtn_ok;
895 * The xattr already exists we need to replace it.
897 flags = xattr_naming_spaces[name_space_index].flags | ATTR_REPLACE;
898 if (attr_set(jcr->last_fname, bp, current_xattr->value,
899 current_xattr->value_length, flags) != 0) {
902 retval = bxattr_rtn_ok;
905 Mmsg2(jcr->errmsg, _("attr_set error on file \"%s\": ERR=%s\n"),
906 jcr->last_fname, be.bstrerror(errno));
907 Dmsg1(100, "%s", jcr->errmsg);
913 Mmsg2(jcr->errmsg, _("attr_set error on file \"%s\": ERR=%s\n"),
914 jcr->last_fname, be.bstrerror());
915 Dmsg1(100, "%s", jcr->errmsg);
921 retval = bxattr_rtn_ok;
924 xattr_drop_internal_table(xattr_value_list);
930 * Function pointers to the build and restore function to use for these xattrs.
932 static bxattr_rtn_code (*os_backup_xattr_streams)
933 (JCR *jcr, FF_PKT *ff_pkt) =
934 irix_xattr_build_streams;
935 static bxattr_rtn_code (*os_restore_xattr_streams)
936 (JCR *jcr, int stream, char *content, uint32_t content_length) =
937 irix_restore_xattr_streams;
939 #elif defined(HAVE_DARWIN_OS) || \
940 defined(HAVE_LINUX_OS) || \
941 defined(HAVE_HURD_OS)
943 #if (!defined(HAVE_LISTXATTR) && !defined(HAVE_LLISTXATTR)) || \
944 (!defined(HAVE_GETXATTR) && !defined(HAVE_LGETXATTR)) || \
945 (!defined(HAVE_SETXATTR) && !defined(HAVE_LSETXATTR))
946 #error "Missing full support for the XATTR functions."
949 #ifdef HAVE_SYS_XATTR_H
950 #include <sys/xattr.h>
952 #error "Missing sys/xattr.h header file"
956 * Define the supported XATTR streams for this OS
958 #if defined(HAVE_DARWIN_OS)
959 static int os_default_xattr_streams[1] = {
962 static const char *xattr_acl_skiplist[2] = {
963 "com.apple.system.Security",
966 static const char *xattr_skiplist[3] = {
967 "com.apple.system.extendedsecurity",
968 "com.apple.ResourceFork",
971 #elif defined(HAVE_LINUX_OS)
972 static int os_default_xattr_streams[1] = {
975 static const char *xattr_acl_skiplist[3] = {
976 "system.posix_acl_access",
977 "system.posix_acl_default",
980 static const char *xattr_skiplist[1] = {
983 #elif defined(HAVE_HURD_OS)
984 static int os_default_xattr_streams[1] = {
987 static const char *xattr_acl_skiplist[1] = {
990 static const char *xattr_skiplist[1] = {
996 * OSX doesn't have llistxattr, lgetxattr and lsetxattr but has
997 * listxattr, getxattr and setxattr with an extra options argument
998 * which mimics the l variants of the functions when we specify
999 * XATTR_NOFOLLOW as the options value.
1001 #if defined(HAVE_DARWIN_OS)
1002 #define llistxattr(path, list, size) \
1003 listxattr((path), (list), (size), XATTR_NOFOLLOW)
1004 #define lgetxattr(path, name, value, size) \
1005 getxattr((path), (name), (value), (size), 0, XATTR_NOFOLLOW)
1006 #define lsetxattr(path, name, value, size, flags) \
1007 setxattr((path), (name), (value), (size), (flags), XATTR_NOFOLLOW)
1010 * Fallback to the non l-functions when those are not available.
1012 #if defined(HAVE_GETXATTR) && !defined(HAVE_LGETXATTR)
1013 #define lgetxattr getxattr
1015 #if defined(HAVE_SETXATTR) && !defined(HAVE_LSETXATTR)
1016 #define lsetxattr setxattr
1018 #if defined(HAVE_LISTXATTR) && !defined(HAVE_LLISTXATTR)
1019 #define llistxattr listxattr
1023 static bxattr_rtn_code generic_xattr_build_streams(JCR *jcr, FF_PKT *ff_pkt)
1027 char *xattr_list = NULL;
1028 int cnt, xattr_count = 0;
1029 uint32_t name_length;
1030 int32_t xattr_list_len,
1032 uint32_t expected_serialize_len = 0;
1033 xattr_t *current_xattr;
1034 alist *xattr_value_list = NULL;
1035 bxattr_rtn_code retval = bxattr_rtn_error;
1038 * First get the length of the available list with extended attributes.
1040 xattr_list_len = llistxattr(jcr->last_fname, NULL, 0);
1041 switch (xattr_list_len) {
1047 retval = bxattr_rtn_ok;
1049 case BXATTR_ENOTSUP:
1051 * If the filesystem reports it doesn't support XATTRs we clear
1052 * the BXATTR_FLAG_RESTORE_NATIVE flag so we skip XATTR restores
1053 * on all other files on the same filesystem. The
1054 * BXATTR_FLAG_RESTORE_NATIVE flags gets sets again when we
1055 * change from one filesystem to an other.
1057 jcr->xattr_ctx->flags &= ~BXATTR_FLAG_SAVE_NATIVE;
1058 retval = bxattr_rtn_ok;
1061 Mmsg2(jcr->errmsg, _("llistxattr error on file \"%s\": ERR=%s\n"),
1062 jcr->last_fname, be.bstrerror());
1063 Dmsg1(100, "%s", jcr->errmsg);
1069 retval = bxattr_rtn_ok;
1076 * Allocate room for the extented attribute list.
1078 xattr_list = (char *)malloc(xattr_list_len + 1);
1079 memset(xattr_list, 0, xattr_list_len + 1);
1082 * Get the actual list of extended attributes names for a file.
1084 xattr_list_len = llistxattr(jcr->last_fname, xattr_list, xattr_list_len);
1085 if (xattr_list_len < 0) {
1087 if (errno == ENOENT) {
1088 retval = bxattr_rtn_ok;
1090 Mmsg2(jcr->errmsg, _("llistxattr error on file \"%s\": ERR=%s\n"),
1091 jcr->last_fname, be.bstrerror());
1092 Dmsg1(100, "%s", jcr->errmsg);
1096 xattr_list[xattr_list_len] = '\0';
1099 * Walk the list of extended attributes names and retrieve the data.
1100 * We already count the bytes needed for serializing the stream later on.
1102 for (bp = xattr_list;
1103 (bp - xattr_list) + 1 < xattr_list_len;
1104 bp = strchr(bp, '\0') + 1) {
1108 * On some OSes you also get the acls in the extented attribute list.
1109 * So we check if we are already backing up acls and if we do we
1110 * don't store the extended attribute with the same info.
1112 if (ff_pkt->flags & FO_ACL) {
1113 for (cnt = 0; xattr_acl_skiplist[cnt] != NULL; cnt++) {
1114 if (bstrcmp(bp, xattr_acl_skiplist[cnt])) {
1122 * On some OSes we want to skip certain xattrs which are in the xattr_skiplist array.
1125 for (cnt = 0; xattr_skiplist[cnt] != NULL; cnt++) {
1126 if (bstrcmp(bp, xattr_skiplist[cnt])) {
1133 name_length = strlen(bp);
1134 if (skip_xattr || name_length == 0) {
1135 Dmsg1(100, "Skipping xattr named %s\n", bp);
1140 * First see how long the value is for the extended attribute.
1142 xattr_value_len = lgetxattr(jcr->last_fname, bp, NULL, 0);
1143 if (xattr_value_len < 0) {
1145 if (errno == ENOENT) {
1146 retval = bxattr_rtn_ok;
1148 Mmsg2(jcr->errmsg, _("lgetxattr error on file \"%s\": ERR=%s\n"),
1149 jcr->last_fname, be.bstrerror());
1150 Dmsg1(100, "%s", jcr->errmsg);
1156 * Each xattr valuepair starts with a magic so we can restore it easier.
1158 current_xattr = (xattr_t *)malloc(sizeof(xattr_t));
1159 current_xattr->magic = XATTR_MAGIC;
1160 current_xattr->value = NULL;
1161 expected_serialize_len += sizeof(current_xattr->magic);
1164 * Allocate space for storing the name.
1166 current_xattr->name_length = name_length;
1167 current_xattr->name = (char *)malloc(current_xattr->name_length);
1168 memcpy(current_xattr->name, bp, current_xattr->name_length);
1170 expected_serialize_len += sizeof(current_xattr->name_length) + current_xattr->name_length;
1172 switch (xattr_value_len) {
1174 current_xattr->value = NULL;
1175 current_xattr->value_length = 0;
1176 expected_serialize_len += sizeof(current_xattr->value_length);
1180 * Allocate space for storing the value.
1182 current_xattr->value = (char *)malloc(xattr_value_len);
1183 memset(current_xattr->value, 0, xattr_value_len);
1185 xattr_value_len = lgetxattr(jcr->last_fname, bp, current_xattr->value, xattr_value_len);
1186 if (xattr_value_len < 0) {
1191 retval = bxattr_rtn_ok;
1194 Mmsg2(jcr->errmsg, _("lgetxattr error on file \"%s\": ERR=%s\n"),
1195 jcr->last_fname, be.bstrerror());
1196 Dmsg1(100, "%s", jcr->errmsg);
1201 * Default failure path out when retrieval of attr fails.
1203 free(current_xattr->value);
1204 free(current_xattr->name);
1205 free(current_xattr);
1210 * Store the actual length of the value.
1212 current_xattr->value_length = xattr_value_len;
1213 expected_serialize_len += sizeof(current_xattr->value_length) + current_xattr->value_length;
1217 if (xattr_value_list == NULL) {
1218 xattr_value_list = New(alist(10, not_owned_by_alist));
1221 xattr_value_list->append(current_xattr);
1225 * Protect ourself against things getting out of hand.
1227 if (expected_serialize_len >= MAX_XATTR_LENGTH) {
1229 _("Xattr stream on file \"%s\" exceeds maximum size of %d bytes\n"),
1230 jcr->last_fname, MAX_XATTR_LENGTH);
1236 xattr_list = (char *)NULL;
1239 * If we found any xattr send them to the SD.
1241 if (xattr_count > 0) {
1243 * Serialize the datastream.
1245 if (serialize_xattr_stream(jcr, expected_serialize_len,
1246 xattr_value_list) < expected_serialize_len) {
1247 Mmsg1(jcr->errmsg, _("Failed to serialize extended attributes on file \"%s\"\n"),
1249 Dmsg1(100, "%s", jcr->errmsg);
1254 * Send the datastream to the SD.
1256 retval = send_xattr_stream(jcr, os_default_xattr_streams[0]);
1258 retval = bxattr_rtn_ok;
1262 if (xattr_list != NULL) {
1265 if (xattr_value_list != NULL) {
1266 xattr_drop_internal_table(xattr_value_list);
1272 static bxattr_rtn_code generic_restore_xattr_streams(JCR *jcr, int stream,
1274 uint32_t content_length)
1276 xattr_t *current_xattr;
1277 alist *xattr_value_list;
1278 bxattr_rtn_code retval = bxattr_rtn_error;
1280 xattr_value_list = New(alist(10, not_owned_by_alist));
1282 if (unserialize_xattr_stream(jcr, content, content_length,
1283 xattr_value_list) != bxattr_rtn_ok) {
1287 foreach_alist(current_xattr, xattr_value_list) {
1288 if (lsetxattr(jcr->last_fname, current_xattr->name, current_xattr->value, current_xattr->value_length, 0) != 0) {
1290 if (errno == ENOENT) {
1292 } else if (errno == BXATTR_ENOTSUP) {
1294 * If the filesystem reports it doesn't support XATTRs we clear
1295 * the BXATTR_FLAG_RESTORE_NATIVE flag so we skip XATTR restores
1296 * on all other files on the same filesystem. The
1297 * BXATTR_FLAG_RESTORE_NATIVE flags gets sets again when we
1298 * change from one filesystem to an other.
1300 jcr->xattr_ctx->flags &= ~BXATTR_FLAG_RESTORE_NATIVE;
1302 MmsgD2(100, jcr->errmsg,
1303 _("lsetxattr error on file \"%s\": ERR=%s\n"),
1304 jcr->last_fname, be.bstrerror());
1309 retval = bxattr_rtn_ok;
1312 xattr_drop_internal_table(xattr_value_list);
1317 * Function pointers to the build and restore functions to use for these xattrs.
1319 static bxattr_rtn_code (*os_backup_xattr_streams)
1320 (JCR *jcr, FF_PKT *ff_pkt) =
1321 generic_xattr_build_streams;
1322 static bxattr_rtn_code (*os_restore_xattr_streams)
1323 (JCR *jcr, int stream, char *content, uint32_t content_length) =
1324 generic_restore_xattr_streams;
1326 #elif defined(HAVE_FREEBSD_OS) || \
1327 defined(HAVE_NETBSD_OS) || \
1328 defined(HAVE_OPENBSD_OS)
1330 #if (!defined(HAVE_EXTATTR_GET_LINK) && !defined(HAVE_EXTATTR_GET_FILE)) || \
1331 (!defined(HAVE_EXTATTR_SET_LINK) && !defined(HAVE_EXTATTR_SET_FILE)) || \
1332 (!defined(HAVE_EXTATTR_LIST_LINK) && !defined(HAVE_EXTATTR_LIST_FILE)) || \
1333 !defined(HAVE_EXTATTR_NAMESPACE_TO_STRING) || \
1334 !defined(HAVE_EXTATTR_STRING_TO_NAMESPACE)
1335 #error "Missing full support for the extattr functions."
1338 #ifdef HAVE_SYS_EXTATTR_H
1339 #include <sys/extattr.h>
1341 #error "Missing sys/extattr.h header file"
1344 #ifdef HAVE_LIBUTIL_H
1345 #include <libutil.h>
1348 #if !defined(HAVE_EXTATTR_GET_LINK) && defined(HAVE_EXTATTR_GET_FILE)
1349 #define extattr_get_link extattr_get_file
1351 #if !defined(HAVE_EXTATTR_SET_LINK) && defined(HAVE_EXTATTR_SET_FILE)
1352 #define extattr_set_link extattr_set_file
1354 #if !defined(HAVE_EXTATTR_LIST_LINK) && defined(HAVE_EXTATTR_LIST_FILE)
1355 #define extattr_list_link extattr_list_file
1358 #if defined(HAVE_FREEBSD_OS)
1359 static int os_default_xattr_streams[1] = {
1360 STREAM_XATTR_FREEBSD
1362 static int os_default_xattr_namespaces[2] = {
1363 EXTATTR_NAMESPACE_USER,
1364 EXTATTR_NAMESPACE_SYSTEM
1366 static const char *xattr_acl_skiplist[4] = {
1367 "system.posix1e.acl_access",
1368 "system.posix1e.acl_default",
1372 static const char *xattr_skiplist[1] = {
1375 #elif defined(HAVE_NETBSD_OS)
1376 static int os_default_xattr_streams[1] = {
1379 static int os_default_xattr_namespaces[2] = {
1380 EXTATTR_NAMESPACE_USER,
1381 EXTATTR_NAMESPACE_SYSTEM
1383 static const char *xattr_acl_skiplist[1] = {
1386 static const char *xattr_skiplist[1] = {
1389 #elif defined(HAVE_OPENBSD_OS)
1390 static int os_default_xattr_streams[1] = {
1391 STREAM_XATTR_OPENBSD
1393 static int os_default_xattr_namespaces[2] = {
1394 EXTATTR_NAMESPACE_USER,
1395 EXTATTR_NAMESPACE_SYSTEM
1397 static const char *xattr_acl_skiplist[1] = {
1400 static const char *xattr_skiplist[1] = {
1405 static bxattr_rtn_code bsd_backup_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
1408 char *xattr_list = NULL;
1409 int cnt, index, xattr_count = 0;
1410 int32_t xattr_list_len,
1412 uint32_t expected_serialize_len = 0;
1413 unsigned int namespace_index;
1415 char *current_attrnamespace = NULL;
1416 char current_attrname[XATTR_BUFSIZ], current_attrtuple[XATTR_BUFSIZ];
1417 xattr_t *current_xattr;
1418 alist *xattr_value_list = NULL;
1419 bxattr_rtn_code retval = bxattr_rtn_error;
1422 * Loop over all available xattr namespaces.
1424 for (namespace_index = 0;
1425 namespace_index < sizeof(os_default_xattr_namespaces) / sizeof(int);
1426 namespace_index++) {
1427 attrnamespace = os_default_xattr_namespaces[namespace_index];
1430 * First get the length of the available list with extended attributes.
1431 * If we get EPERM on system namespace, don't return error.
1432 * This is expected for normal users trying to archive the system
1433 * namespace on FreeBSD 6.2 and later. On NetBSD 3.1 and later,
1434 * they've decided to return EOPNOTSUPP instead.
1436 xattr_list_len = extattr_list_link(jcr->last_fname, attrnamespace, NULL, 0);
1437 switch (xattr_list_len) {
1443 retval = bxattr_rtn_ok;
1445 #if defined(EOPNOTSUPP)
1449 if (attrnamespace == EXTATTR_NAMESPACE_SYSTEM) {
1456 Mmsg2(jcr->errmsg, _("extattr_list_link error on file \"%s\": ERR=%s\n"),
1457 jcr->last_fname, be.bstrerror());
1458 Dmsg1(100, "%s", jcr->errmsg);
1470 * Allocate room for the extented attribute list.
1472 xattr_list = (char *)malloc(xattr_list_len + 1);
1473 memset(xattr_list, 0, xattr_list_len + 1);
1476 * Get the actual list of extended attributes names for a file.
1478 xattr_list_len = extattr_list_link(jcr->last_fname, attrnamespace,
1479 xattr_list, xattr_list_len);
1480 if (xattr_list_len < 0) {
1482 if (errno == ENOENT) {
1483 retval = bxattr_rtn_ok;
1485 Mmsg2(jcr->errmsg, _("extattr_list_link error on file \"%s\": ERR=%s\n"),
1486 jcr->last_fname, be.bstrerror());
1487 Dmsg1(100, "%s", jcr->errmsg);
1491 xattr_list[xattr_list_len] = '\0';
1494 * Convert the numeric attrnamespace into a string representation and make
1495 * a private copy of that string. The extattr_namespace_to_string functions
1496 * returns a strdupped string which we need to free.
1498 if (extattr_namespace_to_string(attrnamespace, ¤t_attrnamespace) != 0) {
1499 Mmsg2(jcr->errmsg, _("Failed to convert %d into namespace on file \"%s\"\n"),
1500 attrnamespace, jcr->last_fname);
1501 Dmsg1(100, "%s", jcr->errmsg);
1506 * Walk the list of extended attributes names and retrieve the data.
1507 * We already count the bytes needed for serializing the stream later on.
1509 for (index = 0; index < xattr_list_len; index += xattr_list[index] + 1) {
1513 * Print the current name into the buffer as its not null terminated
1514 * we need to use the length encoded in the string for copying only
1517 cnt = xattr_list[index];
1518 if (cnt > ((int)sizeof(current_attrname) - 1)) {
1519 cnt = ((int)sizeof(current_attrname) - 1);
1521 strncpy(current_attrname, xattr_list + (index + 1), cnt);
1522 current_attrname[cnt] = '\0';
1525 * First make a xattr tuple of the current namespace and the name of
1526 * the xattr. e.g. something like user.<attrname> or system.<attrname>
1528 bsnprintf(current_attrtuple, sizeof(current_attrtuple), "%s.%s",
1529 current_attrnamespace, current_attrname);
1532 * On some OSes you also get the acls in the extented attribute list.
1533 * So we check if we are already backing up acls and if we do we
1534 * don't store the extended attribute with the same info.
1536 if (ff_pkt->flags & FO_ACL) {
1537 for (cnt = 0; xattr_acl_skiplist[cnt] != NULL; cnt++) {
1538 if (bstrcmp(current_attrtuple, xattr_acl_skiplist[cnt])) {
1546 * On some OSes we want to skip certain xattrs which are in the
1547 * xattr_skiplist array.
1550 for (cnt = 0; xattr_skiplist[cnt] != NULL; cnt++) {
1551 if (bstrcmp(current_attrtuple, xattr_skiplist[cnt])) {
1559 Dmsg1(100, "Skipping xattr named %s\n", current_attrname);
1564 * First see how long the value is for the extended attribute.
1566 xattr_value_len = extattr_get_link(jcr->last_fname, attrnamespace,
1567 current_attrname, NULL, 0);
1568 switch (xattr_value_len) {
1574 retval = bxattr_rtn_ok;
1577 Mmsg2(jcr->errmsg, _("extattr_get_link error on file \"%s\": ERR=%s\n"),
1578 jcr->last_fname, be.bstrerror());
1579 Dmsg1(100, "%s", jcr->errmsg);
1589 * Each xattr valuepair starts with a magic so we can restore it easier.
1591 current_xattr = (xattr_t *)malloc(sizeof(xattr_t));
1592 memset(current_xattr, 0, sizeof(xattr_t));
1593 current_xattr->magic = XATTR_MAGIC;
1594 expected_serialize_len += sizeof(current_xattr->magic);
1597 * Allocate space for storing the name.
1599 current_xattr->name_length = strlen(current_attrtuple);
1600 current_xattr->name = (char *)malloc(current_xattr->name_length);
1601 memcpy(current_xattr->name, current_attrtuple, current_xattr->name_length);
1603 expected_serialize_len += sizeof(current_xattr->name_length) +
1604 current_xattr->name_length;
1606 switch (xattr_value_len) {
1608 current_xattr->value = NULL;
1609 current_xattr->value_length = 0;
1610 expected_serialize_len += sizeof(current_xattr->value_length);
1614 * Allocate space for storing the value.
1616 current_xattr->value = (char *)malloc(xattr_value_len);
1617 memset(current_xattr->value, 0, xattr_value_len);
1619 xattr_value_len = extattr_get_link(jcr->last_fname, attrnamespace,
1620 current_attrname, current_xattr->value,
1622 if (xattr_value_len < 0) {
1627 retval = bxattr_rtn_ok;
1630 Mmsg2(jcr->errmsg, _("extattr_get_link error on file \"%s\": ERR=%s\n"),
1631 jcr->last_fname, be.bstrerror());
1632 Dmsg1(100, "%s", jcr->errmsg);
1637 * Default failure path out when retrieval of attr fails.
1639 free(current_xattr->value);
1640 free(current_xattr->name);
1641 free(current_xattr);
1646 * Store the actual length of the value.
1648 current_xattr->value_length = xattr_value_len;
1649 expected_serialize_len += sizeof(current_xattr->value_length) +
1650 current_xattr->value_length;
1654 if (xattr_value_list == NULL) {
1655 xattr_value_list = New(alist(10, not_owned_by_alist));
1658 xattr_value_list->append(current_xattr);
1662 * Protect ourself against things getting out of hand.
1664 if (expected_serialize_len >= MAX_XATTR_LENGTH) {
1665 Mmsg2(jcr->errmsg, _("Xattr stream on file \"%s\" exceeds maximum size of %d bytes\n"),
1666 jcr->last_fname, MAX_XATTR_LENGTH);
1667 Dmsg1(100, "%s", jcr->errmsg);
1673 * Drop the local copy of the current_attrnamespace.
1675 actuallyfree(current_attrnamespace);
1676 current_attrnamespace = NULL;
1679 * We are done with this xattr list.
1682 xattr_list = (char *)NULL;
1686 * If we found any xattr send them to the SD.
1688 if (xattr_count > 0) {
1690 * Serialize the datastream.
1692 if (serialize_xattr_stream(jcr,
1693 expected_serialize_len,
1694 xattr_value_list) < expected_serialize_len) {
1695 Mmsg1(jcr->errmsg, _("Failed to serialize extended attributes on file \"%s\"\n"),
1697 Dmsg1(100, "%s", jcr->errmsg);
1702 * Send the datastream to the SD.
1704 retval = send_xattr_stream(jcr, os_default_xattr_streams[0]);
1706 retval = bxattr_rtn_ok;
1710 if (current_attrnamespace != NULL) {
1711 actuallyfree(current_attrnamespace);
1713 if (xattr_list != NULL) {
1716 if (xattr_value_list != NULL) {
1717 xattr_drop_internal_table(xattr_value_list);
1723 static bxattr_rtn_code bsd_restore_xattr_streams(JCR *jcr,
1726 uint32_t content_length)
1728 xattr_t *current_xattr;
1729 alist *xattr_value_list;
1730 int current_attrnamespace, cnt;
1731 char *attrnamespace, *attrname;
1732 bxattr_rtn_code retval = bxattr_rtn_error;
1734 xattr_value_list = New(alist(10, not_owned_by_alist));
1736 if (unserialize_xattr_stream(jcr,
1739 xattr_value_list) != bxattr_rtn_ok) {
1743 foreach_alist(current_xattr, xattr_value_list) {
1745 * Try splitting the xattr_name into a namespace and name part.
1746 * The splitting character is a .
1748 attrnamespace = current_xattr->name;
1749 if ((attrname = strchr(attrnamespace, '.')) == (char *)NULL) {
1750 Mmsg2(jcr->errmsg, _("Failed to split %s into namespace and name part on file \"%s\"\n"),
1751 current_xattr->name, jcr->last_fname);
1752 Dmsg1(100, "%s", jcr->errmsg);
1758 * Make sure the attrnamespace makes sense.
1760 if (extattr_string_to_namespace(attrnamespace, ¤t_attrnamespace) != 0) {
1761 Mmsg2(jcr->errmsg, _("Failed to convert %s into namespace on file \"%s\"\n"),
1762 attrnamespace, jcr->last_fname);
1763 Dmsg1(100, "%s", jcr->errmsg);
1768 * Try restoring the extended attribute.
1770 cnt = extattr_set_link(jcr->last_fname, current_attrnamespace,
1771 attrname, current_xattr->value, current_xattr->value_length);
1772 if (cnt < 0 || cnt != (int)current_xattr->value_length) {
1774 if (errno == ENOENT) {
1777 Mmsg2(jcr->errmsg, _("extattr_set_link error on file \"%s\": ERR=%s\n"),
1778 jcr->last_fname, be.bstrerror());
1779 Dmsg1(100, "%s", jcr->errmsg);
1785 retval = bxattr_rtn_ok;
1788 xattr_drop_internal_table(xattr_value_list);
1793 * Function pointers to the build and restore function to use for these xattrs.
1795 static bxattr_rtn_code (*os_backup_xattr_streams)
1796 (JCR *jcr, FF_PKT *ff_pkt) =
1797 bsd_backup_xattr_streams;
1798 static bxattr_rtn_code (*os_restore_xattr_streams)
1799 (JCR *jcr, int stream, char *content, uint32_t content_length) =
1800 bsd_restore_xattr_streams;
1802 #elif defined(HAVE_OSF1_OS)
1804 #if !defined(HAVE_GETPROPLIST) || \
1805 !defined(HAVE_GET_PROPLIST_ENTRY) || \
1806 !defined(HAVE_SIZEOF_PROPLIST_ENTRY) || \
1807 !defined(HAVE_ADD_PROPLIST_ENTRY) || \
1808 !defined(HAVE_SETPROPLIST)
1809 #error "Missing full support for the Extended Attributes functions."
1812 #ifdef HAVE_SYS_PROPLIST_H
1813 #include <sys/proplist.h>
1815 #error "Missing sys/proplist.h header file"
1819 * Define the supported XATTR streams for this OS
1821 static int os_default_xattr_streams[1] = {
1824 static const char *xattr_acl_skiplist[1] = {
1827 static const char *xattr_skiplist[1] = {
1831 static bxattr_rtn_code tru64_backup_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
1838 int xattr_count = 0;
1841 int32_t xattr_list_len,
1844 uint32_t expected_serialize_len = 0;
1845 xattr_t *current_xattr;
1846 alist *xattr_value_list = NULL;
1847 struct proplistname_args prop_args;
1848 bxattr_rtn_code retval = bxattr_rtn_error;
1849 POOLMEM *xattrbuf = get_pool_memory(PM_MESSAGE);
1851 xattrbuf_size = sizeof_pool_memory(xattrbuf);
1852 xattrbuf_min_size = 0;
1853 xattr_list_len = getproplist(jcr->last_fname, 1, &prop_args, xattrbuf_size,
1854 xattrbuf, &xattrbuf_min_size);
1857 * See what xattr are available.
1859 switch (xattr_list_len) {
1866 * If the filesystem reports it doesn't support XATTRs we clear
1867 * the BXATTR_FLAG_RESTORE_NATIVE flag so we skip XATTR restores
1868 * on all other files on the same filesystem. The
1869 * BXATTR_FLAG_RESTORE_NATIVE flags gets sets again when we
1870 * change from one filesystem to an other.
1872 jcr->xattr_ctx->flags &= ~BXATTR_FLAG_SAVE_NATIVE;
1873 retval = bxattr_rtn_ok;
1876 Mmsg2(jcr->errmsg, _("getproplist error on file \"%s\": ERR=%s\n"),
1877 jcr->last_fname, be.bstrerror());
1878 Dmsg1(100, "%s", jcr->errmsg);
1884 if (xattrbuf_min_size) {
1886 * The buffer isn't big enough to hold the xattr data, we now have
1887 * a minimum buffersize so we resize the buffer and try again.
1889 xattrbuf = check_pool_memory_size(xattrbuf, xattrbuf_min_size + 1);
1890 xattrbuf_size = xattrbuf_min_size + 1;
1891 xattr_list_len = getproplist(jcr->last_fname, 1, &prop_args, xattrbuf_size,
1892 xattrbuf, &xattrbuf_min_size);
1893 switch (xattr_list_len) {
1899 Mmsg2(jcr->errmsg, _("getproplist error on file \"%s\": ERR=%s\n"),
1900 jcr->last_fname, be.bstrerror());
1901 Dmsg1(100, "%s", jcr->errmsg);
1908 * This should never happen as we sized the buffer according to the minimumsize
1909 * returned by a previous getproplist call. If it does happen things are fishy and
1910 * we are better of forgetting this xattr as it seems its list is changing at this
1911 * exact moment so we can never make a good backup copy of it.
1913 retval = bxattr_rtn_ok;
1922 retval = bxattr_rtn_ok;
1931 * Walk the list of extended attributes names and retrieve the data.
1932 * We already count the bytes needed for serializing the stream later on.
1935 while (xattrbuf_size > 0) {
1937 * Call getproplist_entry to initialize name and value
1938 * pointers to entries position within buffer.
1940 xattrbuf_size -= get_proplist_entry(&xattr_name, &flags, &xattr_value_len, &xattr_value, &bp);
1943 * On some OSes you also get the acls in the extented attribute list.
1944 * So we check if we are already backing up acls and if we do we
1945 * don't store the extended attribute with the same info.
1947 if (ff_pkt->flags & FO_ACL) {
1948 for (cnt = 0; xattr_acl_skiplist[cnt] != NULL; cnt++) {
1949 if (bstrcmp(xattr_name, xattr_acl_skiplist[cnt])) {
1957 * On some OSes we want to skip certain xattrs which are in the xattr_skiplist array.
1960 for (cnt = 0; xattr_skiplist[cnt] != NULL; cnt++) {
1961 if (bstrcmp(xattr_name, xattr_skiplist[cnt])) {
1969 Dmsg1(100, "Skipping xattr named %s\n", xattr_name);
1974 * Each xattr valuepair starts with a magic so we can restore it easier.
1976 current_xattr = (xattr_t *)malloc(sizeof(xattr_t));
1977 memset(current_xattr, 0, sizeof(xattr_t));
1978 current_xattr->magic = XATTR_MAGIC;
1979 expected_serialize_len += sizeof(current_xattr->magic);
1981 current_xattr->name_length = strlen(xattr_name);
1982 current_xattr->name = bstrdup(xattr_name);
1984 expected_serialize_len += sizeof(current_xattr->name_length) +
1985 current_xattr->name_length;
1987 current_xattr->value_length = *xattr_value_len;
1988 current_xattr->value = (char *)malloc(current_xattr->value_length);
1989 memcpy(current_xattr->value, xattr_value, current_xattr->value_length);
1991 expected_serialize_len += sizeof(current_xattr->value_length) +
1992 current_xattr->value_length;
1994 if (xattr_value_list == NULL) {
1995 xattr_value_list = New(alist(10, not_owned_by_alist));
1998 xattr_value_list->append(current_xattr);
2002 * Protect ourself against things getting out of hand.
2004 if (expected_serialize_len >= MAX_XATTR_LENGTH) {
2006 _("Xattr stream on file \"%s\" exceeds maximum size of %d bytes\n"),
2007 jcr->last_fname, MAX_XATTR_LENGTH);
2013 * If we found any xattr send them to the SD.
2015 if (xattr_count > 0) {
2017 * Serialize the datastream.
2019 if (serialize_xattr_stream(jcr,
2020 expected_serialize_len,
2021 xattr_value_list) < expected_serialize_len) {
2022 Mmsg1(jcr->errmsg, _("Failed to serialize extended attributes on file \"%s\"\n"),
2024 Dmsg1(100, "%s", jcr->errmsg);
2029 * Send the datastream to the SD.
2031 retval = send_xattr_stream(jcr, os_default_xattr_streams[0]);
2033 retval = bxattr_rtn_ok;
2037 if (xattr_value_list != NULL) {
2038 xattr_drop_internal_table(xattr_value_list);
2040 free_pool_memory(xattrbuf);
2045 static bxattr_rtn_code tru64_restore_xattr_streams(JCR *jcr,
2048 uint32_t content_length)
2050 char *bp, *xattrbuf = NULL;
2051 int32_t xattrbuf_size, cnt;
2052 xattr_t *current_xattr;
2053 alist *xattr_value_list;
2054 bxattr_rtn_code retval = bxattr_rtn_error;
2056 xattr_value_list = New(alist(10, not_owned_by_alist));
2058 if (unserialize_xattr_stream(jcr,
2061 xattr_value_list) != bxattr_rtn_ok) {
2066 * See how big the propertylist must be.
2069 foreach_alist(current_xattr, xattr_value_list) {
2070 xattrbuf_size += sizeof_proplist_entry(current_xattr->name, current_xattr->value_length);
2073 xattrbuf = (char *)malloc(xattrbuf_size);
2076 * Add all value pairs to the proplist.
2080 foreach_alist(current_xattr, xattr_value_list) {
2081 cnt = add_proplist_entry(current_xattr->name, 0, current_xattr->value_length,
2082 current_xattr->value, &bp);
2088 if (cnt != xattrbuf_size) {
2089 Mmsg1(jcr->errmsg, _("Unable create proper proplist to restore xattrs on file \"%s\"\n"),
2091 Dmsg1(100, "%s", jcr->errmsg);
2096 * Restore the list of extended attributes on the file.
2098 cnt = setproplist(jcr->last_fname, 1, xattrbuf_size, xattrbuf);
2106 * If the filesystem reports it doesn't support XATTRs we clear
2107 * the BXATTR_FLAG_RESTORE_NATIVE flag so we skip XATTR restores
2108 * on all other files on the same filesystem. The
2109 * BXATTR_FLAG_RESTORE_NATIVE flags gets sets again when we
2110 * change from one filesystem to an other.
2112 jcr->xattr_ctx->flags &= ~BXATTR_FLAG_RESTORE_NATIVE;
2113 retval = bxattr_rtn_ok;
2116 Mmsg2(jcr->errmsg, _("setproplist error on file \"%s\": ERR=%s\n"),
2117 jcr->last_fname, be.bstrerror());
2118 Dmsg1(100, "%s", jcr->errmsg);
2127 retval = bxattr_rtn_ok;
2133 xattr_drop_internal_table(xattr_value_list);
2139 * Function pointers to the build and restore function to use for these xattrs.
2141 static bxattr_rtn_code (*os_backup_xattr_streams)
2142 (JCR *jcr, FF_PKT *ff_pkt) =
2143 tru64_backup_xattr_streams;
2144 static bxattr_rtn_code (*os_restore_xattr_streams)
2145 (JCR *jcr, int stream, char *content, uint32_t content_length) =
2146 tru64_restore_xattr_streams;
2148 #elif defined(HAVE_SUN_OS)
2150 * Solaris extended attributes were introduced in Solaris 9
2153 * Solaris extensible attributes were introduced in OpenSolaris
2154 * by PSARC 2007/315 Solaris extensible attributes are also
2155 * sometimes called extended system attributes.
2157 * man fsattr(5) on Solaris gives a wealth of info. The most
2158 * important bits are:
2160 * Attributes are logically supported as files within the file
2161 * system. The file system is therefore augmented with an
2162 * orthogonal name space of file attributes. Any file (includ-
2163 * ing attribute files) can have an arbitrarily deep attribute
2164 * tree associated with it. Attribute values are accessed by
2165 * file descriptors obtained through a special attribute inter-
2166 * face. This logical view of "attributes as files" allows the
2167 * leveraging of existing file system interface functionality
2168 * to support the construction, deletion, and manipulation of
2171 * The special files "." and ".." retain their accustomed
2172 * semantics within the attribute hierarchy. The "." attribute
2173 * file refers to the current directory and the ".." attribute
2174 * file refers to the parent directory. The unnamed directory
2175 * at the head of each attribute tree is considered the "child"
2176 * of the file it is associated with and the ".." file refers
2177 * to the associated file. For any non-directory file with
2178 * attributes, the ".." entry in the unnamed directory refers
2179 * to a file that is not a directory.
2181 * Conceptually, the attribute model is fully general. Extended
2182 * attributes can be any type of file (doors, links, direc-
2183 * tories, and so forth) and can even have their own attributes
2184 * (fully recursive). As a result, the attributes associated
2185 * with a file could be an arbitrarily deep directory hierarchy
2186 * where each attribute could have an equally complex attribute
2187 * tree associated with it. Not all implementations are able
2188 * to, or want to, support the full model. Implementation are
2189 * therefore permitted to reject operations that are not sup-
2190 * ported. For example, the implementation for the UFS file
2191 * system allows only regular files as attributes (for example,
2192 * no sub-directories) and rejects attempts to place attributes
2195 * The following list details the operations that are rejected
2196 * in the current implementation:
2198 * link Any attempt to create links between
2199 * attribute and non-attribute space
2200 * is rejected to prevent security-
2201 * related or otherwise sensitive
2202 * attributes from being exposed, and
2203 * therefore manipulable, as regular
2206 * rename Any attempt to rename between
2207 * attribute and non-attribute space
2208 * is rejected to prevent an already
2209 * linked file from being renamed and
2210 * thereby circumventing the link res-
2213 * mkdir, symlink, mknod Any attempt to create a "non-
2214 * regular" file in attribute space is
2215 * rejected to reduce the functional-
2216 * ity, and therefore exposure and
2217 * risk, of the initial implementa-
2220 * The entire available name space has been allocated to "gen-
2221 * eral use" to bring the implementation in line with the NFSv4
2222 * draft standard [NFSv4]. That standard defines "named attri-
2223 * butes" (equivalent to Solaris Extended Attributes) with no
2224 * naming restrictions. All Sun applications making use of
2225 * opaque extended attributes will use the prefix "SUNW".
2228 #ifdef HAVE_SYS_ATTR_H
2229 #include <sys/attr.h>
2236 #ifdef HAVE_SYS_NVPAIR_H
2237 #include <sys/nvpair.h>
2240 #ifdef HAVE_SYS_ACL_H
2241 #include <sys/acl.h>
2244 #if !defined(HAVE_OPENAT) || \
2245 !defined(HAVE_UNLINKAT) || \
2246 !defined(HAVE_FCHOWNAT) || \
2247 !defined(HAVE_FUTIMESAT)
2248 #error "Unable to compile code because of missing openat, unlinkat, fchownat or futimesat function"
2252 * Define the supported XATTR streams for this OS
2254 #if defined(HAVE_SYS_NVPAIR_H) && defined(_PC_SATTR_ENABLED)
2255 static int os_default_xattr_streams[2] = {
2256 STREAM_XATTR_SOLARIS,
2257 STREAM_XATTR_SOLARIS_SYS
2260 static int os_default_xattr_streams[1] = {
2261 STREAM_XATTR_SOLARIS
2263 #endif /* defined(HAVE_SYS_NVPAIR_H) && defined(_PC_SATTR_ENABLED) */
2266 * This code creates a temporary cache with entries for each xattr which has
2267 * a link count > 1 (which indicates it has one or more hard linked counterpart(s))
2269 static inline xattr_link_cache_entry_t *find_xattr_link_cache_entry(JCR *jcr, ino_t inum)
2271 xattr_link_cache_entry_t *ptr;
2273 foreach_alist(ptr, jcr->xattr_ctx->link_cache) {
2274 if (ptr && ptr->inum == inum) {
2281 static inline void add_xattr_link_cache_entry(JCR *jcr, ino_t inum, char *target)
2283 xattr_link_cache_entry_t *ptr;
2285 ptr = (xattr_link_cache_entry_t *)malloc(sizeof(xattr_link_cache_entry_t));
2286 memset(ptr, 0, sizeof(xattr_link_cache_entry_t));
2288 ptr->target = bstrdup(target);
2290 if (!jcr->xattr_ctx->link_cache) {
2291 jcr->xattr_ctx->link_cache = New(alist(10, not_owned_by_alist));
2293 jcr->xattr_ctx->link_cache->append(ptr);
2296 static inline void drop_xattr_link_cache(JCR *jcr)
2298 xattr_link_cache_entry_t *ptr;
2301 * Walk the list of xattr link cache entries and free allocated memory on traversing.
2303 foreach_alist(ptr, jcr->xattr_ctx->link_cache) {
2308 delete jcr->xattr_ctx->link_cache;
2309 jcr->xattr_ctx->link_cache = NULL;
2312 #if defined(HAVE_SYS_NVPAIR_H) && defined(_PC_SATTR_ENABLED)
2314 * This function returns true if a non default extended system attribute
2315 * list is associated with fd and returns false when an error has occured
2316 * or when only extended system attributes other than archive,
2317 * av_modified or crtime are set.
2319 * The function returns true for the following cases:
2321 * - any extended system attribute other than the default attributes
2322 * ('archive', 'av_modified' and 'crtime') is set
2323 * - nvlist has NULL name string
2324 * - nvpair has data type of 'nvlist'
2325 * - default data type.
2327 static bool solaris_has_non_transient_extensible_attributes(int fd)
2335 bool retval = false;
2337 if (fgetattr(fd, XATTR_VIEW_READWRITE, &response) != 0) {
2342 while ((pair = nvlist_next_nvpair(response, pair)) != NULL) {
2343 name = nvpair_name(pair);
2346 fattr = name_to_attr(name);
2352 type = nvpair_type(pair);
2354 case DATA_TYPE_BOOLEAN_VALUE:
2355 if (nvpair_value_boolean_value(pair, &value) != 0) {
2358 if (value && fattr != F_ARCHIVE &&
2359 fattr != F_AV_MODIFIED) {
2364 case DATA_TYPE_UINT64_ARRAY:
2365 if (fattr != F_CRTIME) {
2370 case DATA_TYPE_NVLIST:
2378 if (response != NULL) {
2379 nvlist_free(response);
2383 #endif /* HAVE_SYS_NVPAIR_H && _PC_SATTR_ENABLED */
2385 #if defined(HAVE_ACL) && !defined(HAVE_EXTENDED_ACL)
2387 * See if an acl is a trivial one (e.g. just the stat bits encoded as acl.)
2388 * There is no need to store those acls as we already store the stat bits too.
2390 static bool acl_is_trivial(int count, aclent_t *entries)
2395 for (n = 0; n < count; n++) {
2397 if (!(ace->a_type == USER_OBJ ||
2398 ace->a_type == GROUP_OBJ ||
2399 ace->a_type == OTHER_OBJ ||
2400 ace->a_type == CLASS_OBJ))
2405 #endif /* HAVE_ACL && !HAVE_EXTENDED_ACL */
2407 static bxattr_rtn_code solaris_save_xattr_acl(JCR *jcr, int fd, const char *attrname, char **acl_text)
2409 bxattr_rtn_code retval = bxattr_rtn_error;
2411 #ifdef HAVE_EXTENDED_ACL
2416 * See if this attribute has an ACL
2418 if ((fd != -1 && fpathconf(fd, _PC_ACL_ENABLED) > 0) ||
2419 pathconf(attrname, _PC_ACL_ENABLED) > 0) {
2421 * See if there is a non trivial acl on the file.
2423 if ((fd != -1 && facl_get(fd, ACL_NO_TRIVIAL, &aclp) != 0) ||
2424 acl_get(attrname, ACL_NO_TRIVIAL, &aclp) != 0) {
2429 retval = bxattr_rtn_ok;
2432 Mmsg3(jcr->errmsg, _("Unable to get acl on xattr %s on file \"%s\": ERR=%s\n"),
2433 attrname, jcr->last_fname, be.bstrerror());
2434 Dmsg1(100, "%s", jcr->errmsg);
2440 #if defined(ACL_SID_FMT)
2442 * New format flag added in newer Solaris versions.
2444 flags = ACL_APPEND_ID | ACL_COMPACT_FMT | ACL_SID_FMT;
2446 flags = ACL_APPEND_ID | ACL_COMPACT_FMT;
2447 #endif /* ACL_SID_FMT */
2449 *acl_text = acl_totext(aclp, flags);
2457 retval = bxattr_rtn_ok;
2458 #else /* HAVE_EXTENDED_ACL */
2460 aclent_t *acls = NULL;
2463 * See if this attribute has an ACL
2466 n = facl(fd, GETACLCNT, 0, NULL);
2468 n = acl(attrname, GETACLCNT, 0, NULL);
2471 if (n >= MIN_ACL_ENTRIES) {
2472 acls = (aclent_t *)malloc(n * sizeof(aclent_t));
2473 if ((fd != -1 && facl(fd, GETACL, n, acls) != n) ||
2474 acl(attrname, GETACL, n, acls) != n) {
2480 retval = bxattr_rtn_ok;
2483 Mmsg3(jcr->errmsg, _("Unable to get acl on xattr %s on file \"%s\": ERR=%s\n"),
2484 attrname, jcr->last_fname, be.bstrerror());
2485 Dmsg1(100, "%s", jcr->errmsg);
2492 * See if there is a non trivial acl on the file.
2494 if (!acl_is_trivial(n, acls)) {
2495 if ((*acl_text = acltotext(acls, n)) == NULL) {
2498 Mmsg3(jcr->errmsg, _("Unable to get acl text on xattr %s on file \"%s\": ERR=%s\n"),
2499 attrname, jcr->last_fname, be.bstrerror());
2500 Dmsg1(100, "%s", jcr->errmsg);
2512 retval = bxattr_rtn_ok;
2513 #endif /* HAVE_EXTENDED_ACL */
2515 #else /* HAVE_ACL */
2516 retval = bxattr_rtn_ok;
2517 #endif /* HAVE_ACL */
2524 * Forward declaration for recursive function call.
2526 static bxattr_rtn_code solaris_save_xattrs(JCR *jcr, const char *xattr_namespace, const char *attr_parent);
2529 * Save an extended or extensible attribute.
2530 * This is stored as an opaque stream of bytes with the following encoding:
2532 * <xattr_name>\0<stat_buffer>\0<acl_string>\0<actual_xattr_ctx>
2534 * or for a hardlinked or symlinked attribute
2536 * <xattr_name>\0<stat_buffer>\0<xattr_link_source>\0
2538 * xattr_name can be a subpath relative to the file the xattr is on.
2539 * stat_buffer is the string representation of the stat struct.
2540 * acl_string is an acl text when a non trivial acl is set on the xattr.
2541 * actual_xattr_ctx is the content of the xattr file.
2543 static bxattr_rtn_code solaris_save_xattr(JCR *jcr, int fd, const char *xattr_namespace,
2544 const char *attrname, bool toplevel_hidden_dir, int stream)
2549 xattr_link_cache_entry_t *xlce;
2550 char target_attrname[PATH_MAX];
2551 char link_source[PATH_MAX];
2552 char *acl_text = NULL;
2553 char attribs[MAXSTRING];
2554 char buffer[XATTR_BUFSIZ];
2555 bxattr_rtn_code retval = bxattr_rtn_error;
2557 bsnprintf(target_attrname, sizeof(target_attrname), "%s%s", xattr_namespace, attrname);
2560 * Get the stats of the extended or extensible attribute.
2562 if (fstatat(fd, attrname, &st, AT_SYMLINK_NOFOLLOW) < 0) {
2567 retval = bxattr_rtn_ok;
2570 Mmsg3(jcr->errmsg, _("Unable to get status on xattr %s on file \"%s\": ERR=%s\n"),
2571 target_attrname, jcr->last_fname, be.bstrerror());
2572 Dmsg1(100, "%s", jcr->errmsg);
2578 * Based on the filetype perform the correct action. We support most filetypes here, more
2579 * then the actual implementation on Solaris supports so some code may never get executed
2580 * due to limitations in the implementation.
2582 switch (st.st_mode & S_IFMT) {
2587 * Get any acl on the xattr.
2589 if (solaris_save_xattr_acl(jcr, attrfd, attrname, &acl_text) != bxattr_rtn_ok)
2593 * The current implementation of xattr on Solaris doesn't support this,
2594 * but if it ever does we are prepared.
2595 * Encode the stat struct into an ASCII representation.
2597 encode_stat(attribs, &st, sizeof(st), 0, stream);
2598 cnt = bsnprintf(buffer, sizeof(buffer), "%s%c%s%c%s%c",
2599 target_attrname, 0, attribs, 0,
2600 (acl_text) ? acl_text : "", 0);
2604 * Get any acl on the xattr.
2606 if (solaris_save_xattr_acl(jcr, attrfd, attrname, &acl_text) != bxattr_rtn_ok)
2610 * See if this is the toplevel_hidden_dir being saved.
2612 if (toplevel_hidden_dir) {
2614 * Save the data for later storage when we encounter a real xattr.
2615 * We store the data in the jcr->xattr_ctx->content buffer
2616 * and flush that just before sending out the first real xattr.
2617 * Encode the stat struct into an ASCII representation and jump
2618 * out of the function.
2620 encode_stat(attribs, &st, sizeof(st), 0, stream);
2621 cnt = bsnprintf(buffer, sizeof(buffer),
2623 target_attrname, 0, attribs, 0,
2624 (acl_text) ? acl_text : "", 0);
2625 pm_memcpy(jcr->xattr_ctx->content, buffer, cnt);
2626 jcr->xattr_ctx->content_length = cnt;
2630 * The current implementation of xattr on Solaris doesn't support this,
2631 * but if it ever does we are prepared.
2632 * Encode the stat struct into an ASCII representation.
2634 encode_stat(attribs, &st, sizeof(st), 0, stream);
2635 cnt = bsnprintf(buffer, sizeof(buffer),
2637 target_attrname, 0, attribs, 0,
2638 (acl_text) ? acl_text : "", 0);
2643 * If this is a hardlinked file check the inode cache for a hit.
2645 if (st.st_nlink > 1) {
2647 * See if the cache already knows this inode number.
2649 if ((xlce = find_xattr_link_cache_entry(jcr, st.st_ino)) != NULL) {
2651 * Generate a xattr encoding with the reference to the target in there.
2653 encode_stat(attribs, &st, sizeof(st), st.st_ino, stream);
2654 cnt = bsnprintf(buffer, sizeof(buffer),
2656 target_attrname, 0, attribs, 0, xlce->target, 0);
2657 pm_memcpy(jcr->xattr_ctx->content, buffer, cnt);
2658 jcr->xattr_ctx->content_length = cnt;
2659 retval = send_xattr_stream(jcr, stream);
2662 * For a hard linked file we are ready now, no need to recursively
2663 * save the attributes.
2669 * Store this hard linked file in the cache.
2670 * Store the name relative to the top level xattr space.
2672 add_xattr_link_cache_entry(jcr, st.st_ino, target_attrname + 1);
2676 * Get any acl on the xattr.
2678 if (solaris_save_xattr_acl(jcr, attrfd, attrname, &acl_text) != bxattr_rtn_ok) {
2683 * Encode the stat struct into an ASCII representation.
2685 encode_stat(attribs, &st, sizeof(st), 0, stream);
2686 cnt = bsnprintf(buffer, sizeof(buffer),
2688 target_attrname, 0, attribs, 0, (acl_text) ? acl_text : "", 0);
2691 * Open the extended or extensible attribute file.
2693 if ((attrfd = openat(fd, attrname, O_RDONLY)) < 0) {
2698 retval = bxattr_rtn_ok;
2701 Mmsg3(jcr->errmsg, _("Unable to open xattr %s on \"%s\": ERR=%s\n"),
2702 target_attrname, jcr->last_fname, be.bstrerror());
2703 Dmsg1(100, "%s", jcr->errmsg);
2710 * The current implementation of xattr on Solaris doesn't support this, but if it
2711 * ever does we are prepared.
2712 * Encode the stat struct into an ASCII representation.
2714 if (readlink(attrname, link_source, sizeof(link_source)) < 0) {
2719 retval = bxattr_rtn_ok;
2722 Mmsg3(jcr->errmsg, _("Unable to read symlin %s on \"%s\": ERR=%s\n"),
2723 target_attrname, jcr->last_fname, be.bstrerror());
2724 Dmsg1(100, "%s", jcr->errmsg);
2730 * Generate a xattr encoding with the reference to the target in there.
2732 encode_stat(attribs, &st, sizeof(st), st.st_ino, stream);
2733 cnt = bsnprintf(buffer, sizeof(buffer),
2735 target_attrname, 0, attribs, 0, link_source, 0);
2736 pm_memcpy(jcr->xattr_ctx->content, buffer, cnt);
2737 jcr->xattr_ctx->content_length = cnt;
2738 retval = send_xattr_stream(jcr, stream);
2740 if (retval == bxattr_rtn_ok) {
2741 jcr->xattr_ctx->nr_saved++;
2745 * For a soft linked file we are ready now, no need to recursively save the attributes.
2753 * See if this is the first real xattr being saved.
2754 * If it is save the toplevel_hidden_dir attributes first.
2755 * This is easy as its stored already in the
2756 * jcr->xattr_ctx->content buffer.
2758 if (jcr->xattr_ctx->nr_saved == 0) {
2759 retval = send_xattr_stream(jcr, STREAM_XATTR_SOLARIS);
2760 if (retval != bxattr_rtn_ok) {
2763 jcr->xattr_ctx->nr_saved++;
2766 pm_memcpy(jcr->xattr_ctx->content, buffer, cnt);
2767 jcr->xattr_ctx->content_length = cnt;
2770 * Only dump the content of regular files.
2772 switch (st.st_mode & S_IFMT) {
2774 if (st.st_size > 0) {
2776 * Protect ourself against things getting out of hand.
2778 if (st.st_size >= MAX_XATTR_LENGTH) {
2780 _("Xattr stream on file \"%s\" exceeds maximum size of %d bytes\n"),
2781 jcr->last_fname, MAX_XATTR_LENGTH);
2785 while ((cnt = read(attrfd, buffer, sizeof(buffer))) > 0) {
2786 jcr->xattr_ctx->content =
2787 check_pool_memory_size(jcr->xattr_ctx->content,
2788 jcr->xattr_ctx->content_length + cnt);
2789 memcpy(jcr->xattr_ctx->content +
2790 jcr->xattr_ctx->content_length, buffer, cnt);
2791 jcr->xattr_ctx->content_length += cnt;
2795 Mmsg2(jcr->errmsg, _("Unable to read content of xattr %s on file \"%s\"\n"),
2796 target_attrname, jcr->last_fname);
2797 Dmsg1(100, "%s", jcr->errmsg);
2808 * We build a new xattr stream send it to the SD.
2810 retval = send_xattr_stream(jcr, stream);
2811 if (retval != bxattr_rtn_ok) {
2814 jcr->xattr_ctx->nr_saved++;
2817 * Recursivly call solaris_save_extended_attributes for archiving the attributes
2818 * available on this extended attribute.
2820 retval = solaris_save_xattrs(jcr, xattr_namespace, attrname);
2823 * The recursive call could change our working dir so change back to the wanted workdir.
2825 if (fchdir(fd) < 0) {
2830 retval = bxattr_rtn_ok;
2833 Mmsg2(jcr->errmsg, _("Unable to chdir to xattr space of file \"%s\": ERR=%s\n"),
2834 jcr->last_fname, be.bstrerror());
2835 Dmsg1(100, "%s", jcr->errmsg);
2841 if (acl_text != NULL) {
2850 static bxattr_rtn_code solaris_save_xattrs(JCR *jcr, const char *xattr_namespace, const char *attr_parent)
2853 int fd, filefd = -1, attrdirfd = -1;
2856 char current_xattr_namespace[PATH_MAX];
2857 bxattr_rtn_code retval = bxattr_rtn_error;
2860 * Determine what argument to use. Use attr_parent when set
2861 * (recursive call) or jcr->last_fname for first call. Also save
2862 * the current depth of the xattr_space we are in.
2866 if (xattr_namespace) {
2867 bsnprintf(current_xattr_namespace, sizeof(current_xattr_namespace), "%s%s/",
2868 xattr_namespace, attr_parent);
2870 bstrncpy(current_xattr_namespace, "/", sizeof(current_xattr_namespace));
2873 name = jcr->last_fname;
2874 bstrncpy(current_xattr_namespace, "/", sizeof(current_xattr_namespace));
2878 * Open the file on which to save the xattrs read-only.
2880 if ((filefd = open(name, O_RDONLY | O_NONBLOCK)) < 0) {
2885 retval = bxattr_rtn_ok;
2888 Mmsg2(jcr->errmsg, _("Unable to open file \"%s\": ERR=%s\n"),
2889 jcr->last_fname, be.bstrerror());
2890 Dmsg1(100, "%s", jcr->errmsg);
2896 * Open the xattr naming space.
2898 if ((attrdirfd = openat(filefd, ".", O_RDONLY | O_XATTR)) < 0) {
2904 * Gentile way of the system saying this type of xattr layering is not supported.
2905 * Which is not problem we just forget about this this xattr.
2906 * But as this is not an error we return a positive return value.
2908 retval = bxattr_rtn_ok;
2911 retval = bxattr_rtn_ok;
2914 Mmsg3(jcr->errmsg, _("Unable to open xattr space %s on file \"%s\": ERR=%s\n"),
2915 name, jcr->last_fname, be.bstrerror());
2916 Dmsg1(100, "%s", jcr->errmsg);
2922 * We need to change into the attribute directory to determine if each of the
2923 * attributes should be saved.
2925 if (fchdir(attrdirfd) < 0) {
2928 Mmsg2(jcr->errmsg, _("Unable to chdir to xattr space on file \"%s\": ERR=%s\n"),
2929 jcr->last_fname, be.bstrerror());
2930 Dmsg1(100, "%s", jcr->errmsg);
2935 * Save the data of the toplevel xattr hidden_dir. We save this one before anything
2936 * else because the readdir returns "." entry after the extensible attr entry.
2937 * And as we want this entry before anything else we better just save its data.
2940 solaris_save_xattr(jcr, attrdirfd, current_xattr_namespace, ".",
2941 true, STREAM_XATTR_SOLARIS);
2943 if ((fd = dup(attrdirfd)) == -1 ||
2944 (dirp = fdopendir(fd)) == (DIR *)NULL) {
2947 Mmsg2(jcr->errmsg, _("Unable to list the xattr space on file \"%s\": ERR=%s\n"),
2948 jcr->last_fname, be.bstrerror());
2949 Dmsg1(100, "%s", jcr->errmsg);
2955 * Walk the namespace.
2957 while ((dp = readdir(dirp)) != NULL) {
2959 * Skip only the toplevel . dir.
2961 if (!attr_parent && bstrcmp(dp->d_name, "."))
2965 * Skip all .. directories
2967 if (bstrcmp(dp->d_name, ".."))
2970 Dmsg3(400, "processing extended attribute %s%s on file \"%s\"\n",
2971 current_xattr_namespace, dp->d_name, jcr->last_fname);
2973 #if defined(HAVE_SYS_NVPAIR_H) && defined(_PC_SATTR_ENABLED)
2975 * We are not interested in read-only extensible attributes.
2977 if (bstrcmp(dp->d_name, VIEW_READONLY)) {
2978 Dmsg3(400, "Skipping readonly extensible attributes %s%s on file \"%s\"\n",
2979 current_xattr_namespace, dp->d_name, jcr->last_fname);
2985 * We are only interested in read-write extensible attributes
2986 * when they contain non-transient values.
2988 if (bstrcmp(dp->d_name, VIEW_READWRITE)) {
2990 * Determine if there are non-transient system attributes at the toplevel.
2991 * We need to provide a fd to the open file.
2993 if (!solaris_has_non_transient_extensible_attributes(filefd)) {
2994 Dmsg3(400, "Skipping transient extensible attributes %s%s on file \"%s\"\n",
2995 current_xattr_namespace, dp->d_name, jcr->last_fname);
3002 solaris_save_xattr(jcr, attrdirfd, current_xattr_namespace, dp->d_name,
3003 false, STREAM_XATTR_SOLARIS_SYS);
3006 #endif /* HAVE_SYS_NVPAIR_H && _PC_SATTR_ENABLED */
3011 solaris_save_xattr(jcr, attrdirfd, current_xattr_namespace, dp->d_name,
3012 false, STREAM_XATTR_SOLARIS);
3016 retval = bxattr_rtn_ok;
3019 if (attrdirfd != -1)
3027 static bxattr_rtn_code solaris_restore_xattr_acl(JCR *jcr,
3029 const char *attrname,
3032 #ifdef HAVE_EXTENDED_ACL
3036 if ((error = acl_fromtext(acl_text, &aclp)) != 0) {
3038 _("Unable to convert acl from text on file \"%s\"\n"),
3040 return bxattr_rtn_error;
3043 if ((fd != -1 && facl_set(fd, aclp) != 0) ||
3044 acl_set(attrname, aclp) != 0) {
3047 Mmsg3(jcr->errmsg, _("Unable to restore acl of xattr %s on file \"%s\": ERR=%s\n"),
3048 attrname, jcr->last_fname, be.bstrerror());
3049 Dmsg1(100, "%s", jcr->errmsg);
3050 return bxattr_rtn_error;
3056 return bxattr_rtn_ok;
3058 #else /* HAVE_EXTENDED_ACL */
3060 aclent_t *acls = NULL;
3062 acls = aclfromtext(acl_text, &n);
3064 if ((fd != -1 && facl(fd, SETACL, n, acls) != 0) ||
3065 acl(attrname, SETACL, n, acls) != 0) {
3068 Mmsg3(jcr->errmsg, _("Unable to restore acl of xattr %s on file \"%s\": ERR=%s\n"),
3069 attrname, jcr->last_fname, be.bstrerror());
3070 Dmsg1(100, "%s", jcr->errmsg);
3071 return bxattr_rtn_error;
3078 return bxattr_rtn_ok;
3080 #endif /* HAVE_EXTENDED_ACL */
3083 #endif /* HAVE_ACL */
3085 static bxattr_rtn_code solaris_restore_xattrs(JCR *jcr,
3088 uint32_t content_length)
3091 int fd, filefd = -1, attrdirfd = -1, attrfd = -1;
3092 int used_bytes, cnt;
3093 char *bp, *target_attrname, *attribs;
3094 char *linked_target = NULL;
3095 char *acl_text = NULL;
3099 struct timeval times[2];
3100 bxattr_rtn_code retval = bxattr_rtn_error;
3103 * Restore the xattr stream. First the part that is the same for all xattrs.
3108 * The name of the target xattr has a leading / we are not interested
3109 * in that so skip it when decoding the string. We always start a the /
3110 * of the xattr space anyway.
3112 target_attrname = content + 1;
3113 if ((bp = strchr(target_attrname, '\0')) == (char *)NULL ||
3114 (used_bytes = (bp - content)) >= (int32_t)(content_length - 1)) {
3120 * Open the file on which to restore the xattrs read-only.
3122 if ((filefd = open(jcr->last_fname, O_RDONLY | O_NONBLOCK)) < 0) {
3125 Mmsg2(jcr->errmsg, _("Unable to open file \"%s\": ERR=%s\n"),
3126 jcr->last_fname, be.bstrerror());
3127 Dmsg1(100, "%s", jcr->errmsg);
3132 * Open the xattr naming space and make it the current working dir.
3134 if ((attrdirfd = openat(filefd, ".", O_RDONLY | O_XATTR)) < 0) {
3137 Mmsg2(jcr->errmsg, _("Unable to open xattr space on file \"%s\": ERR=%s\n"),
3138 jcr->last_fname, be.bstrerror());
3139 Dmsg1(100, "%s", jcr->errmsg);
3143 if (fchdir(attrdirfd) < 0) {
3146 Mmsg2(jcr->errmsg, _("Unable to chdir to xattr space on file \"%s\": ERR=%s\n"),
3147 jcr->last_fname, be.bstrerror());
3148 Dmsg1(100, "%s", jcr->errmsg);
3153 * Try to open the correct xattr subdir based on the target_attrname given.
3154 * e.g. check if its a subdir attrname. Each / in the string makes us go
3157 while ((bp = strchr(target_attrname, '/')) != (char *)NULL) {
3160 if ((fd = open(target_attrname, O_RDONLY | O_NONBLOCK)) < 0) {
3163 Mmsg3(jcr->errmsg, _("Unable to open xattr %s on file \"%s\": ERR=%s\n"),
3164 target_attrname, jcr->last_fname, be.bstrerror());
3165 Dmsg1(100, "%s", jcr->errmsg);
3173 * Open the xattr naming space.
3175 if ((fd = openat(filefd, ".", O_RDONLY | O_XATTR)) < 0) {
3178 Mmsg3(jcr->errmsg, _("Unable to open xattr space %s on file \"%s\": ERR=%s\n"),
3179 target_attrname, jcr->last_fname, be.bstrerror());
3180 Dmsg1(100, "%s", jcr->errmsg);
3188 * Make the xattr space our current workingdir.
3190 if (fchdir(attrdirfd) < 0) {
3193 Mmsg3(jcr->errmsg, _("Unable to chdir to xattr space %s on file \"%s\": ERR=%s\n"),
3194 target_attrname, jcr->last_fname, be.bstrerror());
3195 Dmsg1(100, "%s", jcr->errmsg);
3199 target_attrname = ++bp;
3203 * Decode the attributes from the stream.
3205 decode_stat(attribs, &st, sizeof(st), &inum);
3208 * Decode the next field (acl_text).
3210 if ((bp = strchr(attribs, '\0')) == (char *)NULL ||
3211 (used_bytes = (bp - content)) >= (int32_t)(content_length - 1)) {
3217 * Based on the filetype perform the correct action. We support most filetypes here, more
3218 * then the actual implementation on Solaris supports so some code may never get executed
3219 * due to limitations in the implementation.
3221 switch (st.st_mode & S_IFMT) {
3224 * The current implementation of xattr on Solaris doesn't support this,
3225 * but if it ever does we are prepared.
3227 unlinkat(attrdirfd, target_attrname, 0);
3228 if (mkfifo(target_attrname, st.st_mode) < 0) {
3231 Mmsg3(jcr->errmsg, _("Unable to mkfifo xattr %s on file \"%s\": ERR=%s\n"),
3232 target_attrname, jcr->last_fname, be.bstrerror());
3233 Dmsg1(100, "%s", jcr->errmsg);
3240 * The current implementation of xattr on Solaris doesn't support this,
3241 * but if it ever does we are prepared.
3243 unlinkat(attrdirfd, target_attrname, 0);
3244 if (mknod(target_attrname, st.st_mode, st.st_rdev) < 0) {
3247 Mmsg3(jcr->errmsg, _("Unable to mknod xattr %s on file \"%s\": ERR=%s\n"),
3248 target_attrname, jcr->last_fname, be.bstrerror());
3249 Dmsg1(100, "%s", jcr->errmsg);
3255 * If its not the hidden_dir create the entry.
3256 * The current implementation of xattr on Solaris doesn't support this,
3257 * but if it ever does we are prepared.
3259 if (!bstrcmp(target_attrname, ".")) {
3260 unlinkat(attrdirfd, target_attrname, AT_REMOVEDIR);
3261 if (mkdir(target_attrname, st.st_mode) < 0) {
3264 /* *** FIXME *** why not Mmsg? */
3265 Jmsg3(jcr, M_WARNING, 0, _("Unable to mkdir xattr %s on file \"%s\": ERR=%s\n"),
3266 target_attrname, jcr->last_fname, be.bstrerror());
3267 Dmsg3(100, "Unable to mkdir xattr %s on file \"%s\": ERR=%s\n",
3268 target_attrname, jcr->last_fname, be.bstrerror());
3275 * See if this is a hard linked file. e.g. inum != 0
3280 unlinkat(attrdirfd, target_attrname, 0);
3281 if (link(linked_target, target_attrname) < 0) {
3284 Mmsg4(jcr->errmsg, _("Unable to link xattr %s to %s on file \"%s\": ERR=%s\n"),
3285 target_attrname, linked_target, jcr->last_fname, be.bstrerror());
3286 Dmsg1(100, "%s", jcr->errmsg);
3291 * Successfully restored xattr.
3293 retval = bxattr_rtn_ok;
3296 if ((bp = strchr(acl_text, '\0')) == (char *)NULL ||
3297 (used_bytes = (bp - content)) >= (int32_t)content_length) {
3301 if (used_bytes < (int32_t)(content_length - 1))
3305 * Restore the actual xattr.
3307 if (!is_extensible) {
3308 unlinkat(attrdirfd, target_attrname, 0);
3311 if ((attrfd = openat(attrdirfd, target_attrname, O_RDWR | O_CREAT | O_TRUNC, st.st_mode)) < 0) {
3314 Mmsg3(jcr->errmsg, _("Unable to open xattr %s on file \"%s\": ERR=%s\n"),
3315 target_attrname, jcr->last_fname, be.bstrerror());
3316 Dmsg1(100, "%s", jcr->errmsg);
3322 * Restore the actual data.
3324 if (st.st_size > 0) {
3325 used_bytes = (data - content);
3326 cnt = content_length - used_bytes;
3329 * Do a sanity check, the st.st_size should be the same as the number of bytes
3330 * we have available as data of the stream.
3332 if (cnt != st.st_size) {
3333 Mmsg2(jcr->errmsg, _("Unable to restore data of xattr %s on file \"%s\": Not all data available in xattr stream\n"),
3334 target_attrname, jcr->last_fname);
3335 Dmsg1(100, "%s", jcr->errmsg);
3340 cnt = write(attrfd, data, cnt);
3344 Mmsg3(jcr->errmsg, _("Unable to restore data of xattr %s on file \"%s\": ERR=%s\n"),
3345 target_attrname, jcr->last_fname, be.bstrerror());
3346 Dmsg1(100, "%s", jcr->errmsg);
3352 cnt = content_length - used_bytes;
3358 * The current implementation of xattr on Solaris doesn't support this, but if it ever does we are prepared.
3362 if (symlink(linked_target, target_attrname) < 0) {
3365 Mmsg4(jcr->errmsg, _("Unable to symlink xattr %s to %s on file \"%s\": ERR=%s\n"),
3366 target_attrname, linked_target, jcr->last_fname, be.bstrerror());
3367 Dmsg1(100, "%s", jcr->errmsg);
3372 * Successfully restored xattr.
3374 retval = bxattr_rtn_ok;
3381 * Restore owner and acl for non extensible attributes.
3383 if (!is_extensible) {
3384 if (fchownat(attrdirfd, target_attrname, st.st_uid, st.st_gid, AT_SYMLINK_NOFOLLOW) < 0) {
3386 /* EINVAL means is not supported, no fail */
3387 if (errno == EINVAL || errno == ENOENT) {
3388 retval = bxattr_rtn_ok;
3390 Mmsg3(jcr->errmsg, _("Unable to restore owner of xattr %s on file \"%s\": ERR=%s\n"),
3391 target_attrname, jcr->last_fname, be.bstrerror());
3392 Dmsg1(100, "%s", jcr->errmsg);
3399 if (acl_text && *acl_text)
3400 if (solaris_restore_xattr_acl(jcr, attrfd, target_attrname, acl_text) != bxattr_rtn_ok)
3402 #endif /* HAVE_ACL */
3405 * For a non extensible attribute restore access and modification time on the xattr.
3407 if (!is_extensible) {
3408 times[0].tv_sec = st.st_atime;
3409 times[0].tv_usec = 0;
3410 times[1].tv_sec = st.st_mtime;
3411 times[1].tv_usec = 0;
3413 if (futimesat(attrdirfd, target_attrname, times) < 0) {
3415 Mmsg3(jcr->errmsg, _("Unable to restore filetimes of xattr %s on file \"%s\": ERR=%s\n"),
3416 target_attrname, jcr->last_fname, be.bstrerror());
3417 Dmsg1(100, "%s", jcr->errmsg);
3423 * Successfully restored xattr.
3425 retval = bxattr_rtn_ok;
3429 Mmsg1(jcr->errmsg, _("Invalid xattr stream, failed to restore xattr stream on file \"%s\"\n"),
3431 Dmsg1(100, "%s", jcr->errmsg);
3437 if (attrdirfd != -1) {
3446 static bxattr_rtn_code solaris_backup_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
3449 bxattr_rtn_code retval = bxattr_rtn_ok;
3452 * First see if extended attributes or extensible attributes are present.
3453 * If not just pretend things went ok.
3455 if (pathconf(jcr->last_fname, _PC_XATTR_EXISTS) > 0) {
3456 jcr->xattr_ctx->nr_saved = 0;
3459 * As we change the cwd in the save function save the current cwd
3460 * for restore after return from the solaris_save_xattrs function.
3462 getcwd(cwd, sizeof(cwd));
3463 retval = solaris_save_xattrs(jcr, NULL, NULL);
3465 if (jcr->xattr_ctx->link_cache) {
3466 drop_xattr_link_cache(jcr);
3472 static bxattr_rtn_code solaris_restore_xattr_streams(JCR *jcr,
3475 uint32_t content_length)
3478 bool is_extensible = false;
3479 bxattr_rtn_code retval = bxattr_rtn_error;
3482 * First make sure we can restore xattr on the filesystem.
3485 #if defined(HAVE_SYS_NVPAIR_H) && defined(_PC_SATTR_ENABLED)
3486 case STREAM_XATTR_SOLARIS_SYS:
3487 if (pathconf(jcr->last_fname, _PC_SATTR_ENABLED) <= 0) {
3488 Mmsg1(jcr->errmsg, _("Failed to restore extensible attributes on file \"%s\"\n"),
3490 Dmsg1(100, "%s", jcr->errmsg);
3494 is_extensible = true;
3497 case STREAM_XATTR_SOLARIS:
3498 if (pathconf(jcr->last_fname, _PC_XATTR_ENABLED) <= 0) {
3499 Mmsg1(jcr->errmsg, _("Failed to restore extended attributes on file \"%s\"\n"),
3501 Dmsg1(100, "%s", jcr->errmsg);
3510 * As we change the cwd in the restore function save the current cwd
3511 * for restore after return from the solaris_restore_xattrs function.
3513 getcwd(cwd, sizeof(cwd));
3514 retval = solaris_restore_xattrs(jcr, is_extensible, content, content_length);
3523 * Function pointers to the build and restore function to use for these xattrs.
3525 static bxattr_rtn_code (*os_backup_xattr_streams)
3526 (JCR *jcr, FF_PKT *ff_pkt) =
3527 solaris_backup_xattr_streams;
3528 static bxattr_rtn_code (*os_restore_xattr_streams)
3529 (JCR *jcr, int stream, char *content, uint32_t content_length) =
3530 solaris_restore_xattr_streams;
3532 #endif /* defined(HAVE_SUN_OS) */
3535 * Entry points when compiled with support for XATTRs on a supported platform.
3537 bool backup_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
3539 bxattr_rtn_code rtn = bxattr_rtn_ok;
3541 if (!(ff_pkt->flags & FO_XATTR && !ff_pkt->cmd_plugin)) {
3548 * See if we are changing from one device to an other.
3549 * We save the current device we are scanning and compare
3550 * it with the current st_dev in the last stat performed on
3551 * the file we are currently storing.
3553 if (jcr->xattr_ctx->current_dev != ff_pkt->statp.st_dev) {
3555 * Reset the acl save flags.
3557 jcr->xattr_ctx->flags = 0;
3558 jcr->xattr_ctx->flags |= BXATTR_FLAG_SAVE_NATIVE;
3561 * Save that we started scanning a new filesystem.
3563 jcr->xattr_ctx->current_dev = ff_pkt->statp.st_dev;
3566 if ((jcr->xattr_ctx->flags & BXATTR_FLAG_SAVE_NATIVE) && os_restore_xattr_streams) {
3567 rtn = os_backup_xattr_streams(jcr, ff_pkt);
3570 case bxattr_rtn_fatal:
3574 case bxattr_rtn_error:
3575 if (jcr->xattr_ctx->nr_errors < XATTR_MAX_ERROR_PRINT_PER_JOB) {
3576 if (jcr->errmsg[0]) {
3577 Jmsg(jcr, M_WARNING, 0, "Operating system XATTRs not configured.\n");
3579 Jmsg(jcr, M_WARNING, 0, "%s", jcr->errmsg);
3581 jcr->xattr_ctx->nr_errors++;
3585 /* Theoretically we cannot get here */
3590 bxattr_rtn_code restore_xattr_streams(JCR *jcr,
3593 uint32_t content_length)
3598 bxattr_rtn_code retval = bxattr_rtn_error;
3601 * See if we are changing from one device to an other.
3602 * We save the current device we are restoring to and compare
3603 * it with the current st_dev in the last stat performed on
3604 * the file we are currently restoring.
3606 ret = lstat(jcr->last_fname, &st);
3609 if (errno == ENOENT) {
3610 retval = bxattr_rtn_ok;
3612 Mmsg2(jcr->errmsg, _("Unable to stat file \"%s\": ERR=%s\n"),
3613 jcr->last_fname, be.bstrerror());
3614 Dmsg1(100, "%s", jcr->errmsg);
3618 if (jcr->xattr_ctx->current_dev != st.st_dev) {
3620 * Reset the acl save flags.
3622 jcr->xattr_ctx->flags = 0;
3623 jcr->xattr_ctx->flags |= BXATTR_FLAG_RESTORE_NATIVE;
3626 * Save that we started restoring to a new filesystem.
3628 jcr->xattr_ctx->current_dev = st.st_dev;
3632 * See if we are still restoring native xattr to this filesystem.
3634 if ((jcr->xattr_ctx->flags & BXATTR_FLAG_RESTORE_NATIVE) && os_restore_xattr_streams) {
3636 * See if we can restore this stream, and ifso give it a try.
3638 for (cnt = 0; cnt < sizeof(os_default_xattr_streams) / sizeof(int); cnt++) {
3639 if (os_default_xattr_streams[cnt] == stream) {
3640 retval = os_restore_xattr_streams(jcr, stream, content, content_length);
3646 * Increment error count but don't log an error again for the same filesystem.
3648 jcr->xattr_ctx->nr_errors++;
3649 retval = bxattr_rtn_ok;
3654 * Issue a warning and discard the message. But pretend the restore was ok.
3656 Jmsg2(jcr, M_WARNING, 0,
3657 _("Cannot restore Extended Attributes of %s - incompatible xattr stream encountered - %d\n"),
3658 jcr->last_fname, stream);